blob: 9268bff2198e58b3f1a2059ee80ba481c359a9d2 [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
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/renderer/d3d/ProgramD3D.h"
Jamie Madill437d2662014-12-05 14:23:35 -050010
Dian Xianga4928832015-09-15 10:11:17 -070011#include "common/BitSetIterator.h"
Jamie Madill437d2662014-12-05 14:23:35 -050012#include "common/utilities.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050013#include "libANGLE/Framebuffer.h"
14#include "libANGLE/FramebufferAttachment.h"
15#include "libANGLE/Program.h"
Jamie Madilld3dfda22015-07-06 08:28:49 -040016#include "libANGLE/VertexArray.h"
Jamie Madill6df9b372015-02-18 21:28:19 +000017#include "libANGLE/features.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050018#include "libANGLE/renderer/d3d/DynamicHLSL.h"
Jamie Madill85a18042015-03-05 15:41:41 -050019#include "libANGLE/renderer/d3d/FramebufferD3D.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050020#include "libANGLE/renderer/d3d/RendererD3D.h"
21#include "libANGLE/renderer/d3d/ShaderD3D.h"
Geoff Lang359ef262015-01-05 14:42:29 -050022#include "libANGLE/renderer/d3d/ShaderExecutableD3D.h"
Jamie Madill437d2662014-12-05 14:23:35 -050023#include "libANGLE/renderer/d3d/VertexDataManager.h"
Geoff Lang22072132014-11-20 15:15:01 -050024
Brandon Jonesc9610c52014-08-25 17:02:59 -070025namespace rx
26{
27
Brandon Joneseb994362014-09-24 10:27:28 -070028namespace
29{
30
Jamie Madillf8dd7b12015-08-05 13:50:08 -040031gl::InputLayout GetDefaultInputLayoutFromShader(const gl::Shader *vertexShader)
Brandon Joneseb994362014-09-24 10:27:28 -070032{
Jamie Madillbd136f92015-08-10 14:51:37 -040033 gl::InputLayout defaultLayout;
34 for (const sh::Attribute &shaderAttr : vertexShader->getActiveAttributes())
Brandon Joneseb994362014-09-24 10:27:28 -070035 {
Brandon Joneseb994362014-09-24 10:27:28 -070036 if (shaderAttr.type != GL_NONE)
37 {
38 GLenum transposedType = gl::TransposeMatrixType(shaderAttr.type);
39
Jamie Madilld3dfda22015-07-06 08:28:49 -040040 for (size_t rowIndex = 0;
Jamie Madill334d6152015-10-22 14:00:28 -040041 static_cast<int>(rowIndex) < gl::VariableRowCount(transposedType); ++rowIndex)
Brandon Joneseb994362014-09-24 10:27:28 -070042 {
Jamie Madilld3dfda22015-07-06 08:28:49 -040043 GLenum componentType = gl::VariableComponentType(transposedType);
Jamie Madill334d6152015-10-22 14:00:28 -040044 GLuint components = static_cast<GLuint>(gl::VariableColumnCount(transposedType));
Jamie Madilld3dfda22015-07-06 08:28:49 -040045 bool pureInt = (componentType != GL_FLOAT);
Jamie Madill334d6152015-10-22 14:00:28 -040046 gl::VertexFormatType defaultType =
47 gl::GetVertexFormatType(componentType, GL_FALSE, components, pureInt);
Brandon Joneseb994362014-09-24 10:27:28 -070048
Jamie Madillbd136f92015-08-10 14:51:37 -040049 defaultLayout.push_back(defaultType);
Brandon Joneseb994362014-09-24 10:27:28 -070050 }
51 }
52 }
Jamie Madillf8dd7b12015-08-05 13:50:08 -040053
54 return defaultLayout;
Brandon Joneseb994362014-09-24 10:27:28 -070055}
56
Jamie Madill334d6152015-10-22 14:00:28 -040057std::vector<GLenum> GetDefaultOutputLayoutFromShader(
58 const std::vector<PixelShaderOutputVariable> &shaderOutputVars)
Brandon Joneseb994362014-09-24 10:27:28 -070059{
Jamie Madillb4463142014-12-19 14:56:54 -050060 std::vector<GLenum> defaultPixelOutput;
Brandon Joneseb994362014-09-24 10:27:28 -070061
Jamie Madillb4463142014-12-19 14:56:54 -050062 if (!shaderOutputVars.empty())
63 {
Cooper Partin4d61f7e2015-08-12 10:56:50 -070064 defaultPixelOutput.push_back(GL_COLOR_ATTACHMENT0 +
65 static_cast<unsigned int>(shaderOutputVars[0].outputIndex));
Jamie Madillb4463142014-12-19 14:56:54 -050066 }
Brandon Joneseb994362014-09-24 10:27:28 -070067
68 return defaultPixelOutput;
69}
70
Brandon Jones1a8a7e32014-10-01 12:49:30 -070071bool IsRowMajorLayout(const sh::InterfaceBlockField &var)
72{
73 return var.isRowMajorLayout;
74}
75
76bool IsRowMajorLayout(const sh::ShaderVariable &var)
77{
78 return false;
79}
80
Jamie Madill437d2662014-12-05 14:23:35 -050081struct AttributeSorter
82{
Jamie Madill63805b42015-08-25 13:17:39 -040083 AttributeSorter(const ProgramD3D::SemanticIndexArray &semanticIndices)
Jamie Madill80d934b2015-02-19 10:16:12 -050084 : originalIndices(&semanticIndices)
Jamie Madill437d2662014-12-05 14:23:35 -050085 {
86 }
87
88 bool operator()(int a, int b)
89 {
Jamie Madill80d934b2015-02-19 10:16:12 -050090 int indexA = (*originalIndices)[a];
91 int indexB = (*originalIndices)[b];
92
Jamie Madill334d6152015-10-22 14:00:28 -040093 if (indexA == -1)
94 return false;
95 if (indexB == -1)
96 return true;
Jamie Madill80d934b2015-02-19 10:16:12 -050097 return (indexA < indexB);
Jamie Madill437d2662014-12-05 14:23:35 -050098 }
99
Jamie Madill63805b42015-08-25 13:17:39 -0400100 const ProgramD3D::SemanticIndexArray *originalIndices;
Jamie Madill437d2662014-12-05 14:23:35 -0500101};
102
Jamie Madillca03b352015-09-02 12:38:13 -0400103std::vector<PackedVarying> MergeVaryings(const gl::Shader &vertexShader,
104 const gl::Shader &fragmentShader,
105 const std::vector<std::string> &tfVaryings)
Jamie Madillada9ecc2015-08-17 12:53:37 -0400106{
Jamie Madillca03b352015-09-02 12:38:13 -0400107 std::vector<PackedVarying> packedVaryings;
108
109 for (const sh::Varying &output : vertexShader.getVaryings())
Jamie Madillada9ecc2015-08-17 12:53:37 -0400110 {
Jamie Madillca03b352015-09-02 12:38:13 -0400111 bool packed = false;
Jamie Madillada9ecc2015-08-17 12:53:37 -0400112
113 // Built-in varyings obey special rules
Jamie Madillca03b352015-09-02 12:38:13 -0400114 if (output.isBuiltIn())
Jamie Madillada9ecc2015-08-17 12:53:37 -0400115 {
116 continue;
117 }
118
Jamie Madillca03b352015-09-02 12:38:13 -0400119 for (const sh::Varying &input : fragmentShader.getVaryings())
Jamie Madillada9ecc2015-08-17 12:53:37 -0400120 {
Jamie Madillca03b352015-09-02 12:38:13 -0400121 if (output.name == input.name)
Jamie Madillada9ecc2015-08-17 12:53:37 -0400122 {
Jamie Madillca03b352015-09-02 12:38:13 -0400123 packedVaryings.push_back(PackedVarying(input));
124 packed = true;
Jamie Madillada9ecc2015-08-17 12:53:37 -0400125 break;
126 }
127 }
128
Jamie Madillca03b352015-09-02 12:38:13 -0400129 // Keep Transform FB varyings in the merged list always.
130 if (!packed)
131 {
132 for (const std::string &tfVarying : tfVaryings)
133 {
134 if (tfVarying == output.name)
135 {
136 packedVaryings.push_back(PackedVarying(output));
137 packedVaryings.back().vertexOnly = true;
138 break;
139 }
140 }
141 }
Jamie Madillada9ecc2015-08-17 12:53:37 -0400142 }
143
Jamie Madillca03b352015-09-02 12:38:13 -0400144 return packedVaryings;
Brandon Joneseb994362014-09-24 10:27:28 -0700145}
146
Jamie Madill62d31cb2015-09-11 13:25:51 -0400147template <typename VarT>
148void GetUniformBlockInfo(const std::vector<VarT> &fields,
149 const std::string &prefix,
150 sh::BlockLayoutEncoder *encoder,
151 bool inRowMajorLayout,
152 std::map<std::string, sh::BlockMemberInfo> *blockInfoOut)
153{
154 for (const VarT &field : fields)
155 {
156 const std::string &fieldName = (prefix.empty() ? field.name : prefix + "." + field.name);
157
158 if (field.isStruct())
159 {
160 bool rowMajorLayout = (inRowMajorLayout || IsRowMajorLayout(field));
161
162 for (unsigned int arrayElement = 0; arrayElement < field.elementCount(); arrayElement++)
163 {
164 encoder->enterAggregateType();
165
166 const std::string uniformElementName =
167 fieldName + (field.isArray() ? ArrayString(arrayElement) : "");
168 GetUniformBlockInfo(field.fields, uniformElementName, encoder, rowMajorLayout,
169 blockInfoOut);
170
171 encoder->exitAggregateType();
172 }
173 }
174 else
175 {
176 bool isRowMajorMatrix = (gl::IsMatrixType(field.type) && inRowMajorLayout);
177 (*blockInfoOut)[fieldName] =
178 encoder->encodeType(field.type, field.arraySize, isRowMajorMatrix);
179 }
180 }
181}
182
Jamie Madill334d6152015-10-22 14:00:28 -0400183template <typename T>
184bool TransposeMatrix(T *target,
185 const GLfloat *value,
186 int targetWidth,
187 int targetHeight,
188 int srcWidth,
189 int srcHeight)
190{
191 bool dirty = false;
192 int copyWidth = std::min(targetHeight, srcWidth);
193 int copyHeight = std::min(targetWidth, srcHeight);
194
195 for (int x = 0; x < copyWidth; x++)
196 {
197 for (int y = 0; y < copyHeight; y++)
198 {
199 SetIfDirty(target + (x * targetWidth + y), static_cast<T>(value[y * srcWidth + x]),
200 &dirty);
201 }
202 }
203 // clear unfilled right side
204 for (int y = 0; y < copyWidth; y++)
205 {
206 for (int x = copyHeight; x < targetWidth; x++)
207 {
208 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
209 }
210 }
211 // clear unfilled bottom.
212 for (int y = copyWidth; y < targetHeight; y++)
213 {
214 for (int x = 0; x < targetWidth; x++)
215 {
216 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
217 }
218 }
219
220 return dirty;
221}
222
223template <typename T>
224bool ExpandMatrix(T *target,
225 const GLfloat *value,
226 int targetWidth,
227 int targetHeight,
228 int srcWidth,
229 int srcHeight)
230{
231 bool dirty = false;
232 int copyWidth = std::min(targetWidth, srcWidth);
233 int copyHeight = std::min(targetHeight, srcHeight);
234
235 for (int y = 0; y < copyHeight; y++)
236 {
237 for (int x = 0; x < copyWidth; x++)
238 {
239 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(value[y * srcWidth + x]),
240 &dirty);
241 }
242 }
243 // clear unfilled right side
244 for (int y = 0; y < copyHeight; y++)
245 {
246 for (int x = copyWidth; x < targetWidth; x++)
247 {
248 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
249 }
250 }
251 // clear unfilled bottom.
252 for (int y = copyHeight; y < targetHeight; y++)
253 {
254 for (int x = 0; x < targetWidth; x++)
255 {
256 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
257 }
258 }
259
260 return dirty;
261}
262
Jamie Madill4e31ad52015-10-29 10:32:57 -0400263gl::PrimitiveType GetGeometryShaderTypeFromDrawMode(GLenum drawMode)
264{
265 switch (drawMode)
266 {
267 // Uses the point sprite geometry shader.
268 case GL_POINTS:
269 return gl::PRIMITIVE_POINTS;
270
271 // All line drawing uses the same geometry shader.
272 case GL_LINES:
273 case GL_LINE_STRIP:
274 case GL_LINE_LOOP:
275 return gl::PRIMITIVE_LINES;
276
277 // The triangle fan primitive is emulated with strips in D3D11.
278 case GL_TRIANGLES:
279 case GL_TRIANGLE_FAN:
280 return gl::PRIMITIVE_TRIANGLES;
281
282 // Special case for triangle strips.
283 case GL_TRIANGLE_STRIP:
284 return gl::PRIMITIVE_TRIANGLE_STRIP;
285
286 default:
287 UNREACHABLE();
288 return gl::PRIMITIVE_TYPE_MAX;
289 }
290}
291
Jamie Madillada9ecc2015-08-17 12:53:37 -0400292} // anonymous namespace
293
Jamie Madill28afae52015-11-09 15:07:57 -0500294// D3DUniform Implementation
295
Jamie Madill62d31cb2015-09-11 13:25:51 -0400296D3DUniform::D3DUniform(GLenum typeIn,
297 const std::string &nameIn,
298 unsigned int arraySizeIn,
299 bool defaultBlock)
300 : type(typeIn),
301 name(nameIn),
302 arraySize(arraySizeIn),
303 data(nullptr),
304 dirty(true),
Jamie Madill62d31cb2015-09-11 13:25:51 -0400305 vsRegisterIndex(GL_INVALID_INDEX),
Geoff Lang98c56da2015-09-15 15:45:34 -0400306 psRegisterIndex(GL_INVALID_INDEX),
Jamie Madill62d31cb2015-09-11 13:25:51 -0400307 registerCount(0),
308 registerElement(0)
309{
310 // We use data storage for default block uniforms to cache values that are sent to D3D during
311 // rendering
312 // Uniform blocks/buffers are treated separately by the Renderer (ES3 path only)
313 if (defaultBlock)
314 {
315 size_t bytes = gl::VariableInternalSize(type) * elementCount();
316 data = new uint8_t[bytes];
317 memset(data, 0, bytes);
318
319 // TODO(jmadill): is this correct with non-square matrices?
320 registerCount = gl::VariableRowCount(type) * elementCount();
321 }
322}
323
324D3DUniform::~D3DUniform()
325{
326 SafeDeleteArray(data);
327}
328
329bool D3DUniform::isSampler() const
330{
331 return gl::IsSamplerType(type);
332}
333
334bool D3DUniform::isReferencedByVertexShader() const
335{
336 return vsRegisterIndex != GL_INVALID_INDEX;
337}
338
339bool D3DUniform::isReferencedByFragmentShader() const
340{
341 return psRegisterIndex != GL_INVALID_INDEX;
342}
343
Jamie Madill28afae52015-11-09 15:07:57 -0500344// D3DVarying Implementation
345
346D3DVarying::D3DVarying()
347{
348}
349
350D3DVarying::D3DVarying(const std::string &name,
351 GLenum type,
352 GLsizei size,
353 const std::string &semanticName,
354 unsigned int semanticIndex,
355 unsigned int semanticIndexCount)
356 : name(name),
357 type(type),
358 size(size),
359 semanticName(semanticName),
360 semanticIndex(semanticIndex),
361 semanticIndexCount(semanticIndexCount)
362{
363}
364
365// ProgramD3D Implementation
366
Jamie Madilld3dfda22015-07-06 08:28:49 -0400367ProgramD3D::VertexExecutable::VertexExecutable(const gl::InputLayout &inputLayout,
368 const Signature &signature,
Geoff Lang359ef262015-01-05 14:42:29 -0500369 ShaderExecutableD3D *shaderExecutable)
Jamie Madill334d6152015-10-22 14:00:28 -0400370 : mInputs(inputLayout), mSignature(signature), mShaderExecutable(shaderExecutable)
Brandon Joneseb994362014-09-24 10:27:28 -0700371{
Brandon Joneseb994362014-09-24 10:27:28 -0700372}
373
374ProgramD3D::VertexExecutable::~VertexExecutable()
375{
376 SafeDelete(mShaderExecutable);
377}
378
Jamie Madilld3dfda22015-07-06 08:28:49 -0400379// static
380void ProgramD3D::VertexExecutable::getSignature(RendererD3D *renderer,
381 const gl::InputLayout &inputLayout,
382 Signature *signatureOut)
Brandon Joneseb994362014-09-24 10:27:28 -0700383{
Jamie Madillbd136f92015-08-10 14:51:37 -0400384 signatureOut->resize(inputLayout.size());
Jamie Madilld3dfda22015-07-06 08:28:49 -0400385
386 for (size_t index = 0; index < inputLayout.size(); ++index)
Brandon Joneseb994362014-09-24 10:27:28 -0700387 {
Jamie Madilld3dfda22015-07-06 08:28:49 -0400388 gl::VertexFormatType vertexFormatType = inputLayout[index];
Jamie Madillbd136f92015-08-10 14:51:37 -0400389 bool converted = false;
Jamie Madillf8dd7b12015-08-05 13:50:08 -0400390 if (vertexFormatType != gl::VERTEX_FORMAT_INVALID)
Brandon Joneseb994362014-09-24 10:27:28 -0700391 {
Jamie Madillf8dd7b12015-08-05 13:50:08 -0400392 VertexConversionType conversionType =
393 renderer->getVertexConversionType(vertexFormatType);
Jamie Madillbd136f92015-08-10 14:51:37 -0400394 converted = ((conversionType & VERTEX_CONVERT_GPU) != 0);
Brandon Joneseb994362014-09-24 10:27:28 -0700395 }
Jamie Madillbd136f92015-08-10 14:51:37 -0400396
397 (*signatureOut)[index] = converted;
Brandon Joneseb994362014-09-24 10:27:28 -0700398 }
Brandon Joneseb994362014-09-24 10:27:28 -0700399}
400
Jamie Madilld3dfda22015-07-06 08:28:49 -0400401bool ProgramD3D::VertexExecutable::matchesSignature(const Signature &signature) const
402{
Jamie Madillbd136f92015-08-10 14:51:37 -0400403 size_t limit = std::max(mSignature.size(), signature.size());
404 for (size_t index = 0; index < limit; ++index)
405 {
406 // treat undefined indexes as 'not converted'
407 bool a = index < signature.size() ? signature[index] : false;
408 bool b = index < mSignature.size() ? mSignature[index] : false;
409 if (a != b)
410 return false;
411 }
412
413 return true;
Jamie Madilld3dfda22015-07-06 08:28:49 -0400414}
415
416ProgramD3D::PixelExecutable::PixelExecutable(const std::vector<GLenum> &outputSignature,
417 ShaderExecutableD3D *shaderExecutable)
Jamie Madill334d6152015-10-22 14:00:28 -0400418 : mOutputSignature(outputSignature), mShaderExecutable(shaderExecutable)
Brandon Joneseb994362014-09-24 10:27:28 -0700419{
420}
421
422ProgramD3D::PixelExecutable::~PixelExecutable()
423{
424 SafeDelete(mShaderExecutable);
425}
426
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700427ProgramD3D::Sampler::Sampler() : active(false), logicalTextureUnit(0), textureType(GL_TEXTURE_2D)
428{
429}
430
Geoff Lang7dd2e102014-11-10 15:19:26 -0500431unsigned int ProgramD3D::mCurrentSerial = 1;
432
Jamie Madill5c6b7bf2015-08-17 12:53:35 -0400433ProgramD3D::ProgramD3D(const gl::Program::Data &data, RendererD3D *renderer)
434 : ProgramImpl(data),
Brandon Jonesc9610c52014-08-25 17:02:59 -0700435 mRenderer(renderer),
436 mDynamicHLSL(NULL),
Jamie Madill4e31ad52015-10-29 10:32:57 -0400437 mGeometryExecutables(gl::PRIMITIVE_TYPE_MAX, nullptr),
Brandon Jones44151a92014-09-10 11:32:25 -0700438 mUsesPointSize(false),
Jamie Madill3e14e2b2015-10-29 14:38:53 -0400439 mUsesFlatInterpolation(false),
Brandon Jonesc9610c52014-08-25 17:02:59 -0700440 mVertexUniformStorage(NULL),
Brandon Jones44151a92014-09-10 11:32:25 -0700441 mFragmentUniformStorage(NULL),
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700442 mUsedVertexSamplerRange(0),
443 mUsedPixelSamplerRange(0),
444 mDirtySamplerMapping(true),
Geoff Lang7dd2e102014-11-10 15:19:26 -0500445 mSerial(issueSerial())
Brandon Jonesc9610c52014-08-25 17:02:59 -0700446{
Brandon Joneseb994362014-09-24 10:27:28 -0700447 mDynamicHLSL = new DynamicHLSL(renderer);
Brandon Jonesc9610c52014-08-25 17:02:59 -0700448}
449
450ProgramD3D::~ProgramD3D()
451{
452 reset();
453 SafeDelete(mDynamicHLSL);
454}
455
Brandon Jones44151a92014-09-10 11:32:25 -0700456bool ProgramD3D::usesPointSpriteEmulation() const
457{
458 return mUsesPointSize && mRenderer->getMajorShaderModel() >= 4;
459}
460
Jamie Madill3e14e2b2015-10-29 14:38:53 -0400461bool ProgramD3D::usesGeometryShader(GLenum drawMode) const
Brandon Jones44151a92014-09-10 11:32:25 -0700462{
Jamie Madill3e14e2b2015-10-29 14:38:53 -0400463 if (drawMode != GL_POINTS)
464 {
465 return mUsesFlatInterpolation;
466 }
467
Cooper Partine6664f02015-01-09 16:22:24 -0800468 return usesPointSpriteEmulation() && !usesInstancedPointSpriteEmulation();
469}
470
471bool ProgramD3D::usesInstancedPointSpriteEmulation() const
472{
473 return mRenderer->getWorkarounds().useInstancedPointSpriteEmulation;
Brandon Jones44151a92014-09-10 11:32:25 -0700474}
475
Jamie Madill334d6152015-10-22 14:00:28 -0400476GLint ProgramD3D::getSamplerMapping(gl::SamplerType type,
477 unsigned int samplerIndex,
478 const gl::Caps &caps) const
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700479{
480 GLint logicalTextureUnit = -1;
481
482 switch (type)
483 {
Jamie Madill334d6152015-10-22 14:00:28 -0400484 case gl::SAMPLER_PIXEL:
485 ASSERT(samplerIndex < caps.maxTextureImageUnits);
486 if (samplerIndex < mSamplersPS.size() && mSamplersPS[samplerIndex].active)
487 {
488 logicalTextureUnit = mSamplersPS[samplerIndex].logicalTextureUnit;
489 }
490 break;
491 case gl::SAMPLER_VERTEX:
492 ASSERT(samplerIndex < caps.maxVertexTextureImageUnits);
493 if (samplerIndex < mSamplersVS.size() && mSamplersVS[samplerIndex].active)
494 {
495 logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit;
496 }
497 break;
498 default:
499 UNREACHABLE();
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700500 }
501
Jamie Madill334d6152015-10-22 14:00:28 -0400502 if (logicalTextureUnit >= 0 &&
503 logicalTextureUnit < static_cast<GLint>(caps.maxCombinedTextureImageUnits))
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700504 {
505 return logicalTextureUnit;
506 }
507
508 return -1;
509}
510
511// Returns the texture type for a given Direct3D 9 sampler type and
512// index (0-15 for the pixel shader and 0-3 for the vertex shader).
513GLenum ProgramD3D::getSamplerTextureType(gl::SamplerType type, unsigned int samplerIndex) const
514{
515 switch (type)
516 {
Jamie Madill334d6152015-10-22 14:00:28 -0400517 case gl::SAMPLER_PIXEL:
518 ASSERT(samplerIndex < mSamplersPS.size());
519 ASSERT(mSamplersPS[samplerIndex].active);
520 return mSamplersPS[samplerIndex].textureType;
521 case gl::SAMPLER_VERTEX:
522 ASSERT(samplerIndex < mSamplersVS.size());
523 ASSERT(mSamplersVS[samplerIndex].active);
524 return mSamplersVS[samplerIndex].textureType;
525 default:
526 UNREACHABLE();
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700527 }
528
529 return GL_TEXTURE_2D;
530}
531
532GLint ProgramD3D::getUsedSamplerRange(gl::SamplerType type) const
533{
534 switch (type)
535 {
Jamie Madill334d6152015-10-22 14:00:28 -0400536 case gl::SAMPLER_PIXEL:
537 return mUsedPixelSamplerRange;
538 case gl::SAMPLER_VERTEX:
539 return mUsedVertexSamplerRange;
540 default:
541 UNREACHABLE();
542 return 0;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700543 }
544}
545
546void ProgramD3D::updateSamplerMapping()
547{
548 if (!mDirtySamplerMapping)
549 {
550 return;
551 }
552
553 mDirtySamplerMapping = false;
554
555 // Retrieve sampler uniform values
Jamie Madill62d31cb2015-09-11 13:25:51 -0400556 for (const D3DUniform *d3dUniform : mD3DUniforms)
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700557 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400558 if (!d3dUniform->dirty)
559 continue;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700560
Jamie Madill62d31cb2015-09-11 13:25:51 -0400561 if (!d3dUniform->isSampler())
562 continue;
563
564 int count = d3dUniform->elementCount();
565 const GLint(*v)[4] = reinterpret_cast<const GLint(*)[4]>(d3dUniform->data);
566
567 if (d3dUniform->isReferencedByFragmentShader())
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700568 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400569 unsigned int firstIndex = d3dUniform->psRegisterIndex;
570
571 for (int i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700572 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400573 unsigned int samplerIndex = firstIndex + i;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700574
Jamie Madill62d31cb2015-09-11 13:25:51 -0400575 if (samplerIndex < mSamplersPS.size())
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700576 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400577 ASSERT(mSamplersPS[samplerIndex].active);
578 mSamplersPS[samplerIndex].logicalTextureUnit = v[i][0];
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700579 }
Jamie Madill62d31cb2015-09-11 13:25:51 -0400580 }
581 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700582
Jamie Madill62d31cb2015-09-11 13:25:51 -0400583 if (d3dUniform->isReferencedByVertexShader())
584 {
585 unsigned int firstIndex = d3dUniform->vsRegisterIndex;
586
587 for (int i = 0; i < count; i++)
588 {
589 unsigned int samplerIndex = firstIndex + i;
590
591 if (samplerIndex < mSamplersVS.size())
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700592 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400593 ASSERT(mSamplersVS[samplerIndex].active);
594 mSamplersVS[samplerIndex].logicalTextureUnit = v[i][0];
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700595 }
596 }
597 }
598 }
599}
600
Geoff Lang7dd2e102014-11-10 15:19:26 -0500601LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
Brandon Jones22502d52014-08-29 16:58:36 -0700602{
Jamie Madill62d31cb2015-09-11 13:25:51 -0400603 reset();
604
Jamie Madill334d6152015-10-22 14:00:28 -0400605 DeviceIdentifier binaryDeviceIdentifier = {0};
606 stream->readBytes(reinterpret_cast<unsigned char *>(&binaryDeviceIdentifier),
607 sizeof(DeviceIdentifier));
Austin Kinross137b1512015-06-17 16:14:53 -0700608
609 DeviceIdentifier identifier = mRenderer->getAdapterIdentifier();
610 if (memcmp(&identifier, &binaryDeviceIdentifier, sizeof(DeviceIdentifier)) != 0)
611 {
612 infoLog << "Invalid program binary, device configuration has changed.";
613 return LinkResult(false, gl::Error(GL_NO_ERROR));
614 }
615
Jamie Madill2db1fbb2014-12-03 10:58:55 -0500616 int compileFlags = stream->readInt<int>();
617 if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL)
618 {
Jamie Madillf6113162015-05-07 11:49:21 -0400619 infoLog << "Mismatched compilation flags.";
Jamie Madill2db1fbb2014-12-03 10:58:55 -0500620 return LinkResult(false, gl::Error(GL_NO_ERROR));
621 }
622
Jamie Madill63805b42015-08-25 13:17:39 -0400623 // TODO(jmadill): replace MAX_VERTEX_ATTRIBS
624 for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; ++i)
625 {
626 stream->readInt(&mSemanticIndexes[i]);
627 }
628
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700629 const unsigned int psSamplerCount = stream->readInt<unsigned int>();
630 for (unsigned int i = 0; i < psSamplerCount; ++i)
631 {
632 Sampler sampler;
633 stream->readBool(&sampler.active);
634 stream->readInt(&sampler.logicalTextureUnit);
635 stream->readInt(&sampler.textureType);
636 mSamplersPS.push_back(sampler);
637 }
638 const unsigned int vsSamplerCount = stream->readInt<unsigned int>();
639 for (unsigned int i = 0; i < vsSamplerCount; ++i)
640 {
641 Sampler sampler;
642 stream->readBool(&sampler.active);
643 stream->readInt(&sampler.logicalTextureUnit);
644 stream->readInt(&sampler.textureType);
645 mSamplersVS.push_back(sampler);
646 }
647
648 stream->readInt(&mUsedVertexSamplerRange);
649 stream->readInt(&mUsedPixelSamplerRange);
650
651 const unsigned int uniformCount = stream->readInt<unsigned int>();
652 if (stream->error())
653 {
Jamie Madillf6113162015-05-07 11:49:21 -0400654 infoLog << "Invalid program binary.";
Geoff Lang7dd2e102014-11-10 15:19:26 -0500655 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700656 }
657
Jamie Madill62d31cb2015-09-11 13:25:51 -0400658 const auto &linkedUniforms = mData.getUniforms();
659 ASSERT(mD3DUniforms.empty());
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700660 for (unsigned int uniformIndex = 0; uniformIndex < uniformCount; uniformIndex++)
661 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400662 const gl::LinkedUniform &linkedUniform = linkedUniforms[uniformIndex];
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700663
Jamie Madill62d31cb2015-09-11 13:25:51 -0400664 D3DUniform *d3dUniform =
665 new D3DUniform(linkedUniform.type, linkedUniform.name, linkedUniform.arraySize,
666 linkedUniform.isInDefaultBlock());
667 stream->readInt(&d3dUniform->psRegisterIndex);
668 stream->readInt(&d3dUniform->vsRegisterIndex);
669 stream->readInt(&d3dUniform->registerCount);
670 stream->readInt(&d3dUniform->registerElement);
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700671
Jamie Madill62d31cb2015-09-11 13:25:51 -0400672 mD3DUniforms.push_back(d3dUniform);
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700673 }
674
Jamie Madill4a3c2342015-10-08 12:58:45 -0400675 const unsigned int blockCount = stream->readInt<unsigned int>();
676 if (stream->error())
677 {
678 infoLog << "Invalid program binary.";
679 return LinkResult(false, gl::Error(GL_NO_ERROR));
680 }
681
682 ASSERT(mD3DUniformBlocks.empty());
683 for (unsigned int blockIndex = 0; blockIndex < blockCount; ++blockIndex)
684 {
685 D3DUniformBlock uniformBlock;
686 stream->readInt(&uniformBlock.psRegisterIndex);
687 stream->readInt(&uniformBlock.vsRegisterIndex);
688 mD3DUniformBlocks.push_back(uniformBlock);
689 }
690
Brandon Joneseb994362014-09-24 10:27:28 -0700691 const unsigned int transformFeedbackVaryingCount = stream->readInt<unsigned int>();
Jamie Madill28afae52015-11-09 15:07:57 -0500692 mTransformFeedbackD3DVaryings.resize(transformFeedbackVaryingCount);
Jamie Madill334d6152015-10-22 14:00:28 -0400693 for (unsigned int varyingIndex = 0; varyingIndex < transformFeedbackVaryingCount;
694 varyingIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -0700695 {
Jamie Madill28afae52015-11-09 15:07:57 -0500696 D3DVarying *varying = &mTransformFeedbackD3DVaryings[varyingIndex];
Brandon Joneseb994362014-09-24 10:27:28 -0700697
Jamie Madill28afae52015-11-09 15:07:57 -0500698 stream->readString(&varying->name);
699 stream->readInt(&varying->type);
700 stream->readInt(&varying->size);
701 stream->readString(&varying->semanticName);
702 stream->readInt(&varying->semanticIndex);
703 stream->readInt(&varying->semanticIndexCount);
Brandon Joneseb994362014-09-24 10:27:28 -0700704 }
705
Brandon Jones22502d52014-08-29 16:58:36 -0700706 stream->readString(&mVertexHLSL);
Jamie Madill334d6152015-10-22 14:00:28 -0400707 stream->readBytes(reinterpret_cast<unsigned char *>(&mVertexWorkarounds),
708 sizeof(D3DCompilerWorkarounds));
Brandon Jones22502d52014-08-29 16:58:36 -0700709 stream->readString(&mPixelHLSL);
Jamie Madill334d6152015-10-22 14:00:28 -0400710 stream->readBytes(reinterpret_cast<unsigned char *>(&mPixelWorkarounds),
711 sizeof(D3DCompilerWorkarounds));
Brandon Jones22502d52014-08-29 16:58:36 -0700712 stream->readBool(&mUsesFragDepth);
Brandon Jones44151a92014-09-10 11:32:25 -0700713 stream->readBool(&mUsesPointSize);
Jamie Madill3e14e2b2015-10-29 14:38:53 -0400714 stream->readBool(&mUsesFlatInterpolation);
Brandon Jones22502d52014-08-29 16:58:36 -0700715
716 const size_t pixelShaderKeySize = stream->readInt<unsigned int>();
717 mPixelShaderKey.resize(pixelShaderKeySize);
Jamie Madill334d6152015-10-22 14:00:28 -0400718 for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKeySize;
719 pixelShaderKeyIndex++)
Brandon Jones22502d52014-08-29 16:58:36 -0700720 {
721 stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].type);
722 stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].name);
723 stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].source);
724 stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].outputIndex);
725 }
726
Jamie Madill4e31ad52015-10-29 10:32:57 -0400727 stream->readString(&mGeometryShaderPreamble);
728
Jamie Madill334d6152015-10-22 14:00:28 -0400729 const unsigned char *binary = reinterpret_cast<const unsigned char *>(stream->data());
Brandon Joneseb994362014-09-24 10:27:28 -0700730
731 const unsigned int vertexShaderCount = stream->readInt<unsigned int>();
Jamie Madill334d6152015-10-22 14:00:28 -0400732 for (unsigned int vertexShaderIndex = 0; vertexShaderIndex < vertexShaderCount;
733 vertexShaderIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -0700734 {
Jamie Madilld3dfda22015-07-06 08:28:49 -0400735 size_t inputLayoutSize = stream->readInt<size_t>();
Jamie Madillf8dd7b12015-08-05 13:50:08 -0400736 gl::InputLayout inputLayout(inputLayoutSize, gl::VERTEX_FORMAT_INVALID);
Brandon Joneseb994362014-09-24 10:27:28 -0700737
Jamie Madilld3dfda22015-07-06 08:28:49 -0400738 for (size_t inputIndex = 0; inputIndex < inputLayoutSize; inputIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -0700739 {
Jamie Madillf8dd7b12015-08-05 13:50:08 -0400740 inputLayout[inputIndex] = stream->readInt<gl::VertexFormatType>();
Brandon Joneseb994362014-09-24 10:27:28 -0700741 }
742
Jamie Madill334d6152015-10-22 14:00:28 -0400743 unsigned int vertexShaderSize = stream->readInt<unsigned int>();
Brandon Joneseb994362014-09-24 10:27:28 -0700744 const unsigned char *vertexShaderFunction = binary + stream->offset();
Geoff Langb543aff2014-09-30 14:52:54 -0400745
Jamie Madillada9ecc2015-08-17 12:53:37 -0400746 ShaderExecutableD3D *shaderExecutable = nullptr;
747
748 gl::Error error = mRenderer->loadExecutable(
Jamie Madill28afae52015-11-09 15:07:57 -0500749 vertexShaderFunction, vertexShaderSize, SHADER_VERTEX, mTransformFeedbackD3DVaryings,
Jamie Madillada9ecc2015-08-17 12:53:37 -0400750 (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), &shaderExecutable);
Geoff Langb543aff2014-09-30 14:52:54 -0400751 if (error.isError())
752 {
Geoff Lang7dd2e102014-11-10 15:19:26 -0500753 return LinkResult(false, error);
Geoff Langb543aff2014-09-30 14:52:54 -0400754 }
755
Brandon Joneseb994362014-09-24 10:27:28 -0700756 if (!shaderExecutable)
757 {
Jamie Madillf6113162015-05-07 11:49:21 -0400758 infoLog << "Could not create vertex shader.";
Geoff Lang7dd2e102014-11-10 15:19:26 -0500759 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Joneseb994362014-09-24 10:27:28 -0700760 }
761
762 // generated converted input layout
Jamie Madilld3dfda22015-07-06 08:28:49 -0400763 VertexExecutable::Signature signature;
764 VertexExecutable::getSignature(mRenderer, inputLayout, &signature);
Brandon Joneseb994362014-09-24 10:27:28 -0700765
766 // add new binary
Jamie Madill334d6152015-10-22 14:00:28 -0400767 mVertexExecutables.push_back(
768 new VertexExecutable(inputLayout, signature, shaderExecutable));
Brandon Joneseb994362014-09-24 10:27:28 -0700769
770 stream->skip(vertexShaderSize);
771 }
772
773 const size_t pixelShaderCount = stream->readInt<unsigned int>();
774 for (size_t pixelShaderIndex = 0; pixelShaderIndex < pixelShaderCount; pixelShaderIndex++)
775 {
776 const size_t outputCount = stream->readInt<unsigned int>();
777 std::vector<GLenum> outputs(outputCount);
778 for (size_t outputIndex = 0; outputIndex < outputCount; outputIndex++)
779 {
780 stream->readInt(&outputs[outputIndex]);
781 }
782
Jamie Madill334d6152015-10-22 14:00:28 -0400783 const size_t pixelShaderSize = stream->readInt<unsigned int>();
Brandon Joneseb994362014-09-24 10:27:28 -0700784 const unsigned char *pixelShaderFunction = binary + stream->offset();
Jamie Madillada9ecc2015-08-17 12:53:37 -0400785 ShaderExecutableD3D *shaderExecutable = nullptr;
786
787 gl::Error error = mRenderer->loadExecutable(
Jamie Madill28afae52015-11-09 15:07:57 -0500788 pixelShaderFunction, pixelShaderSize, SHADER_PIXEL, mTransformFeedbackD3DVaryings,
Jamie Madillada9ecc2015-08-17 12:53:37 -0400789 (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), &shaderExecutable);
Geoff Langb543aff2014-09-30 14:52:54 -0400790 if (error.isError())
791 {
Geoff Lang7dd2e102014-11-10 15:19:26 -0500792 return LinkResult(false, error);
Geoff Langb543aff2014-09-30 14:52:54 -0400793 }
Brandon Joneseb994362014-09-24 10:27:28 -0700794
795 if (!shaderExecutable)
796 {
Jamie Madillf6113162015-05-07 11:49:21 -0400797 infoLog << "Could not create pixel shader.";
Geoff Lang7dd2e102014-11-10 15:19:26 -0500798 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Joneseb994362014-09-24 10:27:28 -0700799 }
800
801 // add new binary
802 mPixelExecutables.push_back(new PixelExecutable(outputs, shaderExecutable));
803
804 stream->skip(pixelShaderSize);
805 }
806
Jamie Madill4e31ad52015-10-29 10:32:57 -0400807 for (unsigned int geometryExeIndex = 0; geometryExeIndex < gl::PRIMITIVE_TYPE_MAX;
808 ++geometryExeIndex)
Brandon Joneseb994362014-09-24 10:27:28 -0700809 {
Jamie Madill4e31ad52015-10-29 10:32:57 -0400810 unsigned int geometryShaderSize = stream->readInt<unsigned int>();
811 if (geometryShaderSize == 0)
812 {
813 mGeometryExecutables[geometryExeIndex] = nullptr;
814 continue;
815 }
816
Brandon Joneseb994362014-09-24 10:27:28 -0700817 const unsigned char *geometryShaderFunction = binary + stream->offset();
Jamie Madill4e31ad52015-10-29 10:32:57 -0400818 bool splitAttribs = (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS);
819
Jamie Madill28afae52015-11-09 15:07:57 -0500820 gl::Error error = mRenderer->loadExecutable(
821 geometryShaderFunction, geometryShaderSize, SHADER_GEOMETRY,
822 mTransformFeedbackD3DVaryings, splitAttribs, &mGeometryExecutables[geometryExeIndex]);
Geoff Langb543aff2014-09-30 14:52:54 -0400823 if (error.isError())
824 {
Geoff Lang7dd2e102014-11-10 15:19:26 -0500825 return LinkResult(false, error);
Geoff Langb543aff2014-09-30 14:52:54 -0400826 }
Brandon Joneseb994362014-09-24 10:27:28 -0700827
Jamie Madill4e31ad52015-10-29 10:32:57 -0400828 if (!mGeometryExecutables[geometryExeIndex])
Brandon Joneseb994362014-09-24 10:27:28 -0700829 {
Jamie Madillf6113162015-05-07 11:49:21 -0400830 infoLog << "Could not create geometry shader.";
Geoff Lang7dd2e102014-11-10 15:19:26 -0500831 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Joneseb994362014-09-24 10:27:28 -0700832 }
833 stream->skip(geometryShaderSize);
834 }
835
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700836 initializeUniformStorage();
Jamie Madill437d2662014-12-05 14:23:35 -0500837 initAttributesByLayout();
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700838
Geoff Lang7dd2e102014-11-10 15:19:26 -0500839 return LinkResult(true, gl::Error(GL_NO_ERROR));
Brandon Jones22502d52014-08-29 16:58:36 -0700840}
841
Geoff Langb543aff2014-09-30 14:52:54 -0400842gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream)
Brandon Jones22502d52014-08-29 16:58:36 -0700843{
Austin Kinross137b1512015-06-17 16:14:53 -0700844 // Output the DeviceIdentifier before we output any shader code
Jamie Madill334d6152015-10-22 14:00:28 -0400845 // When we load the binary again later, we can validate the device identifier before trying to
846 // compile any HLSL
Austin Kinross137b1512015-06-17 16:14:53 -0700847 DeviceIdentifier binaryIdentifier = mRenderer->getAdapterIdentifier();
Jamie Madill334d6152015-10-22 14:00:28 -0400848 stream->writeBytes(reinterpret_cast<unsigned char *>(&binaryIdentifier),
849 sizeof(DeviceIdentifier));
Austin Kinross137b1512015-06-17 16:14:53 -0700850
Jamie Madill2db1fbb2014-12-03 10:58:55 -0500851 stream->writeInt(ANGLE_COMPILE_OPTIMIZATION_LEVEL);
852
Jamie Madill63805b42015-08-25 13:17:39 -0400853 // TODO(jmadill): replace MAX_VERTEX_ATTRIBS
854 for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; ++i)
855 {
856 stream->writeInt(mSemanticIndexes[i]);
857 }
858
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700859 stream->writeInt(mSamplersPS.size());
860 for (unsigned int i = 0; i < mSamplersPS.size(); ++i)
861 {
862 stream->writeInt(mSamplersPS[i].active);
863 stream->writeInt(mSamplersPS[i].logicalTextureUnit);
864 stream->writeInt(mSamplersPS[i].textureType);
865 }
866
867 stream->writeInt(mSamplersVS.size());
868 for (unsigned int i = 0; i < mSamplersVS.size(); ++i)
869 {
870 stream->writeInt(mSamplersVS[i].active);
871 stream->writeInt(mSamplersVS[i].logicalTextureUnit);
872 stream->writeInt(mSamplersVS[i].textureType);
873 }
874
875 stream->writeInt(mUsedVertexSamplerRange);
876 stream->writeInt(mUsedPixelSamplerRange);
877
Jamie Madill62d31cb2015-09-11 13:25:51 -0400878 stream->writeInt(mD3DUniforms.size());
Jamie Madill4a3c2342015-10-08 12:58:45 -0400879 for (const D3DUniform *uniform : mD3DUniforms)
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700880 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400881 // Type, name and arraySize are redundant, so aren't stored in the binary.
Jamie Madill4a3c2342015-10-08 12:58:45 -0400882 stream->writeInt(uniform->psRegisterIndex);
883 stream->writeInt(uniform->vsRegisterIndex);
884 stream->writeInt(uniform->registerCount);
885 stream->writeInt(uniform->registerElement);
886 }
887
888 stream->writeInt(mD3DUniformBlocks.size());
889 for (const D3DUniformBlock &uniformBlock : mD3DUniformBlocks)
890 {
891 stream->writeInt(uniformBlock.psRegisterIndex);
892 stream->writeInt(uniformBlock.vsRegisterIndex);
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700893 }
894
Jamie Madill28afae52015-11-09 15:07:57 -0500895 stream->writeInt(mTransformFeedbackD3DVaryings.size());
896 for (size_t i = 0; i < mTransformFeedbackD3DVaryings.size(); i++)
Brandon Joneseb994362014-09-24 10:27:28 -0700897 {
Jamie Madill28afae52015-11-09 15:07:57 -0500898 const D3DVarying &varying = mTransformFeedbackD3DVaryings[i];
Brandon Joneseb994362014-09-24 10:27:28 -0700899
900 stream->writeString(varying.name);
901 stream->writeInt(varying.type);
902 stream->writeInt(varying.size);
903 stream->writeString(varying.semanticName);
904 stream->writeInt(varying.semanticIndex);
905 stream->writeInt(varying.semanticIndexCount);
906 }
907
Brandon Jones22502d52014-08-29 16:58:36 -0700908 stream->writeString(mVertexHLSL);
Jamie Madill334d6152015-10-22 14:00:28 -0400909 stream->writeBytes(reinterpret_cast<unsigned char *>(&mVertexWorkarounds),
910 sizeof(D3DCompilerWorkarounds));
Brandon Jones22502d52014-08-29 16:58:36 -0700911 stream->writeString(mPixelHLSL);
Jamie Madill334d6152015-10-22 14:00:28 -0400912 stream->writeBytes(reinterpret_cast<unsigned char *>(&mPixelWorkarounds),
913 sizeof(D3DCompilerWorkarounds));
Brandon Jones22502d52014-08-29 16:58:36 -0700914 stream->writeInt(mUsesFragDepth);
Brandon Jones44151a92014-09-10 11:32:25 -0700915 stream->writeInt(mUsesPointSize);
Jamie Madill3e14e2b2015-10-29 14:38:53 -0400916 stream->writeInt(mUsesFlatInterpolation);
Brandon Jones22502d52014-08-29 16:58:36 -0700917
Brandon Joneseb994362014-09-24 10:27:28 -0700918 const std::vector<PixelShaderOutputVariable> &pixelShaderKey = mPixelShaderKey;
Brandon Jones22502d52014-08-29 16:58:36 -0700919 stream->writeInt(pixelShaderKey.size());
Jamie Madill334d6152015-10-22 14:00:28 -0400920 for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKey.size();
921 pixelShaderKeyIndex++)
Brandon Jones22502d52014-08-29 16:58:36 -0700922 {
Brandon Joneseb994362014-09-24 10:27:28 -0700923 const PixelShaderOutputVariable &variable = pixelShaderKey[pixelShaderKeyIndex];
Brandon Jones22502d52014-08-29 16:58:36 -0700924 stream->writeInt(variable.type);
925 stream->writeString(variable.name);
926 stream->writeString(variable.source);
927 stream->writeInt(variable.outputIndex);
928 }
929
Jamie Madill4e31ad52015-10-29 10:32:57 -0400930 stream->writeString(mGeometryShaderPreamble);
931
Brandon Joneseb994362014-09-24 10:27:28 -0700932 stream->writeInt(mVertexExecutables.size());
Jamie Madill334d6152015-10-22 14:00:28 -0400933 for (size_t vertexExecutableIndex = 0; vertexExecutableIndex < mVertexExecutables.size();
934 vertexExecutableIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -0700935 {
936 VertexExecutable *vertexExecutable = mVertexExecutables[vertexExecutableIndex];
937
Jamie Madilld3dfda22015-07-06 08:28:49 -0400938 const auto &inputLayout = vertexExecutable->inputs();
939 stream->writeInt(inputLayout.size());
940
941 for (size_t inputIndex = 0; inputIndex < inputLayout.size(); inputIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -0700942 {
Jamie Madilld3dfda22015-07-06 08:28:49 -0400943 stream->writeInt(inputLayout[inputIndex]);
Brandon Joneseb994362014-09-24 10:27:28 -0700944 }
945
946 size_t vertexShaderSize = vertexExecutable->shaderExecutable()->getLength();
947 stream->writeInt(vertexShaderSize);
948
949 const uint8_t *vertexBlob = vertexExecutable->shaderExecutable()->getFunction();
950 stream->writeBytes(vertexBlob, vertexShaderSize);
951 }
952
953 stream->writeInt(mPixelExecutables.size());
Jamie Madill334d6152015-10-22 14:00:28 -0400954 for (size_t pixelExecutableIndex = 0; pixelExecutableIndex < mPixelExecutables.size();
955 pixelExecutableIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -0700956 {
957 PixelExecutable *pixelExecutable = mPixelExecutables[pixelExecutableIndex];
958
959 const std::vector<GLenum> outputs = pixelExecutable->outputSignature();
960 stream->writeInt(outputs.size());
961 for (size_t outputIndex = 0; outputIndex < outputs.size(); outputIndex++)
962 {
963 stream->writeInt(outputs[outputIndex]);
964 }
965
966 size_t pixelShaderSize = pixelExecutable->shaderExecutable()->getLength();
967 stream->writeInt(pixelShaderSize);
968
969 const uint8_t *pixelBlob = pixelExecutable->shaderExecutable()->getFunction();
970 stream->writeBytes(pixelBlob, pixelShaderSize);
971 }
972
Jamie Madill4e31ad52015-10-29 10:32:57 -0400973 for (const ShaderExecutableD3D *geometryExe : mGeometryExecutables)
Brandon Joneseb994362014-09-24 10:27:28 -0700974 {
Jamie Madill4e31ad52015-10-29 10:32:57 -0400975 if (geometryExe == nullptr)
976 {
977 stream->writeInt(0);
978 continue;
979 }
980
981 size_t geometryShaderSize = geometryExe->getLength();
982 stream->writeInt(geometryShaderSize);
983 stream->writeBytes(geometryExe->getFunction(), geometryShaderSize);
Brandon Joneseb994362014-09-24 10:27:28 -0700984 }
985
Geoff Langb543aff2014-09-30 14:52:54 -0400986 return gl::Error(GL_NO_ERROR);
Brandon Jones22502d52014-08-29 16:58:36 -0700987}
988
Jamie Madill334d6152015-10-22 14:00:28 -0400989gl::Error ProgramD3D::getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo,
990 ShaderExecutableD3D **outExecutable)
Brandon Jones22502d52014-08-29 16:58:36 -0700991{
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400992 mPixelShaderOutputFormatCache.clear();
Brandon Joneseb994362014-09-24 10:27:28 -0700993
Jamie Madill85a18042015-03-05 15:41:41 -0500994 const FramebufferD3D *fboD3D = GetImplAs<FramebufferD3D>(fbo);
Jamie Madill334d6152015-10-22 14:00:28 -0400995 const gl::AttachmentList &colorbuffers =
996 fboD3D->getColorAttachmentsForRender(mRenderer->getWorkarounds());
Brandon Joneseb994362014-09-24 10:27:28 -0700997
998 for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment)
999 {
1000 const gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment];
1001
1002 if (colorbuffer)
1003 {
Jamie Madill334d6152015-10-22 14:00:28 -04001004 mPixelShaderOutputFormatCache.push_back(colorbuffer->getBinding() == GL_BACK
1005 ? GL_COLOR_ATTACHMENT0
1006 : colorbuffer->getBinding());
Brandon Joneseb994362014-09-24 10:27:28 -07001007 }
1008 else
1009 {
Geoff Lang7a26a1a2015-03-25 12:29:06 -04001010 mPixelShaderOutputFormatCache.push_back(GL_NONE);
Brandon Joneseb994362014-09-24 10:27:28 -07001011 }
1012 }
1013
Geoff Lang7a26a1a2015-03-25 12:29:06 -04001014 return getPixelExecutableForOutputLayout(mPixelShaderOutputFormatCache, outExecutable, nullptr);
Brandon Joneseb994362014-09-24 10:27:28 -07001015}
1016
Jamie Madill97399232014-12-23 12:31:15 -05001017gl::Error ProgramD3D::getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputSignature,
Geoff Lang359ef262015-01-05 14:42:29 -05001018 ShaderExecutableD3D **outExectuable,
Jamie Madill97399232014-12-23 12:31:15 -05001019 gl::InfoLog *infoLog)
Brandon Joneseb994362014-09-24 10:27:28 -07001020{
1021 for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++)
1022 {
1023 if (mPixelExecutables[executableIndex]->matchesSignature(outputSignature))
1024 {
Geoff Langb543aff2014-09-30 14:52:54 -04001025 *outExectuable = mPixelExecutables[executableIndex]->shaderExecutable();
1026 return gl::Error(GL_NO_ERROR);
Brandon Joneseb994362014-09-24 10:27:28 -07001027 }
1028 }
1029
Jamie Madill334d6152015-10-22 14:00:28 -04001030 std::string finalPixelHLSL = mDynamicHLSL->generatePixelShaderForOutputSignature(
1031 mPixelHLSL, mPixelShaderKey, mUsesFragDepth, outputSignature);
Brandon Jones22502d52014-08-29 16:58:36 -07001032
1033 // Generate new pixel executable
Geoff Lang359ef262015-01-05 14:42:29 -05001034 ShaderExecutableD3D *pixelExecutable = NULL;
Jamie Madill97399232014-12-23 12:31:15 -05001035
1036 gl::InfoLog tempInfoLog;
1037 gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
1038
Jamie Madillada9ecc2015-08-17 12:53:37 -04001039 gl::Error error = mRenderer->compileToExecutable(
Jamie Madill28afae52015-11-09 15:07:57 -05001040 *currentInfoLog, finalPixelHLSL, SHADER_PIXEL, mTransformFeedbackD3DVaryings,
Jamie Madillada9ecc2015-08-17 12:53:37 -04001041 (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), mPixelWorkarounds,
1042 &pixelExecutable);
Geoff Langb543aff2014-09-30 14:52:54 -04001043 if (error.isError())
1044 {
1045 return error;
1046 }
Brandon Joneseb994362014-09-24 10:27:28 -07001047
Jamie Madill97399232014-12-23 12:31:15 -05001048 if (pixelExecutable)
1049 {
1050 mPixelExecutables.push_back(new PixelExecutable(outputSignature, pixelExecutable));
1051 }
1052 else if (!infoLog)
Brandon Joneseb994362014-09-24 10:27:28 -07001053 {
1054 std::vector<char> tempCharBuffer(tempInfoLog.getLength() + 3);
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001055 tempInfoLog.getLog(static_cast<GLsizei>(tempInfoLog.getLength()), NULL, &tempCharBuffer[0]);
Brandon Joneseb994362014-09-24 10:27:28 -07001056 ERR("Error compiling dynamic pixel executable:\n%s\n", &tempCharBuffer[0]);
1057 }
Brandon Jones22502d52014-08-29 16:58:36 -07001058
Geoff Langb543aff2014-09-30 14:52:54 -04001059 *outExectuable = pixelExecutable;
1060 return gl::Error(GL_NO_ERROR);
Brandon Jones22502d52014-08-29 16:58:36 -07001061}
1062
Jamie Madilld3dfda22015-07-06 08:28:49 -04001063gl::Error ProgramD3D::getVertexExecutableForInputLayout(const gl::InputLayout &inputLayout,
Geoff Lang359ef262015-01-05 14:42:29 -05001064 ShaderExecutableD3D **outExectuable,
Jamie Madill97399232014-12-23 12:31:15 -05001065 gl::InfoLog *infoLog)
Brandon Jones22502d52014-08-29 16:58:36 -07001066{
Jamie Madilld3dfda22015-07-06 08:28:49 -04001067 VertexExecutable::getSignature(mRenderer, inputLayout, &mCachedVertexSignature);
Brandon Joneseb994362014-09-24 10:27:28 -07001068
1069 for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++)
1070 {
Jamie Madilld3dfda22015-07-06 08:28:49 -04001071 if (mVertexExecutables[executableIndex]->matchesSignature(mCachedVertexSignature))
Brandon Joneseb994362014-09-24 10:27:28 -07001072 {
Geoff Langb543aff2014-09-30 14:52:54 -04001073 *outExectuable = mVertexExecutables[executableIndex]->shaderExecutable();
1074 return gl::Error(GL_NO_ERROR);
Brandon Joneseb994362014-09-24 10:27:28 -07001075 }
1076 }
1077
Brandon Jones22502d52014-08-29 16:58:36 -07001078 // Generate new dynamic layout with attribute conversions
Jamie Madillc349ec02015-08-21 16:53:12 -04001079 std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout(
1080 mVertexHLSL, inputLayout, mData.getAttributes());
Brandon Jones22502d52014-08-29 16:58:36 -07001081
1082 // Generate new vertex executable
Geoff Lang359ef262015-01-05 14:42:29 -05001083 ShaderExecutableD3D *vertexExecutable = NULL;
Jamie Madill97399232014-12-23 12:31:15 -05001084
1085 gl::InfoLog tempInfoLog;
1086 gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
1087
Jamie Madillada9ecc2015-08-17 12:53:37 -04001088 gl::Error error = mRenderer->compileToExecutable(
Jamie Madill28afae52015-11-09 15:07:57 -05001089 *currentInfoLog, finalVertexHLSL, SHADER_VERTEX, mTransformFeedbackD3DVaryings,
Jamie Madillada9ecc2015-08-17 12:53:37 -04001090 (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), mVertexWorkarounds,
1091 &vertexExecutable);
Geoff Langb543aff2014-09-30 14:52:54 -04001092 if (error.isError())
1093 {
1094 return error;
1095 }
1096
Jamie Madill97399232014-12-23 12:31:15 -05001097 if (vertexExecutable)
Brandon Joneseb994362014-09-24 10:27:28 -07001098 {
Jamie Madill334d6152015-10-22 14:00:28 -04001099 mVertexExecutables.push_back(
1100 new VertexExecutable(inputLayout, mCachedVertexSignature, vertexExecutable));
Brandon Joneseb994362014-09-24 10:27:28 -07001101 }
Jamie Madill97399232014-12-23 12:31:15 -05001102 else if (!infoLog)
1103 {
1104 std::vector<char> tempCharBuffer(tempInfoLog.getLength() + 3);
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001105 tempInfoLog.getLog(static_cast<GLsizei>(tempInfoLog.getLength()), NULL, &tempCharBuffer[0]);
Jamie Madill97399232014-12-23 12:31:15 -05001106 ERR("Error compiling dynamic vertex executable:\n%s\n", &tempCharBuffer[0]);
1107 }
Brandon Jones22502d52014-08-29 16:58:36 -07001108
Geoff Langb543aff2014-09-30 14:52:54 -04001109 *outExectuable = vertexExecutable;
1110 return gl::Error(GL_NO_ERROR);
Brandon Jones22502d52014-08-29 16:58:36 -07001111}
1112
Jamie Madill4e31ad52015-10-29 10:32:57 -04001113gl::Error ProgramD3D::getGeometryExecutableForPrimitiveType(const gl::Data &data,
1114 GLenum drawMode,
1115 ShaderExecutableD3D **outExecutable,
1116 gl::InfoLog *infoLog)
1117{
Jamie Madill3e14e2b2015-10-29 14:38:53 -04001118 if (outExecutable)
1119 {
1120 *outExecutable = nullptr;
1121 }
1122
1123 // We only uses a geometry shader for point sprite emulation, or for fixing the provoking
1124 // vertex problem. Otherwise, return a null shader.
1125 if (drawMode != GL_POINTS && !mUsesFlatInterpolation)
1126 {
1127 return gl::Error(GL_NO_ERROR);
1128 }
1129
Jamie Madill4e31ad52015-10-29 10:32:57 -04001130 gl::PrimitiveType geometryShaderType = GetGeometryShaderTypeFromDrawMode(drawMode);
1131
1132 if (mGeometryExecutables[geometryShaderType] != nullptr)
1133 {
1134 if (outExecutable)
1135 {
1136 *outExecutable = mGeometryExecutables[geometryShaderType];
1137 }
1138 return gl::Error(GL_NO_ERROR);
1139 }
1140
1141 std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL(
1142 geometryShaderType, data, mData, mGeometryShaderPreamble);
1143
1144 gl::InfoLog tempInfoLog;
1145 gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
1146
1147 gl::Error error = mRenderer->compileToExecutable(
Jamie Madill28afae52015-11-09 15:07:57 -05001148 *currentInfoLog, geometryHLSL, SHADER_GEOMETRY, mTransformFeedbackD3DVaryings,
Jamie Madill4e31ad52015-10-29 10:32:57 -04001149 (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), D3DCompilerWorkarounds(),
1150 &mGeometryExecutables[geometryShaderType]);
1151
1152 if (!infoLog && error.isError())
1153 {
1154 std::vector<char> tempCharBuffer(tempInfoLog.getLength() + 3);
1155 tempInfoLog.getLog(static_cast<GLsizei>(tempInfoLog.getLength()), NULL, &tempCharBuffer[0]);
1156 ERR("Error compiling dynamic geometry executable:\n%s\n", &tempCharBuffer[0]);
1157 }
1158
1159 if (outExecutable)
1160 {
1161 *outExecutable = mGeometryExecutables[geometryShaderType];
1162 }
1163 return error;
1164}
1165
1166LinkResult ProgramD3D::compileProgramExecutables(const gl::Data &data, gl::InfoLog &infoLog)
Brandon Jones44151a92014-09-10 11:32:25 -07001167{
Jamie Madill5c6b7bf2015-08-17 12:53:35 -04001168 const gl::InputLayout &defaultInputLayout =
1169 GetDefaultInputLayoutFromShader(mData.getAttachedVertexShader());
Jamie Madille4ea2022015-03-26 20:35:05 +00001170 ShaderExecutableD3D *defaultVertexExecutable = NULL;
Jamie Madill334d6152015-10-22 14:00:28 -04001171 gl::Error error =
1172 getVertexExecutableForInputLayout(defaultInputLayout, &defaultVertexExecutable, &infoLog);
Jamie Madille4ea2022015-03-26 20:35:05 +00001173 if (error.isError())
Austin Kinross434953e2015-02-20 10:49:51 -08001174 {
Jamie Madille4ea2022015-03-26 20:35:05 +00001175 return LinkResult(false, error);
1176 }
Austin Kinross434953e2015-02-20 10:49:51 -08001177
Jamie Madill334d6152015-10-22 14:00:28 -04001178 std::vector<GLenum> defaultPixelOutput = GetDefaultOutputLayoutFromShader(getPixelShaderKey());
Geoff Lang359ef262015-01-05 14:42:29 -05001179 ShaderExecutableD3D *defaultPixelExecutable = NULL;
Jamie Madill334d6152015-10-22 14:00:28 -04001180 error =
1181 getPixelExecutableForOutputLayout(defaultPixelOutput, &defaultPixelExecutable, &infoLog);
Geoff Langb543aff2014-09-30 14:52:54 -04001182 if (error.isError())
1183 {
Geoff Lang7dd2e102014-11-10 15:19:26 -05001184 return LinkResult(false, error);
Geoff Langb543aff2014-09-30 14:52:54 -04001185 }
Brandon Jones44151a92014-09-10 11:32:25 -07001186
Jamie Madill4e31ad52015-10-29 10:32:57 -04001187 // Auto-generate the geometry shader here, if we expect to be using point rendering in D3D11.
Jamie Madill3e14e2b2015-10-29 14:38:53 -04001188 if (usesGeometryShader(GL_POINTS))
Brandon Joneseb994362014-09-24 10:27:28 -07001189 {
Jamie Madill4e31ad52015-10-29 10:32:57 -04001190 getGeometryExecutableForPrimitiveType(data, GL_POINTS, nullptr, &infoLog);
Brandon Joneseb994362014-09-24 10:27:28 -07001191 }
1192
Brandon Jones091540d2014-10-29 11:32:04 -07001193#if ANGLE_SHADER_DEBUG_INFO == ANGLE_ENABLED
Jamie Madillca03b352015-09-02 12:38:13 -04001194 const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(mData.getAttachedVertexShader());
Tibor den Ouden97049c62014-10-06 21:39:16 +02001195 if (usesGeometryShader() && mGeometryExecutable)
1196 {
Jamie Madill334d6152015-10-22 14:00:28 -04001197 // Geometry shaders are currently only used internally, so there is no corresponding shader
1198 // object at the interface level. For now the geometry shader debug info is prepended to
1199 // the vertex shader.
Tibor den Ouden97049c62014-10-06 21:39:16 +02001200 vertexShaderD3D->appendDebugInfo("// GEOMETRY SHADER BEGIN\n\n");
1201 vertexShaderD3D->appendDebugInfo(mGeometryExecutable->getDebugInfo());
1202 vertexShaderD3D->appendDebugInfo("\nGEOMETRY SHADER END\n\n\n");
1203 }
1204
1205 if (defaultVertexExecutable)
1206 {
1207 vertexShaderD3D->appendDebugInfo(defaultVertexExecutable->getDebugInfo());
1208 }
1209
1210 if (defaultPixelExecutable)
1211 {
Jamie Madill76f8fa62015-10-29 10:32:56 -04001212 const ShaderD3D *fragmentShaderD3D =
1213 GetImplAs<ShaderD3D>(mData.getAttachedFragmentShader());
Tibor den Ouden97049c62014-10-06 21:39:16 +02001214 fragmentShaderD3D->appendDebugInfo(defaultPixelExecutable->getDebugInfo());
1215 }
1216#endif
1217
Jamie Madill3e14e2b2015-10-29 14:38:53 -04001218 bool linkSuccess =
1219 (defaultVertexExecutable && defaultPixelExecutable &&
1220 (!usesGeometryShader(GL_POINTS) || mGeometryExecutables[gl::PRIMITIVE_POINTS]));
Geoff Lang7dd2e102014-11-10 15:19:26 -05001221 return LinkResult(linkSuccess, gl::Error(GL_NO_ERROR));
Brandon Jones18bd4102014-09-22 14:21:44 -07001222}
1223
Jamie Madillf5f4ad22015-09-02 18:32:38 +00001224LinkResult ProgramD3D::link(const gl::Data &data, gl::InfoLog &infoLog)
Brandon Jones22502d52014-08-29 16:58:36 -07001225{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001226 reset();
1227
1228 // TODO(jmadill): structures containing samplers
1229 for (const gl::LinkedUniform &linkedUniform : mData.getUniforms())
1230 {
1231 if (linkedUniform.isSampler() && linkedUniform.isField())
1232 {
1233 infoLog << "Structures containing samplers not currently supported in D3D.";
1234 return LinkResult(false, gl::Error(GL_NO_ERROR));
1235 }
1236 }
1237
Jamie Madillf5f4ad22015-09-02 18:32:38 +00001238 const gl::Shader *vertexShader = mData.getAttachedVertexShader();
1239 const gl::Shader *fragmentShader = mData.getAttachedFragmentShader();
Brandon Joneseb994362014-09-24 10:27:28 -07001240
Jamie Madillf5f4ad22015-09-02 18:32:38 +00001241 const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(vertexShader);
1242 const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(fragmentShader);
1243
Jamie Madill63069df2015-09-01 17:26:41 +00001244 mSamplersVS.resize(data.caps->maxVertexTextureImageUnits);
Jamie Madillf5f4ad22015-09-02 18:32:38 +00001245 mSamplersPS.resize(data.caps->maxTextureImageUnits);
Brandon Jones22502d52014-08-29 16:58:36 -07001246
Arun Patole44efa0b2015-03-04 17:11:05 +05301247 vertexShaderD3D->generateWorkarounds(&mVertexWorkarounds);
Jamie Madillf5f4ad22015-09-02 18:32:38 +00001248 fragmentShaderD3D->generateWorkarounds(&mPixelWorkarounds);
1249
Austin Kinross02df7962015-07-01 10:03:42 -07001250 if (mRenderer->getRendererLimitations().noFrontFacingSupport)
1251 {
1252 if (fragmentShaderD3D->usesFrontFacing())
1253 {
1254 infoLog << "The current renderer doesn't support gl_FrontFacing";
1255 return LinkResult(false, gl::Error(GL_NO_ERROR));
1256 }
1257 }
1258
Jamie Madillca03b352015-09-02 12:38:13 -04001259 std::vector<PackedVarying> packedVaryings =
1260 MergeVaryings(*vertexShader, *fragmentShader, mData.getTransformFeedbackVaryingNames());
1261
Brandon Jones22502d52014-08-29 16:58:36 -07001262 // Map the varyings to the register file
Jamie Madill4e31ad52015-10-29 10:32:57 -04001263 unsigned int registerCount = 0;
1264 if (!mDynamicHLSL->packVaryings(*data.caps, infoLog, &packedVaryings,
1265 mData.getTransformFeedbackVaryingNames(), &registerCount))
Brandon Jones22502d52014-08-29 16:58:36 -07001266 {
Geoff Lang7dd2e102014-11-10 15:19:26 -05001267 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Jones22502d52014-08-29 16:58:36 -07001268 }
1269
Jamie Madill28afae52015-11-09 15:07:57 -05001270 std::vector<D3DVarying> d3dVaryings;
Jamie Madill4e31ad52015-10-29 10:32:57 -04001271 if (!mDynamicHLSL->generateShaderLinkHLSL(data, mData, infoLog, registerCount, &mPixelHLSL,
Jamie Madill28afae52015-11-09 15:07:57 -05001272 &mVertexHLSL, packedVaryings, &d3dVaryings,
Jamie Madillca03b352015-09-02 12:38:13 -04001273 &mPixelShaderKey, &mUsesFragDepth))
Brandon Jones22502d52014-08-29 16:58:36 -07001274 {
Geoff Lang7dd2e102014-11-10 15:19:26 -05001275 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Jones22502d52014-08-29 16:58:36 -07001276 }
1277
Brandon Jones44151a92014-09-10 11:32:25 -07001278 mUsesPointSize = vertexShaderD3D->usesPointSize();
1279
Jamie Madill3e14e2b2015-10-29 14:38:53 -04001280 // Cache if we use flat shading
1281 for (const auto &varying : packedVaryings)
1282 {
1283 if (varying.varying->interpolation == sh::INTERPOLATION_FLAT)
1284 {
1285 mUsesFlatInterpolation = true;
1286 break;
1287 }
1288 }
1289
Jamie Madill4e31ad52015-10-29 10:32:57 -04001290 if (mRenderer->getMajorShaderModel() >= 4)
1291 {
1292 mGeometryShaderPreamble = mDynamicHLSL->generateGeometryShaderPreamble(
1293 data, mData, registerCount, packedVaryings);
1294 }
1295
Jamie Madill63805b42015-08-25 13:17:39 -04001296 initSemanticIndex();
Jamie Madill437d2662014-12-05 14:23:35 -05001297
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001298 defineUniformsAndAssignRegisters();
Jamie Madille473dee2015-08-18 14:49:01 -04001299
Jamie Madill28afae52015-11-09 15:07:57 -05001300 gatherTransformFeedbackVaryings(d3dVaryings);
Jamie Madillccdf74b2015-08-18 10:46:12 -04001301
Jamie Madill4e31ad52015-10-29 10:32:57 -04001302 LinkResult result = compileProgramExecutables(data, infoLog);
Jamie Madill31c8c562015-08-19 14:08:03 -04001303 if (result.error.isError() || !result.linkSuccess)
1304 {
1305 infoLog << "Failed to create D3D shaders.";
1306 return result;
1307 }
1308
Jamie Madill4a3c2342015-10-08 12:58:45 -04001309 initUniformBlockInfo();
1310
Geoff Lang7dd2e102014-11-10 15:19:26 -05001311 return LinkResult(true, gl::Error(GL_NO_ERROR));
Brandon Jones22502d52014-08-29 16:58:36 -07001312}
1313
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001314GLboolean ProgramD3D::validate(const gl::Caps & /*caps*/, gl::InfoLog * /*infoLog*/)
Jamie Madill36cfd6a2015-08-18 10:46:20 -04001315{
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001316 // TODO(jmadill): Do something useful here?
1317 return GL_TRUE;
Jamie Madill36cfd6a2015-08-18 10:46:20 -04001318}
1319
Jamie Madill4a3c2342015-10-08 12:58:45 -04001320void ProgramD3D::initUniformBlockInfo()
Jamie Madill62d31cb2015-09-11 13:25:51 -04001321{
1322 const gl::Shader *vertexShader = mData.getAttachedVertexShader();
1323
Jamie Madill62d31cb2015-09-11 13:25:51 -04001324 for (const sh::InterfaceBlock &vertexBlock : vertexShader->getInterfaceBlocks())
1325 {
1326 if (!vertexBlock.staticUse && vertexBlock.layout == sh::BLOCKLAYOUT_PACKED)
1327 continue;
1328
Jamie Madill4a3c2342015-10-08 12:58:45 -04001329 if (mBlockDataSizes.count(vertexBlock.name) > 0)
Jamie Madill62d31cb2015-09-11 13:25:51 -04001330 continue;
1331
Jamie Madill4a3c2342015-10-08 12:58:45 -04001332 size_t dataSize = getUniformBlockInfo(vertexBlock);
1333 mBlockDataSizes[vertexBlock.name] = dataSize;
Jamie Madill62d31cb2015-09-11 13:25:51 -04001334 }
1335
1336 const gl::Shader *fragmentShader = mData.getAttachedFragmentShader();
1337
1338 for (const sh::InterfaceBlock &fragmentBlock : fragmentShader->getInterfaceBlocks())
1339 {
1340 if (!fragmentBlock.staticUse && fragmentBlock.layout == sh::BLOCKLAYOUT_PACKED)
1341 continue;
1342
Jamie Madill4a3c2342015-10-08 12:58:45 -04001343 if (mBlockDataSizes.count(fragmentBlock.name) > 0)
Jamie Madill62d31cb2015-09-11 13:25:51 -04001344 continue;
1345
Jamie Madill4a3c2342015-10-08 12:58:45 -04001346 size_t dataSize = getUniformBlockInfo(fragmentBlock);
1347 mBlockDataSizes[fragmentBlock.name] = dataSize;
Jamie Madill62d31cb2015-09-11 13:25:51 -04001348 }
Jamie Madill4a3c2342015-10-08 12:58:45 -04001349}
Jamie Madill62d31cb2015-09-11 13:25:51 -04001350
Jamie Madill4a3c2342015-10-08 12:58:45 -04001351void ProgramD3D::assignUniformBlockRegisters()
1352{
1353 mD3DUniformBlocks.clear();
Jamie Madill62d31cb2015-09-11 13:25:51 -04001354
1355 // Assign registers and update sizes.
Jamie Madill4a3c2342015-10-08 12:58:45 -04001356 const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(mData.getAttachedVertexShader());
1357 const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(mData.getAttachedFragmentShader());
Jamie Madill62d31cb2015-09-11 13:25:51 -04001358
Jamie Madill4a3c2342015-10-08 12:58:45 -04001359 for (const gl::UniformBlock &uniformBlock : mData.getUniformBlocks())
Jamie Madill62d31cb2015-09-11 13:25:51 -04001360 {
1361 unsigned int uniformBlockElement = uniformBlock.isArray ? uniformBlock.arrayElement : 0;
1362
Jamie Madill4a3c2342015-10-08 12:58:45 -04001363 D3DUniformBlock d3dUniformBlock;
1364
Jamie Madill62d31cb2015-09-11 13:25:51 -04001365 if (uniformBlock.vertexStaticUse)
1366 {
1367 unsigned int baseRegister =
1368 vertexShaderD3D->getInterfaceBlockRegister(uniformBlock.name);
Jamie Madill4a3c2342015-10-08 12:58:45 -04001369 d3dUniformBlock.vsRegisterIndex = baseRegister + uniformBlockElement;
Jamie Madill62d31cb2015-09-11 13:25:51 -04001370 }
1371
1372 if (uniformBlock.fragmentStaticUse)
1373 {
1374 unsigned int baseRegister =
1375 fragmentShaderD3D->getInterfaceBlockRegister(uniformBlock.name);
Jamie Madill4a3c2342015-10-08 12:58:45 -04001376 d3dUniformBlock.psRegisterIndex = baseRegister + uniformBlockElement;
Jamie Madill62d31cb2015-09-11 13:25:51 -04001377 }
1378
Jamie Madill4a3c2342015-10-08 12:58:45 -04001379 mD3DUniformBlocks.push_back(d3dUniformBlock);
Jamie Madill62d31cb2015-09-11 13:25:51 -04001380 }
1381}
1382
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001383void ProgramD3D::initializeUniformStorage()
Brandon Jonesc9610c52014-08-25 17:02:59 -07001384{
1385 // Compute total default block size
Jamie Madill334d6152015-10-22 14:00:28 -04001386 unsigned int vertexRegisters = 0;
Brandon Jonesc9610c52014-08-25 17:02:59 -07001387 unsigned int fragmentRegisters = 0;
Jamie Madill62d31cb2015-09-11 13:25:51 -04001388 for (const D3DUniform *d3dUniform : mD3DUniforms)
Brandon Jonesc9610c52014-08-25 17:02:59 -07001389 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001390 if (!d3dUniform->isSampler())
Brandon Jonesc9610c52014-08-25 17:02:59 -07001391 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001392 if (d3dUniform->isReferencedByVertexShader())
Brandon Jonesc9610c52014-08-25 17:02:59 -07001393 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001394 vertexRegisters = std::max(vertexRegisters,
1395 d3dUniform->vsRegisterIndex + d3dUniform->registerCount);
Brandon Jonesc9610c52014-08-25 17:02:59 -07001396 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04001397 if (d3dUniform->isReferencedByFragmentShader())
Brandon Jonesc9610c52014-08-25 17:02:59 -07001398 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001399 fragmentRegisters = std::max(
1400 fragmentRegisters, d3dUniform->psRegisterIndex + d3dUniform->registerCount);
Brandon Jonesc9610c52014-08-25 17:02:59 -07001401 }
1402 }
1403 }
1404
Jamie Madill334d6152015-10-22 14:00:28 -04001405 mVertexUniformStorage = mRenderer->createUniformStorage(vertexRegisters * 16u);
Brandon Jonesc9610c52014-08-25 17:02:59 -07001406 mFragmentUniformStorage = mRenderer->createUniformStorage(fragmentRegisters * 16u);
1407}
1408
Jamie Madill3e14e2b2015-10-29 14:38:53 -04001409gl::Error ProgramD3D::applyUniforms(GLenum drawMode)
Brandon Jones18bd4102014-09-22 14:21:44 -07001410{
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001411 updateSamplerMapping();
1412
Jamie Madill3e14e2b2015-10-29 14:38:53 -04001413 gl::Error error = mRenderer->applyUniforms(*this, drawMode, mD3DUniforms);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001414 if (error.isError())
1415 {
1416 return error;
1417 }
1418
Jamie Madill62d31cb2015-09-11 13:25:51 -04001419 for (D3DUniform *d3dUniform : mD3DUniforms)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001420 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001421 d3dUniform->dirty = false;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001422 }
1423
1424 return gl::Error(GL_NO_ERROR);
Brandon Jones18bd4102014-09-22 14:21:44 -07001425}
1426
Jamie Madilld1fe1642015-08-21 16:26:04 -04001427gl::Error ProgramD3D::applyUniformBuffers(const gl::Data &data)
Brandon Jones18bd4102014-09-22 14:21:44 -07001428{
Jamie Madill4a3c2342015-10-08 12:58:45 -04001429 if (mData.getUniformBlocks().empty())
1430 {
1431 return gl::Error(GL_NO_ERROR);
1432 }
1433
1434 // Lazy init.
1435 if (mD3DUniformBlocks.empty())
1436 {
1437 assignUniformBlockRegisters();
1438 }
1439
Jamie Madill03260fa2015-06-22 13:57:22 -04001440 mVertexUBOCache.clear();
1441 mFragmentUBOCache.clear();
Brandon Jones18bd4102014-09-22 14:21:44 -07001442
1443 const unsigned int reservedBuffersInVS = mRenderer->getReservedVertexUniformBuffers();
1444 const unsigned int reservedBuffersInFS = mRenderer->getReservedFragmentUniformBuffers();
1445
Jamie Madill4a3c2342015-10-08 12:58:45 -04001446 for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < mD3DUniformBlocks.size();
Jamie Madill62d31cb2015-09-11 13:25:51 -04001447 uniformBlockIndex++)
Brandon Jones18bd4102014-09-22 14:21:44 -07001448 {
Jamie Madill4a3c2342015-10-08 12:58:45 -04001449 const D3DUniformBlock &uniformBlock = mD3DUniformBlocks[uniformBlockIndex];
1450 GLuint blockBinding = mData.getUniformBlockBinding(uniformBlockIndex);
Brandon Jones18bd4102014-09-22 14:21:44 -07001451
Brandon Jones18bd4102014-09-22 14:21:44 -07001452 // Unnecessary to apply an unreferenced standard or shared UBO
Jamie Madill4a3c2342015-10-08 12:58:45 -04001453 if (!uniformBlock.vertexStaticUse() && !uniformBlock.fragmentStaticUse())
Brandon Jones18bd4102014-09-22 14:21:44 -07001454 {
1455 continue;
1456 }
1457
Jamie Madill4a3c2342015-10-08 12:58:45 -04001458 if (uniformBlock.vertexStaticUse())
Brandon Jones18bd4102014-09-22 14:21:44 -07001459 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001460 unsigned int registerIndex = uniformBlock.vsRegisterIndex - reservedBuffersInVS;
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00001461 ASSERT(registerIndex < data.caps->maxVertexUniformBlocks);
Jamie Madill03260fa2015-06-22 13:57:22 -04001462
Jamie Madill969194d2015-07-20 14:36:56 -04001463 if (mVertexUBOCache.size() <= registerIndex)
Jamie Madill03260fa2015-06-22 13:57:22 -04001464 {
1465 mVertexUBOCache.resize(registerIndex + 1, -1);
1466 }
1467
1468 ASSERT(mVertexUBOCache[registerIndex] == -1);
1469 mVertexUBOCache[registerIndex] = blockBinding;
Brandon Jones18bd4102014-09-22 14:21:44 -07001470 }
1471
Jamie Madill4a3c2342015-10-08 12:58:45 -04001472 if (uniformBlock.fragmentStaticUse())
Brandon Jones18bd4102014-09-22 14:21:44 -07001473 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001474 unsigned int registerIndex = uniformBlock.psRegisterIndex - reservedBuffersInFS;
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00001475 ASSERT(registerIndex < data.caps->maxFragmentUniformBlocks);
Jamie Madill03260fa2015-06-22 13:57:22 -04001476
1477 if (mFragmentUBOCache.size() <= registerIndex)
1478 {
1479 mFragmentUBOCache.resize(registerIndex + 1, -1);
1480 }
1481
1482 ASSERT(mFragmentUBOCache[registerIndex] == -1);
1483 mFragmentUBOCache[registerIndex] = blockBinding;
Brandon Jones18bd4102014-09-22 14:21:44 -07001484 }
1485 }
1486
Jamie Madill03260fa2015-06-22 13:57:22 -04001487 return mRenderer->setUniformBuffers(data, mVertexUBOCache, mFragmentUBOCache);
Brandon Jones18bd4102014-09-22 14:21:44 -07001488}
1489
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001490void ProgramD3D::dirtyAllUniforms()
Brandon Jones18bd4102014-09-22 14:21:44 -07001491{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001492 for (D3DUniform *d3dUniform : mD3DUniforms)
Brandon Jones18bd4102014-09-22 14:21:44 -07001493 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001494 d3dUniform->dirty = true;
Brandon Jones18bd4102014-09-22 14:21:44 -07001495 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001496}
1497
Jamie Madill334d6152015-10-22 14:00:28 -04001498void ProgramD3D::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001499{
1500 setUniform(location, count, v, GL_FLOAT);
1501}
1502
1503void ProgramD3D::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
1504{
1505 setUniform(location, count, v, GL_FLOAT_VEC2);
1506}
1507
1508void ProgramD3D::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
1509{
1510 setUniform(location, count, v, GL_FLOAT_VEC3);
1511}
1512
1513void ProgramD3D::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
1514{
1515 setUniform(location, count, v, GL_FLOAT_VEC4);
1516}
1517
Jamie Madill334d6152015-10-22 14:00:28 -04001518void ProgramD3D::setUniformMatrix2fv(GLint location,
1519 GLsizei count,
1520 GLboolean transpose,
1521 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001522{
1523 setUniformMatrixfv<2, 2>(location, count, transpose, value, GL_FLOAT_MAT2);
1524}
1525
Jamie Madill334d6152015-10-22 14:00:28 -04001526void ProgramD3D::setUniformMatrix3fv(GLint location,
1527 GLsizei count,
1528 GLboolean transpose,
1529 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001530{
1531 setUniformMatrixfv<3, 3>(location, count, transpose, value, GL_FLOAT_MAT3);
1532}
1533
Jamie Madill334d6152015-10-22 14:00:28 -04001534void ProgramD3D::setUniformMatrix4fv(GLint location,
1535 GLsizei count,
1536 GLboolean transpose,
1537 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001538{
1539 setUniformMatrixfv<4, 4>(location, count, transpose, value, GL_FLOAT_MAT4);
1540}
1541
Jamie Madill334d6152015-10-22 14:00:28 -04001542void ProgramD3D::setUniformMatrix2x3fv(GLint location,
1543 GLsizei count,
1544 GLboolean transpose,
1545 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001546{
1547 setUniformMatrixfv<2, 3>(location, count, transpose, value, GL_FLOAT_MAT2x3);
1548}
1549
Jamie Madill334d6152015-10-22 14:00:28 -04001550void ProgramD3D::setUniformMatrix3x2fv(GLint location,
1551 GLsizei count,
1552 GLboolean transpose,
1553 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001554{
1555 setUniformMatrixfv<3, 2>(location, count, transpose, value, GL_FLOAT_MAT3x2);
1556}
1557
Jamie Madill334d6152015-10-22 14:00:28 -04001558void ProgramD3D::setUniformMatrix2x4fv(GLint location,
1559 GLsizei count,
1560 GLboolean transpose,
1561 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001562{
1563 setUniformMatrixfv<2, 4>(location, count, transpose, value, GL_FLOAT_MAT2x4);
1564}
1565
Jamie Madill334d6152015-10-22 14:00:28 -04001566void ProgramD3D::setUniformMatrix4x2fv(GLint location,
1567 GLsizei count,
1568 GLboolean transpose,
1569 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001570{
1571 setUniformMatrixfv<4, 2>(location, count, transpose, value, GL_FLOAT_MAT4x2);
1572}
1573
Jamie Madill334d6152015-10-22 14:00:28 -04001574void ProgramD3D::setUniformMatrix3x4fv(GLint location,
1575 GLsizei count,
1576 GLboolean transpose,
1577 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001578{
1579 setUniformMatrixfv<3, 4>(location, count, transpose, value, GL_FLOAT_MAT3x4);
1580}
1581
Jamie Madill334d6152015-10-22 14:00:28 -04001582void ProgramD3D::setUniformMatrix4x3fv(GLint location,
1583 GLsizei count,
1584 GLboolean transpose,
1585 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001586{
1587 setUniformMatrixfv<4, 3>(location, count, transpose, value, GL_FLOAT_MAT4x3);
1588}
1589
1590void ProgramD3D::setUniform1iv(GLint location, GLsizei count, const GLint *v)
1591{
1592 setUniform(location, count, v, GL_INT);
1593}
1594
1595void ProgramD3D::setUniform2iv(GLint location, GLsizei count, const GLint *v)
1596{
1597 setUniform(location, count, v, GL_INT_VEC2);
1598}
1599
1600void ProgramD3D::setUniform3iv(GLint location, GLsizei count, const GLint *v)
1601{
1602 setUniform(location, count, v, GL_INT_VEC3);
1603}
1604
1605void ProgramD3D::setUniform4iv(GLint location, GLsizei count, const GLint *v)
1606{
1607 setUniform(location, count, v, GL_INT_VEC4);
1608}
1609
1610void ProgramD3D::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
1611{
1612 setUniform(location, count, v, GL_UNSIGNED_INT);
1613}
1614
1615void ProgramD3D::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
1616{
1617 setUniform(location, count, v, GL_UNSIGNED_INT_VEC2);
1618}
1619
1620void ProgramD3D::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
1621{
1622 setUniform(location, count, v, GL_UNSIGNED_INT_VEC3);
1623}
1624
1625void ProgramD3D::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
1626{
1627 setUniform(location, count, v, GL_UNSIGNED_INT_VEC4);
1628}
1629
Jamie Madill4a3c2342015-10-08 12:58:45 -04001630void ProgramD3D::setUniformBlockBinding(GLuint /*uniformBlockIndex*/,
1631 GLuint /*uniformBlockBinding*/)
Geoff Lang5d124a62015-09-15 13:03:27 -04001632{
1633}
1634
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001635void ProgramD3D::defineUniformsAndAssignRegisters()
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001636{
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001637 D3DUniformMap uniformMap;
Jamie Madill334d6152015-10-22 14:00:28 -04001638 const gl::Shader *vertexShader = mData.getAttachedVertexShader();
Jamie Madill62d31cb2015-09-11 13:25:51 -04001639 for (const sh::Uniform &vertexUniform : vertexShader->getUniforms())
Jamie Madillfb536032015-09-11 13:19:49 -04001640
Jamie Madilla2eb02c2015-09-11 12:31:41 +00001641 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001642 if (vertexUniform.staticUse)
Jamie Madillfb536032015-09-11 13:19:49 -04001643 {
Jamie Madill91445bc2015-09-23 16:47:53 -04001644 defineUniformBase(vertexShader, vertexUniform, &uniformMap);
Jamie Madillfb536032015-09-11 13:19:49 -04001645 }
1646 }
1647
Jamie Madill334d6152015-10-22 14:00:28 -04001648 const gl::Shader *fragmentShader = mData.getAttachedFragmentShader();
Jamie Madill62d31cb2015-09-11 13:25:51 -04001649 for (const sh::Uniform &fragmentUniform : fragmentShader->getUniforms())
Jamie Madillfb536032015-09-11 13:19:49 -04001650 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001651 if (fragmentUniform.staticUse)
Jamie Madillfb536032015-09-11 13:19:49 -04001652 {
Jamie Madill91445bc2015-09-23 16:47:53 -04001653 defineUniformBase(fragmentShader, fragmentUniform, &uniformMap);
Jamie Madillfb536032015-09-11 13:19:49 -04001654 }
1655 }
1656
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001657 // Initialize the D3DUniform list to mirror the indexing of the GL layer.
1658 for (const gl::LinkedUniform &glUniform : mData.getUniforms())
1659 {
1660 if (!glUniform.isInDefaultBlock())
1661 continue;
1662
1663 auto mapEntry = uniformMap.find(glUniform.name);
1664 ASSERT(mapEntry != uniformMap.end());
1665 mD3DUniforms.push_back(mapEntry->second);
1666 }
1667
Jamie Madill62d31cb2015-09-11 13:25:51 -04001668 assignAllSamplerRegisters();
Jamie Madillfb536032015-09-11 13:19:49 -04001669 initializeUniformStorage();
Jamie Madillfb536032015-09-11 13:19:49 -04001670}
1671
Jamie Madill91445bc2015-09-23 16:47:53 -04001672void ProgramD3D::defineUniformBase(const gl::Shader *shader,
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001673 const sh::Uniform &uniform,
1674 D3DUniformMap *uniformMap)
Jamie Madillfb536032015-09-11 13:19:49 -04001675{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001676 if (uniform.isBuiltIn())
Jamie Madillfb536032015-09-11 13:19:49 -04001677 {
Jamie Madill91445bc2015-09-23 16:47:53 -04001678 defineUniform(shader->getType(), uniform, uniform.name, nullptr, uniformMap);
Jamie Madill55def582015-05-04 11:24:57 -04001679 return;
1680 }
1681
Jamie Madill91445bc2015-09-23 16:47:53 -04001682 const ShaderD3D *shaderD3D = GetImplAs<ShaderD3D>(shader);
1683
1684 unsigned int startRegister = shaderD3D->getUniformRegister(uniform.name);
1685 ShShaderOutput outputType = shaderD3D->getCompilerOutputType();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001686 sh::HLSLBlockEncoder encoder(sh::HLSLBlockEncoder::GetStrategyFor(outputType));
Jamie Madill62d31cb2015-09-11 13:25:51 -04001687 encoder.skipRegisters(startRegister);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001688
Jamie Madill91445bc2015-09-23 16:47:53 -04001689 defineUniform(shader->getType(), uniform, uniform.name, &encoder, uniformMap);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001690}
1691
Jamie Madill62d31cb2015-09-11 13:25:51 -04001692D3DUniform *ProgramD3D::getD3DUniformByName(const std::string &name)
1693{
1694 for (D3DUniform *d3dUniform : mD3DUniforms)
1695 {
1696 if (d3dUniform->name == name)
1697 {
1698 return d3dUniform;
1699 }
1700 }
1701
1702 return nullptr;
1703}
1704
Jamie Madill91445bc2015-09-23 16:47:53 -04001705void ProgramD3D::defineUniform(GLenum shaderType,
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001706 const sh::ShaderVariable &uniform,
1707 const std::string &fullName,
1708 sh::HLSLBlockEncoder *encoder,
1709 D3DUniformMap *uniformMap)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001710{
1711 if (uniform.isStruct())
1712 {
1713 for (unsigned int elementIndex = 0; elementIndex < uniform.elementCount(); elementIndex++)
1714 {
1715 const std::string &elementString = (uniform.isArray() ? ArrayString(elementIndex) : "");
1716
Jamie Madill55def582015-05-04 11:24:57 -04001717 if (encoder)
1718 encoder->enterAggregateType();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001719
1720 for (size_t fieldIndex = 0; fieldIndex < uniform.fields.size(); fieldIndex++)
1721 {
Jamie Madill334d6152015-10-22 14:00:28 -04001722 const sh::ShaderVariable &field = uniform.fields[fieldIndex];
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001723 const std::string &fieldFullName = (fullName + elementString + "." + field.name);
1724
Jamie Madill91445bc2015-09-23 16:47:53 -04001725 defineUniform(shaderType, field, fieldFullName, encoder, uniformMap);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001726 }
1727
Jamie Madill55def582015-05-04 11:24:57 -04001728 if (encoder)
1729 encoder->exitAggregateType();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001730 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04001731 return;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001732 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04001733
1734 // Not a struct. Arrays are treated as aggregate types.
1735 if (uniform.isArray() && encoder)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001736 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001737 encoder->enterAggregateType();
1738 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001739
Jamie Madill62d31cb2015-09-11 13:25:51 -04001740 // Advance the uniform offset, to track registers allocation for structs
1741 sh::BlockMemberInfo blockInfo =
1742 encoder ? encoder->encodeType(uniform.type, uniform.arraySize, false)
1743 : sh::BlockMemberInfo::getDefaultBlockInfo();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001744
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001745 auto uniformMapEntry = uniformMap->find(fullName);
1746 D3DUniform *d3dUniform = nullptr;
Jamie Madill2857f482015-02-09 15:35:29 -05001747
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001748 if (uniformMapEntry != uniformMap->end())
Jamie Madill62d31cb2015-09-11 13:25:51 -04001749 {
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001750 d3dUniform = uniformMapEntry->second;
1751 }
1752 else
1753 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001754 d3dUniform = new D3DUniform(uniform.type, fullName, uniform.arraySize, true);
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001755 (*uniformMap)[fullName] = d3dUniform;
Jamie Madill62d31cb2015-09-11 13:25:51 -04001756 }
1757
1758 if (encoder)
1759 {
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001760 d3dUniform->registerElement =
1761 static_cast<unsigned int>(sh::HLSLBlockEncoder::getBlockRegisterElement(blockInfo));
Jamie Madill62d31cb2015-09-11 13:25:51 -04001762 unsigned int reg =
1763 static_cast<unsigned int>(sh::HLSLBlockEncoder::getBlockRegister(blockInfo));
Jamie Madill91445bc2015-09-23 16:47:53 -04001764 if (shaderType == GL_FRAGMENT_SHADER)
Jamie Madill62d31cb2015-09-11 13:25:51 -04001765 {
1766 d3dUniform->psRegisterIndex = reg;
1767 }
Jamie Madill91445bc2015-09-23 16:47:53 -04001768 else
Jamie Madill62d31cb2015-09-11 13:25:51 -04001769 {
Jamie Madill91445bc2015-09-23 16:47:53 -04001770 ASSERT(shaderType == GL_VERTEX_SHADER);
Jamie Madill62d31cb2015-09-11 13:25:51 -04001771 d3dUniform->vsRegisterIndex = reg;
1772 }
Jamie Madillfb536032015-09-11 13:19:49 -04001773
1774 // Arrays are treated as aggregate types
Jamie Madill62d31cb2015-09-11 13:25:51 -04001775 if (uniform.isArray())
Jamie Madillfb536032015-09-11 13:19:49 -04001776 {
1777 encoder->exitAggregateType();
1778 }
1779 }
1780}
1781
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001782template <typename T>
Jamie Madill334d6152015-10-22 14:00:28 -04001783static inline void SetIfDirty(T *dest, const T &source, bool *dirtyFlag)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001784{
1785 ASSERT(dest != NULL);
1786 ASSERT(dirtyFlag != NULL);
1787
1788 *dirtyFlag = *dirtyFlag || (memcmp(dest, &source, sizeof(T)) != 0);
Jamie Madill334d6152015-10-22 14:00:28 -04001789 *dest = source;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001790}
1791
1792template <typename T>
Jamie Madill62d31cb2015-09-11 13:25:51 -04001793void ProgramD3D::setUniform(GLint location, GLsizei countIn, const T *v, GLenum targetUniformType)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001794{
Jamie Madill334d6152015-10-22 14:00:28 -04001795 const int components = gl::VariableComponentCount(targetUniformType);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001796 const GLenum targetBoolType = gl::VariableBoolVectorType(targetUniformType);
1797
Jamie Madill62d31cb2015-09-11 13:25:51 -04001798 D3DUniform *targetUniform = getD3DUniformFromLocation(location);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001799
Jamie Madill62d31cb2015-09-11 13:25:51 -04001800 unsigned int elementCount = targetUniform->elementCount();
1801 unsigned int arrayElement = mData.getUniformLocations()[location].element;
1802 unsigned int count = std::min(elementCount - arrayElement, static_cast<unsigned int>(countIn));
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001803
1804 if (targetUniform->type == targetUniformType)
1805 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001806 T *target = reinterpret_cast<T *>(targetUniform->data) + arrayElement * 4;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001807
Jamie Madill62d31cb2015-09-11 13:25:51 -04001808 for (unsigned int i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001809 {
Jamie Madill334d6152015-10-22 14:00:28 -04001810 T *dest = target + (i * 4);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001811 const T *source = v + (i * components);
1812
1813 for (int c = 0; c < components; c++)
1814 {
1815 SetIfDirty(dest + c, source[c], &targetUniform->dirty);
1816 }
1817 for (int c = components; c < 4; c++)
1818 {
1819 SetIfDirty(dest + c, T(0), &targetUniform->dirty);
1820 }
1821 }
1822 }
1823 else if (targetUniform->type == targetBoolType)
1824 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001825 GLint *boolParams = reinterpret_cast<GLint *>(targetUniform->data) + arrayElement * 4;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001826
Jamie Madill62d31cb2015-09-11 13:25:51 -04001827 for (unsigned int i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001828 {
Jamie Madill334d6152015-10-22 14:00:28 -04001829 GLint *dest = boolParams + (i * 4);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001830 const T *source = v + (i * components);
1831
1832 for (int c = 0; c < components; c++)
1833 {
Jamie Madill334d6152015-10-22 14:00:28 -04001834 SetIfDirty(dest + c, (source[c] == static_cast<T>(0)) ? GL_FALSE : GL_TRUE,
1835 &targetUniform->dirty);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001836 }
1837 for (int c = components; c < 4; c++)
1838 {
1839 SetIfDirty(dest + c, GL_FALSE, &targetUniform->dirty);
1840 }
1841 }
1842 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04001843 else if (targetUniform->isSampler())
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001844 {
1845 ASSERT(targetUniformType == GL_INT);
1846
Jamie Madill62d31cb2015-09-11 13:25:51 -04001847 GLint *target = reinterpret_cast<GLint *>(targetUniform->data) + arrayElement * 4;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001848
1849 bool wasDirty = targetUniform->dirty;
1850
Jamie Madill62d31cb2015-09-11 13:25:51 -04001851 for (unsigned int i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001852 {
Jamie Madill334d6152015-10-22 14:00:28 -04001853 GLint *dest = target + (i * 4);
1854 const GLint *source = reinterpret_cast<const GLint *>(v) + (i * components);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001855
1856 SetIfDirty(dest + 0, source[0], &targetUniform->dirty);
1857 SetIfDirty(dest + 1, 0, &targetUniform->dirty);
1858 SetIfDirty(dest + 2, 0, &targetUniform->dirty);
1859 SetIfDirty(dest + 3, 0, &targetUniform->dirty);
1860 }
1861
1862 if (!wasDirty && targetUniform->dirty)
1863 {
1864 mDirtySamplerMapping = true;
1865 }
Brandon Jones18bd4102014-09-22 14:21:44 -07001866 }
Jamie Madill334d6152015-10-22 14:00:28 -04001867 else
1868 UNREACHABLE();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001869}
1870
1871template <int cols, int rows>
Jamie Madill62d31cb2015-09-11 13:25:51 -04001872void ProgramD3D::setUniformMatrixfv(GLint location,
1873 GLsizei countIn,
1874 GLboolean transpose,
1875 const GLfloat *value,
1876 GLenum targetUniformType)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001877{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001878 D3DUniform *targetUniform = getD3DUniformFromLocation(location);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001879
Jamie Madill62d31cb2015-09-11 13:25:51 -04001880 unsigned int elementCount = targetUniform->elementCount();
1881 unsigned int arrayElement = mData.getUniformLocations()[location].element;
1882 unsigned int count = std::min(elementCount - arrayElement, static_cast<unsigned int>(countIn));
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001883
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001884 const unsigned int targetMatrixStride = (4 * rows);
Jamie Madill62d31cb2015-09-11 13:25:51 -04001885 GLfloat *target =
1886 (GLfloat *)(targetUniform->data + arrayElement * sizeof(GLfloat) * targetMatrixStride);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001887
Jamie Madill62d31cb2015-09-11 13:25:51 -04001888 for (unsigned int i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001889 {
1890 // Internally store matrices as transposed versions to accomodate HLSL matrix indexing
1891 if (transpose == GL_FALSE)
1892 {
Jamie Madill334d6152015-10-22 14:00:28 -04001893 targetUniform->dirty = TransposeMatrix<GLfloat>(target, value, 4, rows, rows, cols) ||
1894 targetUniform->dirty;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001895 }
1896 else
1897 {
Jamie Madill334d6152015-10-22 14:00:28 -04001898 targetUniform->dirty =
1899 ExpandMatrix<GLfloat>(target, value, 4, rows, cols, rows) || targetUniform->dirty;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001900 }
1901 target += targetMatrixStride;
1902 value += cols * rows;
1903 }
1904}
1905
Jamie Madill4a3c2342015-10-08 12:58:45 -04001906size_t ProgramD3D::getUniformBlockInfo(const sh::InterfaceBlock &interfaceBlock)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001907{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001908 ASSERT(interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001909
Jamie Madill62d31cb2015-09-11 13:25:51 -04001910 // define member uniforms
1911 sh::Std140BlockEncoder std140Encoder;
1912 sh::HLSLBlockEncoder hlslEncoder(sh::HLSLBlockEncoder::ENCODE_PACKED);
1913 sh::BlockLayoutEncoder *encoder = nullptr;
1914
1915 if (interfaceBlock.layout == sh::BLOCKLAYOUT_STANDARD)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001916 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001917 encoder = &std140Encoder;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001918 }
1919 else
1920 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001921 encoder = &hlslEncoder;
Jamie Madill61b8dd92015-09-09 19:04:04 +00001922 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04001923
1924 GetUniformBlockInfo(interfaceBlock.fields, "", encoder, interfaceBlock.isRowMajorLayout,
Jamie Madill4a3c2342015-10-08 12:58:45 -04001925 &mBlockInfo);
Jamie Madill62d31cb2015-09-11 13:25:51 -04001926
1927 return encoder->getBlockSize();
Jamie Madill61b8dd92015-09-09 19:04:04 +00001928}
1929
Jamie Madill62d31cb2015-09-11 13:25:51 -04001930void ProgramD3D::assignAllSamplerRegisters()
Jamie Madilla2eb02c2015-09-11 12:31:41 +00001931{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001932 for (const D3DUniform *d3dUniform : mD3DUniforms)
Jamie Madilla2eb02c2015-09-11 12:31:41 +00001933 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001934 if (d3dUniform->isSampler())
Jamie Madillfb536032015-09-11 13:19:49 -04001935 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001936 assignSamplerRegisters(d3dUniform);
Jamie Madillfb536032015-09-11 13:19:49 -04001937 }
Jamie Madilla2eb02c2015-09-11 12:31:41 +00001938 }
1939}
1940
Jamie Madill62d31cb2015-09-11 13:25:51 -04001941void ProgramD3D::assignSamplerRegisters(const D3DUniform *d3dUniform)
Jamie Madillfb536032015-09-11 13:19:49 -04001942{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001943 ASSERT(d3dUniform->isSampler());
1944 ASSERT(d3dUniform->vsRegisterIndex != GL_INVALID_INDEX ||
1945 d3dUniform->psRegisterIndex != GL_INVALID_INDEX);
Jamie Madillfb536032015-09-11 13:19:49 -04001946
Jamie Madill62d31cb2015-09-11 13:25:51 -04001947 if (d3dUniform->vsRegisterIndex != GL_INVALID_INDEX)
Jamie Madillfb536032015-09-11 13:19:49 -04001948 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001949 AssignSamplers(d3dUniform->vsRegisterIndex, d3dUniform->type, d3dUniform->arraySize,
1950 mSamplersVS, &mUsedVertexSamplerRange);
Jamie Madillfb536032015-09-11 13:19:49 -04001951 }
1952
Jamie Madill62d31cb2015-09-11 13:25:51 -04001953 if (d3dUniform->psRegisterIndex != GL_INVALID_INDEX)
Jamie Madillfb536032015-09-11 13:19:49 -04001954 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001955 AssignSamplers(d3dUniform->psRegisterIndex, d3dUniform->type, d3dUniform->arraySize,
1956 mSamplersPS, &mUsedPixelSamplerRange);
Jamie Madillfb536032015-09-11 13:19:49 -04001957 }
1958}
1959
Jamie Madill62d31cb2015-09-11 13:25:51 -04001960// static
1961void ProgramD3D::AssignSamplers(unsigned int startSamplerIndex,
Jamie Madilld3dfda22015-07-06 08:28:49 -04001962 GLenum samplerType,
1963 unsigned int samplerCount,
1964 std::vector<Sampler> &outSamplers,
1965 GLuint *outUsedRange)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001966{
1967 unsigned int samplerIndex = startSamplerIndex;
1968
1969 do
1970 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001971 ASSERT(samplerIndex < outSamplers.size());
1972 Sampler *sampler = &outSamplers[samplerIndex];
1973 sampler->active = true;
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001974 sampler->textureType = gl::SamplerTypeToTextureType(samplerType);
Jamie Madill62d31cb2015-09-11 13:25:51 -04001975 sampler->logicalTextureUnit = 0;
1976 *outUsedRange = std::max(samplerIndex + 1, *outUsedRange);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001977 samplerIndex++;
1978 } while (samplerIndex < startSamplerIndex + samplerCount);
Brandon Jones18bd4102014-09-22 14:21:44 -07001979}
1980
Brandon Jonesc9610c52014-08-25 17:02:59 -07001981void ProgramD3D::reset()
1982{
Brandon Joneseb994362014-09-24 10:27:28 -07001983 SafeDeleteContainer(mVertexExecutables);
1984 SafeDeleteContainer(mPixelExecutables);
Jamie Madill4e31ad52015-10-29 10:32:57 -04001985
1986 for (auto &element : mGeometryExecutables)
1987 {
1988 SafeDelete(element);
1989 }
Brandon Joneseb994362014-09-24 10:27:28 -07001990
Brandon Jones22502d52014-08-29 16:58:36 -07001991 mVertexHLSL.clear();
Geoff Lang6941a552015-07-27 11:06:45 -04001992 mVertexWorkarounds = D3DCompilerWorkarounds();
Brandon Jones22502d52014-08-29 16:58:36 -07001993
1994 mPixelHLSL.clear();
Geoff Lang6941a552015-07-27 11:06:45 -04001995 mPixelWorkarounds = D3DCompilerWorkarounds();
Brandon Jones22502d52014-08-29 16:58:36 -07001996 mUsesFragDepth = false;
1997 mPixelShaderKey.clear();
Brandon Jones44151a92014-09-10 11:32:25 -07001998 mUsesPointSize = false;
Jamie Madill3e14e2b2015-10-29 14:38:53 -04001999 mUsesFlatInterpolation = false;
Brandon Jones22502d52014-08-29 16:58:36 -07002000
Jamie Madill62d31cb2015-09-11 13:25:51 -04002001 SafeDeleteContainer(mD3DUniforms);
Jamie Madill4a3c2342015-10-08 12:58:45 -04002002 mD3DUniformBlocks.clear();
Jamie Madill62d31cb2015-09-11 13:25:51 -04002003
Brandon Jonesc9610c52014-08-25 17:02:59 -07002004 SafeDelete(mVertexUniformStorage);
2005 SafeDelete(mFragmentUniformStorage);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002006
2007 mSamplersPS.clear();
2008 mSamplersVS.clear();
2009
2010 mUsedVertexSamplerRange = 0;
Jamie Madill334d6152015-10-22 14:00:28 -04002011 mUsedPixelSamplerRange = 0;
2012 mDirtySamplerMapping = true;
Jamie Madill437d2662014-12-05 14:23:35 -05002013
Jamie Madill63805b42015-08-25 13:17:39 -04002014 std::fill(mSemanticIndexes, mSemanticIndexes + ArraySize(mSemanticIndexes), -1);
Jamie Madill437d2662014-12-05 14:23:35 -05002015 std::fill(mAttributesByLayout, mAttributesByLayout + ArraySize(mAttributesByLayout), -1);
Jamie Madillccdf74b2015-08-18 10:46:12 -04002016
Jamie Madill28afae52015-11-09 15:07:57 -05002017 mTransformFeedbackD3DVaryings.clear();
Jamie Madill4e31ad52015-10-29 10:32:57 -04002018
2019 mGeometryShaderPreamble.clear();
Brandon Jonesc9610c52014-08-25 17:02:59 -07002020}
2021
Geoff Lang7dd2e102014-11-10 15:19:26 -05002022unsigned int ProgramD3D::getSerial() const
2023{
2024 return mSerial;
2025}
2026
2027unsigned int ProgramD3D::issueSerial()
2028{
2029 return mCurrentSerial++;
2030}
2031
Jamie Madill63805b42015-08-25 13:17:39 -04002032void ProgramD3D::initSemanticIndex()
2033{
2034 const gl::Shader *vertexShader = mData.getAttachedVertexShader();
2035 ASSERT(vertexShader != nullptr);
2036
2037 // Init semantic index
2038 for (const sh::Attribute &attribute : mData.getAttributes())
2039 {
2040 int attributeIndex = attribute.location;
2041 int index = vertexShader->getSemanticIndex(attribute.name);
2042 int regs = gl::VariableRegisterCount(attribute.type);
2043
2044 for (int reg = 0; reg < regs; ++reg)
2045 {
2046 mSemanticIndexes[attributeIndex + reg] = index + reg;
2047 }
2048 }
2049
2050 initAttributesByLayout();
2051}
2052
Jamie Madill437d2662014-12-05 14:23:35 -05002053void ProgramD3D::initAttributesByLayout()
2054{
2055 for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
2056 {
2057 mAttributesByLayout[i] = i;
2058 }
2059
Jamie Madill63805b42015-08-25 13:17:39 -04002060 std::sort(&mAttributesByLayout[0], &mAttributesByLayout[gl::MAX_VERTEX_ATTRIBS],
2061 AttributeSorter(mSemanticIndexes));
Jamie Madill437d2662014-12-05 14:23:35 -05002062}
2063
Jamie Madill334d6152015-10-22 14:00:28 -04002064void ProgramD3D::sortAttributesByLayout(
2065 const std::vector<TranslatedAttribute> &unsortedAttributes,
2066 int sortedSemanticIndicesOut[gl::MAX_VERTEX_ATTRIBS],
2067 const rx::TranslatedAttribute *sortedAttributesOut[gl::MAX_VERTEX_ATTRIBS]) const
Jamie Madill437d2662014-12-05 14:23:35 -05002068{
Jamie Madill476682e2015-06-30 10:04:29 -04002069 for (size_t attribIndex = 0; attribIndex < unsortedAttributes.size(); ++attribIndex)
Jamie Madill437d2662014-12-05 14:23:35 -05002070 {
Jamie Madill334d6152015-10-22 14:00:28 -04002071 int oldIndex = mAttributesByLayout[attribIndex];
Jamie Madill63805b42015-08-25 13:17:39 -04002072 sortedSemanticIndicesOut[attribIndex] = mSemanticIndexes[oldIndex];
Jamie Madill334d6152015-10-22 14:00:28 -04002073 sortedAttributesOut[attribIndex] = &unsortedAttributes[oldIndex];
Jamie Madill437d2662014-12-05 14:23:35 -05002074 }
2075}
2076
Jamie Madill63805b42015-08-25 13:17:39 -04002077void ProgramD3D::updateCachedInputLayout(const gl::State &state)
Jamie Madilld3dfda22015-07-06 08:28:49 -04002078{
Jamie Madillbd136f92015-08-10 14:51:37 -04002079 mCachedInputLayout.clear();
Jamie Madilld3dfda22015-07-06 08:28:49 -04002080 const auto &vertexAttributes = state.getVertexArray()->getVertexAttributes();
Jamie Madillf8dd7b12015-08-05 13:50:08 -04002081
Dian Xianga4928832015-09-15 10:11:17 -07002082 for (unsigned int attributeIndex : angle::IterateBitSet(mData.getActiveAttribLocationsMask()))
Jamie Madilld3dfda22015-07-06 08:28:49 -04002083 {
Jamie Madill63805b42015-08-25 13:17:39 -04002084 int semanticIndex = mSemanticIndexes[attributeIndex];
Jamie Madilld3dfda22015-07-06 08:28:49 -04002085
2086 if (semanticIndex != -1)
2087 {
Jamie Madillbd136f92015-08-10 14:51:37 -04002088 if (mCachedInputLayout.size() < static_cast<size_t>(semanticIndex + 1))
2089 {
2090 mCachedInputLayout.resize(semanticIndex + 1, gl::VERTEX_FORMAT_INVALID);
2091 }
Jamie Madilld3dfda22015-07-06 08:28:49 -04002092 mCachedInputLayout[semanticIndex] =
2093 GetVertexFormatType(vertexAttributes[attributeIndex],
2094 state.getVertexAttribCurrentValue(attributeIndex).Type);
2095 }
2096 }
2097}
2098
Jamie Madill28afae52015-11-09 15:07:57 -05002099void ProgramD3D::gatherTransformFeedbackVaryings(const std::vector<D3DVarying> &d3dVaryings)
Jamie Madillccdf74b2015-08-18 10:46:12 -04002100{
2101 // Gather the linked varyings that are used for transform feedback, they should all exist.
Jamie Madill28afae52015-11-09 15:07:57 -05002102 mTransformFeedbackD3DVaryings.clear();
Jamie Madillccdf74b2015-08-18 10:46:12 -04002103 for (const std::string &tfVaryingName : mData.getTransformFeedbackVaryingNames())
2104 {
Jamie Madill28afae52015-11-09 15:07:57 -05002105 for (const D3DVarying &d3dVarying : d3dVaryings)
Jamie Madillccdf74b2015-08-18 10:46:12 -04002106 {
Jamie Madill28afae52015-11-09 15:07:57 -05002107 if (tfVaryingName == d3dVarying.name)
Jamie Madillccdf74b2015-08-18 10:46:12 -04002108 {
Jamie Madill28afae52015-11-09 15:07:57 -05002109 mTransformFeedbackD3DVaryings.push_back(d3dVarying);
Jamie Madillccdf74b2015-08-18 10:46:12 -04002110 break;
2111 }
2112 }
2113 }
2114}
Jamie Madill62d31cb2015-09-11 13:25:51 -04002115
2116D3DUniform *ProgramD3D::getD3DUniformFromLocation(GLint location)
2117{
2118 return mD3DUniforms[mData.getUniformLocations()[location].index];
2119}
Jamie Madill4a3c2342015-10-08 12:58:45 -04002120
2121bool ProgramD3D::getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const
2122{
2123 std::string baseName = blockName;
2124 gl::ParseAndStripArrayIndex(&baseName);
2125
2126 auto sizeIter = mBlockDataSizes.find(baseName);
2127 if (sizeIter == mBlockDataSizes.end())
2128 {
2129 *sizeOut = 0;
2130 return false;
2131 }
2132
2133 *sizeOut = sizeIter->second;
2134 return true;
2135}
2136
2137bool ProgramD3D::getUniformBlockMemberInfo(const std::string &memberUniformName,
2138 sh::BlockMemberInfo *memberInfoOut) const
2139{
2140 auto infoIter = mBlockInfo.find(memberUniformName);
2141 if (infoIter == mBlockInfo.end())
2142 {
2143 *memberInfoOut = sh::BlockMemberInfo::getDefaultBlockInfo();
2144 return false;
2145 }
2146
2147 *memberInfoOut = infoIter->second;
2148 return true;
2149}
Brandon Jonesc9610c52014-08-25 17:02:59 -07002150}