blob: 5eba95c86900294ed48c33ecd9b87034cb2b8f8b [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 Madill62d31cb2015-09-11 13:25:51 -0400294D3DUniform::D3DUniform(GLenum typeIn,
295 const std::string &nameIn,
296 unsigned int arraySizeIn,
297 bool defaultBlock)
298 : type(typeIn),
299 name(nameIn),
300 arraySize(arraySizeIn),
301 data(nullptr),
302 dirty(true),
Jamie Madill62d31cb2015-09-11 13:25:51 -0400303 vsRegisterIndex(GL_INVALID_INDEX),
Geoff Lang98c56da2015-09-15 15:45:34 -0400304 psRegisterIndex(GL_INVALID_INDEX),
Jamie Madill62d31cb2015-09-11 13:25:51 -0400305 registerCount(0),
306 registerElement(0)
307{
308 // We use data storage for default block uniforms to cache values that are sent to D3D during
309 // rendering
310 // Uniform blocks/buffers are treated separately by the Renderer (ES3 path only)
311 if (defaultBlock)
312 {
313 size_t bytes = gl::VariableInternalSize(type) * elementCount();
314 data = new uint8_t[bytes];
315 memset(data, 0, bytes);
316
317 // TODO(jmadill): is this correct with non-square matrices?
318 registerCount = gl::VariableRowCount(type) * elementCount();
319 }
320}
321
322D3DUniform::~D3DUniform()
323{
324 SafeDeleteArray(data);
325}
326
327bool D3DUniform::isSampler() const
328{
329 return gl::IsSamplerType(type);
330}
331
332bool D3DUniform::isReferencedByVertexShader() const
333{
334 return vsRegisterIndex != GL_INVALID_INDEX;
335}
336
337bool D3DUniform::isReferencedByFragmentShader() const
338{
339 return psRegisterIndex != GL_INVALID_INDEX;
340}
341
Jamie Madilld3dfda22015-07-06 08:28:49 -0400342ProgramD3D::VertexExecutable::VertexExecutable(const gl::InputLayout &inputLayout,
343 const Signature &signature,
Geoff Lang359ef262015-01-05 14:42:29 -0500344 ShaderExecutableD3D *shaderExecutable)
Jamie Madill334d6152015-10-22 14:00:28 -0400345 : mInputs(inputLayout), mSignature(signature), mShaderExecutable(shaderExecutable)
Brandon Joneseb994362014-09-24 10:27:28 -0700346{
Brandon Joneseb994362014-09-24 10:27:28 -0700347}
348
349ProgramD3D::VertexExecutable::~VertexExecutable()
350{
351 SafeDelete(mShaderExecutable);
352}
353
Jamie Madilld3dfda22015-07-06 08:28:49 -0400354// static
355void ProgramD3D::VertexExecutable::getSignature(RendererD3D *renderer,
356 const gl::InputLayout &inputLayout,
357 Signature *signatureOut)
Brandon Joneseb994362014-09-24 10:27:28 -0700358{
Jamie Madillbd136f92015-08-10 14:51:37 -0400359 signatureOut->resize(inputLayout.size());
Jamie Madilld3dfda22015-07-06 08:28:49 -0400360
361 for (size_t index = 0; index < inputLayout.size(); ++index)
Brandon Joneseb994362014-09-24 10:27:28 -0700362 {
Jamie Madilld3dfda22015-07-06 08:28:49 -0400363 gl::VertexFormatType vertexFormatType = inputLayout[index];
Jamie Madillbd136f92015-08-10 14:51:37 -0400364 bool converted = false;
Jamie Madillf8dd7b12015-08-05 13:50:08 -0400365 if (vertexFormatType != gl::VERTEX_FORMAT_INVALID)
Brandon Joneseb994362014-09-24 10:27:28 -0700366 {
Jamie Madillf8dd7b12015-08-05 13:50:08 -0400367 VertexConversionType conversionType =
368 renderer->getVertexConversionType(vertexFormatType);
Jamie Madillbd136f92015-08-10 14:51:37 -0400369 converted = ((conversionType & VERTEX_CONVERT_GPU) != 0);
Brandon Joneseb994362014-09-24 10:27:28 -0700370 }
Jamie Madillbd136f92015-08-10 14:51:37 -0400371
372 (*signatureOut)[index] = converted;
Brandon Joneseb994362014-09-24 10:27:28 -0700373 }
Brandon Joneseb994362014-09-24 10:27:28 -0700374}
375
Jamie Madilld3dfda22015-07-06 08:28:49 -0400376bool ProgramD3D::VertexExecutable::matchesSignature(const Signature &signature) const
377{
Jamie Madillbd136f92015-08-10 14:51:37 -0400378 size_t limit = std::max(mSignature.size(), signature.size());
379 for (size_t index = 0; index < limit; ++index)
380 {
381 // treat undefined indexes as 'not converted'
382 bool a = index < signature.size() ? signature[index] : false;
383 bool b = index < mSignature.size() ? mSignature[index] : false;
384 if (a != b)
385 return false;
386 }
387
388 return true;
Jamie Madilld3dfda22015-07-06 08:28:49 -0400389}
390
391ProgramD3D::PixelExecutable::PixelExecutable(const std::vector<GLenum> &outputSignature,
392 ShaderExecutableD3D *shaderExecutable)
Jamie Madill334d6152015-10-22 14:00:28 -0400393 : mOutputSignature(outputSignature), mShaderExecutable(shaderExecutable)
Brandon Joneseb994362014-09-24 10:27:28 -0700394{
395}
396
397ProgramD3D::PixelExecutable::~PixelExecutable()
398{
399 SafeDelete(mShaderExecutable);
400}
401
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700402ProgramD3D::Sampler::Sampler() : active(false), logicalTextureUnit(0), textureType(GL_TEXTURE_2D)
403{
404}
405
Geoff Lang7dd2e102014-11-10 15:19:26 -0500406unsigned int ProgramD3D::mCurrentSerial = 1;
407
Jamie Madill5c6b7bf2015-08-17 12:53:35 -0400408ProgramD3D::ProgramD3D(const gl::Program::Data &data, RendererD3D *renderer)
409 : ProgramImpl(data),
Brandon Jonesc9610c52014-08-25 17:02:59 -0700410 mRenderer(renderer),
411 mDynamicHLSL(NULL),
Jamie Madill4e31ad52015-10-29 10:32:57 -0400412 mGeometryExecutables(gl::PRIMITIVE_TYPE_MAX, nullptr),
Brandon Jones44151a92014-09-10 11:32:25 -0700413 mUsesPointSize(false),
Jamie Madill3e14e2b2015-10-29 14:38:53 -0400414 mUsesFlatInterpolation(false),
Brandon Jonesc9610c52014-08-25 17:02:59 -0700415 mVertexUniformStorage(NULL),
Brandon Jones44151a92014-09-10 11:32:25 -0700416 mFragmentUniformStorage(NULL),
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700417 mUsedVertexSamplerRange(0),
418 mUsedPixelSamplerRange(0),
419 mDirtySamplerMapping(true),
Geoff Lang7dd2e102014-11-10 15:19:26 -0500420 mSerial(issueSerial())
Brandon Jonesc9610c52014-08-25 17:02:59 -0700421{
Brandon Joneseb994362014-09-24 10:27:28 -0700422 mDynamicHLSL = new DynamicHLSL(renderer);
Brandon Jonesc9610c52014-08-25 17:02:59 -0700423}
424
425ProgramD3D::~ProgramD3D()
426{
427 reset();
428 SafeDelete(mDynamicHLSL);
429}
430
Brandon Jones44151a92014-09-10 11:32:25 -0700431bool ProgramD3D::usesPointSpriteEmulation() const
432{
433 return mUsesPointSize && mRenderer->getMajorShaderModel() >= 4;
434}
435
Jamie Madill3e14e2b2015-10-29 14:38:53 -0400436bool ProgramD3D::usesGeometryShader(GLenum drawMode) const
Brandon Jones44151a92014-09-10 11:32:25 -0700437{
Jamie Madill3e14e2b2015-10-29 14:38:53 -0400438 if (drawMode != GL_POINTS)
439 {
440 return mUsesFlatInterpolation;
441 }
442
Cooper Partine6664f02015-01-09 16:22:24 -0800443 return usesPointSpriteEmulation() && !usesInstancedPointSpriteEmulation();
444}
445
446bool ProgramD3D::usesInstancedPointSpriteEmulation() const
447{
448 return mRenderer->getWorkarounds().useInstancedPointSpriteEmulation;
Brandon Jones44151a92014-09-10 11:32:25 -0700449}
450
Jamie Madill334d6152015-10-22 14:00:28 -0400451GLint ProgramD3D::getSamplerMapping(gl::SamplerType type,
452 unsigned int samplerIndex,
453 const gl::Caps &caps) const
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700454{
455 GLint logicalTextureUnit = -1;
456
457 switch (type)
458 {
Jamie Madill334d6152015-10-22 14:00:28 -0400459 case gl::SAMPLER_PIXEL:
460 ASSERT(samplerIndex < caps.maxTextureImageUnits);
461 if (samplerIndex < mSamplersPS.size() && mSamplersPS[samplerIndex].active)
462 {
463 logicalTextureUnit = mSamplersPS[samplerIndex].logicalTextureUnit;
464 }
465 break;
466 case gl::SAMPLER_VERTEX:
467 ASSERT(samplerIndex < caps.maxVertexTextureImageUnits);
468 if (samplerIndex < mSamplersVS.size() && mSamplersVS[samplerIndex].active)
469 {
470 logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit;
471 }
472 break;
473 default:
474 UNREACHABLE();
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700475 }
476
Jamie Madill334d6152015-10-22 14:00:28 -0400477 if (logicalTextureUnit >= 0 &&
478 logicalTextureUnit < static_cast<GLint>(caps.maxCombinedTextureImageUnits))
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700479 {
480 return logicalTextureUnit;
481 }
482
483 return -1;
484}
485
486// Returns the texture type for a given Direct3D 9 sampler type and
487// index (0-15 for the pixel shader and 0-3 for the vertex shader).
488GLenum ProgramD3D::getSamplerTextureType(gl::SamplerType type, unsigned int samplerIndex) const
489{
490 switch (type)
491 {
Jamie Madill334d6152015-10-22 14:00:28 -0400492 case gl::SAMPLER_PIXEL:
493 ASSERT(samplerIndex < mSamplersPS.size());
494 ASSERT(mSamplersPS[samplerIndex].active);
495 return mSamplersPS[samplerIndex].textureType;
496 case gl::SAMPLER_VERTEX:
497 ASSERT(samplerIndex < mSamplersVS.size());
498 ASSERT(mSamplersVS[samplerIndex].active);
499 return mSamplersVS[samplerIndex].textureType;
500 default:
501 UNREACHABLE();
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700502 }
503
504 return GL_TEXTURE_2D;
505}
506
507GLint ProgramD3D::getUsedSamplerRange(gl::SamplerType type) const
508{
509 switch (type)
510 {
Jamie Madill334d6152015-10-22 14:00:28 -0400511 case gl::SAMPLER_PIXEL:
512 return mUsedPixelSamplerRange;
513 case gl::SAMPLER_VERTEX:
514 return mUsedVertexSamplerRange;
515 default:
516 UNREACHABLE();
517 return 0;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700518 }
519}
520
521void ProgramD3D::updateSamplerMapping()
522{
523 if (!mDirtySamplerMapping)
524 {
525 return;
526 }
527
528 mDirtySamplerMapping = false;
529
530 // Retrieve sampler uniform values
Jamie Madill62d31cb2015-09-11 13:25:51 -0400531 for (const D3DUniform *d3dUniform : mD3DUniforms)
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700532 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400533 if (!d3dUniform->dirty)
534 continue;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700535
Jamie Madill62d31cb2015-09-11 13:25:51 -0400536 if (!d3dUniform->isSampler())
537 continue;
538
539 int count = d3dUniform->elementCount();
540 const GLint(*v)[4] = reinterpret_cast<const GLint(*)[4]>(d3dUniform->data);
541
542 if (d3dUniform->isReferencedByFragmentShader())
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700543 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400544 unsigned int firstIndex = d3dUniform->psRegisterIndex;
545
546 for (int i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700547 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400548 unsigned int samplerIndex = firstIndex + i;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700549
Jamie Madill62d31cb2015-09-11 13:25:51 -0400550 if (samplerIndex < mSamplersPS.size())
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700551 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400552 ASSERT(mSamplersPS[samplerIndex].active);
553 mSamplersPS[samplerIndex].logicalTextureUnit = v[i][0];
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700554 }
Jamie Madill62d31cb2015-09-11 13:25:51 -0400555 }
556 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700557
Jamie Madill62d31cb2015-09-11 13:25:51 -0400558 if (d3dUniform->isReferencedByVertexShader())
559 {
560 unsigned int firstIndex = d3dUniform->vsRegisterIndex;
561
562 for (int i = 0; i < count; i++)
563 {
564 unsigned int samplerIndex = firstIndex + i;
565
566 if (samplerIndex < mSamplersVS.size())
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700567 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400568 ASSERT(mSamplersVS[samplerIndex].active);
569 mSamplersVS[samplerIndex].logicalTextureUnit = v[i][0];
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700570 }
571 }
572 }
573 }
574}
575
Geoff Lang7dd2e102014-11-10 15:19:26 -0500576LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
Brandon Jones22502d52014-08-29 16:58:36 -0700577{
Jamie Madill62d31cb2015-09-11 13:25:51 -0400578 reset();
579
Jamie Madill334d6152015-10-22 14:00:28 -0400580 DeviceIdentifier binaryDeviceIdentifier = {0};
581 stream->readBytes(reinterpret_cast<unsigned char *>(&binaryDeviceIdentifier),
582 sizeof(DeviceIdentifier));
Austin Kinross137b1512015-06-17 16:14:53 -0700583
584 DeviceIdentifier identifier = mRenderer->getAdapterIdentifier();
585 if (memcmp(&identifier, &binaryDeviceIdentifier, sizeof(DeviceIdentifier)) != 0)
586 {
587 infoLog << "Invalid program binary, device configuration has changed.";
588 return LinkResult(false, gl::Error(GL_NO_ERROR));
589 }
590
Jamie Madill2db1fbb2014-12-03 10:58:55 -0500591 int compileFlags = stream->readInt<int>();
592 if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL)
593 {
Jamie Madillf6113162015-05-07 11:49:21 -0400594 infoLog << "Mismatched compilation flags.";
Jamie Madill2db1fbb2014-12-03 10:58:55 -0500595 return LinkResult(false, gl::Error(GL_NO_ERROR));
596 }
597
Jamie Madill63805b42015-08-25 13:17:39 -0400598 // TODO(jmadill): replace MAX_VERTEX_ATTRIBS
599 for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; ++i)
600 {
601 stream->readInt(&mSemanticIndexes[i]);
602 }
603
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700604 const unsigned int psSamplerCount = stream->readInt<unsigned int>();
605 for (unsigned int i = 0; i < psSamplerCount; ++i)
606 {
607 Sampler sampler;
608 stream->readBool(&sampler.active);
609 stream->readInt(&sampler.logicalTextureUnit);
610 stream->readInt(&sampler.textureType);
611 mSamplersPS.push_back(sampler);
612 }
613 const unsigned int vsSamplerCount = stream->readInt<unsigned int>();
614 for (unsigned int i = 0; i < vsSamplerCount; ++i)
615 {
616 Sampler sampler;
617 stream->readBool(&sampler.active);
618 stream->readInt(&sampler.logicalTextureUnit);
619 stream->readInt(&sampler.textureType);
620 mSamplersVS.push_back(sampler);
621 }
622
623 stream->readInt(&mUsedVertexSamplerRange);
624 stream->readInt(&mUsedPixelSamplerRange);
625
626 const unsigned int uniformCount = stream->readInt<unsigned int>();
627 if (stream->error())
628 {
Jamie Madillf6113162015-05-07 11:49:21 -0400629 infoLog << "Invalid program binary.";
Geoff Lang7dd2e102014-11-10 15:19:26 -0500630 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700631 }
632
Jamie Madill62d31cb2015-09-11 13:25:51 -0400633 const auto &linkedUniforms = mData.getUniforms();
634 ASSERT(mD3DUniforms.empty());
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700635 for (unsigned int uniformIndex = 0; uniformIndex < uniformCount; uniformIndex++)
636 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400637 const gl::LinkedUniform &linkedUniform = linkedUniforms[uniformIndex];
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700638
Jamie Madill62d31cb2015-09-11 13:25:51 -0400639 D3DUniform *d3dUniform =
640 new D3DUniform(linkedUniform.type, linkedUniform.name, linkedUniform.arraySize,
641 linkedUniform.isInDefaultBlock());
642 stream->readInt(&d3dUniform->psRegisterIndex);
643 stream->readInt(&d3dUniform->vsRegisterIndex);
644 stream->readInt(&d3dUniform->registerCount);
645 stream->readInt(&d3dUniform->registerElement);
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700646
Jamie Madill62d31cb2015-09-11 13:25:51 -0400647 mD3DUniforms.push_back(d3dUniform);
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700648 }
649
Jamie Madill4a3c2342015-10-08 12:58:45 -0400650 const unsigned int blockCount = stream->readInt<unsigned int>();
651 if (stream->error())
652 {
653 infoLog << "Invalid program binary.";
654 return LinkResult(false, gl::Error(GL_NO_ERROR));
655 }
656
657 ASSERT(mD3DUniformBlocks.empty());
658 for (unsigned int blockIndex = 0; blockIndex < blockCount; ++blockIndex)
659 {
660 D3DUniformBlock uniformBlock;
661 stream->readInt(&uniformBlock.psRegisterIndex);
662 stream->readInt(&uniformBlock.vsRegisterIndex);
663 mD3DUniformBlocks.push_back(uniformBlock);
664 }
665
Brandon Joneseb994362014-09-24 10:27:28 -0700666 const unsigned int transformFeedbackVaryingCount = stream->readInt<unsigned int>();
667 mTransformFeedbackLinkedVaryings.resize(transformFeedbackVaryingCount);
Jamie Madill334d6152015-10-22 14:00:28 -0400668 for (unsigned int varyingIndex = 0; varyingIndex < transformFeedbackVaryingCount;
669 varyingIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -0700670 {
671 gl::LinkedVarying &varying = mTransformFeedbackLinkedVaryings[varyingIndex];
672
673 stream->readString(&varying.name);
674 stream->readInt(&varying.type);
675 stream->readInt(&varying.size);
676 stream->readString(&varying.semanticName);
677 stream->readInt(&varying.semanticIndex);
678 stream->readInt(&varying.semanticIndexCount);
679 }
680
Brandon Jones22502d52014-08-29 16:58:36 -0700681 stream->readString(&mVertexHLSL);
Jamie Madill334d6152015-10-22 14:00:28 -0400682 stream->readBytes(reinterpret_cast<unsigned char *>(&mVertexWorkarounds),
683 sizeof(D3DCompilerWorkarounds));
Brandon Jones22502d52014-08-29 16:58:36 -0700684 stream->readString(&mPixelHLSL);
Jamie Madill334d6152015-10-22 14:00:28 -0400685 stream->readBytes(reinterpret_cast<unsigned char *>(&mPixelWorkarounds),
686 sizeof(D3DCompilerWorkarounds));
Brandon Jones22502d52014-08-29 16:58:36 -0700687 stream->readBool(&mUsesFragDepth);
Brandon Jones44151a92014-09-10 11:32:25 -0700688 stream->readBool(&mUsesPointSize);
Jamie Madill3e14e2b2015-10-29 14:38:53 -0400689 stream->readBool(&mUsesFlatInterpolation);
Brandon Jones22502d52014-08-29 16:58:36 -0700690
691 const size_t pixelShaderKeySize = stream->readInt<unsigned int>();
692 mPixelShaderKey.resize(pixelShaderKeySize);
Jamie Madill334d6152015-10-22 14:00:28 -0400693 for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKeySize;
694 pixelShaderKeyIndex++)
Brandon Jones22502d52014-08-29 16:58:36 -0700695 {
696 stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].type);
697 stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].name);
698 stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].source);
699 stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].outputIndex);
700 }
701
Jamie Madill4e31ad52015-10-29 10:32:57 -0400702 stream->readString(&mGeometryShaderPreamble);
703
Jamie Madill334d6152015-10-22 14:00:28 -0400704 const unsigned char *binary = reinterpret_cast<const unsigned char *>(stream->data());
Brandon Joneseb994362014-09-24 10:27:28 -0700705
706 const unsigned int vertexShaderCount = stream->readInt<unsigned int>();
Jamie Madill334d6152015-10-22 14:00:28 -0400707 for (unsigned int vertexShaderIndex = 0; vertexShaderIndex < vertexShaderCount;
708 vertexShaderIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -0700709 {
Jamie Madilld3dfda22015-07-06 08:28:49 -0400710 size_t inputLayoutSize = stream->readInt<size_t>();
Jamie Madillf8dd7b12015-08-05 13:50:08 -0400711 gl::InputLayout inputLayout(inputLayoutSize, gl::VERTEX_FORMAT_INVALID);
Brandon Joneseb994362014-09-24 10:27:28 -0700712
Jamie Madilld3dfda22015-07-06 08:28:49 -0400713 for (size_t inputIndex = 0; inputIndex < inputLayoutSize; inputIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -0700714 {
Jamie Madillf8dd7b12015-08-05 13:50:08 -0400715 inputLayout[inputIndex] = stream->readInt<gl::VertexFormatType>();
Brandon Joneseb994362014-09-24 10:27:28 -0700716 }
717
Jamie Madill334d6152015-10-22 14:00:28 -0400718 unsigned int vertexShaderSize = stream->readInt<unsigned int>();
Brandon Joneseb994362014-09-24 10:27:28 -0700719 const unsigned char *vertexShaderFunction = binary + stream->offset();
Geoff Langb543aff2014-09-30 14:52:54 -0400720
Jamie Madillada9ecc2015-08-17 12:53:37 -0400721 ShaderExecutableD3D *shaderExecutable = nullptr;
722
723 gl::Error error = mRenderer->loadExecutable(
724 vertexShaderFunction, vertexShaderSize, SHADER_VERTEX, mTransformFeedbackLinkedVaryings,
725 (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), &shaderExecutable);
Geoff Langb543aff2014-09-30 14:52:54 -0400726 if (error.isError())
727 {
Geoff Lang7dd2e102014-11-10 15:19:26 -0500728 return LinkResult(false, error);
Geoff Langb543aff2014-09-30 14:52:54 -0400729 }
730
Brandon Joneseb994362014-09-24 10:27:28 -0700731 if (!shaderExecutable)
732 {
Jamie Madillf6113162015-05-07 11:49:21 -0400733 infoLog << "Could not create vertex shader.";
Geoff Lang7dd2e102014-11-10 15:19:26 -0500734 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Joneseb994362014-09-24 10:27:28 -0700735 }
736
737 // generated converted input layout
Jamie Madilld3dfda22015-07-06 08:28:49 -0400738 VertexExecutable::Signature signature;
739 VertexExecutable::getSignature(mRenderer, inputLayout, &signature);
Brandon Joneseb994362014-09-24 10:27:28 -0700740
741 // add new binary
Jamie Madill334d6152015-10-22 14:00:28 -0400742 mVertexExecutables.push_back(
743 new VertexExecutable(inputLayout, signature, shaderExecutable));
Brandon Joneseb994362014-09-24 10:27:28 -0700744
745 stream->skip(vertexShaderSize);
746 }
747
748 const size_t pixelShaderCount = stream->readInt<unsigned int>();
749 for (size_t pixelShaderIndex = 0; pixelShaderIndex < pixelShaderCount; pixelShaderIndex++)
750 {
751 const size_t outputCount = stream->readInt<unsigned int>();
752 std::vector<GLenum> outputs(outputCount);
753 for (size_t outputIndex = 0; outputIndex < outputCount; outputIndex++)
754 {
755 stream->readInt(&outputs[outputIndex]);
756 }
757
Jamie Madill334d6152015-10-22 14:00:28 -0400758 const size_t pixelShaderSize = stream->readInt<unsigned int>();
Brandon Joneseb994362014-09-24 10:27:28 -0700759 const unsigned char *pixelShaderFunction = binary + stream->offset();
Jamie Madillada9ecc2015-08-17 12:53:37 -0400760 ShaderExecutableD3D *shaderExecutable = nullptr;
761
762 gl::Error error = mRenderer->loadExecutable(
763 pixelShaderFunction, pixelShaderSize, SHADER_PIXEL, mTransformFeedbackLinkedVaryings,
764 (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), &shaderExecutable);
Geoff Langb543aff2014-09-30 14:52:54 -0400765 if (error.isError())
766 {
Geoff Lang7dd2e102014-11-10 15:19:26 -0500767 return LinkResult(false, error);
Geoff Langb543aff2014-09-30 14:52:54 -0400768 }
Brandon Joneseb994362014-09-24 10:27:28 -0700769
770 if (!shaderExecutable)
771 {
Jamie Madillf6113162015-05-07 11:49:21 -0400772 infoLog << "Could not create pixel shader.";
Geoff Lang7dd2e102014-11-10 15:19:26 -0500773 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Joneseb994362014-09-24 10:27:28 -0700774 }
775
776 // add new binary
777 mPixelExecutables.push_back(new PixelExecutable(outputs, shaderExecutable));
778
779 stream->skip(pixelShaderSize);
780 }
781
Jamie Madill4e31ad52015-10-29 10:32:57 -0400782 for (unsigned int geometryExeIndex = 0; geometryExeIndex < gl::PRIMITIVE_TYPE_MAX;
783 ++geometryExeIndex)
Brandon Joneseb994362014-09-24 10:27:28 -0700784 {
Jamie Madill4e31ad52015-10-29 10:32:57 -0400785 unsigned int geometryShaderSize = stream->readInt<unsigned int>();
786 if (geometryShaderSize == 0)
787 {
788 mGeometryExecutables[geometryExeIndex] = nullptr;
789 continue;
790 }
791
Brandon Joneseb994362014-09-24 10:27:28 -0700792 const unsigned char *geometryShaderFunction = binary + stream->offset();
Jamie Madill4e31ad52015-10-29 10:32:57 -0400793 bool splitAttribs = (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS);
794
795 gl::Error error =
796 mRenderer->loadExecutable(geometryShaderFunction, geometryShaderSize, SHADER_GEOMETRY,
797 mTransformFeedbackLinkedVaryings, splitAttribs,
798 &mGeometryExecutables[geometryExeIndex]);
Geoff Langb543aff2014-09-30 14:52:54 -0400799 if (error.isError())
800 {
Geoff Lang7dd2e102014-11-10 15:19:26 -0500801 return LinkResult(false, error);
Geoff Langb543aff2014-09-30 14:52:54 -0400802 }
Brandon Joneseb994362014-09-24 10:27:28 -0700803
Jamie Madill4e31ad52015-10-29 10:32:57 -0400804 if (!mGeometryExecutables[geometryExeIndex])
Brandon Joneseb994362014-09-24 10:27:28 -0700805 {
Jamie Madillf6113162015-05-07 11:49:21 -0400806 infoLog << "Could not create geometry shader.";
Geoff Lang7dd2e102014-11-10 15:19:26 -0500807 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Joneseb994362014-09-24 10:27:28 -0700808 }
809 stream->skip(geometryShaderSize);
810 }
811
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700812 initializeUniformStorage();
Jamie Madill437d2662014-12-05 14:23:35 -0500813 initAttributesByLayout();
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700814
Geoff Lang7dd2e102014-11-10 15:19:26 -0500815 return LinkResult(true, gl::Error(GL_NO_ERROR));
Brandon Jones22502d52014-08-29 16:58:36 -0700816}
817
Geoff Langb543aff2014-09-30 14:52:54 -0400818gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream)
Brandon Jones22502d52014-08-29 16:58:36 -0700819{
Austin Kinross137b1512015-06-17 16:14:53 -0700820 // Output the DeviceIdentifier before we output any shader code
Jamie Madill334d6152015-10-22 14:00:28 -0400821 // When we load the binary again later, we can validate the device identifier before trying to
822 // compile any HLSL
Austin Kinross137b1512015-06-17 16:14:53 -0700823 DeviceIdentifier binaryIdentifier = mRenderer->getAdapterIdentifier();
Jamie Madill334d6152015-10-22 14:00:28 -0400824 stream->writeBytes(reinterpret_cast<unsigned char *>(&binaryIdentifier),
825 sizeof(DeviceIdentifier));
Austin Kinross137b1512015-06-17 16:14:53 -0700826
Jamie Madill2db1fbb2014-12-03 10:58:55 -0500827 stream->writeInt(ANGLE_COMPILE_OPTIMIZATION_LEVEL);
828
Jamie Madill63805b42015-08-25 13:17:39 -0400829 // TODO(jmadill): replace MAX_VERTEX_ATTRIBS
830 for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; ++i)
831 {
832 stream->writeInt(mSemanticIndexes[i]);
833 }
834
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700835 stream->writeInt(mSamplersPS.size());
836 for (unsigned int i = 0; i < mSamplersPS.size(); ++i)
837 {
838 stream->writeInt(mSamplersPS[i].active);
839 stream->writeInt(mSamplersPS[i].logicalTextureUnit);
840 stream->writeInt(mSamplersPS[i].textureType);
841 }
842
843 stream->writeInt(mSamplersVS.size());
844 for (unsigned int i = 0; i < mSamplersVS.size(); ++i)
845 {
846 stream->writeInt(mSamplersVS[i].active);
847 stream->writeInt(mSamplersVS[i].logicalTextureUnit);
848 stream->writeInt(mSamplersVS[i].textureType);
849 }
850
851 stream->writeInt(mUsedVertexSamplerRange);
852 stream->writeInt(mUsedPixelSamplerRange);
853
Jamie Madill62d31cb2015-09-11 13:25:51 -0400854 stream->writeInt(mD3DUniforms.size());
Jamie Madill4a3c2342015-10-08 12:58:45 -0400855 for (const D3DUniform *uniform : mD3DUniforms)
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700856 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400857 // Type, name and arraySize are redundant, so aren't stored in the binary.
Jamie Madill4a3c2342015-10-08 12:58:45 -0400858 stream->writeInt(uniform->psRegisterIndex);
859 stream->writeInt(uniform->vsRegisterIndex);
860 stream->writeInt(uniform->registerCount);
861 stream->writeInt(uniform->registerElement);
862 }
863
864 stream->writeInt(mD3DUniformBlocks.size());
865 for (const D3DUniformBlock &uniformBlock : mD3DUniformBlocks)
866 {
867 stream->writeInt(uniformBlock.psRegisterIndex);
868 stream->writeInt(uniformBlock.vsRegisterIndex);
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700869 }
870
Brandon Joneseb994362014-09-24 10:27:28 -0700871 stream->writeInt(mTransformFeedbackLinkedVaryings.size());
872 for (size_t i = 0; i < mTransformFeedbackLinkedVaryings.size(); i++)
873 {
874 const gl::LinkedVarying &varying = mTransformFeedbackLinkedVaryings[i];
875
876 stream->writeString(varying.name);
877 stream->writeInt(varying.type);
878 stream->writeInt(varying.size);
879 stream->writeString(varying.semanticName);
880 stream->writeInt(varying.semanticIndex);
881 stream->writeInt(varying.semanticIndexCount);
882 }
883
Brandon Jones22502d52014-08-29 16:58:36 -0700884 stream->writeString(mVertexHLSL);
Jamie Madill334d6152015-10-22 14:00:28 -0400885 stream->writeBytes(reinterpret_cast<unsigned char *>(&mVertexWorkarounds),
886 sizeof(D3DCompilerWorkarounds));
Brandon Jones22502d52014-08-29 16:58:36 -0700887 stream->writeString(mPixelHLSL);
Jamie Madill334d6152015-10-22 14:00:28 -0400888 stream->writeBytes(reinterpret_cast<unsigned char *>(&mPixelWorkarounds),
889 sizeof(D3DCompilerWorkarounds));
Brandon Jones22502d52014-08-29 16:58:36 -0700890 stream->writeInt(mUsesFragDepth);
Brandon Jones44151a92014-09-10 11:32:25 -0700891 stream->writeInt(mUsesPointSize);
Jamie Madill3e14e2b2015-10-29 14:38:53 -0400892 stream->writeInt(mUsesFlatInterpolation);
Brandon Jones22502d52014-08-29 16:58:36 -0700893
Brandon Joneseb994362014-09-24 10:27:28 -0700894 const std::vector<PixelShaderOutputVariable> &pixelShaderKey = mPixelShaderKey;
Brandon Jones22502d52014-08-29 16:58:36 -0700895 stream->writeInt(pixelShaderKey.size());
Jamie Madill334d6152015-10-22 14:00:28 -0400896 for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKey.size();
897 pixelShaderKeyIndex++)
Brandon Jones22502d52014-08-29 16:58:36 -0700898 {
Brandon Joneseb994362014-09-24 10:27:28 -0700899 const PixelShaderOutputVariable &variable = pixelShaderKey[pixelShaderKeyIndex];
Brandon Jones22502d52014-08-29 16:58:36 -0700900 stream->writeInt(variable.type);
901 stream->writeString(variable.name);
902 stream->writeString(variable.source);
903 stream->writeInt(variable.outputIndex);
904 }
905
Jamie Madill4e31ad52015-10-29 10:32:57 -0400906 stream->writeString(mGeometryShaderPreamble);
907
Brandon Joneseb994362014-09-24 10:27:28 -0700908 stream->writeInt(mVertexExecutables.size());
Jamie Madill334d6152015-10-22 14:00:28 -0400909 for (size_t vertexExecutableIndex = 0; vertexExecutableIndex < mVertexExecutables.size();
910 vertexExecutableIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -0700911 {
912 VertexExecutable *vertexExecutable = mVertexExecutables[vertexExecutableIndex];
913
Jamie Madilld3dfda22015-07-06 08:28:49 -0400914 const auto &inputLayout = vertexExecutable->inputs();
915 stream->writeInt(inputLayout.size());
916
917 for (size_t inputIndex = 0; inputIndex < inputLayout.size(); inputIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -0700918 {
Jamie Madilld3dfda22015-07-06 08:28:49 -0400919 stream->writeInt(inputLayout[inputIndex]);
Brandon Joneseb994362014-09-24 10:27:28 -0700920 }
921
922 size_t vertexShaderSize = vertexExecutable->shaderExecutable()->getLength();
923 stream->writeInt(vertexShaderSize);
924
925 const uint8_t *vertexBlob = vertexExecutable->shaderExecutable()->getFunction();
926 stream->writeBytes(vertexBlob, vertexShaderSize);
927 }
928
929 stream->writeInt(mPixelExecutables.size());
Jamie Madill334d6152015-10-22 14:00:28 -0400930 for (size_t pixelExecutableIndex = 0; pixelExecutableIndex < mPixelExecutables.size();
931 pixelExecutableIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -0700932 {
933 PixelExecutable *pixelExecutable = mPixelExecutables[pixelExecutableIndex];
934
935 const std::vector<GLenum> outputs = pixelExecutable->outputSignature();
936 stream->writeInt(outputs.size());
937 for (size_t outputIndex = 0; outputIndex < outputs.size(); outputIndex++)
938 {
939 stream->writeInt(outputs[outputIndex]);
940 }
941
942 size_t pixelShaderSize = pixelExecutable->shaderExecutable()->getLength();
943 stream->writeInt(pixelShaderSize);
944
945 const uint8_t *pixelBlob = pixelExecutable->shaderExecutable()->getFunction();
946 stream->writeBytes(pixelBlob, pixelShaderSize);
947 }
948
Jamie Madill4e31ad52015-10-29 10:32:57 -0400949 for (const ShaderExecutableD3D *geometryExe : mGeometryExecutables)
Brandon Joneseb994362014-09-24 10:27:28 -0700950 {
Jamie Madill4e31ad52015-10-29 10:32:57 -0400951 if (geometryExe == nullptr)
952 {
953 stream->writeInt(0);
954 continue;
955 }
956
957 size_t geometryShaderSize = geometryExe->getLength();
958 stream->writeInt(geometryShaderSize);
959 stream->writeBytes(geometryExe->getFunction(), geometryShaderSize);
Brandon Joneseb994362014-09-24 10:27:28 -0700960 }
961
Geoff Langb543aff2014-09-30 14:52:54 -0400962 return gl::Error(GL_NO_ERROR);
Brandon Jones22502d52014-08-29 16:58:36 -0700963}
964
Jamie Madill334d6152015-10-22 14:00:28 -0400965gl::Error ProgramD3D::getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo,
966 ShaderExecutableD3D **outExecutable)
Brandon Jones22502d52014-08-29 16:58:36 -0700967{
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400968 mPixelShaderOutputFormatCache.clear();
Brandon Joneseb994362014-09-24 10:27:28 -0700969
Jamie Madill85a18042015-03-05 15:41:41 -0500970 const FramebufferD3D *fboD3D = GetImplAs<FramebufferD3D>(fbo);
Jamie Madill334d6152015-10-22 14:00:28 -0400971 const gl::AttachmentList &colorbuffers =
972 fboD3D->getColorAttachmentsForRender(mRenderer->getWorkarounds());
Brandon Joneseb994362014-09-24 10:27:28 -0700973
974 for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment)
975 {
976 const gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment];
977
978 if (colorbuffer)
979 {
Jamie Madill334d6152015-10-22 14:00:28 -0400980 mPixelShaderOutputFormatCache.push_back(colorbuffer->getBinding() == GL_BACK
981 ? GL_COLOR_ATTACHMENT0
982 : colorbuffer->getBinding());
Brandon Joneseb994362014-09-24 10:27:28 -0700983 }
984 else
985 {
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400986 mPixelShaderOutputFormatCache.push_back(GL_NONE);
Brandon Joneseb994362014-09-24 10:27:28 -0700987 }
988 }
989
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400990 return getPixelExecutableForOutputLayout(mPixelShaderOutputFormatCache, outExecutable, nullptr);
Brandon Joneseb994362014-09-24 10:27:28 -0700991}
992
Jamie Madill97399232014-12-23 12:31:15 -0500993gl::Error ProgramD3D::getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputSignature,
Geoff Lang359ef262015-01-05 14:42:29 -0500994 ShaderExecutableD3D **outExectuable,
Jamie Madill97399232014-12-23 12:31:15 -0500995 gl::InfoLog *infoLog)
Brandon Joneseb994362014-09-24 10:27:28 -0700996{
997 for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++)
998 {
999 if (mPixelExecutables[executableIndex]->matchesSignature(outputSignature))
1000 {
Geoff Langb543aff2014-09-30 14:52:54 -04001001 *outExectuable = mPixelExecutables[executableIndex]->shaderExecutable();
1002 return gl::Error(GL_NO_ERROR);
Brandon Joneseb994362014-09-24 10:27:28 -07001003 }
1004 }
1005
Jamie Madill334d6152015-10-22 14:00:28 -04001006 std::string finalPixelHLSL = mDynamicHLSL->generatePixelShaderForOutputSignature(
1007 mPixelHLSL, mPixelShaderKey, mUsesFragDepth, outputSignature);
Brandon Jones22502d52014-08-29 16:58:36 -07001008
1009 // Generate new pixel executable
Geoff Lang359ef262015-01-05 14:42:29 -05001010 ShaderExecutableD3D *pixelExecutable = NULL;
Jamie Madill97399232014-12-23 12:31:15 -05001011
1012 gl::InfoLog tempInfoLog;
1013 gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
1014
Jamie Madillada9ecc2015-08-17 12:53:37 -04001015 gl::Error error = mRenderer->compileToExecutable(
1016 *currentInfoLog, finalPixelHLSL, SHADER_PIXEL, mTransformFeedbackLinkedVaryings,
1017 (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), mPixelWorkarounds,
1018 &pixelExecutable);
Geoff Langb543aff2014-09-30 14:52:54 -04001019 if (error.isError())
1020 {
1021 return error;
1022 }
Brandon Joneseb994362014-09-24 10:27:28 -07001023
Jamie Madill97399232014-12-23 12:31:15 -05001024 if (pixelExecutable)
1025 {
1026 mPixelExecutables.push_back(new PixelExecutable(outputSignature, pixelExecutable));
1027 }
1028 else if (!infoLog)
Brandon Joneseb994362014-09-24 10:27:28 -07001029 {
1030 std::vector<char> tempCharBuffer(tempInfoLog.getLength() + 3);
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001031 tempInfoLog.getLog(static_cast<GLsizei>(tempInfoLog.getLength()), NULL, &tempCharBuffer[0]);
Brandon Joneseb994362014-09-24 10:27:28 -07001032 ERR("Error compiling dynamic pixel executable:\n%s\n", &tempCharBuffer[0]);
1033 }
Brandon Jones22502d52014-08-29 16:58:36 -07001034
Geoff Langb543aff2014-09-30 14:52:54 -04001035 *outExectuable = pixelExecutable;
1036 return gl::Error(GL_NO_ERROR);
Brandon Jones22502d52014-08-29 16:58:36 -07001037}
1038
Jamie Madilld3dfda22015-07-06 08:28:49 -04001039gl::Error ProgramD3D::getVertexExecutableForInputLayout(const gl::InputLayout &inputLayout,
Geoff Lang359ef262015-01-05 14:42:29 -05001040 ShaderExecutableD3D **outExectuable,
Jamie Madill97399232014-12-23 12:31:15 -05001041 gl::InfoLog *infoLog)
Brandon Jones22502d52014-08-29 16:58:36 -07001042{
Jamie Madilld3dfda22015-07-06 08:28:49 -04001043 VertexExecutable::getSignature(mRenderer, inputLayout, &mCachedVertexSignature);
Brandon Joneseb994362014-09-24 10:27:28 -07001044
1045 for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++)
1046 {
Jamie Madilld3dfda22015-07-06 08:28:49 -04001047 if (mVertexExecutables[executableIndex]->matchesSignature(mCachedVertexSignature))
Brandon Joneseb994362014-09-24 10:27:28 -07001048 {
Geoff Langb543aff2014-09-30 14:52:54 -04001049 *outExectuable = mVertexExecutables[executableIndex]->shaderExecutable();
1050 return gl::Error(GL_NO_ERROR);
Brandon Joneseb994362014-09-24 10:27:28 -07001051 }
1052 }
1053
Brandon Jones22502d52014-08-29 16:58:36 -07001054 // Generate new dynamic layout with attribute conversions
Jamie Madillc349ec02015-08-21 16:53:12 -04001055 std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout(
1056 mVertexHLSL, inputLayout, mData.getAttributes());
Brandon Jones22502d52014-08-29 16:58:36 -07001057
1058 // Generate new vertex executable
Geoff Lang359ef262015-01-05 14:42:29 -05001059 ShaderExecutableD3D *vertexExecutable = NULL;
Jamie Madill97399232014-12-23 12:31:15 -05001060
1061 gl::InfoLog tempInfoLog;
1062 gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
1063
Jamie Madillada9ecc2015-08-17 12:53:37 -04001064 gl::Error error = mRenderer->compileToExecutable(
1065 *currentInfoLog, finalVertexHLSL, SHADER_VERTEX, mTransformFeedbackLinkedVaryings,
1066 (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), mVertexWorkarounds,
1067 &vertexExecutable);
Geoff Langb543aff2014-09-30 14:52:54 -04001068 if (error.isError())
1069 {
1070 return error;
1071 }
1072
Jamie Madill97399232014-12-23 12:31:15 -05001073 if (vertexExecutable)
Brandon Joneseb994362014-09-24 10:27:28 -07001074 {
Jamie Madill334d6152015-10-22 14:00:28 -04001075 mVertexExecutables.push_back(
1076 new VertexExecutable(inputLayout, mCachedVertexSignature, vertexExecutable));
Brandon Joneseb994362014-09-24 10:27:28 -07001077 }
Jamie Madill97399232014-12-23 12:31:15 -05001078 else if (!infoLog)
1079 {
1080 std::vector<char> tempCharBuffer(tempInfoLog.getLength() + 3);
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001081 tempInfoLog.getLog(static_cast<GLsizei>(tempInfoLog.getLength()), NULL, &tempCharBuffer[0]);
Jamie Madill97399232014-12-23 12:31:15 -05001082 ERR("Error compiling dynamic vertex executable:\n%s\n", &tempCharBuffer[0]);
1083 }
Brandon Jones22502d52014-08-29 16:58:36 -07001084
Geoff Langb543aff2014-09-30 14:52:54 -04001085 *outExectuable = vertexExecutable;
1086 return gl::Error(GL_NO_ERROR);
Brandon Jones22502d52014-08-29 16:58:36 -07001087}
1088
Jamie Madill4e31ad52015-10-29 10:32:57 -04001089gl::Error ProgramD3D::getGeometryExecutableForPrimitiveType(const gl::Data &data,
1090 GLenum drawMode,
1091 ShaderExecutableD3D **outExecutable,
1092 gl::InfoLog *infoLog)
1093{
Jamie Madill3e14e2b2015-10-29 14:38:53 -04001094 if (outExecutable)
1095 {
1096 *outExecutable = nullptr;
1097 }
1098
1099 // We only uses a geometry shader for point sprite emulation, or for fixing the provoking
1100 // vertex problem. Otherwise, return a null shader.
1101 if (drawMode != GL_POINTS && !mUsesFlatInterpolation)
1102 {
1103 return gl::Error(GL_NO_ERROR);
1104 }
1105
Jamie Madill4e31ad52015-10-29 10:32:57 -04001106 gl::PrimitiveType geometryShaderType = GetGeometryShaderTypeFromDrawMode(drawMode);
1107
1108 if (mGeometryExecutables[geometryShaderType] != nullptr)
1109 {
1110 if (outExecutable)
1111 {
1112 *outExecutable = mGeometryExecutables[geometryShaderType];
1113 }
1114 return gl::Error(GL_NO_ERROR);
1115 }
1116
1117 std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL(
1118 geometryShaderType, data, mData, mGeometryShaderPreamble);
1119
1120 gl::InfoLog tempInfoLog;
1121 gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
1122
1123 gl::Error error = mRenderer->compileToExecutable(
1124 *currentInfoLog, geometryHLSL, SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings,
1125 (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), D3DCompilerWorkarounds(),
1126 &mGeometryExecutables[geometryShaderType]);
1127
1128 if (!infoLog && error.isError())
1129 {
1130 std::vector<char> tempCharBuffer(tempInfoLog.getLength() + 3);
1131 tempInfoLog.getLog(static_cast<GLsizei>(tempInfoLog.getLength()), NULL, &tempCharBuffer[0]);
1132 ERR("Error compiling dynamic geometry executable:\n%s\n", &tempCharBuffer[0]);
1133 }
1134
1135 if (outExecutable)
1136 {
1137 *outExecutable = mGeometryExecutables[geometryShaderType];
1138 }
1139 return error;
1140}
1141
1142LinkResult ProgramD3D::compileProgramExecutables(const gl::Data &data, gl::InfoLog &infoLog)
Brandon Jones44151a92014-09-10 11:32:25 -07001143{
Jamie Madill5c6b7bf2015-08-17 12:53:35 -04001144 const gl::InputLayout &defaultInputLayout =
1145 GetDefaultInputLayoutFromShader(mData.getAttachedVertexShader());
Jamie Madille4ea2022015-03-26 20:35:05 +00001146 ShaderExecutableD3D *defaultVertexExecutable = NULL;
Jamie Madill334d6152015-10-22 14:00:28 -04001147 gl::Error error =
1148 getVertexExecutableForInputLayout(defaultInputLayout, &defaultVertexExecutable, &infoLog);
Jamie Madille4ea2022015-03-26 20:35:05 +00001149 if (error.isError())
Austin Kinross434953e2015-02-20 10:49:51 -08001150 {
Jamie Madille4ea2022015-03-26 20:35:05 +00001151 return LinkResult(false, error);
1152 }
Austin Kinross434953e2015-02-20 10:49:51 -08001153
Jamie Madill334d6152015-10-22 14:00:28 -04001154 std::vector<GLenum> defaultPixelOutput = GetDefaultOutputLayoutFromShader(getPixelShaderKey());
Geoff Lang359ef262015-01-05 14:42:29 -05001155 ShaderExecutableD3D *defaultPixelExecutable = NULL;
Jamie Madill334d6152015-10-22 14:00:28 -04001156 error =
1157 getPixelExecutableForOutputLayout(defaultPixelOutput, &defaultPixelExecutable, &infoLog);
Geoff Langb543aff2014-09-30 14:52:54 -04001158 if (error.isError())
1159 {
Geoff Lang7dd2e102014-11-10 15:19:26 -05001160 return LinkResult(false, error);
Geoff Langb543aff2014-09-30 14:52:54 -04001161 }
Brandon Jones44151a92014-09-10 11:32:25 -07001162
Jamie Madill4e31ad52015-10-29 10:32:57 -04001163 // Auto-generate the geometry shader here, if we expect to be using point rendering in D3D11.
Jamie Madill3e14e2b2015-10-29 14:38:53 -04001164 if (usesGeometryShader(GL_POINTS))
Brandon Joneseb994362014-09-24 10:27:28 -07001165 {
Jamie Madill4e31ad52015-10-29 10:32:57 -04001166 getGeometryExecutableForPrimitiveType(data, GL_POINTS, nullptr, &infoLog);
Brandon Joneseb994362014-09-24 10:27:28 -07001167 }
1168
Brandon Jones091540d2014-10-29 11:32:04 -07001169#if ANGLE_SHADER_DEBUG_INFO == ANGLE_ENABLED
Jamie Madillca03b352015-09-02 12:38:13 -04001170 const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(mData.getAttachedVertexShader());
Tibor den Ouden97049c62014-10-06 21:39:16 +02001171 if (usesGeometryShader() && mGeometryExecutable)
1172 {
Jamie Madill334d6152015-10-22 14:00:28 -04001173 // Geometry shaders are currently only used internally, so there is no corresponding shader
1174 // object at the interface level. For now the geometry shader debug info is prepended to
1175 // the vertex shader.
Tibor den Ouden97049c62014-10-06 21:39:16 +02001176 vertexShaderD3D->appendDebugInfo("// GEOMETRY SHADER BEGIN\n\n");
1177 vertexShaderD3D->appendDebugInfo(mGeometryExecutable->getDebugInfo());
1178 vertexShaderD3D->appendDebugInfo("\nGEOMETRY SHADER END\n\n\n");
1179 }
1180
1181 if (defaultVertexExecutable)
1182 {
1183 vertexShaderD3D->appendDebugInfo(defaultVertexExecutable->getDebugInfo());
1184 }
1185
1186 if (defaultPixelExecutable)
1187 {
Jamie Madill76f8fa62015-10-29 10:32:56 -04001188 const ShaderD3D *fragmentShaderD3D =
1189 GetImplAs<ShaderD3D>(mData.getAttachedFragmentShader());
Tibor den Ouden97049c62014-10-06 21:39:16 +02001190 fragmentShaderD3D->appendDebugInfo(defaultPixelExecutable->getDebugInfo());
1191 }
1192#endif
1193
Jamie Madill3e14e2b2015-10-29 14:38:53 -04001194 bool linkSuccess =
1195 (defaultVertexExecutable && defaultPixelExecutable &&
1196 (!usesGeometryShader(GL_POINTS) || mGeometryExecutables[gl::PRIMITIVE_POINTS]));
Geoff Lang7dd2e102014-11-10 15:19:26 -05001197 return LinkResult(linkSuccess, gl::Error(GL_NO_ERROR));
Brandon Jones18bd4102014-09-22 14:21:44 -07001198}
1199
Jamie Madillf5f4ad22015-09-02 18:32:38 +00001200LinkResult ProgramD3D::link(const gl::Data &data, gl::InfoLog &infoLog)
Brandon Jones22502d52014-08-29 16:58:36 -07001201{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001202 reset();
1203
1204 // TODO(jmadill): structures containing samplers
1205 for (const gl::LinkedUniform &linkedUniform : mData.getUniforms())
1206 {
1207 if (linkedUniform.isSampler() && linkedUniform.isField())
1208 {
1209 infoLog << "Structures containing samplers not currently supported in D3D.";
1210 return LinkResult(false, gl::Error(GL_NO_ERROR));
1211 }
1212 }
1213
Jamie Madillf5f4ad22015-09-02 18:32:38 +00001214 const gl::Shader *vertexShader = mData.getAttachedVertexShader();
1215 const gl::Shader *fragmentShader = mData.getAttachedFragmentShader();
Brandon Joneseb994362014-09-24 10:27:28 -07001216
Jamie Madillf5f4ad22015-09-02 18:32:38 +00001217 const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(vertexShader);
1218 const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(fragmentShader);
1219
Jamie Madill63069df2015-09-01 17:26:41 +00001220 mSamplersVS.resize(data.caps->maxVertexTextureImageUnits);
Jamie Madillf5f4ad22015-09-02 18:32:38 +00001221 mSamplersPS.resize(data.caps->maxTextureImageUnits);
Brandon Jones22502d52014-08-29 16:58:36 -07001222
Arun Patole44efa0b2015-03-04 17:11:05 +05301223 vertexShaderD3D->generateWorkarounds(&mVertexWorkarounds);
Jamie Madillf5f4ad22015-09-02 18:32:38 +00001224 fragmentShaderD3D->generateWorkarounds(&mPixelWorkarounds);
1225
Austin Kinross02df7962015-07-01 10:03:42 -07001226 if (mRenderer->getRendererLimitations().noFrontFacingSupport)
1227 {
1228 if (fragmentShaderD3D->usesFrontFacing())
1229 {
1230 infoLog << "The current renderer doesn't support gl_FrontFacing";
1231 return LinkResult(false, gl::Error(GL_NO_ERROR));
1232 }
1233 }
1234
Jamie Madillca03b352015-09-02 12:38:13 -04001235 std::vector<PackedVarying> packedVaryings =
1236 MergeVaryings(*vertexShader, *fragmentShader, mData.getTransformFeedbackVaryingNames());
1237
Brandon Jones22502d52014-08-29 16:58:36 -07001238 // Map the varyings to the register file
Jamie Madill4e31ad52015-10-29 10:32:57 -04001239 unsigned int registerCount = 0;
1240 if (!mDynamicHLSL->packVaryings(*data.caps, infoLog, &packedVaryings,
1241 mData.getTransformFeedbackVaryingNames(), &registerCount))
Brandon Jones22502d52014-08-29 16:58:36 -07001242 {
Geoff Lang7dd2e102014-11-10 15:19:26 -05001243 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Jones22502d52014-08-29 16:58:36 -07001244 }
1245
Jamie Madillccdf74b2015-08-18 10:46:12 -04001246 std::vector<gl::LinkedVarying> linkedVaryings;
Jamie Madill4e31ad52015-10-29 10:32:57 -04001247 if (!mDynamicHLSL->generateShaderLinkHLSL(data, mData, infoLog, registerCount, &mPixelHLSL,
Jamie Madill334d6152015-10-22 14:00:28 -04001248 &mVertexHLSL, packedVaryings, &linkedVaryings,
Jamie Madillca03b352015-09-02 12:38:13 -04001249 &mPixelShaderKey, &mUsesFragDepth))
Brandon Jones22502d52014-08-29 16:58:36 -07001250 {
Geoff Lang7dd2e102014-11-10 15:19:26 -05001251 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Jones22502d52014-08-29 16:58:36 -07001252 }
1253
Brandon Jones44151a92014-09-10 11:32:25 -07001254 mUsesPointSize = vertexShaderD3D->usesPointSize();
1255
Jamie Madill3e14e2b2015-10-29 14:38:53 -04001256 // Cache if we use flat shading
1257 for (const auto &varying : packedVaryings)
1258 {
1259 if (varying.varying->interpolation == sh::INTERPOLATION_FLAT)
1260 {
1261 mUsesFlatInterpolation = true;
1262 break;
1263 }
1264 }
1265
Jamie Madill4e31ad52015-10-29 10:32:57 -04001266 if (mRenderer->getMajorShaderModel() >= 4)
1267 {
1268 mGeometryShaderPreamble = mDynamicHLSL->generateGeometryShaderPreamble(
1269 data, mData, registerCount, packedVaryings);
1270 }
1271
Jamie Madill63805b42015-08-25 13:17:39 -04001272 initSemanticIndex();
Jamie Madill437d2662014-12-05 14:23:35 -05001273
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001274 defineUniformsAndAssignRegisters();
Jamie Madille473dee2015-08-18 14:49:01 -04001275
Jamie Madillccdf74b2015-08-18 10:46:12 -04001276 gatherTransformFeedbackVaryings(linkedVaryings);
1277
Jamie Madill4e31ad52015-10-29 10:32:57 -04001278 LinkResult result = compileProgramExecutables(data, infoLog);
Jamie Madill31c8c562015-08-19 14:08:03 -04001279 if (result.error.isError() || !result.linkSuccess)
1280 {
1281 infoLog << "Failed to create D3D shaders.";
1282 return result;
1283 }
1284
Jamie Madill4a3c2342015-10-08 12:58:45 -04001285 initUniformBlockInfo();
1286
Geoff Lang7dd2e102014-11-10 15:19:26 -05001287 return LinkResult(true, gl::Error(GL_NO_ERROR));
Brandon Jones22502d52014-08-29 16:58:36 -07001288}
1289
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001290GLboolean ProgramD3D::validate(const gl::Caps & /*caps*/, gl::InfoLog * /*infoLog*/)
Jamie Madill36cfd6a2015-08-18 10:46:20 -04001291{
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001292 // TODO(jmadill): Do something useful here?
1293 return GL_TRUE;
Jamie Madill36cfd6a2015-08-18 10:46:20 -04001294}
1295
Jamie Madill4a3c2342015-10-08 12:58:45 -04001296void ProgramD3D::initUniformBlockInfo()
Jamie Madill62d31cb2015-09-11 13:25:51 -04001297{
1298 const gl::Shader *vertexShader = mData.getAttachedVertexShader();
1299
Jamie Madill62d31cb2015-09-11 13:25:51 -04001300 for (const sh::InterfaceBlock &vertexBlock : vertexShader->getInterfaceBlocks())
1301 {
1302 if (!vertexBlock.staticUse && vertexBlock.layout == sh::BLOCKLAYOUT_PACKED)
1303 continue;
1304
Jamie Madill4a3c2342015-10-08 12:58:45 -04001305 if (mBlockDataSizes.count(vertexBlock.name) > 0)
Jamie Madill62d31cb2015-09-11 13:25:51 -04001306 continue;
1307
Jamie Madill4a3c2342015-10-08 12:58:45 -04001308 size_t dataSize = getUniformBlockInfo(vertexBlock);
1309 mBlockDataSizes[vertexBlock.name] = dataSize;
Jamie Madill62d31cb2015-09-11 13:25:51 -04001310 }
1311
1312 const gl::Shader *fragmentShader = mData.getAttachedFragmentShader();
1313
1314 for (const sh::InterfaceBlock &fragmentBlock : fragmentShader->getInterfaceBlocks())
1315 {
1316 if (!fragmentBlock.staticUse && fragmentBlock.layout == sh::BLOCKLAYOUT_PACKED)
1317 continue;
1318
Jamie Madill4a3c2342015-10-08 12:58:45 -04001319 if (mBlockDataSizes.count(fragmentBlock.name) > 0)
Jamie Madill62d31cb2015-09-11 13:25:51 -04001320 continue;
1321
Jamie Madill4a3c2342015-10-08 12:58:45 -04001322 size_t dataSize = getUniformBlockInfo(fragmentBlock);
1323 mBlockDataSizes[fragmentBlock.name] = dataSize;
Jamie Madill62d31cb2015-09-11 13:25:51 -04001324 }
Jamie Madill4a3c2342015-10-08 12:58:45 -04001325}
Jamie Madill62d31cb2015-09-11 13:25:51 -04001326
Jamie Madill4a3c2342015-10-08 12:58:45 -04001327void ProgramD3D::assignUniformBlockRegisters()
1328{
1329 mD3DUniformBlocks.clear();
Jamie Madill62d31cb2015-09-11 13:25:51 -04001330
1331 // Assign registers and update sizes.
Jamie Madill4a3c2342015-10-08 12:58:45 -04001332 const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(mData.getAttachedVertexShader());
1333 const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(mData.getAttachedFragmentShader());
Jamie Madill62d31cb2015-09-11 13:25:51 -04001334
Jamie Madill4a3c2342015-10-08 12:58:45 -04001335 for (const gl::UniformBlock &uniformBlock : mData.getUniformBlocks())
Jamie Madill62d31cb2015-09-11 13:25:51 -04001336 {
1337 unsigned int uniformBlockElement = uniformBlock.isArray ? uniformBlock.arrayElement : 0;
1338
Jamie Madill4a3c2342015-10-08 12:58:45 -04001339 D3DUniformBlock d3dUniformBlock;
1340
Jamie Madill62d31cb2015-09-11 13:25:51 -04001341 if (uniformBlock.vertexStaticUse)
1342 {
1343 unsigned int baseRegister =
1344 vertexShaderD3D->getInterfaceBlockRegister(uniformBlock.name);
Jamie Madill4a3c2342015-10-08 12:58:45 -04001345 d3dUniformBlock.vsRegisterIndex = baseRegister + uniformBlockElement;
Jamie Madill62d31cb2015-09-11 13:25:51 -04001346 }
1347
1348 if (uniformBlock.fragmentStaticUse)
1349 {
1350 unsigned int baseRegister =
1351 fragmentShaderD3D->getInterfaceBlockRegister(uniformBlock.name);
Jamie Madill4a3c2342015-10-08 12:58:45 -04001352 d3dUniformBlock.psRegisterIndex = baseRegister + uniformBlockElement;
Jamie Madill62d31cb2015-09-11 13:25:51 -04001353 }
1354
Jamie Madill4a3c2342015-10-08 12:58:45 -04001355 mD3DUniformBlocks.push_back(d3dUniformBlock);
Jamie Madill62d31cb2015-09-11 13:25:51 -04001356 }
1357}
1358
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001359void ProgramD3D::initializeUniformStorage()
Brandon Jonesc9610c52014-08-25 17:02:59 -07001360{
1361 // Compute total default block size
Jamie Madill334d6152015-10-22 14:00:28 -04001362 unsigned int vertexRegisters = 0;
Brandon Jonesc9610c52014-08-25 17:02:59 -07001363 unsigned int fragmentRegisters = 0;
Jamie Madill62d31cb2015-09-11 13:25:51 -04001364 for (const D3DUniform *d3dUniform : mD3DUniforms)
Brandon Jonesc9610c52014-08-25 17:02:59 -07001365 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001366 if (!d3dUniform->isSampler())
Brandon Jonesc9610c52014-08-25 17:02:59 -07001367 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001368 if (d3dUniform->isReferencedByVertexShader())
Brandon Jonesc9610c52014-08-25 17:02:59 -07001369 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001370 vertexRegisters = std::max(vertexRegisters,
1371 d3dUniform->vsRegisterIndex + d3dUniform->registerCount);
Brandon Jonesc9610c52014-08-25 17:02:59 -07001372 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04001373 if (d3dUniform->isReferencedByFragmentShader())
Brandon Jonesc9610c52014-08-25 17:02:59 -07001374 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001375 fragmentRegisters = std::max(
1376 fragmentRegisters, d3dUniform->psRegisterIndex + d3dUniform->registerCount);
Brandon Jonesc9610c52014-08-25 17:02:59 -07001377 }
1378 }
1379 }
1380
Jamie Madill334d6152015-10-22 14:00:28 -04001381 mVertexUniformStorage = mRenderer->createUniformStorage(vertexRegisters * 16u);
Brandon Jonesc9610c52014-08-25 17:02:59 -07001382 mFragmentUniformStorage = mRenderer->createUniformStorage(fragmentRegisters * 16u);
1383}
1384
Jamie Madill3e14e2b2015-10-29 14:38:53 -04001385gl::Error ProgramD3D::applyUniforms(GLenum drawMode)
Brandon Jones18bd4102014-09-22 14:21:44 -07001386{
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001387 updateSamplerMapping();
1388
Jamie Madill3e14e2b2015-10-29 14:38:53 -04001389 gl::Error error = mRenderer->applyUniforms(*this, drawMode, mD3DUniforms);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001390 if (error.isError())
1391 {
1392 return error;
1393 }
1394
Jamie Madill62d31cb2015-09-11 13:25:51 -04001395 for (D3DUniform *d3dUniform : mD3DUniforms)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001396 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001397 d3dUniform->dirty = false;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001398 }
1399
1400 return gl::Error(GL_NO_ERROR);
Brandon Jones18bd4102014-09-22 14:21:44 -07001401}
1402
Jamie Madilld1fe1642015-08-21 16:26:04 -04001403gl::Error ProgramD3D::applyUniformBuffers(const gl::Data &data)
Brandon Jones18bd4102014-09-22 14:21:44 -07001404{
Jamie Madill4a3c2342015-10-08 12:58:45 -04001405 if (mData.getUniformBlocks().empty())
1406 {
1407 return gl::Error(GL_NO_ERROR);
1408 }
1409
1410 // Lazy init.
1411 if (mD3DUniformBlocks.empty())
1412 {
1413 assignUniformBlockRegisters();
1414 }
1415
Jamie Madill03260fa2015-06-22 13:57:22 -04001416 mVertexUBOCache.clear();
1417 mFragmentUBOCache.clear();
Brandon Jones18bd4102014-09-22 14:21:44 -07001418
1419 const unsigned int reservedBuffersInVS = mRenderer->getReservedVertexUniformBuffers();
1420 const unsigned int reservedBuffersInFS = mRenderer->getReservedFragmentUniformBuffers();
1421
Jamie Madill4a3c2342015-10-08 12:58:45 -04001422 for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < mD3DUniformBlocks.size();
Jamie Madill62d31cb2015-09-11 13:25:51 -04001423 uniformBlockIndex++)
Brandon Jones18bd4102014-09-22 14:21:44 -07001424 {
Jamie Madill4a3c2342015-10-08 12:58:45 -04001425 const D3DUniformBlock &uniformBlock = mD3DUniformBlocks[uniformBlockIndex];
1426 GLuint blockBinding = mData.getUniformBlockBinding(uniformBlockIndex);
Brandon Jones18bd4102014-09-22 14:21:44 -07001427
Brandon Jones18bd4102014-09-22 14:21:44 -07001428 // Unnecessary to apply an unreferenced standard or shared UBO
Jamie Madill4a3c2342015-10-08 12:58:45 -04001429 if (!uniformBlock.vertexStaticUse() && !uniformBlock.fragmentStaticUse())
Brandon Jones18bd4102014-09-22 14:21:44 -07001430 {
1431 continue;
1432 }
1433
Jamie Madill4a3c2342015-10-08 12:58:45 -04001434 if (uniformBlock.vertexStaticUse())
Brandon Jones18bd4102014-09-22 14:21:44 -07001435 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001436 unsigned int registerIndex = uniformBlock.vsRegisterIndex - reservedBuffersInVS;
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00001437 ASSERT(registerIndex < data.caps->maxVertexUniformBlocks);
Jamie Madill03260fa2015-06-22 13:57:22 -04001438
Jamie Madill969194d2015-07-20 14:36:56 -04001439 if (mVertexUBOCache.size() <= registerIndex)
Jamie Madill03260fa2015-06-22 13:57:22 -04001440 {
1441 mVertexUBOCache.resize(registerIndex + 1, -1);
1442 }
1443
1444 ASSERT(mVertexUBOCache[registerIndex] == -1);
1445 mVertexUBOCache[registerIndex] = blockBinding;
Brandon Jones18bd4102014-09-22 14:21:44 -07001446 }
1447
Jamie Madill4a3c2342015-10-08 12:58:45 -04001448 if (uniformBlock.fragmentStaticUse())
Brandon Jones18bd4102014-09-22 14:21:44 -07001449 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001450 unsigned int registerIndex = uniformBlock.psRegisterIndex - reservedBuffersInFS;
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00001451 ASSERT(registerIndex < data.caps->maxFragmentUniformBlocks);
Jamie Madill03260fa2015-06-22 13:57:22 -04001452
1453 if (mFragmentUBOCache.size() <= registerIndex)
1454 {
1455 mFragmentUBOCache.resize(registerIndex + 1, -1);
1456 }
1457
1458 ASSERT(mFragmentUBOCache[registerIndex] == -1);
1459 mFragmentUBOCache[registerIndex] = blockBinding;
Brandon Jones18bd4102014-09-22 14:21:44 -07001460 }
1461 }
1462
Jamie Madill03260fa2015-06-22 13:57:22 -04001463 return mRenderer->setUniformBuffers(data, mVertexUBOCache, mFragmentUBOCache);
Brandon Jones18bd4102014-09-22 14:21:44 -07001464}
1465
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001466void ProgramD3D::dirtyAllUniforms()
Brandon Jones18bd4102014-09-22 14:21:44 -07001467{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001468 for (D3DUniform *d3dUniform : mD3DUniforms)
Brandon Jones18bd4102014-09-22 14:21:44 -07001469 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001470 d3dUniform->dirty = true;
Brandon Jones18bd4102014-09-22 14:21:44 -07001471 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001472}
1473
Jamie Madill334d6152015-10-22 14:00:28 -04001474void ProgramD3D::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001475{
1476 setUniform(location, count, v, GL_FLOAT);
1477}
1478
1479void ProgramD3D::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
1480{
1481 setUniform(location, count, v, GL_FLOAT_VEC2);
1482}
1483
1484void ProgramD3D::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
1485{
1486 setUniform(location, count, v, GL_FLOAT_VEC3);
1487}
1488
1489void ProgramD3D::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
1490{
1491 setUniform(location, count, v, GL_FLOAT_VEC4);
1492}
1493
Jamie Madill334d6152015-10-22 14:00:28 -04001494void ProgramD3D::setUniformMatrix2fv(GLint location,
1495 GLsizei count,
1496 GLboolean transpose,
1497 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001498{
1499 setUniformMatrixfv<2, 2>(location, count, transpose, value, GL_FLOAT_MAT2);
1500}
1501
Jamie Madill334d6152015-10-22 14:00:28 -04001502void ProgramD3D::setUniformMatrix3fv(GLint location,
1503 GLsizei count,
1504 GLboolean transpose,
1505 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001506{
1507 setUniformMatrixfv<3, 3>(location, count, transpose, value, GL_FLOAT_MAT3);
1508}
1509
Jamie Madill334d6152015-10-22 14:00:28 -04001510void ProgramD3D::setUniformMatrix4fv(GLint location,
1511 GLsizei count,
1512 GLboolean transpose,
1513 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001514{
1515 setUniformMatrixfv<4, 4>(location, count, transpose, value, GL_FLOAT_MAT4);
1516}
1517
Jamie Madill334d6152015-10-22 14:00:28 -04001518void ProgramD3D::setUniformMatrix2x3fv(GLint location,
1519 GLsizei count,
1520 GLboolean transpose,
1521 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001522{
1523 setUniformMatrixfv<2, 3>(location, count, transpose, value, GL_FLOAT_MAT2x3);
1524}
1525
Jamie Madill334d6152015-10-22 14:00:28 -04001526void ProgramD3D::setUniformMatrix3x2fv(GLint location,
1527 GLsizei count,
1528 GLboolean transpose,
1529 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001530{
1531 setUniformMatrixfv<3, 2>(location, count, transpose, value, GL_FLOAT_MAT3x2);
1532}
1533
Jamie Madill334d6152015-10-22 14:00:28 -04001534void ProgramD3D::setUniformMatrix2x4fv(GLint location,
1535 GLsizei count,
1536 GLboolean transpose,
1537 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001538{
1539 setUniformMatrixfv<2, 4>(location, count, transpose, value, GL_FLOAT_MAT2x4);
1540}
1541
Jamie Madill334d6152015-10-22 14:00:28 -04001542void ProgramD3D::setUniformMatrix4x2fv(GLint location,
1543 GLsizei count,
1544 GLboolean transpose,
1545 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001546{
1547 setUniformMatrixfv<4, 2>(location, count, transpose, value, GL_FLOAT_MAT4x2);
1548}
1549
Jamie Madill334d6152015-10-22 14:00:28 -04001550void ProgramD3D::setUniformMatrix3x4fv(GLint location,
1551 GLsizei count,
1552 GLboolean transpose,
1553 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001554{
1555 setUniformMatrixfv<3, 4>(location, count, transpose, value, GL_FLOAT_MAT3x4);
1556}
1557
Jamie Madill334d6152015-10-22 14:00:28 -04001558void ProgramD3D::setUniformMatrix4x3fv(GLint location,
1559 GLsizei count,
1560 GLboolean transpose,
1561 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001562{
1563 setUniformMatrixfv<4, 3>(location, count, transpose, value, GL_FLOAT_MAT4x3);
1564}
1565
1566void ProgramD3D::setUniform1iv(GLint location, GLsizei count, const GLint *v)
1567{
1568 setUniform(location, count, v, GL_INT);
1569}
1570
1571void ProgramD3D::setUniform2iv(GLint location, GLsizei count, const GLint *v)
1572{
1573 setUniform(location, count, v, GL_INT_VEC2);
1574}
1575
1576void ProgramD3D::setUniform3iv(GLint location, GLsizei count, const GLint *v)
1577{
1578 setUniform(location, count, v, GL_INT_VEC3);
1579}
1580
1581void ProgramD3D::setUniform4iv(GLint location, GLsizei count, const GLint *v)
1582{
1583 setUniform(location, count, v, GL_INT_VEC4);
1584}
1585
1586void ProgramD3D::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
1587{
1588 setUniform(location, count, v, GL_UNSIGNED_INT);
1589}
1590
1591void ProgramD3D::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
1592{
1593 setUniform(location, count, v, GL_UNSIGNED_INT_VEC2);
1594}
1595
1596void ProgramD3D::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
1597{
1598 setUniform(location, count, v, GL_UNSIGNED_INT_VEC3);
1599}
1600
1601void ProgramD3D::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
1602{
1603 setUniform(location, count, v, GL_UNSIGNED_INT_VEC4);
1604}
1605
Jamie Madill4a3c2342015-10-08 12:58:45 -04001606void ProgramD3D::setUniformBlockBinding(GLuint /*uniformBlockIndex*/,
1607 GLuint /*uniformBlockBinding*/)
Geoff Lang5d124a62015-09-15 13:03:27 -04001608{
1609}
1610
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001611void ProgramD3D::defineUniformsAndAssignRegisters()
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001612{
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001613 D3DUniformMap uniformMap;
Jamie Madill334d6152015-10-22 14:00:28 -04001614 const gl::Shader *vertexShader = mData.getAttachedVertexShader();
Jamie Madill62d31cb2015-09-11 13:25:51 -04001615 for (const sh::Uniform &vertexUniform : vertexShader->getUniforms())
Jamie Madillfb536032015-09-11 13:19:49 -04001616
Jamie Madilla2eb02c2015-09-11 12:31:41 +00001617 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001618 if (vertexUniform.staticUse)
Jamie Madillfb536032015-09-11 13:19:49 -04001619 {
Jamie Madill91445bc2015-09-23 16:47:53 -04001620 defineUniformBase(vertexShader, vertexUniform, &uniformMap);
Jamie Madillfb536032015-09-11 13:19:49 -04001621 }
1622 }
1623
Jamie Madill334d6152015-10-22 14:00:28 -04001624 const gl::Shader *fragmentShader = mData.getAttachedFragmentShader();
Jamie Madill62d31cb2015-09-11 13:25:51 -04001625 for (const sh::Uniform &fragmentUniform : fragmentShader->getUniforms())
Jamie Madillfb536032015-09-11 13:19:49 -04001626 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001627 if (fragmentUniform.staticUse)
Jamie Madillfb536032015-09-11 13:19:49 -04001628 {
Jamie Madill91445bc2015-09-23 16:47:53 -04001629 defineUniformBase(fragmentShader, fragmentUniform, &uniformMap);
Jamie Madillfb536032015-09-11 13:19:49 -04001630 }
1631 }
1632
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001633 // Initialize the D3DUniform list to mirror the indexing of the GL layer.
1634 for (const gl::LinkedUniform &glUniform : mData.getUniforms())
1635 {
1636 if (!glUniform.isInDefaultBlock())
1637 continue;
1638
1639 auto mapEntry = uniformMap.find(glUniform.name);
1640 ASSERT(mapEntry != uniformMap.end());
1641 mD3DUniforms.push_back(mapEntry->second);
1642 }
1643
Jamie Madill62d31cb2015-09-11 13:25:51 -04001644 assignAllSamplerRegisters();
Jamie Madillfb536032015-09-11 13:19:49 -04001645 initializeUniformStorage();
Jamie Madillfb536032015-09-11 13:19:49 -04001646}
1647
Jamie Madill91445bc2015-09-23 16:47:53 -04001648void ProgramD3D::defineUniformBase(const gl::Shader *shader,
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001649 const sh::Uniform &uniform,
1650 D3DUniformMap *uniformMap)
Jamie Madillfb536032015-09-11 13:19:49 -04001651{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001652 if (uniform.isBuiltIn())
Jamie Madillfb536032015-09-11 13:19:49 -04001653 {
Jamie Madill91445bc2015-09-23 16:47:53 -04001654 defineUniform(shader->getType(), uniform, uniform.name, nullptr, uniformMap);
Jamie Madill55def582015-05-04 11:24:57 -04001655 return;
1656 }
1657
Jamie Madill91445bc2015-09-23 16:47:53 -04001658 const ShaderD3D *shaderD3D = GetImplAs<ShaderD3D>(shader);
1659
1660 unsigned int startRegister = shaderD3D->getUniformRegister(uniform.name);
1661 ShShaderOutput outputType = shaderD3D->getCompilerOutputType();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001662 sh::HLSLBlockEncoder encoder(sh::HLSLBlockEncoder::GetStrategyFor(outputType));
Jamie Madill62d31cb2015-09-11 13:25:51 -04001663 encoder.skipRegisters(startRegister);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001664
Jamie Madill91445bc2015-09-23 16:47:53 -04001665 defineUniform(shader->getType(), uniform, uniform.name, &encoder, uniformMap);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001666}
1667
Jamie Madill62d31cb2015-09-11 13:25:51 -04001668D3DUniform *ProgramD3D::getD3DUniformByName(const std::string &name)
1669{
1670 for (D3DUniform *d3dUniform : mD3DUniforms)
1671 {
1672 if (d3dUniform->name == name)
1673 {
1674 return d3dUniform;
1675 }
1676 }
1677
1678 return nullptr;
1679}
1680
Jamie Madill91445bc2015-09-23 16:47:53 -04001681void ProgramD3D::defineUniform(GLenum shaderType,
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001682 const sh::ShaderVariable &uniform,
1683 const std::string &fullName,
1684 sh::HLSLBlockEncoder *encoder,
1685 D3DUniformMap *uniformMap)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001686{
1687 if (uniform.isStruct())
1688 {
1689 for (unsigned int elementIndex = 0; elementIndex < uniform.elementCount(); elementIndex++)
1690 {
1691 const std::string &elementString = (uniform.isArray() ? ArrayString(elementIndex) : "");
1692
Jamie Madill55def582015-05-04 11:24:57 -04001693 if (encoder)
1694 encoder->enterAggregateType();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001695
1696 for (size_t fieldIndex = 0; fieldIndex < uniform.fields.size(); fieldIndex++)
1697 {
Jamie Madill334d6152015-10-22 14:00:28 -04001698 const sh::ShaderVariable &field = uniform.fields[fieldIndex];
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001699 const std::string &fieldFullName = (fullName + elementString + "." + field.name);
1700
Jamie Madill91445bc2015-09-23 16:47:53 -04001701 defineUniform(shaderType, field, fieldFullName, encoder, uniformMap);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001702 }
1703
Jamie Madill55def582015-05-04 11:24:57 -04001704 if (encoder)
1705 encoder->exitAggregateType();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001706 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04001707 return;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001708 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04001709
1710 // Not a struct. Arrays are treated as aggregate types.
1711 if (uniform.isArray() && encoder)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001712 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001713 encoder->enterAggregateType();
1714 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001715
Jamie Madill62d31cb2015-09-11 13:25:51 -04001716 // Advance the uniform offset, to track registers allocation for structs
1717 sh::BlockMemberInfo blockInfo =
1718 encoder ? encoder->encodeType(uniform.type, uniform.arraySize, false)
1719 : sh::BlockMemberInfo::getDefaultBlockInfo();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001720
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001721 auto uniformMapEntry = uniformMap->find(fullName);
1722 D3DUniform *d3dUniform = nullptr;
Jamie Madill2857f482015-02-09 15:35:29 -05001723
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001724 if (uniformMapEntry != uniformMap->end())
Jamie Madill62d31cb2015-09-11 13:25:51 -04001725 {
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001726 d3dUniform = uniformMapEntry->second;
1727 }
1728 else
1729 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001730 d3dUniform = new D3DUniform(uniform.type, fullName, uniform.arraySize, true);
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001731 (*uniformMap)[fullName] = d3dUniform;
Jamie Madill62d31cb2015-09-11 13:25:51 -04001732 }
1733
1734 if (encoder)
1735 {
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001736 d3dUniform->registerElement =
1737 static_cast<unsigned int>(sh::HLSLBlockEncoder::getBlockRegisterElement(blockInfo));
Jamie Madill62d31cb2015-09-11 13:25:51 -04001738 unsigned int reg =
1739 static_cast<unsigned int>(sh::HLSLBlockEncoder::getBlockRegister(blockInfo));
Jamie Madill91445bc2015-09-23 16:47:53 -04001740 if (shaderType == GL_FRAGMENT_SHADER)
Jamie Madill62d31cb2015-09-11 13:25:51 -04001741 {
1742 d3dUniform->psRegisterIndex = reg;
1743 }
Jamie Madill91445bc2015-09-23 16:47:53 -04001744 else
Jamie Madill62d31cb2015-09-11 13:25:51 -04001745 {
Jamie Madill91445bc2015-09-23 16:47:53 -04001746 ASSERT(shaderType == GL_VERTEX_SHADER);
Jamie Madill62d31cb2015-09-11 13:25:51 -04001747 d3dUniform->vsRegisterIndex = reg;
1748 }
Jamie Madillfb536032015-09-11 13:19:49 -04001749
1750 // Arrays are treated as aggregate types
Jamie Madill62d31cb2015-09-11 13:25:51 -04001751 if (uniform.isArray())
Jamie Madillfb536032015-09-11 13:19:49 -04001752 {
1753 encoder->exitAggregateType();
1754 }
1755 }
1756}
1757
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001758template <typename T>
Jamie Madill334d6152015-10-22 14:00:28 -04001759static inline void SetIfDirty(T *dest, const T &source, bool *dirtyFlag)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001760{
1761 ASSERT(dest != NULL);
1762 ASSERT(dirtyFlag != NULL);
1763
1764 *dirtyFlag = *dirtyFlag || (memcmp(dest, &source, sizeof(T)) != 0);
Jamie Madill334d6152015-10-22 14:00:28 -04001765 *dest = source;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001766}
1767
1768template <typename T>
Jamie Madill62d31cb2015-09-11 13:25:51 -04001769void ProgramD3D::setUniform(GLint location, GLsizei countIn, const T *v, GLenum targetUniformType)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001770{
Jamie Madill334d6152015-10-22 14:00:28 -04001771 const int components = gl::VariableComponentCount(targetUniformType);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001772 const GLenum targetBoolType = gl::VariableBoolVectorType(targetUniformType);
1773
Jamie Madill62d31cb2015-09-11 13:25:51 -04001774 D3DUniform *targetUniform = getD3DUniformFromLocation(location);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001775
Jamie Madill62d31cb2015-09-11 13:25:51 -04001776 unsigned int elementCount = targetUniform->elementCount();
1777 unsigned int arrayElement = mData.getUniformLocations()[location].element;
1778 unsigned int count = std::min(elementCount - arrayElement, static_cast<unsigned int>(countIn));
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001779
1780 if (targetUniform->type == targetUniformType)
1781 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001782 T *target = reinterpret_cast<T *>(targetUniform->data) + arrayElement * 4;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001783
Jamie Madill62d31cb2015-09-11 13:25:51 -04001784 for (unsigned int i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001785 {
Jamie Madill334d6152015-10-22 14:00:28 -04001786 T *dest = target + (i * 4);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001787 const T *source = v + (i * components);
1788
1789 for (int c = 0; c < components; c++)
1790 {
1791 SetIfDirty(dest + c, source[c], &targetUniform->dirty);
1792 }
1793 for (int c = components; c < 4; c++)
1794 {
1795 SetIfDirty(dest + c, T(0), &targetUniform->dirty);
1796 }
1797 }
1798 }
1799 else if (targetUniform->type == targetBoolType)
1800 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001801 GLint *boolParams = reinterpret_cast<GLint *>(targetUniform->data) + arrayElement * 4;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001802
Jamie Madill62d31cb2015-09-11 13:25:51 -04001803 for (unsigned int i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001804 {
Jamie Madill334d6152015-10-22 14:00:28 -04001805 GLint *dest = boolParams + (i * 4);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001806 const T *source = v + (i * components);
1807
1808 for (int c = 0; c < components; c++)
1809 {
Jamie Madill334d6152015-10-22 14:00:28 -04001810 SetIfDirty(dest + c, (source[c] == static_cast<T>(0)) ? GL_FALSE : GL_TRUE,
1811 &targetUniform->dirty);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001812 }
1813 for (int c = components; c < 4; c++)
1814 {
1815 SetIfDirty(dest + c, GL_FALSE, &targetUniform->dirty);
1816 }
1817 }
1818 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04001819 else if (targetUniform->isSampler())
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001820 {
1821 ASSERT(targetUniformType == GL_INT);
1822
Jamie Madill62d31cb2015-09-11 13:25:51 -04001823 GLint *target = reinterpret_cast<GLint *>(targetUniform->data) + arrayElement * 4;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001824
1825 bool wasDirty = targetUniform->dirty;
1826
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 = target + (i * 4);
1830 const GLint *source = reinterpret_cast<const GLint *>(v) + (i * components);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001831
1832 SetIfDirty(dest + 0, source[0], &targetUniform->dirty);
1833 SetIfDirty(dest + 1, 0, &targetUniform->dirty);
1834 SetIfDirty(dest + 2, 0, &targetUniform->dirty);
1835 SetIfDirty(dest + 3, 0, &targetUniform->dirty);
1836 }
1837
1838 if (!wasDirty && targetUniform->dirty)
1839 {
1840 mDirtySamplerMapping = true;
1841 }
Brandon Jones18bd4102014-09-22 14:21:44 -07001842 }
Jamie Madill334d6152015-10-22 14:00:28 -04001843 else
1844 UNREACHABLE();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001845}
1846
1847template <int cols, int rows>
Jamie Madill62d31cb2015-09-11 13:25:51 -04001848void ProgramD3D::setUniformMatrixfv(GLint location,
1849 GLsizei countIn,
1850 GLboolean transpose,
1851 const GLfloat *value,
1852 GLenum targetUniformType)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001853{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001854 D3DUniform *targetUniform = getD3DUniformFromLocation(location);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001855
Jamie Madill62d31cb2015-09-11 13:25:51 -04001856 unsigned int elementCount = targetUniform->elementCount();
1857 unsigned int arrayElement = mData.getUniformLocations()[location].element;
1858 unsigned int count = std::min(elementCount - arrayElement, static_cast<unsigned int>(countIn));
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001859
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001860 const unsigned int targetMatrixStride = (4 * rows);
Jamie Madill62d31cb2015-09-11 13:25:51 -04001861 GLfloat *target =
1862 (GLfloat *)(targetUniform->data + arrayElement * sizeof(GLfloat) * targetMatrixStride);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001863
Jamie Madill62d31cb2015-09-11 13:25:51 -04001864 for (unsigned int i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001865 {
1866 // Internally store matrices as transposed versions to accomodate HLSL matrix indexing
1867 if (transpose == GL_FALSE)
1868 {
Jamie Madill334d6152015-10-22 14:00:28 -04001869 targetUniform->dirty = TransposeMatrix<GLfloat>(target, value, 4, rows, rows, cols) ||
1870 targetUniform->dirty;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001871 }
1872 else
1873 {
Jamie Madill334d6152015-10-22 14:00:28 -04001874 targetUniform->dirty =
1875 ExpandMatrix<GLfloat>(target, value, 4, rows, cols, rows) || targetUniform->dirty;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001876 }
1877 target += targetMatrixStride;
1878 value += cols * rows;
1879 }
1880}
1881
Jamie Madill4a3c2342015-10-08 12:58:45 -04001882size_t ProgramD3D::getUniformBlockInfo(const sh::InterfaceBlock &interfaceBlock)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001883{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001884 ASSERT(interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001885
Jamie Madill62d31cb2015-09-11 13:25:51 -04001886 // define member uniforms
1887 sh::Std140BlockEncoder std140Encoder;
1888 sh::HLSLBlockEncoder hlslEncoder(sh::HLSLBlockEncoder::ENCODE_PACKED);
1889 sh::BlockLayoutEncoder *encoder = nullptr;
1890
1891 if (interfaceBlock.layout == sh::BLOCKLAYOUT_STANDARD)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001892 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001893 encoder = &std140Encoder;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001894 }
1895 else
1896 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001897 encoder = &hlslEncoder;
Jamie Madill61b8dd92015-09-09 19:04:04 +00001898 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04001899
1900 GetUniformBlockInfo(interfaceBlock.fields, "", encoder, interfaceBlock.isRowMajorLayout,
Jamie Madill4a3c2342015-10-08 12:58:45 -04001901 &mBlockInfo);
Jamie Madill62d31cb2015-09-11 13:25:51 -04001902
1903 return encoder->getBlockSize();
Jamie Madill61b8dd92015-09-09 19:04:04 +00001904}
1905
Jamie Madill62d31cb2015-09-11 13:25:51 -04001906void ProgramD3D::assignAllSamplerRegisters()
Jamie Madilla2eb02c2015-09-11 12:31:41 +00001907{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001908 for (const D3DUniform *d3dUniform : mD3DUniforms)
Jamie Madilla2eb02c2015-09-11 12:31:41 +00001909 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001910 if (d3dUniform->isSampler())
Jamie Madillfb536032015-09-11 13:19:49 -04001911 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001912 assignSamplerRegisters(d3dUniform);
Jamie Madillfb536032015-09-11 13:19:49 -04001913 }
Jamie Madilla2eb02c2015-09-11 12:31:41 +00001914 }
1915}
1916
Jamie Madill62d31cb2015-09-11 13:25:51 -04001917void ProgramD3D::assignSamplerRegisters(const D3DUniform *d3dUniform)
Jamie Madillfb536032015-09-11 13:19:49 -04001918{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001919 ASSERT(d3dUniform->isSampler());
1920 ASSERT(d3dUniform->vsRegisterIndex != GL_INVALID_INDEX ||
1921 d3dUniform->psRegisterIndex != GL_INVALID_INDEX);
Jamie Madillfb536032015-09-11 13:19:49 -04001922
Jamie Madill62d31cb2015-09-11 13:25:51 -04001923 if (d3dUniform->vsRegisterIndex != GL_INVALID_INDEX)
Jamie Madillfb536032015-09-11 13:19:49 -04001924 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001925 AssignSamplers(d3dUniform->vsRegisterIndex, d3dUniform->type, d3dUniform->arraySize,
1926 mSamplersVS, &mUsedVertexSamplerRange);
Jamie Madillfb536032015-09-11 13:19:49 -04001927 }
1928
Jamie Madill62d31cb2015-09-11 13:25:51 -04001929 if (d3dUniform->psRegisterIndex != GL_INVALID_INDEX)
Jamie Madillfb536032015-09-11 13:19:49 -04001930 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001931 AssignSamplers(d3dUniform->psRegisterIndex, d3dUniform->type, d3dUniform->arraySize,
1932 mSamplersPS, &mUsedPixelSamplerRange);
Jamie Madillfb536032015-09-11 13:19:49 -04001933 }
1934}
1935
Jamie Madill62d31cb2015-09-11 13:25:51 -04001936// static
1937void ProgramD3D::AssignSamplers(unsigned int startSamplerIndex,
Jamie Madilld3dfda22015-07-06 08:28:49 -04001938 GLenum samplerType,
1939 unsigned int samplerCount,
1940 std::vector<Sampler> &outSamplers,
1941 GLuint *outUsedRange)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001942{
1943 unsigned int samplerIndex = startSamplerIndex;
1944
1945 do
1946 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001947 ASSERT(samplerIndex < outSamplers.size());
1948 Sampler *sampler = &outSamplers[samplerIndex];
1949 sampler->active = true;
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001950 sampler->textureType = gl::SamplerTypeToTextureType(samplerType);
Jamie Madill62d31cb2015-09-11 13:25:51 -04001951 sampler->logicalTextureUnit = 0;
1952 *outUsedRange = std::max(samplerIndex + 1, *outUsedRange);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001953 samplerIndex++;
1954 } while (samplerIndex < startSamplerIndex + samplerCount);
Brandon Jones18bd4102014-09-22 14:21:44 -07001955}
1956
Brandon Jonesc9610c52014-08-25 17:02:59 -07001957void ProgramD3D::reset()
1958{
Brandon Joneseb994362014-09-24 10:27:28 -07001959 SafeDeleteContainer(mVertexExecutables);
1960 SafeDeleteContainer(mPixelExecutables);
Jamie Madill4e31ad52015-10-29 10:32:57 -04001961
1962 for (auto &element : mGeometryExecutables)
1963 {
1964 SafeDelete(element);
1965 }
Brandon Joneseb994362014-09-24 10:27:28 -07001966
Brandon Jones22502d52014-08-29 16:58:36 -07001967 mVertexHLSL.clear();
Geoff Lang6941a552015-07-27 11:06:45 -04001968 mVertexWorkarounds = D3DCompilerWorkarounds();
Brandon Jones22502d52014-08-29 16:58:36 -07001969
1970 mPixelHLSL.clear();
Geoff Lang6941a552015-07-27 11:06:45 -04001971 mPixelWorkarounds = D3DCompilerWorkarounds();
Brandon Jones22502d52014-08-29 16:58:36 -07001972 mUsesFragDepth = false;
1973 mPixelShaderKey.clear();
Brandon Jones44151a92014-09-10 11:32:25 -07001974 mUsesPointSize = false;
Jamie Madill3e14e2b2015-10-29 14:38:53 -04001975 mUsesFlatInterpolation = false;
Brandon Jones22502d52014-08-29 16:58:36 -07001976
Jamie Madill62d31cb2015-09-11 13:25:51 -04001977 SafeDeleteContainer(mD3DUniforms);
Jamie Madill4a3c2342015-10-08 12:58:45 -04001978 mD3DUniformBlocks.clear();
Jamie Madill62d31cb2015-09-11 13:25:51 -04001979
Brandon Jonesc9610c52014-08-25 17:02:59 -07001980 SafeDelete(mVertexUniformStorage);
1981 SafeDelete(mFragmentUniformStorage);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001982
1983 mSamplersPS.clear();
1984 mSamplersVS.clear();
1985
1986 mUsedVertexSamplerRange = 0;
Jamie Madill334d6152015-10-22 14:00:28 -04001987 mUsedPixelSamplerRange = 0;
1988 mDirtySamplerMapping = true;
Jamie Madill437d2662014-12-05 14:23:35 -05001989
Jamie Madill63805b42015-08-25 13:17:39 -04001990 std::fill(mSemanticIndexes, mSemanticIndexes + ArraySize(mSemanticIndexes), -1);
Jamie Madill437d2662014-12-05 14:23:35 -05001991 std::fill(mAttributesByLayout, mAttributesByLayout + ArraySize(mAttributesByLayout), -1);
Jamie Madillccdf74b2015-08-18 10:46:12 -04001992
1993 mTransformFeedbackLinkedVaryings.clear();
Jamie Madill4e31ad52015-10-29 10:32:57 -04001994
1995 mGeometryShaderPreamble.clear();
Brandon Jonesc9610c52014-08-25 17:02:59 -07001996}
1997
Geoff Lang7dd2e102014-11-10 15:19:26 -05001998unsigned int ProgramD3D::getSerial() const
1999{
2000 return mSerial;
2001}
2002
2003unsigned int ProgramD3D::issueSerial()
2004{
2005 return mCurrentSerial++;
2006}
2007
Jamie Madill63805b42015-08-25 13:17:39 -04002008void ProgramD3D::initSemanticIndex()
2009{
2010 const gl::Shader *vertexShader = mData.getAttachedVertexShader();
2011 ASSERT(vertexShader != nullptr);
2012
2013 // Init semantic index
2014 for (const sh::Attribute &attribute : mData.getAttributes())
2015 {
2016 int attributeIndex = attribute.location;
2017 int index = vertexShader->getSemanticIndex(attribute.name);
2018 int regs = gl::VariableRegisterCount(attribute.type);
2019
2020 for (int reg = 0; reg < regs; ++reg)
2021 {
2022 mSemanticIndexes[attributeIndex + reg] = index + reg;
2023 }
2024 }
2025
2026 initAttributesByLayout();
2027}
2028
Jamie Madill437d2662014-12-05 14:23:35 -05002029void ProgramD3D::initAttributesByLayout()
2030{
2031 for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
2032 {
2033 mAttributesByLayout[i] = i;
2034 }
2035
Jamie Madill63805b42015-08-25 13:17:39 -04002036 std::sort(&mAttributesByLayout[0], &mAttributesByLayout[gl::MAX_VERTEX_ATTRIBS],
2037 AttributeSorter(mSemanticIndexes));
Jamie Madill437d2662014-12-05 14:23:35 -05002038}
2039
Jamie Madill334d6152015-10-22 14:00:28 -04002040void ProgramD3D::sortAttributesByLayout(
2041 const std::vector<TranslatedAttribute> &unsortedAttributes,
2042 int sortedSemanticIndicesOut[gl::MAX_VERTEX_ATTRIBS],
2043 const rx::TranslatedAttribute *sortedAttributesOut[gl::MAX_VERTEX_ATTRIBS]) const
Jamie Madill437d2662014-12-05 14:23:35 -05002044{
Jamie Madill476682e2015-06-30 10:04:29 -04002045 for (size_t attribIndex = 0; attribIndex < unsortedAttributes.size(); ++attribIndex)
Jamie Madill437d2662014-12-05 14:23:35 -05002046 {
Jamie Madill334d6152015-10-22 14:00:28 -04002047 int oldIndex = mAttributesByLayout[attribIndex];
Jamie Madill63805b42015-08-25 13:17:39 -04002048 sortedSemanticIndicesOut[attribIndex] = mSemanticIndexes[oldIndex];
Jamie Madill334d6152015-10-22 14:00:28 -04002049 sortedAttributesOut[attribIndex] = &unsortedAttributes[oldIndex];
Jamie Madill437d2662014-12-05 14:23:35 -05002050 }
2051}
2052
Jamie Madill63805b42015-08-25 13:17:39 -04002053void ProgramD3D::updateCachedInputLayout(const gl::State &state)
Jamie Madilld3dfda22015-07-06 08:28:49 -04002054{
Jamie Madillbd136f92015-08-10 14:51:37 -04002055 mCachedInputLayout.clear();
Jamie Madilld3dfda22015-07-06 08:28:49 -04002056 const auto &vertexAttributes = state.getVertexArray()->getVertexAttributes();
Jamie Madillf8dd7b12015-08-05 13:50:08 -04002057
Dian Xianga4928832015-09-15 10:11:17 -07002058 for (unsigned int attributeIndex : angle::IterateBitSet(mData.getActiveAttribLocationsMask()))
Jamie Madilld3dfda22015-07-06 08:28:49 -04002059 {
Jamie Madill63805b42015-08-25 13:17:39 -04002060 int semanticIndex = mSemanticIndexes[attributeIndex];
Jamie Madilld3dfda22015-07-06 08:28:49 -04002061
2062 if (semanticIndex != -1)
2063 {
Jamie Madillbd136f92015-08-10 14:51:37 -04002064 if (mCachedInputLayout.size() < static_cast<size_t>(semanticIndex + 1))
2065 {
2066 mCachedInputLayout.resize(semanticIndex + 1, gl::VERTEX_FORMAT_INVALID);
2067 }
Jamie Madilld3dfda22015-07-06 08:28:49 -04002068 mCachedInputLayout[semanticIndex] =
2069 GetVertexFormatType(vertexAttributes[attributeIndex],
2070 state.getVertexAttribCurrentValue(attributeIndex).Type);
2071 }
2072 }
2073}
2074
Jamie Madillccdf74b2015-08-18 10:46:12 -04002075void ProgramD3D::gatherTransformFeedbackVaryings(
2076 const std::vector<gl::LinkedVarying> &linkedVaryings)
2077{
2078 // Gather the linked varyings that are used for transform feedback, they should all exist.
2079 mTransformFeedbackLinkedVaryings.clear();
2080 for (const std::string &tfVaryingName : mData.getTransformFeedbackVaryingNames())
2081 {
2082 for (const gl::LinkedVarying &linkedVarying : linkedVaryings)
2083 {
2084 if (tfVaryingName == linkedVarying.name)
2085 {
2086 mTransformFeedbackLinkedVaryings.push_back(linkedVarying);
2087 break;
2088 }
2089 }
2090 }
2091}
Jamie Madill62d31cb2015-09-11 13:25:51 -04002092
2093D3DUniform *ProgramD3D::getD3DUniformFromLocation(GLint location)
2094{
2095 return mD3DUniforms[mData.getUniformLocations()[location].index];
2096}
Jamie Madill4a3c2342015-10-08 12:58:45 -04002097
2098bool ProgramD3D::getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const
2099{
2100 std::string baseName = blockName;
2101 gl::ParseAndStripArrayIndex(&baseName);
2102
2103 auto sizeIter = mBlockDataSizes.find(baseName);
2104 if (sizeIter == mBlockDataSizes.end())
2105 {
2106 *sizeOut = 0;
2107 return false;
2108 }
2109
2110 *sizeOut = sizeIter->second;
2111 return true;
2112}
2113
2114bool ProgramD3D::getUniformBlockMemberInfo(const std::string &memberUniformName,
2115 sh::BlockMemberInfo *memberInfoOut) const
2116{
2117 auto infoIter = mBlockInfo.find(memberUniformName);
2118 if (infoIter == mBlockInfo.end())
2119 {
2120 *memberInfoOut = sh::BlockMemberInfo::getDefaultBlockInfo();
2121 return false;
2122 }
2123
2124 *memberInfoOut = infoIter->second;
2125 return true;
2126}
Brandon Jonesc9610c52014-08-25 17:02:59 -07002127}