DiligentGraphics / DiligentCore

A modern cross-platform low-level graphics API
http://diligentgraphics.com/diligent-engine/
Apache License 2.0
632 stars 138 forks source link

[bug] d3d12: GenerateMips() error: invalid mip level range #599

Closed WangHoi closed 3 months ago

WangHoi commented 3 months ago

d3d12: GenerateMips() error: invalid mip level range

Steps to re-produce:

  1. Create a Texture with mipmaps.
  2. Fill texture mip0 with a compute shader
  3. GenerateMips()

Problem

Diligent Engine: ERROR: Debug assertion failed in Diligent::`anonymous-namespace'::StateTransitionHelper::AddD3D12ResourceBarriers(), file CommandContext.cpp, line 309:
Invalid mip level range

My early inspection

GenerateMips.cpp:

        // Transition dst mip levels to UAV state
        StateTransitionDesc DstMipsBarrier{pTexD3D12, OriginalState, RESOURCE_STATE_UNORDERED_ACCESS, STATE_TRANSITION_FLAG_NONE};
        if (DstMipsBarrier.OldState != DstMipsBarrier.NewState)
        {
            DstMipsBarrier.FirstMipLevel   = ViewDesc.MostDetailedMip + TopMip + 1;
            DstMipsBarrier.MipLevelsCount  = NumMips;
            DstMipsBarrier.FirstArraySlice = ViewDesc.FirstArraySlice;
            DstMipsBarrier.ArraySliceCount = ViewDesc.NumArraySlices;
            Ctx.TransitionResource(*pTexD3D12, DstMipsBarrier);
        }

        ComputeCtx.Dispatch((DstWidth + 7) / 8, (DstHeight + 7) / 8, ViewDesc.NumArraySlices);

        // Transition the lowest level back to original layout or leave it in RESOURCE_STATE_SHADER_RESOURCE
        // if all subresources are processed
        if (SrcMipBarrier.NewState != FinalState)
        {
            SrcMipBarrier.OldState = SrcMipBarrier.NewState;
            SrcMipBarrier.NewState = FinalState;
            Ctx.TransitionResource(*pTexD3D12, SrcMipBarrier);
        }

        if (DstMipsBarrier.NewState != FinalState)
        {
            DstMipsBarrier.OldState = DstMipsBarrier.NewState;
            DstMipsBarrier.NewState = FinalState;
            // Do not transition the bottom level if we have more mips to process
            if (TopMip + NumMips < BottomMip)
                --DstMipsBarrier.MipLevelsCount;
            if (DstMipsBarrier.MipLevelsCount > 0)
                Ctx.TransitionResource(*pTexD3D12, DstMipsBarrier);
        }

Transition DstMipsBarrier to FinalState, the DstMipsBarrier.MipLevelsCount maybe default to -1. If previous DstMipsBarrier.OldState == DstMipsBarrier.NewState.


I can provide sample code later if you like.

TheMostDiligent commented 3 months ago

Can you provide a sample code that reproduces the problem?

WangHoi commented 3 months ago

This is the sample: generate_mips.zip

WangHoi commented 3 months ago

Btw, maybe off-topic, there are some cool mipmap generation algorithms: