From a1e2f781a88360250745b90c185bd59fa0a3eac9 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Fri, 23 Feb 2024 20:06:46 +0000 Subject: [PATCH] Set constant buffers added logic to set constant buffers dx side --- Engine/source/gfx/D3D11/gfxD3D11Shader.cpp | 167 +++++++++++++++++++-- Engine/source/gfx/D3D11/gfxD3D11Shader.h | 31 +++- 2 files changed, 180 insertions(+), 18 deletions(-) diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp index 0b6d3f330..2db4e58b7 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp @@ -331,6 +331,30 @@ void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF& return; } + if (matrixType == GFXSCT_Float4x4) + { + dMemcpy(buf, transposed, sizeof(MatrixF)); + return; + } + + U32 csize; + switch (matrixType) + { + case GFXSCT_Float2x2: + csize = 24; //this takes up 16+8 + break; + case GFXSCT_Float3x3: + csize = 44; //This takes up 16+16+12 + break; + case GFXSCT_Float4x3: + csize = 48; + break; + default: + return; + break; + } + + dMemcpy(buf, transposed, csize); } @@ -340,9 +364,13 @@ 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] ; static Vector transposed; if (arraySize > transposed.size()) @@ -359,8 +387,37 @@ void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF* } // TODO: Maybe support this in the future? - if (h->mInstancingConstant) + if (_dxHandle->mInstancingConstant) return; + + if (matrixType == GFXSCT_Float4x4) + { + dMemcpy(buf + _dxHandle->mOffset, transposed.address(), _dxHandle->getSize()); + return; + } + + U32 csize; + switch (matrixType) + { + case GFXSCT_Float2x2: + csize = 24; //this takes up 16+8 + break; + case GFXSCT_Float3x3: + csize = 44; //This takes up 16+16+12 + break; + case GFXSCT_Float4x3: + csize = 48; + break; + default: + return; + break; + } + + for (int i = 0; i < arraySize; i++) + { + dMemcpy(buf + _dxHandle->mOffset + (i * csize), transposed[i], csize); + } + } const String GFXD3D11ShaderConstBuffer::describeSelf() const @@ -372,19 +429,22 @@ const String GFXD3D11ShaderConstBuffer::describeSelf() const return ret; } -void GFXD3D11ShaderConstBuffer::zombify() -{ -} - -void GFXD3D11ShaderConstBuffer::resurrect() -{ -} - bool GFXD3D11ShaderConstBuffer::isDirty() { return true; } +void GFXD3D11ShaderConstBuffer::addBuffer(BufferDesc bufDesc, U32 size) +{ + BufferMap::Iterator buffer = mBufferMap.find(bufDesc); + // already added? pass... + if (buffer != mBufferMap.end()) + return; + + // new buffer with our size. + mBufferMap[bufDesc] = new U8[size]; +} + void GFXD3D11ShaderConstBuffer::activate( GFXD3D11ShaderConstBuffer *prevShaderBuffer ) { PROFILE_SCOPE(GFXD3D11ShaderConstBuffer_activate); @@ -422,7 +482,14 @@ GFXD3D11Shader::~GFXD3D11Shader() delete i->value; for (BufferMap::Iterator i = mBuffers.begin(); i != mBuffers.end(); i++) + { delete[] i->value; + } + + for (U32 i = 0; i < 16; i++) + { + SAFE_RELEASE(mBoundConstantBuffers[i]); + } // release shaders SAFE_RELEASE(mVertShader); @@ -707,6 +774,7 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection *refTable, desc.constType = GFXSCT_ConstBuffer; desc.bindPoint = shaderInputBind.BindPoint; desc.shaderStage = shaderStage; + desc.samplerReg = -1; ID3D11ShaderReflectionConstantBuffer* constantBuffer = refTable->GetConstantBufferByName(shaderInputBind.Name); D3D11_SHADER_BUFFER_DESC constantBufferDesc; @@ -737,6 +805,7 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection *refTable, varDesc.arraySize = mMax(shaderTypeDesc.Elements, 1); varDesc.size = shaderVarDesc.Size; varDesc.shaderStage = shaderStage; + varDesc.samplerReg = -1; if (shaderTypeDesc.Class == D3D_SVC_SCALAR || shaderTypeDesc.Class == D3D_SVC_VECTOR) { @@ -823,6 +892,7 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection *refTable, desc.name = String::ToString("$%s", desc.name.c_str()); desc.constType = GFXSCT_Sampler; desc.samplerReg = shaderInputBind.BindPoint; + desc.bindPoint = shaderInputBind.BindPoint; // not really needed but hey.. desc.shaderStage = shaderStage; mShaderConsts.push_back(desc); } @@ -892,12 +962,35 @@ void GFXD3D11Shader::_buildShaderConstantHandles() if (buffer != mBuffers.end()) continue; + ID3D11Buffer* constBuffer = nullptr; + D3D11_BUFFER_DESC cbDesc; + cbDesc.ByteWidth = desc.size; + cbDesc.Usage = D3D11_USAGE_DEFAULT; + cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + cbDesc.CPUAccessFlags = 0; + cbDesc.MiscFlags = 0; + cbDesc.StructureByteStride = 0; + + HRESULT hr; + hr = D3D11DEVICE->CreateBuffer(&cbDesc, NULL, &constBuffer); + + if (FAILED(hr)) + { + AssertFatal(false, "can't create constant buffer: %s", desc.name.c_str()); + } + + mBoundConstantBuffers[desc.bindPoint] = constBuffer; + // new buffer with our size. mBuffers[bufDesc] = new U8[desc.size]; + + // do not add to handles.. + continue; } HandleMap::Iterator handle = mHandles.find(desc.name); // already added? reinit just in case.. + // not sure if we need to do anything different with samplers. if (handle != mHandles.end()) { handle->value->reinit(desc); @@ -954,9 +1047,59 @@ void GFXD3D11Shader::_buildInstancingShaderConstantHandles() } } +void GFXD3D11Shader::setConstantsFromBuffer(GFXD3D11ShaderConstBuffer* buffer) +{ + BufferRange bufRanges[6] = {}; + + for (BufferMap::Iterator i = mBuffers.begin(); i != mBuffers.end(); ++i) + { + BufferDesc oldBufferDesc = i->key; + U8* oldBuff = i->value; + + U8* newBuff = buffer->mBufferMap[i->key]; + + if (dMemcmp(oldBuff, newBuff, sizeof(oldBuff)) != 0) + { + // else copy new over the buffer. + dMemcpy(oldBuff, newBuff, sizeof(oldBuff)); + + // buffer has been changed and needs updating. + D3D11DEVICECONTEXT->UpdateSubresource(mBoundConstantBuffers[oldBufferDesc.bindingPoint], 0, NULL, oldBuff, sizeof(oldBuff), 0); + } + + bufRanges[oldBufferDesc.stage].addSlot(oldBufferDesc.bindingPoint); + } + + if (mVertShader != nullptr) + { + const U32 bufStartSlot = bufRanges[SHADER_STAGE::VERTEX_SHADER].mBufMin; + const U32 numBufs = bufRanges[SHADER_STAGE::VERTEX_SHADER].mBufMax - bufRanges[SHADER_STAGE::VERTEX_SHADER].mBufMin + 1; + ID3D11Buffer** vsBuffers = mBoundConstantBuffers + bufStartSlot; + + D3D11DEVICECONTEXT->VSSetConstantBuffers(bufStartSlot, numBufs, vsBuffers); + } + + if (mPixShader != nullptr) + { + const U32 bufStartSlot = bufRanges[SHADER_STAGE::PIXEL_SHADER].mBufMin; + const U32 numBufs = bufRanges[SHADER_STAGE::PIXEL_SHADER].mBufMax - bufRanges[SHADER_STAGE::PIXEL_SHADER].mBufMin + 1; + ID3D11Buffer** psBuffers = mBoundConstantBuffers + bufStartSlot; + + D3D11DEVICECONTEXT->PSSetConstantBuffers(bufStartSlot, numBufs, psBuffers); + } + +} + GFXShaderConstBufferRef GFXD3D11Shader::allocConstBuffer() { GFXD3D11ShaderConstBuffer* buffer = new GFXD3D11ShaderConstBuffer(this); + + for (BufferMap::Iterator i = mBuffers.begin(); i != mBuffers.end(); ++i) + { + // add our buffer descriptions to the full const buffer. + buffer->addBuffer(i->key, sizeof(i->value)); + } + 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 235aac852..e5d54fa07 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.h +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.h @@ -36,13 +36,13 @@ class GFXD3D11Shader; enum SHADER_STAGE { - UNKNOWN_STAGE, VERTEX_SHADER, PIXEL_SHADER, GEOMETRY_SHADER, DOMAIN_SHADER, HULL_SHADER, - COMPUTE_SHADER + COMPUTE_SHADER, + UNKNOWN_STAGE }; // simple class to hold everything required for a buffer map. @@ -62,6 +62,18 @@ struct BufferDesc }; +struct BufferRange +{ + U32 mBufMin = 0xFFFFFFFF; + U32 mBufMax = 0; + + inline void addSlot(U32 slot) + { + mBufMin = getMin(mBufMin, slot); + mBufMax = getMax(mBufMax, slot); + } +}; + class GFXD3D11ShaderConstHandle : public GFXShaderConstHandle { friend class GFXD3D11Shader; @@ -81,7 +93,7 @@ public: 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 mSampler; } + S32 getSamplerRegister() const { return (!isSampler() || !mValid) ? -1 : mSampler; } // Returns true if this is a handle to a sampler register. bool isSampler() const @@ -94,7 +106,7 @@ public: U32 mOffset; U32 mSize; S32 mBinding; // buffer binding point used to map handles to buffers. - S32 mSampler; // sampler. + S32 mSampler; // sampler number, will be -1 if not a sampler. SHADER_STAGE mStage; bool mInstancingConstant; }; @@ -102,7 +114,6 @@ public: /// The D3D11 implementation of a shader constant buffer. class GFXD3D11ShaderConstBuffer : public GFXShaderConstBuffer { - friend class GFXD3D11Shader; // Cache device context ID3D11DeviceContext* mDeviceContext; @@ -120,6 +131,8 @@ public: /// Used internally by GXD3D11ShaderConstBuffer to determine if it's dirty. bool isDirty(); + void addBuffer(BufferDesc bufDesc, U32 size); + /// Called from GFXD3D11Shader when constants have changed and need /// to be the shader this buffer references is reloaded. void onShaderReload(GFXD3D11Shader *shader); @@ -153,6 +166,7 @@ public: virtual void resurrect() {} private: + friend class GFXD3D11Shader; /// We keep a weak reference to the shader /// because it will often be deleted. WeakRefPtr mShader; @@ -203,6 +217,9 @@ protected: ID3D11VertexShader *mVertShader; ID3D11PixelShader *mPixShader; + // we probably want this to be GFXDevice and not per shader. + ID3D11Buffer* mBoundConstantBuffers[16] = {}; + static gfxD3DIncludeRef smD3DInclude; HandleMap mHandles; @@ -215,7 +232,9 @@ protected: /// Vector of descriptions (consolidated for the getShaderConstDesc call) Vector mShaderConsts; - + + //Vector mDeviceBuffers; + // These two functions are used when compiling shaders from hlsl virtual bool _compileShader( const Torque::Path &filePath, SHADER_STAGE shaderStage,