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.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; isArrayD3DUniform57 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 activeInShaderD3DInterfaceBlock91 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 D3DUBOCache 110 { 111 unsigned int registerIndex; 112 int binding; 113 }; 114 115 struct D3DUBOCacheUseSB : D3DUBOCache 116 { 117 unsigned int byteWidth; 118 unsigned int structureByteStride; 119 }; 120 121 struct D3DVarying final 122 { 123 D3DVarying(); 124 D3DVarying(const std::string &semanticNameIn, 125 unsigned int semanticIndexIn, 126 unsigned int componentCountIn, 127 unsigned int outputSlotIn); 128 129 D3DVarying(const D3DVarying &) = default; 130 D3DVarying &operator=(const D3DVarying &) = default; 131 132 std::string semanticName; 133 unsigned int semanticIndex; 134 unsigned int componentCount; 135 unsigned int outputSlot; 136 }; 137 138 class ProgramD3DMetadata final : angle::NonCopyable 139 { 140 public: 141 ProgramD3DMetadata(RendererD3D *renderer, 142 const gl::ShaderMap<const ShaderD3D *> &attachedShaders, 143 EGLenum clientType); 144 ~ProgramD3DMetadata(); 145 146 int getRendererMajorShaderModel() const; 147 bool usesBroadcast(const gl::State &data) const; 148 bool usesSecondaryColor() const; 149 bool usesFragDepth() const; 150 bool usesPointCoord() const; 151 bool usesFragCoord() const; 152 bool usesPointSize() const; 153 bool usesInsertedPointCoordValue() const; 154 bool usesViewScale() const; 155 bool hasANGLEMultiviewEnabled() const; 156 bool usesVertexID() const; 157 bool usesViewID() const; 158 bool canSelectViewInVertexShader() const; 159 bool addsPointCoordToVertexShader() const; 160 bool usesTransformFeedbackGLPosition() const; 161 bool usesSystemValuePointSize() const; 162 bool usesMultipleFragmentOuts() const; 163 bool usesCustomOutVars() const; 164 const ShaderD3D *getFragmentShader() const; 165 166 private: 167 const int mRendererMajorShaderModel; 168 const std::string mShaderModelSuffix; 169 const bool mUsesInstancedPointSpriteEmulation; 170 const bool mUsesViewScale; 171 const bool mCanSelectViewInVertexShader; 172 const gl::ShaderMap<const ShaderD3D *> mAttachedShaders; 173 const EGLenum mClientType; 174 }; 175 176 using D3DUniformMap = std::map<std::string, D3DUniform *>; 177 178 class ProgramD3D : public ProgramImpl 179 { 180 public: 181 ProgramD3D(const gl::ProgramState &data, RendererD3D *renderer); 182 ~ProgramD3D() override; 183 getPixelShaderKey()184 const std::vector<PixelShaderOutputVariable> &getPixelShaderKey() { return mPixelShaderKey; } 185 186 GLint getSamplerMapping(gl::ShaderType type, 187 unsigned int samplerIndex, 188 const gl::Caps &caps) const; 189 gl::TextureType getSamplerTextureType(gl::ShaderType type, unsigned int samplerIndex) const; 190 gl::RangeUI getUsedSamplerRange(gl::ShaderType type) const; 191 192 enum SamplerMapping 193 { 194 WasDirty, 195 WasClean, 196 }; 197 198 SamplerMapping updateSamplerMapping(); 199 200 GLint getImageMapping(gl::ShaderType type, 201 unsigned int imageIndex, 202 bool readonly, 203 const gl::Caps &caps) const; 204 gl::RangeUI getUsedImageRange(gl::ShaderType type, bool readonly) const; 205 usesPointSize()206 bool usesPointSize() const { return mUsesPointSize; } 207 bool usesPointSpriteEmulation() const; 208 bool usesGeometryShader(const gl::State &state, gl::PrimitiveMode drawMode) const; 209 bool usesGeometryShaderForPointSpriteEmulation() const; 210 bool usesGetDimensionsIgnoresBaseLevel() const; 211 bool usesInstancedPointSpriteEmulation() const; 212 213 std::unique_ptr<LinkEvent> load(const gl::Context *context, 214 gl::BinaryInputStream *stream, 215 gl::InfoLog &infoLog) override; 216 void save(const gl::Context *context, gl::BinaryOutputStream *stream) override; 217 void setBinaryRetrievableHint(bool retrievable) override; 218 void setSeparable(bool separable) override; 219 220 angle::Result getVertexExecutableForCachedInputLayout(d3d::Context *context, 221 ShaderExecutableD3D **outExectuable, 222 gl::InfoLog *infoLog); 223 angle::Result getGeometryExecutableForPrimitiveType(d3d::Context *errContext, 224 const gl::State &state, 225 gl::PrimitiveMode drawMode, 226 ShaderExecutableD3D **outExecutable, 227 gl::InfoLog *infoLog); 228 angle::Result getPixelExecutableForCachedOutputLayout(d3d::Context *context, 229 ShaderExecutableD3D **outExectuable, 230 gl::InfoLog *infoLog); 231 angle::Result getComputeExecutableForImage2DBindLayout(d3d::Context *context, 232 ShaderExecutableD3D **outExecutable, 233 gl::InfoLog *infoLog); 234 std::unique_ptr<LinkEvent> link(const gl::Context *context, 235 const gl::ProgramLinkedResources &resources, 236 gl::InfoLog &infoLog, 237 const gl::ProgramMergedVaryings &mergedVaryings) override; 238 GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) override; 239 240 void updateUniformBufferCache(const gl::Caps &caps); 241 242 unsigned int getAtomicCounterBufferRegisterIndex(GLuint binding, 243 gl::ShaderType shaderType) const; 244 245 unsigned int getShaderStorageBufferRegisterIndex(GLuint blockIndex, 246 gl::ShaderType shaderType) const; 247 const std::vector<D3DUBOCache> &getShaderUniformBufferCache(gl::ShaderType shaderType) const; 248 const std::vector<D3DUBOCacheUseSB> &getShaderUniformBufferCacheUseSB( 249 gl::ShaderType shaderType) const; 250 251 void dirtyAllUniforms(); 252 253 void setUniform1fv(GLint location, GLsizei count, const GLfloat *v) override; 254 void setUniform2fv(GLint location, GLsizei count, const GLfloat *v) override; 255 void setUniform3fv(GLint location, GLsizei count, const GLfloat *v) override; 256 void setUniform4fv(GLint location, GLsizei count, const GLfloat *v) override; 257 void setUniform1iv(GLint location, GLsizei count, const GLint *v) override; 258 void setUniform2iv(GLint location, GLsizei count, const GLint *v) override; 259 void setUniform3iv(GLint location, GLsizei count, const GLint *v) override; 260 void setUniform4iv(GLint location, GLsizei count, const GLint *v) override; 261 void setUniform1uiv(GLint location, GLsizei count, const GLuint *v) override; 262 void setUniform2uiv(GLint location, GLsizei count, const GLuint *v) override; 263 void setUniform3uiv(GLint location, GLsizei count, const GLuint *v) override; 264 void setUniform4uiv(GLint location, GLsizei count, const GLuint *v) override; 265 void setUniformMatrix2fv(GLint location, 266 GLsizei count, 267 GLboolean transpose, 268 const GLfloat *value) override; 269 void setUniformMatrix3fv(GLint location, 270 GLsizei count, 271 GLboolean transpose, 272 const GLfloat *value) override; 273 void setUniformMatrix4fv(GLint location, 274 GLsizei count, 275 GLboolean transpose, 276 const GLfloat *value) override; 277 void setUniformMatrix2x3fv(GLint location, 278 GLsizei count, 279 GLboolean transpose, 280 const GLfloat *value) override; 281 void setUniformMatrix3x2fv(GLint location, 282 GLsizei count, 283 GLboolean transpose, 284 const GLfloat *value) override; 285 void setUniformMatrix2x4fv(GLint location, 286 GLsizei count, 287 GLboolean transpose, 288 const GLfloat *value) override; 289 void setUniformMatrix4x2fv(GLint location, 290 GLsizei count, 291 GLboolean transpose, 292 const GLfloat *value) override; 293 void setUniformMatrix3x4fv(GLint location, 294 GLsizei count, 295 GLboolean transpose, 296 const GLfloat *value) override; 297 void setUniformMatrix4x3fv(GLint location, 298 GLsizei count, 299 GLboolean transpose, 300 const GLfloat *value) override; 301 302 void getUniformfv(const gl::Context *context, GLint location, GLfloat *params) const override; 303 void getUniformiv(const gl::Context *context, GLint location, GLint *params) const override; 304 void getUniformuiv(const gl::Context *context, GLint location, GLuint *params) const override; 305 getShaderUniformStorage(gl::ShaderType shaderType)306 UniformStorageD3D *getShaderUniformStorage(gl::ShaderType shaderType) const 307 { 308 return mShaderUniformStorages[shaderType].get(); 309 } 310 311 unsigned int getSerial() const; 312 getAttribLocationToD3DSemantics()313 const AttribIndexArray &getAttribLocationToD3DSemantics() const 314 { 315 return mAttribLocationToD3DSemantic; 316 } 317 318 void updateCachedInputLayout(Serial associatedSerial, const gl::State &state); 319 void updateCachedOutputLayout(const gl::Context *context, const gl::Framebuffer *framebuffer); 320 void updateCachedComputeImage2DBindLayout(const gl::Context *context); 321 isSamplerMappingDirty()322 bool isSamplerMappingDirty() { return mDirtySamplerMapping; } 323 324 // Checks if we need to recompile certain shaders. 325 bool hasVertexExecutableForCachedInputLayout(); 326 bool hasGeometryExecutableForPrimitiveType(const gl::State &state, gl::PrimitiveMode drawMode); 327 bool hasPixelExecutableForCachedOutputLayout(); 328 bool hasComputeExecutableForCachedImage2DBindLayout(); 329 anyShaderUniformsDirty()330 bool anyShaderUniformsDirty() const { return mShaderUniformsDirty.any(); } 331 areShaderUniformsDirty(gl::ShaderType shaderType)332 bool areShaderUniformsDirty(gl::ShaderType shaderType) const 333 { 334 return mShaderUniformsDirty[shaderType]; 335 } getD3DUniforms()336 const std::vector<D3DUniform *> &getD3DUniforms() const { return mD3DUniforms; } 337 void markUniformsClean(); 338 getState()339 const gl::ProgramState &getState() const { return mState; } 340 hasShaderStage(gl::ShaderType shaderType)341 bool hasShaderStage(gl::ShaderType shaderType) const 342 { 343 return mState.getExecutable().getLinkedShaderStages()[shaderType]; 344 } 345 346 void assignImage2DRegisters(unsigned int startImageIndex, 347 int startLogicalImageUnit, 348 bool readonly); 349 bool hasNamedUniform(const std::string &name); 350 usesVertexID()351 bool usesVertexID() const { return mUsesVertexID; } 352 353 private: 354 // These forward-declared tasks are used for multi-thread shader compiles. 355 class GetExecutableTask; 356 class GetVertexExecutableTask; 357 class GetPixelExecutableTask; 358 class GetGeometryExecutableTask; 359 class GetComputeExecutableTask; 360 class GraphicsProgramLinkEvent; 361 class ComputeProgramLinkEvent; 362 363 class LoadBinaryTask; 364 class LoadBinaryLinkEvent; 365 366 class VertexExecutable 367 { 368 public: 369 enum HLSLAttribType 370 { 371 FLOAT, 372 UNSIGNED_INT, 373 SIGNED_INT, 374 }; 375 376 typedef std::vector<HLSLAttribType> Signature; 377 378 VertexExecutable(const gl::InputLayout &inputLayout, 379 const Signature &signature, 380 ShaderExecutableD3D *shaderExecutable); 381 ~VertexExecutable(); 382 383 bool matchesSignature(const Signature &signature) const; 384 static void getSignature(RendererD3D *renderer, 385 const gl::InputLayout &inputLayout, 386 Signature *signatureOut); 387 inputs()388 const gl::InputLayout &inputs() const { return mInputs; } signature()389 const Signature &signature() const { return mSignature; } shaderExecutable()390 ShaderExecutableD3D *shaderExecutable() const { return mShaderExecutable; } 391 392 private: 393 static HLSLAttribType GetAttribType(GLenum type); 394 395 gl::InputLayout mInputs; 396 Signature mSignature; 397 ShaderExecutableD3D *mShaderExecutable; 398 }; 399 400 class PixelExecutable 401 { 402 public: 403 PixelExecutable(const std::vector<GLenum> &outputSignature, 404 ShaderExecutableD3D *shaderExecutable); 405 ~PixelExecutable(); 406 matchesSignature(const std::vector<GLenum> & signature)407 bool matchesSignature(const std::vector<GLenum> &signature) const 408 { 409 return mOutputSignature == signature; 410 } 411 outputSignature()412 const std::vector<GLenum> &outputSignature() const { return mOutputSignature; } shaderExecutable()413 ShaderExecutableD3D *shaderExecutable() const { return mShaderExecutable; } 414 415 private: 416 std::vector<GLenum> mOutputSignature; 417 ShaderExecutableD3D *mShaderExecutable; 418 }; 419 420 class ComputeExecutable 421 { 422 public: 423 ComputeExecutable(const gl::ImageUnitTextureTypeMap &signature, 424 std::unique_ptr<ShaderExecutableD3D> shaderExecutable); 425 ~ComputeExecutable(); 426 matchesSignature(const gl::ImageUnitTextureTypeMap & signature)427 bool matchesSignature(const gl::ImageUnitTextureTypeMap &signature) const 428 { 429 return mSignature == signature; 430 } 431 signature()432 const gl::ImageUnitTextureTypeMap &signature() const { return mSignature; } shaderExecutable()433 ShaderExecutableD3D *shaderExecutable() const { return mShaderExecutable.get(); } 434 435 private: 436 gl::ImageUnitTextureTypeMap mSignature; 437 std::unique_ptr<ShaderExecutableD3D> mShaderExecutable; 438 }; 439 440 struct Sampler 441 { 442 Sampler(); 443 444 bool active; 445 GLint logicalTextureUnit; 446 gl::TextureType textureType; 447 }; 448 449 struct Image 450 { 451 Image(); 452 bool active; 453 GLint logicalImageUnit; 454 }; 455 456 void initializeUniformStorage(const gl::ShaderBitSet &availableShaderStages); 457 458 void defineUniformsAndAssignRegisters(); 459 void defineUniformBase(const gl::Shader *shader, 460 const sh::ShaderVariable &uniform, 461 D3DUniformMap *uniformMap); 462 void assignAllSamplerRegisters(); 463 void assignSamplerRegisters(size_t uniformIndex); 464 465 static void AssignSamplers(unsigned int startSamplerIndex, 466 const gl::UniformTypeInfo &typeInfo, 467 unsigned int samplerCount, 468 std::vector<Sampler> &outSamplers, 469 gl::RangeUI *outUsedRange); 470 471 void assignAllImageRegisters(); 472 void assignAllAtomicCounterRegisters(); 473 void assignImageRegisters(size_t uniformIndex); 474 static void AssignImages(unsigned int startImageIndex, 475 int startLogicalImageUnit, 476 unsigned int imageCount, 477 std::vector<Image> &outImages, 478 gl::RangeUI *outUsedRange); 479 480 template <typename DestT> 481 void getUniformInternal(GLint location, DestT *dataOut) const; 482 483 template <typename T> 484 void setUniformImpl(D3DUniform *targetUniform, 485 const gl::VariableLocation &locationInfo, 486 GLsizei count, 487 const T *v, 488 uint8_t *targetData, 489 GLenum uniformType); 490 491 template <typename T> 492 void setUniformInternal(GLint location, GLsizei count, const T *v, GLenum uniformType); 493 494 template <int cols, int rows> 495 void setUniformMatrixfvInternal(GLint location, 496 GLsizei count, 497 GLboolean transpose, 498 const GLfloat *value); 499 500 std::unique_ptr<LinkEvent> compileProgramExecutables(const gl::Context *context, 501 gl::InfoLog &infoLog); 502 std::unique_ptr<LinkEvent> compileComputeExecutable(const gl::Context *context, 503 gl::InfoLog &infoLog); 504 505 angle::Result loadBinaryShaderExecutables(d3d::Context *contextD3D, 506 gl::BinaryInputStream *stream, 507 gl::InfoLog &infoLog); 508 509 void gatherTransformFeedbackVaryings(const gl::VaryingPacking &varyings, 510 const BuiltinInfo &builtins); 511 D3DUniform *getD3DUniformFromLocation(GLint location); 512 const D3DUniform *getD3DUniformFromLocation(GLint location) const; 513 514 void initAttribLocationsToD3DSemantic(); 515 516 void reset(); 517 void initializeUniformBlocks(); 518 void initializeShaderStorageBlocks(); 519 520 void updateCachedInputLayoutFromShader(); 521 void updateCachedOutputLayoutFromShader(); 522 void updateCachedImage2DBindLayoutFromComputeShader(); 523 void updateCachedVertexExecutableIndex(); 524 void updateCachedPixelExecutableIndex(); 525 void updateCachedComputeExecutableIndex(); 526 527 void linkResources(const gl::ProgramLinkedResources &resources); 528 529 RendererD3D *mRenderer; 530 DynamicHLSL *mDynamicHLSL; 531 532 std::vector<std::unique_ptr<VertexExecutable>> mVertexExecutables; 533 std::vector<std::unique_ptr<PixelExecutable>> mPixelExecutables; 534 angle::PackedEnumMap<gl::PrimitiveMode, std::unique_ptr<ShaderExecutableD3D>> 535 mGeometryExecutables; 536 std::vector<std::unique_ptr<ComputeExecutable>> mComputeExecutables; 537 538 gl::ShaderMap<std::string> mShaderHLSL; 539 gl::ShaderMap<angle::CompilerWorkaroundsD3D> mShaderWorkarounds; 540 541 bool mUsesFragDepth; 542 bool mHasANGLEMultiviewEnabled; 543 bool mUsesVertexID; 544 bool mUsesViewID; 545 std::vector<PixelShaderOutputVariable> mPixelShaderKey; 546 547 // Common code for all dynamic geometry shaders. Consists mainly of the GS input and output 548 // structures, built from the linked varying info. We store the string itself instead of the 549 // packed varyings for simplicity. 550 std::string mGeometryShaderPreamble; 551 552 bool mUsesPointSize; 553 bool mUsesFlatInterpolation; 554 555 gl::ShaderMap<std::unique_ptr<UniformStorageD3D>> mShaderUniformStorages; 556 557 gl::ShaderMap<std::vector<Sampler>> mShaderSamplers; 558 gl::ShaderMap<gl::RangeUI> mUsedShaderSamplerRanges; 559 bool mDirtySamplerMapping; 560 561 std::vector<Image> mImagesCS; 562 std::vector<Image> mReadonlyImagesCS; 563 gl::RangeUI mUsedComputeImageRange; 564 gl::RangeUI mUsedComputeReadonlyImageRange; 565 gl::RangeUI mUsedComputeAtomicCounterRange; 566 567 // Cache for pixel shader output layout to save reallocations. 568 std::vector<GLenum> mPixelShaderOutputLayoutCache; 569 Optional<size_t> mCachedPixelExecutableIndex; 570 571 AttribIndexArray mAttribLocationToD3DSemantic; 572 573 unsigned int mSerial; 574 575 gl::ShaderMap<std::vector<D3DUBOCache>> mShaderUBOCaches; 576 gl::ShaderMap<std::vector<D3DUBOCacheUseSB>> mShaderUBOCachesUseSB; 577 VertexExecutable::Signature mCachedVertexSignature; 578 gl::InputLayout mCachedInputLayout; 579 Optional<size_t> mCachedVertexExecutableIndex; 580 581 std::vector<D3DVarying> mStreamOutVaryings; 582 std::vector<D3DUniform *> mD3DUniforms; 583 std::map<std::string, int> mImageBindingMap; 584 std::map<std::string, int> mAtomicBindingMap; 585 std::vector<D3DUniformBlock> mD3DUniformBlocks; 586 std::vector<D3DInterfaceBlock> mD3DShaderStorageBlocks; 587 std::array<unsigned int, gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS> 588 mComputeAtomicCounterBufferRegisterIndices; 589 590 std::vector<sh::ShaderVariable> mImage2DUniforms; 591 gl::ImageUnitTextureTypeMap mComputeShaderImage2DBindLayoutCache; 592 Optional<size_t> mCachedComputeExecutableIndex; 593 594 gl::ShaderBitSet mShaderUniformsDirty; 595 596 static unsigned int issueSerial(); 597 static unsigned int mCurrentSerial; 598 599 Serial mCurrentVertexArrayStateSerial; 600 }; 601 } // namespace rx 602 603 #endif // LIBANGLE_RENDERER_D3D_PROGRAMD3D_H_ 604