Skip to content

Commit

Permalink
feat(rendering): add conditional shader compilation
Browse files Browse the repository at this point in the history
  • Loading branch information
tomas7770 committed Jan 25, 2025
1 parent da5f5e3 commit 245e738
Show file tree
Hide file tree
Showing 7 changed files with 111 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added

- SSAO resolution scale (#1423, **@tomas7770**).
- Conditional shader compilation (#1406, **@tomas7770**).

### Changed

Expand Down
1 change: 1 addition & 0 deletions engine/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ set(CUBOS_ENGINE_SOURCE
"src/render/defaults/target.cpp"
"src/render/shader/plugin.cpp"
"src/render/shader/shader.cpp"
"src/render/shader/shader_builder.cpp"
"src/render/shader/bridge.cpp"
"src/render/g_buffer/plugin.cpp"
"src/render/g_buffer/g_buffer.cpp"
Expand Down
15 changes: 13 additions & 2 deletions engine/include/cubos/engine/render/shader/shader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <cubos/core/reflection/reflect.hpp>

#include <cubos/engine/api.hpp>
#include <cubos/engine/render/shader/shader_builder.hpp>

namespace cubos::engine
{
Expand All @@ -22,14 +23,24 @@ namespace cubos::engine

/// @brief Constructs a shader from code.
/// @param shaderStage Shader stage created from GLSL code.
Shader(cubos::core::gl::ShaderStage shaderStage)
: mShaderStage(std::move(shaderStage)){};
/// @param renderDevice Render device used to create the shader.
/// @param stage Shader stage to create.
/// @param contents Shader source code.
Shader(cubos::core::gl::ShaderStage shaderStage, cubos::core::gl::RenderDevice& renderDevice,
cubos::core::gl::Stage stage, const std::string& contents)
: mShaderStage(std::move(shaderStage))
, mBuilder(renderDevice, stage, contents){};

/// @brief Returns the asset's shader stage.
/// @return Shader stage.
cubos::core::gl::ShaderStage shaderStage() const;

/// @brief Returns a shader builder to configure compile-time shader parameters.
/// @return Shader builder.
const ShaderBuilder& builder() const;

private:
cubos::core::gl::ShaderStage mShaderStage;
ShaderBuilder mBuilder;
};
} // namespace cubos::engine
60 changes: 60 additions & 0 deletions engine/include/cubos/engine/render/shader/shader_builder.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/// @file
/// @brief Class @ref cubos::engine::ShaderBuilder.
/// @ingroup render-shader-plugin

#pragma once

#include <string>

#include <cubos/core/gl/render_device.hpp>

#include <cubos/engine/api.hpp>

namespace cubos::engine
{
class Shader;

/// @brief Configures compile-time shader parameters using #define macros.
/// @ingroup render-shader-plugin
class CUBOS_ENGINE_API ShaderBuilder final
{
public:
/// @brief Creates a shader builder.
/// @param renderDevice Render device used to create the shader.
/// @param stage Shader stage to create.
/// @param contents Shader source code.
ShaderBuilder(cubos::core::gl::RenderDevice& renderDevice, const cubos::core::gl::Stage stage,
const std::string& contents)
: mRenderDevice(renderDevice)
, mStage(stage)
, mContents(contents){};

/// @brief Creates a shader builder, using the same render device and shader stage as another builder.
/// @param shaderBuilder Shader builder to copy parameters from.
/// @param contents Shader source code.
ShaderBuilder(const ShaderBuilder& shaderBuilder, const std::string& contents)
: mRenderDevice(shaderBuilder.mRenderDevice)
, mStage(shaderBuilder.mStage)
, mContents(contents){};

/// @brief Defines a parameter with no value.
/// @param defineName Parameter name to define.
/// @return New shader builder with the parameter defined.
ShaderBuilder with(const std::string& defineName) const;

/// @brief Defines a parameter with a value.
/// @param defineName Parameter name to define.
/// @param defineValue Parameter value.
/// @return New shader builder with the parameter defined.
ShaderBuilder with(const std::string& defineName, const std::string& defineValue) const;

/// @brief Compiles a shader from the source code stored in the builder.
/// @return Shader asset.
std::shared_ptr<Shader> build() const;

private:
cubos::core::gl::RenderDevice& mRenderDevice; ///< Render device used to create the shader.
const cubos::core::gl::Stage mStage; ///< Shader stage type to create.
const std::string mContents; ///< Shader source code.
};
} // namespace cubos::engine
2 changes: 1 addition & 1 deletion engine/src/render/shader/bridge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ bool ShaderBridge::loadFromFile(Assets& assets, const AnyAsset& handle, Stream&
}

// Store the asset's data.
assets.store(handle, Shader(shaderStage));
assets.store(handle, Shader(shaderStage, mRenderDevice, mStage, contents));
return true;
}

Expand Down
5 changes: 5 additions & 0 deletions engine/src/render/shader/shader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,8 @@ cubos::core::gl::ShaderStage Shader::shaderStage() const
{
return mShaderStage;
}

const ShaderBuilder& Shader::builder() const
{
return mBuilder;
}
30 changes: 30 additions & 0 deletions engine/src/render/shader/shader_builder.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#include <cubos/core/reflection/external/glm.hpp>
#include <cubos/core/reflection/external/primitives.hpp>
#include <cubos/core/reflection/traits/constructible.hpp>
#include <cubos/core/reflection/type.hpp>

#include <cubos/engine/render/shader/shader.hpp>
#include <cubos/engine/render/shader/shader_builder.hpp>

using namespace cubos::engine;

ShaderBuilder ShaderBuilder::with(const std::string& defineName) const
{
return ShaderBuilder(*this, "#define " + defineName + "\n" + mContents);
}

ShaderBuilder ShaderBuilder::with(const std::string& defineName, const std::string& defineValue) const
{
return ShaderBuilder(*this, "#define " + defineName + " " + defineValue + "\n" + mContents);
}

std::shared_ptr<Shader> ShaderBuilder::build() const
{
cubos::core::gl::ShaderStage shaderStage = mRenderDevice.createShaderStage(mStage, mContents.c_str());
if (shaderStage == nullptr)
{
CUBOS_ERROR("Shader asset stage creation failed");
return nullptr;
}
return std::make_shared<Shader>(shaderStage, mRenderDevice, mStage, mContents);
}

0 comments on commit 245e738

Please sign in to comment.