Don't require dxc for compiling RT patching shaders

* We do some manual uint64 emulation with uint2 which compiles on fxc, re-used
  from the execute indirect patching.
This commit is contained in:
baldurk
2024-04-30 18:28:33 +01:00
parent c26c4b11d0
commit cfc5204a69
6 changed files with 206 additions and 72 deletions
+71 -3
View File
@@ -34,6 +34,7 @@
#define float2 Vec2f
#define float3 Vec3f
#define uint4 Vec4u
#define uint2 Vec2u
#define int4 Vec4i
#define float4 Vec4f
#define float4x4 Matrix4f
@@ -195,8 +196,76 @@ cbuffer AccStructPatchInfo REG(b0)
uint addressCount;
};
#if defined(SHADER_MODEL_MIN_6_0_REQUIRED) || defined(__cplusplus)
// INCLUDE_GPUADDRESS_HELPERS should only be set for unit tests to check these functions below,
// otherwise it pollutes the interface
#if defined(__cplusplus) && !defined(INCLUDE_GPUADDRESS_HELPERS)
// on the GPU this will be uint2 {.x = LSB, .y = MSB} to match uint64 order
typedef uint64_t GPUAddress;
#else
typedef uint2 GPUAddress;
#endif
// don't define the helpers in C++ by default, unless we're using them for unit tests
#if !defined(__cplusplus) || defined(INCLUDE_GPUADDRESS_HELPERS)
#if defined(__cplusplus)
#define max RDCMAX
#define min RDCMIN
#endif
bool lessThan(GPUAddress a, GPUAddress b)
{
// either MSB is less, or MSB is equal and LSB is less-equal
return a.y < b.y || (a.y == b.y && a.x < b.x);
}
bool lessEqual(GPUAddress a, GPUAddress b)
{
return lessThan(a, b) || (a.y == b.y && a.x == b.x);
}
GPUAddress add(GPUAddress a, GPUAddress b)
{
uint msb = 0, lsb = 0;
if(b.x > 0 && a.x > 0xffffffff - b.x)
{
uint x = max(a.x, b.x) - 0x80000000;
uint y = min(a.x, b.x);
uint sum = x + y;
msb = a.y + b.y + 1;
lsb = sum - 0x80000000;
}
else
{
msb = a.y + b.y;
lsb = a.x + b.x;
}
return GPUAddress(lsb, msb);
}
GPUAddress sub(GPUAddress a, GPUAddress b)
{
uint msb = 0, lsb = 0;
if(a.x < b.x)
{
uint diff = b.x - a.x;
msb = a.y - b.y - 1;
lsb = 0xffffffff - (diff - 1);
}
else
{
msb = a.y - b.y;
lsb = a.x - b.x;
}
return GPUAddress(lsb, msb);
}
#endif
struct BlasAddressRange
{
@@ -213,10 +282,9 @@ struct BlasAddressPair
// This corresponds to D3D12_RAYTRACING_INSTANCE_DESC structure
struct InstanceDesc
{
uint64_t padding[7];
uint2 padding[7];
GPUAddress blasAddress;
};
#endif
cbuffer DebugSampleOperation REG(b0)
{
+7 -60
View File
@@ -154,77 +154,24 @@ cbuffer countbuffer : register(b2)
struct buffermapping
{
// {.x = LSB, .y = MSB} to match uint64 order
uint2 origBase;
uint2 origEnd;
uint2 newBase;
uint2 pad;
GPUAddress origBase;
GPUAddress origEnd;
GPUAddress newBase;
GPUAddress pad;
};
StructuredBuffer<buffermapping> buffers : register(t0);
RWByteAddressBuffer arguments : register(u0);
bool uint64LessThan(uint2 a, uint2 b)
{
// either MSB is less, or MSB is equal and LSB is less-equal
return a.y < b.y || (a.y == b.y && a.x < b.x);
}
bool uint64LessEqual(uint2 a, uint2 b)
{
return uint64LessThan(a, b) || (a.y == b.y && a.x == b.x);
}
uint2 uint64Add(uint2 a, uint2 b)
{
uint msb = 0, lsb = 0;
if(b.x > 0 && a.x > 0xffffffff - b.x)
{
uint x = max(a.x, b.x) - 0x80000000;
uint y = min(a.x, b.x);
uint sum = x + y;
msb = a.y + b.y + 1;
lsb = sum - 0x80000000;
}
else
{
msb = a.y + b.y;
lsb = a.x + b.x;
}
return uint2(lsb, msb);
}
uint2 uint64Sub(uint2 a, uint2 b)
{
uint msb = 0, lsb = 0;
if(a.x < b.x)
{
uint diff = b.x - a.x;
msb = a.y - b.y - 1;
lsb = 0xffffffff - (diff - 1);
}
else
{
msb = a.y - b.y;
lsb = a.x - b.x;
}
return uint2(lsb, msb);
}
uint2 PatchAddress(uint2 addr)
GPUAddress PatchAddress(GPUAddress addr)
{
for(uint i = 0; i < bufCount; i++)
{
buffermapping b = buffers[i];
if(uint64LessEqual(b.origBase, addr) && uint64LessThan(addr, b.origEnd))
if(lessEqual(b.origBase, addr) && lessThan(addr, b.origEnd))
{
return uint64Add(b.newBase, uint64Sub(addr, b.origBase));
return add(b.newBase, sub(addr, b.origBase));
}
}
+6 -8
View File
@@ -22,17 +22,14 @@
* THE SOFTWARE.
******************************************************************************/
#ifndef SHADER_MODEL_MIN_6_0_REQUIRED
#define SHADER_MODEL_MIN_6_0_REQUIRED
#endif
#include "hlsl_cbuffers.h"
RWStructuredBuffer<InstanceDesc> instanceDescs : register(u0, space0);
StructuredBuffer<BlasAddressPair> oldNewAddressesPair : register(t0, space0);
RWStructuredBuffer<InstanceDesc> instanceDescs : register(u0);
StructuredBuffer<BlasAddressPair> oldNewAddressesPair : register(t0);
bool InRange(BlasAddressRange addressRange, GPUAddress address)
{
if(addressRange.start <= address && address <= addressRange.end)
if(lessEqual(addressRange.start, address) && lessThan(address, addressRange.end))
{
return true;
}
@@ -49,8 +46,9 @@ bool InRange(BlasAddressRange addressRange, GPUAddress address)
{
if(InRange(oldNewAddressesPair[i].oldAddress, instanceBlasAddress))
{
uint64_t offset = instanceBlasAddress - oldNewAddressesPair[i].oldAddress.start;
instanceDescs[dispatchGroup.x].blasAddress = oldNewAddressesPair[i].newAddress.start + offset;
GPUAddress offset = sub(instanceBlasAddress, oldNewAddressesPair[i].oldAddress.start);
instanceDescs[dispatchGroup.x].blasAddress =
add(oldNewAddressesPair[i].newAddress.start, offset);
return;
}
}