diff --git a/res/shaders/BasePass.slang b/res/shaders/BasePass.slang index e17fa0f..d45c1c6 100644 --- a/res/shaders/BasePass.slang +++ b/res/shaders/BasePass.slang @@ -1,6 +1,7 @@ import Common; import LightEnv; import MaterialParameter; +import MATERIAL_FILE_NAME; struct LightCullingData { @@ -8,7 +9,6 @@ struct LightCullingData RWTexture2D lightGrid; }; -layout(set=5) ParameterBlock pLightCullingData; [shader("pixel")] diff --git a/res/shaders/RayTracing.slang b/res/shaders/RayTracing.slang deleted file mode 100644 index e69de29..0000000 diff --git a/res/shaders/Skybox.slang b/res/shaders/Skybox.slang index c7c7d42..f0e2aea 100644 --- a/res/shaders/Skybox.slang +++ b/res/shaders/Skybox.slang @@ -10,7 +10,6 @@ struct SkyboxData float4x4 transformMatrix; float4 fogBlend; }; -layout(set=1) ParameterBlock pSkyboxData; [shader("vertex")] @@ -88,7 +87,6 @@ struct TextureData TextureCube cubeMap2; SamplerState sampler; }; -layout(set=2) ParameterBlock pSkyboxTextures; static const float lowerLimit = 0.0; static const float upperLimit = 0.1; diff --git a/res/shaders/lib/Scene.slang b/res/shaders/lib/Scene.slang index 0648f96..4126b3a 100644 --- a/res/shaders/lib/Scene.slang +++ b/res/shaders/lib/Scene.slang @@ -43,12 +43,16 @@ struct MeshletCullingInfo struct DrawCallOffsets { - uint32_t instanceOffset; + uint instanceOffset; uint textureOffset; uint samplerOffset; uint floatOffset; }; +#ifdef RAY_TRACING +layout(shaderRecordEXT) +#else layout(push_constant) +#endif ConstantBuffer pOffsets; struct Scene diff --git a/res/shaders/raytracing/ClosestHit.slang b/res/shaders/raytracing/ClosestHit.slang index dcb742f..272860b 100644 --- a/res/shaders/raytracing/ClosestHit.slang +++ b/res/shaders/raytracing/ClosestHit.slang @@ -1,14 +1,15 @@ import Common; -import RayTracingData; import VertexData; import MaterialParameter; -import Scene; import LightEnv; +import Scene; +import RayTracingData; +import MATERIAL_FILE_NAME; // simplification: all BLAS only have 1 geometry [shader("closesthit")] -void main(inout payload Payload hitValue, in BuiltInTriangleIntersectionAttributes attr) +void closesthit(inout float3 hitValue, in BuiltInTriangleIntersectionAttributes attr) { const float3 barycentricCoords = float3(1.0f - attr.barycentrics.x - attr.barycentrics.y, attr.barycentrics.x, attr.barycentrics.y); @@ -52,5 +53,5 @@ void main(inout payload Payload hitValue, in BuiltInTriangleIntersectionAttribut result = result / (result + float3(1.0)); result = pow(result, float3(1.0/2.2)); - hitValue.color = result; + hitValue = result; } \ No newline at end of file diff --git a/res/shaders/raytracing/Miss.slang b/res/shaders/raytracing/Miss.slang new file mode 100644 index 0000000..e20ece8 --- /dev/null +++ b/res/shaders/raytracing/Miss.slang @@ -0,0 +1,7 @@ +import RayTracingData; + +[shader("miss")] +void main(inout float3 p) +{ + p = float3(1, 0, 1); +} \ No newline at end of file diff --git a/res/shaders/raytracing/RayGen.slang b/res/shaders/raytracing/RayGen.slang index b20ccf0..9fd9b5c 100644 --- a/res/shaders/raytracing/RayGen.slang +++ b/res/shaders/raytracing/RayGen.slang @@ -17,11 +17,9 @@ void main() uint max_rays = 24; - uint object_type = 100; float4 color = float4(0, 0, 0, 0); - uint current_mode = 0; float expectedDistance = -1; - Payload payload; + float3 payload; RayDesc desc = { origin.xyz, @@ -32,5 +30,5 @@ void main() TraceRay(pRayTracingParams.scene, RAY_FLAG_FORCE_OPAQUE, 0xff, 0, 0, 0, desc, payload); - pRayTracingParams.image[DispatchRaysIndex().xy] = payload.color; + pRayTracingParams.image[DispatchRaysIndex().xy] = float4(payload, 1.0f); } diff --git a/res/shaders/raytracing/RayTracingData.slang b/res/shaders/raytracing/RayTracingData.slang index 2096dd7..8ab202b 100644 --- a/res/shaders/raytracing/RayTracingData.slang +++ b/res/shaders/raytracing/RayTracingData.slang @@ -1,13 +1,7 @@ - -struct Payload -{ - float3 color; -}; - struct RayTracingParams { RaytracingAccelerationStructure scene; - RWTexture2D image; + RWTexture2D image; StructuredBuffer indexBuffer; }; ParameterBlock pRayTracingParams; diff --git a/src/Engine/Graphics/Command.h b/src/Engine/Graphics/Command.h index 996a196..693012f 100644 --- a/src/Engine/Graphics/Command.h +++ b/src/Engine/Graphics/Command.h @@ -2,16 +2,17 @@ #include "Descriptor.h" #include "Enums.h" - namespace Seele { namespace Gfx { DECLARE_REF(Viewport) +DECLARE_REF(RayTracingPipeline) class RenderCommand { public: RenderCommand(); virtual ~RenderCommand(); virtual void setViewport(Gfx::PViewport viewport) = 0; virtual void bindPipeline(Gfx::PGraphicsPipeline pipeline) = 0; + virtual void bindPipeline(Gfx::PRayTracingPipeline pipeline) = 0; virtual void bindDescriptor(Gfx::PDescriptorSet set, Array dynamicOffsets = {}) = 0; virtual void bindDescriptor(const Array& sets, Array dynamicOffsets = {}) = 0; virtual void bindVertexBuffer(const Array& buffer) = 0; @@ -21,6 +22,7 @@ class RenderCommand { virtual void drawIndexed(uint32 indexCount, uint32 instanceCount, int32 firstIndex, uint32 vertexOffset, uint32 firstInstance) = 0; virtual void drawMesh(uint32 groupX, uint32 groupY, uint32 groupZ) = 0; virtual void drawMeshIndirect(Gfx::PShaderBuffer buffer, uint64 offset, uint32 drawCount, uint32 stride) = 0; + virtual void traceRays(uint32 width, uint32 height, uint32 depth) = 0; std::string name; }; DEFINE_REF(RenderCommand) diff --git a/src/Engine/Graphics/Descriptor.cpp b/src/Engine/Graphics/Descriptor.cpp index 09cfbbe..78530cb 100644 --- a/src/Engine/Graphics/Descriptor.cpp +++ b/src/Engine/Graphics/Descriptor.cpp @@ -58,11 +58,6 @@ void PipelineLayout::addDescriptorLayout(PDescriptorLayout layout) { descriptorS void PipelineLayout::addPushConstants(const SePushConstantRange& pushConstant) { pushConstants.add(pushConstant); } -void PipelineLayout::addMapping(Map mapping) { - for (const auto& [name, index] : mapping) { - if (parameterMapping.contains(name)) { - assert(parameterMapping[name] == index); - } - parameterMapping[name] = index; - } +void PipelineLayout::addMapping(std::string name, uint32 index) { + parameterMapping[name] = index; } diff --git a/src/Engine/Graphics/Descriptor.h b/src/Engine/Graphics/Descriptor.h index 310330c..e7d0289 100644 --- a/src/Engine/Graphics/Descriptor.h +++ b/src/Engine/Graphics/Descriptor.h @@ -3,7 +3,6 @@ #include "Initializer.h" #include "Resources.h" - namespace Seele { namespace Gfx { struct DescriptorBinding { @@ -56,13 +55,15 @@ DECLARE_REF(ShaderBuffer) DECLARE_REF(Texture) DECLARE_REF(Texture2D) DECLARE_REF(Sampler) +DECLARE_REF(TopLevelAS) class DescriptorSet { public: DescriptorSet(PDescriptorLayout layout); virtual ~DescriptorSet(); virtual void writeChanges() = 0; virtual void updateBuffer(uint32 binding, PUniformBuffer uniformBuffer) = 0; - virtual void updateBuffer(uint32 binding, PShaderBuffer ShaderBuffer) = 0; + virtual void updateBuffer(uint32 binding, PIndexBuffer indexBuffer) = 0; + virtual void updateBuffer(uint32 binding, PShaderBuffer shaderBuffer) = 0; virtual void updateBuffer(uint32_t binding, uint32 index, Gfx::PShaderBuffer uniformBuffer) = 0; virtual void updateSampler(uint32 binding, PSampler sampler) = 0; virtual void updateSampler(uint32_t binding, uint32 dstArrayIndex, Gfx::PSampler samplerState) = 0; @@ -70,6 +71,7 @@ class DescriptorSet { virtual void updateTexture(uint32 binding, uint32 dstArrayIndex, PTexture texture) = 0; virtual void updateTextureArray(uint32_t binding, Array texture) = 0; virtual void updateSamplerArray(uint32_t binding, Array samplers) = 0; + virtual void updateAccelerationStructure(uint32 binding, PTopLevelAS as) = 0; bool operator<(PDescriptorSet other); constexpr PDescriptorLayout getLayout() const { return layout; } @@ -92,7 +94,7 @@ class PipelineLayout { constexpr uint32 getHash() const { return layoutHash; } constexpr const Map& getLayouts() const { return descriptorSetLayouts; } constexpr uint32 findParameter(const std::string& param) const { return parameterMapping[param]; } - void addMapping(Map mapping); + void addMapping(std::string name, uint32 index); constexpr std::string getName() const { return name; }; protected: diff --git a/src/Engine/Graphics/Enums.h b/src/Engine/Graphics/Enums.h index 2797726..aabceac 100644 --- a/src/Engine/Graphics/Enums.h +++ b/src/Engine/Graphics/Enums.h @@ -1129,8 +1129,12 @@ typedef enum SeDescriptorType { SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC = 8, SE_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC = 9, SE_DESCRIPTOR_TYPE_INPUT_ATTACHMENT = 10, - SE_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT = 1000138000, + SE_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK = 1000138000, + SE_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR = 1000150000, SE_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV = 1000165000, + SE_DESCRIPTOR_TYPE_SAMPLE_WEIGHT_IMAGE_QCOM = 1000440000, + SE_DESCRIPTOR_TYPE_BLOCK_MATCH_IMAGE_QCOM = 1000440001, + SE_DESCRIPTOR_TYPE_MUTABLE_EXT = 1000351000, } SeDescriptorType; typedef enum SeDescriptorBindingFlagBits { diff --git a/src/Engine/Graphics/Graphics.h b/src/Engine/Graphics/Graphics.h index 768fea3..5573113 100644 --- a/src/Engine/Graphics/Graphics.h +++ b/src/Engine/Graphics/Graphics.h @@ -27,6 +27,7 @@ DECLARE_REF(IndexBuffer) DECLARE_REF(UniformBuffer) DECLARE_REF(PipelineLayout) DECLARE_REF(GraphicsPipeline) +DECLARE_REF(RayTracingPipeline) DECLARE_REF(ComputePipeline) DECLARE_REF(RenderCommand) DECLARE_REF(ComputeCommand) @@ -73,6 +74,7 @@ class Graphics { virtual ORenderCommand createRenderCommand(const std::string& name = "") = 0; virtual OComputeCommand createComputeCommand(const std::string& name = "") = 0; + virtual void beginShaderCompilation(const ShaderCompilationInfo& compileInfo) = 0; virtual OVertexShader createVertexShader(const ShaderCreateInfo& createInfo) = 0; virtual OFragmentShader createFragmentShader(const ShaderCreateInfo& createInfo) = 0; virtual OComputeShader createComputeShader(const ShaderCreateInfo& createInfo) = 0; @@ -80,6 +82,7 @@ class Graphics { virtual OTaskShader createTaskShader(const ShaderCreateInfo& createInfo) = 0; virtual PGraphicsPipeline createGraphicsPipeline(LegacyPipelineCreateInfo createInfo) = 0; virtual PGraphicsPipeline createGraphicsPipeline(MeshPipelineCreateInfo createInfo) = 0; + virtual PRayTracingPipeline createRayTracingPipeline(RayTracingPipelineCreateInfo createInfo) = 0; virtual PComputePipeline createComputePipeline(ComputePipelineCreateInfo createInfo) = 0; virtual OSampler createSampler(const SamplerCreateInfo& createInfo) = 0; diff --git a/src/Engine/Graphics/Initializer.h b/src/Engine/Graphics/Initializer.h index 73fb534..d826df5 100644 --- a/src/Engine/Graphics/Initializer.h +++ b/src/Engine/Graphics/Initializer.h @@ -104,15 +104,17 @@ struct ShaderBufferCreateInfo { std::string name = "Unnamed"; }; DECLARE_NAME_REF(Gfx, PipelineLayout) -struct ShaderCreateInfo { +struct ShaderCompilationInfo { std::string name; // Debug info - std::string mainModule; - Array additionalModules; - std::string entryPoint; + Array modules; + Array> entryPoints; // entry function name, module name Array> typeParameter; Map defines; Gfx::PPipelineLayout rootSignature; }; +struct ShaderCreateInfo { + uint32 entryPointIndex; +}; struct VertexInputBinding { uint32 binding; uint32 stride; @@ -204,6 +206,7 @@ DECLARE_REF(MissShader) DECLARE_REF(CallableShader) DECLARE_REF(RenderPass) DECLARE_REF(PipelineLayout) +DECLARE_REF(BottomLevelAS) struct LegacyPipelineCreateInfo { SePrimitiveTopology topology = Gfx::SE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; PVertexInput vertexInput = nullptr; @@ -232,18 +235,25 @@ struct ComputePipelineCreateInfo { Gfx::PComputeShader computeShader = nullptr; Gfx::PPipelineLayout pipelineLayout = nullptr; }; +struct RayTracingHitGroup { + PClosestHitShader closestHitShader; + PAnyHitShader anyHitShader; + PIntersectionShader intersectionShader; + Array parameters; +}; struct RayTracingPipelineCreateInfo { PPipelineLayout pipelineLayout = nullptr; PRayGenShader rayGenShader = nullptr; - Array closestHitShaders; - Array anyHitShaders; - Array intersectionShaders; + Array hitgroups; Array missShaders; Array callableShaders; }; struct BottomLevelASCreateInfo { PMesh mesh; }; -struct TopLevelASCreateInfo {}; +struct TopLevelASCreateInfo { + Array instances; + Array bottomLevelStructures; +}; } // namespace Gfx } // namespace Seele diff --git a/src/Engine/Graphics/Mesh.cpp b/src/Engine/Graphics/Mesh.cpp index 65fd70b..f5a61a0 100644 --- a/src/Engine/Graphics/Mesh.cpp +++ b/src/Engine/Graphics/Mesh.cpp @@ -2,7 +2,6 @@ #include "Asset/AssetRegistry.h" #include "Graphics/Graphics.h" - using namespace Seele; Mesh::Mesh() {} @@ -36,4 +35,7 @@ void Mesh::load(ArchiveBuffer& buffer) { id = vertexData->allocateVertexData(vertexCount); vertexData->loadMesh(id, indices, meshlets); vertexData->deserializeMesh(id, buffer); + blas = buffer.getGraphics()->createBottomLevelAccelerationStructure(Gfx::BottomLevelASCreateInfo{ + .mesh = this, + }); } diff --git a/src/Engine/Graphics/RayTracing.cpp b/src/Engine/Graphics/RayTracing.cpp index 1d4120f..454277e 100644 --- a/src/Engine/Graphics/RayTracing.cpp +++ b/src/Engine/Graphics/RayTracing.cpp @@ -3,7 +3,7 @@ using namespace Seele::Gfx; -RayTracingPipeline::RayTracingPipeline(Gfx::PPipelineLayout layout) {} +RayTracingPipeline::RayTracingPipeline(Gfx::PPipelineLayout layout) : layout(layout) {} RayTracingPipeline::~RayTracingPipeline() {} diff --git a/src/Engine/Graphics/RayTracing.h b/src/Engine/Graphics/RayTracing.h index 740da1f..adcc474 100644 --- a/src/Engine/Graphics/RayTracing.h +++ b/src/Engine/Graphics/RayTracing.h @@ -4,8 +4,7 @@ namespace Seele { namespace Gfx { DECLARE_REF(PipelineLayout) -class RayTracingPipeline -{ +class RayTracingPipeline { public: RayTracingPipeline(PPipelineLayout layout); virtual ~RayTracingPipeline(); @@ -18,7 +17,7 @@ DEFINE_REF(RayTracingPipeline) class BottomLevelAS { public: BottomLevelAS(); - ~BottomLevelAS(); + virtual ~BottomLevelAS(); private: }; @@ -26,7 +25,7 @@ DEFINE_REF(BottomLevelAS) class TopLevelAS { public: TopLevelAS(); - ~TopLevelAS(); + virtual ~TopLevelAS(); private: }; diff --git a/src/Engine/Graphics/RenderPass/BasePass.cpp b/src/Engine/Graphics/RenderPass/BasePass.cpp index a869028..dcb9deb 100644 --- a/src/Engine/Graphics/RenderPass/BasePass.cpp +++ b/src/Engine/Graphics/RenderPass/BasePass.cpp @@ -472,17 +472,19 @@ void BasePass::createRenderPass() { debugPipelineLayout = graphics->createPipelineLayout("DebugPassLayout"); debugPipelineLayout->addDescriptorLayout(viewParamsLayout); - ShaderCreateInfo createInfo = { + ShaderCompilationInfo createInfo = { .name = "DebugVertex", - .mainModule = "Debug", - .entryPoint = "vertexMain", + .modules = {"Debug"}, + .entryPoints = + { + {"vertexMain", "Debug"}, + {"fragmentMain", "Debug"}, + }, .rootSignature = debugPipelineLayout, }; - debugVertexShader = graphics->createVertexShader(createInfo); - - createInfo.name = "DebugFragment"; - createInfo.entryPoint = "fragmentMain"; - debugFragmentShader = graphics->createFragmentShader(createInfo); + graphics->beginShaderCompilation(createInfo); + debugVertexShader = graphics->createVertexShader({0}); + debugFragmentShader = graphics->createFragmentShader({1}); debugPipelineLayout->create(); VertexInputStateCreateInfo inputCreate = { @@ -578,17 +580,15 @@ void BasePass::createRenderPass() { pipelineLayout->addDescriptorLayout(skyboxDataLayout); pipelineLayout->addDescriptorLayout(textureLayout); - ShaderCreateInfo createInfo = { + ShaderCompilationInfo createInfo = { .name = "SkyboxVertex", - .mainModule = "Skybox", - .entryPoint = "vertexMain", + .modules = {"Skybox"}, + .entryPoints = {{"vertexMain", "Skybox"}, {"fragmentMain", "Skybox"}}, .rootSignature = pipelineLayout, }; - vertexShader = graphics->createVertexShader(createInfo); - - createInfo.name = "SkyboxFragment"; - createInfo.entryPoint = "fragmentMain"; - fragmentShader = graphics->createFragmentShader(createInfo); + graphics->beginShaderCompilation(createInfo); + vertexShader = graphics->createVertexShader({0}); + fragmentShader = graphics->createFragmentShader({1}); pipelineLayout->create(); diff --git a/src/Engine/Graphics/RenderPass/DepthCullingPass.cpp b/src/Engine/Graphics/RenderPass/DepthCullingPass.cpp index c724db4..ed887f9 100644 --- a/src/Engine/Graphics/RenderPass/DepthCullingPass.cpp +++ b/src/Engine/Graphics/RenderPass/DepthCullingPass.cpp @@ -65,9 +65,7 @@ DepthCullingPass::DepthCullingPass(Gfx::PGraphics graphics, PScene scene) : Rend DepthCullingPass::~DepthCullingPass() {} -void DepthCullingPass::beginFrame(const Component::Camera& cam) { - RenderPass::beginFrame(cam); -} +void DepthCullingPass::beginFrame(const Component::Camera& cam) { RenderPass::beginFrame(cam); } void DepthCullingPass::render() { query->beginQuery(); @@ -231,14 +229,15 @@ void DepthCullingPass::publishOutputs() { }; depthMipBuffer = graphics->createShaderBuffer(depthMipInfo); - ShaderCreateInfo mipComputeInfo = { + ShaderCompilationInfo mipComputeInfo = { .name = "DepthMipCompute", - .mainModule = "DepthMipGen", - .entryPoint = "initialReduce", + .modules = {"DepthMipGen"}, + .entryPoints = {{"initialReduce", "DepthMipGen"}, {"reduceLevel", "DepthMipGen"}}, .rootSignature = depthComputeLayout, }; - depthInitialReduceShader = graphics->createComputeShader(mipComputeInfo); + graphics->beginShaderCompilation(mipComputeInfo); + depthInitialReduceShader = graphics->createComputeShader({0}); depthComputeLayout->create(); Gfx::ComputePipelineCreateInfo pipelineCreateInfo = { @@ -246,10 +245,7 @@ void DepthCullingPass::publishOutputs() { .pipelineLayout = depthComputeLayout, }; depthInitialReduce = graphics->createComputePipeline(pipelineCreateInfo); - - mipComputeInfo.entryPoint = "reduceLevel"; - - depthMipGenShader = graphics->createComputeShader(mipComputeInfo); + depthMipGenShader = graphics->createComputeShader({1}); pipelineCreateInfo.computeShader = depthMipGenShader; diff --git a/src/Engine/Graphics/RenderPass/LightCullingPass.cpp b/src/Engine/Graphics/RenderPass/LightCullingPass.cpp index 703b554..fc5c50f 100644 --- a/src/Engine/Graphics/RenderPass/LightCullingPass.cpp +++ b/src/Engine/Graphics/RenderPass/LightCullingPass.cpp @@ -144,13 +144,14 @@ void LightCullingPass::publishOutputs() { cullingLayout->addDescriptorLayout(cullingDescriptorLayout); cullingLayout->addDescriptorLayout(lightEnv->getDescriptorLayout()); - ShaderCreateInfo createInfo = { + ShaderCompilationInfo createInfo = { .name = "Culling", - .mainModule = "LightCulling", - .entryPoint = "cullLights", + .modules = {"LightCulling"}, + .entryPoints = {{"cullLights", "LightCulling"}}, .rootSignature = cullingLayout, }; - cullingShader = graphics->createComputeShader(createInfo); + graphics->beginShaderCompilation(createInfo); + cullingShader = graphics->createComputeShader({0}); cullingLayout->create(); Gfx::ComputePipelineCreateInfo pipelineInfo; @@ -166,14 +167,15 @@ void LightCullingPass::publishOutputs() { cullingEnableLayout->addDescriptorLayout(cullingDescriptorLayout); cullingEnableLayout->addDescriptorLayout(lightEnv->getDescriptorLayout()); - ShaderCreateInfo createInfo = { + ShaderCompilationInfo createInfo = { .name = "Culling", - .mainModule = "LightCulling", - .entryPoint = "cullLights", + .modules = {"LightCulling"}, + .entryPoints = {{"cullLights", "LightCulling"}}, .rootSignature = cullingEnableLayout, }; createInfo.defines["LIGHT_CULLING"] = "1"; - cullingEnabledShader = graphics->createComputeShader(createInfo); + graphics->beginShaderCompilation(createInfo); + cullingEnabledShader = graphics->createComputeShader({0}); cullingEnableLayout->create(); Gfx::ComputePipelineCreateInfo pipelineInfo; @@ -265,14 +267,14 @@ void LightCullingPass::setupFrustums() { frustumLayout = graphics->createPipelineLayout("FrustumLayout"); frustumLayout->addDescriptorLayout(viewParamsLayout); frustumLayout->addDescriptorLayout(dispatchParamsLayout); - ShaderCreateInfo createInfo = { + ShaderCompilationInfo createInfo = { .name = "Frustum", - .mainModule = "ComputeFrustums", - .entryPoint = "computeFrustums", + .modules = {"ComputeFrustums"}, + .entryPoints = {{"computeFrustums", "ComputeFrustums"}}, .rootSignature = frustumLayout, }; - std::cout << "Compiling frustumShader" << std::endl; - frustumShader = graphics->createComputeShader(createInfo); + graphics->beginShaderCompilation(createInfo); + frustumShader = graphics->createComputeShader({0}); // Have to compile shader before finalizing layout as parameters get mapped later frustumLayout->create(); dispatchParamsLayout->create(); diff --git a/src/Engine/Graphics/RenderPass/RayTracingPass.cpp b/src/Engine/Graphics/RenderPass/RayTracingPass.cpp index e69de29..143e231 100644 --- a/src/Engine/Graphics/RenderPass/RayTracingPass.cpp +++ b/src/Engine/Graphics/RenderPass/RayTracingPass.cpp @@ -0,0 +1,125 @@ +#include "RayTracingPass.h" +#include "Graphics/RayTracing.h" +#include "Graphics/Shader.h" +#include "Graphics/StaticMeshVertexData.h" +#include "RenderPass.h" + +using namespace Seele; + +RayTracingPass::RayTracingPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics, scene) { + paramsLayout = graphics->createDescriptorLayout("pRayTracingParams"); + paramsLayout->addDescriptorBinding(Gfx::DescriptorBinding{ + .binding = 0, + .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, + }); + paramsLayout->addDescriptorBinding(Gfx::DescriptorBinding{ + .binding = 1, + .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_IMAGE, + }); + paramsLayout->addDescriptorBinding(Gfx::DescriptorBinding{ + .binding = 2, + .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER, + }); + paramsLayout->create(); + pipelineLayout = graphics->createPipelineLayout("RayTracing"); + pipelineLayout->addDescriptorLayout(viewParamsLayout); + pipelineLayout->addDescriptorLayout(Material::getDescriptorLayout()); + pipelineLayout->addDescriptorLayout(paramsLayout); + pipelineLayout->addDescriptorLayout(scene->getLightEnvironment()->getDescriptorLayout()); + graphics->getShaderCompiler()->registerRenderPass("RayTracing", Gfx::PassConfig{ + .baseLayout = pipelineLayout, + .mainFile = "ClosestHit", + .useMaterial = true, + .rayTracing = true, + }); +} + +void RayTracingPass::beginFrame(const Component::Camera& cam) { RenderPass::beginFrame(cam); } + +void RayTracingPass::render() { + Gfx::ORenderCommand command = graphics->createRenderCommand("RayTracing"); + Array hitgroups; + Array accelerationStructures; + Array instanceData; + + for (VertexData* vertexData : VertexData::getList()) { + auto& materialData = vertexData->getMaterialData(); + + for (auto& matData : materialData) { + if (matData.instances.size() == 0) + continue; + PMaterial mat = matData.material; + + Gfx::ShaderPermutation permutation = graphics->getShaderCompiler()->getTemplate("RayTracing"); + permutation.setMaterial(mat->getName()); + permutation.setVertexData(vertexData->getTypeName()); + + const Gfx::ShaderCollection* collection = graphics->getShaderCompiler()->findShaders(Gfx::PermutationId(permutation)); + assert(collection != nullptr); + + for (auto& inst : matData.instances) { + for (uint32 i = 0; i < inst.instanceData.size(); ++i) { + Gfx::RayTracingHitGroup hitgroup = { + .closestHitShader = collection->closestHitShader, + .anyHitShader = nullptr, + .intersectionShader = nullptr, + }; + hitgroup.parameters.resize(sizeof(VertexData::DrawCallOffsets)); + std::memcpy(hitgroup.parameters.data(), &inst.offsets, sizeof(VertexData::DrawCallOffsets)); + hitgroups.add(hitgroup); + + instanceData.add(inst.instanceData[i]); + accelerationStructures.add(inst.rayTracingData[i]); + } + } + } + } + Gfx::OTopLevelAS tlas = graphics->createTopLevelAccelerationStructure(Gfx::TopLevelASCreateInfo{ + .instances = instanceData, + .bottomLevelStructures = accelerationStructures, + }); + Gfx::PDescriptorSet desc = paramsLayout->allocateDescriptorSet(); + desc->updateAccelerationStructure(0, tlas); + desc->updateTexture(1, Gfx::PTexture2D(texture)); + desc->updateBuffer(2, StaticMeshVertexData::getInstance()->getIndexBuffer()); + desc->writeChanges(); + + Gfx::PRayTracingPipeline pipeline = graphics->createRayTracingPipeline(Gfx::RayTracingPipelineCreateInfo{ + .pipelineLayout = pipelineLayout, + .rayGenShader = raygen, + .hitgroups = hitgroups, + .missShaders = {miss}, + }); + + command->bindPipeline(pipeline); + command->bindDescriptor({viewParamsSet, StaticMeshVertexData::getInstance()->getInstanceDataSet(), + StaticMeshVertexData::getInstance()->getVertexDataSet(), Material::getDescriptorSet(), + scene->getLightEnvironment()->getDescriptorSet()}); + command->traceRays(texture->getWidth(), texture->getHeight(), 1); + Array commands; + commands.add(std::move(command)); + graphics->executeCommands(std::move(commands)); +} + +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, + }); +} + +void RayTracingPass::createRenderPass() {} diff --git a/src/Engine/Graphics/RenderPass/RayTracingPass.h b/src/Engine/Graphics/RenderPass/RayTracingPass.h index de8ee45..d264966 100644 --- a/src/Engine/Graphics/RenderPass/RayTracingPass.h +++ b/src/Engine/Graphics/RenderPass/RayTracingPass.h @@ -1,4 +1,5 @@ #pragma once +#include "Graphics/Graphics.h" #include "RenderPass.h" namespace Seele { @@ -14,5 +15,11 @@ class RayTracingPass : public RenderPass { virtual void createRenderPass() override; private: + Gfx::PRayGenShader raygen; + Gfx::PMissShader miss; + Gfx::ODescriptorLayout paramsLayout; + Gfx::OPipelineLayout pipelineLayout; + Gfx::OTexture2D texture; + }; } // namespace Seele \ No newline at end of file diff --git a/src/Engine/Graphics/RenderPass/RenderPass.cpp b/src/Engine/Graphics/RenderPass/RenderPass.cpp index 13366af..2ffe416 100644 --- a/src/Engine/Graphics/RenderPass/RenderPass.cpp +++ b/src/Engine/Graphics/RenderPass/RenderPass.cpp @@ -3,7 +3,6 @@ using namespace Seele; RenderPass::RenderPass(Gfx::PGraphics graphics, PScene scene) : graphics(graphics), scene(scene) { - viewParamsLayout = graphics->createDescriptorLayout("pViewParams"); viewParamsLayout->addDescriptorBinding(Gfx::DescriptorBinding{ .binding = 0, diff --git a/src/Engine/Graphics/RenderPass/TextPass.cpp b/src/Engine/Graphics/RenderPass/TextPass.cpp index d68831c..dee17f0 100644 --- a/src/Engine/Graphics/RenderPass/TextPass.cpp +++ b/src/Engine/Graphics/RenderPass/TextPass.cpp @@ -5,7 +5,6 @@ #include "Graphics/RenderTarget.h" #include "RenderGraph.h" - using namespace Seele; TextPass::TextPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics, scene) {} @@ -97,16 +96,15 @@ void TextPass::createRenderPass() { renderTarget = resources->requestRenderTarget("UIPASS_COLOR"); depthAttachment = resources->requestRenderTarget("UIPASS_DEPTH"); - ShaderCreateInfo createInfo = { + ShaderCompilationInfo createInfo = { .name = "TextVertex", - .mainModule = "TextPass", - .entryPoint = "vertexMain", + .modules = {"TextPass"}, + .entryPoints = {{"vertexMain", "TextPass"}, {"fragmentMain", "TextFragment"}}, }; - vertexShader = graphics->createVertexShader(createInfo); + graphics->beginShaderCompilation(createInfo); + vertexShader = graphics->createVertexShader({0}); + fragmentShader = graphics->createFragmentShader({1}); - createInfo.name = "TextFragment"; - createInfo.entryPoint = "fragmentMain"; - fragmentShader = graphics->createFragmentShader(createInfo); generalLayout = graphics->createDescriptorLayout("pRender"); generalLayout->addDescriptorBinding(Gfx::DescriptorBinding{ .binding = 0, diff --git a/src/Engine/Graphics/RenderPass/UIPass.cpp b/src/Engine/Graphics/RenderPass/UIPass.cpp index c1ebc2e..94b63a7 100644 --- a/src/Engine/Graphics/RenderPass/UIPass.cpp +++ b/src/Engine/Graphics/RenderPass/UIPass.cpp @@ -5,7 +5,6 @@ #include "Graphics/RenderTarget.h" #include "RenderGraph.h" - using namespace Seele; UIPass::UIPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics, scene) {} @@ -80,16 +79,18 @@ void UIPass::publishOutputs() { } void UIPass::createRenderPass() { - ShaderCreateInfo createInfo = { + ShaderCompilationInfo createInfo = { .name = "UIVertex", - .mainModule = "UIPass", - .entryPoint = "vertexMain", + .modules = {"UIPass"}, + .entryPoints = + { + {"vertexMain", "UIPass"}, + {"fragmentMain", "UIFragment"}, + }, }; - vertexShader = graphics->createVertexShader(createInfo); - - createInfo.name = "UIFragment"; - createInfo.entryPoint = "fragmentMain"; - fragmentShader = graphics->createFragmentShader(createInfo); + graphics->beginShaderCompilation(createInfo); + vertexShader = graphics->createVertexShader({0}); + fragmentShader = graphics->createFragmentShader({1}); descriptorLayout = graphics->createDescriptorLayout("pParams"); descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{ diff --git a/src/Engine/Graphics/RenderPass/VisibilityPass.cpp b/src/Engine/Graphics/RenderPass/VisibilityPass.cpp index e7dc168..bcdf919 100644 --- a/src/Engine/Graphics/RenderPass/VisibilityPass.cpp +++ b/src/Engine/Graphics/RenderPass/VisibilityPass.cpp @@ -59,21 +59,22 @@ void VisibilityPass::publishOutputs() { visibilityDescriptor->create(); visibilityLayout = graphics->createPipelineLayout("VisibilityLayout"); - visibilityLayout->addDescriptorLayout(viewParamsLayout); visibilityLayout->addDescriptorLayout(visibilityDescriptor); + visibilityLayout->addDescriptorLayout(viewParamsLayout); - ShaderCreateInfo createInfo = { + ShaderCompilationInfo createInfo = { .name = "Visibility", - .mainModule = "VisibilityCompute", - .entryPoint = "computeMain", + .modules = {"VisibilityCompute"}, + .entryPoints = {{"computeMain", "VisibilityCompute"}}, .rootSignature = visibilityLayout, }; - visibilityShader = graphics->createComputeShader(createInfo); + graphics->beginShaderCompilation(createInfo); + visibilityShader = graphics->createComputeShader({0}); visibilityLayout->create(); Gfx::ComputePipelineCreateInfo pipelineInfo; pipelineInfo.computeShader = visibilityShader; - pipelineInfo.pipelineLayout = std::move(visibilityLayout); + pipelineInfo.pipelineLayout = visibilityLayout; visibilityPipeline = graphics->createComputePipeline(std::move(pipelineInfo)); cullingBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{ diff --git a/src/Engine/Graphics/Shader.cpp b/src/Engine/Graphics/Shader.cpp index 37f9be5..83e83b4 100644 --- a/src/Engine/Graphics/Shader.cpp +++ b/src/Engine/Graphics/Shader.cpp @@ -35,6 +35,8 @@ ShaderPermutation ShaderCompiler::getTemplate(std::string name) { PassConfig& pass = passes[name]; if (pass.useMeshShading) { permutation.setMeshFile(pass.mainFile); + } else if (pass.rayTracing) { + permutation.setRayTracingFile(pass.mainFile); } else { permutation.setVertexFile(pass.mainFile); } @@ -49,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); @@ -65,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); @@ -80,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) { @@ -99,11 +101,11 @@ void ShaderCompiler::createShaders(ShaderPermutation permutation, Gfx::OPipeline ShaderCollection collection; collection.pipelineLayout = std::move(layout); - ShaderCreateInfo createInfo; + ShaderCompilationInfo createInfo; createInfo.name = fmt::format("Material {0}", permutation.materialName); createInfo.rootSignature = collection.pipelineLayout; if (std::strlen(permutation.materialName) > 0) { - createInfo.additionalModules.add(permutation.materialName); + createInfo.modules.add(permutation.materialName); createInfo.defines["MATERIAL_FILE_NAME"] = permutation.materialName; } if (permutation.positionOnly) { @@ -116,27 +118,42 @@ void ShaderCompiler::createShaders(ShaderPermutation permutation, Gfx::OPipeline createInfo.defines["VISIBILITY"] = "1"; } createInfo.typeParameter.add({Pair("IVertexData", permutation.vertexDataName)}); - createInfo.additionalModules.add(permutation.vertexDataName); + createInfo.modules.add(permutation.vertexDataName); if (permutation.useMeshShading) { if (permutation.hasTaskShader) { - createInfo.mainModule = permutation.taskFile; - createInfo.entryPoint = "taskMain"; - collection.taskShader = graphics->createTaskShader(createInfo); + createInfo.entryPoints.add({"taskMain", permutation.taskFile}); + createInfo.modules.add(permutation.taskFile); } - createInfo.mainModule = permutation.vertexMeshFile; - createInfo.entryPoint = "meshMain"; - collection.meshShader = graphics->createMeshShader(createInfo); + createInfo.entryPoints.add({"meshMain", permutation.vertexMeshFile}); + createInfo.modules.add(permutation.vertexMeshFile); + } else if (permutation.rayTracing) { + createInfo.defines["RAY_TRACING"] = "1"; + createInfo.entryPoints.add({"closesthit", permutation.vertexMeshFile}); + createInfo.modules.add(permutation.vertexMeshFile); } else { - createInfo.mainModule = permutation.vertexMeshFile; - createInfo.entryPoint = "vertexMain"; - collection.vertexShader = graphics->createVertexShader(createInfo); + createInfo.entryPoints.add({"vertexMain", permutation.vertexMeshFile}); + createInfo.modules.add(permutation.vertexMeshFile); + } + if (permutation.hasFragment) { + createInfo.entryPoints.add({"fragmentMain", permutation.fragmentFile}); + createInfo.modules.add(permutation.fragmentFile); } + graphics->beginShaderCompilation(createInfo); + uint32 shaderIndex = 0; + if (permutation.useMeshShading) { + if (permutation.hasTaskShader) { + collection.taskShader = graphics->createTaskShader({shaderIndex++}); + } + collection.meshShader = graphics->createMeshShader({shaderIndex++}); + } else if (permutation.rayTracing) { + collection.closestHitShader = graphics->createClosestHitShader({shaderIndex++}); + } else { + collection.vertexShader = graphics->createVertexShader({shaderIndex++}); + } if (permutation.hasFragment) { - createInfo.mainModule = permutation.fragmentFile; - createInfo.entryPoint = "fragmentMain"; - collection.fragmentShader = graphics->createFragmentShader(createInfo); + collection.fragmentShader = graphics->createFragmentShader({shaderIndex++}); } collection.pipelineLayout->create(); { diff --git a/src/Engine/Graphics/Shader.h b/src/Engine/Graphics/Shader.h index 46be4f8..7c455e9 100644 --- a/src/Engine/Graphics/Shader.h +++ b/src/Engine/Graphics/Shader.h @@ -4,7 +4,6 @@ #include "Resources.h" #include "VertexData.h" - namespace Seele { namespace Gfx { @@ -100,6 +99,7 @@ struct ShaderPermutation { uint8 positionOnly; uint8 depthCulling; uint8 visibilityPass; + uint8 rayTracing; // TODO: lightmapping etc ShaderPermutation() { std::memset(this, 0, sizeof(ShaderPermutation)); } void setTaskFile(std::string_view name) { @@ -117,6 +117,11 @@ struct ShaderPermutation { useMeshShading = 1; strncpy(vertexMeshFile, name.data(), sizeof(vertexMeshFile)); } + void setRayTracingFile(std::string_view name) { + std::memset(vertexMeshFile, 0, sizeof(vertexMeshFile)); + rayTracing = true; + strncpy(vertexMeshFile, name.data(), sizeof(vertexMeshFile)); + } void setFragmentFile(std::string_view name) { std::memset(fragmentFile, 0, sizeof(fragmentFile)); hasFragment = 1; @@ -149,6 +154,7 @@ struct ShaderCollection { OTaskShader taskShader; OMeshShader meshShader; OFragmentShader fragmentShader; + OClosestHitShader closestHitShader; }; struct PassConfig { @@ -161,6 +167,7 @@ struct PassConfig { bool hasTaskShader = false; bool useMaterial = false; bool useVisibility = false; + bool rayTracing = false; }; class ShaderCompiler { public: diff --git a/src/Engine/Graphics/VertexData.cpp b/src/Engine/Graphics/VertexData.cpp index 00f3d04..07cd197 100644 --- a/src/Engine/Graphics/VertexData.cpp +++ b/src/Engine/Graphics/VertexData.cpp @@ -19,6 +19,7 @@ void VertexData::resetMeshData() { std::unique_lock l(materialDataLock); transparentInstanceData.clear(); transparentMeshData.clear(); + rayTracingScene.clear(); for (auto& mat : materialData) { for (auto& inst : mat.instances) { inst.instanceData.clear(); @@ -74,9 +75,11 @@ void VertexData::updateMesh(entt::entity id, uint32 meshIndex, PMesh mesh, Compo } BatchedDrawCall& matInstanceData = matData.instances[referencedInstance->getId()]; matInstanceData.materialInstance = referencedInstance; - - matInstanceData.instanceData.add(inst); + auto [instanceId, meshletOffset] = getCullingMapping(id, meshIndex, data.numMeshlets); + + matInstanceData.rayTracingData.add(mesh->blas); + matInstanceData.instanceData.add(inst); matInstanceData.instanceMeshData.add(data); matInstanceData.cullingOffsets.add(meshletOffset); referencedInstance->updateDescriptor(); @@ -140,6 +143,7 @@ void VertexData::createDescriptors() { cullingOffsets.add(instance.cullingOffsets[i]); instanceData.add(instance.instanceData[i]); instanceMeshData.add(instance.instanceMeshData[i]); + rayTracingScene.add(instance.rayTracingData[i]); // instance.numMeshlets += instance.instanceMeshData[i].numMeshlets; // cullingOffsets.add(numMeshlets); } diff --git a/src/Engine/Graphics/VertexData.h b/src/Engine/Graphics/VertexData.h index ae9e667..fcf5526 100644 --- a/src/Engine/Graphics/VertexData.h +++ b/src/Engine/Graphics/VertexData.h @@ -37,6 +37,7 @@ class VertexData { DrawCallOffsets offsets; Array instanceData; Array instanceMeshData; + Array rayTracingData; Array cullingOffsets; }; struct MaterialData { @@ -70,6 +71,7 @@ class VertexData { Gfx::PDescriptorSet getInstanceDataSet() { return descriptorSet; } 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]; } uint64 getIndicesOffset(uint32 meshletIndex) { return meshlets[meshletIndex].indicesOffset; } uint64 getNumInstances() const { return instanceData.size(); } @@ -142,6 +144,8 @@ class VertexData { Array instanceMeshData; Gfx::OShaderBuffer instanceMeshDataBuffer; + + Array rayTracingScene; Array transparentInstanceData; Gfx::OShaderBuffer transparentInstanceDataBuffer; diff --git a/src/Engine/Graphics/Vulkan/Command.cpp b/src/Engine/Graphics/Vulkan/Command.cpp index 92731fe..90c123a 100644 --- a/src/Engine/Graphics/Vulkan/Command.cpp +++ b/src/Engine/Graphics/Vulkan/Command.cpp @@ -4,6 +4,7 @@ #include "Framebuffer.h" #include "Graphics.h" #include "Pipeline.h" +#include "RayTracing.h" #include "RenderPass.h" #include "Window.h" @@ -178,9 +179,7 @@ void RenderCommand::begin(PRenderPass renderPass, PFramebuffer framebuffer, VkQu ready = false; VkCommandBufferInheritanceInfo inheritanceInfo = { .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, - .renderPass = renderPass->getHandle(), .subpass = 0, - .framebuffer = framebuffer->getHandle(), .occlusionQueryEnable = 0, .queryFlags = 0, .pipelineStatistics = pipelineFlags, @@ -188,9 +187,13 @@ void RenderCommand::begin(PRenderPass renderPass, PFramebuffer framebuffer, VkQu VkCommandBufferBeginInfo beginInfo = { .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, .pNext = nullptr, - .flags = VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, .pInheritanceInfo = &inheritanceInfo, }; + if (renderPass != nullptr || framebuffer != nullptr) { + inheritanceInfo.renderPass = renderPass->getHandle(); + inheritanceInfo.framebuffer = framebuffer->getHandle(); + beginInfo.flags = VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT; + } VK_CHECK(vkBeginCommandBuffer(handle, &beginInfo)); } @@ -229,6 +232,12 @@ void RenderCommand::bindPipeline(Gfx::PGraphicsPipeline gfxPipeline) { pipeline->bind(handle); } +void RenderCommand::bindPipeline(Gfx::PRayTracingPipeline gfxPipeline) { + assert(threadId == std::this_thread::get_id()); + rtPipeline = gfxPipeline.cast(); + rtPipeline->bind(handle); +} + void RenderCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet, Array dynamicOffsets) { assert(threadId == std::this_thread::get_id()); auto descriptor = descriptorSet.cast(); @@ -243,15 +252,16 @@ void RenderCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet, ArraygetHandle(); - vkCmdBindDescriptorSets(handle, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->getLayout(), - pipeline->getPipelineLayout()->findParameter(descriptorSet->getName()), 1, &setHandle, dynamicOffsets.size(), - dynamicOffsets.data()); + 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()); } void RenderCommand::bindDescriptor(const Array& descriptorSets, Array dynamicOffsets) { assert(threadId == std::this_thread::get_id()); VkDescriptorSet* sets = new VkDescriptorSet[descriptorSets.size()]; std::memset(sets, 0, sizeof(VkDescriptorSet) * descriptorSets.size()); + Gfx::PPipelineLayout layout = pipeline != nullptr ? pipeline->getPipelineLayout() : rtPipeline->getPipelineLayout(); for (uint32 i = 0; i < descriptorSets.size(); ++i) { auto descriptorSet = descriptorSets[i].cast(); assert(descriptorSet->writeDescriptors.size() == 0); @@ -267,7 +277,7 @@ void RenderCommand::bindDescriptor(const Array& descriptorS } } } - sets[pipeline->getPipelineLayout()->findParameter(descriptorSet->getName())] = descriptorSet->getHandle(); + sets[layout->findParameter(descriptorSet->getName())] = descriptorSet->getHandle(); } vkCmdBindDescriptorSets(handle, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->getLayout(), 0, (uint32)descriptorSets.size(), sets, dynamicOffsets.size(), dynamicOffsets.data()); @@ -320,7 +330,12 @@ void RenderCommand::drawMeshIndirect(Gfx::PShaderBuffer buffer, uint64 offset, u vkCmdDrawMeshTasksIndirectEXT(handle, buffer.cast()->getHandle(), offset, drawCount, stride); } -void RenderCommand::traceRays() {} +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); +} ComputeCommand::ComputeCommand(PGraphics graphics, VkCommandPool cmdPool) : graphics(graphics), owner(cmdPool) { VkCommandBufferAllocateInfo allocInfo = { diff --git a/src/Engine/Graphics/Vulkan/Command.h b/src/Engine/Graphics/Vulkan/Command.h index bef3865..acb764e 100644 --- a/src/Engine/Graphics/Vulkan/Command.h +++ b/src/Engine/Graphics/Vulkan/Command.h @@ -65,6 +65,7 @@ DEFINE_REF(Command) DECLARE_REF(GraphicsPipeline) DECLARE_REF(ComputePipeline) +DECLARE_REF(RayTracingPipeline) class RenderCommand : public Gfx::RenderCommand { public: RenderCommand(PGraphics graphics, VkCommandPool cmdPool); @@ -76,6 +77,7 @@ class RenderCommand : public Gfx::RenderCommand { bool isReady(); virtual void setViewport(Gfx::PViewport viewport) override; virtual void bindPipeline(Gfx::PGraphicsPipeline pipeline) override; + virtual void bindPipeline(Gfx::PRayTracingPipeline pipeline) override; virtual void bindDescriptor(Gfx::PDescriptorSet descriptorSet, Array dynamicOffsets) override; virtual void bindDescriptor(const Array& descriptorSets, Array dynamicOffsets) override; virtual void bindVertexBuffer(const Array& buffers) override; @@ -85,11 +87,11 @@ class RenderCommand : public Gfx::RenderCommand { virtual void drawIndexed(uint32 indexCount, uint32 instanceCount, int32 firstIndex, uint32 vertexOffset, uint32 firstInstance) override; virtual void drawMesh(uint32 groupX, uint32 groupY, uint32 groupZ) override; virtual void drawMeshIndirect(Gfx::PShaderBuffer buffer, uint64 offset, uint32 drawCount, uint32 stride) override; - - virtual void traceRays(); + virtual void traceRays(uint32 width, uint32 height, uint32 depth) override; private: PGraphicsPipeline pipeline; + PRayTracingPipeline rtPipeline; bool ready; Array boundResources; VkViewport currentViewport; diff --git a/src/Engine/Graphics/Vulkan/Descriptor.cpp b/src/Engine/Graphics/Vulkan/Descriptor.cpp index a02cd5d..8626ba1 100644 --- a/src/Engine/Graphics/Vulkan/Descriptor.cpp +++ b/src/Engine/Graphics/Vulkan/Descriptor.cpp @@ -4,7 +4,7 @@ #include "Command.h" #include "Graphics.h" #include "Texture.h" - +#include "RayTracing.h" using namespace Seele; using namespace Seele::Vulkan; @@ -62,21 +62,17 @@ DescriptorPool::DescriptorPool(PGraphics graphics, PDescriptorLayout layout) cachedHandles[i] = nullptr; } - uint32 perTypeSizes[VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT]; // TODO: FIX ENUM - std::memset(perTypeSizes, 0, sizeof(perTypeSizes)); + Map perTypeSizes; for (uint32 i = 0; i < layout->getBindings().size(); ++i) { auto& binding = layout->getBindings()[i]; - int typeIndex = binding.descriptorType; - perTypeSizes[typeIndex] += 512; + perTypeSizes[binding.descriptorType] += 512; } Array poolSizes; - for (uint32 i = 0; i < VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; ++i) { - if (perTypeSizes[i] > 0) { - VkDescriptorPoolSize size; - size.descriptorCount = perTypeSizes[i]; - size.type = (VkDescriptorType)i; - poolSizes.add(size); - } + for (const auto [type, num] : perTypeSizes) { + VkDescriptorPoolSize size; + size.descriptorCount = num; + size.type = cast(type); + poolSizes.add(size); } VkDescriptorPoolCreateInfo createInfo = { .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, @@ -227,6 +223,32 @@ void DescriptorSet::updateBuffer(uint32_t binding, Gfx::PShaderBuffer shaderBuff boundResources[binding][0] = vulkanBuffer->getAlloc(); } +void DescriptorSet::updateBuffer(uint32_t binding, Gfx::PIndexBuffer indexBuffer) { + PIndexBuffer vulkanBuffer = indexBuffer.cast(); + if (boundResources[binding][0] == vulkanBuffer->getAlloc()) { + return; + } + + bufferInfos.add(VkDescriptorBufferInfo{ + .buffer = vulkanBuffer->getHandle(), + .offset = 0, + .range = vulkanBuffer->getSize(), + }); + writeDescriptors.add(VkWriteDescriptorSet{ + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .pNext = nullptr, + .dstSet = setHandle, + .dstBinding = binding, + .dstArrayElement = 0, + .descriptorCount = 1, + .descriptorType = cast(layout->getBindings()[binding].descriptorType), + .pBufferInfo = &bufferInfos.back(), + }); + + boundResources[binding][0] = vulkanBuffer->getAlloc(); +} + + void DescriptorSet::updateBuffer(uint32_t binding, uint32 index, Gfx::PShaderBuffer shaderBuffer) { PShaderBuffer vulkanBuffer = shaderBuffer.cast(); if (boundResources[binding][index] == vulkanBuffer->getAlloc()) { @@ -429,6 +451,25 @@ 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, + }); + writeDescriptors.add(VkWriteDescriptorSet{ + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .pNext = &accelerationInfos.back(), + .dstSet = setHandle, + .dstBinding = binding, + .dstArrayElement = 0, + .descriptorCount = 1, + .descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, + }); +} void DescriptorSet::writeChanges() { if (writeDescriptors.size() > 0) { diff --git a/src/Engine/Graphics/Vulkan/Descriptor.h b/src/Engine/Graphics/Vulkan/Descriptor.h index 8a3aadd..e23982d 100644 --- a/src/Engine/Graphics/Vulkan/Descriptor.h +++ b/src/Engine/Graphics/Vulkan/Descriptor.h @@ -48,15 +48,17 @@ class DescriptorSet : public Gfx::DescriptorSet, public CommandBoundResource { DescriptorSet(PGraphics graphics, PDescriptorPool owner); virtual ~DescriptorSet(); virtual void writeChanges() override; - virtual void updateBuffer(uint32_t binding, Gfx::PUniformBuffer uniformBuffer) override; - virtual void updateBuffer(uint32_t binding, Gfx::PShaderBuffer uniformBuffer) override; - virtual void updateBuffer(uint32_t binding, uint32 index, Gfx::PShaderBuffer uniformBuffer) override; - virtual void updateSampler(uint32_t binding, Gfx::PSampler samplerState) override; - virtual void updateSampler(uint32_t binding, uint32 dstArrayIndex, Gfx::PSampler samplerState) override; - virtual void updateTexture(uint32_t binding, Gfx::PTexture texture, Gfx::PSampler sampler = nullptr) override; + virtual void updateBuffer(uint32 binding, Gfx::PUniformBuffer uniformBuffer) override; + virtual void updateBuffer(uint32 binding, Gfx::PShaderBuffer uniformBuffer) override; + virtual void updateBuffer(uint32 binding, Gfx::PIndexBuffer uniformBuffer) override; + virtual void updateBuffer(uint32 binding, uint32 index, Gfx::PShaderBuffer uniformBuffer) override; + virtual void updateSampler(uint32 binding, Gfx::PSampler samplerState) override; + virtual void updateSampler(uint32 binding, uint32 dstArrayIndex, Gfx::PSampler samplerState) override; + virtual void updateTexture(uint32 binding, Gfx::PTexture texture, Gfx::PSampler sampler = nullptr) override; virtual void updateTexture(uint32 binding, uint32 dstArrayIndex, Gfx::PTexture texture) override; - virtual void updateTextureArray(uint32_t binding, Array texture) override; - virtual void updateSamplerArray(uint32_t binding, Array samplers) override; + virtual void updateTextureArray(uint32 binding, Array texture) override; + virtual void updateSamplerArray(uint32 binding, Array samplers) override; + virtual void updateAccelerationStructure(uint32 binding, Gfx::PTopLevelAS as) override; constexpr bool isCurrentlyInUse() const { return currentlyInUse; } constexpr void allocate() { currentlyInUse = true; } @@ -66,6 +68,7 @@ class DescriptorSet : public Gfx::DescriptorSet, public CommandBoundResource { private: List imageInfos; List bufferInfos; + List accelerationInfos; Array writeDescriptors; // contains the previously bound resources at every binding // since the layout is fixed, trying to bind a texture to a buffer diff --git a/src/Engine/Graphics/Vulkan/Enums.cpp b/src/Engine/Graphics/Vulkan/Enums.cpp index dfa1d8c..ea11d3b 100644 --- a/src/Engine/Graphics/Vulkan/Enums.cpp +++ b/src/Engine/Graphics/Vulkan/Enums.cpp @@ -29,12 +29,14 @@ VkDescriptorType Seele::Vulkan::cast(const Seele::Gfx::SeDescriptorType& descrip return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC; case SE_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: return VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; -#ifdef USE_EXTENSIONS - case SE_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT: - return VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT; + case SE_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK: + return VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK; + case SE_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR: + return VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; case SE_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV: return VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV; -#endif + case SE_DESCRIPTOR_TYPE_BLOCK_MATCH_IMAGE_QCOM: + return VK_DESCRIPTOR_TYPE_BLOCK_MATCH_IMAGE_QCOM; default: break; } @@ -43,7 +45,6 @@ VkDescriptorType Seele::Vulkan::cast(const Seele::Gfx::SeDescriptorType& descrip Seele::Gfx::SeDescriptorType Seele::Vulkan::cast(const VkDescriptorType& descriptorType) { switch (descriptorType) { - case VK_DESCRIPTOR_TYPE_SAMPLER: return SE_DESCRIPTOR_TYPE_SAMPLER; case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: @@ -66,12 +67,14 @@ Seele::Gfx::SeDescriptorType Seele::Vulkan::cast(const VkDescriptorType& descrip return SE_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC; case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: return SE_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; -#ifdef USE_EXTENSIONS - case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT: - return SE_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT; + case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK: + return SE_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK; + case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR: + return SE_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV: return SE_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV; -#endif + case VK_DESCRIPTOR_TYPE_BLOCK_MATCH_IMAGE_QCOM: + return SE_DESCRIPTOR_TYPE_BLOCK_MATCH_IMAGE_QCOM; default: throw std::logic_error("Not implemented"); } @@ -79,7 +82,6 @@ Seele::Gfx::SeDescriptorType Seele::Vulkan::cast(const VkDescriptorType& descrip VkShaderStageFlagBits Seele::Vulkan::cast(const Seele::Gfx::SeShaderStageFlagBits& stage) { switch (stage) { - case SE_SHADER_STAGE_VERTEX_BIT: return VK_SHADER_STAGE_VERTEX_BIT; case SE_SHADER_STAGE_TESSELLATION_CONTROL_BIT: diff --git a/src/Engine/Graphics/Vulkan/Graphics.cpp b/src/Engine/Graphics/Vulkan/Graphics.cpp index f7ef121..2f9b71e 100644 --- a/src/Engine/Graphics/Vulkan/Graphics.cpp +++ b/src/Engine/Graphics/Vulkan/Graphics.cpp @@ -15,6 +15,7 @@ #include "Shader.h" #include "Window.h" #include +#include "Graphics/slang-compile.h" #include #include @@ -35,6 +36,8 @@ PFN_vkCreateAccelerationStructureKHR createAccelerationStructure; PFN_vkCmdBuildAccelerationStructuresKHR cmdBuildAccelerationStructures; PFN_vkGetAccelerationStructureBuildSizesKHR getAccelerationStructureBuildSize; PFN_vkCreateRayTracingPipelinesKHR createRayTracingPipelines; +PFN_vkGetRayTracingShaderGroupHandlesKHR getRayTracingShaderGroupHandles; +PFN_vkCmdTraceRaysKHR cmdTraceRays; void vkCmdDrawMeshTasksEXT(VkCommandBuffer command, uint32 groupX, uint32 groupY, uint32 groupZ) { cmdDrawMeshTasks(command, groupX, groupY, groupZ); @@ -69,12 +72,26 @@ void vkGetAccelerationStructureBuildSizesKHR(VkDevice device, VkAccelerationStru } VkResult vkCreateRayTracingPipelinesKHR(VkDevice device, VkDeferredOperationKHR deferredOperation, VkPipelineCache pipelineCache, - uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoKHR* pCreateInfos, - const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines) -{ + uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoKHR* pCreateInfos, + const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines) { return createRayTracingPipelines(device, deferredOperation, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines); } +VkResult vkGetRayTracingShaderGroupHandlesKHR(VkDevice device, VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, + size_t dataSize, void* pData) { + return getRayTracingShaderGroupHandles(device, pipeline, firstGroup, groupCount, dataSize, pData); +} + +void vkCmdTraceRaysKHR(VkCommandBuffer commandBuffer, const VkStridedDeviceAddressRegionKHR* pRaygenShaderBindingTable, + const VkStridedDeviceAddressRegionKHR* pMissShaderBindingTable, + const VkStridedDeviceAddressRegionKHR* pHitShaderBindingTable, + const VkStridedDeviceAddressRegionKHR* pCallableShaderBindingTable, uint32_t width, uint32_t height, + uint32_t depth) { + cmdTraceRays(commandBuffer, pRaygenShaderBindingTable, pMissShaderBindingTable, pHitShaderBindingTable, pCallableShaderBindingTable, + width, height, depth); +} + + Graphics::Graphics() : instance(VK_NULL_HANDLE), handle(VK_NULL_HANDLE), physicalDevice(VK_NULL_HANDLE), callback(VK_NULL_HANDLE) {} Graphics::~Graphics() { @@ -142,9 +159,7 @@ void Graphics::beginRenderPass(Gfx::PRenderPass renderPass) { getGraphicsCommands()->getCommands()->beginRenderPass(rp, framebuffer); } -void Graphics::endRenderPass() { - getGraphicsCommands()->getCommands()->endRenderPass(); -} +void Graphics::endRenderPass() { getGraphicsCommands()->getCommands()->endRenderPass(); } void Graphics::waitDeviceIdle() { vkDeviceWaitIdle(handle); } @@ -174,6 +189,8 @@ 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); } + Gfx::OVertexShader Graphics::createVertexShader(const ShaderCreateInfo& createInfo) { OVertexShader shader = new VertexShader(this); shader->create(createInfo); @@ -208,6 +225,10 @@ Gfx::PGraphicsPipeline Graphics::createGraphicsPipeline(Gfx::MeshPipelineCreateI return pipelineCache->createPipeline(std::move(createInfo)); } +Gfx::PRayTracingPipeline Graphics::createRayTracingPipeline(Gfx::RayTracingPipelineCreateInfo createInfo) { + return pipelineCache->createPipeline(std::move(createInfo)); +} + Gfx::PComputePipeline Graphics::createComputePipeline(Gfx::ComputePipelineCreateInfo createInfo) { return pipelineCache->createPipeline(std::move(createInfo)); } @@ -704,4 +725,6 @@ void Graphics::createDevice(GraphicsInitializer initializer) { getAccelerationStructureBuildSize = (PFN_vkGetAccelerationStructureBuildSizesKHR)vkGetDeviceProcAddr(handle, "vkGetAccelerationStructureBuildSizesKHR"); createRayTracingPipelines = (PFN_vkCreateRayTracingPipelinesKHR)vkGetDeviceProcAddr(handle, "vkCreateRayTracingPipelinesKHR"); + getRayTracingShaderGroupHandles = + (PFN_vkGetRayTracingShaderGroupHandlesKHR)vkGetDeviceProcAddr(handle, "vkGetRayTracingShaderGroupHandlesKHR"); } diff --git a/src/Engine/Graphics/Vulkan/Graphics.h b/src/Engine/Graphics/Vulkan/Graphics.h index 722e211..25b600d 100644 --- a/src/Engine/Graphics/Vulkan/Graphics.h +++ b/src/Engine/Graphics/Vulkan/Graphics.h @@ -54,6 +54,7 @@ class Graphics : public Gfx::Graphics { virtual Gfx::ORenderCommand createRenderCommand(const std::string& name) override; virtual Gfx::OComputeCommand createComputeCommand(const std::string& name) override; + virtual void beginShaderCompilation(const ShaderCompilationInfo& compileInfo) override; virtual Gfx::OVertexShader createVertexShader(const ShaderCreateInfo& createInfo) override; virtual Gfx::OFragmentShader createFragmentShader(const ShaderCreateInfo& createInfo) override; virtual Gfx::OComputeShader createComputeShader(const ShaderCreateInfo& createInfo) override; @@ -61,6 +62,7 @@ class Graphics : public Gfx::Graphics { virtual Gfx::OMeshShader createMeshShader(const ShaderCreateInfo& createInfo) override; virtual Gfx::PGraphicsPipeline createGraphicsPipeline(Gfx::LegacyPipelineCreateInfo createInfo) override; virtual Gfx::PGraphicsPipeline createGraphicsPipeline(Gfx::MeshPipelineCreateInfo createInfo) override; + virtual Gfx::PRayTracingPipeline createRayTracingPipeline(Gfx::RayTracingPipelineCreateInfo createInfo) override; virtual Gfx::PComputePipeline createComputePipeline(Gfx::ComputePipelineCreateInfo createInfo) override; virtual Gfx::OSampler createSampler(const SamplerCreateInfo& createInfo) override; diff --git a/src/Engine/Graphics/Vulkan/PipelineCache.cpp b/src/Engine/Graphics/Vulkan/PipelineCache.cpp index 7780e11..1d62f58 100644 --- a/src/Engine/Graphics/Vulkan/PipelineCache.cpp +++ b/src/Engine/Graphics/Vulkan/PipelineCache.cpp @@ -5,6 +5,7 @@ #include "RenderPass.h" #include "Shader.h" #include +#include using namespace Seele; using namespace Seele::Vulkan; @@ -489,8 +490,8 @@ PRayTracingPipeline PipelineCache::createPipeline(Gfx::RayTracingPipelineCreateI }); } { - for (auto gfxHit : createInfo.closestHitShaders) { - auto hit = gfxHit.cast(); + for (auto hitgroup : createInfo.hitgroups) { + auto hit = hitgroup.closestHitShader.cast(); shaderStages.add(VkPipelineShaderStageCreateInfo{ .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, .pNext = nullptr, @@ -499,59 +500,38 @@ PRayTracingPipeline PipelineCache::createPipeline(Gfx::RayTracingPipelineCreateI .module = hit->getModuleHandle(), .pName = hit->getEntryPointName(), }); + uint32 anyHitIndex = VK_SHADER_UNUSED_KHR; + uint32 intersectionIndex = VK_SHADER_UNUSED_KHR; + if (hitgroup.anyHitShader != nullptr) { + auto anyHit = hitgroup.anyHitShader.cast(); + shaderStages.add(VkPipelineShaderStageCreateInfo{ + .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .stage = VK_SHADER_STAGE_ANY_HIT_BIT_KHR, + .module = hit->getModuleHandle(), + .pName = hit->getEntryPointName(), + }); + } + if (hitgroup.intersectionShader != nullptr) { + auto intersect = hitgroup.intersectionShader.cast(); + shaderStages.add(VkPipelineShaderStageCreateInfo{ + .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .stage = VK_SHADER_STAGE_INTERSECTION_BIT_KHR, + .module = intersect->getModuleHandle(), + .pName = intersect->getEntryPointName(), + }); + } shaderGroups.add(VkRayTracingShaderGroupCreateInfoKHR{ .sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR, .pNext = nullptr, .type = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR, .generalShader = VK_SHADER_UNUSED_KHR, .closestHitShader = static_cast(shaderStages.size() - 1), - .anyHitShader = VK_SHADER_UNUSED_KHR, - .intersectionShader = VK_SHADER_UNUSED_KHR, - }); - } - } - { - for (auto gfxHit : createInfo.anyHitShaders) { - auto hit = gfxHit.cast(); - shaderStages.add(VkPipelineShaderStageCreateInfo{ - .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .stage = VK_SHADER_STAGE_ANY_HIT_BIT_KHR, - .module = hit->getModuleHandle(), - .pName = hit->getEntryPointName(), - }); - shaderGroups.add(VkRayTracingShaderGroupCreateInfoKHR{ - .sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR, - .pNext = nullptr, - .type = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR, - .generalShader = VK_SHADER_UNUSED_KHR, - .closestHitShader = VK_SHADER_UNUSED_KHR, - .anyHitShader = static_cast(shaderStages.size() - 1), - .intersectionShader = VK_SHADER_UNUSED_KHR, - }); - } - } - { - for (auto gfxIntersect : createInfo.intersectionShaders) { - auto intersect = gfxIntersect.cast(); - shaderStages.add(VkPipelineShaderStageCreateInfo{ - .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .stage = VK_SHADER_STAGE_INTERSECTION_BIT_KHR, - .module = intersect->getModuleHandle(), - .pName = intersect->getEntryPointName(), - }); - - shaderGroups.add(VkRayTracingShaderGroupCreateInfoKHR{ - .sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR, - .pNext = nullptr, - .type = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR, - .generalShader = VK_SHADER_UNUSED_KHR, - .closestHitShader = VK_SHADER_UNUSED_KHR, - .anyHitShader = VK_SHADER_UNUSED_KHR, - .intersectionShader = static_cast(shaderStages.size() - 1), + .anyHitShader = anyHitIndex, + .intersectionShader = intersectionIndex, }); } } @@ -613,7 +593,89 @@ PRayTracingPipeline PipelineCache::createPipeline(Gfx::RayTracingPipelineCreateI }; VkPipeline pipelineHandle; VK_CHECK(vkCreateRayTracingPipelinesKHR(graphics->getDevice(), VK_NULL_HANDLE, cache, 1, &pipelineInfo, nullptr, &pipelineHandle)); - ORayTracingPipeline pipeline = new RayTracingPipeline(graphics, pipelineHandle, createInfo.pipelineLayout); + + const uint32_t handleSize = graphics->getRayTracingProperties().shaderGroupHandleSize; + const uint32_t handleAlignment = graphics->getRayTracingProperties().shaderGroupHandleAlignment; + const uint32_t handleSizeAligned = align(handleSize, handleAlignment); + const uint32_t groupCount = static_cast(shaderGroups.size()); + const uint32_t sbtSize = handleSizeAligned * groupCount; + + Array sbt(sbtSize); + + vkGetRayTracingShaderGroupHandlesKHR(graphics->getDevice(), pipelineHandle, 0, shaderGroups.size(), sbtSize, sbt.data()); + + Array rayGenSbt(handleSizeAligned); + std::memcpy(rayGenSbt.data(), sbt.data(), handleSize); + + uint64 sbtOffset = handleSizeAligned; + uint32 maxParamSize = 0; + 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) { + 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; + } + + Array missSbt(handleSizeAligned); + std::memcpy(missSbt.data(), sbt.data() + sbtOffset, handleSize); + + OBufferAllocation rayGenBuffer = + new BufferAllocation(graphics, "RayGenSBT", + VkBufferCreateInfo{ + .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, + .pNext = nullptr, + .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, + }, + VmaAllocationCreateInfo{ + .usage = VMA_MEMORY_USAGE_AUTO, + }, + Gfx::QueueType::GRAPHICS); + rayGenBuffer->updateContents(0, rayGenSbt.size(), rayGenSbt.data()); + + OBufferAllocation hitBuffer = + new BufferAllocation(graphics, "HitSBT", + VkBufferCreateInfo{ + .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, + .pNext = nullptr, + .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, + }, + VmaAllocationCreateInfo{ + .usage = VMA_MEMORY_USAGE_AUTO, + }, + Gfx::QueueType::GRAPHICS); + hitBuffer->updateContents(0, hitSbt.size(), hitSbt.data()); + + OBufferAllocation missBuffer = + new BufferAllocation(graphics, "MissSBT", + VkBufferCreateInfo{ + .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, + .pNext = nullptr, + .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, + }, + VmaAllocationCreateInfo{ + .usage = VMA_MEMORY_USAGE_AUTO, + }, + Gfx::QueueType::GRAPHICS); + missBuffer->updateContents(0, missSbt.size(), missSbt.data()); + + ORayTracingPipeline pipeline = + new RayTracingPipeline(graphics, pipelineHandle, std::move(rayGenBuffer), handleSizeAligned, std::move(hitBuffer), hitStride, + std::move(missBuffer), handleSizeAligned, 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 bd21743..713aa8d 100644 --- a/src/Engine/Graphics/Vulkan/RayTracing.cpp +++ b/src/Engine/Graphics/Vulkan/RayTracing.cpp @@ -30,7 +30,7 @@ BottomLevelAS::BottomLevelAS(PGraphics graphics, const Gfx::BottomLevelASCreateI .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_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, @@ -139,6 +139,9 @@ BottomLevelAS::BottomLevelAS(PGraphics graphics, const Gfx::BottomLevelASCreateI 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)); @@ -150,11 +153,159 @@ BottomLevelAS::BottomLevelAS(PGraphics graphics, const Gfx::BottomLevelASCreateI BottomLevelAS::~BottomLevelAS() { graphics->getDestructionManager()->queueResourceForDestruction(std::move(buffer)); } -TopLevelAS::TopLevelAS(PGraphics graphics, const Gfx::TopLevelASCreateInfo& createInfo) {} +TopLevelAS::TopLevelAS(PGraphics graphics, const Gfx::TopLevelASCreateInfo& createInfo) { + Array instances(createInfo.instances.size()); + for (uint32 i = 0; i < instances.size(); ++i) { + auto blas = createInfo.bottomLevelStructures[i].cast(); + + instances[i] = VkAccelerationStructureInstanceKHR{ + .transform = + VkTransformMatrixKHR{ + createInfo.instances[i].transformMatrix[0][0], + createInfo.instances[i].transformMatrix[1][0], + createInfo.instances[i].transformMatrix[2][0], + createInfo.instances[i].transformMatrix[3][0], + createInfo.instances[i].transformMatrix[0][1], + createInfo.instances[i].transformMatrix[1][1], + createInfo.instances[i].transformMatrix[2][1], + createInfo.instances[i].transformMatrix[3][1], + createInfo.instances[i].transformMatrix[0][2], + createInfo.instances[i].transformMatrix[1][2], + createInfo.instances[i].transformMatrix[2][2], + createInfo.instances[i].transformMatrix[3][2], + }, + .instanceCustomIndex = i, + .mask = 0xff, + .instanceShaderBindingTableRecordOffset = i, + .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); + + VkDeviceOrHostAddressConstKHR instanceDeviceAddress = { + .deviceAddress = instanceAllocation->deviceAddress, + }; + + VkAccelerationStructureGeometryKHR geometry = { + .sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR, + .pNext = nullptr, + .geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR, + .geometry = {.instances = + { + .sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR, + .pNext = nullptr, + .arrayOfPointers = VK_FALSE, + .data = instanceDeviceAddress, + }}, + .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 = instances.size(); + + 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); + + buffer = new BufferAllocation( + graphics, "TLAS", + VkBufferCreateInfo{ + .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{ + .usage = VMA_MEMORY_USAGE_AUTO, + }, + Gfx::QueueType::GRAPHICS); + + VkAccelerationStructureCreateInfoKHR accelerationInfo = { + .sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR, + .pNext = nullptr, + .buffer = buffer->buffer, + .size = buildSizesInfo.accelerationStructureSize, + .type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR, + }; + VK_CHECK(vkCreateAccelerationStructureKHR(graphics->getDevice(), &accelerationInfo, nullptr, &handle)); + + OBufferAllocation scratchBuffer = + new BufferAllocation(graphics, "ScratchBuffer", + VkBufferCreateInfo{ + .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{ + .usage = VMA_MEMORY_USAGE_AUTO, + }, + Gfx::QueueType::GRAPHICS); + + VkAccelerationStructureBuildGeometryInfoKHR buildGeometry = { + .sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR, + .pNext = nullptr, + .flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR, + .mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR, + .dstAccelerationStructure = handle, + .geometryCount = 1, + .pGeometries = &geometry, + .scratchData = + { + .deviceAddress = scratchBuffer->deviceAddress, + }, + }; + VkAccelerationStructureBuildRangeInfoKHR buildRange = { + .primitiveCount = uint32(instances.size()), + .primitiveOffset = 0, + .firstVertex = 0, + .transformOffset = 0, + }; + VkAccelerationStructureBuildRangeInfoKHR* buildRangeInfos[] = {&buildRange}; + + auto cmd = graphics->getGraphicsCommands()->getCommands(); + vkCmdBuildAccelerationStructuresKHR(cmd->getHandle(), 1, &buildGeometry, buildRangeInfos); + scratchBuffer->bind(); + + graphics->getDestructionManager()->queueResourceForDestruction(std::move(scratchBuffer)); +} TopLevelAS::~TopLevelAS() {} -RayTracingPipeline::RayTracingPipeline(PGraphics graphics, VkPipeline handle, Gfx::PPipelineLayout layout) - : Gfx::RayTracingPipeline(layout), graphics(graphics), pipeline(handle) {} +RayTracingPipeline::RayTracingPipeline(PGraphics graphics, VkPipeline handle, OBufferAllocation rayGen, uint64 rayGenStride, + OBufferAllocation hit, uint64 hitStride, OBufferAllocation miss, uint64 missStride, + 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) {} RayTracingPipeline::~RayTracingPipeline() {} + +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 8b1beb1..b9aaccd 100644 --- a/src/Engine/Graphics/Vulkan/RayTracing.h +++ b/src/Engine/Graphics/Vulkan/RayTracing.h @@ -1,9 +1,9 @@ #pragma once +#include "Buffer.h" #include "Graphics.h" #include "Graphics/Initializer.h" #include "Graphics/RayTracing.h" #include -#include "Buffer.h" namespace Seele { namespace Vulkan { @@ -11,6 +11,7 @@ class BottomLevelAS : public Gfx::BottomLevelAS { public: BottomLevelAS(PGraphics graphics, const Gfx::BottomLevelASCreateInfo& createInfo); ~BottomLevelAS(); + uint64 getDeviceAddress() const { return buffer->deviceAddress; } private: PGraphics graphics; @@ -23,22 +24,52 @@ class TopLevelAS : public Gfx::TopLevelAS { public: TopLevelAS(PGraphics graphics, const Gfx::TopLevelASCreateInfo& createInfo); ~TopLevelAS(); + const VkAccelerationStructureKHR getHandle() const { return handle; } private: PGraphics graphics; VkAccelerationStructureKHR handle; + OBufferAllocation instanceAllocation; + OBufferAllocation buffer; }; DEFINE_REF(TopLevelAS) -class RayTracingPipeline : public Gfx::RayTracingPipeline -{ +class RayTracingPipeline : public Gfx::RayTracingPipeline { public: - RayTracingPipeline(PGraphics graphics, VkPipeline handle, Gfx::PPipelineLayout layout); + RayTracingPipeline(PGraphics graphics, VkPipeline handle, OBufferAllocation rayGen, uint64 rayGenStride, OBufferAllocation hit, + uint64 hitStride, OBufferAllocation miss, uint64 missStride, Gfx::PPipelineLayout layout); virtual ~RayTracingPipeline(); - + void bind(VkCommandBuffer handle); + VkStridedDeviceAddressRegionKHR getRayGenRegion() { + return VkStridedDeviceAddressRegionKHR{ + .deviceAddress = rayGen->deviceAddress, + .stride = rayGenStride, + .size = rayGen->size, + }; + } + VkStridedDeviceAddressRegionKHR getHitRegion() { + return VkStridedDeviceAddressRegionKHR{ + .deviceAddress = hit->deviceAddress, + .stride = hitStride, + .size = hit->size, + }; + } + VkStridedDeviceAddressRegionKHR getMissRegion() { + return VkStridedDeviceAddressRegionKHR{ + .deviceAddress = miss->deviceAddress, + .stride = missStride, + .size = miss->size, + }; + } private: PGraphics graphics; VkPipeline pipeline; + OBufferAllocation rayGen; + uint64 rayGenStride; + OBufferAllocation hit; + uint64 hitStride; + OBufferAllocation miss; + uint64 missStride; }; DEFINE_REF(RayTracingPipeline) } // namespace Vulkan diff --git a/src/Engine/Graphics/Vulkan/Shader.cpp b/src/Engine/Graphics/Vulkan/Shader.cpp index 7a96257..8c914ff 100644 --- a/src/Engine/Graphics/Vulkan/Shader.cpp +++ b/src/Engine/Graphics/Vulkan/Shader.cpp @@ -20,10 +20,8 @@ Shader::~Shader() { uint32 Seele::Vulkan::Shader::getShaderHash() const { return hash; } -void Shader::create(ShaderCreateInfo createInfo) { - Map paramMapping; - Slang::ComPtr kernelBlob = generateShader(createInfo, SLANG_SPIRV, paramMapping); - createInfo.rootSignature->addMapping(paramMapping); +void Shader::create(const ShaderCreateInfo& createInfo) { + Slang::ComPtr kernelBlob = generateShader(createInfo); 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 1c131f6..f2cb380 100644 --- a/src/Engine/Graphics/Vulkan/Shader.h +++ b/src/Engine/Graphics/Vulkan/Shader.h @@ -13,7 +13,7 @@ class Shader { Shader(PGraphics graphics, VkShaderStageFlags stage); virtual ~Shader(); - void create(ShaderCreateInfo createInfo); + void create(const ShaderCreateInfo& createInfo); constexpr VkShaderModule getModuleHandle() const { return module; } constexpr const char* getEntryPointName() const { diff --git a/src/Engine/Graphics/slang-compile.cpp b/src/Engine/Graphics/slang-compile.cpp index b2c29d0..1bc3c10 100644 --- a/src/Engine/Graphics/slang-compile.cpp +++ b/src/Engine/Graphics/slang-compile.cpp @@ -1,9 +1,11 @@ #include "slang-compile.h" #include "Containers/Array.h" +#include "Graphics/Descriptor.h" #include #include #include +using namespace Seele; #define CHECK_RESULT(x) \ { \ @@ -20,15 +22,17 @@ } \ } -Slang::ComPtr Seele::generateShader(const ShaderCreateInfo& createInfo, SlangCompileTarget target, - Map& paramMapping) { - thread_local Slang::ComPtr globalSession; +thread_local Slang::ComPtr globalSession; +thread_local Slang::ComPtr specializedComponent; +thread_local Slang::ComPtr session; + +void Seele::beginCompilation(const ShaderCompilationInfo& info, SlangCompileTarget target, Gfx::PPipelineLayout layout) { if (!globalSession) { slang::createGlobalSession(globalSession.writeRef()); } slang::SessionDesc sessionDesc; sessionDesc.flags = 0; - StaticArray option; + StaticArray option; option[0].name = slang::CompilerOptionName::IgnoreCapabilities; option[0].value.kind = slang::CompilerOptionValueKind::Int; option[0].value.intValue0 = 1; @@ -41,12 +45,15 @@ Slang::ComPtr Seele::generateShader(const ShaderCreateInfo& create option[3].name = slang::CompilerOptionName::DebugInformationFormat; option[3].value.kind = slang::CompilerOptionValueKind::Int; option[3].value.intValue0 = SLANG_DEBUG_INFO_FORMAT_PDB; + option[4].name = slang::CompilerOptionName::DumpIntermediates; + option[4].value.kind = slang::CompilerOptionValueKind::Int; + option[4].value.intValue0 = 1; sessionDesc.compilerOptionEntries = option.data(); sessionDesc.compilerOptionEntryCount = option.size(); sessionDesc.defaultMatrixLayoutMode = SLANG_MATRIX_LAYOUT_COLUMN_MAJOR; Array macros; - for (const auto& [key, val] : createInfo.defines) { + for (const auto& [key, val] : info.defines) { macros.add(slang::PreprocessorMacroDesc{ .name = key, .value = val, @@ -59,28 +66,30 @@ Slang::ComPtr Seele::generateShader(const ShaderCreateInfo& create targetDesc.format = target; sessionDesc.targetCount = 1; sessionDesc.targets = &targetDesc; - StaticArray searchPaths = {"shaders/", "shaders/lib/", "shaders/generated/"}; + StaticArray searchPaths = {"shaders/", "shaders/lib/", "shaders/raytracing/", "shaders/generated/"}; sessionDesc.searchPaths = searchPaths.data(); sessionDesc.searchPathCount = searchPaths.size(); - Slang::ComPtr session; - CHECK_RESULT(globalSession->createSession(sessionDesc, session.writeRef())); Slang::ComPtr diagnostics; - Array modules; - Slang::ComPtr entrypoint; - for (const auto& moduleName : createInfo.additionalModules) { - modules.add(session->loadModule(moduleName.c_str(), diagnostics.writeRef())); + + CHECK_RESULT(globalSession->createSession(sessionDesc, session.writeRef())); + Array components; + Map moduleMap; + for (const auto& moduleName : info.modules) { + slang::IModule* loaded = session->loadModule(moduleName.c_str(), diagnostics.writeRef()); + components.add(loaded); + moduleMap[moduleName] = loaded; CHECK_DIAGNOSTICS(); } - slang::IModule* mainModule = session->loadModule(createInfo.mainModule.c_str(), diagnostics.writeRef()); - modules.add(mainModule); - CHECK_DIAGNOSTICS(); - CHECK_RESULT(mainModule->findEntryPointByName(createInfo.entryPoint.c_str(), entrypoint.writeRef())); - modules.add(entrypoint); + for (const auto& [name, mod] : info.entryPoints) { + slang::IEntryPoint* entry; + moduleMap[mod]->findEntryPointByName(name.c_str(), &entry); + components.add(entry); + } Slang::ComPtr moduleComposition; - session->createCompositeComponentType(modules.data(), modules.size(), moduleComposition.writeRef(), diagnostics.writeRef()); + session->createCompositeComponentType(components.data(), components.size(), moduleComposition.writeRef(), diagnostics.writeRef()); CHECK_DIAGNOSTICS(); @@ -94,25 +103,28 @@ Slang::ComPtr Seele::generateShader(const ShaderCreateInfo& create CHECK_DIAGNOSTICS(); Array specialization; - for (const auto& [key, value] : createInfo.typeParameter) { + for (const auto& [key, value] : info.typeParameter) { specialization.add(slang::SpecializationArg::fromType(reflection->findTypeByName(value))); } - Slang::ComPtr specializedComponent; linkedProgram->specialize(specialization.data(), specialization.size(), specializedComponent.writeRef(), diagnostics.writeRef()); CHECK_DIAGNOSTICS(); - Slang::ComPtr kernelBlob; - specializedComponent->getEntryPointCode(0, 0, kernelBlob.writeRef(), diagnostics.writeRef()); - CHECK_DIAGNOSTICS(); slang::ProgramLayout* signature = specializedComponent->getLayout(0, diagnostics.writeRef()); CHECK_DIAGNOSTICS(); for (size_t i = 0; i < signature->getParameterCount(); ++i) { auto param = signature->getParameterByIndex(i); - paramMapping[param->getName()] = param->getBindingIndex(); + layout->addMapping(param->getName(), param->getBindingIndex()); } // workaround - paramMapping["pVertexData"] = 1; - paramMapping["pMaterial"] = 4; + layout->addMapping("pVertexData", 1); + layout->addMapping("pMaterial", 4); +} + +Slang::ComPtr Seele::generateShader(const ShaderCreateInfo& createInfo) { + Slang::ComPtr diagnostics; + Slang::ComPtr kernelBlob; + specializedComponent->getEntryPointCode(createInfo.entryPointIndex, 0, kernelBlob.writeRef(), diagnostics.writeRef()); + CHECK_DIAGNOSTICS(); return kernelBlob; } diff --git a/src/Engine/Graphics/slang-compile.h b/src/Engine/Graphics/slang-compile.h index 89f9a2f..c12d7ef 100644 --- a/src/Engine/Graphics/slang-compile.h +++ b/src/Engine/Graphics/slang-compile.h @@ -4,6 +4,6 @@ #include namespace Seele { -Slang::ComPtr generateShader(const ShaderCreateInfo& createInfo, SlangCompileTarget target, - Map& paramMapping); +void beginCompilation(const ShaderCompilationInfo& info, SlangCompileTarget target, Gfx::PPipelineLayout layout); +Slang::ComPtr generateShader(const ShaderCreateInfo& createInfo); } diff --git a/src/Engine/Math/Math.h b/src/Engine/Math/Math.h index 11b6834..6db0b73 100644 --- a/src/Engine/Math/Math.h +++ b/src/Engine/Math/Math.h @@ -3,7 +3,6 @@ #include "Matrix.h" #include "Vector.h" - namespace Seele { struct Rect { bool isEmpty() const { return size.x == 0 || size.y == 0; } @@ -19,4 +18,5 @@ struct Rect3D { Vector size = Vector(0); Vector offset = Vector(0); }; +template constexpr T align(T size, T alignment) { return (size + alignment - 1) & ~(alignment - 1); } } // namespace Seele \ No newline at end of file diff --git a/src/Engine/Window/GameView.cpp b/src/Engine/Window/GameView.cpp index 4562cb4..5a8a0a1 100644 --- a/src/Engine/Window/GameView.cpp +++ b/src/Engine/Window/GameView.cpp @@ -10,6 +10,7 @@ #include "Graphics/RenderPass/LightCullingPass.h" #include "Graphics/RenderPass/RenderGraphResources.h" #include "Graphics/RenderPass/VisibilityPass.h" +#include "Graphics/RenderPass/RayTracingPass.h" #include "System/CameraUpdater.h" #include "System/LightGather.h" #include "System/MeshUpdater.h" @@ -22,11 +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 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(); }