Home | History | Annotate | Download | only in d3d
      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