From a1cb7dcbe797016aa0dd8648f2626b4681cfab2c Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Thu, 20 Nov 2025 10:39:16 +0100 Subject: [PATCH] Fix GPU BVH shader compilation for macOS/iOS --- Content/Shaders/SDF.flax | 4 +- Source/Shaders/MeshAccelerationStructure.hlsl | 37 +++++++++---------- Source/Shaders/SDF.shader | 10 +---- 3 files changed, 21 insertions(+), 30 deletions(-) diff --git a/Content/Shaders/SDF.flax b/Content/Shaders/SDF.flax index 5141c14dd..709cc20f2 100644 --- a/Content/Shaders/SDF.flax +++ b/Content/Shaders/SDF.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d2b1dc1523cb2140db7ce5fed6e97b09d7fcebbe6cc19fca7708b5b882267040 -size 4175 +oid sha256:d3922811f0eb56cbb515c93cd53d80316740ea78219aa81118d2c9dee4a9d230 +size 4142 diff --git a/Source/Shaders/MeshAccelerationStructure.hlsl b/Source/Shaders/MeshAccelerationStructure.hlsl index d98d25404..0559e5f55 100644 --- a/Source/Shaders/MeshAccelerationStructure.hlsl +++ b/Source/Shaders/MeshAccelerationStructure.hlsl @@ -16,13 +16,10 @@ struct BVHNode int Count; // Negative for non-leaf nodes }; -struct BVHBuffers -{ - StructuredBuffer BVHBuffer; - ByteAddressBuffer VertexBuffer; - ByteAddressBuffer IndexBuffer; - uint VertexStride; -}; +// Pass all data via separate params (SPIR-V doesn't support buffers in structures) +#define BVHBuffers_Param StructuredBuffer BVHBuffer, ByteAddressBuffer VertexBuffer, ByteAddressBuffer IndexBuffer, uint VertexStride +#define BVHBuffers_Init(BVHBuffer, VertexBuffer, IndexBuffer, VertexStride) BVHBuffer, VertexBuffer, IndexBuffer, VertexStride +#define BVHBuffers_Pass BVHBuffers_Init(BVHBuffer, VertexBuffer, IndexBuffer, VertexStride) struct BVHHit { @@ -30,11 +27,11 @@ struct BVHHit bool IsBackface; }; -float3 LoadVertexBVH(BVHBuffers bvh, uint index) +float3 LoadVertexBVH(BVHBuffers_Param, uint index) { int addr = index << 2u; - uint vertexIndex = bvh.IndexBuffer.Load(addr); - return asfloat(bvh.VertexBuffer.Load3(vertexIndex * bvh.VertexStride)); + uint vertexIndex = IndexBuffer.Load(addr); + return asfloat(VertexBuffer.Load3(vertexIndex * VertexStride)); } // [https://tavianator.com/2011/ray_box.html] @@ -52,7 +49,7 @@ float RayTestBoxBVH(float3 rayPos, float3 rayDir, float3 boxMin, float3 boxMax) } // Performs raytracing against the BVH acceleration structure to find the closest intersection with a triangle. -bool RayCastBVH(BVHBuffers bvh, float3 rayPos, float3 rayDir, out BVHHit hit, float maxDistance = 1000000.0f) +bool RayCastBVH(BVHBuffers_Param, float3 rayPos, float3 rayDir, out BVHHit hit, float maxDistance = 1000000.0f) { hit = (BVHHit)0; hit.Distance = maxDistance; @@ -66,7 +63,7 @@ bool RayCastBVH(BVHBuffers bvh, float3 rayPos, float3 rayDir, out BVHHit hit, fl LOOP while (stackCount > 0) { - BVHNode node = bvh.BVHBuffer[stack[--stackCount]]; + BVHNode node = BVHBuffer[stack[--stackCount]]; // Raytrace bounds float boundsHit = RayTestBoxBVH(rayPos, rayDir, node.BoundsMin, node.BoundsMax); @@ -82,9 +79,9 @@ bool RayCastBVH(BVHBuffers bvh, float3 rayPos, float3 rayDir, out BVHHit hit, fl for (uint i = indexStart; i < indexEnd;) { // Load triangle - float3 v0 = LoadVertexBVH(bvh, i++); - float3 v1 = LoadVertexBVH(bvh, i++); - float3 v2 = LoadVertexBVH(bvh, i++); + float3 v0 = LoadVertexBVH(BVHBuffers_Pass, i++); + float3 v1 = LoadVertexBVH(BVHBuffers_Pass, i++); + float3 v2 = LoadVertexBVH(BVHBuffers_Pass, i++); // Raytrace triangle float distance; @@ -109,7 +106,7 @@ bool RayCastBVH(BVHBuffers bvh, float3 rayPos, float3 rayDir, out BVHHit hit, fl } // Performs a query against the BVH acceleration structure to find the closest distance to a triangle from a given point. -bool PointQueryBVH(BVHBuffers bvh, float3 pos, out BVHHit hit, float maxDistance = 1000000.0f) +bool PointQueryBVH(BVHBuffers_Param, float3 pos, out BVHHit hit, float maxDistance = 1000000.0f) { hit = (BVHHit)0; hit.Distance = maxDistance; @@ -123,7 +120,7 @@ bool PointQueryBVH(BVHBuffers bvh, float3 pos, out BVHHit hit, float maxDistance LOOP while (stackCount > 0) { - BVHNode node = bvh.BVHBuffer[stack[--stackCount]]; + BVHNode node = BVHBuffer[stack[--stackCount]]; // Skip too far nodes if (PointDistanceBox(node.BoundsMin, node.BoundsMax, pos) >= hit.Distance) @@ -138,9 +135,9 @@ bool PointQueryBVH(BVHBuffers bvh, float3 pos, out BVHHit hit, float maxDistance for (uint i = indexStart; i < indexEnd;) { // Load triangle - float3 v0 = LoadVertexBVH(bvh, i++); - float3 v1 = LoadVertexBVH(bvh, i++); - float3 v2 = LoadVertexBVH(bvh, i++); + float3 v0 = LoadVertexBVH(BVHBuffers_Pass, i++); + float3 v1 = LoadVertexBVH(BVHBuffers_Pass, i++); + float3 v2 = LoadVertexBVH(BVHBuffers_Pass, i++); // Check triangle float distance = sqrt(DistancePointToTriangle2(pos, v0, v1, v2)); diff --git a/Source/Shaders/SDF.shader b/Source/Shaders/SDF.shader index b2ae928f7..77e27d8f9 100644 --- a/Source/Shaders/SDF.shader +++ b/Source/Shaders/SDF.shader @@ -77,15 +77,9 @@ void CS_RasterizeTriangles(uint3 GroupId : SV_GroupID, uint3 GroupThreadID : SV_ int3 voxelCoord = GetVoxelCoord(voxelIndex); float3 voxelPos = GetVoxelPos(voxelCoord); - BVHBuffers bvh; - bvh.BVHBuffer = BVHBuffer; - bvh.VertexBuffer = VertexBuffer; - bvh.IndexBuffer = IndexBuffer; - bvh.VertexStride = VertexStride; - // Point query to find the distance to the closest surface BVHHit hit; - PointQueryBVH(bvh, voxelPos, hit, MaxDistance); + PointQueryBVH(BVHBuffers_Init(BVHBuffer, VertexBuffer, IndexBuffer, VertexStride), voxelPos, hit, MaxDistance); float sdf = hit.Distance; // Raycast triangles around voxel to count triangle backfaces hit @@ -104,7 +98,7 @@ void CS_RasterizeTriangles(uint3 GroupId : SV_GroupID, uint3 GroupThreadID : SV_ for (uint i = 0; i < CLOSEST_CACHE_SIZE; i++) { float3 rayDir = closestDirections[i]; - if (RayCastBVH(bvh, voxelPos, rayDir, hit, MaxDistance)) + if (RayCastBVH(BVHBuffers_Init(BVHBuffer, VertexBuffer, IndexBuffer, VertexStride), voxelPos, rayDir, hit, MaxDistance)) { sdf = min(sdf, hit.Distance); if (hit.IsBackface)