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) override; 237 GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) override; 238 239 void updateUniformBufferCache(const gl::Caps &caps); 240 241 unsigned int getAtomicCounterBufferRegisterIndex(GLuint binding, 242 gl::ShaderType shaderType) const; 243 244 unsigned int getShaderStorageBufferRegisterIndex(GLuint blockIndex, 245 gl::ShaderType shaderType) const; 246 const std::vector<D3DUBOCache> &getShaderUniformBufferCache(gl::ShaderType shaderType) const; 247 const std::vector<D3DUBOCacheUseSB> &getShaderUniformBufferCacheUseSB( 248 gl::ShaderType shaderType) const; 249 250 void dirtyAllUniforms(); 251 252 void setUniform1fv(GLint location, GLsizei count, const GLfloat *v) override; 253 void setUniform2fv(GLint location, GLsizei count, const GLfloat *v) override; 254 void setUniform3fv(GLint location, GLsizei count, const GLfloat *v) override; 255 void setUniform4fv(GLint location, GLsizei count, const GLfloat *v) override; 256 void setUniform1iv(GLint location, GLsizei count, const GLint *v) override; 257 void setUniform2iv(GLint location, GLsizei count, const GLint *v) override; 258 void setUniform3iv(GLint location, GLsizei count, const GLint *v) override; 259 void setUniform4iv(GLint location, GLsizei count, const GLint *v) override; 260 void setUniform1uiv(GLint location, GLsizei count, const GLuint *v) override; 261 void setUniform2uiv(GLint location, GLsizei count, const GLuint *v) override; 262 void setUniform3uiv(GLint location, GLsizei count, const GLuint *v) override; 263 void setUniform4uiv(GLint location, GLsizei count, const GLuint *v) override; 264 void setUniformMatrix2fv(GLint location, 265 GLsizei count, 266 GLboolean transpose, 267 const GLfloat *value) override; 268 void setUniformMatrix3fv(GLint location, 269 GLsizei count, 270 GLboolean transpose, 271 const GLfloat *value) override; 272 void setUniformMatrix4fv(GLint location, 273 GLsizei count, 274 GLboolean transpose, 275 const GLfloat *value) override; 276 void setUniformMatrix2x3fv(GLint location, 277 GLsizei count, 278 GLboolean transpose, 279 const GLfloat *value) override; 280 void setUniformMatrix3x2fv(GLint location, 281 GLsizei count, 282 GLboolean transpose, 283 const GLfloat *value) override; 284 void setUniformMatrix2x4fv(GLint location, 285 GLsizei count, 286 GLboolean transpose, 287 const GLfloat *value) override; 288 void setUniformMatrix4x2fv(GLint location, 289 GLsizei count, 290 GLboolean transpose, 291 const GLfloat *value) override; 292 void setUniformMatrix3x4fv(GLint location, 293 GLsizei count, 294 GLboolean transpose, 295 const GLfloat *value) override; 296 void setUniformMatrix4x3fv(GLint location, 297 GLsizei count, 298 GLboolean transpose, 299 const GLfloat *value) override; 300 301 void getUniformfv(const gl::Context *context, GLint location, GLfloat *params) const override; 302 void getUniformiv(const gl::Context *context, GLint location, GLint *params) const override; 303 void getUniformuiv(const gl::Context *context, GLint location, GLuint *params) const override; 304 getShaderUniformStorage(gl::ShaderType shaderType)305 UniformStorageD3D *getShaderUniformStorage(gl::ShaderType shaderType) const 306 { 307 return mShaderUniformStorages[shaderType].get(); 308 } 309 310 unsigned int getSerial() const; 311 getAttribLocationToD3DSemantics()312 const AttribIndexArray &getAttribLocationToD3DSemantics() const 313 { 314 return mAttribLocationToD3DSemantic; 315 } 316 317 void updateCachedInputLayout(Serial associatedSerial, const gl::State &state); 318 void updateCachedOutputLayout(const gl::Context *context, const gl::Framebuffer *framebuffer); 319 void updateCachedComputeImage2DBindLayout(const gl::Context *context); 320 isSamplerMappingDirty()321 bool isSamplerMappingDirty() { return mDirtySamplerMapping; } 322 323 // Checks if we need to recompile certain shaders. 324 bool hasVertexExecutableForCachedInputLayout(); 325 bool hasGeometryExecutableForPrimitiveType(const gl::State &state, gl::PrimitiveMode drawMode); 326 bool hasPixelExecutableForCachedOutputLayout(); 327 bool hasComputeExecutableForCachedImage2DBindLayout(); 328 anyShaderUniformsDirty()329 bool anyShaderUniformsDirty() const { return mShaderUniformsDirty.any(); } 330 areShaderUniformsDirty(gl::ShaderType shaderType)331 bool areShaderUniformsDirty(gl::ShaderType shaderType) const 332 { 333 return mShaderUniformsDirty[shaderType]; 334 } getD3DUniforms()335 const std::vector<D3DUniform *> &getD3DUniforms() const { return mD3DUniforms; } 336 void markUniformsClean(); 337 getState()338 const gl::ProgramState &getState() const { return mState; } 339 hasShaderStage(gl::ShaderType shaderType)340 bool hasShaderStage(gl::ShaderType shaderType) const 341 { 342 return mState.getProgramExecutable().getLinkedShaderStages()[shaderType]; 343 } 344 345 void assignImage2DRegisters(unsigned int startImageIndex, 346 int startLogicalImageUnit, 347 bool readonly); 348 bool hasNamedUniform(const std::string &name); 349 usesVertexID()350 bool usesVertexID() const { return mUsesVertexID; } 351 352 private: 353 // These forward-declared tasks are used for multi-thread shader compiles. 354 class GetExecutableTask; 355 class GetVertexExecutableTask; 356 class GetPixelExecutableTask; 357 class GetGeometryExecutableTask; 358 class GetComputeExecutableTask; 359 class GraphicsProgramLinkEvent; 360 class ComputeProgramLinkEvent; 361 362 class LoadBinaryTask; 363 class LoadBinaryLinkEvent; 364 365 class VertexExecutable 366 { 367 public: 368 enum HLSLAttribType 369 { 370 FLOAT, 371 UNSIGNED_INT, 372 SIGNED_INT, 373 }; 374 375 typedef std::vector<HLSLAttribType> Signature; 376 377 VertexExecutable(const gl::InputLayout &inputLayout, 378 const Signature &signature, 379 ShaderExecutableD3D *shaderExecutable); 380 ~VertexExecutable(); 381 382 bool matchesSignature(const Signature &signature) const; 383 static void getSignature(RendererD3D *renderer, 384 const gl::InputLayout &inputLayout, 385 Signature *signatureOut); 386 inputs()387 const gl::InputLayout &inputs() const { return mInputs; } signature()388 const Signature &signature() const { return mSignature; } shaderExecutable()389 ShaderExecutableD3D *shaderExecutable() const { return mShaderExecutable; } 390 391 private: 392 static HLSLAttribType GetAttribType(GLenum type); 393 394 gl::InputLayout mInputs; 395 Signature mSignature; 396 ShaderExecutableD3D *mShaderExecutable; 397 }; 398 399 class PixelExecutable 400 { 401 public: 402 PixelExecutable(const std::vector<GLenum> &outputSignature, 403 ShaderExecutableD3D *shaderExecutable); 404 ~PixelExecutable(); 405 matchesSignature(const std::vector<GLenum> & signature)406 bool matchesSignature(const std::vector<GLenum> &signature) const 407 { 408 return mOutputSignature == signature; 409 } 410 outputSignature()411 const std::vector<GLenum> &outputSignature() const { return mOutputSignature; } shaderExecutable()412 ShaderExecutableD3D *shaderExecutable() const { return mShaderExecutable; } 413 414 private: 415 std::vector<GLenum> mOutputSignature; 416 ShaderExecutableD3D *mShaderExecutable; 417 }; 418 419 class ComputeExecutable 420 { 421 public: 422 ComputeExecutable(const gl::ImageUnitTextureTypeMap &signature, 423 std::unique_ptr<ShaderExecutableD3D> shaderExecutable); 424 ~ComputeExecutable(); 425 matchesSignature(const gl::ImageUnitTextureTypeMap & signature)426 bool matchesSignature(const gl::ImageUnitTextureTypeMap &signature) const 427 { 428 return mSignature == signature; 429 } 430 signature()431 const gl::ImageUnitTextureTypeMap &signature() const { return mSignature; } shaderExecutable()432 ShaderExecutableD3D *shaderExecutable() const { return mShaderExecutable.get(); } 433 434 private: 435 gl::ImageUnitTextureTypeMap mSignature; 436 std::unique_ptr<ShaderExecutableD3D> mShaderExecutable; 437 }; 438 439 struct Sampler 440 { 441 Sampler(); 442 443 bool active; 444 GLint logicalTextureUnit; 445 gl::TextureType textureType; 446 }; 447 448 struct Image 449 { 450 Image(); 451 bool active; 452 GLint logicalImageUnit; 453 }; 454 455 void initializeUniformStorage(const gl::ShaderBitSet &availableShaderStages); 456 457 void defineUniformsAndAssignRegisters(); 458 void defineUniformBase(const gl::Shader *shader, 459 const sh::ShaderVariable &uniform, 460 D3DUniformMap *uniformMap); 461 void assignAllSamplerRegisters(); 462 void assignSamplerRegisters(size_t uniformIndex); 463 464 static void AssignSamplers(unsigned int startSamplerIndex, 465 const gl::UniformTypeInfo &typeInfo, 466 unsigned int samplerCount, 467 std::vector<Sampler> &outSamplers, 468 gl::RangeUI *outUsedRange); 469 470 void assignAllImageRegisters(); 471 void assignAllAtomicCounterRegisters(); 472 void assignImageRegisters(size_t uniformIndex); 473 static void AssignImages(unsigned int startImageIndex, 474 int startLogicalImageUnit, 475 unsigned int imageCount, 476 std::vector<Image> &outImages, 477 gl::RangeUI *outUsedRange); 478 479 template <typename DestT> 480 void getUniformInternal(GLint location, DestT *dataOut) const; 481 482 template <typename T> 483 void setUniformImpl(const gl::VariableLocation &locationInfo, 484 GLsizei count, 485 const T *v, 486 uint8_t *targetData, 487 GLenum uniformType); 488 489 template <typename T> 490 void setUniformInternal(GLint location, GLsizei count, const T *v, GLenum uniformType); 491 492 template <int cols, int rows> 493 void setUniformMatrixfvInternal(GLint location, 494 GLsizei count, 495 GLboolean transpose, 496 const GLfloat *value); 497 498 std::unique_ptr<LinkEvent> compileProgramExecutables(const gl::Context *context, 499 gl::InfoLog &infoLog); 500 std::unique_ptr<LinkEvent> compileComputeExecutable(const gl::Context *context, 501 gl::InfoLog &infoLog); 502 503 angle::Result loadBinaryShaderExecutables(d3d::Context *contextD3D, 504 gl::BinaryInputStream *stream, 505 gl::InfoLog &infoLog); 506 507 void gatherTransformFeedbackVaryings(const gl::VaryingPacking &varyings, 508 const BuiltinInfo &builtins); 509 D3DUniform *getD3DUniformFromLocation(GLint location); 510 const D3DUniform *getD3DUniformFromLocation(GLint location) const; 511 512 void initAttribLocationsToD3DSemantic(); 513 514 void reset(); 515 void initializeUniformBlocks(); 516 void initializeShaderStorageBlocks(); 517 518 void updateCachedInputLayoutFromShader(); 519 void updateCachedOutputLayoutFromShader(); 520 void updateCachedImage2DBindLayoutFromComputeShader(); 521 void updateCachedVertexExecutableIndex(); 522 void updateCachedPixelExecutableIndex(); 523 void updateCachedComputeExecutableIndex(); 524 525 void linkResources(const gl::ProgramLinkedResources &resources); 526 527 RendererD3D *mRenderer; 528 DynamicHLSL *mDynamicHLSL; 529 530 std::vector<std::unique_ptr<VertexExecutable>> mVertexExecutables; 531 std::vector<std::unique_ptr<PixelExecutable>> mPixelExecutables; 532 angle::PackedEnumMap<gl::PrimitiveMode, std::unique_ptr<ShaderExecutableD3D>> 533 mGeometryExecutables; 534 std::vector<std::unique_ptr<ComputeExecutable>> mComputeExecutables; 535 536 gl::ShaderMap<std::string> mShaderHLSL; 537 gl::ShaderMap<angle::CompilerWorkaroundsD3D> mShaderWorkarounds; 538 539 bool mUsesFragDepth; 540 bool mHasANGLEMultiviewEnabled; 541 bool mUsesVertexID; 542 bool mUsesViewID; 543 std::vector<PixelShaderOutputVariable> mPixelShaderKey; 544 545 // Common code for all dynamic geometry shaders. Consists mainly of the GS input and output 546 // structures, built from the linked varying info. We store the string itself instead of the 547 // packed varyings for simplicity. 548 std::string mGeometryShaderPreamble; 549 550 bool mUsesPointSize; 551 bool mUsesFlatInterpolation; 552 553 gl::ShaderMap<std::unique_ptr<UniformStorageD3D>> mShaderUniformStorages; 554 555 gl::ShaderMap<std::vector<Sampler>> mShaderSamplers; 556 gl::ShaderMap<gl::RangeUI> mUsedShaderSamplerRanges; 557 bool mDirtySamplerMapping; 558 559 std::vector<Image> mImagesCS; 560 std::vector<Image> mReadonlyImagesCS; 561 gl::RangeUI mUsedComputeImageRange; 562 gl::RangeUI mUsedComputeReadonlyImageRange; 563 gl::RangeUI mUsedComputeAtomicCounterRange; 564 565 // Cache for pixel shader output layout to save reallocations. 566 std::vector<GLenum> mPixelShaderOutputLayoutCache; 567 Optional<size_t> mCachedPixelExecutableIndex; 568 569 AttribIndexArray mAttribLocationToD3DSemantic; 570 571 unsigned int mSerial; 572 573 gl::ShaderMap<std::vector<D3DUBOCache>> mShaderUBOCaches; 574 gl::ShaderMap<std::vector<D3DUBOCacheUseSB>> mShaderUBOCachesUseSB; 575 VertexExecutable::Signature mCachedVertexSignature; 576 gl::InputLayout mCachedInputLayout; 577 Optional<size_t> mCachedVertexExecutableIndex; 578 579 std::vector<D3DVarying> mStreamOutVaryings; 580 std::vector<D3DUniform *> mD3DUniforms; 581 std::map<std::string, int> mImageBindingMap; 582 std::map<std::string, int> mAtomicBindingMap; 583 std::vector<D3DUniformBlock> mD3DUniformBlocks; 584 std::vector<D3DInterfaceBlock> mD3DShaderStorageBlocks; 585 std::array<unsigned int, gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFERS> 586 mComputeAtomicCounterBufferRegisterIndices; 587 588 std::vector<sh::ShaderVariable> mImage2DUniforms; 589 gl::ImageUnitTextureTypeMap mComputeShaderImage2DBindLayoutCache; 590 Optional<size_t> mCachedComputeExecutableIndex; 591 592 gl::ShaderBitSet mShaderUniformsDirty; 593 594 static unsigned int issueSerial(); 595 static unsigned int mCurrentSerial; 596 597 Serial mCurrentVertexArrayStateSerial; 598 }; 599 } // namespace rx 600 601 #endif // LIBANGLE_RENDERER_D3D_PROGRAMD3D_H_ 602