blob: 11c330f3588bf0b78b1cd3fe133e6cc7d60b978a [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"
Jamie Madill785e8a02018-10-04 17:42:00 -040024#include "libANGLE/renderer/d3d/ContextD3D.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050025#include "libANGLE/renderer/d3d/DynamicHLSL.h"
Jamie Madill85a18042015-03-05 15:41:41 -050026#include "libANGLE/renderer/d3d/FramebufferD3D.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050027#include "libANGLE/renderer/d3d/ShaderD3D.h"
Geoff Lang359ef262015-01-05 14:42:29 -050028#include "libANGLE/renderer/d3d/ShaderExecutableD3D.h"
Jamie Madill437d2662014-12-05 14:23:35 -050029#include "libANGLE/renderer/d3d/VertexDataManager.h"
Luc Ferron46bcea52018-05-31 09:48:36 -040030#include "libANGLE/renderer/renderer_utils.h"
Geoff Lang22072132014-11-20 15:15:01 -050031
Jamie Madill01074252016-11-28 15:55:51 -050032using namespace angle;
33
Brandon Jonesc9610c52014-08-25 17:02:59 -070034namespace rx
35{
36
Brandon Joneseb994362014-09-24 10:27:28 -070037namespace
38{
39
jchen103fd614d2018-08-13 12:21:58 +080040void GetDefaultInputLayoutFromShader(gl::Shader *vertexShader, gl::InputLayout *inputLayoutOut)
Brandon Joneseb994362014-09-24 10:27:28 -070041{
Jamie Madill4c19a8a2017-07-24 11:46:06 -040042 inputLayoutOut->clear();
43
jchen103fd614d2018-08-13 12:21:58 +080044 for (const sh::Attribute &shaderAttr : vertexShader->getActiveAttributes())
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);
Frank Henigmand633b152018-10-04 23:34:31 -040056 angle::FormatID defaultID =
57 gl::GetVertexFormatID(componentType, GL_FALSE, components, pureInt);
Brandon Joneseb994362014-09-24 10:27:28 -070058
Frank Henigmand633b152018-10-04 23:34:31 -040059 inputLayoutOut->push_back(defaultID);
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
Xinghua Caof3179a62018-07-12 16:22:06 +080078void GetDefaultImage2DBindLayoutFromComputeShader(const std::vector<sh::Uniform> &image2DUniforms,
79 gl::ImageUnitTextureTypeMap *image2DBindLayout)
80{
81 image2DBindLayout->clear();
82
83 for (const sh::Uniform &image2D : image2DUniforms)
84 {
85 if (gl::IsImage2DType(image2D.type))
86 {
87 if (image2D.binding == -1)
88 {
89 image2DBindLayout->insert(std::make_pair(0, gl::TextureType::_2D));
90 }
91 else
92 {
93 for (unsigned int index = 0; index < image2D.getArraySizeProduct(); index++)
94 {
95 image2DBindLayout->insert(
96 std::make_pair(image2D.binding + index, gl::TextureType::_2D));
97 }
98 }
99 }
100 }
101}
102
Jamie Madill04796cd2018-05-24 19:52:16 -0400103gl::PrimitiveMode GetGeometryShaderTypeFromDrawMode(gl::PrimitiveMode drawMode)
Jamie Madill4e31ad52015-10-29 10:32:57 -0400104{
105 switch (drawMode)
106 {
107 // Uses the point sprite geometry shader.
Jamie Madill493f9572018-05-24 19:52:15 -0400108 case gl::PrimitiveMode::Points:
Jamie Madill04796cd2018-05-24 19:52:16 -0400109 return gl::PrimitiveMode::Points;
Jamie Madill4e31ad52015-10-29 10:32:57 -0400110
111 // All line drawing uses the same geometry shader.
Jamie Madill493f9572018-05-24 19:52:15 -0400112 case gl::PrimitiveMode::Lines:
113 case gl::PrimitiveMode::LineStrip:
114 case gl::PrimitiveMode::LineLoop:
Jamie Madill04796cd2018-05-24 19:52:16 -0400115 return gl::PrimitiveMode::Lines;
Jamie Madill4e31ad52015-10-29 10:32:57 -0400116
117 // The triangle fan primitive is emulated with strips in D3D11.
Jamie Madill493f9572018-05-24 19:52:15 -0400118 case gl::PrimitiveMode::Triangles:
119 case gl::PrimitiveMode::TriangleFan:
Jamie Madill04796cd2018-05-24 19:52:16 -0400120 return gl::PrimitiveMode::Triangles;
Jamie Madill4e31ad52015-10-29 10:32:57 -0400121
122 // Special case for triangle strips.
Jamie Madill493f9572018-05-24 19:52:15 -0400123 case gl::PrimitiveMode::TriangleStrip:
Jamie Madill04796cd2018-05-24 19:52:16 -0400124 return gl::PrimitiveMode::TriangleStrip;
Jamie Madill4e31ad52015-10-29 10:32:57 -0400125
126 default:
127 UNREACHABLE();
Jamie Madill04796cd2018-05-24 19:52:16 -0400128 return gl::PrimitiveMode::InvalidEnum;
Jamie Madill4e31ad52015-10-29 10:32:57 -0400129 }
130}
131
Jiawei Shao467c15f2018-04-24 15:04:26 +0800132bool HasFlatInterpolationVarying(const std::vector<sh::Varying> &varyings)
Jamie Madill192745a2016-12-22 15:58:21 -0500133{
134 // Note: this assumes nested structs can only be packed with one interpolation.
135 for (const auto &varying : varyings)
136 {
137 if (varying.interpolation == sh::INTERPOLATION_FLAT)
138 {
139 return true;
140 }
141 }
142
143 return false;
144}
145
jchen103fd614d2018-08-13 12:21:58 +0800146bool FindFlatInterpolationVaryingPerShader(gl::Shader *shader)
Jiawei Shao467c15f2018-04-24 15:04:26 +0800147{
jchen103fd614d2018-08-13 12:21:58 +0800148 ASSERT(shader);
Jiawei Shao467c15f2018-04-24 15:04:26 +0800149 switch (shader->getType())
150 {
151 case gl::ShaderType::Vertex:
jchen103fd614d2018-08-13 12:21:58 +0800152 return HasFlatInterpolationVarying(shader->getOutputVaryings());
Jiawei Shao467c15f2018-04-24 15:04:26 +0800153 case gl::ShaderType::Fragment:
jchen103fd614d2018-08-13 12:21:58 +0800154 return HasFlatInterpolationVarying(shader->getInputVaryings());
Jiawei Shao467c15f2018-04-24 15:04:26 +0800155 case gl::ShaderType::Geometry:
jchen103fd614d2018-08-13 12:21:58 +0800156 return HasFlatInterpolationVarying(shader->getInputVaryings()) ||
157 HasFlatInterpolationVarying(shader->getOutputVaryings());
Jiawei Shao467c15f2018-04-24 15:04:26 +0800158 default:
159 UNREACHABLE();
160 return false;
161 }
162}
163
jchen103fd614d2018-08-13 12:21:58 +0800164bool FindFlatInterpolationVarying(const gl::ShaderMap<gl::Shader *> &shaders)
Jiawei Shao467c15f2018-04-24 15:04:26 +0800165{
Jiawei Shao467c15f2018-04-24 15:04:26 +0800166 for (gl::ShaderType shaderType : gl::kAllGraphicsShaderTypes)
167 {
168 gl::Shader *shader = shaders[shaderType];
169 if (!shader)
170 {
171 continue;
172 }
173
jchen103fd614d2018-08-13 12:21:58 +0800174 if (FindFlatInterpolationVaryingPerShader(shader))
Jiawei Shao467c15f2018-04-24 15:04:26 +0800175 {
176 return true;
177 }
178 }
179
180 return false;
181}
182
Qin Jiajia3026f112018-10-09 12:13:38 +0800183class InterfaceBlockInfo final : angle::NonCopyable
Jamie Madill6db1c2e2017-11-08 09:17:40 -0500184{
185 public:
Qin Jiajia3026f112018-10-09 12:13:38 +0800186 InterfaceBlockInfo() {}
Jamie Madill6db1c2e2017-11-08 09:17:40 -0500187
Qin Jiajia3026f112018-10-09 12:13:38 +0800188 void getShaderBlockInfo(const std::vector<sh::InterfaceBlock> &interfaceBlocks);
Jamie Madill6db1c2e2017-11-08 09:17:40 -0500189
190 bool getBlockSize(const std::string &name, const std::string &mappedName, size_t *sizeOut);
191 bool getBlockMemberInfo(const std::string &name,
192 const std::string &mappedName,
193 sh::BlockMemberInfo *infoOut);
194
195 private:
196 size_t getBlockInfo(const sh::InterfaceBlock &interfaceBlock);
197
198 std::map<std::string, size_t> mBlockSizes;
199 sh::BlockLayoutMap mBlockLayout;
200};
201
Qin Jiajia3026f112018-10-09 12:13:38 +0800202void InterfaceBlockInfo::getShaderBlockInfo(const std::vector<sh::InterfaceBlock> &interfaceBlocks)
Jamie Madill6db1c2e2017-11-08 09:17:40 -0500203{
Qin Jiajia3026f112018-10-09 12:13:38 +0800204 for (const sh::InterfaceBlock &interfaceBlock : interfaceBlocks)
Jamie Madill6db1c2e2017-11-08 09:17:40 -0500205 {
Olli Etuaho107c7242018-03-20 15:45:35 +0200206 if (!interfaceBlock.active && interfaceBlock.layout == sh::BLOCKLAYOUT_PACKED)
Jamie Madill6db1c2e2017-11-08 09:17:40 -0500207 continue;
208
209 if (mBlockSizes.count(interfaceBlock.name) > 0)
210 continue;
211
212 size_t dataSize = getBlockInfo(interfaceBlock);
213 mBlockSizes[interfaceBlock.name] = dataSize;
214 }
215}
216
Qin Jiajia3026f112018-10-09 12:13:38 +0800217size_t InterfaceBlockInfo::getBlockInfo(const sh::InterfaceBlock &interfaceBlock)
Jamie Madill6db1c2e2017-11-08 09:17:40 -0500218{
Olli Etuaho107c7242018-03-20 15:45:35 +0200219 ASSERT(interfaceBlock.active || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED);
Jamie Madill6db1c2e2017-11-08 09:17:40 -0500220
221 // define member uniforms
222 sh::Std140BlockEncoder std140Encoder;
Qin Jiajia5df1d282019-01-04 14:22:59 +0800223 sh::Std430BlockEncoder std430Encoder;
Jamie Madill6db1c2e2017-11-08 09:17:40 -0500224 sh::HLSLBlockEncoder hlslEncoder(sh::HLSLBlockEncoder::ENCODE_PACKED, false);
225 sh::BlockLayoutEncoder *encoder = nullptr;
226
227 if (interfaceBlock.layout == sh::BLOCKLAYOUT_STD140)
228 {
229 encoder = &std140Encoder;
230 }
Qin Jiajia5df1d282019-01-04 14:22:59 +0800231 else if (interfaceBlock.layout == sh::BLOCKLAYOUT_STD430)
232 {
233 encoder = &std430Encoder;
234 }
Jamie Madill6db1c2e2017-11-08 09:17:40 -0500235 else
236 {
237 encoder = &hlslEncoder;
238 }
239
Qin Jiajia3026f112018-10-09 12:13:38 +0800240 sh::GetInterfaceBlockInfo(interfaceBlock.fields, interfaceBlock.fieldPrefix(), encoder,
241 &mBlockLayout);
Jamie Madill6db1c2e2017-11-08 09:17:40 -0500242
Jamie Madill4e712be2019-01-03 13:53:59 -0500243 return encoder->getCurrentOffset();
Jamie Madill6db1c2e2017-11-08 09:17:40 -0500244}
245
Qin Jiajia3026f112018-10-09 12:13:38 +0800246bool InterfaceBlockInfo::getBlockSize(const std::string &name,
247 const std::string &mappedName,
248 size_t *sizeOut)
Jamie Madill6db1c2e2017-11-08 09:17:40 -0500249{
250 size_t nameLengthWithoutArrayIndex;
251 gl::ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
252 std::string baseName = name.substr(0u, nameLengthWithoutArrayIndex);
253 auto sizeIter = mBlockSizes.find(baseName);
254 if (sizeIter == mBlockSizes.end())
255 {
256 *sizeOut = 0;
257 return false;
258 }
259
260 *sizeOut = sizeIter->second;
261 return true;
262};
263
Qin Jiajia3026f112018-10-09 12:13:38 +0800264bool InterfaceBlockInfo::getBlockMemberInfo(const std::string &name,
265 const std::string &mappedName,
266 sh::BlockMemberInfo *infoOut)
Jamie Madill6db1c2e2017-11-08 09:17:40 -0500267{
268 auto infoIter = mBlockLayout.find(name);
269 if (infoIter == mBlockLayout.end())
270 {
Jamie Madill04ea03e2019-01-01 15:14:25 -0500271 *infoOut = sh::kDefaultBlockMemberInfo;
Jamie Madill6db1c2e2017-11-08 09:17:40 -0500272 return false;
273 }
274
275 *infoOut = infoIter->second;
276 return true;
277};
Jamie Madill8c78ce42018-12-16 19:14:58 -0500278
279// Helper class that gathers uniform info from the default uniform block.
280class UniformEncodingVisitorD3D : public sh::BlockEncoderVisitor
281{
282 public:
283 UniformEncodingVisitorD3D(gl::ShaderType shaderType,
284 HLSLRegisterType registerType,
285 sh::BlockLayoutEncoder *encoder,
286 D3DUniformMap *uniformMapOut)
287 : sh::BlockEncoderVisitor("", "", encoder),
288 mShaderType(shaderType),
289 mRegisterType(registerType),
290 mUniformMapOut(uniformMapOut)
291 {}
292
293 void visitNamedSampler(const sh::ShaderVariable &sampler,
294 const std::string &name,
295 const std::string &mappedName) override
296 {
297 auto uniformMapEntry = mUniformMapOut->find(name);
298 if (uniformMapEntry == mUniformMapOut->end())
299 {
300 (*mUniformMapOut)[name] =
301 new D3DUniform(sampler.type, mRegisterType, name, sampler.arraySizes, true);
302 }
303 }
304
305 void encodeVariable(const sh::ShaderVariable &variable,
306 const sh::BlockMemberInfo &variableInfo,
307 const std::string &name,
308 const std::string &mappedName) override
309 {
310 auto uniformMapEntry = mUniformMapOut->find(name);
311 D3DUniform *d3dUniform = nullptr;
312
313 if (uniformMapEntry != mUniformMapOut->end())
314 {
315 d3dUniform = uniformMapEntry->second;
316 }
317 else
318 {
319 d3dUniform =
320 new D3DUniform(variable.type, mRegisterType, name, variable.arraySizes, true);
321 (*mUniformMapOut)[name] = d3dUniform;
322 }
323
324 d3dUniform->registerElement = static_cast<unsigned int>(
325 sh::BlockLayoutEncoder::GetBlockRegisterElement(variableInfo));
326 unsigned int reg =
327 static_cast<unsigned int>(sh::BlockLayoutEncoder::GetBlockRegister(variableInfo));
328
329 ASSERT(mShaderType != gl::ShaderType::InvalidEnum);
330 d3dUniform->mShaderRegisterIndexes[mShaderType] = reg;
331 }
332
333 private:
334 gl::ShaderType mShaderType;
335 HLSLRegisterType mRegisterType;
336 D3DUniformMap *mUniformMapOut;
337};
Jamie Madillada9ecc2015-08-17 12:53:37 -0400338} // anonymous namespace
339
Jamie Madill28afae52015-11-09 15:07:57 -0500340// D3DUniform Implementation
341
Jamie Madill33bb7c42017-09-09 23:32:51 -0400342D3DUniform::D3DUniform(GLenum type,
Xinghua Cao26143fd2017-11-01 18:19:05 +0800343 HLSLRegisterType reg,
Jamie Madill62d31cb2015-09-11 13:25:51 -0400344 const std::string &nameIn,
Olli Etuaho465835d2017-09-26 13:34:10 +0300345 const std::vector<unsigned int> &arraySizesIn,
Jamie Madill62d31cb2015-09-11 13:25:51 -0400346 bool defaultBlock)
Jamie Madill33bb7c42017-09-09 23:32:51 -0400347 : typeInfo(gl::GetUniformTypeInfo(type)),
Jamie Madill62d31cb2015-09-11 13:25:51 -0400348 name(nameIn),
Olli Etuaho465835d2017-09-26 13:34:10 +0300349 arraySizes(arraySizesIn),
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800350 mShaderData({}),
Xinghua Cao26143fd2017-11-01 18:19:05 +0800351 regType(reg),
Jamie Madill62d31cb2015-09-11 13:25:51 -0400352 registerCount(0),
353 registerElement(0)
354{
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800355 mShaderRegisterIndexes.fill(GL_INVALID_INDEX);
356
Jamie Madill62d31cb2015-09-11 13:25:51 -0400357 // We use data storage for default block uniforms to cache values that are sent to D3D during
358 // rendering
359 // Uniform blocks/buffers are treated separately by the Renderer (ES3 path only)
360 if (defaultBlock)
361 {
Jamie Madillcc2ed612017-03-14 15:59:00 -0400362 // Use the row count as register count, will work for non-square matrices.
Olli Etuaho465835d2017-09-26 13:34:10 +0300363 registerCount = typeInfo.rowCount * getArraySizeProduct();
Jamie Madill62d31cb2015-09-11 13:25:51 -0400364 }
365}
366
Jamie Madillb980c562018-11-27 11:34:27 -0500367D3DUniform::~D3DUniform() {}
Jamie Madillbe5e2ec2017-08-31 13:28:28 -0400368
Olli Etuaho465835d2017-09-26 13:34:10 +0300369unsigned int D3DUniform::getArraySizeProduct() const
370{
371 return gl::ArraySizeProduct(arraySizes);
372}
373
Jamie Madillbe5e2ec2017-08-31 13:28:28 -0400374const uint8_t *D3DUniform::getDataPtrToElement(size_t elementIndex) const
375{
Olli Etuaho465835d2017-09-26 13:34:10 +0300376 ASSERT((!isArray() && elementIndex == 0) ||
377 (isArray() && elementIndex < getArraySizeProduct()));
Jamie Madillbe5e2ec2017-08-31 13:28:28 -0400378
379 if (isSampler())
380 {
381 return reinterpret_cast<const uint8_t *>(&mSamplerData[elementIndex]);
382 }
383
Jamie Madill33bb7c42017-09-09 23:32:51 -0400384 return firstNonNullData() + (elementIndex > 0 ? (typeInfo.internalSize * elementIndex) : 0u);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400385}
386
387bool D3DUniform::isSampler() const
388{
Jamie Madill33bb7c42017-09-09 23:32:51 -0400389 return typeInfo.isSampler;
Jamie Madill62d31cb2015-09-11 13:25:51 -0400390}
391
Xinghua Cao26143fd2017-11-01 18:19:05 +0800392bool D3DUniform::isImage() const
393{
394 return typeInfo.isImageType;
395}
396
Xinghua Caof3179a62018-07-12 16:22:06 +0800397bool D3DUniform::isImage2D() const
398{
399 return gl::IsImage2DType(typeInfo.type);
400}
401
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800402bool D3DUniform::isReferencedByShader(gl::ShaderType shaderType) const
Jamie Madill62d31cb2015-09-11 13:25:51 -0400403{
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800404 return mShaderRegisterIndexes[shaderType] != GL_INVALID_INDEX;
Xinghua Caob1239382016-12-13 15:07:05 +0800405}
406
Jamie Madillbe5e2ec2017-08-31 13:28:28 -0400407const uint8_t *D3DUniform::firstNonNullData() const
408{
Jamie Madillbe5e2ec2017-08-31 13:28:28 -0400409 if (!mSamplerData.empty())
410 {
411 return reinterpret_cast<const uint8_t *>(mSamplerData.data());
412 }
413
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800414 for (gl::ShaderType shaderType : gl::AllShaderTypes())
415 {
416 if (mShaderData[shaderType])
417 {
418 return mShaderData[shaderType];
419 }
420 }
421
422 UNREACHABLE();
423 return nullptr;
Jamie Madillbe5e2ec2017-08-31 13:28:28 -0400424}
425
Jamie Madillab2bfa82019-01-15 19:06:47 -0500426// D3DInterfaceBlock Implementation
427D3DInterfaceBlock::D3DInterfaceBlock()
428{
429 mShaderRegisterIndexes.fill(GL_INVALID_INDEX);
430}
431
432D3DInterfaceBlock::D3DInterfaceBlock(const D3DInterfaceBlock &other) = default;
433
Jamie Madill28afae52015-11-09 15:07:57 -0500434// D3DVarying Implementation
435
Jamie Madillb980c562018-11-27 11:34:27 -0500436D3DVarying::D3DVarying() : semanticIndex(0), componentCount(0), outputSlot(0) {}
Jamie Madill28afae52015-11-09 15:07:57 -0500437
Jamie Madill9fc36822015-11-18 13:08:07 -0500438D3DVarying::D3DVarying(const std::string &semanticNameIn,
439 unsigned int semanticIndexIn,
440 unsigned int componentCountIn,
441 unsigned int outputSlotIn)
442 : semanticName(semanticNameIn),
443 semanticIndex(semanticIndexIn),
444 componentCount(componentCountIn),
445 outputSlot(outputSlotIn)
Jamie Madillb980c562018-11-27 11:34:27 -0500446{}
Jamie Madill28afae52015-11-09 15:07:57 -0500447
Jamie Madille39a3f02015-11-17 20:42:15 -0500448// ProgramD3DMetadata Implementation
449
Jamie Madillc9bde922016-07-24 17:58:50 -0400450ProgramD3DMetadata::ProgramD3DMetadata(RendererD3D *renderer,
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800451 const gl::ShaderMap<const ShaderD3D *> &attachedShaders)
Jamie Madillc9bde922016-07-24 17:58:50 -0400452 : mRendererMajorShaderModel(renderer->getMajorShaderModel()),
453 mShaderModelSuffix(renderer->getShaderModelSuffix()),
454 mUsesInstancedPointSpriteEmulation(
455 renderer->getWorkarounds().useInstancedPointSpriteEmulation),
456 mUsesViewScale(renderer->presentPathFastEnabled()),
Martin Radevc1d4e552017-08-21 12:01:10 +0300457 mCanSelectViewInVertexShader(renderer->canSelectViewInVertexShader()),
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800458 mAttachedShaders(attachedShaders)
Jamie Madillb980c562018-11-27 11:34:27 -0500459{}
Jamie Madille39a3f02015-11-17 20:42:15 -0500460
Jamie Madillab2bfa82019-01-15 19:06:47 -0500461ProgramD3DMetadata::~ProgramD3DMetadata() = default;
462
Jamie Madille39a3f02015-11-17 20:42:15 -0500463int ProgramD3DMetadata::getRendererMajorShaderModel() const
464{
465 return mRendererMajorShaderModel;
466}
467
Jamie Madillc3dc5d42018-12-30 12:12:04 -0500468bool ProgramD3DMetadata::usesBroadcast(const gl::State &data) const
Jamie Madille39a3f02015-11-17 20:42:15 -0500469{
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800470 return (mAttachedShaders[gl::ShaderType::Fragment]->usesFragColor() &&
471 mAttachedShaders[gl::ShaderType::Fragment]->usesMultipleRenderTargets() &&
Corentin Wallezc084de12017-06-05 14:28:52 -0700472 data.getClientMajorVersion() < 3);
Jamie Madille39a3f02015-11-17 20:42:15 -0500473}
474
Jamie Madill48ef11b2016-04-27 15:21:52 -0400475bool ProgramD3DMetadata::usesFragDepth() const
Jamie Madille39a3f02015-11-17 20:42:15 -0500476{
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800477 return mAttachedShaders[gl::ShaderType::Fragment]->usesFragDepth();
Jamie Madille39a3f02015-11-17 20:42:15 -0500478}
479
480bool ProgramD3DMetadata::usesPointCoord() const
481{
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800482 return mAttachedShaders[gl::ShaderType::Fragment]->usesPointCoord();
Jamie Madille39a3f02015-11-17 20:42:15 -0500483}
484
485bool ProgramD3DMetadata::usesFragCoord() const
486{
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800487 return mAttachedShaders[gl::ShaderType::Fragment]->usesFragCoord();
Jamie Madille39a3f02015-11-17 20:42:15 -0500488}
489
490bool ProgramD3DMetadata::usesPointSize() const
491{
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800492 return mAttachedShaders[gl::ShaderType::Vertex]->usesPointSize();
Jamie Madille39a3f02015-11-17 20:42:15 -0500493}
494
495bool ProgramD3DMetadata::usesInsertedPointCoordValue() const
496{
Jamie Madillc9bde922016-07-24 17:58:50 -0400497 return (!usesPointSize() || !mUsesInstancedPointSpriteEmulation) && usesPointCoord() &&
498 mRendererMajorShaderModel >= 4;
Jamie Madille39a3f02015-11-17 20:42:15 -0500499}
500
Austin Kinross2a63b3f2016-02-08 12:29:08 -0800501bool ProgramD3DMetadata::usesViewScale() const
502{
503 return mUsesViewScale;
504}
505
Martin Radev41ac68e2017-06-06 12:16:58 +0300506bool ProgramD3DMetadata::hasANGLEMultiviewEnabled() const
507{
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800508 return mAttachedShaders[gl::ShaderType::Vertex]->hasANGLEMultiviewEnabled();
Martin Radev41ac68e2017-06-06 12:16:58 +0300509}
510
511bool ProgramD3DMetadata::usesViewID() const
512{
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800513 return mAttachedShaders[gl::ShaderType::Fragment]->usesViewID();
Martin Radev41ac68e2017-06-06 12:16:58 +0300514}
515
Martin Radevc1d4e552017-08-21 12:01:10 +0300516bool ProgramD3DMetadata::canSelectViewInVertexShader() const
517{
518 return mCanSelectViewInVertexShader;
519}
520
Jamie Madille39a3f02015-11-17 20:42:15 -0500521bool ProgramD3DMetadata::addsPointCoordToVertexShader() const
522{
Jamie Madillc9bde922016-07-24 17:58:50 -0400523 // PointSprite emulation requiress that gl_PointCoord is present in the vertex shader
Jamie Madille39a3f02015-11-17 20:42:15 -0500524 // VS_OUTPUT structure to ensure compatibility with the generated PS_INPUT of the pixel shader.
Jamie Madillc9bde922016-07-24 17:58:50 -0400525 // Even with a geometry shader, the app can render triangles or lines and reference
526 // gl_PointCoord in the fragment shader, requiring us to provide a dummy value. For
527 // simplicity, we always add this to the vertex shader when the fragment shader
528 // references gl_PointCoord, even if we could skip it in the geometry shader.
Jamie Madille39a3f02015-11-17 20:42:15 -0500529 return (mUsesInstancedPointSpriteEmulation && usesPointCoord()) ||
530 usesInsertedPointCoordValue();
531}
532
533bool ProgramD3DMetadata::usesTransformFeedbackGLPosition() const
534{
535 // gl_Position only needs to be outputted from the vertex shader if transform feedback is
536 // active. This isn't supported on D3D11 Feature Level 9_3, so we don't output gl_Position from
537 // the vertex shader in this case. This saves us 1 output vector.
538 return !(mRendererMajorShaderModel >= 4 && mShaderModelSuffix != "");
539}
540
541bool ProgramD3DMetadata::usesSystemValuePointSize() const
542{
543 return !mUsesInstancedPointSpriteEmulation && usesPointSize();
544}
545
546bool ProgramD3DMetadata::usesMultipleFragmentOuts() const
547{
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800548 return mAttachedShaders[gl::ShaderType::Fragment]->usesMultipleRenderTargets();
Jamie Madille39a3f02015-11-17 20:42:15 -0500549}
550
551GLint ProgramD3DMetadata::getMajorShaderVersion() const
552{
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800553 return mAttachedShaders[gl::ShaderType::Vertex]->getData().getShaderVersion();
Jamie Madille39a3f02015-11-17 20:42:15 -0500554}
555
556const ShaderD3D *ProgramD3DMetadata::getFragmentShader() const
557{
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800558 return mAttachedShaders[gl::ShaderType::Fragment];
Jamie Madille39a3f02015-11-17 20:42:15 -0500559}
560
Jamie Madill28afae52015-11-09 15:07:57 -0500561// ProgramD3D Implementation
562
Jamie Madilld3dfda22015-07-06 08:28:49 -0400563ProgramD3D::VertexExecutable::VertexExecutable(const gl::InputLayout &inputLayout,
564 const Signature &signature,
Geoff Lang359ef262015-01-05 14:42:29 -0500565 ShaderExecutableD3D *shaderExecutable)
Jamie Madill334d6152015-10-22 14:00:28 -0400566 : mInputs(inputLayout), mSignature(signature), mShaderExecutable(shaderExecutable)
Jamie Madillb980c562018-11-27 11:34:27 -0500567{}
Brandon Joneseb994362014-09-24 10:27:28 -0700568
569ProgramD3D::VertexExecutable::~VertexExecutable()
570{
571 SafeDelete(mShaderExecutable);
572}
573
Jamie Madilld3dfda22015-07-06 08:28:49 -0400574// static
Jamie Madillbdec2f42016-03-02 16:35:32 -0500575ProgramD3D::VertexExecutable::HLSLAttribType ProgramD3D::VertexExecutable::GetAttribType(
576 GLenum type)
577{
578 switch (type)
579 {
580 case GL_INT:
581 return HLSLAttribType::SIGNED_INT;
582 case GL_UNSIGNED_INT:
583 return HLSLAttribType::UNSIGNED_INT;
584 case GL_SIGNED_NORMALIZED:
585 case GL_UNSIGNED_NORMALIZED:
586 case GL_FLOAT:
587 return HLSLAttribType::FLOAT;
588 default:
589 UNREACHABLE();
590 return HLSLAttribType::FLOAT;
591 }
592}
593
594// static
Jamie Madilld3dfda22015-07-06 08:28:49 -0400595void ProgramD3D::VertexExecutable::getSignature(RendererD3D *renderer,
596 const gl::InputLayout &inputLayout,
597 Signature *signatureOut)
Brandon Joneseb994362014-09-24 10:27:28 -0700598{
Jamie Madillbdec2f42016-03-02 16:35:32 -0500599 signatureOut->assign(inputLayout.size(), HLSLAttribType::FLOAT);
Jamie Madilld3dfda22015-07-06 08:28:49 -0400600
601 for (size_t index = 0; index < inputLayout.size(); ++index)
Brandon Joneseb994362014-09-24 10:27:28 -0700602 {
Frank Henigmand633b152018-10-04 23:34:31 -0400603 angle::FormatID vertexFormatID = inputLayout[index];
604 if (vertexFormatID == angle::FormatID::NONE)
Jamie Madillbdec2f42016-03-02 16:35:32 -0500605 continue;
Jamie Madillbd136f92015-08-10 14:51:37 -0400606
Frank Henigmand633b152018-10-04 23:34:31 -0400607 VertexConversionType conversionType = renderer->getVertexConversionType(vertexFormatID);
Jamie Madillbdec2f42016-03-02 16:35:32 -0500608 if ((conversionType & VERTEX_CONVERT_GPU) == 0)
609 continue;
610
Frank Henigmand633b152018-10-04 23:34:31 -0400611 GLenum componentType = renderer->getVertexComponentType(vertexFormatID);
Jamie Madillbdec2f42016-03-02 16:35:32 -0500612 (*signatureOut)[index] = GetAttribType(componentType);
Brandon Joneseb994362014-09-24 10:27:28 -0700613 }
Brandon Joneseb994362014-09-24 10:27:28 -0700614}
615
Jamie Madilld3dfda22015-07-06 08:28:49 -0400616bool ProgramD3D::VertexExecutable::matchesSignature(const Signature &signature) const
617{
Jamie Madillbd136f92015-08-10 14:51:37 -0400618 size_t limit = std::max(mSignature.size(), signature.size());
619 for (size_t index = 0; index < limit; ++index)
620 {
Jamie Madillbdec2f42016-03-02 16:35:32 -0500621 // treat undefined indexes as FLOAT
622 auto a = index < signature.size() ? signature[index] : HLSLAttribType::FLOAT;
623 auto b = index < mSignature.size() ? mSignature[index] : HLSLAttribType::FLOAT;
Jamie Madillbd136f92015-08-10 14:51:37 -0400624 if (a != b)
625 return false;
626 }
627
628 return true;
Jamie Madilld3dfda22015-07-06 08:28:49 -0400629}
630
631ProgramD3D::PixelExecutable::PixelExecutable(const std::vector<GLenum> &outputSignature,
632 ShaderExecutableD3D *shaderExecutable)
Jamie Madill334d6152015-10-22 14:00:28 -0400633 : mOutputSignature(outputSignature), mShaderExecutable(shaderExecutable)
Jamie Madillb980c562018-11-27 11:34:27 -0500634{}
Brandon Joneseb994362014-09-24 10:27:28 -0700635
636ProgramD3D::PixelExecutable::~PixelExecutable()
637{
638 SafeDelete(mShaderExecutable);
639}
640
Xinghua Caof3179a62018-07-12 16:22:06 +0800641ProgramD3D::ComputeExecutable::ComputeExecutable(
642 const gl::ImageUnitTextureTypeMap &signature,
643 std::unique_ptr<ShaderExecutableD3D> shaderExecutable)
644 : mSignature(signature), mShaderExecutable(std::move(shaderExecutable))
645{}
646
647ProgramD3D::ComputeExecutable::~ComputeExecutable() {}
648
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800649ProgramD3D::Sampler::Sampler()
650 : active(false), logicalTextureUnit(0), textureType(gl::TextureType::_2D)
Jamie Madillb980c562018-11-27 11:34:27 -0500651{}
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700652
Jamie Madillb980c562018-11-27 11:34:27 -0500653ProgramD3D::Image::Image() : active(false), logicalImageUnit(0) {}
Xinghua Cao26143fd2017-11-01 18:19:05 +0800654
Geoff Lang7dd2e102014-11-10 15:19:26 -0500655unsigned int ProgramD3D::mCurrentSerial = 1;
656
Jamie Madill48ef11b2016-04-27 15:21:52 -0400657ProgramD3D::ProgramD3D(const gl::ProgramState &state, RendererD3D *renderer)
658 : ProgramImpl(state),
Brandon Jonesc9610c52014-08-25 17:02:59 -0700659 mRenderer(renderer),
Xinghua Caob1239382016-12-13 15:07:05 +0800660 mDynamicHLSL(nullptr),
Brandon Jones44151a92014-09-10 11:32:25 -0700661 mUsesPointSize(false),
Jamie Madill3e14e2b2015-10-29 14:38:53 -0400662 mUsesFlatInterpolation(false),
Jiawei Shao467c15f2018-04-24 15:04:26 +0800663 mUsedShaderSamplerRanges({}),
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700664 mDirtySamplerMapping(true),
Xinghua Cao6dfdca82018-08-03 17:10:55 +0800665 mUsedComputeImageRange(0, 0),
666 mUsedComputeReadonlyImageRange(0, 0),
Jiawei Shao3dd8d2912018-03-30 09:39:09 +0800667 mSerial(issueSerial())
Brandon Jonesc9610c52014-08-25 17:02:59 -0700668{
Brandon Joneseb994362014-09-24 10:27:28 -0700669 mDynamicHLSL = new DynamicHLSL(renderer);
Brandon Jonesc9610c52014-08-25 17:02:59 -0700670}
671
672ProgramD3D::~ProgramD3D()
673{
674 reset();
675 SafeDelete(mDynamicHLSL);
676}
677
Brandon Jones44151a92014-09-10 11:32:25 -0700678bool ProgramD3D::usesPointSpriteEmulation() const
679{
680 return mUsesPointSize && mRenderer->getMajorShaderModel() >= 4;
681}
682
Martin Radev41ac68e2017-06-06 12:16:58 +0300683bool ProgramD3D::usesGeometryShaderForPointSpriteEmulation() const
684{
685 return usesPointSpriteEmulation() && !usesInstancedPointSpriteEmulation();
686}
687
Jamie Madill493f9572018-05-24 19:52:15 -0400688bool ProgramD3D::usesGeometryShader(gl::PrimitiveMode drawMode) const
Brandon Jones44151a92014-09-10 11:32:25 -0700689{
Martin Radevc1d4e552017-08-21 12:01:10 +0300690 if (mHasANGLEMultiviewEnabled && !mRenderer->canSelectViewInVertexShader())
Martin Radev41ac68e2017-06-06 12:16:58 +0300691 {
692 return true;
693 }
Jamie Madill493f9572018-05-24 19:52:15 -0400694 if (drawMode != gl::PrimitiveMode::Points)
Jamie Madill3e14e2b2015-10-29 14:38:53 -0400695 {
696 return mUsesFlatInterpolation;
697 }
Martin Radev41ac68e2017-06-06 12:16:58 +0300698 return usesGeometryShaderForPointSpriteEmulation();
Cooper Partine6664f02015-01-09 16:22:24 -0800699}
700
701bool ProgramD3D::usesInstancedPointSpriteEmulation() const
702{
703 return mRenderer->getWorkarounds().useInstancedPointSpriteEmulation;
Brandon Jones44151a92014-09-10 11:32:25 -0700704}
705
Xinghua Cao37584b32017-12-01 11:04:03 +0800706GLint ProgramD3D::getSamplerMapping(gl::ShaderType type,
Jamie Madill334d6152015-10-22 14:00:28 -0400707 unsigned int samplerIndex,
708 const gl::Caps &caps) const
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700709{
710 GLint logicalTextureUnit = -1;
711
Jiawei Shao467c15f2018-04-24 15:04:26 +0800712 ASSERT(type != gl::ShaderType::InvalidEnum);
713
Jiawei Shao54aafe52018-04-27 14:54:57 +0800714 ASSERT(samplerIndex < caps.maxShaderTextureImageUnits[type]);
Jiawei Shao467c15f2018-04-24 15:04:26 +0800715
716 const auto &samplers = mShaderSamplers[type];
717 if (samplerIndex < samplers.size() && samplers[samplerIndex].active)
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700718 {
Jiawei Shao467c15f2018-04-24 15:04:26 +0800719 logicalTextureUnit = samplers[samplerIndex].logicalTextureUnit;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700720 }
721
Jamie Madill334d6152015-10-22 14:00:28 -0400722 if (logicalTextureUnit >= 0 &&
723 logicalTextureUnit < static_cast<GLint>(caps.maxCombinedTextureImageUnits))
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700724 {
725 return logicalTextureUnit;
726 }
727
728 return -1;
729}
730
731// Returns the texture type for a given Direct3D 9 sampler type and
732// index (0-15 for the pixel shader and 0-3 for the vertex shader).
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800733gl::TextureType ProgramD3D::getSamplerTextureType(gl::ShaderType type,
734 unsigned int samplerIndex) const
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700735{
Jiawei Shao467c15f2018-04-24 15:04:26 +0800736 ASSERT(type != gl::ShaderType::InvalidEnum);
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700737
Jiawei Shao467c15f2018-04-24 15:04:26 +0800738 const auto &samplers = mShaderSamplers[type];
739 ASSERT(samplerIndex < samplers.size());
740 ASSERT(samplers[samplerIndex].active);
741
742 return samplers[samplerIndex].textureType;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700743}
744
Xinghua Cao6dfdca82018-08-03 17:10:55 +0800745gl::RangeUI ProgramD3D::getUsedSamplerRange(gl::ShaderType type) const
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700746{
Jiawei Shao467c15f2018-04-24 15:04:26 +0800747 ASSERT(type != gl::ShaderType::InvalidEnum);
748 return mUsedShaderSamplerRanges[type];
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700749}
750
Jamie Madillaf4ffe02017-09-09 23:32:48 -0400751ProgramD3D::SamplerMapping ProgramD3D::updateSamplerMapping()
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700752{
753 if (!mDirtySamplerMapping)
754 {
Jamie Madillaf4ffe02017-09-09 23:32:48 -0400755 return SamplerMapping::WasClean;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700756 }
757
758 mDirtySamplerMapping = false;
759
760 // Retrieve sampler uniform values
Jamie Madill62d31cb2015-09-11 13:25:51 -0400761 for (const D3DUniform *d3dUniform : mD3DUniforms)
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700762 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400763 if (!d3dUniform->isSampler())
764 continue;
765
Olli Etuaho465835d2017-09-26 13:34:10 +0300766 int count = d3dUniform->getArraySizeProduct();
Jamie Madill62d31cb2015-09-11 13:25:51 -0400767
Jiawei Shao467c15f2018-04-24 15:04:26 +0800768 for (gl::ShaderType shaderType : gl::AllShaderTypes())
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700769 {
Jiawei Shao467c15f2018-04-24 15:04:26 +0800770 if (!d3dUniform->isReferencedByShader(shaderType))
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700771 {
Jiawei Shao467c15f2018-04-24 15:04:26 +0800772 continue;
Jamie Madill62d31cb2015-09-11 13:25:51 -0400773 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700774
Jiawei Shao467c15f2018-04-24 15:04:26 +0800775 unsigned int firstIndex = d3dUniform->mShaderRegisterIndexes[shaderType];
Jamie Madill62d31cb2015-09-11 13:25:51 -0400776
Jiawei Shao467c15f2018-04-24 15:04:26 +0800777 std::vector<Sampler> &samplers = mShaderSamplers[shaderType];
Jamie Madill62d31cb2015-09-11 13:25:51 -0400778 for (int i = 0; i < count; i++)
779 {
780 unsigned int samplerIndex = firstIndex + i;
781
Jiawei Shao467c15f2018-04-24 15:04:26 +0800782 if (samplerIndex < samplers.size())
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700783 {
Jiawei Shao467c15f2018-04-24 15:04:26 +0800784 ASSERT(samplers[samplerIndex].active);
785 samplers[samplerIndex].logicalTextureUnit = d3dUniform->mSamplerData[i];
Xinghua Caob1239382016-12-13 15:07:05 +0800786 }
787 }
788 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700789 }
Jamie Madillaf4ffe02017-09-09 23:32:48 -0400790
791 return SamplerMapping::WasDirty;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700792}
793
Xinghua Cao26143fd2017-11-01 18:19:05 +0800794GLint ProgramD3D::getImageMapping(gl::ShaderType type,
795 unsigned int imageIndex,
796 bool readonly,
797 const gl::Caps &caps) const
798{
799 GLint logicalImageUnit = -1;
800 ASSERT(imageIndex < caps.maxImageUnits);
801 switch (type)
802 {
Jiawei Shao385b3e02018-03-21 09:43:28 +0800803 case gl::ShaderType::Compute:
Xinghua Cao26143fd2017-11-01 18:19:05 +0800804 if (readonly && imageIndex < mReadonlyImagesCS.size() &&
805 mReadonlyImagesCS[imageIndex].active)
806 {
807 logicalImageUnit = mReadonlyImagesCS[imageIndex].logicalImageUnit;
808 }
809 else if (imageIndex < mImagesCS.size() && mImagesCS[imageIndex].active)
810 {
811 logicalImageUnit = mImagesCS[imageIndex].logicalImageUnit;
812 }
813 break;
814 // TODO(xinghua.cao@intel.com): add image mapping for vertex shader and pixel shader.
815 default:
816 UNREACHABLE();
817 }
818
819 if (logicalImageUnit >= 0 && logicalImageUnit < static_cast<GLint>(caps.maxImageUnits))
820 {
821 return logicalImageUnit;
822 }
823
824 return -1;
825}
826
Xinghua Cao6dfdca82018-08-03 17:10:55 +0800827gl::RangeUI ProgramD3D::getUsedImageRange(gl::ShaderType type, bool readonly) const
Xinghua Cao26143fd2017-11-01 18:19:05 +0800828{
829 switch (type)
830 {
Jiawei Shao385b3e02018-03-21 09:43:28 +0800831 case gl::ShaderType::Compute:
Xinghua Cao26143fd2017-11-01 18:19:05 +0800832 return readonly ? mUsedComputeReadonlyImageRange : mUsedComputeImageRange;
Qin Jiajia155bfd12018-08-31 17:27:10 +0800833 // TODO(xinghua.cao@intel.com): add real image range of vertex shader and pixel shader.
834 case gl::ShaderType::Vertex:
835 case gl::ShaderType::Fragment:
836 return {0, 0};
Xinghua Cao26143fd2017-11-01 18:19:05 +0800837 default:
838 UNREACHABLE();
Xinghua Cao6dfdca82018-08-03 17:10:55 +0800839 return {0, 0};
Xinghua Cao26143fd2017-11-01 18:19:05 +0800840 }
841}
842
Jamie Madill785e8a02018-10-04 17:42:00 -0400843angle::Result ProgramD3D::load(const gl::Context *context,
844 gl::InfoLog &infoLog,
845 gl::BinaryInputStream *stream)
Brandon Jones22502d52014-08-29 16:58:36 -0700846{
Jamie Madilla7d12dc2016-12-13 15:08:19 -0500847 // TODO(jmadill): Use Renderer from contextImpl.
848
Jamie Madill62d31cb2015-09-11 13:25:51 -0400849 reset();
850
Jamie Madill334d6152015-10-22 14:00:28 -0400851 DeviceIdentifier binaryDeviceIdentifier = {0};
852 stream->readBytes(reinterpret_cast<unsigned char *>(&binaryDeviceIdentifier),
853 sizeof(DeviceIdentifier));
Austin Kinross137b1512015-06-17 16:14:53 -0700854
855 DeviceIdentifier identifier = mRenderer->getAdapterIdentifier();
856 if (memcmp(&identifier, &binaryDeviceIdentifier, sizeof(DeviceIdentifier)) != 0)
857 {
858 infoLog << "Invalid program binary, device configuration has changed.";
Jamie Madill7c985f52018-11-29 18:16:17 -0500859 return angle::Result::Incomplete;
Austin Kinross137b1512015-06-17 16:14:53 -0700860 }
861
Jamie Madill2db1fbb2014-12-03 10:58:55 -0500862 int compileFlags = stream->readInt<int>();
863 if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL)
864 {
Jamie Madillf6113162015-05-07 11:49:21 -0400865 infoLog << "Mismatched compilation flags.";
Jamie Madill7c985f52018-11-29 18:16:17 -0500866 return angle::Result::Incomplete;
Jamie Madill2db1fbb2014-12-03 10:58:55 -0500867 }
868
Jamie Madill8047c0d2016-03-07 13:02:12 -0500869 for (int &index : mAttribLocationToD3DSemantic)
Jamie Madill63805b42015-08-25 13:17:39 -0400870 {
Jamie Madill8047c0d2016-03-07 13:02:12 -0500871 stream->readInt(&index);
Jamie Madill63805b42015-08-25 13:17:39 -0400872 }
873
Jiawei Shao467c15f2018-04-24 15:04:26 +0800874 for (gl::ShaderType shaderType : gl::AllShaderTypes())
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700875 {
Jiawei Shao467c15f2018-04-24 15:04:26 +0800876 const unsigned int samplerCount = stream->readInt<unsigned int>();
877 for (unsigned int i = 0; i < samplerCount; ++i)
878 {
879 Sampler sampler;
880 stream->readBool(&sampler.active);
881 stream->readInt(&sampler.logicalTextureUnit);
882 stream->readEnum(&sampler.textureType);
883 mShaderSamplers[shaderType].push_back(sampler);
884 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700885
Xinghua Cao6dfdca82018-08-03 17:10:55 +0800886 unsigned int samplerRangeLow, samplerRangeHigh;
887 stream->readInt(&samplerRangeLow);
888 stream->readInt(&samplerRangeHigh);
889 mUsedShaderSamplerRanges[shaderType] = gl::RangeUI(samplerRangeLow, samplerRangeHigh);
Xinghua Caob1239382016-12-13 15:07:05 +0800890 }
891
Xinghua Cao26143fd2017-11-01 18:19:05 +0800892 const unsigned int csImageCount = stream->readInt<unsigned int>();
893 for (unsigned int i = 0; i < csImageCount; ++i)
894 {
895 Image image;
896 stream->readBool(&image.active);
897 stream->readInt(&image.logicalImageUnit);
898 mImagesCS.push_back(image);
899 }
900
901 const unsigned int csReadonlyImageCount = stream->readInt<unsigned int>();
902 for (unsigned int i = 0; i < csReadonlyImageCount; ++i)
903 {
904 Image image;
905 stream->readBool(&image.active);
906 stream->readInt(&image.logicalImageUnit);
907 mReadonlyImagesCS.push_back(image);
908 }
909
Xinghua Cao6dfdca82018-08-03 17:10:55 +0800910 unsigned int computeImageRangeLow, computeImageRangeHigh, computeReadonlyImageRangeLow,
911 computeReadonlyImageRangeHigh;
912 stream->readInt(&computeImageRangeLow);
913 stream->readInt(&computeImageRangeHigh);
914 stream->readInt(&computeReadonlyImageRangeLow);
915 stream->readInt(&computeReadonlyImageRangeHigh);
916 mUsedComputeImageRange = gl::RangeUI(computeImageRangeLow, computeImageRangeHigh);
917 mUsedComputeReadonlyImageRange =
918 gl::RangeUI(computeReadonlyImageRangeLow, computeReadonlyImageRangeHigh);
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700919
Qin Jiajiaa602f902018-09-11 14:40:24 +0800920 const unsigned int shaderStorageBlockCount = stream->readInt<unsigned int>();
921 if (stream->error())
922 {
923 infoLog << "Invalid program binary.";
Jamie Madill7c985f52018-11-29 18:16:17 -0500924 return angle::Result::Incomplete;
Qin Jiajiaa602f902018-09-11 14:40:24 +0800925 }
926
927 ASSERT(mD3DShaderStorageBlocks.empty());
928 for (unsigned int blockIndex = 0; blockIndex < shaderStorageBlockCount; ++blockIndex)
929 {
930 D3DInterfaceBlock shaderStorageBlock;
931 for (gl::ShaderType shaderType : gl::AllShaderTypes())
932 {
933 stream->readInt(&shaderStorageBlock.mShaderRegisterIndexes[shaderType]);
934 }
935 mD3DShaderStorageBlocks.push_back(shaderStorageBlock);
936 }
937
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700938 const unsigned int uniformCount = stream->readInt<unsigned int>();
939 if (stream->error())
940 {
Jamie Madillf6113162015-05-07 11:49:21 -0400941 infoLog << "Invalid program binary.";
Jamie Madill7c985f52018-11-29 18:16:17 -0500942 return angle::Result::Incomplete;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700943 }
944
Jamie Madill48ef11b2016-04-27 15:21:52 -0400945 const auto &linkedUniforms = mState.getUniforms();
Jamie Madill62d31cb2015-09-11 13:25:51 -0400946 ASSERT(mD3DUniforms.empty());
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700947 for (unsigned int uniformIndex = 0; uniformIndex < uniformCount; uniformIndex++)
948 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400949 const gl::LinkedUniform &linkedUniform = linkedUniforms[uniformIndex];
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700950
Jamie Madill62d31cb2015-09-11 13:25:51 -0400951 D3DUniform *d3dUniform =
Xinghua Cao26143fd2017-11-01 18:19:05 +0800952 new D3DUniform(linkedUniform.type, HLSLRegisterType::None, linkedUniform.name,
953 linkedUniform.arraySizes, linkedUniform.isInDefaultBlock());
954 stream->readInt<HLSLRegisterType>(&d3dUniform->regType);
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800955 for (gl::ShaderType shaderType : gl::AllShaderTypes())
956 {
957 stream->readInt(&d3dUniform->mShaderRegisterIndexes[shaderType]);
958 }
Jamie Madill62d31cb2015-09-11 13:25:51 -0400959 stream->readInt(&d3dUniform->registerCount);
960 stream->readInt(&d3dUniform->registerElement);
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700961
Jamie Madill62d31cb2015-09-11 13:25:51 -0400962 mD3DUniforms.push_back(d3dUniform);
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700963 }
964
Jamie Madill4a3c2342015-10-08 12:58:45 -0400965 const unsigned int blockCount = stream->readInt<unsigned int>();
966 if (stream->error())
967 {
968 infoLog << "Invalid program binary.";
Jamie Madill7c985f52018-11-29 18:16:17 -0500969 return angle::Result::Incomplete;
Jamie Madill4a3c2342015-10-08 12:58:45 -0400970 }
971
972 ASSERT(mD3DUniformBlocks.empty());
973 for (unsigned int blockIndex = 0; blockIndex < blockCount; ++blockIndex)
974 {
Qin Jiajiaa602f902018-09-11 14:40:24 +0800975 D3DInterfaceBlock uniformBlock;
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800976 for (gl::ShaderType shaderType : gl::AllShaderTypes())
977 {
978 stream->readInt(&uniformBlock.mShaderRegisterIndexes[shaderType]);
979 }
Jamie Madill4a3c2342015-10-08 12:58:45 -0400980 mD3DUniformBlocks.push_back(uniformBlock);
981 }
982
Jamie Madill9fc36822015-11-18 13:08:07 -0500983 const unsigned int streamOutVaryingCount = stream->readInt<unsigned int>();
984 mStreamOutVaryings.resize(streamOutVaryingCount);
985 for (unsigned int varyingIndex = 0; varyingIndex < streamOutVaryingCount; ++varyingIndex)
Brandon Joneseb994362014-09-24 10:27:28 -0700986 {
Jamie Madill9fc36822015-11-18 13:08:07 -0500987 D3DVarying *varying = &mStreamOutVaryings[varyingIndex];
Brandon Joneseb994362014-09-24 10:27:28 -0700988
Jamie Madill28afae52015-11-09 15:07:57 -0500989 stream->readString(&varying->semanticName);
990 stream->readInt(&varying->semanticIndex);
Jamie Madill9fc36822015-11-18 13:08:07 -0500991 stream->readInt(&varying->componentCount);
992 stream->readInt(&varying->outputSlot);
Brandon Joneseb994362014-09-24 10:27:28 -0700993 }
994
Jiawei Shao467c15f2018-04-24 15:04:26 +0800995 for (gl::ShaderType shaderType : gl::AllShaderTypes())
996 {
997 stream->readString(&mShaderHLSL[shaderType]);
998 stream->readBytes(reinterpret_cast<unsigned char *>(&mShaderWorkarounds[shaderType]),
999 sizeof(angle::CompilerWorkaroundsD3D));
1000 }
1001
Brandon Jones22502d52014-08-29 16:58:36 -07001002 stream->readBool(&mUsesFragDepth);
Martin Radev41ac68e2017-06-06 12:16:58 +03001003 stream->readBool(&mHasANGLEMultiviewEnabled);
1004 stream->readBool(&mUsesViewID);
Brandon Jones44151a92014-09-10 11:32:25 -07001005 stream->readBool(&mUsesPointSize);
Jamie Madill3e14e2b2015-10-29 14:38:53 -04001006 stream->readBool(&mUsesFlatInterpolation);
Brandon Jones22502d52014-08-29 16:58:36 -07001007
1008 const size_t pixelShaderKeySize = stream->readInt<unsigned int>();
1009 mPixelShaderKey.resize(pixelShaderKeySize);
Jamie Madill334d6152015-10-22 14:00:28 -04001010 for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKeySize;
1011 pixelShaderKeyIndex++)
Brandon Jones22502d52014-08-29 16:58:36 -07001012 {
1013 stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].type);
1014 stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].name);
1015 stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].source);
1016 stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].outputIndex);
1017 }
1018
Jamie Madill4e31ad52015-10-29 10:32:57 -04001019 stream->readString(&mGeometryShaderPreamble);
1020
Jamie Madill334d6152015-10-22 14:00:28 -04001021 const unsigned char *binary = reinterpret_cast<const unsigned char *>(stream->data());
Brandon Joneseb994362014-09-24 10:27:28 -07001022
Jamie Madillb0a838b2016-11-13 20:02:12 -05001023 bool separateAttribs = (mState.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS);
1024
Jamie Madill785e8a02018-10-04 17:42:00 -04001025 d3d::Context *contextD3D = GetImplAs<ContextD3D>(context);
1026
Brandon Joneseb994362014-09-24 10:27:28 -07001027 const unsigned int vertexShaderCount = stream->readInt<unsigned int>();
Jamie Madill334d6152015-10-22 14:00:28 -04001028 for (unsigned int vertexShaderIndex = 0; vertexShaderIndex < vertexShaderCount;
1029 vertexShaderIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -07001030 {
Jamie Madilld3dfda22015-07-06 08:28:49 -04001031 size_t inputLayoutSize = stream->readInt<size_t>();
Frank Henigmand633b152018-10-04 23:34:31 -04001032 gl::InputLayout inputLayout(inputLayoutSize, angle::FormatID::NONE);
Brandon Joneseb994362014-09-24 10:27:28 -07001033
Jamie Madilld3dfda22015-07-06 08:28:49 -04001034 for (size_t inputIndex = 0; inputIndex < inputLayoutSize; inputIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -07001035 {
Frank Henigmand633b152018-10-04 23:34:31 -04001036 inputLayout[inputIndex] = stream->readInt<angle::FormatID>();
Brandon Joneseb994362014-09-24 10:27:28 -07001037 }
1038
Jamie Madill334d6152015-10-22 14:00:28 -04001039 unsigned int vertexShaderSize = stream->readInt<unsigned int>();
Brandon Joneseb994362014-09-24 10:27:28 -07001040 const unsigned char *vertexShaderFunction = binary + stream->offset();
Geoff Langb543aff2014-09-30 14:52:54 -04001041
Jamie Madillada9ecc2015-08-17 12:53:37 -04001042 ShaderExecutableD3D *shaderExecutable = nullptr;
1043
Jamie Madill785e8a02018-10-04 17:42:00 -04001044 ANGLE_TRY(mRenderer->loadExecutable(contextD3D, vertexShaderFunction, vertexShaderSize,
Jiawei Shao385b3e02018-03-21 09:43:28 +08001045 gl::ShaderType::Vertex, mStreamOutVaryings,
1046 separateAttribs, &shaderExecutable));
Geoff Langb543aff2014-09-30 14:52:54 -04001047
Brandon Joneseb994362014-09-24 10:27:28 -07001048 if (!shaderExecutable)
1049 {
Jamie Madillf6113162015-05-07 11:49:21 -04001050 infoLog << "Could not create vertex shader.";
Jamie Madill7c985f52018-11-29 18:16:17 -05001051 return angle::Result::Incomplete;
Brandon Joneseb994362014-09-24 10:27:28 -07001052 }
1053
1054 // generated converted input layout
Jamie Madilld3dfda22015-07-06 08:28:49 -04001055 VertexExecutable::Signature signature;
1056 VertexExecutable::getSignature(mRenderer, inputLayout, &signature);
Brandon Joneseb994362014-09-24 10:27:28 -07001057
1058 // add new binary
Xinghua Caob1239382016-12-13 15:07:05 +08001059 mVertexExecutables.push_back(std::unique_ptr<VertexExecutable>(
1060 new VertexExecutable(inputLayout, signature, shaderExecutable)));
Brandon Joneseb994362014-09-24 10:27:28 -07001061
1062 stream->skip(vertexShaderSize);
1063 }
1064
1065 const size_t pixelShaderCount = stream->readInt<unsigned int>();
1066 for (size_t pixelShaderIndex = 0; pixelShaderIndex < pixelShaderCount; pixelShaderIndex++)
1067 {
1068 const size_t outputCount = stream->readInt<unsigned int>();
1069 std::vector<GLenum> outputs(outputCount);
1070 for (size_t outputIndex = 0; outputIndex < outputCount; outputIndex++)
1071 {
1072 stream->readInt(&outputs[outputIndex]);
1073 }
1074
Jamie Madill334d6152015-10-22 14:00:28 -04001075 const size_t pixelShaderSize = stream->readInt<unsigned int>();
Brandon Joneseb994362014-09-24 10:27:28 -07001076 const unsigned char *pixelShaderFunction = binary + stream->offset();
Jamie Madillada9ecc2015-08-17 12:53:37 -04001077 ShaderExecutableD3D *shaderExecutable = nullptr;
1078
Jamie Madill785e8a02018-10-04 17:42:00 -04001079 ANGLE_TRY(mRenderer->loadExecutable(contextD3D, pixelShaderFunction, pixelShaderSize,
Jiawei Shao385b3e02018-03-21 09:43:28 +08001080 gl::ShaderType::Fragment, mStreamOutVaryings,
Yunchao He85072e82017-11-14 15:43:28 +08001081 separateAttribs, &shaderExecutable));
Brandon Joneseb994362014-09-24 10:27:28 -07001082
1083 if (!shaderExecutable)
1084 {
Jamie Madillf6113162015-05-07 11:49:21 -04001085 infoLog << "Could not create pixel shader.";
Jamie Madill7c985f52018-11-29 18:16:17 -05001086 return angle::Result::Incomplete;
Brandon Joneseb994362014-09-24 10:27:28 -07001087 }
1088
1089 // add new binary
Xinghua Caob1239382016-12-13 15:07:05 +08001090 mPixelExecutables.push_back(
1091 std::unique_ptr<PixelExecutable>(new PixelExecutable(outputs, shaderExecutable)));
Brandon Joneseb994362014-09-24 10:27:28 -07001092
1093 stream->skip(pixelShaderSize);
1094 }
1095
Jamie Madill04796cd2018-05-24 19:52:16 -04001096 for (auto &geometryExe : mGeometryExecutables)
Brandon Joneseb994362014-09-24 10:27:28 -07001097 {
Jamie Madill4e31ad52015-10-29 10:32:57 -04001098 unsigned int geometryShaderSize = stream->readInt<unsigned int>();
1099 if (geometryShaderSize == 0)
1100 {
Jamie Madill4e31ad52015-10-29 10:32:57 -04001101 continue;
1102 }
1103
Brandon Joneseb994362014-09-24 10:27:28 -07001104 const unsigned char *geometryShaderFunction = binary + stream->offset();
Jamie Madill4e31ad52015-10-29 10:32:57 -04001105
Xinghua Caob1239382016-12-13 15:07:05 +08001106 ShaderExecutableD3D *geometryExecutable = nullptr;
Jamie Madill785e8a02018-10-04 17:42:00 -04001107 ANGLE_TRY(mRenderer->loadExecutable(contextD3D, geometryShaderFunction, geometryShaderSize,
Jiawei Shao385b3e02018-03-21 09:43:28 +08001108 gl::ShaderType::Geometry, mStreamOutVaryings,
Yunchao He85072e82017-11-14 15:43:28 +08001109 separateAttribs, &geometryExecutable));
Brandon Joneseb994362014-09-24 10:27:28 -07001110
Xinghua Caob1239382016-12-13 15:07:05 +08001111 if (!geometryExecutable)
Brandon Joneseb994362014-09-24 10:27:28 -07001112 {
Jamie Madillf6113162015-05-07 11:49:21 -04001113 infoLog << "Could not create geometry shader.";
Jamie Madill7c985f52018-11-29 18:16:17 -05001114 return angle::Result::Incomplete;
Brandon Joneseb994362014-09-24 10:27:28 -07001115 }
Xinghua Caob1239382016-12-13 15:07:05 +08001116
Jamie Madill04796cd2018-05-24 19:52:16 -04001117 geometryExe.reset(geometryExecutable);
Xinghua Caob1239382016-12-13 15:07:05 +08001118
Brandon Joneseb994362014-09-24 10:27:28 -07001119 stream->skip(geometryShaderSize);
1120 }
1121
Xinghua Caof3179a62018-07-12 16:22:06 +08001122 const size_t computeShaderCount = stream->readInt<unsigned int>();
1123 for (size_t computeShaderIndex = 0; computeShaderIndex < computeShaderCount;
1124 computeShaderIndex++)
Xinghua Caob1239382016-12-13 15:07:05 +08001125 {
Xinghua Caof3179a62018-07-12 16:22:06 +08001126 const size_t signatureCount = stream->readInt<unsigned int>();
1127 gl::ImageUnitTextureTypeMap signatures;
1128 for (size_t signatureIndex = 0; signatureIndex < signatureCount; signatureIndex++)
1129 {
1130 unsigned int imageUint;
1131 gl::TextureType textureType;
1132 stream->readInt<unsigned int>(&imageUint);
1133 stream->readInt<gl::TextureType>(&textureType);
1134 signatures.insert(std::pair<unsigned int, gl::TextureType>(imageUint, textureType));
1135 }
1136
1137 const size_t computeShaderSize = stream->readInt<unsigned int>();
Xinghua Caob1239382016-12-13 15:07:05 +08001138 const unsigned char *computeShaderFunction = binary + stream->offset();
1139
1140 ShaderExecutableD3D *computeExecutable = nullptr;
Jamie Madill785e8a02018-10-04 17:42:00 -04001141 ANGLE_TRY(mRenderer->loadExecutable(contextD3D, computeShaderFunction, computeShaderSize,
Jiawei Shao385b3e02018-03-21 09:43:28 +08001142 gl::ShaderType::Compute, std::vector<D3DVarying>(),
1143 false, &computeExecutable));
Xinghua Caob1239382016-12-13 15:07:05 +08001144
1145 if (!computeExecutable)
1146 {
1147 infoLog << "Could not create compute shader.";
Jamie Madill7c985f52018-11-29 18:16:17 -05001148 return angle::Result::Incomplete;
Xinghua Caob1239382016-12-13 15:07:05 +08001149 }
1150
Xinghua Caof3179a62018-07-12 16:22:06 +08001151 // add new binary
1152 mComputeExecutables.push_back(std::unique_ptr<ComputeExecutable>(new ComputeExecutable(
1153 signatures, std::unique_ptr<ShaderExecutableD3D>(computeExecutable))));
1154
1155 stream->skip(computeShaderSize);
1156 }
1157
1158 const size_t bindLayoutCount = stream->readInt<unsigned int>();
1159 for (size_t bindLayoutIndex = 0; bindLayoutIndex < bindLayoutCount; bindLayoutIndex++)
1160 {
1161 mComputeShaderImage2DBindLayoutCache.insert(std::pair<unsigned int, gl::TextureType>(
1162 stream->readInt<unsigned int>(), gl::TextureType::_2D));
Xinghua Caob1239382016-12-13 15:07:05 +08001163 }
1164
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08001165 initializeUniformStorage(mState.getLinkedShaderStages());
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001166
Jiawei Shao3dd8d2912018-03-30 09:39:09 +08001167 dirtyAllUniforms();
1168
Jamie Madill7c985f52018-11-29 18:16:17 -05001169 return angle::Result::Continue;
Brandon Jones22502d52014-08-29 16:58:36 -07001170}
1171
Jamie Madill27a60632017-06-30 15:12:01 -04001172void ProgramD3D::save(const gl::Context *context, gl::BinaryOutputStream *stream)
Brandon Jones22502d52014-08-29 16:58:36 -07001173{
Austin Kinross137b1512015-06-17 16:14:53 -07001174 // Output the DeviceIdentifier before we output any shader code
Jamie Madill334d6152015-10-22 14:00:28 -04001175 // When we load the binary again later, we can validate the device identifier before trying to
1176 // compile any HLSL
Austin Kinross137b1512015-06-17 16:14:53 -07001177 DeviceIdentifier binaryIdentifier = mRenderer->getAdapterIdentifier();
Jamie Madill334d6152015-10-22 14:00:28 -04001178 stream->writeBytes(reinterpret_cast<unsigned char *>(&binaryIdentifier),
1179 sizeof(DeviceIdentifier));
Austin Kinross137b1512015-06-17 16:14:53 -07001180
Jamie Madill2db1fbb2014-12-03 10:58:55 -05001181 stream->writeInt(ANGLE_COMPILE_OPTIMIZATION_LEVEL);
1182
Jamie Madill8047c0d2016-03-07 13:02:12 -05001183 for (int d3dSemantic : mAttribLocationToD3DSemantic)
Jamie Madill63805b42015-08-25 13:17:39 -04001184 {
Jamie Madill8047c0d2016-03-07 13:02:12 -05001185 stream->writeInt(d3dSemantic);
Jamie Madill63805b42015-08-25 13:17:39 -04001186 }
1187
Jiawei Shao467c15f2018-04-24 15:04:26 +08001188 for (gl::ShaderType shaderType : gl::AllShaderTypes())
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001189 {
Jiawei Shao467c15f2018-04-24 15:04:26 +08001190 stream->writeInt(mShaderSamplers[shaderType].size());
1191 for (unsigned int i = 0; i < mShaderSamplers[shaderType].size(); ++i)
1192 {
1193 stream->writeInt(mShaderSamplers[shaderType][i].active);
1194 stream->writeInt(mShaderSamplers[shaderType][i].logicalTextureUnit);
1195 stream->writeEnum(mShaderSamplers[shaderType][i].textureType);
1196 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001197
Xinghua Cao6dfdca82018-08-03 17:10:55 +08001198 stream->writeInt(mUsedShaderSamplerRanges[shaderType].low());
1199 stream->writeInt(mUsedShaderSamplerRanges[shaderType].high());
Xinghua Caob1239382016-12-13 15:07:05 +08001200 }
1201
Xinghua Cao26143fd2017-11-01 18:19:05 +08001202 stream->writeInt(mImagesCS.size());
1203 for (unsigned int i = 0; i < mImagesCS.size(); ++i)
1204 {
1205 stream->writeInt(mImagesCS[i].active);
1206 stream->writeInt(mImagesCS[i].logicalImageUnit);
1207 }
1208
1209 stream->writeInt(mReadonlyImagesCS.size());
1210 for (unsigned int i = 0; i < mReadonlyImagesCS.size(); ++i)
1211 {
1212 stream->writeInt(mReadonlyImagesCS[i].active);
1213 stream->writeInt(mReadonlyImagesCS[i].logicalImageUnit);
1214 }
1215
Xinghua Cao6dfdca82018-08-03 17:10:55 +08001216 stream->writeInt(mUsedComputeImageRange.low());
1217 stream->writeInt(mUsedComputeImageRange.high());
1218 stream->writeInt(mUsedComputeReadonlyImageRange.low());
1219 stream->writeInt(mUsedComputeReadonlyImageRange.high());
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001220
Qin Jiajiaa602f902018-09-11 14:40:24 +08001221 stream->writeInt(mD3DShaderStorageBlocks.size());
1222 for (const D3DInterfaceBlock &shaderStorageBlock : mD3DShaderStorageBlocks)
1223 {
1224 for (gl::ShaderType shaderType : gl::AllShaderTypes())
1225 {
1226 stream->writeIntOrNegOne(shaderStorageBlock.mShaderRegisterIndexes[shaderType]);
1227 }
1228 }
1229
Jamie Madill62d31cb2015-09-11 13:25:51 -04001230 stream->writeInt(mD3DUniforms.size());
Jamie Madill4a3c2342015-10-08 12:58:45 -04001231 for (const D3DUniform *uniform : mD3DUniforms)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001232 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001233 // Type, name and arraySize are redundant, so aren't stored in the binary.
Xinghua Cao26143fd2017-11-01 18:19:05 +08001234 stream->writeInt(static_cast<unsigned int>(uniform->regType));
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08001235 for (gl::ShaderType shaderType : gl::AllShaderTypes())
1236 {
1237 stream->writeIntOrNegOne(uniform->mShaderRegisterIndexes[shaderType]);
1238 }
Jamie Madill4a3c2342015-10-08 12:58:45 -04001239 stream->writeInt(uniform->registerCount);
1240 stream->writeInt(uniform->registerElement);
1241 }
1242
1243 stream->writeInt(mD3DUniformBlocks.size());
Qin Jiajiaa602f902018-09-11 14:40:24 +08001244 for (const D3DInterfaceBlock &uniformBlock : mD3DUniformBlocks)
Jamie Madill4a3c2342015-10-08 12:58:45 -04001245 {
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08001246 for (gl::ShaderType shaderType : gl::AllShaderTypes())
1247 {
1248 stream->writeIntOrNegOne(uniformBlock.mShaderRegisterIndexes[shaderType]);
1249 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001250 }
1251
Jamie Madill9fc36822015-11-18 13:08:07 -05001252 stream->writeInt(mStreamOutVaryings.size());
1253 for (const auto &varying : mStreamOutVaryings)
Brandon Joneseb994362014-09-24 10:27:28 -07001254 {
Brandon Joneseb994362014-09-24 10:27:28 -07001255 stream->writeString(varying.semanticName);
1256 stream->writeInt(varying.semanticIndex);
Jamie Madill9fc36822015-11-18 13:08:07 -05001257 stream->writeInt(varying.componentCount);
1258 stream->writeInt(varying.outputSlot);
Brandon Joneseb994362014-09-24 10:27:28 -07001259 }
1260
Jiawei Shao467c15f2018-04-24 15:04:26 +08001261 for (gl::ShaderType shaderType : gl::AllShaderTypes())
1262 {
1263 stream->writeString(mShaderHLSL[shaderType]);
1264 stream->writeBytes(reinterpret_cast<unsigned char *>(&mShaderWorkarounds[shaderType]),
1265 sizeof(angle::CompilerWorkaroundsD3D));
1266 }
1267
Brandon Jones22502d52014-08-29 16:58:36 -07001268 stream->writeInt(mUsesFragDepth);
Martin Radev41ac68e2017-06-06 12:16:58 +03001269 stream->writeInt(mHasANGLEMultiviewEnabled);
1270 stream->writeInt(mUsesViewID);
Brandon Jones44151a92014-09-10 11:32:25 -07001271 stream->writeInt(mUsesPointSize);
Jamie Madill3e14e2b2015-10-29 14:38:53 -04001272 stream->writeInt(mUsesFlatInterpolation);
Brandon Jones22502d52014-08-29 16:58:36 -07001273
Brandon Joneseb994362014-09-24 10:27:28 -07001274 const std::vector<PixelShaderOutputVariable> &pixelShaderKey = mPixelShaderKey;
Brandon Jones22502d52014-08-29 16:58:36 -07001275 stream->writeInt(pixelShaderKey.size());
Jamie Madill334d6152015-10-22 14:00:28 -04001276 for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKey.size();
1277 pixelShaderKeyIndex++)
Brandon Jones22502d52014-08-29 16:58:36 -07001278 {
Brandon Joneseb994362014-09-24 10:27:28 -07001279 const PixelShaderOutputVariable &variable = pixelShaderKey[pixelShaderKeyIndex];
Brandon Jones22502d52014-08-29 16:58:36 -07001280 stream->writeInt(variable.type);
1281 stream->writeString(variable.name);
1282 stream->writeString(variable.source);
1283 stream->writeInt(variable.outputIndex);
1284 }
1285
Jamie Madill4e31ad52015-10-29 10:32:57 -04001286 stream->writeString(mGeometryShaderPreamble);
1287
Brandon Joneseb994362014-09-24 10:27:28 -07001288 stream->writeInt(mVertexExecutables.size());
Jamie Madill334d6152015-10-22 14:00:28 -04001289 for (size_t vertexExecutableIndex = 0; vertexExecutableIndex < mVertexExecutables.size();
1290 vertexExecutableIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -07001291 {
Xinghua Caob1239382016-12-13 15:07:05 +08001292 VertexExecutable *vertexExecutable = mVertexExecutables[vertexExecutableIndex].get();
Brandon Joneseb994362014-09-24 10:27:28 -07001293
Jamie Madilld3dfda22015-07-06 08:28:49 -04001294 const auto &inputLayout = vertexExecutable->inputs();
1295 stream->writeInt(inputLayout.size());
1296
1297 for (size_t inputIndex = 0; inputIndex < inputLayout.size(); inputIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -07001298 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001299 stream->writeInt(static_cast<unsigned int>(inputLayout[inputIndex]));
Brandon Joneseb994362014-09-24 10:27:28 -07001300 }
1301
1302 size_t vertexShaderSize = vertexExecutable->shaderExecutable()->getLength();
1303 stream->writeInt(vertexShaderSize);
1304
1305 const uint8_t *vertexBlob = vertexExecutable->shaderExecutable()->getFunction();
1306 stream->writeBytes(vertexBlob, vertexShaderSize);
1307 }
1308
1309 stream->writeInt(mPixelExecutables.size());
Jamie Madill334d6152015-10-22 14:00:28 -04001310 for (size_t pixelExecutableIndex = 0; pixelExecutableIndex < mPixelExecutables.size();
1311 pixelExecutableIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -07001312 {
Xinghua Caob1239382016-12-13 15:07:05 +08001313 PixelExecutable *pixelExecutable = mPixelExecutables[pixelExecutableIndex].get();
Brandon Joneseb994362014-09-24 10:27:28 -07001314
1315 const std::vector<GLenum> outputs = pixelExecutable->outputSignature();
1316 stream->writeInt(outputs.size());
1317 for (size_t outputIndex = 0; outputIndex < outputs.size(); outputIndex++)
1318 {
1319 stream->writeInt(outputs[outputIndex]);
1320 }
1321
1322 size_t pixelShaderSize = pixelExecutable->shaderExecutable()->getLength();
1323 stream->writeInt(pixelShaderSize);
1324
1325 const uint8_t *pixelBlob = pixelExecutable->shaderExecutable()->getFunction();
1326 stream->writeBytes(pixelBlob, pixelShaderSize);
1327 }
1328
Xinghua Caob1239382016-12-13 15:07:05 +08001329 for (auto const &geometryExecutable : mGeometryExecutables)
Brandon Joneseb994362014-09-24 10:27:28 -07001330 {
Xinghua Caob1239382016-12-13 15:07:05 +08001331 if (!geometryExecutable)
Jamie Madill4e31ad52015-10-29 10:32:57 -04001332 {
1333 stream->writeInt(0);
1334 continue;
1335 }
1336
Xinghua Caob1239382016-12-13 15:07:05 +08001337 size_t geometryShaderSize = geometryExecutable->getLength();
Jamie Madill4e31ad52015-10-29 10:32:57 -04001338 stream->writeInt(geometryShaderSize);
Xinghua Caob1239382016-12-13 15:07:05 +08001339 stream->writeBytes(geometryExecutable->getFunction(), geometryShaderSize);
1340 }
1341
Xinghua Caof3179a62018-07-12 16:22:06 +08001342 stream->writeInt(mComputeExecutables.size());
1343 for (size_t computeExecutableIndex = 0; computeExecutableIndex < mComputeExecutables.size();
1344 computeExecutableIndex++)
Xinghua Caob1239382016-12-13 15:07:05 +08001345 {
Xinghua Caof3179a62018-07-12 16:22:06 +08001346 ComputeExecutable *computeExecutable = mComputeExecutables[computeExecutableIndex].get();
1347
1348 const gl::ImageUnitTextureTypeMap signatures = computeExecutable->signature();
1349 stream->writeInt(signatures.size());
1350 for (const auto &signature : signatures)
1351 {
1352 stream->writeInt(signature.first);
1353 stream->writeInt(static_cast<unsigned int>(signature.second));
1354 }
1355
1356 size_t computeShaderSize = computeExecutable->shaderExecutable()->getLength();
Xinghua Caob1239382016-12-13 15:07:05 +08001357 stream->writeInt(computeShaderSize);
Xinghua Caof3179a62018-07-12 16:22:06 +08001358
1359 const uint8_t *computeBlob = computeExecutable->shaderExecutable()->getFunction();
1360 stream->writeBytes(computeBlob, computeShaderSize);
Xinghua Caob1239382016-12-13 15:07:05 +08001361 }
Xinghua Caof3179a62018-07-12 16:22:06 +08001362
1363 stream->writeInt(mComputeShaderImage2DBindLayoutCache.size());
1364 for (auto &image2DBindLayout : mComputeShaderImage2DBindLayoutCache)
Xinghua Caob1239382016-12-13 15:07:05 +08001365 {
Xinghua Caof3179a62018-07-12 16:22:06 +08001366 stream->writeInt(image2DBindLayout.first);
Brandon Joneseb994362014-09-24 10:27:28 -07001367 }
Brandon Jones22502d52014-08-29 16:58:36 -07001368}
1369
Jamie Madillb980c562018-11-27 11:34:27 -05001370void ProgramD3D::setBinaryRetrievableHint(bool /* retrievable */) {}
Geoff Langc5629752015-12-07 16:29:04 -05001371
Jamie Madillb980c562018-11-27 11:34:27 -05001372void ProgramD3D::setSeparable(bool /* separable */) {}
Yunchao He61afff12017-03-14 15:34:03 +08001373
Jamie Madillec1fe5b2018-08-10 10:05:52 -04001374angle::Result ProgramD3D::getPixelExecutableForCachedOutputLayout(
Jamie Madill785e8a02018-10-04 17:42:00 -04001375 d3d::Context *context,
Jamie Madillec1fe5b2018-08-10 10:05:52 -04001376 ShaderExecutableD3D **outExecutable,
1377 gl::InfoLog *infoLog)
Brandon Joneseb994362014-09-24 10:27:28 -07001378{
Jamie Madill0e7f1732017-09-09 23:32:50 -04001379 if (mCachedPixelExecutableIndex.valid())
Brandon Joneseb994362014-09-24 10:27:28 -07001380 {
Jamie Madill0e7f1732017-09-09 23:32:50 -04001381 *outExecutable = mPixelExecutables[mCachedPixelExecutableIndex.value()]->shaderExecutable();
Jamie Madill7c985f52018-11-29 18:16:17 -05001382 return angle::Result::Continue;
Brandon Joneseb994362014-09-24 10:27:28 -07001383 }
1384
Jamie Madill334d6152015-10-22 14:00:28 -04001385 std::string finalPixelHLSL = mDynamicHLSL->generatePixelShaderForOutputSignature(
Jiawei Shao467c15f2018-04-24 15:04:26 +08001386 mShaderHLSL[gl::ShaderType::Fragment], mPixelShaderKey, mUsesFragDepth,
1387 mPixelShaderOutputLayoutCache);
Brandon Jones22502d52014-08-29 16:58:36 -07001388
1389 // Generate new pixel executable
Yunchao Hed7297bf2017-04-19 15:27:10 +08001390 ShaderExecutableD3D *pixelExecutable = nullptr;
Jamie Madill97399232014-12-23 12:31:15 -05001391
1392 gl::InfoLog tempInfoLog;
1393 gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
1394
Jamie Madill01074252016-11-28 15:55:51 -05001395 ANGLE_TRY(mRenderer->compileToExecutable(
Jamie Madillb1565902018-07-27 08:12:48 -04001396 context, *currentInfoLog, finalPixelHLSL, gl::ShaderType::Fragment, mStreamOutVaryings,
Jiawei Shao467c15f2018-04-24 15:04:26 +08001397 (mState.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS),
1398 mShaderWorkarounds[gl::ShaderType::Fragment], &pixelExecutable));
Brandon Joneseb994362014-09-24 10:27:28 -07001399
Jamie Madill97399232014-12-23 12:31:15 -05001400 if (pixelExecutable)
1401 {
Xinghua Caob1239382016-12-13 15:07:05 +08001402 mPixelExecutables.push_back(std::unique_ptr<PixelExecutable>(
Jamie Madill4c19a8a2017-07-24 11:46:06 -04001403 new PixelExecutable(mPixelShaderOutputLayoutCache, pixelExecutable)));
Jamie Madill0e7f1732017-09-09 23:32:50 -04001404 mCachedPixelExecutableIndex = mPixelExecutables.size() - 1;
Jamie Madill97399232014-12-23 12:31:15 -05001405 }
1406 else if (!infoLog)
Brandon Joneseb994362014-09-24 10:27:28 -07001407 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05001408 ERR() << "Error compiling dynamic pixel executable:" << std::endl
1409 << tempInfoLog.str() << std::endl;
Brandon Joneseb994362014-09-24 10:27:28 -07001410 }
Brandon Jones22502d52014-08-29 16:58:36 -07001411
Jamie Madill4c19a8a2017-07-24 11:46:06 -04001412 *outExecutable = pixelExecutable;
Jamie Madill7c985f52018-11-29 18:16:17 -05001413 return angle::Result::Continue;
Brandon Jones22502d52014-08-29 16:58:36 -07001414}
1415
Jamie Madillec1fe5b2018-08-10 10:05:52 -04001416angle::Result ProgramD3D::getVertexExecutableForCachedInputLayout(
Jamie Madill785e8a02018-10-04 17:42:00 -04001417 d3d::Context *context,
Jamie Madillec1fe5b2018-08-10 10:05:52 -04001418 ShaderExecutableD3D **outExectuable,
1419 gl::InfoLog *infoLog)
Brandon Jones22502d52014-08-29 16:58:36 -07001420{
Jamie Madill0e7f1732017-09-09 23:32:50 -04001421 if (mCachedVertexExecutableIndex.valid())
Brandon Joneseb994362014-09-24 10:27:28 -07001422 {
Jamie Madill0e7f1732017-09-09 23:32:50 -04001423 *outExectuable =
1424 mVertexExecutables[mCachedVertexExecutableIndex.value()]->shaderExecutable();
Jamie Madill7c985f52018-11-29 18:16:17 -05001425 return angle::Result::Continue;
Brandon Joneseb994362014-09-24 10:27:28 -07001426 }
1427
Brandon Jones22502d52014-08-29 16:58:36 -07001428 // Generate new dynamic layout with attribute conversions
Jamie Madillc349ec02015-08-21 16:53:12 -04001429 std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout(
Jiawei Shao467c15f2018-04-24 15:04:26 +08001430 mShaderHLSL[gl::ShaderType::Vertex], mCachedInputLayout, mState.getAttributes());
Brandon Jones22502d52014-08-29 16:58:36 -07001431
1432 // Generate new vertex executable
Yunchao Hed7297bf2017-04-19 15:27:10 +08001433 ShaderExecutableD3D *vertexExecutable = nullptr;
Jamie Madill97399232014-12-23 12:31:15 -05001434
1435 gl::InfoLog tempInfoLog;
1436 gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
1437
Jamie Madill01074252016-11-28 15:55:51 -05001438 ANGLE_TRY(mRenderer->compileToExecutable(
Jamie Madillb1565902018-07-27 08:12:48 -04001439 context, *currentInfoLog, finalVertexHLSL, gl::ShaderType::Vertex, mStreamOutVaryings,
Jiawei Shao467c15f2018-04-24 15:04:26 +08001440 (mState.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS),
1441 mShaderWorkarounds[gl::ShaderType::Vertex], &vertexExecutable));
Geoff Langb543aff2014-09-30 14:52:54 -04001442
Jamie Madill97399232014-12-23 12:31:15 -05001443 if (vertexExecutable)
Brandon Joneseb994362014-09-24 10:27:28 -07001444 {
Xinghua Caob1239382016-12-13 15:07:05 +08001445 mVertexExecutables.push_back(std::unique_ptr<VertexExecutable>(
Jamie Madill4c19a8a2017-07-24 11:46:06 -04001446 new VertexExecutable(mCachedInputLayout, mCachedVertexSignature, vertexExecutable)));
Jamie Madill0e7f1732017-09-09 23:32:50 -04001447 mCachedVertexExecutableIndex = mVertexExecutables.size() - 1;
Brandon Joneseb994362014-09-24 10:27:28 -07001448 }
Jamie Madill97399232014-12-23 12:31:15 -05001449 else if (!infoLog)
1450 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05001451 ERR() << "Error compiling dynamic vertex executable:" << std::endl
1452 << tempInfoLog.str() << std::endl;
Jamie Madill97399232014-12-23 12:31:15 -05001453 }
Brandon Jones22502d52014-08-29 16:58:36 -07001454
Geoff Langb543aff2014-09-30 14:52:54 -04001455 *outExectuable = vertexExecutable;
Jamie Madill7c985f52018-11-29 18:16:17 -05001456 return angle::Result::Continue;
Brandon Jones22502d52014-08-29 16:58:36 -07001457}
1458
Jamie Madill785e8a02018-10-04 17:42:00 -04001459angle::Result ProgramD3D::getGeometryExecutableForPrimitiveType(d3d::Context *context,
1460 const gl::Caps &caps,
Jamie Madillec1fe5b2018-08-10 10:05:52 -04001461 gl::PrimitiveMode drawMode,
1462 ShaderExecutableD3D **outExecutable,
1463 gl::InfoLog *infoLog)
Jamie Madill4e31ad52015-10-29 10:32:57 -04001464{
Jamie Madill3e14e2b2015-10-29 14:38:53 -04001465 if (outExecutable)
1466 {
1467 *outExecutable = nullptr;
1468 }
1469
Austin Kinross88829e82016-01-12 13:04:41 -08001470 // Return a null shader if the current rendering doesn't use a geometry shader
1471 if (!usesGeometryShader(drawMode))
Jamie Madill3e14e2b2015-10-29 14:38:53 -04001472 {
Jamie Madill7c985f52018-11-29 18:16:17 -05001473 return angle::Result::Continue;
Jamie Madill3e14e2b2015-10-29 14:38:53 -04001474 }
1475
Jamie Madill04796cd2018-05-24 19:52:16 -04001476 gl::PrimitiveMode geometryShaderType = GetGeometryShaderTypeFromDrawMode(drawMode);
Jamie Madill4e31ad52015-10-29 10:32:57 -04001477
Xinghua Caob1239382016-12-13 15:07:05 +08001478 if (mGeometryExecutables[geometryShaderType])
Jamie Madill4e31ad52015-10-29 10:32:57 -04001479 {
1480 if (outExecutable)
1481 {
Xinghua Caob1239382016-12-13 15:07:05 +08001482 *outExecutable = mGeometryExecutables[geometryShaderType].get();
Jamie Madill4e31ad52015-10-29 10:32:57 -04001483 }
Jamie Madill7c985f52018-11-29 18:16:17 -05001484 return angle::Result::Continue;
Jamie Madill4e31ad52015-10-29 10:32:57 -04001485 }
1486
1487 std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL(
Jamie Madill785e8a02018-10-04 17:42:00 -04001488 caps, geometryShaderType, mState, mRenderer->presentPathFastEnabled(),
Martin Radevc1d4e552017-08-21 12:01:10 +03001489 mHasANGLEMultiviewEnabled, mRenderer->canSelectViewInVertexShader(),
1490 usesGeometryShaderForPointSpriteEmulation(), mGeometryShaderPreamble);
Jamie Madill4e31ad52015-10-29 10:32:57 -04001491
1492 gl::InfoLog tempInfoLog;
1493 gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
1494
Xinghua Caob1239382016-12-13 15:07:05 +08001495 ShaderExecutableD3D *geometryExecutable = nullptr;
Jamie Madillec1fe5b2018-08-10 10:05:52 -04001496 angle::Result result = mRenderer->compileToExecutable(
Jamie Madillb1565902018-07-27 08:12:48 -04001497 context, *currentInfoLog, geometryHLSL, gl::ShaderType::Geometry, mStreamOutVaryings,
Jamie Madill408293f2016-12-20 10:11:45 -05001498 (mState.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS),
Xinghua Caob1239382016-12-13 15:07:05 +08001499 angle::CompilerWorkaroundsD3D(), &geometryExecutable);
Jamie Madill4e31ad52015-10-29 10:32:57 -04001500
Jamie Madill7c985f52018-11-29 18:16:17 -05001501 if (!infoLog && result == angle::Result::Stop)
Jamie Madill4e31ad52015-10-29 10:32:57 -04001502 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05001503 ERR() << "Error compiling dynamic geometry executable:" << std::endl
1504 << tempInfoLog.str() << std::endl;
Jamie Madill4e31ad52015-10-29 10:32:57 -04001505 }
1506
Xinghua Caob1239382016-12-13 15:07:05 +08001507 if (geometryExecutable != nullptr)
1508 {
1509 mGeometryExecutables[geometryShaderType].reset(geometryExecutable);
1510 }
1511
Jamie Madill4e31ad52015-10-29 10:32:57 -04001512 if (outExecutable)
1513 {
Xinghua Caob1239382016-12-13 15:07:05 +08001514 *outExecutable = mGeometryExecutables[geometryShaderType].get();
Jamie Madill4e31ad52015-10-29 10:32:57 -04001515 }
Jamie Madillec1fe5b2018-08-10 10:05:52 -04001516 return result;
Jamie Madill4e31ad52015-10-29 10:32:57 -04001517}
1518
Jamie Madill785e8a02018-10-04 17:42:00 -04001519class ProgramD3D::GetExecutableTask : public Closure, public d3d::Context
Brandon Jones44151a92014-09-10 11:32:25 -07001520{
Jamie Madill01074252016-11-28 15:55:51 -05001521 public:
Jamie Madill785e8a02018-10-04 17:42:00 -04001522 GetExecutableTask(ProgramD3D *program) : mProgram(program) {}
Brandon Joneseb994362014-09-24 10:27:28 -07001523
Jamie Madillec1fe5b2018-08-10 10:05:52 -04001524 virtual angle::Result run() = 0;
Jamie Madill01074252016-11-28 15:55:51 -05001525
Jamie Madillec1fe5b2018-08-10 10:05:52 -04001526 void operator()() override { mResult = run(); }
Jamie Madill01074252016-11-28 15:55:51 -05001527
Jamie Madillec1fe5b2018-08-10 10:05:52 -04001528 angle::Result getResult() const { return mResult; }
Jamie Madill01074252016-11-28 15:55:51 -05001529 const gl::InfoLog &getInfoLog() const { return mInfoLog; }
Jamie Madillec1fe5b2018-08-10 10:05:52 -04001530 ShaderExecutableD3D *getExecutable() { return mExecutable; }
Jamie Madill01074252016-11-28 15:55:51 -05001531
Jamie Madillc1fd7372018-10-26 22:48:39 -04001532 void handleResult(HRESULT hr,
1533 const char *message,
1534 const char *file,
1535 const char *function,
1536 unsigned int line) override
Jamie Madill785e8a02018-10-04 17:42:00 -04001537 {
1538 mStoredHR = hr;
1539 mStoredMessage = message;
1540 mStoredFile = file;
1541 mStoredFunction = function;
1542 mStoredLine = line;
1543 }
1544
1545 void popError(d3d::Context *context)
1546 {
Jamie Madillc1fd7372018-10-26 22:48:39 -04001547 context->handleResult(mStoredHR, mStoredMessage, mStoredFile, mStoredFunction, mStoredLine);
Jamie Madill785e8a02018-10-04 17:42:00 -04001548 }
1549
Jamie Madill01074252016-11-28 15:55:51 -05001550 protected:
Jamie Madill785e8a02018-10-04 17:42:00 -04001551 ProgramD3D *mProgram = nullptr;
Jamie Madill7c985f52018-11-29 18:16:17 -05001552 angle::Result mResult = angle::Result::Continue;
Jamie Madill01074252016-11-28 15:55:51 -05001553 gl::InfoLog mInfoLog;
Jamie Madill785e8a02018-10-04 17:42:00 -04001554 ShaderExecutableD3D *mExecutable = nullptr;
1555 HRESULT mStoredHR = S_OK;
1556 const char *mStoredMessage = nullptr;
1557 const char *mStoredFile = nullptr;
1558 const char *mStoredFunction = nullptr;
1559 unsigned int mStoredLine = 0;
Jamie Madill01074252016-11-28 15:55:51 -05001560};
1561
1562class ProgramD3D::GetVertexExecutableTask : public ProgramD3D::GetExecutableTask
1563{
1564 public:
Jamie Madill785e8a02018-10-04 17:42:00 -04001565 GetVertexExecutableTask(ProgramD3D *program) : GetExecutableTask(program) {}
Jamie Madillec1fe5b2018-08-10 10:05:52 -04001566 angle::Result run() override
Jamie Madill01074252016-11-28 15:55:51 -05001567 {
jchen103fd614d2018-08-13 12:21:58 +08001568 mProgram->updateCachedInputLayoutFromShader();
Jamie Madill01074252016-11-28 15:55:51 -05001569
Jamie Madill785e8a02018-10-04 17:42:00 -04001570 ANGLE_TRY(mProgram->getVertexExecutableForCachedInputLayout(this, &mExecutable, &mInfoLog));
Jamie Madill01074252016-11-28 15:55:51 -05001571
Jamie Madill7c985f52018-11-29 18:16:17 -05001572 return angle::Result::Continue;
Jamie Madill01074252016-11-28 15:55:51 -05001573 }
1574};
1575
jchen103fd614d2018-08-13 12:21:58 +08001576void ProgramD3D::updateCachedInputLayoutFromShader()
Jamie Madill4c19a8a2017-07-24 11:46:06 -04001577{
jchen103fd614d2018-08-13 12:21:58 +08001578 GetDefaultInputLayoutFromShader(mState.getAttachedShader(gl::ShaderType::Vertex),
Jiawei Shao385b3e02018-03-21 09:43:28 +08001579 &mCachedInputLayout);
Jamie Madill4c19a8a2017-07-24 11:46:06 -04001580 VertexExecutable::getSignature(mRenderer, mCachedInputLayout, &mCachedVertexSignature);
Jamie Madill0e7f1732017-09-09 23:32:50 -04001581 updateCachedVertexExecutableIndex();
Jamie Madill4c19a8a2017-07-24 11:46:06 -04001582}
1583
Jamie Madill01074252016-11-28 15:55:51 -05001584class ProgramD3D::GetPixelExecutableTask : public ProgramD3D::GetExecutableTask
1585{
1586 public:
Jamie Madill785e8a02018-10-04 17:42:00 -04001587 GetPixelExecutableTask(ProgramD3D *program) : GetExecutableTask(program) {}
Jamie Madillec1fe5b2018-08-10 10:05:52 -04001588 angle::Result run() override
Jamie Madill01074252016-11-28 15:55:51 -05001589 {
Jamie Madill4c19a8a2017-07-24 11:46:06 -04001590 mProgram->updateCachedOutputLayoutFromShader();
Jamie Madill01074252016-11-28 15:55:51 -05001591
Jamie Madill785e8a02018-10-04 17:42:00 -04001592 ANGLE_TRY(mProgram->getPixelExecutableForCachedOutputLayout(this, &mExecutable, &mInfoLog));
Jamie Madill01074252016-11-28 15:55:51 -05001593
Jamie Madill7c985f52018-11-29 18:16:17 -05001594 return angle::Result::Continue;
Jamie Madill01074252016-11-28 15:55:51 -05001595 }
1596};
1597
Jamie Madill4c19a8a2017-07-24 11:46:06 -04001598void ProgramD3D::updateCachedOutputLayoutFromShader()
1599{
1600 GetDefaultOutputLayoutFromShader(mPixelShaderKey, &mPixelShaderOutputLayoutCache);
Jamie Madill0e7f1732017-09-09 23:32:50 -04001601 updateCachedPixelExecutableIndex();
Jamie Madill4c19a8a2017-07-24 11:46:06 -04001602}
1603
Xinghua Caof3179a62018-07-12 16:22:06 +08001604void ProgramD3D::updateCachedImage2DBindLayoutFromComputeShader()
1605{
1606 GetDefaultImage2DBindLayoutFromComputeShader(mImage2DUniforms,
1607 &mComputeShaderImage2DBindLayoutCache);
1608 updateCachedComputeExecutableIndex();
1609}
1610
Jamie Madill01074252016-11-28 15:55:51 -05001611class ProgramD3D::GetGeometryExecutableTask : public ProgramD3D::GetExecutableTask
1612{
1613 public:
Jamie Madill785e8a02018-10-04 17:42:00 -04001614 GetGeometryExecutableTask(ProgramD3D *program, const gl::Caps &caps)
1615 : GetExecutableTask(program), mCaps(caps)
Jamie Madillb980c562018-11-27 11:34:27 -05001616 {}
Jamie Madill01074252016-11-28 15:55:51 -05001617
Jamie Madillec1fe5b2018-08-10 10:05:52 -04001618 angle::Result run() override
Jamie Madill01074252016-11-28 15:55:51 -05001619 {
1620 // Auto-generate the geometry shader here, if we expect to be using point rendering in
1621 // D3D11.
Jamie Madill493f9572018-05-24 19:52:15 -04001622 if (mProgram->usesGeometryShader(gl::PrimitiveMode::Points))
Jamie Madill01074252016-11-28 15:55:51 -05001623 {
Jamie Madill493f9572018-05-24 19:52:15 -04001624 ANGLE_TRY(mProgram->getGeometryExecutableForPrimitiveType(
Jamie Madill785e8a02018-10-04 17:42:00 -04001625 this, mCaps, gl::PrimitiveMode::Points, &mExecutable, &mInfoLog));
Jamie Madill01074252016-11-28 15:55:51 -05001626 }
1627
Jamie Madill7c985f52018-11-29 18:16:17 -05001628 return angle::Result::Continue;
Jamie Madill01074252016-11-28 15:55:51 -05001629 }
Jamie Madill785e8a02018-10-04 17:42:00 -04001630
1631 private:
1632 const gl::Caps &mCaps;
Jamie Madill01074252016-11-28 15:55:51 -05001633};
1634
jchen107ae70d82018-07-06 13:47:01 +08001635// The LinkEvent implementation for linking a rendering(VS, FS, GS) program.
1636class ProgramD3D::GraphicsProgramLinkEvent final : public LinkEvent
1637{
1638 public:
1639 GraphicsProgramLinkEvent(gl::InfoLog &infoLog,
1640 std::shared_ptr<WorkerThreadPool> workerPool,
1641 std::shared_ptr<ProgramD3D::GetVertexExecutableTask> vertexTask,
1642 std::shared_ptr<ProgramD3D::GetPixelExecutableTask> pixelTask,
1643 std::shared_ptr<ProgramD3D::GetGeometryExecutableTask> geometryTask,
1644 bool useGS,
1645 const ShaderD3D *vertexShader,
1646 const ShaderD3D *fragmentShader)
1647 : mInfoLog(infoLog),
1648 mWorkerPool(workerPool),
1649 mVertexTask(vertexTask),
1650 mPixelTask(pixelTask),
1651 mGeometryTask(geometryTask),
1652 mWaitEvents(
1653 {{std::shared_ptr<WaitableEvent>(workerPool->postWorkerTask(mVertexTask)),
1654 std::shared_ptr<WaitableEvent>(workerPool->postWorkerTask(mPixelTask)),
1655 std::shared_ptr<WaitableEvent>(workerPool->postWorkerTask(mGeometryTask))}}),
1656 mUseGS(useGS),
1657 mVertexShader(vertexShader),
1658 mFragmentShader(fragmentShader)
Jamie Madillb980c562018-11-27 11:34:27 -05001659 {}
jchen107ae70d82018-07-06 13:47:01 +08001660
Jamie Madill785e8a02018-10-04 17:42:00 -04001661 angle::Result wait(const gl::Context *context) override
jchen107ae70d82018-07-06 13:47:01 +08001662 {
1663 WaitableEvent::WaitMany(&mWaitEvents);
1664
Jamie Madill785e8a02018-10-04 17:42:00 -04001665 ANGLE_TRY(checkTask(context, mVertexTask.get()));
1666 ANGLE_TRY(checkTask(context, mPixelTask.get()));
1667 ANGLE_TRY(checkTask(context, mGeometryTask.get()));
1668
Jamie Madill7c985f52018-11-29 18:16:17 -05001669 if (mVertexTask.get()->getResult() == angle::Result::Incomplete ||
1670 mPixelTask.get()->getResult() == angle::Result::Incomplete ||
1671 mGeometryTask.get()->getResult() == angle::Result::Incomplete)
jchen107ae70d82018-07-06 13:47:01 +08001672 {
Jamie Madill7c985f52018-11-29 18:16:17 -05001673 return angle::Result::Incomplete;
jchen107ae70d82018-07-06 13:47:01 +08001674 }
1675
1676 ShaderExecutableD3D *defaultVertexExecutable = mVertexTask->getExecutable();
1677 ShaderExecutableD3D *defaultPixelExecutable = mPixelTask->getExecutable();
1678 ShaderExecutableD3D *pointGS = mGeometryTask->getExecutable();
1679
1680 if (mUseGS && pointGS)
1681 {
1682 // Geometry shaders are currently only used internally, so there is no corresponding
1683 // shader object at the interface level. For now the geometry shader debug info is
1684 // prepended to the vertex shader.
1685 mVertexShader->appendDebugInfo("// GEOMETRY SHADER BEGIN\n\n");
1686 mVertexShader->appendDebugInfo(pointGS->getDebugInfo());
1687 mVertexShader->appendDebugInfo("\nGEOMETRY SHADER END\n\n\n");
1688 }
1689
1690 if (defaultVertexExecutable)
1691 {
1692 mVertexShader->appendDebugInfo(defaultVertexExecutable->getDebugInfo());
1693 }
1694
1695 if (defaultPixelExecutable)
1696 {
1697 mFragmentShader->appendDebugInfo(defaultPixelExecutable->getDebugInfo());
1698 }
1699
1700 bool isLinked = (defaultVertexExecutable && defaultPixelExecutable && (!mUseGS || pointGS));
1701 if (!isLinked)
1702 {
1703 mInfoLog << "Failed to create D3D Shaders";
1704 }
Jamie Madill7c985f52018-11-29 18:16:17 -05001705 return isLinked ? angle::Result::Continue : angle::Result::Incomplete;
jchen107ae70d82018-07-06 13:47:01 +08001706 }
1707
1708 bool isLinking() override
1709 {
1710 for (auto &event : mWaitEvents)
1711 {
1712 if (!event->isReady())
1713 {
1714 return true;
1715 }
1716 }
1717 return false;
1718 }
1719
1720 private:
Jamie Madill785e8a02018-10-04 17:42:00 -04001721 angle::Result checkTask(const gl::Context *context, ProgramD3D::GetExecutableTask *task)
jchen107ae70d82018-07-06 13:47:01 +08001722 {
1723 if (!task->getInfoLog().empty())
1724 {
1725 mInfoLog << task->getInfoLog().str();
1726 }
Jamie Madill785e8a02018-10-04 17:42:00 -04001727
1728 // Continue and Incomplete are not errors. For Stop, pass the error to the ContextD3D.
Jamie Madill7c985f52018-11-29 18:16:17 -05001729 if (task->getResult() != angle::Result::Stop)
jchen107ae70d82018-07-06 13:47:01 +08001730 {
Jamie Madill7c985f52018-11-29 18:16:17 -05001731 return angle::Result::Continue;
jchen107ae70d82018-07-06 13:47:01 +08001732 }
Jamie Madill785e8a02018-10-04 17:42:00 -04001733
1734 ContextD3D *contextD3D = GetImplAs<ContextD3D>(context);
1735 task->popError(contextD3D);
Jamie Madill7c985f52018-11-29 18:16:17 -05001736 return angle::Result::Stop;
jchen107ae70d82018-07-06 13:47:01 +08001737 }
1738
1739 gl::InfoLog &mInfoLog;
1740 std::shared_ptr<WorkerThreadPool> mWorkerPool;
1741 std::shared_ptr<ProgramD3D::GetVertexExecutableTask> mVertexTask;
1742 std::shared_ptr<ProgramD3D::GetPixelExecutableTask> mPixelTask;
1743 std::shared_ptr<ProgramD3D::GetGeometryExecutableTask> mGeometryTask;
1744 std::array<std::shared_ptr<WaitableEvent>, 3> mWaitEvents;
1745 bool mUseGS;
1746 const ShaderD3D *mVertexShader;
1747 const ShaderD3D *mFragmentShader;
1748};
1749
1750std::unique_ptr<LinkEvent> ProgramD3D::compileProgramExecutables(const gl::Context *context,
1751 gl::InfoLog &infoLog)
Jamie Madill01074252016-11-28 15:55:51 -05001752{
1753 // Ensure the compiler is initialized to avoid race conditions.
Jamie Madill785e8a02018-10-04 17:42:00 -04001754 angle::Result result = mRenderer->ensureHLSLCompilerInitialized(GetImplAs<ContextD3D>(context));
Jamie Madill7c985f52018-11-29 18:16:17 -05001755 if (result != angle::Result::Continue)
Jiawei Shao02f15232017-12-27 10:10:28 +08001756 {
jchen107ae70d82018-07-06 13:47:01 +08001757 return std::make_unique<LinkEventDone>(result);
Jiawei Shao02f15232017-12-27 10:10:28 +08001758 }
Jamie Madill01074252016-11-28 15:55:51 -05001759
Jamie Madill785e8a02018-10-04 17:42:00 -04001760 auto vertexTask = std::make_shared<GetVertexExecutableTask>(this);
1761 auto pixelTask = std::make_shared<GetPixelExecutableTask>(this);
1762 auto geometryTask = std::make_shared<GetGeometryExecutableTask>(this, context->getCaps());
jchen107ae70d82018-07-06 13:47:01 +08001763 bool useGS = usesGeometryShader(gl::PrimitiveMode::Points);
Jiawei Shao385b3e02018-03-21 09:43:28 +08001764 const ShaderD3D *vertexShaderD3D =
1765 GetImplAs<ShaderD3D>(mState.getAttachedShader(gl::ShaderType::Vertex));
jchen107ae70d82018-07-06 13:47:01 +08001766 const ShaderD3D *fragmentShaderD3D =
1767 GetImplAs<ShaderD3D>(mState.getAttachedShader(gl::ShaderType::Fragment));
Jamie Madill847638a2015-11-20 13:01:41 -05001768
jchen107ae70d82018-07-06 13:47:01 +08001769 return std::make_unique<GraphicsProgramLinkEvent>(infoLog, context->getWorkerThreadPool(),
1770 vertexTask, pixelTask, geometryTask, useGS,
1771 vertexShaderD3D, fragmentShaderD3D);
Brandon Jones18bd4102014-09-22 14:21:44 -07001772}
1773
Xinghua Caof3179a62018-07-12 16:22:06 +08001774angle::Result ProgramD3D::getComputeExecutableForImage2DBindLayout(
1775 d3d::Context *context,
1776 ShaderExecutableD3D **outExecutable,
1777 gl::InfoLog *infoLog)
1778{
1779 if (mCachedComputeExecutableIndex.valid())
1780 {
1781 *outExecutable =
1782 mComputeExecutables[mCachedComputeExecutableIndex.value()]->shaderExecutable();
1783 return angle::Result::Continue;
1784 }
1785
1786 std::string finalComputeHLSL = mDynamicHLSL->generateComputeShaderForImage2DBindSignature(
1787 context, *this, mState, mImage2DUniforms, mComputeShaderImage2DBindLayoutCache);
1788
1789 // Generate new compute executable
1790 ShaderExecutableD3D *computeExecutable = nullptr;
1791
1792 gl::InfoLog tempInfoLog;
1793 gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
1794
1795 ANGLE_TRY(mRenderer->compileToExecutable(
1796 context, *currentInfoLog, finalComputeHLSL, gl::ShaderType::Compute,
1797 std::vector<D3DVarying>(), false, angle::CompilerWorkaroundsD3D(), &computeExecutable));
1798
1799 if (computeExecutable)
1800 {
1801 mComputeExecutables.push_back(std::unique_ptr<ComputeExecutable>(
1802 new ComputeExecutable(mComputeShaderImage2DBindLayoutCache,
1803 std::unique_ptr<ShaderExecutableD3D>(computeExecutable))));
1804 mCachedComputeExecutableIndex = mComputeExecutables.size() - 1;
1805 }
1806 else if (!infoLog)
1807 {
1808 ERR() << "Error compiling dynamic compute executable:" << std::endl
1809 << tempInfoLog.str() << std::endl;
1810 }
1811 *outExecutable = computeExecutable;
1812
1813 return angle::Result::Continue;
1814}
1815
Jamie Madill785e8a02018-10-04 17:42:00 -04001816angle::Result ProgramD3D::compileComputeExecutable(d3d::Context *context, gl::InfoLog &infoLog)
Xinghua Caob1239382016-12-13 15:07:05 +08001817{
1818 // Ensure the compiler is initialized to avoid race conditions.
Jamie Madillb1565902018-07-27 08:12:48 -04001819 ANGLE_TRY(mRenderer->ensureHLSLCompilerInitialized(context));
Xinghua Caob1239382016-12-13 15:07:05 +08001820
Xinghua Caof3179a62018-07-12 16:22:06 +08001821 updateCachedImage2DBindLayoutFromComputeShader();
Xinghua Caob1239382016-12-13 15:07:05 +08001822
1823 ShaderExecutableD3D *computeExecutable = nullptr;
Xinghua Caof3179a62018-07-12 16:22:06 +08001824 ANGLE_TRY(getComputeExecutableForImage2DBindLayout(context, &computeExecutable, &infoLog));
Xinghua Caob1239382016-12-13 15:07:05 +08001825
Xinghua Caof3179a62018-07-12 16:22:06 +08001826 return computeExecutable ? angle::Result::Continue : angle::Result::Incomplete;
Xinghua Caob1239382016-12-13 15:07:05 +08001827}
1828
jchen107ae70d82018-07-06 13:47:01 +08001829std::unique_ptr<LinkEvent> ProgramD3D::link(const gl::Context *context,
1830 const gl::ProgramLinkedResources &resources,
1831 gl::InfoLog &infoLog)
Brandon Jones22502d52014-08-29 16:58:36 -07001832{
Jamie Madillc3dc5d42018-12-30 12:12:04 -05001833 const auto &data = context->getState();
Jamie Madill8ecf7f92017-01-13 17:29:52 -05001834
Jamie Madill62d31cb2015-09-11 13:25:51 -04001835 reset();
1836
Jiawei Shao385b3e02018-03-21 09:43:28 +08001837 gl::Shader *computeShader = mState.getAttachedShader(gl::ShaderType::Compute);
Xinghua Caob1239382016-12-13 15:07:05 +08001838 if (computeShader)
Austin Kinross02df7962015-07-01 10:03:42 -07001839 {
Jiawei Shao54aafe52018-04-27 14:54:57 +08001840 mShaderSamplers[gl::ShaderType::Compute].resize(
1841 data.getCaps().maxShaderTextureImageUnits[gl::ShaderType::Compute]);
Xinghua Cao26143fd2017-11-01 18:19:05 +08001842 mImagesCS.resize(data.getCaps().maxImageUnits);
1843 mReadonlyImagesCS.resize(data.getCaps().maxImageUnits);
Xinghua Caob1239382016-12-13 15:07:05 +08001844
Jiawei Shao3dd8d2912018-03-30 09:39:09 +08001845 mShaderUniformsDirty.set(gl::ShaderType::Compute);
Xinghua Caob1239382016-12-13 15:07:05 +08001846
jchen103fd614d2018-08-13 12:21:58 +08001847 linkResources(resources);
jchen107ae70d82018-07-06 13:47:01 +08001848
Xinghua Caof3179a62018-07-12 16:22:06 +08001849 for (const sh::Uniform &uniform : computeShader->getUniforms())
1850 {
1851 if (gl::IsImageType(uniform.type) && gl::IsImage2DType(uniform.type))
1852 {
1853 mImage2DUniforms.push_back(uniform);
1854 }
1855 }
1856
1857 defineUniformsAndAssignRegisters();
1858
Jamie Madill785e8a02018-10-04 17:42:00 -04001859 angle::Result result = compileComputeExecutable(GetImplAs<ContextD3D>(context), infoLog);
Jamie Madill7c985f52018-11-29 18:16:17 -05001860 if (result != angle::Result::Continue)
Xinghua Caob1239382016-12-13 15:07:05 +08001861 {
1862 infoLog << "Failed to create D3D compute shader.";
Xinghua Caob1239382016-12-13 15:07:05 +08001863 }
jchen107ae70d82018-07-06 13:47:01 +08001864 return std::make_unique<LinkEventDone>(result);
Xinghua Caob1239382016-12-13 15:07:05 +08001865 }
1866 else
1867 {
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08001868 gl::ShaderMap<const ShaderD3D *> shadersD3D = {};
Jiawei Shao467c15f2018-04-24 15:04:26 +08001869 for (gl::ShaderType shaderType : gl::kAllGraphicsShaderTypes)
1870 {
1871 if (mState.getAttachedShader(shaderType))
1872 {
1873 shadersD3D[shaderType] = GetImplAs<ShaderD3D>(mState.getAttachedShader(shaderType));
Xinghua Caob1239382016-12-13 15:07:05 +08001874
Jiawei Shao467c15f2018-04-24 15:04:26 +08001875 mShaderSamplers[shaderType].resize(
Jiawei Shao54aafe52018-04-27 14:54:57 +08001876 data.getCaps().maxShaderTextureImageUnits[shaderType]);
Xinghua Caob1239382016-12-13 15:07:05 +08001877
Jiawei Shao467c15f2018-04-24 15:04:26 +08001878 shadersD3D[shaderType]->generateWorkarounds(&mShaderWorkarounds[shaderType]);
1879
1880 mShaderUniformsDirty.set(shaderType);
1881 }
1882 }
Xinghua Caob1239382016-12-13 15:07:05 +08001883
1884 if (mRenderer->getNativeLimitations().noFrontFacingSupport)
1885 {
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08001886 if (shadersD3D[gl::ShaderType::Fragment]->usesFrontFacing())
Xinghua Caob1239382016-12-13 15:07:05 +08001887 {
1888 infoLog << "The current renderer doesn't support gl_FrontFacing";
Jamie Madill7c985f52018-11-29 18:16:17 -05001889 return std::make_unique<LinkEventDone>(angle::Result::Incomplete);
Xinghua Caob1239382016-12-13 15:07:05 +08001890 }
1891 }
1892
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08001893 ProgramD3DMetadata metadata(mRenderer, shadersD3D);
Jamie Madillc9727f32017-11-07 12:37:07 -05001894 BuiltinVaryingsD3D builtins(metadata, resources.varyingPacking);
Xinghua Caob1239382016-12-13 15:07:05 +08001895
jchen103fd614d2018-08-13 12:21:58 +08001896 mDynamicHLSL->generateShaderLinkHLSL(context->getCaps(), mState, metadata,
1897 resources.varyingPacking, builtins, &mShaderHLSL);
Xinghua Caob1239382016-12-13 15:07:05 +08001898
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08001899 mUsesPointSize = shadersD3D[gl::ShaderType::Vertex]->usesPointSize();
Xinghua Caob1239382016-12-13 15:07:05 +08001900 mDynamicHLSL->getPixelShaderOutputKey(data, mState, metadata, &mPixelShaderKey);
Xinghua Cao26143fd2017-11-01 18:19:05 +08001901 mUsesFragDepth = metadata.usesFragDepth();
Martin Radev41ac68e2017-06-06 12:16:58 +03001902 mUsesViewID = metadata.usesViewID();
1903 mHasANGLEMultiviewEnabled = metadata.hasANGLEMultiviewEnabled();
Xinghua Caob1239382016-12-13 15:07:05 +08001904
1905 // Cache if we use flat shading
jchen103fd614d2018-08-13 12:21:58 +08001906 mUsesFlatInterpolation = FindFlatInterpolationVarying(mState.getAttachedShaders());
Xinghua Caob1239382016-12-13 15:07:05 +08001907
1908 if (mRenderer->getMajorShaderModel() >= 4)
1909 {
Martin Radev41ac68e2017-06-06 12:16:58 +03001910 mGeometryShaderPreamble = mDynamicHLSL->generateGeometryShaderPreamble(
Jamie Madillc9727f32017-11-07 12:37:07 -05001911 resources.varyingPacking, builtins, mHasANGLEMultiviewEnabled,
Martin Radevc1d4e552017-08-21 12:01:10 +03001912 metadata.canSelectViewInVertexShader());
Xinghua Caob1239382016-12-13 15:07:05 +08001913 }
1914
jchen103fd614d2018-08-13 12:21:58 +08001915 initAttribLocationsToD3DSemantic();
Xinghua Caob1239382016-12-13 15:07:05 +08001916
jchen103fd614d2018-08-13 12:21:58 +08001917 defineUniformsAndAssignRegisters();
Xinghua Caob1239382016-12-13 15:07:05 +08001918
Jiawei Shao385b3e02018-03-21 09:43:28 +08001919 gatherTransformFeedbackVaryings(resources.varyingPacking, builtins[gl::ShaderType::Vertex]);
Xinghua Caob1239382016-12-13 15:07:05 +08001920
jchen103fd614d2018-08-13 12:21:58 +08001921 linkResources(resources);
jchen107ae70d82018-07-06 13:47:01 +08001922
1923 return compileProgramExecutables(context, infoLog);
Austin Kinross02df7962015-07-01 10:03:42 -07001924 }
Brandon Jones22502d52014-08-29 16:58:36 -07001925}
1926
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001927GLboolean ProgramD3D::validate(const gl::Caps & /*caps*/, gl::InfoLog * /*infoLog*/)
Jamie Madill36cfd6a2015-08-18 10:46:20 -04001928{
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001929 // TODO(jmadill): Do something useful here?
1930 return GL_TRUE;
Jamie Madill36cfd6a2015-08-18 10:46:20 -04001931}
1932
Qin Jiajiaa602f902018-09-11 14:40:24 +08001933void ProgramD3D::initializeShaderStorageBlocks()
1934{
1935 if (mState.getShaderStorageBlocks().empty())
1936 {
1937 return;
1938 }
1939
1940 ASSERT(mD3DShaderStorageBlocks.empty());
1941
1942 // Assign registers and update sizes.
1943 gl::ShaderMap<const ShaderD3D *> shadersD3D = {};
1944 for (gl::ShaderType shaderType : gl::AllShaderTypes())
1945 {
1946 shadersD3D[shaderType] = SafeGetImplAs<ShaderD3D>(mState.getAttachedShader(shaderType));
1947 }
1948
1949 for (const gl::InterfaceBlock &shaderStorageBlock : mState.getShaderStorageBlocks())
1950 {
1951 unsigned int shaderStorageBlockElement =
1952 shaderStorageBlock.isArray ? shaderStorageBlock.arrayElement : 0;
1953
1954 D3DInterfaceBlock d3dShaderStorageBlock;
1955
1956 for (gl::ShaderType shaderType : gl::AllShaderTypes())
1957 {
1958 if (shaderStorageBlock.isActive(shaderType))
1959 {
1960 ASSERT(shadersD3D[shaderType]);
1961 unsigned int baseRegister =
1962 shadersD3D[shaderType]->getShaderStorageBlockRegister(shaderStorageBlock.name);
1963 d3dShaderStorageBlock.mShaderRegisterIndexes[shaderType] =
1964 baseRegister + shaderStorageBlockElement;
1965 }
1966 }
1967
1968 mD3DShaderStorageBlocks.push_back(d3dShaderStorageBlock);
1969 }
1970}
1971
Jamie Madill6db1c2e2017-11-08 09:17:40 -05001972void ProgramD3D::initializeUniformBlocks()
Jamie Madill62d31cb2015-09-11 13:25:51 -04001973{
Jamie Madill6db1c2e2017-11-08 09:17:40 -05001974 if (mState.getUniformBlocks().empty())
Jamie Madill51f522f2016-12-21 15:10:55 -05001975 {
1976 return;
1977 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04001978
Jamie Madill6db1c2e2017-11-08 09:17:40 -05001979 ASSERT(mD3DUniformBlocks.empty());
1980
Jamie Madill62d31cb2015-09-11 13:25:51 -04001981 // Assign registers and update sizes.
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08001982 gl::ShaderMap<const ShaderD3D *> shadersD3D = {};
1983 for (gl::ShaderType shaderType : gl::AllShaderTypes())
1984 {
1985 shadersD3D[shaderType] = SafeGetImplAs<ShaderD3D>(mState.getAttachedShader(shaderType));
1986 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04001987
Jiajia Qin729b2c62017-08-14 09:36:11 +08001988 for (const gl::InterfaceBlock &uniformBlock : mState.getUniformBlocks())
Jamie Madill62d31cb2015-09-11 13:25:51 -04001989 {
1990 unsigned int uniformBlockElement = uniformBlock.isArray ? uniformBlock.arrayElement : 0;
1991
Qin Jiajiaa602f902018-09-11 14:40:24 +08001992 D3DInterfaceBlock d3dUniformBlock;
Jamie Madill4a3c2342015-10-08 12:58:45 -04001993
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08001994 for (gl::ShaderType shaderType : gl::AllShaderTypes())
Jamie Madill62d31cb2015-09-11 13:25:51 -04001995 {
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08001996 if (uniformBlock.isActive(shaderType))
1997 {
1998 ASSERT(shadersD3D[shaderType]);
1999 unsigned int baseRegister =
2000 shadersD3D[shaderType]->getUniformBlockRegister(uniformBlock.name);
2001 d3dUniformBlock.mShaderRegisterIndexes[shaderType] =
2002 baseRegister + uniformBlockElement;
2003 }
Xinghua Caob1239382016-12-13 15:07:05 +08002004 }
2005
Jamie Madill4a3c2342015-10-08 12:58:45 -04002006 mD3DUniformBlocks.push_back(d3dUniformBlock);
Jamie Madill62d31cb2015-09-11 13:25:51 -04002007 }
2008}
2009
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002010void ProgramD3D::initializeUniformStorage(const gl::ShaderBitSet &availableShaderStages)
Brandon Jonesc9610c52014-08-25 17:02:59 -07002011{
2012 // Compute total default block size
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002013 gl::ShaderMap<unsigned int> shaderRegisters = {};
Jamie Madill62d31cb2015-09-11 13:25:51 -04002014 for (const D3DUniform *d3dUniform : mD3DUniforms)
Brandon Jonesc9610c52014-08-25 17:02:59 -07002015 {
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002016 if (d3dUniform->isSampler())
Brandon Jonesc9610c52014-08-25 17:02:59 -07002017 {
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002018 continue;
2019 }
2020
Jiawei Shao0661eb82018-06-13 10:51:54 +08002021 for (gl::ShaderType shaderType : availableShaderStages)
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002022 {
2023 if (d3dUniform->isReferencedByShader(shaderType))
Brandon Jonesc9610c52014-08-25 17:02:59 -07002024 {
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002025 shaderRegisters[shaderType] = std::max(
2026 shaderRegisters[shaderType],
2027 d3dUniform->mShaderRegisterIndexes[shaderType] + d3dUniform->registerCount);
Xinghua Caob1239382016-12-13 15:07:05 +08002028 }
Brandon Jonesc9610c52014-08-25 17:02:59 -07002029 }
2030 }
2031
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002032 // We only reset uniform storages for the shader stages available in the program (attached
2033 // shaders in ProgramD3D::link() and linkedShaderStages in ProgramD3D::load()).
Jiawei Shao0661eb82018-06-13 10:51:54 +08002034 for (gl::ShaderType shaderType : availableShaderStages)
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002035 {
Jiawei Shao0661eb82018-06-13 10:51:54 +08002036 mShaderUniformStorages[shaderType].reset(
2037 mRenderer->createUniformStorage(shaderRegisters[shaderType] * 16u));
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002038 }
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002039
2040 // Iterate the uniforms again to assign data pointers to default block uniforms.
2041 for (D3DUniform *d3dUniform : mD3DUniforms)
2042 {
2043 if (d3dUniform->isSampler())
2044 {
Olli Etuaho465835d2017-09-26 13:34:10 +03002045 d3dUniform->mSamplerData.resize(d3dUniform->getArraySizeProduct(), 0);
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002046 continue;
2047 }
2048
Jiawei Shao0661eb82018-06-13 10:51:54 +08002049 for (gl::ShaderType shaderType : availableShaderStages)
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002050 {
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002051 if (d3dUniform->isReferencedByShader(shaderType))
2052 {
2053 d3dUniform->mShaderData[shaderType] =
2054 mShaderUniformStorages[shaderType]->getDataPointer(
2055 d3dUniform->mShaderRegisterIndexes[shaderType],
2056 d3dUniform->registerElement);
2057 }
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002058 }
2059 }
Brandon Jonesc9610c52014-08-25 17:02:59 -07002060}
2061
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002062void ProgramD3D::updateUniformBufferCache(
2063 const gl::Caps &caps,
2064 const gl::ShaderMap<unsigned int> &reservedShaderRegisterIndexes)
Brandon Jones18bd4102014-09-22 14:21:44 -07002065{
Jamie Madill48ef11b2016-04-27 15:21:52 -04002066 if (mState.getUniformBlocks().empty())
Jamie Madill4a3c2342015-10-08 12:58:45 -04002067 {
Jamie Madilld63961d2017-09-12 15:22:57 -04002068 return;
Jamie Madill4a3c2342015-10-08 12:58:45 -04002069 }
2070
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002071 for (gl::ShaderType shaderType : gl::AllShaderTypes())
2072 {
2073 mShaderUBOCaches[shaderType].clear();
2074 }
Brandon Jones18bd4102014-09-22 14:21:44 -07002075
Jamie Madill4a3c2342015-10-08 12:58:45 -04002076 for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < mD3DUniformBlocks.size();
Jamie Madill62d31cb2015-09-11 13:25:51 -04002077 uniformBlockIndex++)
Brandon Jones18bd4102014-09-22 14:21:44 -07002078 {
Qin Jiajiaa602f902018-09-11 14:40:24 +08002079 const D3DInterfaceBlock &uniformBlock = mD3DUniformBlocks[uniformBlockIndex];
Jamie Madillb980c562018-11-27 11:34:27 -05002080 GLuint blockBinding = mState.getUniformBlockBinding(uniformBlockIndex);
Brandon Jones18bd4102014-09-22 14:21:44 -07002081
Brandon Jones18bd4102014-09-22 14:21:44 -07002082 // Unnecessary to apply an unreferenced standard or shared UBO
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002083 for (gl::ShaderType shaderType : gl::AllShaderTypes())
Brandon Jones18bd4102014-09-22 14:21:44 -07002084 {
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002085 if (!uniformBlock.activeInShader(shaderType))
2086 {
2087 continue;
2088 }
Brandon Jones18bd4102014-09-22 14:21:44 -07002089
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002090 unsigned int registerIndex = uniformBlock.mShaderRegisterIndexes[shaderType] -
2091 reservedShaderRegisterIndexes[shaderType];
Jiawei Shao54aafe52018-04-27 14:54:57 +08002092 ASSERT(registerIndex < caps.maxShaderUniformBlocks[shaderType]);
Jamie Madill03260fa2015-06-22 13:57:22 -04002093
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002094 std::vector<int> &shaderUBOcache = mShaderUBOCaches[shaderType];
2095 if (shaderUBOcache.size() <= registerIndex)
Jamie Madill03260fa2015-06-22 13:57:22 -04002096 {
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002097 shaderUBOcache.resize(registerIndex + 1, -1);
Jamie Madill03260fa2015-06-22 13:57:22 -04002098 }
2099
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002100 ASSERT(shaderUBOcache[registerIndex] == -1);
2101 shaderUBOcache[registerIndex] = blockBinding;
Brandon Jones18bd4102014-09-22 14:21:44 -07002102 }
2103 }
Jamie Madilld63961d2017-09-12 15:22:57 -04002104}
Brandon Jones18bd4102014-09-22 14:21:44 -07002105
Qin Jiajiaa602f902018-09-11 14:40:24 +08002106unsigned int ProgramD3D::getShaderStorageBufferRegisterIndex(GLuint blockIndex,
2107 gl::ShaderType shaderType) const
2108{
2109 return mD3DShaderStorageBlocks[blockIndex].mShaderRegisterIndexes[shaderType];
2110}
2111
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002112const std::vector<GLint> &ProgramD3D::getShaderUniformBufferCache(gl::ShaderType shaderType) const
Jamie Madilld63961d2017-09-12 15:22:57 -04002113{
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002114 return mShaderUBOCaches[shaderType];
Brandon Jones18bd4102014-09-22 14:21:44 -07002115}
2116
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002117void ProgramD3D::dirtyAllUniforms()
Brandon Jones18bd4102014-09-22 14:21:44 -07002118{
Jiawei Shao3dd8d2912018-03-30 09:39:09 +08002119 mShaderUniformsDirty = mState.getLinkedShaderStages();
Jamie Madill4148fd72017-09-14 15:46:20 -04002120}
2121
2122void ProgramD3D::markUniformsClean()
2123{
Jiawei Shao3dd8d2912018-03-30 09:39:09 +08002124 mShaderUniformsDirty.reset();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002125}
2126
Jamie Madill334d6152015-10-22 14:00:28 -04002127void ProgramD3D::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002128{
Jamie Madill33bb7c42017-09-09 23:32:51 -04002129 setUniformInternal(location, count, v, GL_FLOAT);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002130}
2131
2132void ProgramD3D::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
2133{
Jamie Madill33bb7c42017-09-09 23:32:51 -04002134 setUniformInternal(location, count, v, GL_FLOAT_VEC2);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002135}
2136
2137void ProgramD3D::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
2138{
Jamie Madill33bb7c42017-09-09 23:32:51 -04002139 setUniformInternal(location, count, v, GL_FLOAT_VEC3);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002140}
2141
2142void ProgramD3D::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
2143{
Jamie Madill33bb7c42017-09-09 23:32:51 -04002144 setUniformInternal(location, count, v, GL_FLOAT_VEC4);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002145}
2146
Jamie Madill334d6152015-10-22 14:00:28 -04002147void ProgramD3D::setUniformMatrix2fv(GLint location,
2148 GLsizei count,
2149 GLboolean transpose,
2150 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002151{
Luc Ferron46bcea52018-05-31 09:48:36 -04002152 setUniformMatrixfvInternal<2, 2>(location, count, transpose, value);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002153}
2154
Jamie Madill334d6152015-10-22 14:00:28 -04002155void ProgramD3D::setUniformMatrix3fv(GLint location,
2156 GLsizei count,
2157 GLboolean transpose,
2158 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002159{
Luc Ferron46bcea52018-05-31 09:48:36 -04002160 setUniformMatrixfvInternal<3, 3>(location, count, transpose, value);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002161}
2162
Jamie Madill334d6152015-10-22 14:00:28 -04002163void ProgramD3D::setUniformMatrix4fv(GLint location,
2164 GLsizei count,
2165 GLboolean transpose,
2166 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002167{
Luc Ferron46bcea52018-05-31 09:48:36 -04002168 setUniformMatrixfvInternal<4, 4>(location, count, transpose, value);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002169}
2170
Jamie Madill334d6152015-10-22 14:00:28 -04002171void ProgramD3D::setUniformMatrix2x3fv(GLint location,
2172 GLsizei count,
2173 GLboolean transpose,
2174 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002175{
Luc Ferron46bcea52018-05-31 09:48:36 -04002176 setUniformMatrixfvInternal<2, 3>(location, count, transpose, value);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002177}
2178
Jamie Madill334d6152015-10-22 14:00:28 -04002179void ProgramD3D::setUniformMatrix3x2fv(GLint location,
2180 GLsizei count,
2181 GLboolean transpose,
2182 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002183{
Luc Ferron46bcea52018-05-31 09:48:36 -04002184 setUniformMatrixfvInternal<3, 2>(location, count, transpose, value);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002185}
2186
Jamie Madill334d6152015-10-22 14:00:28 -04002187void ProgramD3D::setUniformMatrix2x4fv(GLint location,
2188 GLsizei count,
2189 GLboolean transpose,
2190 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002191{
Luc Ferron46bcea52018-05-31 09:48:36 -04002192 setUniformMatrixfvInternal<2, 4>(location, count, transpose, value);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002193}
2194
Jamie Madill334d6152015-10-22 14:00:28 -04002195void ProgramD3D::setUniformMatrix4x2fv(GLint location,
2196 GLsizei count,
2197 GLboolean transpose,
2198 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002199{
Luc Ferron46bcea52018-05-31 09:48:36 -04002200 setUniformMatrixfvInternal<4, 2>(location, count, transpose, value);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002201}
2202
Jamie Madill334d6152015-10-22 14:00:28 -04002203void ProgramD3D::setUniformMatrix3x4fv(GLint location,
2204 GLsizei count,
2205 GLboolean transpose,
2206 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002207{
Luc Ferron46bcea52018-05-31 09:48:36 -04002208 setUniformMatrixfvInternal<3, 4>(location, count, transpose, value);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002209}
2210
Jamie Madill334d6152015-10-22 14:00:28 -04002211void ProgramD3D::setUniformMatrix4x3fv(GLint location,
2212 GLsizei count,
2213 GLboolean transpose,
2214 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002215{
Luc Ferron46bcea52018-05-31 09:48:36 -04002216 setUniformMatrixfvInternal<4, 3>(location, count, transpose, value);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002217}
2218
2219void ProgramD3D::setUniform1iv(GLint location, GLsizei count, const GLint *v)
2220{
Jamie Madill33bb7c42017-09-09 23:32:51 -04002221 setUniformInternal(location, count, v, GL_INT);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002222}
2223
2224void ProgramD3D::setUniform2iv(GLint location, GLsizei count, const GLint *v)
2225{
Jamie Madill33bb7c42017-09-09 23:32:51 -04002226 setUniformInternal(location, count, v, GL_INT_VEC2);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002227}
2228
2229void ProgramD3D::setUniform3iv(GLint location, GLsizei count, const GLint *v)
2230{
Jamie Madill33bb7c42017-09-09 23:32:51 -04002231 setUniformInternal(location, count, v, GL_INT_VEC3);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002232}
2233
2234void ProgramD3D::setUniform4iv(GLint location, GLsizei count, const GLint *v)
2235{
Jamie Madill33bb7c42017-09-09 23:32:51 -04002236 setUniformInternal(location, count, v, GL_INT_VEC4);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002237}
2238
2239void ProgramD3D::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
2240{
Jamie Madill33bb7c42017-09-09 23:32:51 -04002241 setUniformInternal(location, count, v, GL_UNSIGNED_INT);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002242}
2243
2244void ProgramD3D::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
2245{
Jamie Madill33bb7c42017-09-09 23:32:51 -04002246 setUniformInternal(location, count, v, GL_UNSIGNED_INT_VEC2);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002247}
2248
2249void ProgramD3D::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
2250{
Jamie Madill33bb7c42017-09-09 23:32:51 -04002251 setUniformInternal(location, count, v, GL_UNSIGNED_INT_VEC3);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002252}
2253
2254void ProgramD3D::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
2255{
Jamie Madill33bb7c42017-09-09 23:32:51 -04002256 setUniformInternal(location, count, v, GL_UNSIGNED_INT_VEC4);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002257}
2258
jchen103fd614d2018-08-13 12:21:58 +08002259void ProgramD3D::defineUniformsAndAssignRegisters()
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002260{
Jamie Madill3d3d2f22015-09-23 16:47:51 -04002261 D3DUniformMap uniformMap;
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002262
2263 gl::ShaderBitSet attachedShaders;
Jiawei Shao385b3e02018-03-21 09:43:28 +08002264 for (gl::ShaderType shaderType : gl::AllShaderTypes())
Jamie Madill417df922017-01-12 09:23:07 -05002265 {
Jiawei Shao385b3e02018-03-21 09:43:28 +08002266 gl::Shader *shader = mState.getAttachedShader(shaderType);
2267 if (shader)
Jamie Madillfb536032015-09-11 13:19:49 -04002268 {
jchen103fd614d2018-08-13 12:21:58 +08002269 for (const sh::Uniform &uniform : shader->getUniforms())
Xinghua Caob1239382016-12-13 15:07:05 +08002270 {
Jiawei Shao385b3e02018-03-21 09:43:28 +08002271 if (uniform.active)
2272 {
2273 defineUniformBase(shader, uniform, &uniformMap);
2274 }
Xinghua Caob1239382016-12-13 15:07:05 +08002275 }
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002276
2277 attachedShaders.set(shader->getType());
Jamie Madillfb536032015-09-11 13:19:49 -04002278 }
2279 }
2280
Jamie Madill3d3d2f22015-09-23 16:47:51 -04002281 // Initialize the D3DUniform list to mirror the indexing of the GL layer.
Jamie Madill48ef11b2016-04-27 15:21:52 -04002282 for (const gl::LinkedUniform &glUniform : mState.getUniforms())
Jamie Madill3d3d2f22015-09-23 16:47:51 -04002283 {
2284 if (!glUniform.isInDefaultBlock())
2285 continue;
2286
Olli Etuahod2551232017-10-26 20:03:33 +03002287 std::string name = glUniform.name;
2288 if (glUniform.isArray())
2289 {
2290 // In the program state, array uniform names include [0] as in the program resource
2291 // spec. Here we don't include it.
2292 // TODO(oetuaho@nvidia.com): consider using the same uniform naming here as in the GL
2293 // layer.
2294 ASSERT(angle::EndsWith(name, "[0]"));
2295 name.resize(name.length() - 3);
2296 }
2297 auto mapEntry = uniformMap.find(name);
Jamie Madill3d3d2f22015-09-23 16:47:51 -04002298 ASSERT(mapEntry != uniformMap.end());
2299 mD3DUniforms.push_back(mapEntry->second);
2300 }
2301
Jamie Madill62d31cb2015-09-11 13:25:51 -04002302 assignAllSamplerRegisters();
Xinghua Cao6dfdca82018-08-03 17:10:55 +08002303 // Samplers and readonly images share shader input resource slot, adjust low value of
2304 // readonly image range.
2305 mUsedComputeReadonlyImageRange =
2306 gl::RangeUI(mUsedShaderSamplerRanges[gl::ShaderType::Compute].high(),
2307 mUsedShaderSamplerRanges[gl::ShaderType::Compute].high());
Xinghua Cao26143fd2017-11-01 18:19:05 +08002308 assignAllImageRegisters();
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002309 initializeUniformStorage(attachedShaders);
Jamie Madillfb536032015-09-11 13:19:49 -04002310}
2311
Jamie Madill91445bc2015-09-23 16:47:53 -04002312void ProgramD3D::defineUniformBase(const gl::Shader *shader,
Jamie Madill3d3d2f22015-09-23 16:47:51 -04002313 const sh::Uniform &uniform,
2314 D3DUniformMap *uniformMap)
Jamie Madillfb536032015-09-11 13:19:49 -04002315{
Jamie Madill8c78ce42018-12-16 19:14:58 -05002316 sh::DummyBlockEncoder dummyEncoder;
2317
Xinghua Cao26143fd2017-11-01 18:19:05 +08002318 // Samplers get their registers assigned in assignAllSamplerRegisters, and images get their
2319 // registers assigned in assignAllImageRegisters.
2320 if (gl::IsSamplerType(uniform.type))
Jamie Madillfb536032015-09-11 13:19:49 -04002321 {
Jamie Madill8c78ce42018-12-16 19:14:58 -05002322 UniformEncodingVisitorD3D visitor(shader->getType(), HLSLRegisterType::Texture,
2323 &dummyEncoder, uniformMap);
2324 sh::TraverseShaderVariable(uniform, false, &visitor);
Xinghua Cao26143fd2017-11-01 18:19:05 +08002325 return;
2326 }
Jamie Madill8c78ce42018-12-16 19:14:58 -05002327
2328 if (gl::IsImageType(uniform.type))
Xinghua Cao26143fd2017-11-01 18:19:05 +08002329 {
2330 if (uniform.readonly)
2331 {
Jamie Madill8c78ce42018-12-16 19:14:58 -05002332 UniformEncodingVisitorD3D visitor(shader->getType(), HLSLRegisterType::Texture,
2333 &dummyEncoder, uniformMap);
2334 sh::TraverseShaderVariable(uniform, false, &visitor);
Xinghua Cao26143fd2017-11-01 18:19:05 +08002335 }
2336 else
2337 {
Jamie Madill8c78ce42018-12-16 19:14:58 -05002338 UniformEncodingVisitorD3D visitor(shader->getType(),
2339 HLSLRegisterType::UnorderedAccessView, &dummyEncoder,
2340 uniformMap);
2341 sh::TraverseShaderVariable(uniform, false, &visitor);
Xinghua Cao26143fd2017-11-01 18:19:05 +08002342 }
2343 mImageBindingMap[uniform.name] = uniform.binding;
2344 return;
2345 }
Jamie Madill8c78ce42018-12-16 19:14:58 -05002346
2347 if (uniform.isBuiltIn() && !uniform.isEmulatedBuiltIn())
Xinghua Cao26143fd2017-11-01 18:19:05 +08002348 {
Jamie Madill8c78ce42018-12-16 19:14:58 -05002349 UniformEncodingVisitorD3D visitor(shader->getType(), HLSLRegisterType::None, &dummyEncoder,
2350 uniformMap);
2351 sh::TraverseShaderVariable(uniform, false, &visitor);
Jamie Madill55def582015-05-04 11:24:57 -04002352 return;
2353 }
2354
Jamie Madill91445bc2015-09-23 16:47:53 -04002355 const ShaderD3D *shaderD3D = GetImplAs<ShaderD3D>(shader);
Jamie Madill91445bc2015-09-23 16:47:53 -04002356 unsigned int startRegister = shaderD3D->getUniformRegister(uniform.name);
Xinghua Cao26143fd2017-11-01 18:19:05 +08002357 ShShaderOutput outputType = shaderD3D->getCompilerOutputType();
Jamie Madillcc2ed612017-03-14 15:59:00 -04002358 sh::HLSLBlockEncoder encoder(sh::HLSLBlockEncoder::GetStrategyFor(outputType), true);
Jamie Madill62d31cb2015-09-11 13:25:51 -04002359 encoder.skipRegisters(startRegister);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002360
Jamie Madill8c78ce42018-12-16 19:14:58 -05002361 UniformEncodingVisitorD3D visitor(shader->getType(), HLSLRegisterType::None, &encoder,
2362 uniformMap);
2363 sh::TraverseShaderVariable(uniform, false, &visitor);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002364}
2365
Xinghua Caof3179a62018-07-12 16:22:06 +08002366bool ProgramD3D::hasNamedUniform(const std::string &name)
Jamie Madill62d31cb2015-09-11 13:25:51 -04002367{
2368 for (D3DUniform *d3dUniform : mD3DUniforms)
2369 {
2370 if (d3dUniform->name == name)
2371 {
Xinghua Caof3179a62018-07-12 16:22:06 +08002372 return true;
Jamie Madill62d31cb2015-09-11 13:25:51 -04002373 }
2374 }
2375
Xinghua Caof3179a62018-07-12 16:22:06 +08002376 return false;
Jamie Madill62d31cb2015-09-11 13:25:51 -04002377}
2378
Jamie Madill134f93d2017-08-31 17:11:00 -04002379// Assume count is already clamped.
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002380template <typename T>
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002381void ProgramD3D::setUniformImpl(const gl::VariableLocation &locationInfo,
Jamie Madill134f93d2017-08-31 17:11:00 -04002382 GLsizei count,
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002383 const T *v,
2384 uint8_t *targetData,
Jamie Madill33bb7c42017-09-09 23:32:51 -04002385 GLenum uniformType)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002386{
Jamie Madill493f9572018-05-24 19:52:15 -04002387 D3DUniform *targetUniform = mD3DUniforms[locationInfo.index];
2388 const int components = targetUniform->typeInfo.componentCount;
Olli Etuaho1734e172017-10-27 15:30:27 +03002389 const unsigned int arrayElementOffset = locationInfo.arrayIndex;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002390
Jamie Madill33bb7c42017-09-09 23:32:51 -04002391 if (targetUniform->typeInfo.type == uniformType)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002392 {
Olli Etuahoc8538042017-09-27 11:20:15 +03002393 T *dest = reinterpret_cast<T *>(targetData) + arrayElementOffset * 4;
Jamie Madill33bb7c42017-09-09 23:32:51 -04002394 const T *source = v;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002395
Jamie Madill33bb7c42017-09-09 23:32:51 -04002396 for (GLint i = 0; i < count; i++, dest += 4, source += components)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002397 {
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002398 memcpy(dest, source, components * sizeof(T));
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002399 }
2400 }
Jamie Madill33bb7c42017-09-09 23:32:51 -04002401 else
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002402 {
Jamie Madill33bb7c42017-09-09 23:32:51 -04002403 ASSERT(targetUniform->typeInfo.type == gl::VariableBoolVectorType(uniformType));
Olli Etuahoc8538042017-09-27 11:20:15 +03002404 GLint *boolParams = reinterpret_cast<GLint *>(targetData) + arrayElementOffset * 4;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002405
Jamie Madill134f93d2017-08-31 17:11:00 -04002406 for (GLint i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002407 {
Jamie Madill334d6152015-10-22 14:00:28 -04002408 GLint *dest = boolParams + (i * 4);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002409 const T *source = v + (i * components);
2410
2411 for (int c = 0; c < components; c++)
2412 {
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002413 dest[c] = (source[c] == static_cast<T>(0)) ? GL_FALSE : GL_TRUE;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002414 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002415 }
Brandon Jones18bd4102014-09-22 14:21:44 -07002416 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002417}
2418
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002419template <typename T>
Jamie Madill33bb7c42017-09-09 23:32:51 -04002420void ProgramD3D::setUniformInternal(GLint location, GLsizei count, const T *v, GLenum uniformType)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002421{
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002422 const gl::VariableLocation &locationInfo = mState.getUniformLocations()[location];
2423 D3DUniform *targetUniform = mD3DUniforms[locationInfo.index];
2424
Jamie Madill33bb7c42017-09-09 23:32:51 -04002425 if (targetUniform->typeInfo.isSampler)
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002426 {
Jamie Madill33bb7c42017-09-09 23:32:51 -04002427 ASSERT(uniformType == GL_INT);
Jamie Madill80823cc2017-09-14 15:46:21 -04002428 size_t size = count * sizeof(T);
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002429 GLint *dest = &targetUniform->mSamplerData[locationInfo.arrayIndex];
Jamie Madill80823cc2017-09-14 15:46:21 -04002430 if (memcmp(dest, v, size) != 0)
2431 {
2432 memcpy(dest, v, size);
2433 mDirtySamplerMapping = true;
2434 }
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002435 return;
2436 }
2437
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002438 for (gl::ShaderType shaderType : gl::AllShaderTypes())
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002439 {
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002440 if (targetUniform->mShaderData[shaderType])
2441 {
2442 setUniformImpl(locationInfo, count, v, targetUniform->mShaderData[shaderType],
2443 uniformType);
2444 mShaderUniformsDirty.set(shaderType);
2445 }
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002446 }
2447}
2448
2449template <int cols, int rows>
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002450void ProgramD3D::setUniformMatrixfvInternal(GLint location,
2451 GLsizei countIn,
2452 GLboolean transpose,
Luc Ferron46bcea52018-05-31 09:48:36 -04002453 const GLfloat *value)
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002454{
Xinghua Cao6dfdca82018-08-03 17:10:55 +08002455 D3DUniform *targetUniform = getD3DUniformFromLocation(location);
Luc Ferron46bcea52018-05-31 09:48:36 -04002456 const gl::VariableLocation &uniformLocation = mState.getUniformLocations()[location];
2457 unsigned int arrayElementOffset = uniformLocation.arrayIndex;
2458 unsigned int elementCount = targetUniform->getArraySizeProduct();
2459
2460 // Internally store matrices as transposed versions to accomodate HLSL matrix indexing
2461 transpose = !transpose;
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002462
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002463 for (gl::ShaderType shaderType : gl::AllShaderTypes())
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002464 {
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002465 if (targetUniform->mShaderData[shaderType])
Jamie Madill80823cc2017-09-14 15:46:21 -04002466 {
Luc Ferron46bcea52018-05-31 09:48:36 -04002467 if (SetFloatUniformMatrix<cols, rows>(arrayElementOffset, elementCount, countIn,
2468 transpose, value,
2469 targetUniform->mShaderData[shaderType]))
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002470 {
2471 mShaderUniformsDirty.set(shaderType);
2472 }
Jamie Madill80823cc2017-09-14 15:46:21 -04002473 }
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002474 }
2475}
2476
Jamie Madill62d31cb2015-09-11 13:25:51 -04002477void ProgramD3D::assignAllSamplerRegisters()
Jamie Madilla2eb02c2015-09-11 12:31:41 +00002478{
Olli Etuaho465835d2017-09-26 13:34:10 +03002479 for (size_t uniformIndex = 0; uniformIndex < mD3DUniforms.size(); ++uniformIndex)
Jamie Madilla2eb02c2015-09-11 12:31:41 +00002480 {
Olli Etuaho465835d2017-09-26 13:34:10 +03002481 if (mD3DUniforms[uniformIndex]->isSampler())
Jamie Madillfb536032015-09-11 13:19:49 -04002482 {
Olli Etuaho465835d2017-09-26 13:34:10 +03002483 assignSamplerRegisters(uniformIndex);
Jamie Madillfb536032015-09-11 13:19:49 -04002484 }
Jamie Madilla2eb02c2015-09-11 12:31:41 +00002485 }
2486}
2487
Olli Etuaho465835d2017-09-26 13:34:10 +03002488void ProgramD3D::assignSamplerRegisters(size_t uniformIndex)
Jamie Madillfb536032015-09-11 13:19:49 -04002489{
Olli Etuaho465835d2017-09-26 13:34:10 +03002490 D3DUniform *d3dUniform = mD3DUniforms[uniformIndex];
Jamie Madill62d31cb2015-09-11 13:25:51 -04002491 ASSERT(d3dUniform->isSampler());
Olli Etuaho465835d2017-09-26 13:34:10 +03002492 // If the uniform is an array of arrays, then we have separate entries for each inner array in
2493 // mD3DUniforms. However, the sampler register info is stored in the shader only for the
2494 // outermost array.
2495 std::vector<unsigned int> subscripts;
Jamie Madill8c78ce42018-12-16 19:14:58 -05002496 const std::string baseName = gl::ParseResourceName(d3dUniform->name, &subscripts);
2497 unsigned int registerOffset =
2498 mState.getUniforms()[uniformIndex].parentArrayIndex() * d3dUniform->getArraySizeProduct();
Olli Etuaho465835d2017-09-26 13:34:10 +03002499
Jiawei Shao467c15f2018-04-24 15:04:26 +08002500 bool hasUniform = false;
2501 for (gl::ShaderType shaderType : gl::AllShaderTypes())
Jamie Madillfb536032015-09-11 13:19:49 -04002502 {
Jiawei Shao467c15f2018-04-24 15:04:26 +08002503 if (!mState.getAttachedShader(shaderType))
Xinghua Caob1239382016-12-13 15:07:05 +08002504 {
Jiawei Shao467c15f2018-04-24 15:04:26 +08002505 continue;
Xinghua Caob1239382016-12-13 15:07:05 +08002506 }
Jiawei Shao467c15f2018-04-24 15:04:26 +08002507
2508 const ShaderD3D *shaderD3D = GetImplAs<ShaderD3D>(mState.getAttachedShader(shaderType));
2509 if (shaderD3D->hasUniform(baseName))
Xinghua Caob1239382016-12-13 15:07:05 +08002510 {
Jiawei Shao467c15f2018-04-24 15:04:26 +08002511 d3dUniform->mShaderRegisterIndexes[shaderType] =
2512 shaderD3D->getUniformRegister(baseName) + registerOffset;
2513 ASSERT(d3dUniform->mShaderRegisterIndexes[shaderType] != GL_INVALID_VALUE);
2514
2515 AssignSamplers(d3dUniform->mShaderRegisterIndexes[shaderType], d3dUniform->typeInfo,
2516 d3dUniform->getArraySizeProduct(), mShaderSamplers[shaderType],
2517 &mUsedShaderSamplerRanges[shaderType]);
2518 hasUniform = true;
Xinghua Caob1239382016-12-13 15:07:05 +08002519 }
Jamie Madillfb536032015-09-11 13:19:49 -04002520 }
Jiawei Shao467c15f2018-04-24 15:04:26 +08002521
2522 ASSERT(hasUniform);
Jamie Madillfb536032015-09-11 13:19:49 -04002523}
2524
Jamie Madill62d31cb2015-09-11 13:25:51 -04002525// static
2526void ProgramD3D::AssignSamplers(unsigned int startSamplerIndex,
Jamie Madill33bb7c42017-09-09 23:32:51 -04002527 const gl::UniformTypeInfo &typeInfo,
Jamie Madilld3dfda22015-07-06 08:28:49 -04002528 unsigned int samplerCount,
2529 std::vector<Sampler> &outSamplers,
Xinghua Cao6dfdca82018-08-03 17:10:55 +08002530 gl::RangeUI *outUsedRange)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002531{
2532 unsigned int samplerIndex = startSamplerIndex;
Xinghua Cao6dfdca82018-08-03 17:10:55 +08002533 unsigned int low = outUsedRange->low();
2534 unsigned int high = outUsedRange->high();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002535
2536 do
2537 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002538 ASSERT(samplerIndex < outSamplers.size());
2539 Sampler *sampler = &outSamplers[samplerIndex];
2540 sampler->active = true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002541 sampler->textureType = gl::FromGLenum<gl::TextureType>(typeInfo.textureType);
Jamie Madill62d31cb2015-09-11 13:25:51 -04002542 sampler->logicalTextureUnit = 0;
Xinghua Cao6dfdca82018-08-03 17:10:55 +08002543 low = std::min(samplerIndex, low);
2544 high = std::max(samplerIndex + 1, high);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002545 samplerIndex++;
2546 } while (samplerIndex < startSamplerIndex + samplerCount);
Xinghua Cao6dfdca82018-08-03 17:10:55 +08002547
2548 ASSERT(low < high);
2549 *outUsedRange = gl::RangeUI(low, high);
Brandon Jones18bd4102014-09-22 14:21:44 -07002550}
2551
Xinghua Cao26143fd2017-11-01 18:19:05 +08002552void ProgramD3D::assignAllImageRegisters()
2553{
2554 for (size_t uniformIndex = 0; uniformIndex < mD3DUniforms.size(); ++uniformIndex)
2555 {
Xinghua Caof3179a62018-07-12 16:22:06 +08002556 if (mD3DUniforms[uniformIndex]->isImage() && !mD3DUniforms[uniformIndex]->isImage2D())
Xinghua Cao26143fd2017-11-01 18:19:05 +08002557 {
2558 assignImageRegisters(uniformIndex);
2559 }
2560 }
2561}
2562
2563void ProgramD3D::assignImageRegisters(size_t uniformIndex)
2564{
2565 D3DUniform *d3dUniform = mD3DUniforms[uniformIndex];
2566 ASSERT(d3dUniform->isImage());
2567 // If the uniform is an array of arrays, then we have separate entries for each inner array in
2568 // mD3DUniforms. However, the image register info is stored in the shader only for the
2569 // outermost array.
2570 std::vector<unsigned int> subscripts;
Jamie Madill8c78ce42018-12-16 19:14:58 -05002571 const std::string baseName = gl::ParseResourceName(d3dUniform->name, &subscripts);
2572 unsigned int registerOffset =
2573 mState.getUniforms()[uniformIndex].parentArrayIndex() * d3dUniform->getArraySizeProduct();
Xinghua Cao26143fd2017-11-01 18:19:05 +08002574
Jiawei Shao385b3e02018-03-21 09:43:28 +08002575 const gl::Shader *computeShader = mState.getAttachedShader(gl::ShaderType::Compute);
Xinghua Cao26143fd2017-11-01 18:19:05 +08002576 if (computeShader)
2577 {
Jiawei Shao385b3e02018-03-21 09:43:28 +08002578 const ShaderD3D *computeShaderD3D =
2579 GetImplAs<ShaderD3D>(mState.getAttachedShader(gl::ShaderType::Compute));
Xinghua Cao26143fd2017-11-01 18:19:05 +08002580 ASSERT(computeShaderD3D->hasUniform(baseName));
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002581 d3dUniform->mShaderRegisterIndexes[gl::ShaderType::Compute] =
Xinghua Cao26143fd2017-11-01 18:19:05 +08002582 computeShaderD3D->getUniformRegister(baseName) + registerOffset;
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002583 ASSERT(d3dUniform->mShaderRegisterIndexes[gl::ShaderType::Compute] != GL_INVALID_INDEX);
Xinghua Cao26143fd2017-11-01 18:19:05 +08002584 auto bindingIter = mImageBindingMap.find(baseName);
2585 ASSERT(bindingIter != mImageBindingMap.end());
2586 if (d3dUniform->regType == HLSLRegisterType::Texture)
2587 {
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002588 AssignImages(d3dUniform->mShaderRegisterIndexes[gl::ShaderType::Compute],
2589 bindingIter->second, d3dUniform->getArraySizeProduct(), mReadonlyImagesCS,
Xinghua Cao26143fd2017-11-01 18:19:05 +08002590 &mUsedComputeReadonlyImageRange);
2591 }
2592 else if (d3dUniform->regType == HLSLRegisterType::UnorderedAccessView)
2593 {
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002594 AssignImages(d3dUniform->mShaderRegisterIndexes[gl::ShaderType::Compute],
2595 bindingIter->second, d3dUniform->getArraySizeProduct(), mImagesCS,
2596 &mUsedComputeImageRange);
Xinghua Cao26143fd2017-11-01 18:19:05 +08002597 }
2598 else
2599 {
2600 UNREACHABLE();
2601 }
2602 }
2603 else
2604 {
2605 // TODO(xinghua.cao@intel.com): Implement image variables in vertex shader and pixel shader.
2606 UNIMPLEMENTED();
2607 }
2608}
2609
2610// static
2611void ProgramD3D::AssignImages(unsigned int startImageIndex,
2612 int startLogicalImageUnit,
2613 unsigned int imageCount,
2614 std::vector<Image> &outImages,
Xinghua Cao6dfdca82018-08-03 17:10:55 +08002615 gl::RangeUI *outUsedRange)
Xinghua Cao26143fd2017-11-01 18:19:05 +08002616{
2617 unsigned int imageIndex = startImageIndex;
Xinghua Cao6dfdca82018-08-03 17:10:55 +08002618 unsigned int low = outUsedRange->low();
2619 unsigned int high = outUsedRange->high();
2620
Xinghua Cao26143fd2017-11-01 18:19:05 +08002621 // If declare without a binding qualifier, any uniform image variable (include all elements of
2622 // unbound image array) shoud be bound to unit zero.
2623 if (startLogicalImageUnit == -1)
2624 {
2625 ASSERT(imageIndex < outImages.size());
2626 Image *image = &outImages[imageIndex];
2627 image->active = true;
2628 image->logicalImageUnit = 0;
Xinghua Cao6dfdca82018-08-03 17:10:55 +08002629 low = std::min(imageIndex, low);
2630 high = std::max(imageIndex + 1, high);
2631 ASSERT(low < high);
2632 *outUsedRange = gl::RangeUI(low, high);
Xinghua Cao26143fd2017-11-01 18:19:05 +08002633 return;
2634 }
2635
2636 unsigned int logcalImageUnit = startLogicalImageUnit;
2637 do
2638 {
2639 ASSERT(imageIndex < outImages.size());
2640 Image *image = &outImages[imageIndex];
2641 image->active = true;
2642 image->logicalImageUnit = logcalImageUnit;
Xinghua Cao6dfdca82018-08-03 17:10:55 +08002643 low = std::min(imageIndex, low);
2644 high = std::max(imageIndex + 1, high);
Xinghua Cao26143fd2017-11-01 18:19:05 +08002645 imageIndex++;
2646 logcalImageUnit++;
2647 } while (imageIndex < startImageIndex + imageCount);
Xinghua Cao6dfdca82018-08-03 17:10:55 +08002648
2649 ASSERT(low < high);
2650 *outUsedRange = gl::RangeUI(low, high);
Xinghua Cao26143fd2017-11-01 18:19:05 +08002651}
2652
Xinghua Caof3179a62018-07-12 16:22:06 +08002653void ProgramD3D::assignImage2DRegisters(unsigned int startImageIndex,
2654 int startLogicalImageUnit,
2655 bool readonly)
2656{
2657 if (readonly)
2658 {
2659 AssignImages(startImageIndex, startLogicalImageUnit, 1, mReadonlyImagesCS,
2660 &mUsedComputeReadonlyImageRange);
2661 }
2662 else
2663 {
2664 AssignImages(startImageIndex, startLogicalImageUnit, 1, mImagesCS, &mUsedComputeImageRange);
2665 }
2666}
2667
Brandon Jonesc9610c52014-08-25 17:02:59 -07002668void ProgramD3D::reset()
2669{
Xinghua Caob1239382016-12-13 15:07:05 +08002670 mVertexExecutables.clear();
2671 mPixelExecutables.clear();
Xinghua Caof3179a62018-07-12 16:22:06 +08002672 mComputeExecutables.clear();
Jamie Madill4e31ad52015-10-29 10:32:57 -04002673
Xinghua Caob1239382016-12-13 15:07:05 +08002674 for (auto &geometryExecutable : mGeometryExecutables)
Jamie Madill4e31ad52015-10-29 10:32:57 -04002675 {
Xinghua Caob1239382016-12-13 15:07:05 +08002676 geometryExecutable.reset(nullptr);
Jamie Madill4e31ad52015-10-29 10:32:57 -04002677 }
Brandon Joneseb994362014-09-24 10:27:28 -07002678
Jiawei Shao467c15f2018-04-24 15:04:26 +08002679 for (gl::ShaderType shaderType : gl::AllShaderTypes())
2680 {
2681 mShaderHLSL[shaderType].clear();
2682 mShaderWorkarounds[shaderType] = CompilerWorkaroundsD3D();
2683 }
Brandon Jones22502d52014-08-29 16:58:36 -07002684
Xinghua Cao26143fd2017-11-01 18:19:05 +08002685 mUsesFragDepth = false;
Martin Radev41ac68e2017-06-06 12:16:58 +03002686 mHasANGLEMultiviewEnabled = false;
2687 mUsesViewID = false;
Brandon Jones22502d52014-08-29 16:58:36 -07002688 mPixelShaderKey.clear();
Xinghua Cao26143fd2017-11-01 18:19:05 +08002689 mUsesPointSize = false;
Jamie Madill3e14e2b2015-10-29 14:38:53 -04002690 mUsesFlatInterpolation = false;
Brandon Jones22502d52014-08-29 16:58:36 -07002691
Jamie Madill62d31cb2015-09-11 13:25:51 -04002692 SafeDeleteContainer(mD3DUniforms);
Jamie Madill4a3c2342015-10-08 12:58:45 -04002693 mD3DUniformBlocks.clear();
Qin Jiajiaa602f902018-09-11 14:40:24 +08002694 mD3DShaderStorageBlocks.clear();
Jamie Madill62d31cb2015-09-11 13:25:51 -04002695
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002696 for (gl::ShaderType shaderType : gl::AllShaderTypes())
2697 {
2698 mShaderUniformStorages[shaderType].reset();
Jiawei Shao467c15f2018-04-24 15:04:26 +08002699 mShaderSamplers[shaderType].clear();
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002700 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002701
Xinghua Cao26143fd2017-11-01 18:19:05 +08002702 mImagesCS.clear();
2703 mReadonlyImagesCS.clear();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002704
Xinghua Cao6dfdca82018-08-03 17:10:55 +08002705 mUsedShaderSamplerRanges.fill({0, 0});
Xinghua Cao26143fd2017-11-01 18:19:05 +08002706 mDirtySamplerMapping = true;
Xinghua Cao6dfdca82018-08-03 17:10:55 +08002707 mUsedComputeImageRange = {0, 0};
2708 mUsedComputeReadonlyImageRange = {0, 0};
Jamie Madill437d2662014-12-05 14:23:35 -05002709
Jamie Madill8047c0d2016-03-07 13:02:12 -05002710 mAttribLocationToD3DSemantic.fill(-1);
Jamie Madillccdf74b2015-08-18 10:46:12 -04002711
Jamie Madill9fc36822015-11-18 13:08:07 -05002712 mStreamOutVaryings.clear();
Jamie Madill4e31ad52015-10-29 10:32:57 -04002713
2714 mGeometryShaderPreamble.clear();
Jamie Madill561ed3a2017-08-31 16:48:09 -04002715
Jiawei Shao3dd8d2912018-03-30 09:39:09 +08002716 markUniformsClean();
Jamie Madill0e7f1732017-09-09 23:32:50 -04002717
2718 mCachedPixelExecutableIndex.reset();
2719 mCachedVertexExecutableIndex.reset();
Brandon Jonesc9610c52014-08-25 17:02:59 -07002720}
2721
Geoff Lang7dd2e102014-11-10 15:19:26 -05002722unsigned int ProgramD3D::getSerial() const
2723{
2724 return mSerial;
2725}
2726
2727unsigned int ProgramD3D::issueSerial()
2728{
2729 return mCurrentSerial++;
2730}
2731
jchen103fd614d2018-08-13 12:21:58 +08002732void ProgramD3D::initAttribLocationsToD3DSemantic()
Jamie Madill63805b42015-08-25 13:17:39 -04002733{
Jiawei Shao385b3e02018-03-21 09:43:28 +08002734 gl::Shader *vertexShader = mState.getAttachedShader(gl::ShaderType::Vertex);
Jamie Madill63805b42015-08-25 13:17:39 -04002735 ASSERT(vertexShader != nullptr);
2736
2737 // Init semantic index
Jamie Madill34ca4f52017-06-13 11:49:39 -04002738 int semanticIndex = 0;
jchen103fd614d2018-08-13 12:21:58 +08002739 for (const sh::Attribute &attribute : vertexShader->getActiveAttributes())
Jamie Madill63805b42015-08-25 13:17:39 -04002740 {
Jamie Madill8047c0d2016-03-07 13:02:12 -05002741 int regCount = gl::VariableRegisterCount(attribute.type);
Jamie Madill34ca4f52017-06-13 11:49:39 -04002742 GLuint location = mState.getAttributeLocation(attribute.name);
2743 ASSERT(location != std::numeric_limits<GLuint>::max());
Jamie Madill63805b42015-08-25 13:17:39 -04002744
Jamie Madill8047c0d2016-03-07 13:02:12 -05002745 for (int reg = 0; reg < regCount; ++reg)
Jamie Madill63805b42015-08-25 13:17:39 -04002746 {
Jamie Madill34ca4f52017-06-13 11:49:39 -04002747 mAttribLocationToD3DSemantic[location + reg] = semanticIndex++;
Jamie Madill63805b42015-08-25 13:17:39 -04002748 }
2749 }
Jamie Madill437d2662014-12-05 14:23:35 -05002750}
2751
Jamie Madilla779b612017-07-24 11:46:05 -04002752void ProgramD3D::updateCachedInputLayout(Serial associatedSerial, const gl::State &state)
Jamie Madilld3dfda22015-07-06 08:28:49 -04002753{
Jamie Madilla779b612017-07-24 11:46:05 -04002754 if (mCurrentVertexArrayStateSerial == associatedSerial)
2755 {
2756 return;
2757 }
2758
2759 mCurrentVertexArrayStateSerial = associatedSerial;
Jamie Madillbd136f92015-08-10 14:51:37 -04002760 mCachedInputLayout.clear();
Jamie Madill0e7f1732017-09-09 23:32:50 -04002761
Jamie Madilld3dfda22015-07-06 08:28:49 -04002762 const auto &vertexAttributes = state.getVertexArray()->getVertexAttributes();
Jamie Madillf8dd7b12015-08-05 13:50:08 -04002763
Jamie Madill6de51852017-04-12 09:53:01 -04002764 for (size_t locationIndex : mState.getActiveAttribLocationsMask())
Jamie Madilld3dfda22015-07-06 08:28:49 -04002765 {
Jamie Madill8047c0d2016-03-07 13:02:12 -05002766 int d3dSemantic = mAttribLocationToD3DSemantic[locationIndex];
Jamie Madilld3dfda22015-07-06 08:28:49 -04002767
Jamie Madill8047c0d2016-03-07 13:02:12 -05002768 if (d3dSemantic != -1)
Jamie Madilld3dfda22015-07-06 08:28:49 -04002769 {
Jamie Madill8047c0d2016-03-07 13:02:12 -05002770 if (mCachedInputLayout.size() < static_cast<size_t>(d3dSemantic + 1))
Jamie Madillbd136f92015-08-10 14:51:37 -04002771 {
Frank Henigmand633b152018-10-04 23:34:31 -04002772 mCachedInputLayout.resize(d3dSemantic + 1, angle::FormatID::NONE);
Jamie Madillbd136f92015-08-10 14:51:37 -04002773 }
Jamie Madill8047c0d2016-03-07 13:02:12 -05002774 mCachedInputLayout[d3dSemantic] =
Frank Henigmand633b152018-10-04 23:34:31 -04002775 GetVertexFormatID(vertexAttributes[locationIndex],
2776 state.getVertexAttribCurrentValue(locationIndex).Type);
Jamie Madilld3dfda22015-07-06 08:28:49 -04002777 }
2778 }
Jamie Madill4c19a8a2017-07-24 11:46:06 -04002779
2780 VertexExecutable::getSignature(mRenderer, mCachedInputLayout, &mCachedVertexSignature);
Jamie Madill0e7f1732017-09-09 23:32:50 -04002781
2782 updateCachedVertexExecutableIndex();
Jamie Madill4c19a8a2017-07-24 11:46:06 -04002783}
2784
2785void ProgramD3D::updateCachedOutputLayout(const gl::Context *context,
2786 const gl::Framebuffer *framebuffer)
2787{
Jamie Madill0e7f1732017-09-09 23:32:50 -04002788 mPixelShaderOutputLayoutCache.clear();
2789
2790 FramebufferD3D *fboD3D = GetImplAs<FramebufferD3D>(framebuffer);
2791 const auto &colorbuffers = fboD3D->getColorAttachmentsForRender(context);
2792
2793 for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment)
2794 {
2795 const gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment];
2796
2797 if (colorbuffer)
2798 {
2799 auto binding = colorbuffer->getBinding() == GL_BACK ? GL_COLOR_ATTACHMENT0
2800 : colorbuffer->getBinding();
2801 mPixelShaderOutputLayoutCache.push_back(binding);
2802 }
2803 else
2804 {
2805 mPixelShaderOutputLayoutCache.push_back(GL_NONE);
2806 }
2807 }
2808
2809 updateCachedPixelExecutableIndex();
Jamie Madilld3dfda22015-07-06 08:28:49 -04002810}
2811
Xinghua Caof3179a62018-07-12 16:22:06 +08002812void ProgramD3D::updateCachedComputeImage2DBindLayout(const gl::Context *context)
2813{
2814 const auto &glState = context->getState();
2815 for (auto &image2DBindLayout : mComputeShaderImage2DBindLayoutCache)
2816 {
2817 const gl::ImageUnit &imageUnit = glState.getImageUnit(image2DBindLayout.first);
2818 if (imageUnit.texture.get())
2819 {
2820 image2DBindLayout.second = imageUnit.texture->getType();
2821 }
2822 else
2823 {
2824 image2DBindLayout.second = gl::TextureType::_2D;
2825 }
2826 }
2827
2828 updateCachedComputeExecutableIndex();
2829}
2830
Jamie Madill192745a2016-12-22 15:58:21 -05002831void ProgramD3D::gatherTransformFeedbackVaryings(const gl::VaryingPacking &varyingPacking,
2832 const BuiltinInfo &builtins)
Jamie Madillccdf74b2015-08-18 10:46:12 -04002833{
Jamie Madill9fc36822015-11-18 13:08:07 -05002834 const std::string &varyingSemantic =
2835 GetVaryingSemantic(mRenderer->getMajorShaderModel(), usesPointSize());
2836
Jamie Madillccdf74b2015-08-18 10:46:12 -04002837 // Gather the linked varyings that are used for transform feedback, they should all exist.
Jamie Madill9fc36822015-11-18 13:08:07 -05002838 mStreamOutVaryings.clear();
2839
Jamie Madill48ef11b2016-04-27 15:21:52 -04002840 const auto &tfVaryingNames = mState.getTransformFeedbackVaryingNames();
Jamie Madill9fc36822015-11-18 13:08:07 -05002841 for (unsigned int outputSlot = 0; outputSlot < static_cast<unsigned int>(tfVaryingNames.size());
2842 ++outputSlot)
Jamie Madillccdf74b2015-08-18 10:46:12 -04002843 {
Jamie Madill9fc36822015-11-18 13:08:07 -05002844 const auto &tfVaryingName = tfVaryingNames[outputSlot];
2845 if (tfVaryingName == "gl_Position")
Jamie Madillccdf74b2015-08-18 10:46:12 -04002846 {
Jamie Madill9fc36822015-11-18 13:08:07 -05002847 if (builtins.glPosition.enabled)
Jamie Madillccdf74b2015-08-18 10:46:12 -04002848 {
Jiawei Shaoda92a472018-07-02 15:55:19 +08002849 mStreamOutVaryings.emplace_back(builtins.glPosition.semantic,
2850 builtins.glPosition.index, 4, outputSlot);
Jamie Madill9fc36822015-11-18 13:08:07 -05002851 }
2852 }
2853 else if (tfVaryingName == "gl_FragCoord")
2854 {
2855 if (builtins.glFragCoord.enabled)
2856 {
Jiawei Shaoda92a472018-07-02 15:55:19 +08002857 mStreamOutVaryings.emplace_back(builtins.glFragCoord.semantic,
2858 builtins.glFragCoord.index, 4, outputSlot);
Jamie Madill9fc36822015-11-18 13:08:07 -05002859 }
2860 }
2861 else if (tfVaryingName == "gl_PointSize")
2862 {
2863 if (builtins.glPointSize.enabled)
2864 {
Jiawei Shaoda92a472018-07-02 15:55:19 +08002865 mStreamOutVaryings.emplace_back("PSIZE", 0, 1, outputSlot);
Jamie Madill9fc36822015-11-18 13:08:07 -05002866 }
2867 }
2868 else
2869 {
Jiawei Shaoda92a472018-07-02 15:55:19 +08002870 const auto &registerInfos = varyingPacking.getRegisterList();
2871 for (GLuint registerIndex = 0u; registerIndex < registerInfos.size(); ++registerIndex)
Jamie Madill9fc36822015-11-18 13:08:07 -05002872 {
Jiawei Shaoda92a472018-07-02 15:55:19 +08002873 const auto &registerInfo = registerInfos[registerIndex];
Xinghua Cao6dfdca82018-08-03 17:10:55 +08002874 const auto &varying = *registerInfo.packedVarying->varying;
2875 GLenum transposedType = gl::TransposeMatrixType(varying.type);
2876 int componentCount = gl::VariableColumnCount(transposedType);
jchen108225e732017-11-14 16:29:03 +08002877 ASSERT(!varying.isBuiltIn() && !varying.isStruct());
Jamie Madill55c25d02015-11-18 13:08:08 -05002878
Jamie Madill9fc36822015-11-18 13:08:07 -05002879 // There can be more than one register assigned to a particular varying, and each
2880 // register needs its own stream out entry.
jchen108225e732017-11-14 16:29:03 +08002881 if (registerInfo.tfVaryingName() == tfVaryingName)
Jamie Madill9fc36822015-11-18 13:08:07 -05002882 {
Jiawei Shaoda92a472018-07-02 15:55:19 +08002883 mStreamOutVaryings.emplace_back(varyingSemantic, registerIndex, componentCount,
2884 outputSlot);
Jamie Madill9fc36822015-11-18 13:08:07 -05002885 }
Jamie Madillccdf74b2015-08-18 10:46:12 -04002886 }
2887 }
2888 }
2889}
Jamie Madill62d31cb2015-09-11 13:25:51 -04002890
2891D3DUniform *ProgramD3D::getD3DUniformFromLocation(GLint location)
2892{
Jamie Madill48ef11b2016-04-27 15:21:52 -04002893 return mD3DUniforms[mState.getUniformLocations()[location].index];
Jamie Madill62d31cb2015-09-11 13:25:51 -04002894}
Jamie Madill4a3c2342015-10-08 12:58:45 -04002895
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002896const D3DUniform *ProgramD3D::getD3DUniformFromLocation(GLint location) const
2897{
2898 return mD3DUniforms[mState.getUniformLocations()[location].index];
2899}
2900
Sami Väisänen46eaa942016-06-29 10:26:37 +03002901void ProgramD3D::setPathFragmentInputGen(const std::string &inputName,
2902 GLenum genMode,
2903 GLint components,
2904 const GLfloat *coeffs)
2905{
2906 UNREACHABLE();
2907}
2908
Jamie Madill4c19a8a2017-07-24 11:46:06 -04002909bool ProgramD3D::hasVertexExecutableForCachedInputLayout()
2910{
Jamie Madill0e7f1732017-09-09 23:32:50 -04002911 return mCachedVertexExecutableIndex.valid();
Jamie Madill4c19a8a2017-07-24 11:46:06 -04002912}
2913
Jamie Madill493f9572018-05-24 19:52:15 -04002914bool ProgramD3D::hasGeometryExecutableForPrimitiveType(gl::PrimitiveMode drawMode)
Jamie Madill4c19a8a2017-07-24 11:46:06 -04002915{
2916 if (!usesGeometryShader(drawMode))
2917 {
2918 // No shader necessary mean we have the required (null) executable.
2919 return true;
2920 }
2921
Jamie Madill04796cd2018-05-24 19:52:16 -04002922 gl::PrimitiveMode geometryShaderType = GetGeometryShaderTypeFromDrawMode(drawMode);
Jamie Madill4c19a8a2017-07-24 11:46:06 -04002923 return mGeometryExecutables[geometryShaderType].get() != nullptr;
2924}
2925
2926bool ProgramD3D::hasPixelExecutableForCachedOutputLayout()
2927{
Jamie Madill0e7f1732017-09-09 23:32:50 -04002928 return mCachedPixelExecutableIndex.valid();
Jamie Madill4c19a8a2017-07-24 11:46:06 -04002929}
2930
Xinghua Caof3179a62018-07-12 16:22:06 +08002931bool ProgramD3D::hasComputeExecutableForCachedImage2DBindLayout()
2932{
2933 return mCachedComputeExecutableIndex.valid();
2934}
2935
Jamie Madill54164b02017-08-28 15:17:37 -04002936template <typename DestT>
2937void ProgramD3D::getUniformInternal(GLint location, DestT *dataOut) const
2938{
2939 const gl::VariableLocation &locationInfo = mState.getUniformLocations()[location];
2940 const gl::LinkedUniform &uniform = mState.getUniforms()[locationInfo.index];
2941
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002942 const D3DUniform *targetUniform = getD3DUniformFromLocation(location);
Olli Etuaho1734e172017-10-27 15:30:27 +03002943 const uint8_t *srcPointer = targetUniform->getDataPtrToElement(locationInfo.arrayIndex);
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002944
2945 if (gl::IsMatrixType(uniform.type))
2946 {
Luc Ferron48cdc2e2018-05-31 09:58:34 -04002947 GetMatrixUniform(uniform.type, dataOut, reinterpret_cast<const DestT *>(srcPointer), true);
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002948 }
2949 else
2950 {
2951 memcpy(dataOut, srcPointer, uniform.getElementSize());
2952 }
Jamie Madill54164b02017-08-28 15:17:37 -04002953}
2954
2955void ProgramD3D::getUniformfv(const gl::Context *context, GLint location, GLfloat *params) const
2956{
2957 getUniformInternal(location, params);
2958}
2959
2960void ProgramD3D::getUniformiv(const gl::Context *context, GLint location, GLint *params) const
2961{
2962 getUniformInternal(location, params);
2963}
2964
2965void ProgramD3D::getUniformuiv(const gl::Context *context, GLint location, GLuint *params) const
2966{
2967 getUniformInternal(location, params);
2968}
2969
Jamie Madill0e7f1732017-09-09 23:32:50 -04002970void ProgramD3D::updateCachedVertexExecutableIndex()
2971{
2972 mCachedVertexExecutableIndex.reset();
2973 for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++)
2974 {
2975 if (mVertexExecutables[executableIndex]->matchesSignature(mCachedVertexSignature))
2976 {
2977 mCachedVertexExecutableIndex = executableIndex;
2978 break;
2979 }
2980 }
2981}
2982
2983void ProgramD3D::updateCachedPixelExecutableIndex()
2984{
2985 mCachedPixelExecutableIndex.reset();
2986 for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++)
2987 {
2988 if (mPixelExecutables[executableIndex]->matchesSignature(mPixelShaderOutputLayoutCache))
2989 {
2990 mCachedPixelExecutableIndex = executableIndex;
2991 break;
2992 }
2993 }
2994}
2995
Xinghua Caof3179a62018-07-12 16:22:06 +08002996void ProgramD3D::updateCachedComputeExecutableIndex()
2997{
2998 mCachedComputeExecutableIndex.reset();
2999 for (size_t executableIndex = 0; executableIndex < mComputeExecutables.size();
3000 executableIndex++)
3001 {
3002 if (mComputeExecutables[executableIndex]->matchesSignature(
3003 mComputeShaderImage2DBindLayoutCache))
3004 {
3005 mCachedComputeExecutableIndex = executableIndex;
3006 break;
3007 }
3008 }
3009}
3010
jchen103fd614d2018-08-13 12:21:58 +08003011void ProgramD3D::linkResources(const gl::ProgramLinkedResources &resources)
Jamie Madill6db1c2e2017-11-08 09:17:40 -05003012{
Qin Jiajia3026f112018-10-09 12:13:38 +08003013 InterfaceBlockInfo uniformBlockInfo;
Jiawei Shao385b3e02018-03-21 09:43:28 +08003014 for (gl::ShaderType shaderType : gl::AllShaderTypes())
Jamie Madill6db1c2e2017-11-08 09:17:40 -05003015 {
Jiawei Shao385b3e02018-03-21 09:43:28 +08003016 gl::Shader *shader = mState.getAttachedShader(shaderType);
3017 if (shader)
3018 {
Qin Jiajia3026f112018-10-09 12:13:38 +08003019 uniformBlockInfo.getShaderBlockInfo(shader->getUniformBlocks());
Jiawei Shao385b3e02018-03-21 09:43:28 +08003020 }
Jamie Madill6db1c2e2017-11-08 09:17:40 -05003021 }
3022
3023 // Gather interface block info.
3024 auto getUniformBlockSize = [&uniformBlockInfo](const std::string &name,
3025 const std::string &mappedName, size_t *sizeOut) {
3026 return uniformBlockInfo.getBlockSize(name, mappedName, sizeOut);
3027 };
3028
3029 auto getUniformBlockMemberInfo = [&uniformBlockInfo](const std::string &name,
3030 const std::string &mappedName,
3031 sh::BlockMemberInfo *infoOut) {
3032 return uniformBlockInfo.getBlockMemberInfo(name, mappedName, infoOut);
3033 };
3034
3035 resources.uniformBlockLinker.linkBlocks(getUniformBlockSize, getUniformBlockMemberInfo);
3036 initializeUniformBlocks();
3037
Qin Jiajia3026f112018-10-09 12:13:38 +08003038 InterfaceBlockInfo shaderStorageBlockInfo;
3039 for (gl::ShaderType shaderType : gl::AllShaderTypes())
3040 {
3041 gl::Shader *shader = mState.getAttachedShader(shaderType);
3042 if (shader)
3043 {
3044 shaderStorageBlockInfo.getShaderBlockInfo(shader->getShaderStorageBlocks());
3045 }
3046 }
3047 auto getShaderStorageBlockSize = [&shaderStorageBlockInfo](const std::string &name,
3048 const std::string &mappedName,
3049 size_t *sizeOut) {
3050 return shaderStorageBlockInfo.getBlockSize(name, mappedName, sizeOut);
Jamie Madill6db1c2e2017-11-08 09:17:40 -05003051 };
3052
Qin Jiajia3026f112018-10-09 12:13:38 +08003053 auto getShaderStorageBlockMemberInfo = [&shaderStorageBlockInfo](const std::string &name,
3054 const std::string &mappedName,
3055 sh::BlockMemberInfo *infoOut) {
3056 return shaderStorageBlockInfo.getBlockMemberInfo(name, mappedName, infoOut);
3057 };
Jamie Madill6db1c2e2017-11-08 09:17:40 -05003058
3059 resources.shaderStorageBlockLinker.linkBlocks(getShaderStorageBlockSize,
3060 getShaderStorageBlockMemberInfo);
Qin Jiajiaa602f902018-09-11 14:40:24 +08003061 initializeShaderStorageBlocks();
Enrico Gallia3b2e712018-12-08 16:46:48 -08003062
3063 std::map<int, unsigned int> sizeMap;
3064 getAtomicCounterBufferSizeMap(sizeMap);
3065 resources.atomicCounterBufferLinker.link(sizeMap);
3066}
3067
3068void ProgramD3D::getAtomicCounterBufferSizeMap(std::map<int, unsigned int> &sizeMapOut) const
3069{
3070 for (unsigned int index : mState.getAtomicCounterUniformRange())
3071 {
3072 const gl::LinkedUniform &glUniform = mState.getUniforms()[index];
3073
3074 auto &bufferDataSize = sizeMapOut[glUniform.binding];
3075
3076 // Calculate the size of the buffer by finding the end of the last uniform with the same
3077 // binding. The end of the uniform is calculated by finding the initial offset of the
3078 // uniform and adding size of the uniform. For arrays, the size is the number of elements
3079 // times the element size (should always by 4 for atomic_units).
3080 unsigned dataOffset =
3081 glUniform.offset + (glUniform.getBasicTypeElementCount() * glUniform.getElementSize());
3082 if (dataOffset > bufferDataSize)
3083 {
3084 bufferDataSize = dataOffset;
3085 }
3086 }
Jamie Madill6db1c2e2017-11-08 09:17:40 -05003087}
3088
Jamie Madill8047c0d2016-03-07 13:02:12 -05003089} // namespace rx