Commit current work
Reworked conditions, added uber-shaders, comparison nodes, fixed Discard
This commit is contained in:
@@ -17,30 +17,48 @@ namespace Nz
|
||||
friend class MaterialPipeline;
|
||||
|
||||
public:
|
||||
struct UniformOffsets;
|
||||
|
||||
BasicMaterial(Material& material);
|
||||
|
||||
inline void EnableAlphaTest(bool alphaTest);
|
||||
|
||||
inline const std::shared_ptr<Texture>& GetAlphaMap() const;
|
||||
float GetAlphaThreshold() const;
|
||||
inline const std::shared_ptr<TextureSampler>& GetAlphaSampler() const;
|
||||
float GetAlphaTestThreshold() const;
|
||||
Color GetDiffuseColor() const;
|
||||
inline const std::shared_ptr<Texture>& GetDiffuseMap() const;
|
||||
inline const std::shared_ptr<TextureSampler>& GetDiffuseSampler() const;
|
||||
|
||||
inline bool HasAlphaMap() const;
|
||||
inline bool HasAlphaThreshold() const;
|
||||
inline bool HasAlphaTest() const;
|
||||
inline bool HasAlphaTestThreshold() const;
|
||||
inline bool HasDiffuseColor() const;
|
||||
inline bool HasDiffuseMap() const;
|
||||
|
||||
inline void SetAlphaMap(std::shared_ptr<Texture> alphaMap);
|
||||
void SetAlphaThreshold(float alphaThreshold);
|
||||
inline void SetAlphaSampler(std::shared_ptr<TextureSampler> alphaSampler);
|
||||
void SetAlphaTestThreshold(float alphaThreshold);
|
||||
void SetDiffuseColor(const Color& diffuse);
|
||||
inline void SetDiffuseMap(std::shared_ptr<Texture> diffuseMap);
|
||||
inline void SetDiffuseSampler(std::shared_ptr<TextureSampler> diffuseSampler);
|
||||
|
||||
static const std::shared_ptr<MaterialSettings>& GetSettings();
|
||||
static inline const UniformOffsets& GetOffsets();
|
||||
static inline const std::shared_ptr<MaterialSettings>& GetSettings();
|
||||
|
||||
private:
|
||||
struct UniformOffsets
|
||||
{
|
||||
std::size_t alphaThreshold;
|
||||
std::size_t diffuseColor;
|
||||
std::size_t totalSize;
|
||||
};
|
||||
|
||||
private:
|
||||
struct ConditionIndexes
|
||||
{
|
||||
std::size_t alphaTest;
|
||||
std::size_t hasAlphaMap;
|
||||
std::size_t hasDiffuseMap;
|
||||
};
|
||||
|
||||
struct TextureIndexes
|
||||
@@ -54,11 +72,13 @@ namespace Nz
|
||||
|
||||
Material& m_material;
|
||||
std::size_t m_uniformBlockIndex;
|
||||
ConditionIndexes m_conditionIndexes;
|
||||
TextureIndexes m_textureIndexes;
|
||||
UniformOffsets m_uniformOffsets;
|
||||
|
||||
static std::shared_ptr<MaterialSettings> s_materialSettings;
|
||||
static std::size_t s_uniformBlockIndex;
|
||||
static ConditionIndexes s_conditionIndexes;
|
||||
static TextureIndexes s_textureIndexes;
|
||||
static UniformOffsets s_uniformOffsets;
|
||||
};
|
||||
|
||||
@@ -9,24 +9,47 @@
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
inline void BasicMaterial::EnableAlphaTest(bool alphaTest)
|
||||
{
|
||||
NazaraAssert(HasAlphaTest(), "Material has no alpha test condition");
|
||||
m_material.EnableCondition(m_conditionIndexes.alphaTest, alphaTest);
|
||||
}
|
||||
|
||||
inline const std::shared_ptr<Texture>& BasicMaterial::GetAlphaMap() const
|
||||
{
|
||||
NazaraAssert(HasAlphaMap(), "Material has no alpha map slot");
|
||||
NazaraAssert(HasAlphaMap(), "Material has no alpha texture slot");
|
||||
return m_material.GetTexture(m_textureIndexes.alpha);
|
||||
}
|
||||
|
||||
inline const std::shared_ptr<TextureSampler>& BasicMaterial::GetAlphaSampler() const
|
||||
{
|
||||
NazaraAssert(HasAlphaMap(), "Material has no alpha texture slot");
|
||||
return m_material.GetTextureSampler(m_textureIndexes.alpha);
|
||||
}
|
||||
|
||||
inline const std::shared_ptr<Texture>& BasicMaterial::GetDiffuseMap() const
|
||||
{
|
||||
NazaraAssert(HasDiffuseMap(), "Material has no alpha map slot");
|
||||
NazaraAssert(HasDiffuseMap(), "Material has no alpha texture slot");
|
||||
return m_material.GetTexture(m_textureIndexes.diffuse);
|
||||
}
|
||||
|
||||
inline const std::shared_ptr<TextureSampler>& BasicMaterial::GetDiffuseSampler() const
|
||||
{
|
||||
NazaraAssert(HasDiffuseMap(), "Material has no alpha texture slot");
|
||||
return m_material.GetTextureSampler(m_textureIndexes.diffuse);
|
||||
}
|
||||
|
||||
inline bool BasicMaterial::HasAlphaMap() const
|
||||
{
|
||||
return m_textureIndexes.alpha != MaterialSettings::InvalidIndex;
|
||||
}
|
||||
|
||||
inline bool BasicMaterial::HasAlphaThreshold() const
|
||||
inline bool BasicMaterial::HasAlphaTest() const
|
||||
{
|
||||
return m_conditionIndexes.alphaTest != MaterialSettings::InvalidIndex;
|
||||
}
|
||||
|
||||
inline bool BasicMaterial::HasAlphaTestThreshold() const
|
||||
{
|
||||
return m_uniformOffsets.alphaThreshold != MaterialSettings::InvalidIndex;
|
||||
}
|
||||
@@ -44,13 +67,43 @@ namespace Nz
|
||||
inline void BasicMaterial::SetAlphaMap(std::shared_ptr<Texture> alphaMap)
|
||||
{
|
||||
NazaraAssert(HasAlphaMap(), "Material has no alpha map slot");
|
||||
bool hasAlphaMap = (alphaMap != nullptr);
|
||||
m_material.SetTexture(m_textureIndexes.alpha, std::move(alphaMap));
|
||||
|
||||
if (m_conditionIndexes.hasDiffuseMap != MaterialSettings::InvalidIndex)
|
||||
m_material.EnableCondition(m_conditionIndexes.hasAlphaMap, hasAlphaMap);
|
||||
}
|
||||
|
||||
inline void BasicMaterial::SetAlphaSampler(std::shared_ptr<TextureSampler> alphaSampler)
|
||||
{
|
||||
NazaraAssert(HasAlphaMap(), "Material has no alpha map slot");
|
||||
m_material.SetTextureSampler(m_textureIndexes.alpha, std::move(alphaSampler));
|
||||
}
|
||||
|
||||
inline void BasicMaterial::SetDiffuseMap(std::shared_ptr<Texture> diffuseMap)
|
||||
{
|
||||
NazaraAssert(HasDiffuseMap(), "Material has no diffuse map slot");
|
||||
bool hasDiffuseMap = (diffuseMap != nullptr);
|
||||
m_material.SetTexture(m_textureIndexes.diffuse, std::move(diffuseMap));
|
||||
|
||||
if (m_conditionIndexes.hasDiffuseMap != MaterialSettings::InvalidIndex)
|
||||
m_material.EnableCondition(m_conditionIndexes.hasDiffuseMap, hasDiffuseMap);
|
||||
}
|
||||
|
||||
inline void BasicMaterial::SetDiffuseSampler(std::shared_ptr<TextureSampler> diffuseSampler)
|
||||
{
|
||||
NazaraAssert(HasDiffuseMap(), "Material has no diffuse map slot");
|
||||
m_material.SetTextureSampler(m_textureIndexes.diffuse, std::move(diffuseSampler));
|
||||
}
|
||||
|
||||
inline const std::shared_ptr<MaterialSettings>& BasicMaterial::GetSettings()
|
||||
{
|
||||
return s_materialSettings;
|
||||
}
|
||||
|
||||
inline auto BasicMaterial::GetOffsets() -> const UniformOffsets&
|
||||
{
|
||||
return s_uniformOffsets;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ namespace Nz
|
||||
inline void EnableAlphaTest(bool alphaTest);
|
||||
inline void EnableBlending(bool blending);
|
||||
inline void EnableColorWrite(bool colorWrite);
|
||||
inline void EnableCondition(std::size_t conditionIndex, bool enable);
|
||||
inline void EnableDepthBuffer(bool depthBuffer);
|
||||
inline void EnableDepthSorting(bool depthSorting);
|
||||
inline void EnableDepthWrite(bool depthWrite);
|
||||
@@ -53,7 +54,7 @@ namespace Nz
|
||||
inline void EnableVertexColor(bool vertexColor);
|
||||
|
||||
inline void EnsurePipelineUpdate() const;
|
||||
|
||||
|
||||
inline RendererComparison GetDepthCompareFunc() const;
|
||||
inline BlendFunc GetDstBlend() const;
|
||||
inline FaceSide GetFaceCulling() const;
|
||||
@@ -63,7 +64,7 @@ namespace Nz
|
||||
inline const MaterialPipelineInfo& GetPipelineInfo() const;
|
||||
inline float GetPointSize() const;
|
||||
inline const std::shared_ptr<const MaterialSettings>& GetSettings() const;
|
||||
inline const std::shared_ptr<ShaderStage>& GetShader(ShaderStageType shaderStage) const;
|
||||
inline const std::shared_ptr<UberShader>& GetShader(ShaderStageType shaderStage) const;
|
||||
inline BlendFunc GetSrcBlend() const;
|
||||
inline const std::shared_ptr<Texture>& GetTexture(std::size_t textureIndex) const;
|
||||
inline const std::shared_ptr<TextureSampler>& GetTextureSampler(std::size_t textureIndex) const;
|
||||
@@ -76,6 +77,7 @@ namespace Nz
|
||||
inline bool IsAlphaTestEnabled() const;
|
||||
inline bool IsBlendingEnabled() const;
|
||||
inline bool IsColorWriteEnabled() const;
|
||||
inline bool IsConditionEnabled(std::size_t conditionIndex) const;
|
||||
inline bool IsDepthBufferEnabled() const;
|
||||
inline bool IsDepthSortingEnabled() const;
|
||||
inline bool IsDepthWriteEnabled() const;
|
||||
@@ -92,7 +94,6 @@ namespace Nz
|
||||
inline void SetFaceFilling(FaceFilling filling);
|
||||
inline void SetLineWidth(float lineWidth);
|
||||
inline void SetPointSize(float pointSize);
|
||||
inline void SetShader(ShaderStageType shaderStage, std::shared_ptr<ShaderStage> shader);
|
||||
inline void SetUniformBuffer(std::size_t bufferIndex, UniformBufferRef uniformBuffer);
|
||||
inline void SetSrcBlend(BlendFunc func);
|
||||
inline void SetTexture(std::size_t textureIndex, std::shared_ptr<Texture> texture);
|
||||
@@ -115,7 +116,8 @@ namespace Nz
|
||||
std::vector<MaterialTexture> m_textures;
|
||||
std::vector<UniformBufferRef> m_uniformBuffers;
|
||||
mutable std::shared_ptr<MaterialPipeline> m_pipeline;
|
||||
MaterialPipelineInfo m_pipelineInfo;
|
||||
UInt32 m_enabledConditions;
|
||||
mutable MaterialPipelineInfo m_pipelineInfo;
|
||||
mutable bool m_pipelineUpdated;
|
||||
bool m_shadowCastingEnabled;
|
||||
};
|
||||
|
||||
@@ -111,6 +111,15 @@ namespace Nz
|
||||
InvalidatePipeline();
|
||||
}
|
||||
|
||||
inline void Material::EnableCondition(std::size_t conditionIndex, bool enable)
|
||||
{
|
||||
if (TestBit<UInt64>(m_enabledConditions, conditionIndex) != enable)
|
||||
{
|
||||
m_enabledConditions = SetBit<UInt64>(m_enabledConditions, conditionIndex);
|
||||
InvalidatePipeline();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Enable/Disable depth buffer for this material
|
||||
*
|
||||
@@ -428,9 +437,9 @@ namespace Nz
|
||||
* \brief Gets the über-shader used by this material
|
||||
* \return Constant pointer to the über-shader used
|
||||
*/
|
||||
inline const std::shared_ptr<ShaderStage>& Material::GetShader(ShaderStageType shaderStage) const
|
||||
inline const std::shared_ptr<UberShader>& Material::GetShader(ShaderStageType shaderStage) const
|
||||
{
|
||||
return m_pipelineInfo.shaders[UnderlyingCast(shaderStage)];
|
||||
return m_pipelineInfo.shaders[UnderlyingCast(shaderStage)].uberShader;
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -507,6 +516,11 @@ namespace Nz
|
||||
return m_pipelineInfo.colorWrite;
|
||||
}
|
||||
|
||||
inline bool Material::IsConditionEnabled(std::size_t conditionIndex) const
|
||||
{
|
||||
return TestBit<UInt64>(m_enabledConditions, conditionIndex);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether this material has depth buffer enabled
|
||||
* \return true If it is the case
|
||||
@@ -682,22 +696,6 @@ namespace Nz
|
||||
InvalidatePipeline();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the shader with a constant reference to a ubershader
|
||||
*
|
||||
* \param uberShader Uber shader to apply
|
||||
*
|
||||
* \remark Invalidates the pipeline
|
||||
*
|
||||
* \see GetShader
|
||||
*/
|
||||
inline void Material::SetShader(ShaderStageType shaderStage, std::shared_ptr<ShaderStage> shader)
|
||||
{
|
||||
m_pipelineInfo.shaders[UnderlyingCast(shaderStage)] = std::move(shader);
|
||||
|
||||
InvalidatePipeline();
|
||||
}
|
||||
|
||||
inline void Material::SetUniformBuffer(std::size_t bufferIndex, UniformBufferRef uniformBuffer)
|
||||
{
|
||||
NazaraAssert(bufferIndex < m_uniformBuffers.size(), "Invalid shared uniform buffer index");
|
||||
@@ -739,6 +737,19 @@ namespace Nz
|
||||
|
||||
inline void Material::UpdatePipeline() const
|
||||
{
|
||||
for (auto& shader : m_pipelineInfo.shaders)
|
||||
shader.enabledConditions = 0;
|
||||
|
||||
const auto& conditions = m_settings->GetConditions();
|
||||
for (std::size_t conditionIndex = 0; conditionIndex < conditions.size(); ++conditionIndex)
|
||||
{
|
||||
if (TestBit<UInt64>(m_enabledConditions, conditionIndex))
|
||||
{
|
||||
for (std::size_t shaderStage = 0; shaderStage < ShaderStageTypeCount; ++shaderStage)
|
||||
m_pipelineInfo.shaders[shaderStage].enabledConditions |= conditions[conditionIndex].enabledConditions[shaderStage];
|
||||
}
|
||||
}
|
||||
|
||||
m_pipeline = MaterialPipeline::Get(m_pipelineInfo);
|
||||
m_pipelineUpdated = true;
|
||||
}
|
||||
|
||||
@@ -17,18 +17,24 @@
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class ShaderStage;
|
||||
class UberShader;
|
||||
|
||||
struct MaterialPipelineInfo : RenderStates
|
||||
{
|
||||
struct ShaderStage
|
||||
{
|
||||
std::shared_ptr<UberShader> uberShader;
|
||||
Nz::UInt64 enabledConditions = 0;
|
||||
};
|
||||
|
||||
bool alphaTest = false;
|
||||
bool depthSorting = false;
|
||||
bool hasVertexColor = false;
|
||||
bool reflectionMapping = false;
|
||||
bool shadowReceive = true;
|
||||
|
||||
std::array<ShaderStage, ShaderStageTypeCount> shaders;
|
||||
std::shared_ptr<const MaterialSettings> settings;
|
||||
std::array<std::shared_ptr<ShaderStage>, ShaderStageTypeCount> shaders;
|
||||
};
|
||||
|
||||
inline bool operator==(const MaterialPipelineInfo& lhs, const MaterialPipelineInfo& rhs);
|
||||
|
||||
@@ -40,7 +40,10 @@ namespace Nz
|
||||
|
||||
for (std::size_t i = 0; i < lhs.shaders.size(); ++i)
|
||||
{
|
||||
if (lhs.shaders[i] != rhs.shaders[i])
|
||||
if (lhs.shaders[i].enabledConditions != rhs.shaders[i].enabledConditions)
|
||||
return false;
|
||||
|
||||
if (lhs.shaders[i].uberShader != rhs.shaders[i].uberShader)
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -82,7 +85,10 @@ namespace std
|
||||
NazaraPipelineMember(settings.get()); //< Hash pointer
|
||||
|
||||
for (const auto& shader : pipelineInfo.shaders)
|
||||
Nz::HashCombine(seed, shader.get());
|
||||
{
|
||||
Nz::HashCombine(seed, shader.enabledConditions);
|
||||
Nz::HashCombine(seed, shader.uberShader.get());
|
||||
}
|
||||
|
||||
#undef NazaraPipelineMember
|
||||
#undef NazaraPipelineBoolMember
|
||||
|
||||
@@ -19,29 +19,35 @@
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class UberShader;
|
||||
|
||||
class MaterialSettings
|
||||
{
|
||||
public:
|
||||
using DefaultShaders = std::array<std::shared_ptr<ShaderStage>, ShaderStageTypeCount>;
|
||||
using PredefinedBinding = std::array<std::size_t, PredefinedShaderBindingCount>;
|
||||
using Shaders = std::array<std::shared_ptr<UberShader>, ShaderStageTypeCount>;
|
||||
|
||||
struct Builder;
|
||||
struct Condition;
|
||||
struct SharedUniformBlock;
|
||||
struct Texture;
|
||||
struct UniformBlock;
|
||||
|
||||
inline MaterialSettings();
|
||||
inline MaterialSettings(std::vector<Texture> textures, std::vector<UniformBlock> uniformBlocks, std::vector<SharedUniformBlock> sharedUniformBlocks, const PredefinedBinding& predefinedBinding, DefaultShaders defaultShaders);
|
||||
inline MaterialSettings(Builder builder);
|
||||
MaterialSettings(const MaterialSettings&) = default;
|
||||
MaterialSettings(MaterialSettings&&) = delete;
|
||||
~MaterialSettings() = default;
|
||||
|
||||
inline const std::shared_ptr<ShaderStage>& GetDefaultShader(ShaderStageType stage) const;
|
||||
inline const DefaultShaders& GetDefaultShaders() const;
|
||||
inline const std::vector<Condition>& GetConditions() const;
|
||||
inline std::size_t GetConditionIndex(const std::string_view& name) const;
|
||||
inline std::size_t GetPredefinedBindingIndex(PredefinedShaderBinding binding) const;
|
||||
inline const std::shared_ptr<RenderPipelineLayout>& GetRenderPipelineLayout() const;
|
||||
inline const std::shared_ptr<UberShader>& GetShader(ShaderStageType stage) const;
|
||||
inline const Shaders& GetShaders() const;
|
||||
inline const std::vector<SharedUniformBlock>& GetSharedUniformBlocks() const;
|
||||
inline std::size_t GetSharedUniformBlockVariableOffset(std::size_t uniformBlockIndex, const std::string_view& name) const;
|
||||
inline std::size_t GetSharedUniformBlockIndex(const std::string_view& name) const;
|
||||
inline std::size_t GetSharedUniformBlockVariableOffset(std::size_t uniformBlockIndex, const std::string_view& name) const;
|
||||
inline const std::vector<Texture>& GetTextures() const;
|
||||
inline std::size_t GetTextureIndex(const std::string_view& name) const;
|
||||
inline const std::vector<UniformBlock>& GetUniformBlocks() const;
|
||||
@@ -53,6 +59,22 @@ namespace Nz
|
||||
|
||||
static constexpr std::size_t InvalidIndex = std::numeric_limits<std::size_t>::max();
|
||||
|
||||
struct Builder
|
||||
{
|
||||
PredefinedBinding predefinedBinding;
|
||||
Shaders shaders;
|
||||
std::vector<Condition> conditions;
|
||||
std::vector<Texture> textures;
|
||||
std::vector<UniformBlock> uniformBlocks;
|
||||
std::vector<SharedUniformBlock> sharedUniformBlocks;
|
||||
};
|
||||
|
||||
struct Condition
|
||||
{
|
||||
std::string name;
|
||||
std::array<UInt64, ShaderStageTypeCount> enabledConditions;
|
||||
};
|
||||
|
||||
struct UniformVariable
|
||||
{
|
||||
std::string name;
|
||||
@@ -84,11 +106,7 @@ namespace Nz
|
||||
|
||||
private:
|
||||
std::shared_ptr<RenderPipelineLayout> m_pipelineLayout;
|
||||
std::vector<SharedUniformBlock> m_sharedUniformBlocks;
|
||||
std::vector<Texture> m_textures;
|
||||
std::vector<UniformBlock> m_uniformBlocks;
|
||||
DefaultShaders m_defaultShaders;
|
||||
PredefinedBinding m_predefinedBinding;
|
||||
Builder m_data;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -10,22 +10,18 @@
|
||||
namespace Nz
|
||||
{
|
||||
inline MaterialSettings::MaterialSettings() :
|
||||
MaterialSettings({}, {}, {}, { InvalidIndex }, {})
|
||||
MaterialSettings(Builder{})
|
||||
{
|
||||
}
|
||||
|
||||
inline MaterialSettings::MaterialSettings(std::vector<Texture> textures, std::vector<UniformBlock> uniformBlocks, std::vector<SharedUniformBlock> sharedUniformBlocks, const PredefinedBinding& predefinedBindings, DefaultShaders defaultShaders) :
|
||||
m_sharedUniformBlocks(std::move(sharedUniformBlocks)),
|
||||
m_textures(std::move(textures)),
|
||||
m_uniformBlocks(std::move(uniformBlocks)),
|
||||
m_defaultShaders(std::move(defaultShaders)),
|
||||
m_predefinedBinding(predefinedBindings)
|
||||
inline MaterialSettings::MaterialSettings(Builder data) :
|
||||
m_data(std::move(data))
|
||||
{
|
||||
RenderPipelineLayoutInfo info;
|
||||
|
||||
unsigned int bindingIndex = 0;
|
||||
|
||||
for (const Texture& textureInfo : m_textures)
|
||||
for (const Texture& textureInfo : m_data.textures)
|
||||
{
|
||||
info.bindings.push_back({
|
||||
//textureInfo.bindingPoint,
|
||||
@@ -35,7 +31,7 @@ namespace Nz
|
||||
});
|
||||
}
|
||||
|
||||
for (const UniformBlock& ubo : m_uniformBlocks)
|
||||
for (const UniformBlock& ubo : m_data.uniformBlocks)
|
||||
{
|
||||
info.bindings.push_back({
|
||||
//ubo.bindingPoint,
|
||||
@@ -45,7 +41,7 @@ namespace Nz
|
||||
});
|
||||
}
|
||||
|
||||
for (const SharedUniformBlock& ubo : m_sharedUniformBlocks)
|
||||
for (const SharedUniformBlock& ubo : m_data.sharedUniformBlocks)
|
||||
{
|
||||
info.bindings.push_back({
|
||||
//ubo.bindingPoint,
|
||||
@@ -58,19 +54,25 @@ namespace Nz
|
||||
m_pipelineLayout = Graphics::Instance()->GetRenderDevice().InstantiateRenderPipelineLayout(std::move(info));
|
||||
}
|
||||
|
||||
inline const std::shared_ptr<ShaderStage>& MaterialSettings::GetDefaultShader(ShaderStageType stage) const
|
||||
inline auto MaterialSettings::GetConditions() const -> const std::vector<Condition>&
|
||||
{
|
||||
return m_defaultShaders[UnderlyingCast(stage)];
|
||||
return m_data.conditions;
|
||||
}
|
||||
|
||||
inline auto MaterialSettings::GetDefaultShaders() const -> const DefaultShaders&
|
||||
inline std::size_t MaterialSettings::GetConditionIndex(const std::string_view& name) const
|
||||
{
|
||||
return m_defaultShaders;
|
||||
for (std::size_t i = 0; i < m_data.conditions.size(); ++i)
|
||||
{
|
||||
if (m_data.conditions[i].name == name)
|
||||
return i;
|
||||
}
|
||||
|
||||
return InvalidIndex;
|
||||
}
|
||||
|
||||
inline std::size_t MaterialSettings::GetPredefinedBindingIndex(PredefinedShaderBinding binding) const
|
||||
{
|
||||
return m_predefinedBinding[UnderlyingCast(binding)];
|
||||
return m_data.predefinedBinding[UnderlyingCast(binding)];
|
||||
}
|
||||
|
||||
inline const std::shared_ptr<RenderPipelineLayout>& MaterialSettings::GetRenderPipelineLayout() const
|
||||
@@ -78,32 +80,37 @@ namespace Nz
|
||||
return m_pipelineLayout;
|
||||
}
|
||||
|
||||
inline const std::shared_ptr<UberShader>& MaterialSettings::GetShader(ShaderStageType stage) const
|
||||
{
|
||||
return m_data.shaders[UnderlyingCast(stage)];
|
||||
}
|
||||
|
||||
inline auto MaterialSettings::GetShaders() const -> const Shaders&
|
||||
{
|
||||
return m_data.shaders;
|
||||
}
|
||||
|
||||
inline auto MaterialSettings::GetSharedUniformBlocks() const -> const std::vector<SharedUniformBlock>&
|
||||
{
|
||||
return m_sharedUniformBlocks;
|
||||
return m_data.sharedUniformBlocks;
|
||||
}
|
||||
|
||||
inline std::size_t MaterialSettings::GetSharedUniformBlockIndex(const std::string_view& name) const
|
||||
{
|
||||
for (std::size_t i = 0; i < m_sharedUniformBlocks.size(); ++i)
|
||||
for (std::size_t i = 0; i < m_data.sharedUniformBlocks.size(); ++i)
|
||||
{
|
||||
if (m_sharedUniformBlocks[i].name == name)
|
||||
if (m_data.sharedUniformBlocks[i].name == name)
|
||||
return i;
|
||||
}
|
||||
|
||||
return InvalidIndex;
|
||||
}
|
||||
|
||||
inline auto MaterialSettings::GetTextures() const -> const std::vector<Texture>&
|
||||
{
|
||||
return m_textures;
|
||||
}
|
||||
|
||||
inline std::size_t MaterialSettings::GetSharedUniformBlockVariableOffset(std::size_t uniformBlockIndex, const std::string_view& name) const
|
||||
{
|
||||
assert(uniformBlockIndex < m_sharedUniformBlocks.size());
|
||||
assert(uniformBlockIndex < m_data.sharedUniformBlocks.size());
|
||||
|
||||
const std::vector<UniformVariable>& variables = m_sharedUniformBlocks[uniformBlockIndex].uniforms;
|
||||
const std::vector<UniformVariable>& variables = m_data.sharedUniformBlocks[uniformBlockIndex].uniforms;
|
||||
for (std::size_t i = 0; i < variables.size(); ++i)
|
||||
{
|
||||
if (variables[i].name == name)
|
||||
@@ -113,11 +120,16 @@ namespace Nz
|
||||
return InvalidIndex;
|
||||
}
|
||||
|
||||
inline auto MaterialSettings::GetTextures() const -> const std::vector<Texture>&
|
||||
{
|
||||
return m_data.textures;
|
||||
}
|
||||
|
||||
inline std::size_t MaterialSettings::GetTextureIndex(const std::string_view& name) const
|
||||
{
|
||||
for (std::size_t i = 0; i < m_textures.size(); ++i)
|
||||
for (std::size_t i = 0; i < m_data.textures.size(); ++i)
|
||||
{
|
||||
if (m_textures[i].name == name)
|
||||
if (m_data.textures[i].name == name)
|
||||
return i;
|
||||
}
|
||||
|
||||
@@ -126,14 +138,14 @@ namespace Nz
|
||||
|
||||
inline auto MaterialSettings::GetUniformBlocks() const -> const std::vector<UniformBlock>&
|
||||
{
|
||||
return m_uniformBlocks;
|
||||
return m_data.uniformBlocks;
|
||||
}
|
||||
|
||||
inline std::size_t MaterialSettings::GetUniformBlockIndex(const std::string_view& name) const
|
||||
{
|
||||
for (std::size_t i = 0; i < m_uniformBlocks.size(); ++i)
|
||||
for (std::size_t i = 0; i < m_data.uniformBlocks.size(); ++i)
|
||||
{
|
||||
if (m_uniformBlocks[i].name == name)
|
||||
if (m_data.uniformBlocks[i].name == name)
|
||||
return i;
|
||||
}
|
||||
|
||||
@@ -142,9 +154,9 @@ namespace Nz
|
||||
|
||||
inline std::size_t MaterialSettings::GetUniformBlockVariableOffset(std::size_t uniformBlockIndex, const std::string_view& name) const
|
||||
{
|
||||
assert(uniformBlockIndex < m_uniformBlocks.size());
|
||||
assert(uniformBlockIndex < m_data.uniformBlocks.size());
|
||||
|
||||
const std::vector<UniformVariable>& variables = m_uniformBlocks[uniformBlockIndex].uniforms;
|
||||
const std::vector<UniformVariable>& variables = m_data.uniformBlocks[uniformBlockIndex].uniforms;
|
||||
for (std::size_t i = 0; i < variables.size(); ++i)
|
||||
{
|
||||
if (variables[i].name == name)
|
||||
|
||||
39
include/Nazara/Graphics/UberShader.hpp
Normal file
39
include/Nazara/Graphics/UberShader.hpp
Normal file
@@ -0,0 +1,39 @@
|
||||
// Copyright (C) 2017 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Graphics module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_UBER_SHADER_HPP
|
||||
#define NAZARA_UBER_SHADER_HPP
|
||||
|
||||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <Nazara/Core/Bitset.hpp>
|
||||
#include <Nazara/Graphics/Config.hpp>
|
||||
#include <Nazara/Shader/ShaderAst.hpp>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class ShaderStage;
|
||||
|
||||
class NAZARA_GRAPHICS_API UberShader
|
||||
{
|
||||
public:
|
||||
inline UberShader(ShaderAst shaderAst);
|
||||
~UberShader() = default;
|
||||
|
||||
UInt64 GetConditionFlagByName(const std::string_view& condition) const;
|
||||
|
||||
const std::shared_ptr<ShaderStage>& Get(UInt64 combination);
|
||||
|
||||
private:
|
||||
std::unordered_map<UInt64 /*combination*/, std::shared_ptr<ShaderStage>> m_combinations;
|
||||
ShaderAst m_shaderAst;
|
||||
UInt64 m_combinationMask;
|
||||
};
|
||||
}
|
||||
|
||||
#include <Nazara/Graphics/UberShader.inl>
|
||||
|
||||
#endif // NAZARA_UBER_SHADER_HPP
|
||||
12
include/Nazara/Graphics/UberShader.inl
Normal file
12
include/Nazara/Graphics/UberShader.inl
Normal file
@@ -0,0 +1,12 @@
|
||||
// Copyright (C) 2017 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Graphics module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Graphics/UberShader.hpp>
|
||||
#include <Nazara/Graphics/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
}
|
||||
|
||||
#include <Nazara/Graphics/DebugOff.hpp>
|
||||
@@ -36,6 +36,7 @@ namespace Nz
|
||||
std::shared_ptr<CommandPool> InstantiateCommandPool(QueueType queueType) override;
|
||||
std::shared_ptr<RenderPipeline> InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) override;
|
||||
std::shared_ptr<RenderPipelineLayout> InstantiateRenderPipelineLayout(RenderPipelineLayoutInfo pipelineLayoutInfo) override;
|
||||
std::shared_ptr<ShaderStage> InstantiateShaderStage(const ShaderAst& shaderAst, const ShaderWriter::States& states) override;
|
||||
std::shared_ptr<ShaderStage> InstantiateShaderStage(ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize) override;
|
||||
std::shared_ptr<Texture> InstantiateTexture(const TextureInfo& params) override;
|
||||
std::shared_ptr<TextureSampler> InstantiateTextureSampler(const TextureSamplerInfo& params) override;
|
||||
|
||||
@@ -52,9 +52,11 @@ namespace Nz
|
||||
void Release(ShaderBinding& binding);
|
||||
inline void TryToShrink();
|
||||
|
||||
static constexpr UInt32 InvalidIndex = 0xFFFFFFFF;
|
||||
|
||||
struct TextureDescriptor
|
||||
{
|
||||
UInt32 bindingIndex;
|
||||
UInt32 bindingIndex = InvalidIndex;
|
||||
GLuint texture;
|
||||
GLuint sampler;
|
||||
GL::TextureTarget textureTarget;
|
||||
@@ -62,7 +64,7 @@ namespace Nz
|
||||
|
||||
struct UniformBufferDescriptor
|
||||
{
|
||||
UInt32 bindingIndex;
|
||||
UInt32 bindingIndex = InvalidIndex;
|
||||
GLuint buffer;
|
||||
GLintptr offset;
|
||||
GLsizeiptr size;
|
||||
|
||||
@@ -12,13 +12,17 @@
|
||||
#include <Nazara/Renderer/ShaderStage.hpp>
|
||||
#include <Nazara/OpenGLRenderer/Wrapper/Context.hpp>
|
||||
#include <Nazara/OpenGLRenderer/Wrapper/Shader.hpp>
|
||||
#include <Nazara/Shader/ShaderWriter.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class ShaderAst;
|
||||
|
||||
class NAZARA_OPENGLRENDERER_API OpenGLShaderStage : public ShaderStage
|
||||
{
|
||||
public:
|
||||
OpenGLShaderStage(OpenGLDevice& device, const ShaderAst& shaderAst, const ShaderWriter::States& states);
|
||||
OpenGLShaderStage(OpenGLDevice& device, ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize);
|
||||
OpenGLShaderStage(const OpenGLShaderStage&) = delete;
|
||||
OpenGLShaderStage(OpenGLShaderStage&&) noexcept = default;
|
||||
@@ -30,6 +34,9 @@ namespace Nz
|
||||
OpenGLShaderStage& operator=(OpenGLShaderStage&&) noexcept = default;
|
||||
|
||||
private:
|
||||
void CheckCompilationStatus();
|
||||
void Create(OpenGLDevice& device, const ShaderAst& shaderAst, const ShaderWriter::States& states);
|
||||
|
||||
GL::Shader m_shader;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -9,7 +9,8 @@ namespace Nz::GL
|
||||
{
|
||||
inline GL::WGLContext::WGLContext(const OpenGLDevice* device, const WGLLoader& loader) :
|
||||
Context(device),
|
||||
m_loader(loader)
|
||||
m_loader(loader),
|
||||
m_handle(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <Nazara/Renderer/RenderPipelineLayout.hpp>
|
||||
#include <Nazara/Renderer/Texture.hpp>
|
||||
#include <Nazara/Renderer/TextureSampler.hpp>
|
||||
#include <Nazara/Shader/ShaderWriter.hpp>
|
||||
#include <Nazara/Utility/AbstractBuffer.hpp>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@@ -21,6 +22,7 @@
|
||||
namespace Nz
|
||||
{
|
||||
class CommandPool;
|
||||
class ShaderAst;
|
||||
class ShaderStage;
|
||||
|
||||
class NAZARA_RENDERER_API RenderDevice
|
||||
@@ -33,6 +35,7 @@ namespace Nz
|
||||
virtual std::shared_ptr<CommandPool> InstantiateCommandPool(QueueType queueType) = 0;
|
||||
virtual std::shared_ptr<RenderPipeline> InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) = 0;
|
||||
virtual std::shared_ptr<RenderPipelineLayout> InstantiateRenderPipelineLayout(RenderPipelineLayoutInfo pipelineLayoutInfo) = 0;
|
||||
virtual std::shared_ptr<ShaderStage> InstantiateShaderStage(const ShaderAst& shaderAst, const ShaderWriter::States& states) = 0;
|
||||
virtual std::shared_ptr<ShaderStage> InstantiateShaderStage(ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize) = 0;
|
||||
std::shared_ptr<ShaderStage> InstantiateShaderStage(ShaderStageType type, ShaderLanguage lang, const std::filesystem::path& sourcePath);
|
||||
virtual std::shared_ptr<Texture> InstantiateTexture(const TextureInfo& params) = 0;
|
||||
|
||||
@@ -41,6 +41,8 @@ namespace Nz
|
||||
void AddStruct(std::string name, std::vector<StructMember> members);
|
||||
void AddUniform(std::string name, ShaderExpressionType type, std::optional<std::size_t> bindingIndex = {}, std::optional<ShaderNodes::MemoryLayout> memoryLayout = {});
|
||||
|
||||
inline std::size_t FindConditionByName(const std::string_view& conditionName) const;
|
||||
|
||||
inline const Condition& GetCondition(std::size_t i) const;
|
||||
inline std::size_t GetConditionCount() const;
|
||||
inline const std::vector<Condition>& GetConditions() const;
|
||||
@@ -110,6 +112,8 @@ namespace Nz
|
||||
ShaderExpressionType type;
|
||||
};
|
||||
|
||||
static constexpr std::size_t InvalidCondition = std::numeric_limits<std::size_t>::max();
|
||||
|
||||
private:
|
||||
std::vector<Condition> m_conditions;
|
||||
std::vector<Function> m_functions;
|
||||
|
||||
@@ -12,6 +12,17 @@ namespace Nz
|
||||
{
|
||||
}
|
||||
|
||||
inline std::size_t ShaderAst::FindConditionByName(const std::string_view& conditionName) const
|
||||
{
|
||||
for (std::size_t i = 0; i < m_conditions.size(); ++i)
|
||||
{
|
||||
if (m_conditions[i].name == conditionName)
|
||||
return i;
|
||||
}
|
||||
|
||||
return InvalidCondition;
|
||||
}
|
||||
|
||||
inline auto Nz::ShaderAst::GetCondition(std::size_t i) const -> const Condition&
|
||||
{
|
||||
assert(i < m_functions.size());
|
||||
|
||||
@@ -141,6 +141,7 @@ namespace Nz
|
||||
};
|
||||
|
||||
NAZARA_SHADER_API ByteArray SerializeShader(const ShaderAst& shader);
|
||||
inline ShaderAst UnserializeShader(const void* data, std::size_t size);
|
||||
NAZARA_SHADER_API ShaderAst UnserializeShader(ByteStream& stream);
|
||||
}
|
||||
|
||||
|
||||
@@ -128,6 +128,12 @@ namespace Nz
|
||||
m_stream(stream)
|
||||
{
|
||||
}
|
||||
|
||||
inline ShaderAst UnserializeShader(const void* data, std::size_t size)
|
||||
{
|
||||
ByteStream byteStream(data, size);
|
||||
return UnserializeShader(byteStream);
|
||||
}
|
||||
}
|
||||
|
||||
#include <Nazara/Shader/DebugOff.hpp>
|
||||
|
||||
@@ -56,7 +56,12 @@ namespace Nz::ShaderBuilder
|
||||
constexpr GenBuilder<ShaderNodes::DeclareVariable> DeclareVariable;
|
||||
constexpr GenBuilder<ShaderNodes::Discard> Discard;
|
||||
constexpr BinOpBuilder<ShaderNodes::BinaryType::Divide> Divide;
|
||||
constexpr BinOpBuilder<ShaderNodes::BinaryType::Equality> Equal;
|
||||
constexpr BinOpBuilder<ShaderNodes::BinaryType::CompEq> Equal;
|
||||
constexpr BinOpBuilder<ShaderNodes::BinaryType::CompGt> GreaterThan;
|
||||
constexpr BinOpBuilder<ShaderNodes::BinaryType::CompGe> GreaterThanOrEqual;
|
||||
constexpr BinOpBuilder<ShaderNodes::BinaryType::CompLt> LessThan;
|
||||
constexpr BinOpBuilder<ShaderNodes::BinaryType::CompLe> LessThanOrEqual;
|
||||
constexpr BinOpBuilder<ShaderNodes::BinaryType::CompNe> NotEqual;
|
||||
constexpr GenBuilder<ShaderNodes::ExpressionStatement> ExprStatement;
|
||||
constexpr GenBuilder<ShaderNodes::Identifier> Identifier;
|
||||
constexpr GenBuilder<ShaderNodes::IntrinsicCall> IntrinsicCall;
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace Nz::ShaderNodes
|
||||
UInt1, //< uint
|
||||
UInt2, //< uvec2
|
||||
UInt3, //< uvec3
|
||||
UInt4 //< uvec4
|
||||
UInt4 //< uvec4
|
||||
};
|
||||
|
||||
enum class BinaryType
|
||||
@@ -43,7 +43,12 @@ namespace Nz::ShaderNodes
|
||||
Multiply, //< *
|
||||
Divide, //< /
|
||||
|
||||
Equality //< ==
|
||||
CompEq, //< ==
|
||||
CompGe, //< >=
|
||||
CompGt, //< >
|
||||
CompLe, //< <=
|
||||
CompLt, //< <
|
||||
CompNe //< <=
|
||||
};
|
||||
|
||||
enum class BuiltinEntry
|
||||
@@ -87,7 +92,9 @@ namespace Nz::ShaderNodes
|
||||
IntrinsicCall,
|
||||
Sample2D,
|
||||
SwizzleOp,
|
||||
StatementBlock
|
||||
StatementBlock,
|
||||
|
||||
Max = StatementBlock
|
||||
};
|
||||
|
||||
enum class SsaInstruction
|
||||
|
||||
@@ -149,7 +149,7 @@ namespace Nz::ShaderNodes
|
||||
|
||||
|
||||
inline Discard::Discard() :
|
||||
Statement(NodeType::DeclareVariable)
|
||||
Statement(NodeType::Discard)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace Nz
|
||||
|
||||
struct States
|
||||
{
|
||||
std::unordered_set<std::string> enabledConditions;
|
||||
Nz::UInt64 enabledConditions = 0;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -3,13 +3,17 @@
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Shader/SpirvWriter.hpp>
|
||||
#include <Nazara/Math/Algorithm.hpp>
|
||||
#include <Nazara/Shader/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
inline bool SpirvWriter::IsConditionEnabled(const std::string& condition) const
|
||||
{
|
||||
return m_context.states->enabledConditions.find(condition) != m_context.states->enabledConditions.end();
|
||||
std::size_t conditionIndex = m_context.shader->FindConditionByName(condition);
|
||||
assert(conditionIndex != ShaderAst::InvalidCondition);
|
||||
|
||||
return TestBit<Nz::UInt64>(m_context.states->enabledConditions, conditionIndex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ namespace Nz
|
||||
std::shared_ptr<CommandPool> InstantiateCommandPool(QueueType queueType) override;
|
||||
std::shared_ptr<RenderPipeline> InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) override;
|
||||
std::shared_ptr<RenderPipelineLayout> InstantiateRenderPipelineLayout(RenderPipelineLayoutInfo pipelineLayoutInfo) override;
|
||||
std::shared_ptr<ShaderStage> InstantiateShaderStage(const ShaderAst& shaderAst, const ShaderWriter::States& states) override;
|
||||
std::shared_ptr<ShaderStage> InstantiateShaderStage(ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize) override;
|
||||
std::shared_ptr<Texture> InstantiateTexture(const TextureInfo& params) override;
|
||||
std::shared_ptr<TextureSampler> InstantiateTextureSampler(const TextureSamplerInfo& params) override;
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <Nazara/Renderer/Enums.hpp>
|
||||
#include <Nazara/Renderer/ShaderStage.hpp>
|
||||
#include <Nazara/Shader/ShaderWriter.hpp>
|
||||
#include <Nazara/VulkanRenderer/Wrapper/ShaderModule.hpp>
|
||||
#include <vector>
|
||||
|
||||
@@ -23,6 +24,7 @@ namespace Nz
|
||||
VulkanShaderStage(VulkanShaderStage&&) = delete;
|
||||
~VulkanShaderStage() = default;
|
||||
|
||||
bool Create(Vk::Device& device, const ShaderAst& shader, const ShaderWriter::States& states);
|
||||
bool Create(Vk::Device& device, ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize);
|
||||
|
||||
inline const Vk::ShaderModule& GetHandle() const;
|
||||
|
||||
Reference in New Issue
Block a user