diff options
| author | Egor Yusov <egor.yusov@gmail.com> | 2019-02-22 04:30:57 +0000 |
|---|---|---|
| committer | Egor Yusov <egor.yusov@gmail.com> | 2019-02-22 04:30:57 +0000 |
| commit | ccbc4ecd6cb012de71cb4cafa04175d268aa64d3 (patch) | |
| tree | ba1d7b1dc485aac0ceee1951c6481f5b3065c4f6 /Graphics/GraphicsEngineOpenGL | |
| parent | Fixed SRBs with non-separable shaders in GL back-end (diff) | |
| download | DiligentCore-ccbc4ecd6cb012de71cb4cafa04175d268aa64d3.tar.gz DiligentCore-ccbc4ecd6cb012de71cb4cafa04175d268aa64d3.zip | |
Implemented workaround to allow binding static resources when separate shader objects are not available in GL back-end
Diffstat (limited to 'Graphics/GraphicsEngineOpenGL')
5 files changed, 165 insertions, 21 deletions
diff --git a/Graphics/GraphicsEngineOpenGL/include/ShaderGLImpl.h b/Graphics/GraphicsEngineOpenGL/include/ShaderGLImpl.h index 8c5435ad..77c5f554 100644 --- a/Graphics/GraphicsEngineOpenGL/include/ShaderGLImpl.h +++ b/Graphics/GraphicsEngineOpenGL/include/ShaderGLImpl.h @@ -75,9 +75,12 @@ public: virtual void BindResources( IResourceMapping* pResourceMapping, Uint32 Flags )override final; - virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface )override final; + virtual void QueryInterface( const INTERFACE_ID &IID, IObject **ppInterface )override final; - virtual IShaderVariable* GetShaderVariable( const Char* Name )override final; + // If separate shaders are not available, the method can optionally create + // a placeholder for static resource variable + IShaderVariable* GetShaderVariable(const Char* Name, bool CreatePlaceholder); + virtual IShaderVariable* GetShaderVariable(const Char* Name)override final; virtual Uint32 GetVariableCount() const override final; @@ -85,13 +88,62 @@ public: GLProgram& GetGlProgram(){return m_GlProgObj;} + // This class is used to keep references to static resources when separate shaders are not available + class StaticVarPlaceholder final : public ObjectBase<IShaderVariable> + { + public: + StaticVarPlaceholder(IReferenceCounters* pRefCounters, String Name, Uint32 Index) : + ObjectBase<IShaderVariable>(pRefCounters), + m_Name (std::move(Name)), + m_Index (Index) + {} + + virtual void Set(IDeviceObject* pObject)override final + { + SetArray(&pObject, 0, 1); + } + virtual void SetArray(IDeviceObject* const* ppObjects, Uint32 FirstElement, Uint32 NumElements)override final + { + if (m_Objects.size() < FirstElement + NumElements) + m_Objects.resize(FirstElement + NumElements); + for (Uint32 i=0; i < NumElements; ++i) + m_Objects[FirstElement + i] = ppObjects[i]; + } + virtual SHADER_VARIABLE_TYPE GetType()const override final + { + return SHADER_VARIABLE_TYPE_STATIC; + } + virtual Uint32 GetArraySize()const override final + { + return static_cast<Uint32>(m_Objects.size()); + } + virtual const Char* GetName()const override final + { + return m_Name.c_str(); + } + virtual Uint32 GetIndex()const override final + { + return m_Index; + } + IDeviceObject* Get(Uint32 ArrayIndex) + { + return ArrayIndex < m_Objects.size() ? m_Objects[ArrayIndex].RawPtr() : nullptr; + } + private: + const String m_Name; + const Uint32 m_Index; + std::vector<RefCntAutoPtr<IDeviceObject>> m_Objects; + }; private: friend class PipelineStateGLImpl; friend class DeviceContextGLImpl; - GLProgram m_GlProgObj; // Used if program pipeline supported - GLObjectWrappers::GLShaderObj m_GLShaderObj; // Used if program pipelines are not supported + GLProgram m_GlProgObj; // Used if program pipeline supported + GLObjectWrappers::GLShaderObj m_GLShaderObj; // Used if program pipelines are not supported + + std::vector<RefCntAutoPtr<StaticVarPlaceholder>> m_StaticResources; // Used only if program pipelines are not supported to + // hold static resources. }; } diff --git a/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp index b5889d94..d7ff2b32 100644 --- a/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp @@ -388,9 +388,10 @@ namespace Diligent GLProgramObj.dbgVerifyBindingCompleteness(pDynamicResources, m_pPipelineState); #endif - for(int BindDynamicResources = 0; BindDynamicResources < (pShaderResBindingGL ? 2 : 1); ++BindDynamicResources) + // When program pipelines are not supported, all resources are dynamic resources + for (int BindDynamicResources = (ProgramPipelineSupported ? 0 : 1); BindDynamicResources < (pShaderResBindingGL ? 2 : 1); ++BindDynamicResources) { - GLProgramResources &ProgResources = BindDynamicResources ? *pDynamicResources : GLProgramObj.GetConstantResources(); + GLProgramResources& ProgResources = BindDynamicResources ? *pDynamicResources : GLProgramObj.GetConstantResources(); #ifdef VERIFY_RESOURCE_BINDINGS ProgResources.dbgVerifyResourceBindings(); diff --git a/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp index 5a22c65b..3f0fed9b 100644 --- a/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp @@ -204,7 +204,7 @@ void PipelineStateGLImpl::CreateShaderResourceBinding(IShaderResourceBinding** p auto& SRBAllocator = pRenderDeviceGL->GetSRBAllocator(); auto pResBinding = NEW_RC_OBJ(SRBAllocator, "ShaderResourceBindingGLImpl instance", ShaderResourceBindingGLImpl)(this); if (InitStaticResources) - pResBinding->InitializeStaticResources(nullptr); + pResBinding->InitializeStaticResources(this); pResBinding->QueryInterface(IID_ShaderResourceBinding, reinterpret_cast<IObject**>(ppShaderResourceBinding)); } diff --git a/Graphics/GraphicsEngineOpenGL/src/ShaderGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/ShaderGLImpl.cpp index a1c1cd20..65a797c0 100644 --- a/Graphics/GraphicsEngineOpenGL/src/ShaderGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/ShaderGLImpl.cpp @@ -97,7 +97,7 @@ ShaderGLImpl::ShaderGLImpl(IReferenceCounters* pRefCounters, if (CreationAttribs.ppCompilerOutput != nullptr) { // infoLogLen accounts for null terminator - auto *pOutputDataBlob = MakeNewRCObj<DataBlobImpl>()(infoLogLen + FullSource.length() + 1); + auto* pOutputDataBlob = MakeNewRCObj<DataBlobImpl>()(infoLogLen + FullSource.length() + 1); char* DataPtr = reinterpret_cast<char*>(pOutputDataBlob->GetDataPtr()); if (infoLogLen > 0) memcpy(DataPtr, infoLog.data(), infoLogLen); @@ -182,40 +182,60 @@ void ShaderGLImpl::BindResources( IResourceMapping* pResourceMapping, Uint32 Fla } else { - static bool FirstTime = true; - if( FirstTime ) - { - LOG_WARNING_MESSAGE( "IShader::BindResources() effectively does nothing when separable programs are not supported by the device. Use IDeviceContext::BindShaderResources() instead." ); - FirstTime = false; - } + LOG_WARNING_MESSAGE_ONCE( "IShader::BindResources() effectively does nothing when separable programs are not supported by the device." ); } } -IShaderVariable* ShaderGLImpl::GetShaderVariable( const Char* Name ) +IShaderVariable* ShaderGLImpl::GetShaderVariable(const Char* Name) +{ + return GetShaderVariable(Name, true); +} + +IShaderVariable* ShaderGLImpl::GetShaderVariable(const Char* Name, bool CreatePlaceholder) { - DEV_CHECK_ERR(m_GlProgObj, "Shader variable queries are currently supported for separable programs only"); if( m_GlProgObj ) return m_GlProgObj.GetConstantResources().GetShaderVariable(Name); else - return nullptr; + { + for (auto& Res : m_StaticResources) + { + if( strcmp(Res->GetName(), Name) == 0) + return Res; + } + + if (CreatePlaceholder) + { + auto* pNewVar = MakeNewRCObj<StaticVarPlaceholder>()(Name, static_cast<Uint32>(m_StaticResources.size())); + m_StaticResources.emplace_back(pNewVar); + return pNewVar; + } + else + { + return nullptr; + } + } } Uint32 ShaderGLImpl::GetVariableCount() const { - DEV_CHECK_ERR(m_GlProgObj, "Shader variable queries are currently supported for separable programs only"); if( m_GlProgObj ) return m_GlProgObj.GetConstantResources().GetVariableCount(); else - return 0; + { + LOG_WARNING_MESSAGE("When separate shader objects are unavailable, GetVariableCount() returns the number of resources being set so far " + "rather than the total number of static shader resources."); + return static_cast<Uint32>(m_StaticResources.size()); + } } IShaderVariable* ShaderGLImpl::GetShaderVariable(Uint32 Index) { - DEV_CHECK_ERR(m_GlProgObj, "Shader variable queries are currently supported for separable programs only"); if( m_GlProgObj ) return m_GlProgObj.GetConstantResources().GetShaderVariable(Index); else - return 0; + { + return Index < m_StaticResources.size() ? m_StaticResources[Index].RawPtr() : nullptr; + } } } diff --git a/Graphics/GraphicsEngineOpenGL/src/ShaderResourceBindingGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/ShaderResourceBindingGLImpl.cpp index 05a79001..f58be350 100644 --- a/Graphics/GraphicsEngineOpenGL/src/ShaderResourceBindingGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/ShaderResourceBindingGLImpl.cpp @@ -127,7 +127,78 @@ GLProgramResources& ShaderResourceBindingGLImpl::GetProgramResources(SHADER_TYPE void ShaderResourceBindingGLImpl::InitializeStaticResources(const IPipelineState* pPipelineState) { + if (!IsUsingSeparatePrograms()) + { + class ResourceMappingProxy final : public IResourceMapping + { + public: + ResourceMappingProxy(const PipelineStateGLImpl& PSO) : + m_PSO(PSO) + { + } + virtual void QueryInterface (const INTERFACE_ID& IID, IObject** ppInterface)override final + { + UNEXPECTED("This method should never be called"); + } + virtual CounterValueType AddRef()override final + { + UNEXPECTED("This method should never be called"); + return 0; + } + virtual CounterValueType Release()override final + { + UNEXPECTED("This method should never be called"); + return 0; + } + virtual IReferenceCounters* GetReferenceCounters()const override final + { + UNEXPECTED("This method should never be called"); + return nullptr; + } + virtual void AddResource (const Char* Name, IDeviceObject* pObject, bool bIsUnique)override final + { + UNEXPECTED("This method should never be called"); + } + virtual void AddResourceArray (const Char* Name, Uint32 StartIndex, IDeviceObject* const* ppObjects, Uint32 NumElements, bool bIsUnique)override final + { + UNEXPECTED("This method should never be called"); + } + virtual void RemoveResourceByName (const Char* Name, Uint32 ArrayIndex = 0) + { + UNEXPECTED("This method should never be called"); + } + virtual void GetResource (const Char* Name, IDeviceObject** ppResource, Uint32 ArrayIndex = 0) + { + auto NumShaders = m_PSO.GetNumShaders(); + for (Uint32 s=0; s < NumShaders; ++s) + { + auto* pShader = m_PSO.GetShader<ShaderGLImpl>(s); + auto* pVar = pShader->GetShaderVariable(Name, false); + if (pVar != nullptr) + { + auto* pStaticVarPlaceholder = ValidatedCast<ShaderGLImpl::StaticVarPlaceholder>(pVar); + *ppResource = pStaticVarPlaceholder->Get(ArrayIndex); + if (*ppResource != nullptr) + (*ppResource)->AddRef(); + } + } + } + virtual size_t GetSize() + { + UNEXPECTED("This method should never be called"); + return 0; + } + private: + const PipelineStateGLImpl& m_PSO; + }; + if (pPipelineState != nullptr) + { + const auto* PSOGL = ValidatedCast<const PipelineStateGLImpl>(pPipelineState); + ResourceMappingProxy StaticResMapping(*PSOGL); + m_DynamicProgResources[0].BindResources(&StaticResMapping, 0); + } + } } } |
