From 791e3b65628e7f53565172380c88a8cddde338f0 Mon Sep 17 00:00:00 2001 From: Chuck Walbourn Date: Thu, 29 Aug 2024 17:26:30 -0700 Subject: [PATCH] GenerateMips updated to handle sRGB better --- Src/ResourceUploadBatch.cpp | 17 +++++++++---- Src/Shaders/CompileShaders.cmd | 24 ++++++++++++------ Src/Shaders/GenerateMips.hlsl | 46 ++++++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 12 deletions(-) diff --git a/Src/ResourceUploadBatch.cpp b/Src/ResourceUploadBatch.cpp index 88c8d1b9..ee548d95 100644 --- a/Src/ResourceUploadBatch.cpp +++ b/Src/ResourceUploadBatch.cpp @@ -26,12 +26,16 @@ namespace { #ifdef _GAMING_XBOX_SCARLETT #include "XboxGamingScarlettGenerateMips_main.inc" +#include "XboxGamingScarlettGenerateMips_sRGB.inc" #elif defined(_GAMING_XBOX) #include "XboxGamingXboxOneGenerateMips_main.inc" +#include "XboxGamingXboxOneGenerateMips_sRGB.inc" #elif defined(_XBOX_ONE) && defined(_TITLE) #include "XboxOneGenerateMips_main.inc" +#include "XboxOneGenerateMips_sRGB.inc" #else #include "GenerateMips_main.inc" +#include "GenerateMips_sRGB.inc" #endif bool FormatIsUAVCompatible(_In_ ID3D12Device* device, bool typedUAVLoadAdditionalFormats, DXGI_FORMAT format) noexcept @@ -222,12 +226,14 @@ namespace ComPtr rootSignature; ComPtr generateMipsPSO; + ComPtr generateMipsPSO_sRGB; GenerateMipsResources( _In_ ID3D12Device* device) { rootSignature = CreateGenMipsRootSignature(device); generateMipsPSO = CreateGenMipsPipelineState(device, rootSignature.Get(), GenerateMips_main, sizeof(GenerateMips_main)); + generateMipsPSO_sRGB = CreateGenMipsPipelineState(device, rootSignature.Get(), GenerateMips_sRGB, sizeof(GenerateMips_sRGB)); } GenerateMipsResources(const GenerateMipsResources&) = delete; @@ -476,7 +482,7 @@ class ResourceUploadBatch::Impl // This is true of BGRA or sRGB textures, for example. if (uavCompat) { - GenerateMips_UnorderedAccessPath(resource); + GenerateMips_UnorderedAccessPath(resource, false); } else if (!mTypedUAVLoadAdditionalFormats) { @@ -645,7 +651,8 @@ class ResourceUploadBatch::Impl private: // Resource is UAV compatible void GenerateMips_UnorderedAccessPath( - _In_ ID3D12Resource* resource) + _In_ ID3D12Resource* resource, + bool srgb) { #if defined(_MSC_VER) || !defined(_WIN32) const auto desc = resource->GetDesc(); @@ -759,7 +766,7 @@ class ResourceUploadBatch::Impl uav2srvDesc.Transition.StateAfter = D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE; // based on format, select srgb or not - ComPtr pso = mGenMipsResources->generateMipsPSO; + ComPtr pso = srgb ? mGenMipsResources->generateMipsPSO_sRGB : mGenMipsResources->generateMipsPSO; // Set up state mList->SetComputeRootSignature(mGenMipsResources->rootSignature.Get()); @@ -899,7 +906,7 @@ class ResourceUploadBatch::Impl TransitionResource(mList.Get(), resourceCopy.Get(), D3D12_RESOURCE_STATE_COPY_DEST, originalState); // Generate the mips - GenerateMips_UnorderedAccessPath(resourceCopy.Get()); + GenerateMips_UnorderedAccessPath(resourceCopy.Get(), FormatIsSRGB(resourceDesc.Format)); // Direct copy back D3D12_RESOURCE_BARRIER barrier[2] = {}; @@ -1019,7 +1026,7 @@ class ResourceUploadBatch::Impl aliasBarrier[1].Transition.StateAfter = originalState; mList->ResourceBarrier(2, aliasBarrier); - GenerateMips_UnorderedAccessPath(resourceCopy.Get()); + GenerateMips_UnorderedAccessPath(resourceCopy.Get(), FormatIsSRGB(resourceDesc.Format)); // Direct copy back RGB to BGR aliasBarrier[0].Aliasing.pResourceBefore = resourceCopy.Get(); diff --git a/Src/Shaders/CompileShaders.cmd b/Src/Shaders/CompileShaders.cmd index 52ac592d..7ad43bcb 100644 --- a/Src/Shaders/CompileShaders.cmd +++ b/Src/Shaders/CompileShaders.cmd @@ -34,7 +34,7 @@ if not exist %XBOXFXC% goto needxdk goto continue :continuegxdk -set XBOXOPTS=/D__XBOX_PER_THREAD_SCRATCH_SIZE_LIMIT_IN_BYTES=0 +set XBOXOPTS=-HV 2021 /D__XBOX_PER_THREAD_SCRATCH_SIZE_LIMIT_IN_BYTES=0 if %2.==scarlett. ( set XBOXPREFIX=XboxGamingScarlett set XBOXDXC="%GameDKLatest%\GXDK\bin\Scarlett\DXC.exe" @@ -49,11 +49,12 @@ if not exist %XBOXDXC% goto needgxdk goto continue :continuedxil +set DXILOPTS=-HV 2021 if defined DirectXShaderCompiler goto dxcviaenv set PCDXC="%WindowsSdkVerBinPath%%FXCARCH%\dxc.exe" -if exist %PCDXC% goto continue +if exist %PCDXC% goto dxilver set PCDXC="%WindowsSdkBinPath%%WindowsSDKVersion%\%FXCARCH%\dxc.exe" -if exist %PCDXC% goto continue +if exist %PCDXC% goto dxilver set PCDXC=dxc.exe goto continue @@ -63,6 +64,14 @@ set PCDXC="%DirectXShaderCompiler%" if exist %PCDXC% goto continue goto needdxil +:dxilver +if not defined WindowsSDKVersion goto continue +REM known DXC.EXE versions that don't support -HV 2021 +if not "x%WindowsSDKVersion:10.0.19041.0=%"=="x%WindowsSDKVersion%" set DXILOPTS=%DXILOPTS:-HV 2021=% +if not "x%WindowsSDKVersion:10.0.20348.0=%"=="x%WindowsSDKVersion%" set DXILOPTS=%DXILOPTS:-HV 2021=% +if not "x%WindowsSDKVersion:10.0.22000.0=%"=="x%WindowsSDKVersion%" set DXILOPTS=%DXILOPTS:-HV 2021=% +goto continue + :continuepc set PCOPTS= @@ -256,6 +265,7 @@ call :CompileShader%1 PostProcess ps PSMerge call :CompileShader%1 PostProcess ps PSBloomCombine call :CompileComputeShader%1 GenerateMips main +call :CompileComputeShader%1 GenerateMips sRGB call :CompileShader%1 ToneMap vs VSQuad call :CompileShader%1 ToneMap ps PSCopy @@ -307,14 +317,14 @@ echo %fxc% exit /b :CompileShaderdxil -set dxc=%PCDXC% "%1.fx" %FXCOPTS% /T%2_6_0 /E%3 "/Fh%CompileShadersOutput%\%1_%3.inc" "/Fd%CompileShadersOutput%\%1_%3.pdb" /Vn%1_%3 +set dxc=%PCDXC% "%1.fx" %FXCOPTS% /T%2_6_0 %DXILOPTS% /E%3 "/Fh%CompileShadersOutput%\%1_%3.inc" "/Fd%CompileShadersOutput%\%1_%3.pdb" /Vn%1_%3 echo. echo %dxc% %dxc% || set error=1 exit /b :CompileComputeShaderdxil -set dxc=%PCDXC% "%1.hlsl" %FXCOPTS% /Tcs_6_0 /E%2 "/Fh%CompileShadersOutput%\%1_%2.inc" "/Fd%CompileShadersOutput%\%1_%2.pdb" /Vn%1_%2 +set dxc=%PCDXC% "%1.hlsl" %FXCOPTS% /Tcs_6_0 %DXILOPTS% /E%2 "/Fh%CompileShadersOutput%\%1_%2.inc" "/Fd%CompileShadersOutput%\%1_%2.pdb" /Vn%1_%2 echo. echo %dxc% %dxc% || set error=1 @@ -335,14 +345,14 @@ echo %fxc% exit /b :CompileShadergxdk -set dxc=%XBOXDXC% "%1.fx" %FXCOPTS% -HV 2021 /T%2_6_0 %XBOXOPTS% /E%3 "/Fh%CompileShadersOutput%\%XBOXPREFIX%%1_%3.inc" "/Fd%CompileShadersOutput%\%XBOXPREFIX%%1_%3.pdb" /Vn%1_%3 +set dxc=%XBOXDXC% "%1.fx" %FXCOPTS% /T%2_6_0 %XBOXOPTS% /E%3 "/Fh%CompileShadersOutput%\%XBOXPREFIX%%1_%3.inc" "/Fd%CompileShadersOutput%\%XBOXPREFIX%%1_%3.pdb" /Vn%1_%3 echo. echo %dxc% %dxc% || set error=1 exit /b :CompileComputeShadergxdk -set dxc=%XBOXDXC% "%1.hlsl" %FXCOPTS% -HV 2021 /Tcs_6_0 %XBOXOPTS% /E%2 "/Fh%CompileShadersOutput%\%XBOXPREFIX%%1_%2.inc" "/Fd%CompileShadersOutput%\%XBOXPREFIX%%1_%2.pdb" /Vn%1_%2 +set dxc=%XBOXDXC% "%1.hlsl" %FXCOPTS% /Tcs_6_0 %XBOXOPTS% /E%2 "/Fh%CompileShadersOutput%\%XBOXPREFIX%%1_%2.inc" "/Fd%CompileShadersOutput%\%XBOXPREFIX%%1_%2.pdb" /Vn%1_%2 echo. echo %dxc% %dxc% || set error=1 diff --git a/Src/Shaders/GenerateMips.hlsl b/Src/Shaders/GenerateMips.hlsl index a34aae1e..daf33a20 100644 --- a/Src/Shaders/GenerateMips.hlsl +++ b/Src/Shaders/GenerateMips.hlsl @@ -28,3 +28,49 @@ void main(uint3 DTid : SV_DispatchThreadID) { OutMip[DTid.xy] = Mip(DTid.xy); } + +float3 ApplySRGBCurve(float3 x) +{ +#if __HLSL_VERSION >= 2021 + // This is exactly the sRGB curve + //return select(x < 0.0031308, 12.92 * x, 1.055 * pow(abs(x), 1.0 / 2.4) - 0.055); + + // This is cheaper but nearly equivalent to the exact sRGB curve + return select(x < 0.0031308, 12.92 * x, 1.13005 * sqrt(abs(x - 0.00228)) - 0.13448 * x + 0.005719); +#else + float3 result; + if (x.r < 0.0031308) + { + result.r = 12.92 * x.r; + } + else + { + result.r = 1.055 * pow(abs(x.r), 1.0 / 2.4) - 0.055; + } + if (x.g < 0.0031308) + { + result.g = 12.92 * x.g; + } + else + { + result.g = 1.055 * pow(abs(x.g), 1.0 / 2.4) - 0.055; + } + if (x.b < 0.0031308) + { + result.b = 12.92 * x.b; + } + else + { + result.b = 1.055 * pow(abs(x.b), 1.0 / 2.4) - 0.055; + } + return result; +#endif +} + +[RootSignature(GenerateMipsRS)] +[numthreads(8, 8, 1)] +void sRGB(uint3 DTid : SV_DispatchThreadID) +{ + float4 Linear = Mip(DTid.xy); + OutMip[DTid.xy] = float4(ApplySRGBCurve(Linear.rgb), Linear.a); +}