blob: 9c633b0ed1a9a4e8eb728dee684ccd070993cd3c [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
Jamie Madill20e005b2017-04-07 14:19:22 -040011#include "common/bitset_utils.h"
Jamie Madill437d2662014-12-05 14:23:35 -050012#include "common/utilities.h"
Jamie Madillc564c072017-06-01 12:45:42 -040013#include "libANGLE/Context.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050014#include "libANGLE/Framebuffer.h"
15#include "libANGLE/FramebufferAttachment.h"
16#include "libANGLE/Program.h"
Jamie Madill53ea9cc2016-05-17 10:12:52 -040017#include "libANGLE/Uniform.h"
Jamie Madill192745a2016-12-22 15:58:21 -050018#include "libANGLE/VaryingPacking.h"
Jamie Madilld3dfda22015-07-06 08:28:49 -040019#include "libANGLE/VertexArray.h"
Jamie Madill6df9b372015-02-18 21:28:19 +000020#include "libANGLE/features.h"
Jamie Madill54164b02017-08-28 15:17:37 -040021#include "libANGLE/queryconversions.h"
Jamie Madill8ecf7f92017-01-13 17:29:52 -050022#include "libANGLE/renderer/ContextImpl.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050023#include "libANGLE/renderer/d3d/DynamicHLSL.h"
Jamie Madill85a18042015-03-05 15:41:41 -050024#include "libANGLE/renderer/d3d/FramebufferD3D.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050025#include "libANGLE/renderer/d3d/RendererD3D.h"
26#include "libANGLE/renderer/d3d/ShaderD3D.h"
Geoff Lang359ef262015-01-05 14:42:29 -050027#include "libANGLE/renderer/d3d/ShaderExecutableD3D.h"
Jamie Madill437d2662014-12-05 14:23:35 -050028#include "libANGLE/renderer/d3d/VertexDataManager.h"
Geoff Lang22072132014-11-20 15:15:01 -050029
Jamie Madill01074252016-11-28 15:55:51 -050030using namespace angle;
31
Brandon Jonesc9610c52014-08-25 17:02:59 -070032namespace rx
33{
34
Brandon Joneseb994362014-09-24 10:27:28 -070035namespace
36{
37
Jamie Madill4c19a8a2017-07-24 11:46:06 -040038void GetDefaultInputLayoutFromShader(const gl::Context *context,
39 gl::Shader *vertexShader,
40 gl::InputLayout *inputLayoutOut)
Brandon Joneseb994362014-09-24 10:27:28 -070041{
Jamie Madill4c19a8a2017-07-24 11:46:06 -040042 inputLayoutOut->clear();
43
Jamie Madillbd044ed2017-06-05 12:59:21 -040044 for (const sh::Attribute &shaderAttr : vertexShader->getActiveAttributes(context))
Brandon Joneseb994362014-09-24 10:27:28 -070045 {
Brandon Joneseb994362014-09-24 10:27:28 -070046 if (shaderAttr.type != GL_NONE)
47 {
48 GLenum transposedType = gl::TransposeMatrixType(shaderAttr.type);
49
Jamie Madilld3dfda22015-07-06 08:28:49 -040050 for (size_t rowIndex = 0;
Jamie Madill334d6152015-10-22 14:00:28 -040051 static_cast<int>(rowIndex) < gl::VariableRowCount(transposedType); ++rowIndex)
Brandon Joneseb994362014-09-24 10:27:28 -070052 {
Jamie Madilld3dfda22015-07-06 08:28:49 -040053 GLenum componentType = gl::VariableComponentType(transposedType);
Jamie Madill334d6152015-10-22 14:00:28 -040054 GLuint components = static_cast<GLuint>(gl::VariableColumnCount(transposedType));
Jamie Madilld3dfda22015-07-06 08:28:49 -040055 bool pureInt = (componentType != GL_FLOAT);
Jamie Madill334d6152015-10-22 14:00:28 -040056 gl::VertexFormatType defaultType =
57 gl::GetVertexFormatType(componentType, GL_FALSE, components, pureInt);
Brandon Joneseb994362014-09-24 10:27:28 -070058
Jamie Madill4c19a8a2017-07-24 11:46:06 -040059 inputLayoutOut->push_back(defaultType);
Brandon Joneseb994362014-09-24 10:27:28 -070060 }
61 }
62 }
63}
64
Jamie Madill4c19a8a2017-07-24 11:46:06 -040065void GetDefaultOutputLayoutFromShader(
66 const std::vector<PixelShaderOutputVariable> &shaderOutputVars,
67 std::vector<GLenum> *outputLayoutOut)
Brandon Joneseb994362014-09-24 10:27:28 -070068{
Jamie Madill4c19a8a2017-07-24 11:46:06 -040069 outputLayoutOut->clear();
Brandon Joneseb994362014-09-24 10:27:28 -070070
Jamie Madillb4463142014-12-19 14:56:54 -050071 if (!shaderOutputVars.empty())
72 {
Jamie Madill4c19a8a2017-07-24 11:46:06 -040073 outputLayoutOut->push_back(GL_COLOR_ATTACHMENT0 +
74 static_cast<unsigned int>(shaderOutputVars[0].outputIndex));
Jamie Madillb4463142014-12-19 14:56:54 -050075 }
Jamie Madill4c19a8a2017-07-24 11:46:06 -040076}
Brandon Joneseb994362014-09-24 10:27:28 -070077
Corentin Wallezb58e9ba2016-12-15 14:07:56 -080078template <typename T, int cols, int rows>
79bool TransposeExpandMatrix(T *target, const GLfloat *value)
Jamie Madill334d6152015-10-22 14:00:28 -040080{
Corentin Wallezb58e9ba2016-12-15 14:07:56 -080081 constexpr int targetWidth = 4;
82 constexpr int targetHeight = rows;
83 constexpr int srcWidth = rows;
84 constexpr int srcHeight = cols;
85
86 constexpr int copyWidth = std::min(targetHeight, srcWidth);
87 constexpr int copyHeight = std::min(targetWidth, srcHeight);
88
89 T staging[targetWidth * targetHeight] = {0};
Jamie Madill334d6152015-10-22 14:00:28 -040090
91 for (int x = 0; x < copyWidth; x++)
92 {
93 for (int y = 0; y < copyHeight; y++)
94 {
Corentin Wallezb58e9ba2016-12-15 14:07:56 -080095 staging[x * targetWidth + y] = static_cast<T>(value[y * srcWidth + x]);
Jamie Madill334d6152015-10-22 14:00:28 -040096 }
97 }
98
Corentin Wallezb58e9ba2016-12-15 14:07:56 -080099 if (memcmp(target, staging, targetWidth * targetHeight * sizeof(T)) == 0)
100 {
101 return false;
102 }
103
104 memcpy(target, staging, targetWidth * targetHeight * sizeof(T));
105 return true;
Jamie Madill334d6152015-10-22 14:00:28 -0400106}
107
Corentin Wallezb58e9ba2016-12-15 14:07:56 -0800108template <typename T, int cols, int rows>
109bool ExpandMatrix(T *target, const GLfloat *value)
Jamie Madill334d6152015-10-22 14:00:28 -0400110{
Corentin Wallezb58e9ba2016-12-15 14:07:56 -0800111 constexpr int targetWidth = 4;
112 constexpr int targetHeight = rows;
113 constexpr int srcWidth = cols;
114 constexpr int srcHeight = rows;
115
116 constexpr int copyWidth = std::min(targetWidth, srcWidth);
117 constexpr int copyHeight = std::min(targetHeight, srcHeight);
118
119 T staging[targetWidth * targetHeight] = {0};
Jamie Madill334d6152015-10-22 14:00:28 -0400120
121 for (int y = 0; y < copyHeight; y++)
122 {
123 for (int x = 0; x < copyWidth; x++)
124 {
Corentin Wallezb58e9ba2016-12-15 14:07:56 -0800125 staging[y * targetWidth + x] = static_cast<T>(value[y * srcWidth + x]);
Jamie Madill334d6152015-10-22 14:00:28 -0400126 }
127 }
128
Corentin Wallezb58e9ba2016-12-15 14:07:56 -0800129 if (memcmp(target, staging, targetWidth * targetHeight * sizeof(T)) == 0)
130 {
131 return false;
132 }
133
134 memcpy(target, staging, targetWidth * targetHeight * sizeof(T));
135 return true;
Jamie Madill334d6152015-10-22 14:00:28 -0400136}
137
Jamie Madill4e31ad52015-10-29 10:32:57 -0400138gl::PrimitiveType GetGeometryShaderTypeFromDrawMode(GLenum drawMode)
139{
140 switch (drawMode)
141 {
142 // Uses the point sprite geometry shader.
143 case GL_POINTS:
144 return gl::PRIMITIVE_POINTS;
145
146 // All line drawing uses the same geometry shader.
147 case GL_LINES:
148 case GL_LINE_STRIP:
149 case GL_LINE_LOOP:
150 return gl::PRIMITIVE_LINES;
151
152 // The triangle fan primitive is emulated with strips in D3D11.
153 case GL_TRIANGLES:
154 case GL_TRIANGLE_FAN:
155 return gl::PRIMITIVE_TRIANGLES;
156
157 // Special case for triangle strips.
158 case GL_TRIANGLE_STRIP:
159 return gl::PRIMITIVE_TRIANGLE_STRIP;
160
161 default:
162 UNREACHABLE();
163 return gl::PRIMITIVE_TYPE_MAX;
164 }
165}
166
Jamie Madill192745a2016-12-22 15:58:21 -0500167bool FindFlatInterpolationVarying(const std::vector<sh::Varying> &varyings)
168{
169 // Note: this assumes nested structs can only be packed with one interpolation.
170 for (const auto &varying : varyings)
171 {
172 if (varying.interpolation == sh::INTERPOLATION_FLAT)
173 {
174 return true;
175 }
176 }
177
178 return false;
179}
180
Jamie Madillbe5e2ec2017-08-31 13:28:28 -0400181// Helper method to de-tranpose a matrix uniform for an API query.
182void GetMatrixUniform(GLint columns, GLint rows, GLfloat *dataOut, const GLfloat *source)
183{
184 for (GLint col = 0; col < columns; ++col)
185 {
186 for (GLint row = 0; row < rows; ++row)
187 {
188 GLfloat *outptr = dataOut + ((col * rows) + row);
189 const GLfloat *inptr = source + ((row * 4) + col);
190 *outptr = *inptr;
191 }
192 }
193}
194
195template <typename NonFloatT>
196void GetMatrixUniform(GLint columns, GLint rows, NonFloatT *dataOut, const NonFloatT *source)
197{
198 UNREACHABLE();
199}
200
Jamie Madillada9ecc2015-08-17 12:53:37 -0400201} // anonymous namespace
202
Jamie Madill28afae52015-11-09 15:07:57 -0500203// D3DUniform Implementation
204
Jamie Madill33bb7c42017-09-09 23:32:51 -0400205D3DUniform::D3DUniform(GLenum type,
Jamie Madill62d31cb2015-09-11 13:25:51 -0400206 const std::string &nameIn,
207 unsigned int arraySizeIn,
208 bool defaultBlock)
Jamie Madill33bb7c42017-09-09 23:32:51 -0400209 : typeInfo(gl::GetUniformTypeInfo(type)),
Jamie Madill62d31cb2015-09-11 13:25:51 -0400210 name(nameIn),
211 arraySize(arraySizeIn),
Jamie Madillbe5e2ec2017-08-31 13:28:28 -0400212 vsData(nullptr),
213 psData(nullptr),
214 csData(nullptr),
Jamie Madill62d31cb2015-09-11 13:25:51 -0400215 vsRegisterIndex(GL_INVALID_INDEX),
Geoff Lang98c56da2015-09-15 15:45:34 -0400216 psRegisterIndex(GL_INVALID_INDEX),
Xinghua Caob1239382016-12-13 15:07:05 +0800217 csRegisterIndex(GL_INVALID_INDEX),
Jamie Madill62d31cb2015-09-11 13:25:51 -0400218 registerCount(0),
219 registerElement(0)
220{
221 // We use data storage for default block uniforms to cache values that are sent to D3D during
222 // rendering
223 // Uniform blocks/buffers are treated separately by the Renderer (ES3 path only)
224 if (defaultBlock)
225 {
Jamie Madillcc2ed612017-03-14 15:59:00 -0400226 // Use the row count as register count, will work for non-square matrices.
Jamie Madill33bb7c42017-09-09 23:32:51 -0400227 registerCount = typeInfo.rowCount * elementCount();
Jamie Madill62d31cb2015-09-11 13:25:51 -0400228 }
229}
230
231D3DUniform::~D3DUniform()
232{
Jamie Madillbe5e2ec2017-08-31 13:28:28 -0400233}
234
235const uint8_t *D3DUniform::getDataPtrToElement(size_t elementIndex) const
236{
237 ASSERT((arraySize == 0 && elementIndex == 0) || (arraySize > 0 && elementIndex < arraySize));
238
239 if (isSampler())
240 {
241 return reinterpret_cast<const uint8_t *>(&mSamplerData[elementIndex]);
242 }
243
Jamie Madill33bb7c42017-09-09 23:32:51 -0400244 return firstNonNullData() + (elementIndex > 0 ? (typeInfo.internalSize * elementIndex) : 0u);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400245}
246
247bool D3DUniform::isSampler() const
248{
Jamie Madill33bb7c42017-09-09 23:32:51 -0400249 return typeInfo.isSampler;
Jamie Madill62d31cb2015-09-11 13:25:51 -0400250}
251
252bool D3DUniform::isReferencedByVertexShader() const
253{
254 return vsRegisterIndex != GL_INVALID_INDEX;
255}
256
257bool D3DUniform::isReferencedByFragmentShader() const
258{
259 return psRegisterIndex != GL_INVALID_INDEX;
260}
261
Xinghua Caob1239382016-12-13 15:07:05 +0800262bool D3DUniform::isReferencedByComputeShader() const
263{
264 return csRegisterIndex != GL_INVALID_INDEX;
265}
266
Jamie Madillbe5e2ec2017-08-31 13:28:28 -0400267const uint8_t *D3DUniform::firstNonNullData() const
268{
269 ASSERT(vsData || psData || csData || !mSamplerData.empty());
270
271 if (!mSamplerData.empty())
272 {
273 return reinterpret_cast<const uint8_t *>(mSamplerData.data());
274 }
275
276 return vsData ? vsData : (psData ? psData : csData);
277}
278
Jamie Madill28afae52015-11-09 15:07:57 -0500279// D3DVarying Implementation
280
Jamie Madill9fc36822015-11-18 13:08:07 -0500281D3DVarying::D3DVarying() : semanticIndex(0), componentCount(0), outputSlot(0)
Jamie Madill28afae52015-11-09 15:07:57 -0500282{
283}
284
Jamie Madill9fc36822015-11-18 13:08:07 -0500285D3DVarying::D3DVarying(const std::string &semanticNameIn,
286 unsigned int semanticIndexIn,
287 unsigned int componentCountIn,
288 unsigned int outputSlotIn)
289 : semanticName(semanticNameIn),
290 semanticIndex(semanticIndexIn),
291 componentCount(componentCountIn),
292 outputSlot(outputSlotIn)
Jamie Madill28afae52015-11-09 15:07:57 -0500293{
294}
295
Jamie Madille39a3f02015-11-17 20:42:15 -0500296// ProgramD3DMetadata Implementation
297
Jamie Madillc9bde922016-07-24 17:58:50 -0400298ProgramD3DMetadata::ProgramD3DMetadata(RendererD3D *renderer,
Jamie Madille39a3f02015-11-17 20:42:15 -0500299 const ShaderD3D *vertexShader,
300 const ShaderD3D *fragmentShader)
Jamie Madillc9bde922016-07-24 17:58:50 -0400301 : mRendererMajorShaderModel(renderer->getMajorShaderModel()),
302 mShaderModelSuffix(renderer->getShaderModelSuffix()),
303 mUsesInstancedPointSpriteEmulation(
304 renderer->getWorkarounds().useInstancedPointSpriteEmulation),
305 mUsesViewScale(renderer->presentPathFastEnabled()),
Martin Radev41ac68e2017-06-06 12:16:58 +0300306 mHasANGLEMultiviewEnabled(vertexShader->hasANGLEMultiviewEnabled()),
307 mUsesViewID(fragmentShader->usesViewID()),
Martin Radevc1d4e552017-08-21 12:01:10 +0300308 mCanSelectViewInVertexShader(renderer->canSelectViewInVertexShader()),
Jamie Madille39a3f02015-11-17 20:42:15 -0500309 mVertexShader(vertexShader),
310 mFragmentShader(fragmentShader)
311{
312}
313
314int ProgramD3DMetadata::getRendererMajorShaderModel() const
315{
316 return mRendererMajorShaderModel;
317}
318
Jamie Madill9082b982016-04-27 15:21:51 -0400319bool ProgramD3DMetadata::usesBroadcast(const gl::ContextState &data) const
Jamie Madille39a3f02015-11-17 20:42:15 -0500320{
Corentin Wallezc084de12017-06-05 14:28:52 -0700321 return (mFragmentShader->usesFragColor() && mFragmentShader->usesMultipleRenderTargets() &&
322 data.getClientMajorVersion() < 3);
Jamie Madille39a3f02015-11-17 20:42:15 -0500323}
324
Jamie Madill48ef11b2016-04-27 15:21:52 -0400325bool ProgramD3DMetadata::usesFragDepth() const
Jamie Madille39a3f02015-11-17 20:42:15 -0500326{
Jamie Madill63286672015-11-24 13:00:08 -0500327 return mFragmentShader->usesFragDepth();
Jamie Madille39a3f02015-11-17 20:42:15 -0500328}
329
330bool ProgramD3DMetadata::usesPointCoord() const
331{
332 return mFragmentShader->usesPointCoord();
333}
334
335bool ProgramD3DMetadata::usesFragCoord() const
336{
337 return mFragmentShader->usesFragCoord();
338}
339
340bool ProgramD3DMetadata::usesPointSize() const
341{
342 return mVertexShader->usesPointSize();
343}
344
345bool ProgramD3DMetadata::usesInsertedPointCoordValue() const
346{
Jamie Madillc9bde922016-07-24 17:58:50 -0400347 return (!usesPointSize() || !mUsesInstancedPointSpriteEmulation) && usesPointCoord() &&
348 mRendererMajorShaderModel >= 4;
Jamie Madille39a3f02015-11-17 20:42:15 -0500349}
350
Austin Kinross2a63b3f2016-02-08 12:29:08 -0800351bool ProgramD3DMetadata::usesViewScale() const
352{
353 return mUsesViewScale;
354}
355
Martin Radev41ac68e2017-06-06 12:16:58 +0300356bool ProgramD3DMetadata::hasANGLEMultiviewEnabled() const
357{
358 return mHasANGLEMultiviewEnabled;
359}
360
361bool ProgramD3DMetadata::usesViewID() const
362{
363 return mUsesViewID;
364}
365
Martin Radevc1d4e552017-08-21 12:01:10 +0300366bool ProgramD3DMetadata::canSelectViewInVertexShader() const
367{
368 return mCanSelectViewInVertexShader;
369}
370
Jamie Madille39a3f02015-11-17 20:42:15 -0500371bool ProgramD3DMetadata::addsPointCoordToVertexShader() const
372{
Jamie Madillc9bde922016-07-24 17:58:50 -0400373 // PointSprite emulation requiress that gl_PointCoord is present in the vertex shader
Jamie Madille39a3f02015-11-17 20:42:15 -0500374 // VS_OUTPUT structure to ensure compatibility with the generated PS_INPUT of the pixel shader.
Jamie Madillc9bde922016-07-24 17:58:50 -0400375 // Even with a geometry shader, the app can render triangles or lines and reference
376 // gl_PointCoord in the fragment shader, requiring us to provide a dummy value. For
377 // simplicity, we always add this to the vertex shader when the fragment shader
378 // references gl_PointCoord, even if we could skip it in the geometry shader.
Jamie Madille39a3f02015-11-17 20:42:15 -0500379 return (mUsesInstancedPointSpriteEmulation && usesPointCoord()) ||
380 usesInsertedPointCoordValue();
381}
382
383bool ProgramD3DMetadata::usesTransformFeedbackGLPosition() const
384{
385 // gl_Position only needs to be outputted from the vertex shader if transform feedback is
386 // active. This isn't supported on D3D11 Feature Level 9_3, so we don't output gl_Position from
387 // the vertex shader in this case. This saves us 1 output vector.
388 return !(mRendererMajorShaderModel >= 4 && mShaderModelSuffix != "");
389}
390
391bool ProgramD3DMetadata::usesSystemValuePointSize() const
392{
393 return !mUsesInstancedPointSpriteEmulation && usesPointSize();
394}
395
396bool ProgramD3DMetadata::usesMultipleFragmentOuts() const
397{
398 return mFragmentShader->usesMultipleRenderTargets();
399}
400
401GLint ProgramD3DMetadata::getMajorShaderVersion() const
402{
403 return mVertexShader->getData().getShaderVersion();
404}
405
406const ShaderD3D *ProgramD3DMetadata::getFragmentShader() const
407{
408 return mFragmentShader;
409}
410
Jamie Madill28afae52015-11-09 15:07:57 -0500411// ProgramD3D Implementation
412
Jamie Madilld3dfda22015-07-06 08:28:49 -0400413ProgramD3D::VertexExecutable::VertexExecutable(const gl::InputLayout &inputLayout,
414 const Signature &signature,
Geoff Lang359ef262015-01-05 14:42:29 -0500415 ShaderExecutableD3D *shaderExecutable)
Jamie Madill334d6152015-10-22 14:00:28 -0400416 : mInputs(inputLayout), mSignature(signature), mShaderExecutable(shaderExecutable)
Brandon Joneseb994362014-09-24 10:27:28 -0700417{
Brandon Joneseb994362014-09-24 10:27:28 -0700418}
419
420ProgramD3D::VertexExecutable::~VertexExecutable()
421{
422 SafeDelete(mShaderExecutable);
423}
424
Jamie Madilld3dfda22015-07-06 08:28:49 -0400425// static
Jamie Madillbdec2f42016-03-02 16:35:32 -0500426ProgramD3D::VertexExecutable::HLSLAttribType ProgramD3D::VertexExecutable::GetAttribType(
427 GLenum type)
428{
429 switch (type)
430 {
431 case GL_INT:
432 return HLSLAttribType::SIGNED_INT;
433 case GL_UNSIGNED_INT:
434 return HLSLAttribType::UNSIGNED_INT;
435 case GL_SIGNED_NORMALIZED:
436 case GL_UNSIGNED_NORMALIZED:
437 case GL_FLOAT:
438 return HLSLAttribType::FLOAT;
439 default:
440 UNREACHABLE();
441 return HLSLAttribType::FLOAT;
442 }
443}
444
445// static
Jamie Madilld3dfda22015-07-06 08:28:49 -0400446void ProgramD3D::VertexExecutable::getSignature(RendererD3D *renderer,
447 const gl::InputLayout &inputLayout,
448 Signature *signatureOut)
Brandon Joneseb994362014-09-24 10:27:28 -0700449{
Jamie Madillbdec2f42016-03-02 16:35:32 -0500450 signatureOut->assign(inputLayout.size(), HLSLAttribType::FLOAT);
Jamie Madilld3dfda22015-07-06 08:28:49 -0400451
452 for (size_t index = 0; index < inputLayout.size(); ++index)
Brandon Joneseb994362014-09-24 10:27:28 -0700453 {
Jamie Madilld3dfda22015-07-06 08:28:49 -0400454 gl::VertexFormatType vertexFormatType = inputLayout[index];
Jamie Madillbdec2f42016-03-02 16:35:32 -0500455 if (vertexFormatType == gl::VERTEX_FORMAT_INVALID)
456 continue;
Jamie Madillbd136f92015-08-10 14:51:37 -0400457
Jamie Madillbdec2f42016-03-02 16:35:32 -0500458 VertexConversionType conversionType = renderer->getVertexConversionType(vertexFormatType);
459 if ((conversionType & VERTEX_CONVERT_GPU) == 0)
460 continue;
461
462 GLenum componentType = renderer->getVertexComponentType(vertexFormatType);
463 (*signatureOut)[index] = GetAttribType(componentType);
Brandon Joneseb994362014-09-24 10:27:28 -0700464 }
Brandon Joneseb994362014-09-24 10:27:28 -0700465}
466
Jamie Madilld3dfda22015-07-06 08:28:49 -0400467bool ProgramD3D::VertexExecutable::matchesSignature(const Signature &signature) const
468{
Jamie Madillbd136f92015-08-10 14:51:37 -0400469 size_t limit = std::max(mSignature.size(), signature.size());
470 for (size_t index = 0; index < limit; ++index)
471 {
Jamie Madillbdec2f42016-03-02 16:35:32 -0500472 // treat undefined indexes as FLOAT
473 auto a = index < signature.size() ? signature[index] : HLSLAttribType::FLOAT;
474 auto b = index < mSignature.size() ? mSignature[index] : HLSLAttribType::FLOAT;
Jamie Madillbd136f92015-08-10 14:51:37 -0400475 if (a != b)
476 return false;
477 }
478
479 return true;
Jamie Madilld3dfda22015-07-06 08:28:49 -0400480}
481
482ProgramD3D::PixelExecutable::PixelExecutable(const std::vector<GLenum> &outputSignature,
483 ShaderExecutableD3D *shaderExecutable)
Jamie Madill334d6152015-10-22 14:00:28 -0400484 : mOutputSignature(outputSignature), mShaderExecutable(shaderExecutable)
Brandon Joneseb994362014-09-24 10:27:28 -0700485{
486}
487
488ProgramD3D::PixelExecutable::~PixelExecutable()
489{
490 SafeDelete(mShaderExecutable);
491}
492
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700493ProgramD3D::Sampler::Sampler() : active(false), logicalTextureUnit(0), textureType(GL_TEXTURE_2D)
494{
495}
496
Geoff Lang7dd2e102014-11-10 15:19:26 -0500497unsigned int ProgramD3D::mCurrentSerial = 1;
498
Jamie Madill48ef11b2016-04-27 15:21:52 -0400499ProgramD3D::ProgramD3D(const gl::ProgramState &state, RendererD3D *renderer)
500 : ProgramImpl(state),
Brandon Jonesc9610c52014-08-25 17:02:59 -0700501 mRenderer(renderer),
Xinghua Caob1239382016-12-13 15:07:05 +0800502 mDynamicHLSL(nullptr),
503 mGeometryExecutables(gl::PRIMITIVE_TYPE_MAX),
504 mComputeExecutable(nullptr),
Brandon Jones44151a92014-09-10 11:32:25 -0700505 mUsesPointSize(false),
Jamie Madill3e14e2b2015-10-29 14:38:53 -0400506 mUsesFlatInterpolation(false),
Xinghua Caob1239382016-12-13 15:07:05 +0800507 mVertexUniformStorage(nullptr),
508 mFragmentUniformStorage(nullptr),
509 mComputeUniformStorage(nullptr),
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700510 mUsedVertexSamplerRange(0),
511 mUsedPixelSamplerRange(0),
Xinghua Caob1239382016-12-13 15:07:05 +0800512 mUsedComputeSamplerRange(0),
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700513 mDirtySamplerMapping(true),
Jamie Madill561ed3a2017-08-31 16:48:09 -0400514 mSerial(issueSerial()),
Jamie Madill4148fd72017-09-14 15:46:20 -0400515 mVertexUniformsDirty(true),
516 mFragmentUniformsDirty(true),
517 mComputeUniformsDirty(true)
Brandon Jonesc9610c52014-08-25 17:02:59 -0700518{
Brandon Joneseb994362014-09-24 10:27:28 -0700519 mDynamicHLSL = new DynamicHLSL(renderer);
Brandon Jonesc9610c52014-08-25 17:02:59 -0700520}
521
522ProgramD3D::~ProgramD3D()
523{
524 reset();
525 SafeDelete(mDynamicHLSL);
526}
527
Brandon Jones44151a92014-09-10 11:32:25 -0700528bool ProgramD3D::usesPointSpriteEmulation() const
529{
530 return mUsesPointSize && mRenderer->getMajorShaderModel() >= 4;
531}
532
Martin Radev41ac68e2017-06-06 12:16:58 +0300533bool ProgramD3D::usesGeometryShaderForPointSpriteEmulation() const
534{
535 return usesPointSpriteEmulation() && !usesInstancedPointSpriteEmulation();
536}
537
Jamie Madill3e14e2b2015-10-29 14:38:53 -0400538bool ProgramD3D::usesGeometryShader(GLenum drawMode) const
Brandon Jones44151a92014-09-10 11:32:25 -0700539{
Martin Radevc1d4e552017-08-21 12:01:10 +0300540 if (mHasANGLEMultiviewEnabled && !mRenderer->canSelectViewInVertexShader())
Martin Radev41ac68e2017-06-06 12:16:58 +0300541 {
542 return true;
543 }
Jamie Madill3e14e2b2015-10-29 14:38:53 -0400544 if (drawMode != GL_POINTS)
545 {
546 return mUsesFlatInterpolation;
547 }
Martin Radev41ac68e2017-06-06 12:16:58 +0300548 return usesGeometryShaderForPointSpriteEmulation();
Cooper Partine6664f02015-01-09 16:22:24 -0800549}
550
551bool ProgramD3D::usesInstancedPointSpriteEmulation() const
552{
553 return mRenderer->getWorkarounds().useInstancedPointSpriteEmulation;
Brandon Jones44151a92014-09-10 11:32:25 -0700554}
555
Jamie Madill334d6152015-10-22 14:00:28 -0400556GLint ProgramD3D::getSamplerMapping(gl::SamplerType type,
557 unsigned int samplerIndex,
558 const gl::Caps &caps) const
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700559{
560 GLint logicalTextureUnit = -1;
561
562 switch (type)
563 {
Jamie Madill334d6152015-10-22 14:00:28 -0400564 case gl::SAMPLER_PIXEL:
565 ASSERT(samplerIndex < caps.maxTextureImageUnits);
566 if (samplerIndex < mSamplersPS.size() && mSamplersPS[samplerIndex].active)
567 {
568 logicalTextureUnit = mSamplersPS[samplerIndex].logicalTextureUnit;
569 }
570 break;
571 case gl::SAMPLER_VERTEX:
572 ASSERT(samplerIndex < caps.maxVertexTextureImageUnits);
573 if (samplerIndex < mSamplersVS.size() && mSamplersVS[samplerIndex].active)
574 {
575 logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit;
576 }
577 break;
Xinghua Caob1239382016-12-13 15:07:05 +0800578 case gl::SAMPLER_COMPUTE:
579 ASSERT(samplerIndex < caps.maxComputeTextureImageUnits);
580 if (samplerIndex < mSamplersCS.size() && mSamplersCS[samplerIndex].active)
581 {
582 logicalTextureUnit = mSamplersCS[samplerIndex].logicalTextureUnit;
583 }
584 break;
Jamie Madill334d6152015-10-22 14:00:28 -0400585 default:
586 UNREACHABLE();
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700587 }
588
Jamie Madill334d6152015-10-22 14:00:28 -0400589 if (logicalTextureUnit >= 0 &&
590 logicalTextureUnit < static_cast<GLint>(caps.maxCombinedTextureImageUnits))
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700591 {
592 return logicalTextureUnit;
593 }
594
595 return -1;
596}
597
598// Returns the texture type for a given Direct3D 9 sampler type and
599// index (0-15 for the pixel shader and 0-3 for the vertex shader).
600GLenum ProgramD3D::getSamplerTextureType(gl::SamplerType type, unsigned int samplerIndex) const
601{
602 switch (type)
603 {
Jamie Madill334d6152015-10-22 14:00:28 -0400604 case gl::SAMPLER_PIXEL:
605 ASSERT(samplerIndex < mSamplersPS.size());
606 ASSERT(mSamplersPS[samplerIndex].active);
607 return mSamplersPS[samplerIndex].textureType;
608 case gl::SAMPLER_VERTEX:
609 ASSERT(samplerIndex < mSamplersVS.size());
610 ASSERT(mSamplersVS[samplerIndex].active);
611 return mSamplersVS[samplerIndex].textureType;
Xinghua Caob1239382016-12-13 15:07:05 +0800612 case gl::SAMPLER_COMPUTE:
613 ASSERT(samplerIndex < mSamplersCS.size());
614 ASSERT(mSamplersCS[samplerIndex].active);
615 return mSamplersCS[samplerIndex].textureType;
Jamie Madill334d6152015-10-22 14:00:28 -0400616 default:
617 UNREACHABLE();
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700618 }
619
620 return GL_TEXTURE_2D;
621}
622
Olli Etuaho618bebc2016-01-15 16:40:00 +0200623GLuint ProgramD3D::getUsedSamplerRange(gl::SamplerType type) const
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700624{
625 switch (type)
626 {
Jamie Madill334d6152015-10-22 14:00:28 -0400627 case gl::SAMPLER_PIXEL:
628 return mUsedPixelSamplerRange;
629 case gl::SAMPLER_VERTEX:
630 return mUsedVertexSamplerRange;
Xinghua Caob1239382016-12-13 15:07:05 +0800631 case gl::SAMPLER_COMPUTE:
632 return mUsedComputeSamplerRange;
Jamie Madill334d6152015-10-22 14:00:28 -0400633 default:
634 UNREACHABLE();
Olli Etuaho618bebc2016-01-15 16:40:00 +0200635 return 0u;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700636 }
637}
638
Jamie Madillaf4ffe02017-09-09 23:32:48 -0400639ProgramD3D::SamplerMapping ProgramD3D::updateSamplerMapping()
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700640{
641 if (!mDirtySamplerMapping)
642 {
Jamie Madillaf4ffe02017-09-09 23:32:48 -0400643 return SamplerMapping::WasClean;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700644 }
645
646 mDirtySamplerMapping = false;
647
648 // Retrieve sampler uniform values
Jamie Madill62d31cb2015-09-11 13:25:51 -0400649 for (const D3DUniform *d3dUniform : mD3DUniforms)
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700650 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400651 if (!d3dUniform->isSampler())
652 continue;
653
654 int count = d3dUniform->elementCount();
Jamie Madill62d31cb2015-09-11 13:25:51 -0400655
656 if (d3dUniform->isReferencedByFragmentShader())
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700657 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400658 unsigned int firstIndex = d3dUniform->psRegisterIndex;
659
660 for (int i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700661 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400662 unsigned int samplerIndex = firstIndex + i;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700663
Jamie Madill62d31cb2015-09-11 13:25:51 -0400664 if (samplerIndex < mSamplersPS.size())
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700665 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400666 ASSERT(mSamplersPS[samplerIndex].active);
Jamie Madillbe5e2ec2017-08-31 13:28:28 -0400667 mSamplersPS[samplerIndex].logicalTextureUnit = d3dUniform->mSamplerData[i];
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700668 }
Jamie Madill62d31cb2015-09-11 13:25:51 -0400669 }
670 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700671
Jamie Madill62d31cb2015-09-11 13:25:51 -0400672 if (d3dUniform->isReferencedByVertexShader())
673 {
674 unsigned int firstIndex = d3dUniform->vsRegisterIndex;
675
676 for (int i = 0; i < count; i++)
677 {
678 unsigned int samplerIndex = firstIndex + i;
679
680 if (samplerIndex < mSamplersVS.size())
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700681 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400682 ASSERT(mSamplersVS[samplerIndex].active);
Jamie Madillbe5e2ec2017-08-31 13:28:28 -0400683 mSamplersVS[samplerIndex].logicalTextureUnit = d3dUniform->mSamplerData[i];
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700684 }
685 }
686 }
Xinghua Caob1239382016-12-13 15:07:05 +0800687
688 if (d3dUniform->isReferencedByComputeShader())
689 {
690 unsigned int firstIndex = d3dUniform->csRegisterIndex;
691
692 for (int i = 0; i < count; i++)
693 {
694 unsigned int samplerIndex = firstIndex + i;
695
696 if (samplerIndex < mSamplersCS.size())
697 {
698 ASSERT(mSamplersCS[samplerIndex].active);
Jamie Madillbe5e2ec2017-08-31 13:28:28 -0400699 mSamplersCS[samplerIndex].logicalTextureUnit = d3dUniform->mSamplerData[i];
Xinghua Caob1239382016-12-13 15:07:05 +0800700 }
701 }
702 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700703 }
Jamie Madillaf4ffe02017-09-09 23:32:48 -0400704
705 return SamplerMapping::WasDirty;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700706}
707
Jamie Madill9cf9e872017-06-05 12:59:25 -0400708gl::LinkResult ProgramD3D::load(const gl::Context *context,
709 gl::InfoLog &infoLog,
710 gl::BinaryInputStream *stream)
Brandon Jones22502d52014-08-29 16:58:36 -0700711{
Jamie Madilla7d12dc2016-12-13 15:08:19 -0500712 // TODO(jmadill): Use Renderer from contextImpl.
713
Jamie Madill62d31cb2015-09-11 13:25:51 -0400714 reset();
715
Jamie Madill334d6152015-10-22 14:00:28 -0400716 DeviceIdentifier binaryDeviceIdentifier = {0};
717 stream->readBytes(reinterpret_cast<unsigned char *>(&binaryDeviceIdentifier),
718 sizeof(DeviceIdentifier));
Austin Kinross137b1512015-06-17 16:14:53 -0700719
720 DeviceIdentifier identifier = mRenderer->getAdapterIdentifier();
721 if (memcmp(&identifier, &binaryDeviceIdentifier, sizeof(DeviceIdentifier)) != 0)
722 {
723 infoLog << "Invalid program binary, device configuration has changed.";
Jamie Madillb0a838b2016-11-13 20:02:12 -0500724 return false;
Austin Kinross137b1512015-06-17 16:14:53 -0700725 }
726
Jamie Madill2db1fbb2014-12-03 10:58:55 -0500727 int compileFlags = stream->readInt<int>();
728 if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL)
729 {
Jamie Madillf6113162015-05-07 11:49:21 -0400730 infoLog << "Mismatched compilation flags.";
Jamie Madillb0a838b2016-11-13 20:02:12 -0500731 return false;
Jamie Madill2db1fbb2014-12-03 10:58:55 -0500732 }
733
Jamie Madill8047c0d2016-03-07 13:02:12 -0500734 for (int &index : mAttribLocationToD3DSemantic)
Jamie Madill63805b42015-08-25 13:17:39 -0400735 {
Jamie Madill8047c0d2016-03-07 13:02:12 -0500736 stream->readInt(&index);
Jamie Madill63805b42015-08-25 13:17:39 -0400737 }
738
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700739 const unsigned int psSamplerCount = stream->readInt<unsigned int>();
740 for (unsigned int i = 0; i < psSamplerCount; ++i)
741 {
742 Sampler sampler;
743 stream->readBool(&sampler.active);
744 stream->readInt(&sampler.logicalTextureUnit);
745 stream->readInt(&sampler.textureType);
746 mSamplersPS.push_back(sampler);
747 }
748 const unsigned int vsSamplerCount = stream->readInt<unsigned int>();
749 for (unsigned int i = 0; i < vsSamplerCount; ++i)
750 {
751 Sampler sampler;
752 stream->readBool(&sampler.active);
753 stream->readInt(&sampler.logicalTextureUnit);
754 stream->readInt(&sampler.textureType);
755 mSamplersVS.push_back(sampler);
756 }
757
Xinghua Caob1239382016-12-13 15:07:05 +0800758 const unsigned int csSamplerCount = stream->readInt<unsigned int>();
759 for (unsigned int i = 0; i < csSamplerCount; ++i)
760 {
761 Sampler sampler;
762 stream->readBool(&sampler.active);
763 stream->readInt(&sampler.logicalTextureUnit);
764 stream->readInt(&sampler.textureType);
765 mSamplersCS.push_back(sampler);
766 }
767
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700768 stream->readInt(&mUsedVertexSamplerRange);
769 stream->readInt(&mUsedPixelSamplerRange);
Xinghua Caob1239382016-12-13 15:07:05 +0800770 stream->readInt(&mUsedComputeSamplerRange);
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700771
772 const unsigned int uniformCount = stream->readInt<unsigned int>();
773 if (stream->error())
774 {
Jamie Madillf6113162015-05-07 11:49:21 -0400775 infoLog << "Invalid program binary.";
Jamie Madillb0a838b2016-11-13 20:02:12 -0500776 return false;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700777 }
778
Jamie Madill48ef11b2016-04-27 15:21:52 -0400779 const auto &linkedUniforms = mState.getUniforms();
Jamie Madill62d31cb2015-09-11 13:25:51 -0400780 ASSERT(mD3DUniforms.empty());
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700781 for (unsigned int uniformIndex = 0; uniformIndex < uniformCount; uniformIndex++)
782 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400783 const gl::LinkedUniform &linkedUniform = linkedUniforms[uniformIndex];
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700784
Jamie Madill62d31cb2015-09-11 13:25:51 -0400785 D3DUniform *d3dUniform =
786 new D3DUniform(linkedUniform.type, linkedUniform.name, linkedUniform.arraySize,
787 linkedUniform.isInDefaultBlock());
788 stream->readInt(&d3dUniform->psRegisterIndex);
789 stream->readInt(&d3dUniform->vsRegisterIndex);
Xinghua Caob1239382016-12-13 15:07:05 +0800790 stream->readInt(&d3dUniform->csRegisterIndex);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400791 stream->readInt(&d3dUniform->registerCount);
792 stream->readInt(&d3dUniform->registerElement);
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700793
Jamie Madill62d31cb2015-09-11 13:25:51 -0400794 mD3DUniforms.push_back(d3dUniform);
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700795 }
796
Jamie Madill4a3c2342015-10-08 12:58:45 -0400797 const unsigned int blockCount = stream->readInt<unsigned int>();
798 if (stream->error())
799 {
800 infoLog << "Invalid program binary.";
Jamie Madillb0a838b2016-11-13 20:02:12 -0500801 return false;
Jamie Madill4a3c2342015-10-08 12:58:45 -0400802 }
803
804 ASSERT(mD3DUniformBlocks.empty());
805 for (unsigned int blockIndex = 0; blockIndex < blockCount; ++blockIndex)
806 {
807 D3DUniformBlock uniformBlock;
808 stream->readInt(&uniformBlock.psRegisterIndex);
809 stream->readInt(&uniformBlock.vsRegisterIndex);
Xinghua Caob1239382016-12-13 15:07:05 +0800810 stream->readInt(&uniformBlock.csRegisterIndex);
Jamie Madill4a3c2342015-10-08 12:58:45 -0400811 mD3DUniformBlocks.push_back(uniformBlock);
812 }
813
Jamie Madill9fc36822015-11-18 13:08:07 -0500814 const unsigned int streamOutVaryingCount = stream->readInt<unsigned int>();
815 mStreamOutVaryings.resize(streamOutVaryingCount);
816 for (unsigned int varyingIndex = 0; varyingIndex < streamOutVaryingCount; ++varyingIndex)
Brandon Joneseb994362014-09-24 10:27:28 -0700817 {
Jamie Madill9fc36822015-11-18 13:08:07 -0500818 D3DVarying *varying = &mStreamOutVaryings[varyingIndex];
Brandon Joneseb994362014-09-24 10:27:28 -0700819
Jamie Madill28afae52015-11-09 15:07:57 -0500820 stream->readString(&varying->semanticName);
821 stream->readInt(&varying->semanticIndex);
Jamie Madill9fc36822015-11-18 13:08:07 -0500822 stream->readInt(&varying->componentCount);
823 stream->readInt(&varying->outputSlot);
Brandon Joneseb994362014-09-24 10:27:28 -0700824 }
825
Brandon Jones22502d52014-08-29 16:58:36 -0700826 stream->readString(&mVertexHLSL);
Jamie Madill334d6152015-10-22 14:00:28 -0400827 stream->readBytes(reinterpret_cast<unsigned char *>(&mVertexWorkarounds),
Jamie Madill408293f2016-12-20 10:11:45 -0500828 sizeof(angle::CompilerWorkaroundsD3D));
Brandon Jones22502d52014-08-29 16:58:36 -0700829 stream->readString(&mPixelHLSL);
Jamie Madill334d6152015-10-22 14:00:28 -0400830 stream->readBytes(reinterpret_cast<unsigned char *>(&mPixelWorkarounds),
Jamie Madill408293f2016-12-20 10:11:45 -0500831 sizeof(angle::CompilerWorkaroundsD3D));
Brandon Jones22502d52014-08-29 16:58:36 -0700832 stream->readBool(&mUsesFragDepth);
Martin Radev41ac68e2017-06-06 12:16:58 +0300833 stream->readBool(&mHasANGLEMultiviewEnabled);
834 stream->readBool(&mUsesViewID);
Brandon Jones44151a92014-09-10 11:32:25 -0700835 stream->readBool(&mUsesPointSize);
Jamie Madill3e14e2b2015-10-29 14:38:53 -0400836 stream->readBool(&mUsesFlatInterpolation);
Brandon Jones22502d52014-08-29 16:58:36 -0700837
838 const size_t pixelShaderKeySize = stream->readInt<unsigned int>();
839 mPixelShaderKey.resize(pixelShaderKeySize);
Jamie Madill334d6152015-10-22 14:00:28 -0400840 for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKeySize;
841 pixelShaderKeyIndex++)
Brandon Jones22502d52014-08-29 16:58:36 -0700842 {
843 stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].type);
844 stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].name);
845 stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].source);
846 stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].outputIndex);
847 }
848
Jamie Madill4e31ad52015-10-29 10:32:57 -0400849 stream->readString(&mGeometryShaderPreamble);
850
Jamie Madill334d6152015-10-22 14:00:28 -0400851 const unsigned char *binary = reinterpret_cast<const unsigned char *>(stream->data());
Brandon Joneseb994362014-09-24 10:27:28 -0700852
Jamie Madillb0a838b2016-11-13 20:02:12 -0500853 bool separateAttribs = (mState.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS);
854
Brandon Joneseb994362014-09-24 10:27:28 -0700855 const unsigned int vertexShaderCount = stream->readInt<unsigned int>();
Jamie Madill334d6152015-10-22 14:00:28 -0400856 for (unsigned int vertexShaderIndex = 0; vertexShaderIndex < vertexShaderCount;
857 vertexShaderIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -0700858 {
Jamie Madilld3dfda22015-07-06 08:28:49 -0400859 size_t inputLayoutSize = stream->readInt<size_t>();
Jamie Madillf8dd7b12015-08-05 13:50:08 -0400860 gl::InputLayout inputLayout(inputLayoutSize, gl::VERTEX_FORMAT_INVALID);
Brandon Joneseb994362014-09-24 10:27:28 -0700861
Jamie Madilld3dfda22015-07-06 08:28:49 -0400862 for (size_t inputIndex = 0; inputIndex < inputLayoutSize; inputIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -0700863 {
Jamie Madillf8dd7b12015-08-05 13:50:08 -0400864 inputLayout[inputIndex] = stream->readInt<gl::VertexFormatType>();
Brandon Joneseb994362014-09-24 10:27:28 -0700865 }
866
Jamie Madill334d6152015-10-22 14:00:28 -0400867 unsigned int vertexShaderSize = stream->readInt<unsigned int>();
Brandon Joneseb994362014-09-24 10:27:28 -0700868 const unsigned char *vertexShaderFunction = binary + stream->offset();
Geoff Langb543aff2014-09-30 14:52:54 -0400869
Jamie Madillada9ecc2015-08-17 12:53:37 -0400870 ShaderExecutableD3D *shaderExecutable = nullptr;
871
Jamie Madillb0a838b2016-11-13 20:02:12 -0500872 ANGLE_TRY(mRenderer->loadExecutable(vertexShaderFunction, vertexShaderSize, SHADER_VERTEX,
873 mStreamOutVaryings, separateAttribs,
874 &shaderExecutable));
Geoff Langb543aff2014-09-30 14:52:54 -0400875
Brandon Joneseb994362014-09-24 10:27:28 -0700876 if (!shaderExecutable)
877 {
Jamie Madillf6113162015-05-07 11:49:21 -0400878 infoLog << "Could not create vertex shader.";
Jamie Madillb0a838b2016-11-13 20:02:12 -0500879 return false;
Brandon Joneseb994362014-09-24 10:27:28 -0700880 }
881
882 // generated converted input layout
Jamie Madilld3dfda22015-07-06 08:28:49 -0400883 VertexExecutable::Signature signature;
884 VertexExecutable::getSignature(mRenderer, inputLayout, &signature);
Brandon Joneseb994362014-09-24 10:27:28 -0700885
886 // add new binary
Xinghua Caob1239382016-12-13 15:07:05 +0800887 mVertexExecutables.push_back(std::unique_ptr<VertexExecutable>(
888 new VertexExecutable(inputLayout, signature, shaderExecutable)));
Brandon Joneseb994362014-09-24 10:27:28 -0700889
890 stream->skip(vertexShaderSize);
891 }
892
893 const size_t pixelShaderCount = stream->readInt<unsigned int>();
894 for (size_t pixelShaderIndex = 0; pixelShaderIndex < pixelShaderCount; pixelShaderIndex++)
895 {
896 const size_t outputCount = stream->readInt<unsigned int>();
897 std::vector<GLenum> outputs(outputCount);
898 for (size_t outputIndex = 0; outputIndex < outputCount; outputIndex++)
899 {
900 stream->readInt(&outputs[outputIndex]);
901 }
902
Jamie Madill334d6152015-10-22 14:00:28 -0400903 const size_t pixelShaderSize = stream->readInt<unsigned int>();
Brandon Joneseb994362014-09-24 10:27:28 -0700904 const unsigned char *pixelShaderFunction = binary + stream->offset();
Jamie Madillada9ecc2015-08-17 12:53:37 -0400905 ShaderExecutableD3D *shaderExecutable = nullptr;
906
Jamie Madillb0a838b2016-11-13 20:02:12 -0500907 ANGLE_TRY(mRenderer->loadExecutable(pixelShaderFunction, pixelShaderSize, SHADER_PIXEL,
908 mStreamOutVaryings, separateAttribs,
909 &shaderExecutable));
Brandon Joneseb994362014-09-24 10:27:28 -0700910
911 if (!shaderExecutable)
912 {
Jamie Madillf6113162015-05-07 11:49:21 -0400913 infoLog << "Could not create pixel shader.";
Jamie Madillb0a838b2016-11-13 20:02:12 -0500914 return false;
Brandon Joneseb994362014-09-24 10:27:28 -0700915 }
916
917 // add new binary
Xinghua Caob1239382016-12-13 15:07:05 +0800918 mPixelExecutables.push_back(
919 std::unique_ptr<PixelExecutable>(new PixelExecutable(outputs, shaderExecutable)));
Brandon Joneseb994362014-09-24 10:27:28 -0700920
921 stream->skip(pixelShaderSize);
922 }
923
Jamie Madill4e31ad52015-10-29 10:32:57 -0400924 for (unsigned int geometryExeIndex = 0; geometryExeIndex < gl::PRIMITIVE_TYPE_MAX;
925 ++geometryExeIndex)
Brandon Joneseb994362014-09-24 10:27:28 -0700926 {
Jamie Madill4e31ad52015-10-29 10:32:57 -0400927 unsigned int geometryShaderSize = stream->readInt<unsigned int>();
928 if (geometryShaderSize == 0)
929 {
Jamie Madill4e31ad52015-10-29 10:32:57 -0400930 continue;
931 }
932
Brandon Joneseb994362014-09-24 10:27:28 -0700933 const unsigned char *geometryShaderFunction = binary + stream->offset();
Jamie Madill4e31ad52015-10-29 10:32:57 -0400934
Xinghua Caob1239382016-12-13 15:07:05 +0800935 ShaderExecutableD3D *geometryExecutable = nullptr;
Jamie Madillb0a838b2016-11-13 20:02:12 -0500936 ANGLE_TRY(mRenderer->loadExecutable(geometryShaderFunction, geometryShaderSize,
937 SHADER_GEOMETRY, mStreamOutVaryings, separateAttribs,
Xinghua Caob1239382016-12-13 15:07:05 +0800938 &geometryExecutable));
Brandon Joneseb994362014-09-24 10:27:28 -0700939
Xinghua Caob1239382016-12-13 15:07:05 +0800940 if (!geometryExecutable)
Brandon Joneseb994362014-09-24 10:27:28 -0700941 {
Jamie Madillf6113162015-05-07 11:49:21 -0400942 infoLog << "Could not create geometry shader.";
Jamie Madillb0a838b2016-11-13 20:02:12 -0500943 return false;
Brandon Joneseb994362014-09-24 10:27:28 -0700944 }
Xinghua Caob1239382016-12-13 15:07:05 +0800945
946 mGeometryExecutables[geometryExeIndex].reset(geometryExecutable);
947
Brandon Joneseb994362014-09-24 10:27:28 -0700948 stream->skip(geometryShaderSize);
949 }
950
Xinghua Caob1239382016-12-13 15:07:05 +0800951 unsigned int computeShaderSize = stream->readInt<unsigned int>();
952 if (computeShaderSize > 0)
953 {
954 const unsigned char *computeShaderFunction = binary + stream->offset();
955
956 ShaderExecutableD3D *computeExecutable = nullptr;
957 ANGLE_TRY(mRenderer->loadExecutable(computeShaderFunction, computeShaderSize,
958 SHADER_COMPUTE, std::vector<D3DVarying>(), false,
959 &computeExecutable));
960
961 if (!computeExecutable)
962 {
963 infoLog << "Could not create compute shader.";
964 return false;
965 }
966
967 mComputeExecutable.reset(computeExecutable);
968 }
969
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700970 initializeUniformStorage();
971
Jamie Madillb0a838b2016-11-13 20:02:12 -0500972 return true;
Brandon Jones22502d52014-08-29 16:58:36 -0700973}
974
Jamie Madill27a60632017-06-30 15:12:01 -0400975void ProgramD3D::save(const gl::Context *context, gl::BinaryOutputStream *stream)
Brandon Jones22502d52014-08-29 16:58:36 -0700976{
Austin Kinross137b1512015-06-17 16:14:53 -0700977 // Output the DeviceIdentifier before we output any shader code
Jamie Madill334d6152015-10-22 14:00:28 -0400978 // When we load the binary again later, we can validate the device identifier before trying to
979 // compile any HLSL
Austin Kinross137b1512015-06-17 16:14:53 -0700980 DeviceIdentifier binaryIdentifier = mRenderer->getAdapterIdentifier();
Jamie Madill334d6152015-10-22 14:00:28 -0400981 stream->writeBytes(reinterpret_cast<unsigned char *>(&binaryIdentifier),
982 sizeof(DeviceIdentifier));
Austin Kinross137b1512015-06-17 16:14:53 -0700983
Jamie Madill2db1fbb2014-12-03 10:58:55 -0500984 stream->writeInt(ANGLE_COMPILE_OPTIMIZATION_LEVEL);
985
Jamie Madill8047c0d2016-03-07 13:02:12 -0500986 for (int d3dSemantic : mAttribLocationToD3DSemantic)
Jamie Madill63805b42015-08-25 13:17:39 -0400987 {
Jamie Madill8047c0d2016-03-07 13:02:12 -0500988 stream->writeInt(d3dSemantic);
Jamie Madill63805b42015-08-25 13:17:39 -0400989 }
990
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700991 stream->writeInt(mSamplersPS.size());
992 for (unsigned int i = 0; i < mSamplersPS.size(); ++i)
993 {
994 stream->writeInt(mSamplersPS[i].active);
995 stream->writeInt(mSamplersPS[i].logicalTextureUnit);
996 stream->writeInt(mSamplersPS[i].textureType);
997 }
998
999 stream->writeInt(mSamplersVS.size());
1000 for (unsigned int i = 0; i < mSamplersVS.size(); ++i)
1001 {
1002 stream->writeInt(mSamplersVS[i].active);
1003 stream->writeInt(mSamplersVS[i].logicalTextureUnit);
1004 stream->writeInt(mSamplersVS[i].textureType);
1005 }
1006
Xinghua Caob1239382016-12-13 15:07:05 +08001007 stream->writeInt(mSamplersCS.size());
1008 for (unsigned int i = 0; i < mSamplersCS.size(); ++i)
1009 {
1010 stream->writeInt(mSamplersCS[i].active);
1011 stream->writeInt(mSamplersCS[i].logicalTextureUnit);
1012 stream->writeInt(mSamplersCS[i].textureType);
1013 }
1014
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001015 stream->writeInt(mUsedVertexSamplerRange);
1016 stream->writeInt(mUsedPixelSamplerRange);
Xinghua Caob1239382016-12-13 15:07:05 +08001017 stream->writeInt(mUsedComputeSamplerRange);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001018
Jamie Madill62d31cb2015-09-11 13:25:51 -04001019 stream->writeInt(mD3DUniforms.size());
Jamie Madill4a3c2342015-10-08 12:58:45 -04001020 for (const D3DUniform *uniform : mD3DUniforms)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001021 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001022 // Type, name and arraySize are redundant, so aren't stored in the binary.
Jamie Madille2e406c2016-06-02 13:04:10 -04001023 stream->writeIntOrNegOne(uniform->psRegisterIndex);
1024 stream->writeIntOrNegOne(uniform->vsRegisterIndex);
Xinghua Caob1239382016-12-13 15:07:05 +08001025 stream->writeIntOrNegOne(uniform->csRegisterIndex);
Jamie Madill4a3c2342015-10-08 12:58:45 -04001026 stream->writeInt(uniform->registerCount);
1027 stream->writeInt(uniform->registerElement);
1028 }
1029
Jamie Madill51f522f2016-12-21 15:10:55 -05001030 // Ensure we init the uniform block structure data if we should.
1031 // http://anglebug.com/1637
1032 ensureUniformBlocksInitialized();
1033
Jamie Madill4a3c2342015-10-08 12:58:45 -04001034 stream->writeInt(mD3DUniformBlocks.size());
1035 for (const D3DUniformBlock &uniformBlock : mD3DUniformBlocks)
1036 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001037 stream->writeIntOrNegOne(uniformBlock.psRegisterIndex);
1038 stream->writeIntOrNegOne(uniformBlock.vsRegisterIndex);
Xinghua Caob1239382016-12-13 15:07:05 +08001039 stream->writeIntOrNegOne(uniformBlock.csRegisterIndex);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001040 }
1041
Jamie Madill9fc36822015-11-18 13:08:07 -05001042 stream->writeInt(mStreamOutVaryings.size());
1043 for (const auto &varying : mStreamOutVaryings)
Brandon Joneseb994362014-09-24 10:27:28 -07001044 {
Brandon Joneseb994362014-09-24 10:27:28 -07001045 stream->writeString(varying.semanticName);
1046 stream->writeInt(varying.semanticIndex);
Jamie Madill9fc36822015-11-18 13:08:07 -05001047 stream->writeInt(varying.componentCount);
1048 stream->writeInt(varying.outputSlot);
Brandon Joneseb994362014-09-24 10:27:28 -07001049 }
1050
Brandon Jones22502d52014-08-29 16:58:36 -07001051 stream->writeString(mVertexHLSL);
Jamie Madill334d6152015-10-22 14:00:28 -04001052 stream->writeBytes(reinterpret_cast<unsigned char *>(&mVertexWorkarounds),
Jamie Madill408293f2016-12-20 10:11:45 -05001053 sizeof(angle::CompilerWorkaroundsD3D));
Brandon Jones22502d52014-08-29 16:58:36 -07001054 stream->writeString(mPixelHLSL);
Jamie Madill334d6152015-10-22 14:00:28 -04001055 stream->writeBytes(reinterpret_cast<unsigned char *>(&mPixelWorkarounds),
Jamie Madill408293f2016-12-20 10:11:45 -05001056 sizeof(angle::CompilerWorkaroundsD3D));
Brandon Jones22502d52014-08-29 16:58:36 -07001057 stream->writeInt(mUsesFragDepth);
Martin Radev41ac68e2017-06-06 12:16:58 +03001058 stream->writeInt(mHasANGLEMultiviewEnabled);
1059 stream->writeInt(mUsesViewID);
Brandon Jones44151a92014-09-10 11:32:25 -07001060 stream->writeInt(mUsesPointSize);
Jamie Madill3e14e2b2015-10-29 14:38:53 -04001061 stream->writeInt(mUsesFlatInterpolation);
Brandon Jones22502d52014-08-29 16:58:36 -07001062
Brandon Joneseb994362014-09-24 10:27:28 -07001063 const std::vector<PixelShaderOutputVariable> &pixelShaderKey = mPixelShaderKey;
Brandon Jones22502d52014-08-29 16:58:36 -07001064 stream->writeInt(pixelShaderKey.size());
Jamie Madill334d6152015-10-22 14:00:28 -04001065 for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKey.size();
1066 pixelShaderKeyIndex++)
Brandon Jones22502d52014-08-29 16:58:36 -07001067 {
Brandon Joneseb994362014-09-24 10:27:28 -07001068 const PixelShaderOutputVariable &variable = pixelShaderKey[pixelShaderKeyIndex];
Brandon Jones22502d52014-08-29 16:58:36 -07001069 stream->writeInt(variable.type);
1070 stream->writeString(variable.name);
1071 stream->writeString(variable.source);
1072 stream->writeInt(variable.outputIndex);
1073 }
1074
Jamie Madill4e31ad52015-10-29 10:32:57 -04001075 stream->writeString(mGeometryShaderPreamble);
1076
Brandon Joneseb994362014-09-24 10:27:28 -07001077 stream->writeInt(mVertexExecutables.size());
Jamie Madill334d6152015-10-22 14:00:28 -04001078 for (size_t vertexExecutableIndex = 0; vertexExecutableIndex < mVertexExecutables.size();
1079 vertexExecutableIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -07001080 {
Xinghua Caob1239382016-12-13 15:07:05 +08001081 VertexExecutable *vertexExecutable = mVertexExecutables[vertexExecutableIndex].get();
Brandon Joneseb994362014-09-24 10:27:28 -07001082
Jamie Madilld3dfda22015-07-06 08:28:49 -04001083 const auto &inputLayout = vertexExecutable->inputs();
1084 stream->writeInt(inputLayout.size());
1085
1086 for (size_t inputIndex = 0; inputIndex < inputLayout.size(); inputIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -07001087 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001088 stream->writeInt(static_cast<unsigned int>(inputLayout[inputIndex]));
Brandon Joneseb994362014-09-24 10:27:28 -07001089 }
1090
1091 size_t vertexShaderSize = vertexExecutable->shaderExecutable()->getLength();
1092 stream->writeInt(vertexShaderSize);
1093
1094 const uint8_t *vertexBlob = vertexExecutable->shaderExecutable()->getFunction();
1095 stream->writeBytes(vertexBlob, vertexShaderSize);
1096 }
1097
1098 stream->writeInt(mPixelExecutables.size());
Jamie Madill334d6152015-10-22 14:00:28 -04001099 for (size_t pixelExecutableIndex = 0; pixelExecutableIndex < mPixelExecutables.size();
1100 pixelExecutableIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -07001101 {
Xinghua Caob1239382016-12-13 15:07:05 +08001102 PixelExecutable *pixelExecutable = mPixelExecutables[pixelExecutableIndex].get();
Brandon Joneseb994362014-09-24 10:27:28 -07001103
1104 const std::vector<GLenum> outputs = pixelExecutable->outputSignature();
1105 stream->writeInt(outputs.size());
1106 for (size_t outputIndex = 0; outputIndex < outputs.size(); outputIndex++)
1107 {
1108 stream->writeInt(outputs[outputIndex]);
1109 }
1110
1111 size_t pixelShaderSize = pixelExecutable->shaderExecutable()->getLength();
1112 stream->writeInt(pixelShaderSize);
1113
1114 const uint8_t *pixelBlob = pixelExecutable->shaderExecutable()->getFunction();
1115 stream->writeBytes(pixelBlob, pixelShaderSize);
1116 }
1117
Xinghua Caob1239382016-12-13 15:07:05 +08001118 for (auto const &geometryExecutable : mGeometryExecutables)
Brandon Joneseb994362014-09-24 10:27:28 -07001119 {
Xinghua Caob1239382016-12-13 15:07:05 +08001120 if (!geometryExecutable)
Jamie Madill4e31ad52015-10-29 10:32:57 -04001121 {
1122 stream->writeInt(0);
1123 continue;
1124 }
1125
Xinghua Caob1239382016-12-13 15:07:05 +08001126 size_t geometryShaderSize = geometryExecutable->getLength();
Jamie Madill4e31ad52015-10-29 10:32:57 -04001127 stream->writeInt(geometryShaderSize);
Xinghua Caob1239382016-12-13 15:07:05 +08001128 stream->writeBytes(geometryExecutable->getFunction(), geometryShaderSize);
1129 }
1130
1131 if (mComputeExecutable)
1132 {
1133 size_t computeShaderSize = mComputeExecutable->getLength();
1134 stream->writeInt(computeShaderSize);
1135 stream->writeBytes(mComputeExecutable->getFunction(), computeShaderSize);
1136 }
1137 else
1138 {
1139 stream->writeInt(0);
Brandon Joneseb994362014-09-24 10:27:28 -07001140 }
Brandon Jones22502d52014-08-29 16:58:36 -07001141}
1142
Geoff Langc5629752015-12-07 16:29:04 -05001143void ProgramD3D::setBinaryRetrievableHint(bool /* retrievable */)
1144{
1145}
1146
Yunchao He61afff12017-03-14 15:34:03 +08001147void ProgramD3D::setSeparable(bool /* separable */)
1148{
1149}
1150
Jamie Madill4c19a8a2017-07-24 11:46:06 -04001151gl::Error ProgramD3D::getPixelExecutableForCachedOutputLayout(ShaderExecutableD3D **outExecutable,
1152 gl::InfoLog *infoLog)
Brandon Joneseb994362014-09-24 10:27:28 -07001153{
Jamie Madill0e7f1732017-09-09 23:32:50 -04001154 if (mCachedPixelExecutableIndex.valid())
Brandon Joneseb994362014-09-24 10:27:28 -07001155 {
Jamie Madill0e7f1732017-09-09 23:32:50 -04001156 *outExecutable = mPixelExecutables[mCachedPixelExecutableIndex.value()]->shaderExecutable();
1157 return gl::NoError();
Brandon Joneseb994362014-09-24 10:27:28 -07001158 }
1159
Jamie Madill334d6152015-10-22 14:00:28 -04001160 std::string finalPixelHLSL = mDynamicHLSL->generatePixelShaderForOutputSignature(
Jamie Madill4c19a8a2017-07-24 11:46:06 -04001161 mPixelHLSL, mPixelShaderKey, mUsesFragDepth, mPixelShaderOutputLayoutCache);
Brandon Jones22502d52014-08-29 16:58:36 -07001162
1163 // Generate new pixel executable
Yunchao Hed7297bf2017-04-19 15:27:10 +08001164 ShaderExecutableD3D *pixelExecutable = nullptr;
Jamie Madill97399232014-12-23 12:31:15 -05001165
1166 gl::InfoLog tempInfoLog;
1167 gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
1168
Jamie Madill01074252016-11-28 15:55:51 -05001169 ANGLE_TRY(mRenderer->compileToExecutable(
Jamie Madill9fc36822015-11-18 13:08:07 -05001170 *currentInfoLog, finalPixelHLSL, SHADER_PIXEL, mStreamOutVaryings,
Jamie Madill48ef11b2016-04-27 15:21:52 -04001171 (mState.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), mPixelWorkarounds,
Jamie Madill01074252016-11-28 15:55:51 -05001172 &pixelExecutable));
Brandon Joneseb994362014-09-24 10:27:28 -07001173
Jamie Madill97399232014-12-23 12:31:15 -05001174 if (pixelExecutable)
1175 {
Xinghua Caob1239382016-12-13 15:07:05 +08001176 mPixelExecutables.push_back(std::unique_ptr<PixelExecutable>(
Jamie Madill4c19a8a2017-07-24 11:46:06 -04001177 new PixelExecutable(mPixelShaderOutputLayoutCache, pixelExecutable)));
Jamie Madill0e7f1732017-09-09 23:32:50 -04001178 mCachedPixelExecutableIndex = mPixelExecutables.size() - 1;
Jamie Madill97399232014-12-23 12:31:15 -05001179 }
1180 else if (!infoLog)
Brandon Joneseb994362014-09-24 10:27:28 -07001181 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05001182 ERR() << "Error compiling dynamic pixel executable:" << std::endl
1183 << tempInfoLog.str() << std::endl;
Brandon Joneseb994362014-09-24 10:27:28 -07001184 }
Brandon Jones22502d52014-08-29 16:58:36 -07001185
Jamie Madill4c19a8a2017-07-24 11:46:06 -04001186 *outExecutable = pixelExecutable;
Jamie Madill01074252016-11-28 15:55:51 -05001187 return gl::NoError();
Brandon Jones22502d52014-08-29 16:58:36 -07001188}
1189
Jamie Madill4c19a8a2017-07-24 11:46:06 -04001190gl::Error ProgramD3D::getVertexExecutableForCachedInputLayout(ShaderExecutableD3D **outExectuable,
1191 gl::InfoLog *infoLog)
Brandon Jones22502d52014-08-29 16:58:36 -07001192{
Jamie Madill0e7f1732017-09-09 23:32:50 -04001193 if (mCachedVertexExecutableIndex.valid())
Brandon Joneseb994362014-09-24 10:27:28 -07001194 {
Jamie Madill0e7f1732017-09-09 23:32:50 -04001195 *outExectuable =
1196 mVertexExecutables[mCachedVertexExecutableIndex.value()]->shaderExecutable();
1197 return gl::NoError();
Brandon Joneseb994362014-09-24 10:27:28 -07001198 }
1199
Brandon Jones22502d52014-08-29 16:58:36 -07001200 // Generate new dynamic layout with attribute conversions
Jamie Madillc349ec02015-08-21 16:53:12 -04001201 std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout(
Jamie Madill4c19a8a2017-07-24 11:46:06 -04001202 mVertexHLSL, mCachedInputLayout, mState.getAttributes());
Brandon Jones22502d52014-08-29 16:58:36 -07001203
1204 // Generate new vertex executable
Yunchao Hed7297bf2017-04-19 15:27:10 +08001205 ShaderExecutableD3D *vertexExecutable = nullptr;
Jamie Madill97399232014-12-23 12:31:15 -05001206
1207 gl::InfoLog tempInfoLog;
1208 gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
1209
Jamie Madill01074252016-11-28 15:55:51 -05001210 ANGLE_TRY(mRenderer->compileToExecutable(
Jamie Madill9fc36822015-11-18 13:08:07 -05001211 *currentInfoLog, finalVertexHLSL, SHADER_VERTEX, mStreamOutVaryings,
Jamie Madill48ef11b2016-04-27 15:21:52 -04001212 (mState.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), mVertexWorkarounds,
Jamie Madill01074252016-11-28 15:55:51 -05001213 &vertexExecutable));
Geoff Langb543aff2014-09-30 14:52:54 -04001214
Jamie Madill97399232014-12-23 12:31:15 -05001215 if (vertexExecutable)
Brandon Joneseb994362014-09-24 10:27:28 -07001216 {
Xinghua Caob1239382016-12-13 15:07:05 +08001217 mVertexExecutables.push_back(std::unique_ptr<VertexExecutable>(
Jamie Madill4c19a8a2017-07-24 11:46:06 -04001218 new VertexExecutable(mCachedInputLayout, mCachedVertexSignature, vertexExecutable)));
Jamie Madill0e7f1732017-09-09 23:32:50 -04001219 mCachedVertexExecutableIndex = mVertexExecutables.size() - 1;
Brandon Joneseb994362014-09-24 10:27:28 -07001220 }
Jamie Madill97399232014-12-23 12:31:15 -05001221 else if (!infoLog)
1222 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05001223 ERR() << "Error compiling dynamic vertex executable:" << std::endl
1224 << tempInfoLog.str() << std::endl;
Jamie Madill97399232014-12-23 12:31:15 -05001225 }
Brandon Jones22502d52014-08-29 16:58:36 -07001226
Geoff Langb543aff2014-09-30 14:52:54 -04001227 *outExectuable = vertexExecutable;
Jamie Madill01074252016-11-28 15:55:51 -05001228 return gl::NoError();
Brandon Jones22502d52014-08-29 16:58:36 -07001229}
1230
Jamie Madillc9fed8d2017-09-12 15:23:00 -04001231gl::Error ProgramD3D::getGeometryExecutableForPrimitiveType(const gl::Context *context,
Jamie Madill4e31ad52015-10-29 10:32:57 -04001232 GLenum drawMode,
1233 ShaderExecutableD3D **outExecutable,
1234 gl::InfoLog *infoLog)
1235{
Jamie Madill3e14e2b2015-10-29 14:38:53 -04001236 if (outExecutable)
1237 {
1238 *outExecutable = nullptr;
1239 }
1240
Austin Kinross88829e82016-01-12 13:04:41 -08001241 // Return a null shader if the current rendering doesn't use a geometry shader
1242 if (!usesGeometryShader(drawMode))
Jamie Madill3e14e2b2015-10-29 14:38:53 -04001243 {
Jamie Madill51f522f2016-12-21 15:10:55 -05001244 return gl::NoError();
Jamie Madill3e14e2b2015-10-29 14:38:53 -04001245 }
1246
Jamie Madill4e31ad52015-10-29 10:32:57 -04001247 gl::PrimitiveType geometryShaderType = GetGeometryShaderTypeFromDrawMode(drawMode);
1248
Xinghua Caob1239382016-12-13 15:07:05 +08001249 if (mGeometryExecutables[geometryShaderType])
Jamie Madill4e31ad52015-10-29 10:32:57 -04001250 {
1251 if (outExecutable)
1252 {
Xinghua Caob1239382016-12-13 15:07:05 +08001253 *outExecutable = mGeometryExecutables[geometryShaderType].get();
Jamie Madill4e31ad52015-10-29 10:32:57 -04001254 }
Jamie Madill51f522f2016-12-21 15:10:55 -05001255 return gl::NoError();
Jamie Madill4e31ad52015-10-29 10:32:57 -04001256 }
1257
1258 std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL(
Jamie Madillc9fed8d2017-09-12 15:23:00 -04001259 context, geometryShaderType, mState, mRenderer->presentPathFastEnabled(),
Martin Radevc1d4e552017-08-21 12:01:10 +03001260 mHasANGLEMultiviewEnabled, mRenderer->canSelectViewInVertexShader(),
1261 usesGeometryShaderForPointSpriteEmulation(), mGeometryShaderPreamble);
Jamie Madill4e31ad52015-10-29 10:32:57 -04001262
1263 gl::InfoLog tempInfoLog;
1264 gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
1265
Xinghua Caob1239382016-12-13 15:07:05 +08001266 ShaderExecutableD3D *geometryExecutable = nullptr;
1267 gl::Error error = mRenderer->compileToExecutable(
Jamie Madill9fc36822015-11-18 13:08:07 -05001268 *currentInfoLog, geometryHLSL, SHADER_GEOMETRY, mStreamOutVaryings,
Jamie Madill408293f2016-12-20 10:11:45 -05001269 (mState.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS),
Xinghua Caob1239382016-12-13 15:07:05 +08001270 angle::CompilerWorkaroundsD3D(), &geometryExecutable);
Jamie Madill4e31ad52015-10-29 10:32:57 -04001271
1272 if (!infoLog && error.isError())
1273 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05001274 ERR() << "Error compiling dynamic geometry executable:" << std::endl
1275 << tempInfoLog.str() << std::endl;
Jamie Madill4e31ad52015-10-29 10:32:57 -04001276 }
1277
Xinghua Caob1239382016-12-13 15:07:05 +08001278 if (geometryExecutable != nullptr)
1279 {
1280 mGeometryExecutables[geometryShaderType].reset(geometryExecutable);
1281 }
1282
Jamie Madill4e31ad52015-10-29 10:32:57 -04001283 if (outExecutable)
1284 {
Xinghua Caob1239382016-12-13 15:07:05 +08001285 *outExecutable = mGeometryExecutables[geometryShaderType].get();
Jamie Madill4e31ad52015-10-29 10:32:57 -04001286 }
1287 return error;
1288}
1289
Jamie Madill01074252016-11-28 15:55:51 -05001290class ProgramD3D::GetExecutableTask : public Closure
Brandon Jones44151a92014-09-10 11:32:25 -07001291{
Jamie Madill01074252016-11-28 15:55:51 -05001292 public:
1293 GetExecutableTask(ProgramD3D *program)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001294 : mProgram(program), mError(gl::NoError()), mInfoLog(), mResult(nullptr)
Brandon Joneseb994362014-09-24 10:27:28 -07001295 {
Brandon Joneseb994362014-09-24 10:27:28 -07001296 }
1297
Jamie Madill01074252016-11-28 15:55:51 -05001298 virtual gl::Error run() = 0;
1299
1300 void operator()() override { mError = run(); }
1301
1302 const gl::Error &getError() const { return mError; }
1303 const gl::InfoLog &getInfoLog() const { return mInfoLog; }
1304 ShaderExecutableD3D *getResult() { return mResult; }
1305
1306 protected:
1307 ProgramD3D *mProgram;
1308 gl::Error mError;
1309 gl::InfoLog mInfoLog;
1310 ShaderExecutableD3D *mResult;
1311};
1312
1313class ProgramD3D::GetVertexExecutableTask : public ProgramD3D::GetExecutableTask
1314{
1315 public:
Jamie Madillbd044ed2017-06-05 12:59:21 -04001316 GetVertexExecutableTask(ProgramD3D *program, const gl::Context *context)
1317 : GetExecutableTask(program), mContext(context)
1318 {
1319 }
Jamie Madill01074252016-11-28 15:55:51 -05001320 gl::Error run() override
1321 {
Jamie Madill4c19a8a2017-07-24 11:46:06 -04001322 mProgram->updateCachedInputLayoutFromShader(mContext);
Jamie Madill01074252016-11-28 15:55:51 -05001323
Jamie Madill4c19a8a2017-07-24 11:46:06 -04001324 ANGLE_TRY(mProgram->getVertexExecutableForCachedInputLayout(&mResult, &mInfoLog));
Jamie Madill01074252016-11-28 15:55:51 -05001325
1326 return gl::NoError();
1327 }
Jamie Madillbd044ed2017-06-05 12:59:21 -04001328
1329 private:
1330 const gl::Context *mContext;
Jamie Madill01074252016-11-28 15:55:51 -05001331};
1332
Jamie Madill4c19a8a2017-07-24 11:46:06 -04001333void ProgramD3D::updateCachedInputLayoutFromShader(const gl::Context *context)
1334{
1335 GetDefaultInputLayoutFromShader(context, mState.getAttachedVertexShader(), &mCachedInputLayout);
1336 VertexExecutable::getSignature(mRenderer, mCachedInputLayout, &mCachedVertexSignature);
Jamie Madill0e7f1732017-09-09 23:32:50 -04001337 updateCachedVertexExecutableIndex();
Jamie Madill4c19a8a2017-07-24 11:46:06 -04001338}
1339
Jamie Madill01074252016-11-28 15:55:51 -05001340class ProgramD3D::GetPixelExecutableTask : public ProgramD3D::GetExecutableTask
1341{
1342 public:
1343 GetPixelExecutableTask(ProgramD3D *program) : GetExecutableTask(program) {}
1344 gl::Error run() override
1345 {
Jamie Madill4c19a8a2017-07-24 11:46:06 -04001346 mProgram->updateCachedOutputLayoutFromShader();
Jamie Madill01074252016-11-28 15:55:51 -05001347
Jamie Madill4c19a8a2017-07-24 11:46:06 -04001348 ANGLE_TRY(mProgram->getPixelExecutableForCachedOutputLayout(&mResult, &mInfoLog));
Jamie Madill01074252016-11-28 15:55:51 -05001349
1350 return gl::NoError();
1351 }
1352};
1353
Jamie Madill4c19a8a2017-07-24 11:46:06 -04001354void ProgramD3D::updateCachedOutputLayoutFromShader()
1355{
1356 GetDefaultOutputLayoutFromShader(mPixelShaderKey, &mPixelShaderOutputLayoutCache);
Jamie Madill0e7f1732017-09-09 23:32:50 -04001357 updateCachedPixelExecutableIndex();
Jamie Madill4c19a8a2017-07-24 11:46:06 -04001358}
1359
Jamie Madill01074252016-11-28 15:55:51 -05001360class ProgramD3D::GetGeometryExecutableTask : public ProgramD3D::GetExecutableTask
1361{
1362 public:
Jamie Madillc9fed8d2017-09-12 15:23:00 -04001363 GetGeometryExecutableTask(ProgramD3D *program, const gl::Context *context)
1364 : GetExecutableTask(program), mContext(context)
Jamie Madill01074252016-11-28 15:55:51 -05001365 {
1366 }
1367
1368 gl::Error run() override
1369 {
1370 // Auto-generate the geometry shader here, if we expect to be using point rendering in
1371 // D3D11.
1372 if (mProgram->usesGeometryShader(GL_POINTS))
1373 {
Jamie Madillc9fed8d2017-09-12 15:23:00 -04001374 ANGLE_TRY(mProgram->getGeometryExecutableForPrimitiveType(mContext, GL_POINTS, &mResult,
1375 &mInfoLog));
Jamie Madill01074252016-11-28 15:55:51 -05001376 }
1377
1378 return gl::NoError();
1379 }
1380
1381 private:
Jamie Madillc9fed8d2017-09-12 15:23:00 -04001382 const gl::Context *mContext;
Jamie Madill01074252016-11-28 15:55:51 -05001383};
1384
Xinghua Cao73badc02017-03-29 19:14:53 +08001385gl::Error ProgramD3D::getComputeExecutable(ShaderExecutableD3D **outExecutable)
1386{
1387 if (outExecutable)
1388 {
1389 *outExecutable = mComputeExecutable.get();
1390 }
1391
1392 return gl::NoError();
1393}
1394
Jamie Madill9cf9e872017-06-05 12:59:25 -04001395gl::LinkResult ProgramD3D::compileProgramExecutables(const gl::Context *context,
1396 gl::InfoLog &infoLog)
Jamie Madill01074252016-11-28 15:55:51 -05001397{
1398 // Ensure the compiler is initialized to avoid race conditions.
1399 ANGLE_TRY(mRenderer->ensureHLSLCompilerInitialized());
1400
1401 WorkerThreadPool *workerPool = mRenderer->getWorkerThreadPool();
1402
Jamie Madillbd044ed2017-06-05 12:59:21 -04001403 GetVertexExecutableTask vertexTask(this, context);
Jamie Madill01074252016-11-28 15:55:51 -05001404 GetPixelExecutableTask pixelTask(this);
Jamie Madillc9fed8d2017-09-12 15:23:00 -04001405 GetGeometryExecutableTask geometryTask(this, context);
Jamie Madill01074252016-11-28 15:55:51 -05001406
1407 std::array<WaitableEvent, 3> waitEvents = {{workerPool->postWorkerTask(&vertexTask),
1408 workerPool->postWorkerTask(&pixelTask),
1409 workerPool->postWorkerTask(&geometryTask)}};
1410
1411 WaitableEvent::WaitMany(&waitEvents);
1412
1413 infoLog << vertexTask.getInfoLog().str();
1414 infoLog << pixelTask.getInfoLog().str();
1415 infoLog << geometryTask.getInfoLog().str();
1416
1417 ANGLE_TRY(vertexTask.getError());
1418 ANGLE_TRY(pixelTask.getError());
1419 ANGLE_TRY(geometryTask.getError());
1420
1421 ShaderExecutableD3D *defaultVertexExecutable = vertexTask.getResult();
1422 ShaderExecutableD3D *defaultPixelExecutable = pixelTask.getResult();
1423 ShaderExecutableD3D *pointGS = geometryTask.getResult();
1424
Jamie Madill48ef11b2016-04-27 15:21:52 -04001425 const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(mState.getAttachedVertexShader());
Jamie Madill847638a2015-11-20 13:01:41 -05001426
1427 if (usesGeometryShader(GL_POINTS) && pointGS)
Tibor den Ouden97049c62014-10-06 21:39:16 +02001428 {
Jamie Madill334d6152015-10-22 14:00:28 -04001429 // Geometry shaders are currently only used internally, so there is no corresponding shader
1430 // object at the interface level. For now the geometry shader debug info is prepended to
1431 // the vertex shader.
Tibor den Ouden97049c62014-10-06 21:39:16 +02001432 vertexShaderD3D->appendDebugInfo("// GEOMETRY SHADER BEGIN\n\n");
Jamie Madill847638a2015-11-20 13:01:41 -05001433 vertexShaderD3D->appendDebugInfo(pointGS->getDebugInfo());
Tibor den Ouden97049c62014-10-06 21:39:16 +02001434 vertexShaderD3D->appendDebugInfo("\nGEOMETRY SHADER END\n\n\n");
1435 }
1436
1437 if (defaultVertexExecutable)
1438 {
1439 vertexShaderD3D->appendDebugInfo(defaultVertexExecutable->getDebugInfo());
1440 }
1441
1442 if (defaultPixelExecutable)
1443 {
Jamie Madill76f8fa62015-10-29 10:32:56 -04001444 const ShaderD3D *fragmentShaderD3D =
Jamie Madill48ef11b2016-04-27 15:21:52 -04001445 GetImplAs<ShaderD3D>(mState.getAttachedFragmentShader());
Tibor den Ouden97049c62014-10-06 21:39:16 +02001446 fragmentShaderD3D->appendDebugInfo(defaultPixelExecutable->getDebugInfo());
1447 }
Tibor den Ouden97049c62014-10-06 21:39:16 +02001448
Jamie Madillb0a838b2016-11-13 20:02:12 -05001449 return (defaultVertexExecutable && defaultPixelExecutable &&
1450 (!usesGeometryShader(GL_POINTS) || pointGS));
Brandon Jones18bd4102014-09-22 14:21:44 -07001451}
1452
Jamie Madill9cf9e872017-06-05 12:59:25 -04001453gl::LinkResult ProgramD3D::compileComputeExecutable(const gl::Context *context,
1454 gl::InfoLog &infoLog)
Xinghua Caob1239382016-12-13 15:07:05 +08001455{
1456 // Ensure the compiler is initialized to avoid race conditions.
1457 ANGLE_TRY(mRenderer->ensureHLSLCompilerInitialized());
1458
Jamie Madillbd044ed2017-06-05 12:59:21 -04001459 std::string computeShader = mDynamicHLSL->generateComputeShaderLinkHLSL(context, mState);
Xinghua Caob1239382016-12-13 15:07:05 +08001460
1461 ShaderExecutableD3D *computeExecutable = nullptr;
1462 ANGLE_TRY(mRenderer->compileToExecutable(infoLog, computeShader, SHADER_COMPUTE,
1463 std::vector<D3DVarying>(), false,
1464 angle::CompilerWorkaroundsD3D(), &computeExecutable));
1465
1466 if (computeExecutable == nullptr)
1467 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05001468 ERR() << "Error compiling dynamic compute executable:" << std::endl
1469 << infoLog.str() << std::endl;
Xinghua Caob1239382016-12-13 15:07:05 +08001470 }
1471 else
1472 {
1473 const ShaderD3D *computeShaderD3D = GetImplAs<ShaderD3D>(mState.getAttachedComputeShader());
1474 computeShaderD3D->appendDebugInfo(computeExecutable->getDebugInfo());
1475 mComputeExecutable.reset(computeExecutable);
1476 }
1477
1478 return mComputeExecutable.get() != nullptr;
1479}
1480
Jamie Madill9cf9e872017-06-05 12:59:25 -04001481gl::LinkResult ProgramD3D::link(const gl::Context *context,
1482 const gl::VaryingPacking &packing,
1483 gl::InfoLog &infoLog)
Brandon Jones22502d52014-08-29 16:58:36 -07001484{
Jamie Madillc564c072017-06-01 12:45:42 -04001485 const auto &data = context->getContextState();
Jamie Madill8ecf7f92017-01-13 17:29:52 -05001486
Jamie Madill62d31cb2015-09-11 13:25:51 -04001487 reset();
1488
Jamie Madillbd044ed2017-06-05 12:59:21 -04001489 gl::Shader *computeShader = mState.getAttachedComputeShader();
Xinghua Caob1239382016-12-13 15:07:05 +08001490 if (computeShader)
Austin Kinross02df7962015-07-01 10:03:42 -07001491 {
Xinghua Caob1239382016-12-13 15:07:05 +08001492 mSamplersCS.resize(data.getCaps().maxComputeTextureImageUnits);
1493
Jamie Madillbd044ed2017-06-05 12:59:21 -04001494 defineUniformsAndAssignRegisters(context);
Xinghua Caob1239382016-12-13 15:07:05 +08001495
Jamie Madill9cf9e872017-06-05 12:59:25 -04001496 gl::LinkResult result = compileComputeExecutable(context, infoLog);
Xinghua Caob1239382016-12-13 15:07:05 +08001497 if (result.isError())
Austin Kinross02df7962015-07-01 10:03:42 -07001498 {
Xinghua Caob1239382016-12-13 15:07:05 +08001499 infoLog << result.getError().getMessage();
1500 return result;
1501 }
1502 else if (!result.getResult())
1503 {
1504 infoLog << "Failed to create D3D compute shader.";
1505 return result;
1506 }
1507
Jamie Madillbd044ed2017-06-05 12:59:21 -04001508 initUniformBlockInfo(context, computeShader);
Xinghua Caob1239382016-12-13 15:07:05 +08001509 }
1510 else
1511 {
Jamie Madillbd044ed2017-06-05 12:59:21 -04001512 gl::Shader *vertexShader = mState.getAttachedVertexShader();
1513 gl::Shader *fragmentShader = mState.getAttachedFragmentShader();
Xinghua Caob1239382016-12-13 15:07:05 +08001514
1515 const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(vertexShader);
1516 const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(fragmentShader);
1517
1518 mSamplersVS.resize(data.getCaps().maxVertexTextureImageUnits);
1519 mSamplersPS.resize(data.getCaps().maxTextureImageUnits);
1520
1521 vertexShaderD3D->generateWorkarounds(&mVertexWorkarounds);
1522 fragmentShaderD3D->generateWorkarounds(&mPixelWorkarounds);
1523
1524 if (mRenderer->getNativeLimitations().noFrontFacingSupport)
1525 {
1526 if (fragmentShaderD3D->usesFrontFacing())
1527 {
1528 infoLog << "The current renderer doesn't support gl_FrontFacing";
1529 return false;
1530 }
1531 }
1532
1533 // TODO(jmadill): Implement more sophisticated component packing in D3D9.
1534 // We can fail here because we use one semantic per GLSL varying. D3D11 can pack varyings
1535 // intelligently, but D3D9 assumes one semantic per register.
1536 if (mRenderer->getRendererClass() == RENDERER_D3D9 &&
1537 packing.getMaxSemanticIndex() > data.getCaps().maxVaryingVectors)
1538 {
1539 infoLog << "Cannot pack these varyings on D3D9.";
Jamie Madillb0a838b2016-11-13 20:02:12 -05001540 return false;
Austin Kinross02df7962015-07-01 10:03:42 -07001541 }
Xinghua Caob1239382016-12-13 15:07:05 +08001542
1543 ProgramD3DMetadata metadata(mRenderer, vertexShaderD3D, fragmentShaderD3D);
1544 BuiltinVaryingsD3D builtins(metadata, packing);
1545
Jamie Madillbd044ed2017-06-05 12:59:21 -04001546 mDynamicHLSL->generateShaderLinkHLSL(context, mState, metadata, packing, builtins,
1547 &mPixelHLSL, &mVertexHLSL);
Xinghua Caob1239382016-12-13 15:07:05 +08001548
1549 mUsesPointSize = vertexShaderD3D->usesPointSize();
1550 mDynamicHLSL->getPixelShaderOutputKey(data, mState, metadata, &mPixelShaderKey);
1551 mUsesFragDepth = metadata.usesFragDepth();
Martin Radev41ac68e2017-06-06 12:16:58 +03001552 mUsesViewID = metadata.usesViewID();
1553 mHasANGLEMultiviewEnabled = metadata.hasANGLEMultiviewEnabled();
Xinghua Caob1239382016-12-13 15:07:05 +08001554
1555 // Cache if we use flat shading
Jamie Madillbd044ed2017-06-05 12:59:21 -04001556 mUsesFlatInterpolation =
Jiawei Shao3d404882017-10-16 13:30:48 +08001557 (FindFlatInterpolationVarying(fragmentShader->getInputVaryings(context)) ||
1558 FindFlatInterpolationVarying(vertexShader->getOutputVaryings(context)));
Xinghua Caob1239382016-12-13 15:07:05 +08001559
1560 if (mRenderer->getMajorShaderModel() >= 4)
1561 {
Martin Radev41ac68e2017-06-06 12:16:58 +03001562 mGeometryShaderPreamble = mDynamicHLSL->generateGeometryShaderPreamble(
Martin Radevc1d4e552017-08-21 12:01:10 +03001563 packing, builtins, mHasANGLEMultiviewEnabled,
1564 metadata.canSelectViewInVertexShader());
Xinghua Caob1239382016-12-13 15:07:05 +08001565 }
1566
Jamie Madillbd044ed2017-06-05 12:59:21 -04001567 initAttribLocationsToD3DSemantic(context);
Xinghua Caob1239382016-12-13 15:07:05 +08001568
Jamie Madillbd044ed2017-06-05 12:59:21 -04001569 defineUniformsAndAssignRegisters(context);
Xinghua Caob1239382016-12-13 15:07:05 +08001570
1571 gatherTransformFeedbackVaryings(packing, builtins[SHADER_VERTEX]);
1572
Jamie Madill9cf9e872017-06-05 12:59:25 -04001573 gl::LinkResult result = compileProgramExecutables(context, infoLog);
Xinghua Caob1239382016-12-13 15:07:05 +08001574 if (result.isError())
1575 {
1576 infoLog << result.getError().getMessage();
1577 return result;
1578 }
1579 else if (!result.getResult())
1580 {
1581 infoLog << "Failed to create D3D shaders.";
1582 return result;
1583 }
1584
Jamie Madillbd044ed2017-06-05 12:59:21 -04001585 initUniformBlockInfo(context, vertexShader);
1586 initUniformBlockInfo(context, fragmentShader);
Austin Kinross02df7962015-07-01 10:03:42 -07001587 }
1588
Jamie Madillb0a838b2016-11-13 20:02:12 -05001589 return true;
Brandon Jones22502d52014-08-29 16:58:36 -07001590}
1591
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001592GLboolean ProgramD3D::validate(const gl::Caps & /*caps*/, gl::InfoLog * /*infoLog*/)
Jamie Madill36cfd6a2015-08-18 10:46:20 -04001593{
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001594 // TODO(jmadill): Do something useful here?
1595 return GL_TRUE;
Jamie Madill36cfd6a2015-08-18 10:46:20 -04001596}
1597
Jamie Madillbd044ed2017-06-05 12:59:21 -04001598void ProgramD3D::initUniformBlockInfo(const gl::Context *context, gl::Shader *shader)
Jamie Madill62d31cb2015-09-11 13:25:51 -04001599{
Jiajia Qin9b11ea42017-07-11 16:50:08 +08001600 for (const sh::InterfaceBlock &interfaceBlock : shader->getUniformBlocks(context))
Jamie Madill62d31cb2015-09-11 13:25:51 -04001601 {
Xinghua Caob1239382016-12-13 15:07:05 +08001602 if (!interfaceBlock.staticUse && interfaceBlock.layout == sh::BLOCKLAYOUT_PACKED)
Jamie Madill62d31cb2015-09-11 13:25:51 -04001603 continue;
1604
Xinghua Caob1239382016-12-13 15:07:05 +08001605 if (mBlockDataSizes.count(interfaceBlock.name) > 0)
Jamie Madill62d31cb2015-09-11 13:25:51 -04001606 continue;
1607
Xinghua Caob1239382016-12-13 15:07:05 +08001608 size_t dataSize = getUniformBlockInfo(interfaceBlock);
1609 mBlockDataSizes[interfaceBlock.name] = dataSize;
Jamie Madill62d31cb2015-09-11 13:25:51 -04001610 }
Jamie Madill4a3c2342015-10-08 12:58:45 -04001611}
Jamie Madill62d31cb2015-09-11 13:25:51 -04001612
Jamie Madill51f522f2016-12-21 15:10:55 -05001613void ProgramD3D::ensureUniformBlocksInitialized()
Jamie Madill4a3c2342015-10-08 12:58:45 -04001614{
Jamie Madill51f522f2016-12-21 15:10:55 -05001615 // Lazy init.
1616 if (mState.getUniformBlocks().empty() || !mD3DUniformBlocks.empty())
1617 {
1618 return;
1619 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04001620
1621 // Assign registers and update sizes.
Xinghua Caob1239382016-12-13 15:07:05 +08001622 const ShaderD3D *vertexShaderD3D = SafeGetImplAs<ShaderD3D>(mState.getAttachedVertexShader());
1623 const ShaderD3D *fragmentShaderD3D =
1624 SafeGetImplAs<ShaderD3D>(mState.getAttachedFragmentShader());
1625 const ShaderD3D *computeShaderD3D = SafeGetImplAs<ShaderD3D>(mState.getAttachedComputeShader());
Jamie Madill62d31cb2015-09-11 13:25:51 -04001626
Jiajia Qin729b2c62017-08-14 09:36:11 +08001627 for (const gl::InterfaceBlock &uniformBlock : mState.getUniformBlocks())
Jamie Madill62d31cb2015-09-11 13:25:51 -04001628 {
1629 unsigned int uniformBlockElement = uniformBlock.isArray ? uniformBlock.arrayElement : 0;
1630
Jamie Madill4a3c2342015-10-08 12:58:45 -04001631 D3DUniformBlock d3dUniformBlock;
1632
Jamie Madill62d31cb2015-09-11 13:25:51 -04001633 if (uniformBlock.vertexStaticUse)
1634 {
Xinghua Caob1239382016-12-13 15:07:05 +08001635 ASSERT(vertexShaderD3D != nullptr);
Jiajia Qin9b11ea42017-07-11 16:50:08 +08001636 unsigned int baseRegister = vertexShaderD3D->getUniformBlockRegister(uniformBlock.name);
Jamie Madill4a3c2342015-10-08 12:58:45 -04001637 d3dUniformBlock.vsRegisterIndex = baseRegister + uniformBlockElement;
Jamie Madill62d31cb2015-09-11 13:25:51 -04001638 }
1639
1640 if (uniformBlock.fragmentStaticUse)
1641 {
Xinghua Caob1239382016-12-13 15:07:05 +08001642 ASSERT(fragmentShaderD3D != nullptr);
Jamie Madill62d31cb2015-09-11 13:25:51 -04001643 unsigned int baseRegister =
Jiajia Qin9b11ea42017-07-11 16:50:08 +08001644 fragmentShaderD3D->getUniformBlockRegister(uniformBlock.name);
Jamie Madill4a3c2342015-10-08 12:58:45 -04001645 d3dUniformBlock.psRegisterIndex = baseRegister + uniformBlockElement;
Jamie Madill62d31cb2015-09-11 13:25:51 -04001646 }
1647
Xinghua Caob1239382016-12-13 15:07:05 +08001648 if (uniformBlock.computeStaticUse)
1649 {
1650 ASSERT(computeShaderD3D != nullptr);
1651 unsigned int baseRegister =
Jiajia Qin9b11ea42017-07-11 16:50:08 +08001652 computeShaderD3D->getUniformBlockRegister(uniformBlock.name);
Xinghua Caob1239382016-12-13 15:07:05 +08001653 d3dUniformBlock.csRegisterIndex = baseRegister + uniformBlockElement;
1654 }
1655
Jamie Madill4a3c2342015-10-08 12:58:45 -04001656 mD3DUniformBlocks.push_back(d3dUniformBlock);
Jamie Madill62d31cb2015-09-11 13:25:51 -04001657 }
1658}
1659
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001660void ProgramD3D::initializeUniformStorage()
Brandon Jonesc9610c52014-08-25 17:02:59 -07001661{
1662 // Compute total default block size
Jamie Madill334d6152015-10-22 14:00:28 -04001663 unsigned int vertexRegisters = 0;
Brandon Jonesc9610c52014-08-25 17:02:59 -07001664 unsigned int fragmentRegisters = 0;
Xinghua Caob1239382016-12-13 15:07:05 +08001665 unsigned int computeRegisters = 0;
Jamie Madill62d31cb2015-09-11 13:25:51 -04001666 for (const D3DUniform *d3dUniform : mD3DUniforms)
Brandon Jonesc9610c52014-08-25 17:02:59 -07001667 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001668 if (!d3dUniform->isSampler())
Brandon Jonesc9610c52014-08-25 17:02:59 -07001669 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001670 if (d3dUniform->isReferencedByVertexShader())
Brandon Jonesc9610c52014-08-25 17:02:59 -07001671 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001672 vertexRegisters = std::max(vertexRegisters,
1673 d3dUniform->vsRegisterIndex + d3dUniform->registerCount);
Brandon Jonesc9610c52014-08-25 17:02:59 -07001674 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04001675 if (d3dUniform->isReferencedByFragmentShader())
Brandon Jonesc9610c52014-08-25 17:02:59 -07001676 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001677 fragmentRegisters = std::max(
1678 fragmentRegisters, d3dUniform->psRegisterIndex + d3dUniform->registerCount);
Brandon Jonesc9610c52014-08-25 17:02:59 -07001679 }
Xinghua Caob1239382016-12-13 15:07:05 +08001680 if (d3dUniform->isReferencedByComputeShader())
1681 {
1682 computeRegisters = std::max(
1683 computeRegisters, d3dUniform->csRegisterIndex + d3dUniform->registerCount);
1684 }
Brandon Jonesc9610c52014-08-25 17:02:59 -07001685 }
1686 }
1687
Xinghua Caob1239382016-12-13 15:07:05 +08001688 mVertexUniformStorage =
1689 std::unique_ptr<UniformStorageD3D>(mRenderer->createUniformStorage(vertexRegisters * 16u));
1690 mFragmentUniformStorage = std::unique_ptr<UniformStorageD3D>(
1691 mRenderer->createUniformStorage(fragmentRegisters * 16u));
1692 mComputeUniformStorage =
1693 std::unique_ptr<UniformStorageD3D>(mRenderer->createUniformStorage(computeRegisters * 16u));
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04001694
1695 // Iterate the uniforms again to assign data pointers to default block uniforms.
1696 for (D3DUniform *d3dUniform : mD3DUniforms)
1697 {
1698 if (d3dUniform->isSampler())
1699 {
1700 d3dUniform->mSamplerData.resize(d3dUniform->elementCount(), 0);
1701 continue;
1702 }
1703
1704 if (d3dUniform->isReferencedByVertexShader())
1705 {
1706 d3dUniform->vsData = mVertexUniformStorage->getDataPointer(d3dUniform->vsRegisterIndex,
1707 d3dUniform->registerElement);
1708 }
1709
1710 if (d3dUniform->isReferencedByFragmentShader())
1711 {
1712 d3dUniform->psData = mFragmentUniformStorage->getDataPointer(
1713 d3dUniform->psRegisterIndex, d3dUniform->registerElement);
1714 }
1715
1716 if (d3dUniform->isReferencedByComputeShader())
1717 {
1718 d3dUniform->csData = mComputeUniformStorage->getDataPointer(
1719 d3dUniform->csRegisterIndex, d3dUniform->registerElement);
1720 }
1721 }
Brandon Jonesc9610c52014-08-25 17:02:59 -07001722}
1723
Jamie Madilld63961d2017-09-12 15:22:57 -04001724void ProgramD3D::updateUniformBufferCache(const gl::Caps &caps,
1725 unsigned int reservedVertex,
1726 unsigned int reservedFragment)
Brandon Jones18bd4102014-09-22 14:21:44 -07001727{
Jamie Madill48ef11b2016-04-27 15:21:52 -04001728 if (mState.getUniformBlocks().empty())
Jamie Madill4a3c2342015-10-08 12:58:45 -04001729 {
Jamie Madilld63961d2017-09-12 15:22:57 -04001730 return;
Jamie Madill4a3c2342015-10-08 12:58:45 -04001731 }
1732
Jamie Madill51f522f2016-12-21 15:10:55 -05001733 ensureUniformBlocksInitialized();
Jamie Madill4a3c2342015-10-08 12:58:45 -04001734
Jamie Madill03260fa2015-06-22 13:57:22 -04001735 mVertexUBOCache.clear();
1736 mFragmentUBOCache.clear();
Brandon Jones18bd4102014-09-22 14:21:44 -07001737
Jamie Madill4a3c2342015-10-08 12:58:45 -04001738 for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < mD3DUniformBlocks.size();
Jamie Madill62d31cb2015-09-11 13:25:51 -04001739 uniformBlockIndex++)
Brandon Jones18bd4102014-09-22 14:21:44 -07001740 {
Jamie Madill4a3c2342015-10-08 12:58:45 -04001741 const D3DUniformBlock &uniformBlock = mD3DUniformBlocks[uniformBlockIndex];
Jamie Madill48ef11b2016-04-27 15:21:52 -04001742 GLuint blockBinding = mState.getUniformBlockBinding(uniformBlockIndex);
Brandon Jones18bd4102014-09-22 14:21:44 -07001743
Brandon Jones18bd4102014-09-22 14:21:44 -07001744 // Unnecessary to apply an unreferenced standard or shared UBO
Jamie Madill4a3c2342015-10-08 12:58:45 -04001745 if (!uniformBlock.vertexStaticUse() && !uniformBlock.fragmentStaticUse())
Brandon Jones18bd4102014-09-22 14:21:44 -07001746 {
1747 continue;
1748 }
1749
Jamie Madill4a3c2342015-10-08 12:58:45 -04001750 if (uniformBlock.vertexStaticUse())
Brandon Jones18bd4102014-09-22 14:21:44 -07001751 {
Jamie Madilld63961d2017-09-12 15:22:57 -04001752 unsigned int registerIndex = uniformBlock.vsRegisterIndex - reservedVertex;
1753 ASSERT(registerIndex < caps.maxVertexUniformBlocks);
Jamie Madill03260fa2015-06-22 13:57:22 -04001754
Jamie Madill969194d2015-07-20 14:36:56 -04001755 if (mVertexUBOCache.size() <= registerIndex)
Jamie Madill03260fa2015-06-22 13:57:22 -04001756 {
1757 mVertexUBOCache.resize(registerIndex + 1, -1);
1758 }
1759
1760 ASSERT(mVertexUBOCache[registerIndex] == -1);
1761 mVertexUBOCache[registerIndex] = blockBinding;
Brandon Jones18bd4102014-09-22 14:21:44 -07001762 }
1763
Jamie Madill4a3c2342015-10-08 12:58:45 -04001764 if (uniformBlock.fragmentStaticUse())
Brandon Jones18bd4102014-09-22 14:21:44 -07001765 {
Jamie Madilld63961d2017-09-12 15:22:57 -04001766 unsigned int registerIndex = uniformBlock.psRegisterIndex - reservedFragment;
1767 ASSERT(registerIndex < caps.maxFragmentUniformBlocks);
Jamie Madill03260fa2015-06-22 13:57:22 -04001768
1769 if (mFragmentUBOCache.size() <= registerIndex)
1770 {
1771 mFragmentUBOCache.resize(registerIndex + 1, -1);
1772 }
1773
1774 ASSERT(mFragmentUBOCache[registerIndex] == -1);
1775 mFragmentUBOCache[registerIndex] = blockBinding;
Brandon Jones18bd4102014-09-22 14:21:44 -07001776 }
1777 }
Jamie Madilld63961d2017-09-12 15:22:57 -04001778}
Brandon Jones18bd4102014-09-22 14:21:44 -07001779
Jamie Madilld63961d2017-09-12 15:22:57 -04001780const std::vector<GLint> &ProgramD3D::getVertexUniformBufferCache() const
1781{
1782 return mVertexUBOCache;
1783}
1784
1785const std::vector<GLint> &ProgramD3D::getFragmentUniformBufferCache() const
1786{
1787 return mFragmentUBOCache;
Brandon Jones18bd4102014-09-22 14:21:44 -07001788}
1789
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001790void ProgramD3D::dirtyAllUniforms()
Brandon Jones18bd4102014-09-22 14:21:44 -07001791{
Jamie Madill4148fd72017-09-14 15:46:20 -04001792 mVertexUniformsDirty = true;
1793 mFragmentUniformsDirty = true;
1794 mComputeUniformsDirty = true;
1795}
1796
1797void ProgramD3D::markUniformsClean()
1798{
1799 mVertexUniformsDirty = false;
1800 mFragmentUniformsDirty = false;
1801 mComputeUniformsDirty = false;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001802}
1803
Jamie Madill334d6152015-10-22 14:00:28 -04001804void ProgramD3D::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001805{
Jamie Madill33bb7c42017-09-09 23:32:51 -04001806 setUniformInternal(location, count, v, GL_FLOAT);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001807}
1808
1809void ProgramD3D::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
1810{
Jamie Madill33bb7c42017-09-09 23:32:51 -04001811 setUniformInternal(location, count, v, GL_FLOAT_VEC2);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001812}
1813
1814void ProgramD3D::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
1815{
Jamie Madill33bb7c42017-09-09 23:32:51 -04001816 setUniformInternal(location, count, v, GL_FLOAT_VEC3);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001817}
1818
1819void ProgramD3D::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
1820{
Jamie Madill33bb7c42017-09-09 23:32:51 -04001821 setUniformInternal(location, count, v, GL_FLOAT_VEC4);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001822}
1823
Jamie Madill334d6152015-10-22 14:00:28 -04001824void ProgramD3D::setUniformMatrix2fv(GLint location,
1825 GLsizei count,
1826 GLboolean transpose,
1827 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001828{
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04001829 setUniformMatrixfvInternal<2, 2>(location, count, transpose, value, GL_FLOAT_MAT2);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001830}
1831
Jamie Madill334d6152015-10-22 14:00:28 -04001832void ProgramD3D::setUniformMatrix3fv(GLint location,
1833 GLsizei count,
1834 GLboolean transpose,
1835 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001836{
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04001837 setUniformMatrixfvInternal<3, 3>(location, count, transpose, value, GL_FLOAT_MAT3);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001838}
1839
Jamie Madill334d6152015-10-22 14:00:28 -04001840void ProgramD3D::setUniformMatrix4fv(GLint location,
1841 GLsizei count,
1842 GLboolean transpose,
1843 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001844{
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04001845 setUniformMatrixfvInternal<4, 4>(location, count, transpose, value, GL_FLOAT_MAT4);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001846}
1847
Jamie Madill334d6152015-10-22 14:00:28 -04001848void ProgramD3D::setUniformMatrix2x3fv(GLint location,
1849 GLsizei count,
1850 GLboolean transpose,
1851 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001852{
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04001853 setUniformMatrixfvInternal<2, 3>(location, count, transpose, value, GL_FLOAT_MAT2x3);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001854}
1855
Jamie Madill334d6152015-10-22 14:00:28 -04001856void ProgramD3D::setUniformMatrix3x2fv(GLint location,
1857 GLsizei count,
1858 GLboolean transpose,
1859 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001860{
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04001861 setUniformMatrixfvInternal<3, 2>(location, count, transpose, value, GL_FLOAT_MAT3x2);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001862}
1863
Jamie Madill334d6152015-10-22 14:00:28 -04001864void ProgramD3D::setUniformMatrix2x4fv(GLint location,
1865 GLsizei count,
1866 GLboolean transpose,
1867 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001868{
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04001869 setUniformMatrixfvInternal<2, 4>(location, count, transpose, value, GL_FLOAT_MAT2x4);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001870}
1871
Jamie Madill334d6152015-10-22 14:00:28 -04001872void ProgramD3D::setUniformMatrix4x2fv(GLint location,
1873 GLsizei count,
1874 GLboolean transpose,
1875 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001876{
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04001877 setUniformMatrixfvInternal<4, 2>(location, count, transpose, value, GL_FLOAT_MAT4x2);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001878}
1879
Jamie Madill334d6152015-10-22 14:00:28 -04001880void ProgramD3D::setUniformMatrix3x4fv(GLint location,
1881 GLsizei count,
1882 GLboolean transpose,
1883 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001884{
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04001885 setUniformMatrixfvInternal<3, 4>(location, count, transpose, value, GL_FLOAT_MAT3x4);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001886}
1887
Jamie Madill334d6152015-10-22 14:00:28 -04001888void ProgramD3D::setUniformMatrix4x3fv(GLint location,
1889 GLsizei count,
1890 GLboolean transpose,
1891 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001892{
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04001893 setUniformMatrixfvInternal<4, 3>(location, count, transpose, value, GL_FLOAT_MAT4x3);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001894}
1895
1896void ProgramD3D::setUniform1iv(GLint location, GLsizei count, const GLint *v)
1897{
Jamie Madill33bb7c42017-09-09 23:32:51 -04001898 setUniformInternal(location, count, v, GL_INT);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001899}
1900
1901void ProgramD3D::setUniform2iv(GLint location, GLsizei count, const GLint *v)
1902{
Jamie Madill33bb7c42017-09-09 23:32:51 -04001903 setUniformInternal(location, count, v, GL_INT_VEC2);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001904}
1905
1906void ProgramD3D::setUniform3iv(GLint location, GLsizei count, const GLint *v)
1907{
Jamie Madill33bb7c42017-09-09 23:32:51 -04001908 setUniformInternal(location, count, v, GL_INT_VEC3);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001909}
1910
1911void ProgramD3D::setUniform4iv(GLint location, GLsizei count, const GLint *v)
1912{
Jamie Madill33bb7c42017-09-09 23:32:51 -04001913 setUniformInternal(location, count, v, GL_INT_VEC4);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001914}
1915
1916void ProgramD3D::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
1917{
Jamie Madill33bb7c42017-09-09 23:32:51 -04001918 setUniformInternal(location, count, v, GL_UNSIGNED_INT);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001919}
1920
1921void ProgramD3D::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
1922{
Jamie Madill33bb7c42017-09-09 23:32:51 -04001923 setUniformInternal(location, count, v, GL_UNSIGNED_INT_VEC2);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001924}
1925
1926void ProgramD3D::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
1927{
Jamie Madill33bb7c42017-09-09 23:32:51 -04001928 setUniformInternal(location, count, v, GL_UNSIGNED_INT_VEC3);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001929}
1930
1931void ProgramD3D::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
1932{
Jamie Madill33bb7c42017-09-09 23:32:51 -04001933 setUniformInternal(location, count, v, GL_UNSIGNED_INT_VEC4);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001934}
1935
Jamie Madill4a3c2342015-10-08 12:58:45 -04001936void ProgramD3D::setUniformBlockBinding(GLuint /*uniformBlockIndex*/,
1937 GLuint /*uniformBlockBinding*/)
Geoff Lang5d124a62015-09-15 13:03:27 -04001938{
1939}
1940
Jamie Madillbd044ed2017-06-05 12:59:21 -04001941void ProgramD3D::defineUniformsAndAssignRegisters(const gl::Context *context)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001942{
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001943 D3DUniformMap uniformMap;
Jamie Madillbd044ed2017-06-05 12:59:21 -04001944 gl::Shader *computeShader = mState.getAttachedComputeShader();
Xinghua Caob1239382016-12-13 15:07:05 +08001945 if (computeShader)
Jamie Madill417df922017-01-12 09:23:07 -05001946 {
Jamie Madillbd044ed2017-06-05 12:59:21 -04001947 for (const sh::Uniform &computeUniform : computeShader->getUniforms(context))
Jamie Madillfb536032015-09-11 13:19:49 -04001948 {
Xinghua Caob1239382016-12-13 15:07:05 +08001949 if (computeUniform.staticUse)
1950 {
1951 defineUniformBase(computeShader, computeUniform, &uniformMap);
1952 }
Jamie Madillfb536032015-09-11 13:19:49 -04001953 }
1954 }
Xinghua Caob1239382016-12-13 15:07:05 +08001955 else
Jamie Madillfb536032015-09-11 13:19:49 -04001956 {
Jamie Madillbd044ed2017-06-05 12:59:21 -04001957 gl::Shader *vertexShader = mState.getAttachedVertexShader();
1958 for (const sh::Uniform &vertexUniform : vertexShader->getUniforms(context))
Jamie Madillfb536032015-09-11 13:19:49 -04001959 {
Xinghua Caob1239382016-12-13 15:07:05 +08001960 if (vertexUniform.staticUse)
1961 {
1962 defineUniformBase(vertexShader, vertexUniform, &uniformMap);
1963 }
1964 }
1965
Jamie Madillbd044ed2017-06-05 12:59:21 -04001966 gl::Shader *fragmentShader = mState.getAttachedFragmentShader();
1967 for (const sh::Uniform &fragmentUniform : fragmentShader->getUniforms(context))
Xinghua Caob1239382016-12-13 15:07:05 +08001968 {
1969 if (fragmentUniform.staticUse)
1970 {
1971 defineUniformBase(fragmentShader, fragmentUniform, &uniformMap);
1972 }
Jamie Madillfb536032015-09-11 13:19:49 -04001973 }
1974 }
1975
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001976 // Initialize the D3DUniform list to mirror the indexing of the GL layer.
Jamie Madill48ef11b2016-04-27 15:21:52 -04001977 for (const gl::LinkedUniform &glUniform : mState.getUniforms())
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001978 {
1979 if (!glUniform.isInDefaultBlock())
1980 continue;
1981
1982 auto mapEntry = uniformMap.find(glUniform.name);
1983 ASSERT(mapEntry != uniformMap.end());
1984 mD3DUniforms.push_back(mapEntry->second);
1985 }
1986
Jamie Madill62d31cb2015-09-11 13:25:51 -04001987 assignAllSamplerRegisters();
Jamie Madillfb536032015-09-11 13:19:49 -04001988 initializeUniformStorage();
Jamie Madillfb536032015-09-11 13:19:49 -04001989}
1990
Jamie Madill91445bc2015-09-23 16:47:53 -04001991void ProgramD3D::defineUniformBase(const gl::Shader *shader,
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001992 const sh::Uniform &uniform,
1993 D3DUniformMap *uniformMap)
Jamie Madillfb536032015-09-11 13:19:49 -04001994{
Olli Etuaho96963162016-03-21 11:54:33 +02001995 // Samplers get their registers assigned in assignAllSamplerRegisters.
1996 if (uniform.isBuiltIn() || gl::IsSamplerType(uniform.type))
Jamie Madillfb536032015-09-11 13:19:49 -04001997 {
Jamie Madill91445bc2015-09-23 16:47:53 -04001998 defineUniform(shader->getType(), uniform, uniform.name, nullptr, uniformMap);
Jamie Madill55def582015-05-04 11:24:57 -04001999 return;
2000 }
2001
Jamie Madill91445bc2015-09-23 16:47:53 -04002002 const ShaderD3D *shaderD3D = GetImplAs<ShaderD3D>(shader);
2003
2004 unsigned int startRegister = shaderD3D->getUniformRegister(uniform.name);
2005 ShShaderOutput outputType = shaderD3D->getCompilerOutputType();
Jamie Madillcc2ed612017-03-14 15:59:00 -04002006 sh::HLSLBlockEncoder encoder(sh::HLSLBlockEncoder::GetStrategyFor(outputType), true);
Jamie Madill62d31cb2015-09-11 13:25:51 -04002007 encoder.skipRegisters(startRegister);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002008
Jamie Madill91445bc2015-09-23 16:47:53 -04002009 defineUniform(shader->getType(), uniform, uniform.name, &encoder, uniformMap);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002010}
2011
Jamie Madill62d31cb2015-09-11 13:25:51 -04002012D3DUniform *ProgramD3D::getD3DUniformByName(const std::string &name)
2013{
2014 for (D3DUniform *d3dUniform : mD3DUniforms)
2015 {
2016 if (d3dUniform->name == name)
2017 {
2018 return d3dUniform;
2019 }
2020 }
2021
2022 return nullptr;
2023}
2024
Jamie Madill91445bc2015-09-23 16:47:53 -04002025void ProgramD3D::defineUniform(GLenum shaderType,
Jamie Madill3d3d2f22015-09-23 16:47:51 -04002026 const sh::ShaderVariable &uniform,
2027 const std::string &fullName,
2028 sh::HLSLBlockEncoder *encoder,
2029 D3DUniformMap *uniformMap)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002030{
2031 if (uniform.isStruct())
2032 {
2033 for (unsigned int elementIndex = 0; elementIndex < uniform.elementCount(); elementIndex++)
2034 {
2035 const std::string &elementString = (uniform.isArray() ? ArrayString(elementIndex) : "");
2036
Jamie Madill55def582015-05-04 11:24:57 -04002037 if (encoder)
2038 encoder->enterAggregateType();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002039
2040 for (size_t fieldIndex = 0; fieldIndex < uniform.fields.size(); fieldIndex++)
2041 {
Jamie Madill334d6152015-10-22 14:00:28 -04002042 const sh::ShaderVariable &field = uniform.fields[fieldIndex];
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002043 const std::string &fieldFullName = (fullName + elementString + "." + field.name);
2044
Olli Etuaho96963162016-03-21 11:54:33 +02002045 // Samplers get their registers assigned in assignAllSamplerRegisters.
2046 // Also they couldn't use the same encoder as the rest of the struct, since they are
2047 // extracted out of the struct by the shader translator.
2048 if (gl::IsSamplerType(field.type))
2049 {
2050 defineUniform(shaderType, field, fieldFullName, nullptr, uniformMap);
2051 }
2052 else
2053 {
2054 defineUniform(shaderType, field, fieldFullName, encoder, uniformMap);
2055 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002056 }
2057
Jamie Madill55def582015-05-04 11:24:57 -04002058 if (encoder)
2059 encoder->exitAggregateType();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002060 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04002061 return;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002062 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04002063
2064 // Not a struct. Arrays are treated as aggregate types.
2065 if (uniform.isArray() && encoder)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002066 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002067 encoder->enterAggregateType();
2068 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002069
Jamie Madill62d31cb2015-09-11 13:25:51 -04002070 // Advance the uniform offset, to track registers allocation for structs
2071 sh::BlockMemberInfo blockInfo =
2072 encoder ? encoder->encodeType(uniform.type, uniform.arraySize, false)
2073 : sh::BlockMemberInfo::getDefaultBlockInfo();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002074
Jamie Madill3d3d2f22015-09-23 16:47:51 -04002075 auto uniformMapEntry = uniformMap->find(fullName);
2076 D3DUniform *d3dUniform = nullptr;
Jamie Madill2857f482015-02-09 15:35:29 -05002077
Jamie Madill3d3d2f22015-09-23 16:47:51 -04002078 if (uniformMapEntry != uniformMap->end())
Jamie Madill62d31cb2015-09-11 13:25:51 -04002079 {
Jamie Madill3d3d2f22015-09-23 16:47:51 -04002080 d3dUniform = uniformMapEntry->second;
2081 }
2082 else
2083 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002084 d3dUniform = new D3DUniform(uniform.type, fullName, uniform.arraySize, true);
Jamie Madill3d3d2f22015-09-23 16:47:51 -04002085 (*uniformMap)[fullName] = d3dUniform;
Jamie Madill62d31cb2015-09-11 13:25:51 -04002086 }
2087
2088 if (encoder)
2089 {
Jamie Madill3d3d2f22015-09-23 16:47:51 -04002090 d3dUniform->registerElement =
2091 static_cast<unsigned int>(sh::HLSLBlockEncoder::getBlockRegisterElement(blockInfo));
Jamie Madill62d31cb2015-09-11 13:25:51 -04002092 unsigned int reg =
2093 static_cast<unsigned int>(sh::HLSLBlockEncoder::getBlockRegister(blockInfo));
Jamie Madill91445bc2015-09-23 16:47:53 -04002094 if (shaderType == GL_FRAGMENT_SHADER)
Jamie Madill62d31cb2015-09-11 13:25:51 -04002095 {
2096 d3dUniform->psRegisterIndex = reg;
2097 }
Xinghua Caob1239382016-12-13 15:07:05 +08002098 else if (shaderType == GL_VERTEX_SHADER)
2099 {
2100 d3dUniform->vsRegisterIndex = reg;
2101 }
Jamie Madill91445bc2015-09-23 16:47:53 -04002102 else
Jamie Madill62d31cb2015-09-11 13:25:51 -04002103 {
Xinghua Caob1239382016-12-13 15:07:05 +08002104 ASSERT(shaderType == GL_COMPUTE_SHADER);
2105 d3dUniform->csRegisterIndex = reg;
Jamie Madill62d31cb2015-09-11 13:25:51 -04002106 }
Jamie Madillfb536032015-09-11 13:19:49 -04002107
2108 // Arrays are treated as aggregate types
Jamie Madill62d31cb2015-09-11 13:25:51 -04002109 if (uniform.isArray())
Jamie Madillfb536032015-09-11 13:19:49 -04002110 {
2111 encoder->exitAggregateType();
2112 }
2113 }
2114}
2115
Jamie Madill134f93d2017-08-31 17:11:00 -04002116// Assume count is already clamped.
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002117template <typename T>
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002118void ProgramD3D::setUniformImpl(const gl::VariableLocation &locationInfo,
Jamie Madill134f93d2017-08-31 17:11:00 -04002119 GLsizei count,
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002120 const T *v,
2121 uint8_t *targetData,
Jamie Madill33bb7c42017-09-09 23:32:51 -04002122 GLenum uniformType)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002123{
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002124 D3DUniform *targetUniform = mD3DUniforms[locationInfo.index];
Jamie Madill33bb7c42017-09-09 23:32:51 -04002125 const int components = targetUniform->typeInfo.componentCount;
Olli Etuahoc8538042017-09-27 11:20:15 +03002126 unsigned int arrayElementOffset = locationInfo.flattenedArrayOffset;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002127
Jamie Madill33bb7c42017-09-09 23:32:51 -04002128 if (targetUniform->typeInfo.type == uniformType)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002129 {
Olli Etuahoc8538042017-09-27 11:20:15 +03002130 T *dest = reinterpret_cast<T *>(targetData) + arrayElementOffset * 4;
Jamie Madill33bb7c42017-09-09 23:32:51 -04002131 const T *source = v;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002132
Jamie Madill33bb7c42017-09-09 23:32:51 -04002133 for (GLint i = 0; i < count; i++, dest += 4, source += components)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002134 {
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002135 memcpy(dest, source, components * sizeof(T));
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002136 }
2137 }
Jamie Madill33bb7c42017-09-09 23:32:51 -04002138 else
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002139 {
Jamie Madill33bb7c42017-09-09 23:32:51 -04002140 ASSERT(targetUniform->typeInfo.type == gl::VariableBoolVectorType(uniformType));
Olli Etuahoc8538042017-09-27 11:20:15 +03002141 GLint *boolParams = reinterpret_cast<GLint *>(targetData) + arrayElementOffset * 4;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002142
Jamie Madill134f93d2017-08-31 17:11:00 -04002143 for (GLint i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002144 {
Jamie Madill334d6152015-10-22 14:00:28 -04002145 GLint *dest = boolParams + (i * 4);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002146 const T *source = v + (i * components);
2147
2148 for (int c = 0; c < components; c++)
2149 {
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002150 dest[c] = (source[c] == static_cast<T>(0)) ? GL_FALSE : GL_TRUE;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002151 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002152 }
Brandon Jones18bd4102014-09-22 14:21:44 -07002153 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002154}
2155
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002156template <typename T>
Jamie Madill33bb7c42017-09-09 23:32:51 -04002157void ProgramD3D::setUniformInternal(GLint location, GLsizei count, const T *v, GLenum uniformType)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002158{
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002159 const gl::VariableLocation &locationInfo = mState.getUniformLocations()[location];
2160 D3DUniform *targetUniform = mD3DUniforms[locationInfo.index];
2161
Jamie Madill33bb7c42017-09-09 23:32:51 -04002162 if (targetUniform->typeInfo.isSampler)
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002163 {
Jamie Madill33bb7c42017-09-09 23:32:51 -04002164 ASSERT(uniformType == GL_INT);
Jamie Madill80823cc2017-09-14 15:46:21 -04002165 size_t size = count * sizeof(T);
Olli Etuahoc8538042017-09-27 11:20:15 +03002166 auto dest = &targetUniform->mSamplerData[locationInfo.flattenedArrayOffset];
Jamie Madill80823cc2017-09-14 15:46:21 -04002167 if (memcmp(dest, v, size) != 0)
2168 {
2169 memcpy(dest, v, size);
2170 mDirtySamplerMapping = true;
2171 }
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002172 return;
2173 }
2174
2175 if (targetUniform->vsData)
2176 {
Jamie Madill33bb7c42017-09-09 23:32:51 -04002177 setUniformImpl(locationInfo, count, v, targetUniform->vsData, uniformType);
Jamie Madill4148fd72017-09-14 15:46:20 -04002178 mVertexUniformsDirty = true;
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002179 }
2180
2181 if (targetUniform->psData)
2182 {
Jamie Madill33bb7c42017-09-09 23:32:51 -04002183 setUniformImpl(locationInfo, count, v, targetUniform->psData, uniformType);
Jamie Madill4148fd72017-09-14 15:46:20 -04002184 mFragmentUniformsDirty = true;
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002185 }
2186
2187 if (targetUniform->csData)
2188 {
Jamie Madill33bb7c42017-09-09 23:32:51 -04002189 setUniformImpl(locationInfo, count, v, targetUniform->csData, uniformType);
Jamie Madill4148fd72017-09-14 15:46:20 -04002190 mComputeUniformsDirty = true;
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002191 }
2192}
2193
2194template <int cols, int rows>
Jamie Madill80823cc2017-09-14 15:46:21 -04002195bool ProgramD3D::setUniformMatrixfvImpl(GLint location,
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002196 GLsizei countIn,
2197 GLboolean transpose,
2198 const GLfloat *value,
2199 uint8_t *targetData,
2200 GLenum targetUniformType)
2201{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002202 D3DUniform *targetUniform = getD3DUniformFromLocation(location);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002203
Jamie Madill62d31cb2015-09-11 13:25:51 -04002204 unsigned int elementCount = targetUniform->elementCount();
Olli Etuahoc8538042017-09-27 11:20:15 +03002205 unsigned int arrayElementOffset = mState.getUniformLocations()[location].flattenedArrayOffset;
2206 unsigned int count =
2207 std::min(elementCount - arrayElementOffset, static_cast<unsigned int>(countIn));
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002208
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002209 const unsigned int targetMatrixStride = (4 * rows);
Olli Etuahoc8538042017-09-27 11:20:15 +03002210 GLfloat *target = reinterpret_cast<GLfloat *>(
2211 targetData + arrayElementOffset * sizeof(GLfloat) * targetMatrixStride);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002212
Jamie Madill80823cc2017-09-14 15:46:21 -04002213 bool dirty = false;
2214
Jamie Madill62d31cb2015-09-11 13:25:51 -04002215 for (unsigned int i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002216 {
2217 // Internally store matrices as transposed versions to accomodate HLSL matrix indexing
2218 if (transpose == GL_FALSE)
2219 {
Jamie Madill80823cc2017-09-14 15:46:21 -04002220 dirty = TransposeExpandMatrix<GLfloat, cols, rows>(target, value) || dirty;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002221 }
2222 else
2223 {
Jamie Madill80823cc2017-09-14 15:46:21 -04002224 dirty = ExpandMatrix<GLfloat, cols, rows>(target, value) || dirty;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002225 }
2226 target += targetMatrixStride;
2227 value += cols * rows;
2228 }
Jamie Madill80823cc2017-09-14 15:46:21 -04002229
2230 return dirty;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002231}
2232
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002233template <int cols, int rows>
2234void ProgramD3D::setUniformMatrixfvInternal(GLint location,
2235 GLsizei countIn,
2236 GLboolean transpose,
2237 const GLfloat *value,
2238 GLenum targetUniformType)
2239{
2240 D3DUniform *targetUniform = getD3DUniformFromLocation(location);
2241
2242 if (targetUniform->vsData)
2243 {
Jamie Madill80823cc2017-09-14 15:46:21 -04002244 if (setUniformMatrixfvImpl<cols, rows>(location, countIn, transpose, value,
2245 targetUniform->vsData, targetUniformType))
2246 {
2247 mVertexUniformsDirty = true;
2248 }
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002249 }
2250
2251 if (targetUniform->psData)
2252 {
Jamie Madill80823cc2017-09-14 15:46:21 -04002253 if (setUniformMatrixfvImpl<cols, rows>(location, countIn, transpose, value,
2254 targetUniform->psData, targetUniformType))
2255 {
2256 mFragmentUniformsDirty = true;
2257 }
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002258 }
2259
2260 if (targetUniform->csData)
2261 {
Jamie Madill80823cc2017-09-14 15:46:21 -04002262 if (setUniformMatrixfvImpl<cols, rows>(location, countIn, transpose, value,
2263 targetUniform->csData, targetUniformType))
2264 {
2265 mComputeUniformsDirty = true;
2266 }
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002267 }
2268}
2269
Jamie Madill4a3c2342015-10-08 12:58:45 -04002270size_t ProgramD3D::getUniformBlockInfo(const sh::InterfaceBlock &interfaceBlock)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002271{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002272 ASSERT(interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002273
Jamie Madill62d31cb2015-09-11 13:25:51 -04002274 // define member uniforms
2275 sh::Std140BlockEncoder std140Encoder;
Jamie Madillcc2ed612017-03-14 15:59:00 -04002276 sh::HLSLBlockEncoder hlslEncoder(sh::HLSLBlockEncoder::ENCODE_PACKED, false);
Jamie Madill62d31cb2015-09-11 13:25:51 -04002277 sh::BlockLayoutEncoder *encoder = nullptr;
2278
Qin Jiajiaca68d982017-09-18 16:41:56 +08002279 if (interfaceBlock.layout == sh::BLOCKLAYOUT_STD140)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002280 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002281 encoder = &std140Encoder;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002282 }
2283 else
2284 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002285 encoder = &hlslEncoder;
Jamie Madill61b8dd92015-09-09 19:04:04 +00002286 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04002287
Jamie Madill1bfa6b72017-10-13 14:07:45 -04002288 sh::GetUniformBlockInfo(interfaceBlock.fields, interfaceBlock.fieldPrefix(), encoder,
2289 interfaceBlock.isRowMajorLayout, &mBlockInfo);
Jamie Madill62d31cb2015-09-11 13:25:51 -04002290
2291 return encoder->getBlockSize();
Jamie Madill61b8dd92015-09-09 19:04:04 +00002292}
2293
Jamie Madill62d31cb2015-09-11 13:25:51 -04002294void ProgramD3D::assignAllSamplerRegisters()
Jamie Madilla2eb02c2015-09-11 12:31:41 +00002295{
Olli Etuaho96963162016-03-21 11:54:33 +02002296 for (D3DUniform *d3dUniform : mD3DUniforms)
Jamie Madilla2eb02c2015-09-11 12:31:41 +00002297 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002298 if (d3dUniform->isSampler())
Jamie Madillfb536032015-09-11 13:19:49 -04002299 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002300 assignSamplerRegisters(d3dUniform);
Jamie Madillfb536032015-09-11 13:19:49 -04002301 }
Jamie Madilla2eb02c2015-09-11 12:31:41 +00002302 }
2303}
2304
Olli Etuaho96963162016-03-21 11:54:33 +02002305void ProgramD3D::assignSamplerRegisters(D3DUniform *d3dUniform)
Jamie Madillfb536032015-09-11 13:19:49 -04002306{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002307 ASSERT(d3dUniform->isSampler());
Xinghua Caob1239382016-12-13 15:07:05 +08002308 const gl::Shader *computeShader = mState.getAttachedComputeShader();
2309 if (computeShader)
Jamie Madillfb536032015-09-11 13:19:49 -04002310 {
Xinghua Caob1239382016-12-13 15:07:05 +08002311 const ShaderD3D *computeShaderD3D = GetImplAs<ShaderD3D>(mState.getAttachedComputeShader());
2312 ASSERT(computeShaderD3D->hasUniform(d3dUniform));
2313 d3dUniform->csRegisterIndex = computeShaderD3D->getUniformRegister(d3dUniform->name);
2314 ASSERT(d3dUniform->csRegisterIndex != GL_INVALID_INDEX);
Jamie Madill33bb7c42017-09-09 23:32:51 -04002315 AssignSamplers(d3dUniform->csRegisterIndex, d3dUniform->typeInfo, d3dUniform->arraySize,
Xinghua Caob1239382016-12-13 15:07:05 +08002316 mSamplersCS, &mUsedComputeSamplerRange);
Jamie Madillfb536032015-09-11 13:19:49 -04002317 }
Xinghua Caob1239382016-12-13 15:07:05 +08002318 else
Jamie Madillfb536032015-09-11 13:19:49 -04002319 {
Xinghua Caob1239382016-12-13 15:07:05 +08002320 const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(mState.getAttachedVertexShader());
2321 const ShaderD3D *fragmentShaderD3D =
2322 GetImplAs<ShaderD3D>(mState.getAttachedFragmentShader());
2323 ASSERT(vertexShaderD3D->hasUniform(d3dUniform) ||
2324 fragmentShaderD3D->hasUniform(d3dUniform));
2325 if (vertexShaderD3D->hasUniform(d3dUniform))
2326 {
2327 d3dUniform->vsRegisterIndex = vertexShaderD3D->getUniformRegister(d3dUniform->name);
2328 ASSERT(d3dUniform->vsRegisterIndex != GL_INVALID_INDEX);
Jamie Madill33bb7c42017-09-09 23:32:51 -04002329 AssignSamplers(d3dUniform->vsRegisterIndex, d3dUniform->typeInfo, d3dUniform->arraySize,
Xinghua Caob1239382016-12-13 15:07:05 +08002330 mSamplersVS, &mUsedVertexSamplerRange);
2331 }
2332 if (fragmentShaderD3D->hasUniform(d3dUniform))
2333 {
2334 d3dUniform->psRegisterIndex = fragmentShaderD3D->getUniformRegister(d3dUniform->name);
2335 ASSERT(d3dUniform->psRegisterIndex != GL_INVALID_INDEX);
Jamie Madill33bb7c42017-09-09 23:32:51 -04002336 AssignSamplers(d3dUniform->psRegisterIndex, d3dUniform->typeInfo, d3dUniform->arraySize,
Xinghua Caob1239382016-12-13 15:07:05 +08002337 mSamplersPS, &mUsedPixelSamplerRange);
2338 }
Jamie Madillfb536032015-09-11 13:19:49 -04002339 }
2340}
2341
Jamie Madill62d31cb2015-09-11 13:25:51 -04002342// static
2343void ProgramD3D::AssignSamplers(unsigned int startSamplerIndex,
Jamie Madill33bb7c42017-09-09 23:32:51 -04002344 const gl::UniformTypeInfo &typeInfo,
Jamie Madilld3dfda22015-07-06 08:28:49 -04002345 unsigned int samplerCount,
2346 std::vector<Sampler> &outSamplers,
2347 GLuint *outUsedRange)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002348{
2349 unsigned int samplerIndex = startSamplerIndex;
2350
2351 do
2352 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002353 ASSERT(samplerIndex < outSamplers.size());
2354 Sampler *sampler = &outSamplers[samplerIndex];
2355 sampler->active = true;
Jamie Madill33bb7c42017-09-09 23:32:51 -04002356 sampler->textureType = typeInfo.samplerTextureType;
Jamie Madill62d31cb2015-09-11 13:25:51 -04002357 sampler->logicalTextureUnit = 0;
2358 *outUsedRange = std::max(samplerIndex + 1, *outUsedRange);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002359 samplerIndex++;
2360 } while (samplerIndex < startSamplerIndex + samplerCount);
Brandon Jones18bd4102014-09-22 14:21:44 -07002361}
2362
Brandon Jonesc9610c52014-08-25 17:02:59 -07002363void ProgramD3D::reset()
2364{
Xinghua Caob1239382016-12-13 15:07:05 +08002365 mVertexExecutables.clear();
2366 mPixelExecutables.clear();
Jamie Madill4e31ad52015-10-29 10:32:57 -04002367
Xinghua Caob1239382016-12-13 15:07:05 +08002368 for (auto &geometryExecutable : mGeometryExecutables)
Jamie Madill4e31ad52015-10-29 10:32:57 -04002369 {
Xinghua Caob1239382016-12-13 15:07:05 +08002370 geometryExecutable.reset(nullptr);
Jamie Madill4e31ad52015-10-29 10:32:57 -04002371 }
Brandon Joneseb994362014-09-24 10:27:28 -07002372
Xinghua Caob1239382016-12-13 15:07:05 +08002373 mComputeExecutable.reset(nullptr);
2374
Brandon Jones22502d52014-08-29 16:58:36 -07002375 mVertexHLSL.clear();
Jamie Madill408293f2016-12-20 10:11:45 -05002376 mVertexWorkarounds = angle::CompilerWorkaroundsD3D();
Brandon Jones22502d52014-08-29 16:58:36 -07002377
2378 mPixelHLSL.clear();
Jamie Madill408293f2016-12-20 10:11:45 -05002379 mPixelWorkarounds = angle::CompilerWorkaroundsD3D();
Brandon Jones22502d52014-08-29 16:58:36 -07002380 mUsesFragDepth = false;
Martin Radev41ac68e2017-06-06 12:16:58 +03002381 mHasANGLEMultiviewEnabled = false;
2382 mUsesViewID = false;
Brandon Jones22502d52014-08-29 16:58:36 -07002383 mPixelShaderKey.clear();
Brandon Jones44151a92014-09-10 11:32:25 -07002384 mUsesPointSize = false;
Jamie Madill3e14e2b2015-10-29 14:38:53 -04002385 mUsesFlatInterpolation = false;
Brandon Jones22502d52014-08-29 16:58:36 -07002386
Jamie Madill62d31cb2015-09-11 13:25:51 -04002387 SafeDeleteContainer(mD3DUniforms);
Jamie Madill4a3c2342015-10-08 12:58:45 -04002388 mD3DUniformBlocks.clear();
Jamie Madill62d31cb2015-09-11 13:25:51 -04002389
Xinghua Caob1239382016-12-13 15:07:05 +08002390 mVertexUniformStorage.reset(nullptr);
2391 mFragmentUniformStorage.reset(nullptr);
2392 mComputeUniformStorage.reset(nullptr);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002393
2394 mSamplersPS.clear();
2395 mSamplersVS.clear();
Xinghua Caob1239382016-12-13 15:07:05 +08002396 mSamplersCS.clear();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002397
2398 mUsedVertexSamplerRange = 0;
Jamie Madill334d6152015-10-22 14:00:28 -04002399 mUsedPixelSamplerRange = 0;
Xinghua Caob1239382016-12-13 15:07:05 +08002400 mUsedComputeSamplerRange = 0;
Jamie Madill334d6152015-10-22 14:00:28 -04002401 mDirtySamplerMapping = true;
Jamie Madill437d2662014-12-05 14:23:35 -05002402
Jamie Madill8047c0d2016-03-07 13:02:12 -05002403 mAttribLocationToD3DSemantic.fill(-1);
Jamie Madillccdf74b2015-08-18 10:46:12 -04002404
Jamie Madill9fc36822015-11-18 13:08:07 -05002405 mStreamOutVaryings.clear();
Jamie Madill4e31ad52015-10-29 10:32:57 -04002406
2407 mGeometryShaderPreamble.clear();
Jamie Madill561ed3a2017-08-31 16:48:09 -04002408
Jamie Madill4148fd72017-09-14 15:46:20 -04002409 dirtyAllUniforms();
Jamie Madill0e7f1732017-09-09 23:32:50 -04002410
2411 mCachedPixelExecutableIndex.reset();
2412 mCachedVertexExecutableIndex.reset();
Brandon Jonesc9610c52014-08-25 17:02:59 -07002413}
2414
Geoff Lang7dd2e102014-11-10 15:19:26 -05002415unsigned int ProgramD3D::getSerial() const
2416{
2417 return mSerial;
2418}
2419
2420unsigned int ProgramD3D::issueSerial()
2421{
2422 return mCurrentSerial++;
2423}
2424
Jamie Madillbd044ed2017-06-05 12:59:21 -04002425void ProgramD3D::initAttribLocationsToD3DSemantic(const gl::Context *context)
Jamie Madill63805b42015-08-25 13:17:39 -04002426{
Jamie Madillbd044ed2017-06-05 12:59:21 -04002427 gl::Shader *vertexShader = mState.getAttachedVertexShader();
Jamie Madill63805b42015-08-25 13:17:39 -04002428 ASSERT(vertexShader != nullptr);
2429
2430 // Init semantic index
Jamie Madill34ca4f52017-06-13 11:49:39 -04002431 int semanticIndex = 0;
2432 for (const sh::Attribute &attribute : vertexShader->getActiveAttributes(context))
Jamie Madill63805b42015-08-25 13:17:39 -04002433 {
Jamie Madill8047c0d2016-03-07 13:02:12 -05002434 int regCount = gl::VariableRegisterCount(attribute.type);
Jamie Madill34ca4f52017-06-13 11:49:39 -04002435 GLuint location = mState.getAttributeLocation(attribute.name);
2436 ASSERT(location != std::numeric_limits<GLuint>::max());
Jamie Madill63805b42015-08-25 13:17:39 -04002437
Jamie Madill8047c0d2016-03-07 13:02:12 -05002438 for (int reg = 0; reg < regCount; ++reg)
Jamie Madill63805b42015-08-25 13:17:39 -04002439 {
Jamie Madill34ca4f52017-06-13 11:49:39 -04002440 mAttribLocationToD3DSemantic[location + reg] = semanticIndex++;
Jamie Madill63805b42015-08-25 13:17:39 -04002441 }
2442 }
Jamie Madill437d2662014-12-05 14:23:35 -05002443}
2444
Jamie Madilla779b612017-07-24 11:46:05 -04002445void ProgramD3D::updateCachedInputLayout(Serial associatedSerial, const gl::State &state)
Jamie Madilld3dfda22015-07-06 08:28:49 -04002446{
Jamie Madilla779b612017-07-24 11:46:05 -04002447 if (mCurrentVertexArrayStateSerial == associatedSerial)
2448 {
2449 return;
2450 }
2451
2452 mCurrentVertexArrayStateSerial = associatedSerial;
Jamie Madillbd136f92015-08-10 14:51:37 -04002453 mCachedInputLayout.clear();
Jamie Madill0e7f1732017-09-09 23:32:50 -04002454
Jamie Madilld3dfda22015-07-06 08:28:49 -04002455 const auto &vertexAttributes = state.getVertexArray()->getVertexAttributes();
Jamie Madillf8dd7b12015-08-05 13:50:08 -04002456
Jamie Madill6de51852017-04-12 09:53:01 -04002457 for (size_t locationIndex : mState.getActiveAttribLocationsMask())
Jamie Madilld3dfda22015-07-06 08:28:49 -04002458 {
Jamie Madill8047c0d2016-03-07 13:02:12 -05002459 int d3dSemantic = mAttribLocationToD3DSemantic[locationIndex];
Jamie Madilld3dfda22015-07-06 08:28:49 -04002460
Jamie Madill8047c0d2016-03-07 13:02:12 -05002461 if (d3dSemantic != -1)
Jamie Madilld3dfda22015-07-06 08:28:49 -04002462 {
Jamie Madill8047c0d2016-03-07 13:02:12 -05002463 if (mCachedInputLayout.size() < static_cast<size_t>(d3dSemantic + 1))
Jamie Madillbd136f92015-08-10 14:51:37 -04002464 {
Jamie Madill8047c0d2016-03-07 13:02:12 -05002465 mCachedInputLayout.resize(d3dSemantic + 1, gl::VERTEX_FORMAT_INVALID);
Jamie Madillbd136f92015-08-10 14:51:37 -04002466 }
Jamie Madill8047c0d2016-03-07 13:02:12 -05002467 mCachedInputLayout[d3dSemantic] =
2468 GetVertexFormatType(vertexAttributes[locationIndex],
2469 state.getVertexAttribCurrentValue(locationIndex).Type);
Jamie Madilld3dfda22015-07-06 08:28:49 -04002470 }
2471 }
Jamie Madill4c19a8a2017-07-24 11:46:06 -04002472
2473 VertexExecutable::getSignature(mRenderer, mCachedInputLayout, &mCachedVertexSignature);
Jamie Madill0e7f1732017-09-09 23:32:50 -04002474
2475 updateCachedVertexExecutableIndex();
Jamie Madill4c19a8a2017-07-24 11:46:06 -04002476}
2477
2478void ProgramD3D::updateCachedOutputLayout(const gl::Context *context,
2479 const gl::Framebuffer *framebuffer)
2480{
Jamie Madill0e7f1732017-09-09 23:32:50 -04002481 mPixelShaderOutputLayoutCache.clear();
2482
2483 FramebufferD3D *fboD3D = GetImplAs<FramebufferD3D>(framebuffer);
2484 const auto &colorbuffers = fboD3D->getColorAttachmentsForRender(context);
2485
2486 for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment)
2487 {
2488 const gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment];
2489
2490 if (colorbuffer)
2491 {
2492 auto binding = colorbuffer->getBinding() == GL_BACK ? GL_COLOR_ATTACHMENT0
2493 : colorbuffer->getBinding();
2494 mPixelShaderOutputLayoutCache.push_back(binding);
2495 }
2496 else
2497 {
2498 mPixelShaderOutputLayoutCache.push_back(GL_NONE);
2499 }
2500 }
2501
2502 updateCachedPixelExecutableIndex();
Jamie Madilld3dfda22015-07-06 08:28:49 -04002503}
2504
Jamie Madill192745a2016-12-22 15:58:21 -05002505void ProgramD3D::gatherTransformFeedbackVaryings(const gl::VaryingPacking &varyingPacking,
2506 const BuiltinInfo &builtins)
Jamie Madillccdf74b2015-08-18 10:46:12 -04002507{
Jamie Madill9fc36822015-11-18 13:08:07 -05002508 const std::string &varyingSemantic =
2509 GetVaryingSemantic(mRenderer->getMajorShaderModel(), usesPointSize());
2510
Jamie Madillccdf74b2015-08-18 10:46:12 -04002511 // Gather the linked varyings that are used for transform feedback, they should all exist.
Jamie Madill9fc36822015-11-18 13:08:07 -05002512 mStreamOutVaryings.clear();
2513
Jamie Madill48ef11b2016-04-27 15:21:52 -04002514 const auto &tfVaryingNames = mState.getTransformFeedbackVaryingNames();
Jamie Madill9fc36822015-11-18 13:08:07 -05002515 for (unsigned int outputSlot = 0; outputSlot < static_cast<unsigned int>(tfVaryingNames.size());
2516 ++outputSlot)
Jamie Madillccdf74b2015-08-18 10:46:12 -04002517 {
Jamie Madill9fc36822015-11-18 13:08:07 -05002518 const auto &tfVaryingName = tfVaryingNames[outputSlot];
2519 if (tfVaryingName == "gl_Position")
Jamie Madillccdf74b2015-08-18 10:46:12 -04002520 {
Jamie Madill9fc36822015-11-18 13:08:07 -05002521 if (builtins.glPosition.enabled)
Jamie Madillccdf74b2015-08-18 10:46:12 -04002522 {
Jamie Madill9fc36822015-11-18 13:08:07 -05002523 mStreamOutVaryings.push_back(D3DVarying(builtins.glPosition.semantic,
2524 builtins.glPosition.index, 4, outputSlot));
2525 }
2526 }
2527 else if (tfVaryingName == "gl_FragCoord")
2528 {
2529 if (builtins.glFragCoord.enabled)
2530 {
2531 mStreamOutVaryings.push_back(D3DVarying(builtins.glFragCoord.semantic,
2532 builtins.glFragCoord.index, 4, outputSlot));
2533 }
2534 }
2535 else if (tfVaryingName == "gl_PointSize")
2536 {
2537 if (builtins.glPointSize.enabled)
2538 {
2539 mStreamOutVaryings.push_back(D3DVarying("PSIZE", 0, 1, outputSlot));
2540 }
2541 }
2542 else
2543 {
Olli Etuahoc8538042017-09-27 11:20:15 +03002544 std::vector<unsigned int> subscripts;
2545 std::string baseName = gl::ParseResourceName(tfVaryingName, &subscripts);
jchen10a9042d32017-03-17 08:50:45 +08002546 size_t subscript = GL_INVALID_INDEX;
Olli Etuahoc8538042017-09-27 11:20:15 +03002547 if (!subscripts.empty())
2548 {
2549 subscript = subscripts.back();
2550 }
Jamie Madill192745a2016-12-22 15:58:21 -05002551 for (const auto &registerInfo : varyingPacking.getRegisterList())
Jamie Madill9fc36822015-11-18 13:08:07 -05002552 {
Jamie Madill55c25d02015-11-18 13:08:08 -05002553 const auto &varying = *registerInfo.packedVarying->varying;
2554 GLenum transposedType = gl::TransposeMatrixType(varying.type);
Jamie Madill9fc36822015-11-18 13:08:07 -05002555 int componentCount = gl::VariableColumnCount(transposedType);
2556 ASSERT(!varying.isBuiltIn());
2557
Jamie Madill55c25d02015-11-18 13:08:08 -05002558 // Transform feedback for varying structs is underspecified.
2559 // See Khronos bug 9856.
2560 // TODO(jmadill): Figure out how to be spec-compliant here.
2561 if (registerInfo.packedVarying->isStructField() || varying.isStruct())
2562 continue;
2563
Jamie Madill9fc36822015-11-18 13:08:07 -05002564 // There can be more than one register assigned to a particular varying, and each
2565 // register needs its own stream out entry.
jchen10a9042d32017-03-17 08:50:45 +08002566 if (baseName == registerInfo.packedVarying->varying->name &&
2567 (subscript == GL_INVALID_INDEX || subscript == registerInfo.varyingArrayIndex))
Jamie Madill9fc36822015-11-18 13:08:07 -05002568 {
2569 mStreamOutVaryings.push_back(D3DVarying(
2570 varyingSemantic, registerInfo.semanticIndex, componentCount, outputSlot));
2571 }
Jamie Madillccdf74b2015-08-18 10:46:12 -04002572 }
2573 }
2574 }
2575}
Jamie Madill62d31cb2015-09-11 13:25:51 -04002576
2577D3DUniform *ProgramD3D::getD3DUniformFromLocation(GLint location)
2578{
Jamie Madill48ef11b2016-04-27 15:21:52 -04002579 return mD3DUniforms[mState.getUniformLocations()[location].index];
Jamie Madill62d31cb2015-09-11 13:25:51 -04002580}
Jamie Madill4a3c2342015-10-08 12:58:45 -04002581
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002582const D3DUniform *ProgramD3D::getD3DUniformFromLocation(GLint location) const
2583{
2584 return mD3DUniforms[mState.getUniformLocations()[location].index];
2585}
2586
Olli Etuaho855d9642017-05-17 14:05:06 +03002587bool ProgramD3D::getUniformBlockSize(const std::string &blockName,
2588 const std::string & /* blockMappedName */,
2589 size_t *sizeOut) const
Jamie Madill4a3c2342015-10-08 12:58:45 -04002590{
2591 std::string baseName = blockName;
2592 gl::ParseAndStripArrayIndex(&baseName);
2593
2594 auto sizeIter = mBlockDataSizes.find(baseName);
2595 if (sizeIter == mBlockDataSizes.end())
2596 {
2597 *sizeOut = 0;
2598 return false;
2599 }
2600
2601 *sizeOut = sizeIter->second;
2602 return true;
2603}
2604
2605bool ProgramD3D::getUniformBlockMemberInfo(const std::string &memberUniformName,
Olli Etuaho855d9642017-05-17 14:05:06 +03002606 const std::string & /* memberUniformMappedName */,
Jamie Madill4a3c2342015-10-08 12:58:45 -04002607 sh::BlockMemberInfo *memberInfoOut) const
2608{
2609 auto infoIter = mBlockInfo.find(memberUniformName);
2610 if (infoIter == mBlockInfo.end())
2611 {
2612 *memberInfoOut = sh::BlockMemberInfo::getDefaultBlockInfo();
2613 return false;
2614 }
2615
2616 *memberInfoOut = infoIter->second;
2617 return true;
2618}
Sami Väisänen46eaa942016-06-29 10:26:37 +03002619
2620void ProgramD3D::setPathFragmentInputGen(const std::string &inputName,
2621 GLenum genMode,
2622 GLint components,
2623 const GLfloat *coeffs)
2624{
2625 UNREACHABLE();
2626}
2627
Jamie Madill4c19a8a2017-07-24 11:46:06 -04002628bool ProgramD3D::hasVertexExecutableForCachedInputLayout()
2629{
Jamie Madill0e7f1732017-09-09 23:32:50 -04002630 return mCachedVertexExecutableIndex.valid();
Jamie Madill4c19a8a2017-07-24 11:46:06 -04002631}
2632
2633bool ProgramD3D::hasGeometryExecutableForPrimitiveType(GLenum drawMode)
2634{
2635 if (!usesGeometryShader(drawMode))
2636 {
2637 // No shader necessary mean we have the required (null) executable.
2638 return true;
2639 }
2640
2641 gl::PrimitiveType geometryShaderType = GetGeometryShaderTypeFromDrawMode(drawMode);
2642 return mGeometryExecutables[geometryShaderType].get() != nullptr;
2643}
2644
2645bool ProgramD3D::hasPixelExecutableForCachedOutputLayout()
2646{
Jamie Madill0e7f1732017-09-09 23:32:50 -04002647 return mCachedPixelExecutableIndex.valid();
Jamie Madill4c19a8a2017-07-24 11:46:06 -04002648}
2649
Jamie Madill54164b02017-08-28 15:17:37 -04002650template <typename DestT>
2651void ProgramD3D::getUniformInternal(GLint location, DestT *dataOut) const
2652{
2653 const gl::VariableLocation &locationInfo = mState.getUniformLocations()[location];
2654 const gl::LinkedUniform &uniform = mState.getUniforms()[locationInfo.index];
2655
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002656 const D3DUniform *targetUniform = getD3DUniformFromLocation(location);
Olli Etuahoc8538042017-09-27 11:20:15 +03002657 const uint8_t *srcPointer = targetUniform->getDataPtrToElement(
2658 locationInfo.arrayIndices.empty() ? 0u : locationInfo.flattenedArrayOffset);
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002659
2660 if (gl::IsMatrixType(uniform.type))
2661 {
2662 GetMatrixUniform(gl::VariableColumnCount(uniform.type), gl::VariableRowCount(uniform.type),
2663 dataOut, reinterpret_cast<const DestT *>(srcPointer));
2664 }
2665 else
2666 {
2667 memcpy(dataOut, srcPointer, uniform.getElementSize());
2668 }
Jamie Madill54164b02017-08-28 15:17:37 -04002669}
2670
2671void ProgramD3D::getUniformfv(const gl::Context *context, GLint location, GLfloat *params) const
2672{
2673 getUniformInternal(location, params);
2674}
2675
2676void ProgramD3D::getUniformiv(const gl::Context *context, GLint location, GLint *params) const
2677{
2678 getUniformInternal(location, params);
2679}
2680
2681void ProgramD3D::getUniformuiv(const gl::Context *context, GLint location, GLuint *params) const
2682{
2683 getUniformInternal(location, params);
2684}
2685
Jamie Madill0e7f1732017-09-09 23:32:50 -04002686void ProgramD3D::updateCachedVertexExecutableIndex()
2687{
2688 mCachedVertexExecutableIndex.reset();
2689 for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++)
2690 {
2691 if (mVertexExecutables[executableIndex]->matchesSignature(mCachedVertexSignature))
2692 {
2693 mCachedVertexExecutableIndex = executableIndex;
2694 break;
2695 }
2696 }
2697}
2698
2699void ProgramD3D::updateCachedPixelExecutableIndex()
2700{
2701 mCachedPixelExecutableIndex.reset();
2702 for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++)
2703 {
2704 if (mPixelExecutables[executableIndex]->matchesSignature(mPixelShaderOutputLayoutCache))
2705 {
2706 mCachedPixelExecutableIndex = executableIndex;
2707 break;
2708 }
2709 }
2710}
2711
Jamie Madill8047c0d2016-03-07 13:02:12 -05002712} // namespace rx