diff options
| author | assiduous <assiduous@diligentgraphics.com> | 2021-03-06 05:25:09 +0000 |
|---|---|---|
| committer | assiduous <assiduous@diligentgraphics.com> | 2021-03-19 00:38:16 +0000 |
| commit | 335670925e06e08f2e31efc40b8cf2e5aba820c5 (patch) | |
| tree | 05784503faa83d5584212bed15608d496a962522 /Graphics/GraphicsEngineOpenGL | |
| parent | Some updates to DXBCUtils and DXCompiler (diff) | |
| download | DiligentCore-335670925e06e08f2e31efc40b8cf2e5aba820c5.tar.gz DiligentCore-335670925e06e08f2e31efc40b8cf2e5aba820c5.zip | |
OpenGL backend: updated resource binding procedure
Diffstat (limited to 'Graphics/GraphicsEngineOpenGL')
10 files changed, 242 insertions, 237 deletions
diff --git a/Graphics/GraphicsEngineOpenGL/include/BufferGLImpl.hpp b/Graphics/GraphicsEngineOpenGL/include/BufferGLImpl.hpp index 9fd8be2f..b4a27125 100644 --- a/Graphics/GraphicsEngineOpenGL/include/BufferGLImpl.hpp +++ b/Graphics/GraphicsEngineOpenGL/include/BufferGLImpl.hpp @@ -72,7 +72,7 @@ public: void MapRange(GLContextState& CtxState, MAP_TYPE MapType, Uint32 MapFlags, Uint32 Offset, Uint32 Length, PVoid& pMappedData); void Unmap(GLContextState& CtxState); - void BufferMemoryBarrier(MEMORY_BARRIER RequiredBarriers, class GLContextState& GLContextState); + __forceinline void BufferMemoryBarrier(MEMORY_BARRIER RequiredBarriers, GLContextState& GLContextState); const GLObjectWrappers::GLBufferObj& GetGLHandle() { return m_GlBuffer; } @@ -96,4 +96,19 @@ private: const GLenum m_GLUsageHint; }; +void BufferGLImpl::BufferMemoryBarrier(MEMORY_BARRIER RequiredBarriers, GLContextState& GLContextState) +{ +#if GL_ARB_shader_image_load_store +# ifdef DILIGENT_DEBUG + { + constexpr auto BufferBarriers = MEMORY_BARRIER_ALL_BUFFER_BARRIERS; + VERIFY((RequiredBarriers & BufferBarriers) != 0, "At least one buffer memory barrier flag should be set"); + VERIFY((RequiredBarriers & ~BufferBarriers) == 0, "Inappropriate buffer memory barrier flag"); + } +# endif + + GLContextState.EnsureMemoryBarrier(RequiredBarriers, this); +#endif +} + } // namespace Diligent diff --git a/Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.hpp b/Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.hpp index 9926204f..79ea1926 100644 --- a/Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.hpp +++ b/Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.hpp @@ -283,7 +283,6 @@ private: __forceinline void PostDraw(); using TBindings = PipelineResourceSignatureGLImpl::TBindings; - void BindProgramResources(MEMORY_BARRIER& NewMemoryBarriers, const ShaderResourceBindingGLImpl* pShaderResBindingGL, TBindings& Bindings); void BindProgramResources(); #ifdef DILIGENT_DEVELOPMENT @@ -307,8 +306,8 @@ private: #ifdef DILIGENT_DEVELOPMENT bool CommittedResourcesValidated = false; - // Binding offsets that was used at last BindProgramResources() call. - std::array<TBindings, MAX_RESOURCE_SIGNATURES> BoundResOffsets = {}; + // Binding offsets that was used in the last BindProgramResources() call. + std::array<TBindings, MAX_RESOURCE_SIGNATURES> BaseBindings = {}; #endif SRBState() diff --git a/Graphics/GraphicsEngineOpenGL/include/PipelineResourceSignatureGLImpl.hpp b/Graphics/GraphicsEngineOpenGL/include/PipelineResourceSignatureGLImpl.hpp index a1a0de52..3c2ad8ee 100644 --- a/Graphics/GraphicsEngineOpenGL/include/PipelineResourceSignatureGLImpl.hpp +++ b/Graphics/GraphicsEngineOpenGL/include/PipelineResourceSignatureGLImpl.hpp @@ -129,7 +129,7 @@ public: SHADER_TYPE Stages, const TBindings& Bindings) const; - __forceinline void AddBindings(TBindings& Bindings) const + __forceinline void ShiftBindings(TBindings& Bindings) const { for (Uint32 i = 0; i < Bindings.size(); ++i) { diff --git a/Graphics/GraphicsEngineOpenGL/include/ShaderResourceCacheGL.hpp b/Graphics/GraphicsEngineOpenGL/include/ShaderResourceCacheGL.hpp index 35e340cc..38b7e6ec 100644 --- a/Graphics/GraphicsEngineOpenGL/include/ShaderResourceCacheGL.hpp +++ b/Graphics/GraphicsEngineOpenGL/include/ShaderResourceCacheGL.hpp @@ -27,6 +27,9 @@ #pragma once +#include <array> +#include <vector> + #include "BufferGLImpl.hpp" #include "TextureBaseGL.hpp" #include "SamplerGLImpl.hpp" @@ -253,6 +256,11 @@ public: bool StaticResourcesInitialized() const { return m_bStaticResourcesInitialized; } #endif + void BindResources(GLContextState& GLState, + const std::array<Uint32, 4>& BaseBindings, + std::vector<TextureBaseGL*>& WritableTextures, + std::vector<BufferGLImpl*>& WritableBuffers) const; + private: CachedUB& GetUB(Uint32 CacheOffset) { diff --git a/Graphics/GraphicsEngineOpenGL/include/TextureBaseGL.hpp b/Graphics/GraphicsEngineOpenGL/include/TextureBaseGL.hpp index 2d4101ea..8a6faebb 100644 --- a/Graphics/GraphicsEngineOpenGL/include/TextureBaseGL.hpp +++ b/Graphics/GraphicsEngineOpenGL/include/TextureBaseGL.hpp @@ -35,6 +35,7 @@ #include "TextureViewGLImpl.hpp" #include "AsyncWritableResource.hpp" #include "RenderDeviceGLImpl.hpp" +#include "GLContextState.hpp" namespace Diligent { @@ -82,7 +83,7 @@ public: GLenum GetGLTexFormat() const { return m_GLTexFormat; } - void TextureMemoryBarrier(MEMORY_BARRIER RequiredBarriers, class GLContextState& GLContextState); + __forceinline void TextureMemoryBarrier(MEMORY_BARRIER RequiredBarriers, class GLContextState& GLContextState); virtual void AttachToFramebuffer(const struct TextureViewDesc& ViewDesc, GLenum AttachmentPoint) = 0; @@ -133,4 +134,19 @@ protected: //Uint32 m_uiMapTarget; }; +void TextureBaseGL::TextureMemoryBarrier(MEMORY_BARRIER RequiredBarriers, GLContextState& GLContextState) +{ +#if GL_ARB_shader_image_load_store +# ifdef DILIGENT_DEBUG + { + constexpr Uint32 TextureBarriers = MEMORY_BARRIER_ALL_TEXTURE_BARRIERS; + VERIFY((RequiredBarriers & TextureBarriers) != 0, "At least one texture memory barrier flag should be set"); + VERIFY((RequiredBarriers & ~TextureBarriers) == 0, "Inappropriate texture memory barrier flag"); + } +# endif + + GLContextState.EnsureMemoryBarrier(RequiredBarriers, this); +#endif +} + } // namespace Diligent diff --git a/Graphics/GraphicsEngineOpenGL/src/BufferGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/BufferGLImpl.cpp index 2ef67a48..e7d45caf 100644 --- a/Graphics/GraphicsEngineOpenGL/src/BufferGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/BufferGLImpl.cpp @@ -346,21 +346,6 @@ void BufferGLImpl::Unmap(GLContextState& CtxState) (void)Result; } -void BufferGLImpl::BufferMemoryBarrier(MEMORY_BARRIER RequiredBarriers, GLContextState& GLContextState) -{ -#if GL_ARB_shader_image_load_store -# ifdef DILIGENT_DEBUG - { - constexpr auto BufferBarriers = MEMORY_BARRIER_ALL_BUFFER_BARRIERS; - VERIFY((RequiredBarriers & BufferBarriers) != 0, "At least one buffer memory barrier flag should be set"); - VERIFY((RequiredBarriers & ~BufferBarriers) == 0, "Inappropriate buffer memory barrier flag"); - } -# endif - - GLContextState.EnsureMemoryBarrier(RequiredBarriers, this); -#endif -} - void BufferGLImpl::CreateViewInternal(const BufferViewDesc& OrigViewDesc, IBufferView** ppView, bool bIsDefaultView) { VERIFY(ppView != nullptr, "Buffer view pointer address is null"); diff --git a/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp index 7c843321..36b6df70 100644 --- a/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp @@ -126,9 +126,7 @@ void DeviceContextGLImpl::SetPipelineState(IPipelineState* pPipelineState) m_ContextState.EnableDepthTest(DepthStencilDesc.DepthEnable); m_ContextState.EnableDepthWrites(DepthStencilDesc.DepthWriteEnable); m_ContextState.SetDepthFunc(DepthStencilDesc.DepthFunc); - m_ContextState.EnableStencilTest(DepthStencilDesc.StencilEnable); - m_ContextState.SetStencilWriteMask(DepthStencilDesc.StencilWriteMask); { @@ -687,7 +685,7 @@ void DeviceContextGLImpl::DvpValidateCommittedShaderResources() if (m_BindInfo.CommittedResourcesValidated) return; - m_pPipelineState->DvpVerifySRBResources(m_BindInfo.SRBs.data(), m_BindInfo.BoundResOffsets.data(), static_cast<Uint32>(m_BindInfo.SRBs.size())); + m_pPipelineState->DvpVerifySRBResources(m_BindInfo.SRBs.data(), m_BindInfo.BaseBindings.data(), static_cast<Uint32>(m_BindInfo.SRBs.size())); m_BindInfo.CommittedResourcesValidated = true; } #endif @@ -700,219 +698,38 @@ void DeviceContextGLImpl::BindProgramResources() if ((m_BindInfo.StaleSRBMask & m_BindInfo.ActiveSRBMask) == 0) return; + VERIFY_EXPR(m_BoundWritableTextures.empty()); + VERIFY_EXPR(m_BoundWritableBuffers.empty()); + m_CommitedResourcesTentativeBarriers = MEMORY_BARRIER_NONE; TBindings Bindings = {}; auto ActiveSRBMask = Uint32{m_BindInfo.ActiveSRBMask}; while (ActiveSRBMask != 0) { - Uint32 sign = PlatformMisc::GetLSB(ActiveSRBMask); - Uint32 SigBit = (1u << sign); + Uint32 sign = PlatformMisc::GetLSB(ActiveSRBMask); VERIFY_EXPR(sign < m_pPipelineState->GetResourceSignatureCount()); - ActiveSRBMask &= ~SigBit; + Uint32 SignBit = (1u << sign); + ActiveSRBMask &= ~SignBit; const auto* pSRB = m_BindInfo.SRBs[sign]; - VERIFY_EXPR(pSRB); + DEV_CHECK_ERR(pSRB != nullptr, "No SRB is bound for index ", sign); - if (m_BindInfo.StaleSRBMask & SigBit) + if (m_BindInfo.StaleSRBMask & SignBit) { - BindProgramResources(m_CommitedResourcesTentativeBarriers, pSRB, Bindings); + auto& ResoureCache = pSRB->GetResourceCache(); + ResoureCache.BindResources(GetContextState(), Bindings, m_BoundWritableTextures, m_BoundWritableBuffers); #ifdef DILIGENT_DEVELOPMENT - m_BindInfo.BoundResOffsets[sign] = Bindings; + m_BindInfo.BaseBindings[sign] = Bindings; #endif } - pSRB->GetSignature()->AddBindings(Bindings); + pSRB->GetSignature()->ShiftBindings(Bindings); } m_BindInfo.StaleSRBMask &= ~m_BindInfo.ActiveSRBMask; -} - -void DeviceContextGLImpl::BindProgramResources(MEMORY_BARRIER& NewMemoryBarriers, const ShaderResourceBindingGLImpl* pShaderResBindingGL, TBindings& Bindings) -{ - const auto SRBIndex = pShaderResBindingGL->GetBindingIndex(); - const auto& ResourceCache = pShaderResBindingGL->GetResourceCache(); - - - VERIFY_EXPR(m_BoundWritableTextures.empty()); - VERIFY_EXPR(m_BoundWritableBuffers.empty()); - - for (Uint32 ub = 0, binding = Bindings[BINDING_RANGE_UNIFORM_BUFFER]; ub < ResourceCache.GetUBCount(); ++ub, ++binding) - { - const auto& UB = ResourceCache.GetConstUB(ub); - if (!UB.pBuffer) - continue; - - auto* pBufferGL = UB.pBuffer.RawPtr<BufferGLImpl>(); - pBufferGL->BufferMemoryBarrier( - MEMORY_BARRIER_UNIFORM_BUFFER, // Shader uniforms sourced from buffer objects after the barrier - // will reflect data written by shaders prior to the barrier - m_ContextState); - - m_ContextState.BindUniformBuffer(binding, pBufferGL->m_GlBuffer); - //glBindBufferRange(GL_UNIFORM_BUFFER, it->Index, pBufferGL->m_GlBuffer, 0, pBufferGL->GetDesc().uiSizeInBytes); - } - - for (Uint32 s = 0, binding = Bindings[BINDING_RANGE_TEXTURE]; s < ResourceCache.GetTextureCount(); ++s, ++binding) - { - const auto& Sam = ResourceCache.GetConstTexture(s); - if (!Sam.pView) - continue; - - // We must check 'pTexture' first as 'pBuffer' is in union with 'pSampler' - if (Sam.pTexture != nullptr) - { - auto* pTexViewGL = Sam.pView.RawPtr<TextureViewGLImpl>(); - auto* pTextureGL = ValidatedCast<TextureBaseGL>(Sam.pTexture); - VERIFY_EXPR(pTextureGL == pTexViewGL->GetTexture()); - m_ContextState.BindTexture(binding, pTexViewGL->GetBindTarget(), pTexViewGL->GetHandle()); - - pTextureGL->TextureMemoryBarrier( - MEMORY_BARRIER_TEXTURE_FETCH, // Texture fetches from shaders, including fetches from buffer object - // memory via buffer textures, after the barrier will reflect data - // written by shaders prior to the barrier - m_ContextState); - - if (Sam.pSampler) - { - m_ContextState.BindSampler(binding, Sam.pSampler->GetHandle()); - } - else - { - m_ContextState.BindSampler(binding, GLObjectWrappers::GLSamplerObj(false)); - } - } - else if (Sam.pBuffer != nullptr) - { - auto* pBufViewGL = Sam.pView.RawPtr<BufferViewGLImpl>(); - auto* pBufferGL = ValidatedCast<BufferGLImpl>(Sam.pBuffer); - VERIFY_EXPR(pBufferGL == pBufViewGL->GetBuffer()); - - m_ContextState.BindTexture(binding, GL_TEXTURE_BUFFER, pBufViewGL->GetTexBufferHandle()); - m_ContextState.BindSampler(binding, GLObjectWrappers::GLSamplerObj(false)); // Use default texture sampling parameters - - pBufferGL->BufferMemoryBarrier( - MEMORY_BARRIER_TEXEL_BUFFER, // Texture fetches from shaders, including fetches from buffer object - // memory via buffer textures, after the barrier will reflect data - // written by shaders prior to the barrier - m_ContextState); - } - } - -#if GL_ARB_shader_image_load_store - for (Uint32 img = 0, binding = Bindings[BINDING_RANGE_IMAGE]; img < ResourceCache.GetImageCount(); ++img, ++binding) - { - const auto& Img = ResourceCache.GetConstImage(img); - if (!Img.pView) - continue; - - // We must check 'pTexture' first as 'pBuffer' is in union with 'pSampler' - if (Img.pTexture != nullptr) - { - auto* pTexViewGL = Img.pView.RawPtr<TextureViewGLImpl>(); - auto* pTextureGL = ValidatedCast<TextureBaseGL>(Img.pTexture); - VERIFY_EXPR(pTextureGL == pTexViewGL->GetTexture()); - - const auto& ViewDesc = pTexViewGL->GetDesc(); - VERIFY(ViewDesc.ViewType == TEXTURE_VIEW_UNORDERED_ACCESS, "Unexpected buffer view type"); - - if (ViewDesc.AccessFlags & UAV_ACCESS_FLAG_WRITE) - { - pTextureGL->TextureMemoryBarrier( - MEMORY_BARRIER_STORAGE_IMAGE, // Memory accesses using shader image load, store, and atomic built-in - // functions issued after the barrier will reflect data written by shaders - // prior to the barrier. Additionally, image stores and atomics issued after - // the barrier will not execute until all memory accesses (e.g., loads, - // stores, texture fetches, vertex fetches) initiated prior to the barrier - // complete. - m_ContextState); - // We cannot set pending memory barriers here, because - // if some texture is bound twice, the logic will fail - m_BoundWritableTextures.push_back(pTextureGL); - } - -# ifdef DILIGENT_DEBUG - // Check that the texure being bound has immutable storage - { - m_ContextState.BindTexture(-1, pTexViewGL->GetBindTarget(), pTexViewGL->GetHandle()); - GLint IsImmutable = 0; - glGetTexParameteriv(pTexViewGL->GetBindTarget(), GL_TEXTURE_IMMUTABLE_FORMAT, &IsImmutable); - DEV_CHECK_GL_ERROR("glGetTexParameteriv() failed"); - VERIFY(IsImmutable, "Only immutable textures can be bound to pipeline using glBindImageTexture()"); - m_ContextState.BindTexture(-1, pTexViewGL->GetBindTarget(), GLObjectWrappers::GLTextureObj::Null()); - } -# endif - auto GlTexFormat = TexFormatToGLInternalTexFormat(ViewDesc.Format); - // Note that if a format qulifier is specified in the shader, the format - // must match it - - GLboolean Layered = ViewDesc.NumArraySlices > 1 && ViewDesc.FirstArraySlice == 0; - // If "layered" is TRUE, the entire Mip level is bound. Layer parameter is ignored in this - // case. If "layered" is FALSE, only the single layer identified by "layer" will - // be bound. When "layered" is FALSE, the single bound layer is treated as a 2D texture. - GLint Layer = ViewDesc.FirstArraySlice; - - auto GLAccess = AccessFlags2GLAccess(ViewDesc.AccessFlags); - // WARNING: Texture being bound to the image unit must be complete - // That means that if an integer texture is being bound, its - // GL_TEXTURE_MIN_FILTER and GL_TEXTURE_MAG_FILTER must be NEAREST, - // otherwise it will be incomplete - m_ContextState.BindImage(binding, pTexViewGL, ViewDesc.MostDetailedMip, Layered, Layer, GLAccess, GlTexFormat); - // Do not use binding points from reflection as they may not be initialized - } - else if (Img.pBuffer != nullptr) - { - auto* pBuffViewGL = Img.pView.RawPtr<BufferViewGLImpl>(); - auto* pBufferGL = ValidatedCast<BufferGLImpl>(Img.pBuffer); - VERIFY_EXPR(pBufferGL == pBuffViewGL->GetBuffer()); - - const auto& ViewDesc = pBuffViewGL->GetDesc(); - VERIFY(ViewDesc.ViewType == BUFFER_VIEW_UNORDERED_ACCESS, "Unexpected buffer view type"); - - pBufferGL->BufferMemoryBarrier( - MEMORY_BARRIER_IMAGE_BUFFER, // Memory accesses using shader image load, store, and atomic built-in - // functions issued after the barrier will reflect data written by shaders - // prior to the barrier. Additionally, image stores and atomics issued after - // the barrier will not execute until all memory accesses (e.g., loads, - // stores, texture fetches, vertex fetches) initiated prior to the barrier - // complete. - m_ContextState); - - m_BoundWritableBuffers.push_back(pBufferGL); - - auto GlFormat = TypeToGLTexFormat(ViewDesc.Format.ValueType, ViewDesc.Format.NumComponents, ViewDesc.Format.IsNormalized); - m_ContextState.BindImage(binding, pBuffViewGL, GL_READ_WRITE, GlFormat); - } - } -#endif - - -#if GL_ARB_shader_storage_buffer_object - for (Uint32 ssbo = 0, binding = Bindings[BINDING_RANGE_STORAGE_BUFFER]; ssbo < ResourceCache.GetSSBOCount(); ++ssbo, ++binding) - { - const auto& SSBO = ResourceCache.GetConstSSBO(ssbo); - if (!SSBO.pBufferView) - return; - - auto* pBufferViewGL = SSBO.pBufferView.RawPtr<BufferViewGLImpl>(); - const auto& ViewDesc = pBufferViewGL->GetDesc(); - VERIFY(ViewDesc.ViewType == BUFFER_VIEW_UNORDERED_ACCESS || ViewDesc.ViewType == BUFFER_VIEW_SHADER_RESOURCE, "Unexpected buffer view type"); - - auto* pBufferGL = pBufferViewGL->GetBuffer<BufferGLImpl>(); - pBufferGL->BufferMemoryBarrier( - MEMORY_BARRIER_STORAGE_BUFFER, // Accesses to shader storage blocks after the barrier - // will reflect writes prior to the barrier - m_ContextState); - - m_ContextState.BindStorageBlock(binding, pBufferGL->m_GlBuffer, ViewDesc.ByteOffset, ViewDesc.ByteWidth); - - if (ViewDesc.ViewType == BUFFER_VIEW_UNORDERED_ACCESS) - m_BoundWritableBuffers.push_back(pBufferGL); - } -#endif - #if GL_ARB_shader_image_load_store // Go through the list of textures bound as AUVs and set the required memory barriers @@ -920,7 +737,7 @@ void DeviceContextGLImpl::BindProgramResources(MEMORY_BARRIER& NewMemoryBarriers { constexpr MEMORY_BARRIER TextureMemBarriers = MEMORY_BARRIER_ALL_TEXTURE_BARRIERS; - NewMemoryBarriers |= TextureMemBarriers; + m_CommitedResourcesTentativeBarriers |= TextureMemBarriers; // Set new required barriers for the time when texture is used next time pWritableTex->SetPendingMemoryBarriers(TextureMemBarriers); @@ -931,7 +748,7 @@ void DeviceContextGLImpl::BindProgramResources(MEMORY_BARRIER& NewMemoryBarriers { constexpr MEMORY_BARRIER BufferMemoryBarriers = MEMORY_BARRIER_ALL_BUFFER_BARRIERS; - NewMemoryBarriers |= BufferMemoryBarriers; + m_CommitedResourcesTentativeBarriers |= BufferMemoryBarriers; // Set new required barriers for the time when buffer is used next time pWritableBuff->SetPendingMemoryBarriers(BufferMemoryBarriers); } diff --git a/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp index 4841ebb4..b787fd38 100644 --- a/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp @@ -215,7 +215,7 @@ void PipelineStateGLImpl::InitResourceLayouts(const PipelineStateCreateInfo& Cre { pSignature->ApplyBindings(m_GLPrograms[0], CtxState, ActiveStages, Bindings); } - pSignature->AddBindings(Bindings); + pSignature->ShiftBindings(Bindings); } const auto& Limits = GetDevice()->GetDeviceLimits(); @@ -590,7 +590,7 @@ void PipelineStateGLImpl::DvpVerifySRBResources(ShaderResourceBindingGLImpl* pSR DEV_CHECK_ERR(Bindings == BoundResOffsets[sign], "Bound resources has incorrect base binding indices, this may indicate a bug in resource signature compatibility comparison."); - pSignature->AddBindings(Bindings); + pSignature->ShiftBindings(Bindings); } diff --git a/Graphics/GraphicsEngineOpenGL/src/ShaderResourceCacheGL.cpp b/Graphics/GraphicsEngineOpenGL/src/ShaderResourceCacheGL.cpp index fe1a2078..94f2ebfc 100644 --- a/Graphics/GraphicsEngineOpenGL/src/ShaderResourceCacheGL.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/ShaderResourceCacheGL.cpp @@ -28,6 +28,7 @@ #include "pch.h" #include "ShaderResourceCacheGL.hpp" #include "PipelineResourceSignatureGLImpl.hpp" +#include "GLTypeConversions.hpp" namespace Diligent { @@ -116,4 +117,184 @@ ShaderResourceCacheGL::~ShaderResourceCacheGL() } } +void ShaderResourceCacheGL::BindResources(GLContextState& GLState, + const std::array<Uint32, 4>& BaseBindings, + std::vector<TextureBaseGL*>& WritableTextures, + std::vector<BufferGLImpl*>& WritableBuffers) const +{ + for (Uint32 ub = 0, binding = BaseBindings[BINDING_RANGE_UNIFORM_BUFFER]; ub < GetUBCount(); ++ub, ++binding) + { + const auto& UB = GetConstUB(ub); + if (!UB.pBuffer) + continue; + + auto* pBufferGL = UB.pBuffer.RawPtr<BufferGLImpl>(); + pBufferGL->BufferMemoryBarrier( + MEMORY_BARRIER_UNIFORM_BUFFER, // Shader uniforms sourced from buffer objects after the barrier + // will reflect data written by shaders prior to the barrier + GLState); + + GLState.BindUniformBuffer(binding, pBufferGL->GetGLHandle()); + //glBindBufferRange(GL_UNIFORM_BUFFER, it->Index, pBufferGL->m_GlBuffer, 0, pBufferGL->GetDesc().uiSizeInBytes); + } + + for (Uint32 s = 0, binding = BaseBindings[BINDING_RANGE_TEXTURE]; s < GetTextureCount(); ++s, ++binding) + { + const auto& Tex = GetConstTexture(s); + if (!Tex.pView) + continue; + + // We must check 'pTexture' first as 'pBuffer' is in union with 'pSampler' + if (Tex.pTexture != nullptr) + { + auto* pTexViewGL = Tex.pView.RawPtr<TextureViewGLImpl>(); + auto* pTextureGL = ValidatedCast<TextureBaseGL>(Tex.pTexture); + VERIFY_EXPR(pTextureGL == pTexViewGL->GetTexture()); + GLState.BindTexture(binding, pTexViewGL->GetBindTarget(), pTexViewGL->GetHandle()); + + pTextureGL->TextureMemoryBarrier( + MEMORY_BARRIER_TEXTURE_FETCH, // Texture fetches from shaders, including fetches from buffer object + // memory via buffer textures, after the barrier will reflect data + // written by shaders prior to the barrier + GLState); + + if (Tex.pSampler) + { + GLState.BindSampler(binding, Tex.pSampler->GetHandle()); + } + else + { + GLState.BindSampler(binding, GLObjectWrappers::GLSamplerObj{false}); + } + } + else if (Tex.pBuffer != nullptr) + { + auto* pBufViewGL = Tex.pView.RawPtr<BufferViewGLImpl>(); + auto* pBufferGL = ValidatedCast<BufferGLImpl>(Tex.pBuffer); + VERIFY_EXPR(pBufferGL == pBufViewGL->GetBuffer()); + + GLState.BindTexture(binding, GL_TEXTURE_BUFFER, pBufViewGL->GetTexBufferHandle()); + GLState.BindSampler(binding, GLObjectWrappers::GLSamplerObj{false}); // Use default texture sampling parameters + + pBufferGL->BufferMemoryBarrier( + MEMORY_BARRIER_TEXEL_BUFFER, // Texture fetches from shaders, including fetches from buffer object + // memory via buffer textures, after the barrier will reflect data + // written by shaders prior to the barrier + GLState); + } + } + +#if GL_ARB_shader_image_load_store + for (Uint32 img = 0, binding = BaseBindings[BINDING_RANGE_IMAGE]; img < GetImageCount(); ++img, ++binding) + { + const auto& Img = GetConstImage(img); + if (!Img.pView) + continue; + + // We must check 'pTexture' first as 'pBuffer' is in union with 'pSampler' + if (Img.pTexture != nullptr) + { + auto* pTexViewGL = Img.pView.RawPtr<TextureViewGLImpl>(); + auto* pTextureGL = ValidatedCast<TextureBaseGL>(Img.pTexture); + VERIFY_EXPR(pTextureGL == pTexViewGL->GetTexture()); + + const auto& ViewDesc = pTexViewGL->GetDesc(); + VERIFY(ViewDesc.ViewType == TEXTURE_VIEW_UNORDERED_ACCESS, "Unexpected buffer view type"); + + if (ViewDesc.AccessFlags & UAV_ACCESS_FLAG_WRITE) + { + pTextureGL->TextureMemoryBarrier( + MEMORY_BARRIER_STORAGE_IMAGE, // Memory accesses using shader image load, store, and atomic built-in + // functions issued after the barrier will reflect data written by shaders + // prior to the barrier. Additionally, image stores and atomics issued after + // the barrier will not execute until all memory accesses (e.g., loads, + // stores, texture fetches, vertex fetches) initiated prior to the barrier + // complete. + GLState); + // We cannot set pending memory barriers here, because + // if some texture is bound twice, the logic will fail + WritableTextures.push_back(pTextureGL); + } + +# ifdef DILIGENT_DEBUG + // Check that the texure being bound has immutable storage + { + GLState.BindTexture(-1, pTexViewGL->GetBindTarget(), pTexViewGL->GetHandle()); + GLint IsImmutable = 0; + glGetTexParameteriv(pTexViewGL->GetBindTarget(), GL_TEXTURE_IMMUTABLE_FORMAT, &IsImmutable); + DEV_CHECK_GL_ERROR("glGetTexParameteriv() failed"); + VERIFY(IsImmutable, "Only immutable textures can be bound to pipeline using glBindImageTexture()"); + GLState.BindTexture(-1, pTexViewGL->GetBindTarget(), GLObjectWrappers::GLTextureObj::Null()); + } +# endif + auto GlTexFormat = TexFormatToGLInternalTexFormat(ViewDesc.Format); + // Note that if a format qulifier is specified in the shader, the format + // must match it + + GLboolean Layered = ViewDesc.NumArraySlices > 1 && ViewDesc.FirstArraySlice == 0; + // If "layered" is TRUE, the entire Mip level is bound. Layer parameter is ignored in this + // case. If "layered" is FALSE, only the single layer identified by "layer" will + // be bound. When "layered" is FALSE, the single bound layer is treated as a 2D texture. + GLint Layer = ViewDesc.FirstArraySlice; + + auto GLAccess = AccessFlags2GLAccess(ViewDesc.AccessFlags); + // WARNING: Texture being bound to the image unit must be complete + // That means that if an integer texture is being bound, its + // GL_TEXTURE_MIN_FILTER and GL_TEXTURE_MAG_FILTER must be NEAREST, + // otherwise it will be incomplete + GLState.BindImage(binding, pTexViewGL, ViewDesc.MostDetailedMip, Layered, Layer, GLAccess, GlTexFormat); + // Do not use binding points from reflection as they may not be initialized + } + else if (Img.pBuffer != nullptr) + { + auto* pBuffViewGL = Img.pView.RawPtr<BufferViewGLImpl>(); + auto* pBufferGL = ValidatedCast<BufferGLImpl>(Img.pBuffer); + VERIFY_EXPR(pBufferGL == pBuffViewGL->GetBuffer()); + + const auto& ViewDesc = pBuffViewGL->GetDesc(); + VERIFY(ViewDesc.ViewType == BUFFER_VIEW_UNORDERED_ACCESS, "Unexpected buffer view type"); + + pBufferGL->BufferMemoryBarrier( + MEMORY_BARRIER_IMAGE_BUFFER, // Memory accesses using shader image load, store, and atomic built-in + // functions issued after the barrier will reflect data written by shaders + // prior to the barrier. Additionally, image stores and atomics issued after + // the barrier will not execute until all memory accesses (e.g., loads, + // stores, texture fetches, vertex fetches) initiated prior to the barrier + // complete. + GLState); + + WritableBuffers.push_back(pBufferGL); + + auto GlFormat = TypeToGLTexFormat(ViewDesc.Format.ValueType, ViewDesc.Format.NumComponents, ViewDesc.Format.IsNormalized); + GLState.BindImage(binding, pBuffViewGL, GL_READ_WRITE, GlFormat); + } + } +#endif + + +#if GL_ARB_shader_storage_buffer_object + for (Uint32 ssbo = 0, binding = BaseBindings[BINDING_RANGE_STORAGE_BUFFER]; ssbo < GetSSBOCount(); ++ssbo, ++binding) + { + const auto& SSBO = GetConstSSBO(ssbo); + if (!SSBO.pBufferView) + return; + + auto* const pBufferViewGL = SSBO.pBufferView.RawPtr<BufferViewGLImpl>(); + const auto& ViewDesc = pBufferViewGL->GetDesc(); + VERIFY(ViewDesc.ViewType == BUFFER_VIEW_UNORDERED_ACCESS || ViewDesc.ViewType == BUFFER_VIEW_SHADER_RESOURCE, "Unexpected buffer view type"); + + auto* pBufferGL = pBufferViewGL->GetBuffer<BufferGLImpl>(); + pBufferGL->BufferMemoryBarrier( + MEMORY_BARRIER_STORAGE_BUFFER, // Accesses to shader storage blocks after the barrier + // will reflect writes prior to the barrier + GLState); + + GLState.BindStorageBlock(binding, pBufferGL->GetGLHandle(), ViewDesc.ByteOffset, ViewDesc.ByteWidth); + + if (ViewDesc.ViewType == BUFFER_VIEW_UNORDERED_ACCESS) + WritableBuffers.push_back(pBufferGL); + } +#endif +} + } // namespace Diligent diff --git a/Graphics/GraphicsEngineOpenGL/src/TextureBaseGL.cpp b/Graphics/GraphicsEngineOpenGL/src/TextureBaseGL.cpp index 67a69a61..d38a468d 100644 --- a/Graphics/GraphicsEngineOpenGL/src/TextureBaseGL.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/TextureBaseGL.cpp @@ -646,22 +646,6 @@ void TextureBaseGL::CopyData(DeviceContextGLImpl* pDeviceCtxGL, } } - -void TextureBaseGL::TextureMemoryBarrier(MEMORY_BARRIER RequiredBarriers, GLContextState& GLContextState) -{ -#if GL_ARB_shader_image_load_store -# ifdef DILIGENT_DEBUG - { - constexpr Uint32 TextureBarriers = MEMORY_BARRIER_ALL_TEXTURE_BARRIERS; - VERIFY((RequiredBarriers & TextureBarriers) != 0, "At least one texture memory barrier flag should be set"); - VERIFY((RequiredBarriers & ~TextureBarriers) == 0, "Inappropriate texture memory barrier flag"); - } -# endif - - GLContextState.EnsureMemoryBarrier(RequiredBarriers, this); -#endif -} - void TextureBaseGL::SetDefaultGLParameters() { #ifdef DILIGENT_DEBUG |
