blob: d7d97cc2bd25d009ca47333087a618b9dd5330e0 [file] [log] [blame]
Brandon Jonesc9610c52014-08-25 17:02:59 -07001//
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"
Brandon Jones22502d52014-08-29 16:58:36 -070016#include "libGLESv2/renderer/d3d/ShaderD3D.h"
Brandon Jonesc9610c52014-08-25 17:02:59 -070017#include "libGLESv2/main.h"
18
19namespace rx
20{
21
22ProgramD3D::ProgramD3D(rx::Renderer *renderer)
23 : ProgramImpl(),
24 mRenderer(renderer),
25 mDynamicHLSL(NULL),
Brandon Jones22502d52014-08-29 16:58:36 -070026 mVertexWorkarounds(rx::ANGLE_D3D_WORKAROUND_NONE),
27 mPixelWorkarounds(rx::ANGLE_D3D_WORKAROUND_NONE),
Brandon Jonesc9610c52014-08-25 17:02:59 -070028 mVertexUniformStorage(NULL),
29 mFragmentUniformStorage(NULL)
30{
31 mDynamicHLSL = new rx::DynamicHLSL(renderer);
32}
33
34ProgramD3D::~ProgramD3D()
35{
36 reset();
37 SafeDelete(mDynamicHLSL);
38}
39
40ProgramD3D *ProgramD3D::makeProgramD3D(ProgramImpl *impl)
41{
42 ASSERT(HAS_DYNAMIC_TYPE(ProgramD3D*, impl));
43 return static_cast<ProgramD3D*>(impl);
44}
45
46const ProgramD3D *ProgramD3D::makeProgramD3D(const ProgramImpl *impl)
47{
48 ASSERT(HAS_DYNAMIC_TYPE(const ProgramD3D*, impl));
49 return static_cast<const ProgramD3D*>(impl);
50}
51
Brandon Jones22502d52014-08-29 16:58:36 -070052bool 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
73bool 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
95rx::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
110rx::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
128bool 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
Geoff Langbdee2d52014-09-17 11:02:51 -0400145 if (*registers < 0)
Brandon Jones22502d52014-08-29 16:58:36 -0700146 {
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
Brandon Jonesc9610c52014-08-25 17:02:59 -0700165void 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
191void ProgramD3D::reset()
192{
Brandon Jones22502d52014-08-29 16:58:36 -0700193 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
Brandon Jonesc9610c52014-08-25 17:02:59 -0700201 SafeDelete(mVertexUniformStorage);
202 SafeDelete(mFragmentUniformStorage);
203}
204
205}