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.cpp: Defines the rx::ProgramD3D class which implements rx::ProgramImpl. 8 9 #include "libGLESv2/renderer/d3d/ProgramD3D.h" 10 11 #include "common/utilities.h" 12 #include "libGLESv2/ProgramBinary.h" 13 #include "libGLESv2/renderer/Renderer.h" 14 #include "libGLESv2/renderer/ShaderExecutable.h" 15 #include "libGLESv2/renderer/d3d/DynamicHLSL.h" 16 #include "libGLESv2/renderer/d3d/ShaderD3D.h" 17 #include "libGLESv2/main.h" 18 19 namespace rx 20 { 21 22 ProgramD3D::ProgramD3D(rx::Renderer *renderer) 23 : ProgramImpl(), 24 mRenderer(renderer), 25 mDynamicHLSL(NULL), 26 mVertexWorkarounds(rx::ANGLE_D3D_WORKAROUND_NONE), 27 mPixelWorkarounds(rx::ANGLE_D3D_WORKAROUND_NONE), 28 mVertexUniformStorage(NULL), 29 mFragmentUniformStorage(NULL) 30 { 31 mDynamicHLSL = new rx::DynamicHLSL(renderer); 32 } 33 34 ProgramD3D::~ProgramD3D() 35 { 36 reset(); 37 SafeDelete(mDynamicHLSL); 38 } 39 40 ProgramD3D *ProgramD3D::makeProgramD3D(ProgramImpl *impl) 41 { 42 ASSERT(HAS_DYNAMIC_TYPE(ProgramD3D*, impl)); 43 return static_cast<ProgramD3D*>(impl); 44 } 45 46 const ProgramD3D *ProgramD3D::makeProgramD3D(const ProgramImpl *impl) 47 { 48 ASSERT(HAS_DYNAMIC_TYPE(const ProgramD3D*, impl)); 49 return static_cast<const ProgramD3D*>(impl); 50 } 51 52 bool ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) 53 { 54 stream->readString(&mVertexHLSL); 55 stream->readInt(&mVertexWorkarounds); 56 stream->readString(&mPixelHLSL); 57 stream->readInt(&mPixelWorkarounds); 58 stream->readBool(&mUsesFragDepth); 59 60 const size_t pixelShaderKeySize = stream->readInt<unsigned int>(); 61 mPixelShaderKey.resize(pixelShaderKeySize); 62 for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKeySize; pixelShaderKeyIndex++) 63 { 64 stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].type); 65 stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].name); 66 stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].source); 67 stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].outputIndex); 68 } 69 70 return true; 71 } 72 73 bool ProgramD3D::save(gl::BinaryOutputStream *stream) 74 { 75 stream->writeString(mVertexHLSL); 76 stream->writeInt(mVertexWorkarounds); 77 stream->writeString(mPixelHLSL); 78 stream->writeInt(mPixelWorkarounds); 79 stream->writeInt(mUsesFragDepth); 80 81 const std::vector<rx::PixelShaderOutputVariable> &pixelShaderKey = mPixelShaderKey; 82 stream->writeInt(pixelShaderKey.size()); 83 for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKey.size(); pixelShaderKeyIndex++) 84 { 85 const rx::PixelShaderOutputVariable &variable = pixelShaderKey[pixelShaderKeyIndex]; 86 stream->writeInt(variable.type); 87 stream->writeString(variable.name); 88 stream->writeString(variable.source); 89 stream->writeInt(variable.outputIndex); 90 } 91 92 return true; 93 } 94 95 rx::ShaderExecutable *ProgramD3D::getPixelExecutableForOutputLayout(gl::InfoLog &infoLog, const std::vector<GLenum> &outputSignature, 96 const std::vector<gl::LinkedVarying> &transformFeedbackLinkedVaryings, 97 bool separatedOutputBuffers) 98 { 99 std::string finalPixelHLSL = mDynamicHLSL->generatePixelShaderForOutputSignature(mPixelHLSL, mPixelShaderKey, mUsesFragDepth, 100 outputSignature); 101 102 // Generate new pixel executable 103 rx::ShaderExecutable *pixelExecutable = mRenderer->compileToExecutable(infoLog, finalPixelHLSL.c_str(), rx::SHADER_PIXEL, 104 transformFeedbackLinkedVaryings, separatedOutputBuffers, 105 mPixelWorkarounds); 106 107 return pixelExecutable; 108 } 109 110 rx::ShaderExecutable *ProgramD3D::getVertexExecutableForInputLayout(gl::InfoLog &infoLog, 111 const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS], 112 const sh::Attribute shaderAttributes[], 113 const std::vector<gl::LinkedVarying> &transformFeedbackLinkedVaryings, 114 bool separatedOutputBuffers) 115 { 116 // Generate new dynamic layout with attribute conversions 117 std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout(mVertexHLSL, inputLayout, shaderAttributes); 118 119 // Generate new vertex executable 120 rx::ShaderExecutable *vertexExecutable = mRenderer->compileToExecutable(infoLog, finalVertexHLSL.c_str(), 121 rx::SHADER_VERTEX, 122 transformFeedbackLinkedVaryings, separatedOutputBuffers, 123 mVertexWorkarounds); 124 125 return vertexExecutable; 126 } 127 128 bool ProgramD3D::link(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader, 129 const std::vector<std::string> &transformFeedbackVaryings, int *registers, 130 std::vector<gl::LinkedVarying> *linkedVaryings, std::map<int, gl::VariableLocation> *outputVariables) 131 { 132 rx::ShaderD3D *vertexShaderD3D = rx::ShaderD3D::makeShaderD3D(vertexShader->getImplementation()); 133 rx::ShaderD3D *fragmentShaderD3D = rx::ShaderD3D::makeShaderD3D(fragmentShader->getImplementation()); 134 135 mPixelHLSL = fragmentShaderD3D->getTranslatedSource(); 136 mPixelWorkarounds = fragmentShaderD3D->getD3DWorkarounds(); 137 138 mVertexHLSL = vertexShaderD3D->getTranslatedSource(); 139 mVertexWorkarounds = vertexShaderD3D->getD3DWorkarounds(); 140 141 // Map the varyings to the register file 142 rx::VaryingPacking packing = { NULL }; 143 *registers = mDynamicHLSL->packVaryings(infoLog, packing, fragmentShaderD3D, vertexShaderD3D, transformFeedbackVaryings); 144 145 if (*registers < 0) 146 { 147 return false; 148 } 149 150 if (!gl::ProgramBinary::linkVaryings(infoLog, fragmentShader, vertexShader)) 151 { 152 return false; 153 } 154 155 if (!mDynamicHLSL->generateShaderLinkHLSL(infoLog, *registers, packing, mPixelHLSL, mVertexHLSL, 156 fragmentShaderD3D, vertexShaderD3D, transformFeedbackVaryings, 157 linkedVaryings, outputVariables, &mPixelShaderKey, &mUsesFragDepth)) 158 { 159 return false; 160 } 161 162 return true; 163 } 164 165 void ProgramD3D::initializeUniformStorage(const std::vector<gl::LinkedUniform*> &uniforms) 166 { 167 // Compute total default block size 168 unsigned int vertexRegisters = 0; 169 unsigned int fragmentRegisters = 0; 170 for (size_t uniformIndex = 0; uniformIndex < uniforms.size(); uniformIndex++) 171 { 172 const gl::LinkedUniform &uniform = *uniforms[uniformIndex]; 173 174 if (!gl::IsSampler(uniform.type)) 175 { 176 if (uniform.isReferencedByVertexShader()) 177 { 178 vertexRegisters = std::max(vertexRegisters, uniform.vsRegisterIndex + uniform.registerCount); 179 } 180 if (uniform.isReferencedByFragmentShader()) 181 { 182 fragmentRegisters = std::max(fragmentRegisters, uniform.psRegisterIndex + uniform.registerCount); 183 } 184 } 185 } 186 187 mVertexUniformStorage = mRenderer->createUniformStorage(vertexRegisters * 16u); 188 mFragmentUniformStorage = mRenderer->createUniformStorage(fragmentRegisters * 16u); 189 } 190 191 void ProgramD3D::reset() 192 { 193 mVertexHLSL.clear(); 194 mVertexWorkarounds = rx::ANGLE_D3D_WORKAROUND_NONE; 195 196 mPixelHLSL.clear(); 197 mPixelWorkarounds = rx::ANGLE_D3D_WORKAROUND_NONE; 198 mUsesFragDepth = false; 199 mPixelShaderKey.clear(); 200 201 SafeDelete(mVertexUniformStorage); 202 SafeDelete(mFragmentUniformStorage); 203 } 204 205 } 206