blob: 179186a00b115999ad9189b14d745db8fc9fe343 [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
11#include "common/utilities.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050012#include "libANGLE/Framebuffer.h"
13#include "libANGLE/FramebufferAttachment.h"
14#include "libANGLE/Program.h"
Jamie Madilld3dfda22015-07-06 08:28:49 -040015#include "libANGLE/VertexArray.h"
Jamie Madill6df9b372015-02-18 21:28:19 +000016#include "libANGLE/features.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050017#include "libANGLE/renderer/d3d/DynamicHLSL.h"
Jamie Madill85a18042015-03-05 15:41:41 -050018#include "libANGLE/renderer/d3d/FramebufferD3D.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050019#include "libANGLE/renderer/d3d/RendererD3D.h"
20#include "libANGLE/renderer/d3d/ShaderD3D.h"
Geoff Lang359ef262015-01-05 14:42:29 -050021#include "libANGLE/renderer/d3d/ShaderExecutableD3D.h"
Jamie Madill437d2662014-12-05 14:23:35 -050022#include "libANGLE/renderer/d3d/VertexDataManager.h"
Geoff Lang22072132014-11-20 15:15:01 -050023
Brandon Jonesc9610c52014-08-25 17:02:59 -070024namespace rx
25{
26
Brandon Joneseb994362014-09-24 10:27:28 -070027namespace
28{
29
Brandon Jones1a8a7e32014-10-01 12:49:30 -070030GLenum GetTextureType(GLenum samplerType)
31{
32 switch (samplerType)
33 {
34 case GL_SAMPLER_2D:
35 case GL_INT_SAMPLER_2D:
36 case GL_UNSIGNED_INT_SAMPLER_2D:
37 case GL_SAMPLER_2D_SHADOW:
38 return GL_TEXTURE_2D;
39 case GL_SAMPLER_3D:
40 case GL_INT_SAMPLER_3D:
41 case GL_UNSIGNED_INT_SAMPLER_3D:
42 return GL_TEXTURE_3D;
43 case GL_SAMPLER_CUBE:
44 case GL_SAMPLER_CUBE_SHADOW:
45 return GL_TEXTURE_CUBE_MAP;
46 case GL_INT_SAMPLER_CUBE:
47 case GL_UNSIGNED_INT_SAMPLER_CUBE:
48 return GL_TEXTURE_CUBE_MAP;
49 case GL_SAMPLER_2D_ARRAY:
50 case GL_INT_SAMPLER_2D_ARRAY:
51 case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
52 case GL_SAMPLER_2D_ARRAY_SHADOW:
53 return GL_TEXTURE_2D_ARRAY;
54 default: UNREACHABLE();
55 }
56
57 return GL_TEXTURE_2D;
58}
59
Jamie Madillf8dd7b12015-08-05 13:50:08 -040060gl::InputLayout GetDefaultInputLayoutFromShader(const gl::Shader *vertexShader)
Brandon Joneseb994362014-09-24 10:27:28 -070061{
Jamie Madillbd136f92015-08-10 14:51:37 -040062 gl::InputLayout defaultLayout;
63 for (const sh::Attribute &shaderAttr : vertexShader->getActiveAttributes())
Brandon Joneseb994362014-09-24 10:27:28 -070064 {
Brandon Joneseb994362014-09-24 10:27:28 -070065 if (shaderAttr.type != GL_NONE)
66 {
67 GLenum transposedType = gl::TransposeMatrixType(shaderAttr.type);
68
Jamie Madilld3dfda22015-07-06 08:28:49 -040069 for (size_t rowIndex = 0;
70 static_cast<int>(rowIndex) < gl::VariableRowCount(transposedType);
71 ++rowIndex)
Brandon Joneseb994362014-09-24 10:27:28 -070072 {
Jamie Madilld3dfda22015-07-06 08:28:49 -040073 GLenum componentType = gl::VariableComponentType(transposedType);
74 GLuint components = static_cast<GLuint>(gl::VariableColumnCount(transposedType));
75 bool pureInt = (componentType != GL_FLOAT);
76 gl::VertexFormatType defaultType = gl::GetVertexFormatType(
77 componentType, GL_FALSE, components, pureInt);
Brandon Joneseb994362014-09-24 10:27:28 -070078
Jamie Madillbd136f92015-08-10 14:51:37 -040079 defaultLayout.push_back(defaultType);
Brandon Joneseb994362014-09-24 10:27:28 -070080 }
81 }
82 }
Jamie Madillf8dd7b12015-08-05 13:50:08 -040083
84 return defaultLayout;
Brandon Joneseb994362014-09-24 10:27:28 -070085}
86
87std::vector<GLenum> GetDefaultOutputLayoutFromShader(const std::vector<PixelShaderOutputVariable> &shaderOutputVars)
88{
Jamie Madillb4463142014-12-19 14:56:54 -050089 std::vector<GLenum> defaultPixelOutput;
Brandon Joneseb994362014-09-24 10:27:28 -070090
Jamie Madillb4463142014-12-19 14:56:54 -050091 if (!shaderOutputVars.empty())
92 {
Cooper Partin4d61f7e2015-08-12 10:56:50 -070093 defaultPixelOutput.push_back(GL_COLOR_ATTACHMENT0 +
94 static_cast<unsigned int>(shaderOutputVars[0].outputIndex));
Jamie Madillb4463142014-12-19 14:56:54 -050095 }
Brandon Joneseb994362014-09-24 10:27:28 -070096
97 return defaultPixelOutput;
98}
99
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700100bool IsRowMajorLayout(const sh::InterfaceBlockField &var)
101{
102 return var.isRowMajorLayout;
103}
104
105bool IsRowMajorLayout(const sh::ShaderVariable &var)
106{
107 return false;
108}
109
Jamie Madill437d2662014-12-05 14:23:35 -0500110struct AttributeSorter
111{
Jamie Madill63805b42015-08-25 13:17:39 -0400112 AttributeSorter(const ProgramD3D::SemanticIndexArray &semanticIndices)
Jamie Madill80d934b2015-02-19 10:16:12 -0500113 : originalIndices(&semanticIndices)
Jamie Madill437d2662014-12-05 14:23:35 -0500114 {
115 }
116
117 bool operator()(int a, int b)
118 {
Jamie Madill80d934b2015-02-19 10:16:12 -0500119 int indexA = (*originalIndices)[a];
120 int indexB = (*originalIndices)[b];
121
122 if (indexA == -1) return false;
123 if (indexB == -1) return true;
124 return (indexA < indexB);
Jamie Madill437d2662014-12-05 14:23:35 -0500125 }
126
Jamie Madill63805b42015-08-25 13:17:39 -0400127 const ProgramD3D::SemanticIndexArray *originalIndices;
Jamie Madill437d2662014-12-05 14:23:35 -0500128};
129
Jamie Madill532061b2015-08-31 15:16:45 -0400130std::vector<PackedVarying> MergeVaryings(const gl::Shader &vertexShader,
131 const gl::Shader &fragmentShader,
132 const std::vector<std::string> &tfVaryings)
Jamie Madillada9ecc2015-08-17 12:53:37 -0400133{
Jamie Madill532061b2015-08-31 15:16:45 -0400134 std::vector<PackedVarying> packedVaryings;
135
136 for (const sh::Varying &output : vertexShader.getVaryings())
Jamie Madillada9ecc2015-08-17 12:53:37 -0400137 {
Jamie Madill532061b2015-08-31 15:16:45 -0400138 bool packed = false;
Jamie Madillada9ecc2015-08-17 12:53:37 -0400139
140 // Built-in varyings obey special rules
Jamie Madill532061b2015-08-31 15:16:45 -0400141 if (output.isBuiltIn())
Jamie Madillada9ecc2015-08-17 12:53:37 -0400142 {
143 continue;
144 }
145
Jamie Madill532061b2015-08-31 15:16:45 -0400146 for (const sh::Varying &input : fragmentShader.getVaryings())
Jamie Madillada9ecc2015-08-17 12:53:37 -0400147 {
Jamie Madill532061b2015-08-31 15:16:45 -0400148 if (output.name == input.name)
Jamie Madillada9ecc2015-08-17 12:53:37 -0400149 {
Jamie Madill532061b2015-08-31 15:16:45 -0400150 packedVaryings.push_back(PackedVarying(input));
151 packed = true;
Jamie Madillada9ecc2015-08-17 12:53:37 -0400152 break;
153 }
154 }
155
Jamie Madill532061b2015-08-31 15:16:45 -0400156 // Keep Transform FB varyings in the merged list always.
157 if (!packed)
158 {
159 for (const std::string &tfVarying : tfVaryings)
160 {
161 if (tfVarying == output.name)
162 {
163 packedVaryings.push_back(PackedVarying(output));
164 packedVaryings.back().vertexOnly = true;
165 packed = true;
166 break;
167 }
168 }
169 }
170
171 // We permit unreferenced varyings
172 ASSERT(packed || !output.staticUse);
Jamie Madillada9ecc2015-08-17 12:53:37 -0400173 }
174
Jamie Madill532061b2015-08-31 15:16:45 -0400175 return packedVaryings;
Brandon Joneseb994362014-09-24 10:27:28 -0700176}
177
Jamie Madillada9ecc2015-08-17 12:53:37 -0400178} // anonymous namespace
179
Jamie Madilld3dfda22015-07-06 08:28:49 -0400180ProgramD3D::VertexExecutable::VertexExecutable(const gl::InputLayout &inputLayout,
181 const Signature &signature,
Geoff Lang359ef262015-01-05 14:42:29 -0500182 ShaderExecutableD3D *shaderExecutable)
Jamie Madilld3dfda22015-07-06 08:28:49 -0400183 : mInputs(inputLayout),
184 mSignature(signature),
185 mShaderExecutable(shaderExecutable)
Brandon Joneseb994362014-09-24 10:27:28 -0700186{
Brandon Joneseb994362014-09-24 10:27:28 -0700187}
188
189ProgramD3D::VertexExecutable::~VertexExecutable()
190{
191 SafeDelete(mShaderExecutable);
192}
193
Jamie Madilld3dfda22015-07-06 08:28:49 -0400194// static
195void ProgramD3D::VertexExecutable::getSignature(RendererD3D *renderer,
196 const gl::InputLayout &inputLayout,
197 Signature *signatureOut)
Brandon Joneseb994362014-09-24 10:27:28 -0700198{
Jamie Madillbd136f92015-08-10 14:51:37 -0400199 signatureOut->resize(inputLayout.size());
Jamie Madilld3dfda22015-07-06 08:28:49 -0400200
201 for (size_t index = 0; index < inputLayout.size(); ++index)
Brandon Joneseb994362014-09-24 10:27:28 -0700202 {
Jamie Madilld3dfda22015-07-06 08:28:49 -0400203 gl::VertexFormatType vertexFormatType = inputLayout[index];
Jamie Madillbd136f92015-08-10 14:51:37 -0400204 bool converted = false;
Jamie Madillf8dd7b12015-08-05 13:50:08 -0400205 if (vertexFormatType != gl::VERTEX_FORMAT_INVALID)
Brandon Joneseb994362014-09-24 10:27:28 -0700206 {
Jamie Madillf8dd7b12015-08-05 13:50:08 -0400207 VertexConversionType conversionType =
208 renderer->getVertexConversionType(vertexFormatType);
Jamie Madillbd136f92015-08-10 14:51:37 -0400209 converted = ((conversionType & VERTEX_CONVERT_GPU) != 0);
Brandon Joneseb994362014-09-24 10:27:28 -0700210 }
Jamie Madillbd136f92015-08-10 14:51:37 -0400211
212 (*signatureOut)[index] = converted;
Brandon Joneseb994362014-09-24 10:27:28 -0700213 }
Brandon Joneseb994362014-09-24 10:27:28 -0700214}
215
Jamie Madilld3dfda22015-07-06 08:28:49 -0400216bool ProgramD3D::VertexExecutable::matchesSignature(const Signature &signature) const
217{
Jamie Madillbd136f92015-08-10 14:51:37 -0400218 size_t limit = std::max(mSignature.size(), signature.size());
219 for (size_t index = 0; index < limit; ++index)
220 {
221 // treat undefined indexes as 'not converted'
222 bool a = index < signature.size() ? signature[index] : false;
223 bool b = index < mSignature.size() ? mSignature[index] : false;
224 if (a != b)
225 return false;
226 }
227
228 return true;
Jamie Madilld3dfda22015-07-06 08:28:49 -0400229}
230
231ProgramD3D::PixelExecutable::PixelExecutable(const std::vector<GLenum> &outputSignature,
232 ShaderExecutableD3D *shaderExecutable)
Brandon Joneseb994362014-09-24 10:27:28 -0700233 : mOutputSignature(outputSignature),
234 mShaderExecutable(shaderExecutable)
235{
236}
237
238ProgramD3D::PixelExecutable::~PixelExecutable()
239{
240 SafeDelete(mShaderExecutable);
241}
242
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700243ProgramD3D::Sampler::Sampler() : active(false), logicalTextureUnit(0), textureType(GL_TEXTURE_2D)
244{
245}
246
Geoff Lang7dd2e102014-11-10 15:19:26 -0500247unsigned int ProgramD3D::mCurrentSerial = 1;
248
Jamie Madill5c6b7bf2015-08-17 12:53:35 -0400249ProgramD3D::ProgramD3D(const gl::Program::Data &data, RendererD3D *renderer)
250 : ProgramImpl(data),
Brandon Jonesc9610c52014-08-25 17:02:59 -0700251 mRenderer(renderer),
252 mDynamicHLSL(NULL),
Brandon Joneseb994362014-09-24 10:27:28 -0700253 mGeometryExecutable(NULL),
Brandon Jones44151a92014-09-10 11:32:25 -0700254 mUsesPointSize(false),
Brandon Jonesc9610c52014-08-25 17:02:59 -0700255 mVertexUniformStorage(NULL),
Brandon Jones44151a92014-09-10 11:32:25 -0700256 mFragmentUniformStorage(NULL),
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700257 mUsedVertexSamplerRange(0),
258 mUsedPixelSamplerRange(0),
259 mDirtySamplerMapping(true),
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400260 mTextureUnitTypesCache(renderer->getRendererCaps().maxCombinedTextureImageUnits),
Geoff Lang7dd2e102014-11-10 15:19:26 -0500261 mShaderVersion(100),
262 mSerial(issueSerial())
Brandon Jonesc9610c52014-08-25 17:02:59 -0700263{
Brandon Joneseb994362014-09-24 10:27:28 -0700264 mDynamicHLSL = new DynamicHLSL(renderer);
Brandon Jonesc9610c52014-08-25 17:02:59 -0700265}
266
267ProgramD3D::~ProgramD3D()
268{
269 reset();
270 SafeDelete(mDynamicHLSL);
271}
272
Brandon Jones44151a92014-09-10 11:32:25 -0700273bool ProgramD3D::usesPointSpriteEmulation() const
274{
275 return mUsesPointSize && mRenderer->getMajorShaderModel() >= 4;
276}
277
278bool ProgramD3D::usesGeometryShader() const
279{
Cooper Partine6664f02015-01-09 16:22:24 -0800280 return usesPointSpriteEmulation() && !usesInstancedPointSpriteEmulation();
281}
282
283bool ProgramD3D::usesInstancedPointSpriteEmulation() const
284{
285 return mRenderer->getWorkarounds().useInstancedPointSpriteEmulation;
Brandon Jones44151a92014-09-10 11:32:25 -0700286}
287
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700288GLint ProgramD3D::getSamplerMapping(gl::SamplerType type, unsigned int samplerIndex, const gl::Caps &caps) const
289{
290 GLint logicalTextureUnit = -1;
291
292 switch (type)
293 {
294 case gl::SAMPLER_PIXEL:
295 ASSERT(samplerIndex < caps.maxTextureImageUnits);
296 if (samplerIndex < mSamplersPS.size() && mSamplersPS[samplerIndex].active)
297 {
298 logicalTextureUnit = mSamplersPS[samplerIndex].logicalTextureUnit;
299 }
300 break;
301 case gl::SAMPLER_VERTEX:
302 ASSERT(samplerIndex < caps.maxVertexTextureImageUnits);
303 if (samplerIndex < mSamplersVS.size() && mSamplersVS[samplerIndex].active)
304 {
305 logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit;
306 }
307 break;
308 default: UNREACHABLE();
309 }
310
311 if (logicalTextureUnit >= 0 && logicalTextureUnit < static_cast<GLint>(caps.maxCombinedTextureImageUnits))
312 {
313 return logicalTextureUnit;
314 }
315
316 return -1;
317}
318
319// Returns the texture type for a given Direct3D 9 sampler type and
320// index (0-15 for the pixel shader and 0-3 for the vertex shader).
321GLenum ProgramD3D::getSamplerTextureType(gl::SamplerType type, unsigned int samplerIndex) const
322{
323 switch (type)
324 {
325 case gl::SAMPLER_PIXEL:
326 ASSERT(samplerIndex < mSamplersPS.size());
327 ASSERT(mSamplersPS[samplerIndex].active);
328 return mSamplersPS[samplerIndex].textureType;
329 case gl::SAMPLER_VERTEX:
330 ASSERT(samplerIndex < mSamplersVS.size());
331 ASSERT(mSamplersVS[samplerIndex].active);
332 return mSamplersVS[samplerIndex].textureType;
333 default: UNREACHABLE();
334 }
335
336 return GL_TEXTURE_2D;
337}
338
339GLint ProgramD3D::getUsedSamplerRange(gl::SamplerType type) const
340{
341 switch (type)
342 {
343 case gl::SAMPLER_PIXEL:
344 return mUsedPixelSamplerRange;
345 case gl::SAMPLER_VERTEX:
346 return mUsedVertexSamplerRange;
347 default:
348 UNREACHABLE();
349 return 0;
350 }
351}
352
353void ProgramD3D::updateSamplerMapping()
354{
355 if (!mDirtySamplerMapping)
356 {
357 return;
358 }
359
360 mDirtySamplerMapping = false;
361
362 // Retrieve sampler uniform values
363 for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
364 {
365 gl::LinkedUniform *targetUniform = mUniforms[uniformIndex];
366
367 if (targetUniform->dirty)
368 {
Geoff Lang2ec386b2014-12-03 14:44:38 -0500369 if (gl::IsSamplerType(targetUniform->type))
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700370 {
371 int count = targetUniform->elementCount();
372 GLint (*v)[4] = reinterpret_cast<GLint(*)[4]>(targetUniform->data);
373
374 if (targetUniform->isReferencedByFragmentShader())
375 {
376 unsigned int firstIndex = targetUniform->psRegisterIndex;
377
378 for (int i = 0; i < count; i++)
379 {
380 unsigned int samplerIndex = firstIndex + i;
381
382 if (samplerIndex < mSamplersPS.size())
383 {
384 ASSERT(mSamplersPS[samplerIndex].active);
385 mSamplersPS[samplerIndex].logicalTextureUnit = v[i][0];
386 }
387 }
388 }
389
390 if (targetUniform->isReferencedByVertexShader())
391 {
392 unsigned int firstIndex = targetUniform->vsRegisterIndex;
393
394 for (int i = 0; i < count; i++)
395 {
396 unsigned int samplerIndex = firstIndex + i;
397
398 if (samplerIndex < mSamplersVS.size())
399 {
400 ASSERT(mSamplersVS[samplerIndex].active);
401 mSamplersVS[samplerIndex].logicalTextureUnit = v[i][0];
402 }
403 }
404 }
405 }
406 }
407 }
408}
409
410bool ProgramD3D::validateSamplers(gl::InfoLog *infoLog, const gl::Caps &caps)
411{
Jamie Madill13776892015-04-28 12:39:06 -0400412 // Skip cache if we're using an infolog, so we get the full error.
413 // Also skip the cache if the sample mapping has changed, or if we haven't ever validated.
414 if (!mDirtySamplerMapping && infoLog == nullptr && mCachedValidateSamplersResult.valid())
415 {
416 return mCachedValidateSamplersResult.value();
417 }
418
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700419 // if any two active samplers in a program are of different types, but refer to the same
420 // texture image unit, and this is the current program, then ValidateProgram will fail, and
421 // DrawArrays and DrawElements will issue the INVALID_OPERATION error.
422 updateSamplerMapping();
423
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400424 std::fill(mTextureUnitTypesCache.begin(), mTextureUnitTypesCache.end(), GL_NONE);
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700425
426 for (unsigned int i = 0; i < mUsedPixelSamplerRange; ++i)
427 {
428 if (mSamplersPS[i].active)
429 {
430 unsigned int unit = mSamplersPS[i].logicalTextureUnit;
431
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400432 if (unit >= caps.maxCombinedTextureImageUnits)
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700433 {
434 if (infoLog)
435 {
Jamie Madillf6113162015-05-07 11:49:21 -0400436 (*infoLog) << "Sampler uniform (" << unit
437 << ") exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS ("
438 << caps.maxCombinedTextureImageUnits << ")";
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700439 }
440
Jamie Madill13776892015-04-28 12:39:06 -0400441 mCachedValidateSamplersResult = false;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700442 return false;
443 }
444
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400445 if (mTextureUnitTypesCache[unit] != GL_NONE)
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700446 {
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400447 if (mSamplersPS[i].textureType != mTextureUnitTypesCache[unit])
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700448 {
449 if (infoLog)
450 {
Jamie Madillf6113162015-05-07 11:49:21 -0400451 (*infoLog) << "Samplers of conflicting types refer to the same texture image unit ("
452 << unit << ").";
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700453 }
454
Jamie Madill13776892015-04-28 12:39:06 -0400455 mCachedValidateSamplersResult = false;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700456 return false;
457 }
458 }
459 else
460 {
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400461 mTextureUnitTypesCache[unit] = mSamplersPS[i].textureType;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700462 }
463 }
464 }
465
466 for (unsigned int i = 0; i < mUsedVertexSamplerRange; ++i)
467 {
468 if (mSamplersVS[i].active)
469 {
470 unsigned int unit = mSamplersVS[i].logicalTextureUnit;
471
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400472 if (unit >= caps.maxCombinedTextureImageUnits)
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700473 {
474 if (infoLog)
475 {
Jamie Madillf6113162015-05-07 11:49:21 -0400476 (*infoLog) << "Sampler uniform (" << unit
477 << ") exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS ("
478 << caps.maxCombinedTextureImageUnits << ")";
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700479 }
480
Jamie Madill13776892015-04-28 12:39:06 -0400481 mCachedValidateSamplersResult = false;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700482 return false;
483 }
484
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400485 if (mTextureUnitTypesCache[unit] != GL_NONE)
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700486 {
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400487 if (mSamplersVS[i].textureType != mTextureUnitTypesCache[unit])
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700488 {
489 if (infoLog)
490 {
Jamie Madillf6113162015-05-07 11:49:21 -0400491 (*infoLog) << "Samplers of conflicting types refer to the same texture image unit ("
492 << unit << ").";
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700493 }
494
Jamie Madill13776892015-04-28 12:39:06 -0400495 mCachedValidateSamplersResult = false;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700496 return false;
497 }
498 }
499 else
500 {
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400501 mTextureUnitTypesCache[unit] = mSamplersVS[i].textureType;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700502 }
503 }
504 }
505
Jamie Madill13776892015-04-28 12:39:06 -0400506 mCachedValidateSamplersResult = true;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700507 return true;
508}
509
Geoff Lang7dd2e102014-11-10 15:19:26 -0500510LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
Brandon Jones22502d52014-08-29 16:58:36 -0700511{
Austin Kinross137b1512015-06-17 16:14:53 -0700512 DeviceIdentifier binaryDeviceIdentifier = { 0 };
513 stream->readBytes(reinterpret_cast<unsigned char*>(&binaryDeviceIdentifier), sizeof(DeviceIdentifier));
514
515 DeviceIdentifier identifier = mRenderer->getAdapterIdentifier();
516 if (memcmp(&identifier, &binaryDeviceIdentifier, sizeof(DeviceIdentifier)) != 0)
517 {
518 infoLog << "Invalid program binary, device configuration has changed.";
519 return LinkResult(false, gl::Error(GL_NO_ERROR));
520 }
521
Jamie Madill2db1fbb2014-12-03 10:58:55 -0500522 int compileFlags = stream->readInt<int>();
523 if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL)
524 {
Jamie Madillf6113162015-05-07 11:49:21 -0400525 infoLog << "Mismatched compilation flags.";
Jamie Madill2db1fbb2014-12-03 10:58:55 -0500526 return LinkResult(false, gl::Error(GL_NO_ERROR));
527 }
528
Brandon Jones44151a92014-09-10 11:32:25 -0700529 stream->readInt(&mShaderVersion);
530
Jamie Madill63805b42015-08-25 13:17:39 -0400531 // TODO(jmadill): replace MAX_VERTEX_ATTRIBS
532 for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; ++i)
533 {
534 stream->readInt(&mSemanticIndexes[i]);
535 }
536
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700537 const unsigned int psSamplerCount = stream->readInt<unsigned int>();
538 for (unsigned int i = 0; i < psSamplerCount; ++i)
539 {
540 Sampler sampler;
541 stream->readBool(&sampler.active);
542 stream->readInt(&sampler.logicalTextureUnit);
543 stream->readInt(&sampler.textureType);
544 mSamplersPS.push_back(sampler);
545 }
546 const unsigned int vsSamplerCount = stream->readInt<unsigned int>();
547 for (unsigned int i = 0; i < vsSamplerCount; ++i)
548 {
549 Sampler sampler;
550 stream->readBool(&sampler.active);
551 stream->readInt(&sampler.logicalTextureUnit);
552 stream->readInt(&sampler.textureType);
553 mSamplersVS.push_back(sampler);
554 }
555
556 stream->readInt(&mUsedVertexSamplerRange);
557 stream->readInt(&mUsedPixelSamplerRange);
558
559 const unsigned int uniformCount = stream->readInt<unsigned int>();
560 if (stream->error())
561 {
Jamie Madillf6113162015-05-07 11:49:21 -0400562 infoLog << "Invalid program binary.";
Geoff Lang7dd2e102014-11-10 15:19:26 -0500563 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700564 }
565
566 mUniforms.resize(uniformCount);
567 for (unsigned int uniformIndex = 0; uniformIndex < uniformCount; uniformIndex++)
568 {
569 GLenum type = stream->readInt<GLenum>();
570 GLenum precision = stream->readInt<GLenum>();
571 std::string name = stream->readString();
572 unsigned int arraySize = stream->readInt<unsigned int>();
573 int blockIndex = stream->readInt<int>();
574
575 int offset = stream->readInt<int>();
576 int arrayStride = stream->readInt<int>();
577 int matrixStride = stream->readInt<int>();
578 bool isRowMajorMatrix = stream->readBool();
579
580 const sh::BlockMemberInfo blockInfo(offset, arrayStride, matrixStride, isRowMajorMatrix);
581
582 gl::LinkedUniform *uniform = new gl::LinkedUniform(type, precision, name, arraySize, blockIndex, blockInfo);
583
584 stream->readInt(&uniform->psRegisterIndex);
585 stream->readInt(&uniform->vsRegisterIndex);
586 stream->readInt(&uniform->registerCount);
587 stream->readInt(&uniform->registerElement);
588
589 mUniforms[uniformIndex] = uniform;
590 }
591
592 const unsigned int uniformIndexCount = stream->readInt<unsigned int>();
593 if (stream->error())
594 {
Jamie Madillf6113162015-05-07 11:49:21 -0400595 infoLog << "Invalid program binary.";
Geoff Lang7dd2e102014-11-10 15:19:26 -0500596 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700597 }
598
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700599 for (unsigned int uniformIndexIndex = 0; uniformIndexIndex < uniformIndexCount; uniformIndexIndex++)
600 {
Geoff Lang95137842015-06-02 15:38:43 -0400601 GLuint location;
602 stream->readInt(&location);
603
604 gl::VariableLocation variable;
605 stream->readString(&variable.name);
606 stream->readInt(&variable.element);
607 stream->readInt(&variable.index);
608
609 mUniformIndex[location] = variable;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700610 }
611
612 unsigned int uniformBlockCount = stream->readInt<unsigned int>();
613 if (stream->error())
614 {
Jamie Madillf6113162015-05-07 11:49:21 -0400615 infoLog << "Invalid program binary.";
Geoff Lang7dd2e102014-11-10 15:19:26 -0500616 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700617 }
618
619 mUniformBlocks.resize(uniformBlockCount);
620 for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < uniformBlockCount; ++uniformBlockIndex)
621 {
622 std::string name = stream->readString();
623 unsigned int elementIndex = stream->readInt<unsigned int>();
624 unsigned int dataSize = stream->readInt<unsigned int>();
625
626 gl::UniformBlock *uniformBlock = new gl::UniformBlock(name, elementIndex, dataSize);
627
628 stream->readInt(&uniformBlock->psRegisterIndex);
629 stream->readInt(&uniformBlock->vsRegisterIndex);
630
631 unsigned int numMembers = stream->readInt<unsigned int>();
632 uniformBlock->memberUniformIndexes.resize(numMembers);
633 for (unsigned int blockMemberIndex = 0; blockMemberIndex < numMembers; blockMemberIndex++)
634 {
635 stream->readInt(&uniformBlock->memberUniformIndexes[blockMemberIndex]);
636 }
637
638 mUniformBlocks[uniformBlockIndex] = uniformBlock;
639 }
640
Brandon Joneseb994362014-09-24 10:27:28 -0700641 const unsigned int transformFeedbackVaryingCount = stream->readInt<unsigned int>();
642 mTransformFeedbackLinkedVaryings.resize(transformFeedbackVaryingCount);
643 for (unsigned int varyingIndex = 0; varyingIndex < transformFeedbackVaryingCount; varyingIndex++)
644 {
645 gl::LinkedVarying &varying = mTransformFeedbackLinkedVaryings[varyingIndex];
646
647 stream->readString(&varying.name);
648 stream->readInt(&varying.type);
649 stream->readInt(&varying.size);
650 stream->readString(&varying.semanticName);
651 stream->readInt(&varying.semanticIndex);
652 stream->readInt(&varying.semanticIndexCount);
653 }
654
Brandon Jones22502d52014-08-29 16:58:36 -0700655 stream->readString(&mVertexHLSL);
Arun Patole44efa0b2015-03-04 17:11:05 +0530656 stream->readBytes(reinterpret_cast<unsigned char*>(&mVertexWorkarounds), sizeof(D3DCompilerWorkarounds));
Brandon Jones22502d52014-08-29 16:58:36 -0700657 stream->readString(&mPixelHLSL);
Arun Patole44efa0b2015-03-04 17:11:05 +0530658 stream->readBytes(reinterpret_cast<unsigned char*>(&mPixelWorkarounds), sizeof(D3DCompilerWorkarounds));
Brandon Jones22502d52014-08-29 16:58:36 -0700659 stream->readBool(&mUsesFragDepth);
Brandon Jones44151a92014-09-10 11:32:25 -0700660 stream->readBool(&mUsesPointSize);
Brandon Jones22502d52014-08-29 16:58:36 -0700661
662 const size_t pixelShaderKeySize = stream->readInt<unsigned int>();
663 mPixelShaderKey.resize(pixelShaderKeySize);
664 for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKeySize; pixelShaderKeyIndex++)
665 {
666 stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].type);
667 stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].name);
668 stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].source);
669 stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].outputIndex);
670 }
671
Brandon Joneseb994362014-09-24 10:27:28 -0700672 const unsigned char* binary = reinterpret_cast<const unsigned char*>(stream->data());
673
674 const unsigned int vertexShaderCount = stream->readInt<unsigned int>();
675 for (unsigned int vertexShaderIndex = 0; vertexShaderIndex < vertexShaderCount; vertexShaderIndex++)
676 {
Jamie Madilld3dfda22015-07-06 08:28:49 -0400677 size_t inputLayoutSize = stream->readInt<size_t>();
Jamie Madillf8dd7b12015-08-05 13:50:08 -0400678 gl::InputLayout inputLayout(inputLayoutSize, gl::VERTEX_FORMAT_INVALID);
Brandon Joneseb994362014-09-24 10:27:28 -0700679
Jamie Madilld3dfda22015-07-06 08:28:49 -0400680 for (size_t inputIndex = 0; inputIndex < inputLayoutSize; inputIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -0700681 {
Jamie Madillf8dd7b12015-08-05 13:50:08 -0400682 inputLayout[inputIndex] = stream->readInt<gl::VertexFormatType>();
Brandon Joneseb994362014-09-24 10:27:28 -0700683 }
684
685 unsigned int vertexShaderSize = stream->readInt<unsigned int>();
686 const unsigned char *vertexShaderFunction = binary + stream->offset();
Geoff Langb543aff2014-09-30 14:52:54 -0400687
Jamie Madillada9ecc2015-08-17 12:53:37 -0400688 ShaderExecutableD3D *shaderExecutable = nullptr;
689
690 gl::Error error = mRenderer->loadExecutable(
691 vertexShaderFunction, vertexShaderSize, SHADER_VERTEX, mTransformFeedbackLinkedVaryings,
692 (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), &shaderExecutable);
Geoff Langb543aff2014-09-30 14:52:54 -0400693 if (error.isError())
694 {
Geoff Lang7dd2e102014-11-10 15:19:26 -0500695 return LinkResult(false, error);
Geoff Langb543aff2014-09-30 14:52:54 -0400696 }
697
Brandon Joneseb994362014-09-24 10:27:28 -0700698 if (!shaderExecutable)
699 {
Jamie Madillf6113162015-05-07 11:49:21 -0400700 infoLog << "Could not create vertex shader.";
Geoff Lang7dd2e102014-11-10 15:19:26 -0500701 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Joneseb994362014-09-24 10:27:28 -0700702 }
703
704 // generated converted input layout
Jamie Madilld3dfda22015-07-06 08:28:49 -0400705 VertexExecutable::Signature signature;
706 VertexExecutable::getSignature(mRenderer, inputLayout, &signature);
Brandon Joneseb994362014-09-24 10:27:28 -0700707
708 // add new binary
709 mVertexExecutables.push_back(new VertexExecutable(inputLayout, signature, shaderExecutable));
710
711 stream->skip(vertexShaderSize);
712 }
713
714 const size_t pixelShaderCount = stream->readInt<unsigned int>();
715 for (size_t pixelShaderIndex = 0; pixelShaderIndex < pixelShaderCount; pixelShaderIndex++)
716 {
717 const size_t outputCount = stream->readInt<unsigned int>();
718 std::vector<GLenum> outputs(outputCount);
719 for (size_t outputIndex = 0; outputIndex < outputCount; outputIndex++)
720 {
721 stream->readInt(&outputs[outputIndex]);
722 }
723
724 const size_t pixelShaderSize = stream->readInt<unsigned int>();
725 const unsigned char *pixelShaderFunction = binary + stream->offset();
Jamie Madillada9ecc2015-08-17 12:53:37 -0400726 ShaderExecutableD3D *shaderExecutable = nullptr;
727
728 gl::Error error = mRenderer->loadExecutable(
729 pixelShaderFunction, pixelShaderSize, SHADER_PIXEL, mTransformFeedbackLinkedVaryings,
730 (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), &shaderExecutable);
Geoff Langb543aff2014-09-30 14:52:54 -0400731 if (error.isError())
732 {
Geoff Lang7dd2e102014-11-10 15:19:26 -0500733 return LinkResult(false, error);
Geoff Langb543aff2014-09-30 14:52:54 -0400734 }
Brandon Joneseb994362014-09-24 10:27:28 -0700735
736 if (!shaderExecutable)
737 {
Jamie Madillf6113162015-05-07 11:49:21 -0400738 infoLog << "Could not create pixel shader.";
Geoff Lang7dd2e102014-11-10 15:19:26 -0500739 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Joneseb994362014-09-24 10:27:28 -0700740 }
741
742 // add new binary
743 mPixelExecutables.push_back(new PixelExecutable(outputs, shaderExecutable));
744
745 stream->skip(pixelShaderSize);
746 }
747
748 unsigned int geometryShaderSize = stream->readInt<unsigned int>();
749
750 if (geometryShaderSize > 0)
751 {
752 const unsigned char *geometryShaderFunction = binary + stream->offset();
Jamie Madillada9ecc2015-08-17 12:53:37 -0400753 gl::Error error = mRenderer->loadExecutable(
754 geometryShaderFunction, geometryShaderSize, SHADER_GEOMETRY,
755 mTransformFeedbackLinkedVaryings,
756 (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), &mGeometryExecutable);
Geoff Langb543aff2014-09-30 14:52:54 -0400757 if (error.isError())
758 {
Geoff Lang7dd2e102014-11-10 15:19:26 -0500759 return LinkResult(false, error);
Geoff Langb543aff2014-09-30 14:52:54 -0400760 }
Brandon Joneseb994362014-09-24 10:27:28 -0700761
762 if (!mGeometryExecutable)
763 {
Jamie Madillf6113162015-05-07 11:49:21 -0400764 infoLog << "Could not create geometry shader.";
Geoff Lang7dd2e102014-11-10 15:19:26 -0500765 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Joneseb994362014-09-24 10:27:28 -0700766 }
767 stream->skip(geometryShaderSize);
768 }
769
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700770 initializeUniformStorage();
Jamie Madill437d2662014-12-05 14:23:35 -0500771 initAttributesByLayout();
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700772
Geoff Lang7dd2e102014-11-10 15:19:26 -0500773 return LinkResult(true, gl::Error(GL_NO_ERROR));
Brandon Jones22502d52014-08-29 16:58:36 -0700774}
775
Geoff Langb543aff2014-09-30 14:52:54 -0400776gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream)
Brandon Jones22502d52014-08-29 16:58:36 -0700777{
Austin Kinross137b1512015-06-17 16:14:53 -0700778 // Output the DeviceIdentifier before we output any shader code
779 // When we load the binary again later, we can validate the device identifier before trying to compile any HLSL
780 DeviceIdentifier binaryIdentifier = mRenderer->getAdapterIdentifier();
781 stream->writeBytes(reinterpret_cast<unsigned char*>(&binaryIdentifier), sizeof(DeviceIdentifier));
782
Jamie Madill2db1fbb2014-12-03 10:58:55 -0500783 stream->writeInt(ANGLE_COMPILE_OPTIMIZATION_LEVEL);
784
Brandon Jones44151a92014-09-10 11:32:25 -0700785 stream->writeInt(mShaderVersion);
786
Jamie Madill63805b42015-08-25 13:17:39 -0400787 // TODO(jmadill): replace MAX_VERTEX_ATTRIBS
788 for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; ++i)
789 {
790 stream->writeInt(mSemanticIndexes[i]);
791 }
792
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700793 stream->writeInt(mSamplersPS.size());
794 for (unsigned int i = 0; i < mSamplersPS.size(); ++i)
795 {
796 stream->writeInt(mSamplersPS[i].active);
797 stream->writeInt(mSamplersPS[i].logicalTextureUnit);
798 stream->writeInt(mSamplersPS[i].textureType);
799 }
800
801 stream->writeInt(mSamplersVS.size());
802 for (unsigned int i = 0; i < mSamplersVS.size(); ++i)
803 {
804 stream->writeInt(mSamplersVS[i].active);
805 stream->writeInt(mSamplersVS[i].logicalTextureUnit);
806 stream->writeInt(mSamplersVS[i].textureType);
807 }
808
809 stream->writeInt(mUsedVertexSamplerRange);
810 stream->writeInt(mUsedPixelSamplerRange);
811
812 stream->writeInt(mUniforms.size());
813 for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); ++uniformIndex)
814 {
815 const gl::LinkedUniform &uniform = *mUniforms[uniformIndex];
816
817 stream->writeInt(uniform.type);
818 stream->writeInt(uniform.precision);
819 stream->writeString(uniform.name);
820 stream->writeInt(uniform.arraySize);
821 stream->writeInt(uniform.blockIndex);
822
823 stream->writeInt(uniform.blockInfo.offset);
824 stream->writeInt(uniform.blockInfo.arrayStride);
825 stream->writeInt(uniform.blockInfo.matrixStride);
826 stream->writeInt(uniform.blockInfo.isRowMajorMatrix);
827
828 stream->writeInt(uniform.psRegisterIndex);
829 stream->writeInt(uniform.vsRegisterIndex);
830 stream->writeInt(uniform.registerCount);
831 stream->writeInt(uniform.registerElement);
832 }
833
834 stream->writeInt(mUniformIndex.size());
Geoff Lang95137842015-06-02 15:38:43 -0400835 for (const auto &uniform : mUniformIndex)
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700836 {
Geoff Lang95137842015-06-02 15:38:43 -0400837 GLuint location = uniform.first;
838 stream->writeInt(location);
839
840 const gl::VariableLocation &variable = uniform.second;
841 stream->writeString(variable.name);
842 stream->writeInt(variable.element);
843 stream->writeInt(variable.index);
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700844 }
845
846 stream->writeInt(mUniformBlocks.size());
847 for (size_t uniformBlockIndex = 0; uniformBlockIndex < mUniformBlocks.size(); ++uniformBlockIndex)
848 {
849 const gl::UniformBlock& uniformBlock = *mUniformBlocks[uniformBlockIndex];
850
851 stream->writeString(uniformBlock.name);
852 stream->writeInt(uniformBlock.elementIndex);
853 stream->writeInt(uniformBlock.dataSize);
854
855 stream->writeInt(uniformBlock.memberUniformIndexes.size());
856 for (unsigned int blockMemberIndex = 0; blockMemberIndex < uniformBlock.memberUniformIndexes.size(); blockMemberIndex++)
857 {
858 stream->writeInt(uniformBlock.memberUniformIndexes[blockMemberIndex]);
859 }
860
861 stream->writeInt(uniformBlock.psRegisterIndex);
862 stream->writeInt(uniformBlock.vsRegisterIndex);
863 }
864
Brandon Joneseb994362014-09-24 10:27:28 -0700865 stream->writeInt(mTransformFeedbackLinkedVaryings.size());
866 for (size_t i = 0; i < mTransformFeedbackLinkedVaryings.size(); i++)
867 {
868 const gl::LinkedVarying &varying = mTransformFeedbackLinkedVaryings[i];
869
870 stream->writeString(varying.name);
871 stream->writeInt(varying.type);
872 stream->writeInt(varying.size);
873 stream->writeString(varying.semanticName);
874 stream->writeInt(varying.semanticIndex);
875 stream->writeInt(varying.semanticIndexCount);
876 }
877
Brandon Jones22502d52014-08-29 16:58:36 -0700878 stream->writeString(mVertexHLSL);
Arun Patole44efa0b2015-03-04 17:11:05 +0530879 stream->writeBytes(reinterpret_cast<unsigned char*>(&mVertexWorkarounds), sizeof(D3DCompilerWorkarounds));
Brandon Jones22502d52014-08-29 16:58:36 -0700880 stream->writeString(mPixelHLSL);
Arun Patole44efa0b2015-03-04 17:11:05 +0530881 stream->writeBytes(reinterpret_cast<unsigned char*>(&mPixelWorkarounds), sizeof(D3DCompilerWorkarounds));
Brandon Jones22502d52014-08-29 16:58:36 -0700882 stream->writeInt(mUsesFragDepth);
Brandon Jones44151a92014-09-10 11:32:25 -0700883 stream->writeInt(mUsesPointSize);
Brandon Jones22502d52014-08-29 16:58:36 -0700884
Brandon Joneseb994362014-09-24 10:27:28 -0700885 const std::vector<PixelShaderOutputVariable> &pixelShaderKey = mPixelShaderKey;
Brandon Jones22502d52014-08-29 16:58:36 -0700886 stream->writeInt(pixelShaderKey.size());
887 for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKey.size(); pixelShaderKeyIndex++)
888 {
Brandon Joneseb994362014-09-24 10:27:28 -0700889 const PixelShaderOutputVariable &variable = pixelShaderKey[pixelShaderKeyIndex];
Brandon Jones22502d52014-08-29 16:58:36 -0700890 stream->writeInt(variable.type);
891 stream->writeString(variable.name);
892 stream->writeString(variable.source);
893 stream->writeInt(variable.outputIndex);
894 }
895
Brandon Joneseb994362014-09-24 10:27:28 -0700896 stream->writeInt(mVertexExecutables.size());
897 for (size_t vertexExecutableIndex = 0; vertexExecutableIndex < mVertexExecutables.size(); vertexExecutableIndex++)
898 {
899 VertexExecutable *vertexExecutable = mVertexExecutables[vertexExecutableIndex];
900
Jamie Madilld3dfda22015-07-06 08:28:49 -0400901 const auto &inputLayout = vertexExecutable->inputs();
902 stream->writeInt(inputLayout.size());
903
904 for (size_t inputIndex = 0; inputIndex < inputLayout.size(); inputIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -0700905 {
Jamie Madilld3dfda22015-07-06 08:28:49 -0400906 stream->writeInt(inputLayout[inputIndex]);
Brandon Joneseb994362014-09-24 10:27:28 -0700907 }
908
909 size_t vertexShaderSize = vertexExecutable->shaderExecutable()->getLength();
910 stream->writeInt(vertexShaderSize);
911
912 const uint8_t *vertexBlob = vertexExecutable->shaderExecutable()->getFunction();
913 stream->writeBytes(vertexBlob, vertexShaderSize);
914 }
915
916 stream->writeInt(mPixelExecutables.size());
917 for (size_t pixelExecutableIndex = 0; pixelExecutableIndex < mPixelExecutables.size(); pixelExecutableIndex++)
918 {
919 PixelExecutable *pixelExecutable = mPixelExecutables[pixelExecutableIndex];
920
921 const std::vector<GLenum> outputs = pixelExecutable->outputSignature();
922 stream->writeInt(outputs.size());
923 for (size_t outputIndex = 0; outputIndex < outputs.size(); outputIndex++)
924 {
925 stream->writeInt(outputs[outputIndex]);
926 }
927
928 size_t pixelShaderSize = pixelExecutable->shaderExecutable()->getLength();
929 stream->writeInt(pixelShaderSize);
930
931 const uint8_t *pixelBlob = pixelExecutable->shaderExecutable()->getFunction();
932 stream->writeBytes(pixelBlob, pixelShaderSize);
933 }
934
935 size_t geometryShaderSize = (mGeometryExecutable != NULL) ? mGeometryExecutable->getLength() : 0;
936 stream->writeInt(geometryShaderSize);
937
938 if (mGeometryExecutable != NULL && geometryShaderSize > 0)
939 {
940 const uint8_t *geometryBlob = mGeometryExecutable->getFunction();
941 stream->writeBytes(geometryBlob, geometryShaderSize);
942 }
943
Geoff Langb543aff2014-09-30 14:52:54 -0400944 return gl::Error(GL_NO_ERROR);
Brandon Jones22502d52014-08-29 16:58:36 -0700945}
946
Geoff Lang359ef262015-01-05 14:42:29 -0500947gl::Error ProgramD3D::getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo, ShaderExecutableD3D **outExecutable)
Brandon Jones22502d52014-08-29 16:58:36 -0700948{
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400949 mPixelShaderOutputFormatCache.clear();
Brandon Joneseb994362014-09-24 10:27:28 -0700950
Jamie Madill85a18042015-03-05 15:41:41 -0500951 const FramebufferD3D *fboD3D = GetImplAs<FramebufferD3D>(fbo);
952 const gl::AttachmentList &colorbuffers = fboD3D->getColorAttachmentsForRender(mRenderer->getWorkarounds());
Brandon Joneseb994362014-09-24 10:27:28 -0700953
954 for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment)
955 {
956 const gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment];
957
958 if (colorbuffer)
959 {
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400960 mPixelShaderOutputFormatCache.push_back(colorbuffer->getBinding() == GL_BACK ? GL_COLOR_ATTACHMENT0 : colorbuffer->getBinding());
Brandon Joneseb994362014-09-24 10:27:28 -0700961 }
962 else
963 {
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400964 mPixelShaderOutputFormatCache.push_back(GL_NONE);
Brandon Joneseb994362014-09-24 10:27:28 -0700965 }
966 }
967
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400968 return getPixelExecutableForOutputLayout(mPixelShaderOutputFormatCache, outExecutable, nullptr);
Brandon Joneseb994362014-09-24 10:27:28 -0700969}
970
Jamie Madill97399232014-12-23 12:31:15 -0500971gl::Error ProgramD3D::getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputSignature,
Geoff Lang359ef262015-01-05 14:42:29 -0500972 ShaderExecutableD3D **outExectuable,
Jamie Madill97399232014-12-23 12:31:15 -0500973 gl::InfoLog *infoLog)
Brandon Joneseb994362014-09-24 10:27:28 -0700974{
975 for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++)
976 {
977 if (mPixelExecutables[executableIndex]->matchesSignature(outputSignature))
978 {
Geoff Langb543aff2014-09-30 14:52:54 -0400979 *outExectuable = mPixelExecutables[executableIndex]->shaderExecutable();
980 return gl::Error(GL_NO_ERROR);
Brandon Joneseb994362014-09-24 10:27:28 -0700981 }
982 }
983
Brandon Jones22502d52014-08-29 16:58:36 -0700984 std::string finalPixelHLSL = mDynamicHLSL->generatePixelShaderForOutputSignature(mPixelHLSL, mPixelShaderKey, mUsesFragDepth,
985 outputSignature);
986
987 // Generate new pixel executable
Geoff Lang359ef262015-01-05 14:42:29 -0500988 ShaderExecutableD3D *pixelExecutable = NULL;
Jamie Madill97399232014-12-23 12:31:15 -0500989
990 gl::InfoLog tempInfoLog;
991 gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
992
Jamie Madillada9ecc2015-08-17 12:53:37 -0400993 gl::Error error = mRenderer->compileToExecutable(
994 *currentInfoLog, finalPixelHLSL, SHADER_PIXEL, mTransformFeedbackLinkedVaryings,
995 (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), mPixelWorkarounds,
996 &pixelExecutable);
Geoff Langb543aff2014-09-30 14:52:54 -0400997 if (error.isError())
998 {
999 return error;
1000 }
Brandon Joneseb994362014-09-24 10:27:28 -07001001
Jamie Madill97399232014-12-23 12:31:15 -05001002 if (pixelExecutable)
1003 {
1004 mPixelExecutables.push_back(new PixelExecutable(outputSignature, pixelExecutable));
1005 }
1006 else if (!infoLog)
Brandon Joneseb994362014-09-24 10:27:28 -07001007 {
1008 std::vector<char> tempCharBuffer(tempInfoLog.getLength() + 3);
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001009 tempInfoLog.getLog(static_cast<GLsizei>(tempInfoLog.getLength()), NULL, &tempCharBuffer[0]);
Brandon Joneseb994362014-09-24 10:27:28 -07001010 ERR("Error compiling dynamic pixel executable:\n%s\n", &tempCharBuffer[0]);
1011 }
Brandon Jones22502d52014-08-29 16:58:36 -07001012
Geoff Langb543aff2014-09-30 14:52:54 -04001013 *outExectuable = pixelExecutable;
1014 return gl::Error(GL_NO_ERROR);
Brandon Jones22502d52014-08-29 16:58:36 -07001015}
1016
Jamie Madilld3dfda22015-07-06 08:28:49 -04001017gl::Error ProgramD3D::getVertexExecutableForInputLayout(const gl::InputLayout &inputLayout,
Geoff Lang359ef262015-01-05 14:42:29 -05001018 ShaderExecutableD3D **outExectuable,
Jamie Madill97399232014-12-23 12:31:15 -05001019 gl::InfoLog *infoLog)
Brandon Jones22502d52014-08-29 16:58:36 -07001020{
Jamie Madilld3dfda22015-07-06 08:28:49 -04001021 VertexExecutable::getSignature(mRenderer, inputLayout, &mCachedVertexSignature);
Brandon Joneseb994362014-09-24 10:27:28 -07001022
1023 for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++)
1024 {
Jamie Madilld3dfda22015-07-06 08:28:49 -04001025 if (mVertexExecutables[executableIndex]->matchesSignature(mCachedVertexSignature))
Brandon Joneseb994362014-09-24 10:27:28 -07001026 {
Geoff Langb543aff2014-09-30 14:52:54 -04001027 *outExectuable = mVertexExecutables[executableIndex]->shaderExecutable();
1028 return gl::Error(GL_NO_ERROR);
Brandon Joneseb994362014-09-24 10:27:28 -07001029 }
1030 }
1031
Brandon Jones22502d52014-08-29 16:58:36 -07001032 // Generate new dynamic layout with attribute conversions
Jamie Madillc349ec02015-08-21 16:53:12 -04001033 std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout(
1034 mVertexHLSL, inputLayout, mData.getAttributes());
Brandon Jones22502d52014-08-29 16:58:36 -07001035
1036 // Generate new vertex executable
Geoff Lang359ef262015-01-05 14:42:29 -05001037 ShaderExecutableD3D *vertexExecutable = NULL;
Jamie Madill97399232014-12-23 12:31:15 -05001038
1039 gl::InfoLog tempInfoLog;
1040 gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
1041
Jamie Madillada9ecc2015-08-17 12:53:37 -04001042 gl::Error error = mRenderer->compileToExecutable(
1043 *currentInfoLog, finalVertexHLSL, SHADER_VERTEX, mTransformFeedbackLinkedVaryings,
1044 (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), mVertexWorkarounds,
1045 &vertexExecutable);
Geoff Langb543aff2014-09-30 14:52:54 -04001046 if (error.isError())
1047 {
1048 return error;
1049 }
1050
Jamie Madill97399232014-12-23 12:31:15 -05001051 if (vertexExecutable)
Brandon Joneseb994362014-09-24 10:27:28 -07001052 {
Jamie Madilld3dfda22015-07-06 08:28:49 -04001053 mVertexExecutables.push_back(new VertexExecutable(inputLayout, mCachedVertexSignature, vertexExecutable));
Brandon Joneseb994362014-09-24 10:27:28 -07001054 }
Jamie Madill97399232014-12-23 12:31:15 -05001055 else if (!infoLog)
1056 {
1057 std::vector<char> tempCharBuffer(tempInfoLog.getLength() + 3);
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001058 tempInfoLog.getLog(static_cast<GLsizei>(tempInfoLog.getLength()), NULL, &tempCharBuffer[0]);
Jamie Madill97399232014-12-23 12:31:15 -05001059 ERR("Error compiling dynamic vertex executable:\n%s\n", &tempCharBuffer[0]);
1060 }
Brandon Jones22502d52014-08-29 16:58:36 -07001061
Geoff Langb543aff2014-09-30 14:52:54 -04001062 *outExectuable = vertexExecutable;
1063 return gl::Error(GL_NO_ERROR);
Brandon Jones22502d52014-08-29 16:58:36 -07001064}
1065
Jamie Madill532061b2015-08-31 15:16:45 -04001066LinkResult ProgramD3D::compileProgramExecutables(gl::InfoLog &infoLog,
1067 int registers,
1068 const std::vector<PackedVarying> &packedVaryings)
Brandon Jones44151a92014-09-10 11:32:25 -07001069{
Jamie Madill5c6b7bf2015-08-17 12:53:35 -04001070 const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(mData.getAttachedFragmentShader());
Brandon Jones44151a92014-09-10 11:32:25 -07001071
Jamie Madill5c6b7bf2015-08-17 12:53:35 -04001072 const gl::InputLayout &defaultInputLayout =
1073 GetDefaultInputLayoutFromShader(mData.getAttachedVertexShader());
Jamie Madille4ea2022015-03-26 20:35:05 +00001074 ShaderExecutableD3D *defaultVertexExecutable = NULL;
1075 gl::Error error = getVertexExecutableForInputLayout(defaultInputLayout, &defaultVertexExecutable, &infoLog);
1076 if (error.isError())
Austin Kinross434953e2015-02-20 10:49:51 -08001077 {
Jamie Madille4ea2022015-03-26 20:35:05 +00001078 return LinkResult(false, error);
1079 }
Austin Kinross434953e2015-02-20 10:49:51 -08001080
Brandon Joneseb994362014-09-24 10:27:28 -07001081 std::vector<GLenum> defaultPixelOutput = GetDefaultOutputLayoutFromShader(getPixelShaderKey());
Geoff Lang359ef262015-01-05 14:42:29 -05001082 ShaderExecutableD3D *defaultPixelExecutable = NULL;
Jamie Madille4ea2022015-03-26 20:35:05 +00001083 error = getPixelExecutableForOutputLayout(defaultPixelOutput, &defaultPixelExecutable, &infoLog);
Geoff Langb543aff2014-09-30 14:52:54 -04001084 if (error.isError())
1085 {
Geoff Lang7dd2e102014-11-10 15:19:26 -05001086 return LinkResult(false, error);
Geoff Langb543aff2014-09-30 14:52:54 -04001087 }
Brandon Jones44151a92014-09-10 11:32:25 -07001088
Brandon Joneseb994362014-09-24 10:27:28 -07001089 if (usesGeometryShader())
1090 {
Jamie Madill532061b2015-08-31 15:16:45 -04001091 std::string geometryHLSL =
1092 mDynamicHLSL->generateGeometryShaderHLSL(registers, fragmentShaderD3D, packedVaryings);
Brandon Jones44151a92014-09-10 11:32:25 -07001093
Jamie Madillada9ecc2015-08-17 12:53:37 -04001094 error = mRenderer->compileToExecutable(
1095 infoLog, geometryHLSL, SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings,
1096 (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS),
1097 D3DCompilerWorkarounds(), &mGeometryExecutable);
Geoff Langb543aff2014-09-30 14:52:54 -04001098 if (error.isError())
1099 {
Geoff Lang7dd2e102014-11-10 15:19:26 -05001100 return LinkResult(false, error);
Geoff Langb543aff2014-09-30 14:52:54 -04001101 }
Brandon Joneseb994362014-09-24 10:27:28 -07001102 }
1103
Brandon Jones091540d2014-10-29 11:32:04 -07001104#if ANGLE_SHADER_DEBUG_INFO == ANGLE_ENABLED
Jamie Madill532061b2015-08-31 15:16:45 -04001105 const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(mData.getAttachedVertexShader());
1106
Tibor den Ouden97049c62014-10-06 21:39:16 +02001107 if (usesGeometryShader() && mGeometryExecutable)
1108 {
1109 // Geometry shaders are currently only used internally, so there is no corresponding shader object at the interface level
1110 // For now the geometry shader debug info is pre-pended to the vertex shader, this is a bit of a clutch
1111 vertexShaderD3D->appendDebugInfo("// GEOMETRY SHADER BEGIN\n\n");
1112 vertexShaderD3D->appendDebugInfo(mGeometryExecutable->getDebugInfo());
1113 vertexShaderD3D->appendDebugInfo("\nGEOMETRY SHADER END\n\n\n");
1114 }
1115
1116 if (defaultVertexExecutable)
1117 {
1118 vertexShaderD3D->appendDebugInfo(defaultVertexExecutable->getDebugInfo());
1119 }
1120
1121 if (defaultPixelExecutable)
1122 {
1123 fragmentShaderD3D->appendDebugInfo(defaultPixelExecutable->getDebugInfo());
1124 }
1125#endif
1126
Geoff Langb543aff2014-09-30 14:52:54 -04001127 bool linkSuccess = (defaultVertexExecutable && defaultPixelExecutable && (!usesGeometryShader() || mGeometryExecutable));
Geoff Lang7dd2e102014-11-10 15:19:26 -05001128 return LinkResult(linkSuccess, gl::Error(GL_NO_ERROR));
Brandon Jones18bd4102014-09-22 14:21:44 -07001129}
1130
Jamie Madill63069df2015-09-01 17:26:41 +00001131LinkResult ProgramD3D::link(const gl::Data &data,
1132 gl::InfoLog &infoLog,
1133 gl::Shader *fragmentShader,
1134 gl::Shader *vertexShader)
Brandon Jones22502d52014-08-29 16:58:36 -07001135{
Jamie Madill63069df2015-09-01 17:26:41 +00001136 ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(vertexShader);
1137 ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(fragmentShader);
Brandon Joneseb994362014-09-24 10:27:28 -07001138
Jamie Madillb8359272015-08-26 15:57:14 -04001139 mSamplersPS.resize(data.caps->maxTextureImageUnits);
Jamie Madill63069df2015-09-01 17:26:41 +00001140 mSamplersVS.resize(data.caps->maxVertexTextureImageUnits);
1141
1142 mPixelHLSL = fragmentShaderD3D->getTranslatedSource();
1143 fragmentShaderD3D->generateWorkarounds(&mPixelWorkarounds);
Brandon Jones22502d52014-08-29 16:58:36 -07001144
1145 mVertexHLSL = vertexShaderD3D->getTranslatedSource();
Arun Patole44efa0b2015-03-04 17:11:05 +05301146 vertexShaderD3D->generateWorkarounds(&mVertexWorkarounds);
Brandon Jones44151a92014-09-10 11:32:25 -07001147 mShaderVersion = vertexShaderD3D->getShaderVersion();
Brandon Jones22502d52014-08-29 16:58:36 -07001148
Austin Kinross02df7962015-07-01 10:03:42 -07001149 if (mRenderer->getRendererLimitations().noFrontFacingSupport)
1150 {
1151 if (fragmentShaderD3D->usesFrontFacing())
1152 {
1153 infoLog << "The current renderer doesn't support gl_FrontFacing";
1154 return LinkResult(false, gl::Error(GL_NO_ERROR));
1155 }
1156 }
1157
Jamie Madill532061b2015-08-31 15:16:45 -04001158 std::vector<PackedVarying> packedVaryings =
1159 MergeVaryings(*vertexShader, *fragmentShader, mData.getTransformFeedbackVaryingNames());
1160
Brandon Jones22502d52014-08-29 16:58:36 -07001161 // Map the varyings to the register file
Jamie Madill532061b2015-08-31 15:16:45 -04001162 int registers = mDynamicHLSL->packVaryings(infoLog, &packedVaryings,
Jamie Madill31c8c562015-08-19 14:08:03 -04001163 mData.getTransformFeedbackVaryingNames());
Brandon Jones22502d52014-08-29 16:58:36 -07001164
Jamie Madill31c8c562015-08-19 14:08:03 -04001165 if (registers < 0)
Brandon Jones22502d52014-08-29 16:58:36 -07001166 {
Geoff Lang7dd2e102014-11-10 15:19:26 -05001167 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Jones22502d52014-08-29 16:58:36 -07001168 }
1169
Jamie Madillccdf74b2015-08-18 10:46:12 -04001170 std::vector<gl::LinkedVarying> linkedVaryings;
Jamie Madill4cff2472015-08-21 16:53:18 -04001171 if (!mDynamicHLSL->generateShaderLinkHLSL(data, mData, infoLog, registers, mPixelHLSL,
Jamie Madill532061b2015-08-31 15:16:45 -04001172 mVertexHLSL, packedVaryings, &linkedVaryings,
1173 &mPixelShaderKey, &mUsesFragDepth))
Brandon Jones22502d52014-08-29 16:58:36 -07001174 {
Geoff Lang7dd2e102014-11-10 15:19:26 -05001175 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Jones22502d52014-08-29 16:58:36 -07001176 }
1177
Brandon Jones44151a92014-09-10 11:32:25 -07001178 mUsesPointSize = vertexShaderD3D->usesPointSize();
1179
Jamie Madill63805b42015-08-25 13:17:39 -04001180 initSemanticIndex();
Jamie Madill437d2662014-12-05 14:23:35 -05001181
Jamie Madillea918db2015-08-18 14:48:59 -04001182 if (!defineUniforms(infoLog, *data.caps))
1183 {
1184 return LinkResult(false, gl::Error(GL_NO_ERROR));
1185 }
1186
Jamie Madille473dee2015-08-18 14:49:01 -04001187 defineUniformBlocks(*data.caps);
1188
Jamie Madillccdf74b2015-08-18 10:46:12 -04001189 gatherTransformFeedbackVaryings(linkedVaryings);
1190
Jamie Madill532061b2015-08-31 15:16:45 -04001191 LinkResult result = compileProgramExecutables(infoLog, registers, packedVaryings);
Jamie Madill31c8c562015-08-19 14:08:03 -04001192 if (result.error.isError() || !result.linkSuccess)
1193 {
1194 infoLog << "Failed to create D3D shaders.";
1195 return result;
1196 }
1197
Geoff Lang7dd2e102014-11-10 15:19:26 -05001198 return LinkResult(true, gl::Error(GL_NO_ERROR));
Brandon Jones22502d52014-08-29 16:58:36 -07001199}
1200
Jamie Madill36cfd6a2015-08-18 10:46:20 -04001201GLboolean ProgramD3D::validate(const gl::Caps &caps, gl::InfoLog *infoLog)
1202{
1203 applyUniforms();
1204 return validateSamplers(infoLog, caps);
1205}
1206
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001207void ProgramD3D::initializeUniformStorage()
Brandon Jonesc9610c52014-08-25 17:02:59 -07001208{
1209 // Compute total default block size
1210 unsigned int vertexRegisters = 0;
1211 unsigned int fragmentRegisters = 0;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001212 for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
Brandon Jonesc9610c52014-08-25 17:02:59 -07001213 {
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001214 const gl::LinkedUniform &uniform = *mUniforms[uniformIndex];
Brandon Jonesc9610c52014-08-25 17:02:59 -07001215
Geoff Lang2ec386b2014-12-03 14:44:38 -05001216 if (!gl::IsSamplerType(uniform.type))
Brandon Jonesc9610c52014-08-25 17:02:59 -07001217 {
1218 if (uniform.isReferencedByVertexShader())
1219 {
1220 vertexRegisters = std::max(vertexRegisters, uniform.vsRegisterIndex + uniform.registerCount);
1221 }
1222 if (uniform.isReferencedByFragmentShader())
1223 {
1224 fragmentRegisters = std::max(fragmentRegisters, uniform.psRegisterIndex + uniform.registerCount);
1225 }
1226 }
1227 }
1228
1229 mVertexUniformStorage = mRenderer->createUniformStorage(vertexRegisters * 16u);
1230 mFragmentUniformStorage = mRenderer->createUniformStorage(fragmentRegisters * 16u);
1231}
1232
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001233gl::Error ProgramD3D::applyUniforms()
Brandon Jones18bd4102014-09-22 14:21:44 -07001234{
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001235 updateSamplerMapping();
1236
1237 gl::Error error = mRenderer->applyUniforms(*this, mUniforms);
1238 if (error.isError())
1239 {
1240 return error;
1241 }
1242
1243 for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
1244 {
1245 mUniforms[uniformIndex]->dirty = false;
1246 }
1247
1248 return gl::Error(GL_NO_ERROR);
Brandon Jones18bd4102014-09-22 14:21:44 -07001249}
1250
Jamie Madilld1fe1642015-08-21 16:26:04 -04001251gl::Error ProgramD3D::applyUniformBuffers(const gl::Data &data)
Brandon Jones18bd4102014-09-22 14:21:44 -07001252{
Jamie Madill03260fa2015-06-22 13:57:22 -04001253 mVertexUBOCache.clear();
1254 mFragmentUBOCache.clear();
Brandon Jones18bd4102014-09-22 14:21:44 -07001255
1256 const unsigned int reservedBuffersInVS = mRenderer->getReservedVertexUniformBuffers();
1257 const unsigned int reservedBuffersInFS = mRenderer->getReservedFragmentUniformBuffers();
1258
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001259 for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < mUniformBlocks.size(); uniformBlockIndex++)
Brandon Jones18bd4102014-09-22 14:21:44 -07001260 {
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001261 gl::UniformBlock *uniformBlock = mUniformBlocks[uniformBlockIndex];
Jamie Madilld1fe1642015-08-21 16:26:04 -04001262 GLuint blockBinding = mData.getUniformBlockBinding(uniformBlockIndex);
Brandon Jones18bd4102014-09-22 14:21:44 -07001263
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00001264 ASSERT(uniformBlock);
Brandon Jones18bd4102014-09-22 14:21:44 -07001265
1266 // Unnecessary to apply an unreferenced standard or shared UBO
1267 if (!uniformBlock->isReferencedByVertexShader() && !uniformBlock->isReferencedByFragmentShader())
1268 {
1269 continue;
1270 }
1271
1272 if (uniformBlock->isReferencedByVertexShader())
1273 {
1274 unsigned int registerIndex = uniformBlock->vsRegisterIndex - reservedBuffersInVS;
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00001275 ASSERT(registerIndex < data.caps->maxVertexUniformBlocks);
Jamie Madill03260fa2015-06-22 13:57:22 -04001276
Jamie Madill969194d2015-07-20 14:36:56 -04001277 if (mVertexUBOCache.size() <= registerIndex)
Jamie Madill03260fa2015-06-22 13:57:22 -04001278 {
1279 mVertexUBOCache.resize(registerIndex + 1, -1);
1280 }
1281
1282 ASSERT(mVertexUBOCache[registerIndex] == -1);
1283 mVertexUBOCache[registerIndex] = blockBinding;
Brandon Jones18bd4102014-09-22 14:21:44 -07001284 }
1285
1286 if (uniformBlock->isReferencedByFragmentShader())
1287 {
1288 unsigned int registerIndex = uniformBlock->psRegisterIndex - reservedBuffersInFS;
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00001289 ASSERT(registerIndex < data.caps->maxFragmentUniformBlocks);
Jamie Madill03260fa2015-06-22 13:57:22 -04001290
1291 if (mFragmentUBOCache.size() <= registerIndex)
1292 {
1293 mFragmentUBOCache.resize(registerIndex + 1, -1);
1294 }
1295
1296 ASSERT(mFragmentUBOCache[registerIndex] == -1);
1297 mFragmentUBOCache[registerIndex] = blockBinding;
Brandon Jones18bd4102014-09-22 14:21:44 -07001298 }
1299 }
1300
Jamie Madill03260fa2015-06-22 13:57:22 -04001301 return mRenderer->setUniformBuffers(data, mVertexUBOCache, mFragmentUBOCache);
Brandon Jones18bd4102014-09-22 14:21:44 -07001302}
1303
Jamie Madille473dee2015-08-18 14:49:01 -04001304void ProgramD3D::assignUniformBlockRegister(gl::UniformBlock *uniformBlock,
1305 GLenum shader,
1306 unsigned int registerIndex,
1307 const gl::Caps &caps)
Brandon Jones18bd4102014-09-22 14:21:44 -07001308{
Jamie Madille473dee2015-08-18 14:49:01 -04001309 // Validation done in the GL-level Program.
Brandon Jones18bd4102014-09-22 14:21:44 -07001310 if (shader == GL_VERTEX_SHADER)
1311 {
1312 uniformBlock->vsRegisterIndex = registerIndex;
Jamie Madille473dee2015-08-18 14:49:01 -04001313 ASSERT(registerIndex < caps.maxVertexUniformBlocks);
Brandon Jones18bd4102014-09-22 14:21:44 -07001314 }
1315 else if (shader == GL_FRAGMENT_SHADER)
1316 {
1317 uniformBlock->psRegisterIndex = registerIndex;
Jamie Madille473dee2015-08-18 14:49:01 -04001318 ASSERT(registerIndex < caps.maxFragmentUniformBlocks);
Brandon Jones18bd4102014-09-22 14:21:44 -07001319 }
1320 else UNREACHABLE();
Brandon Jones18bd4102014-09-22 14:21:44 -07001321}
1322
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001323void ProgramD3D::dirtyAllUniforms()
Brandon Jones18bd4102014-09-22 14:21:44 -07001324{
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001325 unsigned int numUniforms = static_cast<unsigned int>(mUniforms.size());
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001326 for (unsigned int index = 0; index < numUniforms; index++)
Brandon Jones18bd4102014-09-22 14:21:44 -07001327 {
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001328 mUniforms[index]->dirty = true;
Brandon Jones18bd4102014-09-22 14:21:44 -07001329 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001330}
1331
1332void ProgramD3D::setUniform1fv(GLint location, GLsizei count, const GLfloat* v)
1333{
1334 setUniform(location, count, v, GL_FLOAT);
1335}
1336
1337void ProgramD3D::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
1338{
1339 setUniform(location, count, v, GL_FLOAT_VEC2);
1340}
1341
1342void ProgramD3D::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
1343{
1344 setUniform(location, count, v, GL_FLOAT_VEC3);
1345}
1346
1347void ProgramD3D::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
1348{
1349 setUniform(location, count, v, GL_FLOAT_VEC4);
1350}
1351
1352void ProgramD3D::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1353{
1354 setUniformMatrixfv<2, 2>(location, count, transpose, value, GL_FLOAT_MAT2);
1355}
1356
1357void ProgramD3D::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1358{
1359 setUniformMatrixfv<3, 3>(location, count, transpose, value, GL_FLOAT_MAT3);
1360}
1361
1362void ProgramD3D::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1363{
1364 setUniformMatrixfv<4, 4>(location, count, transpose, value, GL_FLOAT_MAT4);
1365}
1366
1367void ProgramD3D::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1368{
1369 setUniformMatrixfv<2, 3>(location, count, transpose, value, GL_FLOAT_MAT2x3);
1370}
1371
1372void ProgramD3D::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1373{
1374 setUniformMatrixfv<3, 2>(location, count, transpose, value, GL_FLOAT_MAT3x2);
1375}
1376
1377void ProgramD3D::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1378{
1379 setUniformMatrixfv<2, 4>(location, count, transpose, value, GL_FLOAT_MAT2x4);
1380}
1381
1382void ProgramD3D::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1383{
1384 setUniformMatrixfv<4, 2>(location, count, transpose, value, GL_FLOAT_MAT4x2);
1385}
1386
1387void ProgramD3D::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1388{
1389 setUniformMatrixfv<3, 4>(location, count, transpose, value, GL_FLOAT_MAT3x4);
1390}
1391
1392void ProgramD3D::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1393{
1394 setUniformMatrixfv<4, 3>(location, count, transpose, value, GL_FLOAT_MAT4x3);
1395}
1396
1397void ProgramD3D::setUniform1iv(GLint location, GLsizei count, const GLint *v)
1398{
1399 setUniform(location, count, v, GL_INT);
1400}
1401
1402void ProgramD3D::setUniform2iv(GLint location, GLsizei count, const GLint *v)
1403{
1404 setUniform(location, count, v, GL_INT_VEC2);
1405}
1406
1407void ProgramD3D::setUniform3iv(GLint location, GLsizei count, const GLint *v)
1408{
1409 setUniform(location, count, v, GL_INT_VEC3);
1410}
1411
1412void ProgramD3D::setUniform4iv(GLint location, GLsizei count, const GLint *v)
1413{
1414 setUniform(location, count, v, GL_INT_VEC4);
1415}
1416
1417void ProgramD3D::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
1418{
1419 setUniform(location, count, v, GL_UNSIGNED_INT);
1420}
1421
1422void ProgramD3D::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
1423{
1424 setUniform(location, count, v, GL_UNSIGNED_INT_VEC2);
1425}
1426
1427void ProgramD3D::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
1428{
1429 setUniform(location, count, v, GL_UNSIGNED_INT_VEC3);
1430}
1431
1432void ProgramD3D::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
1433{
1434 setUniform(location, count, v, GL_UNSIGNED_INT_VEC4);
1435}
1436
1437void ProgramD3D::getUniformfv(GLint location, GLfloat *params)
1438{
1439 getUniformv(location, params, GL_FLOAT);
1440}
1441
1442void ProgramD3D::getUniformiv(GLint location, GLint *params)
1443{
1444 getUniformv(location, params, GL_INT);
1445}
1446
1447void ProgramD3D::getUniformuiv(GLint location, GLuint *params)
1448{
1449 getUniformv(location, params, GL_UNSIGNED_INT);
1450}
1451
Jamie Madillea918db2015-08-18 14:48:59 -04001452bool ProgramD3D::defineUniforms(gl::InfoLog &infoLog, const gl::Caps &caps)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001453{
Jamie Madillea918db2015-08-18 14:48:59 -04001454 const gl::Shader *vertexShader = mData.getAttachedVertexShader();
1455 const std::vector<sh::Uniform> &vertexUniforms = vertexShader->getUniforms();
1456 const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(vertexShader);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001457
Jamie Madillea918db2015-08-18 14:48:59 -04001458 for (const sh::Uniform &uniform : vertexUniforms)
Brandon Jones18bd4102014-09-22 14:21:44 -07001459 {
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001460 if (uniform.staticUse)
1461 {
Jamie Madill55def582015-05-04 11:24:57 -04001462 unsigned int registerBase = uniform.isBuiltIn() ? GL_INVALID_INDEX :
1463 vertexShaderD3D->getUniformRegister(uniform.name);
1464 defineUniformBase(vertexShaderD3D, uniform, registerBase);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001465 }
1466 }
1467
Jamie Madillea918db2015-08-18 14:48:59 -04001468 const gl::Shader *fragmentShader = mData.getAttachedFragmentShader();
1469 const std::vector<sh::Uniform> &fragmentUniforms = fragmentShader->getUniforms();
1470 const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(fragmentShader);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001471
Jamie Madillea918db2015-08-18 14:48:59 -04001472 for (const sh::Uniform &uniform : fragmentUniforms)
1473 {
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001474 if (uniform.staticUse)
1475 {
Jamie Madill55def582015-05-04 11:24:57 -04001476 unsigned int registerBase = uniform.isBuiltIn() ? GL_INVALID_INDEX :
1477 fragmentShaderD3D->getUniformRegister(uniform.name);
1478 defineUniformBase(fragmentShaderD3D, uniform, registerBase);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001479 }
1480 }
1481
Jamie Madillea918db2015-08-18 14:48:59 -04001482 // TODO(jmadill): move the validation part to gl::Program
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001483 if (!indexUniforms(infoLog, caps))
1484 {
1485 return false;
1486 }
1487
1488 initializeUniformStorage();
1489
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001490 return true;
1491}
1492
Geoff Lang492a7e42014-11-05 13:27:06 -05001493void ProgramD3D::defineUniformBase(const ShaderD3D *shader, const sh::Uniform &uniform, unsigned int uniformRegister)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001494{
Jamie Madill55def582015-05-04 11:24:57 -04001495 if (uniformRegister == GL_INVALID_INDEX)
1496 {
1497 defineUniform(shader, uniform, uniform.name, nullptr);
1498 return;
1499 }
1500
Geoff Lang492a7e42014-11-05 13:27:06 -05001501 ShShaderOutput outputType = shader->getCompilerOutputType();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001502 sh::HLSLBlockEncoder encoder(sh::HLSLBlockEncoder::GetStrategyFor(outputType));
1503 encoder.skipRegisters(uniformRegister);
1504
1505 defineUniform(shader, uniform, uniform.name, &encoder);
1506}
1507
Geoff Lang492a7e42014-11-05 13:27:06 -05001508void ProgramD3D::defineUniform(const ShaderD3D *shader, const sh::ShaderVariable &uniform,
1509 const std::string &fullName, sh::HLSLBlockEncoder *encoder)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001510{
1511 if (uniform.isStruct())
1512 {
1513 for (unsigned int elementIndex = 0; elementIndex < uniform.elementCount(); elementIndex++)
1514 {
1515 const std::string &elementString = (uniform.isArray() ? ArrayString(elementIndex) : "");
1516
Jamie Madill55def582015-05-04 11:24:57 -04001517 if (encoder)
1518 encoder->enterAggregateType();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001519
1520 for (size_t fieldIndex = 0; fieldIndex < uniform.fields.size(); fieldIndex++)
1521 {
1522 const sh::ShaderVariable &field = uniform.fields[fieldIndex];
1523 const std::string &fieldFullName = (fullName + elementString + "." + field.name);
1524
1525 defineUniform(shader, field, fieldFullName, encoder);
1526 }
1527
Jamie Madill55def582015-05-04 11:24:57 -04001528 if (encoder)
1529 encoder->exitAggregateType();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001530 }
1531 }
1532 else // Not a struct
1533 {
1534 // Arrays are treated as aggregate types
Jamie Madill55def582015-05-04 11:24:57 -04001535 if (uniform.isArray() && encoder)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001536 {
1537 encoder->enterAggregateType();
1538 }
1539
1540 gl::LinkedUniform *linkedUniform = getUniformByName(fullName);
1541
Jamie Madill2857f482015-02-09 15:35:29 -05001542 // Advance the uniform offset, to track registers allocation for structs
Jamie Madill55def582015-05-04 11:24:57 -04001543 sh::BlockMemberInfo blockInfo = encoder ?
1544 encoder->encodeType(uniform.type, uniform.arraySize, false) :
1545 sh::BlockMemberInfo::getDefaultBlockInfo();
Jamie Madill2857f482015-02-09 15:35:29 -05001546
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001547 if (!linkedUniform)
1548 {
1549 linkedUniform = new gl::LinkedUniform(uniform.type, uniform.precision, fullName, uniform.arraySize,
Jamie Madill2857f482015-02-09 15:35:29 -05001550 -1, sh::BlockMemberInfo::getDefaultBlockInfo());
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001551 ASSERT(linkedUniform);
Jamie Madill55def582015-05-04 11:24:57 -04001552
1553 if (encoder)
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001554 linkedUniform->registerElement = static_cast<unsigned int>(
1555 sh::HLSLBlockEncoder::getBlockRegisterElement(blockInfo));
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001556 mUniforms.push_back(linkedUniform);
1557 }
1558
Jamie Madill55def582015-05-04 11:24:57 -04001559 if (encoder)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001560 {
Jamie Madill55def582015-05-04 11:24:57 -04001561 if (shader->getShaderType() == GL_FRAGMENT_SHADER)
1562 {
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001563 linkedUniform->psRegisterIndex =
1564 static_cast<unsigned int>(sh::HLSLBlockEncoder::getBlockRegister(blockInfo));
Jamie Madill55def582015-05-04 11:24:57 -04001565 }
1566 else if (shader->getShaderType() == GL_VERTEX_SHADER)
1567 {
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001568 linkedUniform->vsRegisterIndex =
1569 static_cast<unsigned int>(sh::HLSLBlockEncoder::getBlockRegister(blockInfo));
Jamie Madill55def582015-05-04 11:24:57 -04001570 }
1571 else UNREACHABLE();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001572 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001573
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001574 // Arrays are treated as aggregate types
Jamie Madill55def582015-05-04 11:24:57 -04001575 if (uniform.isArray() && encoder)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001576 {
1577 encoder->exitAggregateType();
1578 }
1579 }
1580}
1581
Jamie Madille473dee2015-08-18 14:49:01 -04001582void ProgramD3D::defineUniformBlocks(const gl::Caps &caps)
1583{
1584 const gl::Shader *vertexShader = mData.getAttachedVertexShader();
1585
1586 for (const sh::InterfaceBlock &vertexBlock : vertexShader->getInterfaceBlocks())
1587 {
1588 if (vertexBlock.staticUse || vertexBlock.layout != sh::BLOCKLAYOUT_PACKED)
1589 {
1590 defineUniformBlock(*vertexShader, vertexBlock, caps);
1591 }
1592 }
1593
1594 const gl::Shader *fragmentShader = mData.getAttachedFragmentShader();
1595
1596 for (const sh::InterfaceBlock &fragmentBlock : fragmentShader->getInterfaceBlocks())
1597 {
1598 if (fragmentBlock.staticUse || fragmentBlock.layout != sh::BLOCKLAYOUT_PACKED)
1599 {
1600 defineUniformBlock(*fragmentShader, fragmentBlock, caps);
1601 }
1602 }
1603}
1604
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001605template <typename T>
1606static inline void SetIfDirty(T *dest, const T& source, bool *dirtyFlag)
1607{
1608 ASSERT(dest != NULL);
1609 ASSERT(dirtyFlag != NULL);
1610
1611 *dirtyFlag = *dirtyFlag || (memcmp(dest, &source, sizeof(T)) != 0);
1612 *dest = source;
1613}
1614
1615template <typename T>
1616void ProgramD3D::setUniform(GLint location, GLsizei count, const T* v, GLenum targetUniformType)
1617{
1618 const int components = gl::VariableComponentCount(targetUniformType);
1619 const GLenum targetBoolType = gl::VariableBoolVectorType(targetUniformType);
1620
1621 gl::LinkedUniform *targetUniform = getUniformByLocation(location);
1622
1623 int elementCount = targetUniform->elementCount();
1624
1625 count = std::min(elementCount - (int)mUniformIndex[location].element, count);
1626
1627 if (targetUniform->type == targetUniformType)
1628 {
1629 T *target = reinterpret_cast<T*>(targetUniform->data) + mUniformIndex[location].element * 4;
1630
1631 for (int i = 0; i < count; i++)
1632 {
1633 T *dest = target + (i * 4);
1634 const T *source = v + (i * components);
1635
1636 for (int c = 0; c < components; c++)
1637 {
1638 SetIfDirty(dest + c, source[c], &targetUniform->dirty);
1639 }
1640 for (int c = components; c < 4; c++)
1641 {
1642 SetIfDirty(dest + c, T(0), &targetUniform->dirty);
1643 }
1644 }
1645 }
1646 else if (targetUniform->type == targetBoolType)
1647 {
1648 GLint *boolParams = reinterpret_cast<GLint*>(targetUniform->data) + mUniformIndex[location].element * 4;
1649
1650 for (int i = 0; i < count; i++)
1651 {
1652 GLint *dest = boolParams + (i * 4);
1653 const T *source = v + (i * components);
1654
1655 for (int c = 0; c < components; c++)
1656 {
1657 SetIfDirty(dest + c, (source[c] == static_cast<T>(0)) ? GL_FALSE : GL_TRUE, &targetUniform->dirty);
1658 }
1659 for (int c = components; c < 4; c++)
1660 {
1661 SetIfDirty(dest + c, GL_FALSE, &targetUniform->dirty);
1662 }
1663 }
1664 }
Geoff Lang2ec386b2014-12-03 14:44:38 -05001665 else if (gl::IsSamplerType(targetUniform->type))
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001666 {
1667 ASSERT(targetUniformType == GL_INT);
1668
1669 GLint *target = reinterpret_cast<GLint*>(targetUniform->data) + mUniformIndex[location].element * 4;
1670
1671 bool wasDirty = targetUniform->dirty;
1672
1673 for (int i = 0; i < count; i++)
1674 {
1675 GLint *dest = target + (i * 4);
1676 const GLint *source = reinterpret_cast<const GLint*>(v) + (i * components);
1677
1678 SetIfDirty(dest + 0, source[0], &targetUniform->dirty);
1679 SetIfDirty(dest + 1, 0, &targetUniform->dirty);
1680 SetIfDirty(dest + 2, 0, &targetUniform->dirty);
1681 SetIfDirty(dest + 3, 0, &targetUniform->dirty);
1682 }
1683
1684 if (!wasDirty && targetUniform->dirty)
1685 {
1686 mDirtySamplerMapping = true;
1687 }
Brandon Jones18bd4102014-09-22 14:21:44 -07001688 }
1689 else UNREACHABLE();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001690}
Brandon Jones18bd4102014-09-22 14:21:44 -07001691
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001692template<typename T>
1693bool transposeMatrix(T *target, const GLfloat *value, int targetWidth, int targetHeight, int srcWidth, int srcHeight)
1694{
1695 bool dirty = false;
1696 int copyWidth = std::min(targetHeight, srcWidth);
1697 int copyHeight = std::min(targetWidth, srcHeight);
1698
1699 for (int x = 0; x < copyWidth; x++)
1700 {
1701 for (int y = 0; y < copyHeight; y++)
1702 {
1703 SetIfDirty(target + (x * targetWidth + y), static_cast<T>(value[y * srcWidth + x]), &dirty);
1704 }
1705 }
1706 // clear unfilled right side
1707 for (int y = 0; y < copyWidth; y++)
1708 {
1709 for (int x = copyHeight; x < targetWidth; x++)
1710 {
1711 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
1712 }
1713 }
1714 // clear unfilled bottom.
1715 for (int y = copyWidth; y < targetHeight; y++)
1716 {
1717 for (int x = 0; x < targetWidth; x++)
1718 {
1719 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
1720 }
1721 }
1722
1723 return dirty;
1724}
1725
1726template<typename T>
1727bool expandMatrix(T *target, const GLfloat *value, int targetWidth, int targetHeight, int srcWidth, int srcHeight)
1728{
1729 bool dirty = false;
1730 int copyWidth = std::min(targetWidth, srcWidth);
1731 int copyHeight = std::min(targetHeight, srcHeight);
1732
1733 for (int y = 0; y < copyHeight; y++)
1734 {
1735 for (int x = 0; x < copyWidth; x++)
1736 {
1737 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(value[y * srcWidth + x]), &dirty);
1738 }
1739 }
1740 // clear unfilled right side
1741 for (int y = 0; y < copyHeight; y++)
1742 {
1743 for (int x = copyWidth; x < targetWidth; x++)
1744 {
1745 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
1746 }
1747 }
1748 // clear unfilled bottom.
1749 for (int y = copyHeight; y < targetHeight; y++)
1750 {
1751 for (int x = 0; x < targetWidth; x++)
1752 {
1753 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
1754 }
1755 }
1756
1757 return dirty;
1758}
1759
1760template <int cols, int rows>
1761void ProgramD3D::setUniformMatrixfv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value, GLenum targetUniformType)
1762{
1763 gl::LinkedUniform *targetUniform = getUniformByLocation(location);
1764
1765 int elementCount = targetUniform->elementCount();
1766
1767 count = std::min(elementCount - (int)mUniformIndex[location].element, count);
1768 const unsigned int targetMatrixStride = (4 * rows);
1769 GLfloat *target = (GLfloat*)(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * targetMatrixStride);
1770
1771 for (int i = 0; i < count; i++)
1772 {
1773 // Internally store matrices as transposed versions to accomodate HLSL matrix indexing
1774 if (transpose == GL_FALSE)
1775 {
1776 targetUniform->dirty = transposeMatrix<GLfloat>(target, value, 4, rows, rows, cols) || targetUniform->dirty;
1777 }
1778 else
1779 {
1780 targetUniform->dirty = expandMatrix<GLfloat>(target, value, 4, rows, cols, rows) || targetUniform->dirty;
1781 }
1782 target += targetMatrixStride;
1783 value += cols * rows;
1784 }
1785}
1786
1787template <typename T>
1788void ProgramD3D::getUniformv(GLint location, T *params, GLenum uniformType)
1789{
1790 gl::LinkedUniform *targetUniform = mUniforms[mUniformIndex[location].index];
1791
1792 if (gl::IsMatrixType(targetUniform->type))
1793 {
1794 const int rows = gl::VariableRowCount(targetUniform->type);
1795 const int cols = gl::VariableColumnCount(targetUniform->type);
1796 transposeMatrix(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4 * rows, rows, cols, 4, rows);
1797 }
1798 else if (uniformType == gl::VariableComponentType(targetUniform->type))
1799 {
1800 unsigned int size = gl::VariableComponentCount(targetUniform->type);
1801 memcpy(params, targetUniform->data + mUniformIndex[location].element * 4 * sizeof(T),
1802 size * sizeof(T));
1803 }
1804 else
1805 {
1806 unsigned int size = gl::VariableComponentCount(targetUniform->type);
1807 switch (gl::VariableComponentType(targetUniform->type))
1808 {
1809 case GL_BOOL:
1810 {
1811 GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
1812
1813 for (unsigned int i = 0; i < size; i++)
1814 {
1815 params[i] = (boolParams[i] == GL_FALSE) ? static_cast<T>(0) : static_cast<T>(1);
1816 }
1817 }
1818 break;
1819
1820 case GL_FLOAT:
1821 {
1822 GLfloat *floatParams = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4;
1823
1824 for (unsigned int i = 0; i < size; i++)
1825 {
1826 params[i] = static_cast<T>(floatParams[i]);
1827 }
1828 }
1829 break;
1830
1831 case GL_INT:
1832 {
1833 GLint *intParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
1834
1835 for (unsigned int i = 0; i < size; i++)
1836 {
1837 params[i] = static_cast<T>(intParams[i]);
1838 }
1839 }
1840 break;
1841
1842 case GL_UNSIGNED_INT:
1843 {
1844 GLuint *uintParams = (GLuint*)targetUniform->data + mUniformIndex[location].element * 4;
1845
1846 for (unsigned int i = 0; i < size; i++)
1847 {
1848 params[i] = static_cast<T>(uintParams[i]);
1849 }
1850 }
1851 break;
1852
1853 default: UNREACHABLE();
1854 }
1855 }
1856}
1857
1858template <typename VarT>
1859void ProgramD3D::defineUniformBlockMembers(const std::vector<VarT> &fields, const std::string &prefix, int blockIndex,
1860 sh::BlockLayoutEncoder *encoder, std::vector<unsigned int> *blockUniformIndexes,
1861 bool inRowMajorLayout)
1862{
1863 for (unsigned int uniformIndex = 0; uniformIndex < fields.size(); uniformIndex++)
1864 {
1865 const VarT &field = fields[uniformIndex];
1866 const std::string &fieldName = (prefix.empty() ? field.name : prefix + "." + field.name);
1867
1868 if (field.isStruct())
1869 {
1870 bool rowMajorLayout = (inRowMajorLayout || IsRowMajorLayout(field));
1871
1872 for (unsigned int arrayElement = 0; arrayElement < field.elementCount(); arrayElement++)
1873 {
1874 encoder->enterAggregateType();
1875
1876 const std::string uniformElementName = fieldName + (field.isArray() ? ArrayString(arrayElement) : "");
1877 defineUniformBlockMembers(field.fields, uniformElementName, blockIndex, encoder, blockUniformIndexes, rowMajorLayout);
1878
1879 encoder->exitAggregateType();
1880 }
1881 }
1882 else
1883 {
1884 bool isRowMajorMatrix = (gl::IsMatrixType(field.type) && inRowMajorLayout);
1885
1886 sh::BlockMemberInfo memberInfo = encoder->encodeType(field.type, field.arraySize, isRowMajorMatrix);
1887
1888 gl::LinkedUniform *newUniform = new gl::LinkedUniform(field.type, field.precision, fieldName, field.arraySize,
1889 blockIndex, memberInfo);
1890
1891 // add to uniform list, but not index, since uniform block uniforms have no location
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001892 blockUniformIndexes->push_back(static_cast<GLenum>(mUniforms.size()));
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001893 mUniforms.push_back(newUniform);
1894 }
1895 }
1896}
1897
Jamie Madille473dee2015-08-18 14:49:01 -04001898void ProgramD3D::defineUniformBlock(const gl::Shader &shader,
Jamie Madilld3dfda22015-07-06 08:28:49 -04001899 const sh::InterfaceBlock &interfaceBlock,
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001900 const gl::Caps &caps)
1901{
Jamie Madillf4bf3812015-04-01 16:15:32 -04001902 const ShaderD3D* shaderD3D = GetImplAs<ShaderD3D>(&shader);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001903
1904 // create uniform block entries if they do not exist
1905 if (getUniformBlockIndex(interfaceBlock.name) == GL_INVALID_INDEX)
1906 {
1907 std::vector<unsigned int> blockUniformIndexes;
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001908 const unsigned int blockIndex = static_cast<unsigned int>(mUniformBlocks.size());
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001909
1910 // define member uniforms
1911 sh::BlockLayoutEncoder *encoder = NULL;
1912
1913 if (interfaceBlock.layout == sh::BLOCKLAYOUT_STANDARD)
1914 {
1915 encoder = new sh::Std140BlockEncoder;
1916 }
1917 else
1918 {
1919 encoder = new sh::HLSLBlockEncoder(sh::HLSLBlockEncoder::ENCODE_PACKED);
1920 }
1921 ASSERT(encoder);
1922
1923 defineUniformBlockMembers(interfaceBlock.fields, "", blockIndex, encoder, &blockUniformIndexes, interfaceBlock.isRowMajorLayout);
1924
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001925 unsigned int dataSize = static_cast<unsigned int>(encoder->getBlockSize());
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001926
1927 // create all the uniform blocks
1928 if (interfaceBlock.arraySize > 0)
1929 {
1930 for (unsigned int uniformBlockElement = 0; uniformBlockElement < interfaceBlock.arraySize; uniformBlockElement++)
1931 {
1932 gl::UniformBlock *newUniformBlock = new gl::UniformBlock(interfaceBlock.name, uniformBlockElement, dataSize);
1933 newUniformBlock->memberUniformIndexes = blockUniformIndexes;
1934 mUniformBlocks.push_back(newUniformBlock);
1935 }
1936 }
1937 else
1938 {
1939 gl::UniformBlock *newUniformBlock = new gl::UniformBlock(interfaceBlock.name, GL_INVALID_INDEX, dataSize);
1940 newUniformBlock->memberUniformIndexes = blockUniformIndexes;
1941 mUniformBlocks.push_back(newUniformBlock);
1942 }
1943 }
1944
1945 if (interfaceBlock.staticUse)
1946 {
1947 // Assign registers to the uniform blocks
1948 const GLuint blockIndex = getUniformBlockIndex(interfaceBlock.name);
1949 const unsigned int elementCount = std::max(1u, interfaceBlock.arraySize);
1950 ASSERT(blockIndex != GL_INVALID_INDEX);
1951 ASSERT(blockIndex + elementCount <= mUniformBlocks.size());
1952
1953 unsigned int interfaceBlockRegister = shaderD3D->getInterfaceBlockRegister(interfaceBlock.name);
1954
1955 for (unsigned int uniformBlockElement = 0; uniformBlockElement < elementCount; uniformBlockElement++)
1956 {
1957 gl::UniformBlock *uniformBlock = mUniformBlocks[blockIndex + uniformBlockElement];
1958 ASSERT(uniformBlock->name == interfaceBlock.name);
1959
Jamie Madille473dee2015-08-18 14:49:01 -04001960 assignUniformBlockRegister(uniformBlock, shader.getType(),
1961 interfaceBlockRegister + uniformBlockElement, caps);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001962 }
1963 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001964}
1965
1966bool ProgramD3D::assignSamplers(unsigned int startSamplerIndex,
Jamie Madilld3dfda22015-07-06 08:28:49 -04001967 GLenum samplerType,
1968 unsigned int samplerCount,
1969 std::vector<Sampler> &outSamplers,
1970 GLuint *outUsedRange)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001971{
1972 unsigned int samplerIndex = startSamplerIndex;
1973
1974 do
1975 {
1976 if (samplerIndex < outSamplers.size())
1977 {
1978 Sampler& sampler = outSamplers[samplerIndex];
1979 sampler.active = true;
1980 sampler.textureType = GetTextureType(samplerType);
1981 sampler.logicalTextureUnit = 0;
1982 *outUsedRange = std::max(samplerIndex + 1, *outUsedRange);
1983 }
1984 else
1985 {
1986 return false;
1987 }
1988
1989 samplerIndex++;
1990 } while (samplerIndex < startSamplerIndex + samplerCount);
1991
1992 return true;
1993}
1994
1995bool ProgramD3D::indexSamplerUniform(const gl::LinkedUniform &uniform, gl::InfoLog &infoLog, const gl::Caps &caps)
1996{
Geoff Lang2ec386b2014-12-03 14:44:38 -05001997 ASSERT(gl::IsSamplerType(uniform.type));
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001998 ASSERT(uniform.vsRegisterIndex != GL_INVALID_INDEX || uniform.psRegisterIndex != GL_INVALID_INDEX);
1999
2000 if (uniform.vsRegisterIndex != GL_INVALID_INDEX)
2001 {
2002 if (!assignSamplers(uniform.vsRegisterIndex, uniform.type, uniform.arraySize, mSamplersVS,
2003 &mUsedVertexSamplerRange))
2004 {
Jamie Madillf6113162015-05-07 11:49:21 -04002005 infoLog << "Vertex shader sampler count exceeds the maximum vertex texture units ("
2006 << mSamplersVS.size() << ").";
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002007 return false;
2008 }
2009
2010 unsigned int maxVertexVectors = mRenderer->getReservedVertexUniformVectors() + caps.maxVertexUniformVectors;
2011 if (uniform.vsRegisterIndex + uniform.registerCount > maxVertexVectors)
2012 {
Jamie Madillf6113162015-05-07 11:49:21 -04002013 infoLog << "Vertex shader active uniforms exceed GL_MAX_VERTEX_UNIFORM_VECTORS ("
2014 << caps.maxVertexUniformVectors << ").";
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002015 return false;
2016 }
2017 }
2018
2019 if (uniform.psRegisterIndex != GL_INVALID_INDEX)
2020 {
2021 if (!assignSamplers(uniform.psRegisterIndex, uniform.type, uniform.arraySize, mSamplersPS,
2022 &mUsedPixelSamplerRange))
2023 {
Jamie Madillf6113162015-05-07 11:49:21 -04002024 infoLog << "Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS ("
2025 << mSamplersPS.size() << ").";
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002026 return false;
2027 }
2028
2029 unsigned int maxFragmentVectors = mRenderer->getReservedFragmentUniformVectors() + caps.maxFragmentUniformVectors;
2030 if (uniform.psRegisterIndex + uniform.registerCount > maxFragmentVectors)
2031 {
Jamie Madillf6113162015-05-07 11:49:21 -04002032 infoLog << "Fragment shader active uniforms exceed GL_MAX_FRAGMENT_UNIFORM_VECTORS ("
2033 << caps.maxFragmentUniformVectors << ").";
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002034 return false;
2035 }
2036 }
2037
2038 return true;
2039}
2040
2041bool ProgramD3D::indexUniforms(gl::InfoLog &infoLog, const gl::Caps &caps)
2042{
2043 for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
2044 {
2045 const gl::LinkedUniform &uniform = *mUniforms[uniformIndex];
2046
Geoff Lang2ec386b2014-12-03 14:44:38 -05002047 if (gl::IsSamplerType(uniform.type))
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002048 {
2049 if (!indexSamplerUniform(uniform, infoLog, caps))
2050 {
2051 return false;
2052 }
2053 }
2054
Jamie Madill55def582015-05-04 11:24:57 -04002055 for (unsigned int arrayIndex = 0; arrayIndex < uniform.elementCount(); arrayIndex++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002056 {
Jamie Madill55def582015-05-04 11:24:57 -04002057 if (!uniform.isBuiltIn())
2058 {
Geoff Lang95137842015-06-02 15:38:43 -04002059 // Assign in-order uniform locations
Cooper Partin4d61f7e2015-08-12 10:56:50 -07002060 mUniformIndex[static_cast<GLuint>(mUniformIndex.size())] = gl::VariableLocation(
2061 uniform.name, arrayIndex, static_cast<unsigned int>(uniformIndex));
Jamie Madill55def582015-05-04 11:24:57 -04002062 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002063 }
2064 }
2065
2066 return true;
Brandon Jones18bd4102014-09-22 14:21:44 -07002067}
2068
Brandon Jonesc9610c52014-08-25 17:02:59 -07002069void ProgramD3D::reset()
2070{
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002071 ProgramImpl::reset();
2072
Brandon Joneseb994362014-09-24 10:27:28 -07002073 SafeDeleteContainer(mVertexExecutables);
2074 SafeDeleteContainer(mPixelExecutables);
2075 SafeDelete(mGeometryExecutable);
2076
Brandon Jones22502d52014-08-29 16:58:36 -07002077 mVertexHLSL.clear();
Geoff Lang6941a552015-07-27 11:06:45 -04002078 mVertexWorkarounds = D3DCompilerWorkarounds();
Brandon Jones44151a92014-09-10 11:32:25 -07002079 mShaderVersion = 100;
Brandon Jones22502d52014-08-29 16:58:36 -07002080
2081 mPixelHLSL.clear();
Geoff Lang6941a552015-07-27 11:06:45 -04002082 mPixelWorkarounds = D3DCompilerWorkarounds();
Brandon Jones22502d52014-08-29 16:58:36 -07002083 mUsesFragDepth = false;
2084 mPixelShaderKey.clear();
Brandon Jones44151a92014-09-10 11:32:25 -07002085 mUsesPointSize = false;
Brandon Jones22502d52014-08-29 16:58:36 -07002086
Brandon Jonesc9610c52014-08-25 17:02:59 -07002087 SafeDelete(mVertexUniformStorage);
2088 SafeDelete(mFragmentUniformStorage);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002089
2090 mSamplersPS.clear();
2091 mSamplersVS.clear();
2092
2093 mUsedVertexSamplerRange = 0;
2094 mUsedPixelSamplerRange = 0;
2095 mDirtySamplerMapping = true;
Jamie Madill437d2662014-12-05 14:23:35 -05002096
Jamie Madill63805b42015-08-25 13:17:39 -04002097 std::fill(mSemanticIndexes, mSemanticIndexes + ArraySize(mSemanticIndexes), -1);
Jamie Madill437d2662014-12-05 14:23:35 -05002098 std::fill(mAttributesByLayout, mAttributesByLayout + ArraySize(mAttributesByLayout), -1);
Jamie Madillccdf74b2015-08-18 10:46:12 -04002099
2100 mTransformFeedbackLinkedVaryings.clear();
Brandon Jonesc9610c52014-08-25 17:02:59 -07002101}
2102
Geoff Lang7dd2e102014-11-10 15:19:26 -05002103unsigned int ProgramD3D::getSerial() const
2104{
2105 return mSerial;
2106}
2107
2108unsigned int ProgramD3D::issueSerial()
2109{
2110 return mCurrentSerial++;
2111}
2112
Jamie Madill63805b42015-08-25 13:17:39 -04002113void ProgramD3D::initSemanticIndex()
2114{
2115 const gl::Shader *vertexShader = mData.getAttachedVertexShader();
2116 ASSERT(vertexShader != nullptr);
2117
2118 // Init semantic index
2119 for (const sh::Attribute &attribute : mData.getAttributes())
2120 {
2121 int attributeIndex = attribute.location;
2122 int index = vertexShader->getSemanticIndex(attribute.name);
2123 int regs = gl::VariableRegisterCount(attribute.type);
2124
2125 for (int reg = 0; reg < regs; ++reg)
2126 {
2127 mSemanticIndexes[attributeIndex + reg] = index + reg;
2128 }
2129 }
2130
2131 initAttributesByLayout();
2132}
2133
Jamie Madill437d2662014-12-05 14:23:35 -05002134void ProgramD3D::initAttributesByLayout()
2135{
2136 for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
2137 {
2138 mAttributesByLayout[i] = i;
2139 }
2140
Jamie Madill63805b42015-08-25 13:17:39 -04002141 std::sort(&mAttributesByLayout[0], &mAttributesByLayout[gl::MAX_VERTEX_ATTRIBS],
2142 AttributeSorter(mSemanticIndexes));
Jamie Madill437d2662014-12-05 14:23:35 -05002143}
2144
Jamie Madill476682e2015-06-30 10:04:29 -04002145void ProgramD3D::sortAttributesByLayout(const std::vector<TranslatedAttribute> &unsortedAttributes,
Jamie Madillf9327d32015-06-22 13:57:16 -04002146 int sortedSemanticIndicesOut[gl::MAX_VERTEX_ATTRIBS],
2147 const rx::TranslatedAttribute *sortedAttributesOut[gl::MAX_VERTEX_ATTRIBS]) const
Jamie Madill437d2662014-12-05 14:23:35 -05002148{
Jamie Madill476682e2015-06-30 10:04:29 -04002149 for (size_t attribIndex = 0; attribIndex < unsortedAttributes.size(); ++attribIndex)
Jamie Madill437d2662014-12-05 14:23:35 -05002150 {
Jamie Madill476682e2015-06-30 10:04:29 -04002151 int oldIndex = mAttributesByLayout[attribIndex];
Jamie Madill63805b42015-08-25 13:17:39 -04002152 sortedSemanticIndicesOut[attribIndex] = mSemanticIndexes[oldIndex];
Jamie Madill476682e2015-06-30 10:04:29 -04002153 sortedAttributesOut[attribIndex] = &unsortedAttributes[oldIndex];
Jamie Madill437d2662014-12-05 14:23:35 -05002154 }
2155}
2156
Jamie Madill63805b42015-08-25 13:17:39 -04002157void ProgramD3D::updateCachedInputLayout(const gl::State &state)
Jamie Madilld3dfda22015-07-06 08:28:49 -04002158{
Jamie Madillbd136f92015-08-10 14:51:37 -04002159 mCachedInputLayout.clear();
Jamie Madilld3dfda22015-07-06 08:28:49 -04002160 const auto &vertexAttributes = state.getVertexArray()->getVertexAttributes();
Jamie Madillf8dd7b12015-08-05 13:50:08 -04002161
Jamie Madilld3dfda22015-07-06 08:28:49 -04002162 for (unsigned int attributeIndex = 0; attributeIndex < vertexAttributes.size(); attributeIndex++)
2163 {
Jamie Madill63805b42015-08-25 13:17:39 -04002164 int semanticIndex = mSemanticIndexes[attributeIndex];
Jamie Madilld3dfda22015-07-06 08:28:49 -04002165
2166 if (semanticIndex != -1)
2167 {
Jamie Madillbd136f92015-08-10 14:51:37 -04002168 if (mCachedInputLayout.size() < static_cast<size_t>(semanticIndex + 1))
2169 {
2170 mCachedInputLayout.resize(semanticIndex + 1, gl::VERTEX_FORMAT_INVALID);
2171 }
Jamie Madilld3dfda22015-07-06 08:28:49 -04002172 mCachedInputLayout[semanticIndex] =
2173 GetVertexFormatType(vertexAttributes[attributeIndex],
2174 state.getVertexAttribCurrentValue(attributeIndex).Type);
2175 }
2176 }
2177}
2178
Jamie Madillccdf74b2015-08-18 10:46:12 -04002179void ProgramD3D::gatherTransformFeedbackVaryings(
2180 const std::vector<gl::LinkedVarying> &linkedVaryings)
2181{
2182 // Gather the linked varyings that are used for transform feedback, they should all exist.
2183 mTransformFeedbackLinkedVaryings.clear();
2184 for (const std::string &tfVaryingName : mData.getTransformFeedbackVaryingNames())
2185 {
2186 for (const gl::LinkedVarying &linkedVarying : linkedVaryings)
2187 {
2188 if (tfVaryingName == linkedVarying.name)
2189 {
2190 mTransformFeedbackLinkedVaryings.push_back(linkedVarying);
2191 break;
2192 }
2193 }
2194 }
2195}
Brandon Jonesc9610c52014-08-25 17:02:59 -07002196}