diff options
| author | Egor Yusov <egor.yusov@gmail.com> | 2019-02-21 17:12:03 +0000 |
|---|---|---|
| committer | Egor Yusov <egor.yusov@gmail.com> | 2019-02-21 17:12:03 +0000 |
| commit | 01b7a5ff496b155f9b0fa610262cd888a30293cc (patch) | |
| tree | 24bcd70401768606e460adf9f739c1868a1a6240 /Graphics/GraphicsEngineOpenGL | |
| parent | Not accessing program pipeline when separate shaders are not supported in GL ... (diff) | |
| download | DiligentCore-01b7a5ff496b155f9b0fa610262cd888a30293cc.tar.gz DiligentCore-01b7a5ff496b155f9b0fa610262cd888a30293cc.zip | |
Fixed SRBs with non-separable shaders in GL back-end
Diffstat (limited to 'Graphics/GraphicsEngineOpenGL')
9 files changed, 264 insertions, 196 deletions
diff --git a/Graphics/GraphicsEngineOpenGL/include/GLProgram.h b/Graphics/GraphicsEngineOpenGL/include/GLProgram.h index 759a072f..296ff4fd 100644 --- a/Graphics/GraphicsEngineOpenGL/include/GLProgram.h +++ b/Graphics/GraphicsEngineOpenGL/include/GLProgram.h @@ -30,34 +30,35 @@ namespace Diligent class GLProgram : public GLObjectWrappers::GLProgramObj { public: - GLProgram( bool CreateObject ); - GLProgram( GLProgram&& Program ); + GLProgram(bool CreateObject); + GLProgram(GLProgram&& Program); - void InitResources(RenderDeviceGLImpl* pDeviceGLImpl, - SHADER_VARIABLE_TYPE DefaultVariableType, - const ShaderVariableDesc *VariableDesc, - Uint32 NumVars, - const StaticSamplerDesc *StaticSamplers, - Uint32 NumStaticSamplers, - IObject &Owner); + GLProgram (const GLProgram&) = delete; + GLProgram& operator = (const GLProgram&) = delete; + GLProgram& operator = ( GLProgram&&) = delete; - void BindConstantResources(IResourceMapping *pResourceMapping, Uint32 Flags); + void InitResources(RenderDeviceGLImpl* pDeviceGLImpl, + SHADER_VARIABLE_TYPE DefaultVariableType, + const ShaderVariableDesc* VariableDesc, + Uint32 NumVars, + const StaticSamplerDesc* StaticSamplers, + Uint32 NumStaticSamplers, + IObject& Owner); - const GLProgramResources& GetAllResources()const{return m_AllResources;} + void BindConstantResources(IResourceMapping* pResourceMapping, Uint32 Flags); + + const GLProgramResources& GetAllResources() const{return m_AllResources;} GLProgramResources& GetConstantResources() {return m_ConstantResources;} const GLProgramResources& GetConstantResources()const{return m_ConstantResources;} #ifdef VERIFY_RESOURCE_BINDINGS template<typename TResArrayType> - void dbgVerifyBindingCompletenessHelper(TResArrayType &ResArr, GLProgramResources *pDynamicResources); - void dbgVerifyBindingCompleteness(GLProgramResources *pDynamicResources, class PipelineStateGLImpl *pPSO); + void dbgVerifyBindingCompletenessHelper(TResArrayType& ResArr, GLProgramResources* pDynamicResources); + void dbgVerifyBindingCompleteness(GLProgramResources* pDynamicResources, class PipelineStateGLImpl* pPSO); #endif private: - GLProgram( const GLProgram& Program ); - const GLProgram& operator = (const GLProgram& Program); - GLProgramResources m_AllResources; GLProgramResources m_ConstantResources; // When adding new member DO NOT FORGET TO UPDATE GLProgram( GLProgram&& Program )!!! diff --git a/Graphics/GraphicsEngineOpenGL/include/PipelineStateGLImpl.h b/Graphics/GraphicsEngineOpenGL/include/PipelineStateGLImpl.h index ac7ff869..3e1bbbb1 100644 --- a/Graphics/GraphicsEngineOpenGL/include/PipelineStateGLImpl.h +++ b/Graphics/GraphicsEngineOpenGL/include/PipelineStateGLImpl.h @@ -42,20 +42,23 @@ class PipelineStateGLImpl final : public PipelineStateBase<IPipelineStateGL, Ren public: using TPipelineStateBase = PipelineStateBase<IPipelineStateGL, RenderDeviceGLImpl>; - PipelineStateGLImpl(IReferenceCounters *pRefCounters, RenderDeviceGLImpl *pDeviceGL, const PipelineStateDesc& PipelineDesc, bool IsDeviceInternal = false); + PipelineStateGLImpl(IReferenceCounters* pRefCounters, + RenderDeviceGLImpl* pDeviceGL, + const PipelineStateDesc& PipelineDesc, + bool IsDeviceInternal = false); ~PipelineStateGLImpl(); /// Queries the specific interface, see IObject::QueryInterface() for details - virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface )override; + virtual void QueryInterface( const INTERFACE_ID& IID, IObject** ppInterface )override; - virtual void BindShaderResources( IResourceMapping *pResourceMapping, Uint32 Flags )override final; + virtual void BindShaderResources( IResourceMapping* pResourceMapping, Uint32 Flags )override final; - virtual void CreateShaderResourceBinding( IShaderResourceBinding **ppShaderResourceBinding, bool InitStaticResources )override final; + virtual void CreateShaderResourceBinding( IShaderResourceBinding** ppShaderResourceBinding, bool InitStaticResources )override final; - virtual bool IsCompatibleWith(const IPipelineState *pPSO)const override final; + virtual bool IsCompatibleWith(const IPipelineState* pPSO)const override final; - GLProgram &GetGLProgram(){return m_GLProgram;} - GLObjectWrappers::GLPipelineObj &GetGLProgramPipeline(GLContext::NativeGLContextType Context); + GLProgram& GetGLProgram(){return m_GLProgram;} + GLObjectWrappers::GLPipelineObj& GetGLProgramPipeline(GLContext::NativeGLContextType Context); private: void LinkGLProgram(bool bIsProgramPipelineSupported); diff --git a/Graphics/GraphicsEngineOpenGL/include/ShaderResourceBindingGLImpl.h b/Graphics/GraphicsEngineOpenGL/include/ShaderResourceBindingGLImpl.h index 6fc2fd27..ac76461b 100644 --- a/Graphics/GraphicsEngineOpenGL/include/ShaderResourceBindingGLImpl.h +++ b/Graphics/GraphicsEngineOpenGL/include/ShaderResourceBindingGLImpl.h @@ -36,18 +36,20 @@ namespace Diligent { class FixedBlockMemoryAllocator; +class PipelineStateGLImpl; + /// Implementation of the Diligent::IShaderResourceBindingGL interface class ShaderResourceBindingGLImpl final : public ShaderResourceBindingBase<IShaderResourceBindingGL> { public: using TBase = ShaderResourceBindingBase<IShaderResourceBindingGL>; - ShaderResourceBindingGLImpl(IReferenceCounters *pRefCounters, class PipelineStateGLImpl *pPSO); + ShaderResourceBindingGLImpl(IReferenceCounters* pRefCounters, PipelineStateGLImpl* pPSO); ~ShaderResourceBindingGLImpl(); - virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface )override final; + virtual void QueryInterface( const INTERFACE_ID& IID, IObject** ppInterface )override final; - virtual void BindResources(Uint32 ShaderFlags, IResourceMapping *pResMapping, Uint32 Flags)override final; + virtual void BindResources(Uint32 ShaderFlags, IResourceMapping* pResMapping, Uint32 Flags)override final; virtual IShaderVariable* GetVariable(SHADER_TYPE ShaderType, const char *Name)override final; @@ -57,11 +59,12 @@ public: virtual void InitializeStaticResources(const IPipelineState* pPipelineState)override final; - GLProgramResources &GetProgramResources(SHADER_TYPE ShaderType, PipelineStateGLImpl *pdbgPSO); + GLProgramResources& GetProgramResources(SHADER_TYPE ShaderType, PipelineStateGLImpl* pdbgPSO); private: + bool IsUsingSeparatePrograms()const; + GLProgramResources m_DynamicProgResources[6]; - RefCntWeakPtr<PipelineStateGLImpl> m_wpPSO; }; } diff --git a/Graphics/GraphicsEngineOpenGL/include/TexRegionRender.h b/Graphics/GraphicsEngineOpenGL/include/TexRegionRender.h index 531e32e9..91c31b08 100644 --- a/Graphics/GraphicsEngineOpenGL/include/TexRegionRender.h +++ b/Graphics/GraphicsEngineOpenGL/include/TexRegionRender.h @@ -30,31 +30,33 @@ namespace Diligent class TexRegionRender { public: - TexRegionRender(class RenderDeviceGLImpl *pDeviceGL); - void SetStates(class DeviceContextGLImpl *pCtxGL); - void RestoreStates(class DeviceContextGLImpl *pCtxGL); - void Render(class DeviceContextGLImpl *pCtxGL, - ITextureView *pSrcSRV, - RESOURCE_DIMENSION TexType, - TEXTURE_FORMAT TexFormat, - Int32 DstToSrcXOffset, - Int32 DstToSrcYOffset, - Int32 SrcZ, - Int32 SrcMipLevel); + TexRegionRender(class RenderDeviceGLImpl* pDeviceGL); + void SetStates(class DeviceContextGLImpl* pCtxGL); + void RestoreStates(class DeviceContextGLImpl* pCtxGL); + void Render(class DeviceContextGLImpl* pCtxGL, + ITextureView* pSrcSRV, + RESOURCE_DIMENSION TexType, + TEXTURE_FORMAT TexFormat, + Int32 DstToSrcXOffset, + Int32 DstToSrcYOffset, + Int32 SrcZ, + Int32 SrcMipLevel); private: - Diligent::RefCntAutoPtr<IShader> m_pVertexShader; - Diligent::RefCntAutoPtr<IShader> m_pFragmentShaders[RESOURCE_DIM_NUM_DIMENSIONS * 3]; - Diligent::RefCntAutoPtr<IBuffer> m_pConstantBuffer; - Diligent::RefCntAutoPtr<IPipelineState> m_pPSO[RESOURCE_DIM_NUM_DIMENSIONS * 3]; + RefCntAutoPtr<IShader> m_pVertexShader; + RefCntAutoPtr<IShader> m_pFragmentShaders[RESOURCE_DIM_NUM_DIMENSIONS * 3]; + RefCntAutoPtr<IBuffer> m_pConstantBuffer; + RefCntAutoPtr<IPipelineState> m_pPSO[RESOURCE_DIM_NUM_DIMENSIONS * 3]; + RefCntAutoPtr<IShaderResourceBinding> m_pSRB; + IShaderVariable* m_pSrcTexVar = nullptr; - Diligent::RefCntAutoPtr<IPipelineState> m_pOrigPSO; - Uint32 m_OrigStencilRef = 0; - float m_OrigBlendFactors[4] = {}; - Uint32 m_NumRenderTargets = 0; - ITextureView *m_pOrigRTVs[MaxRenderTargets] = {}; - Diligent::RefCntAutoPtr<ITextureView> m_pOrigDSV; - std::vector<Viewport> m_OrigViewports; + RefCntAutoPtr<IPipelineState> m_pOrigPSO; + Uint32 m_OrigStencilRef = 0; + float m_OrigBlendFactors[4] = {}; + Uint32 m_NumRenderTargets = 0; + ITextureView* m_pOrigRTVs[MaxRenderTargets] = {}; + RefCntAutoPtr<ITextureView> m_pOrigDSV; + std::vector<Viewport> m_OrigViewports; }; } diff --git a/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp index 42db91b6..b5889d94 100644 --- a/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp @@ -63,7 +63,7 @@ namespace Diligent IMPLEMENT_QUERY_INTERFACE( DeviceContextGLImpl, IID_DeviceContextGL, TDeviceContextBase ) - void DeviceContextGLImpl::SetPipelineState(IPipelineState *pPipelineState) + void DeviceContextGLImpl::SetPipelineState(IPipelineState* pPipelineState) { auto* pPipelineStateGLImpl = ValidatedCast<PipelineStateGLImpl>(pPipelineState); TDeviceContextBase::SetPipelineState(pPipelineStateGLImpl, 0 /*Dummy*/); @@ -425,9 +425,9 @@ namespace Diligent #define LOG_MISSING_BINDING(VarType, Res, ArrInd)\ do{ \ if(Res->pResources.size()>1) \ - LOG_ERROR_MESSAGE( "No ", VarType, " is bound to \"", Res->Name, '[', ArrInd, "]\" variable in shader \"", pShaderGL->GetDesc().Name, "\"" );\ + LOG_ERROR_MESSAGE( "No ", VarType, " is bound to '", Res->Name, '[', ArrInd, "]' variable in shader '", pShaderGL->GetDesc().Name, "'" );\ else \ - LOG_ERROR_MESSAGE( "No ", VarType, " is bound to \"", Res->Name, "\" variable in shader \"", pShaderGL->GetDesc().Name, "\"" );\ + LOG_ERROR_MESSAGE( "No ", VarType, " is bound to '", Res->Name, "' variable in shader '", pShaderGL->GetDesc().Name, "'" );\ }while(false) LOG_MISSING_BINDING("uniform buffer", it, ArrInd); diff --git a/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp index caaec37a..5a22c65b 100644 --- a/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp @@ -31,7 +31,10 @@ namespace Diligent { -PipelineStateGLImpl::PipelineStateGLImpl(IReferenceCounters *pRefCounters, class RenderDeviceGLImpl *pDeviceGL, const PipelineStateDesc& PipelineDesc, bool bIsDeviceInternal) : +PipelineStateGLImpl::PipelineStateGLImpl(IReferenceCounters* pRefCounters, + RenderDeviceGLImpl* pDeviceGL, + const PipelineStateDesc& PipelineDesc, + bool bIsDeviceInternal) : TPipelineStateBase(pRefCounters, pDeviceGL, PipelineDesc, bIsDeviceInternal), m_GLProgram(false) { @@ -45,14 +48,14 @@ PipelineStateGLImpl::PipelineStateGLImpl(IReferenceCounters *pRefCounters, class void PipelineStateGLImpl::LinkGLProgram(bool bIsProgramPipelineSupported) { - if( bIsProgramPipelineSupported ) + if (bIsProgramPipelineSupported) { // Program pipelines are not shared between GL contexts, so we cannot create // it now m_ShaderResourceLayoutHash = 0; for (Uint32 Shader = 0; Shader < m_NumShaders; ++Shader) { - auto *pShaderGL = GetShader<ShaderGLImpl>(Shader); + auto* pShaderGL = GetShader<ShaderGLImpl>(Shader); HashCombine(m_ShaderResourceLayoutHash, pShaderGL->m_GlProgObj.GetAllResources().GetHash()); } } @@ -60,71 +63,114 @@ void PipelineStateGLImpl::LinkGLProgram(bool bIsProgramPipelineSupported) { // Create new progam m_GLProgram.Create(); - for( Uint32 Shader = 0; Shader < m_NumShaders; ++Shader ) + for (Uint32 Shader = 0; Shader < m_NumShaders; ++Shader) { - auto *pCurrShader = GetShader<ShaderGLImpl>(Shader); - glAttachShader( m_GLProgram, pCurrShader->m_GLShaderObj ); - CHECK_GL_ERROR( "glAttachShader() failed" ); + auto* pCurrShader = GetShader<ShaderGLImpl>(Shader); + glAttachShader(m_GLProgram, pCurrShader->m_GLShaderObj); + CHECK_GL_ERROR("glAttachShader() failed"); } - glLinkProgram( m_GLProgram ); - CHECK_GL_ERROR( "glLinkProgram() failed" ); + glLinkProgram(m_GLProgram); + CHECK_GL_ERROR("glLinkProgram() failed"); int IsLinked = GL_FALSE; - glGetProgramiv( m_GLProgram, GL_LINK_STATUS, (int *)&IsLinked ); - CHECK_GL_ERROR( "glGetProgramiv() failed" ); - if( !IsLinked ) + glGetProgramiv(m_GLProgram, GL_LINK_STATUS, &IsLinked); + CHECK_GL_ERROR("glGetProgramiv() failed"); + if (!IsLinked) { int LengthWithNull = 0, Length = 0; // Notice that glGetProgramiv is used to get the length for a shader program, not glGetShaderiv. // The length of the info log includes a null terminator. - glGetProgramiv( m_GLProgram, GL_INFO_LOG_LENGTH, &LengthWithNull ); + glGetProgramiv(m_GLProgram, GL_INFO_LOG_LENGTH, &LengthWithNull); // The maxLength includes the NULL character - std::vector<char> shaderProgramInfoLog( LengthWithNull ); + std::vector<char> shaderProgramInfoLog(LengthWithNull); // Notice that glGetProgramInfoLog is used, not glGetShaderInfoLog. - glGetProgramInfoLog( m_GLProgram, LengthWithNull, &Length, &shaderProgramInfoLog[0] ); - VERIFY( Length == LengthWithNull-1, "Incorrect program info log len" ); - LOG_ERROR_MESSAGE( "Failed to link shader program:\n", &shaderProgramInfoLog[0], '\n'); - UNEXPECTED( "glLinkProgram failed" ); + glGetProgramInfoLog(m_GLProgram, LengthWithNull, &Length, shaderProgramInfoLog.data()); + VERIFY(Length == LengthWithNull-1, "Incorrect program info log len"); + LOG_ERROR_MESSAGE("Failed to link shader program:\n", shaderProgramInfoLog.data(), '\n'); + UNEXPECTED("glLinkProgram failed"); } // Detach shaders from the program object - for( Uint32 Shader = 0; Shader < m_NumShaders; ++Shader ) + for (Uint32 Shader = 0; Shader < m_NumShaders; ++Shader) { - auto *pCurrShader = GetShader<ShaderGLImpl>(Shader); - glDetachShader( m_GLProgram, pCurrShader->m_GLShaderObj ); - CHECK_GL_ERROR( "glDetachShader() failed" ); + auto* pCurrShader = GetShader<ShaderGLImpl>(Shader); + glDetachShader(m_GLProgram, pCurrShader->m_GLShaderObj); + CHECK_GL_ERROR("glDetachShader() failed"); } std::vector<ShaderVariableDesc> MergedVarTypesArray; std::vector<StaticSamplerDesc> MergedStSamArray; SHADER_VARIABLE_TYPE DefaultVarType = SHADER_VARIABLE_TYPE_STATIC; - for( Uint32 Shader = 0; Shader < m_NumShaders; ++Shader ) + for (Uint32 Shader = 0; Shader < m_NumShaders; ++Shader) { - auto *pCurrShader = GetShader<ShaderGLImpl>(Shader); + auto* pCurrShader = GetShader<ShaderGLImpl>(Shader); const auto& Desc = pCurrShader->GetDesc(); if (Shader == 0) { DefaultVarType = Desc.DefaultVariableType; - for (Uint32 v = 0; v < Desc.NumVariables; ++v) + } + else + { + if (DefaultVarType != Desc.DefaultVariableType) { - MergedVarTypesArray.push_back(Desc.VariableDesc[v]); + LOG_ERROR_MESSAGE("When separate shader programs are not available, all shaders linked into a program " + "must use the same default variable type."); } - for (Uint32 s = 0; s < Desc.NumStaticSamplers; ++s) + } + + for (Uint32 v = 0; v < Desc.NumVariables; ++v) + { + const auto& NewVar = Desc.VariableDesc[v]; + bool VarExists = false; + for (const auto& Var : MergedVarTypesArray) { - MergedStSamArray.push_back(Desc.StaticSamplers[s]); + if (strcmp(Var.Name, NewVar.Name) == 0) + { + VarExists = true; + if (Var.Type != NewVar.Type) + { + LOG_ERROR_MESSAGE("The type of variable '", Var.Name, "' is not consistent between shader stages. " + "When separate shader programs are not available, all shaders must use the same " + "type for identically named shader variables."); + } + break; + } + } + + if (!VarExists) + { + MergedVarTypesArray.push_back(NewVar); } } - else + + for (Uint32 s = 0; s < Desc.NumStaticSamplers; ++s) { - if (DefaultVarType != Desc.DefaultVariableType) + const auto& NewSampler = Desc.StaticSamplers[s]; + bool SamplerExists = false; + for (const auto& Sampler : MergedStSamArray) + { + if (strcmp(Sampler.SamplerOrTextureName, NewSampler.SamplerOrTextureName) == 0) + { + SamplerExists = true; + if ( !(Sampler.Desc == NewSampler.Desc) ) + { + LOG_ERROR_MESSAGE("Static sampler defined for texture '", NewSampler.SamplerOrTextureName, "' is not consistent between shader stages. " + "When separate shader programs are not available, all shaders must use the same " + "static samplers for identically named shader variables."); + } + break; + } + } + + if (!SamplerExists) { - LOG_ERROR("Inconsistent default variable types for shaders in one program"); + MergedStSamArray.push_back(NewSampler); } } } - auto pDeviceGL = static_cast<RenderDeviceGLImpl*>( GetDevice() ); + auto pDeviceGL = GetDevice(); m_GLProgram.InitResources(pDeviceGL, DefaultVarType, MergedVarTypesArray.data(), static_cast<Uint32>(MergedVarTypesArray.size()), MergedStSamArray.data(), static_cast<Uint32>(MergedStSamArray.size()), *this); m_ShaderResourceLayoutHash = m_GLProgram.GetAllResources().GetHash(); @@ -134,49 +180,49 @@ void PipelineStateGLImpl::LinkGLProgram(bool bIsProgramPipelineSupported) PipelineStateGLImpl::~PipelineStateGLImpl() { - static_cast<RenderDeviceGLImpl*>( GetDevice() )->OnDestroyPSO(this); + GetDevice()->OnDestroyPSO(this); } IMPLEMENT_QUERY_INTERFACE( PipelineStateGLImpl, IID_PipelineStateGL, TPipelineStateBase ) -void PipelineStateGLImpl::BindShaderResources(IResourceMapping *pResourceMapping, Uint32 Flags) +void PipelineStateGLImpl::BindShaderResources(IResourceMapping* pResourceMapping, Uint32 Flags) { - if( GetDevice()->GetDeviceCaps().bSeparableProgramSupported ) + if (GetDevice()->GetDeviceCaps().bSeparableProgramSupported) { TPipelineStateBase::BindShaderResources(pResourceMapping, Flags); } else { - if( m_GLProgram ) - m_GLProgram.BindConstantResources( pResourceMapping, Flags ); + if (m_GLProgram) + m_GLProgram.BindConstantResources(pResourceMapping, Flags); } } -void PipelineStateGLImpl::CreateShaderResourceBinding(IShaderResourceBinding **ppShaderResourceBinding, bool InitStaticResources) +void PipelineStateGLImpl::CreateShaderResourceBinding(IShaderResourceBinding** ppShaderResourceBinding, bool InitStaticResources) { - auto *pRenderDeviceGL = ValidatedCast<RenderDeviceGLImpl>( GetDevice() ); - auto &SRBAllocator = pRenderDeviceGL->GetSRBAllocator(); - auto pResBinding = NEW_RC_OBJ( SRBAllocator, "ShaderResourceBindingGLImpl instance", ShaderResourceBindingGLImpl)(this); + auto* pRenderDeviceGL = GetDevice(); + auto& SRBAllocator = pRenderDeviceGL->GetSRBAllocator(); + auto pResBinding = NEW_RC_OBJ(SRBAllocator, "ShaderResourceBindingGLImpl instance", ShaderResourceBindingGLImpl)(this); if (InitStaticResources) pResBinding->InitializeStaticResources(nullptr); pResBinding->QueryInterface(IID_ShaderResourceBinding, reinterpret_cast<IObject**>(ppShaderResourceBinding)); } -bool PipelineStateGLImpl::IsCompatibleWith(const IPipelineState *pPSO)const +bool PipelineStateGLImpl::IsCompatibleWith(const IPipelineState* pPSO)const { VERIFY_EXPR(pPSO != nullptr); if (pPSO == this) return true; - const PipelineStateGLImpl *pPSOGL = ValidatedCast<const PipelineStateGLImpl>(pPSO); + const PipelineStateGLImpl* pPSOGL = ValidatedCast<const PipelineStateGLImpl>(pPSO); if (m_ShaderResourceLayoutHash != pPSOGL->m_ShaderResourceLayoutHash) return false; - return m_GLProgram.GetAllResources().IsCompatibleWith( pPSOGL->m_GLProgram.GetAllResources() ); + return m_GLProgram.GetAllResources().IsCompatibleWith(pPSOGL->m_GLProgram.GetAllResources()); } -GLObjectWrappers::GLPipelineObj &PipelineStateGLImpl::GetGLProgramPipeline(GLContext::NativeGLContextType Context) +GLObjectWrappers::GLPipelineObj& PipelineStateGLImpl::GetGLProgramPipeline(GLContext::NativeGLContextType Context) { ThreadingTools::LockHelper Lock(m_ProgPipelineLockFlag); auto it = m_GLProgPipelines.find(Context); @@ -185,11 +231,11 @@ GLObjectWrappers::GLPipelineObj &PipelineStateGLImpl::GetGLProgramPipeline(GLCon else { // Create new progam pipeline - it = m_GLProgPipelines.emplace( Context, true ).first; + it = m_GLProgPipelines.emplace(Context, true).first; GLuint Pipeline = it->second; for (Uint32 Shader = 0; Shader < m_NumShaders; ++Shader) { - auto *pCurrShader = GetShader<ShaderGLImpl>(Shader); + auto* pCurrShader = GetShader<ShaderGLImpl>(Shader); auto GLShaderBit = ShaderTypeToGLShaderBit(pCurrShader->GetDesc().ShaderType); // If the program has an active code for each stage mentioned in set flags, // then that code will be used by the pipeline. If program is 0, then the given diff --git a/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLImpl.cpp index c4d2cbb0..d7f79554 100644 --- a/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLImpl.cpp @@ -136,7 +136,7 @@ void RenderDeviceGLImpl :: CreateBufferFromGLHandle(Uint32 GLHandle, const Buffe ); } -void RenderDeviceGLImpl :: CreateShader(const ShaderCreationAttribs& ShaderCreationAttribs, IShader **ppShader, bool bIsDeviceInternal) +void RenderDeviceGLImpl :: CreateShader(const ShaderCreationAttribs& ShaderCreationAttribs, IShader** ppShader, bool bIsDeviceInternal) { CreateDeviceObject( "shader", ShaderCreationAttribs.Desc, ppShader, [&]() diff --git a/Graphics/GraphicsEngineOpenGL/src/ShaderResourceBindingGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/ShaderResourceBindingGLImpl.cpp index 236b90a6..05a79001 100644 --- a/Graphics/GraphicsEngineOpenGL/src/ShaderResourceBindingGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/ShaderResourceBindingGLImpl.cpp @@ -30,17 +30,12 @@ namespace Diligent { -ShaderResourceBindingGLImpl::ShaderResourceBindingGLImpl( IReferenceCounters *pRefCounters, PipelineStateGLImpl *pPSO) : - TBase( pRefCounters, pPSO ), - m_wpPSO(pPSO) +ShaderResourceBindingGLImpl::ShaderResourceBindingGLImpl(IReferenceCounters* pRefCounters, PipelineStateGLImpl* pPSO) : + TBase (pRefCounters, pPSO) { - SHADER_VARIABLE_TYPE VarTypes[] = {SHADER_VARIABLE_TYPE_MUTABLE, SHADER_VARIABLE_TYPE_DYNAMIC}; - if ( static_cast<GLuint>( pPSO->GetGLProgram() ) ) - { - m_DynamicProgResources[0].Clone(pPSO->GetGLProgram().GetAllResources(), VarTypes, _countof(VarTypes), *this); - } - else + if (IsUsingSeparatePrograms()) { + SHADER_VARIABLE_TYPE VarTypes[] = {SHADER_VARIABLE_TYPE_MUTABLE, SHADER_VARIABLE_TYPE_DYNAMIC}; #define INIT_SHADER(SN)\ if(auto p##SN = ValidatedCast<ShaderGLImpl>( pPSO->Get##SN() )) \ { \ @@ -56,60 +51,77 @@ ShaderResourceBindingGLImpl::ShaderResourceBindingGLImpl( IReferenceCounters *pR INIT_SHADER(CS) #undef INIT_SHADER } + else + { + // Clone all variable types + SHADER_VARIABLE_TYPE VarTypes[] = {SHADER_VARIABLE_TYPE_STATIC, SHADER_VARIABLE_TYPE_MUTABLE, SHADER_VARIABLE_TYPE_DYNAMIC}; + m_DynamicProgResources[0].Clone(pPSO->GetGLProgram().GetAllResources(), VarTypes, _countof(VarTypes), *this); + } } ShaderResourceBindingGLImpl::~ShaderResourceBindingGLImpl() { - } -IMPLEMENT_QUERY_INTERFACE( ShaderResourceBindingGLImpl, IID_ShaderResourceBindingGL, TBase ) +IMPLEMENT_QUERY_INTERFACE(ShaderResourceBindingGLImpl, IID_ShaderResourceBindingGL, TBase) -void ShaderResourceBindingGLImpl::BindResources(Uint32 ShaderFlags, IResourceMapping *pResMapping, Uint32 Flags) +bool ShaderResourceBindingGLImpl::IsUsingSeparatePrograms()const { - if(ShaderFlags & SHADER_TYPE_VERTEX) - m_DynamicProgResources[VSInd].BindResources(pResMapping, Flags); - if(ShaderFlags & SHADER_TYPE_PIXEL) - m_DynamicProgResources[PSInd].BindResources(pResMapping, Flags); - if(ShaderFlags & SHADER_TYPE_GEOMETRY) - m_DynamicProgResources[GSInd].BindResources(pResMapping, Flags); - if(ShaderFlags & SHADER_TYPE_HULL) - m_DynamicProgResources[HSInd].BindResources(pResMapping, Flags); - if(ShaderFlags & SHADER_TYPE_DOMAIN) - m_DynamicProgResources[DSInd].BindResources(pResMapping, Flags); - if(ShaderFlags & SHADER_TYPE_COMPUTE) - m_DynamicProgResources[CSInd].BindResources(pResMapping, Flags); + return GetPipelineState<PipelineStateGLImpl>()->GetGLProgram() == 0; +} + +void ShaderResourceBindingGLImpl::BindResources(Uint32 ShaderFlags, IResourceMapping* pResMapping, Uint32 Flags) +{ + if (IsUsingSeparatePrograms()) + { + if(ShaderFlags & SHADER_TYPE_VERTEX) + m_DynamicProgResources[VSInd].BindResources(pResMapping, Flags); + if(ShaderFlags & SHADER_TYPE_PIXEL) + m_DynamicProgResources[PSInd].BindResources(pResMapping, Flags); + if(ShaderFlags & SHADER_TYPE_GEOMETRY) + m_DynamicProgResources[GSInd].BindResources(pResMapping, Flags); + if(ShaderFlags & SHADER_TYPE_HULL) + m_DynamicProgResources[HSInd].BindResources(pResMapping, Flags); + if(ShaderFlags & SHADER_TYPE_DOMAIN) + m_DynamicProgResources[DSInd].BindResources(pResMapping, Flags); + if(ShaderFlags & SHADER_TYPE_COMPUTE) + m_DynamicProgResources[CSInd].BindResources(pResMapping, Flags); + } + else + { + // Using non-separable program + m_DynamicProgResources[0].BindResources(pResMapping, Flags); + } } -IShaderVariable *ShaderResourceBindingGLImpl::GetVariable(SHADER_TYPE ShaderType, const char *Name) +IShaderVariable* ShaderResourceBindingGLImpl::GetVariable(SHADER_TYPE ShaderType, const char* Name) { - auto ShaderInd = GetShaderTypeIndex(ShaderType); + auto ShaderInd = IsUsingSeparatePrograms() ? GetShaderTypeIndex(ShaderType) : 0; return m_DynamicProgResources[ShaderInd].GetShaderVariable(Name); } Uint32 ShaderResourceBindingGLImpl::GetVariableCount(SHADER_TYPE ShaderType) const { - auto ShaderInd = GetShaderTypeIndex(ShaderType); + auto ShaderInd = IsUsingSeparatePrograms() ? GetShaderTypeIndex(ShaderType) : 0; return m_DynamicProgResources[ShaderInd].GetVariableCount(); } IShaderVariable* ShaderResourceBindingGLImpl::GetVariable(SHADER_TYPE ShaderType, Uint32 Index) { - auto ShaderInd = GetShaderTypeIndex(ShaderType); + auto ShaderInd = IsUsingSeparatePrograms() ? GetShaderTypeIndex(ShaderType) : 0; return m_DynamicProgResources[ShaderInd].GetShaderVariable(Index); } static GLProgramResources NullProgramResources; -GLProgramResources &ShaderResourceBindingGLImpl::GetProgramResources(SHADER_TYPE ShaderType, PipelineStateGLImpl *pdbgPSO) +GLProgramResources& ShaderResourceBindingGLImpl::GetProgramResources(SHADER_TYPE ShaderType, PipelineStateGLImpl* pdbgPSO) { #ifdef _DEBUG - auto pPSO = m_wpPSO.Lock(); - if (pdbgPSO->IsIncompatibleWith(pPSO)) + if (pdbgPSO->IsIncompatibleWith(GetPipelineState())) { LOG_ERROR("Shader resource binding is incompatible with the currently bound pipeline state."); } #endif - auto ShaderInd = GetShaderTypeIndex(ShaderType); + auto ShaderInd = IsUsingSeparatePrograms() ? GetShaderTypeIndex(ShaderType) : 0; return m_DynamicProgResources[ShaderInd]; } diff --git a/Graphics/GraphicsEngineOpenGL/src/TexRegionRender.cpp b/Graphics/GraphicsEngineOpenGL/src/TexRegionRender.cpp index f0793679..312889e7 100644 --- a/Graphics/GraphicsEngineOpenGL/src/TexRegionRender.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/TexRegionRender.cpp @@ -59,12 +59,12 @@ namespace Diligent TexRegionRender::TexRegionRender( class RenderDeviceGLImpl *pDeviceGL ) { ShaderCreationAttribs ShaderAttrs; - ShaderAttrs.Desc.Name = "TexRegionRender : Vertex shader"; - ShaderAttrs.Desc.ShaderType = SHADER_TYPE_VERTEX; - ShaderAttrs.Source = VertexShaderSource; - pDeviceGL->CreateShader( ShaderAttrs, &m_pVertexShader, - true // We must indicate the shader is internal device object - ); + ShaderAttrs.Desc.Name = "TexRegionRender : Vertex shader"; + ShaderAttrs.Desc.ShaderType = SHADER_TYPE_VERTEX; + ShaderAttrs.Desc.DefaultVariableType = SHADER_VARIABLE_TYPE_DYNAMIC; + ShaderAttrs.Source = VertexShaderSource; + constexpr bool IsInternalDeviceObject = true; + pDeviceGL->CreateShader(ShaderAttrs, &m_pVertexShader, IsInternalDeviceObject); static const char* SamplerType[RESOURCE_DIM_NUM_DIMENSIONS] = {}; SamplerType[RESOURCE_DIM_TEX_1D] = "sampler1D"; @@ -87,64 +87,65 @@ namespace Diligent //CoordDim[RESOURCE_DIM_TEX_CUBE_ARRAY] = "ivec2(gl_FragCoord.xy)"; BufferDesc CBDesc; - CBDesc.Name = "TexRegionRender: FS constants CB"; - CBDesc.uiSizeInBytes = sizeof(Int32)*4; - CBDesc.Usage = USAGE_DYNAMIC; - CBDesc.BindFlags = BIND_UNIFORM_BUFFER; + CBDesc.Name = "TexRegionRender: FS constants CB"; + CBDesc.uiSizeInBytes = sizeof(Int32)*4; + CBDesc.Usage = USAGE_DYNAMIC; + CBDesc.BindFlags = BIND_UNIFORM_BUFFER; CBDesc.CPUAccessFlags = CPU_ACCESS_WRITE; - pDeviceGL->CreateBuffer( CBDesc, nullptr, &m_pConstantBuffer, - true // We must indicate the buffer is internal device object - ); + pDeviceGL->CreateBuffer(CBDesc, nullptr, &m_pConstantBuffer, IsInternalDeviceObject); PipelineStateDesc PSODesc; - auto &GraphicsPipeline = PSODesc.GraphicsPipeline; + auto& GraphicsPipeline = PSODesc.GraphicsPipeline; GraphicsPipeline.RasterizerDesc.CullMode = CULL_MODE_NONE; GraphicsPipeline.RasterizerDesc.FillMode = FILL_MODE_SOLID; - GraphicsPipeline.DepthStencilDesc.DepthEnable = false; - GraphicsPipeline.DepthStencilDesc.DepthWriteEnable = false; - GraphicsPipeline.pVS = m_pVertexShader; + GraphicsPipeline.DepthStencilDesc.DepthEnable = False; + GraphicsPipeline.DepthStencilDesc.DepthWriteEnable = False; + GraphicsPipeline.pVS = m_pVertexShader; GraphicsPipeline.PrimitiveTopology = PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; static const char* CmpTypePrefix[3] = { "", "i", "u" }; - for( Int32 Dim = RESOURCE_DIM_TEX_2D; Dim <= RESOURCE_DIM_TEX_3D; ++Dim ) + for (Int32 Dim = RESOURCE_DIM_TEX_2D; Dim <= RESOURCE_DIM_TEX_3D; ++Dim) { - const auto *SamplerDim = SamplerType[Dim]; - const auto *SrcLocation = SrcLocations[Dim]; + const auto* SamplerDim = SamplerType[Dim]; + const auto* SrcLocation = SrcLocations[Dim]; for( Int32 Fmt = 0; Fmt < 3; ++Fmt ) { const auto *Prefix = CmpTypePrefix[Fmt]; String Name = "TexRegionRender : Pixel shader "; - Name.append( Prefix ); - Name.append( SamplerDim ); - ShaderAttrs.Desc.Name = Name.c_str(); + Name.append(Prefix); + Name.append(SamplerDim); + ShaderAttrs.Desc.Name = Name.c_str(); ShaderAttrs.Desc.ShaderType = SHADER_TYPE_PIXEL; - + ShaderVariableDesc Vars[] = + { + {"cbConstants", SHADER_VARIABLE_TYPE_MUTABLE} + }; + ShaderAttrs.Desc.NumVariables = _countof(Vars); + ShaderAttrs.Desc.VariableDesc = Vars; + std::stringstream SourceSS; SourceSS << "uniform " << Prefix << SamplerDim << " gSourceTex;\n" - << "layout( location = 0 ) out " << Prefix << "vec4 Out;\n" - << "uniform cbConstants\n" - << "{\n" - << " ivec4 Constants;\n" - << "};\n" - << "void main()\n" - << "{\n" - << " Out = texelFetch( gSourceTex, " << SrcLocation << ", Constants.w );\n" - << "}\n"; + "layout(location = 0) out " << Prefix << "vec4 Out;\n" + "uniform cbConstants\n" + "{\n" + " ivec4 Constants;\n" + "};\n" + "void main()\n" + "{\n" + " Out = texelFetch( gSourceTex, " << SrcLocation << ", Constants.w );\n" + "}\n"; auto Source = SourceSS.str(); ShaderAttrs.Source = Source.c_str(); auto &FragmetShader = m_pFragmentShaders[Dim*3 + Fmt]; - pDeviceGL->CreateShader( ShaderAttrs, &FragmetShader, - true // We must indicate the shader is an internal device object - ); + pDeviceGL->CreateShader(ShaderAttrs, &FragmetShader, IsInternalDeviceObject); GraphicsPipeline.pPS = FragmetShader; - pDeviceGL->CreatePipelineState( PSODesc, &m_pPSO[Dim*3 + Fmt], - true // We must indicate the PSO is an internal device object - ); - - FragmetShader->GetShaderVariable( "cbConstants" )->Set( m_pConstantBuffer ); + pDeviceGL->CreatePipelineState(PSODesc, &m_pPSO[Dim*3 + Fmt], IsInternalDeviceObject); } + m_pPSO[RESOURCE_DIM_TEX_2D*3]->CreateShaderResourceBinding(&m_pSRB); + m_pSRB->GetVariable(SHADER_TYPE_PIXEL, "cbConstants")->Set(m_pConstantBuffer); + m_pSrcTexVar = m_pSRB->GetVariable(SHADER_TYPE_PIXEL, "gSourceTex"); } } @@ -163,7 +164,7 @@ namespace Diligent void TexRegionRender::RestoreStates( DeviceContextGLImpl *pCtxGL ) { pCtxGL->SetRenderTargets( m_NumRenderTargets, m_pOrigRTVs, m_pOrigDSV, RESOURCE_STATE_TRANSITION_MODE_TRANSITION ); - for( Uint32 rt = 0; rt < _countof( m_pOrigRTVs ); ++rt ) + for (Uint32 rt = 0; rt < _countof( m_pOrigRTVs ); ++rt) { if( m_pOrigRTVs[rt] ) m_pOrigRTVs[rt]->Release(); @@ -171,55 +172,55 @@ namespace Diligent } m_pOrigDSV.Release(); - pCtxGL->SetViewports( (Uint32)m_OrigViewports.size(), m_OrigViewports.data(), 0, 0 ); + pCtxGL->SetViewports((Uint32)m_OrigViewports.size(), m_OrigViewports.data(), 0, 0); - if(m_pOrigPSO) + if (m_pOrigPSO) pCtxGL->SetPipelineState( m_pOrigPSO ); m_pOrigPSO.Release(); pCtxGL->SetStencilRef(m_OrigStencilRef); pCtxGL->SetBlendFactors(m_OrigBlendFactors); } - void TexRegionRender::Render( DeviceContextGLImpl *pCtxGL, - ITextureView *pSrcSRV, - RESOURCE_DIMENSION TexType, - TEXTURE_FORMAT TexFormat, - Int32 DstToSrcXOffset, - Int32 DstToSrcYOffset, - Int32 SrcZ, - Int32 SrcMipLevel) + void TexRegionRender::Render( DeviceContextGLImpl* pCtxGL, + ITextureView* pSrcSRV, + RESOURCE_DIMENSION TexType, + TEXTURE_FORMAT TexFormat, + Int32 DstToSrcXOffset, + Int32 DstToSrcYOffset, + Int32 SrcZ, + Int32 SrcMipLevel) { { - MapHelper< int > pConstant( pCtxGL, m_pConstantBuffer, MAP_WRITE, MAP_FLAG_DISCARD ); + MapHelper<int> pConstant(pCtxGL, m_pConstantBuffer, MAP_WRITE, MAP_FLAG_DISCARD); pConstant[0] = DstToSrcXOffset; pConstant[1] = DstToSrcYOffset; pConstant[2] = SrcZ; pConstant[3] = SrcMipLevel; } - const auto &TexFmtAttribs = GetTextureFormatAttribs(TexFormat); + const auto& TexFmtAttribs = GetTextureFormatAttribs(TexFormat); Uint32 FSInd = TexType * 3; - if( TexFmtAttribs.ComponentType == COMPONENT_TYPE_SINT ) + if (TexFmtAttribs.ComponentType == COMPONENT_TYPE_SINT) FSInd += 1; - else if( TexFmtAttribs.ComponentType == COMPONENT_TYPE_UINT ) + else if (TexFmtAttribs.ComponentType == COMPONENT_TYPE_UINT) FSInd += 2; - if( TexFmtAttribs.ComponentType == COMPONENT_TYPE_SNORM ) + if (TexFmtAttribs.ComponentType == COMPONENT_TYPE_SNORM) { LOG_WARNING_MESSAGE("CopyData() is performed by rendering to texture.\n" "There might be an issue in OpenGL driver on NVidia hardware: when rendering to SNORM textures, all negative values are clamped to zero."); } + DEV_CHECK_ERR(m_pPSO[FSInd], "TexRegionRender does not support this combination of texture dimension/format"); + pCtxGL->SetPipelineState(m_pPSO[FSInd]); - // Technically resetting static varaibles is not allowed, but in GL this is OK - auto SrcTexVar = m_pFragmentShaders[FSInd]->GetShaderVariable( "gSourceTex" ); - SrcTexVar->Set( pSrcSRV ); - pCtxGL->CommitShaderResources(nullptr, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); + m_pSrcTexVar->Set( pSrcSRV ); + pCtxGL->CommitShaderResources(m_pSRB, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); DrawAttribs DrawAttrs; DrawAttrs.NumVertices = 4; - pCtxGL->Draw( DrawAttrs ); + pCtxGL->Draw(DrawAttrs); - SrcTexVar->Set( nullptr ); + m_pSrcTexVar->Set(nullptr); } } |
