I'm on the way to add HiZ to my SSR protocol as explained here

I would like to use generatemip, but can't find how to select sampled pixels based on a min value comparison. Is this possible with generatemip?

Must this be done by shader only? If so, I may need to select the previous mip level as resource and the next one as render target. Is this feasible? What is the regular method for this purpose?

As stated in my comment I'm creating the initial texture with generatemip flag and from it create its rendertarget and shaderesource. I copy the regular depthbuffer to level 0 and use generatemip to have the HiZ. But I don't know how to have a min value instead of sampled neighboring pixels.

Alternatively I can use a shader but just can't understand how you retrieve a rendertarget for a given mip level. It seems it has something to do with copysubresource or updateresource but I don't understand how to use it.

  • \$\begingroup\$ I successfully make my mip chain working but with generatemip at the moment which as expected give an averaged result or I don't still get how to control its behavior. A link to start some code for DX11 is here. I will have probably to go for a specific shader. \$\endgroup\$
    – philB
    Jul 6, 2022 at 15:36
  • \$\begingroup\$ So I have this alternative to build an array of rendertarget and their shaderview to have my HiZ with depth min obtained with a shader. works fine. but not practical if I want to use a single resource for the HiZ in my shader where mips are accessed simply within texture.load(x,y,miplevel) call. So I can probably copy these to a texture with mip allowed but its like a duplicate of resources I would like to avoid. So really getting the address of a sub mip resource from a texture created with mips would be great. \$\endgroup\$
    – philB
    Jul 8, 2022 at 13:52

1 Answer 1


After some workaround this is my solution

Using DX11 generatemips

Create texture pTex with mip flag on (eventually fixed number of miplevel) and D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE flags

Create pRTV rendertarget for this pTex with RTVDesc.Texture2D.MipSlice = 0;

Create pSRV shaderesourceview for this pTex with SRVDesc.Texture2D.MipLevels = MipCount; SRVDesc.Texture2D.MostDetailedMip = 0;

Using it

If the initial image has the same format as the pRTV rendertarget use CopyResource

Else you can do this (example copy an initial D24 to a R16)

Set the initial image as resourceview (D24). Set render target pRTV (R16); Set a pixel shader to copy the initial image to the pRTV; Draw square;

If both cases finish with DX11 generatemips(pSRV);

If not using generatemips (owner defined downsampling)

Create texture pTex as previously Create an array[MipCount] of ppRTV rendertarget and ppSRV shaderesourceview for this pTex with

For n=0 to <MipCount 
   RTVDesc.Texture2D.MipSlice = n; 
   create ppRTV[n]
   SRVDesc.Texture2D.MipLevels = 1;
   SRVDesc.Texture2D.MostDetailedMip = n;
   Create ppSRV[n]

Doing mipmap

As previously you start by copying the initial image but to the ppRTV[0] Then

 for (n = 1; n < MipCount; n++)
     SetShaderResources(0, 1, & ppSRV[n - 1]);
     Update shader constant data with current viewportsize if required
     Then divide current viewport size /2
     SetViewports(1, current new size);
     SetRenderTargets(1, ppRTV[n], NULL);
     Render a quad
     Free targets at that point to avoid in debug mode DX messages of resource still bound as target

The default of the array ppSRV is that you will use MipCount texture slots in the shader if you need to use all the mips. To avoid this I combine the two methods by creating the main pRTV and main pSRV as for generatemip AND ppRTV[MipCount] and ppSRV[MipCount] And after manual mipmap generation with ppRTV and ppSRV I copy each ppRTV[n] to each miplevel in main pSRV.

    ID3D11Resource* pDst;
    D3D11_BOX Box;
    Box.back = 1;
    Box.front = 0;
    Box.left = 0;
    Box.top = 0;
    Box.right = gViewPort.Width;
    Box.bottom = gViewPort.Height;
    for (DWORD n = 0; n < 8; n++)
        ID3D11Resource* pSrc;
        gpDC11->CopySubresourceRegion(pDst, n, 0, 0, 0, pSrc, n, &Box);
        Box.right /= 2;
        Box.bottom /= 2;

I don’t like having a copy of the same resources twice but I did not find any way to do it better to have only one texture slot used.

Using it in the final shader

With generatemip or after the copy of array to the main pSRV you declare and use a texture as usual

 Texture2D txMip : register(t8);
 txMip.load(xy, MipLevel)

If using an array of SRV you declare an array of texture

 Texture2D txMip[8]: register(t8);
 txMip[n].load(xy, 0)

Below the result with owner PShader downsampling using array of RTV and SRV with final copy to the main SRV.

enter image description here For HiZ I need a min value check like this:

int3 TexS = int3(Input.Tex.xy, 0);// xy sized to previous screen size in VShader
float FinalColor0 =  txDiffuse.Load(TexS).r;
float FinalColor1 =  txDiffuse.Load(TexS+int3(1,0,0)).r;
if ((FinalColor1==0)||(FinalColor1==1))FinalColor1=FinalColor0;
float FinalColor2 =  txDiffuse.Load(TexS+int3(1,1,0)).r;
if ((FinalColor2==0)||(FinalColor2==1))FinalColor2=FinalColor0;
float FinalColor3 =  txDiffuse.Load(TexS+int3(0,1,0)).r;
if ((FinalColor3==0)||(FinalColor3==1))FinalColor3=FinalColor0;
return min(FinalColor0, min(FinalColor1, min(FinalColor2, FinalColor3)));

The lower sized mips suffer this known border problem (white border in last views). If someone can point me to a better method for border checking it will be great

After some refinements I found that a single texture can be used to generate a single RTV/SRV with miplevels AND/or the same texture can be used to generate arrays of RTVs and SRVs. Updating one or the others updates in fact everything (e.g. updating SRV[5] or writing to RTV[5] updates miplevel 5 of SRV. Indeed the CopySubRegion loop is not necessary.


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .