blob: bb10266f4cc953f8bf22f803e39455def4ae9e40 [file] [log] [blame]
Brandon Jonesc9610c52014-08-25 17:02:59 -07001//
2// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// ProgramD3D.cpp: Defines the rx::ProgramD3D class which implements rx::ProgramImpl.
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/renderer/d3d/ProgramD3D.h"
Jamie Madill437d2662014-12-05 14:23:35 -050010
Dian Xianga4928832015-09-15 10:11:17 -070011#include "common/BitSetIterator.h"
Jamie Madill437d2662014-12-05 14:23:35 -050012#include "common/utilities.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050013#include "libANGLE/Framebuffer.h"
14#include "libANGLE/FramebufferAttachment.h"
15#include "libANGLE/Program.h"
Jamie Madilld3dfda22015-07-06 08:28:49 -040016#include "libANGLE/VertexArray.h"
Jamie Madill6df9b372015-02-18 21:28:19 +000017#include "libANGLE/features.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050018#include "libANGLE/renderer/d3d/DynamicHLSL.h"
Jamie Madill85a18042015-03-05 15:41:41 -050019#include "libANGLE/renderer/d3d/FramebufferD3D.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050020#include "libANGLE/renderer/d3d/RendererD3D.h"
21#include "libANGLE/renderer/d3d/ShaderD3D.h"
Geoff Lang359ef262015-01-05 14:42:29 -050022#include "libANGLE/renderer/d3d/ShaderExecutableD3D.h"
Jamie Madill65345da2015-11-13 11:25:23 -050023#include "libANGLE/renderer/d3d/VaryingPacking.h"
Jamie Madill437d2662014-12-05 14:23:35 -050024#include "libANGLE/renderer/d3d/VertexDataManager.h"
Olli Etuaho30268292016-01-15 16:40:00 +020025#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
Geoff Lang22072132014-11-20 15:15:01 -050026
Brandon Jonesc9610c52014-08-25 17:02:59 -070027namespace rx
28{
29
Brandon Joneseb994362014-09-24 10:27:28 -070030namespace
31{
32
Jamie Madillf8dd7b12015-08-05 13:50:08 -040033gl::InputLayout GetDefaultInputLayoutFromShader(const gl::Shader *vertexShader)
Brandon Joneseb994362014-09-24 10:27:28 -070034{
Jamie Madillbd136f92015-08-10 14:51:37 -040035 gl::InputLayout defaultLayout;
36 for (const sh::Attribute &shaderAttr : vertexShader->getActiveAttributes())
Brandon Joneseb994362014-09-24 10:27:28 -070037 {
Brandon Joneseb994362014-09-24 10:27:28 -070038 if (shaderAttr.type != GL_NONE)
39 {
40 GLenum transposedType = gl::TransposeMatrixType(shaderAttr.type);
41
Jamie Madilld3dfda22015-07-06 08:28:49 -040042 for (size_t rowIndex = 0;
Jamie Madill334d6152015-10-22 14:00:28 -040043 static_cast<int>(rowIndex) < gl::VariableRowCount(transposedType); ++rowIndex)
Brandon Joneseb994362014-09-24 10:27:28 -070044 {
Jamie Madilld3dfda22015-07-06 08:28:49 -040045 GLenum componentType = gl::VariableComponentType(transposedType);
Jamie Madill334d6152015-10-22 14:00:28 -040046 GLuint components = static_cast<GLuint>(gl::VariableColumnCount(transposedType));
Jamie Madilld3dfda22015-07-06 08:28:49 -040047 bool pureInt = (componentType != GL_FLOAT);
Jamie Madill334d6152015-10-22 14:00:28 -040048 gl::VertexFormatType defaultType =
49 gl::GetVertexFormatType(componentType, GL_FALSE, components, pureInt);
Brandon Joneseb994362014-09-24 10:27:28 -070050
Jamie Madillbd136f92015-08-10 14:51:37 -040051 defaultLayout.push_back(defaultType);
Brandon Joneseb994362014-09-24 10:27:28 -070052 }
53 }
54 }
Jamie Madillf8dd7b12015-08-05 13:50:08 -040055
56 return defaultLayout;
Brandon Joneseb994362014-09-24 10:27:28 -070057}
58
Jamie Madill334d6152015-10-22 14:00:28 -040059std::vector<GLenum> GetDefaultOutputLayoutFromShader(
60 const std::vector<PixelShaderOutputVariable> &shaderOutputVars)
Brandon Joneseb994362014-09-24 10:27:28 -070061{
Jamie Madillb4463142014-12-19 14:56:54 -050062 std::vector<GLenum> defaultPixelOutput;
Brandon Joneseb994362014-09-24 10:27:28 -070063
Jamie Madillb4463142014-12-19 14:56:54 -050064 if (!shaderOutputVars.empty())
65 {
Cooper Partin4d61f7e2015-08-12 10:56:50 -070066 defaultPixelOutput.push_back(GL_COLOR_ATTACHMENT0 +
67 static_cast<unsigned int>(shaderOutputVars[0].outputIndex));
Jamie Madillb4463142014-12-19 14:56:54 -050068 }
Brandon Joneseb994362014-09-24 10:27:28 -070069
70 return defaultPixelOutput;
71}
72
Brandon Jones1a8a7e32014-10-01 12:49:30 -070073bool IsRowMajorLayout(const sh::InterfaceBlockField &var)
74{
75 return var.isRowMajorLayout;
76}
77
78bool IsRowMajorLayout(const sh::ShaderVariable &var)
79{
80 return false;
81}
82
Jamie Madill437d2662014-12-05 14:23:35 -050083struct AttributeSorter
84{
Jamie Madill63805b42015-08-25 13:17:39 -040085 AttributeSorter(const ProgramD3D::SemanticIndexArray &semanticIndices)
Jamie Madill80d934b2015-02-19 10:16:12 -050086 : originalIndices(&semanticIndices)
Jamie Madill437d2662014-12-05 14:23:35 -050087 {
88 }
89
90 bool operator()(int a, int b)
91 {
Jamie Madill80d934b2015-02-19 10:16:12 -050092 int indexA = (*originalIndices)[a];
93 int indexB = (*originalIndices)[b];
94
Jamie Madill334d6152015-10-22 14:00:28 -040095 if (indexA == -1)
96 return false;
97 if (indexB == -1)
98 return true;
Jamie Madill80d934b2015-02-19 10:16:12 -050099 return (indexA < indexB);
Jamie Madill437d2662014-12-05 14:23:35 -0500100 }
101
Jamie Madill63805b42015-08-25 13:17:39 -0400102 const ProgramD3D::SemanticIndexArray *originalIndices;
Jamie Madill437d2662014-12-05 14:23:35 -0500103};
104
Jamie Madill9fc36822015-11-18 13:08:07 -0500105// true if varying x has a higher priority in packing than y
106bool ComparePackedVarying(const PackedVarying &x, const PackedVarying &y)
107{
Jamie Madill55c25d02015-11-18 13:08:08 -0500108 return gl::CompareShaderVar(*x.varying, *y.varying);
Jamie Madill9fc36822015-11-18 13:08:07 -0500109}
110
Jamie Madillca03b352015-09-02 12:38:13 -0400111std::vector<PackedVarying> MergeVaryings(const gl::Shader &vertexShader,
112 const gl::Shader &fragmentShader,
113 const std::vector<std::string> &tfVaryings)
Jamie Madillada9ecc2015-08-17 12:53:37 -0400114{
Jamie Madillca03b352015-09-02 12:38:13 -0400115 std::vector<PackedVarying> packedVaryings;
116
117 for (const sh::Varying &output : vertexShader.getVaryings())
Jamie Madillada9ecc2015-08-17 12:53:37 -0400118 {
Jamie Madillca03b352015-09-02 12:38:13 -0400119 bool packed = false;
Jamie Madillada9ecc2015-08-17 12:53:37 -0400120
121 // Built-in varyings obey special rules
Jamie Madillca03b352015-09-02 12:38:13 -0400122 if (output.isBuiltIn())
Jamie Madillada9ecc2015-08-17 12:53:37 -0400123 {
124 continue;
125 }
126
Jamie Madillca03b352015-09-02 12:38:13 -0400127 for (const sh::Varying &input : fragmentShader.getVaryings())
Jamie Madillada9ecc2015-08-17 12:53:37 -0400128 {
Jamie Madillca03b352015-09-02 12:38:13 -0400129 if (output.name == input.name)
Jamie Madillada9ecc2015-08-17 12:53:37 -0400130 {
Jamie Madill55c25d02015-11-18 13:08:08 -0500131 if (output.isStruct())
132 {
133 ASSERT(!output.isArray());
134 for (const auto &field : output.fields)
135 {
136 ASSERT(!field.isStruct() && !field.isArray());
137 packedVaryings.push_back(
138 PackedVarying(field, input.interpolation, input.name));
139 }
140 }
141 else
142 {
143 packedVaryings.push_back(PackedVarying(input, input.interpolation));
144 }
Jamie Madillca03b352015-09-02 12:38:13 -0400145 packed = true;
Jamie Madillada9ecc2015-08-17 12:53:37 -0400146 break;
147 }
148 }
149
Jamie Madillca03b352015-09-02 12:38:13 -0400150 // Keep Transform FB varyings in the merged list always.
151 if (!packed)
152 {
153 for (const std::string &tfVarying : tfVaryings)
154 {
155 if (tfVarying == output.name)
156 {
Jamie Madill55c25d02015-11-18 13:08:08 -0500157 // Transform feedback for varying structs is underspecified.
158 // See Khronos bug 9856.
159 // TODO(jmadill): Figure out how to be spec-compliant here.
160 if (!output.isStruct())
161 {
162 packedVaryings.push_back(PackedVarying(output, output.interpolation));
163 packedVaryings.back().vertexOnly = true;
164 }
Jamie Madillca03b352015-09-02 12:38:13 -0400165 break;
166 }
167 }
168 }
Jamie Madillada9ecc2015-08-17 12:53:37 -0400169 }
170
Jamie Madill9fc36822015-11-18 13:08:07 -0500171 std::sort(packedVaryings.begin(), packedVaryings.end(), ComparePackedVarying);
172
Jamie Madillca03b352015-09-02 12:38:13 -0400173 return packedVaryings;
Brandon Joneseb994362014-09-24 10:27:28 -0700174}
175
Jamie Madill62d31cb2015-09-11 13:25:51 -0400176template <typename VarT>
177void GetUniformBlockInfo(const std::vector<VarT> &fields,
178 const std::string &prefix,
179 sh::BlockLayoutEncoder *encoder,
180 bool inRowMajorLayout,
181 std::map<std::string, sh::BlockMemberInfo> *blockInfoOut)
182{
183 for (const VarT &field : fields)
184 {
185 const std::string &fieldName = (prefix.empty() ? field.name : prefix + "." + field.name);
186
187 if (field.isStruct())
188 {
189 bool rowMajorLayout = (inRowMajorLayout || IsRowMajorLayout(field));
190
191 for (unsigned int arrayElement = 0; arrayElement < field.elementCount(); arrayElement++)
192 {
193 encoder->enterAggregateType();
194
195 const std::string uniformElementName =
196 fieldName + (field.isArray() ? ArrayString(arrayElement) : "");
197 GetUniformBlockInfo(field.fields, uniformElementName, encoder, rowMajorLayout,
198 blockInfoOut);
199
200 encoder->exitAggregateType();
201 }
202 }
203 else
204 {
205 bool isRowMajorMatrix = (gl::IsMatrixType(field.type) && inRowMajorLayout);
206 (*blockInfoOut)[fieldName] =
207 encoder->encodeType(field.type, field.arraySize, isRowMajorMatrix);
208 }
209 }
210}
211
Jamie Madill334d6152015-10-22 14:00:28 -0400212template <typename T>
Jacek Caban2302e692015-12-01 12:44:43 +0100213static inline void SetIfDirty(T *dest, const T &source, bool *dirtyFlag)
214{
215 ASSERT(dest != NULL);
216 ASSERT(dirtyFlag != NULL);
217
218 *dirtyFlag = *dirtyFlag || (memcmp(dest, &source, sizeof(T)) != 0);
219 *dest = source;
220}
221
222template <typename T>
Jamie Madill334d6152015-10-22 14:00:28 -0400223bool TransposeMatrix(T *target,
224 const GLfloat *value,
225 int targetWidth,
226 int targetHeight,
227 int srcWidth,
228 int srcHeight)
229{
230 bool dirty = false;
231 int copyWidth = std::min(targetHeight, srcWidth);
232 int copyHeight = std::min(targetWidth, srcHeight);
233
234 for (int x = 0; x < copyWidth; x++)
235 {
236 for (int y = 0; y < copyHeight; y++)
237 {
238 SetIfDirty(target + (x * targetWidth + y), static_cast<T>(value[y * srcWidth + x]),
239 &dirty);
240 }
241 }
242 // clear unfilled right side
243 for (int y = 0; y < copyWidth; y++)
244 {
245 for (int x = copyHeight; x < targetWidth; x++)
246 {
247 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
248 }
249 }
250 // clear unfilled bottom.
251 for (int y = copyWidth; y < targetHeight; y++)
252 {
253 for (int x = 0; x < targetWidth; x++)
254 {
255 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
256 }
257 }
258
259 return dirty;
260}
261
262template <typename T>
263bool ExpandMatrix(T *target,
264 const GLfloat *value,
265 int targetWidth,
266 int targetHeight,
267 int srcWidth,
268 int srcHeight)
269{
270 bool dirty = false;
271 int copyWidth = std::min(targetWidth, srcWidth);
272 int copyHeight = std::min(targetHeight, srcHeight);
273
274 for (int y = 0; y < copyHeight; y++)
275 {
276 for (int x = 0; x < copyWidth; x++)
277 {
278 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(value[y * srcWidth + x]),
279 &dirty);
280 }
281 }
282 // clear unfilled right side
283 for (int y = 0; y < copyHeight; y++)
284 {
285 for (int x = copyWidth; x < targetWidth; x++)
286 {
287 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
288 }
289 }
290 // clear unfilled bottom.
291 for (int y = copyHeight; y < targetHeight; y++)
292 {
293 for (int x = 0; x < targetWidth; x++)
294 {
295 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
296 }
297 }
298
299 return dirty;
300}
301
Jamie Madill4e31ad52015-10-29 10:32:57 -0400302gl::PrimitiveType GetGeometryShaderTypeFromDrawMode(GLenum drawMode)
303{
304 switch (drawMode)
305 {
306 // Uses the point sprite geometry shader.
307 case GL_POINTS:
308 return gl::PRIMITIVE_POINTS;
309
310 // All line drawing uses the same geometry shader.
311 case GL_LINES:
312 case GL_LINE_STRIP:
313 case GL_LINE_LOOP:
314 return gl::PRIMITIVE_LINES;
315
316 // The triangle fan primitive is emulated with strips in D3D11.
317 case GL_TRIANGLES:
318 case GL_TRIANGLE_FAN:
319 return gl::PRIMITIVE_TRIANGLES;
320
321 // Special case for triangle strips.
322 case GL_TRIANGLE_STRIP:
323 return gl::PRIMITIVE_TRIANGLE_STRIP;
324
325 default:
326 UNREACHABLE();
327 return gl::PRIMITIVE_TYPE_MAX;
328 }
329}
330
Jamie Madillada9ecc2015-08-17 12:53:37 -0400331} // anonymous namespace
332
Jamie Madill28afae52015-11-09 15:07:57 -0500333// D3DUniform Implementation
334
Jamie Madill62d31cb2015-09-11 13:25:51 -0400335D3DUniform::D3DUniform(GLenum typeIn,
336 const std::string &nameIn,
337 unsigned int arraySizeIn,
338 bool defaultBlock)
339 : type(typeIn),
340 name(nameIn),
341 arraySize(arraySizeIn),
342 data(nullptr),
343 dirty(true),
Jamie Madill62d31cb2015-09-11 13:25:51 -0400344 vsRegisterIndex(GL_INVALID_INDEX),
Geoff Lang98c56da2015-09-15 15:45:34 -0400345 psRegisterIndex(GL_INVALID_INDEX),
Jamie Madill62d31cb2015-09-11 13:25:51 -0400346 registerCount(0),
347 registerElement(0)
348{
349 // We use data storage for default block uniforms to cache values that are sent to D3D during
350 // rendering
351 // Uniform blocks/buffers are treated separately by the Renderer (ES3 path only)
352 if (defaultBlock)
353 {
354 size_t bytes = gl::VariableInternalSize(type) * elementCount();
355 data = new uint8_t[bytes];
356 memset(data, 0, bytes);
357
358 // TODO(jmadill): is this correct with non-square matrices?
359 registerCount = gl::VariableRowCount(type) * elementCount();
360 }
361}
362
363D3DUniform::~D3DUniform()
364{
365 SafeDeleteArray(data);
366}
367
368bool D3DUniform::isSampler() const
369{
370 return gl::IsSamplerType(type);
371}
372
373bool D3DUniform::isReferencedByVertexShader() const
374{
375 return vsRegisterIndex != GL_INVALID_INDEX;
376}
377
378bool D3DUniform::isReferencedByFragmentShader() const
379{
380 return psRegisterIndex != GL_INVALID_INDEX;
381}
382
Jamie Madill28afae52015-11-09 15:07:57 -0500383// D3DVarying Implementation
384
Jamie Madill9fc36822015-11-18 13:08:07 -0500385D3DVarying::D3DVarying() : semanticIndex(0), componentCount(0), outputSlot(0)
Jamie Madill28afae52015-11-09 15:07:57 -0500386{
387}
388
Jamie Madill9fc36822015-11-18 13:08:07 -0500389D3DVarying::D3DVarying(const std::string &semanticNameIn,
390 unsigned int semanticIndexIn,
391 unsigned int componentCountIn,
392 unsigned int outputSlotIn)
393 : semanticName(semanticNameIn),
394 semanticIndex(semanticIndexIn),
395 componentCount(componentCountIn),
396 outputSlot(outputSlotIn)
Jamie Madill28afae52015-11-09 15:07:57 -0500397{
398}
399
Jamie Madille39a3f02015-11-17 20:42:15 -0500400// ProgramD3DMetadata Implementation
401
402ProgramD3DMetadata::ProgramD3DMetadata(int rendererMajorShaderModel,
403 const std::string &shaderModelSuffix,
404 bool usesInstancedPointSpriteEmulation,
405 const ShaderD3D *vertexShader,
406 const ShaderD3D *fragmentShader)
407 : mRendererMajorShaderModel(rendererMajorShaderModel),
408 mShaderModelSuffix(shaderModelSuffix),
409 mUsesInstancedPointSpriteEmulation(usesInstancedPointSpriteEmulation),
410 mVertexShader(vertexShader),
411 mFragmentShader(fragmentShader)
412{
413}
414
415int ProgramD3DMetadata::getRendererMajorShaderModel() const
416{
417 return mRendererMajorShaderModel;
418}
419
420bool ProgramD3DMetadata::usesBroadcast(const gl::Data &data) const
421{
422 return (mFragmentShader->usesFragColor() && data.clientVersion < 3);
423}
424
425bool ProgramD3DMetadata::usesFragDepth(const gl::Program::Data &programData) const
426{
Jamie Madill63286672015-11-24 13:00:08 -0500427 return mFragmentShader->usesFragDepth();
Jamie Madille39a3f02015-11-17 20:42:15 -0500428}
429
430bool ProgramD3DMetadata::usesPointCoord() const
431{
432 return mFragmentShader->usesPointCoord();
433}
434
435bool ProgramD3DMetadata::usesFragCoord() const
436{
437 return mFragmentShader->usesFragCoord();
438}
439
440bool ProgramD3DMetadata::usesPointSize() const
441{
442 return mVertexShader->usesPointSize();
443}
444
445bool ProgramD3DMetadata::usesInsertedPointCoordValue() const
446{
447 return !usesPointSize() && usesPointCoord() && mRendererMajorShaderModel >= 4;
448}
449
450bool ProgramD3DMetadata::addsPointCoordToVertexShader() const
451{
452 // Instanced PointSprite emulation requires that gl_PointCoord is present in the vertex shader
453 // VS_OUTPUT structure to ensure compatibility with the generated PS_INPUT of the pixel shader.
454 // GeometryShader PointSprite emulation does not require this additional entry because the
455 // GS_OUTPUT of the Geometry shader contains the pointCoord value and already matches the
456 // PS_INPUT of the generated pixel shader. The Geometry Shader point sprite implementation needs
457 // gl_PointSize to be in VS_OUTPUT and GS_INPUT. Instanced point sprites doesn't need
458 // gl_PointSize in VS_OUTPUT.
459 return (mUsesInstancedPointSpriteEmulation && usesPointCoord()) ||
460 usesInsertedPointCoordValue();
461}
462
463bool ProgramD3DMetadata::usesTransformFeedbackGLPosition() const
464{
465 // gl_Position only needs to be outputted from the vertex shader if transform feedback is
466 // active. This isn't supported on D3D11 Feature Level 9_3, so we don't output gl_Position from
467 // the vertex shader in this case. This saves us 1 output vector.
468 return !(mRendererMajorShaderModel >= 4 && mShaderModelSuffix != "");
469}
470
471bool ProgramD3DMetadata::usesSystemValuePointSize() const
472{
473 return !mUsesInstancedPointSpriteEmulation && usesPointSize();
474}
475
476bool ProgramD3DMetadata::usesMultipleFragmentOuts() const
477{
478 return mFragmentShader->usesMultipleRenderTargets();
479}
480
481GLint ProgramD3DMetadata::getMajorShaderVersion() const
482{
483 return mVertexShader->getData().getShaderVersion();
484}
485
486const ShaderD3D *ProgramD3DMetadata::getFragmentShader() const
487{
488 return mFragmentShader;
489}
490
Olli Etuaho30268292016-01-15 16:40:00 +0200491// SamplerMetadataD3D11 implementation
492
493SamplerMetadataD3D11::SamplerMetadataD3D11()
494 : mSamplerCount(0), mType(gl::SAMPLER_VERTEX), mDirty(false), mSamplerMetadataBuffer(nullptr)
495{
496}
497
498SamplerMetadataD3D11::~SamplerMetadataD3D11()
499{
500 reset();
501}
502
503void SamplerMetadataD3D11::reset()
504{
505 mDirty = false;
506 SafeRelease(mSamplerMetadataBuffer);
507}
508
509void SamplerMetadataD3D11::initData(unsigned int samplerCount, gl::SamplerType type)
510{
511 mSamplerMetadata.resize(samplerCount);
512 mSamplerCount = samplerCount;
513 mType = type;
514}
515
516void SamplerMetadataD3D11::update(unsigned int samplerIndex, unsigned int baseLevel)
517{
518 if (mSamplerMetadata[samplerIndex].baseLevel[0] != static_cast<int>(baseLevel))
519 {
520 mSamplerMetadata[samplerIndex].baseLevel[0] = static_cast<int>(baseLevel);
521 mDirty = true;
522 }
523}
524
525bool SamplerMetadataD3D11::initBuffer(ID3D11Device *device, ID3D11DeviceContext *deviceContext)
526{
527 D3D11_BUFFER_DESC constantBufferDescription = {0};
528 d3d11::InitConstantBufferDesc(&constantBufferDescription,
529 sizeof(dx_SamplerMetadata) * mSamplerCount);
530 HRESULT result =
531 device->CreateBuffer(&constantBufferDescription, nullptr, &mSamplerMetadataBuffer);
532 ASSERT(SUCCEEDED(result));
533 if (FAILED(result))
534 {
535 return false;
536 }
537 if (mType == gl::SAMPLER_VERTEX)
538 {
539 deviceContext->VSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_SAMPLER_METADATA,
540 1, &mSamplerMetadataBuffer);
541 }
542 else
543 {
544 deviceContext->PSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_SAMPLER_METADATA,
545 1, &mSamplerMetadataBuffer);
546 }
547 mDirty = true;
548 return true;
549}
550
551gl::Error SamplerMetadataD3D11::apply(ID3D11Device *device, ID3D11DeviceContext *deviceContext)
552{
553 if (!mSamplerMetadataBuffer && mSamplerCount > 0)
554 {
555 if (!initBuffer(device, deviceContext))
556 {
557 return gl::Error(GL_OUT_OF_MEMORY, "Failed to create shader constant buffer");
558 }
559 }
560 if (mDirty)
561 {
562 ASSERT(mSamplerMetadataBuffer);
563 if (mSamplerMetadataBuffer)
564 {
565 deviceContext->UpdateSubresource(mSamplerMetadataBuffer, 0, nullptr,
566 mSamplerMetadata.data(), 16, 0);
567 mDirty = false;
568 }
569 }
570 return gl::Error(GL_NO_ERROR);
571}
572
Jamie Madill28afae52015-11-09 15:07:57 -0500573// ProgramD3D Implementation
574
Jamie Madilld3dfda22015-07-06 08:28:49 -0400575ProgramD3D::VertexExecutable::VertexExecutable(const gl::InputLayout &inputLayout,
576 const Signature &signature,
Geoff Lang359ef262015-01-05 14:42:29 -0500577 ShaderExecutableD3D *shaderExecutable)
Jamie Madill334d6152015-10-22 14:00:28 -0400578 : mInputs(inputLayout), mSignature(signature), mShaderExecutable(shaderExecutable)
Brandon Joneseb994362014-09-24 10:27:28 -0700579{
Brandon Joneseb994362014-09-24 10:27:28 -0700580}
581
582ProgramD3D::VertexExecutable::~VertexExecutable()
583{
584 SafeDelete(mShaderExecutable);
585}
586
Jamie Madilld3dfda22015-07-06 08:28:49 -0400587// static
588void ProgramD3D::VertexExecutable::getSignature(RendererD3D *renderer,
589 const gl::InputLayout &inputLayout,
590 Signature *signatureOut)
Brandon Joneseb994362014-09-24 10:27:28 -0700591{
Jamie Madillbd136f92015-08-10 14:51:37 -0400592 signatureOut->resize(inputLayout.size());
Jamie Madilld3dfda22015-07-06 08:28:49 -0400593
594 for (size_t index = 0; index < inputLayout.size(); ++index)
Brandon Joneseb994362014-09-24 10:27:28 -0700595 {
Jamie Madilld3dfda22015-07-06 08:28:49 -0400596 gl::VertexFormatType vertexFormatType = inputLayout[index];
Jamie Madillbd136f92015-08-10 14:51:37 -0400597 bool converted = false;
Jamie Madillf8dd7b12015-08-05 13:50:08 -0400598 if (vertexFormatType != gl::VERTEX_FORMAT_INVALID)
Brandon Joneseb994362014-09-24 10:27:28 -0700599 {
Jamie Madillf8dd7b12015-08-05 13:50:08 -0400600 VertexConversionType conversionType =
601 renderer->getVertexConversionType(vertexFormatType);
Jamie Madillbd136f92015-08-10 14:51:37 -0400602 converted = ((conversionType & VERTEX_CONVERT_GPU) != 0);
Brandon Joneseb994362014-09-24 10:27:28 -0700603 }
Jamie Madillbd136f92015-08-10 14:51:37 -0400604
605 (*signatureOut)[index] = converted;
Brandon Joneseb994362014-09-24 10:27:28 -0700606 }
Brandon Joneseb994362014-09-24 10:27:28 -0700607}
608
Jamie Madilld3dfda22015-07-06 08:28:49 -0400609bool ProgramD3D::VertexExecutable::matchesSignature(const Signature &signature) const
610{
Jamie Madillbd136f92015-08-10 14:51:37 -0400611 size_t limit = std::max(mSignature.size(), signature.size());
612 for (size_t index = 0; index < limit; ++index)
613 {
614 // treat undefined indexes as 'not converted'
615 bool a = index < signature.size() ? signature[index] : false;
616 bool b = index < mSignature.size() ? mSignature[index] : false;
617 if (a != b)
618 return false;
619 }
620
621 return true;
Jamie Madilld3dfda22015-07-06 08:28:49 -0400622}
623
624ProgramD3D::PixelExecutable::PixelExecutable(const std::vector<GLenum> &outputSignature,
625 ShaderExecutableD3D *shaderExecutable)
Jamie Madill334d6152015-10-22 14:00:28 -0400626 : mOutputSignature(outputSignature), mShaderExecutable(shaderExecutable)
Brandon Joneseb994362014-09-24 10:27:28 -0700627{
628}
629
630ProgramD3D::PixelExecutable::~PixelExecutable()
631{
632 SafeDelete(mShaderExecutable);
633}
634
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700635ProgramD3D::Sampler::Sampler() : active(false), logicalTextureUnit(0), textureType(GL_TEXTURE_2D)
636{
637}
638
Geoff Lang7dd2e102014-11-10 15:19:26 -0500639unsigned int ProgramD3D::mCurrentSerial = 1;
640
Jamie Madill5c6b7bf2015-08-17 12:53:35 -0400641ProgramD3D::ProgramD3D(const gl::Program::Data &data, RendererD3D *renderer)
642 : ProgramImpl(data),
Brandon Jonesc9610c52014-08-25 17:02:59 -0700643 mRenderer(renderer),
644 mDynamicHLSL(NULL),
Jamie Madill4e31ad52015-10-29 10:32:57 -0400645 mGeometryExecutables(gl::PRIMITIVE_TYPE_MAX, nullptr),
Brandon Jones44151a92014-09-10 11:32:25 -0700646 mUsesPointSize(false),
Jamie Madill3e14e2b2015-10-29 14:38:53 -0400647 mUsesFlatInterpolation(false),
Brandon Jonesc9610c52014-08-25 17:02:59 -0700648 mVertexUniformStorage(NULL),
Brandon Jones44151a92014-09-10 11:32:25 -0700649 mFragmentUniformStorage(NULL),
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700650 mUsedVertexSamplerRange(0),
651 mUsedPixelSamplerRange(0),
652 mDirtySamplerMapping(true),
Geoff Lang7dd2e102014-11-10 15:19:26 -0500653 mSerial(issueSerial())
Brandon Jonesc9610c52014-08-25 17:02:59 -0700654{
Brandon Joneseb994362014-09-24 10:27:28 -0700655 mDynamicHLSL = new DynamicHLSL(renderer);
Brandon Jonesc9610c52014-08-25 17:02:59 -0700656}
657
658ProgramD3D::~ProgramD3D()
659{
660 reset();
661 SafeDelete(mDynamicHLSL);
662}
663
Brandon Jones44151a92014-09-10 11:32:25 -0700664bool ProgramD3D::usesPointSpriteEmulation() const
665{
666 return mUsesPointSize && mRenderer->getMajorShaderModel() >= 4;
667}
668
Jamie Madill3e14e2b2015-10-29 14:38:53 -0400669bool ProgramD3D::usesGeometryShader(GLenum drawMode) const
Brandon Jones44151a92014-09-10 11:32:25 -0700670{
Jamie Madill3e14e2b2015-10-29 14:38:53 -0400671 if (drawMode != GL_POINTS)
672 {
673 return mUsesFlatInterpolation;
674 }
675
Cooper Partine6664f02015-01-09 16:22:24 -0800676 return usesPointSpriteEmulation() && !usesInstancedPointSpriteEmulation();
677}
678
679bool ProgramD3D::usesInstancedPointSpriteEmulation() const
680{
681 return mRenderer->getWorkarounds().useInstancedPointSpriteEmulation;
Brandon Jones44151a92014-09-10 11:32:25 -0700682}
683
Jamie Madill334d6152015-10-22 14:00:28 -0400684GLint ProgramD3D::getSamplerMapping(gl::SamplerType type,
685 unsigned int samplerIndex,
686 const gl::Caps &caps) const
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700687{
688 GLint logicalTextureUnit = -1;
689
690 switch (type)
691 {
Jamie Madill334d6152015-10-22 14:00:28 -0400692 case gl::SAMPLER_PIXEL:
693 ASSERT(samplerIndex < caps.maxTextureImageUnits);
694 if (samplerIndex < mSamplersPS.size() && mSamplersPS[samplerIndex].active)
695 {
696 logicalTextureUnit = mSamplersPS[samplerIndex].logicalTextureUnit;
697 }
698 break;
699 case gl::SAMPLER_VERTEX:
700 ASSERT(samplerIndex < caps.maxVertexTextureImageUnits);
701 if (samplerIndex < mSamplersVS.size() && mSamplersVS[samplerIndex].active)
702 {
703 logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit;
704 }
705 break;
706 default:
707 UNREACHABLE();
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700708 }
709
Jamie Madill334d6152015-10-22 14:00:28 -0400710 if (logicalTextureUnit >= 0 &&
711 logicalTextureUnit < static_cast<GLint>(caps.maxCombinedTextureImageUnits))
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700712 {
713 return logicalTextureUnit;
714 }
715
716 return -1;
717}
718
719// Returns the texture type for a given Direct3D 9 sampler type and
720// index (0-15 for the pixel shader and 0-3 for the vertex shader).
721GLenum ProgramD3D::getSamplerTextureType(gl::SamplerType type, unsigned int samplerIndex) const
722{
723 switch (type)
724 {
Jamie Madill334d6152015-10-22 14:00:28 -0400725 case gl::SAMPLER_PIXEL:
726 ASSERT(samplerIndex < mSamplersPS.size());
727 ASSERT(mSamplersPS[samplerIndex].active);
728 return mSamplersPS[samplerIndex].textureType;
729 case gl::SAMPLER_VERTEX:
730 ASSERT(samplerIndex < mSamplersVS.size());
731 ASSERT(mSamplersVS[samplerIndex].active);
732 return mSamplersVS[samplerIndex].textureType;
733 default:
734 UNREACHABLE();
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700735 }
736
737 return GL_TEXTURE_2D;
738}
739
Olli Etuaho30268292016-01-15 16:40:00 +0200740void ProgramD3D::setSamplerMetadata(gl::SamplerType type,
741 unsigned int samplerIndex,
742 unsigned int baseLevel)
743{
744 SamplerMetadataD3D11 *metadata = nullptr;
745 switch (type)
746 {
747 case gl::SAMPLER_PIXEL:
748 metadata = &mSamplerMetadataPS;
749 break;
750 case gl::SAMPLER_VERTEX:
751 metadata = &mSamplerMetadataVS;
752 break;
753 default:
754 UNREACHABLE();
755 break;
756 }
757 ASSERT(metadata != nullptr);
758 ASSERT(samplerIndex < getUsedSamplerRange(type));
759 metadata->update(samplerIndex, baseLevel);
760}
761
762GLuint ProgramD3D::getUsedSamplerRange(gl::SamplerType type) const
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700763{
764 switch (type)
765 {
Jamie Madill334d6152015-10-22 14:00:28 -0400766 case gl::SAMPLER_PIXEL:
767 return mUsedPixelSamplerRange;
768 case gl::SAMPLER_VERTEX:
769 return mUsedVertexSamplerRange;
770 default:
771 UNREACHABLE();
Olli Etuaho30268292016-01-15 16:40:00 +0200772 return 0u;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700773 }
774}
775
776void ProgramD3D::updateSamplerMapping()
777{
778 if (!mDirtySamplerMapping)
779 {
780 return;
781 }
782
783 mDirtySamplerMapping = false;
784
785 // Retrieve sampler uniform values
Jamie Madill62d31cb2015-09-11 13:25:51 -0400786 for (const D3DUniform *d3dUniform : mD3DUniforms)
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700787 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400788 if (!d3dUniform->dirty)
789 continue;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700790
Jamie Madill62d31cb2015-09-11 13:25:51 -0400791 if (!d3dUniform->isSampler())
792 continue;
793
794 int count = d3dUniform->elementCount();
795 const GLint(*v)[4] = reinterpret_cast<const GLint(*)[4]>(d3dUniform->data);
796
797 if (d3dUniform->isReferencedByFragmentShader())
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700798 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400799 unsigned int firstIndex = d3dUniform->psRegisterIndex;
800
801 for (int i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700802 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400803 unsigned int samplerIndex = firstIndex + i;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700804
Jamie Madill62d31cb2015-09-11 13:25:51 -0400805 if (samplerIndex < mSamplersPS.size())
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700806 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400807 ASSERT(mSamplersPS[samplerIndex].active);
808 mSamplersPS[samplerIndex].logicalTextureUnit = v[i][0];
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700809 }
Jamie Madill62d31cb2015-09-11 13:25:51 -0400810 }
811 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700812
Jamie Madill62d31cb2015-09-11 13:25:51 -0400813 if (d3dUniform->isReferencedByVertexShader())
814 {
815 unsigned int firstIndex = d3dUniform->vsRegisterIndex;
816
817 for (int i = 0; i < count; i++)
818 {
819 unsigned int samplerIndex = firstIndex + i;
820
821 if (samplerIndex < mSamplersVS.size())
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700822 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400823 ASSERT(mSamplersVS[samplerIndex].active);
824 mSamplersVS[samplerIndex].logicalTextureUnit = v[i][0];
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700825 }
826 }
827 }
828 }
829}
830
Geoff Lang7dd2e102014-11-10 15:19:26 -0500831LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
Brandon Jones22502d52014-08-29 16:58:36 -0700832{
Jamie Madill62d31cb2015-09-11 13:25:51 -0400833 reset();
834
Jamie Madill334d6152015-10-22 14:00:28 -0400835 DeviceIdentifier binaryDeviceIdentifier = {0};
836 stream->readBytes(reinterpret_cast<unsigned char *>(&binaryDeviceIdentifier),
837 sizeof(DeviceIdentifier));
Austin Kinross137b1512015-06-17 16:14:53 -0700838
839 DeviceIdentifier identifier = mRenderer->getAdapterIdentifier();
840 if (memcmp(&identifier, &binaryDeviceIdentifier, sizeof(DeviceIdentifier)) != 0)
841 {
842 infoLog << "Invalid program binary, device configuration has changed.";
843 return LinkResult(false, gl::Error(GL_NO_ERROR));
844 }
845
Jamie Madill2db1fbb2014-12-03 10:58:55 -0500846 int compileFlags = stream->readInt<int>();
847 if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL)
848 {
Jamie Madillf6113162015-05-07 11:49:21 -0400849 infoLog << "Mismatched compilation flags.";
Jamie Madill2db1fbb2014-12-03 10:58:55 -0500850 return LinkResult(false, gl::Error(GL_NO_ERROR));
851 }
852
Jamie Madill63805b42015-08-25 13:17:39 -0400853 // TODO(jmadill): replace MAX_VERTEX_ATTRIBS
854 for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; ++i)
855 {
856 stream->readInt(&mSemanticIndexes[i]);
857 }
858
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700859 const unsigned int psSamplerCount = stream->readInt<unsigned int>();
860 for (unsigned int i = 0; i < psSamplerCount; ++i)
861 {
862 Sampler sampler;
863 stream->readBool(&sampler.active);
864 stream->readInt(&sampler.logicalTextureUnit);
865 stream->readInt(&sampler.textureType);
866 mSamplersPS.push_back(sampler);
867 }
868 const unsigned int vsSamplerCount = stream->readInt<unsigned int>();
869 for (unsigned int i = 0; i < vsSamplerCount; ++i)
870 {
871 Sampler sampler;
872 stream->readBool(&sampler.active);
873 stream->readInt(&sampler.logicalTextureUnit);
874 stream->readInt(&sampler.textureType);
875 mSamplersVS.push_back(sampler);
876 }
877
878 stream->readInt(&mUsedVertexSamplerRange);
879 stream->readInt(&mUsedPixelSamplerRange);
880
881 const unsigned int uniformCount = stream->readInt<unsigned int>();
882 if (stream->error())
883 {
Jamie Madillf6113162015-05-07 11:49:21 -0400884 infoLog << "Invalid program binary.";
Geoff Lang7dd2e102014-11-10 15:19:26 -0500885 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700886 }
887
Jamie Madill62d31cb2015-09-11 13:25:51 -0400888 const auto &linkedUniforms = mData.getUniforms();
889 ASSERT(mD3DUniforms.empty());
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700890 for (unsigned int uniformIndex = 0; uniformIndex < uniformCount; uniformIndex++)
891 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400892 const gl::LinkedUniform &linkedUniform = linkedUniforms[uniformIndex];
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700893
Jamie Madill62d31cb2015-09-11 13:25:51 -0400894 D3DUniform *d3dUniform =
895 new D3DUniform(linkedUniform.type, linkedUniform.name, linkedUniform.arraySize,
896 linkedUniform.isInDefaultBlock());
897 stream->readInt(&d3dUniform->psRegisterIndex);
898 stream->readInt(&d3dUniform->vsRegisterIndex);
899 stream->readInt(&d3dUniform->registerCount);
900 stream->readInt(&d3dUniform->registerElement);
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700901
Jamie Madill62d31cb2015-09-11 13:25:51 -0400902 mD3DUniforms.push_back(d3dUniform);
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700903 }
904
Jamie Madill4a3c2342015-10-08 12:58:45 -0400905 const unsigned int blockCount = stream->readInt<unsigned int>();
906 if (stream->error())
907 {
908 infoLog << "Invalid program binary.";
909 return LinkResult(false, gl::Error(GL_NO_ERROR));
910 }
911
912 ASSERT(mD3DUniformBlocks.empty());
913 for (unsigned int blockIndex = 0; blockIndex < blockCount; ++blockIndex)
914 {
915 D3DUniformBlock uniformBlock;
916 stream->readInt(&uniformBlock.psRegisterIndex);
917 stream->readInt(&uniformBlock.vsRegisterIndex);
918 mD3DUniformBlocks.push_back(uniformBlock);
919 }
920
Jamie Madill9fc36822015-11-18 13:08:07 -0500921 const unsigned int streamOutVaryingCount = stream->readInt<unsigned int>();
922 mStreamOutVaryings.resize(streamOutVaryingCount);
923 for (unsigned int varyingIndex = 0; varyingIndex < streamOutVaryingCount; ++varyingIndex)
Brandon Joneseb994362014-09-24 10:27:28 -0700924 {
Jamie Madill9fc36822015-11-18 13:08:07 -0500925 D3DVarying *varying = &mStreamOutVaryings[varyingIndex];
Brandon Joneseb994362014-09-24 10:27:28 -0700926
Jamie Madill28afae52015-11-09 15:07:57 -0500927 stream->readString(&varying->semanticName);
928 stream->readInt(&varying->semanticIndex);
Jamie Madill9fc36822015-11-18 13:08:07 -0500929 stream->readInt(&varying->componentCount);
930 stream->readInt(&varying->outputSlot);
Brandon Joneseb994362014-09-24 10:27:28 -0700931 }
932
Brandon Jones22502d52014-08-29 16:58:36 -0700933 stream->readString(&mVertexHLSL);
Jamie Madill334d6152015-10-22 14:00:28 -0400934 stream->readBytes(reinterpret_cast<unsigned char *>(&mVertexWorkarounds),
935 sizeof(D3DCompilerWorkarounds));
Brandon Jones22502d52014-08-29 16:58:36 -0700936 stream->readString(&mPixelHLSL);
Jamie Madill334d6152015-10-22 14:00:28 -0400937 stream->readBytes(reinterpret_cast<unsigned char *>(&mPixelWorkarounds),
938 sizeof(D3DCompilerWorkarounds));
Brandon Jones22502d52014-08-29 16:58:36 -0700939 stream->readBool(&mUsesFragDepth);
Brandon Jones44151a92014-09-10 11:32:25 -0700940 stream->readBool(&mUsesPointSize);
Jamie Madill3e14e2b2015-10-29 14:38:53 -0400941 stream->readBool(&mUsesFlatInterpolation);
Brandon Jones22502d52014-08-29 16:58:36 -0700942
943 const size_t pixelShaderKeySize = stream->readInt<unsigned int>();
944 mPixelShaderKey.resize(pixelShaderKeySize);
Jamie Madill334d6152015-10-22 14:00:28 -0400945 for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKeySize;
946 pixelShaderKeyIndex++)
Brandon Jones22502d52014-08-29 16:58:36 -0700947 {
948 stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].type);
949 stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].name);
950 stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].source);
951 stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].outputIndex);
952 }
953
Jamie Madill4e31ad52015-10-29 10:32:57 -0400954 stream->readString(&mGeometryShaderPreamble);
955
Jamie Madill334d6152015-10-22 14:00:28 -0400956 const unsigned char *binary = reinterpret_cast<const unsigned char *>(stream->data());
Brandon Joneseb994362014-09-24 10:27:28 -0700957
958 const unsigned int vertexShaderCount = stream->readInt<unsigned int>();
Jamie Madill334d6152015-10-22 14:00:28 -0400959 for (unsigned int vertexShaderIndex = 0; vertexShaderIndex < vertexShaderCount;
960 vertexShaderIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -0700961 {
Jamie Madilld3dfda22015-07-06 08:28:49 -0400962 size_t inputLayoutSize = stream->readInt<size_t>();
Jamie Madillf8dd7b12015-08-05 13:50:08 -0400963 gl::InputLayout inputLayout(inputLayoutSize, gl::VERTEX_FORMAT_INVALID);
Brandon Joneseb994362014-09-24 10:27:28 -0700964
Jamie Madilld3dfda22015-07-06 08:28:49 -0400965 for (size_t inputIndex = 0; inputIndex < inputLayoutSize; inputIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -0700966 {
Jamie Madillf8dd7b12015-08-05 13:50:08 -0400967 inputLayout[inputIndex] = stream->readInt<gl::VertexFormatType>();
Brandon Joneseb994362014-09-24 10:27:28 -0700968 }
969
Jamie Madill334d6152015-10-22 14:00:28 -0400970 unsigned int vertexShaderSize = stream->readInt<unsigned int>();
Brandon Joneseb994362014-09-24 10:27:28 -0700971 const unsigned char *vertexShaderFunction = binary + stream->offset();
Geoff Langb543aff2014-09-30 14:52:54 -0400972
Jamie Madillada9ecc2015-08-17 12:53:37 -0400973 ShaderExecutableD3D *shaderExecutable = nullptr;
974
975 gl::Error error = mRenderer->loadExecutable(
Jamie Madill9fc36822015-11-18 13:08:07 -0500976 vertexShaderFunction, vertexShaderSize, SHADER_VERTEX, mStreamOutVaryings,
Jamie Madillada9ecc2015-08-17 12:53:37 -0400977 (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), &shaderExecutable);
Geoff Langb543aff2014-09-30 14:52:54 -0400978 if (error.isError())
979 {
Geoff Lang7dd2e102014-11-10 15:19:26 -0500980 return LinkResult(false, error);
Geoff Langb543aff2014-09-30 14:52:54 -0400981 }
982
Brandon Joneseb994362014-09-24 10:27:28 -0700983 if (!shaderExecutable)
984 {
Jamie Madillf6113162015-05-07 11:49:21 -0400985 infoLog << "Could not create vertex shader.";
Geoff Lang7dd2e102014-11-10 15:19:26 -0500986 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Joneseb994362014-09-24 10:27:28 -0700987 }
988
989 // generated converted input layout
Jamie Madilld3dfda22015-07-06 08:28:49 -0400990 VertexExecutable::Signature signature;
991 VertexExecutable::getSignature(mRenderer, inputLayout, &signature);
Brandon Joneseb994362014-09-24 10:27:28 -0700992
993 // add new binary
Jamie Madill334d6152015-10-22 14:00:28 -0400994 mVertexExecutables.push_back(
995 new VertexExecutable(inputLayout, signature, shaderExecutable));
Brandon Joneseb994362014-09-24 10:27:28 -0700996
997 stream->skip(vertexShaderSize);
998 }
999
1000 const size_t pixelShaderCount = stream->readInt<unsigned int>();
1001 for (size_t pixelShaderIndex = 0; pixelShaderIndex < pixelShaderCount; pixelShaderIndex++)
1002 {
1003 const size_t outputCount = stream->readInt<unsigned int>();
1004 std::vector<GLenum> outputs(outputCount);
1005 for (size_t outputIndex = 0; outputIndex < outputCount; outputIndex++)
1006 {
1007 stream->readInt(&outputs[outputIndex]);
1008 }
1009
Jamie Madill334d6152015-10-22 14:00:28 -04001010 const size_t pixelShaderSize = stream->readInt<unsigned int>();
Brandon Joneseb994362014-09-24 10:27:28 -07001011 const unsigned char *pixelShaderFunction = binary + stream->offset();
Jamie Madillada9ecc2015-08-17 12:53:37 -04001012 ShaderExecutableD3D *shaderExecutable = nullptr;
1013
1014 gl::Error error = mRenderer->loadExecutable(
Jamie Madill9fc36822015-11-18 13:08:07 -05001015 pixelShaderFunction, pixelShaderSize, SHADER_PIXEL, mStreamOutVaryings,
Jamie Madillada9ecc2015-08-17 12:53:37 -04001016 (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), &shaderExecutable);
Geoff Langb543aff2014-09-30 14:52:54 -04001017 if (error.isError())
1018 {
Geoff Lang7dd2e102014-11-10 15:19:26 -05001019 return LinkResult(false, error);
Geoff Langb543aff2014-09-30 14:52:54 -04001020 }
Brandon Joneseb994362014-09-24 10:27:28 -07001021
1022 if (!shaderExecutable)
1023 {
Jamie Madillf6113162015-05-07 11:49:21 -04001024 infoLog << "Could not create pixel shader.";
Geoff Lang7dd2e102014-11-10 15:19:26 -05001025 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Joneseb994362014-09-24 10:27:28 -07001026 }
1027
1028 // add new binary
1029 mPixelExecutables.push_back(new PixelExecutable(outputs, shaderExecutable));
1030
1031 stream->skip(pixelShaderSize);
1032 }
1033
Jamie Madill4e31ad52015-10-29 10:32:57 -04001034 for (unsigned int geometryExeIndex = 0; geometryExeIndex < gl::PRIMITIVE_TYPE_MAX;
1035 ++geometryExeIndex)
Brandon Joneseb994362014-09-24 10:27:28 -07001036 {
Jamie Madill4e31ad52015-10-29 10:32:57 -04001037 unsigned int geometryShaderSize = stream->readInt<unsigned int>();
1038 if (geometryShaderSize == 0)
1039 {
1040 mGeometryExecutables[geometryExeIndex] = nullptr;
1041 continue;
1042 }
1043
Brandon Joneseb994362014-09-24 10:27:28 -07001044 const unsigned char *geometryShaderFunction = binary + stream->offset();
Jamie Madill4e31ad52015-10-29 10:32:57 -04001045 bool splitAttribs = (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS);
1046
Jamie Madill28afae52015-11-09 15:07:57 -05001047 gl::Error error = mRenderer->loadExecutable(
Jamie Madill9fc36822015-11-18 13:08:07 -05001048 geometryShaderFunction, geometryShaderSize, SHADER_GEOMETRY, mStreamOutVaryings,
1049 splitAttribs, &mGeometryExecutables[geometryExeIndex]);
Geoff Langb543aff2014-09-30 14:52:54 -04001050 if (error.isError())
1051 {
Geoff Lang7dd2e102014-11-10 15:19:26 -05001052 return LinkResult(false, error);
Geoff Langb543aff2014-09-30 14:52:54 -04001053 }
Brandon Joneseb994362014-09-24 10:27:28 -07001054
Jamie Madill4e31ad52015-10-29 10:32:57 -04001055 if (!mGeometryExecutables[geometryExeIndex])
Brandon Joneseb994362014-09-24 10:27:28 -07001056 {
Jamie Madillf6113162015-05-07 11:49:21 -04001057 infoLog << "Could not create geometry shader.";
Geoff Lang7dd2e102014-11-10 15:19:26 -05001058 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Joneseb994362014-09-24 10:27:28 -07001059 }
1060 stream->skip(geometryShaderSize);
1061 }
1062
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001063 initializeUniformStorage();
Jamie Madill437d2662014-12-05 14:23:35 -05001064 initAttributesByLayout();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001065
Olli Etuaho30268292016-01-15 16:40:00 +02001066 mSamplerMetadataPS.initData(getUsedSamplerRange(gl::SAMPLER_PIXEL), gl::SAMPLER_PIXEL);
1067 mSamplerMetadataVS.initData(getUsedSamplerRange(gl::SAMPLER_VERTEX), gl::SAMPLER_VERTEX);
1068
Geoff Lang7dd2e102014-11-10 15:19:26 -05001069 return LinkResult(true, gl::Error(GL_NO_ERROR));
Brandon Jones22502d52014-08-29 16:58:36 -07001070}
1071
Geoff Langb543aff2014-09-30 14:52:54 -04001072gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream)
Brandon Jones22502d52014-08-29 16:58:36 -07001073{
Austin Kinross137b1512015-06-17 16:14:53 -07001074 // Output the DeviceIdentifier before we output any shader code
Jamie Madill334d6152015-10-22 14:00:28 -04001075 // When we load the binary again later, we can validate the device identifier before trying to
1076 // compile any HLSL
Austin Kinross137b1512015-06-17 16:14:53 -07001077 DeviceIdentifier binaryIdentifier = mRenderer->getAdapterIdentifier();
Jamie Madill334d6152015-10-22 14:00:28 -04001078 stream->writeBytes(reinterpret_cast<unsigned char *>(&binaryIdentifier),
1079 sizeof(DeviceIdentifier));
Austin Kinross137b1512015-06-17 16:14:53 -07001080
Jamie Madill2db1fbb2014-12-03 10:58:55 -05001081 stream->writeInt(ANGLE_COMPILE_OPTIMIZATION_LEVEL);
1082
Jamie Madill63805b42015-08-25 13:17:39 -04001083 // TODO(jmadill): replace MAX_VERTEX_ATTRIBS
1084 for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; ++i)
1085 {
1086 stream->writeInt(mSemanticIndexes[i]);
1087 }
1088
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001089 stream->writeInt(mSamplersPS.size());
1090 for (unsigned int i = 0; i < mSamplersPS.size(); ++i)
1091 {
1092 stream->writeInt(mSamplersPS[i].active);
1093 stream->writeInt(mSamplersPS[i].logicalTextureUnit);
1094 stream->writeInt(mSamplersPS[i].textureType);
1095 }
1096
1097 stream->writeInt(mSamplersVS.size());
1098 for (unsigned int i = 0; i < mSamplersVS.size(); ++i)
1099 {
1100 stream->writeInt(mSamplersVS[i].active);
1101 stream->writeInt(mSamplersVS[i].logicalTextureUnit);
1102 stream->writeInt(mSamplersVS[i].textureType);
1103 }
1104
1105 stream->writeInt(mUsedVertexSamplerRange);
1106 stream->writeInt(mUsedPixelSamplerRange);
1107
Jamie Madill62d31cb2015-09-11 13:25:51 -04001108 stream->writeInt(mD3DUniforms.size());
Jamie Madill4a3c2342015-10-08 12:58:45 -04001109 for (const D3DUniform *uniform : mD3DUniforms)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001110 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001111 // Type, name and arraySize are redundant, so aren't stored in the binary.
Jamie Madill4a3c2342015-10-08 12:58:45 -04001112 stream->writeInt(uniform->psRegisterIndex);
1113 stream->writeInt(uniform->vsRegisterIndex);
1114 stream->writeInt(uniform->registerCount);
1115 stream->writeInt(uniform->registerElement);
1116 }
1117
1118 stream->writeInt(mD3DUniformBlocks.size());
1119 for (const D3DUniformBlock &uniformBlock : mD3DUniformBlocks)
1120 {
1121 stream->writeInt(uniformBlock.psRegisterIndex);
1122 stream->writeInt(uniformBlock.vsRegisterIndex);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001123 }
1124
Jamie Madill9fc36822015-11-18 13:08:07 -05001125 stream->writeInt(mStreamOutVaryings.size());
1126 for (const auto &varying : mStreamOutVaryings)
Brandon Joneseb994362014-09-24 10:27:28 -07001127 {
Brandon Joneseb994362014-09-24 10:27:28 -07001128 stream->writeString(varying.semanticName);
1129 stream->writeInt(varying.semanticIndex);
Jamie Madill9fc36822015-11-18 13:08:07 -05001130 stream->writeInt(varying.componentCount);
1131 stream->writeInt(varying.outputSlot);
Brandon Joneseb994362014-09-24 10:27:28 -07001132 }
1133
Brandon Jones22502d52014-08-29 16:58:36 -07001134 stream->writeString(mVertexHLSL);
Jamie Madill334d6152015-10-22 14:00:28 -04001135 stream->writeBytes(reinterpret_cast<unsigned char *>(&mVertexWorkarounds),
1136 sizeof(D3DCompilerWorkarounds));
Brandon Jones22502d52014-08-29 16:58:36 -07001137 stream->writeString(mPixelHLSL);
Jamie Madill334d6152015-10-22 14:00:28 -04001138 stream->writeBytes(reinterpret_cast<unsigned char *>(&mPixelWorkarounds),
1139 sizeof(D3DCompilerWorkarounds));
Brandon Jones22502d52014-08-29 16:58:36 -07001140 stream->writeInt(mUsesFragDepth);
Brandon Jones44151a92014-09-10 11:32:25 -07001141 stream->writeInt(mUsesPointSize);
Jamie Madill3e14e2b2015-10-29 14:38:53 -04001142 stream->writeInt(mUsesFlatInterpolation);
Brandon Jones22502d52014-08-29 16:58:36 -07001143
Brandon Joneseb994362014-09-24 10:27:28 -07001144 const std::vector<PixelShaderOutputVariable> &pixelShaderKey = mPixelShaderKey;
Brandon Jones22502d52014-08-29 16:58:36 -07001145 stream->writeInt(pixelShaderKey.size());
Jamie Madill334d6152015-10-22 14:00:28 -04001146 for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKey.size();
1147 pixelShaderKeyIndex++)
Brandon Jones22502d52014-08-29 16:58:36 -07001148 {
Brandon Joneseb994362014-09-24 10:27:28 -07001149 const PixelShaderOutputVariable &variable = pixelShaderKey[pixelShaderKeyIndex];
Brandon Jones22502d52014-08-29 16:58:36 -07001150 stream->writeInt(variable.type);
1151 stream->writeString(variable.name);
1152 stream->writeString(variable.source);
1153 stream->writeInt(variable.outputIndex);
1154 }
1155
Jamie Madill4e31ad52015-10-29 10:32:57 -04001156 stream->writeString(mGeometryShaderPreamble);
1157
Brandon Joneseb994362014-09-24 10:27:28 -07001158 stream->writeInt(mVertexExecutables.size());
Jamie Madill334d6152015-10-22 14:00:28 -04001159 for (size_t vertexExecutableIndex = 0; vertexExecutableIndex < mVertexExecutables.size();
1160 vertexExecutableIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -07001161 {
1162 VertexExecutable *vertexExecutable = mVertexExecutables[vertexExecutableIndex];
1163
Jamie Madilld3dfda22015-07-06 08:28:49 -04001164 const auto &inputLayout = vertexExecutable->inputs();
1165 stream->writeInt(inputLayout.size());
1166
1167 for (size_t inputIndex = 0; inputIndex < inputLayout.size(); inputIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -07001168 {
Jamie Madilld3dfda22015-07-06 08:28:49 -04001169 stream->writeInt(inputLayout[inputIndex]);
Brandon Joneseb994362014-09-24 10:27:28 -07001170 }
1171
1172 size_t vertexShaderSize = vertexExecutable->shaderExecutable()->getLength();
1173 stream->writeInt(vertexShaderSize);
1174
1175 const uint8_t *vertexBlob = vertexExecutable->shaderExecutable()->getFunction();
1176 stream->writeBytes(vertexBlob, vertexShaderSize);
1177 }
1178
1179 stream->writeInt(mPixelExecutables.size());
Jamie Madill334d6152015-10-22 14:00:28 -04001180 for (size_t pixelExecutableIndex = 0; pixelExecutableIndex < mPixelExecutables.size();
1181 pixelExecutableIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -07001182 {
1183 PixelExecutable *pixelExecutable = mPixelExecutables[pixelExecutableIndex];
1184
1185 const std::vector<GLenum> outputs = pixelExecutable->outputSignature();
1186 stream->writeInt(outputs.size());
1187 for (size_t outputIndex = 0; outputIndex < outputs.size(); outputIndex++)
1188 {
1189 stream->writeInt(outputs[outputIndex]);
1190 }
1191
1192 size_t pixelShaderSize = pixelExecutable->shaderExecutable()->getLength();
1193 stream->writeInt(pixelShaderSize);
1194
1195 const uint8_t *pixelBlob = pixelExecutable->shaderExecutable()->getFunction();
1196 stream->writeBytes(pixelBlob, pixelShaderSize);
1197 }
1198
Jamie Madill4e31ad52015-10-29 10:32:57 -04001199 for (const ShaderExecutableD3D *geometryExe : mGeometryExecutables)
Brandon Joneseb994362014-09-24 10:27:28 -07001200 {
Jamie Madill4e31ad52015-10-29 10:32:57 -04001201 if (geometryExe == nullptr)
1202 {
1203 stream->writeInt(0);
1204 continue;
1205 }
1206
1207 size_t geometryShaderSize = geometryExe->getLength();
1208 stream->writeInt(geometryShaderSize);
1209 stream->writeBytes(geometryExe->getFunction(), geometryShaderSize);
Brandon Joneseb994362014-09-24 10:27:28 -07001210 }
1211
Geoff Langb543aff2014-09-30 14:52:54 -04001212 return gl::Error(GL_NO_ERROR);
Brandon Jones22502d52014-08-29 16:58:36 -07001213}
1214
Geoff Langc5629752015-12-07 16:29:04 -05001215void ProgramD3D::setBinaryRetrievableHint(bool /* retrievable */)
1216{
1217}
1218
Jamie Madill334d6152015-10-22 14:00:28 -04001219gl::Error ProgramD3D::getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo,
1220 ShaderExecutableD3D **outExecutable)
Brandon Jones22502d52014-08-29 16:58:36 -07001221{
Geoff Lang7a26a1a2015-03-25 12:29:06 -04001222 mPixelShaderOutputFormatCache.clear();
Brandon Joneseb994362014-09-24 10:27:28 -07001223
Jamie Madill85a18042015-03-05 15:41:41 -05001224 const FramebufferD3D *fboD3D = GetImplAs<FramebufferD3D>(fbo);
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001225 const gl::AttachmentList &colorbuffers = fboD3D->getColorAttachmentsForRender();
Brandon Joneseb994362014-09-24 10:27:28 -07001226
1227 for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment)
1228 {
1229 const gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment];
1230
1231 if (colorbuffer)
1232 {
Jamie Madill334d6152015-10-22 14:00:28 -04001233 mPixelShaderOutputFormatCache.push_back(colorbuffer->getBinding() == GL_BACK
1234 ? GL_COLOR_ATTACHMENT0
1235 : colorbuffer->getBinding());
Brandon Joneseb994362014-09-24 10:27:28 -07001236 }
1237 else
1238 {
Geoff Lang7a26a1a2015-03-25 12:29:06 -04001239 mPixelShaderOutputFormatCache.push_back(GL_NONE);
Brandon Joneseb994362014-09-24 10:27:28 -07001240 }
1241 }
1242
Geoff Lang7a26a1a2015-03-25 12:29:06 -04001243 return getPixelExecutableForOutputLayout(mPixelShaderOutputFormatCache, outExecutable, nullptr);
Brandon Joneseb994362014-09-24 10:27:28 -07001244}
1245
Jamie Madill97399232014-12-23 12:31:15 -05001246gl::Error ProgramD3D::getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputSignature,
Geoff Lang359ef262015-01-05 14:42:29 -05001247 ShaderExecutableD3D **outExectuable,
Jamie Madill97399232014-12-23 12:31:15 -05001248 gl::InfoLog *infoLog)
Brandon Joneseb994362014-09-24 10:27:28 -07001249{
1250 for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++)
1251 {
1252 if (mPixelExecutables[executableIndex]->matchesSignature(outputSignature))
1253 {
Geoff Langb543aff2014-09-30 14:52:54 -04001254 *outExectuable = mPixelExecutables[executableIndex]->shaderExecutable();
1255 return gl::Error(GL_NO_ERROR);
Brandon Joneseb994362014-09-24 10:27:28 -07001256 }
1257 }
1258
Jamie Madill334d6152015-10-22 14:00:28 -04001259 std::string finalPixelHLSL = mDynamicHLSL->generatePixelShaderForOutputSignature(
1260 mPixelHLSL, mPixelShaderKey, mUsesFragDepth, outputSignature);
Brandon Jones22502d52014-08-29 16:58:36 -07001261
1262 // Generate new pixel executable
Geoff Lang359ef262015-01-05 14:42:29 -05001263 ShaderExecutableD3D *pixelExecutable = NULL;
Jamie Madill97399232014-12-23 12:31:15 -05001264
1265 gl::InfoLog tempInfoLog;
1266 gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
1267
Jamie Madillada9ecc2015-08-17 12:53:37 -04001268 gl::Error error = mRenderer->compileToExecutable(
Jamie Madill9fc36822015-11-18 13:08:07 -05001269 *currentInfoLog, finalPixelHLSL, SHADER_PIXEL, mStreamOutVaryings,
Jamie Madillada9ecc2015-08-17 12:53:37 -04001270 (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), mPixelWorkarounds,
1271 &pixelExecutable);
Geoff Langb543aff2014-09-30 14:52:54 -04001272 if (error.isError())
1273 {
1274 return error;
1275 }
Brandon Joneseb994362014-09-24 10:27:28 -07001276
Jamie Madill97399232014-12-23 12:31:15 -05001277 if (pixelExecutable)
1278 {
1279 mPixelExecutables.push_back(new PixelExecutable(outputSignature, pixelExecutable));
1280 }
1281 else if (!infoLog)
Brandon Joneseb994362014-09-24 10:27:28 -07001282 {
1283 std::vector<char> tempCharBuffer(tempInfoLog.getLength() + 3);
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001284 tempInfoLog.getLog(static_cast<GLsizei>(tempInfoLog.getLength()), NULL, &tempCharBuffer[0]);
Brandon Joneseb994362014-09-24 10:27:28 -07001285 ERR("Error compiling dynamic pixel executable:\n%s\n", &tempCharBuffer[0]);
1286 }
Brandon Jones22502d52014-08-29 16:58:36 -07001287
Geoff Langb543aff2014-09-30 14:52:54 -04001288 *outExectuable = pixelExecutable;
1289 return gl::Error(GL_NO_ERROR);
Brandon Jones22502d52014-08-29 16:58:36 -07001290}
1291
Jamie Madilld3dfda22015-07-06 08:28:49 -04001292gl::Error ProgramD3D::getVertexExecutableForInputLayout(const gl::InputLayout &inputLayout,
Geoff Lang359ef262015-01-05 14:42:29 -05001293 ShaderExecutableD3D **outExectuable,
Jamie Madill97399232014-12-23 12:31:15 -05001294 gl::InfoLog *infoLog)
Brandon Jones22502d52014-08-29 16:58:36 -07001295{
Jamie Madilld3dfda22015-07-06 08:28:49 -04001296 VertexExecutable::getSignature(mRenderer, inputLayout, &mCachedVertexSignature);
Brandon Joneseb994362014-09-24 10:27:28 -07001297
1298 for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++)
1299 {
Jamie Madilld3dfda22015-07-06 08:28:49 -04001300 if (mVertexExecutables[executableIndex]->matchesSignature(mCachedVertexSignature))
Brandon Joneseb994362014-09-24 10:27:28 -07001301 {
Geoff Langb543aff2014-09-30 14:52:54 -04001302 *outExectuable = mVertexExecutables[executableIndex]->shaderExecutable();
1303 return gl::Error(GL_NO_ERROR);
Brandon Joneseb994362014-09-24 10:27:28 -07001304 }
1305 }
1306
Brandon Jones22502d52014-08-29 16:58:36 -07001307 // Generate new dynamic layout with attribute conversions
Jamie Madillc349ec02015-08-21 16:53:12 -04001308 std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout(
1309 mVertexHLSL, inputLayout, mData.getAttributes());
Brandon Jones22502d52014-08-29 16:58:36 -07001310
1311 // Generate new vertex executable
Geoff Lang359ef262015-01-05 14:42:29 -05001312 ShaderExecutableD3D *vertexExecutable = NULL;
Jamie Madill97399232014-12-23 12:31:15 -05001313
1314 gl::InfoLog tempInfoLog;
1315 gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
1316
Jamie Madillada9ecc2015-08-17 12:53:37 -04001317 gl::Error error = mRenderer->compileToExecutable(
Jamie Madill9fc36822015-11-18 13:08:07 -05001318 *currentInfoLog, finalVertexHLSL, SHADER_VERTEX, mStreamOutVaryings,
Jamie Madillada9ecc2015-08-17 12:53:37 -04001319 (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), mVertexWorkarounds,
1320 &vertexExecutable);
Geoff Langb543aff2014-09-30 14:52:54 -04001321 if (error.isError())
1322 {
1323 return error;
1324 }
1325
Jamie Madill97399232014-12-23 12:31:15 -05001326 if (vertexExecutable)
Brandon Joneseb994362014-09-24 10:27:28 -07001327 {
Jamie Madill334d6152015-10-22 14:00:28 -04001328 mVertexExecutables.push_back(
1329 new VertexExecutable(inputLayout, mCachedVertexSignature, vertexExecutable));
Brandon Joneseb994362014-09-24 10:27:28 -07001330 }
Jamie Madill97399232014-12-23 12:31:15 -05001331 else if (!infoLog)
1332 {
1333 std::vector<char> tempCharBuffer(tempInfoLog.getLength() + 3);
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001334 tempInfoLog.getLog(static_cast<GLsizei>(tempInfoLog.getLength()), NULL, &tempCharBuffer[0]);
Jamie Madill97399232014-12-23 12:31:15 -05001335 ERR("Error compiling dynamic vertex executable:\n%s\n", &tempCharBuffer[0]);
1336 }
Brandon Jones22502d52014-08-29 16:58:36 -07001337
Geoff Langb543aff2014-09-30 14:52:54 -04001338 *outExectuable = vertexExecutable;
1339 return gl::Error(GL_NO_ERROR);
Brandon Jones22502d52014-08-29 16:58:36 -07001340}
1341
Jamie Madill4e31ad52015-10-29 10:32:57 -04001342gl::Error ProgramD3D::getGeometryExecutableForPrimitiveType(const gl::Data &data,
1343 GLenum drawMode,
1344 ShaderExecutableD3D **outExecutable,
1345 gl::InfoLog *infoLog)
1346{
Jamie Madill3e14e2b2015-10-29 14:38:53 -04001347 if (outExecutable)
1348 {
1349 *outExecutable = nullptr;
1350 }
1351
Austin Kinross88829e82016-01-12 13:04:41 -08001352 // Return a null shader if the current rendering doesn't use a geometry shader
1353 if (!usesGeometryShader(drawMode))
Jamie Madill3e14e2b2015-10-29 14:38:53 -04001354 {
1355 return gl::Error(GL_NO_ERROR);
1356 }
1357
Jamie Madill4e31ad52015-10-29 10:32:57 -04001358 gl::PrimitiveType geometryShaderType = GetGeometryShaderTypeFromDrawMode(drawMode);
1359
1360 if (mGeometryExecutables[geometryShaderType] != nullptr)
1361 {
1362 if (outExecutable)
1363 {
1364 *outExecutable = mGeometryExecutables[geometryShaderType];
1365 }
1366 return gl::Error(GL_NO_ERROR);
1367 }
1368
1369 std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL(
1370 geometryShaderType, data, mData, mGeometryShaderPreamble);
1371
1372 gl::InfoLog tempInfoLog;
1373 gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
1374
1375 gl::Error error = mRenderer->compileToExecutable(
Jamie Madill9fc36822015-11-18 13:08:07 -05001376 *currentInfoLog, geometryHLSL, SHADER_GEOMETRY, mStreamOutVaryings,
Jamie Madill4e31ad52015-10-29 10:32:57 -04001377 (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), D3DCompilerWorkarounds(),
1378 &mGeometryExecutables[geometryShaderType]);
1379
1380 if (!infoLog && error.isError())
1381 {
1382 std::vector<char> tempCharBuffer(tempInfoLog.getLength() + 3);
1383 tempInfoLog.getLog(static_cast<GLsizei>(tempInfoLog.getLength()), NULL, &tempCharBuffer[0]);
1384 ERR("Error compiling dynamic geometry executable:\n%s\n", &tempCharBuffer[0]);
1385 }
1386
1387 if (outExecutable)
1388 {
1389 *outExecutable = mGeometryExecutables[geometryShaderType];
1390 }
1391 return error;
1392}
1393
1394LinkResult ProgramD3D::compileProgramExecutables(const gl::Data &data, gl::InfoLog &infoLog)
Brandon Jones44151a92014-09-10 11:32:25 -07001395{
Jamie Madill5c6b7bf2015-08-17 12:53:35 -04001396 const gl::InputLayout &defaultInputLayout =
1397 GetDefaultInputLayoutFromShader(mData.getAttachedVertexShader());
Jamie Madille4ea2022015-03-26 20:35:05 +00001398 ShaderExecutableD3D *defaultVertexExecutable = NULL;
Jamie Madill334d6152015-10-22 14:00:28 -04001399 gl::Error error =
1400 getVertexExecutableForInputLayout(defaultInputLayout, &defaultVertexExecutable, &infoLog);
Jamie Madille4ea2022015-03-26 20:35:05 +00001401 if (error.isError())
Austin Kinross434953e2015-02-20 10:49:51 -08001402 {
Jamie Madille4ea2022015-03-26 20:35:05 +00001403 return LinkResult(false, error);
1404 }
Austin Kinross434953e2015-02-20 10:49:51 -08001405
Jamie Madill334d6152015-10-22 14:00:28 -04001406 std::vector<GLenum> defaultPixelOutput = GetDefaultOutputLayoutFromShader(getPixelShaderKey());
Geoff Lang359ef262015-01-05 14:42:29 -05001407 ShaderExecutableD3D *defaultPixelExecutable = NULL;
Jamie Madill334d6152015-10-22 14:00:28 -04001408 error =
1409 getPixelExecutableForOutputLayout(defaultPixelOutput, &defaultPixelExecutable, &infoLog);
Geoff Langb543aff2014-09-30 14:52:54 -04001410 if (error.isError())
1411 {
Geoff Lang7dd2e102014-11-10 15:19:26 -05001412 return LinkResult(false, error);
Geoff Langb543aff2014-09-30 14:52:54 -04001413 }
Brandon Jones44151a92014-09-10 11:32:25 -07001414
Jamie Madill4e31ad52015-10-29 10:32:57 -04001415 // Auto-generate the geometry shader here, if we expect to be using point rendering in D3D11.
Jamie Madill847638a2015-11-20 13:01:41 -05001416 ShaderExecutableD3D *pointGS = nullptr;
Jamie Madill3e14e2b2015-10-29 14:38:53 -04001417 if (usesGeometryShader(GL_POINTS))
Brandon Joneseb994362014-09-24 10:27:28 -07001418 {
Jamie Madill847638a2015-11-20 13:01:41 -05001419 getGeometryExecutableForPrimitiveType(data, GL_POINTS, &pointGS, &infoLog);
Brandon Joneseb994362014-09-24 10:27:28 -07001420 }
1421
Jamie Madillca03b352015-09-02 12:38:13 -04001422 const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(mData.getAttachedVertexShader());
Jamie Madill847638a2015-11-20 13:01:41 -05001423
1424 if (usesGeometryShader(GL_POINTS) && pointGS)
Tibor den Ouden97049c62014-10-06 21:39:16 +02001425 {
Jamie Madill334d6152015-10-22 14:00:28 -04001426 // Geometry shaders are currently only used internally, so there is no corresponding shader
1427 // object at the interface level. For now the geometry shader debug info is prepended to
1428 // the vertex shader.
Tibor den Ouden97049c62014-10-06 21:39:16 +02001429 vertexShaderD3D->appendDebugInfo("// GEOMETRY SHADER BEGIN\n\n");
Jamie Madill847638a2015-11-20 13:01:41 -05001430 vertexShaderD3D->appendDebugInfo(pointGS->getDebugInfo());
Tibor den Ouden97049c62014-10-06 21:39:16 +02001431 vertexShaderD3D->appendDebugInfo("\nGEOMETRY SHADER END\n\n\n");
1432 }
1433
1434 if (defaultVertexExecutable)
1435 {
1436 vertexShaderD3D->appendDebugInfo(defaultVertexExecutable->getDebugInfo());
1437 }
1438
1439 if (defaultPixelExecutable)
1440 {
Jamie Madill76f8fa62015-10-29 10:32:56 -04001441 const ShaderD3D *fragmentShaderD3D =
1442 GetImplAs<ShaderD3D>(mData.getAttachedFragmentShader());
Tibor den Ouden97049c62014-10-06 21:39:16 +02001443 fragmentShaderD3D->appendDebugInfo(defaultPixelExecutable->getDebugInfo());
1444 }
Tibor den Ouden97049c62014-10-06 21:39:16 +02001445
Jamie Madill847638a2015-11-20 13:01:41 -05001446 bool linkSuccess = (defaultVertexExecutable && defaultPixelExecutable &&
1447 (!usesGeometryShader(GL_POINTS) || pointGS));
Geoff Lang7dd2e102014-11-10 15:19:26 -05001448 return LinkResult(linkSuccess, gl::Error(GL_NO_ERROR));
Brandon Jones18bd4102014-09-22 14:21:44 -07001449}
1450
Jamie Madillf5f4ad22015-09-02 18:32:38 +00001451LinkResult ProgramD3D::link(const gl::Data &data, gl::InfoLog &infoLog)
Brandon Jones22502d52014-08-29 16:58:36 -07001452{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001453 reset();
1454
1455 // TODO(jmadill): structures containing samplers
1456 for (const gl::LinkedUniform &linkedUniform : mData.getUniforms())
1457 {
1458 if (linkedUniform.isSampler() && linkedUniform.isField())
1459 {
1460 infoLog << "Structures containing samplers not currently supported in D3D.";
1461 return LinkResult(false, gl::Error(GL_NO_ERROR));
1462 }
1463 }
1464
Jamie Madillf5f4ad22015-09-02 18:32:38 +00001465 const gl::Shader *vertexShader = mData.getAttachedVertexShader();
1466 const gl::Shader *fragmentShader = mData.getAttachedFragmentShader();
Brandon Joneseb994362014-09-24 10:27:28 -07001467
Jamie Madillf5f4ad22015-09-02 18:32:38 +00001468 const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(vertexShader);
1469 const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(fragmentShader);
1470
Jamie Madill63069df2015-09-01 17:26:41 +00001471 mSamplersVS.resize(data.caps->maxVertexTextureImageUnits);
Jamie Madillf5f4ad22015-09-02 18:32:38 +00001472 mSamplersPS.resize(data.caps->maxTextureImageUnits);
Brandon Jones22502d52014-08-29 16:58:36 -07001473
Arun Patole44efa0b2015-03-04 17:11:05 +05301474 vertexShaderD3D->generateWorkarounds(&mVertexWorkarounds);
Jamie Madillf5f4ad22015-09-02 18:32:38 +00001475 fragmentShaderD3D->generateWorkarounds(&mPixelWorkarounds);
1476
Austin Kinross02df7962015-07-01 10:03:42 -07001477 if (mRenderer->getRendererLimitations().noFrontFacingSupport)
1478 {
1479 if (fragmentShaderD3D->usesFrontFacing())
1480 {
1481 infoLog << "The current renderer doesn't support gl_FrontFacing";
1482 return LinkResult(false, gl::Error(GL_NO_ERROR));
1483 }
1484 }
1485
Jamie Madillca03b352015-09-02 12:38:13 -04001486 std::vector<PackedVarying> packedVaryings =
1487 MergeVaryings(*vertexShader, *fragmentShader, mData.getTransformFeedbackVaryingNames());
1488
Brandon Jones22502d52014-08-29 16:58:36 -07001489 // Map the varyings to the register file
Jamie Madill9fc36822015-11-18 13:08:07 -05001490 VaryingPacking varyingPacking(data.caps->maxVaryingVectors);
1491 if (!varyingPacking.packVaryings(infoLog, packedVaryings,
1492 mData.getTransformFeedbackVaryingNames()))
Brandon Jones22502d52014-08-29 16:58:36 -07001493 {
Geoff Lang7dd2e102014-11-10 15:19:26 -05001494 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Jones22502d52014-08-29 16:58:36 -07001495 }
1496
Jamie Madille39a3f02015-11-17 20:42:15 -05001497 ProgramD3DMetadata metadata(mRenderer->getMajorShaderModel(), mRenderer->getShaderModelSuffix(),
1498 usesInstancedPointSpriteEmulation(), vertexShaderD3D,
1499 fragmentShaderD3D);
1500
Jamie Madill9fc36822015-11-18 13:08:07 -05001501 varyingPacking.enableBuiltins(SHADER_VERTEX, metadata);
1502 varyingPacking.enableBuiltins(SHADER_PIXEL, metadata);
1503
1504 if (static_cast<GLuint>(varyingPacking.getRegisterCount()) > data.caps->maxVaryingVectors)
1505 {
1506 infoLog << "No varying registers left to support gl_FragCoord/gl_PointCoord";
1507 return LinkResult(false, gl::Error(GL_NO_ERROR));
1508 }
1509
1510 // TODO(jmadill): Implement more sophisticated component packing in D3D9.
1511 // We can fail here because we use one semantic per GLSL varying. D3D11 can pack varyings
1512 // intelligently, but D3D9 assumes one semantic per register.
1513 if (mRenderer->getRendererClass() == RENDERER_D3D9 &&
1514 varyingPacking.getMaxSemanticIndex() > data.caps->maxVaryingVectors)
1515 {
1516 infoLog << "Cannot pack these varyings on D3D9.";
1517 return LinkResult(false, gl::Error(GL_NO_ERROR));
1518 }
1519
1520 if (!mDynamicHLSL->generateShaderLinkHLSL(data, mData, metadata, varyingPacking, &mPixelHLSL,
1521 &mVertexHLSL))
Brandon Jones22502d52014-08-29 16:58:36 -07001522 {
Geoff Lang7dd2e102014-11-10 15:19:26 -05001523 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Jones22502d52014-08-29 16:58:36 -07001524 }
1525
Brandon Jones44151a92014-09-10 11:32:25 -07001526 mUsesPointSize = vertexShaderD3D->usesPointSize();
Jamie Madille39a3f02015-11-17 20:42:15 -05001527 mDynamicHLSL->getPixelShaderOutputKey(data, mData, metadata, &mPixelShaderKey);
1528 mUsesFragDepth = metadata.usesFragDepth(mData);
Brandon Jones44151a92014-09-10 11:32:25 -07001529
Jamie Madill3e14e2b2015-10-29 14:38:53 -04001530 // Cache if we use flat shading
Jamie Madill55c25d02015-11-18 13:08:08 -05001531 mUsesFlatInterpolation = false;
Jamie Madill3e14e2b2015-10-29 14:38:53 -04001532 for (const auto &varying : packedVaryings)
1533 {
Jamie Madill55c25d02015-11-18 13:08:08 -05001534 if (varying.interpolation == sh::INTERPOLATION_FLAT)
Jamie Madill3e14e2b2015-10-29 14:38:53 -04001535 {
1536 mUsesFlatInterpolation = true;
1537 break;
1538 }
1539 }
1540
Jamie Madill4e31ad52015-10-29 10:32:57 -04001541 if (mRenderer->getMajorShaderModel() >= 4)
1542 {
Jamie Madill9fc36822015-11-18 13:08:07 -05001543 varyingPacking.enableBuiltins(SHADER_GEOMETRY, metadata);
1544 mGeometryShaderPreamble = mDynamicHLSL->generateGeometryShaderPreamble(varyingPacking);
Jamie Madill4e31ad52015-10-29 10:32:57 -04001545 }
1546
Jamie Madill63805b42015-08-25 13:17:39 -04001547 initSemanticIndex();
Jamie Madill437d2662014-12-05 14:23:35 -05001548
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001549 defineUniformsAndAssignRegisters();
Jamie Madille473dee2015-08-18 14:49:01 -04001550
Olli Etuaho30268292016-01-15 16:40:00 +02001551 mSamplerMetadataPS.initData(getUsedSamplerRange(gl::SAMPLER_PIXEL), gl::SAMPLER_PIXEL);
1552 mSamplerMetadataVS.initData(getUsedSamplerRange(gl::SAMPLER_VERTEX), gl::SAMPLER_VERTEX);
1553
Jamie Madill9fc36822015-11-18 13:08:07 -05001554 gatherTransformFeedbackVaryings(varyingPacking);
Jamie Madillccdf74b2015-08-18 10:46:12 -04001555
Jamie Madill4e31ad52015-10-29 10:32:57 -04001556 LinkResult result = compileProgramExecutables(data, infoLog);
Jamie Madill31c8c562015-08-19 14:08:03 -04001557 if (result.error.isError() || !result.linkSuccess)
1558 {
1559 infoLog << "Failed to create D3D shaders.";
1560 return result;
1561 }
1562
Jamie Madill4a3c2342015-10-08 12:58:45 -04001563 initUniformBlockInfo();
1564
Geoff Lang7dd2e102014-11-10 15:19:26 -05001565 return LinkResult(true, gl::Error(GL_NO_ERROR));
Brandon Jones22502d52014-08-29 16:58:36 -07001566}
1567
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001568GLboolean ProgramD3D::validate(const gl::Caps & /*caps*/, gl::InfoLog * /*infoLog*/)
Jamie Madill36cfd6a2015-08-18 10:46:20 -04001569{
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001570 // TODO(jmadill): Do something useful here?
1571 return GL_TRUE;
Jamie Madill36cfd6a2015-08-18 10:46:20 -04001572}
1573
Jamie Madill4a3c2342015-10-08 12:58:45 -04001574void ProgramD3D::initUniformBlockInfo()
Jamie Madill62d31cb2015-09-11 13:25:51 -04001575{
1576 const gl::Shader *vertexShader = mData.getAttachedVertexShader();
1577
Jamie Madill62d31cb2015-09-11 13:25:51 -04001578 for (const sh::InterfaceBlock &vertexBlock : vertexShader->getInterfaceBlocks())
1579 {
1580 if (!vertexBlock.staticUse && vertexBlock.layout == sh::BLOCKLAYOUT_PACKED)
1581 continue;
1582
Jamie Madill4a3c2342015-10-08 12:58:45 -04001583 if (mBlockDataSizes.count(vertexBlock.name) > 0)
Jamie Madill62d31cb2015-09-11 13:25:51 -04001584 continue;
1585
Jamie Madill4a3c2342015-10-08 12:58:45 -04001586 size_t dataSize = getUniformBlockInfo(vertexBlock);
1587 mBlockDataSizes[vertexBlock.name] = dataSize;
Jamie Madill62d31cb2015-09-11 13:25:51 -04001588 }
1589
1590 const gl::Shader *fragmentShader = mData.getAttachedFragmentShader();
1591
1592 for (const sh::InterfaceBlock &fragmentBlock : fragmentShader->getInterfaceBlocks())
1593 {
1594 if (!fragmentBlock.staticUse && fragmentBlock.layout == sh::BLOCKLAYOUT_PACKED)
1595 continue;
1596
Jamie Madill4a3c2342015-10-08 12:58:45 -04001597 if (mBlockDataSizes.count(fragmentBlock.name) > 0)
Jamie Madill62d31cb2015-09-11 13:25:51 -04001598 continue;
1599
Jamie Madill4a3c2342015-10-08 12:58:45 -04001600 size_t dataSize = getUniformBlockInfo(fragmentBlock);
1601 mBlockDataSizes[fragmentBlock.name] = dataSize;
Jamie Madill62d31cb2015-09-11 13:25:51 -04001602 }
Jamie Madill4a3c2342015-10-08 12:58:45 -04001603}
Jamie Madill62d31cb2015-09-11 13:25:51 -04001604
Jamie Madill4a3c2342015-10-08 12:58:45 -04001605void ProgramD3D::assignUniformBlockRegisters()
1606{
1607 mD3DUniformBlocks.clear();
Jamie Madill62d31cb2015-09-11 13:25:51 -04001608
1609 // Assign registers and update sizes.
Jamie Madill4a3c2342015-10-08 12:58:45 -04001610 const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(mData.getAttachedVertexShader());
1611 const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(mData.getAttachedFragmentShader());
Jamie Madill62d31cb2015-09-11 13:25:51 -04001612
Jamie Madill4a3c2342015-10-08 12:58:45 -04001613 for (const gl::UniformBlock &uniformBlock : mData.getUniformBlocks())
Jamie Madill62d31cb2015-09-11 13:25:51 -04001614 {
1615 unsigned int uniformBlockElement = uniformBlock.isArray ? uniformBlock.arrayElement : 0;
1616
Jamie Madill4a3c2342015-10-08 12:58:45 -04001617 D3DUniformBlock d3dUniformBlock;
1618
Jamie Madill62d31cb2015-09-11 13:25:51 -04001619 if (uniformBlock.vertexStaticUse)
1620 {
1621 unsigned int baseRegister =
1622 vertexShaderD3D->getInterfaceBlockRegister(uniformBlock.name);
Jamie Madill4a3c2342015-10-08 12:58:45 -04001623 d3dUniformBlock.vsRegisterIndex = baseRegister + uniformBlockElement;
Jamie Madill62d31cb2015-09-11 13:25:51 -04001624 }
1625
1626 if (uniformBlock.fragmentStaticUse)
1627 {
1628 unsigned int baseRegister =
1629 fragmentShaderD3D->getInterfaceBlockRegister(uniformBlock.name);
Jamie Madill4a3c2342015-10-08 12:58:45 -04001630 d3dUniformBlock.psRegisterIndex = baseRegister + uniformBlockElement;
Jamie Madill62d31cb2015-09-11 13:25:51 -04001631 }
1632
Jamie Madill4a3c2342015-10-08 12:58:45 -04001633 mD3DUniformBlocks.push_back(d3dUniformBlock);
Jamie Madill62d31cb2015-09-11 13:25:51 -04001634 }
1635}
1636
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001637void ProgramD3D::initializeUniformStorage()
Brandon Jonesc9610c52014-08-25 17:02:59 -07001638{
1639 // Compute total default block size
Jamie Madill334d6152015-10-22 14:00:28 -04001640 unsigned int vertexRegisters = 0;
Brandon Jonesc9610c52014-08-25 17:02:59 -07001641 unsigned int fragmentRegisters = 0;
Jamie Madill62d31cb2015-09-11 13:25:51 -04001642 for (const D3DUniform *d3dUniform : mD3DUniforms)
Brandon Jonesc9610c52014-08-25 17:02:59 -07001643 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001644 if (!d3dUniform->isSampler())
Brandon Jonesc9610c52014-08-25 17:02:59 -07001645 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001646 if (d3dUniform->isReferencedByVertexShader())
Brandon Jonesc9610c52014-08-25 17:02:59 -07001647 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001648 vertexRegisters = std::max(vertexRegisters,
1649 d3dUniform->vsRegisterIndex + d3dUniform->registerCount);
Brandon Jonesc9610c52014-08-25 17:02:59 -07001650 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04001651 if (d3dUniform->isReferencedByFragmentShader())
Brandon Jonesc9610c52014-08-25 17:02:59 -07001652 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001653 fragmentRegisters = std::max(
1654 fragmentRegisters, d3dUniform->psRegisterIndex + d3dUniform->registerCount);
Brandon Jonesc9610c52014-08-25 17:02:59 -07001655 }
1656 }
1657 }
1658
Jamie Madill334d6152015-10-22 14:00:28 -04001659 mVertexUniformStorage = mRenderer->createUniformStorage(vertexRegisters * 16u);
Brandon Jonesc9610c52014-08-25 17:02:59 -07001660 mFragmentUniformStorage = mRenderer->createUniformStorage(fragmentRegisters * 16u);
1661}
1662
Jamie Madill3e14e2b2015-10-29 14:38:53 -04001663gl::Error ProgramD3D::applyUniforms(GLenum drawMode)
Brandon Jones18bd4102014-09-22 14:21:44 -07001664{
Olli Etuahoe5df3062015-11-18 13:45:19 +02001665 ASSERT(!mDirtySamplerMapping);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001666
Jamie Madill3e14e2b2015-10-29 14:38:53 -04001667 gl::Error error = mRenderer->applyUniforms(*this, drawMode, mD3DUniforms);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001668 if (error.isError())
1669 {
1670 return error;
1671 }
1672
Jamie Madill62d31cb2015-09-11 13:25:51 -04001673 for (D3DUniform *d3dUniform : mD3DUniforms)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001674 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001675 d3dUniform->dirty = false;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001676 }
1677
Olli Etuaho30268292016-01-15 16:40:00 +02001678 error = mRenderer->applySamplerMetadata(&mSamplerMetadataVS, mUsedVertexSamplerRange,
1679 gl::SAMPLER_VERTEX);
1680 error = mRenderer->applySamplerMetadata(&mSamplerMetadataPS, mUsedPixelSamplerRange,
1681 gl::SAMPLER_PIXEL);
1682
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001683 return gl::Error(GL_NO_ERROR);
Brandon Jones18bd4102014-09-22 14:21:44 -07001684}
1685
Jamie Madilld1fe1642015-08-21 16:26:04 -04001686gl::Error ProgramD3D::applyUniformBuffers(const gl::Data &data)
Brandon Jones18bd4102014-09-22 14:21:44 -07001687{
Jamie Madill4a3c2342015-10-08 12:58:45 -04001688 if (mData.getUniformBlocks().empty())
1689 {
1690 return gl::Error(GL_NO_ERROR);
1691 }
1692
1693 // Lazy init.
1694 if (mD3DUniformBlocks.empty())
1695 {
1696 assignUniformBlockRegisters();
1697 }
1698
Jamie Madill03260fa2015-06-22 13:57:22 -04001699 mVertexUBOCache.clear();
1700 mFragmentUBOCache.clear();
Brandon Jones18bd4102014-09-22 14:21:44 -07001701
1702 const unsigned int reservedBuffersInVS = mRenderer->getReservedVertexUniformBuffers();
1703 const unsigned int reservedBuffersInFS = mRenderer->getReservedFragmentUniformBuffers();
1704
Jamie Madill4a3c2342015-10-08 12:58:45 -04001705 for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < mD3DUniformBlocks.size();
Jamie Madill62d31cb2015-09-11 13:25:51 -04001706 uniformBlockIndex++)
Brandon Jones18bd4102014-09-22 14:21:44 -07001707 {
Jamie Madill4a3c2342015-10-08 12:58:45 -04001708 const D3DUniformBlock &uniformBlock = mD3DUniformBlocks[uniformBlockIndex];
1709 GLuint blockBinding = mData.getUniformBlockBinding(uniformBlockIndex);
Brandon Jones18bd4102014-09-22 14:21:44 -07001710
Brandon Jones18bd4102014-09-22 14:21:44 -07001711 // Unnecessary to apply an unreferenced standard or shared UBO
Jamie Madill4a3c2342015-10-08 12:58:45 -04001712 if (!uniformBlock.vertexStaticUse() && !uniformBlock.fragmentStaticUse())
Brandon Jones18bd4102014-09-22 14:21:44 -07001713 {
1714 continue;
1715 }
1716
Jamie Madill4a3c2342015-10-08 12:58:45 -04001717 if (uniformBlock.vertexStaticUse())
Brandon Jones18bd4102014-09-22 14:21:44 -07001718 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001719 unsigned int registerIndex = uniformBlock.vsRegisterIndex - reservedBuffersInVS;
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00001720 ASSERT(registerIndex < data.caps->maxVertexUniformBlocks);
Jamie Madill03260fa2015-06-22 13:57:22 -04001721
Jamie Madill969194d2015-07-20 14:36:56 -04001722 if (mVertexUBOCache.size() <= registerIndex)
Jamie Madill03260fa2015-06-22 13:57:22 -04001723 {
1724 mVertexUBOCache.resize(registerIndex + 1, -1);
1725 }
1726
1727 ASSERT(mVertexUBOCache[registerIndex] == -1);
1728 mVertexUBOCache[registerIndex] = blockBinding;
Brandon Jones18bd4102014-09-22 14:21:44 -07001729 }
1730
Jamie Madill4a3c2342015-10-08 12:58:45 -04001731 if (uniformBlock.fragmentStaticUse())
Brandon Jones18bd4102014-09-22 14:21:44 -07001732 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001733 unsigned int registerIndex = uniformBlock.psRegisterIndex - reservedBuffersInFS;
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00001734 ASSERT(registerIndex < data.caps->maxFragmentUniformBlocks);
Jamie Madill03260fa2015-06-22 13:57:22 -04001735
1736 if (mFragmentUBOCache.size() <= registerIndex)
1737 {
1738 mFragmentUBOCache.resize(registerIndex + 1, -1);
1739 }
1740
1741 ASSERT(mFragmentUBOCache[registerIndex] == -1);
1742 mFragmentUBOCache[registerIndex] = blockBinding;
Brandon Jones18bd4102014-09-22 14:21:44 -07001743 }
1744 }
1745
Jamie Madill03260fa2015-06-22 13:57:22 -04001746 return mRenderer->setUniformBuffers(data, mVertexUBOCache, mFragmentUBOCache);
Brandon Jones18bd4102014-09-22 14:21:44 -07001747}
1748
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001749void ProgramD3D::dirtyAllUniforms()
Brandon Jones18bd4102014-09-22 14:21:44 -07001750{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001751 for (D3DUniform *d3dUniform : mD3DUniforms)
Brandon Jones18bd4102014-09-22 14:21:44 -07001752 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001753 d3dUniform->dirty = true;
Brandon Jones18bd4102014-09-22 14:21:44 -07001754 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001755}
1756
Jamie Madill334d6152015-10-22 14:00:28 -04001757void ProgramD3D::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001758{
1759 setUniform(location, count, v, GL_FLOAT);
1760}
1761
1762void ProgramD3D::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
1763{
1764 setUniform(location, count, v, GL_FLOAT_VEC2);
1765}
1766
1767void ProgramD3D::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
1768{
1769 setUniform(location, count, v, GL_FLOAT_VEC3);
1770}
1771
1772void ProgramD3D::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
1773{
1774 setUniform(location, count, v, GL_FLOAT_VEC4);
1775}
1776
Jamie Madill334d6152015-10-22 14:00:28 -04001777void ProgramD3D::setUniformMatrix2fv(GLint location,
1778 GLsizei count,
1779 GLboolean transpose,
1780 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001781{
1782 setUniformMatrixfv<2, 2>(location, count, transpose, value, GL_FLOAT_MAT2);
1783}
1784
Jamie Madill334d6152015-10-22 14:00:28 -04001785void ProgramD3D::setUniformMatrix3fv(GLint location,
1786 GLsizei count,
1787 GLboolean transpose,
1788 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001789{
1790 setUniformMatrixfv<3, 3>(location, count, transpose, value, GL_FLOAT_MAT3);
1791}
1792
Jamie Madill334d6152015-10-22 14:00:28 -04001793void ProgramD3D::setUniformMatrix4fv(GLint location,
1794 GLsizei count,
1795 GLboolean transpose,
1796 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001797{
1798 setUniformMatrixfv<4, 4>(location, count, transpose, value, GL_FLOAT_MAT4);
1799}
1800
Jamie Madill334d6152015-10-22 14:00:28 -04001801void ProgramD3D::setUniformMatrix2x3fv(GLint location,
1802 GLsizei count,
1803 GLboolean transpose,
1804 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001805{
1806 setUniformMatrixfv<2, 3>(location, count, transpose, value, GL_FLOAT_MAT2x3);
1807}
1808
Jamie Madill334d6152015-10-22 14:00:28 -04001809void ProgramD3D::setUniformMatrix3x2fv(GLint location,
1810 GLsizei count,
1811 GLboolean transpose,
1812 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001813{
1814 setUniformMatrixfv<3, 2>(location, count, transpose, value, GL_FLOAT_MAT3x2);
1815}
1816
Jamie Madill334d6152015-10-22 14:00:28 -04001817void ProgramD3D::setUniformMatrix2x4fv(GLint location,
1818 GLsizei count,
1819 GLboolean transpose,
1820 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001821{
1822 setUniformMatrixfv<2, 4>(location, count, transpose, value, GL_FLOAT_MAT2x4);
1823}
1824
Jamie Madill334d6152015-10-22 14:00:28 -04001825void ProgramD3D::setUniformMatrix4x2fv(GLint location,
1826 GLsizei count,
1827 GLboolean transpose,
1828 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001829{
1830 setUniformMatrixfv<4, 2>(location, count, transpose, value, GL_FLOAT_MAT4x2);
1831}
1832
Jamie Madill334d6152015-10-22 14:00:28 -04001833void ProgramD3D::setUniformMatrix3x4fv(GLint location,
1834 GLsizei count,
1835 GLboolean transpose,
1836 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001837{
1838 setUniformMatrixfv<3, 4>(location, count, transpose, value, GL_FLOAT_MAT3x4);
1839}
1840
Jamie Madill334d6152015-10-22 14:00:28 -04001841void ProgramD3D::setUniformMatrix4x3fv(GLint location,
1842 GLsizei count,
1843 GLboolean transpose,
1844 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001845{
1846 setUniformMatrixfv<4, 3>(location, count, transpose, value, GL_FLOAT_MAT4x3);
1847}
1848
1849void ProgramD3D::setUniform1iv(GLint location, GLsizei count, const GLint *v)
1850{
1851 setUniform(location, count, v, GL_INT);
1852}
1853
1854void ProgramD3D::setUniform2iv(GLint location, GLsizei count, const GLint *v)
1855{
1856 setUniform(location, count, v, GL_INT_VEC2);
1857}
1858
1859void ProgramD3D::setUniform3iv(GLint location, GLsizei count, const GLint *v)
1860{
1861 setUniform(location, count, v, GL_INT_VEC3);
1862}
1863
1864void ProgramD3D::setUniform4iv(GLint location, GLsizei count, const GLint *v)
1865{
1866 setUniform(location, count, v, GL_INT_VEC4);
1867}
1868
1869void ProgramD3D::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
1870{
1871 setUniform(location, count, v, GL_UNSIGNED_INT);
1872}
1873
1874void ProgramD3D::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
1875{
1876 setUniform(location, count, v, GL_UNSIGNED_INT_VEC2);
1877}
1878
1879void ProgramD3D::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
1880{
1881 setUniform(location, count, v, GL_UNSIGNED_INT_VEC3);
1882}
1883
1884void ProgramD3D::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
1885{
1886 setUniform(location, count, v, GL_UNSIGNED_INT_VEC4);
1887}
1888
Jamie Madill4a3c2342015-10-08 12:58:45 -04001889void ProgramD3D::setUniformBlockBinding(GLuint /*uniformBlockIndex*/,
1890 GLuint /*uniformBlockBinding*/)
Geoff Lang5d124a62015-09-15 13:03:27 -04001891{
1892}
1893
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001894void ProgramD3D::defineUniformsAndAssignRegisters()
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001895{
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001896 D3DUniformMap uniformMap;
Jamie Madill334d6152015-10-22 14:00:28 -04001897 const gl::Shader *vertexShader = mData.getAttachedVertexShader();
Jamie Madill62d31cb2015-09-11 13:25:51 -04001898 for (const sh::Uniform &vertexUniform : vertexShader->getUniforms())
Jamie Madillfb536032015-09-11 13:19:49 -04001899
Jamie Madilla2eb02c2015-09-11 12:31:41 +00001900 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001901 if (vertexUniform.staticUse)
Jamie Madillfb536032015-09-11 13:19:49 -04001902 {
Jamie Madill91445bc2015-09-23 16:47:53 -04001903 defineUniformBase(vertexShader, vertexUniform, &uniformMap);
Jamie Madillfb536032015-09-11 13:19:49 -04001904 }
1905 }
1906
Jamie Madill334d6152015-10-22 14:00:28 -04001907 const gl::Shader *fragmentShader = mData.getAttachedFragmentShader();
Jamie Madill62d31cb2015-09-11 13:25:51 -04001908 for (const sh::Uniform &fragmentUniform : fragmentShader->getUniforms())
Jamie Madillfb536032015-09-11 13:19:49 -04001909 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001910 if (fragmentUniform.staticUse)
Jamie Madillfb536032015-09-11 13:19:49 -04001911 {
Jamie Madill91445bc2015-09-23 16:47:53 -04001912 defineUniformBase(fragmentShader, fragmentUniform, &uniformMap);
Jamie Madillfb536032015-09-11 13:19:49 -04001913 }
1914 }
1915
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001916 // Initialize the D3DUniform list to mirror the indexing of the GL layer.
1917 for (const gl::LinkedUniform &glUniform : mData.getUniforms())
1918 {
1919 if (!glUniform.isInDefaultBlock())
1920 continue;
1921
1922 auto mapEntry = uniformMap.find(glUniform.name);
1923 ASSERT(mapEntry != uniformMap.end());
1924 mD3DUniforms.push_back(mapEntry->second);
1925 }
1926
Jamie Madill62d31cb2015-09-11 13:25:51 -04001927 assignAllSamplerRegisters();
Jamie Madillfb536032015-09-11 13:19:49 -04001928 initializeUniformStorage();
Jamie Madillfb536032015-09-11 13:19:49 -04001929}
1930
Jamie Madill91445bc2015-09-23 16:47:53 -04001931void ProgramD3D::defineUniformBase(const gl::Shader *shader,
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001932 const sh::Uniform &uniform,
1933 D3DUniformMap *uniformMap)
Jamie Madillfb536032015-09-11 13:19:49 -04001934{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001935 if (uniform.isBuiltIn())
Jamie Madillfb536032015-09-11 13:19:49 -04001936 {
Jamie Madill91445bc2015-09-23 16:47:53 -04001937 defineUniform(shader->getType(), uniform, uniform.name, nullptr, uniformMap);
Jamie Madill55def582015-05-04 11:24:57 -04001938 return;
1939 }
1940
Jamie Madill91445bc2015-09-23 16:47:53 -04001941 const ShaderD3D *shaderD3D = GetImplAs<ShaderD3D>(shader);
1942
1943 unsigned int startRegister = shaderD3D->getUniformRegister(uniform.name);
1944 ShShaderOutput outputType = shaderD3D->getCompilerOutputType();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001945 sh::HLSLBlockEncoder encoder(sh::HLSLBlockEncoder::GetStrategyFor(outputType));
Jamie Madill62d31cb2015-09-11 13:25:51 -04001946 encoder.skipRegisters(startRegister);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001947
Jamie Madill91445bc2015-09-23 16:47:53 -04001948 defineUniform(shader->getType(), uniform, uniform.name, &encoder, uniformMap);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001949}
1950
Jamie Madill62d31cb2015-09-11 13:25:51 -04001951D3DUniform *ProgramD3D::getD3DUniformByName(const std::string &name)
1952{
1953 for (D3DUniform *d3dUniform : mD3DUniforms)
1954 {
1955 if (d3dUniform->name == name)
1956 {
1957 return d3dUniform;
1958 }
1959 }
1960
1961 return nullptr;
1962}
1963
Jamie Madill91445bc2015-09-23 16:47:53 -04001964void ProgramD3D::defineUniform(GLenum shaderType,
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001965 const sh::ShaderVariable &uniform,
1966 const std::string &fullName,
1967 sh::HLSLBlockEncoder *encoder,
1968 D3DUniformMap *uniformMap)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001969{
1970 if (uniform.isStruct())
1971 {
1972 for (unsigned int elementIndex = 0; elementIndex < uniform.elementCount(); elementIndex++)
1973 {
1974 const std::string &elementString = (uniform.isArray() ? ArrayString(elementIndex) : "");
1975
Jamie Madill55def582015-05-04 11:24:57 -04001976 if (encoder)
1977 encoder->enterAggregateType();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001978
1979 for (size_t fieldIndex = 0; fieldIndex < uniform.fields.size(); fieldIndex++)
1980 {
Jamie Madill334d6152015-10-22 14:00:28 -04001981 const sh::ShaderVariable &field = uniform.fields[fieldIndex];
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001982 const std::string &fieldFullName = (fullName + elementString + "." + field.name);
1983
Jamie Madill91445bc2015-09-23 16:47:53 -04001984 defineUniform(shaderType, field, fieldFullName, encoder, uniformMap);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001985 }
1986
Jamie Madill55def582015-05-04 11:24:57 -04001987 if (encoder)
1988 encoder->exitAggregateType();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001989 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04001990 return;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001991 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04001992
1993 // Not a struct. Arrays are treated as aggregate types.
1994 if (uniform.isArray() && encoder)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001995 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001996 encoder->enterAggregateType();
1997 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001998
Jamie Madill62d31cb2015-09-11 13:25:51 -04001999 // Advance the uniform offset, to track registers allocation for structs
2000 sh::BlockMemberInfo blockInfo =
2001 encoder ? encoder->encodeType(uniform.type, uniform.arraySize, false)
2002 : sh::BlockMemberInfo::getDefaultBlockInfo();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002003
Jamie Madill3d3d2f22015-09-23 16:47:51 -04002004 auto uniformMapEntry = uniformMap->find(fullName);
2005 D3DUniform *d3dUniform = nullptr;
Jamie Madill2857f482015-02-09 15:35:29 -05002006
Jamie Madill3d3d2f22015-09-23 16:47:51 -04002007 if (uniformMapEntry != uniformMap->end())
Jamie Madill62d31cb2015-09-11 13:25:51 -04002008 {
Jamie Madill3d3d2f22015-09-23 16:47:51 -04002009 d3dUniform = uniformMapEntry->second;
2010 }
2011 else
2012 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002013 d3dUniform = new D3DUniform(uniform.type, fullName, uniform.arraySize, true);
Jamie Madill3d3d2f22015-09-23 16:47:51 -04002014 (*uniformMap)[fullName] = d3dUniform;
Jamie Madill62d31cb2015-09-11 13:25:51 -04002015 }
2016
2017 if (encoder)
2018 {
Jamie Madill3d3d2f22015-09-23 16:47:51 -04002019 d3dUniform->registerElement =
2020 static_cast<unsigned int>(sh::HLSLBlockEncoder::getBlockRegisterElement(blockInfo));
Jamie Madill62d31cb2015-09-11 13:25:51 -04002021 unsigned int reg =
2022 static_cast<unsigned int>(sh::HLSLBlockEncoder::getBlockRegister(blockInfo));
Jamie Madill91445bc2015-09-23 16:47:53 -04002023 if (shaderType == GL_FRAGMENT_SHADER)
Jamie Madill62d31cb2015-09-11 13:25:51 -04002024 {
2025 d3dUniform->psRegisterIndex = reg;
2026 }
Jamie Madill91445bc2015-09-23 16:47:53 -04002027 else
Jamie Madill62d31cb2015-09-11 13:25:51 -04002028 {
Jamie Madill91445bc2015-09-23 16:47:53 -04002029 ASSERT(shaderType == GL_VERTEX_SHADER);
Jamie Madill62d31cb2015-09-11 13:25:51 -04002030 d3dUniform->vsRegisterIndex = reg;
2031 }
Jamie Madillfb536032015-09-11 13:19:49 -04002032
2033 // Arrays are treated as aggregate types
Jamie Madill62d31cb2015-09-11 13:25:51 -04002034 if (uniform.isArray())
Jamie Madillfb536032015-09-11 13:19:49 -04002035 {
2036 encoder->exitAggregateType();
2037 }
2038 }
2039}
2040
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002041template <typename T>
Jamie Madill62d31cb2015-09-11 13:25:51 -04002042void ProgramD3D::setUniform(GLint location, GLsizei countIn, const T *v, GLenum targetUniformType)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002043{
Jamie Madill334d6152015-10-22 14:00:28 -04002044 const int components = gl::VariableComponentCount(targetUniformType);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002045 const GLenum targetBoolType = gl::VariableBoolVectorType(targetUniformType);
2046
Jamie Madill62d31cb2015-09-11 13:25:51 -04002047 D3DUniform *targetUniform = getD3DUniformFromLocation(location);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002048
Jamie Madill62d31cb2015-09-11 13:25:51 -04002049 unsigned int elementCount = targetUniform->elementCount();
2050 unsigned int arrayElement = mData.getUniformLocations()[location].element;
2051 unsigned int count = std::min(elementCount - arrayElement, static_cast<unsigned int>(countIn));
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002052
2053 if (targetUniform->type == targetUniformType)
2054 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002055 T *target = reinterpret_cast<T *>(targetUniform->data) + arrayElement * 4;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002056
Jamie Madill62d31cb2015-09-11 13:25:51 -04002057 for (unsigned int i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002058 {
Jamie Madill334d6152015-10-22 14:00:28 -04002059 T *dest = target + (i * 4);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002060 const T *source = v + (i * components);
2061
2062 for (int c = 0; c < components; c++)
2063 {
2064 SetIfDirty(dest + c, source[c], &targetUniform->dirty);
2065 }
2066 for (int c = components; c < 4; c++)
2067 {
2068 SetIfDirty(dest + c, T(0), &targetUniform->dirty);
2069 }
2070 }
2071 }
2072 else if (targetUniform->type == targetBoolType)
2073 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002074 GLint *boolParams = reinterpret_cast<GLint *>(targetUniform->data) + arrayElement * 4;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002075
Jamie Madill62d31cb2015-09-11 13:25:51 -04002076 for (unsigned int i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002077 {
Jamie Madill334d6152015-10-22 14:00:28 -04002078 GLint *dest = boolParams + (i * 4);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002079 const T *source = v + (i * components);
2080
2081 for (int c = 0; c < components; c++)
2082 {
Jamie Madill334d6152015-10-22 14:00:28 -04002083 SetIfDirty(dest + c, (source[c] == static_cast<T>(0)) ? GL_FALSE : GL_TRUE,
2084 &targetUniform->dirty);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002085 }
2086 for (int c = components; c < 4; c++)
2087 {
2088 SetIfDirty(dest + c, GL_FALSE, &targetUniform->dirty);
2089 }
2090 }
2091 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04002092 else if (targetUniform->isSampler())
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002093 {
2094 ASSERT(targetUniformType == GL_INT);
2095
Jamie Madill62d31cb2015-09-11 13:25:51 -04002096 GLint *target = reinterpret_cast<GLint *>(targetUniform->data) + arrayElement * 4;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002097
2098 bool wasDirty = targetUniform->dirty;
2099
Jamie Madill62d31cb2015-09-11 13:25:51 -04002100 for (unsigned int i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002101 {
Jamie Madill334d6152015-10-22 14:00:28 -04002102 GLint *dest = target + (i * 4);
2103 const GLint *source = reinterpret_cast<const GLint *>(v) + (i * components);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002104
2105 SetIfDirty(dest + 0, source[0], &targetUniform->dirty);
2106 SetIfDirty(dest + 1, 0, &targetUniform->dirty);
2107 SetIfDirty(dest + 2, 0, &targetUniform->dirty);
2108 SetIfDirty(dest + 3, 0, &targetUniform->dirty);
2109 }
2110
2111 if (!wasDirty && targetUniform->dirty)
2112 {
2113 mDirtySamplerMapping = true;
2114 }
Brandon Jones18bd4102014-09-22 14:21:44 -07002115 }
Jamie Madill334d6152015-10-22 14:00:28 -04002116 else
2117 UNREACHABLE();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002118}
2119
2120template <int cols, int rows>
Jamie Madill62d31cb2015-09-11 13:25:51 -04002121void ProgramD3D::setUniformMatrixfv(GLint location,
2122 GLsizei countIn,
2123 GLboolean transpose,
2124 const GLfloat *value,
2125 GLenum targetUniformType)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002126{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002127 D3DUniform *targetUniform = getD3DUniformFromLocation(location);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002128
Jamie Madill62d31cb2015-09-11 13:25:51 -04002129 unsigned int elementCount = targetUniform->elementCount();
2130 unsigned int arrayElement = mData.getUniformLocations()[location].element;
2131 unsigned int count = std::min(elementCount - arrayElement, static_cast<unsigned int>(countIn));
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002132
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002133 const unsigned int targetMatrixStride = (4 * rows);
Jamie Madill62d31cb2015-09-11 13:25:51 -04002134 GLfloat *target =
2135 (GLfloat *)(targetUniform->data + arrayElement * sizeof(GLfloat) * targetMatrixStride);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002136
Jamie Madill62d31cb2015-09-11 13:25:51 -04002137 for (unsigned int i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002138 {
2139 // Internally store matrices as transposed versions to accomodate HLSL matrix indexing
2140 if (transpose == GL_FALSE)
2141 {
Jamie Madill334d6152015-10-22 14:00:28 -04002142 targetUniform->dirty = TransposeMatrix<GLfloat>(target, value, 4, rows, rows, cols) ||
2143 targetUniform->dirty;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002144 }
2145 else
2146 {
Jamie Madill334d6152015-10-22 14:00:28 -04002147 targetUniform->dirty =
2148 ExpandMatrix<GLfloat>(target, value, 4, rows, cols, rows) || targetUniform->dirty;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002149 }
2150 target += targetMatrixStride;
2151 value += cols * rows;
2152 }
2153}
2154
Jamie Madill4a3c2342015-10-08 12:58:45 -04002155size_t ProgramD3D::getUniformBlockInfo(const sh::InterfaceBlock &interfaceBlock)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002156{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002157 ASSERT(interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002158
Jamie Madill62d31cb2015-09-11 13:25:51 -04002159 // define member uniforms
2160 sh::Std140BlockEncoder std140Encoder;
2161 sh::HLSLBlockEncoder hlslEncoder(sh::HLSLBlockEncoder::ENCODE_PACKED);
2162 sh::BlockLayoutEncoder *encoder = nullptr;
2163
2164 if (interfaceBlock.layout == sh::BLOCKLAYOUT_STANDARD)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002165 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002166 encoder = &std140Encoder;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002167 }
2168 else
2169 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002170 encoder = &hlslEncoder;
Jamie Madill61b8dd92015-09-09 19:04:04 +00002171 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04002172
2173 GetUniformBlockInfo(interfaceBlock.fields, "", encoder, interfaceBlock.isRowMajorLayout,
Jamie Madill4a3c2342015-10-08 12:58:45 -04002174 &mBlockInfo);
Jamie Madill62d31cb2015-09-11 13:25:51 -04002175
2176 return encoder->getBlockSize();
Jamie Madill61b8dd92015-09-09 19:04:04 +00002177}
2178
Jamie Madill62d31cb2015-09-11 13:25:51 -04002179void ProgramD3D::assignAllSamplerRegisters()
Jamie Madilla2eb02c2015-09-11 12:31:41 +00002180{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002181 for (const D3DUniform *d3dUniform : mD3DUniforms)
Jamie Madilla2eb02c2015-09-11 12:31:41 +00002182 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002183 if (d3dUniform->isSampler())
Jamie Madillfb536032015-09-11 13:19:49 -04002184 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002185 assignSamplerRegisters(d3dUniform);
Jamie Madillfb536032015-09-11 13:19:49 -04002186 }
Jamie Madilla2eb02c2015-09-11 12:31:41 +00002187 }
2188}
2189
Jamie Madill62d31cb2015-09-11 13:25:51 -04002190void ProgramD3D::assignSamplerRegisters(const D3DUniform *d3dUniform)
Jamie Madillfb536032015-09-11 13:19:49 -04002191{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002192 ASSERT(d3dUniform->isSampler());
2193 ASSERT(d3dUniform->vsRegisterIndex != GL_INVALID_INDEX ||
2194 d3dUniform->psRegisterIndex != GL_INVALID_INDEX);
Jamie Madillfb536032015-09-11 13:19:49 -04002195
Jamie Madill62d31cb2015-09-11 13:25:51 -04002196 if (d3dUniform->vsRegisterIndex != GL_INVALID_INDEX)
Jamie Madillfb536032015-09-11 13:19:49 -04002197 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002198 AssignSamplers(d3dUniform->vsRegisterIndex, d3dUniform->type, d3dUniform->arraySize,
2199 mSamplersVS, &mUsedVertexSamplerRange);
Jamie Madillfb536032015-09-11 13:19:49 -04002200 }
2201
Jamie Madill62d31cb2015-09-11 13:25:51 -04002202 if (d3dUniform->psRegisterIndex != GL_INVALID_INDEX)
Jamie Madillfb536032015-09-11 13:19:49 -04002203 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002204 AssignSamplers(d3dUniform->psRegisterIndex, d3dUniform->type, d3dUniform->arraySize,
2205 mSamplersPS, &mUsedPixelSamplerRange);
Jamie Madillfb536032015-09-11 13:19:49 -04002206 }
2207}
2208
Jamie Madill62d31cb2015-09-11 13:25:51 -04002209// static
2210void ProgramD3D::AssignSamplers(unsigned int startSamplerIndex,
Jamie Madilld3dfda22015-07-06 08:28:49 -04002211 GLenum samplerType,
2212 unsigned int samplerCount,
2213 std::vector<Sampler> &outSamplers,
2214 GLuint *outUsedRange)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002215{
2216 unsigned int samplerIndex = startSamplerIndex;
2217
2218 do
2219 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002220 ASSERT(samplerIndex < outSamplers.size());
2221 Sampler *sampler = &outSamplers[samplerIndex];
2222 sampler->active = true;
Jamie Madill3d3d2f22015-09-23 16:47:51 -04002223 sampler->textureType = gl::SamplerTypeToTextureType(samplerType);
Jamie Madill62d31cb2015-09-11 13:25:51 -04002224 sampler->logicalTextureUnit = 0;
2225 *outUsedRange = std::max(samplerIndex + 1, *outUsedRange);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002226 samplerIndex++;
2227 } while (samplerIndex < startSamplerIndex + samplerCount);
Brandon Jones18bd4102014-09-22 14:21:44 -07002228}
2229
Brandon Jonesc9610c52014-08-25 17:02:59 -07002230void ProgramD3D::reset()
2231{
Brandon Joneseb994362014-09-24 10:27:28 -07002232 SafeDeleteContainer(mVertexExecutables);
2233 SafeDeleteContainer(mPixelExecutables);
Jamie Madill4e31ad52015-10-29 10:32:57 -04002234
2235 for (auto &element : mGeometryExecutables)
2236 {
2237 SafeDelete(element);
2238 }
Brandon Joneseb994362014-09-24 10:27:28 -07002239
Brandon Jones22502d52014-08-29 16:58:36 -07002240 mVertexHLSL.clear();
Geoff Lang6941a552015-07-27 11:06:45 -04002241 mVertexWorkarounds = D3DCompilerWorkarounds();
Brandon Jones22502d52014-08-29 16:58:36 -07002242
2243 mPixelHLSL.clear();
Geoff Lang6941a552015-07-27 11:06:45 -04002244 mPixelWorkarounds = D3DCompilerWorkarounds();
Brandon Jones22502d52014-08-29 16:58:36 -07002245 mUsesFragDepth = false;
2246 mPixelShaderKey.clear();
Brandon Jones44151a92014-09-10 11:32:25 -07002247 mUsesPointSize = false;
Jamie Madill3e14e2b2015-10-29 14:38:53 -04002248 mUsesFlatInterpolation = false;
Brandon Jones22502d52014-08-29 16:58:36 -07002249
Jamie Madill62d31cb2015-09-11 13:25:51 -04002250 SafeDeleteContainer(mD3DUniforms);
Jamie Madill4a3c2342015-10-08 12:58:45 -04002251 mD3DUniformBlocks.clear();
Jamie Madill62d31cb2015-09-11 13:25:51 -04002252
Brandon Jonesc9610c52014-08-25 17:02:59 -07002253 SafeDelete(mVertexUniformStorage);
2254 SafeDelete(mFragmentUniformStorage);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002255
2256 mSamplersPS.clear();
2257 mSamplersVS.clear();
2258
Olli Etuaho30268292016-01-15 16:40:00 +02002259 mSamplerMetadataPS.reset();
2260 mSamplerMetadataVS.reset();
2261
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002262 mUsedVertexSamplerRange = 0;
Jamie Madill334d6152015-10-22 14:00:28 -04002263 mUsedPixelSamplerRange = 0;
2264 mDirtySamplerMapping = true;
Jamie Madill437d2662014-12-05 14:23:35 -05002265
Jamie Madill63805b42015-08-25 13:17:39 -04002266 std::fill(mSemanticIndexes, mSemanticIndexes + ArraySize(mSemanticIndexes), -1);
Jamie Madill437d2662014-12-05 14:23:35 -05002267 std::fill(mAttributesByLayout, mAttributesByLayout + ArraySize(mAttributesByLayout), -1);
Jamie Madillccdf74b2015-08-18 10:46:12 -04002268
Jamie Madill9fc36822015-11-18 13:08:07 -05002269 mStreamOutVaryings.clear();
Jamie Madill4e31ad52015-10-29 10:32:57 -04002270
2271 mGeometryShaderPreamble.clear();
Brandon Jonesc9610c52014-08-25 17:02:59 -07002272}
2273
Geoff Lang7dd2e102014-11-10 15:19:26 -05002274unsigned int ProgramD3D::getSerial() const
2275{
2276 return mSerial;
2277}
2278
2279unsigned int ProgramD3D::issueSerial()
2280{
2281 return mCurrentSerial++;
2282}
2283
Jamie Madill63805b42015-08-25 13:17:39 -04002284void ProgramD3D::initSemanticIndex()
2285{
2286 const gl::Shader *vertexShader = mData.getAttachedVertexShader();
2287 ASSERT(vertexShader != nullptr);
2288
2289 // Init semantic index
2290 for (const sh::Attribute &attribute : mData.getAttributes())
2291 {
2292 int attributeIndex = attribute.location;
2293 int index = vertexShader->getSemanticIndex(attribute.name);
2294 int regs = gl::VariableRegisterCount(attribute.type);
2295
2296 for (int reg = 0; reg < regs; ++reg)
2297 {
2298 mSemanticIndexes[attributeIndex + reg] = index + reg;
2299 }
2300 }
2301
2302 initAttributesByLayout();
2303}
2304
Jamie Madill437d2662014-12-05 14:23:35 -05002305void ProgramD3D::initAttributesByLayout()
2306{
2307 for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
2308 {
2309 mAttributesByLayout[i] = i;
2310 }
2311
Jamie Madill63805b42015-08-25 13:17:39 -04002312 std::sort(&mAttributesByLayout[0], &mAttributesByLayout[gl::MAX_VERTEX_ATTRIBS],
2313 AttributeSorter(mSemanticIndexes));
Jamie Madill437d2662014-12-05 14:23:35 -05002314}
2315
Jamie Madill334d6152015-10-22 14:00:28 -04002316void ProgramD3D::sortAttributesByLayout(
2317 const std::vector<TranslatedAttribute> &unsortedAttributes,
2318 int sortedSemanticIndicesOut[gl::MAX_VERTEX_ATTRIBS],
2319 const rx::TranslatedAttribute *sortedAttributesOut[gl::MAX_VERTEX_ATTRIBS]) const
Jamie Madill437d2662014-12-05 14:23:35 -05002320{
Jamie Madill476682e2015-06-30 10:04:29 -04002321 for (size_t attribIndex = 0; attribIndex < unsortedAttributes.size(); ++attribIndex)
Jamie Madill437d2662014-12-05 14:23:35 -05002322 {
Jamie Madill334d6152015-10-22 14:00:28 -04002323 int oldIndex = mAttributesByLayout[attribIndex];
Jamie Madill63805b42015-08-25 13:17:39 -04002324 sortedSemanticIndicesOut[attribIndex] = mSemanticIndexes[oldIndex];
Jamie Madill334d6152015-10-22 14:00:28 -04002325 sortedAttributesOut[attribIndex] = &unsortedAttributes[oldIndex];
Jamie Madill437d2662014-12-05 14:23:35 -05002326 }
2327}
2328
Jamie Madill63805b42015-08-25 13:17:39 -04002329void ProgramD3D::updateCachedInputLayout(const gl::State &state)
Jamie Madilld3dfda22015-07-06 08:28:49 -04002330{
Jamie Madillbd136f92015-08-10 14:51:37 -04002331 mCachedInputLayout.clear();
Jamie Madilld3dfda22015-07-06 08:28:49 -04002332 const auto &vertexAttributes = state.getVertexArray()->getVertexAttributes();
Jamie Madillf8dd7b12015-08-05 13:50:08 -04002333
Dian Xianga4928832015-09-15 10:11:17 -07002334 for (unsigned int attributeIndex : angle::IterateBitSet(mData.getActiveAttribLocationsMask()))
Jamie Madilld3dfda22015-07-06 08:28:49 -04002335 {
Jamie Madill63805b42015-08-25 13:17:39 -04002336 int semanticIndex = mSemanticIndexes[attributeIndex];
Jamie Madilld3dfda22015-07-06 08:28:49 -04002337
2338 if (semanticIndex != -1)
2339 {
Jamie Madillbd136f92015-08-10 14:51:37 -04002340 if (mCachedInputLayout.size() < static_cast<size_t>(semanticIndex + 1))
2341 {
2342 mCachedInputLayout.resize(semanticIndex + 1, gl::VERTEX_FORMAT_INVALID);
2343 }
Jamie Madilld3dfda22015-07-06 08:28:49 -04002344 mCachedInputLayout[semanticIndex] =
2345 GetVertexFormatType(vertexAttributes[attributeIndex],
2346 state.getVertexAttribCurrentValue(attributeIndex).Type);
2347 }
2348 }
2349}
2350
Jamie Madill9fc36822015-11-18 13:08:07 -05002351void ProgramD3D::gatherTransformFeedbackVaryings(const VaryingPacking &varyingPacking)
Jamie Madillccdf74b2015-08-18 10:46:12 -04002352{
Jamie Madill9fc36822015-11-18 13:08:07 -05002353 const auto &builtins = varyingPacking.builtins(SHADER_VERTEX);
2354
2355 const std::string &varyingSemantic =
2356 GetVaryingSemantic(mRenderer->getMajorShaderModel(), usesPointSize());
2357
Jamie Madillccdf74b2015-08-18 10:46:12 -04002358 // Gather the linked varyings that are used for transform feedback, they should all exist.
Jamie Madill9fc36822015-11-18 13:08:07 -05002359 mStreamOutVaryings.clear();
2360
2361 const auto &tfVaryingNames = mData.getTransformFeedbackVaryingNames();
2362 for (unsigned int outputSlot = 0; outputSlot < static_cast<unsigned int>(tfVaryingNames.size());
2363 ++outputSlot)
Jamie Madillccdf74b2015-08-18 10:46:12 -04002364 {
Jamie Madill9fc36822015-11-18 13:08:07 -05002365 const auto &tfVaryingName = tfVaryingNames[outputSlot];
2366 if (tfVaryingName == "gl_Position")
Jamie Madillccdf74b2015-08-18 10:46:12 -04002367 {
Jamie Madill9fc36822015-11-18 13:08:07 -05002368 if (builtins.glPosition.enabled)
Jamie Madillccdf74b2015-08-18 10:46:12 -04002369 {
Jamie Madill9fc36822015-11-18 13:08:07 -05002370 mStreamOutVaryings.push_back(D3DVarying(builtins.glPosition.semantic,
2371 builtins.glPosition.index, 4, outputSlot));
2372 }
2373 }
2374 else if (tfVaryingName == "gl_FragCoord")
2375 {
2376 if (builtins.glFragCoord.enabled)
2377 {
2378 mStreamOutVaryings.push_back(D3DVarying(builtins.glFragCoord.semantic,
2379 builtins.glFragCoord.index, 4, outputSlot));
2380 }
2381 }
2382 else if (tfVaryingName == "gl_PointSize")
2383 {
2384 if (builtins.glPointSize.enabled)
2385 {
2386 mStreamOutVaryings.push_back(D3DVarying("PSIZE", 0, 1, outputSlot));
2387 }
2388 }
2389 else
2390 {
2391 for (const PackedVaryingRegister &registerInfo : varyingPacking.getRegisterList())
2392 {
Jamie Madill55c25d02015-11-18 13:08:08 -05002393 const auto &varying = *registerInfo.packedVarying->varying;
2394 GLenum transposedType = gl::TransposeMatrixType(varying.type);
Jamie Madill9fc36822015-11-18 13:08:07 -05002395 int componentCount = gl::VariableColumnCount(transposedType);
2396 ASSERT(!varying.isBuiltIn());
2397
Jamie Madill55c25d02015-11-18 13:08:08 -05002398 // Transform feedback for varying structs is underspecified.
2399 // See Khronos bug 9856.
2400 // TODO(jmadill): Figure out how to be spec-compliant here.
2401 if (registerInfo.packedVarying->isStructField() || varying.isStruct())
2402 continue;
2403
Jamie Madill9fc36822015-11-18 13:08:07 -05002404 // There can be more than one register assigned to a particular varying, and each
2405 // register needs its own stream out entry.
2406 if (tfVaryingName == varying.name)
2407 {
2408 mStreamOutVaryings.push_back(D3DVarying(
2409 varyingSemantic, registerInfo.semanticIndex, componentCount, outputSlot));
2410 }
Jamie Madillccdf74b2015-08-18 10:46:12 -04002411 }
2412 }
2413 }
2414}
Jamie Madill62d31cb2015-09-11 13:25:51 -04002415
2416D3DUniform *ProgramD3D::getD3DUniformFromLocation(GLint location)
2417{
2418 return mD3DUniforms[mData.getUniformLocations()[location].index];
2419}
Jamie Madill4a3c2342015-10-08 12:58:45 -04002420
2421bool ProgramD3D::getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const
2422{
2423 std::string baseName = blockName;
2424 gl::ParseAndStripArrayIndex(&baseName);
2425
2426 auto sizeIter = mBlockDataSizes.find(baseName);
2427 if (sizeIter == mBlockDataSizes.end())
2428 {
2429 *sizeOut = 0;
2430 return false;
2431 }
2432
2433 *sizeOut = sizeIter->second;
2434 return true;
2435}
2436
2437bool ProgramD3D::getUniformBlockMemberInfo(const std::string &memberUniformName,
2438 sh::BlockMemberInfo *memberInfoOut) const
2439{
2440 auto infoIter = mBlockInfo.find(memberUniformName);
2441 if (infoIter == mBlockInfo.end())
2442 {
2443 *memberInfoOut = sh::BlockMemberInfo::getDefaultBlockInfo();
2444 return false;
2445 }
2446
2447 *memberInfoOut = infoIter->second;
2448 return true;
2449}
Brandon Jonesc9610c52014-08-25 17:02:59 -07002450}