blob: 1ece8caf52114cb1b2d175c4ffac578c40e2a79e [file] [log] [blame]
Brandon Jonesc9610c52014-08-25 17:02:59 -07001//
2// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// ProgramD3D.cpp: Defines the rx::ProgramD3D class which implements rx::ProgramImpl.
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/renderer/d3d/ProgramD3D.h"
Jamie Madill437d2662014-12-05 14:23:35 -050010
11#include "common/utilities.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050012#include "libANGLE/Framebuffer.h"
13#include "libANGLE/FramebufferAttachment.h"
14#include "libANGLE/Program.h"
Jamie Madilld3dfda22015-07-06 08:28:49 -040015#include "libANGLE/VertexArray.h"
Jamie Madill6df9b372015-02-18 21:28:19 +000016#include "libANGLE/features.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050017#include "libANGLE/renderer/d3d/DynamicHLSL.h"
Jamie Madill85a18042015-03-05 15:41:41 -050018#include "libANGLE/renderer/d3d/FramebufferD3D.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050019#include "libANGLE/renderer/d3d/RendererD3D.h"
20#include "libANGLE/renderer/d3d/ShaderD3D.h"
Geoff Lang359ef262015-01-05 14:42:29 -050021#include "libANGLE/renderer/d3d/ShaderExecutableD3D.h"
Jamie Madill437d2662014-12-05 14:23:35 -050022#include "libANGLE/renderer/d3d/VertexDataManager.h"
Geoff Lang22072132014-11-20 15:15:01 -050023
Brandon Jonesc9610c52014-08-25 17:02:59 -070024namespace rx
25{
26
Brandon Joneseb994362014-09-24 10:27:28 -070027namespace
28{
29
Brandon Jones1a8a7e32014-10-01 12:49:30 -070030GLenum GetTextureType(GLenum samplerType)
31{
32 switch (samplerType)
33 {
34 case GL_SAMPLER_2D:
35 case GL_INT_SAMPLER_2D:
36 case GL_UNSIGNED_INT_SAMPLER_2D:
37 case GL_SAMPLER_2D_SHADOW:
38 return GL_TEXTURE_2D;
39 case GL_SAMPLER_3D:
40 case GL_INT_SAMPLER_3D:
41 case GL_UNSIGNED_INT_SAMPLER_3D:
42 return GL_TEXTURE_3D;
43 case GL_SAMPLER_CUBE:
44 case GL_SAMPLER_CUBE_SHADOW:
45 return GL_TEXTURE_CUBE_MAP;
46 case GL_INT_SAMPLER_CUBE:
47 case GL_UNSIGNED_INT_SAMPLER_CUBE:
48 return GL_TEXTURE_CUBE_MAP;
49 case GL_SAMPLER_2D_ARRAY:
50 case GL_INT_SAMPLER_2D_ARRAY:
51 case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
52 case GL_SAMPLER_2D_ARRAY_SHADOW:
53 return GL_TEXTURE_2D_ARRAY;
54 default: UNREACHABLE();
55 }
56
57 return GL_TEXTURE_2D;
58}
59
Jamie Madillf8dd7b12015-08-05 13:50:08 -040060gl::InputLayout GetDefaultInputLayoutFromShader(const gl::Shader *vertexShader)
Brandon Joneseb994362014-09-24 10:27:28 -070061{
Jamie Madillbd136f92015-08-10 14:51:37 -040062 gl::InputLayout defaultLayout;
63 for (const sh::Attribute &shaderAttr : vertexShader->getActiveAttributes())
Brandon Joneseb994362014-09-24 10:27:28 -070064 {
Brandon Joneseb994362014-09-24 10:27:28 -070065 if (shaderAttr.type != GL_NONE)
66 {
67 GLenum transposedType = gl::TransposeMatrixType(shaderAttr.type);
68
Jamie Madilld3dfda22015-07-06 08:28:49 -040069 for (size_t rowIndex = 0;
70 static_cast<int>(rowIndex) < gl::VariableRowCount(transposedType);
71 ++rowIndex)
Brandon Joneseb994362014-09-24 10:27:28 -070072 {
Jamie Madilld3dfda22015-07-06 08:28:49 -040073 GLenum componentType = gl::VariableComponentType(transposedType);
74 GLuint components = static_cast<GLuint>(gl::VariableColumnCount(transposedType));
75 bool pureInt = (componentType != GL_FLOAT);
76 gl::VertexFormatType defaultType = gl::GetVertexFormatType(
77 componentType, GL_FALSE, components, pureInt);
Brandon Joneseb994362014-09-24 10:27:28 -070078
Jamie Madillbd136f92015-08-10 14:51:37 -040079 defaultLayout.push_back(defaultType);
Brandon Joneseb994362014-09-24 10:27:28 -070080 }
81 }
82 }
Jamie Madillf8dd7b12015-08-05 13:50:08 -040083
84 return defaultLayout;
Brandon Joneseb994362014-09-24 10:27:28 -070085}
86
87std::vector<GLenum> GetDefaultOutputLayoutFromShader(const std::vector<PixelShaderOutputVariable> &shaderOutputVars)
88{
Jamie Madillb4463142014-12-19 14:56:54 -050089 std::vector<GLenum> defaultPixelOutput;
Brandon Joneseb994362014-09-24 10:27:28 -070090
Jamie Madillb4463142014-12-19 14:56:54 -050091 if (!shaderOutputVars.empty())
92 {
Cooper Partin4d61f7e2015-08-12 10:56:50 -070093 defaultPixelOutput.push_back(GL_COLOR_ATTACHMENT0 +
94 static_cast<unsigned int>(shaderOutputVars[0].outputIndex));
Jamie Madillb4463142014-12-19 14:56:54 -050095 }
Brandon Joneseb994362014-09-24 10:27:28 -070096
97 return defaultPixelOutput;
98}
99
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700100bool IsRowMajorLayout(const sh::InterfaceBlockField &var)
101{
102 return var.isRowMajorLayout;
103}
104
105bool IsRowMajorLayout(const sh::ShaderVariable &var)
106{
107 return false;
108}
109
Jamie Madill437d2662014-12-05 14:23:35 -0500110struct AttributeSorter
111{
Jamie Madill63805b42015-08-25 13:17:39 -0400112 AttributeSorter(const ProgramD3D::SemanticIndexArray &semanticIndices)
Jamie Madill80d934b2015-02-19 10:16:12 -0500113 : originalIndices(&semanticIndices)
Jamie Madill437d2662014-12-05 14:23:35 -0500114 {
115 }
116
117 bool operator()(int a, int b)
118 {
Jamie Madill80d934b2015-02-19 10:16:12 -0500119 int indexA = (*originalIndices)[a];
120 int indexB = (*originalIndices)[b];
121
122 if (indexA == -1) return false;
123 if (indexB == -1) return true;
124 return (indexA < indexB);
Jamie Madill437d2662014-12-05 14:23:35 -0500125 }
126
Jamie Madill63805b42015-08-25 13:17:39 -0400127 const ProgramD3D::SemanticIndexArray *originalIndices;
Jamie Madill437d2662014-12-05 14:23:35 -0500128};
129
Jamie Madillca03b352015-09-02 12:38:13 -0400130std::vector<PackedVarying> MergeVaryings(const gl::Shader &vertexShader,
131 const gl::Shader &fragmentShader,
132 const std::vector<std::string> &tfVaryings)
Jamie Madillada9ecc2015-08-17 12:53:37 -0400133{
Jamie Madillca03b352015-09-02 12:38:13 -0400134 std::vector<PackedVarying> packedVaryings;
135
136 for (const sh::Varying &output : vertexShader.getVaryings())
Jamie Madillada9ecc2015-08-17 12:53:37 -0400137 {
Jamie Madillca03b352015-09-02 12:38:13 -0400138 bool packed = false;
Jamie Madillada9ecc2015-08-17 12:53:37 -0400139
140 // Built-in varyings obey special rules
Jamie Madillca03b352015-09-02 12:38:13 -0400141 if (output.isBuiltIn())
Jamie Madillada9ecc2015-08-17 12:53:37 -0400142 {
143 continue;
144 }
145
Jamie Madillca03b352015-09-02 12:38:13 -0400146 for (const sh::Varying &input : fragmentShader.getVaryings())
Jamie Madillada9ecc2015-08-17 12:53:37 -0400147 {
Jamie Madillca03b352015-09-02 12:38:13 -0400148 if (output.name == input.name)
Jamie Madillada9ecc2015-08-17 12:53:37 -0400149 {
Jamie Madillca03b352015-09-02 12:38:13 -0400150 packedVaryings.push_back(PackedVarying(input));
151 packed = true;
Jamie Madillada9ecc2015-08-17 12:53:37 -0400152 break;
153 }
154 }
155
Jamie Madillca03b352015-09-02 12:38:13 -0400156 // Keep Transform FB varyings in the merged list always.
157 if (!packed)
158 {
159 for (const std::string &tfVarying : tfVaryings)
160 {
161 if (tfVarying == output.name)
162 {
163 packedVaryings.push_back(PackedVarying(output));
164 packedVaryings.back().vertexOnly = true;
165 break;
166 }
167 }
168 }
Jamie Madillada9ecc2015-08-17 12:53:37 -0400169 }
170
Jamie Madillca03b352015-09-02 12:38:13 -0400171 return packedVaryings;
Brandon Joneseb994362014-09-24 10:27:28 -0700172}
173
Jamie Madill62d31cb2015-09-11 13:25:51 -0400174template <typename VarT>
175void GetUniformBlockInfo(const std::vector<VarT> &fields,
176 const std::string &prefix,
177 sh::BlockLayoutEncoder *encoder,
178 bool inRowMajorLayout,
179 std::map<std::string, sh::BlockMemberInfo> *blockInfoOut)
180{
181 for (const VarT &field : fields)
182 {
183 const std::string &fieldName = (prefix.empty() ? field.name : prefix + "." + field.name);
184
185 if (field.isStruct())
186 {
187 bool rowMajorLayout = (inRowMajorLayout || IsRowMajorLayout(field));
188
189 for (unsigned int arrayElement = 0; arrayElement < field.elementCount(); arrayElement++)
190 {
191 encoder->enterAggregateType();
192
193 const std::string uniformElementName =
194 fieldName + (field.isArray() ? ArrayString(arrayElement) : "");
195 GetUniformBlockInfo(field.fields, uniformElementName, encoder, rowMajorLayout,
196 blockInfoOut);
197
198 encoder->exitAggregateType();
199 }
200 }
201 else
202 {
203 bool isRowMajorMatrix = (gl::IsMatrixType(field.type) && inRowMajorLayout);
204 (*blockInfoOut)[fieldName] =
205 encoder->encodeType(field.type, field.arraySize, isRowMajorMatrix);
206 }
207 }
208}
209
Jamie Madillada9ecc2015-08-17 12:53:37 -0400210} // anonymous namespace
211
Jamie Madill62d31cb2015-09-11 13:25:51 -0400212D3DUniform::D3DUniform(GLenum typeIn,
213 const std::string &nameIn,
214 unsigned int arraySizeIn,
215 bool defaultBlock)
216 : type(typeIn),
217 name(nameIn),
218 arraySize(arraySizeIn),
219 data(nullptr),
220 dirty(true),
Jamie Madill62d31cb2015-09-11 13:25:51 -0400221 vsRegisterIndex(GL_INVALID_INDEX),
Geoff Lang98c56da2015-09-15 15:45:34 -0400222 psRegisterIndex(GL_INVALID_INDEX),
Jamie Madill62d31cb2015-09-11 13:25:51 -0400223 registerCount(0),
224 registerElement(0)
225{
226 // We use data storage for default block uniforms to cache values that are sent to D3D during
227 // rendering
228 // Uniform blocks/buffers are treated separately by the Renderer (ES3 path only)
229 if (defaultBlock)
230 {
231 size_t bytes = gl::VariableInternalSize(type) * elementCount();
232 data = new uint8_t[bytes];
233 memset(data, 0, bytes);
234
235 // TODO(jmadill): is this correct with non-square matrices?
236 registerCount = gl::VariableRowCount(type) * elementCount();
237 }
238}
239
240D3DUniform::~D3DUniform()
241{
242 SafeDeleteArray(data);
243}
244
245bool D3DUniform::isSampler() const
246{
247 return gl::IsSamplerType(type);
248}
249
250bool D3DUniform::isReferencedByVertexShader() const
251{
252 return vsRegisterIndex != GL_INVALID_INDEX;
253}
254
255bool D3DUniform::isReferencedByFragmentShader() const
256{
257 return psRegisterIndex != GL_INVALID_INDEX;
258}
259
Jamie Madilld3dfda22015-07-06 08:28:49 -0400260ProgramD3D::VertexExecutable::VertexExecutable(const gl::InputLayout &inputLayout,
261 const Signature &signature,
Geoff Lang359ef262015-01-05 14:42:29 -0500262 ShaderExecutableD3D *shaderExecutable)
Jamie Madilld3dfda22015-07-06 08:28:49 -0400263 : mInputs(inputLayout),
264 mSignature(signature),
265 mShaderExecutable(shaderExecutable)
Brandon Joneseb994362014-09-24 10:27:28 -0700266{
Brandon Joneseb994362014-09-24 10:27:28 -0700267}
268
269ProgramD3D::VertexExecutable::~VertexExecutable()
270{
271 SafeDelete(mShaderExecutable);
272}
273
Jamie Madilld3dfda22015-07-06 08:28:49 -0400274// static
275void ProgramD3D::VertexExecutable::getSignature(RendererD3D *renderer,
276 const gl::InputLayout &inputLayout,
277 Signature *signatureOut)
Brandon Joneseb994362014-09-24 10:27:28 -0700278{
Jamie Madillbd136f92015-08-10 14:51:37 -0400279 signatureOut->resize(inputLayout.size());
Jamie Madilld3dfda22015-07-06 08:28:49 -0400280
281 for (size_t index = 0; index < inputLayout.size(); ++index)
Brandon Joneseb994362014-09-24 10:27:28 -0700282 {
Jamie Madilld3dfda22015-07-06 08:28:49 -0400283 gl::VertexFormatType vertexFormatType = inputLayout[index];
Jamie Madillbd136f92015-08-10 14:51:37 -0400284 bool converted = false;
Jamie Madillf8dd7b12015-08-05 13:50:08 -0400285 if (vertexFormatType != gl::VERTEX_FORMAT_INVALID)
Brandon Joneseb994362014-09-24 10:27:28 -0700286 {
Jamie Madillf8dd7b12015-08-05 13:50:08 -0400287 VertexConversionType conversionType =
288 renderer->getVertexConversionType(vertexFormatType);
Jamie Madillbd136f92015-08-10 14:51:37 -0400289 converted = ((conversionType & VERTEX_CONVERT_GPU) != 0);
Brandon Joneseb994362014-09-24 10:27:28 -0700290 }
Jamie Madillbd136f92015-08-10 14:51:37 -0400291
292 (*signatureOut)[index] = converted;
Brandon Joneseb994362014-09-24 10:27:28 -0700293 }
Brandon Joneseb994362014-09-24 10:27:28 -0700294}
295
Jamie Madilld3dfda22015-07-06 08:28:49 -0400296bool ProgramD3D::VertexExecutable::matchesSignature(const Signature &signature) const
297{
Jamie Madillbd136f92015-08-10 14:51:37 -0400298 size_t limit = std::max(mSignature.size(), signature.size());
299 for (size_t index = 0; index < limit; ++index)
300 {
301 // treat undefined indexes as 'not converted'
302 bool a = index < signature.size() ? signature[index] : false;
303 bool b = index < mSignature.size() ? mSignature[index] : false;
304 if (a != b)
305 return false;
306 }
307
308 return true;
Jamie Madilld3dfda22015-07-06 08:28:49 -0400309}
310
311ProgramD3D::PixelExecutable::PixelExecutable(const std::vector<GLenum> &outputSignature,
312 ShaderExecutableD3D *shaderExecutable)
Brandon Joneseb994362014-09-24 10:27:28 -0700313 : mOutputSignature(outputSignature),
314 mShaderExecutable(shaderExecutable)
315{
316}
317
318ProgramD3D::PixelExecutable::~PixelExecutable()
319{
320 SafeDelete(mShaderExecutable);
321}
322
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700323ProgramD3D::Sampler::Sampler() : active(false), logicalTextureUnit(0), textureType(GL_TEXTURE_2D)
324{
325}
326
Geoff Lang7dd2e102014-11-10 15:19:26 -0500327unsigned int ProgramD3D::mCurrentSerial = 1;
328
Jamie Madill5c6b7bf2015-08-17 12:53:35 -0400329ProgramD3D::ProgramD3D(const gl::Program::Data &data, RendererD3D *renderer)
330 : ProgramImpl(data),
Brandon Jonesc9610c52014-08-25 17:02:59 -0700331 mRenderer(renderer),
332 mDynamicHLSL(NULL),
Brandon Joneseb994362014-09-24 10:27:28 -0700333 mGeometryExecutable(NULL),
Brandon Jones44151a92014-09-10 11:32:25 -0700334 mUsesPointSize(false),
Brandon Jonesc9610c52014-08-25 17:02:59 -0700335 mVertexUniformStorage(NULL),
Brandon Jones44151a92014-09-10 11:32:25 -0700336 mFragmentUniformStorage(NULL),
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700337 mUsedVertexSamplerRange(0),
338 mUsedPixelSamplerRange(0),
339 mDirtySamplerMapping(true),
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400340 mTextureUnitTypesCache(renderer->getRendererCaps().maxCombinedTextureImageUnits),
Geoff Lang7dd2e102014-11-10 15:19:26 -0500341 mShaderVersion(100),
342 mSerial(issueSerial())
Brandon Jonesc9610c52014-08-25 17:02:59 -0700343{
Brandon Joneseb994362014-09-24 10:27:28 -0700344 mDynamicHLSL = new DynamicHLSL(renderer);
Brandon Jonesc9610c52014-08-25 17:02:59 -0700345}
346
347ProgramD3D::~ProgramD3D()
348{
349 reset();
350 SafeDelete(mDynamicHLSL);
351}
352
Brandon Jones44151a92014-09-10 11:32:25 -0700353bool ProgramD3D::usesPointSpriteEmulation() const
354{
355 return mUsesPointSize && mRenderer->getMajorShaderModel() >= 4;
356}
357
358bool ProgramD3D::usesGeometryShader() const
359{
Cooper Partine6664f02015-01-09 16:22:24 -0800360 return usesPointSpriteEmulation() && !usesInstancedPointSpriteEmulation();
361}
362
363bool ProgramD3D::usesInstancedPointSpriteEmulation() const
364{
365 return mRenderer->getWorkarounds().useInstancedPointSpriteEmulation;
Brandon Jones44151a92014-09-10 11:32:25 -0700366}
367
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700368GLint ProgramD3D::getSamplerMapping(gl::SamplerType type, unsigned int samplerIndex, const gl::Caps &caps) const
369{
370 GLint logicalTextureUnit = -1;
371
372 switch (type)
373 {
374 case gl::SAMPLER_PIXEL:
375 ASSERT(samplerIndex < caps.maxTextureImageUnits);
376 if (samplerIndex < mSamplersPS.size() && mSamplersPS[samplerIndex].active)
377 {
378 logicalTextureUnit = mSamplersPS[samplerIndex].logicalTextureUnit;
379 }
380 break;
381 case gl::SAMPLER_VERTEX:
382 ASSERT(samplerIndex < caps.maxVertexTextureImageUnits);
383 if (samplerIndex < mSamplersVS.size() && mSamplersVS[samplerIndex].active)
384 {
385 logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit;
386 }
387 break;
388 default: UNREACHABLE();
389 }
390
391 if (logicalTextureUnit >= 0 && logicalTextureUnit < static_cast<GLint>(caps.maxCombinedTextureImageUnits))
392 {
393 return logicalTextureUnit;
394 }
395
396 return -1;
397}
398
399// Returns the texture type for a given Direct3D 9 sampler type and
400// index (0-15 for the pixel shader and 0-3 for the vertex shader).
401GLenum ProgramD3D::getSamplerTextureType(gl::SamplerType type, unsigned int samplerIndex) const
402{
403 switch (type)
404 {
405 case gl::SAMPLER_PIXEL:
406 ASSERT(samplerIndex < mSamplersPS.size());
407 ASSERT(mSamplersPS[samplerIndex].active);
408 return mSamplersPS[samplerIndex].textureType;
409 case gl::SAMPLER_VERTEX:
410 ASSERT(samplerIndex < mSamplersVS.size());
411 ASSERT(mSamplersVS[samplerIndex].active);
412 return mSamplersVS[samplerIndex].textureType;
413 default: UNREACHABLE();
414 }
415
416 return GL_TEXTURE_2D;
417}
418
419GLint ProgramD3D::getUsedSamplerRange(gl::SamplerType type) const
420{
421 switch (type)
422 {
423 case gl::SAMPLER_PIXEL:
424 return mUsedPixelSamplerRange;
425 case gl::SAMPLER_VERTEX:
426 return mUsedVertexSamplerRange;
427 default:
428 UNREACHABLE();
429 return 0;
430 }
431}
432
433void ProgramD3D::updateSamplerMapping()
434{
435 if (!mDirtySamplerMapping)
436 {
437 return;
438 }
439
440 mDirtySamplerMapping = false;
441
442 // Retrieve sampler uniform values
Jamie Madill62d31cb2015-09-11 13:25:51 -0400443 for (const D3DUniform *d3dUniform : mD3DUniforms)
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700444 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400445 if (!d3dUniform->dirty)
446 continue;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700447
Jamie Madill62d31cb2015-09-11 13:25:51 -0400448 if (!d3dUniform->isSampler())
449 continue;
450
451 int count = d3dUniform->elementCount();
452 const GLint(*v)[4] = reinterpret_cast<const GLint(*)[4]>(d3dUniform->data);
453
454 if (d3dUniform->isReferencedByFragmentShader())
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700455 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400456 unsigned int firstIndex = d3dUniform->psRegisterIndex;
457
458 for (int i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700459 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400460 unsigned int samplerIndex = firstIndex + i;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700461
Jamie Madill62d31cb2015-09-11 13:25:51 -0400462 if (samplerIndex < mSamplersPS.size())
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700463 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400464 ASSERT(mSamplersPS[samplerIndex].active);
465 mSamplersPS[samplerIndex].logicalTextureUnit = v[i][0];
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700466 }
Jamie Madill62d31cb2015-09-11 13:25:51 -0400467 }
468 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700469
Jamie Madill62d31cb2015-09-11 13:25:51 -0400470 if (d3dUniform->isReferencedByVertexShader())
471 {
472 unsigned int firstIndex = d3dUniform->vsRegisterIndex;
473
474 for (int i = 0; i < count; i++)
475 {
476 unsigned int samplerIndex = firstIndex + i;
477
478 if (samplerIndex < mSamplersVS.size())
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700479 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400480 ASSERT(mSamplersVS[samplerIndex].active);
481 mSamplersVS[samplerIndex].logicalTextureUnit = v[i][0];
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700482 }
483 }
484 }
485 }
486}
487
488bool ProgramD3D::validateSamplers(gl::InfoLog *infoLog, const gl::Caps &caps)
489{
Jamie Madill13776892015-04-28 12:39:06 -0400490 // Skip cache if we're using an infolog, so we get the full error.
491 // Also skip the cache if the sample mapping has changed, or if we haven't ever validated.
492 if (!mDirtySamplerMapping && infoLog == nullptr && mCachedValidateSamplersResult.valid())
493 {
494 return mCachedValidateSamplersResult.value();
495 }
496
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700497 // if any two active samplers in a program are of different types, but refer to the same
498 // texture image unit, and this is the current program, then ValidateProgram will fail, and
499 // DrawArrays and DrawElements will issue the INVALID_OPERATION error.
500 updateSamplerMapping();
501
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400502 std::fill(mTextureUnitTypesCache.begin(), mTextureUnitTypesCache.end(), GL_NONE);
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700503
504 for (unsigned int i = 0; i < mUsedPixelSamplerRange; ++i)
505 {
506 if (mSamplersPS[i].active)
507 {
508 unsigned int unit = mSamplersPS[i].logicalTextureUnit;
509
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400510 if (unit >= caps.maxCombinedTextureImageUnits)
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700511 {
512 if (infoLog)
513 {
Jamie Madillf6113162015-05-07 11:49:21 -0400514 (*infoLog) << "Sampler uniform (" << unit
515 << ") exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS ("
516 << caps.maxCombinedTextureImageUnits << ")";
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700517 }
518
Jamie Madill13776892015-04-28 12:39:06 -0400519 mCachedValidateSamplersResult = false;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700520 return false;
521 }
522
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400523 if (mTextureUnitTypesCache[unit] != GL_NONE)
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700524 {
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400525 if (mSamplersPS[i].textureType != mTextureUnitTypesCache[unit])
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700526 {
527 if (infoLog)
528 {
Jamie Madillf6113162015-05-07 11:49:21 -0400529 (*infoLog) << "Samplers of conflicting types refer to the same texture image unit ("
530 << unit << ").";
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700531 }
532
Jamie Madill13776892015-04-28 12:39:06 -0400533 mCachedValidateSamplersResult = false;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700534 return false;
535 }
536 }
537 else
538 {
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400539 mTextureUnitTypesCache[unit] = mSamplersPS[i].textureType;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700540 }
541 }
542 }
543
544 for (unsigned int i = 0; i < mUsedVertexSamplerRange; ++i)
545 {
546 if (mSamplersVS[i].active)
547 {
548 unsigned int unit = mSamplersVS[i].logicalTextureUnit;
549
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400550 if (unit >= caps.maxCombinedTextureImageUnits)
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700551 {
552 if (infoLog)
553 {
Jamie Madillf6113162015-05-07 11:49:21 -0400554 (*infoLog) << "Sampler uniform (" << unit
555 << ") exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS ("
556 << caps.maxCombinedTextureImageUnits << ")";
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700557 }
558
Jamie Madill13776892015-04-28 12:39:06 -0400559 mCachedValidateSamplersResult = false;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700560 return false;
561 }
562
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400563 if (mTextureUnitTypesCache[unit] != GL_NONE)
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700564 {
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400565 if (mSamplersVS[i].textureType != mTextureUnitTypesCache[unit])
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700566 {
567 if (infoLog)
568 {
Jamie Madillf6113162015-05-07 11:49:21 -0400569 (*infoLog) << "Samplers of conflicting types refer to the same texture image unit ("
570 << unit << ").";
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700571 }
572
Jamie Madill13776892015-04-28 12:39:06 -0400573 mCachedValidateSamplersResult = false;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700574 return false;
575 }
576 }
577 else
578 {
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400579 mTextureUnitTypesCache[unit] = mSamplersVS[i].textureType;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700580 }
581 }
582 }
583
Jamie Madill13776892015-04-28 12:39:06 -0400584 mCachedValidateSamplersResult = true;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700585 return true;
586}
587
Geoff Lang7dd2e102014-11-10 15:19:26 -0500588LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
Brandon Jones22502d52014-08-29 16:58:36 -0700589{
Jamie Madill62d31cb2015-09-11 13:25:51 -0400590 reset();
591
Austin Kinross137b1512015-06-17 16:14:53 -0700592 DeviceIdentifier binaryDeviceIdentifier = { 0 };
593 stream->readBytes(reinterpret_cast<unsigned char*>(&binaryDeviceIdentifier), sizeof(DeviceIdentifier));
594
595 DeviceIdentifier identifier = mRenderer->getAdapterIdentifier();
596 if (memcmp(&identifier, &binaryDeviceIdentifier, sizeof(DeviceIdentifier)) != 0)
597 {
598 infoLog << "Invalid program binary, device configuration has changed.";
599 return LinkResult(false, gl::Error(GL_NO_ERROR));
600 }
601
Jamie Madill2db1fbb2014-12-03 10:58:55 -0500602 int compileFlags = stream->readInt<int>();
603 if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL)
604 {
Jamie Madillf6113162015-05-07 11:49:21 -0400605 infoLog << "Mismatched compilation flags.";
Jamie Madill2db1fbb2014-12-03 10:58:55 -0500606 return LinkResult(false, gl::Error(GL_NO_ERROR));
607 }
608
Brandon Jones44151a92014-09-10 11:32:25 -0700609 stream->readInt(&mShaderVersion);
610
Jamie Madill63805b42015-08-25 13:17:39 -0400611 // TODO(jmadill): replace MAX_VERTEX_ATTRIBS
612 for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; ++i)
613 {
614 stream->readInt(&mSemanticIndexes[i]);
615 }
616
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700617 const unsigned int psSamplerCount = stream->readInt<unsigned int>();
618 for (unsigned int i = 0; i < psSamplerCount; ++i)
619 {
620 Sampler sampler;
621 stream->readBool(&sampler.active);
622 stream->readInt(&sampler.logicalTextureUnit);
623 stream->readInt(&sampler.textureType);
624 mSamplersPS.push_back(sampler);
625 }
626 const unsigned int vsSamplerCount = stream->readInt<unsigned int>();
627 for (unsigned int i = 0; i < vsSamplerCount; ++i)
628 {
629 Sampler sampler;
630 stream->readBool(&sampler.active);
631 stream->readInt(&sampler.logicalTextureUnit);
632 stream->readInt(&sampler.textureType);
633 mSamplersVS.push_back(sampler);
634 }
635
636 stream->readInt(&mUsedVertexSamplerRange);
637 stream->readInt(&mUsedPixelSamplerRange);
638
639 const unsigned int uniformCount = stream->readInt<unsigned int>();
640 if (stream->error())
641 {
Jamie Madillf6113162015-05-07 11:49:21 -0400642 infoLog << "Invalid program binary.";
Geoff Lang7dd2e102014-11-10 15:19:26 -0500643 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700644 }
645
Jamie Madill62d31cb2015-09-11 13:25:51 -0400646 const auto &linkedUniforms = mData.getUniforms();
647 ASSERT(mD3DUniforms.empty());
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700648 for (unsigned int uniformIndex = 0; uniformIndex < uniformCount; uniformIndex++)
649 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400650 const gl::LinkedUniform &linkedUniform = linkedUniforms[uniformIndex];
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700651
Jamie Madill62d31cb2015-09-11 13:25:51 -0400652 D3DUniform *d3dUniform =
653 new D3DUniform(linkedUniform.type, linkedUniform.name, linkedUniform.arraySize,
654 linkedUniform.isInDefaultBlock());
655 stream->readInt(&d3dUniform->psRegisterIndex);
656 stream->readInt(&d3dUniform->vsRegisterIndex);
657 stream->readInt(&d3dUniform->registerCount);
658 stream->readInt(&d3dUniform->registerElement);
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700659
Jamie Madill62d31cb2015-09-11 13:25:51 -0400660 mD3DUniforms.push_back(d3dUniform);
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700661 }
662
Brandon Joneseb994362014-09-24 10:27:28 -0700663 const unsigned int transformFeedbackVaryingCount = stream->readInt<unsigned int>();
664 mTransformFeedbackLinkedVaryings.resize(transformFeedbackVaryingCount);
665 for (unsigned int varyingIndex = 0; varyingIndex < transformFeedbackVaryingCount; varyingIndex++)
666 {
667 gl::LinkedVarying &varying = mTransformFeedbackLinkedVaryings[varyingIndex];
668
669 stream->readString(&varying.name);
670 stream->readInt(&varying.type);
671 stream->readInt(&varying.size);
672 stream->readString(&varying.semanticName);
673 stream->readInt(&varying.semanticIndex);
674 stream->readInt(&varying.semanticIndexCount);
675 }
676
Brandon Jones22502d52014-08-29 16:58:36 -0700677 stream->readString(&mVertexHLSL);
Arun Patole44efa0b2015-03-04 17:11:05 +0530678 stream->readBytes(reinterpret_cast<unsigned char*>(&mVertexWorkarounds), sizeof(D3DCompilerWorkarounds));
Brandon Jones22502d52014-08-29 16:58:36 -0700679 stream->readString(&mPixelHLSL);
Arun Patole44efa0b2015-03-04 17:11:05 +0530680 stream->readBytes(reinterpret_cast<unsigned char*>(&mPixelWorkarounds), sizeof(D3DCompilerWorkarounds));
Brandon Jones22502d52014-08-29 16:58:36 -0700681 stream->readBool(&mUsesFragDepth);
Brandon Jones44151a92014-09-10 11:32:25 -0700682 stream->readBool(&mUsesPointSize);
Brandon Jones22502d52014-08-29 16:58:36 -0700683
684 const size_t pixelShaderKeySize = stream->readInt<unsigned int>();
685 mPixelShaderKey.resize(pixelShaderKeySize);
686 for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKeySize; pixelShaderKeyIndex++)
687 {
688 stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].type);
689 stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].name);
690 stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].source);
691 stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].outputIndex);
692 }
693
Brandon Joneseb994362014-09-24 10:27:28 -0700694 const unsigned char* binary = reinterpret_cast<const unsigned char*>(stream->data());
695
696 const unsigned int vertexShaderCount = stream->readInt<unsigned int>();
697 for (unsigned int vertexShaderIndex = 0; vertexShaderIndex < vertexShaderCount; vertexShaderIndex++)
698 {
Jamie Madilld3dfda22015-07-06 08:28:49 -0400699 size_t inputLayoutSize = stream->readInt<size_t>();
Jamie Madillf8dd7b12015-08-05 13:50:08 -0400700 gl::InputLayout inputLayout(inputLayoutSize, gl::VERTEX_FORMAT_INVALID);
Brandon Joneseb994362014-09-24 10:27:28 -0700701
Jamie Madilld3dfda22015-07-06 08:28:49 -0400702 for (size_t inputIndex = 0; inputIndex < inputLayoutSize; inputIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -0700703 {
Jamie Madillf8dd7b12015-08-05 13:50:08 -0400704 inputLayout[inputIndex] = stream->readInt<gl::VertexFormatType>();
Brandon Joneseb994362014-09-24 10:27:28 -0700705 }
706
707 unsigned int vertexShaderSize = stream->readInt<unsigned int>();
708 const unsigned char *vertexShaderFunction = binary + stream->offset();
Geoff Langb543aff2014-09-30 14:52:54 -0400709
Jamie Madillada9ecc2015-08-17 12:53:37 -0400710 ShaderExecutableD3D *shaderExecutable = nullptr;
711
712 gl::Error error = mRenderer->loadExecutable(
713 vertexShaderFunction, vertexShaderSize, SHADER_VERTEX, mTransformFeedbackLinkedVaryings,
714 (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), &shaderExecutable);
Geoff Langb543aff2014-09-30 14:52:54 -0400715 if (error.isError())
716 {
Geoff Lang7dd2e102014-11-10 15:19:26 -0500717 return LinkResult(false, error);
Geoff Langb543aff2014-09-30 14:52:54 -0400718 }
719
Brandon Joneseb994362014-09-24 10:27:28 -0700720 if (!shaderExecutable)
721 {
Jamie Madillf6113162015-05-07 11:49:21 -0400722 infoLog << "Could not create vertex shader.";
Geoff Lang7dd2e102014-11-10 15:19:26 -0500723 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Joneseb994362014-09-24 10:27:28 -0700724 }
725
726 // generated converted input layout
Jamie Madilld3dfda22015-07-06 08:28:49 -0400727 VertexExecutable::Signature signature;
728 VertexExecutable::getSignature(mRenderer, inputLayout, &signature);
Brandon Joneseb994362014-09-24 10:27:28 -0700729
730 // add new binary
731 mVertexExecutables.push_back(new VertexExecutable(inputLayout, signature, shaderExecutable));
732
733 stream->skip(vertexShaderSize);
734 }
735
736 const size_t pixelShaderCount = stream->readInt<unsigned int>();
737 for (size_t pixelShaderIndex = 0; pixelShaderIndex < pixelShaderCount; pixelShaderIndex++)
738 {
739 const size_t outputCount = stream->readInt<unsigned int>();
740 std::vector<GLenum> outputs(outputCount);
741 for (size_t outputIndex = 0; outputIndex < outputCount; outputIndex++)
742 {
743 stream->readInt(&outputs[outputIndex]);
744 }
745
746 const size_t pixelShaderSize = stream->readInt<unsigned int>();
747 const unsigned char *pixelShaderFunction = binary + stream->offset();
Jamie Madillada9ecc2015-08-17 12:53:37 -0400748 ShaderExecutableD3D *shaderExecutable = nullptr;
749
750 gl::Error error = mRenderer->loadExecutable(
751 pixelShaderFunction, pixelShaderSize, SHADER_PIXEL, mTransformFeedbackLinkedVaryings,
752 (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), &shaderExecutable);
Geoff Langb543aff2014-09-30 14:52:54 -0400753 if (error.isError())
754 {
Geoff Lang7dd2e102014-11-10 15:19:26 -0500755 return LinkResult(false, error);
Geoff Langb543aff2014-09-30 14:52:54 -0400756 }
Brandon Joneseb994362014-09-24 10:27:28 -0700757
758 if (!shaderExecutable)
759 {
Jamie Madillf6113162015-05-07 11:49:21 -0400760 infoLog << "Could not create pixel shader.";
Geoff Lang7dd2e102014-11-10 15:19:26 -0500761 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Joneseb994362014-09-24 10:27:28 -0700762 }
763
764 // add new binary
765 mPixelExecutables.push_back(new PixelExecutable(outputs, shaderExecutable));
766
767 stream->skip(pixelShaderSize);
768 }
769
770 unsigned int geometryShaderSize = stream->readInt<unsigned int>();
771
772 if (geometryShaderSize > 0)
773 {
774 const unsigned char *geometryShaderFunction = binary + stream->offset();
Jamie Madillada9ecc2015-08-17 12:53:37 -0400775 gl::Error error = mRenderer->loadExecutable(
776 geometryShaderFunction, geometryShaderSize, SHADER_GEOMETRY,
777 mTransformFeedbackLinkedVaryings,
778 (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), &mGeometryExecutable);
Geoff Langb543aff2014-09-30 14:52:54 -0400779 if (error.isError())
780 {
Geoff Lang7dd2e102014-11-10 15:19:26 -0500781 return LinkResult(false, error);
Geoff Langb543aff2014-09-30 14:52:54 -0400782 }
Brandon Joneseb994362014-09-24 10:27:28 -0700783
784 if (!mGeometryExecutable)
785 {
Jamie Madillf6113162015-05-07 11:49:21 -0400786 infoLog << "Could not create geometry shader.";
Geoff Lang7dd2e102014-11-10 15:19:26 -0500787 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Joneseb994362014-09-24 10:27:28 -0700788 }
789 stream->skip(geometryShaderSize);
790 }
791
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700792 initializeUniformStorage();
Jamie Madill437d2662014-12-05 14:23:35 -0500793 initAttributesByLayout();
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700794
Geoff Lang7dd2e102014-11-10 15:19:26 -0500795 return LinkResult(true, gl::Error(GL_NO_ERROR));
Brandon Jones22502d52014-08-29 16:58:36 -0700796}
797
Geoff Langb543aff2014-09-30 14:52:54 -0400798gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream)
Brandon Jones22502d52014-08-29 16:58:36 -0700799{
Austin Kinross137b1512015-06-17 16:14:53 -0700800 // Output the DeviceIdentifier before we output any shader code
801 // When we load the binary again later, we can validate the device identifier before trying to compile any HLSL
802 DeviceIdentifier binaryIdentifier = mRenderer->getAdapterIdentifier();
803 stream->writeBytes(reinterpret_cast<unsigned char*>(&binaryIdentifier), sizeof(DeviceIdentifier));
804
Jamie Madill2db1fbb2014-12-03 10:58:55 -0500805 stream->writeInt(ANGLE_COMPILE_OPTIMIZATION_LEVEL);
806
Brandon Jones44151a92014-09-10 11:32:25 -0700807 stream->writeInt(mShaderVersion);
808
Jamie Madill63805b42015-08-25 13:17:39 -0400809 // TODO(jmadill): replace MAX_VERTEX_ATTRIBS
810 for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; ++i)
811 {
812 stream->writeInt(mSemanticIndexes[i]);
813 }
814
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700815 stream->writeInt(mSamplersPS.size());
816 for (unsigned int i = 0; i < mSamplersPS.size(); ++i)
817 {
818 stream->writeInt(mSamplersPS[i].active);
819 stream->writeInt(mSamplersPS[i].logicalTextureUnit);
820 stream->writeInt(mSamplersPS[i].textureType);
821 }
822
823 stream->writeInt(mSamplersVS.size());
824 for (unsigned int i = 0; i < mSamplersVS.size(); ++i)
825 {
826 stream->writeInt(mSamplersVS[i].active);
827 stream->writeInt(mSamplersVS[i].logicalTextureUnit);
828 stream->writeInt(mSamplersVS[i].textureType);
829 }
830
831 stream->writeInt(mUsedVertexSamplerRange);
832 stream->writeInt(mUsedPixelSamplerRange);
833
Jamie Madill62d31cb2015-09-11 13:25:51 -0400834 stream->writeInt(mD3DUniforms.size());
835 for (size_t uniformIndex = 0; uniformIndex < mD3DUniforms.size(); ++uniformIndex)
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700836 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400837 const D3DUniform &uniform = *mD3DUniforms[uniformIndex];
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700838
Jamie Madill62d31cb2015-09-11 13:25:51 -0400839 // Type, name and arraySize are redundant, so aren't stored in the binary.
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700840 stream->writeInt(uniform.psRegisterIndex);
841 stream->writeInt(uniform.vsRegisterIndex);
842 stream->writeInt(uniform.registerCount);
843 stream->writeInt(uniform.registerElement);
844 }
845
Brandon Joneseb994362014-09-24 10:27:28 -0700846 stream->writeInt(mTransformFeedbackLinkedVaryings.size());
847 for (size_t i = 0; i < mTransformFeedbackLinkedVaryings.size(); i++)
848 {
849 const gl::LinkedVarying &varying = mTransformFeedbackLinkedVaryings[i];
850
851 stream->writeString(varying.name);
852 stream->writeInt(varying.type);
853 stream->writeInt(varying.size);
854 stream->writeString(varying.semanticName);
855 stream->writeInt(varying.semanticIndex);
856 stream->writeInt(varying.semanticIndexCount);
857 }
858
Brandon Jones22502d52014-08-29 16:58:36 -0700859 stream->writeString(mVertexHLSL);
Arun Patole44efa0b2015-03-04 17:11:05 +0530860 stream->writeBytes(reinterpret_cast<unsigned char*>(&mVertexWorkarounds), sizeof(D3DCompilerWorkarounds));
Brandon Jones22502d52014-08-29 16:58:36 -0700861 stream->writeString(mPixelHLSL);
Arun Patole44efa0b2015-03-04 17:11:05 +0530862 stream->writeBytes(reinterpret_cast<unsigned char*>(&mPixelWorkarounds), sizeof(D3DCompilerWorkarounds));
Brandon Jones22502d52014-08-29 16:58:36 -0700863 stream->writeInt(mUsesFragDepth);
Brandon Jones44151a92014-09-10 11:32:25 -0700864 stream->writeInt(mUsesPointSize);
Brandon Jones22502d52014-08-29 16:58:36 -0700865
Brandon Joneseb994362014-09-24 10:27:28 -0700866 const std::vector<PixelShaderOutputVariable> &pixelShaderKey = mPixelShaderKey;
Brandon Jones22502d52014-08-29 16:58:36 -0700867 stream->writeInt(pixelShaderKey.size());
868 for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKey.size(); pixelShaderKeyIndex++)
869 {
Brandon Joneseb994362014-09-24 10:27:28 -0700870 const PixelShaderOutputVariable &variable = pixelShaderKey[pixelShaderKeyIndex];
Brandon Jones22502d52014-08-29 16:58:36 -0700871 stream->writeInt(variable.type);
872 stream->writeString(variable.name);
873 stream->writeString(variable.source);
874 stream->writeInt(variable.outputIndex);
875 }
876
Brandon Joneseb994362014-09-24 10:27:28 -0700877 stream->writeInt(mVertexExecutables.size());
878 for (size_t vertexExecutableIndex = 0; vertexExecutableIndex < mVertexExecutables.size(); vertexExecutableIndex++)
879 {
880 VertexExecutable *vertexExecutable = mVertexExecutables[vertexExecutableIndex];
881
Jamie Madilld3dfda22015-07-06 08:28:49 -0400882 const auto &inputLayout = vertexExecutable->inputs();
883 stream->writeInt(inputLayout.size());
884
885 for (size_t inputIndex = 0; inputIndex < inputLayout.size(); inputIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -0700886 {
Jamie Madilld3dfda22015-07-06 08:28:49 -0400887 stream->writeInt(inputLayout[inputIndex]);
Brandon Joneseb994362014-09-24 10:27:28 -0700888 }
889
890 size_t vertexShaderSize = vertexExecutable->shaderExecutable()->getLength();
891 stream->writeInt(vertexShaderSize);
892
893 const uint8_t *vertexBlob = vertexExecutable->shaderExecutable()->getFunction();
894 stream->writeBytes(vertexBlob, vertexShaderSize);
895 }
896
897 stream->writeInt(mPixelExecutables.size());
898 for (size_t pixelExecutableIndex = 0; pixelExecutableIndex < mPixelExecutables.size(); pixelExecutableIndex++)
899 {
900 PixelExecutable *pixelExecutable = mPixelExecutables[pixelExecutableIndex];
901
902 const std::vector<GLenum> outputs = pixelExecutable->outputSignature();
903 stream->writeInt(outputs.size());
904 for (size_t outputIndex = 0; outputIndex < outputs.size(); outputIndex++)
905 {
906 stream->writeInt(outputs[outputIndex]);
907 }
908
909 size_t pixelShaderSize = pixelExecutable->shaderExecutable()->getLength();
910 stream->writeInt(pixelShaderSize);
911
912 const uint8_t *pixelBlob = pixelExecutable->shaderExecutable()->getFunction();
913 stream->writeBytes(pixelBlob, pixelShaderSize);
914 }
915
916 size_t geometryShaderSize = (mGeometryExecutable != NULL) ? mGeometryExecutable->getLength() : 0;
917 stream->writeInt(geometryShaderSize);
918
919 if (mGeometryExecutable != NULL && geometryShaderSize > 0)
920 {
921 const uint8_t *geometryBlob = mGeometryExecutable->getFunction();
922 stream->writeBytes(geometryBlob, geometryShaderSize);
923 }
924
Geoff Langb543aff2014-09-30 14:52:54 -0400925 return gl::Error(GL_NO_ERROR);
Brandon Jones22502d52014-08-29 16:58:36 -0700926}
927
Geoff Lang359ef262015-01-05 14:42:29 -0500928gl::Error ProgramD3D::getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo, ShaderExecutableD3D **outExecutable)
Brandon Jones22502d52014-08-29 16:58:36 -0700929{
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400930 mPixelShaderOutputFormatCache.clear();
Brandon Joneseb994362014-09-24 10:27:28 -0700931
Jamie Madill85a18042015-03-05 15:41:41 -0500932 const FramebufferD3D *fboD3D = GetImplAs<FramebufferD3D>(fbo);
933 const gl::AttachmentList &colorbuffers = fboD3D->getColorAttachmentsForRender(mRenderer->getWorkarounds());
Brandon Joneseb994362014-09-24 10:27:28 -0700934
935 for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment)
936 {
937 const gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment];
938
939 if (colorbuffer)
940 {
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400941 mPixelShaderOutputFormatCache.push_back(colorbuffer->getBinding() == GL_BACK ? GL_COLOR_ATTACHMENT0 : colorbuffer->getBinding());
Brandon Joneseb994362014-09-24 10:27:28 -0700942 }
943 else
944 {
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400945 mPixelShaderOutputFormatCache.push_back(GL_NONE);
Brandon Joneseb994362014-09-24 10:27:28 -0700946 }
947 }
948
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400949 return getPixelExecutableForOutputLayout(mPixelShaderOutputFormatCache, outExecutable, nullptr);
Brandon Joneseb994362014-09-24 10:27:28 -0700950}
951
Jamie Madill97399232014-12-23 12:31:15 -0500952gl::Error ProgramD3D::getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputSignature,
Geoff Lang359ef262015-01-05 14:42:29 -0500953 ShaderExecutableD3D **outExectuable,
Jamie Madill97399232014-12-23 12:31:15 -0500954 gl::InfoLog *infoLog)
Brandon Joneseb994362014-09-24 10:27:28 -0700955{
956 for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++)
957 {
958 if (mPixelExecutables[executableIndex]->matchesSignature(outputSignature))
959 {
Geoff Langb543aff2014-09-30 14:52:54 -0400960 *outExectuable = mPixelExecutables[executableIndex]->shaderExecutable();
961 return gl::Error(GL_NO_ERROR);
Brandon Joneseb994362014-09-24 10:27:28 -0700962 }
963 }
964
Brandon Jones22502d52014-08-29 16:58:36 -0700965 std::string finalPixelHLSL = mDynamicHLSL->generatePixelShaderForOutputSignature(mPixelHLSL, mPixelShaderKey, mUsesFragDepth,
966 outputSignature);
967
968 // Generate new pixel executable
Geoff Lang359ef262015-01-05 14:42:29 -0500969 ShaderExecutableD3D *pixelExecutable = NULL;
Jamie Madill97399232014-12-23 12:31:15 -0500970
971 gl::InfoLog tempInfoLog;
972 gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
973
Jamie Madillada9ecc2015-08-17 12:53:37 -0400974 gl::Error error = mRenderer->compileToExecutable(
975 *currentInfoLog, finalPixelHLSL, SHADER_PIXEL, mTransformFeedbackLinkedVaryings,
976 (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), mPixelWorkarounds,
977 &pixelExecutable);
Geoff Langb543aff2014-09-30 14:52:54 -0400978 if (error.isError())
979 {
980 return error;
981 }
Brandon Joneseb994362014-09-24 10:27:28 -0700982
Jamie Madill97399232014-12-23 12:31:15 -0500983 if (pixelExecutable)
984 {
985 mPixelExecutables.push_back(new PixelExecutable(outputSignature, pixelExecutable));
986 }
987 else if (!infoLog)
Brandon Joneseb994362014-09-24 10:27:28 -0700988 {
989 std::vector<char> tempCharBuffer(tempInfoLog.getLength() + 3);
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700990 tempInfoLog.getLog(static_cast<GLsizei>(tempInfoLog.getLength()), NULL, &tempCharBuffer[0]);
Brandon Joneseb994362014-09-24 10:27:28 -0700991 ERR("Error compiling dynamic pixel executable:\n%s\n", &tempCharBuffer[0]);
992 }
Brandon Jones22502d52014-08-29 16:58:36 -0700993
Geoff Langb543aff2014-09-30 14:52:54 -0400994 *outExectuable = pixelExecutable;
995 return gl::Error(GL_NO_ERROR);
Brandon Jones22502d52014-08-29 16:58:36 -0700996}
997
Jamie Madilld3dfda22015-07-06 08:28:49 -0400998gl::Error ProgramD3D::getVertexExecutableForInputLayout(const gl::InputLayout &inputLayout,
Geoff Lang359ef262015-01-05 14:42:29 -0500999 ShaderExecutableD3D **outExectuable,
Jamie Madill97399232014-12-23 12:31:15 -05001000 gl::InfoLog *infoLog)
Brandon Jones22502d52014-08-29 16:58:36 -07001001{
Jamie Madilld3dfda22015-07-06 08:28:49 -04001002 VertexExecutable::getSignature(mRenderer, inputLayout, &mCachedVertexSignature);
Brandon Joneseb994362014-09-24 10:27:28 -07001003
1004 for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++)
1005 {
Jamie Madilld3dfda22015-07-06 08:28:49 -04001006 if (mVertexExecutables[executableIndex]->matchesSignature(mCachedVertexSignature))
Brandon Joneseb994362014-09-24 10:27:28 -07001007 {
Geoff Langb543aff2014-09-30 14:52:54 -04001008 *outExectuable = mVertexExecutables[executableIndex]->shaderExecutable();
1009 return gl::Error(GL_NO_ERROR);
Brandon Joneseb994362014-09-24 10:27:28 -07001010 }
1011 }
1012
Brandon Jones22502d52014-08-29 16:58:36 -07001013 // Generate new dynamic layout with attribute conversions
Jamie Madillc349ec02015-08-21 16:53:12 -04001014 std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout(
1015 mVertexHLSL, inputLayout, mData.getAttributes());
Brandon Jones22502d52014-08-29 16:58:36 -07001016
1017 // Generate new vertex executable
Geoff Lang359ef262015-01-05 14:42:29 -05001018 ShaderExecutableD3D *vertexExecutable = NULL;
Jamie Madill97399232014-12-23 12:31:15 -05001019
1020 gl::InfoLog tempInfoLog;
1021 gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
1022
Jamie Madillada9ecc2015-08-17 12:53:37 -04001023 gl::Error error = mRenderer->compileToExecutable(
1024 *currentInfoLog, finalVertexHLSL, SHADER_VERTEX, mTransformFeedbackLinkedVaryings,
1025 (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), mVertexWorkarounds,
1026 &vertexExecutable);
Geoff Langb543aff2014-09-30 14:52:54 -04001027 if (error.isError())
1028 {
1029 return error;
1030 }
1031
Jamie Madill97399232014-12-23 12:31:15 -05001032 if (vertexExecutable)
Brandon Joneseb994362014-09-24 10:27:28 -07001033 {
Jamie Madilld3dfda22015-07-06 08:28:49 -04001034 mVertexExecutables.push_back(new VertexExecutable(inputLayout, mCachedVertexSignature, vertexExecutable));
Brandon Joneseb994362014-09-24 10:27:28 -07001035 }
Jamie Madill97399232014-12-23 12:31:15 -05001036 else if (!infoLog)
1037 {
1038 std::vector<char> tempCharBuffer(tempInfoLog.getLength() + 3);
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001039 tempInfoLog.getLog(static_cast<GLsizei>(tempInfoLog.getLength()), NULL, &tempCharBuffer[0]);
Jamie Madill97399232014-12-23 12:31:15 -05001040 ERR("Error compiling dynamic vertex executable:\n%s\n", &tempCharBuffer[0]);
1041 }
Brandon Jones22502d52014-08-29 16:58:36 -07001042
Geoff Langb543aff2014-09-30 14:52:54 -04001043 *outExectuable = vertexExecutable;
1044 return gl::Error(GL_NO_ERROR);
Brandon Jones22502d52014-08-29 16:58:36 -07001045}
1046
Jamie Madillca03b352015-09-02 12:38:13 -04001047LinkResult ProgramD3D::compileProgramExecutables(gl::InfoLog &infoLog,
1048 int registers,
1049 const std::vector<PackedVarying> &packedVaryings)
Brandon Jones44151a92014-09-10 11:32:25 -07001050{
Jamie Madill5c6b7bf2015-08-17 12:53:35 -04001051 const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(mData.getAttachedFragmentShader());
Brandon Jones44151a92014-09-10 11:32:25 -07001052
Jamie Madill5c6b7bf2015-08-17 12:53:35 -04001053 const gl::InputLayout &defaultInputLayout =
1054 GetDefaultInputLayoutFromShader(mData.getAttachedVertexShader());
Jamie Madille4ea2022015-03-26 20:35:05 +00001055 ShaderExecutableD3D *defaultVertexExecutable = NULL;
1056 gl::Error error = getVertexExecutableForInputLayout(defaultInputLayout, &defaultVertexExecutable, &infoLog);
1057 if (error.isError())
Austin Kinross434953e2015-02-20 10:49:51 -08001058 {
Jamie Madille4ea2022015-03-26 20:35:05 +00001059 return LinkResult(false, error);
1060 }
Austin Kinross434953e2015-02-20 10:49:51 -08001061
Brandon Joneseb994362014-09-24 10:27:28 -07001062 std::vector<GLenum> defaultPixelOutput = GetDefaultOutputLayoutFromShader(getPixelShaderKey());
Geoff Lang359ef262015-01-05 14:42:29 -05001063 ShaderExecutableD3D *defaultPixelExecutable = NULL;
Jamie Madille4ea2022015-03-26 20:35:05 +00001064 error = getPixelExecutableForOutputLayout(defaultPixelOutput, &defaultPixelExecutable, &infoLog);
Geoff Langb543aff2014-09-30 14:52:54 -04001065 if (error.isError())
1066 {
Geoff Lang7dd2e102014-11-10 15:19:26 -05001067 return LinkResult(false, error);
Geoff Langb543aff2014-09-30 14:52:54 -04001068 }
Brandon Jones44151a92014-09-10 11:32:25 -07001069
Brandon Joneseb994362014-09-24 10:27:28 -07001070 if (usesGeometryShader())
1071 {
Jamie Madillca03b352015-09-02 12:38:13 -04001072 std::string geometryHLSL =
1073 mDynamicHLSL->generateGeometryShaderHLSL(registers, fragmentShaderD3D, packedVaryings);
Brandon Jones44151a92014-09-10 11:32:25 -07001074
Jamie Madillada9ecc2015-08-17 12:53:37 -04001075 error = mRenderer->compileToExecutable(
1076 infoLog, geometryHLSL, SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings,
1077 (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS),
1078 D3DCompilerWorkarounds(), &mGeometryExecutable);
Geoff Langb543aff2014-09-30 14:52:54 -04001079 if (error.isError())
1080 {
Geoff Lang7dd2e102014-11-10 15:19:26 -05001081 return LinkResult(false, error);
Geoff Langb543aff2014-09-30 14:52:54 -04001082 }
Brandon Joneseb994362014-09-24 10:27:28 -07001083 }
1084
Brandon Jones091540d2014-10-29 11:32:04 -07001085#if ANGLE_SHADER_DEBUG_INFO == ANGLE_ENABLED
Jamie Madillca03b352015-09-02 12:38:13 -04001086 const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(mData.getAttachedVertexShader());
1087
Tibor den Ouden97049c62014-10-06 21:39:16 +02001088 if (usesGeometryShader() && mGeometryExecutable)
1089 {
1090 // Geometry shaders are currently only used internally, so there is no corresponding shader object at the interface level
1091 // For now the geometry shader debug info is pre-pended to the vertex shader, this is a bit of a clutch
1092 vertexShaderD3D->appendDebugInfo("// GEOMETRY SHADER BEGIN\n\n");
1093 vertexShaderD3D->appendDebugInfo(mGeometryExecutable->getDebugInfo());
1094 vertexShaderD3D->appendDebugInfo("\nGEOMETRY SHADER END\n\n\n");
1095 }
1096
1097 if (defaultVertexExecutable)
1098 {
1099 vertexShaderD3D->appendDebugInfo(defaultVertexExecutable->getDebugInfo());
1100 }
1101
1102 if (defaultPixelExecutable)
1103 {
1104 fragmentShaderD3D->appendDebugInfo(defaultPixelExecutable->getDebugInfo());
1105 }
1106#endif
1107
Geoff Langb543aff2014-09-30 14:52:54 -04001108 bool linkSuccess = (defaultVertexExecutable && defaultPixelExecutable && (!usesGeometryShader() || mGeometryExecutable));
Geoff Lang7dd2e102014-11-10 15:19:26 -05001109 return LinkResult(linkSuccess, gl::Error(GL_NO_ERROR));
Brandon Jones18bd4102014-09-22 14:21:44 -07001110}
1111
Jamie Madillf5f4ad22015-09-02 18:32:38 +00001112LinkResult ProgramD3D::link(const gl::Data &data, gl::InfoLog &infoLog)
Brandon Jones22502d52014-08-29 16:58:36 -07001113{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001114 reset();
1115
1116 // TODO(jmadill): structures containing samplers
1117 for (const gl::LinkedUniform &linkedUniform : mData.getUniforms())
1118 {
1119 if (linkedUniform.isSampler() && linkedUniform.isField())
1120 {
1121 infoLog << "Structures containing samplers not currently supported in D3D.";
1122 return LinkResult(false, gl::Error(GL_NO_ERROR));
1123 }
1124 }
1125
Jamie Madillf5f4ad22015-09-02 18:32:38 +00001126 const gl::Shader *vertexShader = mData.getAttachedVertexShader();
1127 const gl::Shader *fragmentShader = mData.getAttachedFragmentShader();
Brandon Joneseb994362014-09-24 10:27:28 -07001128
Jamie Madillf5f4ad22015-09-02 18:32:38 +00001129 const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(vertexShader);
1130 const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(fragmentShader);
1131
Jamie Madill63069df2015-09-01 17:26:41 +00001132 mSamplersVS.resize(data.caps->maxVertexTextureImageUnits);
Jamie Madillf5f4ad22015-09-02 18:32:38 +00001133 mSamplersPS.resize(data.caps->maxTextureImageUnits);
Brandon Jones22502d52014-08-29 16:58:36 -07001134
1135 mVertexHLSL = vertexShaderD3D->getTranslatedSource();
Arun Patole44efa0b2015-03-04 17:11:05 +05301136 vertexShaderD3D->generateWorkarounds(&mVertexWorkarounds);
Brandon Jones44151a92014-09-10 11:32:25 -07001137 mShaderVersion = vertexShaderD3D->getShaderVersion();
Brandon Jones22502d52014-08-29 16:58:36 -07001138
Jamie Madillf5f4ad22015-09-02 18:32:38 +00001139 mPixelHLSL = fragmentShaderD3D->getTranslatedSource();
1140 fragmentShaderD3D->generateWorkarounds(&mPixelWorkarounds);
1141
Austin Kinross02df7962015-07-01 10:03:42 -07001142 if (mRenderer->getRendererLimitations().noFrontFacingSupport)
1143 {
1144 if (fragmentShaderD3D->usesFrontFacing())
1145 {
1146 infoLog << "The current renderer doesn't support gl_FrontFacing";
1147 return LinkResult(false, gl::Error(GL_NO_ERROR));
1148 }
1149 }
1150
Jamie Madillca03b352015-09-02 12:38:13 -04001151 std::vector<PackedVarying> packedVaryings =
1152 MergeVaryings(*vertexShader, *fragmentShader, mData.getTransformFeedbackVaryingNames());
1153
Brandon Jones22502d52014-08-29 16:58:36 -07001154 // Map the varyings to the register file
Jamie Madillca03b352015-09-02 12:38:13 -04001155 int registers = mDynamicHLSL->packVaryings(infoLog, &packedVaryings,
Jamie Madill31c8c562015-08-19 14:08:03 -04001156 mData.getTransformFeedbackVaryingNames());
Brandon Jones22502d52014-08-29 16:58:36 -07001157
Jamie Madill31c8c562015-08-19 14:08:03 -04001158 if (registers < 0)
Brandon Jones22502d52014-08-29 16:58:36 -07001159 {
Geoff Lang7dd2e102014-11-10 15:19:26 -05001160 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Jones22502d52014-08-29 16:58:36 -07001161 }
1162
Jamie Madillccdf74b2015-08-18 10:46:12 -04001163 std::vector<gl::LinkedVarying> linkedVaryings;
Jamie Madill4cff2472015-08-21 16:53:18 -04001164 if (!mDynamicHLSL->generateShaderLinkHLSL(data, mData, infoLog, registers, mPixelHLSL,
Jamie Madillca03b352015-09-02 12:38:13 -04001165 mVertexHLSL, packedVaryings, &linkedVaryings,
1166 &mPixelShaderKey, &mUsesFragDepth))
Brandon Jones22502d52014-08-29 16:58:36 -07001167 {
Geoff Lang7dd2e102014-11-10 15:19:26 -05001168 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Jones22502d52014-08-29 16:58:36 -07001169 }
1170
Brandon Jones44151a92014-09-10 11:32:25 -07001171 mUsesPointSize = vertexShaderD3D->usesPointSize();
1172
Jamie Madill63805b42015-08-25 13:17:39 -04001173 initSemanticIndex();
Jamie Madill437d2662014-12-05 14:23:35 -05001174
Jamie Madill62d31cb2015-09-11 13:25:51 -04001175 assignUniformRegisters();
Jamie Madille473dee2015-08-18 14:49:01 -04001176
Jamie Madillccdf74b2015-08-18 10:46:12 -04001177 gatherTransformFeedbackVaryings(linkedVaryings);
1178
Jamie Madillca03b352015-09-02 12:38:13 -04001179 LinkResult result = compileProgramExecutables(infoLog, registers, packedVaryings);
Jamie Madill31c8c562015-08-19 14:08:03 -04001180 if (result.error.isError() || !result.linkSuccess)
1181 {
1182 infoLog << "Failed to create D3D shaders.";
1183 return result;
1184 }
1185
Geoff Lang7dd2e102014-11-10 15:19:26 -05001186 return LinkResult(true, gl::Error(GL_NO_ERROR));
Brandon Jones22502d52014-08-29 16:58:36 -07001187}
1188
Jamie Madill36cfd6a2015-08-18 10:46:20 -04001189GLboolean ProgramD3D::validate(const gl::Caps &caps, gl::InfoLog *infoLog)
1190{
1191 applyUniforms();
1192 return validateSamplers(infoLog, caps);
1193}
1194
Jamie Madill62d31cb2015-09-11 13:25:51 -04001195void ProgramD3D::gatherUniformBlockInfo(std::vector<gl::UniformBlock> *uniformBlocks,
1196 std::vector<gl::LinkedUniform> *uniforms)
1197{
1198 const gl::Shader *vertexShader = mData.getAttachedVertexShader();
1199
1200 BlockInfoMap blockInfo;
1201 std::map<std::string, size_t> blockDataSizes;
1202
1203 for (const sh::InterfaceBlock &vertexBlock : vertexShader->getInterfaceBlocks())
1204 {
1205 if (!vertexBlock.staticUse && vertexBlock.layout == sh::BLOCKLAYOUT_PACKED)
1206 continue;
1207
1208 if (blockDataSizes.count(vertexBlock.name) > 0)
1209 continue;
1210
1211 size_t dataSize = defineUniformBlock(vertexBlock, &blockInfo);
1212 blockDataSizes[vertexBlock.name] = dataSize;
1213 }
1214
1215 const gl::Shader *fragmentShader = mData.getAttachedFragmentShader();
1216
1217 for (const sh::InterfaceBlock &fragmentBlock : fragmentShader->getInterfaceBlocks())
1218 {
1219 if (!fragmentBlock.staticUse && fragmentBlock.layout == sh::BLOCKLAYOUT_PACKED)
1220 continue;
1221
1222 if (blockDataSizes.count(fragmentBlock.name) > 0)
1223 continue;
1224
1225 size_t dataSize = defineUniformBlock(fragmentBlock, &blockInfo);
1226 blockDataSizes[fragmentBlock.name] = dataSize;
1227 }
1228
1229 // Copy block info out to uniforms.
1230 for (gl::LinkedUniform &linkedUniform : *uniforms)
1231 {
1232 const auto &infoEntry = blockInfo.find(linkedUniform.name);
1233
1234 if (infoEntry != blockInfo.end())
1235 {
1236 linkedUniform.blockInfo = infoEntry->second;
1237 }
1238 }
1239
1240 // Assign registers and update sizes.
1241 const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(vertexShader);
1242 const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(fragmentShader);
1243
1244 for (gl::UniformBlock &uniformBlock : *uniformBlocks)
1245 {
1246 unsigned int uniformBlockElement = uniformBlock.isArray ? uniformBlock.arrayElement : 0;
1247
1248 if (uniformBlock.vertexStaticUse)
1249 {
1250 unsigned int baseRegister =
1251 vertexShaderD3D->getInterfaceBlockRegister(uniformBlock.name);
1252 uniformBlock.vsRegisterIndex = baseRegister + uniformBlockElement;
1253 }
1254
1255 if (uniformBlock.fragmentStaticUse)
1256 {
1257 unsigned int baseRegister =
1258 fragmentShaderD3D->getInterfaceBlockRegister(uniformBlock.name);
1259 uniformBlock.psRegisterIndex = baseRegister + uniformBlockElement;
1260 }
1261
1262 ASSERT(blockDataSizes.count(uniformBlock.name) == 1);
1263 uniformBlock.dataSize = static_cast<unsigned int>(blockDataSizes[uniformBlock.name]);
1264 }
1265}
1266
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001267void ProgramD3D::initializeUniformStorage()
Brandon Jonesc9610c52014-08-25 17:02:59 -07001268{
1269 // Compute total default block size
1270 unsigned int vertexRegisters = 0;
1271 unsigned int fragmentRegisters = 0;
Jamie Madill62d31cb2015-09-11 13:25:51 -04001272 for (const D3DUniform *d3dUniform : mD3DUniforms)
Brandon Jonesc9610c52014-08-25 17:02:59 -07001273 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001274 if (!d3dUniform->isSampler())
Brandon Jonesc9610c52014-08-25 17:02:59 -07001275 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001276 if (d3dUniform->isReferencedByVertexShader())
Brandon Jonesc9610c52014-08-25 17:02:59 -07001277 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001278 vertexRegisters = std::max(vertexRegisters,
1279 d3dUniform->vsRegisterIndex + d3dUniform->registerCount);
Brandon Jonesc9610c52014-08-25 17:02:59 -07001280 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04001281 if (d3dUniform->isReferencedByFragmentShader())
Brandon Jonesc9610c52014-08-25 17:02:59 -07001282 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001283 fragmentRegisters = std::max(
1284 fragmentRegisters, d3dUniform->psRegisterIndex + d3dUniform->registerCount);
Brandon Jonesc9610c52014-08-25 17:02:59 -07001285 }
1286 }
1287 }
1288
1289 mVertexUniformStorage = mRenderer->createUniformStorage(vertexRegisters * 16u);
1290 mFragmentUniformStorage = mRenderer->createUniformStorage(fragmentRegisters * 16u);
1291}
1292
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001293gl::Error ProgramD3D::applyUniforms()
Brandon Jones18bd4102014-09-22 14:21:44 -07001294{
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001295 updateSamplerMapping();
1296
Jamie Madill62d31cb2015-09-11 13:25:51 -04001297 gl::Error error = mRenderer->applyUniforms(*this, mD3DUniforms);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001298 if (error.isError())
1299 {
1300 return error;
1301 }
1302
Jamie Madill62d31cb2015-09-11 13:25:51 -04001303 for (D3DUniform *d3dUniform : mD3DUniforms)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001304 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001305 d3dUniform->dirty = false;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001306 }
1307
1308 return gl::Error(GL_NO_ERROR);
Brandon Jones18bd4102014-09-22 14:21:44 -07001309}
1310
Jamie Madilld1fe1642015-08-21 16:26:04 -04001311gl::Error ProgramD3D::applyUniformBuffers(const gl::Data &data)
Brandon Jones18bd4102014-09-22 14:21:44 -07001312{
Jamie Madill03260fa2015-06-22 13:57:22 -04001313 mVertexUBOCache.clear();
1314 mFragmentUBOCache.clear();
Brandon Jones18bd4102014-09-22 14:21:44 -07001315
1316 const unsigned int reservedBuffersInVS = mRenderer->getReservedVertexUniformBuffers();
1317 const unsigned int reservedBuffersInFS = mRenderer->getReservedFragmentUniformBuffers();
1318
Jamie Madill62d31cb2015-09-11 13:25:51 -04001319 const auto &uniformBlocks = mData.getUniformBlocks();
1320 for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < uniformBlocks.size();
1321 uniformBlockIndex++)
Brandon Jones18bd4102014-09-22 14:21:44 -07001322 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001323 const gl::UniformBlock &uniformBlock = uniformBlocks[uniformBlockIndex];
Jamie Madilld1fe1642015-08-21 16:26:04 -04001324 GLuint blockBinding = mData.getUniformBlockBinding(uniformBlockIndex);
Brandon Jones18bd4102014-09-22 14:21:44 -07001325
Brandon Jones18bd4102014-09-22 14:21:44 -07001326 // Unnecessary to apply an unreferenced standard or shared UBO
Jamie Madill62d31cb2015-09-11 13:25:51 -04001327 if (!uniformBlock.vertexStaticUse && !uniformBlock.fragmentStaticUse)
Brandon Jones18bd4102014-09-22 14:21:44 -07001328 {
1329 continue;
1330 }
1331
Jamie Madill62d31cb2015-09-11 13:25:51 -04001332 if (uniformBlock.vertexStaticUse)
Brandon Jones18bd4102014-09-22 14:21:44 -07001333 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001334 unsigned int registerIndex = uniformBlock.vsRegisterIndex - reservedBuffersInVS;
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00001335 ASSERT(registerIndex < data.caps->maxVertexUniformBlocks);
Jamie Madill03260fa2015-06-22 13:57:22 -04001336
Jamie Madill969194d2015-07-20 14:36:56 -04001337 if (mVertexUBOCache.size() <= registerIndex)
Jamie Madill03260fa2015-06-22 13:57:22 -04001338 {
1339 mVertexUBOCache.resize(registerIndex + 1, -1);
1340 }
1341
1342 ASSERT(mVertexUBOCache[registerIndex] == -1);
1343 mVertexUBOCache[registerIndex] = blockBinding;
Brandon Jones18bd4102014-09-22 14:21:44 -07001344 }
1345
Jamie Madill62d31cb2015-09-11 13:25:51 -04001346 if (uniformBlock.fragmentStaticUse)
Brandon Jones18bd4102014-09-22 14:21:44 -07001347 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001348 unsigned int registerIndex = uniformBlock.psRegisterIndex - reservedBuffersInFS;
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00001349 ASSERT(registerIndex < data.caps->maxFragmentUniformBlocks);
Jamie Madill03260fa2015-06-22 13:57:22 -04001350
1351 if (mFragmentUBOCache.size() <= registerIndex)
1352 {
1353 mFragmentUBOCache.resize(registerIndex + 1, -1);
1354 }
1355
1356 ASSERT(mFragmentUBOCache[registerIndex] == -1);
1357 mFragmentUBOCache[registerIndex] = blockBinding;
Brandon Jones18bd4102014-09-22 14:21:44 -07001358 }
1359 }
1360
Jamie Madill03260fa2015-06-22 13:57:22 -04001361 return mRenderer->setUniformBuffers(data, mVertexUBOCache, mFragmentUBOCache);
Brandon Jones18bd4102014-09-22 14:21:44 -07001362}
1363
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001364void ProgramD3D::dirtyAllUniforms()
Brandon Jones18bd4102014-09-22 14:21:44 -07001365{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001366 for (D3DUniform *d3dUniform : mD3DUniforms)
Brandon Jones18bd4102014-09-22 14:21:44 -07001367 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001368 d3dUniform->dirty = true;
Brandon Jones18bd4102014-09-22 14:21:44 -07001369 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001370}
1371
1372void ProgramD3D::setUniform1fv(GLint location, GLsizei count, const GLfloat* v)
1373{
1374 setUniform(location, count, v, GL_FLOAT);
1375}
1376
1377void ProgramD3D::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
1378{
1379 setUniform(location, count, v, GL_FLOAT_VEC2);
1380}
1381
1382void ProgramD3D::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
1383{
1384 setUniform(location, count, v, GL_FLOAT_VEC3);
1385}
1386
1387void ProgramD3D::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
1388{
1389 setUniform(location, count, v, GL_FLOAT_VEC4);
1390}
1391
1392void ProgramD3D::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1393{
1394 setUniformMatrixfv<2, 2>(location, count, transpose, value, GL_FLOAT_MAT2);
1395}
1396
1397void ProgramD3D::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1398{
1399 setUniformMatrixfv<3, 3>(location, count, transpose, value, GL_FLOAT_MAT3);
1400}
1401
1402void ProgramD3D::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1403{
1404 setUniformMatrixfv<4, 4>(location, count, transpose, value, GL_FLOAT_MAT4);
1405}
1406
1407void ProgramD3D::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1408{
1409 setUniformMatrixfv<2, 3>(location, count, transpose, value, GL_FLOAT_MAT2x3);
1410}
1411
1412void ProgramD3D::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1413{
1414 setUniformMatrixfv<3, 2>(location, count, transpose, value, GL_FLOAT_MAT3x2);
1415}
1416
1417void ProgramD3D::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1418{
1419 setUniformMatrixfv<2, 4>(location, count, transpose, value, GL_FLOAT_MAT2x4);
1420}
1421
1422void ProgramD3D::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1423{
1424 setUniformMatrixfv<4, 2>(location, count, transpose, value, GL_FLOAT_MAT4x2);
1425}
1426
1427void ProgramD3D::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1428{
1429 setUniformMatrixfv<3, 4>(location, count, transpose, value, GL_FLOAT_MAT3x4);
1430}
1431
1432void ProgramD3D::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1433{
1434 setUniformMatrixfv<4, 3>(location, count, transpose, value, GL_FLOAT_MAT4x3);
1435}
1436
1437void ProgramD3D::setUniform1iv(GLint location, GLsizei count, const GLint *v)
1438{
1439 setUniform(location, count, v, GL_INT);
1440}
1441
1442void ProgramD3D::setUniform2iv(GLint location, GLsizei count, const GLint *v)
1443{
1444 setUniform(location, count, v, GL_INT_VEC2);
1445}
1446
1447void ProgramD3D::setUniform3iv(GLint location, GLsizei count, const GLint *v)
1448{
1449 setUniform(location, count, v, GL_INT_VEC3);
1450}
1451
1452void ProgramD3D::setUniform4iv(GLint location, GLsizei count, const GLint *v)
1453{
1454 setUniform(location, count, v, GL_INT_VEC4);
1455}
1456
1457void ProgramD3D::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
1458{
1459 setUniform(location, count, v, GL_UNSIGNED_INT);
1460}
1461
1462void ProgramD3D::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
1463{
1464 setUniform(location, count, v, GL_UNSIGNED_INT_VEC2);
1465}
1466
1467void ProgramD3D::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
1468{
1469 setUniform(location, count, v, GL_UNSIGNED_INT_VEC3);
1470}
1471
1472void ProgramD3D::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
1473{
1474 setUniform(location, count, v, GL_UNSIGNED_INT_VEC4);
1475}
1476
Jamie Madill62d31cb2015-09-11 13:25:51 -04001477void ProgramD3D::assignUniformRegisters()
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001478{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001479 const gl::Shader *vertexShader = mData.getAttachedVertexShader();
1480 const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(vertexShader);
Jamie Madilla2eb02c2015-09-11 12:31:41 +00001481
Jamie Madill62d31cb2015-09-11 13:25:51 -04001482 for (const sh::Uniform &vertexUniform : vertexShader->getUniforms())
Jamie Madillfb536032015-09-11 13:19:49 -04001483
Jamie Madilla2eb02c2015-09-11 12:31:41 +00001484 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001485 if (vertexUniform.staticUse)
Jamie Madillfb536032015-09-11 13:19:49 -04001486 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001487 assignUniformRegistersBase(vertexShaderD3D, vertexUniform);
Jamie Madillfb536032015-09-11 13:19:49 -04001488 }
1489 }
1490
Jamie Madill62d31cb2015-09-11 13:25:51 -04001491 const gl::Shader *fragmentShader = mData.getAttachedFragmentShader();
1492 const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(fragmentShader);
Jamie Madillfb536032015-09-11 13:19:49 -04001493
Jamie Madill62d31cb2015-09-11 13:25:51 -04001494 for (const sh::Uniform &fragmentUniform : fragmentShader->getUniforms())
Jamie Madillfb536032015-09-11 13:19:49 -04001495 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001496 if (fragmentUniform.staticUse)
Jamie Madillfb536032015-09-11 13:19:49 -04001497 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001498 assignUniformRegistersBase(fragmentShaderD3D, fragmentUniform);
Jamie Madillfb536032015-09-11 13:19:49 -04001499 }
1500 }
1501
Jamie Madill62d31cb2015-09-11 13:25:51 -04001502 assignAllSamplerRegisters();
Jamie Madillfb536032015-09-11 13:19:49 -04001503 initializeUniformStorage();
Jamie Madillfb536032015-09-11 13:19:49 -04001504}
1505
Jamie Madill62d31cb2015-09-11 13:25:51 -04001506void ProgramD3D::assignUniformRegistersBase(const ShaderD3D *shader, const sh::Uniform &uniform)
Jamie Madillfb536032015-09-11 13:19:49 -04001507{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001508 if (uniform.isBuiltIn())
Jamie Madillfb536032015-09-11 13:19:49 -04001509 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001510 assignUniformRegisters(shader, uniform, uniform.name, nullptr);
Jamie Madill55def582015-05-04 11:24:57 -04001511 return;
1512 }
1513
Jamie Madill62d31cb2015-09-11 13:25:51 -04001514 unsigned int startRegister = shader->getUniformRegister(uniform.name);
Geoff Lang492a7e42014-11-05 13:27:06 -05001515 ShShaderOutput outputType = shader->getCompilerOutputType();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001516 sh::HLSLBlockEncoder encoder(sh::HLSLBlockEncoder::GetStrategyFor(outputType));
Jamie Madill62d31cb2015-09-11 13:25:51 -04001517 encoder.skipRegisters(startRegister);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001518
Jamie Madill62d31cb2015-09-11 13:25:51 -04001519 assignUniformRegisters(shader, uniform, uniform.name, &encoder);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001520}
1521
Jamie Madill62d31cb2015-09-11 13:25:51 -04001522D3DUniform *ProgramD3D::getD3DUniformByName(const std::string &name)
1523{
1524 for (D3DUniform *d3dUniform : mD3DUniforms)
1525 {
1526 if (d3dUniform->name == name)
1527 {
1528 return d3dUniform;
1529 }
1530 }
1531
1532 return nullptr;
1533}
1534
1535void ProgramD3D::assignUniformRegisters(const ShaderD3D *shader,
1536 const sh::ShaderVariable &uniform,
1537 const std::string &fullName,
1538 sh::HLSLBlockEncoder *encoder)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001539{
1540 if (uniform.isStruct())
1541 {
1542 for (unsigned int elementIndex = 0; elementIndex < uniform.elementCount(); elementIndex++)
1543 {
1544 const std::string &elementString = (uniform.isArray() ? ArrayString(elementIndex) : "");
1545
Jamie Madill55def582015-05-04 11:24:57 -04001546 if (encoder)
1547 encoder->enterAggregateType();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001548
1549 for (size_t fieldIndex = 0; fieldIndex < uniform.fields.size(); fieldIndex++)
1550 {
1551 const sh::ShaderVariable &field = uniform.fields[fieldIndex];
1552 const std::string &fieldFullName = (fullName + elementString + "." + field.name);
1553
Jamie Madill62d31cb2015-09-11 13:25:51 -04001554 assignUniformRegisters(shader, field, fieldFullName, encoder);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001555 }
1556
Jamie Madill55def582015-05-04 11:24:57 -04001557 if (encoder)
1558 encoder->exitAggregateType();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001559 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04001560 return;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001561 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04001562
1563 // Not a struct. Arrays are treated as aggregate types.
1564 if (uniform.isArray() && encoder)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001565 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001566 encoder->enterAggregateType();
1567 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001568
Jamie Madill62d31cb2015-09-11 13:25:51 -04001569 // Advance the uniform offset, to track registers allocation for structs
1570 sh::BlockMemberInfo blockInfo =
1571 encoder ? encoder->encodeType(uniform.type, uniform.arraySize, false)
1572 : sh::BlockMemberInfo::getDefaultBlockInfo();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001573
Jamie Madill62d31cb2015-09-11 13:25:51 -04001574 D3DUniform *d3dUniform = getD3DUniformByName(fullName);
Jamie Madill2857f482015-02-09 15:35:29 -05001575
Jamie Madill62d31cb2015-09-11 13:25:51 -04001576 if (!d3dUniform)
1577 {
1578 // We're building the list twice, make sure we use the same indexing. Special case
1579 // built-ins.
1580 ASSERT(fullName.compare(0, 3, "gl_") == 0 ||
1581 mData.getUniformIndex(fullName) == static_cast<GLint>(mD3DUniforms.size()));
Jamie Madill55def582015-05-04 11:24:57 -04001582
Jamie Madill62d31cb2015-09-11 13:25:51 -04001583 d3dUniform = new D3DUniform(uniform.type, fullName, uniform.arraySize, true);
1584 mD3DUniforms.push_back(d3dUniform);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001585
Jamie Madill55def582015-05-04 11:24:57 -04001586 if (encoder)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001587 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001588 d3dUniform->registerElement =
1589 static_cast<unsigned int>(sh::HLSLBlockEncoder::getBlockRegisterElement(blockInfo));
Jamie Madillfb536032015-09-11 13:19:49 -04001590 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04001591 }
1592
1593 if (encoder)
1594 {
1595 unsigned int reg =
1596 static_cast<unsigned int>(sh::HLSLBlockEncoder::getBlockRegister(blockInfo));
1597 if (shader->getShaderType() == GL_FRAGMENT_SHADER)
1598 {
1599 d3dUniform->psRegisterIndex = reg;
1600 }
1601 else if (shader->getShaderType() == GL_VERTEX_SHADER)
1602 {
1603 d3dUniform->vsRegisterIndex = reg;
1604 }
1605 else
1606 UNREACHABLE();
Jamie Madillfb536032015-09-11 13:19:49 -04001607
1608 // Arrays are treated as aggregate types
Jamie Madill62d31cb2015-09-11 13:25:51 -04001609 if (uniform.isArray())
Jamie Madillfb536032015-09-11 13:19:49 -04001610 {
1611 encoder->exitAggregateType();
1612 }
1613 }
1614}
1615
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001616template <typename T>
1617static inline void SetIfDirty(T *dest, const T& source, bool *dirtyFlag)
1618{
1619 ASSERT(dest != NULL);
1620 ASSERT(dirtyFlag != NULL);
1621
1622 *dirtyFlag = *dirtyFlag || (memcmp(dest, &source, sizeof(T)) != 0);
1623 *dest = source;
1624}
1625
1626template <typename T>
Jamie Madill62d31cb2015-09-11 13:25:51 -04001627void ProgramD3D::setUniform(GLint location, GLsizei countIn, const T *v, GLenum targetUniformType)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001628{
1629 const int components = gl::VariableComponentCount(targetUniformType);
1630 const GLenum targetBoolType = gl::VariableBoolVectorType(targetUniformType);
1631
Jamie Madill62d31cb2015-09-11 13:25:51 -04001632 D3DUniform *targetUniform = getD3DUniformFromLocation(location);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001633
Jamie Madill62d31cb2015-09-11 13:25:51 -04001634 unsigned int elementCount = targetUniform->elementCount();
1635 unsigned int arrayElement = mData.getUniformLocations()[location].element;
1636 unsigned int count = std::min(elementCount - arrayElement, static_cast<unsigned int>(countIn));
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001637
1638 if (targetUniform->type == targetUniformType)
1639 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001640 T *target = reinterpret_cast<T *>(targetUniform->data) + arrayElement * 4;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001641
Jamie Madill62d31cb2015-09-11 13:25:51 -04001642 for (unsigned int i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001643 {
1644 T *dest = target + (i * 4);
1645 const T *source = v + (i * components);
1646
1647 for (int c = 0; c < components; c++)
1648 {
1649 SetIfDirty(dest + c, source[c], &targetUniform->dirty);
1650 }
1651 for (int c = components; c < 4; c++)
1652 {
1653 SetIfDirty(dest + c, T(0), &targetUniform->dirty);
1654 }
1655 }
1656 }
1657 else if (targetUniform->type == targetBoolType)
1658 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001659 GLint *boolParams = reinterpret_cast<GLint *>(targetUniform->data) + arrayElement * 4;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001660
Jamie Madill62d31cb2015-09-11 13:25:51 -04001661 for (unsigned int i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001662 {
1663 GLint *dest = boolParams + (i * 4);
1664 const T *source = v + (i * components);
1665
1666 for (int c = 0; c < components; c++)
1667 {
1668 SetIfDirty(dest + c, (source[c] == static_cast<T>(0)) ? GL_FALSE : GL_TRUE, &targetUniform->dirty);
1669 }
1670 for (int c = components; c < 4; c++)
1671 {
1672 SetIfDirty(dest + c, GL_FALSE, &targetUniform->dirty);
1673 }
1674 }
1675 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04001676 else if (targetUniform->isSampler())
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001677 {
1678 ASSERT(targetUniformType == GL_INT);
1679
Jamie Madill62d31cb2015-09-11 13:25:51 -04001680 GLint *target = reinterpret_cast<GLint *>(targetUniform->data) + arrayElement * 4;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001681
1682 bool wasDirty = targetUniform->dirty;
1683
Jamie Madill62d31cb2015-09-11 13:25:51 -04001684 for (unsigned int i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001685 {
1686 GLint *dest = target + (i * 4);
1687 const GLint *source = reinterpret_cast<const GLint*>(v) + (i * components);
1688
1689 SetIfDirty(dest + 0, source[0], &targetUniform->dirty);
1690 SetIfDirty(dest + 1, 0, &targetUniform->dirty);
1691 SetIfDirty(dest + 2, 0, &targetUniform->dirty);
1692 SetIfDirty(dest + 3, 0, &targetUniform->dirty);
1693 }
1694
1695 if (!wasDirty && targetUniform->dirty)
1696 {
1697 mDirtySamplerMapping = true;
1698 }
Brandon Jones18bd4102014-09-22 14:21:44 -07001699 }
1700 else UNREACHABLE();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001701}
Brandon Jones18bd4102014-09-22 14:21:44 -07001702
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001703template<typename T>
1704bool transposeMatrix(T *target, const GLfloat *value, int targetWidth, int targetHeight, int srcWidth, int srcHeight)
1705{
1706 bool dirty = false;
1707 int copyWidth = std::min(targetHeight, srcWidth);
1708 int copyHeight = std::min(targetWidth, srcHeight);
1709
1710 for (int x = 0; x < copyWidth; x++)
1711 {
1712 for (int y = 0; y < copyHeight; y++)
1713 {
1714 SetIfDirty(target + (x * targetWidth + y), static_cast<T>(value[y * srcWidth + x]), &dirty);
1715 }
1716 }
1717 // clear unfilled right side
1718 for (int y = 0; y < copyWidth; y++)
1719 {
1720 for (int x = copyHeight; x < targetWidth; x++)
1721 {
1722 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
1723 }
1724 }
1725 // clear unfilled bottom.
1726 for (int y = copyWidth; y < targetHeight; y++)
1727 {
1728 for (int x = 0; x < targetWidth; x++)
1729 {
1730 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
1731 }
1732 }
1733
1734 return dirty;
1735}
1736
1737template<typename T>
1738bool expandMatrix(T *target, const GLfloat *value, int targetWidth, int targetHeight, int srcWidth, int srcHeight)
1739{
1740 bool dirty = false;
1741 int copyWidth = std::min(targetWidth, srcWidth);
1742 int copyHeight = std::min(targetHeight, srcHeight);
1743
1744 for (int y = 0; y < copyHeight; y++)
1745 {
1746 for (int x = 0; x < copyWidth; x++)
1747 {
1748 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(value[y * srcWidth + x]), &dirty);
1749 }
1750 }
1751 // clear unfilled right side
1752 for (int y = 0; y < copyHeight; y++)
1753 {
1754 for (int x = copyWidth; x < targetWidth; x++)
1755 {
1756 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
1757 }
1758 }
1759 // clear unfilled bottom.
1760 for (int y = copyHeight; y < targetHeight; y++)
1761 {
1762 for (int x = 0; x < targetWidth; x++)
1763 {
1764 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
1765 }
1766 }
1767
1768 return dirty;
1769}
1770
1771template <int cols, int rows>
Jamie Madill62d31cb2015-09-11 13:25:51 -04001772void ProgramD3D::setUniformMatrixfv(GLint location,
1773 GLsizei countIn,
1774 GLboolean transpose,
1775 const GLfloat *value,
1776 GLenum targetUniformType)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001777{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001778 D3DUniform *targetUniform = getD3DUniformFromLocation(location);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001779
Jamie Madill62d31cb2015-09-11 13:25:51 -04001780 unsigned int elementCount = targetUniform->elementCount();
1781 unsigned int arrayElement = mData.getUniformLocations()[location].element;
1782 unsigned int count = std::min(elementCount - arrayElement, static_cast<unsigned int>(countIn));
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001783
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001784 const unsigned int targetMatrixStride = (4 * rows);
Jamie Madill62d31cb2015-09-11 13:25:51 -04001785 GLfloat *target =
1786 (GLfloat *)(targetUniform->data + arrayElement * sizeof(GLfloat) * targetMatrixStride);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001787
Jamie Madill62d31cb2015-09-11 13:25:51 -04001788 for (unsigned int i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001789 {
1790 // Internally store matrices as transposed versions to accomodate HLSL matrix indexing
1791 if (transpose == GL_FALSE)
1792 {
1793 targetUniform->dirty = transposeMatrix<GLfloat>(target, value, 4, rows, rows, cols) || targetUniform->dirty;
1794 }
1795 else
1796 {
1797 targetUniform->dirty = expandMatrix<GLfloat>(target, value, 4, rows, cols, rows) || targetUniform->dirty;
1798 }
1799 target += targetMatrixStride;
1800 value += cols * rows;
1801 }
1802}
1803
Jamie Madill62d31cb2015-09-11 13:25:51 -04001804size_t ProgramD3D::defineUniformBlock(const sh::InterfaceBlock &interfaceBlock,
1805 BlockInfoMap *blockInfoOut)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001806{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001807 ASSERT(interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001808
Jamie Madill62d31cb2015-09-11 13:25:51 -04001809 // define member uniforms
1810 sh::Std140BlockEncoder std140Encoder;
1811 sh::HLSLBlockEncoder hlslEncoder(sh::HLSLBlockEncoder::ENCODE_PACKED);
1812 sh::BlockLayoutEncoder *encoder = nullptr;
1813
1814 if (interfaceBlock.layout == sh::BLOCKLAYOUT_STANDARD)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001815 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001816 encoder = &std140Encoder;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001817 }
1818 else
1819 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001820 encoder = &hlslEncoder;
Jamie Madill61b8dd92015-09-09 19:04:04 +00001821 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04001822
1823 GetUniformBlockInfo(interfaceBlock.fields, "", encoder, interfaceBlock.isRowMajorLayout,
1824 blockInfoOut);
1825
1826 return encoder->getBlockSize();
Jamie Madill61b8dd92015-09-09 19:04:04 +00001827}
1828
Jamie Madill62d31cb2015-09-11 13:25:51 -04001829void ProgramD3D::assignAllSamplerRegisters()
Jamie Madilla2eb02c2015-09-11 12:31:41 +00001830{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001831 for (const D3DUniform *d3dUniform : mD3DUniforms)
Jamie Madilla2eb02c2015-09-11 12:31:41 +00001832 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001833 if (d3dUniform->isSampler())
Jamie Madillfb536032015-09-11 13:19:49 -04001834 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001835 assignSamplerRegisters(d3dUniform);
Jamie Madillfb536032015-09-11 13:19:49 -04001836 }
Jamie Madilla2eb02c2015-09-11 12:31:41 +00001837 }
1838}
1839
Jamie Madill62d31cb2015-09-11 13:25:51 -04001840void ProgramD3D::assignSamplerRegisters(const D3DUniform *d3dUniform)
Jamie Madillfb536032015-09-11 13:19:49 -04001841{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001842 ASSERT(d3dUniform->isSampler());
1843 ASSERT(d3dUniform->vsRegisterIndex != GL_INVALID_INDEX ||
1844 d3dUniform->psRegisterIndex != GL_INVALID_INDEX);
Jamie Madillfb536032015-09-11 13:19:49 -04001845
Jamie Madill62d31cb2015-09-11 13:25:51 -04001846 if (d3dUniform->vsRegisterIndex != GL_INVALID_INDEX)
Jamie Madillfb536032015-09-11 13:19:49 -04001847 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001848 AssignSamplers(d3dUniform->vsRegisterIndex, d3dUniform->type, d3dUniform->arraySize,
1849 mSamplersVS, &mUsedVertexSamplerRange);
Jamie Madillfb536032015-09-11 13:19:49 -04001850 }
1851
Jamie Madill62d31cb2015-09-11 13:25:51 -04001852 if (d3dUniform->psRegisterIndex != GL_INVALID_INDEX)
Jamie Madillfb536032015-09-11 13:19:49 -04001853 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001854 AssignSamplers(d3dUniform->psRegisterIndex, d3dUniform->type, d3dUniform->arraySize,
1855 mSamplersPS, &mUsedPixelSamplerRange);
Jamie Madillfb536032015-09-11 13:19:49 -04001856 }
1857}
1858
Jamie Madill62d31cb2015-09-11 13:25:51 -04001859// static
1860void ProgramD3D::AssignSamplers(unsigned int startSamplerIndex,
Jamie Madilld3dfda22015-07-06 08:28:49 -04001861 GLenum samplerType,
1862 unsigned int samplerCount,
1863 std::vector<Sampler> &outSamplers,
1864 GLuint *outUsedRange)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001865{
1866 unsigned int samplerIndex = startSamplerIndex;
1867
1868 do
1869 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001870 ASSERT(samplerIndex < outSamplers.size());
1871 Sampler *sampler = &outSamplers[samplerIndex];
1872 sampler->active = true;
1873 sampler->textureType = GetTextureType(samplerType);
1874 sampler->logicalTextureUnit = 0;
1875 *outUsedRange = std::max(samplerIndex + 1, *outUsedRange);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001876 samplerIndex++;
1877 } while (samplerIndex < startSamplerIndex + samplerCount);
Brandon Jones18bd4102014-09-22 14:21:44 -07001878}
1879
Brandon Jonesc9610c52014-08-25 17:02:59 -07001880void ProgramD3D::reset()
1881{
Brandon Joneseb994362014-09-24 10:27:28 -07001882 SafeDeleteContainer(mVertexExecutables);
1883 SafeDeleteContainer(mPixelExecutables);
1884 SafeDelete(mGeometryExecutable);
1885
Brandon Jones22502d52014-08-29 16:58:36 -07001886 mVertexHLSL.clear();
Geoff Lang6941a552015-07-27 11:06:45 -04001887 mVertexWorkarounds = D3DCompilerWorkarounds();
Brandon Jones44151a92014-09-10 11:32:25 -07001888 mShaderVersion = 100;
Brandon Jones22502d52014-08-29 16:58:36 -07001889
1890 mPixelHLSL.clear();
Geoff Lang6941a552015-07-27 11:06:45 -04001891 mPixelWorkarounds = D3DCompilerWorkarounds();
Brandon Jones22502d52014-08-29 16:58:36 -07001892 mUsesFragDepth = false;
1893 mPixelShaderKey.clear();
Brandon Jones44151a92014-09-10 11:32:25 -07001894 mUsesPointSize = false;
Brandon Jones22502d52014-08-29 16:58:36 -07001895
Jamie Madill62d31cb2015-09-11 13:25:51 -04001896 SafeDeleteContainer(mD3DUniforms);
1897
Brandon Jonesc9610c52014-08-25 17:02:59 -07001898 SafeDelete(mVertexUniformStorage);
1899 SafeDelete(mFragmentUniformStorage);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001900
1901 mSamplersPS.clear();
1902 mSamplersVS.clear();
1903
1904 mUsedVertexSamplerRange = 0;
1905 mUsedPixelSamplerRange = 0;
1906 mDirtySamplerMapping = true;
Jamie Madill437d2662014-12-05 14:23:35 -05001907
Jamie Madill63805b42015-08-25 13:17:39 -04001908 std::fill(mSemanticIndexes, mSemanticIndexes + ArraySize(mSemanticIndexes), -1);
Jamie Madill437d2662014-12-05 14:23:35 -05001909 std::fill(mAttributesByLayout, mAttributesByLayout + ArraySize(mAttributesByLayout), -1);
Jamie Madillccdf74b2015-08-18 10:46:12 -04001910
1911 mTransformFeedbackLinkedVaryings.clear();
Brandon Jonesc9610c52014-08-25 17:02:59 -07001912}
1913
Geoff Lang7dd2e102014-11-10 15:19:26 -05001914unsigned int ProgramD3D::getSerial() const
1915{
1916 return mSerial;
1917}
1918
1919unsigned int ProgramD3D::issueSerial()
1920{
1921 return mCurrentSerial++;
1922}
1923
Jamie Madill63805b42015-08-25 13:17:39 -04001924void ProgramD3D::initSemanticIndex()
1925{
1926 const gl::Shader *vertexShader = mData.getAttachedVertexShader();
1927 ASSERT(vertexShader != nullptr);
1928
1929 // Init semantic index
1930 for (const sh::Attribute &attribute : mData.getAttributes())
1931 {
1932 int attributeIndex = attribute.location;
1933 int index = vertexShader->getSemanticIndex(attribute.name);
1934 int regs = gl::VariableRegisterCount(attribute.type);
1935
1936 for (int reg = 0; reg < regs; ++reg)
1937 {
1938 mSemanticIndexes[attributeIndex + reg] = index + reg;
1939 }
1940 }
1941
1942 initAttributesByLayout();
1943}
1944
Jamie Madill437d2662014-12-05 14:23:35 -05001945void ProgramD3D::initAttributesByLayout()
1946{
1947 for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
1948 {
1949 mAttributesByLayout[i] = i;
1950 }
1951
Jamie Madill63805b42015-08-25 13:17:39 -04001952 std::sort(&mAttributesByLayout[0], &mAttributesByLayout[gl::MAX_VERTEX_ATTRIBS],
1953 AttributeSorter(mSemanticIndexes));
Jamie Madill437d2662014-12-05 14:23:35 -05001954}
1955
Jamie Madill476682e2015-06-30 10:04:29 -04001956void ProgramD3D::sortAttributesByLayout(const std::vector<TranslatedAttribute> &unsortedAttributes,
Jamie Madillf9327d32015-06-22 13:57:16 -04001957 int sortedSemanticIndicesOut[gl::MAX_VERTEX_ATTRIBS],
1958 const rx::TranslatedAttribute *sortedAttributesOut[gl::MAX_VERTEX_ATTRIBS]) const
Jamie Madill437d2662014-12-05 14:23:35 -05001959{
Jamie Madill476682e2015-06-30 10:04:29 -04001960 for (size_t attribIndex = 0; attribIndex < unsortedAttributes.size(); ++attribIndex)
Jamie Madill437d2662014-12-05 14:23:35 -05001961 {
Jamie Madill476682e2015-06-30 10:04:29 -04001962 int oldIndex = mAttributesByLayout[attribIndex];
Jamie Madill63805b42015-08-25 13:17:39 -04001963 sortedSemanticIndicesOut[attribIndex] = mSemanticIndexes[oldIndex];
Jamie Madill476682e2015-06-30 10:04:29 -04001964 sortedAttributesOut[attribIndex] = &unsortedAttributes[oldIndex];
Jamie Madill437d2662014-12-05 14:23:35 -05001965 }
1966}
1967
Jamie Madill63805b42015-08-25 13:17:39 -04001968void ProgramD3D::updateCachedInputLayout(const gl::State &state)
Jamie Madilld3dfda22015-07-06 08:28:49 -04001969{
Jamie Madillbd136f92015-08-10 14:51:37 -04001970 mCachedInputLayout.clear();
Jamie Madilld3dfda22015-07-06 08:28:49 -04001971 const auto &vertexAttributes = state.getVertexArray()->getVertexAttributes();
Jamie Madillf8dd7b12015-08-05 13:50:08 -04001972
Jamie Madilld3dfda22015-07-06 08:28:49 -04001973 for (unsigned int attributeIndex = 0; attributeIndex < vertexAttributes.size(); attributeIndex++)
1974 {
Jamie Madill63805b42015-08-25 13:17:39 -04001975 int semanticIndex = mSemanticIndexes[attributeIndex];
Jamie Madilld3dfda22015-07-06 08:28:49 -04001976
1977 if (semanticIndex != -1)
1978 {
Jamie Madillbd136f92015-08-10 14:51:37 -04001979 if (mCachedInputLayout.size() < static_cast<size_t>(semanticIndex + 1))
1980 {
1981 mCachedInputLayout.resize(semanticIndex + 1, gl::VERTEX_FORMAT_INVALID);
1982 }
Jamie Madilld3dfda22015-07-06 08:28:49 -04001983 mCachedInputLayout[semanticIndex] =
1984 GetVertexFormatType(vertexAttributes[attributeIndex],
1985 state.getVertexAttribCurrentValue(attributeIndex).Type);
1986 }
1987 }
1988}
1989
Jamie Madillccdf74b2015-08-18 10:46:12 -04001990void ProgramD3D::gatherTransformFeedbackVaryings(
1991 const std::vector<gl::LinkedVarying> &linkedVaryings)
1992{
1993 // Gather the linked varyings that are used for transform feedback, they should all exist.
1994 mTransformFeedbackLinkedVaryings.clear();
1995 for (const std::string &tfVaryingName : mData.getTransformFeedbackVaryingNames())
1996 {
1997 for (const gl::LinkedVarying &linkedVarying : linkedVaryings)
1998 {
1999 if (tfVaryingName == linkedVarying.name)
2000 {
2001 mTransformFeedbackLinkedVaryings.push_back(linkedVarying);
2002 break;
2003 }
2004 }
2005 }
2006}
Jamie Madill62d31cb2015-09-11 13:25:51 -04002007
2008D3DUniform *ProgramD3D::getD3DUniformFromLocation(GLint location)
2009{
2010 return mD3DUniforms[mData.getUniformLocations()[location].index];
2011}
Brandon Jonesc9610c52014-08-25 17:02:59 -07002012}