diff --git a/src/Engine/Containers/Array.h b/src/Engine/Containers/Array.h index 4673bfd..ee46952 100644 --- a/src/Engine/Containers/Array.h +++ b/src/Engine/Containers/Array.h @@ -171,7 +171,7 @@ public: { _data = allocateArray(init.size()); assert(_data != nullptr); - std::uninitialized_copy(init.begin(), init.end(), begin()); + std::uninitialized_move(init.begin(), init.end(), begin()); } constexpr Array(const Array &other) diff --git a/src/Engine/Graphics/CMakeLists.txt b/src/Engine/Graphics/CMakeLists.txt index f6a72f0..930a40f 100644 --- a/src/Engine/Graphics/CMakeLists.txt +++ b/src/Engine/Graphics/CMakeLists.txt @@ -25,6 +25,8 @@ target_sources(Engine Resources.cpp Shader.h Shader.cpp + slang-compile.h + slang-compile.cpp StaticMeshVertexData.h StaticMeshVertexData.cpp Texture.h diff --git a/src/Engine/Graphics/Metal/Buffer.h b/src/Engine/Graphics/Metal/Buffer.h index 3189d00..de2d15a 100644 --- a/src/Engine/Graphics/Metal/Buffer.h +++ b/src/Engine/Graphics/Metal/Buffer.h @@ -7,7 +7,8 @@ namespace Metal { DECLARE_REF(Graphics) class Buffer { - +public: +private: }; DEFINE_REF(Buffer) class VertexBuffer : public Gfx::VertexBuffer, public Buffer diff --git a/src/Engine/Graphics/Metal/CMakeLists.txt b/src/Engine/Graphics/Metal/CMakeLists.txt index 03c9cf2..e9b54ab 100644 --- a/src/Engine/Graphics/Metal/CMakeLists.txt +++ b/src/Engine/Graphics/Metal/CMakeLists.txt @@ -17,6 +17,8 @@ target_sources(Engine RenderPass.mm Resources.h Resources.mm + Shader.h + Shader.mm Texture.h Texture.mm Window.h diff --git a/src/Engine/Graphics/Metal/Command.h b/src/Engine/Graphics/Metal/Command.h index 834a99b..eb4842e 100644 --- a/src/Engine/Graphics/Metal/Command.h +++ b/src/Engine/Graphics/Metal/Command.h @@ -1,19 +1,14 @@ #pragma once #include "Graphics/Command.h" -#include "Metal/MTLComputeCommandEncoder.hpp" -#include "Metal/MTLDrawable.hpp" -#include "Metal/MTLIOCommandQueue.hpp" -#include "Metal/MTLRenderCommandEncoder.hpp" -#include "MinimalEngine.h" #include "RenderPass.h" #include "Resources.h" -#include "Graphics.h" namespace Seele { namespace Metal { DECLARE_REF(CommandQueue) DECLARE_REF(ComputeCommand) DECLARE_REF(RenderCommand) +DECLARE_REF(Graphics) class Command { public: diff --git a/src/Engine/Graphics/Metal/Graphics.h b/src/Engine/Graphics/Metal/Graphics.h index 2384083..1189e38 100644 --- a/src/Engine/Graphics/Metal/Graphics.h +++ b/src/Engine/Graphics/Metal/Graphics.h @@ -1,5 +1,4 @@ #pragma once -#include "Graphics/Metal/Command.h" #include "Metal/Metal.hpp" #include "Graphics/Graphics.h" @@ -8,6 +7,7 @@ namespace Seele namespace Metal { DECLARE_REF(CommandQueue) +DECLARE_REF(IOCommandQueue) class Graphics : public Gfx::Graphics { public: diff --git a/src/Engine/Graphics/Metal/Pipeline.h b/src/Engine/Graphics/Metal/Pipeline.h index e70e283..bc50f63 100644 --- a/src/Engine/Graphics/Metal/Pipeline.h +++ b/src/Engine/Graphics/Metal/Pipeline.h @@ -1,8 +1,7 @@ #pragma once #include "Graphics/Initializer.h" #include "Graphics/Pipeline.h" -#include "Metal/MTLComputePipeline.hpp" -#include "Metal/MTLRenderPipeline.hpp" +#include "Resources.h" #include "MinimalEngine.h" namespace Seele { diff --git a/src/Engine/Graphics/Metal/RenderPass.h b/src/Engine/Graphics/Metal/RenderPass.h index 98c9fc1..60c5336 100644 --- a/src/Engine/Graphics/Metal/RenderPass.h +++ b/src/Engine/Graphics/Metal/RenderPass.h @@ -1,12 +1,12 @@ #pragma once #include "Graphics/RenderTarget.h" -#include "Graphics.h" -#include "Metal/MTLRenderPass.hpp" +#include "Resources.h" namespace Seele { namespace Metal { +DECLARE_REF(Graphics) class RenderPass : public Gfx::RenderPass { public: diff --git a/src/Engine/Graphics/Metal/Shader.h b/src/Engine/Graphics/Metal/Shader.h new file mode 100644 index 0000000..672b504 --- /dev/null +++ b/src/Engine/Graphics/Metal/Shader.h @@ -0,0 +1,46 @@ +#pragma once +#include "Graphics/Shader.h" +#include "Resources.h" + +namespace Seele { +namespace Metal { +class Shader { +public: + Shader(PGraphics graphics); + virtual ~Shader(); + + void create(const ShaderCreateInfo &createInfo); + + constexpr MTL::Function *getFunction() const { return function; } + constexpr const char *getEntryPointName() const { + // SLang renames all entry points to main, so we dont need that + return "main"; // entryPointName.c_str(); + } + uint32 getShaderHash() const; + +private: + PGraphics graphics; + MTL::Library* library; + MTL::Function *function; + uint32 hash; +}; +DEFINE_REF(Shader) + +template class ShaderBase : public Base, public Shader { +public: + ShaderBase(PGraphics graphics) : Shader(graphics) {} + virtual ~ShaderBase() {} +}; +using VertexShader = ShaderBase; +using FragmentShader = ShaderBase; +using ComputeShader = ShaderBase; +using TaskShader = ShaderBase; +using MeshShader = ShaderBase; + +DEFINE_REF(VertexShader) +DEFINE_REF(FragmentShader) +DEFINE_REF(ComputeShader) +DEFINE_REF(TaskShader) +DEFINE_REF(MeshShader) +} // namespace Metal +} // namespace Seele \ No newline at end of file diff --git a/src/Engine/Graphics/Metal/Shader.mm b/src/Engine/Graphics/Metal/Shader.mm new file mode 100644 index 0000000..0ca9132 --- /dev/null +++ b/src/Engine/Graphics/Metal/Shader.mm @@ -0,0 +1,59 @@ +#include "Shader.h" +#include "Graphics.h" +#include "Graphics/slang-compile.h" +#include "Metal/MTLLibrary.hpp" +#include + +using namespace Seele; +using namespace Seele::Metal; + +Shader::Shader(PGraphics graphics) : graphics(graphics) {} +Shader::~Shader() { + if (function) { + function->release(); + library->release(); + } +} + +void Shader::create(const ShaderCreateInfo &createInfo) { + Slang::ComPtr kernelBlob = generateShader(createInfo, SLANG_DXIL); + thread_local IRCompiler* pCompiler = nullptr; + if(pCompiler == nullptr) + { + pCompiler = IRCompilerCreate(); + } + IRCompilerSetEntryPointName(pCompiler, "main"); + + IRObject* pDXIL = IRObjectCreateFromDXIL(kernelBlob->getBufferPointer(), kernelBlob->getBufferSize(), IRBytecodeOwnershipNone); + + // Compile DXIL to Metal IR: + IRError* pError = nullptr; + IRObject* pOutIR = IRCompilerAllocCompileAndLink(pCompiler, NULL, pDXIL, &pError); + + if (!pOutIR) + { + // Inspect pError to determine cause. + IRErrorDestroy( pError ); + } + + // Retrieve Metallib: + MetaLibBinary* pMetallib = IRMetalLibBinaryCreate(); + IRObjectGetMetalLibBinary(pOutIR, stage, pMetallib); + size_t metallibSize = IRMetalLibGetBytecodeSize(pMetallib); + uint8_t* metallib = new uint8_t[metallibSize]; + IRMetalLibGetBytecode(pMetallib, metallib); + + // Store the metallib to custom format or disk, or use to create a MTLLibrary. + NS::Error* __autoreleasing error = nil; + dispatch_data_t data = + dispatch_data_create(metallib, metallibSize, dispatch_get_main_queue(), NULL); + + library = graphics->getDevice()->newLibrary(data, &error); + function = library->newFunction(NS::String::string("main", NS::ASCIIStringEncoding)); + + delete [] metallib; + IRMetalLibBinaryDestroy(pMetallib); + IRObjectDestroy(pDXIL); + IRObjectDestroy(pOutIR); + IRCompilerDestroy(pCompiler); +} \ No newline at end of file diff --git a/src/Engine/Graphics/Metal/Texture.h b/src/Engine/Graphics/Metal/Texture.h index 7ff0583..81814b1 100644 --- a/src/Engine/Graphics/Metal/Texture.h +++ b/src/Engine/Graphics/Metal/Texture.h @@ -1,7 +1,6 @@ #pragma once #include "Graphics/Texture.h" #include "Graphics.h" -#include "Metal/MTLTexture.hpp" namespace Seele { diff --git a/src/Engine/Graphics/Metal/Texture.mm b/src/Engine/Graphics/Metal/Texture.mm index 4416dbe..4161446 100644 --- a/src/Engine/Graphics/Metal/Texture.mm +++ b/src/Engine/Graphics/Metal/Texture.mm @@ -61,10 +61,7 @@ TextureBase::~TextureBase() { void TextureBase::executePipelineBarrier(Gfx::SeAccessFlags, Gfx::SePipelineStageFlags, Gfx::SeAccessFlags, - Gfx::SePipelineStageFlags) { - - -} + Gfx::SePipelineStageFlags) {} void TextureBase::changeLayout(Gfx::SeImageLayout, Gfx::SeAccessFlags, Gfx::SePipelineStageFlags, Gfx::SeAccessFlags, diff --git a/src/Engine/Graphics/Metal/Window.h b/src/Engine/Graphics/Metal/Window.h index e2eeb76..47302d2 100644 --- a/src/Engine/Graphics/Metal/Window.h +++ b/src/Engine/Graphics/Metal/Window.h @@ -1,7 +1,6 @@ #pragma once #include "Graphics.h" #include "Graphics/Window.h" -#include "Metal/MTLRenderCommandEncoder.hpp" #include "Resources.h" #include "Texture.h" diff --git a/src/Engine/Graphics/RenderPass/BasePass.cpp b/src/Engine/Graphics/RenderPass/BasePass.cpp index c6eaddd..4aad58e 100644 --- a/src/Engine/Graphics/RenderPass/BasePass.cpp +++ b/src/Engine/Graphics/RenderPass/BasePass.cpp @@ -80,7 +80,7 @@ void BasePass::render() } permutation.setFragmentFile("BasePass"); graphics->beginRenderPass(renderPass); - Array commands; + Array commands; for (VertexData* vertexData : VertexData::getList()) { permutation.setVertexData(vertexData->getTypeName()); @@ -98,7 +98,7 @@ void BasePass::render() permutation.setMaterial(materialData.material->getName()); Gfx::PermutationId id(permutation); - Gfx::PRenderCommand command = graphics->createRenderCommand("BaseRender"); + Gfx::ORenderCommand command = graphics->createRenderCommand("BaseRender"); command->setViewport(viewport); Gfx::OPipelineLayout layout = graphics->createPipelineLayout(basePassLayout); layout->addDescriptorLayout(INDEX_MATERIAL, materialData.material->getDescriptorLayout()); @@ -159,10 +159,10 @@ void BasePass::render() } } } - commands.add(command); + commands.add(std::move(command)); } } - graphics->executeCommands(commands); + graphics->executeCommands(std::move(commands)); graphics->endRenderPass(); } diff --git a/src/Engine/Graphics/RenderPass/DebugPass.cpp b/src/Engine/Graphics/RenderPass/DebugPass.cpp index 230828a..9fa9692 100644 --- a/src/Engine/Graphics/RenderPass/DebugPass.cpp +++ b/src/Engine/Graphics/RenderPass/DebugPass.cpp @@ -54,7 +54,9 @@ void DebugPass::render() renderCommand->bindDescriptor(viewParamsSet); renderCommand->bindVertexBuffer({ debugVertices }); renderCommand->draw((uint32)gDebugVertices.size(), 1, 0, 0); - graphics->executeCommands(Array{std::move(renderCommand)}); + Array commands; + commands.add(std::move(renderCommand)); + graphics->executeCommands({std::move(commands)}); graphics->endRenderPass(); gDebugVertices.clear(); } diff --git a/src/Engine/Graphics/RenderPass/LightCullingPass.cpp b/src/Engine/Graphics/RenderPass/LightCullingPass.cpp index 032ae2f..9fae395 100644 --- a/src/Engine/Graphics/RenderPass/LightCullingPass.cpp +++ b/src/Engine/Graphics/RenderPass/LightCullingPass.cpp @@ -60,13 +60,14 @@ void LightCullingPass::render() cullingDescriptorSet->updateTexture(5, Gfx::PTexture2D(oLightGrid)); cullingDescriptorSet->updateTexture(6, Gfx::PTexture2D(tLightGrid)); cullingDescriptorSet->writeChanges(); - Gfx::PComputeCommand computeCommand = graphics->createComputeCommand("CullingCommand"); + Gfx::OComputeCommand computeCommand = graphics->createComputeCommand("CullingCommand"); computeCommand->bindPipeline(cullingPipeline); computeCommand->bindDescriptor({ viewParamsSet, dispatchParamsSet, cullingDescriptorSet, lightEnv->getDescriptorSet() }); computeCommand->dispatch(dispatchParams.numThreadGroups.x, dispatchParams.numThreadGroups.y, dispatchParams.numThreadGroups.z); - Array commands = {computeCommand}; + Array commands; + commands.add(std::move(computeCommand)); //std::cout << "Execute" << std::endl; - graphics->executeCommands(commands); + graphics->executeCommands(std::move(commands)); } void LightCullingPass::endFrame() @@ -246,12 +247,13 @@ void LightCullingPass::setupFrustums() dispatchParamsSet->updateBuffer(1, frustumBuffer); dispatchParamsSet->writeChanges(); - Gfx::PComputeCommand command = graphics->createComputeCommand("FrustumCommand"); + Gfx::OComputeCommand command = graphics->createComputeCommand("FrustumCommand"); command->bindPipeline(frustumPipeline); command->bindDescriptor({ viewParamsSet, dispatchParamsSet }); command->dispatch(numThreadGroups.x, numThreadGroups.y, numThreadGroups.z); - Array commands = {command}; - graphics->executeCommands(commands); + Array commands; + commands.add(std::move(command)); + graphics->executeCommands(std::move(commands)); frustumBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT); } \ No newline at end of file diff --git a/src/Engine/Graphics/RenderPass/SkyboxRenderPass.cpp b/src/Engine/Graphics/RenderPass/SkyboxRenderPass.cpp index 987edd2..2e4cb77 100644 --- a/src/Engine/Graphics/RenderPass/SkyboxRenderPass.cpp +++ b/src/Engine/Graphics/RenderPass/SkyboxRenderPass.cpp @@ -56,12 +56,14 @@ void SkyboxRenderPass::render() Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT ); graphics->beginRenderPass(renderPass); - Gfx::PRenderCommand renderCommand = graphics->createRenderCommand("SkyboxRender"); + Gfx::ORenderCommand renderCommand = graphics->createRenderCommand("SkyboxRender"); renderCommand->setViewport(viewport); renderCommand->bindPipeline(pipeline); renderCommand->bindDescriptor({viewParamsSet, skyboxDataSet, textureSet}); renderCommand->draw(36, 1, 0, 0); - graphics->executeCommands(Array{ renderCommand }); + Array commands; + commands.add(std::move(renderCommand)); + graphics->executeCommands(std::move(commands)); graphics->endRenderPass(); } diff --git a/src/Engine/Graphics/RenderPass/TextPass.cpp b/src/Engine/Graphics/RenderPass/TextPass.cpp index 055c338..4a6907f 100644 --- a/src/Engine/Graphics/RenderPass/TextPass.cpp +++ b/src/Engine/Graphics/RenderPass/TextPass.cpp @@ -73,10 +73,10 @@ void TextPass::beginFrame(const Component::Camera& cam) void TextPass::render() { graphics->beginRenderPass(renderPass); - Array commands; + Array commands; for(const auto& [fontAsset, res] : textResources) { - Gfx::PRenderCommand command = graphics->createRenderCommand("TextPassCommand"); + Gfx::ORenderCommand command = graphics->createRenderCommand("TextPassCommand"); command->setViewport(viewport); command->bindPipeline(pipeline); for(const auto& resource : res) @@ -87,9 +87,9 @@ void TextPass::render() command->pushConstants(layoutRef, Gfx::SE_SHADER_STAGE_VERTEX_BIT | Gfx::SE_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(TextData), &resource.textData); //command->draw(4, static_cast(resource.vertexBuffer->getNumVertices()), 0, 0); } - commands.add(command); + commands.add(std::move(command)); } - graphics->executeCommands(commands); + graphics->executeCommands(std::move(commands)); graphics->endRenderPass(); textResources.clear(); //co_return; diff --git a/src/Engine/Graphics/RenderPass/UIPass.cpp b/src/Engine/Graphics/RenderPass/UIPass.cpp index 4e42a60..b98571e 100644 --- a/src/Engine/Graphics/RenderPass/UIPass.cpp +++ b/src/Engine/Graphics/RenderPass/UIPass.cpp @@ -48,7 +48,9 @@ void UIPass::render() command->bindVertexBuffer({elementBuffer}); command->bindDescriptor(descriptorSet); command->draw(4, static_cast(renderElements.size()), 0, 0); - graphics->executeCommands(Array{std::move(command)}); + Array commands; + commands.add(std::move(command)); + graphics->executeCommands(std::move(commands)); graphics->endRenderPass(); //co_return; diff --git a/src/Engine/Graphics/Vulkan/Enums.h b/src/Engine/Graphics/Vulkan/Enums.h index f6fab12..098ddfb 100644 --- a/src/Engine/Graphics/Vulkan/Enums.h +++ b/src/Engine/Graphics/Vulkan/Enums.h @@ -22,16 +22,6 @@ namespace Seele { namespace Vulkan { - -enum class ShaderType -{ - VERTEX = 0, - FRAGMENT = 1, - COMPUTE = 2, - TASK = 3, - MESH = 4, -}; - VkDescriptorType cast(const Gfx::SeDescriptorType &descriptorType); Gfx::SeDescriptorType cast(const VkDescriptorType &descriptorType); VkShaderStageFlagBits cast(const Gfx::SeShaderStageFlagBits &stage); diff --git a/src/Engine/Graphics/Vulkan/Shader.cpp b/src/Engine/Graphics/Vulkan/Shader.cpp index 4142fa5..2fb0bec 100644 --- a/src/Engine/Graphics/Vulkan/Shader.cpp +++ b/src/Engine/Graphics/Vulkan/Shader.cpp @@ -8,9 +8,8 @@ using namespace Seele; using namespace Seele::Vulkan; -Shader::Shader(PGraphics graphics, ShaderType shaderType, VkShaderStageFlags stage) +Shader::Shader(PGraphics graphics, VkShaderStageFlags stage) : graphics(graphics) - , type(shaderType) , stage(stage) { } @@ -28,91 +27,8 @@ uint32 Seele::Vulkan::Shader::getShaderHash() const return hash; } -#define CHECK_RESULT(x) {SlangResult r = x; if(r != 0) {throw std::runtime_error(fmt::format("Error: {0}", r));}} -#define CHECK_DIAGNOSTICS() {if(diagnostics) {std::cout << (const char*)diagnostics->getBufferPointer() << std::endl; assert(false);}} - void Shader::create(const ShaderCreateInfo& createInfo) { - entryPointName = createInfo.entryPoint; - thread_local Slang::ComPtr globalSession; - if(!globalSession) - { - slang::createGlobalSession(globalSession.writeRef()); - } - slang::SessionDesc sessionDesc; - sessionDesc.flags = 0; - sessionDesc.defaultMatrixLayoutMode = SLANG_MATRIX_LAYOUT_COLUMN_MAJOR; - Array macros; - for(const auto& [key, val] : createInfo.defines) - { - macros.add(slang::PreprocessorMacroDesc{ - .name = key, - .value = val, - }); - } - sessionDesc.preprocessorMacroCount = macros.size(); - sessionDesc.preprocessorMacros = macros.data(); - slang::TargetDesc vulkan; - vulkan.profile = globalSession->findProfile("sm_6_6"); - vulkan.format = SLANG_SPIRV; - sessionDesc.targetCount = 1; - sessionDesc.targets = &vulkan; - StaticArray searchPaths = {"shaders/", "shaders/lib/", "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; - slang::IModule* mainModule = nullptr; - for (const auto& moduleName : createInfo.additionalModules) - { - modules.add(session->loadModule(moduleName.c_str(), diagnostics.writeRef())); - if (moduleName == createInfo.mainModule) - { - mainModule = (slang::IModule*)modules.back(); - } - CHECK_DIAGNOSTICS(); - } - - CHECK_DIAGNOSTICS(); - - mainModule->findEntryPointByName(createInfo.entryPoint.c_str(), entrypoint.writeRef()); - modules.add(entrypoint); - - Slang::ComPtr moduleComposition; - session->createCompositeComponentType(modules.data(), modules.size(), moduleComposition.writeRef(), diagnostics.writeRef()); - - CHECK_DIAGNOSTICS(); - - Slang::ComPtr linkedProgram; - moduleComposition->link(linkedProgram.writeRef(), diagnostics.writeRef()); - - CHECK_DIAGNOSTICS(); - - slang::ProgramLayout* reflection = linkedProgram->getLayout(0, diagnostics.writeRef()); - - CHECK_DIAGNOSTICS(); - - Array specialization; - for(const auto& [key, value] : createInfo.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(); VkShaderModuleCreateInfo moduleInfo = { diff --git a/src/Engine/Graphics/Vulkan/Shader.h b/src/Engine/Graphics/Vulkan/Shader.h index b3aa057..9998647 100644 --- a/src/Engine/Graphics/Vulkan/Shader.h +++ b/src/Engine/Graphics/Vulkan/Shader.h @@ -12,7 +12,7 @@ DECLARE_REF(DescriptorLayout) class Shader { public: - Shader(PGraphics graphics, ShaderType shaderType, VkShaderStageFlags stage); + Shader(PGraphics graphics, VkShaderStageFlags stage); virtual ~Shader(); void create(const ShaderCreateInfo& createInfo); @@ -26,44 +26,36 @@ public: //SLang renames all entry points to main, so we dont need that return "main";//entryPointName.c_str(); } - constexpr ShaderType getShaderType() const - { - return type; - } constexpr VkShaderStageFlags getStage() const { return stage; } - //Map getDescriptorLayouts(); uint32 getShaderHash() const; private: PGraphics graphics; - //Map descriptorSets; VkShaderModule module; - ShaderType type; VkShaderStageFlags stage; - std::string entryPointName; uint32 hash; }; DEFINE_REF(Shader) -template +template class ShaderBase : public Base, public Shader { public: ShaderBase(PGraphics graphics) - : Shader(graphics, shaderType, stageFlags) + : Shader(graphics, stageFlags) { } virtual ~ShaderBase() { } }; -typedef ShaderBase VertexShader; -typedef ShaderBase FragmentShader; -typedef ShaderBase ComputeShader; -typedef ShaderBase TaskShader; -typedef ShaderBase MeshShader; +using VertexShader = ShaderBase; +using FragmentShader = ShaderBase; +using ComputeShader = ShaderBase; +using TaskShader = ShaderBase; +using MeshShader = ShaderBase; DEFINE_REF(VertexShader) DEFINE_REF(FragmentShader) diff --git a/src/Engine/Graphics/slang-compile.cpp b/src/Engine/Graphics/slang-compile.cpp new file mode 100644 index 0000000..25b1876 --- /dev/null +++ b/src/Engine/Graphics/slang-compile.cpp @@ -0,0 +1,93 @@ +#include "slang-compile.h" +#include +#include +#include "Containers/Array.h" +#include +#include + +#define CHECK_RESULT(x) {SlangResult r = x; if(r != 0) {throw std::runtime_error(fmt::format("Error: {0}", r));}} +#define CHECK_DIAGNOSTICS() {if(diagnostics) {std::cout << (const char*)diagnostics->getBufferPointer() << std::endl; assert(false);}} + +Slang::ComPtr Seele::generateShader(const ShaderCreateInfo& createInfo, SlangCompileTarget target) +{ + thread_local Slang::ComPtr globalSession; + if(!globalSession) + { + slang::createGlobalSession(globalSession.writeRef()); + } + slang::SessionDesc sessionDesc; + sessionDesc.flags = 0; + sessionDesc.defaultMatrixLayoutMode = SLANG_MATRIX_LAYOUT_COLUMN_MAJOR; + Array macros; + for(const auto& [key, val] : createInfo.defines) + { + macros.add(slang::PreprocessorMacroDesc{ + .name = key, + .value = val, + }); + } + sessionDesc.preprocessorMacroCount = macros.size(); + sessionDesc.preprocessorMacros = macros.data(); + slang::TargetDesc vulkan; + vulkan.profile = globalSession->findProfile("sm_6_6"); + vulkan.format = target; + sessionDesc.targetCount = 1; + sessionDesc.targets = &vulkan; + StaticArray searchPaths = {"shaders/", "shaders/lib/", "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; + slang::IModule* mainModule = nullptr; + for (const auto& moduleName : createInfo.additionalModules) + { + modules.add(session->loadModule(moduleName.c_str(), diagnostics.writeRef())); + if (moduleName == createInfo.mainModule) + { + mainModule = (slang::IModule*)modules.back(); + } + CHECK_DIAGNOSTICS(); + } + + CHECK_DIAGNOSTICS(); + + mainModule->findEntryPointByName(createInfo.entryPoint.c_str(), entrypoint.writeRef()); + modules.add(entrypoint); + + Slang::ComPtr moduleComposition; + session->createCompositeComponentType(modules.data(), modules.size(), moduleComposition.writeRef(), diagnostics.writeRef()); + + CHECK_DIAGNOSTICS(); + + Slang::ComPtr linkedProgram; + moduleComposition->link(linkedProgram.writeRef(), diagnostics.writeRef()); + + CHECK_DIAGNOSTICS(); + + slang::ProgramLayout* reflection = linkedProgram->getLayout(0, diagnostics.writeRef()); + + CHECK_DIAGNOSTICS(); + + Array specialization; + for(const auto& [key, value] : createInfo.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(); + return kernelBlob; +} \ No newline at end of file diff --git a/src/Engine/Graphics/slang-compile.h b/src/Engine/Graphics/slang-compile.h new file mode 100644 index 0000000..fb461c5 --- /dev/null +++ b/src/Engine/Graphics/slang-compile.h @@ -0,0 +1,8 @@ +#pragma once +#include "Graphics/Initializer.h" +#include +#include + +namespace Seele { +Slang::ComPtr generateShader(const ShaderCreateInfo& createInfo, SlangCompileTarget target); +} \ No newline at end of file