blob: 6cb5c147ae59a284672268483e153db1449ef8c9 [file] [log] [blame]
Brandon Jonesc9610c52014-08-25 17:02:59 -07001//
2// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// ProgramD3D.cpp: Defines the rx::ProgramD3D class which implements rx::ProgramImpl.
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/renderer/d3d/ProgramD3D.h"
Jamie Madill437d2662014-12-05 14:23:35 -050010
Dian Xianga4928832015-09-15 10:11:17 -070011#include "common/BitSetIterator.h"
Jamie Madill437d2662014-12-05 14:23:35 -050012#include "common/utilities.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050013#include "libANGLE/Framebuffer.h"
14#include "libANGLE/FramebufferAttachment.h"
15#include "libANGLE/Program.h"
Jamie Madilld3dfda22015-07-06 08:28:49 -040016#include "libANGLE/VertexArray.h"
Jamie Madill6df9b372015-02-18 21:28:19 +000017#include "libANGLE/features.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050018#include "libANGLE/renderer/d3d/DynamicHLSL.h"
Jamie Madill85a18042015-03-05 15:41:41 -050019#include "libANGLE/renderer/d3d/FramebufferD3D.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050020#include "libANGLE/renderer/d3d/RendererD3D.h"
21#include "libANGLE/renderer/d3d/ShaderD3D.h"
Geoff Lang359ef262015-01-05 14:42:29 -050022#include "libANGLE/renderer/d3d/ShaderExecutableD3D.h"
Jamie Madill437d2662014-12-05 14:23:35 -050023#include "libANGLE/renderer/d3d/VertexDataManager.h"
Geoff Lang22072132014-11-20 15:15:01 -050024
Brandon Jonesc9610c52014-08-25 17:02:59 -070025namespace rx
26{
27
Brandon Joneseb994362014-09-24 10:27:28 -070028namespace
29{
30
Brandon Jones1a8a7e32014-10-01 12:49:30 -070031GLenum GetTextureType(GLenum samplerType)
32{
33 switch (samplerType)
34 {
35 case GL_SAMPLER_2D:
36 case GL_INT_SAMPLER_2D:
37 case GL_UNSIGNED_INT_SAMPLER_2D:
38 case GL_SAMPLER_2D_SHADOW:
39 return GL_TEXTURE_2D;
40 case GL_SAMPLER_3D:
41 case GL_INT_SAMPLER_3D:
42 case GL_UNSIGNED_INT_SAMPLER_3D:
43 return GL_TEXTURE_3D;
44 case GL_SAMPLER_CUBE:
45 case GL_SAMPLER_CUBE_SHADOW:
46 return GL_TEXTURE_CUBE_MAP;
47 case GL_INT_SAMPLER_CUBE:
48 case GL_UNSIGNED_INT_SAMPLER_CUBE:
49 return GL_TEXTURE_CUBE_MAP;
50 case GL_SAMPLER_2D_ARRAY:
51 case GL_INT_SAMPLER_2D_ARRAY:
52 case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
53 case GL_SAMPLER_2D_ARRAY_SHADOW:
54 return GL_TEXTURE_2D_ARRAY;
55 default: UNREACHABLE();
56 }
57
58 return GL_TEXTURE_2D;
59}
60
Jamie Madillf8dd7b12015-08-05 13:50:08 -040061gl::InputLayout GetDefaultInputLayoutFromShader(const gl::Shader *vertexShader)
Brandon Joneseb994362014-09-24 10:27:28 -070062{
Jamie Madillbd136f92015-08-10 14:51:37 -040063 gl::InputLayout defaultLayout;
64 for (const sh::Attribute &shaderAttr : vertexShader->getActiveAttributes())
Brandon Joneseb994362014-09-24 10:27:28 -070065 {
Brandon Joneseb994362014-09-24 10:27:28 -070066 if (shaderAttr.type != GL_NONE)
67 {
68 GLenum transposedType = gl::TransposeMatrixType(shaderAttr.type);
69
Jamie Madilld3dfda22015-07-06 08:28:49 -040070 for (size_t rowIndex = 0;
71 static_cast<int>(rowIndex) < gl::VariableRowCount(transposedType);
72 ++rowIndex)
Brandon Joneseb994362014-09-24 10:27:28 -070073 {
Jamie Madilld3dfda22015-07-06 08:28:49 -040074 GLenum componentType = gl::VariableComponentType(transposedType);
75 GLuint components = static_cast<GLuint>(gl::VariableColumnCount(transposedType));
76 bool pureInt = (componentType != GL_FLOAT);
77 gl::VertexFormatType defaultType = gl::GetVertexFormatType(
78 componentType, GL_FALSE, components, pureInt);
Brandon Joneseb994362014-09-24 10:27:28 -070079
Jamie Madillbd136f92015-08-10 14:51:37 -040080 defaultLayout.push_back(defaultType);
Brandon Joneseb994362014-09-24 10:27:28 -070081 }
82 }
83 }
Jamie Madillf8dd7b12015-08-05 13:50:08 -040084
85 return defaultLayout;
Brandon Joneseb994362014-09-24 10:27:28 -070086}
87
88std::vector<GLenum> GetDefaultOutputLayoutFromShader(const std::vector<PixelShaderOutputVariable> &shaderOutputVars)
89{
Jamie Madillb4463142014-12-19 14:56:54 -050090 std::vector<GLenum> defaultPixelOutput;
Brandon Joneseb994362014-09-24 10:27:28 -070091
Jamie Madillb4463142014-12-19 14:56:54 -050092 if (!shaderOutputVars.empty())
93 {
Cooper Partin4d61f7e2015-08-12 10:56:50 -070094 defaultPixelOutput.push_back(GL_COLOR_ATTACHMENT0 +
95 static_cast<unsigned int>(shaderOutputVars[0].outputIndex));
Jamie Madillb4463142014-12-19 14:56:54 -050096 }
Brandon Joneseb994362014-09-24 10:27:28 -070097
98 return defaultPixelOutput;
99}
100
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700101bool IsRowMajorLayout(const sh::InterfaceBlockField &var)
102{
103 return var.isRowMajorLayout;
104}
105
106bool IsRowMajorLayout(const sh::ShaderVariable &var)
107{
108 return false;
109}
110
Jamie Madill437d2662014-12-05 14:23:35 -0500111struct AttributeSorter
112{
Jamie Madill63805b42015-08-25 13:17:39 -0400113 AttributeSorter(const ProgramD3D::SemanticIndexArray &semanticIndices)
Jamie Madill80d934b2015-02-19 10:16:12 -0500114 : originalIndices(&semanticIndices)
Jamie Madill437d2662014-12-05 14:23:35 -0500115 {
116 }
117
118 bool operator()(int a, int b)
119 {
Jamie Madill80d934b2015-02-19 10:16:12 -0500120 int indexA = (*originalIndices)[a];
121 int indexB = (*originalIndices)[b];
122
123 if (indexA == -1) return false;
124 if (indexB == -1) return true;
125 return (indexA < indexB);
Jamie Madill437d2662014-12-05 14:23:35 -0500126 }
127
Jamie Madill63805b42015-08-25 13:17:39 -0400128 const ProgramD3D::SemanticIndexArray *originalIndices;
Jamie Madill437d2662014-12-05 14:23:35 -0500129};
130
Jamie Madillca03b352015-09-02 12:38:13 -0400131std::vector<PackedVarying> MergeVaryings(const gl::Shader &vertexShader,
132 const gl::Shader &fragmentShader,
133 const std::vector<std::string> &tfVaryings)
Jamie Madillada9ecc2015-08-17 12:53:37 -0400134{
Jamie Madillca03b352015-09-02 12:38:13 -0400135 std::vector<PackedVarying> packedVaryings;
136
137 for (const sh::Varying &output : vertexShader.getVaryings())
Jamie Madillada9ecc2015-08-17 12:53:37 -0400138 {
Jamie Madillca03b352015-09-02 12:38:13 -0400139 bool packed = false;
Jamie Madillada9ecc2015-08-17 12:53:37 -0400140
141 // Built-in varyings obey special rules
Jamie Madillca03b352015-09-02 12:38:13 -0400142 if (output.isBuiltIn())
Jamie Madillada9ecc2015-08-17 12:53:37 -0400143 {
144 continue;
145 }
146
Jamie Madillca03b352015-09-02 12:38:13 -0400147 for (const sh::Varying &input : fragmentShader.getVaryings())
Jamie Madillada9ecc2015-08-17 12:53:37 -0400148 {
Jamie Madillca03b352015-09-02 12:38:13 -0400149 if (output.name == input.name)
Jamie Madillada9ecc2015-08-17 12:53:37 -0400150 {
Jamie Madillca03b352015-09-02 12:38:13 -0400151 packedVaryings.push_back(PackedVarying(input));
152 packed = true;
Jamie Madillada9ecc2015-08-17 12:53:37 -0400153 break;
154 }
155 }
156
Jamie Madillca03b352015-09-02 12:38:13 -0400157 // Keep Transform FB varyings in the merged list always.
158 if (!packed)
159 {
160 for (const std::string &tfVarying : tfVaryings)
161 {
162 if (tfVarying == output.name)
163 {
164 packedVaryings.push_back(PackedVarying(output));
165 packedVaryings.back().vertexOnly = true;
166 break;
167 }
168 }
169 }
Jamie Madillada9ecc2015-08-17 12:53:37 -0400170 }
171
Jamie Madillca03b352015-09-02 12:38:13 -0400172 return packedVaryings;
Brandon Joneseb994362014-09-24 10:27:28 -0700173}
174
Jamie Madill62d31cb2015-09-11 13:25:51 -0400175template <typename VarT>
176void GetUniformBlockInfo(const std::vector<VarT> &fields,
177 const std::string &prefix,
178 sh::BlockLayoutEncoder *encoder,
179 bool inRowMajorLayout,
180 std::map<std::string, sh::BlockMemberInfo> *blockInfoOut)
181{
182 for (const VarT &field : fields)
183 {
184 const std::string &fieldName = (prefix.empty() ? field.name : prefix + "." + field.name);
185
186 if (field.isStruct())
187 {
188 bool rowMajorLayout = (inRowMajorLayout || IsRowMajorLayout(field));
189
190 for (unsigned int arrayElement = 0; arrayElement < field.elementCount(); arrayElement++)
191 {
192 encoder->enterAggregateType();
193
194 const std::string uniformElementName =
195 fieldName + (field.isArray() ? ArrayString(arrayElement) : "");
196 GetUniformBlockInfo(field.fields, uniformElementName, encoder, rowMajorLayout,
197 blockInfoOut);
198
199 encoder->exitAggregateType();
200 }
201 }
202 else
203 {
204 bool isRowMajorMatrix = (gl::IsMatrixType(field.type) && inRowMajorLayout);
205 (*blockInfoOut)[fieldName] =
206 encoder->encodeType(field.type, field.arraySize, isRowMajorMatrix);
207 }
208 }
209}
210
Jamie Madillada9ecc2015-08-17 12:53:37 -0400211} // anonymous namespace
212
Jamie Madill62d31cb2015-09-11 13:25:51 -0400213D3DUniform::D3DUniform(GLenum typeIn,
214 const std::string &nameIn,
215 unsigned int arraySizeIn,
216 bool defaultBlock)
217 : type(typeIn),
218 name(nameIn),
219 arraySize(arraySizeIn),
220 data(nullptr),
221 dirty(true),
Jamie Madill62d31cb2015-09-11 13:25:51 -0400222 vsRegisterIndex(GL_INVALID_INDEX),
Geoff Lang98c56da2015-09-15 15:45:34 -0400223 psRegisterIndex(GL_INVALID_INDEX),
Jamie Madill62d31cb2015-09-11 13:25:51 -0400224 registerCount(0),
225 registerElement(0)
226{
227 // We use data storage for default block uniforms to cache values that are sent to D3D during
228 // rendering
229 // Uniform blocks/buffers are treated separately by the Renderer (ES3 path only)
230 if (defaultBlock)
231 {
232 size_t bytes = gl::VariableInternalSize(type) * elementCount();
233 data = new uint8_t[bytes];
234 memset(data, 0, bytes);
235
236 // TODO(jmadill): is this correct with non-square matrices?
237 registerCount = gl::VariableRowCount(type) * elementCount();
238 }
239}
240
241D3DUniform::~D3DUniform()
242{
243 SafeDeleteArray(data);
244}
245
246bool D3DUniform::isSampler() const
247{
248 return gl::IsSamplerType(type);
249}
250
251bool D3DUniform::isReferencedByVertexShader() const
252{
253 return vsRegisterIndex != GL_INVALID_INDEX;
254}
255
256bool D3DUniform::isReferencedByFragmentShader() const
257{
258 return psRegisterIndex != GL_INVALID_INDEX;
259}
260
Jamie Madilld3dfda22015-07-06 08:28:49 -0400261ProgramD3D::VertexExecutable::VertexExecutable(const gl::InputLayout &inputLayout,
262 const Signature &signature,
Geoff Lang359ef262015-01-05 14:42:29 -0500263 ShaderExecutableD3D *shaderExecutable)
Jamie Madilld3dfda22015-07-06 08:28:49 -0400264 : mInputs(inputLayout),
265 mSignature(signature),
266 mShaderExecutable(shaderExecutable)
Brandon Joneseb994362014-09-24 10:27:28 -0700267{
Brandon Joneseb994362014-09-24 10:27:28 -0700268}
269
270ProgramD3D::VertexExecutable::~VertexExecutable()
271{
272 SafeDelete(mShaderExecutable);
273}
274
Jamie Madilld3dfda22015-07-06 08:28:49 -0400275// static
276void ProgramD3D::VertexExecutable::getSignature(RendererD3D *renderer,
277 const gl::InputLayout &inputLayout,
278 Signature *signatureOut)
Brandon Joneseb994362014-09-24 10:27:28 -0700279{
Jamie Madillbd136f92015-08-10 14:51:37 -0400280 signatureOut->resize(inputLayout.size());
Jamie Madilld3dfda22015-07-06 08:28:49 -0400281
282 for (size_t index = 0; index < inputLayout.size(); ++index)
Brandon Joneseb994362014-09-24 10:27:28 -0700283 {
Jamie Madilld3dfda22015-07-06 08:28:49 -0400284 gl::VertexFormatType vertexFormatType = inputLayout[index];
Jamie Madillbd136f92015-08-10 14:51:37 -0400285 bool converted = false;
Jamie Madillf8dd7b12015-08-05 13:50:08 -0400286 if (vertexFormatType != gl::VERTEX_FORMAT_INVALID)
Brandon Joneseb994362014-09-24 10:27:28 -0700287 {
Jamie Madillf8dd7b12015-08-05 13:50:08 -0400288 VertexConversionType conversionType =
289 renderer->getVertexConversionType(vertexFormatType);
Jamie Madillbd136f92015-08-10 14:51:37 -0400290 converted = ((conversionType & VERTEX_CONVERT_GPU) != 0);
Brandon Joneseb994362014-09-24 10:27:28 -0700291 }
Jamie Madillbd136f92015-08-10 14:51:37 -0400292
293 (*signatureOut)[index] = converted;
Brandon Joneseb994362014-09-24 10:27:28 -0700294 }
Brandon Joneseb994362014-09-24 10:27:28 -0700295}
296
Jamie Madilld3dfda22015-07-06 08:28:49 -0400297bool ProgramD3D::VertexExecutable::matchesSignature(const Signature &signature) const
298{
Jamie Madillbd136f92015-08-10 14:51:37 -0400299 size_t limit = std::max(mSignature.size(), signature.size());
300 for (size_t index = 0; index < limit; ++index)
301 {
302 // treat undefined indexes as 'not converted'
303 bool a = index < signature.size() ? signature[index] : false;
304 bool b = index < mSignature.size() ? mSignature[index] : false;
305 if (a != b)
306 return false;
307 }
308
309 return true;
Jamie Madilld3dfda22015-07-06 08:28:49 -0400310}
311
312ProgramD3D::PixelExecutable::PixelExecutable(const std::vector<GLenum> &outputSignature,
313 ShaderExecutableD3D *shaderExecutable)
Brandon Joneseb994362014-09-24 10:27:28 -0700314 : mOutputSignature(outputSignature),
315 mShaderExecutable(shaderExecutable)
316{
317}
318
319ProgramD3D::PixelExecutable::~PixelExecutable()
320{
321 SafeDelete(mShaderExecutable);
322}
323
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700324ProgramD3D::Sampler::Sampler() : active(false), logicalTextureUnit(0), textureType(GL_TEXTURE_2D)
325{
326}
327
Geoff Lang7dd2e102014-11-10 15:19:26 -0500328unsigned int ProgramD3D::mCurrentSerial = 1;
329
Jamie Madill5c6b7bf2015-08-17 12:53:35 -0400330ProgramD3D::ProgramD3D(const gl::Program::Data &data, RendererD3D *renderer)
331 : ProgramImpl(data),
Brandon Jonesc9610c52014-08-25 17:02:59 -0700332 mRenderer(renderer),
333 mDynamicHLSL(NULL),
Brandon Joneseb994362014-09-24 10:27:28 -0700334 mGeometryExecutable(NULL),
Brandon Jones44151a92014-09-10 11:32:25 -0700335 mUsesPointSize(false),
Brandon Jonesc9610c52014-08-25 17:02:59 -0700336 mVertexUniformStorage(NULL),
Brandon Jones44151a92014-09-10 11:32:25 -0700337 mFragmentUniformStorage(NULL),
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700338 mUsedVertexSamplerRange(0),
339 mUsedPixelSamplerRange(0),
340 mDirtySamplerMapping(true),
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400341 mTextureUnitTypesCache(renderer->getRendererCaps().maxCombinedTextureImageUnits),
Geoff Lang7dd2e102014-11-10 15:19:26 -0500342 mShaderVersion(100),
343 mSerial(issueSerial())
Brandon Jonesc9610c52014-08-25 17:02:59 -0700344{
Brandon Joneseb994362014-09-24 10:27:28 -0700345 mDynamicHLSL = new DynamicHLSL(renderer);
Brandon Jonesc9610c52014-08-25 17:02:59 -0700346}
347
348ProgramD3D::~ProgramD3D()
349{
350 reset();
351 SafeDelete(mDynamicHLSL);
352}
353
Brandon Jones44151a92014-09-10 11:32:25 -0700354bool ProgramD3D::usesPointSpriteEmulation() const
355{
356 return mUsesPointSize && mRenderer->getMajorShaderModel() >= 4;
357}
358
359bool ProgramD3D::usesGeometryShader() const
360{
Cooper Partine6664f02015-01-09 16:22:24 -0800361 return usesPointSpriteEmulation() && !usesInstancedPointSpriteEmulation();
362}
363
364bool ProgramD3D::usesInstancedPointSpriteEmulation() const
365{
366 return mRenderer->getWorkarounds().useInstancedPointSpriteEmulation;
Brandon Jones44151a92014-09-10 11:32:25 -0700367}
368
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700369GLint ProgramD3D::getSamplerMapping(gl::SamplerType type, unsigned int samplerIndex, const gl::Caps &caps) const
370{
371 GLint logicalTextureUnit = -1;
372
373 switch (type)
374 {
375 case gl::SAMPLER_PIXEL:
376 ASSERT(samplerIndex < caps.maxTextureImageUnits);
377 if (samplerIndex < mSamplersPS.size() && mSamplersPS[samplerIndex].active)
378 {
379 logicalTextureUnit = mSamplersPS[samplerIndex].logicalTextureUnit;
380 }
381 break;
382 case gl::SAMPLER_VERTEX:
383 ASSERT(samplerIndex < caps.maxVertexTextureImageUnits);
384 if (samplerIndex < mSamplersVS.size() && mSamplersVS[samplerIndex].active)
385 {
386 logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit;
387 }
388 break;
389 default: UNREACHABLE();
390 }
391
392 if (logicalTextureUnit >= 0 && logicalTextureUnit < static_cast<GLint>(caps.maxCombinedTextureImageUnits))
393 {
394 return logicalTextureUnit;
395 }
396
397 return -1;
398}
399
400// Returns the texture type for a given Direct3D 9 sampler type and
401// index (0-15 for the pixel shader and 0-3 for the vertex shader).
402GLenum ProgramD3D::getSamplerTextureType(gl::SamplerType type, unsigned int samplerIndex) const
403{
404 switch (type)
405 {
406 case gl::SAMPLER_PIXEL:
407 ASSERT(samplerIndex < mSamplersPS.size());
408 ASSERT(mSamplersPS[samplerIndex].active);
409 return mSamplersPS[samplerIndex].textureType;
410 case gl::SAMPLER_VERTEX:
411 ASSERT(samplerIndex < mSamplersVS.size());
412 ASSERT(mSamplersVS[samplerIndex].active);
413 return mSamplersVS[samplerIndex].textureType;
414 default: UNREACHABLE();
415 }
416
417 return GL_TEXTURE_2D;
418}
419
420GLint ProgramD3D::getUsedSamplerRange(gl::SamplerType type) const
421{
422 switch (type)
423 {
424 case gl::SAMPLER_PIXEL:
425 return mUsedPixelSamplerRange;
426 case gl::SAMPLER_VERTEX:
427 return mUsedVertexSamplerRange;
428 default:
429 UNREACHABLE();
430 return 0;
431 }
432}
433
434void ProgramD3D::updateSamplerMapping()
435{
436 if (!mDirtySamplerMapping)
437 {
438 return;
439 }
440
441 mDirtySamplerMapping = false;
442
443 // Retrieve sampler uniform values
Jamie Madill62d31cb2015-09-11 13:25:51 -0400444 for (const D3DUniform *d3dUniform : mD3DUniforms)
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700445 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400446 if (!d3dUniform->dirty)
447 continue;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700448
Jamie Madill62d31cb2015-09-11 13:25:51 -0400449 if (!d3dUniform->isSampler())
450 continue;
451
452 int count = d3dUniform->elementCount();
453 const GLint(*v)[4] = reinterpret_cast<const GLint(*)[4]>(d3dUniform->data);
454
455 if (d3dUniform->isReferencedByFragmentShader())
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700456 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400457 unsigned int firstIndex = d3dUniform->psRegisterIndex;
458
459 for (int i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700460 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400461 unsigned int samplerIndex = firstIndex + i;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700462
Jamie Madill62d31cb2015-09-11 13:25:51 -0400463 if (samplerIndex < mSamplersPS.size())
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700464 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400465 ASSERT(mSamplersPS[samplerIndex].active);
466 mSamplersPS[samplerIndex].logicalTextureUnit = v[i][0];
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700467 }
Jamie Madill62d31cb2015-09-11 13:25:51 -0400468 }
469 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700470
Jamie Madill62d31cb2015-09-11 13:25:51 -0400471 if (d3dUniform->isReferencedByVertexShader())
472 {
473 unsigned int firstIndex = d3dUniform->vsRegisterIndex;
474
475 for (int i = 0; i < count; i++)
476 {
477 unsigned int samplerIndex = firstIndex + i;
478
479 if (samplerIndex < mSamplersVS.size())
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700480 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400481 ASSERT(mSamplersVS[samplerIndex].active);
482 mSamplersVS[samplerIndex].logicalTextureUnit = v[i][0];
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700483 }
484 }
485 }
486 }
487}
488
489bool ProgramD3D::validateSamplers(gl::InfoLog *infoLog, const gl::Caps &caps)
490{
Jamie Madill13776892015-04-28 12:39:06 -0400491 // Skip cache if we're using an infolog, so we get the full error.
492 // Also skip the cache if the sample mapping has changed, or if we haven't ever validated.
493 if (!mDirtySamplerMapping && infoLog == nullptr && mCachedValidateSamplersResult.valid())
494 {
495 return mCachedValidateSamplersResult.value();
496 }
497
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700498 // if any two active samplers in a program are of different types, but refer to the same
499 // texture image unit, and this is the current program, then ValidateProgram will fail, and
500 // DrawArrays and DrawElements will issue the INVALID_OPERATION error.
501 updateSamplerMapping();
502
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400503 std::fill(mTextureUnitTypesCache.begin(), mTextureUnitTypesCache.end(), GL_NONE);
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700504
505 for (unsigned int i = 0; i < mUsedPixelSamplerRange; ++i)
506 {
507 if (mSamplersPS[i].active)
508 {
509 unsigned int unit = mSamplersPS[i].logicalTextureUnit;
510
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400511 if (unit >= caps.maxCombinedTextureImageUnits)
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700512 {
513 if (infoLog)
514 {
Jamie Madillf6113162015-05-07 11:49:21 -0400515 (*infoLog) << "Sampler uniform (" << unit
516 << ") exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS ("
517 << caps.maxCombinedTextureImageUnits << ")";
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700518 }
519
Jamie Madill13776892015-04-28 12:39:06 -0400520 mCachedValidateSamplersResult = false;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700521 return false;
522 }
523
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400524 if (mTextureUnitTypesCache[unit] != GL_NONE)
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700525 {
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400526 if (mSamplersPS[i].textureType != mTextureUnitTypesCache[unit])
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700527 {
528 if (infoLog)
529 {
Jamie Madillf6113162015-05-07 11:49:21 -0400530 (*infoLog) << "Samplers of conflicting types refer to the same texture image unit ("
531 << unit << ").";
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700532 }
533
Jamie Madill13776892015-04-28 12:39:06 -0400534 mCachedValidateSamplersResult = false;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700535 return false;
536 }
537 }
538 else
539 {
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400540 mTextureUnitTypesCache[unit] = mSamplersPS[i].textureType;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700541 }
542 }
543 }
544
545 for (unsigned int i = 0; i < mUsedVertexSamplerRange; ++i)
546 {
547 if (mSamplersVS[i].active)
548 {
549 unsigned int unit = mSamplersVS[i].logicalTextureUnit;
550
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400551 if (unit >= caps.maxCombinedTextureImageUnits)
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700552 {
553 if (infoLog)
554 {
Jamie Madillf6113162015-05-07 11:49:21 -0400555 (*infoLog) << "Sampler uniform (" << unit
556 << ") exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS ("
557 << caps.maxCombinedTextureImageUnits << ")";
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700558 }
559
Jamie Madill13776892015-04-28 12:39:06 -0400560 mCachedValidateSamplersResult = false;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700561 return false;
562 }
563
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400564 if (mTextureUnitTypesCache[unit] != GL_NONE)
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700565 {
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400566 if (mSamplersVS[i].textureType != mTextureUnitTypesCache[unit])
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700567 {
568 if (infoLog)
569 {
Jamie Madillf6113162015-05-07 11:49:21 -0400570 (*infoLog) << "Samplers of conflicting types refer to the same texture image unit ("
571 << unit << ").";
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700572 }
573
Jamie Madill13776892015-04-28 12:39:06 -0400574 mCachedValidateSamplersResult = false;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700575 return false;
576 }
577 }
578 else
579 {
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400580 mTextureUnitTypesCache[unit] = mSamplersVS[i].textureType;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700581 }
582 }
583 }
584
Jamie Madill13776892015-04-28 12:39:06 -0400585 mCachedValidateSamplersResult = true;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700586 return true;
587}
588
Geoff Lang7dd2e102014-11-10 15:19:26 -0500589LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
Brandon Jones22502d52014-08-29 16:58:36 -0700590{
Jamie Madill62d31cb2015-09-11 13:25:51 -0400591 reset();
592
Austin Kinross137b1512015-06-17 16:14:53 -0700593 DeviceIdentifier binaryDeviceIdentifier = { 0 };
594 stream->readBytes(reinterpret_cast<unsigned char*>(&binaryDeviceIdentifier), sizeof(DeviceIdentifier));
595
596 DeviceIdentifier identifier = mRenderer->getAdapterIdentifier();
597 if (memcmp(&identifier, &binaryDeviceIdentifier, sizeof(DeviceIdentifier)) != 0)
598 {
599 infoLog << "Invalid program binary, device configuration has changed.";
600 return LinkResult(false, gl::Error(GL_NO_ERROR));
601 }
602
Jamie Madill2db1fbb2014-12-03 10:58:55 -0500603 int compileFlags = stream->readInt<int>();
604 if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL)
605 {
Jamie Madillf6113162015-05-07 11:49:21 -0400606 infoLog << "Mismatched compilation flags.";
Jamie Madill2db1fbb2014-12-03 10:58:55 -0500607 return LinkResult(false, gl::Error(GL_NO_ERROR));
608 }
609
Brandon Jones44151a92014-09-10 11:32:25 -0700610 stream->readInt(&mShaderVersion);
611
Jamie Madill63805b42015-08-25 13:17:39 -0400612 // TODO(jmadill): replace MAX_VERTEX_ATTRIBS
613 for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; ++i)
614 {
615 stream->readInt(&mSemanticIndexes[i]);
616 }
617
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700618 const unsigned int psSamplerCount = stream->readInt<unsigned int>();
619 for (unsigned int i = 0; i < psSamplerCount; ++i)
620 {
621 Sampler sampler;
622 stream->readBool(&sampler.active);
623 stream->readInt(&sampler.logicalTextureUnit);
624 stream->readInt(&sampler.textureType);
625 mSamplersPS.push_back(sampler);
626 }
627 const unsigned int vsSamplerCount = stream->readInt<unsigned int>();
628 for (unsigned int i = 0; i < vsSamplerCount; ++i)
629 {
630 Sampler sampler;
631 stream->readBool(&sampler.active);
632 stream->readInt(&sampler.logicalTextureUnit);
633 stream->readInt(&sampler.textureType);
634 mSamplersVS.push_back(sampler);
635 }
636
637 stream->readInt(&mUsedVertexSamplerRange);
638 stream->readInt(&mUsedPixelSamplerRange);
639
640 const unsigned int uniformCount = stream->readInt<unsigned int>();
641 if (stream->error())
642 {
Jamie Madillf6113162015-05-07 11:49:21 -0400643 infoLog << "Invalid program binary.";
Geoff Lang7dd2e102014-11-10 15:19:26 -0500644 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700645 }
646
Jamie Madill62d31cb2015-09-11 13:25:51 -0400647 const auto &linkedUniforms = mData.getUniforms();
648 ASSERT(mD3DUniforms.empty());
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700649 for (unsigned int uniformIndex = 0; uniformIndex < uniformCount; uniformIndex++)
650 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400651 const gl::LinkedUniform &linkedUniform = linkedUniforms[uniformIndex];
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700652
Jamie Madill62d31cb2015-09-11 13:25:51 -0400653 D3DUniform *d3dUniform =
654 new D3DUniform(linkedUniform.type, linkedUniform.name, linkedUniform.arraySize,
655 linkedUniform.isInDefaultBlock());
656 stream->readInt(&d3dUniform->psRegisterIndex);
657 stream->readInt(&d3dUniform->vsRegisterIndex);
658 stream->readInt(&d3dUniform->registerCount);
659 stream->readInt(&d3dUniform->registerElement);
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700660
Jamie Madill62d31cb2015-09-11 13:25:51 -0400661 mD3DUniforms.push_back(d3dUniform);
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700662 }
663
Brandon Joneseb994362014-09-24 10:27:28 -0700664 const unsigned int transformFeedbackVaryingCount = stream->readInt<unsigned int>();
665 mTransformFeedbackLinkedVaryings.resize(transformFeedbackVaryingCount);
666 for (unsigned int varyingIndex = 0; varyingIndex < transformFeedbackVaryingCount; varyingIndex++)
667 {
668 gl::LinkedVarying &varying = mTransformFeedbackLinkedVaryings[varyingIndex];
669
670 stream->readString(&varying.name);
671 stream->readInt(&varying.type);
672 stream->readInt(&varying.size);
673 stream->readString(&varying.semanticName);
674 stream->readInt(&varying.semanticIndex);
675 stream->readInt(&varying.semanticIndexCount);
676 }
677
Brandon Jones22502d52014-08-29 16:58:36 -0700678 stream->readString(&mVertexHLSL);
Arun Patole44efa0b2015-03-04 17:11:05 +0530679 stream->readBytes(reinterpret_cast<unsigned char*>(&mVertexWorkarounds), sizeof(D3DCompilerWorkarounds));
Brandon Jones22502d52014-08-29 16:58:36 -0700680 stream->readString(&mPixelHLSL);
Arun Patole44efa0b2015-03-04 17:11:05 +0530681 stream->readBytes(reinterpret_cast<unsigned char*>(&mPixelWorkarounds), sizeof(D3DCompilerWorkarounds));
Brandon Jones22502d52014-08-29 16:58:36 -0700682 stream->readBool(&mUsesFragDepth);
Brandon Jones44151a92014-09-10 11:32:25 -0700683 stream->readBool(&mUsesPointSize);
Brandon Jones22502d52014-08-29 16:58:36 -0700684
685 const size_t pixelShaderKeySize = stream->readInt<unsigned int>();
686 mPixelShaderKey.resize(pixelShaderKeySize);
687 for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKeySize; pixelShaderKeyIndex++)
688 {
689 stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].type);
690 stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].name);
691 stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].source);
692 stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].outputIndex);
693 }
694
Brandon Joneseb994362014-09-24 10:27:28 -0700695 const unsigned char* binary = reinterpret_cast<const unsigned char*>(stream->data());
696
697 const unsigned int vertexShaderCount = stream->readInt<unsigned int>();
698 for (unsigned int vertexShaderIndex = 0; vertexShaderIndex < vertexShaderCount; vertexShaderIndex++)
699 {
Jamie Madilld3dfda22015-07-06 08:28:49 -0400700 size_t inputLayoutSize = stream->readInt<size_t>();
Jamie Madillf8dd7b12015-08-05 13:50:08 -0400701 gl::InputLayout inputLayout(inputLayoutSize, gl::VERTEX_FORMAT_INVALID);
Brandon Joneseb994362014-09-24 10:27:28 -0700702
Jamie Madilld3dfda22015-07-06 08:28:49 -0400703 for (size_t inputIndex = 0; inputIndex < inputLayoutSize; inputIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -0700704 {
Jamie Madillf8dd7b12015-08-05 13:50:08 -0400705 inputLayout[inputIndex] = stream->readInt<gl::VertexFormatType>();
Brandon Joneseb994362014-09-24 10:27:28 -0700706 }
707
708 unsigned int vertexShaderSize = stream->readInt<unsigned int>();
709 const unsigned char *vertexShaderFunction = binary + stream->offset();
Geoff Langb543aff2014-09-30 14:52:54 -0400710
Jamie Madillada9ecc2015-08-17 12:53:37 -0400711 ShaderExecutableD3D *shaderExecutable = nullptr;
712
713 gl::Error error = mRenderer->loadExecutable(
714 vertexShaderFunction, vertexShaderSize, SHADER_VERTEX, mTransformFeedbackLinkedVaryings,
715 (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), &shaderExecutable);
Geoff Langb543aff2014-09-30 14:52:54 -0400716 if (error.isError())
717 {
Geoff Lang7dd2e102014-11-10 15:19:26 -0500718 return LinkResult(false, error);
Geoff Langb543aff2014-09-30 14:52:54 -0400719 }
720
Brandon Joneseb994362014-09-24 10:27:28 -0700721 if (!shaderExecutable)
722 {
Jamie Madillf6113162015-05-07 11:49:21 -0400723 infoLog << "Could not create vertex shader.";
Geoff Lang7dd2e102014-11-10 15:19:26 -0500724 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Joneseb994362014-09-24 10:27:28 -0700725 }
726
727 // generated converted input layout
Jamie Madilld3dfda22015-07-06 08:28:49 -0400728 VertexExecutable::Signature signature;
729 VertexExecutable::getSignature(mRenderer, inputLayout, &signature);
Brandon Joneseb994362014-09-24 10:27:28 -0700730
731 // add new binary
732 mVertexExecutables.push_back(new VertexExecutable(inputLayout, signature, shaderExecutable));
733
734 stream->skip(vertexShaderSize);
735 }
736
737 const size_t pixelShaderCount = stream->readInt<unsigned int>();
738 for (size_t pixelShaderIndex = 0; pixelShaderIndex < pixelShaderCount; pixelShaderIndex++)
739 {
740 const size_t outputCount = stream->readInt<unsigned int>();
741 std::vector<GLenum> outputs(outputCount);
742 for (size_t outputIndex = 0; outputIndex < outputCount; outputIndex++)
743 {
744 stream->readInt(&outputs[outputIndex]);
745 }
746
747 const size_t pixelShaderSize = stream->readInt<unsigned int>();
748 const unsigned char *pixelShaderFunction = binary + stream->offset();
Jamie Madillada9ecc2015-08-17 12:53:37 -0400749 ShaderExecutableD3D *shaderExecutable = nullptr;
750
751 gl::Error error = mRenderer->loadExecutable(
752 pixelShaderFunction, pixelShaderSize, SHADER_PIXEL, mTransformFeedbackLinkedVaryings,
753 (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), &shaderExecutable);
Geoff Langb543aff2014-09-30 14:52:54 -0400754 if (error.isError())
755 {
Geoff Lang7dd2e102014-11-10 15:19:26 -0500756 return LinkResult(false, error);
Geoff Langb543aff2014-09-30 14:52:54 -0400757 }
Brandon Joneseb994362014-09-24 10:27:28 -0700758
759 if (!shaderExecutable)
760 {
Jamie Madillf6113162015-05-07 11:49:21 -0400761 infoLog << "Could not create pixel shader.";
Geoff Lang7dd2e102014-11-10 15:19:26 -0500762 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Joneseb994362014-09-24 10:27:28 -0700763 }
764
765 // add new binary
766 mPixelExecutables.push_back(new PixelExecutable(outputs, shaderExecutable));
767
768 stream->skip(pixelShaderSize);
769 }
770
771 unsigned int geometryShaderSize = stream->readInt<unsigned int>();
772
773 if (geometryShaderSize > 0)
774 {
775 const unsigned char *geometryShaderFunction = binary + stream->offset();
Jamie Madillada9ecc2015-08-17 12:53:37 -0400776 gl::Error error = mRenderer->loadExecutable(
777 geometryShaderFunction, geometryShaderSize, SHADER_GEOMETRY,
778 mTransformFeedbackLinkedVaryings,
779 (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), &mGeometryExecutable);
Geoff Langb543aff2014-09-30 14:52:54 -0400780 if (error.isError())
781 {
Geoff Lang7dd2e102014-11-10 15:19:26 -0500782 return LinkResult(false, error);
Geoff Langb543aff2014-09-30 14:52:54 -0400783 }
Brandon Joneseb994362014-09-24 10:27:28 -0700784
785 if (!mGeometryExecutable)
786 {
Jamie Madillf6113162015-05-07 11:49:21 -0400787 infoLog << "Could not create geometry shader.";
Geoff Lang7dd2e102014-11-10 15:19:26 -0500788 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Joneseb994362014-09-24 10:27:28 -0700789 }
790 stream->skip(geometryShaderSize);
791 }
792
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700793 initializeUniformStorage();
Jamie Madill437d2662014-12-05 14:23:35 -0500794 initAttributesByLayout();
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700795
Geoff Lang7dd2e102014-11-10 15:19:26 -0500796 return LinkResult(true, gl::Error(GL_NO_ERROR));
Brandon Jones22502d52014-08-29 16:58:36 -0700797}
798
Geoff Langb543aff2014-09-30 14:52:54 -0400799gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream)
Brandon Jones22502d52014-08-29 16:58:36 -0700800{
Austin Kinross137b1512015-06-17 16:14:53 -0700801 // Output the DeviceIdentifier before we output any shader code
802 // When we load the binary again later, we can validate the device identifier before trying to compile any HLSL
803 DeviceIdentifier binaryIdentifier = mRenderer->getAdapterIdentifier();
804 stream->writeBytes(reinterpret_cast<unsigned char*>(&binaryIdentifier), sizeof(DeviceIdentifier));
805
Jamie Madill2db1fbb2014-12-03 10:58:55 -0500806 stream->writeInt(ANGLE_COMPILE_OPTIMIZATION_LEVEL);
807
Brandon Jones44151a92014-09-10 11:32:25 -0700808 stream->writeInt(mShaderVersion);
809
Jamie Madill63805b42015-08-25 13:17:39 -0400810 // TODO(jmadill): replace MAX_VERTEX_ATTRIBS
811 for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; ++i)
812 {
813 stream->writeInt(mSemanticIndexes[i]);
814 }
815
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700816 stream->writeInt(mSamplersPS.size());
817 for (unsigned int i = 0; i < mSamplersPS.size(); ++i)
818 {
819 stream->writeInt(mSamplersPS[i].active);
820 stream->writeInt(mSamplersPS[i].logicalTextureUnit);
821 stream->writeInt(mSamplersPS[i].textureType);
822 }
823
824 stream->writeInt(mSamplersVS.size());
825 for (unsigned int i = 0; i < mSamplersVS.size(); ++i)
826 {
827 stream->writeInt(mSamplersVS[i].active);
828 stream->writeInt(mSamplersVS[i].logicalTextureUnit);
829 stream->writeInt(mSamplersVS[i].textureType);
830 }
831
832 stream->writeInt(mUsedVertexSamplerRange);
833 stream->writeInt(mUsedPixelSamplerRange);
834
Jamie Madill62d31cb2015-09-11 13:25:51 -0400835 stream->writeInt(mD3DUniforms.size());
836 for (size_t uniformIndex = 0; uniformIndex < mD3DUniforms.size(); ++uniformIndex)
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700837 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400838 const D3DUniform &uniform = *mD3DUniforms[uniformIndex];
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700839
Jamie Madill62d31cb2015-09-11 13:25:51 -0400840 // Type, name and arraySize are redundant, so aren't stored in the binary.
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700841 stream->writeInt(uniform.psRegisterIndex);
842 stream->writeInt(uniform.vsRegisterIndex);
843 stream->writeInt(uniform.registerCount);
844 stream->writeInt(uniform.registerElement);
845 }
846
Brandon Joneseb994362014-09-24 10:27:28 -0700847 stream->writeInt(mTransformFeedbackLinkedVaryings.size());
848 for (size_t i = 0; i < mTransformFeedbackLinkedVaryings.size(); i++)
849 {
850 const gl::LinkedVarying &varying = mTransformFeedbackLinkedVaryings[i];
851
852 stream->writeString(varying.name);
853 stream->writeInt(varying.type);
854 stream->writeInt(varying.size);
855 stream->writeString(varying.semanticName);
856 stream->writeInt(varying.semanticIndex);
857 stream->writeInt(varying.semanticIndexCount);
858 }
859
Brandon Jones22502d52014-08-29 16:58:36 -0700860 stream->writeString(mVertexHLSL);
Arun Patole44efa0b2015-03-04 17:11:05 +0530861 stream->writeBytes(reinterpret_cast<unsigned char*>(&mVertexWorkarounds), sizeof(D3DCompilerWorkarounds));
Brandon Jones22502d52014-08-29 16:58:36 -0700862 stream->writeString(mPixelHLSL);
Arun Patole44efa0b2015-03-04 17:11:05 +0530863 stream->writeBytes(reinterpret_cast<unsigned char*>(&mPixelWorkarounds), sizeof(D3DCompilerWorkarounds));
Brandon Jones22502d52014-08-29 16:58:36 -0700864 stream->writeInt(mUsesFragDepth);
Brandon Jones44151a92014-09-10 11:32:25 -0700865 stream->writeInt(mUsesPointSize);
Brandon Jones22502d52014-08-29 16:58:36 -0700866
Brandon Joneseb994362014-09-24 10:27:28 -0700867 const std::vector<PixelShaderOutputVariable> &pixelShaderKey = mPixelShaderKey;
Brandon Jones22502d52014-08-29 16:58:36 -0700868 stream->writeInt(pixelShaderKey.size());
869 for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKey.size(); pixelShaderKeyIndex++)
870 {
Brandon Joneseb994362014-09-24 10:27:28 -0700871 const PixelShaderOutputVariable &variable = pixelShaderKey[pixelShaderKeyIndex];
Brandon Jones22502d52014-08-29 16:58:36 -0700872 stream->writeInt(variable.type);
873 stream->writeString(variable.name);
874 stream->writeString(variable.source);
875 stream->writeInt(variable.outputIndex);
876 }
877
Brandon Joneseb994362014-09-24 10:27:28 -0700878 stream->writeInt(mVertexExecutables.size());
879 for (size_t vertexExecutableIndex = 0; vertexExecutableIndex < mVertexExecutables.size(); vertexExecutableIndex++)
880 {
881 VertexExecutable *vertexExecutable = mVertexExecutables[vertexExecutableIndex];
882
Jamie Madilld3dfda22015-07-06 08:28:49 -0400883 const auto &inputLayout = vertexExecutable->inputs();
884 stream->writeInt(inputLayout.size());
885
886 for (size_t inputIndex = 0; inputIndex < inputLayout.size(); inputIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -0700887 {
Jamie Madilld3dfda22015-07-06 08:28:49 -0400888 stream->writeInt(inputLayout[inputIndex]);
Brandon Joneseb994362014-09-24 10:27:28 -0700889 }
890
891 size_t vertexShaderSize = vertexExecutable->shaderExecutable()->getLength();
892 stream->writeInt(vertexShaderSize);
893
894 const uint8_t *vertexBlob = vertexExecutable->shaderExecutable()->getFunction();
895 stream->writeBytes(vertexBlob, vertexShaderSize);
896 }
897
898 stream->writeInt(mPixelExecutables.size());
899 for (size_t pixelExecutableIndex = 0; pixelExecutableIndex < mPixelExecutables.size(); pixelExecutableIndex++)
900 {
901 PixelExecutable *pixelExecutable = mPixelExecutables[pixelExecutableIndex];
902
903 const std::vector<GLenum> outputs = pixelExecutable->outputSignature();
904 stream->writeInt(outputs.size());
905 for (size_t outputIndex = 0; outputIndex < outputs.size(); outputIndex++)
906 {
907 stream->writeInt(outputs[outputIndex]);
908 }
909
910 size_t pixelShaderSize = pixelExecutable->shaderExecutable()->getLength();
911 stream->writeInt(pixelShaderSize);
912
913 const uint8_t *pixelBlob = pixelExecutable->shaderExecutable()->getFunction();
914 stream->writeBytes(pixelBlob, pixelShaderSize);
915 }
916
917 size_t geometryShaderSize = (mGeometryExecutable != NULL) ? mGeometryExecutable->getLength() : 0;
918 stream->writeInt(geometryShaderSize);
919
920 if (mGeometryExecutable != NULL && geometryShaderSize > 0)
921 {
922 const uint8_t *geometryBlob = mGeometryExecutable->getFunction();
923 stream->writeBytes(geometryBlob, geometryShaderSize);
924 }
925
Geoff Langb543aff2014-09-30 14:52:54 -0400926 return gl::Error(GL_NO_ERROR);
Brandon Jones22502d52014-08-29 16:58:36 -0700927}
928
Geoff Lang359ef262015-01-05 14:42:29 -0500929gl::Error ProgramD3D::getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo, ShaderExecutableD3D **outExecutable)
Brandon Jones22502d52014-08-29 16:58:36 -0700930{
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400931 mPixelShaderOutputFormatCache.clear();
Brandon Joneseb994362014-09-24 10:27:28 -0700932
Jamie Madill85a18042015-03-05 15:41:41 -0500933 const FramebufferD3D *fboD3D = GetImplAs<FramebufferD3D>(fbo);
934 const gl::AttachmentList &colorbuffers = fboD3D->getColorAttachmentsForRender(mRenderer->getWorkarounds());
Brandon Joneseb994362014-09-24 10:27:28 -0700935
936 for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment)
937 {
938 const gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment];
939
940 if (colorbuffer)
941 {
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400942 mPixelShaderOutputFormatCache.push_back(colorbuffer->getBinding() == GL_BACK ? GL_COLOR_ATTACHMENT0 : colorbuffer->getBinding());
Brandon Joneseb994362014-09-24 10:27:28 -0700943 }
944 else
945 {
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400946 mPixelShaderOutputFormatCache.push_back(GL_NONE);
Brandon Joneseb994362014-09-24 10:27:28 -0700947 }
948 }
949
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400950 return getPixelExecutableForOutputLayout(mPixelShaderOutputFormatCache, outExecutable, nullptr);
Brandon Joneseb994362014-09-24 10:27:28 -0700951}
952
Jamie Madill97399232014-12-23 12:31:15 -0500953gl::Error ProgramD3D::getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputSignature,
Geoff Lang359ef262015-01-05 14:42:29 -0500954 ShaderExecutableD3D **outExectuable,
Jamie Madill97399232014-12-23 12:31:15 -0500955 gl::InfoLog *infoLog)
Brandon Joneseb994362014-09-24 10:27:28 -0700956{
957 for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++)
958 {
959 if (mPixelExecutables[executableIndex]->matchesSignature(outputSignature))
960 {
Geoff Langb543aff2014-09-30 14:52:54 -0400961 *outExectuable = mPixelExecutables[executableIndex]->shaderExecutable();
962 return gl::Error(GL_NO_ERROR);
Brandon Joneseb994362014-09-24 10:27:28 -0700963 }
964 }
965
Brandon Jones22502d52014-08-29 16:58:36 -0700966 std::string finalPixelHLSL = mDynamicHLSL->generatePixelShaderForOutputSignature(mPixelHLSL, mPixelShaderKey, mUsesFragDepth,
967 outputSignature);
968
969 // Generate new pixel executable
Geoff Lang359ef262015-01-05 14:42:29 -0500970 ShaderExecutableD3D *pixelExecutable = NULL;
Jamie Madill97399232014-12-23 12:31:15 -0500971
972 gl::InfoLog tempInfoLog;
973 gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
974
Jamie Madillada9ecc2015-08-17 12:53:37 -0400975 gl::Error error = mRenderer->compileToExecutable(
976 *currentInfoLog, finalPixelHLSL, SHADER_PIXEL, mTransformFeedbackLinkedVaryings,
977 (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), mPixelWorkarounds,
978 &pixelExecutable);
Geoff Langb543aff2014-09-30 14:52:54 -0400979 if (error.isError())
980 {
981 return error;
982 }
Brandon Joneseb994362014-09-24 10:27:28 -0700983
Jamie Madill97399232014-12-23 12:31:15 -0500984 if (pixelExecutable)
985 {
986 mPixelExecutables.push_back(new PixelExecutable(outputSignature, pixelExecutable));
987 }
988 else if (!infoLog)
Brandon Joneseb994362014-09-24 10:27:28 -0700989 {
990 std::vector<char> tempCharBuffer(tempInfoLog.getLength() + 3);
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700991 tempInfoLog.getLog(static_cast<GLsizei>(tempInfoLog.getLength()), NULL, &tempCharBuffer[0]);
Brandon Joneseb994362014-09-24 10:27:28 -0700992 ERR("Error compiling dynamic pixel executable:\n%s\n", &tempCharBuffer[0]);
993 }
Brandon Jones22502d52014-08-29 16:58:36 -0700994
Geoff Langb543aff2014-09-30 14:52:54 -0400995 *outExectuable = pixelExecutable;
996 return gl::Error(GL_NO_ERROR);
Brandon Jones22502d52014-08-29 16:58:36 -0700997}
998
Jamie Madilld3dfda22015-07-06 08:28:49 -0400999gl::Error ProgramD3D::getVertexExecutableForInputLayout(const gl::InputLayout &inputLayout,
Geoff Lang359ef262015-01-05 14:42:29 -05001000 ShaderExecutableD3D **outExectuable,
Jamie Madill97399232014-12-23 12:31:15 -05001001 gl::InfoLog *infoLog)
Brandon Jones22502d52014-08-29 16:58:36 -07001002{
Jamie Madilld3dfda22015-07-06 08:28:49 -04001003 VertexExecutable::getSignature(mRenderer, inputLayout, &mCachedVertexSignature);
Brandon Joneseb994362014-09-24 10:27:28 -07001004
1005 for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++)
1006 {
Jamie Madilld3dfda22015-07-06 08:28:49 -04001007 if (mVertexExecutables[executableIndex]->matchesSignature(mCachedVertexSignature))
Brandon Joneseb994362014-09-24 10:27:28 -07001008 {
Geoff Langb543aff2014-09-30 14:52:54 -04001009 *outExectuable = mVertexExecutables[executableIndex]->shaderExecutable();
1010 return gl::Error(GL_NO_ERROR);
Brandon Joneseb994362014-09-24 10:27:28 -07001011 }
1012 }
1013
Brandon Jones22502d52014-08-29 16:58:36 -07001014 // Generate new dynamic layout with attribute conversions
Jamie Madillc349ec02015-08-21 16:53:12 -04001015 std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout(
1016 mVertexHLSL, inputLayout, mData.getAttributes());
Brandon Jones22502d52014-08-29 16:58:36 -07001017
1018 // Generate new vertex executable
Geoff Lang359ef262015-01-05 14:42:29 -05001019 ShaderExecutableD3D *vertexExecutable = NULL;
Jamie Madill97399232014-12-23 12:31:15 -05001020
1021 gl::InfoLog tempInfoLog;
1022 gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
1023
Jamie Madillada9ecc2015-08-17 12:53:37 -04001024 gl::Error error = mRenderer->compileToExecutable(
1025 *currentInfoLog, finalVertexHLSL, SHADER_VERTEX, mTransformFeedbackLinkedVaryings,
1026 (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), mVertexWorkarounds,
1027 &vertexExecutable);
Geoff Langb543aff2014-09-30 14:52:54 -04001028 if (error.isError())
1029 {
1030 return error;
1031 }
1032
Jamie Madill97399232014-12-23 12:31:15 -05001033 if (vertexExecutable)
Brandon Joneseb994362014-09-24 10:27:28 -07001034 {
Jamie Madilld3dfda22015-07-06 08:28:49 -04001035 mVertexExecutables.push_back(new VertexExecutable(inputLayout, mCachedVertexSignature, vertexExecutable));
Brandon Joneseb994362014-09-24 10:27:28 -07001036 }
Jamie Madill97399232014-12-23 12:31:15 -05001037 else if (!infoLog)
1038 {
1039 std::vector<char> tempCharBuffer(tempInfoLog.getLength() + 3);
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001040 tempInfoLog.getLog(static_cast<GLsizei>(tempInfoLog.getLength()), NULL, &tempCharBuffer[0]);
Jamie Madill97399232014-12-23 12:31:15 -05001041 ERR("Error compiling dynamic vertex executable:\n%s\n", &tempCharBuffer[0]);
1042 }
Brandon Jones22502d52014-08-29 16:58:36 -07001043
Geoff Langb543aff2014-09-30 14:52:54 -04001044 *outExectuable = vertexExecutable;
1045 return gl::Error(GL_NO_ERROR);
Brandon Jones22502d52014-08-29 16:58:36 -07001046}
1047
Jamie Madillca03b352015-09-02 12:38:13 -04001048LinkResult ProgramD3D::compileProgramExecutables(gl::InfoLog &infoLog,
1049 int registers,
1050 const std::vector<PackedVarying> &packedVaryings)
Brandon Jones44151a92014-09-10 11:32:25 -07001051{
Jamie Madill5c6b7bf2015-08-17 12:53:35 -04001052 const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(mData.getAttachedFragmentShader());
Brandon Jones44151a92014-09-10 11:32:25 -07001053
Jamie Madill5c6b7bf2015-08-17 12:53:35 -04001054 const gl::InputLayout &defaultInputLayout =
1055 GetDefaultInputLayoutFromShader(mData.getAttachedVertexShader());
Jamie Madille4ea2022015-03-26 20:35:05 +00001056 ShaderExecutableD3D *defaultVertexExecutable = NULL;
1057 gl::Error error = getVertexExecutableForInputLayout(defaultInputLayout, &defaultVertexExecutable, &infoLog);
1058 if (error.isError())
Austin Kinross434953e2015-02-20 10:49:51 -08001059 {
Jamie Madille4ea2022015-03-26 20:35:05 +00001060 return LinkResult(false, error);
1061 }
Austin Kinross434953e2015-02-20 10:49:51 -08001062
Brandon Joneseb994362014-09-24 10:27:28 -07001063 std::vector<GLenum> defaultPixelOutput = GetDefaultOutputLayoutFromShader(getPixelShaderKey());
Geoff Lang359ef262015-01-05 14:42:29 -05001064 ShaderExecutableD3D *defaultPixelExecutable = NULL;
Jamie Madille4ea2022015-03-26 20:35:05 +00001065 error = getPixelExecutableForOutputLayout(defaultPixelOutput, &defaultPixelExecutable, &infoLog);
Geoff Langb543aff2014-09-30 14:52:54 -04001066 if (error.isError())
1067 {
Geoff Lang7dd2e102014-11-10 15:19:26 -05001068 return LinkResult(false, error);
Geoff Langb543aff2014-09-30 14:52:54 -04001069 }
Brandon Jones44151a92014-09-10 11:32:25 -07001070
Brandon Joneseb994362014-09-24 10:27:28 -07001071 if (usesGeometryShader())
1072 {
Jamie Madillca03b352015-09-02 12:38:13 -04001073 std::string geometryHLSL =
1074 mDynamicHLSL->generateGeometryShaderHLSL(registers, fragmentShaderD3D, packedVaryings);
Brandon Jones44151a92014-09-10 11:32:25 -07001075
Jamie Madillada9ecc2015-08-17 12:53:37 -04001076 error = mRenderer->compileToExecutable(
1077 infoLog, geometryHLSL, SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings,
1078 (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS),
1079 D3DCompilerWorkarounds(), &mGeometryExecutable);
Geoff Langb543aff2014-09-30 14:52:54 -04001080 if (error.isError())
1081 {
Geoff Lang7dd2e102014-11-10 15:19:26 -05001082 return LinkResult(false, error);
Geoff Langb543aff2014-09-30 14:52:54 -04001083 }
Brandon Joneseb994362014-09-24 10:27:28 -07001084 }
1085
Brandon Jones091540d2014-10-29 11:32:04 -07001086#if ANGLE_SHADER_DEBUG_INFO == ANGLE_ENABLED
Jamie Madillca03b352015-09-02 12:38:13 -04001087 const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(mData.getAttachedVertexShader());
1088
Tibor den Ouden97049c62014-10-06 21:39:16 +02001089 if (usesGeometryShader() && mGeometryExecutable)
1090 {
1091 // Geometry shaders are currently only used internally, so there is no corresponding shader object at the interface level
1092 // For now the geometry shader debug info is pre-pended to the vertex shader, this is a bit of a clutch
1093 vertexShaderD3D->appendDebugInfo("// GEOMETRY SHADER BEGIN\n\n");
1094 vertexShaderD3D->appendDebugInfo(mGeometryExecutable->getDebugInfo());
1095 vertexShaderD3D->appendDebugInfo("\nGEOMETRY SHADER END\n\n\n");
1096 }
1097
1098 if (defaultVertexExecutable)
1099 {
1100 vertexShaderD3D->appendDebugInfo(defaultVertexExecutable->getDebugInfo());
1101 }
1102
1103 if (defaultPixelExecutable)
1104 {
1105 fragmentShaderD3D->appendDebugInfo(defaultPixelExecutable->getDebugInfo());
1106 }
1107#endif
1108
Geoff Langb543aff2014-09-30 14:52:54 -04001109 bool linkSuccess = (defaultVertexExecutable && defaultPixelExecutable && (!usesGeometryShader() || mGeometryExecutable));
Geoff Lang7dd2e102014-11-10 15:19:26 -05001110 return LinkResult(linkSuccess, gl::Error(GL_NO_ERROR));
Brandon Jones18bd4102014-09-22 14:21:44 -07001111}
1112
Jamie Madillf5f4ad22015-09-02 18:32:38 +00001113LinkResult ProgramD3D::link(const gl::Data &data, gl::InfoLog &infoLog)
Brandon Jones22502d52014-08-29 16:58:36 -07001114{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001115 reset();
1116
1117 // TODO(jmadill): structures containing samplers
1118 for (const gl::LinkedUniform &linkedUniform : mData.getUniforms())
1119 {
1120 if (linkedUniform.isSampler() && linkedUniform.isField())
1121 {
1122 infoLog << "Structures containing samplers not currently supported in D3D.";
1123 return LinkResult(false, gl::Error(GL_NO_ERROR));
1124 }
1125 }
1126
Jamie Madillf5f4ad22015-09-02 18:32:38 +00001127 const gl::Shader *vertexShader = mData.getAttachedVertexShader();
1128 const gl::Shader *fragmentShader = mData.getAttachedFragmentShader();
Brandon Joneseb994362014-09-24 10:27:28 -07001129
Jamie Madillf5f4ad22015-09-02 18:32:38 +00001130 const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(vertexShader);
1131 const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(fragmentShader);
1132
Jamie Madill63069df2015-09-01 17:26:41 +00001133 mSamplersVS.resize(data.caps->maxVertexTextureImageUnits);
Jamie Madillf5f4ad22015-09-02 18:32:38 +00001134 mSamplersPS.resize(data.caps->maxTextureImageUnits);
Brandon Jones22502d52014-08-29 16:58:36 -07001135
1136 mVertexHLSL = vertexShaderD3D->getTranslatedSource();
Arun Patole44efa0b2015-03-04 17:11:05 +05301137 vertexShaderD3D->generateWorkarounds(&mVertexWorkarounds);
Brandon Jones44151a92014-09-10 11:32:25 -07001138 mShaderVersion = vertexShaderD3D->getShaderVersion();
Brandon Jones22502d52014-08-29 16:58:36 -07001139
Jamie Madillf5f4ad22015-09-02 18:32:38 +00001140 mPixelHLSL = fragmentShaderD3D->getTranslatedSource();
1141 fragmentShaderD3D->generateWorkarounds(&mPixelWorkarounds);
1142
Austin Kinross02df7962015-07-01 10:03:42 -07001143 if (mRenderer->getRendererLimitations().noFrontFacingSupport)
1144 {
1145 if (fragmentShaderD3D->usesFrontFacing())
1146 {
1147 infoLog << "The current renderer doesn't support gl_FrontFacing";
1148 return LinkResult(false, gl::Error(GL_NO_ERROR));
1149 }
1150 }
1151
Jamie Madillca03b352015-09-02 12:38:13 -04001152 std::vector<PackedVarying> packedVaryings =
1153 MergeVaryings(*vertexShader, *fragmentShader, mData.getTransformFeedbackVaryingNames());
1154
Brandon Jones22502d52014-08-29 16:58:36 -07001155 // Map the varyings to the register file
Jamie Madillca03b352015-09-02 12:38:13 -04001156 int registers = mDynamicHLSL->packVaryings(infoLog, &packedVaryings,
Jamie Madill31c8c562015-08-19 14:08:03 -04001157 mData.getTransformFeedbackVaryingNames());
Brandon Jones22502d52014-08-29 16:58:36 -07001158
Jamie Madill31c8c562015-08-19 14:08:03 -04001159 if (registers < 0)
Brandon Jones22502d52014-08-29 16:58:36 -07001160 {
Geoff Lang7dd2e102014-11-10 15:19:26 -05001161 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Jones22502d52014-08-29 16:58:36 -07001162 }
1163
Jamie Madillccdf74b2015-08-18 10:46:12 -04001164 std::vector<gl::LinkedVarying> linkedVaryings;
Jamie Madill4cff2472015-08-21 16:53:18 -04001165 if (!mDynamicHLSL->generateShaderLinkHLSL(data, mData, infoLog, registers, mPixelHLSL,
Jamie Madillca03b352015-09-02 12:38:13 -04001166 mVertexHLSL, packedVaryings, &linkedVaryings,
1167 &mPixelShaderKey, &mUsesFragDepth))
Brandon Jones22502d52014-08-29 16:58:36 -07001168 {
Geoff Lang7dd2e102014-11-10 15:19:26 -05001169 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Jones22502d52014-08-29 16:58:36 -07001170 }
1171
Brandon Jones44151a92014-09-10 11:32:25 -07001172 mUsesPointSize = vertexShaderD3D->usesPointSize();
1173
Jamie Madill63805b42015-08-25 13:17:39 -04001174 initSemanticIndex();
Jamie Madill437d2662014-12-05 14:23:35 -05001175
Jamie Madill62d31cb2015-09-11 13:25:51 -04001176 assignUniformRegisters();
Jamie Madille473dee2015-08-18 14:49:01 -04001177
Jamie Madillccdf74b2015-08-18 10:46:12 -04001178 gatherTransformFeedbackVaryings(linkedVaryings);
1179
Jamie Madillca03b352015-09-02 12:38:13 -04001180 LinkResult result = compileProgramExecutables(infoLog, registers, packedVaryings);
Jamie Madill31c8c562015-08-19 14:08:03 -04001181 if (result.error.isError() || !result.linkSuccess)
1182 {
1183 infoLog << "Failed to create D3D shaders.";
1184 return result;
1185 }
1186
Geoff Lang7dd2e102014-11-10 15:19:26 -05001187 return LinkResult(true, gl::Error(GL_NO_ERROR));
Brandon Jones22502d52014-08-29 16:58:36 -07001188}
1189
Jamie Madill36cfd6a2015-08-18 10:46:20 -04001190GLboolean ProgramD3D::validate(const gl::Caps &caps, gl::InfoLog *infoLog)
1191{
1192 applyUniforms();
1193 return validateSamplers(infoLog, caps);
1194}
1195
Jamie Madill62d31cb2015-09-11 13:25:51 -04001196void ProgramD3D::gatherUniformBlockInfo(std::vector<gl::UniformBlock> *uniformBlocks,
1197 std::vector<gl::LinkedUniform> *uniforms)
1198{
1199 const gl::Shader *vertexShader = mData.getAttachedVertexShader();
1200
1201 BlockInfoMap blockInfo;
1202 std::map<std::string, size_t> blockDataSizes;
1203
1204 for (const sh::InterfaceBlock &vertexBlock : vertexShader->getInterfaceBlocks())
1205 {
1206 if (!vertexBlock.staticUse && vertexBlock.layout == sh::BLOCKLAYOUT_PACKED)
1207 continue;
1208
1209 if (blockDataSizes.count(vertexBlock.name) > 0)
1210 continue;
1211
1212 size_t dataSize = defineUniformBlock(vertexBlock, &blockInfo);
1213 blockDataSizes[vertexBlock.name] = dataSize;
1214 }
1215
1216 const gl::Shader *fragmentShader = mData.getAttachedFragmentShader();
1217
1218 for (const sh::InterfaceBlock &fragmentBlock : fragmentShader->getInterfaceBlocks())
1219 {
1220 if (!fragmentBlock.staticUse && fragmentBlock.layout == sh::BLOCKLAYOUT_PACKED)
1221 continue;
1222
1223 if (blockDataSizes.count(fragmentBlock.name) > 0)
1224 continue;
1225
1226 size_t dataSize = defineUniformBlock(fragmentBlock, &blockInfo);
1227 blockDataSizes[fragmentBlock.name] = dataSize;
1228 }
1229
1230 // Copy block info out to uniforms.
1231 for (gl::LinkedUniform &linkedUniform : *uniforms)
1232 {
1233 const auto &infoEntry = blockInfo.find(linkedUniform.name);
1234
1235 if (infoEntry != blockInfo.end())
1236 {
1237 linkedUniform.blockInfo = infoEntry->second;
1238 }
1239 }
1240
1241 // Assign registers and update sizes.
1242 const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(vertexShader);
1243 const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(fragmentShader);
1244
1245 for (gl::UniformBlock &uniformBlock : *uniformBlocks)
1246 {
1247 unsigned int uniformBlockElement = uniformBlock.isArray ? uniformBlock.arrayElement : 0;
1248
1249 if (uniformBlock.vertexStaticUse)
1250 {
1251 unsigned int baseRegister =
1252 vertexShaderD3D->getInterfaceBlockRegister(uniformBlock.name);
1253 uniformBlock.vsRegisterIndex = baseRegister + uniformBlockElement;
1254 }
1255
1256 if (uniformBlock.fragmentStaticUse)
1257 {
1258 unsigned int baseRegister =
1259 fragmentShaderD3D->getInterfaceBlockRegister(uniformBlock.name);
1260 uniformBlock.psRegisterIndex = baseRegister + uniformBlockElement;
1261 }
1262
1263 ASSERT(blockDataSizes.count(uniformBlock.name) == 1);
1264 uniformBlock.dataSize = static_cast<unsigned int>(blockDataSizes[uniformBlock.name]);
1265 }
1266}
1267
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001268void ProgramD3D::initializeUniformStorage()
Brandon Jonesc9610c52014-08-25 17:02:59 -07001269{
1270 // Compute total default block size
1271 unsigned int vertexRegisters = 0;
1272 unsigned int fragmentRegisters = 0;
Jamie Madill62d31cb2015-09-11 13:25:51 -04001273 for (const D3DUniform *d3dUniform : mD3DUniforms)
Brandon Jonesc9610c52014-08-25 17:02:59 -07001274 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001275 if (!d3dUniform->isSampler())
Brandon Jonesc9610c52014-08-25 17:02:59 -07001276 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001277 if (d3dUniform->isReferencedByVertexShader())
Brandon Jonesc9610c52014-08-25 17:02:59 -07001278 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001279 vertexRegisters = std::max(vertexRegisters,
1280 d3dUniform->vsRegisterIndex + d3dUniform->registerCount);
Brandon Jonesc9610c52014-08-25 17:02:59 -07001281 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04001282 if (d3dUniform->isReferencedByFragmentShader())
Brandon Jonesc9610c52014-08-25 17:02:59 -07001283 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001284 fragmentRegisters = std::max(
1285 fragmentRegisters, d3dUniform->psRegisterIndex + d3dUniform->registerCount);
Brandon Jonesc9610c52014-08-25 17:02:59 -07001286 }
1287 }
1288 }
1289
1290 mVertexUniformStorage = mRenderer->createUniformStorage(vertexRegisters * 16u);
1291 mFragmentUniformStorage = mRenderer->createUniformStorage(fragmentRegisters * 16u);
1292}
1293
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001294gl::Error ProgramD3D::applyUniforms()
Brandon Jones18bd4102014-09-22 14:21:44 -07001295{
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001296 updateSamplerMapping();
1297
Jamie Madill62d31cb2015-09-11 13:25:51 -04001298 gl::Error error = mRenderer->applyUniforms(*this, mD3DUniforms);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001299 if (error.isError())
1300 {
1301 return error;
1302 }
1303
Jamie Madill62d31cb2015-09-11 13:25:51 -04001304 for (D3DUniform *d3dUniform : mD3DUniforms)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001305 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001306 d3dUniform->dirty = false;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001307 }
1308
1309 return gl::Error(GL_NO_ERROR);
Brandon Jones18bd4102014-09-22 14:21:44 -07001310}
1311
Jamie Madilld1fe1642015-08-21 16:26:04 -04001312gl::Error ProgramD3D::applyUniformBuffers(const gl::Data &data)
Brandon Jones18bd4102014-09-22 14:21:44 -07001313{
Jamie Madill03260fa2015-06-22 13:57:22 -04001314 mVertexUBOCache.clear();
1315 mFragmentUBOCache.clear();
Brandon Jones18bd4102014-09-22 14:21:44 -07001316
1317 const unsigned int reservedBuffersInVS = mRenderer->getReservedVertexUniformBuffers();
1318 const unsigned int reservedBuffersInFS = mRenderer->getReservedFragmentUniformBuffers();
1319
Jamie Madill62d31cb2015-09-11 13:25:51 -04001320 const auto &uniformBlocks = mData.getUniformBlocks();
1321 for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < uniformBlocks.size();
1322 uniformBlockIndex++)
Brandon Jones18bd4102014-09-22 14:21:44 -07001323 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001324 const gl::UniformBlock &uniformBlock = uniformBlocks[uniformBlockIndex];
Jamie Madilld1fe1642015-08-21 16:26:04 -04001325 GLuint blockBinding = mData.getUniformBlockBinding(uniformBlockIndex);
Brandon Jones18bd4102014-09-22 14:21:44 -07001326
Brandon Jones18bd4102014-09-22 14:21:44 -07001327 // Unnecessary to apply an unreferenced standard or shared UBO
Jamie Madill62d31cb2015-09-11 13:25:51 -04001328 if (!uniformBlock.vertexStaticUse && !uniformBlock.fragmentStaticUse)
Brandon Jones18bd4102014-09-22 14:21:44 -07001329 {
1330 continue;
1331 }
1332
Jamie Madill62d31cb2015-09-11 13:25:51 -04001333 if (uniformBlock.vertexStaticUse)
Brandon Jones18bd4102014-09-22 14:21:44 -07001334 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001335 unsigned int registerIndex = uniformBlock.vsRegisterIndex - reservedBuffersInVS;
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00001336 ASSERT(registerIndex < data.caps->maxVertexUniformBlocks);
Jamie Madill03260fa2015-06-22 13:57:22 -04001337
Jamie Madill969194d2015-07-20 14:36:56 -04001338 if (mVertexUBOCache.size() <= registerIndex)
Jamie Madill03260fa2015-06-22 13:57:22 -04001339 {
1340 mVertexUBOCache.resize(registerIndex + 1, -1);
1341 }
1342
1343 ASSERT(mVertexUBOCache[registerIndex] == -1);
1344 mVertexUBOCache[registerIndex] = blockBinding;
Brandon Jones18bd4102014-09-22 14:21:44 -07001345 }
1346
Jamie Madill62d31cb2015-09-11 13:25:51 -04001347 if (uniformBlock.fragmentStaticUse)
Brandon Jones18bd4102014-09-22 14:21:44 -07001348 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001349 unsigned int registerIndex = uniformBlock.psRegisterIndex - reservedBuffersInFS;
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00001350 ASSERT(registerIndex < data.caps->maxFragmentUniformBlocks);
Jamie Madill03260fa2015-06-22 13:57:22 -04001351
1352 if (mFragmentUBOCache.size() <= registerIndex)
1353 {
1354 mFragmentUBOCache.resize(registerIndex + 1, -1);
1355 }
1356
1357 ASSERT(mFragmentUBOCache[registerIndex] == -1);
1358 mFragmentUBOCache[registerIndex] = blockBinding;
Brandon Jones18bd4102014-09-22 14:21:44 -07001359 }
1360 }
1361
Jamie Madill03260fa2015-06-22 13:57:22 -04001362 return mRenderer->setUniformBuffers(data, mVertexUBOCache, mFragmentUBOCache);
Brandon Jones18bd4102014-09-22 14:21:44 -07001363}
1364
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001365void ProgramD3D::dirtyAllUniforms()
Brandon Jones18bd4102014-09-22 14:21:44 -07001366{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001367 for (D3DUniform *d3dUniform : mD3DUniforms)
Brandon Jones18bd4102014-09-22 14:21:44 -07001368 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001369 d3dUniform->dirty = true;
Brandon Jones18bd4102014-09-22 14:21:44 -07001370 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001371}
1372
1373void ProgramD3D::setUniform1fv(GLint location, GLsizei count, const GLfloat* v)
1374{
1375 setUniform(location, count, v, GL_FLOAT);
1376}
1377
1378void ProgramD3D::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
1379{
1380 setUniform(location, count, v, GL_FLOAT_VEC2);
1381}
1382
1383void ProgramD3D::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
1384{
1385 setUniform(location, count, v, GL_FLOAT_VEC3);
1386}
1387
1388void ProgramD3D::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
1389{
1390 setUniform(location, count, v, GL_FLOAT_VEC4);
1391}
1392
1393void ProgramD3D::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1394{
1395 setUniformMatrixfv<2, 2>(location, count, transpose, value, GL_FLOAT_MAT2);
1396}
1397
1398void ProgramD3D::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1399{
1400 setUniformMatrixfv<3, 3>(location, count, transpose, value, GL_FLOAT_MAT3);
1401}
1402
1403void ProgramD3D::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1404{
1405 setUniformMatrixfv<4, 4>(location, count, transpose, value, GL_FLOAT_MAT4);
1406}
1407
1408void ProgramD3D::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1409{
1410 setUniformMatrixfv<2, 3>(location, count, transpose, value, GL_FLOAT_MAT2x3);
1411}
1412
1413void ProgramD3D::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1414{
1415 setUniformMatrixfv<3, 2>(location, count, transpose, value, GL_FLOAT_MAT3x2);
1416}
1417
1418void ProgramD3D::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1419{
1420 setUniformMatrixfv<2, 4>(location, count, transpose, value, GL_FLOAT_MAT2x4);
1421}
1422
1423void ProgramD3D::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1424{
1425 setUniformMatrixfv<4, 2>(location, count, transpose, value, GL_FLOAT_MAT4x2);
1426}
1427
1428void ProgramD3D::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1429{
1430 setUniformMatrixfv<3, 4>(location, count, transpose, value, GL_FLOAT_MAT3x4);
1431}
1432
1433void ProgramD3D::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1434{
1435 setUniformMatrixfv<4, 3>(location, count, transpose, value, GL_FLOAT_MAT4x3);
1436}
1437
1438void ProgramD3D::setUniform1iv(GLint location, GLsizei count, const GLint *v)
1439{
1440 setUniform(location, count, v, GL_INT);
1441}
1442
1443void ProgramD3D::setUniform2iv(GLint location, GLsizei count, const GLint *v)
1444{
1445 setUniform(location, count, v, GL_INT_VEC2);
1446}
1447
1448void ProgramD3D::setUniform3iv(GLint location, GLsizei count, const GLint *v)
1449{
1450 setUniform(location, count, v, GL_INT_VEC3);
1451}
1452
1453void ProgramD3D::setUniform4iv(GLint location, GLsizei count, const GLint *v)
1454{
1455 setUniform(location, count, v, GL_INT_VEC4);
1456}
1457
1458void ProgramD3D::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
1459{
1460 setUniform(location, count, v, GL_UNSIGNED_INT);
1461}
1462
1463void ProgramD3D::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
1464{
1465 setUniform(location, count, v, GL_UNSIGNED_INT_VEC2);
1466}
1467
1468void ProgramD3D::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
1469{
1470 setUniform(location, count, v, GL_UNSIGNED_INT_VEC3);
1471}
1472
1473void ProgramD3D::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
1474{
1475 setUniform(location, count, v, GL_UNSIGNED_INT_VEC4);
1476}
1477
Jamie Madill62d31cb2015-09-11 13:25:51 -04001478void ProgramD3D::assignUniformRegisters()
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001479{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001480 const gl::Shader *vertexShader = mData.getAttachedVertexShader();
1481 const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(vertexShader);
Jamie Madilla2eb02c2015-09-11 12:31:41 +00001482
Jamie Madill62d31cb2015-09-11 13:25:51 -04001483 for (const sh::Uniform &vertexUniform : vertexShader->getUniforms())
Jamie Madillfb536032015-09-11 13:19:49 -04001484
Jamie Madilla2eb02c2015-09-11 12:31:41 +00001485 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001486 if (vertexUniform.staticUse)
Jamie Madillfb536032015-09-11 13:19:49 -04001487 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001488 assignUniformRegistersBase(vertexShaderD3D, vertexUniform);
Jamie Madillfb536032015-09-11 13:19:49 -04001489 }
1490 }
1491
Jamie Madill62d31cb2015-09-11 13:25:51 -04001492 const gl::Shader *fragmentShader = mData.getAttachedFragmentShader();
1493 const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(fragmentShader);
Jamie Madillfb536032015-09-11 13:19:49 -04001494
Jamie Madill62d31cb2015-09-11 13:25:51 -04001495 for (const sh::Uniform &fragmentUniform : fragmentShader->getUniforms())
Jamie Madillfb536032015-09-11 13:19:49 -04001496 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001497 if (fragmentUniform.staticUse)
Jamie Madillfb536032015-09-11 13:19:49 -04001498 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001499 assignUniformRegistersBase(fragmentShaderD3D, fragmentUniform);
Jamie Madillfb536032015-09-11 13:19:49 -04001500 }
1501 }
1502
Jamie Madill62d31cb2015-09-11 13:25:51 -04001503 assignAllSamplerRegisters();
Jamie Madillfb536032015-09-11 13:19:49 -04001504 initializeUniformStorage();
Jamie Madillfb536032015-09-11 13:19:49 -04001505}
1506
Jamie Madill62d31cb2015-09-11 13:25:51 -04001507void ProgramD3D::assignUniformRegistersBase(const ShaderD3D *shader, const sh::Uniform &uniform)
Jamie Madillfb536032015-09-11 13:19:49 -04001508{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001509 if (uniform.isBuiltIn())
Jamie Madillfb536032015-09-11 13:19:49 -04001510 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001511 assignUniformRegisters(shader, uniform, uniform.name, nullptr);
Jamie Madill55def582015-05-04 11:24:57 -04001512 return;
1513 }
1514
Jamie Madill62d31cb2015-09-11 13:25:51 -04001515 unsigned int startRegister = shader->getUniformRegister(uniform.name);
Geoff Lang492a7e42014-11-05 13:27:06 -05001516 ShShaderOutput outputType = shader->getCompilerOutputType();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001517 sh::HLSLBlockEncoder encoder(sh::HLSLBlockEncoder::GetStrategyFor(outputType));
Jamie Madill62d31cb2015-09-11 13:25:51 -04001518 encoder.skipRegisters(startRegister);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001519
Jamie Madill62d31cb2015-09-11 13:25:51 -04001520 assignUniformRegisters(shader, uniform, uniform.name, &encoder);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001521}
1522
Jamie Madill62d31cb2015-09-11 13:25:51 -04001523D3DUniform *ProgramD3D::getD3DUniformByName(const std::string &name)
1524{
1525 for (D3DUniform *d3dUniform : mD3DUniforms)
1526 {
1527 if (d3dUniform->name == name)
1528 {
1529 return d3dUniform;
1530 }
1531 }
1532
1533 return nullptr;
1534}
1535
1536void ProgramD3D::assignUniformRegisters(const ShaderD3D *shader,
1537 const sh::ShaderVariable &uniform,
1538 const std::string &fullName,
1539 sh::HLSLBlockEncoder *encoder)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001540{
1541 if (uniform.isStruct())
1542 {
1543 for (unsigned int elementIndex = 0; elementIndex < uniform.elementCount(); elementIndex++)
1544 {
1545 const std::string &elementString = (uniform.isArray() ? ArrayString(elementIndex) : "");
1546
Jamie Madill55def582015-05-04 11:24:57 -04001547 if (encoder)
1548 encoder->enterAggregateType();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001549
1550 for (size_t fieldIndex = 0; fieldIndex < uniform.fields.size(); fieldIndex++)
1551 {
1552 const sh::ShaderVariable &field = uniform.fields[fieldIndex];
1553 const std::string &fieldFullName = (fullName + elementString + "." + field.name);
1554
Jamie Madill62d31cb2015-09-11 13:25:51 -04001555 assignUniformRegisters(shader, field, fieldFullName, encoder);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001556 }
1557
Jamie Madill55def582015-05-04 11:24:57 -04001558 if (encoder)
1559 encoder->exitAggregateType();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001560 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04001561 return;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001562 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04001563
1564 // Not a struct. Arrays are treated as aggregate types.
1565 if (uniform.isArray() && encoder)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001566 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001567 encoder->enterAggregateType();
1568 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001569
Jamie Madill62d31cb2015-09-11 13:25:51 -04001570 // Advance the uniform offset, to track registers allocation for structs
1571 sh::BlockMemberInfo blockInfo =
1572 encoder ? encoder->encodeType(uniform.type, uniform.arraySize, false)
1573 : sh::BlockMemberInfo::getDefaultBlockInfo();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001574
Jamie Madill62d31cb2015-09-11 13:25:51 -04001575 D3DUniform *d3dUniform = getD3DUniformByName(fullName);
Jamie Madill2857f482015-02-09 15:35:29 -05001576
Jamie Madill62d31cb2015-09-11 13:25:51 -04001577 if (!d3dUniform)
1578 {
1579 // We're building the list twice, make sure we use the same indexing. Special case
1580 // built-ins.
1581 ASSERT(fullName.compare(0, 3, "gl_") == 0 ||
1582 mData.getUniformIndex(fullName) == static_cast<GLint>(mD3DUniforms.size()));
Jamie Madill55def582015-05-04 11:24:57 -04001583
Jamie Madill62d31cb2015-09-11 13:25:51 -04001584 d3dUniform = new D3DUniform(uniform.type, fullName, uniform.arraySize, true);
1585 mD3DUniforms.push_back(d3dUniform);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001586
Jamie Madill55def582015-05-04 11:24:57 -04001587 if (encoder)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001588 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001589 d3dUniform->registerElement =
1590 static_cast<unsigned int>(sh::HLSLBlockEncoder::getBlockRegisterElement(blockInfo));
Jamie Madillfb536032015-09-11 13:19:49 -04001591 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04001592 }
1593
1594 if (encoder)
1595 {
1596 unsigned int reg =
1597 static_cast<unsigned int>(sh::HLSLBlockEncoder::getBlockRegister(blockInfo));
1598 if (shader->getShaderType() == GL_FRAGMENT_SHADER)
1599 {
1600 d3dUniform->psRegisterIndex = reg;
1601 }
1602 else if (shader->getShaderType() == GL_VERTEX_SHADER)
1603 {
1604 d3dUniform->vsRegisterIndex = reg;
1605 }
1606 else
1607 UNREACHABLE();
Jamie Madillfb536032015-09-11 13:19:49 -04001608
1609 // Arrays are treated as aggregate types
Jamie Madill62d31cb2015-09-11 13:25:51 -04001610 if (uniform.isArray())
Jamie Madillfb536032015-09-11 13:19:49 -04001611 {
1612 encoder->exitAggregateType();
1613 }
1614 }
1615}
1616
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001617template <typename T>
1618static inline void SetIfDirty(T *dest, const T& source, bool *dirtyFlag)
1619{
1620 ASSERT(dest != NULL);
1621 ASSERT(dirtyFlag != NULL);
1622
1623 *dirtyFlag = *dirtyFlag || (memcmp(dest, &source, sizeof(T)) != 0);
1624 *dest = source;
1625}
1626
1627template <typename T>
Jamie Madill62d31cb2015-09-11 13:25:51 -04001628void ProgramD3D::setUniform(GLint location, GLsizei countIn, const T *v, GLenum targetUniformType)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001629{
1630 const int components = gl::VariableComponentCount(targetUniformType);
1631 const GLenum targetBoolType = gl::VariableBoolVectorType(targetUniformType);
1632
Jamie Madill62d31cb2015-09-11 13:25:51 -04001633 D3DUniform *targetUniform = getD3DUniformFromLocation(location);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001634
Jamie Madill62d31cb2015-09-11 13:25:51 -04001635 unsigned int elementCount = targetUniform->elementCount();
1636 unsigned int arrayElement = mData.getUniformLocations()[location].element;
1637 unsigned int count = std::min(elementCount - arrayElement, static_cast<unsigned int>(countIn));
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001638
1639 if (targetUniform->type == targetUniformType)
1640 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001641 T *target = reinterpret_cast<T *>(targetUniform->data) + arrayElement * 4;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001642
Jamie Madill62d31cb2015-09-11 13:25:51 -04001643 for (unsigned int i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001644 {
1645 T *dest = target + (i * 4);
1646 const T *source = v + (i * components);
1647
1648 for (int c = 0; c < components; c++)
1649 {
1650 SetIfDirty(dest + c, source[c], &targetUniform->dirty);
1651 }
1652 for (int c = components; c < 4; c++)
1653 {
1654 SetIfDirty(dest + c, T(0), &targetUniform->dirty);
1655 }
1656 }
1657 }
1658 else if (targetUniform->type == targetBoolType)
1659 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001660 GLint *boolParams = reinterpret_cast<GLint *>(targetUniform->data) + arrayElement * 4;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001661
Jamie Madill62d31cb2015-09-11 13:25:51 -04001662 for (unsigned int i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001663 {
1664 GLint *dest = boolParams + (i * 4);
1665 const T *source = v + (i * components);
1666
1667 for (int c = 0; c < components; c++)
1668 {
1669 SetIfDirty(dest + c, (source[c] == static_cast<T>(0)) ? GL_FALSE : GL_TRUE, &targetUniform->dirty);
1670 }
1671 for (int c = components; c < 4; c++)
1672 {
1673 SetIfDirty(dest + c, GL_FALSE, &targetUniform->dirty);
1674 }
1675 }
1676 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04001677 else if (targetUniform->isSampler())
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001678 {
1679 ASSERT(targetUniformType == GL_INT);
1680
Jamie Madill62d31cb2015-09-11 13:25:51 -04001681 GLint *target = reinterpret_cast<GLint *>(targetUniform->data) + arrayElement * 4;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001682
1683 bool wasDirty = targetUniform->dirty;
1684
Jamie Madill62d31cb2015-09-11 13:25:51 -04001685 for (unsigned int i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001686 {
1687 GLint *dest = target + (i * 4);
1688 const GLint *source = reinterpret_cast<const GLint*>(v) + (i * components);
1689
1690 SetIfDirty(dest + 0, source[0], &targetUniform->dirty);
1691 SetIfDirty(dest + 1, 0, &targetUniform->dirty);
1692 SetIfDirty(dest + 2, 0, &targetUniform->dirty);
1693 SetIfDirty(dest + 3, 0, &targetUniform->dirty);
1694 }
1695
1696 if (!wasDirty && targetUniform->dirty)
1697 {
1698 mDirtySamplerMapping = true;
1699 }
Brandon Jones18bd4102014-09-22 14:21:44 -07001700 }
1701 else UNREACHABLE();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001702}
Brandon Jones18bd4102014-09-22 14:21:44 -07001703
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001704template<typename T>
1705bool transposeMatrix(T *target, const GLfloat *value, int targetWidth, int targetHeight, int srcWidth, int srcHeight)
1706{
1707 bool dirty = false;
1708 int copyWidth = std::min(targetHeight, srcWidth);
1709 int copyHeight = std::min(targetWidth, srcHeight);
1710
1711 for (int x = 0; x < copyWidth; x++)
1712 {
1713 for (int y = 0; y < copyHeight; y++)
1714 {
1715 SetIfDirty(target + (x * targetWidth + y), static_cast<T>(value[y * srcWidth + x]), &dirty);
1716 }
1717 }
1718 // clear unfilled right side
1719 for (int y = 0; y < copyWidth; y++)
1720 {
1721 for (int x = copyHeight; x < targetWidth; x++)
1722 {
1723 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
1724 }
1725 }
1726 // clear unfilled bottom.
1727 for (int y = copyWidth; y < targetHeight; y++)
1728 {
1729 for (int x = 0; x < targetWidth; x++)
1730 {
1731 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
1732 }
1733 }
1734
1735 return dirty;
1736}
1737
1738template<typename T>
1739bool expandMatrix(T *target, const GLfloat *value, int targetWidth, int targetHeight, int srcWidth, int srcHeight)
1740{
1741 bool dirty = false;
1742 int copyWidth = std::min(targetWidth, srcWidth);
1743 int copyHeight = std::min(targetHeight, srcHeight);
1744
1745 for (int y = 0; y < copyHeight; y++)
1746 {
1747 for (int x = 0; x < copyWidth; x++)
1748 {
1749 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(value[y * srcWidth + x]), &dirty);
1750 }
1751 }
1752 // clear unfilled right side
1753 for (int y = 0; y < copyHeight; y++)
1754 {
1755 for (int x = copyWidth; x < targetWidth; x++)
1756 {
1757 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
1758 }
1759 }
1760 // clear unfilled bottom.
1761 for (int y = copyHeight; y < targetHeight; y++)
1762 {
1763 for (int x = 0; x < targetWidth; x++)
1764 {
1765 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
1766 }
1767 }
1768
1769 return dirty;
1770}
1771
1772template <int cols, int rows>
Jamie Madill62d31cb2015-09-11 13:25:51 -04001773void ProgramD3D::setUniformMatrixfv(GLint location,
1774 GLsizei countIn,
1775 GLboolean transpose,
1776 const GLfloat *value,
1777 GLenum targetUniformType)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001778{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001779 D3DUniform *targetUniform = getD3DUniformFromLocation(location);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001780
Jamie Madill62d31cb2015-09-11 13:25:51 -04001781 unsigned int elementCount = targetUniform->elementCount();
1782 unsigned int arrayElement = mData.getUniformLocations()[location].element;
1783 unsigned int count = std::min(elementCount - arrayElement, static_cast<unsigned int>(countIn));
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001784
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001785 const unsigned int targetMatrixStride = (4 * rows);
Jamie Madill62d31cb2015-09-11 13:25:51 -04001786 GLfloat *target =
1787 (GLfloat *)(targetUniform->data + arrayElement * sizeof(GLfloat) * targetMatrixStride);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001788
Jamie Madill62d31cb2015-09-11 13:25:51 -04001789 for (unsigned int i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001790 {
1791 // Internally store matrices as transposed versions to accomodate HLSL matrix indexing
1792 if (transpose == GL_FALSE)
1793 {
1794 targetUniform->dirty = transposeMatrix<GLfloat>(target, value, 4, rows, rows, cols) || targetUniform->dirty;
1795 }
1796 else
1797 {
1798 targetUniform->dirty = expandMatrix<GLfloat>(target, value, 4, rows, cols, rows) || targetUniform->dirty;
1799 }
1800 target += targetMatrixStride;
1801 value += cols * rows;
1802 }
1803}
1804
Jamie Madill62d31cb2015-09-11 13:25:51 -04001805size_t ProgramD3D::defineUniformBlock(const sh::InterfaceBlock &interfaceBlock,
1806 BlockInfoMap *blockInfoOut)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001807{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001808 ASSERT(interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001809
Jamie Madill62d31cb2015-09-11 13:25:51 -04001810 // define member uniforms
1811 sh::Std140BlockEncoder std140Encoder;
1812 sh::HLSLBlockEncoder hlslEncoder(sh::HLSLBlockEncoder::ENCODE_PACKED);
1813 sh::BlockLayoutEncoder *encoder = nullptr;
1814
1815 if (interfaceBlock.layout == sh::BLOCKLAYOUT_STANDARD)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001816 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001817 encoder = &std140Encoder;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001818 }
1819 else
1820 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001821 encoder = &hlslEncoder;
Jamie Madill61b8dd92015-09-09 19:04:04 +00001822 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04001823
1824 GetUniformBlockInfo(interfaceBlock.fields, "", encoder, interfaceBlock.isRowMajorLayout,
1825 blockInfoOut);
1826
1827 return encoder->getBlockSize();
Jamie Madill61b8dd92015-09-09 19:04:04 +00001828}
1829
Jamie Madill62d31cb2015-09-11 13:25:51 -04001830void ProgramD3D::assignAllSamplerRegisters()
Jamie Madilla2eb02c2015-09-11 12:31:41 +00001831{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001832 for (const D3DUniform *d3dUniform : mD3DUniforms)
Jamie Madilla2eb02c2015-09-11 12:31:41 +00001833 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001834 if (d3dUniform->isSampler())
Jamie Madillfb536032015-09-11 13:19:49 -04001835 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001836 assignSamplerRegisters(d3dUniform);
Jamie Madillfb536032015-09-11 13:19:49 -04001837 }
Jamie Madilla2eb02c2015-09-11 12:31:41 +00001838 }
1839}
1840
Jamie Madill62d31cb2015-09-11 13:25:51 -04001841void ProgramD3D::assignSamplerRegisters(const D3DUniform *d3dUniform)
Jamie Madillfb536032015-09-11 13:19:49 -04001842{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001843 ASSERT(d3dUniform->isSampler());
1844 ASSERT(d3dUniform->vsRegisterIndex != GL_INVALID_INDEX ||
1845 d3dUniform->psRegisterIndex != GL_INVALID_INDEX);
Jamie Madillfb536032015-09-11 13:19:49 -04001846
Jamie Madill62d31cb2015-09-11 13:25:51 -04001847 if (d3dUniform->vsRegisterIndex != GL_INVALID_INDEX)
Jamie Madillfb536032015-09-11 13:19:49 -04001848 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001849 AssignSamplers(d3dUniform->vsRegisterIndex, d3dUniform->type, d3dUniform->arraySize,
1850 mSamplersVS, &mUsedVertexSamplerRange);
Jamie Madillfb536032015-09-11 13:19:49 -04001851 }
1852
Jamie Madill62d31cb2015-09-11 13:25:51 -04001853 if (d3dUniform->psRegisterIndex != GL_INVALID_INDEX)
Jamie Madillfb536032015-09-11 13:19:49 -04001854 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001855 AssignSamplers(d3dUniform->psRegisterIndex, d3dUniform->type, d3dUniform->arraySize,
1856 mSamplersPS, &mUsedPixelSamplerRange);
Jamie Madillfb536032015-09-11 13:19:49 -04001857 }
1858}
1859
Jamie Madill62d31cb2015-09-11 13:25:51 -04001860// static
1861void ProgramD3D::AssignSamplers(unsigned int startSamplerIndex,
Jamie Madilld3dfda22015-07-06 08:28:49 -04001862 GLenum samplerType,
1863 unsigned int samplerCount,
1864 std::vector<Sampler> &outSamplers,
1865 GLuint *outUsedRange)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001866{
1867 unsigned int samplerIndex = startSamplerIndex;
1868
1869 do
1870 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001871 ASSERT(samplerIndex < outSamplers.size());
1872 Sampler *sampler = &outSamplers[samplerIndex];
1873 sampler->active = true;
1874 sampler->textureType = GetTextureType(samplerType);
1875 sampler->logicalTextureUnit = 0;
1876 *outUsedRange = std::max(samplerIndex + 1, *outUsedRange);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001877 samplerIndex++;
1878 } while (samplerIndex < startSamplerIndex + samplerCount);
Brandon Jones18bd4102014-09-22 14:21:44 -07001879}
1880
Brandon Jonesc9610c52014-08-25 17:02:59 -07001881void ProgramD3D::reset()
1882{
Brandon Joneseb994362014-09-24 10:27:28 -07001883 SafeDeleteContainer(mVertexExecutables);
1884 SafeDeleteContainer(mPixelExecutables);
1885 SafeDelete(mGeometryExecutable);
1886
Brandon Jones22502d52014-08-29 16:58:36 -07001887 mVertexHLSL.clear();
Geoff Lang6941a552015-07-27 11:06:45 -04001888 mVertexWorkarounds = D3DCompilerWorkarounds();
Brandon Jones44151a92014-09-10 11:32:25 -07001889 mShaderVersion = 100;
Brandon Jones22502d52014-08-29 16:58:36 -07001890
1891 mPixelHLSL.clear();
Geoff Lang6941a552015-07-27 11:06:45 -04001892 mPixelWorkarounds = D3DCompilerWorkarounds();
Brandon Jones22502d52014-08-29 16:58:36 -07001893 mUsesFragDepth = false;
1894 mPixelShaderKey.clear();
Brandon Jones44151a92014-09-10 11:32:25 -07001895 mUsesPointSize = false;
Brandon Jones22502d52014-08-29 16:58:36 -07001896
Jamie Madill62d31cb2015-09-11 13:25:51 -04001897 SafeDeleteContainer(mD3DUniforms);
1898
Brandon Jonesc9610c52014-08-25 17:02:59 -07001899 SafeDelete(mVertexUniformStorage);
1900 SafeDelete(mFragmentUniformStorage);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001901
1902 mSamplersPS.clear();
1903 mSamplersVS.clear();
1904
1905 mUsedVertexSamplerRange = 0;
1906 mUsedPixelSamplerRange = 0;
1907 mDirtySamplerMapping = true;
Jamie Madill437d2662014-12-05 14:23:35 -05001908
Jamie Madill63805b42015-08-25 13:17:39 -04001909 std::fill(mSemanticIndexes, mSemanticIndexes + ArraySize(mSemanticIndexes), -1);
Jamie Madill437d2662014-12-05 14:23:35 -05001910 std::fill(mAttributesByLayout, mAttributesByLayout + ArraySize(mAttributesByLayout), -1);
Jamie Madillccdf74b2015-08-18 10:46:12 -04001911
1912 mTransformFeedbackLinkedVaryings.clear();
Brandon Jonesc9610c52014-08-25 17:02:59 -07001913}
1914
Geoff Lang7dd2e102014-11-10 15:19:26 -05001915unsigned int ProgramD3D::getSerial() const
1916{
1917 return mSerial;
1918}
1919
1920unsigned int ProgramD3D::issueSerial()
1921{
1922 return mCurrentSerial++;
1923}
1924
Jamie Madill63805b42015-08-25 13:17:39 -04001925void ProgramD3D::initSemanticIndex()
1926{
1927 const gl::Shader *vertexShader = mData.getAttachedVertexShader();
1928 ASSERT(vertexShader != nullptr);
1929
1930 // Init semantic index
1931 for (const sh::Attribute &attribute : mData.getAttributes())
1932 {
1933 int attributeIndex = attribute.location;
1934 int index = vertexShader->getSemanticIndex(attribute.name);
1935 int regs = gl::VariableRegisterCount(attribute.type);
1936
1937 for (int reg = 0; reg < regs; ++reg)
1938 {
1939 mSemanticIndexes[attributeIndex + reg] = index + reg;
1940 }
1941 }
1942
1943 initAttributesByLayout();
1944}
1945
Jamie Madill437d2662014-12-05 14:23:35 -05001946void ProgramD3D::initAttributesByLayout()
1947{
1948 for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
1949 {
1950 mAttributesByLayout[i] = i;
1951 }
1952
Jamie Madill63805b42015-08-25 13:17:39 -04001953 std::sort(&mAttributesByLayout[0], &mAttributesByLayout[gl::MAX_VERTEX_ATTRIBS],
1954 AttributeSorter(mSemanticIndexes));
Jamie Madill437d2662014-12-05 14:23:35 -05001955}
1956
Jamie Madill476682e2015-06-30 10:04:29 -04001957void ProgramD3D::sortAttributesByLayout(const std::vector<TranslatedAttribute> &unsortedAttributes,
Jamie Madillf9327d32015-06-22 13:57:16 -04001958 int sortedSemanticIndicesOut[gl::MAX_VERTEX_ATTRIBS],
1959 const rx::TranslatedAttribute *sortedAttributesOut[gl::MAX_VERTEX_ATTRIBS]) const
Jamie Madill437d2662014-12-05 14:23:35 -05001960{
Jamie Madill476682e2015-06-30 10:04:29 -04001961 for (size_t attribIndex = 0; attribIndex < unsortedAttributes.size(); ++attribIndex)
Jamie Madill437d2662014-12-05 14:23:35 -05001962 {
Jamie Madill476682e2015-06-30 10:04:29 -04001963 int oldIndex = mAttributesByLayout[attribIndex];
Jamie Madill63805b42015-08-25 13:17:39 -04001964 sortedSemanticIndicesOut[attribIndex] = mSemanticIndexes[oldIndex];
Jamie Madill476682e2015-06-30 10:04:29 -04001965 sortedAttributesOut[attribIndex] = &unsortedAttributes[oldIndex];
Jamie Madill437d2662014-12-05 14:23:35 -05001966 }
1967}
1968
Jamie Madill63805b42015-08-25 13:17:39 -04001969void ProgramD3D::updateCachedInputLayout(const gl::State &state)
Jamie Madilld3dfda22015-07-06 08:28:49 -04001970{
Jamie Madillbd136f92015-08-10 14:51:37 -04001971 mCachedInputLayout.clear();
Jamie Madilld3dfda22015-07-06 08:28:49 -04001972 const auto &vertexAttributes = state.getVertexArray()->getVertexAttributes();
Jamie Madillf8dd7b12015-08-05 13:50:08 -04001973
Dian Xianga4928832015-09-15 10:11:17 -07001974 for (unsigned int attributeIndex : angle::IterateBitSet(mData.getActiveAttribLocationsMask()))
Jamie Madilld3dfda22015-07-06 08:28:49 -04001975 {
Jamie Madill63805b42015-08-25 13:17:39 -04001976 int semanticIndex = mSemanticIndexes[attributeIndex];
Jamie Madilld3dfda22015-07-06 08:28:49 -04001977
1978 if (semanticIndex != -1)
1979 {
Jamie Madillbd136f92015-08-10 14:51:37 -04001980 if (mCachedInputLayout.size() < static_cast<size_t>(semanticIndex + 1))
1981 {
1982 mCachedInputLayout.resize(semanticIndex + 1, gl::VERTEX_FORMAT_INVALID);
1983 }
Jamie Madilld3dfda22015-07-06 08:28:49 -04001984 mCachedInputLayout[semanticIndex] =
1985 GetVertexFormatType(vertexAttributes[attributeIndex],
1986 state.getVertexAttribCurrentValue(attributeIndex).Type);
1987 }
1988 }
1989}
1990
Jamie Madillccdf74b2015-08-18 10:46:12 -04001991void ProgramD3D::gatherTransformFeedbackVaryings(
1992 const std::vector<gl::LinkedVarying> &linkedVaryings)
1993{
1994 // Gather the linked varyings that are used for transform feedback, they should all exist.
1995 mTransformFeedbackLinkedVaryings.clear();
1996 for (const std::string &tfVaryingName : mData.getTransformFeedbackVaryingNames())
1997 {
1998 for (const gl::LinkedVarying &linkedVarying : linkedVaryings)
1999 {
2000 if (tfVaryingName == linkedVarying.name)
2001 {
2002 mTransformFeedbackLinkedVaryings.push_back(linkedVarying);
2003 break;
2004 }
2005 }
2006 }
2007}
Jamie Madill62d31cb2015-09-11 13:25:51 -04002008
2009D3DUniform *ProgramD3D::getD3DUniformFromLocation(GLint location)
2010{
2011 return mD3DUniforms[mData.getUniformLocations()[location].index];
2012}
Brandon Jonesc9610c52014-08-25 17:02:59 -07002013}