blob: 681c33053c1c91e626de4c821a7472d107a8f9e5 [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
Tibor den Ouden97049c62014-10-06 21:39:16 +0200537#ifdef ANGLE_GENERATE_SHADER_DEBUG_INFO
538 if (usesGeometryShader() && mGeometryExecutable)
539 {
540 // Geometry shaders are currently only used internally, so there is no corresponding shader object at the interface level
541 // For now the geometry shader debug info is pre-pended to the vertex shader, this is a bit of a clutch
542 vertexShaderD3D->appendDebugInfo("// GEOMETRY SHADER BEGIN\n\n");
543 vertexShaderD3D->appendDebugInfo(mGeometryExecutable->getDebugInfo());
544 vertexShaderD3D->appendDebugInfo("\nGEOMETRY SHADER END\n\n\n");
545 }
546
547 if (defaultVertexExecutable)
548 {
549 vertexShaderD3D->appendDebugInfo(defaultVertexExecutable->getDebugInfo());
550 }
551
552 if (defaultPixelExecutable)
553 {
554 fragmentShaderD3D->appendDebugInfo(defaultPixelExecutable->getDebugInfo());
555 }
556#endif
557
Geoff Langb543aff2014-09-30 14:52:54 -0400558 bool linkSuccess = (defaultVertexExecutable && defaultPixelExecutable && (!usesGeometryShader() || mGeometryExecutable));
559 return gl::LinkResult(linkSuccess, gl::Error(GL_NO_ERROR));
Brandon Jones18bd4102014-09-22 14:21:44 -0700560}
561
Geoff Langb543aff2014-09-30 14:52:54 -0400562gl::LinkResult ProgramD3D::link(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader,
563 const std::vector<std::string> &transformFeedbackVaryings, GLenum transformFeedbackBufferMode,
564 int *registers, std::vector<gl::LinkedVarying> *linkedVaryings,
565 std::map<int, gl::VariableLocation> *outputVariables, const gl::Caps &caps)
Brandon Jones22502d52014-08-29 16:58:36 -0700566{
Brandon Joneseb994362014-09-24 10:27:28 -0700567 ShaderD3D *vertexShaderD3D = ShaderD3D::makeShaderD3D(vertexShader->getImplementation());
568 ShaderD3D *fragmentShaderD3D = ShaderD3D::makeShaderD3D(fragmentShader->getImplementation());
569
570 mTransformFeedbackBufferMode = transformFeedbackBufferMode;
Brandon Jones22502d52014-08-29 16:58:36 -0700571
572 mPixelHLSL = fragmentShaderD3D->getTranslatedSource();
573 mPixelWorkarounds = fragmentShaderD3D->getD3DWorkarounds();
574
575 mVertexHLSL = vertexShaderD3D->getTranslatedSource();
576 mVertexWorkarounds = vertexShaderD3D->getD3DWorkarounds();
Brandon Jones44151a92014-09-10 11:32:25 -0700577 mShaderVersion = vertexShaderD3D->getShaderVersion();
Brandon Jones22502d52014-08-29 16:58:36 -0700578
579 // Map the varyings to the register file
Brandon Joneseb994362014-09-24 10:27:28 -0700580 VaryingPacking packing = { NULL };
Brandon Jones22502d52014-08-29 16:58:36 -0700581 *registers = mDynamicHLSL->packVaryings(infoLog, packing, fragmentShaderD3D, vertexShaderD3D, transformFeedbackVaryings);
582
Geoff Langbdee2d52014-09-17 11:02:51 -0400583 if (*registers < 0)
Brandon Jones22502d52014-08-29 16:58:36 -0700584 {
Geoff Langb543aff2014-09-30 14:52:54 -0400585 return gl::LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Jones22502d52014-08-29 16:58:36 -0700586 }
587
588 if (!gl::ProgramBinary::linkVaryings(infoLog, fragmentShader, vertexShader))
589 {
Geoff Langb543aff2014-09-30 14:52:54 -0400590 return gl::LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Jones22502d52014-08-29 16:58:36 -0700591 }
592
593 if (!mDynamicHLSL->generateShaderLinkHLSL(infoLog, *registers, packing, mPixelHLSL, mVertexHLSL,
594 fragmentShaderD3D, vertexShaderD3D, transformFeedbackVaryings,
595 linkedVaryings, outputVariables, &mPixelShaderKey, &mUsesFragDepth))
596 {
Geoff Langb543aff2014-09-30 14:52:54 -0400597 return gl::LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Jones22502d52014-08-29 16:58:36 -0700598 }
599
Brandon Jones44151a92014-09-10 11:32:25 -0700600 mUsesPointSize = vertexShaderD3D->usesPointSize();
601
Geoff Langb543aff2014-09-30 14:52:54 -0400602 return gl::LinkResult(true, gl::Error(GL_NO_ERROR));
Brandon Jones22502d52014-08-29 16:58:36 -0700603}
604
Brandon Jones44151a92014-09-10 11:32:25 -0700605void ProgramD3D::getInputLayoutSignature(const gl::VertexFormat inputLayout[], GLenum signature[]) const
606{
607 mDynamicHLSL->getInputLayoutSignature(inputLayout, signature);
608}
609
Brandon Jonesc9610c52014-08-25 17:02:59 -0700610void ProgramD3D::initializeUniformStorage(const std::vector<gl::LinkedUniform*> &uniforms)
611{
612 // Compute total default block size
613 unsigned int vertexRegisters = 0;
614 unsigned int fragmentRegisters = 0;
615 for (size_t uniformIndex = 0; uniformIndex < uniforms.size(); uniformIndex++)
616 {
617 const gl::LinkedUniform &uniform = *uniforms[uniformIndex];
618
619 if (!gl::IsSampler(uniform.type))
620 {
621 if (uniform.isReferencedByVertexShader())
622 {
623 vertexRegisters = std::max(vertexRegisters, uniform.vsRegisterIndex + uniform.registerCount);
624 }
625 if (uniform.isReferencedByFragmentShader())
626 {
627 fragmentRegisters = std::max(fragmentRegisters, uniform.psRegisterIndex + uniform.registerCount);
628 }
629 }
630 }
631
632 mVertexUniformStorage = mRenderer->createUniformStorage(vertexRegisters * 16u);
633 mFragmentUniformStorage = mRenderer->createUniformStorage(fragmentRegisters * 16u);
634}
635
Brandon Jones18bd4102014-09-22 14:21:44 -0700636gl::Error ProgramD3D::applyUniforms(const std::vector<gl::LinkedUniform*> &uniforms)
637{
638 return mRenderer->applyUniforms(*this, uniforms);
639}
640
641gl::Error ProgramD3D::applyUniformBuffers(const std::vector<gl::UniformBlock*> uniformBlocks, const std::vector<gl::Buffer*> boundBuffers,
Brandon Joneseb994362014-09-24 10:27:28 -0700642 const gl::Caps &caps)
Brandon Jones18bd4102014-09-22 14:21:44 -0700643{
644 const gl::Buffer *vertexUniformBuffers[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS] = {NULL};
645 const gl::Buffer *fragmentUniformBuffers[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS] = {NULL};
646
647 const unsigned int reservedBuffersInVS = mRenderer->getReservedVertexUniformBuffers();
648 const unsigned int reservedBuffersInFS = mRenderer->getReservedFragmentUniformBuffers();
649
650 for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < uniformBlocks.size(); uniformBlockIndex++)
651 {
652 gl::UniformBlock *uniformBlock = uniformBlocks[uniformBlockIndex];
653 gl::Buffer *uniformBuffer = boundBuffers[uniformBlockIndex];
654
655 ASSERT(uniformBlock && uniformBuffer);
656
657 if (uniformBuffer->getSize() < uniformBlock->dataSize)
658 {
659 // undefined behaviour
660 return gl::Error(GL_INVALID_OPERATION, "It is undefined behaviour to use a uniform buffer that is too small.");
661 }
662
663 // Unnecessary to apply an unreferenced standard or shared UBO
664 if (!uniformBlock->isReferencedByVertexShader() && !uniformBlock->isReferencedByFragmentShader())
665 {
666 continue;
667 }
668
669 if (uniformBlock->isReferencedByVertexShader())
670 {
671 unsigned int registerIndex = uniformBlock->vsRegisterIndex - reservedBuffersInVS;
672 ASSERT(vertexUniformBuffers[registerIndex] == NULL);
673 ASSERT(registerIndex < caps.maxVertexUniformBlocks);
674 vertexUniformBuffers[registerIndex] = uniformBuffer;
675 }
676
677 if (uniformBlock->isReferencedByFragmentShader())
678 {
679 unsigned int registerIndex = uniformBlock->psRegisterIndex - reservedBuffersInFS;
680 ASSERT(fragmentUniformBuffers[registerIndex] == NULL);
681 ASSERT(registerIndex < caps.maxFragmentUniformBlocks);
682 fragmentUniformBuffers[registerIndex] = uniformBuffer;
683 }
684 }
685
686 return mRenderer->setUniformBuffers(vertexUniformBuffers, fragmentUniformBuffers);
687}
688
689bool ProgramD3D::assignUniformBlockRegister(gl::InfoLog &infoLog, gl::UniformBlock *uniformBlock, GLenum shader,
690 unsigned int registerIndex, const gl::Caps &caps)
691{
692 if (shader == GL_VERTEX_SHADER)
693 {
694 uniformBlock->vsRegisterIndex = registerIndex;
695 if (registerIndex - mRenderer->getReservedVertexUniformBuffers() >= caps.maxVertexUniformBlocks)
696 {
697 infoLog.append("Vertex shader uniform block count exceed GL_MAX_VERTEX_UNIFORM_BLOCKS (%u)", caps.maxVertexUniformBlocks);
698 return false;
699 }
700 }
701 else if (shader == GL_FRAGMENT_SHADER)
702 {
703 uniformBlock->psRegisterIndex = registerIndex;
704 if (registerIndex - mRenderer->getReservedFragmentUniformBuffers() >= caps.maxFragmentUniformBlocks)
705 {
706 infoLog.append("Fragment shader uniform block count exceed GL_MAX_FRAGMENT_UNIFORM_BLOCKS (%u)", caps.maxFragmentUniformBlocks);
707 return false;
708 }
709 }
710 else UNREACHABLE();
711
712 return true;
713}
714
715unsigned int ProgramD3D::getReservedUniformVectors(GLenum shader)
716{
717 if (shader == GL_VERTEX_SHADER)
718 {
719 return mRenderer->getReservedVertexUniformVectors();
720 }
721 else if (shader == GL_FRAGMENT_SHADER)
722 {
723 return mRenderer->getReservedFragmentUniformVectors();
724 }
725 else UNREACHABLE();
726
727 return 0;
728}
729
Brandon Jonesc9610c52014-08-25 17:02:59 -0700730void ProgramD3D::reset()
731{
Brandon Joneseb994362014-09-24 10:27:28 -0700732 SafeDeleteContainer(mVertexExecutables);
733 SafeDeleteContainer(mPixelExecutables);
734 SafeDelete(mGeometryExecutable);
735
736 mTransformFeedbackBufferMode = GL_NONE;
737 mTransformFeedbackLinkedVaryings.clear();
738
Brandon Jones22502d52014-08-29 16:58:36 -0700739 mVertexHLSL.clear();
Brandon Joneseb994362014-09-24 10:27:28 -0700740 mVertexWorkarounds = ANGLE_D3D_WORKAROUND_NONE;
Brandon Jones44151a92014-09-10 11:32:25 -0700741 mShaderVersion = 100;
Brandon Jones22502d52014-08-29 16:58:36 -0700742
743 mPixelHLSL.clear();
Brandon Joneseb994362014-09-24 10:27:28 -0700744 mPixelWorkarounds = ANGLE_D3D_WORKAROUND_NONE;
Brandon Jones22502d52014-08-29 16:58:36 -0700745 mUsesFragDepth = false;
746 mPixelShaderKey.clear();
Brandon Jones44151a92014-09-10 11:32:25 -0700747 mUsesPointSize = false;
Brandon Jones22502d52014-08-29 16:58:36 -0700748
Brandon Jonesc9610c52014-08-25 17:02:59 -0700749 SafeDelete(mVertexUniformStorage);
750 SafeDelete(mFragmentUniformStorage);
751}
752
753}