blob: 47d4271b8a30cf054c86fd22f1d5174a7cd59f1f [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"
Olli Etuahod2551232017-10-26 20:03:33 +030012#include "common/string_utils.h"
Jamie Madill437d2662014-12-05 14:23:35 -050013#include "common/utilities.h"
Jamie Madillc564c072017-06-01 12:45:42 -040014#include "libANGLE/Context.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050015#include "libANGLE/Framebuffer.h"
16#include "libANGLE/FramebufferAttachment.h"
17#include "libANGLE/Program.h"
Jamie Madill7af0de52017-11-06 17:09:33 -050018#include "libANGLE/ProgramLinkedResources.h"
Jamie Madill53ea9cc2016-05-17 10:12:52 -040019#include "libANGLE/Uniform.h"
Jamie Madilld3dfda22015-07-06 08:28:49 -040020#include "libANGLE/VertexArray.h"
Jamie Madill6df9b372015-02-18 21:28:19 +000021#include "libANGLE/features.h"
Jamie Madill54164b02017-08-28 15:17:37 -040022#include "libANGLE/queryconversions.h"
Jamie Madill8ecf7f92017-01-13 17:29:52 -050023#include "libANGLE/renderer/ContextImpl.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050024#include "libANGLE/renderer/d3d/DynamicHLSL.h"
Jamie Madill85a18042015-03-05 15:41:41 -050025#include "libANGLE/renderer/d3d/FramebufferD3D.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050026#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));
Xinghua Cao26143fd2017-11-01 18:19:05 +080055 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;
Xinghua Cao26143fd2017-11-01 18:19:05 +0800113 constexpr int srcWidth = cols;
114 constexpr int srcHeight = rows;
Corentin Wallezb58e9ba2016-12-15 14:07:56 -0800115
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 Madill04796cd2018-05-24 19:52:16 -0400138gl::PrimitiveMode GetGeometryShaderTypeFromDrawMode(gl::PrimitiveMode drawMode)
Jamie Madill4e31ad52015-10-29 10:32:57 -0400139{
140 switch (drawMode)
141 {
142 // Uses the point sprite geometry shader.
Jamie Madill493f9572018-05-24 19:52:15 -0400143 case gl::PrimitiveMode::Points:
Jamie Madill04796cd2018-05-24 19:52:16 -0400144 return gl::PrimitiveMode::Points;
Jamie Madill4e31ad52015-10-29 10:32:57 -0400145
146 // All line drawing uses the same geometry shader.
Jamie Madill493f9572018-05-24 19:52:15 -0400147 case gl::PrimitiveMode::Lines:
148 case gl::PrimitiveMode::LineStrip:
149 case gl::PrimitiveMode::LineLoop:
Jamie Madill04796cd2018-05-24 19:52:16 -0400150 return gl::PrimitiveMode::Lines;
Jamie Madill4e31ad52015-10-29 10:32:57 -0400151
152 // The triangle fan primitive is emulated with strips in D3D11.
Jamie Madill493f9572018-05-24 19:52:15 -0400153 case gl::PrimitiveMode::Triangles:
154 case gl::PrimitiveMode::TriangleFan:
Jamie Madill04796cd2018-05-24 19:52:16 -0400155 return gl::PrimitiveMode::Triangles;
Jamie Madill4e31ad52015-10-29 10:32:57 -0400156
157 // Special case for triangle strips.
Jamie Madill493f9572018-05-24 19:52:15 -0400158 case gl::PrimitiveMode::TriangleStrip:
Jamie Madill04796cd2018-05-24 19:52:16 -0400159 return gl::PrimitiveMode::TriangleStrip;
Jamie Madill4e31ad52015-10-29 10:32:57 -0400160
161 default:
162 UNREACHABLE();
Jamie Madill04796cd2018-05-24 19:52:16 -0400163 return gl::PrimitiveMode::InvalidEnum;
Jamie Madill4e31ad52015-10-29 10:32:57 -0400164 }
165}
166
Jiawei Shao467c15f2018-04-24 15:04:26 +0800167bool HasFlatInterpolationVarying(const std::vector<sh::Varying> &varyings)
Jamie Madill192745a2016-12-22 15:58:21 -0500168{
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
Jiawei Shao467c15f2018-04-24 15:04:26 +0800181bool FindFlatInterpolationVaryingPerShader(const gl::Context *context, gl::Shader *shader)
182{
183 ASSERT(context && shader);
184 switch (shader->getType())
185 {
186 case gl::ShaderType::Vertex:
187 return HasFlatInterpolationVarying(shader->getOutputVaryings(context));
188 case gl::ShaderType::Fragment:
189 return HasFlatInterpolationVarying(shader->getInputVaryings(context));
190 case gl::ShaderType::Geometry:
191 return HasFlatInterpolationVarying(shader->getInputVaryings(context)) ||
192 HasFlatInterpolationVarying(shader->getOutputVaryings(context));
193 default:
194 UNREACHABLE();
195 return false;
196 }
197}
198
199bool FindFlatInterpolationVarying(const gl::Context *context,
200 const gl::ShaderMap<gl::Shader *> &shaders)
201{
202 ASSERT(context);
203
204 for (gl::ShaderType shaderType : gl::kAllGraphicsShaderTypes)
205 {
206 gl::Shader *shader = shaders[shaderType];
207 if (!shader)
208 {
209 continue;
210 }
211
212 if (FindFlatInterpolationVaryingPerShader(context, shader))
213 {
214 return true;
215 }
216 }
217
218 return false;
219}
220
Jamie Madillbe5e2ec2017-08-31 13:28:28 -0400221// Helper method to de-tranpose a matrix uniform for an API query.
222void GetMatrixUniform(GLint columns, GLint rows, GLfloat *dataOut, const GLfloat *source)
223{
224 for (GLint col = 0; col < columns; ++col)
225 {
226 for (GLint row = 0; row < rows; ++row)
227 {
228 GLfloat *outptr = dataOut + ((col * rows) + row);
229 const GLfloat *inptr = source + ((row * 4) + col);
230 *outptr = *inptr;
231 }
232 }
233}
234
235template <typename NonFloatT>
236void GetMatrixUniform(GLint columns, GLint rows, NonFloatT *dataOut, const NonFloatT *source)
237{
238 UNREACHABLE();
239}
240
Jamie Madill6db1c2e2017-11-08 09:17:40 -0500241class UniformBlockInfo final : angle::NonCopyable
242{
243 public:
244 UniformBlockInfo() {}
245
246 void getShaderBlockInfo(const gl::Context *context, gl::Shader *shader);
247
248 bool getBlockSize(const std::string &name, const std::string &mappedName, size_t *sizeOut);
249 bool getBlockMemberInfo(const std::string &name,
250 const std::string &mappedName,
251 sh::BlockMemberInfo *infoOut);
252
253 private:
254 size_t getBlockInfo(const sh::InterfaceBlock &interfaceBlock);
255
256 std::map<std::string, size_t> mBlockSizes;
257 sh::BlockLayoutMap mBlockLayout;
258};
259
260void UniformBlockInfo::getShaderBlockInfo(const gl::Context *context, gl::Shader *shader)
261{
262 for (const sh::InterfaceBlock &interfaceBlock : shader->getUniformBlocks(context))
263 {
Olli Etuaho107c7242018-03-20 15:45:35 +0200264 if (!interfaceBlock.active && interfaceBlock.layout == sh::BLOCKLAYOUT_PACKED)
Jamie Madill6db1c2e2017-11-08 09:17:40 -0500265 continue;
266
267 if (mBlockSizes.count(interfaceBlock.name) > 0)
268 continue;
269
270 size_t dataSize = getBlockInfo(interfaceBlock);
271 mBlockSizes[interfaceBlock.name] = dataSize;
272 }
273}
274
275size_t UniformBlockInfo::getBlockInfo(const sh::InterfaceBlock &interfaceBlock)
276{
Olli Etuaho107c7242018-03-20 15:45:35 +0200277 ASSERT(interfaceBlock.active || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED);
Jamie Madill6db1c2e2017-11-08 09:17:40 -0500278
279 // define member uniforms
280 sh::Std140BlockEncoder std140Encoder;
281 sh::HLSLBlockEncoder hlslEncoder(sh::HLSLBlockEncoder::ENCODE_PACKED, false);
282 sh::BlockLayoutEncoder *encoder = nullptr;
283
284 if (interfaceBlock.layout == sh::BLOCKLAYOUT_STD140)
285 {
286 encoder = &std140Encoder;
287 }
288 else
289 {
290 encoder = &hlslEncoder;
291 }
292
293 sh::GetUniformBlockInfo(interfaceBlock.fields, interfaceBlock.fieldPrefix(), encoder,
Olli Etuaho3de27032017-11-30 12:16:47 +0200294 &mBlockLayout);
Jamie Madill6db1c2e2017-11-08 09:17:40 -0500295
296 return encoder->getBlockSize();
297}
298
299bool UniformBlockInfo::getBlockSize(const std::string &name,
300 const std::string &mappedName,
301 size_t *sizeOut)
302{
303 size_t nameLengthWithoutArrayIndex;
304 gl::ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
305 std::string baseName = name.substr(0u, nameLengthWithoutArrayIndex);
306 auto sizeIter = mBlockSizes.find(baseName);
307 if (sizeIter == mBlockSizes.end())
308 {
309 *sizeOut = 0;
310 return false;
311 }
312
313 *sizeOut = sizeIter->second;
314 return true;
315};
316
317bool UniformBlockInfo::getBlockMemberInfo(const std::string &name,
318 const std::string &mappedName,
319 sh::BlockMemberInfo *infoOut)
320{
321 auto infoIter = mBlockLayout.find(name);
322 if (infoIter == mBlockLayout.end())
323 {
324 *infoOut = sh::BlockMemberInfo::getDefaultBlockInfo();
325 return false;
326 }
327
328 *infoOut = infoIter->second;
329 return true;
330};
Jamie Madillada9ecc2015-08-17 12:53:37 -0400331} // anonymous namespace
332
Jamie Madill28afae52015-11-09 15:07:57 -0500333// D3DUniform Implementation
334
Jamie Madill33bb7c42017-09-09 23:32:51 -0400335D3DUniform::D3DUniform(GLenum type,
Xinghua Cao26143fd2017-11-01 18:19:05 +0800336 HLSLRegisterType reg,
Jamie Madill62d31cb2015-09-11 13:25:51 -0400337 const std::string &nameIn,
Olli Etuaho465835d2017-09-26 13:34:10 +0300338 const std::vector<unsigned int> &arraySizesIn,
Jamie Madill62d31cb2015-09-11 13:25:51 -0400339 bool defaultBlock)
Jamie Madill33bb7c42017-09-09 23:32:51 -0400340 : typeInfo(gl::GetUniformTypeInfo(type)),
Jamie Madill62d31cb2015-09-11 13:25:51 -0400341 name(nameIn),
Olli Etuaho465835d2017-09-26 13:34:10 +0300342 arraySizes(arraySizesIn),
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800343 mShaderData({}),
Xinghua Cao26143fd2017-11-01 18:19:05 +0800344 regType(reg),
Jamie Madill62d31cb2015-09-11 13:25:51 -0400345 registerCount(0),
346 registerElement(0)
347{
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800348 mShaderRegisterIndexes.fill(GL_INVALID_INDEX);
349
Jamie Madill62d31cb2015-09-11 13:25:51 -0400350 // We use data storage for default block uniforms to cache values that are sent to D3D during
351 // rendering
352 // Uniform blocks/buffers are treated separately by the Renderer (ES3 path only)
353 if (defaultBlock)
354 {
Jamie Madillcc2ed612017-03-14 15:59:00 -0400355 // Use the row count as register count, will work for non-square matrices.
Olli Etuaho465835d2017-09-26 13:34:10 +0300356 registerCount = typeInfo.rowCount * getArraySizeProduct();
Jamie Madill62d31cb2015-09-11 13:25:51 -0400357 }
358}
359
360D3DUniform::~D3DUniform()
361{
Jamie Madillbe5e2ec2017-08-31 13:28:28 -0400362}
363
Olli Etuaho465835d2017-09-26 13:34:10 +0300364unsigned int D3DUniform::getArraySizeProduct() const
365{
366 return gl::ArraySizeProduct(arraySizes);
367}
368
Jamie Madillbe5e2ec2017-08-31 13:28:28 -0400369const uint8_t *D3DUniform::getDataPtrToElement(size_t elementIndex) const
370{
Olli Etuaho465835d2017-09-26 13:34:10 +0300371 ASSERT((!isArray() && elementIndex == 0) ||
372 (isArray() && elementIndex < getArraySizeProduct()));
Jamie Madillbe5e2ec2017-08-31 13:28:28 -0400373
374 if (isSampler())
375 {
376 return reinterpret_cast<const uint8_t *>(&mSamplerData[elementIndex]);
377 }
378
Jamie Madill33bb7c42017-09-09 23:32:51 -0400379 return firstNonNullData() + (elementIndex > 0 ? (typeInfo.internalSize * elementIndex) : 0u);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400380}
381
382bool D3DUniform::isSampler() const
383{
Jamie Madill33bb7c42017-09-09 23:32:51 -0400384 return typeInfo.isSampler;
Jamie Madill62d31cb2015-09-11 13:25:51 -0400385}
386
Xinghua Cao26143fd2017-11-01 18:19:05 +0800387bool D3DUniform::isImage() const
388{
389 return typeInfo.isImageType;
390}
391
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800392bool D3DUniform::isReferencedByShader(gl::ShaderType shaderType) const
Jamie Madill62d31cb2015-09-11 13:25:51 -0400393{
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800394 return mShaderRegisterIndexes[shaderType] != GL_INVALID_INDEX;
Xinghua Caob1239382016-12-13 15:07:05 +0800395}
396
Jamie Madillbe5e2ec2017-08-31 13:28:28 -0400397const uint8_t *D3DUniform::firstNonNullData() const
398{
Jamie Madillbe5e2ec2017-08-31 13:28:28 -0400399 if (!mSamplerData.empty())
400 {
401 return reinterpret_cast<const uint8_t *>(mSamplerData.data());
402 }
403
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800404 for (gl::ShaderType shaderType : gl::AllShaderTypes())
405 {
406 if (mShaderData[shaderType])
407 {
408 return mShaderData[shaderType];
409 }
410 }
411
412 UNREACHABLE();
413 return nullptr;
Jamie Madillbe5e2ec2017-08-31 13:28:28 -0400414}
415
Jamie Madill28afae52015-11-09 15:07:57 -0500416// D3DVarying Implementation
417
Jamie Madill9fc36822015-11-18 13:08:07 -0500418D3DVarying::D3DVarying() : semanticIndex(0), componentCount(0), outputSlot(0)
Jamie Madill28afae52015-11-09 15:07:57 -0500419{
420}
421
Jamie Madill9fc36822015-11-18 13:08:07 -0500422D3DVarying::D3DVarying(const std::string &semanticNameIn,
423 unsigned int semanticIndexIn,
424 unsigned int componentCountIn,
425 unsigned int outputSlotIn)
426 : semanticName(semanticNameIn),
427 semanticIndex(semanticIndexIn),
428 componentCount(componentCountIn),
429 outputSlot(outputSlotIn)
Jamie Madill28afae52015-11-09 15:07:57 -0500430{
431}
432
Jamie Madille39a3f02015-11-17 20:42:15 -0500433// ProgramD3DMetadata Implementation
434
Jamie Madillc9bde922016-07-24 17:58:50 -0400435ProgramD3DMetadata::ProgramD3DMetadata(RendererD3D *renderer,
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800436 const gl::ShaderMap<const ShaderD3D *> &attachedShaders)
Jamie Madillc9bde922016-07-24 17:58:50 -0400437 : mRendererMajorShaderModel(renderer->getMajorShaderModel()),
438 mShaderModelSuffix(renderer->getShaderModelSuffix()),
439 mUsesInstancedPointSpriteEmulation(
440 renderer->getWorkarounds().useInstancedPointSpriteEmulation),
441 mUsesViewScale(renderer->presentPathFastEnabled()),
Martin Radevc1d4e552017-08-21 12:01:10 +0300442 mCanSelectViewInVertexShader(renderer->canSelectViewInVertexShader()),
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800443 mAttachedShaders(attachedShaders)
Jamie Madille39a3f02015-11-17 20:42:15 -0500444{
445}
446
447int ProgramD3DMetadata::getRendererMajorShaderModel() const
448{
449 return mRendererMajorShaderModel;
450}
451
Jamie Madill9082b982016-04-27 15:21:51 -0400452bool ProgramD3DMetadata::usesBroadcast(const gl::ContextState &data) const
Jamie Madille39a3f02015-11-17 20:42:15 -0500453{
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800454 return (mAttachedShaders[gl::ShaderType::Fragment]->usesFragColor() &&
455 mAttachedShaders[gl::ShaderType::Fragment]->usesMultipleRenderTargets() &&
Corentin Wallezc084de12017-06-05 14:28:52 -0700456 data.getClientMajorVersion() < 3);
Jamie Madille39a3f02015-11-17 20:42:15 -0500457}
458
Jamie Madill48ef11b2016-04-27 15:21:52 -0400459bool ProgramD3DMetadata::usesFragDepth() const
Jamie Madille39a3f02015-11-17 20:42:15 -0500460{
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800461 return mAttachedShaders[gl::ShaderType::Fragment]->usesFragDepth();
Jamie Madille39a3f02015-11-17 20:42:15 -0500462}
463
464bool ProgramD3DMetadata::usesPointCoord() const
465{
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800466 return mAttachedShaders[gl::ShaderType::Fragment]->usesPointCoord();
Jamie Madille39a3f02015-11-17 20:42:15 -0500467}
468
469bool ProgramD3DMetadata::usesFragCoord() const
470{
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800471 return mAttachedShaders[gl::ShaderType::Fragment]->usesFragCoord();
Jamie Madille39a3f02015-11-17 20:42:15 -0500472}
473
474bool ProgramD3DMetadata::usesPointSize() const
475{
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800476 return mAttachedShaders[gl::ShaderType::Vertex]->usesPointSize();
Jamie Madille39a3f02015-11-17 20:42:15 -0500477}
478
479bool ProgramD3DMetadata::usesInsertedPointCoordValue() const
480{
Jamie Madillc9bde922016-07-24 17:58:50 -0400481 return (!usesPointSize() || !mUsesInstancedPointSpriteEmulation) && usesPointCoord() &&
482 mRendererMajorShaderModel >= 4;
Jamie Madille39a3f02015-11-17 20:42:15 -0500483}
484
Austin Kinross2a63b3f2016-02-08 12:29:08 -0800485bool ProgramD3DMetadata::usesViewScale() const
486{
487 return mUsesViewScale;
488}
489
Martin Radev41ac68e2017-06-06 12:16:58 +0300490bool ProgramD3DMetadata::hasANGLEMultiviewEnabled() const
491{
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800492 return mAttachedShaders[gl::ShaderType::Vertex]->hasANGLEMultiviewEnabled();
Martin Radev41ac68e2017-06-06 12:16:58 +0300493}
494
495bool ProgramD3DMetadata::usesViewID() const
496{
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800497 return mAttachedShaders[gl::ShaderType::Fragment]->usesViewID();
Martin Radev41ac68e2017-06-06 12:16:58 +0300498}
499
Martin Radevc1d4e552017-08-21 12:01:10 +0300500bool ProgramD3DMetadata::canSelectViewInVertexShader() const
501{
502 return mCanSelectViewInVertexShader;
503}
504
Jamie Madille39a3f02015-11-17 20:42:15 -0500505bool ProgramD3DMetadata::addsPointCoordToVertexShader() const
506{
Jamie Madillc9bde922016-07-24 17:58:50 -0400507 // PointSprite emulation requiress that gl_PointCoord is present in the vertex shader
Jamie Madille39a3f02015-11-17 20:42:15 -0500508 // VS_OUTPUT structure to ensure compatibility with the generated PS_INPUT of the pixel shader.
Jamie Madillc9bde922016-07-24 17:58:50 -0400509 // Even with a geometry shader, the app can render triangles or lines and reference
510 // gl_PointCoord in the fragment shader, requiring us to provide a dummy value. For
511 // simplicity, we always add this to the vertex shader when the fragment shader
512 // references gl_PointCoord, even if we could skip it in the geometry shader.
Jamie Madille39a3f02015-11-17 20:42:15 -0500513 return (mUsesInstancedPointSpriteEmulation && usesPointCoord()) ||
514 usesInsertedPointCoordValue();
515}
516
517bool ProgramD3DMetadata::usesTransformFeedbackGLPosition() const
518{
519 // gl_Position only needs to be outputted from the vertex shader if transform feedback is
520 // active. This isn't supported on D3D11 Feature Level 9_3, so we don't output gl_Position from
521 // the vertex shader in this case. This saves us 1 output vector.
522 return !(mRendererMajorShaderModel >= 4 && mShaderModelSuffix != "");
523}
524
525bool ProgramD3DMetadata::usesSystemValuePointSize() const
526{
527 return !mUsesInstancedPointSpriteEmulation && usesPointSize();
528}
529
530bool ProgramD3DMetadata::usesMultipleFragmentOuts() const
531{
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800532 return mAttachedShaders[gl::ShaderType::Fragment]->usesMultipleRenderTargets();
Jamie Madille39a3f02015-11-17 20:42:15 -0500533}
534
535GLint ProgramD3DMetadata::getMajorShaderVersion() const
536{
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800537 return mAttachedShaders[gl::ShaderType::Vertex]->getData().getShaderVersion();
Jamie Madille39a3f02015-11-17 20:42:15 -0500538}
539
540const ShaderD3D *ProgramD3DMetadata::getFragmentShader() const
541{
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800542 return mAttachedShaders[gl::ShaderType::Fragment];
Jamie Madille39a3f02015-11-17 20:42:15 -0500543}
544
Jamie Madill28afae52015-11-09 15:07:57 -0500545// ProgramD3D Implementation
546
Jamie Madilld3dfda22015-07-06 08:28:49 -0400547ProgramD3D::VertexExecutable::VertexExecutable(const gl::InputLayout &inputLayout,
548 const Signature &signature,
Geoff Lang359ef262015-01-05 14:42:29 -0500549 ShaderExecutableD3D *shaderExecutable)
Jamie Madill334d6152015-10-22 14:00:28 -0400550 : mInputs(inputLayout), mSignature(signature), mShaderExecutable(shaderExecutable)
Brandon Joneseb994362014-09-24 10:27:28 -0700551{
Brandon Joneseb994362014-09-24 10:27:28 -0700552}
553
554ProgramD3D::VertexExecutable::~VertexExecutable()
555{
556 SafeDelete(mShaderExecutable);
557}
558
Jamie Madilld3dfda22015-07-06 08:28:49 -0400559// static
Jamie Madillbdec2f42016-03-02 16:35:32 -0500560ProgramD3D::VertexExecutable::HLSLAttribType ProgramD3D::VertexExecutable::GetAttribType(
561 GLenum type)
562{
563 switch (type)
564 {
565 case GL_INT:
566 return HLSLAttribType::SIGNED_INT;
567 case GL_UNSIGNED_INT:
568 return HLSLAttribType::UNSIGNED_INT;
569 case GL_SIGNED_NORMALIZED:
570 case GL_UNSIGNED_NORMALIZED:
571 case GL_FLOAT:
572 return HLSLAttribType::FLOAT;
573 default:
574 UNREACHABLE();
575 return HLSLAttribType::FLOAT;
576 }
577}
578
579// static
Jamie Madilld3dfda22015-07-06 08:28:49 -0400580void ProgramD3D::VertexExecutable::getSignature(RendererD3D *renderer,
581 const gl::InputLayout &inputLayout,
582 Signature *signatureOut)
Brandon Joneseb994362014-09-24 10:27:28 -0700583{
Jamie Madillbdec2f42016-03-02 16:35:32 -0500584 signatureOut->assign(inputLayout.size(), HLSLAttribType::FLOAT);
Jamie Madilld3dfda22015-07-06 08:28:49 -0400585
586 for (size_t index = 0; index < inputLayout.size(); ++index)
Brandon Joneseb994362014-09-24 10:27:28 -0700587 {
Jamie Madilld3dfda22015-07-06 08:28:49 -0400588 gl::VertexFormatType vertexFormatType = inputLayout[index];
Jamie Madillbdec2f42016-03-02 16:35:32 -0500589 if (vertexFormatType == gl::VERTEX_FORMAT_INVALID)
590 continue;
Jamie Madillbd136f92015-08-10 14:51:37 -0400591
Jamie Madillbdec2f42016-03-02 16:35:32 -0500592 VertexConversionType conversionType = renderer->getVertexConversionType(vertexFormatType);
593 if ((conversionType & VERTEX_CONVERT_GPU) == 0)
594 continue;
595
Xinghua Cao26143fd2017-11-01 18:19:05 +0800596 GLenum componentType = renderer->getVertexComponentType(vertexFormatType);
Jamie Madillbdec2f42016-03-02 16:35:32 -0500597 (*signatureOut)[index] = GetAttribType(componentType);
Brandon Joneseb994362014-09-24 10:27:28 -0700598 }
Brandon Joneseb994362014-09-24 10:27:28 -0700599}
600
Jamie Madilld3dfda22015-07-06 08:28:49 -0400601bool ProgramD3D::VertexExecutable::matchesSignature(const Signature &signature) const
602{
Jamie Madillbd136f92015-08-10 14:51:37 -0400603 size_t limit = std::max(mSignature.size(), signature.size());
604 for (size_t index = 0; index < limit; ++index)
605 {
Jamie Madillbdec2f42016-03-02 16:35:32 -0500606 // treat undefined indexes as FLOAT
607 auto a = index < signature.size() ? signature[index] : HLSLAttribType::FLOAT;
608 auto b = index < mSignature.size() ? mSignature[index] : HLSLAttribType::FLOAT;
Jamie Madillbd136f92015-08-10 14:51:37 -0400609 if (a != b)
610 return false;
611 }
612
613 return true;
Jamie Madilld3dfda22015-07-06 08:28:49 -0400614}
615
616ProgramD3D::PixelExecutable::PixelExecutable(const std::vector<GLenum> &outputSignature,
617 ShaderExecutableD3D *shaderExecutable)
Jamie Madill334d6152015-10-22 14:00:28 -0400618 : mOutputSignature(outputSignature), mShaderExecutable(shaderExecutable)
Brandon Joneseb994362014-09-24 10:27:28 -0700619{
620}
621
622ProgramD3D::PixelExecutable::~PixelExecutable()
623{
624 SafeDelete(mShaderExecutable);
625}
626
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800627ProgramD3D::Sampler::Sampler()
628 : active(false), logicalTextureUnit(0), textureType(gl::TextureType::_2D)
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700629{
630}
631
Xinghua Cao26143fd2017-11-01 18:19:05 +0800632ProgramD3D::Image::Image() : active(false), logicalImageUnit(0)
633{
634}
635
Geoff Lang7dd2e102014-11-10 15:19:26 -0500636unsigned int ProgramD3D::mCurrentSerial = 1;
637
Jamie Madill48ef11b2016-04-27 15:21:52 -0400638ProgramD3D::ProgramD3D(const gl::ProgramState &state, RendererD3D *renderer)
639 : ProgramImpl(state),
Brandon Jonesc9610c52014-08-25 17:02:59 -0700640 mRenderer(renderer),
Xinghua Caob1239382016-12-13 15:07:05 +0800641 mDynamicHLSL(nullptr),
Xinghua Caob1239382016-12-13 15:07:05 +0800642 mComputeExecutable(nullptr),
Brandon Jones44151a92014-09-10 11:32:25 -0700643 mUsesPointSize(false),
Jamie Madill3e14e2b2015-10-29 14:38:53 -0400644 mUsesFlatInterpolation(false),
Jiawei Shao467c15f2018-04-24 15:04:26 +0800645 mUsedShaderSamplerRanges({}),
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700646 mDirtySamplerMapping(true),
Xinghua Cao26143fd2017-11-01 18:19:05 +0800647 mUsedComputeImageRange(0),
648 mUsedComputeReadonlyImageRange(0),
Jiawei Shao3dd8d2912018-03-30 09:39:09 +0800649 mSerial(issueSerial())
Brandon Jonesc9610c52014-08-25 17:02:59 -0700650{
Brandon Joneseb994362014-09-24 10:27:28 -0700651 mDynamicHLSL = new DynamicHLSL(renderer);
Brandon Jonesc9610c52014-08-25 17:02:59 -0700652}
653
654ProgramD3D::~ProgramD3D()
655{
656 reset();
657 SafeDelete(mDynamicHLSL);
658}
659
Brandon Jones44151a92014-09-10 11:32:25 -0700660bool ProgramD3D::usesPointSpriteEmulation() const
661{
662 return mUsesPointSize && mRenderer->getMajorShaderModel() >= 4;
663}
664
Martin Radev41ac68e2017-06-06 12:16:58 +0300665bool ProgramD3D::usesGeometryShaderForPointSpriteEmulation() const
666{
667 return usesPointSpriteEmulation() && !usesInstancedPointSpriteEmulation();
668}
669
Jamie Madill493f9572018-05-24 19:52:15 -0400670bool ProgramD3D::usesGeometryShader(gl::PrimitiveMode drawMode) const
Brandon Jones44151a92014-09-10 11:32:25 -0700671{
Martin Radevc1d4e552017-08-21 12:01:10 +0300672 if (mHasANGLEMultiviewEnabled && !mRenderer->canSelectViewInVertexShader())
Martin Radev41ac68e2017-06-06 12:16:58 +0300673 {
674 return true;
675 }
Jamie Madill493f9572018-05-24 19:52:15 -0400676 if (drawMode != gl::PrimitiveMode::Points)
Jamie Madill3e14e2b2015-10-29 14:38:53 -0400677 {
678 return mUsesFlatInterpolation;
679 }
Martin Radev41ac68e2017-06-06 12:16:58 +0300680 return usesGeometryShaderForPointSpriteEmulation();
Cooper Partine6664f02015-01-09 16:22:24 -0800681}
682
683bool ProgramD3D::usesInstancedPointSpriteEmulation() const
684{
685 return mRenderer->getWorkarounds().useInstancedPointSpriteEmulation;
Brandon Jones44151a92014-09-10 11:32:25 -0700686}
687
Xinghua Cao37584b32017-12-01 11:04:03 +0800688GLint ProgramD3D::getSamplerMapping(gl::ShaderType type,
Jamie Madill334d6152015-10-22 14:00:28 -0400689 unsigned int samplerIndex,
690 const gl::Caps &caps) const
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700691{
692 GLint logicalTextureUnit = -1;
693
Jiawei Shao467c15f2018-04-24 15:04:26 +0800694 ASSERT(type != gl::ShaderType::InvalidEnum);
695
Jiawei Shao54aafe52018-04-27 14:54:57 +0800696 ASSERT(samplerIndex < caps.maxShaderTextureImageUnits[type]);
Jiawei Shao467c15f2018-04-24 15:04:26 +0800697
698 const auto &samplers = mShaderSamplers[type];
699 if (samplerIndex < samplers.size() && samplers[samplerIndex].active)
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700700 {
Jiawei Shao467c15f2018-04-24 15:04:26 +0800701 logicalTextureUnit = samplers[samplerIndex].logicalTextureUnit;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700702 }
703
Jamie Madill334d6152015-10-22 14:00:28 -0400704 if (logicalTextureUnit >= 0 &&
705 logicalTextureUnit < static_cast<GLint>(caps.maxCombinedTextureImageUnits))
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700706 {
707 return logicalTextureUnit;
708 }
709
710 return -1;
711}
712
713// Returns the texture type for a given Direct3D 9 sampler type and
714// index (0-15 for the pixel shader and 0-3 for the vertex shader).
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800715gl::TextureType ProgramD3D::getSamplerTextureType(gl::ShaderType type,
716 unsigned int samplerIndex) const
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700717{
Jiawei Shao467c15f2018-04-24 15:04:26 +0800718 ASSERT(type != gl::ShaderType::InvalidEnum);
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700719
Jiawei Shao467c15f2018-04-24 15:04:26 +0800720 const auto &samplers = mShaderSamplers[type];
721 ASSERT(samplerIndex < samplers.size());
722 ASSERT(samplers[samplerIndex].active);
723
724 return samplers[samplerIndex].textureType;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700725}
726
Xinghua Cao37584b32017-12-01 11:04:03 +0800727GLuint ProgramD3D::getUsedSamplerRange(gl::ShaderType type) const
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700728{
Jiawei Shao467c15f2018-04-24 15:04:26 +0800729 ASSERT(type != gl::ShaderType::InvalidEnum);
730 return mUsedShaderSamplerRanges[type];
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700731}
732
Jamie Madillaf4ffe02017-09-09 23:32:48 -0400733ProgramD3D::SamplerMapping ProgramD3D::updateSamplerMapping()
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700734{
735 if (!mDirtySamplerMapping)
736 {
Jamie Madillaf4ffe02017-09-09 23:32:48 -0400737 return SamplerMapping::WasClean;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700738 }
739
740 mDirtySamplerMapping = false;
741
742 // Retrieve sampler uniform values
Jamie Madill62d31cb2015-09-11 13:25:51 -0400743 for (const D3DUniform *d3dUniform : mD3DUniforms)
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700744 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400745 if (!d3dUniform->isSampler())
746 continue;
747
Olli Etuaho465835d2017-09-26 13:34:10 +0300748 int count = d3dUniform->getArraySizeProduct();
Jamie Madill62d31cb2015-09-11 13:25:51 -0400749
Jiawei Shao467c15f2018-04-24 15:04:26 +0800750 for (gl::ShaderType shaderType : gl::AllShaderTypes())
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700751 {
Jiawei Shao467c15f2018-04-24 15:04:26 +0800752 if (!d3dUniform->isReferencedByShader(shaderType))
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700753 {
Jiawei Shao467c15f2018-04-24 15:04:26 +0800754 continue;
Jamie Madill62d31cb2015-09-11 13:25:51 -0400755 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700756
Jiawei Shao467c15f2018-04-24 15:04:26 +0800757 unsigned int firstIndex = d3dUniform->mShaderRegisterIndexes[shaderType];
Jamie Madill62d31cb2015-09-11 13:25:51 -0400758
Jiawei Shao467c15f2018-04-24 15:04:26 +0800759 std::vector<Sampler> &samplers = mShaderSamplers[shaderType];
Jamie Madill62d31cb2015-09-11 13:25:51 -0400760 for (int i = 0; i < count; i++)
761 {
762 unsigned int samplerIndex = firstIndex + i;
763
Jiawei Shao467c15f2018-04-24 15:04:26 +0800764 if (samplerIndex < samplers.size())
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700765 {
Jiawei Shao467c15f2018-04-24 15:04:26 +0800766 ASSERT(samplers[samplerIndex].active);
767 samplers[samplerIndex].logicalTextureUnit = d3dUniform->mSamplerData[i];
Xinghua Caob1239382016-12-13 15:07:05 +0800768 }
769 }
770 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700771 }
Jamie Madillaf4ffe02017-09-09 23:32:48 -0400772
773 return SamplerMapping::WasDirty;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700774}
775
Xinghua Cao26143fd2017-11-01 18:19:05 +0800776GLint ProgramD3D::getImageMapping(gl::ShaderType type,
777 unsigned int imageIndex,
778 bool readonly,
779 const gl::Caps &caps) const
780{
781 GLint logicalImageUnit = -1;
782 ASSERT(imageIndex < caps.maxImageUnits);
783 switch (type)
784 {
Jiawei Shao385b3e02018-03-21 09:43:28 +0800785 case gl::ShaderType::Compute:
Xinghua Cao26143fd2017-11-01 18:19:05 +0800786 if (readonly && imageIndex < mReadonlyImagesCS.size() &&
787 mReadonlyImagesCS[imageIndex].active)
788 {
789 logicalImageUnit = mReadonlyImagesCS[imageIndex].logicalImageUnit;
790 }
791 else if (imageIndex < mImagesCS.size() && mImagesCS[imageIndex].active)
792 {
793 logicalImageUnit = mImagesCS[imageIndex].logicalImageUnit;
794 }
795 break;
796 // TODO(xinghua.cao@intel.com): add image mapping for vertex shader and pixel shader.
797 default:
798 UNREACHABLE();
799 }
800
801 if (logicalImageUnit >= 0 && logicalImageUnit < static_cast<GLint>(caps.maxImageUnits))
802 {
803 return logicalImageUnit;
804 }
805
806 return -1;
807}
808
809GLuint ProgramD3D::getUsedImageRange(gl::ShaderType type, bool readonly) const
810{
811 switch (type)
812 {
Jiawei Shao385b3e02018-03-21 09:43:28 +0800813 case gl::ShaderType::Compute:
Xinghua Cao26143fd2017-11-01 18:19:05 +0800814 return readonly ? mUsedComputeReadonlyImageRange : mUsedComputeImageRange;
815 // TODO(xinghua.cao@intel.com): add image range of vertex shader and pixel shader.
816 default:
817 UNREACHABLE();
818 return 0u;
819 }
820}
821
Jamie Madill9cf9e872017-06-05 12:59:25 -0400822gl::LinkResult ProgramD3D::load(const gl::Context *context,
823 gl::InfoLog &infoLog,
824 gl::BinaryInputStream *stream)
Brandon Jones22502d52014-08-29 16:58:36 -0700825{
Jamie Madilla7d12dc2016-12-13 15:08:19 -0500826 // TODO(jmadill): Use Renderer from contextImpl.
827
Jamie Madill62d31cb2015-09-11 13:25:51 -0400828 reset();
829
Jamie Madill334d6152015-10-22 14:00:28 -0400830 DeviceIdentifier binaryDeviceIdentifier = {0};
831 stream->readBytes(reinterpret_cast<unsigned char *>(&binaryDeviceIdentifier),
832 sizeof(DeviceIdentifier));
Austin Kinross137b1512015-06-17 16:14:53 -0700833
834 DeviceIdentifier identifier = mRenderer->getAdapterIdentifier();
835 if (memcmp(&identifier, &binaryDeviceIdentifier, sizeof(DeviceIdentifier)) != 0)
836 {
837 infoLog << "Invalid program binary, device configuration has changed.";
Jamie Madillb0a838b2016-11-13 20:02:12 -0500838 return false;
Austin Kinross137b1512015-06-17 16:14:53 -0700839 }
840
Jamie Madill2db1fbb2014-12-03 10:58:55 -0500841 int compileFlags = stream->readInt<int>();
842 if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL)
843 {
Jamie Madillf6113162015-05-07 11:49:21 -0400844 infoLog << "Mismatched compilation flags.";
Jamie Madillb0a838b2016-11-13 20:02:12 -0500845 return false;
Jamie Madill2db1fbb2014-12-03 10:58:55 -0500846 }
847
Jamie Madill8047c0d2016-03-07 13:02:12 -0500848 for (int &index : mAttribLocationToD3DSemantic)
Jamie Madill63805b42015-08-25 13:17:39 -0400849 {
Jamie Madill8047c0d2016-03-07 13:02:12 -0500850 stream->readInt(&index);
Jamie Madill63805b42015-08-25 13:17:39 -0400851 }
852
Jiawei Shao467c15f2018-04-24 15:04:26 +0800853 for (gl::ShaderType shaderType : gl::AllShaderTypes())
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700854 {
Jiawei Shao467c15f2018-04-24 15:04:26 +0800855 const unsigned int samplerCount = stream->readInt<unsigned int>();
856 for (unsigned int i = 0; i < samplerCount; ++i)
857 {
858 Sampler sampler;
859 stream->readBool(&sampler.active);
860 stream->readInt(&sampler.logicalTextureUnit);
861 stream->readEnum(&sampler.textureType);
862 mShaderSamplers[shaderType].push_back(sampler);
863 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700864
Jiawei Shao467c15f2018-04-24 15:04:26 +0800865 stream->readInt(&mUsedShaderSamplerRanges[shaderType]);
Xinghua Caob1239382016-12-13 15:07:05 +0800866 }
867
Xinghua Cao26143fd2017-11-01 18:19:05 +0800868 const unsigned int csImageCount = stream->readInt<unsigned int>();
869 for (unsigned int i = 0; i < csImageCount; ++i)
870 {
871 Image image;
872 stream->readBool(&image.active);
873 stream->readInt(&image.logicalImageUnit);
874 mImagesCS.push_back(image);
875 }
876
877 const unsigned int csReadonlyImageCount = stream->readInt<unsigned int>();
878 for (unsigned int i = 0; i < csReadonlyImageCount; ++i)
879 {
880 Image image;
881 stream->readBool(&image.active);
882 stream->readInt(&image.logicalImageUnit);
883 mReadonlyImagesCS.push_back(image);
884 }
885
Xinghua Cao26143fd2017-11-01 18:19:05 +0800886 stream->readInt(&mUsedComputeImageRange);
887 stream->readInt(&mUsedComputeReadonlyImageRange);
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700888
889 const unsigned int uniformCount = stream->readInt<unsigned int>();
890 if (stream->error())
891 {
Jamie Madillf6113162015-05-07 11:49:21 -0400892 infoLog << "Invalid program binary.";
Jamie Madillb0a838b2016-11-13 20:02:12 -0500893 return false;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700894 }
895
Jamie Madill48ef11b2016-04-27 15:21:52 -0400896 const auto &linkedUniforms = mState.getUniforms();
Jamie Madill62d31cb2015-09-11 13:25:51 -0400897 ASSERT(mD3DUniforms.empty());
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700898 for (unsigned int uniformIndex = 0; uniformIndex < uniformCount; uniformIndex++)
899 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400900 const gl::LinkedUniform &linkedUniform = linkedUniforms[uniformIndex];
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700901
Jamie Madill62d31cb2015-09-11 13:25:51 -0400902 D3DUniform *d3dUniform =
Xinghua Cao26143fd2017-11-01 18:19:05 +0800903 new D3DUniform(linkedUniform.type, HLSLRegisterType::None, linkedUniform.name,
904 linkedUniform.arraySizes, linkedUniform.isInDefaultBlock());
905 stream->readInt<HLSLRegisterType>(&d3dUniform->regType);
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800906 for (gl::ShaderType shaderType : gl::AllShaderTypes())
907 {
908 stream->readInt(&d3dUniform->mShaderRegisterIndexes[shaderType]);
909 }
Jamie Madill62d31cb2015-09-11 13:25:51 -0400910 stream->readInt(&d3dUniform->registerCount);
911 stream->readInt(&d3dUniform->registerElement);
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700912
Jamie Madill62d31cb2015-09-11 13:25:51 -0400913 mD3DUniforms.push_back(d3dUniform);
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700914 }
915
Jamie Madill4a3c2342015-10-08 12:58:45 -0400916 const unsigned int blockCount = stream->readInt<unsigned int>();
917 if (stream->error())
918 {
919 infoLog << "Invalid program binary.";
Jamie Madillb0a838b2016-11-13 20:02:12 -0500920 return false;
Jamie Madill4a3c2342015-10-08 12:58:45 -0400921 }
922
923 ASSERT(mD3DUniformBlocks.empty());
924 for (unsigned int blockIndex = 0; blockIndex < blockCount; ++blockIndex)
925 {
926 D3DUniformBlock uniformBlock;
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800927 for (gl::ShaderType shaderType : gl::AllShaderTypes())
928 {
929 stream->readInt(&uniformBlock.mShaderRegisterIndexes[shaderType]);
930 }
Jamie Madill4a3c2342015-10-08 12:58:45 -0400931 mD3DUniformBlocks.push_back(uniformBlock);
932 }
933
Jamie Madill9fc36822015-11-18 13:08:07 -0500934 const unsigned int streamOutVaryingCount = stream->readInt<unsigned int>();
935 mStreamOutVaryings.resize(streamOutVaryingCount);
936 for (unsigned int varyingIndex = 0; varyingIndex < streamOutVaryingCount; ++varyingIndex)
Brandon Joneseb994362014-09-24 10:27:28 -0700937 {
Jamie Madill9fc36822015-11-18 13:08:07 -0500938 D3DVarying *varying = &mStreamOutVaryings[varyingIndex];
Brandon Joneseb994362014-09-24 10:27:28 -0700939
Jamie Madill28afae52015-11-09 15:07:57 -0500940 stream->readString(&varying->semanticName);
941 stream->readInt(&varying->semanticIndex);
Jamie Madill9fc36822015-11-18 13:08:07 -0500942 stream->readInt(&varying->componentCount);
943 stream->readInt(&varying->outputSlot);
Brandon Joneseb994362014-09-24 10:27:28 -0700944 }
945
Jiawei Shao467c15f2018-04-24 15:04:26 +0800946 for (gl::ShaderType shaderType : gl::AllShaderTypes())
947 {
948 stream->readString(&mShaderHLSL[shaderType]);
949 stream->readBytes(reinterpret_cast<unsigned char *>(&mShaderWorkarounds[shaderType]),
950 sizeof(angle::CompilerWorkaroundsD3D));
951 }
952
Brandon Jones22502d52014-08-29 16:58:36 -0700953 stream->readBool(&mUsesFragDepth);
Martin Radev41ac68e2017-06-06 12:16:58 +0300954 stream->readBool(&mHasANGLEMultiviewEnabled);
955 stream->readBool(&mUsesViewID);
Brandon Jones44151a92014-09-10 11:32:25 -0700956 stream->readBool(&mUsesPointSize);
Jamie Madill3e14e2b2015-10-29 14:38:53 -0400957 stream->readBool(&mUsesFlatInterpolation);
Brandon Jones22502d52014-08-29 16:58:36 -0700958
959 const size_t pixelShaderKeySize = stream->readInt<unsigned int>();
960 mPixelShaderKey.resize(pixelShaderKeySize);
Jamie Madill334d6152015-10-22 14:00:28 -0400961 for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKeySize;
962 pixelShaderKeyIndex++)
Brandon Jones22502d52014-08-29 16:58:36 -0700963 {
964 stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].type);
965 stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].name);
966 stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].source);
967 stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].outputIndex);
968 }
969
Jamie Madill4e31ad52015-10-29 10:32:57 -0400970 stream->readString(&mGeometryShaderPreamble);
971
Jamie Madill334d6152015-10-22 14:00:28 -0400972 const unsigned char *binary = reinterpret_cast<const unsigned char *>(stream->data());
Brandon Joneseb994362014-09-24 10:27:28 -0700973
Jamie Madillb0a838b2016-11-13 20:02:12 -0500974 bool separateAttribs = (mState.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS);
975
Brandon Joneseb994362014-09-24 10:27:28 -0700976 const unsigned int vertexShaderCount = stream->readInt<unsigned int>();
Jamie Madill334d6152015-10-22 14:00:28 -0400977 for (unsigned int vertexShaderIndex = 0; vertexShaderIndex < vertexShaderCount;
978 vertexShaderIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -0700979 {
Jamie Madilld3dfda22015-07-06 08:28:49 -0400980 size_t inputLayoutSize = stream->readInt<size_t>();
Jamie Madillf8dd7b12015-08-05 13:50:08 -0400981 gl::InputLayout inputLayout(inputLayoutSize, gl::VERTEX_FORMAT_INVALID);
Brandon Joneseb994362014-09-24 10:27:28 -0700982
Jamie Madilld3dfda22015-07-06 08:28:49 -0400983 for (size_t inputIndex = 0; inputIndex < inputLayoutSize; inputIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -0700984 {
Jamie Madillf8dd7b12015-08-05 13:50:08 -0400985 inputLayout[inputIndex] = stream->readInt<gl::VertexFormatType>();
Brandon Joneseb994362014-09-24 10:27:28 -0700986 }
987
Jamie Madill334d6152015-10-22 14:00:28 -0400988 unsigned int vertexShaderSize = stream->readInt<unsigned int>();
Brandon Joneseb994362014-09-24 10:27:28 -0700989 const unsigned char *vertexShaderFunction = binary + stream->offset();
Geoff Langb543aff2014-09-30 14:52:54 -0400990
Jamie Madillada9ecc2015-08-17 12:53:37 -0400991 ShaderExecutableD3D *shaderExecutable = nullptr;
992
Yunchao He85072e82017-11-14 15:43:28 +0800993 ANGLE_TRY(mRenderer->loadExecutable(vertexShaderFunction, vertexShaderSize,
Jiawei Shao385b3e02018-03-21 09:43:28 +0800994 gl::ShaderType::Vertex, mStreamOutVaryings,
995 separateAttribs, &shaderExecutable));
Geoff Langb543aff2014-09-30 14:52:54 -0400996
Brandon Joneseb994362014-09-24 10:27:28 -0700997 if (!shaderExecutable)
998 {
Jamie Madillf6113162015-05-07 11:49:21 -0400999 infoLog << "Could not create vertex shader.";
Jamie Madillb0a838b2016-11-13 20:02:12 -05001000 return false;
Brandon Joneseb994362014-09-24 10:27:28 -07001001 }
1002
1003 // generated converted input layout
Jamie Madilld3dfda22015-07-06 08:28:49 -04001004 VertexExecutable::Signature signature;
1005 VertexExecutable::getSignature(mRenderer, inputLayout, &signature);
Brandon Joneseb994362014-09-24 10:27:28 -07001006
1007 // add new binary
Xinghua Caob1239382016-12-13 15:07:05 +08001008 mVertexExecutables.push_back(std::unique_ptr<VertexExecutable>(
1009 new VertexExecutable(inputLayout, signature, shaderExecutable)));
Brandon Joneseb994362014-09-24 10:27:28 -07001010
1011 stream->skip(vertexShaderSize);
1012 }
1013
1014 const size_t pixelShaderCount = stream->readInt<unsigned int>();
1015 for (size_t pixelShaderIndex = 0; pixelShaderIndex < pixelShaderCount; pixelShaderIndex++)
1016 {
1017 const size_t outputCount = stream->readInt<unsigned int>();
1018 std::vector<GLenum> outputs(outputCount);
1019 for (size_t outputIndex = 0; outputIndex < outputCount; outputIndex++)
1020 {
1021 stream->readInt(&outputs[outputIndex]);
1022 }
1023
Jamie Madill334d6152015-10-22 14:00:28 -04001024 const size_t pixelShaderSize = stream->readInt<unsigned int>();
Brandon Joneseb994362014-09-24 10:27:28 -07001025 const unsigned char *pixelShaderFunction = binary + stream->offset();
Jamie Madillada9ecc2015-08-17 12:53:37 -04001026 ShaderExecutableD3D *shaderExecutable = nullptr;
1027
Yunchao He85072e82017-11-14 15:43:28 +08001028 ANGLE_TRY(mRenderer->loadExecutable(pixelShaderFunction, pixelShaderSize,
Jiawei Shao385b3e02018-03-21 09:43:28 +08001029 gl::ShaderType::Fragment, mStreamOutVaryings,
Yunchao He85072e82017-11-14 15:43:28 +08001030 separateAttribs, &shaderExecutable));
Brandon Joneseb994362014-09-24 10:27:28 -07001031
1032 if (!shaderExecutable)
1033 {
Jamie Madillf6113162015-05-07 11:49:21 -04001034 infoLog << "Could not create pixel shader.";
Jamie Madillb0a838b2016-11-13 20:02:12 -05001035 return false;
Brandon Joneseb994362014-09-24 10:27:28 -07001036 }
1037
1038 // add new binary
Xinghua Caob1239382016-12-13 15:07:05 +08001039 mPixelExecutables.push_back(
1040 std::unique_ptr<PixelExecutable>(new PixelExecutable(outputs, shaderExecutable)));
Brandon Joneseb994362014-09-24 10:27:28 -07001041
1042 stream->skip(pixelShaderSize);
1043 }
1044
Jamie Madill04796cd2018-05-24 19:52:16 -04001045 for (auto &geometryExe : mGeometryExecutables)
Brandon Joneseb994362014-09-24 10:27:28 -07001046 {
Jamie Madill4e31ad52015-10-29 10:32:57 -04001047 unsigned int geometryShaderSize = stream->readInt<unsigned int>();
1048 if (geometryShaderSize == 0)
1049 {
Jamie Madill4e31ad52015-10-29 10:32:57 -04001050 continue;
1051 }
1052
Brandon Joneseb994362014-09-24 10:27:28 -07001053 const unsigned char *geometryShaderFunction = binary + stream->offset();
Jamie Madill4e31ad52015-10-29 10:32:57 -04001054
Xinghua Caob1239382016-12-13 15:07:05 +08001055 ShaderExecutableD3D *geometryExecutable = nullptr;
Jamie Madillb0a838b2016-11-13 20:02:12 -05001056 ANGLE_TRY(mRenderer->loadExecutable(geometryShaderFunction, geometryShaderSize,
Jiawei Shao385b3e02018-03-21 09:43:28 +08001057 gl::ShaderType::Geometry, mStreamOutVaryings,
Yunchao He85072e82017-11-14 15:43:28 +08001058 separateAttribs, &geometryExecutable));
Brandon Joneseb994362014-09-24 10:27:28 -07001059
Xinghua Caob1239382016-12-13 15:07:05 +08001060 if (!geometryExecutable)
Brandon Joneseb994362014-09-24 10:27:28 -07001061 {
Jamie Madillf6113162015-05-07 11:49:21 -04001062 infoLog << "Could not create geometry shader.";
Jamie Madillb0a838b2016-11-13 20:02:12 -05001063 return false;
Brandon Joneseb994362014-09-24 10:27:28 -07001064 }
Xinghua Caob1239382016-12-13 15:07:05 +08001065
Jamie Madill04796cd2018-05-24 19:52:16 -04001066 geometryExe.reset(geometryExecutable);
Xinghua Caob1239382016-12-13 15:07:05 +08001067
Brandon Joneseb994362014-09-24 10:27:28 -07001068 stream->skip(geometryShaderSize);
1069 }
1070
Xinghua Caob1239382016-12-13 15:07:05 +08001071 unsigned int computeShaderSize = stream->readInt<unsigned int>();
1072 if (computeShaderSize > 0)
1073 {
1074 const unsigned char *computeShaderFunction = binary + stream->offset();
1075
1076 ShaderExecutableD3D *computeExecutable = nullptr;
1077 ANGLE_TRY(mRenderer->loadExecutable(computeShaderFunction, computeShaderSize,
Jiawei Shao385b3e02018-03-21 09:43:28 +08001078 gl::ShaderType::Compute, std::vector<D3DVarying>(),
1079 false, &computeExecutable));
Xinghua Caob1239382016-12-13 15:07:05 +08001080
1081 if (!computeExecutable)
1082 {
1083 infoLog << "Could not create compute shader.";
1084 return false;
1085 }
1086
1087 mComputeExecutable.reset(computeExecutable);
1088 }
1089
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08001090 initializeUniformStorage(mState.getLinkedShaderStages());
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001091
Jiawei Shao3dd8d2912018-03-30 09:39:09 +08001092 dirtyAllUniforms();
1093
Jamie Madillb0a838b2016-11-13 20:02:12 -05001094 return true;
Brandon Jones22502d52014-08-29 16:58:36 -07001095}
1096
Jamie Madill27a60632017-06-30 15:12:01 -04001097void ProgramD3D::save(const gl::Context *context, gl::BinaryOutputStream *stream)
Brandon Jones22502d52014-08-29 16:58:36 -07001098{
Austin Kinross137b1512015-06-17 16:14:53 -07001099 // Output the DeviceIdentifier before we output any shader code
Jamie Madill334d6152015-10-22 14:00:28 -04001100 // When we load the binary again later, we can validate the device identifier before trying to
1101 // compile any HLSL
Austin Kinross137b1512015-06-17 16:14:53 -07001102 DeviceIdentifier binaryIdentifier = mRenderer->getAdapterIdentifier();
Jamie Madill334d6152015-10-22 14:00:28 -04001103 stream->writeBytes(reinterpret_cast<unsigned char *>(&binaryIdentifier),
1104 sizeof(DeviceIdentifier));
Austin Kinross137b1512015-06-17 16:14:53 -07001105
Jamie Madill2db1fbb2014-12-03 10:58:55 -05001106 stream->writeInt(ANGLE_COMPILE_OPTIMIZATION_LEVEL);
1107
Jamie Madill8047c0d2016-03-07 13:02:12 -05001108 for (int d3dSemantic : mAttribLocationToD3DSemantic)
Jamie Madill63805b42015-08-25 13:17:39 -04001109 {
Jamie Madill8047c0d2016-03-07 13:02:12 -05001110 stream->writeInt(d3dSemantic);
Jamie Madill63805b42015-08-25 13:17:39 -04001111 }
1112
Jiawei Shao467c15f2018-04-24 15:04:26 +08001113 for (gl::ShaderType shaderType : gl::AllShaderTypes())
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001114 {
Jiawei Shao467c15f2018-04-24 15:04:26 +08001115 stream->writeInt(mShaderSamplers[shaderType].size());
1116 for (unsigned int i = 0; i < mShaderSamplers[shaderType].size(); ++i)
1117 {
1118 stream->writeInt(mShaderSamplers[shaderType][i].active);
1119 stream->writeInt(mShaderSamplers[shaderType][i].logicalTextureUnit);
1120 stream->writeEnum(mShaderSamplers[shaderType][i].textureType);
1121 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001122
Jiawei Shao467c15f2018-04-24 15:04:26 +08001123 stream->writeInt(mUsedShaderSamplerRanges[shaderType]);
Xinghua Caob1239382016-12-13 15:07:05 +08001124 }
1125
Xinghua Cao26143fd2017-11-01 18:19:05 +08001126 stream->writeInt(mImagesCS.size());
1127 for (unsigned int i = 0; i < mImagesCS.size(); ++i)
1128 {
1129 stream->writeInt(mImagesCS[i].active);
1130 stream->writeInt(mImagesCS[i].logicalImageUnit);
1131 }
1132
1133 stream->writeInt(mReadonlyImagesCS.size());
1134 for (unsigned int i = 0; i < mReadonlyImagesCS.size(); ++i)
1135 {
1136 stream->writeInt(mReadonlyImagesCS[i].active);
1137 stream->writeInt(mReadonlyImagesCS[i].logicalImageUnit);
1138 }
1139
Xinghua Cao26143fd2017-11-01 18:19:05 +08001140 stream->writeInt(mUsedComputeImageRange);
1141 stream->writeInt(mUsedComputeReadonlyImageRange);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001142
Jamie Madill62d31cb2015-09-11 13:25:51 -04001143 stream->writeInt(mD3DUniforms.size());
Jamie Madill4a3c2342015-10-08 12:58:45 -04001144 for (const D3DUniform *uniform : mD3DUniforms)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001145 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001146 // Type, name and arraySize are redundant, so aren't stored in the binary.
Xinghua Cao26143fd2017-11-01 18:19:05 +08001147 stream->writeInt(static_cast<unsigned int>(uniform->regType));
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08001148 for (gl::ShaderType shaderType : gl::AllShaderTypes())
1149 {
1150 stream->writeIntOrNegOne(uniform->mShaderRegisterIndexes[shaderType]);
1151 }
Jamie Madill4a3c2342015-10-08 12:58:45 -04001152 stream->writeInt(uniform->registerCount);
1153 stream->writeInt(uniform->registerElement);
1154 }
1155
1156 stream->writeInt(mD3DUniformBlocks.size());
1157 for (const D3DUniformBlock &uniformBlock : mD3DUniformBlocks)
1158 {
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08001159 for (gl::ShaderType shaderType : gl::AllShaderTypes())
1160 {
1161 stream->writeIntOrNegOne(uniformBlock.mShaderRegisterIndexes[shaderType]);
1162 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001163 }
1164
Jamie Madill9fc36822015-11-18 13:08:07 -05001165 stream->writeInt(mStreamOutVaryings.size());
1166 for (const auto &varying : mStreamOutVaryings)
Brandon Joneseb994362014-09-24 10:27:28 -07001167 {
Brandon Joneseb994362014-09-24 10:27:28 -07001168 stream->writeString(varying.semanticName);
1169 stream->writeInt(varying.semanticIndex);
Jamie Madill9fc36822015-11-18 13:08:07 -05001170 stream->writeInt(varying.componentCount);
1171 stream->writeInt(varying.outputSlot);
Brandon Joneseb994362014-09-24 10:27:28 -07001172 }
1173
Jiawei Shao467c15f2018-04-24 15:04:26 +08001174 for (gl::ShaderType shaderType : gl::AllShaderTypes())
1175 {
1176 stream->writeString(mShaderHLSL[shaderType]);
1177 stream->writeBytes(reinterpret_cast<unsigned char *>(&mShaderWorkarounds[shaderType]),
1178 sizeof(angle::CompilerWorkaroundsD3D));
1179 }
1180
Brandon Jones22502d52014-08-29 16:58:36 -07001181 stream->writeInt(mUsesFragDepth);
Martin Radev41ac68e2017-06-06 12:16:58 +03001182 stream->writeInt(mHasANGLEMultiviewEnabled);
1183 stream->writeInt(mUsesViewID);
Brandon Jones44151a92014-09-10 11:32:25 -07001184 stream->writeInt(mUsesPointSize);
Jamie Madill3e14e2b2015-10-29 14:38:53 -04001185 stream->writeInt(mUsesFlatInterpolation);
Brandon Jones22502d52014-08-29 16:58:36 -07001186
Brandon Joneseb994362014-09-24 10:27:28 -07001187 const std::vector<PixelShaderOutputVariable> &pixelShaderKey = mPixelShaderKey;
Brandon Jones22502d52014-08-29 16:58:36 -07001188 stream->writeInt(pixelShaderKey.size());
Jamie Madill334d6152015-10-22 14:00:28 -04001189 for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKey.size();
1190 pixelShaderKeyIndex++)
Brandon Jones22502d52014-08-29 16:58:36 -07001191 {
Brandon Joneseb994362014-09-24 10:27:28 -07001192 const PixelShaderOutputVariable &variable = pixelShaderKey[pixelShaderKeyIndex];
Brandon Jones22502d52014-08-29 16:58:36 -07001193 stream->writeInt(variable.type);
1194 stream->writeString(variable.name);
1195 stream->writeString(variable.source);
1196 stream->writeInt(variable.outputIndex);
1197 }
1198
Jamie Madill4e31ad52015-10-29 10:32:57 -04001199 stream->writeString(mGeometryShaderPreamble);
1200
Brandon Joneseb994362014-09-24 10:27:28 -07001201 stream->writeInt(mVertexExecutables.size());
Jamie Madill334d6152015-10-22 14:00:28 -04001202 for (size_t vertexExecutableIndex = 0; vertexExecutableIndex < mVertexExecutables.size();
1203 vertexExecutableIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -07001204 {
Xinghua Caob1239382016-12-13 15:07:05 +08001205 VertexExecutable *vertexExecutable = mVertexExecutables[vertexExecutableIndex].get();
Brandon Joneseb994362014-09-24 10:27:28 -07001206
Jamie Madilld3dfda22015-07-06 08:28:49 -04001207 const auto &inputLayout = vertexExecutable->inputs();
1208 stream->writeInt(inputLayout.size());
1209
1210 for (size_t inputIndex = 0; inputIndex < inputLayout.size(); inputIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -07001211 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001212 stream->writeInt(static_cast<unsigned int>(inputLayout[inputIndex]));
Brandon Joneseb994362014-09-24 10:27:28 -07001213 }
1214
1215 size_t vertexShaderSize = vertexExecutable->shaderExecutable()->getLength();
1216 stream->writeInt(vertexShaderSize);
1217
1218 const uint8_t *vertexBlob = vertexExecutable->shaderExecutable()->getFunction();
1219 stream->writeBytes(vertexBlob, vertexShaderSize);
1220 }
1221
1222 stream->writeInt(mPixelExecutables.size());
Jamie Madill334d6152015-10-22 14:00:28 -04001223 for (size_t pixelExecutableIndex = 0; pixelExecutableIndex < mPixelExecutables.size();
1224 pixelExecutableIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -07001225 {
Xinghua Caob1239382016-12-13 15:07:05 +08001226 PixelExecutable *pixelExecutable = mPixelExecutables[pixelExecutableIndex].get();
Brandon Joneseb994362014-09-24 10:27:28 -07001227
1228 const std::vector<GLenum> outputs = pixelExecutable->outputSignature();
1229 stream->writeInt(outputs.size());
1230 for (size_t outputIndex = 0; outputIndex < outputs.size(); outputIndex++)
1231 {
1232 stream->writeInt(outputs[outputIndex]);
1233 }
1234
1235 size_t pixelShaderSize = pixelExecutable->shaderExecutable()->getLength();
1236 stream->writeInt(pixelShaderSize);
1237
1238 const uint8_t *pixelBlob = pixelExecutable->shaderExecutable()->getFunction();
1239 stream->writeBytes(pixelBlob, pixelShaderSize);
1240 }
1241
Xinghua Caob1239382016-12-13 15:07:05 +08001242 for (auto const &geometryExecutable : mGeometryExecutables)
Brandon Joneseb994362014-09-24 10:27:28 -07001243 {
Xinghua Caob1239382016-12-13 15:07:05 +08001244 if (!geometryExecutable)
Jamie Madill4e31ad52015-10-29 10:32:57 -04001245 {
1246 stream->writeInt(0);
1247 continue;
1248 }
1249
Xinghua Caob1239382016-12-13 15:07:05 +08001250 size_t geometryShaderSize = geometryExecutable->getLength();
Jamie Madill4e31ad52015-10-29 10:32:57 -04001251 stream->writeInt(geometryShaderSize);
Xinghua Caob1239382016-12-13 15:07:05 +08001252 stream->writeBytes(geometryExecutable->getFunction(), geometryShaderSize);
1253 }
1254
1255 if (mComputeExecutable)
1256 {
1257 size_t computeShaderSize = mComputeExecutable->getLength();
1258 stream->writeInt(computeShaderSize);
1259 stream->writeBytes(mComputeExecutable->getFunction(), computeShaderSize);
1260 }
1261 else
1262 {
1263 stream->writeInt(0);
Brandon Joneseb994362014-09-24 10:27:28 -07001264 }
Brandon Jones22502d52014-08-29 16:58:36 -07001265}
1266
Geoff Langc5629752015-12-07 16:29:04 -05001267void ProgramD3D::setBinaryRetrievableHint(bool /* retrievable */)
1268{
1269}
1270
Yunchao He61afff12017-03-14 15:34:03 +08001271void ProgramD3D::setSeparable(bool /* separable */)
1272{
1273}
1274
Jamie Madill4c19a8a2017-07-24 11:46:06 -04001275gl::Error ProgramD3D::getPixelExecutableForCachedOutputLayout(ShaderExecutableD3D **outExecutable,
1276 gl::InfoLog *infoLog)
Brandon Joneseb994362014-09-24 10:27:28 -07001277{
Jamie Madill0e7f1732017-09-09 23:32:50 -04001278 if (mCachedPixelExecutableIndex.valid())
Brandon Joneseb994362014-09-24 10:27:28 -07001279 {
Jamie Madill0e7f1732017-09-09 23:32:50 -04001280 *outExecutable = mPixelExecutables[mCachedPixelExecutableIndex.value()]->shaderExecutable();
1281 return gl::NoError();
Brandon Joneseb994362014-09-24 10:27:28 -07001282 }
1283
Jamie Madill334d6152015-10-22 14:00:28 -04001284 std::string finalPixelHLSL = mDynamicHLSL->generatePixelShaderForOutputSignature(
Jiawei Shao467c15f2018-04-24 15:04:26 +08001285 mShaderHLSL[gl::ShaderType::Fragment], mPixelShaderKey, mUsesFragDepth,
1286 mPixelShaderOutputLayoutCache);
Brandon Jones22502d52014-08-29 16:58:36 -07001287
1288 // Generate new pixel executable
Yunchao Hed7297bf2017-04-19 15:27:10 +08001289 ShaderExecutableD3D *pixelExecutable = nullptr;
Jamie Madill97399232014-12-23 12:31:15 -05001290
1291 gl::InfoLog tempInfoLog;
1292 gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
1293
Jamie Madill01074252016-11-28 15:55:51 -05001294 ANGLE_TRY(mRenderer->compileToExecutable(
Jiawei Shao385b3e02018-03-21 09:43:28 +08001295 *currentInfoLog, finalPixelHLSL, gl::ShaderType::Fragment, mStreamOutVaryings,
Jiawei Shao467c15f2018-04-24 15:04:26 +08001296 (mState.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS),
1297 mShaderWorkarounds[gl::ShaderType::Fragment], &pixelExecutable));
Brandon Joneseb994362014-09-24 10:27:28 -07001298
Jamie Madill97399232014-12-23 12:31:15 -05001299 if (pixelExecutable)
1300 {
Xinghua Caob1239382016-12-13 15:07:05 +08001301 mPixelExecutables.push_back(std::unique_ptr<PixelExecutable>(
Jamie Madill4c19a8a2017-07-24 11:46:06 -04001302 new PixelExecutable(mPixelShaderOutputLayoutCache, pixelExecutable)));
Jamie Madill0e7f1732017-09-09 23:32:50 -04001303 mCachedPixelExecutableIndex = mPixelExecutables.size() - 1;
Jamie Madill97399232014-12-23 12:31:15 -05001304 }
1305 else if (!infoLog)
Brandon Joneseb994362014-09-24 10:27:28 -07001306 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05001307 ERR() << "Error compiling dynamic pixel executable:" << std::endl
1308 << tempInfoLog.str() << std::endl;
Brandon Joneseb994362014-09-24 10:27:28 -07001309 }
Brandon Jones22502d52014-08-29 16:58:36 -07001310
Jamie Madill4c19a8a2017-07-24 11:46:06 -04001311 *outExecutable = pixelExecutable;
Jamie Madill01074252016-11-28 15:55:51 -05001312 return gl::NoError();
Brandon Jones22502d52014-08-29 16:58:36 -07001313}
1314
Jamie Madill4c19a8a2017-07-24 11:46:06 -04001315gl::Error ProgramD3D::getVertexExecutableForCachedInputLayout(ShaderExecutableD3D **outExectuable,
1316 gl::InfoLog *infoLog)
Brandon Jones22502d52014-08-29 16:58:36 -07001317{
Jamie Madill0e7f1732017-09-09 23:32:50 -04001318 if (mCachedVertexExecutableIndex.valid())
Brandon Joneseb994362014-09-24 10:27:28 -07001319 {
Jamie Madill0e7f1732017-09-09 23:32:50 -04001320 *outExectuable =
1321 mVertexExecutables[mCachedVertexExecutableIndex.value()]->shaderExecutable();
1322 return gl::NoError();
Brandon Joneseb994362014-09-24 10:27:28 -07001323 }
1324
Brandon Jones22502d52014-08-29 16:58:36 -07001325 // Generate new dynamic layout with attribute conversions
Jamie Madillc349ec02015-08-21 16:53:12 -04001326 std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout(
Jiawei Shao467c15f2018-04-24 15:04:26 +08001327 mShaderHLSL[gl::ShaderType::Vertex], mCachedInputLayout, mState.getAttributes());
Brandon Jones22502d52014-08-29 16:58:36 -07001328
1329 // Generate new vertex executable
Yunchao Hed7297bf2017-04-19 15:27:10 +08001330 ShaderExecutableD3D *vertexExecutable = nullptr;
Jamie Madill97399232014-12-23 12:31:15 -05001331
1332 gl::InfoLog tempInfoLog;
1333 gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
1334
Jamie Madill01074252016-11-28 15:55:51 -05001335 ANGLE_TRY(mRenderer->compileToExecutable(
Jiawei Shao385b3e02018-03-21 09:43:28 +08001336 *currentInfoLog, finalVertexHLSL, gl::ShaderType::Vertex, mStreamOutVaryings,
Jiawei Shao467c15f2018-04-24 15:04:26 +08001337 (mState.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS),
1338 mShaderWorkarounds[gl::ShaderType::Vertex], &vertexExecutable));
Geoff Langb543aff2014-09-30 14:52:54 -04001339
Jamie Madill97399232014-12-23 12:31:15 -05001340 if (vertexExecutable)
Brandon Joneseb994362014-09-24 10:27:28 -07001341 {
Xinghua Caob1239382016-12-13 15:07:05 +08001342 mVertexExecutables.push_back(std::unique_ptr<VertexExecutable>(
Jamie Madill4c19a8a2017-07-24 11:46:06 -04001343 new VertexExecutable(mCachedInputLayout, mCachedVertexSignature, vertexExecutable)));
Jamie Madill0e7f1732017-09-09 23:32:50 -04001344 mCachedVertexExecutableIndex = mVertexExecutables.size() - 1;
Brandon Joneseb994362014-09-24 10:27:28 -07001345 }
Jamie Madill97399232014-12-23 12:31:15 -05001346 else if (!infoLog)
1347 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05001348 ERR() << "Error compiling dynamic vertex executable:" << std::endl
1349 << tempInfoLog.str() << std::endl;
Jamie Madill97399232014-12-23 12:31:15 -05001350 }
Brandon Jones22502d52014-08-29 16:58:36 -07001351
Geoff Langb543aff2014-09-30 14:52:54 -04001352 *outExectuable = vertexExecutable;
Jamie Madill01074252016-11-28 15:55:51 -05001353 return gl::NoError();
Brandon Jones22502d52014-08-29 16:58:36 -07001354}
1355
Jamie Madillc9fed8d2017-09-12 15:23:00 -04001356gl::Error ProgramD3D::getGeometryExecutableForPrimitiveType(const gl::Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04001357 gl::PrimitiveMode drawMode,
Jamie Madill4e31ad52015-10-29 10:32:57 -04001358 ShaderExecutableD3D **outExecutable,
1359 gl::InfoLog *infoLog)
1360{
Jamie Madill3e14e2b2015-10-29 14:38:53 -04001361 if (outExecutable)
1362 {
1363 *outExecutable = nullptr;
1364 }
1365
Austin Kinross88829e82016-01-12 13:04:41 -08001366 // Return a null shader if the current rendering doesn't use a geometry shader
1367 if (!usesGeometryShader(drawMode))
Jamie Madill3e14e2b2015-10-29 14:38:53 -04001368 {
Jamie Madill51f522f2016-12-21 15:10:55 -05001369 return gl::NoError();
Jamie Madill3e14e2b2015-10-29 14:38:53 -04001370 }
1371
Jamie Madill04796cd2018-05-24 19:52:16 -04001372 gl::PrimitiveMode geometryShaderType = GetGeometryShaderTypeFromDrawMode(drawMode);
Jamie Madill4e31ad52015-10-29 10:32:57 -04001373
Xinghua Caob1239382016-12-13 15:07:05 +08001374 if (mGeometryExecutables[geometryShaderType])
Jamie Madill4e31ad52015-10-29 10:32:57 -04001375 {
1376 if (outExecutable)
1377 {
Xinghua Caob1239382016-12-13 15:07:05 +08001378 *outExecutable = mGeometryExecutables[geometryShaderType].get();
Jamie Madill4e31ad52015-10-29 10:32:57 -04001379 }
Jamie Madill51f522f2016-12-21 15:10:55 -05001380 return gl::NoError();
Jamie Madill4e31ad52015-10-29 10:32:57 -04001381 }
1382
1383 std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL(
Jamie Madillc9fed8d2017-09-12 15:23:00 -04001384 context, geometryShaderType, mState, mRenderer->presentPathFastEnabled(),
Martin Radevc1d4e552017-08-21 12:01:10 +03001385 mHasANGLEMultiviewEnabled, mRenderer->canSelectViewInVertexShader(),
1386 usesGeometryShaderForPointSpriteEmulation(), mGeometryShaderPreamble);
Jamie Madill4e31ad52015-10-29 10:32:57 -04001387
1388 gl::InfoLog tempInfoLog;
1389 gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
1390
Xinghua Caob1239382016-12-13 15:07:05 +08001391 ShaderExecutableD3D *geometryExecutable = nullptr;
1392 gl::Error error = mRenderer->compileToExecutable(
Jiawei Shao385b3e02018-03-21 09:43:28 +08001393 *currentInfoLog, geometryHLSL, gl::ShaderType::Geometry, mStreamOutVaryings,
Jamie Madill408293f2016-12-20 10:11:45 -05001394 (mState.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS),
Xinghua Caob1239382016-12-13 15:07:05 +08001395 angle::CompilerWorkaroundsD3D(), &geometryExecutable);
Jamie Madill4e31ad52015-10-29 10:32:57 -04001396
1397 if (!infoLog && error.isError())
1398 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05001399 ERR() << "Error compiling dynamic geometry executable:" << std::endl
1400 << tempInfoLog.str() << std::endl;
Jamie Madill4e31ad52015-10-29 10:32:57 -04001401 }
1402
Xinghua Caob1239382016-12-13 15:07:05 +08001403 if (geometryExecutable != nullptr)
1404 {
1405 mGeometryExecutables[geometryShaderType].reset(geometryExecutable);
1406 }
1407
Jamie Madill4e31ad52015-10-29 10:32:57 -04001408 if (outExecutable)
1409 {
Xinghua Caob1239382016-12-13 15:07:05 +08001410 *outExecutable = mGeometryExecutables[geometryShaderType].get();
Jamie Madill4e31ad52015-10-29 10:32:57 -04001411 }
1412 return error;
1413}
1414
Jamie Madill01074252016-11-28 15:55:51 -05001415class ProgramD3D::GetExecutableTask : public Closure
Brandon Jones44151a92014-09-10 11:32:25 -07001416{
Jamie Madill01074252016-11-28 15:55:51 -05001417 public:
1418 GetExecutableTask(ProgramD3D *program)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001419 : mProgram(program), mError(gl::NoError()), mInfoLog(), mResult(nullptr)
Brandon Joneseb994362014-09-24 10:27:28 -07001420 {
Brandon Joneseb994362014-09-24 10:27:28 -07001421 }
1422
Jamie Madill01074252016-11-28 15:55:51 -05001423 virtual gl::Error run() = 0;
1424
1425 void operator()() override { mError = run(); }
1426
1427 const gl::Error &getError() const { return mError; }
1428 const gl::InfoLog &getInfoLog() const { return mInfoLog; }
1429 ShaderExecutableD3D *getResult() { return mResult; }
1430
1431 protected:
1432 ProgramD3D *mProgram;
1433 gl::Error mError;
1434 gl::InfoLog mInfoLog;
1435 ShaderExecutableD3D *mResult;
1436};
1437
1438class ProgramD3D::GetVertexExecutableTask : public ProgramD3D::GetExecutableTask
1439{
1440 public:
Jamie Madillbd044ed2017-06-05 12:59:21 -04001441 GetVertexExecutableTask(ProgramD3D *program, const gl::Context *context)
1442 : GetExecutableTask(program), mContext(context)
1443 {
1444 }
Jamie Madill01074252016-11-28 15:55:51 -05001445 gl::Error run() override
1446 {
Jamie Madill4c19a8a2017-07-24 11:46:06 -04001447 mProgram->updateCachedInputLayoutFromShader(mContext);
Jamie Madill01074252016-11-28 15:55:51 -05001448
Jamie Madill4c19a8a2017-07-24 11:46:06 -04001449 ANGLE_TRY(mProgram->getVertexExecutableForCachedInputLayout(&mResult, &mInfoLog));
Jamie Madill01074252016-11-28 15:55:51 -05001450
1451 return gl::NoError();
1452 }
Jamie Madillbd044ed2017-06-05 12:59:21 -04001453
1454 private:
1455 const gl::Context *mContext;
Jamie Madill01074252016-11-28 15:55:51 -05001456};
1457
Jamie Madill4c19a8a2017-07-24 11:46:06 -04001458void ProgramD3D::updateCachedInputLayoutFromShader(const gl::Context *context)
1459{
Jiawei Shao385b3e02018-03-21 09:43:28 +08001460 GetDefaultInputLayoutFromShader(context, mState.getAttachedShader(gl::ShaderType::Vertex),
1461 &mCachedInputLayout);
Jamie Madill4c19a8a2017-07-24 11:46:06 -04001462 VertexExecutable::getSignature(mRenderer, mCachedInputLayout, &mCachedVertexSignature);
Jamie Madill0e7f1732017-09-09 23:32:50 -04001463 updateCachedVertexExecutableIndex();
Jamie Madill4c19a8a2017-07-24 11:46:06 -04001464}
1465
Jamie Madill01074252016-11-28 15:55:51 -05001466class ProgramD3D::GetPixelExecutableTask : public ProgramD3D::GetExecutableTask
1467{
1468 public:
1469 GetPixelExecutableTask(ProgramD3D *program) : GetExecutableTask(program) {}
1470 gl::Error run() override
1471 {
Jamie Madill4c19a8a2017-07-24 11:46:06 -04001472 mProgram->updateCachedOutputLayoutFromShader();
Jamie Madill01074252016-11-28 15:55:51 -05001473
Jamie Madill4c19a8a2017-07-24 11:46:06 -04001474 ANGLE_TRY(mProgram->getPixelExecutableForCachedOutputLayout(&mResult, &mInfoLog));
Jamie Madill01074252016-11-28 15:55:51 -05001475
1476 return gl::NoError();
1477 }
1478};
1479
Jamie Madill4c19a8a2017-07-24 11:46:06 -04001480void ProgramD3D::updateCachedOutputLayoutFromShader()
1481{
1482 GetDefaultOutputLayoutFromShader(mPixelShaderKey, &mPixelShaderOutputLayoutCache);
Jamie Madill0e7f1732017-09-09 23:32:50 -04001483 updateCachedPixelExecutableIndex();
Jamie Madill4c19a8a2017-07-24 11:46:06 -04001484}
1485
Jamie Madill01074252016-11-28 15:55:51 -05001486class ProgramD3D::GetGeometryExecutableTask : public ProgramD3D::GetExecutableTask
1487{
1488 public:
Jamie Madillc9fed8d2017-09-12 15:23:00 -04001489 GetGeometryExecutableTask(ProgramD3D *program, const gl::Context *context)
1490 : GetExecutableTask(program), mContext(context)
Jamie Madill01074252016-11-28 15:55:51 -05001491 {
1492 }
1493
1494 gl::Error run() override
1495 {
1496 // Auto-generate the geometry shader here, if we expect to be using point rendering in
1497 // D3D11.
Jamie Madill493f9572018-05-24 19:52:15 -04001498 if (mProgram->usesGeometryShader(gl::PrimitiveMode::Points))
Jamie Madill01074252016-11-28 15:55:51 -05001499 {
Jamie Madill493f9572018-05-24 19:52:15 -04001500 ANGLE_TRY(mProgram->getGeometryExecutableForPrimitiveType(
1501 mContext, gl::PrimitiveMode::Points, &mResult, &mInfoLog));
Jamie Madill01074252016-11-28 15:55:51 -05001502 }
1503
1504 return gl::NoError();
1505 }
1506
1507 private:
Jamie Madillc9fed8d2017-09-12 15:23:00 -04001508 const gl::Context *mContext;
Jamie Madill01074252016-11-28 15:55:51 -05001509};
1510
Xinghua Cao73badc02017-03-29 19:14:53 +08001511gl::Error ProgramD3D::getComputeExecutable(ShaderExecutableD3D **outExecutable)
1512{
1513 if (outExecutable)
1514 {
1515 *outExecutable = mComputeExecutable.get();
1516 }
1517
1518 return gl::NoError();
1519}
1520
Jamie Madill9cf9e872017-06-05 12:59:25 -04001521gl::LinkResult ProgramD3D::compileProgramExecutables(const gl::Context *context,
1522 gl::InfoLog &infoLog)
Jamie Madill01074252016-11-28 15:55:51 -05001523{
1524 // Ensure the compiler is initialized to avoid race conditions.
1525 ANGLE_TRY(mRenderer->ensureHLSLCompilerInitialized());
1526
1527 WorkerThreadPool *workerPool = mRenderer->getWorkerThreadPool();
1528
Jamie Madillbd044ed2017-06-05 12:59:21 -04001529 GetVertexExecutableTask vertexTask(this, context);
Jamie Madill01074252016-11-28 15:55:51 -05001530 GetPixelExecutableTask pixelTask(this);
Jamie Madillc9fed8d2017-09-12 15:23:00 -04001531 GetGeometryExecutableTask geometryTask(this, context);
Jamie Madill01074252016-11-28 15:55:51 -05001532
1533 std::array<WaitableEvent, 3> waitEvents = {{workerPool->postWorkerTask(&vertexTask),
1534 workerPool->postWorkerTask(&pixelTask),
1535 workerPool->postWorkerTask(&geometryTask)}};
1536
1537 WaitableEvent::WaitMany(&waitEvents);
1538
Jiawei Shao02f15232017-12-27 10:10:28 +08001539 if (!vertexTask.getInfoLog().empty())
1540 {
1541 infoLog << vertexTask.getInfoLog().str();
1542 }
1543 if (!pixelTask.getInfoLog().empty())
1544 {
1545 infoLog << pixelTask.getInfoLog().str();
1546 }
1547 if (!geometryTask.getInfoLog().empty())
1548 {
1549 infoLog << geometryTask.getInfoLog().str();
1550 }
Jamie Madill01074252016-11-28 15:55:51 -05001551
1552 ANGLE_TRY(vertexTask.getError());
1553 ANGLE_TRY(pixelTask.getError());
1554 ANGLE_TRY(geometryTask.getError());
1555
1556 ShaderExecutableD3D *defaultVertexExecutable = vertexTask.getResult();
1557 ShaderExecutableD3D *defaultPixelExecutable = pixelTask.getResult();
1558 ShaderExecutableD3D *pointGS = geometryTask.getResult();
1559
Jiawei Shao385b3e02018-03-21 09:43:28 +08001560 const ShaderD3D *vertexShaderD3D =
1561 GetImplAs<ShaderD3D>(mState.getAttachedShader(gl::ShaderType::Vertex));
Jamie Madill847638a2015-11-20 13:01:41 -05001562
Jamie Madill493f9572018-05-24 19:52:15 -04001563 if (usesGeometryShader(gl::PrimitiveMode::Points) && pointGS)
Tibor den Ouden97049c62014-10-06 21:39:16 +02001564 {
Jamie Madill334d6152015-10-22 14:00:28 -04001565 // Geometry shaders are currently only used internally, so there is no corresponding shader
1566 // object at the interface level. For now the geometry shader debug info is prepended to
1567 // the vertex shader.
Tibor den Ouden97049c62014-10-06 21:39:16 +02001568 vertexShaderD3D->appendDebugInfo("// GEOMETRY SHADER BEGIN\n\n");
Jamie Madill847638a2015-11-20 13:01:41 -05001569 vertexShaderD3D->appendDebugInfo(pointGS->getDebugInfo());
Tibor den Ouden97049c62014-10-06 21:39:16 +02001570 vertexShaderD3D->appendDebugInfo("\nGEOMETRY SHADER END\n\n\n");
1571 }
1572
1573 if (defaultVertexExecutable)
1574 {
1575 vertexShaderD3D->appendDebugInfo(defaultVertexExecutable->getDebugInfo());
1576 }
1577
1578 if (defaultPixelExecutable)
1579 {
Jamie Madill76f8fa62015-10-29 10:32:56 -04001580 const ShaderD3D *fragmentShaderD3D =
Jiawei Shao385b3e02018-03-21 09:43:28 +08001581 GetImplAs<ShaderD3D>(mState.getAttachedShader(gl::ShaderType::Fragment));
Tibor den Ouden97049c62014-10-06 21:39:16 +02001582 fragmentShaderD3D->appendDebugInfo(defaultPixelExecutable->getDebugInfo());
1583 }
Tibor den Ouden97049c62014-10-06 21:39:16 +02001584
Jamie Madillb0a838b2016-11-13 20:02:12 -05001585 return (defaultVertexExecutable && defaultPixelExecutable &&
Jamie Madill493f9572018-05-24 19:52:15 -04001586 (!usesGeometryShader(gl::PrimitiveMode::Points) || pointGS));
Brandon Jones18bd4102014-09-22 14:21:44 -07001587}
1588
Jamie Madill9cf9e872017-06-05 12:59:25 -04001589gl::LinkResult ProgramD3D::compileComputeExecutable(const gl::Context *context,
1590 gl::InfoLog &infoLog)
Xinghua Caob1239382016-12-13 15:07:05 +08001591{
1592 // Ensure the compiler is initialized to avoid race conditions.
1593 ANGLE_TRY(mRenderer->ensureHLSLCompilerInitialized());
1594
Jamie Madillbd044ed2017-06-05 12:59:21 -04001595 std::string computeShader = mDynamicHLSL->generateComputeShaderLinkHLSL(context, mState);
Xinghua Caob1239382016-12-13 15:07:05 +08001596
1597 ShaderExecutableD3D *computeExecutable = nullptr;
Jiawei Shao385b3e02018-03-21 09:43:28 +08001598 ANGLE_TRY(mRenderer->compileToExecutable(infoLog, computeShader, gl::ShaderType::Compute,
Xinghua Caob1239382016-12-13 15:07:05 +08001599 std::vector<D3DVarying>(), false,
1600 angle::CompilerWorkaroundsD3D(), &computeExecutable));
1601
1602 if (computeExecutable == nullptr)
1603 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05001604 ERR() << "Error compiling dynamic compute executable:" << std::endl
1605 << infoLog.str() << std::endl;
Xinghua Caob1239382016-12-13 15:07:05 +08001606 }
1607 else
1608 {
Jiawei Shao385b3e02018-03-21 09:43:28 +08001609 const ShaderD3D *computeShaderD3D =
1610 GetImplAs<ShaderD3D>(mState.getAttachedShader(gl::ShaderType::Compute));
Xinghua Caob1239382016-12-13 15:07:05 +08001611 computeShaderD3D->appendDebugInfo(computeExecutable->getDebugInfo());
1612 mComputeExecutable.reset(computeExecutable);
1613 }
1614
1615 return mComputeExecutable.get() != nullptr;
1616}
1617
Jamie Madill9cf9e872017-06-05 12:59:25 -04001618gl::LinkResult ProgramD3D::link(const gl::Context *context,
Jamie Madillc9727f32017-11-07 12:37:07 -05001619 const gl::ProgramLinkedResources &resources,
Jamie Madill9cf9e872017-06-05 12:59:25 -04001620 gl::InfoLog &infoLog)
Brandon Jones22502d52014-08-29 16:58:36 -07001621{
Jamie Madillc564c072017-06-01 12:45:42 -04001622 const auto &data = context->getContextState();
Jamie Madill8ecf7f92017-01-13 17:29:52 -05001623
Jamie Madill62d31cb2015-09-11 13:25:51 -04001624 reset();
1625
Jiawei Shao385b3e02018-03-21 09:43:28 +08001626 gl::Shader *computeShader = mState.getAttachedShader(gl::ShaderType::Compute);
Xinghua Caob1239382016-12-13 15:07:05 +08001627 if (computeShader)
Austin Kinross02df7962015-07-01 10:03:42 -07001628 {
Jiawei Shao54aafe52018-04-27 14:54:57 +08001629 mShaderSamplers[gl::ShaderType::Compute].resize(
1630 data.getCaps().maxShaderTextureImageUnits[gl::ShaderType::Compute]);
Xinghua Cao26143fd2017-11-01 18:19:05 +08001631 mImagesCS.resize(data.getCaps().maxImageUnits);
1632 mReadonlyImagesCS.resize(data.getCaps().maxImageUnits);
Xinghua Caob1239382016-12-13 15:07:05 +08001633
Jiawei Shao3dd8d2912018-03-30 09:39:09 +08001634 mShaderUniformsDirty.set(gl::ShaderType::Compute);
Jamie Madillbd044ed2017-06-05 12:59:21 -04001635 defineUniformsAndAssignRegisters(context);
Xinghua Caob1239382016-12-13 15:07:05 +08001636
Jamie Madill9cf9e872017-06-05 12:59:25 -04001637 gl::LinkResult result = compileComputeExecutable(context, infoLog);
Xinghua Caob1239382016-12-13 15:07:05 +08001638 if (result.isError())
Austin Kinross02df7962015-07-01 10:03:42 -07001639 {
Xinghua Caob1239382016-12-13 15:07:05 +08001640 infoLog << result.getError().getMessage();
1641 return result;
1642 }
1643 else if (!result.getResult())
1644 {
1645 infoLog << "Failed to create D3D compute shader.";
1646 return result;
1647 }
Xinghua Caob1239382016-12-13 15:07:05 +08001648 }
1649 else
1650 {
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08001651 gl::ShaderMap<const ShaderD3D *> shadersD3D = {};
Jiawei Shao467c15f2018-04-24 15:04:26 +08001652 for (gl::ShaderType shaderType : gl::kAllGraphicsShaderTypes)
1653 {
1654 if (mState.getAttachedShader(shaderType))
1655 {
1656 shadersD3D[shaderType] = GetImplAs<ShaderD3D>(mState.getAttachedShader(shaderType));
Xinghua Caob1239382016-12-13 15:07:05 +08001657
Jiawei Shao467c15f2018-04-24 15:04:26 +08001658 mShaderSamplers[shaderType].resize(
Jiawei Shao54aafe52018-04-27 14:54:57 +08001659 data.getCaps().maxShaderTextureImageUnits[shaderType]);
Xinghua Caob1239382016-12-13 15:07:05 +08001660
Jiawei Shao467c15f2018-04-24 15:04:26 +08001661 shadersD3D[shaderType]->generateWorkarounds(&mShaderWorkarounds[shaderType]);
1662
1663 mShaderUniformsDirty.set(shaderType);
1664 }
1665 }
Xinghua Caob1239382016-12-13 15:07:05 +08001666
1667 if (mRenderer->getNativeLimitations().noFrontFacingSupport)
1668 {
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08001669 if (shadersD3D[gl::ShaderType::Fragment]->usesFrontFacing())
Xinghua Caob1239382016-12-13 15:07:05 +08001670 {
1671 infoLog << "The current renderer doesn't support gl_FrontFacing";
1672 return false;
1673 }
1674 }
1675
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08001676 ProgramD3DMetadata metadata(mRenderer, shadersD3D);
Jamie Madillc9727f32017-11-07 12:37:07 -05001677 BuiltinVaryingsD3D builtins(metadata, resources.varyingPacking);
Xinghua Caob1239382016-12-13 15:07:05 +08001678
Jamie Madillc9727f32017-11-07 12:37:07 -05001679 mDynamicHLSL->generateShaderLinkHLSL(context, mState, metadata, resources.varyingPacking,
Jiawei Shao467c15f2018-04-24 15:04:26 +08001680 builtins, &mShaderHLSL);
Xinghua Caob1239382016-12-13 15:07:05 +08001681
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08001682 mUsesPointSize = shadersD3D[gl::ShaderType::Vertex]->usesPointSize();
Xinghua Caob1239382016-12-13 15:07:05 +08001683 mDynamicHLSL->getPixelShaderOutputKey(data, mState, metadata, &mPixelShaderKey);
Xinghua Cao26143fd2017-11-01 18:19:05 +08001684 mUsesFragDepth = metadata.usesFragDepth();
Martin Radev41ac68e2017-06-06 12:16:58 +03001685 mUsesViewID = metadata.usesViewID();
1686 mHasANGLEMultiviewEnabled = metadata.hasANGLEMultiviewEnabled();
Xinghua Caob1239382016-12-13 15:07:05 +08001687
1688 // Cache if we use flat shading
Jiawei Shao467c15f2018-04-24 15:04:26 +08001689 mUsesFlatInterpolation = FindFlatInterpolationVarying(context, mState.getAttachedShaders());
Xinghua Caob1239382016-12-13 15:07:05 +08001690
1691 if (mRenderer->getMajorShaderModel() >= 4)
1692 {
Martin Radev41ac68e2017-06-06 12:16:58 +03001693 mGeometryShaderPreamble = mDynamicHLSL->generateGeometryShaderPreamble(
Jamie Madillc9727f32017-11-07 12:37:07 -05001694 resources.varyingPacking, builtins, mHasANGLEMultiviewEnabled,
Martin Radevc1d4e552017-08-21 12:01:10 +03001695 metadata.canSelectViewInVertexShader());
Xinghua Caob1239382016-12-13 15:07:05 +08001696 }
1697
Jamie Madillbd044ed2017-06-05 12:59:21 -04001698 initAttribLocationsToD3DSemantic(context);
Xinghua Caob1239382016-12-13 15:07:05 +08001699
Jamie Madillbd044ed2017-06-05 12:59:21 -04001700 defineUniformsAndAssignRegisters(context);
Xinghua Caob1239382016-12-13 15:07:05 +08001701
Jiawei Shao385b3e02018-03-21 09:43:28 +08001702 gatherTransformFeedbackVaryings(resources.varyingPacking, builtins[gl::ShaderType::Vertex]);
Xinghua Caob1239382016-12-13 15:07:05 +08001703
Jamie Madill9cf9e872017-06-05 12:59:25 -04001704 gl::LinkResult result = compileProgramExecutables(context, infoLog);
Xinghua Caob1239382016-12-13 15:07:05 +08001705 if (result.isError())
1706 {
1707 infoLog << result.getError().getMessage();
1708 return result;
1709 }
1710 else if (!result.getResult())
1711 {
1712 infoLog << "Failed to create D3D shaders.";
1713 return result;
1714 }
Austin Kinross02df7962015-07-01 10:03:42 -07001715 }
1716
Jamie Madill6db1c2e2017-11-08 09:17:40 -05001717 linkResources(context, resources);
1718
Jamie Madillb0a838b2016-11-13 20:02:12 -05001719 return true;
Brandon Jones22502d52014-08-29 16:58:36 -07001720}
1721
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001722GLboolean ProgramD3D::validate(const gl::Caps & /*caps*/, gl::InfoLog * /*infoLog*/)
Jamie Madill36cfd6a2015-08-18 10:46:20 -04001723{
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001724 // TODO(jmadill): Do something useful here?
1725 return GL_TRUE;
Jamie Madill36cfd6a2015-08-18 10:46:20 -04001726}
1727
Jamie Madill6db1c2e2017-11-08 09:17:40 -05001728void ProgramD3D::initializeUniformBlocks()
Jamie Madill62d31cb2015-09-11 13:25:51 -04001729{
Jamie Madill6db1c2e2017-11-08 09:17:40 -05001730 if (mState.getUniformBlocks().empty())
Jamie Madill51f522f2016-12-21 15:10:55 -05001731 {
1732 return;
1733 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04001734
Jamie Madill6db1c2e2017-11-08 09:17:40 -05001735 ASSERT(mD3DUniformBlocks.empty());
1736
Jamie Madill62d31cb2015-09-11 13:25:51 -04001737 // Assign registers and update sizes.
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08001738 gl::ShaderMap<const ShaderD3D *> shadersD3D = {};
1739 for (gl::ShaderType shaderType : gl::AllShaderTypes())
1740 {
1741 shadersD3D[shaderType] = SafeGetImplAs<ShaderD3D>(mState.getAttachedShader(shaderType));
1742 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04001743
Jiajia Qin729b2c62017-08-14 09:36:11 +08001744 for (const gl::InterfaceBlock &uniformBlock : mState.getUniformBlocks())
Jamie Madill62d31cb2015-09-11 13:25:51 -04001745 {
1746 unsigned int uniformBlockElement = uniformBlock.isArray ? uniformBlock.arrayElement : 0;
1747
Jamie Madill4a3c2342015-10-08 12:58:45 -04001748 D3DUniformBlock d3dUniformBlock;
1749
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08001750 for (gl::ShaderType shaderType : gl::AllShaderTypes())
Jamie Madill62d31cb2015-09-11 13:25:51 -04001751 {
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08001752 if (uniformBlock.isActive(shaderType))
1753 {
1754 ASSERT(shadersD3D[shaderType]);
1755 unsigned int baseRegister =
1756 shadersD3D[shaderType]->getUniformBlockRegister(uniformBlock.name);
1757 d3dUniformBlock.mShaderRegisterIndexes[shaderType] =
1758 baseRegister + uniformBlockElement;
1759 }
Xinghua Caob1239382016-12-13 15:07:05 +08001760 }
1761
Jamie Madill4a3c2342015-10-08 12:58:45 -04001762 mD3DUniformBlocks.push_back(d3dUniformBlock);
Jamie Madill62d31cb2015-09-11 13:25:51 -04001763 }
1764}
1765
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08001766void ProgramD3D::initializeUniformStorage(const gl::ShaderBitSet &availableShaderStages)
Brandon Jonesc9610c52014-08-25 17:02:59 -07001767{
1768 // Compute total default block size
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08001769 gl::ShaderMap<unsigned int> shaderRegisters = {};
Jamie Madill62d31cb2015-09-11 13:25:51 -04001770 for (const D3DUniform *d3dUniform : mD3DUniforms)
Brandon Jonesc9610c52014-08-25 17:02:59 -07001771 {
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08001772 if (d3dUniform->isSampler())
Brandon Jonesc9610c52014-08-25 17:02:59 -07001773 {
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08001774 continue;
1775 }
1776
1777 for (gl::ShaderType shaderType : gl::AllShaderTypes())
1778 {
1779 if (d3dUniform->isReferencedByShader(shaderType))
Brandon Jonesc9610c52014-08-25 17:02:59 -07001780 {
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08001781 ASSERT(availableShaderStages[shaderType]);
1782 shaderRegisters[shaderType] = std::max(
1783 shaderRegisters[shaderType],
1784 d3dUniform->mShaderRegisterIndexes[shaderType] + d3dUniform->registerCount);
Xinghua Caob1239382016-12-13 15:07:05 +08001785 }
Brandon Jonesc9610c52014-08-25 17:02:59 -07001786 }
1787 }
1788
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08001789 // We only reset uniform storages for the shader stages available in the program (attached
1790 // shaders in ProgramD3D::link() and linkedShaderStages in ProgramD3D::load()).
1791 for (gl::ShaderType shaderType : gl::AllShaderTypes())
1792 {
1793 if (availableShaderStages[shaderType])
1794 {
1795 mShaderUniformStorages[shaderType].reset(
1796 mRenderer->createUniformStorage(shaderRegisters[shaderType] * 16u));
1797 }
1798 }
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04001799
1800 // Iterate the uniforms again to assign data pointers to default block uniforms.
1801 for (D3DUniform *d3dUniform : mD3DUniforms)
1802 {
1803 if (d3dUniform->isSampler())
1804 {
Olli Etuaho465835d2017-09-26 13:34:10 +03001805 d3dUniform->mSamplerData.resize(d3dUniform->getArraySizeProduct(), 0);
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04001806 continue;
1807 }
1808
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08001809 for (gl::ShaderType shaderType : gl::AllShaderTypes())
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04001810 {
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08001811 if (d3dUniform->isReferencedByShader(shaderType))
1812 {
1813 d3dUniform->mShaderData[shaderType] =
1814 mShaderUniformStorages[shaderType]->getDataPointer(
1815 d3dUniform->mShaderRegisterIndexes[shaderType],
1816 d3dUniform->registerElement);
1817 }
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04001818 }
1819 }
Brandon Jonesc9610c52014-08-25 17:02:59 -07001820}
1821
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08001822void ProgramD3D::updateUniformBufferCache(
1823 const gl::Caps &caps,
1824 const gl::ShaderMap<unsigned int> &reservedShaderRegisterIndexes)
Brandon Jones18bd4102014-09-22 14:21:44 -07001825{
Jamie Madill48ef11b2016-04-27 15:21:52 -04001826 if (mState.getUniformBlocks().empty())
Jamie Madill4a3c2342015-10-08 12:58:45 -04001827 {
Jamie Madilld63961d2017-09-12 15:22:57 -04001828 return;
Jamie Madill4a3c2342015-10-08 12:58:45 -04001829 }
1830
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08001831 for (gl::ShaderType shaderType : gl::AllShaderTypes())
1832 {
1833 mShaderUBOCaches[shaderType].clear();
1834 }
Brandon Jones18bd4102014-09-22 14:21:44 -07001835
Jamie Madill4a3c2342015-10-08 12:58:45 -04001836 for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < mD3DUniformBlocks.size();
Jamie Madill62d31cb2015-09-11 13:25:51 -04001837 uniformBlockIndex++)
Brandon Jones18bd4102014-09-22 14:21:44 -07001838 {
Jamie Madill4a3c2342015-10-08 12:58:45 -04001839 const D3DUniformBlock &uniformBlock = mD3DUniformBlocks[uniformBlockIndex];
Jamie Madill48ef11b2016-04-27 15:21:52 -04001840 GLuint blockBinding = mState.getUniformBlockBinding(uniformBlockIndex);
Brandon Jones18bd4102014-09-22 14:21:44 -07001841
Brandon Jones18bd4102014-09-22 14:21:44 -07001842 // Unnecessary to apply an unreferenced standard or shared UBO
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08001843 for (gl::ShaderType shaderType : gl::AllShaderTypes())
Brandon Jones18bd4102014-09-22 14:21:44 -07001844 {
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08001845 if (!uniformBlock.activeInShader(shaderType))
1846 {
1847 continue;
1848 }
Brandon Jones18bd4102014-09-22 14:21:44 -07001849
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08001850 unsigned int registerIndex = uniformBlock.mShaderRegisterIndexes[shaderType] -
1851 reservedShaderRegisterIndexes[shaderType];
Jiawei Shao54aafe52018-04-27 14:54:57 +08001852 ASSERT(registerIndex < caps.maxShaderUniformBlocks[shaderType]);
Jamie Madill03260fa2015-06-22 13:57:22 -04001853
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08001854 std::vector<int> &shaderUBOcache = mShaderUBOCaches[shaderType];
1855 if (shaderUBOcache.size() <= registerIndex)
Jamie Madill03260fa2015-06-22 13:57:22 -04001856 {
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08001857 shaderUBOcache.resize(registerIndex + 1, -1);
Jamie Madill03260fa2015-06-22 13:57:22 -04001858 }
1859
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08001860 ASSERT(shaderUBOcache[registerIndex] == -1);
1861 shaderUBOcache[registerIndex] = blockBinding;
Brandon Jones18bd4102014-09-22 14:21:44 -07001862 }
1863 }
Jamie Madilld63961d2017-09-12 15:22:57 -04001864}
Brandon Jones18bd4102014-09-22 14:21:44 -07001865
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08001866const std::vector<GLint> &ProgramD3D::getShaderUniformBufferCache(gl::ShaderType shaderType) const
Jamie Madilld63961d2017-09-12 15:22:57 -04001867{
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08001868 return mShaderUBOCaches[shaderType];
Brandon Jones18bd4102014-09-22 14:21:44 -07001869}
1870
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001871void ProgramD3D::dirtyAllUniforms()
Brandon Jones18bd4102014-09-22 14:21:44 -07001872{
Jiawei Shao3dd8d2912018-03-30 09:39:09 +08001873 mShaderUniformsDirty = mState.getLinkedShaderStages();
Jamie Madill4148fd72017-09-14 15:46:20 -04001874}
1875
1876void ProgramD3D::markUniformsClean()
1877{
Jiawei Shao3dd8d2912018-03-30 09:39:09 +08001878 mShaderUniformsDirty.reset();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001879}
1880
Jamie Madill334d6152015-10-22 14:00:28 -04001881void ProgramD3D::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001882{
Jamie Madill33bb7c42017-09-09 23:32:51 -04001883 setUniformInternal(location, count, v, GL_FLOAT);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001884}
1885
1886void ProgramD3D::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
1887{
Jamie Madill33bb7c42017-09-09 23:32:51 -04001888 setUniformInternal(location, count, v, GL_FLOAT_VEC2);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001889}
1890
1891void ProgramD3D::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
1892{
Jamie Madill33bb7c42017-09-09 23:32:51 -04001893 setUniformInternal(location, count, v, GL_FLOAT_VEC3);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001894}
1895
1896void ProgramD3D::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
1897{
Jamie Madill33bb7c42017-09-09 23:32:51 -04001898 setUniformInternal(location, count, v, GL_FLOAT_VEC4);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001899}
1900
Jamie Madill334d6152015-10-22 14:00:28 -04001901void ProgramD3D::setUniformMatrix2fv(GLint location,
1902 GLsizei count,
1903 GLboolean transpose,
1904 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001905{
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04001906 setUniformMatrixfvInternal<2, 2>(location, count, transpose, value, GL_FLOAT_MAT2);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001907}
1908
Jamie Madill334d6152015-10-22 14:00:28 -04001909void ProgramD3D::setUniformMatrix3fv(GLint location,
1910 GLsizei count,
1911 GLboolean transpose,
1912 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001913{
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04001914 setUniformMatrixfvInternal<3, 3>(location, count, transpose, value, GL_FLOAT_MAT3);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001915}
1916
Jamie Madill334d6152015-10-22 14:00:28 -04001917void ProgramD3D::setUniformMatrix4fv(GLint location,
1918 GLsizei count,
1919 GLboolean transpose,
1920 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001921{
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04001922 setUniformMatrixfvInternal<4, 4>(location, count, transpose, value, GL_FLOAT_MAT4);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001923}
1924
Jamie Madill334d6152015-10-22 14:00:28 -04001925void ProgramD3D::setUniformMatrix2x3fv(GLint location,
1926 GLsizei count,
1927 GLboolean transpose,
1928 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001929{
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04001930 setUniformMatrixfvInternal<2, 3>(location, count, transpose, value, GL_FLOAT_MAT2x3);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001931}
1932
Jamie Madill334d6152015-10-22 14:00:28 -04001933void ProgramD3D::setUniformMatrix3x2fv(GLint location,
1934 GLsizei count,
1935 GLboolean transpose,
1936 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001937{
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04001938 setUniformMatrixfvInternal<3, 2>(location, count, transpose, value, GL_FLOAT_MAT3x2);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001939}
1940
Jamie Madill334d6152015-10-22 14:00:28 -04001941void ProgramD3D::setUniformMatrix2x4fv(GLint location,
1942 GLsizei count,
1943 GLboolean transpose,
1944 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001945{
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04001946 setUniformMatrixfvInternal<2, 4>(location, count, transpose, value, GL_FLOAT_MAT2x4);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001947}
1948
Jamie Madill334d6152015-10-22 14:00:28 -04001949void ProgramD3D::setUniformMatrix4x2fv(GLint location,
1950 GLsizei count,
1951 GLboolean transpose,
1952 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001953{
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04001954 setUniformMatrixfvInternal<4, 2>(location, count, transpose, value, GL_FLOAT_MAT4x2);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001955}
1956
Jamie Madill334d6152015-10-22 14:00:28 -04001957void ProgramD3D::setUniformMatrix3x4fv(GLint location,
1958 GLsizei count,
1959 GLboolean transpose,
1960 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001961{
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04001962 setUniformMatrixfvInternal<3, 4>(location, count, transpose, value, GL_FLOAT_MAT3x4);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001963}
1964
Jamie Madill334d6152015-10-22 14:00:28 -04001965void ProgramD3D::setUniformMatrix4x3fv(GLint location,
1966 GLsizei count,
1967 GLboolean transpose,
1968 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001969{
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04001970 setUniformMatrixfvInternal<4, 3>(location, count, transpose, value, GL_FLOAT_MAT4x3);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001971}
1972
1973void ProgramD3D::setUniform1iv(GLint location, GLsizei count, const GLint *v)
1974{
Jamie Madill33bb7c42017-09-09 23:32:51 -04001975 setUniformInternal(location, count, v, GL_INT);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001976}
1977
1978void ProgramD3D::setUniform2iv(GLint location, GLsizei count, const GLint *v)
1979{
Jamie Madill33bb7c42017-09-09 23:32:51 -04001980 setUniformInternal(location, count, v, GL_INT_VEC2);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001981}
1982
1983void ProgramD3D::setUniform3iv(GLint location, GLsizei count, const GLint *v)
1984{
Jamie Madill33bb7c42017-09-09 23:32:51 -04001985 setUniformInternal(location, count, v, GL_INT_VEC3);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001986}
1987
1988void ProgramD3D::setUniform4iv(GLint location, GLsizei count, const GLint *v)
1989{
Jamie Madill33bb7c42017-09-09 23:32:51 -04001990 setUniformInternal(location, count, v, GL_INT_VEC4);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001991}
1992
1993void ProgramD3D::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
1994{
Jamie Madill33bb7c42017-09-09 23:32:51 -04001995 setUniformInternal(location, count, v, GL_UNSIGNED_INT);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001996}
1997
1998void ProgramD3D::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
1999{
Jamie Madill33bb7c42017-09-09 23:32:51 -04002000 setUniformInternal(location, count, v, GL_UNSIGNED_INT_VEC2);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002001}
2002
2003void ProgramD3D::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
2004{
Jamie Madill33bb7c42017-09-09 23:32:51 -04002005 setUniformInternal(location, count, v, GL_UNSIGNED_INT_VEC3);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002006}
2007
2008void ProgramD3D::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
2009{
Jamie Madill33bb7c42017-09-09 23:32:51 -04002010 setUniformInternal(location, count, v, GL_UNSIGNED_INT_VEC4);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002011}
2012
Jamie Madillf4141212017-12-12 15:08:07 -05002013void ProgramD3D::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint /*uniformBlockBinding*/)
Geoff Lang5d124a62015-09-15 13:03:27 -04002014{
Jamie Madillf4141212017-12-12 15:08:07 -05002015 mRenderer->onDirtyUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002016}
2017
Jamie Madillbd044ed2017-06-05 12:59:21 -04002018void ProgramD3D::defineUniformsAndAssignRegisters(const gl::Context *context)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002019{
Jamie Madill3d3d2f22015-09-23 16:47:51 -04002020 D3DUniformMap uniformMap;
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002021
2022 gl::ShaderBitSet attachedShaders;
Jiawei Shao385b3e02018-03-21 09:43:28 +08002023 for (gl::ShaderType shaderType : gl::AllShaderTypes())
Jamie Madill417df922017-01-12 09:23:07 -05002024 {
Jiawei Shao385b3e02018-03-21 09:43:28 +08002025 gl::Shader *shader = mState.getAttachedShader(shaderType);
2026 if (shader)
Jamie Madillfb536032015-09-11 13:19:49 -04002027 {
Jiawei Shao385b3e02018-03-21 09:43:28 +08002028 for (const sh::Uniform &uniform : shader->getUniforms(context))
Xinghua Caob1239382016-12-13 15:07:05 +08002029 {
Jiawei Shao385b3e02018-03-21 09:43:28 +08002030 if (uniform.active)
2031 {
2032 defineUniformBase(shader, uniform, &uniformMap);
2033 }
Xinghua Caob1239382016-12-13 15:07:05 +08002034 }
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002035
2036 attachedShaders.set(shader->getType());
Jamie Madillfb536032015-09-11 13:19:49 -04002037 }
2038 }
2039
Jamie Madill3d3d2f22015-09-23 16:47:51 -04002040 // Initialize the D3DUniform list to mirror the indexing of the GL layer.
Jamie Madill48ef11b2016-04-27 15:21:52 -04002041 for (const gl::LinkedUniform &glUniform : mState.getUniforms())
Jamie Madill3d3d2f22015-09-23 16:47:51 -04002042 {
2043 if (!glUniform.isInDefaultBlock())
2044 continue;
2045
Olli Etuahod2551232017-10-26 20:03:33 +03002046 std::string name = glUniform.name;
2047 if (glUniform.isArray())
2048 {
2049 // In the program state, array uniform names include [0] as in the program resource
2050 // spec. Here we don't include it.
2051 // TODO(oetuaho@nvidia.com): consider using the same uniform naming here as in the GL
2052 // layer.
2053 ASSERT(angle::EndsWith(name, "[0]"));
2054 name.resize(name.length() - 3);
2055 }
2056 auto mapEntry = uniformMap.find(name);
Jamie Madill3d3d2f22015-09-23 16:47:51 -04002057 ASSERT(mapEntry != uniformMap.end());
2058 mD3DUniforms.push_back(mapEntry->second);
2059 }
2060
Jamie Madill62d31cb2015-09-11 13:25:51 -04002061 assignAllSamplerRegisters();
Xinghua Cao26143fd2017-11-01 18:19:05 +08002062 assignAllImageRegisters();
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002063 initializeUniformStorage(attachedShaders);
Jamie Madillfb536032015-09-11 13:19:49 -04002064}
2065
Jamie Madill91445bc2015-09-23 16:47:53 -04002066void ProgramD3D::defineUniformBase(const gl::Shader *shader,
Jamie Madill3d3d2f22015-09-23 16:47:51 -04002067 const sh::Uniform &uniform,
2068 D3DUniformMap *uniformMap)
Jamie Madillfb536032015-09-11 13:19:49 -04002069{
Xinghua Cao26143fd2017-11-01 18:19:05 +08002070 // Samplers get their registers assigned in assignAllSamplerRegisters, and images get their
2071 // registers assigned in assignAllImageRegisters.
2072 if (gl::IsSamplerType(uniform.type))
Jamie Madillfb536032015-09-11 13:19:49 -04002073 {
Xinghua Cao26143fd2017-11-01 18:19:05 +08002074 defineUniform(shader->getType(), uniform, uniform.name, HLSLRegisterType::Texture, nullptr,
2075 uniformMap);
2076 return;
2077 }
2078 else if (gl::IsImageType(uniform.type))
2079 {
2080 if (uniform.readonly)
2081 {
2082 defineUniform(shader->getType(), uniform, uniform.name, HLSLRegisterType::Texture,
2083 nullptr, uniformMap);
2084 }
2085 else
2086 {
2087 defineUniform(shader->getType(), uniform, uniform.name,
2088 HLSLRegisterType::UnorderedAccessView, nullptr, uniformMap);
2089 }
2090 mImageBindingMap[uniform.name] = uniform.binding;
2091 return;
2092 }
2093 else if (uniform.isBuiltIn())
2094 {
2095 defineUniform(shader->getType(), uniform, uniform.name, HLSLRegisterType::None, nullptr,
2096 uniformMap);
Jamie Madill55def582015-05-04 11:24:57 -04002097 return;
2098 }
2099
Jamie Madill91445bc2015-09-23 16:47:53 -04002100 const ShaderD3D *shaderD3D = GetImplAs<ShaderD3D>(shader);
Jamie Madill91445bc2015-09-23 16:47:53 -04002101 unsigned int startRegister = shaderD3D->getUniformRegister(uniform.name);
Xinghua Cao26143fd2017-11-01 18:19:05 +08002102 ShShaderOutput outputType = shaderD3D->getCompilerOutputType();
Jamie Madillcc2ed612017-03-14 15:59:00 -04002103 sh::HLSLBlockEncoder encoder(sh::HLSLBlockEncoder::GetStrategyFor(outputType), true);
Jamie Madill62d31cb2015-09-11 13:25:51 -04002104 encoder.skipRegisters(startRegister);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002105
Xinghua Cao26143fd2017-11-01 18:19:05 +08002106 defineUniform(shader->getType(), uniform, uniform.name, HLSLRegisterType::None, &encoder,
2107 uniformMap);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002108}
2109
Jamie Madill62d31cb2015-09-11 13:25:51 -04002110D3DUniform *ProgramD3D::getD3DUniformByName(const std::string &name)
2111{
2112 for (D3DUniform *d3dUniform : mD3DUniforms)
2113 {
2114 if (d3dUniform->name == name)
2115 {
2116 return d3dUniform;
2117 }
2118 }
2119
2120 return nullptr;
2121}
2122
Jiawei Shao385b3e02018-03-21 09:43:28 +08002123void ProgramD3D::defineStructUniformFields(gl::ShaderType shaderType,
Olli Etuaho465835d2017-09-26 13:34:10 +03002124 const std::vector<sh::ShaderVariable> &fields,
2125 const std::string &namePrefix,
Xinghua Cao26143fd2017-11-01 18:19:05 +08002126 const HLSLRegisterType regType,
Olli Etuaho465835d2017-09-26 13:34:10 +03002127 sh::HLSLBlockEncoder *encoder,
2128 D3DUniformMap *uniformMap)
2129{
2130 if (encoder)
2131 encoder->enterAggregateType();
2132
2133 for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
2134 {
2135 const sh::ShaderVariable &field = fields[fieldIndex];
2136 const std::string &fieldFullName = (namePrefix + "." + field.name);
2137
2138 // Samplers get their registers assigned in assignAllSamplerRegisters.
2139 // Also they couldn't use the same encoder as the rest of the struct, since they are
2140 // extracted out of the struct by the shader translator.
2141 if (gl::IsSamplerType(field.type))
2142 {
Xinghua Cao26143fd2017-11-01 18:19:05 +08002143 defineUniform(shaderType, field, fieldFullName, regType, nullptr, uniformMap);
Olli Etuaho465835d2017-09-26 13:34:10 +03002144 }
2145 else
2146 {
Xinghua Cao26143fd2017-11-01 18:19:05 +08002147 defineUniform(shaderType, field, fieldFullName, regType, encoder, uniformMap);
Olli Etuaho465835d2017-09-26 13:34:10 +03002148 }
2149 }
2150
2151 if (encoder)
2152 encoder->exitAggregateType();
2153}
2154
Jiawei Shao385b3e02018-03-21 09:43:28 +08002155void ProgramD3D::defineArrayOfStructsUniformFields(gl::ShaderType shaderType,
Olli Etuaho465835d2017-09-26 13:34:10 +03002156 const sh::ShaderVariable &uniform,
2157 unsigned int arrayNestingIndex,
2158 const std::string &prefix,
Xinghua Cao26143fd2017-11-01 18:19:05 +08002159 const HLSLRegisterType regType,
Olli Etuaho465835d2017-09-26 13:34:10 +03002160 sh::HLSLBlockEncoder *encoder,
2161 D3DUniformMap *uniformMap)
2162{
2163 // Nested arrays are processed starting from outermost (arrayNestingIndex 0u) and ending at the
2164 // innermost.
2165 const unsigned int currentArraySize = uniform.getNestedArraySize(arrayNestingIndex);
2166 for (unsigned int arrayElement = 0u; arrayElement < currentArraySize; ++arrayElement)
2167 {
2168 const std::string &elementString = prefix + ArrayString(arrayElement);
2169 if (arrayNestingIndex + 1u < uniform.arraySizes.size())
2170 {
2171 defineArrayOfStructsUniformFields(shaderType, uniform, arrayNestingIndex + 1u,
Xinghua Cao26143fd2017-11-01 18:19:05 +08002172 elementString, regType, encoder, uniformMap);
Olli Etuaho465835d2017-09-26 13:34:10 +03002173 }
2174 else
2175 {
Xinghua Cao26143fd2017-11-01 18:19:05 +08002176 defineStructUniformFields(shaderType, uniform.fields, elementString, regType, encoder,
Olli Etuaho465835d2017-09-26 13:34:10 +03002177 uniformMap);
2178 }
2179 }
2180}
2181
Jiawei Shao385b3e02018-03-21 09:43:28 +08002182void ProgramD3D::defineArrayUniformElements(gl::ShaderType shaderType,
Olli Etuaho465835d2017-09-26 13:34:10 +03002183 const sh::ShaderVariable &uniform,
2184 const std::string &fullName,
Xinghua Cao26143fd2017-11-01 18:19:05 +08002185 const HLSLRegisterType regType,
Olli Etuaho465835d2017-09-26 13:34:10 +03002186 sh::HLSLBlockEncoder *encoder,
2187 D3DUniformMap *uniformMap)
2188{
2189 if (encoder)
2190 encoder->enterAggregateType();
2191
2192 sh::ShaderVariable uniformElement = uniform;
2193 uniformElement.arraySizes.pop_back();
2194 for (unsigned int arrayIndex = 0u; arrayIndex < uniform.getOutermostArraySize(); ++arrayIndex)
2195 {
2196 std::string elementFullName = fullName + ArrayString(arrayIndex);
Xinghua Cao26143fd2017-11-01 18:19:05 +08002197 defineUniform(shaderType, uniformElement, elementFullName, regType, encoder, uniformMap);
Olli Etuaho465835d2017-09-26 13:34:10 +03002198 }
2199
2200 if (encoder)
2201 encoder->exitAggregateType();
2202}
2203
Jiawei Shao385b3e02018-03-21 09:43:28 +08002204void ProgramD3D::defineUniform(gl::ShaderType shaderType,
Jamie Madill3d3d2f22015-09-23 16:47:51 -04002205 const sh::ShaderVariable &uniform,
2206 const std::string &fullName,
Xinghua Cao26143fd2017-11-01 18:19:05 +08002207 const HLSLRegisterType regType,
Jamie Madill3d3d2f22015-09-23 16:47:51 -04002208 sh::HLSLBlockEncoder *encoder,
2209 D3DUniformMap *uniformMap)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002210{
2211 if (uniform.isStruct())
2212 {
Olli Etuaho465835d2017-09-26 13:34:10 +03002213 if (uniform.isArray())
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002214 {
Xinghua Cao26143fd2017-11-01 18:19:05 +08002215 defineArrayOfStructsUniformFields(shaderType, uniform, 0u, fullName, regType, encoder,
Olli Etuaho465835d2017-09-26 13:34:10 +03002216 uniformMap);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002217 }
Olli Etuaho465835d2017-09-26 13:34:10 +03002218 else
2219 {
Xinghua Cao26143fd2017-11-01 18:19:05 +08002220 defineStructUniformFields(shaderType, uniform.fields, fullName, regType, encoder,
2221 uniformMap);
Olli Etuaho465835d2017-09-26 13:34:10 +03002222 }
2223 return;
2224 }
2225 if (uniform.isArrayOfArrays())
2226 {
Xinghua Cao26143fd2017-11-01 18:19:05 +08002227 defineArrayUniformElements(shaderType, uniform, fullName, regType, encoder, uniformMap);
Jamie Madill62d31cb2015-09-11 13:25:51 -04002228 return;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002229 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04002230
2231 // Not a struct. Arrays are treated as aggregate types.
2232 if (uniform.isArray() && encoder)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002233 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002234 encoder->enterAggregateType();
2235 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002236
Jamie Madill62d31cb2015-09-11 13:25:51 -04002237 // Advance the uniform offset, to track registers allocation for structs
2238 sh::BlockMemberInfo blockInfo =
Olli Etuaho465835d2017-09-26 13:34:10 +03002239 encoder ? encoder->encodeType(uniform.type, uniform.arraySizes, false)
Jamie Madill62d31cb2015-09-11 13:25:51 -04002240 : sh::BlockMemberInfo::getDefaultBlockInfo();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002241
Jamie Madill3d3d2f22015-09-23 16:47:51 -04002242 auto uniformMapEntry = uniformMap->find(fullName);
2243 D3DUniform *d3dUniform = nullptr;
Jamie Madill2857f482015-02-09 15:35:29 -05002244
Jamie Madill3d3d2f22015-09-23 16:47:51 -04002245 if (uniformMapEntry != uniformMap->end())
Jamie Madill62d31cb2015-09-11 13:25:51 -04002246 {
Jamie Madill3d3d2f22015-09-23 16:47:51 -04002247 d3dUniform = uniformMapEntry->second;
2248 }
2249 else
2250 {
Xinghua Cao26143fd2017-11-01 18:19:05 +08002251 d3dUniform = new D3DUniform(uniform.type, regType, fullName, uniform.arraySizes, true);
Jamie Madill3d3d2f22015-09-23 16:47:51 -04002252 (*uniformMap)[fullName] = d3dUniform;
Jamie Madill62d31cb2015-09-11 13:25:51 -04002253 }
2254
2255 if (encoder)
2256 {
Jamie Madill3d3d2f22015-09-23 16:47:51 -04002257 d3dUniform->registerElement =
2258 static_cast<unsigned int>(sh::HLSLBlockEncoder::getBlockRegisterElement(blockInfo));
Jamie Madill62d31cb2015-09-11 13:25:51 -04002259 unsigned int reg =
2260 static_cast<unsigned int>(sh::HLSLBlockEncoder::getBlockRegister(blockInfo));
Jiawei Shao385b3e02018-03-21 09:43:28 +08002261
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002262 ASSERT(shaderType != gl::ShaderType::InvalidEnum);
2263 d3dUniform->mShaderRegisterIndexes[shaderType] = reg;
Jamie Madillfb536032015-09-11 13:19:49 -04002264
2265 // Arrays are treated as aggregate types
Jamie Madill62d31cb2015-09-11 13:25:51 -04002266 if (uniform.isArray())
Jamie Madillfb536032015-09-11 13:19:49 -04002267 {
2268 encoder->exitAggregateType();
2269 }
2270 }
2271}
2272
Jamie Madill134f93d2017-08-31 17:11:00 -04002273// Assume count is already clamped.
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002274template <typename T>
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002275void ProgramD3D::setUniformImpl(const gl::VariableLocation &locationInfo,
Jamie Madill134f93d2017-08-31 17:11:00 -04002276 GLsizei count,
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002277 const T *v,
2278 uint8_t *targetData,
Jamie Madill33bb7c42017-09-09 23:32:51 -04002279 GLenum uniformType)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002280{
Jamie Madill493f9572018-05-24 19:52:15 -04002281 D3DUniform *targetUniform = mD3DUniforms[locationInfo.index];
2282 const int components = targetUniform->typeInfo.componentCount;
Olli Etuaho1734e172017-10-27 15:30:27 +03002283 const unsigned int arrayElementOffset = locationInfo.arrayIndex;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002284
Jamie Madill33bb7c42017-09-09 23:32:51 -04002285 if (targetUniform->typeInfo.type == uniformType)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002286 {
Olli Etuahoc8538042017-09-27 11:20:15 +03002287 T *dest = reinterpret_cast<T *>(targetData) + arrayElementOffset * 4;
Jamie Madill33bb7c42017-09-09 23:32:51 -04002288 const T *source = v;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002289
Jamie Madill33bb7c42017-09-09 23:32:51 -04002290 for (GLint i = 0; i < count; i++, dest += 4, source += components)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002291 {
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002292 memcpy(dest, source, components * sizeof(T));
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002293 }
2294 }
Jamie Madill33bb7c42017-09-09 23:32:51 -04002295 else
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002296 {
Jamie Madill33bb7c42017-09-09 23:32:51 -04002297 ASSERT(targetUniform->typeInfo.type == gl::VariableBoolVectorType(uniformType));
Olli Etuahoc8538042017-09-27 11:20:15 +03002298 GLint *boolParams = reinterpret_cast<GLint *>(targetData) + arrayElementOffset * 4;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002299
Jamie Madill134f93d2017-08-31 17:11:00 -04002300 for (GLint i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002301 {
Jamie Madill334d6152015-10-22 14:00:28 -04002302 GLint *dest = boolParams + (i * 4);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002303 const T *source = v + (i * components);
2304
2305 for (int c = 0; c < components; c++)
2306 {
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002307 dest[c] = (source[c] == static_cast<T>(0)) ? GL_FALSE : GL_TRUE;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002308 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002309 }
Brandon Jones18bd4102014-09-22 14:21:44 -07002310 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002311}
2312
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002313template <typename T>
Jamie Madill33bb7c42017-09-09 23:32:51 -04002314void ProgramD3D::setUniformInternal(GLint location, GLsizei count, const T *v, GLenum uniformType)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002315{
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002316 const gl::VariableLocation &locationInfo = mState.getUniformLocations()[location];
2317 D3DUniform *targetUniform = mD3DUniforms[locationInfo.index];
2318
Jamie Madill33bb7c42017-09-09 23:32:51 -04002319 if (targetUniform->typeInfo.isSampler)
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002320 {
Jamie Madill33bb7c42017-09-09 23:32:51 -04002321 ASSERT(uniformType == GL_INT);
Jamie Madill80823cc2017-09-14 15:46:21 -04002322 size_t size = count * sizeof(T);
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002323 GLint *dest = &targetUniform->mSamplerData[locationInfo.arrayIndex];
Jamie Madill80823cc2017-09-14 15:46:21 -04002324 if (memcmp(dest, v, size) != 0)
2325 {
2326 memcpy(dest, v, size);
2327 mDirtySamplerMapping = true;
2328 }
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002329 return;
2330 }
2331
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002332 for (gl::ShaderType shaderType : gl::AllShaderTypes())
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002333 {
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002334 if (targetUniform->mShaderData[shaderType])
2335 {
2336 setUniformImpl(locationInfo, count, v, targetUniform->mShaderData[shaderType],
2337 uniformType);
2338 mShaderUniformsDirty.set(shaderType);
2339 }
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002340 }
2341}
2342
2343template <int cols, int rows>
Jamie Madill80823cc2017-09-14 15:46:21 -04002344bool ProgramD3D::setUniformMatrixfvImpl(GLint location,
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002345 GLsizei countIn,
2346 GLboolean transpose,
2347 const GLfloat *value,
2348 uint8_t *targetData,
2349 GLenum targetUniformType)
2350{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002351 D3DUniform *targetUniform = getD3DUniformFromLocation(location);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002352
Olli Etuaho465835d2017-09-26 13:34:10 +03002353 unsigned int elementCount = targetUniform->getArraySizeProduct();
Olli Etuaho1734e172017-10-27 15:30:27 +03002354 unsigned int arrayElementOffset = mState.getUniformLocations()[location].arrayIndex;
Olli Etuahoc8538042017-09-27 11:20:15 +03002355 unsigned int count =
2356 std::min(elementCount - arrayElementOffset, static_cast<unsigned int>(countIn));
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002357
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002358 const unsigned int targetMatrixStride = (4 * rows);
Olli Etuahoc8538042017-09-27 11:20:15 +03002359 GLfloat *target = reinterpret_cast<GLfloat *>(
2360 targetData + arrayElementOffset * sizeof(GLfloat) * targetMatrixStride);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002361
Jamie Madill80823cc2017-09-14 15:46:21 -04002362 bool dirty = false;
2363
Jamie Madill62d31cb2015-09-11 13:25:51 -04002364 for (unsigned int i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002365 {
2366 // Internally store matrices as transposed versions to accomodate HLSL matrix indexing
2367 if (transpose == GL_FALSE)
2368 {
Jamie Madill80823cc2017-09-14 15:46:21 -04002369 dirty = TransposeExpandMatrix<GLfloat, cols, rows>(target, value) || dirty;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002370 }
2371 else
2372 {
Jamie Madill80823cc2017-09-14 15:46:21 -04002373 dirty = ExpandMatrix<GLfloat, cols, rows>(target, value) || dirty;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002374 }
2375 target += targetMatrixStride;
2376 value += cols * rows;
2377 }
Jamie Madill80823cc2017-09-14 15:46:21 -04002378
2379 return dirty;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002380}
2381
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002382template <int cols, int rows>
2383void ProgramD3D::setUniformMatrixfvInternal(GLint location,
2384 GLsizei countIn,
2385 GLboolean transpose,
2386 const GLfloat *value,
2387 GLenum targetUniformType)
2388{
2389 D3DUniform *targetUniform = getD3DUniformFromLocation(location);
2390
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002391 for (gl::ShaderType shaderType : gl::AllShaderTypes())
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002392 {
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002393 if (targetUniform->mShaderData[shaderType])
Jamie Madill80823cc2017-09-14 15:46:21 -04002394 {
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002395 if (setUniformMatrixfvImpl<cols, rows>(location, countIn, transpose, value,
2396 targetUniform->mShaderData[shaderType],
2397 targetUniformType))
2398 {
2399 mShaderUniformsDirty.set(shaderType);
2400 }
Jamie Madill80823cc2017-09-14 15:46:21 -04002401 }
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002402 }
2403}
2404
Jamie Madill62d31cb2015-09-11 13:25:51 -04002405void ProgramD3D::assignAllSamplerRegisters()
Jamie Madilla2eb02c2015-09-11 12:31:41 +00002406{
Olli Etuaho465835d2017-09-26 13:34:10 +03002407 for (size_t uniformIndex = 0; uniformIndex < mD3DUniforms.size(); ++uniformIndex)
Jamie Madilla2eb02c2015-09-11 12:31:41 +00002408 {
Olli Etuaho465835d2017-09-26 13:34:10 +03002409 if (mD3DUniforms[uniformIndex]->isSampler())
Jamie Madillfb536032015-09-11 13:19:49 -04002410 {
Olli Etuaho465835d2017-09-26 13:34:10 +03002411 assignSamplerRegisters(uniformIndex);
Jamie Madillfb536032015-09-11 13:19:49 -04002412 }
Jamie Madilla2eb02c2015-09-11 12:31:41 +00002413 }
2414}
2415
Olli Etuaho465835d2017-09-26 13:34:10 +03002416void ProgramD3D::assignSamplerRegisters(size_t uniformIndex)
Jamie Madillfb536032015-09-11 13:19:49 -04002417{
Olli Etuaho465835d2017-09-26 13:34:10 +03002418 D3DUniform *d3dUniform = mD3DUniforms[uniformIndex];
Jamie Madill62d31cb2015-09-11 13:25:51 -04002419 ASSERT(d3dUniform->isSampler());
Olli Etuaho465835d2017-09-26 13:34:10 +03002420 // If the uniform is an array of arrays, then we have separate entries for each inner array in
2421 // mD3DUniforms. However, the sampler register info is stored in the shader only for the
2422 // outermost array.
2423 std::vector<unsigned int> subscripts;
2424 const std::string baseName = gl::ParseResourceName(d3dUniform->name, &subscripts);
2425 unsigned int registerOffset = mState.getUniforms()[uniformIndex].flattenedOffsetInParentArrays *
2426 d3dUniform->getArraySizeProduct();
2427
Jiawei Shao467c15f2018-04-24 15:04:26 +08002428 bool hasUniform = false;
2429 for (gl::ShaderType shaderType : gl::AllShaderTypes())
Jamie Madillfb536032015-09-11 13:19:49 -04002430 {
Jiawei Shao467c15f2018-04-24 15:04:26 +08002431 if (!mState.getAttachedShader(shaderType))
Xinghua Caob1239382016-12-13 15:07:05 +08002432 {
Jiawei Shao467c15f2018-04-24 15:04:26 +08002433 continue;
Xinghua Caob1239382016-12-13 15:07:05 +08002434 }
Jiawei Shao467c15f2018-04-24 15:04:26 +08002435
2436 const ShaderD3D *shaderD3D = GetImplAs<ShaderD3D>(mState.getAttachedShader(shaderType));
2437 if (shaderD3D->hasUniform(baseName))
Xinghua Caob1239382016-12-13 15:07:05 +08002438 {
Jiawei Shao467c15f2018-04-24 15:04:26 +08002439 d3dUniform->mShaderRegisterIndexes[shaderType] =
2440 shaderD3D->getUniformRegister(baseName) + registerOffset;
2441 ASSERT(d3dUniform->mShaderRegisterIndexes[shaderType] != GL_INVALID_VALUE);
2442
2443 AssignSamplers(d3dUniform->mShaderRegisterIndexes[shaderType], d3dUniform->typeInfo,
2444 d3dUniform->getArraySizeProduct(), mShaderSamplers[shaderType],
2445 &mUsedShaderSamplerRanges[shaderType]);
2446 hasUniform = true;
Xinghua Caob1239382016-12-13 15:07:05 +08002447 }
Jamie Madillfb536032015-09-11 13:19:49 -04002448 }
Jiawei Shao467c15f2018-04-24 15:04:26 +08002449
2450 ASSERT(hasUniform);
Jamie Madillfb536032015-09-11 13:19:49 -04002451}
2452
Jamie Madill62d31cb2015-09-11 13:25:51 -04002453// static
2454void ProgramD3D::AssignSamplers(unsigned int startSamplerIndex,
Jamie Madill33bb7c42017-09-09 23:32:51 -04002455 const gl::UniformTypeInfo &typeInfo,
Jamie Madilld3dfda22015-07-06 08:28:49 -04002456 unsigned int samplerCount,
2457 std::vector<Sampler> &outSamplers,
2458 GLuint *outUsedRange)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002459{
2460 unsigned int samplerIndex = startSamplerIndex;
2461
2462 do
2463 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002464 ASSERT(samplerIndex < outSamplers.size());
2465 Sampler *sampler = &outSamplers[samplerIndex];
2466 sampler->active = true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002467 sampler->textureType = gl::FromGLenum<gl::TextureType>(typeInfo.textureType);
Jamie Madill62d31cb2015-09-11 13:25:51 -04002468 sampler->logicalTextureUnit = 0;
2469 *outUsedRange = std::max(samplerIndex + 1, *outUsedRange);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002470 samplerIndex++;
2471 } while (samplerIndex < startSamplerIndex + samplerCount);
Brandon Jones18bd4102014-09-22 14:21:44 -07002472}
2473
Xinghua Cao26143fd2017-11-01 18:19:05 +08002474void ProgramD3D::assignAllImageRegisters()
2475{
2476 for (size_t uniformIndex = 0; uniformIndex < mD3DUniforms.size(); ++uniformIndex)
2477 {
2478 if (mD3DUniforms[uniformIndex]->isImage())
2479 {
2480 assignImageRegisters(uniformIndex);
2481 }
2482 }
2483}
2484
2485void ProgramD3D::assignImageRegisters(size_t uniformIndex)
2486{
2487 D3DUniform *d3dUniform = mD3DUniforms[uniformIndex];
2488 ASSERT(d3dUniform->isImage());
2489 // If the uniform is an array of arrays, then we have separate entries for each inner array in
2490 // mD3DUniforms. However, the image register info is stored in the shader only for the
2491 // outermost array.
2492 std::vector<unsigned int> subscripts;
2493 const std::string baseName = gl::ParseResourceName(d3dUniform->name, &subscripts);
2494 unsigned int registerOffset = mState.getUniforms()[uniformIndex].flattenedOffsetInParentArrays *
2495 d3dUniform->getArraySizeProduct();
2496
Jiawei Shao385b3e02018-03-21 09:43:28 +08002497 const gl::Shader *computeShader = mState.getAttachedShader(gl::ShaderType::Compute);
Xinghua Cao26143fd2017-11-01 18:19:05 +08002498 if (computeShader)
2499 {
Jiawei Shao385b3e02018-03-21 09:43:28 +08002500 const ShaderD3D *computeShaderD3D =
2501 GetImplAs<ShaderD3D>(mState.getAttachedShader(gl::ShaderType::Compute));
Xinghua Cao26143fd2017-11-01 18:19:05 +08002502 ASSERT(computeShaderD3D->hasUniform(baseName));
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002503 d3dUniform->mShaderRegisterIndexes[gl::ShaderType::Compute] =
Xinghua Cao26143fd2017-11-01 18:19:05 +08002504 computeShaderD3D->getUniformRegister(baseName) + registerOffset;
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002505 ASSERT(d3dUniform->mShaderRegisterIndexes[gl::ShaderType::Compute] != GL_INVALID_INDEX);
Xinghua Cao26143fd2017-11-01 18:19:05 +08002506 auto bindingIter = mImageBindingMap.find(baseName);
2507 ASSERT(bindingIter != mImageBindingMap.end());
2508 if (d3dUniform->regType == HLSLRegisterType::Texture)
2509 {
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002510 AssignImages(d3dUniform->mShaderRegisterIndexes[gl::ShaderType::Compute],
2511 bindingIter->second, d3dUniform->getArraySizeProduct(), mReadonlyImagesCS,
Xinghua Cao26143fd2017-11-01 18:19:05 +08002512 &mUsedComputeReadonlyImageRange);
2513 }
2514 else if (d3dUniform->regType == HLSLRegisterType::UnorderedAccessView)
2515 {
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002516 AssignImages(d3dUniform->mShaderRegisterIndexes[gl::ShaderType::Compute],
2517 bindingIter->second, d3dUniform->getArraySizeProduct(), mImagesCS,
2518 &mUsedComputeImageRange);
Xinghua Cao26143fd2017-11-01 18:19:05 +08002519 }
2520 else
2521 {
2522 UNREACHABLE();
2523 }
2524 }
2525 else
2526 {
2527 // TODO(xinghua.cao@intel.com): Implement image variables in vertex shader and pixel shader.
2528 UNIMPLEMENTED();
2529 }
2530}
2531
2532// static
2533void ProgramD3D::AssignImages(unsigned int startImageIndex,
2534 int startLogicalImageUnit,
2535 unsigned int imageCount,
2536 std::vector<Image> &outImages,
2537 GLuint *outUsedRange)
2538{
2539 unsigned int imageIndex = startImageIndex;
2540 // If declare without a binding qualifier, any uniform image variable (include all elements of
2541 // unbound image array) shoud be bound to unit zero.
2542 if (startLogicalImageUnit == -1)
2543 {
2544 ASSERT(imageIndex < outImages.size());
2545 Image *image = &outImages[imageIndex];
2546 image->active = true;
2547 image->logicalImageUnit = 0;
2548 *outUsedRange = std::max(imageIndex + 1, *outUsedRange);
2549 return;
2550 }
2551
2552 unsigned int logcalImageUnit = startLogicalImageUnit;
2553 do
2554 {
2555 ASSERT(imageIndex < outImages.size());
2556 Image *image = &outImages[imageIndex];
2557 image->active = true;
2558 image->logicalImageUnit = logcalImageUnit;
2559 *outUsedRange = std::max(imageIndex + 1, *outUsedRange);
2560 imageIndex++;
2561 logcalImageUnit++;
2562 } while (imageIndex < startImageIndex + imageCount);
2563}
2564
Brandon Jonesc9610c52014-08-25 17:02:59 -07002565void ProgramD3D::reset()
2566{
Xinghua Caob1239382016-12-13 15:07:05 +08002567 mVertexExecutables.clear();
2568 mPixelExecutables.clear();
Jamie Madill4e31ad52015-10-29 10:32:57 -04002569
Xinghua Caob1239382016-12-13 15:07:05 +08002570 for (auto &geometryExecutable : mGeometryExecutables)
Jamie Madill4e31ad52015-10-29 10:32:57 -04002571 {
Xinghua Caob1239382016-12-13 15:07:05 +08002572 geometryExecutable.reset(nullptr);
Jamie Madill4e31ad52015-10-29 10:32:57 -04002573 }
Brandon Joneseb994362014-09-24 10:27:28 -07002574
Xinghua Caob1239382016-12-13 15:07:05 +08002575 mComputeExecutable.reset(nullptr);
2576
Jiawei Shao467c15f2018-04-24 15:04:26 +08002577 for (gl::ShaderType shaderType : gl::AllShaderTypes())
2578 {
2579 mShaderHLSL[shaderType].clear();
2580 mShaderWorkarounds[shaderType] = CompilerWorkaroundsD3D();
2581 }
Brandon Jones22502d52014-08-29 16:58:36 -07002582
Xinghua Cao26143fd2017-11-01 18:19:05 +08002583 mUsesFragDepth = false;
Martin Radev41ac68e2017-06-06 12:16:58 +03002584 mHasANGLEMultiviewEnabled = false;
2585 mUsesViewID = false;
Brandon Jones22502d52014-08-29 16:58:36 -07002586 mPixelShaderKey.clear();
Xinghua Cao26143fd2017-11-01 18:19:05 +08002587 mUsesPointSize = false;
Jamie Madill3e14e2b2015-10-29 14:38:53 -04002588 mUsesFlatInterpolation = false;
Brandon Jones22502d52014-08-29 16:58:36 -07002589
Jamie Madill62d31cb2015-09-11 13:25:51 -04002590 SafeDeleteContainer(mD3DUniforms);
Jamie Madill4a3c2342015-10-08 12:58:45 -04002591 mD3DUniformBlocks.clear();
Jamie Madill62d31cb2015-09-11 13:25:51 -04002592
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002593 for (gl::ShaderType shaderType : gl::AllShaderTypes())
2594 {
2595 mShaderUniformStorages[shaderType].reset();
Jiawei Shao467c15f2018-04-24 15:04:26 +08002596 mShaderSamplers[shaderType].clear();
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002597 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002598
Xinghua Cao26143fd2017-11-01 18:19:05 +08002599 mImagesCS.clear();
2600 mReadonlyImagesCS.clear();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002601
Jiawei Shao467c15f2018-04-24 15:04:26 +08002602 mUsedShaderSamplerRanges.fill(0);
Xinghua Cao26143fd2017-11-01 18:19:05 +08002603 mDirtySamplerMapping = true;
2604 mUsedComputeImageRange = 0;
2605 mUsedComputeReadonlyImageRange = 0;
Jamie Madill437d2662014-12-05 14:23:35 -05002606
Jamie Madill8047c0d2016-03-07 13:02:12 -05002607 mAttribLocationToD3DSemantic.fill(-1);
Jamie Madillccdf74b2015-08-18 10:46:12 -04002608
Jamie Madill9fc36822015-11-18 13:08:07 -05002609 mStreamOutVaryings.clear();
Jamie Madill4e31ad52015-10-29 10:32:57 -04002610
2611 mGeometryShaderPreamble.clear();
Jamie Madill561ed3a2017-08-31 16:48:09 -04002612
Jiawei Shao3dd8d2912018-03-30 09:39:09 +08002613 markUniformsClean();
Jamie Madill0e7f1732017-09-09 23:32:50 -04002614
2615 mCachedPixelExecutableIndex.reset();
2616 mCachedVertexExecutableIndex.reset();
Brandon Jonesc9610c52014-08-25 17:02:59 -07002617}
2618
Geoff Lang7dd2e102014-11-10 15:19:26 -05002619unsigned int ProgramD3D::getSerial() const
2620{
2621 return mSerial;
2622}
2623
2624unsigned int ProgramD3D::issueSerial()
2625{
2626 return mCurrentSerial++;
2627}
2628
Jamie Madillbd044ed2017-06-05 12:59:21 -04002629void ProgramD3D::initAttribLocationsToD3DSemantic(const gl::Context *context)
Jamie Madill63805b42015-08-25 13:17:39 -04002630{
Jiawei Shao385b3e02018-03-21 09:43:28 +08002631 gl::Shader *vertexShader = mState.getAttachedShader(gl::ShaderType::Vertex);
Jamie Madill63805b42015-08-25 13:17:39 -04002632 ASSERT(vertexShader != nullptr);
2633
2634 // Init semantic index
Jamie Madill34ca4f52017-06-13 11:49:39 -04002635 int semanticIndex = 0;
2636 for (const sh::Attribute &attribute : vertexShader->getActiveAttributes(context))
Jamie Madill63805b42015-08-25 13:17:39 -04002637 {
Jamie Madill8047c0d2016-03-07 13:02:12 -05002638 int regCount = gl::VariableRegisterCount(attribute.type);
Jamie Madill34ca4f52017-06-13 11:49:39 -04002639 GLuint location = mState.getAttributeLocation(attribute.name);
2640 ASSERT(location != std::numeric_limits<GLuint>::max());
Jamie Madill63805b42015-08-25 13:17:39 -04002641
Jamie Madill8047c0d2016-03-07 13:02:12 -05002642 for (int reg = 0; reg < regCount; ++reg)
Jamie Madill63805b42015-08-25 13:17:39 -04002643 {
Jamie Madill34ca4f52017-06-13 11:49:39 -04002644 mAttribLocationToD3DSemantic[location + reg] = semanticIndex++;
Jamie Madill63805b42015-08-25 13:17:39 -04002645 }
2646 }
Jamie Madill437d2662014-12-05 14:23:35 -05002647}
2648
Jamie Madilla779b612017-07-24 11:46:05 -04002649void ProgramD3D::updateCachedInputLayout(Serial associatedSerial, const gl::State &state)
Jamie Madilld3dfda22015-07-06 08:28:49 -04002650{
Jamie Madilla779b612017-07-24 11:46:05 -04002651 if (mCurrentVertexArrayStateSerial == associatedSerial)
2652 {
2653 return;
2654 }
2655
2656 mCurrentVertexArrayStateSerial = associatedSerial;
Jamie Madillbd136f92015-08-10 14:51:37 -04002657 mCachedInputLayout.clear();
Jamie Madill0e7f1732017-09-09 23:32:50 -04002658
Jamie Madilld3dfda22015-07-06 08:28:49 -04002659 const auto &vertexAttributes = state.getVertexArray()->getVertexAttributes();
Jamie Madillf8dd7b12015-08-05 13:50:08 -04002660
Jamie Madill6de51852017-04-12 09:53:01 -04002661 for (size_t locationIndex : mState.getActiveAttribLocationsMask())
Jamie Madilld3dfda22015-07-06 08:28:49 -04002662 {
Jamie Madill8047c0d2016-03-07 13:02:12 -05002663 int d3dSemantic = mAttribLocationToD3DSemantic[locationIndex];
Jamie Madilld3dfda22015-07-06 08:28:49 -04002664
Jamie Madill8047c0d2016-03-07 13:02:12 -05002665 if (d3dSemantic != -1)
Jamie Madilld3dfda22015-07-06 08:28:49 -04002666 {
Jamie Madill8047c0d2016-03-07 13:02:12 -05002667 if (mCachedInputLayout.size() < static_cast<size_t>(d3dSemantic + 1))
Jamie Madillbd136f92015-08-10 14:51:37 -04002668 {
Jamie Madill8047c0d2016-03-07 13:02:12 -05002669 mCachedInputLayout.resize(d3dSemantic + 1, gl::VERTEX_FORMAT_INVALID);
Jamie Madillbd136f92015-08-10 14:51:37 -04002670 }
Jamie Madill8047c0d2016-03-07 13:02:12 -05002671 mCachedInputLayout[d3dSemantic] =
2672 GetVertexFormatType(vertexAttributes[locationIndex],
2673 state.getVertexAttribCurrentValue(locationIndex).Type);
Jamie Madilld3dfda22015-07-06 08:28:49 -04002674 }
2675 }
Jamie Madill4c19a8a2017-07-24 11:46:06 -04002676
2677 VertexExecutable::getSignature(mRenderer, mCachedInputLayout, &mCachedVertexSignature);
Jamie Madill0e7f1732017-09-09 23:32:50 -04002678
2679 updateCachedVertexExecutableIndex();
Jamie Madill4c19a8a2017-07-24 11:46:06 -04002680}
2681
2682void ProgramD3D::updateCachedOutputLayout(const gl::Context *context,
2683 const gl::Framebuffer *framebuffer)
2684{
Jamie Madill0e7f1732017-09-09 23:32:50 -04002685 mPixelShaderOutputLayoutCache.clear();
2686
2687 FramebufferD3D *fboD3D = GetImplAs<FramebufferD3D>(framebuffer);
2688 const auto &colorbuffers = fboD3D->getColorAttachmentsForRender(context);
2689
2690 for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment)
2691 {
2692 const gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment];
2693
2694 if (colorbuffer)
2695 {
2696 auto binding = colorbuffer->getBinding() == GL_BACK ? GL_COLOR_ATTACHMENT0
2697 : colorbuffer->getBinding();
2698 mPixelShaderOutputLayoutCache.push_back(binding);
2699 }
2700 else
2701 {
2702 mPixelShaderOutputLayoutCache.push_back(GL_NONE);
2703 }
2704 }
2705
2706 updateCachedPixelExecutableIndex();
Jamie Madilld3dfda22015-07-06 08:28:49 -04002707}
2708
Jamie Madill192745a2016-12-22 15:58:21 -05002709void ProgramD3D::gatherTransformFeedbackVaryings(const gl::VaryingPacking &varyingPacking,
2710 const BuiltinInfo &builtins)
Jamie Madillccdf74b2015-08-18 10:46:12 -04002711{
Jamie Madill9fc36822015-11-18 13:08:07 -05002712 const std::string &varyingSemantic =
2713 GetVaryingSemantic(mRenderer->getMajorShaderModel(), usesPointSize());
2714
Jamie Madillccdf74b2015-08-18 10:46:12 -04002715 // Gather the linked varyings that are used for transform feedback, they should all exist.
Jamie Madill9fc36822015-11-18 13:08:07 -05002716 mStreamOutVaryings.clear();
2717
Jamie Madill48ef11b2016-04-27 15:21:52 -04002718 const auto &tfVaryingNames = mState.getTransformFeedbackVaryingNames();
Jamie Madill9fc36822015-11-18 13:08:07 -05002719 for (unsigned int outputSlot = 0; outputSlot < static_cast<unsigned int>(tfVaryingNames.size());
2720 ++outputSlot)
Jamie Madillccdf74b2015-08-18 10:46:12 -04002721 {
Jamie Madill9fc36822015-11-18 13:08:07 -05002722 const auto &tfVaryingName = tfVaryingNames[outputSlot];
2723 if (tfVaryingName == "gl_Position")
Jamie Madillccdf74b2015-08-18 10:46:12 -04002724 {
Jamie Madill9fc36822015-11-18 13:08:07 -05002725 if (builtins.glPosition.enabled)
Jamie Madillccdf74b2015-08-18 10:46:12 -04002726 {
Jamie Madill9fc36822015-11-18 13:08:07 -05002727 mStreamOutVaryings.push_back(D3DVarying(builtins.glPosition.semantic,
2728 builtins.glPosition.index, 4, outputSlot));
2729 }
2730 }
2731 else if (tfVaryingName == "gl_FragCoord")
2732 {
2733 if (builtins.glFragCoord.enabled)
2734 {
2735 mStreamOutVaryings.push_back(D3DVarying(builtins.glFragCoord.semantic,
2736 builtins.glFragCoord.index, 4, outputSlot));
2737 }
2738 }
2739 else if (tfVaryingName == "gl_PointSize")
2740 {
2741 if (builtins.glPointSize.enabled)
2742 {
2743 mStreamOutVaryings.push_back(D3DVarying("PSIZE", 0, 1, outputSlot));
2744 }
2745 }
2746 else
2747 {
Jamie Madill192745a2016-12-22 15:58:21 -05002748 for (const auto &registerInfo : varyingPacking.getRegisterList())
Jamie Madill9fc36822015-11-18 13:08:07 -05002749 {
Jamie Madill55c25d02015-11-18 13:08:08 -05002750 const auto &varying = *registerInfo.packedVarying->varying;
2751 GLenum transposedType = gl::TransposeMatrixType(varying.type);
jchen108225e732017-11-14 16:29:03 +08002752 int componentCount = gl::VariableColumnCount(transposedType);
2753 ASSERT(!varying.isBuiltIn() && !varying.isStruct());
Jamie Madill55c25d02015-11-18 13:08:08 -05002754
Jamie Madill9fc36822015-11-18 13:08:07 -05002755 // There can be more than one register assigned to a particular varying, and each
2756 // register needs its own stream out entry.
jchen108225e732017-11-14 16:29:03 +08002757 if (registerInfo.tfVaryingName() == tfVaryingName)
Jamie Madill9fc36822015-11-18 13:08:07 -05002758 {
2759 mStreamOutVaryings.push_back(D3DVarying(
2760 varyingSemantic, registerInfo.semanticIndex, componentCount, outputSlot));
2761 }
Jamie Madillccdf74b2015-08-18 10:46:12 -04002762 }
2763 }
2764 }
2765}
Jamie Madill62d31cb2015-09-11 13:25:51 -04002766
2767D3DUniform *ProgramD3D::getD3DUniformFromLocation(GLint location)
2768{
Jamie Madill48ef11b2016-04-27 15:21:52 -04002769 return mD3DUniforms[mState.getUniformLocations()[location].index];
Jamie Madill62d31cb2015-09-11 13:25:51 -04002770}
Jamie Madill4a3c2342015-10-08 12:58:45 -04002771
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002772const D3DUniform *ProgramD3D::getD3DUniformFromLocation(GLint location) const
2773{
2774 return mD3DUniforms[mState.getUniformLocations()[location].index];
2775}
2776
Sami Väisänen46eaa942016-06-29 10:26:37 +03002777void ProgramD3D::setPathFragmentInputGen(const std::string &inputName,
2778 GLenum genMode,
2779 GLint components,
2780 const GLfloat *coeffs)
2781{
2782 UNREACHABLE();
2783}
2784
Jamie Madill4c19a8a2017-07-24 11:46:06 -04002785bool ProgramD3D::hasVertexExecutableForCachedInputLayout()
2786{
Jamie Madill0e7f1732017-09-09 23:32:50 -04002787 return mCachedVertexExecutableIndex.valid();
Jamie Madill4c19a8a2017-07-24 11:46:06 -04002788}
2789
Jamie Madill493f9572018-05-24 19:52:15 -04002790bool ProgramD3D::hasGeometryExecutableForPrimitiveType(gl::PrimitiveMode drawMode)
Jamie Madill4c19a8a2017-07-24 11:46:06 -04002791{
2792 if (!usesGeometryShader(drawMode))
2793 {
2794 // No shader necessary mean we have the required (null) executable.
2795 return true;
2796 }
2797
Jamie Madill04796cd2018-05-24 19:52:16 -04002798 gl::PrimitiveMode geometryShaderType = GetGeometryShaderTypeFromDrawMode(drawMode);
Jamie Madill4c19a8a2017-07-24 11:46:06 -04002799 return mGeometryExecutables[geometryShaderType].get() != nullptr;
2800}
2801
2802bool ProgramD3D::hasPixelExecutableForCachedOutputLayout()
2803{
Jamie Madill0e7f1732017-09-09 23:32:50 -04002804 return mCachedPixelExecutableIndex.valid();
Jamie Madill4c19a8a2017-07-24 11:46:06 -04002805}
2806
Jiawei Shao3dd8d2912018-03-30 09:39:09 +08002807bool ProgramD3D::anyShaderUniformsDirty() const
2808{
2809 return mShaderUniformsDirty.any();
2810}
2811
Jamie Madill54164b02017-08-28 15:17:37 -04002812template <typename DestT>
2813void ProgramD3D::getUniformInternal(GLint location, DestT *dataOut) const
2814{
2815 const gl::VariableLocation &locationInfo = mState.getUniformLocations()[location];
2816 const gl::LinkedUniform &uniform = mState.getUniforms()[locationInfo.index];
2817
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002818 const D3DUniform *targetUniform = getD3DUniformFromLocation(location);
Olli Etuaho1734e172017-10-27 15:30:27 +03002819 const uint8_t *srcPointer = targetUniform->getDataPtrToElement(locationInfo.arrayIndex);
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002820
2821 if (gl::IsMatrixType(uniform.type))
2822 {
2823 GetMatrixUniform(gl::VariableColumnCount(uniform.type), gl::VariableRowCount(uniform.type),
2824 dataOut, reinterpret_cast<const DestT *>(srcPointer));
2825 }
2826 else
2827 {
2828 memcpy(dataOut, srcPointer, uniform.getElementSize());
2829 }
Jamie Madill54164b02017-08-28 15:17:37 -04002830}
2831
2832void ProgramD3D::getUniformfv(const gl::Context *context, GLint location, GLfloat *params) const
2833{
2834 getUniformInternal(location, params);
2835}
2836
2837void ProgramD3D::getUniformiv(const gl::Context *context, GLint location, GLint *params) const
2838{
2839 getUniformInternal(location, params);
2840}
2841
2842void ProgramD3D::getUniformuiv(const gl::Context *context, GLint location, GLuint *params) const
2843{
2844 getUniformInternal(location, params);
2845}
2846
Jamie Madill0e7f1732017-09-09 23:32:50 -04002847void ProgramD3D::updateCachedVertexExecutableIndex()
2848{
2849 mCachedVertexExecutableIndex.reset();
2850 for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++)
2851 {
2852 if (mVertexExecutables[executableIndex]->matchesSignature(mCachedVertexSignature))
2853 {
2854 mCachedVertexExecutableIndex = executableIndex;
2855 break;
2856 }
2857 }
2858}
2859
2860void ProgramD3D::updateCachedPixelExecutableIndex()
2861{
2862 mCachedPixelExecutableIndex.reset();
2863 for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++)
2864 {
2865 if (mPixelExecutables[executableIndex]->matchesSignature(mPixelShaderOutputLayoutCache))
2866 {
2867 mCachedPixelExecutableIndex = executableIndex;
2868 break;
2869 }
2870 }
2871}
2872
Jamie Madill6db1c2e2017-11-08 09:17:40 -05002873void ProgramD3D::linkResources(const gl::Context *context,
2874 const gl::ProgramLinkedResources &resources)
2875{
2876 UniformBlockInfo uniformBlockInfo;
Jiawei Shao385b3e02018-03-21 09:43:28 +08002877 for (gl::ShaderType shaderType : gl::AllShaderTypes())
Jamie Madill6db1c2e2017-11-08 09:17:40 -05002878 {
Jiawei Shao385b3e02018-03-21 09:43:28 +08002879 gl::Shader *shader = mState.getAttachedShader(shaderType);
2880 if (shader)
2881 {
2882 uniformBlockInfo.getShaderBlockInfo(context, shader);
2883 }
Jamie Madill6db1c2e2017-11-08 09:17:40 -05002884 }
2885
2886 // Gather interface block info.
2887 auto getUniformBlockSize = [&uniformBlockInfo](const std::string &name,
2888 const std::string &mappedName, size_t *sizeOut) {
2889 return uniformBlockInfo.getBlockSize(name, mappedName, sizeOut);
2890 };
2891
2892 auto getUniformBlockMemberInfo = [&uniformBlockInfo](const std::string &name,
2893 const std::string &mappedName,
2894 sh::BlockMemberInfo *infoOut) {
2895 return uniformBlockInfo.getBlockMemberInfo(name, mappedName, infoOut);
2896 };
2897
2898 resources.uniformBlockLinker.linkBlocks(getUniformBlockSize, getUniformBlockMemberInfo);
2899 initializeUniformBlocks();
2900
2901 // TODO(jiajia.qin@intel.com): Determine correct shader storage block info.
2902 auto getShaderStorageBlockSize = [](const std::string &name, const std::string &mappedName,
2903 size_t *sizeOut) {
2904 *sizeOut = 0;
2905 return true;
2906 };
2907
2908 auto getShaderStorageBlockMemberInfo =
2909 [](const std::string &name, const std::string &mappedName, sh::BlockMemberInfo *infoOut) {
2910 *infoOut = sh::BlockMemberInfo::getDefaultBlockInfo();
2911 return true;
2912 };
2913
2914 resources.shaderStorageBlockLinker.linkBlocks(getShaderStorageBlockSize,
2915 getShaderStorageBlockMemberInfo);
2916}
2917
Jamie Madill8047c0d2016-03-07 13:02:12 -05002918} // namespace rx