1 //
2 // Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 // StateManager11.h: Defines a class for caching D3D11 state
8 
9 #ifndef LIBANGLE_RENDERER_D3D11_STATEMANAGER11_H_
10 #define LIBANGLE_RENDERER_D3D11_STATEMANAGER11_H_
11 
12 #include <array>
13 
14 #include "libANGLE/ContextState.h"
15 #include "libANGLE/State.h"
16 #include "libANGLE/angletypes.h"
17 #include "libANGLE/renderer/d3d/IndexDataManager.h"
18 #include "libANGLE/renderer/d3d/RendererD3D.h"
19 #include "libANGLE/renderer/d3d/d3d11/InputLayoutCache.h"
20 #include "libANGLE/renderer/d3d/d3d11/Query11.h"
21 #include "libANGLE/renderer/d3d/d3d11/RenderStateCache.h"
22 #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
23 
24 namespace rx
25 {
26 
27 struct RenderTargetDesc;
28 struct Renderer11DeviceCaps;
29 
30 class ShaderConstants11 : angle::NonCopyable
31 {
32   public:
33     ShaderConstants11();
34     ~ShaderConstants11();
35 
36     void init(const gl::Caps &caps);
37     size_t getRequiredBufferSize(gl::SamplerType samplerType) const;
38     void markDirty();
39 
40     void setComputeWorkGroups(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ);
41     void setMultiviewWriteToViewportIndex(GLfloat index);
42     void onViewportChange(const gl::Rectangle &glViewport,
43                           const D3D11_VIEWPORT &dxViewport,
44                           bool is9_3,
45                           bool presentPathFast);
46     void onSamplerChange(gl::SamplerType samplerType,
47                          unsigned int samplerIndex,
48                          const gl::Texture &texture);
49 
50     gl::Error updateBuffer(ID3D11DeviceContext *deviceContext,
51                            gl::SamplerType samplerType,
52                            const ProgramD3D &programD3D,
53                            const d3d11::Buffer &driverConstantBuffer);
54 
55   private:
56     struct Vertex
57     {
VertexVertex58         Vertex()
59             : depthRange{.0f},
60               viewAdjust{.0f},
61               viewCoords{.0f},
62               viewScale{.0f},
63               multiviewWriteToViewportIndex{.0f},
64               padding{.0f}
65         {
66         }
67 
68         float depthRange[4];
69         float viewAdjust[4];
70         float viewCoords[4];
71         float viewScale[2];
72         // multiviewWriteToViewportIndex is used to select either the side-by-side or layered
73         // code-path in the GS. It's value, if set, is either 0.0f or 1.0f. The value is updated
74         // whenever a multi-view draw framebuffer is made active.
75         float multiviewWriteToViewportIndex;
76 
77         // Added here to manually pad the struct.
78         float padding;
79     };
80 
81     struct Pixel
82     {
PixelPixel83         Pixel()
84             : depthRange{.0f},
85               viewCoords{.0f},
86               depthFront{.0f},
87               viewScale{.0f},
88               multiviewWriteToViewportIndex(0),
89               padding(0)
90         {
91         }
92 
93         float depthRange[4];
94         float viewCoords[4];
95         float depthFront[4];
96         float viewScale[2];
97         // multiviewWriteToViewportIndex is used to select either the side-by-side or layered
98         // code-path in the GS. It's value, if set, is either 0.0f or 1.0f. The value is updated
99         // whenever a multi-view draw framebuffer is made active.
100         float multiviewWriteToViewportIndex;
101 
102         // Added here to manually pad the struct.
103         float padding;
104     };
105 
106     struct Compute
107     {
ComputeCompute108         Compute() : numWorkGroups{0u}, padding(0u) {}
109         unsigned int numWorkGroups[3];
110         unsigned int padding;  // This just pads the struct to 16 bytes
111     };
112 
113     struct SamplerMetadata
114     {
SamplerMetadataSamplerMetadata115         SamplerMetadata() : baseLevel(0), internalFormatBits(0), wrapModes(0), padding(0) {}
116 
117         int baseLevel;
118         int internalFormatBits;
119         int wrapModes;
120         int padding;  // This just pads the struct to 16 bytes
121     };
122 
123     static_assert(sizeof(SamplerMetadata) == 16u,
124                   "Sampler metadata struct must be one 4-vec / 16 bytes.");
125 
126     // Return true if dirty.
127     bool updateSamplerMetadata(SamplerMetadata *data, const gl::Texture &texture);
128 
129     Vertex mVertex;
130     bool mVertexDirty;
131     Pixel mPixel;
132     bool mPixelDirty;
133     Compute mCompute;
134     bool mComputeDirty;
135 
136     std::vector<SamplerMetadata> mSamplerMetadataVS;
137     bool mSamplerMetadataVSDirty;
138     std::vector<SamplerMetadata> mSamplerMetadataPS;
139     bool mSamplerMetadataPSDirty;
140     std::vector<SamplerMetadata> mSamplerMetadataCS;
141     bool mSamplerMetadataCSDirty;
142 };
143 
144 class DrawCallVertexParams final : angle::NonCopyable
145 {
146   public:
147     // Use when in a drawArrays call.
148     DrawCallVertexParams(GLint firstVertex, GLsizei vertexCount, GLsizei instances);
149 
150     // Use when in a drawElements call.
151     DrawCallVertexParams(bool firstVertexDefinitelyZero,
152                          const gl::HasIndexRange &hasIndexRange,
153                          GLint baseVertex,
154                          GLsizei instances);
155 
156     // It should be possible to also use an overload to handle the 'slow' indirect draw path.
157     // TODO(jmadill): Indirect draw slow path overload.
158 
159     GLint firstVertex() const;
160     GLsizei vertexCount() const;
161     GLsizei instances() const;
162 
163   private:
164     void ensureResolved() const;
165 
166     mutable const gl::HasIndexRange *mHasIndexRange;
167     mutable Optional<GLint> mFirstVertex;
168     mutable GLsizei mVertexCount;
169     GLsizei mInstances;
170     GLint mBaseVertex;
171 };
172 
173 class StateManager11 final : angle::NonCopyable
174 {
175   public:
176     StateManager11(Renderer11 *renderer);
177     ~StateManager11();
178 
179     gl::Error initialize(const gl::Caps &caps, const gl::Extensions &extensions);
180     void deinitialize();
181 
182     void syncState(const gl::Context *context, const gl::State::DirtyBits &dirtyBits);
183 
184     gl::Error updateStateForCompute(const gl::Context *context,
185                                     GLuint numGroupsX,
186                                     GLuint numGroupsY,
187                                     GLuint numGroupsZ);
188 
189     void updateStencilSizeIfChanged(bool depthStencilInitialized, unsigned int stencilSize);
190 
191     // These invalidations methods are called externally.
192 
193     // Called from TextureStorage11.
194     void invalidateBoundViews();
195 
196     // Called from VertexArray11::updateVertexAttribStorage.
197     void invalidateCurrentValueAttrib(size_t attribIndex);
198 
199     // Checks are done on a framebuffer state change to trigger other state changes.
200     // The Context is allowed to be nullptr for these methods, when called in EGL init code.
201     void invalidateRenderTarget();
202 
203     // Called by instanced point sprite emulation.
204     void invalidateVertexBuffer();
205 
206     // Called by Framebuffer11::syncState for the default sized viewport.
207     void invalidateViewport(const gl::Context *context);
208 
209     // Called by TextureStorage11::markLevelDirty.
210     void invalidateSwizzles();
211 
212     // Called by the Framebuffer11 and VertexArray11.
213     void invalidateShaders();
214 
215     // Called by VertexArray11 to trigger attribute translation.
216     void invalidateVertexAttributeTranslation();
217 
218     void setRenderTarget(ID3D11RenderTargetView *rtv, ID3D11DepthStencilView *dsv);
219     void setRenderTargets(ID3D11RenderTargetView **rtvs, UINT numRtvs, ID3D11DepthStencilView *dsv);
220 
221     void onBeginQuery(Query11 *query);
222     void onDeleteQueryObject(Query11 *query);
223     gl::Error onMakeCurrent(const gl::Context *context);
224 
225     void setInputLayout(const d3d11::InputLayout *inputLayout);
226 
227     // TODO(jmadill): Migrate to d3d11::Buffer.
228     bool queueVertexBufferChange(size_t bufferIndex,
229                                  ID3D11Buffer *buffer,
230                                  UINT stride,
231                                  UINT offset);
232     bool queueVertexOffsetChange(size_t bufferIndex, UINT offsetOnly);
233     void applyVertexBufferChanges();
234 
235     void setSingleVertexBuffer(const d3d11::Buffer *buffer, UINT stride, UINT offset);
236 
237     gl::Error updateState(const gl::Context *context, GLenum drawMode);
238 
239     void setShaderResourceShared(gl::SamplerType shaderType,
240                                  UINT resourceSlot,
241                                  const d3d11::SharedSRV *srv);
242     void setShaderResource(gl::SamplerType shaderType,
243                            UINT resourceSlot,
244                            const d3d11::ShaderResourceView *srv);
245     void setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY primitiveTopology);
246 
247     void setDrawShaders(const d3d11::VertexShader *vertexShader,
248                         const d3d11::GeometryShader *geometryShader,
249                         const d3d11::PixelShader *pixelShader);
250     void setVertexShader(const d3d11::VertexShader *shader);
251     void setGeometryShader(const d3d11::GeometryShader *shader);
252     void setPixelShader(const d3d11::PixelShader *shader);
253     void setComputeShader(const d3d11::ComputeShader *shader);
254     void setVertexConstantBuffer(unsigned int slot, const d3d11::Buffer *buffer);
255     void setPixelConstantBuffer(unsigned int slot, const d3d11::Buffer *buffer);
256     void setDepthStencilState(const d3d11::DepthStencilState *depthStencilState, UINT stencilRef);
257     void setSimpleBlendState(const d3d11::BlendState *blendState);
258     void setRasterizerState(const d3d11::RasterizerState *rasterizerState);
259     void setSimpleViewport(const gl::Extents &viewportExtents);
260     void setSimpleViewport(int width, int height);
261     void setSimplePixelTextureAndSampler(const d3d11::SharedSRV &srv,
262                                          const d3d11::SamplerState &samplerState);
263     void setSimpleScissorRect(const gl::Rectangle &glRect);
264     void setScissorRectD3D(const D3D11_RECT &d3dRect);
265 
266     // Not handled by an internal dirty bit because of the extra draw parameters.
267     gl::Error applyVertexBuffer(const gl::Context *context,
268                                 GLenum mode,
269                                 const DrawCallVertexParams &vertexParams,
270                                 bool isIndexedRendering);
271 
272     gl::Error applyIndexBuffer(const gl::Context *context,
273                                const void *indices,
274                                GLsizei count,
275                                GLenum type,
276                                const gl::HasIndexRange &lazyIndexRange,
277                                bool usePrimitiveRestartWorkaround);
278 
279     void setIndexBuffer(ID3D11Buffer *buffer, DXGI_FORMAT indexFormat, unsigned int offset);
280 
281     gl::Error updateVertexOffsetsForPointSpritesEmulation(GLint startVertex,
282                                                           GLsizei emulatedInstanceId);
283 
284     // TODO(jmadill): Should be private.
285     gl::Error applyComputeUniforms(ProgramD3D *programD3D);
286 
287     // Only used in testing.
getInputLayoutCache()288     InputLayoutCache *getInputLayoutCache() { return &mInputLayoutCache; }
289 
290   private:
291     template <typename SRVType>
292     void setShaderResourceInternal(gl::SamplerType shaderType,
293                                    UINT resourceSlot,
294                                    const SRVType *srv);
295 
296     bool unsetConflictingView(ID3D11View *view);
297     bool unsetConflictingSRVs(gl::SamplerType shaderType,
298                               uintptr_t resource,
299                               const gl::ImageIndex *index);
300     void unsetConflictingAttachmentResources(const gl::FramebufferAttachment *attachment,
301                                              ID3D11Resource *resource);
302 
303     gl::Error syncBlendState(const gl::Context *context,
304                              const gl::Framebuffer *framebuffer,
305                              const gl::BlendState &blendState,
306                              const gl::ColorF &blendColor,
307                              unsigned int sampleMask);
308 
309     gl::Error syncDepthStencilState(const gl::State &glState);
310 
311     gl::Error syncRasterizerState(const gl::Context *context, bool pointDrawMode);
312 
313     void syncScissorRectangle(const gl::Rectangle &scissor, bool enabled);
314 
315     void syncViewport(const gl::Context *context);
316 
317     void checkPresentPath(const gl::Context *context);
318 
319     gl::Error syncFramebuffer(const gl::Context *context, gl::Framebuffer *framebuffer);
320     gl::Error syncProgram(const gl::Context *context, GLenum drawMode);
321 
322     gl::Error syncTextures(const gl::Context *context);
323     gl::Error applyTextures(const gl::Context *context, gl::SamplerType shaderType);
324 
325     gl::Error setSamplerState(const gl::Context *context,
326                               gl::SamplerType type,
327                               int index,
328                               gl::Texture *texture,
329                               const gl::SamplerState &sampler);
330     gl::Error setTexture(const gl::Context *context,
331                          gl::SamplerType type,
332                          int index,
333                          gl::Texture *texture);
334 
335     // Faster than calling setTexture a jillion times
336     gl::Error clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd);
337     void handleMultiviewDrawFramebufferChange(const gl::Context *context);
338 
339     gl::Error syncCurrentValueAttribs(const gl::State &glState);
340 
341     gl::Error generateSwizzle(const gl::Context *context, gl::Texture *texture);
342     gl::Error generateSwizzlesForShader(const gl::Context *context, gl::SamplerType type);
343     gl::Error generateSwizzles(const gl::Context *context);
344 
345     gl::Error applyDriverUniforms(const ProgramD3D &programD3D);
346     gl::Error applyUniforms(ProgramD3D *programD3D);
347 
348     gl::Error syncUniformBuffers(const gl::Context *context, ProgramD3D *programD3D);
349     gl::Error syncTransformFeedbackBuffers(const gl::Context *context);
350 
351     // These are currently only called internally.
352     void invalidateTexturesAndSamplers();
353     void invalidateDriverUniforms();
354     void invalidateProgramUniforms();
355     void invalidateProgramUniformBuffers();
356     void invalidateConstantBuffer(unsigned int slot);
357 
358     // Called by the Framebuffer11 directly.
359     void processFramebufferInvalidation(const gl::Context *context);
360 
361     bool syncIndexBuffer(ID3D11Buffer *buffer, DXGI_FORMAT indexFormat, unsigned int offset);
362 
363     enum DirtyBitType
364     {
365         DIRTY_BIT_RENDER_TARGET,
366         DIRTY_BIT_VIEWPORT_STATE,
367         DIRTY_BIT_SCISSOR_STATE,
368         DIRTY_BIT_RASTERIZER_STATE,
369         DIRTY_BIT_BLEND_STATE,
370         DIRTY_BIT_DEPTH_STENCIL_STATE,
371         DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE,
372         DIRTY_BIT_PROGRAM_UNIFORMS,
373         DIRTY_BIT_DRIVER_UNIFORMS,
374         DIRTY_BIT_PROGRAM_UNIFORM_BUFFERS,
375         DIRTY_BIT_SHADERS,
376         DIRTY_BIT_CURRENT_VALUE_ATTRIBS,
377         DIRTY_BIT_INVALID,
378         DIRTY_BIT_MAX = DIRTY_BIT_INVALID,
379     };
380 
381     using DirtyBits = angle::BitSet<DIRTY_BIT_MAX>;
382 
383     Renderer11 *mRenderer;
384 
385     // Internal dirty bits.
386     DirtyBits mInternalDirtyBits;
387 
388     // Blend State
389     gl::BlendState mCurBlendState;
390     gl::ColorF mCurBlendColor;
391     unsigned int mCurSampleMask;
392 
393     // Currently applied depth stencil state
394     gl::DepthStencilState mCurDepthStencilState;
395     int mCurStencilRef;
396     int mCurStencilBackRef;
397     unsigned int mCurStencilSize;
398     Optional<bool> mCurDisableDepth;
399     Optional<bool> mCurDisableStencil;
400 
401     // Currently applied rasterizer state
402     gl::RasterizerState mCurRasterState;
403 
404     // Currently applied scissor rectangle state
405     bool mCurScissorEnabled;
406     gl::Rectangle mCurScissorRect;
407 
408     // Currently applied viewport state
409     gl::Rectangle mCurViewport;
410     float mCurNear;
411     float mCurFar;
412 
413     // The viewport offsets are guaranteed to be updated whenever the gl::State::DirtyBits are
414     // resolved and can be applied to the viewport and scissor whenever the internal viewport and
415     // scissor bits are resolved.
416     std::vector<gl::Offset> mViewportOffsets;
417 
418     // Things needed in viewport state
419     ShaderConstants11 mShaderConstants;
420 
421     // Render target variables
422     gl::Extents mViewportBounds;
423     bool mRenderTargetIsDirty;
424 
425     // EGL_ANGLE_experimental_present_path variables
426     bool mCurPresentPathFastEnabled;
427     int mCurPresentPathFastColorBufferHeight;
428 
429     // Queries that are currently active in this state
430     std::set<Query11 *> mCurrentQueries;
431 
432     // Currently applied textures
433     struct SRVRecord
434     {
435         uintptr_t srv;
436         uintptr_t resource;
437         D3D11_SHADER_RESOURCE_VIEW_DESC desc;
438     };
439 
440     // A cache of current SRVs that also tracks the highest 'used' (non-NULL) SRV
441     // We might want to investigate a more robust approach that is also fast when there's
442     // a large gap between used SRVs (e.g. if SRV 0 and 7 are non-NULL, this approach will
443     // waste time on SRVs 1-6.)
444     class SRVCache : angle::NonCopyable
445     {
446       public:
447         SRVCache();
448         ~SRVCache();
449 
initialize(size_t size)450         void initialize(size_t size) { mCurrentSRVs.resize(size); }
451 
size()452         size_t size() const { return mCurrentSRVs.size(); }
highestUsed()453         size_t highestUsed() const { return mHighestUsedSRV; }
454 
455         const SRVRecord &operator[](size_t index) const { return mCurrentSRVs[index]; }
456         void clear();
457         void update(size_t resourceIndex, ID3D11ShaderResourceView *srv);
458 
459       private:
460         std::vector<SRVRecord> mCurrentSRVs;
461         size_t mHighestUsedSRV;
462     };
463 
464     SRVCache mCurVertexSRVs;
465     SRVCache mCurPixelSRVs;
466 
467     // A block of NULL pointers, cached so we don't re-allocate every draw call
468     std::vector<ID3D11ShaderResourceView *> mNullSRVs;
469 
470     // Current translations of "Current-Value" data - owned by Context, not VertexArray.
471     gl::AttributesMask mDirtyCurrentValueAttribs;
472     std::vector<TranslatedAttribute> mCurrentValueAttribs;
473 
474     // Current applied input layout.
475     ResourceSerial mCurrentInputLayout;
476     bool mInputLayoutIsDirty;
477     bool mVertexAttribsNeedTranslation;
478 
479     // Current applied vertex states.
480     // TODO(jmadill): Figure out how to use ResourceSerial here.
481     std::array<ID3D11Buffer *, gl::MAX_VERTEX_ATTRIBS> mCurrentVertexBuffers;
482     std::array<UINT, gl::MAX_VERTEX_ATTRIBS> mCurrentVertexStrides;
483     std::array<UINT, gl::MAX_VERTEX_ATTRIBS> mCurrentVertexOffsets;
484     gl::RangeUI mDirtyVertexBufferRange;
485 
486     // Currently applied primitive topology
487     D3D11_PRIMITIVE_TOPOLOGY mCurrentPrimitiveTopology;
488 
489     // Currently applied shaders
490     ResourceSerial mAppliedVertexShader;
491     ResourceSerial mAppliedGeometryShader;
492     ResourceSerial mAppliedPixelShader;
493     ResourceSerial mAppliedComputeShader;
494 
495     // Currently applied sampler states
496     std::vector<bool> mForceSetVertexSamplerStates;
497     std::vector<gl::SamplerState> mCurVertexSamplerStates;
498 
499     std::vector<bool> mForceSetPixelSamplerStates;
500     std::vector<gl::SamplerState> mCurPixelSamplerStates;
501 
502     std::vector<bool> mForceSetComputeSamplerStates;
503     std::vector<gl::SamplerState> mCurComputeSamplerStates;
504 
505     // Special dirty bit for swizzles. Since they use internal shaders, must be done in a pre-pass.
506     bool mDirtySwizzles;
507 
508     // Currently applied index buffer
509     ID3D11Buffer *mAppliedIB;
510     DXGI_FORMAT mAppliedIBFormat;
511     unsigned int mAppliedIBOffset;
512     bool mIndexBufferIsDirty;
513 
514     // Vertex, index and input layouts
515     VertexDataManager mVertexDataManager;
516     IndexDataManager mIndexDataManager;
517     InputLayoutCache mInputLayoutCache;
518     std::vector<const TranslatedAttribute *> mCurrentAttributes;
519     Optional<GLint> mLastFirstVertex;
520 
521     // ANGLE_multiview.
522     bool mIsMultiviewEnabled;
523 
524     // Driver Constants.
525     d3d11::Buffer mDriverConstantBufferVS;
526     d3d11::Buffer mDriverConstantBufferPS;
527     d3d11::Buffer mDriverConstantBufferCS;
528 
529     ResourceSerial mCurrentComputeConstantBuffer;
530     ResourceSerial mCurrentGeometryConstantBuffer;
531 
532     template <typename T>
533     using VertexConstantBufferArray =
534         std::array<T, gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS>;
535 
536     VertexConstantBufferArray<ResourceSerial> mCurrentConstantBufferVS;
537     VertexConstantBufferArray<GLintptr> mCurrentConstantBufferVSOffset;
538     VertexConstantBufferArray<GLsizeiptr> mCurrentConstantBufferVSSize;
539 
540     template <typename T>
541     using FragmentConstantBufferArray =
542         std::array<T, gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS>;
543 
544     FragmentConstantBufferArray<ResourceSerial> mCurrentConstantBufferPS;
545     FragmentConstantBufferArray<GLintptr> mCurrentConstantBufferPSOffset;
546     FragmentConstantBufferArray<GLsizeiptr> mCurrentConstantBufferPSSize;
547 
548     // Currently applied transform feedback buffers
549     Serial mAppliedTFSerial;
550 
551     Serial mEmptySerial;
552 
553     bool mIsTransformFeedbackCurrentlyActiveUnpaused;
554 };
555 
556 }  // namespace rx
557 #endif  // LIBANGLE_RENDERER_D3D11_STATEMANAGER11_H_
558