blob: d37792429d0b3f0d0de6d6f42ada1f02ec50ad6d [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"
Brandon Joneseb994362014-09-24 10:27:28 -070012#include "libGLESv2/Framebuffer.h"
13#include "libGLESv2/FramebufferAttachment.h"
Brandon Jones18bd4102014-09-22 14:21:44 -070014#include "libGLESv2/Program.h"
Brandon Jonesc9610c52014-08-25 17:02:59 -070015#include "libGLESv2/ProgramBinary.h"
16#include "libGLESv2/renderer/Renderer.h"
17#include "libGLESv2/renderer/ShaderExecutable.h"
18#include "libGLESv2/renderer/d3d/DynamicHLSL.h"
Brandon Jones22502d52014-08-29 16:58:36 -070019#include "libGLESv2/renderer/d3d/ShaderD3D.h"
Brandon Jonesc9610c52014-08-25 17:02:59 -070020#include "libGLESv2/main.h"
21
22namespace rx
23{
24
Brandon Joneseb994362014-09-24 10:27:28 -070025namespace
26{
27
28void GetDefaultInputLayoutFromShader(const std::vector<sh::Attribute> &shaderAttributes, gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS])
29{
30 size_t layoutIndex = 0;
31 for (size_t attributeIndex = 0; attributeIndex < shaderAttributes.size(); attributeIndex++)
32 {
33 ASSERT(layoutIndex < gl::MAX_VERTEX_ATTRIBS);
34
35 const sh::Attribute &shaderAttr = shaderAttributes[attributeIndex];
36
37 if (shaderAttr.type != GL_NONE)
38 {
39 GLenum transposedType = gl::TransposeMatrixType(shaderAttr.type);
40
41 for (size_t rowIndex = 0; static_cast<int>(rowIndex) < gl::VariableRowCount(transposedType); rowIndex++, layoutIndex++)
42 {
43 gl::VertexFormat *defaultFormat = &inputLayout[layoutIndex];
44
45 defaultFormat->mType = gl::VariableComponentType(transposedType);
46 defaultFormat->mNormalized = false;
47 defaultFormat->mPureInteger = (defaultFormat->mType != GL_FLOAT); // note: inputs can not be bool
48 defaultFormat->mComponents = gl::VariableColumnCount(transposedType);
49 }
50 }
51 }
52}
53
54std::vector<GLenum> GetDefaultOutputLayoutFromShader(const std::vector<PixelShaderOutputVariable> &shaderOutputVars)
55{
56 std::vector<GLenum> defaultPixelOutput(1);
57
58 ASSERT(!shaderOutputVars.empty());
59 defaultPixelOutput[0] = GL_COLOR_ATTACHMENT0 + shaderOutputVars[0].outputIndex;
60
61 return defaultPixelOutput;
62}
63
64}
65
66ProgramD3D::VertexExecutable::VertexExecutable(const gl::VertexFormat inputLayout[],
67 const GLenum signature[],
68 ShaderExecutable *shaderExecutable)
69 : mShaderExecutable(shaderExecutable)
70{
71 for (size_t attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++)
72 {
73 mInputs[attributeIndex] = inputLayout[attributeIndex];
74 mSignature[attributeIndex] = signature[attributeIndex];
75 }
76}
77
78ProgramD3D::VertexExecutable::~VertexExecutable()
79{
80 SafeDelete(mShaderExecutable);
81}
82
83bool ProgramD3D::VertexExecutable::matchesSignature(const GLenum signature[]) const
84{
85 for (size_t attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++)
86 {
87 if (mSignature[attributeIndex] != signature[attributeIndex])
88 {
89 return false;
90 }
91 }
92
93 return true;
94}
95
96ProgramD3D::PixelExecutable::PixelExecutable(const std::vector<GLenum> &outputSignature, ShaderExecutable *shaderExecutable)
97 : mOutputSignature(outputSignature),
98 mShaderExecutable(shaderExecutable)
99{
100}
101
102ProgramD3D::PixelExecutable::~PixelExecutable()
103{
104 SafeDelete(mShaderExecutable);
105}
106
107ProgramD3D::ProgramD3D(Renderer *renderer)
Brandon Jonesc9610c52014-08-25 17:02:59 -0700108 : ProgramImpl(),
109 mRenderer(renderer),
110 mDynamicHLSL(NULL),
Brandon Joneseb994362014-09-24 10:27:28 -0700111 mGeometryExecutable(NULL),
112 mVertexWorkarounds(ANGLE_D3D_WORKAROUND_NONE),
113 mPixelWorkarounds(ANGLE_D3D_WORKAROUND_NONE),
Brandon Jones44151a92014-09-10 11:32:25 -0700114 mUsesPointSize(false),
Brandon Jonesc9610c52014-08-25 17:02:59 -0700115 mVertexUniformStorage(NULL),
Brandon Jones44151a92014-09-10 11:32:25 -0700116 mFragmentUniformStorage(NULL),
117 mShaderVersion(100)
Brandon Jonesc9610c52014-08-25 17:02:59 -0700118{
Brandon Joneseb994362014-09-24 10:27:28 -0700119 mDynamicHLSL = new DynamicHLSL(renderer);
Brandon Jonesc9610c52014-08-25 17:02:59 -0700120}
121
122ProgramD3D::~ProgramD3D()
123{
124 reset();
125 SafeDelete(mDynamicHLSL);
126}
127
128ProgramD3D *ProgramD3D::makeProgramD3D(ProgramImpl *impl)
129{
130 ASSERT(HAS_DYNAMIC_TYPE(ProgramD3D*, impl));
131 return static_cast<ProgramD3D*>(impl);
132}
133
134const ProgramD3D *ProgramD3D::makeProgramD3D(const ProgramImpl *impl)
135{
136 ASSERT(HAS_DYNAMIC_TYPE(const ProgramD3D*, impl));
137 return static_cast<const ProgramD3D*>(impl);
138}
139
Brandon Jones44151a92014-09-10 11:32:25 -0700140bool ProgramD3D::usesPointSpriteEmulation() const
141{
142 return mUsesPointSize && mRenderer->getMajorShaderModel() >= 4;
143}
144
145bool ProgramD3D::usesGeometryShader() const
146{
147 return usesPointSpriteEmulation();
148}
149
Brandon Jones22502d52014-08-29 16:58:36 -0700150bool ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
151{
Brandon Jones44151a92014-09-10 11:32:25 -0700152 stream->readInt(&mShaderVersion);
153
Brandon Joneseb994362014-09-24 10:27:28 -0700154 stream->readInt(&mTransformFeedbackBufferMode);
155 const unsigned int transformFeedbackVaryingCount = stream->readInt<unsigned int>();
156 mTransformFeedbackLinkedVaryings.resize(transformFeedbackVaryingCount);
157 for (unsigned int varyingIndex = 0; varyingIndex < transformFeedbackVaryingCount; varyingIndex++)
158 {
159 gl::LinkedVarying &varying = mTransformFeedbackLinkedVaryings[varyingIndex];
160
161 stream->readString(&varying.name);
162 stream->readInt(&varying.type);
163 stream->readInt(&varying.size);
164 stream->readString(&varying.semanticName);
165 stream->readInt(&varying.semanticIndex);
166 stream->readInt(&varying.semanticIndexCount);
167 }
168
Brandon Jones22502d52014-08-29 16:58:36 -0700169 stream->readString(&mVertexHLSL);
170 stream->readInt(&mVertexWorkarounds);
171 stream->readString(&mPixelHLSL);
172 stream->readInt(&mPixelWorkarounds);
173 stream->readBool(&mUsesFragDepth);
Brandon Jones44151a92014-09-10 11:32:25 -0700174 stream->readBool(&mUsesPointSize);
Brandon Jones22502d52014-08-29 16:58:36 -0700175
176 const size_t pixelShaderKeySize = stream->readInt<unsigned int>();
177 mPixelShaderKey.resize(pixelShaderKeySize);
178 for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKeySize; pixelShaderKeyIndex++)
179 {
180 stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].type);
181 stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].name);
182 stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].source);
183 stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].outputIndex);
184 }
185
Brandon Joneseb994362014-09-24 10:27:28 -0700186 const unsigned char* binary = reinterpret_cast<const unsigned char*>(stream->data());
187
188 const unsigned int vertexShaderCount = stream->readInt<unsigned int>();
189 for (unsigned int vertexShaderIndex = 0; vertexShaderIndex < vertexShaderCount; vertexShaderIndex++)
190 {
191 gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS];
192
193 for (size_t inputIndex = 0; inputIndex < gl::MAX_VERTEX_ATTRIBS; inputIndex++)
194 {
195 gl::VertexFormat *vertexInput = &inputLayout[inputIndex];
196 stream->readInt(&vertexInput->mType);
197 stream->readInt(&vertexInput->mNormalized);
198 stream->readInt(&vertexInput->mComponents);
199 stream->readBool(&vertexInput->mPureInteger);
200 }
201
202 unsigned int vertexShaderSize = stream->readInt<unsigned int>();
203 const unsigned char *vertexShaderFunction = binary + stream->offset();
204 ShaderExecutable *shaderExecutable = mRenderer->loadExecutable(vertexShaderFunction, vertexShaderSize,
205 SHADER_VERTEX,
206 mTransformFeedbackLinkedVaryings,
207 (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS));
208 if (!shaderExecutable)
209 {
210 infoLog.append("Could not create vertex shader.");
211 return false;
212 }
213
214 // generated converted input layout
215 GLenum signature[gl::MAX_VERTEX_ATTRIBS];
216 getInputLayoutSignature(inputLayout, signature);
217
218 // add new binary
219 mVertexExecutables.push_back(new VertexExecutable(inputLayout, signature, shaderExecutable));
220
221 stream->skip(vertexShaderSize);
222 }
223
224 const size_t pixelShaderCount = stream->readInt<unsigned int>();
225 for (size_t pixelShaderIndex = 0; pixelShaderIndex < pixelShaderCount; pixelShaderIndex++)
226 {
227 const size_t outputCount = stream->readInt<unsigned int>();
228 std::vector<GLenum> outputs(outputCount);
229 for (size_t outputIndex = 0; outputIndex < outputCount; outputIndex++)
230 {
231 stream->readInt(&outputs[outputIndex]);
232 }
233
234 const size_t pixelShaderSize = stream->readInt<unsigned int>();
235 const unsigned char *pixelShaderFunction = binary + stream->offset();
236 ShaderExecutable *shaderExecutable = mRenderer->loadExecutable(pixelShaderFunction, pixelShaderSize,
237 SHADER_PIXEL,
238 mTransformFeedbackLinkedVaryings,
239 (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS));
240
241 if (!shaderExecutable)
242 {
243 infoLog.append("Could not create pixel shader.");
244 return false;
245 }
246
247 // add new binary
248 mPixelExecutables.push_back(new PixelExecutable(outputs, shaderExecutable));
249
250 stream->skip(pixelShaderSize);
251 }
252
253 unsigned int geometryShaderSize = stream->readInt<unsigned int>();
254
255 if (geometryShaderSize > 0)
256 {
257 const unsigned char *geometryShaderFunction = binary + stream->offset();
258 mGeometryExecutable = mRenderer->loadExecutable(geometryShaderFunction, geometryShaderSize,
259 SHADER_GEOMETRY,
260 mTransformFeedbackLinkedVaryings,
261 (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS));
262
263 if (!mGeometryExecutable)
264 {
265 infoLog.append("Could not create geometry shader.");
266 return false;
267 }
268 stream->skip(geometryShaderSize);
269 }
270
Brandon Jones18bd4102014-09-22 14:21:44 -0700271 GUID binaryIdentifier = {0};
272 stream->readBytes(reinterpret_cast<unsigned char*>(&binaryIdentifier), sizeof(GUID));
273
274 GUID identifier = mRenderer->getAdapterIdentifier();
275 if (memcmp(&identifier, &binaryIdentifier, sizeof(GUID)) != 0)
276 {
277 infoLog.append("Invalid program binary.");
278 return false;
279 }
280
Brandon Jones22502d52014-08-29 16:58:36 -0700281 return true;
282}
283
284bool ProgramD3D::save(gl::BinaryOutputStream *stream)
285{
Brandon Jones44151a92014-09-10 11:32:25 -0700286 stream->writeInt(mShaderVersion);
287
Brandon Joneseb994362014-09-24 10:27:28 -0700288 stream->writeInt(mTransformFeedbackBufferMode);
289 stream->writeInt(mTransformFeedbackLinkedVaryings.size());
290 for (size_t i = 0; i < mTransformFeedbackLinkedVaryings.size(); i++)
291 {
292 const gl::LinkedVarying &varying = mTransformFeedbackLinkedVaryings[i];
293
294 stream->writeString(varying.name);
295 stream->writeInt(varying.type);
296 stream->writeInt(varying.size);
297 stream->writeString(varying.semanticName);
298 stream->writeInt(varying.semanticIndex);
299 stream->writeInt(varying.semanticIndexCount);
300 }
301
Brandon Jones22502d52014-08-29 16:58:36 -0700302 stream->writeString(mVertexHLSL);
303 stream->writeInt(mVertexWorkarounds);
304 stream->writeString(mPixelHLSL);
305 stream->writeInt(mPixelWorkarounds);
306 stream->writeInt(mUsesFragDepth);
Brandon Jones44151a92014-09-10 11:32:25 -0700307 stream->writeInt(mUsesPointSize);
Brandon Jones22502d52014-08-29 16:58:36 -0700308
Brandon Joneseb994362014-09-24 10:27:28 -0700309 const std::vector<PixelShaderOutputVariable> &pixelShaderKey = mPixelShaderKey;
Brandon Jones22502d52014-08-29 16:58:36 -0700310 stream->writeInt(pixelShaderKey.size());
311 for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKey.size(); pixelShaderKeyIndex++)
312 {
Brandon Joneseb994362014-09-24 10:27:28 -0700313 const PixelShaderOutputVariable &variable = pixelShaderKey[pixelShaderKeyIndex];
Brandon Jones22502d52014-08-29 16:58:36 -0700314 stream->writeInt(variable.type);
315 stream->writeString(variable.name);
316 stream->writeString(variable.source);
317 stream->writeInt(variable.outputIndex);
318 }
319
Brandon Joneseb994362014-09-24 10:27:28 -0700320 stream->writeInt(mVertexExecutables.size());
321 for (size_t vertexExecutableIndex = 0; vertexExecutableIndex < mVertexExecutables.size(); vertexExecutableIndex++)
322 {
323 VertexExecutable *vertexExecutable = mVertexExecutables[vertexExecutableIndex];
324
325 for (size_t inputIndex = 0; inputIndex < gl::MAX_VERTEX_ATTRIBS; inputIndex++)
326 {
327 const gl::VertexFormat &vertexInput = vertexExecutable->inputs()[inputIndex];
328 stream->writeInt(vertexInput.mType);
329 stream->writeInt(vertexInput.mNormalized);
330 stream->writeInt(vertexInput.mComponents);
331 stream->writeInt(vertexInput.mPureInteger);
332 }
333
334 size_t vertexShaderSize = vertexExecutable->shaderExecutable()->getLength();
335 stream->writeInt(vertexShaderSize);
336
337 const uint8_t *vertexBlob = vertexExecutable->shaderExecutable()->getFunction();
338 stream->writeBytes(vertexBlob, vertexShaderSize);
339 }
340
341 stream->writeInt(mPixelExecutables.size());
342 for (size_t pixelExecutableIndex = 0; pixelExecutableIndex < mPixelExecutables.size(); pixelExecutableIndex++)
343 {
344 PixelExecutable *pixelExecutable = mPixelExecutables[pixelExecutableIndex];
345
346 const std::vector<GLenum> outputs = pixelExecutable->outputSignature();
347 stream->writeInt(outputs.size());
348 for (size_t outputIndex = 0; outputIndex < outputs.size(); outputIndex++)
349 {
350 stream->writeInt(outputs[outputIndex]);
351 }
352
353 size_t pixelShaderSize = pixelExecutable->shaderExecutable()->getLength();
354 stream->writeInt(pixelShaderSize);
355
356 const uint8_t *pixelBlob = pixelExecutable->shaderExecutable()->getFunction();
357 stream->writeBytes(pixelBlob, pixelShaderSize);
358 }
359
360 size_t geometryShaderSize = (mGeometryExecutable != NULL) ? mGeometryExecutable->getLength() : 0;
361 stream->writeInt(geometryShaderSize);
362
363 if (mGeometryExecutable != NULL && geometryShaderSize > 0)
364 {
365 const uint8_t *geometryBlob = mGeometryExecutable->getFunction();
366 stream->writeBytes(geometryBlob, geometryShaderSize);
367 }
368
Brandon Jones18bd4102014-09-22 14:21:44 -0700369 GUID binaryIdentifier = mRenderer->getAdapterIdentifier();
370 stream->writeBytes(reinterpret_cast<unsigned char*>(&binaryIdentifier), sizeof(GUID));
371
Brandon Jones22502d52014-08-29 16:58:36 -0700372 return true;
373}
374
Brandon Joneseb994362014-09-24 10:27:28 -0700375ShaderExecutable *ProgramD3D::getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo)
Brandon Jones22502d52014-08-29 16:58:36 -0700376{
Brandon Joneseb994362014-09-24 10:27:28 -0700377 std::vector<GLenum> outputs;
378
379 const gl::ColorbufferInfo &colorbuffers = fbo->getColorbuffersForRender();
380
381 for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment)
382 {
383 const gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment];
384
385 if (colorbuffer)
386 {
387 outputs.push_back(colorbuffer->getBinding() == GL_BACK ? GL_COLOR_ATTACHMENT0 : colorbuffer->getBinding());
388 }
389 else
390 {
391 outputs.push_back(GL_NONE);
392 }
393 }
394
395 return getPixelExecutableForOutputLayout(outputs);
396}
397
398ShaderExecutable *ProgramD3D::getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputSignature)
399{
400 for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++)
401 {
402 if (mPixelExecutables[executableIndex]->matchesSignature(outputSignature))
403 {
404 return mPixelExecutables[executableIndex]->shaderExecutable();
405 }
406 }
407
Brandon Jones22502d52014-08-29 16:58:36 -0700408 std::string finalPixelHLSL = mDynamicHLSL->generatePixelShaderForOutputSignature(mPixelHLSL, mPixelShaderKey, mUsesFragDepth,
409 outputSignature);
410
411 // Generate new pixel executable
Brandon Joneseb994362014-09-24 10:27:28 -0700412 gl::InfoLog tempInfoLog;
413 ShaderExecutable *pixelExecutable = mRenderer->compileToExecutable(tempInfoLog, finalPixelHLSL, SHADER_PIXEL,
414 mTransformFeedbackLinkedVaryings,
415 (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
416 mPixelWorkarounds);
417
418 if (!pixelExecutable)
419 {
420 std::vector<char> tempCharBuffer(tempInfoLog.getLength() + 3);
421 tempInfoLog.getLog(tempInfoLog.getLength(), NULL, &tempCharBuffer[0]);
422 ERR("Error compiling dynamic pixel executable:\n%s\n", &tempCharBuffer[0]);
423 }
424 else
425 {
426 mPixelExecutables.push_back(new PixelExecutable(outputSignature, pixelExecutable));
427 }
Brandon Jones22502d52014-08-29 16:58:36 -0700428
429 return pixelExecutable;
430}
431
Brandon Joneseb994362014-09-24 10:27:28 -0700432ShaderExecutable *ProgramD3D::getVertexExecutableForInputLayout(const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS])
Brandon Jones22502d52014-08-29 16:58:36 -0700433{
Brandon Joneseb994362014-09-24 10:27:28 -0700434 GLenum signature[gl::MAX_VERTEX_ATTRIBS];
435 getInputLayoutSignature(inputLayout, signature);
436
437 for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++)
438 {
439 if (mVertexExecutables[executableIndex]->matchesSignature(signature))
440 {
441 return mVertexExecutables[executableIndex]->shaderExecutable();
442 }
443 }
444
Brandon Jones22502d52014-08-29 16:58:36 -0700445 // Generate new dynamic layout with attribute conversions
Brandon Joneseb994362014-09-24 10:27:28 -0700446 std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout(mVertexHLSL, inputLayout, mShaderAttributes);
Brandon Jones22502d52014-08-29 16:58:36 -0700447
448 // Generate new vertex executable
Brandon Joneseb994362014-09-24 10:27:28 -0700449 gl::InfoLog tempInfoLog;
450 ShaderExecutable *vertexExecutable = mRenderer->compileToExecutable(tempInfoLog, finalVertexHLSL,
451 SHADER_VERTEX,
452 mTransformFeedbackLinkedVaryings,
453 (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
Brandon Jones18bd4102014-09-22 14:21:44 -0700454 mVertexWorkarounds);
Brandon Joneseb994362014-09-24 10:27:28 -0700455 if (!vertexExecutable)
456 {
457 std::vector<char> tempCharBuffer(tempInfoLog.getLength()+3);
458 tempInfoLog.getLog(tempInfoLog.getLength(), NULL, &tempCharBuffer[0]);
459 ERR("Error compiling dynamic vertex executable:\n%s\n", &tempCharBuffer[0]);
460 }
461 else
462 {
463 mVertexExecutables.push_back(new VertexExecutable(inputLayout, signature, vertexExecutable));
464 }
Brandon Jones22502d52014-08-29 16:58:36 -0700465
466 return vertexExecutable;
467}
468
Brandon Joneseb994362014-09-24 10:27:28 -0700469bool ProgramD3D::compileProgramExecutables(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader,
470 int registers)
Brandon Jones44151a92014-09-10 11:32:25 -0700471{
Brandon Jones18bd4102014-09-22 14:21:44 -0700472 ShaderD3D *vertexShaderD3D = ShaderD3D::makeShaderD3D(vertexShader->getImplementation());
473 ShaderD3D *fragmentShaderD3D = ShaderD3D::makeShaderD3D(fragmentShader->getImplementation());
Brandon Jones44151a92014-09-10 11:32:25 -0700474
Brandon Joneseb994362014-09-24 10:27:28 -0700475 gl::VertexFormat defaultInputLayout[gl::MAX_VERTEX_ATTRIBS];
476 GetDefaultInputLayoutFromShader(vertexShader->getActiveAttributes(), defaultInputLayout);
477 ShaderExecutable *defaultVertexExecutable = getVertexExecutableForInputLayout(defaultInputLayout);
Brandon Jones44151a92014-09-10 11:32:25 -0700478
Brandon Joneseb994362014-09-24 10:27:28 -0700479 std::vector<GLenum> defaultPixelOutput = GetDefaultOutputLayoutFromShader(getPixelShaderKey());
480 ShaderExecutable *defaultPixelExecutable = getPixelExecutableForOutputLayout(defaultPixelOutput);
Brandon Jones44151a92014-09-10 11:32:25 -0700481
Brandon Joneseb994362014-09-24 10:27:28 -0700482 if (usesGeometryShader())
483 {
484 std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL(registers, fragmentShaderD3D, vertexShaderD3D);
Brandon Jones44151a92014-09-10 11:32:25 -0700485
Brandon Joneseb994362014-09-24 10:27:28 -0700486 mGeometryExecutable = mRenderer->compileToExecutable(infoLog, geometryHLSL,
487 SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings,
488 (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
489 ANGLE_D3D_WORKAROUND_NONE);
490 }
491
492 return (defaultVertexExecutable && defaultPixelExecutable && (!usesGeometryShader() || mGeometryExecutable));
Brandon Jones18bd4102014-09-22 14:21:44 -0700493}
494
Brandon Jones22502d52014-08-29 16:58:36 -0700495bool ProgramD3D::link(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader,
Brandon Joneseb994362014-09-24 10:27:28 -0700496 const std::vector<std::string> &transformFeedbackVaryings, GLenum transformFeedbackBufferMode,
497 int *registers, std::vector<gl::LinkedVarying> *linkedVaryings,
498 std::map<int, gl::VariableLocation> *outputVariables, const gl::Caps &caps)
Brandon Jones22502d52014-08-29 16:58:36 -0700499{
Brandon Joneseb994362014-09-24 10:27:28 -0700500 ShaderD3D *vertexShaderD3D = ShaderD3D::makeShaderD3D(vertexShader->getImplementation());
501 ShaderD3D *fragmentShaderD3D = ShaderD3D::makeShaderD3D(fragmentShader->getImplementation());
502
503 mTransformFeedbackBufferMode = transformFeedbackBufferMode;
Brandon Jones22502d52014-08-29 16:58:36 -0700504
505 mPixelHLSL = fragmentShaderD3D->getTranslatedSource();
506 mPixelWorkarounds = fragmentShaderD3D->getD3DWorkarounds();
507
508 mVertexHLSL = vertexShaderD3D->getTranslatedSource();
509 mVertexWorkarounds = vertexShaderD3D->getD3DWorkarounds();
Brandon Jones44151a92014-09-10 11:32:25 -0700510 mShaderVersion = vertexShaderD3D->getShaderVersion();
Brandon Jones22502d52014-08-29 16:58:36 -0700511
512 // Map the varyings to the register file
Brandon Joneseb994362014-09-24 10:27:28 -0700513 VaryingPacking packing = { NULL };
Brandon Jones22502d52014-08-29 16:58:36 -0700514 *registers = mDynamicHLSL->packVaryings(infoLog, packing, fragmentShaderD3D, vertexShaderD3D, transformFeedbackVaryings);
515
Geoff Langbdee2d52014-09-17 11:02:51 -0400516 if (*registers < 0)
Brandon Jones22502d52014-08-29 16:58:36 -0700517 {
518 return false;
519 }
520
521 if (!gl::ProgramBinary::linkVaryings(infoLog, fragmentShader, vertexShader))
522 {
523 return false;
524 }
525
526 if (!mDynamicHLSL->generateShaderLinkHLSL(infoLog, *registers, packing, mPixelHLSL, mVertexHLSL,
527 fragmentShaderD3D, vertexShaderD3D, transformFeedbackVaryings,
528 linkedVaryings, outputVariables, &mPixelShaderKey, &mUsesFragDepth))
529 {
530 return false;
531 }
532
Brandon Jones44151a92014-09-10 11:32:25 -0700533 mUsesPointSize = vertexShaderD3D->usesPointSize();
534
Brandon Jones22502d52014-08-29 16:58:36 -0700535 return true;
536}
537
Brandon Jones44151a92014-09-10 11:32:25 -0700538void ProgramD3D::getInputLayoutSignature(const gl::VertexFormat inputLayout[], GLenum signature[]) const
539{
540 mDynamicHLSL->getInputLayoutSignature(inputLayout, signature);
541}
542
Brandon Jonesc9610c52014-08-25 17:02:59 -0700543void ProgramD3D::initializeUniformStorage(const std::vector<gl::LinkedUniform*> &uniforms)
544{
545 // Compute total default block size
546 unsigned int vertexRegisters = 0;
547 unsigned int fragmentRegisters = 0;
548 for (size_t uniformIndex = 0; uniformIndex < uniforms.size(); uniformIndex++)
549 {
550 const gl::LinkedUniform &uniform = *uniforms[uniformIndex];
551
552 if (!gl::IsSampler(uniform.type))
553 {
554 if (uniform.isReferencedByVertexShader())
555 {
556 vertexRegisters = std::max(vertexRegisters, uniform.vsRegisterIndex + uniform.registerCount);
557 }
558 if (uniform.isReferencedByFragmentShader())
559 {
560 fragmentRegisters = std::max(fragmentRegisters, uniform.psRegisterIndex + uniform.registerCount);
561 }
562 }
563 }
564
565 mVertexUniformStorage = mRenderer->createUniformStorage(vertexRegisters * 16u);
566 mFragmentUniformStorage = mRenderer->createUniformStorage(fragmentRegisters * 16u);
567}
568
Brandon Jones18bd4102014-09-22 14:21:44 -0700569gl::Error ProgramD3D::applyUniforms(const std::vector<gl::LinkedUniform*> &uniforms)
570{
571 return mRenderer->applyUniforms(*this, uniforms);
572}
573
574gl::Error ProgramD3D::applyUniformBuffers(const std::vector<gl::UniformBlock*> uniformBlocks, const std::vector<gl::Buffer*> boundBuffers,
Brandon Joneseb994362014-09-24 10:27:28 -0700575 const gl::Caps &caps)
Brandon Jones18bd4102014-09-22 14:21:44 -0700576{
577 const gl::Buffer *vertexUniformBuffers[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS] = {NULL};
578 const gl::Buffer *fragmentUniformBuffers[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS] = {NULL};
579
580 const unsigned int reservedBuffersInVS = mRenderer->getReservedVertexUniformBuffers();
581 const unsigned int reservedBuffersInFS = mRenderer->getReservedFragmentUniformBuffers();
582
583 for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < uniformBlocks.size(); uniformBlockIndex++)
584 {
585 gl::UniformBlock *uniformBlock = uniformBlocks[uniformBlockIndex];
586 gl::Buffer *uniformBuffer = boundBuffers[uniformBlockIndex];
587
588 ASSERT(uniformBlock && uniformBuffer);
589
590 if (uniformBuffer->getSize() < uniformBlock->dataSize)
591 {
592 // undefined behaviour
593 return gl::Error(GL_INVALID_OPERATION, "It is undefined behaviour to use a uniform buffer that is too small.");
594 }
595
596 // Unnecessary to apply an unreferenced standard or shared UBO
597 if (!uniformBlock->isReferencedByVertexShader() && !uniformBlock->isReferencedByFragmentShader())
598 {
599 continue;
600 }
601
602 if (uniformBlock->isReferencedByVertexShader())
603 {
604 unsigned int registerIndex = uniformBlock->vsRegisterIndex - reservedBuffersInVS;
605 ASSERT(vertexUniformBuffers[registerIndex] == NULL);
606 ASSERT(registerIndex < caps.maxVertexUniformBlocks);
607 vertexUniformBuffers[registerIndex] = uniformBuffer;
608 }
609
610 if (uniformBlock->isReferencedByFragmentShader())
611 {
612 unsigned int registerIndex = uniformBlock->psRegisterIndex - reservedBuffersInFS;
613 ASSERT(fragmentUniformBuffers[registerIndex] == NULL);
614 ASSERT(registerIndex < caps.maxFragmentUniformBlocks);
615 fragmentUniformBuffers[registerIndex] = uniformBuffer;
616 }
617 }
618
619 return mRenderer->setUniformBuffers(vertexUniformBuffers, fragmentUniformBuffers);
620}
621
622bool ProgramD3D::assignUniformBlockRegister(gl::InfoLog &infoLog, gl::UniformBlock *uniformBlock, GLenum shader,
623 unsigned int registerIndex, const gl::Caps &caps)
624{
625 if (shader == GL_VERTEX_SHADER)
626 {
627 uniformBlock->vsRegisterIndex = registerIndex;
628 if (registerIndex - mRenderer->getReservedVertexUniformBuffers() >= caps.maxVertexUniformBlocks)
629 {
630 infoLog.append("Vertex shader uniform block count exceed GL_MAX_VERTEX_UNIFORM_BLOCKS (%u)", caps.maxVertexUniformBlocks);
631 return false;
632 }
633 }
634 else if (shader == GL_FRAGMENT_SHADER)
635 {
636 uniformBlock->psRegisterIndex = registerIndex;
637 if (registerIndex - mRenderer->getReservedFragmentUniformBuffers() >= caps.maxFragmentUniformBlocks)
638 {
639 infoLog.append("Fragment shader uniform block count exceed GL_MAX_FRAGMENT_UNIFORM_BLOCKS (%u)", caps.maxFragmentUniformBlocks);
640 return false;
641 }
642 }
643 else UNREACHABLE();
644
645 return true;
646}
647
648unsigned int ProgramD3D::getReservedUniformVectors(GLenum shader)
649{
650 if (shader == GL_VERTEX_SHADER)
651 {
652 return mRenderer->getReservedVertexUniformVectors();
653 }
654 else if (shader == GL_FRAGMENT_SHADER)
655 {
656 return mRenderer->getReservedFragmentUniformVectors();
657 }
658 else UNREACHABLE();
659
660 return 0;
661}
662
Brandon Jonesc9610c52014-08-25 17:02:59 -0700663void ProgramD3D::reset()
664{
Brandon Joneseb994362014-09-24 10:27:28 -0700665 SafeDeleteContainer(mVertexExecutables);
666 SafeDeleteContainer(mPixelExecutables);
667 SafeDelete(mGeometryExecutable);
668
669 mTransformFeedbackBufferMode = GL_NONE;
670 mTransformFeedbackLinkedVaryings.clear();
671
Brandon Jones22502d52014-08-29 16:58:36 -0700672 mVertexHLSL.clear();
Brandon Joneseb994362014-09-24 10:27:28 -0700673 mVertexWorkarounds = ANGLE_D3D_WORKAROUND_NONE;
Brandon Jones44151a92014-09-10 11:32:25 -0700674 mShaderVersion = 100;
Brandon Jones22502d52014-08-29 16:58:36 -0700675
676 mPixelHLSL.clear();
Brandon Joneseb994362014-09-24 10:27:28 -0700677 mPixelWorkarounds = ANGLE_D3D_WORKAROUND_NONE;
Brandon Jones22502d52014-08-29 16:58:36 -0700678 mUsesFragDepth = false;
679 mPixelShaderKey.clear();
Brandon Jones44151a92014-09-10 11:32:25 -0700680 mUsesPointSize = false;
Brandon Jones22502d52014-08-29 16:58:36 -0700681
Brandon Jonesc9610c52014-08-25 17:02:59 -0700682 SafeDelete(mVertexUniformStorage);
683 SafeDelete(mFragmentUniformStorage);
684}
685
686}