Files
XCEngine/engine/include/XCEngine/Resources/Shader/Shader.h

204 lines
6.5 KiB
C++

#pragma once
#include <XCEngine/Core/Asset/IResource.h>
#include <XCEngine/Core/Containers/Array.h>
#include <XCEngine/Core/Types.h>
#include <XCEngine/Resources/Material/MaterialRenderState.h>
#include <XCEngine/Resources/Shader/ShaderKeywordTypes.h>
namespace XCEngine {
namespace Resources {
enum class ShaderType : Core::uint8 {
Vertex,
Fragment,
Geometry,
Compute,
Hull,
Domain
};
enum class ShaderLanguage : Core::uint8 {
GLSL,
HLSL,
SPIRV
};
enum class ShaderBackend : Core::uint8 {
Generic = 0,
D3D12,
OpenGL,
Vulkan
};
// Keep shader property kinds close to Unity's public shader syntax so the
// runtime contract can be reused when ShaderLab-compatible parsing is added.
enum class ShaderPropertyType : Core::uint8 {
Float = 0,
Range,
Int,
Vector,
Color,
Texture2D,
TextureCube
};
enum class ShaderResourceType : Core::uint8 {
ConstantBuffer = 0,
Texture2D,
TextureCube,
Sampler
};
struct ShaderUniform {
Containers::String name;
Core::uint32 location;
Core::uint32 size;
Core::uint32 type;
};
struct ShaderAttribute {
Containers::String name;
Core::uint32 location;
Core::uint32 size;
Core::uint32 type;
};
struct ShaderPassTagEntry {
Containers::String name;
Containers::String value;
};
struct ShaderPropertyDesc {
Containers::String name;
Containers::String displayName;
ShaderPropertyType type = ShaderPropertyType::Float;
Containers::String defaultValue;
Containers::String semantic;
};
struct ShaderResourceBindingDesc {
Containers::String name;
ShaderResourceType type = ShaderResourceType::ConstantBuffer;
Core::uint32 set = 0;
Core::uint32 binding = 0;
Containers::String semantic;
};
struct ShaderStageVariant {
ShaderType stage = ShaderType::Fragment;
ShaderLanguage language = ShaderLanguage::GLSL;
ShaderBackend backend = ShaderBackend::Generic;
ShaderKeywordSet requiredKeywords;
Containers::String entryPoint;
Containers::String profile;
Containers::String sourceCode;
Containers::Array<Core::uint8> compiledBinary;
};
struct ShaderPass {
Containers::String name;
bool hasFixedFunctionState = false;
MaterialRenderState fixedFunctionState;
Containers::Array<ShaderPassTagEntry> tags;
Containers::Array<ShaderResourceBindingDesc> resources;
Containers::Array<ShaderKeywordDeclaration> keywordDeclarations;
Containers::Array<ShaderStageVariant> variants;
};
class Shader : public IResource {
public:
Shader();
virtual ~Shader() override;
ResourceType GetType() const override { return ResourceType::Shader; }
const Containers::String& GetName() const override { return m_name; }
const Containers::String& GetPath() const override { return m_path; }
ResourceGUID GetGUID() const override { return m_guid; }
bool IsValid() const override { return m_isValid; }
size_t GetMemorySize() const override { return m_memorySize; }
void Release() override;
void SetShaderType(ShaderType type);
ShaderType GetShaderType() const { return m_shaderType; }
void SetShaderLanguage(ShaderLanguage lang);
ShaderLanguage GetShaderLanguage() const { return m_language; }
void SetSourceCode(const Containers::String& source);
const Containers::String& GetSourceCode() const { return m_sourceCode; }
void SetCompiledBinary(const Containers::Array<Core::uint8>& binary);
const Containers::Array<Core::uint8>& GetCompiledBinary() const { return m_compiledBinary; }
void AddUniform(const ShaderUniform& uniform);
const Containers::Array<ShaderUniform>& GetUniforms() const { return m_uniforms; }
void AddAttribute(const ShaderAttribute& attribute);
const Containers::Array<ShaderAttribute>& GetAttributes() const { return m_attributes; }
void AddProperty(const ShaderPropertyDesc& property);
void ClearProperties();
const Containers::Array<ShaderPropertyDesc>& GetProperties() const { return m_properties; }
const ShaderPropertyDesc* FindProperty(const Containers::String& propertyName) const;
void SetFallback(const Containers::String& fallback);
const Containers::String& GetFallback() const { return m_fallback; }
void AddPass(const ShaderPass& pass);
void ClearPasses();
Core::uint32 GetPassCount() const { return static_cast<Core::uint32>(m_passes.Size()); }
const Containers::Array<ShaderPass>& GetPasses() const { return m_passes; }
void AddPassVariant(const Containers::String& passName, const ShaderStageVariant& variant);
void SetPassTag(
const Containers::String& passName,
const Containers::String& tagName,
const Containers::String& tagValue);
void AddPassResourceBinding(
const Containers::String& passName,
const ShaderResourceBindingDesc& binding);
void AddPassKeywordDeclaration(
const Containers::String& passName,
const ShaderKeywordDeclaration& declaration);
bool HasPass(const Containers::String& passName) const;
const ShaderPass* FindPass(const Containers::String& passName) const;
ShaderPass* FindPass(const Containers::String& passName);
bool PassDeclaresKeyword(
const Containers::String& passName,
const Containers::String& keyword) const;
bool DeclaresKeyword(const Containers::String& keyword) const;
const ShaderResourceBindingDesc* FindPassResourceBinding(
const Containers::String& passName,
const Containers::String& resourceName) const;
const ShaderStageVariant* FindVariant(
const Containers::String& passName,
ShaderType stage,
ShaderBackend backend = ShaderBackend::Generic,
const ShaderKeywordSet& enabledKeywords = ShaderKeywordSet()) const;
class IRHIShader* GetRHIResource() const { return m_rhiResource; }
void SetRHIResource(class IRHIShader* resource);
private:
ShaderPass& GetOrCreatePass(const Containers::String& passName);
ShaderStageVariant& GetOrCreateLegacyVariant();
void SyncLegacyVariant();
ShaderType m_shaderType = ShaderType::Fragment;
ShaderLanguage m_language = ShaderLanguage::GLSL;
Containers::String m_sourceCode;
Containers::Array<Core::uint8> m_compiledBinary;
Containers::Array<ShaderUniform> m_uniforms;
Containers::Array<ShaderAttribute> m_attributes;
Containers::Array<ShaderPropertyDesc> m_properties;
Containers::Array<ShaderPass> m_passes;
Containers::String m_fallback;
class IRHIShader* m_rhiResource = nullptr;
};
} // namespace Resources
} // namespace XCEngine