1 // 2 // Copyright (c) 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 "platform/WorkaroundsD3D.h" 21 22 namespace rx 23 { 24 class RendererD3D; 25 class UniformStorageD3D; 26 class ShaderExecutableD3D; 27 28 #if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL) 29 // WARNING: D3DCOMPILE_OPTIMIZATION_LEVEL3 may lead to a DX9 shader compiler hang. 30 // It should only be used selectively to work around specific bugs. 31 #define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL1 32 #endif 33 34 // Helper struct representing a single shader uniform 35 // TODO(jmadill): Make uniform blocks shared between all programs, so we don't need separate 36 // register indices. 37 struct D3DUniform : private angle::NonCopyable 38 { 39 D3DUniform(GLenum type, 40 const std::string &nameIn, 41 const std::vector<unsigned int> &arraySizesIn, 42 bool defaultBlock); 43 ~D3DUniform(); 44 45 bool isSampler() const; 46 isArrayD3DUniform47 bool isArray() const { return !arraySizes.empty(); } 48 unsigned int getArraySizeProduct() const; 49 50 bool isReferencedByVertexShader() const; 51 bool isReferencedByFragmentShader() const; 52 bool isReferencedByComputeShader() const; 53 54 const uint8_t *firstNonNullData() const; 55 const uint8_t *getDataPtrToElement(size_t elementIndex) const; 56 57 // Duplicated from the GL layer 58 const gl::UniformTypeInfo &typeInfo; 59 std::string name; // Names of arrays don't include [0], unlike at the GL layer. 60 std::vector<unsigned int> arraySizes; 61 62 // Pointer to a system copies of the data. Separate pointers for each uniform storage type. 63 uint8_t *vsData; 64 uint8_t *psData; 65 uint8_t *csData; 66 67 // Register information. 68 unsigned int vsRegisterIndex; 69 unsigned int psRegisterIndex; 70 unsigned int csRegisterIndex; 71 unsigned int registerCount; 72 73 // Register "elements" are used for uniform structs in ES3, to appropriately identify single 74 // uniforms 75 // inside aggregate types, which are packed according C-like structure rules. 76 unsigned int registerElement; 77 78 // Special buffer for sampler values. 79 std::vector<GLint> mSamplerData; 80 }; 81 82 struct D3DUniformBlock 83 { D3DUniformBlockD3DUniformBlock84 D3DUniformBlock() 85 : vsRegisterIndex(GL_INVALID_INDEX), 86 psRegisterIndex(GL_INVALID_INDEX), 87 csRegisterIndex(GL_INVALID_INDEX) 88 { 89 } 90 vertexStaticUseD3DUniformBlock91 bool vertexStaticUse() const { return vsRegisterIndex != GL_INVALID_INDEX; } 92 fragmentStaticUseD3DUniformBlock93 bool fragmentStaticUse() const { return psRegisterIndex != GL_INVALID_INDEX; } 94 computeStaticUseD3DUniformBlock95 bool computeStaticUse() const { return csRegisterIndex != GL_INVALID_INDEX; } 96 97 unsigned int vsRegisterIndex; 98 unsigned int psRegisterIndex; 99 unsigned int csRegisterIndex; 100 }; 101 102 struct D3DVarying final 103 { 104 D3DVarying(); 105 D3DVarying(const std::string &semanticNameIn, 106 unsigned int semanticIndexIn, 107 unsigned int componentCountIn, 108 unsigned int outputSlotIn); 109 110 D3DVarying(const D3DVarying &) = default; 111 D3DVarying &operator=(const D3DVarying &) = default; 112 113 std::string semanticName; 114 unsigned int semanticIndex; 115 unsigned int componentCount; 116 unsigned int outputSlot; 117 }; 118 119 class ProgramD3DMetadata final : angle::NonCopyable 120 { 121 public: 122 ProgramD3DMetadata(RendererD3D *renderer, 123 const ShaderD3D *vertexShader, 124 const ShaderD3D *fragmentShader); 125 126 int getRendererMajorShaderModel() const; 127 bool usesBroadcast(const gl::ContextState &data) const; 128 bool usesFragDepth() const; 129 bool usesPointCoord() const; 130 bool usesFragCoord() const; 131 bool usesPointSize() const; 132 bool usesInsertedPointCoordValue() const; 133 bool usesViewScale() const; 134 bool hasANGLEMultiviewEnabled() const; 135 bool usesViewID() const; 136 bool canSelectViewInVertexShader() const; 137 bool addsPointCoordToVertexShader() const; 138 bool usesTransformFeedbackGLPosition() const; 139 bool usesSystemValuePointSize() const; 140 bool usesMultipleFragmentOuts() const; 141 GLint getMajorShaderVersion() const; 142 const ShaderD3D *getFragmentShader() const; 143 144 private: 145 const int mRendererMajorShaderModel; 146 const std::string mShaderModelSuffix; 147 const bool mUsesInstancedPointSpriteEmulation; 148 const bool mUsesViewScale; 149 const bool mHasANGLEMultiviewEnabled; 150 const bool mUsesViewID; 151 const bool mCanSelectViewInVertexShader; 152 const ShaderD3D *mVertexShader; 153 const ShaderD3D *mFragmentShader; 154 }; 155 156 class ProgramD3D : public ProgramImpl 157 { 158 public: 159 ProgramD3D(const gl::ProgramState &data, RendererD3D *renderer); 160 ~ProgramD3D() override; 161 getPixelShaderKey()162 const std::vector<PixelShaderOutputVariable> &getPixelShaderKey() { return mPixelShaderKey; } 163 164 GLint getSamplerMapping(gl::SamplerType type, 165 unsigned int samplerIndex, 166 const gl::Caps &caps) const; 167 GLenum getSamplerTextureType(gl::SamplerType type, unsigned int samplerIndex) const; 168 GLuint getUsedSamplerRange(gl::SamplerType type) const; 169 170 enum SamplerMapping 171 { 172 WasDirty, 173 WasClean, 174 }; 175 176 SamplerMapping updateSamplerMapping(); 177 usesPointSize()178 bool usesPointSize() const { return mUsesPointSize; } 179 bool usesPointSpriteEmulation() const; 180 bool usesGeometryShader(GLenum drawMode) const; 181 bool usesGeometryShaderForPointSpriteEmulation() const; 182 bool usesInstancedPointSpriteEmulation() const; 183 184 gl::LinkResult load(const gl::Context *context, 185 gl::InfoLog &infoLog, 186 gl::BinaryInputStream *stream) override; 187 void save(const gl::Context *context, gl::BinaryOutputStream *stream) override; 188 void setBinaryRetrievableHint(bool retrievable) override; 189 void setSeparable(bool separable) override; 190 191 gl::Error getVertexExecutableForCachedInputLayout(ShaderExecutableD3D **outExectuable, 192 gl::InfoLog *infoLog); 193 gl::Error getGeometryExecutableForPrimitiveType(const gl::Context *context, 194 GLenum drawMode, 195 ShaderExecutableD3D **outExecutable, 196 gl::InfoLog *infoLog); 197 gl::Error getPixelExecutableForCachedOutputLayout(ShaderExecutableD3D **outExectuable, 198 gl::InfoLog *infoLog); 199 gl::Error getComputeExecutable(ShaderExecutableD3D **outExecutable); 200 gl::LinkResult link(const gl::Context *context, 201 const gl::ProgramLinkedResources &resources, 202 gl::InfoLog &infoLog) override; 203 GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) override; 204 205 void setPathFragmentInputGen(const std::string &inputName, 206 GLenum genMode, 207 GLint components, 208 const GLfloat *coeffs) override; 209 210 void initializeUniformStorage(); 211 void updateUniformBufferCache(const gl::Caps &caps, 212 unsigned int reservedVertex, 213 unsigned int reservedFragment); 214 const std::vector<GLint> &getVertexUniformBufferCache() const; 215 const std::vector<GLint> &getFragmentUniformBufferCache() const; 216 217 void dirtyAllUniforms(); 218 219 void setUniform1fv(GLint location, GLsizei count, const GLfloat *v) override; 220 void setUniform2fv(GLint location, GLsizei count, const GLfloat *v) override; 221 void setUniform3fv(GLint location, GLsizei count, const GLfloat *v) override; 222 void setUniform4fv(GLint location, GLsizei count, const GLfloat *v) override; 223 void setUniform1iv(GLint location, GLsizei count, const GLint *v) override; 224 void setUniform2iv(GLint location, GLsizei count, const GLint *v) override; 225 void setUniform3iv(GLint location, GLsizei count, const GLint *v) override; 226 void setUniform4iv(GLint location, GLsizei count, const GLint *v) override; 227 void setUniform1uiv(GLint location, GLsizei count, const GLuint *v) override; 228 void setUniform2uiv(GLint location, GLsizei count, const GLuint *v) override; 229 void setUniform3uiv(GLint location, GLsizei count, const GLuint *v) override; 230 void setUniform4uiv(GLint location, GLsizei count, const GLuint *v) override; 231 void setUniformMatrix2fv(GLint location, 232 GLsizei count, 233 GLboolean transpose, 234 const GLfloat *value) override; 235 void setUniformMatrix3fv(GLint location, 236 GLsizei count, 237 GLboolean transpose, 238 const GLfloat *value) override; 239 void setUniformMatrix4fv(GLint location, 240 GLsizei count, 241 GLboolean transpose, 242 const GLfloat *value) override; 243 void setUniformMatrix2x3fv(GLint location, 244 GLsizei count, 245 GLboolean transpose, 246 const GLfloat *value) override; 247 void setUniformMatrix3x2fv(GLint location, 248 GLsizei count, 249 GLboolean transpose, 250 const GLfloat *value) override; 251 void setUniformMatrix2x4fv(GLint location, 252 GLsizei count, 253 GLboolean transpose, 254 const GLfloat *value) override; 255 void setUniformMatrix4x2fv(GLint location, 256 GLsizei count, 257 GLboolean transpose, 258 const GLfloat *value) override; 259 void setUniformMatrix3x4fv(GLint location, 260 GLsizei count, 261 GLboolean transpose, 262 const GLfloat *value) override; 263 void setUniformMatrix4x3fv(GLint location, 264 GLsizei count, 265 GLboolean transpose, 266 const GLfloat *value) override; 267 268 void getUniformfv(const gl::Context *context, GLint location, GLfloat *params) const override; 269 void getUniformiv(const gl::Context *context, GLint location, GLint *params) const override; 270 void getUniformuiv(const gl::Context *context, GLint location, GLuint *params) const override; 271 272 void setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) override; 273 getVertexUniformStorage()274 UniformStorageD3D &getVertexUniformStorage() const { return *mVertexUniformStorage.get(); } getFragmentUniformStorage()275 UniformStorageD3D &getFragmentUniformStorage() const { return *mFragmentUniformStorage.get(); } getComputeUniformStorage()276 UniformStorageD3D &getComputeUniformStorage() const { return *mComputeUniformStorage.get(); } 277 278 unsigned int getSerial() const; 279 getAttribLocationToD3DSemantics()280 const AttribIndexArray &getAttribLocationToD3DSemantics() const 281 { 282 return mAttribLocationToD3DSemantic; 283 } 284 285 void updateCachedInputLayout(Serial associatedSerial, const gl::State &state); 286 void updateCachedOutputLayout(const gl::Context *context, const gl::Framebuffer *framebuffer); 287 isSamplerMappingDirty()288 bool isSamplerMappingDirty() { return mDirtySamplerMapping; } 289 290 // Checks if we need to recompile certain shaders. 291 bool hasVertexExecutableForCachedInputLayout(); 292 bool hasGeometryExecutableForPrimitiveType(GLenum drawMode); 293 bool hasPixelExecutableForCachedOutputLayout(); 294 areVertexUniformsDirty()295 bool areVertexUniformsDirty() const { return mVertexUniformsDirty; } areFragmentUniformsDirty()296 bool areFragmentUniformsDirty() const { return mFragmentUniformsDirty; } areComputeUniformsDirty()297 bool areComputeUniformsDirty() const { return mComputeUniformsDirty; } getD3DUniforms()298 const std::vector<D3DUniform *> &getD3DUniforms() const { return mD3DUniforms; } 299 void markUniformsClean(); 300 301 private: 302 // These forward-declared tasks are used for multi-thread shader compiles. 303 class GetExecutableTask; 304 class GetVertexExecutableTask; 305 class GetPixelExecutableTask; 306 class GetGeometryExecutableTask; 307 308 class VertexExecutable 309 { 310 public: 311 enum HLSLAttribType 312 { 313 FLOAT, 314 UNSIGNED_INT, 315 SIGNED_INT, 316 }; 317 318 typedef std::vector<HLSLAttribType> Signature; 319 320 VertexExecutable(const gl::InputLayout &inputLayout, 321 const Signature &signature, 322 ShaderExecutableD3D *shaderExecutable); 323 ~VertexExecutable(); 324 325 bool matchesSignature(const Signature &signature) const; 326 static void getSignature(RendererD3D *renderer, 327 const gl::InputLayout &inputLayout, 328 Signature *signatureOut); 329 inputs()330 const gl::InputLayout &inputs() const { return mInputs; } signature()331 const Signature &signature() const { return mSignature; } shaderExecutable()332 ShaderExecutableD3D *shaderExecutable() const { return mShaderExecutable; } 333 334 private: 335 static HLSLAttribType GetAttribType(GLenum type); 336 337 gl::InputLayout mInputs; 338 Signature mSignature; 339 ShaderExecutableD3D *mShaderExecutable; 340 }; 341 342 class PixelExecutable 343 { 344 public: 345 PixelExecutable(const std::vector<GLenum> &outputSignature, 346 ShaderExecutableD3D *shaderExecutable); 347 ~PixelExecutable(); 348 matchesSignature(const std::vector<GLenum> & signature)349 bool matchesSignature(const std::vector<GLenum> &signature) const 350 { 351 return mOutputSignature == signature; 352 } 353 outputSignature()354 const std::vector<GLenum> &outputSignature() const { return mOutputSignature; } shaderExecutable()355 ShaderExecutableD3D *shaderExecutable() const { return mShaderExecutable; } 356 357 private: 358 std::vector<GLenum> mOutputSignature; 359 ShaderExecutableD3D *mShaderExecutable; 360 }; 361 362 struct Sampler 363 { 364 Sampler(); 365 366 bool active; 367 GLint logicalTextureUnit; 368 GLenum textureType; 369 }; 370 371 typedef std::map<std::string, D3DUniform *> D3DUniformMap; 372 373 void defineUniformsAndAssignRegisters(const gl::Context *context); 374 void defineUniformBase(const gl::Shader *shader, 375 const sh::Uniform &uniform, 376 D3DUniformMap *uniformMap); 377 void defineStructUniformFields(GLenum shaderType, 378 const std::vector<sh::ShaderVariable> &fields, 379 const std::string &namePrefix, 380 sh::HLSLBlockEncoder *encoder, 381 D3DUniformMap *uniformMap); 382 void defineArrayOfStructsUniformFields(GLenum shaderType, 383 const sh::ShaderVariable &uniform, 384 unsigned int arrayNestingIndex, 385 const std::string &prefix, 386 sh::HLSLBlockEncoder *encoder, 387 D3DUniformMap *uniformMap); 388 void defineArrayUniformElements(GLenum shaderType, 389 const sh::ShaderVariable &uniform, 390 const std::string &fullName, 391 sh::HLSLBlockEncoder *encoder, 392 D3DUniformMap *uniformMap); 393 void defineUniform(GLenum shaderType, 394 const sh::ShaderVariable &uniform, 395 const std::string &fullName, 396 sh::HLSLBlockEncoder *encoder, 397 D3DUniformMap *uniformMap); 398 void assignAllSamplerRegisters(); 399 void assignSamplerRegisters(size_t uniformIndex); 400 401 static void AssignSamplers(unsigned int startSamplerIndex, 402 const gl::UniformTypeInfo &typeInfo, 403 unsigned int samplerCount, 404 std::vector<Sampler> &outSamplers, 405 GLuint *outUsedRange); 406 407 template <typename DestT> 408 void getUniformInternal(GLint location, DestT *dataOut) const; 409 410 template <typename T> 411 void setUniformImpl(const gl::VariableLocation &locationInfo, 412 GLsizei count, 413 const T *v, 414 uint8_t *targetData, 415 GLenum uniformType); 416 417 template <typename T> 418 void setUniformInternal(GLint location, GLsizei count, const T *v, GLenum uniformType); 419 420 template <int cols, int rows> 421 bool setUniformMatrixfvImpl(GLint location, 422 GLsizei count, 423 GLboolean transpose, 424 const GLfloat *value, 425 uint8_t *targetData, 426 GLenum targetUniformType); 427 428 template <int cols, int rows> 429 void setUniformMatrixfvInternal(GLint location, 430 GLsizei count, 431 GLboolean transpose, 432 const GLfloat *value, 433 GLenum targetUniformType); 434 435 gl::LinkResult compileProgramExecutables(const gl::Context *context, gl::InfoLog &infoLog); 436 gl::LinkResult compileComputeExecutable(const gl::Context *context, gl::InfoLog &infoLog); 437 438 void gatherTransformFeedbackVaryings(const gl::VaryingPacking &varyings, 439 const BuiltinInfo &builtins); 440 D3DUniform *getD3DUniformByName(const std::string &name); 441 D3DUniform *getD3DUniformFromLocation(GLint location); 442 const D3DUniform *getD3DUniformFromLocation(GLint location) const; 443 444 void initAttribLocationsToD3DSemantic(const gl::Context *context); 445 446 void reset(); 447 void initializeUniformBlocks(); 448 449 void updateCachedInputLayoutFromShader(const gl::Context *context); 450 void updateCachedOutputLayoutFromShader(); 451 void updateCachedVertexExecutableIndex(); 452 void updateCachedPixelExecutableIndex(); 453 454 void linkResources(const gl::Context *context, const gl::ProgramLinkedResources &resources); 455 456 RendererD3D *mRenderer; 457 DynamicHLSL *mDynamicHLSL; 458 459 std::vector<std::unique_ptr<VertexExecutable>> mVertexExecutables; 460 std::vector<std::unique_ptr<PixelExecutable>> mPixelExecutables; 461 std::vector<std::unique_ptr<ShaderExecutableD3D>> mGeometryExecutables; 462 std::unique_ptr<ShaderExecutableD3D> mComputeExecutable; 463 464 std::string mVertexHLSL; 465 angle::CompilerWorkaroundsD3D mVertexWorkarounds; 466 467 std::string mPixelHLSL; 468 angle::CompilerWorkaroundsD3D mPixelWorkarounds; 469 bool mUsesFragDepth; 470 bool mHasANGLEMultiviewEnabled; 471 bool mUsesViewID; 472 std::vector<PixelShaderOutputVariable> mPixelShaderKey; 473 474 // Common code for all dynamic geometry shaders. Consists mainly of the GS input and output 475 // structures, built from the linked varying info. We store the string itself instead of the 476 // packed varyings for simplicity. 477 std::string mGeometryShaderPreamble; 478 479 bool mUsesPointSize; 480 bool mUsesFlatInterpolation; 481 482 std::unique_ptr<UniformStorageD3D> mVertexUniformStorage; 483 std::unique_ptr<UniformStorageD3D> mFragmentUniformStorage; 484 std::unique_ptr<UniformStorageD3D> mComputeUniformStorage; 485 486 std::vector<Sampler> mSamplersPS; 487 std::vector<Sampler> mSamplersVS; 488 std::vector<Sampler> mSamplersCS; 489 GLuint mUsedVertexSamplerRange; 490 GLuint mUsedPixelSamplerRange; 491 GLuint mUsedComputeSamplerRange; 492 bool mDirtySamplerMapping; 493 494 // Cache for pixel shader output layout to save reallocations. 495 std::vector<GLenum> mPixelShaderOutputLayoutCache; 496 Optional<size_t> mCachedPixelExecutableIndex; 497 498 AttribIndexArray mAttribLocationToD3DSemantic; 499 500 unsigned int mSerial; 501 502 std::vector<GLint> mVertexUBOCache; 503 std::vector<GLint> mFragmentUBOCache; 504 VertexExecutable::Signature mCachedVertexSignature; 505 gl::InputLayout mCachedInputLayout; 506 Optional<size_t> mCachedVertexExecutableIndex; 507 508 std::vector<D3DVarying> mStreamOutVaryings; 509 std::vector<D3DUniform *> mD3DUniforms; 510 std::vector<D3DUniformBlock> mD3DUniformBlocks; 511 512 bool mVertexUniformsDirty; 513 bool mFragmentUniformsDirty; 514 bool mComputeUniformsDirty; 515 516 static unsigned int issueSerial(); 517 static unsigned int mCurrentSerial; 518 519 Serial mCurrentVertexArrayStateSerial; 520 }; 521 } // namespace rx 522 523 #endif // LIBANGLE_RENDERER_D3D_PROGRAMD3D_H_ 524