From b5958189cf2d2419f63ae3ccbfea7d0d31df0470 Mon Sep 17 00:00:00 2001 From: Dominic Masters Date: Tue, 17 Dec 2024 12:32:44 -0600 Subject: [PATCH] Some slang progress --- assets/shaders/hello-world.glsl | Bin 1628 -> 0 bytes assets/shaders/hello-world.slang | 61 ++++---- fragment.glsl | 80 ---------- lib/CMakeLists.txt | 2 +- src/dawn/CMakeLists.txt | 2 + src/dawn/asset/AssetLoader.cpp | 7 + src/dawn/asset/AssetLoader.hpp | 5 + src/dawn/asset/loader/CMakeLists.txt | 2 + src/dawn/asset/loader/ShaderLoader.cpp | 137 ++++++++++++++++++ src/dawn/asset/loader/ShaderLoader.hpp | 40 +++++ src/dawn/asset/loader/StringLoader.cpp | 38 +++++ src/dawn/asset/loader/StringLoader.hpp | 36 +++++ .../component/display/material/Material.cpp | 7 +- .../component/display/material/Material.hpp | 12 ++ .../material/SimpleTexturedMaterial.cpp | 8 + .../material/SimpleTexturedMaterial.hpp | 5 + src/dawn/display/shader/CMakeLists.txt | 2 + src/dawn/display/shader/ShaderManager.cpp | 48 ++++++ src/dawn/display/shader/ShaderManager.hpp | 45 +++++- .../shader/ShaderManagerSlangFileSystem.cpp | 78 ++++++++++ .../shader/ShaderManagerSlangFileSystem.hpp | 46 ++++++ src/dawn/game/IGame.cpp | 3 + src/dawn/game/IGame.hpp | 2 + src/dawn/util/String.cpp | 9 ++ src/dawn/util/String.hpp | 9 ++ src/dawnopengl/CMakeLists.txt | 1 - src/dawnopengl/display/Texture.hpp | 2 +- src/dawnopengl/display/shader/Shader.hpp | 21 +++ .../display/shader/SimpleTexturedShader.cpp | 57 +++----- .../display/material/MapMaterial.cpp | 8 + .../display/material/MapMaterial.hpp | 5 + src/dawnrpg/game/Game.cpp | 6 + vertex.glsl | 88 ----------- 33 files changed, 617 insertions(+), 255 deletions(-) delete mode 100644 assets/shaders/hello-world.glsl delete mode 100644 fragment.glsl create mode 100644 src/dawn/asset/loader/ShaderLoader.cpp create mode 100644 src/dawn/asset/loader/ShaderLoader.hpp create mode 100644 src/dawn/asset/loader/StringLoader.cpp create mode 100644 src/dawn/asset/loader/StringLoader.hpp create mode 100644 src/dawn/display/shader/ShaderManager.cpp create mode 100644 src/dawn/display/shader/ShaderManagerSlangFileSystem.cpp create mode 100644 src/dawn/display/shader/ShaderManagerSlangFileSystem.hpp delete mode 100644 vertex.glsl diff --git a/assets/shaders/hello-world.glsl b/assets/shaders/hello-world.glsl deleted file mode 100644 index cbccee48f545472665e8efd1d1236e58256815ba..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1628 zcmYk6?M@Rx6ov;{iUJDAmxy8!6%|D=jln2H;*Vlt4GCI*ZZ_>=O4<&Y?neCQ{df~z zf_LLbV&ePE?r4X+oH-x!p0n>vS{hv+H)A8_o-t-$V9lCQGa`H0l)TS=+Dw?T?5NO- zJAD#!!iKOZJQE%ZGde@fxKPsHq%7yh%#`?yi5hY0I_Jl!b@9g}I_cUtt)17RSGL=T zPpuoI?VZ}TF%_Mlp4E=i7z@WG+2c0{Z|l)f?BZUMCa&&mb{4(wcTTM94WhsR$GETO zY!)3kdz!S;j`g#{4;Qm#QL~eL%6k%H{w!+PcGC585JQQKDXsg*iym2Y7!Teh=V|5= zxndpjx`c5;44u-vtP!74SMjTjolz=CQb!gLd#m$_WTvIBRlX1 z+OK<3G4D|}PyWZnGwJUn>8I}Vk?r(TuUB*;*?S5$bcb6l|2cjZzIiwYXI(cwEn5+0 zghN$^J6V^{s!N%m8F}`skPk6*CiYSYF?tgFG88Knv2Q~$bf)gRz)ZZmHGviUTe<6f zv?fna^7zAf-Ya?flgA&<^Nv>q7J1%w@aJ?2-ZlTa^B#-Zqfu2@Qax`UpSc(GAML6F z=Qay}R(tZ-^&gEnLu^%CXiRLic)$1o)a86-b47c;0nMx8nJ;|u^U5sAhJMT1v#48< zg$IQE4eimMJl_g0`DJs_+?M5gn4fr9_$Vv}(EDl;L+>BzG$qUWt$K3&9!?1K!orQ-HwC!4 z2e|256^QSPhgtA{=^UJ#hl^VDx+9sDR6jK4H-t0Peb9~2kKYgC b)UrZf;=_IEA7 shader. cbuffer Uniforms { float4x4 u_Projection; float4x4 u_View; float4x4 u_Model; float4 u_Color; - int u_HasTexture; // Changed from bool to int for compatibility -} + bool u_HasTexture; + uniform Sampler2D u_Texture; +}; -// Per-vertex attributes to be assembled from bound vertex buffers. struct AssembledVertex { float3 position : POSITION; - float2 texcoord : TEXCOORD0; + float2 texcoord : TEXCOORD; }; -// Output of the vertex shader, and input to the fragment shader. -struct CoarseVertex { - float2 texcoord : TEXCOORD0; - float4 position : SV_Position; // Needed for rasterization -}; - -// Output of the fragment shader. struct Fragment { - float4 color : SV_Target; // SV_Target is required for color output + float4 color; }; -// Combined Texture and Sampler (avoids linking issues) -Texture2D textureMap; -SamplerState textureSampler; +struct VertexStageOutput { + float2 uv : UV; + float4 sv_position : SV_Position; +}; + +float4 someFunction(float4 color) { + return color * float4(0.5, 0.5, 0.5, 1.0); +} -// Vertex Shader [shader("vertex")] -CoarseVertex vertexMain(AssembledVertex assembledVertex) { - CoarseVertex output; +VertexStageOutput vertexMain(AssembledVertex assembledVertex) { + VertexStageOutput output; - // Transform vertex position using Model-View-Projection matrix - float4 worldPosition = mul(u_Model, float4(assembledVertex.position, 1.0)); - float4 viewPosition = mul(u_View, worldPosition); - output.position = mul(u_Projection, viewPosition); + float3 position = assembledVertex.position; - // Pass through texture coordinates - output.texcoord = assembledVertex.texcoord; + output.uv = assembledVertex.texcoord; + + output.sv_position = mul( + float4(position, 1.0), + mul(u_Model, mul(u_View, u_Projection)) + ); return output; } -// Fragment Shader [shader("fragment")] -Fragment fragmentMain(CoarseVertex coarseVertex) { +Fragment fragmentMain(float2 uv: UV) : SV_Target { Fragment output; - - // Sample the texture if a texture is bound - if (u_HasTexture != 0) { - output.color = textureMap.Sample(textureSampler, coarseVertex.texcoord); + if(u_HasTexture) { + output.color = u_Texture.Sample(uv) * u_Color; } else { - // Use the uniform color if no texture is bound - output.color = u_Color; + output.color = someFunction(u_Color); } - return output; } \ No newline at end of file diff --git a/fragment.glsl b/fragment.glsl deleted file mode 100644 index 725ae456..00000000 --- a/fragment.glsl +++ /dev/null @@ -1,80 +0,0 @@ -#version 450 -layout(column_major) uniform; -layout(column_major) buffer; - -#line 1883 0 -struct _MatrixStorage_float4x4std140_0 -{ - vec4 data_0[4]; -}; - - -#line 7 1 -struct SLANG_ParameterGroup_Uniforms_std140_0 -{ - _MatrixStorage_float4x4std140_0 u_Projection_0; - _MatrixStorage_float4x4std140_0 u_View_0; - _MatrixStorage_float4x4std140_0 u_Model_0; - vec4 u_Color_0; - bool u_HasTexture_0; -}; - - -#line 2 -layout(binding = 0) -layout(std140) uniform block_SLANG_ParameterGroup_Uniforms_std140_0 -{ - _MatrixStorage_float4x4std140_0 u_Projection_0; - _MatrixStorage_float4x4std140_0 u_View_0; - _MatrixStorage_float4x4std140_0 u_Model_0; - vec4 u_Color_0; - bool u_HasTexture_0; -}Uniforms_0; -layout(binding = 1) -uniform sampler2D u_Texture_0; - - -#line 4811 0 -layout(location = 0) -out vec4 entryPointParam_fragmentMain_color_0; - - -#line 4811 -layout(location = 0) -in vec2 uv_0; - - -#line 21 1 -struct Fragment_0 -{ - vec4 color_0; -}; - - -#line 49 -void main() -{ - - Fragment_0 output_0; - if(Uniforms_0.u_HasTexture_0) - { - -#line 54 - output_0.color_0 = (texture((u_Texture_0), (uv_0))) * Uniforms_0.u_Color_0; - -#line 53 - } - else - { - output_0.color_0 = Uniforms_0.u_Color_0; - -#line 53 - } - -#line 53 - entryPointParam_fragmentMain_color_0 = output_0.color_0; - -#line 53 - return; -} - diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index de4fdb56..272c8ea1 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -57,7 +57,7 @@ endif() FetchContent_Declare( slang GIT_REPOSITORY https://github.com/shader-slang/slang - GIT_TAG v2024.15.1 + GIT_TAG v2024.17 ) FetchContent_MakeAvailable(slang) diff --git a/src/dawn/CMakeLists.txt b/src/dawn/CMakeLists.txt index c907e0c4..bdde05a6 100644 --- a/src/dawn/CMakeLists.txt +++ b/src/dawn/CMakeLists.txt @@ -10,6 +10,7 @@ target_link_libraries(${DAWN_TARGET_NAME} glm::glm nlohmann_json::nlohmann_json freetype + slang ) # Includes @@ -37,5 +38,6 @@ add_subdirectory(ui) # Assets tool_copy(en en.json) +tool_copy(helloShader shaders/hello-world.slang) add_dependencies(${DAWN_TARGET_NAME} dawnassets) \ No newline at end of file diff --git a/src/dawn/asset/AssetLoader.cpp b/src/dawn/asset/AssetLoader.cpp index d289b5e8..d13f0445 100644 --- a/src/dawn/asset/AssetLoader.cpp +++ b/src/dawn/asset/AssetLoader.cpp @@ -5,6 +5,7 @@ #include "AssetLoader.hpp" #include "assert/assert.hpp" +#include "asset/AssetManager.hpp" using namespace Dawn; @@ -27,6 +28,12 @@ std::shared_ptr AssetLoader::getAssetManager() { return am; } +void AssetLoader::loadImmediately() { + while(!this->loaded) { + this->getAssetManager()->update(); + } +} + AssetLoader::~AssetLoader() { this->loaded = false; } \ No newline at end of file diff --git a/src/dawn/asset/AssetLoader.hpp b/src/dawn/asset/AssetLoader.hpp index 3c4f6be9..18c62d32 100644 --- a/src/dawn/asset/AssetLoader.hpp +++ b/src/dawn/asset/AssetLoader.hpp @@ -57,6 +57,11 @@ namespace Dawn { * @return The asset manager. */ std::shared_ptr getAssetManager(); + + /** + * Load the asset immediately, this is blocking on the main thread. + */ + void loadImmediately(); /** * Dispose the asset item. diff --git a/src/dawn/asset/loader/CMakeLists.txt b/src/dawn/asset/loader/CMakeLists.txt index 74e37390..61c1481f 100644 --- a/src/dawn/asset/loader/CMakeLists.txt +++ b/src/dawn/asset/loader/CMakeLists.txt @@ -9,6 +9,8 @@ target_sources(${DAWN_TARGET_NAME} TextureLoader.cpp JSONLoader.cpp TrueTypeLoader.cpp + ShaderLoader.cpp + StringLoader.cpp ) # Subdirs diff --git a/src/dawn/asset/loader/ShaderLoader.cpp b/src/dawn/asset/loader/ShaderLoader.cpp new file mode 100644 index 00000000..b57ffb1c --- /dev/null +++ b/src/dawn/asset/loader/ShaderLoader.cpp @@ -0,0 +1,137 @@ +// Copyright (c) 2024 Dominic Masters +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +#include "ShaderLoader.hpp" +#include "assert/assert.hpp" +#include "asset/AssetManager.hpp" +#include "game/Game.hpp" + +#include + +using namespace Dawn; + +const std::string ShaderLoader::ASSET_TYPE = "shader"; + +ShaderLoader::ShaderLoader( + const std::shared_ptr assetManager, + const std::string name +) : + AssetLoader(assetManager, name), + state(ShaderLoaderState::INITIAL) +{ +} + +void ShaderLoader::updateAsync() { +} + +void ShaderLoader::updateSync() { + if(state != ShaderLoaderState::INITIAL) return; + + this->state = ShaderLoaderState::LOADING; + assertFalse(loaded, "ShaderLoader already loaded."); + + auto sm = this->getAssetManager()->getGame()->shaderManager; + + // Load the shader string + Slang::ComPtr diagnostics; + module = sm->session->loadModule( + this->name.c_str(), + diagnostics.writeRef() + ); + + // Get list of entry points and create components + int32_t definedEntryPointCount = module->getDefinedEntryPointCount(); + IComponentType** components = new IComponentType*[definedEntryPointCount + 1]; + int32_t j = 0; + + components[j++] = module; + + for(auto i = 0; i < definedEntryPointCount; i++) { + Slang::ComPtr ep; + auto result = module->getDefinedEntryPoint(i, ep.writeRef()); + + if(result != SLANG_OK) { + assertUnreachable("Failed to get entry point."); + return; + } + + auto name = ep->getFunctionReflection()->getName(); + std::cout << "Found entry point: " << name << std::endl; + entryPoints.push_back(std::string(name)); + components[j++] = ep; + } + + // Create the composite component type + sm->session->createCompositeComponentType( + components, + sizeof(components) / sizeof(components[0]), + program.writeRef() + ); + + // Link the program. + auto result = program->link(linkedProgram.writeRef(), diagnostics.writeRef()); + if(diagnostics) { + assertUnreachable("%s\n", (const char*) diagnostics->getBufferPointer()); + return; + } + + // result + Slang::ComPtr blob; + auto result2 = linkedProgram->getEntryPointCode( + 0, + 0, + blob.writeRef(), + diagnostics.writeRef() + ); + + if(diagnostics) { + assertUnreachable("%s\n", (const char*) diagnostics->getBufferPointer()); + } + + this->state = ShaderLoaderState::LOADED; + this->loaded = true; +} + +std::string ShaderLoader::getAssetType() const { + return ShaderLoader::ASSET_TYPE; +} + +std::string ShaderLoader::getEntryPointCode(const std::string &entryPoint) { + assertTrue(loaded, "ShaderLoader not loaded."); + assertNotNull(linkedProgram, "ShaderLoader linkedProgram is null."); + + // Get the entry point index + int32_t entryIndex = -1; + for(auto i = 0; i < entryPoints.size(); i++) { + if(entryPoints[i] != entryPoint) continue; + entryIndex = i; + break; + } + assertTrue(entryIndex != -1, "EntryPoint not found."); + + // Find the entry point code + Slang::ComPtr blob; + Slang::ComPtr diagnostics; + auto result = linkedProgram->getEntryPointCode( + entryIndex, + 0, + blob.writeRef(), + diagnostics.writeRef() + ); + + if(diagnostics) { + assertUnreachable("%s\n", (const char*) diagnostics->getBufferPointer()); + return ""; + } + + return std::string((const char*)blob->getBufferPointer()); +} + +ShaderLoader::~ShaderLoader() { + if(linkedProgram) { + linkedProgram->release(); + linkedProgram = nullptr; + } +} \ No newline at end of file diff --git a/src/dawn/asset/loader/ShaderLoader.hpp b/src/dawn/asset/loader/ShaderLoader.hpp new file mode 100644 index 00000000..0e5c04f7 --- /dev/null +++ b/src/dawn/asset/loader/ShaderLoader.hpp @@ -0,0 +1,40 @@ +// Copyright (c) 2024 Dominic Masters +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +#pragma once +#include "asset/AssetLoader.hpp" +#include "asset/AssetDataLoader.hpp" +#include "display/shader/ShaderManager.hpp" + +namespace Dawn { + enum class ShaderLoaderState { + INITIAL, + LOADING, + LOADED + }; + + class ShaderLoader : public AssetLoader { + protected: + enum ShaderLoaderState state; + + public: + const static std::string ASSET_TYPE; + + std::vector entryPoints; + Slang::ComPtr linkedProgram; + Slang::ComPtr program; + IModule* module; + + ShaderLoader( + const std::shared_ptr assetManager, + const std::string name + ); + void updateSync() override; + void updateAsync() override; + std::string getAssetType() const override; + std::string getEntryPointCode(const std::string &entryPoint); + ~ShaderLoader(); + }; +} \ No newline at end of file diff --git a/src/dawn/asset/loader/StringLoader.cpp b/src/dawn/asset/loader/StringLoader.cpp new file mode 100644 index 00000000..e7d24f64 --- /dev/null +++ b/src/dawn/asset/loader/StringLoader.cpp @@ -0,0 +1,38 @@ +// Copyright (c) 2024 Dominic Masters +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +#include "StringLoader.hpp" + +using namespace Dawn; + +const std::string StringLoader::ASSET_TYPE = "string"; + +StringLoader::StringLoader( + const std::shared_ptr assetManager, + const std::string name +) : + AssetLoader(assetManager, name), + loader(name), + state(StringLoaderState::INITIAL) +{ +} + +void StringLoader::updateSync() { +} + +void StringLoader::updateAsync() { + if(this->state != StringLoaderState::INITIAL) return; + this->state = StringLoaderState::LOADING_STRING; + this->data = this->loader.getEntireContentsAsString(); + this->state = StringLoaderState::DONE; + this->loaded = true; +} + +std::string StringLoader::getAssetType() const { + return StringLoader::ASSET_TYPE; +} + +StringLoader::~StringLoader() { +} \ No newline at end of file diff --git a/src/dawn/asset/loader/StringLoader.hpp b/src/dawn/asset/loader/StringLoader.hpp new file mode 100644 index 00000000..2c6545cc --- /dev/null +++ b/src/dawn/asset/loader/StringLoader.hpp @@ -0,0 +1,36 @@ +// Copyright (c) 2024 Dominic Masters +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +#pragma once +#include "asset/AssetLoader.hpp" +#include "asset/AssetDataLoader.hpp" + +namespace Dawn { + enum class StringLoaderState { + INITIAL, + LOADING_STRING, + DONE + }; + + class StringLoader : public AssetLoader { + protected: + AssetDataLoader loader; + enum StringLoaderState state; + + public: + const static std::string ASSET_TYPE; + + std::string data; + + StringLoader( + const std::shared_ptr assetManager, + const std::string name + ); + void updateSync() override; + void updateAsync() override; + std::string getAssetType() const override; + ~StringLoader(); + }; +} \ No newline at end of file diff --git a/src/dawn/component/display/material/Material.cpp b/src/dawn/component/display/material/Material.cpp index 59bbf643..63b6b7ac 100644 --- a/src/dawn/component/display/material/Material.cpp +++ b/src/dawn/component/display/material/Material.cpp @@ -4,13 +4,16 @@ // https://opensource.org/licenses/MIT #include "Material.hpp" +#include "game/Game.hpp" using namespace Dawn; void Material::onInit() { - + this->lockedShaders = this->getLockedShaders( + getGame()->renderHost->shaderManager + ); } void Material::onDispose() { - + this->lockedShaders.clear(); } \ No newline at end of file diff --git a/src/dawn/component/display/material/Material.hpp b/src/dawn/component/display/material/Material.hpp index 76b2e466..55efec6f 100644 --- a/src/dawn/component/display/material/Material.hpp +++ b/src/dawn/component/display/material/Material.hpp @@ -12,7 +12,19 @@ namespace Dawn { public SceneComponent, public IRenderableComponent { + private: + std::vector> lockedShaders; + protected: + /** + * Locks the shaders to be used for rendering. + * + * @param shaderManager Shader manager to use. + * @return List of shaders to be used. + */ + virtual std::vector> getLockedShaders( + ShaderManager &shaderManager + ) = 0; public: void onInit() override; diff --git a/src/dawn/component/display/material/SimpleTexturedMaterial.cpp b/src/dawn/component/display/material/SimpleTexturedMaterial.cpp index 4a16fded..19f7e6f4 100644 --- a/src/dawn/component/display/material/SimpleTexturedMaterial.cpp +++ b/src/dawn/component/display/material/SimpleTexturedMaterial.cpp @@ -9,6 +9,14 @@ using namespace Dawn; +std::vector< + std::shared_ptr +> SimpleTexturedMaterial::getLockedShaders(ShaderManager &shaderManager) { + return { + shaderManager.getShader() + }; +} + void SimpleTexturedMaterial::load(std::shared_ptr ctx) { if(ctx->data.contains("color")) { this->setColor(JSON::color(ctx->data["color"])); diff --git a/src/dawn/component/display/material/SimpleTexturedMaterial.hpp b/src/dawn/component/display/material/SimpleTexturedMaterial.hpp index ac13e8b4..5a364e16 100644 --- a/src/dawn/component/display/material/SimpleTexturedMaterial.hpp +++ b/src/dawn/component/display/material/SimpleTexturedMaterial.hpp @@ -14,6 +14,11 @@ namespace Dawn { struct SimpleTexturedShaderData data; std::shared_ptr texture; + protected: + std::vector> getLockedShaders( + ShaderManager &shaderManager + ) override; + public: void load(std::shared_ptr ctx) override; diff --git a/src/dawn/display/shader/CMakeLists.txt b/src/dawn/display/shader/CMakeLists.txt index 1d4aa6a9..7bf594f0 100644 --- a/src/dawn/display/shader/CMakeLists.txt +++ b/src/dawn/display/shader/CMakeLists.txt @@ -8,4 +8,6 @@ target_sources(${DAWN_TARGET_NAME} PRIVATE IShader.cpp IShaderStage.cpp + ShaderManager.cpp + ShaderManagerSlangFileSystem.cpp ) \ No newline at end of file diff --git a/src/dawn/display/shader/ShaderManager.cpp b/src/dawn/display/shader/ShaderManager.cpp new file mode 100644 index 00000000..b897b485 --- /dev/null +++ b/src/dawn/display/shader/ShaderManager.cpp @@ -0,0 +1,48 @@ +// Copyright (c) 2024 Dominic Masters +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +#include "ShaderManager.hpp" +#include "assert/assert.hpp" + +using namespace Dawn; + +ShaderManager::ShaderManager() { +} + +void ShaderManager::init(const std::shared_ptr &game) { + assertNotNull(game, "Game instance must not be null."); + + this->game = game; + + // Create the file system + this->fileSystem.sm = shared_from_this(); + + // Create the global session + createGlobalSession(globalSession.writeRef()); + + // Set the target description, TODO: interface + targetDescription.format = SLANG_GLSL; + targetDescription.profile = globalSession->findProfile("glsl_330"); + + // Set the session description + sessionDescription.targets = &targetDescription; + sessionDescription.targetCount = 1; + sessionDescription.searchPathCount = 0; + sessionDescription.fileSystem = &this->fileSystem; + + // Create session + globalSession->createSession(sessionDescription, session.writeRef()); +} + +std::shared_ptr ShaderManager::getGame() { + auto game = this->game.lock(); + assertNotNull(game, "Game instance must not be null."); + return game; +} + +ShaderManager::~ShaderManager() { + // Clear all shaders + shaders.clear(); +} \ No newline at end of file diff --git a/src/dawn/display/shader/ShaderManager.hpp b/src/dawn/display/shader/ShaderManager.hpp index 864e9e11..193e339b 100644 --- a/src/dawn/display/shader/ShaderManager.hpp +++ b/src/dawn/display/shader/ShaderManager.hpp @@ -5,13 +5,45 @@ #pragma once #include "display/shader/Shader.hpp" +#include "ShaderManagerSlangFileSystem.hpp" +using namespace slang; namespace Dawn { - class ShaderManager { + class Game; + class ShaderLoader; + + class ShaderManager : public std::enable_shared_from_this { private: - std::vector> shaders; + std::vector> shaders; + + std::weak_ptr game; + ShaderManagerSlangFileSystem fileSystem; + + Slang::ComPtr globalSession; + TargetDesc targetDescription; + SessionDesc sessionDescription; + Slang::ComPtr session; public: + /** + * Creates a new shader manager. + */ + ShaderManager(); + + /** + * Initializes the shader manager. + * + * @param game The game instance that the shader manager is being used in. + */ + void init(const std::shared_ptr &game); + + /** + * Retreives the game instance. + * + * @return Game instance. + */ + std::shared_ptr getGame(); + /** * Retreives an instance of the shader from the shader manager. If the * shader does not exist it will be created. @@ -23,8 +55,7 @@ namespace Dawn { std::shared_ptr getShader() { auto itShaders = shaders.begin(); while(itShaders != shaders.end()) { - // auto shader = itShaders->lock(); - auto shader = *itShaders; + auto shader = itShaders->lock(); if(!shader) { itShaders = shaders.erase(itShaders); continue; @@ -44,8 +75,8 @@ namespace Dawn { /** * Disposes of all shaders. */ - ~ShaderManager() { - shaders.clear(); - } + ~ShaderManager(); + + friend class ShaderLoader; }; } \ No newline at end of file diff --git a/src/dawn/display/shader/ShaderManagerSlangFileSystem.cpp b/src/dawn/display/shader/ShaderManagerSlangFileSystem.cpp new file mode 100644 index 00000000..f8538f83 --- /dev/null +++ b/src/dawn/display/shader/ShaderManagerSlangFileSystem.cpp @@ -0,0 +1,78 @@ +// Copyright (c) 2024 Dominic Masters +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +#include "ShaderManagerSlangFileSystem.hpp" +#include "assert/assert.hpp" +#include "display/shader/ShaderManager.hpp" +#include "game/Game.hpp" +#include "asset/loader/StringLoader.hpp" +#include "util/String.hpp" + +using namespace Dawn; + +void const * ShaderManagerSlangString::getBufferPointer() { + return this->str.c_str(); +} + +size_t ShaderManagerSlangString::getBufferSize() { + return this->str.size(); +} + +SlangResult ShaderManagerSlangString::queryInterface( + SlangUUID const& uuid, + void** outObject +) { + return SLANG_E_NOT_IMPLEMENTED; +} + +uint32_t ShaderManagerSlangString::addRef() { + return refs++; +} + +uint32_t ShaderManagerSlangString::release() { + return refs--; +} + +// + +SlangResult ShaderManagerSlangFileSystem::loadFile( + const char* path, + ISlangBlob** outBlob +) { + auto shaderManager = this->sm.lock(); + assertNotNull(shaderManager, "ShaderManager must not be null."); + + if(!String::endsWith(path, ".slang")) return SLANG_E_NOT_FOUND; + + std::cout << "Loading: " << path << std::endl; + auto loader = shaderManager->getGame()->assetManager->get(path); + loader->loadImmediately(); + + auto blob = new ShaderManagerSlangString(); + blob->str = loader->data; + *outBlob = blob; + + std::cout << "Loaded: " << path << std::endl; + return SLANG_OK; +} + +SlangResult ShaderManagerSlangFileSystem::queryInterface( + SlangUUID const& uuid, + void** outObject +) { + return SLANG_E_NOT_IMPLEMENTED; +} + +uint32_t ShaderManagerSlangFileSystem::addRef() { + return refs++; +} + +uint32_t ShaderManagerSlangFileSystem::release() { + return refs--; +} + +void * ShaderManagerSlangFileSystem::castAs(SlangUUID const& uuid) { + return nullptr; +} \ No newline at end of file diff --git a/src/dawn/display/shader/ShaderManagerSlangFileSystem.hpp b/src/dawn/display/shader/ShaderManagerSlangFileSystem.hpp new file mode 100644 index 00000000..403a5b22 --- /dev/null +++ b/src/dawn/display/shader/ShaderManagerSlangFileSystem.hpp @@ -0,0 +1,46 @@ +// Copyright (c) 2024 Dominic Masters +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +#pragma once +#include "dawn.hpp" +#include "slang.h" +#include "slang-gfx.h" +#include "slang-com-ptr.h" +using namespace slang; + +namespace Dawn { + class ShaderManager; + + struct ShaderManagerSlangString : public ISlangBlob { + std::string str; + uint32_t refs = 0; + + void const* getBufferPointer() override; + size_t getBufferSize() override; + SlangResult queryInterface(SlangUUID const& uuid, void** outObject) override; + uint32_t addRef() override; + uint32_t release() override; + }; + + struct ShaderManagerSlangFileSystem : public ISlangFileSystem { + private: + std::weak_ptr sm; + uint32_t refs = 0; + + public: + SlangResult loadFile( + const char* path, + ISlangBlob** outBlob + ) override; + + SlangResult queryInterface(SlangUUID const& uuid, void** outObject) override; + + uint32_t addRef() override; + uint32_t release() override; + void * castAs(SlangUUID const& uuid) override; + + friend class ShaderManager; + }; +} \ No newline at end of file diff --git a/src/dawn/game/IGame.cpp b/src/dawn/game/IGame.cpp index 0adc9dcc..94d76f7d 100644 --- a/src/dawn/game/IGame.cpp +++ b/src/dawn/game/IGame.cpp @@ -62,6 +62,9 @@ void IGame::init() { settingsManager->init(selfAsGame); settingsManager->load(); + shaderManager = std::make_shared(); + shaderManager->init(shared_from_this()); + this->initManagers(); // TEST diff --git a/src/dawn/game/IGame.hpp b/src/dawn/game/IGame.hpp index f4da0638..7f084fce 100644 --- a/src/dawn/game/IGame.hpp +++ b/src/dawn/game/IGame.hpp @@ -13,6 +13,7 @@ #include "locale/LocaleManager.hpp" #include "save/SaveManager.hpp" #include "settings/SettingsManager.hpp" +#include "display/shader/ShaderManager.hpp" #ifdef DAWN_ENABLE_PHYSICS #include "physics/PhysicsManager.hpp" @@ -59,6 +60,7 @@ namespace Dawn { std::shared_ptr assetManager; std::shared_ptr localeManager; std::shared_ptr settingsManager; + std::shared_ptr shaderManager; #ifdef DAWN_ENABLE_PHYSICS std::shared_ptr physicsManager; diff --git a/src/dawn/util/String.cpp b/src/dawn/util/String.cpp index cf8ba655..e1da5ab7 100644 --- a/src/dawn/util/String.cpp +++ b/src/dawn/util/String.cpp @@ -33,4 +33,13 @@ std::vector String::split( res.push_back(s.substr(posStart)); return res; +} + +bool_t String::endsWith(const std::string &str, const std::string &needle) { + if(str.length() >= needle.length()) { + return (0 == str.compare( + str.length() - needle.length(), needle.length(), needle + )); + } + return false; } \ No newline at end of file diff --git a/src/dawn/util/String.hpp b/src/dawn/util/String.hpp index dce7d94e..6184e4c8 100644 --- a/src/dawn/util/String.hpp +++ b/src/dawn/util/String.hpp @@ -37,5 +37,14 @@ namespace Dawn { const std::string &str, const std::string &delim ); + + /** + * Checks if the given string starts with the given needle. + * + * @param str String to check. + * @param needle String to check for. + * @return True if the string starts with the needle. + */ + static bool_t endsWith(const std::string &str, const std::string &needle); }; } \ No newline at end of file diff --git a/src/dawnopengl/CMakeLists.txt b/src/dawnopengl/CMakeLists.txt index 3d093640..8d986ed8 100644 --- a/src/dawnopengl/CMakeLists.txt +++ b/src/dawnopengl/CMakeLists.txt @@ -6,7 +6,6 @@ # Libraries target_link_libraries(${DAWN_TARGET_NAME} PUBLIC - slang ) # Includes diff --git a/src/dawnopengl/display/Texture.hpp b/src/dawnopengl/display/Texture.hpp index 9c54dbf7..a6a1f9fb 100644 --- a/src/dawnopengl/display/Texture.hpp +++ b/src/dawnopengl/display/Texture.hpp @@ -17,7 +17,7 @@ namespace Dawn { int32_t width = -1; int32_t height = -1; GLuint id = -1; - GLuint samplerId = -1; + // GLuint samplerId = -1; TextureFormat format; TextureDataFormat dataFormat; diff --git a/src/dawnopengl/display/shader/Shader.hpp b/src/dawnopengl/display/shader/Shader.hpp index 86109020..c4829bb1 100644 --- a/src/dawnopengl/display/shader/Shader.hpp +++ b/src/dawnopengl/display/shader/Shader.hpp @@ -87,6 +87,27 @@ namespace Dawn { assertNoGLError(); assertTrue(status == GL_TRUE, "Failed to link shader program."); + std::vector uniformNames; + GLint numUniforms = 0; + + // Get the number of active uniforms + glGetProgramiv(shaderProgram, GL_ACTIVE_UNIFORMS, &numUniforms); + assertNoGLError(); + + // Iterate through each uniform + // for (GLint i = 0; i < numUniforms; ++i) { + // char name[256]; + // GLsizei length; + // GLint size; + // GLenum type; + + // // Get the uniform name + // glGetActiveUniform(shaderProgram, i, sizeof(name), &length, &size, &type, name); + // assertNoGLError(); + // std::cout << "Uniform: " << i << ":" << name << std::endl; + // // uniformNames.push_back(std::string(name)); + // } + // Map parameters correctly. std::for_each( parameters.begin(), diff --git a/src/dawnopengl/display/shader/SimpleTexturedShader.cpp b/src/dawnopengl/display/shader/SimpleTexturedShader.cpp index 9e86130c..ac432c56 100644 --- a/src/dawnopengl/display/shader/SimpleTexturedShader.cpp +++ b/src/dawnopengl/display/shader/SimpleTexturedShader.cpp @@ -30,19 +30,14 @@ void SimpleTexturedShader::getStages( float4x4 u_Model; float4 u_Color; bool u_HasTexture; + uniform Sampler2D u_Texture; }; - layout(binding = 1) - uniform Sampler2D u_Texture; - struct AssembledVertex { float3 position : POSITION; float2 texcoord : TEXCOORD; }; - struct CoarseVertex { - }; - struct Fragment { float4 color; }; @@ -126,8 +121,6 @@ void SimpleTexturedShader::getStages( program.writeRef() ); - slang::ProgramLayout* layout = program->getLayout(); - Slang::ComPtr linkedProgram; auto result = program->link(linkedProgram.writeRef(), diagnostics.writeRef()); std::cout << "Result: " << result << std::endl; @@ -150,6 +143,21 @@ void SimpleTexturedShader::getStages( return; } + slang::ProgramLayout* layout = program->getLayout(); + unsigned parameterCount = layout->getParameterCount(); + for(unsigned pp = 0; pp < parameterCount; pp++) { + slang::VariableLayoutReflection* parameter = layout->getParameterByIndex(pp); + std::cout << "Parameter: " << parameter->getName() << std::endl; + + auto layout = parameter->getTypeLayout(); + auto fields = layout->getFieldCount(); + for(unsigned ff = 0; ff < fields; ff++) { + slang::VariableLayoutReflection* field = layout->getFieldByIndex(ff); + std::string fieldName = field->getName(); + std::cout << "Field: " << fieldName << std::endl; + } + } + std::string vertexString = (const char*)vertexBlob->getBufferPointer(); std::ofstream out("/home/yourwishes/htdocs/Dawn/vertex.glsl"); out << vertexString; @@ -220,40 +228,9 @@ void SimpleTexturedShader::getStages( } )); - // Parameters - // parameters.push_back(ShaderParameter( - // "u_Projection", - // &rel->projection, - // ShaderParameterType::MAT4 - // )); - - // parameters.push_back(ShaderParameter( - // "u_View", - // &rel->view, - // ShaderParameterType::MAT4 - // )); - - // parameters.push_back(ShaderParameter( - // "u_Model", - // &rel->model, - // ShaderParameterType::MAT4 - // )); - - // parameters.push_back(ShaderParameter( - // "u_Color", - // &rel->color, - // ShaderParameterType::COLOR - // )); - - // parameters.push_back(ShaderParameter( - // "u_HasTexture", - // &rel->hasTexture, - // ShaderParameterType::BOOLEAN - // )); - parameters.push_back(ShaderParameter( - "u_Texture_0", + "Uniforms_u_Texture_0", &rel->texture, ShaderParameterType::TEXTURE )); diff --git a/src/dawnrpg/component/display/material/MapMaterial.cpp b/src/dawnrpg/component/display/material/MapMaterial.cpp index 655272ce..b05b26a9 100644 --- a/src/dawnrpg/component/display/material/MapMaterial.cpp +++ b/src/dawnrpg/component/display/material/MapMaterial.cpp @@ -9,6 +9,14 @@ using namespace Dawn; +std::vector< + std::shared_ptr +> MapMaterial::getLockedShaders(ShaderManager &shaderManager) { + return { + shaderManager.getShader() + }; +} + void MapMaterial::load(std::shared_ptr ctx) { if(ctx->data.contains("color")) { this->setColor(JSON::color(ctx->data["color"])); diff --git a/src/dawnrpg/component/display/material/MapMaterial.hpp b/src/dawnrpg/component/display/material/MapMaterial.hpp index 48d8759d..d1b8e935 100644 --- a/src/dawnrpg/component/display/material/MapMaterial.hpp +++ b/src/dawnrpg/component/display/material/MapMaterial.hpp @@ -10,6 +10,11 @@ namespace Dawn { class MapMaterial : public Material { + protected: + std::vector> getLockedShaders( + ShaderManager &shaderManager + ) override; + private: struct MapShaderData data; std::shared_ptr texture; diff --git a/src/dawnrpg/game/Game.cpp b/src/dawnrpg/game/Game.cpp index 562e8497..43d0c69d 100644 --- a/src/dawnrpg/game/Game.cpp +++ b/src/dawnrpg/game/Game.cpp @@ -11,6 +11,8 @@ #include "component/RPGPlayer.hpp" #include "component/RPGMap.hpp" +#include "asset/loader/ShaderLoader.hpp" + using namespace Dawn; Game::Game() : IGame() { @@ -27,6 +29,10 @@ std::string Game::getInitialScene() { void Game::initManagers() { this->rpgManager = std::make_shared(); this->rpgManager->init(shared_from_this()); + + auto sl = assetManager->get("shaders/hello-world.slang"); + sl->loadImmediately(); + auto code = sl->getEntryPointCode("vertexMain"); } Game::~Game() { diff --git a/vertex.glsl b/vertex.glsl deleted file mode 100644 index 4945646b..00000000 --- a/vertex.glsl +++ /dev/null @@ -1,88 +0,0 @@ -#version 450 -layout(column_major) uniform; -layout(column_major) buffer; - -#line 1312 0 -struct _MatrixStorage_float4x4std140_0 -{ - vec4 data_0[4]; -}; - - -#line 7 1 -struct SLANG_ParameterGroup_Uniforms_std140_0 -{ - _MatrixStorage_float4x4std140_0 u_Projection_0; - _MatrixStorage_float4x4std140_0 u_View_0; - _MatrixStorage_float4x4std140_0 u_Model_0; - vec4 u_Color_0; - bool u_HasTexture_0; -}; - - -#line 2 -layout(binding = 0) -layout(std140) uniform block_SLANG_ParameterGroup_Uniforms_std140_0 -{ - _MatrixStorage_float4x4std140_0 u_Projection_0; - _MatrixStorage_float4x4std140_0 u_View_0; - _MatrixStorage_float4x4std140_0 u_Model_0; - vec4 u_Color_0; - bool u_HasTexture_0; -}Uniforms_0; - -#line 2 -mat4x4 unpackStorage_0(_MatrixStorage_float4x4std140_0 _S1) -{ - -#line 2 - return mat4x4(_S1.data_0[0][0], _S1.data_0[0][1], _S1.data_0[0][2], _S1.data_0[0][3], _S1.data_0[1][0], _S1.data_0[1][1], _S1.data_0[1][2], _S1.data_0[1][3], _S1.data_0[2][0], _S1.data_0[2][1], _S1.data_0[2][2], _S1.data_0[2][3], _S1.data_0[3][0], _S1.data_0[3][1], _S1.data_0[3][2], _S1.data_0[3][3]); -} - - -#line 13 -layout(location = 0) -out vec2 entryPointParam_vertexMain_uv_0; - - -#line 13 -layout(location = 0) -in vec3 assembledVertex_position_0; - - -#line 13 -layout(location = 1) -in vec2 assembledVertex_texcoord_0; - - -#line 25 -struct VertexStageOutput_0 -{ - vec2 uv_0; - vec4 sv_position_0; -}; - -void main() -{ - - VertexStageOutput_0 output_0; - - - - output_0.uv_0 = assembledVertex_texcoord_0; - - output_0.sv_position_0 = (((((((((unpackStorage_0(Uniforms_0.u_Projection_0)) * (unpackStorage_0(Uniforms_0.u_View_0))))) * (unpackStorage_0(Uniforms_0.u_Model_0))))) * (vec4(assembledVertex_position_0, 1.0)))); - -#line 45 - VertexStageOutput_0 _S2 = output_0; - -#line 45 - entryPointParam_vertexMain_uv_0 = output_0.uv_0; - -#line 45 - gl_Position = _S2.sv_position_0; - -#line 45 - return; -} -