diff --git a/res/shaders/raytracing/Callable.slang b/res/shaders/raytracing/Callable.slang new file mode 100644 index 0000000..2420f86 --- /dev/null +++ b/res/shaders/raytracing/Callable.slang @@ -0,0 +1,28 @@ +import Common; +import RayTracingData; +import MaterialParameter; +import LightEnv; +import MATERIAL_FILE_NAME; + +[shader("callable")] +void callable(inout CallablePayload payload) +{ + LightingParameter lightingParams = payload.params.getLightingParameter(); + MaterialParameter materialParams = payload.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)); + payload.color = float3(0, 0, 1); +} \ No newline at end of file diff --git a/res/shaders/raytracing/ClosestHit.slang b/res/shaders/raytracing/ClosestHit.slang index 272860b..4ae6b8b 100644 --- a/res/shaders/raytracing/ClosestHit.slang +++ b/res/shaders/raytracing/ClosestHit.slang @@ -4,12 +4,11 @@ import MaterialParameter; import LightEnv; import Scene; import RayTracingData; -import MATERIAL_FILE_NAME; // simplification: all BLAS only have 1 geometry [shader("closesthit")] -void closesthit(inout float3 hitValue, in BuiltInTriangleIntersectionAttributes attr) +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); @@ -35,23 +34,10 @@ void closesthit(inout float3 hitValue, in BuiltInTriangleIntersectionAttributes 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)); + CallablePayload callable; + callable.params = params; - hitValue = result; + CallShader(0, callable); + + hitValue.color = float3(0, 1, 1) + callable.color; } \ No newline at end of file diff --git a/res/shaders/raytracing/Miss.slang b/res/shaders/raytracing/Miss.slang index e20ece8..97f6600 100644 --- a/res/shaders/raytracing/Miss.slang +++ b/res/shaders/raytracing/Miss.slang @@ -1,7 +1,7 @@ import RayTracingData; [shader("miss")] -void main(inout float3 p) +void miss(inout RayPayload p) { - p = float3(1, 0, 1); + p.color = float3(0, 1, 0); } \ No newline at end of file diff --git a/res/shaders/raytracing/RayGen.slang b/res/shaders/raytracing/RayGen.slang index 9fd9b5c..85ff154 100644 --- a/res/shaders/raytracing/RayGen.slang +++ b/res/shaders/raytracing/RayGen.slang @@ -2,33 +2,33 @@ import Common; import RayTracingData; [shader("raygeneration")] -void main() +void raygen() { const float2 pixelCenter = float2(DispatchRaysIndex().xy) + float2(0.5); const float2 inUV = pixelCenter / float2(DispatchRaysDimensions().xy); float2 d = inUV * 2.0 - 1.0; float4 origin = mul(pViewParams.inverseViewMatrix, float4(0, 0, 0, 1)); - float4 target = mul(pViewParams.inverseProjection, float4(d.x, d.y, 1, 1)); - float4 direction = mul(pViewParams.inverseViewMatrix, float4(normalize(target.xyz), 0)); + float4 target = mul(pViewParams.inverseProjection, float4(d.x, d.y, 1, 1)); + float4 direction = mul(pViewParams.inverseViewMatrix, float4(target.xyz, 0)); float tmin = 0.0001; float tmax = 10000.0; uint max_rays = 24; - float4 color = float4(0, 0, 0, 0); - float expectedDistance = -1; - float3 payload; + RayPayload payload; - RayDesc desc = { - origin.xyz, - tmin, - direction.xyz, - tmax, - }; + RayDesc desc; + desc.Origin = origin.xyz; + desc.Direction = direction.xyz; + desc.TMin = tmin; + desc.TMax = tmax; - TraceRay(pRayTracingParams.scene, RAY_FLAG_FORCE_OPAQUE, 0xff, 0, 0, 0, desc, payload); + pRayTracingParams.origins[DispatchRaysIndex().x + DispatchRaysDimensions().x * DispatchRaysIndex().y] = origin.xyz; + pRayTracingParams.rayDirections[DispatchRaysIndex().x + DispatchRaysDimensions().x * DispatchRaysIndex().y] = direction.xyz; - pRayTracingParams.image[DispatchRaysIndex().xy] = float4(payload, 1.0f); + TraceRay(pRayTracingParams.scene, 0, 0xff, 0, 1, 0, desc, payload); + + pRayTracingParams.image[DispatchRaysIndex().xy] = float4(payload.color, 1.0f); } diff --git a/res/shaders/raytracing/RayTracingData.slang b/res/shaders/raytracing/RayTracingData.slang index 8ab202b..5bd865e 100644 --- a/res/shaders/raytracing/RayTracingData.slang +++ b/res/shaders/raytracing/RayTracingData.slang @@ -1,7 +1,23 @@ +import MaterialParameter; + struct RayTracingParams { RaytracingAccelerationStructure scene; RWTexture2D image; StructuredBuffer indexBuffer; + RWStructuredBuffer rayDirections; + RWStructuredBuffer origins; }; +layout(set=5) ParameterBlock pRayTracingParams; + +struct CallablePayload +{ + FragmentParameter params; + float3 color; +}; + +struct RayPayload +{ + float3 color; +}; \ No newline at end of file diff --git a/src/Editor/Asset/MeshLoader.cpp b/src/Editor/Asset/MeshLoader.cpp index 4d38320..c560ddb 100644 --- a/src/Editor/Asset/MeshLoader.cpp +++ b/src/Editor/Asset/MeshLoader.cpp @@ -46,6 +46,7 @@ void MeshLoader::convertAssimpARGB(unsigned char* dst, aiTexel* src, uint32 numP } void MeshLoader::loadTextures(const aiScene* scene, const std::filesystem::path& meshDirectory, const std::string& importPath, Array& textures) { + std::cout << "Loading Textures" << std::endl; for (uint32 i = 0; i < scene->mNumTextures; ++i) { aiTexture* tex = scene->mTextures[i]; auto texPath = std::filesystem::path(tex->mFilename.C_Str()); @@ -75,6 +76,7 @@ void MeshLoader::loadTextures(const aiScene* scene, const std::filesystem::path& .importPath = importPath, }); textures.add(AssetRegistry::findTexture(importPath, texPath.stem().string())); + std::cout << "Loaded " << i << "/" << scene->mNumTextures << std::endl; } } diff --git a/src/Editor/Asset/TextureLoader.cpp b/src/Editor/Asset/TextureLoader.cpp index b7e7c2c..2a0d241 100644 --- a/src/Editor/Asset/TextureLoader.cpp +++ b/src/Editor/Asset/TextureLoader.cpp @@ -125,12 +125,12 @@ void TextureLoader::import(TextureImportArgs args, PTextureAsset textureAsset) { .structSize = sizeof(ktxBasisParams), .uastc = true, .threadCount = std::thread::hardware_concurrency() - 2, - .uastcFlags = KTX_PACK_UASTC_LEVEL_FASTER, + .uastcFlags = KTX_PACK_UASTC_LEVEL_DEFAULT, .uastcRDO = true, }; KTX_ASSERT(ktxTexture2_CompressBasisEx(kTexture, &basisParams)); - KTX_ASSERT(ktxTexture2_DeflateZstd(kTexture, 10)); + KTX_ASSERT(ktxTexture2_DeflateZstd(kTexture, 15)); char writer[100]; snprintf(writer, sizeof(writer), "%s version %s", "SeeleEngine", "0.0.1"); diff --git a/src/Engine/Containers/Map.h b/src/Engine/Containers/Map.h index 77583a6..6a17412 100644 --- a/src/Engine/Containers/Map.h +++ b/src/Engine/Containers/Map.h @@ -34,6 +34,7 @@ struct Map : public Tree, _KeyFun>, Compare, Allocat constexpr explicit Map(const Compare& comp, const Allocator& alloc = Allocator()) noexcept(noexcept(Allocator())) : Super(comp, alloc) {} constexpr explicit Map(const Allocator& alloc) noexcept(noexcept(Compare())) : Super(alloc) {} + constexpr Map(std::initializer_list> init) : Super(init) {} constexpr mapped_type& operator[](const key_type& key) { auto [it, inserted] = Super::insert(Pair(key, V())); return it->value; diff --git a/src/Engine/Containers/Tree.h b/src/Engine/Containers/Tree.h index b9e8a1c..27d4111 100644 --- a/src/Engine/Containers/Tree.h +++ b/src/Engine/Containers/Tree.h @@ -110,6 +110,12 @@ template init) + : alloc(NodeAlloc()), root(nullptr), beginIt(nullptr), endIt(nullptr), iteratorsDirty(true), _size(0), comp(Compare()) { + for (const auto& it : init) { + insert(it); + } + } constexpr Tree(const Tree& other) : alloc(other.alloc), root(nullptr), iteratorsDirty(true), _size(), comp(other.comp) { for (const auto& elem : other) { insert(elem); diff --git a/src/Engine/Graphics/Buffer.h b/src/Engine/Graphics/Buffer.h index 7d4d340..7785788 100644 --- a/src/Engine/Graphics/Buffer.h +++ b/src/Engine/Graphics/Buffer.h @@ -76,6 +76,7 @@ class ShaderBuffer : public Buffer { public: ShaderBuffer(QueueFamilyMapping mapping, const ShaderBufferCreateInfo& createInfo); virtual ~ShaderBuffer(); + virtual void readContents(Array& data) = 0; virtual void rotateBuffer(uint64 size, bool preserveContents = false) = 0; virtual void updateContents(const ShaderBufferCreateInfo& sourceData) = 0; constexpr uint32 getNumElements() const { return numElements; } diff --git a/src/Engine/Graphics/Graphics.h b/src/Engine/Graphics/Graphics.h index 5573113..8833f43 100644 --- a/src/Engine/Graphics/Graphics.h +++ b/src/Engine/Graphics/Graphics.h @@ -103,6 +103,7 @@ class Graphics { // Ray Tracing virtual OBottomLevelAS createBottomLevelAccelerationStructure(const BottomLevelASCreateInfo& createInfo) = 0; virtual OTopLevelAS createTopLevelAccelerationStructure(const TopLevelASCreateInfo& createInfo) = 0; + virtual void buildBottomLevelAccelerationStructures(Array data) = 0; virtual ORayGenShader createRayGenShader(const ShaderCreateInfo& createInfo) = 0; virtual OAnyHitShader createAnyHitShader(const ShaderCreateInfo& createInfo) = 0; diff --git a/src/Engine/Graphics/Initializer.h b/src/Engine/Graphics/Initializer.h index d826df5..4cffa8e 100644 --- a/src/Engine/Graphics/Initializer.h +++ b/src/Engine/Graphics/Initializer.h @@ -235,18 +235,30 @@ struct ComputePipelineCreateInfo { Gfx::PComputeShader computeShader = nullptr; Gfx::PPipelineLayout pipelineLayout = nullptr; }; +struct RayTracingRayGenGroup { + PRayGenShader shader; + Array parameters; +}; struct RayTracingHitGroup { PClosestHitShader closestHitShader; PAnyHitShader anyHitShader; PIntersectionShader intersectionShader; Array parameters; }; +struct RayTracingMissGroup { + PMissShader shader; + Array parameters; +}; +struct RayTracingCallableGroup { + PCallableShader shader; + Array parameters; +}; struct RayTracingPipelineCreateInfo { PPipelineLayout pipelineLayout = nullptr; - PRayGenShader rayGenShader = nullptr; - Array hitgroups; - Array missShaders; - Array callableShaders; + RayTracingRayGenGroup rayGenGroup; + Array hitGroups; + Array missGroups; + Array callableGroups; }; struct BottomLevelASCreateInfo { PMesh mesh; diff --git a/src/Engine/Graphics/Mesh.cpp b/src/Engine/Graphics/Mesh.cpp index f5a61a0..d40aecb 100644 --- a/src/Engine/Graphics/Mesh.cpp +++ b/src/Engine/Graphics/Mesh.cpp @@ -38,4 +38,5 @@ void Mesh::load(ArchiveBuffer& buffer) { blas = buffer.getGraphics()->createBottomLevelAccelerationStructure(Gfx::BottomLevelASCreateInfo{ .mesh = this, }); + vertexData->registerBottomLevelAccelerationStructure(blas); } diff --git a/src/Engine/Graphics/RenderPass/RayTracingPass.cpp b/src/Engine/Graphics/RenderPass/RayTracingPass.cpp index 143e231..64f2e59 100644 --- a/src/Engine/Graphics/RenderPass/RayTracingPass.cpp +++ b/src/Engine/Graphics/RenderPass/RayTracingPass.cpp @@ -20,15 +20,27 @@ RayTracingPass::RayTracingPass(Gfx::PGraphics graphics, PScene scene) : RenderPa .binding = 2, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER, }); + paramsLayout->addDescriptorBinding(Gfx::DescriptorBinding{ + .binding = 3, + .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER, + .access = Gfx::SE_DESCRIPTOR_ACCESS_READ_WRITE_BIT, + }); + paramsLayout->addDescriptorBinding(Gfx::DescriptorBinding{ + .binding = 4, + .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER, + .access = Gfx::SE_DESCRIPTOR_ACCESS_READ_WRITE_BIT, + }); paramsLayout->create(); pipelineLayout = graphics->createPipelineLayout("RayTracing"); pipelineLayout->addDescriptorLayout(viewParamsLayout); pipelineLayout->addDescriptorLayout(Material::getDescriptorLayout()); pipelineLayout->addDescriptorLayout(paramsLayout); pipelineLayout->addDescriptorLayout(scene->getLightEnvironment()->getDescriptorLayout()); + pipelineLayout->addDescriptorLayout(StaticMeshVertexData::getInstance()->getVertexDataLayout()); + pipelineLayout->addDescriptorLayout(StaticMeshVertexData::getInstance()->getInstanceDataLayout()); graphics->getShaderCompiler()->registerRenderPass("RayTracing", Gfx::PassConfig{ .baseLayout = pipelineLayout, - .mainFile = "ClosestHit", + .mainFile = "Callable", .useMaterial = true, .rayTracing = true, }); @@ -38,7 +50,7 @@ void RayTracingPass::beginFrame(const Component::Camera& cam) { RenderPass::begi void RayTracingPass::render() { Gfx::ORenderCommand command = graphics->createRenderCommand("RayTracing"); - Array hitgroups; + Array callableGroups; Array accelerationStructures; Array instanceData; @@ -59,14 +71,12 @@ void RayTracingPass::render() { for (auto& inst : matData.instances) { for (uint32 i = 0; i < inst.instanceData.size(); ++i) { - Gfx::RayTracingHitGroup hitgroup = { - .closestHitShader = collection->closestHitShader, - .anyHitShader = nullptr, - .intersectionShader = nullptr, + Gfx::RayTracingCallableGroup callableGroup = { + .shader = collection->callableShader, }; - hitgroup.parameters.resize(sizeof(VertexData::DrawCallOffsets)); - std::memcpy(hitgroup.parameters.data(), &inst.offsets, sizeof(VertexData::DrawCallOffsets)); - hitgroups.add(hitgroup); + callableGroup.parameters.resize(sizeof(VertexData::DrawCallOffsets)); + std::memcpy(callableGroup.parameters.data(), &inst.offsets, sizeof(VertexData::DrawCallOffsets)); + callableGroups.add(callableGroup); instanceData.add(inst.instanceData[i]); accelerationStructures.add(inst.rayTracingData[i]); @@ -82,44 +92,74 @@ void RayTracingPass::render() { desc->updateAccelerationStructure(0, tlas); desc->updateTexture(1, Gfx::PTexture2D(texture)); desc->updateBuffer(2, StaticMeshVertexData::getInstance()->getIndexBuffer()); + desc->updateBuffer(3, directionBuffer); + desc->updateBuffer(4, originBuffer); desc->writeChanges(); Gfx::PRayTracingPipeline pipeline = graphics->createRayTracingPipeline(Gfx::RayTracingPipelineCreateInfo{ .pipelineLayout = pipelineLayout, - .rayGenShader = raygen, - .hitgroups = hitgroups, - .missShaders = {miss}, + .rayGenGroup = {.shader = rayGen}, + .hitGroups = {{.closestHitShader = closestHit}}, + .missGroups = {{.shader = miss}}, + .callableGroups = callableGroups, }); command->bindPipeline(pipeline); + StaticMeshVertexData::getInstance()->getInstanceDataSet()->writeChanges(); + StaticMeshVertexData::getInstance()->getVertexDataSet()->writeChanges(); command->bindDescriptor({viewParamsSet, StaticMeshVertexData::getInstance()->getInstanceDataSet(), StaticMeshVertexData::getInstance()->getVertexDataSet(), Material::getDescriptorSet(), - scene->getLightEnvironment()->getDescriptorSet()}); + scene->getLightEnvironment()->getDescriptorSet(), desc}); command->traceRays(texture->getWidth(), texture->getHeight(), 1); Array commands; commands.add(std::move(command)); graphics->executeCommands(std::move(commands)); + viewport->getOwner()->getBackBuffer()->changeLayout(Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, Gfx::SE_ACCESS_NONE, + Gfx::SE_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, + Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT); + graphics->copyTexture(Gfx::PTexture2D(texture), viewport->getOwner()->getBackBuffer()); } void RayTracingPass::endFrame() {} void RayTracingPass::publishOutputs() { - ShaderCompilationInfo createInfo{ - .name = "RayGen", - .modules = {"RayGen", "Miss"}, - .entryPoints = {{"main", "RayGen"}, {"main", "Miss"}}, - .rootSignature = pipelineLayout, - }; - graphics->beginShaderCompilation(createInfo); - raygen = graphics->createRayGenShader({0}); - miss = graphics->createMissShader({1}); - texture = graphics->createTexture2D(TextureCreateInfo{ .format = Gfx::SE_FORMAT_R32G32B32A32_SFLOAT, .width = viewport->getOwner()->getFramebufferWidth(), .height = viewport->getOwner()->getFramebufferHeight(), .usage = Gfx::SE_IMAGE_USAGE_STORAGE_BIT, }); + texture->changeLayout(Gfx::SE_IMAGE_LAYOUT_GENERAL, Gfx::SE_ACCESS_NONE, Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT); + ShaderCompilationInfo compileInfo = { + .name = "RT", + .modules = {"RayGen", "ClosestHit", "Miss", "StaticMeshVertexData"}, + .entryPoints = {{"raygen", "RayGen"}, {"closestHit", "ClosestHit"}, {"miss", "Miss"}}, + .typeParameter = {{"IVertexData", "StaticMeshVertexData"}}, + .defines = {{"RAY_TRACING", "1"}}, + .rootSignature = pipelineLayout, + }; + graphics->beginShaderCompilation(compileInfo); + rayGen = graphics->createRayGenShader({0}); + closestHit = graphics->createClosestHitShader({1}); + miss = graphics->createMissShader({2}); + pipelineLayout->create(); + directionBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{ + .sourceData = + { + .size = sizeof(Vector) * texture->getWidth() * texture->getHeight(), + }, + .dynamic = true, + .name = "DirectionBuffer", + }); + originBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{ + .sourceData = + { + .size = sizeof(Vector) * texture->getWidth() * texture->getHeight(), + }, + .dynamic = true, + .name = "OriginBuffer", + }); } void RayTracingPass::createRenderPass() {} diff --git a/src/Engine/Graphics/RenderPass/RayTracingPass.h b/src/Engine/Graphics/RenderPass/RayTracingPass.h index d264966..b6caa45 100644 --- a/src/Engine/Graphics/RenderPass/RayTracingPass.h +++ b/src/Engine/Graphics/RenderPass/RayTracingPass.h @@ -15,11 +15,13 @@ class RayTracingPass : public RenderPass { virtual void createRenderPass() override; private: - Gfx::PRayGenShader raygen; - Gfx::PMissShader miss; Gfx::ODescriptorLayout paramsLayout; Gfx::OPipelineLayout pipelineLayout; Gfx::OTexture2D texture; - + Gfx::ORayGenShader rayGen; + Gfx::OClosestHitShader closestHit; + Gfx::OMissShader miss; + Gfx::OShaderBuffer directionBuffer; + Gfx::OShaderBuffer originBuffer; }; } // namespace Seele \ No newline at end of file diff --git a/src/Engine/Graphics/Shader.cpp b/src/Engine/Graphics/Shader.cpp index 83e83b4..adc7e90 100644 --- a/src/Engine/Graphics/Shader.cpp +++ b/src/Engine/Graphics/Shader.cpp @@ -51,13 +51,13 @@ ShaderPermutation ShaderCompiler::getTemplate(std::string name) { } void ShaderCompiler::compile() { - //List> work; + List> work; for (const auto& [name, pass] : passes) { for (const auto& [vdName, vd] : vertexData) { if (pass.useMaterial) { for (const auto& [matName, mat] : materials) { for (int y = 0; y < 2; y++) { - //work.add([=]() { + work.add([=]() { ShaderPermutation permutation = getTemplate(name); permutation.setPositionOnly(false); permutation.setDepthCulling(y); @@ -67,13 +67,13 @@ void ShaderCompiler::compile() { layout->addDescriptorLayout(vd->getInstanceDataLayout()); permutation.setMaterial(mat->getName()); createShaders(permutation, std::move(layout)); - //}); + }); } } } else { for (int x = 0; x < 2; x++) { for (int y = 0; y < 2; y++) { - //work.add([=]() { + work.add([=]() { ShaderPermutation permutation = getTemplate(name); permutation.setPositionOnly(x); permutation.setDepthCulling(y); @@ -82,13 +82,13 @@ void ShaderCompiler::compile() { layout->addDescriptorLayout(vd->getVertexDataLayout()); layout->addDescriptorLayout(vd->getInstanceDataLayout()); createShaders(permutation, std::move(layout)); - //}); + }); } } } } } - //getThreadPool().runAndWait(std::move(work)); + getThreadPool().runAndWait(std::move(work)); } void ShaderCompiler::createShaders(ShaderPermutation permutation, Gfx::OPipelineLayout layout) { @@ -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.add({"closesthit", permutation.vertexMeshFile}); + createInfo.entryPoints = {{"callable", "Callable"}}; 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.closestHitShader = graphics->createClosestHitShader({shaderIndex++}); + collection.callableShader = graphics->createCallableShader({shaderIndex++}); } else { collection.vertexShader = graphics->createVertexShader({shaderIndex++}); } diff --git a/src/Engine/Graphics/Shader.h b/src/Engine/Graphics/Shader.h index 7c455e9..5f38319 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; - OClosestHitShader closestHitShader; + OCallableShader callableShader; }; struct PassConfig { diff --git a/src/Engine/Graphics/VertexData.cpp b/src/Engine/Graphics/VertexData.cpp index 07cd197..1d35779 100644 --- a/src/Engine/Graphics/VertexData.cpp +++ b/src/Engine/Graphics/VertexData.cpp @@ -293,6 +293,7 @@ void VertexData::commitMeshes() { .dynamic = false, .name = "PrimitiveIndicesBuffer", }); + graphics->buildBottomLevelAccelerationStructures(std::move(dataToBuild)); } MeshId VertexData::allocateVertexData(uint64 numVertices) { @@ -309,10 +310,6 @@ MeshId VertexData::allocateVertexData(uint64 numVertices) { return res; } -uint64 VertexData::getMeshOffset(MeshId id) { return meshOffsets[id]; } - -uint64 VertexData::getMeshVertexCount(MeshId id) { return meshVertexCounts[id]; } - List vertexDataList; List VertexData::getList() { return vertexDataList; } diff --git a/src/Engine/Graphics/VertexData.h b/src/Engine/Graphics/VertexData.h index fcf5526..b9d60a7 100644 --- a/src/Engine/Graphics/VertexData.h +++ b/src/Engine/Graphics/VertexData.h @@ -56,8 +56,8 @@ class VertexData { void loadMesh(MeshId id, Array indices, Array meshlets); void commitMeshes(); MeshId allocateVertexData(uint64 numVertices); - uint64 getMeshOffset(MeshId id); - uint64 getMeshVertexCount(MeshId id); + uint64 getMeshOffset(MeshId id) const { return meshOffsets[id]; } + uint64 getMeshVertexCount(MeshId id) { return meshVertexCounts[id]; } virtual void serializeMesh(MeshId id, uint64 numVertices, ArchiveBuffer& buffer) = 0; virtual void deserializeMesh(MeshId id, ArchiveBuffer& buffer) = 0; virtual void bindBuffers(Gfx::PRenderCommand command) = 0; @@ -72,7 +72,8 @@ class VertexData { const Array& getMaterialData() const { return materialData; } const Array& getTransparentData() const { return transparentData; } const Array& getRayTracingData() const { return rayTracingScene; } - const MeshData& getMeshData(MeshId id) { return meshData[id]; } + const MeshData& getMeshData(MeshId id) const { return meshData[id]; } + void registerBottomLevelAccelerationStructure(Gfx::PBottomLevelAS blas) { dataToBuild.add(blas); } uint64 getIndicesOffset(uint32 meshletIndex) { return meshlets[meshletIndex].indicesOffset; } uint64 getNumInstances() const { return instanceData.size(); } static List getList(); @@ -138,6 +139,7 @@ class VertexData { Gfx::OShaderBuffer cullingOffsetBuffer; // for legacy pipeline Gfx::OIndexBuffer indexBuffer; + Array dataToBuild; // Material data Array instanceData; Gfx::OShaderBuffer instanceBuffer; diff --git a/src/Engine/Graphics/Vulkan/Buffer.cpp b/src/Engine/Graphics/Vulkan/Buffer.cpp index 54ca8ec..a249fe0 100644 --- a/src/Engine/Graphics/Vulkan/Buffer.cpp +++ b/src/Engine/Graphics/Vulkan/Buffer.cpp @@ -237,8 +237,7 @@ void Buffer::createBuffer(uint64 size, uint32 destIndex) { .usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE, }; buffers[destIndex] = new BufferAllocation(graphics, name, info, allocInfo, initialOwner); - if (createCleared) - { + if (createCleared) { PCommand command = graphics->getQueueCommands(initialOwner)->getCommands(); vkCmdFillBuffer(command->getHandle(), buffers[destIndex]->buffer, 0, VK_WHOLE_SIZE, clearValue); pipelineBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, @@ -351,6 +350,11 @@ ShaderBuffer::ShaderBuffer(PGraphics graphics, const ShaderBufferCreateInfo& cre ShaderBuffer::~ShaderBuffer() {} +void ShaderBuffer::readContents(Array& data) { + data.resize(getSize()); + getAlloc()->readContents(0, data.size(), data.data()); +} + void ShaderBuffer::updateContents(const ShaderBufferCreateInfo& createInfo) { if (createInfo.sourceData.data == nullptr) { return; @@ -407,7 +411,7 @@ IndexBuffer::IndexBuffer(PGraphics graphics, const IndexBufferCreateInfo& create : Gfx::IndexBuffer(graphics->getFamilyMapping(), createInfo), Vulkan::Buffer(graphics, createInfo.sourceData.size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | - VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, + VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, createInfo.sourceData.owner, false, createInfo.name) { getAlloc()->updateContents(createInfo.sourceData.offset, createInfo.sourceData.size, createInfo.sourceData.data); } diff --git a/src/Engine/Graphics/Vulkan/Buffer.h b/src/Engine/Graphics/Vulkan/Buffer.h index de5f187..363fca0 100644 --- a/src/Engine/Graphics/Vulkan/Buffer.h +++ b/src/Engine/Graphics/Vulkan/Buffer.h @@ -109,6 +109,7 @@ class ShaderBuffer : public Gfx::ShaderBuffer, public Buffer { public: ShaderBuffer(PGraphics graphics, const ShaderBufferCreateInfo& sourceData); virtual ~ShaderBuffer(); + virtual void readContents(Array& data) override; virtual void updateContents(const ShaderBufferCreateInfo& createInfo) override; virtual void rotateBuffer(uint64 size, bool preserveContents = false) override; diff --git a/src/Engine/Graphics/Vulkan/Command.cpp b/src/Engine/Graphics/Vulkan/Command.cpp index 90c123a..622a7de 100644 --- a/src/Engine/Graphics/Vulkan/Command.cpp +++ b/src/Engine/Graphics/Vulkan/Command.cpp @@ -74,7 +74,6 @@ void Command::endRenderPass() { } void Command::executeCommands(Array commands) { - assert(state == State::RenderPass); if (commands.size() == 0) { // std::cout << "No commands provided" << std::endl; return; @@ -253,8 +252,9 @@ void RenderCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet, ArraygetHandle(); Gfx::PPipelineLayout layout = pipeline != nullptr ? pipeline->getPipelineLayout() : rtPipeline->getPipelineLayout(); - vkCmdBindDescriptorSets(handle, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->getLayout(), layout->findParameter(descriptorSet->getName()), - 1, &setHandle, dynamicOffsets.size(), dynamicOffsets.data()); + vkCmdBindDescriptorSets(handle, pipeline != nullptr ? VK_PIPELINE_BIND_POINT_GRAPHICS : VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, + pipeline->getLayout(), layout->findParameter(descriptorSet->getName()), 1, &setHandle, dynamicOffsets.size(), + dynamicOffsets.data()); } void RenderCommand::bindDescriptor(const Array& descriptorSets, Array dynamicOffsets) { @@ -279,7 +279,8 @@ void RenderCommand::bindDescriptor(const Array& descriptorS } sets[layout->findParameter(descriptorSet->getName())] = descriptorSet->getHandle(); } - vkCmdBindDescriptorSets(handle, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->getLayout(), 0, (uint32)descriptorSets.size(), sets, + vkCmdBindDescriptorSets(handle, pipeline != nullptr ? VK_PIPELINE_BIND_POINT_GRAPHICS : VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, + pipeline != nullptr ? pipeline->getLayout() : rtPipeline->getLayout(), 0, (uint32)descriptorSets.size(), sets, dynamicOffsets.size(), dynamicOffsets.data()); delete[] sets; } @@ -334,7 +335,8 @@ void RenderCommand::traceRays(uint32 width, uint32 height, uint32 depth) { VkStridedDeviceAddressRegionKHR rayGenRef = rtPipeline->getRayGenRegion(); VkStridedDeviceAddressRegionKHR hitRef = rtPipeline->getHitRegion(); VkStridedDeviceAddressRegionKHR missRef = rtPipeline->getMissRegion(); - vkCmdTraceRaysKHR(handle, &rayGenRef, &missRef, &hitRef, nullptr, width, height, depth); + VkStridedDeviceAddressRegionKHR callableRef = rtPipeline->getCallableRegion(); + vkCmdTraceRaysKHR(handle, &rayGenRef, &missRef, &hitRef, &callableRef, width, height, depth); } ComputeCommand::ComputeCommand(PGraphics graphics, VkCommandPool cmdPool) : graphics(graphics), owner(cmdPool) { diff --git a/src/Engine/Graphics/Vulkan/Descriptor.cpp b/src/Engine/Graphics/Vulkan/Descriptor.cpp index 8626ba1..771bf6b 100644 --- a/src/Engine/Graphics/Vulkan/Descriptor.cpp +++ b/src/Engine/Graphics/Vulkan/Descriptor.cpp @@ -453,12 +453,11 @@ void DescriptorSet::updateSamplerArray(uint32_t binding, Array sa void DescriptorSet::updateAccelerationStructure(uint32 binding, Gfx::PTopLevelAS as) { auto tlas = as.cast(); - auto handle = tlas->getHandle(); accelerationInfos.add(VkWriteDescriptorSetAccelerationStructureKHR{ .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR, .pNext = nullptr, .accelerationStructureCount = 1, - .pAccelerationStructures = &handle, + .pAccelerationStructures = &tlas->handle, }); writeDescriptors.add(VkWriteDescriptorSet{ .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, diff --git a/src/Engine/Graphics/Vulkan/Graphics.cpp b/src/Engine/Graphics/Vulkan/Graphics.cpp index 2f9b71e..366a721 100644 --- a/src/Engine/Graphics/Vulkan/Graphics.cpp +++ b/src/Engine/Graphics/Vulkan/Graphics.cpp @@ -8,6 +8,8 @@ #include "Graphics/Enums.h" #include "Graphics/Graphics.h" #include "Graphics/Initializer.h" +#include "Graphics/StaticMeshVertexData.h" +#include "Graphics/slang-compile.h" #include "PipelineCache.h" #include "Query.h" #include "RayTracing.h" @@ -15,7 +17,6 @@ #include "Shader.h" #include "Window.h" #include -#include "Graphics/slang-compile.h" #include #include @@ -91,7 +92,6 @@ void vkCmdTraceRaysKHR(VkCommandBuffer commandBuffer, const VkStridedDeviceAddre width, height, depth); } - Graphics::Graphics() : instance(VK_NULL_HANDLE), handle(VK_NULL_HANDLE), physicalDevice(VK_NULL_HANDLE), callback(VK_NULL_HANDLE) {} Graphics::~Graphics() { @@ -189,7 +189,9 @@ Gfx::ORenderCommand Graphics::createRenderCommand(const std::string& name) { ret Gfx::OComputeCommand Graphics::createComputeCommand(const std::string& name) { return getComputeCommands()->createComputeCommand(name); } -void Graphics::beginShaderCompilation(const ShaderCompilationInfo& createInfo) { beginCompilation(createInfo, SLANG_SPIRV, createInfo.rootSignature); } +void Graphics::beginShaderCompilation(const ShaderCompilationInfo& createInfo) { + beginCompilation(createInfo, SLANG_SPIRV, createInfo.rootSignature); +} Gfx::OVertexShader Graphics::createVertexShader(const ShaderCreateInfo& createInfo) { OVertexShader shader = new VertexShader(this); @@ -319,6 +321,13 @@ void Graphics::resolveTexture(Gfx::PTexture source, Gfx::PTexture destination) { void Graphics::copyTexture(Gfx::PTexture source, Gfx::PTexture destination) { PTextureBase src = source.cast(); PTextureBase dst = destination.cast(); + Gfx::SeImageLayout srcLayout = src->getLayout(); + Gfx::SeImageLayout dstLayout = dst->getLayout(); + src->changeLayout(Gfx::SE_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, Gfx::SE_ACCESS_MEMORY_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + Gfx::SE_ACCESS_TRANSFER_READ_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT); + dst->changeLayout(Gfx::SE_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, Gfx::SE_ACCESS_MEMORY_WRITE_BIT | Gfx::SE_ACCESS_MEMORY_READ_BIT, + Gfx::SE_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT); + VkImageBlit blit = { .srcSubresource = { @@ -349,6 +358,12 @@ void Graphics::copyTexture(Gfx::PTexture source, Gfx::PTexture destination) { vkCmdBlitImage(command->getHandle(), src->getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dst->getImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit, src->getAspect() & VK_IMAGE_ASPECT_DEPTH_BIT ? VK_FILTER_NEAREST : VK_FILTER_LINEAR); + + src->changeLayout(srcLayout, Gfx::SE_ACCESS_TRANSFER_READ_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT, + Gfx::SE_ACCESS_MEMORY_READ_BIT | Gfx::SE_ACCESS_MEMORY_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + + dst->changeLayout(dstLayout, Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT, + Gfx::SE_ACCESS_MEMORY_READ_BIT | Gfx::SE_ACCESS_MEMORY_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT); } Gfx::OBottomLevelAS Graphics::createBottomLevelAccelerationStructure(const Gfx::BottomLevelASCreateInfo& createInfo) { @@ -359,6 +374,148 @@ Gfx::OTopLevelAS Graphics::createTopLevelAccelerationStructure(const Gfx::TopLev return new TopLevelAS(this, createInfo); } +void Graphics::buildBottomLevelAccelerationStructures(Array data) { + Gfx::PShaderBuffer positionBuffer = StaticMeshVertexData::getInstance()->getPositionBuffer(); + Gfx::PIndexBuffer indexBuffer = StaticMeshVertexData::getInstance()->getIndexBuffer(); + + VkBufferCreateInfo transformBufferInfo = { + .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .size = sizeof(VkTransformMatrixKHR) * data.size(), + .usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | + VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_TRANSFER_DST_BIT, + }; + VmaAllocationCreateInfo transformAllocInfo = { + .flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, + .usage = VMA_MEMORY_USAGE_AUTO, + }; + + Array matrices; + for (const auto gfxBlas : data) { + const auto blas = gfxBlas.cast(); + matrices.add(blas->getTransform()); + } + OBufferAllocation transformBuffer = + new BufferAllocation(this, "TransformBuffer", transformBufferInfo, transformAllocInfo, Gfx::QueueType::GRAPHICS); + transformBuffer->updateContents(0, sizeof(VkTransformMatrixKHR) * matrices.size(), matrices.data()); + + Array geometries(data.size()); + Array buildGeometries(data.size()); + Array buildSizes(data.size()); + Array scratchBuffers(data.size()); + Array buildRanges(data.size()); + Array buildRangePointers(data.size()); + for (uint32 i = 0; i < data.size(); ++i) { + auto blas = data[i].cast(); + VkDeviceOrHostAddressConstKHR vertexDataAddress = { + .deviceAddress = positionBuffer.cast()->getDeviceAddress() + blas->getVertexOffset(), + }; + VkDeviceOrHostAddressConstKHR indexDataAddress = { + .deviceAddress = indexBuffer.cast()->getDeviceAddress() + blas->getIndexOffset(), + }; + VkDeviceOrHostAddressConstKHR transformDataAddress = { + .deviceAddress = transformBuffer->deviceAddress + i * sizeof(VkTransformMatrixKHR), + }; + geometries[i] = { + .sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR, + .pNext = nullptr, + .geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR, + .geometry = + { + .triangles = + { + .sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR, + .pNext = nullptr, + .vertexFormat = VK_FORMAT_R32G32B32_SFLOAT, + .vertexData = vertexDataAddress, + .vertexStride = sizeof(Vector4), + .maxVertex = static_cast(blas->getVertexCount()), + .indexType = VK_INDEX_TYPE_UINT32, + .indexData = indexDataAddress, + .transformData = transformDataAddress, + }, + }, + .flags = VK_GEOMETRY_OPAQUE_BIT_KHR, + }; + buildGeometries[i] = { + .sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR, + .pNext = nullptr, + .type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR, + .flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR, + .geometryCount = 1, + .pGeometries = &geometries[i], + }; + + buildSizes[i] = { + .sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR, + .pNext = nullptr, + }; + const uint32 primitiveCount = blas->getPrimitiveCount(); + vkGetAccelerationStructureBuildSizesKHR(handle, VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, &buildGeometries[i], + &primitiveCount, &buildSizes[i]); + + VkBufferCreateInfo bufferInfo = { + .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .size = buildSizes[i].accelerationStructureSize, + .usage = VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, + }; + VmaAllocationCreateInfo bufferAllocInfo = { + .usage = VMA_MEMORY_USAGE_AUTO, + }; + blas->buffer = new BufferAllocation(this, "BLAS", bufferInfo, bufferAllocInfo, Gfx::QueueType::GRAPHICS); + + VkAccelerationStructureCreateInfoKHR blasInfo = { + .sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR, + .pNext = nullptr, + .createFlags = 0, + .buffer = blas->buffer->buffer, + .offset = 0, + .size = buildSizes[i].accelerationStructureSize, + .type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR, + }; + VK_CHECK(vkCreateAccelerationStructureKHR(handle, &blasInfo, nullptr, &blas->handle)); + + VkBufferCreateInfo scratchInfo = { + .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .size = buildSizes[i].buildScratchSize, + .usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, + }; + VmaAllocationCreateInfo scratchAllocInfo = { + .usage = VMA_MEMORY_USAGE_AUTO, + }; + scratchBuffers[i] = new BufferAllocation(this, "ScratchBuffer", scratchInfo, scratchAllocInfo, Gfx::QueueType::GRAPHICS, + accelerationProperties.minAccelerationStructureScratchOffsetAlignment); + + buildGeometries[i].dstAccelerationStructure = blas->handle; + buildGeometries[i].scratchData.deviceAddress = scratchBuffers[i]->deviceAddress; + + buildRanges[i] = VkAccelerationStructureBuildRangeInfoKHR{ + .primitiveCount = primitiveCount, + .primitiveOffset = 0, + .firstVertex = 0, + .transformOffset = 0, + }; + buildRangePointers[i] = &buildRanges[i]; + } + + PCommand cmd = graphicsCommands->getCommands(); + vkCmdBuildAccelerationStructuresKHR(cmd->getHandle(), buildGeometries.size(), buildGeometries.data(), buildRangePointers.data()); + transformBuffer->bind(); + cmd->bindResource(PBufferAllocation(transformBuffer)); + destructionManager->queueResourceForDestruction(std::move(transformBuffer)); + + for (auto& scratchAlloc : scratchBuffers) { + scratchAlloc->bind(); + cmd->bindResource(PBufferAllocation(scratchAlloc)); + destructionManager->queueResourceForDestruction(std::move(scratchAlloc)); + } +} + Gfx::ORayGenShader Graphics::createRayGenShader(const ShaderCreateInfo& createInfo) { ORayGenShader shader = new RayGenShader(this); shader->create(createInfo); @@ -499,7 +656,7 @@ void Graphics::setupDebugCallback() { .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, .pNext = nullptr, .flags = 0, - .messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT, + .messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT, .messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT, .pfnUserCallback = &debugCallback, @@ -583,10 +740,8 @@ void Graphics::pickPhysicalDevice() { .pNext = &features12, .features = { - .geometryShader = true, .fillModeNonSolid = true, .wideLines = true, - .occlusionQueryPrecise = true, .pipelineStatisticsQuery = true, .fragmentStoresAndAtomics = true, .shaderInt64 = true, @@ -727,4 +882,5 @@ void Graphics::createDevice(GraphicsInitializer initializer) { createRayTracingPipelines = (PFN_vkCreateRayTracingPipelinesKHR)vkGetDeviceProcAddr(handle, "vkCreateRayTracingPipelinesKHR"); getRayTracingShaderGroupHandles = (PFN_vkGetRayTracingShaderGroupHandlesKHR)vkGetDeviceProcAddr(handle, "vkGetRayTracingShaderGroupHandlesKHR"); + cmdTraceRays = (PFN_vkCmdTraceRaysKHR)vkGetDeviceProcAddr(handle, "vkCmdTraceRaysKHR"); } diff --git a/src/Engine/Graphics/Vulkan/Graphics.h b/src/Engine/Graphics/Vulkan/Graphics.h index 25b600d..e3ab4a9 100644 --- a/src/Engine/Graphics/Vulkan/Graphics.h +++ b/src/Engine/Graphics/Vulkan/Graphics.h @@ -81,6 +81,7 @@ class Graphics : public Gfx::Graphics { // Ray Tracing virtual Gfx::OBottomLevelAS createBottomLevelAccelerationStructure(const Gfx::BottomLevelASCreateInfo& createInfo) override; virtual Gfx::OTopLevelAS createTopLevelAccelerationStructure(const Gfx::TopLevelASCreateInfo& createInfo) override; + virtual void buildBottomLevelAccelerationStructures(Array data) override; virtual Gfx::ORayGenShader createRayGenShader(const ShaderCreateInfo& createInfo) override; virtual Gfx::OAnyHitShader createAnyHitShader(const ShaderCreateInfo& createInfo) override; diff --git a/src/Engine/Graphics/Vulkan/PipelineCache.cpp b/src/Engine/Graphics/Vulkan/PipelineCache.cpp index 1d62f58..4435a0d 100644 --- a/src/Engine/Graphics/Vulkan/PipelineCache.cpp +++ b/src/Engine/Graphics/Vulkan/PipelineCache.cpp @@ -470,14 +470,14 @@ PRayTracingPipeline PipelineCache::createPipeline(Gfx::RayTracingPipelineCreateI Array shaderStages; Array shaderGroups; { - auto rayGen = createInfo.rayGenShader.cast(); + auto rayGen = createInfo.rayGenGroup.shader.cast(); shaderStages.add(VkPipelineShaderStageCreateInfo{ .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, .pNext = nullptr, .flags = 0, .stage = VK_SHADER_STAGE_RAYGEN_BIT_KHR, .module = rayGen->getModuleHandle(), - .pName = rayGen->getEntryPointName(), + .pName = "main", }); shaderGroups.add(VkRayTracingShaderGroupCreateInfoKHR{ .sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR, @@ -490,7 +490,7 @@ PRayTracingPipeline PipelineCache::createPipeline(Gfx::RayTracingPipelineCreateI }); } { - for (auto hitgroup : createInfo.hitgroups) { + for (auto hitgroup : createInfo.hitGroups) { auto hit = hitgroup.closestHitShader.cast(); shaderStages.add(VkPipelineShaderStageCreateInfo{ .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, @@ -498,8 +498,9 @@ PRayTracingPipeline PipelineCache::createPipeline(Gfx::RayTracingPipelineCreateI .flags = 0, .stage = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, .module = hit->getModuleHandle(), - .pName = hit->getEntryPointName(), + .pName = "main", }); + uint32 hitIndex = static_cast(shaderStages.size() - 1); uint32 anyHitIndex = VK_SHADER_UNUSED_KHR; uint32 intersectionIndex = VK_SHADER_UNUSED_KHR; if (hitgroup.anyHitShader != nullptr) { @@ -509,8 +510,8 @@ PRayTracingPipeline PipelineCache::createPipeline(Gfx::RayTracingPipelineCreateI .pNext = nullptr, .flags = 0, .stage = VK_SHADER_STAGE_ANY_HIT_BIT_KHR, - .module = hit->getModuleHandle(), - .pName = hit->getEntryPointName(), + .module = anyHit->getModuleHandle(), + .pName = "main", }); } if (hitgroup.intersectionShader != nullptr) { @@ -529,15 +530,15 @@ PRayTracingPipeline PipelineCache::createPipeline(Gfx::RayTracingPipelineCreateI .pNext = nullptr, .type = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR, .generalShader = VK_SHADER_UNUSED_KHR, - .closestHitShader = static_cast(shaderStages.size() - 1), + .closestHitShader = hitIndex, .anyHitShader = anyHitIndex, .intersectionShader = intersectionIndex, }); } } { - for (auto gfxMiss : createInfo.missShaders) { - auto miss = gfxMiss.cast(); + for (auto gfxMiss : createInfo.missGroups) { + auto miss = gfxMiss.shader.cast(); shaderStages.add(VkPipelineShaderStageCreateInfo{ .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, .pNext = nullptr, @@ -558,15 +559,15 @@ PRayTracingPipeline PipelineCache::createPipeline(Gfx::RayTracingPipelineCreateI } } { - for (auto gfxCallable : createInfo.callableShaders) { - auto miss = gfxCallable.cast(); + for (auto gfxCallable : createInfo.callableGroups) { + auto call = gfxCallable.shader.cast(); shaderStages.add(VkPipelineShaderStageCreateInfo{ .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, .pNext = nullptr, .flags = 0, .stage = VK_SHADER_STAGE_CALLABLE_BIT_KHR, - .module = miss->getModuleHandle(), - .pName = miss->getEntryPointName(), + .module = call->getModuleHandle(), + .pName = call->getEntryPointName(), }); shaderGroups.add(VkRayTracingShaderGroupCreateInfoKHR{ .sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR, @@ -604,26 +605,51 @@ PRayTracingPipeline PipelineCache::createPipeline(Gfx::RayTracingPipelineCreateI vkGetRayTracingShaderGroupHandlesKHR(graphics->getDevice(), pipelineHandle, 0, shaderGroups.size(), sbtSize, sbt.data()); + uint32 rayGenSize = align(handleSize + createInfo.rayGenGroup.parameters.size(), handleAlignment); Array rayGenSbt(handleSizeAligned); std::memcpy(rayGenSbt.data(), sbt.data(), handleSize); + std::memcpy(rayGenSbt.data() + handleSize, createInfo.rayGenGroup.parameters.data(), createInfo.rayGenGroup.parameters.size()); uint64 sbtOffset = handleSizeAligned; + uint32 maxParamSize = 0; - for (auto& hitgroup : createInfo.hitgroups) { + for (auto& hitgroup : createInfo.hitGroups) { maxParamSize = std::max(maxParamSize, hitgroup.parameters.size()); } - uint64 hitStride = align(handleSize + maxParamSize, handleAlignment); - Array hitSbt(hitStride * createInfo.hitgroups.size()); - for (uint64 i = 0; i < createInfo.hitgroups.size(); ++i) { + Array hitSbt(hitStride * createInfo.hitGroups.size()); + for (uint64 i = 0; i < createInfo.hitGroups.size(); ++i) { 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()); + std::memcpy(hitSbt.data() + i * hitStride + handleSize, createInfo.hitGroups[i].parameters.data(), + createInfo.hitGroups[i].parameters.size()); + sbtOffset += handleSizeAligned; + } + + maxParamSize = 0; + for (auto& missGroup : createInfo.missGroups) { + maxParamSize = std::max(maxParamSize, missGroup.parameters.size()); + } + uint64 missStride = align(handleSize + maxParamSize, handleAlignment); + Array missSbt(missStride * createInfo.missGroups.size()); + for (uint64 i = 0; i < createInfo.missGroups.size(); ++i) { + 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; } - Array missSbt(handleSizeAligned); - std::memcpy(missSbt.data(), sbt.data() + sbtOffset, handleSize); + maxParamSize = 0; + for (auto& callableGroup : createInfo.callableGroups) { + maxParamSize = std::max(maxParamSize, callableGroup.parameters.size()); + } + uint64 callableStride = align(handleSize + maxParamSize, handleAlignment); + Array callableSbt(callableStride * createInfo.callableGroups.size()); + for (uint64 i = 0; i < createInfo.callableGroups.size(); ++i) { + std::memcpy(callableSbt.data() + i * callableStride, sbt.data() + sbtOffset, handleSize); + std::memcpy(callableSbt.data() + i * callableStride + handleSize, createInfo.callableGroups[i].parameters.data(), + createInfo.callableGroups[i].parameters.size()); + sbtOffset += handleSizeAligned; + } OBufferAllocation rayGenBuffer = new BufferAllocation(graphics, "RayGenSBT", @@ -633,13 +659,15 @@ PRayTracingPipeline PipelineCache::createPipeline(Gfx::RayTracingPipelineCreateI .flags = 0, .size = rayGenSbt.size(), .usage = VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | - VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, + VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, }, VmaAllocationCreateInfo{ .usage = VMA_MEMORY_USAGE_AUTO, }, Gfx::QueueType::GRAPHICS); rayGenBuffer->updateContents(0, rayGenSbt.size(), rayGenSbt.data()); + rayGenBuffer->pipelineBarrier(Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT, Gfx::SE_ACCESS_SHADER_READ_BIT, + Gfx::SE_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR); OBufferAllocation hitBuffer = new BufferAllocation(graphics, "HitSBT", @@ -649,13 +677,15 @@ PRayTracingPipeline PipelineCache::createPipeline(Gfx::RayTracingPipelineCreateI .flags = 0, .size = hitSbt.size(), .usage = VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | - VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, + VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, }, VmaAllocationCreateInfo{ .usage = VMA_MEMORY_USAGE_AUTO, }, Gfx::QueueType::GRAPHICS); hitBuffer->updateContents(0, hitSbt.size(), hitSbt.data()); + hitBuffer->pipelineBarrier(Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT, Gfx::SE_ACCESS_SHADER_READ_BIT, + Gfx::SE_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR); OBufferAllocation missBuffer = new BufferAllocation(graphics, "MissSBT", @@ -665,17 +695,39 @@ PRayTracingPipeline PipelineCache::createPipeline(Gfx::RayTracingPipelineCreateI .flags = 0, .size = missSbt.size(), .usage = VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | - VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, + VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, }, VmaAllocationCreateInfo{ .usage = VMA_MEMORY_USAGE_AUTO, }, Gfx::QueueType::GRAPHICS); missBuffer->updateContents(0, missSbt.size(), missSbt.data()); + missBuffer->pipelineBarrier(Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT, Gfx::SE_ACCESS_SHADER_READ_BIT, + Gfx::SE_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR); + + + OBufferAllocation callableBuffer = + new BufferAllocation(graphics, "CallableSBT", + VkBufferCreateInfo{ + .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .size = callableSbt.size(), + .usage = VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | + VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, + }, + VmaAllocationCreateInfo{ + .usage = VMA_MEMORY_USAGE_AUTO, + }, + Gfx::QueueType::GRAPHICS); + callableBuffer->updateContents(0, callableSbt.size(), callableSbt.data()); + callableBuffer->pipelineBarrier(Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT, Gfx::SE_ACCESS_SHADER_READ_BIT, + Gfx::SE_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR); + ORayTracingPipeline pipeline = - new RayTracingPipeline(graphics, pipelineHandle, std::move(rayGenBuffer), handleSizeAligned, std::move(hitBuffer), hitStride, - std::move(missBuffer), handleSizeAligned, createInfo.pipelineLayout); + new RayTracingPipeline(graphics, pipelineHandle, std::move(rayGenBuffer), rayGenSize, std::move(hitBuffer), hitStride, + std::move(missBuffer), missStride, std::move(callableBuffer), callableStride, 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 713aa8d..ca0e727 100644 --- a/src/Engine/Graphics/Vulkan/RayTracing.cpp +++ b/src/Engine/Graphics/Vulkan/RayTracing.cpp @@ -14,146 +14,25 @@ using namespace Seele::Vulkan; BottomLevelAS::BottomLevelAS(PGraphics graphics, const Gfx::BottomLevelASCreateInfo& createInfo) : graphics(graphics), material(createInfo.mesh->referencedMaterial->getHandle()) { + matrix = { + // createInfo.mesh->transform[0][0], createInfo.mesh->transform[0][1], createInfo.mesh->transform[0][2], + // createInfo.mesh->transform[0][3], createInfo.mesh->transform[1][0], createInfo.mesh->transform[1][1], + // createInfo.mesh->transform[1][2], createInfo.mesh->transform[1][3], createInfo.mesh->transform[2][0], + // createInfo.mesh->transform[2][1], createInfo.mesh->transform[2][2], createInfo.mesh->transform[2][3], + 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, + }; VertexData* vertexData = createInfo.mesh->vertexData; MeshData meshData = vertexData->getMeshData(createInfo.mesh->id); - Gfx::PShaderBuffer positionBuffer = vertexData->getPositionBuffer(); - Gfx::PIndexBuffer indexBuffer = vertexData->getIndexBuffer(); - VkTransformMatrixKHR matrix = { - createInfo.mesh->transform[0][0], createInfo.mesh->transform[1][0], createInfo.mesh->transform[2][0], - createInfo.mesh->transform[3][0], createInfo.mesh->transform[0][1], createInfo.mesh->transform[1][1], - createInfo.mesh->transform[2][1], createInfo.mesh->transform[3][1], createInfo.mesh->transform[0][2], - createInfo.mesh->transform[1][2], createInfo.mesh->transform[2][2], createInfo.mesh->transform[3][2], - }; - VkBufferCreateInfo transformBufferInfo = { - .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .size = sizeof(VkTransformMatrixKHR), - .usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | - VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_TRANSFER_DST_BIT, - }; - VmaAllocationCreateInfo transformAllocInfo = { - .flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, - .usage = VMA_MEMORY_USAGE_AUTO, - }; - OBufferAllocation transformBuffer = - new BufferAllocation(graphics, "TransformBuffer", transformBufferInfo, transformAllocInfo, Gfx::QueueType::GRAPHICS); - transformBuffer->updateContents(0, sizeof(VkTransformMatrixKHR), &matrix); + vertexOffset = vertexData->getMeshOffset(createInfo.mesh->id) * sizeof(Vector4); + indexOffset = meshData.firstIndex * sizeof(uint32); + primitiveCount = meshData.numIndices / 3; - VkDeviceOrHostAddressConstKHR vertexDataAddress = { - .deviceAddress = - positionBuffer.cast()->getDeviceAddress() + vertexData->getMeshOffset(createInfo.mesh->id) * sizeof(Vector4), - }; - VkDeviceOrHostAddressConstKHR indexDataAddress = { - .deviceAddress = indexBuffer.cast()->getDeviceAddress() + meshData.firstIndex * sizeof(uint32), - }; - VkDeviceOrHostAddressConstKHR transformDataAddress = { - .deviceAddress = transformBuffer->deviceAddress, - }; - VkAccelerationStructureGeometryKHR geometry = { - .sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR, - .pNext = nullptr, - .geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR, - .geometry = - { - .triangles = - { - .sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR, - .pNext = nullptr, - .vertexFormat = VK_FORMAT_R32G32B32_SFLOAT, - .vertexData = vertexDataAddress, - .vertexStride = sizeof(Vector), - .maxVertex = static_cast(createInfo.mesh->vertexCount), - .indexType = VK_INDEX_TYPE_UINT32, - .indexData = indexDataAddress, - .transformData = transformDataAddress, - }, - }, - .flags = VK_GEOMETRY_OPAQUE_BIT_KHR, - }; - VkAccelerationStructureBuildGeometryInfoKHR structureBuildGeometry = { - .sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR, - .pNext = nullptr, - .type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR, - .flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR, - .geometryCount = 1, - .pGeometries = &geometry, - }; - - const uint32 primitiveCount = meshData.numIndices / 3; - - VkAccelerationStructureBuildSizesInfoKHR buildSizesInfo = { - .sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR, - .pNext = nullptr, - }; - vkGetAccelerationStructureBuildSizesKHR(graphics->getDevice(), VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, &structureBuildGeometry, - &primitiveCount, &buildSizesInfo); - - VkBufferCreateInfo bufferInfo = { - .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .size = buildSizesInfo.accelerationStructureSize, - .usage = VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, - }; - VmaAllocationCreateInfo bufferAllocInfo = { - .usage = VMA_MEMORY_USAGE_AUTO, - }; - buffer = new BufferAllocation(graphics, "BLAS", bufferInfo, bufferAllocInfo, Gfx::QueueType::GRAPHICS); - - VkAccelerationStructureCreateInfoKHR blasInfo = { - .sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR, - .pNext = nullptr, - .createFlags = 0, - .buffer = buffer->buffer, - .offset = 0, - .size = buildSizesInfo.accelerationStructureSize, - .type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR, - }; - VK_CHECK(vkCreateAccelerationStructureKHR(graphics->getDevice(), &blasInfo, nullptr, &handle)); - - VkBufferCreateInfo scratchInfo = { - .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .size = buildSizesInfo.buildScratchSize, - .usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, - }; - VmaAllocationCreateInfo scratchAllocInfo = { - .usage = VMA_MEMORY_USAGE_AUTO, - }; - OBufferAllocation scratchAlloc = - new BufferAllocation(graphics, "ScratchBuffer", scratchInfo, scratchAllocInfo, Gfx::QueueType::GRAPHICS, - graphics->getAccelerationProperties().minAccelerationStructureScratchOffsetAlignment); - - structureBuildGeometry.dstAccelerationStructure = handle; - structureBuildGeometry.scratchData.deviceAddress = scratchAlloc->deviceAddress; - - VkAccelerationStructureBuildRangeInfoKHR buildRangeInfo = { - .primitiveCount = primitiveCount, - .primitiveOffset = 0, - .firstVertex = 0, - .transformOffset = 0, - }; - Array ranges = {&buildRangeInfo}; - - PCommand cmd = graphics->getGraphicsCommands()->getCommands(); - vkCmdBuildAccelerationStructuresKHR(cmd->getHandle(), 1, &structureBuildGeometry, ranges.data()); - scratchAlloc->bind(); - buffer->bind(); - transformBuffer->bind(); - cmd->bindResource(PBufferAllocation(transformBuffer)); - cmd->bindResource(PBufferAllocation(buffer)); - cmd->bindResource(PBufferAllocation(scratchAlloc)); - - graphics->getDestructionManager()->queueResourceForDestruction(std::move(transformBuffer)); - graphics->getDestructionManager()->queueResourceForDestruction(std::move(scratchAlloc)); // todo: compact } BottomLevelAS::~BottomLevelAS() { graphics->getDestructionManager()->queueResourceForDestruction(std::move(buffer)); } -TopLevelAS::TopLevelAS(PGraphics graphics, const Gfx::TopLevelASCreateInfo& createInfo) { +TopLevelAS::TopLevelAS(PGraphics graphics, const Gfx::TopLevelASCreateInfo& createInfo) : graphics(graphics) { Array instances(createInfo.instances.size()); for (uint32 i = 0; i < instances.size(); ++i) { auto blas = createInfo.bottomLevelStructures[i].cast(); @@ -174,28 +53,28 @@ TopLevelAS::TopLevelAS(PGraphics graphics, const Gfx::TopLevelASCreateInfo& crea createInfo.instances[i].transformMatrix[2][2], createInfo.instances[i].transformMatrix[3][2], }, - .instanceCustomIndex = i, + .instanceCustomIndex = 0, .mask = 0xff, - .instanceShaderBindingTableRecordOffset = i, + .instanceShaderBindingTableRecordOffset = 0, .flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR, .accelerationStructureReference = blas->getDeviceAddress(), }; } - instanceAllocation = new BufferAllocation( - graphics, "ASInstances", - VkBufferCreateInfo{ - .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .size = sizeof(VkAccelerationStructureInstanceKHR) * instances.size(), - .usage = VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, - }, - VmaAllocationCreateInfo{ - .usage = VMA_MEMORY_USAGE_AUTO, - }, - Gfx::QueueType::GRAPHICS); - + instanceAllocation = new BufferAllocation(graphics, "ASInstances", + VkBufferCreateInfo{ + .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .size = sizeof(VkAccelerationStructureInstanceKHR) * instances.size(), + .usage = VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | + VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, + }, + VmaAllocationCreateInfo{ + .usage = VMA_MEMORY_USAGE_AUTO, + }, + Gfx::QueueType::GRAPHICS); + instanceAllocation->updateContents(0, sizeof(VkAccelerationStructureInstanceKHR) * instances.size(), instances.data()); VkDeviceOrHostAddressConstKHR instanceDeviceAddress = { .deviceAddress = instanceAllocation->deviceAddress, }; @@ -203,7 +82,7 @@ TopLevelAS::TopLevelAS(PGraphics graphics, const Gfx::TopLevelASCreateInfo& crea VkAccelerationStructureGeometryKHR geometry = { .sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR, .pNext = nullptr, - .geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR, + .geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR, .geometry = {.instances = { .sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR, @@ -216,7 +95,7 @@ TopLevelAS::TopLevelAS(PGraphics graphics, const Gfx::TopLevelASCreateInfo& crea VkAccelerationStructureBuildGeometryInfoKHR structureBuildGeometry = { .sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR, .pNext = nullptr, - .type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR, + .type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR, .flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR, .geometryCount = 1, .pGeometries = &geometry, @@ -294,18 +173,33 @@ TopLevelAS::TopLevelAS(PGraphics graphics, const Gfx::TopLevelASCreateInfo& crea auto cmd = graphics->getGraphicsCommands()->getCommands(); vkCmdBuildAccelerationStructuresKHR(cmd->getHandle(), 1, &buildGeometry, buildRangeInfos); scratchBuffer->bind(); - + cmd->bindResource(PBufferAllocation(scratchBuffer)); graphics->getDestructionManager()->queueResourceForDestruction(std::move(scratchBuffer)); + + buffer->bind(); + cmd->bindResource(PBufferAllocation(buffer)); + + instanceAllocation->bind(); + cmd->bindResource(PBufferAllocation(instanceAllocation)); } -TopLevelAS::~TopLevelAS() {} +TopLevelAS::~TopLevelAS() { + graphics->getDestructionManager()->queueResourceForDestruction(std::move(buffer)); + graphics->getDestructionManager()->queueResourceForDestruction(std::move(instanceAllocation)); +} RayTracingPipeline::RayTracingPipeline(PGraphics graphics, VkPipeline handle, OBufferAllocation rayGen, uint64 rayGenStride, OBufferAllocation hit, uint64 hitStride, OBufferAllocation miss, uint64 missStride, - Gfx::PPipelineLayout layout) + OBufferAllocation callable, uint64 callableStride, Gfx::PPipelineLayout layout) : Gfx::RayTracingPipeline(layout), graphics(graphics), pipeline(handle), rayGen(std::move(rayGen)), rayGenStride(rayGenStride), - hit(std::move(hit)), hitStride(hitStride), miss(std::move(miss)), missStride(missStride) {} + hit(std::move(hit)), hitStride(hitStride), miss(std::move(miss)), missStride(missStride), callable(std::move(callable)), + callableStride(callableStride) {} -RayTracingPipeline::~RayTracingPipeline() {} +RayTracingPipeline::~RayTracingPipeline() { + graphics->getDestructionManager()->queueResourceForDestruction(std::move(rayGen)); + graphics->getDestructionManager()->queueResourceForDestruction(std::move(hit)); + graphics->getDestructionManager()->queueResourceForDestruction(std::move(miss)); + graphics->getDestructionManager()->queueResourceForDestruction(std::move(callable)); +} void RayTracingPipeline::bind(VkCommandBuffer handle) { vkCmdBindPipeline(handle, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline); } diff --git a/src/Engine/Graphics/Vulkan/RayTracing.h b/src/Engine/Graphics/Vulkan/RayTracing.h index b9aaccd..ca39316 100644 --- a/src/Engine/Graphics/Vulkan/RayTracing.h +++ b/src/Engine/Graphics/Vulkan/RayTracing.h @@ -1,5 +1,6 @@ #pragma once #include "Buffer.h" +#include "Descriptor.h" #include "Graphics.h" #include "Graphics/Initializer.h" #include "Graphics/RayTracing.h" @@ -12,12 +13,23 @@ class BottomLevelAS : public Gfx::BottomLevelAS { BottomLevelAS(PGraphics graphics, const Gfx::BottomLevelASCreateInfo& createInfo); ~BottomLevelAS(); uint64 getDeviceAddress() const { return buffer->deviceAddress; } + constexpr VkTransformMatrixKHR getTransform() const { return matrix; } + constexpr uint64 getIndexOffset() const { return indexOffset; } + constexpr uint64 getVertexOffset() const { return vertexOffset; } + constexpr uint64 getVertexCount() const { return vertexCount; } + constexpr uint32 getPrimitiveCount() const { return primitiveCount; } private: PGraphics graphics; VkAccelerationStructureKHR handle; OBufferAllocation buffer; PMaterialInstance material; + VkTransformMatrixKHR matrix; + uint64 indexOffset; + uint64 vertexOffset; + uint64 vertexCount; + uint32 primitiveCount; + friend class Graphics; }; DEFINE_REF(BottomLevelAS) class TopLevelAS : public Gfx::TopLevelAS { @@ -31,13 +43,14 @@ class TopLevelAS : public Gfx::TopLevelAS { VkAccelerationStructureKHR handle; OBufferAllocation instanceAllocation; OBufferAllocation buffer; + friend class DescriptorSet; }; DEFINE_REF(TopLevelAS) - class RayTracingPipeline : public Gfx::RayTracingPipeline { public: RayTracingPipeline(PGraphics graphics, VkPipeline handle, OBufferAllocation rayGen, uint64 rayGenStride, OBufferAllocation hit, - uint64 hitStride, OBufferAllocation miss, uint64 missStride, Gfx::PPipelineLayout layout); + uint64 hitStride, OBufferAllocation miss, uint64 missStride, OBufferAllocation callable, uint64 callableStride, + Gfx::PPipelineLayout layout); virtual ~RayTracingPipeline(); void bind(VkCommandBuffer handle); VkStridedDeviceAddressRegionKHR getRayGenRegion() { @@ -61,6 +74,15 @@ class RayTracingPipeline : public Gfx::RayTracingPipeline { .size = miss->size, }; } + VkStridedDeviceAddressRegionKHR getCallableRegion() { + return VkStridedDeviceAddressRegionKHR{ + .deviceAddress = callable->deviceAddress, + .stride = callableStride, + .size = callable->size, + }; + } + VkPipelineLayout getLayout() const { return layout.cast()->getHandle(); } + private: PGraphics graphics; VkPipeline pipeline; @@ -70,6 +92,8 @@ class RayTracingPipeline : public Gfx::RayTracingPipeline { uint64 hitStride; OBufferAllocation miss; uint64 missStride; + OBufferAllocation callable; + uint64 callableStride; }; DEFINE_REF(RayTracingPipeline) } // namespace Vulkan diff --git a/src/Engine/Graphics/Vulkan/Shader.cpp b/src/Engine/Graphics/Vulkan/Shader.cpp index 8c914ff..2315228 100644 --- a/src/Engine/Graphics/Vulkan/Shader.cpp +++ b/src/Engine/Graphics/Vulkan/Shader.cpp @@ -21,7 +21,8 @@ Shader::~Shader() { uint32 Seele::Vulkan::Shader::getShaderHash() const { return hash; } void Shader::create(const ShaderCreateInfo& createInfo) { - Slang::ComPtr kernelBlob = generateShader(createInfo); + auto [kernelBlob, entryName] = generateShader(createInfo); + entryPointName = entryName; VkShaderModuleCreateInfo moduleInfo = { .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, .pNext = nullptr, diff --git a/src/Engine/Graphics/Vulkan/Shader.h b/src/Engine/Graphics/Vulkan/Shader.h index f2cb380..2b2cc3c 100644 --- a/src/Engine/Graphics/Vulkan/Shader.h +++ b/src/Engine/Graphics/Vulkan/Shader.h @@ -18,7 +18,7 @@ class Shader { constexpr VkShaderModule getModuleHandle() const { return module; } constexpr const char* getEntryPointName() const { // SLang renames all entry points to main, so we dont need that - return "main"; // entryPointName.c_str(); + return "main";// entryPointName.c_str(); } constexpr VkShaderStageFlags getStage() const { return stage; } uint32 getShaderHash() const; @@ -27,6 +27,7 @@ class Shader { PGraphics graphics; VkShaderModule module; VkShaderStageFlags stage; + std::string entryPointName; uint32 hash; }; DEFINE_REF(Shader) diff --git a/src/Engine/Graphics/slang-compile.cpp b/src/Engine/Graphics/slang-compile.cpp index 1bc3c10..7198bd5 100644 --- a/src/Engine/Graphics/slang-compile.cpp +++ b/src/Engine/Graphics/slang-compile.cpp @@ -25,6 +25,7 @@ using namespace Seele; thread_local Slang::ComPtr globalSession; thread_local Slang::ComPtr specializedComponent; thread_local Slang::ComPtr session; +thread_local Array entryPoints; void Seele::beginCompilation(const ShaderCompilationInfo& info, SlangCompileTarget target, Gfx::PPipelineLayout layout) { if (!globalSession) { @@ -81,8 +82,9 @@ void Seele::beginCompilation(const ShaderCompilationInfo& info, SlangCompileTarg moduleMap[moduleName] = loaded; CHECK_DIAGNOSTICS(); } - + entryPoints.clear(); for (const auto& [name, mod] : info.entryPoints) { + entryPoints.add(name); slang::IEntryPoint* entry; moduleMap[mod]->findEntryPointByName(name.c_str(), &entry); components.add(entry); @@ -119,12 +121,15 @@ void Seele::beginCompilation(const ShaderCompilationInfo& info, SlangCompileTarg // workaround layout->addMapping("pVertexData", 1); layout->addMapping("pMaterial", 4); + layout->addMapping("pLightEnv", 3); + layout->addMapping("pRayTracingParams", 5); + layout->addMapping("pScene", 2); } -Slang::ComPtr Seele::generateShader(const ShaderCreateInfo& createInfo) { +Pair, std::string> Seele::generateShader(const ShaderCreateInfo& createInfo) { Slang::ComPtr diagnostics; Slang::ComPtr kernelBlob; specializedComponent->getEntryPointCode(createInfo.entryPointIndex, 0, kernelBlob.writeRef(), diagnostics.writeRef()); CHECK_DIAGNOSTICS(); - return kernelBlob; + return {kernelBlob, entryPoints[createInfo.entryPointIndex]}; } diff --git a/src/Engine/Graphics/slang-compile.h b/src/Engine/Graphics/slang-compile.h index c12d7ef..fe320a0 100644 --- a/src/Engine/Graphics/slang-compile.h +++ b/src/Engine/Graphics/slang-compile.h @@ -5,5 +5,5 @@ namespace Seele { void beginCompilation(const ShaderCompilationInfo& info, SlangCompileTarget target, Gfx::PPipelineLayout layout); -Slang::ComPtr generateShader(const ShaderCreateInfo& createInfo); +Pair, std::string> generateShader(const ShaderCreateInfo& createInfo); } diff --git a/src/Engine/Material/Material.cpp b/src/Engine/Material/Material.cpp index bc90b05..2f3a49f 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_CLOSEST_HIT_BIT_KHR, + .shaderStages = Gfx::SE_SHADER_STAGE_FRAGMENT_BIT | Gfx::SE_SHADER_STAGE_CALLABLE_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_CLOSEST_HIT_BIT_KHR, + .shaderStages = Gfx::SE_SHADER_STAGE_FRAGMENT_BIT | Gfx::SE_SHADER_STAGE_CALLABLE_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_CLOSEST_HIT_BIT_KHR, + .shaderStages = Gfx::SE_SHADER_STAGE_FRAGMENT_BIT | Gfx::SE_SHADER_STAGE_CALLABLE_BIT_KHR, }); layout->create(); floatBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{