diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp index e08c4f057..0b6d3f330 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp @@ -107,31 +107,45 @@ GFXD3D11ShaderConstHandle::GFXD3D11ShaderConstHandle(GFXD3D11Shader* shader) } GFXD3D11ShaderConstHandle::GFXD3D11ShaderConstHandle(GFXD3D11Shader* shader, - const SHADER_STAGE shaderStage, - const U32 offset, - const U32 size, - const GFXShaderConstDesc& desc, - S32 bindingPoint, - S32 samplerNum) + const GFXShaderConstDesc& desc) : mShader(shader), - mStage(shaderStage), - mOffset(offset), - mSize(size), mDesc(desc), - mBinding(bindingPoint), - mSampler(bindingPoint), + mStage((SHADER_STAGE)desc.shaderStage), + mOffset(desc.offset), + mSize(desc.size * desc.arraySize), + mBinding(desc.bindPoint), + mSampler(desc.samplerReg), mInstancingConstant(false) { - mValid = false; + if (desc.constType == GFXSCT_ConstBuffer) + mValid = false; + else + mValid = true; } GFXD3D11ShaderConstHandle::~GFXD3D11ShaderConstHandle() { } +void GFXD3D11ShaderConstHandle::reinit(const GFXShaderConstDesc& desc) +{ + mDesc = desc; + mStage = (SHADER_STAGE)desc.shaderStage; + mOffset = desc.offset; + mSize = desc.size * desc.arraySize; + mBinding = desc.bindPoint; + mSampler = desc.samplerReg; + mInstancingConstant = false; + + if (desc.constType == GFXSCT_ConstBuffer) + mValid = false; + else + mValid = true; +} + //------------------------------------------------------------------------------ -GFXD3D11ShaderConstBuffer::GFXD3D11ShaderConstBuffer( GFXD3D11Shader* shader, U32 bufSize, U8* existingConstants) +GFXD3D11ShaderConstBuffer::GFXD3D11ShaderConstBuffer( GFXD3D11Shader* shader) { mDeviceContext = D3D11DEVICECONTEXT; } @@ -148,29 +162,35 @@ GFXShader* GFXD3D11ShaderConstBuffer::getShader() void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const F32 fv) { + internalSet(handle, fv); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const Point2F& fv) -{ +{ + internalSet(handle, fv); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const Point3F& fv) -{ +{ + internalSet(handle, fv); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const Point4F& fv) -{ +{ + internalSet(handle, fv); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const PlaneF& fv) -{ +{ + internalSet(handle, fv); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const LinearColorF& fv) -{ +{ + internalSet(handle, fv); } -void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const S32 f) +void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const S32 fv) { // This is the only type that is allowed to be used // with a sampler shader constant type, but it is only @@ -181,52 +201,104 @@ void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const S32 f) if ( ((GFXD3D11ShaderConstHandle*)handle)->isSampler() ) return; + internalSet(handle, fv); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const Point2I& fv) -{ +{ + internalSet(handle, fv); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const Point3I& fv) -{ +{ + internalSet(handle, fv); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const Point4I& fv) -{ +{ + internalSet(handle, fv); +} + + +template +void GFXD3D11ShaderConstBuffer::internalSet(GFXShaderConstHandle* handle, const ConstType& param) +{ + AssertFatal(handle, "GFXD3D11ShaderConstBuffer::internalSet - Handle is NULL!"); + AssertFatal(handle->isValid(), "GFXD3D11ShaderConstBuffer::internalSet - Handle is not valid!"); + AssertFatal(dynamic_cast(handle), "GFXD3D11ShaderConstBuffer::internalSet - Incorrect const buffer type"); + + GFXD3D11ShaderConstHandle* _dxHandle = static_cast(handle); + AssertFatal(mShader == _dxHandle->mShader, "GFXD3D11ShaderConstBuffer::internalSet - Should only set handles which are owned by our shader"); + + BufferDesc bufDesc(_dxHandle->mBinding, (SHADER_STAGE)_dxHandle->mStage); + U8* buf = mBufferMap[bufDesc] + _dxHandle->mOffset; + + if (_dxHandle->mInstancingConstant) + buf = mInstPtr + _dxHandle->mOffset; + + dMemcpy(buf, ¶m, sizeof(ConstType)); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray& fv) -{ +{ + internalSet(handle, fv); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray& fv) -{ +{ + internalSet(handle, fv); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray& fv) -{ +{ + internalSet(handle, fv); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray& fv) -{ +{ + internalSet(handle, fv); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray& fv) -{ +{ + internalSet(handle, fv); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray& fv) -{ +{ + internalSet(handle, fv); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray& fv) -{ +{ + internalSet(handle, fv); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray& fv) -{ +{ + internalSet(handle, fv); +} + +template +void GFXD3D11ShaderConstBuffer::internalSet(GFXShaderConstHandle* handle, const AlignedArray& fv) +{ + AssertFatal(handle, "GFXD3D11ShaderConstBuffer::internalSet - Handle is NULL!"); + AssertFatal(handle->isValid(), "GFXD3D11ShaderConstBuffer::internalSet - Handle is not valid!"); + AssertFatal(dynamic_cast(handle), "GFXD3D11ShaderConstBuffer::internalSet - Incorrect const buffer type"); + + GFXD3D11ShaderConstHandle* _dxHandle = static_cast(handle); + AssertFatal(mShader == _dxHandle->mShader, "GFXD3D11ShaderConstBuffer::internalSet - Should only set handles which are owned by our shader"); + AssertFatal(!_glHandle->mInstancingConstant, "GFXD3D11ShaderConstBuffer::internalSet - Instancing not supported for array"); + BufferDesc bufDesc(_dxHandle->mBinding, (SHADER_STAGE)_dxHandle->mStage); + U8* buf = mBufferMap[bufDesc]; + const U8* fvBuffer = static_cast(fv.getBuffer()); + for (U32 i = 0; i < fv.size(); ++i) + { + dMemcpy(buf + _dxHandle->mOffset + i * sizeof(ConstType), fvBuffer, sizeof(ConstType)); + fvBuffer += fv.getElementSize(); + } + } -#undef SET_CONSTANT void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF& mat, const GFXShaderConstType matrixType) { @@ -234,11 +306,32 @@ void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF& AssertFatal(handle->isValid(), "Handle is not valid!" ); AssertFatal(static_cast(handle), "Incorrect const buffer type!"); - const GFXD3D11ShaderConstHandle* h = static_cast(handle); - AssertFatal(!h->isSampler(), "Handle is sampler constant!" ); - AssertFatal(h->mShader == mShader, "Mismatched shaders!"); + const GFXD3D11ShaderConstHandle* _dxHandle = static_cast(handle); + AssertFatal(!_dxHandle->isSampler(), "Handle is sampler constant!" ); + AssertFatal(_dxHandle->mShader == mShader, "Mismatched shaders!"); + BufferDesc bufDesc(_dxHandle->mBinding, (SHADER_STAGE)_dxHandle->mStage); + U8* buf = mBufferMap[bufDesc] + _dxHandle->mOffset; MatrixF transposed; + if (matrixType == GFXSCT_Float4x3) + { + transposed = mat; + } + else + { + mat.transposeTo(transposed); + } + + if (_dxHandle->mInstancingConstant) + { + if (matrixType == GFXSCT_Float4x4) + dMemcpy(mInstPtr + _dxHandle->mOffset, mat, sizeof(mat)); + + // TODO: Support 3x3 and 2x2 matricies? + return; + } + + } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF* mat, const U32 arraySize, const GFXShaderConstType matrixType) @@ -287,10 +380,6 @@ void GFXD3D11ShaderConstBuffer::resurrect() { } -void GFXD3D11ShaderConstBuffer::_createBuffers() -{ -} - bool GFXD3D11ShaderConstBuffer::isDirty() { return true; @@ -299,16 +388,14 @@ bool GFXD3D11ShaderConstBuffer::isDirty() void GFXD3D11ShaderConstBuffer::activate( GFXD3D11ShaderConstBuffer *prevShaderBuffer ) { PROFILE_SCOPE(GFXD3D11ShaderConstBuffer_activate); - + mShader->setConstantsFromBuffer(this); + mWasLost = false; } void GFXD3D11ShaderConstBuffer::onShaderReload( GFXD3D11Shader *shader ) { AssertFatal( shader == mShader, "GFXD3D11ShaderConstBuffer::onShaderReload is hosed!" ); - - _createBuffers(); - // Set the lost state. mWasLost = true; } @@ -316,8 +403,6 @@ void GFXD3D11ShaderConstBuffer::onShaderReload( GFXD3D11Shader *shader ) //------------------------------------------------------------------------------ GFXD3D11Shader::GFXD3D11Shader() - :mConstBufferSize(0), - mConstBuffer(NULL) { VECTOR_SET_ASSOCIATION( mShaderConsts ); @@ -336,7 +421,8 @@ GFXD3D11Shader::~GFXD3D11Shader() for (HandleMap::Iterator i = mHandles.begin(); i != mHandles.end(); i++) delete i->value; - delete[] mConstBuffer; + for (BufferMap::Iterator i = mBuffers.begin(); i != mBuffers.end(); i++) + delete[] i->value; // release shaders SAFE_RELEASE(mVertShader); @@ -374,10 +460,6 @@ bool GFXD3D11Shader::_init() mShaderConsts.clear(); - for (HandleMap::Iterator iter = mHandles.begin(); iter != mHandles.end(); ++iter) - (iter->value)->setValid(false); - mValidHandles.clear(); - if (!mVertexFile.isEmpty() && !_compileShader( mVertexFile, SHADER_STAGE::VERTEX_SHADER, d3dMacros) ) return false; @@ -696,7 +778,7 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection *refTable, } else if (shaderTypeDesc.Class == D3D_SVC_STRUCT) { - // we gotta loop through its variables =/ ad support in future. for now continue so it skips. + // we gotta loop through its variables =/ add support in future. for now continue so it skips. continue; } @@ -740,7 +822,7 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection *refTable, if (desc.name.find("$") != 0) desc.name = String::ToString("$%s", desc.name.c_str()); desc.constType = GFXSCT_Sampler; - desc.bindPoint = shaderInputBind.BindPoint; + desc.samplerReg = shaderInputBind.BindPoint; desc.shaderStage = shaderStage; mShaderConsts.push_back(desc); } @@ -790,7 +872,43 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection *refTable, void GFXD3D11Shader::_buildShaderConstantHandles() { + // Mark all existing handles as invalid. + // Those that are found when parsing the descriptions will then be marked valid again. + for (HandleMap::Iterator iter = mHandles.begin(); iter != mHandles.end(); ++iter) + (iter->value)->setValid(false); + mValidHandles.clear(); + // loop through all constants, add them to the handle map + // and add the const buffers to the buffer map. + for (U32 i = 0; i < mShaderConsts.size(); i++) + { + GFXShaderConstDesc& desc = mShaderConsts[i]; + + if (desc.constType == GFXSCT_ConstBuffer) + { + BufferDesc bufDesc(desc.bindPoint, (SHADER_STAGE)desc.shaderStage); + BufferMap::Iterator buffer = mBuffers.find(bufDesc); + // already added? pass... + if (buffer != mBuffers.end()) + continue; + + // new buffer with our size. + mBuffers[bufDesc] = new U8[desc.size]; + } + + HandleMap::Iterator handle = mHandles.find(desc.name); + // already added? reinit just in case.. + if (handle != mHandles.end()) + { + handle->value->reinit(desc); + } + else + { + mHandles[desc.name] = new GFXD3D11ShaderConstHandle(this, desc); + } + } + + _buildInstancingShaderConstantHandles(); } void GFXD3D11Shader::_buildInstancingShaderConstantHandles() @@ -819,7 +937,7 @@ void GFXD3D11Shader::_buildInstancingShaderConstantHandles() handle->setValid( true ); handle->mInstancingConstant = true; - + handle->mOffset = offset; // If this is a matrix we will have 2 or 3 more of these // semantics with the same name after it. @@ -838,7 +956,7 @@ void GFXD3D11Shader::_buildInstancingShaderConstantHandles() GFXShaderConstBufferRef GFXD3D11Shader::allocConstBuffer() { - GFXD3D11ShaderConstBuffer* buffer = new GFXD3D11ShaderConstBuffer(this, mConstBufferSize, mConstBuffer); + GFXD3D11ShaderConstBuffer* buffer = new GFXD3D11ShaderConstBuffer(this); mActiveBuffers.push_back( buffer ); buffer->registerResourceWithDevice(getOwningDevice()); return buffer; diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.h b/Engine/source/gfx/D3D11/gfxD3D11Shader.h index 7dea06f6c..235aac852 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.h +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.h @@ -45,6 +45,23 @@ enum SHADER_STAGE COMPUTE_SHADER }; +// simple class to hold everything required for a buffer map. +struct BufferDesc +{ + // for the moment we dont really need to care about the buffer name. + S32 bindingPoint; + SHADER_STAGE stage; + + BufferDesc() + : bindingPoint(-1), stage(SHADER_STAGE::UNKNOWN_STAGE) + {} + + BufferDesc( U32 inBindingPoint, SHADER_STAGE inputStage) + : bindingPoint(inBindingPoint), stage(inputStage) + {} + +}; + class GFXD3D11ShaderConstHandle : public GFXShaderConstHandle { friend class GFXD3D11Shader; @@ -52,15 +69,10 @@ public: GFXD3D11ShaderConstHandle(GFXD3D11Shader* shader); GFXD3D11ShaderConstHandle(GFXD3D11Shader* shader, - const SHADER_STAGE shaderStage, - const U32 offset, - const U32 size, - const GFXShaderConstDesc& desc, - S32 bindingPoint, - S32 samplerNum); + const GFXShaderConstDesc& desc); virtual ~GFXD3D11ShaderConstHandle(); - + void reinit(const GFXShaderConstDesc& desc); const String& getName() const { return mDesc.name; } GFXShaderConstType getType() const { return mDesc.constType; } U32 getArraySize() const { return mDesc.arraySize; } @@ -95,8 +107,9 @@ class GFXD3D11ShaderConstBuffer : public GFXShaderConstBuffer ID3D11DeviceContext* mDeviceContext; public: + typedef Map BufferMap; - GFXD3D11ShaderConstBuffer(GFXD3D11Shader* shader, U32 bufSize, U8* existingConstants); + GFXD3D11ShaderConstBuffer(GFXD3D11Shader* shader); virtual ~GFXD3D11ShaderConstBuffer(); @@ -136,16 +149,20 @@ public: // GFXResource virtual const String describeSelf() const; - virtual void zombify(); - virtual void resurrect(); - -protected: - - void _createBuffers(); + virtual void zombify() {} + virtual void resurrect() {} +private: /// We keep a weak reference to the shader /// because it will often be deleted. WeakRefPtr mShader; + BufferMap mBufferMap; + + template + void internalSet(GFXShaderConstHandle* handle, const ConstType& param); + + template + void internalSet(GFXShaderConstHandle* handle, const AlignedArray& fv); }; class gfxD3D11Include; @@ -160,6 +177,7 @@ class GFXD3D11Shader : public GFXShader public: typedef Map HandleMap; + typedef Map BufferMap; GFXD3D11Shader(); virtual ~GFXD3D11Shader(); @@ -188,8 +206,8 @@ protected: static gfxD3DIncludeRef smD3DInclude; HandleMap mHandles; - U32 mConstBufferSize; - U8* mConstBuffer; + BufferMap mBuffers; + Vector mValidHandles; /// The shader disassembly from DX when this shader is compiled. /// We only store this data in non-release builds. @@ -208,10 +226,9 @@ protected: // This is used in both cases virtual void _buildShaderConstantHandles(); - - /// Used to build the instancing shader constants from - /// the instancing vertex format. void _buildInstancingShaderConstantHandles(); + + void setConstantsFromBuffer(GFXD3D11ShaderConstBuffer* buffer); }; inline bool GFXD3D11Shader::getDisassembly(String &outStr) const diff --git a/Engine/source/gfx/gfxShader.h b/Engine/source/gfx/gfxShader.h index 8901c9332..a8008eddf 100644 --- a/Engine/source/gfx/gfxShader.h +++ b/Engine/source/gfx/gfxShader.h @@ -71,11 +71,12 @@ struct GFXShaderConstDesc 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. + U32 arraySize; // > 1 means it is an array! + S32 bindPoint; // bind point used for ubo/cb. + S32 samplerReg; // sampler register. + 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.