git.s-ol.nu ~forks/DiligentCore / bef8cae
OpenGL: added resource signature azhirnov authored 6 months ago assiduous committed 6 months ago
44 changed file(s) with 4839 addition(s) and 3604 deletion(s). Raw diff Collapse all Expand all
1212 set(CMAKE_XCODE_SCHEME_MALLOC_SCRIBBLE YES)
1313 # Place guard pages on each side of large (4096 bytes or more) buffers
1414 set(CMAKE_XCODE_SCHEME_MALLOC_GUARD_EDGES YES)
15
16
17 ### !!!TEMPORARY!!!
18 set(DILIGENT_NO_OPENGL ON CACHE BOOL "Temporary disable OpenGL backend")
19
2015
2116 if(NOT CMAKE_BUILD_TYPE)
2217 set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE)
154154 return PlatformMisc::CountOneBits(Uint32{m_ShaderStages});
155155 }
156156
157 SHADER_TYPE GetActiveShaderStages() const
158 {
159 return m_ShaderStages;
160 }
161
162157 // Returns the number of shader stages that have static resources.
163158 Uint32 GetNumStaticResStages() const
164159 {
657657 const struct IPipelineState* pPSO) CONST PURE;
658658
659659
660 /// Returns the number of pipeline resource signature used to created this pipeline.
660 /// Returns the number of pipeline resource signatures used by this pipeline.
661
662 /// \remarks After the PSO is created, pipeline resource signatures are arranged by their binding indices.
663 /// The value returned by this function is given by the maximum signature binding index plus one,
664 /// and thus may not be equal to PipelineStateCreateInfo::ResourceSignaturesCount.
661665 VIRTUAL Uint32 METHOD(GetResourceSignatureCount)(THIS) CONST PURE;
662666
663667 /// Returns pipeline resource signature at the give index.
120120
121121 void Destruct();
122122
123 #ifdef DILIGENT_DEVELOPMENT
123124 struct ResourceAttribution
124125 {
125126 static constexpr Uint32 InvalidSignatureIndex = ~0u;
153154
154155 bool IsImmutableSampler() const
155156 {
156 return *this && ImmutableSamplerIndex != InvalidSamplerIndex;
157 return operator bool() && ImmutableSamplerIndex != InvalidSamplerIndex;
157158 }
158159 };
159160 ResourceAttribution GetResourceAttribution(const char* Name, SHADER_TYPE Stage) const;
160161
161 #ifdef DILIGENT_DEVELOPMENT
162162 void DvpValidateShaderResources(const ShaderD3D12Impl* pShader, const LocalRootSignatureD3D12* pLocalRootSig);
163163 #endif
164164
668668 }
669669
670670
671 #ifdef DILIGENT_DEVELOPMENT
671672 PipelineStateD3D12Impl::ResourceAttribution PipelineStateD3D12Impl::GetResourceAttribution(const char* Name, SHADER_TYPE Stage) const
672673 {
673674 const auto SignCount = GetResourceSignatureCount();
690691 return ResourceAttribution{};
691692 }
692693
693 #ifdef DILIGENT_DEVELOPMENT
694694 void PipelineStateD3D12Impl::DvpValidateShaderResources(const ShaderD3D12Impl* pShader, const LocalRootSignatureD3D12* pLocalRootSig)
695695 {
696696 const auto& pShaderResources = pShader->GetShaderResources();
1212 include/GLContext.hpp
1313 include/GLContextState.hpp
1414 include/GLObjectWrapper.hpp
15 include/GLProgramResourceCache.hpp
16 include/GLPipelineResourceLayout.hpp
17 include/GLProgramResources.hpp
15 include/ShaderResourceCacheGL.hpp
16 include/ShaderVariableGL.hpp
17 include/ShaderResourcesGL.hpp
1818 include/GLTypeConversions.hpp
1919 include/pch.h
2020 include/PipelineStateGLImpl.hpp
21 include/PipelineResourceSignatureGLImpl.hpp
2122 include/QueryGLImpl.hpp
2223 include/RenderDeviceGLImpl.hpp
2324 include/RenderPassGLImpl.hpp
6667 src/FramebufferGLImpl.cpp
6768 src/GLContextState.cpp
6869 src/GLObjectWrapper.cpp
69 src/GLProgramResourceCache.cpp
70 src/GLPipelineResourceLayout.cpp
71 src/GLProgramResources.cpp
70 src/ShaderResourceCacheGL.cpp
71 src/ShaderVariableGL.cpp
72 src/ShaderResourcesGL.cpp
7273 src/GLTypeConversions.cpp
7374 src/PipelineStateGLImpl.cpp
75 src/PipelineResourceSignatureGLImpl.cpp
7476 src/QueryGLImpl.cpp
7577 src/RenderDeviceGLImpl.cpp
7678 src/RenderPassGLImpl.cpp
2929 namespace Diligent
3030 {
3131
32 enum MEMORY_BARRIER : Uint32
33 {
34 MEMORY_BARRIER_NONE = 0,
35 MEMORY_BARRIER_ALL = GL_ALL_BARRIER_BITS,
36
37 // Buffer barriers.
38 // Driver does not handle buffer write access in shader and write/read access to a persistent mapped memory.
39 MEMORY_BARRIER_VERTEX_BUFFER = GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT, // map/storage -> vertex
40 MEMORY_BARRIER_INDEX_BUFFER = GL_ELEMENT_ARRAY_BARRIER_BIT, // map/storage -> index
41 MEMORY_BARRIER_UNIFORM_BUFFER = GL_UNIFORM_BARRIER_BIT, // map/storage -> uniform
42 MEMORY_BARRIER_BUFFER_UPDATE = GL_BUFFER_UPDATE_BARRIER_BIT, // map/storage -> host read/write/map or copy
43 MEMORY_BARRIER_CLIENT_MAPPED_BUFFER = GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT, // map/storage -> map, only for persistent mapped memory without GL_MAP_COHERENT_BIT
44 MEMORY_BARRIER_STORAGE_BUFFER = GL_SHADER_STORAGE_BARRIER_BIT, // map/storage -> storage
45 MEMORY_BARRIER_INDIRECT_BUFFER = GL_COMMAND_BARRIER_BIT, // map/storage -> indirect
46 MEMORY_BARRIER_TEXEL_BUFFER = GL_TEXTURE_FETCH_BARRIER_BIT, // map/storage -> texel buffer fetch
47 MEMORY_BARRIER_PIXEL_BUFFER = GL_PIXEL_BUFFER_BARRIER_BIT, // map/storage -> copy to/from texture
48 MEMORY_BARRIER_IMAGE_BUFFER = GL_SHADER_IMAGE_ACCESS_BARRIER_BIT, // map/storage -> image buffer
49 MEMORY_BARRIER_ALL_BUFFER_BARRIERS =
50 MEMORY_BARRIER_VERTEX_BUFFER |
51 MEMORY_BARRIER_INDEX_BUFFER |
52 MEMORY_BARRIER_UNIFORM_BUFFER |
53 MEMORY_BARRIER_BUFFER_UPDATE |
54 MEMORY_BARRIER_CLIENT_MAPPED_BUFFER |
55 MEMORY_BARRIER_STORAGE_BUFFER |
56 MEMORY_BARRIER_INDIRECT_BUFFER |
57 MEMORY_BARRIER_TEXEL_BUFFER |
58 MEMORY_BARRIER_IMAGE_BUFFER,
59
60
61 // Texture barriers
62 MEMORY_BARRIER_TEXTURE_FETCH = GL_TEXTURE_FETCH_BARRIER_BIT, // storage -> fetch
63 MEMORY_BARRIER_STORAGE_IMAGE = GL_SHADER_IMAGE_ACCESS_BARRIER_BIT, // storage -> storage
64 MEMORY_BARRIER_TEXTURE_UPDATE = GL_TEXTURE_UPDATE_BARRIER_BIT, // storage -> host read/write or copy
65 MEMORY_BARRIER_FRAMEBUFFER = GL_FRAMEBUFFER_BARRIER_BIT, // storage -> framebuffer
66 MEMORY_BARRIER_ALL_TEXTURE_BARRIERS =
67 MEMORY_BARRIER_TEXTURE_FETCH |
68 MEMORY_BARRIER_STORAGE_IMAGE |
69 MEMORY_BARRIER_TEXTURE_UPDATE |
70 MEMORY_BARRIER_FRAMEBUFFER,
71 };
72 DEFINE_FLAG_ENUM_OPERATORS(MEMORY_BARRIER);
73
74
3275 class AsyncWritableResource
3376 {
3477 public:
3578 AsyncWritableResource() noexcept {}
3679
37 void SetPendingMemoryBarriers(Uint32 Barriers) { m_PendingMemoryBarriers |= Barriers; }
38 Uint32 GetPendingMemortBarriers() { return m_PendingMemoryBarriers; }
80 void SetPendingMemoryBarriers(MEMORY_BARRIER Barriers) { m_PendingMemoryBarriers |= Barriers; }
81 MEMORY_BARRIER GetPendingMemortBarriers() { return m_PendingMemoryBarriers; }
3982
4083 private:
4184 friend class GLContextState;
42 void ResetPendingMemoryBarriers(Uint32 Barriers) { m_PendingMemoryBarriers = Barriers; }
43 void ClearPendingMemoryBarriers(Uint32 Barriers) { m_PendingMemoryBarriers &= ~Barriers; }
85 void ResetPendingMemoryBarriers(MEMORY_BARRIER Barriers) { m_PendingMemoryBarriers = Barriers; }
86 void ClearPendingMemoryBarriers(MEMORY_BARRIER Barriers) { m_PendingMemoryBarriers &= ~Barriers; }
4487
45 // Buffer barriers:
46 // GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT
47 // GL_ELEMENT_ARRAY_BARRIER_BIT
48 // GL_UNIFORM_BARRIER_BIT
49 // GL_BUFFER_UPDATE_BARRIER_BIT
50 // GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT
51 // GL_SHADER_STORAGE_BARRIER_BIT
52
53 // Texture barriers:
54 // GL_TEXTURE_FETCH_BARRIER_BIT
55 // GL_SHADER_IMAGE_ACCESS_BARRIER_BIT
56 // GL_PIXEL_BUFFER_BARRIER_BIT
57 // GL_TEXTURE_UPDATE_BARRIER_BIT
58
59 // Misc barriers:
60 // GL_FRAMEBUFFER_BARRIER_BIT
61 // GL_TRANSFORM_FEEDBACK_BARRIER_BIT
62 // GL_ATOMIC_COUNTER_BARRIER_BIT
63 // GL_QUERY_BUFFER_BARRIER_BIT
64
65 Uint32 m_PendingMemoryBarriers = 0;
88 MEMORY_BARRIER m_PendingMemoryBarriers = MEMORY_BARRIER_NONE;
6689 };
6790
6891 } // namespace Diligent
7373 void MapRange(GLContextState& CtxState, MAP_TYPE MapType, Uint32 MapFlags, Uint32 Offset, Uint32 Length, PVoid& pMappedData);
7474 void Unmap(GLContextState& CtxState);
7575
76 void BufferMemoryBarrier(Uint32 RequiredBarriers, class GLContextState& GLContextState);
76 void BufferMemoryBarrier(MEMORY_BARRIER RequiredBarriers, class GLContextState& GLContextState);
7777
7878 const GLObjectWrappers::GLBufferObj& GetGLHandle() { return m_GlBuffer; }
7979
4141 #include "PipelineStateGLImpl.hpp"
4242 #include "BottomLevelASBase.hpp"
4343 #include "TopLevelASBase.hpp"
44 #include "ShaderResourceBindingGLImpl.hpp"
4445
4546 namespace Diligent
4647 {
271272 /// Implementation of IDeviceContextGL::UpdateCurrentGLContext().
272273 virtual bool DILIGENT_CALL_TYPE UpdateCurrentGLContext() override final;
273274
274 void BindProgramResources(Uint32& NewMemoryBarriers, IShaderResourceBinding* pResBinding);
275
276275 GLContextState& GetContextState() { return m_ContextState; }
277276
278277 void CommitRenderTargets();
295294 __forceinline void PrepareForIndirectDraw(IBuffer* pAttribsBuffer);
296295 __forceinline void PostDraw();
297296
297 using TBindings = PipelineResourceSignatureGLImpl::TBindings;
298 void BindProgramResources(MEMORY_BARRIER& NewMemoryBarriers, const ShaderResourceBindingGLImpl* pShaderResBindingGL, TBindings& Bindings);
299 void BindProgramResources();
300
301 #ifdef DILIGENT_DEVELOPMENT
302 void DvpValidateCommittedShaderResources();
303 #endif
304
298305 void BeginSubpass();
299306 void EndSubpass();
300307
301 Uint32 m_CommitedResourcesTentativeBarriers = 0;
308 struct SRBState
309 {
310 // Do not use strong references!
311 std::array<ShaderResourceBindingGLImpl*, MAX_RESOURCE_SIGNATURES> SRBs = {};
312
313 using Bitfield = Uint8;
314 static_assert(sizeof(Bitfield) * 8 >= MAX_RESOURCE_SIGNATURES, "not enought space to store MAX_RESOURCE_SIGNATURES bits");
315
316 Bitfield ActiveSRBMask = 0; // Indicates which SRBs are active in current PSO
317 Bitfield StaleSRBMask = 0; // Indicates stale SRBs that have descriptor sets that need to be bound
318
319 #ifdef DILIGENT_DEVELOPMENT
320 bool CommittedResourcesValidated = false;
321
322 // Binding offsets that was used at last BindProgramResources() call.
323 std::array<TBindings, MAX_RESOURCE_SIGNATURES> BoundResOffsets = {};
324 #endif
325
326 SRBState()
327 {}
328
329 void SetStaleSRBBit(Uint32 Index) { StaleSRBMask |= static_cast<Bitfield>(1u << Index); }
330 void ClearStaleSRBBit(Uint32 Index) { StaleSRBMask &= static_cast<Bitfield>(~(1u << Index)); }
331
332 } m_BindInfo;
333
334 MEMORY_BARRIER m_CommitedResourcesTentativeBarriers = MEMORY_BARRIER_NONE;
302335
303336 std::vector<class TextureBaseGL*> m_BoundWritableTextures;
304337 std::vector<class BufferGLImpl*> m_BoundWritableBuffers;
3030 #include "GLObjectWrapper.hpp"
3131 #include "UniqueIdentifier.hpp"
3232 #include "GLContext.hpp"
33 #include "AsyncWritableResource.hpp"
3334
3435 namespace Diligent
3536 {
5455 void BindImage (Uint32 Index, class BufferViewGLImpl* pBuffView, GLenum Access, GLenum Format);
5556 void BindStorageBlock (Int32 Index, const GLObjectWrappers::GLBufferObj& Buff, GLintptr Offset, GLsizeiptr Size);
5657
57 void EnsureMemoryBarrier(Uint32 RequiredBarriers, class AsyncWritableResource *pRes = nullptr);
58 void SetPendingMemoryBarriers(Uint32 PendingBarriers);
58 void EnsureMemoryBarrier(MEMORY_BARRIER RequiredBarriers, class AsyncWritableResource *pRes = nullptr);
59 void SetPendingMemoryBarriers(MEMORY_BARRIER PendingBarriers);
5960
6061 void EnableDepthTest (bool bEnable);
6162 void EnableDepthWrites (bool bEnable);
201202 };
202203 std::vector<BoundSSBOInfo> m_BoundStorageBlocks;
203204
204 Uint32 m_PendingMemoryBarriers = 0;
205 MEMORY_BARRIER m_PendingMemoryBarriers = MEMORY_BARRIER_NONE;
205206
206207 class EnableStateHelper
207208 {
+0
-471
Graphics/GraphicsEngineOpenGL/include/GLPipelineResourceLayout.hpp less more
0 /*
1 * Copyright 2019-2021 Diligent Graphics LLC
2 * Copyright 2015-2019 Egor Yusov
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * In no event and under no legal theory, whether in tort (including negligence),
17 * contract, or otherwise, unless required by applicable law (such as deliberate
18 * and grossly negligent acts) or agreed to in writing, shall any Contributor be
19 * liable for any damages, including any direct, indirect, special, incidental,
20 * or consequential damages of any character arising as a result of this License or
21 * out of the use or inability to use the software (including but not limited to damages
22 * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
23 * all other commercial damages or losses), even if such Contributor has been advised
24 * of the possibility of such damages.
25 */
26
27 #pragma once
28
29 // GLPipelineResourceLayout class manages resource bindings for all stages in a pipeline
30
31 //
32 //
33 // To program resource cache
34 //
35 // A A A A A A A A
36 // | | | | | | | |
37 // Binding Binding Binding Binding Binding Binding Binding Binding
38 // ___________________ ____|__________|__________________|________|______________|___________|______________|____________|____________
39 // | | | | | | | | | | | | | | |
40 // |GLProgramResources |--------------->| UB[0] | UB[1] | ... | Sam[0] | Sam[1] | ... | Img[0] | Img[1] | ... | SSBOs[0] | SSBOs[1] | ... |
41 // |___________________| |__________|__________|_______|________|________|_______|________|________|_______|__________|__________|_______|
42 // A A A A
43 // | | | |
44 // Ref Ref Ref Ref
45 // .-==========================-. _____|____________________________________|________________________|____________________________|______________
46 // || || | | | | | | | | | | |
47 // __|| GLPipelineResourceLayout ||------->| UBInfo[0] | UBInfo[1] | ... | SamInfo[0] | SamInfo[1] | ... | ImgInfo[0] | ... | SSBO[0] | ... |
48 // | || || |___________|___________|_______|____________|____________|_______|____________|_________|___________|__________|
49 // | '-==========================-' / \
50 // | Ref Ref
51 // | / \
52 // | ___________________ ________V________________________________________________V_____________________________________________________
53 // | | | | | | | | | | | | | | | |
54 // | |GLProgramResources |--------------->| UB[0] | UB[1] | ... | Sam[0] | Sam[1] | ... | Img[0] | Img[1] | ... | SSBOs[0] | SSBOs[1] | ... |
55 // | |___________________| |__________|__________|_______|________|________|_______|________|________|_______|__________|__________|_______|
56 // | | | | | | | | |
57 // | Binding Binding Binding Binding Binding Binding Binding Binding
58 // | | | | | | | | |
59 // | _______________________ ____V___________V________________V_________V________________V________V________________V___________V_____________
60 // | | | | | | | |
61 // '-->|GLProgramResourceCache |----------->| Uinform Buffers | Samplers | Images | Storge Buffers |
62 // |_______________________| |___________________________|___________________________|___________________________|___________________________|
63 //
64 //
65 // Note that GLProgramResources are kept by PipelineStateGLImpl. GLPipelineResourceLayout class is either part of the same PSO class,
66 // or part of ShaderResourceBindingGLImpl object that keeps a strong reference to the pipeline. So all references from GLVariableBase
67 // are always valid.
68
69 #include <array>
70
71 #include "Object.h"
72 #include "ShaderResourceVariableBase.hpp"
73 #include "GLProgramResources.hpp"
74 #include "GLProgramResourceCache.hpp"
75
76 namespace Diligent
77 {
78
79 class GLPipelineResourceLayout
80 {
81 public:
82 GLPipelineResourceLayout(IObject& Owner) :
83 m_Owner(Owner)
84 {
85 m_ProgramIndex.fill(-1);
86 }
87
88 ~GLPipelineResourceLayout();
89
90 // No copies, only moves are allowed
91 // clang-format off
92 GLPipelineResourceLayout (const GLPipelineResourceLayout&) = delete;
93 GLPipelineResourceLayout& operator = (const GLPipelineResourceLayout&) = delete;
94 GLPipelineResourceLayout ( GLPipelineResourceLayout&&) = default;
95 GLPipelineResourceLayout& operator = ( GLPipelineResourceLayout&&) = delete;
96 // clang-format on
97
98 void Initialize(GLProgramResources* ProgramResources,
99 Uint32 NumPrograms,
100 PIPELINE_TYPE PipelineType,
101 const PipelineResourceLayoutDesc& ResourceLayout,
102 const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
103 Uint32 NumAllowedTypes,
104 GLProgramResourceCache* pResourceCache);
105
106 static size_t GetRequiredMemorySize(GLProgramResources* ProgramResources,
107 Uint32 NumPrograms,
108 const PipelineResourceLayoutDesc& ResourceLayout,
109 const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
110 Uint32 NumAllowedTypes);
111
112 void CopyResources(GLProgramResourceCache& DstCache) const;
113
114 struct GLVariableBase : public ShaderVariableBase<GLPipelineResourceLayout>
115 {
116 using TBase = ShaderVariableBase<GLPipelineResourceLayout>;
117 GLVariableBase(const GLProgramResources::GLResourceAttribs& ResourceAttribs,
118 GLPipelineResourceLayout& ParentLayout,
119 SHADER_RESOURCE_VARIABLE_TYPE VariableType,
120 Int32 ImtblSamplerIdx) :
121 // clang-format off
122 TBase {ParentLayout},
123 m_Attribs {ResourceAttribs },
124 m_VariableType {VariableType },
125 m_ImtblSamplerIdx {ImtblSamplerIdx}
126 // clang-format on
127 {
128 VERIFY_EXPR(ImtblSamplerIdx < 0 || ResourceAttribs.ResourceType == SHADER_RESOURCE_TYPE_TEXTURE_SRV);
129 }
130
131 virtual SHADER_RESOURCE_VARIABLE_TYPE DILIGENT_CALL_TYPE GetType() const override final
132 {
133 return m_VariableType;
134 }
135
136 virtual void DILIGENT_CALL_TYPE GetResourceDesc(ShaderResourceDesc& ResourceDesc) const override final
137 {
138 ResourceDesc = m_Attribs.GetResourceDesc();
139 }
140
141 virtual Uint32 DILIGENT_CALL_TYPE GetIndex() const override final
142 {
143 return m_ParentResLayout.GetVariableIndex(*this);
144 }
145
146 const GLProgramResources::GLResourceAttribs& m_Attribs;
147 const SHADER_RESOURCE_VARIABLE_TYPE m_VariableType;
148 const Int32 m_ImtblSamplerIdx;
149 };
150
151
152 struct UniformBuffBindInfo final : GLVariableBase
153 {
154 UniformBuffBindInfo(const GLProgramResources::GLResourceAttribs& ResourceAttribs,
155 GLPipelineResourceLayout& ParentResLayout,
156 SHADER_RESOURCE_VARIABLE_TYPE VariableType) :
157 GLVariableBase{ResourceAttribs, ParentResLayout, VariableType, -1}
158 {}
159
160 // Non-virtual function
161 void BindResource(IDeviceObject* pObject, Uint32 ArrayIndex);
162
163 virtual void DILIGENT_CALL_TYPE Set(IDeviceObject* pObject) override final
164 {
165 BindResource(pObject, 0);
166 }
167
168 virtual void DILIGENT_CALL_TYPE SetArray(IDeviceObject* const* ppObjects,
169 Uint32 FirstElement,
170 Uint32 NumElements) override final
171 {
172 VerifyAndCorrectSetArrayArguments(m_Attribs.Name, m_Attribs.ArraySize, FirstElement, NumElements);
173 for (Uint32 elem = 0; elem < NumElements; ++elem)
174 BindResource(ppObjects[elem], FirstElement + elem);
175 }
176
177 virtual bool DILIGENT_CALL_TYPE IsBound(Uint32 ArrayIndex) const override final
178 {
179 VERIFY_EXPR(ArrayIndex < m_Attribs.ArraySize);
180 return m_ParentResLayout.m_pResourceCache->IsUBBound(m_Attribs.Binding + ArrayIndex);
181 }
182 };
183
184
185 struct SamplerBindInfo final : GLVariableBase
186 {
187 SamplerBindInfo(const GLProgramResources::GLResourceAttribs& ResourceAttribs,
188 GLPipelineResourceLayout& ParentResLayout,
189 SHADER_RESOURCE_VARIABLE_TYPE VariableType,
190 Int32 ImtblSamplerIdx) :
191 GLVariableBase{ResourceAttribs, ParentResLayout, VariableType, ImtblSamplerIdx}
192 {}
193
194 // Non-virtual function
195 void BindResource(IDeviceObject* pObject, Uint32 ArrayIndex);
196
197 virtual void DILIGENT_CALL_TYPE Set(IDeviceObject* pObject) override final
198 {
199 BindResource(pObject, 0);
200 }
201
202 virtual void DILIGENT_CALL_TYPE SetArray(IDeviceObject* const* ppObjects,
203 Uint32 FirstElement,
204 Uint32 NumElements) override final
205 {
206 VerifyAndCorrectSetArrayArguments(m_Attribs.Name, m_Attribs.ArraySize, FirstElement, NumElements);
207 for (Uint32 elem = 0; elem < NumElements; ++elem)
208 BindResource(ppObjects[elem], FirstElement + elem);
209 }
210
211 virtual bool DILIGENT_CALL_TYPE IsBound(Uint32 ArrayIndex) const override final
212 {
213 VERIFY_EXPR(ArrayIndex < m_Attribs.ArraySize);
214 return m_ParentResLayout.m_pResourceCache->IsSamplerBound(m_Attribs.Binding + ArrayIndex, m_Attribs.ResourceType == SHADER_RESOURCE_TYPE_TEXTURE_SRV);
215 }
216 };
217
218
219 struct ImageBindInfo final : GLVariableBase
220 {
221 ImageBindInfo(const GLProgramResources::GLResourceAttribs& ResourceAttribs,
222 GLPipelineResourceLayout& ParentResLayout,
223 SHADER_RESOURCE_VARIABLE_TYPE VariableType) :
224 GLVariableBase{ResourceAttribs, ParentResLayout, VariableType, -1}
225 {}
226
227 // Provide non-virtual function
228 void BindResource(IDeviceObject* pObject, Uint32 ArrayIndex);
229
230 virtual void DILIGENT_CALL_TYPE Set(IDeviceObject* pObject) override final
231 {
232 BindResource(pObject, 0);
233 }
234
235 virtual void DILIGENT_CALL_TYPE SetArray(IDeviceObject* const* ppObjects,
236 Uint32 FirstElement,
237 Uint32 NumElements) override final
238 {
239 VerifyAndCorrectSetArrayArguments(m_Attribs.Name, m_Attribs.ArraySize, FirstElement, NumElements);
240 for (Uint32 elem = 0; elem < NumElements; ++elem)
241 BindResource(ppObjects[elem], FirstElement + elem);
242 }
243
244 virtual bool DILIGENT_CALL_TYPE IsBound(Uint32 ArrayIndex) const override final
245 {
246 VERIFY_EXPR(ArrayIndex < m_Attribs.ArraySize);
247 return m_ParentResLayout.m_pResourceCache->IsImageBound(m_Attribs.Binding + ArrayIndex, m_Attribs.ResourceType == SHADER_RESOURCE_TYPE_TEXTURE_UAV);
248 }
249 };
250
251
252 struct StorageBufferBindInfo final : GLVariableBase
253 {
254 StorageBufferBindInfo(const GLProgramResources::GLResourceAttribs& ResourceAttribs,
255 GLPipelineResourceLayout& ParentResLayout,
256 SHADER_RESOURCE_VARIABLE_TYPE VariableType) :
257 GLVariableBase{ResourceAttribs, ParentResLayout, VariableType, -1}
258 {}
259
260 // Non-virtual function
261 void BindResource(IDeviceObject* pObject, Uint32 ArrayIndex);
262
263 virtual void DILIGENT_CALL_TYPE Set(IDeviceObject* pObject) override final
264 {
265 BindResource(pObject, 0);
266 }
267
268 virtual void DILIGENT_CALL_TYPE SetArray(IDeviceObject* const* ppObjects,
269 Uint32 FirstElement,
270 Uint32 NumElements) override final
271 {
272 VerifyAndCorrectSetArrayArguments(m_Attribs.Name, m_Attribs.ArraySize, FirstElement, NumElements);
273 for (Uint32 elem = 0; elem < NumElements; ++elem)
274 BindResource(ppObjects[elem], FirstElement + elem);
275 }
276
277 virtual bool DILIGENT_CALL_TYPE IsBound(Uint32 ArrayIndex) const override final
278 {
279 VERIFY_EXPR(ArrayIndex < m_Attribs.ArraySize);
280 return m_ParentResLayout.m_pResourceCache->IsSSBOBound(m_Attribs.Binding + ArrayIndex);
281 }
282 };
283
284
285 // dbgResourceCache is only used for sanity check and as a remainder that the resource cache must be alive
286 // while Layout is alive
287 void BindResources(SHADER_TYPE ShaderStage, IResourceMapping* pResourceMapping, Uint32 Flags, const GLProgramResourceCache& dbgResourceCache);
288
289 #ifdef DILIGENT_DEVELOPMENT
290 bool dvpVerifyBindings(const GLProgramResourceCache& ResourceCache) const;
291 #endif
292
293 IShaderResourceVariable* GetShaderVariable(SHADER_TYPE ShaderStage, const Char* Name);
294 IShaderResourceVariable* GetShaderVariable(SHADER_TYPE ShaderStage, Uint32 Index);
295
296 IObject& GetOwner() { return m_Owner; }
297
298 Uint32 GetNumVariables(SHADER_TYPE ShaderStage) const;
299
300 // clang-format off
301 Uint32 GetNumUBs() const { return (m_SamplerOffset - m_UBOffset) / sizeof(UniformBuffBindInfo); }
302 Uint32 GetNumSamplers() const { return (m_ImageOffset - m_SamplerOffset) / sizeof(SamplerBindInfo); }
303 Uint32 GetNumImages() const { return (m_StorageBufferOffset - m_ImageOffset) / sizeof(ImageBindInfo) ; }
304 Uint32 GetNumStorageBuffers() const { return (m_VariableEndOffset - m_StorageBufferOffset) / sizeof(StorageBufferBindInfo); }
305 // clang-format on
306
307 template <typename ResourceType> Uint32 GetNumResources() const;
308
309 template <typename ResourceType>
310 const ResourceType& GetConstResource(Uint32 ResIndex) const
311 {
312 VERIFY(ResIndex < GetNumResources<ResourceType>(), "Resource index (", ResIndex, ") exceeds max allowed value (", GetNumResources<ResourceType>(), ")");
313 auto Offset = GetResourceOffset<ResourceType>();
314 return reinterpret_cast<const ResourceType*>(reinterpret_cast<const Uint8*>(m_ResourceBuffer.get()) + Offset)[ResIndex];
315 }
316
317 Uint32 GetVariableIndex(const GLVariableBase& Var) const;
318
319 private:
320 // clang-format off
321 /* 0*/ IObject& m_Owner;
322 // No need to use shared pointer, as the resource cache is either part of the same
323 // ShaderGLImpl object, or ShaderResourceBindingGLImpl object
324 /* 8*/ GLProgramResourceCache* m_pResourceCache = nullptr;
325 /*16*/ std::unique_ptr<void, STDDeleterRawMem<void> > m_ResourceBuffer;
326
327 // Offsets in bytes
328 using OffsetType = Uint16;
329 static constexpr OffsetType m_UBOffset = 0;
330 /*32*/ OffsetType m_SamplerOffset = 0;
331 /*34*/ OffsetType m_ImageOffset = 0;
332 /*36*/ OffsetType m_StorageBufferOffset = 0;
333 /*38*/ OffsetType m_VariableEndOffset = 0;
334 /*40*/ std::array<Int8, MAX_SHADERS_IN_PIPELINE> m_ProgramIndex = {};
335 /*45*/ Uint8 m_NumPrograms = 0;
336 /*46*/ Uint8 m_PipelineType = 255u;
337 /*47*/
338 /*48*/ // End of structure
339 // clang-format on
340
341 template <typename ResourceType> OffsetType GetResourceOffset() const;
342
343 template <typename ResourceType>
344 ResourceType& GetResource(Uint32 ResIndex)
345 {
346 VERIFY(ResIndex < GetNumResources<ResourceType>(), "Resource index (", ResIndex, ") exceeds max allowed value (", GetNumResources<ResourceType>() - 1, ")");
347 auto Offset = GetResourceOffset<ResourceType>();
348 return reinterpret_cast<ResourceType*>(reinterpret_cast<Uint8*>(m_ResourceBuffer.get()) + Offset)[ResIndex];
349 }
350
351 GLProgramResources::ResourceCounters& GetProgramVarEndOffsets(Uint32 prog)
352 {
353 VERIFY_EXPR(prog < m_NumPrograms);
354 return reinterpret_cast<GLProgramResources::ResourceCounters*>(reinterpret_cast<Uint8*>(m_ResourceBuffer.get()) + m_VariableEndOffset)[prog];
355 }
356
357 const GLProgramResources::ResourceCounters& GetProgramVarEndOffsets(Uint32 prog) const
358 {
359 VERIFY_EXPR(prog < m_NumPrograms);
360 return reinterpret_cast<GLProgramResources::ResourceCounters*>(reinterpret_cast<Uint8*>(m_ResourceBuffer.get()) + m_VariableEndOffset)[prog];
361 }
362
363 template <typename ResourceType>
364 IShaderResourceVariable* GetResourceByName(SHADER_TYPE ShaderStage, const Char* Name);
365
366 template <typename THandleUB,
367 typename THandleSampler,
368 typename THandleImage,
369 typename THandleStorageBuffer>
370 void HandleResources(THandleUB HandleUB,
371 THandleSampler HandleSampler,
372 THandleImage HandleImage,
373 THandleStorageBuffer HandleStorageBuffer)
374 {
375 for (Uint32 ub = 0; ub < GetNumResources<UniformBuffBindInfo>(); ++ub)
376 HandleUB(GetResource<UniformBuffBindInfo>(ub));
377
378 for (Uint32 s = 0; s < GetNumResources<SamplerBindInfo>(); ++s)
379 HandleSampler(GetResource<SamplerBindInfo>(s));
380
381 for (Uint32 i = 0; i < GetNumResources<ImageBindInfo>(); ++i)
382 HandleImage(GetResource<ImageBindInfo>(i));
383
384 for (Uint32 s = 0; s < GetNumResources<StorageBufferBindInfo>(); ++s)
385 HandleStorageBuffer(GetResource<StorageBufferBindInfo>(s));
386 }
387
388 template <typename THandleUB,
389 typename THandleSampler,
390 typename THandleImage,
391 typename THandleStorageBuffer>
392 void HandleConstResources(THandleUB HandleUB,
393 THandleSampler HandleSampler,
394 THandleImage HandleImage,
395 THandleStorageBuffer HandleStorageBuffer) const
396 {
397 for (Uint32 ub = 0; ub < GetNumResources<UniformBuffBindInfo>(); ++ub)
398 HandleUB(GetConstResource<UniformBuffBindInfo>(ub));
399
400 for (Uint32 s = 0; s < GetNumResources<SamplerBindInfo>(); ++s)
401 HandleSampler(GetConstResource<SamplerBindInfo>(s));
402
403 for (Uint32 i = 0; i < GetNumResources<ImageBindInfo>(); ++i)
404 HandleImage(GetConstResource<ImageBindInfo>(i));
405
406 for (Uint32 s = 0; s < GetNumResources<StorageBufferBindInfo>(); ++s)
407 HandleStorageBuffer(GetConstResource<StorageBufferBindInfo>(s));
408 }
409
410 friend class ShaderVariableIndexLocator;
411 friend class ShaderVariableLocator;
412 };
413
414
415
416 template <>
417 inline Uint32 GLPipelineResourceLayout::GetNumResources<GLPipelineResourceLayout::UniformBuffBindInfo>() const
418 {
419 return GetNumUBs();
420 }
421
422 template <>
423 inline Uint32 GLPipelineResourceLayout::GetNumResources<GLPipelineResourceLayout::SamplerBindInfo>() const
424 {
425 return GetNumSamplers();
426 }
427
428 template <>
429 inline Uint32 GLPipelineResourceLayout::GetNumResources<GLPipelineResourceLayout::ImageBindInfo>() const
430 {
431 return GetNumImages();
432 }
433
434 template <>
435 inline Uint32 GLPipelineResourceLayout::GetNumResources<GLPipelineResourceLayout::StorageBufferBindInfo>() const
436 {
437 return GetNumStorageBuffers();
438 }
439
440
441
442 template <>
443 inline GLPipelineResourceLayout::OffsetType GLPipelineResourceLayout::
444 GetResourceOffset<GLPipelineResourceLayout::UniformBuffBindInfo>() const
445 {
446 return m_UBOffset;
447 }
448
449 template <>
450 inline GLPipelineResourceLayout::OffsetType GLPipelineResourceLayout::
451 GetResourceOffset<GLPipelineResourceLayout::SamplerBindInfo>() const
452 {
453 return m_SamplerOffset;
454 }
455
456 template <>
457 inline GLPipelineResourceLayout::OffsetType GLPipelineResourceLayout::
458 GetResourceOffset<GLPipelineResourceLayout::ImageBindInfo>() const
459 {
460 return m_ImageOffset;
461 }
462
463 template <>
464 inline GLPipelineResourceLayout::OffsetType GLPipelineResourceLayout::
465 GetResourceOffset<GLPipelineResourceLayout::StorageBufferBindInfo>() const
466 {
467 return m_StorageBufferOffset;
468 }
469
470 } // namespace Diligent
+0
-276
Graphics/GraphicsEngineOpenGL/include/GLProgramResourceCache.hpp less more
0 /*
1 * Copyright 2019-2021 Diligent Graphics LLC
2 * Copyright 2015-2019 Egor Yusov
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * In no event and under no legal theory, whether in tort (including negligence),
17 * contract, or otherwise, unless required by applicable law (such as deliberate
18 * and grossly negligent acts) or agreed to in writing, shall any Contributor be
19 * liable for any damages, including any direct, indirect, special, incidental,
20 * or consequential damages of any character arising as a result of this License or
21 * out of the use or inability to use the software (including but not limited to damages
22 * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
23 * all other commercial damages or losses), even if such Contributor has been advised
24 * of the possibility of such damages.
25 */
26
27 #pragma once
28
29 #include "BufferGLImpl.hpp"
30 #include "TextureBaseGL.hpp"
31 #include "SamplerGLImpl.hpp"
32
33 namespace Diligent
34 {
35
36 /// The class implements a cache that holds resources bound to a specific GL program
37 // All resources are stored in the continuous memory using the following layout:
38 //
39 // | Cached UBs | Cached Samplers | Cached Images | Cached Storage Blocks |
40 // |----------------------------------------------------|--------------------------|---------------------------|
41 // | 0 | 1 | ... | UBCount-1 | 0 | 1 | ...| SmpCount-1 | 0 | 1 | ... | ImgCount-1 | 0 | 1 | ... | SBOCount-1 |
42 // -----------------------------------------------------------------------------------------------------------
43 //
44 class GLProgramResourceCache
45 {
46 public:
47 GLProgramResourceCache() noexcept
48 {}
49
50 ~GLProgramResourceCache();
51
52 // clang-format off
53 GLProgramResourceCache (const GLProgramResourceCache&) = delete;
54 GLProgramResourceCache& operator = (const GLProgramResourceCache&) = delete;
55 GLProgramResourceCache (GLProgramResourceCache&&) = delete;
56 GLProgramResourceCache& operator = (GLProgramResourceCache&&) = delete;
57 // clang-format on
58
59 /// Describes a resource bound to a uniform buffer or a shader storage block slot
60 struct CachedUB
61 {
62 /// Strong reference to the buffer
63 RefCntAutoPtr<BufferGLImpl> pBuffer;
64 };
65
66 /// Describes a resource bound to a sampler or an image slot
67 struct CachedResourceView
68 {
69 /// We keep strong reference to the view instead of the reference
70 /// to the texture or buffer because this is more efficient from
71 /// performance point of view: this avoids one pair of
72 /// AddStrongRef()/ReleaseStrongRef(). The view holds a strong reference
73 /// to the texture or the buffer, so it makes no difference.
74 RefCntAutoPtr<IDeviceObject> pView;
75
76 TextureBaseGL* pTexture = nullptr;
77 union
78 {
79 BufferGLImpl* pBuffer = nullptr; // When pTexture == nullptr
80 SamplerGLImpl* pSampler; // When pTexture != nullptr
81 };
82 CachedResourceView() noexcept {}
83
84 void Set(RefCntAutoPtr<TextureViewGLImpl>&& pTexView, bool SetSampler)
85 {
86 // Do not null out pSampler as it could've been initialized by PipelineStateGLImpl::InitializeSRBResourceCache!
87 // pSampler = nullptr;
88
89 // Avoid unnecessary virtual function calls
90 pTexture = pTexView ? ValidatedCast<TextureBaseGL>(pTexView->TextureViewGLImpl::GetTexture()) : nullptr;
91 if (pTexView && SetSampler)
92 {
93 pSampler = ValidatedCast<SamplerGLImpl>(pTexView->GetSampler());
94 }
95
96 pView.Attach(pTexView.Detach());
97 }
98
99 void Set(RefCntAutoPtr<BufferViewGLImpl>&& pBufView)
100 {
101 pTexture = nullptr;
102 // Avoid unnecessary virtual function calls
103 pBuffer = pBufView ? ValidatedCast<BufferGLImpl>(pBufView->BufferViewGLImpl::GetBuffer()) : nullptr;
104 pView.Attach(pBufView.Detach());
105 }
106 };
107
108 struct CachedSSBO
109 {
110 /// Strong reference to the buffer
111 RefCntAutoPtr<BufferViewGLImpl> pBufferView;
112 };
113
114
115 static size_t GetRequriedMemorySize(Uint32 UBCount, Uint32 SamplerCount, Uint32 ImageCount, Uint32 SSBOCount);
116
117 void Initialize(Uint32 UBCount, Uint32 SamplerCount, Uint32 ImageCount, Uint32 SSBOCount, IMemoryAllocator& MemAllocator);
118 void Destroy(IMemoryAllocator& MemAllocator);
119
120 void SetUniformBuffer(Uint32 Binding, RefCntAutoPtr<BufferGLImpl>&& pBuff)
121 {
122 GetUB(Binding).pBuffer = std::move(pBuff);
123 }
124
125 void SetTexSampler(Uint32 Binding, RefCntAutoPtr<TextureViewGLImpl>&& pTexView, bool SetSampler)
126 {
127 GetSampler(Binding).Set(std::move(pTexView), SetSampler);
128 }
129
130 void SetImmutableSampler(Uint32 Binding, ISampler* pImtblSampler)
131 {
132 GetSampler(Binding).pSampler = ValidatedCast<SamplerGLImpl>(pImtblSampler);
133 }
134
135 void CopySampler(Uint32 Binding, const CachedResourceView& SrcSam)
136 {
137 GetSampler(Binding) = SrcSam;
138 }
139
140 void SetBufSampler(Uint32 Binding, RefCntAutoPtr<BufferViewGLImpl>&& pBuffView)
141 {
142 GetSampler(Binding).Set(std::move(pBuffView));
143 }
144
145 void SetTexImage(Uint32 Binding, RefCntAutoPtr<TextureViewGLImpl>&& pTexView)
146 {
147 GetImage(Binding).Set(std::move(pTexView), false);
148 }
149
150 void SetBufImage(Uint32 Binding, RefCntAutoPtr<BufferViewGLImpl>&& pBuffView)
151 {
152 GetImage(Binding).Set(std::move(pBuffView));
153 }
154
155 void CopyImage(Uint32 Binding, const CachedResourceView& SrcImg)
156 {
157 GetImage(Binding) = SrcImg;
158 }
159
160 void SetSSBO(Uint32 Binding, RefCntAutoPtr<BufferViewGLImpl>&& pBuffView)
161 {
162 GetSSBO(Binding).pBufferView = std::move(pBuffView);
163 }
164
165 bool IsUBBound(Uint32 Binding) const
166 {
167 if (Binding >= GetUBCount())
168 return false;
169
170 const auto& UB = GetConstUB(Binding);
171 return UB.pBuffer;
172 }
173
174 bool IsSamplerBound(Uint32 Binding, bool dbgIsTextureView) const
175 {
176 if (Binding >= GetSamplerCount())
177 return false;
178
179 const auto& Sampler = GetConstSampler(Binding);
180 VERIFY_EXPR(dbgIsTextureView || Sampler.pTexture == nullptr);
181 return Sampler.pView;
182 }
183
184 bool IsImageBound(Uint32 Binding, bool dbgIsTextureView) const
185 {
186 if (Binding >= GetImageCount())
187 return false;
188
189 const auto& Image = GetConstImage(Binding);
190 VERIFY_EXPR(dbgIsTextureView || Image.pTexture == nullptr);
191 return Image.pView;
192 }
193
194 bool IsSSBOBound(Uint32 Binding) const
195 {
196 if (Binding >= GetSSBOCount())
197 return false;
198
199 const auto& SSBO = GetConstSSBO(Binding);
200 return SSBO.pBufferView;
201 }
202
203 // clang-format off
204 Uint32 GetUBCount() const { return (m_SmplrsOffset - m_UBsOffset) / sizeof(CachedUB); }
205 Uint32 GetSamplerCount() const { return (m_ImgsOffset - m_SmplrsOffset) / sizeof(CachedResourceView); }
206 Uint32 GetImageCount() const { return (m_SSBOsOffset - m_ImgsOffset) / sizeof(CachedResourceView); }
207 Uint32 GetSSBOCount() const { return (m_MemoryEndOffset - m_SSBOsOffset) / sizeof(CachedSSBO); }
208 // clang-format on
209
210 const CachedUB& GetConstUB(Uint32 Binding) const
211 {
212 VERIFY(Binding < GetUBCount(), "Uniform buffer binding (", Binding, ") is out of range");
213 return reinterpret_cast<CachedUB*>(m_pResourceData + m_UBsOffset)[Binding];
214 }
215
216 const CachedResourceView& GetConstSampler(Uint32 Binding) const
217 {
218 VERIFY(Binding < GetSamplerCount(), "Sampler binding (", Binding, ") is out of range");
219 return reinterpret_cast<CachedResourceView*>(m_pResourceData + m_SmplrsOffset)[Binding];
220 }
221
222 const CachedResourceView& GetConstImage(Uint32 Binding) const
223 {
224 VERIFY(Binding < GetImageCount(), "Image buffer binding (", Binding, ") is out of range");
225 return reinterpret_cast<CachedResourceView*>(m_pResourceData + m_ImgsOffset)[Binding];
226 }
227
228 const CachedSSBO& GetConstSSBO(Uint32 Binding) const
229 {
230 VERIFY(Binding < GetSSBOCount(), "Shader storage block binding (", Binding, ") is out of range");
231 return reinterpret_cast<CachedSSBO*>(m_pResourceData + m_SSBOsOffset)[Binding];
232 }
233
234 bool IsInitialized() const
235 {
236 return m_MemoryEndOffset != InvalidResourceOffset;
237 }
238
239 private:
240 CachedUB& GetUB(Uint32 Binding)
241 {
242 return const_cast<CachedUB&>(const_cast<const GLProgramResourceCache*>(this)->GetConstUB(Binding));
243 }
244
245 CachedResourceView& GetSampler(Uint32 Binding)
246 {
247 return const_cast<CachedResourceView&>(const_cast<const GLProgramResourceCache*>(this)->GetConstSampler(Binding));
248 }
249
250 CachedResourceView& GetImage(Uint32 Binding)
251 {
252 return const_cast<CachedResourceView&>(const_cast<const GLProgramResourceCache*>(this)->GetConstImage(Binding));
253 }
254
255 CachedSSBO& GetSSBO(Uint32 Binding)
256 {
257 return const_cast<CachedSSBO&>(const_cast<const GLProgramResourceCache*>(this)->GetConstSSBO(Binding));
258 }
259
260 static constexpr const Uint16 InvalidResourceOffset = 0xFFFF;
261 static constexpr const Uint16 m_UBsOffset = 0;
262
263 Uint16 m_SmplrsOffset = InvalidResourceOffset;
264 Uint16 m_ImgsOffset = InvalidResourceOffset;
265 Uint16 m_SSBOsOffset = InvalidResourceOffset;
266 Uint16 m_MemoryEndOffset = InvalidResourceOffset;
267
268 Uint8* m_pResourceData = nullptr;
269
270 #ifdef DILIGENT_DEBUG
271 IMemoryAllocator* m_pdbgMemoryAllocator = nullptr;
272 #endif
273 };
274
275 } // namespace Diligent
+0
-521
Graphics/GraphicsEngineOpenGL/include/GLProgramResources.hpp less more
0 /*
1 * Copyright 2019-2021 Diligent Graphics LLC
2 * Copyright 2015-2019 Egor Yusov
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * In no event and under no legal theory, whether in tort (including negligence),
17 * contract, or otherwise, unless required by applicable law (such as deliberate
18 * and grossly negligent acts) or agreed to in writing, shall any Contributor be
19 * liable for any damages, including any direct, indirect, special, incidental,
20 * or consequential damages of any character arising as a result of this License or
21 * out of the use or inability to use the software (including but not limited to damages
22 * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
23 * all other commercial damages or losses), even if such Contributor has been advised
24 * of the possibility of such damages.
25 */
26
27 #pragma once
28
29 // GLProgramResources class allocates single continuous chunk of memory to store all program resources, as follows:
30 //
31 //
32 // m_UniformBuffers m_Samplers m_Images m_StorageBlocks
33 // | | | | | |
34 // | UB[0] ... UB[Nu-1] | Sam[0] ... Sam[Ns-1] | Img[0] ... Img[Ni-1] | SB[0] ... SB[Nsb-1] | Resource Names |
35 //
36 // Nu - number of uniform buffers
37 // Ns - number of samplers
38 // Ni - number of images
39 // Nsb - number of storage blocks
40
41 #include <vector>
42
43 #include "Object.h"
44 #include "StringPool.hpp"
45 #include "HashUtils.hpp"
46 #include "ShaderResourceVariableBase.hpp"
47
48 namespace Diligent
49 {
50
51 class GLProgramResources
52 {
53 public:
54 GLProgramResources() {}
55 ~GLProgramResources();
56 // clang-format off
57 GLProgramResources (GLProgramResources&& Program)noexcept;
58
59 GLProgramResources (const GLProgramResources&) = delete;
60 GLProgramResources& operator = (const GLProgramResources&) = delete;
61 GLProgramResources& operator = ( GLProgramResources&&) = delete;
62 // clang-format on
63
64 /// Loads program uniforms and assigns bindings
65 void LoadUniforms(SHADER_TYPE ShaderStages,
66 const GLObjectWrappers::GLProgramObj& GLProgram,
67 class GLContextState& State,
68 Uint32& UniformBufferBinding,
69 Uint32& SamplerBinding,
70 Uint32& ImageBinding,
71 Uint32& StorageBufferBinding);
72
73 struct GLResourceAttribs
74 {
75 // clang-format off
76 /* 0 */ const Char* Name;
77 /* 8 */ const SHADER_TYPE ShaderStages;
78 /* 12 */ const SHADER_RESOURCE_TYPE ResourceType;
79 /* 16 */ const Uint32 Binding;
80 /* 20 */ Uint32 ArraySize;
81 /* 24 */ // End of data
82 // clang-format on
83
84 GLResourceAttribs(const Char* _Name,
85 SHADER_TYPE _ShaderStages,
86 SHADER_RESOURCE_TYPE _ResourceType,
87 Uint32 _Binding,
88 Uint32 _ArraySize) noexcept :
89 // clang-format off
90 Name {_Name },
91 ShaderStages {_ShaderStages},
92 ResourceType {_ResourceType},
93 Binding {_Binding },
94 ArraySize {_ArraySize }
95 // clang-format on
96 {
97 VERIFY(_ShaderStages != SHADER_TYPE_UNKNOWN, "At least one shader stage must be specified");
98 VERIFY(_ResourceType != SHADER_RESOURCE_TYPE_UNKNOWN, "Unknown shader resource type");
99 VERIFY(_ArraySize >= 1, "Array size must be greater than 1");
100 }
101
102 GLResourceAttribs(const GLResourceAttribs& Attribs,
103 StringPool& NamesPool) noexcept :
104 // clang-format off
105 GLResourceAttribs
106 {
107 NamesPool.CopyString(Attribs.Name),
108 Attribs.ShaderStages,
109 Attribs.ResourceType,
110 Attribs.Binding,
111 Attribs.ArraySize
112 }
113 // clang-format on
114 {
115 }
116
117 bool IsCompatibleWith(const GLResourceAttribs& Var)const
118 {
119 // clang-format off
120 return ShaderStages == Var.ShaderStages &&
121 ResourceType == Var.ResourceType &&
122 Binding == Var.Binding &&
123 ArraySize == Var.ArraySize;
124 // clang-format on
125 }
126
127 size_t GetHash() const
128 {
129 return ComputeHash(static_cast<Uint32>(ShaderStages), static_cast<Uint32>(ResourceType), Binding, ArraySize);
130 }
131
132 String GetPrintName(Uint32 ArrayInd) const
133 {
134 VERIFY_EXPR(ArrayInd < ArraySize);
135 if (ArraySize > 1)
136 return String(Name) + '[' + std::to_string(ArrayInd) + ']';
137 else
138 return Name;
139 }
140
141 ShaderResourceDesc GetResourceDesc() const
142 {
143 ShaderResourceDesc ResourceDesc;
144 ResourceDesc.Name = Name;
145 ResourceDesc.ArraySize = ArraySize;
146 ResourceDesc.Type = ResourceType;
147 return ResourceDesc;
148 }
149
150 RESOURCE_DIMENSION GetResourceDimension() const
151 {
152 return RESOURCE_DIM_UNDEFINED;
153 }
154
155 bool IsMultisample() const
156 {
157 return false;
158 }
159 };
160
161 struct UniformBufferInfo final : GLResourceAttribs
162 {
163 // clang-format off
164 UniformBufferInfo (const UniformBufferInfo&) = delete;
165 UniformBufferInfo& operator= (const UniformBufferInfo&) = delete;
166 UniformBufferInfo ( UniformBufferInfo&&) = default;
167 UniformBufferInfo& operator= ( UniformBufferInfo&&) = delete;
168
169 UniformBufferInfo(const Char* _Name,
170 SHADER_TYPE _ShaderStages,
171 SHADER_RESOURCE_TYPE _ResourceType,
172 Uint32 _Binding,
173 Uint32 _ArraySize,
174 GLuint _UBIndex)noexcept :
175 GLResourceAttribs{_Name, _ShaderStages, _ResourceType, _Binding, _ArraySize},
176 UBIndex {_UBIndex}
177 {}
178
179 UniformBufferInfo(const UniformBufferInfo& UB,
180 StringPool& NamesPool)noexcept :
181 GLResourceAttribs{UB, NamesPool},
182 UBIndex {UB.UBIndex }
183 {}
184 // clang-format on
185
186 bool IsCompatibleWith(const UniformBufferInfo& UB) const
187 {
188 return UBIndex == UB.UBIndex &&
189 GLResourceAttribs::IsCompatibleWith(UB);
190 }
191
192 size_t GetHash() const
193 {
194 return ComputeHash(UBIndex, GLResourceAttribs::GetHash());
195 }
196
197 const GLuint UBIndex;
198 };
199 static_assert((sizeof(UniformBufferInfo) % sizeof(void*)) == 0, "sizeof(UniformBufferInfo) must be multiple of sizeof(void*)");
200
201
202 struct SamplerInfo final : GLResourceAttribs
203 {
204 // clang-format off
205 SamplerInfo (const SamplerInfo&) = delete;
206 SamplerInfo& operator= (const SamplerInfo&) = delete;
207 SamplerInfo ( SamplerInfo&&) = default;
208 SamplerInfo& operator= ( SamplerInfo&&) = delete;
209
210 SamplerInfo(const Char* _Name,
211 SHADER_TYPE _ShaderStages,
212 SHADER_RESOURCE_TYPE _ResourceType,
213 Uint32 _Binding,
214 Uint32 _ArraySize,
215 GLint _Location,
216 GLenum _SamplerType)noexcept :
217 GLResourceAttribs{_Name, _ShaderStages, _ResourceType, _Binding, _ArraySize},
218 Location {_Location },
219 SamplerType {_SamplerType}
220 {}
221
222 SamplerInfo(const SamplerInfo& Sam,
223 StringPool& NamesPool)noexcept :
224 GLResourceAttribs{Sam, NamesPool},
225 Location {Sam.Location },
226 SamplerType {Sam.SamplerType}
227 {}
228
229 bool IsCompatibleWith(const SamplerInfo& Sam)const
230 {
231 return Location == Sam.Location &&
232 SamplerType == Sam.SamplerType &&
233 GLResourceAttribs::IsCompatibleWith(Sam);
234 }
235 // clang-format on
236
237 size_t GetHash() const
238 {
239 return ComputeHash(Location, SamplerType, GLResourceAttribs::GetHash());
240 }
241
242 const GLint Location;
243 const GLenum SamplerType;
244 };
245 static_assert((sizeof(SamplerInfo) % sizeof(void*)) == 0, "sizeof(SamplerInfo) must be multiple of sizeof(void*)");
246
247
248 struct ImageInfo final : GLResourceAttribs
249 {
250 // clang-format off
251 ImageInfo (const ImageInfo&) = delete;
252 ImageInfo& operator= (const ImageInfo&) = delete;
253 ImageInfo ( ImageInfo&&) = default;
254 ImageInfo& operator= ( ImageInfo&&) = delete;
255
256 ImageInfo(const Char* _Name,
257 SHADER_TYPE _ShaderStages,
258 SHADER_RESOURCE_TYPE _ResourceType,
259 Uint32 _Binding,
260 Uint32 _ArraySize,
261 GLint _Location,
262 GLenum _ImageType)noexcept :
263 GLResourceAttribs{_Name, _ShaderStages, _ResourceType, _Binding, _ArraySize},
264 Location {_Location },
265 ImageType {_ImageType}
266 {}
267
268 ImageInfo(const ImageInfo& Img,
269 StringPool& NamesPool)noexcept :
270 GLResourceAttribs{Img, NamesPool},
271 Location {Img.Location },
272 ImageType {Img.ImageType}
273 {}
274
275 bool IsCompatibleWith(const ImageInfo& Img)const
276 {
277 return Location == Img.Location &&
278 ImageType == Img.ImageType &&
279 GLResourceAttribs::IsCompatibleWith(Img);
280 }
281 // clang-format on
282
283 size_t GetHash() const
284 {
285 return ComputeHash(Location, ImageType, GLResourceAttribs::GetHash());
286 }
287
288 const GLint Location;
289 const GLenum ImageType;
290 };
291 static_assert((sizeof(ImageInfo) % sizeof(void*)) == 0, "sizeof(ImageInfo) must be multiple of sizeof(void*)");
292
293
294 struct StorageBlockInfo final : GLResourceAttribs
295 {
296 // clang-format off
297 StorageBlockInfo (const StorageBlockInfo&) = delete;
298 StorageBlockInfo& operator= (const StorageBlockInfo&) = delete;
299 StorageBlockInfo ( StorageBlockInfo&&) = default;
300 StorageBlockInfo& operator= ( StorageBlockInfo&&) = delete;
301
302 StorageBlockInfo(const Char* _Name,
303 SHADER_TYPE _ShaderStages,
304 SHADER_RESOURCE_TYPE _ResourceType,
305 Uint32 _Binding,
306 Uint32 _ArraySize,
307 GLint _SBIndex)noexcept :
308 GLResourceAttribs{_Name, _ShaderStages, _ResourceType, _Binding, _ArraySize},
309 SBIndex {_SBIndex}
310 {}
311
312 StorageBlockInfo(const StorageBlockInfo& SB,
313 StringPool& NamesPool)noexcept :
314 GLResourceAttribs{SB, NamesPool},
315 SBIndex {SB.SBIndex}
316 {}
317
318 bool IsCompatibleWith(const StorageBlockInfo& SB)const
319 {
320 return SBIndex == SB.SBIndex &&
321 GLResourceAttribs::IsCompatibleWith(SB);
322 }
323 // clang-format on
324
325 size_t GetHash() const
326 {
327 return ComputeHash(SBIndex, GLResourceAttribs::GetHash());
328 }
329
330 const GLint SBIndex;
331 };
332 static_assert((sizeof(StorageBlockInfo) % sizeof(void*)) == 0, "sizeof(StorageBlockInfo) must be multiple of sizeof(void*)");
333
334
335 // clang-format off
336 Uint32 GetNumUniformBuffers()const { return m_NumUniformBuffers; }
337 Uint32 GetNumSamplers() const { return m_NumSamplers; }
338 Uint32 GetNumImages() const { return m_NumImages; }
339 Uint32 GetNumStorageBlocks() const { return m_NumStorageBlocks; }
340 // clang-format on
341
342 UniformBufferInfo& GetUniformBuffer(Uint32 Index)
343 {
344 VERIFY(Index < m_NumUniformBuffers, "Uniform buffer index (", Index, ") is out of range");
345 return m_UniformBuffers[Index];
346 }
347
348 SamplerInfo& GetSampler(Uint32 Index)
349 {
350 VERIFY(Index < m_NumSamplers, "Sampler index (", Index, ") is out of range");
351 return m_Samplers[Index];
352 }
353
354 ImageInfo& GetImage(Uint32 Index)
355 {
356 VERIFY(Index < m_NumImages, "Image index (", Index, ") is out of range");
357 return m_Images[Index];
358 }
359
360 StorageBlockInfo& GetStorageBlock(Uint32 Index)
361 {
362 VERIFY(Index < m_NumStorageBlocks, "Storage block index (", Index, ") is out of range");
363 return m_StorageBlocks[Index];
364 }
365
366
367 const UniformBufferInfo& GetUniformBuffer(Uint32 Index) const
368 {
369 VERIFY(Index < m_NumUniformBuffers, "Uniform buffer index (", Index, ") is out of range");
370 return m_UniformBuffers[Index];
371 }
372
373 const SamplerInfo& GetSampler(Uint32 Index) const
374 {
375 VERIFY(Index < m_NumSamplers, "Sampler index (", Index, ") is out of range");
376 return m_Samplers[Index];
377 }
378
379 const ImageInfo& GetImage(Uint32 Index) const
380 {
381 VERIFY(Index < m_NumImages, "Image index (", Index, ") is out of range");
382 return m_Images[Index];
383 }
384
385 const StorageBlockInfo& GetStorageBlock(Uint32 Index) const
386 {
387 VERIFY(Index < m_NumStorageBlocks, "Storage block index (", Index, ") is out of range");
388 return m_StorageBlocks[Index];
389 }
390
391 Uint32 GetVariableCount() const
392 {
393 return m_NumUniformBuffers + m_NumSamplers + m_NumImages + m_NumStorageBlocks;
394 }
395
396 ShaderResourceDesc GetResourceDesc(Uint32 Index) const;
397
398 bool IsCompatibleWith(const GLProgramResources& Res) const;
399 size_t GetHash() const;
400
401 SHADER_TYPE GetShaderStages() const { return m_ShaderStages; }
402
403 template <typename THandleUB,
404 typename THandleSampler,
405 typename THandleImg,
406 typename THandleSB>
407 void ProcessConstResources(THandleUB HandleUB,
408 THandleSampler HandleSampler,
409 THandleImg HandleImg,
410 THandleSB HandleSB,
411 const PipelineResourceLayoutDesc* pResourceLayout = nullptr,
412 const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes = nullptr,
413 Uint32 NumAllowedTypes = 0) const
414 {
415 const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes);
416
417 auto CheckResourceType = [&](const char* Name) //
418 {
419 if (pResourceLayout == nullptr)
420 return true;
421 else
422 {
423 auto VarType = GetShaderVariableType(m_ShaderStages, Name, *pResourceLayout);
424 return IsAllowedType(VarType, AllowedTypeBits);
425 }
426 };
427
428 for (Uint32 ub = 0; ub < m_NumUniformBuffers; ++ub)
429 {
430 const auto& UB = GetUniformBuffer(ub);
431 if (CheckResourceType(UB.Name))
432 HandleUB(UB);
433 }
434
435 for (Uint32 s = 0; s < m_NumSamplers; ++s)
436 {
437 const auto& Sam = GetSampler(s);
438 if (CheckResourceType(Sam.Name))
439 HandleSampler(Sam);
440 }
441
442 for (Uint32 img = 0; img < m_NumImages; ++img)
443 {
444 const auto& Img = GetImage(img);
445 if (CheckResourceType(Img.Name))
446 HandleImg(Img);
447 }
448
449 for (Uint32 sb = 0; sb < m_NumStorageBlocks; ++sb)
450 {
451 const auto& SB = GetStorageBlock(sb);
452 if (CheckResourceType(SB.Name))
453 HandleSB(SB);
454 }
455 }
456
457 template <typename THandleUB,
458 typename THandleSampler,
459 typename THandleImg,
460 typename THandleSB>
461 void ProcessResources(THandleUB HandleUB,
462 THandleSampler HandleSampler,
463 THandleImg HandleImg,
464 THandleSB HandleSB)
465 {
466 for (Uint32 ub = 0; ub < m_NumUniformBuffers; ++ub)
467 HandleUB(GetUniformBuffer(ub));
468
469 for (Uint32 s = 0; s < m_NumSamplers; ++s)
470 HandleSampler(GetSampler(s));
471
472 for (Uint32 img = 0; img < m_NumImages; ++img)
473 HandleImg(GetImage(img));
474
475 for (Uint32 sb = 0; sb < m_NumStorageBlocks; ++sb)
476 HandleSB(GetStorageBlock(sb));
477 }
478
479 struct ResourceCounters
480 {
481 Uint32 NumUBs = 0;
482 Uint32 NumSamplers = 0;
483 Uint32 NumImages = 0;
484 Uint32 NumStorageBlocks = 0;
485 };
486 void CountResources(const PipelineResourceLayoutDesc& ResourceLayout,
487 const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
488 Uint32 NumAllowedTypes,
489 ResourceCounters& Counters) const;
490
491
492 private:
493 void AllocateResources(std::vector<UniformBufferInfo>& UniformBlocks,
494 std::vector<SamplerInfo>& Samplers,
495 std::vector<ImageInfo>& Images,
496 std::vector<StorageBlockInfo>& StorageBlocks);
497
498 // clang-format off
499 // There could be more than one stage if using non-separable programs
500 SHADER_TYPE m_ShaderStages = SHADER_TYPE_UNKNOWN;
501
502 // Memory layout:
503 //
504 // | Uniform buffers | Samplers | Images | Storage Blocks | String Pool Data |
505 //
506
507 UniformBufferInfo* m_UniformBuffers = nullptr;
508 SamplerInfo* m_Samplers = nullptr;
509 ImageInfo* m_Images = nullptr;
510 StorageBlockInfo* m_StorageBlocks = nullptr;
511
512 Uint32 m_NumUniformBuffers = 0;
513 Uint32 m_NumSamplers = 0;
514 Uint32 m_NumImages = 0;
515 Uint32 m_NumStorageBlocks = 0;
516 // clang-format on
517 // When adding new member DO NOT FORGET TO UPDATE GLProgramResources( GLProgramResources&& ProgramResources )!!!
518 };
519
520 } // namespace Diligent
515515 # define GL_ARB_shader_image_load_store 1
516516 #endif
517517
518 #ifndef GL_MAX_IMAGE_UNITS
519 # define GL_MAX_IMAGE_UNITS 0x8F38
520 #endif
521
518522 #ifndef GL_ARB_shader_storage_buffer_object
519523 # define GL_ARB_shader_storage_buffer_object 1
520524 #endif
0 /*
1 * Copyright 2019-2021 Diligent Graphics LLC
2 * Copyright 2015-2019 Egor Yusov
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * In no event and under no legal theory, whether in tort (including negligence),
17 * contract, or otherwise, unless required by applicable law (such as deliberate
18 * and grossly negligent acts) or agreed to in writing, shall any Contributor be
19 * liable for any damages, including any direct, indirect, special, incidental,
20 * or consequential damages of any character arising as a result of this License or
21 * out of the use or inability to use the software (including but not limited to damages
22 * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
23 * all other commercial damages or losses), even if such Contributor has been advised
24 * of the possibility of such damages.
25 */
26
27 #pragma once
28
29 /// \file
30 /// Declaration of Diligent::PipelineResourceSignatureGLImpl class
31
32 #include <array>
33
34 #include "PipelineResourceSignatureBase.hpp"
35 #include "ShaderResourceCacheGL.hpp"
36 #include "ShaderResourcesGL.hpp"
37
38 namespace Diligent
39 {
40 class RenderDeviceGLImpl;
41 class ShaderVariableGL;
42
43 enum BINDING_RANGE : Uint32
44 {
45 BINDING_RANGE_UNIFORM_BUFFER = 0,
46 BINDING_RANGE_TEXTURE,
47 BINDING_RANGE_IMAGE,
48 BINDING_RANGE_STORAGE_BUFFER,
49 BINDING_RANGE_COUNT,
50 BINDING_RANGE_UNKNOWN = ~0u
51 };
52 BINDING_RANGE PipelineResourceToBindingRange(const PipelineResourceDesc& Desc);
53 const char* GetBindingRangeName(BINDING_RANGE Range);
54
55
56 /// Implementation of the Diligent::PipelineResourceSignatureGLImpl class
57 class PipelineResourceSignatureGLImpl final : public PipelineResourceSignatureBase<IPipelineResourceSignature, RenderDeviceGLImpl>
58 {
59 public:
60 using TPipelineResourceSignatureBase = PipelineResourceSignatureBase<IPipelineResourceSignature, RenderDeviceGLImpl>;
61
62 PipelineResourceSignatureGLImpl(IReferenceCounters* pRefCounters,
63 RenderDeviceGLImpl* pDevice,
64 const PipelineResourceSignatureDesc& Desc,
65 bool bIsDeviceInternal = false);
66 ~PipelineResourceSignatureGLImpl();
67
68 // sizeof(ResourceAttribs) == 8, x64
69 struct ResourceAttribs
70 {
71 private:
72 static constexpr Uint32 _SamplerIndBits = 31;
73 static constexpr Uint32 _SamplerAssignedBits = 1;
74
75 public:
76 static constexpr Uint32 InvalidCacheOffset = ~0u;
77 static constexpr Uint32 InvalidSamplerInd = (1u << _SamplerIndBits) - 1;
78
79 // clang-format off
80 const Uint32 CacheOffset; // SRB and Signature has the same cache offsets for static resources.
81 // Binding = m_FirstBinding[Range] + CacheOffset
82 const Uint32 SamplerInd : _SamplerIndBits; // ImtblSamplerAssigned == true: index of the immutable sampler in m_ImmutableSamplers.
83 // ImtblSamplerAssigned == false: index of the assigned sampler in m_Desc.Resources.
84 const Uint32 ImtblSamplerAssigned : _SamplerAssignedBits; // Immutable sampler flag
85 // clang-format on
86
87 ResourceAttribs(Uint32 _CacheOffset,
88 Uint32 _SamplerInd,
89 bool _ImtblSamplerAssigned) noexcept :
90 // clang-format off
91 CacheOffset {_CacheOffset },
92 SamplerInd {_SamplerInd },
93 ImtblSamplerAssigned{_ImtblSamplerAssigned ? 1u : 0u}
94 // clang-format on
95 {
96 VERIFY(SamplerInd == _SamplerInd, "Sampler index (", _SamplerInd, ") exceeds maximum representable value");
97 VERIFY(!_ImtblSamplerAssigned || SamplerInd != InvalidSamplerInd, "Immutable sampler assigned, but sampler index is not valid");
98 }
99
100 bool IsSamplerAssigned() const { return SamplerInd != InvalidSamplerInd; }
101 bool IsImmutableSamplerAssigned() const { return ImtblSamplerAssigned != 0; }
102 };
103
104 const ResourceAttribs& GetResourceAttribs(Uint32 ResIndex) const
105 {
106 VERIFY_EXPR(ResIndex < m_Desc.NumResources);
107 return m_pResourceAttribs[ResIndex];
108 }
109
110 const PipelineResourceDesc& GetResourceDesc(Uint32 ResIndex) const
111 {
112 VERIFY_EXPR(ResIndex < m_Desc.NumResources);
113 return m_Desc.Resources[ResIndex];
114 }
115
116 bool HasDynamicResources() const
117 {
118 auto IndexRange = GetResourceIndexRange(SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC);
119 return IndexRange.second > IndexRange.first;
120 }
121
122 using TBindings = std::array<Uint32, BINDING_RANGE_COUNT>;
123
124 void ApplyBindings(GLObjectWrappers::GLProgramObj& GLProgram,
125 class GLContextState& State,
126 SHADER_TYPE Stages,
127 const TBindings& Bindings) const;
128
129 void AddBindings(TBindings& Bindings) const;
130
131 /// Implementation of IPipelineResourceSignature::CreateShaderResourceBinding.
132 virtual void DILIGENT_CALL_TYPE CreateShaderResourceBinding(IShaderResourceBinding** ppShaderResourceBinding,
133 bool InitStaticResources) override final;
134
135 /// Implementation of IPipelineResourceSignature::GetStaticVariableByName.
136 virtual IShaderResourceVariable* DILIGENT_CALL_TYPE GetStaticVariableByName(SHADER_TYPE ShaderType, const Char* Name) override final;
137
138 /// Implementation of IPipelineResourceSignature::GetStaticVariableByIndex.
139 virtual IShaderResourceVariable* DILIGENT_CALL_TYPE GetStaticVariableByIndex(SHADER_TYPE ShaderType, Uint32 Index) override final;
140
141 /// Implementation of IPipelineResourceSignature::GetStaticVariableCount.
142 virtual Uint32 DILIGENT_CALL_TYPE GetStaticVariableCount(SHADER_TYPE ShaderType) const override final;
143
144 /// Implementation of IPipelineResourceSignature::BindStaticResources.
145 virtual void DILIGENT_CALL_TYPE BindStaticResources(Uint32 ShaderFlags,
146 IResourceMapping* pResourceMapping,
147 Uint32 Flags) override final;
148
149 /// Implementation of IPipelineResourceSignature::IsCompatibleWith.
150 virtual bool DILIGENT_CALL_TYPE IsCompatibleWith(const IPipelineResourceSignature* pPRS) const override final
151 {
152 if (pPRS == nullptr)
153 {
154 return GetHash() == 0;
155 }
156 return IsCompatibleWith(*ValidatedCast<const PipelineResourceSignatureGLImpl>(pPRS));
157 }
158
159 /// Implementation of IPipelineResourceSignature::InitializeStaticSRBResources.
160 virtual void DILIGENT_CALL_TYPE InitializeStaticSRBResources(IShaderResourceBinding* pSRB) const override final;
161
162 bool IsCompatibleWith(const PipelineResourceSignatureGLImpl& Other) const;
163
164 bool IsIncompatibleWith(const PipelineResourceSignatureGLImpl& Other) const
165 {
166 return GetHash() != Other.GetHash() || m_BindingCount != Other.m_BindingCount;
167 }
168
169 void InitSRBResourceCache(ShaderResourceCacheGL& ResourceCache) const;
170
171 #ifdef DILIGENT_DEVELOPMENT
172 /// Verifies committed resource attribs using the SPIRV resource attributes from the PSO.
173 bool DvpValidateCommittedResource(const ShaderResourcesGL::GLResourceAttribs& GLAttribs,
174 RESOURCE_DIMENSION ResourceDim,
175 bool IsMultisample,
176 Uint32 ResIndex,
177 const ShaderResourceCacheGL& ResourceCache,
178 const char* ShaderName,
179 const char* PSOName) const;
180 #endif
181
182 private:
183 PipelineResourceSignatureGLImpl(IReferenceCounters* pRefCounters,
184 RenderDeviceGLImpl* pDevice,
185 const PipelineResourceSignatureDesc& Desc,
186 bool bIsDeviceInternal,
187 int Internal);
188
189 // Copies static resources from the static resource cache to the destination cache
190 void CopyStaticResources(ShaderResourceCacheGL& ResourceCache) const;
191
192 void CreateLayouts();
193
194 void Destruct();
195
196 size_t CalculateHash() const;
197
198 private:
199 TBindings m_BindingCount = {};
200
201 ResourceAttribs* m_pResourceAttribs = nullptr; // [m_Desc.NumResources]
202
203 // Resource cache for static resource variables only
204 ShaderResourceCacheGL* m_pStaticResCache = nullptr;
205
206 ShaderVariableGL* m_StaticVarsMgrs = nullptr; // [GetNumStaticResStages()]
207
208 using SamplerPtr = RefCntAutoPtr<ISampler>;
209 SamplerPtr* m_ImmutableSamplers = nullptr; // [m_Desc.NumImmutableSamplers]
210 };
211
212
213 __forceinline void PipelineResourceSignatureGLImpl::AddBindings(TBindings& Bindings) const
214 {
215 for (Uint32 i = 0; i < Bindings.size(); ++i)
216 {
217 Bindings[i] += m_BindingCount[i];
218 }
219 }
220
221 } // namespace Diligent
3333 #include "GLObjectWrapper.hpp"
3434 #include "GLContext.hpp"
3535 #include "RenderDeviceGLImpl.hpp"
36 #include "GLProgramResources.hpp"
37 #include "GLPipelineResourceLayout.hpp"
38 #include "GLProgramResourceCache.hpp"
36 #include "ShaderVariableGL.hpp"
3937 #include "ShaderGLImpl.hpp"
38 #include "PipelineResourceSignatureGLImpl.hpp"
4039
4140 namespace Diligent
4241 {
6261 /// Queries the specific interface, see IObject::QueryInterface() for details
6362 virtual void DILIGENT_CALL_TYPE QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override;
6463
65 /// Implementation of IPipelineState::BindStaticResources() in OpenGL backend.
66 virtual void DILIGENT_CALL_TYPE BindStaticResources(Uint32 ShaderFlags,
67 IResourceMapping* pResourceMapping,
68 Uint32 Flags) override final;
64 /// Implementation of IPipelineState::GetResourceSignatureCount() in OpenGL backend.
65 virtual Uint32 DILIGENT_CALL_TYPE GetResourceSignatureCount() const override final { return m_SignatureCount; }
6966
70 /// Implementation of IPipelineState::GetStaticVariableCount() in OpenGL backend.
71 virtual Uint32 DILIGENT_CALL_TYPE GetStaticVariableCount(SHADER_TYPE ShaderType) const override final;
72
73 /// Implementation of IPipelineState::GetStaticVariableByName() in OpenGL backend.
74 virtual IShaderResourceVariable* DILIGENT_CALL_TYPE GetStaticVariableByName(SHADER_TYPE ShaderType, const Char* Name) override final;
75
76 /// Implementation of IPipelineState::GetStaticVariableByIndex() in OpenGL backend.
77 virtual IShaderResourceVariable* DILIGENT_CALL_TYPE GetStaticVariableByIndex(SHADER_TYPE ShaderType, Uint32 Index) override final;
78
79 /// Implementation of IPipelineState::CreateShaderResourceBinding() in OpenGL backend.
80 virtual void DILIGENT_CALL_TYPE CreateShaderResourceBinding(IShaderResourceBinding** ppShaderResourceBinding,
81 bool InitStaticResources) override final;
67 /// Implementation of IPipelineState::GetResourceSignature() in OpenGL backend.
68 virtual IPipelineResourceSignature* DILIGENT_CALL_TYPE GetResourceSignature(Uint32 Index) const override final
69 {
70 VERIFY_EXPR(Index < m_SignatureCount);
71 return m_Signatures[Index].RawPtr<IPipelineResourceSignature>();
72 }
8273
8374 /// Implementation of IPipelineState::IsCompatibleWith() in OpenGL backend.
8475 virtual bool DILIGENT_CALL_TYPE IsCompatibleWith(const IPipelineState* pPSO) const override final;
8576
8677 void CommitProgram(GLContextState& State);
8778
88 void InitializeSRBResourceCache(GLProgramResourceCache& ResourceCache) const;
79 Uint32 GetSignatureCount() const { return m_SignatureCount; }
8980
90 const GLPipelineResourceLayout& GetResourceLayout() const { return m_ResourceLayout; }
91 const GLPipelineResourceLayout& GetStaticResourceLayout() const { return m_StaticResourceLayout; }
92 const GLProgramResourceCache& GetStaticResourceCache() const { return m_StaticResourceCache; }
81 PipelineResourceSignatureGLImpl* GetSignature(Uint32 index) const
82 {
83 VERIFY_EXPR(index < m_SignatureCount);
84 return m_Signatures[index].RawPtr<PipelineResourceSignatureGLImpl>();
85 }
86
87 #ifdef DILIGENT_DEVELOPMENT
88 using TBindings = PipelineResourceSignatureGLImpl::TBindings;
89 void DvpVerifySRBResources(class ShaderResourceBindingGLImpl* pSRBs[], const TBindings BoundResOffsets[], Uint32 NumSRBs) const;
90 #endif
9391
9492 private:
93 using ShaderStageInfo = ShaderGLImpl::ShaderStageInfo;
94 using TShaderStages = std::vector<ShaderStageInfo>;
95
9596 GLObjectWrappers::GLPipelineObj& GetGLProgramPipeline(GLContext::NativeGLContextType Context);
9697
97 void InitImmutableSamplersInResourceCache(const GLPipelineResourceLayout& ResourceLayout, GLProgramResourceCache& Cache) const;
98 template <typename PSOCreateInfoType>
99 void InitInternalObjects(const PSOCreateInfoType& CreateInfo, const TShaderStages& ShaderStages);
98100
99 template <typename PSOCreateInfoType>
100 void Initialize(const PSOCreateInfoType& CreateInfo, std::vector<ShaderGLImpl*>& Shaders);
101 void InitResourceLayouts(const PipelineStateCreateInfo& CreateInfo,
102 const TShaderStages& ShaderStages,
103 SHADER_TYPE ActiveStages);
101104
102 void InitResourceLayouts(std::vector<ShaderGLImpl*>& Shaders,
103 FixedLinearAllocator& MemPool);
105 void CreateDefaultSignature(const PipelineStateCreateInfo& CreateInfo,
106 const TShaderStages& ShaderStages,
107 SHADER_TYPE ActiveStages,
108 IPipelineResourceSignature** ppSignature);
104109
105110 void Destruct();
106111
112 SHADER_TYPE GetShaderStageType(Uint32 Index) const;
113 Uint32 GetNumShaderStages() const { return m_NumPrograms; }
114
115 #ifdef DILIGENT_DEVELOPMENT
116 struct ResourceAttribution
117 {
118 static constexpr Uint32 InvalidSignatureIndex = ~0u;
119 static constexpr Uint32 InvalidResourceIndex = PipelineResourceSignatureGLImpl::InvalidResourceIndex;
120 static constexpr Uint32 InvalidSamplerIndex = InvalidImmutableSamplerIndex;
121
122 const PipelineResourceSignatureGLImpl* pSignature = nullptr;
123
124 Uint32 SignatureIndex = InvalidSignatureIndex;
125 Uint32 ResourceIndex = InvalidResourceIndex;
126 Uint32 ImmutableSamplerIndex = InvalidSamplerIndex;
127
128 ResourceAttribution() noexcept {}
129 ResourceAttribution(const PipelineResourceSignatureGLImpl* _pSignature,
130 Uint32 _SignatureIndex,
131 Uint32 _ResourceIndex,
132 Uint32 _ImmutableSamplerIndex = InvalidResourceIndex) noexcept :
133 pSignature{_pSignature},
134 SignatureIndex{_SignatureIndex},
135 ResourceIndex{_ResourceIndex},
136 ImmutableSamplerIndex{_ImmutableSamplerIndex}
137 {
138 VERIFY_EXPR(pSignature == nullptr || pSignature->GetDesc().BindingIndex == SignatureIndex);
139 VERIFY_EXPR((ResourceIndex == InvalidResourceIndex) || (ImmutableSamplerIndex == InvalidSamplerIndex));
140 }
141
142 explicit operator bool() const
143 {
144 return SignatureIndex != InvalidSignatureIndex && (ResourceIndex != InvalidResourceIndex || ImmutableSamplerIndex != InvalidSamplerIndex);
145 }
146
147 bool IsImmutableSampler() const
148 {
149 return operator bool() && ImmutableSamplerIndex != InvalidSamplerIndex;
150 }
151 };
152 ResourceAttribution GetResourceAttribution(const char* Name, SHADER_TYPE Stage) const;
153
154 void DvpValidateShaderResources(const std::shared_ptr<const ShaderResourcesGL>& pShaderResources, const char* ShaderName, SHADER_TYPE ShaderStages);
155 #endif
156
157 private:
107158 // Linked GL programs for every shader stage. Every pipeline needs to have its own programs
108 // because resource bindings assigned by GLProgramResources::LoadUniforms depend on other
159 // because resource bindings assigned by PipelineResourceSignatureGLImpl::ApplyBindings depend on other
109160 // shader stages.
110161 using GLProgramObj = GLObjectWrappers::GLProgramObj;
111 GLProgramObj* m_GLPrograms = nullptr; // [m_NumShaderStages]
162 GLProgramObj* m_GLPrograms = nullptr; // [m_NumPrograms]
112163
113164 ThreadingTools::LockFlag m_ProgPipelineLockFlag;
114165
115166 std::vector<std::pair<GLContext::NativeGLContextType, GLObjectWrappers::GLPipelineObj>> m_GLProgPipelines;
116167
117 // Resource layout that keeps variables of all types, but does not reference a
118 // resource cache.
119 // This layout is used by SRB objects to initialize only mutable and dynamic variables and by
120 // DeviceContextGLImpl::BindProgramResources to verify resource bindings.
121 GLPipelineResourceLayout m_ResourceLayout;
168 using SignatureArrayType = std::array<RefCntAutoPtr<PipelineResourceSignatureGLImpl>, MAX_RESOURCE_SIGNATURES>;
169 SignatureArrayType m_Signatures = {};
170 Uint8 m_SignatureCount = 0;
122171
123 // Resource layout that only keeps static variables
124 GLPipelineResourceLayout m_StaticResourceLayout;
125 // Resource cache for static resource variables only
126 GLProgramResourceCache m_StaticResourceCache;
172 Uint8 m_NumPrograms = 0;
173 bool m_IsProgramPipelineSupported = false;
174 std::array<SHADER_TYPE, 5> m_ShaderTypes = {};
127175
128 // Program resources for all shader stages in the pipeline
129 GLProgramResources* m_ProgramResources = nullptr; // [m_NumShaderStages]
176 #ifdef DILIGENT_DEVELOPMENT
177 // Shader resources for all shaders in all shader stages in the pipeline.
178 std::vector<std::shared_ptr<const ShaderResourcesGL>> m_ShaderResources;
179 std::vector<String> m_ShaderNames;
130180
131 Uint32 m_TotalUniformBufferBindings = 0;
132 Uint32 m_TotalSamplerBindings = 0;
133 Uint32 m_TotalImageBindings = 0;
134 Uint32 m_TotalStorageBufferBindings = 0;
135
136 using SamplerPtr = RefCntAutoPtr<ISampler>;
137 SamplerPtr* m_ImmutableSamplers = nullptr; // [m_Desc.ResourceLayout.NumImmutableSamplers]
181 // Shader resource attributions for every resource in m_ShaderResources, in the same order.
182 std::vector<ResourceAttribution> m_ResourceAttibutions;
183 #endif
138184 };
139185
140186 } // namespace Diligent
130130 virtual void DILIGENT_CALL_TYPE CreateSBT(const ShaderBindingTableDesc& Desc,
131131 IShaderBindingTable** ppSBT) override final;
132132
133 /// Implementation of IRenderDevice::CreatePipelineResourceSignature() in OpenGL backend.
134 virtual void DILIGENT_CALL_TYPE CreatePipelineResourceSignature(const PipelineResourceSignatureDesc& Desc,
135 IPipelineResourceSignature** ppSignature) override final;
136
137 void CreatePipelineResourceSignature(const PipelineResourceSignatureDesc& Desc,
138 IPipelineResourceSignature** ppSignature,
139 bool IsDeviceInternal);
140
133141 /// Implementation of IRenderDeviceGL::CreateTextureFromGLHandle().
134142 virtual void DILIGENT_CALL_TYPE CreateTextureFromGLHandle(Uint32 GLHandle,
135143 Uint32 GLBindTarget,
165173 Uint64 GetCommandQueueMask() const { return Uint64{1}; }
166174
167175 void InitTexRegionRender();
176
177 struct DeviceLimits
178 {
179 GLint MaxUniformBlocks;
180 GLint MaxTextureUnits;
181 GLint MaxStorageBlock;
182 GLint MaxImagesUnits;
183 };
184 const DeviceLimits& GetDeviceLimits() const { return m_DeviceLimits; }
168185
169186 protected:
170187 friend class DeviceContextGLImpl;
198215 void FlagSupportedTexFormats();
199216
200217 int m_ShowDebugGLOutput = 1;
218
219 DeviceLimits m_DeviceLimits = {};
201220 };
202221
203222 } // namespace Diligent
3232 #include "RenderDevice.h"
3333 #include "GLObjectWrapper.hpp"
3434 #include "RenderDeviceGLImpl.hpp"
35 #include "GLProgramResources.hpp"
35 #include "ShaderResourcesGL.hpp"
3636
3737 namespace Diligent
3838 {
9191 /// Implementation of IShader::GetResource() in OpenGL backend.
9292 virtual void DILIGENT_CALL_TYPE GetResourceDesc(Uint32 Index, ShaderResourceDesc& ResourceDesc) const override final;
9393
94 static GLObjectWrappers::GLProgramObj LinkProgram(ShaderGLImpl** ppShaders, Uint32 NumShaders, bool IsSeparableProgram);
94 struct ShaderStageInfo
95 {
96 ShaderStageInfo(const ShaderGLImpl* _pShader);
97
98 SHADER_TYPE Type = SHADER_TYPE_UNKNOWN;
99 const ShaderGLImpl* pShader = nullptr;
100 };
101 static GLObjectWrappers::GLProgramObj LinkProgram(const ShaderStageInfo* pShaderStagess, Uint32 NumShaders, bool IsSeparableProgram);
102
103 const std::shared_ptr<const ShaderResourcesGL>& GetShaderResources() const { return m_pShaderResources; }
95104
96105 private:
97 GLObjectWrappers::GLShaderObj m_GLShaderObj;
98 GLProgramResources m_Resources;
106 GLObjectWrappers::GLShaderObj m_GLShaderObj;
107 std::shared_ptr<const ShaderResourcesGL> m_pShaderResources;
99108 };
100109
101110 } // namespace Diligent
3232 #include "ShaderResourceBindingGL.h"
3333 #include "RenderDeviceGL.h"
3434 #include "ShaderResourceBindingBase.hpp"
35 #include "GLProgramResources.hpp"
36 #include "ShaderBase.hpp"
37 #include "GLProgramResourceCache.hpp"
38 #include "GLPipelineResourceLayout.hpp"
35 #include "ShaderResourcesGL.hpp"
36 #include "ShaderResourceCacheGL.hpp"
37 #include "ShaderVariableGL.hpp"
38 #include "PipelineResourceSignatureGLImpl.hpp"
3939
4040 namespace Diligent
4141 {
4242
43 class PipelineStateGLImpl;
44
4543 /// Shader resource binding object implementation in OpenGL backend.
46 class ShaderResourceBindingGLImpl final : public ShaderResourceBindingBase<IShaderResourceBindingGL, PipelineStateGLImpl>
44 class ShaderResourceBindingGLImpl final : public ShaderResourceBindingBase<IShaderResourceBindingGL, PipelineResourceSignatureGLImpl>
4745 {
4846 public:
49 using TBase = ShaderResourceBindingBase<IShaderResourceBindingGL, PipelineStateGLImpl>;
47 using TBase = ShaderResourceBindingBase<IShaderResourceBindingGL, PipelineResourceSignatureGLImpl>;
5048
51 ShaderResourceBindingGLImpl(IReferenceCounters* pRefCounters,
52 PipelineStateGLImpl* pPSO,
53 GLProgramResources* ProgramResources,
54 Uint32 NumPrograms);
49 ShaderResourceBindingGLImpl(IReferenceCounters* pRefCounters,
50 PipelineResourceSignatureGLImpl* pPRS);
5551 ~ShaderResourceBindingGLImpl();
5652
5753 virtual void DILIGENT_CALL_TYPE QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final;
7066 /// Implementation of IShaderResourceBinding::GetVariableByIndex() in OpenGL backend.
7167 virtual IShaderResourceVariable* DILIGENT_CALL_TYPE GetVariableByIndex(SHADER_TYPE ShaderType, Uint32 Index) override final;
7268
73 /// Implementation of IShaderResourceBinding::InitializeStaticResources() in OpenGL backend.
74 virtual void DILIGENT_CALL_TYPE InitializeStaticResources(const IPipelineState* pPipelineState) override final;
75
76 const GLProgramResourceCache& GetResourceCache(PipelineStateGLImpl* pdbgPSO);
69 ShaderResourceCacheGL& GetResourceCache() { return m_ShaderResourceCache; }
70 ShaderResourceCacheGL const& GetResourceCache() const { return m_ShaderResourceCache; }
7771
7872 private:
79 // The resource layout only references mutable and dynamic variables
80 GLPipelineResourceLayout m_ResourceLayout;
73 void Destruct();
8174
8275 // The resource cache holds resource bindings for all variables
83 GLProgramResourceCache m_ResourceCache;
76 ShaderResourceCacheGL m_ShaderResourceCache;
8477
85 bool m_bIsStaticResourcesBound = false;
78 // The resource layout only references mutable and dynamic variables
79 ShaderVariableGL* m_pShaderVarMgrs = nullptr; // [GetNumShaders()]
8680 };
8781
8882 } // namespace Diligent
0 /*
1 * Copyright 2019-2021 Diligent Graphics LLC
2 * Copyright 2015-2019 Egor Yusov
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * In no event and under no legal theory, whether in tort (including negligence),
17 * contract, or otherwise, unless required by applicable law (such as deliberate
18 * and grossly negligent acts) or agreed to in writing, shall any Contributor be
19 * liable for any damages, including any direct, indirect, special, incidental,
20 * or consequential damages of any character arising as a result of this License or
21 * out of the use or inability to use the software (including but not limited to damages
22 * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
23 * all other commercial damages or losses), even if such Contributor has been advised
24 * of the possibility of such damages.
25 */
26
27 #pragma once
28
29 #include "BufferGLImpl.hpp"
30 #include "TextureBaseGL.hpp"
31 #include "SamplerGLImpl.hpp"
32
33 namespace Diligent
34 {
35
36 /// The class implements a cache that holds resources bound to a specific GL program
37 // All resources are stored in the continuous memory using the following layout:
38 //
39 // | Cached UBs | Cached Textures | Cached Images | Cached Storage Blocks |
40 // |----------------------------------------------------|--------------------------|---------------------------|
41 // | 0 | 1 | ... | UBCount-1 | 0 | 1 | ...| SmpCount-1 | 0 | 1 | ... | ImgCount-1 | 0 | 1 | ... | SBOCount-1 |
42 // -----------------------------------------------------------------------------------------------------------
43 //
44 class ShaderResourceCacheGL
45 {
46 public:
47 enum class CacheContentType : Uint8
48 {
49 Signature = 0, // The cache is used by the pipeline resource signature to hold static resources.
50 SRB = 1 // The cache is used by SRB to hold resources of all types (static, mutable, dynamic).
51 };
52
53 explicit ShaderResourceCacheGL(CacheContentType ContentType) noexcept :
54 m_ContentType{ContentType}
55 {}
56
57 ~ShaderResourceCacheGL();
58
59 // clang-format off
60 ShaderResourceCacheGL (const ShaderResourceCacheGL&) = delete;
61 ShaderResourceCacheGL& operator = (const ShaderResourceCacheGL&) = delete;
62 ShaderResourceCacheGL (ShaderResourceCacheGL&&) = delete;
63 ShaderResourceCacheGL& operator = (ShaderResourceCacheGL&&) = delete;
64 // clang-format on
65
66 /// Describes a resource bound to a uniform buffer or a shader storage block slot
67 struct CachedUB
68 {
69 /// Strong reference to the buffer
70 RefCntAutoPtr<BufferGLImpl> pBuffer;
71 };
72
73 /// Describes a resource bound to a sampler or an image slot
74 struct CachedResourceView
75 {
76 /// We keep strong reference to the view instead of the reference
77 /// to the texture or buffer because this is more efficient from
78 /// performance point of view: this avoids one pair of
79 /// AddStrongRef()/ReleaseStrongRef(). The view holds a strong reference
80 /// to the texture or the buffer, so it makes no difference.
81 RefCntAutoPtr<IDeviceObject> pView;
82
83 TextureBaseGL* pTexture = nullptr;
84 union
85 {
86 BufferGLImpl* pBuffer = nullptr; // When pTexture == nullptr
87 SamplerGLImpl* pSampler; // When pTexture != nullptr
88 };
89 CachedResourceView() noexcept {}
90
91 void Set(RefCntAutoPtr<TextureViewGLImpl>&& pTexView, bool SetSampler)
92 {
93 // Do not null out pSampler as it could've been initialized by PipelineStateGLImpl::InitializeSRBResourceCache!
94 // pSampler = nullptr;
95
96 // Avoid unnecessary virtual function calls
97 pTexture = pTexView ? ValidatedCast<TextureBaseGL>(pTexView->TextureViewGLImpl::GetTexture()) : nullptr;
98 if (pTexView && SetSampler)
99 {
100 pSampler = ValidatedCast<SamplerGLImpl>(pTexView->GetSampler());
101 }
102
103 pView.Attach(pTexView.Detach());
104 }
105
106 void Set(RefCntAutoPtr<BufferViewGLImpl>&& pBufView)
107 {
108 pTexture = nullptr;
109 // Avoid unnecessary virtual function calls
110 pBuffer = pBufView ? ValidatedCast<BufferGLImpl>(pBufView->BufferViewGLImpl::GetBuffer()) : nullptr;
111 pView.Attach(pBufView.Detach());
112 }
113 };
114
115 struct CachedSSBO
116 {
117 /// Strong reference to the buffer
118 RefCntAutoPtr<BufferViewGLImpl> pBufferView;
119 };
120
121
122 static size_t GetRequriedMemorySize(Uint32 UBCount, Uint32 TextureCount, Uint32 ImageCount, Uint32 SSBOCount);
123
124 void Initialize(Uint32 UBCount, Uint32 TextureCount, Uint32 ImageCount, Uint32 SSBOCount, IMemoryAllocator& MemAllocator);
125 void Destroy(IMemoryAllocator& MemAllocator);
126
127 void SetUniformBuffer(Uint32 CacheOffset, RefCntAutoPtr<BufferGLImpl>&& pBuff)
128 {
129 GetUB(CacheOffset).pBuffer = std::move(pBuff);
130 }
131
132 void SetTexture(Uint32 CacheOffset, RefCntAutoPtr<TextureViewGLImpl>&& pTexView, bool SetSampler)
133 {
134 GetTexture(CacheOffset).Set(std::move(pTexView), SetSampler);
135 }
136
137 void SetSampler(Uint32 CacheOffset, ISampler* pSampler)
138 {
139 GetTexture(CacheOffset).pSampler = ValidatedCast<SamplerGLImpl>(pSampler);
140 }
141
142 void SetTexelBuffer(Uint32 CacheOffset, RefCntAutoPtr<BufferViewGLImpl>&& pBuffView)
143 {
144 GetTexture(CacheOffset).Set(std::move(pBuffView));
145 }
146
147 void SetTexImage(Uint32 CacheOffset, RefCntAutoPtr<TextureViewGLImpl>&& pTexView)
148 {
149 GetImage(CacheOffset).Set(std::move(pTexView), false);
150 }
151
152 void SetBufImage(Uint32 CacheOffset, RefCntAutoPtr<BufferViewGLImpl>&& pBuffView)
153 {
154 GetImage(CacheOffset).Set(std::move(pBuffView));
155 }
156
157 void SetSSBO(Uint32 CacheOffset, RefCntAutoPtr<BufferViewGLImpl>&& pBuffView)
158 {
159 GetSSBO(CacheOffset).pBufferView = std::move(pBuffView);
160 }
161
162 void CopyTexture(Uint32 Binding, const CachedResourceView& SrcSam)
163 {
164 GetTexture(Binding) = SrcSam;
165 }
166
167 void CopyImage(Uint32 CacheOffset, const CachedResourceView& SrcImg)
168 {
169 GetImage(CacheOffset) = SrcImg;
170 }
171
172 bool IsUBBound(Uint32 CacheOffset) const
173 {
174 if (CacheOffset >= GetUBCount())
175 return false;
176
177 const auto& UB = GetConstUB(CacheOffset);
178 return UB.pBuffer;
179 }
180
181 bool IsTextureBound(Uint32 CacheOffset, bool dbgIsTextureView) const
182 {
183 if (CacheOffset >= GetTextureCount())
184 return false;
185
186 const auto& Texture = GetConstTexture(CacheOffset);
187 VERIFY_EXPR(dbgIsTextureView || Texture.pTexture == nullptr);
188 return Texture.pView;
189 }
190
191 bool IsImageBound(Uint32 CacheOffset, bool dbgIsTextureView) const
192 {
193 if (CacheOffset >= GetImageCount())
194 return false;
195
196 const auto& Image = GetConstImage(CacheOffset);
197 VERIFY_EXPR(dbgIsTextureView || Image.pTexture == nullptr);
198 return Image.pView;
199 }
200
201 bool IsSSBOBound(Uint32 CacheOffset) const
202 {
203 if (CacheOffset >= GetSSBOCount())
204 return false;
205
206 const auto& SSBO = GetConstSSBO(CacheOffset);
207 return SSBO.pBufferView;
208 }
209
210 // clang-format off
211 Uint32 GetUBCount() const { return (m_TexturesOffset - m_UBsOffset) / sizeof(CachedUB); }
212 Uint32 GetTextureCount() const { return (m_ImagesOffset - m_TexturesOffset) / sizeof(CachedResourceView); }
213 Uint32 GetImageCount() const { return (m_SSBOsOffset - m_ImagesOffset) / sizeof(CachedResourceView); }
214 Uint32 GetSSBOCount() const { return (m_MemoryEndOffset - m_SSBOsOffset) / sizeof(CachedSSBO); }
215 // clang-format on
216
217 const CachedUB& GetConstUB(Uint32 CacheOffset) const
218 {
219 VERIFY(CacheOffset < GetUBCount(), "Uniform buffer index (", CacheOffset, ") is out of range");
220 return reinterpret_cast<CachedUB*>(m_pResourceData + m_UBsOffset)[CacheOffset];
221 }
222
223 const CachedResourceView& GetConstTexture(Uint32 CacheOffset) const
224 {
225 VERIFY(CacheOffset < GetTextureCount(), "Texture index (", CacheOffset, ") is out of range");
226 return reinterpret_cast<CachedResourceView*>(m_pResourceData + m_TexturesOffset)[CacheOffset];
227 }
228
229 const CachedResourceView& GetConstImage(Uint32 CacheOffset) const
230 {
231 VERIFY(CacheOffset < GetImageCount(), "Image buffer index (", CacheOffset, ") is out of range");
232 return reinterpret_cast<CachedResourceView*>(m_pResourceData + m_ImagesOffset)[CacheOffset];
233 }
234
235 const CachedSSBO& GetConstSSBO(Uint32 CacheOffset) const
236 {
237 VERIFY(CacheOffset < GetSSBOCount(), "Shader storage block index (", CacheOffset, ") is out of range");
238 return reinterpret_cast<CachedSSBO*>(m_pResourceData + m_SSBOsOffset)[CacheOffset];
239 }
240
241 bool IsInitialized() const
242 {
243 return m_MemoryEndOffset != InvalidResourceOffset;
244 }
245
246 CacheContentType GetContentType() const { return m_ContentType; }
247
248 #ifdef DILIGENT_DEVELOPMENT
249 void SetStaticResourcesInitialized()
250 {
251 m_bStaticResourcesInitialized = true;
252 }
253 bool StaticResourcesInitialized() const { return m_bStaticResourcesInitialized; }
254 #endif
255
256 private:
257 CachedUB& GetUB(Uint32 CacheOffset)
258 {
259 return const_cast<CachedUB&>(const_cast<const ShaderResourceCacheGL*>(this)->GetConstUB(CacheOffset));
260 }
261
262 CachedResourceView& GetTexture(Uint32 CacheOffset)
263 {
264 return const_cast<CachedResourceView&>(const_cast<const ShaderResourceCacheGL*>(this)->GetConstTexture(CacheOffset));
265 }
266
267 CachedResourceView& GetImage(Uint32 CacheOffset)
268 {
269 return const_cast<CachedResourceView&>(const_cast<const ShaderResourceCacheGL*>(this)->GetConstImage(CacheOffset));
270 }
271
272 CachedSSBO& GetSSBO(Uint32 CacheOffset)
273 {
274 return const_cast<CachedSSBO&>(const_cast<const ShaderResourceCacheGL*>(this)->GetConstSSBO(CacheOffset));
275 }
276
277 static constexpr const Uint16 InvalidResourceOffset = 0xFFFF;
278 static constexpr const Uint16 m_UBsOffset = 0;
279
280 Uint16 m_TexturesOffset = InvalidResourceOffset;
281 Uint16 m_ImagesOffset = InvalidResourceOffset;
282 Uint16 m_SSBOsOffset = InvalidResourceOffset;
283 Uint16 m_MemoryEndOffset = InvalidResourceOffset;
284
285 Uint8* m_pResourceData = nullptr;
286
287 // Indicates what types of resources are stored in the cache
288 const CacheContentType m_ContentType;
289
290 #ifdef DILIGENT_DEBUG
291 IMemoryAllocator* m_pdbgMemoryAllocator = nullptr;
292 #endif
293 #ifdef DILIGENT_DEVELOPMENT
294 bool m_bStaticResourcesInitialized = false;
295 #endif
296 };
297
298 } // namespace Diligent
0 /*
1 * Copyright 2019-2021 Diligent Graphics LLC
2 * Copyright 2015-2019 Egor Yusov
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * In no event and under no legal theory, whether in tort (including negligence),
17 * contract, or otherwise, unless required by applicable law (such as deliberate
18 * and grossly negligent acts) or agreed to in writing, shall any Contributor be
19 * liable for any damages, including any direct, indirect, special, incidental,
20 * or consequential damages of any character arising as a result of this License or
21 * out of the use or inability to use the software (including but not limited to damages
22 * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
23 * all other commercial damages or losses), even if such Contributor has been advised
24 * of the possibility of such damages.
25 */
26
27 #pragma once
28
29 // ShaderResourcesGL class allocates single continuous chunk of memory to store all program resources, as follows:
30 //
31 //
32 // m_UniformBuffers m_Textures m_Images m_StorageBlocks
33 // | | | | | |
34 // | UB[0] ... UB[Nu-1] | Tex[0] ... Tex[Ns-1] | Img[0] ... Img[Ni-1] | SB[0] ... SB[Nsb-1] | Resource Names |
35 //
36 // Nu - number of uniform buffers
37 // Ns - number of samplers
38 // Ni - number of images
39 // Nsb - number of storage blocks
40
41 #include <vector>
42
43 #include "Object.h"
44 #include "StringPool.hpp"
45 #include "HashUtils.hpp"
46 #include "ShaderResourceVariableBase.hpp"
47
48 namespace Diligent
49 {
50
51 class ShaderResourcesGL
52 {
53 public:
54 ShaderResourcesGL() {}
55 ~ShaderResourcesGL();
56 // clang-format off
57 ShaderResourcesGL (ShaderResourcesGL&& Program)noexcept;
58
59 ShaderResourcesGL (const ShaderResourcesGL&) = delete;
60 ShaderResourcesGL& operator = (const ShaderResourcesGL&) = delete;
61 ShaderResourcesGL& operator = ( ShaderResourcesGL&&) = delete;
62 // clang-format on
63
64 /// Loads program uniforms and assigns bindings
65 void LoadUniforms(SHADER_TYPE ShaderStages,
66 const GLObjectWrappers::GLProgramObj& GLProgram,
67 class GLContextState& State);
68
69 struct GLResourceAttribs
70 {
71 // clang-format off
72 /* 0 */ const Char* Name;
73 /* 8 */ const SHADER_TYPE ShaderStages;
74 /* 12 */ const SHADER_RESOURCE_TYPE ResourceType;
75 /* 16 */ Uint32 ArraySize;
76 /* 20 */ // End of data
77 // clang-format on
78
79 GLResourceAttribs(const Char* _Name,
80 SHADER_TYPE _ShaderStages,
81 SHADER_RESOURCE_TYPE _ResourceType,
82 Uint32 _ArraySize) noexcept :
83 // clang-format off
84 Name {_Name },
85 ShaderStages {_ShaderStages},
86 ResourceType {_ResourceType},
87 ArraySize {_ArraySize }
88 // clang-format on
89 {
90 VERIFY(_ShaderStages != SHADER_TYPE_UNKNOWN, "At least one shader stage must be specified");
91 VERIFY(_ResourceType != SHADER_RESOURCE_TYPE_UNKNOWN, "Unknown shader resource type");
92 VERIFY(_ArraySize >= 1, "Array size must be greater than 1");
93 }
94
95 GLResourceAttribs(const GLResourceAttribs& Attribs,
96 StringPool& NamesPool) noexcept :
97 // clang-format off
98 GLResourceAttribs
99 {
100 NamesPool.CopyString(Attribs.Name),
101 Attribs.ShaderStages,
102 Attribs.ResourceType,
103 Attribs.ArraySize
104 }
105 // clang-format on
106 {
107 }
108
109 ShaderResourceDesc GetResourceDesc() const
110 {
111 ShaderResourceDesc ResourceDesc;
112 ResourceDesc.Name = Name;
113 ResourceDesc.ArraySize = ArraySize;
114 ResourceDesc.Type = ResourceType;
115 return ResourceDesc;
116 }
117 };
118
119 struct UniformBufferInfo final : GLResourceAttribs
120 {
121 // clang-format off
122 UniformBufferInfo (const UniformBufferInfo&) = delete;
123 UniformBufferInfo& operator= (const UniformBufferInfo&) = delete;
124 UniformBufferInfo ( UniformBufferInfo&&) = default;
125 UniformBufferInfo& operator= ( UniformBufferInfo&&) = delete;
126
127 UniformBufferInfo(const Char* _Name,
128 SHADER_TYPE _ShaderStages,
129 SHADER_RESOURCE_TYPE _ResourceType,
130 Uint32 _ArraySize,
131 GLuint _UBIndex)noexcept :
132 GLResourceAttribs{_Name, _ShaderStages, _ResourceType, _ArraySize},
133 UBIndex {_UBIndex}
134 {}
135
136 UniformBufferInfo(const UniformBufferInfo& UB,
137 StringPool& NamesPool)noexcept :
138 GLResourceAttribs{UB, NamesPool},
139 UBIndex {UB.UBIndex }
140 {}
141 // clang-format on
142
143 const GLuint UBIndex;
144 };
145 static_assert((sizeof(UniformBufferInfo) % sizeof(void*)) == 0, "sizeof(UniformBufferInfo) must be multiple of sizeof(void*)");
146
147
148 struct TextureInfo final : GLResourceAttribs
149 {
150 // clang-format off
151 TextureInfo (const TextureInfo&) = delete;
152 TextureInfo& operator= (const TextureInfo&) = delete;
153 TextureInfo ( TextureInfo&&) = default;
154 TextureInfo& operator= ( TextureInfo&&) = delete;
155
156 TextureInfo(const Char* _Name,
157 SHADER_TYPE _ShaderStages,
158 SHADER_RESOURCE_TYPE _ResourceType,
159 Uint32 _ArraySize,
160 GLenum _TextureType,
161 RESOURCE_DIMENSION _ResourceDim,
162 bool _IsMultisample) noexcept :
163 GLResourceAttribs{_Name, _ShaderStages, _ResourceType, _ArraySize},
164 TextureType {_TextureType},
165 ResourceDim {_ResourceDim},
166 IsMultisample {_IsMultisample}
167 {}
168
169 TextureInfo(const TextureInfo& Tex,
170 StringPool& NamesPool) noexcept :
171 GLResourceAttribs{Tex, NamesPool},
172 TextureType {Tex.TextureType},
173 ResourceDim {Tex.ResourceDim},
174 IsMultisample {Tex.IsMultisample}
175 {}
176 // clang-format on
177
178 const GLenum TextureType;
179 const RESOURCE_DIMENSION ResourceDim;
180 const bool IsMultisample;
181 };
182 static_assert((sizeof(TextureInfo) % sizeof(void*)) == 0, "sizeof(TextureInfo) must be multiple of sizeof(void*)");
183
184
185 struct ImageInfo final : GLResourceAttribs
186 {
187 // clang-format off
188 ImageInfo (const ImageInfo&) = delete;
189 ImageInfo& operator= (const ImageInfo&) = delete;
190 ImageInfo ( ImageInfo&&) = default;
191 ImageInfo& operator= ( ImageInfo&&) = delete;
192
193 ImageInfo(const Char* _Name,
194 SHADER_TYPE _ShaderStages,
195 SHADER_RESOURCE_TYPE _ResourceType,
196 Uint32 _ArraySize,
197 GLenum _ImageType,
198 RESOURCE_DIMENSION _ResourceDim,
199 bool _IsMultisample) noexcept :
200 GLResourceAttribs{_Name, _ShaderStages, _ResourceType, _ArraySize},
201 ImageType {_ImageType},
202 ResourceDim {_ResourceDim},
203 IsMultisample {_IsMultisample}
204 {}
205
206 ImageInfo(const ImageInfo& Img,
207 StringPool& NamesPool) noexcept :
208 GLResourceAttribs{Img, NamesPool},
209 ImageType {Img.ImageType},
210 ResourceDim {Img.ResourceDim},
211 IsMultisample {Img.IsMultisample}
212 {}
213 // clang-format on
214
215 const GLenum ImageType;
216 const RESOURCE_DIMENSION ResourceDim;
217 const bool IsMultisample;
218 };
219 static_assert((sizeof(ImageInfo) % sizeof(void*)) == 0, "sizeof(ImageInfo) must be multiple of sizeof(void*)");
220
221
222 struct StorageBlockInfo final : GLResourceAttribs
223 {
224 // clang-format off
225 StorageBlockInfo (const StorageBlockInfo&) = delete;
226 StorageBlockInfo& operator= (const StorageBlockInfo&) = delete;
227 StorageBlockInfo ( StorageBlockInfo&&) = default;
228 StorageBlockInfo& operator= ( StorageBlockInfo&&) = delete;
229
230 StorageBlockInfo(const Char* _Name,
231 SHADER_TYPE _ShaderStages,
232 SHADER_RESOURCE_TYPE _ResourceType,
233 Uint32 _ArraySize,
234 GLint _SBIndex)noexcept :
235 GLResourceAttribs{_Name, _ShaderStages, _ResourceType, _ArraySize},
236 SBIndex {_SBIndex}
237 {}
238
239 StorageBlockInfo(const StorageBlockInfo& SB,
240 StringPool& NamesPool)noexcept :
241 GLResourceAttribs{SB, NamesPool},
242 SBIndex {SB.SBIndex}
243 {}
244 // clang-format on
245
246 const GLint SBIndex;
247 };
248 static_assert((sizeof(StorageBlockInfo) % sizeof(void*)) == 0, "sizeof(StorageBlockInfo) must be multiple of sizeof(void*)");
249
250
251 // clang-format off
252 Uint32 GetNumUniformBuffers()const { return m_NumUniformBuffers; }
253 Uint32 GetNumTextures() const { return m_NumTextures; }
254 Uint32 GetNumImages() const { return m_NumImages; }
255 Uint32 GetNumStorageBlocks() const { return m_NumStorageBlocks; }
256 // clang-format on
257
258 UniformBufferInfo& GetUniformBuffer(Uint32 Index)
259 {
260 VERIFY(Index < m_NumUniformBuffers, "Uniform buffer index (", Index, ") is out of range");
261 return m_UniformBuffers[Index];
262 }
263
264 TextureInfo& GetTexture(Uint32 Index)
265 {
266 VERIFY(Index < m_NumTextures, "Texture index (", Index, ") is out of range");
267 return m_Textures[Index];
268 }
269
270 ImageInfo& GetImage(Uint32 Index)
271 {
272 VERIFY(Index < m_NumImages, "Image index (", Index, ") is out of range");
273 return m_Images[Index];
274 }
275
276 StorageBlockInfo& GetStorageBlock(Uint32 Index)
277 {
278 VERIFY(Index < m_NumStorageBlocks, "Storage block index (", Index, ") is out of range");
279 return m_StorageBlocks[Index];
280 }
281
282
283 const UniformBufferInfo& GetUniformBuffer(Uint32 Index) const
284 {
285 VERIFY(Index < m_NumUniformBuffers, "Uniform buffer index (", Index, ") is out of range");
286 return m_UniformBuffers[Index];
287 }
288
289 const TextureInfo& GetTexture(Uint32 Index) const
290 {
291 VERIFY(Index < m_NumTextures, "Texture index (", Index, ") is out of range");
292 return m_Textures[Index];
293 }
294
295 const ImageInfo& GetImage(Uint32 Index) const
296 {
297 VERIFY(Index < m_NumImages, "Image index (", Index, ") is out of range");
298 return m_Images[Index];
299 }
300
301 const StorageBlockInfo& GetStorageBlock(Uint32 Index) const
302 {
303 VERIFY(Index < m_NumStorageBlocks, "Storage block index (", Index, ") is out of range");
304 return m_StorageBlocks[Index];
305 }
306
307 Uint32 GetVariableCount() const
308 {
309 return m_NumUniformBuffers + m_NumTextures + m_NumImages + m_NumStorageBlocks;
310 }
311
312 ShaderResourceDesc GetResourceDesc(Uint32 Index) const;
313
314 SHADER_TYPE GetShaderStages() const { return m_ShaderStages; }
315
316 template <typename THandleUB,
317 typename THandleTexture,
318 typename THandleImg,
319 typename THandleSB>
320 void ProcessConstResources(THandleUB HandleUB,
321 THandleTexture HandleTexture,
322 THandleImg HandleImg,
323 THandleSB HandleSB,
324 const PipelineResourceLayoutDesc* pResourceLayout = nullptr,
325 const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes = nullptr,
326 Uint32 NumAllowedTypes = 0) const
327 {
328 const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes);
329
330 auto CheckResourceType = [&](const char* Name) //
331 {
332 if (pResourceLayout == nullptr)
333 return true;
334 else
335 {
336 auto VarType = GetShaderVariableType(m_ShaderStages, Name, *pResourceLayout);
337 return IsAllowedType(VarType, AllowedTypeBits);
338 }
339 };
340
341 for (Uint32 ub = 0; ub < m_NumUniformBuffers; ++ub)
342 {
343 const auto& UB = GetUniformBuffer(ub);
344 if (CheckResourceType(UB.Name))
345 HandleUB(UB);
346 }
347
348 for (Uint32 s = 0; s < m_NumTextures; ++s)
349 {
350 const auto& Sam = GetTexture(s);
351 if (CheckResourceType(Sam.Name))
352 HandleTexture(Sam);
353 }
354
355 for (Uint32 img = 0; img < m_NumImages; ++img)
356 {
357 const auto& Img = GetImage(img);
358 if (CheckResourceType(Img.Name))
359 HandleImg(Img);
360 }
361
362 for (Uint32 sb = 0; sb < m_NumStorageBlocks; ++sb)
363 {
364 const auto& SB = GetStorageBlock(sb);
365 if (CheckResourceType(SB.Name))
366 HandleSB(SB);
367 }
368 }
369
370 template <typename THandleUB,
371 typename THandleTexture,
372 typename THandleImg,
373 typename THandleSB>
374 void ProcessResources(THandleUB HandleUB,
375 THandleTexture HandleTexture,
376 THandleImg HandleImg,
377 THandleSB HandleSB)
378 {
379 for (Uint32 ub = 0; ub < m_NumUniformBuffers; ++ub)
380 HandleUB(GetUniformBuffer(ub));
381
382 for (Uint32 s = 0; s < m_NumTextures; ++s)
383 HandleTexture(GetTexture(s));
384
385 for (Uint32 img = 0; img < m_NumImages; ++img)
386 HandleImg(GetImage(img));
387
388 for (Uint32 sb = 0; sb < m_NumStorageBlocks; ++sb)
389 HandleSB(GetStorageBlock(sb));
390 }
391
392 private:
393 void AllocateResources(std::vector<UniformBufferInfo>& UniformBlocks,
394 std::vector<TextureInfo>& Textures,
395 std::vector<ImageInfo>& Images,
396 std::vector<StorageBlockInfo>& StorageBlocks);
397
398 // clang-format off
399 // There could be more than one stage if using non-separable programs
400 SHADER_TYPE m_ShaderStages = SHADER_TYPE_UNKNOWN;
401
402 // Memory layout:
403 //
404 // | Uniform buffers | Textures | Images | Storage Blocks | String Pool Data |
405 //
406
407 UniformBufferInfo* m_UniformBuffers = nullptr;
408 TextureInfo* m_Textures = nullptr;
409 ImageInfo* m_Images = nullptr;
410 StorageBlockInfo* m_StorageBlocks = nullptr;
411
412 Uint32 m_NumUniformBuffers = 0;
413 Uint32 m_NumTextures = 0;
414 Uint32 m_NumImages = 0;
415 Uint32 m_NumStorageBlocks = 0;
416 // clang-format on
417 // When adding new member DO NOT FORGET TO UPDATE ShaderResourcesGL( ShaderResourcesGL&& ProgramResources )!!!
418 };
419
420 } // namespace Diligent
0 /*
1 * Copyright 2019-2021 Diligent Graphics LLC
2 * Copyright 2015-2019 Egor Yusov
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * In no event and under no legal theory, whether in tort (including negligence),
17 * contract, or otherwise, unless required by applicable law (such as deliberate
18 * and grossly negligent acts) or agreed to in writing, shall any Contributor be
19 * liable for any damages, including any direct, indirect, special, incidental,
20 * or consequential damages of any character arising as a result of this License or
21 * out of the use or inability to use the software (including but not limited to damages
22 * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
23 * all other commercial damages or losses), even if such Contributor has been advised
24 * of the possibility of such damages.
25 */
26
27 #pragma once
28
29 // ShaderVariableGL class manages resource bindings for all stages in a pipeline
30
31 //
32 //
33 // To program resource cache
34 //
35 // A A A A A A A A
36 // | | | | | | | |
37 // Binding Binding Binding Binding Binding Binding Binding Binding
38 // ___________________ ____|__________|__________________|________|______________|___________|______________|____________|____________
39 // | | | | | | | | | | | | | | |
40 // | ShaderResourcesGL |--------------->| UB[0] | UB[1] | ... | Sam[0] | Sam[1] | ... | Img[0] | Img[1] | ... | SSBOs[0] | SSBOs[1] | ... |
41 // |___________________| |__________|__________|_______|________|________|_______|________|________|_______|__________|__________|_______|
42 // A A A A
43 // | | | |
44 // Ref Ref Ref Ref
45 // .-==========================-. _____|____________________________________|________________________|____________________________|______________
46 // || || | | | | | | | | | | |
47 // __|| ShaderVariableGL ||------->| UBInfo[0] | UBInfo[1] | ... | SamInfo[0] | SamInfo[1] | ... | ImgInfo[0] | ... | SSBO[0] | ... |
48 // | || || |___________|___________|_______|____________|____________|_______|____________|_________|___________|__________|
49 // | '-==========================-' / \
50 // | Ref Ref
51 // | / \
52 // | ___________________ ________V________________________________________________V_____________________________________________________
53 // | | | | | | | | | | | | | | | |
54 // | | ShaderResourcesGL |--------------->| UB[0] | UB[1] | ... | Sam[0] | Sam[1] | ... | Img[0] | Img[1] | ... | SSBOs[0] | SSBOs[1] | ... |
55 // | |___________________| |__________|__________|_______|________|________|_______|________|________|_______|__________|__________|_______|
56 // | | | | | | | | |
57 // | Binding Binding Binding Binding Binding Binding Binding Binding
58 // | | | | | | | | |
59 // | _______________________ ____V___________V________________V_________V________________V________V________________V___________V_____________
60 // | | | | | | | |
61 // '-->| ShaderResourceCacheGL |----------->| Uinform Buffers | Textures | Images | Storge Buffers |
62 // |_______________________| |___________________________|___________________________|___________________________|___________________________|
63 //
64 //
65 // Note that ShaderResourcesGL are kept by PipelineStateGLImpl. ShaderVariableGL class is either part of the same PSO class,
66 // or part of ShaderResourceBindingGLImpl object that keeps a strong reference to the pipeline. So all references from GLVariableBase
67 // are always valid.
68
69 #include <array>
70
71 #include "Object.h"
72 #include "ShaderResourceVariableBase.hpp"
73 #include "ShaderResourceCacheGL.hpp"
74 #include "PipelineResourceSignatureGLImpl.hpp"
75
76 namespace Diligent
77 {
78
79 // sizeof(ShaderVariableGL) == 48 (x64, msvc, Release)
80 class ShaderVariableGL
81 {
82 public:
83 ShaderVariableGL(IObject& Owner, ShaderResourceCacheGL& ResourceCache) noexcept :
84 m_Owner(Owner),
85 m_ResourceCache{ResourceCache}
86 {}
87
88 ~ShaderVariableGL();
89
90 // No copies, only moves are allowed
91 // clang-format off
92 ShaderVariableGL (const ShaderVariableGL&) = delete;
93 ShaderVariableGL& operator = (const ShaderVariableGL&) = delete;
94 ShaderVariableGL ( ShaderVariableGL&&) = default;
95 ShaderVariableGL& operator = ( ShaderVariableGL&&) = delete;
96 // clang-format on
97
98 void Initialize(const PipelineResourceSignatureGLImpl& Signature,
99 const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
100 Uint32 NumAllowedTypes,
101 SHADER_TYPE ShaderType);
102
103 static size_t GetRequiredMemorySize(const PipelineResourceSignatureGLImpl& Signature,
104 const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
105 Uint32 NumAllowedTypes,
106 SHADER_TYPE ShaderType);
107
108 using ResourceAttribs = PipelineResourceSignatureGLImpl::ResourceAttribs;
109
110 const PipelineResourceDesc& GetResourceDesc(Uint32 Index) const
111 {
112 VERIFY_EXPR(m_pSignature);
113 return m_pSignature->GetResourceDesc(Index);
114 }
115 const ResourceAttribs& GetAttribs(Uint32 Index) const
116 {
117 VERIFY_EXPR(m_pSignature);
118 return m_pSignature->GetResourceAttribs(Index);
119 }
120
121
122 struct GLVariableBase : public ShaderVariableBase<ShaderVariableGL>
123 {
124 using TBase = ShaderVariableBase<ShaderVariableGL>;
125 GLVariableBase(ShaderVariableGL& ParentLayout, Uint32 ResIndex) :
126 TBase{ParentLayout},
127 m_ResIndex{ResIndex}
128 {}
129
130 const PipelineResourceDesc& GetDesc() const { return m_ParentManager.GetResourceDesc(m_ResIndex); }
131 const ResourceAttribs& GetAttribs() const { return m_ParentManager.GetAttribs(m_ResIndex); }
132
133 virtual SHADER_RESOURCE_VARIABLE_TYPE DILIGENT_CALL_TYPE GetType() const override final
134 {
135 return GetDesc().VarType;
136 }
137
138 virtual void DILIGENT_CALL_TYPE GetResourceDesc(ShaderResourceDesc& ResourceDesc) const override final
139 {
140 const auto& Desc = GetDesc();
141 ResourceDesc.Name = Desc.Name;
142 ResourceDesc.Type = Desc.ResourceType;
143 ResourceDesc.ArraySize = Desc.ArraySize;
144 }
145
146 virtual Uint32 DILIGENT_CALL_TYPE GetIndex() const override final
147 {
148 return m_ParentManager.GetVariableIndex(*this);
149 }
150
151 const Uint32 m_ResIndex;
152 };
153
154
155 struct UniformBuffBindInfo final : GLVariableBase
156 {
157 UniformBuffBindInfo(ShaderVariableGL& ParentLayout, Uint32 ResIndex) :
158 GLVariableBase{ParentLayout, ResIndex}
159 {}
160
161 // Non-virtual function
162 void BindResource(IDeviceObject* pObject, Uint32 ArrayIndex);
163
164 virtual void DILIGENT_CALL_TYPE Set(IDeviceObject* pObject) override final
165 {
166 BindResource(pObject, 0);
167 }
168
169 virtual void DILIGENT_CALL_TYPE SetArray(IDeviceObject* const* ppObjects,
170 Uint32 FirstElement,
171 Uint32 NumElements) override final
172 {
173 const auto& Desc = GetDesc();
174 VerifyAndCorrectSetArrayArguments(Desc.Name, Desc.ArraySize, FirstElement, NumElements);
175 for (Uint32 elem = 0; elem < NumElements; ++elem)
176 BindResource(ppObjects[elem], FirstElement + elem);
177 }
178
179 virtual bool DILIGENT_CALL_TYPE IsBound(Uint32 ArrayIndex) const override final
180 {
181 VERIFY_EXPR(ArrayIndex < GetDesc().ArraySize);
182 return m_ParentManager.m_ResourceCache.IsUBBound(GetAttribs().CacheOffset + ArrayIndex);
183 }
184 };
185
186
187 struct SamplerBindInfo final : GLVariableBase
188 {
189 SamplerBindInfo(ShaderVariableGL& ParentLayout, Uint32 ResIndex) :
190 GLVariableBase{ParentLayout, ResIndex}
191 {}
192
193 // Non-virtual function
194 void BindResource(IDeviceObject* pObject, Uint32 ArrayIndex);
195
196 virtual void DILIGENT_CALL_TYPE Set(IDeviceObject* pObject) override final
197 {
198 BindResource(pObject, 0);
199 }
200
201 virtual void DILIGENT_CALL_TYPE SetArray(IDeviceObject* const* ppObjects,
202 Uint32 FirstElement,
203 Uint32 NumElements) override final
204 {
205 const auto& Desc = GetDesc();
206 VerifyAndCorrectSetArrayArguments(Desc.Name, Desc.ArraySize, FirstElement, NumElements);
207 for (Uint32 elem = 0; elem < NumElements; ++elem)
208 BindResource(ppObjects[elem], FirstElement + elem);
209 }
210
211 virtual bool DILIGENT_CALL_TYPE IsBound(Uint32 ArrayIndex) const override final
212 {
213 VERIFY_EXPR(ArrayIndex < GetDesc().ArraySize);
214 return m_ParentManager.m_ResourceCache.IsTextureBound(GetAttribs().CacheOffset + ArrayIndex, GetDesc().ResourceType == SHADER_RESOURCE_TYPE_TEXTURE_SRV);
215 }
216 };
217
218
219 struct ImageBindInfo final : GLVariableBase
220 {
221 ImageBindInfo(ShaderVariableGL& ParentLayout, Uint32 ResIndex) :
222 GLVariableBase{ParentLayout, ResIndex}
223 {}
224
225 // Provide non-virtual function
226 void BindResource(IDeviceObject* pObject, Uint32 ArrayIndex);
227
228 virtual void DILIGENT_CALL_TYPE Set(IDeviceObject* pObject) override final
229 {
230 BindResource(pObject, 0);
231 }
232
233 virtual void DILIGENT_CALL_TYPE SetArray(IDeviceObject* const* ppObjects,
234 Uint32 FirstElement,
235 Uint32 NumElements) override final
236 {
237 const auto& Desc = GetDesc();
238 VerifyAndCorrectSetArrayArguments(Desc.Name, Desc.ArraySize, FirstElement, NumElements);
239 for (Uint32 elem = 0; elem < NumElements; ++elem)
240 BindResource(ppObjects[elem], FirstElement + elem);
241 }
242
243 virtual bool DILIGENT_CALL_TYPE IsBound(Uint32 ArrayIndex) const override final
244 {
245 VERIFY_EXPR(ArrayIndex < GetDesc().ArraySize);
246 return m_ParentManager.m_ResourceCache.IsImageBound(GetAttribs().CacheOffset + ArrayIndex, GetDesc().ResourceType == SHADER_RESOURCE_TYPE_TEXTURE_UAV);
247 }
248 };
249
250
251 struct StorageBufferBindInfo final : GLVariableBase
252 {
253 StorageBufferBindInfo(ShaderVariableGL& ParentLayout, Uint32 ResIndex) :
254 GLVariableBase{ParentLayout, ResIndex}
255 {}
256
257 // Non-virtual function
258 void BindResource(IDeviceObject* pObject, Uint32 ArrayIndex);
259
260 virtual void DILIGENT_CALL_TYPE Set(IDeviceObject* pObject) override final
261 {
262 BindResource(pObject, 0);
263 }
264
265 virtual void DILIGENT_CALL_TYPE SetArray(IDeviceObject* const* ppObjects,
266 Uint32 FirstElement,
267 Uint32 NumElements) override final
268 {
269 const auto& Desc = GetDesc();
270 VerifyAndCorrectSetArrayArguments(Desc.Name, Desc.ArraySize, FirstElement, NumElements);
271 for (Uint32 elem = 0; elem < NumElements; ++elem)
272 BindResource(ppObjects[elem], FirstElement + elem);
273 }
274
275 virtual bool DILIGENT_CALL_TYPE IsBound(Uint32 ArrayIndex) const override final
276 {
277 VERIFY_EXPR(ArrayIndex < GetDesc().ArraySize);
278 return m_ParentManager.m_ResourceCache.IsSSBOBound(GetAttribs().CacheOffset + ArrayIndex);
279 }
280 };
281
282
283 // dbgResourceCache is only used for sanity check and as a remainder that the resource cache must be alive
284 // while Layout is alive
285 void BindResources(IResourceMapping* pResourceMapping, Uint32 Flags);
286
287 #ifdef DILIGENT_DEVELOPMENT
288 bool dvpVerifyBindings(const ShaderResourceCacheGL& ResourceCache) const;
289 #endif
290
291 IShaderResourceVariable* GetVariable(const Char* Name) const;
292 IShaderResourceVariable* GetVariable(Uint32 Index) const;
293
294 IObject& GetOwner() { return m_Owner; }
295
296 Uint32 GetVariableCount() const;
297
298 // clang-format off
299 Uint32 GetNumUBs() const { return (m_TextureOffset - m_UBOffset) / sizeof(UniformBuffBindInfo); }
300 Uint32 GetNumTextures() const { return (m_ImageOffset - m_TextureOffset) / sizeof(SamplerBindInfo); }
301 Uint32 GetNumImages() const { return (m_StorageBufferOffset - m_ImageOffset) / sizeof(ImageBindInfo) ; }
302 Uint32 GetNumStorageBuffers() const { return (m_VariableEndOffset - m_StorageBufferOffset) / sizeof(StorageBufferBindInfo); }
303 // clang-format on
304
305 template <typename ResourceType> Uint32 GetNumResources() const;
306
307 template <typename ResourceType>
308 const ResourceType& GetConstResource(Uint32 ResIndex) const
309 {
310 VERIFY(ResIndex < GetNumResources<ResourceType>(), "Resource index (", ResIndex, ") exceeds max allowed value (", GetNumResources<ResourceType>(), ")");
311 auto Offset = GetResourceOffset<ResourceType>();
312 return reinterpret_cast<const ResourceType*>(reinterpret_cast<const Uint8*>(m_ResourceBuffer.get()) + Offset)[ResIndex];
313 }
314
315 Uint32 GetVariableIndex(const GLVariableBase& Var) const;
316
317 private:
318 struct ResourceCounters
319 {
320 Uint32 NumUBs = 0;
321 Uint32 NumTextures = 0;
322 Uint32 NumImages = 0;
323 Uint32 NumStorageBlocks = 0;
324 };
325 static void CountResources(const PipelineResourceSignatureGLImpl& Signature,
326 const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
327 Uint32 NumAllowedTypes,
328 SHADER_TYPE ShaderType,
329 ResourceCounters& Counters);
330
331 template <typename HandlerType>
332 static void ProcessSignatureResources(const PipelineResourceSignatureGLImpl& Signature,
333 const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
334 Uint32 NumAllowedTypes,
335 SHADER_TYPE ShaderType,
336 HandlerType Handler);
337
338 // Offsets in bytes
339 using OffsetType = Uint16;
340
341 template <typename ResourceType> OffsetType GetResourceOffset() const;
342
343 template <typename ResourceType>
344 ResourceType& GetResource(Uint32 ResIndex) const
345 {
346 VERIFY(ResIndex < GetNumResources<ResourceType>(), "Resource index (", ResIndex, ") exceeds max allowed value (", GetNumResources<ResourceType>() - 1, ")");
347 auto Offset = GetResourceOffset<ResourceType>();
348 return reinterpret_cast<ResourceType*>(reinterpret_cast<Uint8*>(m_ResourceBuffer.get()) + Offset)[ResIndex];
349 }
350
351 template <typename ResourceType>
352 IShaderResourceVariable* GetResourceByName(const Char* Name) const;
353
354 template <typename THandleUB,
355 typename THandleSampler,
356 typename THandleImage,
357 typename THandleStorageBuffer>
358 void HandleResources(THandleUB HandleUB,
359 THandleSampler HandleSampler,
360 THandleImage HandleImage,
361 THandleStorageBuffer HandleStorageBuffer)
362 {
363 for (Uint32 ub = 0; ub < GetNumResources<UniformBuffBindInfo>(); ++ub)
364 HandleUB(GetResource<UniformBuffBindInfo>(ub));
365
366 for (Uint32 s = 0; s < GetNumResources<SamplerBindInfo>(); ++s)
367 HandleSampler(GetResource<SamplerBindInfo>(s));
368
369 for (Uint32 i = 0; i < GetNumResources<ImageBindInfo>(); ++i)
370 HandleImage(GetResource<ImageBindInfo>(i));
371
372 for (Uint32 s = 0; s < GetNumResources<StorageBufferBindInfo>(); ++s)
373 HandleStorageBuffer(GetResource<StorageBufferBindInfo>(s));
374 }
375
376 template <typename THandleUB,
377 typename THandleSampler,
378 typename THandleImage,
379 typename THandleStorageBuffer>
380 void HandleConstResources(THandleUB HandleUB,
381 THandleSampler HandleSampler,
382 THandleImage HandleImage,
383 THandleStorageBuffer HandleStorageBuffer) const
384 {
385 for (Uint32 ub = 0; ub < GetNumResources<UniformBuffBindInfo>(); ++ub)
386 HandleUB(GetConstResource<UniformBuffBindInfo>(ub));
387
388 for (Uint32 s = 0; s < GetNumResources<SamplerBindInfo>(); ++s)
389 HandleSampler(GetConstResource<SamplerBindInfo>(s));
390
391 for (Uint32 i = 0; i < GetNumResources<ImageBindInfo>(); ++i)
392 HandleImage(GetConstResource<ImageBindInfo>(i));
393