blob: 15c6e13b5c314321b8fb408015bad252d6355890 [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 Jones44151a92014-09-10 11:32:25 -070028 mUsesPointSize(false),
Brandon Jonesc9610c52014-08-25 17:02:59 -070029 mVertexUniformStorage(NULL),
Brandon Jones44151a92014-09-10 11:32:25 -070030 mFragmentUniformStorage(NULL),
31 mShaderVersion(100)
Brandon Jonesc9610c52014-08-25 17:02:59 -070032{
33 mDynamicHLSL = new rx::DynamicHLSL(renderer);
34}
35
36ProgramD3D::~ProgramD3D()
37{
38 reset();
39 SafeDelete(mDynamicHLSL);
40}
41
42ProgramD3D *ProgramD3D::makeProgramD3D(ProgramImpl *impl)
43{
44 ASSERT(HAS_DYNAMIC_TYPE(ProgramD3D*, impl));
45 return static_cast<ProgramD3D*>(impl);
46}
47
48const ProgramD3D *ProgramD3D::makeProgramD3D(const ProgramImpl *impl)
49{
50 ASSERT(HAS_DYNAMIC_TYPE(const ProgramD3D*, impl));
51 return static_cast<const ProgramD3D*>(impl);
52}
53
Brandon Jones44151a92014-09-10 11:32:25 -070054bool ProgramD3D::usesPointSize() const
55{
56 return mUsesPointSize;
57}
58
59bool ProgramD3D::usesPointSpriteEmulation() const
60{
61 return mUsesPointSize && mRenderer->getMajorShaderModel() >= 4;
62}
63
64bool ProgramD3D::usesGeometryShader() const
65{
66 return usesPointSpriteEmulation();
67}
68
Brandon Jones22502d52014-08-29 16:58:36 -070069bool ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
70{
Brandon Jones44151a92014-09-10 11:32:25 -070071 stream->readInt(&mShaderVersion);
72
Brandon Jones22502d52014-08-29 16:58:36 -070073 stream->readString(&mVertexHLSL);
74 stream->readInt(&mVertexWorkarounds);
75 stream->readString(&mPixelHLSL);
76 stream->readInt(&mPixelWorkarounds);
77 stream->readBool(&mUsesFragDepth);
Brandon Jones44151a92014-09-10 11:32:25 -070078 stream->readBool(&mUsesPointSize);
Brandon Jones22502d52014-08-29 16:58:36 -070079
80 const size_t pixelShaderKeySize = stream->readInt<unsigned int>();
81 mPixelShaderKey.resize(pixelShaderKeySize);
82 for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKeySize; pixelShaderKeyIndex++)
83 {
84 stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].type);
85 stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].name);
86 stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].source);
87 stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].outputIndex);
88 }
89
90 return true;
91}
92
93bool ProgramD3D::save(gl::BinaryOutputStream *stream)
94{
Brandon Jones44151a92014-09-10 11:32:25 -070095 stream->writeInt(mShaderVersion);
96
Brandon Jones22502d52014-08-29 16:58:36 -070097 stream->writeString(mVertexHLSL);
98 stream->writeInt(mVertexWorkarounds);
99 stream->writeString(mPixelHLSL);
100 stream->writeInt(mPixelWorkarounds);
101 stream->writeInt(mUsesFragDepth);
Brandon Jones44151a92014-09-10 11:32:25 -0700102 stream->writeInt(mUsesPointSize);
Brandon Jones22502d52014-08-29 16:58:36 -0700103
104 const std::vector<rx::PixelShaderOutputVariable> &pixelShaderKey = mPixelShaderKey;
105 stream->writeInt(pixelShaderKey.size());
106 for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKey.size(); pixelShaderKeyIndex++)
107 {
108 const rx::PixelShaderOutputVariable &variable = pixelShaderKey[pixelShaderKeyIndex];
109 stream->writeInt(variable.type);
110 stream->writeString(variable.name);
111 stream->writeString(variable.source);
112 stream->writeInt(variable.outputIndex);
113 }
114
115 return true;
116}
117
118rx::ShaderExecutable *ProgramD3D::getPixelExecutableForOutputLayout(gl::InfoLog &infoLog, const std::vector<GLenum> &outputSignature,
119 const std::vector<gl::LinkedVarying> &transformFeedbackLinkedVaryings,
120 bool separatedOutputBuffers)
121{
122 std::string finalPixelHLSL = mDynamicHLSL->generatePixelShaderForOutputSignature(mPixelHLSL, mPixelShaderKey, mUsesFragDepth,
123 outputSignature);
124
125 // Generate new pixel executable
126 rx::ShaderExecutable *pixelExecutable = mRenderer->compileToExecutable(infoLog, finalPixelHLSL.c_str(), rx::SHADER_PIXEL,
127 transformFeedbackLinkedVaryings, separatedOutputBuffers,
128 mPixelWorkarounds);
129
130 return pixelExecutable;
131}
132
133rx::ShaderExecutable *ProgramD3D::getVertexExecutableForInputLayout(gl::InfoLog &infoLog,
134 const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS],
135 const sh::Attribute shaderAttributes[],
136 const std::vector<gl::LinkedVarying> &transformFeedbackLinkedVaryings,
137 bool separatedOutputBuffers)
138{
139 // Generate new dynamic layout with attribute conversions
140 std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout(mVertexHLSL, inputLayout, shaderAttributes);
141
142 // Generate new vertex executable
143 rx::ShaderExecutable *vertexExecutable = mRenderer->compileToExecutable(infoLog, finalVertexHLSL.c_str(),
144 rx::SHADER_VERTEX,
145 transformFeedbackLinkedVaryings, separatedOutputBuffers,
146 mVertexWorkarounds);
147
148 return vertexExecutable;
149}
150
Brandon Jones44151a92014-09-10 11:32:25 -0700151rx::ShaderExecutable *ProgramD3D::getGeometryExecutable(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader,
152 const std::vector<gl::LinkedVarying> &transformFeedbackLinkedVaryings,
153 bool separatedOutputBuffers, int registers)
154{
155 rx::ShaderD3D *vertexShaderD3D = rx::ShaderD3D::makeShaderD3D(vertexShader->getImplementation());
156 rx::ShaderD3D *fragmentShaderD3D = rx::ShaderD3D::makeShaderD3D(fragmentShader->getImplementation());
157
158 std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL(registers, fragmentShaderD3D, vertexShaderD3D);
159
160 rx::ShaderExecutable *geometryExecutable = mRenderer->compileToExecutable(infoLog, geometryHLSL.c_str(),
161 rx::SHADER_GEOMETRY, transformFeedbackLinkedVaryings,
162 separatedOutputBuffers, rx::ANGLE_D3D_WORKAROUND_NONE);
163
164 return geometryExecutable;
165}
166
Brandon Jones22502d52014-08-29 16:58:36 -0700167bool ProgramD3D::link(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader,
168 const std::vector<std::string> &transformFeedbackVaryings, int *registers,
169 std::vector<gl::LinkedVarying> *linkedVaryings, std::map<int, gl::VariableLocation> *outputVariables)
170{
171 rx::ShaderD3D *vertexShaderD3D = rx::ShaderD3D::makeShaderD3D(vertexShader->getImplementation());
172 rx::ShaderD3D *fragmentShaderD3D = rx::ShaderD3D::makeShaderD3D(fragmentShader->getImplementation());
173
174 mPixelHLSL = fragmentShaderD3D->getTranslatedSource();
175 mPixelWorkarounds = fragmentShaderD3D->getD3DWorkarounds();
176
177 mVertexHLSL = vertexShaderD3D->getTranslatedSource();
178 mVertexWorkarounds = vertexShaderD3D->getD3DWorkarounds();
Brandon Jones44151a92014-09-10 11:32:25 -0700179 mShaderVersion = vertexShaderD3D->getShaderVersion();
Brandon Jones22502d52014-08-29 16:58:36 -0700180
181 // Map the varyings to the register file
182 rx::VaryingPacking packing = { NULL };
183 *registers = mDynamicHLSL->packVaryings(infoLog, packing, fragmentShaderD3D, vertexShaderD3D, transformFeedbackVaryings);
184
Geoff Langbdee2d52014-09-17 11:02:51 -0400185 if (*registers < 0)
Brandon Jones22502d52014-08-29 16:58:36 -0700186 {
187 return false;
188 }
189
190 if (!gl::ProgramBinary::linkVaryings(infoLog, fragmentShader, vertexShader))
191 {
192 return false;
193 }
194
195 if (!mDynamicHLSL->generateShaderLinkHLSL(infoLog, *registers, packing, mPixelHLSL, mVertexHLSL,
196 fragmentShaderD3D, vertexShaderD3D, transformFeedbackVaryings,
197 linkedVaryings, outputVariables, &mPixelShaderKey, &mUsesFragDepth))
198 {
199 return false;
200 }
201
Brandon Jones44151a92014-09-10 11:32:25 -0700202 mUsesPointSize = vertexShaderD3D->usesPointSize();
203
Brandon Jones22502d52014-08-29 16:58:36 -0700204 return true;
205}
206
Brandon Jones44151a92014-09-10 11:32:25 -0700207void ProgramD3D::getInputLayoutSignature(const gl::VertexFormat inputLayout[], GLenum signature[]) const
208{
209 mDynamicHLSL->getInputLayoutSignature(inputLayout, signature);
210}
211
Brandon Jonesc9610c52014-08-25 17:02:59 -0700212void ProgramD3D::initializeUniformStorage(const std::vector<gl::LinkedUniform*> &uniforms)
213{
214 // Compute total default block size
215 unsigned int vertexRegisters = 0;
216 unsigned int fragmentRegisters = 0;
217 for (size_t uniformIndex = 0; uniformIndex < uniforms.size(); uniformIndex++)
218 {
219 const gl::LinkedUniform &uniform = *uniforms[uniformIndex];
220
221 if (!gl::IsSampler(uniform.type))
222 {
223 if (uniform.isReferencedByVertexShader())
224 {
225 vertexRegisters = std::max(vertexRegisters, uniform.vsRegisterIndex + uniform.registerCount);
226 }
227 if (uniform.isReferencedByFragmentShader())
228 {
229 fragmentRegisters = std::max(fragmentRegisters, uniform.psRegisterIndex + uniform.registerCount);
230 }
231 }
232 }
233
234 mVertexUniformStorage = mRenderer->createUniformStorage(vertexRegisters * 16u);
235 mFragmentUniformStorage = mRenderer->createUniformStorage(fragmentRegisters * 16u);
236}
237
238void ProgramD3D::reset()
239{
Brandon Jones22502d52014-08-29 16:58:36 -0700240 mVertexHLSL.clear();
241 mVertexWorkarounds = rx::ANGLE_D3D_WORKAROUND_NONE;
Brandon Jones44151a92014-09-10 11:32:25 -0700242 mShaderVersion = 100;
Brandon Jones22502d52014-08-29 16:58:36 -0700243
244 mPixelHLSL.clear();
245 mPixelWorkarounds = rx::ANGLE_D3D_WORKAROUND_NONE;
246 mUsesFragDepth = false;
247 mPixelShaderKey.clear();
Brandon Jones44151a92014-09-10 11:32:25 -0700248 mUsesPointSize = false;
Brandon Jones22502d52014-08-29 16:58:36 -0700249
Brandon Jonesc9610c52014-08-25 17:02:59 -0700250 SafeDelete(mVertexUniformStorage);
251 SafeDelete(mFragmentUniformStorage);
252}
253
254}