added depth min/max generation pass

This commit is contained in:
myT 2024-03-29 03:53:19 +01:00
parent 490617de7a
commit c737a2833f
9 changed files with 186 additions and 1 deletions

View file

@ -499,6 +499,7 @@ struct CRP : IRenderPipeline
void BlitRenderTarget(HTexture destination, const char* passName);
void DrawSceneView(const drawSceneViewCommand_t& cmd);
void UploadSceneViewData();
void BuildDepthPyramid();
HTexture GetReadRenderTarget();
HTexture GetWriteRenderTarget();
@ -508,6 +509,7 @@ struct CRP : IRenderPipeline
float frameSeed;
HTexture readbackRenderTarget;
HTexture depthTexture;
HTexture depthMinMaxTexture;
HTexture normalTexture;
HTexture motionVectorTexture; // raw, for TAA/denoisers/etc
HTexture motionVectorMBTexture; // mangled, for motion blur only
@ -523,6 +525,7 @@ struct CRP : IRenderPipeline
HTexture blueNoise2D;
FreezeFrame::Id freezeFrame;
HTexture frozenTexture;
HPipeline depthPyramidPipeline;
// blit
HPipeline blitPipelineLDR;

View file

@ -33,6 +33,7 @@ along with Challenge Quake 3. If not, see <https://www.gnu.org/licenses/>.
#include "compshaders/crp/mip_1.h"
#include "compshaders/crp/mip_2.h"
#include "compshaders/crp/mip_3.h"
#include "compshaders/crp/depth_pyramid.h"
struct SceneViewConst
@ -47,6 +48,15 @@ struct SceneViewConst
};
};
#pragma pack(push, 4)
struct DepthPyramidRC
{
uint32_t destTextureIndices[7];
uint32_t depthTextureIndex;
uint32_t depthSamplerIndex;
};
#pragma pack(pop)
CRP crp;
IRenderPipeline* crpp = &crp;
@ -436,12 +446,21 @@ void CRP::Init()
desc.committedResource = true;
desc.shortLifeTime = true;
desc.initialState = ResourceStates::DepthWriteBit;
desc.allowedState = ResourceStates::DepthAccessBits | ResourceStates::PixelShaderAccessBit;
desc.allowedState = ResourceStates::DepthAccessBits | ResourceStates::PixelShaderAccessBit | ResourceStates::ComputeShaderAccessBit;
desc.format = TextureFormat::Depth32_Float;
desc.SetClearDepthStencil(0.0f, 0);
depthTexture = RHI::CreateTexture(desc);
}
{
TextureDesc desc("depth pyramid", glConfig.vidWidth, glConfig.vidHeight, 7);
desc.shortLifeTime = true;
desc.initialState = ResourceStates::UnorderedAccessBit;
desc.allowedState = ResourceStates::UnorderedAccessBit | ResourceStates::PixelShaderAccessBit | ResourceStates::ComputeShaderAccessBit;
desc.format = TextureFormat::R32G32_Float;
depthMinMaxTexture = RHI::CreateTexture(desc);
}
{
TextureDesc desc("GBuffer normals", glConfig.vidWidth, glConfig.vidHeight);
desc.committedResource = true;
@ -509,6 +528,8 @@ void CRP::Init()
blitPipelineHDR = CreateGraphicsPipeline(desc);
}
depthPyramidPipeline = CreateComputePipeline("Depth Pyramid", ShaderByteCode(g_depth_pyramid_cs));
{
BufferDesc desc("scene view upload #1", SceneViewConst::BufferBytes, ResourceStates::ShaderAccessBits);
desc.shortLifeTime = true;
@ -993,6 +1014,30 @@ void CRP::UploadSceneViewData()
sceneViewIndex++;
}
void CRP::BuildDepthPyramid()
{
SCOPED_RENDER_PASS("Depth Pyramid", 1.0f, 1.0f, 1.0f);
CmdBeginBarrier();
CmdTextureBarrier(depthTexture, ResourceStates::ComputeShaderAccessBit);
CmdTextureBarrier(depthMinMaxTexture, ResourceStates::UnorderedAccessBit);
CmdEndBarrier();
DepthPyramidRC rc = {};
for(uint32_t i = 0; i < ARRAY_LEN(rc.destTextureIndices); i++)
{
rc.destTextureIndices[i] = GetTextureIndexUAV(depthMinMaxTexture, i);
}
rc.depthTextureIndex = GetTextureIndexSRV(depthTexture);
rc.depthSamplerIndex = GetSamplerIndex(TW_CLAMP_TO_EDGE, TextureFilter::Point);
const int w = glConfig.vidWidth / 2;
const int h = glConfig.vidHeight / 2;
CmdBindPipeline(depthPyramidPipeline);
CmdSetComputeRootConstants(0, sizeof(rc), &rc);
CmdDispatch((w + 7) / 8, (h + 7) / 8, 1);
}
void CRP::ReadPixels(int w, int h, int alignment, colorSpace_t colorSpace, void* outPixels)
{
ReadTextureImage(outPixels, readbackRenderTarget, w, h, alignment, colorSpace);

View file

@ -396,3 +396,27 @@ float2 PolarToCartesian(float2 polar)
return cartesian;
}
template<typename T>
T min3(T v0, T v1, T v2)
{
return min(v0, min(v1, v2));
}
template<typename T>
T max3(T v0, T v1, T v2)
{
return max(v0, max(v1, v2));
}
template<typename T>
T min4(T v0, T v1, T v2, T v3)
{
return min(min(v0, v1), min(v2, v3));
}
template<typename T>
T max4(T v0, T v1, T v2, T v3)
{
return max(max(v0, v1), max(v2, v3));
}

View file

@ -0,0 +1,100 @@
/*
===========================================================================
Copyright (C) 2024 Gian 'myT' Schellenbaum
This file is part of Challenge Quake 3 (CNQ3).
Challenge Quake 3 is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Challenge Quake 3 is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Challenge Quake 3. If not, see <https://www.gnu.org/licenses/>.
===========================================================================
*/
// outputs min/max depth values for mip levels 0 to 7 in one go
#include "common.hlsli"
cbuffer RootConstants
{
uint destTextureIndex0;
uint destTextureIndex1;
uint destTextureIndex2;
uint destTextureIndex3;
uint destTextureIndex4;
uint destTextureIndex5;
uint destTextureIndex6;
uint depthTextureIndex;
uint depthSamplerIndex;
}
groupshared float2 s_depth[32][32];
void ProcessMip(uint threadCount, uint scale, uint destTextureIndex, uint3 gtid, uint3 gid, bool writeToSM)
{
if(gtid.x < threadCount && gtid.y < threadCount)
{
uint2 baseCoords = gtid.xy * scale * 2;
uint4 coords = uint4(baseCoords, baseCoords + scale.xx);
float2 v0 = s_depth[coords.x][coords.y];
float2 v1 = s_depth[coords.x][coords.w];
float2 v2 = s_depth[coords.z][coords.y];
float2 v3 = s_depth[coords.z][coords.w];
float minZ = min4(v0.x, v1.x, v2.x, v3.x);
float maxZ = max4(v0.y, v1.y, v2.y, v3.y);
float2 minMaxZ = float2(minZ, maxZ);
if(writeToSM)
{
s_depth[coords.x][coords.y] = minMaxZ;
}
RWTexture2D<float2> dst = ResourceDescriptorHeap[destTextureIndex];
dst[gid.xy * threadCount + gtid.xy] = minMaxZ;
}
}
[numthreads(32, 32, 1)]
void cs(uint3 dtid : SV_DispatchThreadID, uint3 gtid : SV_GroupThreadID, uint3 gid : SV_GroupID)
{
Texture2D<float> depthTexture = ResourceDescriptorHeap[depthTextureIndex];
SamplerState depthSampler = SamplerDescriptorHeap[depthSamplerIndex];
RWTexture2D<float2> dst0 = ResourceDescriptorHeap[destTextureIndex0];
RWTexture2D<float2> dst1 = ResourceDescriptorHeap[destTextureIndex1];
float2 depthTextureSize = float2(GetTextureSize(depthTexture));
// GatherRed order: x=(0, 1), y=(1, 1), z=(1, 0), w=(0, 0)
float2 tc = (float2(dtid.xy * 2) + float2(0.5, 0.5)) / depthTextureSize;
float4 mip0 = depthTexture.GatherRed(depthSampler, tc);
float minZ = min4(mip0.x, mip0.y, mip0.z, mip0.w);
float maxZ = max4(mip0.x, mip0.y, mip0.z, mip0.w);
float2 minMaxZ = float2(minZ, maxZ);
s_depth[gtid.x][gtid.y] = minMaxZ;
dst0[dtid.xy * 2 + int2(0, 0)] = mip0.ww;
dst0[dtid.xy * 2 + int2(0, 1)] = mip0.xx;
dst0[dtid.xy * 2 + int2(1, 0)] = mip0.zz;
dst0[dtid.xy * 2 + int2(1, 1)] = mip0.yy;
dst1[dtid.xy] = minMaxZ;
GroupMemoryBarrierWithGroupSync();
ProcessMip(16, 1, destTextureIndex2, gtid, gid, true);
GroupMemoryBarrierWithGroupSync();
ProcessMip(8, 2, destTextureIndex3, gtid, gid, true);
GroupMemoryBarrierWithGroupSync();
ProcessMip(4, 4, destTextureIndex4, gtid, gid, true);
GroupMemoryBarrierWithGroupSync();
ProcessMip(2, 8, destTextureIndex5, gtid, gid, true);
GroupMemoryBarrierWithGroupSync();
ProcessMip(1, 16, destTextureIndex6, gtid, gid, false);
}

View file

@ -440,6 +440,7 @@ void ProcessCRP()
CompileCompute("mblur_tile_max.h", "mblur_tile_max.hlsl", "tile_max");
CompilePixelShader("mblur_blur.h", "mblur_blur.hlsl", "blur");
CompilePixelShader("mblur_pack.h", "mblur_pack.hlsl", "pack");
CompileCompute("depth_pyramid.h", "depth_pyramid.hlsl", "depth_pyramid");
}
int main(int /*argc*/, const char** argv)

View file

@ -193,6 +193,9 @@
<FxCompile Include="..\..\code\renderer\shaders\crp\blit.hlsl">
<ExcludedFromBuild>true</ExcludedFromBuild>
</FxCompile>
<FxCompile Include="..\..\code\renderer\shaders\crp\depth_pyramid.hlsl">
<ExcludedFromBuild>true</ExcludedFromBuild>
</FxCompile>
<FxCompile Include="..\..\code\renderer\shaders\crp\dl_denoising.hlsl">
<ExcludedFromBuild>true</ExcludedFromBuild>
</FxCompile>

View file

@ -97,6 +97,9 @@
<FxCompile Include="..\..\code\renderer\shaders\crp\blit.hlsl">
<Filter>shaders\crp</Filter>
</FxCompile>
<FxCompile Include="..\..\code\renderer\shaders\crp\depth_pyramid.hlsl">
<Filter>shaders\crp</Filter>
</FxCompile>
<FxCompile Include="..\..\code\renderer\shaders\crp\dl_denoising.hlsl">
<Filter>shaders\crp</Filter>
</FxCompile>

View file

@ -195,6 +195,9 @@
<FxCompile Include="..\..\code\renderer\shaders\crp\blit.hlsl">
<ExcludedFromBuild>true</ExcludedFromBuild>
</FxCompile>
<FxCompile Include="..\..\code\renderer\shaders\crp\depth_pyramid.hlsl">
<ExcludedFromBuild>true</ExcludedFromBuild>
</FxCompile>
<FxCompile Include="..\..\code\renderer\shaders\crp\dl_denoising.hlsl">
<ExcludedFromBuild>true</ExcludedFromBuild>
</FxCompile>

View file

@ -97,6 +97,9 @@
<FxCompile Include="..\..\code\renderer\shaders\crp\blit.hlsl">
<Filter>shaders\crp</Filter>
</FxCompile>
<FxCompile Include="..\..\code\renderer\shaders\crp\depth_pyramid.hlsl">
<Filter>shaders\crp</Filter>
</FxCompile>
<FxCompile Include="..\..\code\renderer\shaders\crp\dl_denoising.hlsl">
<Filter>shaders\crp</Filter>
</FxCompile>