From 9dc5ae833bb76b3028a5cecac6134c444e8ce6bd Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Wed, 13 Mar 2024 22:23:01 +0000 Subject: [PATCH] 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_