From b5b16e60333d5a5bc66e793f2424c7e0c639699f Mon Sep 17 00:00:00 2001 From: myT <> Date: Sun, 18 Feb 2024 22:51:59 +0100 Subject: [PATCH] DXR 1.1 and SV_Barycentrics support are now optional --- code/renderer/crp_dynamic_lights.cpp | 8 +++- code/renderer/crp_local.h | 5 ++- code/renderer/crp_main.cpp | 7 +--- code/renderer/crp_prepass.cpp | 13 +++++- code/renderer/crp_raytracing.cpp | 56 +++++++++++++++++++++++--- code/renderer/grp_main.cpp | 1 - code/renderer/rhi_d3d12.cpp | 24 +++++------ code/renderer/rhi_local.h | 3 -- code/renderer/shaders/crp/prepass.hlsl | 15 +++++++ code/renderer/tr_local.h | 2 + code/shadercomp/shadercomp.cpp | 30 +++++++++++--- 11 files changed, 126 insertions(+), 38 deletions(-) diff --git a/code/renderer/crp_dynamic_lights.cpp b/code/renderer/crp_dynamic_lights.cpp index 9c067dc..3e5667f 100644 --- a/code/renderer/crp_dynamic_lights.cpp +++ b/code/renderer/crp_dynamic_lights.cpp @@ -45,6 +45,11 @@ struct DenoiseRC void DynamicLights::Init() { + if(!rhiInfo.hasInlineRaytracing) + { + return; + } + { GraphicsPipelineDesc desc("Dynamic Lights"); desc.shortLifeTime = true; @@ -77,8 +82,7 @@ void DynamicLights::Draw() return; } - const HBuffer tlasBuffer = crp.raytracing.GetTLAS(); - if(IsNullHandle(tlasBuffer) || + if(!crp.raytracing.CanRaytrace() || backEnd.refdef.num_dlights <= 0) { CmdBeginBarrier(); diff --git a/code/renderer/crp_local.h b/code/renderer/crp_local.h index 61b5539..f2fe66d 100644 --- a/code/renderer/crp_local.h +++ b/code/renderer/crp_local.h @@ -335,8 +335,9 @@ struct Raytracing void Init(); void ProcessWorld(world_t& world); void BeginFrame(bool wantUpdate); - HBuffer GetTLAS() { return tlasBuffer; } - HBuffer GetInstanceBuffer() { return tlasInstanceBuffer; } + uint32_t GetTLASBufferIndex(); + uint32_t GetInstanceBufferIndex(); + bool CanRaytrace(); private: void TagMapSurfacesRecursively(mnode_t* node); diff --git a/code/renderer/crp_main.cpp b/code/renderer/crp_main.cpp index a7ee200..6f283b1 100644 --- a/code/renderer/crp_main.cpp +++ b/code/renderer/crp_main.cpp @@ -287,7 +287,6 @@ void CRP::Init() InitDesc initDesc; initDesc.directDescriptorHeapIndexing = true; - initDesc.inlineRaytracing = true; srp.firstInit = RHI::Init(initDesc); srp.psoStatsValid = false; @@ -916,8 +915,6 @@ void CRP::UploadSceneViewData() const viewParms_t& vp = backEnd.viewParms; const HBuffer uploadBuffer = sceneViewUploadBuffers[GetFrameIndex()]; const uint32_t uploadByteOffset = sceneViewIndex * SceneViewConst::StructBytes; - const HBuffer tlasBuffer = raytracing.GetTLAS(); - const HBuffer tlasInstanceBuffer = raytracing.GetInstanceBuffer(); SceneView& dest = *(SceneView*)(MapBuffer(uploadBuffer) + uploadByteOffset); @@ -953,8 +950,8 @@ void CRP::UploadSceneViewData() dest.motionVectorTextureIndex = GetTextureIndexSRV(motionVectorTexture); dest.motionVectorMBTextureIndex = GetTextureIndexSRV(motionVectorMBTexture); dest.lightTextureIndex = GetTextureIndexSRV(lightTexture); - dest.tlasBufferIndex = IsNullHandle(tlasBuffer) ? 0 : GetBufferIndexSRV(tlasBuffer); - dest.tlasInstanceBufferIndex = IsNullHandle(tlasInstanceBuffer) ? 0 : GetBufferIndexSRV(tlasInstanceBuffer); + dest.tlasBufferIndex = raytracing.GetTLASBufferIndex(); + dest.tlasInstanceBufferIndex = raytracing.GetInstanceBufferIndex(); dest.lightCount = refdef.num_dlights; RB_LinearDepthConstants(&dest.linearDepthA, &dest.linearDepthB); dest.zNear = vp.zNear; diff --git a/code/renderer/crp_prepass.cpp b/code/renderer/crp_prepass.cpp index 9011caa..0b5fbaf 100644 --- a/code/renderer/crp_prepass.cpp +++ b/code/renderer/crp_prepass.cpp @@ -23,6 +23,7 @@ along with Challenge Quake 3. If not, see . #include "crp_local.h" #include "compshaders/crp/prepass.h" +#include "compshaders/crp/prepass_bary.h" #include "compshaders/crp/fullscreen.h" #include "compshaders/crp/skybox_motion.h" @@ -315,8 +316,16 @@ void Prepass::ProcessShader(shader_t& shader) desc.name = "pre-pass"; desc.rootSignature = RHI_MAKE_NULL_HANDLE(); desc.shortLifeTime = true; // the PSO cache is only valid for this map! - desc.vertexShader.Set(g_prepass_vs); - desc.pixelShader.Set(g_prepass_ps); + if(rhiInfo.hasBarycentrics) + { + desc.vertexShader.Set(g_prepass_bary_vs); + desc.pixelShader.Set(g_prepass_bary_ps); + } + else + { + desc.vertexShader.Set(g_prepass_vs); + desc.pixelShader.Set(g_prepass_ps); + } desc.vertexLayout.AddAttribute(a++, ShaderSemantic::Position, DataType::Float32, 3, 0); desc.vertexLayout.AddAttribute(a++, ShaderSemantic::Normal, DataType::Float32, 3, 0); desc.vertexLayout.AddAttribute(a++, ShaderSemantic::TexCoord, DataType::Float32, 2, 0); diff --git a/code/renderer/crp_raytracing.cpp b/code/renderer/crp_raytracing.cpp index 2203e3c..2a2ab0c 100644 --- a/code/renderer/crp_raytracing.cpp +++ b/code/renderer/crp_raytracing.cpp @@ -166,12 +166,6 @@ static void CreateOrGrowBuffer(HBuffer& buffer, uint32_t& curByteCount, const Bu void Raytracing::Init() { - const uint32_t structByteCount = sizeof(TLASInstance); - BufferDesc desc("BLAS support instance", 2 * BLASBucket::Count * structByteCount, ResourceStates::ShaderAccessBits); - desc.shortLifeTime = true; - desc.structureByteCount = structByteCount; - tlasInstanceBuffer = CreateBuffer(desc); - // make sure we're not trying to use deleted buffers after a video restart for(uint32_t i = 0; i < BLASBucket::Count; i++) { @@ -180,10 +174,27 @@ void Raytracing::Init() dynamicBLASBuffers[i] = {}; } tlasBuffer = RHI_MAKE_NULL_HANDLE(); + + if(!rhiInfo.hasInlineRaytracing) + { + tlasInstanceBuffer = RHI_MAKE_NULL_HANDLE(); + return; + } + + const uint32_t structByteCount = sizeof(TLASInstance); + BufferDesc desc("BLAS support instance", 2 * BLASBucket::Count * structByteCount, ResourceStates::ShaderAccessBits); + desc.shortLifeTime = true; + desc.structureByteCount = structByteCount; + tlasInstanceBuffer = CreateBuffer(desc); } void Raytracing::ProcessWorld(world_t& world) { + if(!rhiInfo.hasInlineRaytracing) + { + return; + } + TagMapSurfacesRecursively(world.nodes); BLASBuilder staticBLASes[BLASBucket::Count]; @@ -248,6 +259,11 @@ void Raytracing::ProcessWorld(world_t& world) void Raytracing::BeginFrame(bool wantUpdate) { + if(!rhiInfo.hasInlineRaytracing) + { + return; + } + if(tr.world == NULL || tr.sceneCounterRT == 0) { return; @@ -651,3 +667,31 @@ bool Raytracing::DynamicSurfaceList::GetSurface(Surface& surface, uint32_t index return skip; } + +uint32_t Raytracing::GetTLASBufferIndex() +{ + if(IsNullHandle(tlasBuffer)) + { + return 0; + } + + return GetBufferIndexSRV(tlasBuffer); +} + +uint32_t Raytracing::GetInstanceBufferIndex() +{ + if(IsNullHandle(tlasInstanceBuffer)) + { + return 0; + } + + return GetBufferIndexSRV(tlasInstanceBuffer); +} + +bool Raytracing::CanRaytrace() +{ + return + rhiInfo.hasInlineRaytracing && + GetTLASBufferIndex() != 0 && + GetInstanceBufferIndex() != 0; +} diff --git a/code/renderer/grp_main.cpp b/code/renderer/grp_main.cpp index 422a0cf..457e690 100644 --- a/code/renderer/grp_main.cpp +++ b/code/renderer/grp_main.cpp @@ -98,7 +98,6 @@ void GRP::Init() { InitDesc initDesc; initDesc.directDescriptorHeapIndexing = false; - initDesc.inlineRaytracing = false; srp.firstInit = RHI::Init(initDesc); if(srp.firstInit) diff --git a/code/renderer/rhi_d3d12.cpp b/code/renderer/rhi_d3d12.cpp index 1d7fb25..a5ddbd9 100644 --- a/code/renderer/rhi_d3d12.cpp +++ b/code/renderer/rhi_d3d12.cpp @@ -3351,18 +3351,6 @@ namespace RHI } } - if(initDesc.inlineRaytracing) - { - D3D12_FEATURE_DATA_D3D12_OPTIONS5 options5 = {}; - if(SUCCEEDED(rhi.device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS5, &options5, sizeof(options5)))) - { - if(options5.RaytracingTier < D3D12_RAYTRACING_TIER_1_1) - { - ri.Error(ERR_FATAL, "The CRP requires DXR 1.1 capable hardware\n"); - } - } - } - { D3D12MA::ALLOCATOR_DESC desc = {}; desc.pDevice = rhi.device; @@ -3624,6 +3612,16 @@ namespace RHI ri.Printf(PRINT_ALL, "Supported VRS modes: %s\n", modeLists[listIndex]); } + D3D12_FEATURE_DATA_D3D12_OPTIONS5 options5 = {}; + const bool hasInlineRaytracing = + SUCCEEDED(rhi.device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS5, &options5, sizeof(options5))) && + options5.RaytracingTier >= D3D12_RAYTRACING_TIER_1_1; + + D3D12_FEATURE_DATA_D3D12_OPTIONS3 options3 = {}; + const bool hasBarycentrics = + SUCCEEDED(rhi.device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS3, &options3, sizeof(options3))) && + options3.BarycentricsSupported; + glInfo.maxTextureSize = MAX_TEXTURE_SIZE; glInfo.maxAnisotropy = 16; glInfo.depthFadeSupport = qtrue; @@ -3638,6 +3636,8 @@ namespace RHI rhiInfo.hasExtendedVRS = rhi.extendedVRSSupport; rhiInfo.isUMA = rhi.allocator->IsUMA(); rhiInfo.isCacheCoherentUMA = rhi.allocator->IsCacheCoherentUMA(); + rhiInfo.hasInlineRaytracing = hasInlineRaytracing; + rhiInfo.hasBarycentrics = hasBarycentrics; rhi.initialized = true; diff --git a/code/renderer/rhi_local.h b/code/renderer/rhi_local.h index f976a75..b5b1ff2 100644 --- a/code/renderer/rhi_local.h +++ b/code/renderer/rhi_local.h @@ -720,9 +720,6 @@ namespace RHI // - all shader resources are exclusively used through ResourceDescriptorHeap and SamplerDescriptorHeap // - all root signature and descriptor table functions are disabled bool directDescriptorHeapIndexing = false; - - // shut down if DXR 1.1 isn't available - bool inlineRaytracing = false; }; bool Init(const InitDesc& desc); // true when a full init happened (the device was created) diff --git a/code/renderer/shaders/crp/prepass.hlsl b/code/renderer/shaders/crp/prepass.hlsl index 52d77cf..aced8e2 100644 --- a/code/renderer/shaders/crp/prepass.hlsl +++ b/code/renderer/shaders/crp/prepass.hlsl @@ -61,8 +61,13 @@ struct VOut float4 currPosition : CURRPOSITION; float4 prevPosition : PREVPOSITION; float4 prevPositionMB : PREVPOSITIONMB; +#if BARYCENTRICS nointerpolation float3 normalWS : NORMALWS; nointerpolation float3 positionWS : POSITIONWS; +#else + float3 normalWS : NORMALWS; + float3 positionWS : POSITIONWS; +#endif float2 texCoords : TEXCOORD0; float4 color : COLOR0; float clipDist : SV_ClipDistance0; @@ -120,7 +125,11 @@ struct POut float4 shadingPosition : SV_Target3; }; +#if BARYCENTRICS POut ps(VOut input, float3 barycentrics : SV_Barycentrics) +#else +POut ps(VOut input) +#endif { if(alphaTest != ATEST_NONE) { @@ -133,6 +142,7 @@ POut ps(VOut input, float3 barycentrics : SV_Barycentrics) } } +#if BARYCENTRICS float3 p0 = GetAttributeAtVertex(input.positionWS, 0); float3 p1 = GetAttributeAtVertex(input.positionWS, 1); float3 p2 = GetAttributeAtVertex(input.positionWS, 2); @@ -151,6 +161,11 @@ POut ps(VOut input, float3 barycentrics : SV_Barycentrics) float3 dist3 = saturate(abs(shadingPosition - position)); float dist = saturate(distance(shadingPosition, position)); float positionDelta = asfloat(PackColor(float4(dist3, dist))); +#else + float3 normal = input.normalWS; + float3 shadingPosition = input.positionWS + 0.01 * normal; + float positionDelta = asfloat(0); +#endif float2 currPosTC = NDCToTC(input.currPosition.xy / input.currPosition.w); float2 prevPosTC = NDCToTC(input.prevPosition.xy / input.prevPosition.w); diff --git a/code/renderer/tr_local.h b/code/renderer/tr_local.h index 0fd552d..1441d34 100644 --- a/code/renderer/tr_local.h +++ b/code/renderer/tr_local.h @@ -1755,6 +1755,8 @@ struct RHIInfo qbool hasExtendedVRS; qbool isUMA; qbool isCacheCoherentUMA; + qbool hasInlineRaytracing; + qbool hasBarycentrics; }; extern RHIInfo rhiInfo; diff --git a/code/shadercomp/shadercomp.cpp b/code/shadercomp/shadercomp.cpp index 8385421..e77a0b9 100644 --- a/code/shadercomp/shadercomp.cpp +++ b/code/shadercomp/shadercomp.cpp @@ -170,35 +170,54 @@ void CompileSMAAShaders() ProcessSMAAShadersForPreset("ultra", "-D SMAA_PRESET_ULTRA=1"); } -void CompileGraphics(const char* headerPath, const char* shaderPath, const char* varName) +void CompileGraphics(const char* headerPath, const char* shaderPath, const char* varName, + int vsOptionCount = 0, int psOptionCount = 0, ...) { const char* vsHeaderRelPath = va("%s.vs.h", shaderPath); const char* psHeaderRelPath = va("%s.ps.h", shaderPath); const char* vsHeaderPath = OutputPath(vsHeaderRelPath); const char* psHeaderPath = OutputPath(psHeaderRelPath); - const char* vsExtras[] = + + int vsExtraCount = 4; + int psExtraCount = 4; + const char* vsExtras[64] = { "-D", "VERTEX_SHADER=1", "-Vn", HeaderVariable(va("g_%s_vs", varName)) }; - const char* psExtras[] = + const char* psExtras[64] = { "-D", "PIXEL_SHADER=1", "-Vn", HeaderVariable(va("g_%s_ps", varName)) }; + assert(vsExtraCount + vsOptionCount <= _countof(vsExtras)); + assert(psExtraCount + psOptionCount <= _countof(psExtras)); + + va_list argPtr; + va_start(argPtr, psOptionCount); + for(int i = 0; i < vsOptionCount; i++) + { + vsExtras[vsExtraCount++] = va_arg(argPtr, const char*); + } + for(int i = 0; i < psOptionCount; i++) + { + psExtras[psExtraCount++] = va_arg(argPtr, const char*); + } + va_end(argPtr); + ShaderArgs args; args.entryPoint = "vs"; args.headerPath = vsHeaderRelPath; args.shaderPath = shaderPath; args.targetProfile = targetVS; - CompileShader(args, _countof(vsExtras), vsExtras); + CompileShader(args, vsExtraCount, vsExtras); args.entryPoint = "ps"; args.headerPath = psHeaderRelPath; args.shaderPath = shaderPath; args.targetProfile = targetPS; - CompileShader(args, _countof(psExtras), psExtras); + CompileShader(args, psExtraCount, psExtras); const char* outHeaderPath = OutputPath(headerPath); system(va("type %s %s > %s", vsHeaderPath, psHeaderPath, outHeaderPath)); @@ -389,6 +408,7 @@ void ProcessCRP() CompileCompute("mip_2.h", "mip_2.hlsl", "mip_2"); CompileCompute("mip_3.h", "mip_3.hlsl", "mip_3"); CompileGraphics("prepass.h", "prepass.hlsl", "prepass"); + CompileGraphics("prepass_bary.h", "prepass.hlsl", "prepass_bary", 1, 1, "-D BARYCENTRICS=1", "-D BARYCENTRICS=1"); CompileGraphics("opaque.h", "opaque.hlsl", "opaque"); CompileGraphics("transp_draw.h", "transp_draw.hlsl", "transp_draw"); CompilePixelShader("transp_resolve.h", "transp_resolve.hlsl", "transp_resolve");