blob: 58e08f70b1bb9ce9a6fb99b71388f213f4e7663f [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 Madill54f882c2015-09-02 14:33:48 -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 Madill54f882c2015-09-02 14:33:48 -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),
221 psRegisterIndex(GL_INVALID_INDEX),
222 vsRegisterIndex(GL_INVALID_INDEX),
223 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 unsigned char[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 Madill54f882c2015-09-02 14:33:48 -0400443 for (const D3DUniform *d3dUniform : mD3DUniforms)
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700444 {
Jamie Madill54f882c2015-09-02 14:33:48 -0400445 if (!d3dUniform->dirty)
446 continue;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700447
Jamie Madill54f882c2015-09-02 14:33:48 -0400448 if (!d3dUniform->isSampler())
449 continue;
450
451 int count = d3dUniform->elementCount();
452 GLint(*v)[4] = reinterpret_cast<GLint(*)[4]>(d3dUniform->data);
453
454 if (d3dUniform->isReferencedByFragmentShader())
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700455 {
Jamie Madill54f882c2015-09-02 14:33:48 -0400456 unsigned int firstIndex = d3dUniform->psRegisterIndex;
457
458 for (int i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700459 {
Jamie Madill54f882c2015-09-02 14:33:48 -0400460 unsigned int samplerIndex = firstIndex + i;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700461
Jamie Madill54f882c2015-09-02 14:33:48 -0400462 if (samplerIndex < mSamplersPS.size())
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700463 {
Jamie Madill54f882c2015-09-02 14:33:48 -0400464 ASSERT(mSamplersPS[samplerIndex].active);
465 mSamplersPS[samplerIndex].logicalTextureUnit = v[i][0];
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700466 }
Jamie Madill54f882c2015-09-02 14:33:48 -0400467 }
468 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700469
Jamie Madill54f882c2015-09-02 14:33:48 -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 Madill54f882c2015-09-02 14:33:48 -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 Madill54f882c2015-09-02 14:33:48 -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 Madill54f882c2015-09-02 14:33:48 -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 Madill54f882c2015-09-02 14:33:48 -0400650 const gl::LinkedUniform &linkedUniform = linkedUniforms[uniformIndex];
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700651
Jamie Madill54f882c2015-09-02 14:33:48 -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 Madill54f882c2015-09-02 14:33:48 -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 Madill54f882c2015-09-02 14:33:48 -0400834 stream->writeInt(mD3DUniforms.size());
835 for (size_t uniformIndex = 0; uniformIndex < mD3DUniforms.size(); ++uniformIndex)
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700836 {
Jamie Madill54f882c2015-09-02 14:33:48 -0400837 const D3DUniform &uniform = *mD3DUniforms[uniformIndex];
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700838
Jamie Madill54f882c2015-09-02 14:33:48 -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 Madill54f882c2015-09-02 14:33:48 -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 Madill54f882c2015-09-02 14:33:48 -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 Madill54f882c2015-09-02 14:33:48 -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 Madill54f882c2015-09-02 14:33:48 -04001272 for (const D3DUniform *d3dUniform : mD3DUniforms)
Brandon Jonesc9610c52014-08-25 17:02:59 -07001273 {
Jamie Madill54f882c2015-09-02 14:33:48 -04001274 if (!d3dUniform->isSampler())
Brandon Jonesc9610c52014-08-25 17:02:59 -07001275 {
Jamie Madill54f882c2015-09-02 14:33:48 -04001276 if (d3dUniform->isReferencedByVertexShader())
Brandon Jonesc9610c52014-08-25 17:02:59 -07001277 {
Jamie Madill54f882c2015-09-02 14:33:48 -04001278 vertexRegisters = std::max(vertexRegisters,
1279 d3dUniform->vsRegisterIndex + d3dUniform->registerCount);
Brandon Jonesc9610c52014-08-25 17:02:59 -07001280 }
Jamie Madill54f882c2015-09-02 14:33:48 -04001281 if (d3dUniform->isReferencedByFragmentShader())
Brandon Jonesc9610c52014-08-25 17:02:59 -07001282 {
Jamie Madill54f882c2015-09-02 14:33:48 -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 Madill54f882c2015-09-02 14:33:48 -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 Madill54f882c2015-09-02 14:33:48 -04001303 for (D3DUniform *d3dUniform : mD3DUniforms)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001304 {
Jamie Madill54f882c2015-09-02 14:33:48 -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 Madill54f882c2015-09-02 14:33:48 -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 Madill54f882c2015-09-02 14:33:48 -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 Madill54f882c2015-09-02 14:33:48 -04001327 if (!uniformBlock.vertexStaticUse && !uniformBlock.fragmentStaticUse)
Brandon Jones18bd4102014-09-22 14:21:44 -07001328 {
1329 continue;
1330 }
1331
Jamie Madill54f882c2015-09-02 14:33:48 -04001332 if (uniformBlock.vertexStaticUse)
Brandon Jones18bd4102014-09-22 14:21:44 -07001333 {
Jamie Madill54f882c2015-09-02 14:33:48 -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 Madill54f882c2015-09-02 14:33:48 -04001346 if (uniformBlock.fragmentStaticUse)
Brandon Jones18bd4102014-09-22 14:21:44 -07001347 {
Jamie Madill54f882c2015-09-02 14:33:48 -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 Madill54f882c2015-09-02 14:33:48 -04001366 for (D3DUniform *d3dUniform : mD3DUniforms)
Brandon Jones18bd4102014-09-22 14:21:44 -07001367 {
Jamie Madill54f882c2015-09-02 14:33:48 -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
1477void ProgramD3D::getUniformfv(GLint location, GLfloat *params)
1478{
1479 getUniformv(location, params, GL_FLOAT);
1480}
1481
1482void ProgramD3D::getUniformiv(GLint location, GLint *params)
1483{
1484 getUniformv(location, params, GL_INT);
1485}
1486
1487void ProgramD3D::getUniformuiv(GLint location, GLuint *params)
1488{
1489 getUniformv(location, params, GL_UNSIGNED_INT);
1490}
1491
Jamie Madill54f882c2015-09-02 14:33:48 -04001492void ProgramD3D::assignUniformRegisters()
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001493{
Jamie Madill54f882c2015-09-02 14:33:48 -04001494 const gl::Shader *vertexShader = mData.getAttachedVertexShader();
1495 const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(vertexShader);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001496
Jamie Madill54f882c2015-09-02 14:33:48 -04001497 for (const sh::Uniform &vertexUniform : vertexShader->getUniforms())
Brandon Jones18bd4102014-09-22 14:21:44 -07001498 {
Jamie Madill54f882c2015-09-02 14:33:48 -04001499 if (vertexUniform.staticUse)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001500 {
Jamie Madill54f882c2015-09-02 14:33:48 -04001501 assignUniformRegistersBase(vertexShaderD3D, vertexUniform);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001502 }
1503 }
1504
Jamie Madill54f882c2015-09-02 14:33:48 -04001505 const gl::Shader *fragmentShader = mData.getAttachedFragmentShader();
1506 const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(fragmentShader);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001507
Jamie Madill54f882c2015-09-02 14:33:48 -04001508 for (const sh::Uniform &fragmentUniform : fragmentShader->getUniforms())
Jamie Madillea918db2015-08-18 14:48:59 -04001509 {
Jamie Madill54f882c2015-09-02 14:33:48 -04001510 if (fragmentUniform.staticUse)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001511 {
Jamie Madill54f882c2015-09-02 14:33:48 -04001512 assignUniformRegistersBase(fragmentShaderD3D, fragmentUniform);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001513 }
1514 }
1515
Jamie Madill54f882c2015-09-02 14:33:48 -04001516 assignAllSamplerRegisters();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001517 initializeUniformStorage();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001518}
1519
Jamie Madill54f882c2015-09-02 14:33:48 -04001520void ProgramD3D::assignUniformRegistersBase(const ShaderD3D *shader, const sh::Uniform &uniform)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001521{
Jamie Madill54f882c2015-09-02 14:33:48 -04001522 if (uniform.isBuiltIn())
Jamie Madill55def582015-05-04 11:24:57 -04001523 {
Jamie Madill54f882c2015-09-02 14:33:48 -04001524 assignUniformRegisters(shader, uniform, uniform.name, nullptr);
Jamie Madill55def582015-05-04 11:24:57 -04001525 return;
1526 }
1527
Jamie Madill54f882c2015-09-02 14:33:48 -04001528 unsigned int startRegister = shader->getUniformRegister(uniform.name);
Geoff Lang492a7e42014-11-05 13:27:06 -05001529 ShShaderOutput outputType = shader->getCompilerOutputType();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001530 sh::HLSLBlockEncoder encoder(sh::HLSLBlockEncoder::GetStrategyFor(outputType));
Jamie Madill54f882c2015-09-02 14:33:48 -04001531 encoder.skipRegisters(startRegister);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001532
Jamie Madill54f882c2015-09-02 14:33:48 -04001533 assignUniformRegisters(shader, uniform, uniform.name, &encoder);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001534}
1535
Jamie Madill54f882c2015-09-02 14:33:48 -04001536D3DUniform *ProgramD3D::getD3DUniformByName(const std::string &name)
1537{
1538 for (D3DUniform *d3dUniform : mD3DUniforms)
1539 {
1540 if (d3dUniform->name == name)
1541 {
1542 return d3dUniform;
1543 }
1544 }
1545
1546 return nullptr;
1547}
1548
1549void ProgramD3D::assignUniformRegisters(const ShaderD3D *shader,
1550 const sh::ShaderVariable &uniform,
1551 const std::string &fullName,
1552 sh::HLSLBlockEncoder *encoder)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001553{
1554 if (uniform.isStruct())
1555 {
1556 for (unsigned int elementIndex = 0; elementIndex < uniform.elementCount(); elementIndex++)
1557 {
1558 const std::string &elementString = (uniform.isArray() ? ArrayString(elementIndex) : "");
1559
Jamie Madill55def582015-05-04 11:24:57 -04001560 if (encoder)
1561 encoder->enterAggregateType();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001562
1563 for (size_t fieldIndex = 0; fieldIndex < uniform.fields.size(); fieldIndex++)
1564 {
1565 const sh::ShaderVariable &field = uniform.fields[fieldIndex];
1566 const std::string &fieldFullName = (fullName + elementString + "." + field.name);
1567
Jamie Madill54f882c2015-09-02 14:33:48 -04001568 assignUniformRegisters(shader, field, fieldFullName, encoder);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001569 }
1570
Jamie Madill55def582015-05-04 11:24:57 -04001571 if (encoder)
1572 encoder->exitAggregateType();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001573 }
Jamie Madill54f882c2015-09-02 14:33:48 -04001574 return;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001575 }
Jamie Madill54f882c2015-09-02 14:33:48 -04001576
1577 // Not a struct. Arrays are treated as aggregate types.
1578 if (uniform.isArray() && encoder)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001579 {
Jamie Madill54f882c2015-09-02 14:33:48 -04001580 encoder->enterAggregateType();
1581 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001582
Jamie Madill54f882c2015-09-02 14:33:48 -04001583 // Advance the uniform offset, to track registers allocation for structs
1584 sh::BlockMemberInfo blockInfo =
1585 encoder ? encoder->encodeType(uniform.type, uniform.arraySize, false)
1586 : sh::BlockMemberInfo::getDefaultBlockInfo();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001587
Jamie Madill54f882c2015-09-02 14:33:48 -04001588 D3DUniform *d3dUniform = getD3DUniformByName(fullName);
Jamie Madill2857f482015-02-09 15:35:29 -05001589
Jamie Madill54f882c2015-09-02 14:33:48 -04001590 if (!d3dUniform)
1591 {
1592 // We're building the list twice, make sure we use the same indexing. Special case
1593 // built-ins.
1594 ASSERT(fullName.compare(0, 3, "gl_") == 0 ||
1595 mData.getUniformIndex(fullName) == static_cast<GLint>(mD3DUniforms.size()));
Jamie Madill55def582015-05-04 11:24:57 -04001596
Jamie Madill54f882c2015-09-02 14:33:48 -04001597 d3dUniform = new D3DUniform(uniform.type, fullName, uniform.arraySize, true);
1598 mD3DUniforms.push_back(d3dUniform);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001599
Jamie Madill55def582015-05-04 11:24:57 -04001600 if (encoder)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001601 {
Jamie Madill54f882c2015-09-02 14:33:48 -04001602 d3dUniform->registerElement =
1603 static_cast<unsigned int>(sh::HLSLBlockEncoder::getBlockRegisterElement(blockInfo));
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001604 }
Jamie Madill54f882c2015-09-02 14:33:48 -04001605 }
1606
1607 if (encoder)
1608 {
1609 unsigned int reg =
1610 static_cast<unsigned int>(sh::HLSLBlockEncoder::getBlockRegister(blockInfo));
1611 if (shader->getShaderType() == GL_FRAGMENT_SHADER)
1612 {
1613 d3dUniform->psRegisterIndex = reg;
1614 }
1615 else if (shader->getShaderType() == GL_VERTEX_SHADER)
1616 {
1617 d3dUniform->vsRegisterIndex = reg;
1618 }
1619 else
1620 UNREACHABLE();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001621
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001622 // Arrays are treated as aggregate types
Jamie Madill54f882c2015-09-02 14:33:48 -04001623 if (uniform.isArray())
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001624 {
1625 encoder->exitAggregateType();
1626 }
1627 }
1628}
1629
1630template <typename T>
1631static inline void SetIfDirty(T *dest, const T& source, bool *dirtyFlag)
1632{
1633 ASSERT(dest != NULL);
1634 ASSERT(dirtyFlag != NULL);
1635
1636 *dirtyFlag = *dirtyFlag || (memcmp(dest, &source, sizeof(T)) != 0);
1637 *dest = source;
1638}
1639
1640template <typename T>
Jamie Madill54f882c2015-09-02 14:33:48 -04001641void ProgramD3D::setUniform(GLint location, GLsizei countIn, const T *v, GLenum targetUniformType)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001642{
1643 const int components = gl::VariableComponentCount(targetUniformType);
1644 const GLenum targetBoolType = gl::VariableBoolVectorType(targetUniformType);
1645
Jamie Madill54f882c2015-09-02 14:33:48 -04001646 D3DUniform *targetUniform = getD3DUniformFromLocation(location);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001647
Jamie Madill54f882c2015-09-02 14:33:48 -04001648 unsigned int elementCount = targetUniform->elementCount();
1649 unsigned int arrayElement = mData.getUniformLocations()[location].element;
1650 unsigned int count = std::min(elementCount - arrayElement, static_cast<unsigned int>(countIn));
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001651
1652 if (targetUniform->type == targetUniformType)
1653 {
Jamie Madill54f882c2015-09-02 14:33:48 -04001654 T *target = reinterpret_cast<T *>(targetUniform->data) + arrayElement * 4;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001655
Jamie Madill54f882c2015-09-02 14:33:48 -04001656 for (unsigned int i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001657 {
1658 T *dest = target + (i * 4);
1659 const T *source = v + (i * components);
1660
1661 for (int c = 0; c < components; c++)
1662 {
1663 SetIfDirty(dest + c, source[c], &targetUniform->dirty);
1664 }
1665 for (int c = components; c < 4; c++)
1666 {
1667 SetIfDirty(dest + c, T(0), &targetUniform->dirty);
1668 }
1669 }
1670 }
1671 else if (targetUniform->type == targetBoolType)
1672 {
Jamie Madill54f882c2015-09-02 14:33:48 -04001673 GLint *boolParams = reinterpret_cast<GLint *>(targetUniform->data) + arrayElement * 4;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001674
Jamie Madill54f882c2015-09-02 14:33:48 -04001675 for (unsigned int i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001676 {
1677 GLint *dest = boolParams + (i * 4);
1678 const T *source = v + (i * components);
1679
1680 for (int c = 0; c < components; c++)
1681 {
1682 SetIfDirty(dest + c, (source[c] == static_cast<T>(0)) ? GL_FALSE : GL_TRUE, &targetUniform->dirty);
1683 }
1684 for (int c = components; c < 4; c++)
1685 {
1686 SetIfDirty(dest + c, GL_FALSE, &targetUniform->dirty);
1687 }
1688 }
1689 }
Jamie Madill54f882c2015-09-02 14:33:48 -04001690 else if (targetUniform->isSampler())
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001691 {
1692 ASSERT(targetUniformType == GL_INT);
1693
Jamie Madill54f882c2015-09-02 14:33:48 -04001694 GLint *target = reinterpret_cast<GLint *>(targetUniform->data) + arrayElement * 4;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001695
1696 bool wasDirty = targetUniform->dirty;
1697
Jamie Madill54f882c2015-09-02 14:33:48 -04001698 for (unsigned int i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001699 {
1700 GLint *dest = target + (i * 4);
1701 const GLint *source = reinterpret_cast<const GLint*>(v) + (i * components);
1702
1703 SetIfDirty(dest + 0, source[0], &targetUniform->dirty);
1704 SetIfDirty(dest + 1, 0, &targetUniform->dirty);
1705 SetIfDirty(dest + 2, 0, &targetUniform->dirty);
1706 SetIfDirty(dest + 3, 0, &targetUniform->dirty);
1707 }
1708
1709 if (!wasDirty && targetUniform->dirty)
1710 {
1711 mDirtySamplerMapping = true;
1712 }
Brandon Jones18bd4102014-09-22 14:21:44 -07001713 }
1714 else UNREACHABLE();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001715}
Brandon Jones18bd4102014-09-22 14:21:44 -07001716
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001717template<typename T>
1718bool transposeMatrix(T *target, const GLfloat *value, int targetWidth, int targetHeight, int srcWidth, int srcHeight)
1719{
1720 bool dirty = false;
1721 int copyWidth = std::min(targetHeight, srcWidth);
1722 int copyHeight = std::min(targetWidth, srcHeight);
1723
1724 for (int x = 0; x < copyWidth; x++)
1725 {
1726 for (int y = 0; y < copyHeight; y++)
1727 {
1728 SetIfDirty(target + (x * targetWidth + y), static_cast<T>(value[y * srcWidth + x]), &dirty);
1729 }
1730 }
1731 // clear unfilled right side
1732 for (int y = 0; y < copyWidth; y++)
1733 {
1734 for (int x = copyHeight; x < targetWidth; x++)
1735 {
1736 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
1737 }
1738 }
1739 // clear unfilled bottom.
1740 for (int y = copyWidth; y < targetHeight; y++)
1741 {
1742 for (int x = 0; x < targetWidth; x++)
1743 {
1744 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
1745 }
1746 }
1747
1748 return dirty;
1749}
1750
1751template<typename T>
1752bool expandMatrix(T *target, const GLfloat *value, int targetWidth, int targetHeight, int srcWidth, int srcHeight)
1753{
1754 bool dirty = false;
1755 int copyWidth = std::min(targetWidth, srcWidth);
1756 int copyHeight = std::min(targetHeight, srcHeight);
1757
1758 for (int y = 0; y < copyHeight; y++)
1759 {
1760 for (int x = 0; x < copyWidth; x++)
1761 {
1762 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(value[y * srcWidth + x]), &dirty);
1763 }
1764 }
1765 // clear unfilled right side
1766 for (int y = 0; y < copyHeight; y++)
1767 {
1768 for (int x = copyWidth; x < targetWidth; x++)
1769 {
1770 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
1771 }
1772 }
1773 // clear unfilled bottom.
1774 for (int y = copyHeight; y < targetHeight; y++)
1775 {
1776 for (int x = 0; x < targetWidth; x++)
1777 {
1778 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
1779 }
1780 }
1781
1782 return dirty;
1783}
1784
1785template <int cols, int rows>
Jamie Madill54f882c2015-09-02 14:33:48 -04001786void ProgramD3D::setUniformMatrixfv(GLint location,
1787 GLsizei countIn,
1788 GLboolean transpose,
1789 const GLfloat *value,
1790 GLenum targetUniformType)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001791{
Jamie Madill54f882c2015-09-02 14:33:48 -04001792 D3DUniform *targetUniform = getD3DUniformFromLocation(location);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001793
Jamie Madill54f882c2015-09-02 14:33:48 -04001794 unsigned int elementCount = targetUniform->elementCount();
1795 unsigned int arrayElement = mData.getUniformLocations()[location].element;
1796 unsigned int count = std::min(elementCount - arrayElement, static_cast<unsigned int>(countIn));
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001797
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001798 const unsigned int targetMatrixStride = (4 * rows);
Jamie Madill54f882c2015-09-02 14:33:48 -04001799 GLfloat *target =
1800 (GLfloat *)(targetUniform->data + arrayElement * sizeof(GLfloat) * targetMatrixStride);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001801
Jamie Madill54f882c2015-09-02 14:33:48 -04001802 for (unsigned int i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001803 {
1804 // Internally store matrices as transposed versions to accomodate HLSL matrix indexing
1805 if (transpose == GL_FALSE)
1806 {
1807 targetUniform->dirty = transposeMatrix<GLfloat>(target, value, 4, rows, rows, cols) || targetUniform->dirty;
1808 }
1809 else
1810 {
1811 targetUniform->dirty = expandMatrix<GLfloat>(target, value, 4, rows, cols, rows) || targetUniform->dirty;
1812 }
1813 target += targetMatrixStride;
1814 value += cols * rows;
1815 }
1816}
1817
1818template <typename T>
1819void ProgramD3D::getUniformv(GLint location, T *params, GLenum uniformType)
1820{
Jamie Madill54f882c2015-09-02 14:33:48 -04001821 D3DUniform *targetUniform = getD3DUniformFromLocation(location);
1822 unsigned int arrayElement = mData.getUniformLocations()[location].element;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001823
1824 if (gl::IsMatrixType(targetUniform->type))
1825 {
1826 const int rows = gl::VariableRowCount(targetUniform->type);
1827 const int cols = gl::VariableColumnCount(targetUniform->type);
Jamie Madill54f882c2015-09-02 14:33:48 -04001828 transposeMatrix(params, (GLfloat *)targetUniform->data + arrayElement * 4 * rows, rows,
1829 cols, 4, rows);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001830 }
1831 else if (uniformType == gl::VariableComponentType(targetUniform->type))
1832 {
1833 unsigned int size = gl::VariableComponentCount(targetUniform->type);
Jamie Madill54f882c2015-09-02 14:33:48 -04001834 memcpy(params, targetUniform->data + arrayElement * 4 * sizeof(T), size * sizeof(T));
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001835 }
1836 else
1837 {
1838 unsigned int size = gl::VariableComponentCount(targetUniform->type);
1839 switch (gl::VariableComponentType(targetUniform->type))
1840 {
1841 case GL_BOOL:
1842 {
Jamie Madill54f882c2015-09-02 14:33:48 -04001843 GLint *boolParams = (GLint *)targetUniform->data + arrayElement * 4;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001844
1845 for (unsigned int i = 0; i < size; i++)
1846 {
1847 params[i] = (boolParams[i] == GL_FALSE) ? static_cast<T>(0) : static_cast<T>(1);
1848 }
1849 }
1850 break;
1851
1852 case GL_FLOAT:
1853 {
Jamie Madill54f882c2015-09-02 14:33:48 -04001854 GLfloat *floatParams = (GLfloat *)targetUniform->data + arrayElement * 4;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001855
1856 for (unsigned int i = 0; i < size; i++)
1857 {
1858 params[i] = static_cast<T>(floatParams[i]);
1859 }
1860 }
1861 break;
1862
1863 case GL_INT:
1864 {
Jamie Madill54f882c2015-09-02 14:33:48 -04001865 GLint *intParams = (GLint *)targetUniform->data + arrayElement * 4;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001866
1867 for (unsigned int i = 0; i < size; i++)
1868 {
1869 params[i] = static_cast<T>(intParams[i]);
1870 }
1871 }
1872 break;
1873
1874 case GL_UNSIGNED_INT:
1875 {
Jamie Madill54f882c2015-09-02 14:33:48 -04001876 GLuint *uintParams = (GLuint *)targetUniform->data + arrayElement * 4;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001877
1878 for (unsigned int i = 0; i < size; i++)
1879 {
1880 params[i] = static_cast<T>(uintParams[i]);
1881 }
1882 }
1883 break;
1884
1885 default: UNREACHABLE();
1886 }
1887 }
1888}
1889
Jamie Madill54f882c2015-09-02 14:33:48 -04001890size_t ProgramD3D::defineUniformBlock(const sh::InterfaceBlock &interfaceBlock,
1891 BlockInfoMap *blockInfoOut)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001892{
Jamie Madill54f882c2015-09-02 14:33:48 -04001893 ASSERT(interfaceBlock.staticUse || interfaceBlock.layout == sh::BLOCKLAYOUT_PACKED);
1894
1895 // define member uniforms
1896 sh::Std140BlockEncoder std140Encoder;
1897 sh::HLSLBlockEncoder hlslEncoder(sh::HLSLBlockEncoder::ENCODE_PACKED);
1898 sh::BlockLayoutEncoder *encoder = nullptr;
1899
1900 if (interfaceBlock.layout == sh::BLOCKLAYOUT_STANDARD)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001901 {
Jamie Madill54f882c2015-09-02 14:33:48 -04001902 encoder = &std140Encoder;
1903 }
1904 else
1905 {
1906 encoder = &hlslEncoder;
1907 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001908
Jamie Madill54f882c2015-09-02 14:33:48 -04001909 GetUniformBlockInfo(interfaceBlock.fields, "", encoder, interfaceBlock.isRowMajorLayout,
1910 blockInfoOut);
1911
1912 return encoder->getBlockSize();
1913}
1914
1915void ProgramD3D::assignAllSamplerRegisters()
1916{
1917 for (const D3DUniform *d3dUniform : mD3DUniforms)
1918 {
1919 if (d3dUniform->isSampler())
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001920 {
Jamie Madill54f882c2015-09-02 14:33:48 -04001921 assignSamplerRegisters(d3dUniform);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001922 }
1923 }
1924}
1925
Jamie Madill54f882c2015-09-02 14:33:48 -04001926void ProgramD3D::assignSamplerRegisters(const D3DUniform *d3dUniform)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001927{
Jamie Madill54f882c2015-09-02 14:33:48 -04001928 ASSERT(d3dUniform->isSampler());
1929 ASSERT(d3dUniform->vsRegisterIndex != GL_INVALID_INDEX ||
1930 d3dUniform->psRegisterIndex != GL_INVALID_INDEX);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001931
Jamie Madill54f882c2015-09-02 14:33:48 -04001932 if (d3dUniform->vsRegisterIndex != GL_INVALID_INDEX)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001933 {
Jamie Madill54f882c2015-09-02 14:33:48 -04001934 AssignSamplers(d3dUniform->vsRegisterIndex, d3dUniform->type, d3dUniform->arraySize,
1935 mSamplersVS, &mUsedVertexSamplerRange);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001936 }
1937
Jamie Madill54f882c2015-09-02 14:33:48 -04001938 if (d3dUniform->psRegisterIndex != GL_INVALID_INDEX)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001939 {
Jamie Madill54f882c2015-09-02 14:33:48 -04001940 AssignSamplers(d3dUniform->psRegisterIndex, d3dUniform->type, d3dUniform->arraySize,
1941 mSamplersPS, &mUsedPixelSamplerRange);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001942 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001943}
1944
Jamie Madill54f882c2015-09-02 14:33:48 -04001945// static
1946void ProgramD3D::AssignSamplers(unsigned int startSamplerIndex,
Jamie Madilld3dfda22015-07-06 08:28:49 -04001947 GLenum samplerType,
1948 unsigned int samplerCount,
1949 std::vector<Sampler> &outSamplers,
1950 GLuint *outUsedRange)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001951{
1952 unsigned int samplerIndex = startSamplerIndex;
1953
1954 do
1955 {
Jamie Madill54f882c2015-09-02 14:33:48 -04001956 ASSERT(samplerIndex < outSamplers.size());
1957 Sampler *sampler = &outSamplers[samplerIndex];
1958 sampler->active = true;
1959 sampler->textureType = GetTextureType(samplerType);
1960 sampler->logicalTextureUnit = 0;
1961 *outUsedRange = std::max(samplerIndex + 1, *outUsedRange);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001962 samplerIndex++;
1963 } while (samplerIndex < startSamplerIndex + samplerCount);
Brandon Jones18bd4102014-09-22 14:21:44 -07001964}
1965
Brandon Jonesc9610c52014-08-25 17:02:59 -07001966void ProgramD3D::reset()
1967{
Brandon Joneseb994362014-09-24 10:27:28 -07001968 SafeDeleteContainer(mVertexExecutables);
1969 SafeDeleteContainer(mPixelExecutables);
1970 SafeDelete(mGeometryExecutable);
1971
Brandon Jones22502d52014-08-29 16:58:36 -07001972 mVertexHLSL.clear();
Geoff Lang6941a552015-07-27 11:06:45 -04001973 mVertexWorkarounds = D3DCompilerWorkarounds();
Brandon Jones44151a92014-09-10 11:32:25 -07001974 mShaderVersion = 100;
Brandon Jones22502d52014-08-29 16:58:36 -07001975
1976 mPixelHLSL.clear();
Geoff Lang6941a552015-07-27 11:06:45 -04001977 mPixelWorkarounds = D3DCompilerWorkarounds();
Brandon Jones22502d52014-08-29 16:58:36 -07001978 mUsesFragDepth = false;
1979 mPixelShaderKey.clear();
Brandon Jones44151a92014-09-10 11:32:25 -07001980 mUsesPointSize = false;
Brandon Jones22502d52014-08-29 16:58:36 -07001981
Jamie Madill54f882c2015-09-02 14:33:48 -04001982 SafeDeleteContainer(mD3DUniforms);
1983
Brandon Jonesc9610c52014-08-25 17:02:59 -07001984 SafeDelete(mVertexUniformStorage);
1985 SafeDelete(mFragmentUniformStorage);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001986
1987 mSamplersPS.clear();
1988 mSamplersVS.clear();
1989
1990 mUsedVertexSamplerRange = 0;
1991 mUsedPixelSamplerRange = 0;
1992 mDirtySamplerMapping = true;
Jamie Madill437d2662014-12-05 14:23:35 -05001993
Jamie Madill63805b42015-08-25 13:17:39 -04001994 std::fill(mSemanticIndexes, mSemanticIndexes + ArraySize(mSemanticIndexes), -1);
Jamie Madill437d2662014-12-05 14:23:35 -05001995 std::fill(mAttributesByLayout, mAttributesByLayout + ArraySize(mAttributesByLayout), -1);
Jamie Madillccdf74b2015-08-18 10:46:12 -04001996
1997 mTransformFeedbackLinkedVaryings.clear();
Brandon Jonesc9610c52014-08-25 17:02:59 -07001998}
1999
Geoff Lang7dd2e102014-11-10 15:19:26 -05002000unsigned int ProgramD3D::getSerial() const
2001{
2002 return mSerial;
2003}
2004
2005unsigned int ProgramD3D::issueSerial()
2006{
2007 return mCurrentSerial++;
2008}
2009
Jamie Madill63805b42015-08-25 13:17:39 -04002010void ProgramD3D::initSemanticIndex()
2011{
2012 const gl::Shader *vertexShader = mData.getAttachedVertexShader();
2013 ASSERT(vertexShader != nullptr);
2014
2015 // Init semantic index
2016 for (const sh::Attribute &attribute : mData.getAttributes())
2017 {
2018 int attributeIndex = attribute.location;
2019 int index = vertexShader->getSemanticIndex(attribute.name);
2020 int regs = gl::VariableRegisterCount(attribute.type);
2021
2022 for (int reg = 0; reg < regs; ++reg)
2023 {
2024 mSemanticIndexes[attributeIndex + reg] = index + reg;
2025 }
2026 }
2027
2028 initAttributesByLayout();
2029}
2030
Jamie Madill437d2662014-12-05 14:23:35 -05002031void ProgramD3D::initAttributesByLayout()
2032{
2033 for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
2034 {
2035 mAttributesByLayout[i] = i;
2036 }
2037
Jamie Madill63805b42015-08-25 13:17:39 -04002038 std::sort(&mAttributesByLayout[0], &mAttributesByLayout[gl::MAX_VERTEX_ATTRIBS],
2039 AttributeSorter(mSemanticIndexes));
Jamie Madill437d2662014-12-05 14:23:35 -05002040}
2041
Jamie Madill476682e2015-06-30 10:04:29 -04002042void ProgramD3D::sortAttributesByLayout(const std::vector<TranslatedAttribute> &unsortedAttributes,
Jamie Madillf9327d32015-06-22 13:57:16 -04002043 int sortedSemanticIndicesOut[gl::MAX_VERTEX_ATTRIBS],
2044 const rx::TranslatedAttribute *sortedAttributesOut[gl::MAX_VERTEX_ATTRIBS]) const
Jamie Madill437d2662014-12-05 14:23:35 -05002045{
Jamie Madill476682e2015-06-30 10:04:29 -04002046 for (size_t attribIndex = 0; attribIndex < unsortedAttributes.size(); ++attribIndex)
Jamie Madill437d2662014-12-05 14:23:35 -05002047 {
Jamie Madill476682e2015-06-30 10:04:29 -04002048 int oldIndex = mAttributesByLayout[attribIndex];
Jamie Madill63805b42015-08-25 13:17:39 -04002049 sortedSemanticIndicesOut[attribIndex] = mSemanticIndexes[oldIndex];
Jamie Madill476682e2015-06-30 10:04:29 -04002050 sortedAttributesOut[attribIndex] = &unsortedAttributes[oldIndex];
Jamie Madill437d2662014-12-05 14:23:35 -05002051 }
2052}
2053
Jamie Madill63805b42015-08-25 13:17:39 -04002054void ProgramD3D::updateCachedInputLayout(const gl::State &state)
Jamie Madilld3dfda22015-07-06 08:28:49 -04002055{
Jamie Madillbd136f92015-08-10 14:51:37 -04002056 mCachedInputLayout.clear();
Jamie Madilld3dfda22015-07-06 08:28:49 -04002057 const auto &vertexAttributes = state.getVertexArray()->getVertexAttributes();
Jamie Madillf8dd7b12015-08-05 13:50:08 -04002058
Jamie Madilld3dfda22015-07-06 08:28:49 -04002059 for (unsigned int attributeIndex = 0; attributeIndex < vertexAttributes.size(); attributeIndex++)
2060 {
Jamie Madill63805b42015-08-25 13:17:39 -04002061 int semanticIndex = mSemanticIndexes[attributeIndex];
Jamie Madilld3dfda22015-07-06 08:28:49 -04002062
2063 if (semanticIndex != -1)
2064 {
Jamie Madillbd136f92015-08-10 14:51:37 -04002065 if (mCachedInputLayout.size() < static_cast<size_t>(semanticIndex + 1))
2066 {
2067 mCachedInputLayout.resize(semanticIndex + 1, gl::VERTEX_FORMAT_INVALID);
2068 }
Jamie Madilld3dfda22015-07-06 08:28:49 -04002069 mCachedInputLayout[semanticIndex] =
2070 GetVertexFormatType(vertexAttributes[attributeIndex],
2071 state.getVertexAttribCurrentValue(attributeIndex).Type);
2072 }
2073 }
2074}
2075
Jamie Madillccdf74b2015-08-18 10:46:12 -04002076void ProgramD3D::gatherTransformFeedbackVaryings(
2077 const std::vector<gl::LinkedVarying> &linkedVaryings)
2078{
2079 // Gather the linked varyings that are used for transform feedback, they should all exist.
2080 mTransformFeedbackLinkedVaryings.clear();
2081 for (const std::string &tfVaryingName : mData.getTransformFeedbackVaryingNames())
2082 {
2083 for (const gl::LinkedVarying &linkedVarying : linkedVaryings)
2084 {
2085 if (tfVaryingName == linkedVarying.name)
2086 {
2087 mTransformFeedbackLinkedVaryings.push_back(linkedVarying);
2088 break;
2089 }
2090 }
2091 }
2092}
Jamie Madill54f882c2015-09-02 14:33:48 -04002093
2094D3DUniform *ProgramD3D::getD3DUniformFromLocation(GLint location)
2095{
2096 return mD3DUniforms[mData.getUniformLocations()[location].index];
2097}
Brandon Jonesc9610c52014-08-25 17:02:59 -07002098}