Basic shader compilation

This commit is contained in:
Dynamitos
2024-04-11 12:38:42 +02:00
parent c3be0e23e7
commit 77dc9ef3fd
24 changed files with 254 additions and 148 deletions
+1 -1
View File
@@ -171,7 +171,7 @@ public:
{ {
_data = allocateArray(init.size()); _data = allocateArray(init.size());
assert(_data != nullptr); assert(_data != nullptr);
std::uninitialized_copy(init.begin(), init.end(), begin()); std::uninitialized_move(init.begin(), init.end(), begin());
} }
constexpr Array(const Array &other) constexpr Array(const Array &other)
+2
View File
@@ -25,6 +25,8 @@ target_sources(Engine
Resources.cpp Resources.cpp
Shader.h Shader.h
Shader.cpp Shader.cpp
slang-compile.h
slang-compile.cpp
StaticMeshVertexData.h StaticMeshVertexData.h
StaticMeshVertexData.cpp StaticMeshVertexData.cpp
Texture.h Texture.h
+2 -1
View File
@@ -7,7 +7,8 @@ namespace Metal {
DECLARE_REF(Graphics) DECLARE_REF(Graphics)
class Buffer class Buffer
{ {
public:
private:
}; };
DEFINE_REF(Buffer) DEFINE_REF(Buffer)
class VertexBuffer : public Gfx::VertexBuffer, public Buffer class VertexBuffer : public Gfx::VertexBuffer, public Buffer
+2
View File
@@ -17,6 +17,8 @@ target_sources(Engine
RenderPass.mm RenderPass.mm
Resources.h Resources.h
Resources.mm Resources.mm
Shader.h
Shader.mm
Texture.h Texture.h
Texture.mm Texture.mm
Window.h Window.h
+1 -6
View File
@@ -1,19 +1,14 @@
#pragma once #pragma once
#include "Graphics/Command.h" #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 "RenderPass.h"
#include "Resources.h" #include "Resources.h"
#include "Graphics.h"
namespace Seele { namespace Seele {
namespace Metal { namespace Metal {
DECLARE_REF(CommandQueue) DECLARE_REF(CommandQueue)
DECLARE_REF(ComputeCommand) DECLARE_REF(ComputeCommand)
DECLARE_REF(RenderCommand) DECLARE_REF(RenderCommand)
DECLARE_REF(Graphics)
class Command class Command
{ {
public: public:
+1 -1
View File
@@ -1,5 +1,4 @@
#pragma once #pragma once
#include "Graphics/Metal/Command.h"
#include "Metal/Metal.hpp" #include "Metal/Metal.hpp"
#include "Graphics/Graphics.h" #include "Graphics/Graphics.h"
@@ -8,6 +7,7 @@ namespace Seele
namespace Metal namespace Metal
{ {
DECLARE_REF(CommandQueue) DECLARE_REF(CommandQueue)
DECLARE_REF(IOCommandQueue)
class Graphics : public Gfx::Graphics class Graphics : public Gfx::Graphics
{ {
public: public:
+1 -2
View File
@@ -1,8 +1,7 @@
#pragma once #pragma once
#include "Graphics/Initializer.h" #include "Graphics/Initializer.h"
#include "Graphics/Pipeline.h" #include "Graphics/Pipeline.h"
#include "Metal/MTLComputePipeline.hpp" #include "Resources.h"
#include "Metal/MTLRenderPipeline.hpp"
#include "MinimalEngine.h" #include "MinimalEngine.h"
namespace Seele { namespace Seele {
+2 -2
View File
@@ -1,12 +1,12 @@
#pragma once #pragma once
#include "Graphics/RenderTarget.h" #include "Graphics/RenderTarget.h"
#include "Graphics.h" #include "Resources.h"
#include "Metal/MTLRenderPass.hpp"
namespace Seele namespace Seele
{ {
namespace Metal namespace Metal
{ {
DECLARE_REF(Graphics)
class RenderPass : public Gfx::RenderPass class RenderPass : public Gfx::RenderPass
{ {
public: public:
+46
View File
@@ -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 <typename Base> class ShaderBase : public Base, public Shader {
public:
ShaderBase(PGraphics graphics) : Shader(graphics) {}
virtual ~ShaderBase() {}
};
using VertexShader = ShaderBase<Gfx::VertexShader>;
using FragmentShader = ShaderBase<Gfx::FragmentShader>;
using ComputeShader = ShaderBase<Gfx::ComputeShader>;
using TaskShader = ShaderBase<Gfx::TaskShader>;
using MeshShader = ShaderBase<Gfx::MeshShader>;
DEFINE_REF(VertexShader)
DEFINE_REF(FragmentShader)
DEFINE_REF(ComputeShader)
DEFINE_REF(TaskShader)
DEFINE_REF(MeshShader)
} // namespace Metal
} // namespace Seele
+59
View File
@@ -0,0 +1,59 @@
#include "Shader.h"
#include "Graphics.h"
#include "Graphics/slang-compile.h"
#include "Metal/MTLLibrary.hpp"
#include <slang.h>
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<slang::IBlob> 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);
}
-1
View File
@@ -1,7 +1,6 @@
#pragma once #pragma once
#include "Graphics/Texture.h" #include "Graphics/Texture.h"
#include "Graphics.h" #include "Graphics.h"
#include "Metal/MTLTexture.hpp"
namespace Seele namespace Seele
{ {
+1 -4
View File
@@ -61,10 +61,7 @@ TextureBase::~TextureBase() {
void TextureBase::executePipelineBarrier(Gfx::SeAccessFlags, void TextureBase::executePipelineBarrier(Gfx::SeAccessFlags,
Gfx::SePipelineStageFlags, Gfx::SePipelineStageFlags,
Gfx::SeAccessFlags, Gfx::SeAccessFlags,
Gfx::SePipelineStageFlags) { Gfx::SePipelineStageFlags) {}
}
void TextureBase::changeLayout(Gfx::SeImageLayout, Gfx::SeAccessFlags, void TextureBase::changeLayout(Gfx::SeImageLayout, Gfx::SeAccessFlags,
Gfx::SePipelineStageFlags, Gfx::SeAccessFlags, Gfx::SePipelineStageFlags, Gfx::SeAccessFlags,
-1
View File
@@ -1,7 +1,6 @@
#pragma once #pragma once
#include "Graphics.h" #include "Graphics.h"
#include "Graphics/Window.h" #include "Graphics/Window.h"
#include "Metal/MTLRenderCommandEncoder.hpp"
#include "Resources.h" #include "Resources.h"
#include "Texture.h" #include "Texture.h"
+4 -4
View File
@@ -80,7 +80,7 @@ void BasePass::render()
} }
permutation.setFragmentFile("BasePass"); permutation.setFragmentFile("BasePass");
graphics->beginRenderPass(renderPass); graphics->beginRenderPass(renderPass);
Array<Gfx::PRenderCommand> commands; Array<Gfx::ORenderCommand> commands;
for (VertexData* vertexData : VertexData::getList()) for (VertexData* vertexData : VertexData::getList())
{ {
permutation.setVertexData(vertexData->getTypeName()); permutation.setVertexData(vertexData->getTypeName());
@@ -98,7 +98,7 @@ void BasePass::render()
permutation.setMaterial(materialData.material->getName()); permutation.setMaterial(materialData.material->getName());
Gfx::PermutationId id(permutation); Gfx::PermutationId id(permutation);
Gfx::PRenderCommand command = graphics->createRenderCommand("BaseRender"); Gfx::ORenderCommand command = graphics->createRenderCommand("BaseRender");
command->setViewport(viewport); command->setViewport(viewport);
Gfx::OPipelineLayout layout = graphics->createPipelineLayout(basePassLayout); Gfx::OPipelineLayout layout = graphics->createPipelineLayout(basePassLayout);
layout->addDescriptorLayout(INDEX_MATERIAL, materialData.material->getDescriptorLayout()); 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(); graphics->endRenderPass();
} }
+3 -1
View File
@@ -54,7 +54,9 @@ void DebugPass::render()
renderCommand->bindDescriptor(viewParamsSet); renderCommand->bindDescriptor(viewParamsSet);
renderCommand->bindVertexBuffer({ debugVertices }); renderCommand->bindVertexBuffer({ debugVertices });
renderCommand->draw((uint32)gDebugVertices.size(), 1, 0, 0); renderCommand->draw((uint32)gDebugVertices.size(), 1, 0, 0);
graphics->executeCommands(Array{std::move(renderCommand)}); Array<Gfx::ORenderCommand> commands;
commands.add(std::move(renderCommand));
graphics->executeCommands({std::move(commands)});
graphics->endRenderPass(); graphics->endRenderPass();
gDebugVertices.clear(); gDebugVertices.clear();
} }
@@ -60,13 +60,14 @@ void LightCullingPass::render()
cullingDescriptorSet->updateTexture(5, Gfx::PTexture2D(oLightGrid)); cullingDescriptorSet->updateTexture(5, Gfx::PTexture2D(oLightGrid));
cullingDescriptorSet->updateTexture(6, Gfx::PTexture2D(tLightGrid)); cullingDescriptorSet->updateTexture(6, Gfx::PTexture2D(tLightGrid));
cullingDescriptorSet->writeChanges(); cullingDescriptorSet->writeChanges();
Gfx::PComputeCommand computeCommand = graphics->createComputeCommand("CullingCommand"); Gfx::OComputeCommand computeCommand = graphics->createComputeCommand("CullingCommand");
computeCommand->bindPipeline(cullingPipeline); computeCommand->bindPipeline(cullingPipeline);
computeCommand->bindDescriptor({ viewParamsSet, dispatchParamsSet, cullingDescriptorSet, lightEnv->getDescriptorSet() }); computeCommand->bindDescriptor({ viewParamsSet, dispatchParamsSet, cullingDescriptorSet, lightEnv->getDescriptorSet() });
computeCommand->dispatch(dispatchParams.numThreadGroups.x, dispatchParams.numThreadGroups.y, dispatchParams.numThreadGroups.z); computeCommand->dispatch(dispatchParams.numThreadGroups.x, dispatchParams.numThreadGroups.y, dispatchParams.numThreadGroups.z);
Array<Gfx::PComputeCommand> commands = {computeCommand}; Array<Gfx::OComputeCommand> commands;
commands.add(std::move(computeCommand));
//std::cout << "Execute" << std::endl; //std::cout << "Execute" << std::endl;
graphics->executeCommands(commands); graphics->executeCommands(std::move(commands));
} }
void LightCullingPass::endFrame() void LightCullingPass::endFrame()
@@ -246,12 +247,13 @@ void LightCullingPass::setupFrustums()
dispatchParamsSet->updateBuffer(1, frustumBuffer); dispatchParamsSet->updateBuffer(1, frustumBuffer);
dispatchParamsSet->writeChanges(); dispatchParamsSet->writeChanges();
Gfx::PComputeCommand command = graphics->createComputeCommand("FrustumCommand"); Gfx::OComputeCommand command = graphics->createComputeCommand("FrustumCommand");
command->bindPipeline(frustumPipeline); command->bindPipeline(frustumPipeline);
command->bindDescriptor({ viewParamsSet, dispatchParamsSet }); command->bindDescriptor({ viewParamsSet, dispatchParamsSet });
command->dispatch(numThreadGroups.x, numThreadGroups.y, numThreadGroups.z); command->dispatch(numThreadGroups.x, numThreadGroups.y, numThreadGroups.z);
Array<Gfx::PComputeCommand> commands = {command}; Array<Gfx::OComputeCommand> commands;
graphics->executeCommands(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, 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); Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
} }
@@ -56,12 +56,14 @@ void SkyboxRenderPass::render()
Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
); );
graphics->beginRenderPass(renderPass); graphics->beginRenderPass(renderPass);
Gfx::PRenderCommand renderCommand = graphics->createRenderCommand("SkyboxRender"); Gfx::ORenderCommand renderCommand = graphics->createRenderCommand("SkyboxRender");
renderCommand->setViewport(viewport); renderCommand->setViewport(viewport);
renderCommand->bindPipeline(pipeline); renderCommand->bindPipeline(pipeline);
renderCommand->bindDescriptor({viewParamsSet, skyboxDataSet, textureSet}); renderCommand->bindDescriptor({viewParamsSet, skyboxDataSet, textureSet});
renderCommand->draw(36, 1, 0, 0); renderCommand->draw(36, 1, 0, 0);
graphics->executeCommands(Array{ renderCommand }); Array<Gfx::ORenderCommand> commands;
commands.add(std::move(renderCommand));
graphics->executeCommands(std::move(commands));
graphics->endRenderPass(); graphics->endRenderPass();
} }
+4 -4
View File
@@ -73,10 +73,10 @@ void TextPass::beginFrame(const Component::Camera& cam)
void TextPass::render() void TextPass::render()
{ {
graphics->beginRenderPass(renderPass); graphics->beginRenderPass(renderPass);
Array<Gfx::PRenderCommand> commands; Array<Gfx::ORenderCommand> commands;
for(const auto& [fontAsset, res] : textResources) for(const auto& [fontAsset, res] : textResources)
{ {
Gfx::PRenderCommand command = graphics->createRenderCommand("TextPassCommand"); Gfx::ORenderCommand command = graphics->createRenderCommand("TextPassCommand");
command->setViewport(viewport); command->setViewport(viewport);
command->bindPipeline(pipeline); command->bindPipeline(pipeline);
for(const auto& resource : res) 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->pushConstants(layoutRef, Gfx::SE_SHADER_STAGE_VERTEX_BIT | Gfx::SE_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(TextData), &resource.textData);
//command->draw(4, static_cast<uint32>(resource.vertexBuffer->getNumVertices()), 0, 0); //command->draw(4, static_cast<uint32>(resource.vertexBuffer->getNumVertices()), 0, 0);
} }
commands.add(command); commands.add(std::move(command));
} }
graphics->executeCommands(commands); graphics->executeCommands(std::move(commands));
graphics->endRenderPass(); graphics->endRenderPass();
textResources.clear(); textResources.clear();
//co_return; //co_return;
+3 -1
View File
@@ -48,7 +48,9 @@ void UIPass::render()
command->bindVertexBuffer({elementBuffer}); command->bindVertexBuffer({elementBuffer});
command->bindDescriptor(descriptorSet); command->bindDescriptor(descriptorSet);
command->draw(4, static_cast<uint32>(renderElements.size()), 0, 0); command->draw(4, static_cast<uint32>(renderElements.size()), 0, 0);
graphics->executeCommands(Array{std::move(command)}); Array<Gfx::ORenderCommand> commands;
commands.add(std::move(command));
graphics->executeCommands(std::move(commands));
graphics->endRenderPass(); graphics->endRenderPass();
//co_return; //co_return;
-10
View File
@@ -22,16 +22,6 @@ namespace Seele
{ {
namespace Vulkan namespace Vulkan
{ {
enum class ShaderType
{
VERTEX = 0,
FRAGMENT = 1,
COMPUTE = 2,
TASK = 3,
MESH = 4,
};
VkDescriptorType cast(const Gfx::SeDescriptorType &descriptorType); VkDescriptorType cast(const Gfx::SeDescriptorType &descriptorType);
Gfx::SeDescriptorType cast(const VkDescriptorType &descriptorType); Gfx::SeDescriptorType cast(const VkDescriptorType &descriptorType);
VkShaderStageFlagBits cast(const Gfx::SeShaderStageFlagBits &stage); VkShaderStageFlagBits cast(const Gfx::SeShaderStageFlagBits &stage);
+1 -85
View File
@@ -8,9 +8,8 @@
using namespace Seele; using namespace Seele;
using namespace Seele::Vulkan; using namespace Seele::Vulkan;
Shader::Shader(PGraphics graphics, ShaderType shaderType, VkShaderStageFlags stage) Shader::Shader(PGraphics graphics, VkShaderStageFlags stage)
: graphics(graphics) : graphics(graphics)
, type(shaderType)
, stage(stage) , stage(stage)
{ {
} }
@@ -28,91 +27,8 @@ uint32 Seele::Vulkan::Shader::getShaderHash() const
return hash; 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) void Shader::create(const ShaderCreateInfo& createInfo)
{ {
entryPointName = createInfo.entryPoint;
thread_local Slang::ComPtr<slang::IGlobalSession> globalSession;
if(!globalSession)
{
slang::createGlobalSession(globalSession.writeRef());
}
slang::SessionDesc sessionDesc;
sessionDesc.flags = 0;
sessionDesc.defaultMatrixLayoutMode = SLANG_MATRIX_LAYOUT_COLUMN_MAJOR;
Array<slang::PreprocessorMacroDesc> 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<const char*, 3> searchPaths = {"shaders/", "shaders/lib/", "shaders/generated/"};
sessionDesc.searchPaths = searchPaths.data();
sessionDesc.searchPathCount = searchPaths.size();
Slang::ComPtr<slang::ISession> session;
CHECK_RESULT(globalSession->createSession(sessionDesc, session.writeRef()));
Slang::ComPtr<slang::IBlob> diagnostics;
Array<slang::IComponentType*> modules;
Slang::ComPtr<slang::IEntryPoint> 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<slang::IComponentType> moduleComposition;
session->createCompositeComponentType(modules.data(), modules.size(), moduleComposition.writeRef(), diagnostics.writeRef());
CHECK_DIAGNOSTICS();
Slang::ComPtr<slang::IComponentType> linkedProgram;
moduleComposition->link(linkedProgram.writeRef(), diagnostics.writeRef());
CHECK_DIAGNOSTICS();
slang::ProgramLayout* reflection = linkedProgram->getLayout(0, diagnostics.writeRef());
CHECK_DIAGNOSTICS();
Array<slang::SpecializationArg> specialization;
for(const auto& [key, value] : createInfo.typeParameter)
{
specialization.add(slang::SpecializationArg::fromType(reflection->findTypeByName(value)));
}
Slang::ComPtr<slang::IComponentType> specializedComponent;
linkedProgram->specialize(specialization.data(), specialization.size(), specializedComponent.writeRef(), diagnostics.writeRef());
CHECK_DIAGNOSTICS();
Slang::ComPtr<slang::IBlob> kernelBlob;
specializedComponent->getEntryPointCode(
0,
0,
kernelBlob.writeRef(),
diagnostics.writeRef()
);
CHECK_DIAGNOSTICS();
VkShaderModuleCreateInfo moduleInfo = VkShaderModuleCreateInfo moduleInfo =
{ {
+8 -16
View File
@@ -12,7 +12,7 @@ DECLARE_REF(DescriptorLayout)
class Shader class Shader
{ {
public: public:
Shader(PGraphics graphics, ShaderType shaderType, VkShaderStageFlags stage); Shader(PGraphics graphics, VkShaderStageFlags stage);
virtual ~Shader(); virtual ~Shader();
void create(const ShaderCreateInfo& createInfo); void create(const ShaderCreateInfo& createInfo);
@@ -26,44 +26,36 @@ public:
//SLang renames all entry points to main, so we dont need that //SLang renames all entry points to main, so we dont need that
return "main";//entryPointName.c_str(); return "main";//entryPointName.c_str();
} }
constexpr ShaderType getShaderType() const
{
return type;
}
constexpr VkShaderStageFlags getStage() const constexpr VkShaderStageFlags getStage() const
{ {
return stage; return stage;
} }
//Map<uint32, PDescriptorLayout> getDescriptorLayouts();
uint32 getShaderHash() const; uint32 getShaderHash() const;
private: private:
PGraphics graphics; PGraphics graphics;
//Map<uint32, PDescriptorLayout> descriptorSets;
VkShaderModule module; VkShaderModule module;
ShaderType type;
VkShaderStageFlags stage; VkShaderStageFlags stage;
std::string entryPointName;
uint32 hash; uint32 hash;
}; };
DEFINE_REF(Shader) DEFINE_REF(Shader)
template <typename Base, ShaderType shaderType, VkShaderStageFlags stageFlags> template <typename Base, VkShaderStageFlags stageFlags>
class ShaderBase : public Base, public Shader class ShaderBase : public Base, public Shader
{ {
public: public:
ShaderBase(PGraphics graphics) ShaderBase(PGraphics graphics)
: Shader(graphics, shaderType, stageFlags) : Shader(graphics, stageFlags)
{ {
} }
virtual ~ShaderBase() virtual ~ShaderBase()
{ {
} }
}; };
typedef ShaderBase<Gfx::VertexShader, ShaderType::VERTEX, VK_SHADER_STAGE_VERTEX_BIT> VertexShader; using VertexShader = ShaderBase<Gfx::VertexShader, VK_SHADER_STAGE_VERTEX_BIT>;
typedef ShaderBase<Gfx::FragmentShader, ShaderType::FRAGMENT, VK_SHADER_STAGE_FRAGMENT_BIT> FragmentShader; using FragmentShader = ShaderBase<Gfx::FragmentShader, VK_SHADER_STAGE_FRAGMENT_BIT>;
typedef ShaderBase<Gfx::ComputeShader, ShaderType::COMPUTE, VK_SHADER_STAGE_COMPUTE_BIT> ComputeShader; using ComputeShader = ShaderBase<Gfx::ComputeShader, VK_SHADER_STAGE_COMPUTE_BIT>;
typedef ShaderBase<Gfx::TaskShader, ShaderType::TASK, VK_SHADER_STAGE_TASK_BIT_EXT> TaskShader; using TaskShader = ShaderBase<Gfx::TaskShader, VK_SHADER_STAGE_TASK_BIT_EXT>;
typedef ShaderBase<Gfx::MeshShader, ShaderType::MESH, VK_SHADER_STAGE_MESH_BIT_EXT> MeshShader; using MeshShader = ShaderBase<Gfx::MeshShader, VK_SHADER_STAGE_MESH_BIT_EXT>;
DEFINE_REF(VertexShader) DEFINE_REF(VertexShader)
DEFINE_REF(FragmentShader) DEFINE_REF(FragmentShader)
+93
View File
@@ -0,0 +1,93 @@
#include "slang-compile.h"
#include <slang-com-ptr.h>
#include <slang.h>
#include "Containers/Array.h"
#include <fmt/core.h>
#include <iostream>
#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<slang::IBlob> Seele::generateShader(const ShaderCreateInfo& createInfo, SlangCompileTarget target)
{
thread_local Slang::ComPtr<slang::IGlobalSession> globalSession;
if(!globalSession)
{
slang::createGlobalSession(globalSession.writeRef());
}
slang::SessionDesc sessionDesc;
sessionDesc.flags = 0;
sessionDesc.defaultMatrixLayoutMode = SLANG_MATRIX_LAYOUT_COLUMN_MAJOR;
Array<slang::PreprocessorMacroDesc> 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<const char*, 3> searchPaths = {"shaders/", "shaders/lib/", "shaders/generated/"};
sessionDesc.searchPaths = searchPaths.data();
sessionDesc.searchPathCount = searchPaths.size();
Slang::ComPtr<slang::ISession> session;
CHECK_RESULT(globalSession->createSession(sessionDesc, session.writeRef()));
Slang::ComPtr<slang::IBlob> diagnostics;
Array<slang::IComponentType*> modules;
Slang::ComPtr<slang::IEntryPoint> 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<slang::IComponentType> moduleComposition;
session->createCompositeComponentType(modules.data(), modules.size(), moduleComposition.writeRef(), diagnostics.writeRef());
CHECK_DIAGNOSTICS();
Slang::ComPtr<slang::IComponentType> linkedProgram;
moduleComposition->link(linkedProgram.writeRef(), diagnostics.writeRef());
CHECK_DIAGNOSTICS();
slang::ProgramLayout* reflection = linkedProgram->getLayout(0, diagnostics.writeRef());
CHECK_DIAGNOSTICS();
Array<slang::SpecializationArg> specialization;
for(const auto& [key, value] : createInfo.typeParameter)
{
specialization.add(slang::SpecializationArg::fromType(reflection->findTypeByName(value)));
}
Slang::ComPtr<slang::IComponentType> specializedComponent;
linkedProgram->specialize(specialization.data(), specialization.size(), specializedComponent.writeRef(), diagnostics.writeRef());
CHECK_DIAGNOSTICS();
Slang::ComPtr<slang::IBlob> kernelBlob;
specializedComponent->getEntryPointCode(
0,
0,
kernelBlob.writeRef(),
diagnostics.writeRef()
);
CHECK_DIAGNOSTICS();
return kernelBlob;
}
+8
View File
@@ -0,0 +1,8 @@
#pragma once
#include "Graphics/Initializer.h"
#include <slang-com-ptr.h>
#include <slang.h>
namespace Seele {
Slang::ComPtr<slang::IBlob> generateShader(const ShaderCreateInfo& createInfo, SlangCompileTarget target);
}