blob: 7dd70ed164c4a1f4ef8d5adc639a922c21483fc4 [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
Geoff Langb543aff2014-09-30 14:52:54 -0400150gl::LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
Brandon Jones22502d52014-08-29 16:58:36 -0700151{
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();
Geoff Langb543aff2014-09-30 14:52:54 -0400204
205 ShaderExecutable *shaderExecutable = NULL;
206 gl::Error error = mRenderer->loadExecutable(vertexShaderFunction, vertexShaderSize,
207 SHADER_VERTEX,
208 mTransformFeedbackLinkedVaryings,
209 (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
210 &shaderExecutable);
211 if (error.isError())
212 {
213 return gl::LinkResult(false, error);
214 }
215
Brandon Joneseb994362014-09-24 10:27:28 -0700216 if (!shaderExecutable)
217 {
218 infoLog.append("Could not create vertex shader.");
Geoff Langb543aff2014-09-30 14:52:54 -0400219 return gl::LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Joneseb994362014-09-24 10:27:28 -0700220 }
221
222 // generated converted input layout
223 GLenum signature[gl::MAX_VERTEX_ATTRIBS];
224 getInputLayoutSignature(inputLayout, signature);
225
226 // add new binary
227 mVertexExecutables.push_back(new VertexExecutable(inputLayout, signature, shaderExecutable));
228
229 stream->skip(vertexShaderSize);
230 }
231
232 const size_t pixelShaderCount = stream->readInt<unsigned int>();
233 for (size_t pixelShaderIndex = 0; pixelShaderIndex < pixelShaderCount; pixelShaderIndex++)
234 {
235 const size_t outputCount = stream->readInt<unsigned int>();
236 std::vector<GLenum> outputs(outputCount);
237 for (size_t outputIndex = 0; outputIndex < outputCount; outputIndex++)
238 {
239 stream->readInt(&outputs[outputIndex]);
240 }
241
242 const size_t pixelShaderSize = stream->readInt<unsigned int>();
243 const unsigned char *pixelShaderFunction = binary + stream->offset();
Geoff Langb543aff2014-09-30 14:52:54 -0400244 ShaderExecutable *shaderExecutable = NULL;
245 gl::Error error = mRenderer->loadExecutable(pixelShaderFunction, pixelShaderSize, SHADER_PIXEL,
246 mTransformFeedbackLinkedVaryings,
247 (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
248 &shaderExecutable);
249 if (error.isError())
250 {
251 return gl::LinkResult(false, error);
252 }
Brandon Joneseb994362014-09-24 10:27:28 -0700253
254 if (!shaderExecutable)
255 {
256 infoLog.append("Could not create pixel shader.");
Geoff Langb543aff2014-09-30 14:52:54 -0400257 return gl::LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Joneseb994362014-09-24 10:27:28 -0700258 }
259
260 // add new binary
261 mPixelExecutables.push_back(new PixelExecutable(outputs, shaderExecutable));
262
263 stream->skip(pixelShaderSize);
264 }
265
266 unsigned int geometryShaderSize = stream->readInt<unsigned int>();
267
268 if (geometryShaderSize > 0)
269 {
270 const unsigned char *geometryShaderFunction = binary + stream->offset();
Geoff Langb543aff2014-09-30 14:52:54 -0400271 gl::Error error = mRenderer->loadExecutable(geometryShaderFunction, geometryShaderSize, SHADER_GEOMETRY,
272 mTransformFeedbackLinkedVaryings,
273 (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
274 &mGeometryExecutable);
275 if (error.isError())
276 {
277 return gl::LinkResult(false, error);
278 }
Brandon Joneseb994362014-09-24 10:27:28 -0700279
280 if (!mGeometryExecutable)
281 {
282 infoLog.append("Could not create geometry shader.");
Geoff Langb543aff2014-09-30 14:52:54 -0400283 return gl::LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Joneseb994362014-09-24 10:27:28 -0700284 }
285 stream->skip(geometryShaderSize);
286 }
287
Brandon Jones18bd4102014-09-22 14:21:44 -0700288 GUID binaryIdentifier = {0};
289 stream->readBytes(reinterpret_cast<unsigned char*>(&binaryIdentifier), sizeof(GUID));
290
291 GUID identifier = mRenderer->getAdapterIdentifier();
292 if (memcmp(&identifier, &binaryIdentifier, sizeof(GUID)) != 0)
293 {
294 infoLog.append("Invalid program binary.");
Geoff Langb543aff2014-09-30 14:52:54 -0400295 return gl::LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Jones18bd4102014-09-22 14:21:44 -0700296 }
297
Geoff Langb543aff2014-09-30 14:52:54 -0400298 return gl::LinkResult(true, gl::Error(GL_NO_ERROR));
Brandon Jones22502d52014-08-29 16:58:36 -0700299}
300
Geoff Langb543aff2014-09-30 14:52:54 -0400301gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream)
Brandon Jones22502d52014-08-29 16:58:36 -0700302{
Brandon Jones44151a92014-09-10 11:32:25 -0700303 stream->writeInt(mShaderVersion);
304
Brandon Joneseb994362014-09-24 10:27:28 -0700305 stream->writeInt(mTransformFeedbackBufferMode);
306 stream->writeInt(mTransformFeedbackLinkedVaryings.size());
307 for (size_t i = 0; i < mTransformFeedbackLinkedVaryings.size(); i++)
308 {
309 const gl::LinkedVarying &varying = mTransformFeedbackLinkedVaryings[i];
310
311 stream->writeString(varying.name);
312 stream->writeInt(varying.type);
313 stream->writeInt(varying.size);
314 stream->writeString(varying.semanticName);
315 stream->writeInt(varying.semanticIndex);
316 stream->writeInt(varying.semanticIndexCount);
317 }
318
Brandon Jones22502d52014-08-29 16:58:36 -0700319 stream->writeString(mVertexHLSL);
320 stream->writeInt(mVertexWorkarounds);
321 stream->writeString(mPixelHLSL);
322 stream->writeInt(mPixelWorkarounds);
323 stream->writeInt(mUsesFragDepth);
Brandon Jones44151a92014-09-10 11:32:25 -0700324 stream->writeInt(mUsesPointSize);
Brandon Jones22502d52014-08-29 16:58:36 -0700325
Brandon Joneseb994362014-09-24 10:27:28 -0700326 const std::vector<PixelShaderOutputVariable> &pixelShaderKey = mPixelShaderKey;
Brandon Jones22502d52014-08-29 16:58:36 -0700327 stream->writeInt(pixelShaderKey.size());
328 for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKey.size(); pixelShaderKeyIndex++)
329 {
Brandon Joneseb994362014-09-24 10:27:28 -0700330 const PixelShaderOutputVariable &variable = pixelShaderKey[pixelShaderKeyIndex];
Brandon Jones22502d52014-08-29 16:58:36 -0700331 stream->writeInt(variable.type);
332 stream->writeString(variable.name);
333 stream->writeString(variable.source);
334 stream->writeInt(variable.outputIndex);
335 }
336
Brandon Joneseb994362014-09-24 10:27:28 -0700337 stream->writeInt(mVertexExecutables.size());
338 for (size_t vertexExecutableIndex = 0; vertexExecutableIndex < mVertexExecutables.size(); vertexExecutableIndex++)
339 {
340 VertexExecutable *vertexExecutable = mVertexExecutables[vertexExecutableIndex];
341
342 for (size_t inputIndex = 0; inputIndex < gl::MAX_VERTEX_ATTRIBS; inputIndex++)
343 {
344 const gl::VertexFormat &vertexInput = vertexExecutable->inputs()[inputIndex];
345 stream->writeInt(vertexInput.mType);
346 stream->writeInt(vertexInput.mNormalized);
347 stream->writeInt(vertexInput.mComponents);
348 stream->writeInt(vertexInput.mPureInteger);
349 }
350
351 size_t vertexShaderSize = vertexExecutable->shaderExecutable()->getLength();
352 stream->writeInt(vertexShaderSize);
353
354 const uint8_t *vertexBlob = vertexExecutable->shaderExecutable()->getFunction();
355 stream->writeBytes(vertexBlob, vertexShaderSize);
356 }
357
358 stream->writeInt(mPixelExecutables.size());
359 for (size_t pixelExecutableIndex = 0; pixelExecutableIndex < mPixelExecutables.size(); pixelExecutableIndex++)
360 {
361 PixelExecutable *pixelExecutable = mPixelExecutables[pixelExecutableIndex];
362
363 const std::vector<GLenum> outputs = pixelExecutable->outputSignature();
364 stream->writeInt(outputs.size());
365 for (size_t outputIndex = 0; outputIndex < outputs.size(); outputIndex++)
366 {
367 stream->writeInt(outputs[outputIndex]);
368 }
369
370 size_t pixelShaderSize = pixelExecutable->shaderExecutable()->getLength();
371 stream->writeInt(pixelShaderSize);
372
373 const uint8_t *pixelBlob = pixelExecutable->shaderExecutable()->getFunction();
374 stream->writeBytes(pixelBlob, pixelShaderSize);
375 }
376
377 size_t geometryShaderSize = (mGeometryExecutable != NULL) ? mGeometryExecutable->getLength() : 0;
378 stream->writeInt(geometryShaderSize);
379
380 if (mGeometryExecutable != NULL && geometryShaderSize > 0)
381 {
382 const uint8_t *geometryBlob = mGeometryExecutable->getFunction();
383 stream->writeBytes(geometryBlob, geometryShaderSize);
384 }
385
Brandon Jones18bd4102014-09-22 14:21:44 -0700386 GUID binaryIdentifier = mRenderer->getAdapterIdentifier();
Geoff Langb543aff2014-09-30 14:52:54 -0400387 stream->writeBytes(reinterpret_cast<unsigned char*>(&binaryIdentifier), sizeof(GUID));
Brandon Jones18bd4102014-09-22 14:21:44 -0700388
Geoff Langb543aff2014-09-30 14:52:54 -0400389 return gl::Error(GL_NO_ERROR);
Brandon Jones22502d52014-08-29 16:58:36 -0700390}
391
Geoff Langb543aff2014-09-30 14:52:54 -0400392gl::Error ProgramD3D::getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo, ShaderExecutable **outExecutable)
Brandon Jones22502d52014-08-29 16:58:36 -0700393{
Brandon Joneseb994362014-09-24 10:27:28 -0700394 std::vector<GLenum> outputs;
395
396 const gl::ColorbufferInfo &colorbuffers = fbo->getColorbuffersForRender();
397
398 for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment)
399 {
400 const gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment];
401
402 if (colorbuffer)
403 {
404 outputs.push_back(colorbuffer->getBinding() == GL_BACK ? GL_COLOR_ATTACHMENT0 : colorbuffer->getBinding());
405 }
406 else
407 {
408 outputs.push_back(GL_NONE);
409 }
410 }
411
Geoff Langb543aff2014-09-30 14:52:54 -0400412 return getPixelExecutableForOutputLayout(outputs, outExecutable);
Brandon Joneseb994362014-09-24 10:27:28 -0700413}
414
Geoff Langb543aff2014-09-30 14:52:54 -0400415gl::Error ProgramD3D::getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputSignature, ShaderExecutable **outExectuable)
Brandon Joneseb994362014-09-24 10:27:28 -0700416{
417 for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++)
418 {
419 if (mPixelExecutables[executableIndex]->matchesSignature(outputSignature))
420 {
Geoff Langb543aff2014-09-30 14:52:54 -0400421 *outExectuable = mPixelExecutables[executableIndex]->shaderExecutable();
422 return gl::Error(GL_NO_ERROR);
Brandon Joneseb994362014-09-24 10:27:28 -0700423 }
424 }
425
Brandon Jones22502d52014-08-29 16:58:36 -0700426 std::string finalPixelHLSL = mDynamicHLSL->generatePixelShaderForOutputSignature(mPixelHLSL, mPixelShaderKey, mUsesFragDepth,
427 outputSignature);
428
429 // Generate new pixel executable
Brandon Joneseb994362014-09-24 10:27:28 -0700430 gl::InfoLog tempInfoLog;
Geoff Langb543aff2014-09-30 14:52:54 -0400431 ShaderExecutable *pixelExecutable = NULL;
432 gl::Error error = mRenderer->compileToExecutable(tempInfoLog, finalPixelHLSL, SHADER_PIXEL,
433 mTransformFeedbackLinkedVaryings,
434 (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
435 mPixelWorkarounds, &pixelExecutable);
436 if (error.isError())
437 {
438 return error;
439 }
Brandon Joneseb994362014-09-24 10:27:28 -0700440
441 if (!pixelExecutable)
442 {
443 std::vector<char> tempCharBuffer(tempInfoLog.getLength() + 3);
444 tempInfoLog.getLog(tempInfoLog.getLength(), NULL, &tempCharBuffer[0]);
445 ERR("Error compiling dynamic pixel executable:\n%s\n", &tempCharBuffer[0]);
446 }
447 else
448 {
449 mPixelExecutables.push_back(new PixelExecutable(outputSignature, pixelExecutable));
450 }
Brandon Jones22502d52014-08-29 16:58:36 -0700451
Geoff Langb543aff2014-09-30 14:52:54 -0400452 *outExectuable = pixelExecutable;
453 return gl::Error(GL_NO_ERROR);
Brandon Jones22502d52014-08-29 16:58:36 -0700454}
455
Geoff Langb543aff2014-09-30 14:52:54 -0400456gl::Error ProgramD3D::getVertexExecutableForInputLayout(const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS], ShaderExecutable **outExectuable)
Brandon Jones22502d52014-08-29 16:58:36 -0700457{
Brandon Joneseb994362014-09-24 10:27:28 -0700458 GLenum signature[gl::MAX_VERTEX_ATTRIBS];
459 getInputLayoutSignature(inputLayout, signature);
460
461 for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++)
462 {
463 if (mVertexExecutables[executableIndex]->matchesSignature(signature))
464 {
Geoff Langb543aff2014-09-30 14:52:54 -0400465 *outExectuable = mVertexExecutables[executableIndex]->shaderExecutable();
466 return gl::Error(GL_NO_ERROR);
Brandon Joneseb994362014-09-24 10:27:28 -0700467 }
468 }
469
Brandon Jones22502d52014-08-29 16:58:36 -0700470 // Generate new dynamic layout with attribute conversions
Brandon Joneseb994362014-09-24 10:27:28 -0700471 std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout(mVertexHLSL, inputLayout, mShaderAttributes);
Brandon Jones22502d52014-08-29 16:58:36 -0700472
473 // Generate new vertex executable
Brandon Joneseb994362014-09-24 10:27:28 -0700474 gl::InfoLog tempInfoLog;
Geoff Langb543aff2014-09-30 14:52:54 -0400475 ShaderExecutable *vertexExecutable = NULL;
476 gl::Error error = mRenderer->compileToExecutable(tempInfoLog, finalVertexHLSL, SHADER_VERTEX,
477 mTransformFeedbackLinkedVaryings,
478 (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
479 mVertexWorkarounds, &vertexExecutable);
480 if (error.isError())
481 {
482 return error;
483 }
484
Brandon Joneseb994362014-09-24 10:27:28 -0700485 if (!vertexExecutable)
486 {
487 std::vector<char> tempCharBuffer(tempInfoLog.getLength()+3);
488 tempInfoLog.getLog(tempInfoLog.getLength(), NULL, &tempCharBuffer[0]);
489 ERR("Error compiling dynamic vertex executable:\n%s\n", &tempCharBuffer[0]);
490 }
491 else
492 {
493 mVertexExecutables.push_back(new VertexExecutable(inputLayout, signature, vertexExecutable));
494 }
Brandon Jones22502d52014-08-29 16:58:36 -0700495
Geoff Langb543aff2014-09-30 14:52:54 -0400496 *outExectuable = vertexExecutable;
497 return gl::Error(GL_NO_ERROR);
Brandon Jones22502d52014-08-29 16:58:36 -0700498}
499
Geoff Langb543aff2014-09-30 14:52:54 -0400500gl::LinkResult ProgramD3D::compileProgramExecutables(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader,
501 int registers)
Brandon Jones44151a92014-09-10 11:32:25 -0700502{
Brandon Jones18bd4102014-09-22 14:21:44 -0700503 ShaderD3D *vertexShaderD3D = ShaderD3D::makeShaderD3D(vertexShader->getImplementation());
504 ShaderD3D *fragmentShaderD3D = ShaderD3D::makeShaderD3D(fragmentShader->getImplementation());
Brandon Jones44151a92014-09-10 11:32:25 -0700505
Brandon Joneseb994362014-09-24 10:27:28 -0700506 gl::VertexFormat defaultInputLayout[gl::MAX_VERTEX_ATTRIBS];
507 GetDefaultInputLayoutFromShader(vertexShader->getActiveAttributes(), defaultInputLayout);
Geoff Langb543aff2014-09-30 14:52:54 -0400508 ShaderExecutable *defaultVertexExecutable = NULL;
509 gl::Error error = getVertexExecutableForInputLayout(defaultInputLayout, &defaultVertexExecutable);
510 if (error.isError())
511 {
512 return gl::LinkResult(false, error);
513 }
Brandon Jones44151a92014-09-10 11:32:25 -0700514
Brandon Joneseb994362014-09-24 10:27:28 -0700515 std::vector<GLenum> defaultPixelOutput = GetDefaultOutputLayoutFromShader(getPixelShaderKey());
Geoff Langb543aff2014-09-30 14:52:54 -0400516 ShaderExecutable *defaultPixelExecutable = NULL;
517 error = getPixelExecutableForOutputLayout(defaultPixelOutput, &defaultPixelExecutable);
518 if (error.isError())
519 {
520 return gl::LinkResult(false, error);
521 }
Brandon Jones44151a92014-09-10 11:32:25 -0700522
Brandon Joneseb994362014-09-24 10:27:28 -0700523 if (usesGeometryShader())
524 {
525 std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL(registers, fragmentShaderD3D, vertexShaderD3D);
Brandon Jones44151a92014-09-10 11:32:25 -0700526
Geoff Langb543aff2014-09-30 14:52:54 -0400527
528 error = mRenderer->compileToExecutable(infoLog, geometryHLSL, SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings,
529 (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
530 ANGLE_D3D_WORKAROUND_NONE, &mGeometryExecutable);
531 if (error.isError())
532 {
533 return gl::LinkResult(false, error);
534 }
Brandon Joneseb994362014-09-24 10:27:28 -0700535 }
536
Geoff Langb543aff2014-09-30 14:52:54 -0400537 bool linkSuccess = (defaultVertexExecutable && defaultPixelExecutable && (!usesGeometryShader() || mGeometryExecutable));
538 return gl::LinkResult(linkSuccess, gl::Error(GL_NO_ERROR));
Brandon Jones18bd4102014-09-22 14:21:44 -0700539}
540
Geoff Langb543aff2014-09-30 14:52:54 -0400541gl::LinkResult ProgramD3D::link(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader,
542 const std::vector<std::string> &transformFeedbackVaryings, GLenum transformFeedbackBufferMode,
543 int *registers, std::vector<gl::LinkedVarying> *linkedVaryings,
544 std::map<int, gl::VariableLocation> *outputVariables, const gl::Caps &caps)
Brandon Jones22502d52014-08-29 16:58:36 -0700545{
Brandon Joneseb994362014-09-24 10:27:28 -0700546 ShaderD3D *vertexShaderD3D = ShaderD3D::makeShaderD3D(vertexShader->getImplementation());
547 ShaderD3D *fragmentShaderD3D = ShaderD3D::makeShaderD3D(fragmentShader->getImplementation());
548
549 mTransformFeedbackBufferMode = transformFeedbackBufferMode;
Brandon Jones22502d52014-08-29 16:58:36 -0700550
551 mPixelHLSL = fragmentShaderD3D->getTranslatedSource();
552 mPixelWorkarounds = fragmentShaderD3D->getD3DWorkarounds();
553
554 mVertexHLSL = vertexShaderD3D->getTranslatedSource();
555 mVertexWorkarounds = vertexShaderD3D->getD3DWorkarounds();
Brandon Jones44151a92014-09-10 11:32:25 -0700556 mShaderVersion = vertexShaderD3D->getShaderVersion();
Brandon Jones22502d52014-08-29 16:58:36 -0700557
558 // Map the varyings to the register file
Brandon Joneseb994362014-09-24 10:27:28 -0700559 VaryingPacking packing = { NULL };
Brandon Jones22502d52014-08-29 16:58:36 -0700560 *registers = mDynamicHLSL->packVaryings(infoLog, packing, fragmentShaderD3D, vertexShaderD3D, transformFeedbackVaryings);
561
Geoff Langbdee2d52014-09-17 11:02:51 -0400562 if (*registers < 0)
Brandon Jones22502d52014-08-29 16:58:36 -0700563 {
Geoff Langb543aff2014-09-30 14:52:54 -0400564 return gl::LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Jones22502d52014-08-29 16:58:36 -0700565 }
566
567 if (!gl::ProgramBinary::linkVaryings(infoLog, fragmentShader, vertexShader))
568 {
Geoff Langb543aff2014-09-30 14:52:54 -0400569 return gl::LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Jones22502d52014-08-29 16:58:36 -0700570 }
571
572 if (!mDynamicHLSL->generateShaderLinkHLSL(infoLog, *registers, packing, mPixelHLSL, mVertexHLSL,
573 fragmentShaderD3D, vertexShaderD3D, transformFeedbackVaryings,
574 linkedVaryings, outputVariables, &mPixelShaderKey, &mUsesFragDepth))
575 {
Geoff Langb543aff2014-09-30 14:52:54 -0400576 return gl::LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Jones22502d52014-08-29 16:58:36 -0700577 }
578
Brandon Jones44151a92014-09-10 11:32:25 -0700579 mUsesPointSize = vertexShaderD3D->usesPointSize();
580
Geoff Langb543aff2014-09-30 14:52:54 -0400581 return gl::LinkResult(true, gl::Error(GL_NO_ERROR));
Brandon Jones22502d52014-08-29 16:58:36 -0700582}
583
Brandon Jones44151a92014-09-10 11:32:25 -0700584void ProgramD3D::getInputLayoutSignature(const gl::VertexFormat inputLayout[], GLenum signature[]) const
585{
586 mDynamicHLSL->getInputLayoutSignature(inputLayout, signature);
587}
588
Brandon Jonesc9610c52014-08-25 17:02:59 -0700589void ProgramD3D::initializeUniformStorage(const std::vector<gl::LinkedUniform*> &uniforms)
590{
591 // Compute total default block size
592 unsigned int vertexRegisters = 0;
593 unsigned int fragmentRegisters = 0;
594 for (size_t uniformIndex = 0; uniformIndex < uniforms.size(); uniformIndex++)
595 {
596 const gl::LinkedUniform &uniform = *uniforms[uniformIndex];
597
598 if (!gl::IsSampler(uniform.type))
599 {
600 if (uniform.isReferencedByVertexShader())
601 {
602 vertexRegisters = std::max(vertexRegisters, uniform.vsRegisterIndex + uniform.registerCount);
603 }
604 if (uniform.isReferencedByFragmentShader())
605 {
606 fragmentRegisters = std::max(fragmentRegisters, uniform.psRegisterIndex + uniform.registerCount);
607 }
608 }
609 }
610
611 mVertexUniformStorage = mRenderer->createUniformStorage(vertexRegisters * 16u);
612 mFragmentUniformStorage = mRenderer->createUniformStorage(fragmentRegisters * 16u);
613}
614
Brandon Jones18bd4102014-09-22 14:21:44 -0700615gl::Error ProgramD3D::applyUniforms(const std::vector<gl::LinkedUniform*> &uniforms)
616{
617 return mRenderer->applyUniforms(*this, uniforms);
618}
619
620gl::Error ProgramD3D::applyUniformBuffers(const std::vector<gl::UniformBlock*> uniformBlocks, const std::vector<gl::Buffer*> boundBuffers,
Brandon Joneseb994362014-09-24 10:27:28 -0700621 const gl::Caps &caps)
Brandon Jones18bd4102014-09-22 14:21:44 -0700622{
623 const gl::Buffer *vertexUniformBuffers[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS] = {NULL};
624 const gl::Buffer *fragmentUniformBuffers[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS] = {NULL};
625
626 const unsigned int reservedBuffersInVS = mRenderer->getReservedVertexUniformBuffers();
627 const unsigned int reservedBuffersInFS = mRenderer->getReservedFragmentUniformBuffers();
628
629 for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < uniformBlocks.size(); uniformBlockIndex++)
630 {
631 gl::UniformBlock *uniformBlock = uniformBlocks[uniformBlockIndex];
632 gl::Buffer *uniformBuffer = boundBuffers[uniformBlockIndex];
633
634 ASSERT(uniformBlock && uniformBuffer);
635
636 if (uniformBuffer->getSize() < uniformBlock->dataSize)
637 {
638 // undefined behaviour
639 return gl::Error(GL_INVALID_OPERATION, "It is undefined behaviour to use a uniform buffer that is too small.");
640 }
641
642 // Unnecessary to apply an unreferenced standard or shared UBO
643 if (!uniformBlock->isReferencedByVertexShader() && !uniformBlock->isReferencedByFragmentShader())
644 {
645 continue;
646 }
647
648 if (uniformBlock->isReferencedByVertexShader())
649 {
650 unsigned int registerIndex = uniformBlock->vsRegisterIndex - reservedBuffersInVS;
651 ASSERT(vertexUniformBuffers[registerIndex] == NULL);
652 ASSERT(registerIndex < caps.maxVertexUniformBlocks);
653 vertexUniformBuffers[registerIndex] = uniformBuffer;
654 }
655
656 if (uniformBlock->isReferencedByFragmentShader())
657 {
658 unsigned int registerIndex = uniformBlock->psRegisterIndex - reservedBuffersInFS;
659 ASSERT(fragmentUniformBuffers[registerIndex] == NULL);
660 ASSERT(registerIndex < caps.maxFragmentUniformBlocks);
661 fragmentUniformBuffers[registerIndex] = uniformBuffer;
662 }
663 }
664
665 return mRenderer->setUniformBuffers(vertexUniformBuffers, fragmentUniformBuffers);
666}
667
668bool ProgramD3D::assignUniformBlockRegister(gl::InfoLog &infoLog, gl::UniformBlock *uniformBlock, GLenum shader,
669 unsigned int registerIndex, const gl::Caps &caps)
670{
671 if (shader == GL_VERTEX_SHADER)
672 {
673 uniformBlock->vsRegisterIndex = registerIndex;
674 if (registerIndex - mRenderer->getReservedVertexUniformBuffers() >= caps.maxVertexUniformBlocks)
675 {
676 infoLog.append("Vertex shader uniform block count exceed GL_MAX_VERTEX_UNIFORM_BLOCKS (%u)", caps.maxVertexUniformBlocks);
677 return false;
678 }
679 }
680 else if (shader == GL_FRAGMENT_SHADER)
681 {
682 uniformBlock->psRegisterIndex = registerIndex;
683 if (registerIndex - mRenderer->getReservedFragmentUniformBuffers() >= caps.maxFragmentUniformBlocks)
684 {
685 infoLog.append("Fragment shader uniform block count exceed GL_MAX_FRAGMENT_UNIFORM_BLOCKS (%u)", caps.maxFragmentUniformBlocks);
686 return false;
687 }
688 }
689 else UNREACHABLE();
690
691 return true;
692}
693
694unsigned int ProgramD3D::getReservedUniformVectors(GLenum shader)
695{
696 if (shader == GL_VERTEX_SHADER)
697 {
698 return mRenderer->getReservedVertexUniformVectors();
699 }
700 else if (shader == GL_FRAGMENT_SHADER)
701 {
702 return mRenderer->getReservedFragmentUniformVectors();
703 }
704 else UNREACHABLE();
705
706 return 0;
707}
708
Brandon Jonesc9610c52014-08-25 17:02:59 -0700709void ProgramD3D::reset()
710{
Brandon Joneseb994362014-09-24 10:27:28 -0700711 SafeDeleteContainer(mVertexExecutables);
712 SafeDeleteContainer(mPixelExecutables);
713 SafeDelete(mGeometryExecutable);
714
715 mTransformFeedbackBufferMode = GL_NONE;
716 mTransformFeedbackLinkedVaryings.clear();
717
Brandon Jones22502d52014-08-29 16:58:36 -0700718 mVertexHLSL.clear();
Brandon Joneseb994362014-09-24 10:27:28 -0700719 mVertexWorkarounds = ANGLE_D3D_WORKAROUND_NONE;
Brandon Jones44151a92014-09-10 11:32:25 -0700720 mShaderVersion = 100;
Brandon Jones22502d52014-08-29 16:58:36 -0700721
722 mPixelHLSL.clear();
Brandon Joneseb994362014-09-24 10:27:28 -0700723 mPixelWorkarounds = ANGLE_D3D_WORKAROUND_NONE;
Brandon Jones22502d52014-08-29 16:58:36 -0700724 mUsesFragDepth = false;
725 mPixelShaderKey.clear();
Brandon Jones44151a92014-09-10 11:32:25 -0700726 mUsesPointSize = false;
Brandon Jones22502d52014-08-29 16:58:36 -0700727
Brandon Jonesc9610c52014-08-25 17:02:59 -0700728 SafeDelete(mVertexUniformStorage);
729 SafeDelete(mFragmentUniformStorage);
730}
731
732}