diff --git a/WickedEngine/ShaderInterop_BVH.h b/WickedEngine/ShaderInterop_BVH.h index 05663e527..1cd787887 100644 --- a/WickedEngine/ShaderInterop_BVH.h +++ b/WickedEngine/ShaderInterop_BVH.h @@ -14,15 +14,18 @@ CBUFFER(BVHCB, CBSLOT_RENDERER_BVH) uint xTraceBVHMeshVertexPOSStride; }; + struct BVHPrimitive { float3 v0; - uint n0; - float3 v1; - uint n1; - float3 v2; +}; +struct BVHPrimitiveData +{ + uint userdata; + uint n0; + uint n1; uint n2; uint2 u0; diff --git a/WickedEngine/bvh_primitivesCS.hlsl b/WickedEngine/bvh_primitivesCS.hlsl index d4b336fd1..2213af38c 100644 --- a/WickedEngine/bvh_primitivesCS.hlsl +++ b/WickedEngine/bvh_primitivesCS.hlsl @@ -16,7 +16,8 @@ TYPEDBUFFER(meshVertexBuffer_COL, float4, TEXSLOT_ONDEMAND5); RWSTRUCTUREDBUFFER(primitiveIDBuffer, uint, 0); RWSTRUCTUREDBUFFER(primitiveBuffer, BVHPrimitive, 1); -RWSTRUCTUREDBUFFER(primitiveMortonBuffer, float, 2); // morton buffer is float because sorting is written for floats! +RWSTRUCTUREDBUFFER(primitiveDataBuffer, BVHPrimitiveData, 2); +RWSTRUCTUREDBUFFER(primitiveMortonBuffer, float, 3); // morton buffer is float because sorting is written for floats! // Expands a 10-bit integer into 30 bits @@ -79,9 +80,10 @@ void main(uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex) const uint materialIndex = xTraceBVHMaterialOffset + subsetIndex; TracedRenderingMaterial material = materialBuffer[materialIndex]; - float3 pos0 = mul(WORLD, float4(pos_nor0.xyz, 1)).xyz; - float3 pos1 = mul(WORLD, float4(pos_nor1.xyz, 1)).xyz; - float3 pos2 = mul(WORLD, float4(pos_nor2.xyz, 1)).xyz; + BVHPrimitive prim; + prim.v0 = mul(WORLD, float4(pos_nor0.xyz, 1)).xyz; + prim.v1 = mul(WORLD, float4(pos_nor1.xyz, 1)).xyz; + prim.v2 = mul(WORLD, float4(pos_nor2.xyz, 1)).xyz; nor0 = normalize(mul((float3x3)WORLD, nor0)); nor1 = normalize(mul((float3x3)WORLD, nor1)); nor2 = normalize(mul((float3x3)WORLD, nor2)); @@ -89,7 +91,7 @@ void main(uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex) float4 u1 = float4(meshVertexBuffer_UV0[i1] * material.texMulAdd.xy + material.texMulAdd.zw, meshVertexBuffer_UV1[i1]); float4 u2 = float4(meshVertexBuffer_UV0[i2] * material.texMulAdd.xy + material.texMulAdd.zw, meshVertexBuffer_UV1[i2]); - float4 color = xTraceBVHInstanceColor * material.baseColor; + const float4 color = xTraceBVHInstanceColor * material.baseColor; float4 c0 = color; float4 c1 = color; float4 c2 = color; @@ -108,22 +110,22 @@ void main(uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex) { const float3 facenormal = normalize(nor0 + nor1 + nor2); - float x1 = pos1.x - pos0.x; - float x2 = pos2.x - pos0.x; - float y1 = pos1.y - pos0.y; - float y2 = pos2.y - pos0.y; - float z1 = pos1.z - pos0.z; - float z2 = pos2.z - pos0.z; + const float x1 = prim.v1.x - prim.v0.x; + const float x2 = prim.v2.x - prim.v0.x; + const float y1 = prim.v1.y - prim.v0.y; + const float y2 = prim.v2.y - prim.v0.y; + const float z1 = prim.v1.z - prim.v0.z; + const float z2 = prim.v2.z - prim.v0.z; - float s1 = u1.x - u0.x; - float s2 = u2.x - u0.x; - float t1 = u1.y - u0.y; - float t2 = u2.y - u0.y; + const float s1 = u1.x - u0.x; + const float s2 = u2.x - u0.x; + const float t1 = u1.y - u0.y; + const float t2 = u2.y - u0.y; - float r = 1.0f / (s1 * t2 - s2 * t1); - float3 sdir = float3((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, + const float r = 1.0f / (s1 * t2 - s2 * t1); + const float3 sdir = float3((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r); - float3 tdir = float3((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, + const float3 tdir = float3((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r); tangent.xyz = normalize(sdir - facenormal * dot(facenormal, sdir)); @@ -132,26 +134,25 @@ void main(uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex) binormal = normalize(cross(tangent.xyz, facenormal) * tangent.w); } - // Pack primitive to store: - BVHPrimitive prim = (BVHPrimitive)0; - prim.v0 = pos0; - prim.v1 = pos1; - prim.v2 = pos2; - prim.n0 = pack_unitvector(nor0); - prim.n1 = pack_unitvector(nor1); - prim.n2 = pack_unitvector(nor2); - prim.u0 = pack_half4(u0); - prim.u1 = pack_half4(u1); - prim.u2 = pack_half4(u2); - prim.c0 = pack_rgba(c0); - prim.c1 = pack_rgba(c1); - prim.c2 = pack_rgba(c2); - prim.tangent = pack_unitvector(tangent.xyz); - prim.binormal = pack_unitvector(binormal); - prim.materialIndex = materialIndex; + // Pack primitive data: + BVHPrimitiveData primdata; + primdata.userdata = 0; + primdata.n0 = pack_unitvector(nor0); + primdata.n1 = pack_unitvector(nor1); + primdata.n2 = pack_unitvector(nor2); + primdata.u0 = pack_half4(u0); + primdata.u1 = pack_half4(u1); + primdata.u2 = pack_half4(u2); + primdata.c0 = pack_rgba(c0); + primdata.c1 = pack_rgba(c1); + primdata.c2 = pack_rgba(c2); + primdata.tangent = pack_unitvector(tangent.xyz); + primdata.binormal = pack_unitvector(binormal); + primdata.materialIndex = materialIndex; - // Store packed primitive: + // Store primitive: primitiveBuffer[primitiveID] = prim; + primitiveDataBuffer[primitiveID] = primdata; primitiveIDBuffer[primitiveID] = primitiveID; // will be sorted by morton so we need this! diff --git a/WickedEngine/raySceneIntersectHF.hlsli b/WickedEngine/raySceneIntersectHF.hlsli index 1c84657d0..d39e4e667 100644 --- a/WickedEngine/raySceneIntersectHF.hlsli +++ b/WickedEngine/raySceneIntersectHF.hlsli @@ -9,10 +9,11 @@ STRUCTUREDBUFFER(materialBuffer, TracedRenderingMaterial, TEXSLOT_ONDEMAND0); TEXTURE2D(materialTextureAtlas, float4, TEXSLOT_ONDEMAND1); -STRUCTUREDBUFFER(primitiveBuffer, BVHPrimitive, TEXSLOT_ONDEMAND2); -RAWBUFFER(primitiveCounterBuffer, TEXSLOT_ONDEMAND3); -STRUCTUREDBUFFER(primitiveIDBuffer, uint, TEXSLOT_ONDEMAND4); -STRUCTUREDBUFFER(bvhNodeBuffer, BVHNode, TEXSLOT_ONDEMAND5); +RAWBUFFER(primitiveCounterBuffer, TEXSLOT_ONDEMAND2); +STRUCTUREDBUFFER(primitiveIDBuffer, uint, TEXSLOT_ONDEMAND3); +STRUCTUREDBUFFER(primitiveBuffer, BVHPrimitive, TEXSLOT_ONDEMAND4); +STRUCTUREDBUFFER(primitiveDataBuffer, BVHPrimitiveData, TEXSLOT_ONDEMAND5); +STRUCTUREDBUFFER(bvhNodeBuffer, BVHNode, TEXSLOT_ONDEMAND6); // Returns the closest hit primitive if any (useful for generic trace). If nothing was hit, then rayHit.distance will be equal to INFINITE_RAYHIT @@ -193,7 +194,7 @@ inline float3 Shade(inout Ray ray, inout RayHit hit, inout float seed, in float2 { if (hit.distance < INFINITE_RAYHIT) { - Primitive_Triangle tri = Primitive_UnpackTriangle(primitiveBuffer[hit.primitiveID]); + TriangleData tri = TriangleData_Unpack(primitiveDataBuffer[hit.primitiveID]); float u = hit.bary.x; float v = hit.bary.y; diff --git a/WickedEngine/raytrace_lightsamplingCS.hlsl b/WickedEngine/raytrace_lightsamplingCS.hlsl index 37e0bec5a..1e9d9de6e 100644 --- a/WickedEngine/raytrace_lightsamplingCS.hlsl +++ b/WickedEngine/raytrace_lightsamplingCS.hlsl @@ -34,7 +34,7 @@ void main( uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex) float3 finalResult = 0; - Primitive_Triangle tri = Primitive_UnpackTriangle(primitiveBuffer[ray.primitiveID]); + TriangleData tri = TriangleData_Unpack(primitiveDataBuffer[ray.primitiveID]); float u = ray.bary.x; float v = ray.bary.y; diff --git a/WickedEngine/tracedRenderingHF.hlsli b/WickedEngine/tracedRenderingHF.hlsli index cef9cca98..baed60dbc 100644 --- a/WickedEngine/tracedRenderingHF.hlsli +++ b/WickedEngine/tracedRenderingHF.hlsli @@ -153,7 +153,7 @@ inline RayHit CreateRayHit() //} -struct Primitive_Triangle +struct TriangleData { float3 v0, v1, v2; // positions float3 n0, n1, n2; // normals @@ -163,29 +163,26 @@ struct Primitive_Triangle float3 binormal; uint materialIndex; }; -inline Primitive_Triangle Primitive_UnpackTriangle(in BVHPrimitive prim) +inline TriangleData TriangleData_Unpack(in BVHPrimitiveData primdata) { - Primitive_Triangle tri; + TriangleData tri; - tri.v0 = prim.v0; - tri.v1 = prim.v1; - tri.v2 = prim.v2; - tri.materialIndex = prim.materialIndex; + tri.n0 = unpack_unitvector(primdata.n0); + tri.n1 = unpack_unitvector(primdata.n1); + tri.n2 = unpack_unitvector(primdata.n2); - tri.n0 = unpack_unitvector(prim.n0); - tri.n1 = unpack_unitvector(prim.n1); - tri.n2 = unpack_unitvector(prim.n2); + tri.u0 = unpack_half4(primdata.u0); + tri.u1 = unpack_half4(primdata.u1); + tri.u2 = unpack_half4(primdata.u2); - tri.tangent = unpack_unitvector(prim.tangent); - tri.binormal = unpack_unitvector(prim.binormal); + tri.c0 = unpack_rgba(primdata.c0); + tri.c1 = unpack_rgba(primdata.c1); + tri.c2 = unpack_rgba(primdata.c2); - tri.u0 = unpack_half4(prim.u0); - tri.u1 = unpack_half4(prim.u1); - tri.u2 = unpack_half4(prim.u2); + tri.tangent = unpack_unitvector(primdata.tangent); + tri.binormal = unpack_unitvector(primdata.binormal); - tri.c0 = unpack_rgba(prim.c0); - tri.c1 = unpack_rgba(prim.c1); - tri.c2 = unpack_rgba(prim.c2); + tri.materialIndex = primdata.materialIndex; return tri; } diff --git a/WickedEngine/wiGPUBVH.cpp b/WickedEngine/wiGPUBVH.cpp index 0a86b8b85..952c9e3d5 100644 --- a/WickedEngine/wiGPUBVH.cpp +++ b/WickedEngine/wiGPUBVH.cpp @@ -347,6 +347,17 @@ void wiGPUBVH::Build(const Scene& scene, GRAPHICSTHREAD threadID) assert(SUCCEEDED(hr)); device->SetName(&bvhFlagBuffer, "BVHFlagBuffer"); + desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS; + desc.StructureByteStride = sizeof(uint); + desc.ByteWidth = desc.StructureByteStride * maxPrimitiveCount; + desc.CPUAccessFlags = 0; + desc.Format = FORMAT_UNKNOWN; + desc.MiscFlags = RESOURCE_MISC_BUFFER_STRUCTURED; + desc.Usage = USAGE_DEFAULT; + hr = device->CreateBuffer(&desc, nullptr, &primitiveIDBuffer); + assert(SUCCEEDED(hr)); + device->SetName(&primitiveIDBuffer, "primitiveIDBuffer"); + desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS; desc.StructureByteStride = sizeof(BVHPrimitive); desc.ByteWidth = desc.StructureByteStride * maxPrimitiveCount; @@ -359,15 +370,15 @@ void wiGPUBVH::Build(const Scene& scene, GRAPHICSTHREAD threadID) device->SetName(&primitiveBuffer, "primitiveBuffer"); desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS; - desc.StructureByteStride = sizeof(uint); + desc.StructureByteStride = sizeof(BVHPrimitiveData); desc.ByteWidth = desc.StructureByteStride * maxPrimitiveCount; desc.CPUAccessFlags = 0; desc.Format = FORMAT_UNKNOWN; desc.MiscFlags = RESOURCE_MISC_BUFFER_STRUCTURED; desc.Usage = USAGE_DEFAULT; - hr = device->CreateBuffer(&desc, nullptr, &primitiveIDBuffer); + hr = device->CreateBuffer(&desc, nullptr, &primitiveDataBuffer); assert(SUCCEEDED(hr)); - device->SetName(&primitiveIDBuffer, "primitiveIDBuffer"); + device->SetName(&primitiveDataBuffer, "primitiveDataBuffer"); desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS; desc.ByteWidth = desc.StructureByteStride * maxPrimitiveCount; @@ -413,6 +424,7 @@ void wiGPUBVH::Build(const Scene& scene, GRAPHICSTHREAD threadID) GPUResource* uavs[] = { &primitiveIDBuffer, &primitiveBuffer, + &primitiveDataBuffer, &primitiveMortonBuffer, }; device->BindUAVs(CS, uavs, 0, ARRAYSIZE(uavs), threadID); @@ -633,9 +645,10 @@ void wiGPUBVH::Bind(SHADERSTAGE stage, GRAPHICSTHREAD threadID) const const GPUResource* res[] = { &globalMaterialBuffer, (globalMaterialAtlas.IsValid() ? &globalMaterialAtlas : wiTextureHelper::getWhite()), - &primitiveBuffer, &primitiveCounterBuffer, &primitiveIDBuffer, + &primitiveBuffer, + &primitiveDataBuffer, &bvhNodeBuffer, }; device->BindResources(stage, res, TEXSLOT_ONDEMAND0, ARRAYSIZE(res), threadID); diff --git a/WickedEngine/wiGPUBVH.h b/WickedEngine/wiGPUBVH.h index cedbf2eee..a9e436f7c 100644 --- a/WickedEngine/wiGPUBVH.h +++ b/WickedEngine/wiGPUBVH.h @@ -17,9 +17,10 @@ private: // Scene BVH intersection resources: wiGraphics::GPUBuffer bvhNodeBuffer; wiGraphics::GPUBuffer bvhFlagBuffer; - wiGraphics::GPUBuffer primitiveBuffer; wiGraphics::GPUBuffer primitiveCounterBuffer; wiGraphics::GPUBuffer primitiveIDBuffer; + wiGraphics::GPUBuffer primitiveBuffer; + wiGraphics::GPUBuffer primitiveDataBuffer; wiGraphics::GPUBuffer primitiveMortonBuffer; wiGraphics::GPUBuffer primitiveSortedMortonBuffer; uint32_t maxPrimitiveCount = 0;