From 064ba2239193fe02363f8a9bc98baf3c28c86f87 Mon Sep 17 00:00:00 2001 From: Dynamitos Date: Mon, 15 Jul 2024 17:55:22 +0200 Subject: [PATCH] Adding normal mapping --- res/shaders/lib/BRDF.slang | 37 ++--- res/shaders/lib/LightEnv.slang | 10 +- res/shaders/lib/MaterialParameter.slang | 15 +- res/shaders/raytracing/ClosestHit.slang | 71 ++++---- src/Engine/Asset/TextureAsset.cpp | 7 +- .../Graphics/RenderPass/RayTracingPass.cpp | 34 ++-- .../Graphics/RenderPass/RayTracingPass.h | 1 - src/Engine/Graphics/Shader.cpp | 4 +- src/Engine/Graphics/Shader.h | 2 +- src/Engine/Graphics/Vulkan/Buffer.cpp | 1 + src/Engine/Graphics/Vulkan/PipelineCache.cpp | 157 +++++------------- src/Engine/Graphics/Vulkan/RayTracing.cpp | 2 +- src/Engine/Graphics/slang-compile.cpp | 2 +- src/Engine/Material/Material.cpp | 6 +- src/Engine/Window/GameView.cpp | 12 +- 15 files changed, 151 insertions(+), 210 deletions(-) diff --git a/res/shaders/lib/BRDF.slang b/res/shaders/lib/BRDF.slang index 7feceb5..802a986 100644 --- a/res/shaders/lib/BRDF.slang +++ b/res/shaders/lib/BRDF.slang @@ -2,7 +2,7 @@ import Common; interface IBRDF { - float3 evaluate(float3x3 tbn, float3 viewDir_WS, float3 lightDir_WS, float3 normal_WS, float3 lightColor); + float3 evaluate(float3 viewDir_TS, float3 lightDir_TS, float3 lightColor); float3 evaluateAmbient(); }; @@ -19,13 +19,12 @@ struct Phong : IBRDF normal = float3(0, 0, 1); } - float3 evaluate(float3x3 tbn, float3 viewDir_WS, float3 lightDir_WS, float3 n, float3 lightColor) + float3 evaluate(float3 viewDir_TS, float3 lightDir_TS, float3 lightColor) { float3 normal_TS = normal; - float3 normal_WS = n;//normalize(mul(tbn, normal_TS)); - float3 nDotL = dot(normal_WS, lightDir_WS); - float3 r = 2 * (nDotL) * normal_WS - lightDir_WS; - float rDotV = dot(r, viewDir_WS); + float3 nDotL = dot(normal_TS, lightDir_TS); + float3 r = 2 * (nDotL) * normal_TS - lightDir_TS; + float rDotV = dot(r, viewDir_TS); return lightColor * (baseColor * max(nDotL, 0.0));// + specular * pow(max(rDotV, 0.0), max(shininess, 1))); } @@ -49,12 +48,11 @@ struct BlinnPhong : IBRDF normal = float3(0, 0, 1); } - float3 evaluate(float3x3 tbn, float3 viewDir_WS, float3 lightDir_WS, float3 normal_WS, float3 lightColor) + float3 evaluate(float3 viewDir_TS, float3 lightDir_TS, float3 lightColor) { float3 normal_TS = normalize(normal); - //float3 normal_WS = normalize(mul(tbn, normal_TS)); - float diffuse = max(dot(normal_WS, lightDir_WS), 0); - float3 h = normalize(lightDir_WS + viewDir_WS); + float diffuse = max(dot(normal_TS, lightDir_TS), 0); + float3 h = normalize(lightDir_TS + viewDir_TS); float specular = pow(saturate(dot(normal_TS, h)), shininess); return (baseColor * diffuse * lightColor) + (specularColor * specular); @@ -76,11 +74,10 @@ struct CelShading : IBRDF normal = float3(0, 0, 1); } - float3 evaluate(float3x3 tbn, float3 viewDir_WS, float3 lightDir_WS, float3 n, float3 lightColor) + float3 evaluate(float3 viewDir_TS, float3 lightDir_TS, float3 lightColor) { float3 normal_TS = normalize(normal); - float3 normal_WS = normalize(mul(tbn, normal_TS)); - float nDotL = dot(normal_WS, lightDir_WS); + float nDotL = dot(normal_TS, lightDir_TS); float diffuse = max(nDotL, 0); float3 darkenedBase = baseColor * 0.8; @@ -148,21 +145,21 @@ struct CookTorrance : IBRDF return F0 + (1.0 - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0); } - float3 evaluate(float3x3 tbn, float3 viewDir_WS, float3 lightDir_WS, float3 normal_WS, float3 lightColor) + float3 evaluate(float3 viewDir_TS, float3 lightDir_TS, float3 lightColor) { - float3 n = normal_WS;//normalize(mul(tbn, normal)); - float3 h = normalize(lightDir_WS + viewDir_WS); + float3 n = normal;//normalize(mul(tbn, normal)); + float3 h = normalize(lightDir_TS + viewDir_TS); float3 F0 = float3(0.04); F0 = lerp(F0, baseColor, metallic); - float3 F = FresnelSchlick(max(dot(h, viewDir_WS), 0.0), F0); + float3 F = FresnelSchlick(max(dot(h, viewDir_TS), 0.0), F0); float NDF = TrowbridgeReitzGGX(n, h); - float G = Smith(n, viewDir_WS, lightDir_WS); + float G = Smith(n, viewDir_TS, lightDir_TS); float3 num = NDF * G * F; - float denom = 4.0 * max(dot(n, viewDir_WS), 0.0) * max(dot(n, lightDir_WS), 0.0) + 0.000001; + float denom = 4.0 * max(dot(n, viewDir_TS), 0.0) * max(dot(n, lightDir_TS), 0.0) + 0.000001; float3 specular = num / denom; float3 k_s = F; @@ -170,7 +167,7 @@ struct CookTorrance : IBRDF k_d *= 1.0 - metallic; - float nDotL = max(dot(n, lightDir_WS), 0.0); + float nDotL = max(dot(n, lightDir_TS), 0.0); float3 result = (k_d * baseColor / PI + specular) * nDotL * lightColor; return result * ambientOcclusion; diff --git a/res/shaders/lib/LightEnv.slang b/res/shaders/lib/LightEnv.slang index ca6732a..a8c9217 100644 --- a/res/shaders/lib/LightEnv.slang +++ b/res/shaders/lib/LightEnv.slang @@ -14,7 +14,8 @@ struct DirectionalLight : ILightEnv float3 illuminate(LightingParameter params, B brdf) { - return brdf.evaluate(params.tbn, params.viewDir_WS, -normalize(direction.xyz), params.normal_WS, color.xyz); + float3 dir_TS = mul(params.tbn, -normalize(direction.xyz)); + return brdf.evaluate(params.viewDir_TS, dir_TS, color.xyz); } }; @@ -25,10 +26,11 @@ struct PointLight : ILightEnv float3 illuminate(LightingParameter params, B brdf) { - float3 lightDir_WS = position_WS.xyz - params.position_WS; - float d = length(lightDir_WS); + float3 pos_TS = mul(params.tbn, position_WS.xyz); + float3 lightDir_TS = pos_TS.xyz - params.position_TS; + float d = length(lightDir_TS); float illuminance = max(1 - d / colorRange.w, 0); - return illuminance * brdf.evaluate(params.tbn, params.viewDir_WS, normalize(lightDir_WS), normalize(params.normal_WS), colorRange.xyz); + return illuminance * brdf.evaluate(params.viewDir_TS, normalize(lightDir_TS), colorRange.xyz); } bool insidePlane(Plane plane, float3 position) diff --git a/res/shaders/lib/MaterialParameter.slang b/res/shaders/lib/MaterialParameter.slang index ae9c2b7..cdd47db 100644 --- a/res/shaders/lib/MaterialParameter.slang +++ b/res/shaders/lib/MaterialParameter.slang @@ -11,9 +11,9 @@ struct MaterialParameter struct LightingParameter { float3x3 tbn; - float3 normal_WS; - float3 position_WS; - float3 viewDir_WS; + float3 normal_TS; + float3 position_TS; + float3 viewDir_TS; }; // data passed to fragment shader @@ -42,10 +42,11 @@ struct FragmentParameter LightingParameter getLightingParameter() { LightingParameter result; - result.tbn = float3x3(normalize(tangent_WS), normalize(biTangent_WS), normalize(normal_WS)); - result.position_WS = position_WS; - result.viewDir_WS = normalize(cameraPos_WS - position_WS); - result.normal_WS = normal_WS; + float3x3 tbn = float3x3(normalize(tangent_WS), normalize(biTangent_WS), normalize(normal_WS)); + result.tbn = tbn; + result.position_TS = mul(tbn, position_WS); + result.viewDir_TS = mul(tbn, normalize(cameraPos_WS - position_WS)); + result.normal_TS = mul(tbn, normal_WS); return result; } #endif diff --git a/res/shaders/raytracing/ClosestHit.slang b/res/shaders/raytracing/ClosestHit.slang index c4950a1..f0b76fb 100644 --- a/res/shaders/raytracing/ClosestHit.slang +++ b/res/shaders/raytracing/ClosestHit.slang @@ -3,40 +3,55 @@ import MaterialParameter; import LightEnv; import Scene; import RayTracingData; +import VertexData; +import Material; +import MATERIAL_FILE_NAME; // simplification: all BLAS only have 1 geometry [shader("closesthit")] void closestHit(inout RayPayload hitValue, in BuiltInTriangleIntersectionAttributes attr) { - //const float3 barycentricCoords = float3(1.0f - attr.barycentrics.x - attr.barycentrics.y, attr.barycentrics.x, attr.barycentrics.y); + const float3 barycentricCoords = float3(1.0f - attr.barycentrics.x - attr.barycentrics.y, attr.barycentrics.x, attr.barycentrics.y); - //InstanceData inst = pScene.instances[InstanceID()]; - //MeshData m = pScene.meshData[InstanceID()]; -// - //// offset into the index buffer - //uint indexOffset = m.firstIndex; - //// added to indices to reference correct part of global mesh pool - //uint vertexOffset = pScene.meshletInfos[m.meshletOffset].indicesOffset; -// - //uint vertexIndex0 = vertexOffset + pRayTracingParams.indexBuffer[indexOffset + 3 * PrimitiveIndex() + 0]; - //uint vertexIndex1 = vertexOffset + pRayTracingParams.indexBuffer[indexOffset + 3 * PrimitiveIndex() + 1]; - //uint vertexIndex2 = vertexOffset + pRayTracingParams.indexBuffer[indexOffset + 3 * PrimitiveIndex() + 2]; -// - //VertexAttributes attr0 = pVertexData.getAttributes(vertexIndex0); - //VertexAttributes attr1 = pVertexData.getAttributes(vertexIndex1); - //VertexAttributes attr2 = pVertexData.getAttributes(vertexIndex2); -// - //FragmentParameter f0 = attr0.getParameter(inst.transformMatrix); - //FragmentParameter f1 = attr1.getParameter(inst.transformMatrix); - //FragmentParameter f2 = attr2.getParameter(inst.transformMatrix); -// - //FragmentParameter params = FragmentParameter.interpolate(f0, f1, f2, barycentricCoords); -// - //CallablePayload callable; - //callable.params = params; -// - //CallShader(InstanceID(), callable); + InstanceData inst = pScene.instances[InstanceID()]; + MeshData m = pScene.meshData[InstanceID()]; - hitValue.color = float3(1, 0, 0); + // offset into the index buffer + uint indexOffset = m.firstIndex; + // added to indices to reference correct part of global mesh pool + uint vertexOffset = pScene.meshletInfos[m.meshletOffset].indicesOffset; + + uint vertexIndex0 = vertexOffset + pRayTracingParams.indexBuffer[indexOffset + 3 * PrimitiveIndex() + 0]; + uint vertexIndex1 = vertexOffset + pRayTracingParams.indexBuffer[indexOffset + 3 * PrimitiveIndex() + 1]; + uint vertexIndex2 = vertexOffset + pRayTracingParams.indexBuffer[indexOffset + 3 * PrimitiveIndex() + 2]; + + VertexAttributes attr0 = pVertexData.getAttributes(vertexIndex0); + VertexAttributes attr1 = pVertexData.getAttributes(vertexIndex1); + VertexAttributes attr2 = pVertexData.getAttributes(vertexIndex2); + + FragmentParameter f0 = attr0.getParameter(inst.transformMatrix); + FragmentParameter f1 = attr1.getParameter(inst.transformMatrix); + FragmentParameter f2 = attr2.getParameter(inst.transformMatrix); + + FragmentParameter params = FragmentParameter.interpolate(f0, f1, f2, barycentricCoords); + + LightingParameter lightingParams = params.getLightingParameter(); + MaterialParameter materialParams = params.getMaterialParameter(); + let brdf = Material.prepare(materialParams); + + float3 result = float3(0, 0, 0); + for(int i = 0; i < pLightEnv.numDirectionalLights; ++i) + { + result += pLightEnv.directionalLights[i].illuminate(lightingParams, brdf); + } + for(uint i = 0; i < pLightEnv.numPointLights; ++i) + { + result += pLightEnv.pointLights[i].illuminate(lightingParams, brdf); + } + result += brdf.evaluateAmbient(); + // gamma correction + result = result / (result + float3(1.0)); + result = pow(result, float3(1.0/2.2)); + hitValue.color = getMaterialTextureParameter(0).Sample(getMaterialSamplerParameter(0), params.texCoords[0]).xyz; } \ No newline at end of file diff --git a/src/Engine/Asset/TextureAsset.cpp b/src/Engine/Asset/TextureAsset.cpp index 58b147d..c3223ac 100644 --- a/src/Engine/Asset/TextureAsset.cpp +++ b/src/Engine/Asset/TextureAsset.cpp @@ -22,9 +22,7 @@ TextureAsset::TextureAsset(std::string_view folderPath, std::string_view name) : TextureAsset::~TextureAsset() {} -void TextureAsset::save(ArchiveBuffer& buffer) const { - Serialization::save(buffer, ktxData); -} +void TextureAsset::save(ArchiveBuffer& buffer) const { Serialization::save(buffer, ktxData); } void TextureAsset::load(ArchiveBuffer& buffer) { ktxTexture2* ktxHandle; @@ -33,7 +31,7 @@ void TextureAsset::load(ArchiveBuffer& buffer) { ktxTexture_CreateFromMemory(ktxData.data(), ktxData.size(), KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, (ktxTexture**)&ktxHandle)); ktxTexture2_TranscodeBasis(ktxHandle, KTX_TTF_RGBA32, 0); - //ktxTexture2_DeflateZstd(ktxHandle, 0); + // ktxTexture2_DeflateZstd(ktxHandle, 0); Gfx::PGraphics graphics = buffer.getGraphics(); TextureCreateInfo createInfo = { @@ -51,6 +49,7 @@ void TextureAsset::load(ArchiveBuffer& buffer) { .layers = ktxHandle->numFaces, .elements = ktxHandle->numLayers, .usage = Gfx::SE_IMAGE_USAGE_SAMPLED_BIT, + .name = name, }; if (ktxHandle->isCubemap) { texture = graphics->createTextureCube(createInfo); diff --git a/src/Engine/Graphics/RenderPass/RayTracingPass.cpp b/src/Engine/Graphics/RenderPass/RayTracingPass.cpp index 9783fa5..83247e1 100644 --- a/src/Engine/Graphics/RenderPass/RayTracingPass.cpp +++ b/src/Engine/Graphics/RenderPass/RayTracingPass.cpp @@ -33,7 +33,7 @@ RayTracingPass::RayTracingPass(Gfx::PGraphics graphics, PScene scene) : RenderPa pipelineLayout->addDescriptorLayout(StaticMeshVertexData::getInstance()->getInstanceDataLayout()); graphics->getShaderCompiler()->registerRenderPass("RayTracing", Gfx::PassConfig{ .baseLayout = pipelineLayout, - .mainFile = "Callable", + .mainFile = "ClosestHit", .useMaterial = true, .rayTracing = true, }); @@ -42,8 +42,7 @@ RayTracingPass::RayTracingPass(Gfx::PGraphics graphics, PScene scene) : RenderPa void RayTracingPass::beginFrame(const Component::Camera& cam) { RenderPass::beginFrame(cam); } void RayTracingPass::render() { - Gfx::ORenderCommand command = graphics->createRenderCommand("RayTracing"); - Array callableGroups; + Array callableGroups; Array accelerationStructures; Array instanceData; @@ -64,8 +63,8 @@ void RayTracingPass::render() { for (auto& inst : matData.instances) { for (uint32 i = 0; i < inst.instanceData.size(); ++i) { - Gfx::RayTracingCallableGroup callableGroup = { - .shader = collection->callableShader, + Gfx::RayTracingHitGroup callableGroup = { + .closestHitShader = collection->callableShader, }; callableGroup.parameters.resize(sizeof(VertexData::DrawCallOffsets)); std::memcpy(callableGroup.parameters.data(), &inst.offsets, sizeof(VertexData::DrawCallOffsets)); @@ -77,6 +76,13 @@ void RayTracingPass::render() { } } } + pipeline = graphics->createRayTracingPipeline(Gfx::RayTracingPipelineCreateInfo{ + .pipelineLayout = pipelineLayout, + .rayGenGroup = {.shader = rayGen}, + .hitGroups = callableGroups, + .missGroups = {{.shader = miss}}, + //.callableGroups = callableGroups, + }); tlas = graphics->createTopLevelAccelerationStructure(Gfx::TopLevelASCreateInfo{ .instances = instanceData, .bottomLevelStructures = accelerationStructures, @@ -87,6 +93,7 @@ void RayTracingPass::render() { desc->updateBuffer(2, StaticMeshVertexData::getInstance()->getIndexBuffer()); desc->writeChanges(); + Gfx::ORenderCommand command = graphics->createRenderCommand("RayTracing"); command->bindPipeline(pipeline); StaticMeshVertexData::getInstance()->getInstanceDataSet()->writeChanges(); StaticMeshVertexData::getInstance()->getVertexDataSet()->writeChanges(); @@ -118,26 +125,15 @@ void RayTracingPass::publishOutputs() { Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT); ShaderCompilationInfo compileInfo = { .name = "RT", - .modules = {"RayGen", "ClosestHit", "Miss"}, - .entryPoints = {{"raygen", "RayGen"}, {"closestHit", "ClosestHit"}, {"miss", "Miss"}}, + .modules = {"RayGen", "Miss"}, + .entryPoints = {{"raygen", "RayGen"}, {"miss", "Miss"}}, .defines = {{"RAY_TRACING", "1"}}, .rootSignature = pipelineLayout, }; graphics->beginShaderCompilation(compileInfo); rayGen = graphics->createRayGenShader({0}); - closestHit = graphics->createClosestHitShader({1}); - miss = graphics->createMissShader({2}); + miss = graphics->createMissShader({1}); pipelineLayout->create(); - pipeline = graphics->createRayTracingPipeline(Gfx::RayTracingPipelineCreateInfo{ - .pipelineLayout = pipelineLayout, - .rayGenGroup = {.shader = rayGen}, - .hitGroups = {{.closestHitShader = closestHit}}, - .missGroups = {{.shader = miss}}, - //.callableGroups = callableGroups, - }); - Component::Transform transform; - transform.setScale(Vector(1, 1, 1)); - transform.setPosition(Vector(0, 0, 1)); } void RayTracingPass::createRenderPass() {} diff --git a/src/Engine/Graphics/RenderPass/RayTracingPass.h b/src/Engine/Graphics/RenderPass/RayTracingPass.h index 8b8ecab..7a16606 100644 --- a/src/Engine/Graphics/RenderPass/RayTracingPass.h +++ b/src/Engine/Graphics/RenderPass/RayTracingPass.h @@ -19,7 +19,6 @@ class RayTracingPass : public RenderPass { Gfx::OPipelineLayout pipelineLayout; Gfx::OTexture2D texture; Gfx::ORayGenShader rayGen; - Gfx::OClosestHitShader closestHit; Gfx::OMissShader miss; Gfx::PRayTracingPipeline pipeline; Gfx::OTopLevelAS tlas; diff --git a/src/Engine/Graphics/Shader.cpp b/src/Engine/Graphics/Shader.cpp index adc7e90..5e45e3e 100644 --- a/src/Engine/Graphics/Shader.cpp +++ b/src/Engine/Graphics/Shader.cpp @@ -129,7 +129,7 @@ void ShaderCompiler::createShaders(ShaderPermutation permutation, Gfx::OPipeline createInfo.modules.add(permutation.vertexMeshFile); } else if (permutation.rayTracing) { createInfo.defines["RAY_TRACING"] = "1"; - createInfo.entryPoints = {{"callable", "Callable"}}; + createInfo.entryPoints = {{"closestHit", "ClosestHit"}}; createInfo.modules.add(permutation.vertexMeshFile); } else { createInfo.entryPoints.add({"vertexMain", permutation.vertexMeshFile}); @@ -148,7 +148,7 @@ void ShaderCompiler::createShaders(ShaderPermutation permutation, Gfx::OPipeline } collection.meshShader = graphics->createMeshShader({shaderIndex++}); } else if (permutation.rayTracing) { - collection.callableShader = graphics->createCallableShader({shaderIndex++}); + collection.callableShader = graphics->createClosestHitShader({shaderIndex++}); } else { collection.vertexShader = graphics->createVertexShader({shaderIndex++}); } diff --git a/src/Engine/Graphics/Shader.h b/src/Engine/Graphics/Shader.h index 5f38319..46592f4 100644 --- a/src/Engine/Graphics/Shader.h +++ b/src/Engine/Graphics/Shader.h @@ -154,7 +154,7 @@ struct ShaderCollection { OTaskShader taskShader; OMeshShader meshShader; OFragmentShader fragmentShader; - OCallableShader callableShader; + OClosestHitShader callableShader; }; struct PassConfig { diff --git a/src/Engine/Graphics/Vulkan/Buffer.cpp b/src/Engine/Graphics/Vulkan/Buffer.cpp index 3db672c..72460fe 100644 --- a/src/Engine/Graphics/Vulkan/Buffer.cpp +++ b/src/Engine/Graphics/Vulkan/Buffer.cpp @@ -20,6 +20,7 @@ BufferAllocation::BufferAllocation(PGraphics graphics, const std::string& name, .objectHandle = (uint64)buffer, .pObjectName = name.c_str(), }; + assert(!name.empty()); vkSetDebugUtilsObjectNameEXT(graphics->getDevice(), &nameInfo); if (bufferInfo.usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) { VkBufferDeviceAddressInfo addrInfo = { diff --git a/src/Engine/Graphics/Vulkan/PipelineCache.cpp b/src/Engine/Graphics/Vulkan/PipelineCache.cpp index 56ab0de..22bd877 100644 --- a/src/Engine/Graphics/Vulkan/PipelineCache.cpp +++ b/src/Engine/Graphics/Vulkan/PipelineCache.cpp @@ -490,7 +490,7 @@ PRayTracingPipeline PipelineCache::createPipeline(Gfx::RayTracingPipelineCreateI }); } { - for (auto hitgroup : createInfo.hitGroups) { + for (const auto& hitgroup : createInfo.hitGroups) { auto hit = hitgroup.closestHitShader.cast(); shaderStages.add(VkPipelineShaderStageCreateInfo{ .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, @@ -594,174 +594,105 @@ PRayTracingPipeline PipelineCache::createPipeline(Gfx::RayTracingPipelineCreateI }; VkPipeline pipelineHandle; VK_CHECK(vkCreateRayTracingPipelinesKHR(graphics->getDevice(), VK_NULL_HANDLE, cache, 1, &pipelineInfo, nullptr, &pipelineHandle)); - /* - const uint32_t handle_size = graphics->getRayTracingProperties().shaderGroupHandleSize; - const uint32_t handle_size_aligned = - align(graphics->getRayTracingProperties().shaderGroupHandleSize, graphics->getRayTracingProperties().shaderGroupHandleAlignment); - const uint32_t handle_alignment = graphics->getRayTracingProperties().shaderGroupHandleAlignment; - const uint32_t group_count = static_cast(shaderGroups.size()); - const uint32_t sbt_size = group_count * handle_size_aligned; - const VkBufferUsageFlags sbt_buffer_usage_flags = - VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; - const VmaMemoryUsage sbt_memory_usage = VMA_MEMORY_USAGE_CPU_TO_GPU; - - // Raygen - // Create binding table buffers for each shader type - OBufferAllocation raygen_shader_binding_table = new BufferAllocation(graphics, "RayGen", - VkBufferCreateInfo{ - .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .pNext = nullptr, - .size = handle_size, - .usage = sbt_buffer_usage_flags, - }, - VmaAllocationCreateInfo{ - .usage = sbt_memory_usage, - }, - Gfx::QueueType::GRAPHICS, 0); - OBufferAllocation miss_shader_binding_table = new BufferAllocation(graphics, "Miss", - VkBufferCreateInfo{ - .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .pNext = nullptr, - .size = handle_size, - .usage = sbt_buffer_usage_flags, - }, - VmaAllocationCreateInfo{ - .usage = sbt_memory_usage, - }, - Gfx::QueueType::GRAPHICS, 0); - OBufferAllocation hit_shader_binding_table = new BufferAllocation(graphics, "Hit", - VkBufferCreateInfo{ - .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .pNext = nullptr, - .size = handle_size, - .usage = sbt_buffer_usage_flags, - }, - VmaAllocationCreateInfo{ - .usage = sbt_memory_usage, - }, - Gfx::QueueType::GRAPHICS, 0); - - // Copy the pipeline's shader handles into a host buffer - std::vector shader_handle_storage(sbt_size); - VK_CHECK(vkGetRayTracingShaderGroupHandlesKHR(graphics->getDevice(), pipelineHandle, 0, group_count, sbt_size, - shader_handle_storage.data())); - - // Copy the shader handles from the host buffer to the binding tables - uint8_t* data = static_cast(raygen_shader_binding_table->map()); - memcpy(data, shader_handle_storage.data(), handle_size); - data = static_cast(miss_shader_binding_table->map()); - memcpy(data, shader_handle_storage.data() + handle_size_aligned, handle_size); - data = static_cast(hit_shader_binding_table->map()); - memcpy(data, shader_handle_storage.data() + handle_size_aligned * 2, handle_size); - raygen_shader_binding_table->unmap(); - miss_shader_binding_table->unmap(); - hit_shader_binding_table->unmap();*/ const uint32_t handleSize = graphics->getRayTracingProperties().shaderGroupHandleSize; const uint32_t handleSizeAligned = align(graphics->getRayTracingProperties().shaderGroupHandleSize, graphics->getRayTracingProperties().shaderGroupHandleAlignment); const uint32_t handleAlignment = graphics->getRayTracingProperties().shaderGroupHandleAlignment; + const uint32_t sbtAlignment = graphics->getRayTracingProperties().shaderGroupBaseAlignment; const uint32_t groupCount = static_cast(shaderGroups.size()); const uint32_t sbtSize = groupCount * handleSizeAligned; const VkBufferUsageFlags sbtBufferUsage = - VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; - const VmaMemoryUsage sbtMemoryUsage = VMA_MEMORY_USAGE_CPU_TO_GPU; - + VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; + const VmaMemoryUsage sbtMemoryUsage = VMA_MEMORY_USAGE_AUTO; + + uint64 rayGenStride = align(handleSize + createInfo.rayGenGroup.parameters.size(), handleAlignment); + uint64 hitStride = handleSize; + for (const auto& h : createInfo.hitGroups) { + hitStride = std::max(hitStride, align(handleSize + h.parameters.size(), handleAlignment)); + } + uint64 missStride = handleSize; + for (const auto& m : createInfo.missGroups) { + missStride = std::max(missStride, align(handleSize + m.parameters.size(), handleAlignment)); + } OBufferAllocation rayGenBuffer = new BufferAllocation(graphics, "RayGenSBT", VkBufferCreateInfo{ .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .pNext = nullptr, .flags = 0, - .size = handleSize, + .size = rayGenStride, .usage = sbtBufferUsage, }, VmaAllocationCreateInfo{ .usage = sbtMemoryUsage, }, - Gfx::QueueType::GRAPHICS); + Gfx::QueueType::GRAPHICS, sbtAlignment); OBufferAllocation hitBuffer = new BufferAllocation(graphics, "HitSBT", VkBufferCreateInfo{ .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .pNext = nullptr, .flags = 0, - .size = handleSize * createInfo.hitGroups.size(), + .size = hitStride * createInfo.hitGroups.size(), .usage = sbtBufferUsage, }, VmaAllocationCreateInfo{ .usage = sbtMemoryUsage, }, - Gfx::QueueType::GRAPHICS); + Gfx::QueueType::GRAPHICS, sbtAlignment); OBufferAllocation missBuffer = new BufferAllocation(graphics, "MissSBT", VkBufferCreateInfo{ .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .pNext = nullptr, .flags = 0, - .size = handleSize * createInfo.missGroups.size(), + .size = missStride * createInfo.missGroups.size(), .usage = sbtBufferUsage, }, VmaAllocationCreateInfo{ .usage = sbtMemoryUsage, }, - Gfx::QueueType::GRAPHICS); + Gfx::QueueType::GRAPHICS, sbtAlignment); Array sbt(sbtSize); vkGetRayTracingShaderGroupHandlesKHR(graphics->getDevice(), pipelineHandle, 0, shaderGroups.size(), sbtSize, sbt.data()); - /* maxParamSize = 0; - for (auto& callableGroup : createInfo.callableGroups) { - maxParamSize = std::max(maxParamSize, callableGroup.parameters.size()); - } - uint64 callableStride = align(handleSize + maxParamSize, handleAlignment); - - OBufferAllocation callableBuffer = new BufferAllocation(graphics, "CallableSBT", - VkBufferCreateInfo{ - .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .size = callableStride * createInfo.callableGroups.size(), - .usage = sbtBufferUsage, - }, - VmaAllocationCreateInfo{ - .usage = sbtMemoryUsage, - }, - Gfx::QueueType::GRAPHICS); - uint8* callableData = static_cast(callableBuffer->map()); - for (uint64 i = 0; i < createInfo.callableGroups.size(); ++i) { - std::memcpy(callableData, sbt.data() + sbtOffset, handleSize); - std::memcpy(callableData + handleSize, createInfo.callableGroups[i].parameters.data(), - createInfo.callableGroups[i].parameters.size()); - sbtOffset += handleSizeAligned; - callableData += callableStride; - } - callableBuffer->unmap(); - */ uint64 sbtOffset = 0; - uint8* rayGenData = static_cast(rayGenBuffer->map()); - std::memcpy(rayGenData, sbt.data() + sbtOffset, handleSize); - rayGenBuffer->unmap(); + Array rayGenSbt(rayGenStride); + std::memcpy(rayGenSbt.data(), sbt.data() + sbtOffset, handleSize); + std::memcpy(rayGenSbt.data() + handleSize, createInfo.rayGenGroup.parameters.data(), createInfo.rayGenGroup.parameters.size()); sbtOffset += handleSizeAligned; + rayGenBuffer->updateContents(0, rayGenSbt.size(), rayGenSbt.data()); + rayGenBuffer->pipelineBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_SHADER_READ_BIT, + VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR); - uint8* hitData = static_cast(hitBuffer->map()); + + Array hitSbt(hitStride * createInfo.hitGroups.size()); for (uint64 i = 0; i < createInfo.hitGroups.size(); ++i) { - std::memcpy(hitData, sbt.data() + sbtOffset, handleSize); + std::memcpy(hitSbt.data() + i * hitStride, sbt.data() + sbtOffset, handleSize); + std::memcpy(hitSbt.data() + i * hitStride + handleSize, createInfo.hitGroups[i].parameters.data(), + createInfo.hitGroups[i].parameters.size()); sbtOffset += handleSizeAligned; - hitData += handleSizeAligned; } - hitBuffer->unmap(); + hitBuffer->updateContents(0, hitSbt.size(), hitSbt.data()); + hitBuffer->pipelineBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_SHADER_READ_BIT, + VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR); - uint8* missData = static_cast(missBuffer->map()); + + Array missSbt(missStride * createInfo.missGroups.size()); for (uint64 i = 0; i < createInfo.missGroups.size(); ++i) { - std::memcpy(missData, sbt.data() + sbtOffset, handleSize); + std::memcpy(missSbt.data() + i * missStride, sbt.data() + sbtOffset, handleSize); + std::memcpy(missSbt.data() + i * missStride + handleSize, createInfo.missGroups[i].parameters.data(), + createInfo.missGroups[i].parameters.size()); sbtOffset += handleSizeAligned; - missData += handleSizeAligned; } - missBuffer->unmap(); + missBuffer->updateContents(0, missSbt.size(), missSbt.data()); + missBuffer->pipelineBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_SHADER_READ_BIT, + VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR); ORayTracingPipeline pipeline = - new RayTracingPipeline(graphics, pipelineHandle, std::move(rayGenBuffer), handleSizeAligned, std::move(hitBuffer), - handleSizeAligned, std::move(missBuffer), handleSizeAligned, nullptr, 0, createInfo.pipelineLayout); + new RayTracingPipeline(graphics, pipelineHandle, std::move(rayGenBuffer), rayGenStride, std::move(hitBuffer), + hitStride, std::move(missBuffer), missStride, nullptr, 0, createInfo.pipelineLayout); PRayTracingPipeline handle = pipeline; rayTracingPipelines[hash] = std::move(pipeline); return handle; diff --git a/src/Engine/Graphics/Vulkan/RayTracing.cpp b/src/Engine/Graphics/Vulkan/RayTracing.cpp index 99c5bf2..8b6fb50 100644 --- a/src/Engine/Graphics/Vulkan/RayTracing.cpp +++ b/src/Engine/Graphics/Vulkan/RayTracing.cpp @@ -56,7 +56,7 @@ TopLevelAS::TopLevelAS(PGraphics graphics, const Gfx::TopLevelASCreateInfo& crea }, .instanceCustomIndex = i, .mask = 0xff, - .instanceShaderBindingTableRecordOffset = 0, + .instanceShaderBindingTableRecordOffset = i, .flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR, .accelerationStructureReference = blas->getDeviceAddress(), }; diff --git a/src/Engine/Graphics/slang-compile.cpp b/src/Engine/Graphics/slang-compile.cpp index 5212802..2dbcba7 100644 --- a/src/Engine/Graphics/slang-compile.cpp +++ b/src/Engine/Graphics/slang-compile.cpp @@ -78,9 +78,9 @@ void Seele::beginCompilation(const ShaderCompilationInfo& info, SlangCompileTarg Map moduleMap; for (const auto& moduleName : info.modules) { slang::IModule* loaded = session->loadModule(moduleName.c_str(), diagnostics.writeRef()); + CHECK_DIAGNOSTICS(); components.add(loaded); moduleMap[moduleName] = loaded; - CHECK_DIAGNOSTICS(); } entryPoints.clear(); for (const auto& [name, mod] : info.entryPoints) { diff --git a/src/Engine/Material/Material.cpp b/src/Engine/Material/Material.cpp index 2f3a49f..bc90b05 100644 --- a/src/Engine/Material/Material.cpp +++ b/src/Engine/Material/Material.cpp @@ -40,21 +40,21 @@ void Material::init(Gfx::PGraphics graphics) { .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE, .descriptorCount = 2000, .bindingFlags = Gfx::SE_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT, - .shaderStages = Gfx::SE_SHADER_STAGE_FRAGMENT_BIT | Gfx::SE_SHADER_STAGE_CALLABLE_BIT_KHR, + .shaderStages = Gfx::SE_SHADER_STAGE_FRAGMENT_BIT | Gfx::SE_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, }); layout->addDescriptorBinding(Gfx::DescriptorBinding{ .binding = 1, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLER, .descriptorCount = 2000, .bindingFlags = Gfx::SE_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT, - .shaderStages = Gfx::SE_SHADER_STAGE_FRAGMENT_BIT | Gfx::SE_SHADER_STAGE_CALLABLE_BIT_KHR, + .shaderStages = Gfx::SE_SHADER_STAGE_FRAGMENT_BIT | Gfx::SE_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, }); layout->addDescriptorBinding(Gfx::DescriptorBinding{ .binding = 2, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER, .descriptorCount = 1, .bindingFlags = Gfx::SE_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT, - .shaderStages = Gfx::SE_SHADER_STAGE_FRAGMENT_BIT | Gfx::SE_SHADER_STAGE_CALLABLE_BIT_KHR, + .shaderStages = Gfx::SE_SHADER_STAGE_FRAGMENT_BIT | Gfx::SE_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, }); layout->create(); floatBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{ diff --git a/src/Engine/Window/GameView.cpp b/src/Engine/Window/GameView.cpp index 5a8a0a1..e40c96b 100644 --- a/src/Engine/Window/GameView.cpp +++ b/src/Engine/Window/GameView.cpp @@ -23,12 +23,12 @@ using namespace Seele; GameView::GameView(Gfx::PGraphics graphics, PWindow window, const ViewportCreateInfo& createInfo, std::string dllPath) : View(graphics, window, createInfo, "Game"), scene(new Scene(graphics)), gameInterface(dllPath) { reloadGame(); - //renderGraph.addPass(new CachedDepthPass(graphics, scene)); - //renderGraph.addPass(new DepthCullingPass(graphics, scene)); - //renderGraph.addPass(new VisibilityPass(graphics, scene)); - //renderGraph.addPass(new LightCullingPass(graphics, scene)); - //renderGraph.addPass(new BasePass(graphics, scene)); - renderGraph.addPass(new RayTracingPass(graphics, scene)); + renderGraph.addPass(new CachedDepthPass(graphics, scene)); + renderGraph.addPass(new DepthCullingPass(graphics, scene)); + renderGraph.addPass(new VisibilityPass(graphics, scene)); + renderGraph.addPass(new LightCullingPass(graphics, scene)); + renderGraph.addPass(new BasePass(graphics, scene)); + //renderGraph.addPass(new RayTracingPass(graphics, scene)); renderGraph.setViewport(viewport); renderGraph.createRenderPass(); }