summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngineOpenGL
diff options
context:
space:
mode:
authorEgor Yusov <egor.yusov@gmail.com>2019-02-22 04:30:57 +0000
committerEgor Yusov <egor.yusov@gmail.com>2019-02-22 04:30:57 +0000
commitccbc4ecd6cb012de71cb4cafa04175d268aa64d3 (patch)
treeba1d7b1dc485aac0ceee1951c6481f5b3065c4f6 /Graphics/GraphicsEngineOpenGL
parentFixed SRBs with non-separable shaders in GL back-end (diff)
downloadDiligentCore-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')
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/ShaderGLImpl.h60
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp5
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp2
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/ShaderGLImpl.cpp48
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/ShaderResourceBindingGLImpl.cpp71
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);
+ }
+ }
}
}