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_