// // Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // // ProgramD3D.h: Defines the rx::ProgramD3D class which implements rx::ProgramImpl. #ifndef LIBANGLE_RENDERER_D3D_PROGRAMD3D_H_ #define LIBANGLE_RENDERER_D3D_PROGRAMD3D_H_ #include #include #include "compiler/translator/blocklayoutHLSL.h" #include "libANGLE/Constants.h" #include "libANGLE/formatutils.h" #include "libANGLE/renderer/ProgramImpl.h" #include "libANGLE/renderer/d3d/DynamicHLSL.h" #include "libANGLE/renderer/d3d/WorkaroundsD3D.h" namespace rx { class RendererD3D; class UniformStorageD3D; class ShaderExecutableD3D; #if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL) // WARNING: D3DCOMPILE_OPTIMIZATION_LEVEL3 may lead to a DX9 shader compiler hang. // It should only be used selectively to work around specific bugs. #define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL1 #endif // Helper struct representing a single shader uniform struct D3DUniform : angle::NonCopyable { D3DUniform(GLenum typeIn, const std::string &nameIn, unsigned int arraySizeIn, bool defaultBlock); ~D3DUniform(); bool isSampler() const; unsigned int elementCount() const { return std::max(1u, arraySize); } bool isReferencedByVertexShader() const; bool isReferencedByFragmentShader() const; // Duplicated from the GL layer GLenum type; std::string name; unsigned int arraySize; // Pointer to a system copy of the data. // TODO(jmadill): remove this in favor of gl::LinkedUniform::data(). uint8_t *data; // Has the data been updated since the last sync? bool dirty; // Register information. unsigned int vsRegisterIndex; unsigned int psRegisterIndex; unsigned int registerCount; // Register "elements" are used for uniform structs in ES3, to appropriately identify single // uniforms // inside aggregate types, which are packed according C-like structure rules. unsigned int registerElement; }; struct D3DUniformBlock { D3DUniformBlock() : vsRegisterIndex(GL_INVALID_INDEX), psRegisterIndex(GL_INVALID_INDEX) {} bool vertexStaticUse() const { return vsRegisterIndex != GL_INVALID_INDEX; } bool fragmentStaticUse() const { return psRegisterIndex != GL_INVALID_INDEX; } unsigned int vsRegisterIndex; unsigned int psRegisterIndex; }; struct D3DVarying final { D3DVarying(); D3DVarying(const std::string &semanticNameIn, unsigned int semanticIndexIn, unsigned int componentCountIn, unsigned int outputSlotIn); D3DVarying(const D3DVarying &) = default; D3DVarying &operator=(const D3DVarying &) = default; std::string semanticName; unsigned int semanticIndex; unsigned int componentCount; unsigned int outputSlot; }; class ProgramD3DMetadata : angle::NonCopyable { public: ProgramD3DMetadata(int rendererMajorShaderModel, const std::string &shaderModelSuffix, bool usesInstancedPointSpriteEmulation, bool usesViewScale, const ShaderD3D *vertexShader, const ShaderD3D *fragmentShader); int getRendererMajorShaderModel() const; bool usesBroadcast(const gl::Data &data) const; bool usesFragDepth(const gl::Program::Data &programData) const; bool usesPointCoord() const; bool usesFragCoord() const; bool usesPointSize() const; bool usesInsertedPointCoordValue() const; bool usesViewScale() const; bool addsPointCoordToVertexShader() const; bool usesTransformFeedbackGLPosition() const; bool usesSystemValuePointSize() const; bool usesMultipleFragmentOuts() const; GLint getMajorShaderVersion() const; const ShaderD3D *getFragmentShader() const; private: const int mRendererMajorShaderModel; const std::string mShaderModelSuffix; const bool mUsesInstancedPointSpriteEmulation; const bool mUsesViewScale; const ShaderD3D *mVertexShader; const ShaderD3D *mFragmentShader; }; class ProgramD3D : public ProgramImpl { public: typedef int SemanticIndexArray[gl::MAX_VERTEX_ATTRIBS]; ProgramD3D(const gl::Program::Data &data, RendererD3D *renderer); virtual ~ProgramD3D(); const std::vector &getPixelShaderKey() { return mPixelShaderKey; } GLint getSamplerMapping(gl::SamplerType type, unsigned int samplerIndex, const gl::Caps &caps) const; GLenum getSamplerTextureType(gl::SamplerType type, unsigned int samplerIndex) const; GLint getUsedSamplerRange(gl::SamplerType type) const; void updateSamplerMapping(); bool usesPointSize() const { return mUsesPointSize; } bool usesPointSpriteEmulation() const; bool usesGeometryShader(GLenum drawMode) const; bool usesInstancedPointSpriteEmulation() const; LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) override; gl::Error save(gl::BinaryOutputStream *stream) override; void setBinaryRetrievableHint(bool retrievable) override; gl::Error getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo, ShaderExecutableD3D **outExectuable); gl::Error getPixelExecutableForOutputLayout(const std::vector &outputLayout, ShaderExecutableD3D **outExectuable, gl::InfoLog *infoLog); gl::Error getVertexExecutableForInputLayout(const gl::InputLayout &inputLayout, ShaderExecutableD3D **outExectuable, gl::InfoLog *infoLog); gl::Error getGeometryExecutableForPrimitiveType(const gl::Data &data, GLenum drawMode, ShaderExecutableD3D **outExecutable, gl::InfoLog *infoLog); LinkResult link(const gl::Data &data, gl::InfoLog &infoLog) override; GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) override; bool getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const override; bool getUniformBlockMemberInfo(const std::string &memberUniformName, sh::BlockMemberInfo *memberInfoOut) const override; void initializeUniformStorage(); gl::Error applyUniforms(GLenum drawMode); gl::Error applyUniformBuffers(const gl::Data &data); void dirtyAllUniforms(); void setUniform1fv(GLint location, GLsizei count, const GLfloat *v); void setUniform2fv(GLint location, GLsizei count, const GLfloat *v); void setUniform3fv(GLint location, GLsizei count, const GLfloat *v); void setUniform4fv(GLint location, GLsizei count, const GLfloat *v); void setUniform1iv(GLint location, GLsizei count, const GLint *v); void setUniform2iv(GLint location, GLsizei count, const GLint *v); void setUniform3iv(GLint location, GLsizei count, const GLint *v); void setUniform4iv(GLint location, GLsizei count, const GLint *v); void setUniform1uiv(GLint location, GLsizei count, const GLuint *v); void setUniform2uiv(GLint location, GLsizei count, const GLuint *v); void setUniform3uiv(GLint location, GLsizei count, const GLuint *v); void setUniform4uiv(GLint location, GLsizei count, const GLuint *v); void setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); void setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); void setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); void setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); void setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); void setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); void setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); void setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); void setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); void setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) override; const UniformStorageD3D &getVertexUniformStorage() const { return *mVertexUniformStorage; } const UniformStorageD3D &getFragmentUniformStorage() const { return *mFragmentUniformStorage; } unsigned int getSerial() const; void sortAttributesByLayout( const std::vector &unsortedAttributes, int sortedSemanticIndicesOut[gl::MAX_VERTEX_ATTRIBS], const rx::TranslatedAttribute *sortedAttributesOut[gl::MAX_VERTEX_ATTRIBS]) const; const SemanticIndexArray &getSemanticIndexes() const { return mSemanticIndexes; } const SemanticIndexArray &getAttributesByLayout() const { return mAttributesByLayout; } void updateCachedInputLayout(const gl::State &state); const gl::InputLayout &getCachedInputLayout() const { return mCachedInputLayout; } bool isSamplerMappingDirty() { return mDirtySamplerMapping; } private: class VertexExecutable { public: typedef std::vector Signature; VertexExecutable(const gl::InputLayout &inputLayout, const Signature &signature, ShaderExecutableD3D *shaderExecutable); ~VertexExecutable(); bool matchesSignature(const Signature &signature) const; static void getSignature(RendererD3D *renderer, const gl::InputLayout &inputLayout, Signature *signatureOut); const gl::InputLayout &inputs() const { return mInputs; } const Signature &signature() const { return mSignature; } ShaderExecutableD3D *shaderExecutable() const { return mShaderExecutable; } private: gl::InputLayout mInputs; Signature mSignature; ShaderExecutableD3D *mShaderExecutable; }; class PixelExecutable { public: PixelExecutable(const std::vector &outputSignature, ShaderExecutableD3D *shaderExecutable); ~PixelExecutable(); bool matchesSignature(const std::vector &signature) const { return mOutputSignature == signature; } const std::vector &outputSignature() const { return mOutputSignature; } ShaderExecutableD3D *shaderExecutable() const { return mShaderExecutable; } private: std::vector mOutputSignature; ShaderExecutableD3D *mShaderExecutable; }; struct Sampler { Sampler(); bool active; GLint logicalTextureUnit; GLenum textureType; }; typedef std::map D3DUniformMap; void defineUniformsAndAssignRegisters(); void defineUniformBase(const gl::Shader *shader, const sh::Uniform &uniform, D3DUniformMap *uniformMap); void defineUniform(GLenum shaderType, const sh::ShaderVariable &uniform, const std::string &fullName, sh::HLSLBlockEncoder *encoder, D3DUniformMap *uniformMap); void assignAllSamplerRegisters(); void assignSamplerRegisters(const D3DUniform *d3dUniform); static void AssignSamplers(unsigned int startSamplerIndex, GLenum samplerType, unsigned int samplerCount, std::vector &outSamplers, GLuint *outUsedRange); template void setUniform(GLint location, GLsizei count, const T *v, GLenum targetUniformType); template void setUniformMatrixfv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value, GLenum targetUniformType); LinkResult compileProgramExecutables(const gl::Data &data, gl::InfoLog &infoLog); void gatherTransformFeedbackVaryings(const VaryingPacking &varyings); D3DUniform *getD3DUniformByName(const std::string &name); D3DUniform *getD3DUniformFromLocation(GLint location); void initSemanticIndex(); void initAttributesByLayout(); void reset(); void assignUniformBlockRegisters(); void initUniformBlockInfo(); size_t getUniformBlockInfo(const sh::InterfaceBlock &interfaceBlock); RendererD3D *mRenderer; DynamicHLSL *mDynamicHLSL; std::vector mVertexExecutables; std::vector mPixelExecutables; std::vector mGeometryExecutables; std::string mVertexHLSL; D3DCompilerWorkarounds mVertexWorkarounds; std::string mPixelHLSL; D3DCompilerWorkarounds mPixelWorkarounds; bool mUsesFragDepth; std::vector mPixelShaderKey; // Common code for all dynamic geometry shaders. Consists mainly of the GS input and output // structures, built from the linked varying info. We store the string itself instead of the // packed varyings for simplicity. std::string mGeometryShaderPreamble; bool mUsesPointSize; bool mUsesFlatInterpolation; UniformStorageD3D *mVertexUniformStorage; UniformStorageD3D *mFragmentUniformStorage; std::vector mSamplersPS; std::vector mSamplersVS; GLuint mUsedVertexSamplerRange; GLuint mUsedPixelSamplerRange; bool mDirtySamplerMapping; // Cache for getPixelExecutableForFramebuffer std::vector mPixelShaderOutputFormatCache; SemanticIndexArray mSemanticIndexes; SemanticIndexArray mAttributesByLayout; unsigned int mSerial; std::vector mVertexUBOCache; std::vector mFragmentUBOCache; VertexExecutable::Signature mCachedVertexSignature; gl::InputLayout mCachedInputLayout; std::vector mStreamOutVaryings; std::vector mD3DUniforms; std::vector mD3DUniformBlocks; std::map mBlockInfo; std::map mBlockDataSizes; static unsigned int issueSerial(); static unsigned int mCurrentSerial; }; } #endif // LIBANGLE_RENDERER_D3D_PROGRAMD3D_H_