Shader refactor

Refactored DX Shader compilation and reflection to be more similar to opengl
Added support for more than 1 const buffer per shader stage.

This is boilerplate code, no functionality yet, that will be added in further commits. Though this builds without errors do not try and run it at this point.
This commit is contained in:
marauder2k7 2024-02-22 09:58:45 +00:00
parent 1cb5ed6884
commit 55519aac57
4 changed files with 333 additions and 1198 deletions

File diff suppressed because it is too large Load diff

View file

@ -34,263 +34,49 @@
class GFXD3D11Shader;
enum CONST_CLASS
enum SHADER_STAGE
{
D3DPC_SCALAR,
D3DPC_VECTOR,
D3DPC_MATRIX_ROWS,
D3DPC_MATRIX_COLUMNS,
D3DPC_OBJECT,
D3DPC_STRUCT
};
enum CONST_TYPE
{
D3DPT_VOID,
D3DPT_BOOL,
D3DPT_INT,
D3DPT_FLOAT,
D3DPT_STRING,
D3DPT_TEXTURE,
D3DPT_TEXTURE1D,
D3DPT_TEXTURE2D,
D3DPT_TEXTURE3D,
D3DPT_TEXTURECUBE,
D3DPT_SAMPLER,
D3DPT_SAMPLER1D,
D3DPT_SAMPLER2D,
D3DPT_SAMPLER3D,
D3DPT_SAMPLERCUBE,
D3DPT_PIXELSHADER,
D3DPT_VERTEXSHADER,
D3DPT_PIXELFRAGMENT,
D3DPT_VERTEXFRAGMENT
};
enum REGISTER_TYPE
{
D3DRS_BOOL,
D3DRS_INT4,
D3DRS_FLOAT4,
D3DRS_SAMPLER
};
struct ConstantDesc
{
String Name = String::EmptyString;
S32 RegisterIndex = 0;
S32 RegisterCount = 0;
S32 Rows = 0;
S32 Columns = 0;
S32 Elements = 0;
S32 StructMembers = 0;
REGISTER_TYPE RegisterSet = D3DRS_FLOAT4;
CONST_CLASS Class = D3DPC_SCALAR;
CONST_TYPE Type = D3DPT_FLOAT;
U32 Bytes = 0;
};
class ConstantTable
{
public:
bool Create(const void* data);
U32 GetConstantCount() const { return m_constants.size(); }
const String& GetCreator() const { return m_creator; }
const ConstantDesc* GetConstantByIndex(U32 i) const { return &m_constants[i]; }
const ConstantDesc* GetConstantByName(const String& name) const;
void ClearConstants() { m_constants.clear(); }
private:
Vector<ConstantDesc> m_constants;
String m_creator;
};
// Structs
struct CTHeader
{
U32 Size;
U32 Creator;
U32 Version;
U32 Constants;
U32 ConstantInfo;
U32 Flags;
U32 Target;
};
struct CTInfo
{
U32 Name;
U16 RegisterSet;
U16 RegisterIndex;
U16 RegisterCount;
U16 Reserved;
U32 TypeInfo;
U32 DefaultValue;
};
struct CTType
{
U16 Class;
U16 Type;
U16 Rows;
U16 Columns;
U16 Elements;
U16 StructMembers;
U32 StructMemberInfo;
};
// Shader instruction opcodes
const U32 SIO_COMMENT = 0x0000FFFE;
const U32 SIO_END = 0x0000FFFF;
const U32 SI_OPCODE_MASK = 0x0000FFFF;
const U32 SI_COMMENTSIZE_MASK = 0x7FFF0000;
const U32 CTAB_CONSTANT = 0x42415443;
// Member functions
inline bool ConstantTable::Create(const void* data)
{
const U32* ptr = static_cast<const U32*>(data);
while(*++ptr != SIO_END)
{
if((*ptr & SI_OPCODE_MASK) == SIO_COMMENT)
{
// Check for CTAB comment
U32 comment_size = (*ptr & SI_COMMENTSIZE_MASK) >> 16;
if(*(ptr+1) != CTAB_CONSTANT)
{
ptr += comment_size;
continue;
}
// Read header
const char* ctab = reinterpret_cast<const char*>(ptr+2);
size_t ctab_size = (comment_size-1)*4;
const CTHeader* header = reinterpret_cast<const CTHeader*>(ctab);
if(ctab_size < sizeof(*header) || header->Size != sizeof(*header))
return false;
m_creator = ctab + header->Creator;
// Read constants
m_constants.reserve(header->Constants);
const CTInfo* info = reinterpret_cast<const CTInfo*>(ctab + header->ConstantInfo);
for(U32 i = 0; i < header->Constants; ++i)
{
const CTType* type = reinterpret_cast<const CTType*>(ctab + info[i].TypeInfo);
// Fill struct
ConstantDesc desc;
desc.Name = ctab + info[i].Name;
desc.RegisterSet = static_cast<REGISTER_TYPE>(info[i].RegisterSet);
desc.RegisterIndex = info[i].RegisterIndex;
desc.RegisterCount = info[i].RegisterCount;
desc.Rows = type->Rows;
desc.Class = static_cast<CONST_CLASS>(type->Class);
desc.Type = static_cast<CONST_TYPE>(type->Type);
desc.Columns = type->Columns;
desc.Elements = type->Elements;
desc.StructMembers = type->StructMembers;
desc.Bytes = 4 * desc.Elements * desc.Rows * desc.Columns;
m_constants.push_back(desc);
}
return true;
}
}
return false;
}
inline const ConstantDesc* ConstantTable::GetConstantByName(const String& name) const
{
Vector<ConstantDesc>::const_iterator it;
for(it = m_constants.begin(); it != m_constants.end(); ++it)
{
if(it->Name == name)
return &(*it);
}
return NULL;
}
/////////////////// Constant Buffers /////////////////////////////
// Maximum number of CBuffers ($Globals & $Params)
const U32 CBUFFER_MAX = 2;
struct ConstSubBufferDesc
{
U32 start;
U32 size;
ConstSubBufferDesc() : start(0), size(0){}
};
class GFXD3D11ConstBufferLayout : public GenericConstBufferLayout
{
public:
GFXD3D11ConstBufferLayout();
/// Get our constant sub buffer data
Vector<ConstSubBufferDesc> &getSubBufferDesc(){ return mSubBuffers; }
/// We need to manually set the size due to D3D11 alignment
void setSize(U32 size){ mBufferSize = size;}
/// Set a parameter, given a base pointer
virtual bool set(const ParamDesc& pd, const GFXShaderConstType constType, const U32 size, const void* data, U8* basePointer);
protected:
/// Set a matrix, given a base pointer
virtual bool setMatrix(const ParamDesc& pd, const GFXShaderConstType constType, const U32 size, const void* data, U8* basePointer);
Vector<ConstSubBufferDesc> mSubBuffers;
VERTEX_SHADER,
PIXEL_SHADER,
GEOMETRY_SHADER,
DOMAIN_SHADER,
HULL_SHADER,
COMPUTE_SHADER
};
class GFXD3D11ShaderConstHandle : public GFXShaderConstHandle
{
friend class GFXD3D11Shader;
public:
// GFXShaderConstHandle
const String& getName() const;
GFXShaderConstType getType() const;
U32 getArraySize() const;
GFXD3D11ShaderConstHandle(GFXD3D11Shader* shader);
GFXD3D11ShaderConstHandle(GFXD3D11Shader* shader, const GFXShaderConstDesc& desc, S32 samplerNum);
virtual ~GFXD3D11ShaderConstHandle();
WeakRefPtr<GFXD3D11Shader> mShader;
const String& getName() const { return mDesc.name; }
GFXShaderConstType getType() const { return mDesc.constType; }
U32 getArraySize() const { return mDesc.arraySize; }
bool mVertexConstant;
GenericConstBufferLayout::ParamDesc mVertexHandle;
bool mPixelConstant;
GenericConstBufferLayout::ParamDesc mPixelHandle;
/// Is true if this constant is for hardware mesh instancing.
///
/// Note: We currently store its settings in mPixelHandle.
///
bool mInstancingConstant;
void setValid( bool valid ) { mValid = valid; }
S32 getSamplerRegister() const;
U32 getSize() const;
void setValid(bool valid) { mValid = valid; }
/// @warning This will always return the value assigned when the shader was
/// initialized. If the value is later changed this method won't reflect that.
S32 getSamplerRegister() const { return mSamplerNum; }
// Returns true if this is a handle to a sampler register.
bool isSampler() const
{
return ( mPixelConstant && mPixelHandle.constType >= GFXSCT_Sampler ) || ( mVertexConstant && mVertexHandle.constType >= GFXSCT_Sampler );
}
/// Restore to uninitialized state.
void clear()
{
mShader = NULL;
mVertexConstant = false;
mPixelConstant = false;
mInstancingConstant = false;
mVertexHandle.clear();
mPixelHandle.clear();
mValid = false;
return (getType() >= GFXSCT_Sampler);
}
GFXD3D11ShaderConstHandle();
GFXShaderConstDesc mDesc;
GFXD3D11Shader* mShader;
U32 mOffset;
U32 mSize;
S32 mSamplerNum;
SHADER_STAGE stage;
bool mInstancingConstant;
};
/// The D3D11 implementation of a shader constant buffer.
@ -302,9 +88,7 @@ class GFXD3D11ShaderConstBuffer : public GFXShaderConstBuffer
public:
GFXD3D11ShaderConstBuffer(GFXD3D11Shader* shader,
GFXD3D11ConstBufferLayout* vertexLayout,
GFXD3D11ConstBufferLayout* pixelLayout);
GFXD3D11ShaderConstBuffer(GFXD3D11Shader* shader, U32 bufSize, U8* existingConstants);
virtual ~GFXD3D11ShaderConstBuffer();
@ -351,26 +135,9 @@ protected:
void _createBuffers();
template<class T>
inline void SET_CONSTANT(GFXShaderConstHandle* handle,
const T& fv,
GenericConstBuffer *vBuffer,
GenericConstBuffer *pBuffer);
// Constant buffers, VSSetConstantBuffers1 has issues on win 7. So unfortunately for now we have multiple constant buffers
ID3D11Buffer* mConstantBuffersV[CBUFFER_MAX];
ID3D11Buffer* mConstantBuffersP[CBUFFER_MAX];
/// We keep a weak reference to the shader
/// because it will often be deleted.
WeakRefPtr<GFXD3D11Shader> mShader;
//vertex
GFXD3D11ConstBufferLayout* mVertexConstBufferLayout;
GenericConstBuffer* mVertexConstBuffer;
//pixel
GFXD3D11ConstBufferLayout* mPixelConstBufferLayout;
GenericConstBuffer* mPixelConstBuffer;
};
class gfxD3D11Include;
@ -407,57 +174,32 @@ protected:
static const U32 smCompiledShaderTag;
ConstantTable table;
ID3D11VertexShader *mVertShader;
ID3D11PixelShader *mPixShader;
GFXD3D11ConstBufferLayout* mVertexConstBufferLayout;
GFXD3D11ConstBufferLayout* mPixelConstBufferLayout;
static gfxD3DIncludeRef smD3DInclude;
HandleMap mHandles;
U32 mConstBufferSize;
U8* mConstBuffer;
Vector<GFXD3D11ShaderConstHandle*> mValidHandles;
/// The shader disassembly from DX when this shader is compiled.
/// We only store this data in non-release builds.
String mDissasembly;
/// Vector of sampler type descriptions consolidated from _compileShader.
Vector<GFXShaderConstDesc> mSamplerDescriptions;
/// Vector of descriptions (consolidated for the getShaderConstDesc call)
Vector<GFXShaderConstDesc> mShaderConsts;
// These two functions are used when compiling shaders from hlsl
virtual bool _compileShader( const Torque::Path &filePath,
const String &target,
const D3D_SHADER_MACRO *defines,
GenericConstBufferLayout *bufferLayout,
Vector<GFXShaderConstDesc> &samplerDescriptions );
SHADER_STAGE shaderStage,
const D3D_SHADER_MACRO *defines);
void _getShaderConstants( ID3D11ShaderReflection* refTable,
GenericConstBufferLayout *bufferLayout,
Vector<GFXShaderConstDesc> &samplerDescriptions );
bool _convertShaderVariable(const D3D11_SHADER_TYPE_DESC &typeDesc, GFXShaderConstDesc &desc);
bool _saveCompiledOutput( const Torque::Path &filePath,
ID3DBlob *buffer,
GenericConstBufferLayout *bufferLayout,
Vector<GFXShaderConstDesc> &samplerDescriptions );
// Loads precompiled shaders
bool _loadCompiledOutput( const Torque::Path &filePath,
const String &target,
GenericConstBufferLayout *bufferLayoutF,
Vector<GFXShaderConstDesc> &samplerDescriptions );
void _getShaderConstants( ID3D11ShaderReflection* refTable,
SHADER_STAGE shaderStage);
// This is used in both cases
virtual void _buildShaderConstantHandles(GenericConstBufferLayout *layout, bool vertexConst);
virtual void _buildSamplerShaderConstantHandles( Vector<GFXShaderConstDesc> &samplerDescriptions );
virtual void _buildShaderConstantHandles();
/// Used to build the instancing shader constants from
/// the instancing vertex format.

View file

@ -313,24 +313,37 @@ enum GFXMatrixType
enum GFXShaderConstType
{
/// GFX"S"hader"C"onstant"T"ype
GFXSCT_ConstBuffer,
// Scalar
GFXSCT_Float,
GFXSCT_Float,
// Vectors
GFXSCT_Float2,
GFXSCT_Float3,
GFXSCT_Float4,
GFXSCT_Float2,
GFXSCT_Float3,
GFXSCT_Float4,
// Matrices
GFXSCT_Float2x2,
GFXSCT_Float2x2,
GFXSCT_Float3x3,
GFXSCT_Float3x4,
GFXSCT_Float4x3,
GFXSCT_Float4x4,
GFXSCT_Float4x4,
// Scalar
GFXSCT_Int,
GFXSCT_Int,
// Vectors
GFXSCT_Int2,
GFXSCT_Int3,
GFXSCT_Int4,
GFXSCT_Int2,
GFXSCT_Int3,
GFXSCT_Int4,
// Scalar
GFXSCT_UInt,
// Vectors
GFXSCT_UInt2,
GFXSCT_UInt3,
GFXSCT_UInt4,
// Scalar
GFXSCT_Bool,
// Vectors
GFXSCT_Bool2,
GFXSCT_Bool3,
GFXSCT_Bool4,
// Samplers
GFXSCT_Sampler,
GFXSCT_SamplerCube,

View file

@ -72,6 +72,10 @@ public:
String name;
GFXShaderConstType constType;
U32 arraySize; // > 1 means it is an array!
U32 bindPoint; // bind point used for ubo/cb, sampler register for samplers.
U32 offset; // offset for vars
U32 size; // size of buffer/type
U32 shaderStage; // only used dx side.
};
/// This is an opaque handle used by GFXShaderConstBuffer clients to set individual shader constants.