From fba034195eb9b3a13eb1c17a6be5c4d9c4826b80 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Thu, 27 Jul 2023 09:25:32 +0100 Subject: [PATCH 01/53] Update test-results.yml --- .github/workflows/test-results.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/test-results.yml b/.github/workflows/test-results.yml index 12fbe4b9d..9e9082fd5 100644 --- a/.github/workflows/test-results.yml +++ b/.github/workflows/test-results.yml @@ -23,10 +23,12 @@ jobs: } - { name: "Linux Test Results", + runos: ubuntu-latest, artifact-name: "torque3dLinuxGCCUnitTest" } - { name: "Mac Test Results", + runos: macos-latest, artifact-name: "torque3dMacOSXCLANGUnitTest" } From a43675be7e5174c3cf9fb55baa3c1a768e176aa7 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Thu, 27 Jul 2023 09:53:52 +0100 Subject: [PATCH 02/53] test runner --- .github/workflows/build-windows-msvc.yml | 1 - .github/workflows/test-results-linux.yml | 40 ++++++++++++++++++++++ .github/workflows/test-results-mac.yml | 40 ++++++++++++++++++++++ .github/workflows/test-results-windows.yml | 40 ++++++++++++++++++++++ 4 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/test-results-linux.yml create mode 100644 .github/workflows/test-results-mac.yml create mode 100644 .github/workflows/test-results-windows.yml diff --git a/.github/workflows/build-windows-msvc.yml b/.github/workflows/build-windows-msvc.yml index ee642d711..6dd243048 100644 --- a/.github/workflows/build-windows-msvc.yml +++ b/.github/workflows/build-windows-msvc.yml @@ -9,7 +9,6 @@ concurrency: cancel-in-progress: true jobs: build-windows: - if: github.repository == 'TorqueGameEngines/Torque3D' name: ${{matrix.config.name}} runs-on: windows-latest strategy: diff --git a/.github/workflows/test-results-linux.yml b/.github/workflows/test-results-linux.yml new file mode 100644 index 000000000..0792902a1 --- /dev/null +++ b/.github/workflows/test-results-linux.yml @@ -0,0 +1,40 @@ +name: Report Test Results +on: + workflow_run: + workflows: ["Linux Build"] + types: + - completed + +permissions: + checks: write + +jobs: + checks: + name: ${{matrix.config.name}} + runs-on: ${{matrix.config.runos}} + strategy: + fail-fast: false + matrix: + config: + - { + name: "Linux Test Results", + runos: ubuntu-latest, + artifact-name: "torque3dLinuxGCCUnitTest" + } + + steps: + - name: Download Linux Test Report + uses: dawidd6/action-download-artifact@v2 + with: + path: Linux + name: ${{matrix.config.artifact-name}} + workflow: ${{ github.event.workflow.id }} + run_id: ${{ github.event.workflow_run.id }} + + - name: Test Reporter + uses: phoenix-actions/test-reporting@v12 + with: + artifact: ${{matrix.config.artifact-name}} + name: ${{matrix.config.name}} + path: "**/My Projects/Torque3D/game/test_detail.xml" + reporter: java-junit diff --git a/.github/workflows/test-results-mac.yml b/.github/workflows/test-results-mac.yml new file mode 100644 index 000000000..8c55748a1 --- /dev/null +++ b/.github/workflows/test-results-mac.yml @@ -0,0 +1,40 @@ +name: Report Test Results +on: + workflow_run: + workflows: ["MacOSX Build"] + types: + - completed + +permissions: + checks: write + +jobs: + checks: + name: ${{matrix.config.name}} + runs-on: ${{matrix.config.runos}} + strategy: + fail-fast: false + matrix: + config: + - { + name: "Mac Test Results", + runos: macos-latest, + artifact-name: "torque3dMacOSXCLANGUnitTest" + } + + steps: + - name: Download Mac Test Report + uses: dawidd6/action-download-artifact@v2 + with: + path: macOS + name: ${{matrix.config.artifact-name}} + workflow: ${{ github.event.workflow.id }} + run_id: ${{ github.event.workflow_run.id }} + + - name: Test Reporter + uses: phoenix-actions/test-reporting@v12 + with: + artifact: ${{matrix.config.artifact-name}} + name: ${{matrix.config.name}} + path: "**/My Projects/Torque3D/game/test_detail.xml" + reporter: java-junit diff --git a/.github/workflows/test-results-windows.yml b/.github/workflows/test-results-windows.yml new file mode 100644 index 000000000..0fa435464 --- /dev/null +++ b/.github/workflows/test-results-windows.yml @@ -0,0 +1,40 @@ +name: Report Test Results +on: + workflow_run: + workflows: ["Windows Build"] + types: + - completed + +permissions: + checks: write + +jobs: + checks: + name: ${{matrix.config.name}} + runs-on: ${{matrix.config.runos}} + strategy: + fail-fast: false + matrix: + config: + - { + name: "Windows Test Results", + runos: windows-latest, + artifact-name: "torque3dWindowsMSVCUnitTest" + } + + steps: + - name: Download Windows Test Report + uses: dawidd6/action-download-artifact@v2 + with: + path: Windows + name: ${{matrix.config.artifact-name}} + workflow: ${{ github.event.workflow.id }} + run_id: ${{ github.event.workflow_run.id }} + + - name: Test Reporter + uses: phoenix-actions/test-reporting@v12 + with: + artifact: ${{matrix.config.artifact-name}} + name: ${{matrix.config.name}} + path: "**/My Projects/Torque3D/game/test_detail.xml" + reporter: java-junit From 74d87c54a018e9c89e7a6840caf072fc36a7a161 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Tue, 1 Aug 2023 06:43:45 +0100 Subject: [PATCH 03/53] Update test-results-linux.yml --- .github/workflows/test-results-linux.yml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/.github/workflows/test-results-linux.yml b/.github/workflows/test-results-linux.yml index c7a5977f6..7f61a8c5f 100644 --- a/.github/workflows/test-results-linux.yml +++ b/.github/workflows/test-results-linux.yml @@ -21,15 +21,6 @@ jobs: runos: ubuntu-latest, artifact-name: "torque3dLinuxGCCUnitTest" } -<<<<<<<< HEAD:.github/workflows/test-results.yml - - { - name: "Mac Test Results", - runos: macos-latest, - artifact-name: "torque3dMacOSXCLANGUnitTest" - } -======== ->>>>>>>> upstream/development:.github/workflows/test-results-linux.yml - steps: - name: Download Linux Test Report uses: dawidd6/action-download-artifact@v2 From 55519aac5756eeda38268c74171976ed2fb2b409 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Thu, 22 Feb 2024 09:58:45 +0000 Subject: [PATCH 04/53] 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. --- Engine/source/gfx/D3D11/gfxD3D11Shader.cpp | 1164 +++++--------------- Engine/source/gfx/D3D11/gfxD3D11Shader.h | 330 +----- Engine/source/gfx/gfxEnums.h | 33 +- Engine/source/gfx/gfxShader.h | 4 + 4 files changed, 333 insertions(+), 1198 deletions(-) diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp index 17827349d..555ec9d98 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp @@ -93,262 +93,35 @@ HRESULT gfxD3D11Include::Close( THIS_ LPCVOID pData ) return S_OK; } +GFXD3D11ShaderConstHandle::GFXD3D11ShaderConstHandle(GFXD3D11Shader* shader) +{ +} + +GFXD3D11ShaderConstHandle::GFXD3D11ShaderConstHandle(GFXD3D11Shader* shader, const GFXShaderConstDesc& desc, S32 samplerNum) +{ +} + +GFXD3D11ShaderConstHandle::~GFXD3D11ShaderConstHandle() +{ +} + +U32 GFXD3D11ShaderConstHandle::getSize() const +{ + return U32(); +} + GFXD3D11ShaderConstHandle::GFXD3D11ShaderConstHandle() { - clear(); -} - -const String& GFXD3D11ShaderConstHandle::getName() const -{ - if ( mVertexConstant ) - return mVertexHandle.name; - else - return mPixelHandle.name; -} - -GFXShaderConstType GFXD3D11ShaderConstHandle::getType() const -{ - if ( mVertexConstant ) - return mVertexHandle.constType; - else - return mPixelHandle.constType; -} - -U32 GFXD3D11ShaderConstHandle::getArraySize() const -{ - if ( mVertexConstant ) - return mVertexHandle.arraySize; - else - return mPixelHandle.arraySize; -} - -S32 GFXD3D11ShaderConstHandle::getSamplerRegister() const -{ - if ( !mValid || !isSampler() ) - return -1; - - // We always store sampler type and register index in the pixelHandle, - // sampler registers are shared between vertex and pixel shaders anyway. - - return mPixelHandle.offset; -} - -GFXD3D11ConstBufferLayout::GFXD3D11ConstBufferLayout() -{ - mSubBuffers.reserve(CBUFFER_MAX); -} - -bool GFXD3D11ConstBufferLayout::set(const ParamDesc& pd, const GFXShaderConstType constType, const U32 inSize, const void* data, U8* basePointer) -{ - PROFILE_SCOPE(GenericConstBufferLayout_set); - S32 size = inSize; - // Shader compilers like to optimize float4x4 uniforms into float3x3s. - // So long as the real paramater is a matrix of-some-type and the data - // passed in is a MatrixF ( which is will be ), we DO NOT have a - // mismatched const type. - AssertFatal(pd.constType == constType || - ( - (pd.constType == GFXSCT_Float2x2 || - pd.constType == GFXSCT_Float3x3 || - pd.constType == GFXSCT_Float4x3 || - pd.constType == GFXSCT_Float4x4) && - (constType == GFXSCT_Float2x2 || - constType == GFXSCT_Float3x3 || - constType == GFXSCT_Float4x3 || - constType == GFXSCT_Float4x4) - ), "Mismatched const type!"); - - // This "cute" bit of code allows us to support 2x3 and 3x3 matrices in shader constants but use our MatrixF class. Yes, a hack. -BTR - switch (pd.constType) - { - case GFXSCT_Float2x2: - case GFXSCT_Float3x3: - case GFXSCT_Float4x3: - case GFXSCT_Float4x4: - return setMatrix(pd, constType, size, data, basePointer); - break; - // TODO add other AlignedVector here - case GFXSCT_Float2: - if (size > sizeof(Point2F)) - size = pd.size; - default: - break; - } - - AssertFatal(pd.size >= size, "Not enough room in the buffer for this data!"); - - // Ok, we only set data if it's different than the data we already have, this maybe more expensive than just setting the data, but - // we'll have to do some timings to see. For example, the lighting shader constants rarely change, but we can't assume that at the - // renderInstMgr level, but we can check down here. -BTR - if (dMemcmp(basePointer + pd.offset, data, size) != 0) - { - dMemcpy(basePointer + pd.offset, data, size); - return true; - } - return false; -} - -bool GFXD3D11ConstBufferLayout::setMatrix(const ParamDesc& pd, const GFXShaderConstType constType, const U32 size, const void* data, U8* basePointer) -{ - PROFILE_SCOPE(GFXD3D11ConstBufferLayout_setMatrix); - - if (pd.constType == GFXSCT_Float4x4) - { - // Special case, we can just blast this guy. - AssertFatal(pd.size >= size, "Not enough room in the buffer for this data!"); - if (dMemcmp(basePointer+pd.offset, data, size) != 0) - { - dMemcpy(basePointer+pd.offset, data, size); - return true; - } - - return false; - } - else - { - PROFILE_SCOPE(GFXD3D11ConstBufferLayout_setMatrix_not4x4); - - // Figure out how big of a chunk we are copying. We're going to copy 4 columns by N rows of data - U32 csize; - switch (pd.constType) - { - 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: - AssertFatal(false, "Unhandled case!"); - return false; - break; - } - - // Loop through and copy - bool ret = false; - U8* currDestPointer = basePointer+pd.offset; - const U8* currSourcePointer = static_cast(data); - const U8* endData = currSourcePointer + size; - while (currSourcePointer < endData) - { - if (dMemcmp(currDestPointer, currSourcePointer, csize) != 0) - { - dMemcpy(currDestPointer, currSourcePointer, csize); - ret = true; - } - else if (pd.constType == GFXSCT_Float4x3) - { - ret = true; - } - - currDestPointer += csize; - currSourcePointer += sizeof(MatrixF); - } - - return ret; - } } //------------------------------------------------------------------------------ -GFXD3D11ShaderConstBuffer::GFXD3D11ShaderConstBuffer( GFXD3D11Shader* shader, - GFXD3D11ConstBufferLayout* vertexLayout, - GFXD3D11ConstBufferLayout* pixelLayout) +GFXD3D11ShaderConstBuffer::GFXD3D11ShaderConstBuffer( GFXD3D11Shader* shader, U32 bufSize, U8* existingConstants) { - AssertFatal( shader, "GFXD3D11ShaderConstBuffer() - Got a null shader!" ); - - // We hold on to this so we don't have to call - // this virtual method during activation. - mShader = shader; - - for (U32 i = 0; i < CBUFFER_MAX; ++i) - { - mConstantBuffersV[i] = NULL; - mConstantBuffersP[i] = NULL; - } - - // TODO: Remove buffers and layouts that don't exist for performance? - //Mandatory - mVertexConstBufferLayout = vertexLayout; - mVertexConstBuffer = new GenericConstBuffer(vertexLayout); - - mPixelConstBufferLayout = pixelLayout; - mPixelConstBuffer = new GenericConstBuffer(pixelLayout); - - mDeviceContext = D3D11DEVICECONTEXT; - - _createBuffers(); - } GFXD3D11ShaderConstBuffer::~GFXD3D11ShaderConstBuffer() -{ - // release constant buffer - for (U32 i = 0; i < CBUFFER_MAX; ++i) - { - SAFE_RELEASE(mConstantBuffersP[i]); - SAFE_RELEASE(mConstantBuffersV[i]); - } - - SAFE_DELETE(mVertexConstBuffer); - SAFE_DELETE(mPixelConstBuffer); - - - if ( mShader ) - mShader->_unlinkBuffer( this ); -} - -void GFXD3D11ShaderConstBuffer::_createBuffers() { - HRESULT hr; - // Create a vertex constant buffer - if (mVertexConstBufferLayout->getBufferSize() > 0) - { - const Vector &subBuffers = mVertexConstBufferLayout->getSubBufferDesc(); - for (U32 i = 0; i < subBuffers.size(); ++i) - { - D3D11_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = subBuffers[i].size; - cbDesc.Usage = D3D11_USAGE_DEFAULT; - cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = 0; - cbDesc.MiscFlags = 0; - cbDesc.StructureByteStride = 0; - hr = D3D11DEVICE->CreateBuffer(&cbDesc, NULL, &mConstantBuffersV[i]); - - if (FAILED(hr)) - { - AssertFatal(false, "can't create constant mConstantBuffersV!"); - } - } - } - - // Create a pixel constant buffer - if (mPixelConstBufferLayout->getBufferSize()) - { - const Vector &subBuffers = mPixelConstBufferLayout->getSubBufferDesc(); - for (U32 i = 0; i < subBuffers.size(); ++i) - { - // Create a pixel float constant buffer - D3D11_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = subBuffers[i].size; - cbDesc.Usage = D3D11_USAGE_DEFAULT; - cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = 0; - cbDesc.MiscFlags = 0; - cbDesc.StructureByteStride = 0; - - hr = D3D11DEVICE->CreateBuffer(&cbDesc, NULL, &mConstantBuffersP[i]); - - if (FAILED(hr)) - { - AssertFatal(false, "can't create constant mConstantBuffersP!"); - } - } - } } GFXShader* GFXD3D11ShaderConstBuffer::getShader() @@ -356,60 +129,28 @@ GFXShader* GFXD3D11ShaderConstBuffer::getShader() return mShader; } -// This is kind of cheesy, but I don't think templates would work well here because -// these functions potentially need to be handled differently by other derived types -template -inline void GFXD3D11ShaderConstBuffer::SET_CONSTANT( GFXShaderConstHandle* handle, const T& fv, - GenericConstBuffer *vBuffer, GenericConstBuffer *pBuffer ) -{ - AssertFatal(static_cast(handle), "Incorrect const buffer type!"); - const GFXD3D11ShaderConstHandle* h = static_cast(handle); - AssertFatal(h, "Handle is NULL!" ); - AssertFatal(h->isValid(), "Handle is not valid!" ); - AssertFatal(!h->isSampler(), "Handle is sampler constant!" ); - AssertFatal(!mShader.isNull(), "Buffer's shader is null!" ); - AssertFatal(!h->mShader.isNull(), "Handle's shader is null!" ); - AssertFatal(h->mShader.getPointer() == mShader.getPointer(), "Mismatched shaders!"); - - if ( h->mInstancingConstant ) - { - dMemcpy( mInstPtr+h->mPixelHandle.offset, &fv, sizeof( fv ) ); - return; - } - if (h->mVertexConstant) - vBuffer->set(h->mVertexHandle, fv); - if (h->mPixelConstant) - pBuffer->set(h->mPixelHandle, fv); -} - void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const F32 fv) { - SET_CONSTANT(handle, fv, mVertexConstBuffer, mPixelConstBuffer); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const Point2F& fv) { - SET_CONSTANT(handle, fv, mVertexConstBuffer, mPixelConstBuffer); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const Point3F& fv) { - SET_CONSTANT(handle, fv, mVertexConstBuffer, mPixelConstBuffer); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const Point4F& fv) { - SET_CONSTANT(handle, fv, mVertexConstBuffer, mPixelConstBuffer); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const PlaneF& fv) { - SET_CONSTANT(handle, fv, mVertexConstBuffer, mPixelConstBuffer); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const LinearColorF& fv) { - SET_CONSTANT(handle, fv, mVertexConstBuffer, mPixelConstBuffer); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const S32 f) @@ -423,62 +164,50 @@ void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const S32 f) if ( ((GFXD3D11ShaderConstHandle*)handle)->isSampler() ) return; - SET_CONSTANT(handle, f, mVertexConstBuffer, mPixelConstBuffer); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const Point2I& fv) { - SET_CONSTANT(handle, fv, mVertexConstBuffer, mPixelConstBuffer); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const Point3I& fv) { - SET_CONSTANT(handle, fv, mVertexConstBuffer, mPixelConstBuffer); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const Point4I& fv) { - SET_CONSTANT(handle, fv, mVertexConstBuffer, mPixelConstBuffer); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray& fv) { - SET_CONSTANT(handle, fv, mVertexConstBuffer, mPixelConstBuffer); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray& fv) { - SET_CONSTANT(handle, fv, mVertexConstBuffer, mPixelConstBuffer); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray& fv) { - SET_CONSTANT(handle, fv, mVertexConstBuffer, mPixelConstBuffer); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray& fv) { - SET_CONSTANT(handle, fv, mVertexConstBuffer, mPixelConstBuffer); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray& fv) { - SET_CONSTANT(handle, fv, mVertexConstBuffer, mPixelConstBuffer); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray& fv) { - SET_CONSTANT(handle, fv, mVertexConstBuffer, mPixelConstBuffer); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray& fv) { - SET_CONSTANT(handle, fv, mVertexConstBuffer, mPixelConstBuffer); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray& fv) { - SET_CONSTANT(handle, fv, mVertexConstBuffer, mPixelConstBuffer); } #undef SET_CONSTANT @@ -493,39 +222,17 @@ void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF& AssertFatal(h->mShader == mShader, "Mismatched shaders!"); MatrixF transposed; - if (matrixType == GFXSCT_Float4x3) - { - transposed = mat; - } - else - { - mat.transposeTo(transposed); - } - - if (h->mInstancingConstant) - { - if ( matrixType == GFXSCT_Float4x4 ) - dMemcpy( mInstPtr+h->mPixelHandle.offset, mat, sizeof( mat ) ); - - // TODO: Support 3x3 and 2x2 matricies? - return; - } - - if (h->mVertexConstant) - mVertexConstBuffer->set(h->mVertexHandle, transposed, matrixType); - if (h->mPixelConstant) - mPixelConstBuffer->set(h->mPixelHandle, transposed, matrixType); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF* mat, const U32 arraySize, const GFXShaderConstType matrixType) { - AssertFatal(handle, "Handle is NULL!" ); - AssertFatal(handle->isValid(), "Handle is not valid!" ); + AssertFatal(handle, "Handle is NULL!"); + 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!"); + 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!"); static Vector transposed; if (arraySize > transposed.size()) @@ -542,13 +249,8 @@ void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF* } // TODO: Maybe support this in the future? - if (h->mInstancingConstant) + if (h->mInstancingConstant) return; - - if (h->mVertexConstant) - mVertexConstBuffer->set(h->mVertexHandle, transposed.begin(), arraySize, matrixType); - if (h->mPixelConstant) - mPixelConstBuffer->set(h->mPixelHandle, transposed.begin(), arraySize, matrixType); } const String GFXD3D11ShaderConstBuffer::describeSelf() const @@ -556,13 +258,6 @@ const String GFXD3D11ShaderConstBuffer::describeSelf() const String ret; ret = String(" GFXD3D11ShaderConstBuffer\n"); - for (U32 i = 0; i < mVertexConstBufferLayout->getParameterCount(); i++) - { - GenericConstBufferLayout::ParamDesc pd; - mVertexConstBufferLayout->getDesc(i, pd); - - ret += String::ToString(" Constant name: %s", pd.name.c_str()); - } return ret; } @@ -575,132 +270,25 @@ void GFXD3D11ShaderConstBuffer::resurrect() { } +void GFXD3D11ShaderConstBuffer::_createBuffers() +{ +} + bool GFXD3D11ShaderConstBuffer::isDirty() { - bool ret = mVertexConstBuffer->isDirty(); - ret |= mPixelConstBuffer->isDirty(); - - return ret; + return true; } void GFXD3D11ShaderConstBuffer::activate( GFXD3D11ShaderConstBuffer *prevShaderBuffer ) { PROFILE_SCOPE(GFXD3D11ShaderConstBuffer_activate); - // NOTE: This is a really critical function as it gets - // called between every draw call to update the constants. - // - // Alot of the calls here are inlined... be careful - // what you change. - - // If the buffer has changed we need to compare it - // with the new buffer to see if we can skip copying - // equal buffer content. - // - // If the buffer hasn't changed then we only will - // be copying the changes that have occured since - // the last activate call. - if ( prevShaderBuffer != this ) - { - // If the previous buffer is dirty, than we can't compare - // against it, because it hasn't sent its contents to the - // card yet and must be copied. - if ( prevShaderBuffer && !prevShaderBuffer->isDirty() ) - { - PROFILE_SCOPE(GFXD3D11ShaderConstBuffer_activate_dirty_check_1); - // If the buffer content is equal then we set the dirty - // flag to false knowing the current state of the card matches - // the new buffer. - // - // If the content is not equal we set the dirty flag to - // true which causes the full content of the buffer to be - // copied to the card. - // - mVertexConstBuffer->setDirty( !prevShaderBuffer->mVertexConstBuffer->isEqual( mVertexConstBuffer ) ); - mPixelConstBuffer->setDirty( !prevShaderBuffer->mPixelConstBuffer->isEqual( mPixelConstBuffer ) ); - } - else - { - // This happens rarely... but it can happen. - // We copy the entire dirty state to the card. - PROFILE_SCOPE(GFXD3D11ShaderConstBuffer_activate_dirty_check_2); - - mVertexConstBuffer->setDirty( true ); - mPixelConstBuffer->setDirty( true ); - } - } - - D3D11_MAPPED_SUBRESOURCE pConstData; - ZeroMemory(&pConstData, sizeof(D3D11_MAPPED_SUBRESOURCE)); - - const U8* buf; - U32 nbBuffers = 0; - if(mVertexConstBuffer->isDirty()) - { - const Vector &subBuffers = mVertexConstBufferLayout->getSubBufferDesc(); - // TODO: This is not very effecient updating the whole lot, re-implement the dirty system to work with multiple constant buffers. - // TODO: Implement DX 11.1 UpdateSubresource1 which supports updating ranges with constant buffers - buf = mVertexConstBuffer->getEntireBuffer(); - for (U32 i = 0; i < subBuffers.size(); ++i) - { - const ConstSubBufferDesc &desc = subBuffers[i]; - mDeviceContext->UpdateSubresource(mConstantBuffersV[i], 0, NULL, buf + desc.start, desc.size, 0); - nbBuffers++; - } - - mDeviceContext->VSSetConstantBuffers(0, nbBuffers, mConstantBuffersV); - } - - nbBuffers = 0; - - if(mPixelConstBuffer->isDirty()) - { - const Vector &subBuffers = mPixelConstBufferLayout->getSubBufferDesc(); - // TODO: This is not very effecient updating the whole lot, re-implement the dirty system to work with multiple constant buffers. - // TODO: Implement DX 11.1 UpdateSubresource1 which supports updating ranges with constant buffers - buf = mPixelConstBuffer->getEntireBuffer(); - for (U32 i = 0; i < subBuffers.size(); ++i) - { - const ConstSubBufferDesc &desc = subBuffers[i]; - mDeviceContext->UpdateSubresource(mConstantBuffersP[i], 0, NULL, buf + desc.start, desc.size, 0); - nbBuffers++; - } - - mDeviceContext->PSSetConstantBuffers(0, nbBuffers, mConstantBuffersP); - } - - #ifdef TORQUE_DEBUG - // Make sure all the constants for this buffer were assigned. - if(mWasLost) - { - mVertexConstBuffer->assertUnassignedConstants( mShader->getVertexShaderFile().c_str() ); - mPixelConstBuffer->assertUnassignedConstants( mShader->getPixelShaderFile().c_str() ); - } - #endif - - // Clear the lost state. - mWasLost = false; } void GFXD3D11ShaderConstBuffer::onShaderReload( GFXD3D11Shader *shader ) { AssertFatal( shader == mShader, "GFXD3D11ShaderConstBuffer::onShaderReload is hosed!" ); - // release constant buffers - for (U32 i = 0; i < CBUFFER_MAX; ++i) - { - SAFE_RELEASE(mConstantBuffersP[i]); - SAFE_RELEASE(mConstantBuffersV[i]); - } - - SAFE_DELETE( mVertexConstBuffer ); - SAFE_DELETE( mPixelConstBuffer ); - - AssertFatal( mVertexConstBufferLayout == shader->mVertexConstBufferLayout, "GFXD3D11ShaderConstBuffer::onShaderReload is hosed!" ); - AssertFatal( mPixelConstBufferLayout == shader->mPixelConstBufferLayout, "GFXD3D11ShaderConstBuffer::onShaderReload is hosed!" ); - - mVertexConstBuffer = new GenericConstBuffer( mVertexConstBufferLayout ); - mPixelConstBuffer = new GenericConstBuffer( mPixelConstBufferLayout ); _createBuffers(); @@ -711,14 +299,14 @@ void GFXD3D11ShaderConstBuffer::onShaderReload( GFXD3D11Shader *shader ) //------------------------------------------------------------------------------ GFXD3D11Shader::GFXD3D11Shader() + :mConstBufferSize(0), + mConstBuffer(NULL) { VECTOR_SET_ASSOCIATION( mShaderConsts ); AssertFatal(D3D11DEVICE, "Invalid device for shader."); mVertShader = NULL; mPixShader = NULL; - mVertexConstBufferLayout = NULL; - mPixelConstBufferLayout = NULL; if( smD3DInclude == NULL ) smD3DInclude = new gfxD3D11Include; @@ -731,9 +319,7 @@ GFXD3D11Shader::~GFXD3D11Shader() for (HandleMap::Iterator i = mHandles.begin(); i != mHandles.end(); i++) delete i->value; - // delete const buffer layouts - SAFE_DELETE(mVertexConstBufferLayout); - SAFE_DELETE(mPixelConstBufferLayout); + delete[] mConstBuffer; // release shaders SAFE_RELEASE(mVertShader); @@ -769,62 +355,18 @@ bool GFXD3D11Shader::_init() memset(&d3dMacros[macroCount - 1], 0, sizeof(D3D_SHADER_MACRO)); - if ( !mVertexConstBufferLayout ) - mVertexConstBufferLayout = new GFXD3D11ConstBufferLayout(); - else - mVertexConstBufferLayout->clear(); - - if ( !mPixelConstBufferLayout ) - mPixelConstBufferLayout = new GFXD3D11ConstBufferLayout(); - else - mPixelConstBufferLayout->clear(); - - - mSamplerDescriptions.clear(); mShaderConsts.clear(); - String vertTarget = D3D11->getVertexShaderTarget(); - String pixTarget = D3D11->getPixelShaderTarget(); + for (HandleMap::Iterator iter = mHandles.begin(); iter != mHandles.end(); ++iter) + (iter->value)->setValid(false); + mValidHandles.clear(); - if ( !Con::getBoolVariable( "$shaders::forceLoadCSF", false ) ) - { - if (!mVertexFile.isEmpty() && !_compileShader( mVertexFile, vertTarget, d3dMacros, mVertexConstBufferLayout, mSamplerDescriptions ) ) - return false; + if (!mVertexFile.isEmpty() && !_compileShader( mVertexFile, SHADER_STAGE::VERTEX_SHADER, d3dMacros) ) + return false; - if (!mPixelFile.isEmpty() && !_compileShader( mPixelFile, pixTarget, d3dMacros, mPixelConstBufferLayout, mSamplerDescriptions ) ) - return false; + if (!mPixelFile.isEmpty() && !_compileShader( mPixelFile, SHADER_STAGE::PIXEL_SHADER, d3dMacros)) + return false; - } - else - { - if ( !_loadCompiledOutput( mVertexFile, vertTarget, mVertexConstBufferLayout, mSamplerDescriptions ) ) - { - if ( smLogErrors ) - Con::errorf( "GFXD3D11Shader::init - Unable to load precompiled vertex shader for '%s'.", mVertexFile.getFullPath().c_str() ); - - return false; - } - - if ( !_loadCompiledOutput( mPixelFile, pixTarget, mPixelConstBufferLayout, mSamplerDescriptions ) ) - { - if ( smLogErrors ) - Con::errorf( "GFXD3D11Shader::init - Unable to load precompiled pixel shader for '%s'.", mPixelFile.getFullPath().c_str() ); - - return false; - } - } - - // Existing handles are resored to an uninitialized state. - // Those that are found when parsing the layout parameters - // will then be re-initialized. - HandleMap::Iterator iter = mHandles.begin(); - for ( ; iter != mHandles.end(); iter++ ) - (iter->value)->clear(); - - _buildShaderConstantHandles(mVertexConstBufferLayout, true); - _buildShaderConstantHandles(mPixelConstBufferLayout, false); - - _buildSamplerShaderConstantHandles( mSamplerDescriptions ); _buildInstancingShaderConstantHandles(); // Notify any existing buffers that the buffer @@ -837,10 +379,8 @@ bool GFXD3D11Shader::_init() } bool GFXD3D11Shader::_compileShader( const Torque::Path &filePath, - const String& target, - const D3D_SHADER_MACRO *defines, - GenericConstBufferLayout* bufferLayout, - Vector &samplerDescriptions ) + SHADER_STAGE shaderStage, + const D3D_SHADER_MACRO *defines) { PROFILE_SCOPE( GFXD3D11Shader_CompileShader ); @@ -896,6 +436,28 @@ bool GFXD3D11Shader::_compileShader( const Torque::Path &filePath, s.read(bufSize, buffer); buffer[bufSize] = 0; + String target; + + switch (shaderStage) + { + case VERTEX_SHADER: + target = D3D11->getVertexShaderTarget(); + break; + case PIXEL_SHADER: + target = D3D11->getPixelShaderTarget(); + break; + case GEOMETRY_SHADER: + break; + case DOMAIN_SHADER: + break; + case HULL_SHADER: + break; + case COMPUTE_SHADER: + break; + default: + break; + } + res = D3DCompile(buffer, bufSize, realPath.getFullPath().c_str(), defines, smD3DInclude, "main", target, flags, 0, &code, &errorBuff); } @@ -971,14 +533,27 @@ bool GFXD3D11Shader::_compileShader( const Torque::Path &filePath, } SAFE_RELEASE(disassem); - } - + } #endif - - if (target.compare("ps_", 3) == 0) - res = D3D11DEVICE->CreatePixelShader(code->GetBufferPointer(), code->GetBufferSize(), NULL, &mPixShader); - else if (target.compare("vs_", 3) == 0) + switch (shaderStage) + { + case VERTEX_SHADER: res = D3D11DEVICE->CreateVertexShader(code->GetBufferPointer(), code->GetBufferSize(), NULL, &mVertShader); + break; + case PIXEL_SHADER: + res = D3D11DEVICE->CreatePixelShader(code->GetBufferPointer(), code->GetBufferSize(), NULL, &mPixShader); + break; + case GEOMETRY_SHADER: + break; + case DOMAIN_SHADER: + break; + case HULL_SHADER: + break; + case COMPUTE_SHADER: + break; + default: + break; + } if (FAILED(res)) { @@ -992,15 +567,7 @@ bool GFXD3D11Shader::_compileShader( const Torque::Path &filePath, } if(res == S_OK) - _getShaderConstants(reflectionTable, bufferLayout, samplerDescriptions); - -#ifdef TORQUE_ENABLE_CSF_GENERATION - - // Ok, we've got a valid shader and constants, let's write them all out. - if (!_saveCompiledOutput(filePath, code, bufferLayout) && smLogErrors) - Con::errorf( "GFXD3D11Shader::_compileShader - Unable to save shader compile output for: %s", - filePath.getFullPath().c_str()); -#endif + _getShaderConstants(reflectionTable, shaderStage); if(FAILED(res) && smLogErrors) Con::errorf("GFXD3D11Shader::_compileShader - Unable to create shader for '%s'.", filePath.getFullPath().c_str()); @@ -1010,15 +577,28 @@ bool GFXD3D11Shader::_compileShader( const Torque::Path &filePath, bool result = code && SUCCEEDED(res); #ifdef TORQUE_DEBUG - if (target.compare("vs_", 3) == 0) + + String shader; + switch (shaderStage) { - String vertShader = mVertexFile.getFileName(); - mVertShader->SetPrivateData(WKPDID_D3DDebugObjectName, vertShader.size(), vertShader.c_str()); - } - else if (target.compare("ps_", 3) == 0) - { - String pixelShader = mPixelFile.getFileName(); - mPixShader->SetPrivateData(WKPDID_D3DDebugObjectName, pixelShader.size(), pixelShader.c_str()); + case VERTEX_SHADER: + shader = mVertexFile.getFileName(); + mVertShader->SetPrivateData(WKPDID_D3DDebugObjectName, shader.size(), shader.c_str()); + break; + case PIXEL_SHADER: + shader = mPixelFile.getFileName(); + mPixShader->SetPrivateData(WKPDID_D3DDebugObjectName, shader.size(), shader.c_str()); + break; + case GEOMETRY_SHADER: + break; + case DOMAIN_SHADER: + break; + case HULL_SHADER: + break; + case COMPUTE_SHADER: + break; + default: + break; } #endif @@ -1029,384 +609,200 @@ bool GFXD3D11Shader::_compileShader( const Torque::Path &filePath, return result; } void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection *refTable, - GenericConstBufferLayout *bufferLayoutIn, - Vector &samplerDescriptions ) + SHADER_STAGE shaderStage) { PROFILE_SCOPE( GFXD3D11Shader_GetShaderConstants ); AssertFatal(refTable, "NULL constant table not allowed, is this an assembly shader?"); - GFXD3D11ConstBufferLayout *bufferLayout = (GFXD3D11ConstBufferLayout*)bufferLayoutIn; - Vector &subBuffers = bufferLayout->getSubBufferDesc(); - subBuffers.clear(); + D3D11_SHADER_DESC shaderDesc; + refTable->GetDesc(&shaderDesc); - D3D11_SHADER_DESC tableDesc; - HRESULT hr = refTable->GetDesc(&tableDesc); - if (FAILED(hr)) - { - AssertFatal(false, "Shader Reflection table unable to be created"); - } - - //offset for sub constant buffers - U32 bufferOffset = 0; - for (U32 i = 0; i < tableDesc.ConstantBuffers; i++) - { - ID3D11ShaderReflectionConstantBuffer* constantBuffer = refTable->GetConstantBufferByIndex(i); - D3D11_SHADER_BUFFER_DESC constantBufferDesc; - - if (constantBuffer->GetDesc(&constantBufferDesc) == S_OK) - { - - #ifdef TORQUE_DEBUG - AssertFatal(constantBufferDesc.Type == D3D_CT_CBUFFER, "Only scalar cbuffers supported for now."); - - if (String::compare(constantBufferDesc.Name, "$Globals") != 0 && String::compare(constantBufferDesc.Name, "$Params") != 0) - AssertFatal(false, "Only $Global and $Params cbuffer supported for now."); - #endif - #ifdef D3D11_DEBUG_SPEW - Con::printf("Constant Buffer Name: %s", constantBufferDesc.Name); - #endif - - for(U32 j =0; j< constantBufferDesc.Variables; j++) - { - GFXShaderConstDesc desc; - ID3D11ShaderReflectionVariable* variable = constantBuffer->GetVariableByIndex(j); - D3D11_SHADER_VARIABLE_DESC variableDesc; - D3D11_SHADER_TYPE_DESC variableTypeDesc; - - variable->GetDesc(&variableDesc); - - ID3D11ShaderReflectionType* variableType =variable->GetType(); - - variableType->GetDesc(&variableTypeDesc); - desc.name = String(variableDesc.Name); - // Prepend a "$" if it doesn't exist. Just to make things consistent. - if (desc.name.find("$") != 0) - desc.name = String::ToString("$%s", desc.name.c_str()); - - bool unusedVar = variableDesc.uFlags & D3D_SVF_USED ? false : true; - - if (variableTypeDesc.Elements == 0) - desc.arraySize = 1; - else - desc.arraySize = variableTypeDesc.Elements; - - #ifdef D3D11_DEBUG_SPEW - Con::printf("Variable Name %s:, offset: %d, size: %d, constantDesc.Elements: %d", desc.name.c_str(), variableDesc.StartOffset, variableDesc.Size, desc.arraySize); - #endif - if (_convertShaderVariable(variableTypeDesc, desc)) - { - //The HLSL compiler for 4.0 and above doesn't strip out unused registered constants. We'll have to do it manually - if (!unusedVar) - { - mShaderConsts.push_back(desc); - U32 alignBytes = getAlignmentValue(desc.constType); - U32 paramSize = variableDesc.Size; - bufferLayout->addParameter( desc.name, - desc.constType, - variableDesc.StartOffset + bufferOffset, - paramSize, - desc.arraySize, - alignBytes); - - } //unusedVar - } //_convertShaderVariable - } //constantBufferDesc.Variables - - // fill out our const sub buffer sizes etc - ConstSubBufferDesc subBufferDesc; - subBufferDesc.size = constantBufferDesc.Size; - subBufferDesc.start = bufferOffset; - subBuffers.push_back(subBufferDesc); - // increase our bufferOffset by the constant buffer size - bufferOffset += constantBufferDesc.Size; - - } - else - AssertFatal(false, "Unable to get shader constant description! (may need more elements of constantDesc"); - } - - // Set buffer size to the aligned size - bufferLayout->setSize(bufferOffset); - - - //get the sampler descriptions from the resource binding description - U32 resourceCount = tableDesc.BoundResources; - for (U32 i = 0; i < resourceCount; i++) + for (U32 i = 0; i < shaderDesc.BoundResources; i++) { GFXShaderConstDesc desc; - D3D11_SHADER_INPUT_BIND_DESC bindDesc; - refTable->GetResourceBindingDesc(i, &bindDesc); + D3D11_SHADER_INPUT_BIND_DESC shaderInputBind; + refTable->GetResourceBindingDesc(i, &shaderInputBind); - switch (bindDesc.Type) + if (shaderInputBind.Type == D3D_SIT_CBUFFER) + { + desc.name = String(shaderInputBind.Name); + if (desc.name.find("$") != 0) + desc.name = String::ToString("$%s", desc.name.c_str()); + desc.constType = GFXSCT_ConstBuffer; + desc.bindPoint = shaderInputBind.BindPoint; + desc.shaderStage = shaderStage; + ID3D11ShaderReflectionConstantBuffer* constantBuffer = refTable->GetConstantBufferByName(shaderInputBind.Name); + D3D11_SHADER_BUFFER_DESC constantBufferDesc; + + constantBuffer->GetDesc(&constantBufferDesc); + + // push back our const buffer as a descriptor, this also marks the start of a buffer. + desc.size = constantBufferDesc.Size; + mShaderConsts.push_back(desc); + + // now loop vars and add them to mShaderConsts. + for (U32 j = 0; j < constantBufferDesc.Variables; j++) + { + GFXShaderConstDesc varDesc; + ID3D11ShaderReflectionVariable* bufferVar = constantBuffer->GetVariableByIndex(j); + D3D11_SHADER_VARIABLE_DESC shaderVarDesc; + bufferVar->GetDesc(&shaderVarDesc); + + D3D11_SHADER_TYPE_DESC shaderTypeDesc; + bufferVar->GetType()->GetDesc(&shaderTypeDesc); + + varDesc.name = String(shaderVarDesc.Name); + if (varDesc.name.find("$") != 0) + varDesc.name = String::ToString("$%s", varDesc.name.c_str()); + + // set the bind point to the same as the const buffer. + varDesc.bindPoint = desc.bindPoint; + varDesc.offset = shaderVarDesc.StartOffset; + varDesc.arraySize = mMax(shaderTypeDesc.Elements, 1); + varDesc.shaderStage = shaderStage; + + if (shaderTypeDesc.Class == D3D_SVC_SCALAR || shaderTypeDesc.Class == D3D_SVC_VECTOR) + { + switch (shaderTypeDesc.Type) + { + case D3D_SVT_BOOL: + varDesc.constType = (GFXShaderConstType)((U32)GFXSCT_Bool + shaderTypeDesc.Columns - 1); + case D3D_SVT_FLOAT: + varDesc.constType = (GFXShaderConstType)((U32)GFXSCT_Float + shaderTypeDesc.Columns - 1); + case D3D_SVT_INT: + varDesc.constType = (GFXShaderConstType)((U32)GFXSCT_Int + shaderTypeDesc.Columns - 1); + case D3D_SVT_UINT: + varDesc.constType = (GFXShaderConstType)((U32)GFXSCT_UInt + shaderTypeDesc.Columns - 1); + default: + AssertFatal(false, "Unknown shader constant class enum"); + break; + } + } + else if (shaderTypeDesc.Class == D3D_SVC_MATRIX_COLUMNS || shaderTypeDesc.Class == D3D_SVC_MATRIX_ROWS) + { + if (shaderTypeDesc.Type != D3D_SVT_FLOAT) + { + AssertFatal(false, "Only Float matrices are supported for now."); + } + + switch (shaderTypeDesc.Rows) + { + case 3: + varDesc.constType = shaderTypeDesc.Columns == 4 ? GFXSCT_Float3x4 : GFXSCT_Float3x3; + break; + case 4: + varDesc.constType = shaderTypeDesc.Columns == 3 ? GFXSCT_Float3x3 : GFXSCT_Float4x4; + break; + } + } + else if (shaderTypeDesc.Class == D3D_SVC_STRUCT) + { + // we gotta loop through its variables =/ + continue; + } + + mShaderConsts.push_back(varDesc); + } + } + else if (shaderInputBind.Type == D3D_SIT_TEXTURE) + { + switch (shaderInputBind.Dimension) + { + case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_TEXTURE1D: + break; + case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_TEXTURE1DARRAY: + break; + case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_TEXTURE2D: + break; + case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_TEXTURE2DARRAY: + break; + case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_TEXTURE2DMS: + break; + case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_TEXTURE2DMSARRAY: + break; + case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_TEXTURE3D: + break; + case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_TEXTURECUBE: + break; + case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_TEXTURECUBEARRAY: + break; + case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_BUFFER: + break; + case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_BUFFEREX: + break; + default: + break; + } + } + else if (shaderInputBind.Type == D3D_SIT_SAMPLER) { - case D3D_SIT_SAMPLER: // Prepend a "$" if it doesn't exist. Just to make things consistent. - desc.name = String(bindDesc.Name); + desc.name = String(shaderInputBind.Name); if (desc.name.find("$") != 0) desc.name = String::ToString("$%s", desc.name.c_str()); desc.constType = GFXSCT_Sampler; - desc.arraySize = bindDesc.BindPoint; - samplerDescriptions.push_back(desc); - break; - + desc.bindPoint = shaderInputBind.BindPoint; + desc.shaderStage = shaderStage; + mShaderConsts.push_back(desc); } - } - -} - -bool GFXD3D11Shader::_convertShaderVariable(const D3D11_SHADER_TYPE_DESC &typeDesc, GFXShaderConstDesc &desc) -{ - switch (typeDesc.Type) - { - case D3D_SVT_INT: - { - switch (typeDesc.Class) + else if (shaderInputBind.Type == D3D_SIT_UAV_RWTYPED) { - case D3D_SVC_SCALAR: - desc.constType = GFXSCT_Int; - break; - case D3D_SVC_VECTOR: - { - switch (typeDesc.Columns) + switch (shaderInputBind.Dimension) { - case 1: - desc.constType = GFXSCT_Int; + case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_TEXTURE1D: break; - case 2: - desc.constType = GFXSCT_Int2; + case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_TEXTURE1DARRAY: break; - case 3: - desc.constType = GFXSCT_Int3; + case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_TEXTURE2D: break; - case 4: - desc.constType = GFXSCT_Int4; + case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_TEXTURE2DARRAY: + break; + case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_TEXTURE2DMS: + break; + case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_TEXTURE2DMSARRAY: + break; + case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_TEXTURE3D: + break; + case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_TEXTURECUBE: + break; + case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_TEXTURECUBEARRAY: + break; + case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_BUFFER: + break; + case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_BUFFEREX: + break; + default: break; } } - break; - } - break; - } - case D3D_SVT_FLOAT: - { - switch (typeDesc.Class) + else if (shaderInputBind.Type == D3D_SIT_STRUCTURED) { - case D3D_SVC_SCALAR: - desc.constType = GFXSCT_Float; - break; - case D3D_SVC_VECTOR: - { - switch (typeDesc.Columns) - { - case 1: - desc.constType = GFXSCT_Float; - break; - case 2: - desc.constType = GFXSCT_Float2; - break; - case 3: - desc.constType = GFXSCT_Float3; - break; - case 4: - desc.constType = GFXSCT_Float4; - break; - } } - break; - case D3D_SVC_MATRIX_ROWS: - case D3D_SVC_MATRIX_COLUMNS: + else if (shaderInputBind.Type == D3D_SIT_UAV_RWSTRUCTURED) { - switch (typeDesc.Rows) - { - case 3: - desc.constType = typeDesc.Columns == 4 ? GFXSCT_Float3x4 : GFXSCT_Float3x3; - break; - case 4: - desc.constType = typeDesc.Columns == 3 ? GFXSCT_Float4x3 : GFXSCT_Float4x4; - break; - } } - break; - case D3D_SVC_OBJECT: - case D3D_SVC_STRUCT: - return false; + else if (shaderInputBind.Type == D3D_SIT_BYTEADDRESS) + { + } + else if (shaderInputBind.Type == D3D_SIT_UAV_RWBYTEADDRESS) + { + } + else if (shaderInputBind.Type == D3D_SIT_UAV_APPEND_STRUCTURED) + { + } + else if (shaderInputBind.Type == D3D_SIT_UAV_CONSUME_STRUCTURED) + { + } + else if (shaderInputBind.Type == D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER) + { } } - break; - - default: - AssertFatal(false, "Unknown shader constant class enum"); - break; - } - - return true; } -const U32 GFXD3D11Shader::smCompiledShaderTag = MakeFourCC('t','c','s','f'); - -bool GFXD3D11Shader::_saveCompiledOutput( const Torque::Path &filePath, - ID3DBlob *buffer, - GenericConstBufferLayout *bufferLayout, - Vector &samplerDescriptions ) +void GFXD3D11Shader::_buildShaderConstantHandles() { - Torque::Path outputPath(filePath); - outputPath.setExtension("csf"); // "C"ompiled "S"hader "F"ile (fancy!) - FileStream f; - if (!f.open(outputPath, Torque::FS::File::Write)) - return false; - if (!f.write(smCompiledShaderTag)) - return false; - // We could reverse engineer the structure in the compiled output, but this - // is a bit easier because we can just read it into the struct that we want. - if (!bufferLayout->write(&f)) - return false; - - U32 bufferSize = buffer->GetBufferSize(); - if (!f.write(bufferSize)) - return false; - if (!f.write(bufferSize, buffer->GetBufferPointer())) - return false; - - // Write out sampler descriptions. - - f.write( samplerDescriptions.size() ); - - for ( U32 i = 0; i < samplerDescriptions.size(); i++ ) - { - f.write( samplerDescriptions[i].name ); - f.write( (U32)(samplerDescriptions[i].constType) ); - f.write( samplerDescriptions[i].arraySize ); - } - - f.close(); - - return true; -} - -bool GFXD3D11Shader::_loadCompiledOutput( const Torque::Path &filePath, - const String &target, - GenericConstBufferLayout *bufferLayout, - Vector &samplerDescriptions ) -{ - Torque::Path outputPath(filePath); - outputPath.setExtension("csf"); // "C"ompiled "S"hader "F"ile (fancy!) - - FileStream f; - if (!f.open(outputPath, Torque::FS::File::Read)) - return false; - U32 fileTag; - if (!f.read(&fileTag)) - return false; - if (fileTag != smCompiledShaderTag) - return false; - if (!bufferLayout->read(&f)) - return false; - U32 bufferSize; - if (!f.read(&bufferSize)) - return false; - U32 waterMark = FrameAllocator::getWaterMark(); - DWORD* buffer = static_cast(FrameAllocator::alloc(bufferSize)); - if (!f.read(bufferSize, buffer)) - return false; - - // Read sampler descriptions. - - U32 samplerCount; - f.read( &samplerCount ); - - for ( U32 i = 0; i < samplerCount; i++ ) - { - GFXShaderConstDesc samplerDesc; - f.read( &(samplerDesc.name) ); - f.read( (U32*)&(samplerDesc.constType) ); - f.read( &(samplerDesc.arraySize) ); - - samplerDescriptions.push_back( samplerDesc ); - } - - f.close(); - - HRESULT res; - if (target.compare("ps_", 3) == 0) - res = D3D11DEVICE->CreatePixelShader(buffer, bufferSize, NULL, &mPixShader); - else - res = D3D11DEVICE->CreateVertexShader(buffer, bufferSize, NULL, &mVertShader); - AssertFatal(SUCCEEDED(res), "Unable to load shader!"); - - FrameAllocator::setWaterMark(waterMark); - return SUCCEEDED(res); -} - -void GFXD3D11Shader::_buildShaderConstantHandles(GenericConstBufferLayout* layout, bool vertexConst) -{ - for (U32 i = 0; i < layout->getParameterCount(); i++) - { - GenericConstBufferLayout::ParamDesc pd; - layout->getDesc(i, pd); - - GFXD3D11ShaderConstHandle* handle; - HandleMap::Iterator j = mHandles.find(pd.name); - - if (j != mHandles.end()) - { - handle = j->value; - handle->mShader = this; - handle->setValid( true ); - } - else - { - handle = new GFXD3D11ShaderConstHandle(); - handle->mShader = this; - mHandles[pd.name] = handle; - handle->setValid( true ); - } - - if (vertexConst) - { - handle->mVertexConstant = true; - handle->mVertexHandle = pd; - } - else - { - handle->mPixelConstant = true; - handle->mPixelHandle = pd; - } - } -} - -void GFXD3D11Shader::_buildSamplerShaderConstantHandles( Vector &samplerDescriptions ) -{ - Vector::iterator iter = samplerDescriptions.begin(); - for ( ; iter != samplerDescriptions.end(); iter++ ) - { - const GFXShaderConstDesc &desc = *iter; - - AssertFatal( desc.constType == GFXSCT_Sampler || - desc.constType == GFXSCT_SamplerCube || - desc.constType == GFXSCT_SamplerCubeArray || - desc.constType == GFXSCT_SamplerTextureArray, - "GFXD3D11Shader::_buildSamplerShaderConstantHandles - Invalid samplerDescription type!" ); - - GFXD3D11ShaderConstHandle *handle; - HandleMap::Iterator j = mHandles.find(desc.name); - - if ( j != mHandles.end() ) - handle = j->value; - else - { - handle = new GFXD3D11ShaderConstHandle(); - mHandles[desc.name] = handle; - } - - handle->mShader = this; - handle->setValid( true ); - handle->mPixelConstant = true; - handle->mPixelHandle.name = desc.name; - handle->mPixelHandle.constType = desc.constType; - handle->mPixelHandle.offset = desc.arraySize; - } } void GFXD3D11Shader::_buildInstancingShaderConstantHandles() @@ -1437,21 +833,6 @@ void GFXD3D11Shader::_buildInstancingShaderConstantHandles() handle->setValid( true ); handle->mInstancingConstant = true; - // We shouldn't have an instancing constant that is also - // a vertex or pixel constant! This means the shader features - // are confused as to what is instanced. - // - AssertFatal( !handle->mVertexConstant && - !handle->mPixelConstant, - "GFXD3D11Shader::_buildInstancingShaderConstantHandles - Bad instanced constant!" ); - - // HACK: The GFXD3D11ShaderConstHandle will check mVertexConstant then - // fall back to reading the mPixelHandle values. We depend on this here - // and store the data we need in the mPixelHandle constant although its - // not a pixel shader constant. - // - handle->mPixelHandle.name = constName; - handle->mPixelHandle.offset = offset; // If this is a matrix we will have 2 or 3 more of these // semantics with the same name after it. @@ -1470,15 +851,10 @@ void GFXD3D11Shader::_buildInstancingShaderConstantHandles() GFXShaderConstBufferRef GFXD3D11Shader::allocConstBuffer() { - if (mVertexConstBufferLayout && mPixelConstBufferLayout) - { - GFXD3D11ShaderConstBuffer* buffer = new GFXD3D11ShaderConstBuffer(this, mVertexConstBufferLayout, mPixelConstBufferLayout); - mActiveBuffers.push_back( buffer ); - buffer->registerResourceWithDevice(getOwningDevice()); - return buffer; - } - - return NULL; + GFXD3D11ShaderConstBuffer* buffer = new GFXD3D11ShaderConstBuffer(this, mConstBufferSize, mConstBuffer); + mActiveBuffers.push_back( buffer ); + buffer->registerResourceWithDevice(getOwningDevice()); + return buffer; } /// Returns a shader constant handle for name, if the variable doesn't exist NULL is returned. diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.h b/Engine/source/gfx/D3D11/gfxD3D11Shader.h index 8ae17a979..4de965dc8 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.h +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.h @@ -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 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(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(ptr+2); - size_t ctab_size = (comment_size-1)*4; - - const CTHeader* header = reinterpret_cast(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(ctab + header->ConstantInfo); - for(U32 i = 0; i < header->Constants; ++i) - { - const CTType* type = reinterpret_cast(ctab + info[i].TypeInfo); - - // Fill struct - ConstantDesc desc; - desc.Name = ctab + info[i].Name; - desc.RegisterSet = static_cast(info[i].RegisterSet); - desc.RegisterIndex = info[i].RegisterIndex; - desc.RegisterCount = info[i].RegisterCount; - desc.Rows = type->Rows; - desc.Class = static_cast(type->Class); - desc.Type = static_cast(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::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 &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 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 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 - 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 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 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 mSamplerDescriptions; - /// Vector of descriptions (consolidated for the getShaderConstDesc call) Vector 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 &samplerDescriptions ); + SHADER_STAGE shaderStage, + const D3D_SHADER_MACRO *defines); - void _getShaderConstants( ID3D11ShaderReflection* refTable, - GenericConstBufferLayout *bufferLayout, - Vector &samplerDescriptions ); - - bool _convertShaderVariable(const D3D11_SHADER_TYPE_DESC &typeDesc, GFXShaderConstDesc &desc); - - - bool _saveCompiledOutput( const Torque::Path &filePath, - ID3DBlob *buffer, - GenericConstBufferLayout *bufferLayout, - Vector &samplerDescriptions ); - - // Loads precompiled shaders - bool _loadCompiledOutput( const Torque::Path &filePath, - const String &target, - GenericConstBufferLayout *bufferLayoutF, - Vector &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 &samplerDescriptions ); + virtual void _buildShaderConstantHandles(); /// Used to build the instancing shader constants from /// the instancing vertex format. diff --git a/Engine/source/gfx/gfxEnums.h b/Engine/source/gfx/gfxEnums.h index 7a0572d40..83e0bfccb 100644 --- a/Engine/source/gfx/gfxEnums.h +++ b/Engine/source/gfx/gfxEnums.h @@ -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, diff --git a/Engine/source/gfx/gfxShader.h b/Engine/source/gfx/gfxShader.h index 473412728..8901c9332 100644 --- a/Engine/source/gfx/gfxShader.h +++ b/Engine/source/gfx/gfxShader.h @@ -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. From 630bee97c7b97b48133df2d17bb2b68ca723fd40 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Thu, 22 Feb 2024 21:37:44 +0000 Subject: [PATCH 05/53] backup --- Engine/source/gfx/D3D11/gfxD3D11Shader.cpp | 128 +++++++++------------ Engine/source/gfx/D3D11/gfxD3D11Shader.h | 22 ++-- Engine/source/gfx/gl/gfxGLShader.cpp | 5 +- 3 files changed, 75 insertions(+), 80 deletions(-) diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp index 555ec9d98..e08c4f057 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp @@ -94,29 +94,46 @@ HRESULT gfxD3D11Include::Close( THIS_ LPCVOID pData ) } GFXD3D11ShaderConstHandle::GFXD3D11ShaderConstHandle(GFXD3D11Shader* shader) + : mShader(shader), + mOffset(0), + mSize(0), + mBinding(-1), + mSampler(-1), + mInstancingConstant(false) { + dMemset(&mDesc, 0, sizeof(mDesc)); + mValid = false; + mStage = SHADER_STAGE::UNKNOWN_STAGE; } -GFXD3D11ShaderConstHandle::GFXD3D11ShaderConstHandle(GFXD3D11Shader* shader, const GFXShaderConstDesc& desc, S32 samplerNum) +GFXD3D11ShaderConstHandle::GFXD3D11ShaderConstHandle(GFXD3D11Shader* shader, + const SHADER_STAGE shaderStage, + const U32 offset, + const U32 size, + const GFXShaderConstDesc& desc, + S32 bindingPoint, + S32 samplerNum) + : mShader(shader), + mStage(shaderStage), + mOffset(offset), + mSize(size), + mDesc(desc), + mBinding(bindingPoint), + mSampler(bindingPoint), + mInstancingConstant(false) { + mValid = false; } GFXD3D11ShaderConstHandle::~GFXD3D11ShaderConstHandle() { } -U32 GFXD3D11ShaderConstHandle::getSize() const -{ - return U32(); -} - -GFXD3D11ShaderConstHandle::GFXD3D11ShaderConstHandle() -{ -} - //------------------------------------------------------------------------------ + GFXD3D11ShaderConstBuffer::GFXD3D11ShaderConstBuffer( GFXD3D11Shader* shader, U32 bufSize, U8* existingConstants) { + mDeviceContext = D3D11DEVICECONTEXT; } GFXD3D11ShaderConstBuffer::~GFXD3D11ShaderConstBuffer() @@ -367,7 +384,7 @@ bool GFXD3D11Shader::_init() if (!mPixelFile.isEmpty() && !_compileShader( mPixelFile, SHADER_STAGE::PIXEL_SHADER, d3dMacros)) return false; - _buildInstancingShaderConstantHandles(); + _buildShaderConstantHandles(); // Notify any existing buffers that the buffer // layouts have changed and they need to update. @@ -459,35 +476,8 @@ bool GFXD3D11Shader::_compileShader( const Torque::Path &filePath, } res = D3DCompile(buffer, bufSize, realPath.getFullPath().c_str(), defines, smD3DInclude, "main", target, flags, 0, &code, &errorBuff); - } - // Is it a precompiled obj shader? - else if(filePath.getExtension().equal("obj", String::NoCase)) - { - FileStream s; - if(!s.open(filePath, Torque::FS::File::Read)) - { - AssertISV(false, avar("GFXD3D11Shader::initShader - failed to open shader '%s'.", filePath.getFullPath().c_str())); - - if ( smLogErrors ) - Con::errorf( "GFXD3D11Shader::_compileShader - Failed to open shader file '%s'.", filePath.getFullPath().c_str() ); - - return false; - } - - res = D3DCreateBlob(s.getStreamSize(), &code); - AssertISV(SUCCEEDED(res), "Unable to create buffer!"); - s.read(s.getStreamSize(), code->GetBufferPointer()); - } - else - { - if (smLogErrors) - Con::errorf("GFXD3D11Shader::_compileShader - Unsupported shader file type '%s'.", filePath.getFullPath().c_str()); - - return false; - } - if(errorBuff) { // remove \n at end of buffer @@ -608,6 +598,7 @@ bool GFXD3D11Shader::_compileShader( const Torque::Path &filePath, return result; } + void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection *refTable, SHADER_STAGE shaderStage) { @@ -618,6 +609,7 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection *refTable, D3D11_SHADER_DESC shaderDesc; refTable->GetDesc(&shaderDesc); + // we loop through and account for the most common data types. for (U32 i = 0; i < shaderDesc.BoundResources; i++) { GFXShaderConstDesc desc; @@ -629,6 +621,7 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection *refTable, desc.name = String(shaderInputBind.Name); if (desc.name.find("$") != 0) desc.name = String::ToString("$%s", desc.name.c_str()); + desc.constType = GFXSCT_ConstBuffer; desc.bindPoint = shaderInputBind.BindPoint; desc.shaderStage = shaderStage; @@ -660,6 +653,7 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection *refTable, varDesc.bindPoint = desc.bindPoint; varDesc.offset = shaderVarDesc.StartOffset; varDesc.arraySize = mMax(shaderTypeDesc.Elements, 1); + varDesc.size = shaderVarDesc.Size; varDesc.shaderStage = shaderStage; if (shaderTypeDesc.Class == D3D_SVC_SCALAR || shaderTypeDesc.Class == D3D_SVC_VECTOR) @@ -668,14 +662,18 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection *refTable, { case D3D_SVT_BOOL: varDesc.constType = (GFXShaderConstType)((U32)GFXSCT_Bool + shaderTypeDesc.Columns - 1); - case D3D_SVT_FLOAT: - varDesc.constType = (GFXShaderConstType)((U32)GFXSCT_Float + shaderTypeDesc.Columns - 1); + break; case D3D_SVT_INT: varDesc.constType = (GFXShaderConstType)((U32)GFXSCT_Int + shaderTypeDesc.Columns - 1); + break; + case D3D_SVT_FLOAT: + varDesc.constType = (GFXShaderConstType)((U32)GFXSCT_Float + shaderTypeDesc.Columns - 1); + break; case D3D_SVT_UINT: varDesc.constType = (GFXShaderConstType)((U32)GFXSCT_UInt + shaderTypeDesc.Columns - 1); + break; default: - AssertFatal(false, "Unknown shader constant class enum"); + AssertFatal(false, "Unknown shader constant class enum, maybe you could add it?"); break; } } @@ -683,7 +681,7 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection *refTable, { if (shaderTypeDesc.Type != D3D_SVT_FLOAT) { - AssertFatal(false, "Only Float matrices are supported for now."); + AssertFatal(false, "Only Float matrices are supported for now. Support for other types needs to be added."); } switch (shaderTypeDesc.Rows) @@ -698,7 +696,7 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection *refTable, } else if (shaderTypeDesc.Class == D3D_SVC_STRUCT) { - // we gotta loop through its variables =/ + // we gotta loop through its variables =/ ad support in future. for now continue so it skips. continue; } @@ -707,7 +705,7 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection *refTable, } else if (shaderInputBind.Type == D3D_SIT_TEXTURE) { - switch (shaderInputBind.Dimension) + /*switch (shaderInputBind.Dimension) { case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_TEXTURE1D: break; @@ -733,7 +731,7 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection *refTable, break; default: break; - } + }*/ } else if (shaderInputBind.Type == D3D_SIT_SAMPLER) { @@ -746,9 +744,15 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection *refTable, desc.shaderStage = shaderStage; mShaderConsts.push_back(desc); } - else if (shaderInputBind.Type == D3D_SIT_UAV_RWTYPED) + else if (shaderInputBind.Type == D3D_SIT_UAV_RWTYPED || + shaderInputBind.Type == D3D_SIT_UAV_RWSTRUCTURED || + shaderInputBind.Type == D3D_SIT_UAV_RWBYTEADDRESS || + shaderInputBind.Type == D3D_SIT_UAV_APPEND_STRUCTURED || + shaderInputBind.Type == D3D_SIT_UAV_CONSUME_STRUCTURED || + shaderInputBind.Type == D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER) { - switch (shaderInputBind.Dimension) + // these should return an unorderedAccessViews and add them to shaderResources. + /*switch (shaderInputBind.Dimension) { case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_TEXTURE1D: break; @@ -774,28 +778,12 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection *refTable, break; default: break; - } + }*/ } - else if (shaderInputBind.Type == D3D_SIT_STRUCTURED) - { - } - else if (shaderInputBind.Type == D3D_SIT_UAV_RWSTRUCTURED) - { - } - else if (shaderInputBind.Type == D3D_SIT_BYTEADDRESS) - { - } - else if (shaderInputBind.Type == D3D_SIT_UAV_RWBYTEADDRESS) - { - } - else if (shaderInputBind.Type == D3D_SIT_UAV_APPEND_STRUCTURED) - { - } - else if (shaderInputBind.Type == D3D_SIT_UAV_CONSUME_STRUCTURED) - { - } - else if (shaderInputBind.Type == D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER) + else if (shaderInputBind.Type == D3D_SIT_STRUCTURED || + shaderInputBind.Type == D3D_SIT_BYTEADDRESS) { + // these should return shaderResourceViews and add them to shaderResources. } } } @@ -825,11 +813,10 @@ void GFXD3D11Shader::_buildInstancingShaderConstantHandles() handle = j->value; else { - handle = new GFXD3D11ShaderConstHandle(); + handle = new GFXD3D11ShaderConstHandle(this); mHandles[ constName ] = handle; } - handle->mShader = this; handle->setValid( true ); handle->mInstancingConstant = true; @@ -867,9 +854,8 @@ GFXShaderConstHandle* GFXD3D11Shader::getShaderConstHandle(const String& name) } else { - GFXD3D11ShaderConstHandle *handle = new GFXD3D11ShaderConstHandle(); + GFXD3D11ShaderConstHandle *handle = new GFXD3D11ShaderConstHandle(this); handle->setValid( false ); - handle->mShader = this; mHandles[name] = handle; return handle; diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.h b/Engine/source/gfx/D3D11/gfxD3D11Shader.h index 4de965dc8..7dea06f6c 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.h +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.h @@ -36,6 +36,7 @@ class GFXD3D11Shader; enum SHADER_STAGE { + UNKNOWN_STAGE, VERTEX_SHADER, PIXEL_SHADER, GEOMETRY_SHADER, @@ -47,21 +48,28 @@ enum SHADER_STAGE class GFXD3D11ShaderConstHandle : public GFXShaderConstHandle { friend class GFXD3D11Shader; -public: +public: GFXD3D11ShaderConstHandle(GFXD3D11Shader* shader); - GFXD3D11ShaderConstHandle(GFXD3D11Shader* shader, const GFXShaderConstDesc& desc, S32 samplerNum); + GFXD3D11ShaderConstHandle(GFXD3D11Shader* shader, + const SHADER_STAGE shaderStage, + const U32 offset, + const U32 size, + const GFXShaderConstDesc& desc, + S32 bindingPoint, + S32 samplerNum); + virtual ~GFXD3D11ShaderConstHandle(); const String& getName() const { return mDesc.name; } GFXShaderConstType getType() const { return mDesc.constType; } U32 getArraySize() const { return mDesc.arraySize; } - U32 getSize() const; + U32 getSize() const { return mSize; } 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; } + S32 getSamplerRegister() const { return mSampler; } // Returns true if this is a handle to a sampler register. bool isSampler() const @@ -69,13 +77,13 @@ public: return (getType() >= GFXSCT_Sampler); } - GFXD3D11ShaderConstHandle(); GFXShaderConstDesc mDesc; GFXD3D11Shader* mShader; U32 mOffset; U32 mSize; - S32 mSamplerNum; - SHADER_STAGE stage; + S32 mBinding; // buffer binding point used to map handles to buffers. + S32 mSampler; // sampler. + SHADER_STAGE mStage; bool mInstancingConstant; }; diff --git a/Engine/source/gfx/gl/gfxGLShader.cpp b/Engine/source/gfx/gl/gfxGLShader.cpp index c8366ed56..2dc047e2b 100644 --- a/Engine/source/gfx/gl/gfxGLShader.cpp +++ b/Engine/source/gfx/gl/gfxGLShader.cpp @@ -59,9 +59,9 @@ public: GFXShaderConstDesc mDesc; GFXGLShader* mShader; - GLuint mLocation; U32 mOffset; - U32 mSize; + U32 mSize; + GLuint mLocation; S32 mSamplerNum; bool mInstancingConstant; }; @@ -799,6 +799,7 @@ GFXShaderConstHandle* GFXGLShader::getShaderConstHandle(const String& name) else { GFXGLShaderConstHandle* handle = new GFXGLShaderConstHandle( this ); + handle->setValid(false); mHandles[ name ] = handle; return handle; From 97ed5226675ffba95632e427174ba0abd2919464 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Fri, 23 Feb 2024 17:18:45 +0000 Subject: [PATCH 06/53] gfxD3D handles and buffermap init handles coded. bufferMap added. --- Engine/source/gfx/D3D11/gfxD3D11Shader.cpp | 224 ++++++++++++++++----- Engine/source/gfx/D3D11/gfxD3D11Shader.h | 55 +++-- Engine/source/gfx/gfxShader.h | 11 +- 3 files changed, 213 insertions(+), 77 deletions(-) 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. From a1e2f781a88360250745b90c185bd59fa0a3eac9 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Fri, 23 Feb 2024 20:06:46 +0000 Subject: [PATCH 07/53] 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, From 4caa54ad7e51b8a8f64c0a26884650db71fb306c Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Fri, 23 Feb 2024 21:27:44 +0000 Subject: [PATCH 08/53] working example everything is working apart from samplers...... --- Engine/source/gfx/D3D11/gfxD3D11Shader.cpp | 75 +++++++++------------- Engine/source/gfx/D3D11/gfxD3D11Shader.h | 37 +++-------- 2 files changed, 40 insertions(+), 72 deletions(-) diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp index 2db4e58b7..d5e5d400c 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp @@ -147,12 +147,16 @@ void GFXD3D11ShaderConstHandle::reinit(const GFXShaderConstDesc& desc) GFXD3D11ShaderConstBuffer::GFXD3D11ShaderConstBuffer( GFXD3D11Shader* shader) { + mShader = shader; mDeviceContext = D3D11DEVICECONTEXT; } GFXD3D11ShaderConstBuffer::~GFXD3D11ShaderConstBuffer() { - + for (BufferMap::Iterator i = mBufferMap.begin(); i != mBufferMap.end(); i++) + { + delete[] i->value; + } } GFXShader* GFXD3D11ShaderConstBuffer::getShader() @@ -230,7 +234,7 @@ void GFXD3D11ShaderConstBuffer::internalSet(GFXShaderConstHandle* handle, const 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); + BufferKey bufDesc(_dxHandle->mBinding, (SHADER_STAGE)_dxHandle->mStage); U8* buf = mBufferMap[bufDesc] + _dxHandle->mOffset; if (_dxHandle->mInstancingConstant) @@ -288,8 +292,8 @@ void GFXD3D11ShaderConstBuffer::internalSet(GFXShaderConstHandle* handle, const 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); + AssertFatal(!_dxHandle->mInstancingConstant, "GFXD3D11ShaderConstBuffer::internalSet - Instancing not supported for array"); + BufferKey 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) @@ -309,7 +313,7 @@ void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF& 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); + BufferKey bufDesc(_dxHandle->mBinding, (SHADER_STAGE)_dxHandle->mStage); U8* buf = mBufferMap[bufDesc] + _dxHandle->mOffset; MatrixF transposed; @@ -368,7 +372,7 @@ void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF* AssertFatal(!_dxHandle->isSampler(), "Handle is sampler constant!"); AssertFatal(_dxHandle->mShader == mShader, "Mismatched shaders!"); - BufferDesc bufDesc(_dxHandle->mBinding, (SHADER_STAGE)_dxHandle->mStage); + BufferKey bufDesc(_dxHandle->mBinding, (SHADER_STAGE)_dxHandle->mStage); U8* buf = mBufferMap[bufDesc] ; @@ -434,15 +438,16 @@ bool GFXD3D11ShaderConstBuffer::isDirty() return true; } -void GFXD3D11ShaderConstBuffer::addBuffer(BufferDesc bufDesc, U32 size) +void GFXD3D11ShaderConstBuffer::addBuffer(U32 bufBindingPoint, SHADER_STAGE shaderStage, U32 size) { - BufferMap::Iterator buffer = mBufferMap.find(bufDesc); + BufferKey bufKey(bufBindingPoint, shaderStage); + BufferMap::Iterator buffer = mBufferMap.find(bufKey); // already added? pass... if (buffer != mBufferMap.end()) return; // new buffer with our size. - mBufferMap[bufDesc] = new U8[size]; + mBufferMap[bufKey] = new U8[size]; } void GFXD3D11ShaderConstBuffer::activate( GFXD3D11ShaderConstBuffer *prevShaderBuffer ) @@ -472,6 +477,11 @@ GFXD3D11Shader::GFXD3D11Shader() if( smD3DInclude == NULL ) smD3DInclude = new gfxD3D11Include; + + for (U32 i = 0; i < 16; i++) + { + mBoundConstantBuffers[i] = NULL; + } } //------------------------------------------------------------------------------ @@ -652,28 +662,6 @@ bool GFXD3D11Shader::_compileShader( const Torque::Path &filePath, if(code != NULL) { -#ifndef TORQUE_SHIPPING - - if(gDisassembleAllShaders) - { - ID3DBlob* disassem = NULL; - D3DDisassemble(code->GetBufferPointer(), code->GetBufferSize(), 0, NULL, &disassem); - mDissasembly = (const char*)disassem->GetBufferPointer(); - - String filename = filePath.getFullPath(); - filename.replace( ".hlsl", "_dis.txt" ); - - FileStream *fstream = FileStream::createAndOpen( filename, Torque::FS::File::Write ); - if ( fstream ) - { - fstream->write( mDissasembly ); - fstream->close(); - delete fstream; - } - - SAFE_RELEASE(disassem); - } -#endif switch (shaderStage) { case VERTEX_SHADER: @@ -892,7 +880,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.bindPoint = -1; desc.shaderStage = shaderStage; mShaderConsts.push_back(desc); } @@ -946,7 +934,6 @@ void GFXD3D11Shader::_buildShaderConstantHandles() // 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. @@ -956,8 +943,10 @@ void GFXD3D11Shader::_buildShaderConstantHandles() if (desc.constType == GFXSCT_ConstBuffer) { - BufferDesc bufDesc(desc.bindPoint, (SHADER_STAGE)desc.shaderStage); - BufferMap::Iterator buffer = mBuffers.find(bufDesc); + BufferKey bufKey(desc.bindPoint, (SHADER_STAGE)desc.shaderStage); + + + BufferMap::Iterator buffer = mBuffers.find(bufKey); // already added? pass... if (buffer != mBuffers.end()) continue; @@ -976,13 +965,13 @@ void GFXD3D11Shader::_buildShaderConstantHandles() if (FAILED(hr)) { - AssertFatal(false, "can't create constant buffer: %s", desc.name.c_str()); + AssertFatal(false, "can't create constant buffer"); } mBoundConstantBuffers[desc.bindPoint] = constBuffer; // new buffer with our size. - mBuffers[bufDesc] = new U8[desc.size]; + mBuffers[bufKey] = new U8[desc.size]; // do not add to handles.. continue; @@ -1053,7 +1042,7 @@ void GFXD3D11Shader::setConstantsFromBuffer(GFXD3D11ShaderConstBuffer* buffer) for (BufferMap::Iterator i = mBuffers.begin(); i != mBuffers.end(); ++i) { - BufferDesc oldBufferDesc = i->key; + BufferKey oldBufferDesc = i->key; U8* oldBuff = i->value; U8* newBuff = buffer->mBufferMap[i->key]; @@ -1064,13 +1053,13 @@ void GFXD3D11Shader::setConstantsFromBuffer(GFXD3D11ShaderConstBuffer* buffer) dMemcpy(oldBuff, newBuff, sizeof(oldBuff)); // buffer has been changed and needs updating. - D3D11DEVICECONTEXT->UpdateSubresource(mBoundConstantBuffers[oldBufferDesc.bindingPoint], 0, NULL, oldBuff, sizeof(oldBuff), 0); + D3D11DEVICECONTEXT->UpdateSubresource(mBoundConstantBuffers[oldBufferDesc.key1], 0, NULL, oldBuff, sizeof(oldBuff), 0); } - bufRanges[oldBufferDesc.stage].addSlot(oldBufferDesc.bindingPoint); + bufRanges[oldBufferDesc.key2].addSlot(oldBufferDesc.key1); } - if (mVertShader != nullptr) + if (mVertShader != nullptr && bufRanges[SHADER_STAGE::VERTEX_SHADER].isValid()) { 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; @@ -1079,7 +1068,7 @@ void GFXD3D11Shader::setConstantsFromBuffer(GFXD3D11ShaderConstBuffer* buffer) D3D11DEVICECONTEXT->VSSetConstantBuffers(bufStartSlot, numBufs, vsBuffers); } - if (mPixShader != nullptr) + if (mPixShader != nullptr && bufRanges[SHADER_STAGE::PIXEL_SHADER].isValid()) { 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; @@ -1097,7 +1086,7 @@ GFXShaderConstBufferRef GFXD3D11Shader::allocConstBuffer() 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)); + buffer->addBuffer(i->key.key1,i->key.key2, sizeof(i->value)); } mActiveBuffers.push_back( buffer ); diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.h b/Engine/source/gfx/D3D11/gfxD3D11Shader.h index e5d54fa07..4cdf94870 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.h +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.h @@ -45,22 +45,8 @@ enum SHADER_STAGE UNKNOWN_STAGE }; -// 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) - {} - -}; +typedef CompoundKey BufferKey; struct BufferRange { @@ -72,6 +58,8 @@ struct BufferRange mBufMin = getMin(mBufMin, slot); mBufMax = getMax(mBufMax, slot); } + + inline bool isValid() const { return mBufMin <= mBufMax; } }; class GFXD3D11ShaderConstHandle : public GFXShaderConstHandle @@ -118,7 +106,7 @@ class GFXD3D11ShaderConstBuffer : public GFXShaderConstBuffer ID3D11DeviceContext* mDeviceContext; public: - typedef Map BufferMap; + typedef Map BufferMap; GFXD3D11ShaderConstBuffer(GFXD3D11Shader* shader); @@ -131,7 +119,7 @@ public: /// Used internally by GXD3D11ShaderConstBuffer to determine if it's dirty. bool isDirty(); - void addBuffer(BufferDesc bufDesc, U32 size); + void addBuffer(U32 bufBindingPoint, SHADER_STAGE shaderStage, U32 size); /// Called from GFXD3D11Shader when constants have changed and need /// to be the shader this buffer references is reloaded. @@ -191,7 +179,8 @@ class GFXD3D11Shader : public GFXShader public: typedef Map HandleMap; - typedef Map BufferMap; + + typedef Map BufferMap; GFXD3D11Shader(); virtual ~GFXD3D11Shader(); @@ -218,18 +207,13 @@ protected: ID3D11PixelShader *mPixShader; // we probably want this to be GFXDevice and not per shader. - ID3D11Buffer* mBoundConstantBuffers[16] = {}; + ID3D11Buffer* mBoundConstantBuffers[16]; static gfxD3DIncludeRef smD3DInclude; HandleMap mHandles; BufferMap mBuffers; - Vector mValidHandles; - /// The shader disassembly from DX when this shader is compiled. - /// We only store this data in non-release builds. - String mDissasembly; - /// Vector of descriptions (consolidated for the getShaderConstDesc call) Vector mShaderConsts; @@ -250,10 +234,5 @@ protected: void setConstantsFromBuffer(GFXD3D11ShaderConstBuffer* buffer); }; -inline bool GFXD3D11Shader::getDisassembly(String &outStr) const -{ - outStr = mDissasembly; - return (outStr.isNotEmpty()); -} #endif From 42b8748f5b2347d4e817183815a4e46b559087ce Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Sat, 24 Feb 2024 12:04:53 +0000 Subject: [PATCH 09/53] bkup still memory heap issue --- Engine/source/gfx/D3D11/gfxD3D11Shader.cpp | 186 +++++++++++------- Engine/source/gfx/D3D11/gfxD3D11Shader.h | 14 +- .../materials/processedCustomMaterial.cpp | 1 - .../materials/processedShaderMaterial.cpp | 1 - 4 files changed, 121 insertions(+), 81 deletions(-) diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp index d5e5d400c..101b22ed5 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp @@ -157,6 +157,11 @@ GFXD3D11ShaderConstBuffer::~GFXD3D11ShaderConstBuffer() { delete[] i->value; } + + mBufferMap.clear(); + + if (mShader) + mShader->_unlinkBuffer(this); } GFXShader* GFXD3D11ShaderConstBuffer::getShader() @@ -234,7 +239,7 @@ void GFXD3D11ShaderConstBuffer::internalSet(GFXShaderConstHandle* handle, const GFXD3D11ShaderConstHandle* _dxHandle = static_cast(handle); AssertFatal(mShader == _dxHandle->mShader, "GFXD3D11ShaderConstBuffer::internalSet - Should only set handles which are owned by our shader"); - BufferKey bufDesc(_dxHandle->mBinding, (SHADER_STAGE)_dxHandle->mStage); + const BufferKey bufDesc(_dxHandle->mBinding, (SHADER_STAGE)_dxHandle->mStage); U8* buf = mBufferMap[bufDesc] + _dxHandle->mOffset; if (_dxHandle->mInstancingConstant) @@ -293,7 +298,7 @@ void GFXD3D11ShaderConstBuffer::internalSet(GFXShaderConstHandle* handle, const GFXD3D11ShaderConstHandle* _dxHandle = static_cast(handle); AssertFatal(mShader == _dxHandle->mShader, "GFXD3D11ShaderConstBuffer::internalSet - Should only set handles which are owned by our shader"); AssertFatal(!_dxHandle->mInstancingConstant, "GFXD3D11ShaderConstBuffer::internalSet - Instancing not supported for array"); - BufferKey bufDesc(_dxHandle->mBinding, (SHADER_STAGE)_dxHandle->mStage); + const BufferKey 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) @@ -313,7 +318,7 @@ void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF& const GFXD3D11ShaderConstHandle* _dxHandle = static_cast(handle); AssertFatal(!_dxHandle->isSampler(), "Handle is sampler constant!" ); AssertFatal(_dxHandle->mShader == mShader, "Mismatched shaders!"); - BufferKey bufDesc(_dxHandle->mBinding, (SHADER_STAGE)_dxHandle->mStage); + const BufferKey bufDesc(_dxHandle->mBinding, (SHADER_STAGE)_dxHandle->mStage); U8* buf = mBufferMap[bufDesc] + _dxHandle->mOffset; MatrixF transposed; @@ -372,7 +377,7 @@ void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF* AssertFatal(!_dxHandle->isSampler(), "Handle is sampler constant!"); AssertFatal(_dxHandle->mShader == mShader, "Mismatched shaders!"); - BufferKey bufDesc(_dxHandle->mBinding, (SHADER_STAGE)_dxHandle->mStage); + const BufferKey bufDesc(_dxHandle->mBinding, (SHADER_STAGE)_dxHandle->mStage); U8* buf = mBufferMap[bufDesc] ; @@ -433,21 +438,18 @@ const String GFXD3D11ShaderConstBuffer::describeSelf() const return ret; } -bool GFXD3D11ShaderConstBuffer::isDirty() -{ - return true; -} - void GFXD3D11ShaderConstBuffer::addBuffer(U32 bufBindingPoint, SHADER_STAGE shaderStage, U32 size) { - BufferKey bufKey(bufBindingPoint, shaderStage); + const BufferKey bufKey(bufBindingPoint, shaderStage); BufferMap::Iterator buffer = mBufferMap.find(bufKey); // already added? pass... if (buffer != mBufferMap.end()) return; + U8* buf = new U8[size]; + dMemset(buf, 0, size); // new buffer with our size. - mBufferMap[bufKey] = new U8[size]; + mBufferMap[bufKey] = buf; } void GFXD3D11ShaderConstBuffer::activate( GFXD3D11ShaderConstBuffer *prevShaderBuffer ) @@ -461,6 +463,11 @@ void GFXD3D11ShaderConstBuffer::onShaderReload( GFXD3D11Shader *shader ) { AssertFatal( shader == mShader, "GFXD3D11ShaderConstBuffer::onShaderReload is hosed!" ); + for (BufferMap::Iterator i = mBufferMap.begin(); i != mBufferMap.end(); i++) + { + delete[] i->value; + } + // Set the lost state. mWasLost = true; } @@ -496,6 +503,10 @@ GFXD3D11Shader::~GFXD3D11Shader() delete[] i->value; } + mHandles.clear(); + + mBuffers.clear(); + for (U32 i = 0; i < 16; i++) { SAFE_RELEASE(mBoundConstantBuffers[i]); @@ -536,7 +547,7 @@ bool GFXD3D11Shader::_init() memset(&d3dMacros[macroCount - 1], 0, sizeof(D3D_SHADER_MACRO)); mShaderConsts.clear(); - + mSamplerDescriptions.clear(); if (!mVertexFile.isEmpty() && !_compileShader( mVertexFile, SHADER_STAGE::VERTEX_SHADER, d3dMacros) ) return false; @@ -662,36 +673,37 @@ bool GFXD3D11Shader::_compileShader( const Torque::Path &filePath, if(code != NULL) { - switch (shaderStage) - { - case VERTEX_SHADER: - res = D3D11DEVICE->CreateVertexShader(code->GetBufferPointer(), code->GetBufferSize(), NULL, &mVertShader); - break; - case PIXEL_SHADER: - res = D3D11DEVICE->CreatePixelShader(code->GetBufferPointer(), code->GetBufferSize(), NULL, &mPixShader); - break; - case GEOMETRY_SHADER: - break; - case DOMAIN_SHADER: - break; - case HULL_SHADER: - break; - case COMPUTE_SHADER: - break; - default: - break; - } + switch (shaderStage) + { + case VERTEX_SHADER: + res = D3D11DEVICE->CreateVertexShader(code->GetBufferPointer(), code->GetBufferSize(), NULL, &mVertShader); + break; + case PIXEL_SHADER: + res = D3D11DEVICE->CreatePixelShader(code->GetBufferPointer(), code->GetBufferSize(), NULL, &mPixShader); + break; + case GEOMETRY_SHADER: + break; + case DOMAIN_SHADER: + break; + case HULL_SHADER: + break; + case COMPUTE_SHADER: + break; + default: + break; + } - if (FAILED(res)) - { - AssertFatal(false, "D3D11Shader::_compilershader- failed to create shader"); - } + if (FAILED(res)) + { + AssertFatal(false, "D3D11Shader::_compilershader- failed to create shader"); + } - if(res == S_OK){ - HRESULT reflectionResult = D3DReflect(code->GetBufferPointer(), code->GetBufferSize(), IID_ID3D11ShaderReflection, (void**)&reflectionTable); - if(FAILED(reflectionResult)) - AssertFatal(false, "D3D11Shader::_compilershader - Failed to get shader reflection table interface"); - } + if(res == S_OK) + { + HRESULT reflectionResult = D3DReflect(code->GetBufferPointer(), code->GetBufferSize(), IID_ID3D11ShaderReflection, (void**)&reflectionTable); + if(FAILED(reflectionResult)) + AssertFatal(false, "D3D11Shader::_compilershader - Failed to get shader reflection table interface"); + } if(res == S_OK) _getShaderConstants(reflectionTable, shaderStage); @@ -704,29 +716,28 @@ bool GFXD3D11Shader::_compileShader( const Torque::Path &filePath, bool result = code && SUCCEEDED(res); #ifdef TORQUE_DEBUG - - String shader; - switch (shaderStage) - { - case VERTEX_SHADER: - shader = mVertexFile.getFileName(); - mVertShader->SetPrivateData(WKPDID_D3DDebugObjectName, shader.size(), shader.c_str()); - break; - case PIXEL_SHADER: - shader = mPixelFile.getFileName(); - mPixShader->SetPrivateData(WKPDID_D3DDebugObjectName, shader.size(), shader.c_str()); - break; - case GEOMETRY_SHADER: - break; - case DOMAIN_SHADER: - break; - case HULL_SHADER: - break; - case COMPUTE_SHADER: - break; - default: - break; - } + //String shader; + //switch (shaderStage) + //{ + //case VERTEX_SHADER: + // shader = mVertexFile.getFileName(); + // mVertShader->SetPrivateData(WKPDID_D3DDebugObjectName, shader.size(), shader.c_str()); + // break; + //case PIXEL_SHADER: + // shader = mPixelFile.getFileName(); + // mPixShader->SetPrivateData(WKPDID_D3DDebugObjectName, shader.size(), shader.c_str()); + // break; + //case GEOMETRY_SHADER: + // break; + //case DOMAIN_SHADER: + // break; + //case HULL_SHADER: + // break; + //case COMPUTE_SHADER: + // break; + //default: + // break; + //} #endif SAFE_RELEASE(code); @@ -768,6 +779,9 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection *refTable, constantBuffer->GetDesc(&constantBufferDesc); +#ifdef D3D11_DEBUG_SPEW + Con::printf("Constant Buffer Name: %s", constantBufferDesc.Name); +#endif // push back our const buffer as a descriptor, this also marks the start of a buffer. desc.size = constantBufferDesc.Size; mShaderConsts.push_back(desc); @@ -783,6 +797,10 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection *refTable, D3D11_SHADER_TYPE_DESC shaderTypeDesc; bufferVar->GetType()->GetDesc(&shaderTypeDesc); + bool unusedVar = shaderVarDesc.uFlags & D3D_SVF_USED ? false : true; + if (unusedVar) + continue; + varDesc.name = String(shaderVarDesc.Name); if (varDesc.name.find("$") != 0) varDesc.name = String::ToString("$%s", varDesc.name.c_str()); @@ -795,6 +813,10 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection *refTable, varDesc.shaderStage = shaderStage; varDesc.samplerReg = -1; +#ifdef D3D11_DEBUG_SPEW + Con::printf("Variable Name %s:, offset: %d, size: %d, constantDesc.Elements: %d", varDesc.name.c_str(), varDesc.StartOffset, varDesc.Size, varDesc.arraySize); +#endif + if (shaderTypeDesc.Class == D3D_SVC_SCALAR || shaderTypeDesc.Class == D3D_SVC_VECTOR) { switch (shaderTypeDesc.Type) @@ -882,7 +904,8 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection *refTable, desc.samplerReg = shaderInputBind.BindPoint; desc.bindPoint = -1; desc.shaderStage = shaderStage; - mShaderConsts.push_back(desc); + desc.arraySize = shaderInputBind.BindCount; + mSamplerDescriptions.push_back(desc); } else if (shaderInputBind.Type == D3D_SIT_UAV_RWTYPED || shaderInputBind.Type == D3D_SIT_UAV_RWSTRUCTURED || @@ -943,8 +966,7 @@ void GFXD3D11Shader::_buildShaderConstantHandles() if (desc.constType == GFXSCT_ConstBuffer) { - BufferKey bufKey(desc.bindPoint, (SHADER_STAGE)desc.shaderStage); - + const BufferKey bufKey(desc.bindPoint, (SHADER_STAGE)desc.shaderStage); BufferMap::Iterator buffer = mBuffers.find(bufKey); // already added? pass... @@ -970,8 +992,10 @@ void GFXD3D11Shader::_buildShaderConstantHandles() mBoundConstantBuffers[desc.bindPoint] = constBuffer; + U8* buf = new U8[desc.size]; + dMemset(buf, 0, desc.size); // new buffer with our size. - mBuffers[bufKey] = new U8[desc.size]; + mBuffers[bufKey] = buf; // do not add to handles.. continue; @@ -990,6 +1014,29 @@ void GFXD3D11Shader::_buildShaderConstantHandles() } } + for (U32 i = 0; i < mSamplerDescriptions.size(); i++) + { + GFXShaderConstDesc& desc = mSamplerDescriptions[i]; + + AssertFatal(desc.constType == GFXSCT_Sampler || + desc.constType == GFXSCT_SamplerCube || + desc.constType == GFXSCT_SamplerCubeArray || + desc.constType == GFXSCT_SamplerTextureArray, + "GFXD3D11Shader::_buildShaderConstantHandles - Invalid samplerDescription type!"); + + 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); + } + else + { + mHandles[desc.name] = new GFXD3D11ShaderConstHandle(this, desc); + } + } + _buildInstancingShaderConstantHandles(); } @@ -1040,9 +1087,12 @@ void GFXD3D11Shader::setConstantsFromBuffer(GFXD3D11ShaderConstBuffer* buffer) { BufferRange bufRanges[6] = {}; + D3D11_MAPPED_SUBRESOURCE pConstData; + ZeroMemory(&pConstData, sizeof(D3D11_MAPPED_SUBRESOURCE)); + for (BufferMap::Iterator i = mBuffers.begin(); i != mBuffers.end(); ++i) { - BufferKey oldBufferDesc = i->key; + const BufferKey oldBufferDesc = i->key; U8* oldBuff = i->value; U8* newBuff = buffer->mBufferMap[i->key]; diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.h b/Engine/source/gfx/D3D11/gfxD3D11Shader.h index 4cdf94870..286097ee5 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.h +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.h @@ -29,7 +29,6 @@ #include "core/util/tDictionary.h" #include "gfx/gfxShader.h" #include "gfx/gfxResource.h" -#include "gfx/genericConstBuffer.h" #include "gfx/D3D11/gfxD3D11Device.h" class GFXD3D11Shader; @@ -50,7 +49,7 @@ typedef CompoundKey BufferKey; struct BufferRange { - U32 mBufMin = 0xFFFFFFFF; + U32 mBufMin = U32_MAX; U32 mBufMax = 0; inline void addSlot(U32 slot) @@ -116,9 +115,6 @@ public: /// @param mPrevShaderBuffer The previously active buffer void activate(GFXD3D11ShaderConstBuffer *prevShaderBuffer); - /// Used internally by GXD3D11ShaderConstBuffer to determine if it's dirty. - bool isDirty(); - void addBuffer(U32 bufBindingPoint, SHADER_STAGE shaderStage, U32 size); /// Called from GFXD3D11Shader when constants have changed and need @@ -191,7 +187,6 @@ public: virtual GFXShaderConstHandle* getShaderConstHandle(const String& name); virtual GFXShaderConstHandle* findShaderConstHandle(const String& name); virtual U32 getAlignmentValue(const GFXShaderConstType constType) const; - virtual bool getDisassembly( String &outStr ) const; // GFXResource virtual void zombify(); @@ -199,9 +194,7 @@ public: protected: - virtual bool _init(); - - static const U32 smCompiledShaderTag; + virtual bool _init(); ID3D11VertexShader *mVertShader; ID3D11PixelShader *mPixShader; @@ -216,8 +209,7 @@ protected: /// Vector of descriptions (consolidated for the getShaderConstDesc call) Vector mShaderConsts; - - //Vector mDeviceBuffers; + Vector mSamplerDescriptions; // These two functions are used when compiling shaders from hlsl virtual bool _compileShader( const Torque::Path &filePath, diff --git a/Engine/source/materials/processedCustomMaterial.cpp b/Engine/source/materials/processedCustomMaterial.cpp index 15772c078..5c16a012e 100644 --- a/Engine/source/materials/processedCustomMaterial.cpp +++ b/Engine/source/materials/processedCustomMaterial.cpp @@ -35,7 +35,6 @@ #include "materials/materialParameters.h" #include "gfx/sim/gfxStateBlockData.h" #include "core/util/safeDelete.h" -#include "gfx/genericConstBuffer.h" #include "console/simFieldDictionary.h" #include "console/propertyParsing.h" #include "gfx/util/screenspace.h" diff --git a/Engine/source/materials/processedShaderMaterial.cpp b/Engine/source/materials/processedShaderMaterial.cpp index dfba63533..83f58e1d9 100644 --- a/Engine/source/materials/processedShaderMaterial.cpp +++ b/Engine/source/materials/processedShaderMaterial.cpp @@ -26,7 +26,6 @@ #include "core/util/safeDelete.h" #include "gfx/sim/cubemapData.h" #include "gfx/gfxShader.h" -#include "gfx/genericConstBuffer.h" #include "gfx/gfxPrimitiveBuffer.h" #include "scene/sceneRenderState.h" #include "shaderGen/shaderFeature.h" From dd4d48d65441714cdf0928f6e5a0678f72000c79 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Sat, 24 Feb 2024 12:40:12 +0000 Subject: [PATCH 10/53] working example now its working.. still not perfect but its getting there --- Engine/source/gfx/D3D11/gfxD3D11Shader.cpp | 161 ++++++++++----------- Engine/source/gfx/D3D11/gfxD3D11Shader.h | 12 +- 2 files changed, 85 insertions(+), 88 deletions(-) diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp index 101b22ed5..85cea0ef6 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp @@ -149,6 +149,11 @@ GFXD3D11ShaderConstBuffer::GFXD3D11ShaderConstBuffer( GFXD3D11Shader* shader) { mShader = shader; mDeviceContext = D3D11DEVICECONTEXT; + + for (U32 i = 0; i < 16; i++) + { + mBoundConstantBuffers[i] = NULL; + } } GFXD3D11ShaderConstBuffer::~GFXD3D11ShaderConstBuffer() @@ -160,6 +165,12 @@ GFXD3D11ShaderConstBuffer::~GFXD3D11ShaderConstBuffer() mBufferMap.clear(); + for (U32 i = 0; i < 16; i++) + { + SAFE_RELEASE(mBoundConstantBuffers[i]); + } + + if (mShader) mShader->_unlinkBuffer(this); } @@ -342,7 +353,7 @@ void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF& if (matrixType == GFXSCT_Float4x4) { - dMemcpy(buf, transposed, sizeof(MatrixF)); + dMemcpy(buf, &transposed, sizeof(MatrixF)); return; } @@ -447,15 +458,76 @@ void GFXD3D11ShaderConstBuffer::addBuffer(U32 bufBindingPoint, SHADER_STAGE shad return; U8* buf = new U8[size]; - dMemset(buf, 0, size); // new buffer with our size. mBufferMap[bufKey] = buf; + + D3D11_BUFFER_DESC cbDesc; + cbDesc.ByteWidth = 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, &mBoundConstantBuffers[bufBindingPoint]); + + if (FAILED(hr)) + { + AssertFatal(false, "can't create constant buffer"); + } } void GFXD3D11ShaderConstBuffer::activate( GFXD3D11ShaderConstBuffer *prevShaderBuffer ) { PROFILE_SCOPE(GFXD3D11ShaderConstBuffer_activate); - mShader->setConstantsFromBuffer(this); + + if (prevShaderBuffer == NULL) + return; + + BufferRange bufRanges[6] = {}; + + D3D11_MAPPED_SUBRESOURCE pConstData; + ZeroMemory(&pConstData, sizeof(D3D11_MAPPED_SUBRESOURCE)); + + for (BufferMap::Iterator i = mBufferMap.begin(); i != mBufferMap.end(); ++i) + { + const BufferKey oldBufferDesc = i->key; + U8* oldBuff = i->value; + + U8* newBuff = prevShaderBuffer->mBufferMap[i->key]; + U32 size = mShader->mBuffers[i->key].size(); + + if (dMemcmp(oldBuff, newBuff, size) != 0) + { + // else copy new over the buffer. + dMemcpy(oldBuff, newBuff, size); + + // buffer has been changed and needs updating. + D3D11DEVICECONTEXT->UpdateSubresource(mBoundConstantBuffers[oldBufferDesc.key1], 0, NULL, oldBuff, size, 0); + } + + bufRanges[oldBufferDesc.key2].addSlot(oldBufferDesc.key1); + } + + if (bufRanges[SHADER_STAGE::VERTEX_SHADER].isValid()) + { + 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 (bufRanges[SHADER_STAGE::PIXEL_SHADER].isValid()) + { + 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); + } + mWasLost = false; } @@ -485,10 +557,7 @@ GFXD3D11Shader::GFXD3D11Shader() if( smD3DInclude == NULL ) smD3DInclude = new gfxD3D11Include; - for (U32 i = 0; i < 16; i++) - { - mBoundConstantBuffers[i] = NULL; - } + } //------------------------------------------------------------------------------ @@ -500,18 +569,13 @@ GFXD3D11Shader::~GFXD3D11Shader() for (BufferMap::Iterator i = mBuffers.begin(); i != mBuffers.end(); i++) { - delete[] i->value; + i->value.clear(); } mHandles.clear(); mBuffers.clear(); - for (U32 i = 0; i < 16; i++) - { - SAFE_RELEASE(mBoundConstantBuffers[i]); - } - // release shaders SAFE_RELEASE(mVertShader); SAFE_RELEASE(mPixShader); @@ -973,27 +1037,8 @@ 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"); - } - - mBoundConstantBuffers[desc.bindPoint] = constBuffer; - - U8* buf = new U8[desc.size]; - dMemset(buf, 0, desc.size); + Vector buf; + buf.setSize(desc.size); // new buffer with our size. mBuffers[bufKey] = buf; @@ -1083,52 +1128,6 @@ void GFXD3D11Shader::_buildInstancingShaderConstantHandles() } } -void GFXD3D11Shader::setConstantsFromBuffer(GFXD3D11ShaderConstBuffer* buffer) -{ - BufferRange bufRanges[6] = {}; - - D3D11_MAPPED_SUBRESOURCE pConstData; - ZeroMemory(&pConstData, sizeof(D3D11_MAPPED_SUBRESOURCE)); - - for (BufferMap::Iterator i = mBuffers.begin(); i != mBuffers.end(); ++i) - { - const BufferKey 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.key1], 0, NULL, oldBuff, sizeof(oldBuff), 0); - } - - bufRanges[oldBufferDesc.key2].addSlot(oldBufferDesc.key1); - } - - if (mVertShader != nullptr && bufRanges[SHADER_STAGE::VERTEX_SHADER].isValid()) - { - 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 && bufRanges[SHADER_STAGE::PIXEL_SHADER].isValid()) - { - 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); @@ -1136,7 +1135,7 @@ GFXShaderConstBufferRef GFXD3D11Shader::allocConstBuffer() for (BufferMap::Iterator i = mBuffers.begin(); i != mBuffers.end(); ++i) { // add our buffer descriptions to the full const buffer. - buffer->addBuffer(i->key.key1,i->key.key2, sizeof(i->value)); + buffer->addBuffer(i->key.key1,i->key.key2, i->value.size()); } mActiveBuffers.push_back( buffer ); diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.h b/Engine/source/gfx/D3D11/gfxD3D11Shader.h index 286097ee5..fb40a9e48 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.h +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.h @@ -149,7 +149,7 @@ public: virtual void zombify() {} virtual void resurrect() {} -private: +protected: friend class GFXD3D11Shader; /// We keep a weak reference to the shader /// because it will often be deleted. @@ -161,6 +161,9 @@ private: template void internalSet(GFXShaderConstHandle* handle, const AlignedArray& fv); + + // we probably want this to be GFXDevice and not per shader. + ID3D11Buffer* mBoundConstantBuffers[16]; }; class gfxD3D11Include; @@ -175,8 +178,7 @@ class GFXD3D11Shader : public GFXShader public: typedef Map HandleMap; - - typedef Map BufferMap; + typedef Map> BufferMap; GFXD3D11Shader(); virtual ~GFXD3D11Shader(); @@ -199,9 +201,6 @@ protected: ID3D11VertexShader *mVertShader; ID3D11PixelShader *mPixShader; - // we probably want this to be GFXDevice and not per shader. - ID3D11Buffer* mBoundConstantBuffers[16]; - static gfxD3DIncludeRef smD3DInclude; HandleMap mHandles; @@ -223,7 +222,6 @@ protected: virtual void _buildShaderConstantHandles(); void _buildInstancingShaderConstantHandles(); - void setConstantsFromBuffer(GFXD3D11ShaderConstBuffer* buffer); }; From 8887e21f4b464e1dd6b0cf7b51effc5b4b22a2ac Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Sat, 24 Feb 2024 14:42:30 +0000 Subject: [PATCH 11/53] working working example, renders all gui controls. We still cant render a scene, something to do with the constant buffer at slot 0 of the vertex shader being too small..... gotta figure this one out.................. --- Engine/source/gfx/D3D11/gfxD3D11Shader.cpp | 52 +++++++++++++--------- Engine/source/gfx/D3D11/gfxD3D11Shader.h | 13 +++++- 2 files changed, 44 insertions(+), 21 deletions(-) diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp index 85cea0ef6..a20149b71 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp @@ -160,7 +160,7 @@ GFXD3D11ShaderConstBuffer::~GFXD3D11ShaderConstBuffer() { for (BufferMap::Iterator i = mBufferMap.begin(); i != mBufferMap.end(); i++) { - delete[] i->value; + delete[] i->value.data; } mBufferMap.clear(); @@ -251,7 +251,7 @@ void GFXD3D11ShaderConstBuffer::internalSet(GFXShaderConstHandle* handle, const AssertFatal(mShader == _dxHandle->mShader, "GFXD3D11ShaderConstBuffer::internalSet - Should only set handles which are owned by our shader"); const BufferKey bufDesc(_dxHandle->mBinding, (SHADER_STAGE)_dxHandle->mStage); - U8* buf = mBufferMap[bufDesc] + _dxHandle->mOffset; + U8* buf = mBufferMap[bufDesc].data + _dxHandle->mOffset; if (_dxHandle->mInstancingConstant) buf = mInstPtr + _dxHandle->mOffset; @@ -310,7 +310,7 @@ void GFXD3D11ShaderConstBuffer::internalSet(GFXShaderConstHandle* handle, const AssertFatal(mShader == _dxHandle->mShader, "GFXD3D11ShaderConstBuffer::internalSet - Should only set handles which are owned by our shader"); AssertFatal(!_dxHandle->mInstancingConstant, "GFXD3D11ShaderConstBuffer::internalSet - Instancing not supported for array"); const BufferKey bufDesc(_dxHandle->mBinding, (SHADER_STAGE)_dxHandle->mStage); - U8* buf = mBufferMap[bufDesc]; + U8* buf = mBufferMap[bufDesc].data; const U8* fvBuffer = static_cast(fv.getBuffer()); for (U32 i = 0; i < fv.size(); ++i) { @@ -330,7 +330,7 @@ void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF& AssertFatal(!_dxHandle->isSampler(), "Handle is sampler constant!" ); AssertFatal(_dxHandle->mShader == mShader, "Mismatched shaders!"); const BufferKey bufDesc(_dxHandle->mBinding, (SHADER_STAGE)_dxHandle->mStage); - U8* buf = mBufferMap[bufDesc] + _dxHandle->mOffset; + U8* buf = mBufferMap[bufDesc].data; MatrixF transposed; if (matrixType == GFXSCT_Float4x3) @@ -374,7 +374,7 @@ void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF& break; } - dMemcpy(buf, transposed, csize); + dMemcpy(buf, (const F32*)transposed, csize); } @@ -390,7 +390,7 @@ void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF* const BufferKey bufDesc(_dxHandle->mBinding, (SHADER_STAGE)_dxHandle->mStage); - U8* buf = mBufferMap[bufDesc] ; + U8* buf = mBufferMap[bufDesc].data; static Vector transposed; if (arraySize > transposed.size()) @@ -457,9 +457,11 @@ void GFXD3D11ShaderConstBuffer::addBuffer(U32 bufBindingPoint, SHADER_STAGE shad if (buffer != mBufferMap.end()) return; - U8* buf = new U8[size]; // new buffer with our size. - mBufferMap[bufKey] = buf; + mBufferMap[bufKey].data = new U8[size]; + // always dirty on new. + mBufferMap[bufKey].size = size; + mBufferMap[bufKey].isDirty = true; D3D11_BUFFER_DESC cbDesc; cbDesc.ByteWidth = size; @@ -492,22 +494,32 @@ void GFXD3D11ShaderConstBuffer::activate( GFXD3D11ShaderConstBuffer *prevShaderB for (BufferMap::Iterator i = mBufferMap.begin(); i != mBufferMap.end(); ++i) { - const BufferKey oldBufferDesc = i->key; - U8* oldBuff = i->value; + const BufferKey thisBufferDesc = i->key; + ConstantBuffer thisBuff = i->value; - U8* newBuff = prevShaderBuffer->mBufferMap[i->key]; - U32 size = mShader->mBuffers[i->key].size(); + const ConstantBuffer prevBuffer = prevShaderBuffer->mBufferMap[i->key]; - if (dMemcmp(oldBuff, newBuff, size) != 0) + if (prevBuffer.data && !prevBuffer.isDirty) { - // else copy new over the buffer. - dMemcpy(oldBuff, newBuff, size); - - // buffer has been changed and needs updating. - D3D11DEVICECONTEXT->UpdateSubresource(mBoundConstantBuffers[oldBufferDesc.key1], 0, NULL, oldBuff, size, 0); + if (prevBuffer.size != thisBuff.size) + { + thisBuff.isDirty = true; + } + else if (dMemcmp(prevBuffer.data, thisBuff.data, thisBuff.size) != 0) + { + thisBuff.isDirty = true; + } + } + else + { + thisBuff.isDirty = true; } - bufRanges[oldBufferDesc.key2].addSlot(oldBufferDesc.key1); + if (thisBuff.data && thisBuff.isDirty) + { + D3D11DEVICECONTEXT->UpdateSubresource(mBoundConstantBuffers[thisBufferDesc.key1], 0, NULL, thisBuff.data, thisBuff.size, 0); + bufRanges[thisBufferDesc.key2].addSlot(thisBufferDesc.key1); + } } if (bufRanges[SHADER_STAGE::VERTEX_SHADER].isValid()) @@ -537,7 +549,7 @@ void GFXD3D11ShaderConstBuffer::onShaderReload( GFXD3D11Shader *shader ) for (BufferMap::Iterator i = mBufferMap.begin(); i != mBufferMap.end(); i++) { - delete[] i->value; + delete[] i->value.data; } // Set the lost state. diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.h b/Engine/source/gfx/D3D11/gfxD3D11Shader.h index fb40a9e48..deab25f91 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.h +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.h @@ -61,6 +61,13 @@ struct BufferRange inline bool isValid() const { return mBufMin <= mBufMax; } }; +struct ConstantBuffer +{ + U8* data; + U32 size; + bool isDirty; +}; + class GFXD3D11ShaderConstHandle : public GFXShaderConstHandle { friend class GFXD3D11Shader; @@ -105,7 +112,7 @@ class GFXD3D11ShaderConstBuffer : public GFXShaderConstBuffer ID3D11DeviceContext* mDeviceContext; public: - typedef Map BufferMap; + typedef Map BufferMap; GFXD3D11ShaderConstBuffer(GFXD3D11Shader* shader); @@ -117,6 +124,9 @@ public: void addBuffer(U32 bufBindingPoint, SHADER_STAGE shaderStage, U32 size); + bool isDirty() { return mDirty; } + void setDirty(bool isDirty) { mDirty = isDirty; } + /// Called from GFXD3D11Shader when constants have changed and need /// to be the shader this buffer references is reloaded. void onShaderReload(GFXD3D11Shader *shader); @@ -164,6 +174,7 @@ protected: // we probably want this to be GFXDevice and not per shader. ID3D11Buffer* mBoundConstantBuffers[16]; + bool mDirty; }; class gfxD3D11Include; From e8d8138c74b80a3f3411d2ceb0d40f9370b86a43 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Sat, 24 Feb 2024 16:26:09 +0000 Subject: [PATCH 12/53] working last commit before global conform --- Engine/source/gfx/D3D11/gfxD3D11Shader.cpp | 74 +++++++++------------- Engine/source/gfx/D3D11/gfxD3D11Shader.h | 4 -- 2 files changed, 30 insertions(+), 48 deletions(-) diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp index a20149b71..8231f32cb 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp @@ -158,11 +158,6 @@ GFXD3D11ShaderConstBuffer::GFXD3D11ShaderConstBuffer( GFXD3D11Shader* shader) GFXD3D11ShaderConstBuffer::~GFXD3D11ShaderConstBuffer() { - for (BufferMap::Iterator i = mBufferMap.begin(); i != mBufferMap.end(); i++) - { - delete[] i->value.data; - } - mBufferMap.clear(); for (U32 i = 0; i < 16; i++) @@ -459,6 +454,7 @@ void GFXD3D11ShaderConstBuffer::addBuffer(U32 bufBindingPoint, SHADER_STAGE shad // new buffer with our size. mBufferMap[bufKey].data = new U8[size]; + dMemset(mBufferMap[bufKey].data, 0, size); // always dirty on new. mBufferMap[bufKey].size = size; mBufferMap[bufKey].isDirty = true; @@ -487,10 +483,7 @@ void GFXD3D11ShaderConstBuffer::activate( GFXD3D11ShaderConstBuffer *prevShaderB if (prevShaderBuffer == NULL) return; - BufferRange bufRanges[6] = {}; - - D3D11_MAPPED_SUBRESOURCE pConstData; - ZeroMemory(&pConstData, sizeof(D3D11_MAPPED_SUBRESOURCE)); + BufferRange bufRanges[6]; for (BufferMap::Iterator i = mBufferMap.begin(); i != mBufferMap.end(); ++i) { @@ -505,10 +498,15 @@ void GFXD3D11ShaderConstBuffer::activate( GFXD3D11ShaderConstBuffer *prevShaderB { thisBuff.isDirty = true; } - else if (dMemcmp(prevBuffer.data, thisBuff.data, thisBuff.size) != 0) + + if (dMemcmp(prevBuffer.data, thisBuff.data, thisBuff.size) != 0) { thisBuff.isDirty = true; } + else + { + thisBuff.isDirty = false; + } } else { @@ -576,14 +574,6 @@ GFXD3D11Shader::GFXD3D11Shader() GFXD3D11Shader::~GFXD3D11Shader() { - for (HandleMap::Iterator i = mHandles.begin(); i != mHandles.end(); i++) - delete i->value; - - for (BufferMap::Iterator i = mBuffers.begin(); i != mBuffers.end(); i++) - { - i->value.clear(); - } - mHandles.clear(); mBuffers.clear(); @@ -792,28 +782,28 @@ bool GFXD3D11Shader::_compileShader( const Torque::Path &filePath, bool result = code && SUCCEEDED(res); #ifdef TORQUE_DEBUG - //String shader; - //switch (shaderStage) - //{ - //case VERTEX_SHADER: - // shader = mVertexFile.getFileName(); - // mVertShader->SetPrivateData(WKPDID_D3DDebugObjectName, shader.size(), shader.c_str()); - // break; - //case PIXEL_SHADER: - // shader = mPixelFile.getFileName(); - // mPixShader->SetPrivateData(WKPDID_D3DDebugObjectName, shader.size(), shader.c_str()); - // break; - //case GEOMETRY_SHADER: - // break; - //case DOMAIN_SHADER: - // break; - //case HULL_SHADER: - // break; - //case COMPUTE_SHADER: - // break; - //default: - // break; - //} + String shader; + switch (shaderStage) + { + case VERTEX_SHADER: + shader = mVertexFile.getFileName(); + mVertShader->SetPrivateData(WKPDID_D3DDebugObjectName, shader.size(), shader.c_str()); + break; + case PIXEL_SHADER: + shader = mPixelFile.getFileName(); + mPixShader->SetPrivateData(WKPDID_D3DDebugObjectName, shader.size(), shader.c_str()); + break; + case GEOMETRY_SHADER: + break; + case DOMAIN_SHADER: + break; + case HULL_SHADER: + break; + case COMPUTE_SHADER: + break; + default: + break; + } #endif SAFE_RELEASE(code); @@ -873,10 +863,6 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection *refTable, D3D11_SHADER_TYPE_DESC shaderTypeDesc; bufferVar->GetType()->GetDesc(&shaderTypeDesc); - bool unusedVar = shaderVarDesc.uFlags & D3D_SVF_USED ? false : true; - if (unusedVar) - continue; - varDesc.name = String(shaderVarDesc.Name); if (varDesc.name.find("$") != 0) varDesc.name = String::ToString("$%s", varDesc.name.c_str()); diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.h b/Engine/source/gfx/D3D11/gfxD3D11Shader.h index deab25f91..2269a8603 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.h +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.h @@ -124,9 +124,6 @@ public: void addBuffer(U32 bufBindingPoint, SHADER_STAGE shaderStage, U32 size); - bool isDirty() { return mDirty; } - void setDirty(bool isDirty) { mDirty = isDirty; } - /// Called from GFXD3D11Shader when constants have changed and need /// to be the shader this buffer references is reloaded. void onShaderReload(GFXD3D11Shader *shader); @@ -174,7 +171,6 @@ protected: // we probably want this to be GFXDevice and not per shader. ID3D11Buffer* mBoundConstantBuffers[16]; - bool mDirty; }; class gfxD3D11Include; From 3f3ef12c3b5d0c7b75edbbd0db34e82ccc2ca997 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Sat, 24 Feb 2024 17:33:28 +0000 Subject: [PATCH 13/53] handle the global buffer global buffer needs a special case --- Engine/source/gfx/D3D11/gfxD3D11Shader.cpp | 46 ++++++++++++++++++---- Engine/source/gfx/D3D11/gfxD3D11Shader.h | 5 +++ 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp index 8231f32cb..184248974 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp @@ -520,7 +520,19 @@ void GFXD3D11ShaderConstBuffer::activate( GFXD3D11ShaderConstBuffer *prevShaderB } } - if (bufRanges[SHADER_STAGE::VERTEX_SHADER].isValid()) + if (bufRanges[SHADER_STAGE::ALL_SHADERS].isValid()) + { + const U32 bufStartSlot = bufRanges[SHADER_STAGE::ALL_SHADERS].mBufMin; + const U32 numBufs = bufRanges[SHADER_STAGE::ALL_SHADERS].mBufMax - bufRanges[SHADER_STAGE::ALL_SHADERS].mBufMin + 1; + ID3D11Buffer** globalBuffer = mBoundConstantBuffers + bufStartSlot; + + if(mShader->mVertShader) + D3D11DEVICECONTEXT->VSSetConstantBuffers(bufStartSlot, numBufs, globalBuffer); + if(mShader->mPixShader) + D3D11DEVICECONTEXT->PSSetConstantBuffers(bufStartSlot, numBufs, globalBuffer); + } + + if (mShader->mVertShader && bufRanges[SHADER_STAGE::VERTEX_SHADER].isValid()) { 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; @@ -529,7 +541,7 @@ void GFXD3D11ShaderConstBuffer::activate( GFXD3D11ShaderConstBuffer *prevShaderB D3D11DEVICECONTEXT->VSSetConstantBuffers(bufStartSlot, numBufs, vsBuffers); } - if (bufRanges[SHADER_STAGE::PIXEL_SHADER].isValid()) + if (mShader->mPixShader && bufRanges[SHADER_STAGE::PIXEL_SHADER].isValid()) { 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; @@ -567,7 +579,9 @@ GFXD3D11Shader::GFXD3D11Shader() if( smD3DInclude == NULL ) smD3DInclude = new gfxD3D11Include; - + globalAdded = false; + globalOffset = 0; + globalSize = 0; } //------------------------------------------------------------------------------ @@ -823,6 +837,7 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection *refTable, D3D11_SHADER_DESC shaderDesc; refTable->GetDesc(&shaderDesc); + bool globalBuffer = false; // we loop through and account for the most common data types. for (U32 i = 0; i < shaderDesc.BoundResources; i++) { @@ -836,9 +851,14 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection *refTable, if (desc.name.find("$") != 0) desc.name = String::ToString("$%s", desc.name.c_str()); + if (String::compare(desc.name, "$Globals") == 0 || String::compare(desc.name, "$Params") == 0) + { + globalBuffer = true; + } + desc.constType = GFXSCT_ConstBuffer; desc.bindPoint = shaderInputBind.BindPoint; - desc.shaderStage = shaderStage; + desc.shaderStage = globalBuffer ? SHADER_STAGE::ALL_SHADERS : shaderStage; desc.samplerReg = -1; ID3D11ShaderReflectionConstantBuffer* constantBuffer = refTable->GetConstantBufferByName(shaderInputBind.Name); D3D11_SHADER_BUFFER_DESC constantBufferDesc; @@ -850,7 +870,13 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection *refTable, #endif // push back our const buffer as a descriptor, this also marks the start of a buffer. desc.size = constantBufferDesc.Size; - mShaderConsts.push_back(desc); + + globalSize += desc.size; + + if(globalBuffer && !globalAdded) + mShaderConsts.push_back(desc); + else if (!globalBuffer) + mShaderConsts.push_back(desc); // now loop vars and add them to mShaderConsts. for (U32 j = 0; j < constantBufferDesc.Variables; j++) @@ -869,10 +895,10 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection *refTable, // set the bind point to the same as the const buffer. varDesc.bindPoint = desc.bindPoint; - varDesc.offset = shaderVarDesc.StartOffset; + varDesc.offset = globalBuffer ? globalOffset + shaderVarDesc.StartOffset : shaderVarDesc.StartOffset; varDesc.arraySize = mMax(shaderTypeDesc.Elements, 1); varDesc.size = shaderVarDesc.Size; - varDesc.shaderStage = shaderStage; + varDesc.shaderStage = globalBuffer ? SHADER_STAGE::ALL_SHADERS : shaderStage; varDesc.samplerReg = -1; #ifdef D3D11_DEBUG_SPEW @@ -925,6 +951,8 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection *refTable, mShaderConsts.push_back(varDesc); } + + globalOffset += desc.size; } else if (shaderInputBind.Type == D3D_SIT_TEXTURE) { @@ -1037,6 +1065,10 @@ void GFXD3D11Shader::_buildShaderConstantHandles() Vector buf; buf.setSize(desc.size); + + if (desc.shaderStage == SHADER_STAGE::ALL_SHADERS) + buf.setSize(globalSize); + // new buffer with our size. mBuffers[bufKey] = buf; diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.h b/Engine/source/gfx/D3D11/gfxD3D11Shader.h index 2269a8603..1ca1afabc 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.h +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.h @@ -35,6 +35,7 @@ class GFXD3D11Shader; enum SHADER_STAGE { + ALL_SHADERS, VERTEX_SHADER, PIXEL_SHADER, GEOMETRY_SHADER, @@ -229,6 +230,10 @@ protected: virtual void _buildShaderConstantHandles(); void _buildInstancingShaderConstantHandles(); + + bool globalAdded; + U32 globalOffset; + U32 globalSize; }; From 6355e122d26dbdba099c1546c28331b40cf2d823 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Sat, 24 Feb 2024 19:52:35 +0000 Subject: [PATCH 14/53] compare before change check to see if data is different in internal sets before changing values --- Engine/source/gfx/D3D11/gfxD3D11Shader.cpp | 52 ++++++++++++++-------- Engine/source/gfx/D3D11/gfxD3D11Shader.h | 1 - 2 files changed, 33 insertions(+), 20 deletions(-) diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp index 184248974..d23585579 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp @@ -251,7 +251,10 @@ void GFXD3D11ShaderConstBuffer::internalSet(GFXShaderConstHandle* handle, const if (_dxHandle->mInstancingConstant) buf = mInstPtr + _dxHandle->mOffset; - dMemcpy(buf, ¶m, sizeof(ConstType)); + if (dMemcmp(buf, ¶m, sizeof(ConstType)) != 0) + { + dMemcpy(buf, ¶m, sizeof(ConstType)); + } } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray& fv) @@ -307,12 +310,12 @@ void GFXD3D11ShaderConstBuffer::internalSet(GFXShaderConstHandle* handle, const const BufferKey bufDesc(_dxHandle->mBinding, (SHADER_STAGE)_dxHandle->mStage); U8* buf = mBufferMap[bufDesc].data; 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(); - } + U32 size = fv.getElementSize() * fv.size(); + if (dMemcmp(buf + _dxHandle->mOffset, fvBuffer, size) != 0) + { + dMemcpy(buf + _dxHandle->mOffset, fvBuffer, size); + } } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF& mat, const GFXShaderConstType matrixType) @@ -348,7 +351,10 @@ void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF& if (matrixType == GFXSCT_Float4x4) { - dMemcpy(buf, &transposed, sizeof(MatrixF)); + if (dMemcmp(buf + _dxHandle->mOffset, &transposed, sizeof(MatrixF)) != 0) + { + dMemcpy(buf + _dxHandle->mOffset, &transposed, sizeof(MatrixF)); + } return; } @@ -369,7 +375,10 @@ void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF& break; } - dMemcpy(buf, (const F32*)transposed, csize); + if (dMemcmp(buf + _dxHandle->mOffset, &transposed, csize) != 0) + { + dMemcpy(buf + _dxHandle->mOffset, &transposed, csize); + } } @@ -407,7 +416,10 @@ void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF* if (matrixType == GFXSCT_Float4x4) { - dMemcpy(buf + _dxHandle->mOffset, transposed.address(), _dxHandle->getSize()); + if (dMemcmp(buf + _dxHandle->mOffset, transposed.address(), sizeof(MatrixF) * arraySize) != 0) + { + dMemcpy(buf + _dxHandle->mOffset, transposed.address(), sizeof(MatrixF) * arraySize); + } return; } @@ -430,7 +442,10 @@ void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF* for (int i = 0; i < arraySize; i++) { - dMemcpy(buf + _dxHandle->mOffset + (i * csize), transposed[i], csize); + if (dMemcmp(buf + _dxHandle->mOffset + (i * csize), transposed[i], csize) != 0) + { + dMemcpy(buf + _dxHandle->mOffset + (i * csize), transposed[i], csize); + } } } @@ -580,7 +595,6 @@ GFXD3D11Shader::GFXD3D11Shader() smD3DInclude = new gfxD3D11Include; globalAdded = false; - globalOffset = 0; globalSize = 0; } @@ -836,14 +850,13 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection *refTable, D3D11_SHADER_DESC shaderDesc; refTable->GetDesc(&shaderDesc); - - bool globalBuffer = false; // we loop through and account for the most common data types. for (U32 i = 0; i < shaderDesc.BoundResources; i++) { GFXShaderConstDesc desc; D3D11_SHADER_INPUT_BIND_DESC shaderInputBind; refTable->GetResourceBindingDesc(i, &shaderInputBind); + bool globalBuffer = false; if (shaderInputBind.Type == D3D_SIT_CBUFFER) { @@ -870,11 +883,12 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection *refTable, #endif // push back our const buffer as a descriptor, this also marks the start of a buffer. desc.size = constantBufferDesc.Size; - - globalSize += desc.size; - - if(globalBuffer && !globalAdded) + + if (globalBuffer && !globalAdded) + { mShaderConsts.push_back(desc); + globalAdded = true; + } else if (!globalBuffer) mShaderConsts.push_back(desc); @@ -895,7 +909,7 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection *refTable, // set the bind point to the same as the const buffer. varDesc.bindPoint = desc.bindPoint; - varDesc.offset = globalBuffer ? globalOffset + shaderVarDesc.StartOffset : shaderVarDesc.StartOffset; + varDesc.offset = (globalBuffer && shaderStage != SHADER_STAGE::VERTEX_SHADER) ? globalSize + shaderVarDesc.StartOffset : shaderVarDesc.StartOffset; varDesc.arraySize = mMax(shaderTypeDesc.Elements, 1); varDesc.size = shaderVarDesc.Size; varDesc.shaderStage = globalBuffer ? SHADER_STAGE::ALL_SHADERS : shaderStage; @@ -952,7 +966,7 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection *refTable, mShaderConsts.push_back(varDesc); } - globalOffset += desc.size; + globalSize += desc.size; } else if (shaderInputBind.Type == D3D_SIT_TEXTURE) { diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.h b/Engine/source/gfx/D3D11/gfxD3D11Shader.h index 1ca1afabc..e4a2639cd 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.h +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.h @@ -232,7 +232,6 @@ protected: bool globalAdded; - U32 globalOffset; U32 globalSize; }; From 8c01a1a85bdfddbb352a0121371e17b73cb0dfee Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Sun, 25 Feb 2024 13:39:22 +0000 Subject: [PATCH 15/53] Working This commit has everything rendering kind of correctly, but the colours seem off from lighting. --- Engine/source/gfx/D3D11/gfxD3D11Shader.cpp | 247 ++++++++++----------- Engine/source/gfx/D3D11/gfxD3D11Shader.h | 7 +- 2 files changed, 121 insertions(+), 133 deletions(-) diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp index d23585579..5216a5b23 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp @@ -112,7 +112,7 @@ GFXD3D11ShaderConstHandle::GFXD3D11ShaderConstHandle(GFXD3D11Shader* shader, mDesc(desc), mStage((SHADER_STAGE)desc.shaderStage), mOffset(desc.offset), - mSize(desc.size * desc.arraySize), + mSize(desc.size), mBinding(desc.bindPoint), mSampler(desc.samplerReg), mInstancingConstant(false) @@ -246,14 +246,32 @@ void GFXD3D11ShaderConstBuffer::internalSet(GFXShaderConstHandle* handle, const AssertFatal(mShader == _dxHandle->mShader, "GFXD3D11ShaderConstBuffer::internalSet - Should only set handles which are owned by our shader"); const BufferKey bufDesc(_dxHandle->mBinding, (SHADER_STAGE)_dxHandle->mStage); - U8* buf = mBufferMap[bufDesc].data + _dxHandle->mOffset; + U8* buf = mBufferMap[bufDesc].data; if (_dxHandle->mInstancingConstant) buf = mInstPtr + _dxHandle->mOffset; - if (dMemcmp(buf, ¶m, sizeof(ConstType)) != 0) + dMemcpy(buf + _dxHandle->mOffset, ¶m, sizeof(ConstType)); +} + +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(!_dxHandle->mInstancingConstant, "GFXD3D11ShaderConstBuffer::internalSet - Instancing not supported for array"); + const BufferKey bufDesc(_dxHandle->mBinding, (SHADER_STAGE)_dxHandle->mStage); + U8* buf = mBufferMap[bufDesc].data; + const U8* fvBuffer = static_cast(fv.getBuffer()); + U32 size = fv.getElementSize() * fv.size(); + + if (dMemcmp(buf + _dxHandle->mOffset, fvBuffer, _dxHandle->mSize) != 0) { - dMemcpy(buf, ¶m, sizeof(ConstType)); + dMemcpy(buf + _dxHandle->mOffset, fvBuffer, _dxHandle->mSize); } } @@ -297,27 +315,6 @@ void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedA 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(!_dxHandle->mInstancingConstant, "GFXD3D11ShaderConstBuffer::internalSet - Instancing not supported for array"); - const BufferKey bufDesc(_dxHandle->mBinding, (SHADER_STAGE)_dxHandle->mStage); - U8* buf = mBufferMap[bufDesc].data; - const U8* fvBuffer = static_cast(fv.getBuffer()); - U32 size = fv.getElementSize() * fv.size(); - - if (dMemcmp(buf + _dxHandle->mOffset, fvBuffer, size) != 0) - { - dMemcpy(buf + _dxHandle->mOffset, fvBuffer, size); - } -} - void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF& mat, const GFXShaderConstType matrixType) { AssertFatal(handle, "Handle is NULL!" ); @@ -416,9 +413,9 @@ void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF* if (matrixType == GFXSCT_Float4x4) { - if (dMemcmp(buf + _dxHandle->mOffset, transposed.address(), sizeof(MatrixF) * arraySize) != 0) + if (dMemcmp(buf + _dxHandle->mOffset, transposed.begin(), sizeof(MatrixF) * arraySize) != 0) { - dMemcpy(buf + _dxHandle->mOffset, transposed.address(), sizeof(MatrixF) * arraySize); + dMemcpy(buf + _dxHandle->mOffset, transposed.begin(), sizeof(MatrixF) * arraySize); } return; } @@ -468,10 +465,11 @@ void GFXD3D11ShaderConstBuffer::addBuffer(U32 bufBindingPoint, SHADER_STAGE shad return; // new buffer with our size. - mBufferMap[bufKey].data = new U8[size]; - dMemset(mBufferMap[bufKey].data, 0, size); - // always dirty on new. + U8* buf = new U8[size]; + dMemset(buf, 0, size); + mBufferMap[bufKey].data = buf; mBufferMap[bufKey].size = size; + // always dirty on new. mBufferMap[bufKey].isDirty = true; D3D11_BUFFER_DESC cbDesc; @@ -483,7 +481,7 @@ void GFXD3D11ShaderConstBuffer::addBuffer(U32 bufBindingPoint, SHADER_STAGE shad cbDesc.StructureByteStride = 0; HRESULT hr; - hr = D3D11DEVICE->CreateBuffer(&cbDesc, NULL, &mBoundConstantBuffers[bufBindingPoint]); + hr = D3D11DEVICE->CreateBuffer(&cbDesc, NULL, &mBoundConstantBuffers[(U32)shaderStage + bufBindingPoint]); if (FAILED(hr)) { @@ -505,48 +503,40 @@ void GFXD3D11ShaderConstBuffer::activate( GFXD3D11ShaderConstBuffer *prevShaderB const BufferKey thisBufferDesc = i->key; ConstantBuffer thisBuff = i->value; - const ConstantBuffer prevBuffer = prevShaderBuffer->mBufferMap[i->key]; - - if (prevBuffer.data && !prevBuffer.isDirty) + if (prevShaderBuffer != this) { - if (prevBuffer.size != thisBuff.size) - { - thisBuff.isDirty = true; - } - if (dMemcmp(prevBuffer.data, thisBuff.data, thisBuff.size) != 0) + const ConstantBuffer prevBuffer = prevShaderBuffer->mBufferMap[i->key]; + + if (prevBuffer.data && !prevBuffer.isDirty) { - thisBuff.isDirty = true; + if (prevBuffer.size != thisBuff.size) + { + thisBuff.isDirty = true; + } + + if (dMemcmp(prevBuffer.data, thisBuff.data, thisBuff.size) != 0) + { + thisBuff.isDirty = true; + } + else + { + thisBuff.isDirty = false; + } } else { - thisBuff.isDirty = false; + thisBuff.isDirty = true; } } - else - { - thisBuff.isDirty = true; - } if (thisBuff.data && thisBuff.isDirty) { - D3D11DEVICECONTEXT->UpdateSubresource(mBoundConstantBuffers[thisBufferDesc.key1], 0, NULL, thisBuff.data, thisBuff.size, 0); + D3D11DEVICECONTEXT->UpdateSubresource(mBoundConstantBuffers[(U32)thisBufferDesc.key2 + thisBufferDesc.key1], 0, NULL, thisBuff.data, thisBuff.size, 0); bufRanges[thisBufferDesc.key2].addSlot(thisBufferDesc.key1); } } - if (bufRanges[SHADER_STAGE::ALL_SHADERS].isValid()) - { - const U32 bufStartSlot = bufRanges[SHADER_STAGE::ALL_SHADERS].mBufMin; - const U32 numBufs = bufRanges[SHADER_STAGE::ALL_SHADERS].mBufMax - bufRanges[SHADER_STAGE::ALL_SHADERS].mBufMin + 1; - ID3D11Buffer** globalBuffer = mBoundConstantBuffers + bufStartSlot; - - if(mShader->mVertShader) - D3D11DEVICECONTEXT->VSSetConstantBuffers(bufStartSlot, numBufs, globalBuffer); - if(mShader->mPixShader) - D3D11DEVICECONTEXT->PSSetConstantBuffers(bufStartSlot, numBufs, globalBuffer); - } - if (mShader->mVertShader && bufRanges[SHADER_STAGE::VERTEX_SHADER].isValid()) { const U32 bufStartSlot = bufRanges[SHADER_STAGE::VERTEX_SHADER].mBufMin; @@ -560,7 +550,7 @@ void GFXD3D11ShaderConstBuffer::activate( GFXD3D11ShaderConstBuffer *prevShaderB { 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; + ID3D11Buffer** psBuffers = mBoundConstantBuffers + bufStartSlot + (U32)SHADER_STAGE::PIXEL_SHADER; D3D11DEVICECONTEXT->PSSetConstantBuffers(bufStartSlot, numBufs, psBuffers); } @@ -572,10 +562,22 @@ void GFXD3D11ShaderConstBuffer::onShaderReload( GFXD3D11Shader *shader ) { AssertFatal( shader == mShader, "GFXD3D11ShaderConstBuffer::onShaderReload is hosed!" ); + for (U32 i = 0; i < 16; i++) + { + SAFE_RELEASE(mBoundConstantBuffers[i]); + } + for (BufferMap::Iterator i = mBufferMap.begin(); i != mBufferMap.end(); i++) { delete[] i->value.data; } + mBufferMap.clear(); + + for (GFXD3D11Shader::BufferMap::Iterator i = shader->mBuffers.begin(); i != shader->mBuffers.end(); ++i) + { + // add our buffer descriptions to the full const buffer. + this->addBuffer(i->value.bindPoint, (SHADER_STAGE)i->value.shaderStage, i->value.size); + } // Set the lost state. mWasLost = true; @@ -593,9 +595,6 @@ GFXD3D11Shader::GFXD3D11Shader() if( smD3DInclude == NULL ) smD3DInclude = new gfxD3D11Include; - - globalAdded = false; - globalSize = 0; } //------------------------------------------------------------------------------ @@ -841,56 +840,53 @@ bool GFXD3D11Shader::_compileShader( const Torque::Path &filePath, return result; } -void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection *refTable, - SHADER_STAGE shaderStage) +void GFXD3D11Shader::_getShaderConstants(ID3D11ShaderReflection* refTable, + SHADER_STAGE shaderStage) { - PROFILE_SCOPE( GFXD3D11Shader_GetShaderConstants ); + PROFILE_SCOPE(GFXD3D11Shader_GetShaderConstants); AssertFatal(refTable, "NULL constant table not allowed, is this an assembly shader?"); D3D11_SHADER_DESC shaderDesc; - refTable->GetDesc(&shaderDesc); + if (refTable->GetDesc(&shaderDesc) != S_OK) + { + AssertFatal(false, "Shader Reflection table unable to be created"); + } // we loop through and account for the most common data types. - for (U32 i = 0; i < shaderDesc.BoundResources; i++) + + U32 bufferOffset = 0; + for (U32 i = 0; i < shaderDesc.ConstantBuffers; i++) { GFXShaderConstDesc desc; - D3D11_SHADER_INPUT_BIND_DESC shaderInputBind; - refTable->GetResourceBindingDesc(i, &shaderInputBind); + ID3D11ShaderReflectionConstantBuffer* constantBuffer = refTable->GetConstantBufferByIndex(i); + D3D11_SHADER_BUFFER_DESC constantBufferDesc; + bool globalBuffer = false; - - if (shaderInputBind.Type == D3D_SIT_CBUFFER) + if (constantBuffer->GetDesc(&constantBufferDesc) == S_OK) { - desc.name = String(shaderInputBind.Name); - if (desc.name.find("$") != 0) - desc.name = String::ToString("$%s", desc.name.c_str()); - + desc.name = String(constantBufferDesc.Name); + desc.size = constantBufferDesc.Size; + // we join global and params into 1 buffer. if (String::compare(desc.name, "$Globals") == 0 || String::compare(desc.name, "$Params") == 0) { + desc.name = "$defaultTorqueBuffer_" + String::ToString((U32)shaderStage); globalBuffer = true; } desc.constType = GFXSCT_ConstBuffer; - desc.bindPoint = shaderInputBind.BindPoint; - desc.shaderStage = globalBuffer ? SHADER_STAGE::ALL_SHADERS : shaderStage; + desc.shaderStage = shaderStage; desc.samplerReg = -1; - ID3D11ShaderReflectionConstantBuffer* constantBuffer = refTable->GetConstantBufferByName(shaderInputBind.Name); - D3D11_SHADER_BUFFER_DESC constantBufferDesc; + // get our binding point. + D3D11_SHADER_INPUT_BIND_DESC shaderInputBind; + refTable->GetResourceBindingDescByName(constantBufferDesc.Name, &shaderInputBind); + desc.bindPoint = shaderInputBind.BindPoint; - constantBuffer->GetDesc(&constantBufferDesc); - -#ifdef D3D11_DEBUG_SPEW - Con::printf("Constant Buffer Name: %s", constantBufferDesc.Name); -#endif - // push back our const buffer as a descriptor, this also marks the start of a buffer. - desc.size = constantBufferDesc.Size; - - if (globalBuffer && !globalAdded) + BufferMap::Iterator buffer = mBuffers.find(desc.name); + // already added? + if (buffer == mBuffers.end()) { - mShaderConsts.push_back(desc); - globalAdded = true; + mBuffers[desc.name] = desc; } - else if (!globalBuffer) - mShaderConsts.push_back(desc); // now loop vars and add them to mShaderConsts. for (U32 j = 0; j < constantBufferDesc.Variables; j++) @@ -909,10 +905,10 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection *refTable, // set the bind point to the same as the const buffer. varDesc.bindPoint = desc.bindPoint; - varDesc.offset = (globalBuffer && shaderStage != SHADER_STAGE::VERTEX_SHADER) ? globalSize + shaderVarDesc.StartOffset : shaderVarDesc.StartOffset; + varDesc.offset = globalBuffer ? bufferOffset + shaderVarDesc.StartOffset : shaderVarDesc.StartOffset; varDesc.arraySize = mMax(shaderTypeDesc.Elements, 1); varDesc.size = shaderVarDesc.Size; - varDesc.shaderStage = globalBuffer ? SHADER_STAGE::ALL_SHADERS : shaderStage; + varDesc.shaderStage = shaderStage; varDesc.samplerReg = -1; #ifdef D3D11_DEBUG_SPEW @@ -949,12 +945,12 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection *refTable, switch (shaderTypeDesc.Rows) { - case 3: - varDesc.constType = shaderTypeDesc.Columns == 4 ? GFXSCT_Float3x4 : GFXSCT_Float3x3; - break; - case 4: - varDesc.constType = shaderTypeDesc.Columns == 3 ? GFXSCT_Float3x3 : GFXSCT_Float4x4; - break; + case 3: + varDesc.constType = shaderTypeDesc.Columns == 4 ? GFXSCT_Float3x4 : GFXSCT_Float3x3; + break; + case 4: + varDesc.constType = shaderTypeDesc.Columns == 3 ? GFXSCT_Float3x3 : GFXSCT_Float4x4; + break; } } else if (shaderTypeDesc.Class == D3D_SVC_STRUCT) @@ -965,10 +961,30 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection *refTable, mShaderConsts.push_back(varDesc); } - - globalSize += desc.size; + } - else if (shaderInputBind.Type == D3D_SIT_TEXTURE) + else + { + AssertFatal(false, "Unable to get shader constant description! (may need more elements of constantDesc"); + } + + if(globalBuffer) + bufferOffset += desc.size; + } + + BufferMap::Iterator buf = mBuffers.find("$defaultTorqueBuffer_" + String::ToString((U32)shaderStage)); + if (buf != mBuffers.end()) + { + buf->value.size += bufferOffset; + } + + for (U32 i = 0; i < shaderDesc.BoundResources; i++) + { + GFXShaderConstDesc desc; + D3D11_SHADER_INPUT_BIND_DESC shaderInputBind; + refTable->GetResourceBindingDesc(i, &shaderInputBind); + + if (shaderInputBind.Type == D3D_SIT_TEXTURE) { /*switch (shaderInputBind.Dimension) { @@ -1067,29 +1083,6 @@ void GFXD3D11Shader::_buildShaderConstantHandles() for (U32 i = 0; i < mShaderConsts.size(); i++) { GFXShaderConstDesc& desc = mShaderConsts[i]; - - if (desc.constType == GFXSCT_ConstBuffer) - { - const BufferKey bufKey(desc.bindPoint, (SHADER_STAGE)desc.shaderStage); - - BufferMap::Iterator buffer = mBuffers.find(bufKey); - // already added? pass... - if (buffer != mBuffers.end()) - continue; - - Vector buf; - buf.setSize(desc.size); - - if (desc.shaderStage == SHADER_STAGE::ALL_SHADERS) - buf.setSize(globalSize); - - // new buffer with our size. - mBuffers[bufKey] = buf; - - // 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. @@ -1179,7 +1172,7 @@ GFXShaderConstBufferRef GFXD3D11Shader::allocConstBuffer() for (BufferMap::Iterator i = mBuffers.begin(); i != mBuffers.end(); ++i) { // add our buffer descriptions to the full const buffer. - buffer->addBuffer(i->key.key1,i->key.key2, i->value.size()); + buffer->addBuffer(i->value.bindPoint, (SHADER_STAGE)i->value.shaderStage, i->value.size); } mActiveBuffers.push_back( buffer ); diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.h b/Engine/source/gfx/D3D11/gfxD3D11Shader.h index e4a2639cd..35ce62a17 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.h +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.h @@ -35,7 +35,6 @@ class GFXD3D11Shader; enum SHADER_STAGE { - ALL_SHADERS, VERTEX_SHADER, PIXEL_SHADER, GEOMETRY_SHADER, @@ -186,7 +185,7 @@ class GFXD3D11Shader : public GFXShader public: typedef Map HandleMap; - typedef Map> BufferMap; + typedef Map BufferMap; GFXD3D11Shader(); virtual ~GFXD3D11Shader(); @@ -229,10 +228,6 @@ protected: // This is used in both cases virtual void _buildShaderConstantHandles(); void _buildInstancingShaderConstantHandles(); - - - bool globalAdded; - U32 globalSize; }; From af29a2af0a9c886c6a0e10a4b8c16b862f6540e1 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Sun, 25 Feb 2024 15:26:48 +0000 Subject: [PATCH 16/53] Remove code duplication Removed code duplication, all types can be routed through the same function apart from matrices. --- Engine/source/gfx/D3D11/gfxD3D11Shader.cpp | 265 ++++++++++----------- Engine/source/gfx/D3D11/gfxD3D11Shader.h | 8 +- 2 files changed, 131 insertions(+), 142 deletions(-) diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp index 5216a5b23..650b93cc8 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp @@ -175,34 +175,134 @@ GFXShader* GFXD3D11ShaderConstBuffer::getShader() return mShader; } +void GFXD3D11ShaderConstBuffer::setMatrix(GFXShaderConstHandle* handle, const U32 inSize, const void* data) +{ + 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"); + const BufferKey bufDesc(_dxHandle->mBinding, (SHADER_STAGE)_dxHandle->mStage); + U8* buf = mBufferMap[bufDesc].data; + + if (_dxHandle->mDesc.constType == GFXSCT_Float4x4) + { + // Special case, we can just blast this guy. + if (dMemcmp(buf + _dxHandle->mDesc.offset, data, inSize) != 0) + { + dMemcpy(buf + _dxHandle->mDesc.offset, data, inSize); + } + + return; + } + else + { + PROFILE_SCOPE(GFXD3D11ConstBufferLayout_setMatrix_not4x4); + + // Figure out how big of a chunk we are copying. We're going to copy 4 columns by N rows of data + U32 csize; + switch (_dxHandle->mDesc.constType) + { + 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: + AssertFatal(false, "Unhandled case!"); + return; + break; + } + + // Loop through and copy + bool ret = false; + U8* currDestPointer = buf + _dxHandle->mDesc.offset; + const U8* currSourcePointer = static_cast(data); + const U8* endData = currSourcePointer + inSize; + while (currSourcePointer < endData) + { + if (dMemcmp(currDestPointer, currSourcePointer, csize) != 0) + { + dMemcpy(currDestPointer, currSourcePointer, csize); + ret = true; + } + + currDestPointer += csize; + currSourcePointer += sizeof(MatrixF); + } + } +} + +void GFXD3D11ShaderConstBuffer::internalSet(GFXShaderConstHandle* handle, const U32 inSize, const void* data) +{ + 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"); + + S32 size = inSize; + switch (_dxHandle->mDesc.constType) + { + case GFXSCT_Float2x2: + case GFXSCT_Float3x3: + case GFXSCT_Float4x3: + case GFXSCT_Float4x4: + setMatrix(handle, size, data); + return; + break; + // TODO add other AlignedVector here + case GFXSCT_Float2: + if (size > sizeof(Point2F)) + size = _dxHandle->mDesc.size; + default: + break; + } + + const BufferKey bufDesc(_dxHandle->mBinding, (SHADER_STAGE)_dxHandle->mStage); + U8* buf = mBufferMap[bufDesc].data; + + + if (dMemcmp(buf + _dxHandle->mDesc.offset, data, size) != 0) + { + dMemcpy(buf + _dxHandle->mDesc.offset, data, size); + } +} + void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const F32 fv) { - internalSet(handle, fv); + internalSet(handle, sizeof(F32), &fv); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const Point2F& fv) { - internalSet(handle, fv); + internalSet(handle, sizeof(Point2F), &fv); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const Point3F& fv) { - internalSet(handle, fv); + internalSet(handle, sizeof(Point3F), &fv); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const Point4F& fv) { - internalSet(handle, fv); + internalSet(handle, sizeof(Point4F), &fv); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const PlaneF& fv) { - internalSet(handle, fv); + internalSet(handle, sizeof(PlaneF), &fv); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const LinearColorF& fv) { - internalSet(handle, fv); + internalSet(handle, sizeof(Point4F), &fv); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const S32 fv) @@ -216,103 +316,62 @@ void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const S32 fv) if ( ((GFXD3D11ShaderConstHandle*)handle)->isSampler() ) return; - internalSet(handle, fv); + internalSet(handle, sizeof(S32), &fv); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const Point2I& fv) { - internalSet(handle, fv); + internalSet(handle, sizeof(Point2I), &fv); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const Point3I& fv) { - internalSet(handle, fv); + internalSet(handle, sizeof(Point3I), &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"); - - const BufferKey bufDesc(_dxHandle->mBinding, (SHADER_STAGE)_dxHandle->mStage); - U8* buf = mBufferMap[bufDesc].data; - - if (_dxHandle->mInstancingConstant) - buf = mInstPtr + _dxHandle->mOffset; - - dMemcpy(buf + _dxHandle->mOffset, ¶m, sizeof(ConstType)); -} - -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(!_dxHandle->mInstancingConstant, "GFXD3D11ShaderConstBuffer::internalSet - Instancing not supported for array"); - const BufferKey bufDesc(_dxHandle->mBinding, (SHADER_STAGE)_dxHandle->mStage); - U8* buf = mBufferMap[bufDesc].data; - const U8* fvBuffer = static_cast(fv.getBuffer()); - U32 size = fv.getElementSize() * fv.size(); - - if (dMemcmp(buf + _dxHandle->mOffset, fvBuffer, _dxHandle->mSize) != 0) - { - dMemcpy(buf + _dxHandle->mOffset, fvBuffer, _dxHandle->mSize); - } + internalSet(handle, sizeof(Point4I), &fv); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray& fv) { - internalSet(handle, fv); + internalSet(handle, fv.getElementSize() * fv.size(), fv.getBuffer()); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray& fv) { - internalSet(handle, fv); + internalSet(handle, fv.getElementSize() * fv.size(), fv.getBuffer()); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray& fv) { - internalSet(handle, fv); + internalSet(handle, fv.getElementSize() * fv.size(), fv.getBuffer()); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray& fv) { - internalSet(handle, fv); + internalSet(handle, fv.getElementSize() * fv.size(), fv.getBuffer()); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray& fv) { - internalSet(handle, fv); + internalSet(handle, fv.getElementSize() * fv.size(), fv.getBuffer()); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray& fv) { - internalSet(handle, fv); + internalSet(handle, fv.getElementSize() * fv.size(), fv.getBuffer()); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray& fv) { - internalSet(handle, fv); + internalSet(handle, fv.getElementSize() * fv.size(), fv.getBuffer()); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray& fv) { - internalSet(handle, fv); + internalSet(handle, fv.getElementSize() * fv.size(), fv.getBuffer()); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF& mat, const GFXShaderConstType matrixType) @@ -324,8 +383,6 @@ void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF& const GFXD3D11ShaderConstHandle* _dxHandle = static_cast(handle); AssertFatal(!_dxHandle->isSampler(), "Handle is sampler constant!" ); AssertFatal(_dxHandle->mShader == mShader, "Mismatched shaders!"); - const BufferKey bufDesc(_dxHandle->mBinding, (SHADER_STAGE)_dxHandle->mStage); - U8* buf = mBufferMap[bufDesc].data; MatrixF transposed; if (matrixType == GFXSCT_Float4x3) @@ -346,37 +403,7 @@ void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF& return; } - if (matrixType == GFXSCT_Float4x4) - { - if (dMemcmp(buf + _dxHandle->mOffset, &transposed, sizeof(MatrixF)) != 0) - { - dMemcpy(buf + _dxHandle->mOffset, &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; - } - - if (dMemcmp(buf + _dxHandle->mOffset, &transposed, csize) != 0) - { - dMemcpy(buf + _dxHandle->mOffset, &transposed, csize); - } - + internalSet(handle, sizeof(MatrixF), &transposed); } void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF* mat, const U32 arraySize, const GFXShaderConstType matrixType) @@ -389,10 +416,6 @@ void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF* AssertFatal(!_dxHandle->isSampler(), "Handle is sampler constant!"); AssertFatal(_dxHandle->mShader == mShader, "Mismatched shaders!"); - const BufferKey bufDesc(_dxHandle->mBinding, (SHADER_STAGE)_dxHandle->mStage); - - U8* buf = mBufferMap[bufDesc].data; - static Vector transposed; if (arraySize > transposed.size()) transposed.setSize(arraySize); @@ -411,39 +434,7 @@ void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF* if (_dxHandle->mInstancingConstant) return; - if (matrixType == GFXSCT_Float4x4) - { - if (dMemcmp(buf + _dxHandle->mOffset, transposed.begin(), sizeof(MatrixF) * arraySize) != 0) - { - dMemcpy(buf + _dxHandle->mOffset, transposed.begin(), sizeof(MatrixF) * arraySize); - } - 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++) - { - if (dMemcmp(buf + _dxHandle->mOffset + (i * csize), transposed[i], csize) != 0) - { - dMemcpy(buf + _dxHandle->mOffset + (i * csize), transposed[i], csize); - } - } + internalSet(handle, sizeof(MatrixF) * arraySize, transposed.begin()); } @@ -672,7 +663,7 @@ bool GFXD3D11Shader::_compileShader( const Torque::Path &filePath, ID3D11ShaderReflection* reflectionTable = NULL; #ifdef TORQUE_GFX_VISUAL_DEBUG //for use with NSight, GPU Perf studio, VS graphics debugger - U32 flags = D3DCOMPILE_DEBUG | D3DCOMPILE_ENABLE_STRICTNESS | D3DCOMPILE_PREFER_FLOW_CONTROL | D3DCOMPILE_SKIP_OPTIMIZATION; + U32 flags = D3DCOMPILE_DEBUG | D3DCOMPILE_ENABLE_STRICTNESS | D3DCOMPILE_PREFER_FLOW_CONTROL | D3DCOMPILE_SKIP_OPTIMIZATION; #elif defined(TORQUE_DEBUG) //debug build U32 flags = D3DCOMPILE_DEBUG | D3DCOMPILE_ENABLE_STRICTNESS | D3DCOMPILE_WARNINGS_ARE_ERRORS; #else //release build @@ -791,15 +782,15 @@ bool GFXD3D11Shader::_compileShader( const Torque::Path &filePath, AssertFatal(false, "D3D11Shader::_compilershader- failed to create shader"); } - if(res == S_OK) + if(res == S_OK) { - HRESULT reflectionResult = D3DReflect(code->GetBufferPointer(), code->GetBufferSize(), IID_ID3D11ShaderReflection, (void**)&reflectionTable); - if(FAILED(reflectionResult)) - AssertFatal(false, "D3D11Shader::_compilershader - Failed to get shader reflection table interface"); - } + HRESULT reflectionResult = D3DReflect(code->GetBufferPointer(), code->GetBufferSize(), IID_ID3D11ShaderReflection, (void**)&reflectionTable); + if(FAILED(reflectionResult)) + AssertFatal(false, "D3D11Shader::_compilershader - Failed to get shader reflection table interface"); + } - if(res == S_OK) - _getShaderConstants(reflectionTable, shaderStage); + if(res == S_OK) + _getShaderConstants(reflectionTable, shaderStage); if(FAILED(res) && smLogErrors) Con::errorf("GFXD3D11Shader::_compileShader - Unable to create shader for '%s'.", filePath.getFullPath().c_str()); diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.h b/Engine/source/gfx/D3D11/gfxD3D11Shader.h index 35ce62a17..c7aed3a7b 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.h +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.h @@ -163,11 +163,9 @@ protected: WeakRefPtr mShader; BufferMap mBufferMap; - template - void internalSet(GFXShaderConstHandle* handle, const ConstType& param); - - template - void internalSet(GFXShaderConstHandle* handle, const AlignedArray& fv); + void setMatrix(GFXShaderConstHandle* handle, const U32 inSize, const void* data); + void internalSet(GFXShaderConstHandle* handle, const U32 inSize, const void* data); + // we probably want this to be GFXDevice and not per shader. ID3D11Buffer* mBoundConstantBuffers[16]; From 25bc9cf354cf0eea103cec203328ad83adc622b8 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Sun, 25 Feb 2024 22:51:37 +0000 Subject: [PATCH 17/53] stumped buffers seem to be being added correctly, but for whatever reason render is not correct =/ --- Engine/source/gfx/D3D11/gfxD3D11Shader.cpp | 115 ++++++++++++--------- Engine/source/gfx/D3D11/gfxD3D11Shader.h | 2 +- Engine/source/gfx/gfxShader.h | 2 +- 3 files changed, 70 insertions(+), 49 deletions(-) diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp index 650b93cc8..1aa32a48d 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp @@ -150,22 +150,28 @@ GFXD3D11ShaderConstBuffer::GFXD3D11ShaderConstBuffer( GFXD3D11Shader* shader) mShader = shader; mDeviceContext = D3D11DEVICECONTEXT; - for (U32 i = 0; i < 16; i++) + for (U32 i = 0; i < 6; i++) { - mBoundConstantBuffers[i] = NULL; + for (U32 j = 0; j < 16; j++) + { + mBoundConstantBuffers[i][j] = NULL; + } } + } GFXD3D11ShaderConstBuffer::~GFXD3D11ShaderConstBuffer() { mBufferMap.clear(); - for (U32 i = 0; i < 16; i++) + for (U32 i = 0; i < 6; i++) { - SAFE_RELEASE(mBoundConstantBuffers[i]); + for (U32 j = 0; j < 16; j++) + { + SAFE_RELEASE(mBoundConstantBuffers[i][j]); + } } - if (mShader) mShader->_unlinkBuffer(this); } @@ -246,8 +252,14 @@ void GFXD3D11ShaderConstBuffer::internalSet(GFXShaderConstHandle* handle, const GFXD3D11ShaderConstHandle* _dxHandle = static_cast(handle); AssertFatal(mShader == _dxHandle->mShader, "GFXD3D11ShaderConstBuffer::internalSet - Should only set handles which are owned by our shader"); - S32 size = inSize; + + if (_dxHandle->mInstancingConstant) + { + dMemcpy(mInstPtr + _dxHandle->mOffset, data, size); + return; + } + switch (_dxHandle->mDesc.constType) { case GFXSCT_Float2x2: @@ -268,7 +280,6 @@ void GFXD3D11ShaderConstBuffer::internalSet(GFXShaderConstHandle* handle, const const BufferKey bufDesc(_dxHandle->mBinding, (SHADER_STAGE)_dxHandle->mStage); U8* buf = mBufferMap[bufDesc].data; - if (dMemcmp(buf + _dxHandle->mDesc.offset, data, size) != 0) { dMemcpy(buf + _dxHandle->mDesc.offset, data, size); @@ -472,7 +483,7 @@ void GFXD3D11ShaderConstBuffer::addBuffer(U32 bufBindingPoint, SHADER_STAGE shad cbDesc.StructureByteStride = 0; HRESULT hr; - hr = D3D11DEVICE->CreateBuffer(&cbDesc, NULL, &mBoundConstantBuffers[(U32)shaderStage + bufBindingPoint]); + hr = D3D11DEVICE->CreateBuffer(&cbDesc, NULL, &mBoundConstantBuffers[shaderStage][bufBindingPoint]); if (FAILED(hr)) { @@ -523,7 +534,7 @@ void GFXD3D11ShaderConstBuffer::activate( GFXD3D11ShaderConstBuffer *prevShaderB if (thisBuff.data && thisBuff.isDirty) { - D3D11DEVICECONTEXT->UpdateSubresource(mBoundConstantBuffers[(U32)thisBufferDesc.key2 + thisBufferDesc.key1], 0, NULL, thisBuff.data, thisBuff.size, 0); + D3D11DEVICECONTEXT->UpdateSubresource(mBoundConstantBuffers[thisBufferDesc.key2][thisBufferDesc.key1], 0, NULL, thisBuff.data, thisBuff.size, 0); bufRanges[thisBufferDesc.key2].addSlot(thisBufferDesc.key1); } } @@ -532,7 +543,7 @@ void GFXD3D11ShaderConstBuffer::activate( GFXD3D11ShaderConstBuffer *prevShaderB { 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; + ID3D11Buffer** vsBuffers = mBoundConstantBuffers[SHADER_STAGE::VERTEX_SHADER] + bufStartSlot; D3D11DEVICECONTEXT->VSSetConstantBuffers(bufStartSlot, numBufs, vsBuffers); } @@ -541,7 +552,7 @@ void GFXD3D11ShaderConstBuffer::activate( GFXD3D11ShaderConstBuffer *prevShaderB { 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 + (U32)SHADER_STAGE::PIXEL_SHADER; + ID3D11Buffer** psBuffers = mBoundConstantBuffers[SHADER_STAGE::PIXEL_SHADER] + bufStartSlot; D3D11DEVICECONTEXT->PSSetConstantBuffers(bufStartSlot, numBufs, psBuffers); } @@ -553,9 +564,12 @@ void GFXD3D11ShaderConstBuffer::onShaderReload( GFXD3D11Shader *shader ) { AssertFatal( shader == mShader, "GFXD3D11ShaderConstBuffer::onShaderReload is hosed!" ); - for (U32 i = 0; i < 16; i++) + for (U32 i = 0; i < 6; i++) { - SAFE_RELEASE(mBoundConstantBuffers[i]); + for (U32 j = 0; j < 16; j++) + { + SAFE_RELEASE(mBoundConstantBuffers[i][j]); + } } for (BufferMap::Iterator i = mBufferMap.begin(); i != mBufferMap.end(); i++) @@ -831,8 +845,8 @@ bool GFXD3D11Shader::_compileShader( const Torque::Path &filePath, return result; } -void GFXD3D11Shader::_getShaderConstants(ID3D11ShaderReflection* refTable, - SHADER_STAGE shaderStage) +void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection* refTable, + SHADER_STAGE shaderStage) { PROFILE_SCOPE(GFXD3D11Shader_GetShaderConstants); @@ -844,26 +858,17 @@ void GFXD3D11Shader::_getShaderConstants(ID3D11ShaderReflection* refTable, AssertFatal(false, "Shader Reflection table unable to be created"); } // we loop through and account for the most common data types. - - U32 bufferOffset = 0; + bool foundGlobals = false; for (U32 i = 0; i < shaderDesc.ConstantBuffers; i++) { GFXShaderConstDesc desc; ID3D11ShaderReflectionConstantBuffer* constantBuffer = refTable->GetConstantBufferByIndex(i); D3D11_SHADER_BUFFER_DESC constantBufferDesc; - - bool globalBuffer = false; + if (constantBuffer->GetDesc(&constantBufferDesc) == S_OK) { desc.name = String(constantBufferDesc.Name); desc.size = constantBufferDesc.Size; - // we join global and params into 1 buffer. - if (String::compare(desc.name, "$Globals") == 0 || String::compare(desc.name, "$Params") == 0) - { - desc.name = "$defaultTorqueBuffer_" + String::ToString((U32)shaderStage); - globalBuffer = true; - } - desc.constType = GFXSCT_ConstBuffer; desc.shaderStage = shaderStage; desc.samplerReg = -1; @@ -871,6 +876,15 @@ void GFXD3D11Shader::_getShaderConstants(ID3D11ShaderReflection* refTable, D3D11_SHADER_INPUT_BIND_DESC shaderInputBind; refTable->GetResourceBindingDescByName(constantBufferDesc.Name, &shaderInputBind); desc.bindPoint = shaderInputBind.BindPoint; + if (String::compare(desc.name, "$Globals") == 0 || String::compare(desc.name, "$Params") == 0) + { + desc.name = desc.name + String::ToString((U32)shaderStage); + + if (foundGlobals) + desc.bindPoint += 1; + + foundGlobals = true; + } BufferMap::Iterator buffer = mBuffers.find(desc.name); // already added? @@ -896,7 +910,7 @@ void GFXD3D11Shader::_getShaderConstants(ID3D11ShaderReflection* refTable, // set the bind point to the same as the const buffer. varDesc.bindPoint = desc.bindPoint; - varDesc.offset = globalBuffer ? bufferOffset + shaderVarDesc.StartOffset : shaderVarDesc.StartOffset; + varDesc.offset = shaderVarDesc.StartOffset; varDesc.arraySize = mMax(shaderTypeDesc.Elements, 1); varDesc.size = shaderVarDesc.Size; varDesc.shaderStage = shaderStage; @@ -959,14 +973,6 @@ void GFXD3D11Shader::_getShaderConstants(ID3D11ShaderReflection* refTable, AssertFatal(false, "Unable to get shader constant description! (may need more elements of constantDesc"); } - if(globalBuffer) - bufferOffset += desc.size; - } - - BufferMap::Iterator buf = mBuffers.find("$defaultTorqueBuffer_" + String::ToString((U32)shaderStage)); - if (buf != mBuffers.end()) - { - buf->value.size += bufferOffset; } for (U32 i = 0; i < shaderDesc.BoundResources; i++) @@ -1073,23 +1079,26 @@ void GFXD3D11Shader::_buildShaderConstantHandles() // and add the const buffers to the buffer map. for (U32 i = 0; i < mShaderConsts.size(); i++) { + GFXD3D11ShaderConstHandle* handle; GFXShaderConstDesc& desc = mShaderConsts[i]; - HandleMap::Iterator handle = mHandles.find(desc.name); + HandleMap::Iterator j = 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()) + if (j != mHandles.end()) { - handle->value->reinit(desc); + handle = j->value; + handle->reinit(desc); } else { - mHandles[desc.name] = new GFXD3D11ShaderConstHandle(this, desc); + handle = new GFXD3D11ShaderConstHandle(this, desc); + mHandles[desc.name] = handle; } } - for (U32 i = 0; i < mSamplerDescriptions.size(); i++) + for (U32 j = 0; j < mSamplerDescriptions.size(); j++) { - GFXShaderConstDesc& desc = mSamplerDescriptions[i]; + const GFXShaderConstDesc& desc = mSamplerDescriptions[j]; AssertFatal(desc.constType == GFXSCT_Sampler || desc.constType == GFXSCT_SamplerCube || @@ -1097,16 +1106,19 @@ void GFXD3D11Shader::_buildShaderConstantHandles() desc.constType == GFXSCT_SamplerTextureArray, "GFXD3D11Shader::_buildShaderConstantHandles - Invalid samplerDescription type!"); - HandleMap::Iterator handle = mHandles.find(desc.name); + GFXD3D11ShaderConstHandle* handle; + HandleMap::Iterator k = 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()) + if (k != mHandles.end()) { - handle->value->reinit(desc); + handle = k->value; + handle->reinit(desc); } else { - mHandles[desc.name] = new GFXD3D11ShaderConstHandle(this, desc); + handle = new GFXD3D11ShaderConstHandle(this, desc); + mHandles[desc.name] = handle; } } @@ -1128,18 +1140,27 @@ void GFXD3D11Shader::_buildInstancingShaderConstantHandles() GFXD3D11ShaderConstHandle *handle; HandleMap::Iterator j = mHandles.find( constName ); + GFXShaderConstDesc desc; + + desc.name = constName; + desc.offset = offset; + desc.constType = GFXSCT_ConstBuffer; + desc.shaderStage = SHADER_STAGE::PIXEL_SHADER; + desc.samplerReg = -1; + desc.size = 0; + desc.arraySize = 1; if ( j != mHandles.end() ) handle = j->value; else { - handle = new GFXD3D11ShaderConstHandle(this); + handle = new GFXD3D11ShaderConstHandle(this, desc); mHandles[ constName ] = handle; } + handle->mShader = this; 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. diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.h b/Engine/source/gfx/D3D11/gfxD3D11Shader.h index c7aed3a7b..9e02a7653 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.h +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.h @@ -168,7 +168,7 @@ protected: // we probably want this to be GFXDevice and not per shader. - ID3D11Buffer* mBoundConstantBuffers[16]; + ID3D11Buffer* mBoundConstantBuffers[6][16]; }; class gfxD3D11Include; diff --git a/Engine/source/gfx/gfxShader.h b/Engine/source/gfx/gfxShader.h index a8008eddf..3e17246c1 100644 --- a/Engine/source/gfx/gfxShader.h +++ b/Engine/source/gfx/gfxShader.h @@ -70,7 +70,7 @@ struct GFXShaderConstDesc { public: String name; - GFXShaderConstType constType; + GFXShaderConstType constType; U32 arraySize; // > 1 means it is an array! S32 bindPoint; // bind point used for ubo/cb. S32 samplerReg; // sampler register. From e24971517ea77ad2492e84e269b3953320898903 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Sun, 25 Feb 2024 23:10:23 +0000 Subject: [PATCH 18/53] commit before pr --- Engine/source/gfx/D3D11/gfxD3D11Shader.cpp | 1 + Engine/source/gfx/genericConstBuffer.cpp | 289 ---------------- Engine/source/gfx/genericConstBuffer.h | 374 --------------------- 3 files changed, 1 insertion(+), 663 deletions(-) delete mode 100644 Engine/source/gfx/genericConstBuffer.cpp delete mode 100644 Engine/source/gfx/genericConstBuffer.h diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp index 1aa32a48d..a436545ab 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp @@ -273,6 +273,7 @@ void GFXD3D11ShaderConstBuffer::internalSet(GFXShaderConstHandle* handle, const case GFXSCT_Float2: if (size > sizeof(Point2F)) size = _dxHandle->mDesc.size; + break; default: break; } diff --git a/Engine/source/gfx/genericConstBuffer.cpp b/Engine/source/gfx/genericConstBuffer.cpp deleted file mode 100644 index 185150720..000000000 --- a/Engine/source/gfx/genericConstBuffer.cpp +++ /dev/null @@ -1,289 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#include "platform/platform.h" -#include "gfx/genericConstBuffer.h" - -#include "platform/profiler.h" -#include "core/stream/stream.h" - - -GenericConstBufferLayout::GenericConstBufferLayout() -{ - VECTOR_SET_ASSOCIATION( mParams ); - - mBufferSize = 0; - mCurrentIndex = 0; - mTimesCleared = 0; -} - -void GenericConstBufferLayout::addParameter(const String& name, const GFXShaderConstType constType, const U32 offset, const U32 size, const U32 arraySize, const U32 alignValue) -{ -#ifdef TORQUE_DEBUG - // Make sure we don't have overlapping parameters - S32 start = offset; - S32 end = offset + size; - for (Params::iterator i = mParams.begin(); i != mParams.end(); i++) - { - const ParamDesc& dp = *i; - S32 pstart = dp.offset; - S32 pend = pstart + dp.size; - pstart -= start; - pend -= end; - // This is like a minkowski sum for two line segments, if the newly formed line contains - // the origin, then they intersect - bool intersect = ((pstart >= 0 && 0 >= pend) || ((pend >= 0 && 0 >= pstart))); - AssertFatal(!intersect, "Overlapping shader parameter!"); - } -#endif - ParamDesc desc; - desc.name = name; - desc.constType = constType; - desc.offset = offset; - desc.size = size; - desc.arraySize = arraySize; - desc.alignValue = alignValue; - desc.index = mCurrentIndex++; - mParams.push_back(desc); - mBufferSize = getMax(desc.offset + desc.size, mBufferSize); - AssertFatal(mBufferSize, "Empty constant buffer!"); -} - -bool GenericConstBufferLayout::set(const ParamDesc& pd, const GFXShaderConstType constType, const U32 size, const void* data, U8* basePointer) -{ - PROFILE_SCOPE(GenericConstBufferLayout_set); - - // Shader compilers like to optimize float4x4 uniforms into float3x3s. - // So long as the real paramater is a matrix of-some-type and the data - // passed in is a MatrixF ( which is will be ), we DO NOT have a - // mismatched const type. - AssertFatal( pd.constType == constType || - ( - ( pd.constType == GFXSCT_Float2x2 || - pd.constType == GFXSCT_Float3x3 || - pd.constType == GFXSCT_Float3x4 || - pd.constType == GFXSCT_Float4x3 || - pd.constType == GFXSCT_Float4x4 ) && - ( constType == GFXSCT_Float2x2 || - constType == GFXSCT_Float3x3 || - constType == GFXSCT_Float3x4 || - constType == GFXSCT_Float4x3 || - constType == GFXSCT_Float4x4 ) - ), "Mismatched const type!" ); - - // This "cute" bit of code allows us to support 2x3 and 3x3 matrices in shader constants but use our MatrixF class. Yes, a hack. -BTR - switch (pd.constType) - { - case GFXSCT_Float2x2 : - case GFXSCT_Float3x3 : - case GFXSCT_Float4x3 : - case GFXSCT_Float4x4 : - return setMatrix(pd, constType, size, data, basePointer); - break; - default : - break; - } - - AssertFatal(pd.size >= size, "Not enough room in the buffer for this data!"); - - // Ok, we only set data if it's different than the data we already have, this maybe more expensive than just setting the data, but - // we'll have to do some timings to see. For example, the lighting shader constants rarely change, but we can't assume that at the - // renderInstMgr level, but we can check down here. -BTR - if (dMemcmp(basePointer+pd.offset, data, size) != 0) - { - dMemcpy(basePointer+pd.offset, data, size); - return true; - } - return false; -} - -bool GenericConstBufferLayout::setMatrix(const ParamDesc& pd, const GFXShaderConstType constType, const U32 size, const void* data, U8* basePointer) -{ - PROFILE_SCOPE(GenericConstBufferLayout_setMatrix); - - // We're generic, so just copy the full MatrixF in - AssertFatal(pd.size >= size, "Not enough room in the buffer for this data!"); - - // Matrices are an annoying case because of the alignment issues. There are alignment issues in the matrix itself, and then potential inter matrices alignment issues. - // So GL and DX will need to derive their own GenericConstBufferLayout classes and override this method to deal with that stuff. For GenericConstBuffer, copy the whole - // 4x4 matrix regardless of the target case. - - if (dMemcmp(basePointer+pd.offset, data, size) != 0) - { - dMemcpy(basePointer+pd.offset, data, size); - return true; - } - - return false; -} - -bool GenericConstBufferLayout::getDesc(const String& name, ParamDesc& param) const -{ - for (U32 i = 0; i < mParams.size(); i++) - { - if (mParams[i].name.equal(name)) - { - param = mParams[i]; - return true; - } - } - return false; -} - -bool GenericConstBufferLayout::getDesc(const U32 index, ParamDesc& param) const -{ - if ( index < mParams.size() ) - { - param = mParams[index]; - return true; - } - - return false; -} - -bool GenericConstBufferLayout::write(Stream* s) -{ - // Write out the size of the ParamDesc structure as a sanity check. - if (!s->write((U32) sizeof(ParamDesc))) - return false; - // Next, write out the number of elements we've got. - if (!s->write(mParams.size())) - return false; - for (U32 i = 0; i < mParams.size(); i++) - { - s->write(mParams[i].name); - - if (!s->write(mParams[i].offset)) - return false; - if (!s->write(mParams[i].size)) - return false; - U32 t = (U32) mParams[i].constType; - if (!s->write(t)) - return false; - if (!s->write(mParams[i].arraySize)) - return false; - if (!s->write(mParams[i].alignValue)) - return false; - if (!s->write(mParams[i].index)) - return false; - } - return true; -} - -/// Load this layout from a stream -bool GenericConstBufferLayout::read(Stream* s) -{ - U32 structSize; - if (!s->read(&structSize)) - return false; - if (structSize != sizeof(ParamDesc)) - { - AssertFatal(false, "Invalid shader layout structure size!"); - return false; - } - U32 numParams; - if (!s->read(&numParams)) - return false; - mParams.setSize(numParams); - mBufferSize = 0; - mCurrentIndex = 0; - for (U32 i = 0; i < mParams.size(); i++) - { - s->read(&mParams[i].name); - if (!s->read(&mParams[i].offset)) - return false; - if (!s->read(&mParams[i].size)) - return false; - U32 t; - if (!s->read(&t)) - return false; - mParams[i].constType = (GFXShaderConstType) t; - if (!s->read(&mParams[i].arraySize)) - return false; - if (!s->read(&mParams[i].alignValue)) - return false; - if (!s->read(&mParams[i].index)) - return false; - mBufferSize = getMax(mParams[i].offset + mParams[i].size, mBufferSize); - mCurrentIndex = getMax(mParams[i].index, mCurrentIndex); - } - mCurrentIndex++; - return true; -} - -void GenericConstBufferLayout::clear() -{ - mParams.clear(); - mBufferSize = 0; - mCurrentIndex = 0; - mTimesCleared++; -} - - -GenericConstBuffer::GenericConstBuffer(GenericConstBufferLayout* layout) - : mLayout( layout ), - mBuffer( NULL ), - mDirtyStart( U32_MAX ), - mDirtyEnd( 0 ) -{ - if ( layout && layout->getBufferSize() > 0 ) - { - mBuffer = new U8[mLayout->getBufferSize()]; - - // Always set a default value, that way our isEqual checks - // will work in release as well. - dMemset( mBuffer, 0xFFFF, mLayout->getBufferSize() ); - - #ifdef TORQUE_DEBUG - - // Clear the debug assignment tracking. - mWasAssigned.setSize( layout->getParameterCount() ); - dMemset( mWasAssigned.address(), 0, mWasAssigned.memSize() ); - - #endif - } -} - -GenericConstBuffer::~GenericConstBuffer() -{ - delete [] mBuffer; -} - -#ifdef TORQUE_DEBUG - -void GenericConstBuffer::assertUnassignedConstants( const char *shaderName ) -{ - for ( U32 i=0; i < mWasAssigned.size(); i++ ) - { - if ( mWasAssigned[i] ) - continue; - - GenericConstBufferLayout::ParamDesc pd; - mLayout->getDesc( i, pd ); - - // Assert on the unassigned constant. - //AssertFatal( false, avar( "The '%s' shader constant in shader '%s' was unassigned!", - // pd.name.c_str(), shaderName ) ); - } -} - -#endif diff --git a/Engine/source/gfx/genericConstBuffer.h b/Engine/source/gfx/genericConstBuffer.h deleted file mode 100644 index afa097be7..000000000 --- a/Engine/source/gfx/genericConstBuffer.h +++ /dev/null @@ -1,374 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#ifndef _GENERICCONSTBUFFER_H_ -#define _GENERICCONSTBUFFER_H_ - -#ifndef _TORQUE_STRING_H_ -#include "core/util/str.h" -#endif -#ifndef _TDICTIONARY_H_ -#include "core/util/tDictionary.h" -#endif -#ifndef _TVECTOR_H_ -#include "core/util/tVector.h" -#endif -#ifndef _ALIGNEDARRAY_H_ -#include "core/util/tAlignedArray.h" -#endif -#ifndef _COLOR_H_ -#include "core/color.h" -#endif -#ifndef _MMATRIX_H_ -#include "math/mMatrix.h" -#endif -#ifndef _MPOINT2_H_ -#include "math/mPoint2.h" -#endif -#ifndef _GFXENUMS_H_ -#include "gfx/gfxEnums.h" -#endif - -class Stream; - - -/// This class defines the memory layout for a GenericConstBuffer. -class GenericConstBufferLayout -{ -public: - /// Describes the parameters we contain - struct ParamDesc - { - ParamDesc() - : name(), - offset( 0 ), - size( 0 ), - constType( GFXSCT_Float ), - arraySize( 0 ), - alignValue( 0 ), - index( 0 ) - { - } - - void clear() - { - name = String::EmptyString; - offset = 0; - size = 0; - constType = GFXSCT_Float; - arraySize = 0; - alignValue = 0; - index = 0; - } - - /// Parameter name - String name; - - /// Offset into the memory block - U32 offset; - - /// Size of the block - U32 size; - - /// Type of data - GFXShaderConstType constType; - - // For arrays, how many elements - U32 arraySize; - - // Array element alignment value - U32 alignValue; - - /// 0 based index of this param, in order of addParameter calls. - U32 index; - }; - - GenericConstBufferLayout(); - virtual ~GenericConstBufferLayout() {} - - /// Add a parameter to the buffer - virtual void addParameter(const String& name, const GFXShaderConstType constType, const U32 offset, const U32 size, const U32 arraySize, const U32 alignValue); - - /// Get the size of the buffer - inline U32 getBufferSize() const { return mBufferSize; } - - /// Get the number of parameters - inline U32 getParameterCount() const { return mParams.size(); } - - /// Returns the ParamDesc of a parameter - bool getDesc(const String& name, ParamDesc& param) const; - - /// Returns the ParamDesc of a parameter - bool getDesc(const U32 index, ParamDesc& param) const; - - /// Set a parameter, given a base pointer - virtual bool set(const ParamDesc& pd, const GFXShaderConstType constType, const U32 size, const void* data, U8* basePointer); - - /// Save this layout to a stream - bool write(Stream* s); - - /// Load this layout from a stream - bool read(Stream* s); - - /// Restore to initial state. - void clear(); - -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 of parameter descriptions. - typedef Vector Params; - - /// Vector of parameter descriptions. - Params mParams; - U32 mBufferSize; - U32 mCurrentIndex; - - // This if for debugging shader reloading and can be removed later. - U32 mTimesCleared; -}; - - -/// This class manages shader constant data in a system memory buffer. It is -/// used by device specific classes for batching together many constant changes -/// which are then copied to the device thru a single API call. -/// -/// @see GenericConstBufferLayout -/// -class GenericConstBuffer -{ -public: - GenericConstBuffer(GenericConstBufferLayout* layout); - ~GenericConstBuffer(); - - /// @name Set shader constant values - /// @{ - /// Actually set shader constant values - /// @param name Name of the constant, this should be a name contained in the array returned in getShaderConstDesc, - /// if an invalid name is used, its ignored, but it's not an error. - inline void set(const GenericConstBufferLayout::ParamDesc& pd, const F32 f) { internalSet(pd, GFXSCT_Float, sizeof(F32), &f); } - inline void set(const GenericConstBufferLayout::ParamDesc& pd, const Point2F& fv) { internalSet(pd, GFXSCT_Float2, sizeof(Point2F), &fv); } - inline void set(const GenericConstBufferLayout::ParamDesc& pd, const Point3F& fv) { internalSet(pd, GFXSCT_Float3, sizeof(Point3F), &fv); } - inline void set(const GenericConstBufferLayout::ParamDesc& pd, const Point4F& fv) { internalSet(pd, GFXSCT_Float4, sizeof(Point4F), &fv); } - inline void set(const GenericConstBufferLayout::ParamDesc& pd, const PlaneF& fv) { internalSet(pd, GFXSCT_Float4, sizeof(PlaneF), &fv); } - inline void set(const GenericConstBufferLayout::ParamDesc& pd, const LinearColorF& fv) { internalSet(pd, GFXSCT_Float4, sizeof(Point4F), &fv); } - inline void set(const GenericConstBufferLayout::ParamDesc& pd, const S32 f) { internalSet(pd, GFXSCT_Int, sizeof(S32), &f); } - inline void set(const GenericConstBufferLayout::ParamDesc& pd, const Point2I& fv) { internalSet(pd, GFXSCT_Int2, sizeof(Point2I), &fv); } - inline void set(const GenericConstBufferLayout::ParamDesc& pd, const Point3I& fv) { internalSet(pd, GFXSCT_Int3, sizeof(Point3I), &fv); } - inline void set(const GenericConstBufferLayout::ParamDesc& pd, const Point4I& fv) { internalSet(pd, GFXSCT_Int4, sizeof(Point4I), &fv); } - inline void set(const GenericConstBufferLayout::ParamDesc& pd, const AlignedArray& fv) { internalSet(pd, GFXSCT_Float, fv.getElementSize() * fv.size(), fv.getBuffer()); } - inline void set(const GenericConstBufferLayout::ParamDesc& pd, const AlignedArray& fv) { internalSet(pd, GFXSCT_Float2, fv.getElementSize() * fv.size(), fv.getBuffer()); } - inline void set(const GenericConstBufferLayout::ParamDesc& pd, const AlignedArray& fv) { internalSet(pd, GFXSCT_Float3, fv.getElementSize() * fv.size(), fv.getBuffer()); } - inline void set(const GenericConstBufferLayout::ParamDesc& pd, const AlignedArray& fv) { internalSet(pd, GFXSCT_Float4, fv.getElementSize() * fv.size(), fv.getBuffer()); } - inline void set(const GenericConstBufferLayout::ParamDesc& pd, const AlignedArray& fv) { internalSet(pd, GFXSCT_Int, fv.getElementSize() * fv.size(), fv.getBuffer()); } - inline void set(const GenericConstBufferLayout::ParamDesc& pd, const AlignedArray& fv) { internalSet(pd, GFXSCT_Int2, fv.getElementSize() * fv.size(), fv.getBuffer()); } - inline void set(const GenericConstBufferLayout::ParamDesc& pd, const AlignedArray& fv) { internalSet(pd, GFXSCT_Int3, fv.getElementSize() * fv.size(), fv.getBuffer()); } - inline void set(const GenericConstBufferLayout::ParamDesc& pd, const AlignedArray& fv) { internalSet(pd, GFXSCT_Int4, fv.getElementSize() * fv.size(), fv.getBuffer()); } - - inline void set( const GenericConstBufferLayout::ParamDesc& pd, const MatrixF& mat, const GFXShaderConstType matrixType ) - { - AssertFatal( matrixType == GFXSCT_Float2x2 || - matrixType == GFXSCT_Float3x3 || - matrixType == GFXSCT_Float3x4 || - matrixType == GFXSCT_Float4x3 || - matrixType == GFXSCT_Float4x4, - "GenericConstBuffer::set() - Invalid matrix type!" ); - - internalSet( pd, matrixType, sizeof(MatrixF), &mat ); - } - - inline void set( const GenericConstBufferLayout::ParamDesc& pd, const MatrixF* mat, const U32 arraySize, const GFXShaderConstType matrixType ) - { - AssertFatal( matrixType == GFXSCT_Float2x2 || - matrixType == GFXSCT_Float3x3 || - matrixType == GFXSCT_Float3x4 || - matrixType == GFXSCT_Float4x3 || - matrixType == GFXSCT_Float4x4, - "GenericConstBuffer::set() - Invalid matrix type!" ); - - internalSet( pd, matrixType, sizeof(MatrixF)*arraySize, mat ); - } - - /// Gets the dirty buffer range and clears the dirty - /// state at the same time. - inline const U8* getDirtyBuffer( U32 *start, U32 *size ); - - /// Gets the entire buffer ignoring dirty range - inline const U8* getEntireBuffer(); - - /// Sets the entire buffer as dirty or clears the dirty state. - inline void setDirty( bool dirty ); - - /// Returns true if the buffer has been modified since the - /// last call to getDirtyBuffer or setDirty. The buffer is - /// not dirty on initial creation. - /// - /// @see getDirtyBuffer - /// @see setDirty - inline bool isDirty() const { return mDirtyEnd != 0; } - - /// Returns true if have the same layout and hold the same - /// data as the input buffer. - inline bool isEqual( const GenericConstBuffer *buffer ) const; - - /// Returns our layout object. - inline GenericConstBufferLayout* getLayout() const { return mLayout; } - - #ifdef TORQUE_DEBUG - - /// Helper function used to assert on unset constants. - void assertUnassignedConstants( const char *shaderName ); - - #endif - -protected: - - /// Returns a pointer to the raw buffer - inline const U8* getBuffer() const { return mBuffer; } - - /// Called by the inlined set functions above to do the - /// real dirty work of copying the data to the right location - /// within the buffer. - inline void internalSet( const GenericConstBufferLayout::ParamDesc &pd, - const GFXShaderConstType constType, - const U32 size, - const void *data ); - - /// The buffer layout. - GenericConstBufferLayout *mLayout; - - /// The pointer to the contant store or - /// NULL if the layout is empty. - U8 *mBuffer; - - /// The byte offset to the start of the dirty - /// range within the buffer or U32_MAX if the - /// buffer is not dirty. - U32 mDirtyStart; - - /// The btye offset to the end of the dirty - /// range within the buffer or 0 if the buffer - /// is not dirty. - U32 mDirtyEnd; - - - #ifdef TORQUE_DEBUG - - /// A vector used to keep track if a constant - /// has beed assigned a value or not. - /// - /// @see assertUnassignedConstants - Vector mWasAssigned; - - #endif -}; - - -// NOTE: These inlines below are here to get the very best possible -// performance when setting the device shader constants and can be -// called 4000-8000 times per frame or more. -// -// You need a very good reason to consider changing them. - -inline void GenericConstBuffer::internalSet( const GenericConstBufferLayout::ParamDesc &pd, - const GFXShaderConstType constType, - const U32 size, - const void *data ) -{ - // NOTE: We should have never gotten here if the buffer - // was null as no valid shader constant could have been - // assigned. - // - // If this happens its a bug in another part of the code. - // - AssertFatal( mBuffer, "GenericConstBuffer::internalSet - The buffer is NULL!" ); - - if ( mLayout->set( pd, constType, size, data, mBuffer ) ) - { - #ifdef TORQUE_DEBUG - - // Update the debug assignment tracking. - mWasAssigned[ pd.index ] = true; - - #endif - - // Keep track of the dirty range so it can be queried - // later in GenericConstBuffer::getDirtyBuffer. - mDirtyStart = getMin( pd.offset, mDirtyStart ); - mDirtyEnd = getMax( pd.offset + pd.size, mDirtyEnd ); - } -} - -inline void GenericConstBuffer::setDirty( bool dirty ) -{ - if ( !mBuffer ) - return; - - if ( dirty ) - { - mDirtyStart = 0; - mDirtyEnd = mLayout->getBufferSize(); - } - else if ( !dirty ) - { - mDirtyStart = U32_MAX; - mDirtyEnd = 0; - } -} - -inline const U8* GenericConstBuffer::getDirtyBuffer( U32 *start, U32 *size ) -{ - AssertFatal( isDirty(), "GenericConstBuffer::getDirtyBuffer() - Buffer is not dirty!" ); - AssertFatal( mDirtyEnd > mDirtyStart, "GenericConstBuffer::getDirtyBuffer() - Dirty range is invalid!" ); - AssertFatal( mBuffer, "GenericConstBuffer::getDirtyBuffer() - Buffer is empty!" ); - - // Use the area we calculated during internalSet. - *size = mDirtyEnd - mDirtyStart; - *start = mDirtyStart; - const U8 *buffer = mBuffer + mDirtyStart; - - // Clear the dirty state while we're here. - mDirtyStart = U32_MAX; - mDirtyEnd = 0; - - return buffer; -} - -inline const U8* GenericConstBuffer::getEntireBuffer() -{ - AssertFatal(mBuffer, "GenericConstBuffer::getDirtyBuffer() - Buffer is empty!"); - - return mBuffer; -} - -inline bool GenericConstBuffer::isEqual( const GenericConstBuffer *buffer ) const -{ - U32 bsize = mLayout->getBufferSize(); - if ( bsize != buffer->mLayout->getBufferSize() ) - return false; - - return dMemcmp( mBuffer, buffer->getBuffer(), bsize ) == 0; -} - -#endif // _GENERICCONSTBUFFER_H_ From b979f4befceb17bcbd037b0a3dd9daf71d86cd07 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Mon, 26 Feb 2024 09:22:19 +0000 Subject: [PATCH 19/53] everything works ... apart from the sun =/ --- Engine/source/gfx/D3D11/gfxD3D11Shader.cpp | 152 ++++++++++++--------- Engine/source/gfx/D3D11/gfxD3D11Shader.h | 24 +--- Engine/source/gfx/gfxShader.h | 13 +- 3 files changed, 105 insertions(+), 84 deletions(-) diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp index a436545ab..b8429eb63 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp @@ -103,14 +103,14 @@ GFXD3D11ShaderConstHandle::GFXD3D11ShaderConstHandle(GFXD3D11Shader* shader) { dMemset(&mDesc, 0, sizeof(mDesc)); mValid = false; - mStage = SHADER_STAGE::UNKNOWN_STAGE; + mStageFlags = 0; } GFXD3D11ShaderConstHandle::GFXD3D11ShaderConstHandle(GFXD3D11Shader* shader, const GFXShaderConstDesc& desc) : mShader(shader), mDesc(desc), - mStage((SHADER_STAGE)desc.shaderStage), + mOffset(desc.offset), mSize(desc.size), mBinding(desc.bindPoint), @@ -121,6 +121,8 @@ GFXD3D11ShaderConstHandle::GFXD3D11ShaderConstHandle(GFXD3D11Shader* shader, mValid = false; else mValid = true; + + mStageFlags = desc.shaderStage; } GFXD3D11ShaderConstHandle::~GFXD3D11ShaderConstHandle() @@ -130,7 +132,7 @@ GFXD3D11ShaderConstHandle::~GFXD3D11ShaderConstHandle() void GFXD3D11ShaderConstHandle::reinit(const GFXShaderConstDesc& desc) { mDesc = desc; - mStage = (SHADER_STAGE)desc.shaderStage; + mStageFlags = desc.shaderStage; mOffset = desc.offset; mSize = desc.size * desc.arraySize; mBinding = desc.bindPoint; @@ -181,7 +183,7 @@ GFXShader* GFXD3D11ShaderConstBuffer::getShader() return mShader; } -void GFXD3D11ShaderConstBuffer::setMatrix(GFXShaderConstHandle* handle, const U32 inSize, const void* data) +void GFXD3D11ShaderConstBuffer::setMatrix(GFXShaderConstHandle* handle, const U32 inSize, const void* data, U8* basePointer) { AssertFatal(handle, "GFXD3D11ShaderConstBuffer::internalSet - Handle is NULL!"); AssertFatal(handle->isValid(), "GFXD3D11ShaderConstBuffer::internalSet - Handle is not valid!"); @@ -189,8 +191,8 @@ void GFXD3D11ShaderConstBuffer::setMatrix(GFXShaderConstHandle* handle, const U3 GFXD3D11ShaderConstHandle* _dxHandle = static_cast(handle); AssertFatal(mShader == _dxHandle->mShader, "GFXD3D11ShaderConstBuffer::internalSet - Should only set handles which are owned by our shader"); - const BufferKey bufDesc(_dxHandle->mBinding, (SHADER_STAGE)_dxHandle->mStage); - U8* buf = mBufferMap[bufDesc].data; + + U8* buf = basePointer; if (_dxHandle->mDesc.constType == GFXSCT_Float4x4) { @@ -254,60 +256,66 @@ void GFXD3D11ShaderConstBuffer::internalSet(GFXShaderConstHandle* handle, const AssertFatal(mShader == _dxHandle->mShader, "GFXD3D11ShaderConstBuffer::internalSet - Should only set handles which are owned by our shader"); S32 size = inSize; - if (_dxHandle->mInstancingConstant) + for (U32 i = VERTEX_SHADER; i <= COMPUTE_SHADER; i = GFXShaderStage(i << 1)) { - dMemcpy(mInstPtr + _dxHandle->mOffset, data, size); - return; - } + if (_dxHandle->mStageFlags & i) + { + BufferKey bufDesc(_dxHandle->mBinding, (GFXShaderStage)i); + U8* basePointer = mBufferMap[bufDesc].data; - switch (_dxHandle->mDesc.constType) - { - case GFXSCT_Float2x2: - case GFXSCT_Float3x3: - case GFXSCT_Float4x3: - case GFXSCT_Float4x4: - setMatrix(handle, size, data); - return; - break; - // TODO add other AlignedVector here - case GFXSCT_Float2: - if (size > sizeof(Point2F)) - size = _dxHandle->mDesc.size; - break; - default: - break; - } + if (_dxHandle->mInstancingConstant) + { + dMemcpy(mInstPtr + _dxHandle->mOffset, data, size); + return; + } - const BufferKey bufDesc(_dxHandle->mBinding, (SHADER_STAGE)_dxHandle->mStage); - U8* buf = mBufferMap[bufDesc].data; + switch (_dxHandle->mDesc.constType) + { + case GFXSCT_Float2x2: + case GFXSCT_Float3x3: + case GFXSCT_Float4x3: + case GFXSCT_Float4x4: + setMatrix(handle, size, data, basePointer); + return; + break; + // TODO add other AlignedVector here + case GFXSCT_Float2: + if (size > sizeof(Point2F)) + size = _dxHandle->mDesc.size; + break; + default: + break; + } - if (dMemcmp(buf + _dxHandle->mDesc.offset, data, size) != 0) - { - dMemcpy(buf + _dxHandle->mDesc.offset, data, size); + if (dMemcmp(basePointer + _dxHandle->mDesc.offset, data, size) != 0) + { + dMemcpy(basePointer + _dxHandle->mDesc.offset, data, size); + } + } } } -void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const F32 fv) +void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const F32 fv) { internalSet(handle, sizeof(F32), &fv); } -void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const Point2F& fv) +void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const Point2F& fv) { internalSet(handle, sizeof(Point2F), &fv); } -void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const Point3F& fv) +void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const Point3F& fv) { internalSet(handle, sizeof(Point3F), &fv); } -void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const Point4F& fv) +void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const Point4F& fv) { internalSet(handle, sizeof(Point4F), &fv); } -void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const PlaneF& fv) +void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const PlaneF& fv) { internalSet(handle, sizeof(PlaneF), &fv); } @@ -318,14 +326,14 @@ void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const LinearCo } 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 // allowed to be set from GLSL. // // So we ignore it here... all other cases will assert. // - if ( ((GFXD3D11ShaderConstHandle*)handle)->isSampler() ) + if (((GFXD3D11ShaderConstHandle*)handle)->isSampler()) return; internalSet(handle, sizeof(S32), &fv); @@ -386,14 +394,14 @@ void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedA internalSet(handle, fv.getElementSize() * fv.size(), fv.getBuffer()); } -void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF& mat, const GFXShaderConstType matrixType) -{ - AssertFatal(handle, "Handle is NULL!" ); - AssertFatal(handle->isValid(), "Handle is not valid!" ); +void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF& mat, const GFXShaderConstType matrixType) +{ + AssertFatal(handle, "Handle is NULL!"); + AssertFatal(handle->isValid(), "Handle is not valid!"); - AssertFatal(static_cast(handle), "Incorrect const buffer type!"); + AssertFatal(static_cast(handle), "Incorrect const buffer type!"); const GFXD3D11ShaderConstHandle* _dxHandle = static_cast(handle); - AssertFatal(!_dxHandle->isSampler(), "Handle is sampler constant!" ); + AssertFatal(!_dxHandle->isSampler(), "Handle is sampler constant!"); AssertFatal(_dxHandle->mShader == mShader, "Mismatched shaders!"); MatrixF transposed; @@ -447,7 +455,6 @@ void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF* return; internalSet(handle, sizeof(MatrixF) * arraySize, transposed.begin()); - } const String GFXD3D11ShaderConstBuffer::describeSelf() const @@ -459,7 +466,7 @@ const String GFXD3D11ShaderConstBuffer::describeSelf() const return ret; } -void GFXD3D11ShaderConstBuffer::addBuffer(U32 bufBindingPoint, SHADER_STAGE shaderStage, U32 size) +void GFXD3D11ShaderConstBuffer::addBuffer(U32 bufBindingPoint, GFXShaderStage shaderStage, U32 size) { const BufferKey bufKey(bufBindingPoint, shaderStage); BufferMap::Iterator buffer = mBufferMap.find(bufKey); @@ -540,20 +547,20 @@ void GFXD3D11ShaderConstBuffer::activate( GFXD3D11ShaderConstBuffer *prevShaderB } } - if (mShader->mVertShader && bufRanges[SHADER_STAGE::VERTEX_SHADER].isValid()) + if (mShader->mVertShader && bufRanges[GFXShaderStage::VERTEX_SHADER].isValid()) { - 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[SHADER_STAGE::VERTEX_SHADER] + bufStartSlot; + const U32 bufStartSlot = bufRanges[GFXShaderStage::VERTEX_SHADER].mBufMin; + const U32 numBufs = bufRanges[GFXShaderStage::VERTEX_SHADER].mBufMax - bufRanges[GFXShaderStage::VERTEX_SHADER].mBufMin + 1; + ID3D11Buffer** vsBuffers = mBoundConstantBuffers[GFXShaderStage::VERTEX_SHADER] + bufStartSlot; D3D11DEVICECONTEXT->VSSetConstantBuffers(bufStartSlot, numBufs, vsBuffers); } - if (mShader->mPixShader && bufRanges[SHADER_STAGE::PIXEL_SHADER].isValid()) + if (mShader->mPixShader && bufRanges[GFXShaderStage::PIXEL_SHADER].isValid()) { - 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[SHADER_STAGE::PIXEL_SHADER] + bufStartSlot; + const U32 bufStartSlot = bufRanges[GFXShaderStage::PIXEL_SHADER].mBufMin; + const U32 numBufs = bufRanges[GFXShaderStage::PIXEL_SHADER].mBufMax - bufRanges[GFXShaderStage::PIXEL_SHADER].mBufMin + 1; + ID3D11Buffer** psBuffers = mBoundConstantBuffers[GFXShaderStage::PIXEL_SHADER] + bufStartSlot; D3D11DEVICECONTEXT->PSSetConstantBuffers(bufStartSlot, numBufs, psBuffers); } @@ -582,7 +589,7 @@ void GFXD3D11ShaderConstBuffer::onShaderReload( GFXD3D11Shader *shader ) for (GFXD3D11Shader::BufferMap::Iterator i = shader->mBuffers.begin(); i != shader->mBuffers.end(); ++i) { // add our buffer descriptions to the full const buffer. - this->addBuffer(i->value.bindPoint, (SHADER_STAGE)i->value.shaderStage, i->value.size); + this->addBuffer(i->value.bindPoint, i->value.shaderStage, i->value.size); } // Set the lost state. @@ -647,10 +654,10 @@ bool GFXD3D11Shader::_init() mShaderConsts.clear(); mSamplerDescriptions.clear(); - if (!mVertexFile.isEmpty() && !_compileShader( mVertexFile, SHADER_STAGE::VERTEX_SHADER, d3dMacros) ) + if (!mVertexFile.isEmpty() && !_compileShader( mVertexFile, GFXShaderStage::VERTEX_SHADER, d3dMacros) ) return false; - if (!mPixelFile.isEmpty() && !_compileShader( mPixelFile, SHADER_STAGE::PIXEL_SHADER, d3dMacros)) + if (!mPixelFile.isEmpty() && !_compileShader( mPixelFile, GFXShaderStage::PIXEL_SHADER, d3dMacros)) return false; _buildShaderConstantHandles(); @@ -665,7 +672,7 @@ bool GFXD3D11Shader::_init() } bool GFXD3D11Shader::_compileShader( const Torque::Path &filePath, - SHADER_STAGE shaderStage, + GFXShaderStage shaderStage, const D3D_SHADER_MACRO *defines) { PROFILE_SCOPE( GFXD3D11Shader_CompileShader ); @@ -847,7 +854,7 @@ bool GFXD3D11Shader::_compileShader( const Torque::Path &filePath, } void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection* refTable, - SHADER_STAGE shaderStage) + GFXShaderStage shaderStage) { PROFILE_SCOPE(GFXD3D11Shader_GetShaderConstants); @@ -1088,7 +1095,11 @@ void GFXD3D11Shader::_buildShaderConstantHandles() if (j != mHandles.end()) { handle = j->value; - handle->reinit(desc); + handle->mShader = this; + if((handle->mStageFlags & desc.shaderStage) == 0) + handle->mStageFlags |= (U32)desc.shaderStage; + + handle->setValid(true); } else { @@ -1114,13 +1125,15 @@ void GFXD3D11Shader::_buildShaderConstantHandles() if (k != mHandles.end()) { handle = k->value; - handle->reinit(desc); } else { handle = new GFXD3D11ShaderConstHandle(this, desc); mHandles[desc.name] = handle; } + + handle->mShader = this; + handle->setValid(true); } _buildInstancingShaderConstantHandles(); @@ -1145,8 +1158,17 @@ void GFXD3D11Shader::_buildInstancingShaderConstantHandles() desc.name = constName; desc.offset = offset; - desc.constType = GFXSCT_ConstBuffer; - desc.shaderStage = SHADER_STAGE::PIXEL_SHADER; + switch (element.getType()) + { + case GFXDeclType_Float4: + desc.constType = GFXSCT_Float4; + break; + + default: + desc.constType = GFXSCT_Float; + break; + } + desc.shaderStage = GFXShaderStage::PIXEL_SHADER; desc.samplerReg = -1; desc.size = 0; desc.arraySize = 1; @@ -1185,7 +1207,7 @@ GFXShaderConstBufferRef GFXD3D11Shader::allocConstBuffer() for (BufferMap::Iterator i = mBuffers.begin(); i != mBuffers.end(); ++i) { // add our buffer descriptions to the full const buffer. - buffer->addBuffer(i->value.bindPoint, (SHADER_STAGE)i->value.shaderStage, i->value.size); + buffer->addBuffer(i->value.bindPoint, i->value.shaderStage, i->value.size); } mActiveBuffers.push_back( buffer ); diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.h b/Engine/source/gfx/D3D11/gfxD3D11Shader.h index 9e02a7653..7b99f6a0a 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.h +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.h @@ -33,19 +33,7 @@ class GFXD3D11Shader; -enum SHADER_STAGE -{ - VERTEX_SHADER, - PIXEL_SHADER, - GEOMETRY_SHADER, - DOMAIN_SHADER, - HULL_SHADER, - COMPUTE_SHADER, - UNKNOWN_STAGE -}; - - -typedef CompoundKey BufferKey; +typedef CompoundKey BufferKey; struct BufferRange { @@ -101,7 +89,7 @@ public: U32 mSize; S32 mBinding; // buffer binding point used to map handles to buffers. S32 mSampler; // sampler number, will be -1 if not a sampler. - SHADER_STAGE mStage; + U32 mStageFlags; bool mInstancingConstant; }; @@ -122,7 +110,7 @@ public: /// @param mPrevShaderBuffer The previously active buffer void activate(GFXD3D11ShaderConstBuffer *prevShaderBuffer); - void addBuffer(U32 bufBindingPoint, SHADER_STAGE shaderStage, U32 size); + void addBuffer(U32 bufBindingPoint, GFXShaderStage shaderStage, U32 size); /// Called from GFXD3D11Shader when constants have changed and need /// to be the shader this buffer references is reloaded. @@ -163,7 +151,7 @@ protected: WeakRefPtr mShader; BufferMap mBufferMap; - void setMatrix(GFXShaderConstHandle* handle, const U32 inSize, const void* data); + void setMatrix(GFXShaderConstHandle* handle, const U32 inSize, const void* data, U8* basePointer); void internalSet(GFXShaderConstHandle* handle, const U32 inSize, const void* data); @@ -217,11 +205,11 @@ protected: // These two functions are used when compiling shaders from hlsl virtual bool _compileShader( const Torque::Path &filePath, - SHADER_STAGE shaderStage, + GFXShaderStage shaderStage, const D3D_SHADER_MACRO *defines); void _getShaderConstants( ID3D11ShaderReflection* refTable, - SHADER_STAGE shaderStage); + GFXShaderStage shaderStage); // This is used in both cases virtual void _buildShaderConstantHandles(); diff --git a/Engine/source/gfx/gfxShader.h b/Engine/source/gfx/gfxShader.h index 3e17246c1..91d7f28f6 100644 --- a/Engine/source/gfx/gfxShader.h +++ b/Engine/source/gfx/gfxShader.h @@ -65,6 +65,17 @@ class GFXShader; class GFXVertexFormat; +enum GFXShaderStage +{ + VERTEX_SHADER = BIT(0), + PIXEL_SHADER = BIT(1), + GEOMETRY_SHADER = BIT(2), + DOMAIN_SHADER = BIT(3), + HULL_SHADER = BIT(4), + COMPUTE_SHADER = BIT(5), + UNKNOWN_STAGE = 0 +}; + /// Instances of this struct are returned GFXShaderConstBuffer struct GFXShaderConstDesc { @@ -76,7 +87,7 @@ public: S32 samplerReg; // sampler register. U32 offset; // offset for vars U32 size; // size of buffer/type - U32 shaderStage; // only used dx side. + GFXShaderStage shaderStage; // only used dx side. }; /// This is an opaque handle used by GFXShaderConstBuffer clients to set individual shader constants. From c876e8695703abebb39c8cee8bfa376dbcc902ee Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Mon, 26 Feb 2024 16:38:56 +0000 Subject: [PATCH 20/53] Update gfxD3D11Shader.cpp cleanups --- Engine/source/gfx/D3D11/gfxD3D11Shader.cpp | 51 ++++++++++------------ 1 file changed, 22 insertions(+), 29 deletions(-) diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp index b8429eb63..39c6004df 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp @@ -164,8 +164,6 @@ GFXD3D11ShaderConstBuffer::GFXD3D11ShaderConstBuffer( GFXD3D11Shader* shader) GFXD3D11ShaderConstBuffer::~GFXD3D11ShaderConstBuffer() { - mBufferMap.clear(); - for (U32 i = 0; i < 6; i++) { for (U32 j = 0; j < 16; j++) @@ -469,17 +467,11 @@ const String GFXD3D11ShaderConstBuffer::describeSelf() const void GFXD3D11ShaderConstBuffer::addBuffer(U32 bufBindingPoint, GFXShaderStage shaderStage, U32 size) { const BufferKey bufKey(bufBindingPoint, shaderStage); - BufferMap::Iterator buffer = mBufferMap.find(bufKey); - // already added? pass... - if (buffer != mBufferMap.end()) - return; - - // new buffer with our size. + // doesnt matter if its already added. U8* buf = new U8[size]; dMemset(buf, 0, size); mBufferMap[bufKey].data = buf; mBufferMap[bufKey].size = size; - // always dirty on new. mBufferMap[bufKey].isDirty = true; D3D11_BUFFER_DESC cbDesc; @@ -515,23 +507,31 @@ void GFXD3D11ShaderConstBuffer::activate( GFXD3D11ShaderConstBuffer *prevShaderB if (prevShaderBuffer != this) { - - const ConstantBuffer prevBuffer = prevShaderBuffer->mBufferMap[i->key]; - - if (prevBuffer.data && !prevBuffer.isDirty) + if (prevShaderBuffer) { - if (prevBuffer.size != thisBuff.size) - { - thisBuff.isDirty = true; - } + const ConstantBuffer prevBuffer = prevShaderBuffer->mBufferMap[i->key]; - if (dMemcmp(prevBuffer.data, thisBuff.data, thisBuff.size) != 0) + if (prevBuffer.data && !prevBuffer.isDirty) { - thisBuff.isDirty = true; + if (prevBuffer.size != thisBuff.size) + { + thisBuff.isDirty = true; + } + else + { + if (dMemcmp(prevBuffer.data, thisBuff.data, thisBuff.size) != 0) + { + thisBuff.isDirty = true; + } + else + { + thisBuff.isDirty = false; + } + } } else { - thisBuff.isDirty = false; + thisBuff.isDirty = true; } } else @@ -580,12 +580,6 @@ void GFXD3D11ShaderConstBuffer::onShaderReload( GFXD3D11Shader *shader ) } } - for (BufferMap::Iterator i = mBufferMap.begin(); i != mBufferMap.end(); i++) - { - delete[] i->value.data; - } - mBufferMap.clear(); - for (GFXD3D11Shader::BufferMap::Iterator i = shader->mBuffers.begin(); i != shader->mBuffers.end(); ++i) { // add our buffer descriptions to the full const buffer. @@ -614,9 +608,8 @@ GFXD3D11Shader::GFXD3D11Shader() GFXD3D11Shader::~GFXD3D11Shader() { - mHandles.clear(); - - mBuffers.clear(); + for (HandleMap::Iterator i = mHandles.begin(); i != mHandles.end(); i++) + delete i->value; // release shaders SAFE_RELEASE(mVertShader); From 37636bcd26c3d571cdb5dc6293f5c35d15e40a8c Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Mon, 26 Feb 2024 22:25:11 +0000 Subject: [PATCH 21/53] switch to vectors uses vectors for buffers instead of 2d array --- Engine/source/gfx/D3D11/gfxD3D11Shader.cpp | 102 +++++++++++---------- Engine/source/gfx/D3D11/gfxD3D11Shader.h | 3 +- Engine/source/gfx/gfxShader.h | 3 +- 3 files changed, 56 insertions(+), 52 deletions(-) diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp index 39c6004df..14acc8d80 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp @@ -154,24 +154,26 @@ GFXD3D11ShaderConstBuffer::GFXD3D11ShaderConstBuffer( GFXD3D11Shader* shader) for (U32 i = 0; i < 6; i++) { - for (U32 j = 0; j < 16; j++) - { - mBoundConstantBuffers[i][j] = NULL; - } + VECTOR_SET_ASSOCIATION(mBoundConstVec[i]); } - } GFXD3D11ShaderConstBuffer::~GFXD3D11ShaderConstBuffer() { for (U32 i = 0; i < 6; i++) { - for (U32 j = 0; j < 16; j++) + for (U32 j = 0; j < mBoundConstVec[i].size(); j++) { - SAFE_RELEASE(mBoundConstantBuffers[i][j]); + SAFE_RELEASE(mBoundConstVec[i][j]); } + mBoundConstVec[i].clear(); } + for (auto& pair : mBufferMap) { + delete[] pair.value.data; + } + mBufferMap.clear(); // Clear the map + if (mShader) mShader->_unlinkBuffer(this); } @@ -415,7 +417,7 @@ void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF& if (_dxHandle->mInstancingConstant) { if (matrixType == GFXSCT_Float4x4) - dMemcpy(mInstPtr + _dxHandle->mOffset, mat, sizeof(mat)); + dMemcpy(mInstPtr + _dxHandle->mDesc.offset, mat, sizeof(mat)); // TODO: Support 3x3 and 2x2 matricies? return; @@ -474,6 +476,7 @@ void GFXD3D11ShaderConstBuffer::addBuffer(U32 bufBindingPoint, GFXShaderStage sh mBufferMap[bufKey].size = size; mBufferMap[bufKey].isDirty = true; + ID3D11Buffer* tempBuf; D3D11_BUFFER_DESC cbDesc; cbDesc.ByteWidth = size; cbDesc.Usage = D3D11_USAGE_DEFAULT; @@ -483,12 +486,14 @@ void GFXD3D11ShaderConstBuffer::addBuffer(U32 bufBindingPoint, GFXShaderStage sh cbDesc.StructureByteStride = 0; HRESULT hr; - hr = D3D11DEVICE->CreateBuffer(&cbDesc, NULL, &mBoundConstantBuffers[shaderStage][bufBindingPoint]); + hr = D3D11DEVICE->CreateBuffer(&cbDesc, NULL, &tempBuf); if (FAILED(hr)) { AssertFatal(false, "can't create constant buffer"); } + + mBoundConstVec[shaderStage - 1].push_back(tempBuf); } void GFXD3D11ShaderConstBuffer::activate( GFXD3D11ShaderConstBuffer *prevShaderBuffer ) @@ -507,32 +512,25 @@ void GFXD3D11ShaderConstBuffer::activate( GFXD3D11ShaderConstBuffer *prevShaderB if (prevShaderBuffer != this) { - if (prevShaderBuffer) - { - const ConstantBuffer prevBuffer = prevShaderBuffer->mBufferMap[i->key]; + const ConstantBuffer prevBuffer = prevShaderBuffer->mBufferMap[i->key]; - if (prevBuffer.data && !prevBuffer.isDirty) + if (prevBuffer.data && !prevBuffer.isDirty) + { + if (prevBuffer.size != thisBuff.size) { - if (prevBuffer.size != thisBuff.size) + thisBuff.isDirty = true; + } + else + { + if (dMemcmp(prevBuffer.data, thisBuff.data, thisBuff.size) != 0) { thisBuff.isDirty = true; } else { - if (dMemcmp(prevBuffer.data, thisBuff.data, thisBuff.size) != 0) - { - thisBuff.isDirty = true; - } - else - { - thisBuff.isDirty = false; - } + thisBuff.isDirty = false; } } - else - { - thisBuff.isDirty = true; - } } else { @@ -542,25 +540,25 @@ void GFXD3D11ShaderConstBuffer::activate( GFXD3D11ShaderConstBuffer *prevShaderB if (thisBuff.data && thisBuff.isDirty) { - D3D11DEVICECONTEXT->UpdateSubresource(mBoundConstantBuffers[thisBufferDesc.key2][thisBufferDesc.key1], 0, NULL, thisBuff.data, thisBuff.size, 0); - bufRanges[thisBufferDesc.key2].addSlot(thisBufferDesc.key1); + D3D11DEVICECONTEXT->UpdateSubresource(mBoundConstVec[thisBufferDesc.key2 - 1][thisBufferDesc.key1], 0, NULL, thisBuff.data, thisBuff.size, 0); + bufRanges[thisBufferDesc.key2-1].addSlot(thisBufferDesc.key1); } } - if (mShader->mVertShader && bufRanges[GFXShaderStage::VERTEX_SHADER].isValid()) + if (mShader->mVertShader && bufRanges[GFXShaderStage::VERTEX_SHADER - 1].isValid()) { - const U32 bufStartSlot = bufRanges[GFXShaderStage::VERTEX_SHADER].mBufMin; - const U32 numBufs = bufRanges[GFXShaderStage::VERTEX_SHADER].mBufMax - bufRanges[GFXShaderStage::VERTEX_SHADER].mBufMin + 1; - ID3D11Buffer** vsBuffers = mBoundConstantBuffers[GFXShaderStage::VERTEX_SHADER] + bufStartSlot; + const U32 bufStartSlot = bufRanges[GFXShaderStage::VERTEX_SHADER - 1].mBufMin; + const U32 numBufs = bufRanges[GFXShaderStage::VERTEX_SHADER - 1].mBufMax - bufRanges[GFXShaderStage::VERTEX_SHADER - 1].mBufMin + 1; + ID3D11Buffer** vsBuffers = mBoundConstVec[GFXShaderStage::VERTEX_SHADER-1].address() + bufStartSlot; D3D11DEVICECONTEXT->VSSetConstantBuffers(bufStartSlot, numBufs, vsBuffers); } - if (mShader->mPixShader && bufRanges[GFXShaderStage::PIXEL_SHADER].isValid()) + if (mShader->mPixShader && bufRanges[GFXShaderStage::PIXEL_SHADER - 1].isValid()) { - const U32 bufStartSlot = bufRanges[GFXShaderStage::PIXEL_SHADER].mBufMin; - const U32 numBufs = bufRanges[GFXShaderStage::PIXEL_SHADER].mBufMax - bufRanges[GFXShaderStage::PIXEL_SHADER].mBufMin + 1; - ID3D11Buffer** psBuffers = mBoundConstantBuffers[GFXShaderStage::PIXEL_SHADER] + bufStartSlot; + const U32 bufStartSlot = bufRanges[GFXShaderStage::PIXEL_SHADER - 1].mBufMin; + const U32 numBufs = bufRanges[GFXShaderStage::PIXEL_SHADER - 1].mBufMax - bufRanges[GFXShaderStage::PIXEL_SHADER - 1].mBufMin + 1; + ID3D11Buffer** psBuffers = mBoundConstVec[GFXShaderStage::PIXEL_SHADER-1].address() + bufStartSlot; D3D11DEVICECONTEXT->PSSetConstantBuffers(bufStartSlot, numBufs, psBuffers); } @@ -574,12 +572,18 @@ void GFXD3D11ShaderConstBuffer::onShaderReload( GFXD3D11Shader *shader ) for (U32 i = 0; i < 6; i++) { - for (U32 j = 0; j < 16; j++) + for (U32 j = 0; j < mBoundConstVec[i].size(); j++) { - SAFE_RELEASE(mBoundConstantBuffers[i][j]); + SAFE_RELEASE(mBoundConstVec[i][j]); } + mBoundConstVec[i].clear(); } + for (auto& pair : mBufferMap) { + delete[] pair.value.data; + } + mBufferMap.clear(); // Clear the map + for (GFXD3D11Shader::BufferMap::Iterator i = shader->mBuffers.begin(); i != shader->mBuffers.end(); ++i) { // add our buffer descriptions to the full const buffer. @@ -608,8 +612,10 @@ GFXD3D11Shader::GFXD3D11Shader() GFXD3D11Shader::~GFXD3D11Shader() { - for (HandleMap::Iterator i = mHandles.begin(); i != mHandles.end(); i++) - delete i->value; + for (auto& pair : mHandles) { + delete pair.value; + } + mHandles.clear(); // release shaders SAFE_RELEASE(mVertShader); @@ -653,6 +659,7 @@ bool GFXD3D11Shader::_init() if (!mPixelFile.isEmpty() && !_compileShader( mPixelFile, GFXShaderStage::PIXEL_SHADER, d3dMacros)) return false; + _buildShaderConstantHandles(); // Notify any existing buffers that the buffer @@ -879,7 +886,7 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection* refTable, desc.bindPoint = shaderInputBind.BindPoint; if (String::compare(desc.name, "$Globals") == 0 || String::compare(desc.name, "$Params") == 0) { - desc.name = desc.name + String::ToString((U32)shaderStage); + desc.name = desc.name + String::ToString((U32)shaderStage-1); if (foundGlobals) desc.bindPoint += 1; @@ -887,12 +894,7 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection* refTable, foundGlobals = true; } - BufferMap::Iterator buffer = mBuffers.find(desc.name); - // already added? - if (buffer == mBuffers.end()) - { - mBuffers[desc.name] = desc; - } + mBuffers[desc.name] = desc; // now loop vars and add them to mShaderConsts. for (U32 j = 0; j < constantBufferDesc.Variables; j++) @@ -905,6 +907,10 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection* refTable, D3D11_SHADER_TYPE_DESC shaderTypeDesc; bufferVar->GetType()->GetDesc(&shaderTypeDesc); + bool unusedVar = shaderVarDesc.uFlags & D3D_SVF_USED ? false : true; + if (unusedVar) + continue; + varDesc.name = String(shaderVarDesc.Name); if (varDesc.name.find("$") != 0) varDesc.name = String::ToString("$%s", varDesc.name.c_str()); @@ -955,7 +961,7 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection* refTable, varDesc.constType = shaderTypeDesc.Columns == 4 ? GFXSCT_Float3x4 : GFXSCT_Float3x3; break; case 4: - varDesc.constType = shaderTypeDesc.Columns == 3 ? GFXSCT_Float3x3 : GFXSCT_Float4x4; + varDesc.constType = shaderTypeDesc.Columns == 3 ? GFXSCT_Float4x3 : GFXSCT_Float4x4; break; } } diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.h b/Engine/source/gfx/D3D11/gfxD3D11Shader.h index 7b99f6a0a..14118e57b 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.h +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.h @@ -154,9 +154,8 @@ protected: void setMatrix(GFXShaderConstHandle* handle, const U32 inSize, const void* data, U8* basePointer); void internalSet(GFXShaderConstHandle* handle, const U32 inSize, const void* data); - // we probably want this to be GFXDevice and not per shader. - ID3D11Buffer* mBoundConstantBuffers[6][16]; + Vector mBoundConstVec[6]; }; class gfxD3D11Include; diff --git a/Engine/source/gfx/gfxShader.h b/Engine/source/gfx/gfxShader.h index 91d7f28f6..4a880135d 100644 --- a/Engine/source/gfx/gfxShader.h +++ b/Engine/source/gfx/gfxShader.h @@ -72,8 +72,7 @@ enum GFXShaderStage GEOMETRY_SHADER = BIT(2), DOMAIN_SHADER = BIT(3), HULL_SHADER = BIT(4), - COMPUTE_SHADER = BIT(5), - UNKNOWN_STAGE = 0 + COMPUTE_SHADER = BIT(5) }; /// Instances of this struct are returned GFXShaderConstBuffer From 78df01af5553e65ab34c58e8c1974b00ac954963 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Mon, 26 Feb 2024 22:44:32 +0000 Subject: [PATCH 22/53] Update gfxD3D11Shader.cpp plugging leaks --- Engine/source/gfx/D3D11/gfxD3D11Shader.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp index 14acc8d80..1bb22a164 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp @@ -613,7 +613,10 @@ GFXD3D11Shader::GFXD3D11Shader() GFXD3D11Shader::~GFXD3D11Shader() { for (auto& pair : mHandles) { - delete pair.value; + if (pair.value != nullptr) { + delete pair.value; + pair.value = nullptr; + } } mHandles.clear(); @@ -1079,8 +1082,9 @@ 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); + for (auto& pair : mHandles) { + pair.value->setValid(false); + } // loop through all constants, add them to the handle map // and add the const buffers to the buffer map. From e9a38539a3dc1b91b26deda6e62ac4f0931e19a8 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Tue, 27 Feb 2024 09:15:19 +0000 Subject: [PATCH 23/53] multiple desc per handle Added multiple descriptions to handles. While maps are very efficient and match data very quickly due to hashing and what not, they are tricky memory wise, we cant clear them if they are only made up of structs and enums. Need to explore other methods for doing this. Original system had a sub buffer system with a check based on whether the handle was marked vertex/pixel. With 6 stages possible now we need to think of a more effective method. Since shaderstage is now a bit flag maybe some sort of streaming setup could be used to write without a loop. --- Engine/source/gfx/D3D11/gfxD3D11Shader.cpp | 91 ++++++++++------------ Engine/source/gfx/D3D11/gfxD3D11Shader.h | 27 +++++-- 2 files changed, 59 insertions(+), 59 deletions(-) diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp index 1bb22a164..f12ea5a15 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp @@ -95,13 +95,12 @@ HRESULT gfxD3D11Include::Close( THIS_ LPCVOID pData ) GFXD3D11ShaderConstHandle::GFXD3D11ShaderConstHandle(GFXD3D11Shader* shader) : mShader(shader), - mOffset(0), mSize(0), - mBinding(-1), mSampler(-1), + mArraySize(1), mInstancingConstant(false) { - dMemset(&mDesc, 0, sizeof(mDesc)); + mType = GFXSCT_ConstBuffer; mValid = false; mStageFlags = 0; } @@ -109,18 +108,17 @@ GFXD3D11ShaderConstHandle::GFXD3D11ShaderConstHandle(GFXD3D11Shader* shader) GFXD3D11ShaderConstHandle::GFXD3D11ShaderConstHandle(GFXD3D11Shader* shader, const GFXShaderConstDesc& desc) : mShader(shader), - mDesc(desc), - - mOffset(desc.offset), mSize(desc.size), - mBinding(desc.bindPoint), mSampler(desc.samplerReg), + mType(desc.constType), + mArraySize(desc.arraySize), mInstancingConstant(false) { if (desc.constType == GFXSCT_ConstBuffer) mValid = false; else mValid = true; + addDesc(desc.shaderStage, desc); mStageFlags = desc.shaderStage; } @@ -129,25 +127,20 @@ GFXD3D11ShaderConstHandle::~GFXD3D11ShaderConstHandle() { } -void GFXD3D11ShaderConstHandle::reinit(const GFXShaderConstDesc& desc) +void GFXD3D11ShaderConstHandle::addDesc(GFXShaderStage stage, const GFXShaderConstDesc& desc) { - mDesc = desc; - mStageFlags = desc.shaderStage; - mOffset = desc.offset; - mSize = desc.size * desc.arraySize; - mBinding = desc.bindPoint; - mSampler = desc.samplerReg; - mInstancingConstant = false; + // just add for now. + mDescMap[stage] = desc; +} - if (desc.constType == GFXSCT_ConstBuffer) - mValid = false; - else - mValid = true; +const GFXShaderConstDesc GFXD3D11ShaderConstHandle::getDesc(GFXShaderStage stage) +{ + return mDescMap[stage]; } //------------------------------------------------------------------------------ -GFXD3D11ShaderConstBuffer::GFXD3D11ShaderConstBuffer( GFXD3D11Shader* shader) +GFXD3D11ShaderConstBuffer::GFXD3D11ShaderConstBuffer(GFXD3D11Shader* shader) { mShader = shader; mDeviceContext = D3D11DEVICECONTEXT; @@ -183,23 +176,16 @@ GFXShader* GFXD3D11ShaderConstBuffer::getShader() return mShader; } -void GFXD3D11ShaderConstBuffer::setMatrix(GFXShaderConstHandle* handle, const U32 inSize, const void* data, U8* basePointer) +void GFXD3D11ShaderConstBuffer::setMatrix(const GFXShaderConstDesc& constDesc, const U32 inSize, const void* data, U8* basePointer) { - 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"); - U8* buf = basePointer; - if (_dxHandle->mDesc.constType == GFXSCT_Float4x4) + if (constDesc.constType == GFXSCT_Float4x4) { // Special case, we can just blast this guy. - if (dMemcmp(buf + _dxHandle->mDesc.offset, data, inSize) != 0) + if (dMemcmp(buf + constDesc.offset, data, inSize) != 0) { - dMemcpy(buf + _dxHandle->mDesc.offset, data, inSize); + dMemcpy(buf + constDesc.offset, data, inSize); } return; @@ -210,7 +196,7 @@ void GFXD3D11ShaderConstBuffer::setMatrix(GFXShaderConstHandle* handle, const U3 // Figure out how big of a chunk we are copying. We're going to copy 4 columns by N rows of data U32 csize; - switch (_dxHandle->mDesc.constType) + switch (constDesc.constType) { case GFXSCT_Float2x2: csize = 24; //this takes up 16+8 @@ -229,7 +215,7 @@ void GFXD3D11ShaderConstBuffer::setMatrix(GFXShaderConstHandle* handle, const U3 // Loop through and copy bool ret = false; - U8* currDestPointer = buf + _dxHandle->mDesc.offset; + U8* currDestPointer = buf + constDesc.offset; const U8* currSourcePointer = static_cast(data); const U8* endData = currSourcePointer + inSize; while (currSourcePointer < endData) @@ -260,36 +246,37 @@ void GFXD3D11ShaderConstBuffer::internalSet(GFXShaderConstHandle* handle, const { if (_dxHandle->mStageFlags & i) { - BufferKey bufDesc(_dxHandle->mBinding, (GFXShaderStage)i); + GFXShaderConstDesc constDesc = _dxHandle->getDesc((GFXShaderStage)i); + BufferKey bufDesc(constDesc.bindPoint, (GFXShaderStage)i); U8* basePointer = mBufferMap[bufDesc].data; if (_dxHandle->mInstancingConstant) { - dMemcpy(mInstPtr + _dxHandle->mOffset, data, size); + dMemcpy(mInstPtr + constDesc.offset, data, size); return; } - switch (_dxHandle->mDesc.constType) + switch (constDesc.constType) { case GFXSCT_Float2x2: case GFXSCT_Float3x3: case GFXSCT_Float4x3: case GFXSCT_Float4x4: - setMatrix(handle, size, data, basePointer); + setMatrix(constDesc, size, data, basePointer); return; break; // TODO add other AlignedVector here case GFXSCT_Float2: if (size > sizeof(Point2F)) - size = _dxHandle->mDesc.size; + size = constDesc.size; break; default: break; } - if (dMemcmp(basePointer + _dxHandle->mDesc.offset, data, size) != 0) + if (dMemcmp(basePointer + constDesc.offset, data, size) != 0) { - dMemcpy(basePointer + _dxHandle->mDesc.offset, data, size); + dMemcpy(basePointer + constDesc.offset, data, size); } } } @@ -399,8 +386,9 @@ void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF& AssertFatal(handle, "Handle is NULL!"); AssertFatal(handle->isValid(), "Handle is not valid!"); - AssertFatal(static_cast(handle), "Incorrect const buffer type!"); - const GFXD3D11ShaderConstHandle* _dxHandle = static_cast(handle); + AssertFatal(static_cast(handle), "Incorrect const buffer type!"); + GFXD3D11ShaderConstHandle* _dxHandle = static_cast(handle); + AssertFatal(!_dxHandle->isSampler(), "Handle is sampler constant!"); AssertFatal(_dxHandle->mShader == mShader, "Mismatched shaders!"); @@ -416,8 +404,9 @@ void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF& if (_dxHandle->mInstancingConstant) { + GFXShaderConstDesc constDesc = _dxHandle->getDesc(GFXShaderStage::PIXEL_SHADER); if (matrixType == GFXSCT_Float4x4) - dMemcpy(mInstPtr + _dxHandle->mDesc.offset, mat, sizeof(mat)); + dMemcpy(mInstPtr + constDesc.offset, mat, sizeof(mat)); // TODO: Support 3x3 and 2x2 matricies? return; @@ -656,13 +645,19 @@ bool GFXD3D11Shader::_init() mShaderConsts.clear(); mSamplerDescriptions.clear(); + if (!mVertexFile.isEmpty() && !_compileShader( mVertexFile, GFXShaderStage::VERTEX_SHADER, d3dMacros) ) return false; if (!mPixelFile.isEmpty() && !_compileShader( mPixelFile, GFXShaderStage::PIXEL_SHADER, d3dMacros)) return false; - + // Mark all existing handles as invalid. + // Those that are found when parsing the descriptions will then be marked valid again. + for (auto& pair : mHandles) { + pair.value->clear(); + } + _buildShaderConstantHandles(); // Notify any existing buffers that the buffer @@ -1080,12 +1075,6 @@ 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 (auto& pair : mHandles) { - pair.value->setValid(false); - } - // 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++) @@ -1101,7 +1090,7 @@ void GFXD3D11Shader::_buildShaderConstantHandles() handle->mShader = this; if((handle->mStageFlags & desc.shaderStage) == 0) handle->mStageFlags |= (U32)desc.shaderStage; - + handle->addDesc(desc.shaderStage, desc); handle->setValid(true); } else diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.h b/Engine/source/gfx/D3D11/gfxD3D11Shader.h index 14118e57b..d758be32a 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.h +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.h @@ -60,16 +60,18 @@ class GFXD3D11ShaderConstHandle : public GFXShaderConstHandle { friend class GFXD3D11Shader; public: + typedef Map DescMap; GFXD3D11ShaderConstHandle(GFXD3D11Shader* shader); GFXD3D11ShaderConstHandle(GFXD3D11Shader* shader, 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; } + void addDesc(GFXShaderStage stage, const GFXShaderConstDesc& desc); + const GFXShaderConstDesc getDesc(GFXShaderStage stage); + const String& getName() const { return mName; } + GFXShaderConstType getType() const { return mType; } + U32 getArraySize() const { return mArraySize; } U32 getSize() const { return mSize; } void setValid(bool valid) { mValid = valid; } @@ -83,11 +85,20 @@ public: return (getType() >= GFXSCT_Sampler); } - GFXShaderConstDesc mDesc; + /// Restore to uninitialized state. + void clear() + { + mShader = NULL; + mInstancingConstant = false; + mValid = false; + } + GFXD3D11Shader* mShader; - U32 mOffset; + DescMap mDescMap; + String mName; + GFXShaderConstType mType; U32 mSize; - S32 mBinding; // buffer binding point used to map handles to buffers. + U32 mArraySize; S32 mSampler; // sampler number, will be -1 if not a sampler. U32 mStageFlags; bool mInstancingConstant; @@ -151,7 +162,7 @@ protected: WeakRefPtr mShader; BufferMap mBufferMap; - void setMatrix(GFXShaderConstHandle* handle, const U32 inSize, const void* data, U8* basePointer); + void setMatrix(const GFXShaderConstDesc& handle, const U32 inSize, const void* data, U8* basePointer); void internalSet(GFXShaderConstHandle* handle, const U32 inSize, const void* data); // we probably want this to be GFXDevice and not per shader. From 040bbdd6d618af860f36781366e84ef93f9178f5 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Tue, 27 Feb 2024 14:51:59 +0000 Subject: [PATCH 24/53] Update gfxD3D11Shader.cpp turns out we dont need to do this if both exist the bind point gets changed anyway --- Engine/source/gfx/D3D11/gfxD3D11Shader.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp index f12ea5a15..25b2e8139 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp @@ -864,7 +864,6 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection* refTable, AssertFatal(false, "Shader Reflection table unable to be created"); } // we loop through and account for the most common data types. - bool foundGlobals = false; for (U32 i = 0; i < shaderDesc.ConstantBuffers; i++) { GFXShaderConstDesc desc; @@ -885,11 +884,6 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection* refTable, if (String::compare(desc.name, "$Globals") == 0 || String::compare(desc.name, "$Params") == 0) { desc.name = desc.name + String::ToString((U32)shaderStage-1); - - if (foundGlobals) - desc.bindPoint += 1; - - foundGlobals = true; } mBuffers[desc.name] = desc; From cd8914b9adc8ad5c214276dc44dcbfba0c9bfe21 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Tue, 27 Feb 2024 20:59:10 +0000 Subject: [PATCH 25/53] reverse bitshift need to reverse the bitshift on shaderstages so we get values between 0-5, need to also revert the mBoundConstVec back to a 2dimensional array so that the binding point can be dynamic as well. --- Engine/source/gfx/D3D11/gfxD3D11Shader.cpp | 180 +++++++++++++-------- Engine/source/gfx/D3D11/gfxD3D11Shader.h | 5 +- 2 files changed, 114 insertions(+), 71 deletions(-) diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp index 25b2e8139..1bde8a3df 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp @@ -246,8 +246,16 @@ void GFXD3D11ShaderConstBuffer::internalSet(GFXShaderConstHandle* handle, const { if (_dxHandle->mStageFlags & i) { + S32 shaderStageID = -1; // Initialize to -1 (bit not found) + for (int j = 0; j < sizeof(S32) * 8; ++j) { + if (i & (1 << j)) { + shaderStageID = j; + break; + } + } + GFXShaderConstDesc constDesc = _dxHandle->getDesc((GFXShaderStage)i); - BufferKey bufDesc(constDesc.bindPoint, (GFXShaderStage)i); + BufferKey bufDesc(constDesc.bindPoint, shaderStageID); U8* basePointer = mBufferMap[bufDesc].data; if (_dxHandle->mInstancingConstant) @@ -457,7 +465,15 @@ const String GFXD3D11ShaderConstBuffer::describeSelf() const void GFXD3D11ShaderConstBuffer::addBuffer(U32 bufBindingPoint, GFXShaderStage shaderStage, U32 size) { - const BufferKey bufKey(bufBindingPoint, shaderStage); + S32 shaderStageID = -1; // Initialize to -1 (bit not found) + for (int i = 0; i < sizeof(S32) * 8; ++i) { + if (shaderStage & (1 << i)) { + shaderStageID = i; + break; + } + } + + const BufferKey bufKey(bufBindingPoint, shaderStageID); // doesnt matter if its already added. U8* buf = new U8[size]; dMemset(buf, 0, size); @@ -482,7 +498,7 @@ void GFXD3D11ShaderConstBuffer::addBuffer(U32 bufBindingPoint, GFXShaderStage sh AssertFatal(false, "can't create constant buffer"); } - mBoundConstVec[shaderStage - 1].push_back(tempBuf); + mBoundConstVec[shaderStageID].push_back(tempBuf); } void GFXD3D11ShaderConstBuffer::activate( GFXD3D11ShaderConstBuffer *prevShaderBuffer ) @@ -529,25 +545,25 @@ void GFXD3D11ShaderConstBuffer::activate( GFXD3D11ShaderConstBuffer *prevShaderB if (thisBuff.data && thisBuff.isDirty) { - D3D11DEVICECONTEXT->UpdateSubresource(mBoundConstVec[thisBufferDesc.key2 - 1][thisBufferDesc.key1], 0, NULL, thisBuff.data, thisBuff.size, 0); - bufRanges[thisBufferDesc.key2-1].addSlot(thisBufferDesc.key1); + D3D11DEVICECONTEXT->UpdateSubresource(mBoundConstVec[thisBufferDesc.key2][thisBufferDesc.key1], 0, NULL, thisBuff.data, thisBuff.size, 0); + bufRanges[thisBufferDesc.key2].addSlot(thisBufferDesc.key1); } } - if (mShader->mVertShader && bufRanges[GFXShaderStage::VERTEX_SHADER - 1].isValid()) + if (mShader->mVertShader && bufRanges[0].isValid()) { - const U32 bufStartSlot = bufRanges[GFXShaderStage::VERTEX_SHADER - 1].mBufMin; - const U32 numBufs = bufRanges[GFXShaderStage::VERTEX_SHADER - 1].mBufMax - bufRanges[GFXShaderStage::VERTEX_SHADER - 1].mBufMin + 1; - ID3D11Buffer** vsBuffers = mBoundConstVec[GFXShaderStage::VERTEX_SHADER-1].address() + bufStartSlot; + const U32 bufStartSlot = bufRanges[0].mBufMin; + const U32 numBufs = bufRanges[0].mBufMax - bufRanges[0].mBufMin + 1; + ID3D11Buffer** vsBuffers = mBoundConstVec[0].address() + bufStartSlot; D3D11DEVICECONTEXT->VSSetConstantBuffers(bufStartSlot, numBufs, vsBuffers); } - if (mShader->mPixShader && bufRanges[GFXShaderStage::PIXEL_SHADER - 1].isValid()) + if (mShader->mPixShader && bufRanges[1].isValid()) { - const U32 bufStartSlot = bufRanges[GFXShaderStage::PIXEL_SHADER - 1].mBufMin; - const U32 numBufs = bufRanges[GFXShaderStage::PIXEL_SHADER - 1].mBufMax - bufRanges[GFXShaderStage::PIXEL_SHADER - 1].mBufMin + 1; - ID3D11Buffer** psBuffers = mBoundConstVec[GFXShaderStage::PIXEL_SHADER-1].address() + bufStartSlot; + const U32 bufStartSlot = bufRanges[1].mBufMin; + const U32 numBufs = bufRanges[1].mBufMax - bufRanges[1].mBufMin + 1; + ID3D11Buffer** psBuffers = mBoundConstVec[1].address() + bufStartSlot; D3D11DEVICECONTEXT->PSSetConstantBuffers(bufStartSlot, numBufs, psBuffers); } @@ -891,7 +907,6 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection* refTable, // now loop vars and add them to mShaderConsts. for (U32 j = 0; j < constantBufferDesc.Variables; j++) { - GFXShaderConstDesc varDesc; ID3D11ShaderReflectionVariable* bufferVar = constantBuffer->GetVariableByIndex(j); D3D11_SHADER_VARIABLE_DESC shaderVarDesc; bufferVar->GetDesc(&shaderVarDesc); @@ -903,67 +918,49 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection* refTable, if (unusedVar) continue; - varDesc.name = String(shaderVarDesc.Name); - if (varDesc.name.find("$") != 0) - varDesc.name = String::ToString("$%s", varDesc.name.c_str()); - - // set the bind point to the same as the const buffer. - varDesc.bindPoint = desc.bindPoint; - varDesc.offset = shaderVarDesc.StartOffset; - varDesc.arraySize = mMax(shaderTypeDesc.Elements, 1); - varDesc.size = shaderVarDesc.Size; - varDesc.shaderStage = shaderStage; - varDesc.samplerReg = -1; - -#ifdef D3D11_DEBUG_SPEW - Con::printf("Variable Name %s:, offset: %d, size: %d, constantDesc.Elements: %d", varDesc.name.c_str(), varDesc.StartOffset, varDesc.Size, varDesc.arraySize); -#endif - - if (shaderTypeDesc.Class == D3D_SVC_SCALAR || shaderTypeDesc.Class == D3D_SVC_VECTOR) - { - switch (shaderTypeDesc.Type) - { - case D3D_SVT_BOOL: - varDesc.constType = (GFXShaderConstType)((U32)GFXSCT_Bool + shaderTypeDesc.Columns - 1); - break; - case D3D_SVT_INT: - varDesc.constType = (GFXShaderConstType)((U32)GFXSCT_Int + shaderTypeDesc.Columns - 1); - break; - case D3D_SVT_FLOAT: - varDesc.constType = (GFXShaderConstType)((U32)GFXSCT_Float + shaderTypeDesc.Columns - 1); - break; - case D3D_SVT_UINT: - varDesc.constType = (GFXShaderConstType)((U32)GFXSCT_UInt + shaderTypeDesc.Columns - 1); - break; - default: - AssertFatal(false, "Unknown shader constant class enum, maybe you could add it?"); - break; - } - } - else if (shaderTypeDesc.Class == D3D_SVC_MATRIX_COLUMNS || shaderTypeDesc.Class == D3D_SVC_MATRIX_ROWS) - { - if (shaderTypeDesc.Type != D3D_SVT_FLOAT) - { - AssertFatal(false, "Only Float matrices are supported for now. Support for other types needs to be added."); - } - - switch (shaderTypeDesc.Rows) - { - case 3: - varDesc.constType = shaderTypeDesc.Columns == 4 ? GFXSCT_Float3x4 : GFXSCT_Float3x3; - break; - case 4: - varDesc.constType = shaderTypeDesc.Columns == 3 ? GFXSCT_Float4x3 : GFXSCT_Float4x4; - break; - } - } - else if (shaderTypeDesc.Class == D3D_SVC_STRUCT) + if (shaderTypeDesc.Class == D3D_SVC_STRUCT) { // we gotta loop through its variables =/ add support in future. for now continue so it skips. + // no idea how to handle arrays of structs.... + /*for (U32 j = 0; j < shaderTypeDesc.Members; j++) + { + GFXShaderConstDesc memVarDesc; + ID3D11ShaderReflectionType* memType = bufferVar->GetType()->GetMemberTypeByIndex(j); + D3D11_SHADER_TYPE_DESC memTypeDesc; + memType->GetDesc(&memTypeDesc); + memVarDesc.name = String(shaderVarDesc.Name) + "." + String(memTypeDesc.Name); + if (memVarDesc.name.find("$") != 0) + memVarDesc.name = String::ToString("$%s", memVarDesc.name.c_str()); + + #ifdef D3D11_DEBUG_SPEW + Con::printf("Variable Name %s:, offset: %d", memVarDesc.name.c_str(), memVarDesc.Offset); + #endif + + }*/ + continue; } + else + { + GFXShaderConstDesc varDesc; + varDesc.name = String(shaderVarDesc.Name); + if (varDesc.name.find("$") != 0) + varDesc.name = String::ToString("$%s", varDesc.name.c_str()); - mShaderConsts.push_back(varDesc); + // set the bind point to the same as the const buffer. + varDesc.bindPoint = desc.bindPoint; + varDesc.offset = shaderVarDesc.StartOffset; + varDesc.arraySize = mMax(shaderTypeDesc.Elements, 1); + varDesc.size = shaderVarDesc.Size; + varDesc.shaderStage = shaderStage; + varDesc.samplerReg = -1; + varDesc.constType = convertConstType(shaderTypeDesc); + +#ifdef D3D11_DEBUG_SPEW + Con::printf("Variable Name %s:, offset: %d, size: %d, constantDesc.Elements: %d", varDesc.name.c_str(), varDesc.StartOffset, varDesc.Size, varDesc.arraySize); +#endif + mShaderConsts.push_back(varDesc); + } } } @@ -1067,6 +1064,49 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection* refTable, } } +GFXShaderConstType GFXD3D11Shader::convertConstType(const D3D11_SHADER_TYPE_DESC typeDesc) +{ + if (typeDesc.Class == D3D_SVC_SCALAR || typeDesc.Class == D3D_SVC_VECTOR) + { + switch (typeDesc.Type) + { + case D3D_SVT_BOOL: + return (GFXShaderConstType)((U32)GFXSCT_Bool + typeDesc.Columns - 1); + break; + case D3D_SVT_INT: + return (GFXShaderConstType)((U32)GFXSCT_Int + typeDesc.Columns - 1); + break; + case D3D_SVT_FLOAT: + return (GFXShaderConstType)((U32)GFXSCT_Float + typeDesc.Columns - 1); + break; + case D3D_SVT_UINT: + return (GFXShaderConstType)((U32)GFXSCT_UInt + typeDesc.Columns - 1); + break; + default: + AssertFatal(false, "Unknown shader constant class enum, maybe you could add it?"); + break; + } + } + else if (typeDesc.Class == D3D_SVC_MATRIX_COLUMNS || typeDesc.Class == D3D_SVC_MATRIX_ROWS) + { + if (typeDesc.Type != D3D_SVT_FLOAT) + { + AssertFatal(false, "Only Float matrices are supported for now. Support for other types needs to be added."); + } + + switch (typeDesc.Rows) + { + case 3: + return typeDesc.Columns == 4 ? GFXSCT_Float3x4 : GFXSCT_Float3x3; + break; + case 4: + return typeDesc.Columns == 3 ? GFXSCT_Float4x3 : GFXSCT_Float4x4; + break; + } + } + +} + void GFXD3D11Shader::_buildShaderConstantHandles() { // loop through all constants, add them to the handle map diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.h b/Engine/source/gfx/D3D11/gfxD3D11Shader.h index d758be32a..42d6fdba5 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.h +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.h @@ -33,7 +33,7 @@ class GFXD3D11Shader; -typedef CompoundKey BufferKey; +typedef CompoundKey BufferKey; struct BufferRange { @@ -224,6 +224,9 @@ protected: // This is used in both cases virtual void _buildShaderConstantHandles(); void _buildInstancingShaderConstantHandles(); + + GFXShaderConstType convertConstType(D3D11_SHADER_TYPE_DESC typeDesc); + }; From a7021c0ed3b6d99fd73b8c558726a1712b7f4629 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Thu, 29 Feb 2024 14:34:22 +0000 Subject: [PATCH 26/53] cleanup Reverted back to a 2d array since when the const buffer changes are made to the shaders they will be completely swapped out for a 1d array with a max size of 16 for the program, id3d11buffers will be shared across shaders apart from object buffers. We still need to decide on a structure to get everything setup so to keep functionality a max of 2 buffers per stage with 1 buffer as a padding so we can start coding constant buffers right away --- Engine/source/gfx/D3D11/gfxD3D11Shader.cpp | 68 ++++++---------------- Engine/source/gfx/D3D11/gfxD3D11Shader.h | 5 +- 2 files changed, 21 insertions(+), 52 deletions(-) diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp index 1bde8a3df..ad62b68e7 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp @@ -147,7 +147,10 @@ GFXD3D11ShaderConstBuffer::GFXD3D11ShaderConstBuffer(GFXD3D11Shader* shader) for (U32 i = 0; i < 6; i++) { - VECTOR_SET_ASSOCIATION(mBoundConstVec[i]); + for (U32 j = 0; j < 3; j++) + { + mBoundBuffers[i][j] = NULL; + } } } @@ -155,11 +158,10 @@ GFXD3D11ShaderConstBuffer::~GFXD3D11ShaderConstBuffer() { for (U32 i = 0; i < 6; i++) { - for (U32 j = 0; j < mBoundConstVec[i].size(); j++) + for (U32 j = 0; j < 3; j++) { - SAFE_RELEASE(mBoundConstVec[i][j]); + SAFE_RELEASE(mBoundBuffers[i][j]); } - mBoundConstVec[i].clear(); } for (auto& pair : mBufferMap) { @@ -481,7 +483,7 @@ void GFXD3D11ShaderConstBuffer::addBuffer(U32 bufBindingPoint, GFXShaderStage sh mBufferMap[bufKey].size = size; mBufferMap[bufKey].isDirty = true; - ID3D11Buffer* tempBuf; + //ID3D11Buffer* tempBuf; D3D11_BUFFER_DESC cbDesc; cbDesc.ByteWidth = size; cbDesc.Usage = D3D11_USAGE_DEFAULT; @@ -491,23 +493,18 @@ void GFXD3D11ShaderConstBuffer::addBuffer(U32 bufBindingPoint, GFXShaderStage sh cbDesc.StructureByteStride = 0; HRESULT hr; - hr = D3D11DEVICE->CreateBuffer(&cbDesc, NULL, &tempBuf); + hr = D3D11DEVICE->CreateBuffer(&cbDesc, NULL, &mBoundBuffers[(U32)shaderStageID][bufBindingPoint]); if (FAILED(hr)) { AssertFatal(false, "can't create constant buffer"); } - - mBoundConstVec[shaderStageID].push_back(tempBuf); } void GFXD3D11ShaderConstBuffer::activate( GFXD3D11ShaderConstBuffer *prevShaderBuffer ) { PROFILE_SCOPE(GFXD3D11ShaderConstBuffer_activate); - if (prevShaderBuffer == NULL) - return; - BufferRange bufRanges[6]; for (BufferMap::Iterator i = mBufferMap.begin(); i != mBufferMap.end(); ++i) @@ -515,7 +512,7 @@ void GFXD3D11ShaderConstBuffer::activate( GFXD3D11ShaderConstBuffer *prevShaderB const BufferKey thisBufferDesc = i->key; ConstantBuffer thisBuff = i->value; - if (prevShaderBuffer != this) + if (prevShaderBuffer && prevShaderBuffer != this) { const ConstantBuffer prevBuffer = prevShaderBuffer->mBufferMap[i->key]; @@ -542,10 +539,14 @@ void GFXD3D11ShaderConstBuffer::activate( GFXD3D11ShaderConstBuffer *prevShaderB thisBuff.isDirty = true; } } + else + { + thisBuff.isDirty = true; + } if (thisBuff.data && thisBuff.isDirty) { - D3D11DEVICECONTEXT->UpdateSubresource(mBoundConstVec[thisBufferDesc.key2][thisBufferDesc.key1], 0, NULL, thisBuff.data, thisBuff.size, 0); + D3D11DEVICECONTEXT->UpdateSubresource(mBoundBuffers[thisBufferDesc.key2][thisBufferDesc.key1], 0, NULL, thisBuff.data, thisBuff.size, 0); bufRanges[thisBufferDesc.key2].addSlot(thisBufferDesc.key1); } } @@ -554,7 +555,7 @@ void GFXD3D11ShaderConstBuffer::activate( GFXD3D11ShaderConstBuffer *prevShaderB { const U32 bufStartSlot = bufRanges[0].mBufMin; const U32 numBufs = bufRanges[0].mBufMax - bufRanges[0].mBufMin + 1; - ID3D11Buffer** vsBuffers = mBoundConstVec[0].address() + bufStartSlot; + ID3D11Buffer** vsBuffers = mBoundBuffers[0] + bufStartSlot; D3D11DEVICECONTEXT->VSSetConstantBuffers(bufStartSlot, numBufs, vsBuffers); } @@ -563,7 +564,7 @@ void GFXD3D11ShaderConstBuffer::activate( GFXD3D11ShaderConstBuffer *prevShaderB { const U32 bufStartSlot = bufRanges[1].mBufMin; const U32 numBufs = bufRanges[1].mBufMax - bufRanges[1].mBufMin + 1; - ID3D11Buffer** psBuffers = mBoundConstVec[1].address() + bufStartSlot; + ID3D11Buffer** psBuffers = mBoundBuffers[1] + bufStartSlot; D3D11DEVICECONTEXT->PSSetConstantBuffers(bufStartSlot, numBufs, psBuffers); } @@ -577,11 +578,10 @@ void GFXD3D11ShaderConstBuffer::onShaderReload( GFXD3D11Shader *shader ) for (U32 i = 0; i < 6; i++) { - for (U32 j = 0; j < mBoundConstVec[i].size(); j++) + for (U32 j = 0; j < 3; j++) { - SAFE_RELEASE(mBoundConstVec[i][j]); + SAFE_RELEASE(mBoundBuffers[i][j]); } - mBoundConstVec[i].clear(); } for (auto& pair : mBufferMap) { @@ -914,10 +914,6 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection* refTable, D3D11_SHADER_TYPE_DESC shaderTypeDesc; bufferVar->GetType()->GetDesc(&shaderTypeDesc); - bool unusedVar = shaderVarDesc.uFlags & D3D_SVF_USED ? false : true; - if (unusedVar) - continue; - if (shaderTypeDesc.Class == D3D_SVC_STRUCT) { // we gotta loop through its variables =/ add support in future. for now continue so it skips. @@ -979,6 +975,7 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection* refTable, if (shaderInputBind.Type == D3D_SIT_TEXTURE) { + // these should return shaderResourceViews and add them to shaderResources. /*switch (shaderInputBind.Dimension) { case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_TEXTURE1D: @@ -1028,33 +1025,6 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection* refTable, shaderInputBind.Type == D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER) { // these should return an unorderedAccessViews and add them to shaderResources. - /*switch (shaderInputBind.Dimension) - { - case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_TEXTURE1D: - break; - case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_TEXTURE1DARRAY: - break; - case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_TEXTURE2D: - break; - case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_TEXTURE2DARRAY: - break; - case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_TEXTURE2DMS: - break; - case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_TEXTURE2DMSARRAY: - break; - case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_TEXTURE3D: - break; - case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_TEXTURECUBE: - break; - case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_TEXTURECUBEARRAY: - break; - case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_BUFFER: - break; - case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_BUFFEREX: - break; - default: - break; - }*/ } else if (shaderInputBind.Type == D3D_SIT_STRUCTURED || shaderInputBind.Type == D3D_SIT_BYTEADDRESS) diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.h b/Engine/source/gfx/D3D11/gfxD3D11Shader.h index 42d6fdba5..3460ea6f5 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.h +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.h @@ -164,9 +164,8 @@ protected: void setMatrix(const GFXShaderConstDesc& handle, const U32 inSize, const void* data, U8* basePointer); void internalSet(GFXShaderConstHandle* handle, const U32 inSize, const void* data); - - // we probably want this to be GFXDevice and not per shader. - Vector mBoundConstVec[6]; + + ID3D11Buffer* mBoundBuffers[6][3]; }; class gfxD3D11Include; From 017246cfa33ff6f0a4e00ecb9c5c2fee0bfe4b47 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Fri, 1 Mar 2024 14:30:31 +0000 Subject: [PATCH 27/53] Update gfxD3D11Shader.cpp --- Engine/source/gfx/D3D11/gfxD3D11Shader.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp index ad62b68e7..ba5c5e227 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp @@ -973,7 +973,7 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection* refTable, D3D11_SHADER_INPUT_BIND_DESC shaderInputBind; refTable->GetResourceBindingDesc(i, &shaderInputBind); - if (shaderInputBind.Type == D3D_SIT_TEXTURE) + if (shaderInputBind.Type == D3D_SIT_TEXTURE || shaderInputBind.Type == D3D_SIT_UAV_RWTYPED) { // these should return shaderResourceViews and add them to shaderResources. /*switch (shaderInputBind.Dimension) @@ -1017,8 +1017,7 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection* refTable, desc.arraySize = shaderInputBind.BindCount; mSamplerDescriptions.push_back(desc); } - else if (shaderInputBind.Type == D3D_SIT_UAV_RWTYPED || - shaderInputBind.Type == D3D_SIT_UAV_RWSTRUCTURED || + else if (shaderInputBind.Type == D3D_SIT_UAV_RWSTRUCTURED || shaderInputBind.Type == D3D_SIT_UAV_RWBYTEADDRESS || shaderInputBind.Type == D3D_SIT_UAV_APPEND_STRUCTURED || shaderInputBind.Type == D3D_SIT_UAV_CONSUME_STRUCTURED || From 457cdd00bb258b9fa7f7dc0bebac921fa40efab5 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Sat, 2 Mar 2024 20:09:45 +0000 Subject: [PATCH 28/53] shader editor ground work Adds the ground work for shader editor Adds the base gui for the shader editor --- .../gui/shaderEditor/guiShaderEditor.cpp | 40 ++++++ .../source/gui/shaderEditor/guiShaderEditor.h | 96 +++++++++++++++ .../gui/shaderEditor/nodes/shaderNode.cpp | 27 +++++ .../gui/shaderEditor/nodes/shaderNode.h | 84 +++++++++++++ .../gui/shaderEditorGui.asset.taml | 7 ++ .../shaderEditor/gui/shaderEditorGui.ed.gui | 114 ++++++++++++++++++ Tools/CMake/modules/tools.cmake | 3 +- 7 files changed, 370 insertions(+), 1 deletion(-) create mode 100644 Engine/source/gui/shaderEditor/guiShaderEditor.cpp create mode 100644 Engine/source/gui/shaderEditor/guiShaderEditor.h create mode 100644 Engine/source/gui/shaderEditor/nodes/shaderNode.cpp create mode 100644 Engine/source/gui/shaderEditor/nodes/shaderNode.h create mode 100644 Templates/BaseGame/game/tools/shaderEditor/gui/shaderEditorGui.asset.taml create mode 100644 Templates/BaseGame/game/tools/shaderEditor/gui/shaderEditorGui.ed.gui diff --git a/Engine/source/gui/shaderEditor/guiShaderEditor.cpp b/Engine/source/gui/shaderEditor/guiShaderEditor.cpp new file mode 100644 index 000000000..3ede1823f --- /dev/null +++ b/Engine/source/gui/shaderEditor/guiShaderEditor.cpp @@ -0,0 +1,40 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "platform/platform.h" +#include "gui/shaderEditor/guiShaderEditor.h" + +#include "core/frameAllocator.h" +#include "core/stream/fileStream.h" +#include "core/stream/memStream.h" +#include "console/consoleTypes.h" +#include "gui/core/guiCanvas.h" +#include "console/engineAPI.h" +#include "console/script.h" + +IMPLEMENT_CONOBJECT(GuiShaderEditor); + +ConsoleDocClass(GuiShaderEditor, + "@brief Implementation of a shader node editor.\n\n" + "Editor use only.\n\n" + "@internal" +); diff --git a/Engine/source/gui/shaderEditor/guiShaderEditor.h b/Engine/source/gui/shaderEditor/guiShaderEditor.h new file mode 100644 index 000000000..3d0773f62 --- /dev/null +++ b/Engine/source/gui/shaderEditor/guiShaderEditor.h @@ -0,0 +1,96 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifndef _GUISHADEREDITOR_H_ +#define _GUISHADEREDITOR_H_ + +#ifndef _GUICONTROL_H_ +#include "gui/core/guiControl.h" +#endif +#ifndef _UNDO_H_ +#include "util/undo.h" +#endif +#ifndef _GFX_GFXDRAWER_H_ +#include "gfx/gfxDrawUtil.h" +#endif + +#ifndef _SHADERNODE_H_ +#include "gui/shaderEditor/nodes/shaderNode.h" +#endif // !_SHADERNODE_H_ + +class GuiShaderEditor : public GuiControl +{ +public: + + typedef GuiControl Parent; + + enum mouseModes { Selecting, MovingSelection, DragConnection, DragSelecting, DragClone }; + +protected: + + // list + typedef Vector ShaderNodeVector; + // all nodes in this graph. + ShaderNodeVector mCurrNodes; + + // Undo + SimGroup* mTrash; + SimSet* mSelectedSet; + + // mouse interaction + mouseModes mMouseDownMode; + Point2I mLastMousePos; + Point2I mLastDragPos; + Point2I mSelectionAnchor; + Point2I mDragBeginPoint; + Vector mDragBeginPoints; + bool mDragAddSelection; + bool mDragMoveUndo; + ShaderNodeVector mSelectedNodes; + +public: + GuiShaderEditor(); + + DECLARE_CONOBJECT(GuiShaderEditor); + DECLARE_CATEGORY("Shader Editor"); + DECLARE_DESCRIPTION("Implements a shader node based editor."); + + bool onWake(); + void onSleep(); + static void initPersistFields(); + virtual bool onAdd() override; + virtual void onRemove() override; + + virtual void onPreRender() override; + virtual void onRender(Point2I offset, const RectI& updateRect) override; + + // interaction + virtual bool onKeyDown(const GuiEvent& event) override; + virtual void onMouseDown(const GuiEvent& event) override; + virtual void onMouseUp(const GuiEvent& event) override; + virtual void onMouseMove(const GuiEvent& event) override; + virtual void onMiddleMouseDown(const GuiEvent& event) override; + virtual bool onMouseWheelUp(const GuiEvent& event) override; + virtual bool onMouseWheelDown(const GuiEvent& event) override; +}; + +#endif _GUISHADEREDITOR_H_ diff --git a/Engine/source/gui/shaderEditor/nodes/shaderNode.cpp b/Engine/source/gui/shaderEditor/nodes/shaderNode.cpp new file mode 100644 index 000000000..dfb284269 --- /dev/null +++ b/Engine/source/gui/shaderEditor/nodes/shaderNode.cpp @@ -0,0 +1,27 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "platform/platform.h" + +#include "gui/shaderEditor/nodes/shaderNode.h" + + diff --git a/Engine/source/gui/shaderEditor/nodes/shaderNode.h b/Engine/source/gui/shaderEditor/nodes/shaderNode.h new file mode 100644 index 000000000..9be57caf7 --- /dev/null +++ b/Engine/source/gui/shaderEditor/nodes/shaderNode.h @@ -0,0 +1,84 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifndef _SHADERNODE_H_ +#define _SHADERNODE_H_ + +#ifndef _SIMBASE_H_ +#include "console/simBase.h" +#endif + +enum class NodeTypes +{ + Uniform, + Input, + Output, + TextureSampler, + MathOperation, + Procedural +}; + +enum class DataDimensions +{ + Scalar, + Vector2, + Vector3, + Vector4, + Mat4x4, +}; + +struct NodeInput +{ + String name; + DataDimensions dimensions; +}; + +struct NodeOutput +{ + String name; + DataDimensions dimensions; +}; + +class ShaderNode : public GuiControl +{ +private: + typedef GuiControl Parent; + +public: + ShaderNode(); + + bool onWake(); + void onSleep(); + static void initPersistFields(); + virtual bool onAdd() override; + virtual void onRemove() override; + + // Serialization functions + void write(Stream& stream, U32 tabStop = 0, U32 flags = 0); + void read(Stream& stream); + + // is the parent that all other nodes are derived from. + DECLARE_CONOBJECT(ShaderNode); + DECLARE_CATEGORY("Shader Core"); + DECLARE_DESCRIPTION("Base class for all shader nodes."); +}; +#endif // !_SHADERNODE_H_ diff --git a/Templates/BaseGame/game/tools/shaderEditor/gui/shaderEditorGui.asset.taml b/Templates/BaseGame/game/tools/shaderEditor/gui/shaderEditorGui.asset.taml new file mode 100644 index 000000000..9898caa03 --- /dev/null +++ b/Templates/BaseGame/game/tools/shaderEditor/gui/shaderEditorGui.asset.taml @@ -0,0 +1,7 @@ + diff --git a/Templates/BaseGame/game/tools/shaderEditor/gui/shaderEditorGui.ed.gui b/Templates/BaseGame/game/tools/shaderEditor/gui/shaderEditorGui.ed.gui new file mode 100644 index 000000000..c5709f856 --- /dev/null +++ b/Templates/BaseGame/game/tools/shaderEditor/gui/shaderEditorGui.ed.gui @@ -0,0 +1,114 @@ +//--- OBJECT WRITE BEGIN --- +$guiContent = new GuiControl(ShaderEditorGui) { + extent = "800 600"; + profile = "GuiDefaultProfile"; + tooltipProfile = "ToolsGuiToolTipProfile"; + isContainer = "1"; + canSaveDynamicFields = "1"; + + new GuiFrameSetCtrl() { + columns = "0 200 625"; + borderWidth = "2"; + borderColor = "10 10 10 0"; + autoBalance = "1"; + extent = "800 600"; + horizSizing = "width"; + vertSizing = "height"; + profile = "ToolsGuiFrameSetProfile"; + tooltipProfile = "ToolsGuiToolTipProfile"; + + new GuiControl() { + extent = "198 600"; + horizSizing = "width"; + vertSizing = "height"; + profile = "ToolsGuiDefaultProfile"; + tooltipProfile = "ToolsGuiToolTipProfile"; + isContainer = "1"; + + new GuiSplitContainer() { + orientation = "Horizontal"; + splitPoint = "0 200"; + extent = "197 600"; + horizSizing = "width"; + vertSizing = "height"; + profile = "ToolsGuiDefaultProfile"; + tooltipProfile = "ToolsGuiToolTipProfile"; + + new GuiPanel(ShaderEditorPreview) { + docking = "Client"; + extent = "197 198"; + profile = "ToolsGuiButtonProfile"; + tooltipProfile = "ToolsGuiToolTipProfile"; + internalName = "Panel1"; + }; + new GuiPanel(ShaderEditorInspector) { + docking = "Client"; + position = "0 202"; + extent = "197 398"; + profile = "ToolsGuiButtonProfile"; + tooltipProfile = "ToolsGuiToolTipProfile"; + internalName = "panel2"; + }; + }; + }; + new GuiControl() { + position = "200 0"; + extent = "423 600"; + horizSizing = "width"; + vertSizing = "height"; + profile = "ToolsGuiButtonProfile"; + tooltipProfile = "ToolsGuiToolTipProfile"; + isContainer = "1"; + }; + new GuiControl(ShaderEditorSidebar) { + position = "625 0"; + extent = "175 600"; + horizSizing = "width"; + vertSizing = "height"; + profile = "ToolsGuiDefaultProfile"; + tooltipProfile = "ToolsGuiButtonProfile"; + isContainer = "1"; + + new GuiTabBookCtrl(ShaderEditorTabBook) { + tabHeight = "20"; + allowReorder = "1"; + selectedPage = "0"; + position = "3 5"; + extent = "166 400"; + horizSizing = "width"; + vertSizing = "height"; + profile = "ToolsGuiTabBookProfile"; + tooltipProfile = "ToolsGuiToolTipProfile"; + + new GuiTabPageCtrl() { + fitBook = "1"; + text = "Library"; + position = "0 20"; + extent = "166 380"; + horizSizing = "width"; + vertSizing = "height"; + profile = "ToolsGuiTabPageProfile"; + tooltipProfile = "ToolsGuiToolTipProfile"; + + new GuiScrollCtrl() { + hScrollBar = "dynamic"; + childMargin = "0 2"; + extent = "166 370"; + horizSizing = "width"; + vertSizing = "height"; + profile = "ToolsGuiScrollProfile"; + tooltipProfile = "ToolsGuiToolTipProfile"; + + new GuiStackControl(ShaderToolbox) { + extent = "486 1000"; + horizSizing = "width"; + profile = "ToolsGuiDefaultProfile"; + tooltipProfile = "ToolsGuiToolTipProfile"; + }; + }; + }; + }; + }; + }; +}; +//--- OBJECT WRITE END --- diff --git a/Tools/CMake/modules/tools.cmake b/Tools/CMake/modules/tools.cmake index 070c4e15b..62cad2f3b 100644 --- a/Tools/CMake/modules/tools.cmake +++ b/Tools/CMake/modules/tools.cmake @@ -4,7 +4,8 @@ option(TORQUE_TOOLS "Enable Torque Tools" ON) if(TORQUE_TOOLS) message("Enabling Torque Tools Module") - file(GLOB_RECURSE TORQUE_TOOLS_SOURCES "gui/editor/*.cpp" "gui/editor/*.h" "gui/worldEditor/*.cpp" "gui/worldEditor/*.h") + file(GLOB_RECURSE TORQUE_TOOLS_SOURCES "gui/editor/*.cpp" "gui/editor/*.h" "gui/worldEditor/*.cpp" "gui/worldEditor/*.h" "gui/shaderEditor/*.cpp" "gui/shaderEditor/*.h" + "gui/shaderEditor/nodes/*.cpp" "gui/shaderEditor/nodes/*.h") file(GLOB_RECURSE TORQUE_TOOLS_SOURCES2 "environment/editors/*.cpp" "environment/editors/*.h") file(GLOB_RECURSE TORQUE_TOOLS_SOURCES3 "forest/editor/*.cpp" "forest/editor/*.h") From be0689549a40904f7e0a74043a32db827ef52f0c Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Sat, 2 Mar 2024 20:14:11 +0000 Subject: [PATCH 29/53] place functions in cpp stop cli bitching..... --- .../gui/shaderEditor/guiShaderEditor.cpp | 65 +++++++++++++++++++ .../gui/shaderEditor/nodes/shaderNode.cpp | 41 ++++++++++++ .../gui/shaderEditor/nodes/shaderNode.h | 4 ++ 3 files changed, 110 insertions(+) diff --git a/Engine/source/gui/shaderEditor/guiShaderEditor.cpp b/Engine/source/gui/shaderEditor/guiShaderEditor.cpp index 3ede1823f..5cb7dc4c5 100644 --- a/Engine/source/gui/shaderEditor/guiShaderEditor.cpp +++ b/Engine/source/gui/shaderEditor/guiShaderEditor.cpp @@ -38,3 +38,68 @@ ConsoleDocClass(GuiShaderEditor, "Editor use only.\n\n" "@internal" ); + +GuiShaderEditor::GuiShaderEditor() +{ +} + +bool GuiShaderEditor::onWake() +{ + return false; +} + +void GuiShaderEditor::onSleep() +{ +} + +void GuiShaderEditor::initPersistFields() +{ +} + +bool GuiShaderEditor::onAdd() +{ + return false; +} + +void GuiShaderEditor::onRemove() +{ +} + +void GuiShaderEditor::onPreRender() +{ +} + +void GuiShaderEditor::onRender(Point2I offset, const RectI& updateRect) +{ +} + +bool GuiShaderEditor::onKeyDown(const GuiEvent& event) +{ + return false; +} + +void GuiShaderEditor::onMouseDown(const GuiEvent& event) +{ +} + +void GuiShaderEditor::onMouseUp(const GuiEvent& event) +{ +} + +void GuiShaderEditor::onMouseMove(const GuiEvent& event) +{ +} + +void GuiShaderEditor::onMiddleMouseDown(const GuiEvent& event) +{ +} + +bool GuiShaderEditor::onMouseWheelUp(const GuiEvent& event) +{ + return false; +} + +bool GuiShaderEditor::onMouseWheelDown(const GuiEvent& event) +{ + return false; +} diff --git a/Engine/source/gui/shaderEditor/nodes/shaderNode.cpp b/Engine/source/gui/shaderEditor/nodes/shaderNode.cpp index dfb284269..c14561ada 100644 --- a/Engine/source/gui/shaderEditor/nodes/shaderNode.cpp +++ b/Engine/source/gui/shaderEditor/nodes/shaderNode.cpp @@ -24,4 +24,45 @@ #include "gui/shaderEditor/nodes/shaderNode.h" +IMPLEMENT_CONOBJECT(ShaderNode); +ConsoleDocClass(ShaderNode, + "@brief Base class for all nodes to derive from.\n\n" + "Editor use only.\n\n" + "@internal" +); + + +ShaderNode::ShaderNode() +{ +} + +bool ShaderNode::onWake() +{ + return false; +} + +void ShaderNode::onSleep() +{ +} + +void ShaderNode::initPersistFields() +{ +} + +bool ShaderNode::onAdd() +{ + return false; +} + +void ShaderNode::onRemove() +{ +} + +void ShaderNode::write(Stream& stream, U32 tabStop, U32 flags) +{ +} + +void ShaderNode::read(Stream& stream) +{ +} diff --git a/Engine/source/gui/shaderEditor/nodes/shaderNode.h b/Engine/source/gui/shaderEditor/nodes/shaderNode.h index 9be57caf7..7f01865f5 100644 --- a/Engine/source/gui/shaderEditor/nodes/shaderNode.h +++ b/Engine/source/gui/shaderEditor/nodes/shaderNode.h @@ -23,6 +23,10 @@ #ifndef _SHADERNODE_H_ #define _SHADERNODE_H_ +#ifndef _GUICONTROL_H_ +#include "gui/core/guiControl.h" +#endif + #ifndef _SIMBASE_H_ #include "console/simBase.h" #endif From 6e85b430882b25d119802ba08c154bb9917fa812 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Sun, 3 Mar 2024 19:24:49 +0000 Subject: [PATCH 30/53] backup before connections everything in shaderEditor now finished only thing left to add is the connections. --- .../gui/shaderEditor/guiShaderEditor.cpp | 536 +++++++++++++++++- .../source/gui/shaderEditor/guiShaderEditor.h | 33 +- .../gui/shaderEditor/nodes/shaderNode.cpp | 13 +- .../gui/shaderEditor/nodes/shaderNode.h | 4 +- 4 files changed, 577 insertions(+), 9 deletions(-) diff --git a/Engine/source/gui/shaderEditor/guiShaderEditor.cpp b/Engine/source/gui/shaderEditor/guiShaderEditor.cpp index 5cb7dc4c5..71ff0b6c6 100644 --- a/Engine/source/gui/shaderEditor/guiShaderEditor.cpp +++ b/Engine/source/gui/shaderEditor/guiShaderEditor.cpp @@ -40,37 +40,142 @@ ConsoleDocClass(GuiShaderEditor, ); GuiShaderEditor::GuiShaderEditor() + : mDragBeginPoint(-1, -1), + mViewOffset(0,0), + mZoomScale(1.0f), + mFullBoxSelection(false), + mDragAddSelection(false), + mDragMoveUndo(false) { + VECTOR_SET_ASSOCIATION(mCurrNodes); + VECTOR_SET_ASSOCIATION(mSelectedNodes); + VECTOR_SET_ASSOCIATION(mDragBeginPoints); + + mActive = true; + mMouseDownMode = GuiShaderEditor::Selecting; + + mTrash = NULL; + mSelectedSet = NULL; } bool GuiShaderEditor::onWake() { - return false; + if (!Parent::onWake()) + return false; + + return true; } void GuiShaderEditor::onSleep() { + Parent::onSleep(); } void GuiShaderEditor::initPersistFields() { + docsURL; + addGroup("Selection"); + addField("fullBoxSelection", TypeBool, Offset(mFullBoxSelection, GuiShaderEditor), + "If true, rectangle selection will only select controls fully inside the drag rectangle."); + endGroup("Selection"); + Parent::initPersistFields(); } bool GuiShaderEditor::onAdd() { - return false; + if (!Parent::onAdd()) + return false; + + mTrash = new SimGroup(); + mSelectedSet = new SimSet(); + + if (!mTrash->registerObject()) + return false; + if (!mSelectedSet->registerObject()) + return false; + + return true; } void GuiShaderEditor::onRemove() { + mTrash->deleteObject(); + mSelectedSet->deleteObject(); + + mTrash = NULL; + mSelectedSet = NULL; } void GuiShaderEditor::onPreRender() { + setUpdate(); +} + +void GuiShaderEditor::renderNodes(Point2I offset, const RectI& updateRect) +{ + // Save the current clip rect + // so we can restore it at the end of this method. + RectI savedClipRect = GFX->getClipRect(); + + // offset is the upper-left corner of this control in screen coordinates + // updateRect is the intersection rectangle in screen coords of the control + // hierarchy. This can be set as the clip rectangle in most cases. + RectI clipRect = updateRect; + + GFXDrawUtil* drawer = GFX->getDrawUtil(); + + for (ShaderNode* node : mCurrNodes) + { + // this is useful for sub node graphs. + if (node->isVisible()) + { + Point2I childPos = offset + node->getPosition(); + RectI childClip(childPos, node->getExtent() + Point2I(1, 1)); + + if (childClip.intersect(clipRect)) + { + GFX->setClipRect(childClip); + GFX->setStateBlock(mDefaultGuiSB); + node->onRender(offset, childClip); + } + + if (selectionContains(node)) + { + GFX->setClipRect(clipRect); + childClip.inset(1, 1); + drawer->drawRect(childClip, ColorI(255, 255, 0, 128)); + } + } + } + + // Restore the clip rect to what it was at the start + // of this method. + GFX->setClipRect(savedClipRect); } void GuiShaderEditor::onRender(Point2I offset, const RectI& updateRect) { + offset += mViewOffset * mZoomScale; + + GFXDrawUtil* drawer = GFX->getDrawUtil(); + + // render our nodes. + renderNodes(offset, updateRect); + + // Draw selection rectangle last so it is rendered on top. + if (mActive && mMouseDownMode == DragSelecting) + { + RectI b; + getDragRect(b); + b.point += offset; + + // Draw outline. + drawer->drawRect(b, ColorI(100, 100, 100, 128)); + + // Draw fill. + b.inset(1, 1); + drawer->drawRectFill(b, ColorI(150, 150, 150, 128)); + } } bool GuiShaderEditor::onKeyDown(const GuiEvent& event) @@ -80,26 +185,449 @@ bool GuiShaderEditor::onKeyDown(const GuiEvent& event) void GuiShaderEditor::onMouseDown(const GuiEvent& event) { + if (!mActive) + { + Parent::onMouseDown(event); + return; + } + + setFirstResponder(); + + // lock mouse + mouseLock(); + + // get mouse pos with our view offset and scale. + mLastMousePos = globalToLocalCoord(event.mousePoint) + mViewOffset * mZoomScale; + + ShaderNode* node = findHitNode(mLastMousePos); + + if (event.modifier & SI_SHIFT) + { + startDragRectangle(mLastMousePos); + mDragAddSelection = true; + } + else if (selectionContains(node)) + { + if (event.modifier & SI_MULTISELECT) + { + removeSelection(node); + setMouseMode(Selecting); + } + else if (event.modifier & SI_PRIMARY_ALT) + { + startDragClone(mLastMousePos); + } + else + { + startDragMove(mLastMousePos); + } + } + else + { + if (node == NULL) + { + startDragRectangle(mLastMousePos); + mDragAddSelection = false; + } + else if (event.modifier & SI_PRIMARY_ALT && node != NULL) + { + // Alt is down. Start a drag clone. + clearSelection(); + addSelection(node); + startDragClone(mLastMousePos); + } + else if (event.modifier & SI_MULTISELECT) + { + addSelection(node); + } + else + { + // Clicked on node. Start move. + clearSelection(); + addSelection(node); + startDragMove(mLastMousePos); + } + } + } void GuiShaderEditor::onMouseUp(const GuiEvent& event) { + if (!mActive) + { + Parent::onMouseUp(event); + return; + } + + ShaderNode* node = findHitNode(mLastMousePos); + + //unlock the mouse + mouseUnlock(); + + // Reset Drag Axis Alignment Information + mDragBeginPoint.set(-1, -1); + mDragBeginPoints.clear(); + + // get mouse pos with our view offset and scale. + mLastMousePos = globalToLocalCoord(event.mousePoint) + mViewOffset * mZoomScale; + + if (mMouseDownMode == DragSelecting) + { + if (!(event.modifier & SI_MULTISELECT) && !mDragAddSelection) + clearSelection(); + + RectI rect; + getDragRect(rect); + + if (rect.extent.x <= 2 && rect.extent.y <= 2) + { + addSelectionAtPoint(rect.point); + } + else + { + Vector< ShaderNode* > hits; + findNodesInRect(rect, hits); + + for (ShaderNode* node : hits) + { + addSelection(node); + } + } + } + + if (mMouseDownMode == MovingSelection && mDragMoveUndo) + { + + } + + //reset the mouse mode + setFirstResponder(); + setMouseMode(Selecting); } -void GuiShaderEditor::onMouseMove(const GuiEvent& event) +void GuiShaderEditor::onMouseDragged(const GuiEvent& event) { + if (!mActive) + { + Parent::onMouseDragged(event); + return; + } + + // get mouse pos with our view offset and scale. + Point2I mousePoint = globalToLocalCoord(event.mousePoint) + mViewOffset * mZoomScale; + + if (mMouseDownMode == DragClone) + { + // If we haven't yet crossed the mouse delta to actually start the + // clone, check if we have now. + + S32 delta = mAbs((mousePoint - mDragBeginPoint).len()); + if (delta >= 4) + { + cloneSelection(); + mLastMousePos = mDragBeginPoint; + mDragMoveUndo = false; + + setMouseMode(MovingSelection); + } + } + + if (mMouseDownMode == MovingSelection && mSelectedNodes.size()) + { + Point2I delta = mousePoint - mLastMousePos; + RectI selBounds = getSelectionBounds(); + + if (delta.x || delta.y) + moveSelection(delta, mDragMoveUndo); + + mLastMousePos += delta; + } + else + mLastMousePos = mousePoint; } void GuiShaderEditor::onMiddleMouseDown(const GuiEvent& event) { + if (!mActive) + { + Parent::onMiddleMouseDown(event); + return; + } + + setFirstResponder(); + + // lock mouse + mouseLock(); + + // get mouse pos with our view offset and scale. + mLastMousePos = globalToLocalCoord(event.mousePoint) + mViewOffset * mZoomScale; + + setMouseMode(DragPanning); + +} + +void GuiShaderEditor::onMiddleMouseUp(const GuiEvent& event) +{ + if (!mActive) + { + Parent::onMiddleMouseUp(event); + return; + } + + //unlock the mouse + mouseUnlock(); + + // Reset Drag Axis Alignment Information + mDragBeginPoint.set(-1, -1); + mDragBeginPoints.clear(); + + // get mouse pos with our view offset and scale. + mLastMousePos = globalToLocalCoord(event.mousePoint) + mViewOffset * mZoomScale; + + setFirstResponder(); + setMouseMode(Selecting); +} + +void GuiShaderEditor::onMiddleMouseDragged(const GuiEvent& event) +{ + if (!mActive) + { + Parent::onMiddleMouseDragged(event); + return; + } + + // get mouse pos with our view offset and scale. + Point2I mousePoint = globalToLocalCoord(event.mousePoint) + mViewOffset * mZoomScale; + + if (mMouseDownMode == DragPanning) + { + Point2I delta = mousePoint - mLastMousePos; + RectI selBounds = getSelectionBounds(); + + // invert it + if (delta.x || delta.y) + mViewOffset += -delta; + + mLastMousePos += delta; + } + else + mLastMousePos = mousePoint; } bool GuiShaderEditor::onMouseWheelUp(const GuiEvent& event) { - return false; + if (!mActive || !mAwake || !mVisible) + return Parent::onMouseWheelUp(event); + + mZoomScale *= 1.1; + + return true; } bool GuiShaderEditor::onMouseWheelDown(const GuiEvent& event) { + if (!mActive || !mAwake || !mVisible) + return Parent::onMouseWheelDown(event); + + mZoomScale *= 0.9; + + return true; +} + +RectI GuiShaderEditor::getSelectionBounds() +{ + + Vector::const_iterator i = mSelectedNodes.begin(); + + Point2I minPos = (*i)->localToGlobalCoord(Point2I(0, 0)) + mViewOffset * mZoomScale; + Point2I maxPos = minPos; + + for (; i != mSelectedNodes.end(); i++) + { + Point2I iPos = (**i).localToGlobalCoord(Point2I(0, 0)) + mViewOffset * mZoomScale; + + minPos.x = getMin(iPos.x, minPos.x); + minPos.y = getMin(iPos.y, minPos.y); + + Point2I iExt = (**i).getExtent(); + + iPos.x += iExt.x; + iPos.y += iExt.y; + + maxPos.x = getMax(iPos.x, maxPos.x); + maxPos.y = getMax(iPos.y, maxPos.y); + } + + minPos = globalToLocalCoord(minPos) + mViewOffset * mZoomScale; + maxPos = globalToLocalCoord(maxPos) + mViewOffset * mZoomScale; + + return RectI(minPos.x, minPos.y, (maxPos.x - minPos.x), (maxPos.y - minPos.y)); +} + +void GuiShaderEditor::deleteSelection() +{ + for (ShaderNode* node : mSelectedNodes) + { + mTrash->addObject(node); + } + + clearSelection(); +} + +void GuiShaderEditor::moveSelection(const Point2I& delta, bool callback) +{ + for (ShaderNode* node : mSelectedNodes) + { + node->setPosition(node->getPosition() + delta); + } +} + +void GuiShaderEditor::clearSelection() +{ + mSelectedNodes.clear(); +} + +void GuiShaderEditor::cloneSelection() +{ + Vector newSelection; + + for (ShaderNode* node : mSelectedNodes) + { + ShaderNode* clone = dynamic_cast(node->deepClone()); + if (clone) + newSelection.push_back(clone); + } + + clearSelection(); + + for (ShaderNode* cloneNode : newSelection) + { + addSelection(cloneNode); + } +} + +void GuiShaderEditor::addSelectionAtPoint(const Point2I& pos) +{ + // turn hit off on already selected nodes. + canHitSelectedNodes(false); + + ShaderNode* node = findHitNode(pos); + + // reset hit status. + canHitSelectedNodes(); + + if (node) + addSelection(node); +} + +void GuiShaderEditor::addSelection(ShaderNode* inNode) +{ + if (inNode != NULL && !selectionContains(inNode)) + { + mSelectedNodes.push_back(inNode); + } +} + +bool GuiShaderEditor::selectionContains(ShaderNode* inNode) +{ + for (ShaderNode* node : mSelectedNodes) + { + if (node == inNode) + return true; + } + return false; } + +void GuiShaderEditor::removeSelection(ShaderNode* inNode) +{ + if (selectionContains(inNode)) + { + Vector< ShaderNode* >::iterator i = T3D::find(mSelectedNodes.begin(), mSelectedNodes.end(), inNode); + if (i != mSelectedNodes.end()) + mSelectedNodes.erase(i); + } +} + +void GuiShaderEditor::canHitSelectedNodes(bool state) +{ + for (ShaderNode* node : mSelectedNodes) + node->setCanHit(state); +} + +//----------------------------------------------------------------------------- +// Input handling +//----------------------------------------------------------------------------- + +ShaderNode* GuiShaderEditor::findHitNode(const Point2I& pt) +{ + for (ShaderNode* node : mCurrNodes) + { + if (node->pointInControl(pt)) + { + return node; + } + } + + return nullptr; +} + +void GuiShaderEditor::findNodesInRect(const RectI& rect, Vector& outResult) +{ + canHitSelectedNodes(false); + for (ShaderNode* node : mCurrNodes) + { + if (node->getBounds().overlaps(rect)) + { + outResult.push_back(node); + } + } + + canHitSelectedNodes(); +} + +void GuiShaderEditor::getDragRect(RectI& box) +{ + box.point.x = getMin(mLastMousePos.x, mSelectionAnchor.x); + box.extent.x = getMax(mLastMousePos.x, mSelectionAnchor.x) - box.point.x + 1; + box.point.y = getMin(mLastMousePos.y, mSelectionAnchor.y); + box.extent.y = getMax(mLastMousePos.y, mSelectionAnchor.y) - box.point.y + 1; +} + +void GuiShaderEditor::startDragMove(const Point2I& startPoint) +{ + mDragMoveUndo = true; + + mDragBeginPoint = startPoint; + + mDragBeginPoints.reserve(mSelectedNodes.size()); + + for (ShaderNode* node : mSelectedNodes) + { + mDragBeginPoints.push_back(node->getPosition()); + } + + setMouseMode(MovingSelection); + +} + +void GuiShaderEditor::startDragRectangle(const Point2I& startPoint) +{ + mSelectionAnchor = startPoint; + setMouseMode(DragSelecting); +} + +void GuiShaderEditor::startDragClone(const Point2I& startPoint) +{ + mDragBeginPoint = startPoint; + setMouseMode(DragClone); +} + +void GuiShaderEditor::setMouseMode(mouseModes mode) +{ + if (mMouseDownMode != mode) + { + mMouseDownMode = mode; + } +} + diff --git a/Engine/source/gui/shaderEditor/guiShaderEditor.h b/Engine/source/gui/shaderEditor/guiShaderEditor.h index 3d0773f62..efed5659a 100644 --- a/Engine/source/gui/shaderEditor/guiShaderEditor.h +++ b/Engine/source/gui/shaderEditor/guiShaderEditor.h @@ -43,7 +43,7 @@ public: typedef GuiControl Parent; - enum mouseModes { Selecting, MovingSelection, DragConnection, DragSelecting, DragClone }; + enum mouseModes { Selecting, MovingSelection, DragPanning, DragConnection, DragSelecting, DragClone }; protected: @@ -56,6 +56,9 @@ protected: SimGroup* mTrash; SimSet* mSelectedSet; + // view controls + Point2I mViewOffset; + F32 mZoomScale; // mouse interaction mouseModes mMouseDownMode; Point2I mLastMousePos; @@ -65,8 +68,21 @@ protected: Vector mDragBeginPoints; bool mDragAddSelection; bool mDragMoveUndo; + bool mFullBoxSelection; ShaderNodeVector mSelectedNodes; + void renderNodes(Point2I offset, const RectI& updateRect); + + // functions for handling mouse events. + ShaderNode* findHitNode(const Point2I& pt); + void findNodesInRect(const RectI& rect, Vector& outResult); + + void getDragRect(RectI& box); + void startDragMove(const Point2I& startPoint); + void startDragRectangle(const Point2I& startPoint); + void startDragClone(const Point2I& startPoint); + void setMouseMode(mouseModes mode); + public: GuiShaderEditor(); @@ -87,10 +103,23 @@ public: virtual bool onKeyDown(const GuiEvent& event) override; virtual void onMouseDown(const GuiEvent& event) override; virtual void onMouseUp(const GuiEvent& event) override; - virtual void onMouseMove(const GuiEvent& event) override; + virtual void onMouseDragged(const GuiEvent& event) override; virtual void onMiddleMouseDown(const GuiEvent& event) override; + virtual void onMiddleMouseUp(const GuiEvent& event) override; + virtual void onMiddleMouseDragged(const GuiEvent& event) override; virtual bool onMouseWheelUp(const GuiEvent& event) override; virtual bool onMouseWheelDown(const GuiEvent& event) override; + + RectI getSelectionBounds(); + void deleteSelection(); + void moveSelection(const Point2I& delta, bool callback = true); + void clearSelection(); + void cloneSelection(); + void addSelectionAtPoint(const Point2I& pos); + void addSelection(ShaderNode* inNode); + bool selectionContains(ShaderNode* inNode); + void removeSelection(ShaderNode* inNode); + void canHitSelectedNodes(bool state = true); }; #endif _GUISHADEREDITOR_H_ diff --git a/Engine/source/gui/shaderEditor/nodes/shaderNode.cpp b/Engine/source/gui/shaderEditor/nodes/shaderNode.cpp index c14561ada..8b48d40bc 100644 --- a/Engine/source/gui/shaderEditor/nodes/shaderNode.cpp +++ b/Engine/source/gui/shaderEditor/nodes/shaderNode.cpp @@ -39,20 +39,29 @@ ShaderNode::ShaderNode() bool ShaderNode::onWake() { - return false; + if (!Parent::onWake()) + return false; + + return true; } void ShaderNode::onSleep() { + Parent::onSleep(); } void ShaderNode::initPersistFields() { + docsURL; + Parent::initPersistFields(); } bool ShaderNode::onAdd() { - return false; + if (!Parent::onAdd()) + return false; + + return true; } void ShaderNode::onRemove() diff --git a/Engine/source/gui/shaderEditor/nodes/shaderNode.h b/Engine/source/gui/shaderEditor/nodes/shaderNode.h index 7f01865f5..a5bb46937 100644 --- a/Engine/source/gui/shaderEditor/nodes/shaderNode.h +++ b/Engine/source/gui/shaderEditor/nodes/shaderNode.h @@ -38,11 +38,13 @@ enum class NodeTypes Output, TextureSampler, MathOperation, - Procedural + Procedural, + Generator }; enum class DataDimensions { + Dynamic, // can be any dimension, usually defined by what was connected to it. Scalar, Vector2, Vector3, From daa0cfef3ab46c4aaadb1f95ad77fc175ff392b8 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Sun, 3 Mar 2024 21:13:58 +0000 Subject: [PATCH 31/53] shader node editor test node editor functioning correctly, connections needed next shader nodes to be added in the next commit also --- .../gui/shaderEditor/guiShaderEditor.cpp | 92 ++++++++++--------- .../source/gui/shaderEditor/guiShaderEditor.h | 1 - .../gui/shaderEditor/nodes/shaderNode.cpp | 44 ++++++++- .../gui/shaderEditor/nodes/shaderNode.h | 13 +++ .../game/tools/gui/profiles.ed.tscript | 10 ++ .../shaderEditor/gui/shaderEditorGui.ed.gui | 38 +++++--- 6 files changed, 136 insertions(+), 62 deletions(-) diff --git a/Engine/source/gui/shaderEditor/guiShaderEditor.cpp b/Engine/source/gui/shaderEditor/guiShaderEditor.cpp index 71ff0b6c6..454c3ea24 100644 --- a/Engine/source/gui/shaderEditor/guiShaderEditor.cpp +++ b/Engine/source/gui/shaderEditor/guiShaderEditor.cpp @@ -55,7 +55,9 @@ GuiShaderEditor::GuiShaderEditor() mMouseDownMode = GuiShaderEditor::Selecting; mTrash = NULL; - mSelectedSet = NULL; + + // test + mCurrNodes.push_back(new ShaderNode()); } bool GuiShaderEditor::onWake() @@ -87,23 +89,31 @@ bool GuiShaderEditor::onAdd() return false; mTrash = new SimGroup(); - mSelectedSet = new SimSet(); if (!mTrash->registerObject()) return false; - if (!mSelectedSet->registerObject()) - return false; + return true; } void GuiShaderEditor::onRemove() { + Parent::onRemove(); + mTrash->deleteObject(); - mSelectedSet->deleteObject(); mTrash = NULL; - mSelectedSet = NULL; + + for (ShaderNode* node : mCurrNodes) + { + SAFE_DELETE(node); + } + + for (ShaderNode* node : mSelectedNodes) + { + SAFE_DELETE(node); + } } void GuiShaderEditor::onPreRender() @@ -121,8 +131,7 @@ void GuiShaderEditor::renderNodes(Point2I offset, const RectI& updateRect) // updateRect is the intersection rectangle in screen coords of the control // hierarchy. This can be set as the clip rectangle in most cases. RectI clipRect = updateRect; - - GFXDrawUtil* drawer = GFX->getDrawUtil(); + clipRect.inset(2, 2); for (ShaderNode* node : mCurrNodes) { @@ -130,20 +139,22 @@ void GuiShaderEditor::renderNodes(Point2I offset, const RectI& updateRect) if (node->isVisible()) { Point2I childPos = offset + node->getPosition(); - RectI childClip(childPos, node->getExtent() + Point2I(1, 1)); + RectI childClip(childPos, node->getExtent() ); + + if (selectionContains(node)) + { + node->mSelected = true; + } + else + { + node->mSelected = false; + } if (childClip.intersect(clipRect)) { GFX->setClipRect(childClip); GFX->setStateBlock(mDefaultGuiSB); - node->onRender(offset, childClip); - } - - if (selectionContains(node)) - { - GFX->setClipRect(clipRect); - childClip.inset(1, 1); - drawer->drawRect(childClip, ColorI(255, 255, 0, 128)); + node->onRender(childPos, childClip); } } } @@ -155,7 +166,7 @@ void GuiShaderEditor::renderNodes(Point2I offset, const RectI& updateRect) void GuiShaderEditor::onRender(Point2I offset, const RectI& updateRect) { - offset += mViewOffset * mZoomScale; + offset += mViewOffset; GFXDrawUtil* drawer = GFX->getDrawUtil(); @@ -197,20 +208,20 @@ void GuiShaderEditor::onMouseDown(const GuiEvent& event) mouseLock(); // get mouse pos with our view offset and scale. - mLastMousePos = globalToLocalCoord(event.mousePoint) + mViewOffset * mZoomScale; + mLastMousePos = globalToLocalCoord(event.mousePoint) - mViewOffset; - ShaderNode* node = findHitNode(mLastMousePos); + ShaderNode* hitNode = findHitNode(mLastMousePos); if (event.modifier & SI_SHIFT) { startDragRectangle(mLastMousePos); mDragAddSelection = true; } - else if (selectionContains(node)) + else if (selectionContains(hitNode)) { if (event.modifier & SI_MULTISELECT) { - removeSelection(node); + removeSelection(hitNode); setMouseMode(Selecting); } else if (event.modifier & SI_PRIMARY_ALT) @@ -224,27 +235,27 @@ void GuiShaderEditor::onMouseDown(const GuiEvent& event) } else { - if (node == NULL) + if (hitNode == NULL) { startDragRectangle(mLastMousePos); mDragAddSelection = false; } - else if (event.modifier & SI_PRIMARY_ALT && node != NULL) + else if (event.modifier & SI_PRIMARY_ALT && hitNode != NULL) { // Alt is down. Start a drag clone. clearSelection(); - addSelection(node); + addSelection(hitNode); startDragClone(mLastMousePos); } else if (event.modifier & SI_MULTISELECT) { - addSelection(node); + addSelection(hitNode); } else { // Clicked on node. Start move. clearSelection(); - addSelection(node); + addSelection(hitNode); startDragMove(mLastMousePos); } } @@ -259,8 +270,6 @@ void GuiShaderEditor::onMouseUp(const GuiEvent& event) return; } - ShaderNode* node = findHitNode(mLastMousePos); - //unlock the mouse mouseUnlock(); @@ -269,7 +278,7 @@ void GuiShaderEditor::onMouseUp(const GuiEvent& event) mDragBeginPoints.clear(); // get mouse pos with our view offset and scale. - mLastMousePos = globalToLocalCoord(event.mousePoint) + mViewOffset * mZoomScale; + mLastMousePos = globalToLocalCoord(event.mousePoint) - mViewOffset; if (mMouseDownMode == DragSelecting) { @@ -295,11 +304,6 @@ void GuiShaderEditor::onMouseUp(const GuiEvent& event) } } - if (mMouseDownMode == MovingSelection && mDragMoveUndo) - { - - } - //reset the mouse mode setFirstResponder(); setMouseMode(Selecting); @@ -314,7 +318,7 @@ void GuiShaderEditor::onMouseDragged(const GuiEvent& event) } // get mouse pos with our view offset and scale. - Point2I mousePoint = globalToLocalCoord(event.mousePoint) + mViewOffset * mZoomScale; + Point2I mousePoint = globalToLocalCoord(event.mousePoint) - mViewOffset; if (mMouseDownMode == DragClone) { @@ -360,7 +364,7 @@ void GuiShaderEditor::onMiddleMouseDown(const GuiEvent& event) mouseLock(); // get mouse pos with our view offset and scale. - mLastMousePos = globalToLocalCoord(event.mousePoint) + mViewOffset * mZoomScale; + mLastMousePos = globalToLocalCoord(event.mousePoint); setMouseMode(DragPanning); @@ -382,7 +386,7 @@ void GuiShaderEditor::onMiddleMouseUp(const GuiEvent& event) mDragBeginPoints.clear(); // get mouse pos with our view offset and scale. - mLastMousePos = globalToLocalCoord(event.mousePoint) + mViewOffset * mZoomScale; + mLastMousePos = globalToLocalCoord(event.mousePoint); setFirstResponder(); setMouseMode(Selecting); @@ -397,13 +401,11 @@ void GuiShaderEditor::onMiddleMouseDragged(const GuiEvent& event) } // get mouse pos with our view offset and scale. - Point2I mousePoint = globalToLocalCoord(event.mousePoint) + mViewOffset * mZoomScale; + Point2I mousePoint = globalToLocalCoord(event.mousePoint); if (mMouseDownMode == DragPanning) { Point2I delta = mousePoint - mLastMousePos; - RectI selBounds = getSelectionBounds(); - // invert it if (delta.x || delta.y) mViewOffset += -delta; @@ -439,12 +441,12 @@ RectI GuiShaderEditor::getSelectionBounds() Vector::const_iterator i = mSelectedNodes.begin(); - Point2I minPos = (*i)->localToGlobalCoord(Point2I(0, 0)) + mViewOffset * mZoomScale; + Point2I minPos = (*i)->localToGlobalCoord(Point2I(0, 0)); Point2I maxPos = minPos; for (; i != mSelectedNodes.end(); i++) { - Point2I iPos = (**i).localToGlobalCoord(Point2I(0, 0)) + mViewOffset * mZoomScale; + Point2I iPos = (**i).localToGlobalCoord(Point2I(0, 0)); minPos.x = getMin(iPos.x, minPos.x); minPos.y = getMin(iPos.y, minPos.y); @@ -458,8 +460,8 @@ RectI GuiShaderEditor::getSelectionBounds() maxPos.y = getMax(iPos.y, maxPos.y); } - minPos = globalToLocalCoord(minPos) + mViewOffset * mZoomScale; - maxPos = globalToLocalCoord(maxPos) + mViewOffset * mZoomScale; + minPos = globalToLocalCoord(minPos); + maxPos = globalToLocalCoord(maxPos); return RectI(minPos.x, minPos.y, (maxPos.x - minPos.x), (maxPos.y - minPos.y)); } diff --git a/Engine/source/gui/shaderEditor/guiShaderEditor.h b/Engine/source/gui/shaderEditor/guiShaderEditor.h index efed5659a..5e9d3f866 100644 --- a/Engine/source/gui/shaderEditor/guiShaderEditor.h +++ b/Engine/source/gui/shaderEditor/guiShaderEditor.h @@ -54,7 +54,6 @@ protected: // Undo SimGroup* mTrash; - SimSet* mSelectedSet; // view controls Point2I mViewOffset; diff --git a/Engine/source/gui/shaderEditor/nodes/shaderNode.cpp b/Engine/source/gui/shaderEditor/nodes/shaderNode.cpp index 8b48d40bc..1aa24aced 100644 --- a/Engine/source/gui/shaderEditor/nodes/shaderNode.cpp +++ b/Engine/source/gui/shaderEditor/nodes/shaderNode.cpp @@ -21,9 +21,10 @@ //----------------------------------------------------------------------------- #include "platform/platform.h" - #include "gui/shaderEditor/nodes/shaderNode.h" +#include "gui/core/guiCanvas.h" + IMPLEMENT_CONOBJECT(ShaderNode); ConsoleDocClass(ShaderNode, @@ -35,6 +36,14 @@ ConsoleDocClass(ShaderNode, ShaderNode::ShaderNode() { + mTitle = "Default Node"; + mSelected = false; + // fixed extent for all nodes, only height should be changed + setExtent(150, 100); + + GuiControlProfile* profile = NULL; + if (Sim::findObject("ToolsGuiDefaultProfile", profile)) + setControlProfile(profile); } bool ShaderNode::onWake() @@ -66,6 +75,39 @@ bool ShaderNode::onAdd() void ShaderNode::onRemove() { + Parent::onRemove(); +} + +void ShaderNode::onRender(Point2I offset, const RectI& updateRect) +{ + if (!mProfile) + return Parent::onRender(offset, updateRect); + + GFXDrawUtil* drawer = GFX->getDrawUtil(); + + // Get our rect. + RectI winRect; + winRect.point = offset; + winRect.extent = getExtent(); + + // draw background. + drawer->drawRectFill(winRect, mProfile->mFillColor); + + // draw header text. + U32 strWidth = mProfile->mFont->getStrWidth(mTitle.c_str()); + Point2I headerPos = Point2I((getExtent().x / 2) - (strWidth / 2), (30 / 2) - (mProfile->mFont->getFontSize() / 2)); + drawer->setBitmapModulation(mProfile->mFontColor); + drawer->drawText(mProfile->mFont, headerPos + offset, mTitle); + drawer->clearBitmapModulation(); + + ColorI border(128, 128, 128, 128); + + if (mSelected) + border = ColorI(128, 0, 128, 128); + + winRect.inset(1, 1); + drawer->drawRect(winRect, border); + } void ShaderNode::write(Stream& stream, U32 tabStop, U32 flags) diff --git a/Engine/source/gui/shaderEditor/nodes/shaderNode.h b/Engine/source/gui/shaderEditor/nodes/shaderNode.h index a5bb46937..68334e9b8 100644 --- a/Engine/source/gui/shaderEditor/nodes/shaderNode.h +++ b/Engine/source/gui/shaderEditor/nodes/shaderNode.h @@ -31,8 +31,14 @@ #include "console/simBase.h" #endif +#ifndef _GFX_GFXDRAWER_H_ +#include "gfx/gfxDrawUtil.h" +#endif + + enum class NodeTypes { + Default, Uniform, Input, Output, @@ -69,6 +75,9 @@ class ShaderNode : public GuiControl private: typedef GuiControl Parent; +protected: + String mTitle; + public: ShaderNode(); @@ -78,6 +87,8 @@ public: virtual bool onAdd() override; virtual void onRemove() override; + virtual void onRender(Point2I offset, const RectI& updateRect) override; + // Serialization functions void write(Stream& stream, U32 tabStop = 0, U32 flags = 0); void read(Stream& stream); @@ -86,5 +97,7 @@ public: DECLARE_CONOBJECT(ShaderNode); DECLARE_CATEGORY("Shader Core"); DECLARE_DESCRIPTION("Base class for all shader nodes."); + + bool mSelected; }; #endif // !_SHADERNODE_H_ diff --git a/Templates/BaseGame/game/tools/gui/profiles.ed.tscript b/Templates/BaseGame/game/tools/gui/profiles.ed.tscript index 770c2ad61..c8b2e4a1c 100644 --- a/Templates/BaseGame/game/tools/gui/profiles.ed.tscript +++ b/Templates/BaseGame/game/tools/gui/profiles.ed.tscript @@ -943,6 +943,16 @@ singleton GuiControlProfile( GuiBackFillProfile ) category = "Editor"; }; +singleton GuiControlProfile(GuiShaderEditorProfile : ToolsGuiDefaultProfile) +{ + opaque = true; +}; + +singleton GuiControlProfile(ShaderNodeProfile : ToolsGuiDefaultProfile) +{ + opaque = true; +}; + singleton GuiControlProfile( GuiControlListPopupProfile ) { opaque = true; diff --git a/Templates/BaseGame/game/tools/shaderEditor/gui/shaderEditorGui.ed.gui b/Templates/BaseGame/game/tools/shaderEditor/gui/shaderEditorGui.ed.gui index c5709f856..9a6f23cc5 100644 --- a/Templates/BaseGame/game/tools/shaderEditor/gui/shaderEditorGui.ed.gui +++ b/Templates/BaseGame/game/tools/shaderEditor/gui/shaderEditorGui.ed.gui @@ -1,24 +1,24 @@ //--- OBJECT WRITE BEGIN --- $guiContent = new GuiControl(ShaderEditorGui) { - extent = "800 600"; + extent = "1280 720"; profile = "GuiDefaultProfile"; tooltipProfile = "ToolsGuiToolTipProfile"; isContainer = "1"; canSaveDynamicFields = "1"; new GuiFrameSetCtrl() { - columns = "0 200 625"; + columns = "0 320 1000"; borderWidth = "2"; borderColor = "10 10 10 0"; autoBalance = "1"; - extent = "800 600"; + extent = "1280 720"; horizSizing = "width"; vertSizing = "height"; profile = "ToolsGuiFrameSetProfile"; tooltipProfile = "ToolsGuiToolTipProfile"; new GuiControl() { - extent = "198 600"; + extent = "318 720"; horizSizing = "width"; vertSizing = "height"; profile = "ToolsGuiDefaultProfile"; @@ -28,7 +28,7 @@ $guiContent = new GuiControl(ShaderEditorGui) { new GuiSplitContainer() { orientation = "Horizontal"; splitPoint = "0 200"; - extent = "197 600"; + extent = "317 720"; horizSizing = "width"; vertSizing = "height"; profile = "ToolsGuiDefaultProfile"; @@ -36,7 +36,7 @@ $guiContent = new GuiControl(ShaderEditorGui) { new GuiPanel(ShaderEditorPreview) { docking = "Client"; - extent = "197 198"; + extent = "317 198"; profile = "ToolsGuiButtonProfile"; tooltipProfile = "ToolsGuiToolTipProfile"; internalName = "Panel1"; @@ -44,7 +44,7 @@ $guiContent = new GuiControl(ShaderEditorGui) { new GuiPanel(ShaderEditorInspector) { docking = "Client"; position = "0 202"; - extent = "197 398"; + extent = "317 518"; profile = "ToolsGuiButtonProfile"; tooltipProfile = "ToolsGuiToolTipProfile"; internalName = "panel2"; @@ -52,17 +52,25 @@ $guiContent = new GuiControl(ShaderEditorGui) { }; }; new GuiControl() { - position = "200 0"; - extent = "423 600"; + position = "320 0"; + extent = "678 720"; horizSizing = "width"; vertSizing = "height"; profile = "ToolsGuiButtonProfile"; tooltipProfile = "ToolsGuiToolTipProfile"; isContainer = "1"; + + new GuiShaderEditor(ShaderNodeGraph) { + extent = "678 720"; + horizSizing = "width"; + vertSizing = "height"; + profile = "GuiShaderEditorProfile"; + tooltipProfile = "GuiToolTipProfile"; + }; }; new GuiControl(ShaderEditorSidebar) { - position = "625 0"; - extent = "175 600"; + position = "1000 0"; + extent = "280 720"; horizSizing = "width"; vertSizing = "height"; profile = "ToolsGuiDefaultProfile"; @@ -74,7 +82,7 @@ $guiContent = new GuiControl(ShaderEditorGui) { allowReorder = "1"; selectedPage = "0"; position = "3 5"; - extent = "166 400"; + extent = "271 520"; horizSizing = "width"; vertSizing = "height"; profile = "ToolsGuiTabBookProfile"; @@ -84,7 +92,7 @@ $guiContent = new GuiControl(ShaderEditorGui) { fitBook = "1"; text = "Library"; position = "0 20"; - extent = "166 380"; + extent = "271 500"; horizSizing = "width"; vertSizing = "height"; profile = "ToolsGuiTabPageProfile"; @@ -93,14 +101,14 @@ $guiContent = new GuiControl(ShaderEditorGui) { new GuiScrollCtrl() { hScrollBar = "dynamic"; childMargin = "0 2"; - extent = "166 370"; + extent = "271 490"; horizSizing = "width"; vertSizing = "height"; profile = "ToolsGuiScrollProfile"; tooltipProfile = "ToolsGuiToolTipProfile"; new GuiStackControl(ShaderToolbox) { - extent = "486 1000"; + extent = "591 1000"; horizSizing = "width"; profile = "ToolsGuiDefaultProfile"; tooltipProfile = "ToolsGuiToolTipProfile"; From b2095db5753fa9d35dd705a4d557668f44714c2b Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Mon, 4 Mar 2024 17:15:13 +0000 Subject: [PATCH 32/53] can key focus --- .../gui/shaderEditor/guiShaderEditor.cpp | 25 +++++++++- .../gui/shaderEditor/nodes/shaderNode.cpp | 49 +++++++++++++++++-- .../gui/shaderEditor/nodes/shaderNode.h | 1 + .../game/tools/gui/profiles.ed.tscript | 1 + 4 files changed, 70 insertions(+), 6 deletions(-) diff --git a/Engine/source/gui/shaderEditor/guiShaderEditor.cpp b/Engine/source/gui/shaderEditor/guiShaderEditor.cpp index 454c3ea24..fd0312769 100644 --- a/Engine/source/gui/shaderEditor/guiShaderEditor.cpp +++ b/Engine/source/gui/shaderEditor/guiShaderEditor.cpp @@ -58,6 +58,7 @@ GuiShaderEditor::GuiShaderEditor() // test mCurrNodes.push_back(new ShaderNode()); + mCurrNodes.push_back(new ShaderNode()); } bool GuiShaderEditor::onWake() @@ -191,6 +192,22 @@ void GuiShaderEditor::onRender(Point2I offset, const RectI& updateRect) bool GuiShaderEditor::onKeyDown(const GuiEvent& event) { + if (!mActive) + return Parent::onKeyDown(event); + + if (!(event.modifier & SI_PRIMARY_CTRL)) + { + switch (event.keyCode) + { + case KEY_BACKSPACE: + case KEY_DELETE: + deleteSelection(); + return true; + default: + break; + } + } + return false; } @@ -367,7 +384,7 @@ void GuiShaderEditor::onMiddleMouseDown(const GuiEvent& event) mLastMousePos = globalToLocalCoord(event.mousePoint); setMouseMode(DragPanning); - + getRoot()->showCursor(false); } void GuiShaderEditor::onMiddleMouseUp(const GuiEvent& event) @@ -378,6 +395,8 @@ void GuiShaderEditor::onMiddleMouseUp(const GuiEvent& event) return; } + getRoot()->showCursor(true); + //unlock the mouse mouseUnlock(); @@ -471,6 +490,10 @@ void GuiShaderEditor::deleteSelection() for (ShaderNode* node : mSelectedNodes) { mTrash->addObject(node); + + Vector< ShaderNode* >::iterator i = T3D::find(mCurrNodes.begin(), mCurrNodes.end(), node); + if (i != mCurrNodes.end()) + mCurrNodes.erase(i); } clearSelection(); diff --git a/Engine/source/gui/shaderEditor/nodes/shaderNode.cpp b/Engine/source/gui/shaderEditor/nodes/shaderNode.cpp index 1aa24aced..16aa08c8b 100644 --- a/Engine/source/gui/shaderEditor/nodes/shaderNode.cpp +++ b/Engine/source/gui/shaderEditor/nodes/shaderNode.cpp @@ -38,8 +38,9 @@ ShaderNode::ShaderNode() { mTitle = "Default Node"; mSelected = false; + mNodeType = NodeTypes::Uniform; // fixed extent for all nodes, only height should be changed - setExtent(150, 100); + setExtent(210, 100); GuiControlProfile* profile = NULL; if (Sim::findObject("ToolsGuiDefaultProfile", profile)) @@ -85,14 +86,53 @@ void ShaderNode::onRender(Point2I offset, const RectI& updateRect) GFXDrawUtil* drawer = GFX->getDrawUtil(); + // draw background. // Get our rect. RectI winRect; winRect.point = offset; winRect.extent = getExtent(); - - // draw background. drawer->drawRectFill(winRect, mProfile->mFillColor); + // draw header + RectI headRect; + headRect.point = offset; + headRect.extent = Point2I(getExtent().x, 30); + + ColorI header(50, 50, 50, 128); + + switch (mNodeType) + { + case NodeTypes::Default: + header = ColorI(128, 50, 128, 128); + break; + case NodeTypes::Uniform: + header = ColorI(50, 100, 128, 128); + break; + case NodeTypes::Input: + header = ColorI(128, 100, 50, 128); + break; + case NodeTypes::Output: + header = ColorI(50, 100, 50, 128); + break; + case NodeTypes::TextureSampler: + header = ColorI(50, 50, 128, 128); + break; + case NodeTypes::MathOperation: + header = ColorI(128, 0, 128, 128); + break; + case NodeTypes::Procedural: + header = ColorI(128, 100, 0, 128); + break; + case NodeTypes::Generator: + header = ColorI(0, 100, 128, 128); + break; + default: + header = ColorI(128, 0, 0, 128); + break; + } + + drawer->drawRectFill(headRect, header); + // draw header text. U32 strWidth = mProfile->mFont->getStrWidth(mTitle.c_str()); Point2I headerPos = Point2I((getExtent().x / 2) - (strWidth / 2), (30 / 2) - (mProfile->mFont->getFontSize() / 2)); @@ -103,9 +143,8 @@ void ShaderNode::onRender(Point2I offset, const RectI& updateRect) ColorI border(128, 128, 128, 128); if (mSelected) - border = ColorI(128, 0, 128, 128); + border = ColorI(128, 0, 128, 255); - winRect.inset(1, 1); drawer->drawRect(winRect, border); } diff --git a/Engine/source/gui/shaderEditor/nodes/shaderNode.h b/Engine/source/gui/shaderEditor/nodes/shaderNode.h index 68334e9b8..09db42bc2 100644 --- a/Engine/source/gui/shaderEditor/nodes/shaderNode.h +++ b/Engine/source/gui/shaderEditor/nodes/shaderNode.h @@ -77,6 +77,7 @@ private: protected: String mTitle; + NodeTypes mNodeType; public: ShaderNode(); diff --git a/Templates/BaseGame/game/tools/gui/profiles.ed.tscript b/Templates/BaseGame/game/tools/gui/profiles.ed.tscript index c8b2e4a1c..b4c0410e8 100644 --- a/Templates/BaseGame/game/tools/gui/profiles.ed.tscript +++ b/Templates/BaseGame/game/tools/gui/profiles.ed.tscript @@ -946,6 +946,7 @@ singleton GuiControlProfile( GuiBackFillProfile ) singleton GuiControlProfile(GuiShaderEditorProfile : ToolsGuiDefaultProfile) { opaque = true; + canKeyFocus = true; }; singleton GuiControlProfile(ShaderNodeProfile : ToolsGuiDefaultProfile) From 155dfe0c69f4c07ebd72cd8411678da13631a256 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Tue, 5 Mar 2024 13:15:33 +0000 Subject: [PATCH 33/53] more options for nodes render nodes with GuiShaderEditor border colors node size now changable. --- .../gui/shaderEditor/guiShaderEditor.cpp | 118 +++++++++++++----- .../source/gui/shaderEditor/guiShaderEditor.h | 13 +- .../gui/shaderEditor/nodes/shaderNode.cpp | 101 +++++++++++---- .../gui/shaderEditor/nodes/shaderNode.h | 29 ++++- 4 files changed, 196 insertions(+), 65 deletions(-) diff --git a/Engine/source/gui/shaderEditor/guiShaderEditor.cpp b/Engine/source/gui/shaderEditor/guiShaderEditor.cpp index fd0312769..b79de5643 100644 --- a/Engine/source/gui/shaderEditor/guiShaderEditor.cpp +++ b/Engine/source/gui/shaderEditor/guiShaderEditor.cpp @@ -30,6 +30,7 @@ #include "gui/core/guiCanvas.h" #include "console/engineAPI.h" #include "console/script.h" +#include "console/typeValidators.h" IMPLEMENT_CONOBJECT(GuiShaderEditor); @@ -55,10 +56,10 @@ GuiShaderEditor::GuiShaderEditor() mMouseDownMode = GuiShaderEditor::Selecting; mTrash = NULL; - + mNodeSize = 10; // test - mCurrNodes.push_back(new ShaderNode()); - mCurrNodes.push_back(new ShaderNode()); + mCurrNodes.push_back(new GuiShaderNode()); + mCurrNodes.push_back(new GuiShaderNode()); } bool GuiShaderEditor::onWake() @@ -74,12 +75,20 @@ void GuiShaderEditor::onSleep() Parent::onSleep(); } +// anything smaller than 4 is way too small.... +IRangeValidator nodeSizeRange(4, 30); + void GuiShaderEditor::initPersistFields() { docsURL; + addGroup("Node Settings"); + addFieldV("nodeSize", TypeS32, Offset(mNodeSize, GuiShaderEditor),&nodeSizeRange, + "Size of nodes."); + endGroup("Node Settings"); + addGroup("Selection"); - addField("fullBoxSelection", TypeBool, Offset(mFullBoxSelection, GuiShaderEditor), - "If true, rectangle selection will only select controls fully inside the drag rectangle."); + addField("fullBoxSelection", TypeBool, Offset(mFullBoxSelection, GuiShaderEditor), + "If true, rectangle selection will only select controls fully inside the drag rectangle."); endGroup("Selection"); Parent::initPersistFields(); } @@ -106,12 +115,12 @@ void GuiShaderEditor::onRemove() mTrash = NULL; - for (ShaderNode* node : mCurrNodes) + for (GuiShaderNode* node : mCurrNodes) { SAFE_DELETE(node); } - for (ShaderNode* node : mSelectedNodes) + for (GuiShaderNode* node : mSelectedNodes) { SAFE_DELETE(node); } @@ -134,8 +143,12 @@ void GuiShaderEditor::renderNodes(Point2I offset, const RectI& updateRect) RectI clipRect = updateRect; clipRect.inset(2, 2); - for (ShaderNode* node : mCurrNodes) + GFXDrawUtil* drawer = GFX->getDrawUtil(); + + // render nodes in reverse order. + for (ShaderNodeVector::iterator i = mCurrNodes.end(); i-- != mCurrNodes.begin(); ) { + GuiShaderNode* node = *i; // this is useful for sub node graphs. if (node->isVisible()) { @@ -155,7 +168,39 @@ void GuiShaderEditor::renderNodes(Point2I offset, const RectI& updateRect) { GFX->setClipRect(childClip); GFX->setStateBlock(mDefaultGuiSB); - node->onRender(childPos, childClip); + node->onRender(childPos, childClip, mNodeSize); + } + + GFX->setClipRect(clipRect); + GFX->setStateBlock(mDefaultGuiSB); + for (NodeInput* input : node->mInputNodes) + { + Point2I pos = node->localToGlobalCoord(input->pos) + offset; + + ColorI border = mProfile->mBorderColor; + + if (node->mSelected) + border = mProfile->mBorderColorSEL; + + RectI socketRect(pos, Point2I(mNodeSize, mNodeSize)); + drawer->drawRect(socketRect, border); + socketRect.inset(1, 1); + drawer->drawRectFill(socketRect, mProfile->mFillColor); + } + + for (NodeOutput* output : node->mOutputNodes) + { + Point2I pos = node->localToGlobalCoord(output->pos) + offset; + + ColorI border = mProfile->mBorderColor; + + if (node->mSelected) + border = mProfile->mBorderColorSEL; + + RectI socketRect(pos, Point2I(mNodeSize, mNodeSize)); + drawer->drawRect(socketRect, border); + socketRect.inset(1, 1); + drawer->drawRectFill(socketRect, mProfile->mFillColor); } } } @@ -227,7 +272,7 @@ void GuiShaderEditor::onMouseDown(const GuiEvent& event) // get mouse pos with our view offset and scale. mLastMousePos = globalToLocalCoord(event.mousePoint) - mViewOffset; - ShaderNode* hitNode = findHitNode(mLastMousePos); + GuiShaderNode* hitNode = findHitNode(mLastMousePos); if (event.modifier & SI_SHIFT) { @@ -311,10 +356,10 @@ void GuiShaderEditor::onMouseUp(const GuiEvent& event) } else { - Vector< ShaderNode* > hits; + Vector< GuiShaderNode* > hits; findNodesInRect(rect, hits); - for (ShaderNode* node : hits) + for (GuiShaderNode* node : hits) { addSelection(node); } @@ -458,7 +503,7 @@ bool GuiShaderEditor::onMouseWheelDown(const GuiEvent& event) RectI GuiShaderEditor::getSelectionBounds() { - Vector::const_iterator i = mSelectedNodes.begin(); + Vector::const_iterator i = mSelectedNodes.begin(); Point2I minPos = (*i)->localToGlobalCoord(Point2I(0, 0)); Point2I maxPos = minPos; @@ -487,11 +532,11 @@ RectI GuiShaderEditor::getSelectionBounds() void GuiShaderEditor::deleteSelection() { - for (ShaderNode* node : mSelectedNodes) + for (GuiShaderNode* node : mSelectedNodes) { mTrash->addObject(node); - Vector< ShaderNode* >::iterator i = T3D::find(mCurrNodes.begin(), mCurrNodes.end(), node); + Vector< GuiShaderNode* >::iterator i = T3D::find(mCurrNodes.begin(), mCurrNodes.end(), node); if (i != mCurrNodes.end()) mCurrNodes.erase(i); } @@ -501,7 +546,7 @@ void GuiShaderEditor::deleteSelection() void GuiShaderEditor::moveSelection(const Point2I& delta, bool callback) { - for (ShaderNode* node : mSelectedNodes) + for (GuiShaderNode* node : mSelectedNodes) { node->setPosition(node->getPosition() + delta); } @@ -514,19 +559,20 @@ void GuiShaderEditor::clearSelection() void GuiShaderEditor::cloneSelection() { - Vector newSelection; + Vector newSelection; - for (ShaderNode* node : mSelectedNodes) + for (GuiShaderNode* node : mSelectedNodes) { - ShaderNode* clone = dynamic_cast(node->deepClone()); + GuiShaderNode* clone = dynamic_cast(node->deepClone()); if (clone) newSelection.push_back(clone); } clearSelection(); - for (ShaderNode* cloneNode : newSelection) + for (GuiShaderNode* cloneNode : newSelection) { + mCurrNodes.push_back(cloneNode); addSelection(cloneNode); } } @@ -536,7 +582,7 @@ void GuiShaderEditor::addSelectionAtPoint(const Point2I& pos) // turn hit off on already selected nodes. canHitSelectedNodes(false); - ShaderNode* node = findHitNode(pos); + GuiShaderNode* node = findHitNode(pos); // reset hit status. canHitSelectedNodes(); @@ -545,7 +591,7 @@ void GuiShaderEditor::addSelectionAtPoint(const Point2I& pos) addSelection(node); } -void GuiShaderEditor::addSelection(ShaderNode* inNode) +void GuiShaderEditor::addSelection(GuiShaderNode* inNode) { if (inNode != NULL && !selectionContains(inNode)) { @@ -553,9 +599,9 @@ void GuiShaderEditor::addSelection(ShaderNode* inNode) } } -bool GuiShaderEditor::selectionContains(ShaderNode* inNode) +bool GuiShaderEditor::selectionContains(GuiShaderNode* inNode) { - for (ShaderNode* node : mSelectedNodes) + for (GuiShaderNode* node : mSelectedNodes) { if (node == inNode) return true; @@ -564,11 +610,11 @@ bool GuiShaderEditor::selectionContains(ShaderNode* inNode) return false; } -void GuiShaderEditor::removeSelection(ShaderNode* inNode) +void GuiShaderEditor::removeSelection(GuiShaderNode* inNode) { if (selectionContains(inNode)) { - Vector< ShaderNode* >::iterator i = T3D::find(mSelectedNodes.begin(), mSelectedNodes.end(), inNode); + Vector< GuiShaderNode* >::iterator i = T3D::find(mSelectedNodes.begin(), mSelectedNodes.end(), inNode); if (i != mSelectedNodes.end()) mSelectedNodes.erase(i); } @@ -576,7 +622,7 @@ void GuiShaderEditor::removeSelection(ShaderNode* inNode) void GuiShaderEditor::canHitSelectedNodes(bool state) { - for (ShaderNode* node : mSelectedNodes) + for (GuiShaderNode* node : mSelectedNodes) node->setCanHit(state); } @@ -584,12 +630,20 @@ void GuiShaderEditor::canHitSelectedNodes(bool state) // Input handling //----------------------------------------------------------------------------- -ShaderNode* GuiShaderEditor::findHitNode(const Point2I& pt) +GuiShaderNode* GuiShaderEditor::findHitNode(const Point2I& pt) { - for (ShaderNode* node : mCurrNodes) + for (GuiShaderNode* node : mCurrNodes) { if (node->pointInControl(pt)) { + // selecting one node, push it to the front of the mcurrnodes stack so its rendered on top. + Vector< GuiShaderNode* >::iterator i = T3D::find(mCurrNodes.begin(), mCurrNodes.end(), node); + if (i != mCurrNodes.end()) + { + mCurrNodes.erase(i); + mCurrNodes.insert(mCurrNodes.begin(), node); + } + return node; } } @@ -597,10 +651,10 @@ ShaderNode* GuiShaderEditor::findHitNode(const Point2I& pt) return nullptr; } -void GuiShaderEditor::findNodesInRect(const RectI& rect, Vector& outResult) +void GuiShaderEditor::findNodesInRect(const RectI& rect, Vector& outResult) { canHitSelectedNodes(false); - for (ShaderNode* node : mCurrNodes) + for (GuiShaderNode* node : mCurrNodes) { if (node->getBounds().overlaps(rect)) { @@ -627,7 +681,7 @@ void GuiShaderEditor::startDragMove(const Point2I& startPoint) mDragBeginPoints.reserve(mSelectedNodes.size()); - for (ShaderNode* node : mSelectedNodes) + for (GuiShaderNode* node : mSelectedNodes) { mDragBeginPoints.push_back(node->getPosition()); } diff --git a/Engine/source/gui/shaderEditor/guiShaderEditor.h b/Engine/source/gui/shaderEditor/guiShaderEditor.h index 5e9d3f866..011e3cb58 100644 --- a/Engine/source/gui/shaderEditor/guiShaderEditor.h +++ b/Engine/source/gui/shaderEditor/guiShaderEditor.h @@ -48,7 +48,7 @@ public: protected: // list - typedef Vector ShaderNodeVector; + typedef Vector ShaderNodeVector; // all nodes in this graph. ShaderNodeVector mCurrNodes; @@ -68,13 +68,14 @@ protected: bool mDragAddSelection; bool mDragMoveUndo; bool mFullBoxSelection; + S32 mNodeSize; ShaderNodeVector mSelectedNodes; void renderNodes(Point2I offset, const RectI& updateRect); // functions for handling mouse events. - ShaderNode* findHitNode(const Point2I& pt); - void findNodesInRect(const RectI& rect, Vector& outResult); + GuiShaderNode* findHitNode(const Point2I& pt); + void findNodesInRect(const RectI& rect, Vector& outResult); void getDragRect(RectI& box); void startDragMove(const Point2I& startPoint); @@ -115,9 +116,9 @@ public: void clearSelection(); void cloneSelection(); void addSelectionAtPoint(const Point2I& pos); - void addSelection(ShaderNode* inNode); - bool selectionContains(ShaderNode* inNode); - void removeSelection(ShaderNode* inNode); + void addSelection(GuiShaderNode* inNode); + bool selectionContains(GuiShaderNode* inNode); + void removeSelection(GuiShaderNode* inNode); void canHitSelectedNodes(bool state = true); }; diff --git a/Engine/source/gui/shaderEditor/nodes/shaderNode.cpp b/Engine/source/gui/shaderEditor/nodes/shaderNode.cpp index 16aa08c8b..ee5766a40 100644 --- a/Engine/source/gui/shaderEditor/nodes/shaderNode.cpp +++ b/Engine/source/gui/shaderEditor/nodes/shaderNode.cpp @@ -25,29 +25,46 @@ #include "gui/core/guiCanvas.h" -IMPLEMENT_CONOBJECT(ShaderNode); +IMPLEMENT_CONOBJECT(GuiShaderNode); -ConsoleDocClass(ShaderNode, +ConsoleDocClass(GuiShaderNode, "@brief Base class for all nodes to derive from.\n\n" "Editor use only.\n\n" "@internal" ); -ShaderNode::ShaderNode() +GuiShaderNode::GuiShaderNode() { + VECTOR_SET_ASSOCIATION(mInputNodes); + VECTOR_SET_ASSOCIATION(mOutputNodes); + mTitle = "Default Node"; mSelected = false; - mNodeType = NodeTypes::Uniform; - // fixed extent for all nodes, only height should be changed - setExtent(210, 100); + mNodeType = NodeTypes::Default; + GuiControlProfile* profile = NULL; - if (Sim::findObject("ToolsGuiDefaultProfile", profile)) + if (Sim::findObject("GuiShaderEditorProfile", profile)) setControlProfile(profile); + + mInputNodes.push_back(new NodeInput("RGBA", DataDimensions::Dynamic)); + mInputNodes.push_back(new NodeInput("RGBA", DataDimensions::Dynamic)); + mInputNodes.push_back(new NodeInput("RGBA", DataDimensions::Dynamic)); + mInputNodes.push_back(new NodeInput("RGBA", DataDimensions::Dynamic)); + + mOutputNodes.push_back(new NodeOutput("RGBA", DataDimensions::Dynamic)); + mOutputNodes.push_back(new NodeOutput("RGBA", DataDimensions::Dynamic)); + mOutputNodes.push_back(new NodeOutput("RGBA", DataDimensions::Dynamic)); + mOutputNodes.push_back(new NodeOutput("RGBA", DataDimensions::Dynamic)); + + // fixed extent for all nodes, only height should be changed + setExtent(210, 35); + + mPrevNodeSize = -1; } -bool ShaderNode::onWake() +bool GuiShaderNode::onWake() { if (!Parent::onWake()) return false; @@ -55,18 +72,18 @@ bool ShaderNode::onWake() return true; } -void ShaderNode::onSleep() +void GuiShaderNode::onSleep() { Parent::onSleep(); } -void ShaderNode::initPersistFields() +void GuiShaderNode::initPersistFields() { docsURL; Parent::initPersistFields(); } -bool ShaderNode::onAdd() +bool GuiShaderNode::onAdd() { if (!Parent::onAdd()) return false; @@ -74,12 +91,12 @@ bool ShaderNode::onAdd() return true; } -void ShaderNode::onRemove() +void GuiShaderNode::onRemove() { Parent::onRemove(); } -void ShaderNode::onRender(Point2I offset, const RectI& updateRect) +void GuiShaderNode::onRender(Point2I offset, const RectI& updateRect, const S32 nodeSize) { if (!mProfile) return Parent::onRender(offset, updateRect); @@ -94,10 +111,6 @@ void ShaderNode::onRender(Point2I offset, const RectI& updateRect) drawer->drawRectFill(winRect, mProfile->mFillColor); // draw header - RectI headRect; - headRect.point = offset; - headRect.extent = Point2I(getExtent().x, 30); - ColorI header(50, 50, 50, 128); switch (mNodeType) @@ -131,28 +144,72 @@ void ShaderNode::onRender(Point2I offset, const RectI& updateRect) break; } + RectI headRect; + U32 headerSize = 30; + headRect.point = offset; + headRect.extent = Point2I(getExtent().x, headerSize); drawer->drawRectFill(headRect, header); // draw header text. U32 strWidth = mProfile->mFont->getStrWidth(mTitle.c_str()); - Point2I headerPos = Point2I((getExtent().x / 2) - (strWidth / 2), (30 / 2) - (mProfile->mFont->getFontSize() / 2)); + Point2I headerPos = Point2I((getExtent().x / 2) - (strWidth / 2), (headerSize / 2) - (mProfile->mFont->getFontSize() / 2)); drawer->setBitmapModulation(mProfile->mFontColor); drawer->drawText(mProfile->mFont, headerPos + offset, mTitle); drawer->clearBitmapModulation(); - ColorI border(128, 128, 128, 128); + ColorI border = mProfile->mBorderColor; if (mSelected) - border = ColorI(128, 0, 128, 255); + border = mProfile->mBorderColorSEL; drawer->drawRect(winRect, border); + + if (mInputNodes.size() > 0 || mOutputNodes.size() > 0) + { + U32 textPadX = nodeSize, textPadY = mProfile->mFont->getFontSize() + (nodeSize / 2); + Point2I slotPos(textPadX, headerSize + (nodeSize / 2)); + drawer->setBitmapModulation(mProfile->mFontColor); + for (NodeInput* input : mInputNodes) + { + drawer->drawText(mProfile->mFont, slotPos + offset, input->name); + + if (input->pos == Point2I::Zero || mPrevNodeSize != nodeSize) + input->pos = Point2I(-(nodeSize / 2), slotPos.y + ((mProfile->mFont->getFontSize() / 2) - (nodeSize / 2))); + + slotPos.y += textPadY; + } + + U32 inputY = slotPos.y; + + slotPos = Point2I(getExtent().x, headerSize + (nodeSize / 2)); + for (NodeOutput* output : mOutputNodes) + { + strWidth = mProfile->mFont->getStrWidth(output->name.c_str()); + slotPos.x = getExtent().x - strWidth - textPadX; + + drawer->drawText(mProfile->mFont, slotPos + offset, output->name); + + if (output->pos == Point2I::Zero || mPrevNodeSize != nodeSize) + output->pos = Point2I(getExtent().x - (nodeSize / 2), slotPos.y + ((mProfile->mFont->getFontSize() / 2) - (nodeSize / 2))); + + slotPos.y += textPadY; + } + drawer->clearBitmapModulation(); + + U32 outputY = slotPos.y; + + if (getExtent().y < slotPos.y || mPrevNodeSize != nodeSize) + setExtent(Point2I(getExtent().x, mMax(inputY, outputY))); + + mPrevNodeSize = nodeSize; + } } -void ShaderNode::write(Stream& stream, U32 tabStop, U32 flags) +void GuiShaderNode::write(Stream& stream, U32 tabStop, U32 flags) { } -void ShaderNode::read(Stream& stream) +void GuiShaderNode::read(Stream& stream) { } diff --git a/Engine/source/gui/shaderEditor/nodes/shaderNode.h b/Engine/source/gui/shaderEditor/nodes/shaderNode.h index 09db42bc2..645125e05 100644 --- a/Engine/source/gui/shaderEditor/nodes/shaderNode.h +++ b/Engine/source/gui/shaderEditor/nodes/shaderNode.h @@ -62,15 +62,31 @@ struct NodeInput { String name; DataDimensions dimensions; + Point2I pos = Point2I::Zero; + + NodeInput() + :name(String::EmptyString), dimensions(DataDimensions::Dynamic) + {} + NodeInput(String inName , DataDimensions inDim) + :name(inName), dimensions(inDim) + {} }; struct NodeOutput { String name; DataDimensions dimensions; + Point2I pos = Point2I::Zero; + + NodeOutput() + :name(String::EmptyString), dimensions(DataDimensions::Dynamic) + {} + NodeOutput(String inName, DataDimensions inDim) + :name(inName), dimensions(inDim) + {} }; -class ShaderNode : public GuiControl +class GuiShaderNode : public GuiControl { private: typedef GuiControl Parent; @@ -78,9 +94,12 @@ private: protected: String mTitle; NodeTypes mNodeType; - + S32 mPrevNodeSize; public: - ShaderNode(); + Vector mInputNodes; + Vector mOutputNodes; + + GuiShaderNode(); bool onWake(); void onSleep(); @@ -88,14 +107,14 @@ public: virtual bool onAdd() override; virtual void onRemove() override; - virtual void onRender(Point2I offset, const RectI& updateRect) override; + void onRender(Point2I offset, const RectI& updateRect, const S32 nodeSize); // Serialization functions void write(Stream& stream, U32 tabStop = 0, U32 flags = 0); void read(Stream& stream); // is the parent that all other nodes are derived from. - DECLARE_CONOBJECT(ShaderNode); + DECLARE_CONOBJECT(GuiShaderNode); DECLARE_CATEGORY("Shader Core"); DECLARE_DESCRIPTION("Base class for all shader nodes."); From 66d8f0f55cb079fc449382285948d22c47bb122e Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Tue, 5 Mar 2024 13:15:54 +0000 Subject: [PATCH 34/53] Update profiles.ed.tscript --- Templates/BaseGame/game/tools/gui/profiles.ed.tscript | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Templates/BaseGame/game/tools/gui/profiles.ed.tscript b/Templates/BaseGame/game/tools/gui/profiles.ed.tscript index b4c0410e8..26886e128 100644 --- a/Templates/BaseGame/game/tools/gui/profiles.ed.tscript +++ b/Templates/BaseGame/game/tools/gui/profiles.ed.tscript @@ -947,11 +947,10 @@ singleton GuiControlProfile(GuiShaderEditorProfile : ToolsGuiDefaultProfile) { opaque = true; canKeyFocus = true; -}; - -singleton GuiControlProfile(ShaderNodeProfile : ToolsGuiDefaultProfile) -{ - opaque = true; + border = true; + borderColor = "128 128 128 128"; + borderColorHL = "128 128 0"; + borderColorSEL = "128 0 128 128"; }; singleton GuiControlProfile( GuiControlListPopupProfile ) From 949f788a0ad867c0b3d8abce29d2c93dbcde3d1b Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Tue, 5 Mar 2024 20:39:33 +0000 Subject: [PATCH 35/53] connections connections rendering and logic finished. can make rendering better in future updates such as using geo shaders for bezier curves and smoother lines. --- .../gui/shaderEditor/guiShaderEditor.cpp | 430 +++++++++++++++--- .../source/gui/shaderEditor/guiShaderEditor.h | 23 +- .../gui/shaderEditor/nodes/shaderNode.cpp | 4 +- .../gui/shaderEditor/nodes/shaderNode.h | 31 +- 4 files changed, 424 insertions(+), 64 deletions(-) diff --git a/Engine/source/gui/shaderEditor/guiShaderEditor.cpp b/Engine/source/gui/shaderEditor/guiShaderEditor.cpp index b79de5643..03cd40ec4 100644 --- a/Engine/source/gui/shaderEditor/guiShaderEditor.cpp +++ b/Engine/source/gui/shaderEditor/guiShaderEditor.cpp @@ -31,6 +31,7 @@ #include "console/engineAPI.h" #include "console/script.h" #include "console/typeValidators.h" +#include "gfx/primBuilder.h" IMPLEMENT_CONOBJECT(GuiShaderEditor); @@ -51,15 +52,17 @@ GuiShaderEditor::GuiShaderEditor() VECTOR_SET_ASSOCIATION(mCurrNodes); VECTOR_SET_ASSOCIATION(mSelectedNodes); VECTOR_SET_ASSOCIATION(mDragBeginPoints); + VECTOR_SET_ASSOCIATION(mCurrConnections); mActive = true; mMouseDownMode = GuiShaderEditor::Selecting; mTrash = NULL; + mTempConnection = NULL; mNodeSize = 10; // test - mCurrNodes.push_back(new GuiShaderNode()); - mCurrNodes.push_back(new GuiShaderNode()); + addNode(new GuiShaderNode()); + addNode(new GuiShaderNode()); } bool GuiShaderEditor::onWake() @@ -115,10 +118,10 @@ void GuiShaderEditor::onRemove() mTrash = NULL; - for (GuiShaderNode* node : mCurrNodes) + /* for (GuiShaderNode* node : mCurrNodes) { SAFE_DELETE(node); - } + }*/ for (GuiShaderNode* node : mSelectedNodes) { @@ -131,6 +134,45 @@ void GuiShaderEditor::onPreRender() setUpdate(); } +void GuiShaderEditor::drawThickLine(const Point2I& pt1, const Point2I& pt2, U32 thickness = 2, ColorI col1 = ColorI(255, 255, 255), ColorI col2 = ColorI(255, 255, 255)) +{ + Point2F dir = Point2F(pt2.x - pt1.x, pt2.y - pt1.y); + if (dir == Point2F::Zero) + return; + + Point2F unitDir = dir / mSqrt(dir.x * dir.x + dir.y * dir.y); + Point2F unitPerp(-unitDir.y, unitDir.x); + Point2F offset = (thickness / 2.0f) * unitPerp; + + GFX->setStateBlock(mDefaultGuiSB); + + Point2F lT = Point2F(pt1.x, pt1.y) + offset; + Point2F lB = Point2F(pt1.x, pt1.y) - offset; + Point2F rT = Point2F(pt2.x, pt2.y) + offset; + Point2F rB = Point2F(pt2.x, pt2.y) - offset; + + + PrimBuild::begin(GFXTriangleStrip, 4); + + // top left. + PrimBuild::color(col1); + PrimBuild::vertex2f(lT.x, lT.y); + + // bottom left. + PrimBuild::color(col1); + PrimBuild::vertex2f(lB.x, lB.y); + + // top right. + PrimBuild::color(col2); + PrimBuild::vertex2f(rT.x, rT.y); + + // bottom right. + PrimBuild::color(col2); + PrimBuild::vertex2f(rB.x, rB.y); + + PrimBuild::end(); +} + void GuiShaderEditor::renderNodes(Point2I offset, const RectI& updateRect) { // Save the current clip rect @@ -168,7 +210,7 @@ void GuiShaderEditor::renderNodes(Point2I offset, const RectI& updateRect) { GFX->setClipRect(childClip); GFX->setStateBlock(mDefaultGuiSB); - node->onRender(childPos, childClip, mNodeSize); + node->renderNode(childPos, childClip, mNodeSize); } GFX->setClipRect(clipRect); @@ -185,7 +227,14 @@ void GuiShaderEditor::renderNodes(Point2I offset, const RectI& updateRect) RectI socketRect(pos, Point2I(mNodeSize, mNodeSize)); drawer->drawRect(socketRect, border); socketRect.inset(1, 1); - drawer->drawRectFill(socketRect, mProfile->mFillColor); + + ColorI fill = mProfile->mFillColor; + if (hasConnection(input)) + { + fill = ColorI::WHITE; + } + + drawer->drawRectFill(socketRect, fill); } for (NodeOutput* output : node->mOutputNodes) @@ -200,7 +249,14 @@ void GuiShaderEditor::renderNodes(Point2I offset, const RectI& updateRect) RectI socketRect(pos, Point2I(mNodeSize, mNodeSize)); drawer->drawRect(socketRect, border); socketRect.inset(1, 1); - drawer->drawRectFill(socketRect, mProfile->mFillColor); + + ColorI fill = mProfile->mFillColor; + if (hasConnection(output)) + { + fill = ColorI::WHITE; + } + + drawer->drawRectFill(socketRect, fill); } } } @@ -210,6 +266,40 @@ void GuiShaderEditor::renderNodes(Point2I offset, const RectI& updateRect) GFX->setClipRect(savedClipRect); } +void GuiShaderEditor::renderConnections(Point2I offset, const RectI& updateRect) +{ + // Save the current clip rect + // so we can restore it at the end of this method. + RectI savedClipRect = GFX->getClipRect(); + + // offset is the upper-left corner of this control in screen coordinates + // updateRect is the intersection rectangle in screen coords of the control + // hierarchy. This can be set as the clip rectangle in most cases. + RectI clipRect = updateRect; + clipRect.inset(2, 2); + + GFXDrawUtil* drawer = GFX->getDrawUtil(); + + for (NodeConnection* conn : mCurrConnections) + { + // for temp connetion, nodeA is always the first node selected. + Point2I start(Point2I::Zero); + Point2I end(Point2I::Zero); + + start = conn->nodeA->localToGlobalCoord(conn->inSocket->pos) + offset; + end = conn->nodeB->localToGlobalCoord(conn->outSocket->pos) + offset; + + start += Point2I(mNodeSize / 2, mNodeSize / 2); + end += Point2I(mNodeSize / 2, mNodeSize / 2); + + drawThickLine(start, end); + } + + // Restore the clip rect to what it was at the start + // of this method. + GFX->setClipRect(savedClipRect); +} + void GuiShaderEditor::onRender(Point2I offset, const RectI& updateRect) { offset += mViewOffset; @@ -217,21 +307,48 @@ void GuiShaderEditor::onRender(Point2I offset, const RectI& updateRect) GFXDrawUtil* drawer = GFX->getDrawUtil(); // render our nodes. + renderConnections(offset, updateRect); renderNodes(offset, updateRect); - // Draw selection rectangle last so it is rendered on top. - if (mActive && mMouseDownMode == DragSelecting) + if (mActive) { - RectI b; - getDragRect(b); - b.point += offset; + if (mMouseDownMode == DragConnection) + { + // something went wrong.... fix it fix it fix it. + if (mTempConnection == NULL) + return; + else + { + // for temp connetion, nodeA is always the first node selected. + Point2I start(Point2I::Zero); + if (mTempConnection->inSocket != NULL) + start = mTempConnection->nodeA->localToGlobalCoord(mTempConnection->inSocket->pos) + offset; + else if(mTempConnection->outSocket != NULL) + start = mTempConnection->nodeA->localToGlobalCoord(mTempConnection->outSocket->pos) + offset; - // Draw outline. - drawer->drawRect(b, ColorI(100, 100, 100, 128)); + RectI sockActive(start, Point2I(mNodeSize, mNodeSize)); + start += Point2I(mNodeSize / 2, mNodeSize / 2); + drawThickLine(start, mLastMousePos + offset); - // Draw fill. - b.inset(1, 1); - drawer->drawRectFill(b, ColorI(150, 150, 150, 128)); + // draw socket overlay over the top of the line. + sockActive.inset(1, 1); + drawer->drawRectFill(sockActive, ColorI(255, 255, 255)); + } + } + // Draw selection rectangle last so it is rendered on top. + if (mMouseDownMode == DragSelecting) + { + RectI b; + getDragRect(b); + b.point += offset; + + // Draw outline. + drawer->drawRect(b, ColorI(100, 100, 100, 128)); + + // Draw fill. + b.inset(1, 1); + drawer->drawRectFill(b, ColorI(150, 150, 150, 128)); + } } } @@ -274,51 +391,59 @@ void GuiShaderEditor::onMouseDown(const GuiEvent& event) GuiShaderNode* hitNode = findHitNode(mLastMousePos); - if (event.modifier & SI_SHIFT) + if(findHitSocket(mLastMousePos)) { - startDragRectangle(mLastMousePos); - mDragAddSelection = true; - } - else if (selectionContains(hitNode)) - { - if (event.modifier & SI_MULTISELECT) - { - removeSelection(hitNode); - setMouseMode(Selecting); - } - else if (event.modifier & SI_PRIMARY_ALT) - { - startDragClone(mLastMousePos); - } - else - { - startDragMove(mLastMousePos); - } + // handled in hit socket. + return; } else { - if (hitNode == NULL) + if (event.modifier & SI_SHIFT) { startDragRectangle(mLastMousePos); - mDragAddSelection = false; + mDragAddSelection = true; } - else if (event.modifier & SI_PRIMARY_ALT && hitNode != NULL) + else if (selectionContains(hitNode)) { - // Alt is down. Start a drag clone. - clearSelection(); - addSelection(hitNode); - startDragClone(mLastMousePos); - } - else if (event.modifier & SI_MULTISELECT) - { - addSelection(hitNode); + if (event.modifier & SI_MULTISELECT) + { + removeSelection(hitNode); + setMouseMode(Selecting); + } + else if (event.modifier & SI_PRIMARY_ALT) + { + startDragClone(mLastMousePos); + } + else + { + startDragMove(mLastMousePos); + } } else { - // Clicked on node. Start move. - clearSelection(); - addSelection(hitNode); - startDragMove(mLastMousePos); + if (hitNode == NULL) + { + startDragRectangle(mLastMousePos); + mDragAddSelection = false; + } + else if (event.modifier & SI_PRIMARY_ALT && hitNode != NULL) + { + // Alt is down. Start a drag clone. + clearSelection(); + addSelection(hitNode); + startDragClone(mLastMousePos); + } + else if (event.modifier & SI_MULTISELECT) + { + addSelection(hitNode); + } + else + { + // Clicked on node. Start move. + clearSelection(); + addSelection(hitNode); + startDragMove(mLastMousePos); + } } } @@ -342,6 +467,35 @@ void GuiShaderEditor::onMouseUp(const GuiEvent& event) // get mouse pos with our view offset and scale. mLastMousePos = globalToLocalCoord(event.mousePoint) - mViewOffset; + if (mMouseDownMode == DragConnection) + { + U32 ret = finishConnection(mLastMousePos); + + if (ret == 1) // we set the input on mouse up, nodeB is the inputSocket, swap order. + { + NodeConnection* conn = new NodeConnection(); + conn->nodeA = mTempConnection->nodeB; + conn->nodeB = mTempConnection->nodeA; + conn->inSocket = mTempConnection->inSocket; + conn->outSocket = mTempConnection->outSocket; + + mCurrConnections.push_back(conn); + } + + if (ret == 2) // we set the output on mouse up, nodeB is the outputSocket + { + NodeConnection* conn = new NodeConnection(); + conn->nodeA = mTempConnection->nodeA; + conn->nodeB = mTempConnection->nodeB; + conn->inSocket = mTempConnection->inSocket; + conn->outSocket = mTempConnection->outSocket; + + mCurrConnections.push_back(conn); + } + + mTempConnection = NULL; + } + if (mMouseDownMode == DragSelecting) { if (!(event.modifier & SI_MULTISELECT) && !mDragAddSelection) @@ -536,6 +690,34 @@ void GuiShaderEditor::deleteSelection() { mTrash->addObject(node); + for (NodeInput* input : node->mInputNodes) + { + NodeConnection* conn; + if (hasConnection(input, conn)) + { + // selecting one node, push it to the front of the mcurrnodes stack so its rendered on top. + Vector< NodeConnection* >::iterator i = T3D::find(mCurrConnections.begin(), mCurrConnections.end(), conn); + if (i != mCurrConnections.end()) + { + mCurrConnections.erase(i); + } + } + } + + for (NodeOutput* output : node->mOutputNodes) + { + NodeConnection* conn; + if (hasConnection(output, conn)) + { + // selecting one node, push it to the front of the mcurrnodes stack so its rendered on top. + Vector< NodeConnection* >::iterator i = T3D::find(mCurrConnections.begin(), mCurrConnections.end(), conn); + if (i != mCurrConnections.end()) + { + mCurrConnections.erase(i); + } + } + } + Vector< GuiShaderNode* >::iterator i = T3D::find(mCurrNodes.begin(), mCurrNodes.end(), node); if (i != mCurrNodes.end()) mCurrNodes.erase(i); @@ -651,6 +833,147 @@ GuiShaderNode* GuiShaderEditor::findHitNode(const Point2I& pt) return nullptr; } +bool GuiShaderEditor::findHitSocket(const Point2I& pt) +{ + Point2I parentOffset = localToGlobalCoord(getPosition()) + mViewOffset; + Point2I offsetPoint = pt + localToGlobalCoord(getPosition()); + + for (GuiShaderNode* node : mCurrNodes) + { + for (NodeInput* inNode : node->mInputNodes) + { + Point2I offSet = node->localToGlobalCoord(inNode->pos) + parentOffset; + RectI box(offSet.x, offSet.y, mNodeSize, mNodeSize); + + S32 xt = offsetPoint.x - box.point.x; + S32 yt = offsetPoint.y - box.point.y; + if (xt >= 0 && yt >= 0 && xt < box.extent.x && yt < box.extent.y) + { + mTempConnection = new NodeConnection(); + mTempConnection->nodeA = node; + mTempConnection->inSocket = inNode; + setMouseMode(DragConnection); + return true; + } + } + + for (NodeOutput* outNode : node->mOutputNodes) + { + Point2I offSet = node->localToGlobalCoord(outNode->pos) + parentOffset; + RectI box(offSet.x, offSet.y, mNodeSize, mNodeSize); + + S32 xt = offsetPoint.x - box.point.x; + S32 yt = offsetPoint.y - box.point.y; + if (xt >= 0 && yt >= 0 && xt < box.extent.x && yt < box.extent.y) + { + mTempConnection = new NodeConnection(); + mTempConnection->nodeA = node; + mTempConnection->outSocket = outNode; + setMouseMode(DragConnection); + return true; + } + } + } + return false; +} + +U32 GuiShaderEditor::finishConnection(const Point2I& pt) +{ + Point2I parentOffset = localToGlobalCoord(getPosition()) + mViewOffset; + Point2I offsetPoint = pt + localToGlobalCoord(getPosition()); + + for (GuiShaderNode* node : mCurrNodes) + { + for (NodeInput* inNode : node->mInputNodes) + { + Point2I offSet = node->localToGlobalCoord(inNode->pos) + parentOffset; + RectI box(offSet.x, offSet.y, mNodeSize, mNodeSize); + + S32 xt = offsetPoint.x - box.point.x; + S32 yt = offsetPoint.y - box.point.y; + if (xt >= 0 && yt >= 0 && xt < box.extent.x && yt < box.extent.y) + { + if (mTempConnection->nodeA == node || mTempConnection->inSocket != NULL) + return false; + + NodeConnection* conn; + if(hasConnection(inNode, conn)) + { + // selecting one node, push it to the front of the mcurrnodes stack so its rendered on top. + Vector< NodeConnection* >::iterator i = T3D::find(mCurrConnections.begin(), mCurrConnections.end(), conn); + if (i != mCurrConnections.end()) + { + mCurrConnections.erase(i); + } + } + + mTempConnection->nodeB = node; + mTempConnection->inSocket = inNode; + return 1; + } + } + + for (NodeOutput* outNode : node->mOutputNodes) + { + Point2I offSet = node->localToGlobalCoord(outNode->pos) + parentOffset; + RectI box(offSet.x, offSet.y, mNodeSize, mNodeSize); + + S32 xt = offsetPoint.x - box.point.x; + S32 yt = offsetPoint.y - box.point.y; + if (xt >= 0 && yt >= 0 && xt < box.extent.x && yt < box.extent.y) + { + if (mTempConnection->nodeA == node || mTempConnection->outSocket != NULL) + return false; + + NodeConnection* conn; + if (hasConnection(mTempConnection->inSocket, conn)) + { + // selecting one node, push it to the front of the mcurrnodes stack so its rendered on top. + Vector< NodeConnection* >::iterator i = T3D::find(mCurrConnections.begin(), mCurrConnections.end(), conn); + if (i != mCurrConnections.end()) + { + mCurrConnections.erase(i); + } + } + + mTempConnection->nodeB = node; + mTempConnection->outSocket = outNode; + return 2; + } + } + } + return 0; +} + +bool GuiShaderEditor::hasConnection(NodeSocket* inSocket) +{ + for (NodeConnection* con : mCurrConnections) + { + if (con->inSocket == dynamic_cast(inSocket) || con->outSocket == dynamic_cast(inSocket)) + { + return true; + } + } + + return false; +} + +bool GuiShaderEditor::hasConnection(NodeSocket* inSocket, NodeConnection*& conn) +{ + for (NodeConnection* con : mCurrConnections) + { + if (con->inSocket == dynamic_cast(inSocket) || con->outSocket == dynamic_cast(inSocket)) + { + if (conn != nullptr) + conn = con; + + return true; + } + } + + return false; +} + void GuiShaderEditor::findNodesInRect(const RectI& rect, Vector& outResult) { canHitSelectedNodes(false); @@ -710,3 +1033,8 @@ void GuiShaderEditor::setMouseMode(mouseModes mode) } } +void GuiShaderEditor::addNode(GuiShaderNode* newNode) +{ + mCurrNodes.push_back(newNode); +} + diff --git a/Engine/source/gui/shaderEditor/guiShaderEditor.h b/Engine/source/gui/shaderEditor/guiShaderEditor.h index 011e3cb58..0305882a6 100644 --- a/Engine/source/gui/shaderEditor/guiShaderEditor.h +++ b/Engine/source/gui/shaderEditor/guiShaderEditor.h @@ -37,6 +37,17 @@ #include "gui/shaderEditor/nodes/shaderNode.h" #endif // !_SHADERNODE_H_ +struct NodeConnection +{ + // keep track of the nodes hit. + GuiShaderNode* nodeA = NULL; + GuiShaderNode* nodeB = NULL; + + // keep track of the sockets. + NodeInput* inSocket = NULL; + NodeOutput* outSocket = NULL; +}; + class GuiShaderEditor : public GuiControl { public: @@ -49,9 +60,11 @@ protected: // list typedef Vector ShaderNodeVector; + typedef Vector ShderNodeConnections; // all nodes in this graph. ShaderNodeVector mCurrNodes; - + ShderNodeConnections mCurrConnections; + NodeConnection* mTempConnection; // Undo SimGroup* mTrash; @@ -72,9 +85,15 @@ protected: ShaderNodeVector mSelectedNodes; void renderNodes(Point2I offset, const RectI& updateRect); + void renderConnections(Point2I offset, const RectI& updateRect); // functions for handling mouse events. GuiShaderNode* findHitNode(const Point2I& pt); + bool findHitSocket(const Point2I& pt); + U32 finishConnection(const Point2I& pt); + bool hasConnection(NodeSocket* inSocket); + bool hasConnection(NodeSocket* inSocket, NodeConnection*& conn); + void findNodesInRect(const RectI& rect, Vector& outResult); void getDragRect(RectI& box); @@ -82,6 +101,7 @@ protected: void startDragRectangle(const Point2I& startPoint); void startDragClone(const Point2I& startPoint); void setMouseMode(mouseModes mode); + void addNode(GuiShaderNode* newNode); public: GuiShaderEditor(); @@ -97,6 +117,7 @@ public: virtual void onRemove() override; virtual void onPreRender() override; + void drawThickLine(const Point2I& pt1, const Point2I& pt2, U32 thickness, ColorI col1, ColorI col2); virtual void onRender(Point2I offset, const RectI& updateRect) override; // interaction diff --git a/Engine/source/gui/shaderEditor/nodes/shaderNode.cpp b/Engine/source/gui/shaderEditor/nodes/shaderNode.cpp index ee5766a40..40cfceebf 100644 --- a/Engine/source/gui/shaderEditor/nodes/shaderNode.cpp +++ b/Engine/source/gui/shaderEditor/nodes/shaderNode.cpp @@ -96,7 +96,7 @@ void GuiShaderNode::onRemove() Parent::onRemove(); } -void GuiShaderNode::onRender(Point2I offset, const RectI& updateRect, const S32 nodeSize) +void GuiShaderNode::renderNode(Point2I offset, const RectI& updateRect, const S32 nodeSize) { if (!mProfile) return Parent::onRender(offset, updateRect); @@ -191,7 +191,7 @@ void GuiShaderNode::onRender(Point2I offset, const RectI& updateRect, const S32 drawer->drawText(mProfile->mFont, slotPos + offset, output->name); if (output->pos == Point2I::Zero || mPrevNodeSize != nodeSize) - output->pos = Point2I(getExtent().x - (nodeSize / 2), slotPos.y + ((mProfile->mFont->getFontSize() / 2) - (nodeSize / 2))); + output->pos = Point2I(getExtent().x - (nodeSize / 2) - 1 , slotPos.y + ((mProfile->mFont->getFontSize() / 2) - (nodeSize / 2))); slotPos.y += textPadY; } diff --git a/Engine/source/gui/shaderEditor/nodes/shaderNode.h b/Engine/source/gui/shaderEditor/nodes/shaderNode.h index 645125e05..cbfd4f701 100644 --- a/Engine/source/gui/shaderEditor/nodes/shaderNode.h +++ b/Engine/source/gui/shaderEditor/nodes/shaderNode.h @@ -58,31 +58,43 @@ enum class DataDimensions Mat4x4, }; -struct NodeInput +// parent class for sockets detection in shaderEditor. +struct NodeSocket { String name; DataDimensions dimensions; + NodeSocket() + :name(String::EmptyString), dimensions(DataDimensions::Dynamic) + {} + NodeSocket(String inName, DataDimensions inDim) + :name(inName), dimensions(inDim) + {} + +public: + virtual ~NodeSocket() {} +}; + +struct NodeInput : NodeSocket +{ Point2I pos = Point2I::Zero; NodeInput() - :name(String::EmptyString), dimensions(DataDimensions::Dynamic) + :NodeSocket() {} NodeInput(String inName , DataDimensions inDim) - :name(inName), dimensions(inDim) + :NodeSocket(inName , inDim) {} }; -struct NodeOutput +struct NodeOutput : NodeSocket { - String name; - DataDimensions dimensions; Point2I pos = Point2I::Zero; NodeOutput() - :name(String::EmptyString), dimensions(DataDimensions::Dynamic) + :NodeSocket() {} NodeOutput(String inName, DataDimensions inDim) - :name(inName), dimensions(inDim) + :NodeSocket(inName, inDim) {} }; @@ -107,8 +119,7 @@ public: virtual bool onAdd() override; virtual void onRemove() override; - void onRender(Point2I offset, const RectI& updateRect, const S32 nodeSize); - + void renderNode(Point2I offset, const RectI& updateRect, const S32 nodeSize); // Serialization functions void write(Stream& stream, U32 tabStop = 0, U32 flags = 0); void read(Stream& stream); From 808e2f4200dea7e3309dd73cdc168b97f3bb7c44 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Wed, 6 Mar 2024 13:26:39 +0000 Subject: [PATCH 36/53] Groundwork for other shaders Adds the ground work for geometry shaders Expands shaderData and gfxShader to allow for more shader types note: when building a GFXShader in source you have to call setShaderStageFile with the shaderStage and the filepath for that stage. Once we add compute shaders this will become more apparent as compute shaders are a stage of their own and do not require vertex and pixel files whereas other shaders sometimes do. --- Engine/source/gfx/gfxShader.cpp | 55 ++++-- Engine/source/gfx/gfxShader.h | 85 ++++----- .../gui/shaderEditor/guiShaderEditor.cpp | 6 +- .../source/gui/shaderEditor/guiShaderEditor.h | 2 +- Engine/source/materials/shaderData.cpp | 162 ++++++++++-------- Engine/source/materials/shaderData.h | 30 ++-- Engine/source/shaderGen/shaderGen.cpp | 41 +++-- 7 files changed, 220 insertions(+), 161 deletions(-) diff --git a/Engine/source/gfx/gfxShader.cpp b/Engine/source/gfx/gfxShader.cpp index 1fc35a995..62f6aff96 100644 --- a/Engine/source/gfx/gfxShader.cpp +++ b/Engine/source/gfx/gfxShader.cpp @@ -49,9 +49,9 @@ GFXShader::~GFXShader() } #ifndef TORQUE_OPENGL -bool GFXShader::init( const Torque::Path &vertFile, - const Torque::Path &pixFile, - F32 pixVersion, +bool GFXShader::init( const Torque::Path &vertFile, + const Torque::Path &pixFile, + F32 pixVersion, const Vector ¯os ) { Vector samplerNames; @@ -59,13 +59,18 @@ bool GFXShader::init( const Torque::Path &vertFile, } #endif -bool GFXShader::init( const Torque::Path &vertFile, - const Torque::Path &pixFile, - F32 pixVersion, +bool GFXShader::init( F32 pixVersion, const Vector ¯os, const Vector &samplerNames, GFXVertexFormat *instanceFormat) { + // early out. + if (mVertexFile.isEmpty() && mPixelFile.isEmpty() && mGeometryFile.isEmpty()) + { + Con::errorf("Shader files empty, please call setShaderStageFile from shaderData"); + return false; + } + // Take care of instancing if (instanceFormat) { @@ -74,8 +79,6 @@ bool GFXShader::init( const Torque::Path &vertFile, } // Store the inputs for use in reloading. - mVertexFile = vertFile; - mPixelFile = pixFile; mPixVersion = pixVersion; mMacros = macros; mSamplerNamesOrdered = samplerNames; @@ -91,8 +94,12 @@ bool GFXShader::init( const Torque::Path &vertFile, _updateDesc(); // Add file change notifications for reloads. - Torque::FS::AddChangeNotification( mVertexFile, this, &GFXShader::_onFileChanged ); - Torque::FS::AddChangeNotification( mPixelFile, this, &GFXShader::_onFileChanged ); + if(!mVertexFile.isEmpty()) + Torque::FS::AddChangeNotification( mVertexFile, this, &GFXShader::_onFileChanged ); + if(!mPixelFile.isEmpty()) + Torque::FS::AddChangeNotification( mPixelFile, this, &GFXShader::_onFileChanged ); + if(!mGeometryFile.isEmpty()) + Torque::FS::AddChangeNotification( mGeometryFile, this, &GFXShader::_onFileChanged); return true; } @@ -119,11 +126,11 @@ bool GFXShader::reload() void GFXShader::_updateDesc() { - mDescription = String::ToString( "Files: %s, %s Pix Version: %0.2f\nMacros: ", + mDescription = String::ToString( "Files: %s, %s Pix Version: %0.2f\nMacros: ", mVertexFile.getFullPath().c_str(), mPixelFile.getFullPath().c_str(), mPixVersion ); GFXShaderMacro::stringize( smGlobalMacros, &mDescription ); - GFXShaderMacro::stringize( mMacros, &mDescription ); + GFXShaderMacro::stringize( mMacros, &mDescription ); } void GFXShader::addGlobalMacro( const String &name, const String &value ) @@ -161,8 +168,26 @@ bool GFXShader::removeGlobalMacro( const String &name ) return false; } +void GFXShader::setShaderStageFile(const GFXShaderStage stage, const Torque::Path& filePath) +{ + switch (stage) + { + case GFXShaderStage::VERTEX_SHADER: + mVertexFile = filePath; + break; + case GFXShaderStage::PIXEL_SHADER: + mPixelFile = filePath; + break; + case GFXShaderStage::GEOMETRY_SHADER: + mGeometryFile = filePath; + break; + default: + break; + } +} + void GFXShader::_unlinkBuffer( GFXShaderConstBuffer *buf ) -{ +{ Vector::iterator iter = mActiveBuffers.begin(); for ( ; iter != mActiveBuffers.end(); iter++ ) { @@ -177,7 +202,7 @@ void GFXShader::_unlinkBuffer( GFXShaderConstBuffer *buf ) } -DefineEngineFunction( addGlobalShaderMacro, void, +DefineEngineFunction( addGlobalShaderMacro, void, ( const char *name, const char *value ), ( nullAsType() ), "Adds a global shader macro which will be merged with the script defined " "macros on every shader. The macro will replace the value of an existing " @@ -189,7 +214,7 @@ DefineEngineFunction( addGlobalShaderMacro, void, GFXShader::addGlobalMacro( name, value ); } -DefineEngineFunction( removeGlobalShaderMacro, void, ( const char *name ),, +DefineEngineFunction( removeGlobalShaderMacro, void, ( const char *name ),, "Removes an existing global macro by name.\n" "@see addGlobalShaderMacro\n" "@ingroup Rendering\n" ) diff --git a/Engine/source/gfx/gfxShader.h b/Engine/source/gfx/gfxShader.h index 4a880135d..abc45e9fe 100644 --- a/Engine/source/gfx/gfxShader.h +++ b/Engine/source/gfx/gfxShader.h @@ -76,7 +76,7 @@ enum GFXShaderStage }; /// Instances of this struct are returned GFXShaderConstBuffer -struct GFXShaderConstDesc +struct GFXShaderConstDesc { public: String name; @@ -92,7 +92,7 @@ public: /// This is an opaque handle used by GFXShaderConstBuffer clients to set individual shader constants. /// Derived classes can put whatever info they need into here, these handles are owned by the shader constant buffer /// (or shader). Client code should not free these. -class GFXShaderConstHandle +class GFXShaderConstHandle { public: @@ -101,8 +101,8 @@ public: /// Returns true if this constant is valid and can /// be set on the shader. - bool isValid() const { return mValid; } - + bool isValid() const { return mValid; } + /// Returns the name of the constant handle. virtual const String& getName() const = 0; @@ -110,7 +110,7 @@ public: virtual GFXShaderConstType getType() const = 0; virtual U32 getArraySize() const = 0; - + /// Returns -1 if this handle does not point to a Sampler. virtual S32 getSamplerRegister() const = 0; @@ -119,7 +119,7 @@ protected: /// The state of the constant which is /// set from the derived class. bool mValid; - + }; @@ -143,7 +143,7 @@ protected: /// @see wasLost bool mWasLost; - GFXShaderConstBuffer() + GFXShaderConstBuffer() : mWasLost( true ), mInstPtr( NULL ) { @@ -155,16 +155,16 @@ public: virtual GFXShader* getShader() = 0; /// The content of the buffer is in the lost state when - /// first created or when the shader is reloaded. When + /// first created or when the shader is reloaded. When /// the content is lost you must refill the buffer /// with all the constants used by your shader. /// - /// Use this property to avoid setting constants which do + /// Use this property to avoid setting constants which do /// not changefrom one frame to the next. /// bool wasLost() const { return mWasLost; } - /// An inline helper which ensures the handle is valid + /// An inline helper which ensures the handle is valid /// before the virtual set method is called. /// /// You should prefer using this method unless your sure the @@ -183,7 +183,7 @@ public: /// /// Perfer using setSafe unless you can check the handle /// validity yourself and skip a significat amount of work. - /// + /// /// @see GFXShaderConstHandle::isValid() /// virtual void set(GFXShaderConstHandle* handle, const F32 f) = 0; @@ -204,19 +204,19 @@ public: virtual void set(GFXShaderConstHandle* handle, const AlignedArray& fv) = 0; virtual void set(GFXShaderConstHandle* handle, const AlignedArray& fv) = 0; virtual void set(GFXShaderConstHandle* handle, const AlignedArray& fv) = 0; - - /// Set a variable sized matrix shader constant. - virtual void set( GFXShaderConstHandle* handle, - const MatrixF& mat, + + /// Set a variable sized matrix shader constant. + virtual void set( GFXShaderConstHandle* handle, + const MatrixF& mat, const GFXShaderConstType matrixType = GFXSCT_Float4x4 ) = 0; - + /// Set a variable sized matrix shader constant from - /// an array of matricies. - virtual void set( GFXShaderConstHandle* handle, - const MatrixF* mat, - const U32 arraySize, + /// an array of matricies. + virtual void set( GFXShaderConstHandle* handle, + const MatrixF* mat, + const U32 arraySize, const GFXShaderConstType matrixType = GFXSCT_Float4x4 ) = 0; - + // TODO: Make this protected and put a real API around it. U8 *mInstPtr; }; @@ -232,8 +232,8 @@ class GFXShader : public StrongRefBase, public GFXResource friend class GFXShaderConstBuffer; protected: - - /// These are system wide shader macros which are + + /// These are system wide shader macros which are /// merged with shader specific macros at creation. static Vector smGlobalMacros; @@ -244,19 +244,22 @@ protected: static bool smLogWarnings; /// The vertex shader file. - Torque::Path mVertexFile; + Torque::Path mVertexFile; /// The pixel shader file. - Torque::Path mPixelFile; + Torque::Path mPixelFile; - /// The macros to be passed to the shader. + // the geometry shader file. + Torque::Path mGeometryFile; + + /// The macros to be passed to the shader. Vector mMacros; /// Ordered SamplerNames /// We need to store a list of sampler for allow OpenGL to /// assign correct location for each sampler. /// GLSL 150 not allow explicit uniform location. - /// Only used on OpenGL + /// Only used on OpenGL Vector mSamplerNamesOrdered; /// The pixel version this is compiled for. @@ -271,7 +274,7 @@ protected: Signal mReloadSignal; /// Vector of buffers that reference this shader. - /// It is the responsibility of the derived shader class to populate this + /// It is the responsibility of the derived shader class to populate this /// vector and to notify them when this shader is reloaded. Classes /// derived from GFXShaderConstBuffer should call _unlinkBuffer from /// their destructor. @@ -282,7 +285,7 @@ protected: /// A protected constructor so it cannot be instantiated. GFXShader(); -public: +public: /// Adds a global shader macro which will be merged with /// the script defined macros on every shader reload. @@ -303,9 +306,9 @@ public: /// Toggle logging for shader errors. static void setLogging( bool logErrors, - bool logWarning ) + bool logWarning ) { - smLogErrors = logErrors; + smLogErrors = logErrors; smLogWarnings = logWarning; } @@ -315,16 +318,14 @@ public: /// /// Deprecated. Remove on T3D 4.0 #ifndef TORQUE_OPENGL - bool init( const Torque::Path &vertFile, - const Torque::Path &pixFile, - F32 pixVersion, + bool init( const Torque::Path &vertFile, + const Torque::Path &pixFile, + F32 pixVersion, const Vector ¯os ); #endif /// - bool init( const Torque::Path &vertFile, - const Torque::Path &pixFile, - F32 pixVersion, + bool init( F32 pixVersion, const Vector ¯os, const Vector &samplerNames, GFXVertexFormat *instanceFormat = NULL ); @@ -335,23 +336,23 @@ public: Signal getReloadSignal() { return mReloadSignal; } /// Allocate a constant buffer - virtual GFXShaderConstBufferRef allocConstBuffer() = 0; + virtual GFXShaderConstBufferRef allocConstBuffer() = 0; /// Returns our list of shader constants, the material can get this and just set the constants it knows about virtual const Vector& getShaderConstDesc() const = 0; /// Returns a shader constant handle for the name constant. /// - /// Since shaders can reload and later have handles that didn't + /// Since shaders can reload and later have handles that didn't /// exist originally this will return a handle in an invalid state /// if the constant doesn't exist at this time. - virtual GFXShaderConstHandle* getShaderConstHandle( const String& name ) = 0; + virtual GFXShaderConstHandle* getShaderConstHandle( const String& name ) = 0; /// Returns a shader constant handle for the name constant, if the variable doesn't exist NULL is returned. virtual GFXShaderConstHandle* findShaderConstHandle( const String& name ) = 0; /// Returns the alignment value for constType - virtual U32 getAlignmentValue(const GFXShaderConstType constType) const = 0; + virtual U32 getAlignmentValue(const GFXShaderConstType constType) const = 0; /// Returns the required vertex format for this shader. /// Returns the pixel shader version. @@ -364,6 +365,8 @@ public: /// the shader disassembly. virtual bool getDisassembly( String &outStr ) const { return false; } + void setShaderStageFile(const GFXShaderStage stage, const Torque::Path& filePath); + /// Returns the vertex shader file path. const String& getVertexShaderFile() const { return mVertexFile.getFullPath(); } diff --git a/Engine/source/gui/shaderEditor/guiShaderEditor.cpp b/Engine/source/gui/shaderEditor/guiShaderEditor.cpp index 03cd40ec4..334ffe720 100644 --- a/Engine/source/gui/shaderEditor/guiShaderEditor.cpp +++ b/Engine/source/gui/shaderEditor/guiShaderEditor.cpp @@ -134,7 +134,7 @@ void GuiShaderEditor::onPreRender() setUpdate(); } -void GuiShaderEditor::drawThickLine(const Point2I& pt1, const Point2I& pt2, U32 thickness = 2, ColorI col1 = ColorI(255, 255, 255), ColorI col2 = ColorI(255, 255, 255)) +void GuiShaderEditor::drawThickLine(const Point2I& pt1, const Point2I& pt2, U32 thickness, ColorI col1, ColorI col2) { Point2F dir = Point2F(pt2.x - pt1.x, pt2.y - pt1.y); if (dir == Point2F::Zero) @@ -292,7 +292,7 @@ void GuiShaderEditor::renderConnections(Point2I offset, const RectI& updateRect) start += Point2I(mNodeSize / 2, mNodeSize / 2); end += Point2I(mNodeSize / 2, mNodeSize / 2); - drawThickLine(start, end); + drawThickLine(start, end, mNodeSize/3); } // Restore the clip rect to what it was at the start @@ -328,7 +328,7 @@ void GuiShaderEditor::onRender(Point2I offset, const RectI& updateRect) RectI sockActive(start, Point2I(mNodeSize, mNodeSize)); start += Point2I(mNodeSize / 2, mNodeSize / 2); - drawThickLine(start, mLastMousePos + offset); + drawThickLine(start, mLastMousePos + offset, mNodeSize/3); // draw socket overlay over the top of the line. sockActive.inset(1, 1); diff --git a/Engine/source/gui/shaderEditor/guiShaderEditor.h b/Engine/source/gui/shaderEditor/guiShaderEditor.h index 0305882a6..0a8f6ccff 100644 --- a/Engine/source/gui/shaderEditor/guiShaderEditor.h +++ b/Engine/source/gui/shaderEditor/guiShaderEditor.h @@ -117,7 +117,7 @@ public: virtual void onRemove() override; virtual void onPreRender() override; - void drawThickLine(const Point2I& pt1, const Point2I& pt2, U32 thickness, ColorI col1, ColorI col2); + void drawThickLine(const Point2I& pt1, const Point2I& pt2, U32 thickness = 2, ColorI col1 = ColorI(255, 255, 255), ColorI col2 = ColorI(255, 255, 255)); virtual void onRender(Point2I offset, const RectI& updateRect) override; // interaction diff --git a/Engine/source/materials/shaderData.cpp b/Engine/source/materials/shaderData.cpp index 8d8e8d103..34eab775d 100644 --- a/Engine/source/materials/shaderData.cpp +++ b/Engine/source/materials/shaderData.cpp @@ -48,10 +48,12 @@ ConsoleDocClass( ShaderData, "// Used for the procedural clould system\n" "singleton ShaderData( CloudLayerShader )\n" "{\n" - " DXVertexShaderFile = $Core::CommonShaderPath @ \"/cloudLayerV.hlsl\";\n" - " DXPixelShaderFile = $Core::CommonShaderPath @ \"/cloudLayerP.hlsl\";\n" - " OGLVertexShaderFile = $Core::CommonShaderPath @ \"/gl/cloudLayerV.glsl\";\n" - " OGLPixelShaderFile = $Core::CommonShaderPath @ \"/gl/cloudLayerP.glsl\";\n" + " DXVertexShaderFile = $Core::CommonShaderPath @ \"/cloudLayerV.hlsl\";\n" + " DXPixelShaderFile = $Core::CommonShaderPath @ \"/cloudLayerP.hlsl\";\n" + " DXGeometryShaderFile = $Core::CommonShaderPath @ \"/cloudLayerG.hlsl\";\n" + " OGLVertexShaderFile = $Core::CommonShaderPath @ \"/gl/cloudLayerV.glsl\";\n" + " OGLPixelShaderFile = $Core::CommonShaderPath @ \"/gl/cloudLayerP.glsl\";\n" + " OGLGeometryShaderFile = $Core::CommonShaderPath @ \"/gl/cloudLayerG.glsl\";\n" " pixVersion = 2.0;\n" "};\n" "@endtsexample\n\n" @@ -67,70 +69,87 @@ ShaderData::ShaderData() for( int i = 0; i < NumTextures; ++i) mRTParams[i] = false; + + mDXVertexShaderName = StringTable->EmptyString(); + mDXPixelShaderName = StringTable->EmptyString(); + mDXGeometryShaderName = StringTable->EmptyString(); + + mOGLVertexShaderName = StringTable->EmptyString(); + mOGLPixelShaderName = StringTable->EmptyString(); + mOGLGeometryShaderName = StringTable->EmptyString(); } void ShaderData::initPersistFields() { docsURL; - addField("DXVertexShaderFile", TypeStringFilename, Offset(mDXVertexShaderName, ShaderData), - "@brief %Path to the DirectX vertex shader file to use for this ShaderData.\n\n" - "It must contain only one program and no pixel shader, just the vertex shader." - "It can be either an HLSL or assembly level shader. HLSL's must have a " - "filename extension of .hlsl, otherwise its assumed to be an assembly file."); + addField("DXVertexShaderFile", TypeStringFilename, Offset(mDXVertexShaderName, ShaderData), + "@brief %Path to the DirectX vertex shader file to use for this ShaderData.\n\n" + "It must contain only one program and no pixel shader, just the vertex shader." + "It can be either an HLSL or assembly level shader. HLSL's must have a " + "filename extension of .hlsl, otherwise its assumed to be an assembly file."); - addField("DXPixelShaderFile", TypeStringFilename, Offset(mDXPixelShaderName, ShaderData), - "@brief %Path to the DirectX pixel shader file to use for this ShaderData.\n\n" - "It must contain only one program and no vertex shader, just the pixel " - "shader. It can be either an HLSL or assembly level shader. HLSL's " - "must have a filename extension of .hlsl, otherwise its assumed to be an assembly file."); + addField("DXPixelShaderFile", TypeStringFilename, Offset(mDXPixelShaderName, ShaderData), + "@brief %Path to the DirectX pixel shader file to use for this ShaderData.\n\n" + "It must contain only one program and no vertex shader, just the pixel " + "shader. It can be either an HLSL or assembly level shader. HLSL's " + "must have a filename extension of .hlsl, otherwise its assumed to be an assembly file."); - addField("OGLVertexShaderFile", TypeStringFilename, Offset(mOGLVertexShaderName, ShaderData), - "@brief %Path to an OpenGL vertex shader file to use for this ShaderData.\n\n" - "It must contain only one program and no pixel shader, just the vertex shader."); + addField("DXGeometryShaderFile", TypeStringFilename, Offset(mDXGeometryShaderName, ShaderData), + "@brief %Path to the DirectX geometry shader file to use for this ShaderData.\n\n" + "It can be either an HLSL or assembly level shader. HLSL's must have a " + "filename extension of .hlsl, otherwise its assumed to be an assembly file."); - addField("OGLPixelShaderFile", TypeStringFilename, Offset(mOGLPixelShaderName, ShaderData), - "@brief %Path to an OpenGL pixel shader file to use for this ShaderData.\n\n" - "It must contain only one program and no vertex shader, just the pixel " - "shader."); + addField("OGLVertexShaderFile", TypeStringFilename, Offset(mOGLVertexShaderName, ShaderData), + "@brief %Path to an OpenGL vertex shader file to use for this ShaderData.\n\n" + "It must contain only one program and no pixel shader, just the vertex shader."); - addField("useDevicePixVersion", TypeBool, Offset(mUseDevicePixVersion, ShaderData), - "@brief If true, the maximum pixel shader version offered by the graphics card will be used.\n\n" - "Otherwise, the script-defined pixel shader version will be used.\n\n"); + addField("OGLPixelShaderFile", TypeStringFilename, Offset(mOGLPixelShaderName, ShaderData), + "@brief %Path to an OpenGL pixel shader file to use for this ShaderData.\n\n" + "It must contain only one program and no vertex shader, just the pixel " + "shader."); - addField("pixVersion", TypeF32, Offset(mPixVersion, ShaderData), - "@brief Indicates target level the shader should be compiled.\n\n" - "Valid numbers at the time of this writing are 1.1, 1.4, 2.0, and 3.0. " - "The shader will not run properly if the hardware does not support the " - "level of shader compiled."); - - addField("defines", TypeRealString, Offset(mDefines, ShaderData), - "@brief String of case-sensitive defines passed to the shader compiler.\n\n" + addField("OGLGeometryShaderFile", TypeStringFilename, Offset(mOGLGeometryShaderName, ShaderData), + "@brief %Path to the OpenGL Geometry shader file to use for this ShaderData.\n\n"); + + addField("useDevicePixVersion", TypeBool, Offset(mUseDevicePixVersion, ShaderData), + "@brief If true, the maximum pixel shader version offered by the graphics card will be used.\n\n" + "Otherwise, the script-defined pixel shader version will be used.\n\n"); + + addField("pixVersion", TypeF32, Offset(mPixVersion, ShaderData), + "@brief Indicates target level the shader should be compiled.\n\n" + "Valid numbers at the time of this writing are 1.1, 1.4, 2.0, and 3.0. " + "The shader will not run properly if the hardware does not support the " + "level of shader compiled."); + + addField("defines", TypeRealString, Offset(mDefines, ShaderData), + "@brief String of case-sensitive defines passed to the shader compiler.\n\n" "The string should be delimited by a semicolon, tab, or newline character." - + "@tsexample\n" - "singleton ShaderData( FlashShader )\n" - "{\n" - "DXVertexShaderFile = $shaderGen::cachePath @ \"/postFx/flashV.hlsl\";\n" - "DXPixelShaderFile = $shaderGen::cachePath @ \"/postFx/flashP.hlsl\";\n\n" - " //Define setting the color of WHITE_COLOR.\n" - "defines = \"WHITE_COLOR=float4(1.0,1.0,1.0,0.0)\";\n\n" - "pixVersion = 2.0\n" - "}\n" + "singleton ShaderData( FlashShader )\n" + "{\n" + "DXVertexShaderFile = $shaderGen::cachePath @ \"/postFx/flashV.hlsl\";\n" + "DXPixelShaderFile = $shaderGen::cachePath @ \"/postFx/flashP.hlsl\";\n\n" + "DXGeometryShaderFile = $shaderGen::cachePath @ \"/postFx/flashG.hlsl\";\n\n" + " //Define setting the color of WHITE_COLOR.\n" + "defines = \"WHITE_COLOR=float4(1.0,1.0,1.0,0.0)\";\n\n" + "pixVersion = 2.0\n" + "}\n" "@endtsexample\n\n" - ); + ); - addField("samplerNames", TypeRealString, Offset(mSamplerNames, ShaderData), NumTextures, + addField("samplerNames", TypeRealString, Offset(mSamplerNames, ShaderData), NumTextures, "@brief Indicates names of samplers present in shader. Order is important.\n\n" - "Order of sampler names are used to assert correct sampler register/location" + "Order of sampler names are used to assert correct sampler register/location" "Other objects (GFXStateBlockData, PostEffect...) use index number to link samplers." - ); + ); - addField("rtParams", TypeBool, Offset(mRTParams, ShaderData), NumTextures, ""); + addField("rtParams", TypeBool, Offset(mRTParams, ShaderData), NumTextures, ""); Parent::initPersistFields(); // Make sure we get activation signals. - LightManager::smActivateSignal.notify( &ShaderData::_onLMActivate ); + LightManager::smActivateSignal.notify(&ShaderData::_onLMActivate); } bool ShaderData::onAdd() @@ -147,8 +166,8 @@ bool ShaderData::onAdd() for(int i = 0; i < NumTextures; ++i) { - if( mSamplerNames[i].isNotEmpty() && !mSamplerNames[i].startsWith("$") ) - mSamplerNames[i].insert(0, "$"); + if( mSamplerNames[i].isNotEmpty() && !mSamplerNames[i].startsWith("$") ) + mSamplerNames[i].insert(0, "$"); } return true; @@ -164,12 +183,12 @@ void ShaderData::onRemove() const Vector& ShaderData::_getMacros() { - // If they have already been processed then + // If they have already been processed then // return the cached result. if ( mShaderMacros.size() != 0 || mDefines.isEmpty() ) return mShaderMacros; - mShaderMacros.clear(); + mShaderMacros.clear(); GFXShaderMacro macro; const U32 defineCount = StringUnit::getUnitCount( mDefines, ";\n\t" ); for ( U32 i=0; i < defineCount; i++ ) @@ -195,7 +214,7 @@ GFXShader* ShaderData::getShader( const Vector ¯os ) // Convert the final macro list to a string. String cacheKey; - GFXShaderMacro::stringize( macros, &cacheKey ); + GFXShaderMacro::stringize( macros, &cacheKey ); // Lookup the shader for this instance. ShaderCache::Iterator iter = mShaders.find( cacheKey ); @@ -237,9 +256,13 @@ GFXShader* ShaderData::_createShader( const Vector ¯os ) { case Direct3D11: { - success = shader->init( mDXVertexShaderName, - mDXPixelShaderName, - pixver, + if (mDXVertexShaderName != String::EmptyString) + shader->setShaderStageFile(GFXShaderStage::VERTEX_SHADER, mDXVertexShaderName); + if (mDXPixelShaderName != String::EmptyString) + shader->setShaderStageFile(GFXShaderStage::PIXEL_SHADER, mDXPixelShaderName); + if (mDXGeometryShaderName != String::EmptyString) + shader->setShaderStageFile(GFXShaderStage::GEOMETRY_SHADER, mDXGeometryShaderName); + success = shader->init( pixver, macros, samplers); break; @@ -247,14 +270,19 @@ GFXShader* ShaderData::_createShader( const Vector ¯os ) case OpenGL: { - success = shader->init( mOGLVertexShaderName, - mOGLPixelShaderName, - pixver, + if(mOGLVertexShaderName != String::EmptyString) + shader->setShaderStageFile(GFXShaderStage::VERTEX_SHADER, mOGLVertexShaderName); + if (mOGLPixelShaderName != String::EmptyString) + shader->setShaderStageFile(GFXShaderStage::PIXEL_SHADER, mOGLPixelShaderName); + if (mOGLGeometryShaderName != String::EmptyString) + shader->setShaderStageFile(GFXShaderStage::GEOMETRY_SHADER, mOGLGeometryShaderName); + + success = shader->init( pixver, macros, samplers); break; } - + default: // Other device types are assumed to not support shaders. success = false; @@ -268,7 +296,7 @@ GFXShader* ShaderData::_createShader( const Vector ¯os ) { if(descs[i].constType != GFXSCT_Sampler && descs[i].constType != GFXSCT_SamplerCube) continue; - + GFXShaderConstHandle *handle = shader->findShaderConstHandle(descs[i].name); if(!handle || !handle->isValid()) continue; @@ -321,7 +349,7 @@ void ShaderData::_onLMActivate( const char *lm, bool activate ) bool ShaderData::hasSamplerDef(const String &_samplerName, int &pos) const { - String samplerName = _samplerName.startsWith("$") ? _samplerName : "$"+_samplerName; + String samplerName = _samplerName.startsWith("$") ? _samplerName : "$"+_samplerName; for(int i = 0; i < NumTextures; ++i) { if( mSamplerNames[i].equal(samplerName, String::NoCase ) ) @@ -342,9 +370,9 @@ bool ShaderData::_checkDefinition(GFXShader *shader) samplers.reserve(NumTextures); bool rtParams[NumTextures]; for(int i = 0; i < NumTextures; ++i) - rtParams[i] = false; + rtParams[i] = false; - const Vector &shaderConstDesc = shader->getShaderConstDesc(); + const Vector &shaderConstDesc = shader->getShaderConstDesc(); for(int i = 0; i < shaderConstDesc.size(); ++i) { @@ -352,7 +380,7 @@ bool ShaderData::_checkDefinition(GFXShader *shader) if(desc.constType == GFXSCT_Sampler) { samplers.push_back(desc.name ); - } + } } for(int i = 0; i < samplers.size(); ++i) @@ -361,14 +389,14 @@ bool ShaderData::_checkDefinition(GFXShader *shader) bool find = hasSamplerDef(samplers[i], pos); if(find && pos >= 0 && mRTParams[pos]) - { + { if( !shader->findShaderConstHandle( String::ToString("$rtParams%d", pos)) ) { String errStr = String::ToString("ShaderData(%s) sampler[%d] used but rtParams%d not used in shader compilation. Possible error", shader->getPixelShaderFile().c_str(), pos, pos); Con::errorf(errStr); error = true; } - } + } if(!find) { @@ -377,7 +405,7 @@ bool ShaderData::_checkDefinition(GFXShader *shader) GFXAssertFatal(0, errStr); error = true; } - } + } return !error; } diff --git a/Engine/source/materials/shaderData.h b/Engine/source/materials/shaderData.h index 4bef16679..e07f513cf 100644 --- a/Engine/source/materials/shaderData.h +++ b/Engine/source/materials/shaderData.h @@ -47,7 +47,7 @@ protected: /// static Vector smAllShaderData; - typedef HashTable ShaderCache; + typedef HashTable ShaderCache; ShaderCache mShaders; @@ -56,12 +56,12 @@ protected: F32 mPixVersion; StringTableEntry mDXVertexShaderName; - StringTableEntry mDXPixelShaderName; + StringTableEntry mDXGeometryShaderName; StringTableEntry mOGLVertexShaderName; - StringTableEntry mOGLPixelShaderName; + StringTableEntry mOGLGeometryShaderName; /// A semicolon, tab, or newline delimited string of case /// sensitive defines that are passed to the shader compiler. @@ -80,40 +80,40 @@ protected: /// them if the content has changed. const Vector& _getMacros(); - /// Helper for converting an array of macros + /// Helper for converting an array of macros /// into a formatted string. - void _stringizeMacros( const Vector ¯os, - String *outString ); + void _stringizeMacros(const Vector& macros, + String* outString); /// Creates a new shader returning NULL on error. - GFXShader* _createShader( const Vector ¯os ); + GFXShader* _createShader(const Vector& macros); /// @see LightManager::smActivateSignal - static void _onLMActivate( const char *lm, bool activate ); + static void _onLMActivate(const char* lm, bool activate); enum { NumTextures = 16 }; - String mSamplerNames[NumTextures]; + String mSamplerNames[NumTextures]; bool mRTParams[NumTextures]; - bool _checkDefinition(GFXShader *shader); + bool _checkDefinition(GFXShader* shader); public: - void setSamplerName(const String &name, int idx) { mSamplerNames[idx] = name; } + void setSamplerName(const String& name, int idx) { mSamplerNames[idx] = name; } String getSamplerName(int idx) const { return mSamplerNames[idx]; } - bool hasSamplerDef(const String &samplerName, int &pos) const; + bool hasSamplerDef(const String& samplerName, int& pos) const; bool hasRTParamsDef(const int pos) const { return mRTParams[pos]; } ShaderData(); - /// Returns an initialized shader instance or NULL + /// Returns an initialized shader instance or NULL /// if the shader failed to be created. - GFXShader* getShader( const Vector ¯os = Vector() ); + GFXShader* getShader(const Vector& macros = Vector()); /// Forces a reinitialization of all the instanced shaders. void reloadShaders(); @@ -124,7 +124,7 @@ public: /// Returns the required pixel shader version for this shader. F32 getPixVersion() const { return mPixVersion; } - + // SimObject virtual bool onAdd(); virtual void onRemove(); diff --git a/Engine/source/shaderGen/shaderGen.cpp b/Engine/source/shaderGen/shaderGen.cpp index 9ae35d474..54b297772 100644 --- a/Engine/source/shaderGen/shaderGen.cpp +++ b/Engine/source/shaderGen/shaderGen.cpp @@ -47,7 +47,7 @@ MODULE_BEGIN( ShaderGen ) { ManagedSingleton< ShaderGen >::createSingleton(); } - + MODULE_SHUTDOWN { ManagedSingleton< ShaderGen >::deleteSingleton(); @@ -94,7 +94,7 @@ bool ShaderGen::_handleGFXEvent(GFXDevice::GFXDeviceEventType event) } void ShaderGen::initShaderGen() -{ +{ if (mInit) return; @@ -125,7 +125,7 @@ void ShaderGen::initShaderGen() { // If we didn't get a path then we're gonna cache the shaders to // a virtualized memory file system. - mMemFS = new Torque::Mem::MemFileSystem( "shadergen:/" ); + mMemFS = new Torque::Mem::MemFileSystem( "shadergen:/" ); Torque::FS::Mount( "shadergen", mMemFS ); } else @@ -136,8 +136,8 @@ void ShaderGen::initShaderGen() } void ShaderGen::generateShader( const MaterialFeatureData &featureData, - char *vertFile, - char *pixFile, + char *vertFile, + char *pixFile, F32 *pixVersion, const GFXVertexFormat *vertexFormat, const char* cacheName, @@ -155,23 +155,23 @@ void ShaderGen::generateShader( const MaterialFeatureData &featureData, char pixShaderName[256]; // Note: We use a postfix of _V/_P here so that it sorts the matching - // vert and pixel shaders together when listed alphabetically. + // vert and pixel shaders together when listed alphabetically. dSprintf( vertShaderName, sizeof(vertShaderName), "shadergen:/%s_V.%s", cacheName, mFileEnding.c_str() ); dSprintf( pixShaderName, sizeof(pixShaderName), "shadergen:/%s_P.%s", cacheName, mFileEnding.c_str() ); - + dStrcpy( vertFile, vertShaderName, 256 ); dStrcpy( pixFile, pixShaderName, 256 ); - + // this needs to change - need to optimize down to ps v.1.1 *pixVersion = GFX->getPixelShaderVersion(); - + if ( !Con::getBoolVariable( "ShaderGen::GenNewShaders", true ) ) { // If we are not regenerating the shader we will return here. // But we must fill in the shader macros first! _processVertFeatures( macros, true ); - _processPixFeatures( macros, true ); + _processPixFeatures( macros, true ); return; } @@ -190,7 +190,7 @@ void ShaderGen::generateShader( const MaterialFeatureData &featureData, _processVertFeatures(macros); _printVertShader( *s ); delete s; - + ((ShaderConnector*)mComponents[C_CONNECTOR])->reset(); LangElement::deleteElements(); @@ -202,7 +202,7 @@ void ShaderGen::generateShader( const MaterialFeatureData &featureData, AssertFatal(false, "Failed to open Shader Stream" ); delete s; return; - } + } mOutput = new MultiLine; _processPixFeatures(macros); @@ -284,7 +284,7 @@ void ShaderGen::_processVertFeatures( Vector ¯os, bool macro mOutput->addStatement( feature->getOutput() ); feature->reset(); - mOutput->addStatement( new GenOp( " \r\n" ) ); + mOutput->addStatement( new GenOp( " \r\n" ) ); } } @@ -327,7 +327,7 @@ void ShaderGen::_processPixFeatures( Vector ¯os, bool macros mOutput->addStatement( new GenOp( " \r\n" ) ); } } - + ShaderConnector *connect = dynamic_cast( mComponents[C_CONNECTOR] ); connect->sortVars(); } @@ -335,7 +335,7 @@ void ShaderGen::_processPixFeatures( Vector ¯os, bool macros void ShaderGen::_printFeatureList(Stream &stream) { mPrinter->printLine(stream, "// Features:"); - + const FeatureSet &features = mFeatureData.features; for( U32 i=0; i < features.getCount(); i++ ) @@ -376,7 +376,7 @@ void ShaderGen::_printDependencies(Stream &stream) for( U32 j=0; j < dependencies.size(); j++ ) { - if ( j != i && + if ( j != i && *dependencies[i] == *dependencies[j] ) { dup = true; @@ -386,7 +386,7 @@ void ShaderGen::_printDependencies(Stream &stream) if ( dup ) dependencies.erase( i ); - else + else i++; } @@ -493,7 +493,10 @@ GFXShader* ShaderGen::getShader( const MaterialFeatureData &featureData, const G generateShader( featureData, vertFile, pixFile, &pixVersion, vertexFormat, cacheKey, shaderMacros ); GFXShader *shader = GFX->createShader(); - if (!shader->init(vertFile, pixFile, pixVersion, shaderMacros, samplers, &mInstancingFormat)) + shader->setShaderStageFile(GFXShaderStage::VERTEX_SHADER, vertFile); + shader->setShaderStageFile(GFXShaderStage::PIXEL_SHADER, pixFile); + + if (!shader->init(pixVersion, shaderMacros, samplers, &mInstancingFormat)) { delete shader; return NULL; @@ -508,5 +511,5 @@ void ShaderGen::flushProceduralShaders() { // The shaders are reference counted, so we // just need to clear the map. - mProcShaders.clear(); + mProcShaders.clear(); } From 4a6fbd5811ca096728a9a72d365549185159521b Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Wed, 6 Mar 2024 13:51:50 +0000 Subject: [PATCH 37/53] DX and GL Geometry shaders added Added the dx and gl geometry shader compile codes. --- Engine/source/gfx/D3D11/gfxD3D11Device.cpp | 145 ++++++------ Engine/source/gfx/D3D11/gfxD3D11Device.h | 31 +-- Engine/source/gfx/D3D11/gfxD3D11Shader.cpp | 79 ++++--- Engine/source/gfx/D3D11/gfxD3D11Shader.h | 13 +- Engine/source/gfx/gl/gfxGLShader.cpp | 243 ++++++++++++--------- Engine/source/gfx/gl/gfxGLShader.h | 40 ++-- 6 files changed, 312 insertions(+), 239 deletions(-) diff --git a/Engine/source/gfx/D3D11/gfxD3D11Device.cpp b/Engine/source/gfx/D3D11/gfxD3D11Device.cpp index 7c83d098b..98497534a 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Device.cpp +++ b/Engine/source/gfx/D3D11/gfxD3D11Device.cpp @@ -105,6 +105,7 @@ GFXD3D11Device::GFXD3D11Device(U32 index) mLastVertShader = NULL; mLastPixShader = NULL; + mLastGeoShader = NULL; mCanCurrentlyRender = false; mTextureManager = NULL; @@ -202,7 +203,7 @@ GFXFormat GFXD3D11Device::selectSupportedFormat(GFXTextureProfile *profile, cons features |= D3D11_FORMAT_SUPPORT_BLENDABLE; if(mustfilter) features |= D3D11_FORMAT_SUPPORT_SHADER_SAMPLE; - + for(U32 i = 0; i < formats.size(); i++) { if(GFXD3D11TextureFormat[formats[i]] == DXGI_FORMAT_UNKNOWN) @@ -213,7 +214,7 @@ GFXFormat GFXD3D11Device::selectSupportedFormat(GFXTextureProfile *profile, cons if(supportFlag & features) return formats[i]; } - + return GFXFormatR8G8B8A8; } @@ -261,7 +262,7 @@ void GFXD3D11Device::enumerateAdapters(Vector &adapterList) CreateDXGIFactory1(__uuidof(IDXGIFactory1), reinterpret_cast(&DXGIFactory)); - for(U32 adapterIndex = 0; DXGIFactory->EnumAdapters1(adapterIndex, &EnumAdapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) + for(U32 adapterIndex = 0; DXGIFactory->EnumAdapters1(adapterIndex, &EnumAdapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) { GFXAdapter *toAdd = new GFXAdapter; toAdd->mType = Direct3D11; @@ -286,7 +287,7 @@ void GFXD3D11Device::enumerateAdapters(Vector &adapterList) dStrncpy(toAdd->mName, Description.c_str(), GFXAdapter::MaxAdapterNameLen); dStrncat(toAdd->mName, " (D3D11)", sizeof(toAdd->mName) - strlen(toAdd->mName) - 1); - IDXGIOutput* pOutput = NULL; + IDXGIOutput* pOutput = NULL; HRESULT hr; hr = EnumAdapter->EnumOutputs(adapterIndex, &pOutput); @@ -310,7 +311,7 @@ void GFXD3D11Device::enumerateAdapters(Vector &adapterList) if(FAILED(hr)) AssertFatal(false, "GFXD3D11Device::enumerateAdapters -> GetDisplayModeList call failure"); - displayModes = new DXGI_MODE_DESC[numModes]; + displayModes = new DXGI_MODE_DESC[numModes]; // Get the list hr = pOutput->GetDisplayModeList(format, 0, &numModes, displayModes); @@ -376,7 +377,7 @@ void GFXD3D11Device::enumerateAdapters(Vector &adapterList) SAFE_RELEASE(DXGIFactory); } -void GFXD3D11Device::enumerateVideoModes() +void GFXD3D11Device::enumerateVideoModes() { mVideoModes.clear(); @@ -389,9 +390,9 @@ void GFXD3D11Device::enumerateVideoModes() if (FAILED(hr)) AssertFatal(false, "GFXD3D11Device::enumerateVideoModes -> CreateDXGIFactory1 call failure"); - for(U32 adapterIndex = 0; DXGIFactory->EnumAdapters1(adapterIndex, &EnumAdapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) + for(U32 adapterIndex = 0; DXGIFactory->EnumAdapters1(adapterIndex, &EnumAdapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) { - IDXGIOutput* pOutput = NULL; + IDXGIOutput* pOutput = NULL; hr = EnumAdapter->EnumOutputs(adapterIndex, &pOutput); @@ -414,7 +415,7 @@ void GFXD3D11Device::enumerateVideoModes() if(FAILED(hr)) AssertFatal(false, "GFXD3D11Device::enumerateVideoModes -> GetDisplayModeList call failure"); - displayModes = new DXGI_MODE_DESC[numModes]; + displayModes = new DXGI_MODE_DESC[numModes]; // Get the list hr = pOutput->GetDisplayModeList(format, 0, &numModes, displayModes); @@ -519,14 +520,16 @@ void GFXD3D11Device::init(const GFXVideoMode &mode, PlatformWindow *window) { case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: - mVertexShaderTarget = "vs_5_0"; - mPixelShaderTarget = "ps_5_0"; + mVertexShaderTarget = "vs_5_0"; + mPixelShaderTarget = "ps_5_0"; + mGeometryShaderTarget = "gs_5_0"; mPixVersion = 5.0f; mShaderModel = "50"; break; case D3D_FEATURE_LEVEL_10_1: - mVertexShaderTarget = "vs_4_1"; - mPixelShaderTarget = "ps_4_1"; + mVertexShaderTarget = "vs_4_1"; + mPixelShaderTarget = "ps_4_1"; + mGeometryShaderTarget = "gs_4_1"; mPixVersion = 4.1f; mShaderModel = "41"; break; @@ -546,7 +549,7 @@ void GFXD3D11Device::init(const GFXVideoMode &mode, PlatformWindow *window) SAFE_RELEASE(testQuery); Con::printf("Hardware occlusion query detected: %s", mOcclusionQuerySupported ? "Yes" : "No"); - + mCardProfiler = new GFXD3D11CardProfiler(); mCardProfiler->init(); @@ -589,10 +592,10 @@ void GFXD3D11Device::_suppressDebugMessages() } } -bool GFXD3D11Device::beginSceneInternal() +bool GFXD3D11Device::beginSceneInternal() { mCanCurrentlyRender = true; - return mCanCurrentlyRender; + return mCanCurrentlyRender; } GFXWindowTarget * GFXD3D11Device::allocWindowTarget(PlatformWindow *window) @@ -739,7 +742,7 @@ void GFXD3D11Device::setupGenericShaders(GenericShaderType type) _updateRenderTargets(); } - MatrixF tempMatrix = mProjectionMatrix * mViewMatrix * mWorldMatrix[mWorldStackSize]; + MatrixF tempMatrix = mProjectionMatrix * mViewMatrix * mWorldMatrix[mWorldStackSize]; mGenericShaderBuffer[type]->setSafe(mModelViewProjSC[type], tempMatrix); setShader(mGenericShader[type]); @@ -764,7 +767,7 @@ void GFXD3D11Device::setStateBlockInternal(GFXStateBlock* block, bool force) if (force) d3dCurrent = NULL; - d3dBlock->activate(d3dCurrent); + d3dBlock->activate(d3dCurrent); } /// Called by base GFXDevice to actually set a const buffer @@ -863,7 +866,7 @@ void GFXD3D11Device::clearColorAttachment(const U32 attachment, const LinearColo mD3DDeviceContext->ClearRenderTargetView(rtView, clearColor); } -void GFXD3D11Device::endSceneInternal() +void GFXD3D11Device::endSceneInternal() { mCanCurrentlyRender = false; } @@ -875,7 +878,7 @@ void GFXD3D11Device::_updateRenderTargets() if (mRTDeactivate) { mRTDeactivate->deactivate(); - mRTDeactivate = NULL; + mRTDeactivate = NULL; } // NOTE: The render target changes are not really accurate @@ -887,7 +890,7 @@ void GFXD3D11Device::_updateRenderTargets() mCurrentRT->activate(); mRTDirty = false; - } + } if (mViewportDirty) { @@ -906,7 +909,7 @@ void GFXD3D11Device::_updateRenderTargets() } } -void GFXD3D11Device::releaseDefaultPoolResources() +void GFXD3D11Device::releaseDefaultPoolResources() { // Release all the dynamic vertex buffer arrays // Forcibly clean up the pools @@ -919,7 +922,7 @@ void GFXD3D11Device::releaseDefaultPoolResources() // We gotta clear the current const buffer else the next // activate may erroneously think the device is still holding - // this state and fail to set it. + // this state and fail to set it. mCurrentConstBuffer = NULL; // Set current VB to NULL and set state dirty @@ -943,7 +946,7 @@ void GFXD3D11Device::releaseDefaultPoolResources() mPrimitiveBufferDirty = true; // Zombify texture manager (for D3D this only modifies default pool textures) - if( mTextureManager ) + if( mTextureManager ) mTextureManager->zombify(); // Set global dirty state so the IB/PB and VB get reset @@ -958,7 +961,7 @@ void GFXD3D11Device::releaseDefaultPoolResources() } } -void GFXD3D11Device::reacquireDefaultPoolResources() +void GFXD3D11Device::reacquireDefaultPoolResources() { // Now do the dynamic index buffers if( mDynamicPB == NULL ) @@ -974,7 +977,7 @@ void GFXD3D11Device::reacquireDefaultPoolResources() HRESULT hr = D3D11DEVICE->CreateBuffer(&desc, NULL, &mDynamicPB->ib); - if(FAILED(hr)) + if(FAILED(hr)) { AssertFatal(false, "Failed to allocate dynamic IB"); } @@ -1020,7 +1023,7 @@ GFXD3D11VertexBuffer * GFXD3D11Device::createVBPool( const GFXVertexFormat *vert newBuff->mDevice = this; // Requesting it will allocate it. - vertexFormat->getDecl(); + vertexFormat->getDecl(); D3D11_BUFFER_DESC desc; desc.ByteWidth = vertSize * GFX_MAX_DYNAMIC_VERTS; @@ -1032,7 +1035,7 @@ GFXD3D11VertexBuffer * GFXD3D11Device::createVBPool( const GFXVertexFormat *vert HRESULT hr = D3D11DEVICE->CreateBuffer(&desc, NULL, &newBuff->vb); - if(FAILED(hr)) + if(FAILED(hr)) { AssertFatal(false, "Failed to allocate dynamic VB"); } @@ -1042,9 +1045,9 @@ GFXD3D11VertexBuffer * GFXD3D11Device::createVBPool( const GFXVertexFormat *vert //----------------------------------------------------------------------------- -void GFXD3D11Device::setClipRect( const RectI &inRect ) +void GFXD3D11Device::setClipRect( const RectI &inRect ) { - // We transform the incoming rect by the view + // We transform the incoming rect by the view // matrix first, so that it can be used to pan // and scale the clip rect. // @@ -1052,7 +1055,7 @@ void GFXD3D11Device::setClipRect( const RectI &inRect ) Point3F pos( inRect.point.x, inRect.point.y, 0.0f ); Point3F extent( inRect.extent.x, inRect.extent.y, 0.0f ); getViewMatrix().mulP( pos ); - getViewMatrix().mulV( extent ); + getViewMatrix().mulV( extent ); RectI rect( pos.x, pos.y, extent.x, extent.y ); // Clip the rect against the renderable size. @@ -1068,8 +1071,8 @@ void GFXD3D11Device::setClipRect( const RectI &inRect ) F32 b = F32( mClipRect.point.y + mClipRect.extent.y ); F32 t = F32( mClipRect.point.y ); - // Set up projection matrix, - static Point4F pt; + // Set up projection matrix, + static Point4F pt; pt.set(2.0f / (r - l), 0.0f, 0.0f, 0.0f); mTempMatrix.setColumn(0, pt); @@ -1085,7 +1088,7 @@ void GFXD3D11Device::setClipRect( const RectI &inRect ) setProjectionMatrix( mTempMatrix ); // Set up world/view matrix - mTempMatrix.identity(); + mTempMatrix.identity(); setWorldMatrix( mTempMatrix ); setViewport( mClipRect ); @@ -1097,7 +1100,7 @@ void GFXD3D11Device::setVertexStream( U32 stream, GFXVertexBuffer *buffer ) if ( stream == 0 ) { - // Set the volatile buffer which is used to + // Set the volatile buffer which is used to // offset the start index when doing draw calls. if ( d3dBuffer && d3dBuffer->mVolatileStart > 0 ) mVolatileVB = d3dBuffer; @@ -1106,7 +1109,7 @@ void GFXD3D11Device::setVertexStream( U32 stream, GFXVertexBuffer *buffer ) } // NOTE: We do not use the stream offset here for stream 0 - // as that feature is *supposedly* not as well supported as + // as that feature is *supposedly* not as well supported as // using the start index in drawPrimitive. // // If we can verify that this is not the case then we should @@ -1125,7 +1128,7 @@ void GFXD3D11Device::setVertexStreamFrequency( U32 stream, U32 frequency ) mDrawInstancesCount = frequency; // instances count } -void GFXD3D11Device::_setPrimitiveBuffer( GFXPrimitiveBuffer *buffer ) +void GFXD3D11Device::_setPrimitiveBuffer( GFXPrimitiveBuffer *buffer ) { mCurrentPB = static_cast( buffer ); @@ -1160,7 +1163,7 @@ U32 GFXD3D11Device::primCountToIndexCount(GFXPrimitiveType primType, U32 primiti } -void GFXD3D11Device::drawPrimitive( GFXPrimitiveType primType, U32 vertexStart, U32 primitiveCount ) +void GFXD3D11Device::drawPrimitive( GFXPrimitiveType primType, U32 vertexStart, U32 primitiveCount ) { // This is done to avoid the function call overhead if possible if( mStateDirty ) @@ -1172,12 +1175,12 @@ void GFXD3D11Device::drawPrimitive( GFXPrimitiveType primType, U32 vertexStart, vertexStart += mVolatileVB->mVolatileStart; mD3DDeviceContext->IASetPrimitiveTopology(GFXD3D11PrimType[primType]); - + if ( mDrawInstancesCount ) mD3DDeviceContext->DrawInstanced(primCountToIndexCount(primType, primitiveCount), mDrawInstancesCount, vertexStart, 0); else mD3DDeviceContext->Draw(primCountToIndexCount(primType, primitiveCount), vertexStart); - + mDeviceStatistics.mDrawCalls++; if ( mVertexBufferFrequency[0] > 1 ) mDeviceStatistics.mPolyCount += primitiveCount * mVertexBufferFrequency[0]; @@ -1185,12 +1188,12 @@ void GFXD3D11Device::drawPrimitive( GFXPrimitiveType primType, U32 vertexStart, mDeviceStatistics.mPolyCount += primitiveCount; } -void GFXD3D11Device::drawIndexedPrimitive( GFXPrimitiveType primType, - U32 startVertex, - U32 minIndex, - U32 numVerts, - U32 startIndex, - U32 primitiveCount ) +void GFXD3D11Device::drawIndexedPrimitive( GFXPrimitiveType primType, + U32 startVertex, + U32 minIndex, + U32 numVerts, + U32 startIndex, + U32 primitiveCount ) { // This is done to avoid the function call overhead if possible if( mStateDirty ) @@ -1204,11 +1207,11 @@ void GFXD3D11Device::drawIndexedPrimitive( GFXPrimitiveType primType, startVertex += mVolatileVB->mVolatileStart; mD3DDeviceContext->IASetPrimitiveTopology(GFXD3D11PrimType[primType]); - + if ( mDrawInstancesCount ) mD3DDeviceContext->DrawIndexedInstanced(primCountToIndexCount(primType, primitiveCount), mDrawInstancesCount, mCurrentPB->mVolatileStart + startIndex, startVertex, 0); else - mD3DDeviceContext->DrawIndexed(primCountToIndexCount(primType,primitiveCount), mCurrentPB->mVolatileStart + startIndex, startVertex); + mD3DDeviceContext->DrawIndexed(primCountToIndexCount(primType,primitiveCount), mCurrentPB->mVolatileStart + startIndex, startVertex); mDeviceStatistics.mDrawCalls++; if ( mVertexBufferFrequency[0] > 1 ) @@ -1245,7 +1248,13 @@ void GFXD3D11Device::setShader(GFXShader *shader, bool force) { mD3DDeviceContext->VSSetShader( d3dShader->mVertShader, NULL, 0); mLastVertShader = d3dShader->mVertShader; - } + } + + if (d3dShader->mGeoShader != mLastGeoShader || force) + { + mD3DDeviceContext->GSSetShader(d3dShader->mGeoShader, NULL, 0); + mLastGeoShader = d3dShader->mGeoShader; + } } else { @@ -1308,7 +1317,7 @@ GFXPrimitiveBuffer * GFXD3D11Device::allocPrimitiveBuffer(U32 numIndices, U32 nu HRESULT hr = D3D11DEVICE->CreateBuffer(&desc, NULL, &res->ib); - if(FAILED(hr)) + if(FAILED(hr)) { AssertFatal(false, "Failed to allocate an index buffer."); } @@ -1329,12 +1338,12 @@ GFXVertexBuffer * GFXD3D11Device::allocVertexBuffer(U32 numVerts, const GFXVerte { PROFILE_SCOPE( GFXD3D11Device_allocVertexBuffer ); - GFXD3D11VertexBuffer *res = new GFXD3D11VertexBuffer( this, - numVerts, - vertexFormat, - vertSize, + GFXD3D11VertexBuffer *res = new GFXD3D11VertexBuffer( this, + numVerts, + vertexFormat, + vertSize, bufferType ); - + // Determine usage flags D3D11_USAGE usage = D3D11_USAGE_DEFAULT; @@ -1387,7 +1396,7 @@ GFXVertexBuffer * GFXD3D11Device::allocVertexBuffer(U32 numVerts, const GFXVerte HRESULT hr = D3D11DEVICE->CreateBuffer(&desc, NULL, &res->vb); - if(FAILED(hr)) + if(FAILED(hr)) { AssertFatal(false, "Failed to allocate VB"); } @@ -1540,16 +1549,16 @@ GFXVertexDecl* GFXD3D11Device::allocVertexDecl( const GFXVertexFormat *vertexFor return decl; U32 elemCount = vertexFormat->getElementCount(); - + ID3DBlob* code = NULL; - + // We have to generate a temporary shader here for now since the input layout creation // expects a shader to be already compiled to verify the vertex layout structure. The problem // is that most of the time the regular shaders are compiled AFTER allocVertexDecl is called. if(!decl) { //TODO: Perhaps save/cache the ID3DBlob for later use on identical vertex formats,save creating/compiling the temp shader everytime - String shaderData = _createTempShaderInternal(vertexFormat); + String shaderData = _createTempShaderInternal(vertexFormat); #ifdef TORQUE_DEBUG U32 flags = D3DCOMPILE_DEBUG | D3DCOMPILE_ENABLE_STRICTNESS | D3DCOMPILE_WARNINGS_ARE_ERRORS; @@ -1569,11 +1578,11 @@ GFXVertexDecl* GFXD3D11Device::allocVertexDecl( const GFXVertexFormat *vertexFor SAFE_RELEASE(errorBlob); } - + AssertFatal(code, "D3D11Device::allocVertexDecl - compiled vert shader code missing!"); // Setup the declaration struct. - + U32 stream; D3D11_INPUT_ELEMENT_DESC *vd = new D3D11_INPUT_ELEMENT_DESC[ elemCount]; @@ -1599,7 +1608,7 @@ GFXVertexDecl* GFXD3D11Device::allocVertexDecl( const GFXVertexFormat *vertexFor vd[i].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; vd[i].InstanceDataStepRate = 0; } - // We force the usage index of 0 for everything but + // We force the usage index of 0 for everything but // texture coords for now... this may change later. vd[i].SemanticIndex = 0; @@ -1634,7 +1643,7 @@ GFXVertexDecl* GFXD3D11Device::allocVertexDecl( const GFXVertexFormat *vertexFor decl = new D3D11VertexDecl(); HRESULT hr = mD3DDevice->CreateInputLayout(vd, elemCount,code->GetBufferPointer(), code->GetBufferSize(), &decl->decl); - + if (FAILED(hr)) { AssertFatal(false, "GFXD3D11Device::allocVertexDecl - Failed to create vertex input layout!"); @@ -1654,7 +1663,7 @@ void GFXD3D11Device::setVertexDecl( const GFXVertexDecl *decl ) ID3D11InputLayout *dx11Decl = NULL; if (decl) dx11Decl = static_cast(decl)->decl; - + mD3DDeviceContext->IASetInputLayout(dx11Decl); } @@ -1709,7 +1718,7 @@ GFXFence *GFXD3D11Device::createFence() } // CodeReview: At some point I would like a specialized implementation of - // the method used by the general fence, only without the overhead incurred + // the method used by the general fence, only without the overhead incurred // by using the GFX constructs. Primarily the lock() method on texture handles // will do a data copy, and this method doesn't require a copy, just a lock // [5/10/2007 Pat] @@ -1719,12 +1728,12 @@ GFXFence *GFXD3D11Device::createFence() } GFXOcclusionQuery* GFXD3D11Device::createOcclusionQuery() -{ +{ GFXOcclusionQuery *query; if (mOcclusionQuerySupported) query = new GFXD3D11OcclusionQuery( this ); else - return NULL; + return NULL; query->registerResourceWithDevice(this); return query; @@ -1794,7 +1803,7 @@ const char* GFXD3D11Device::interpretDebugResult(long result) //generics case E_UNEXPECTED: error = "E_UNEXPECTED"; - break; + break; case E_NOTIMPL: error = "E_NOTIMPL"; break; diff --git a/Engine/source/gfx/D3D11/gfxD3D11Device.h b/Engine/source/gfx/D3D11/gfxD3D11Device.h index c1b775152..7b5b24a7d 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Device.h +++ b/Engine/source/gfx/D3D11/gfxD3D11Device.h @@ -121,6 +121,7 @@ protected: ID3D11VertexShader *mLastVertShader; ID3D11PixelShader *mLastPixShader; + ID3D11GeometryShader *mLastGeoShader; S32 mCreateFenceType; @@ -140,6 +141,7 @@ protected: // Shader Model targers String mVertexShaderTarget; String mPixelShaderTarget; + String mGeometryShaderTarget; // String for use with shader macros in the form of shader model version * 10 String mShaderModel; bool mDebugLayers; @@ -148,7 +150,7 @@ protected: bool mOcclusionQuerySupported; - U32 mDrawInstancesCount; + U32 mDrawInstancesCount; /// To manage creating and re-creating of these when device is aquired void reacquireDefaultPoolResources(); @@ -181,11 +183,11 @@ protected: // Index buffer management // { virtual void _setPrimitiveBuffer( GFXPrimitiveBuffer *buffer ); - virtual void drawIndexedPrimitive( GFXPrimitiveType primType, - U32 startVertex, - U32 minIndex, - U32 numVerts, - U32 startIndex, + virtual void drawIndexedPrimitive( GFXPrimitiveType primType, + U32 startVertex, + U32 minIndex, + U32 numVerts, + U32 startIndex, U32 primitiveCount ); // } @@ -197,7 +199,7 @@ protected: String _createTempShaderInternal(const GFXVertexFormat *vertexFormat); // Supress any debug layer messages we don't want to see void _suppressDebugMessages(); - + public: static GFXDevice *createInstance( U32 adapterIndex ); @@ -229,7 +231,7 @@ public: virtual GFXTextureArray* createTextureArray(); virtual F32 getPixelShaderVersion() const { return mPixVersion; } - virtual void setPixelShaderVersion( F32 version ){ mPixVersion = version;} + virtual void setPixelShaderVersion( F32 version ){ mPixVersion = version;} virtual void setShader(GFXShader *shader, bool force = false); virtual U32 getNumSamplers() const { return 16; } @@ -252,10 +254,10 @@ public: virtual void setClipRect( const RectI &rect ); virtual const RectI& getClipRect() const { return mClipRect; } - // } + // } + - /// @name Render Targets /// @{ virtual void _updateRenderTargets(); @@ -263,14 +265,14 @@ public: // Vertex/Index buffer management // { - virtual GFXVertexBuffer* allocVertexBuffer( U32 numVerts, + virtual GFXVertexBuffer* allocVertexBuffer( U32 numVerts, const GFXVertexFormat *vertexFormat, U32 vertSize, GFXBufferType bufferType, void* data = NULL); - virtual GFXPrimitiveBuffer *allocPrimitiveBuffer( U32 numIndices, - U32 numPrimitives, + virtual GFXPrimitiveBuffer *allocPrimitiveBuffer( U32 numIndices, + U32 numPrimitives, GFXBufferType bufferType, void* data = NULL); @@ -307,7 +309,7 @@ public: GFXFence *createFence(); - GFXOcclusionQuery* createOcclusionQuery(); + GFXOcclusionQuery* createOcclusionQuery(); // Default multisample parameters DXGI_SAMPLE_DESC getMultisampleType() const { return mMultisampleDesc; } @@ -317,6 +319,7 @@ public: // Shader Model targers const String &getVertexShaderTarget() const { return mVertexShaderTarget; } const String &getPixelShaderTarget() const { return mPixelShaderTarget; } + const String &getGeometryShaderTarget() const { return mGeometryShaderTarget; } const String &getShaderModel() const { return mShaderModel; } // grab the sampler map diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp index ba5c5e227..294e4d1ff 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp @@ -215,7 +215,7 @@ void GFXD3D11ShaderConstBuffer::setMatrix(const GFXShaderConstDesc& constDesc, c break; } - // Loop through and copy + // Loop through and copy bool ret = false; U8* currDestPointer = buf + constDesc.offset; const U8* currSourcePointer = static_cast(data); @@ -418,7 +418,7 @@ void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF& if (matrixType == GFXSCT_Float4x4) dMemcpy(mInstPtr + constDesc.offset, mat, sizeof(mat)); - // TODO: Support 3x3 and 2x2 matricies? + // TODO: Support 3x3 and 2x2 matricies? return; } @@ -569,6 +569,16 @@ void GFXD3D11ShaderConstBuffer::activate( GFXD3D11ShaderConstBuffer *prevShaderB D3D11DEVICECONTEXT->PSSetConstantBuffers(bufStartSlot, numBufs, psBuffers); } + if (mShader->mGeoShader && bufRanges[2].isValid()) + { + const U32 bufStartSlot = bufRanges[2].mBufMin; + const U32 numBufs = bufRanges[2].mBufMax - bufRanges[2].mBufMin + 1; + ID3D11Buffer** psBuffers = mBoundBuffers[2] + bufStartSlot; + + D3D11DEVICECONTEXT->GSSetConstantBuffers(bufStartSlot, numBufs, psBuffers); + } + + mWasLost = false; } @@ -608,6 +618,7 @@ GFXD3D11Shader::GFXD3D11Shader() AssertFatal(D3D11DEVICE, "Invalid device for shader."); mVertShader = NULL; mPixShader = NULL; + mGeoShader = NULL; if( smD3DInclude == NULL ) smD3DInclude = new gfxD3D11Include; @@ -628,6 +639,7 @@ GFXD3D11Shader::~GFXD3D11Shader() // release shaders SAFE_RELEASE(mVertShader); SAFE_RELEASE(mPixShader); + SAFE_RELEASE(mGeoShader); //maybe add SAFE_RELEASE(mVertexCode) ? } @@ -637,6 +649,7 @@ bool GFXD3D11Shader::_init() SAFE_RELEASE(mVertShader); SAFE_RELEASE(mPixShader); + SAFE_RELEASE(mGeoShader); // Create the macro array including the system wide macros. const U32 macroCount = smGlobalMacros.size() + mMacros.size() + 2; @@ -668,6 +681,12 @@ bool GFXD3D11Shader::_init() if (!mPixelFile.isEmpty() && !_compileShader( mPixelFile, GFXShaderStage::PIXEL_SHADER, d3dMacros)) return false; + if (!mGeometryFile.isEmpty()) + { + if (!_compileShader(mGeometryFile, GFXShaderStage::GEOMETRY_SHADER, d3dMacros)) + return false; + } + // Mark all existing handles as invalid. // Those that are found when parsing the descriptions will then be marked valid again. for (auto& pair : mHandles) { @@ -676,7 +695,7 @@ bool GFXD3D11Shader::_init() _buildShaderConstantHandles(); - // Notify any existing buffers that the buffer + // Notify any existing buffers that the buffer // layouts have changed and they need to update. Vector::iterator biter = mActiveBuffers.begin(); for ( ; biter != mActiveBuffers.end(); biter++ ) @@ -685,7 +704,7 @@ bool GFXD3D11Shader::_init() return true; } -bool GFXD3D11Shader::_compileShader( const Torque::Path &filePath, +bool GFXD3D11Shader::_compileShader( const Torque::Path &filePath, GFXShaderStage shaderStage, const D3D_SHADER_MACRO *defines) { @@ -711,9 +730,9 @@ bool GFXD3D11Shader::_compileShader( const Torque::Path &filePath, #endif // Is it an HLSL shader? - if(filePath.getExtension().equal("hlsl", String::NoCase)) + if(filePath.getExtension().equal("hlsl", String::NoCase)) { - // Set this so that the D3DInclude::Open will have this + // Set this so that the D3DInclude::Open will have this // information for relative paths. smD3DInclude->setPath(filePath.getRootAndPath()); @@ -754,6 +773,7 @@ bool GFXD3D11Shader::_compileShader( const Torque::Path &filePath, target = D3D11->getPixelShaderTarget(); break; case GEOMETRY_SHADER: + target = D3D11->getGeometryShaderTarget(); break; case DOMAIN_SHADER: break; @@ -802,6 +822,7 @@ bool GFXD3D11Shader::_compileShader( const Torque::Path &filePath, res = D3D11DEVICE->CreatePixelShader(code->GetBufferPointer(), code->GetBufferSize(), NULL, &mPixShader); break; case GEOMETRY_SHADER: + res = D3D11DEVICE->CreateGeometryShader(code->GetBufferPointer(), code->GetBufferSize(), NULL, &mGeoShader); break; case DOMAIN_SHADER: break; @@ -812,7 +833,7 @@ bool GFXD3D11Shader::_compileShader( const Torque::Path &filePath, default: break; } - + if (FAILED(res)) { AssertFatal(false, "D3D11Shader::_compilershader- failed to create shader"); @@ -848,6 +869,8 @@ bool GFXD3D11Shader::_compileShader( const Torque::Path &filePath, mPixShader->SetPrivateData(WKPDID_D3DDebugObjectName, shader.size(), shader.c_str()); break; case GEOMETRY_SHADER: + shader = mGeometryFile.getFileName(); + mGeoShader->SetPrivateData(WKPDID_D3DDebugObjectName, shader.size(), shader.c_str()); break; case DOMAIN_SHADER: break; @@ -859,8 +882,8 @@ bool GFXD3D11Shader::_compileShader( const Torque::Path &filePath, break; } #endif - - SAFE_RELEASE(code); + + SAFE_RELEASE(code); SAFE_RELEASE(reflectionTable); SAFE_RELEASE(errorBuff); @@ -885,7 +908,7 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection* refTable, GFXShaderConstDesc desc; ID3D11ShaderReflectionConstantBuffer* constantBuffer = refTable->GetConstantBufferByIndex(i); D3D11_SHADER_BUFFER_DESC constantBufferDesc; - + if (constantBuffer->GetDesc(&constantBufferDesc) == S_OK) { desc.name = String(constantBufferDesc.Name); @@ -954,11 +977,11 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection* refTable, #ifdef D3D11_DEBUG_SPEW Con::printf("Variable Name %s:, offset: %d, size: %d, constantDesc.Elements: %d", varDesc.name.c_str(), varDesc.StartOffset, varDesc.Size, varDesc.arraySize); -#endif +#endif mShaderConsts.push_back(varDesc); } } - + } else { @@ -1073,7 +1096,7 @@ GFXShaderConstType GFXD3D11Shader::convertConstType(const D3D11_SHADER_TYPE_DESC break; } } - + } void GFXD3D11Shader::_buildShaderConstantHandles() @@ -1144,7 +1167,7 @@ void GFXD3D11Shader::_buildInstancingShaderConstantHandles() for ( U32 i=0; i < mInstancingFormat->getElementCount(); i++ ) { const GFXVertexElement &element = mInstancingFormat->getElement( i ); - + String constName = String::ToString( "$%s", element.getSemantic().c_str() ); GFXD3D11ShaderConstHandle *handle; @@ -1169,15 +1192,15 @@ void GFXD3D11Shader::_buildInstancingShaderConstantHandles() desc.arraySize = 1; if ( j != mHandles.end() ) - handle = j->value; + handle = j->value; else { handle = new GFXD3D11ShaderConstHandle(this, desc); - mHandles[ constName ] = handle; + mHandles[ constName ] = handle; } handle->mShader = this; - handle->setValid( true ); + handle->setValid( true ); handle->mInstancingConstant = true; // If this is a matrix we will have 2 or 3 more of these @@ -1213,19 +1236,19 @@ GFXShaderConstBufferRef GFXD3D11Shader::allocConstBuffer() /// Returns a shader constant handle for name, if the variable doesn't exist NULL is returned. GFXShaderConstHandle* GFXD3D11Shader::getShaderConstHandle(const String& name) { - HandleMap::Iterator i = mHandles.find(name); + HandleMap::Iterator i = mHandles.find(name); if ( i != mHandles.end() ) { return i->value; - } - else - { + } + else + { GFXD3D11ShaderConstHandle *handle = new GFXD3D11ShaderConstHandle(this); handle->setValid( false ); mHandles[name] = handle; - return handle; - } + return handle; + } } GFXShaderConstHandle* GFXD3D11Shader::findShaderConstHandle(const String& name) @@ -1245,7 +1268,7 @@ const Vector& GFXD3D11Shader::getShaderConstDesc() const } U32 GFXD3D11Shader::getAlignmentValue(const GFXShaderConstType constType) const -{ +{ const U32 mRowSizeF = 16; const U32 mRowSizeI = 16; @@ -1253,7 +1276,7 @@ U32 GFXD3D11Shader::getAlignmentValue(const GFXShaderConstType constType) const { case GFXSCT_Float : case GFXSCT_Float2 : - case GFXSCT_Float3 : + case GFXSCT_Float3 : case GFXSCT_Float4 : return mRowSizeF; break; @@ -1261,7 +1284,7 @@ U32 GFXD3D11Shader::getAlignmentValue(const GFXShaderConstType constType) const case GFXSCT_Float2x2 : return mRowSizeF * 2; break; - case GFXSCT_Float3x3 : + case GFXSCT_Float3x3 : return mRowSizeF * 3; break; case GFXSCT_Float4x3: @@ -1269,11 +1292,11 @@ U32 GFXD3D11Shader::getAlignmentValue(const GFXShaderConstType constType) const break; case GFXSCT_Float4x4 : return mRowSizeF * 4; - break; + break; //// Scalar case GFXSCT_Int : case GFXSCT_Int2 : - case GFXSCT_Int3 : + case GFXSCT_Int3 : case GFXSCT_Int4 : return mRowSizeI; break; diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.h b/Engine/source/gfx/D3D11/gfxD3D11Shader.h index 3460ea6f5..ffa9dbb2e 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.h +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.h @@ -80,7 +80,7 @@ public: S32 getSamplerRegister() const { return (!isSampler() || !mValid) ? -1 : mSampler; } // Returns true if this is a handle to a sampler register. - bool isSampler() const + bool isSampler() const { return (getType() >= GFXSCT_Sampler); } @@ -157,7 +157,7 @@ public: protected: friend class GFXD3D11Shader; - /// We keep a weak reference to the shader + /// We keep a weak reference to the shader /// because it will often be deleted. WeakRefPtr mShader; BufferMap mBufferMap; @@ -183,12 +183,12 @@ public: typedef Map BufferMap; GFXD3D11Shader(); - virtual ~GFXD3D11Shader(); + virtual ~GFXD3D11Shader(); // GFXShader virtual GFXShaderConstBufferRef allocConstBuffer(); virtual const Vector& getShaderConstDesc() const; - virtual GFXShaderConstHandle* getShaderConstHandle(const String& name); + virtual GFXShaderConstHandle* getShaderConstHandle(const String& name); virtual GFXShaderConstHandle* findShaderConstHandle(const String& name); virtual U32 getAlignmentValue(const GFXShaderConstType constType) const; @@ -202,6 +202,7 @@ protected: ID3D11VertexShader *mVertShader; ID3D11PixelShader *mPixShader; + ID3D11GeometryShader *mGeoShader; static gfxD3DIncludeRef smD3DInclude; @@ -213,13 +214,13 @@ protected: Vector mSamplerDescriptions; // These two functions are used when compiling shaders from hlsl - virtual bool _compileShader( const Torque::Path &filePath, + virtual bool _compileShader( const Torque::Path &filePath, GFXShaderStage shaderStage, const D3D_SHADER_MACRO *defines); void _getShaderConstants( ID3D11ShaderReflection* refTable, GFXShaderStage shaderStage); - + // This is used in both cases virtual void _buildShaderConstantHandles(); void _buildInstancingShaderConstantHandles(); diff --git a/Engine/source/gfx/gl/gfxGLShader.cpp b/Engine/source/gfx/gl/gfxGLShader.cpp index 2dc047e2b..9bd6ac183 100644 --- a/Engine/source/gfx/gl/gfxGLShader.cpp +++ b/Engine/source/gfx/gl/gfxGLShader.cpp @@ -39,12 +39,12 @@ class GFXGLShaderConstHandle : public GFXShaderConstHandle { friend class GFXGLShader; -public: - +public: + GFXGLShaderConstHandle( GFXGLShader *shader ); GFXGLShaderConstHandle( GFXGLShader *shader, const GFXShaderConstDesc &desc, GLuint loc, S32 samplerNum ); virtual ~GFXGLShaderConstHandle(); - + void reinit( const GFXShaderConstDesc &desc, GLuint loc, S32 samplerNum ); const String& getName() const { return mDesc.name; } @@ -52,7 +52,7 @@ public: U32 getArraySize() const { return mDesc.arraySize; } U32 getSize() const; - void setValid( bool valid ) { mValid = valid; } + 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; } @@ -62,7 +62,7 @@ public: U32 mOffset; U32 mSize; GLuint mLocation; - S32 mSamplerNum; + S32 mSamplerNum; bool mInstancingConstant; }; @@ -75,7 +75,7 @@ GFXGLShaderConstHandle::GFXGLShaderConstHandle( GFXGLShader *shader ) static U32 shaderConstTypeSize(GFXShaderConstType type) { - switch(type) + switch(type) { case GFXSCT_Float: case GFXSCT_Int: @@ -107,7 +107,7 @@ static U32 shaderConstTypeSize(GFXShaderConstType type) } } -GFXGLShaderConstHandle::GFXGLShaderConstHandle( GFXGLShader *shader, const GFXShaderConstDesc &desc, GLuint loc, S32 samplerNum ) +GFXGLShaderConstHandle::GFXGLShaderConstHandle( GFXGLShader *shader, const GFXShaderConstDesc &desc, GLuint loc, S32 samplerNum ) : mShader(shader), mInstancingConstant(false) { reinit(desc, loc, samplerNum); @@ -120,7 +120,7 @@ void GFXGLShaderConstHandle::reinit( const GFXShaderConstDesc& desc, GLuint loc, mSamplerNum = samplerNum; mOffset = 0; mInstancingConstant = false; - + U32 elemSize = shaderConstTypeSize(mDesc.constType); AssertFatal(elemSize, "GFXGLShaderConst::GFXGLShaderConst - elemSize is 0"); mSize = mDesc.arraySize * elemSize; @@ -169,7 +169,7 @@ void GFXGLShaderConstBuffer::internalSet(GFXShaderConstHandle* handle, const Con AssertFatal(mShader == _glHandle->mShader, "GFXGLShaderConstBuffer::set - Should only set handles which are owned by our shader"); U8 *buf = mBuffer + _glHandle->mOffset; - if(_glHandle->mInstancingConstant) + if(_glHandle->mInstancingConstant) buf = mInstPtr + _glHandle->mOffset; dMemcpy(buf, ¶m, sizeof(ConstType)); @@ -204,7 +204,7 @@ void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const LinearColor { internalSet(handle, fv); } - + void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const S32 fv) { internalSet(handle, fv); @@ -258,7 +258,7 @@ void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArra internalSet(handle, fv); } -void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray& fv) +void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray& fv) { internalSet(handle, fv); } @@ -292,7 +292,7 @@ void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF& ma GFXGLShaderConstHandle* _glHandle = static_cast(handle); AssertFatal(mShader == _glHandle->mShader, "GFXGLShaderConstBuffer::set - Should only set handles which are owned by our shader"); AssertFatal(!_glHandle->mInstancingConstant || matType == GFXSCT_Float4x4, "GFXGLShaderConstBuffer::set - Only support GFXSCT_Float4x4 for instancing"); - + switch(matType) { case GFXSCT_Float2x2: @@ -316,15 +316,15 @@ void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF& ma dMemcpy(mBuffer + _glHandle->mOffset, (const F32*)mat, (sizeof(F32) * 12));// matrix with end row chopped off break; case GFXSCT_Float4x4: - { + { if(_glHandle->mInstancingConstant) { - MatrixF transposed; + MatrixF transposed; mat.transposeTo(transposed); dMemcpy( mInstPtr + _glHandle->mOffset, (const F32*)transposed, sizeof(MatrixF) ); return; } - + dMemcpy(mBuffer + _glHandle->mOffset, (const F32*)mat, sizeof(MatrixF)); break; } @@ -340,7 +340,7 @@ void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF* ma AssertFatal(handle->isValid(), "GFXGLShaderConstBuffer::set - Handle is not valid!" ); GFXGLShaderConstHandle* _glHandle = static_cast(handle); - AssertFatal(mShader == _glHandle->mShader, "GFXGLShaderConstBuffer::set - Should only set handles which are owned by our shader"); + AssertFatal(mShader == _glHandle->mShader, "GFXGLShaderConstBuffer::set - Should only set handles which are owned by our shader"); AssertFatal(!_glHandle->mInstancingConstant, "GFXGLShaderConstBuffer::set - Instancing not supported for matrix arrays"); switch (matrixType) { @@ -385,6 +385,7 @@ void GFXGLShaderConstBuffer::onShaderReload( GFXGLShader *shader ) GFXGLShader::GFXGLShader(GFXGLDevice* device) : mVertexShader(0), mPixelShader(0), + mGeometryShader(0), mProgram(0), mDevice(device), mConstBufferSize(0), @@ -397,7 +398,7 @@ GFXGLShader::~GFXGLShader() clearShaders(); for(HandleMap::Iterator i = mHandles.begin(); i != mHandles.end(); i++) delete i->value; - + delete[] mConstBuffer; } @@ -406,10 +407,12 @@ void GFXGLShader::clearShaders() glDeleteProgram(mProgram); glDeleteShader(mVertexShader); glDeleteShader(mPixelShader); - + glDeleteShader(mGeometryShader); + mProgram = 0; mVertexShader = 0; mPixelShader = 0; + mGeometryShader = 0; } bool GFXGLShader::_init() @@ -422,44 +425,57 @@ bool GFXGLShader::_init() clearShaders(); mProgram = glCreateProgram(); - + // Set the macros and add the global ones. Vector macros; macros.merge( mMacros ); macros.merge( smGlobalMacros ); - + macros.increment(); macros.last().name = "TORQUE_SM"; macros.last().value = 40; macros.increment(); macros.last().name = "TORQUE_VERTEX_SHADER"; macros.last().value = ""; - + // Default to true so we're "successful" if a vertex/pixel shader wasn't specified. bool compiledVertexShader = true; bool compiledPixelShader = true; - - // Compile the vertex and pixel shaders if specified. - if(!mVertexFile.isEmpty()) - compiledVertexShader = initShader(mVertexFile, true, macros); + bool compiledGeometryShader = true; + + // Compile the vertex and pixel shaders if specified. + if (!mVertexFile.isEmpty()) + { + compiledVertexShader = initShader(mVertexFile, GFXShaderStage::VERTEX_SHADER, macros); + if (!compiledVertexShader) + return false; + } + + if (!mPixelFile.isEmpty()) + { + macros.last().name = "TORQUE_PIXEL_SHADER"; + compiledPixelShader = initShader(mPixelFile, GFXShaderStage::PIXEL_SHADER, macros); + if (!compiledPixelShader) + return false; + } + + if (!mGeometryFile.isEmpty()) + { + macros.last().name = "TORQUE_GEOMETRY_SHADER"; + compiledGeometryShader = initShader(mPixelFile, GFXShaderStage::GEOMETRY_SHADER, macros); + if (!compiledGeometryShader) + return false; + } - macros.last().name = "TORQUE_PIXEL_SHADER"; - if(!mPixelFile.isEmpty()) - compiledPixelShader = initShader(mPixelFile, false, macros); - - // If either shader was present and failed to compile, bail. - if(!compiledVertexShader || !compiledPixelShader) - return false; - // Link it! glLinkProgram( mProgram ); - + GLint activeAttribs = 0; glGetProgramiv(mProgram, GL_ACTIVE_ATTRIBUTES, &activeAttribs ); - + GLint maxLength; glGetProgramiv(mProgram, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxLength); - + FrameTemp tempData(maxLength+1); *tempData.address() = '\0'; // Check atributes @@ -467,11 +483,11 @@ bool GFXGLShader::_init() { GLint size; GLenum type; - + glGetActiveAttrib(mProgram, i, maxLength + 1, NULL, &size, &type, tempData.address()); - + StringTableEntry argName = StringTable->insert(tempData.address()); - + CHECK_AARG(Torque::GL_VertexAttrib_Position, vPosition); CHECK_AARG(Torque::GL_VertexAttrib_Normal, vNormal); CHECK_AARG(Torque::GL_VertexAttrib_Color, vColor); @@ -502,13 +518,13 @@ bool GFXGLShader::_init() glBindFragDataLocation(mProgram, i, buffer); } - + // Link it again! glLinkProgram( mProgram ); - + GLint linkStatus; glGetProgramiv( mProgram, GL_LINK_STATUS, &linkStatus ); - + // Dump the info log to the console U32 logLength = 0; glGetProgramiv(mProgram, GL_INFO_LOG_LENGTH, (GLint*)&logLength); @@ -517,7 +533,7 @@ bool GFXGLShader::_init() FrameAllocatorMarker fam; char* log = (char*)fam.alloc( logLength ); glGetProgramInfoLog( mProgram, logLength, NULL, log ); - + if ( linkStatus == GL_FALSE ) { if ( smLogErrors ) @@ -539,16 +555,16 @@ bool GFXGLShader::_init() if ( linkStatus == GL_FALSE ) return false; - initConstantDescs(); + initConstantDescs(); initHandles(); - - // Notify Buffers we might have changed in size. - // If this was our first init then we won't have any activeBuffers + + // Notify Buffers we might have changed in size. + // If this was our first init then we won't have any activeBuffers // to worry about unnecessarily calling. Vector::iterator biter = mActiveBuffers.begin(); - for ( ; biter != mActiveBuffers.end(); biter++ ) + for ( ; biter != mActiveBuffers.end(); biter++ ) ((GFXGLShaderConstBuffer*)(*biter))->onShaderReload( this ); - + return true; } @@ -565,23 +581,23 @@ void GFXGLShader::initConstantDescs() maxNameLength++; FrameTemp uniformName(maxNameLength); - + for(U32 i = 0; i < numUniforms; i++) { GLint size; GLenum type; glGetActiveUniform(mProgram, i, maxNameLength, NULL, &size, &type, uniformName); GFXShaderConstDesc desc; - + desc.name = String((char*)uniformName); - + // Remove array brackets from the name desc.name = desc.name.substr(0, desc.name.find('[')); - + // Insert $ to match D3D behavior of having a $ prepended to parameters to main. desc.name.insert(0, '$'); desc.arraySize = size; - + switch(type) { case GL_FLOAT: @@ -641,24 +657,24 @@ void GFXGLShader::initConstantDescs() // If we don't recognize the constant don't add its description. continue; } - + mConstants.push_back(desc); } } void GFXGLShader::initHandles() -{ +{ // 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 ); + for ( HandleMap::Iterator iter = mHandles.begin(); iter != mHandles.end(); ++iter ) + (iter->value)->setValid( false ); mValidHandles.clear(); - // Loop through all ConstantDescriptions, + // Loop through all ConstantDescriptions, // if they aren't in the HandleMap add them, if they are reinitialize them. for ( U32 i = 0; i < mConstants.size(); i++ ) { - GFXShaderConstDesc &desc = mConstants[i]; + GFXShaderConstDesc &desc = mConstants[i]; // Index element 1 of the name to skip the '$' we inserted earier. GLint loc = glGetUniformLocation(mProgram, &desc.name.c_str()[1]); @@ -678,11 +694,11 @@ void GFXGLShader::initHandles() } if ( handle != mHandles.end() ) { - handle->value->reinit( desc, loc, sampler ); - } - else + handle->value->reinit( desc, loc, sampler ); + } + else { - mHandles[desc.name] = new GFXGLShaderConstHandle( this, desc, loc, sampler ); + mHandles[desc.name] = new GFXGLShaderConstHandle( this, desc, loc, sampler ); } } @@ -703,10 +719,10 @@ void GFXGLShader::initHandles() mConstBufferSize += handle->getSize(); } } - + mConstBuffer = new U8[mConstBufferSize]; dMemset(mConstBuffer, 0, mConstBufferSize); - + // Set our program so uniforms are assigned properly. mDevice->setShader(this, false); @@ -736,15 +752,15 @@ void GFXGLShader::initHandles() for ( U32 i=0; i < mInstancingFormat->getElementCount(); i++ ) { const GFXVertexElement &element = mInstancingFormat->getElement( i ); - + String constName = String::ToString( "$%s", element.getSemantic().c_str() ); - HandleMap::Iterator handle = mHandles.find(constName); + HandleMap::Iterator handle = mHandles.find(constName); if ( handle != mHandles.end() ) - { + { AssertFatal(0, ""); - } - else + } + else { GFXShaderConstDesc desc; desc.name = constName; @@ -759,7 +775,7 @@ void GFXGLShader::initHandles() desc.constType = GFXSCT_Float; break; } - + GFXGLShaderConstHandle *h = new GFXGLShaderConstHandle( this, desc, -1, -1 ); h->mInstancingConstant = true; h->mOffset = offset; @@ -801,7 +817,7 @@ GFXShaderConstHandle* GFXGLShader::getShaderConstHandle(const String& name) GFXGLShaderConstHandle* handle = new GFXGLShaderConstHandle( this ); handle->setValid(false); mHandles[ name ] = handle; - + return handle; } } @@ -826,11 +842,11 @@ void GFXGLShader::setConstantsFromBuffer(GFXGLShaderConstBuffer* buffer) if(handle->mInstancingConstant) continue; - + // Don't set if the value has not be changed. if(dMemcmp(mConstBuffer + handle->mOffset, buffer->mBuffer + handle->mOffset, handle->getSize()) == 0) continue; - + // Copy new value into our const buffer and set in GL. dMemcpy(mConstBuffer + handle->mOffset, buffer->mBuffer + handle->mOffset, handle->getSize()); @@ -872,7 +888,7 @@ void GFXGLShader::setConstantsFromBuffer(GFXGLShaderConstBuffer* buffer) break; case GFXSCT_Float4x3: // NOTE: To save a transpose here we could store the matrix transposed (i.e. column major) in the constant buffer. - // See _mesa_uniform_matrix in the mesa source for the correct transpose algorithm for a 4x3 matrix. + // See _mesa_uniform_matrix in the mesa source for the correct transpose algorithm for a 4x3 matrix. glUniformMatrix4x3fv(handle->mLocation, handle->mDesc.arraySize, true, (GLfloat*)(mConstBuffer + handle->mOffset)); break; case GFXSCT_Float4x4: @@ -919,7 +935,7 @@ char* GFXGLShader::_handleIncludes( const Torque::Path& path, FileStream *s ) //dStrncpy( buffer, linePragma.c_str(), linePragmaLen ); s->read(shaderLen, buffer); buffer[shaderLen] = 0; - + char* p = dStrstr(buffer, "#include"); while(p) { @@ -944,12 +960,12 @@ char* GFXGLShader::_handleIncludes( const Torque::Path& path, FileStream *s ) // First try it as a local file. Torque::Path includePath = Torque::Path::Join(path.getPath(), '/', includeFile); includePath = Torque::Path::CompressPath(includePath); - + FileStream includeStream; if ( !includeStream.open( includePath, Torque::FS::File::Read ) ) { - // Try again assuming the path is absolute + // Try again assuming the path is absolute // and/or relative. includePath = String( includeFile ); includePath = Torque::Path::CompressPath(includePath); @@ -958,7 +974,7 @@ char* GFXGLShader::_handleIncludes( const Torque::Path& path, FileStream *s ) AssertISV(false, avar("failed to open include '%s'.", includePath.getFullPath().c_str())); if ( smLogErrors ) - Con::errorf( "GFXGLShader::_handleIncludes - Failed to open include '%s'.", + Con::errorf( "GFXGLShader::_handleIncludes - Failed to open include '%s'.", includePath.getFullPath().c_str() ); // Fail... don't return the buffer. @@ -968,17 +984,17 @@ char* GFXGLShader::_handleIncludes( const Torque::Path& path, FileStream *s ) } char* includedText = _handleIncludes(includePath, &includeStream); - + // If a sub-include fails... cleanup and return. if ( !includedText ) { dFree(buffer); return NULL; } - + // TODO: Disabled till this is fixed correctly. // - // Count the number of lines in the file + // Count the number of lines in the file // before the include. /* U32 includeLine = 0; @@ -1002,7 +1018,7 @@ char* GFXGLShader::_handleIncludes( const Torque::Path& path, FileStream *s ) // Add a new line pragma to restore the proper // file and line number after the include. //sItx += String::ToString( "\r\n#line %d \r\n", includeLine ); - + dFree(includedText); manip.insert(q-buffer, sItx); char* manipBuf = dStrdup(manip.c_str()); @@ -1012,18 +1028,18 @@ char* GFXGLShader::_handleIncludes( const Torque::Path& path, FileStream *s ) } p = dStrstr(p, "#include"); } - + return buffer; } -bool GFXGLShader::_loadShaderFromStream( GLuint shader, - const Torque::Path &path, - FileStream *s, +bool GFXGLShader::_loadShaderFromStream( GLuint shader, + const Torque::Path &path, + FileStream *s, const Vector ¯os ) { Vector buffers; Vector lengths; - + // The GLSL version declaration must go first! const char *versionDecl = "#version 330\n"; buffers.push_back( dStrdup( versionDecl ) ); @@ -1052,16 +1068,16 @@ bool GFXGLShader::_loadShaderFromStream( GLuint shader, buffers.push_back( dStrdup( define.c_str() ) ); lengths.push_back( define.length() ); } - + // Now finally add the shader source. U32 shaderLen = s->getStreamSize(); char *buffer = _handleIncludes(path, s); if ( !buffer ) return false; - + buffers.push_back(buffer); lengths.push_back(shaderLen); - + glShaderSource(shader, buffers.size(), (const GLchar**)const_cast(buffers.address()), NULL); #if defined(TORQUE_DEBUG) && defined(TORQUE_DEBUG_GFX) @@ -1084,19 +1100,40 @@ bool GFXGLShader::_loadShaderFromStream( GLuint shader, return true; } -bool GFXGLShader::initShader( const Torque::Path &file, - bool isVertex, +bool GFXGLShader::initShader( const Torque::Path &file, + GFXShaderStage stage, const Vector ¯os ) { PROFILE_SCOPE(GFXGLShader_CompileShader); - GLuint activeShader = glCreateShader(isVertex ? GL_VERTEX_SHADER : GL_FRAGMENT_SHADER); - if(isVertex) + + GLuint activeShader; + + switch (stage) + { + case VERTEX_SHADER: + activeShader = glCreateShader(GL_VERTEX_SHADER); mVertexShader = activeShader; - else + break; + case PIXEL_SHADER: + activeShader = glCreateShader(GL_FRAGMENT_SHADER); mPixelShader = activeShader; + break; + case GEOMETRY_SHADER: + activeShader = glCreateShader(GL_GEOMETRY_SHADER); + mGeometryShader = activeShader; + break; + case DOMAIN_SHADER: + break; + case HULL_SHADER: + break; + case COMPUTE_SHADER: + break; + default: + break; + } + glAttachShader(mProgram, activeShader); - - + // Ok it's not in the shader gen manager, so ask Torque for it FileStream stream; if ( !stream.open( file, Torque::FS::File::Read ) ) @@ -1104,12 +1141,12 @@ bool GFXGLShader::initShader( const Torque::Path &file, AssertISV(false, avar("GFXGLShader::initShader - failed to open shader '%s'.", file.getFullPath().c_str())); if ( smLogErrors ) - Con::errorf( "GFXGLShader::initShader - Failed to open shader file '%s'.", + Con::errorf( "GFXGLShader::initShader - Failed to open shader file '%s'.", file.getFullPath().c_str() ); return false; } - + if (!_loadShaderFromStream(activeShader, file, &stream, macros)) { if (smLogErrors) @@ -1122,7 +1159,7 @@ bool GFXGLShader::initShader( const Torque::Path &file, // Dump the info log to the console U32 logLength = 0; glGetShaderiv(activeShader, GL_INFO_LOG_LENGTH, (GLint*)&logLength); - + if ( logLength ) { FrameAllocatorMarker fam; @@ -1164,6 +1201,6 @@ const String GFXGLShader::describeSelf() const ret = String::ToString(" Program: %i", mProgram); ret += String::ToString(" Vertex Path: %s", mVertexFile.getFullPath().c_str()); ret += String::ToString(" Pixel Path: %s", mPixelFile.getFullPath().c_str()); - + return ret; } diff --git a/Engine/source/gfx/gl/gfxGLShader.h b/Engine/source/gfx/gl/gfxGLShader.h index e3d3bb69c..a3664d4b1 100644 --- a/Engine/source/gfx/gl/gfxGLShader.h +++ b/Engine/source/gfx/gl/gfxGLShader.h @@ -50,43 +50,43 @@ public: virtual const Vector& getShaderConstDesc() const; /// Returns the alignment value for constType - virtual U32 getAlignmentValue(const GFXShaderConstType constType) const; + virtual U32 getAlignmentValue(const GFXShaderConstType constType) const; virtual GFXShaderConstBufferRef allocConstBuffer(); /// @} - + /// @name GFXResource interface /// @{ virtual void zombify(); virtual void resurrect() { reload(); } virtual const String describeSelf() const; - /// @} + /// @} /// Activates this shader in the GL context. void useProgram(); - + protected: friend class GFXGLShaderConstBuffer; friend class GFXGLShaderConstHandle; - - virtual bool _init(); - bool initShader( const Torque::Path &file, - bool isVertex, + virtual bool _init(); + + bool initShader( const Torque::Path &file, + GFXShaderStage stage, const Vector ¯os ); void clearShaders(); void initConstantDescs(); void initHandles(); void setConstantsFromBuffer(GFXGLShaderConstBuffer* buffer); - + static char* _handleIncludes( const Torque::Path &path, FileStream *s ); - static bool _loadShaderFromStream( GLuint shader, - const Torque::Path& path, - FileStream* s, + static bool _loadShaderFromStream( GLuint shader, + const Torque::Path& path, + FileStream* s, const Vector& macros ); /// @name Internal GL handles @@ -95,7 +95,7 @@ protected: GLuint mPixelShader; GLuint mProgram; /// @} - + Vector mConstants; U32 mConstBufferSize; U8* mConstBuffer; @@ -109,7 +109,7 @@ class GFXGLShaderConstBuffer : public GFXShaderConstBuffer public: GFXGLShaderConstBuffer(GFXGLShader* shader, U32 bufSize, U8* existingConstants); ~GFXGLShaderConstBuffer(); - + /// Called by GFXGLDevice to activate this buffer. void activate(); @@ -123,7 +123,7 @@ public: virtual void set(GFXShaderConstHandle* handle, const Point3F& fv); virtual void set(GFXShaderConstHandle* handle, const Point4F& fv); virtual void set(GFXShaderConstHandle* handle, const PlaneF& fv); - virtual void set(GFXShaderConstHandle* handle, const LinearColorF& fv); + virtual void set(GFXShaderConstHandle* handle, const LinearColorF& fv); virtual void set(GFXShaderConstHandle* handle, const S32 f); virtual void set(GFXShaderConstHandle* handle, const Point2I& fv); virtual void set(GFXShaderConstHandle* handle, const Point3I& fv); @@ -131,13 +131,13 @@ public: virtual void set(GFXShaderConstHandle* handle, const AlignedArray& fv); virtual void set(GFXShaderConstHandle* handle, const AlignedArray& fv); virtual void set(GFXShaderConstHandle* handle, const AlignedArray& fv); - virtual void set(GFXShaderConstHandle* handle, const AlignedArray& fv); + virtual void set(GFXShaderConstHandle* handle, const AlignedArray& fv); virtual void set(GFXShaderConstHandle* handle, const AlignedArray& fv); virtual void set(GFXShaderConstHandle* handle, const AlignedArray& fv); virtual void set(GFXShaderConstHandle* handle, const AlignedArray& fv); virtual void set(GFXShaderConstHandle* handle, const AlignedArray& fv); virtual void set(GFXShaderConstHandle* handle, const MatrixF& mat, const GFXShaderConstType matType = GFXSCT_Float4x4); - virtual void set(GFXShaderConstHandle* handle, const MatrixF* mat, const U32 arraySize, const GFXShaderConstType matrixType = GFXSCT_Float4x4); + virtual void set(GFXShaderConstHandle* handle, const MatrixF* mat, const U32 arraySize, const GFXShaderConstType matrixType = GFXSCT_Float4x4); // GFXResource virtual const String describeSelf() const; @@ -149,12 +149,12 @@ private: friend class GFXGLShader; U8* mBuffer; WeakRefPtr mShader; - + template void internalSet(GFXShaderConstHandle* handle, const ConstType& param); - + template void internalSet(GFXShaderConstHandle* handle, const AlignedArray& fv); }; -#endif // _GFXGLSHADER_H_ \ No newline at end of file +#endif // _GFXGLSHADER_H_ From 39c2cc09fcc35f25db96a17f8eebdc1318cd8678 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Wed, 6 Mar 2024 14:02:30 +0000 Subject: [PATCH 38/53] Update gfxGLShader.h forgot to save the file... --- Engine/source/gfx/gl/gfxGLShader.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Engine/source/gfx/gl/gfxGLShader.h b/Engine/source/gfx/gl/gfxGLShader.h index a3664d4b1..1c88a95f3 100644 --- a/Engine/source/gfx/gl/gfxGLShader.h +++ b/Engine/source/gfx/gl/gfxGLShader.h @@ -93,6 +93,7 @@ protected: /// @{ GLuint mVertexShader; GLuint mPixelShader; + GLuint mGeometryShader; GLuint mProgram; /// @} From c9d70de609a699ec923f12864247f4ed9fa70487 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Wed, 6 Mar 2024 17:27:18 +0000 Subject: [PATCH 39/53] extra draw gui add the extra functions for drawing gui elements RoundedRectangle: All draw rect functions now pass through roundedRectangle which uses a shader and can draw borders, and rounds the corners Draw thick line: draws a line thicker than 1 pixel, uses a geometry shader to do this Draw Circle: Draws a circle with a border parameter. --- Engine/source/gfx/gfxDrawUtil.cpp | 347 +++++++++++++----- Engine/source/gfx/gfxDrawUtil.h | 82 +++-- .../gui/shaderEditor/guiShaderEditor.cpp | 61 +-- .../gui/shaderEditor/nodes/shaderNode.cpp | 20 +- .../rendering/scripts/gfxData/shaders.tscript | 28 ++ .../shaders/fixedFunction/circleP.hlsl | 66 ++++ .../fixedFunction/roundedRectangleP.hlsl | 109 ++++++ .../shaders/fixedFunction/thickLineG.hlsl | 77 ++++ .../shaders/fixedFunction/thickLineP.hlsl | 34 ++ 9 files changed, 654 insertions(+), 170 deletions(-) create mode 100644 Templates/BaseGame/game/core/rendering/shaders/fixedFunction/circleP.hlsl create mode 100644 Templates/BaseGame/game/core/rendering/shaders/fixedFunction/roundedRectangleP.hlsl create mode 100644 Templates/BaseGame/game/core/rendering/shaders/fixedFunction/thickLineG.hlsl create mode 100644 Templates/BaseGame/game/core/rendering/shaders/fixedFunction/thickLineP.hlsl diff --git a/Engine/source/gfx/gfxDrawUtil.cpp b/Engine/source/gfx/gfxDrawUtil.cpp index 1dd9f5fca..a683c56f7 100644 --- a/Engine/source/gfx/gfxDrawUtil.cpp +++ b/Engine/source/gfx/gfxDrawUtil.cpp @@ -34,7 +34,7 @@ #include "gfx/gfxPrimitiveBuffer.h" #include "gfx/primBuilder.h" #include "gfx/gfxDebugEvent.h" - +#include "materials/shaderData.h" #include "math/mPolyhedron.impl.h" @@ -45,7 +45,7 @@ GFXDrawUtil::GFXDrawUtil( GFXDevice * d) mTextAnchorColor.set(0xFF, 0xFF, 0xFF, 0xFF); mFontRenderBatcher = new FontRenderBatcher(); - _setupStateBlocks(); + _setupStateBlocks(); } GFXDrawUtil::~GFXDrawUtil() @@ -90,6 +90,33 @@ void GFXDrawUtil::_setupStateBlocks() rectFill.setZReadWrite(false); rectFill.setBlend(true, GFXBlendSrcAlpha, GFXBlendInvSrcAlpha); mRectFillSB = mDevice->createStateBlock(rectFill); + + // Find ShaderData + ShaderData* shaderData; + mRoundRectangleShader = Sim::findObject("RoundedRectangleGUI", shaderData) ? shaderData->getShader() : NULL; + if (!mRoundRectangleShader) + { + Con::errorf("GFXDrawUtil - could not find Rounded Rectangle shader"); + } + // Create ShaderConstBuffer and Handles + mRoundRectangleShaderConsts = mRoundRectangleShader->allocConstBuffer(); + + mCircleShader = Sim::findObject("CircularGUI", shaderData) ? shaderData->getShader() : NULL; + if (!mCircleShader) + { + Con::errorf("GFXDrawUtil - could not find circle shader"); + } + // Create ShaderConstBuffer and Handles + mCircleShaderConsts = mCircleShader->allocConstBuffer(); + + mThickLineShader = Sim::findObject("ThickLineGUI", shaderData) ? shaderData->getShader() : NULL; + if (!mThickLineShader) + { + Con::errorf("GFXDrawUtil - could not find Thick line shader"); + } + // Create ShaderConstBuffer and Handles + mThickLineShaderConsts = mThickLineShader->allocConstBuffer(); + } //----------------------------------------------------------------------------- @@ -118,13 +145,13 @@ void GFXDrawUtil::setTextAnchorColor( const ColorI &ancColor ) //----------------------------------------------------------------------------- // Draw Text //----------------------------------------------------------------------------- -U32 GFXDrawUtil::drawText( GFont *font, const Point2I &ptDraw, const UTF16 *in_string, +U32 GFXDrawUtil::drawText( GFont *font, const Point2I &ptDraw, const UTF16 *in_string, const ColorI *colorTable, const U32 maxColorIndex, F32 rot ) { return drawTextN( font, ptDraw, in_string, dStrlen(in_string), colorTable, maxColorIndex, rot ); } -U32 GFXDrawUtil::drawText( GFont *font, const Point2I &ptDraw, const UTF8 *in_string, +U32 GFXDrawUtil::drawText( GFont *font, const Point2I &ptDraw, const UTF8 *in_string, const ColorI *colorTable, const U32 maxColorIndex, F32 rot ) { return drawTextN( font, ptDraw, in_string, dStrlen(in_string), colorTable, maxColorIndex, rot ); @@ -154,7 +181,7 @@ U32 GFXDrawUtil::drawTextN( GFont *font, const Point2I &ptDraw, const UTF8 *in_s return drawTextN( font, ptDraw, ubuf, n, colorTable, maxColorIndex, rot ); } -U32 GFXDrawUtil::drawTextN( GFont *font, const Point2I &ptDraw, const UTF16 *in_string, +U32 GFXDrawUtil::drawTextN( GFont *font, const Point2I &ptDraw, const UTF16 *in_string, U32 n, const ColorI *colorTable, const U32 maxColorIndex, F32 rot ) { // return on zero length strings @@ -178,11 +205,11 @@ U32 GFXDrawUtil::drawTextN( GFont *font, const Point2I &ptDraw, const UTF16 *in_ S32 ptX = 0; - // Queue everything for render. + // Queue everything for render. mFontRenderBatcher->init(font, n); U32 i; - UTF16 c; + UTF16 c; for (i = 0, c = in_string[i]; i < n && in_string[i]; i++, c = in_string[i]) { switch(c) @@ -193,25 +220,25 @@ U32 GFXDrawUtil::drawTextN( GFont *font, const Point2I &ptDraw, const UTF16 *in_ case 14: { // Color code - if (colorTable) + if (colorTable) { - static U8 remap[15] = - { + static U8 remap[15] = + { 0x0, // 0 special null terminator 0x0, // 1 ascii start-of-heading?? - 0x1, - 0x2, - 0x3, - 0x4, - 0x5, - 0x6, + 0x1, + 0x2, + 0x3, + 0x4, + 0x5, + 0x6, 0x0, // 8 special backspace 0x0, // 9 special tab 0x0, // a special \n - 0x7, + 0x7, 0x8, 0x0, // a special \r - 0x9 + 0x9 }; U8 remapped = remap[c]; @@ -256,7 +283,7 @@ U32 GFXDrawUtil::drawTextN( GFont *font, const Point2I &ptDraw, const UTF16 *in_ } // Tab character - case dT('\t'): + case dT('\t'): { if ( tabci == NULL ) tabci = &(font->getCharInfo( dT(' ') )); @@ -272,7 +299,7 @@ U32 GFXDrawUtil::drawTextN( GFont *font, const Point2I &ptDraw, const UTF16 *in_ // Don't draw invalid characters. default: { - if( !font->isValidChar( c ) ) + if( !font->isValidChar( c ) ) continue; } } @@ -354,7 +381,7 @@ void GFXDrawUtil::drawBitmapStretchSR( GFXTextureObject* texture, const RectF &d { // Sanity if no texture is specified. if(!texture) - return; + return; GFXVertexBufferHandle verts(mDevice, 4, GFXBufferTypeVolatile ); verts.lock(); @@ -369,13 +396,13 @@ void GFXDrawUtil::drawBitmapStretchSR( GFXTextureObject* texture, const RectF &d F32 screenTop = dstRect.point.y; F32 screenBottom = (dstRect.point.y + dstRect.extent.y); - if( in_flip & GFXBitmapFlip_X ) + if( in_flip & GFXBitmapFlip_X ) { F32 temp = texLeft; texLeft = texRight; texRight = temp; } - if( in_flip & GFXBitmapFlip_Y ) + if( in_flip & GFXBitmapFlip_Y ) { F32 temp = texTop; texTop = texBottom; @@ -435,7 +462,7 @@ void GFXDrawUtil::drawBitmapStretchSR( GFXTextureObject* texture, const RectF &d AssertFatal(false, "No GFXDrawUtil state block defined for this filter type!"); mDevice->setStateBlock(mBitmapStretchSB); break; - } + } mDevice->setTexture( 0, texture ); mDevice->setupGenericShaders( GFXDevice::GSModColorTexture ); @@ -445,7 +472,7 @@ void GFXDrawUtil::drawBitmapStretchSR( GFXTextureObject* texture, const RectF &d //----------------------------------------------------------------------------- // Draw Rectangle //----------------------------------------------------------------------------- -void GFXDrawUtil::drawRect( const Point2I &upperLeft, const Point2I &lowerRight, const ColorI &color ) +void GFXDrawUtil::drawRect( const Point2I &upperLeft, const Point2I &lowerRight, const ColorI &color ) { drawRect( Point2F((F32)upperLeft.x,(F32)upperLeft.y),Point2F((F32)lowerRight.x,(F32)lowerRight.y),color); } @@ -513,57 +540,94 @@ void GFXDrawUtil::drawRect( const Point2F &upperLeft, const Point2F &lowerRight, //----------------------------------------------------------------------------- // Draw Rectangle Fill //----------------------------------------------------------------------------- -void GFXDrawUtil::drawRectFill( const RectF &rect, const ColorI &color ) +void GFXDrawUtil::drawRectFill(const RectF& rect, const ColorI& color, const F32& borderSize, const ColorI& borderColor) { - drawRectFill(rect.point, Point2F(rect.extent.x + rect.point.x - 1, rect.extent.y + rect.point.y - 1), color ); + drawRoundedRect(0.0f, rect.point, Point2F(rect.extent.x + rect.point.x - 1, rect.extent.y + rect.point.y - 1), color, borderSize, borderColor); } -void GFXDrawUtil::drawRectFill( const Point2I &upperLeft, const Point2I &lowerRight, const ColorI &color ) -{ - drawRectFill(Point2F((F32)upperLeft.x, (F32)upperLeft.y), Point2F((F32)lowerRight.x, (F32)lowerRight.y), color); +void GFXDrawUtil::drawRectFill(const Point2I& upperLeft, const Point2I& lowerRight, const ColorI& color, const F32& borderSize, const ColorI& borderColor) +{ + drawRoundedRect(0.0f, Point2F((F32)upperLeft.x, (F32)upperLeft.y), Point2F((F32)lowerRight.x, (F32)lowerRight.y), color, borderSize, borderColor); } -void GFXDrawUtil::drawRectFill( const RectI &rect, const ColorI &color ) +void GFXDrawUtil::drawRectFill(const RectI& rect, const ColorI& color, const F32& borderSize, const ColorI& borderColor) { - drawRectFill(rect.point, Point2I(rect.extent.x + rect.point.x - 1, rect.extent.y + rect.point.y - 1), color ); + drawRoundedRect(0.0f, rect.point, Point2I(rect.extent.x + rect.point.x - 1, rect.extent.y + rect.point.y - 1), color, borderSize, borderColor); } -void GFXDrawUtil::drawRectFill( const Point2F &upperLeft, const Point2F &lowerRight, const ColorI &color ) +void GFXDrawUtil::drawRectFill(const Point2F& upperLeft, const Point2F& lowerRight, const ColorI& color, const F32& borderSize,const ColorI& borderColor) +{ + // draw a rounded rect with 0 radiuse. + drawRoundedRect(0.0f, upperLeft, lowerRight, color, borderSize, borderColor); +} + +void GFXDrawUtil::drawRoundedRect(const F32& cornerRadius, const RectI& rect, const ColorI& color, const F32& borderSize, const ColorI& borderColor) +{ + drawRoundedRect(cornerRadius, rect.point, Point2I(rect.extent.x + rect.point.x - 1, rect.extent.y + rect.point.y - 1), color, borderSize, borderColor); +} + +void GFXDrawUtil::drawRoundedRect(const F32& cornerRadius, const Point2I& upperLeft, const Point2I& lowerRight, const ColorI& color, const F32& borderSize, const ColorI& borderColor) +{ + drawRoundedRect(cornerRadius, Point2F((F32)upperLeft.x, (F32)upperLeft.y), Point2F((F32)lowerRight.x, (F32)lowerRight.y), color, borderSize, borderColor); +} + +void GFXDrawUtil::drawRoundedRect(const F32& cornerRadius, + const Point2F& upperLeft, + const Point2F& lowerRight, + const ColorI& color, + const F32& borderSize, + const ColorI& borderColor) { - // - // Convert Box a----------x - // | | - // x----------b - // Into Quad - // v0---------v1 - // | a x | - // | | - // | x b | - // v2---------v3 - // // NorthWest and NorthEast facing offset vectors - Point2F nw(-0.5,-0.5); /* \ */ - Point2F ne(0.5,-0.5); /* / */ + Point2F nw(-0.5, -0.5); /* \ */ + Point2F ne(0.5, -0.5); /* / */ GFXVertexBufferHandle verts(mDevice, 4, GFXBufferTypeVolatile); verts.lock(); F32 ulOffset = 0.5f - mDevice->getFillConventionOffset(); - - verts[0].point.set( upperLeft.x+nw.x + ulOffset, upperLeft.y+nw.y + ulOffset, 0.0f ); - verts[1].point.set( lowerRight.x + ne.x + ulOffset, upperLeft.y + ne.y + ulOffset, 0.0f); - verts[2].point.set( upperLeft.x - ne.x + ulOffset, lowerRight.y - ne.y + ulOffset, 0.0f); - verts[3].point.set( lowerRight.x - nw.x + ulOffset, lowerRight.y - nw.y + ulOffset, 0.0f); + + verts[0].point.set(upperLeft.x + nw.x + ulOffset, upperLeft.y + nw.y + ulOffset, 0.0f); + verts[1].point.set(lowerRight.x + ne.x + ulOffset, upperLeft.y + ne.y + ulOffset, 0.0f); + verts[2].point.set(upperLeft.x - ne.x + ulOffset, lowerRight.y - ne.y + ulOffset, 0.0f); + verts[3].point.set(lowerRight.x - nw.x + ulOffset, lowerRight.y - nw.y + ulOffset, 0.0f); for (S32 i = 0; i < 4; i++) verts[i].color = color; verts.unlock(); + mDevice->setVertexBuffer(verts); mDevice->setStateBlock(mRectFillSB); - mDevice->setVertexBuffer( verts ); - mDevice->setupGenericShaders(); - mDevice->drawPrimitive( GFXTriangleStrip, 0, 2 ); + + Point2F topLeftCorner(upperLeft.x + nw.x + ulOffset, upperLeft.y + nw.y + ulOffset); + Point2F bottomRightCorner(lowerRight.x - nw.x + ulOffset, lowerRight.y - nw.y + ulOffset); + + /*mDevice->setupGenericShaders();*/ + GFX->setShader(mRoundRectangleShader); + GFX->setShaderConstBuffer(mRoundRectangleShaderConsts); + + MatrixF tempMatrix = GFX->getProjectionMatrix() * GFX->getViewMatrix() * GFX->getWorldMatrix(); + Point2F size((F32)(bottomRightCorner.x - topLeftCorner.x), (F32)(bottomRightCorner.y - topLeftCorner.y)); + + F32 minExtent = mMin(size.x, size.y); + + F32 radius = cornerRadius; + if ((minExtent * 0.5) < radius) + { + radius = mClampF(radius, 0.0f, (minExtent * 0.5)); + } + + mRoundRectangleShaderConsts->set(mRoundRectangleShader->getShaderConstHandle("$modelView"), tempMatrix, GFXSCT_Float4x4); + mRoundRectangleShaderConsts->setSafe(mRoundRectangleShader->getShaderConstHandle("$radius"), radius); + mRoundRectangleShaderConsts->setSafe(mRoundRectangleShader->getShaderConstHandle("$sizeUni"), size); + mRoundRectangleShaderConsts->setSafe(mRoundRectangleShader->getShaderConstHandle("$borderSize"), borderSize); + mRoundRectangleShaderConsts->setSafe(mRoundRectangleShader->getShaderConstHandle("$borderCol"), borderColor); + + Point2F rectCenter((F32)(topLeftCorner.x + (size.x / 2.0)), (F32)(topLeftCorner.y + (size.y / 2.0))); + mRoundRectangleShaderConsts->setSafe(mRoundRectangleShader->getShaderConstHandle("$rectCenter"), rectCenter); + + mDevice->drawPrimitive(GFXTriangleStrip, 0, 2); } void GFXDrawUtil::draw2DSquare( const Point2F &screenPoint, F32 width, F32 spinAngle ) @@ -608,7 +672,73 @@ void GFXDrawUtil::draw2DSquare( const Point2F &screenPoint, F32 width, F32 spinA } //----------------------------------------------------------------------------- -// Draw Line +// Draw Circle : FILL +//----------------------------------------------------------------------------- +void GFXDrawUtil::drawCircleFill(const RectI& rect, const ColorI& color, F32 radius, const F32& borderSize, const ColorI& borderColor) +{ + drawCircleFill(rect.point, Point2I(rect.extent.x + rect.point.x - 1, rect.extent.y + rect.point.y - 1), color, radius, borderSize, borderColor); +} + +void GFXDrawUtil::drawCircleFill(const Point2I& upperLeft, const Point2I& lowerRight, const ColorI& color, F32 radius, const F32& borderSize, const ColorI& borderColor) +{ + drawCircleFill(Point2F((F32)upperLeft.x, (F32)upperLeft.y), Point2F((F32)lowerRight.x, (F32)lowerRight.y), color, radius, borderSize, borderColor); +} + +void GFXDrawUtil::drawCircleFill(const Point2F& upperLeft, const Point2F& lowerRight, const ColorI& color, F32 radius, const F32& borderSize, const ColorI& borderColor) +{ + // NorthWest and NorthEast facing offset vectors + Point2F nw(-0.5, -0.5); /* \ */ + Point2F ne(0.5, -0.5); /* / */ + + GFXVertexBufferHandle verts(mDevice, 4, GFXBufferTypeVolatile); + verts.lock(); + + F32 ulOffset = 0.5f - mDevice->getFillConventionOffset(); + + verts[0].point.set(upperLeft.x + nw.x + ulOffset, upperLeft.y + nw.y + ulOffset, 0.0f); + verts[1].point.set(lowerRight.x + ne.x + ulOffset, upperLeft.y + ne.y + ulOffset, 0.0f); + verts[2].point.set(upperLeft.x - ne.x + ulOffset, lowerRight.y - ne.y + ulOffset, 0.0f); + verts[3].point.set(lowerRight.x - nw.x + ulOffset, lowerRight.y - nw.y + ulOffset, 0.0f); + for (S32 i = 0; i < 4; i++) + verts[i].color = color; + + verts.unlock(); + mDevice->setVertexBuffer(verts); + + mDevice->setStateBlock(mRectFillSB); + + Point2F topLeftCorner(upperLeft.x + nw.x + ulOffset, upperLeft.y + nw.y + ulOffset); + Point2F bottomRightCorner(lowerRight.x - nw.x + ulOffset, lowerRight.y - nw.y + ulOffset); + + /*mDevice->setupGenericShaders();*/ + GFX->setShader(mCircleShader); + GFX->setShaderConstBuffer(mCircleShaderConsts); + + MatrixF tempMatrix = GFX->getProjectionMatrix() * GFX->getViewMatrix() * GFX->getWorldMatrix(); + Point2F size((F32)(bottomRightCorner.x - topLeftCorner.x), (F32)(bottomRightCorner.y - topLeftCorner.y)); + + Point2F rectCenter((F32)(topLeftCorner.x + (size.x / 2.0)), (F32)(topLeftCorner.y + (size.y / 2.0))); + mCircleShaderConsts->setSafe(mCircleShader->getShaderConstHandle("$rectCenter"), rectCenter); + + F32 minExtent = mMin(size.x, size.y); + F32 shaderRadius = radius; + + if ((minExtent * 0.5) < shaderRadius) + { + shaderRadius = mClampF(radius, 0.0f, (minExtent * 0.5)); + } + + mCircleShaderConsts->set(mCircleShader->getShaderConstHandle("$modelView"), tempMatrix, GFXSCT_Float4x4); + mCircleShaderConsts->setSafe(mCircleShader->getShaderConstHandle("$radius"), shaderRadius); + mCircleShaderConsts->setSafe(mCircleShader->getShaderConstHandle("$sizeUni"), size); + mCircleShaderConsts->setSafe(mCircleShader->getShaderConstHandle("$borderSize"), borderSize); + mCircleShaderConsts->setSafe(mCircleShader->getShaderConstHandle("$borderCol"), borderColor); + + mDevice->drawPrimitive(GFXTriangleStrip, 0, 2); +} + +//----------------------------------------------------------------------------- +// Draw Lines : Single Pixel //----------------------------------------------------------------------------- void GFXDrawUtil::drawLine( const Point3F &startPt, const Point3F &endPt, const ColorI &color ) { @@ -648,6 +778,55 @@ void GFXDrawUtil::drawLine( F32 x1, F32 y1, F32 z1, F32 x2, F32 y2, F32 z2, cons mDevice->drawPrimitive( GFXLineList, 0, 1 ); } +//----------------------------------------------------------------------------- +// Draw Lines : Thick +//----------------------------------------------------------------------------- +void GFXDrawUtil::drawThickLine(const Point2I& startPt, const Point2I& endPt, const ColorI& color, const F32& thickness) +{ + drawThickLine(startPt.x, startPt.y, 0.0f, endPt.x, endPt.y, 0.0f, color, thickness); +} + +void GFXDrawUtil::drawThickLine(const Point2F& startPt, const Point2F& endPt, const ColorI& color, const F32& thickness) +{ + drawThickLine(startPt.x, startPt.y, 0.0f, endPt.x, endPt.y, 0.0f, color, thickness); +} + +void GFXDrawUtil::drawThickLine(F32 x1, F32 y1, F32 z1, F32 x2, F32 y2, F32 z2, const ColorI& color, const F32& thickness) +{ + // less than 2 just draw an ordinary line... why you ever here.... + if (thickness < 2.0f) + { + drawLine(x1, y1, z1, x2, y2, z2, color); + return; + } + + GFXVertexBufferHandle verts(mDevice, 2, GFXBufferTypeVolatile); + verts.lock(); + + verts[0].point.set(x1, y1, z1); + verts[1].point.set(x2, y2, z2); + verts[0].color = color; + verts[1].color = color; + + verts.unlock(); + + mDevice->setVertexBuffer(verts); + mDevice->setStateBlock(mRectFillSB); + GFX->setShader(mThickLineShader); + GFX->setShaderConstBuffer(mThickLineShaderConsts); + + MatrixF tempMatrix = GFX->getProjectionMatrix() * GFX->getViewMatrix() * GFX->getWorldMatrix(); + mThickLineShaderConsts->set(mThickLineShader->getShaderConstHandle("$modelView"), tempMatrix, GFXSCT_Float4x4); + mThickLineShaderConsts->setSafe(mThickLineShader->getShaderConstHandle("$thickness"), thickness); + + const Point2I& resolution = GFX->getActiveRenderTarget()->getSize(); + Point2F TargetSize(1.0 / (F32)resolution.x, 1.0 / (F32)resolution.y); + + mThickLineShaderConsts->setSafe(mThickLineShader->getShaderConstHandle("$oneOverViewport"), TargetSize); + + mDevice->drawPrimitive(GFXLineList, 0, 1); +} + //----------------------------------------------------------------------------- // 3D World Draw Misc //----------------------------------------------------------------------------- @@ -713,13 +892,13 @@ void GFXDrawUtil::drawSphere( const GFXStateBlockDesc &desc, F32 radius, const P //----------------------------------------------------------------------------- -static const Point3F cubePoints[8] = +static const Point3F cubePoints[8] = { Point3F(-1, -1, -1), Point3F(-1, -1, 1), Point3F(-1, 1, -1), Point3F(-1, 1, 1), Point3F( 1, -1, -1), Point3F( 1, -1, 1), Point3F( 1, 1, -1), Point3F( 1, 1, 1) }; -static const U32 cubeFaces[6][4] = +static const U32 cubeFaces[6][4] = { { 0, 4, 6, 2 }, { 0, 2, 3, 1 }, { 0, 1, 5, 4 }, { 3, 2, 6, 7 }, { 7, 6, 4, 5 }, { 3, 7, 5, 1 } @@ -812,7 +991,7 @@ void GFXDrawUtil::drawPolygon( const GFXStateBlockDesc& desc, const Point3F* poi for( U32 i = 0; i < numPoints; ++ i ) xfm->mulP( verts[ i ].point ); } - + if( isWireframe ) { verts[ numVerts - 1 ].point = verts[ 0 ].point; @@ -899,7 +1078,7 @@ void GFXDrawUtil::_drawSolidCube( const GFXStateBlockDesc &desc, const Point3F & for(S32 i = 0; i < 6; i++) { idx = cubeFaces[i][0]; - verts[vertexIndex].point = cubePoints[idx] * halfSize; + verts[vertexIndex].point = cubePoints[idx] * halfSize; verts[vertexIndex].color = color; vertexIndex++; @@ -1113,10 +1292,10 @@ void GFXDrawUtil::drawObjectBox( const GFXStateBlockDesc &desc, const Point3F &s cubePts[i] = cubePoints[i]/2; } - // 8 corner points of the box + // 8 corner points of the box for ( U32 i = 0; i < 8; i++ ) { - //const Point3F &start = cubePoints[i]; + //const Point3F &start = cubePoints[i]; // 3 lines per corner point for ( U32 j = 0; j < 3; j++ ) @@ -1128,7 +1307,7 @@ void GFXDrawUtil::drawObjectBox( const GFXStateBlockDesc &desc, const Point3F &s scaledObjMat.mulP(start); PrimBuild::vertex3fv(start); scaledObjMat.mulP(end); - PrimBuild::vertex3fv(end); + PrimBuild::vertex3fv(end); } } @@ -1164,10 +1343,10 @@ void GFXDrawUtil::drawCapsule( const GFXStateBlockDesc &desc, const Point3F &cen } void GFXDrawUtil::_drawSolidCapsule( const GFXStateBlockDesc &desc, const Point3F ¢er, F32 radius, F32 height, const ColorI &color, const MatrixF *xfm ) -{ +{ MatrixF mat; if ( xfm ) - mat = *xfm; + mat = *xfm; else mat = MatrixF::Identity; @@ -1176,7 +1355,7 @@ void GFXDrawUtil::_drawSolidCapsule( const GFXStateBlockDesc &desc, const Point3 verts.lock(); for (S32 i=0; i 0 ) vSteps = size.y / step.y + 0.5 + 1; - + if( uSteps <= 1 || vSteps <= 1 ) return; - + const U32 numVertices = uSteps * 2 + vSteps * 2; const U32 numLines = uSteps + vSteps; - + Point3F origin; switch( plane ) { @@ -1552,14 +1731,14 @@ void GFXDrawUtil::drawPlaneGrid( const GFXStateBlockDesc &desc, const Point3F &p verts[vertCount].point = Point3F( start + step.x * i, origin.y + size.y, origin.z ); else verts[vertCount].point = Point3F( start + step.x * i, origin.y, origin.z + size.y ); - + verts[vertCount].color = color; ++vertCount; } } if( plane == PlaneXY || plane == PlaneYZ ) - { + { U32 num; F32 stp; if( plane == PlaneXY ) @@ -1574,7 +1753,7 @@ void GFXDrawUtil::drawPlaneGrid( const GFXStateBlockDesc &desc, const Point3F &p } F32 start = mFloor( origin.y / stp + 0.5f ) * stp; - + for ( U32 i = 0; i < num; i++ ) { verts[vertCount].point = Point3F( origin.x, start + stp * i, origin.z ); @@ -1585,7 +1764,7 @@ void GFXDrawUtil::drawPlaneGrid( const GFXStateBlockDesc &desc, const Point3F &p verts[vertCount].point = Point3F( origin.x + size.x, start + stp * i, origin.z ); else verts[vertCount].point = Point3F( origin.x, start + stp * i, origin.z + size.x ); - + verts[vertCount].color = color; ++vertCount; } @@ -1604,7 +1783,7 @@ void GFXDrawUtil::drawPlaneGrid( const GFXStateBlockDesc &desc, const Point3F &p verts[vertCount].point = Point3F( origin.x + size.x, origin.y, start + step.y * i ); else verts[vertCount].point = Point3F( origin.x, origin.y + size.x, start + step.y * i ); - + verts[vertCount].color = color; ++vertCount; } @@ -1629,7 +1808,7 @@ void GFXDrawUtil::drawTransform( const GFXStateBlockDesc &desc, const MatrixF &m GFXVertexBufferHandle verts( mDevice, 6, GFXBufferTypeVolatile ); verts.lock(); - const static ColorI defColors[3] = + const static ColorI defColors[3] = { ColorI::RED, ColorI::GREEN, @@ -1655,7 +1834,7 @@ void GFXDrawUtil::drawTransform( const GFXStateBlockDesc &desc, const MatrixF &m { verts[1].point *= *scale; verts[3].point *= *scale; - verts[5].point *= *scale; + verts[5].point *= *scale; } verts.unlock(); diff --git a/Engine/source/gfx/gfxDrawUtil.h b/Engine/source/gfx/gfxDrawUtil.h index 7c74e1d9d..8cb3adb77 100644 --- a/Engine/source/gfx/gfxDrawUtil.h +++ b/Engine/source/gfx/gfxDrawUtil.h @@ -46,22 +46,36 @@ public: ~GFXDrawUtil(); //----------------------------------------------------------------------------- - // Draw Rectangles + // Draw Rectangles : OUTLINE //----------------------------------------------------------------------------- - void drawRect( const Point2F &upperLeft, const Point2F &lowerRight, const ColorI &color ); - void drawRect( const RectF &rect, const ColorI &color ); - void drawRect( const Point2I &upperLeft, const Point2I &lowerRight, const ColorI &color ); - void drawRect( const RectI &rect, const ColorI &color ); - - void drawRectFill( const Point2F &upperL, const Point2F &lowerR, const ColorI &color ); - void drawRectFill( const RectF &rect, const ColorI &color ); - void drawRectFill( const Point2I &upperLeft, const Point2I &lowerRight, const ColorI &color ); - void drawRectFill( const RectI &rect, const ColorI &color ); - - void draw2DSquare( const Point2F &screenPoint, F32 width, F32 spinAngle = 0.0f ); + void drawRect(const Point2F& upperLeft, const Point2F& lowerRight, const ColorI& color); + void drawRect(const RectF& rect, const ColorI& color); + void drawRect(const Point2I& upperLeft, const Point2I& lowerRight, const ColorI& color); + void drawRect(const RectI& rect, const ColorI& color); //----------------------------------------------------------------------------- - // Draw Lines + // Draw Rectangles : FILL + //----------------------------------------------------------------------------- + + void drawRectFill(const Point2F& upperL, const Point2F& lowerR, const ColorI& color, const F32& borderSize = 0.0f, const ColorI& borderColor = ColorI(0, 0, 0, 0)); + void drawRectFill(const RectF& rect, const ColorI& color, const F32& borderSize = 0.0f, const ColorI& borderColor = ColorI(0, 0, 0, 0)); + void drawRectFill(const Point2I& upperLeft, const Point2I& lowerRight, const ColorI& color, const F32& borderSize = 0.0f, const ColorI& borderColor = ColorI(0, 0, 0, 0)); + void drawRectFill(const RectI& rect, const ColorI& color, const F32& borderSize = 0.0f, const ColorI& borderColor = ColorI(0, 0, 0, 0)); + void drawRoundedRect(const F32& cornerRadius, const RectI& rect, const ColorI& color, const F32& borderSize = 0.0f, const ColorI& borderColor = ColorI(0, 0, 0, 0)); + void drawRoundedRect(const F32& cornerRadius, const Point2I& upperLeft, const Point2I& lowerRight, const ColorI& color, const F32& borderSize = 0.0f, const ColorI& borderColor = ColorI(0, 0, 0, 0)); + void drawRoundedRect(const F32& cornerRadius, const Point2F& upperLeft, const Point2F& lowerRight, const ColorI& color, const F32& borderSize = 0.0f, const ColorI& borderColor = ColorI(0, 0, 0, 0)); + + void draw2DSquare(const Point2F& screenPoint, F32 width, F32 spinAngle = 0.0f); + + //----------------------------------------------------------------------------- + // Draw Circle : FILL + //----------------------------------------------------------------------------- + void drawCircleFill(const RectI& rect, const ColorI& color, F32 radius, const F32& borderSize = 0.0f, const ColorI& borderColor = ColorI(0, 0, 0, 0)); + void drawCircleFill(const Point2I& upperLeft, const Point2I& lowerRight, const ColorI& color, F32 radius, const F32& borderSize = 0.0f, const ColorI& borderColor = ColorI(0, 0, 0, 0)); + void drawCircleFill(const Point2F& upperLeft, const Point2F& lowerRight, const ColorI& color, F32 radius, const F32& borderSize = 0.0f, const ColorI& borderColor = ColorI(0, 0, 0, 0)); + + //----------------------------------------------------------------------------- + // Draw Lines : Single Pixel //----------------------------------------------------------------------------- void drawLine( const Point3F &startPt, const Point3F &endPt, const ColorI &color ); void drawLine( const Point2F &startPt, const Point2F &endPt, const ColorI &color ); @@ -69,6 +83,13 @@ public: void drawLine( F32 x1, F32 y1, F32 x2, F32 y2, const ColorI &color ); void drawLine( F32 x1, F32 y1, F32 z1, F32 x2, F32 y2, F32 z2, const ColorI &color ); + //----------------------------------------------------------------------------- + // Draw Lines : Thick + //----------------------------------------------------------------------------- + void drawThickLine(const Point2I& startPt, const Point2I& endPt, const ColorI& color, const F32& thickness); + void drawThickLine(const Point2F& startPt, const Point2F& endPt, const ColorI& color, const F32& thickness); + void drawThickLine(F32 x1, F32 y1, F32 z1, F32 x2, F32 y2, F32 z2, const ColorI& color, const F32& thickness); + //----------------------------------------------------------------------------- // Draw Text //----------------------------------------------------------------------------- @@ -92,7 +113,7 @@ public: //----------------------------------------------------------------------------- // Draw Bitmaps - //----------------------------------------------------------------------------- + //----------------------------------------------------------------------------- void drawBitmap( GFXTextureObject*texture, const Point2F &in_rAt, const GFXBitmapFlip in_flip = GFXBitmapFlip_None, const GFXTextureFilterType filter = GFXTextureFilterPoint , bool in_wrap = true, F32 angle = 0.0f); void drawBitmapSR( GFXTextureObject*texture, const Point2F &in_rAt, const RectF &srcRect, const GFXBitmapFlip in_flip = GFXBitmapFlip_None, const GFXTextureFilterType filter = GFXTextureFilterPoint , bool in_wrap = true, F32 angle = 0.0f); void drawBitmapStretch( GFXTextureObject*texture, const RectF &dstRect, const GFXBitmapFlip in_flip = GFXBitmapFlip_None, const GFXTextureFilterType filter = GFXTextureFilterPoint , bool in_wrap = true, F32 angle = 0.0f); @@ -108,15 +129,15 @@ public: //----------------------------------------------------------------------------- void drawTriangle( const GFXStateBlockDesc &desc, const Point3F &p0, const Point3F &p1, const Point3F &p2, const ColorI &color, const MatrixF *xfm = NULL ); void drawPolygon( const GFXStateBlockDesc& desc, const Point3F* points, U32 numPoints, const ColorI& color, const MatrixF* xfm = NULL ); - void drawCube( const GFXStateBlockDesc &desc, const Point3F &size, const Point3F &pos, const ColorI &color, const MatrixF *xfm = NULL ); - void drawCube( const GFXStateBlockDesc &desc, const Box3F &box, const ColorI &color, const MatrixF *xfm = NULL ); - void drawObjectBox( const GFXStateBlockDesc &desc, const Point3F &size, const Point3F &pos, const MatrixF &objMat, const ColorI &color ); - void drawSphere( const GFXStateBlockDesc &desc, F32 radius, const Point3F &pos, const ColorI &color, bool drawTop = true, bool drawBottom = true, const MatrixF *xfm = NULL ); + void drawCube( const GFXStateBlockDesc &desc, const Point3F &size, const Point3F &pos, const ColorI &color, const MatrixF *xfm = NULL ); + void drawCube( const GFXStateBlockDesc &desc, const Box3F &box, const ColorI &color, const MatrixF *xfm = NULL ); + void drawObjectBox( const GFXStateBlockDesc &desc, const Point3F &size, const Point3F &pos, const MatrixF &objMat, const ColorI &color ); + void drawSphere( const GFXStateBlockDesc &desc, F32 radius, const Point3F &pos, const ColorI &color, bool drawTop = true, bool drawBottom = true, const MatrixF *xfm = NULL ); void drawCapsule( const GFXStateBlockDesc &desc, const Point3F ¢er, F32 radius, F32 height, const ColorI &color, const MatrixF *xfm = NULL ); - void drawCone( const GFXStateBlockDesc &desc, const Point3F &basePnt, const Point3F &tipPnt, F32 baseRadius, const ColorI &color ); - void drawCylinder( const GFXStateBlockDesc &desc, const Point3F &basePnt, const Point3F &tipPnt, F32 baseRadius, const ColorI &color ); + void drawCone( const GFXStateBlockDesc &desc, const Point3F &basePnt, const Point3F &tipPnt, F32 baseRadius, const ColorI &color ); + void drawCylinder( const GFXStateBlockDesc &desc, const Point3F &basePnt, const Point3F &tipPnt, F32 baseRadius, const ColorI &color ); void drawArrow( const GFXStateBlockDesc &desc, const Point3F &start, const Point3F &end, const ColorI &color, F32 baseRad = 0.0f); - void drawFrustum( const Frustum& f, const ColorI &color ); + void drawFrustum( const Frustum& f, const ColorI &color ); /// Draw a solid or wireframe (depending on fill mode of @a desc) polyhedron with the given color. /// @@ -128,7 +149,7 @@ public: /// Draws a solid XY plane centered on the point with the specified dimensions. void drawSolidPlane( const GFXStateBlockDesc &desc, const Point3F &pos, const Point2F &size, const ColorI &color ); - + enum Plane { PlaneXY, @@ -142,7 +163,7 @@ public: /// Draws axis lines representing the passed matrix. /// If scale is NULL axes will be drawn the length they exist within the MatrixF. /// If colors is NULL the default colors are RED, GREEEN, BLUE ( x, y, z ). - void drawTransform( const GFXStateBlockDesc &desc, const MatrixF &mat, const Point3F *scale = NULL, const ColorI colors[3] = NULL ); + void drawTransform( const GFXStateBlockDesc &desc, const MatrixF &mat, const Point3F *scale = NULL, const ColorI colors[3] = NULL ); protected: @@ -174,8 +195,21 @@ protected: GFXStateBlockRef mBitmapStretchWrapSB; GFXStateBlockRef mBitmapStretchWrapLinearSB; GFXStateBlockRef mRectFillSB; - + FontRenderBatcher* mFontRenderBatcher; + + // Expanded shaders + // rounded rectangle. + GFXShaderRef mRoundRectangleShader; + GFXShaderConstBufferRef mRoundRectangleShaderConsts; + + // thick line. + GFXShaderRef mCircleShader; + GFXShaderConstBufferRef mCircleShaderConsts; + + // thick line. + GFXShaderRef mThickLineShader; + GFXShaderConstBufferRef mThickLineShaderConsts; }; #endif // _GFX_GFXDRAWER_H_ diff --git a/Engine/source/gui/shaderEditor/guiShaderEditor.cpp b/Engine/source/gui/shaderEditor/guiShaderEditor.cpp index 334ffe720..549609cb0 100644 --- a/Engine/source/gui/shaderEditor/guiShaderEditor.cpp +++ b/Engine/source/gui/shaderEditor/guiShaderEditor.cpp @@ -134,45 +134,6 @@ void GuiShaderEditor::onPreRender() setUpdate(); } -void GuiShaderEditor::drawThickLine(const Point2I& pt1, const Point2I& pt2, U32 thickness, ColorI col1, ColorI col2) -{ - Point2F dir = Point2F(pt2.x - pt1.x, pt2.y - pt1.y); - if (dir == Point2F::Zero) - return; - - Point2F unitDir = dir / mSqrt(dir.x * dir.x + dir.y * dir.y); - Point2F unitPerp(-unitDir.y, unitDir.x); - Point2F offset = (thickness / 2.0f) * unitPerp; - - GFX->setStateBlock(mDefaultGuiSB); - - Point2F lT = Point2F(pt1.x, pt1.y) + offset; - Point2F lB = Point2F(pt1.x, pt1.y) - offset; - Point2F rT = Point2F(pt2.x, pt2.y) + offset; - Point2F rB = Point2F(pt2.x, pt2.y) - offset; - - - PrimBuild::begin(GFXTriangleStrip, 4); - - // top left. - PrimBuild::color(col1); - PrimBuild::vertex2f(lT.x, lT.y); - - // bottom left. - PrimBuild::color(col1); - PrimBuild::vertex2f(lB.x, lB.y); - - // top right. - PrimBuild::color(col2); - PrimBuild::vertex2f(rT.x, rT.y); - - // bottom right. - PrimBuild::color(col2); - PrimBuild::vertex2f(rB.x, rB.y); - - PrimBuild::end(); -} - void GuiShaderEditor::renderNodes(Point2I offset, const RectI& updateRect) { // Save the current clip rect @@ -224,17 +185,14 @@ void GuiShaderEditor::renderNodes(Point2I offset, const RectI& updateRect) if (node->mSelected) border = mProfile->mBorderColorSEL; - RectI socketRect(pos, Point2I(mNodeSize, mNodeSize)); - drawer->drawRect(socketRect, border); - socketRect.inset(1, 1); - ColorI fill = mProfile->mFillColor; if (hasConnection(input)) { fill = ColorI::WHITE; } - drawer->drawRectFill(socketRect, fill); + RectI socketRect(pos, Point2I(mNodeSize, mNodeSize)); + drawer->drawCircleFill(socketRect, fill, mNodeSize / 2, 2.0f, border); } for (NodeOutput* output : node->mOutputNodes) @@ -246,9 +204,8 @@ void GuiShaderEditor::renderNodes(Point2I offset, const RectI& updateRect) if (node->mSelected) border = mProfile->mBorderColorSEL; - RectI socketRect(pos, Point2I(mNodeSize, mNodeSize)); - drawer->drawRect(socketRect, border); - socketRect.inset(1, 1); + if(node->mSelected) + border = mProfile->mBorderColorSEL; ColorI fill = mProfile->mFillColor; if (hasConnection(output)) @@ -256,7 +213,8 @@ void GuiShaderEditor::renderNodes(Point2I offset, const RectI& updateRect) fill = ColorI::WHITE; } - drawer->drawRectFill(socketRect, fill); + RectI socketRect(pos, Point2I(mNodeSize, mNodeSize)); + drawer->drawCircleFill(socketRect, fill, mNodeSize / 2, 2.0f, border); } } } @@ -292,7 +250,7 @@ void GuiShaderEditor::renderConnections(Point2I offset, const RectI& updateRect) start += Point2I(mNodeSize / 2, mNodeSize / 2); end += Point2I(mNodeSize / 2, mNodeSize / 2); - drawThickLine(start, end, mNodeSize/3); + drawer->drawThickLine(start, end,ColorI(255,255,255,255), (F32)mNodeSize/3); } // Restore the clip rect to what it was at the start @@ -328,11 +286,12 @@ void GuiShaderEditor::onRender(Point2I offset, const RectI& updateRect) RectI sockActive(start, Point2I(mNodeSize, mNodeSize)); start += Point2I(mNodeSize / 2, mNodeSize / 2); - drawThickLine(start, mLastMousePos + offset, mNodeSize/3); + + drawer->drawThickLine(start, mLastMousePos + offset, ColorI(255, 255, 255, 255), (F32)mNodeSize / 3); // draw socket overlay over the top of the line. sockActive.inset(1, 1); - drawer->drawRectFill(sockActive, ColorI(255, 255, 255)); + drawer->drawCircleFill(sockActive, ColorI(255, 255, 255), mNodeSize / 2); } } // Draw selection rectangle last so it is rendered on top. diff --git a/Engine/source/gui/shaderEditor/nodes/shaderNode.cpp b/Engine/source/gui/shaderEditor/nodes/shaderNode.cpp index 40cfceebf..be024db68 100644 --- a/Engine/source/gui/shaderEditor/nodes/shaderNode.cpp +++ b/Engine/source/gui/shaderEditor/nodes/shaderNode.cpp @@ -108,7 +108,13 @@ void GuiShaderNode::renderNode(Point2I offset, const RectI& updateRect, const S3 RectI winRect; winRect.point = offset; winRect.extent = getExtent(); - drawer->drawRectFill(winRect, mProfile->mFillColor); + + ColorI border = mProfile->mBorderColor; + + if (mSelected) + border = mProfile->mBorderColorSEL; + + drawer->drawRoundedRect(15.0f, winRect, mProfile->mFillColor, 3.0f, border); // draw header ColorI header(50, 50, 50, 128); @@ -148,7 +154,7 @@ void GuiShaderNode::renderNode(Point2I offset, const RectI& updateRect, const S3 U32 headerSize = 30; headRect.point = offset; headRect.extent = Point2I(getExtent().x, headerSize); - drawer->drawRectFill(headRect, header); + drawer->drawRoundedRect(15.0f, headRect, header); // draw header text. U32 strWidth = mProfile->mFont->getStrWidth(mTitle.c_str()); @@ -157,14 +163,6 @@ void GuiShaderNode::renderNode(Point2I offset, const RectI& updateRect, const S3 drawer->drawText(mProfile->mFont, headerPos + offset, mTitle); drawer->clearBitmapModulation(); - ColorI border = mProfile->mBorderColor; - - if (mSelected) - border = mProfile->mBorderColorSEL; - - drawer->drawRect(winRect, border); - - if (mInputNodes.size() > 0 || mOutputNodes.size() > 0) { U32 textPadX = nodeSize, textPadY = mProfile->mFont->getFontSize() + (nodeSize / 2); @@ -175,7 +173,7 @@ void GuiShaderNode::renderNode(Point2I offset, const RectI& updateRect, const S3 drawer->drawText(mProfile->mFont, slotPos + offset, input->name); if (input->pos == Point2I::Zero || mPrevNodeSize != nodeSize) - input->pos = Point2I(-(nodeSize / 2), slotPos.y + ((mProfile->mFont->getFontSize() / 2) - (nodeSize / 2))); + input->pos = Point2I(-(nodeSize / 2) + 1, slotPos.y + ((mProfile->mFont->getFontSize() / 2) - (nodeSize / 2))); slotPos.y += textPadY; } diff --git a/Templates/BaseGame/game/core/rendering/scripts/gfxData/shaders.tscript b/Templates/BaseGame/game/core/rendering/scripts/gfxData/shaders.tscript index 6a2981fa9..0b3d1ae47 100644 --- a/Templates/BaseGame/game/core/rendering/scripts/gfxData/shaders.tscript +++ b/Templates/BaseGame/game/core/rendering/scripts/gfxData/shaders.tscript @@ -149,4 +149,32 @@ singleton ShaderData( CubemapSaveShader ) samplerNames[0] = "$cubemapTex"; pixVersion = 3.0; +}; + +//----------------------------------------------------------------------------- +// GUI shaders +//----------------------------------------------------------------------------- +singleton ShaderData( RoundedRectangleGUI ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/fixedFunction/colorV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/fixedFunction/roundedRectangleP.hlsl"; + + pixVersion = 3.0; +}; + +singleton ShaderData( CircularGUI ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/fixedFunction/colorV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/fixedFunction/circleP.hlsl"; + + pixVersion = 3.0; +}; + +singleton ShaderData( ThickLineGUI ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/fixedFunction/colorV.hlsl"; + DXGeometryShaderFile = $Core::CommonShaderPath @ "/fixedFunction/thickLineG.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/fixedFunction/thickLineP.hlsl"; + + pixVersion = 3.0; }; \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/circleP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/circleP.hlsl new file mode 100644 index 000000000..053b6e9ff --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/circleP.hlsl @@ -0,0 +1,66 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "../shaderModel.hlsl" + +struct Conn +{ + float4 HPOS : TORQUE_POSITION; + float4 color : COLOR; +}; + +uniform float2 sizeUni; +uniform float radius; +uniform float2 rectCenter; +uniform float borderSize; +uniform float4 borderCol; + +float circle(float2 p, float radius) +{ + float dist = length(p - float2(0.5,0.5)); + return 1.0 - smoothstep(radius - (radius*0.01), + radius + (radius*0.01), + dot(dist,dist) * 4.0); +} + +float4 main(Conn IN) : TORQUE_TARGET0 +{ + float distance = length(IN.HPOS.xy - rectCenter); + if(distance > radius) + { + discard; + } + + if(distance < radius) + { + if(distance < (radius - borderSize)) + { + return IN.color; + } + else + { + return borderCol; + } + } + + return IN.color; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/roundedRectangleP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/roundedRectangleP.hlsl new file mode 100644 index 000000000..e051574c1 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/roundedRectangleP.hlsl @@ -0,0 +1,109 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "../shaderModel.hlsl" + +struct Conn +{ + float4 HPOS : TORQUE_POSITION; + float4 color : COLOR; +}; + +uniform float2 sizeUni; +uniform float2 rectCenter; +uniform float radius; +uniform float borderSize; +uniform float4 borderCol; + +float RoundedRectSDF(float2 p, float2 size, float radius) +{ + float2 halfSize = size / 2.0; + + // Calculate distance to each side of the rectangle + float2 dist = abs(p) - halfSize + radius; + + // Compute the distance to the rounded corners + float cornerDist = length(max(abs(p) - (halfSize - float2(radius, radius)), 0.0)); + + // Return the minimum distance (negative inside, positive outside) + return min(max(dist.x, dist.y), 0.0) + cornerDist - radius; +} + +float4 main(Conn IN) : TORQUE_TARGET0 +{ + float2 p = IN.HPOS.xy; + float2 halfSize = sizeUni * 0.5; + float halfBorder = borderSize * 0.5; + + p -= rectCenter; + + // Calculate signed distance field for rounded rectangle + float4 fromColor = IN.color; + // alpha + float4 toColor = float4(0.0, 0.0, 0.0, 0.0); + + float cornerRadius = radius; + + // if ((p.y < 0.0 && p.x < 0.0) || // top left corner + // (p.y < 0.0 && p.x > 0.0) || // top right corner + // (p.y > 0.0 && p.x > 0.0) || // bottom right corner. + // (p.y > 0.0 && p.x < 0.0)) // bottom left corner + // { + // cornerRadius = radius; + // } + + if(cornerRadius > 0.0 || halfBorder > 0.0) + { + float sdf = RoundedRectSDF(p, sizeUni, cornerRadius - halfBorder); + + clip(0.01 - sdf); + + if(halfBorder > 0.0) + { + if(sdf < 0.0) + { + // if ((p.y >= -halfSize.y - radius + halfBorder && p.y <= -halfSize.y + radius - halfBorder) || // top border + // (p.y >= halfSize.y - radius + halfBorder && p.y <= halfSize.y + radius - halfBorder) || // bottom border + // (p.x >= -halfSize.x - radius + halfBorder && p.x <= -halfSize.x + radius - halfBorder) || // left border + // (p.x >= halfSize.x - radius + halfBorder && p.x <= halfSize.x + radius - halfBorder) ) { // right border + + // } + + toColor = borderCol; + } + + sdf = abs(sdf) - halfBorder; + + // Apply smoothing to create rounded effect + float blending = smoothstep(1.0, -1.0, sdf); + + return lerp(fromColor, toColor, blending); + } + + float alpha = smoothstep(1.0, 0.0, sdf); + return float4(IN.color.rgb, IN.color.a * alpha); + } + else + { + return IN.color; + } +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/thickLineG.hlsl b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/thickLineG.hlsl new file mode 100644 index 000000000..a7cf3d67a --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/thickLineG.hlsl @@ -0,0 +1,77 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "../shaderModel.hlsl" + +struct Conn +{ + float4 HPOS : TORQUE_POSITION; + float4 color : COLOR; +}; + +struct PSConn +{ + float4 HPOS : TORQUE_POSITION; + float4 color : COLOR; +}; + +uniform float thickness; +uniform float2 oneOverViewport; + +[maxvertexcount(4)] +void main(line Conn lineSegment[2], inout TriangleStream outstream) +{ + // Calculate the direction of the line segment + float2 direction = normalize(lineSegment[1].HPOS.xy - lineSegment[0].HPOS.xy); + + // Calculate perpendicular direction + float2 perpendicular = normalize(float2(-direction.y, direction.x)); + + // Calculate offset for thickness + float2 offset = float2(thickness * oneOverViewport.x, thickness * oneOverViewport.y) * perpendicular; + + // Calculate vertices for the line with thickness + float2 p0 = lineSegment[0].HPOS.xy + offset; + float2 p1 = lineSegment[0].HPOS.xy - offset; + float2 p2 = lineSegment[1].HPOS.xy + offset; + float2 p3 = lineSegment[1].HPOS.xy - offset; + + PSConn output; + + output.HPOS = float4(p0, 0.0f, 1.0f); + output.color = lineSegment[0].color; + outstream.Append(output); + + output.HPOS = float4(p1, 0.0f, 1.0f); + output.color = lineSegment[0].color; + outstream.Append(output); + + output.HPOS = float4(p2, 0.0f, 1.0f); + output.color = lineSegment[1].color; + outstream.Append(output); + + output.HPOS = float4(p3, 0.0f, 1.0f); + output.color = lineSegment[1].color; + outstream.Append(output); + + outstream.RestartStrip(); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/thickLineP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/thickLineP.hlsl new file mode 100644 index 000000000..e2659f777 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/thickLineP.hlsl @@ -0,0 +1,34 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "../shaderModel.hlsl" + +struct PSConn +{ + float4 HPOS : TORQUE_POSITION; + float4 color : COLOR; +}; + +float4 main(PSConn IN) : TORQUE_TARGET0 +{ + return IN.color; +} \ No newline at end of file From 2dc623df7efb8618231259e29b372a9064e1c8c6 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Wed, 6 Mar 2024 19:57:18 +0000 Subject: [PATCH 40/53] material output node material output node added colors denoting node sockets added. this will probably be changed. --- .../gui/shaderEditor/guiShaderEditor.cpp | 20 +++----- .../source/gui/shaderEditor/guiShaderEditor.h | 2 +- .../shaderNode.cpp => guiShaderNode.cpp} | 14 +----- .../{nodes/shaderNode.h => guiShaderNode.h} | 27 ++++++++++- .../shaderEditor/nodes/materialOutputNode.cpp | 47 +++++++++++++++++++ .../shaderEditor/nodes/materialOutputNode.h | 35 ++++++++++++++ 6 files changed, 117 insertions(+), 28 deletions(-) rename Engine/source/gui/shaderEditor/{nodes/shaderNode.cpp => guiShaderNode.cpp} (89%) rename Engine/source/gui/shaderEditor/{nodes/shaderNode.h => guiShaderNode.h} (83%) create mode 100644 Engine/source/gui/shaderEditor/nodes/materialOutputNode.cpp create mode 100644 Engine/source/gui/shaderEditor/nodes/materialOutputNode.h diff --git a/Engine/source/gui/shaderEditor/guiShaderEditor.cpp b/Engine/source/gui/shaderEditor/guiShaderEditor.cpp index 549609cb0..5bd6262a6 100644 --- a/Engine/source/gui/shaderEditor/guiShaderEditor.cpp +++ b/Engine/source/gui/shaderEditor/guiShaderEditor.cpp @@ -22,6 +22,7 @@ #include "platform/platform.h" #include "gui/shaderEditor/guiShaderEditor.h" +#include "gui/shaderEditor/nodes/materialOutputNode.h" #include "core/frameAllocator.h" #include "core/stream/fileStream.h" @@ -61,7 +62,7 @@ GuiShaderEditor::GuiShaderEditor() mTempConnection = NULL; mNodeSize = 10; // test - addNode(new GuiShaderNode()); + addNode(new MaterialOutputNode()); addNode(new GuiShaderNode()); } @@ -180,15 +181,12 @@ void GuiShaderEditor::renderNodes(Point2I offset, const RectI& updateRect) { Point2I pos = node->localToGlobalCoord(input->pos) + offset; - ColorI border = mProfile->mBorderColor; - - if (node->mSelected) - border = mProfile->mBorderColorSEL; + ColorI border = input->col; ColorI fill = mProfile->mFillColor; if (hasConnection(input)) { - fill = ColorI::WHITE; + fill = input->col; } RectI socketRect(pos, Point2I(mNodeSize, mNodeSize)); @@ -199,18 +197,12 @@ void GuiShaderEditor::renderNodes(Point2I offset, const RectI& updateRect) { Point2I pos = node->localToGlobalCoord(output->pos) + offset; - ColorI border = mProfile->mBorderColor; - - if (node->mSelected) - border = mProfile->mBorderColorSEL; - - if(node->mSelected) - border = mProfile->mBorderColorSEL; + ColorI border = output->col; ColorI fill = mProfile->mFillColor; if (hasConnection(output)) { - fill = ColorI::WHITE; + fill = output->col; } RectI socketRect(pos, Point2I(mNodeSize, mNodeSize)); diff --git a/Engine/source/gui/shaderEditor/guiShaderEditor.h b/Engine/source/gui/shaderEditor/guiShaderEditor.h index 0a8f6ccff..4cb7fd5fd 100644 --- a/Engine/source/gui/shaderEditor/guiShaderEditor.h +++ b/Engine/source/gui/shaderEditor/guiShaderEditor.h @@ -34,7 +34,7 @@ #endif #ifndef _SHADERNODE_H_ -#include "gui/shaderEditor/nodes/shaderNode.h" +#include "gui/shaderEditor/guiShaderNode.h" #endif // !_SHADERNODE_H_ struct NodeConnection diff --git a/Engine/source/gui/shaderEditor/nodes/shaderNode.cpp b/Engine/source/gui/shaderEditor/guiShaderNode.cpp similarity index 89% rename from Engine/source/gui/shaderEditor/nodes/shaderNode.cpp rename to Engine/source/gui/shaderEditor/guiShaderNode.cpp index be024db68..fb3e377e4 100644 --- a/Engine/source/gui/shaderEditor/nodes/shaderNode.cpp +++ b/Engine/source/gui/shaderEditor/guiShaderNode.cpp @@ -21,7 +21,7 @@ //----------------------------------------------------------------------------- #include "platform/platform.h" -#include "gui/shaderEditor/nodes/shaderNode.h" +#include "gui/shaderEditor/guiShaderNode.h" #include "gui/core/guiCanvas.h" @@ -48,18 +48,8 @@ GuiShaderNode::GuiShaderNode() if (Sim::findObject("GuiShaderEditorProfile", profile)) setControlProfile(profile); - mInputNodes.push_back(new NodeInput("RGBA", DataDimensions::Dynamic)); - mInputNodes.push_back(new NodeInput("RGBA", DataDimensions::Dynamic)); - mInputNodes.push_back(new NodeInput("RGBA", DataDimensions::Dynamic)); - mInputNodes.push_back(new NodeInput("RGBA", DataDimensions::Dynamic)); - - mOutputNodes.push_back(new NodeOutput("RGBA", DataDimensions::Dynamic)); - mOutputNodes.push_back(new NodeOutput("RGBA", DataDimensions::Dynamic)); - mOutputNodes.push_back(new NodeOutput("RGBA", DataDimensions::Dynamic)); - mOutputNodes.push_back(new NodeOutput("RGBA", DataDimensions::Dynamic)); - // fixed extent for all nodes, only height should be changed - setExtent(210, 35); + setExtent(180, 35); mPrevNodeSize = -1; } diff --git a/Engine/source/gui/shaderEditor/nodes/shaderNode.h b/Engine/source/gui/shaderEditor/guiShaderNode.h similarity index 83% rename from Engine/source/gui/shaderEditor/nodes/shaderNode.h rename to Engine/source/gui/shaderEditor/guiShaderNode.h index cbfd4f701..25f702ee1 100644 --- a/Engine/source/gui/shaderEditor/nodes/shaderNode.h +++ b/Engine/source/gui/shaderEditor/guiShaderNode.h @@ -63,12 +63,37 @@ struct NodeSocket { String name; DataDimensions dimensions; + ColorI col = ColorI::WHITE; NodeSocket() :name(String::EmptyString), dimensions(DataDimensions::Dynamic) {} NodeSocket(String inName, DataDimensions inDim) :name(inName), dimensions(inDim) - {} + { + switch (inDim) + { + case DataDimensions::Dynamic: + col = ColorI(200, 200, 200, 200); + break; + case DataDimensions::Scalar: + col = ColorI(210, 105, 30, 200); + break; + case DataDimensions::Vector2: + col = ColorI(152, 251,152, 200); + break; + case DataDimensions::Vector3: + col = ColorI(127, 255, 212, 200); + break; + case DataDimensions::Vector4: + col = ColorI(100, 149, 237, 200); + break; + case DataDimensions::Mat4x4: + col = ColorI(153, 50, 204, 200); + break; + default: + break; + } + } public: virtual ~NodeSocket() {} diff --git a/Engine/source/gui/shaderEditor/nodes/materialOutputNode.cpp b/Engine/source/gui/shaderEditor/nodes/materialOutputNode.cpp new file mode 100644 index 000000000..c53fc0925 --- /dev/null +++ b/Engine/source/gui/shaderEditor/nodes/materialOutputNode.cpp @@ -0,0 +1,47 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "platform/platform.h" +#include "gui/shaderEditor/nodes/materialOutputNode.h" + +IMPLEMENT_CONOBJECT(MaterialOutputNode); + +ConsoleDocClass(MaterialOutputNode, + "@brief Deferred Material output.\n\n" + "Editor use only.\n\n" + "@internal" +); + +MaterialOutputNode::MaterialOutputNode() + : GuiShaderNode() +{ + mNodeType = NodeTypes::Output; + + mInputNodes.push_back(new NodeInput("Albedo", DataDimensions::Vector3)); + mInputNodes.push_back(new NodeInput("Normal", DataDimensions::Vector3)); + mInputNodes.push_back(new NodeInput("Ambient Occlusion", DataDimensions::Scalar)); + mInputNodes.push_back(new NodeInput("Metallic", DataDimensions::Scalar)); + mInputNodes.push_back(new NodeInput("Roughness", DataDimensions::Scalar)); + mInputNodes.push_back(new NodeInput("Emissive Color", DataDimensions::Vector3)); + mInputNodes.push_back(new NodeInput("Opacity", DataDimensions::Scalar)); + + mTitle = "Standard BRDF"; +} diff --git a/Engine/source/gui/shaderEditor/nodes/materialOutputNode.h b/Engine/source/gui/shaderEditor/nodes/materialOutputNode.h new file mode 100644 index 000000000..a3b496c0a --- /dev/null +++ b/Engine/source/gui/shaderEditor/nodes/materialOutputNode.h @@ -0,0 +1,35 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "gui/shaderEditor/guiShaderNode.h" + +class MaterialOutputNode : public GuiShaderNode +{ + typedef GuiShaderNode Parent; +public: + MaterialOutputNode(); + + // is the parent that all other nodes are derived from. + DECLARE_CONOBJECT(MaterialOutputNode); + DECLARE_CATEGORY("Shader Output"); + DECLARE_DESCRIPTION("Deferred Material output."); +}; From 0d448ad76106e5a37c3516e3103b66c7eb557765 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Thu, 7 Mar 2024 09:47:18 +0000 Subject: [PATCH 41/53] smoothing out results from gui shaders roundedRectangle and circle drawing now smooth out their results --- Engine/source/gfx/gfxDrawUtil.cpp | 5 +++ Engine/source/gfx/gfxDrawUtil.h | 4 +- .../gui/shaderEditor/guiShaderEditor.cpp | 13 +++++-- .../source/gui/shaderEditor/guiShaderNode.h | 12 +++--- .../shaders/fixedFunction/circleP.hlsl | 36 ++++++++--------- .../fixedFunction/roundedRectangleP.hlsl | 39 ++++++++----------- 6 files changed, 57 insertions(+), 52 deletions(-) diff --git a/Engine/source/gfx/gfxDrawUtil.cpp b/Engine/source/gfx/gfxDrawUtil.cpp index a683c56f7..36b921f8a 100644 --- a/Engine/source/gfx/gfxDrawUtil.cpp +++ b/Engine/source/gfx/gfxDrawUtil.cpp @@ -627,6 +627,11 @@ void GFXDrawUtil::drawRoundedRect(const F32& cornerRadius, Point2F rectCenter((F32)(topLeftCorner.x + (size.x / 2.0)), (F32)(topLeftCorner.y + (size.y / 2.0))); mRoundRectangleShaderConsts->setSafe(mRoundRectangleShader->getShaderConstHandle("$rectCenter"), rectCenter); + const Point2I& resolution = GFX->getActiveRenderTarget()->getSize(); + Point2F TargetSize(1.0 / (F32)resolution.x, 1.0 / (F32)resolution.y); + + mRoundRectangleShaderConsts->setSafe(mRoundRectangleShader->getShaderConstHandle("$oneOverViewport"), TargetSize); + mDevice->drawPrimitive(GFXTriangleStrip, 0, 2); } diff --git a/Engine/source/gfx/gfxDrawUtil.h b/Engine/source/gfx/gfxDrawUtil.h index 8cb3adb77..7a641fb64 100644 --- a/Engine/source/gfx/gfxDrawUtil.h +++ b/Engine/source/gfx/gfxDrawUtil.h @@ -31,12 +31,12 @@ #include "math/mPolyhedron.h" #endif - - class FontRenderBatcher; class Frustum; + + /// Helper class containing utility functions for useful drawing routines /// (line, box, rect, billboard, text). class GFXDrawUtil diff --git a/Engine/source/gui/shaderEditor/guiShaderEditor.cpp b/Engine/source/gui/shaderEditor/guiShaderEditor.cpp index 5bd6262a6..54aa11847 100644 --- a/Engine/source/gui/shaderEditor/guiShaderEditor.cpp +++ b/Engine/source/gui/shaderEditor/guiShaderEditor.cpp @@ -271,19 +271,26 @@ void GuiShaderEditor::onRender(Point2I offset, const RectI& updateRect) { // for temp connetion, nodeA is always the first node selected. Point2I start(Point2I::Zero); + ColorI color(ColorI::WHITE); if (mTempConnection->inSocket != NULL) + { start = mTempConnection->nodeA->localToGlobalCoord(mTempConnection->inSocket->pos) + offset; - else if(mTempConnection->outSocket != NULL) + color = mTempConnection->inSocket->col; + } + else if (mTempConnection->outSocket != NULL) + { start = mTempConnection->nodeA->localToGlobalCoord(mTempConnection->outSocket->pos) + offset; + color = mTempConnection->outSocket->col; + } RectI sockActive(start, Point2I(mNodeSize, mNodeSize)); start += Point2I(mNodeSize / 2, mNodeSize / 2); - drawer->drawThickLine(start, mLastMousePos + offset, ColorI(255, 255, 255, 255), (F32)mNodeSize / 3); + drawer->drawThickLine(start, mLastMousePos + offset, color, (F32)mNodeSize / 3); // draw socket overlay over the top of the line. sockActive.inset(1, 1); - drawer->drawCircleFill(sockActive, ColorI(255, 255, 255), mNodeSize / 2); + drawer->drawCircleFill(sockActive, color, mNodeSize / 2); } } // Draw selection rectangle last so it is rendered on top. diff --git a/Engine/source/gui/shaderEditor/guiShaderNode.h b/Engine/source/gui/shaderEditor/guiShaderNode.h index 25f702ee1..0ab409ca9 100644 --- a/Engine/source/gui/shaderEditor/guiShaderNode.h +++ b/Engine/source/gui/shaderEditor/guiShaderNode.h @@ -73,22 +73,22 @@ struct NodeSocket switch (inDim) { case DataDimensions::Dynamic: - col = ColorI(200, 200, 200, 200); + col = ColorI(200, 200, 200, 128); break; case DataDimensions::Scalar: - col = ColorI(210, 105, 30, 200); + col = ColorI(210, 105, 30, 128); break; case DataDimensions::Vector2: - col = ColorI(152, 251,152, 200); + col = ColorI(152, 251,152, 128); break; case DataDimensions::Vector3: - col = ColorI(127, 255, 212, 200); + col = ColorI(127, 255, 212, 128); break; case DataDimensions::Vector4: - col = ColorI(100, 149, 237, 200); + col = ColorI(100, 149, 237, 128); break; case DataDimensions::Mat4x4: - col = ColorI(153, 50, 204, 200); + col = ColorI(153, 50, 204, 128); break; default: break; diff --git a/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/circleP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/circleP.hlsl index 053b6e9ff..08384871b 100644 --- a/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/circleP.hlsl +++ b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/circleP.hlsl @@ -34,33 +34,33 @@ uniform float2 rectCenter; uniform float borderSize; uniform float4 borderCol; -float circle(float2 p, float radius) +float circle(float2 p, float2 center, float r) { - float dist = length(p - float2(0.5,0.5)); - return 1.0 - smoothstep(radius - (radius*0.01), - radius + (radius*0.01), - dot(dist,dist) * 4.0); + return length(p - center); } float4 main(Conn IN) : TORQUE_TARGET0 { - float distance = length(IN.HPOS.xy - rectCenter); - if(distance > radius) - { - discard; - } + float distance = circle(IN.HPOS.xy, rectCenter, radius); + + float4 fromColor = borderCol; + float4 toColor = float4(0.0, 0.0, 0.0, 0.0); if(distance < radius) { - if(distance < (radius - borderSize)) + distance = abs(distance) - radius; + + if(distance < (radius - (borderSize * 0.5))) { - return IN.color; + toColor = IN.color; + distance = abs(distance) - (borderSize * 0.5); } - else - { - return borderCol; - } - } - return IN.color; + float blend = smoothstep(0.0, 1.0, distance); + return lerp(fromColor, toColor, blend); + } + + distance = abs(distance) - radius; + float blend = smoothstep(0.0, 1.0, distance); + return lerp(fromColor, toColor, blend); } \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/roundedRectangleP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/roundedRectangleP.hlsl index e051574c1..a7277e400 100644 --- a/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/roundedRectangleP.hlsl +++ b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/roundedRectangleP.hlsl @@ -30,34 +30,33 @@ struct Conn uniform float2 sizeUni; uniform float2 rectCenter; +uniform float2 oneOverViewport; uniform float radius; uniform float borderSize; uniform float4 borderCol; float RoundedRectSDF(float2 p, float2 size, float radius) { - float2 halfSize = size / 2.0; - // Calculate distance to each side of the rectangle - float2 dist = abs(p) - halfSize + radius; + float2 dist = abs(p) - size + float2(radius, radius); // Compute the distance to the rounded corners - float cornerDist = length(max(abs(p) - (halfSize - float2(radius, radius)), 0.0)); + float cornerDist = length(max(dist, 0.0)); // Return the minimum distance (negative inside, positive outside) - return min(max(dist.x, dist.y), 0.0) + cornerDist - radius; + return min(max(dist.x, dist.y), 0.0) + cornerDist - radius; } float4 main(Conn IN) : TORQUE_TARGET0 { float2 p = IN.HPOS.xy; - float2 halfSize = sizeUni * 0.5; - float halfBorder = borderSize * 0.5; - p -= rectCenter; + float halfBorder = borderSize * 0.5; + float2 halfSize = sizeUni * 0.5; + p -= rectCenter; // Calculate signed distance field for rounded rectangle - float4 fromColor = IN.color; + float4 fromColor = borderCol; // alpha float4 toColor = float4(0.0, 0.0, 0.0, 0.0); @@ -73,9 +72,7 @@ float4 main(Conn IN) : TORQUE_TARGET0 if(cornerRadius > 0.0 || halfBorder > 0.0) { - float sdf = RoundedRectSDF(p, sizeUni, cornerRadius - halfBorder); - - clip(0.01 - sdf); + float sdf = RoundedRectSDF(p, halfSize, cornerRadius - halfBorder); if(halfBorder > 0.0) { @@ -87,20 +84,16 @@ float4 main(Conn IN) : TORQUE_TARGET0 // (p.x >= halfSize.x - radius + halfBorder && p.x <= halfSize.x + radius - halfBorder) ) { // right border // } - - toColor = borderCol; + toColor = IN.color; } - sdf = abs(sdf) - halfBorder; - - // Apply smoothing to create rounded effect - float blending = smoothstep(1.0, -1.0, sdf); - - return lerp(fromColor, toColor, blending); + } + else{ + fromColor = IN.color; } - - float alpha = smoothstep(1.0, 0.0, sdf); - return float4(IN.color.rgb, IN.color.a * alpha); + + float alpha = smoothstep(-1.0, 1.0, sdf); + return lerp(fromColor, toColor, alpha); } else { From dbbd9383e7ada9f736db2ed6a52734faf9629cb7 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Thu, 7 Mar 2024 10:20:06 +0000 Subject: [PATCH 42/53] better rounded rect --- Engine/source/gui/shaderEditor/guiShaderNode.cpp | 2 +- .../shaders/fixedFunction/roundedRectangleP.hlsl | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Engine/source/gui/shaderEditor/guiShaderNode.cpp b/Engine/source/gui/shaderEditor/guiShaderNode.cpp index fb3e377e4..65dea429d 100644 --- a/Engine/source/gui/shaderEditor/guiShaderNode.cpp +++ b/Engine/source/gui/shaderEditor/guiShaderNode.cpp @@ -104,7 +104,7 @@ void GuiShaderNode::renderNode(Point2I offset, const RectI& updateRect, const S3 if (mSelected) border = mProfile->mBorderColorSEL; - drawer->drawRoundedRect(15.0f, winRect, mProfile->mFillColor, 3.0f, border); + drawer->drawRoundedRect(15.0f, winRect, mProfile->mFillColor, 5.0f, border); // draw header ColorI header(50, 50, 50, 128); diff --git a/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/roundedRectangleP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/roundedRectangleP.hlsl index a7277e400..dea3e6bee 100644 --- a/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/roundedRectangleP.hlsl +++ b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/roundedRectangleP.hlsl @@ -85,18 +85,18 @@ float4 main(Conn IN) : TORQUE_TARGET0 // } toColor = IN.color; - } - sdf = abs(sdf) - halfBorder; + } + sdf = abs(sdf) / borderSize; } else{ fromColor = IN.color; - } + } float alpha = smoothstep(-1.0, 1.0, sdf); return lerp(fromColor, toColor, alpha); } else - { + { return IN.color; } } \ No newline at end of file From d9c4269d8b9bf8e1ecfb510613dcab12190f1620 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Thu, 7 Mar 2024 17:22:48 +0000 Subject: [PATCH 43/53] bug fix deleteSelection when an output node had multiple connections only the first one was deleted, needed a new function to return a vector of connections that are now looped and deleted at the end of delete selection. few other minor additions and fixes. --- Engine/source/gfx/gfxDrawUtil.cpp | 2 +- .../gui/shaderEditor/guiShaderEditor.cpp | 52 +++++++++++-------- .../source/gui/shaderEditor/guiShaderEditor.h | 1 + .../shaderEditor/nodes/materialOutputNode.cpp | 10 ++-- .../shaderEditor/nodes/materialOutputNode.h | 10 ++-- .../gui/shaderEditor/nodes/mathNode.cpp | 50 ++++++++++++++++++ .../source/gui/shaderEditor/nodes/mathNode.h | 39 ++++++++++++++ .../fixedFunction/roundedRectangleP.hlsl | 5 +- 8 files changed, 137 insertions(+), 32 deletions(-) create mode 100644 Engine/source/gui/shaderEditor/nodes/mathNode.cpp create mode 100644 Engine/source/gui/shaderEditor/nodes/mathNode.h diff --git a/Engine/source/gfx/gfxDrawUtil.cpp b/Engine/source/gfx/gfxDrawUtil.cpp index 36b921f8a..49de99d5e 100644 --- a/Engine/source/gfx/gfxDrawUtil.cpp +++ b/Engine/source/gfx/gfxDrawUtil.cpp @@ -1294,7 +1294,7 @@ void GFXDrawUtil::drawObjectBox( const GFXStateBlockDesc &desc, const Point3F &s Point3F cubePts[8]; for (U32 i = 0; i < 8; i++) { - cubePts[i] = cubePoints[i]/2; + cubePts[i] = cubePoints[i]/2; } // 8 corner points of the box diff --git a/Engine/source/gui/shaderEditor/guiShaderEditor.cpp b/Engine/source/gui/shaderEditor/guiShaderEditor.cpp index 54aa11847..f5ff22af7 100644 --- a/Engine/source/gui/shaderEditor/guiShaderEditor.cpp +++ b/Engine/source/gui/shaderEditor/guiShaderEditor.cpp @@ -23,6 +23,7 @@ #include "platform/platform.h" #include "gui/shaderEditor/guiShaderEditor.h" #include "gui/shaderEditor/nodes/materialOutputNode.h" +#include "gui/shaderEditor/nodes/mathNode.h" #include "core/frameAllocator.h" #include "core/stream/fileStream.h" @@ -62,7 +63,8 @@ GuiShaderEditor::GuiShaderEditor() mTempConnection = NULL; mNodeSize = 10; // test - addNode(new MaterialOutputNode()); + addNode(new BRDFOutputNode()); + addNode(new MathAddNode()); addNode(new GuiShaderNode()); } @@ -648,31 +650,23 @@ void GuiShaderEditor::deleteSelection() { mTrash->addObject(node); + Vector connVec; for (NodeInput* input : node->mInputNodes) { - NodeConnection* conn; - if (hasConnection(input, conn)) - { - // selecting one node, push it to the front of the mcurrnodes stack so its rendered on top. - Vector< NodeConnection* >::iterator i = T3D::find(mCurrConnections.begin(), mCurrConnections.end(), conn); - if (i != mCurrConnections.end()) - { - mCurrConnections.erase(i); - } - } + hasConnection(input, connVec); } for (NodeOutput* output : node->mOutputNodes) { - NodeConnection* conn; - if (hasConnection(output, conn)) + hasConnection(output, connVec); + } + + for (NodeConnection* conn : connVec) + { + Vector< NodeConnection* >::iterator i = T3D::find(mCurrConnections.begin(), mCurrConnections.end(), conn); + if (i != mCurrConnections.end()) { - // selecting one node, push it to the front of the mcurrnodes stack so its rendered on top. - Vector< NodeConnection* >::iterator i = T3D::find(mCurrConnections.begin(), mCurrConnections.end(), conn); - if (i != mCurrConnections.end()) - { - mCurrConnections.erase(i); - } + mCurrConnections.erase(i); } } @@ -857,7 +851,6 @@ U32 GuiShaderEditor::finishConnection(const Point2I& pt) NodeConnection* conn; if(hasConnection(inNode, conn)) { - // selecting one node, push it to the front of the mcurrnodes stack so its rendered on top. Vector< NodeConnection* >::iterator i = T3D::find(mCurrConnections.begin(), mCurrConnections.end(), conn); if (i != mCurrConnections.end()) { @@ -886,7 +879,6 @@ U32 GuiShaderEditor::finishConnection(const Point2I& pt) NodeConnection* conn; if (hasConnection(mTempConnection->inSocket, conn)) { - // selecting one node, push it to the front of the mcurrnodes stack so its rendered on top. Vector< NodeConnection* >::iterator i = T3D::find(mCurrConnections.begin(), mCurrConnections.end(), conn); if (i != mCurrConnections.end()) { @@ -916,6 +908,22 @@ bool GuiShaderEditor::hasConnection(NodeSocket* inSocket) return false; } +bool GuiShaderEditor::hasConnection(NodeSocket* inSocket, Vector& conn) +{ + bool ret = false; + + for (NodeConnection* con : mCurrConnections) + { + if (con->inSocket == dynamic_cast(inSocket) || con->outSocket == dynamic_cast(inSocket)) + { + conn.push_back(con); + ret = true; + } + } + + return ret; +} + bool GuiShaderEditor::hasConnection(NodeSocket* inSocket, NodeConnection*& conn) { for (NodeConnection* con : mCurrConnections) @@ -924,11 +932,9 @@ bool GuiShaderEditor::hasConnection(NodeSocket* inSocket, NodeConnection*& conn) { if (conn != nullptr) conn = con; - return true; } } - return false; } diff --git a/Engine/source/gui/shaderEditor/guiShaderEditor.h b/Engine/source/gui/shaderEditor/guiShaderEditor.h index 4cb7fd5fd..a853951a4 100644 --- a/Engine/source/gui/shaderEditor/guiShaderEditor.h +++ b/Engine/source/gui/shaderEditor/guiShaderEditor.h @@ -92,6 +92,7 @@ protected: bool findHitSocket(const Point2I& pt); U32 finishConnection(const Point2I& pt); bool hasConnection(NodeSocket* inSocket); + bool hasConnection(NodeSocket* inSocket, Vector& conn); bool hasConnection(NodeSocket* inSocket, NodeConnection*& conn); void findNodesInRect(const RectI& rect, Vector& outResult); diff --git a/Engine/source/gui/shaderEditor/nodes/materialOutputNode.cpp b/Engine/source/gui/shaderEditor/nodes/materialOutputNode.cpp index c53fc0925..a0b4d10c2 100644 --- a/Engine/source/gui/shaderEditor/nodes/materialOutputNode.cpp +++ b/Engine/source/gui/shaderEditor/nodes/materialOutputNode.cpp @@ -22,15 +22,19 @@ #include "platform/platform.h" #include "gui/shaderEditor/nodes/materialOutputNode.h" -IMPLEMENT_CONOBJECT(MaterialOutputNode); +//----------------------------------------------------------------- +// BRDF Output Node. +//----------------------------------------------------------------- -ConsoleDocClass(MaterialOutputNode, +IMPLEMENT_CONOBJECT(BRDFOutputNode); + +ConsoleDocClass(BRDFOutputNode, "@brief Deferred Material output.\n\n" "Editor use only.\n\n" "@internal" ); -MaterialOutputNode::MaterialOutputNode() +BRDFOutputNode::BRDFOutputNode() : GuiShaderNode() { mNodeType = NodeTypes::Output; diff --git a/Engine/source/gui/shaderEditor/nodes/materialOutputNode.h b/Engine/source/gui/shaderEditor/nodes/materialOutputNode.h index a3b496c0a..023fb869e 100644 --- a/Engine/source/gui/shaderEditor/nodes/materialOutputNode.h +++ b/Engine/source/gui/shaderEditor/nodes/materialOutputNode.h @@ -22,14 +22,18 @@ #include "gui/shaderEditor/guiShaderNode.h" -class MaterialOutputNode : public GuiShaderNode +//----------------------------------------------------------------- +// Put all material output nodes here. +//----------------------------------------------------------------- + +class BRDFOutputNode : public GuiShaderNode { typedef GuiShaderNode Parent; public: - MaterialOutputNode(); + BRDFOutputNode(); // is the parent that all other nodes are derived from. - DECLARE_CONOBJECT(MaterialOutputNode); + DECLARE_CONOBJECT(BRDFOutputNode); DECLARE_CATEGORY("Shader Output"); DECLARE_DESCRIPTION("Deferred Material output."); }; diff --git a/Engine/source/gui/shaderEditor/nodes/mathNode.cpp b/Engine/source/gui/shaderEditor/nodes/mathNode.cpp new file mode 100644 index 000000000..ebcf13284 --- /dev/null +++ b/Engine/source/gui/shaderEditor/nodes/mathNode.cpp @@ -0,0 +1,50 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "platform/platform.h" + +#include "gui/shaderEditor/nodes/mathNode.h" + +//----------------------------------------------------------------- +// Math addition Node. +//----------------------------------------------------------------- + +IMPLEMENT_CONOBJECT(MathAddNode); + +ConsoleDocClass(MathAddNode, + "@brief Math addition node.\n\n" + "Editor use only.\n\n" + "@internal" +); + + +MathAddNode::MathAddNode() + : GuiShaderNode() +{ + mNodeType = NodeTypes::MathOperation; + + mInputNodes.push_back(new NodeInput("A", DataDimensions::Dynamic)); + mInputNodes.push_back(new NodeInput("B", DataDimensions::Dynamic)); + + mOutputNodes.push_back(new NodeOutput("Result", DataDimensions::Dynamic)); + + mTitle = "Math Node"; +} diff --git a/Engine/source/gui/shaderEditor/nodes/mathNode.h b/Engine/source/gui/shaderEditor/nodes/mathNode.h new file mode 100644 index 000000000..92a177aba --- /dev/null +++ b/Engine/source/gui/shaderEditor/nodes/mathNode.h @@ -0,0 +1,39 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "gui/shaderEditor/guiShaderNode.h" + +//----------------------------------------------------------------- +// Put all Math nodes here. +//----------------------------------------------------------------- + +class MathAddNode : public GuiShaderNode +{ + typedef GuiShaderNode Parent; +public: + MathAddNode(); + + // is the parent that all other nodes are derived from. + DECLARE_CONOBJECT(MathAddNode); + DECLARE_CATEGORY("Shader Math"); + DECLARE_DESCRIPTION("Math addition node."); +}; diff --git a/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/roundedRectangleP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/roundedRectangleP.hlsl index dea3e6bee..9dbffc4f4 100644 --- a/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/roundedRectangleP.hlsl +++ b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/roundedRectangleP.hlsl @@ -84,9 +84,10 @@ float4 main(Conn IN) : TORQUE_TARGET0 // (p.x >= halfSize.x - radius + halfBorder && p.x <= halfSize.x + radius - halfBorder) ) { // right border // } - toColor = IN.color; + toColor = IN.color; + sdf = abs(sdf) / borderSize; } - sdf = abs(sdf) / borderSize; + } else{ fromColor = IN.color; From fbed04050a5bb541c61b88a7b7a1593595a10087 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Sat, 9 Mar 2024 18:34:43 +0000 Subject: [PATCH 44/53] gui shaders for opengl First opengl geometry shader along with the other shaders for gui rendering opengl side. --- Engine/source/gfx/gl/gfxGLShader.cpp | 2 +- .../gui/shaderEditor/guiShaderEditor.cpp | 9 +- .../gui/shaderEditor/nodes/mathNode.cpp | 1 - .../rendering/scripts/gfxData/shaders.tscript | 10 ++ .../shaders/fixedFunction/circleP.hlsl | 4 +- .../shaders/fixedFunction/gl/circleP.glsl | 62 ++++++++++++ .../fixedFunction/gl/roundedRectangleP.glsl | 98 +++++++++++++++++++ .../shaders/fixedFunction/gl/thickLineG.glsl | 67 +++++++++++++ .../shaders/fixedFunction/gl/thickLineP.glsl | 30 ++++++ 9 files changed, 274 insertions(+), 9 deletions(-) create mode 100644 Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/circleP.glsl create mode 100644 Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/roundedRectangleP.glsl create mode 100644 Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/thickLineG.glsl create mode 100644 Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/thickLineP.glsl diff --git a/Engine/source/gfx/gl/gfxGLShader.cpp b/Engine/source/gfx/gl/gfxGLShader.cpp index 9bd6ac183..1d6a8ab88 100644 --- a/Engine/source/gfx/gl/gfxGLShader.cpp +++ b/Engine/source/gfx/gl/gfxGLShader.cpp @@ -462,7 +462,7 @@ bool GFXGLShader::_init() if (!mGeometryFile.isEmpty()) { macros.last().name = "TORQUE_GEOMETRY_SHADER"; - compiledGeometryShader = initShader(mPixelFile, GFXShaderStage::GEOMETRY_SHADER, macros); + compiledGeometryShader = initShader(mGeometryFile, GFXShaderStage::GEOMETRY_SHADER, macros); if (!compiledGeometryShader) return false; } diff --git a/Engine/source/gui/shaderEditor/guiShaderEditor.cpp b/Engine/source/gui/shaderEditor/guiShaderEditor.cpp index f5ff22af7..2de12705e 100644 --- a/Engine/source/gui/shaderEditor/guiShaderEditor.cpp +++ b/Engine/source/gui/shaderEditor/guiShaderEditor.cpp @@ -192,7 +192,7 @@ void GuiShaderEditor::renderNodes(Point2I offset, const RectI& updateRect) } RectI socketRect(pos, Point2I(mNodeSize, mNodeSize)); - drawer->drawCircleFill(socketRect, fill, mNodeSize / 2, 2.0f, border); + drawer->drawCircleFill(socketRect, fill, mNodeSize / 2, 1.0f, border); } for (NodeOutput* output : node->mOutputNodes) @@ -208,7 +208,7 @@ void GuiShaderEditor::renderNodes(Point2I offset, const RectI& updateRect) } RectI socketRect(pos, Point2I(mNodeSize, mNodeSize)); - drawer->drawCircleFill(socketRect, fill, mNodeSize / 2, 2.0f, border); + drawer->drawCircleFill(socketRect, fill, mNodeSize / 2, 1.0f, border); } } } @@ -244,7 +244,7 @@ void GuiShaderEditor::renderConnections(Point2I offset, const RectI& updateRect) start += Point2I(mNodeSize / 2, mNodeSize / 2); end += Point2I(mNodeSize / 2, mNodeSize / 2); - drawer->drawThickLine(start, end,ColorI(255,255,255,255), (F32)mNodeSize/3); + drawer->drawThickLine(start, end,ColorI(255,255,255,255), 2.0f); } // Restore the clip rect to what it was at the start @@ -288,10 +288,9 @@ void GuiShaderEditor::onRender(Point2I offset, const RectI& updateRect) RectI sockActive(start, Point2I(mNodeSize, mNodeSize)); start += Point2I(mNodeSize / 2, mNodeSize / 2); - drawer->drawThickLine(start, mLastMousePos + offset, color, (F32)mNodeSize / 3); + drawer->drawThickLine(start, mLastMousePos + offset, color, 2.0f); // draw socket overlay over the top of the line. - sockActive.inset(1, 1); drawer->drawCircleFill(sockActive, color, mNodeSize / 2); } } diff --git a/Engine/source/gui/shaderEditor/nodes/mathNode.cpp b/Engine/source/gui/shaderEditor/nodes/mathNode.cpp index ebcf13284..ed6905339 100644 --- a/Engine/source/gui/shaderEditor/nodes/mathNode.cpp +++ b/Engine/source/gui/shaderEditor/nodes/mathNode.cpp @@ -35,7 +35,6 @@ ConsoleDocClass(MathAddNode, "@internal" ); - MathAddNode::MathAddNode() : GuiShaderNode() { diff --git a/Templates/BaseGame/game/core/rendering/scripts/gfxData/shaders.tscript b/Templates/BaseGame/game/core/rendering/scripts/gfxData/shaders.tscript index 0b3d1ae47..51552e141 100644 --- a/Templates/BaseGame/game/core/rendering/scripts/gfxData/shaders.tscript +++ b/Templates/BaseGame/game/core/rendering/scripts/gfxData/shaders.tscript @@ -158,6 +158,9 @@ singleton ShaderData( RoundedRectangleGUI ) { DXVertexShaderFile = $Core::CommonShaderPath @ "/fixedFunction/colorV.hlsl"; DXPixelShaderFile = $Core::CommonShaderPath @ "/fixedFunction/roundedRectangleP.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/fixedFunction/gl/colorV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/fixedFunction/gl/roundedRectangleP.glsl"; pixVersion = 3.0; }; @@ -166,6 +169,9 @@ singleton ShaderData( CircularGUI ) { DXVertexShaderFile = $Core::CommonShaderPath @ "/fixedFunction/colorV.hlsl"; DXPixelShaderFile = $Core::CommonShaderPath @ "/fixedFunction/circleP.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/fixedFunction/gl/colorV.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/fixedFunction/gl/circleP.glsl"; pixVersion = 3.0; }; @@ -175,6 +181,10 @@ singleton ShaderData( ThickLineGUI ) DXVertexShaderFile = $Core::CommonShaderPath @ "/fixedFunction/colorV.hlsl"; DXGeometryShaderFile = $Core::CommonShaderPath @ "/fixedFunction/thickLineG.hlsl"; DXPixelShaderFile = $Core::CommonShaderPath @ "/fixedFunction/thickLineP.hlsl"; + + OGLVertexShaderFile = $Core::CommonShaderPath @ "/fixedFunction/gl/colorV.glsl"; + OGLGeometryShaderFile = $Core::CommonShaderPath @ "/fixedFunction/gl/thickLineG.glsl"; + OGLPixelShaderFile = $Core::CommonShaderPath @ "/fixedFunction/gl/thickLineP.glsl"; pixVersion = 3.0; }; \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/circleP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/circleP.hlsl index 08384871b..684e53ff3 100644 --- a/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/circleP.hlsl +++ b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/circleP.hlsl @@ -50,10 +50,10 @@ float4 main(Conn IN) : TORQUE_TARGET0 { distance = abs(distance) - radius; - if(distance < (radius - (borderSize * 0.5))) + if(distance < (radius - (borderSize))) { toColor = IN.color; - distance = abs(distance) - (borderSize * 0.5); + distance = abs(distance) - (borderSize); } float blend = smoothstep(0.0, 1.0, distance); diff --git a/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/circleP.glsl b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/circleP.glsl new file mode 100644 index 000000000..4882019b8 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/circleP.glsl @@ -0,0 +1,62 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +in vec4 color; + +out vec4 OUT_col; + +uniform vec2 sizeUni; +uniform float radius; +uniform vec2 rectCenter; +uniform float borderSize; +uniform vec4 borderCol; + +float circle(vec2 p, vec2 center, float r) +{ + return length(p - center); +} + +void main() +{ + float dist = circle(gl_FragCoord.xy, rectCenter, radius); + + vec4 fromColor = borderCol; + vec4 toColor = vec4(0.0, 0.0, 0.0, 0.0); + + if(dist < radius) + { + dist = abs(dist) - radius; + + if(dist < (radius - (borderSize))) + { + toColor = color; + dist = abs(dist) - (borderSize); + } + + float blend = smoothstep(0.0, 1.0, dist); + OUT_col = mix(fromColor, toColor, blend); + } + + dist = abs(dist) - radius; + float blend = smoothstep(0.0, 1.0, dist); + OUT_col = mix(fromColor, toColor, blend); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/roundedRectangleP.glsl b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/roundedRectangleP.glsl new file mode 100644 index 000000000..57599b550 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/roundedRectangleP.glsl @@ -0,0 +1,98 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +in vec4 color; + +out vec4 OUT_col; + +uniform vec2 sizeUni; +uniform vec2 rectCenter; +uniform vec2 oneOverViewport; +uniform float radius; +uniform float borderSize; +uniform vec4 borderCol; + +float RoundedRectSDF(vec2 p, vec2 size, float radius) +{ + // Calculate distance to each side of the rectangle + vec2 dist = abs(p) - size + vec2(radius, radius); + + // Compute the distance to the rounded corners + float cornerDist = length(max(dist, 0.0)); + + // Return the minimum distance (negative inside, positive outside) + return min(max(dist.x, dist.y), 0.0) + cornerDist - radius; +} + +void main() +{ + vec2 p = gl_FragCoord.xy; + + float halfBorder = borderSize * 0.5; + vec2 halfSize = sizeUni * 0.5; + p -= rectCenter; + + // Calculate signed distance field for rounded rectangle + vec4 fromColor = borderCol; + // alpha + vec4 toColor = vec4(0.0, 0.0, 0.0, 0.0); + + float cornerRadius = radius; + + // if ((p.y < 0.0 && p.x < 0.0) || // top left corner + // (p.y < 0.0 && p.x > 0.0) || // top right corner + // (p.y > 0.0 && p.x > 0.0) || // bottom right corner. + // (p.y > 0.0 && p.x < 0.0)) // bottom left corner + // { + // cornerRadius = radius; + // } + + if(cornerRadius > 0.0 || halfBorder > 0.0) + { + float sdf = RoundedRectSDF(p, halfSize, cornerRadius - halfBorder); + + if(halfBorder > 0.0) + { + if(sdf < 0.0) + { + // if ((p.y >= -halfSize.y - radius + halfBorder && p.y <= -halfSize.y + radius - halfBorder) || // top border + // (p.y >= halfSize.y - radius + halfBorder && p.y <= halfSize.y + radius - halfBorder) || // bottom border + // (p.x >= -halfSize.x - radius + halfBorder && p.x <= -halfSize.x + radius - halfBorder) || // left border + // (p.x >= halfSize.x - radius + halfBorder && p.x <= halfSize.x + radius - halfBorder) ) { // right border + + // } + toColor = color; + sdf = abs(sdf) / borderSize; + } + + } + else{ + fromColor = color; + } + + float alpha = smoothstep(-1.0, 1.0, sdf); + OUT_col = mix(fromColor, toColor, alpha); + } + else + { + OUT_col = color; + } +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/thickLineG.glsl b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/thickLineG.glsl new file mode 100644 index 000000000..f52486699 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/thickLineG.glsl @@ -0,0 +1,67 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +layout (lines) in; +layout (triangle_strip, max_vertices = 4) out; + +in VS_OUT { + vec4 color; +} gs_in[]; + + +out vec4 fragColor; + +uniform float thickness; +uniform vec2 oneOverViewport; + +void main() +{ + // Calculate the direction of the line segment + vec2 direction = normalize(gl_in[1].gl_Position.xy - gl_in[0].gl_Position.xy); + + // Calculate perpendicular direction + vec2 perpendicular = normalize(vec2(-direction.y, direction.x)); + + // Calculate offset for thickness + vec2 offset = vec2(thickness * oneOverViewport.x, thickness * oneOverViewport.y) * perpendicular; + + // Calculate vertices for the line with thickness + vec2 p0 = gl_in[0].gl_Position.xy + offset; + vec2 p1 = gl_in[0].gl_Position.xy - offset; + vec2 p2 = gl_in[1].gl_Position.xy + offset; + vec2 p3 = gl_in[1].gl_Position.xy - offset; + + fragColor = gs_in[0].color; + gl_Position = vec4(p0, 0.0f, 1.0f); + EmitVertex(); + + gl_Position = vec4(p1, 0.0f, 1.0f); + EmitVertex(); + + gl_Position = vec4(p2, 0.0f, 1.0f); + EmitVertex(); + + gl_Position = vec4(p3, 0.0f, 1.0f); + EmitVertex(); + + EndPrimitive(); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/thickLineP.glsl b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/thickLineP.glsl new file mode 100644 index 000000000..eeee83abc --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/gl/thickLineP.glsl @@ -0,0 +1,30 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +in vec4 fragColor; + +out vec4 OUT_col; + +void main() +{ + OUT_col = fragColor; +} \ No newline at end of file From 9dc5ae833bb76b3028a5cecac6134c444e8ce6bd Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Wed, 13 Mar 2024 22:23:01 +0000 Subject: [PATCH 45/53] opengl ubo setup opengl can now compile with ubo buffer objects similar to cbuffers on dx side. cleaned double up of data from both sides, gfxhandles only need to use the desc info instead of holding onto its own. --- Engine/source/gfx/D3D11/gfxD3D11Shader.cpp | 14 +- Engine/source/gfx/D3D11/gfxD3D11Shader.h | 16 +- Engine/source/gfx/gfxShader.h | 12 +- Engine/source/gfx/gl/gfxGLDevice.cpp | 186 ++-- Engine/source/gfx/gl/gfxGLDevice.h | 69 +- Engine/source/gfx/gl/gfxGLShader.cpp | 1037 ++++++++++++-------- Engine/source/gfx/gl/gfxGLShader.h | 212 ++-- 7 files changed, 941 insertions(+), 605 deletions(-) diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp index 294e4d1ff..78f22f8c9 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp @@ -95,12 +95,9 @@ HRESULT gfxD3D11Include::Close( THIS_ LPCVOID pData ) GFXD3D11ShaderConstHandle::GFXD3D11ShaderConstHandle(GFXD3D11Shader* shader) : mShader(shader), - mSize(0), - mSampler(-1), - mArraySize(1), mInstancingConstant(false) { - mType = GFXSCT_ConstBuffer; + dMemset(&mDesc, 0, sizeof(mDesc)); mValid = false; mStageFlags = 0; } @@ -108,18 +105,15 @@ GFXD3D11ShaderConstHandle::GFXD3D11ShaderConstHandle(GFXD3D11Shader* shader) GFXD3D11ShaderConstHandle::GFXD3D11ShaderConstHandle(GFXD3D11Shader* shader, const GFXShaderConstDesc& desc) : mShader(shader), - mSize(desc.size), - mSampler(desc.samplerReg), - mType(desc.constType), - mArraySize(desc.arraySize), + mDesc(desc), mInstancingConstant(false) { if (desc.constType == GFXSCT_ConstBuffer) mValid = false; else mValid = true; - addDesc(desc.shaderStage, desc); + addDesc(desc.shaderStage, desc); mStageFlags = desc.shaderStage; } @@ -976,7 +970,7 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection* refTable, varDesc.constType = convertConstType(shaderTypeDesc); #ifdef D3D11_DEBUG_SPEW - Con::printf("Variable Name %s:, offset: %d, size: %d, constantDesc.Elements: %d", varDesc.name.c_str(), varDesc.StartOffset, varDesc.Size, varDesc.arraySize); + Con::printf("Variable Name %s:, offset: %d, size: %d, constantDesc.Elements: %d", varDesc.name.c_str(), varDesc.offset, varDesc.size, varDesc.arraySize); #endif mShaderConsts.push_back(varDesc); } diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.h b/Engine/source/gfx/D3D11/gfxD3D11Shader.h index ffa9dbb2e..f233f0f01 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.h +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.h @@ -69,15 +69,15 @@ public: virtual ~GFXD3D11ShaderConstHandle(); void addDesc(GFXShaderStage stage, const GFXShaderConstDesc& desc); const GFXShaderConstDesc getDesc(GFXShaderStage stage); - const String& getName() const { return mName; } - GFXShaderConstType getType() const { return mType; } - U32 getArraySize() const { return mArraySize; } + const String& getName() const { return mDesc.name; } + GFXShaderConstType getType() const { return mDesc.constType; } + U32 getArraySize() const { return mDesc.arraySize; } - U32 getSize() const { return mSize; } + U32 getSize() const { return mDesc.size; } 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 (!isSampler() || !mValid) ? -1 : mSampler; } + S32 getSamplerRegister() const { return (!isSampler() || !mValid) ? -1 : mDesc.samplerReg; } // Returns true if this is a handle to a sampler register. bool isSampler() const @@ -93,13 +93,9 @@ public: mValid = false; } + GFXShaderConstDesc mDesc; GFXD3D11Shader* mShader; DescMap mDescMap; - String mName; - GFXShaderConstType mType; - U32 mSize; - U32 mArraySize; - S32 mSampler; // sampler number, will be -1 if not a sampler. U32 mStageFlags; bool mInstancingConstant; }; diff --git a/Engine/source/gfx/gfxShader.h b/Engine/source/gfx/gfxShader.h index abc45e9fe..0a5ed19c4 100644 --- a/Engine/source/gfx/gfxShader.h +++ b/Engine/source/gfx/gfxShader.h @@ -81,12 +81,12 @@ struct GFXShaderConstDesc public: String name; GFXShaderConstType constType; - 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 - GFXShaderStage shaderStage; // only used dx side. + U32 arraySize = 0; // > 1 means it is an array! + S32 bindPoint = -1; // bind point used for ubo/cb + S32 samplerReg = -1; // sampler register. + U32 offset = 0; // offset for vars + U32 size = 0; // size of buffer/type + GFXShaderStage shaderStage; // only used dx side. }; /// This is an opaque handle used by GFXShaderConstBuffer clients to set individual shader constants. diff --git a/Engine/source/gfx/gl/gfxGLDevice.cpp b/Engine/source/gfx/gl/gfxGLDevice.cpp index 07dfcb10d..452e72227 100644 --- a/Engine/source/gfx/gl/gfxGLDevice.cpp +++ b/Engine/source/gfx/gl/gfxGLDevice.cpp @@ -57,7 +57,7 @@ #include "gfx/gl/tGL/tXGL.h" #endif -GFXAdapter::CreateDeviceInstanceDelegate GFXGLDevice::mCreateDeviceInstance(GFXGLDevice::createInstance); +GFXAdapter::CreateDeviceInstanceDelegate GFXGLDevice::mCreateDeviceInstance(GFXGLDevice::createInstance); GFXDevice *GFXGLDevice::createInstance( U32 adapterIndex ) { @@ -76,7 +76,7 @@ void loadGLCore() if(coreLoaded) return; coreLoaded = true; - + // Make sure we've got our GL bindings. GL::gglPerformBinds(); } @@ -87,11 +87,11 @@ void loadGLExtensions(void *context) if(extensionsLoaded) return; extensionsLoaded = true; - + GL::gglPerformExtensionBinds(context); } -void STDCALL glDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, +void STDCALL glDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const void *userParam) { // JTH [11/24/2016]: This is a temporary fix so that we do not get spammed for redundant fbo changes. @@ -118,24 +118,24 @@ void STDCALL glAmdDebugCallback(GLuint id, GLenum category, GLenum severity, GLs } void GFXGLDevice::initGLState() -{ +{ // We don't currently need to sync device state with a known good place because we are // going to set everything in GFXGLStateBlock, but if we change our GFXGLStateBlock strategy, this may // need to happen. - + // Deal with the card profiler here when we know we have a valid context. mCardProfiler = new GFXGLCardProfiler(); - mCardProfiler->init(); + mCardProfiler->init(); glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, (GLint*)&mMaxShaderTextures); // JTH: Needs removed, ffp //glGetIntegerv(GL_MAX_TEXTURE_UNITS, (GLint*)&mMaxFFTextures); glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, (GLint*)&mMaxTRColors); mMaxTRColors = getMin( mMaxTRColors, (U32)(GFXTextureTarget::MaxRenderSlotId-1) ); - + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - + // [JTH 5/6/2016] GLSL 1.50 is really SM 4.0 - // Setting mPixelShaderVersion to 3.0 will allow Advanced Lighting to run. + // Setting mPixelShaderVersion to 3.0 will allow Advanced Lighting to run. mPixelShaderVersion = 3.0; // Set capability extensions. @@ -150,7 +150,7 @@ void GFXGLDevice::initGLState() String vendorStr = (const char*)glGetString( GL_VENDOR ); if( vendorStr.find("NVIDIA", 0, String::NoCase | String::Left) != String::NPos) mUseGlMap = false; - + // Workaround for all Mac's, has a problem using glMap* with volatile buffers #ifdef TORQUE_OS_MAC mUseGlMap = false; @@ -173,7 +173,7 @@ void GFXGLDevice::initGLState() else if(gglHasExtension(AMD_debug_output)) { glEnable(GL_DEBUG_OUTPUT); - glDebugMessageCallbackAMD(glAmdDebugCallback, NULL); + glDebugMessageCallbackAMD(glAmdDebugCallback, NULL); //glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB); GLuint unusedIds = 0; glDebugMessageEnableAMD(GL_DONT_CARE, GL_DONT_CARE, 0,&unusedIds, GL_TRUE); @@ -258,16 +258,17 @@ GFXGLDevice::GFXGLDevice(U32 adapterIndex) : mModelViewProjSC[i] = NULL; mOpenglStateCache = new GFXGLStateCache; + mCurrentConstBuffer = NULL; } GFXGLDevice::~GFXGLDevice() { mCurrentStateBlock = NULL; - for(int i = 0; i < VERTEX_STREAM_COUNT; ++i) + for(int i = 0; i < VERTEX_STREAM_COUNT; ++i) mCurrentVB[i] = NULL; mCurrentPB = NULL; - + for(U32 i = 0; i < mVolatileVBs.size(); i++) mVolatileVBs[i] = NULL; for(U32 i = 0; i < mVolatilePBs.size(); i++) @@ -297,7 +298,7 @@ GFXGLDevice::~GFXGLDevice() walk->zombify(); walk = walk->getNextResource(); } - + if( mCardProfiler ) SAFE_DELETE( mCardProfiler ); @@ -310,12 +311,12 @@ void GFXGLDevice::zombify() { mTextureManager->zombify(); - for(int i = 0; i < VERTEX_STREAM_COUNT; ++i) + for(int i = 0; i < VERTEX_STREAM_COUNT; ++i) if(mCurrentVB[i]) mCurrentVB[i]->finish(); if(mCurrentPB) mCurrentPB->finish(); - + //mVolatileVBs.clear(); //mVolatilePBs.clear(); GFXResource* walk = mResourceListHead; @@ -334,12 +335,12 @@ void GFXGLDevice::resurrect() walk->resurrect(); walk = walk->getNextResource(); } - for(int i = 0; i < VERTEX_STREAM_COUNT; ++i) + for(int i = 0; i < VERTEX_STREAM_COUNT; ++i) if(mCurrentVB[i]) mCurrentVB[i]->prepare(); if(mCurrentPB) mCurrentPB->prepare(); - + mTextureManager->resurrect(); } @@ -366,7 +367,7 @@ GFXPrimitiveBuffer* GFXGLDevice::findVolatilePBO(U32 numIndices, U32 numPrimitiv for(U32 i = 0; i < mVolatilePBs.size(); i++) if((mVolatilePBs[i]->mIndexCount >= numIndices) && (mVolatilePBs[i]->getRefCount() == 1)) return mVolatilePBs[i]; - + // No existing PB, so create one StrongRefPtr buf(new GFXGLPrimitiveBuffer(GFX, numIndices, numPrimitives, GFXBufferTypeVolatile)); buf->registerResourceWithDevice(this); @@ -374,18 +375,18 @@ GFXPrimitiveBuffer* GFXGLDevice::findVolatilePBO(U32 numIndices, U32 numPrimitiv return buf.getPointer(); } -GFXVertexBuffer *GFXGLDevice::allocVertexBuffer( U32 numVerts, - const GFXVertexFormat *vertexFormat, - U32 vertSize, +GFXVertexBuffer *GFXGLDevice::allocVertexBuffer( U32 numVerts, + const GFXVertexFormat *vertexFormat, + U32 vertSize, GFXBufferType bufferType, - void* data ) + void* data ) { PROFILE_SCOPE(GFXGLDevice_allocVertexBuffer); if(bufferType == GFXBufferTypeVolatile) return findVolatileVBO(numVerts, vertexFormat, vertSize); - + GFXGLVertexBuffer* buf = new GFXGLVertexBuffer( GFX, numVerts, vertexFormat, vertSize, bufferType ); - buf->registerResourceWithDevice(this); + buf->registerResourceWithDevice(this); if(data) { @@ -398,10 +399,10 @@ GFXVertexBuffer *GFXGLDevice::allocVertexBuffer( U32 numVerts, return buf; } -GFXPrimitiveBuffer *GFXGLDevice::allocPrimitiveBuffer( U32 numIndices, U32 numPrimitives, GFXBufferType bufferType, void* data ) +GFXPrimitiveBuffer *GFXGLDevice::allocPrimitiveBuffer( U32 numIndices, U32 numPrimitives, GFXBufferType bufferType, void* data ) { GFXPrimitiveBuffer* buf; - + if(bufferType == GFXBufferTypeVolatile) { buf = findVolatilePBO(numIndices, numPrimitives); @@ -411,7 +412,7 @@ GFXPrimitiveBuffer *GFXGLDevice::allocPrimitiveBuffer( U32 numIndices, U32 numPr buf = new GFXGLPrimitiveBuffer(GFX, numIndices, numPrimitives, bufferType); buf->registerResourceWithDevice(this); } - + if(data) { void* dest; @@ -430,7 +431,7 @@ void GFXGLDevice::setVertexStream( U32 stream, GFXVertexBuffer *buffer ) { // Reset the state the old VB required, then set the state the new VB requires. if( mCurrentVB[stream] ) - { + { mCurrentVB[stream]->finish(); } @@ -460,10 +461,10 @@ void GFXGLDevice::setVertexStreamFrequency( U32 stream, U32 frequency ) } GFXCubemap* GFXGLDevice::createCubemap() -{ +{ GFXGLCubemap* cube = new GFXGLCubemap(); cube->registerResourceWithDevice(this); - return cube; + return cube; }; GFXCubemapArray *GFXGLDevice::createCubemapArray() @@ -480,7 +481,7 @@ GFXTextureArray* GFXGLDevice::createTextureArray() return textureArray; } -void GFXGLDevice::endSceneInternal() +void GFXGLDevice::endSceneInternal() { // nothing to do for opengl mCanCurrentlyRender = false; @@ -556,9 +557,9 @@ void GFXGLDevice::clear(U32 flags, const LinearColorF& color, F32 z, U32 stencil { // Make sure we have flushed our render target state. _updateRenderTargets(); - + bool writeAllColors = true; - bool zwrite = true; + bool zwrite = true; bool writeAllStencil = true; const GFXStateBlockDesc *desc = NULL; if (mCurrentGLStateBlock) @@ -568,7 +569,7 @@ void GFXGLDevice::clear(U32 flags, const LinearColorF& color, F32 z, U32 stencil writeAllColors = desc->colorWriteRed && desc->colorWriteGreen && desc->colorWriteBlue && desc->colorWriteAlpha; writeAllStencil = desc->stencilWriteMask == 0xFFFFFFFF; } - + glColorMask(true, true, true, true); glDepthMask(true); glStencilMask(0xFFFFFFFF); @@ -585,7 +586,7 @@ void GFXGLDevice::clear(U32 flags, const LinearColorF& color, F32 z, U32 stencil if(!writeAllColors) glColorMask(desc->colorWriteRed, desc->colorWriteGreen, desc->colorWriteBlue, desc->colorWriteAlpha); - + if(!zwrite) glDepthMask(false); @@ -623,20 +624,20 @@ inline GLsizei GFXGLDevice::primCountToIndexCount(GFXPrimitiveType primType, U32 AssertFatal(false, "GFXGLDevice::primCountToIndexCount - unrecognized prim type"); break; } - + return 0; } -GFXVertexDecl* GFXGLDevice::allocVertexDecl( const GFXVertexFormat *vertexFormat ) +GFXVertexDecl* GFXGLDevice::allocVertexDecl( const GFXVertexFormat *vertexFormat ) { PROFILE_SCOPE(GFXGLDevice_allocVertexDecl); typedef Map GFXGLVertexDeclMap; - static GFXGLVertexDeclMap declMap; + static GFXGLVertexDeclMap declMap; GFXGLVertexDeclMap::Iterator itr = declMap.find( (void*)vertexFormat->getDescription().c_str() ); // description string are interned, safe to use c_str() if(itr != declMap.end()) return &itr->value; - GFXGLVertexDecl &decl = declMap[(void*)vertexFormat->getDescription().c_str()]; + GFXGLVertexDecl &decl = declMap[(void*)vertexFormat->getDescription().c_str()]; decl.init(vertexFormat); return &decl; } @@ -652,7 +653,7 @@ inline void GFXGLDevice::preDrawPrimitive() { updateStates(); } - + if(mCurrentShaderConstBuffer) setShaderConstBufferInternal(mCurrentShaderConstBuffer); @@ -660,18 +661,18 @@ inline void GFXGLDevice::preDrawPrimitive() { AssertFatal(mCurrVertexDecl, ""); const GFXGLVertexDecl* decl = static_cast(mCurrVertexDecl); - + for(int i = 0; i < getNumVertexStreams(); ++i) { if(mCurrentVB[i]) { - mCurrentVB[i]->prepare(i, mCurrentVB_Divisor[i]); // GL_ARB_vertex_attrib_binding + mCurrentVB[i]->prepare(i, mCurrentVB_Divisor[i]); // GL_ARB_vertex_attrib_binding decl->prepareBuffer_old( i, mCurrentVB[i]->mBuffer, mCurrentVB_Divisor[i] ); // old vertex buffer/format } } - decl->updateActiveVertexAttrib( GFXGL->getOpenglCache()->getCacheVertexAttribActive() ); - } + decl->updateActiveVertexAttrib( GFXGL->getOpenglCache()->getCacheVertexAttribActive() ); + } mNeedUpdateVertexAttrib = false; } @@ -682,26 +683,26 @@ inline void GFXGLDevice::postDrawPrimitive(U32 primitiveCount) mDeviceStatistics.mPolyCount += primitiveCount; } -void GFXGLDevice::drawPrimitive( GFXPrimitiveType primType, U32 vertexStart, U32 primitiveCount ) +void GFXGLDevice::drawPrimitive( GFXPrimitiveType primType, U32 vertexStart, U32 primitiveCount ) { preDrawPrimitive(); - + if(mCurrentVB[0]) vertexStart += mCurrentVB[0]->mBufferVertexOffset; if(mDrawInstancesCount) glDrawArraysInstanced(GFXGLPrimType[primType], vertexStart, primCountToIndexCount(primType, primitiveCount), mDrawInstancesCount); else - glDrawArrays(GFXGLPrimType[primType], vertexStart, primCountToIndexCount(primType, primitiveCount)); + glDrawArrays(GFXGLPrimType[primType], vertexStart, primCountToIndexCount(primType, primitiveCount)); postDrawPrimitive(primitiveCount); } -void GFXGLDevice::drawIndexedPrimitive( GFXPrimitiveType primType, - U32 startVertex, - U32 minIndex, - U32 numVerts, - U32 startIndex, +void GFXGLDevice::drawIndexedPrimitive( GFXPrimitiveType primType, + U32 startVertex, + U32 minIndex, + U32 numVerts, + U32 startIndex, U32 primitiveCount ) { preDrawPrimitive(); @@ -732,7 +733,7 @@ void GFXGLDevice::setTextureInternal(U32 textureUnit, const GFXTextureObject*tex { mActiveTextureType[textureUnit] = tex->getBinding(); tex->bind(textureUnit); - } + } else if(mActiveTextureType[textureUnit] != GL_ZERO) { glActiveTexture(GL_TEXTURE0 + textureUnit); @@ -805,21 +806,21 @@ void GFXGLDevice::setClipRect( const RectI &inRect ) F32 r = F32(mClip.point.x + mClip.extent.x); F32 b = F32(mClip.point.y + mClip.extent.y); F32 t = F32(mClip.point.y); - - // Set up projection matrix, + + // Set up projection matrix, //static Point4F pt; pt.set(2.0f / (r - l), 0.0f, 0.0f, 0.0f); mProjectionMatrix.setColumn(0, pt); - + pt.set(0.0f, 2.0f / (t - b), 0.0f, 0.0f); mProjectionMatrix.setColumn(1, pt); - + pt.set(0.0f, 0.0f, 1.0f, 0.0f); mProjectionMatrix.setColumn(2, pt); - + pt.set((l + r) / (l - r), (t + b) / (b - t), 1.0f, 1.0f); mProjectionMatrix.setColumn(3, pt); - + MatrixF mTempMatrix(true); setViewMatrix( mTempMatrix ); setWorldMatrix( mTempMatrix ); @@ -844,7 +845,7 @@ void GFXGLDevice::setStateBlockInternal(GFXStateBlock* block, bool force) GFXGLStateBlock* glCurrent = static_cast(mCurrentStateBlock.getPointer()); if (force) glCurrent = NULL; - + glBlock->activate(glCurrent); // Doesn't use current yet. mCurrentGLStateBlock = glBlock; } @@ -863,19 +864,19 @@ GFXFence * GFXGLDevice::createFence() GFXFence* fence = _createPlatformSpecificFence(); if(!fence) fence = new GFXGeneralFence( this ); - + fence->registerResourceWithDevice(this); return fence; } GFXOcclusionQuery* GFXGLDevice::createOcclusionQuery() -{ +{ GFXOcclusionQuery *query = new GFXGLOcclusionQuery( this ); query->registerResourceWithDevice(this); return query; } -void GFXGLDevice::setupGenericShaders( GenericShaderType type ) +void GFXGLDevice::setupGenericShaders( GenericShaderType type ) { AssertFatal(type != GSTargetRestore, ""); @@ -927,7 +928,7 @@ void GFXGLDevice::setupGenericShaders( GenericShaderType type ) Sim::getRootGroup()->addObject(shaderData); } - MatrixF tempMatrix = mProjectionMatrix * mViewMatrix * mWorldMatrix[mWorldStackSize]; + MatrixF tempMatrix = mProjectionMatrix * mViewMatrix * mWorldMatrix[mWorldStackSize]; mGenericShaderBuffer[type]->setSafe(mModelViewProjSC[type], tempMatrix); setShader( mGenericShader[type] ); @@ -959,8 +960,19 @@ void GFXGLDevice::setShader(GFXShader *shader, bool force) void GFXGLDevice::setShaderConstBufferInternal(GFXShaderConstBuffer* buffer) { - PROFILE_SCOPE(GFXGLDevice_setShaderConstBufferInternal); - static_cast(buffer)->activate(); + if (buffer) + { + PROFILE_SCOPE(GFXGLDevice_setShaderConstBufferInternal); + AssertFatal(static_cast(buffer), "Incorrect shader const buffer type for this device!"); + GFXGLShaderConstBuffer* oglBuffer = static_cast(buffer); + + oglBuffer->activate(mCurrentConstBuffer); + mCurrentConstBuffer = oglBuffer; + } + else + { + mCurrentConstBuffer = NULL; + } } U32 GFXGLDevice::getNumSamplers() const @@ -968,7 +980,7 @@ U32 GFXGLDevice::getNumSamplers() const return getMin((U32)GFX_TEXTURE_STAGE_COUNT,mPixelShaderVersion > 0.001f ? mMaxShaderTextures : mMaxFFTextures); } -GFXTextureObject* GFXGLDevice::getDefaultDepthTex() const +GFXTextureObject* GFXGLDevice::getDefaultDepthTex() const { if(mWindowRT && mWindowRT->getPointer()) return static_cast( mWindowRT->getPointer() )->mBackBufferDepthTex.getPointer(); @@ -976,9 +988,9 @@ GFXTextureObject* GFXGLDevice::getDefaultDepthTex() const return NULL; } -U32 GFXGLDevice::getNumRenderTargets() const -{ - return mMaxTRColors; +U32 GFXGLDevice::getNumRenderTargets() const +{ + return mMaxTRColors; } void GFXGLDevice::_updateRenderTargets() @@ -988,9 +1000,9 @@ void GFXGLDevice::_updateRenderTargets() if ( mRTDeactivate ) { mRTDeactivate->deactivate(); - mRTDeactivate = NULL; + mRTDeactivate = NULL; } - + // NOTE: The render target changes is not really accurate // as the GFXTextureTarget supports MRT internally. So when // we activate a GFXTarget it could result in multiple calls @@ -1006,31 +1018,31 @@ void GFXGLDevice::_updateRenderTargets() else { GFXGLWindowTarget *win = dynamic_cast( mCurrentRT.getPointer() ); - AssertFatal( win != NULL, + AssertFatal( win != NULL, "GFXGLDevice::_updateRenderTargets() - invalid target subclass passed!" ); - + win->makeActive(); - + if( win->mContext != static_cast(GFX)->mContext ) { mRTDirty = false; GFX->updateStates(true); } } - + mRTDirty = false; } - + if ( mViewportDirty ) { - glViewport( mViewport.point.x, mViewport.point.y, mViewport.extent.x, mViewport.extent.y ); + glViewport( mViewport.point.x, mViewport.point.y, mViewport.extent.x, mViewport.extent.y ); mViewportDirty = false; } } -GFXFormat GFXGLDevice::selectSupportedFormat( GFXTextureProfile* profile, - const Vector& formats, - bool texture, +GFXFormat GFXGLDevice::selectSupportedFormat( GFXTextureProfile* profile, + const Vector& formats, + bool texture, bool mustblend, bool mustfilter ) { @@ -1041,10 +1053,10 @@ GFXFormat GFXGLDevice::selectSupportedFormat( GFXTextureProfile* profile, continue; if(GFXGLTextureInternalFormat[formats[i]] == GL_ZERO) continue; - + return formats[i]; } - + return GFXFormatR8G8B8A8; } @@ -1055,7 +1067,7 @@ U32 GFXGLDevice::getTotalVideoMemory_GL_EXT() { GLint mem[4] = {0}; glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, mem); // Retrieve the texture pool - + /* With mem[0] i get only the total memory free in the pool in KB * * mem[0] - total memory free in the pool @@ -1066,7 +1078,7 @@ U32 GFXGLDevice::getTotalVideoMemory_GL_EXT() return mem[0] / 1024; } - + //source http://www.opengl.org/registry/specs/NVX/gpu_memory_info.txt else if( gglHasExtension(NVX_gpu_memory_info) ) { diff --git a/Engine/source/gfx/gl/gfxGLDevice.h b/Engine/source/gfx/gl/gfxGLDevice.h index 3a42db9d6..36b0cfa71 100644 --- a/Engine/source/gfx/gl/gfxGLDevice.h +++ b/Engine/source/gfx/gl/gfxGLDevice.h @@ -43,6 +43,7 @@ class GFXGLCubemap; class GFXGLCubemapArray; class GFXGLStateCache; class GFXGLVertexDecl; +class GFXGLShaderConstBuffer; class GFXGLDevice : public GFXDevice { @@ -105,13 +106,13 @@ public: /// @{ virtual F32 getPixelShaderVersion() const { return mPixelShaderVersion; } virtual void setPixelShaderVersion( F32 version ) { mPixelShaderVersion = version; } - + virtual void setShader(GFXShader *shader, bool force = false); - + /// @attention GL cannot check if the given format supports blending or filtering! virtual GFXFormat selectSupportedFormat(GFXTextureProfile *profile, const Vector &formats, bool texture, bool mustblend, bool mustfilter); - + /// Returns the number of texture samplers that can be used in a shader rendering pass virtual U32 getNumSamplers() const; @@ -128,11 +129,11 @@ public: virtual void drawPrimitive( GFXPrimitiveType primType, U32 vertexStart, U32 primitiveCount ); - virtual void drawIndexedPrimitive( GFXPrimitiveType primType, - U32 startVertex, - U32 minIndex, - U32 numVerts, - U32 startIndex, + virtual void drawIndexedPrimitive( GFXPrimitiveType primType, + U32 startVertex, + U32 minIndex, + U32 numVerts, + U32 startIndex, U32 primitiveCount ); virtual void setClipRect( const RectI &rect ); @@ -142,15 +143,15 @@ public: virtual U32 getMaxDynamicVerts() { return GFX_MAX_DYNAMIC_VERTS; } virtual U32 getMaxDynamicIndices() { return GFX_MAX_DYNAMIC_INDICES; } - + GFXFence *createFence(); - + GFXOcclusionQuery* createOcclusionQuery(); GFXGLStateBlockRef getCurrentStateBlock() { return mCurrentGLStateBlock; } - + virtual void setupGenericShaders( GenericShaderType type = GSColor ); - + /// bool supportsAnisotropic() const { return mCapabilities.anisotropicFiltering; } @@ -158,16 +159,16 @@ public: GFXTextureObject* getDefaultDepthTex() const; - /// Returns the number of vertex streams supported by the device. + /// Returns the number of vertex streams supported by the device. const U32 getNumVertexStreams() const { return mNumVertexStream; } - bool glUseMap() const { return mUseGlMap; } + bool glUseMap() const { return mUseGlMap; } const char* interpretDebugResult(long result) { return "Not Implemented"; }; -protected: +protected: /// Called by GFXDevice to create a device specific stateblock virtual GFXStateBlockRef createStateBlockInternal(const GFXStateBlockDesc& desc); /// Called by GFXDevice to actually set a stateblock. - virtual void setStateBlockInternal(GFXStateBlock* block, bool force); + virtual void setStateBlockInternal(GFXStateBlock* block, bool force); /// Called by base GFXDevice to actually set a const buffer virtual void setShaderConstBufferInternal(GFXShaderConstBuffer* buffer); @@ -184,13 +185,13 @@ protected: /// is created. virtual void initStates() { } - virtual GFXVertexBuffer *allocVertexBuffer( U32 numVerts, + virtual GFXVertexBuffer *allocVertexBuffer( U32 numVerts, const GFXVertexFormat *vertexFormat, - U32 vertSize, + U32 vertSize, GFXBufferType bufferType, void* data = NULL); virtual GFXPrimitiveBuffer *allocPrimitiveBuffer( U32 numIndices, U32 numPrimitives, GFXBufferType bufferType, void* data = NULL ); - + // NOTE: The GL device doesn't need a vertex declaration at // this time, but we need to return something to keep the system // from retrying to allocate one on every call. @@ -199,11 +200,11 @@ protected: virtual void setVertexDecl( const GFXVertexDecl *decl ); virtual void setVertexStream( U32 stream, GFXVertexBuffer *buffer ); - virtual void setVertexStreamFrequency( U32 stream, U32 frequency ); - + virtual void setVertexStreamFrequency( U32 stream, U32 frequency ); + StrongRefPtr mCurrentConstBuffer; private: typedef GFXDevice Parent; - + friend class GFXGLTextureObject; friend class GFXGLCubemap; friend class GFXGLCubemapArray; @@ -215,18 +216,18 @@ private: static GFXAdapter::CreateDeviceInstanceDelegate mCreateDeviceInstance; U32 mAdapterIndex; - + StrongRefPtr mCurrentVB[VERTEX_STREAM_COUNT]; U32 mCurrentVB_Divisor[VERTEX_STREAM_COUNT]; bool mNeedUpdateVertexAttrib; StrongRefPtr mCurrentPB; U32 mDrawInstancesCount; - + GFXShader* mCurrentShader; GFXShaderRef mGenericShader[GS_COUNT]; GFXShaderConstBufferRef mGenericShaderBuffer[GS_COUNT]; GFXShaderConstHandle *mModelViewProjSC[GS_COUNT]; - + /// Since GL does not have separate world and view matrices we need to track them MatrixF m_mCurrentWorld; MatrixF m_mCurrentView; @@ -237,34 +238,34 @@ private: F32 mPixelShaderVersion; U32 mNumVertexStream; - + U32 mMaxShaderTextures; U32 mMaxFFTextures; U32 mMaxTRColors; RectI mClip; - + GFXGLStateBlockRef mCurrentGLStateBlock; - + GLenum mActiveTextureType[GFX_TEXTURE_STAGE_COUNT]; - + Vector< StrongRefPtr > mVolatileVBs; ///< Pool of existing volatile VBs so we can reuse previously created ones Vector< StrongRefPtr > mVolatilePBs; ///< Pool of existing volatile PBs so we can reuse previously created ones GLsizei primCountToIndexCount(GFXPrimitiveType primType, U32 primitiveCount); void preDrawPrimitive(); - void postDrawPrimitive(U32 primitiveCount); - + void postDrawPrimitive(U32 primitiveCount); + GFXVertexBuffer* findVolatileVBO(U32 numVerts, const GFXVertexFormat *vertexFormat, U32 vertSize); ///< Returns an existing volatile VB which has >= numVerts and the same vert flags/size, or creates a new VB if necessary GFXPrimitiveBuffer* findVolatilePBO(U32 numIndices, U32 numPrimitives); ///< Returns an existing volatile PB which has >= numIndices, or creates a new PB if necessary void vsyncCallback(); ///< Vsync callback - + void initGLState(); ///< Guaranteed to be called after all extensions have been loaded, use to init card profiler, shader version, max samplers, etc. - + GFXFence* _createPlatformSpecificFence(); ///< If our platform (e.g. OS X) supports a fence extenstion (e.g. GL_APPLE_fence) this will create one, otherwise returns NULL - + void setPB(GFXGLPrimitiveBuffer* pb); ///< Sets mCurrentPB GFXGLStateCache *mOpenglStateCache; diff --git a/Engine/source/gfx/gl/gfxGLShader.cpp b/Engine/source/gfx/gl/gfxGLShader.cpp index 1d6a8ab88..9a15be4f8 100644 --- a/Engine/source/gfx/gl/gfxGLShader.cpp +++ b/Engine/source/gfx/gl/gfxGLShader.cpp @@ -34,51 +34,51 @@ #define CHECK_AARG(pos, name) static StringTableEntry attr_##name = StringTable->insert(#name); if (argName == attr_##name) { glBindAttribLocation(mProgram, pos, attr_##name); continue; } - -class GFXGLShaderConstHandle : public GFXShaderConstHandle -{ - friend class GFXGLShader; - -public: - - GFXGLShaderConstHandle( GFXGLShader *shader ); - GFXGLShaderConstHandle( GFXGLShader *shader, const GFXShaderConstDesc &desc, GLuint loc, S32 samplerNum ); - virtual ~GFXGLShaderConstHandle(); - - void reinit( const GFXShaderConstDesc &desc, GLuint loc, S32 samplerNum ); - - const String& getName() const { return mDesc.name; } - GFXShaderConstType getType() const { return mDesc.constType; } - U32 getArraySize() const { return mDesc.arraySize; } - - 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; } - - GFXShaderConstDesc mDesc; - GFXGLShader* mShader; - U32 mOffset; - U32 mSize; - GLuint mLocation; - S32 mSamplerNum; - bool mInstancingConstant; -}; - -GFXGLShaderConstHandle::GFXGLShaderConstHandle( GFXGLShader *shader ) - : mShader( shader ), mLocation(0), mOffset(0), mSize(0), mSamplerNum(-1), mInstancingConstant(false) +GFXGLShaderConstHandle::GFXGLShaderConstHandle(GFXGLShader* shader) + : mShader(shader), + mUBOUniform(false), + mInstancingConstant(false) { dMemset(&mDesc, 0, sizeof(mDesc)); mValid = false; } +GFXGLShaderConstHandle::GFXGLShaderConstHandle(GFXGLShader* shader, + const GFXShaderConstDesc& desc) + : mShader(shader), + mDesc(desc), + mUBOUniform(false), + mInstancingConstant(false) +{ + if (desc.constType == GFXSCT_ConstBuffer) + mValid = false; + else + mValid = true; +} + +void GFXGLShaderConstHandle::reinit(const GFXShaderConstDesc& desc) +{ + mDesc = desc; + mValid = true; +} + +GFXGLShaderConstHandle::~GFXGLShaderConstHandle() +{ +} + +const GFXShaderConstDesc GFXGLShaderConstHandle::getDesc() +{ + return mDesc; +} + static U32 shaderConstTypeSize(GFXShaderConstType type) { - switch(type) + switch (type) { case GFXSCT_Float: case GFXSCT_Int: + case GFXSCT_UInt: + case GFXSCT_Bool: case GFXSCT_Sampler: case GFXSCT_SamplerCube: case GFXSCT_SamplerCubeArray: @@ -86,12 +86,18 @@ static U32 shaderConstTypeSize(GFXShaderConstType type) return 4; case GFXSCT_Float2: case GFXSCT_Int2: + case GFXSCT_UInt2: + case GFXSCT_Bool2: return 8; case GFXSCT_Float3: case GFXSCT_Int3: + case GFXSCT_UInt3: + case GFXSCT_Bool3: return 12; case GFXSCT_Float4: case GFXSCT_Int4: + case GFXSCT_UInt4: + case GFXSCT_Bool4: return 16; case GFXSCT_Float2x2: return 16; @@ -102,79 +108,56 @@ static U32 shaderConstTypeSize(GFXShaderConstType type) case GFXSCT_Float4x4: return 64; default: - AssertFatal(false,"shaderConstTypeSize - Unrecognized constant type"); + AssertFatal(false, "shaderConstTypeSize - Unrecognized constant type"); return 0; } } -GFXGLShaderConstHandle::GFXGLShaderConstHandle( GFXGLShader *shader, const GFXShaderConstDesc &desc, GLuint loc, S32 samplerNum ) - : mShader(shader), mInstancingConstant(false) -{ - reinit(desc, loc, samplerNum); -} - -void GFXGLShaderConstHandle::reinit( const GFXShaderConstDesc& desc, GLuint loc, S32 samplerNum ) -{ - mDesc = desc; - mLocation = loc; - mSamplerNum = samplerNum; - mOffset = 0; - mInstancingConstant = false; - - U32 elemSize = shaderConstTypeSize(mDesc.constType); - AssertFatal(elemSize, "GFXGLShaderConst::GFXGLShaderConst - elemSize is 0"); - mSize = mDesc.arraySize * elemSize; - mValid = true; -} - - -U32 GFXGLShaderConstHandle::getSize() const -{ - return mSize; -} - -GFXGLShaderConstHandle::~GFXGLShaderConstHandle() -{ -} - -GFXGLShaderConstBuffer::GFXGLShaderConstBuffer(GFXGLShader* shader, U32 bufSize, U8* existingConstants) +GFXGLShaderConstBuffer::GFXGLShaderConstBuffer(GFXGLShader* shader) { mShader = shader; - mBuffer = new U8[bufSize]; mWasLost = true; - - // Copy the existing constant buffer to preserve sampler numbers - /// @warning This preserves a lot more than sampler numbers, obviously. If there - /// is any code that assumes a new constant buffer will have everything set to - /// 0, it will break. - dMemcpy(mBuffer, existingConstants, bufSize); } GFXGLShaderConstBuffer::~GFXGLShaderConstBuffer() { - delete[] mBuffer; - - if ( mShader ) - mShader->_unlinkBuffer( this ); + if (mShader) + mShader->_unlinkBuffer(this); } template void GFXGLShaderConstBuffer::internalSet(GFXShaderConstHandle* handle, const ConstType& param) { - AssertFatal(handle, "GFXGLShaderConstBuffer::internalSet - Handle is NULL!" ); - AssertFatal(handle->isValid(), "GFXGLShaderConstBuffer::internalSet - Handle is not valid!" ); + AssertFatal(handle, "GFXGLShaderConstBuffer::internalSet - Handle is NULL!"); + AssertFatal(handle->isValid(), "GFXGLShaderConstBuffer::internalSet - Handle is not valid!"); AssertFatal(dynamic_cast(handle), "GFXGLShaderConstBuffer::set - Incorrect const buffer type"); GFXGLShaderConstHandle* _glHandle = static_cast(handle); AssertFatal(mShader == _glHandle->mShader, "GFXGLShaderConstBuffer::set - Should only set handles which are owned by our shader"); - U8 *buf = mBuffer + _glHandle->mOffset; - if(_glHandle->mInstancingConstant) - buf = mInstPtr + _glHandle->mOffset; + U8* basePointer; + if (!_glHandle->mUBOUniform) + { + basePointer = mBufferMap[-1].data; + } + else + { + basePointer = mBufferMap[_glHandle->mDesc.bindPoint].data; + } + + U8* buf = basePointer + _glHandle->mDesc.offset; + + if (_glHandle->mInstancingConstant) + buf = mInstPtr + _glHandle->mDesc.offset; dMemcpy(buf, ¶m, sizeof(ConstType)); } +GFXShader* GFXGLShaderConstBuffer::getShader() +{ + return mShader; +} + void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const F32 fv) { internalSet(handle, fv); @@ -228,17 +211,28 @@ void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const Point4I& fv template void GFXGLShaderConstBuffer::internalSet(GFXShaderConstHandle* handle, const AlignedArray& fv) { - AssertFatal(handle, "GFXGLShaderConstBuffer::internalSet - Handle is NULL!" ); - AssertFatal(handle->isValid(), "GFXGLShaderConstBuffer::internalSet - Handle is not valid!" ); + AssertFatal(handle, "GFXGLShaderConstBuffer::internalSet - Handle is NULL!"); + AssertFatal(handle->isValid(), "GFXGLShaderConstBuffer::internalSet - Handle is not valid!"); AssertFatal(dynamic_cast(handle), "GFXGLShaderConstBuffer::set - Incorrect const buffer type"); GFXGLShaderConstHandle* _glHandle = static_cast(handle); AssertFatal(mShader == _glHandle->mShader, "GFXGLShaderConstBuffer::set - Should only set handles which are owned by our shader"); AssertFatal(!_glHandle->mInstancingConstant, "GFXGLShaderConstBuffer::set - Instancing not supported for array"); - const U8* fvBuffer = static_cast(fv.getBuffer()); - for(U32 i = 0; i < fv.size(); ++i) + + U8* basePointer; + if (!_glHandle->mUBOUniform) { - dMemcpy(mBuffer + _glHandle->mOffset + i * sizeof(ConstType), fvBuffer, sizeof(ConstType)); + basePointer = mBufferMap[-1].data; + } + else + { + basePointer = mBufferMap[_glHandle->mDesc.bindPoint].data; + } + + const U8* fvBuffer = static_cast(fv.getBuffer()); + for (U32 i = 0; i < fv.size(); ++i) + { + dMemcpy(basePointer + _glHandle->mDesc.offset + i * sizeof(ConstType), fvBuffer, sizeof(ConstType)); fvBuffer += fv.getElementSize(); } } @@ -285,47 +279,57 @@ void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArra void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF& mat, const GFXShaderConstType matType) { - AssertFatal(handle, "GFXGLShaderConstBuffer::set - Handle is NULL!" ); - AssertFatal(handle->isValid(), "GFXGLShaderConstBuffer::set - Handle is not valid!" ); + AssertFatal(handle, "GFXGLShaderConstBuffer::set - Handle is NULL!"); + AssertFatal(handle->isValid(), "GFXGLShaderConstBuffer::set - Handle is not valid!"); AssertFatal(dynamic_cast(handle), "GFXGLShaderConstBuffer::set - Incorrect const buffer type"); GFXGLShaderConstHandle* _glHandle = static_cast(handle); AssertFatal(mShader == _glHandle->mShader, "GFXGLShaderConstBuffer::set - Should only set handles which are owned by our shader"); AssertFatal(!_glHandle->mInstancingConstant || matType == GFXSCT_Float4x4, "GFXGLShaderConstBuffer::set - Only support GFXSCT_Float4x4 for instancing"); - switch(matType) + U8* basePointer; + if (!_glHandle->mUBOUniform) + { + basePointer = mBufferMap[-1].data; + } + else + { + basePointer = mBufferMap[_glHandle->mDesc.bindPoint].data; + } + + switch (matType) { case GFXSCT_Float2x2: - reinterpret_cast(mBuffer + _glHandle->mOffset)[0] = mat[0]; - reinterpret_cast(mBuffer + _glHandle->mOffset)[1] = mat[1]; - reinterpret_cast(mBuffer + _glHandle->mOffset)[2] = mat[4]; - reinterpret_cast(mBuffer + _glHandle->mOffset)[3] = mat[5]; + reinterpret_cast(basePointer + _glHandle->mDesc.offset)[0] = mat[0]; + reinterpret_cast(basePointer + _glHandle->mDesc.offset)[1] = mat[1]; + reinterpret_cast(basePointer + _glHandle->mDesc.offset)[2] = mat[4]; + reinterpret_cast(basePointer + _glHandle->mDesc.offset)[3] = mat[5]; break; case GFXSCT_Float3x3: - reinterpret_cast(mBuffer + _glHandle->mOffset)[0] = mat[0]; - reinterpret_cast(mBuffer + _glHandle->mOffset)[1] = mat[1]; - reinterpret_cast(mBuffer + _glHandle->mOffset)[2] = mat[2]; - reinterpret_cast(mBuffer + _glHandle->mOffset)[3] = mat[4]; - reinterpret_cast(mBuffer + _glHandle->mOffset)[4] = mat[5]; - reinterpret_cast(mBuffer + _glHandle->mOffset)[5] = mat[6]; - reinterpret_cast(mBuffer + _glHandle->mOffset)[6] = mat[8]; - reinterpret_cast(mBuffer + _glHandle->mOffset)[7] = mat[9]; - reinterpret_cast(mBuffer + _glHandle->mOffset)[8] = mat[10]; + reinterpret_cast(basePointer + _glHandle->mDesc.offset)[0] = mat[0]; + reinterpret_cast(basePointer + _glHandle->mDesc.offset)[1] = mat[1]; + reinterpret_cast(basePointer + _glHandle->mDesc.offset)[2] = mat[2]; + reinterpret_cast(basePointer + _glHandle->mDesc.offset)[3] = mat[4]; + reinterpret_cast(basePointer + _glHandle->mDesc.offset)[4] = mat[5]; + reinterpret_cast(basePointer + _glHandle->mDesc.offset)[5] = mat[6]; + reinterpret_cast(basePointer + _glHandle->mDesc.offset)[6] = mat[8]; + reinterpret_cast(basePointer + _glHandle->mDesc.offset)[7] = mat[9]; + reinterpret_cast(basePointer + _glHandle->mDesc.offset)[8] = mat[10]; break; case GFXSCT_Float4x3: - dMemcpy(mBuffer + _glHandle->mOffset, (const F32*)mat, (sizeof(F32) * 12));// matrix with end row chopped off + dMemcpy(basePointer + _glHandle->mDesc.offset, (const F32*)mat, (sizeof(F32) * 12));// matrix with end row chopped off break; case GFXSCT_Float4x4: { - if(_glHandle->mInstancingConstant) + if (_glHandle->mInstancingConstant) { MatrixF transposed; mat.transposeTo(transposed); - dMemcpy( mInstPtr + _glHandle->mOffset, (const F32*)transposed, sizeof(MatrixF) ); + dMemcpy(mInstPtr + _glHandle->mDesc.offset, (const F32*)transposed, sizeof(MatrixF)); return; } - dMemcpy(mBuffer + _glHandle->mOffset, (const F32*)mat, sizeof(MatrixF)); + dMemcpy(basePointer + _glHandle->mDesc.offset, (const F32*)mat, sizeof(MatrixF)); break; } default: @@ -336,49 +340,147 @@ void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF& ma void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF* mat, const U32 arraySize, const GFXShaderConstType matrixType) { - AssertFatal(handle, "GFXGLShaderConstBuffer::set - Handle is NULL!" ); - AssertFatal(handle->isValid(), "GFXGLShaderConstBuffer::set - Handle is not valid!" ); + AssertFatal(handle, "GFXGLShaderConstBuffer::set - Handle is NULL!"); + AssertFatal(handle->isValid(), "GFXGLShaderConstBuffer::set - Handle is not valid!"); GFXGLShaderConstHandle* _glHandle = static_cast(handle); AssertFatal(mShader == _glHandle->mShader, "GFXGLShaderConstBuffer::set - Should only set handles which are owned by our shader"); AssertFatal(!_glHandle->mInstancingConstant, "GFXGLShaderConstBuffer::set - Instancing not supported for matrix arrays"); + U8* basePointer; + if (!_glHandle->mUBOUniform) + { + basePointer = mBufferMap[-1].data; + } + else + { + basePointer = mBufferMap[_glHandle->mDesc.bindPoint].data; + } + switch (matrixType) { - case GFXSCT_Float4x3: - // Copy each item with the last row chopped off - for (int i = 0; imOffset + (i*(sizeof(F32) * 12)), (F32*)(mat + i), sizeof(F32) * 12); - } + case GFXSCT_Float4x3: + // Copy each item with the last row chopped off + for (int i = 0; i < arraySize; i++) + { + dMemcpy(basePointer + _glHandle->mDesc.offset + (i * (sizeof(F32) * 12)), (F32*)(mat + i), sizeof(F32) * 12); + } + break; + case GFXSCT_Float4x4: + dMemcpy(basePointer + _glHandle->mDesc.offset, (F32*)mat, _glHandle->getSize()); + break; + default: + AssertFatal(false, "GFXGLShaderConstBuffer::set - setting array of non 4x4 matrices!"); break; - case GFXSCT_Float4x4: - dMemcpy(mBuffer + _glHandle->mOffset, (F32*)mat, _glHandle->getSize()); - break; - default: - AssertFatal(false, "GFXGLShaderConstBuffer::set - setting array of non 4x4 matrices!"); - break; } } -void GFXGLShaderConstBuffer::activate() +void GFXGLShaderConstBuffer::activate(GFXGLShaderConstBuffer* prevShaderBuffer) { PROFILE_SCOPE(GFXGLShaderConstBuffer_activate); - mShader->setConstantsFromBuffer(this); + + for (BufferMap::Iterator i = mBufferMap.begin(); i != mBufferMap.end(); ++i) + { + const S32 thisBufferDesc = i->key; + + // set the global buffer differently + if (thisBufferDesc == -1) + { + mShader->setConstantsFromBuffer(mBufferMap[-1].data); + continue; + } + + ConstantBuffer thisBuff = i->value; + + if (prevShaderBuffer && prevShaderBuffer != this) + { + const ConstantBuffer prevBuffer = prevShaderBuffer->mBufferMap[i->key]; + + if (prevBuffer.data && !prevBuffer.isDirty) + { + if (prevBuffer.size != thisBuff.size) + { + thisBuff.isDirty = true; + } + else + { + if (dMemcmp(prevBuffer.data, thisBuff.data, thisBuff.size) != 0) + { + thisBuff.isDirty = true; + } + else + { + thisBuff.isDirty = false; + } + } + } + else + { + thisBuff.isDirty = true; + } + } + else + { + thisBuff.isDirty = true; + } + + if (thisBuff.data && thisBuff.isDirty) + { + glBindBuffer(GL_UNIFORM_BUFFER, thisBuff.bufHandle); + glBufferData(GL_UNIFORM_BUFFER, thisBuff.size, thisBuff.data, GL_DYNAMIC_DRAW); + glBindBufferBase(GL_UNIFORM_BUFFER, thisBufferDesc, thisBuff.bufHandle); + } + } + mWasLost = false; } +void GFXGLShaderConstBuffer::addBuffer(S32 bufBindingPoint, U32 size) +{ + // if this is the global buffer set it to the highest. + if (bufBindingPoint == -1) + { + // we dont create a bufferhandle for this one. + U8* buf = new U8[size]; + dMemset(buf, 0, size); + mBufferMap[-1].data = buf; + mBufferMap[-1].size = size; + mBufferMap[-1].isDirty = true; + } + else + { + U8* buf = new U8[size]; + dMemset(buf, 0, size); + mBufferMap[bufBindingPoint].data = buf; + mBufferMap[bufBindingPoint].size = size; + mBufferMap[bufBindingPoint].isDirty = true; + + GLuint uboHandle; + glGenBuffers(1, &uboHandle); + + mBufferMap[bufBindingPoint].bufHandle = uboHandle; + } +} + const String GFXGLShaderConstBuffer::describeSelf() const { return String(); } -void GFXGLShaderConstBuffer::onShaderReload( GFXGLShader *shader ) +void GFXGLShaderConstBuffer::onShaderReload(GFXGLShader* shader) { - AssertFatal( shader == mShader, "GFXGLShaderConstBuffer::onShaderReload, mismatched shaders!" ); + AssertFatal(shader == mShader, "GFXGLShaderConstBuffer::onShaderReload, mismatched shaders!"); + + for (auto& pair : mBufferMap) { + delete[] pair.value.data; + } + mBufferMap.clear(); // Clear the map + + for (GFXGLShader::BufferMap::Iterator i = shader->mBuffers.begin(); i != shader->mBuffers.end(); ++i) + { + // add our buffer descriptions to the full const buffer. + this->addBuffer(i->value.bindPoint, i->value.size); + } - delete[] mBuffer; - mBuffer = new U8[mShader->mConstBufferSize]; - dMemset(mBuffer, 0, mShader->mConstBufferSize); mWasLost = true; } @@ -388,18 +490,23 @@ GFXGLShader::GFXGLShader(GFXGLDevice* device) : mGeometryShader(0), mProgram(0), mDevice(device), - mConstBufferSize(0), - mConstBuffer(NULL) + mGlobalConstBuffer(NULL) { } GFXGLShader::~GFXGLShader() { clearShaders(); - for(HandleMap::Iterator i = mHandles.begin(); i != mHandles.end(); i++) - delete i->value; + for (auto& pair : mHandles) { + if (pair.value != nullptr) { + delete pair.value; + pair.value = nullptr; + } + } + mHandles.clear(); - delete[] mConstBuffer; + if (mGlobalConstBuffer) + delete[] mGlobalConstBuffer; } void GFXGLShader::clearShaders() @@ -419,7 +526,7 @@ bool GFXGLShader::_init() { PROFILE_SCOPE(GFXGLShader_Init); // Don't initialize empty shaders. - if ( mVertexFile.isEmpty() && mPixelFile.isEmpty() ) + if (mVertexFile.isEmpty() && mPixelFile.isEmpty()) return false; clearShaders(); @@ -428,8 +535,8 @@ bool GFXGLShader::_init() // Set the macros and add the global ones. Vector macros; - macros.merge( mMacros ); - macros.merge( smGlobalMacros ); + macros.merge(mMacros); + macros.merge(smGlobalMacros); macros.increment(); macros.last().name = "TORQUE_SM"; @@ -468,18 +575,18 @@ bool GFXGLShader::_init() } // Link it! - glLinkProgram( mProgram ); + glLinkProgram(mProgram); - GLint activeAttribs = 0; - glGetProgramiv(mProgram, GL_ACTIVE_ATTRIBUTES, &activeAttribs ); + GLint activeAttribs = 0; + glGetProgramiv(mProgram, GL_ACTIVE_ATTRIBUTES, &activeAttribs); GLint maxLength; glGetProgramiv(mProgram, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxLength); - FrameTemp tempData(maxLength+1); + FrameTemp tempData(maxLength + 1); *tempData.address() = '\0'; // Check atributes - for (U32 i=0; iinsert(tempData.address()); - CHECK_AARG(Torque::GL_VertexAttrib_Position, vPosition); - CHECK_AARG(Torque::GL_VertexAttrib_Normal, vNormal); - CHECK_AARG(Torque::GL_VertexAttrib_Color, vColor); - CHECK_AARG(Torque::GL_VertexAttrib_Tangent, vTangent); - CHECK_AARG(Torque::GL_VertexAttrib_TangentW, vTangentW); - CHECK_AARG(Torque::GL_VertexAttrib_Binormal, vBinormal); - CHECK_AARG(Torque::GL_VertexAttrib_TexCoord0, vTexCoord0); - CHECK_AARG(Torque::GL_VertexAttrib_TexCoord1, vTexCoord1); - CHECK_AARG(Torque::GL_VertexAttrib_TexCoord2, vTexCoord2); - CHECK_AARG(Torque::GL_VertexAttrib_TexCoord3, vTexCoord3); - CHECK_AARG(Torque::GL_VertexAttrib_TexCoord4, vTexCoord4); - CHECK_AARG(Torque::GL_VertexAttrib_TexCoord5, vTexCoord5); - CHECK_AARG(Torque::GL_VertexAttrib_TexCoord6, vTexCoord6); - CHECK_AARG(Torque::GL_VertexAttrib_TexCoord7, vTexCoord7); - CHECK_AARG(Torque::GL_VertexAttrib_TexCoord8, vTexCoord8); - CHECK_AARG(Torque::GL_VertexAttrib_TexCoord9, vTexCoord9); + CHECK_AARG(Torque::GL_VertexAttrib_Position, vPosition); + CHECK_AARG(Torque::GL_VertexAttrib_Normal, vNormal); + CHECK_AARG(Torque::GL_VertexAttrib_Color, vColor); + CHECK_AARG(Torque::GL_VertexAttrib_Tangent, vTangent); + CHECK_AARG(Torque::GL_VertexAttrib_TangentW, vTangentW); + CHECK_AARG(Torque::GL_VertexAttrib_Binormal, vBinormal); + CHECK_AARG(Torque::GL_VertexAttrib_TexCoord0, vTexCoord0); + CHECK_AARG(Torque::GL_VertexAttrib_TexCoord1, vTexCoord1); + CHECK_AARG(Torque::GL_VertexAttrib_TexCoord2, vTexCoord2); + CHECK_AARG(Torque::GL_VertexAttrib_TexCoord3, vTexCoord3); + CHECK_AARG(Torque::GL_VertexAttrib_TexCoord4, vTexCoord4); + CHECK_AARG(Torque::GL_VertexAttrib_TexCoord5, vTexCoord5); + CHECK_AARG(Torque::GL_VertexAttrib_TexCoord6, vTexCoord6); + CHECK_AARG(Torque::GL_VertexAttrib_TexCoord7, vTexCoord7); + CHECK_AARG(Torque::GL_VertexAttrib_TexCoord8, vTexCoord8); + CHECK_AARG(Torque::GL_VertexAttrib_TexCoord9, vTexCoord9); } //always have OUT_col glBindFragDataLocation(mProgram, 0, "OUT_col"); // Check OUT_colN - for(U32 i=1;i<4;i++) + for (U32 i = 1; i < 4; i++) { char buffer[10]; - dSprintf(buffer, sizeof(buffer), "OUT_col%u",i); + dSprintf(buffer, sizeof(buffer), "OUT_col%u", i); GLint location = glGetFragDataLocation(mProgram, buffer); - if(location>0) + if (location > 0) glBindFragDataLocation(mProgram, i, buffer); } // Link it again! - glLinkProgram( mProgram ); + glLinkProgram(mProgram); GLint linkStatus; - glGetProgramiv( mProgram, GL_LINK_STATUS, &linkStatus ); + glGetProgramiv(mProgram, GL_LINK_STATUS, &linkStatus); // Dump the info log to the console U32 logLength = 0; glGetProgramiv(mProgram, GL_INFO_LOG_LENGTH, (GLint*)&logLength); - if ( logLength ) + if (logLength) { FrameAllocatorMarker fam; - char* log = (char*)fam.alloc( logLength ); - glGetProgramInfoLog( mProgram, logLength, NULL, log ); + char* log = (char*)fam.alloc(logLength); + glGetProgramInfoLog(mProgram, logLength, NULL, log); - if ( linkStatus == GL_FALSE ) + if (linkStatus == GL_FALSE) { - if ( smLogErrors ) + if (smLogErrors) { - Con::errorf( "GFXGLShader::init - Error linking shader!" ); - Con::errorf( "Program %s / %s: %s", + Con::errorf("GFXGLShader::init - Error linking shader!"); + Con::errorf("Program %s / %s: %s", mVertexFile.getFullPath().c_str(), mPixelFile.getFullPath().c_str(), log); } } - else if ( smLogWarnings ) + else if (smLogWarnings) { - Con::warnf( "Program %s / %s: %s", + Con::warnf("Program %s / %s: %s", mVertexFile.getFullPath().c_str(), mPixelFile.getFullPath().c_str(), log); } } // If we failed to link, bail. - if ( linkStatus == GL_FALSE ) + if (linkStatus == GL_FALSE) return false; initConstantDescs(); @@ -562,103 +669,208 @@ bool GFXGLShader::_init() // If this was our first init then we won't have any activeBuffers // to worry about unnecessarily calling. Vector::iterator biter = mActiveBuffers.begin(); - for ( ; biter != mActiveBuffers.end(); biter++ ) - ((GFXGLShaderConstBuffer*)(*biter))->onShaderReload( this ); + for (; biter != mActiveBuffers.end(); biter++) + ((GFXGLShaderConstBuffer*)(*biter))->onShaderReload(this); return true; } void GFXGLShader::initConstantDescs() { - mConstants.clear(); - GLint numUniforms; - glGetProgramiv(mProgram, GL_ACTIVE_UNIFORMS, &numUniforms); + // clear our vectors. + mShaderConsts.clear(); + GLint maxNameLength; glGetProgramiv(mProgram, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxNameLength); - if(!maxNameLength) + if (!maxNameLength) return; maxNameLength++; FrameTemp uniformName(maxNameLength); - for(U32 i = 0; i < numUniforms; i++) + // parse ubos first and add them to our table, same as in dx + // this is required so that in the other uniform loop we dont add + // a uniform that exists in a ubo again. + GLint numUBOS; + glGetProgramiv(mProgram, GL_ACTIVE_UNIFORM_BLOCKS, &numUBOS); + for (U32 i = 0; i < numUBOS; i++) { + GFXShaderConstDesc desc; + GLint uboNameLen; + glGetActiveUniformBlockiv(mProgram, i, GL_UNIFORM_BLOCK_NAME_LENGTH, &uboNameLen); + if (!uboNameLen) + return; + uboNameLen++; + + // get the name of the ubo for getting required data. + FrameTemp uboName(uboNameLen); + glGetActiveUniformBlockName(mProgram, i, uboNameLen, NULL, uboName); + GLint uboBinding; + glGetActiveUniformBlockiv(mProgram, i, GL_UNIFORM_BLOCK_BINDING, &uboBinding); + GLint uboSize; + glGetActiveUniformBlockiv(mProgram, i, GL_UNIFORM_BLOCK_DATA_SIZE, &uboSize); + GLint numUboUniforms; + glGetActiveUniformBlockiv(mProgram, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &numUboUniforms); + GLint* indices = new GLint[numUboUniforms]; + glGetActiveUniformBlockiv(mProgram, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, indices); + + // fill out ubo desc. + desc.name = String((char*)uboName); + desc.bindPoint = uboBinding; + desc.size = uboSize; + desc.constType = GFXSCT_ConstBuffer; + desc.samplerReg = -1; + + mBuffers[desc.name] = desc; + + // loop uniforms in the ubo. + for (U32 j = 0; j < numUboUniforms; j++) + { + GFXShaderConstDesc varDesc; + + GLint uniformIndex = indices[j]; + GLint size; + GLenum type; + GLint offset; + glGetActiveUniformsiv(mProgram, 1, (const GLuint*)&uniformIndex, GL_UNIFORM_OFFSET, &offset); + glGetActiveUniform(mProgram, uniformIndex, maxNameLength, NULL, &size, &type, uniformName); + + varDesc.name = String((char*)uniformName); + // remove array brackets. + varDesc.name = varDesc.name.substr(0, varDesc.name.find('[')); + // Insert $ to match D3D behavior of having a $ prepended to parameters to main. + varDesc.name.insert(0, '$'); + varDesc.bindPoint = desc.bindPoint; // just set to the buffer bindpoint for uniforms in a ubo. + varDesc.offset = offset; + varDesc.arraySize = size; + varDesc.constType = convertConstType(type); + varDesc.size = shaderConstTypeSize(varDesc.constType) * size; + varDesc.samplerReg = -1; + +#ifdef OPENGL_DEBUG_SPEW + Con::printf("Variable Name %s:, offset: %d, size: %d, constantDesc.Elements: %d", varDesc.name.c_str(), varDesc.offset, varDesc.size, varDesc.arraySize); +#endif + mShaderConsts.push_back(varDesc); + } + } + + GLint numUniforms; + glGetProgramiv(mProgram, GL_ACTIVE_UNIFORMS, &numUniforms); + + for (U32 i = 0; i < numUniforms; i++) { + // skip if this uniform is inside a ubo. + GLint blk; + glGetActiveUniformsiv(mProgram, 1, (GLuint*)&i, GL_UNIFORM_BLOCK_INDEX, &blk); + if (blk != -1) + { + continue; + } + GLint size; GLenum type; glGetActiveUniform(mProgram, i, maxNameLength, NULL, &size, &type, uniformName); + GFXShaderConstDesc desc; - desc.name = String((char*)uniformName); - // Remove array brackets from the name desc.name = desc.name.substr(0, desc.name.find('[')); - // Insert $ to match D3D behavior of having a $ prepended to parameters to main. desc.name.insert(0, '$'); + + desc.bindPoint = -1; desc.arraySize = size; + desc.constType = convertConstType(type); + desc.size = shaderConstTypeSize(desc.constType) * size; + desc.samplerReg = -1; + mShaderConsts.push_back(desc); + } +} - switch(type) - { - case GL_FLOAT: - desc.constType = GFXSCT_Float; - break; - case GL_FLOAT_VEC2: - desc.constType = GFXSCT_Float2; - break; - case GL_FLOAT_VEC3: - desc.constType = GFXSCT_Float3; - break; - case GL_FLOAT_VEC4: - desc.constType = GFXSCT_Float4; - break; - case GL_INT: - desc.constType = GFXSCT_Int; - break; - case GL_INT_VEC2: - desc.constType = GFXSCT_Int2; - break; - case GL_INT_VEC3: - desc.constType = GFXSCT_Int3; - break; - case GL_INT_VEC4: - desc.constType = GFXSCT_Int4; - break; - case GL_FLOAT_MAT2: - desc.constType = GFXSCT_Float2x2; - break; - case GL_FLOAT_MAT3: - desc.constType = GFXSCT_Float3x3; - break; - case GL_FLOAT_MAT4: - desc.constType = GFXSCT_Float4x4; - break; - case GL_FLOAT_MAT4x3: // jamesu - columns, rows - desc.constType = GFXSCT_Float4x3; - break; - case GL_SAMPLER_1D: - case GL_SAMPLER_2D: - case GL_SAMPLER_3D: - case GL_SAMPLER_1D_SHADOW: - case GL_SAMPLER_2D_SHADOW: - desc.constType = GFXSCT_Sampler; - break; - case GL_SAMPLER_CUBE: - desc.constType = GFXSCT_SamplerCube; - break; - case GL_SAMPLER_CUBE_MAP_ARRAY_ARB: - desc.constType = GFXSCT_SamplerCubeArray; - break; - case GL_SAMPLER_2D_ARRAY: - desc.constType = GFXSCT_SamplerTextureArray; - break; - default: - AssertFatal(false, "GFXGLShader::initConstantDescs - unrecognized uniform type"); - // If we don't recognize the constant don't add its description. - continue; - } - - mConstants.push_back(desc); +GFXShaderConstType GFXGLShader::convertConstType(GLenum constType) +{ + switch (constType) + { + case GL_FLOAT: + return GFXSCT_Float; + break; + case GL_FLOAT_VEC2: + return GFXSCT_Float2; + break; + case GL_FLOAT_VEC3: + return GFXSCT_Float3; + break; + case GL_FLOAT_VEC4: + return GFXSCT_Float4; + break; + case GL_INT: + return GFXSCT_Int; + break; + case GL_INT_VEC2: + return GFXSCT_Int2; + break; + case GL_INT_VEC3: + return GFXSCT_Int3; + break; + case GL_INT_VEC4: + return GFXSCT_Int4; + break; + case GL_UNSIGNED_INT: + return GFXSCT_UInt; + break; + case GL_UNSIGNED_INT_VEC2: + return GFXSCT_UInt2; + break; + case GL_UNSIGNED_INT_VEC3: + return GFXSCT_UInt3; + break; + case GL_UNSIGNED_INT_VEC4: + return GFXSCT_UInt4; + break; + case GL_BOOL: + return GFXSCT_Bool; + break; + case GL_BOOL_VEC2: + return GFXSCT_Bool2; + break; + case GL_BOOL_VEC3: + return GFXSCT_Bool3; + break; + case GL_BOOL_VEC4: + return GFXSCT_Bool4; + break; + case GL_FLOAT_MAT2: + return GFXSCT_Float2x2; + break; + case GL_FLOAT_MAT3: + return GFXSCT_Float3x3; + break; + case GL_FLOAT_MAT4: + return GFXSCT_Float4x4; + break; + case GL_FLOAT_MAT4x3: // jamesu - columns, rows + return GFXSCT_Float4x3; + break; + case GL_SAMPLER_1D: + case GL_SAMPLER_2D: + case GL_SAMPLER_3D: + case GL_SAMPLER_1D_SHADOW: + case GL_SAMPLER_2D_SHADOW: + return GFXSCT_Sampler; + break; + case GL_SAMPLER_CUBE: + return GFXSCT_SamplerCube; + break; + case GL_SAMPLER_CUBE_MAP_ARRAY_ARB: + return GFXSCT_SamplerCubeArray; + break; + case GL_SAMPLER_2D_ARRAY: + return GFXSCT_SamplerTextureArray; + break; + default: + AssertFatal(false, "GFXGLShader::initConstantDescs - unrecognized uniform type"); + // If we don't recognize the constant don't add its description. + break; } } @@ -666,15 +878,13 @@ void GFXGLShader::initHandles() { // 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(); + for (HandleMap::Iterator iter = mHandles.begin(); iter != mHandles.end(); ++iter) + (iter->value)->setValid(false); - // Loop through all ConstantDescriptions, - // if they aren't in the HandleMap add them, if they are reinitialize them. - for ( U32 i = 0; i < mConstants.size(); i++ ) + // Loop through constants that exist in ubos. + for (U32 i = 0; i < mShaderConsts.size(); i++) { - GFXShaderConstDesc &desc = mConstants[i]; + GFXShaderConstDesc& desc = mShaderConsts[i]; // Index element 1 of the name to skip the '$' we inserted earier. GLint loc = glGetUniformLocation(mProgram, &desc.name.c_str()[1]); @@ -683,7 +893,7 @@ void GFXGLShader::initHandles() HandleMap::Iterator handle = mHandles.find(desc.name); S32 sampler = -1; - if(desc.constType == GFXSCT_Sampler || + if (desc.constType == GFXSCT_Sampler || desc.constType == GFXSCT_SamplerCube || desc.constType == GFXSCT_SamplerCubeArray || desc.constType == GFXSCT_SamplerTextureArray) @@ -691,37 +901,71 @@ void GFXGLShader::initHandles() S32 idx = mSamplerNamesOrdered.find_next(desc.name); AssertFatal(idx != -1, ""); sampler = idx; //assignedSamplerNum++; + desc.samplerReg = idx; } - if ( handle != mHandles.end() ) + + if (handle != mHandles.end()) { - handle->value->reinit( desc, loc, sampler ); + if (desc.bindPoint == -1) + { + desc.bindPoint = loc; + mHandles[desc.name]->mUBOUniform = false; + } + else + { + mHandles[desc.name]->mUBOUniform = true; + } + + handle->value->reinit(desc); } else { - mHandles[desc.name] = new GFXGLShaderConstHandle( this, desc, loc, sampler ); + if (desc.bindPoint == -1) + { + desc.bindPoint = loc; + mHandles[desc.name] = new GFXGLShaderConstHandle(this, desc); + mHandles[desc.name]->mUBOUniform = false; + } + else + { + mHandles[desc.name] = new GFXGLShaderConstHandle(this, desc); + mHandles[desc.name]->mUBOUniform = true; + } } } - // Loop through handles once more to set their offset and calculate our - // constBuffer size. - if ( mConstBuffer ) - delete[] mConstBuffer; - mConstBufferSize = 0; + // we have a global const buffer, set it up and add it. + U32 constBufferSize = 0; - for ( HandleMap::Iterator iter = mHandles.begin(); iter != mHandles.end(); ++iter ) + if (mGlobalConstBuffer) + delete[] mGlobalConstBuffer; + + for (HandleMap::Iterator iter = mHandles.begin(); iter != mHandles.end(); ++iter) { GFXGLShaderConstHandle* handle = iter->value; - if ( handle->isValid() ) + if (handle->isValid() && !handle->mUBOUniform) { - mValidHandles.push_back(handle); - handle->mOffset = mConstBufferSize; - mConstBufferSize += handle->getSize(); + handle->mDesc.offset = constBufferSize; + constBufferSize += handle->getSize(); } } - mConstBuffer = new U8[mConstBufferSize]; - dMemset(mConstBuffer, 0, mConstBufferSize); + if (constBufferSize > 0) + { + GFXShaderConstDesc desc; + // fill out ubo desc. + desc.name = "Global"; + desc.bindPoint = -1; + desc.size = constBufferSize; + desc.constType = GFXSCT_ConstBuffer; + desc.samplerReg = -1; + + mBuffers[desc.name] = desc; + + mGlobalConstBuffer = new U8[constBufferSize]; + dMemset(mGlobalConstBuffer, 0, constBufferSize); + } // Set our program so uniforms are assigned properly. mDevice->setShader(this, false); @@ -730,16 +974,16 @@ void GFXGLShader::initHandles() for (HandleMap::Iterator iter = mHandles.begin(); iter != mHandles.end(); ++iter) { GFXGLShaderConstHandle* handle = iter->value; - if(handle->isValid() && + if (handle->isValid() && (handle->getType() == GFXSCT_Sampler || handle->getType() == GFXSCT_SamplerCube || handle->getType() == GFXSCT_SamplerCubeArray || handle->getType() == GFXSCT_SamplerTextureArray)) { // Set sampler number on our program. - glUniform1i(handle->mLocation, handle->mSamplerNum); + glUniform1i(handle->mDesc.bindPoint, handle->mDesc.samplerReg); // Set sampler in constant buffer so it does not get unset later. - dMemcpy(mConstBuffer + handle->mOffset, &handle->mSamplerNum, handle->getSize()); + dMemcpy(mGlobalConstBuffer + handle->mDesc.offset, &handle->mDesc.samplerReg, handle->getSize()); } } @@ -749,14 +993,14 @@ void GFXGLShader::initHandles() U32 offset = 0; - for ( U32 i=0; i < mInstancingFormat->getElementCount(); i++ ) + for (U32 i = 0; i < mInstancingFormat->getElementCount(); i++) { - const GFXVertexElement &element = mInstancingFormat->getElement( i ); + const GFXVertexElement& element = mInstancingFormat->getElement(i); - String constName = String::ToString( "$%s", element.getSemantic().c_str() ); + String constName = String::ToString("$%s", element.getSemantic().c_str()); HandleMap::Iterator handle = mHandles.find(constName); - if ( handle != mHandles.end() ) + if (handle != mHandles.end()) { AssertFatal(0, ""); } @@ -765,7 +1009,7 @@ void GFXGLShader::initHandles() GFXShaderConstDesc desc; desc.name = constName; desc.arraySize = 1; - switch(element.getType()) + switch (element.getType()) { case GFXDeclType_Float4: desc.constType = GFXSCT_Float4; @@ -776,26 +1020,27 @@ void GFXGLShader::initHandles() break; } - GFXGLShaderConstHandle *h = new GFXGLShaderConstHandle( this, desc, -1, -1 ); + GFXGLShaderConstHandle* h = new GFXGLShaderConstHandle(this, desc); h->mInstancingConstant = true; - h->mOffset = offset; - mHandles[constName] = h; + h->mDesc.offset = offset; + h->mUBOUniform = false; + mHandles[constName] = h; offset += element.getSizeInBytes(); ++i; // If this is a matrix we will have 2 or 3 more of these // semantics with the same name after it. - for ( ; i < mInstancingFormat->getElementCount(); i++ ) + for (; i < mInstancingFormat->getElementCount(); i++) { - const GFXVertexElement &nextElement = mInstancingFormat->getElement( i ); - if ( nextElement.getSemantic() != element.getSemantic() ) + const GFXVertexElement& nextElement = mInstancingFormat->getElement(i); + if (nextElement.getSemantic() != element.getSemantic()) { i--; break; } ++desc.arraySize; - if(desc.arraySize == 4 && desc.constType == GFXSCT_Float4) + if (desc.arraySize == 4 && desc.constType == GFXSCT_Float4) { desc.arraySize = 1; desc.constType = GFXSCT_Float4x4; @@ -810,13 +1055,13 @@ void GFXGLShader::initHandles() GFXShaderConstHandle* GFXGLShader::getShaderConstHandle(const String& name) { HandleMap::Iterator i = mHandles.find(name); - if(i != mHandles.end()) + if (i != mHandles.end()) return i->value; else { - GFXGLShaderConstHandle* handle = new GFXGLShaderConstHandle( this ); + GFXGLShaderConstHandle* handle = new GFXGLShaderConstHandle(this); handle->setValid(false); - mHandles[ name ] = handle; + mHandles[name] = handle; return handle; } @@ -825,7 +1070,7 @@ GFXShaderConstHandle* GFXGLShader::getShaderConstHandle(const String& name) GFXShaderConstHandle* GFXGLShader::findShaderConstHandle(const String& name) { HandleMap::Iterator i = mHandles.find(name); - if(i != mHandles.end()) + if (i != mHandles.end()) return i->value; else { @@ -833,79 +1078,92 @@ GFXShaderConstHandle* GFXGLShader::findShaderConstHandle(const String& name) } } -void GFXGLShader::setConstantsFromBuffer(GFXGLShaderConstBuffer* buffer) +void GFXGLShader::setConstantsFromBuffer(U8* buffer) { - for(Vector::iterator i = mValidHandles.begin(); i != mValidHandles.end(); ++i) + for (HandleMap::Iterator i = mHandles.begin(); i != mHandles.end(); ++i) { - GFXGLShaderConstHandle* handle = *i; + GFXGLShaderConstHandle* handle = i->value; AssertFatal(handle, "GFXGLShader::setConstantsFromBuffer - Null handle"); + // skip ubo uniforms. + if (handle->mUBOUniform || !handle->isValid()) + continue; - if(handle->mInstancingConstant) + if (handle->mInstancingConstant) continue; // Don't set if the value has not be changed. - if(dMemcmp(mConstBuffer + handle->mOffset, buffer->mBuffer + handle->mOffset, handle->getSize()) == 0) + if (dMemcmp(mGlobalConstBuffer + handle->mDesc.offset, buffer + handle->mDesc.offset, handle->getSize()) == 0) continue; // Copy new value into our const buffer and set in GL. - dMemcpy(mConstBuffer + handle->mOffset, buffer->mBuffer + handle->mOffset, handle->getSize()); + dMemcpy(mGlobalConstBuffer + handle->mDesc.offset, buffer + handle->mDesc.offset, handle->getSize()); - switch(handle->mDesc.constType) + switch (handle->mDesc.constType) { - case GFXSCT_Float: - glUniform1fv(handle->mLocation, handle->mDesc.arraySize, (GLfloat*)(mConstBuffer + handle->mOffset)); - break; - case GFXSCT_Float2: - glUniform2fv(handle->mLocation, handle->mDesc.arraySize, (GLfloat*)(mConstBuffer + handle->mOffset)); - break; - case GFXSCT_Float3: - glUniform3fv(handle->mLocation, handle->mDesc.arraySize, (GLfloat*)(mConstBuffer + handle->mOffset)); - break; - case GFXSCT_Float4: - glUniform4fv(handle->mLocation, handle->mDesc.arraySize, (GLfloat*)(mConstBuffer + handle->mOffset)); - break; - case GFXSCT_Int: - case GFXSCT_Sampler: - case GFXSCT_SamplerCube: - case GFXSCT_SamplerCubeArray: - case GFXSCT_SamplerTextureArray: - glUniform1iv(handle->mLocation, handle->mDesc.arraySize, (GLint*)(mConstBuffer + handle->mOffset)); - break; - case GFXSCT_Int2: - glUniform2iv(handle->mLocation, handle->mDesc.arraySize, (GLint*)(mConstBuffer + handle->mOffset)); - break; - case GFXSCT_Int3: - glUniform3iv(handle->mLocation, handle->mDesc.arraySize, (GLint*)(mConstBuffer + handle->mOffset)); - break; - case GFXSCT_Int4: - glUniform4iv(handle->mLocation, handle->mDesc.arraySize, (GLint*)(mConstBuffer + handle->mOffset)); - break; - case GFXSCT_Float2x2: - glUniformMatrix2fv(handle->mLocation, handle->mDesc.arraySize, true, (GLfloat*)(mConstBuffer + handle->mOffset)); - break; - case GFXSCT_Float3x3: - glUniformMatrix3fv(handle->mLocation, handle->mDesc.arraySize, true, (GLfloat*)(mConstBuffer + handle->mOffset)); - break; - case GFXSCT_Float4x3: - // NOTE: To save a transpose here we could store the matrix transposed (i.e. column major) in the constant buffer. - // See _mesa_uniform_matrix in the mesa source for the correct transpose algorithm for a 4x3 matrix. - glUniformMatrix4x3fv(handle->mLocation, handle->mDesc.arraySize, true, (GLfloat*)(mConstBuffer + handle->mOffset)); - break; - case GFXSCT_Float4x4: - glUniformMatrix4fv(handle->mLocation, handle->mDesc.arraySize, true, (GLfloat*)(mConstBuffer + handle->mOffset)); - break; - default: - AssertFatal(0,""); - break; + case GFXSCT_Float: + glUniform1fv(handle->mDesc.bindPoint, handle->mDesc.arraySize, (GLfloat*)(mGlobalConstBuffer + handle->mDesc.offset)); + break; + case GFXSCT_Float2: + glUniform2fv(handle->mDesc.bindPoint, handle->mDesc.arraySize, (GLfloat*)(mGlobalConstBuffer + handle->mDesc.offset)); + break; + case GFXSCT_Float3: + glUniform3fv(handle->mDesc.bindPoint, handle->mDesc.arraySize, (GLfloat*)(mGlobalConstBuffer + handle->mDesc.offset)); + break; + case GFXSCT_Float4: + glUniform4fv(handle->mDesc.bindPoint, handle->mDesc.arraySize, (GLfloat*)(mGlobalConstBuffer + handle->mDesc.offset)); + break; + case GFXSCT_Sampler: + case GFXSCT_SamplerCube: + case GFXSCT_SamplerCubeArray: + case GFXSCT_SamplerTextureArray: + // Set sampler number on our program. + glUniform1i(handle->mDesc.bindPoint, handle->mDesc.samplerReg); + break; + case GFXSCT_Int: + glUniform1iv(handle->mDesc.bindPoint, handle->mDesc.arraySize, (GLint*)(mGlobalConstBuffer + handle->mDesc.offset)); + break; + case GFXSCT_Int2: + glUniform2iv(handle->mDesc.bindPoint, handle->mDesc.arraySize, (GLint*)(mGlobalConstBuffer + handle->mDesc.offset)); + break; + case GFXSCT_Int3: + glUniform3iv(handle->mDesc.bindPoint, handle->mDesc.arraySize, (GLint*)(mGlobalConstBuffer + handle->mDesc.offset)); + break; + case GFXSCT_Int4: + glUniform4iv(handle->mDesc.bindPoint, handle->mDesc.arraySize, (GLint*)(mGlobalConstBuffer + handle->mDesc.offset)); + break; + case GFXSCT_Float2x2: + glUniformMatrix2fv(handle->mDesc.bindPoint, handle->mDesc.arraySize, true, (GLfloat*)(mGlobalConstBuffer + handle->mDesc.offset)); + break; + case GFXSCT_Float3x3: + glUniformMatrix3fv(handle->mDesc.bindPoint, handle->mDesc.arraySize, true, (GLfloat*)(mGlobalConstBuffer + handle->mDesc.offset)); + break; + case GFXSCT_Float4x3: + // NOTE: To save a transpose here we could store the matrix transposed (i.e. column major) in the constant buffer. + // See _mesa_uniform_matrix in the mesa source for the correct transpose algorithm for a 4x3 matrix. + glUniformMatrix4x3fv(handle->mDesc.bindPoint, handle->mDesc.arraySize, true, (GLfloat*)(mGlobalConstBuffer + handle->mDesc.offset)); + break; + case GFXSCT_Float4x4: + glUniformMatrix4fv(handle->mDesc.bindPoint, handle->mDesc.arraySize, true, (GLfloat*)(mGlobalConstBuffer + handle->mDesc.offset)); + break; + default: + AssertFatal(0, ""); + break; } + } } GFXShaderConstBufferRef GFXGLShader::allocConstBuffer() { - GFXGLShaderConstBuffer* buffer = new GFXGLShaderConstBuffer(this, mConstBufferSize, mConstBuffer); + GFXGLShaderConstBuffer* buffer = new GFXGLShaderConstBuffer(this); + for (BufferMap::Iterator i = mBuffers.begin(); i != mBuffers.end(); ++i) + { + // add our buffer descriptions to the full const buffer. + buffer->addBuffer(i->value.bindPoint, i->value.size); + } + buffer->registerResourceWithDevice(getOwningDevice()); - mActiveBuffers.push_back( buffer ); + mActiveBuffers.push_back(buffer); return buffer; } @@ -917,10 +1175,9 @@ void GFXGLShader::useProgram() void GFXGLShader::zombify() { clearShaders(); - dMemset(mConstBuffer, 0, mConstBufferSize); } -char* GFXGLShader::_handleIncludes( const Torque::Path& path, FileStream *s ) +char* GFXGLShader::_handleIncludes(const Torque::Path& path, FileStream* s) { // TODO: The #line pragma on GLSL takes something called a // "source-string-number" which it then never explains. @@ -937,18 +1194,18 @@ char* GFXGLShader::_handleIncludes( const Torque::Path& path, FileStream *s ) buffer[shaderLen] = 0; char* p = dStrstr(buffer, "#include"); - while(p) + while (p) { char* q = p; p += 8; - if(dIsspace(*p)) + if (dIsspace(*p)) { U32 n = 0; - while(dIsspace(*p)) ++p; + while (dIsspace(*p)) ++p; AssertFatal(*p == '"', "Bad #include directive"); ++p; static char includeFile[256]; - while(*p != '"') + while (*p != '"') { AssertFatal(*p != 0, "Bad #include directive"); includeFile[n++] = *p++; @@ -963,19 +1220,19 @@ char* GFXGLShader::_handleIncludes( const Torque::Path& path, FileStream *s ) FileStream includeStream; - if ( !includeStream.open( includePath, Torque::FS::File::Read ) ) + if (!includeStream.open(includePath, Torque::FS::File::Read)) { // Try again assuming the path is absolute // and/or relative. - includePath = String( includeFile ); + includePath = String(includeFile); includePath = Torque::Path::CompressPath(includePath); - if ( !includeStream.open( includePath, Torque::FS::File::Read ) ) + if (!includeStream.open(includePath, Torque::FS::File::Read)) { AssertISV(false, avar("failed to open include '%s'.", includePath.getFullPath().c_str())); - if ( smLogErrors ) - Con::errorf( "GFXGLShader::_handleIncludes - Failed to open include '%s'.", - includePath.getFullPath().c_str() ); + if (smLogErrors) + Con::errorf("GFXGLShader::_handleIncludes - Failed to open include '%s'.", + includePath.getFullPath().c_str()); // Fail... don't return the buffer. dFree(buffer); @@ -986,7 +1243,7 @@ char* GFXGLShader::_handleIncludes( const Torque::Path& path, FileStream *s ) char* includedText = _handleIncludes(includePath, &includeStream); // If a sub-include fails... cleanup and return. - if ( !includedText ) + if (!includedText) { dFree(buffer); return NULL; @@ -1010,7 +1267,7 @@ char* GFXGLShader::_handleIncludes( const Torque::Path& path, FileStream *s ) */ String manip(buffer); - manip.erase(q-buffer, p-q); + manip.erase(q - buffer, p - q); String sItx(includedText); // TODO: Disabled till this is fixed correctly. @@ -1020,7 +1277,7 @@ char* GFXGLShader::_handleIncludes( const Torque::Path& path, FileStream *s ) //sItx += String::ToString( "\r\n#line %d \r\n", includeLine ); dFree(includedText); - manip.insert(q-buffer, sItx); + manip.insert(q - buffer, sItx); char* manipBuf = dStrdup(manip.c_str()); p = manipBuf + (q - buffer); dFree(buffer); @@ -1032,18 +1289,18 @@ char* GFXGLShader::_handleIncludes( const Torque::Path& path, FileStream *s ) return buffer; } -bool GFXGLShader::_loadShaderFromStream( GLuint shader, - const Torque::Path &path, - FileStream *s, - const Vector ¯os ) +bool GFXGLShader::_loadShaderFromStream(GLuint shader, + const Torque::Path& path, + FileStream* s, + const Vector& macros) { Vector buffers; Vector lengths; // The GLSL version declaration must go first! - const char *versionDecl = "#version 330\n"; - buffers.push_back( dStrdup( versionDecl ) ); - lengths.push_back( dStrlen( versionDecl ) ); + const char* versionDecl = "#version 330\n"; + buffers.push_back(dStrdup(versionDecl)); + lengths.push_back(dStrlen(versionDecl)); //Required extensions. These are already checked when creating the GFX adapter, if we make it this far it's supported const char* cubeArrayExt = "#extension GL_ARB_texture_cube_map_array : enable\n"; @@ -1059,20 +1316,20 @@ bool GFXGLShader::_loadShaderFromStream( GLuint shader, lengths.push_back(dStrlen(newLine)); // Now add all the macros. - for( U32 i = 0; i < macros.size(); i++ ) + for (U32 i = 0; i < macros.size(); i++) { - if(macros[i].name.isEmpty()) // TODO OPENGL + if (macros[i].name.isEmpty()) // TODO OPENGL continue; - String define = String::ToString( "#define %s %s\n", macros[i].name.c_str(), macros[i].value.c_str() ); - buffers.push_back( dStrdup( define.c_str() ) ); - lengths.push_back( define.length() ); + String define = String::ToString("#define %s %s\n", macros[i].name.c_str(), macros[i].value.c_str()); + buffers.push_back(dStrdup(define.c_str())); + lengths.push_back(define.length()); } // Now finally add the shader source. U32 shaderLen = s->getStreamSize(); - char *buffer = _handleIncludes(path, s); - if ( !buffer ) + char* buffer = _handleIncludes(path, s); + if (!buffer) return false; buffers.push_back(buffer); @@ -1082,31 +1339,31 @@ bool GFXGLShader::_loadShaderFromStream( GLuint shader, #if defined(TORQUE_DEBUG) && defined(TORQUE_DEBUG_GFX) FileStream stream; - if ( !stream.open( path.getFullPath()+"_DEBUG", Torque::FS::File::Write ) ) + if (!stream.open(path.getFullPath() + "_DEBUG", Torque::FS::File::Write)) { AssertISV(false, avar("GFXGLShader::initShader - failed to write debug shader '%s'.", path.getFullPath().c_str())); } - for(int i = 0; i < buffers.size(); ++i) - stream.writeText(buffers[i]); + for (int i = 0; i < buffers.size(); ++i) + stream.writeText(buffers[i]); #endif // Cleanup the shader source buffer. - for ( U32 i=0; i < buffers.size(); i++ ) - dFree( buffers[i] ); + for (U32 i = 0; i < buffers.size(); i++) + dFree(buffers[i]); glCompileShader(shader); return true; } -bool GFXGLShader::initShader( const Torque::Path &file, - GFXShaderStage stage, - const Vector ¯os ) +bool GFXGLShader::initShader(const Torque::Path& file, + GFXShaderStage stage, + const Vector& macros) { PROFILE_SCOPE(GFXGLShader_CompileShader); - GLuint activeShader; + GLuint activeShader = 0; switch (stage) { @@ -1136,13 +1393,13 @@ bool GFXGLShader::initShader( const Torque::Path &file, // Ok it's not in the shader gen manager, so ask Torque for it FileStream stream; - if ( !stream.open( file, Torque::FS::File::Read ) ) + if (!stream.open(file, Torque::FS::File::Read)) { AssertISV(false, avar("GFXGLShader::initShader - failed to open shader '%s'.", file.getFullPath().c_str())); - if ( smLogErrors ) - Con::errorf( "GFXGLShader::initShader - Failed to open shader file '%s'.", - file.getFullPath().c_str() ); + if (smLogErrors) + Con::errorf("GFXGLShader::initShader - Failed to open shader file '%s'.", + file.getFullPath().c_str()); return false; } @@ -1160,22 +1417,22 @@ bool GFXGLShader::initShader( const Torque::Path &file, U32 logLength = 0; glGetShaderiv(activeShader, GL_INFO_LOG_LENGTH, (GLint*)&logLength); - if ( logLength ) + if (logLength) { FrameAllocatorMarker fam; char* log = (char*)fam.alloc(logLength); glGetShaderInfoLog(activeShader, logLength, NULL, log); - if (compile == GL_FALSE ) + if (compile == GL_FALSE) { - if ( smLogErrors ) + if (smLogErrors) { - Con::errorf( "GFXGLShader::initShader - Error compiling shader!" ); - Con::errorf( "Program %s: %s", file.getFullPath().c_str(), log ); + Con::errorf("GFXGLShader::initShader - Error compiling shader!"); + Con::errorf("Program %s: %s", file.getFullPath().c_str(), log); } } - else if ( smLogWarnings ) - Con::warnf( "Program %s: %s", file.getFullPath().c_str(), log ); + else if (smLogWarnings) + Con::warnf("Program %s: %s", file.getFullPath().c_str(), log); } return compile != GL_FALSE; @@ -1185,7 +1442,7 @@ bool GFXGLShader::initShader( const Torque::Path &file, const Vector& GFXGLShader::getShaderConstDesc() const { PROFILE_SCOPE(GFXGLShader_GetShaderConstants); - return mConstants; + return mShaderConsts; } /// Returns the alignment value for constType diff --git a/Engine/source/gfx/gl/gfxGLShader.h b/Engine/source/gfx/gl/gfxGLShader.h index 1c88a95f3..ee8b53dc6 100644 --- a/Engine/source/gfx/gl/gfxGLShader.h +++ b/Engine/source/gfx/gl/gfxGLShader.h @@ -29,96 +29,95 @@ #include "core/util/tSignal.h" #include "core/util/tDictionary.h" -class GFXGLShaderConstHandle; class FileStream; -class GFXGLShaderConstBuffer; class GFXGLDevice; +class GFXGLShader; -class GFXGLShader : public GFXShader +struct BufferRange { - typedef Map HandleMap; + U32 mBufMin = U32_MAX; + U32 mBufMax = 0; + + inline void addSlot(U32 slot) + { + mBufMin = getMin(mBufMin, slot); + mBufMax = getMax(mBufMax, slot); + } + + inline bool isValid() const { return mBufMin <= mBufMax; } +}; + +struct ConstantBuffer +{ + GLuint bufHandle; + U8* data; + U32 size; + bool isDirty; +}; + +class GFXGLShaderConstHandle : public GFXShaderConstHandle +{ + friend class GFXGLShader; + public: - GFXGLShader(GFXGLDevice* device); - virtual ~GFXGLShader(); + // DX side needs the description map as the same uniform can exist across stages. for gl it is program wide. + GFXGLShaderConstHandle(GFXGLShader* shader); + GFXGLShaderConstHandle(GFXGLShader* shader, + const GFXShaderConstDesc& desc); - /// @name GFXShader interface - /// @{ - virtual GFXShaderConstHandle* getShaderConstHandle(const String& name); - virtual GFXShaderConstHandle* findShaderConstHandle(const String& name); + void reinit(const GFXShaderConstDesc& desc); - /// Returns our list of shader constants, the material can get this and just set the constants it knows about - virtual const Vector& getShaderConstDesc() const; + virtual ~GFXGLShaderConstHandle(); + const GFXShaderConstDesc getDesc(); + const String& getName() const { return mDesc.name; } + GFXShaderConstType getType() const { return mDesc.constType; } + U32 getArraySize() const { return mDesc.arraySize; } - /// Returns the alignment value for constType - virtual U32 getAlignmentValue(const GFXShaderConstType constType) const; + U32 getSize() const { return mDesc.size; } + 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 (!isSampler() || !mValid) ? -1 : mDesc.samplerReg; } - virtual GFXShaderConstBufferRef allocConstBuffer(); + // Returns true if this is a handle to a sampler register. + bool isSampler() const + { + return (getType() >= GFXSCT_Sampler); + } - /// @} + /// Restore to uninitialized state. + void clear() + { + mShader = NULL; + mInstancingConstant = false; + mValid = false; + } - /// @name GFXResource interface - /// @{ - virtual void zombify(); - virtual void resurrect() { reload(); } - virtual const String describeSelf() const; - /// @} - - /// Activates this shader in the GL context. - void useProgram(); - -protected: - - friend class GFXGLShaderConstBuffer; - friend class GFXGLShaderConstHandle; - - virtual bool _init(); - - bool initShader( const Torque::Path &file, - GFXShaderStage stage, - const Vector ¯os ); - - void clearShaders(); - void initConstantDescs(); - void initHandles(); - void setConstantsFromBuffer(GFXGLShaderConstBuffer* buffer); - - static char* _handleIncludes( const Torque::Path &path, FileStream *s ); - - static bool _loadShaderFromStream( GLuint shader, - const Torque::Path& path, - FileStream* s, - const Vector& macros ); - - /// @name Internal GL handles - /// @{ - GLuint mVertexShader; - GLuint mPixelShader; - GLuint mGeometryShader; - GLuint mProgram; - /// @} - - Vector mConstants; - U32 mConstBufferSize; - U8* mConstBuffer; - HandleMap mHandles; - GFXGLDevice* mDevice; - Vector mValidHandles; + GFXShaderConstDesc mDesc; + GFXGLShader* mShader; + bool mUBOUniform; + bool mInstancingConstant; }; class GFXGLShaderConstBuffer : public GFXShaderConstBuffer { public: - GFXGLShaderConstBuffer(GFXGLShader* shader, U32 bufSize, U8* existingConstants); + // -1 is the global buffer. + typedef Map BufferMap; + + GFXGLShaderConstBuffer(GFXGLShader* shader); ~GFXGLShaderConstBuffer(); /// Called by GFXGLDevice to activate this buffer. - void activate(); + void activate(GFXGLShaderConstBuffer* prevShaderBuffer); + + void addBuffer(S32 bufBindingPoint, U32 size); /// Called when the shader this buffer references is reloaded. - void onShaderReload( GFXGLShader *shader ); + void onShaderReload(GFXGLShader* shader); // GFXShaderConstBuffer - virtual GFXShader* getShader() { return mShader; } + virtual GFXShader* getShader(); virtual void set(GFXShaderConstHandle* handle, const F32 fv); virtual void set(GFXShaderConstHandle* handle, const Point2F& fv); virtual void set(GFXShaderConstHandle* handle, const Point3F& fv); @@ -148,8 +147,9 @@ public: private: friend class GFXGLShader; - U8* mBuffer; + WeakRefPtr mShader; + BufferMap mBufferMap; template void internalSet(GFXShaderConstHandle* handle, const ConstType& param); @@ -158,4 +158,80 @@ private: void internalSet(GFXShaderConstHandle* handle, const AlignedArray& fv); }; +class GFXGLShader : public GFXShader +{ + friend class GFXGLShaderConstBuffer; + friend class GFXGLShaderConstHandle; +public: + typedef Map HandleMap; + typedef Map BufferMap; + + GFXGLShader(GFXGLDevice* device); + virtual ~GFXGLShader(); + + /// @name GFXShader interface + /// @{ + virtual GFXShaderConstHandle* getShaderConstHandle(const String& name); + virtual GFXShaderConstHandle* findShaderConstHandle(const String& name); + + /// Returns our list of shader constants, the material can get this and just set the constants it knows about + virtual const Vector& getShaderConstDesc() const; + + /// Returns the alignment value for constType + virtual U32 getAlignmentValue(const GFXShaderConstType constType) const; + + virtual GFXShaderConstBufferRef allocConstBuffer(); + + /// @} + + /// @name GFXResource interface + /// @{ + virtual void zombify(); + virtual void resurrect() { reload(); } + virtual const String describeSelf() const; + /// @} + + /// Activates this shader in the GL context. + void useProgram(); + +protected: + virtual bool _init(); + + bool initShader(const Torque::Path& file, + GFXShaderStage stage, + const Vector& macros); + + void clearShaders(); + + void initConstantDescs(); + void initHandles(); + void setConstantsFromBuffer(U8* buffer); + + static char* _handleIncludes(const Torque::Path& path, FileStream* s); + + static bool _loadShaderFromStream(GLuint shader, + const Torque::Path& path, + FileStream* s, + const Vector& macros); + + /// @name Internal GL handles + /// @{ + GLuint mVertexShader; + GLuint mPixelShader; + GLuint mGeometryShader; + GLuint mProgram; + /// @} + + U8* mGlobalConstBuffer; + + Vector mShaderConsts; + + HandleMap mHandles; + BufferMap mBuffers; + + GFXGLDevice* mDevice; + + GFXShaderConstType convertConstType(GLenum constType); +}; + #endif // _GFXGLSHADER_H_ From e6c653c441b87440179153f6b2eb028500491e87 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Thu, 14 Mar 2024 08:28:11 +0000 Subject: [PATCH 46/53] warnings cleanup cleanup and some warning fixes --- Engine/source/gfx/D3D11/gfxD3D11Shader.cpp | 10 ++++- .../source/gfx/bitmap/loaders/bitmapSTB.cpp | 10 +++-- Engine/source/gfx/gfxEnums.h | 39 ++++++++++--------- Engine/source/gfx/gfxShader.h | 6 +-- Engine/source/gfx/gl/gfxGLShader.cpp | 4 +- .../gui/shaderEditor/guiShaderEditor.cpp | 4 +- Engine/source/scene/sceneQueryUtil.h | 6 +-- .../shaderGen/HLSL/debugVizFeatureHLSL.cpp | 18 ++++----- 8 files changed, 55 insertions(+), 42 deletions(-) diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp index 78f22f8c9..7a2b7d515 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp @@ -469,6 +469,12 @@ void GFXD3D11ShaderConstBuffer::addBuffer(U32 bufBindingPoint, GFXShaderStage sh } } + // no shaderstage defined? cannot be!!! + if (shaderStageID == -1) + { + AssertFatal(false, "DX Const buffer requires a shaderStage flag."); + } + const BufferKey bufKey(bufBindingPoint, shaderStageID); // doesnt matter if its already added. U8* buf = new U8[size]; @@ -572,8 +578,8 @@ void GFXD3D11ShaderConstBuffer::activate( GFXD3D11ShaderConstBuffer *prevShaderB D3D11DEVICECONTEXT->GSSetConstantBuffers(bufStartSlot, numBufs, psBuffers); } - mWasLost = false; + } void GFXD3D11ShaderConstBuffer::onShaderReload( GFXD3D11Shader *shader ) @@ -1091,6 +1097,8 @@ GFXShaderConstType GFXD3D11Shader::convertConstType(const D3D11_SHADER_TYPE_DESC } } + return GFXSCT_Uknown; + } void GFXD3D11Shader::_buildShaderConstantHandles() diff --git a/Engine/source/gfx/bitmap/loaders/bitmapSTB.cpp b/Engine/source/gfx/bitmap/loaders/bitmapSTB.cpp index 6eb79895c..d4a6455b4 100644 --- a/Engine/source/gfx/bitmap/loaders/bitmapSTB.cpp +++ b/Engine/source/gfx/bitmap/loaders/bitmapSTB.cpp @@ -34,6 +34,9 @@ #define STBIWDEF static inline #endif +#pragma warning( push ) +#pragma warning( disable : 4505 ) // unreferenced function removed. + #define STB_IMAGE_IMPLEMENTATION #define STB_IMAGE_STATIC #include "stb_image.h" @@ -42,6 +45,8 @@ #define STB_IMAGE_WRITE_STATIC #include "stb_image_write.h" +#pragma warning(pop) + static bool sReadSTB(const Torque::Path& path, GBitmap* bitmap); static bool sReadStreamSTB(Stream& stream, GBitmap* bitmap, U32 len); @@ -147,7 +152,7 @@ bool sReadSTB(const Torque::Path& path, GBitmap* bitmap) U32 buffSize = readIes->getStreamSize(); char* buffer = new char[buffSize]; readIes->read(buffSize, buffer); - + IESFileInfo info; IESLoadHelper IESLoader; @@ -399,8 +404,6 @@ bool sWriteSTB(const Torque::Path& path, GBitmap* bitmap, U32 compressionLevel) String ext = path.getExtension(); - - U32 stride = width * bytes; // we always have at least 1 U32 comp = 1; @@ -554,7 +557,6 @@ void DeferredPNGWriter::append(GBitmap* bitmap, U32 rows) mData->channels = bitmap->getBytesPerPixel(); } - const U32 height = getMin(bitmap->getHeight(), rows); const dsize_t dataChuckSize = bitmap->getByteSize(); const U8* pSrcData = bitmap->getBits(); diff --git a/Engine/source/gfx/gfxEnums.h b/Engine/source/gfx/gfxEnums.h index 83e0bfccb..cc670f6a6 100644 --- a/Engine/source/gfx/gfxEnums.h +++ b/Engine/source/gfx/gfxEnums.h @@ -64,7 +64,7 @@ enum GFXTexCallbackCode GFXResurrect, }; -enum GFXPrimitiveType +enum GFXPrimitiveType { GFXPT_FIRST = 0, GFXPointList = 0, @@ -75,7 +75,7 @@ enum GFXPrimitiveType GFXPT_COUNT }; -enum GFXBitmapFlip +enum GFXBitmapFlip { GFXBitmapFlip_None = 0, GFXBitmapFlip_X = 1 << 0, @@ -83,7 +83,7 @@ enum GFXBitmapFlip GFXBitmapFlip_XY = GFXBitmapFlip_X | GFXBitmapFlip_Y }; -enum GFXTextureAddressMode +enum GFXTextureAddressMode { GFXAddress_FIRST = 0, GFXAddressWrap = 0, @@ -94,7 +94,7 @@ enum GFXTextureAddressMode GFXAddress_COUNT }; -enum GFXTextureFilterType +enum GFXTextureFilterType { GFXTextureFilter_FIRST = 0, GFXTextureFilterNone = 0, @@ -104,7 +104,7 @@ enum GFXTextureFilterType GFXTextureFilter_COUNT }; -enum GFXFillMode +enum GFXFillMode { GFXFill_FIRST = 1, GFXFillPoint = 1, @@ -113,7 +113,7 @@ enum GFXFillMode GFXFill_COUNT }; -enum GFXFormat +enum GFXFormat { // when adding formats make sure to place // them in the correct group! @@ -152,7 +152,7 @@ enum GFXFormat GFXFormatR11G11B10, GFXFormatD32, GFXFormatD24X8, - GFXFormatD24S8, + GFXFormatD24S8, GFXFormatD24FS8, // Guaranteed RGBA8 (for apis which really dont like bgr) @@ -172,7 +172,7 @@ enum GFXFormat GFXFormatBC3, //dxt4/5 GFXFormatBC4, //3dc+ / ati1 GFXFormatBC5, //3dc / ati2 - // compressed sRGB formats + // compressed sRGB formats GFXFormatBC1_SRGB, GFXFormatBC2_SRGB, GFXFormatBC3_SRGB, @@ -191,7 +191,7 @@ enum GFXFormat /// Returns the byte size of the pixel for non-compressed formats. inline U32 GFXFormat_getByteSize( GFXFormat format ) { - AssertFatal( format < GFXFormat_UNKNOWNSIZE, + AssertFatal( format < GFXFormat_UNKNOWNSIZE, "GFXDevice::formatByteSize - Cannot size a compressed format!" ); if ( format < GFXFormat_16BIT ) @@ -205,12 +205,12 @@ inline U32 GFXFormat_getByteSize( GFXFormat format ) else if ( format < GFXFormat_128BIT ) return 8;// 64 bit... - // This should be 128bits... else its a DDS and + // This should be 128bits... else its a DDS and // the assert should have gone off above. return 16; } -enum GFXClearFlags +enum GFXClearFlags { GFXClearTarget = 1 << 0, GFXClearZBuffer = 1 << 1, @@ -218,7 +218,7 @@ enum GFXClearFlags }; /// The supported blend modes. -enum GFXBlend +enum GFXBlend { GFXBlend_FIRST = 0, GFXBlendZero = 0, /// (0, 0, 0, 0) @@ -238,7 +238,7 @@ enum GFXBlend /// Constants that name each GFXDevice type. Any new GFXDevice subclass must be /// added to this enum. A string representing its name must also be added to /// GFXInit::getAdapterNameFromType(). -enum GFXAdapterType +enum GFXAdapterType { OpenGL = 0, Direct3D11, @@ -255,7 +255,7 @@ enum GFXCullMode GFXCull_COUNT }; -enum GFXCmpFunc +enum GFXCmpFunc { GFXCmp_FIRST = 0, GFXCmpNever = 0, @@ -269,7 +269,7 @@ enum GFXCmpFunc GFXCmp_COUNT }; -enum GFXStencilOp +enum GFXStencilOp { GFXStencilOp_FIRST = 0, GFXStencilOpKeep = 0, @@ -283,8 +283,8 @@ enum GFXStencilOp GFXStencilOp_COUNT }; -enum GFXBlendOp -{ +enum GFXBlendOp +{ GFXBlendOp_FIRST = 0, GFXBlendOpAdd = 0, GFXBlendOpSubtract, @@ -294,7 +294,7 @@ enum GFXBlendOp GFXBlendOp_COUNT }; -enum GFXMatrixType +enum GFXMatrixType { GFXMatrixWorld = 256, GFXMatrixView = 2, @@ -312,6 +312,7 @@ enum GFXMatrixType enum GFXShaderConstType { + GFXSCT_Uknown, /// GFX"S"hader"C"onstant"T"ype GFXSCT_ConstBuffer, // Scalar @@ -365,7 +366,7 @@ enum GFXDeclType /// @see Point2F GFXDeclType_Float2, - /// A three-component F32. + /// A three-component F32. /// @see Point3F GFXDeclType_Float3, diff --git a/Engine/source/gfx/gfxShader.h b/Engine/source/gfx/gfxShader.h index 0a5ed19c4..4edcdce7d 100644 --- a/Engine/source/gfx/gfxShader.h +++ b/Engine/source/gfx/gfxShader.h @@ -79,14 +79,14 @@ enum GFXShaderStage struct GFXShaderConstDesc { public: - String name; - GFXShaderConstType constType; + String name = String::EmptyString; + GFXShaderConstType constType = GFXSCT_Uknown; U32 arraySize = 0; // > 1 means it is an array! S32 bindPoint = -1; // bind point used for ubo/cb S32 samplerReg = -1; // sampler register. U32 offset = 0; // offset for vars U32 size = 0; // size of buffer/type - GFXShaderStage shaderStage; // only used dx side. + GFXShaderStage shaderStage = VERTEX_SHADER; // only used dx side.not wasting a bit for an unknown? }; /// This is an opaque handle used by GFXShaderConstBuffer clients to set individual shader constants. diff --git a/Engine/source/gfx/gl/gfxGLShader.cpp b/Engine/source/gfx/gl/gfxGLShader.cpp index 9a15be4f8..fd2da2f3f 100644 --- a/Engine/source/gfx/gl/gfxGLShader.cpp +++ b/Engine/source/gfx/gl/gfxGLShader.cpp @@ -868,10 +868,12 @@ GFXShaderConstType GFXGLShader::convertConstType(GLenum constType) return GFXSCT_SamplerTextureArray; break; default: - AssertFatal(false, "GFXGLShader::initConstantDescs - unrecognized uniform type"); + AssertFatal(false, "Unknown shader constant class enum, maybe you could add it?"); // If we don't recognize the constant don't add its description. break; } + + return GFXSCT_Uknown; } void GFXGLShader::initHandles() diff --git a/Engine/source/gui/shaderEditor/guiShaderEditor.cpp b/Engine/source/gui/shaderEditor/guiShaderEditor.cpp index 2de12705e..7d0415296 100644 --- a/Engine/source/gui/shaderEditor/guiShaderEditor.cpp +++ b/Engine/source/gui/shaderEditor/guiShaderEditor.cpp @@ -598,7 +598,7 @@ bool GuiShaderEditor::onMouseWheelUp(const GuiEvent& event) if (!mActive || !mAwake || !mVisible) return Parent::onMouseWheelUp(event); - mZoomScale *= 1.1; + mZoomScale *= 1.1f; return true; } @@ -608,7 +608,7 @@ bool GuiShaderEditor::onMouseWheelDown(const GuiEvent& event) if (!mActive || !mAwake || !mVisible) return Parent::onMouseWheelDown(event); - mZoomScale *= 0.9; + mZoomScale *= 0.9f; return true; } diff --git a/Engine/source/scene/sceneQueryUtil.h b/Engine/source/scene/sceneQueryUtil.h index d53af4b17..5c913127b 100644 --- a/Engine/source/scene/sceneQueryUtil.h +++ b/Engine/source/scene/sceneQueryUtil.h @@ -5,7 +5,7 @@ /// allows it to return the appropriate geometry. enum PolyListContext { - /// A hint that the polyist is intended + /// A hint that the polyist is intended /// for collision testing. PLC_Collision, @@ -24,7 +24,7 @@ enum PolyListContext /// A hint that the polyist will be used /// to export geometry and would like to have - /// texture coords and materials. + /// texture coords and materials. PLC_Export }; @@ -71,7 +71,7 @@ struct SceneBinRange inline bool isGlobal() const { return minCoord[0] == 0 && - minCoord[0] == 0 && + minCoord[1] == 0 && maxCoord[0] == 0xFFFF && maxCoord[1] == 0xFFFF; } diff --git a/Engine/source/shaderGen/HLSL/debugVizFeatureHLSL.cpp b/Engine/source/shaderGen/HLSL/debugVizFeatureHLSL.cpp index bef95f4fd..72c50cd40 100644 --- a/Engine/source/shaderGen/HLSL/debugVizFeatureHLSL.cpp +++ b/Engine/source/shaderGen/HLSL/debugVizFeatureHLSL.cpp @@ -122,13 +122,13 @@ void DebugVizHLSL::processPix(Vector& componentList, if (fd.features[MFT_LightMap] || fd.features[MFT_ToneMap] || fd.features[MFT_VertLit]) return; - MultiLine* meta = new MultiLine; + MultiLine* newMeta = new MultiLine; // Now the wsPosition and wsView. Var* worldToTangent = getInWorldToTangent(componentList); Var* wsNormal = getInWorldNormal(componentList); Var* wsPosition = getInWsPosition(componentList); - Var* wsView = getWsView(wsPosition, meta); + Var* wsView = getWsView(wsPosition, newMeta); //Reflection Probe WIP U32 MAX_FORWARD_PROBES = 4; @@ -153,32 +153,32 @@ void DebugVizHLSL::processPix(Vector& componentList, Var* showAttenVar = new Var("showAttenVar", "int"); char buf[64]; dSprintf(buf, sizeof(buf), " @ = %s;\r\n", showAtten); - meta->addStatement(new GenOp(buf, new DecOp(showAttenVar))); + newMeta->addStatement(new GenOp(buf, new DecOp(showAttenVar))); Var* showContribVar = new Var("showContribVar", "int"); dSprintf(buf, sizeof(buf), " @ = %s;\r\n", showContrib); - meta->addStatement(new GenOp(buf, new DecOp(showContribVar))); + newMeta->addStatement(new GenOp(buf, new DecOp(showContribVar))); Var* showSpecVar = new Var("showSpecVar", "int"); dSprintf(buf, sizeof(buf), " @ = %s;\r\n", showSpec); - meta->addStatement(new GenOp(buf, new DecOp(showSpecVar))); + newMeta->addStatement(new GenOp(buf, new DecOp(showSpecVar))); Var* showDiffVar = new Var("showDiffVar", "int"); dSprintf(buf, sizeof(buf), " @ = %s;\r\n", showDiff); - meta->addStatement(new GenOp(buf, new DecOp(showDiffVar))); + newMeta->addStatement(new GenOp(buf, new DecOp(showDiffVar))); String computeForwardProbes = String(" @ = debugVizForwardProbes(@,@,@,@,@,@,@,@,\r\n\t\t"); computeForwardProbes += String("@,TORQUE_SAMPLER2D_MAKEARG(@),\r\n\t\t"); computeForwardProbes += String("TORQUE_SAMPLERCUBEARRAY_MAKEARG(@),TORQUE_SAMPLERCUBEARRAY_MAKEARG(@), @, @, @, @).rgb; \r\n"); - meta->addStatement(new GenOp(computeForwardProbes.c_str(), ibl, surface, cubeMips, numProbes, worldToObjArray, probeConfigData, inProbePosArray, refScaleArray, inRefPosArray, + newMeta->addStatement(new GenOp(computeForwardProbes.c_str(), ibl, surface, cubeMips, numProbes, worldToObjArray, probeConfigData, inProbePosArray, refScaleArray, inRefPosArray, skylightCubemapIdx, BRDFTexture, irradianceCubemapAR, specularCubemapAR, showAttenVar, showContribVar, showSpecVar, showDiffVar)); - meta->addStatement(new GenOp(" @.rgb = @.rgb;\r\n", color, ibl)); + newMeta->addStatement(new GenOp(" @.rgb = @.rgb;\r\n", color, ibl)); - output = meta; + output = newMeta; return; } } From bd7bbd782c76a3548408fc94d1a50691aa2a143e Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Thu, 14 Mar 2024 08:32:29 +0000 Subject: [PATCH 47/53] Revert "Merge branch 'development' into ShaderConstBuffer-CleanupRefactor" This reverts commit ae11d996d9d3ca6577099f5daa0ade1fe55c8d82, reversing changes made to e6c653c441b87440179153f6b2eb028500491e87. --- .github/workflows/build-windows-msvc.yml | 1 + .github/workflows/test-results-linux.yml | 1 + Engine/source/console/arrayObject.cpp | 22 ------------------- Engine/source/console/arrayObject.h | 6 +---- .../utility/scripts/helperFunctions.tscript | 2 +- 5 files changed, 4 insertions(+), 28 deletions(-) diff --git a/.github/workflows/build-windows-msvc.yml b/.github/workflows/build-windows-msvc.yml index 6dd243048..ee642d711 100644 --- a/.github/workflows/build-windows-msvc.yml +++ b/.github/workflows/build-windows-msvc.yml @@ -9,6 +9,7 @@ concurrency: cancel-in-progress: true jobs: build-windows: + if: github.repository == 'TorqueGameEngines/Torque3D' name: ${{matrix.config.name}} runs-on: windows-latest strategy: diff --git a/.github/workflows/test-results-linux.yml b/.github/workflows/test-results-linux.yml index 7f61a8c5f..23a6b7a23 100644 --- a/.github/workflows/test-results-linux.yml +++ b/.github/workflows/test-results-linux.yml @@ -21,6 +21,7 @@ jobs: runos: ubuntu-latest, artifact-name: "torque3dLinuxGCCUnitTest" } + steps: - name: Download Linux Test Report uses: dawidd6/action-download-artifact@v2 diff --git a/Engine/source/console/arrayObject.cpp b/Engine/source/console/arrayObject.cpp index d5eaffe98..cfd25d6cb 100644 --- a/Engine/source/console/arrayObject.cpp +++ b/Engine/source/console/arrayObject.cpp @@ -404,22 +404,6 @@ void ArrayObject::uniqueKey() //----------------------------------------------------------------------------- -void ArrayObject::uniquePair() -{ - for (S32 i = 0; i < mArray.size(); i++) - { - for (S32 j = i + 1; j < mArray.size(); j++) - { - if (isEqual(mArray[i].key, mArray[j].key) && isEqual(mArray[i].value, mArray[j].value)) - { - erase(j); - j--; - } - } - } -} -//----------------------------------------------------------------------------- - void ArrayObject::duplicate(ArrayObject* obj) { empty(); @@ -756,12 +740,6 @@ DefineEngineMethod( ArrayObject, uniqueKey, void, (),, object->uniqueKey(); } -DefineEngineMethod(ArrayObject, uniquePair, void, (), , - "Removes any elements that have duplicated key and value pairs (leaving the first instance)") -{ - object->uniquePair(); -} - DefineEngineMethod( ArrayObject, duplicate, bool, ( ArrayObject* target ),, "Alters array into an exact duplicate of the target array.\n" "@param target ArrayObject to duplicate\n" ) diff --git a/Engine/source/console/arrayObject.h b/Engine/source/console/arrayObject.h index cde4f92b6..81531b6c2 100644 --- a/Engine/source/console/arrayObject.h +++ b/Engine/source/console/arrayObject.h @@ -158,10 +158,6 @@ public: /// (keeps the first instance only) void uniqueKey(); - /// Removes any duplicate keys from the array - /// (keeps the first instance only) - void uniquePair(); - /// Makes this array an exact duplicate of another array void duplicate( ArrayObject *obj ); @@ -233,4 +229,4 @@ public: static void initPersistFields(); }; -#endif // _ARRAYOBJECT_H_ +#endif // _ARRAYOBJECT_H_ \ No newline at end of file diff --git a/Templates/BaseGame/game/core/utility/scripts/helperFunctions.tscript b/Templates/BaseGame/game/core/utility/scripts/helperFunctions.tscript index fc6e0d33c..905100648 100644 --- a/Templates/BaseGame/game/core/utility/scripts/helperFunctions.tscript +++ b/Templates/BaseGame/game/core/utility/scripts/helperFunctions.tscript @@ -650,7 +650,7 @@ function populateAllFonts() continue; %fontarray.push_back(%obj.fontType,%obj.fontSize); } - %fontarray.uniquePair(); + %fontarray.uniqueKey(); %fontarrayCount = %fontarray.count(); From d7b68a97ee1c406ea2cccde1c8c3404809bfe48d Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Thu, 14 Mar 2024 08:37:05 +0000 Subject: [PATCH 48/53] no idea why this was changed in a previous commit how the fuck did this get changed! --- Engine/source/console/arrayObject.cpp | 526 ++++++++++++++------------ Engine/source/console/arrayObject.h | 94 ++--- 2 files changed, 323 insertions(+), 297 deletions(-) diff --git a/Engine/source/console/arrayObject.cpp b/Engine/source/console/arrayObject.cpp index cfd25d6cb..bc3235485 100644 --- a/Engine/source/console/arrayObject.cpp +++ b/Engine/source/console/arrayObject.cpp @@ -29,7 +29,7 @@ IMPLEMENT_CONOBJECT(ArrayObject); -ConsoleDocClass( ArrayObject, +ConsoleDocClass(ArrayObject, "@brief Data structure for storing indexed sequences of key/value pairs.\n\n" "This is a powerful array class providing PHP style arrays in TorqueScript.\n\n" @@ -60,72 +60,72 @@ bool ArrayObject::smCaseSensitive = false; const char* ArrayObject::smCompareFunction; -S32 QSORT_CALLBACK ArrayObject::_valueCompare( const void* a, const void* b ) +S32 QSORT_CALLBACK ArrayObject::_valueCompare(const void* a, const void* b) { - ArrayObject::Element *ea = (ArrayObject::Element *) (a); - ArrayObject::Element *eb = (ArrayObject::Element *) (b); + ArrayObject::Element* ea = (ArrayObject::Element*)(a); + ArrayObject::Element* eb = (ArrayObject::Element*)(b); S32 result = smCaseSensitive ? dStrnatcmp(ea->value, eb->value) : dStrnatcasecmp(ea->value, eb->value); - return ( smDecreasing ? -result : result ); + return (smDecreasing ? -result : result); } -S32 QSORT_CALLBACK ArrayObject::_valueNumCompare( const void* a, const void* b ) +S32 QSORT_CALLBACK ArrayObject::_valueNumCompare(const void* a, const void* b) { - ArrayObject::Element *ea = (ArrayObject::Element *) (a); - ArrayObject::Element *eb = (ArrayObject::Element *) (b); + ArrayObject::Element* ea = (ArrayObject::Element*)(a); + ArrayObject::Element* eb = (ArrayObject::Element*)(b); F32 aCol = dAtof(ea->value); F32 bCol = dAtof(eb->value); F32 result = aCol - bCol; S32 res = result < 0 ? -1 : (result > 0 ? 1 : 0); - return ( smDecreasing ? -res : res ); + return (smDecreasing ? -res : res); } -S32 QSORT_CALLBACK ArrayObject::_keyCompare( const void* a, const void* b ) +S32 QSORT_CALLBACK ArrayObject::_keyCompare(const void* a, const void* b) { - ArrayObject::Element *ea = (ArrayObject::Element *) (a); - ArrayObject::Element *eb = (ArrayObject::Element *) (b); + ArrayObject::Element* ea = (ArrayObject::Element*)(a); + ArrayObject::Element* eb = (ArrayObject::Element*)(b); S32 result = smCaseSensitive ? dStrnatcmp(ea->key, eb->key) : dStrnatcasecmp(ea->key, eb->key); - return ( smDecreasing ? -result : result ); + return (smDecreasing ? -result : result); } -S32 QSORT_CALLBACK ArrayObject::_keyNumCompare( const void* a, const void* b ) +S32 QSORT_CALLBACK ArrayObject::_keyNumCompare(const void* a, const void* b) { - ArrayObject::Element *ea = (ArrayObject::Element *) (a); - ArrayObject::Element *eb = (ArrayObject::Element *) (b); + ArrayObject::Element* ea = (ArrayObject::Element*)(a); + ArrayObject::Element* eb = (ArrayObject::Element*)(b); const char* aCol = ea->key; const char* bCol = eb->key; F32 result = dAtof(aCol) - dAtof(bCol); S32 res = result < 0 ? -1 : (result > 0 ? 1 : 0); - return ( smDecreasing ? -res : res ); + return (smDecreasing ? -res : res); } -S32 QSORT_CALLBACK ArrayObject::_keyFunctionCompare( const void* a, const void* b ) +S32 QSORT_CALLBACK ArrayObject::_keyFunctionCompare(const void* a, const void* b) { - ArrayObject::Element* ea = ( ArrayObject::Element* )( a ); - ArrayObject::Element* eb = ( ArrayObject::Element* )( b ); - + ArrayObject::Element* ea = (ArrayObject::Element*)(a); + ArrayObject::Element* eb = (ArrayObject::Element*)(b); + ConsoleValue cValue = Con::executef((const char*)smCompareFunction, ea->key, eb->key); S32 result = cValue.getInt(); - S32 res = result < 0 ? -1 : ( result > 0 ? 1 : 0 ); - return ( smDecreasing ? -res : res ); + S32 res = result < 0 ? -1 : (result > 0 ? 1 : 0); + return (smDecreasing ? -res : res); } -S32 QSORT_CALLBACK ArrayObject::_valueFunctionCompare( const void* a, const void* b ) +S32 QSORT_CALLBACK ArrayObject::_valueFunctionCompare(const void* a, const void* b) { - ArrayObject::Element* ea = ( ArrayObject::Element* )( a ); - ArrayObject::Element* eb = ( ArrayObject::Element* )( b ); - - ConsoleValue cValue = Con::executef( (const char*)smCompareFunction, ea->value, eb->value ); + ArrayObject::Element* ea = (ArrayObject::Element*)(a); + ArrayObject::Element* eb = (ArrayObject::Element*)(b); + + ConsoleValue cValue = Con::executef((const char*)smCompareFunction, ea->value, eb->value); S32 result = cValue.getInt(); - S32 res = result < 0 ? -1 : ( result > 0 ? 1 : 0 ); - return ( smDecreasing ? -res : res ); + S32 res = result < 0 ? -1 : (result > 0 ? 1 : 0); + return (smDecreasing ? -res : res); } //----------------------------------------------------------------------------- ArrayObject::ArrayObject() - : mCaseSensitive( false ), - mCurrentIndex( 0 ) + : mCaseSensitive(false), + mCurrentIndex(0) { } @@ -134,44 +134,44 @@ ArrayObject::ArrayObject() void ArrayObject::initPersistFields() { docsURL; - addField( "caseSensitive", TypeBool, Offset( mCaseSensitive, ArrayObject ), + addField("caseSensitive", TypeBool, Offset(mCaseSensitive, ArrayObject), "Makes the keys and values case-sensitive.\n" - "By default, comparison of key and value strings will be case-insensitive." ); + "By default, comparison of key and value strings will be case-insensitive."); - addProtectedField( "key", TypeCaseString, 0, &_addKeyFromField, &emptyStringProtectedGetFn, - "Helper field which allows you to add new key['keyname'] = value pairs." ); + addProtectedField("key", TypeCaseString, 0, &_addKeyFromField, &emptyStringProtectedGetFn, + "Helper field which allows you to add new key['keyname'] = value pairs."); Parent::initPersistFields(); } //----------------------------------------------------------------------------- -bool ArrayObject::_addKeyFromField( void *object, const char *index, const char *data ) +bool ArrayObject::_addKeyFromField(void* object, const char* index, const char* data) { - static_cast( object )->push_back( index, data ); + static_cast(object)->push_back(index, data); return false; } //----------------------------------------------------------------------------- -S32 ArrayObject::getIndexFromValue( const String &value ) const +S32 ArrayObject::getIndexFromValue(const String& value) const { S32 currentIndex = mMax(mCurrentIndex, 0); S32 foundIndex = -1; - for ( S32 i = currentIndex; i < mArray.size(); i++ ) + for (S32 i = currentIndex; i < mArray.size(); i++) { - if ( isEqual( mArray[i].value, value ) ) + if (isEqual(mArray[i].value, value)) { foundIndex = i; break; } } - if( foundIndex < 0 ) + if (foundIndex < 0) { - for ( S32 i = 0; i < currentIndex; i++ ) + for (S32 i = 0; i < currentIndex; i++) { - if ( isEqual( mArray[i].value, value ) ) + if (isEqual(mArray[i].value, value)) { foundIndex = i; break; @@ -184,24 +184,24 @@ S32 ArrayObject::getIndexFromValue( const String &value ) const //----------------------------------------------------------------------------- -S32 ArrayObject::getIndexFromKey( const String &key ) const +S32 ArrayObject::getIndexFromKey(const String& key) const { S32 currentIndex = mMax(mCurrentIndex, 0); S32 foundIndex = -1; - for ( S32 i = currentIndex; i < mArray.size(); i++ ) + for (S32 i = currentIndex; i < mArray.size(); i++) { - if ( isEqual( mArray[i].key, key ) ) + if (isEqual(mArray[i].key, key)) { foundIndex = i; break; } } - if( foundIndex < 0 ) + if (foundIndex < 0) { - for ( S32 i = 0; i < currentIndex; i++ ) + for (S32 i = 0; i < currentIndex; i++) { - if ( isEqual( mArray[i].key, key ) ) + if (isEqual(mArray[i].key, key)) { foundIndex = i; break; @@ -214,24 +214,24 @@ S32 ArrayObject::getIndexFromKey( const String &key ) const //----------------------------------------------------------------------------- -S32 ArrayObject::getIndexFromKeyValue( const String &key, const String &value ) const +S32 ArrayObject::getIndexFromKeyValue(const String& key, const String& value) const { S32 currentIndex = mMax(mCurrentIndex, 0); S32 foundIndex = -1; - for ( S32 i = currentIndex; i < mArray.size(); i++ ) + for (S32 i = currentIndex; i < mArray.size(); i++) { - if ( isEqual( mArray[i].key, key ) && isEqual( mArray[i].value, value ) ) + if (isEqual(mArray[i].key, key) && isEqual(mArray[i].value, value)) { foundIndex = i; break; } } - if ( foundIndex < 0 ) + if (foundIndex < 0) { - for ( S32 i = 0; i < currentIndex; i++ ) + for (S32 i = 0; i < currentIndex; i++) { - if ( isEqual( mArray[i].key, key ) && isEqual( mArray[i].value, value ) ) + if (isEqual(mArray[i].key, key) && isEqual(mArray[i].value, value)) { foundIndex = i; break; @@ -244,9 +244,9 @@ S32 ArrayObject::getIndexFromKeyValue( const String &key, const String &value ) //----------------------------------------------------------------------------- -const String& ArrayObject::getKeyFromIndex( S32 index ) const +const String& ArrayObject::getKeyFromIndex(S32 index) const { - if ( index >= mArray.size() || index < 0 ) + if (index >= mArray.size() || index < 0) return String::EmptyString; return mArray[index].key; @@ -254,9 +254,9 @@ const String& ArrayObject::getKeyFromIndex( S32 index ) const //----------------------------------------------------------------------------- -const String& ArrayObject::getValueFromIndex( S32 index ) const +const String& ArrayObject::getValueFromIndex(S32 index) const { - if( index >= mArray.size() || index < 0 ) + if (index >= mArray.size() || index < 0) return String::EmptyString; return mArray[index].value; @@ -264,12 +264,12 @@ const String& ArrayObject::getValueFromIndex( S32 index ) const //----------------------------------------------------------------------------- -S32 ArrayObject::countValue( const String &value ) const +S32 ArrayObject::countValue(const String& value) const { S32 count = 0; - for ( S32 i = 0; i < mArray.size(); i++ ) + for (S32 i = 0; i < mArray.size(); i++) { - if ( isEqual( mArray[i].value, value ) ) + if (isEqual(mArray[i].value, value)) count++; } @@ -278,12 +278,12 @@ S32 ArrayObject::countValue( const String &value ) const //----------------------------------------------------------------------------- -S32 ArrayObject::countKey( const String &key) const +S32 ArrayObject::countKey(const String& key) const { S32 count = 0; - for ( S32 i = 0; i < mArray.size(); i++ ) + for (S32 i = 0; i < mArray.size(); i++) { - if ( isEqual( mArray[i].key, key ) ) + if (isEqual(mArray[i].key, key)) count++; } @@ -292,36 +292,36 @@ S32 ArrayObject::countKey( const String &key) const //----------------------------------------------------------------------------- -void ArrayObject::push_back( const String &key, const String &value ) +void ArrayObject::push_back(const String& key, const String& value) { - mArray.push_back( Element( key, value ) ); + mArray.push_back(Element(key, value)); } //----------------------------------------------------------------------------- -void ArrayObject::push_front( const String &key, const String &value ) +void ArrayObject::push_front(const String& key, const String& value) { - mArray.push_front( Element( key, value ) ); + mArray.push_front(Element(key, value)); } //----------------------------------------------------------------------------- -void ArrayObject::insert( const String &key, const String &value, S32 index ) +void ArrayObject::insert(const String& key, const String& value, S32 index) { - index = mClamp( index, 0, mArray.size() ); - mArray.insert( index, Element( key, value ) ); + index = mClamp(index, 0, mArray.size()); + mArray.insert(index, Element(key, value)); } //----------------------------------------------------------------------------- void ArrayObject::pop_back() { - if(mArray.size() <= 0) + if (mArray.size() <= 0) return; mArray.pop_back(); - if( mCurrentIndex >= mArray.size() ) + if (mCurrentIndex >= mArray.size()) mCurrentIndex = mArray.size() - 1; } @@ -329,23 +329,23 @@ void ArrayObject::pop_back() void ArrayObject::pop_front() { - if( mArray.size() <= 0 ) + if (mArray.size() <= 0) return; mArray.pop_front(); - - if( mCurrentIndex >= mArray.size() ) + + if (mCurrentIndex >= mArray.size()) mCurrentIndex = mArray.size() - 1; } //----------------------------------------------------------------------------- -void ArrayObject::erase( S32 index ) +void ArrayObject::erase(S32 index) { - if(index < 0 || index >= mArray.size()) + if (index < 0 || index >= mArray.size()) return; - mArray.erase( index ); + mArray.erase(index); } //----------------------------------------------------------------------------- @@ -360,7 +360,7 @@ void ArrayObject::empty() void ArrayObject::moveIndex(S32 prev, S32 index) { - if(index >= mArray.size()) + if (index >= mArray.size()) push_back(mArray[prev].key, mArray[prev].value); else mArray[index] = mArray[prev]; @@ -372,11 +372,11 @@ void ArrayObject::moveIndex(S32 prev, S32 index) void ArrayObject::uniqueValue() { - for(S32 i=0; icount(); i++) + for (S32 i = 0; i < obj->count(); i++) { const String& tempval = obj->getValueFromIndex(i); const String& tempkey = obj->getKeyFromIndex(i); @@ -418,16 +434,16 @@ void ArrayObject::duplicate(ArrayObject* obj) //----------------------------------------------------------------------------- -void ArrayObject::crop( ArrayObject *obj ) +void ArrayObject::crop(ArrayObject* obj) { - for( S32 i = 0; i < obj->count(); i++ ) + for (S32 i = 0; i < obj->count(); i++) { - const String &tempkey = obj->getKeyFromIndex( i ); - for( S32 j = 0; j < mArray.size(); j++ ) + const String& tempkey = obj->getKeyFromIndex(i); + for (S32 j = 0; j < mArray.size(); j++) { - if( isEqual( mArray[j].key, tempkey ) ) + if (isEqual(mArray[j].key, tempkey)) { - mArray.erase( j ); + mArray.erase(j); j--; } } @@ -438,7 +454,7 @@ void ArrayObject::crop( ArrayObject *obj ) void ArrayObject::append(ArrayObject* obj) { - for(S32 i=0; icount(); i++) + for (S32 i = 0; i < obj->count(); i++) { const String& tempval = obj->getValueFromIndex(i); const String& tempkey = obj->getKeyFromIndex(i); @@ -448,7 +464,7 @@ void ArrayObject::append(ArrayObject* obj) //----------------------------------------------------------------------------- -void ArrayObject::setKey( const String &key, S32 index ) +void ArrayObject::setKey(const String& key, S32 index) { if (index >= mArray.size() || index < 0) return; @@ -458,54 +474,54 @@ void ArrayObject::setKey( const String &key, S32 index ) //----------------------------------------------------------------------------- -void ArrayObject::setValue( const String &value, S32 index ) +void ArrayObject::setValue(const String& value, S32 index) { if (index >= mArray.size() || index < 0) return; - + mArray[index].value = value; } //----------------------------------------------------------------------------- -void ArrayObject::sort( bool valsort, bool asc, bool numeric ) +void ArrayObject::sort(bool valsort, bool asc, bool numeric) { - if ( mArray.size() <= 1 ) + if (mArray.size() <= 1) return; smDecreasing = asc ? false : true; smCaseSensitive = isCaseSensitive(); - if ( numeric ) + if (numeric) { - if ( valsort ) - dQsort( (void *)&(mArray[0]), mArray.size(), sizeof(Element), _valueNumCompare) ; + if (valsort) + dQsort((void*)&(mArray[0]), mArray.size(), sizeof(Element), _valueNumCompare); else - dQsort( (void *)&(mArray[0]), mArray.size(), sizeof(Element), _keyNumCompare ); + dQsort((void*)&(mArray[0]), mArray.size(), sizeof(Element), _keyNumCompare); } else { - if( valsort ) - dQsort( (void *)&(mArray[0]), mArray.size(), sizeof(Element), _valueCompare ); + if (valsort) + dQsort((void*)&(mArray[0]), mArray.size(), sizeof(Element), _valueCompare); else - dQsort( (void *)&(mArray[0]), mArray.size(), sizeof(Element), _keyCompare ); + dQsort((void*)&(mArray[0]), mArray.size(), sizeof(Element), _keyCompare); } } //----------------------------------------------------------------------------- -void ArrayObject::sort( bool valsort, bool asc, const char* callbackFunctionName ) +void ArrayObject::sort(bool valsort, bool asc, const char* callbackFunctionName) { - if( mArray.size() <= 1 ) + if (mArray.size() <= 1) return; smDecreasing = asc ? false : true; smCompareFunction = callbackFunctionName; - if( valsort ) - dQsort( ( void* ) &( mArray[ 0 ] ), mArray.size(), sizeof( Element ), _valueFunctionCompare ) ; + if (valsort) + dQsort((void*)&(mArray[0]), mArray.size(), sizeof(Element), _valueFunctionCompare); else - dQsort( ( void* ) &( mArray[ 0 ] ), mArray.size(), sizeof( Element ), _keyFunctionCompare ); + dQsort((void*)&(mArray[0]), mArray.size(), sizeof(Element), _keyFunctionCompare); smCompareFunction = NULL; } @@ -522,7 +538,7 @@ S32 ArrayObject::moveFirst() S32 ArrayObject::moveLast() { - if ( mArray.empty() ) + if (mArray.empty()) mCurrentIndex = 0; else mCurrentIndex = mArray.size() - 1; @@ -533,11 +549,11 @@ S32 ArrayObject::moveLast() S32 ArrayObject::moveNext() { - if ( mCurrentIndex >= mArray.size() - 1 ) + if (mCurrentIndex >= mArray.size() - 1) return -1; - + mCurrentIndex++; - + return mCurrentIndex; } @@ -545,21 +561,21 @@ S32 ArrayObject::moveNext() S32 ArrayObject::movePrev() { - if ( mCurrentIndex <= 0 ) + if (mCurrentIndex <= 0) return -1; mCurrentIndex--; - + return mCurrentIndex; } //----------------------------------------------------------------------------- -void ArrayObject::setCurrent( S32 idx ) +void ArrayObject::setCurrent(S32 idx) { - if ( idx < 0 || idx >= mArray.size() ) + if (idx < 0 || idx >= mArray.size()) { - Con::errorf( "ArrayObject::setCurrent( %d ) is out of the array bounds!", idx ); + Con::errorf("ArrayObject::setCurrent( %d ) is out of the array bounds!", idx); return; } @@ -570,13 +586,13 @@ void ArrayObject::setCurrent( S32 idx ) void ArrayObject::echo() { - Con::printf( "ArrayObject Listing:" ); - Con::printf( "Index Key Value" ); - for ( U32 i = 0; i < mArray.size(); i++ ) + Con::printf("ArrayObject Listing:"); + Con::printf("Index Key Value"); + for (U32 i = 0; i < mArray.size(); i++) { const String& key = mArray[i].key; const String& val = mArray[i].value; - Con::printf( "%d [%s] => %s", i, key.c_str(), val.c_str() ); + Con::printf("%d [%s] => %s", i, key.c_str(), val.c_str()); } } @@ -584,20 +600,20 @@ void ArrayObject::echo() // Console Methods. //============================================================================= -DefineEngineMethod( ArrayObject, getIndexFromValue, S32, ( const char* value ),, +DefineEngineMethod(ArrayObject, getIndexFromValue, S32, (const char* value), , "Search the array from the current position for the element " "@param value Array value to search for\n" - "@return Index of the first element found, or -1 if none\n" ) + "@return Index of the first element found, or -1 if none\n") { - return object->getIndexFromValue( value ); + return object->getIndexFromValue(value); } -DefineEngineMethod( ArrayObject, getIndexFromKey, S32, ( const char* key ),, +DefineEngineMethod(ArrayObject, getIndexFromKey, S32, (const char* key), , "Search the array from the current position for the key " "@param value Array key to search for\n" - "@return Index of the first element found, or -1 if none\n" ) + "@return Index of the first element found, or -1 if none\n") { - return object->getIndexFromKey( key ); + return object->getIndexFromKey(key); } DefineEngineMethod(ArrayObject, getValueFromKey, const char*, (const char* key), , @@ -616,246 +632,252 @@ DefineEngineMethod(ArrayObject, getKeyFromValue, const char*, (const char* key), return object->getKeyFromIndex(object->getIndexFromValue(key)).c_str(); } -DefineEngineMethod( ArrayObject, getValue, const char*, ( S32 index ),, +DefineEngineMethod(ArrayObject, getValue, const char*, (S32 index), , "Get the value of the array element at the submitted index.\n" "@param index 0-based index of the array element to get\n" "@return The value of the array element at the specified index, " - "or \"\" if the index is out of range\n" ) + "or \"\" if the index is out of range\n") { - return object->getValueFromIndex( index ).c_str(); + return object->getValueFromIndex(index).c_str(); } -DefineEngineMethod( ArrayObject, getKey, const char*, ( S32 index ),, +DefineEngineMethod(ArrayObject, getKey, const char*, (S32 index), , "Get the key of the array element at the submitted index.\n" "@param index 0-based index of the array element to get\n" "@return The key associated with the array element at the " - "specified index, or \"\" if the index is out of range\n" ) + "specified index, or \"\" if the index is out of range\n") { - return object->getKeyFromIndex( index ).c_str(); + return object->getKeyFromIndex(index).c_str(); } -DefineEngineMethod( ArrayObject, setKey, void, ( const char* key, S32 index ),, +DefineEngineMethod(ArrayObject, setKey, void, (const char* key, S32 index), , "Set the key at the given index.\n" "@param key New key value\n" - "@param index 0-based index of the array element to update\n" ) + "@param index 0-based index of the array element to update\n") { - object->setKey( key, index ); + object->setKey(key, index); } -DefineEngineMethod( ArrayObject, setValue, void, ( const char* value, S32 index ),, +DefineEngineMethod(ArrayObject, setValue, void, (const char* value, S32 index), , "Set the value at the given index.\n" "@param value New array element value\n" - "@param index 0-based index of the array element to update\n" ) + "@param index 0-based index of the array element to update\n") { - object->setValue( value, index ); + object->setValue(value, index); } -DefineEngineMethod( ArrayObject, count, S32, (),, - "Get the number of elements in the array." ) +DefineEngineMethod(ArrayObject, count, S32, (), , + "Get the number of elements in the array.") { return (S32)object->count(); } -DefineEngineMethod( ArrayObject, countValue, S32, ( const char* value ),, +DefineEngineMethod(ArrayObject, countValue, S32, (const char* value), , "Get the number of times a particular value is found in the array.\n" - "@param value Array element value to count\n" ) + "@param value Array element value to count\n") { - return (S32)object->countValue( value ); + return (S32)object->countValue(value); } -DefineEngineMethod( ArrayObject, countKey, S32, ( const char* key ),, +DefineEngineMethod(ArrayObject, countKey, S32, (const char* key), , "Get the number of times a particular key is found in the array.\n" - "@param key Key value to count\n" ) + "@param key Key value to count\n") { - return (S32)object->countKey( key ); + return (S32)object->countKey(key); } -DefineEngineMethod( ArrayObject, add, void, ( const char* key, const char* value ), ( "" ), +DefineEngineMethod(ArrayObject, add, void, (const char* key, const char* value), (""), "Adds a new element to the end of an array (same as push_back()).\n" "@param key Key for the new element\n" - "@param value Value for the new element\n" ) + "@param value Value for the new element\n") { - object->push_back( key, value ); + object->push_back(key, value); } -DefineEngineMethod( ArrayObject, push_back, void, ( const char* key, const char* value ), ( "" ), +DefineEngineMethod(ArrayObject, push_back, void, (const char* key, const char* value), (""), "Adds a new element to the end of an array.\n" "@param key Key for the new element\n" - "@param value Value for the new element\n" ) + "@param value Value for the new element\n") { - object->push_back( key, value ); + object->push_back(key, value); } -DefineEngineMethod( ArrayObject, push_front, void, ( const char* key, const char* value ), ( "" ), - "Adds a new element to the front of an array" ) +DefineEngineMethod(ArrayObject, push_front, void, (const char* key, const char* value), (""), + "Adds a new element to the front of an array") { - object->push_front( key, value ); + object->push_front(key, value); } -DefineEngineMethod( ArrayObject, insert, void, ( const char* key, const char* value, S32 index ),, +DefineEngineMethod(ArrayObject, insert, void, (const char* key, const char* value, S32 index), , "Adds a new element to a specified position in the array.\n" "- @a index = 0 will insert an element at the start of the array (same as push_front())\n" "- @a index = %array.count() will insert an element at the end of the array (same as push_back())\n\n" "@param key Key for the new element\n" "@param value Value for the new element\n" - "@param index 0-based index at which to insert the new element" ) + "@param index 0-based index at which to insert the new element") { - object->insert( key, value, index ); + object->insert(key, value, index); } -DefineEngineMethod( ArrayObject, pop_back, void, (),, - "Removes the last element from the array" ) +DefineEngineMethod(ArrayObject, pop_back, void, (), , + "Removes the last element from the array") { object->pop_back(); } -DefineEngineMethod( ArrayObject, pop_front, void, (),, - "Removes the first element from the array" ) +DefineEngineMethod(ArrayObject, pop_front, void, (), , + "Removes the first element from the array") { object->pop_front(); } -DefineEngineMethod( ArrayObject, erase, void, ( S32 index ),, +DefineEngineMethod(ArrayObject, erase, void, (S32 index), , "Removes an element at a specific position from the array.\n" - "@param index 0-based index of the element to remove\n" ) + "@param index 0-based index of the element to remove\n") { - object->erase( index ); + object->erase(index); } -DefineEngineMethod( ArrayObject, empty, void, (),, - "Emptys all elements from an array" ) +DefineEngineMethod(ArrayObject, empty, void, (), , + "Emptys all elements from an array") { object->empty(); } -DefineEngineMethod( ArrayObject, uniqueValue, void, (),, - "Removes any elements that have duplicated values (leaving the first instance)" ) +DefineEngineMethod(ArrayObject, uniqueValue, void, (), , + "Removes any elements that have duplicated values (leaving the first instance)") { object->uniqueValue(); } -DefineEngineMethod( ArrayObject, uniqueKey, void, (),, - "Removes any elements that have duplicated keys (leaving the first instance)" ) +DefineEngineMethod(ArrayObject, uniqueKey, void, (), , + "Removes any elements that have duplicated keys (leaving the first instance)") { object->uniqueKey(); } -DefineEngineMethod( ArrayObject, duplicate, bool, ( ArrayObject* target ),, +DefineEngineMethod(ArrayObject, uniquePair, void, (), , + "Removes any elements that have duplicated key and value pairs (leaving the first instance)") +{ + object->uniquePair(); +} + +DefineEngineMethod(ArrayObject, duplicate, bool, (ArrayObject* target), , "Alters array into an exact duplicate of the target array.\n" - "@param target ArrayObject to duplicate\n" ) + "@param target ArrayObject to duplicate\n") { - if ( target ) + if (target) { - object->duplicate( target ); + object->duplicate(target); return true; } return false; } -DefineEngineMethod( ArrayObject, crop, bool, ( ArrayObject* target ),, +DefineEngineMethod(ArrayObject, crop, bool, (ArrayObject* target), , "Removes elements with matching keys from array.\n" - "@param target ArrayObject containing keys to remove from this array\n" ) + "@param target ArrayObject containing keys to remove from this array\n") { - if ( target ) + if (target) { - object->crop( target ); + object->crop(target); return true; } return false; } -DefineEngineMethod( ArrayObject, append, bool, ( ArrayObject* target ),, +DefineEngineMethod(ArrayObject, append, bool, (ArrayObject* target), , "Appends the target array to the array object.\n" - "@param target ArrayObject to append to the end of this array\n" ) + "@param target ArrayObject to append to the end of this array\n") { - if ( target ) + if (target) { - object->append( target ); + object->append(target); return true; } return false; } -DefineEngineMethod( ArrayObject, sort, void, ( bool ascending ), ( false ), +DefineEngineMethod(ArrayObject, sort, void, (bool ascending), (false), "Alpha sorts the array by value\n\n" - "@param ascending [optional] True for ascending sort, false for descending sort\n" ) + "@param ascending [optional] True for ascending sort, false for descending sort\n") { - object->sort( true, ascending, false ); + object->sort(true, ascending, false); } -DefineEngineMethod( ArrayObject, sorta, void, (),, - "Alpha sorts the array by value in ascending order" ) +DefineEngineMethod(ArrayObject, sorta, void, (), , + "Alpha sorts the array by value in ascending order") { - object->sort( true, true, false ); + object->sort(true, true, false); } -DefineEngineMethod( ArrayObject, sortd, void, (),, - "Alpha sorts the array by value in descending order" ) +DefineEngineMethod(ArrayObject, sortd, void, (), , + "Alpha sorts the array by value in descending order") { - object->sort( true, false, false ); + object->sort(true, false, false); } -DefineEngineMethod( ArrayObject, sortk, void, ( bool ascending ), ( false ), +DefineEngineMethod(ArrayObject, sortk, void, (bool ascending), (false), "Alpha sorts the array by key\n\n" - "@param ascending [optional] True for ascending sort, false for descending sort\n" ) + "@param ascending [optional] True for ascending sort, false for descending sort\n") { - object->sort( false, ascending, false ); + object->sort(false, ascending, false); } -DefineEngineMethod( ArrayObject, sortka, void, (),, - "Alpha sorts the array by key in ascending order" ) +DefineEngineMethod(ArrayObject, sortka, void, (), , + "Alpha sorts the array by key in ascending order") { - object->sort( false, true, false ); + object->sort(false, true, false); } -DefineEngineMethod( ArrayObject, sortkd, void, (),, - "Alpha sorts the array by key in descending order" ) +DefineEngineMethod(ArrayObject, sortkd, void, (), , + "Alpha sorts the array by key in descending order") { - object->sort( false, false, false ); + object->sort(false, false, false); } -DefineEngineMethod( ArrayObject, sortn, void, ( bool ascending ), ( false ), +DefineEngineMethod(ArrayObject, sortn, void, (bool ascending), (false), "Numerically sorts the array by value\n\n" - "@param ascending [optional] True for ascending sort, false for descending sort\n" ) + "@param ascending [optional] True for ascending sort, false for descending sort\n") { - object->sort( true, ascending, true ); + object->sort(true, ascending, true); } -DefineEngineMethod( ArrayObject, sortna, void, (),, - "Numerically sorts the array by value in ascending order" ) +DefineEngineMethod(ArrayObject, sortna, void, (), , + "Numerically sorts the array by value in ascending order") { - object->sort( true, true, true ); + object->sort(true, true, true); } -DefineEngineMethod( ArrayObject, sortnd, void, (),, - "Numerically sorts the array by value in descending order" ) +DefineEngineMethod(ArrayObject, sortnd, void, (), , + "Numerically sorts the array by value in descending order") { - object->sort( true, false, true ); + object->sort(true, false, true); } -DefineEngineMethod( ArrayObject, sortnk, void, ( bool ascending ), ( false ), +DefineEngineMethod(ArrayObject, sortnk, void, (bool ascending), (false), "Numerically sorts the array by key\n\n" - "@param ascending [optional] True for ascending sort, false for descending sort\n" ) + "@param ascending [optional] True for ascending sort, false for descending sort\n") { - object->sort( false, ascending, true ); + object->sort(false, ascending, true); } -DefineEngineMethod( ArrayObject, sortnka, void, (),, - "Numerical sorts the array by key in ascending order" ) +DefineEngineMethod(ArrayObject, sortnka, void, (), , + "Numerical sorts the array by key in ascending order") { - object->sort( false, true, true ); + object->sort(false, true, true); } -DefineEngineMethod( ArrayObject, sortnkd, void, (),, - "Numerical sorts the array by key in descending order" ) +DefineEngineMethod(ArrayObject, sortnkd, void, (), , + "Numerical sorts the array by key in descending order") { - object->sort( false, false, true ); + object->sort(false, false, true); } -DefineEngineMethod( ArrayObject, sortf, void, ( const char* functionName ),, +DefineEngineMethod(ArrayObject, sortf, void, (const char* functionName), , "Sorts the array by value in ascending order using the given callback function.\n" "@param functionName Name of a function that takes two arguments A and B and returns -1 if A is less, 1 if B is less, and 0 if both are equal.\n\n" "@tsexample\n" @@ -864,78 +886,78 @@ DefineEngineMethod( ArrayObject, sortf, void, ( const char* functionName ),, " return strcmp( %a.name, %b.name );\n" "}\n\n" "%array.sortf( \"mySortCallback\" );\n" - "@endtsexample\n" ) + "@endtsexample\n") { - object->sort( true, true, functionName ); + object->sort(true, true, functionName); } -DefineEngineMethod( ArrayObject, sortfk, void, ( const char* functionName ),, +DefineEngineMethod(ArrayObject, sortfk, void, (const char* functionName), , "Sorts the array by key in ascending order using the given callback function.\n" "@param functionName Name of a function that takes two arguments A and B and returns -1 if A is less, 1 if B is less, and 0 if both are equal." - "@see sortf\n" ) + "@see sortf\n") { - object->sort( false, true, functionName ); + object->sort(false, true, functionName); } -DefineEngineMethod( ArrayObject, sortfd, void, ( const char* functionName ),, +DefineEngineMethod(ArrayObject, sortfd, void, (const char* functionName), , "Sorts the array by value in descending order using the given callback function.\n" "@param functionName Name of a function that takes two arguments A and B and returns -1 if A is less, 1 if B is less, and 0 if both are equal." - "@see sortf\n" ) + "@see sortf\n") { - object->sort( true, false, functionName ); + object->sort(true, false, functionName); } -DefineEngineMethod( ArrayObject, sortfkd, void, ( const char* functionName ),, +DefineEngineMethod(ArrayObject, sortfkd, void, (const char* functionName), , "Sorts the array by key in descending order using the given callback function.\n" "@param functionName Name of a function that takes two arguments A and B and returns -1 if A is less, 1 if B is less, and 0 if both are equal." - "@see sortf\n" ) + "@see sortf\n") { - object->sort( false, false, functionName ); + object->sort(false, false, functionName); } -DefineEngineMethod( ArrayObject, moveFirst, S32, (),, +DefineEngineMethod(ArrayObject, moveFirst, S32, (), , "Moves array pointer to start of array\n\n" - "@return Returns the new array pointer" ) + "@return Returns the new array pointer") { return object->moveFirst(); } -DefineEngineMethod( ArrayObject, moveLast, S32, (),, +DefineEngineMethod(ArrayObject, moveLast, S32, (), , "Moves array pointer to end of array\n\n" - "@return Returns the new array pointer" ) + "@return Returns the new array pointer") { return object->moveLast(); } -DefineEngineMethod( ArrayObject, moveNext, S32, (),, +DefineEngineMethod(ArrayObject, moveNext, S32, (), , "Moves array pointer to next position\n\n" - "@return Returns the new array pointer, or -1 if already at the end" ) + "@return Returns the new array pointer, or -1 if already at the end") { return object->moveNext(); } -DefineEngineMethod( ArrayObject, movePrev, S32, (),, +DefineEngineMethod(ArrayObject, movePrev, S32, (), , "Moves array pointer to prev position\n\n" - "@return Returns the new array pointer, or -1 if already at the start" ) + "@return Returns the new array pointer, or -1 if already at the start") { return object->movePrev(); } -DefineEngineMethod( ArrayObject, getCurrent, S32, (),, - "Gets the current pointer index" ) +DefineEngineMethod(ArrayObject, getCurrent, S32, (), , + "Gets the current pointer index") { return object->getCurrent(); } -DefineEngineMethod( ArrayObject, setCurrent, void, ( S32 index ),, +DefineEngineMethod(ArrayObject, setCurrent, void, (S32 index), , "Sets the current pointer index.\n" - "@param index New 0-based pointer index\n" ) + "@param index New 0-based pointer index\n") { - object->setCurrent( index ); + object->setCurrent(index); } -DefineEngineMethod( ArrayObject, echo, void, (),, - "Echos the array contents to the console" ) +DefineEngineMethod(ArrayObject, echo, void, (), , + "Echos the array contents to the console") { object->echo(); } diff --git a/Engine/source/console/arrayObject.h b/Engine/source/console/arrayObject.h index 81531b6c2..0abdd6648 100644 --- a/Engine/source/console/arrayObject.h +++ b/Engine/source/console/arrayObject.h @@ -45,15 +45,15 @@ protected: String key; String value; Element() { } - Element( const String& _key, const String& _value ) : key(_key), value(_value) { } + Element(const String& _key, const String& _value) : key(_key), value(_value) { } }; bool mCaseSensitive; S32 mCurrentIndex; - + /// The array of key/value pairs. Vector< Element > mArray; - + /// @name Sorting /// @{ @@ -61,60 +61,60 @@ protected: static bool smCaseSensitive; static const char* smCompareFunction; - static S32 QSORT_CALLBACK _valueCompare( const void *a, const void *b ); - static S32 QSORT_CALLBACK _valueNumCompare( const void *a, const void *b ); - static S32 QSORT_CALLBACK _keyCompare( const void *a, const void *b ); - static S32 QSORT_CALLBACK _keyNumCompare( const void *a, const void *b ); - static S32 QSORT_CALLBACK _keyFunctionCompare( const void* a, const void* b ); - static S32 QSORT_CALLBACK _valueFunctionCompare( const void* a, const void* b ); - + static S32 QSORT_CALLBACK _valueCompare(const void* a, const void* b); + static S32 QSORT_CALLBACK _valueNumCompare(const void* a, const void* b); + static S32 QSORT_CALLBACK _keyCompare(const void* a, const void* b); + static S32 QSORT_CALLBACK _keyNumCompare(const void* a, const void* b); + static S32 QSORT_CALLBACK _keyFunctionCompare(const void* a, const void* b); + static S32 QSORT_CALLBACK _valueFunctionCompare(const void* a, const void* b); + /// @} - static bool _addKeyFromField( void *object, const char *index, const char *data ); + static bool _addKeyFromField(void* object, const char* index, const char* data); public: - + ArrayObject(); - /// @name Data Query + /// @name Data Query /// @{ - + /// Returns true if string handling by the array is case-sensitive. bool isCaseSensitive() const { return mCaseSensitive; } - bool isEqual( const String &valA, const String &valB ) const + bool isEqual(const String& valA, const String& valB) const { - return valA.equal( valB, isCaseSensitive() ? String::Case : String::NoCase ); + return valA.equal(valB, isCaseSensitive() ? String::Case : String::NoCase); } - /// Searches the array for the first matching value from the + /// Searches the array for the first matching value from the /// current array position. It will return -1 if no matching /// index is found. - S32 getIndexFromValue( const String &value ) const; + S32 getIndexFromValue(const String& value) const; /// Searches the array for the first matching key from the current /// array position. It will return -1 if no matching index found. - S32 getIndexFromKey( const String &key ) const; - + S32 getIndexFromKey(const String& key) const; + /// Returns the key for a given index. /// Will return a null value for an invalid index - const String& getKeyFromIndex( S32 index ) const; + const String& getKeyFromIndex(S32 index) const; /// Returns the value for a given index. /// Will return a null value for an invalid index - const String& getValueFromIndex( S32 index ) const; - + const String& getValueFromIndex(S32 index) const; + /// - S32 getIndexFromKeyValue( const String &key, const String &value ) const; + S32 getIndexFromKeyValue(const String& key, const String& value) const; /// Counts the number of elements in the array S32 count() const { return mArray.size(); } /// Counts the number of instances of a particular value in the array - S32 countValue( const String &value ) const; + S32 countValue(const String& value) const; /// Counts the number of instances of a particular key in the array - S32 countKey( const String &key ) const; + S32 countKey(const String& key) const; /// @} @@ -122,13 +122,13 @@ public: /// @{ /// Adds a new array item to the end of the array - void push_back( const String &key, const String &value ); + void push_back(const String& key, const String& value); /// Adds a new array item to the front of the array - void push_front( const String &key, const String &value ); + void push_front(const String& key, const String& value); /// Adds a new array item to a particular index of the array - void insert( const String &key, const String &value, S32 index ); + void insert(const String& key, const String& value, S32 index); /// Removes an array item from the end of the array void pop_back(); @@ -137,13 +137,13 @@ public: void pop_front(); /// Removes an array item from a particular index of the array - void erase( S32 index ); + void erase(S32 index); /// Clears an array void empty(); /// Moves a key and value from one index location to another. - void moveIndex( S32 prev, S32 index ); + void moveIndex(S32 prev, S32 index); /// @} @@ -158,32 +158,36 @@ public: /// (keeps the first instance only) void uniqueKey(); + /// Removes any duplicate keys from the array + /// (keeps the first instance only) + void uniquePair(); + /// Makes this array an exact duplicate of another array - void duplicate( ArrayObject *obj ); + void duplicate(ArrayObject* obj); /// Crops the keys that exists in the target array from our current array - void crop( ArrayObject *obj ); + void crop(ArrayObject* obj); /// Appends the target array to our current array - void append( ArrayObject *obj ); + void append(ArrayObject* obj); /// Sets the key at the given index - void setKey( const String &key, S32 index ); + void setKey(const String& key, S32 index); /// Sets the key at the given index - void setValue( const String &value, S32 index ); + void setValue(const String& value, S32 index); /// This sorts the array. /// @param valtest Determines whether sorting by value or key. /// @param asc Determines if sorting ascending or descending. /// @param numeric Determines if sorting alpha or numeric search. - void sort( bool valtest, bool asc, bool numeric ); - + void sort(bool valtest, bool asc, bool numeric); + /// This sorts the array using a script callback. /// @param valtest Determines whether sorting by value or key. /// @param asc Determines if sorting ascending or descending. /// @param callbackFunctionName Name of the script function. - void sort( bool valtest, bool asc, const char* callbackFunctionName ); + void sort(bool valtest, bool asc, const char* callbackFunctionName); /// @} @@ -208,7 +212,7 @@ public: S32 getCurrent() const { return mCurrentIndex; } /// - void setCurrent( S32 idx ); + void setCurrent(S32 idx); /// @} @@ -222,11 +226,11 @@ public: /// @} // SimObject - DECLARE_CONOBJECT( ArrayObject ); - DECLARE_CATEGORY( "Core" ); - DECLARE_DESCRIPTION( "An object storing an indexed sequence of key/value pairs." ); - + DECLARE_CONOBJECT(ArrayObject); + DECLARE_CATEGORY("Core"); + DECLARE_DESCRIPTION("An object storing an indexed sequence of key/value pairs."); + static void initPersistFields(); }; -#endif // _ARRAYOBJECT_H_ \ No newline at end of file +#endif // _ARRAYOBJECT_H_ From e46a7a7d47fbd255161bc45802563de3bf2cb2a1 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Thu, 14 Mar 2024 08:40:10 +0000 Subject: [PATCH 49/53] re-download array object from development re-download arrayObject from development so it doesn't show up as if there have been changes --- Engine/source/console/arrayObject.cpp | 504 +++++++++++++------------- Engine/source/console/arrayObject.h | 88 ++--- 2 files changed, 296 insertions(+), 296 deletions(-) diff --git a/Engine/source/console/arrayObject.cpp b/Engine/source/console/arrayObject.cpp index bc3235485..d5eaffe98 100644 --- a/Engine/source/console/arrayObject.cpp +++ b/Engine/source/console/arrayObject.cpp @@ -29,7 +29,7 @@ IMPLEMENT_CONOBJECT(ArrayObject); -ConsoleDocClass(ArrayObject, +ConsoleDocClass( ArrayObject, "@brief Data structure for storing indexed sequences of key/value pairs.\n\n" "This is a powerful array class providing PHP style arrays in TorqueScript.\n\n" @@ -60,72 +60,72 @@ bool ArrayObject::smCaseSensitive = false; const char* ArrayObject::smCompareFunction; -S32 QSORT_CALLBACK ArrayObject::_valueCompare(const void* a, const void* b) +S32 QSORT_CALLBACK ArrayObject::_valueCompare( const void* a, const void* b ) { - ArrayObject::Element* ea = (ArrayObject::Element*)(a); - ArrayObject::Element* eb = (ArrayObject::Element*)(b); + ArrayObject::Element *ea = (ArrayObject::Element *) (a); + ArrayObject::Element *eb = (ArrayObject::Element *) (b); S32 result = smCaseSensitive ? dStrnatcmp(ea->value, eb->value) : dStrnatcasecmp(ea->value, eb->value); - return (smDecreasing ? -result : result); + return ( smDecreasing ? -result : result ); } -S32 QSORT_CALLBACK ArrayObject::_valueNumCompare(const void* a, const void* b) +S32 QSORT_CALLBACK ArrayObject::_valueNumCompare( const void* a, const void* b ) { - ArrayObject::Element* ea = (ArrayObject::Element*)(a); - ArrayObject::Element* eb = (ArrayObject::Element*)(b); + ArrayObject::Element *ea = (ArrayObject::Element *) (a); + ArrayObject::Element *eb = (ArrayObject::Element *) (b); F32 aCol = dAtof(ea->value); F32 bCol = dAtof(eb->value); F32 result = aCol - bCol; S32 res = result < 0 ? -1 : (result > 0 ? 1 : 0); - return (smDecreasing ? -res : res); + return ( smDecreasing ? -res : res ); } -S32 QSORT_CALLBACK ArrayObject::_keyCompare(const void* a, const void* b) +S32 QSORT_CALLBACK ArrayObject::_keyCompare( const void* a, const void* b ) { - ArrayObject::Element* ea = (ArrayObject::Element*)(a); - ArrayObject::Element* eb = (ArrayObject::Element*)(b); + ArrayObject::Element *ea = (ArrayObject::Element *) (a); + ArrayObject::Element *eb = (ArrayObject::Element *) (b); S32 result = smCaseSensitive ? dStrnatcmp(ea->key, eb->key) : dStrnatcasecmp(ea->key, eb->key); - return (smDecreasing ? -result : result); + return ( smDecreasing ? -result : result ); } -S32 QSORT_CALLBACK ArrayObject::_keyNumCompare(const void* a, const void* b) +S32 QSORT_CALLBACK ArrayObject::_keyNumCompare( const void* a, const void* b ) { - ArrayObject::Element* ea = (ArrayObject::Element*)(a); - ArrayObject::Element* eb = (ArrayObject::Element*)(b); + ArrayObject::Element *ea = (ArrayObject::Element *) (a); + ArrayObject::Element *eb = (ArrayObject::Element *) (b); const char* aCol = ea->key; const char* bCol = eb->key; F32 result = dAtof(aCol) - dAtof(bCol); S32 res = result < 0 ? -1 : (result > 0 ? 1 : 0); - return (smDecreasing ? -res : res); + return ( smDecreasing ? -res : res ); } -S32 QSORT_CALLBACK ArrayObject::_keyFunctionCompare(const void* a, const void* b) +S32 QSORT_CALLBACK ArrayObject::_keyFunctionCompare( const void* a, const void* b ) { - ArrayObject::Element* ea = (ArrayObject::Element*)(a); - ArrayObject::Element* eb = (ArrayObject::Element*)(b); - + ArrayObject::Element* ea = ( ArrayObject::Element* )( a ); + ArrayObject::Element* eb = ( ArrayObject::Element* )( b ); + ConsoleValue cValue = Con::executef((const char*)smCompareFunction, ea->key, eb->key); S32 result = cValue.getInt(); - S32 res = result < 0 ? -1 : (result > 0 ? 1 : 0); - return (smDecreasing ? -res : res); + S32 res = result < 0 ? -1 : ( result > 0 ? 1 : 0 ); + return ( smDecreasing ? -res : res ); } -S32 QSORT_CALLBACK ArrayObject::_valueFunctionCompare(const void* a, const void* b) +S32 QSORT_CALLBACK ArrayObject::_valueFunctionCompare( const void* a, const void* b ) { - ArrayObject::Element* ea = (ArrayObject::Element*)(a); - ArrayObject::Element* eb = (ArrayObject::Element*)(b); - - ConsoleValue cValue = Con::executef((const char*)smCompareFunction, ea->value, eb->value); + ArrayObject::Element* ea = ( ArrayObject::Element* )( a ); + ArrayObject::Element* eb = ( ArrayObject::Element* )( b ); + + ConsoleValue cValue = Con::executef( (const char*)smCompareFunction, ea->value, eb->value ); S32 result = cValue.getInt(); - S32 res = result < 0 ? -1 : (result > 0 ? 1 : 0); - return (smDecreasing ? -res : res); + S32 res = result < 0 ? -1 : ( result > 0 ? 1 : 0 ); + return ( smDecreasing ? -res : res ); } //----------------------------------------------------------------------------- ArrayObject::ArrayObject() - : mCaseSensitive(false), - mCurrentIndex(0) + : mCaseSensitive( false ), + mCurrentIndex( 0 ) { } @@ -134,44 +134,44 @@ ArrayObject::ArrayObject() void ArrayObject::initPersistFields() { docsURL; - addField("caseSensitive", TypeBool, Offset(mCaseSensitive, ArrayObject), + addField( "caseSensitive", TypeBool, Offset( mCaseSensitive, ArrayObject ), "Makes the keys and values case-sensitive.\n" - "By default, comparison of key and value strings will be case-insensitive."); + "By default, comparison of key and value strings will be case-insensitive." ); - addProtectedField("key", TypeCaseString, 0, &_addKeyFromField, &emptyStringProtectedGetFn, - "Helper field which allows you to add new key['keyname'] = value pairs."); + addProtectedField( "key", TypeCaseString, 0, &_addKeyFromField, &emptyStringProtectedGetFn, + "Helper field which allows you to add new key['keyname'] = value pairs." ); Parent::initPersistFields(); } //----------------------------------------------------------------------------- -bool ArrayObject::_addKeyFromField(void* object, const char* index, const char* data) +bool ArrayObject::_addKeyFromField( void *object, const char *index, const char *data ) { - static_cast(object)->push_back(index, data); + static_cast( object )->push_back( index, data ); return false; } //----------------------------------------------------------------------------- -S32 ArrayObject::getIndexFromValue(const String& value) const +S32 ArrayObject::getIndexFromValue( const String &value ) const { S32 currentIndex = mMax(mCurrentIndex, 0); S32 foundIndex = -1; - for (S32 i = currentIndex; i < mArray.size(); i++) + for ( S32 i = currentIndex; i < mArray.size(); i++ ) { - if (isEqual(mArray[i].value, value)) + if ( isEqual( mArray[i].value, value ) ) { foundIndex = i; break; } } - if (foundIndex < 0) + if( foundIndex < 0 ) { - for (S32 i = 0; i < currentIndex; i++) + for ( S32 i = 0; i < currentIndex; i++ ) { - if (isEqual(mArray[i].value, value)) + if ( isEqual( mArray[i].value, value ) ) { foundIndex = i; break; @@ -184,24 +184,24 @@ S32 ArrayObject::getIndexFromValue(const String& value) const //----------------------------------------------------------------------------- -S32 ArrayObject::getIndexFromKey(const String& key) const +S32 ArrayObject::getIndexFromKey( const String &key ) const { S32 currentIndex = mMax(mCurrentIndex, 0); S32 foundIndex = -1; - for (S32 i = currentIndex; i < mArray.size(); i++) + for ( S32 i = currentIndex; i < mArray.size(); i++ ) { - if (isEqual(mArray[i].key, key)) + if ( isEqual( mArray[i].key, key ) ) { foundIndex = i; break; } } - if (foundIndex < 0) + if( foundIndex < 0 ) { - for (S32 i = 0; i < currentIndex; i++) + for ( S32 i = 0; i < currentIndex; i++ ) { - if (isEqual(mArray[i].key, key)) + if ( isEqual( mArray[i].key, key ) ) { foundIndex = i; break; @@ -214,24 +214,24 @@ S32 ArrayObject::getIndexFromKey(const String& key) const //----------------------------------------------------------------------------- -S32 ArrayObject::getIndexFromKeyValue(const String& key, const String& value) const +S32 ArrayObject::getIndexFromKeyValue( const String &key, const String &value ) const { S32 currentIndex = mMax(mCurrentIndex, 0); S32 foundIndex = -1; - for (S32 i = currentIndex; i < mArray.size(); i++) + for ( S32 i = currentIndex; i < mArray.size(); i++ ) { - if (isEqual(mArray[i].key, key) && isEqual(mArray[i].value, value)) + if ( isEqual( mArray[i].key, key ) && isEqual( mArray[i].value, value ) ) { foundIndex = i; break; } } - if (foundIndex < 0) + if ( foundIndex < 0 ) { - for (S32 i = 0; i < currentIndex; i++) + for ( S32 i = 0; i < currentIndex; i++ ) { - if (isEqual(mArray[i].key, key) && isEqual(mArray[i].value, value)) + if ( isEqual( mArray[i].key, key ) && isEqual( mArray[i].value, value ) ) { foundIndex = i; break; @@ -244,9 +244,9 @@ S32 ArrayObject::getIndexFromKeyValue(const String& key, const String& value) co //----------------------------------------------------------------------------- -const String& ArrayObject::getKeyFromIndex(S32 index) const +const String& ArrayObject::getKeyFromIndex( S32 index ) const { - if (index >= mArray.size() || index < 0) + if ( index >= mArray.size() || index < 0 ) return String::EmptyString; return mArray[index].key; @@ -254,9 +254,9 @@ const String& ArrayObject::getKeyFromIndex(S32 index) const //----------------------------------------------------------------------------- -const String& ArrayObject::getValueFromIndex(S32 index) const +const String& ArrayObject::getValueFromIndex( S32 index ) const { - if (index >= mArray.size() || index < 0) + if( index >= mArray.size() || index < 0 ) return String::EmptyString; return mArray[index].value; @@ -264,12 +264,12 @@ const String& ArrayObject::getValueFromIndex(S32 index) const //----------------------------------------------------------------------------- -S32 ArrayObject::countValue(const String& value) const +S32 ArrayObject::countValue( const String &value ) const { S32 count = 0; - for (S32 i = 0; i < mArray.size(); i++) + for ( S32 i = 0; i < mArray.size(); i++ ) { - if (isEqual(mArray[i].value, value)) + if ( isEqual( mArray[i].value, value ) ) count++; } @@ -278,12 +278,12 @@ S32 ArrayObject::countValue(const String& value) const //----------------------------------------------------------------------------- -S32 ArrayObject::countKey(const String& key) const +S32 ArrayObject::countKey( const String &key) const { S32 count = 0; - for (S32 i = 0; i < mArray.size(); i++) + for ( S32 i = 0; i < mArray.size(); i++ ) { - if (isEqual(mArray[i].key, key)) + if ( isEqual( mArray[i].key, key ) ) count++; } @@ -292,36 +292,36 @@ S32 ArrayObject::countKey(const String& key) const //----------------------------------------------------------------------------- -void ArrayObject::push_back(const String& key, const String& value) +void ArrayObject::push_back( const String &key, const String &value ) { - mArray.push_back(Element(key, value)); + mArray.push_back( Element( key, value ) ); } //----------------------------------------------------------------------------- -void ArrayObject::push_front(const String& key, const String& value) +void ArrayObject::push_front( const String &key, const String &value ) { - mArray.push_front(Element(key, value)); + mArray.push_front( Element( key, value ) ); } //----------------------------------------------------------------------------- -void ArrayObject::insert(const String& key, const String& value, S32 index) +void ArrayObject::insert( const String &key, const String &value, S32 index ) { - index = mClamp(index, 0, mArray.size()); - mArray.insert(index, Element(key, value)); + index = mClamp( index, 0, mArray.size() ); + mArray.insert( index, Element( key, value ) ); } //----------------------------------------------------------------------------- void ArrayObject::pop_back() { - if (mArray.size() <= 0) + if(mArray.size() <= 0) return; mArray.pop_back(); - if (mCurrentIndex >= mArray.size()) + if( mCurrentIndex >= mArray.size() ) mCurrentIndex = mArray.size() - 1; } @@ -329,23 +329,23 @@ void ArrayObject::pop_back() void ArrayObject::pop_front() { - if (mArray.size() <= 0) + if( mArray.size() <= 0 ) return; mArray.pop_front(); - - if (mCurrentIndex >= mArray.size()) + + if( mCurrentIndex >= mArray.size() ) mCurrentIndex = mArray.size() - 1; } //----------------------------------------------------------------------------- -void ArrayObject::erase(S32 index) +void ArrayObject::erase( S32 index ) { - if (index < 0 || index >= mArray.size()) + if(index < 0 || index >= mArray.size()) return; - mArray.erase(index); + mArray.erase( index ); } //----------------------------------------------------------------------------- @@ -360,7 +360,7 @@ void ArrayObject::empty() void ArrayObject::moveIndex(S32 prev, S32 index) { - if (index >= mArray.size()) + if(index >= mArray.size()) push_back(mArray[prev].key, mArray[prev].value); else mArray[index] = mArray[prev]; @@ -372,11 +372,11 @@ void ArrayObject::moveIndex(S32 prev, S32 index) void ArrayObject::uniqueValue() { - for (S32 i = 0; i < mArray.size(); i++) + for(S32 i=0; icount(); i++) + for(S32 i=0; icount(); i++) { const String& tempval = obj->getValueFromIndex(i); const String& tempkey = obj->getKeyFromIndex(i); @@ -434,16 +434,16 @@ void ArrayObject::duplicate(ArrayObject* obj) //----------------------------------------------------------------------------- -void ArrayObject::crop(ArrayObject* obj) +void ArrayObject::crop( ArrayObject *obj ) { - for (S32 i = 0; i < obj->count(); i++) + for( S32 i = 0; i < obj->count(); i++ ) { - const String& tempkey = obj->getKeyFromIndex(i); - for (S32 j = 0; j < mArray.size(); j++) + const String &tempkey = obj->getKeyFromIndex( i ); + for( S32 j = 0; j < mArray.size(); j++ ) { - if (isEqual(mArray[j].key, tempkey)) + if( isEqual( mArray[j].key, tempkey ) ) { - mArray.erase(j); + mArray.erase( j ); j--; } } @@ -454,7 +454,7 @@ void ArrayObject::crop(ArrayObject* obj) void ArrayObject::append(ArrayObject* obj) { - for (S32 i = 0; i < obj->count(); i++) + for(S32 i=0; icount(); i++) { const String& tempval = obj->getValueFromIndex(i); const String& tempkey = obj->getKeyFromIndex(i); @@ -464,7 +464,7 @@ void ArrayObject::append(ArrayObject* obj) //----------------------------------------------------------------------------- -void ArrayObject::setKey(const String& key, S32 index) +void ArrayObject::setKey( const String &key, S32 index ) { if (index >= mArray.size() || index < 0) return; @@ -474,54 +474,54 @@ void ArrayObject::setKey(const String& key, S32 index) //----------------------------------------------------------------------------- -void ArrayObject::setValue(const String& value, S32 index) +void ArrayObject::setValue( const String &value, S32 index ) { if (index >= mArray.size() || index < 0) return; - + mArray[index].value = value; } //----------------------------------------------------------------------------- -void ArrayObject::sort(bool valsort, bool asc, bool numeric) +void ArrayObject::sort( bool valsort, bool asc, bool numeric ) { - if (mArray.size() <= 1) + if ( mArray.size() <= 1 ) return; smDecreasing = asc ? false : true; smCaseSensitive = isCaseSensitive(); - if (numeric) + if ( numeric ) { - if (valsort) - dQsort((void*)&(mArray[0]), mArray.size(), sizeof(Element), _valueNumCompare); + if ( valsort ) + dQsort( (void *)&(mArray[0]), mArray.size(), sizeof(Element), _valueNumCompare) ; else - dQsort((void*)&(mArray[0]), mArray.size(), sizeof(Element), _keyNumCompare); + dQsort( (void *)&(mArray[0]), mArray.size(), sizeof(Element), _keyNumCompare ); } else { - if (valsort) - dQsort((void*)&(mArray[0]), mArray.size(), sizeof(Element), _valueCompare); + if( valsort ) + dQsort( (void *)&(mArray[0]), mArray.size(), sizeof(Element), _valueCompare ); else - dQsort((void*)&(mArray[0]), mArray.size(), sizeof(Element), _keyCompare); + dQsort( (void *)&(mArray[0]), mArray.size(), sizeof(Element), _keyCompare ); } } //----------------------------------------------------------------------------- -void ArrayObject::sort(bool valsort, bool asc, const char* callbackFunctionName) +void ArrayObject::sort( bool valsort, bool asc, const char* callbackFunctionName ) { - if (mArray.size() <= 1) + if( mArray.size() <= 1 ) return; smDecreasing = asc ? false : true; smCompareFunction = callbackFunctionName; - if (valsort) - dQsort((void*)&(mArray[0]), mArray.size(), sizeof(Element), _valueFunctionCompare); + if( valsort ) + dQsort( ( void* ) &( mArray[ 0 ] ), mArray.size(), sizeof( Element ), _valueFunctionCompare ) ; else - dQsort((void*)&(mArray[0]), mArray.size(), sizeof(Element), _keyFunctionCompare); + dQsort( ( void* ) &( mArray[ 0 ] ), mArray.size(), sizeof( Element ), _keyFunctionCompare ); smCompareFunction = NULL; } @@ -538,7 +538,7 @@ S32 ArrayObject::moveFirst() S32 ArrayObject::moveLast() { - if (mArray.empty()) + if ( mArray.empty() ) mCurrentIndex = 0; else mCurrentIndex = mArray.size() - 1; @@ -549,11 +549,11 @@ S32 ArrayObject::moveLast() S32 ArrayObject::moveNext() { - if (mCurrentIndex >= mArray.size() - 1) + if ( mCurrentIndex >= mArray.size() - 1 ) return -1; - + mCurrentIndex++; - + return mCurrentIndex; } @@ -561,21 +561,21 @@ S32 ArrayObject::moveNext() S32 ArrayObject::movePrev() { - if (mCurrentIndex <= 0) + if ( mCurrentIndex <= 0 ) return -1; mCurrentIndex--; - + return mCurrentIndex; } //----------------------------------------------------------------------------- -void ArrayObject::setCurrent(S32 idx) +void ArrayObject::setCurrent( S32 idx ) { - if (idx < 0 || idx >= mArray.size()) + if ( idx < 0 || idx >= mArray.size() ) { - Con::errorf("ArrayObject::setCurrent( %d ) is out of the array bounds!", idx); + Con::errorf( "ArrayObject::setCurrent( %d ) is out of the array bounds!", idx ); return; } @@ -586,13 +586,13 @@ void ArrayObject::setCurrent(S32 idx) void ArrayObject::echo() { - Con::printf("ArrayObject Listing:"); - Con::printf("Index Key Value"); - for (U32 i = 0; i < mArray.size(); i++) + Con::printf( "ArrayObject Listing:" ); + Con::printf( "Index Key Value" ); + for ( U32 i = 0; i < mArray.size(); i++ ) { const String& key = mArray[i].key; const String& val = mArray[i].value; - Con::printf("%d [%s] => %s", i, key.c_str(), val.c_str()); + Con::printf( "%d [%s] => %s", i, key.c_str(), val.c_str() ); } } @@ -600,20 +600,20 @@ void ArrayObject::echo() // Console Methods. //============================================================================= -DefineEngineMethod(ArrayObject, getIndexFromValue, S32, (const char* value), , +DefineEngineMethod( ArrayObject, getIndexFromValue, S32, ( const char* value ),, "Search the array from the current position for the element " "@param value Array value to search for\n" - "@return Index of the first element found, or -1 if none\n") + "@return Index of the first element found, or -1 if none\n" ) { - return object->getIndexFromValue(value); + return object->getIndexFromValue( value ); } -DefineEngineMethod(ArrayObject, getIndexFromKey, S32, (const char* key), , +DefineEngineMethod( ArrayObject, getIndexFromKey, S32, ( const char* key ),, "Search the array from the current position for the key " "@param value Array key to search for\n" - "@return Index of the first element found, or -1 if none\n") + "@return Index of the first element found, or -1 if none\n" ) { - return object->getIndexFromKey(key); + return object->getIndexFromKey( key ); } DefineEngineMethod(ArrayObject, getValueFromKey, const char*, (const char* key), , @@ -632,126 +632,126 @@ DefineEngineMethod(ArrayObject, getKeyFromValue, const char*, (const char* key), return object->getKeyFromIndex(object->getIndexFromValue(key)).c_str(); } -DefineEngineMethod(ArrayObject, getValue, const char*, (S32 index), , +DefineEngineMethod( ArrayObject, getValue, const char*, ( S32 index ),, "Get the value of the array element at the submitted index.\n" "@param index 0-based index of the array element to get\n" "@return The value of the array element at the specified index, " - "or \"\" if the index is out of range\n") + "or \"\" if the index is out of range\n" ) { - return object->getValueFromIndex(index).c_str(); + return object->getValueFromIndex( index ).c_str(); } -DefineEngineMethod(ArrayObject, getKey, const char*, (S32 index), , +DefineEngineMethod( ArrayObject, getKey, const char*, ( S32 index ),, "Get the key of the array element at the submitted index.\n" "@param index 0-based index of the array element to get\n" "@return The key associated with the array element at the " - "specified index, or \"\" if the index is out of range\n") + "specified index, or \"\" if the index is out of range\n" ) { - return object->getKeyFromIndex(index).c_str(); + return object->getKeyFromIndex( index ).c_str(); } -DefineEngineMethod(ArrayObject, setKey, void, (const char* key, S32 index), , +DefineEngineMethod( ArrayObject, setKey, void, ( const char* key, S32 index ),, "Set the key at the given index.\n" "@param key New key value\n" - "@param index 0-based index of the array element to update\n") + "@param index 0-based index of the array element to update\n" ) { - object->setKey(key, index); + object->setKey( key, index ); } -DefineEngineMethod(ArrayObject, setValue, void, (const char* value, S32 index), , +DefineEngineMethod( ArrayObject, setValue, void, ( const char* value, S32 index ),, "Set the value at the given index.\n" "@param value New array element value\n" - "@param index 0-based index of the array element to update\n") + "@param index 0-based index of the array element to update\n" ) { - object->setValue(value, index); + object->setValue( value, index ); } -DefineEngineMethod(ArrayObject, count, S32, (), , - "Get the number of elements in the array.") +DefineEngineMethod( ArrayObject, count, S32, (),, + "Get the number of elements in the array." ) { return (S32)object->count(); } -DefineEngineMethod(ArrayObject, countValue, S32, (const char* value), , +DefineEngineMethod( ArrayObject, countValue, S32, ( const char* value ),, "Get the number of times a particular value is found in the array.\n" - "@param value Array element value to count\n") + "@param value Array element value to count\n" ) { - return (S32)object->countValue(value); + return (S32)object->countValue( value ); } -DefineEngineMethod(ArrayObject, countKey, S32, (const char* key), , +DefineEngineMethod( ArrayObject, countKey, S32, ( const char* key ),, "Get the number of times a particular key is found in the array.\n" - "@param key Key value to count\n") + "@param key Key value to count\n" ) { - return (S32)object->countKey(key); + return (S32)object->countKey( key ); } -DefineEngineMethod(ArrayObject, add, void, (const char* key, const char* value), (""), +DefineEngineMethod( ArrayObject, add, void, ( const char* key, const char* value ), ( "" ), "Adds a new element to the end of an array (same as push_back()).\n" "@param key Key for the new element\n" - "@param value Value for the new element\n") + "@param value Value for the new element\n" ) { - object->push_back(key, value); + object->push_back( key, value ); } -DefineEngineMethod(ArrayObject, push_back, void, (const char* key, const char* value), (""), +DefineEngineMethod( ArrayObject, push_back, void, ( const char* key, const char* value ), ( "" ), "Adds a new element to the end of an array.\n" "@param key Key for the new element\n" - "@param value Value for the new element\n") + "@param value Value for the new element\n" ) { - object->push_back(key, value); + object->push_back( key, value ); } -DefineEngineMethod(ArrayObject, push_front, void, (const char* key, const char* value), (""), - "Adds a new element to the front of an array") +DefineEngineMethod( ArrayObject, push_front, void, ( const char* key, const char* value ), ( "" ), + "Adds a new element to the front of an array" ) { - object->push_front(key, value); + object->push_front( key, value ); } -DefineEngineMethod(ArrayObject, insert, void, (const char* key, const char* value, S32 index), , +DefineEngineMethod( ArrayObject, insert, void, ( const char* key, const char* value, S32 index ),, "Adds a new element to a specified position in the array.\n" "- @a index = 0 will insert an element at the start of the array (same as push_front())\n" "- @a index = %array.count() will insert an element at the end of the array (same as push_back())\n\n" "@param key Key for the new element\n" "@param value Value for the new element\n" - "@param index 0-based index at which to insert the new element") + "@param index 0-based index at which to insert the new element" ) { - object->insert(key, value, index); + object->insert( key, value, index ); } -DefineEngineMethod(ArrayObject, pop_back, void, (), , - "Removes the last element from the array") +DefineEngineMethod( ArrayObject, pop_back, void, (),, + "Removes the last element from the array" ) { object->pop_back(); } -DefineEngineMethod(ArrayObject, pop_front, void, (), , - "Removes the first element from the array") +DefineEngineMethod( ArrayObject, pop_front, void, (),, + "Removes the first element from the array" ) { object->pop_front(); } -DefineEngineMethod(ArrayObject, erase, void, (S32 index), , +DefineEngineMethod( ArrayObject, erase, void, ( S32 index ),, "Removes an element at a specific position from the array.\n" - "@param index 0-based index of the element to remove\n") + "@param index 0-based index of the element to remove\n" ) { - object->erase(index); + object->erase( index ); } -DefineEngineMethod(ArrayObject, empty, void, (), , - "Emptys all elements from an array") +DefineEngineMethod( ArrayObject, empty, void, (),, + "Emptys all elements from an array" ) { object->empty(); } -DefineEngineMethod(ArrayObject, uniqueValue, void, (), , - "Removes any elements that have duplicated values (leaving the first instance)") +DefineEngineMethod( ArrayObject, uniqueValue, void, (),, + "Removes any elements that have duplicated values (leaving the first instance)" ) { object->uniqueValue(); } -DefineEngineMethod(ArrayObject, uniqueKey, void, (), , - "Removes any elements that have duplicated keys (leaving the first instance)") +DefineEngineMethod( ArrayObject, uniqueKey, void, (),, + "Removes any elements that have duplicated keys (leaving the first instance)" ) { object->uniqueKey(); } @@ -762,122 +762,122 @@ DefineEngineMethod(ArrayObject, uniquePair, void, (), , object->uniquePair(); } -DefineEngineMethod(ArrayObject, duplicate, bool, (ArrayObject* target), , +DefineEngineMethod( ArrayObject, duplicate, bool, ( ArrayObject* target ),, "Alters array into an exact duplicate of the target array.\n" - "@param target ArrayObject to duplicate\n") + "@param target ArrayObject to duplicate\n" ) { - if (target) + if ( target ) { - object->duplicate(target); + object->duplicate( target ); return true; } return false; } -DefineEngineMethod(ArrayObject, crop, bool, (ArrayObject* target), , +DefineEngineMethod( ArrayObject, crop, bool, ( ArrayObject* target ),, "Removes elements with matching keys from array.\n" - "@param target ArrayObject containing keys to remove from this array\n") + "@param target ArrayObject containing keys to remove from this array\n" ) { - if (target) + if ( target ) { - object->crop(target); + object->crop( target ); return true; } return false; } -DefineEngineMethod(ArrayObject, append, bool, (ArrayObject* target), , +DefineEngineMethod( ArrayObject, append, bool, ( ArrayObject* target ),, "Appends the target array to the array object.\n" - "@param target ArrayObject to append to the end of this array\n") + "@param target ArrayObject to append to the end of this array\n" ) { - if (target) + if ( target ) { - object->append(target); + object->append( target ); return true; } return false; } -DefineEngineMethod(ArrayObject, sort, void, (bool ascending), (false), +DefineEngineMethod( ArrayObject, sort, void, ( bool ascending ), ( false ), "Alpha sorts the array by value\n\n" - "@param ascending [optional] True for ascending sort, false for descending sort\n") + "@param ascending [optional] True for ascending sort, false for descending sort\n" ) { - object->sort(true, ascending, false); + object->sort( true, ascending, false ); } -DefineEngineMethod(ArrayObject, sorta, void, (), , - "Alpha sorts the array by value in ascending order") +DefineEngineMethod( ArrayObject, sorta, void, (),, + "Alpha sorts the array by value in ascending order" ) { - object->sort(true, true, false); + object->sort( true, true, false ); } -DefineEngineMethod(ArrayObject, sortd, void, (), , - "Alpha sorts the array by value in descending order") +DefineEngineMethod( ArrayObject, sortd, void, (),, + "Alpha sorts the array by value in descending order" ) { - object->sort(true, false, false); + object->sort( true, false, false ); } -DefineEngineMethod(ArrayObject, sortk, void, (bool ascending), (false), +DefineEngineMethod( ArrayObject, sortk, void, ( bool ascending ), ( false ), "Alpha sorts the array by key\n\n" - "@param ascending [optional] True for ascending sort, false for descending sort\n") + "@param ascending [optional] True for ascending sort, false for descending sort\n" ) { - object->sort(false, ascending, false); + object->sort( false, ascending, false ); } -DefineEngineMethod(ArrayObject, sortka, void, (), , - "Alpha sorts the array by key in ascending order") +DefineEngineMethod( ArrayObject, sortka, void, (),, + "Alpha sorts the array by key in ascending order" ) { - object->sort(false, true, false); + object->sort( false, true, false ); } -DefineEngineMethod(ArrayObject, sortkd, void, (), , - "Alpha sorts the array by key in descending order") +DefineEngineMethod( ArrayObject, sortkd, void, (),, + "Alpha sorts the array by key in descending order" ) { - object->sort(false, false, false); + object->sort( false, false, false ); } -DefineEngineMethod(ArrayObject, sortn, void, (bool ascending), (false), +DefineEngineMethod( ArrayObject, sortn, void, ( bool ascending ), ( false ), "Numerically sorts the array by value\n\n" - "@param ascending [optional] True for ascending sort, false for descending sort\n") + "@param ascending [optional] True for ascending sort, false for descending sort\n" ) { - object->sort(true, ascending, true); + object->sort( true, ascending, true ); } -DefineEngineMethod(ArrayObject, sortna, void, (), , - "Numerically sorts the array by value in ascending order") +DefineEngineMethod( ArrayObject, sortna, void, (),, + "Numerically sorts the array by value in ascending order" ) { - object->sort(true, true, true); + object->sort( true, true, true ); } -DefineEngineMethod(ArrayObject, sortnd, void, (), , - "Numerically sorts the array by value in descending order") +DefineEngineMethod( ArrayObject, sortnd, void, (),, + "Numerically sorts the array by value in descending order" ) { - object->sort(true, false, true); + object->sort( true, false, true ); } -DefineEngineMethod(ArrayObject, sortnk, void, (bool ascending), (false), +DefineEngineMethod( ArrayObject, sortnk, void, ( bool ascending ), ( false ), "Numerically sorts the array by key\n\n" - "@param ascending [optional] True for ascending sort, false for descending sort\n") + "@param ascending [optional] True for ascending sort, false for descending sort\n" ) { - object->sort(false, ascending, true); + object->sort( false, ascending, true ); } -DefineEngineMethod(ArrayObject, sortnka, void, (), , - "Numerical sorts the array by key in ascending order") +DefineEngineMethod( ArrayObject, sortnka, void, (),, + "Numerical sorts the array by key in ascending order" ) { - object->sort(false, true, true); + object->sort( false, true, true ); } -DefineEngineMethod(ArrayObject, sortnkd, void, (), , - "Numerical sorts the array by key in descending order") +DefineEngineMethod( ArrayObject, sortnkd, void, (),, + "Numerical sorts the array by key in descending order" ) { - object->sort(false, false, true); + object->sort( false, false, true ); } -DefineEngineMethod(ArrayObject, sortf, void, (const char* functionName), , +DefineEngineMethod( ArrayObject, sortf, void, ( const char* functionName ),, "Sorts the array by value in ascending order using the given callback function.\n" "@param functionName Name of a function that takes two arguments A and B and returns -1 if A is less, 1 if B is less, and 0 if both are equal.\n\n" "@tsexample\n" @@ -886,78 +886,78 @@ DefineEngineMethod(ArrayObject, sortf, void, (const char* functionName), , " return strcmp( %a.name, %b.name );\n" "}\n\n" "%array.sortf( \"mySortCallback\" );\n" - "@endtsexample\n") + "@endtsexample\n" ) { - object->sort(true, true, functionName); + object->sort( true, true, functionName ); } -DefineEngineMethod(ArrayObject, sortfk, void, (const char* functionName), , +DefineEngineMethod( ArrayObject, sortfk, void, ( const char* functionName ),, "Sorts the array by key in ascending order using the given callback function.\n" "@param functionName Name of a function that takes two arguments A and B and returns -1 if A is less, 1 if B is less, and 0 if both are equal." - "@see sortf\n") + "@see sortf\n" ) { - object->sort(false, true, functionName); + object->sort( false, true, functionName ); } -DefineEngineMethod(ArrayObject, sortfd, void, (const char* functionName), , +DefineEngineMethod( ArrayObject, sortfd, void, ( const char* functionName ),, "Sorts the array by value in descending order using the given callback function.\n" "@param functionName Name of a function that takes two arguments A and B and returns -1 if A is less, 1 if B is less, and 0 if both are equal." - "@see sortf\n") + "@see sortf\n" ) { - object->sort(true, false, functionName); + object->sort( true, false, functionName ); } -DefineEngineMethod(ArrayObject, sortfkd, void, (const char* functionName), , +DefineEngineMethod( ArrayObject, sortfkd, void, ( const char* functionName ),, "Sorts the array by key in descending order using the given callback function.\n" "@param functionName Name of a function that takes two arguments A and B and returns -1 if A is less, 1 if B is less, and 0 if both are equal." - "@see sortf\n") + "@see sortf\n" ) { - object->sort(false, false, functionName); + object->sort( false, false, functionName ); } -DefineEngineMethod(ArrayObject, moveFirst, S32, (), , +DefineEngineMethod( ArrayObject, moveFirst, S32, (),, "Moves array pointer to start of array\n\n" - "@return Returns the new array pointer") + "@return Returns the new array pointer" ) { return object->moveFirst(); } -DefineEngineMethod(ArrayObject, moveLast, S32, (), , +DefineEngineMethod( ArrayObject, moveLast, S32, (),, "Moves array pointer to end of array\n\n" - "@return Returns the new array pointer") + "@return Returns the new array pointer" ) { return object->moveLast(); } -DefineEngineMethod(ArrayObject, moveNext, S32, (), , +DefineEngineMethod( ArrayObject, moveNext, S32, (),, "Moves array pointer to next position\n\n" - "@return Returns the new array pointer, or -1 if already at the end") + "@return Returns the new array pointer, or -1 if already at the end" ) { return object->moveNext(); } -DefineEngineMethod(ArrayObject, movePrev, S32, (), , +DefineEngineMethod( ArrayObject, movePrev, S32, (),, "Moves array pointer to prev position\n\n" - "@return Returns the new array pointer, or -1 if already at the start") + "@return Returns the new array pointer, or -1 if already at the start" ) { return object->movePrev(); } -DefineEngineMethod(ArrayObject, getCurrent, S32, (), , - "Gets the current pointer index") +DefineEngineMethod( ArrayObject, getCurrent, S32, (),, + "Gets the current pointer index" ) { return object->getCurrent(); } -DefineEngineMethod(ArrayObject, setCurrent, void, (S32 index), , +DefineEngineMethod( ArrayObject, setCurrent, void, ( S32 index ),, "Sets the current pointer index.\n" - "@param index New 0-based pointer index\n") + "@param index New 0-based pointer index\n" ) { - object->setCurrent(index); + object->setCurrent( index ); } -DefineEngineMethod(ArrayObject, echo, void, (), , - "Echos the array contents to the console") +DefineEngineMethod( ArrayObject, echo, void, (),, + "Echos the array contents to the console" ) { object->echo(); } diff --git a/Engine/source/console/arrayObject.h b/Engine/source/console/arrayObject.h index 0abdd6648..cde4f92b6 100644 --- a/Engine/source/console/arrayObject.h +++ b/Engine/source/console/arrayObject.h @@ -45,15 +45,15 @@ protected: String key; String value; Element() { } - Element(const String& _key, const String& _value) : key(_key), value(_value) { } + Element( const String& _key, const String& _value ) : key(_key), value(_value) { } }; bool mCaseSensitive; S32 mCurrentIndex; - + /// The array of key/value pairs. Vector< Element > mArray; - + /// @name Sorting /// @{ @@ -61,60 +61,60 @@ protected: static bool smCaseSensitive; static const char* smCompareFunction; - static S32 QSORT_CALLBACK _valueCompare(const void* a, const void* b); - static S32 QSORT_CALLBACK _valueNumCompare(const void* a, const void* b); - static S32 QSORT_CALLBACK _keyCompare(const void* a, const void* b); - static S32 QSORT_CALLBACK _keyNumCompare(const void* a, const void* b); - static S32 QSORT_CALLBACK _keyFunctionCompare(const void* a, const void* b); - static S32 QSORT_CALLBACK _valueFunctionCompare(const void* a, const void* b); - + static S32 QSORT_CALLBACK _valueCompare( const void *a, const void *b ); + static S32 QSORT_CALLBACK _valueNumCompare( const void *a, const void *b ); + static S32 QSORT_CALLBACK _keyCompare( const void *a, const void *b ); + static S32 QSORT_CALLBACK _keyNumCompare( const void *a, const void *b ); + static S32 QSORT_CALLBACK _keyFunctionCompare( const void* a, const void* b ); + static S32 QSORT_CALLBACK _valueFunctionCompare( const void* a, const void* b ); + /// @} - static bool _addKeyFromField(void* object, const char* index, const char* data); + static bool _addKeyFromField( void *object, const char *index, const char *data ); public: - + ArrayObject(); - /// @name Data Query + /// @name Data Query /// @{ - + /// Returns true if string handling by the array is case-sensitive. bool isCaseSensitive() const { return mCaseSensitive; } - bool isEqual(const String& valA, const String& valB) const + bool isEqual( const String &valA, const String &valB ) const { - return valA.equal(valB, isCaseSensitive() ? String::Case : String::NoCase); + return valA.equal( valB, isCaseSensitive() ? String::Case : String::NoCase ); } - /// Searches the array for the first matching value from the + /// Searches the array for the first matching value from the /// current array position. It will return -1 if no matching /// index is found. - S32 getIndexFromValue(const String& value) const; + S32 getIndexFromValue( const String &value ) const; /// Searches the array for the first matching key from the current /// array position. It will return -1 if no matching index found. - S32 getIndexFromKey(const String& key) const; - + S32 getIndexFromKey( const String &key ) const; + /// Returns the key for a given index. /// Will return a null value for an invalid index - const String& getKeyFromIndex(S32 index) const; + const String& getKeyFromIndex( S32 index ) const; /// Returns the value for a given index. /// Will return a null value for an invalid index - const String& getValueFromIndex(S32 index) const; - + const String& getValueFromIndex( S32 index ) const; + /// - S32 getIndexFromKeyValue(const String& key, const String& value) const; + S32 getIndexFromKeyValue( const String &key, const String &value ) const; /// Counts the number of elements in the array S32 count() const { return mArray.size(); } /// Counts the number of instances of a particular value in the array - S32 countValue(const String& value) const; + S32 countValue( const String &value ) const; /// Counts the number of instances of a particular key in the array - S32 countKey(const String& key) const; + S32 countKey( const String &key ) const; /// @} @@ -122,13 +122,13 @@ public: /// @{ /// Adds a new array item to the end of the array - void push_back(const String& key, const String& value); + void push_back( const String &key, const String &value ); /// Adds a new array item to the front of the array - void push_front(const String& key, const String& value); + void push_front( const String &key, const String &value ); /// Adds a new array item to a particular index of the array - void insert(const String& key, const String& value, S32 index); + void insert( const String &key, const String &value, S32 index ); /// Removes an array item from the end of the array void pop_back(); @@ -137,13 +137,13 @@ public: void pop_front(); /// Removes an array item from a particular index of the array - void erase(S32 index); + void erase( S32 index ); /// Clears an array void empty(); /// Moves a key and value from one index location to another. - void moveIndex(S32 prev, S32 index); + void moveIndex( S32 prev, S32 index ); /// @} @@ -163,31 +163,31 @@ public: void uniquePair(); /// Makes this array an exact duplicate of another array - void duplicate(ArrayObject* obj); + void duplicate( ArrayObject *obj ); /// Crops the keys that exists in the target array from our current array - void crop(ArrayObject* obj); + void crop( ArrayObject *obj ); /// Appends the target array to our current array - void append(ArrayObject* obj); + void append( ArrayObject *obj ); /// Sets the key at the given index - void setKey(const String& key, S32 index); + void setKey( const String &key, S32 index ); /// Sets the key at the given index - void setValue(const String& value, S32 index); + void setValue( const String &value, S32 index ); /// This sorts the array. /// @param valtest Determines whether sorting by value or key. /// @param asc Determines if sorting ascending or descending. /// @param numeric Determines if sorting alpha or numeric search. - void sort(bool valtest, bool asc, bool numeric); - + void sort( bool valtest, bool asc, bool numeric ); + /// This sorts the array using a script callback. /// @param valtest Determines whether sorting by value or key. /// @param asc Determines if sorting ascending or descending. /// @param callbackFunctionName Name of the script function. - void sort(bool valtest, bool asc, const char* callbackFunctionName); + void sort( bool valtest, bool asc, const char* callbackFunctionName ); /// @} @@ -212,7 +212,7 @@ public: S32 getCurrent() const { return mCurrentIndex; } /// - void setCurrent(S32 idx); + void setCurrent( S32 idx ); /// @} @@ -226,10 +226,10 @@ public: /// @} // SimObject - DECLARE_CONOBJECT(ArrayObject); - DECLARE_CATEGORY("Core"); - DECLARE_DESCRIPTION("An object storing an indexed sequence of key/value pairs."); - + DECLARE_CONOBJECT( ArrayObject ); + DECLARE_CATEGORY( "Core" ); + DECLARE_DESCRIPTION( "An object storing an indexed sequence of key/value pairs." ); + static void initPersistFields(); }; From a7dabae88abe3c46274d1fde87c32e9759c0abf5 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Thu, 14 Mar 2024 11:30:52 +0000 Subject: [PATCH 50/53] Update helperFunctions.tscript --- .../BaseGame/game/core/utility/scripts/helperFunctions.tscript | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Templates/BaseGame/game/core/utility/scripts/helperFunctions.tscript b/Templates/BaseGame/game/core/utility/scripts/helperFunctions.tscript index 905100648..fc6e0d33c 100644 --- a/Templates/BaseGame/game/core/utility/scripts/helperFunctions.tscript +++ b/Templates/BaseGame/game/core/utility/scripts/helperFunctions.tscript @@ -650,7 +650,7 @@ function populateAllFonts() continue; %fontarray.push_back(%obj.fontType,%obj.fontSize); } - %fontarray.uniqueKey(); + %fontarray.uniquePair(); %fontarrayCount = %fontarray.count(); From 1e8841e6b53a261f7cacc821d5b98762ad999c14 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Thu, 14 Mar 2024 13:32:21 +0000 Subject: [PATCH 51/53] pushed buffer creation up to the device level now shaders ask the device to create a buffer, if a buffer of the same name and size already exist then a pointer to that buffer is returned instead. Going to see if something similar can be added to the opengl end. --- Engine/source/gfx/D3D11/gfxD3D11Device.cpp | 41 ++++++++++++ Engine/source/gfx/D3D11/gfxD3D11Device.h | 5 ++ Engine/source/gfx/D3D11/gfxD3D11Shader.cpp | 74 +++++++++------------- Engine/source/gfx/D3D11/gfxD3D11Shader.h | 4 +- 4 files changed, 79 insertions(+), 45 deletions(-) diff --git a/Engine/source/gfx/D3D11/gfxD3D11Device.cpp b/Engine/source/gfx/D3D11/gfxD3D11Device.cpp index 98497534a..6e937bc34 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Device.cpp +++ b/Engine/source/gfx/D3D11/gfxD3D11Device.cpp @@ -160,6 +160,11 @@ GFXD3D11Device::~GFXD3D11Device() for (; sampIter != mSamplersMap.end(); ++sampIter) SAFE_RELEASE(sampIter->value); + // Free device buffers + DeviceBufferMap::Iterator bufferIter = mDeviceBufferMap.begin(); + for (; bufferIter != mDeviceBufferMap.end(); ++bufferIter) + SAFE_RELEASE(bufferIter->value); + // Free the vertex declarations. VertexDeclMap::Iterator iter = mVertexDecls.begin(); for (; iter != mVertexDecls.end(); ++iter) @@ -1861,3 +1866,39 @@ const char* GFXD3D11Device::interpretDebugResult(long result) } return error; } + +ID3D11Buffer* GFXD3D11Device::getDeviceBuffer(const GFXShaderConstDesc desc) +{ + String name(desc.name + "_" + String::ToString(desc.size)); + DeviceBufferMap::Iterator buf = mDeviceBufferMap.find(name); + if (buf != mDeviceBufferMap.end()) + { + mDeviceBufferMap[name]->AddRef(); + return mDeviceBufferMap[name]; + } + + ID3D11Buffer* tempBuf; + 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, &tempBuf); + + if (FAILED(hr)) + { + AssertFatal(false, "Failed to create device buffer."); + } + + mDeviceBufferMap[name] = tempBuf; + +#ifdef TORQUE_DEBUG + tempBuf->SetPrivateData(WKPDID_D3DDebugObjectName, name.size(), name.c_str()); +#endif + + return tempBuf; +} diff --git a/Engine/source/gfx/D3D11/gfxD3D11Device.h b/Engine/source/gfx/D3D11/gfxD3D11Device.h index 7b5b24a7d..41b3415e9 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Device.h +++ b/Engine/source/gfx/D3D11/gfxD3D11Device.h @@ -51,6 +51,7 @@ class GFXD3D11Device : public GFXDevice { public: typedef Map SamplerMap; + typedef Map DeviceBufferMap; private: friend class GFXResource; @@ -105,6 +106,7 @@ protected: /// Used to lookup sampler state for a given hash key SamplerMap mSamplersMap; + DeviceBufferMap mDeviceBufferMap; ID3D11RenderTargetView* mDeviceBackBufferView; ID3D11DepthStencilView* mDeviceDepthStencilView; @@ -326,6 +328,9 @@ public: const SamplerMap &getSamplersMap() const { return mSamplersMap; } SamplerMap &getSamplersMap(){ return mSamplersMap; } const char* interpretDebugResult(long result); + + // grab device buffer. + ID3D11Buffer* getDeviceBuffer(const GFXShaderConstDesc desc); }; #endif diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp index 7a2b7d515..5dd1a95d7 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp @@ -141,23 +141,15 @@ GFXD3D11ShaderConstBuffer::GFXD3D11ShaderConstBuffer(GFXD3D11Shader* shader) for (U32 i = 0; i < 6; i++) { - for (U32 j = 0; j < 3; j++) + for (U32 j = 0; j < 16; j++) { - mBoundBuffers[i][j] = NULL; + mBoundBuffers[i][j] = nullptr; } } } GFXD3D11ShaderConstBuffer::~GFXD3D11ShaderConstBuffer() { - for (U32 i = 0; i < 6; i++) - { - for (U32 j = 0; j < 3; j++) - { - SAFE_RELEASE(mBoundBuffers[i][j]); - } - } - for (auto& pair : mBufferMap) { delete[] pair.value.data; } @@ -459,11 +451,11 @@ const String GFXD3D11ShaderConstBuffer::describeSelf() const return ret; } -void GFXD3D11ShaderConstBuffer::addBuffer(U32 bufBindingPoint, GFXShaderStage shaderStage, U32 size) +void GFXD3D11ShaderConstBuffer::addBuffer(const GFXShaderConstDesc desc) { S32 shaderStageID = -1; // Initialize to -1 (bit not found) for (int i = 0; i < sizeof(S32) * 8; ++i) { - if (shaderStage & (1 << i)) { + if (desc.shaderStage & (1 << i)) { shaderStageID = i; break; } @@ -475,30 +467,15 @@ void GFXD3D11ShaderConstBuffer::addBuffer(U32 bufBindingPoint, GFXShaderStage sh AssertFatal(false, "DX Const buffer requires a shaderStage flag."); } - const BufferKey bufKey(bufBindingPoint, shaderStageID); + const BufferKey bufKey(desc.bindPoint, shaderStageID); // doesnt matter if its already added. - U8* buf = new U8[size]; - dMemset(buf, 0, size); + U8* buf = new U8[desc.size]; + dMemset(buf, 0, desc.size); mBufferMap[bufKey].data = buf; - mBufferMap[bufKey].size = size; + mBufferMap[bufKey].size = desc.size; mBufferMap[bufKey].isDirty = true; - //ID3D11Buffer* tempBuf; - D3D11_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = 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, &mBoundBuffers[(U32)shaderStageID][bufBindingPoint]); - - if (FAILED(hr)) - { - AssertFatal(false, "can't create constant buffer"); - } + mBoundBuffers[(U32)shaderStageID][desc.bindPoint] = D3D11->getDeviceBuffer(desc); } void GFXD3D11ShaderConstBuffer::activate( GFXD3D11ShaderConstBuffer *prevShaderBuffer ) @@ -586,14 +563,6 @@ void GFXD3D11ShaderConstBuffer::onShaderReload( GFXD3D11Shader *shader ) { AssertFatal( shader == mShader, "GFXD3D11ShaderConstBuffer::onShaderReload is hosed!" ); - for (U32 i = 0; i < 6; i++) - { - for (U32 j = 0; j < 3; j++) - { - SAFE_RELEASE(mBoundBuffers[i][j]); - } - } - for (auto& pair : mBufferMap) { delete[] pair.value.data; } @@ -602,7 +571,7 @@ void GFXD3D11ShaderConstBuffer::onShaderReload( GFXD3D11Shader *shader ) for (GFXD3D11Shader::BufferMap::Iterator i = shader->mBuffers.begin(); i != shader->mBuffers.end(); ++i) { // add our buffer descriptions to the full const buffer. - this->addBuffer(i->value.bindPoint, i->value.shaderStage, i->value.size); + this->addBuffer(i->value); } // Set the lost state. @@ -922,7 +891,26 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection* refTable, desc.bindPoint = shaderInputBind.BindPoint; if (String::compare(desc.name, "$Globals") == 0 || String::compare(desc.name, "$Params") == 0) { - desc.name = desc.name + String::ToString((U32)shaderStage-1); + switch (shaderStage) + { + case VERTEX_SHADER: + desc.name = desc.name + "_" + mVertexFile.getFileName(); + break; + case PIXEL_SHADER: + desc.name = desc.name + "_" + mPixelFile.getFileName(); + break; + case GEOMETRY_SHADER: + desc.name = desc.name + "_" + mGeometryFile.getFileName(); + break; + case DOMAIN_SHADER: + break; + case HULL_SHADER: + break; + case COMPUTE_SHADER: + break; + default: + break; + } } mBuffers[desc.name] = desc; @@ -1227,7 +1215,7 @@ GFXShaderConstBufferRef GFXD3D11Shader::allocConstBuffer() for (BufferMap::Iterator i = mBuffers.begin(); i != mBuffers.end(); ++i) { // add our buffer descriptions to the full const buffer. - buffer->addBuffer(i->value.bindPoint, i->value.shaderStage, i->value.size); + buffer->addBuffer(i->value); } mActiveBuffers.push_back( buffer ); diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.h b/Engine/source/gfx/D3D11/gfxD3D11Shader.h index f233f0f01..80bb55b5e 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.h +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.h @@ -117,7 +117,7 @@ public: /// @param mPrevShaderBuffer The previously active buffer void activate(GFXD3D11ShaderConstBuffer *prevShaderBuffer); - void addBuffer(U32 bufBindingPoint, GFXShaderStage shaderStage, U32 size); + void addBuffer(const GFXShaderConstDesc desc); /// Called from GFXD3D11Shader when constants have changed and need /// to be the shader this buffer references is reloaded. @@ -161,7 +161,7 @@ protected: void setMatrix(const GFXShaderConstDesc& handle, const U32 inSize, const void* data, U8* basePointer); void internalSet(GFXShaderConstHandle* handle, const U32 inSize, const void* data); - ID3D11Buffer* mBoundBuffers[6][3]; + ID3D11Buffer* mBoundBuffers[6][16]; }; class gfxD3D11Include; From 11d8604d8e84c83cda7d735f1f697a9bdbd9c4dc Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Thu, 14 Mar 2024 14:23:08 +0000 Subject: [PATCH 52/53] ogl device buffer creation now ogl mirrors dx side with ubo creation and clearing pushed up to the device level. --- Engine/source/gfx/D3D11/gfxD3D11Shader.cpp | 8 ++++++ Engine/source/gfx/gl/gfxGLDevice.cpp | 22 ++++++++++++++++ Engine/source/gfx/gl/gfxGLDevice.h | 8 ++++++ Engine/source/gfx/gl/gfxGLShader.cpp | 29 ++++++++++------------ Engine/source/gfx/gl/gfxGLShader.h | 2 +- 5 files changed, 52 insertions(+), 17 deletions(-) diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp index 5dd1a95d7..6259be330 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp @@ -155,6 +155,14 @@ GFXD3D11ShaderConstBuffer::~GFXD3D11ShaderConstBuffer() } mBufferMap.clear(); // Clear the map + for (U32 i = 0; i < 6; i++) + { + for (U32 j = 0; j < 16; j++) + { + mBoundBuffers[i][j] = nullptr; + } + } + if (mShader) mShader->_unlinkBuffer(this); } diff --git a/Engine/source/gfx/gl/gfxGLDevice.cpp b/Engine/source/gfx/gl/gfxGLDevice.cpp index 452e72227..148a68648 100644 --- a/Engine/source/gfx/gl/gfxGLDevice.cpp +++ b/Engine/source/gfx/gl/gfxGLDevice.cpp @@ -292,6 +292,11 @@ GFXGLDevice::~GFXGLDevice() mTextureManager->kill(); } + // Free device buffers + DeviceBufferMap::Iterator bufferIter = mDeviceBufferMap.begin(); + for (; bufferIter != mDeviceBufferMap.end(); ++bufferIter) + glDeleteBuffers(1, &bufferIter->value); + GFXResource* walk = mResourceListHead; while(walk) { @@ -307,6 +312,23 @@ GFXGLDevice::~GFXGLDevice() SAFE_DELETE( mOpenglStateCache ); } +GLuint GFXGLDevice::getDeviceBuffer(const GFXShaderConstDesc desc) +{ + String name(desc.name + "_" + String::ToString(desc.size)); + DeviceBufferMap::Iterator buf = mDeviceBufferMap.find(name); + if (buf != mDeviceBufferMap.end()) + { + return mDeviceBufferMap[name]; + } + + GLuint uboHandle; + glGenBuffers(1, &uboHandle); + + mDeviceBufferMap[name] = uboHandle; + + return uboHandle; +} + void GFXGLDevice::zombify() { mTextureManager->zombify(); diff --git a/Engine/source/gfx/gl/gfxGLDevice.h b/Engine/source/gfx/gl/gfxGLDevice.h index 36b0cfa71..981aff662 100644 --- a/Engine/source/gfx/gl/gfxGLDevice.h +++ b/Engine/source/gfx/gl/gfxGLDevice.h @@ -47,6 +47,7 @@ class GFXGLShaderConstBuffer; class GFXGLDevice : public GFXDevice { + public: struct GLCapabilities { @@ -60,6 +61,11 @@ public: }; GLCapabilities mCapabilities; + // UBO map + typedef Map DeviceBufferMap; + // grab device buffer. + GLuint getDeviceBuffer(const GFXShaderConstDesc desc); + void zombify(); void resurrect(); GFXGLDevice(U32 adapterIndex); @@ -202,6 +208,8 @@ protected: virtual void setVertexStream( U32 stream, GFXVertexBuffer *buffer ); virtual void setVertexStreamFrequency( U32 stream, U32 frequency ); StrongRefPtr mCurrentConstBuffer; + DeviceBufferMap mDeviceBufferMap; + private: typedef GFXDevice Parent; diff --git a/Engine/source/gfx/gl/gfxGLShader.cpp b/Engine/source/gfx/gl/gfxGLShader.cpp index fd2da2f3f..e13ff1a52 100644 --- a/Engine/source/gfx/gl/gfxGLShader.cpp +++ b/Engine/source/gfx/gl/gfxGLShader.cpp @@ -434,30 +434,27 @@ void GFXGLShaderConstBuffer::activate(GFXGLShaderConstBuffer* prevShaderBuffer) mWasLost = false; } -void GFXGLShaderConstBuffer::addBuffer(S32 bufBindingPoint, U32 size) +void GFXGLShaderConstBuffer::addBuffer(const GFXShaderConstDesc desc) { // if this is the global buffer set it to the highest. - if (bufBindingPoint == -1) + if (desc.bindPoint == -1) { // we dont create a bufferhandle for this one. - U8* buf = new U8[size]; - dMemset(buf, 0, size); + U8* buf = new U8[desc.size]; + dMemset(buf, 0, desc.size); mBufferMap[-1].data = buf; - mBufferMap[-1].size = size; + mBufferMap[-1].size = desc.size; mBufferMap[-1].isDirty = true; } else { - U8* buf = new U8[size]; - dMemset(buf, 0, size); - mBufferMap[bufBindingPoint].data = buf; - mBufferMap[bufBindingPoint].size = size; - mBufferMap[bufBindingPoint].isDirty = true; + U8* buf = new U8[desc.size]; + dMemset(buf, 0, desc.size); + mBufferMap[desc.bindPoint].data = buf; + mBufferMap[desc.bindPoint].size = desc.size; + mBufferMap[desc.bindPoint].isDirty = true; - GLuint uboHandle; - glGenBuffers(1, &uboHandle); - - mBufferMap[bufBindingPoint].bufHandle = uboHandle; + mBufferMap[desc.bindPoint].bufHandle = GFXGL->getDeviceBuffer(desc); } } @@ -478,7 +475,7 @@ void GFXGLShaderConstBuffer::onShaderReload(GFXGLShader* shader) for (GFXGLShader::BufferMap::Iterator i = shader->mBuffers.begin(); i != shader->mBuffers.end(); ++i) { // add our buffer descriptions to the full const buffer. - this->addBuffer(i->value.bindPoint, i->value.size); + this->addBuffer(i->value); } mWasLost = true; @@ -1161,7 +1158,7 @@ GFXShaderConstBufferRef GFXGLShader::allocConstBuffer() for (BufferMap::Iterator i = mBuffers.begin(); i != mBuffers.end(); ++i) { // add our buffer descriptions to the full const buffer. - buffer->addBuffer(i->value.bindPoint, i->value.size); + buffer->addBuffer(i->value); } buffer->registerResourceWithDevice(getOwningDevice()); diff --git a/Engine/source/gfx/gl/gfxGLShader.h b/Engine/source/gfx/gl/gfxGLShader.h index ee8b53dc6..1ca420b9e 100644 --- a/Engine/source/gfx/gl/gfxGLShader.h +++ b/Engine/source/gfx/gl/gfxGLShader.h @@ -111,7 +111,7 @@ public: /// Called by GFXGLDevice to activate this buffer. void activate(GFXGLShaderConstBuffer* prevShaderBuffer); - void addBuffer(S32 bufBindingPoint, U32 size); + void addBuffer(const GFXShaderConstDesc desc); /// Called when the shader this buffer references is reloaded. void onShaderReload(GFXGLShader* shader); From db97e8473a8f06b5a1bfee737f4386bc7d551496 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Thu, 14 Mar 2024 15:14:01 +0000 Subject: [PATCH 53/53] Update winPlatformCPUCount.cpp fix pragma push/pop. --- .../platformWin32/winPlatformCPUCount.cpp | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/Engine/source/platformWin32/winPlatformCPUCount.cpp b/Engine/source/platformWin32/winPlatformCPUCount.cpp index e4b113c67..31edce054 100644 --- a/Engine/source/platformWin32/winPlatformCPUCount.cpp +++ b/Engine/source/platformWin32/winPlatformCPUCount.cpp @@ -1,19 +1,19 @@ // Original code is: -// Copyright (c) 2005 Intel Corporation +// Copyright (c) 2005 Intel Corporation // All Rights Reserved // // CPUCount.cpp : Detects three forms of hardware multi-threading support across IA-32 platform -// The three forms of HW multithreading are: Multi-processor, Multi-core, and +// The three forms of HW multithreading are: Multi-processor, Multi-core, and // HyperThreading Technology. // This application enumerates all the logical processors enabled by OS and BIOS, -// determine the HW topology of these enabled logical processors in the system +// determine the HW topology of these enabled logical processors in the system // using information provided by CPUID instruction. // A multi-processing system can support any combination of the three forms of HW -// multi-threading support. The relevant topology can be identified using a -// three level decomposition of the "initial APIC ID" into -// Package_id, core_id, and SMT_id. Such decomposition provides a three-level map of +// multi-threading support. The relevant topology can be identified using a +// three level decomposition of the "initial APIC ID" into +// Package_id, core_id, and SMT_id. Such decomposition provides a three-level map of // the topology of hardware resources and -// allow multi-threaded software to manage shared hardware resources in +// allow multi-threaded software to manage shared hardware resources in // the platform to reduce resource contention // Multicore detection algorithm for processor and cache topology requires @@ -60,25 +60,25 @@ namespace CPUInfo { PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer = NULL; DWORD returnLength = 0; - + // get buffer length DWORD rc = GetLogicalProcessorInformation( buffer, &returnLength ); buffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)malloc( returnLength ); - rc = GetLogicalProcessorInformation( buffer, &returnLength ); + rc = GetLogicalProcessorInformation( buffer, &returnLength ); // if we fail, assume single threaded if( FALSE == rc ) - { + { free( buffer ); Con::errorf("Unable to determine CPU Count, assuming 1 core"); TotAvailCore = 1; TotAvailLogical = 1; return CONFIG_SingleCoreAndHTNotCapable; - } + } -#pragma push -#pragma warning (disable: 6011) +#pragma warning( push ) +#pragma warning( disable: 6011 ) PSYSTEM_LOGICAL_PROCESSOR_INFORMATION ptr = buffer; DWORD byteOffset = 0; @@ -95,7 +95,7 @@ namespace CPUInfo { } free( buffer ); -#pragma pop +#pragma warning( pop ) EConfig StatusFlag = CONFIG_SingleCoreAndHTNotCapable;