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