DXR 1.1 and SV_Barycentrics support are now optional

This commit is contained in:
myT 2024-02-18 22:51:59 +01:00
parent 62f3a17e55
commit b5b16e6033
11 changed files with 126 additions and 38 deletions

View file

@ -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();

View file

@ -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);

View file

@ -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;

View file

@ -23,6 +23,7 @@ along with Challenge Quake 3. If not, see <https://www.gnu.org/licenses/>.
#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!
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);

View file

@ -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;
}

View file

@ -98,7 +98,6 @@ void GRP::Init()
{
InitDesc initDesc;
initDesc.directDescriptorHeapIndexing = false;
initDesc.inlineRaytracing = false;
srp.firstInit = RHI::Init(initDesc);
if(srp.firstInit)

View file

@ -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;

View file

@ -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)

View file

@ -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);

View file

@ -1755,6 +1755,8 @@ struct RHIInfo
qbool hasExtendedVRS;
qbool isUMA;
qbool isCacheCoherentUMA;
qbool hasInlineRaytracing;
qbool hasBarycentrics;
};
extern RHIInfo rhiInfo;

View file

@ -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");