Handle shader options of any type
This commit is contained in:
@@ -160,19 +160,19 @@ namespace Nz
|
||||
if (optionIndexes)
|
||||
optionIndexes->hasDiffuseMap = settings.options.size();
|
||||
|
||||
MaterialSettings::BuildOption(settings.options, settings.shaders, "HasDiffuseMap", "HAS_DIFFUSE_TEXTURE");
|
||||
MaterialSettings::BuildOption(settings.options, settings.shaders, "HasDiffuseMap", "HasDiffuseTexture");
|
||||
|
||||
// HasAlphaMap
|
||||
if (optionIndexes)
|
||||
optionIndexes->hasAlphaMap = settings.options.size();
|
||||
|
||||
MaterialSettings::BuildOption(settings.options, settings.shaders, "HasAlphaMap", "HAS_ALPHA_TEXTURE");
|
||||
MaterialSettings::BuildOption(settings.options, settings.shaders, "HasAlphaMap", "HasAlphaTexture");
|
||||
|
||||
// AlphaTest
|
||||
if (optionIndexes)
|
||||
optionIndexes->alphaTest = settings.options.size();
|
||||
|
||||
MaterialSettings::BuildOption(settings.options, settings.shaders, "AlphaTest", "ALPHA_TEST");
|
||||
MaterialSettings::BuildOption(settings.options, settings.shaders, "AlphaTest", "AlphaTest");
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ namespace Nz
|
||||
*/
|
||||
MaterialPass::MaterialPass(std::shared_ptr<const MaterialSettings> settings) :
|
||||
m_settings(std::move(settings)),
|
||||
m_enabledOptions(0),
|
||||
m_forceCommandBufferRegeneration(false),
|
||||
m_pipelineUpdated(false),
|
||||
m_shaderBindingUpdated(false)
|
||||
@@ -99,23 +98,20 @@ namespace Nz
|
||||
void MaterialPass::UpdatePipeline() const
|
||||
{
|
||||
for (auto& shader : m_pipelineInfo.shaders)
|
||||
shader.enabledOptions = 0;
|
||||
shader.optionValues.fill(ShaderAst::NoValue{});
|
||||
|
||||
const auto& options = m_settings->GetOptions();
|
||||
for (std::size_t optionIndex = 0; optionIndex < options.size(); ++optionIndex)
|
||||
{
|
||||
if (TestBit<UInt64>(m_enabledOptions, optionIndex))
|
||||
const auto& option = options[optionIndex];
|
||||
assert(option.optionIndexByShader.size() <= m_pipelineInfo.shaders.size());
|
||||
|
||||
for (std::size_t shaderIndex = 0; shaderIndex < option.optionIndexByShader.size(); ++shaderIndex)
|
||||
{
|
||||
for (auto& shader : m_pipelineInfo.shaders)
|
||||
{
|
||||
ShaderStageTypeFlags supportedStages = shader.uberShader->GetSupportedStages();
|
||||
for (std::size_t i = 0; i < ShaderStageTypeCount; ++i)
|
||||
{
|
||||
ShaderStageType shaderStage = static_cast<ShaderStageType>(i);
|
||||
if (supportedStages & shaderStage)
|
||||
shader.enabledOptions |= options[optionIndex].enabledOptions[i];
|
||||
}
|
||||
}
|
||||
if (!option.optionIndexByShader[shaderIndex].has_value())
|
||||
continue;
|
||||
|
||||
m_pipelineInfo.shaders[shaderIndex].optionValues[optionIndex] = m_optionValues[optionIndex];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -45,14 +45,18 @@ namespace Nz
|
||||
}
|
||||
|
||||
RenderPipelineInfo renderPipelineInfo;
|
||||
static_cast<RenderStates&>(renderPipelineInfo).operator=(m_pipelineInfo); // Not the line I4m the most proud of
|
||||
static_cast<RenderStates&>(renderPipelineInfo).operator=(m_pipelineInfo); // Not the line I'm the most proud of
|
||||
|
||||
renderPipelineInfo.pipelineLayout = m_pipelineInfo.settings->GetRenderPipelineLayout();
|
||||
|
||||
for (const auto& shader : m_pipelineInfo.shaders)
|
||||
{
|
||||
if (shader.uberShader)
|
||||
renderPipelineInfo.shaderModules.push_back(shader.uberShader->Get(shader.enabledOptions));
|
||||
{
|
||||
UberShader::Config config{ shader.optionValues };
|
||||
|
||||
renderPipelineInfo.shaderModules.push_back(shader.uberShader->Get(config));
|
||||
}
|
||||
}
|
||||
|
||||
renderPipelineInfo.vertexBuffers = vertexBuffers;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
option HAS_DIFFUSE_TEXTURE: bool;
|
||||
option HAS_ALPHA_TEXTURE: bool;
|
||||
option ALPHA_TEST: bool;
|
||||
option HasDiffuseTexture: bool = false;
|
||||
option HasAlphaTexture: bool = false;
|
||||
option AlphaTest: bool = false;
|
||||
|
||||
const HasUV = HAS_DIFFUSE_TEXTURE || HAS_ALPHA_TEXTURE;
|
||||
const HasUV = HasDiffuseTexture || HasAlphaTexture;
|
||||
|
||||
[layout(std140)]
|
||||
struct BasicSettings
|
||||
@@ -56,15 +56,15 @@ struct FragOut
|
||||
fn main(input: FragIn) -> FragOut
|
||||
{
|
||||
let diffuseColor = settings.DiffuseColor;
|
||||
const if (HAS_DIFFUSE_TEXTURE)
|
||||
const if (HasDiffuseTexture)
|
||||
// TODO: diffuseColor *= MaterialDiffuseMap.Sample(input.uv)
|
||||
diffuseColor = diffuseColor * MaterialDiffuseMap.Sample(input.uv);
|
||||
|
||||
const if (HAS_ALPHA_TEXTURE)
|
||||
const if (HasAlphaTexture)
|
||||
// TODO: diffuseColor.w *= MaterialAlphaMap.Sample(input.uv)).x
|
||||
diffuseColor = vec4<f32>(diffuseColor.x, diffuseColor.y, diffuseColor.z, MaterialAlphaMap.Sample(input.uv).x * diffuseColor.w);
|
||||
|
||||
const if (ALPHA_TEST)
|
||||
const if (AlphaTest)
|
||||
{
|
||||
if (diffuseColor.w < settings.AlphaThreshold)
|
||||
discard;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
option HAS_DIFFUSE_TEXTURE: bool;
|
||||
option HAS_ALPHA_TEXTURE: bool;
|
||||
option ALPHA_TEST: bool;
|
||||
option HasDiffuseTexture: bool = false;
|
||||
option HasAlphaTexture: bool = false;
|
||||
option AlphaTest: bool = false;
|
||||
|
||||
const HasUV = ALPHA_TEST && (HAS_DIFFUSE_TEXTURE || HAS_ALPHA_TEXTURE);
|
||||
const HasUV = AlphaTest && (HasDiffuseTexture || HasAlphaTexture);
|
||||
|
||||
[layout(std140)]
|
||||
struct BasicSettings
|
||||
@@ -47,15 +47,15 @@ struct FragIn
|
||||
[location(0), cond(HasUV)] uv: vec2<f32>
|
||||
}
|
||||
|
||||
[entry(frag), cond(ALPHA_TEST)]
|
||||
[entry(frag), cond(AlphaTest)]
|
||||
fn main(input: FragIn)
|
||||
{
|
||||
let alpha = settings.DiffuseColor.a;
|
||||
const if (HAS_DIFFUSE_TEXTURE)
|
||||
const if (HasDiffuseTexture)
|
||||
// TODO: alpha *= MaterialDiffuseMap.Sample(input.uv).a;
|
||||
alpha = alpha * MaterialDiffuseMap.Sample(input.uv).a;
|
||||
|
||||
const if (HAS_ALPHA_TEXTURE)
|
||||
const if (HasAlphaTexture)
|
||||
// TODO: alpha *= MaterialAlphaMap.Sample(input.uv).x
|
||||
alpha = alpha * MaterialAlphaMap.Sample(input.uv).x;
|
||||
|
||||
@@ -64,7 +64,7 @@ fn main(input: FragIn)
|
||||
}
|
||||
|
||||
// Dummy fragment shader (TODO: Add a way to delete stage?)
|
||||
[entry(frag), cond(!ALPHA_TEST)]
|
||||
[entry(frag), cond(!AlphaTest)]
|
||||
fn main() {}
|
||||
|
||||
// Vertex stage
|
||||
|
||||
@@ -33,7 +33,11 @@ namespace Nz
|
||||
|
||||
callbacks.onOptionDeclaration = [&](const std::string& optionName, const ShaderAst::ExpressionType& optionType)
|
||||
{
|
||||
m_optionIndexByName[optionName] = optionCount;
|
||||
m_optionIndexByName[optionName] = Option{
|
||||
optionCount,
|
||||
optionType
|
||||
};
|
||||
|
||||
optionCount++;
|
||||
};
|
||||
|
||||
@@ -43,36 +47,26 @@ namespace Nz
|
||||
if (m_shaderStages & supportedStageType != m_shaderStages)
|
||||
throw std::runtime_error("shader doesn't support all required shader stages");
|
||||
|
||||
if (optionCount >= 64)
|
||||
throw std::runtime_error("Too many conditions");
|
||||
|
||||
m_combinationMask = std::numeric_limits<UInt64>::max();
|
||||
m_combinationMask <<= optionCount;
|
||||
m_combinationMask = ~m_combinationMask;
|
||||
if (optionCount >= MaximumOptionValue)
|
||||
throw std::runtime_error("Too many shader options (at most " + std::to_string(MaximumOptionValue) + " are supported)");
|
||||
}
|
||||
|
||||
UInt64 UberShader::GetOptionFlagByName(const std::string& optionName) const
|
||||
const std::shared_ptr<ShaderModule>& UberShader::Get(const Config& config)
|
||||
{
|
||||
auto it = m_optionIndexByName.find(optionName);
|
||||
if (it == m_optionIndexByName.end())
|
||||
return 0;
|
||||
|
||||
return SetBit<UInt64>(0, it->second);
|
||||
}
|
||||
|
||||
const std::shared_ptr<ShaderModule>& UberShader::Get(UInt64 combination)
|
||||
{
|
||||
combination &= m_combinationMask;
|
||||
|
||||
auto it = m_combinations.find(combination);
|
||||
auto it = m_combinations.find(config);
|
||||
if (it == m_combinations.end())
|
||||
{
|
||||
ShaderWriter::States states;
|
||||
states.enabledOptions = combination;
|
||||
|
||||
for (std::size_t i = 0; i < MaximumOptionValue; ++i)
|
||||
{
|
||||
if (!std::holds_alternative<ShaderAst::NoValue>(config.optionValues[i]))
|
||||
states.optionValues[i] = config.optionValues[i];
|
||||
}
|
||||
|
||||
std::shared_ptr<ShaderModule> stage = Graphics::Instance()->GetRenderDevice()->InstantiateShaderModule(m_shaderStages, *m_shaderAst, std::move(states));
|
||||
|
||||
it = m_combinations.emplace(combination, std::move(stage)).first;
|
||||
it = m_combinations.emplace(config, std::move(stage)).first;
|
||||
}
|
||||
|
||||
return it->second;
|
||||
|
||||
Reference in New Issue
Block a user