blob: d43e560f606afdbcb8731c9e9201f91bdea32ab3 [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);
Jamie Madilldd34b3b2019-01-16 09:59:54 -050056
57 gl::VertexAttribType attribType =
58 gl::FromGLenum<gl::VertexAttribType>(componentType);
59
Frank Henigmand633b152018-10-04 23:34:31 -040060 angle::FormatID defaultID =
Jamie Madilldd34b3b2019-01-16 09:59:54 -050061 gl::GetVertexFormatID(attribType, GL_FALSE, components, pureInt);
Brandon Joneseb994362014-09-24 10:27:28 -070062
Frank Henigmand633b152018-10-04 23:34:31 -040063 inputLayoutOut->push_back(defaultID);
Brandon Joneseb994362014-09-24 10:27:28 -070064 }
65 }
66 }
67}
68
Jamie Madill4c19a8a2017-07-24 11:46:06 -040069void GetDefaultOutputLayoutFromShader(
70 const std::vector<PixelShaderOutputVariable> &shaderOutputVars,
71 std::vector<GLenum> *outputLayoutOut)
Brandon Joneseb994362014-09-24 10:27:28 -070072{
Jamie Madill4c19a8a2017-07-24 11:46:06 -040073 outputLayoutOut->clear();
Brandon Joneseb994362014-09-24 10:27:28 -070074
Jamie Madillb4463142014-12-19 14:56:54 -050075 if (!shaderOutputVars.empty())
76 {
Jamie Madill4c19a8a2017-07-24 11:46:06 -040077 outputLayoutOut->push_back(GL_COLOR_ATTACHMENT0 +
78 static_cast<unsigned int>(shaderOutputVars[0].outputIndex));
Jamie Madillb4463142014-12-19 14:56:54 -050079 }
Jamie Madill4c19a8a2017-07-24 11:46:06 -040080}
Brandon Joneseb994362014-09-24 10:27:28 -070081
Xinghua Caof3179a62018-07-12 16:22:06 +080082void GetDefaultImage2DBindLayoutFromComputeShader(const std::vector<sh::Uniform> &image2DUniforms,
83 gl::ImageUnitTextureTypeMap *image2DBindLayout)
84{
85 image2DBindLayout->clear();
86
87 for (const sh::Uniform &image2D : image2DUniforms)
88 {
89 if (gl::IsImage2DType(image2D.type))
90 {
91 if (image2D.binding == -1)
92 {
93 image2DBindLayout->insert(std::make_pair(0, gl::TextureType::_2D));
94 }
95 else
96 {
97 for (unsigned int index = 0; index < image2D.getArraySizeProduct(); index++)
98 {
99 image2DBindLayout->insert(
100 std::make_pair(image2D.binding + index, gl::TextureType::_2D));
101 }
102 }
103 }
104 }
105}
106
Jamie Madill04796cd2018-05-24 19:52:16 -0400107gl::PrimitiveMode GetGeometryShaderTypeFromDrawMode(gl::PrimitiveMode drawMode)
Jamie Madill4e31ad52015-10-29 10:32:57 -0400108{
109 switch (drawMode)
110 {
111 // Uses the point sprite geometry shader.
Jamie Madill493f9572018-05-24 19:52:15 -0400112 case gl::PrimitiveMode::Points:
Jamie Madill04796cd2018-05-24 19:52:16 -0400113 return gl::PrimitiveMode::Points;
Jamie Madill4e31ad52015-10-29 10:32:57 -0400114
115 // All line drawing uses the same geometry shader.
Jamie Madill493f9572018-05-24 19:52:15 -0400116 case gl::PrimitiveMode::Lines:
117 case gl::PrimitiveMode::LineStrip:
118 case gl::PrimitiveMode::LineLoop:
Jamie Madill04796cd2018-05-24 19:52:16 -0400119 return gl::PrimitiveMode::Lines;
Jamie Madill4e31ad52015-10-29 10:32:57 -0400120
121 // The triangle fan primitive is emulated with strips in D3D11.
Jamie Madill493f9572018-05-24 19:52:15 -0400122 case gl::PrimitiveMode::Triangles:
123 case gl::PrimitiveMode::TriangleFan:
Jamie Madill04796cd2018-05-24 19:52:16 -0400124 return gl::PrimitiveMode::Triangles;
Jamie Madill4e31ad52015-10-29 10:32:57 -0400125
126 // Special case for triangle strips.
Jamie Madill493f9572018-05-24 19:52:15 -0400127 case gl::PrimitiveMode::TriangleStrip:
Jamie Madill04796cd2018-05-24 19:52:16 -0400128 return gl::PrimitiveMode::TriangleStrip;
Jamie Madill4e31ad52015-10-29 10:32:57 -0400129
130 default:
131 UNREACHABLE();
Jamie Madill04796cd2018-05-24 19:52:16 -0400132 return gl::PrimitiveMode::InvalidEnum;
Jamie Madill4e31ad52015-10-29 10:32:57 -0400133 }
134}
135
Jiawei Shao467c15f2018-04-24 15:04:26 +0800136bool HasFlatInterpolationVarying(const std::vector<sh::Varying> &varyings)
Jamie Madill192745a2016-12-22 15:58:21 -0500137{
138 // Note: this assumes nested structs can only be packed with one interpolation.
139 for (const auto &varying : varyings)
140 {
141 if (varying.interpolation == sh::INTERPOLATION_FLAT)
142 {
143 return true;
144 }
145 }
146
147 return false;
148}
149
jchen103fd614d2018-08-13 12:21:58 +0800150bool FindFlatInterpolationVaryingPerShader(gl::Shader *shader)
Jiawei Shao467c15f2018-04-24 15:04:26 +0800151{
jchen103fd614d2018-08-13 12:21:58 +0800152 ASSERT(shader);
Jiawei Shao467c15f2018-04-24 15:04:26 +0800153 switch (shader->getType())
154 {
155 case gl::ShaderType::Vertex:
jchen103fd614d2018-08-13 12:21:58 +0800156 return HasFlatInterpolationVarying(shader->getOutputVaryings());
Jiawei Shao467c15f2018-04-24 15:04:26 +0800157 case gl::ShaderType::Fragment:
jchen103fd614d2018-08-13 12:21:58 +0800158 return HasFlatInterpolationVarying(shader->getInputVaryings());
Jiawei Shao467c15f2018-04-24 15:04:26 +0800159 case gl::ShaderType::Geometry:
jchen103fd614d2018-08-13 12:21:58 +0800160 return HasFlatInterpolationVarying(shader->getInputVaryings()) ||
161 HasFlatInterpolationVarying(shader->getOutputVaryings());
Jiawei Shao467c15f2018-04-24 15:04:26 +0800162 default:
163 UNREACHABLE();
164 return false;
165 }
166}
167
jchen103fd614d2018-08-13 12:21:58 +0800168bool FindFlatInterpolationVarying(const gl::ShaderMap<gl::Shader *> &shaders)
Jiawei Shao467c15f2018-04-24 15:04:26 +0800169{
Jiawei Shao467c15f2018-04-24 15:04:26 +0800170 for (gl::ShaderType shaderType : gl::kAllGraphicsShaderTypes)
171 {
172 gl::Shader *shader = shaders[shaderType];
173 if (!shader)
174 {
175 continue;
176 }
177
jchen103fd614d2018-08-13 12:21:58 +0800178 if (FindFlatInterpolationVaryingPerShader(shader))
Jiawei Shao467c15f2018-04-24 15:04:26 +0800179 {
180 return true;
181 }
182 }
183
184 return false;
185}
186
Qin Jiajia3026f112018-10-09 12:13:38 +0800187class InterfaceBlockInfo final : angle::NonCopyable
Jamie Madill6db1c2e2017-11-08 09:17:40 -0500188{
189 public:
Qin Jiajia3026f112018-10-09 12:13:38 +0800190 InterfaceBlockInfo() {}
Jamie Madill6db1c2e2017-11-08 09:17:40 -0500191
Qin Jiajia3026f112018-10-09 12:13:38 +0800192 void getShaderBlockInfo(const std::vector<sh::InterfaceBlock> &interfaceBlocks);
Jamie Madill6db1c2e2017-11-08 09:17:40 -0500193
194 bool getBlockSize(const std::string &name, const std::string &mappedName, size_t *sizeOut);
195 bool getBlockMemberInfo(const std::string &name,
196 const std::string &mappedName,
197 sh::BlockMemberInfo *infoOut);
198
199 private:
200 size_t getBlockInfo(const sh::InterfaceBlock &interfaceBlock);
201
202 std::map<std::string, size_t> mBlockSizes;
203 sh::BlockLayoutMap mBlockLayout;
204};
205
Qin Jiajia3026f112018-10-09 12:13:38 +0800206void InterfaceBlockInfo::getShaderBlockInfo(const std::vector<sh::InterfaceBlock> &interfaceBlocks)
Jamie Madill6db1c2e2017-11-08 09:17:40 -0500207{
Qin Jiajia3026f112018-10-09 12:13:38 +0800208 for (const sh::InterfaceBlock &interfaceBlock : interfaceBlocks)
Jamie Madill6db1c2e2017-11-08 09:17:40 -0500209 {
Olli Etuaho107c7242018-03-20 15:45:35 +0200210 if (!interfaceBlock.active && interfaceBlock.layout == sh::BLOCKLAYOUT_PACKED)
Jamie Madill6db1c2e2017-11-08 09:17:40 -0500211 continue;
212
213 if (mBlockSizes.count(interfaceBlock.name) > 0)
214 continue;
215
216 size_t dataSize = getBlockInfo(interfaceBlock);
217 mBlockSizes[interfaceBlock.name] = dataSize;
218 }
219}
220
Qin Jiajia3026f112018-10-09 12:13:38 +0800221size_t InterfaceBlockInfo::getBlockInfo(const sh::InterfaceBlock &interfaceBlock)
Jamie Madill6db1c2e2017-11-08 09:17:40 -0500222{
Olli Etuaho107c7242018-03-20 15:45:35 +0200223 ASSERT(interfaceBlock.active || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED);
Jamie Madill6db1c2e2017-11-08 09:17:40 -0500224
225 // define member uniforms
226 sh::Std140BlockEncoder std140Encoder;
Qin Jiajia5df1d282019-01-04 14:22:59 +0800227 sh::Std430BlockEncoder std430Encoder;
Jamie Madill6db1c2e2017-11-08 09:17:40 -0500228 sh::HLSLBlockEncoder hlslEncoder(sh::HLSLBlockEncoder::ENCODE_PACKED, false);
229 sh::BlockLayoutEncoder *encoder = nullptr;
230
231 if (interfaceBlock.layout == sh::BLOCKLAYOUT_STD140)
232 {
233 encoder = &std140Encoder;
234 }
Qin Jiajia5df1d282019-01-04 14:22:59 +0800235 else if (interfaceBlock.layout == sh::BLOCKLAYOUT_STD430)
236 {
237 encoder = &std430Encoder;
238 }
Jamie Madill6db1c2e2017-11-08 09:17:40 -0500239 else
240 {
241 encoder = &hlslEncoder;
242 }
243
Qin Jiajia3026f112018-10-09 12:13:38 +0800244 sh::GetInterfaceBlockInfo(interfaceBlock.fields, interfaceBlock.fieldPrefix(), encoder,
245 &mBlockLayout);
Jamie Madill6db1c2e2017-11-08 09:17:40 -0500246
Jamie Madill4e712be2019-01-03 13:53:59 -0500247 return encoder->getCurrentOffset();
Jamie Madill6db1c2e2017-11-08 09:17:40 -0500248}
249
Qin Jiajia3026f112018-10-09 12:13:38 +0800250bool InterfaceBlockInfo::getBlockSize(const std::string &name,
251 const std::string &mappedName,
252 size_t *sizeOut)
Jamie Madill6db1c2e2017-11-08 09:17:40 -0500253{
254 size_t nameLengthWithoutArrayIndex;
255 gl::ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
256 std::string baseName = name.substr(0u, nameLengthWithoutArrayIndex);
257 auto sizeIter = mBlockSizes.find(baseName);
258 if (sizeIter == mBlockSizes.end())
259 {
260 *sizeOut = 0;
261 return false;
262 }
263
264 *sizeOut = sizeIter->second;
265 return true;
266};
267
Qin Jiajia3026f112018-10-09 12:13:38 +0800268bool InterfaceBlockInfo::getBlockMemberInfo(const std::string &name,
269 const std::string &mappedName,
270 sh::BlockMemberInfo *infoOut)
Jamie Madill6db1c2e2017-11-08 09:17:40 -0500271{
272 auto infoIter = mBlockLayout.find(name);
273 if (infoIter == mBlockLayout.end())
274 {
Jamie Madill04ea03e2019-01-01 15:14:25 -0500275 *infoOut = sh::kDefaultBlockMemberInfo;
Jamie Madill6db1c2e2017-11-08 09:17:40 -0500276 return false;
277 }
278
279 *infoOut = infoIter->second;
280 return true;
281};
Jamie Madill8c78ce42018-12-16 19:14:58 -0500282
283// Helper class that gathers uniform info from the default uniform block.
284class UniformEncodingVisitorD3D : public sh::BlockEncoderVisitor
285{
286 public:
287 UniformEncodingVisitorD3D(gl::ShaderType shaderType,
288 HLSLRegisterType registerType,
289 sh::BlockLayoutEncoder *encoder,
290 D3DUniformMap *uniformMapOut)
291 : sh::BlockEncoderVisitor("", "", encoder),
292 mShaderType(shaderType),
293 mRegisterType(registerType),
294 mUniformMapOut(uniformMapOut)
295 {}
296
297 void visitNamedSampler(const sh::ShaderVariable &sampler,
298 const std::string &name,
299 const std::string &mappedName) override
300 {
301 auto uniformMapEntry = mUniformMapOut->find(name);
302 if (uniformMapEntry == mUniformMapOut->end())
303 {
304 (*mUniformMapOut)[name] =
305 new D3DUniform(sampler.type, mRegisterType, name, sampler.arraySizes, true);
306 }
307 }
308
309 void encodeVariable(const sh::ShaderVariable &variable,
310 const sh::BlockMemberInfo &variableInfo,
311 const std::string &name,
312 const std::string &mappedName) override
313 {
314 auto uniformMapEntry = mUniformMapOut->find(name);
315 D3DUniform *d3dUniform = nullptr;
316
317 if (uniformMapEntry != mUniformMapOut->end())
318 {
319 d3dUniform = uniformMapEntry->second;
320 }
321 else
322 {
323 d3dUniform =
324 new D3DUniform(variable.type, mRegisterType, name, variable.arraySizes, true);
325 (*mUniformMapOut)[name] = d3dUniform;
326 }
327
328 d3dUniform->registerElement = static_cast<unsigned int>(
329 sh::BlockLayoutEncoder::GetBlockRegisterElement(variableInfo));
330 unsigned int reg =
331 static_cast<unsigned int>(sh::BlockLayoutEncoder::GetBlockRegister(variableInfo));
332
333 ASSERT(mShaderType != gl::ShaderType::InvalidEnum);
334 d3dUniform->mShaderRegisterIndexes[mShaderType] = reg;
335 }
336
337 private:
338 gl::ShaderType mShaderType;
339 HLSLRegisterType mRegisterType;
340 D3DUniformMap *mUniformMapOut;
341};
Jamie Madillada9ecc2015-08-17 12:53:37 -0400342} // anonymous namespace
343
Jamie Madill28afae52015-11-09 15:07:57 -0500344// D3DUniform Implementation
345
Jamie Madill33bb7c42017-09-09 23:32:51 -0400346D3DUniform::D3DUniform(GLenum type,
Xinghua Cao26143fd2017-11-01 18:19:05 +0800347 HLSLRegisterType reg,
Jamie Madill62d31cb2015-09-11 13:25:51 -0400348 const std::string &nameIn,
Olli Etuaho465835d2017-09-26 13:34:10 +0300349 const std::vector<unsigned int> &arraySizesIn,
Jamie Madill62d31cb2015-09-11 13:25:51 -0400350 bool defaultBlock)
Jamie Madill33bb7c42017-09-09 23:32:51 -0400351 : typeInfo(gl::GetUniformTypeInfo(type)),
Jamie Madill62d31cb2015-09-11 13:25:51 -0400352 name(nameIn),
Olli Etuaho465835d2017-09-26 13:34:10 +0300353 arraySizes(arraySizesIn),
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800354 mShaderData({}),
Xinghua Cao26143fd2017-11-01 18:19:05 +0800355 regType(reg),
Jamie Madill62d31cb2015-09-11 13:25:51 -0400356 registerCount(0),
357 registerElement(0)
358{
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800359 mShaderRegisterIndexes.fill(GL_INVALID_INDEX);
360
Jamie Madill62d31cb2015-09-11 13:25:51 -0400361 // We use data storage for default block uniforms to cache values that are sent to D3D during
362 // rendering
363 // Uniform blocks/buffers are treated separately by the Renderer (ES3 path only)
364 if (defaultBlock)
365 {
Jamie Madillcc2ed612017-03-14 15:59:00 -0400366 // Use the row count as register count, will work for non-square matrices.
Olli Etuaho465835d2017-09-26 13:34:10 +0300367 registerCount = typeInfo.rowCount * getArraySizeProduct();
Jamie Madill62d31cb2015-09-11 13:25:51 -0400368 }
369}
370
Jamie Madillb980c562018-11-27 11:34:27 -0500371D3DUniform::~D3DUniform() {}
Jamie Madillbe5e2ec2017-08-31 13:28:28 -0400372
Olli Etuaho465835d2017-09-26 13:34:10 +0300373unsigned int D3DUniform::getArraySizeProduct() const
374{
375 return gl::ArraySizeProduct(arraySizes);
376}
377
Jamie Madillbe5e2ec2017-08-31 13:28:28 -0400378const uint8_t *D3DUniform::getDataPtrToElement(size_t elementIndex) const
379{
Olli Etuaho465835d2017-09-26 13:34:10 +0300380 ASSERT((!isArray() && elementIndex == 0) ||
381 (isArray() && elementIndex < getArraySizeProduct()));
Jamie Madillbe5e2ec2017-08-31 13:28:28 -0400382
383 if (isSampler())
384 {
385 return reinterpret_cast<const uint8_t *>(&mSamplerData[elementIndex]);
386 }
387
Jamie Madill33bb7c42017-09-09 23:32:51 -0400388 return firstNonNullData() + (elementIndex > 0 ? (typeInfo.internalSize * elementIndex) : 0u);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400389}
390
391bool D3DUniform::isSampler() const
392{
Jamie Madill33bb7c42017-09-09 23:32:51 -0400393 return typeInfo.isSampler;
Jamie Madill62d31cb2015-09-11 13:25:51 -0400394}
395
Xinghua Cao26143fd2017-11-01 18:19:05 +0800396bool D3DUniform::isImage() const
397{
398 return typeInfo.isImageType;
399}
400
Xinghua Caof3179a62018-07-12 16:22:06 +0800401bool D3DUniform::isImage2D() const
402{
403 return gl::IsImage2DType(typeInfo.type);
404}
405
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800406bool D3DUniform::isReferencedByShader(gl::ShaderType shaderType) const
Jamie Madill62d31cb2015-09-11 13:25:51 -0400407{
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800408 return mShaderRegisterIndexes[shaderType] != GL_INVALID_INDEX;
Xinghua Caob1239382016-12-13 15:07:05 +0800409}
410
Jamie Madillbe5e2ec2017-08-31 13:28:28 -0400411const uint8_t *D3DUniform::firstNonNullData() const
412{
Jamie Madillbe5e2ec2017-08-31 13:28:28 -0400413 if (!mSamplerData.empty())
414 {
415 return reinterpret_cast<const uint8_t *>(mSamplerData.data());
416 }
417
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800418 for (gl::ShaderType shaderType : gl::AllShaderTypes())
419 {
420 if (mShaderData[shaderType])
421 {
422 return mShaderData[shaderType];
423 }
424 }
425
426 UNREACHABLE();
427 return nullptr;
Jamie Madillbe5e2ec2017-08-31 13:28:28 -0400428}
429
Jamie Madillab2bfa82019-01-15 19:06:47 -0500430// D3DInterfaceBlock Implementation
431D3DInterfaceBlock::D3DInterfaceBlock()
432{
433 mShaderRegisterIndexes.fill(GL_INVALID_INDEX);
434}
435
436D3DInterfaceBlock::D3DInterfaceBlock(const D3DInterfaceBlock &other) = default;
437
Jamie Madill28afae52015-11-09 15:07:57 -0500438// D3DVarying Implementation
439
Jamie Madillb980c562018-11-27 11:34:27 -0500440D3DVarying::D3DVarying() : semanticIndex(0), componentCount(0), outputSlot(0) {}
Jamie Madill28afae52015-11-09 15:07:57 -0500441
Jamie Madill9fc36822015-11-18 13:08:07 -0500442D3DVarying::D3DVarying(const std::string &semanticNameIn,
443 unsigned int semanticIndexIn,
444 unsigned int componentCountIn,
445 unsigned int outputSlotIn)
446 : semanticName(semanticNameIn),
447 semanticIndex(semanticIndexIn),
448 componentCount(componentCountIn),
449 outputSlot(outputSlotIn)
Jamie Madillb980c562018-11-27 11:34:27 -0500450{}
Jamie Madill28afae52015-11-09 15:07:57 -0500451
Jamie Madille39a3f02015-11-17 20:42:15 -0500452// ProgramD3DMetadata Implementation
453
Jamie Madillc9bde922016-07-24 17:58:50 -0400454ProgramD3DMetadata::ProgramD3DMetadata(RendererD3D *renderer,
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800455 const gl::ShaderMap<const ShaderD3D *> &attachedShaders)
Jamie Madillc9bde922016-07-24 17:58:50 -0400456 : mRendererMajorShaderModel(renderer->getMajorShaderModel()),
457 mShaderModelSuffix(renderer->getShaderModelSuffix()),
458 mUsesInstancedPointSpriteEmulation(
459 renderer->getWorkarounds().useInstancedPointSpriteEmulation),
460 mUsesViewScale(renderer->presentPathFastEnabled()),
Martin Radevc1d4e552017-08-21 12:01:10 +0300461 mCanSelectViewInVertexShader(renderer->canSelectViewInVertexShader()),
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800462 mAttachedShaders(attachedShaders)
Jamie Madillb980c562018-11-27 11:34:27 -0500463{}
Jamie Madille39a3f02015-11-17 20:42:15 -0500464
Jamie Madillab2bfa82019-01-15 19:06:47 -0500465ProgramD3DMetadata::~ProgramD3DMetadata() = default;
466
Jamie Madille39a3f02015-11-17 20:42:15 -0500467int ProgramD3DMetadata::getRendererMajorShaderModel() const
468{
469 return mRendererMajorShaderModel;
470}
471
Jamie Madillc3dc5d42018-12-30 12:12:04 -0500472bool ProgramD3DMetadata::usesBroadcast(const gl::State &data) const
Jamie Madille39a3f02015-11-17 20:42:15 -0500473{
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800474 return (mAttachedShaders[gl::ShaderType::Fragment]->usesFragColor() &&
475 mAttachedShaders[gl::ShaderType::Fragment]->usesMultipleRenderTargets() &&
Corentin Wallezc084de12017-06-05 14:28:52 -0700476 data.getClientMajorVersion() < 3);
Jamie Madille39a3f02015-11-17 20:42:15 -0500477}
478
Jamie Madill48ef11b2016-04-27 15:21:52 -0400479bool ProgramD3DMetadata::usesFragDepth() const
Jamie Madille39a3f02015-11-17 20:42:15 -0500480{
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800481 return mAttachedShaders[gl::ShaderType::Fragment]->usesFragDepth();
Jamie Madille39a3f02015-11-17 20:42:15 -0500482}
483
484bool ProgramD3DMetadata::usesPointCoord() const
485{
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800486 return mAttachedShaders[gl::ShaderType::Fragment]->usesPointCoord();
Jamie Madille39a3f02015-11-17 20:42:15 -0500487}
488
489bool ProgramD3DMetadata::usesFragCoord() const
490{
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800491 return mAttachedShaders[gl::ShaderType::Fragment]->usesFragCoord();
Jamie Madille39a3f02015-11-17 20:42:15 -0500492}
493
494bool ProgramD3DMetadata::usesPointSize() const
495{
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800496 return mAttachedShaders[gl::ShaderType::Vertex]->usesPointSize();
Jamie Madille39a3f02015-11-17 20:42:15 -0500497}
498
499bool ProgramD3DMetadata::usesInsertedPointCoordValue() const
500{
Jamie Madillc9bde922016-07-24 17:58:50 -0400501 return (!usesPointSize() || !mUsesInstancedPointSpriteEmulation) && usesPointCoord() &&
502 mRendererMajorShaderModel >= 4;
Jamie Madille39a3f02015-11-17 20:42:15 -0500503}
504
Austin Kinross2a63b3f2016-02-08 12:29:08 -0800505bool ProgramD3DMetadata::usesViewScale() const
506{
507 return mUsesViewScale;
508}
509
Martin Radev41ac68e2017-06-06 12:16:58 +0300510bool ProgramD3DMetadata::hasANGLEMultiviewEnabled() const
511{
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800512 return mAttachedShaders[gl::ShaderType::Vertex]->hasANGLEMultiviewEnabled();
Martin Radev41ac68e2017-06-06 12:16:58 +0300513}
514
515bool ProgramD3DMetadata::usesViewID() const
516{
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800517 return mAttachedShaders[gl::ShaderType::Fragment]->usesViewID();
Martin Radev41ac68e2017-06-06 12:16:58 +0300518}
519
Martin Radevc1d4e552017-08-21 12:01:10 +0300520bool ProgramD3DMetadata::canSelectViewInVertexShader() const
521{
522 return mCanSelectViewInVertexShader;
523}
524
Jamie Madille39a3f02015-11-17 20:42:15 -0500525bool ProgramD3DMetadata::addsPointCoordToVertexShader() const
526{
Jamie Madillc9bde922016-07-24 17:58:50 -0400527 // PointSprite emulation requiress that gl_PointCoord is present in the vertex shader
Jamie Madille39a3f02015-11-17 20:42:15 -0500528 // VS_OUTPUT structure to ensure compatibility with the generated PS_INPUT of the pixel shader.
Jamie Madillc9bde922016-07-24 17:58:50 -0400529 // Even with a geometry shader, the app can render triangles or lines and reference
530 // gl_PointCoord in the fragment shader, requiring us to provide a dummy value. For
531 // simplicity, we always add this to the vertex shader when the fragment shader
532 // references gl_PointCoord, even if we could skip it in the geometry shader.
Jamie Madille39a3f02015-11-17 20:42:15 -0500533 return (mUsesInstancedPointSpriteEmulation && usesPointCoord()) ||
534 usesInsertedPointCoordValue();
535}
536
537bool ProgramD3DMetadata::usesTransformFeedbackGLPosition() const
538{
539 // gl_Position only needs to be outputted from the vertex shader if transform feedback is
540 // active. This isn't supported on D3D11 Feature Level 9_3, so we don't output gl_Position from
541 // the vertex shader in this case. This saves us 1 output vector.
542 return !(mRendererMajorShaderModel >= 4 && mShaderModelSuffix != "");
543}
544
545bool ProgramD3DMetadata::usesSystemValuePointSize() const
546{
547 return !mUsesInstancedPointSpriteEmulation && usesPointSize();
548}
549
550bool ProgramD3DMetadata::usesMultipleFragmentOuts() const
551{
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800552 return mAttachedShaders[gl::ShaderType::Fragment]->usesMultipleRenderTargets();
Jamie Madille39a3f02015-11-17 20:42:15 -0500553}
554
555GLint ProgramD3DMetadata::getMajorShaderVersion() const
556{
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800557 return mAttachedShaders[gl::ShaderType::Vertex]->getData().getShaderVersion();
Jamie Madille39a3f02015-11-17 20:42:15 -0500558}
559
560const ShaderD3D *ProgramD3DMetadata::getFragmentShader() const
561{
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800562 return mAttachedShaders[gl::ShaderType::Fragment];
Jamie Madille39a3f02015-11-17 20:42:15 -0500563}
564
Jamie Madill28afae52015-11-09 15:07:57 -0500565// ProgramD3D Implementation
566
Jamie Madilld3dfda22015-07-06 08:28:49 -0400567ProgramD3D::VertexExecutable::VertexExecutable(const gl::InputLayout &inputLayout,
568 const Signature &signature,
Geoff Lang359ef262015-01-05 14:42:29 -0500569 ShaderExecutableD3D *shaderExecutable)
Jamie Madill334d6152015-10-22 14:00:28 -0400570 : mInputs(inputLayout), mSignature(signature), mShaderExecutable(shaderExecutable)
Jamie Madillb980c562018-11-27 11:34:27 -0500571{}
Brandon Joneseb994362014-09-24 10:27:28 -0700572
573ProgramD3D::VertexExecutable::~VertexExecutable()
574{
575 SafeDelete(mShaderExecutable);
576}
577
Jamie Madilld3dfda22015-07-06 08:28:49 -0400578// static
Jamie Madillbdec2f42016-03-02 16:35:32 -0500579ProgramD3D::VertexExecutable::HLSLAttribType ProgramD3D::VertexExecutable::GetAttribType(
580 GLenum type)
581{
582 switch (type)
583 {
584 case GL_INT:
585 return HLSLAttribType::SIGNED_INT;
586 case GL_UNSIGNED_INT:
587 return HLSLAttribType::UNSIGNED_INT;
588 case GL_SIGNED_NORMALIZED:
589 case GL_UNSIGNED_NORMALIZED:
590 case GL_FLOAT:
591 return HLSLAttribType::FLOAT;
592 default:
593 UNREACHABLE();
594 return HLSLAttribType::FLOAT;
595 }
596}
597
598// static
Jamie Madilld3dfda22015-07-06 08:28:49 -0400599void ProgramD3D::VertexExecutable::getSignature(RendererD3D *renderer,
600 const gl::InputLayout &inputLayout,
601 Signature *signatureOut)
Brandon Joneseb994362014-09-24 10:27:28 -0700602{
Jamie Madillbdec2f42016-03-02 16:35:32 -0500603 signatureOut->assign(inputLayout.size(), HLSLAttribType::FLOAT);
Jamie Madilld3dfda22015-07-06 08:28:49 -0400604
605 for (size_t index = 0; index < inputLayout.size(); ++index)
Brandon Joneseb994362014-09-24 10:27:28 -0700606 {
Frank Henigmand633b152018-10-04 23:34:31 -0400607 angle::FormatID vertexFormatID = inputLayout[index];
608 if (vertexFormatID == angle::FormatID::NONE)
Jamie Madillbdec2f42016-03-02 16:35:32 -0500609 continue;
Jamie Madillbd136f92015-08-10 14:51:37 -0400610
Frank Henigmand633b152018-10-04 23:34:31 -0400611 VertexConversionType conversionType = renderer->getVertexConversionType(vertexFormatID);
Jamie Madillbdec2f42016-03-02 16:35:32 -0500612 if ((conversionType & VERTEX_CONVERT_GPU) == 0)
613 continue;
614
Frank Henigmand633b152018-10-04 23:34:31 -0400615 GLenum componentType = renderer->getVertexComponentType(vertexFormatID);
Jamie Madillbdec2f42016-03-02 16:35:32 -0500616 (*signatureOut)[index] = GetAttribType(componentType);
Brandon Joneseb994362014-09-24 10:27:28 -0700617 }
Brandon Joneseb994362014-09-24 10:27:28 -0700618}
619
Jamie Madilld3dfda22015-07-06 08:28:49 -0400620bool ProgramD3D::VertexExecutable::matchesSignature(const Signature &signature) const
621{
Jamie Madillbd136f92015-08-10 14:51:37 -0400622 size_t limit = std::max(mSignature.size(), signature.size());
623 for (size_t index = 0; index < limit; ++index)
624 {
Jamie Madillbdec2f42016-03-02 16:35:32 -0500625 // treat undefined indexes as FLOAT
626 auto a = index < signature.size() ? signature[index] : HLSLAttribType::FLOAT;
627 auto b = index < mSignature.size() ? mSignature[index] : HLSLAttribType::FLOAT;
Jamie Madillbd136f92015-08-10 14:51:37 -0400628 if (a != b)
629 return false;
630 }
631
632 return true;
Jamie Madilld3dfda22015-07-06 08:28:49 -0400633}
634
635ProgramD3D::PixelExecutable::PixelExecutable(const std::vector<GLenum> &outputSignature,
636 ShaderExecutableD3D *shaderExecutable)
Jamie Madill334d6152015-10-22 14:00:28 -0400637 : mOutputSignature(outputSignature), mShaderExecutable(shaderExecutable)
Jamie Madillb980c562018-11-27 11:34:27 -0500638{}
Brandon Joneseb994362014-09-24 10:27:28 -0700639
640ProgramD3D::PixelExecutable::~PixelExecutable()
641{
642 SafeDelete(mShaderExecutable);
643}
644
Xinghua Caof3179a62018-07-12 16:22:06 +0800645ProgramD3D::ComputeExecutable::ComputeExecutable(
646 const gl::ImageUnitTextureTypeMap &signature,
647 std::unique_ptr<ShaderExecutableD3D> shaderExecutable)
648 : mSignature(signature), mShaderExecutable(std::move(shaderExecutable))
649{}
650
651ProgramD3D::ComputeExecutable::~ComputeExecutable() {}
652
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800653ProgramD3D::Sampler::Sampler()
654 : active(false), logicalTextureUnit(0), textureType(gl::TextureType::_2D)
Jamie Madillb980c562018-11-27 11:34:27 -0500655{}
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700656
Jamie Madillb980c562018-11-27 11:34:27 -0500657ProgramD3D::Image::Image() : active(false), logicalImageUnit(0) {}
Xinghua Cao26143fd2017-11-01 18:19:05 +0800658
Geoff Lang7dd2e102014-11-10 15:19:26 -0500659unsigned int ProgramD3D::mCurrentSerial = 1;
660
Jamie Madill48ef11b2016-04-27 15:21:52 -0400661ProgramD3D::ProgramD3D(const gl::ProgramState &state, RendererD3D *renderer)
662 : ProgramImpl(state),
Brandon Jonesc9610c52014-08-25 17:02:59 -0700663 mRenderer(renderer),
Xinghua Caob1239382016-12-13 15:07:05 +0800664 mDynamicHLSL(nullptr),
Brandon Jones44151a92014-09-10 11:32:25 -0700665 mUsesPointSize(false),
Jamie Madill3e14e2b2015-10-29 14:38:53 -0400666 mUsesFlatInterpolation(false),
Jiawei Shao467c15f2018-04-24 15:04:26 +0800667 mUsedShaderSamplerRanges({}),
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700668 mDirtySamplerMapping(true),
Xinghua Cao6dfdca82018-08-03 17:10:55 +0800669 mUsedComputeImageRange(0, 0),
670 mUsedComputeReadonlyImageRange(0, 0),
Jiawei Shao3dd8d2912018-03-30 09:39:09 +0800671 mSerial(issueSerial())
Brandon Jonesc9610c52014-08-25 17:02:59 -0700672{
Brandon Joneseb994362014-09-24 10:27:28 -0700673 mDynamicHLSL = new DynamicHLSL(renderer);
Brandon Jonesc9610c52014-08-25 17:02:59 -0700674}
675
676ProgramD3D::~ProgramD3D()
677{
678 reset();
679 SafeDelete(mDynamicHLSL);
680}
681
Brandon Jones44151a92014-09-10 11:32:25 -0700682bool ProgramD3D::usesPointSpriteEmulation() const
683{
684 return mUsesPointSize && mRenderer->getMajorShaderModel() >= 4;
685}
686
Martin Radev41ac68e2017-06-06 12:16:58 +0300687bool ProgramD3D::usesGeometryShaderForPointSpriteEmulation() const
688{
689 return usesPointSpriteEmulation() && !usesInstancedPointSpriteEmulation();
690}
691
Jeff Gilbert465d6092019-01-02 16:21:18 -0800692bool ProgramD3D::usesGeometryShader(const gl::State &state, const gl::PrimitiveMode drawMode) const
Brandon Jones44151a92014-09-10 11:32:25 -0700693{
Martin Radevc1d4e552017-08-21 12:01:10 +0300694 if (mHasANGLEMultiviewEnabled && !mRenderer->canSelectViewInVertexShader())
Martin Radev41ac68e2017-06-06 12:16:58 +0300695 {
696 return true;
697 }
Jamie Madill493f9572018-05-24 19:52:15 -0400698 if (drawMode != gl::PrimitiveMode::Points)
Jamie Madill3e14e2b2015-10-29 14:38:53 -0400699 {
Jeff Gilbert465d6092019-01-02 16:21:18 -0800700 if (!mUsesFlatInterpolation)
701 {
702 return false;
703 }
704 return state.getProvokingVertex() == gl::ProvokingVertex::LastVertexConvention;
Jamie Madill3e14e2b2015-10-29 14:38:53 -0400705 }
Martin Radev41ac68e2017-06-06 12:16:58 +0300706 return usesGeometryShaderForPointSpriteEmulation();
Cooper Partine6664f02015-01-09 16:22:24 -0800707}
708
709bool ProgramD3D::usesInstancedPointSpriteEmulation() const
710{
711 return mRenderer->getWorkarounds().useInstancedPointSpriteEmulation;
Brandon Jones44151a92014-09-10 11:32:25 -0700712}
713
Xinghua Cao37584b32017-12-01 11:04:03 +0800714GLint ProgramD3D::getSamplerMapping(gl::ShaderType type,
Jamie Madill334d6152015-10-22 14:00:28 -0400715 unsigned int samplerIndex,
716 const gl::Caps &caps) const
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700717{
718 GLint logicalTextureUnit = -1;
719
Jiawei Shao467c15f2018-04-24 15:04:26 +0800720 ASSERT(type != gl::ShaderType::InvalidEnum);
721
Jiawei Shao54aafe52018-04-27 14:54:57 +0800722 ASSERT(samplerIndex < caps.maxShaderTextureImageUnits[type]);
Jiawei Shao467c15f2018-04-24 15:04:26 +0800723
724 const auto &samplers = mShaderSamplers[type];
725 if (samplerIndex < samplers.size() && samplers[samplerIndex].active)
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700726 {
Jiawei Shao467c15f2018-04-24 15:04:26 +0800727 logicalTextureUnit = samplers[samplerIndex].logicalTextureUnit;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700728 }
729
Jamie Madill334d6152015-10-22 14:00:28 -0400730 if (logicalTextureUnit >= 0 &&
731 logicalTextureUnit < static_cast<GLint>(caps.maxCombinedTextureImageUnits))
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700732 {
733 return logicalTextureUnit;
734 }
735
736 return -1;
737}
738
739// Returns the texture type for a given Direct3D 9 sampler type and
740// index (0-15 for the pixel shader and 0-3 for the vertex shader).
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800741gl::TextureType ProgramD3D::getSamplerTextureType(gl::ShaderType type,
742 unsigned int samplerIndex) const
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700743{
Jiawei Shao467c15f2018-04-24 15:04:26 +0800744 ASSERT(type != gl::ShaderType::InvalidEnum);
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700745
Jiawei Shao467c15f2018-04-24 15:04:26 +0800746 const auto &samplers = mShaderSamplers[type];
747 ASSERT(samplerIndex < samplers.size());
748 ASSERT(samplers[samplerIndex].active);
749
750 return samplers[samplerIndex].textureType;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700751}
752
Xinghua Cao6dfdca82018-08-03 17:10:55 +0800753gl::RangeUI ProgramD3D::getUsedSamplerRange(gl::ShaderType type) const
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700754{
Jiawei Shao467c15f2018-04-24 15:04:26 +0800755 ASSERT(type != gl::ShaderType::InvalidEnum);
756 return mUsedShaderSamplerRanges[type];
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700757}
758
Jamie Madillaf4ffe02017-09-09 23:32:48 -0400759ProgramD3D::SamplerMapping ProgramD3D::updateSamplerMapping()
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700760{
761 if (!mDirtySamplerMapping)
762 {
Jamie Madillaf4ffe02017-09-09 23:32:48 -0400763 return SamplerMapping::WasClean;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700764 }
765
766 mDirtySamplerMapping = false;
767
768 // Retrieve sampler uniform values
Jamie Madill62d31cb2015-09-11 13:25:51 -0400769 for (const D3DUniform *d3dUniform : mD3DUniforms)
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700770 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400771 if (!d3dUniform->isSampler())
772 continue;
773
Olli Etuaho465835d2017-09-26 13:34:10 +0300774 int count = d3dUniform->getArraySizeProduct();
Jamie Madill62d31cb2015-09-11 13:25:51 -0400775
Jiawei Shao467c15f2018-04-24 15:04:26 +0800776 for (gl::ShaderType shaderType : gl::AllShaderTypes())
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700777 {
Jiawei Shao467c15f2018-04-24 15:04:26 +0800778 if (!d3dUniform->isReferencedByShader(shaderType))
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700779 {
Jiawei Shao467c15f2018-04-24 15:04:26 +0800780 continue;
Jamie Madill62d31cb2015-09-11 13:25:51 -0400781 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700782
Jiawei Shao467c15f2018-04-24 15:04:26 +0800783 unsigned int firstIndex = d3dUniform->mShaderRegisterIndexes[shaderType];
Jamie Madill62d31cb2015-09-11 13:25:51 -0400784
Jiawei Shao467c15f2018-04-24 15:04:26 +0800785 std::vector<Sampler> &samplers = mShaderSamplers[shaderType];
Jamie Madill62d31cb2015-09-11 13:25:51 -0400786 for (int i = 0; i < count; i++)
787 {
788 unsigned int samplerIndex = firstIndex + i;
789
Jiawei Shao467c15f2018-04-24 15:04:26 +0800790 if (samplerIndex < samplers.size())
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700791 {
Jiawei Shao467c15f2018-04-24 15:04:26 +0800792 ASSERT(samplers[samplerIndex].active);
793 samplers[samplerIndex].logicalTextureUnit = d3dUniform->mSamplerData[i];
Xinghua Caob1239382016-12-13 15:07:05 +0800794 }
795 }
796 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700797 }
Jamie Madillaf4ffe02017-09-09 23:32:48 -0400798
799 return SamplerMapping::WasDirty;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700800}
801
Xinghua Cao26143fd2017-11-01 18:19:05 +0800802GLint ProgramD3D::getImageMapping(gl::ShaderType type,
803 unsigned int imageIndex,
804 bool readonly,
805 const gl::Caps &caps) const
806{
807 GLint logicalImageUnit = -1;
808 ASSERT(imageIndex < caps.maxImageUnits);
809 switch (type)
810 {
Jiawei Shao385b3e02018-03-21 09:43:28 +0800811 case gl::ShaderType::Compute:
Xinghua Cao26143fd2017-11-01 18:19:05 +0800812 if (readonly && imageIndex < mReadonlyImagesCS.size() &&
813 mReadonlyImagesCS[imageIndex].active)
814 {
815 logicalImageUnit = mReadonlyImagesCS[imageIndex].logicalImageUnit;
816 }
817 else if (imageIndex < mImagesCS.size() && mImagesCS[imageIndex].active)
818 {
819 logicalImageUnit = mImagesCS[imageIndex].logicalImageUnit;
820 }
821 break;
822 // TODO(xinghua.cao@intel.com): add image mapping for vertex shader and pixel shader.
823 default:
824 UNREACHABLE();
825 }
826
827 if (logicalImageUnit >= 0 && logicalImageUnit < static_cast<GLint>(caps.maxImageUnits))
828 {
829 return logicalImageUnit;
830 }
831
832 return -1;
833}
834
Xinghua Cao6dfdca82018-08-03 17:10:55 +0800835gl::RangeUI ProgramD3D::getUsedImageRange(gl::ShaderType type, bool readonly) const
Xinghua Cao26143fd2017-11-01 18:19:05 +0800836{
837 switch (type)
838 {
Jiawei Shao385b3e02018-03-21 09:43:28 +0800839 case gl::ShaderType::Compute:
Xinghua Cao26143fd2017-11-01 18:19:05 +0800840 return readonly ? mUsedComputeReadonlyImageRange : mUsedComputeImageRange;
Qin Jiajia155bfd12018-08-31 17:27:10 +0800841 // TODO(xinghua.cao@intel.com): add real image range of vertex shader and pixel shader.
842 case gl::ShaderType::Vertex:
843 case gl::ShaderType::Fragment:
844 return {0, 0};
Xinghua Cao26143fd2017-11-01 18:19:05 +0800845 default:
846 UNREACHABLE();
Xinghua Cao6dfdca82018-08-03 17:10:55 +0800847 return {0, 0};
Xinghua Cao26143fd2017-11-01 18:19:05 +0800848 }
849}
850
Jamie Madill785e8a02018-10-04 17:42:00 -0400851angle::Result ProgramD3D::load(const gl::Context *context,
852 gl::InfoLog &infoLog,
853 gl::BinaryInputStream *stream)
Brandon Jones22502d52014-08-29 16:58:36 -0700854{
Jamie Madilla7d12dc2016-12-13 15:08:19 -0500855 // TODO(jmadill): Use Renderer from contextImpl.
856
Jamie Madill62d31cb2015-09-11 13:25:51 -0400857 reset();
858
Jamie Madill334d6152015-10-22 14:00:28 -0400859 DeviceIdentifier binaryDeviceIdentifier = {0};
860 stream->readBytes(reinterpret_cast<unsigned char *>(&binaryDeviceIdentifier),
861 sizeof(DeviceIdentifier));
Austin Kinross137b1512015-06-17 16:14:53 -0700862
863 DeviceIdentifier identifier = mRenderer->getAdapterIdentifier();
864 if (memcmp(&identifier, &binaryDeviceIdentifier, sizeof(DeviceIdentifier)) != 0)
865 {
866 infoLog << "Invalid program binary, device configuration has changed.";
Jamie Madill7c985f52018-11-29 18:16:17 -0500867 return angle::Result::Incomplete;
Austin Kinross137b1512015-06-17 16:14:53 -0700868 }
869
Jamie Madill2db1fbb2014-12-03 10:58:55 -0500870 int compileFlags = stream->readInt<int>();
871 if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL)
872 {
Jamie Madillf6113162015-05-07 11:49:21 -0400873 infoLog << "Mismatched compilation flags.";
Jamie Madill7c985f52018-11-29 18:16:17 -0500874 return angle::Result::Incomplete;
Jamie Madill2db1fbb2014-12-03 10:58:55 -0500875 }
876
Jamie Madill8047c0d2016-03-07 13:02:12 -0500877 for (int &index : mAttribLocationToD3DSemantic)
Jamie Madill63805b42015-08-25 13:17:39 -0400878 {
Jamie Madill8047c0d2016-03-07 13:02:12 -0500879 stream->readInt(&index);
Jamie Madill63805b42015-08-25 13:17:39 -0400880 }
881
Jiawei Shao467c15f2018-04-24 15:04:26 +0800882 for (gl::ShaderType shaderType : gl::AllShaderTypes())
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700883 {
Jiawei Shao467c15f2018-04-24 15:04:26 +0800884 const unsigned int samplerCount = stream->readInt<unsigned int>();
885 for (unsigned int i = 0; i < samplerCount; ++i)
886 {
887 Sampler sampler;
888 stream->readBool(&sampler.active);
889 stream->readInt(&sampler.logicalTextureUnit);
890 stream->readEnum(&sampler.textureType);
891 mShaderSamplers[shaderType].push_back(sampler);
892 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700893
Xinghua Cao6dfdca82018-08-03 17:10:55 +0800894 unsigned int samplerRangeLow, samplerRangeHigh;
895 stream->readInt(&samplerRangeLow);
896 stream->readInt(&samplerRangeHigh);
897 mUsedShaderSamplerRanges[shaderType] = gl::RangeUI(samplerRangeLow, samplerRangeHigh);
Xinghua Caob1239382016-12-13 15:07:05 +0800898 }
899
Xinghua Cao26143fd2017-11-01 18:19:05 +0800900 const unsigned int csImageCount = stream->readInt<unsigned int>();
901 for (unsigned int i = 0; i < csImageCount; ++i)
902 {
903 Image image;
904 stream->readBool(&image.active);
905 stream->readInt(&image.logicalImageUnit);
906 mImagesCS.push_back(image);
907 }
908
909 const unsigned int csReadonlyImageCount = stream->readInt<unsigned int>();
910 for (unsigned int i = 0; i < csReadonlyImageCount; ++i)
911 {
912 Image image;
913 stream->readBool(&image.active);
914 stream->readInt(&image.logicalImageUnit);
915 mReadonlyImagesCS.push_back(image);
916 }
917
Xinghua Cao6dfdca82018-08-03 17:10:55 +0800918 unsigned int computeImageRangeLow, computeImageRangeHigh, computeReadonlyImageRangeLow,
919 computeReadonlyImageRangeHigh;
920 stream->readInt(&computeImageRangeLow);
921 stream->readInt(&computeImageRangeHigh);
922 stream->readInt(&computeReadonlyImageRangeLow);
923 stream->readInt(&computeReadonlyImageRangeHigh);
924 mUsedComputeImageRange = gl::RangeUI(computeImageRangeLow, computeImageRangeHigh);
925 mUsedComputeReadonlyImageRange =
926 gl::RangeUI(computeReadonlyImageRangeLow, computeReadonlyImageRangeHigh);
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700927
Qin Jiajiaa602f902018-09-11 14:40:24 +0800928 const unsigned int shaderStorageBlockCount = stream->readInt<unsigned int>();
929 if (stream->error())
930 {
931 infoLog << "Invalid program binary.";
Jamie Madill7c985f52018-11-29 18:16:17 -0500932 return angle::Result::Incomplete;
Qin Jiajiaa602f902018-09-11 14:40:24 +0800933 }
934
935 ASSERT(mD3DShaderStorageBlocks.empty());
936 for (unsigned int blockIndex = 0; blockIndex < shaderStorageBlockCount; ++blockIndex)
937 {
938 D3DInterfaceBlock shaderStorageBlock;
939 for (gl::ShaderType shaderType : gl::AllShaderTypes())
940 {
941 stream->readInt(&shaderStorageBlock.mShaderRegisterIndexes[shaderType]);
942 }
943 mD3DShaderStorageBlocks.push_back(shaderStorageBlock);
944 }
945
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700946 const unsigned int uniformCount = stream->readInt<unsigned int>();
947 if (stream->error())
948 {
Jamie Madillf6113162015-05-07 11:49:21 -0400949 infoLog << "Invalid program binary.";
Jamie Madill7c985f52018-11-29 18:16:17 -0500950 return angle::Result::Incomplete;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700951 }
952
Jamie Madill48ef11b2016-04-27 15:21:52 -0400953 const auto &linkedUniforms = mState.getUniforms();
Jamie Madill62d31cb2015-09-11 13:25:51 -0400954 ASSERT(mD3DUniforms.empty());
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700955 for (unsigned int uniformIndex = 0; uniformIndex < uniformCount; uniformIndex++)
956 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400957 const gl::LinkedUniform &linkedUniform = linkedUniforms[uniformIndex];
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700958
Jamie Madill62d31cb2015-09-11 13:25:51 -0400959 D3DUniform *d3dUniform =
Xinghua Cao26143fd2017-11-01 18:19:05 +0800960 new D3DUniform(linkedUniform.type, HLSLRegisterType::None, linkedUniform.name,
961 linkedUniform.arraySizes, linkedUniform.isInDefaultBlock());
962 stream->readInt<HLSLRegisterType>(&d3dUniform->regType);
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800963 for (gl::ShaderType shaderType : gl::AllShaderTypes())
964 {
965 stream->readInt(&d3dUniform->mShaderRegisterIndexes[shaderType]);
966 }
Jamie Madill62d31cb2015-09-11 13:25:51 -0400967 stream->readInt(&d3dUniform->registerCount);
968 stream->readInt(&d3dUniform->registerElement);
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700969
Jamie Madill62d31cb2015-09-11 13:25:51 -0400970 mD3DUniforms.push_back(d3dUniform);
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700971 }
972
Jamie Madill4a3c2342015-10-08 12:58:45 -0400973 const unsigned int blockCount = stream->readInt<unsigned int>();
974 if (stream->error())
975 {
976 infoLog << "Invalid program binary.";
Jamie Madill7c985f52018-11-29 18:16:17 -0500977 return angle::Result::Incomplete;
Jamie Madill4a3c2342015-10-08 12:58:45 -0400978 }
979
980 ASSERT(mD3DUniformBlocks.empty());
981 for (unsigned int blockIndex = 0; blockIndex < blockCount; ++blockIndex)
982 {
Qin Jiajiaa602f902018-09-11 14:40:24 +0800983 D3DInterfaceBlock uniformBlock;
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +0800984 for (gl::ShaderType shaderType : gl::AllShaderTypes())
985 {
986 stream->readInt(&uniformBlock.mShaderRegisterIndexes[shaderType]);
987 }
Jamie Madill4a3c2342015-10-08 12:58:45 -0400988 mD3DUniformBlocks.push_back(uniformBlock);
989 }
990
Jamie Madill9fc36822015-11-18 13:08:07 -0500991 const unsigned int streamOutVaryingCount = stream->readInt<unsigned int>();
992 mStreamOutVaryings.resize(streamOutVaryingCount);
993 for (unsigned int varyingIndex = 0; varyingIndex < streamOutVaryingCount; ++varyingIndex)
Brandon Joneseb994362014-09-24 10:27:28 -0700994 {
Jamie Madill9fc36822015-11-18 13:08:07 -0500995 D3DVarying *varying = &mStreamOutVaryings[varyingIndex];
Brandon Joneseb994362014-09-24 10:27:28 -0700996
Jamie Madill28afae52015-11-09 15:07:57 -0500997 stream->readString(&varying->semanticName);
998 stream->readInt(&varying->semanticIndex);
Jamie Madill9fc36822015-11-18 13:08:07 -0500999 stream->readInt(&varying->componentCount);
1000 stream->readInt(&varying->outputSlot);
Brandon Joneseb994362014-09-24 10:27:28 -07001001 }
1002
Jiawei Shao467c15f2018-04-24 15:04:26 +08001003 for (gl::ShaderType shaderType : gl::AllShaderTypes())
1004 {
1005 stream->readString(&mShaderHLSL[shaderType]);
1006 stream->readBytes(reinterpret_cast<unsigned char *>(&mShaderWorkarounds[shaderType]),
1007 sizeof(angle::CompilerWorkaroundsD3D));
1008 }
1009
Brandon Jones22502d52014-08-29 16:58:36 -07001010 stream->readBool(&mUsesFragDepth);
Martin Radev41ac68e2017-06-06 12:16:58 +03001011 stream->readBool(&mHasANGLEMultiviewEnabled);
1012 stream->readBool(&mUsesViewID);
Brandon Jones44151a92014-09-10 11:32:25 -07001013 stream->readBool(&mUsesPointSize);
Jamie Madill3e14e2b2015-10-29 14:38:53 -04001014 stream->readBool(&mUsesFlatInterpolation);
Brandon Jones22502d52014-08-29 16:58:36 -07001015
1016 const size_t pixelShaderKeySize = stream->readInt<unsigned int>();
1017 mPixelShaderKey.resize(pixelShaderKeySize);
Jamie Madill334d6152015-10-22 14:00:28 -04001018 for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKeySize;
1019 pixelShaderKeyIndex++)
Brandon Jones22502d52014-08-29 16:58:36 -07001020 {
1021 stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].type);
1022 stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].name);
1023 stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].source);
1024 stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].outputIndex);
1025 }
1026
Jamie Madill4e31ad52015-10-29 10:32:57 -04001027 stream->readString(&mGeometryShaderPreamble);
1028
Jamie Madill334d6152015-10-22 14:00:28 -04001029 const unsigned char *binary = reinterpret_cast<const unsigned char *>(stream->data());
Brandon Joneseb994362014-09-24 10:27:28 -07001030
Jamie Madillb0a838b2016-11-13 20:02:12 -05001031 bool separateAttribs = (mState.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS);
1032
Jamie Madill785e8a02018-10-04 17:42:00 -04001033 d3d::Context *contextD3D = GetImplAs<ContextD3D>(context);
1034
Brandon Joneseb994362014-09-24 10:27:28 -07001035 const unsigned int vertexShaderCount = stream->readInt<unsigned int>();
Jamie Madill334d6152015-10-22 14:00:28 -04001036 for (unsigned int vertexShaderIndex = 0; vertexShaderIndex < vertexShaderCount;
1037 vertexShaderIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -07001038 {
Jamie Madilld3dfda22015-07-06 08:28:49 -04001039 size_t inputLayoutSize = stream->readInt<size_t>();
Frank Henigmand633b152018-10-04 23:34:31 -04001040 gl::InputLayout inputLayout(inputLayoutSize, angle::FormatID::NONE);
Brandon Joneseb994362014-09-24 10:27:28 -07001041
Jamie Madilld3dfda22015-07-06 08:28:49 -04001042 for (size_t inputIndex = 0; inputIndex < inputLayoutSize; inputIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -07001043 {
Frank Henigmand633b152018-10-04 23:34:31 -04001044 inputLayout[inputIndex] = stream->readInt<angle::FormatID>();
Brandon Joneseb994362014-09-24 10:27:28 -07001045 }
1046
Jamie Madill334d6152015-10-22 14:00:28 -04001047 unsigned int vertexShaderSize = stream->readInt<unsigned int>();
Brandon Joneseb994362014-09-24 10:27:28 -07001048 const unsigned char *vertexShaderFunction = binary + stream->offset();
Geoff Langb543aff2014-09-30 14:52:54 -04001049
Jamie Madillada9ecc2015-08-17 12:53:37 -04001050 ShaderExecutableD3D *shaderExecutable = nullptr;
1051
Jamie Madill785e8a02018-10-04 17:42:00 -04001052 ANGLE_TRY(mRenderer->loadExecutable(contextD3D, vertexShaderFunction, vertexShaderSize,
Jiawei Shao385b3e02018-03-21 09:43:28 +08001053 gl::ShaderType::Vertex, mStreamOutVaryings,
1054 separateAttribs, &shaderExecutable));
Geoff Langb543aff2014-09-30 14:52:54 -04001055
Brandon Joneseb994362014-09-24 10:27:28 -07001056 if (!shaderExecutable)
1057 {
Jamie Madillf6113162015-05-07 11:49:21 -04001058 infoLog << "Could not create vertex shader.";
Jamie Madill7c985f52018-11-29 18:16:17 -05001059 return angle::Result::Incomplete;
Brandon Joneseb994362014-09-24 10:27:28 -07001060 }
1061
1062 // generated converted input layout
Jamie Madilld3dfda22015-07-06 08:28:49 -04001063 VertexExecutable::Signature signature;
1064 VertexExecutable::getSignature(mRenderer, inputLayout, &signature);
Brandon Joneseb994362014-09-24 10:27:28 -07001065
1066 // add new binary
Xinghua Caob1239382016-12-13 15:07:05 +08001067 mVertexExecutables.push_back(std::unique_ptr<VertexExecutable>(
1068 new VertexExecutable(inputLayout, signature, shaderExecutable)));
Brandon Joneseb994362014-09-24 10:27:28 -07001069
1070 stream->skip(vertexShaderSize);
1071 }
1072
1073 const size_t pixelShaderCount = stream->readInt<unsigned int>();
1074 for (size_t pixelShaderIndex = 0; pixelShaderIndex < pixelShaderCount; pixelShaderIndex++)
1075 {
1076 const size_t outputCount = stream->readInt<unsigned int>();
1077 std::vector<GLenum> outputs(outputCount);
1078 for (size_t outputIndex = 0; outputIndex < outputCount; outputIndex++)
1079 {
1080 stream->readInt(&outputs[outputIndex]);
1081 }
1082
Jamie Madill334d6152015-10-22 14:00:28 -04001083 const size_t pixelShaderSize = stream->readInt<unsigned int>();
Brandon Joneseb994362014-09-24 10:27:28 -07001084 const unsigned char *pixelShaderFunction = binary + stream->offset();
Jamie Madillada9ecc2015-08-17 12:53:37 -04001085 ShaderExecutableD3D *shaderExecutable = nullptr;
1086
Jamie Madill785e8a02018-10-04 17:42:00 -04001087 ANGLE_TRY(mRenderer->loadExecutable(contextD3D, pixelShaderFunction, pixelShaderSize,
Jiawei Shao385b3e02018-03-21 09:43:28 +08001088 gl::ShaderType::Fragment, mStreamOutVaryings,
Yunchao He85072e82017-11-14 15:43:28 +08001089 separateAttribs, &shaderExecutable));
Brandon Joneseb994362014-09-24 10:27:28 -07001090
1091 if (!shaderExecutable)
1092 {
Jamie Madillf6113162015-05-07 11:49:21 -04001093 infoLog << "Could not create pixel shader.";
Jamie Madill7c985f52018-11-29 18:16:17 -05001094 return angle::Result::Incomplete;
Brandon Joneseb994362014-09-24 10:27:28 -07001095 }
1096
1097 // add new binary
Xinghua Caob1239382016-12-13 15:07:05 +08001098 mPixelExecutables.push_back(
1099 std::unique_ptr<PixelExecutable>(new PixelExecutable(outputs, shaderExecutable)));
Brandon Joneseb994362014-09-24 10:27:28 -07001100
1101 stream->skip(pixelShaderSize);
1102 }
1103
Jamie Madill04796cd2018-05-24 19:52:16 -04001104 for (auto &geometryExe : mGeometryExecutables)
Brandon Joneseb994362014-09-24 10:27:28 -07001105 {
Jamie Madill4e31ad52015-10-29 10:32:57 -04001106 unsigned int geometryShaderSize = stream->readInt<unsigned int>();
1107 if (geometryShaderSize == 0)
1108 {
Jamie Madill4e31ad52015-10-29 10:32:57 -04001109 continue;
1110 }
1111
Brandon Joneseb994362014-09-24 10:27:28 -07001112 const unsigned char *geometryShaderFunction = binary + stream->offset();
Jamie Madill4e31ad52015-10-29 10:32:57 -04001113
Xinghua Caob1239382016-12-13 15:07:05 +08001114 ShaderExecutableD3D *geometryExecutable = nullptr;
Jamie Madill785e8a02018-10-04 17:42:00 -04001115 ANGLE_TRY(mRenderer->loadExecutable(contextD3D, geometryShaderFunction, geometryShaderSize,
Jiawei Shao385b3e02018-03-21 09:43:28 +08001116 gl::ShaderType::Geometry, mStreamOutVaryings,
Yunchao He85072e82017-11-14 15:43:28 +08001117 separateAttribs, &geometryExecutable));
Brandon Joneseb994362014-09-24 10:27:28 -07001118
Xinghua Caob1239382016-12-13 15:07:05 +08001119 if (!geometryExecutable)
Brandon Joneseb994362014-09-24 10:27:28 -07001120 {
Jamie Madillf6113162015-05-07 11:49:21 -04001121 infoLog << "Could not create geometry shader.";
Jamie Madill7c985f52018-11-29 18:16:17 -05001122 return angle::Result::Incomplete;
Brandon Joneseb994362014-09-24 10:27:28 -07001123 }
Xinghua Caob1239382016-12-13 15:07:05 +08001124
Jamie Madill04796cd2018-05-24 19:52:16 -04001125 geometryExe.reset(geometryExecutable);
Xinghua Caob1239382016-12-13 15:07:05 +08001126
Brandon Joneseb994362014-09-24 10:27:28 -07001127 stream->skip(geometryShaderSize);
1128 }
1129
Xinghua Caof3179a62018-07-12 16:22:06 +08001130 const size_t computeShaderCount = stream->readInt<unsigned int>();
1131 for (size_t computeShaderIndex = 0; computeShaderIndex < computeShaderCount;
1132 computeShaderIndex++)
Xinghua Caob1239382016-12-13 15:07:05 +08001133 {
Xinghua Caof3179a62018-07-12 16:22:06 +08001134 const size_t signatureCount = stream->readInt<unsigned int>();
1135 gl::ImageUnitTextureTypeMap signatures;
1136 for (size_t signatureIndex = 0; signatureIndex < signatureCount; signatureIndex++)
1137 {
1138 unsigned int imageUint;
1139 gl::TextureType textureType;
1140 stream->readInt<unsigned int>(&imageUint);
1141 stream->readInt<gl::TextureType>(&textureType);
1142 signatures.insert(std::pair<unsigned int, gl::TextureType>(imageUint, textureType));
1143 }
1144
1145 const size_t computeShaderSize = stream->readInt<unsigned int>();
Xinghua Caob1239382016-12-13 15:07:05 +08001146 const unsigned char *computeShaderFunction = binary + stream->offset();
1147
1148 ShaderExecutableD3D *computeExecutable = nullptr;
Jamie Madill785e8a02018-10-04 17:42:00 -04001149 ANGLE_TRY(mRenderer->loadExecutable(contextD3D, computeShaderFunction, computeShaderSize,
Jiawei Shao385b3e02018-03-21 09:43:28 +08001150 gl::ShaderType::Compute, std::vector<D3DVarying>(),
1151 false, &computeExecutable));
Xinghua Caob1239382016-12-13 15:07:05 +08001152
1153 if (!computeExecutable)
1154 {
1155 infoLog << "Could not create compute shader.";
Jamie Madill7c985f52018-11-29 18:16:17 -05001156 return angle::Result::Incomplete;
Xinghua Caob1239382016-12-13 15:07:05 +08001157 }
1158
Xinghua Caof3179a62018-07-12 16:22:06 +08001159 // add new binary
1160 mComputeExecutables.push_back(std::unique_ptr<ComputeExecutable>(new ComputeExecutable(
1161 signatures, std::unique_ptr<ShaderExecutableD3D>(computeExecutable))));
1162
1163 stream->skip(computeShaderSize);
1164 }
1165
1166 const size_t bindLayoutCount = stream->readInt<unsigned int>();
1167 for (size_t bindLayoutIndex = 0; bindLayoutIndex < bindLayoutCount; bindLayoutIndex++)
1168 {
1169 mComputeShaderImage2DBindLayoutCache.insert(std::pair<unsigned int, gl::TextureType>(
1170 stream->readInt<unsigned int>(), gl::TextureType::_2D));
Xinghua Caob1239382016-12-13 15:07:05 +08001171 }
1172
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08001173 initializeUniformStorage(mState.getLinkedShaderStages());
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001174
Jiawei Shao3dd8d2912018-03-30 09:39:09 +08001175 dirtyAllUniforms();
1176
Jamie Madill7c985f52018-11-29 18:16:17 -05001177 return angle::Result::Continue;
Brandon Jones22502d52014-08-29 16:58:36 -07001178}
1179
Jamie Madill27a60632017-06-30 15:12:01 -04001180void ProgramD3D::save(const gl::Context *context, gl::BinaryOutputStream *stream)
Brandon Jones22502d52014-08-29 16:58:36 -07001181{
Austin Kinross137b1512015-06-17 16:14:53 -07001182 // Output the DeviceIdentifier before we output any shader code
Jamie Madill334d6152015-10-22 14:00:28 -04001183 // When we load the binary again later, we can validate the device identifier before trying to
1184 // compile any HLSL
Austin Kinross137b1512015-06-17 16:14:53 -07001185 DeviceIdentifier binaryIdentifier = mRenderer->getAdapterIdentifier();
Jamie Madill334d6152015-10-22 14:00:28 -04001186 stream->writeBytes(reinterpret_cast<unsigned char *>(&binaryIdentifier),
1187 sizeof(DeviceIdentifier));
Austin Kinross137b1512015-06-17 16:14:53 -07001188
Jamie Madill2db1fbb2014-12-03 10:58:55 -05001189 stream->writeInt(ANGLE_COMPILE_OPTIMIZATION_LEVEL);
1190
Jamie Madill8047c0d2016-03-07 13:02:12 -05001191 for (int d3dSemantic : mAttribLocationToD3DSemantic)
Jamie Madill63805b42015-08-25 13:17:39 -04001192 {
Jamie Madill8047c0d2016-03-07 13:02:12 -05001193 stream->writeInt(d3dSemantic);
Jamie Madill63805b42015-08-25 13:17:39 -04001194 }
1195
Jiawei Shao467c15f2018-04-24 15:04:26 +08001196 for (gl::ShaderType shaderType : gl::AllShaderTypes())
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001197 {
Jiawei Shao467c15f2018-04-24 15:04:26 +08001198 stream->writeInt(mShaderSamplers[shaderType].size());
1199 for (unsigned int i = 0; i < mShaderSamplers[shaderType].size(); ++i)
1200 {
1201 stream->writeInt(mShaderSamplers[shaderType][i].active);
1202 stream->writeInt(mShaderSamplers[shaderType][i].logicalTextureUnit);
1203 stream->writeEnum(mShaderSamplers[shaderType][i].textureType);
1204 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001205
Xinghua Cao6dfdca82018-08-03 17:10:55 +08001206 stream->writeInt(mUsedShaderSamplerRanges[shaderType].low());
1207 stream->writeInt(mUsedShaderSamplerRanges[shaderType].high());
Xinghua Caob1239382016-12-13 15:07:05 +08001208 }
1209
Xinghua Cao26143fd2017-11-01 18:19:05 +08001210 stream->writeInt(mImagesCS.size());
1211 for (unsigned int i = 0; i < mImagesCS.size(); ++i)
1212 {
1213 stream->writeInt(mImagesCS[i].active);
1214 stream->writeInt(mImagesCS[i].logicalImageUnit);
1215 }
1216
1217 stream->writeInt(mReadonlyImagesCS.size());
1218 for (unsigned int i = 0; i < mReadonlyImagesCS.size(); ++i)
1219 {
1220 stream->writeInt(mReadonlyImagesCS[i].active);
1221 stream->writeInt(mReadonlyImagesCS[i].logicalImageUnit);
1222 }
1223
Xinghua Cao6dfdca82018-08-03 17:10:55 +08001224 stream->writeInt(mUsedComputeImageRange.low());
1225 stream->writeInt(mUsedComputeImageRange.high());
1226 stream->writeInt(mUsedComputeReadonlyImageRange.low());
1227 stream->writeInt(mUsedComputeReadonlyImageRange.high());
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001228
Qin Jiajiaa602f902018-09-11 14:40:24 +08001229 stream->writeInt(mD3DShaderStorageBlocks.size());
1230 for (const D3DInterfaceBlock &shaderStorageBlock : mD3DShaderStorageBlocks)
1231 {
1232 for (gl::ShaderType shaderType : gl::AllShaderTypes())
1233 {
1234 stream->writeIntOrNegOne(shaderStorageBlock.mShaderRegisterIndexes[shaderType]);
1235 }
1236 }
1237
Jamie Madill62d31cb2015-09-11 13:25:51 -04001238 stream->writeInt(mD3DUniforms.size());
Jamie Madill4a3c2342015-10-08 12:58:45 -04001239 for (const D3DUniform *uniform : mD3DUniforms)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001240 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001241 // Type, name and arraySize are redundant, so aren't stored in the binary.
Xinghua Cao26143fd2017-11-01 18:19:05 +08001242 stream->writeInt(static_cast<unsigned int>(uniform->regType));
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08001243 for (gl::ShaderType shaderType : gl::AllShaderTypes())
1244 {
1245 stream->writeIntOrNegOne(uniform->mShaderRegisterIndexes[shaderType]);
1246 }
Jamie Madill4a3c2342015-10-08 12:58:45 -04001247 stream->writeInt(uniform->registerCount);
1248 stream->writeInt(uniform->registerElement);
1249 }
1250
1251 stream->writeInt(mD3DUniformBlocks.size());
Qin Jiajiaa602f902018-09-11 14:40:24 +08001252 for (const D3DInterfaceBlock &uniformBlock : mD3DUniformBlocks)
Jamie Madill4a3c2342015-10-08 12:58:45 -04001253 {
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08001254 for (gl::ShaderType shaderType : gl::AllShaderTypes())
1255 {
1256 stream->writeIntOrNegOne(uniformBlock.mShaderRegisterIndexes[shaderType]);
1257 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001258 }
1259
Jamie Madill9fc36822015-11-18 13:08:07 -05001260 stream->writeInt(mStreamOutVaryings.size());
1261 for (const auto &varying : mStreamOutVaryings)
Brandon Joneseb994362014-09-24 10:27:28 -07001262 {
Brandon Joneseb994362014-09-24 10:27:28 -07001263 stream->writeString(varying.semanticName);
1264 stream->writeInt(varying.semanticIndex);
Jamie Madill9fc36822015-11-18 13:08:07 -05001265 stream->writeInt(varying.componentCount);
1266 stream->writeInt(varying.outputSlot);
Brandon Joneseb994362014-09-24 10:27:28 -07001267 }
1268
Jiawei Shao467c15f2018-04-24 15:04:26 +08001269 for (gl::ShaderType shaderType : gl::AllShaderTypes())
1270 {
1271 stream->writeString(mShaderHLSL[shaderType]);
1272 stream->writeBytes(reinterpret_cast<unsigned char *>(&mShaderWorkarounds[shaderType]),
1273 sizeof(angle::CompilerWorkaroundsD3D));
1274 }
1275
Brandon Jones22502d52014-08-29 16:58:36 -07001276 stream->writeInt(mUsesFragDepth);
Martin Radev41ac68e2017-06-06 12:16:58 +03001277 stream->writeInt(mHasANGLEMultiviewEnabled);
1278 stream->writeInt(mUsesViewID);
Brandon Jones44151a92014-09-10 11:32:25 -07001279 stream->writeInt(mUsesPointSize);
Jamie Madill3e14e2b2015-10-29 14:38:53 -04001280 stream->writeInt(mUsesFlatInterpolation);
Brandon Jones22502d52014-08-29 16:58:36 -07001281
Brandon Joneseb994362014-09-24 10:27:28 -07001282 const std::vector<PixelShaderOutputVariable> &pixelShaderKey = mPixelShaderKey;
Brandon Jones22502d52014-08-29 16:58:36 -07001283 stream->writeInt(pixelShaderKey.size());
Jamie Madill334d6152015-10-22 14:00:28 -04001284 for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKey.size();
1285 pixelShaderKeyIndex++)
Brandon Jones22502d52014-08-29 16:58:36 -07001286 {
Brandon Joneseb994362014-09-24 10:27:28 -07001287 const PixelShaderOutputVariable &variable = pixelShaderKey[pixelShaderKeyIndex];
Brandon Jones22502d52014-08-29 16:58:36 -07001288 stream->writeInt(variable.type);
1289 stream->writeString(variable.name);
1290 stream->writeString(variable.source);
1291 stream->writeInt(variable.outputIndex);
1292 }
1293
Jamie Madill4e31ad52015-10-29 10:32:57 -04001294 stream->writeString(mGeometryShaderPreamble);
1295
Brandon Joneseb994362014-09-24 10:27:28 -07001296 stream->writeInt(mVertexExecutables.size());
Jamie Madill334d6152015-10-22 14:00:28 -04001297 for (size_t vertexExecutableIndex = 0; vertexExecutableIndex < mVertexExecutables.size();
1298 vertexExecutableIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -07001299 {
Xinghua Caob1239382016-12-13 15:07:05 +08001300 VertexExecutable *vertexExecutable = mVertexExecutables[vertexExecutableIndex].get();
Brandon Joneseb994362014-09-24 10:27:28 -07001301
Jamie Madilld3dfda22015-07-06 08:28:49 -04001302 const auto &inputLayout = vertexExecutable->inputs();
1303 stream->writeInt(inputLayout.size());
1304
1305 for (size_t inputIndex = 0; inputIndex < inputLayout.size(); inputIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -07001306 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001307 stream->writeInt(static_cast<unsigned int>(inputLayout[inputIndex]));
Brandon Joneseb994362014-09-24 10:27:28 -07001308 }
1309
1310 size_t vertexShaderSize = vertexExecutable->shaderExecutable()->getLength();
1311 stream->writeInt(vertexShaderSize);
1312
1313 const uint8_t *vertexBlob = vertexExecutable->shaderExecutable()->getFunction();
1314 stream->writeBytes(vertexBlob, vertexShaderSize);
1315 }
1316
1317 stream->writeInt(mPixelExecutables.size());
Jamie Madill334d6152015-10-22 14:00:28 -04001318 for (size_t pixelExecutableIndex = 0; pixelExecutableIndex < mPixelExecutables.size();
1319 pixelExecutableIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -07001320 {
Xinghua Caob1239382016-12-13 15:07:05 +08001321 PixelExecutable *pixelExecutable = mPixelExecutables[pixelExecutableIndex].get();
Brandon Joneseb994362014-09-24 10:27:28 -07001322
1323 const std::vector<GLenum> outputs = pixelExecutable->outputSignature();
1324 stream->writeInt(outputs.size());
1325 for (size_t outputIndex = 0; outputIndex < outputs.size(); outputIndex++)
1326 {
1327 stream->writeInt(outputs[outputIndex]);
1328 }
1329
1330 size_t pixelShaderSize = pixelExecutable->shaderExecutable()->getLength();
1331 stream->writeInt(pixelShaderSize);
1332
1333 const uint8_t *pixelBlob = pixelExecutable->shaderExecutable()->getFunction();
1334 stream->writeBytes(pixelBlob, pixelShaderSize);
1335 }
1336
Xinghua Caob1239382016-12-13 15:07:05 +08001337 for (auto const &geometryExecutable : mGeometryExecutables)
Brandon Joneseb994362014-09-24 10:27:28 -07001338 {
Xinghua Caob1239382016-12-13 15:07:05 +08001339 if (!geometryExecutable)
Jamie Madill4e31ad52015-10-29 10:32:57 -04001340 {
1341 stream->writeInt(0);
1342 continue;
1343 }
1344
Xinghua Caob1239382016-12-13 15:07:05 +08001345 size_t geometryShaderSize = geometryExecutable->getLength();
Jamie Madill4e31ad52015-10-29 10:32:57 -04001346 stream->writeInt(geometryShaderSize);
Xinghua Caob1239382016-12-13 15:07:05 +08001347 stream->writeBytes(geometryExecutable->getFunction(), geometryShaderSize);
1348 }
1349
Xinghua Caof3179a62018-07-12 16:22:06 +08001350 stream->writeInt(mComputeExecutables.size());
1351 for (size_t computeExecutableIndex = 0; computeExecutableIndex < mComputeExecutables.size();
1352 computeExecutableIndex++)
Xinghua Caob1239382016-12-13 15:07:05 +08001353 {
Xinghua Caof3179a62018-07-12 16:22:06 +08001354 ComputeExecutable *computeExecutable = mComputeExecutables[computeExecutableIndex].get();
1355
1356 const gl::ImageUnitTextureTypeMap signatures = computeExecutable->signature();
1357 stream->writeInt(signatures.size());
1358 for (const auto &signature : signatures)
1359 {
1360 stream->writeInt(signature.first);
1361 stream->writeInt(static_cast<unsigned int>(signature.second));
1362 }
1363
1364 size_t computeShaderSize = computeExecutable->shaderExecutable()->getLength();
Xinghua Caob1239382016-12-13 15:07:05 +08001365 stream->writeInt(computeShaderSize);
Xinghua Caof3179a62018-07-12 16:22:06 +08001366
1367 const uint8_t *computeBlob = computeExecutable->shaderExecutable()->getFunction();
1368 stream->writeBytes(computeBlob, computeShaderSize);
Xinghua Caob1239382016-12-13 15:07:05 +08001369 }
Xinghua Caof3179a62018-07-12 16:22:06 +08001370
1371 stream->writeInt(mComputeShaderImage2DBindLayoutCache.size());
1372 for (auto &image2DBindLayout : mComputeShaderImage2DBindLayoutCache)
Xinghua Caob1239382016-12-13 15:07:05 +08001373 {
Xinghua Caof3179a62018-07-12 16:22:06 +08001374 stream->writeInt(image2DBindLayout.first);
Brandon Joneseb994362014-09-24 10:27:28 -07001375 }
Brandon Jones22502d52014-08-29 16:58:36 -07001376}
1377
Jamie Madillb980c562018-11-27 11:34:27 -05001378void ProgramD3D::setBinaryRetrievableHint(bool /* retrievable */) {}
Geoff Langc5629752015-12-07 16:29:04 -05001379
Jamie Madillb980c562018-11-27 11:34:27 -05001380void ProgramD3D::setSeparable(bool /* separable */) {}
Yunchao He61afff12017-03-14 15:34:03 +08001381
Jamie Madillec1fe5b2018-08-10 10:05:52 -04001382angle::Result ProgramD3D::getPixelExecutableForCachedOutputLayout(
Jamie Madill785e8a02018-10-04 17:42:00 -04001383 d3d::Context *context,
Jamie Madillec1fe5b2018-08-10 10:05:52 -04001384 ShaderExecutableD3D **outExecutable,
1385 gl::InfoLog *infoLog)
Brandon Joneseb994362014-09-24 10:27:28 -07001386{
Jamie Madill0e7f1732017-09-09 23:32:50 -04001387 if (mCachedPixelExecutableIndex.valid())
Brandon Joneseb994362014-09-24 10:27:28 -07001388 {
Jamie Madill0e7f1732017-09-09 23:32:50 -04001389 *outExecutable = mPixelExecutables[mCachedPixelExecutableIndex.value()]->shaderExecutable();
Jamie Madill7c985f52018-11-29 18:16:17 -05001390 return angle::Result::Continue;
Brandon Joneseb994362014-09-24 10:27:28 -07001391 }
1392
Jamie Madill334d6152015-10-22 14:00:28 -04001393 std::string finalPixelHLSL = mDynamicHLSL->generatePixelShaderForOutputSignature(
Jiawei Shao467c15f2018-04-24 15:04:26 +08001394 mShaderHLSL[gl::ShaderType::Fragment], mPixelShaderKey, mUsesFragDepth,
1395 mPixelShaderOutputLayoutCache);
Brandon Jones22502d52014-08-29 16:58:36 -07001396
1397 // Generate new pixel executable
Yunchao Hed7297bf2017-04-19 15:27:10 +08001398 ShaderExecutableD3D *pixelExecutable = nullptr;
Jamie Madill97399232014-12-23 12:31:15 -05001399
1400 gl::InfoLog tempInfoLog;
1401 gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
1402
Jamie Madill01074252016-11-28 15:55:51 -05001403 ANGLE_TRY(mRenderer->compileToExecutable(
Jamie Madillb1565902018-07-27 08:12:48 -04001404 context, *currentInfoLog, finalPixelHLSL, gl::ShaderType::Fragment, mStreamOutVaryings,
Jiawei Shao467c15f2018-04-24 15:04:26 +08001405 (mState.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS),
1406 mShaderWorkarounds[gl::ShaderType::Fragment], &pixelExecutable));
Brandon Joneseb994362014-09-24 10:27:28 -07001407
Jamie Madill97399232014-12-23 12:31:15 -05001408 if (pixelExecutable)
1409 {
Xinghua Caob1239382016-12-13 15:07:05 +08001410 mPixelExecutables.push_back(std::unique_ptr<PixelExecutable>(
Jamie Madill4c19a8a2017-07-24 11:46:06 -04001411 new PixelExecutable(mPixelShaderOutputLayoutCache, pixelExecutable)));
Jamie Madill0e7f1732017-09-09 23:32:50 -04001412 mCachedPixelExecutableIndex = mPixelExecutables.size() - 1;
Jamie Madill97399232014-12-23 12:31:15 -05001413 }
1414 else if (!infoLog)
Brandon Joneseb994362014-09-24 10:27:28 -07001415 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05001416 ERR() << "Error compiling dynamic pixel executable:" << std::endl
1417 << tempInfoLog.str() << std::endl;
Brandon Joneseb994362014-09-24 10:27:28 -07001418 }
Brandon Jones22502d52014-08-29 16:58:36 -07001419
Jamie Madill4c19a8a2017-07-24 11:46:06 -04001420 *outExecutable = pixelExecutable;
Jamie Madill7c985f52018-11-29 18:16:17 -05001421 return angle::Result::Continue;
Brandon Jones22502d52014-08-29 16:58:36 -07001422}
1423
Jamie Madillec1fe5b2018-08-10 10:05:52 -04001424angle::Result ProgramD3D::getVertexExecutableForCachedInputLayout(
Jamie Madill785e8a02018-10-04 17:42:00 -04001425 d3d::Context *context,
Jamie Madillec1fe5b2018-08-10 10:05:52 -04001426 ShaderExecutableD3D **outExectuable,
1427 gl::InfoLog *infoLog)
Brandon Jones22502d52014-08-29 16:58:36 -07001428{
Jamie Madill0e7f1732017-09-09 23:32:50 -04001429 if (mCachedVertexExecutableIndex.valid())
Brandon Joneseb994362014-09-24 10:27:28 -07001430 {
Jamie Madill0e7f1732017-09-09 23:32:50 -04001431 *outExectuable =
1432 mVertexExecutables[mCachedVertexExecutableIndex.value()]->shaderExecutable();
Jamie Madill7c985f52018-11-29 18:16:17 -05001433 return angle::Result::Continue;
Brandon Joneseb994362014-09-24 10:27:28 -07001434 }
1435
Brandon Jones22502d52014-08-29 16:58:36 -07001436 // Generate new dynamic layout with attribute conversions
Jamie Madillc349ec02015-08-21 16:53:12 -04001437 std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout(
Jiawei Shao467c15f2018-04-24 15:04:26 +08001438 mShaderHLSL[gl::ShaderType::Vertex], mCachedInputLayout, mState.getAttributes());
Brandon Jones22502d52014-08-29 16:58:36 -07001439
1440 // Generate new vertex executable
Yunchao Hed7297bf2017-04-19 15:27:10 +08001441 ShaderExecutableD3D *vertexExecutable = nullptr;
Jamie Madill97399232014-12-23 12:31:15 -05001442
1443 gl::InfoLog tempInfoLog;
1444 gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
1445
Jamie Madill01074252016-11-28 15:55:51 -05001446 ANGLE_TRY(mRenderer->compileToExecutable(
Jamie Madillb1565902018-07-27 08:12:48 -04001447 context, *currentInfoLog, finalVertexHLSL, gl::ShaderType::Vertex, mStreamOutVaryings,
Jiawei Shao467c15f2018-04-24 15:04:26 +08001448 (mState.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS),
1449 mShaderWorkarounds[gl::ShaderType::Vertex], &vertexExecutable));
Geoff Langb543aff2014-09-30 14:52:54 -04001450
Jamie Madill97399232014-12-23 12:31:15 -05001451 if (vertexExecutable)
Brandon Joneseb994362014-09-24 10:27:28 -07001452 {
Xinghua Caob1239382016-12-13 15:07:05 +08001453 mVertexExecutables.push_back(std::unique_ptr<VertexExecutable>(
Jamie Madill4c19a8a2017-07-24 11:46:06 -04001454 new VertexExecutable(mCachedInputLayout, mCachedVertexSignature, vertexExecutable)));
Jamie Madill0e7f1732017-09-09 23:32:50 -04001455 mCachedVertexExecutableIndex = mVertexExecutables.size() - 1;
Brandon Joneseb994362014-09-24 10:27:28 -07001456 }
Jamie Madill97399232014-12-23 12:31:15 -05001457 else if (!infoLog)
1458 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05001459 ERR() << "Error compiling dynamic vertex executable:" << std::endl
1460 << tempInfoLog.str() << std::endl;
Jamie Madill97399232014-12-23 12:31:15 -05001461 }
Brandon Jones22502d52014-08-29 16:58:36 -07001462
Geoff Langb543aff2014-09-30 14:52:54 -04001463 *outExectuable = vertexExecutable;
Jamie Madill7c985f52018-11-29 18:16:17 -05001464 return angle::Result::Continue;
Brandon Jones22502d52014-08-29 16:58:36 -07001465}
1466
Jamie Madill785e8a02018-10-04 17:42:00 -04001467angle::Result ProgramD3D::getGeometryExecutableForPrimitiveType(d3d::Context *context,
Jeff Gilbert465d6092019-01-02 16:21:18 -08001468 const gl::State &state,
Jamie Madillec1fe5b2018-08-10 10:05:52 -04001469 gl::PrimitiveMode drawMode,
1470 ShaderExecutableD3D **outExecutable,
1471 gl::InfoLog *infoLog)
Jamie Madill4e31ad52015-10-29 10:32:57 -04001472{
Jamie Madill3e14e2b2015-10-29 14:38:53 -04001473 if (outExecutable)
1474 {
1475 *outExecutable = nullptr;
1476 }
1477
Austin Kinross88829e82016-01-12 13:04:41 -08001478 // Return a null shader if the current rendering doesn't use a geometry shader
Jeff Gilbert465d6092019-01-02 16:21:18 -08001479 if (!usesGeometryShader(state, drawMode))
Jamie Madill3e14e2b2015-10-29 14:38:53 -04001480 {
Jamie Madill7c985f52018-11-29 18:16:17 -05001481 return angle::Result::Continue;
Jamie Madill3e14e2b2015-10-29 14:38:53 -04001482 }
1483
Jamie Madill04796cd2018-05-24 19:52:16 -04001484 gl::PrimitiveMode geometryShaderType = GetGeometryShaderTypeFromDrawMode(drawMode);
Jamie Madill4e31ad52015-10-29 10:32:57 -04001485
Xinghua Caob1239382016-12-13 15:07:05 +08001486 if (mGeometryExecutables[geometryShaderType])
Jamie Madill4e31ad52015-10-29 10:32:57 -04001487 {
1488 if (outExecutable)
1489 {
Xinghua Caob1239382016-12-13 15:07:05 +08001490 *outExecutable = mGeometryExecutables[geometryShaderType].get();
Jamie Madill4e31ad52015-10-29 10:32:57 -04001491 }
Jamie Madill7c985f52018-11-29 18:16:17 -05001492 return angle::Result::Continue;
Jamie Madill4e31ad52015-10-29 10:32:57 -04001493 }
Jeff Gilbert465d6092019-01-02 16:21:18 -08001494 const gl::Caps &caps = state.getCaps();
Jamie Madill4e31ad52015-10-29 10:32:57 -04001495 std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL(
Jamie Madill785e8a02018-10-04 17:42:00 -04001496 caps, geometryShaderType, mState, mRenderer->presentPathFastEnabled(),
Martin Radevc1d4e552017-08-21 12:01:10 +03001497 mHasANGLEMultiviewEnabled, mRenderer->canSelectViewInVertexShader(),
1498 usesGeometryShaderForPointSpriteEmulation(), mGeometryShaderPreamble);
Jamie Madill4e31ad52015-10-29 10:32:57 -04001499
1500 gl::InfoLog tempInfoLog;
1501 gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
1502
Xinghua Caob1239382016-12-13 15:07:05 +08001503 ShaderExecutableD3D *geometryExecutable = nullptr;
Jamie Madillec1fe5b2018-08-10 10:05:52 -04001504 angle::Result result = mRenderer->compileToExecutable(
Jamie Madillb1565902018-07-27 08:12:48 -04001505 context, *currentInfoLog, geometryHLSL, gl::ShaderType::Geometry, mStreamOutVaryings,
Jamie Madill408293f2016-12-20 10:11:45 -05001506 (mState.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS),
Xinghua Caob1239382016-12-13 15:07:05 +08001507 angle::CompilerWorkaroundsD3D(), &geometryExecutable);
Jamie Madill4e31ad52015-10-29 10:32:57 -04001508
Jamie Madill7c985f52018-11-29 18:16:17 -05001509 if (!infoLog && result == angle::Result::Stop)
Jamie Madill4e31ad52015-10-29 10:32:57 -04001510 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05001511 ERR() << "Error compiling dynamic geometry executable:" << std::endl
1512 << tempInfoLog.str() << std::endl;
Jamie Madill4e31ad52015-10-29 10:32:57 -04001513 }
1514
Xinghua Caob1239382016-12-13 15:07:05 +08001515 if (geometryExecutable != nullptr)
1516 {
1517 mGeometryExecutables[geometryShaderType].reset(geometryExecutable);
1518 }
1519
Jamie Madill4e31ad52015-10-29 10:32:57 -04001520 if (outExecutable)
1521 {
Xinghua Caob1239382016-12-13 15:07:05 +08001522 *outExecutable = mGeometryExecutables[geometryShaderType].get();
Jamie Madill4e31ad52015-10-29 10:32:57 -04001523 }
Jamie Madillec1fe5b2018-08-10 10:05:52 -04001524 return result;
Jamie Madill4e31ad52015-10-29 10:32:57 -04001525}
1526
Jamie Madill785e8a02018-10-04 17:42:00 -04001527class ProgramD3D::GetExecutableTask : public Closure, public d3d::Context
Brandon Jones44151a92014-09-10 11:32:25 -07001528{
Jamie Madill01074252016-11-28 15:55:51 -05001529 public:
Jamie Madill785e8a02018-10-04 17:42:00 -04001530 GetExecutableTask(ProgramD3D *program) : mProgram(program) {}
Brandon Joneseb994362014-09-24 10:27:28 -07001531
Jamie Madillec1fe5b2018-08-10 10:05:52 -04001532 virtual angle::Result run() = 0;
Jamie Madill01074252016-11-28 15:55:51 -05001533
Jamie Madillec1fe5b2018-08-10 10:05:52 -04001534 void operator()() override { mResult = run(); }
Jamie Madill01074252016-11-28 15:55:51 -05001535
Jamie Madillec1fe5b2018-08-10 10:05:52 -04001536 angle::Result getResult() const { return mResult; }
Jamie Madill01074252016-11-28 15:55:51 -05001537 const gl::InfoLog &getInfoLog() const { return mInfoLog; }
Jamie Madillec1fe5b2018-08-10 10:05:52 -04001538 ShaderExecutableD3D *getExecutable() { return mExecutable; }
Jamie Madill01074252016-11-28 15:55:51 -05001539
Jamie Madillc1fd7372018-10-26 22:48:39 -04001540 void handleResult(HRESULT hr,
1541 const char *message,
1542 const char *file,
1543 const char *function,
1544 unsigned int line) override
Jamie Madill785e8a02018-10-04 17:42:00 -04001545 {
1546 mStoredHR = hr;
1547 mStoredMessage = message;
1548 mStoredFile = file;
1549 mStoredFunction = function;
1550 mStoredLine = line;
1551 }
1552
1553 void popError(d3d::Context *context)
1554 {
Jamie Madillc1fd7372018-10-26 22:48:39 -04001555 context->handleResult(mStoredHR, mStoredMessage, mStoredFile, mStoredFunction, mStoredLine);
Jamie Madill785e8a02018-10-04 17:42:00 -04001556 }
1557
Jamie Madill01074252016-11-28 15:55:51 -05001558 protected:
Jamie Madill785e8a02018-10-04 17:42:00 -04001559 ProgramD3D *mProgram = nullptr;
Jamie Madill7c985f52018-11-29 18:16:17 -05001560 angle::Result mResult = angle::Result::Continue;
Jamie Madill01074252016-11-28 15:55:51 -05001561 gl::InfoLog mInfoLog;
Jamie Madill785e8a02018-10-04 17:42:00 -04001562 ShaderExecutableD3D *mExecutable = nullptr;
1563 HRESULT mStoredHR = S_OK;
1564 const char *mStoredMessage = nullptr;
1565 const char *mStoredFile = nullptr;
1566 const char *mStoredFunction = nullptr;
1567 unsigned int mStoredLine = 0;
Jamie Madill01074252016-11-28 15:55:51 -05001568};
1569
1570class ProgramD3D::GetVertexExecutableTask : public ProgramD3D::GetExecutableTask
1571{
1572 public:
Jamie Madill785e8a02018-10-04 17:42:00 -04001573 GetVertexExecutableTask(ProgramD3D *program) : GetExecutableTask(program) {}
Jamie Madillec1fe5b2018-08-10 10:05:52 -04001574 angle::Result run() override
Jamie Madill01074252016-11-28 15:55:51 -05001575 {
jchen103fd614d2018-08-13 12:21:58 +08001576 mProgram->updateCachedInputLayoutFromShader();
Jamie Madill01074252016-11-28 15:55:51 -05001577
Jamie Madill785e8a02018-10-04 17:42:00 -04001578 ANGLE_TRY(mProgram->getVertexExecutableForCachedInputLayout(this, &mExecutable, &mInfoLog));
Jamie Madill01074252016-11-28 15:55:51 -05001579
Jamie Madill7c985f52018-11-29 18:16:17 -05001580 return angle::Result::Continue;
Jamie Madill01074252016-11-28 15:55:51 -05001581 }
1582};
1583
jchen103fd614d2018-08-13 12:21:58 +08001584void ProgramD3D::updateCachedInputLayoutFromShader()
Jamie Madill4c19a8a2017-07-24 11:46:06 -04001585{
jchen103fd614d2018-08-13 12:21:58 +08001586 GetDefaultInputLayoutFromShader(mState.getAttachedShader(gl::ShaderType::Vertex),
Jiawei Shao385b3e02018-03-21 09:43:28 +08001587 &mCachedInputLayout);
Jamie Madill4c19a8a2017-07-24 11:46:06 -04001588 VertexExecutable::getSignature(mRenderer, mCachedInputLayout, &mCachedVertexSignature);
Jamie Madill0e7f1732017-09-09 23:32:50 -04001589 updateCachedVertexExecutableIndex();
Jamie Madill4c19a8a2017-07-24 11:46:06 -04001590}
1591
Jamie Madill01074252016-11-28 15:55:51 -05001592class ProgramD3D::GetPixelExecutableTask : public ProgramD3D::GetExecutableTask
1593{
1594 public:
Jamie Madill785e8a02018-10-04 17:42:00 -04001595 GetPixelExecutableTask(ProgramD3D *program) : GetExecutableTask(program) {}
Jamie Madillec1fe5b2018-08-10 10:05:52 -04001596 angle::Result run() override
Jamie Madill01074252016-11-28 15:55:51 -05001597 {
Jamie Madill4c19a8a2017-07-24 11:46:06 -04001598 mProgram->updateCachedOutputLayoutFromShader();
Jamie Madill01074252016-11-28 15:55:51 -05001599
Jamie Madill785e8a02018-10-04 17:42:00 -04001600 ANGLE_TRY(mProgram->getPixelExecutableForCachedOutputLayout(this, &mExecutable, &mInfoLog));
Jamie Madill01074252016-11-28 15:55:51 -05001601
Jamie Madill7c985f52018-11-29 18:16:17 -05001602 return angle::Result::Continue;
Jamie Madill01074252016-11-28 15:55:51 -05001603 }
1604};
1605
Jamie Madill4c19a8a2017-07-24 11:46:06 -04001606void ProgramD3D::updateCachedOutputLayoutFromShader()
1607{
1608 GetDefaultOutputLayoutFromShader(mPixelShaderKey, &mPixelShaderOutputLayoutCache);
Jamie Madill0e7f1732017-09-09 23:32:50 -04001609 updateCachedPixelExecutableIndex();
Jamie Madill4c19a8a2017-07-24 11:46:06 -04001610}
1611
Xinghua Caof3179a62018-07-12 16:22:06 +08001612void ProgramD3D::updateCachedImage2DBindLayoutFromComputeShader()
1613{
1614 GetDefaultImage2DBindLayoutFromComputeShader(mImage2DUniforms,
1615 &mComputeShaderImage2DBindLayoutCache);
1616 updateCachedComputeExecutableIndex();
1617}
1618
Jamie Madill01074252016-11-28 15:55:51 -05001619class ProgramD3D::GetGeometryExecutableTask : public ProgramD3D::GetExecutableTask
1620{
1621 public:
Jeff Gilbert465d6092019-01-02 16:21:18 -08001622 GetGeometryExecutableTask(ProgramD3D *program, const gl::State &state)
1623 : GetExecutableTask(program), mState(state)
Jamie Madillb980c562018-11-27 11:34:27 -05001624 {}
Jamie Madill01074252016-11-28 15:55:51 -05001625
Jamie Madillec1fe5b2018-08-10 10:05:52 -04001626 angle::Result run() override
Jamie Madill01074252016-11-28 15:55:51 -05001627 {
1628 // Auto-generate the geometry shader here, if we expect to be using point rendering in
1629 // D3D11.
Jeff Gilbert465d6092019-01-02 16:21:18 -08001630 if (mProgram->usesGeometryShader(mState, gl::PrimitiveMode::Points))
Jamie Madill01074252016-11-28 15:55:51 -05001631 {
Jamie Madill493f9572018-05-24 19:52:15 -04001632 ANGLE_TRY(mProgram->getGeometryExecutableForPrimitiveType(
Jeff Gilbert465d6092019-01-02 16:21:18 -08001633 this, mState, gl::PrimitiveMode::Points, &mExecutable, &mInfoLog));
Jamie Madill01074252016-11-28 15:55:51 -05001634 }
1635
Jamie Madill7c985f52018-11-29 18:16:17 -05001636 return angle::Result::Continue;
Jamie Madill01074252016-11-28 15:55:51 -05001637 }
Jamie Madill785e8a02018-10-04 17:42:00 -04001638
1639 private:
Jeff Gilbert465d6092019-01-02 16:21:18 -08001640 const gl::State &mState;
Jamie Madill01074252016-11-28 15:55:51 -05001641};
1642
jchen107ae70d82018-07-06 13:47:01 +08001643// The LinkEvent implementation for linking a rendering(VS, FS, GS) program.
1644class ProgramD3D::GraphicsProgramLinkEvent final : public LinkEvent
1645{
1646 public:
1647 GraphicsProgramLinkEvent(gl::InfoLog &infoLog,
1648 std::shared_ptr<WorkerThreadPool> workerPool,
1649 std::shared_ptr<ProgramD3D::GetVertexExecutableTask> vertexTask,
1650 std::shared_ptr<ProgramD3D::GetPixelExecutableTask> pixelTask,
1651 std::shared_ptr<ProgramD3D::GetGeometryExecutableTask> geometryTask,
1652 bool useGS,
1653 const ShaderD3D *vertexShader,
1654 const ShaderD3D *fragmentShader)
1655 : mInfoLog(infoLog),
1656 mWorkerPool(workerPool),
1657 mVertexTask(vertexTask),
1658 mPixelTask(pixelTask),
1659 mGeometryTask(geometryTask),
1660 mWaitEvents(
1661 {{std::shared_ptr<WaitableEvent>(workerPool->postWorkerTask(mVertexTask)),
1662 std::shared_ptr<WaitableEvent>(workerPool->postWorkerTask(mPixelTask)),
1663 std::shared_ptr<WaitableEvent>(workerPool->postWorkerTask(mGeometryTask))}}),
1664 mUseGS(useGS),
1665 mVertexShader(vertexShader),
1666 mFragmentShader(fragmentShader)
Jamie Madillb980c562018-11-27 11:34:27 -05001667 {}
jchen107ae70d82018-07-06 13:47:01 +08001668
Jamie Madill785e8a02018-10-04 17:42:00 -04001669 angle::Result wait(const gl::Context *context) override
jchen107ae70d82018-07-06 13:47:01 +08001670 {
1671 WaitableEvent::WaitMany(&mWaitEvents);
1672
Jamie Madill785e8a02018-10-04 17:42:00 -04001673 ANGLE_TRY(checkTask(context, mVertexTask.get()));
1674 ANGLE_TRY(checkTask(context, mPixelTask.get()));
1675 ANGLE_TRY(checkTask(context, mGeometryTask.get()));
1676
Jamie Madill7c985f52018-11-29 18:16:17 -05001677 if (mVertexTask.get()->getResult() == angle::Result::Incomplete ||
1678 mPixelTask.get()->getResult() == angle::Result::Incomplete ||
1679 mGeometryTask.get()->getResult() == angle::Result::Incomplete)
jchen107ae70d82018-07-06 13:47:01 +08001680 {
Jamie Madill7c985f52018-11-29 18:16:17 -05001681 return angle::Result::Incomplete;
jchen107ae70d82018-07-06 13:47:01 +08001682 }
1683
1684 ShaderExecutableD3D *defaultVertexExecutable = mVertexTask->getExecutable();
1685 ShaderExecutableD3D *defaultPixelExecutable = mPixelTask->getExecutable();
1686 ShaderExecutableD3D *pointGS = mGeometryTask->getExecutable();
1687
1688 if (mUseGS && pointGS)
1689 {
1690 // Geometry shaders are currently only used internally, so there is no corresponding
1691 // shader object at the interface level. For now the geometry shader debug info is
1692 // prepended to the vertex shader.
1693 mVertexShader->appendDebugInfo("// GEOMETRY SHADER BEGIN\n\n");
1694 mVertexShader->appendDebugInfo(pointGS->getDebugInfo());
1695 mVertexShader->appendDebugInfo("\nGEOMETRY SHADER END\n\n\n");
1696 }
1697
1698 if (defaultVertexExecutable)
1699 {
1700 mVertexShader->appendDebugInfo(defaultVertexExecutable->getDebugInfo());
1701 }
1702
1703 if (defaultPixelExecutable)
1704 {
1705 mFragmentShader->appendDebugInfo(defaultPixelExecutable->getDebugInfo());
1706 }
1707
1708 bool isLinked = (defaultVertexExecutable && defaultPixelExecutable && (!mUseGS || pointGS));
1709 if (!isLinked)
1710 {
1711 mInfoLog << "Failed to create D3D Shaders";
1712 }
Jamie Madill7c985f52018-11-29 18:16:17 -05001713 return isLinked ? angle::Result::Continue : angle::Result::Incomplete;
jchen107ae70d82018-07-06 13:47:01 +08001714 }
1715
1716 bool isLinking() override
1717 {
1718 for (auto &event : mWaitEvents)
1719 {
1720 if (!event->isReady())
1721 {
1722 return true;
1723 }
1724 }
1725 return false;
1726 }
1727
1728 private:
Jamie Madill785e8a02018-10-04 17:42:00 -04001729 angle::Result checkTask(const gl::Context *context, ProgramD3D::GetExecutableTask *task)
jchen107ae70d82018-07-06 13:47:01 +08001730 {
1731 if (!task->getInfoLog().empty())
1732 {
1733 mInfoLog << task->getInfoLog().str();
1734 }
Jamie Madill785e8a02018-10-04 17:42:00 -04001735
1736 // Continue and Incomplete are not errors. For Stop, pass the error to the ContextD3D.
Jamie Madill7c985f52018-11-29 18:16:17 -05001737 if (task->getResult() != angle::Result::Stop)
jchen107ae70d82018-07-06 13:47:01 +08001738 {
Jamie Madill7c985f52018-11-29 18:16:17 -05001739 return angle::Result::Continue;
jchen107ae70d82018-07-06 13:47:01 +08001740 }
Jamie Madill785e8a02018-10-04 17:42:00 -04001741
1742 ContextD3D *contextD3D = GetImplAs<ContextD3D>(context);
1743 task->popError(contextD3D);
Jamie Madill7c985f52018-11-29 18:16:17 -05001744 return angle::Result::Stop;
jchen107ae70d82018-07-06 13:47:01 +08001745 }
1746
1747 gl::InfoLog &mInfoLog;
1748 std::shared_ptr<WorkerThreadPool> mWorkerPool;
1749 std::shared_ptr<ProgramD3D::GetVertexExecutableTask> mVertexTask;
1750 std::shared_ptr<ProgramD3D::GetPixelExecutableTask> mPixelTask;
1751 std::shared_ptr<ProgramD3D::GetGeometryExecutableTask> mGeometryTask;
1752 std::array<std::shared_ptr<WaitableEvent>, 3> mWaitEvents;
1753 bool mUseGS;
1754 const ShaderD3D *mVertexShader;
1755 const ShaderD3D *mFragmentShader;
1756};
1757
1758std::unique_ptr<LinkEvent> ProgramD3D::compileProgramExecutables(const gl::Context *context,
1759 gl::InfoLog &infoLog)
Jamie Madill01074252016-11-28 15:55:51 -05001760{
1761 // Ensure the compiler is initialized to avoid race conditions.
Jamie Madill785e8a02018-10-04 17:42:00 -04001762 angle::Result result = mRenderer->ensureHLSLCompilerInitialized(GetImplAs<ContextD3D>(context));
Jamie Madill7c985f52018-11-29 18:16:17 -05001763 if (result != angle::Result::Continue)
Jiawei Shao02f15232017-12-27 10:10:28 +08001764 {
jchen107ae70d82018-07-06 13:47:01 +08001765 return std::make_unique<LinkEventDone>(result);
Jiawei Shao02f15232017-12-27 10:10:28 +08001766 }
Jamie Madill01074252016-11-28 15:55:51 -05001767
Jamie Madill785e8a02018-10-04 17:42:00 -04001768 auto vertexTask = std::make_shared<GetVertexExecutableTask>(this);
1769 auto pixelTask = std::make_shared<GetPixelExecutableTask>(this);
Jeff Gilbert465d6092019-01-02 16:21:18 -08001770 auto geometryTask = std::make_shared<GetGeometryExecutableTask>(this, context->getState());
1771 bool useGS = usesGeometryShader(context->getState(), gl::PrimitiveMode::Points);
Jiawei Shao385b3e02018-03-21 09:43:28 +08001772 const ShaderD3D *vertexShaderD3D =
1773 GetImplAs<ShaderD3D>(mState.getAttachedShader(gl::ShaderType::Vertex));
jchen107ae70d82018-07-06 13:47:01 +08001774 const ShaderD3D *fragmentShaderD3D =
1775 GetImplAs<ShaderD3D>(mState.getAttachedShader(gl::ShaderType::Fragment));
Jamie Madill847638a2015-11-20 13:01:41 -05001776
jchen107ae70d82018-07-06 13:47:01 +08001777 return std::make_unique<GraphicsProgramLinkEvent>(infoLog, context->getWorkerThreadPool(),
1778 vertexTask, pixelTask, geometryTask, useGS,
1779 vertexShaderD3D, fragmentShaderD3D);
Brandon Jones18bd4102014-09-22 14:21:44 -07001780}
1781
Xinghua Caof3179a62018-07-12 16:22:06 +08001782angle::Result ProgramD3D::getComputeExecutableForImage2DBindLayout(
1783 d3d::Context *context,
1784 ShaderExecutableD3D **outExecutable,
1785 gl::InfoLog *infoLog)
1786{
1787 if (mCachedComputeExecutableIndex.valid())
1788 {
1789 *outExecutable =
1790 mComputeExecutables[mCachedComputeExecutableIndex.value()]->shaderExecutable();
1791 return angle::Result::Continue;
1792 }
1793
1794 std::string finalComputeHLSL = mDynamicHLSL->generateComputeShaderForImage2DBindSignature(
1795 context, *this, mState, mImage2DUniforms, mComputeShaderImage2DBindLayoutCache);
1796
1797 // Generate new compute executable
1798 ShaderExecutableD3D *computeExecutable = nullptr;
1799
1800 gl::InfoLog tempInfoLog;
1801 gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
1802
1803 ANGLE_TRY(mRenderer->compileToExecutable(
1804 context, *currentInfoLog, finalComputeHLSL, gl::ShaderType::Compute,
1805 std::vector<D3DVarying>(), false, angle::CompilerWorkaroundsD3D(), &computeExecutable));
1806
1807 if (computeExecutable)
1808 {
1809 mComputeExecutables.push_back(std::unique_ptr<ComputeExecutable>(
1810 new ComputeExecutable(mComputeShaderImage2DBindLayoutCache,
1811 std::unique_ptr<ShaderExecutableD3D>(computeExecutable))));
1812 mCachedComputeExecutableIndex = mComputeExecutables.size() - 1;
1813 }
1814 else if (!infoLog)
1815 {
1816 ERR() << "Error compiling dynamic compute executable:" << std::endl
1817 << tempInfoLog.str() << std::endl;
1818 }
1819 *outExecutable = computeExecutable;
1820
1821 return angle::Result::Continue;
1822}
1823
Jamie Madill785e8a02018-10-04 17:42:00 -04001824angle::Result ProgramD3D::compileComputeExecutable(d3d::Context *context, gl::InfoLog &infoLog)
Xinghua Caob1239382016-12-13 15:07:05 +08001825{
1826 // Ensure the compiler is initialized to avoid race conditions.
Jamie Madillb1565902018-07-27 08:12:48 -04001827 ANGLE_TRY(mRenderer->ensureHLSLCompilerInitialized(context));
Xinghua Caob1239382016-12-13 15:07:05 +08001828
Xinghua Caof3179a62018-07-12 16:22:06 +08001829 updateCachedImage2DBindLayoutFromComputeShader();
Xinghua Caob1239382016-12-13 15:07:05 +08001830
1831 ShaderExecutableD3D *computeExecutable = nullptr;
Xinghua Caof3179a62018-07-12 16:22:06 +08001832 ANGLE_TRY(getComputeExecutableForImage2DBindLayout(context, &computeExecutable, &infoLog));
Xinghua Caob1239382016-12-13 15:07:05 +08001833
Xinghua Caof3179a62018-07-12 16:22:06 +08001834 return computeExecutable ? angle::Result::Continue : angle::Result::Incomplete;
Xinghua Caob1239382016-12-13 15:07:05 +08001835}
1836
jchen107ae70d82018-07-06 13:47:01 +08001837std::unique_ptr<LinkEvent> ProgramD3D::link(const gl::Context *context,
1838 const gl::ProgramLinkedResources &resources,
1839 gl::InfoLog &infoLog)
Brandon Jones22502d52014-08-29 16:58:36 -07001840{
Jamie Madillc3dc5d42018-12-30 12:12:04 -05001841 const auto &data = context->getState();
Jamie Madill8ecf7f92017-01-13 17:29:52 -05001842
Jamie Madill62d31cb2015-09-11 13:25:51 -04001843 reset();
1844
Jiawei Shao385b3e02018-03-21 09:43:28 +08001845 gl::Shader *computeShader = mState.getAttachedShader(gl::ShaderType::Compute);
Xinghua Caob1239382016-12-13 15:07:05 +08001846 if (computeShader)
Austin Kinross02df7962015-07-01 10:03:42 -07001847 {
Jiawei Shao54aafe52018-04-27 14:54:57 +08001848 mShaderSamplers[gl::ShaderType::Compute].resize(
1849 data.getCaps().maxShaderTextureImageUnits[gl::ShaderType::Compute]);
Xinghua Cao26143fd2017-11-01 18:19:05 +08001850 mImagesCS.resize(data.getCaps().maxImageUnits);
1851 mReadonlyImagesCS.resize(data.getCaps().maxImageUnits);
Xinghua Caob1239382016-12-13 15:07:05 +08001852
Jiawei Shao3dd8d2912018-03-30 09:39:09 +08001853 mShaderUniformsDirty.set(gl::ShaderType::Compute);
Xinghua Caob1239382016-12-13 15:07:05 +08001854
jchen103fd614d2018-08-13 12:21:58 +08001855 linkResources(resources);
jchen107ae70d82018-07-06 13:47:01 +08001856
Xinghua Caof3179a62018-07-12 16:22:06 +08001857 for (const sh::Uniform &uniform : computeShader->getUniforms())
1858 {
1859 if (gl::IsImageType(uniform.type) && gl::IsImage2DType(uniform.type))
1860 {
1861 mImage2DUniforms.push_back(uniform);
1862 }
1863 }
1864
1865 defineUniformsAndAssignRegisters();
1866
Jamie Madill785e8a02018-10-04 17:42:00 -04001867 angle::Result result = compileComputeExecutable(GetImplAs<ContextD3D>(context), infoLog);
Jamie Madill7c985f52018-11-29 18:16:17 -05001868 if (result != angle::Result::Continue)
Xinghua Caob1239382016-12-13 15:07:05 +08001869 {
1870 infoLog << "Failed to create D3D compute shader.";
Xinghua Caob1239382016-12-13 15:07:05 +08001871 }
jchen107ae70d82018-07-06 13:47:01 +08001872 return std::make_unique<LinkEventDone>(result);
Xinghua Caob1239382016-12-13 15:07:05 +08001873 }
1874 else
1875 {
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08001876 gl::ShaderMap<const ShaderD3D *> shadersD3D = {};
Jiawei Shao467c15f2018-04-24 15:04:26 +08001877 for (gl::ShaderType shaderType : gl::kAllGraphicsShaderTypes)
1878 {
1879 if (mState.getAttachedShader(shaderType))
1880 {
1881 shadersD3D[shaderType] = GetImplAs<ShaderD3D>(mState.getAttachedShader(shaderType));
Xinghua Caob1239382016-12-13 15:07:05 +08001882
Jiawei Shao467c15f2018-04-24 15:04:26 +08001883 mShaderSamplers[shaderType].resize(
Jiawei Shao54aafe52018-04-27 14:54:57 +08001884 data.getCaps().maxShaderTextureImageUnits[shaderType]);
Xinghua Caob1239382016-12-13 15:07:05 +08001885
Jiawei Shao467c15f2018-04-24 15:04:26 +08001886 shadersD3D[shaderType]->generateWorkarounds(&mShaderWorkarounds[shaderType]);
1887
1888 mShaderUniformsDirty.set(shaderType);
1889 }
1890 }
Xinghua Caob1239382016-12-13 15:07:05 +08001891
1892 if (mRenderer->getNativeLimitations().noFrontFacingSupport)
1893 {
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08001894 if (shadersD3D[gl::ShaderType::Fragment]->usesFrontFacing())
Xinghua Caob1239382016-12-13 15:07:05 +08001895 {
1896 infoLog << "The current renderer doesn't support gl_FrontFacing";
Jamie Madill7c985f52018-11-29 18:16:17 -05001897 return std::make_unique<LinkEventDone>(angle::Result::Incomplete);
Xinghua Caob1239382016-12-13 15:07:05 +08001898 }
1899 }
1900
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08001901 ProgramD3DMetadata metadata(mRenderer, shadersD3D);
Jamie Madillc9727f32017-11-07 12:37:07 -05001902 BuiltinVaryingsD3D builtins(metadata, resources.varyingPacking);
Xinghua Caob1239382016-12-13 15:07:05 +08001903
jchen103fd614d2018-08-13 12:21:58 +08001904 mDynamicHLSL->generateShaderLinkHLSL(context->getCaps(), mState, metadata,
1905 resources.varyingPacking, builtins, &mShaderHLSL);
Xinghua Caob1239382016-12-13 15:07:05 +08001906
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08001907 mUsesPointSize = shadersD3D[gl::ShaderType::Vertex]->usesPointSize();
Xinghua Caob1239382016-12-13 15:07:05 +08001908 mDynamicHLSL->getPixelShaderOutputKey(data, mState, metadata, &mPixelShaderKey);
Xinghua Cao26143fd2017-11-01 18:19:05 +08001909 mUsesFragDepth = metadata.usesFragDepth();
Martin Radev41ac68e2017-06-06 12:16:58 +03001910 mUsesViewID = metadata.usesViewID();
1911 mHasANGLEMultiviewEnabled = metadata.hasANGLEMultiviewEnabled();
Xinghua Caob1239382016-12-13 15:07:05 +08001912
1913 // Cache if we use flat shading
jchen103fd614d2018-08-13 12:21:58 +08001914 mUsesFlatInterpolation = FindFlatInterpolationVarying(mState.getAttachedShaders());
Xinghua Caob1239382016-12-13 15:07:05 +08001915
1916 if (mRenderer->getMajorShaderModel() >= 4)
1917 {
Martin Radev41ac68e2017-06-06 12:16:58 +03001918 mGeometryShaderPreamble = mDynamicHLSL->generateGeometryShaderPreamble(
Jamie Madillc9727f32017-11-07 12:37:07 -05001919 resources.varyingPacking, builtins, mHasANGLEMultiviewEnabled,
Martin Radevc1d4e552017-08-21 12:01:10 +03001920 metadata.canSelectViewInVertexShader());
Xinghua Caob1239382016-12-13 15:07:05 +08001921 }
1922
jchen103fd614d2018-08-13 12:21:58 +08001923 initAttribLocationsToD3DSemantic();
Xinghua Caob1239382016-12-13 15:07:05 +08001924
jchen103fd614d2018-08-13 12:21:58 +08001925 defineUniformsAndAssignRegisters();
Xinghua Caob1239382016-12-13 15:07:05 +08001926
Jiawei Shao385b3e02018-03-21 09:43:28 +08001927 gatherTransformFeedbackVaryings(resources.varyingPacking, builtins[gl::ShaderType::Vertex]);
Xinghua Caob1239382016-12-13 15:07:05 +08001928
jchen103fd614d2018-08-13 12:21:58 +08001929 linkResources(resources);
jchen107ae70d82018-07-06 13:47:01 +08001930
1931 return compileProgramExecutables(context, infoLog);
Austin Kinross02df7962015-07-01 10:03:42 -07001932 }
Brandon Jones22502d52014-08-29 16:58:36 -07001933}
1934
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001935GLboolean ProgramD3D::validate(const gl::Caps & /*caps*/, gl::InfoLog * /*infoLog*/)
Jamie Madill36cfd6a2015-08-18 10:46:20 -04001936{
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001937 // TODO(jmadill): Do something useful here?
1938 return GL_TRUE;
Jamie Madill36cfd6a2015-08-18 10:46:20 -04001939}
1940
Qin Jiajiaa602f902018-09-11 14:40:24 +08001941void ProgramD3D::initializeShaderStorageBlocks()
1942{
1943 if (mState.getShaderStorageBlocks().empty())
1944 {
1945 return;
1946 }
1947
1948 ASSERT(mD3DShaderStorageBlocks.empty());
1949
1950 // Assign registers and update sizes.
1951 gl::ShaderMap<const ShaderD3D *> shadersD3D = {};
1952 for (gl::ShaderType shaderType : gl::AllShaderTypes())
1953 {
1954 shadersD3D[shaderType] = SafeGetImplAs<ShaderD3D>(mState.getAttachedShader(shaderType));
1955 }
1956
1957 for (const gl::InterfaceBlock &shaderStorageBlock : mState.getShaderStorageBlocks())
1958 {
1959 unsigned int shaderStorageBlockElement =
1960 shaderStorageBlock.isArray ? shaderStorageBlock.arrayElement : 0;
1961
1962 D3DInterfaceBlock d3dShaderStorageBlock;
1963
1964 for (gl::ShaderType shaderType : gl::AllShaderTypes())
1965 {
1966 if (shaderStorageBlock.isActive(shaderType))
1967 {
1968 ASSERT(shadersD3D[shaderType]);
1969 unsigned int baseRegister =
1970 shadersD3D[shaderType]->getShaderStorageBlockRegister(shaderStorageBlock.name);
1971 d3dShaderStorageBlock.mShaderRegisterIndexes[shaderType] =
1972 baseRegister + shaderStorageBlockElement;
1973 }
1974 }
1975
1976 mD3DShaderStorageBlocks.push_back(d3dShaderStorageBlock);
1977 }
1978}
1979
Jamie Madill6db1c2e2017-11-08 09:17:40 -05001980void ProgramD3D::initializeUniformBlocks()
Jamie Madill62d31cb2015-09-11 13:25:51 -04001981{
Jamie Madill6db1c2e2017-11-08 09:17:40 -05001982 if (mState.getUniformBlocks().empty())
Jamie Madill51f522f2016-12-21 15:10:55 -05001983 {
1984 return;
1985 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04001986
Jamie Madill6db1c2e2017-11-08 09:17:40 -05001987 ASSERT(mD3DUniformBlocks.empty());
1988
Jamie Madill62d31cb2015-09-11 13:25:51 -04001989 // Assign registers and update sizes.
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08001990 gl::ShaderMap<const ShaderD3D *> shadersD3D = {};
1991 for (gl::ShaderType shaderType : gl::AllShaderTypes())
1992 {
1993 shadersD3D[shaderType] = SafeGetImplAs<ShaderD3D>(mState.getAttachedShader(shaderType));
1994 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04001995
Jiajia Qin729b2c62017-08-14 09:36:11 +08001996 for (const gl::InterfaceBlock &uniformBlock : mState.getUniformBlocks())
Jamie Madill62d31cb2015-09-11 13:25:51 -04001997 {
1998 unsigned int uniformBlockElement = uniformBlock.isArray ? uniformBlock.arrayElement : 0;
1999
Qin Jiajiaa602f902018-09-11 14:40:24 +08002000 D3DInterfaceBlock d3dUniformBlock;
Jamie Madill4a3c2342015-10-08 12:58:45 -04002001
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002002 for (gl::ShaderType shaderType : gl::AllShaderTypes())
Jamie Madill62d31cb2015-09-11 13:25:51 -04002003 {
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002004 if (uniformBlock.isActive(shaderType))
2005 {
2006 ASSERT(shadersD3D[shaderType]);
2007 unsigned int baseRegister =
2008 shadersD3D[shaderType]->getUniformBlockRegister(uniformBlock.name);
2009 d3dUniformBlock.mShaderRegisterIndexes[shaderType] =
2010 baseRegister + uniformBlockElement;
2011 }
Xinghua Caob1239382016-12-13 15:07:05 +08002012 }
2013
Jamie Madill4a3c2342015-10-08 12:58:45 -04002014 mD3DUniformBlocks.push_back(d3dUniformBlock);
Jamie Madill62d31cb2015-09-11 13:25:51 -04002015 }
2016}
2017
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002018void ProgramD3D::initializeUniformStorage(const gl::ShaderBitSet &availableShaderStages)
Brandon Jonesc9610c52014-08-25 17:02:59 -07002019{
2020 // Compute total default block size
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002021 gl::ShaderMap<unsigned int> shaderRegisters = {};
Jamie Madill62d31cb2015-09-11 13:25:51 -04002022 for (const D3DUniform *d3dUniform : mD3DUniforms)
Brandon Jonesc9610c52014-08-25 17:02:59 -07002023 {
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002024 if (d3dUniform->isSampler())
Brandon Jonesc9610c52014-08-25 17:02:59 -07002025 {
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002026 continue;
2027 }
2028
Jiawei Shao0661eb82018-06-13 10:51:54 +08002029 for (gl::ShaderType shaderType : availableShaderStages)
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002030 {
2031 if (d3dUniform->isReferencedByShader(shaderType))
Brandon Jonesc9610c52014-08-25 17:02:59 -07002032 {
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002033 shaderRegisters[shaderType] = std::max(
2034 shaderRegisters[shaderType],
2035 d3dUniform->mShaderRegisterIndexes[shaderType] + d3dUniform->registerCount);
Xinghua Caob1239382016-12-13 15:07:05 +08002036 }
Brandon Jonesc9610c52014-08-25 17:02:59 -07002037 }
2038 }
2039
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002040 // We only reset uniform storages for the shader stages available in the program (attached
2041 // shaders in ProgramD3D::link() and linkedShaderStages in ProgramD3D::load()).
Jiawei Shao0661eb82018-06-13 10:51:54 +08002042 for (gl::ShaderType shaderType : availableShaderStages)
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002043 {
Jiawei Shao0661eb82018-06-13 10:51:54 +08002044 mShaderUniformStorages[shaderType].reset(
2045 mRenderer->createUniformStorage(shaderRegisters[shaderType] * 16u));
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002046 }
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002047
2048 // Iterate the uniforms again to assign data pointers to default block uniforms.
2049 for (D3DUniform *d3dUniform : mD3DUniforms)
2050 {
2051 if (d3dUniform->isSampler())
2052 {
Olli Etuaho465835d2017-09-26 13:34:10 +03002053 d3dUniform->mSamplerData.resize(d3dUniform->getArraySizeProduct(), 0);
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002054 continue;
2055 }
2056
Jiawei Shao0661eb82018-06-13 10:51:54 +08002057 for (gl::ShaderType shaderType : availableShaderStages)
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002058 {
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002059 if (d3dUniform->isReferencedByShader(shaderType))
2060 {
2061 d3dUniform->mShaderData[shaderType] =
2062 mShaderUniformStorages[shaderType]->getDataPointer(
2063 d3dUniform->mShaderRegisterIndexes[shaderType],
2064 d3dUniform->registerElement);
2065 }
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002066 }
2067 }
Brandon Jonesc9610c52014-08-25 17:02:59 -07002068}
2069
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002070void ProgramD3D::updateUniformBufferCache(
2071 const gl::Caps &caps,
2072 const gl::ShaderMap<unsigned int> &reservedShaderRegisterIndexes)
Brandon Jones18bd4102014-09-22 14:21:44 -07002073{
Jamie Madill48ef11b2016-04-27 15:21:52 -04002074 if (mState.getUniformBlocks().empty())
Jamie Madill4a3c2342015-10-08 12:58:45 -04002075 {
Jamie Madilld63961d2017-09-12 15:22:57 -04002076 return;
Jamie Madill4a3c2342015-10-08 12:58:45 -04002077 }
2078
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002079 for (gl::ShaderType shaderType : gl::AllShaderTypes())
2080 {
2081 mShaderUBOCaches[shaderType].clear();
2082 }
Brandon Jones18bd4102014-09-22 14:21:44 -07002083
Jamie Madill4a3c2342015-10-08 12:58:45 -04002084 for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < mD3DUniformBlocks.size();
Jamie Madill62d31cb2015-09-11 13:25:51 -04002085 uniformBlockIndex++)
Brandon Jones18bd4102014-09-22 14:21:44 -07002086 {
Qin Jiajiaa602f902018-09-11 14:40:24 +08002087 const D3DInterfaceBlock &uniformBlock = mD3DUniformBlocks[uniformBlockIndex];
Jamie Madillb980c562018-11-27 11:34:27 -05002088 GLuint blockBinding = mState.getUniformBlockBinding(uniformBlockIndex);
Brandon Jones18bd4102014-09-22 14:21:44 -07002089
Brandon Jones18bd4102014-09-22 14:21:44 -07002090 // Unnecessary to apply an unreferenced standard or shared UBO
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002091 for (gl::ShaderType shaderType : gl::AllShaderTypes())
Brandon Jones18bd4102014-09-22 14:21:44 -07002092 {
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002093 if (!uniformBlock.activeInShader(shaderType))
2094 {
2095 continue;
2096 }
Brandon Jones18bd4102014-09-22 14:21:44 -07002097
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002098 unsigned int registerIndex = uniformBlock.mShaderRegisterIndexes[shaderType] -
2099 reservedShaderRegisterIndexes[shaderType];
Jiawei Shao54aafe52018-04-27 14:54:57 +08002100 ASSERT(registerIndex < caps.maxShaderUniformBlocks[shaderType]);
Jamie Madill03260fa2015-06-22 13:57:22 -04002101
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002102 std::vector<int> &shaderUBOcache = mShaderUBOCaches[shaderType];
2103 if (shaderUBOcache.size() <= registerIndex)
Jamie Madill03260fa2015-06-22 13:57:22 -04002104 {
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002105 shaderUBOcache.resize(registerIndex + 1, -1);
Jamie Madill03260fa2015-06-22 13:57:22 -04002106 }
2107
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002108 ASSERT(shaderUBOcache[registerIndex] == -1);
2109 shaderUBOcache[registerIndex] = blockBinding;
Brandon Jones18bd4102014-09-22 14:21:44 -07002110 }
2111 }
Jamie Madilld63961d2017-09-12 15:22:57 -04002112}
Brandon Jones18bd4102014-09-22 14:21:44 -07002113
Qin Jiajiaa602f902018-09-11 14:40:24 +08002114unsigned int ProgramD3D::getShaderStorageBufferRegisterIndex(GLuint blockIndex,
2115 gl::ShaderType shaderType) const
2116{
2117 return mD3DShaderStorageBlocks[blockIndex].mShaderRegisterIndexes[shaderType];
2118}
2119
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002120const std::vector<GLint> &ProgramD3D::getShaderUniformBufferCache(gl::ShaderType shaderType) const
Jamie Madilld63961d2017-09-12 15:22:57 -04002121{
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002122 return mShaderUBOCaches[shaderType];
Brandon Jones18bd4102014-09-22 14:21:44 -07002123}
2124
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002125void ProgramD3D::dirtyAllUniforms()
Brandon Jones18bd4102014-09-22 14:21:44 -07002126{
Jiawei Shao3dd8d2912018-03-30 09:39:09 +08002127 mShaderUniformsDirty = mState.getLinkedShaderStages();
Jamie Madill4148fd72017-09-14 15:46:20 -04002128}
2129
2130void ProgramD3D::markUniformsClean()
2131{
Jiawei Shao3dd8d2912018-03-30 09:39:09 +08002132 mShaderUniformsDirty.reset();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002133}
2134
Jamie Madill334d6152015-10-22 14:00:28 -04002135void ProgramD3D::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002136{
Jamie Madill33bb7c42017-09-09 23:32:51 -04002137 setUniformInternal(location, count, v, GL_FLOAT);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002138}
2139
2140void ProgramD3D::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
2141{
Jamie Madill33bb7c42017-09-09 23:32:51 -04002142 setUniformInternal(location, count, v, GL_FLOAT_VEC2);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002143}
2144
2145void ProgramD3D::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
2146{
Jamie Madill33bb7c42017-09-09 23:32:51 -04002147 setUniformInternal(location, count, v, GL_FLOAT_VEC3);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002148}
2149
2150void ProgramD3D::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
2151{
Jamie Madill33bb7c42017-09-09 23:32:51 -04002152 setUniformInternal(location, count, v, GL_FLOAT_VEC4);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002153}
2154
Jamie Madill334d6152015-10-22 14:00:28 -04002155void ProgramD3D::setUniformMatrix2fv(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<2, 2>(location, count, transpose, value);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002161}
2162
Jamie Madill334d6152015-10-22 14:00:28 -04002163void ProgramD3D::setUniformMatrix3fv(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<3, 3>(location, count, transpose, value);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002169}
2170
Jamie Madill334d6152015-10-22 14:00:28 -04002171void ProgramD3D::setUniformMatrix4fv(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<4, 4>(location, count, transpose, value);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002177}
2178
Jamie Madill334d6152015-10-22 14:00:28 -04002179void ProgramD3D::setUniformMatrix2x3fv(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<2, 3>(location, count, transpose, value);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002185}
2186
Jamie Madill334d6152015-10-22 14:00:28 -04002187void ProgramD3D::setUniformMatrix3x2fv(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<3, 2>(location, count, transpose, value);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002193}
2194
Jamie Madill334d6152015-10-22 14:00:28 -04002195void ProgramD3D::setUniformMatrix2x4fv(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<2, 4>(location, count, transpose, value);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002201}
2202
Jamie Madill334d6152015-10-22 14:00:28 -04002203void ProgramD3D::setUniformMatrix4x2fv(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<4, 2>(location, count, transpose, value);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002209}
2210
Jamie Madill334d6152015-10-22 14:00:28 -04002211void ProgramD3D::setUniformMatrix3x4fv(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<3, 4>(location, count, transpose, value);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002217}
2218
Jamie Madill334d6152015-10-22 14:00:28 -04002219void ProgramD3D::setUniformMatrix4x3fv(GLint location,
2220 GLsizei count,
2221 GLboolean transpose,
2222 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002223{
Luc Ferron46bcea52018-05-31 09:48:36 -04002224 setUniformMatrixfvInternal<4, 3>(location, count, transpose, value);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002225}
2226
2227void ProgramD3D::setUniform1iv(GLint location, GLsizei count, const GLint *v)
2228{
Jamie Madill33bb7c42017-09-09 23:32:51 -04002229 setUniformInternal(location, count, v, GL_INT);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002230}
2231
2232void ProgramD3D::setUniform2iv(GLint location, GLsizei count, const GLint *v)
2233{
Jamie Madill33bb7c42017-09-09 23:32:51 -04002234 setUniformInternal(location, count, v, GL_INT_VEC2);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002235}
2236
2237void ProgramD3D::setUniform3iv(GLint location, GLsizei count, const GLint *v)
2238{
Jamie Madill33bb7c42017-09-09 23:32:51 -04002239 setUniformInternal(location, count, v, GL_INT_VEC3);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002240}
2241
2242void ProgramD3D::setUniform4iv(GLint location, GLsizei count, const GLint *v)
2243{
Jamie Madill33bb7c42017-09-09 23:32:51 -04002244 setUniformInternal(location, count, v, GL_INT_VEC4);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002245}
2246
2247void ProgramD3D::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
2248{
Jamie Madill33bb7c42017-09-09 23:32:51 -04002249 setUniformInternal(location, count, v, GL_UNSIGNED_INT);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002250}
2251
2252void ProgramD3D::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
2253{
Jamie Madill33bb7c42017-09-09 23:32:51 -04002254 setUniformInternal(location, count, v, GL_UNSIGNED_INT_VEC2);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002255}
2256
2257void ProgramD3D::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
2258{
Jamie Madill33bb7c42017-09-09 23:32:51 -04002259 setUniformInternal(location, count, v, GL_UNSIGNED_INT_VEC3);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002260}
2261
2262void ProgramD3D::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
2263{
Jamie Madill33bb7c42017-09-09 23:32:51 -04002264 setUniformInternal(location, count, v, GL_UNSIGNED_INT_VEC4);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002265}
2266
jchen103fd614d2018-08-13 12:21:58 +08002267void ProgramD3D::defineUniformsAndAssignRegisters()
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002268{
Jamie Madill3d3d2f22015-09-23 16:47:51 -04002269 D3DUniformMap uniformMap;
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002270
2271 gl::ShaderBitSet attachedShaders;
Jiawei Shao385b3e02018-03-21 09:43:28 +08002272 for (gl::ShaderType shaderType : gl::AllShaderTypes())
Jamie Madill417df922017-01-12 09:23:07 -05002273 {
Jiawei Shao385b3e02018-03-21 09:43:28 +08002274 gl::Shader *shader = mState.getAttachedShader(shaderType);
2275 if (shader)
Jamie Madillfb536032015-09-11 13:19:49 -04002276 {
jchen103fd614d2018-08-13 12:21:58 +08002277 for (const sh::Uniform &uniform : shader->getUniforms())
Xinghua Caob1239382016-12-13 15:07:05 +08002278 {
Jiawei Shao385b3e02018-03-21 09:43:28 +08002279 if (uniform.active)
2280 {
2281 defineUniformBase(shader, uniform, &uniformMap);
2282 }
Xinghua Caob1239382016-12-13 15:07:05 +08002283 }
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002284
2285 attachedShaders.set(shader->getType());
Jamie Madillfb536032015-09-11 13:19:49 -04002286 }
2287 }
2288
Jamie Madill3d3d2f22015-09-23 16:47:51 -04002289 // Initialize the D3DUniform list to mirror the indexing of the GL layer.
Jamie Madill48ef11b2016-04-27 15:21:52 -04002290 for (const gl::LinkedUniform &glUniform : mState.getUniforms())
Jamie Madill3d3d2f22015-09-23 16:47:51 -04002291 {
2292 if (!glUniform.isInDefaultBlock())
2293 continue;
2294
Olli Etuahod2551232017-10-26 20:03:33 +03002295 std::string name = glUniform.name;
2296 if (glUniform.isArray())
2297 {
2298 // In the program state, array uniform names include [0] as in the program resource
2299 // spec. Here we don't include it.
2300 // TODO(oetuaho@nvidia.com): consider using the same uniform naming here as in the GL
2301 // layer.
2302 ASSERT(angle::EndsWith(name, "[0]"));
2303 name.resize(name.length() - 3);
2304 }
2305 auto mapEntry = uniformMap.find(name);
Jamie Madill3d3d2f22015-09-23 16:47:51 -04002306 ASSERT(mapEntry != uniformMap.end());
2307 mD3DUniforms.push_back(mapEntry->second);
2308 }
2309
Jamie Madill62d31cb2015-09-11 13:25:51 -04002310 assignAllSamplerRegisters();
Xinghua Cao6dfdca82018-08-03 17:10:55 +08002311 // Samplers and readonly images share shader input resource slot, adjust low value of
2312 // readonly image range.
2313 mUsedComputeReadonlyImageRange =
2314 gl::RangeUI(mUsedShaderSamplerRanges[gl::ShaderType::Compute].high(),
2315 mUsedShaderSamplerRanges[gl::ShaderType::Compute].high());
Xinghua Cao26143fd2017-11-01 18:19:05 +08002316 assignAllImageRegisters();
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002317 initializeUniformStorage(attachedShaders);
Jamie Madillfb536032015-09-11 13:19:49 -04002318}
2319
Jamie Madill91445bc2015-09-23 16:47:53 -04002320void ProgramD3D::defineUniformBase(const gl::Shader *shader,
Jamie Madill3d3d2f22015-09-23 16:47:51 -04002321 const sh::Uniform &uniform,
2322 D3DUniformMap *uniformMap)
Jamie Madillfb536032015-09-11 13:19:49 -04002323{
Jamie Madill8c78ce42018-12-16 19:14:58 -05002324 sh::DummyBlockEncoder dummyEncoder;
2325
Xinghua Cao26143fd2017-11-01 18:19:05 +08002326 // Samplers get their registers assigned in assignAllSamplerRegisters, and images get their
2327 // registers assigned in assignAllImageRegisters.
2328 if (gl::IsSamplerType(uniform.type))
Jamie Madillfb536032015-09-11 13:19:49 -04002329 {
Jamie Madill8c78ce42018-12-16 19:14:58 -05002330 UniformEncodingVisitorD3D visitor(shader->getType(), HLSLRegisterType::Texture,
2331 &dummyEncoder, uniformMap);
2332 sh::TraverseShaderVariable(uniform, false, &visitor);
Xinghua Cao26143fd2017-11-01 18:19:05 +08002333 return;
2334 }
Jamie Madill8c78ce42018-12-16 19:14:58 -05002335
2336 if (gl::IsImageType(uniform.type))
Xinghua Cao26143fd2017-11-01 18:19:05 +08002337 {
2338 if (uniform.readonly)
2339 {
Jamie Madill8c78ce42018-12-16 19:14:58 -05002340 UniformEncodingVisitorD3D visitor(shader->getType(), HLSLRegisterType::Texture,
2341 &dummyEncoder, uniformMap);
2342 sh::TraverseShaderVariable(uniform, false, &visitor);
Xinghua Cao26143fd2017-11-01 18:19:05 +08002343 }
2344 else
2345 {
Jamie Madill8c78ce42018-12-16 19:14:58 -05002346 UniformEncodingVisitorD3D visitor(shader->getType(),
2347 HLSLRegisterType::UnorderedAccessView, &dummyEncoder,
2348 uniformMap);
2349 sh::TraverseShaderVariable(uniform, false, &visitor);
Xinghua Cao26143fd2017-11-01 18:19:05 +08002350 }
2351 mImageBindingMap[uniform.name] = uniform.binding;
2352 return;
2353 }
Jamie Madill8c78ce42018-12-16 19:14:58 -05002354
2355 if (uniform.isBuiltIn() && !uniform.isEmulatedBuiltIn())
Xinghua Cao26143fd2017-11-01 18:19:05 +08002356 {
Jamie Madill8c78ce42018-12-16 19:14:58 -05002357 UniformEncodingVisitorD3D visitor(shader->getType(), HLSLRegisterType::None, &dummyEncoder,
2358 uniformMap);
2359 sh::TraverseShaderVariable(uniform, false, &visitor);
Jamie Madill55def582015-05-04 11:24:57 -04002360 return;
2361 }
2362
Jamie Madill91445bc2015-09-23 16:47:53 -04002363 const ShaderD3D *shaderD3D = GetImplAs<ShaderD3D>(shader);
Jamie Madill91445bc2015-09-23 16:47:53 -04002364 unsigned int startRegister = shaderD3D->getUniformRegister(uniform.name);
Xinghua Cao26143fd2017-11-01 18:19:05 +08002365 ShShaderOutput outputType = shaderD3D->getCompilerOutputType();
Jamie Madillcc2ed612017-03-14 15:59:00 -04002366 sh::HLSLBlockEncoder encoder(sh::HLSLBlockEncoder::GetStrategyFor(outputType), true);
Jamie Madill62d31cb2015-09-11 13:25:51 -04002367 encoder.skipRegisters(startRegister);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002368
Jamie Madill8c78ce42018-12-16 19:14:58 -05002369 UniformEncodingVisitorD3D visitor(shader->getType(), HLSLRegisterType::None, &encoder,
2370 uniformMap);
2371 sh::TraverseShaderVariable(uniform, false, &visitor);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002372}
2373
Xinghua Caof3179a62018-07-12 16:22:06 +08002374bool ProgramD3D::hasNamedUniform(const std::string &name)
Jamie Madill62d31cb2015-09-11 13:25:51 -04002375{
2376 for (D3DUniform *d3dUniform : mD3DUniforms)
2377 {
2378 if (d3dUniform->name == name)
2379 {
Xinghua Caof3179a62018-07-12 16:22:06 +08002380 return true;
Jamie Madill62d31cb2015-09-11 13:25:51 -04002381 }
2382 }
2383
Xinghua Caof3179a62018-07-12 16:22:06 +08002384 return false;
Jamie Madill62d31cb2015-09-11 13:25:51 -04002385}
2386
Jamie Madill134f93d2017-08-31 17:11:00 -04002387// Assume count is already clamped.
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002388template <typename T>
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002389void ProgramD3D::setUniformImpl(const gl::VariableLocation &locationInfo,
Jamie Madill134f93d2017-08-31 17:11:00 -04002390 GLsizei count,
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002391 const T *v,
2392 uint8_t *targetData,
Jamie Madill33bb7c42017-09-09 23:32:51 -04002393 GLenum uniformType)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002394{
Jamie Madill493f9572018-05-24 19:52:15 -04002395 D3DUniform *targetUniform = mD3DUniforms[locationInfo.index];
2396 const int components = targetUniform->typeInfo.componentCount;
Olli Etuaho1734e172017-10-27 15:30:27 +03002397 const unsigned int arrayElementOffset = locationInfo.arrayIndex;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002398
Jamie Madill33bb7c42017-09-09 23:32:51 -04002399 if (targetUniform->typeInfo.type == uniformType)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002400 {
Olli Etuahoc8538042017-09-27 11:20:15 +03002401 T *dest = reinterpret_cast<T *>(targetData) + arrayElementOffset * 4;
Jamie Madill33bb7c42017-09-09 23:32:51 -04002402 const T *source = v;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002403
Jamie Madill33bb7c42017-09-09 23:32:51 -04002404 for (GLint i = 0; i < count; i++, dest += 4, source += components)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002405 {
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002406 memcpy(dest, source, components * sizeof(T));
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002407 }
2408 }
Jamie Madill33bb7c42017-09-09 23:32:51 -04002409 else
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002410 {
Jamie Madill33bb7c42017-09-09 23:32:51 -04002411 ASSERT(targetUniform->typeInfo.type == gl::VariableBoolVectorType(uniformType));
Olli Etuahoc8538042017-09-27 11:20:15 +03002412 GLint *boolParams = reinterpret_cast<GLint *>(targetData) + arrayElementOffset * 4;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002413
Jamie Madill134f93d2017-08-31 17:11:00 -04002414 for (GLint i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002415 {
Jamie Madill334d6152015-10-22 14:00:28 -04002416 GLint *dest = boolParams + (i * 4);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002417 const T *source = v + (i * components);
2418
2419 for (int c = 0; c < components; c++)
2420 {
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002421 dest[c] = (source[c] == static_cast<T>(0)) ? GL_FALSE : GL_TRUE;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002422 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002423 }
Brandon Jones18bd4102014-09-22 14:21:44 -07002424 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002425}
2426
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002427template <typename T>
Jamie Madill33bb7c42017-09-09 23:32:51 -04002428void ProgramD3D::setUniformInternal(GLint location, GLsizei count, const T *v, GLenum uniformType)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002429{
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002430 const gl::VariableLocation &locationInfo = mState.getUniformLocations()[location];
2431 D3DUniform *targetUniform = mD3DUniforms[locationInfo.index];
2432
Jamie Madill33bb7c42017-09-09 23:32:51 -04002433 if (targetUniform->typeInfo.isSampler)
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002434 {
Jamie Madill33bb7c42017-09-09 23:32:51 -04002435 ASSERT(uniformType == GL_INT);
Jamie Madill80823cc2017-09-14 15:46:21 -04002436 size_t size = count * sizeof(T);
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002437 GLint *dest = &targetUniform->mSamplerData[locationInfo.arrayIndex];
Jamie Madill80823cc2017-09-14 15:46:21 -04002438 if (memcmp(dest, v, size) != 0)
2439 {
2440 memcpy(dest, v, size);
2441 mDirtySamplerMapping = true;
2442 }
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002443 return;
2444 }
2445
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002446 for (gl::ShaderType shaderType : gl::AllShaderTypes())
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002447 {
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002448 if (targetUniform->mShaderData[shaderType])
2449 {
2450 setUniformImpl(locationInfo, count, v, targetUniform->mShaderData[shaderType],
2451 uniformType);
2452 mShaderUniformsDirty.set(shaderType);
2453 }
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002454 }
2455}
2456
2457template <int cols, int rows>
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002458void ProgramD3D::setUniformMatrixfvInternal(GLint location,
2459 GLsizei countIn,
2460 GLboolean transpose,
Luc Ferron46bcea52018-05-31 09:48:36 -04002461 const GLfloat *value)
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002462{
Xinghua Cao6dfdca82018-08-03 17:10:55 +08002463 D3DUniform *targetUniform = getD3DUniformFromLocation(location);
Luc Ferron46bcea52018-05-31 09:48:36 -04002464 const gl::VariableLocation &uniformLocation = mState.getUniformLocations()[location];
2465 unsigned int arrayElementOffset = uniformLocation.arrayIndex;
2466 unsigned int elementCount = targetUniform->getArraySizeProduct();
2467
2468 // Internally store matrices as transposed versions to accomodate HLSL matrix indexing
2469 transpose = !transpose;
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002470
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002471 for (gl::ShaderType shaderType : gl::AllShaderTypes())
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002472 {
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002473 if (targetUniform->mShaderData[shaderType])
Jamie Madill80823cc2017-09-14 15:46:21 -04002474 {
Luc Ferron46bcea52018-05-31 09:48:36 -04002475 if (SetFloatUniformMatrix<cols, rows>(arrayElementOffset, elementCount, countIn,
2476 transpose, value,
2477 targetUniform->mShaderData[shaderType]))
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002478 {
2479 mShaderUniformsDirty.set(shaderType);
2480 }
Jamie Madill80823cc2017-09-14 15:46:21 -04002481 }
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002482 }
2483}
2484
Jamie Madill62d31cb2015-09-11 13:25:51 -04002485void ProgramD3D::assignAllSamplerRegisters()
Jamie Madilla2eb02c2015-09-11 12:31:41 +00002486{
Olli Etuaho465835d2017-09-26 13:34:10 +03002487 for (size_t uniformIndex = 0; uniformIndex < mD3DUniforms.size(); ++uniformIndex)
Jamie Madilla2eb02c2015-09-11 12:31:41 +00002488 {
Olli Etuaho465835d2017-09-26 13:34:10 +03002489 if (mD3DUniforms[uniformIndex]->isSampler())
Jamie Madillfb536032015-09-11 13:19:49 -04002490 {
Olli Etuaho465835d2017-09-26 13:34:10 +03002491 assignSamplerRegisters(uniformIndex);
Jamie Madillfb536032015-09-11 13:19:49 -04002492 }
Jamie Madilla2eb02c2015-09-11 12:31:41 +00002493 }
2494}
2495
Olli Etuaho465835d2017-09-26 13:34:10 +03002496void ProgramD3D::assignSamplerRegisters(size_t uniformIndex)
Jamie Madillfb536032015-09-11 13:19:49 -04002497{
Olli Etuaho465835d2017-09-26 13:34:10 +03002498 D3DUniform *d3dUniform = mD3DUniforms[uniformIndex];
Jamie Madill62d31cb2015-09-11 13:25:51 -04002499 ASSERT(d3dUniform->isSampler());
Olli Etuaho465835d2017-09-26 13:34:10 +03002500 // If the uniform is an array of arrays, then we have separate entries for each inner array in
2501 // mD3DUniforms. However, the sampler register info is stored in the shader only for the
2502 // outermost array.
2503 std::vector<unsigned int> subscripts;
Jamie Madill8c78ce42018-12-16 19:14:58 -05002504 const std::string baseName = gl::ParseResourceName(d3dUniform->name, &subscripts);
2505 unsigned int registerOffset =
2506 mState.getUniforms()[uniformIndex].parentArrayIndex() * d3dUniform->getArraySizeProduct();
Olli Etuaho465835d2017-09-26 13:34:10 +03002507
Jiawei Shao467c15f2018-04-24 15:04:26 +08002508 bool hasUniform = false;
2509 for (gl::ShaderType shaderType : gl::AllShaderTypes())
Jamie Madillfb536032015-09-11 13:19:49 -04002510 {
Jiawei Shao467c15f2018-04-24 15:04:26 +08002511 if (!mState.getAttachedShader(shaderType))
Xinghua Caob1239382016-12-13 15:07:05 +08002512 {
Jiawei Shao467c15f2018-04-24 15:04:26 +08002513 continue;
Xinghua Caob1239382016-12-13 15:07:05 +08002514 }
Jiawei Shao467c15f2018-04-24 15:04:26 +08002515
2516 const ShaderD3D *shaderD3D = GetImplAs<ShaderD3D>(mState.getAttachedShader(shaderType));
2517 if (shaderD3D->hasUniform(baseName))
Xinghua Caob1239382016-12-13 15:07:05 +08002518 {
Jiawei Shao467c15f2018-04-24 15:04:26 +08002519 d3dUniform->mShaderRegisterIndexes[shaderType] =
2520 shaderD3D->getUniformRegister(baseName) + registerOffset;
2521 ASSERT(d3dUniform->mShaderRegisterIndexes[shaderType] != GL_INVALID_VALUE);
2522
2523 AssignSamplers(d3dUniform->mShaderRegisterIndexes[shaderType], d3dUniform->typeInfo,
2524 d3dUniform->getArraySizeProduct(), mShaderSamplers[shaderType],
2525 &mUsedShaderSamplerRanges[shaderType]);
2526 hasUniform = true;
Xinghua Caob1239382016-12-13 15:07:05 +08002527 }
Jamie Madillfb536032015-09-11 13:19:49 -04002528 }
Jiawei Shao467c15f2018-04-24 15:04:26 +08002529
2530 ASSERT(hasUniform);
Jamie Madillfb536032015-09-11 13:19:49 -04002531}
2532
Jamie Madill62d31cb2015-09-11 13:25:51 -04002533// static
2534void ProgramD3D::AssignSamplers(unsigned int startSamplerIndex,
Jamie Madill33bb7c42017-09-09 23:32:51 -04002535 const gl::UniformTypeInfo &typeInfo,
Jamie Madilld3dfda22015-07-06 08:28:49 -04002536 unsigned int samplerCount,
2537 std::vector<Sampler> &outSamplers,
Xinghua Cao6dfdca82018-08-03 17:10:55 +08002538 gl::RangeUI *outUsedRange)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002539{
2540 unsigned int samplerIndex = startSamplerIndex;
Xinghua Cao6dfdca82018-08-03 17:10:55 +08002541 unsigned int low = outUsedRange->low();
2542 unsigned int high = outUsedRange->high();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002543
2544 do
2545 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002546 ASSERT(samplerIndex < outSamplers.size());
2547 Sampler *sampler = &outSamplers[samplerIndex];
2548 sampler->active = true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002549 sampler->textureType = gl::FromGLenum<gl::TextureType>(typeInfo.textureType);
Jamie Madill62d31cb2015-09-11 13:25:51 -04002550 sampler->logicalTextureUnit = 0;
Xinghua Cao6dfdca82018-08-03 17:10:55 +08002551 low = std::min(samplerIndex, low);
2552 high = std::max(samplerIndex + 1, high);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002553 samplerIndex++;
2554 } while (samplerIndex < startSamplerIndex + samplerCount);
Xinghua Cao6dfdca82018-08-03 17:10:55 +08002555
2556 ASSERT(low < high);
2557 *outUsedRange = gl::RangeUI(low, high);
Brandon Jones18bd4102014-09-22 14:21:44 -07002558}
2559
Xinghua Cao26143fd2017-11-01 18:19:05 +08002560void ProgramD3D::assignAllImageRegisters()
2561{
2562 for (size_t uniformIndex = 0; uniformIndex < mD3DUniforms.size(); ++uniformIndex)
2563 {
Xinghua Caof3179a62018-07-12 16:22:06 +08002564 if (mD3DUniforms[uniformIndex]->isImage() && !mD3DUniforms[uniformIndex]->isImage2D())
Xinghua Cao26143fd2017-11-01 18:19:05 +08002565 {
2566 assignImageRegisters(uniformIndex);
2567 }
2568 }
2569}
2570
2571void ProgramD3D::assignImageRegisters(size_t uniformIndex)
2572{
2573 D3DUniform *d3dUniform = mD3DUniforms[uniformIndex];
2574 ASSERT(d3dUniform->isImage());
2575 // If the uniform is an array of arrays, then we have separate entries for each inner array in
2576 // mD3DUniforms. However, the image register info is stored in the shader only for the
2577 // outermost array.
2578 std::vector<unsigned int> subscripts;
Jamie Madill8c78ce42018-12-16 19:14:58 -05002579 const std::string baseName = gl::ParseResourceName(d3dUniform->name, &subscripts);
2580 unsigned int registerOffset =
2581 mState.getUniforms()[uniformIndex].parentArrayIndex() * d3dUniform->getArraySizeProduct();
Xinghua Cao26143fd2017-11-01 18:19:05 +08002582
Jiawei Shao385b3e02018-03-21 09:43:28 +08002583 const gl::Shader *computeShader = mState.getAttachedShader(gl::ShaderType::Compute);
Xinghua Cao26143fd2017-11-01 18:19:05 +08002584 if (computeShader)
2585 {
Jiawei Shao385b3e02018-03-21 09:43:28 +08002586 const ShaderD3D *computeShaderD3D =
2587 GetImplAs<ShaderD3D>(mState.getAttachedShader(gl::ShaderType::Compute));
Xinghua Cao26143fd2017-11-01 18:19:05 +08002588 ASSERT(computeShaderD3D->hasUniform(baseName));
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002589 d3dUniform->mShaderRegisterIndexes[gl::ShaderType::Compute] =
Xinghua Cao26143fd2017-11-01 18:19:05 +08002590 computeShaderD3D->getUniformRegister(baseName) + registerOffset;
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002591 ASSERT(d3dUniform->mShaderRegisterIndexes[gl::ShaderType::Compute] != GL_INVALID_INDEX);
Xinghua Cao26143fd2017-11-01 18:19:05 +08002592 auto bindingIter = mImageBindingMap.find(baseName);
2593 ASSERT(bindingIter != mImageBindingMap.end());
2594 if (d3dUniform->regType == HLSLRegisterType::Texture)
2595 {
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002596 AssignImages(d3dUniform->mShaderRegisterIndexes[gl::ShaderType::Compute],
2597 bindingIter->second, d3dUniform->getArraySizeProduct(), mReadonlyImagesCS,
Xinghua Cao26143fd2017-11-01 18:19:05 +08002598 &mUsedComputeReadonlyImageRange);
2599 }
2600 else if (d3dUniform->regType == HLSLRegisterType::UnorderedAccessView)
2601 {
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002602 AssignImages(d3dUniform->mShaderRegisterIndexes[gl::ShaderType::Compute],
2603 bindingIter->second, d3dUniform->getArraySizeProduct(), mImagesCS,
2604 &mUsedComputeImageRange);
Xinghua Cao26143fd2017-11-01 18:19:05 +08002605 }
2606 else
2607 {
2608 UNREACHABLE();
2609 }
2610 }
2611 else
2612 {
2613 // TODO(xinghua.cao@intel.com): Implement image variables in vertex shader and pixel shader.
2614 UNIMPLEMENTED();
2615 }
2616}
2617
2618// static
2619void ProgramD3D::AssignImages(unsigned int startImageIndex,
2620 int startLogicalImageUnit,
2621 unsigned int imageCount,
2622 std::vector<Image> &outImages,
Xinghua Cao6dfdca82018-08-03 17:10:55 +08002623 gl::RangeUI *outUsedRange)
Xinghua Cao26143fd2017-11-01 18:19:05 +08002624{
2625 unsigned int imageIndex = startImageIndex;
Xinghua Cao6dfdca82018-08-03 17:10:55 +08002626 unsigned int low = outUsedRange->low();
2627 unsigned int high = outUsedRange->high();
2628
Xinghua Cao26143fd2017-11-01 18:19:05 +08002629 // If declare without a binding qualifier, any uniform image variable (include all elements of
2630 // unbound image array) shoud be bound to unit zero.
2631 if (startLogicalImageUnit == -1)
2632 {
2633 ASSERT(imageIndex < outImages.size());
2634 Image *image = &outImages[imageIndex];
2635 image->active = true;
2636 image->logicalImageUnit = 0;
Xinghua Cao6dfdca82018-08-03 17:10:55 +08002637 low = std::min(imageIndex, low);
2638 high = std::max(imageIndex + 1, high);
2639 ASSERT(low < high);
2640 *outUsedRange = gl::RangeUI(low, high);
Xinghua Cao26143fd2017-11-01 18:19:05 +08002641 return;
2642 }
2643
2644 unsigned int logcalImageUnit = startLogicalImageUnit;
2645 do
2646 {
2647 ASSERT(imageIndex < outImages.size());
2648 Image *image = &outImages[imageIndex];
2649 image->active = true;
2650 image->logicalImageUnit = logcalImageUnit;
Xinghua Cao6dfdca82018-08-03 17:10:55 +08002651 low = std::min(imageIndex, low);
2652 high = std::max(imageIndex + 1, high);
Xinghua Cao26143fd2017-11-01 18:19:05 +08002653 imageIndex++;
2654 logcalImageUnit++;
2655 } while (imageIndex < startImageIndex + imageCount);
Xinghua Cao6dfdca82018-08-03 17:10:55 +08002656
2657 ASSERT(low < high);
2658 *outUsedRange = gl::RangeUI(low, high);
Xinghua Cao26143fd2017-11-01 18:19:05 +08002659}
2660
Xinghua Caof3179a62018-07-12 16:22:06 +08002661void ProgramD3D::assignImage2DRegisters(unsigned int startImageIndex,
2662 int startLogicalImageUnit,
2663 bool readonly)
2664{
2665 if (readonly)
2666 {
2667 AssignImages(startImageIndex, startLogicalImageUnit, 1, mReadonlyImagesCS,
2668 &mUsedComputeReadonlyImageRange);
2669 }
2670 else
2671 {
2672 AssignImages(startImageIndex, startLogicalImageUnit, 1, mImagesCS, &mUsedComputeImageRange);
2673 }
2674}
2675
Brandon Jonesc9610c52014-08-25 17:02:59 -07002676void ProgramD3D::reset()
2677{
Xinghua Caob1239382016-12-13 15:07:05 +08002678 mVertexExecutables.clear();
2679 mPixelExecutables.clear();
Xinghua Caof3179a62018-07-12 16:22:06 +08002680 mComputeExecutables.clear();
Jamie Madill4e31ad52015-10-29 10:32:57 -04002681
Xinghua Caob1239382016-12-13 15:07:05 +08002682 for (auto &geometryExecutable : mGeometryExecutables)
Jamie Madill4e31ad52015-10-29 10:32:57 -04002683 {
Xinghua Caob1239382016-12-13 15:07:05 +08002684 geometryExecutable.reset(nullptr);
Jamie Madill4e31ad52015-10-29 10:32:57 -04002685 }
Brandon Joneseb994362014-09-24 10:27:28 -07002686
Jiawei Shao467c15f2018-04-24 15:04:26 +08002687 for (gl::ShaderType shaderType : gl::AllShaderTypes())
2688 {
2689 mShaderHLSL[shaderType].clear();
2690 mShaderWorkarounds[shaderType] = CompilerWorkaroundsD3D();
2691 }
Brandon Jones22502d52014-08-29 16:58:36 -07002692
Xinghua Cao26143fd2017-11-01 18:19:05 +08002693 mUsesFragDepth = false;
Martin Radev41ac68e2017-06-06 12:16:58 +03002694 mHasANGLEMultiviewEnabled = false;
2695 mUsesViewID = false;
Brandon Jones22502d52014-08-29 16:58:36 -07002696 mPixelShaderKey.clear();
Xinghua Cao26143fd2017-11-01 18:19:05 +08002697 mUsesPointSize = false;
Jamie Madill3e14e2b2015-10-29 14:38:53 -04002698 mUsesFlatInterpolation = false;
Brandon Jones22502d52014-08-29 16:58:36 -07002699
Jamie Madill62d31cb2015-09-11 13:25:51 -04002700 SafeDeleteContainer(mD3DUniforms);
Jamie Madill4a3c2342015-10-08 12:58:45 -04002701 mD3DUniformBlocks.clear();
Qin Jiajiaa602f902018-09-11 14:40:24 +08002702 mD3DShaderStorageBlocks.clear();
Jamie Madill62d31cb2015-09-11 13:25:51 -04002703
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002704 for (gl::ShaderType shaderType : gl::AllShaderTypes())
2705 {
2706 mShaderUniformStorages[shaderType].reset();
Jiawei Shao467c15f2018-04-24 15:04:26 +08002707 mShaderSamplers[shaderType].clear();
Jiawei Shaoaf2b33b2018-04-19 10:01:52 +08002708 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002709
Xinghua Cao26143fd2017-11-01 18:19:05 +08002710 mImagesCS.clear();
2711 mReadonlyImagesCS.clear();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07002712
Xinghua Cao6dfdca82018-08-03 17:10:55 +08002713 mUsedShaderSamplerRanges.fill({0, 0});
Xinghua Cao26143fd2017-11-01 18:19:05 +08002714 mDirtySamplerMapping = true;
Xinghua Cao6dfdca82018-08-03 17:10:55 +08002715 mUsedComputeImageRange = {0, 0};
2716 mUsedComputeReadonlyImageRange = {0, 0};
Jamie Madill437d2662014-12-05 14:23:35 -05002717
Jamie Madill8047c0d2016-03-07 13:02:12 -05002718 mAttribLocationToD3DSemantic.fill(-1);
Jamie Madillccdf74b2015-08-18 10:46:12 -04002719
Jamie Madill9fc36822015-11-18 13:08:07 -05002720 mStreamOutVaryings.clear();
Jamie Madill4e31ad52015-10-29 10:32:57 -04002721
2722 mGeometryShaderPreamble.clear();
Jamie Madill561ed3a2017-08-31 16:48:09 -04002723
Jiawei Shao3dd8d2912018-03-30 09:39:09 +08002724 markUniformsClean();
Jamie Madill0e7f1732017-09-09 23:32:50 -04002725
2726 mCachedPixelExecutableIndex.reset();
2727 mCachedVertexExecutableIndex.reset();
Brandon Jonesc9610c52014-08-25 17:02:59 -07002728}
2729
Geoff Lang7dd2e102014-11-10 15:19:26 -05002730unsigned int ProgramD3D::getSerial() const
2731{
2732 return mSerial;
2733}
2734
2735unsigned int ProgramD3D::issueSerial()
2736{
2737 return mCurrentSerial++;
2738}
2739
jchen103fd614d2018-08-13 12:21:58 +08002740void ProgramD3D::initAttribLocationsToD3DSemantic()
Jamie Madill63805b42015-08-25 13:17:39 -04002741{
Jiawei Shao385b3e02018-03-21 09:43:28 +08002742 gl::Shader *vertexShader = mState.getAttachedShader(gl::ShaderType::Vertex);
Jamie Madill63805b42015-08-25 13:17:39 -04002743 ASSERT(vertexShader != nullptr);
2744
2745 // Init semantic index
Jamie Madill34ca4f52017-06-13 11:49:39 -04002746 int semanticIndex = 0;
jchen103fd614d2018-08-13 12:21:58 +08002747 for (const sh::Attribute &attribute : vertexShader->getActiveAttributes())
Jamie Madill63805b42015-08-25 13:17:39 -04002748 {
Jamie Madill8047c0d2016-03-07 13:02:12 -05002749 int regCount = gl::VariableRegisterCount(attribute.type);
Jamie Madill34ca4f52017-06-13 11:49:39 -04002750 GLuint location = mState.getAttributeLocation(attribute.name);
2751 ASSERT(location != std::numeric_limits<GLuint>::max());
Jamie Madill63805b42015-08-25 13:17:39 -04002752
Jamie Madill8047c0d2016-03-07 13:02:12 -05002753 for (int reg = 0; reg < regCount; ++reg)
Jamie Madill63805b42015-08-25 13:17:39 -04002754 {
Jamie Madill34ca4f52017-06-13 11:49:39 -04002755 mAttribLocationToD3DSemantic[location + reg] = semanticIndex++;
Jamie Madill63805b42015-08-25 13:17:39 -04002756 }
2757 }
Jamie Madill437d2662014-12-05 14:23:35 -05002758}
2759
Jamie Madilla779b612017-07-24 11:46:05 -04002760void ProgramD3D::updateCachedInputLayout(Serial associatedSerial, const gl::State &state)
Jamie Madilld3dfda22015-07-06 08:28:49 -04002761{
Jamie Madilla779b612017-07-24 11:46:05 -04002762 if (mCurrentVertexArrayStateSerial == associatedSerial)
2763 {
2764 return;
2765 }
2766
2767 mCurrentVertexArrayStateSerial = associatedSerial;
Jamie Madillbd136f92015-08-10 14:51:37 -04002768 mCachedInputLayout.clear();
Jamie Madill0e7f1732017-09-09 23:32:50 -04002769
Jamie Madilld3dfda22015-07-06 08:28:49 -04002770 const auto &vertexAttributes = state.getVertexArray()->getVertexAttributes();
Jamie Madillf8dd7b12015-08-05 13:50:08 -04002771
Jamie Madill6de51852017-04-12 09:53:01 -04002772 for (size_t locationIndex : mState.getActiveAttribLocationsMask())
Jamie Madilld3dfda22015-07-06 08:28:49 -04002773 {
Jamie Madill8047c0d2016-03-07 13:02:12 -05002774 int d3dSemantic = mAttribLocationToD3DSemantic[locationIndex];
Jamie Madilld3dfda22015-07-06 08:28:49 -04002775
Jamie Madill8047c0d2016-03-07 13:02:12 -05002776 if (d3dSemantic != -1)
Jamie Madilld3dfda22015-07-06 08:28:49 -04002777 {
Jamie Madill8047c0d2016-03-07 13:02:12 -05002778 if (mCachedInputLayout.size() < static_cast<size_t>(d3dSemantic + 1))
Jamie Madillbd136f92015-08-10 14:51:37 -04002779 {
Frank Henigmand633b152018-10-04 23:34:31 -04002780 mCachedInputLayout.resize(d3dSemantic + 1, angle::FormatID::NONE);
Jamie Madillbd136f92015-08-10 14:51:37 -04002781 }
Jamie Madill8047c0d2016-03-07 13:02:12 -05002782 mCachedInputLayout[d3dSemantic] =
Frank Henigmand633b152018-10-04 23:34:31 -04002783 GetVertexFormatID(vertexAttributes[locationIndex],
2784 state.getVertexAttribCurrentValue(locationIndex).Type);
Jamie Madilld3dfda22015-07-06 08:28:49 -04002785 }
2786 }
Jamie Madill4c19a8a2017-07-24 11:46:06 -04002787
2788 VertexExecutable::getSignature(mRenderer, mCachedInputLayout, &mCachedVertexSignature);
Jamie Madill0e7f1732017-09-09 23:32:50 -04002789
2790 updateCachedVertexExecutableIndex();
Jamie Madill4c19a8a2017-07-24 11:46:06 -04002791}
2792
2793void ProgramD3D::updateCachedOutputLayout(const gl::Context *context,
2794 const gl::Framebuffer *framebuffer)
2795{
Jamie Madill0e7f1732017-09-09 23:32:50 -04002796 mPixelShaderOutputLayoutCache.clear();
2797
2798 FramebufferD3D *fboD3D = GetImplAs<FramebufferD3D>(framebuffer);
2799 const auto &colorbuffers = fboD3D->getColorAttachmentsForRender(context);
2800
2801 for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment)
2802 {
2803 const gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment];
2804
2805 if (colorbuffer)
2806 {
2807 auto binding = colorbuffer->getBinding() == GL_BACK ? GL_COLOR_ATTACHMENT0
2808 : colorbuffer->getBinding();
2809 mPixelShaderOutputLayoutCache.push_back(binding);
2810 }
2811 else
2812 {
2813 mPixelShaderOutputLayoutCache.push_back(GL_NONE);
2814 }
2815 }
2816
2817 updateCachedPixelExecutableIndex();
Jamie Madilld3dfda22015-07-06 08:28:49 -04002818}
2819
Xinghua Caof3179a62018-07-12 16:22:06 +08002820void ProgramD3D::updateCachedComputeImage2DBindLayout(const gl::Context *context)
2821{
2822 const auto &glState = context->getState();
2823 for (auto &image2DBindLayout : mComputeShaderImage2DBindLayoutCache)
2824 {
2825 const gl::ImageUnit &imageUnit = glState.getImageUnit(image2DBindLayout.first);
2826 if (imageUnit.texture.get())
2827 {
2828 image2DBindLayout.second = imageUnit.texture->getType();
2829 }
2830 else
2831 {
2832 image2DBindLayout.second = gl::TextureType::_2D;
2833 }
2834 }
2835
2836 updateCachedComputeExecutableIndex();
2837}
2838
Jamie Madill192745a2016-12-22 15:58:21 -05002839void ProgramD3D::gatherTransformFeedbackVaryings(const gl::VaryingPacking &varyingPacking,
2840 const BuiltinInfo &builtins)
Jamie Madillccdf74b2015-08-18 10:46:12 -04002841{
Jamie Madill9fc36822015-11-18 13:08:07 -05002842 const std::string &varyingSemantic =
2843 GetVaryingSemantic(mRenderer->getMajorShaderModel(), usesPointSize());
2844
Jamie Madillccdf74b2015-08-18 10:46:12 -04002845 // Gather the linked varyings that are used for transform feedback, they should all exist.
Jamie Madill9fc36822015-11-18 13:08:07 -05002846 mStreamOutVaryings.clear();
2847
Jamie Madill48ef11b2016-04-27 15:21:52 -04002848 const auto &tfVaryingNames = mState.getTransformFeedbackVaryingNames();
Jamie Madill9fc36822015-11-18 13:08:07 -05002849 for (unsigned int outputSlot = 0; outputSlot < static_cast<unsigned int>(tfVaryingNames.size());
2850 ++outputSlot)
Jamie Madillccdf74b2015-08-18 10:46:12 -04002851 {
Jamie Madill9fc36822015-11-18 13:08:07 -05002852 const auto &tfVaryingName = tfVaryingNames[outputSlot];
2853 if (tfVaryingName == "gl_Position")
Jamie Madillccdf74b2015-08-18 10:46:12 -04002854 {
Jamie Madill9fc36822015-11-18 13:08:07 -05002855 if (builtins.glPosition.enabled)
Jamie Madillccdf74b2015-08-18 10:46:12 -04002856 {
Jiawei Shaoda92a472018-07-02 15:55:19 +08002857 mStreamOutVaryings.emplace_back(builtins.glPosition.semantic,
2858 builtins.glPosition.index, 4, outputSlot);
Jamie Madill9fc36822015-11-18 13:08:07 -05002859 }
2860 }
2861 else if (tfVaryingName == "gl_FragCoord")
2862 {
2863 if (builtins.glFragCoord.enabled)
2864 {
Jiawei Shaoda92a472018-07-02 15:55:19 +08002865 mStreamOutVaryings.emplace_back(builtins.glFragCoord.semantic,
2866 builtins.glFragCoord.index, 4, outputSlot);
Jamie Madill9fc36822015-11-18 13:08:07 -05002867 }
2868 }
2869 else if (tfVaryingName == "gl_PointSize")
2870 {
2871 if (builtins.glPointSize.enabled)
2872 {
Jiawei Shaoda92a472018-07-02 15:55:19 +08002873 mStreamOutVaryings.emplace_back("PSIZE", 0, 1, outputSlot);
Jamie Madill9fc36822015-11-18 13:08:07 -05002874 }
2875 }
2876 else
2877 {
Jiawei Shaoda92a472018-07-02 15:55:19 +08002878 const auto &registerInfos = varyingPacking.getRegisterList();
2879 for (GLuint registerIndex = 0u; registerIndex < registerInfos.size(); ++registerIndex)
Jamie Madill9fc36822015-11-18 13:08:07 -05002880 {
Jiawei Shaoda92a472018-07-02 15:55:19 +08002881 const auto &registerInfo = registerInfos[registerIndex];
Xinghua Cao6dfdca82018-08-03 17:10:55 +08002882 const auto &varying = *registerInfo.packedVarying->varying;
2883 GLenum transposedType = gl::TransposeMatrixType(varying.type);
2884 int componentCount = gl::VariableColumnCount(transposedType);
jchen108225e732017-11-14 16:29:03 +08002885 ASSERT(!varying.isBuiltIn() && !varying.isStruct());
Jamie Madill55c25d02015-11-18 13:08:08 -05002886
Jamie Madill9fc36822015-11-18 13:08:07 -05002887 // There can be more than one register assigned to a particular varying, and each
2888 // register needs its own stream out entry.
jchen108225e732017-11-14 16:29:03 +08002889 if (registerInfo.tfVaryingName() == tfVaryingName)
Jamie Madill9fc36822015-11-18 13:08:07 -05002890 {
Jiawei Shaoda92a472018-07-02 15:55:19 +08002891 mStreamOutVaryings.emplace_back(varyingSemantic, registerIndex, componentCount,
2892 outputSlot);
Jamie Madill9fc36822015-11-18 13:08:07 -05002893 }
Jamie Madillccdf74b2015-08-18 10:46:12 -04002894 }
2895 }
2896 }
2897}
Jamie Madill62d31cb2015-09-11 13:25:51 -04002898
2899D3DUniform *ProgramD3D::getD3DUniformFromLocation(GLint location)
2900{
Jamie Madill48ef11b2016-04-27 15:21:52 -04002901 return mD3DUniforms[mState.getUniformLocations()[location].index];
Jamie Madill62d31cb2015-09-11 13:25:51 -04002902}
Jamie Madill4a3c2342015-10-08 12:58:45 -04002903
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002904const D3DUniform *ProgramD3D::getD3DUniformFromLocation(GLint location) const
2905{
2906 return mD3DUniforms[mState.getUniformLocations()[location].index];
2907}
2908
Sami Väisänen46eaa942016-06-29 10:26:37 +03002909void ProgramD3D::setPathFragmentInputGen(const std::string &inputName,
2910 GLenum genMode,
2911 GLint components,
2912 const GLfloat *coeffs)
2913{
2914 UNREACHABLE();
2915}
2916
Jamie Madill4c19a8a2017-07-24 11:46:06 -04002917bool ProgramD3D::hasVertexExecutableForCachedInputLayout()
2918{
Jamie Madill0e7f1732017-09-09 23:32:50 -04002919 return mCachedVertexExecutableIndex.valid();
Jamie Madill4c19a8a2017-07-24 11:46:06 -04002920}
2921
Jeff Gilbert465d6092019-01-02 16:21:18 -08002922bool ProgramD3D::hasGeometryExecutableForPrimitiveType(const gl::State &state,
2923 gl::PrimitiveMode drawMode)
Jamie Madill4c19a8a2017-07-24 11:46:06 -04002924{
Jeff Gilbert465d6092019-01-02 16:21:18 -08002925 if (!usesGeometryShader(state, drawMode))
Jamie Madill4c19a8a2017-07-24 11:46:06 -04002926 {
2927 // No shader necessary mean we have the required (null) executable.
2928 return true;
2929 }
2930
Jamie Madill04796cd2018-05-24 19:52:16 -04002931 gl::PrimitiveMode geometryShaderType = GetGeometryShaderTypeFromDrawMode(drawMode);
Jamie Madill4c19a8a2017-07-24 11:46:06 -04002932 return mGeometryExecutables[geometryShaderType].get() != nullptr;
2933}
2934
2935bool ProgramD3D::hasPixelExecutableForCachedOutputLayout()
2936{
Jamie Madill0e7f1732017-09-09 23:32:50 -04002937 return mCachedPixelExecutableIndex.valid();
Jamie Madill4c19a8a2017-07-24 11:46:06 -04002938}
2939
Xinghua Caof3179a62018-07-12 16:22:06 +08002940bool ProgramD3D::hasComputeExecutableForCachedImage2DBindLayout()
2941{
2942 return mCachedComputeExecutableIndex.valid();
2943}
2944
Jamie Madill54164b02017-08-28 15:17:37 -04002945template <typename DestT>
2946void ProgramD3D::getUniformInternal(GLint location, DestT *dataOut) const
2947{
2948 const gl::VariableLocation &locationInfo = mState.getUniformLocations()[location];
2949 const gl::LinkedUniform &uniform = mState.getUniforms()[locationInfo.index];
2950
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002951 const D3DUniform *targetUniform = getD3DUniformFromLocation(location);
Olli Etuaho1734e172017-10-27 15:30:27 +03002952 const uint8_t *srcPointer = targetUniform->getDataPtrToElement(locationInfo.arrayIndex);
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002953
2954 if (gl::IsMatrixType(uniform.type))
2955 {
Luc Ferron48cdc2e2018-05-31 09:58:34 -04002956 GetMatrixUniform(uniform.type, dataOut, reinterpret_cast<const DestT *>(srcPointer), true);
Jamie Madillbe5e2ec2017-08-31 13:28:28 -04002957 }
2958 else
2959 {
2960 memcpy(dataOut, srcPointer, uniform.getElementSize());
2961 }
Jamie Madill54164b02017-08-28 15:17:37 -04002962}
2963
2964void ProgramD3D::getUniformfv(const gl::Context *context, GLint location, GLfloat *params) const
2965{
2966 getUniformInternal(location, params);
2967}
2968
2969void ProgramD3D::getUniformiv(const gl::Context *context, GLint location, GLint *params) const
2970{
2971 getUniformInternal(location, params);
2972}
2973
2974void ProgramD3D::getUniformuiv(const gl::Context *context, GLint location, GLuint *params) const
2975{
2976 getUniformInternal(location, params);
2977}
2978
Jamie Madill0e7f1732017-09-09 23:32:50 -04002979void ProgramD3D::updateCachedVertexExecutableIndex()
2980{
2981 mCachedVertexExecutableIndex.reset();
2982 for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++)
2983 {
2984 if (mVertexExecutables[executableIndex]->matchesSignature(mCachedVertexSignature))
2985 {
2986 mCachedVertexExecutableIndex = executableIndex;
2987 break;
2988 }
2989 }
2990}
2991
2992void ProgramD3D::updateCachedPixelExecutableIndex()
2993{
2994 mCachedPixelExecutableIndex.reset();
2995 for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++)
2996 {
2997 if (mPixelExecutables[executableIndex]->matchesSignature(mPixelShaderOutputLayoutCache))
2998 {
2999 mCachedPixelExecutableIndex = executableIndex;
3000 break;
3001 }
3002 }
3003}
3004
Xinghua Caof3179a62018-07-12 16:22:06 +08003005void ProgramD3D::updateCachedComputeExecutableIndex()
3006{
3007 mCachedComputeExecutableIndex.reset();
3008 for (size_t executableIndex = 0; executableIndex < mComputeExecutables.size();
3009 executableIndex++)
3010 {
3011 if (mComputeExecutables[executableIndex]->matchesSignature(
3012 mComputeShaderImage2DBindLayoutCache))
3013 {
3014 mCachedComputeExecutableIndex = executableIndex;
3015 break;
3016 }
3017 }
3018}
3019
jchen103fd614d2018-08-13 12:21:58 +08003020void ProgramD3D::linkResources(const gl::ProgramLinkedResources &resources)
Jamie Madill6db1c2e2017-11-08 09:17:40 -05003021{
Qin Jiajia3026f112018-10-09 12:13:38 +08003022 InterfaceBlockInfo uniformBlockInfo;
Jiawei Shao385b3e02018-03-21 09:43:28 +08003023 for (gl::ShaderType shaderType : gl::AllShaderTypes())
Jamie Madill6db1c2e2017-11-08 09:17:40 -05003024 {
Jiawei Shao385b3e02018-03-21 09:43:28 +08003025 gl::Shader *shader = mState.getAttachedShader(shaderType);
3026 if (shader)
3027 {
Qin Jiajia3026f112018-10-09 12:13:38 +08003028 uniformBlockInfo.getShaderBlockInfo(shader->getUniformBlocks());
Jiawei Shao385b3e02018-03-21 09:43:28 +08003029 }
Jamie Madill6db1c2e2017-11-08 09:17:40 -05003030 }
3031
3032 // Gather interface block info.
3033 auto getUniformBlockSize = [&uniformBlockInfo](const std::string &name,
3034 const std::string &mappedName, size_t *sizeOut) {
3035 return uniformBlockInfo.getBlockSize(name, mappedName, sizeOut);
3036 };
3037
3038 auto getUniformBlockMemberInfo = [&uniformBlockInfo](const std::string &name,
3039 const std::string &mappedName,
3040 sh::BlockMemberInfo *infoOut) {
3041 return uniformBlockInfo.getBlockMemberInfo(name, mappedName, infoOut);
3042 };
3043
3044 resources.uniformBlockLinker.linkBlocks(getUniformBlockSize, getUniformBlockMemberInfo);
3045 initializeUniformBlocks();
3046
Qin Jiajia3026f112018-10-09 12:13:38 +08003047 InterfaceBlockInfo shaderStorageBlockInfo;
3048 for (gl::ShaderType shaderType : gl::AllShaderTypes())
3049 {
3050 gl::Shader *shader = mState.getAttachedShader(shaderType);
3051 if (shader)
3052 {
3053 shaderStorageBlockInfo.getShaderBlockInfo(shader->getShaderStorageBlocks());
3054 }
3055 }
3056 auto getShaderStorageBlockSize = [&shaderStorageBlockInfo](const std::string &name,
3057 const std::string &mappedName,
3058 size_t *sizeOut) {
3059 return shaderStorageBlockInfo.getBlockSize(name, mappedName, sizeOut);
Jamie Madill6db1c2e2017-11-08 09:17:40 -05003060 };
3061
Qin Jiajia3026f112018-10-09 12:13:38 +08003062 auto getShaderStorageBlockMemberInfo = [&shaderStorageBlockInfo](const std::string &name,
3063 const std::string &mappedName,
3064 sh::BlockMemberInfo *infoOut) {
3065 return shaderStorageBlockInfo.getBlockMemberInfo(name, mappedName, infoOut);
3066 };
Jamie Madill6db1c2e2017-11-08 09:17:40 -05003067
3068 resources.shaderStorageBlockLinker.linkBlocks(getShaderStorageBlockSize,
3069 getShaderStorageBlockMemberInfo);
Qin Jiajiaa602f902018-09-11 14:40:24 +08003070 initializeShaderStorageBlocks();
Enrico Gallia3b2e712018-12-08 16:46:48 -08003071
3072 std::map<int, unsigned int> sizeMap;
3073 getAtomicCounterBufferSizeMap(sizeMap);
3074 resources.atomicCounterBufferLinker.link(sizeMap);
3075}
3076
3077void ProgramD3D::getAtomicCounterBufferSizeMap(std::map<int, unsigned int> &sizeMapOut) const
3078{
3079 for (unsigned int index : mState.getAtomicCounterUniformRange())
3080 {
3081 const gl::LinkedUniform &glUniform = mState.getUniforms()[index];
3082
3083 auto &bufferDataSize = sizeMapOut[glUniform.binding];
3084
3085 // Calculate the size of the buffer by finding the end of the last uniform with the same
3086 // binding. The end of the uniform is calculated by finding the initial offset of the
3087 // uniform and adding size of the uniform. For arrays, the size is the number of elements
3088 // times the element size (should always by 4 for atomic_units).
3089 unsigned dataOffset =
3090 glUniform.offset + (glUniform.getBasicTypeElementCount() * glUniform.getElementSize());
3091 if (dataOffset > bufferDataSize)
3092 {
3093 bufferDataSize = dataOffset;
3094 }
3095 }
Jamie Madill6db1c2e2017-11-08 09:17:40 -05003096}
3097
Jamie Madill8047c0d2016-03-07 13:02:12 -05003098} // namespace rx