diff --git a/src/Features/ScreenSpaceGI.cpp b/src/Features/ScreenSpaceGI.cpp index 458beccb23..09f8156dba 100644 --- a/src/Features/ScreenSpaceGI.cpp +++ b/src/Features/ScreenSpaceGI.cpp @@ -403,7 +403,7 @@ void ScreenSpaceGI::SetupResources() { texRadiance = eastl::make_unique(texDesc); texRadiance->CreateSRV(srvDesc); - texRadiance->CreateUAV(uavDesc); // Create default UAV for mip 0 + // No default UAV needed: prefilterRadiance binds per-mip UAVs via uavRadiance[]. // Create individual UAVs for each mip level for prefiltering for (uint i = 0; i < 5; ++i) { @@ -415,10 +415,12 @@ void ScreenSpaceGI::SetupResources() DX::ThrowIfFailed(device->CreateUnorderedAccessView(texRadiance->resource.get(), &mipUavDesc, uavRadiance[i].put())); } - // Create temporary texture for prefiltering (single mip level, used as SRV input) + // Staging texture for mip 0 radiance. radianceDisocc writes it directly, + // prefilterRadiance reads it as SRV and writes the mip chain back to texRadiance. + // Avoids a full-texture CopySubresourceRegion each frame. D3D11_TEXTURE2D_DESC tempTexDesc = texDesc; tempTexDesc.MipLevels = 1; - tempTexDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; + tempTexDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_UNORDERED_ACCESS; D3D11_SHADER_RESOURCE_VIEW_DESC tempSrvDesc = { .Format = DXGI_FORMAT_R11G11B10_FLOAT, @@ -428,8 +430,15 @@ void ScreenSpaceGI::SetupResources() .MipLevels = 1 } }; + D3D11_UNORDERED_ACCESS_VIEW_DESC tempUavDesc = { + .Format = DXGI_FORMAT_R11G11B10_FLOAT, + .ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D, + .Texture2D = { .MipSlice = 0 } + }; + texRadianceTemp = eastl::make_unique(tempTexDesc); texRadianceTemp->CreateSRV(tempSrvDesc); + texRadianceTemp->CreateUAV(tempUavDesc); } texDesc.BindFlags &= ~D3D11_BIND_RENDER_TARGET; @@ -774,7 +783,7 @@ void ScreenSpaceGI::DrawSSGI() srvs.at(9) = texGiSpecular[inputAoTexIdx]->srv.get(); srvs.at(10) = nullptr; - uavs.at(0) = texRadiance->uav.get(); + uavs.at(0) = texRadianceTemp->uav.get(); uavs.at(1) = texAccumFrames[!lastFrameAccumTexIdx]->uav.get(); uavs.at(2) = texAo[!inputAoTexIdx]->uav.get(); uavs.at(3) = texIlY[!inputGITexIdx]->uav.get(); @@ -786,22 +795,19 @@ void ScreenSpaceGI::DrawSSGI() context->CSSetShader(radianceDisoccCompute.get(), nullptr, 0); context->Dispatch((internalRes[0] + 7u) >> 3, (internalRes[1] + 7u) >> 3, 1); - // Prefilter radiance texture instead of using GenerateMips for proper dynamic resolution handling + // Prefilter radiance texture instead of using GenerateMips for proper dynamic resolution handling. + // radianceDisocc wrote mip 0 directly to texRadianceTemp above, so we can bind it + // as SRV input here without an intermediate CopySubresourceRegion. { TracyD3D11Zone(globals::state->tracyCtx, "SSGI - Prefilter Radiance"); - // First copy mip 0 from radiance to temporary texture to avoid read/write conflict - context->CopySubresourceRegion( - texRadianceTemp->resource.get(), 0, 0, 0, 0, - texRadiance->resource.get(), 0, nullptr); - resetViews(); - srvs.at(0) = texRadianceTemp->srv.get(); // Use temporary texture as input - uavs.at(0) = uavRadiance[0].get(); // Mip 0 - uavs.at(1) = uavRadiance[1].get(); // Mip 1 - uavs.at(2) = uavRadiance[2].get(); // Mip 2 - uavs.at(3) = uavRadiance[3].get(); // Mip 3 - uavs.at(4) = uavRadiance[4].get(); // Mip 4 + srvs.at(0) = texRadianceTemp->srv.get(); + uavs.at(0) = uavRadiance[0].get(); // Mip 0 + uavs.at(1) = uavRadiance[1].get(); // Mip 1 + uavs.at(2) = uavRadiance[2].get(); // Mip 2 + uavs.at(3) = uavRadiance[3].get(); // Mip 3 + uavs.at(4) = uavRadiance[4].get(); // Mip 4 context->CSSetShaderResources(0, 1, srvs.data()); context->CSSetUnorderedAccessViews(0, 5, uavs.data(), nullptr);