Skip to content

Commit

Permalink
Cleanup ShaderSchema and MaterialComponent. Add compile variant button.
Browse files Browse the repository at this point in the history
  • Loading branch information
roeas committed Sep 22, 2023
1 parent 17005ba commit b500574
Show file tree
Hide file tree
Showing 10 changed files with 68 additions and 136 deletions.
4 changes: 1 addition & 3 deletions Engine/EditorResources/Text.csv
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ TEXT_SAVE,保存,Save
TEXT_SAVE_AS,另存为,Save AS
TEXT_WINDOW,窗口,Window
TEXT_BUILD,编译,Build
TEXT_REBUILD_NONUBER_SHADERS,重新生成着色器,Rebuild Non-Uber shaders
TEXT_REBUILD_PBR_SHADERS,重新生成PBR着色器,Rebuild PBR shaders
TEXT_REBUILD_ANIMATION_SHADERS,重新生成动画着色器,Rebuild Animation shaders
TEXT_BUILD_PBR_VARIANT,编译所有PBR着色器变体,Build All PBR Shader Variant
TEXT_ABOUT,关于,About
TEXT_DOCUMENTS,文档,Documents
6 changes: 3 additions & 3 deletions Engine/Source/Editor/EditorApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -496,11 +496,11 @@ bool EditorApp::IsAtmosphericScatteringEnable() const

void EditorApp::InitShaderPrograms() const
{
ShaderBuilder::PreBuildNonUberShaders(m_pRenderContext.get());
ShaderBuilder::PreBuildUberShaders(m_pRenderContext.get(), m_pSceneWorld->GetPBRMaterialType());
ShaderBuilder::CompileRegisteredNonUberShader(m_pRenderContext.get());
ShaderBuilder::CompileRegisteredUberShader(m_pRenderContext.get(), m_pSceneWorld->GetPBRMaterialType());

#ifdef ENABLE_DDGI
ShaderBuilder::PreBuildUberShaders(m_pSceneWorld->GetDDGIMaterialType());
ShaderBuilder::CompileRegisteredUberShader(m_pSceneWorld->GetDDGIMaterialType());
#endif
}

Expand Down
49 changes: 36 additions & 13 deletions Engine/Source/Editor/Resources/ShaderBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,11 @@
namespace editor
{

void ShaderBuilder::PreBuildUberShaders(engine::RenderContext* pRenderContext, engine::MaterialType* pMaterialType)
namespace
{
const std::string& programName = pMaterialType->GetShaderSchema().GetProgramName();
engine::StringCrc programNameCrc = engine::StringCrc(programName);

if (!pRenderContext->GetShaderVariantCollections().HasFeatureCombine(programNameCrc))
{
return;
}

const std::set<std::string>& combines = pRenderContext->GetShaderVariantCollections().GetFeatureCombines(programNameCrc);
const std::set<std::string>& shaders = pRenderContext->GetShaderVariantCollections().GetShaders(programNameCrc);
CD_ENGINE_INFO("Precompile program {0} variant count : {1}", programName, combines.size());

void CompileShaderVariant(const std::set<std::string>& shaders, const std::set<std::string>& combines)
{
for (const std::string& shader : shaders)
{
engine::ShaderType shaderType = engine::GetShaderType(shader);
Expand All @@ -48,7 +39,9 @@ void ShaderBuilder::PreBuildUberShaders(engine::RenderContext* pRenderContext, e
}
}

void ShaderBuilder::PreBuildNonUberShaders(engine::RenderContext* pRenderContext)
}

void ShaderBuilder::CompileRegisteredNonUberShader(engine::RenderContext* pRenderContext)
{
for (const auto& shaders : pRenderContext->GetShaderVariantCollections().GetShaderPrograms())
{
Expand All @@ -68,6 +61,36 @@ void ShaderBuilder::PreBuildNonUberShaders(engine::RenderContext* pRenderContext
}
}

void ShaderBuilder::CompileRegisteredUberShader(engine::RenderContext* pRenderContext, engine::MaterialType* pMaterialType)
{
const std::string& programName = pMaterialType->GetShaderSchema().GetProgramName();
engine::StringCrc programNameCrc = engine::StringCrc(programName);

if (!pRenderContext->GetShaderVariantCollections().HasFeatureCombine(programNameCrc))
{
return;
}

const std::set<std::string>& shaders = pRenderContext->GetShaderVariantCollections().GetShaders(programNameCrc);
const std::set<std::string>& combines = pRenderContext->GetShaderVariantCollections().GetFeatureCombines(programNameCrc);
CD_ENGINE_INFO("Compiling program {0} variant count : {1}", programName, combines.size());

CompileShaderVariant(shaders, combines);
}

void ShaderBuilder::CompileUberShaderAllVariant(engine::RenderContext* pRenderContext, engine::MaterialType* pMaterialType)
{
const std::string& programName = pMaterialType->GetShaderSchema().GetProgramName();

const std::set<std::string>& shaders = pRenderContext->GetShaderVariantCollections().GetShaders(engine::StringCrc(programName));
const std::set<std::string>& combines = pMaterialType->GetShaderSchema().GetAllFeatureCombines();
CD_ENGINE_INFO("Compiling program {0} variant count : {1}", programName, combines.size());

CompileShaderVariant(shaders, combines);

ResourceBuilder::Get().Update();
}

void ShaderBuilder::BuildShader(engine::RenderContext* pRenderContext, const engine::ShaderCompileInfo& info)
{
const std::set<std::string>& shaders = pRenderContext->GetShaderVariantCollections().GetShaders(engine::StringCrc(info.m_programName));
Expand Down
6 changes: 4 additions & 2 deletions Engine/Source/Editor/Resources/ShaderBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ namespace editor
class ShaderBuilder
{
public:
static void PreBuildNonUberShaders(engine::RenderContext* pRenderContext);
static void PreBuildUberShaders(engine::RenderContext* pRenderContext, engine::MaterialType* pMaterialType);
static void CompileRegisteredNonUberShader(engine::RenderContext* pRenderContext);
static void CompileRegisteredUberShader(engine::RenderContext* pRenderContext, engine::MaterialType* pMaterialType);

static void CompileUberShaderAllVariant(engine::RenderContext* pRenderContext, engine::MaterialType* pMaterialType);

// Compile specified shader program/program variant.
static void BuildShader(engine::RenderContext* pRenderContext, const engine::ShaderCompileInfo& info);
Expand Down
7 changes: 7 additions & 0 deletions Engine/Source/Editor/UILayers/MainMenu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,13 @@ void MainMenu::BuildMenu()
{
if (ImGui::BeginMenu(CD_TEXT("TEXT_BUILD")))
{
engine::SceneWorld* pSceneWorld = GetSceneWorld();

if (ImGui::MenuItem(CD_TEXT("TEXT_BUILD_PBR_VARIANT")))
{
ShaderBuilder::CompileUberShaderAllVariant(GetRenderContext(), pSceneWorld->GetPBRMaterialType());
}

ImGui::EndMenu();
}
}
Expand Down
12 changes: 0 additions & 12 deletions Engine/Source/Runtime/ECWorld/MaterialComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,22 +148,11 @@ void MaterialComponent::DeactiveShaderFeature(engine::ShaderFeature feature)
m_shaderFeatures.erase(feature);
}

void MaterialComponent::MatchUberShaderCrc()
{
m_uberShaderCrc = m_pMaterialType->GetShaderSchema().GetFeaturesCombineCrc(m_shaderFeatures);
}

uint16_t MaterialComponent::GetShadreProgram() const
{
return m_pMaterialType->GetShaderSchema().GetCompiledProgram(m_uberShaderCrc);
}

void MaterialComponent::Reset()
{
m_pMaterialData = nullptr;
m_pMaterialType = nullptr;
m_shaderFeatures.clear();
m_uberShaderCrc = ShaderSchema::DefaultUberShaderCrc;
m_name.clear();
m_albedoColor = cd::Vec3f::One();
m_emissiveColor = cd::Vec3f::One();
Expand Down Expand Up @@ -291,7 +280,6 @@ void MaterialComponent::SetSkyType(SkyType crtType)
m_shaderFeatures.insert(skyTypeToShaderFeature.at(crtType));
}

m_uberShaderCrc = m_pMaterialType->GetShaderSchema().GetFeaturesCombineCrc(m_shaderFeatures);
m_skyType = crtType;
}

Expand Down
3 changes: 0 additions & 3 deletions Engine/Source/Runtime/ECWorld/MaterialComponent.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,6 @@ class MaterialComponent final
// Uber shader data.
void ActiveShaderFeature(ShaderFeature feature);
void DeactiveShaderFeature(ShaderFeature feature);
void MatchUberShaderCrc();
uint16_t GetShadreProgram() const;

void SetShaderFeatures(std::set<ShaderFeature> options) { m_shaderFeatures = cd::MoveTemp(m_shaderFeatures); }
std::set<ShaderFeature>& GetShaderFeatures() { return m_shaderFeatures; }
Expand Down Expand Up @@ -166,7 +164,6 @@ class MaterialComponent final
float m_alphaCutOff;

std::set<ShaderFeature> m_shaderFeatures;
StringCrc m_uberShaderCrc;

SkyType m_skyType;
std::vector<TextureBlob> m_cacheTextureBlobs;
Expand Down
1 change: 1 addition & 0 deletions Engine/Source/Runtime/ImGui/ImGuiBaseLayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include "ECWorld/SceneWorld.h"
#include "ImGui/ImGuiContextInstance.h"
#include "Rendering/RenderContext.h"

#include <imgui/imgui.h>

Expand Down
83 changes: 8 additions & 75 deletions Engine/Source/Runtime/Material/ShaderSchema.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ void ShaderSchema::AddFeatureSet(ShaderFeatureSet featureSet)
}

m_isDirty = true;
m_shaderFeatureSets.emplace_back(cd::MoveTemp(featureSet));
m_shaderFeatureSets.insert(cd::MoveTemp(featureSet));
}

void ShaderSchema::Build()
Expand All @@ -53,9 +53,9 @@ void ShaderSchema::Build()
for (const auto& feature : featureSet)
{
std::string newFeatureName = GetFeatureName(feature);
std::vector<std::string> newFeatureCombines = { newFeatureName };
std::set<std::string> newFeatureCombines = { newFeatureName };

for (const auto& combine : m_featureCombines)
for (const auto& combine : m_allFeatureCombines)
{
// Skip combination which has features in same set.
bool skip = false;
Expand All @@ -73,27 +73,20 @@ void ShaderSchema::Build()
}
if (!skip)
{
newFeatureCombines.emplace_back(combine + newFeatureName);
newFeatureCombines.insert(combine + newFeatureName);
}
}
m_featureCombines.insert(m_featureCombines.end(), newFeatureCombines.begin(), newFeatureCombines.end());
for (const auto& combine : newFeatureCombines)
{
assert(!IsFeaturesValid(StringCrc(combine)));
m_compiledProgramHandles[StringCrc(combine).Value()] = InvalidProgramHandle;
}
m_allFeatureCombines.insert(newFeatureCombines.begin(), newFeatureCombines.end());
}
}

// ShaderSchema also handle non-uber case.
m_featureCombines.emplace_back("");
m_compiledProgramHandles[DefaultUberShaderCrc.Value()] = InvalidProgramHandle;
// Should ShaderSchema handle uber shader without shader feature?
m_allFeatureCombines.insert("");
}

void ShaderSchema::CleanBuild()
{
m_featureCombines.clear();
m_compiledProgramHandles.clear();
m_allFeatureCombines.clear();
m_isDirty = true;
}

Expand All @@ -105,33 +98,6 @@ void ShaderSchema::CleanAll()
m_shaderFeatureSets.clear();
}

void ShaderSchema::SetCompiledProgram(StringCrc shaderFeaturesCrc, uint16_t programHandle)
{
assert(IsFeaturesValid(shaderFeaturesCrc));
m_compiledProgramHandles[shaderFeaturesCrc.Value()] = programHandle;
}

uint16_t ShaderSchema::GetCompiledProgram(StringCrc shaderFeaturesCrc) const
{
auto itProgram = m_compiledProgramHandles.find(shaderFeaturesCrc.Value());

if (itProgram == m_compiledProgramHandles.end())
{
CD_ENGINE_ERROR("Unregistered shader features!");
return InvalidProgramHandle;
}

uint16_t programHandle = itProgram->second;

if (programHandle == InvalidProgramHandle)
{
CD_ENGINE_ERROR("Uncompiled shader features");
return InvalidProgramHandle;
}

return programHandle;
}

std::string ShaderSchema::GetFeaturesCombine(const ShaderFeatureSet& featureSet) const
{
if (m_shaderFeatureSets.empty() || featureSet.empty())
Expand Down Expand Up @@ -166,37 +132,4 @@ StringCrc ShaderSchema::GetFeaturesCombineCrc(const ShaderFeatureSet& featureSet
return StringCrc(GetFeaturesCombine(featureSet));
}

bool ShaderSchema::IsFeaturesValid(StringCrc shaderFeaturesCrc) const
{
return m_compiledProgramHandles.find(shaderFeaturesCrc.Value()) != m_compiledProgramHandles.end();
}

void ShaderSchema::AddUberVSBlob(ShaderBlob shaderBlob)
{
if (m_pVSBlob)
{
// TODO : process vertex uber shaders.
return;
}

m_pVSBlob = std::make_unique<ShaderBlob>(cd::MoveTemp(shaderBlob));
}

void ShaderSchema::AddUberFSBlob(StringCrc shaderFeaturesCrc, ShaderBlob shaderBlob)
{
if (m_shaderFeaturesToFSBlobs.find(shaderFeaturesCrc.Value()) != m_shaderFeaturesToFSBlobs.end())
{
return;
}

m_shaderFeaturesToFSBlobs[shaderFeaturesCrc.Value()] = std::make_unique<ShaderBlob>(cd::MoveTemp(shaderBlob));
}

const ShaderSchema::ShaderBlob& ShaderSchema::GetFSBlob(StringCrc shaderFeaturesCrc) const
{
auto itBlob = m_shaderFeaturesToFSBlobs.find(shaderFeaturesCrc.Value());
assert(itBlob != m_shaderFeaturesToFSBlobs.end());
return *(itBlob->second.get());
}

}
33 changes: 8 additions & 25 deletions Engine/Source/Runtime/Material/ShaderSchema.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,46 +46,29 @@ class ShaderSchema

void AddFeatureSet(ShaderFeatureSet featureSet);

// Calling "AddFeatureSet/SetConflictOptions and Build" after Build will cause unnecessary performance overhead.
void Build();
void CleanBuild();
void CleanAll();

void SetCompiledProgram(StringCrc shaderFeaturesCrc, uint16_t programHandle);
uint16_t GetCompiledProgram(StringCrc shaderFeaturesCrc) const;

std::string GetFeaturesCombine(const ShaderFeatureSet& featureSet) const;
StringCrc GetFeaturesCombineCrc(const ShaderFeatureSet& featureSet) const;
bool IsFeaturesValid(StringCrc shaderFeaturesCrc) const;

std::vector<ShaderFeatureSet>& GetFeatures() { return m_shaderFeatureSets; }
const std::vector<ShaderFeatureSet>& GetFeatures() const { return m_shaderFeatureSets; }

std::vector<std::string>& GetFeatureCombines() { return m_featureCombines; }
const std::vector<std::string>& GetFeatureCombines() const { return m_featureCombines; }
std::set<ShaderFeatureSet>& GetFeatures() { return m_shaderFeatureSets; }
const std::set<ShaderFeatureSet>& GetFeatures() const { return m_shaderFeatureSets; }

// TODO : More generic.
void AddUberVSBlob(ShaderBlob shaderBlob);
void AddUberFSBlob(StringCrc shaderFeaturesCrc, ShaderBlob shaderBlob);
const ShaderBlob& GetVSBlob() const { return *m_pVSBlob.get(); }
const ShaderBlob& GetFSBlob(StringCrc shaderFeaturesCrc) const;
std::set<std::string>& GetAllFeatureCombines() { return m_allFeatureCombines; }
const std::set<std::string>& GetAllFeatureCombines() const { return m_allFeatureCombines; }

private:
std::string m_programName;

std::string m_vertexShaderPath;
std::string m_fragmentShaderPath;

bool m_isDirty = false;
// Adding order of shader features.
std::vector<ShaderFeatureSet> m_shaderFeatureSets;
// Parameters to compile shaders.
std::vector<std::string> m_featureCombines;
// Key: StringCrc(feature combine), Value: shader handle.
std::map<uint32_t, uint16_t> m_compiledProgramHandles;

std::unique_ptr<ShaderBlob> m_pVSBlob;
std::map<uint32_t, std::unique_ptr<ShaderBlob>> m_shaderFeaturesToFSBlobs;
// Registration order of shader features.
std::set<ShaderFeatureSet> m_shaderFeatureSets;
// All permutations matching the registered shader features.
std::set<std::string> m_allFeatureCombines;
};

}

0 comments on commit b500574

Please sign in to comment.