// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
#pragma once
#include "GPUShaderProgram.h"
#include "Engine/Graphics/GPUResource.h"
#include "Engine/Core/Collections/Dictionary.h"
class GPUConstantBuffer;
class GPUShaderProgram;
///
/// The runtime version of the shaders cache supported by the all graphics back-ends. The same for all the shader cache formats (easier to sync and validate).
///
#define GPU_SHADER_CACHE_VERSION 9
///
/// Represents collection of shader programs with permutations and custom names.
///
class GPUShaderProgramsContainer
{
private:
Dictionary _shaders;
public:
///
/// Initializes a new instance of the class.
///
GPUShaderProgramsContainer();
///
/// Finalizes an instance of the class.
///
~GPUShaderProgramsContainer();
public:
///
/// Adds a new shader program to the collection.
///
/// The shader to store.
/// The shader permutation index.
void Add(GPUShaderProgram* shader, int32 permutationIndex);
///
/// Gets a shader of given name and permutation index.
///
/// The shader program name.
/// The shader permutation index.
/// Stored shader program or null if cannot find it.
GPUShaderProgram* Get(const StringAnsiView& name, int32 permutationIndex) const;
///
/// Clears collection (deletes all shaders).
///
void Clear();
public:
///
/// Calculates unique hash for given shader program name and its permutation index.
///
/// The shader program name.
/// The shader program permutation index.
/// Calculated hash value.
static uint32 CalculateHash(const StringAnsiView& name, int32 permutationIndex);
};
///
/// The GPU resource with shader programs that can run on the GPU and are able to perform rendering calculation using textures, vertices and other resources.
///
API_CLASS(Sealed, NoSpawn) class FLAXENGINE_API GPUShader : public GPUResource
{
DECLARE_SCRIPTING_TYPE_NO_SPAWN(GPUShader);
protected:
GPUShaderProgramsContainer _shaders;
GPUConstantBuffer* _constantBuffers[MAX_CONSTANT_BUFFER_SLOTS];
GPUShader();
public:
///
/// Creates the shader resource and loads its data from the bytes.
/// The stream with compiled shader data.
/// True if cannot create state, otherwise false.
virtual bool Create(class MemoryReadStream& stream);
public:
///
/// Gets the vertex shader.
///
/// The shader program name.
/// The shader permutation index.
/// The shader object.
API_FUNCTION() FORCE_INLINE GPUShaderProgramVS* GetVS(const StringAnsiView& name, int32 permutationIndex = 0) const
{
return static_cast(GetShader(ShaderStage::Vertex, name, permutationIndex));
}
///
/// Gets the hull shader.
///
/// The shader program name.
/// The shader permutation index.
/// The shader object.
API_FUNCTION() FORCE_INLINE GPUShaderProgramHS* GetHS(const StringAnsiView& name, int32 permutationIndex = 0) const
{
return static_cast(GetShader(ShaderStage::Hull, name, permutationIndex));
}
///
/// Gets domain shader.
///
/// The shader program name.
/// The shader permutation index.
/// The shader object.
API_FUNCTION() FORCE_INLINE GPUShaderProgramDS* GetDS(const StringAnsiView& name, int32 permutationIndex = 0) const
{
return static_cast(GetShader(ShaderStage::Domain, name, permutationIndex));
}
///
/// Gets the geometry shader.
///
/// The shader program name.
/// The shader permutation index.
/// The shader object.
API_FUNCTION() FORCE_INLINE GPUShaderProgramGS* GetGS(const StringAnsiView& name, int32 permutationIndex = 0) const
{
return static_cast(GetShader(ShaderStage::Geometry, name, permutationIndex));
}
///
/// Gets the pixel shader.
///
/// The shader program name.
/// The shader permutation index.
/// The shader object.
API_FUNCTION() FORCE_INLINE GPUShaderProgramPS* GetPS(const StringAnsiView& name, int32 permutationIndex = 0) const
{
return static_cast(GetShader(ShaderStage::Pixel, name, permutationIndex));
}
///
/// Gets the compute shader.
///
/// The shader program name.
/// The shader permutation index.
/// The shader object.
API_FUNCTION() FORCE_INLINE GPUShaderProgramCS* GetCS(const StringAnsiView& name, int32 permutationIndex = 0) const
{
return static_cast(GetShader(ShaderStage::Compute, name, permutationIndex));
}
///
/// Gets the constant buffer.
///
/// The buffer slot index.
/// The Constant Buffer object.
API_FUNCTION() FORCE_INLINE GPUConstantBuffer* GetCB(int32 slot) const
{
ASSERT_LOW_LAYER(slot >= 0 && slot < ARRAY_COUNT(_constantBuffers));
return _constantBuffers[slot];
}
public:
///
/// Determines whether the specified shader program is in the shader.
///
/// The shader program name.
/// The shader permutation index.
/// true if the shader is valid; otherwise, false.
FORCE_INLINE bool HasShader(const StringAnsiView& name, int32 permutationIndex = 0) const
{
return _shaders.Get(name, permutationIndex) != nullptr;
}
protected:
GPUShaderProgram* GetShader(ShaderStage stage, const StringAnsiView& name, int32 permutationIndex) const;
virtual GPUShaderProgram* CreateGPUShaderProgram(ShaderStage type, const GPUShaderProgramInitializer& initializer, byte* cacheBytes, uint32 cacheSize, MemoryReadStream& stream) = 0;
public:
// [GPUResource]
GPUResourceType GetResourceType() const final override;
protected:
// [GPUResource]
void OnReleaseGPU() override;
};