ProgramD3D.h (23888B)
1 // 2 // Copyright 2014 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 // ProgramD3D.h: Defines the rx::ProgramD3D class which implements rx::ProgramImpl. 8 9 #ifndef LIBANGLE_RENDERER_D3D_PROGRAMD3D_H_ 10 #define LIBANGLE_RENDERER_D3D_PROGRAMD3D_H_ 11 12 #include <string> 13 #include <vector> 14 15 #include "compiler/translator/blocklayoutHLSL.h" 16 #include "libANGLE/Constants.h" 17 #include "libANGLE/formatutils.h" 18 #include "libANGLE/renderer/ProgramImpl.h" 19 #include "libANGLE/renderer/d3d/DynamicHLSL.h" 20 #include "libANGLE/renderer/d3d/RendererD3D.h" 21 #include "platform/FeaturesD3D_autogen.h" 22 23 namespace rx 24 { 25 class RendererD3D; 26 class UniformStorageD3D; 27 class ShaderExecutableD3D; 28 29 #if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL) 30 // WARNING: D3DCOMPILE_OPTIMIZATION_LEVEL3 may lead to a DX9 shader compiler hang. 31 // It should only be used selectively to work around specific bugs. 32 # define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL1 33 #endif 34 35 enum class HLSLRegisterType : uint8_t 36 { 37 None = 0, 38 Texture = 1, 39 UnorderedAccessView = 2 40 }; 41 42 // Helper struct representing a single shader uniform 43 // TODO(jmadill): Make uniform blocks shared between all programs, so we don't need separate 44 // register indices. 45 struct D3DUniform : private angle::NonCopyable 46 { 47 D3DUniform(GLenum type, 48 HLSLRegisterType reg, 49 const std::string &nameIn, 50 const std::vector<unsigned int> &arraySizesIn, 51 bool defaultBlock); 52 ~D3DUniform(); 53 54 bool isSampler() const; 55 bool isImage() const; 56 bool isImage2D() const; 57 bool isArray() const { return !arraySizes.empty(); } 58 unsigned int getArraySizeProduct() const; 59 bool isReferencedByShader(gl::ShaderType shaderType) const; 60 61 const uint8_t *firstNonNullData() const; 62 const uint8_t *getDataPtrToElement(size_t elementIndex) const; 63 64 // Duplicated from the GL layer 65 const gl::UniformTypeInfo &typeInfo; 66 std::string name; // Names of arrays don't include [0], unlike at the GL layer. 67 std::vector<unsigned int> arraySizes; 68 69 // Pointer to a system copies of the data. Separate pointers for each uniform storage type. 70 gl::ShaderMap<uint8_t *> mShaderData; 71 72 // Register information. 73 HLSLRegisterType regType; 74 gl::ShaderMap<unsigned int> mShaderRegisterIndexes; 75 unsigned int registerCount; 76 77 // Register "elements" are used for uniform structs in ES3, to appropriately identify single 78 // uniforms 79 // inside aggregate types, which are packed according C-like structure rules. 80 unsigned int registerElement; 81 82 // Special buffer for sampler values. 83 std::vector<GLint> mSamplerData; 84 }; 85 86 struct D3DInterfaceBlock 87 { 88 D3DInterfaceBlock(); 89 D3DInterfaceBlock(const D3DInterfaceBlock &other); 90 91 bool activeInShader(gl::ShaderType shaderType) const 92 { 93 return mShaderRegisterIndexes[shaderType] != GL_INVALID_INDEX; 94 } 95 96 gl::ShaderMap<unsigned int> mShaderRegisterIndexes; 97 }; 98 99 struct D3DUniformBlock : D3DInterfaceBlock 100 { 101 D3DUniformBlock(); 102 D3DUniformBlock(const D3DUniformBlock &other); 103 104 gl::ShaderMap<bool> mUseStructuredBuffers; 105 gl::ShaderMap<unsigned int> mByteWidths; 106 gl::ShaderMap<unsigned int> mStructureByteStrides; 107 }; 108 109 struct ShaderStorageBlock 110 { 111 std::string name; 112 unsigned int arraySize = 0; 113 unsigned int registerIndex = 0; 114 }; 115 116 struct D3DUBOCache 117 { 118 unsigned int registerIndex; 119 int binding; 120 }; 121 122 struct D3DUBOCacheUseSB : D3DUBOCache 123 { 124 unsigned int byteWidth; 125 unsigned int structureByteStride; 126 }; 127 128 struct D3DVarying final 129 { 130 D3DVarying(); 131 D3DVarying(const std::string &semanticNameIn, 132 unsigned int semanticIndexIn, 133 unsigned int componentCountIn, 134 unsigned int outputSlotIn); 135 136 D3DVarying(const D3DVarying &) = default; 137 D3DVarying &operator=(const D3DVarying &) = default; 138 139 std::string semanticName; 140 unsigned int semanticIndex; 141 unsigned int componentCount; 142 unsigned int outputSlot; 143 }; 144 145 class ProgramD3DMetadata final : angle::NonCopyable 146 { 147 public: 148 ProgramD3DMetadata(RendererD3D *renderer, 149 const gl::ShaderMap<const ShaderD3D *> &attachedShaders, 150 EGLenum clientType); 151 ~ProgramD3DMetadata(); 152 153 int getRendererMajorShaderModel() const; 154 bool usesBroadcast(const gl::State &data) const; 155 bool usesSecondaryColor() const; 156 bool usesFragDepth() const; 157 bool usesPointCoord() const; 158 bool usesFragCoord() const; 159 bool usesPointSize() const; 160 bool usesInsertedPointCoordValue() const; 161 bool usesViewScale() const; 162 bool hasANGLEMultiviewEnabled() const; 163 bool usesVertexID() const; 164 bool usesViewID() const; 165 bool canSelectViewInVertexShader() const; 166 bool addsPointCoordToVertexShader() const; 167 bool usesTransformFeedbackGLPosition() const; 168 bool usesSystemValuePointSize() const; 169 bool usesMultipleFragmentOuts() const; 170 bool usesCustomOutVars() const; 171 const ShaderD3D *getFragmentShader() const; 172 173 private: 174 const int mRendererMajorShaderModel; 175 const std::string mShaderModelSuffix; 176 const bool mUsesInstancedPointSpriteEmulation; 177 const bool mUsesViewScale; 178 const bool mCanSelectViewInVertexShader; 179 const gl::ShaderMap<const ShaderD3D *> mAttachedShaders; 180 const EGLenum mClientType; 181 }; 182 183 using D3DUniformMap = std::map<std::string, D3DUniform *>; 184 185 class ProgramD3D : public ProgramImpl 186 { 187 public: 188 ProgramD3D(const gl::ProgramState &data, RendererD3D *renderer); 189 ~ProgramD3D() override; 190 191 const std::vector<PixelShaderOutputVariable> &getPixelShaderKey() { return mPixelShaderKey; } 192 193 GLint getSamplerMapping(gl::ShaderType type, 194 unsigned int samplerIndex, 195 const gl::Caps &caps) const; 196 gl::TextureType getSamplerTextureType(gl::ShaderType type, unsigned int samplerIndex) const; 197 gl::RangeUI getUsedSamplerRange(gl::ShaderType type) const; 198 199 enum SamplerMapping 200 { 201 WasDirty, 202 WasClean, 203 }; 204 205 SamplerMapping updateSamplerMapping(); 206 207 GLint getImageMapping(gl::ShaderType type, 208 unsigned int imageIndex, 209 bool readonly, 210 const gl::Caps &caps) const; 211 gl::RangeUI getUsedImageRange(gl::ShaderType type, bool readonly) const; 212 213 bool usesPointSize() const { return mUsesPointSize; } 214 bool usesPointSpriteEmulation() const; 215 bool usesGeometryShader(const gl::State &state, gl::PrimitiveMode drawMode) const; 216 bool usesGeometryShaderForPointSpriteEmulation() const; 217 bool usesGetDimensionsIgnoresBaseLevel() const; 218 bool usesInstancedPointSpriteEmulation() const; 219 220 std::unique_ptr<LinkEvent> load(const gl::Context *context, 221 gl::BinaryInputStream *stream, 222 gl::InfoLog &infoLog) override; 223 void save(const gl::Context *context, gl::BinaryOutputStream *stream) override; 224 void setBinaryRetrievableHint(bool retrievable) override; 225 void setSeparable(bool separable) override; 226 227 angle::Result getVertexExecutableForCachedInputLayout(d3d::Context *context, 228 ShaderExecutableD3D **outExectuable, 229 gl::InfoLog *infoLog); 230 angle::Result getGeometryExecutableForPrimitiveType(d3d::Context *errContext, 231 const gl::State &state, 232 gl::PrimitiveMode drawMode, 233 ShaderExecutableD3D **outExecutable, 234 gl::InfoLog *infoLog); 235 angle::Result getPixelExecutableForCachedOutputLayout(d3d::Context *context, 236 ShaderExecutableD3D **outExectuable, 237 gl::InfoLog *infoLog); 238 angle::Result getComputeExecutableForImage2DBindLayout(const gl::Context *glContext, 239 d3d::Context *context, 240 ShaderExecutableD3D **outExecutable, 241 gl::InfoLog *infoLog); 242 std::unique_ptr<LinkEvent> link(const gl::Context *context, 243 const gl::ProgramLinkedResources &resources, 244 gl::InfoLog &infoLog, 245 const gl::ProgramMergedVaryings &mergedVaryings) override; 246 GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) override; 247 248 void updateUniformBufferCache(const gl::Caps &caps); 249 250 unsigned int getAtomicCounterBufferRegisterIndex(GLuint binding, 251 gl::ShaderType shaderType) const; 252 253 unsigned int getShaderStorageBufferRegisterIndex(GLuint blockIndex, 254 gl::ShaderType shaderType) const; 255 const std::vector<D3DUBOCache> &getShaderUniformBufferCache(gl::ShaderType shaderType) const; 256 const std::vector<D3DUBOCacheUseSB> &getShaderUniformBufferCacheUseSB( 257 gl::ShaderType shaderType) const; 258 259 void dirtyAllUniforms(); 260 261 void setUniform1fv(GLint location, GLsizei count, const GLfloat *v) override; 262 void setUniform2fv(GLint location, GLsizei count, const GLfloat *v) override; 263 void setUniform3fv(GLint location, GLsizei count, const GLfloat *v) override; 264 void setUniform4fv(GLint location, GLsizei count, const GLfloat *v) override; 265 void setUniform1iv(GLint location, GLsizei count, const GLint *v) override; 266 void setUniform2iv(GLint location, GLsizei count, const GLint *v) override; 267 void setUniform3iv(GLint location, GLsizei count, const GLint *v) override; 268 void setUniform4iv(GLint location, GLsizei count, const GLint *v) override; 269 void setUniform1uiv(GLint location, GLsizei count, const GLuint *v) override; 270 void setUniform2uiv(GLint location, GLsizei count, const GLuint *v) override; 271 void setUniform3uiv(GLint location, GLsizei count, const GLuint *v) override; 272 void setUniform4uiv(GLint location, GLsizei count, const GLuint *v) override; 273 void setUniformMatrix2fv(GLint location, 274 GLsizei count, 275 GLboolean transpose, 276 const GLfloat *value) override; 277 void setUniformMatrix3fv(GLint location, 278 GLsizei count, 279 GLboolean transpose, 280 const GLfloat *value) override; 281 void setUniformMatrix4fv(GLint location, 282 GLsizei count, 283 GLboolean transpose, 284 const GLfloat *value) override; 285 void setUniformMatrix2x3fv(GLint location, 286 GLsizei count, 287 GLboolean transpose, 288 const GLfloat *value) override; 289 void setUniformMatrix3x2fv(GLint location, 290 GLsizei count, 291 GLboolean transpose, 292 const GLfloat *value) override; 293 void setUniformMatrix2x4fv(GLint location, 294 GLsizei count, 295 GLboolean transpose, 296 const GLfloat *value) override; 297 void setUniformMatrix4x2fv(GLint location, 298 GLsizei count, 299 GLboolean transpose, 300 const GLfloat *value) override; 301 void setUniformMatrix3x4fv(GLint location, 302 GLsizei count, 303 GLboolean transpose, 304 const GLfloat *value) override; 305 void setUniformMatrix4x3fv(GLint location, 306 GLsizei count, 307 GLboolean transpose, 308 const GLfloat *value) override; 309 310 void getUniformfv(const gl::Context *context, GLint location, GLfloat *params) const override; 311 void getUniformiv(const gl::Context *context, GLint location, GLint *params) const override; 312 void getUniformuiv(const gl::Context *context, GLint location, GLuint *params) const override; 313 314 UniformStorageD3D *getShaderUniformStorage(gl::ShaderType shaderType) const 315 { 316 return mShaderUniformStorages[shaderType].get(); 317 } 318 319 unsigned int getSerial() const; 320 321 const AttribIndexArray &getAttribLocationToD3DSemantics() const 322 { 323 return mAttribLocationToD3DSemantic; 324 } 325 326 void updateCachedInputLayout(Serial associatedSerial, const gl::State &state); 327 void updateCachedOutputLayout(const gl::Context *context, const gl::Framebuffer *framebuffer); 328 void updateCachedComputeImage2DBindLayout(const gl::Context *context); 329 330 bool isSamplerMappingDirty() { return mDirtySamplerMapping; } 331 332 // Checks if we need to recompile certain shaders. 333 bool hasVertexExecutableForCachedInputLayout(); 334 bool hasGeometryExecutableForPrimitiveType(const gl::State &state, gl::PrimitiveMode drawMode); 335 bool hasPixelExecutableForCachedOutputLayout(); 336 bool hasComputeExecutableForCachedImage2DBindLayout(); 337 338 bool anyShaderUniformsDirty() const { return mShaderUniformsDirty.any(); } 339 340 bool areShaderUniformsDirty(gl::ShaderType shaderType) const 341 { 342 return mShaderUniformsDirty[shaderType]; 343 } 344 const std::vector<D3DUniform *> &getD3DUniforms() const { return mD3DUniforms; } 345 void markUniformsClean(); 346 347 const gl::ProgramState &getState() const { return mState; } 348 349 bool hasShaderStage(gl::ShaderType shaderType) const 350 { 351 return mState.getExecutable().getLinkedShaderStages()[shaderType]; 352 } 353 354 void assignImage2DRegisters(gl::ShaderType shaderType, 355 unsigned int startImageIndex, 356 int startLogicalImageUnit, 357 bool readonly); 358 bool hasNamedUniform(const std::string &name); 359 360 bool usesVertexID() const { return mUsesVertexID; } 361 362 private: 363 // These forward-declared tasks are used for multi-thread shader compiles. 364 class GetExecutableTask; 365 class GetVertexExecutableTask; 366 class GetPixelExecutableTask; 367 class GetGeometryExecutableTask; 368 class GetComputeExecutableTask; 369 class GraphicsProgramLinkEvent; 370 class ComputeProgramLinkEvent; 371 372 class LoadBinaryTask; 373 class LoadBinaryLinkEvent; 374 375 class VertexExecutable 376 { 377 public: 378 enum HLSLAttribType 379 { 380 FLOAT, 381 UNSIGNED_INT, 382 SIGNED_INT, 383 }; 384 385 typedef std::vector<HLSLAttribType> Signature; 386 387 VertexExecutable(const gl::InputLayout &inputLayout, 388 const Signature &signature, 389 ShaderExecutableD3D *shaderExecutable); 390 ~VertexExecutable(); 391 392 bool matchesSignature(const Signature &signature) const; 393 static void getSignature(RendererD3D *renderer, 394 const gl::InputLayout &inputLayout, 395 Signature *signatureOut); 396 397 const gl::InputLayout &inputs() const { return mInputs; } 398 const Signature &signature() const { return mSignature; } 399 ShaderExecutableD3D *shaderExecutable() const { return mShaderExecutable; } 400 401 private: 402 static HLSLAttribType GetAttribType(GLenum type); 403 404 gl::InputLayout mInputs; 405 Signature mSignature; 406 ShaderExecutableD3D *mShaderExecutable; 407 }; 408 409 class PixelExecutable 410 { 411 public: 412 PixelExecutable(const std::vector<GLenum> &outputSignature, 413 ShaderExecutableD3D *shaderExecutable); 414 ~PixelExecutable(); 415 416 bool matchesSignature(const std::vector<GLenum> &signature) const 417 { 418 return mOutputSignature == signature; 419 } 420 421 const std::vector<GLenum> &outputSignature() const { return mOutputSignature; } 422 ShaderExecutableD3D *shaderExecutable() const { return mShaderExecutable; } 423 424 private: 425 std::vector<GLenum> mOutputSignature; 426 ShaderExecutableD3D *mShaderExecutable; 427 }; 428 429 class ComputeExecutable 430 { 431 public: 432 ComputeExecutable(const gl::ImageUnitTextureTypeMap &signature, 433 std::unique_ptr<ShaderExecutableD3D> shaderExecutable); 434 ~ComputeExecutable(); 435 436 bool matchesSignature(const gl::ImageUnitTextureTypeMap &signature) const 437 { 438 return mSignature == signature; 439 } 440 441 const gl::ImageUnitTextureTypeMap &signature() const { return mSignature; } 442 ShaderExecutableD3D *shaderExecutable() const { return mShaderExecutable.get(); } 443 444 private: 445 gl::ImageUnitTextureTypeMap mSignature; 446 std::unique_ptr<ShaderExecutableD3D> mShaderExecutable; 447 }; 448 449 struct Sampler 450 { 451 Sampler(); 452 453 bool active; 454 GLint logicalTextureUnit; 455 gl::TextureType textureType; 456 }; 457 458 struct Image 459 { 460 Image(); 461 bool active; 462 GLint logicalImageUnit; 463 }; 464 465 void initializeUniformStorage(const gl::ShaderBitSet &availableShaderStages); 466 467 void defineUniformsAndAssignRegisters(const gl::Context *context); 468 void defineUniformBase(const gl::Shader *shader, 469 const sh::ShaderVariable &uniform, 470 D3DUniformMap *uniformMap); 471 void assignAllSamplerRegisters(); 472 void assignSamplerRegisters(size_t uniformIndex); 473 474 static void AssignSamplers(unsigned int startSamplerIndex, 475 const gl::UniformTypeInfo &typeInfo, 476 unsigned int samplerCount, 477 std::vector<Sampler> &outSamplers, 478 gl::RangeUI *outUsedRange); 479 480 void assignAllImageRegisters(); 481 void assignAllAtomicCounterRegisters(); 482 void assignImageRegisters(size_t uniformIndex); 483 static void AssignImages(unsigned int startImageIndex, 484 int startLogicalImageUnit, 485 unsigned int imageCount, 486 std::vector<Image> &outImages, 487 gl::RangeUI *outUsedRange); 488 489 template <typename DestT> 490 void getUniformInternal(GLint location, DestT *dataOut) const; 491 492 template <typename T> 493 void setUniformImpl(D3DUniform *targetUniform, 494 const gl::VariableLocation &locationInfo, 495 GLsizei count, 496 const T *v, 497 uint8_t *targetData, 498 GLenum uniformType); 499 500 template <typename T> 501 void setUniformInternal(GLint location, GLsizei count, const T *v, GLenum uniformType); 502 503 template <int cols, int rows> 504 void setUniformMatrixfvInternal(GLint location, 505 GLsizei count, 506 GLboolean transpose, 507 const GLfloat *value); 508 509 std::unique_ptr<LinkEvent> compileProgramExecutables(const gl::Context *context, 510 gl::InfoLog &infoLog); 511 std::unique_ptr<LinkEvent> compileComputeExecutable(const gl::Context *context, 512 gl::InfoLog &infoLog); 513 514 angle::Result loadBinaryShaderExecutables(d3d::Context *contextD3D, 515 gl::BinaryInputStream *stream, 516 gl::InfoLog &infoLog); 517 518 void gatherTransformFeedbackVaryings(const gl::VaryingPacking &varyings, 519 const BuiltinInfo &builtins); 520 D3DUniform *getD3DUniformFromLocation(GLint location); 521 const D3DUniform *getD3DUniformFromLocation(GLint location) const; 522 523 void initAttribLocationsToD3DSemantic(const gl::Context *context); 524 525 void reset(); 526 void initializeUniformBlocks(); 527 void initializeShaderStorageBlocks(const gl::Context *context); 528 529 void updateCachedInputLayoutFromShader(const gl::Context *context); 530 void updateCachedOutputLayoutFromShader(); 531 void updateCachedImage2DBindLayoutFromShader(gl::ShaderType shaderType); 532 void updateCachedVertexExecutableIndex(); 533 void updateCachedPixelExecutableIndex(); 534 void updateCachedComputeExecutableIndex(); 535 536 void linkResources(const gl::Context *context, const gl::ProgramLinkedResources &resources); 537 538 RendererD3D *mRenderer; 539 DynamicHLSL *mDynamicHLSL; 540 541 std::vector<std::unique_ptr<VertexExecutable>> mVertexExecutables; 542 std::vector<std::unique_ptr<PixelExecutable>> mPixelExecutables; 543 angle::PackedEnumMap<gl::PrimitiveMode, std::unique_ptr<ShaderExecutableD3D>> 544 mGeometryExecutables; 545 std::vector<std::unique_ptr<ComputeExecutable>> mComputeExecutables; 546 547 gl::ShaderMap<std::string> mShaderHLSL; 548 gl::ShaderMap<CompilerWorkaroundsD3D> mShaderWorkarounds; 549 550 bool mUsesFragDepth; 551 bool mHasANGLEMultiviewEnabled; 552 bool mUsesVertexID; 553 bool mUsesViewID; 554 std::vector<PixelShaderOutputVariable> mPixelShaderKey; 555 556 // Common code for all dynamic geometry shaders. Consists mainly of the GS input and output 557 // structures, built from the linked varying info. We store the string itself instead of the 558 // packed varyings for simplicity. 559 std::string mGeometryShaderPreamble; 560 561 bool mUsesPointSize; 562 bool mUsesFlatInterpolation; 563 564 gl::ShaderMap<std::unique_ptr<UniformStorageD3D>> mShaderUniformStorages; 565 566 gl::ShaderMap<std::vector<Sampler>> mShaderSamplers; 567 gl::ShaderMap<gl::RangeUI> mUsedShaderSamplerRanges; 568 bool mDirtySamplerMapping; 569 570 gl::ShaderMap<std::vector<Image>> mImages; 571 gl::ShaderMap<std::vector<Image>> mReadonlyImages; 572 gl::ShaderMap<gl::RangeUI> mUsedImageRange; 573 gl::ShaderMap<gl::RangeUI> mUsedReadonlyImageRange; 574 gl::ShaderMap<gl::RangeUI> mUsedAtomicCounterRange; 575 576 // Cache for pixel shader output layout to save reallocations. 577 std::vector<GLenum> mPixelShaderOutputLayoutCache; 578 Optional<size_t> mCachedPixelExecutableIndex; 579 580 AttribIndexArray mAttribLocationToD3DSemantic; 581 582 unsigned int mSerial; 583 584 gl::ShaderMap<std::vector<D3DUBOCache>> mShaderUBOCaches; 585 gl::ShaderMap<std::vector<D3DUBOCacheUseSB>> mShaderUBOCachesUseSB; 586 VertexExecutable::Signature mCachedVertexSignature; 587 gl::InputLayout mCachedInputLayout; 588 Optional<size_t> mCachedVertexExecutableIndex; 589 590 std::vector<D3DVarying> mStreamOutVaryings; 591 std::vector<D3DUniform *> mD3DUniforms; 592 std::map<std::string, int> mImageBindingMap; 593 std::map<std::string, int> mAtomicBindingMap; 594 std::vector<D3DUniformBlock> mD3DUniformBlocks; 595 std::vector<D3DInterfaceBlock> mD3DShaderStorageBlocks; 596 gl::ShaderMap<std::vector<ShaderStorageBlock>> mShaderStorageBlocks; 597 std::array<unsigned int, gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS> 598 mComputeAtomicCounterBufferRegisterIndices; 599 600 gl::ShaderMap<std::vector<sh::ShaderVariable>> mImage2DUniforms; 601 gl::ShaderMap<gl::ImageUnitTextureTypeMap> mImage2DBindLayoutCache; 602 Optional<size_t> mCachedComputeExecutableIndex; 603 604 gl::ShaderBitSet mShaderUniformsDirty; 605 606 static unsigned int issueSerial(); 607 static unsigned int mCurrentSerial; 608 609 Serial mCurrentVertexArrayStateSerial; 610 }; 611 } // namespace rx 612 613 #endif // LIBANGLE_RENDERER_D3D_PROGRAMD3D_H_