Jump to content
  • Advertisement
Sign in to follow this  

DX11 Direct Compute up/down scaling

This topic is 2569 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello everyone,

I was wondering how would one go about taking a non-power of two texture and using a compute shader, re-scale it either up or down to the nearest power of two.
I know how to get the nearest power of two, and I know how to initialize DirectX 11 and create the required shaders; however I have never used the compute features of DX11.

I'm not sure what happens when I create my texture (using D3DX11CreateTextureFromFile) with a non-power of 2 texture ? I think it ends up padding the texture which undesirable.
Or should I just create a structured buffer, store all the pixels in there and make an unordered access view of that ? But then I need to figure out how to assign the threads as I cannot split a few pixels in half.

The application has to typically process GB worth of textures, hence why I'm going for Direct Compute.

Any ideas ?

Share this post

Link to post
Share on other sites
By default, D3DX11CreateTextureFromFile will not rescale the image when creating the texture. The top mip level will have the same dimensions as your image file.

For your compute shader, you'll want one thread per output texel. Each thread can then take any necessary samples from the input texture, and output the scaled texel value to a RWTexture2D. Since you can only dispatch groups of threads, you may end up with more threads than you need. To handle this, you can either do nothing (writes to invalid texel addresses will get ignored) or you can use an if statement to check if the texel address is valid. If you only want linear filtering then your shader can be dead simple:

// Inputs
Texture2D<float4> InputTexture : register(t0);

// Outputs
RWTexture2D<float2> OutputTexture : register(u0);

// Samplers
SamplerState LinearSampler : register(s0);

// Entry point
[numthreads(TGSize_, TGSize_, 1)]
void Rescale(uint3 GroupID : SV_GroupID, uint3 DispatchThreadID : SV_DispatchThreadID,
uint3 GroupThreadID : SV_GroupThreadID, uint GroupIndex : SV_GroupIndex)
uint2 samplePos = GroupID.xy * uint2(TGSize_, TGSize_) + GroupThreadID.xy;

uint2 textureSize;
OutputTexture.GetDimensions(textureSize.x, textureSize.y);

if(samplePos.x < textureSize.x && samplePos.y < textureSize.y)
float2 uv = (samplePos + 0.5f) / textureSize;
OutputTexture[samplePos] = InputTexture(LinearSampler, uv);

Share this post

Link to post
Share on other sites
Thank you MJP for this precise and concise answer.
The entire point of using compute shaders is to use much better scaling algorithm, but I can easily do that once I get the linear filtering going.

Hopefully your book "[font=Arial, Helvetica, sans-serif][size=2]Practical Rendering and Computation with Direct3D 11" will arrive soon and I'll be able to learn much more about Direct3D 11 :)[/font]

Share this post

Link to post
Share on other sites
Sign in to follow this  

  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!