blob: 0a182ae9543802ce001812c4026aace656cf8453 [file] [log] [blame]
Brandon Jonesc9610c52014-08-25 17:02:59 -07001//
2// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// ProgramD3D.cpp: Defines the rx::ProgramD3D class which implements rx::ProgramImpl.
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/renderer/d3d/ProgramD3D.h"
Jamie Madill437d2662014-12-05 14:23:35 -050010
Dian Xianga4928832015-09-15 10:11:17 -070011#include "common/BitSetIterator.h"
Jamie Madill437d2662014-12-05 14:23:35 -050012#include "common/utilities.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050013#include "libANGLE/Framebuffer.h"
14#include "libANGLE/FramebufferAttachment.h"
15#include "libANGLE/Program.h"
Jamie Madilld3dfda22015-07-06 08:28:49 -040016#include "libANGLE/VertexArray.h"
Jamie Madill6df9b372015-02-18 21:28:19 +000017#include "libANGLE/features.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050018#include "libANGLE/renderer/d3d/DynamicHLSL.h"
Jamie Madill85a18042015-03-05 15:41:41 -050019#include "libANGLE/renderer/d3d/FramebufferD3D.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050020#include "libANGLE/renderer/d3d/RendererD3D.h"
21#include "libANGLE/renderer/d3d/ShaderD3D.h"
Geoff Lang359ef262015-01-05 14:42:29 -050022#include "libANGLE/renderer/d3d/ShaderExecutableD3D.h"
Jamie Madill437d2662014-12-05 14:23:35 -050023#include "libANGLE/renderer/d3d/VertexDataManager.h"
Geoff Lang22072132014-11-20 15:15:01 -050024
Brandon Jonesc9610c52014-08-25 17:02:59 -070025namespace rx
26{
27
Brandon Joneseb994362014-09-24 10:27:28 -070028namespace
29{
30
Jamie Madillf8dd7b12015-08-05 13:50:08 -040031gl::InputLayout GetDefaultInputLayoutFromShader(const gl::Shader *vertexShader)
Brandon Joneseb994362014-09-24 10:27:28 -070032{
Jamie Madillbd136f92015-08-10 14:51:37 -040033 gl::InputLayout defaultLayout;
34 for (const sh::Attribute &shaderAttr : vertexShader->getActiveAttributes())
Brandon Joneseb994362014-09-24 10:27:28 -070035 {
Brandon Joneseb994362014-09-24 10:27:28 -070036 if (shaderAttr.type != GL_NONE)
37 {
38 GLenum transposedType = gl::TransposeMatrixType(shaderAttr.type);
39
Jamie Madilld3dfda22015-07-06 08:28:49 -040040 for (size_t rowIndex = 0;
41 static_cast<int>(rowIndex) < gl::VariableRowCount(transposedType);
42 ++rowIndex)
Brandon Joneseb994362014-09-24 10:27:28 -070043 {
Jamie Madilld3dfda22015-07-06 08:28:49 -040044 GLenum componentType = gl::VariableComponentType(transposedType);
45 GLuint components = static_cast<GLuint>(gl::VariableColumnCount(transposedType));
46 bool pureInt = (componentType != GL_FLOAT);
47 gl::VertexFormatType defaultType = gl::GetVertexFormatType(
48 componentType, GL_FALSE, components, pureInt);
Brandon Joneseb994362014-09-24 10:27:28 -070049
Jamie Madillbd136f92015-08-10 14:51:37 -040050 defaultLayout.push_back(defaultType);
Brandon Joneseb994362014-09-24 10:27:28 -070051 }
52 }
53 }
Jamie Madillf8dd7b12015-08-05 13:50:08 -040054
55 return defaultLayout;
Brandon Joneseb994362014-09-24 10:27:28 -070056}
57
58std::vector<GLenum> GetDefaultOutputLayoutFromShader(const std::vector<PixelShaderOutputVariable> &shaderOutputVars)
59{
Jamie Madillb4463142014-12-19 14:56:54 -050060 std::vector<GLenum> defaultPixelOutput;
Brandon Joneseb994362014-09-24 10:27:28 -070061
Jamie Madillb4463142014-12-19 14:56:54 -050062 if (!shaderOutputVars.empty())
63 {
Cooper Partin4d61f7e2015-08-12 10:56:50 -070064 defaultPixelOutput.push_back(GL_COLOR_ATTACHMENT0 +
65 static_cast<unsigned int>(shaderOutputVars[0].outputIndex));
Jamie Madillb4463142014-12-19 14:56:54 -050066 }
Brandon Joneseb994362014-09-24 10:27:28 -070067
68 return defaultPixelOutput;
69}
70
Brandon Jones1a8a7e32014-10-01 12:49:30 -070071bool IsRowMajorLayout(const sh::InterfaceBlockField &var)
72{
73 return var.isRowMajorLayout;
74}
75
76bool IsRowMajorLayout(const sh::ShaderVariable &var)
77{
78 return false;
79}
80
Jamie Madill437d2662014-12-05 14:23:35 -050081struct AttributeSorter
82{
Jamie Madill63805b42015-08-25 13:17:39 -040083 AttributeSorter(const ProgramD3D::SemanticIndexArray &semanticIndices)
Jamie Madill80d934b2015-02-19 10:16:12 -050084 : originalIndices(&semanticIndices)
Jamie Madill437d2662014-12-05 14:23:35 -050085 {
86 }
87
88 bool operator()(int a, int b)
89 {
Jamie Madill80d934b2015-02-19 10:16:12 -050090 int indexA = (*originalIndices)[a];
91 int indexB = (*originalIndices)[b];
92
93 if (indexA == -1) return false;
94 if (indexB == -1) return true;
95 return (indexA < indexB);
Jamie Madill437d2662014-12-05 14:23:35 -050096 }
97
Jamie Madill63805b42015-08-25 13:17:39 -040098 const ProgramD3D::SemanticIndexArray *originalIndices;
Jamie Madill437d2662014-12-05 14:23:35 -050099};
100
Jamie Madillca03b352015-09-02 12:38:13 -0400101std::vector<PackedVarying> MergeVaryings(const gl::Shader &vertexShader,
102 const gl::Shader &fragmentShader,
103 const std::vector<std::string> &tfVaryings)
Jamie Madillada9ecc2015-08-17 12:53:37 -0400104{
Jamie Madillca03b352015-09-02 12:38:13 -0400105 std::vector<PackedVarying> packedVaryings;
106
107 for (const sh::Varying &output : vertexShader.getVaryings())
Jamie Madillada9ecc2015-08-17 12:53:37 -0400108 {
Jamie Madillca03b352015-09-02 12:38:13 -0400109 bool packed = false;
Jamie Madillada9ecc2015-08-17 12:53:37 -0400110
111 // Built-in varyings obey special rules
Jamie Madillca03b352015-09-02 12:38:13 -0400112 if (output.isBuiltIn())
Jamie Madillada9ecc2015-08-17 12:53:37 -0400113 {
114 continue;
115 }
116
Jamie Madillca03b352015-09-02 12:38:13 -0400117 for (const sh::Varying &input : fragmentShader.getVaryings())
Jamie Madillada9ecc2015-08-17 12:53:37 -0400118 {
Jamie Madillca03b352015-09-02 12:38:13 -0400119 if (output.name == input.name)
Jamie Madillada9ecc2015-08-17 12:53:37 -0400120 {
Jamie Madillca03b352015-09-02 12:38:13 -0400121 packedVaryings.push_back(PackedVarying(input));
122 packed = true;
Jamie Madillada9ecc2015-08-17 12:53:37 -0400123 break;
124 }
125 }
126
Jamie Madillca03b352015-09-02 12:38:13 -0400127 // Keep Transform FB varyings in the merged list always.
128 if (!packed)
129 {
130 for (const std::string &tfVarying : tfVaryings)
131 {
132 if (tfVarying == output.name)
133 {
134 packedVaryings.push_back(PackedVarying(output));
135 packedVaryings.back().vertexOnly = true;
136 break;
137 }
138 }
139 }
Jamie Madillada9ecc2015-08-17 12:53:37 -0400140 }
141
Jamie Madillca03b352015-09-02 12:38:13 -0400142 return packedVaryings;
Brandon Joneseb994362014-09-24 10:27:28 -0700143}
144
Jamie Madill62d31cb2015-09-11 13:25:51 -0400145template <typename VarT>
146void GetUniformBlockInfo(const std::vector<VarT> &fields,
147 const std::string &prefix,
148 sh::BlockLayoutEncoder *encoder,
149 bool inRowMajorLayout,
150 std::map<std::string, sh::BlockMemberInfo> *blockInfoOut)
151{
152 for (const VarT &field : fields)
153 {
154 const std::string &fieldName = (prefix.empty() ? field.name : prefix + "." + field.name);
155
156 if (field.isStruct())
157 {
158 bool rowMajorLayout = (inRowMajorLayout || IsRowMajorLayout(field));
159
160 for (unsigned int arrayElement = 0; arrayElement < field.elementCount(); arrayElement++)
161 {
162 encoder->enterAggregateType();
163
164 const std::string uniformElementName =
165 fieldName + (field.isArray() ? ArrayString(arrayElement) : "");
166 GetUniformBlockInfo(field.fields, uniformElementName, encoder, rowMajorLayout,
167 blockInfoOut);
168
169 encoder->exitAggregateType();
170 }
171 }
172 else
173 {
174 bool isRowMajorMatrix = (gl::IsMatrixType(field.type) && inRowMajorLayout);
175 (*blockInfoOut)[fieldName] =
176 encoder->encodeType(field.type, field.arraySize, isRowMajorMatrix);
177 }
178 }
179}
180
Jamie Madillada9ecc2015-08-17 12:53:37 -0400181} // anonymous namespace
182
Jamie Madill62d31cb2015-09-11 13:25:51 -0400183D3DUniform::D3DUniform(GLenum typeIn,
184 const std::string &nameIn,
185 unsigned int arraySizeIn,
186 bool defaultBlock)
187 : type(typeIn),
188 name(nameIn),
189 arraySize(arraySizeIn),
190 data(nullptr),
191 dirty(true),
Jamie Madill62d31cb2015-09-11 13:25:51 -0400192 vsRegisterIndex(GL_INVALID_INDEX),
Geoff Lang98c56da2015-09-15 15:45:34 -0400193 psRegisterIndex(GL_INVALID_INDEX),
Jamie Madill62d31cb2015-09-11 13:25:51 -0400194 registerCount(0),
195 registerElement(0)
196{
197 // We use data storage for default block uniforms to cache values that are sent to D3D during
198 // rendering
199 // Uniform blocks/buffers are treated separately by the Renderer (ES3 path only)
200 if (defaultBlock)
201 {
202 size_t bytes = gl::VariableInternalSize(type) * elementCount();
203 data = new uint8_t[bytes];
204 memset(data, 0, bytes);
205
206 // TODO(jmadill): is this correct with non-square matrices?
207 registerCount = gl::VariableRowCount(type) * elementCount();
208 }
209}
210
211D3DUniform::~D3DUniform()
212{
213 SafeDeleteArray(data);
214}
215
216bool D3DUniform::isSampler() const
217{
218 return gl::IsSamplerType(type);
219}
220
221bool D3DUniform::isReferencedByVertexShader() const
222{
223 return vsRegisterIndex != GL_INVALID_INDEX;
224}
225
226bool D3DUniform::isReferencedByFragmentShader() const
227{
228 return psRegisterIndex != GL_INVALID_INDEX;
229}
230
Jamie Madilld3dfda22015-07-06 08:28:49 -0400231ProgramD3D::VertexExecutable::VertexExecutable(const gl::InputLayout &inputLayout,
232 const Signature &signature,
Geoff Lang359ef262015-01-05 14:42:29 -0500233 ShaderExecutableD3D *shaderExecutable)
Jamie Madilld3dfda22015-07-06 08:28:49 -0400234 : mInputs(inputLayout),
235 mSignature(signature),
236 mShaderExecutable(shaderExecutable)
Brandon Joneseb994362014-09-24 10:27:28 -0700237{
Brandon Joneseb994362014-09-24 10:27:28 -0700238}
239
240ProgramD3D::VertexExecutable::~VertexExecutable()
241{
242 SafeDelete(mShaderExecutable);
243}
244
Jamie Madilld3dfda22015-07-06 08:28:49 -0400245// static
246void ProgramD3D::VertexExecutable::getSignature(RendererD3D *renderer,
247 const gl::InputLayout &inputLayout,
248 Signature *signatureOut)
Brandon Joneseb994362014-09-24 10:27:28 -0700249{
Jamie Madillbd136f92015-08-10 14:51:37 -0400250 signatureOut->resize(inputLayout.size());
Jamie Madilld3dfda22015-07-06 08:28:49 -0400251
252 for (size_t index = 0; index < inputLayout.size(); ++index)
Brandon Joneseb994362014-09-24 10:27:28 -0700253 {
Jamie Madilld3dfda22015-07-06 08:28:49 -0400254 gl::VertexFormatType vertexFormatType = inputLayout[index];
Jamie Madillbd136f92015-08-10 14:51:37 -0400255 bool converted = false;
Jamie Madillf8dd7b12015-08-05 13:50:08 -0400256 if (vertexFormatType != gl::VERTEX_FORMAT_INVALID)
Brandon Joneseb994362014-09-24 10:27:28 -0700257 {
Jamie Madillf8dd7b12015-08-05 13:50:08 -0400258 VertexConversionType conversionType =
259 renderer->getVertexConversionType(vertexFormatType);
Jamie Madillbd136f92015-08-10 14:51:37 -0400260 converted = ((conversionType & VERTEX_CONVERT_GPU) != 0);
Brandon Joneseb994362014-09-24 10:27:28 -0700261 }
Jamie Madillbd136f92015-08-10 14:51:37 -0400262
263 (*signatureOut)[index] = converted;
Brandon Joneseb994362014-09-24 10:27:28 -0700264 }
Brandon Joneseb994362014-09-24 10:27:28 -0700265}
266
Jamie Madilld3dfda22015-07-06 08:28:49 -0400267bool ProgramD3D::VertexExecutable::matchesSignature(const Signature &signature) const
268{
Jamie Madillbd136f92015-08-10 14:51:37 -0400269 size_t limit = std::max(mSignature.size(), signature.size());
270 for (size_t index = 0; index < limit; ++index)
271 {
272 // treat undefined indexes as 'not converted'
273 bool a = index < signature.size() ? signature[index] : false;
274 bool b = index < mSignature.size() ? mSignature[index] : false;
275 if (a != b)
276 return false;
277 }
278
279 return true;
Jamie Madilld3dfda22015-07-06 08:28:49 -0400280}
281
282ProgramD3D::PixelExecutable::PixelExecutable(const std::vector<GLenum> &outputSignature,
283 ShaderExecutableD3D *shaderExecutable)
Brandon Joneseb994362014-09-24 10:27:28 -0700284 : mOutputSignature(outputSignature),
285 mShaderExecutable(shaderExecutable)
286{
287}
288
289ProgramD3D::PixelExecutable::~PixelExecutable()
290{
291 SafeDelete(mShaderExecutable);
292}
293
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700294ProgramD3D::Sampler::Sampler() : active(false), logicalTextureUnit(0), textureType(GL_TEXTURE_2D)
295{
296}
297
Geoff Lang7dd2e102014-11-10 15:19:26 -0500298unsigned int ProgramD3D::mCurrentSerial = 1;
299
Jamie Madill5c6b7bf2015-08-17 12:53:35 -0400300ProgramD3D::ProgramD3D(const gl::Program::Data &data, RendererD3D *renderer)
301 : ProgramImpl(data),
Brandon Jonesc9610c52014-08-25 17:02:59 -0700302 mRenderer(renderer),
303 mDynamicHLSL(NULL),
Brandon Joneseb994362014-09-24 10:27:28 -0700304 mGeometryExecutable(NULL),
Brandon Jones44151a92014-09-10 11:32:25 -0700305 mUsesPointSize(false),
Brandon Jonesc9610c52014-08-25 17:02:59 -0700306 mVertexUniformStorage(NULL),
Brandon Jones44151a92014-09-10 11:32:25 -0700307 mFragmentUniformStorage(NULL),
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700308 mUsedVertexSamplerRange(0),
309 mUsedPixelSamplerRange(0),
310 mDirtySamplerMapping(true),
Geoff Lang7dd2e102014-11-10 15:19:26 -0500311 mSerial(issueSerial())
Brandon Jonesc9610c52014-08-25 17:02:59 -0700312{
Brandon Joneseb994362014-09-24 10:27:28 -0700313 mDynamicHLSL = new DynamicHLSL(renderer);
Brandon Jonesc9610c52014-08-25 17:02:59 -0700314}
315
316ProgramD3D::~ProgramD3D()
317{
318 reset();
319 SafeDelete(mDynamicHLSL);
320}
321
Brandon Jones44151a92014-09-10 11:32:25 -0700322bool ProgramD3D::usesPointSpriteEmulation() const
323{
324 return mUsesPointSize && mRenderer->getMajorShaderModel() >= 4;
325}
326
327bool ProgramD3D::usesGeometryShader() const
328{
Cooper Partine6664f02015-01-09 16:22:24 -0800329 return usesPointSpriteEmulation() && !usesInstancedPointSpriteEmulation();
330}
331
332bool ProgramD3D::usesInstancedPointSpriteEmulation() const
333{
334 return mRenderer->getWorkarounds().useInstancedPointSpriteEmulation;
Brandon Jones44151a92014-09-10 11:32:25 -0700335}
336
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700337GLint ProgramD3D::getSamplerMapping(gl::SamplerType type, unsigned int samplerIndex, const gl::Caps &caps) const
338{
339 GLint logicalTextureUnit = -1;
340
341 switch (type)
342 {
343 case gl::SAMPLER_PIXEL:
344 ASSERT(samplerIndex < caps.maxTextureImageUnits);
345 if (samplerIndex < mSamplersPS.size() && mSamplersPS[samplerIndex].active)
346 {
347 logicalTextureUnit = mSamplersPS[samplerIndex].logicalTextureUnit;
348 }
349 break;
350 case gl::SAMPLER_VERTEX:
351 ASSERT(samplerIndex < caps.maxVertexTextureImageUnits);
352 if (samplerIndex < mSamplersVS.size() && mSamplersVS[samplerIndex].active)
353 {
354 logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit;
355 }
356 break;
357 default: UNREACHABLE();
358 }
359
360 if (logicalTextureUnit >= 0 && logicalTextureUnit < static_cast<GLint>(caps.maxCombinedTextureImageUnits))
361 {
362 return logicalTextureUnit;
363 }
364
365 return -1;
366}
367
368// Returns the texture type for a given Direct3D 9 sampler type and
369// index (0-15 for the pixel shader and 0-3 for the vertex shader).
370GLenum ProgramD3D::getSamplerTextureType(gl::SamplerType type, unsigned int samplerIndex) const
371{
372 switch (type)
373 {
374 case gl::SAMPLER_PIXEL:
375 ASSERT(samplerIndex < mSamplersPS.size());
376 ASSERT(mSamplersPS[samplerIndex].active);
377 return mSamplersPS[samplerIndex].textureType;
378 case gl::SAMPLER_VERTEX:
379 ASSERT(samplerIndex < mSamplersVS.size());
380 ASSERT(mSamplersVS[samplerIndex].active);
381 return mSamplersVS[samplerIndex].textureType;
382 default: UNREACHABLE();
383 }
384
385 return GL_TEXTURE_2D;
386}
387
388GLint ProgramD3D::getUsedSamplerRange(gl::SamplerType type) const
389{
390 switch (type)
391 {
392 case gl::SAMPLER_PIXEL:
393 return mUsedPixelSamplerRange;
394 case gl::SAMPLER_VERTEX:
395 return mUsedVertexSamplerRange;
396 default:
397 UNREACHABLE();
398 return 0;
399 }
400}
401
402void ProgramD3D::updateSamplerMapping()
403{
404 if (!mDirtySamplerMapping)
405 {
406 return;
407 }
408
409 mDirtySamplerMapping = false;
410
411 // Retrieve sampler uniform values
Jamie Madill62d31cb2015-09-11 13:25:51 -0400412 for (const D3DUniform *d3dUniform : mD3DUniforms)
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700413 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400414 if (!d3dUniform->dirty)
415 continue;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700416
Jamie Madill62d31cb2015-09-11 13:25:51 -0400417 if (!d3dUniform->isSampler())
418 continue;
419
420 int count = d3dUniform->elementCount();
421 const GLint(*v)[4] = reinterpret_cast<const GLint(*)[4]>(d3dUniform->data);
422
423 if (d3dUniform->isReferencedByFragmentShader())
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700424 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400425 unsigned int firstIndex = d3dUniform->psRegisterIndex;
426
427 for (int i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700428 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400429 unsigned int samplerIndex = firstIndex + i;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700430
Jamie Madill62d31cb2015-09-11 13:25:51 -0400431 if (samplerIndex < mSamplersPS.size())
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700432 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400433 ASSERT(mSamplersPS[samplerIndex].active);
434 mSamplersPS[samplerIndex].logicalTextureUnit = v[i][0];
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700435 }
Jamie Madill62d31cb2015-09-11 13:25:51 -0400436 }
437 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700438
Jamie Madill62d31cb2015-09-11 13:25:51 -0400439 if (d3dUniform->isReferencedByVertexShader())
440 {
441 unsigned int firstIndex = d3dUniform->vsRegisterIndex;
442
443 for (int i = 0; i < count; i++)
444 {
445 unsigned int samplerIndex = firstIndex + i;
446
447 if (samplerIndex < mSamplersVS.size())
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700448 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400449 ASSERT(mSamplersVS[samplerIndex].active);
450 mSamplersVS[samplerIndex].logicalTextureUnit = v[i][0];
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700451 }
452 }
453 }
454 }
455}
456
Geoff Lang7dd2e102014-11-10 15:19:26 -0500457LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
Brandon Jones22502d52014-08-29 16:58:36 -0700458{
Jamie Madill62d31cb2015-09-11 13:25:51 -0400459 reset();
460
Austin Kinross137b1512015-06-17 16:14:53 -0700461 DeviceIdentifier binaryDeviceIdentifier = { 0 };
462 stream->readBytes(reinterpret_cast<unsigned char*>(&binaryDeviceIdentifier), sizeof(DeviceIdentifier));
463
464 DeviceIdentifier identifier = mRenderer->getAdapterIdentifier();
465 if (memcmp(&identifier, &binaryDeviceIdentifier, sizeof(DeviceIdentifier)) != 0)
466 {
467 infoLog << "Invalid program binary, device configuration has changed.";
468 return LinkResult(false, gl::Error(GL_NO_ERROR));
469 }
470
Jamie Madill2db1fbb2014-12-03 10:58:55 -0500471 int compileFlags = stream->readInt<int>();
472 if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL)
473 {
Jamie Madillf6113162015-05-07 11:49:21 -0400474 infoLog << "Mismatched compilation flags.";
Jamie Madill2db1fbb2014-12-03 10:58:55 -0500475 return LinkResult(false, gl::Error(GL_NO_ERROR));
476 }
477
Jamie Madill63805b42015-08-25 13:17:39 -0400478 // TODO(jmadill): replace MAX_VERTEX_ATTRIBS
479 for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; ++i)
480 {
481 stream->readInt(&mSemanticIndexes[i]);
482 }
483
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700484 const unsigned int psSamplerCount = stream->readInt<unsigned int>();
485 for (unsigned int i = 0; i < psSamplerCount; ++i)
486 {
487 Sampler sampler;
488 stream->readBool(&sampler.active);
489 stream->readInt(&sampler.logicalTextureUnit);
490 stream->readInt(&sampler.textureType);
491 mSamplersPS.push_back(sampler);
492 }
493 const unsigned int vsSamplerCount = stream->readInt<unsigned int>();
494 for (unsigned int i = 0; i < vsSamplerCount; ++i)
495 {
496 Sampler sampler;
497 stream->readBool(&sampler.active);
498 stream->readInt(&sampler.logicalTextureUnit);
499 stream->readInt(&sampler.textureType);
500 mSamplersVS.push_back(sampler);
501 }
502
503 stream->readInt(&mUsedVertexSamplerRange);
504 stream->readInt(&mUsedPixelSamplerRange);
505
506 const unsigned int uniformCount = stream->readInt<unsigned int>();
507 if (stream->error())
508 {
Jamie Madillf6113162015-05-07 11:49:21 -0400509 infoLog << "Invalid program binary.";
Geoff Lang7dd2e102014-11-10 15:19:26 -0500510 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700511 }
512
Jamie Madill62d31cb2015-09-11 13:25:51 -0400513 const auto &linkedUniforms = mData.getUniforms();
514 ASSERT(mD3DUniforms.empty());
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700515 for (unsigned int uniformIndex = 0; uniformIndex < uniformCount; uniformIndex++)
516 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400517 const gl::LinkedUniform &linkedUniform = linkedUniforms[uniformIndex];
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700518
Jamie Madill62d31cb2015-09-11 13:25:51 -0400519 D3DUniform *d3dUniform =
520 new D3DUniform(linkedUniform.type, linkedUniform.name, linkedUniform.arraySize,
521 linkedUniform.isInDefaultBlock());
522 stream->readInt(&d3dUniform->psRegisterIndex);
523 stream->readInt(&d3dUniform->vsRegisterIndex);
524 stream->readInt(&d3dUniform->registerCount);
525 stream->readInt(&d3dUniform->registerElement);
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700526
Jamie Madill62d31cb2015-09-11 13:25:51 -0400527 mD3DUniforms.push_back(d3dUniform);
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700528 }
529
Brandon Joneseb994362014-09-24 10:27:28 -0700530 const unsigned int transformFeedbackVaryingCount = stream->readInt<unsigned int>();
531 mTransformFeedbackLinkedVaryings.resize(transformFeedbackVaryingCount);
532 for (unsigned int varyingIndex = 0; varyingIndex < transformFeedbackVaryingCount; varyingIndex++)
533 {
534 gl::LinkedVarying &varying = mTransformFeedbackLinkedVaryings[varyingIndex];
535
536 stream->readString(&varying.name);
537 stream->readInt(&varying.type);
538 stream->readInt(&varying.size);
539 stream->readString(&varying.semanticName);
540 stream->readInt(&varying.semanticIndex);
541 stream->readInt(&varying.semanticIndexCount);
542 }
543
Brandon Jones22502d52014-08-29 16:58:36 -0700544 stream->readString(&mVertexHLSL);
Arun Patole44efa0b2015-03-04 17:11:05 +0530545 stream->readBytes(reinterpret_cast<unsigned char*>(&mVertexWorkarounds), sizeof(D3DCompilerWorkarounds));
Brandon Jones22502d52014-08-29 16:58:36 -0700546 stream->readString(&mPixelHLSL);
Arun Patole44efa0b2015-03-04 17:11:05 +0530547 stream->readBytes(reinterpret_cast<unsigned char*>(&mPixelWorkarounds), sizeof(D3DCompilerWorkarounds));
Brandon Jones22502d52014-08-29 16:58:36 -0700548 stream->readBool(&mUsesFragDepth);
Brandon Jones44151a92014-09-10 11:32:25 -0700549 stream->readBool(&mUsesPointSize);
Brandon Jones22502d52014-08-29 16:58:36 -0700550
551 const size_t pixelShaderKeySize = stream->readInt<unsigned int>();
552 mPixelShaderKey.resize(pixelShaderKeySize);
553 for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKeySize; pixelShaderKeyIndex++)
554 {
555 stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].type);
556 stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].name);
557 stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].source);
558 stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].outputIndex);
559 }
560
Brandon Joneseb994362014-09-24 10:27:28 -0700561 const unsigned char* binary = reinterpret_cast<const unsigned char*>(stream->data());
562
563 const unsigned int vertexShaderCount = stream->readInt<unsigned int>();
564 for (unsigned int vertexShaderIndex = 0; vertexShaderIndex < vertexShaderCount; vertexShaderIndex++)
565 {
Jamie Madilld3dfda22015-07-06 08:28:49 -0400566 size_t inputLayoutSize = stream->readInt<size_t>();
Jamie Madillf8dd7b12015-08-05 13:50:08 -0400567 gl::InputLayout inputLayout(inputLayoutSize, gl::VERTEX_FORMAT_INVALID);
Brandon Joneseb994362014-09-24 10:27:28 -0700568
Jamie Madilld3dfda22015-07-06 08:28:49 -0400569 for (size_t inputIndex = 0; inputIndex < inputLayoutSize; inputIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -0700570 {
Jamie Madillf8dd7b12015-08-05 13:50:08 -0400571 inputLayout[inputIndex] = stream->readInt<gl::VertexFormatType>();
Brandon Joneseb994362014-09-24 10:27:28 -0700572 }
573
574 unsigned int vertexShaderSize = stream->readInt<unsigned int>();
575 const unsigned char *vertexShaderFunction = binary + stream->offset();
Geoff Langb543aff2014-09-30 14:52:54 -0400576
Jamie Madillada9ecc2015-08-17 12:53:37 -0400577 ShaderExecutableD3D *shaderExecutable = nullptr;
578
579 gl::Error error = mRenderer->loadExecutable(
580 vertexShaderFunction, vertexShaderSize, SHADER_VERTEX, mTransformFeedbackLinkedVaryings,
581 (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), &shaderExecutable);
Geoff Langb543aff2014-09-30 14:52:54 -0400582 if (error.isError())
583 {
Geoff Lang7dd2e102014-11-10 15:19:26 -0500584 return LinkResult(false, error);
Geoff Langb543aff2014-09-30 14:52:54 -0400585 }
586
Brandon Joneseb994362014-09-24 10:27:28 -0700587 if (!shaderExecutable)
588 {
Jamie Madillf6113162015-05-07 11:49:21 -0400589 infoLog << "Could not create vertex shader.";
Geoff Lang7dd2e102014-11-10 15:19:26 -0500590 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Joneseb994362014-09-24 10:27:28 -0700591 }
592
593 // generated converted input layout
Jamie Madilld3dfda22015-07-06 08:28:49 -0400594 VertexExecutable::Signature signature;
595 VertexExecutable::getSignature(mRenderer, inputLayout, &signature);
Brandon Joneseb994362014-09-24 10:27:28 -0700596
597 // add new binary
598 mVertexExecutables.push_back(new VertexExecutable(inputLayout, signature, shaderExecutable));
599
600 stream->skip(vertexShaderSize);
601 }
602
603 const size_t pixelShaderCount = stream->readInt<unsigned int>();
604 for (size_t pixelShaderIndex = 0; pixelShaderIndex < pixelShaderCount; pixelShaderIndex++)
605 {
606 const size_t outputCount = stream->readInt<unsigned int>();
607 std::vector<GLenum> outputs(outputCount);
608 for (size_t outputIndex = 0; outputIndex < outputCount; outputIndex++)
609 {
610 stream->readInt(&outputs[outputIndex]);
611 }
612
613 const size_t pixelShaderSize = stream->readInt<unsigned int>();
614 const unsigned char *pixelShaderFunction = binary + stream->offset();
Jamie Madillada9ecc2015-08-17 12:53:37 -0400615 ShaderExecutableD3D *shaderExecutable = nullptr;
616
617 gl::Error error = mRenderer->loadExecutable(
618 pixelShaderFunction, pixelShaderSize, SHADER_PIXEL, mTransformFeedbackLinkedVaryings,
619 (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), &shaderExecutable);
Geoff Langb543aff2014-09-30 14:52:54 -0400620 if (error.isError())
621 {
Geoff Lang7dd2e102014-11-10 15:19:26 -0500622 return LinkResult(false, error);
Geoff Langb543aff2014-09-30 14:52:54 -0400623 }
Brandon Joneseb994362014-09-24 10:27:28 -0700624
625 if (!shaderExecutable)
626 {
Jamie Madillf6113162015-05-07 11:49:21 -0400627 infoLog << "Could not create pixel shader.";
Geoff Lang7dd2e102014-11-10 15:19:26 -0500628 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Joneseb994362014-09-24 10:27:28 -0700629 }
630
631 // add new binary
632 mPixelExecutables.push_back(new PixelExecutable(outputs, shaderExecutable));
633
634 stream->skip(pixelShaderSize);
635 }
636
637 unsigned int geometryShaderSize = stream->readInt<unsigned int>();
638
639 if (geometryShaderSize > 0)
640 {
641 const unsigned char *geometryShaderFunction = binary + stream->offset();
Jamie Madillada9ecc2015-08-17 12:53:37 -0400642 gl::Error error = mRenderer->loadExecutable(
643 geometryShaderFunction, geometryShaderSize, SHADER_GEOMETRY,
644 mTransformFeedbackLinkedVaryings,
645 (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), &mGeometryExecutable);
Geoff Langb543aff2014-09-30 14:52:54 -0400646 if (error.isError())
647 {
Geoff Lang7dd2e102014-11-10 15:19:26 -0500648 return LinkResult(false, error);
Geoff Langb543aff2014-09-30 14:52:54 -0400649 }
Brandon Joneseb994362014-09-24 10:27:28 -0700650
651 if (!mGeometryExecutable)
652 {
Jamie Madillf6113162015-05-07 11:49:21 -0400653 infoLog << "Could not create geometry shader.";
Geoff Lang7dd2e102014-11-10 15:19:26 -0500654 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Joneseb994362014-09-24 10:27:28 -0700655 }
656 stream->skip(geometryShaderSize);
657 }
658
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700659 initializeUniformStorage();
Jamie Madill437d2662014-12-05 14:23:35 -0500660 initAttributesByLayout();
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700661
Geoff Lang7dd2e102014-11-10 15:19:26 -0500662 return LinkResult(true, gl::Error(GL_NO_ERROR));
Brandon Jones22502d52014-08-29 16:58:36 -0700663}
664
Geoff Langb543aff2014-09-30 14:52:54 -0400665gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream)
Brandon Jones22502d52014-08-29 16:58:36 -0700666{
Austin Kinross137b1512015-06-17 16:14:53 -0700667 // Output the DeviceIdentifier before we output any shader code
668 // When we load the binary again later, we can validate the device identifier before trying to compile any HLSL
669 DeviceIdentifier binaryIdentifier = mRenderer->getAdapterIdentifier();
670 stream->writeBytes(reinterpret_cast<unsigned char*>(&binaryIdentifier), sizeof(DeviceIdentifier));
671
Jamie Madill2db1fbb2014-12-03 10:58:55 -0500672 stream->writeInt(ANGLE_COMPILE_OPTIMIZATION_LEVEL);
673
Jamie Madill63805b42015-08-25 13:17:39 -0400674 // TODO(jmadill): replace MAX_VERTEX_ATTRIBS
675 for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; ++i)
676 {
677 stream->writeInt(mSemanticIndexes[i]);
678 }
679
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700680 stream->writeInt(mSamplersPS.size());
681 for (unsigned int i = 0; i < mSamplersPS.size(); ++i)
682 {
683 stream->writeInt(mSamplersPS[i].active);
684 stream->writeInt(mSamplersPS[i].logicalTextureUnit);
685 stream->writeInt(mSamplersPS[i].textureType);
686 }
687
688 stream->writeInt(mSamplersVS.size());
689 for (unsigned int i = 0; i < mSamplersVS.size(); ++i)
690 {
691 stream->writeInt(mSamplersVS[i].active);
692 stream->writeInt(mSamplersVS[i].logicalTextureUnit);
693 stream->writeInt(mSamplersVS[i].textureType);
694 }
695
696 stream->writeInt(mUsedVertexSamplerRange);
697 stream->writeInt(mUsedPixelSamplerRange);
698
Jamie Madill62d31cb2015-09-11 13:25:51 -0400699 stream->writeInt(mD3DUniforms.size());
700 for (size_t uniformIndex = 0; uniformIndex < mD3DUniforms.size(); ++uniformIndex)
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700701 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400702 const D3DUniform &uniform = *mD3DUniforms[uniformIndex];
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700703
Jamie Madill62d31cb2015-09-11 13:25:51 -0400704 // Type, name and arraySize are redundant, so aren't stored in the binary.
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700705 stream->writeInt(uniform.psRegisterIndex);
706 stream->writeInt(uniform.vsRegisterIndex);
707 stream->writeInt(uniform.registerCount);
708 stream->writeInt(uniform.registerElement);
709 }
710
Brandon Joneseb994362014-09-24 10:27:28 -0700711 stream->writeInt(mTransformFeedbackLinkedVaryings.size());
712 for (size_t i = 0; i < mTransformFeedbackLinkedVaryings.size(); i++)
713 {
714 const gl::LinkedVarying &varying = mTransformFeedbackLinkedVaryings[i];
715
716 stream->writeString(varying.name);
717 stream->writeInt(varying.type);
718 stream->writeInt(varying.size);
719 stream->writeString(varying.semanticName);
720 stream->writeInt(varying.semanticIndex);
721 stream->writeInt(varying.semanticIndexCount);
722 }
723
Brandon Jones22502d52014-08-29 16:58:36 -0700724 stream->writeString(mVertexHLSL);
Arun Patole44efa0b2015-03-04 17:11:05 +0530725 stream->writeBytes(reinterpret_cast<unsigned char*>(&mVertexWorkarounds), sizeof(D3DCompilerWorkarounds));
Brandon Jones22502d52014-08-29 16:58:36 -0700726 stream->writeString(mPixelHLSL);
Arun Patole44efa0b2015-03-04 17:11:05 +0530727 stream->writeBytes(reinterpret_cast<unsigned char*>(&mPixelWorkarounds), sizeof(D3DCompilerWorkarounds));
Brandon Jones22502d52014-08-29 16:58:36 -0700728 stream->writeInt(mUsesFragDepth);
Brandon Jones44151a92014-09-10 11:32:25 -0700729 stream->writeInt(mUsesPointSize);
Brandon Jones22502d52014-08-29 16:58:36 -0700730
Brandon Joneseb994362014-09-24 10:27:28 -0700731 const std::vector<PixelShaderOutputVariable> &pixelShaderKey = mPixelShaderKey;
Brandon Jones22502d52014-08-29 16:58:36 -0700732 stream->writeInt(pixelShaderKey.size());
733 for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKey.size(); pixelShaderKeyIndex++)
734 {
Brandon Joneseb994362014-09-24 10:27:28 -0700735 const PixelShaderOutputVariable &variable = pixelShaderKey[pixelShaderKeyIndex];
Brandon Jones22502d52014-08-29 16:58:36 -0700736 stream->writeInt(variable.type);
737 stream->writeString(variable.name);
738 stream->writeString(variable.source);
739 stream->writeInt(variable.outputIndex);
740 }
741
Brandon Joneseb994362014-09-24 10:27:28 -0700742 stream->writeInt(mVertexExecutables.size());
743 for (size_t vertexExecutableIndex = 0; vertexExecutableIndex < mVertexExecutables.size(); vertexExecutableIndex++)
744 {
745 VertexExecutable *vertexExecutable = mVertexExecutables[vertexExecutableIndex];
746
Jamie Madilld3dfda22015-07-06 08:28:49 -0400747 const auto &inputLayout = vertexExecutable->inputs();
748 stream->writeInt(inputLayout.size());
749
750 for (size_t inputIndex = 0; inputIndex < inputLayout.size(); inputIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -0700751 {
Jamie Madilld3dfda22015-07-06 08:28:49 -0400752 stream->writeInt(inputLayout[inputIndex]);
Brandon Joneseb994362014-09-24 10:27:28 -0700753 }
754
755 size_t vertexShaderSize = vertexExecutable->shaderExecutable()->getLength();
756 stream->writeInt(vertexShaderSize);
757
758 const uint8_t *vertexBlob = vertexExecutable->shaderExecutable()->getFunction();
759 stream->writeBytes(vertexBlob, vertexShaderSize);
760 }
761
762 stream->writeInt(mPixelExecutables.size());
763 for (size_t pixelExecutableIndex = 0; pixelExecutableIndex < mPixelExecutables.size(); pixelExecutableIndex++)
764 {
765 PixelExecutable *pixelExecutable = mPixelExecutables[pixelExecutableIndex];
766
767 const std::vector<GLenum> outputs = pixelExecutable->outputSignature();
768 stream->writeInt(outputs.size());
769 for (size_t outputIndex = 0; outputIndex < outputs.size(); outputIndex++)
770 {
771 stream->writeInt(outputs[outputIndex]);
772 }
773
774 size_t pixelShaderSize = pixelExecutable->shaderExecutable()->getLength();
775 stream->writeInt(pixelShaderSize);
776
777 const uint8_t *pixelBlob = pixelExecutable->shaderExecutable()->getFunction();
778 stream->writeBytes(pixelBlob, pixelShaderSize);
779 }
780
781 size_t geometryShaderSize = (mGeometryExecutable != NULL) ? mGeometryExecutable->getLength() : 0;
782 stream->writeInt(geometryShaderSize);
783
784 if (mGeometryExecutable != NULL && geometryShaderSize > 0)
785 {
786 const uint8_t *geometryBlob = mGeometryExecutable->getFunction();
787 stream->writeBytes(geometryBlob, geometryShaderSize);
788 }
789
Geoff Langb543aff2014-09-30 14:52:54 -0400790 return gl::Error(GL_NO_ERROR);
Brandon Jones22502d52014-08-29 16:58:36 -0700791}
792
Geoff Lang359ef262015-01-05 14:42:29 -0500793gl::Error ProgramD3D::getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo, ShaderExecutableD3D **outExecutable)
Brandon Jones22502d52014-08-29 16:58:36 -0700794{
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400795 mPixelShaderOutputFormatCache.clear();
Brandon Joneseb994362014-09-24 10:27:28 -0700796
Jamie Madill85a18042015-03-05 15:41:41 -0500797 const FramebufferD3D *fboD3D = GetImplAs<FramebufferD3D>(fbo);
798 const gl::AttachmentList &colorbuffers = fboD3D->getColorAttachmentsForRender(mRenderer->getWorkarounds());
Brandon Joneseb994362014-09-24 10:27:28 -0700799
800 for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment)
801 {
802 const gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment];
803
804 if (colorbuffer)
805 {
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400806 mPixelShaderOutputFormatCache.push_back(colorbuffer->getBinding() == GL_BACK ? GL_COLOR_ATTACHMENT0 : colorbuffer->getBinding());
Brandon Joneseb994362014-09-24 10:27:28 -0700807 }
808 else
809 {
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400810 mPixelShaderOutputFormatCache.push_back(GL_NONE);
Brandon Joneseb994362014-09-24 10:27:28 -0700811 }
812 }
813
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400814 return getPixelExecutableForOutputLayout(mPixelShaderOutputFormatCache, outExecutable, nullptr);
Brandon Joneseb994362014-09-24 10:27:28 -0700815}
816
Jamie Madill97399232014-12-23 12:31:15 -0500817gl::Error ProgramD3D::getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputSignature,
Geoff Lang359ef262015-01-05 14:42:29 -0500818 ShaderExecutableD3D **outExectuable,
Jamie Madill97399232014-12-23 12:31:15 -0500819 gl::InfoLog *infoLog)
Brandon Joneseb994362014-09-24 10:27:28 -0700820{
821 for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++)
822 {
823 if (mPixelExecutables[executableIndex]->matchesSignature(outputSignature))
824 {
Geoff Langb543aff2014-09-30 14:52:54 -0400825 *outExectuable = mPixelExecutables[executableIndex]->shaderExecutable();
826 return gl::Error(GL_NO_ERROR);
Brandon Joneseb994362014-09-24 10:27:28 -0700827 }
828 }
829
Brandon Jones22502d52014-08-29 16:58:36 -0700830 std::string finalPixelHLSL = mDynamicHLSL->generatePixelShaderForOutputSignature(mPixelHLSL, mPixelShaderKey, mUsesFragDepth,
831 outputSignature);
832
833 // Generate new pixel executable
Geoff Lang359ef262015-01-05 14:42:29 -0500834 ShaderExecutableD3D *pixelExecutable = NULL;
Jamie Madill97399232014-12-23 12:31:15 -0500835
836 gl::InfoLog tempInfoLog;
837 gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
838
Jamie Madillada9ecc2015-08-17 12:53:37 -0400839 gl::Error error = mRenderer->compileToExecutable(
840 *currentInfoLog, finalPixelHLSL, SHADER_PIXEL, mTransformFeedbackLinkedVaryings,
841 (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), mPixelWorkarounds,
842 &pixelExecutable);
Geoff Langb543aff2014-09-30 14:52:54 -0400843 if (error.isError())
844 {
845 return error;
846 }
Brandon Joneseb994362014-09-24 10:27:28 -0700847
Jamie Madill97399232014-12-23 12:31:15 -0500848 if (pixelExecutable)
849 {
850 mPixelExecutables.push_back(new PixelExecutable(outputSignature, pixelExecutable));
851 }
852 else if (!infoLog)
Brandon Joneseb994362014-09-24 10:27:28 -0700853 {
854 std::vector<char> tempCharBuffer(tempInfoLog.getLength() + 3);
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700855 tempInfoLog.getLog(static_cast<GLsizei>(tempInfoLog.getLength()), NULL, &tempCharBuffer[0]);
Brandon Joneseb994362014-09-24 10:27:28 -0700856 ERR("Error compiling dynamic pixel executable:\n%s\n", &tempCharBuffer[0]);
857 }
Brandon Jones22502d52014-08-29 16:58:36 -0700858
Geoff Langb543aff2014-09-30 14:52:54 -0400859 *outExectuable = pixelExecutable;
860 return gl::Error(GL_NO_ERROR);
Brandon Jones22502d52014-08-29 16:58:36 -0700861}
862
Jamie Madilld3dfda22015-07-06 08:28:49 -0400863gl::Error ProgramD3D::getVertexExecutableForInputLayout(const gl::InputLayout &inputLayout,
Geoff Lang359ef262015-01-05 14:42:29 -0500864 ShaderExecutableD3D **outExectuable,
Jamie Madill97399232014-12-23 12:31:15 -0500865 gl::InfoLog *infoLog)
Brandon Jones22502d52014-08-29 16:58:36 -0700866{
Jamie Madilld3dfda22015-07-06 08:28:49 -0400867 VertexExecutable::getSignature(mRenderer, inputLayout, &mCachedVertexSignature);
Brandon Joneseb994362014-09-24 10:27:28 -0700868
869 for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++)
870 {
Jamie Madilld3dfda22015-07-06 08:28:49 -0400871 if (mVertexExecutables[executableIndex]->matchesSignature(mCachedVertexSignature))
Brandon Joneseb994362014-09-24 10:27:28 -0700872 {
Geoff Langb543aff2014-09-30 14:52:54 -0400873 *outExectuable = mVertexExecutables[executableIndex]->shaderExecutable();
874 return gl::Error(GL_NO_ERROR);
Brandon Joneseb994362014-09-24 10:27:28 -0700875 }
876 }
877
Brandon Jones22502d52014-08-29 16:58:36 -0700878 // Generate new dynamic layout with attribute conversions
Jamie Madillc349ec02015-08-21 16:53:12 -0400879 std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout(
880 mVertexHLSL, inputLayout, mData.getAttributes());
Brandon Jones22502d52014-08-29 16:58:36 -0700881
882 // Generate new vertex executable
Geoff Lang359ef262015-01-05 14:42:29 -0500883 ShaderExecutableD3D *vertexExecutable = NULL;
Jamie Madill97399232014-12-23 12:31:15 -0500884
885 gl::InfoLog tempInfoLog;
886 gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
887
Jamie Madillada9ecc2015-08-17 12:53:37 -0400888 gl::Error error = mRenderer->compileToExecutable(
889 *currentInfoLog, finalVertexHLSL, SHADER_VERTEX, mTransformFeedbackLinkedVaryings,
890 (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), mVertexWorkarounds,
891 &vertexExecutable);
Geoff Langb543aff2014-09-30 14:52:54 -0400892 if (error.isError())
893 {
894 return error;
895 }
896
Jamie Madill97399232014-12-23 12:31:15 -0500897 if (vertexExecutable)
Brandon Joneseb994362014-09-24 10:27:28 -0700898 {
Jamie Madilld3dfda22015-07-06 08:28:49 -0400899 mVertexExecutables.push_back(new VertexExecutable(inputLayout, mCachedVertexSignature, vertexExecutable));
Brandon Joneseb994362014-09-24 10:27:28 -0700900 }
Jamie Madill97399232014-12-23 12:31:15 -0500901 else if (!infoLog)
902 {
903 std::vector<char> tempCharBuffer(tempInfoLog.getLength() + 3);
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700904 tempInfoLog.getLog(static_cast<GLsizei>(tempInfoLog.getLength()), NULL, &tempCharBuffer[0]);
Jamie Madill97399232014-12-23 12:31:15 -0500905 ERR("Error compiling dynamic vertex executable:\n%s\n", &tempCharBuffer[0]);
906 }
Brandon Jones22502d52014-08-29 16:58:36 -0700907
Geoff Langb543aff2014-09-30 14:52:54 -0400908 *outExectuable = vertexExecutable;
909 return gl::Error(GL_NO_ERROR);
Brandon Jones22502d52014-08-29 16:58:36 -0700910}
911
Jamie Madillca03b352015-09-02 12:38:13 -0400912LinkResult ProgramD3D::compileProgramExecutables(gl::InfoLog &infoLog,
913 int registers,
914 const std::vector<PackedVarying> &packedVaryings)
Brandon Jones44151a92014-09-10 11:32:25 -0700915{
Jamie Madill5c6b7bf2015-08-17 12:53:35 -0400916 const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(mData.getAttachedFragmentShader());
Brandon Jones44151a92014-09-10 11:32:25 -0700917
Jamie Madill5c6b7bf2015-08-17 12:53:35 -0400918 const gl::InputLayout &defaultInputLayout =
919 GetDefaultInputLayoutFromShader(mData.getAttachedVertexShader());
Jamie Madille4ea2022015-03-26 20:35:05 +0000920 ShaderExecutableD3D *defaultVertexExecutable = NULL;
921 gl::Error error = getVertexExecutableForInputLayout(defaultInputLayout, &defaultVertexExecutable, &infoLog);
922 if (error.isError())
Austin Kinross434953e2015-02-20 10:49:51 -0800923 {
Jamie Madille4ea2022015-03-26 20:35:05 +0000924 return LinkResult(false, error);
925 }
Austin Kinross434953e2015-02-20 10:49:51 -0800926
Brandon Joneseb994362014-09-24 10:27:28 -0700927 std::vector<GLenum> defaultPixelOutput = GetDefaultOutputLayoutFromShader(getPixelShaderKey());
Geoff Lang359ef262015-01-05 14:42:29 -0500928 ShaderExecutableD3D *defaultPixelExecutable = NULL;
Jamie Madille4ea2022015-03-26 20:35:05 +0000929 error = getPixelExecutableForOutputLayout(defaultPixelOutput, &defaultPixelExecutable, &infoLog);
Geoff Langb543aff2014-09-30 14:52:54 -0400930 if (error.isError())
931 {
Geoff Lang7dd2e102014-11-10 15:19:26 -0500932 return LinkResult(false, error);
Geoff Langb543aff2014-09-30 14:52:54 -0400933 }
Brandon Jones44151a92014-09-10 11:32:25 -0700934
Brandon Joneseb994362014-09-24 10:27:28 -0700935 if (usesGeometryShader())
936 {
Jamie Madillca03b352015-09-02 12:38:13 -0400937 std::string geometryHLSL =
938 mDynamicHLSL->generateGeometryShaderHLSL(registers, fragmentShaderD3D, packedVaryings);
Brandon Jones44151a92014-09-10 11:32:25 -0700939
Jamie Madillada9ecc2015-08-17 12:53:37 -0400940 error = mRenderer->compileToExecutable(
941 infoLog, geometryHLSL, SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings,
942 (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS),
943 D3DCompilerWorkarounds(), &mGeometryExecutable);
Geoff Langb543aff2014-09-30 14:52:54 -0400944 if (error.isError())
945 {
Geoff Lang7dd2e102014-11-10 15:19:26 -0500946 return LinkResult(false, error);
Geoff Langb543aff2014-09-30 14:52:54 -0400947 }
Brandon Joneseb994362014-09-24 10:27:28 -0700948 }
949
Brandon Jones091540d2014-10-29 11:32:04 -0700950#if ANGLE_SHADER_DEBUG_INFO == ANGLE_ENABLED
Jamie Madillca03b352015-09-02 12:38:13 -0400951 const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(mData.getAttachedVertexShader());
952
Tibor den Ouden97049c62014-10-06 21:39:16 +0200953 if (usesGeometryShader() && mGeometryExecutable)
954 {
955 // Geometry shaders are currently only used internally, so there is no corresponding shader object at the interface level
956 // For now the geometry shader debug info is pre-pended to the vertex shader, this is a bit of a clutch
957 vertexShaderD3D->appendDebugInfo("// GEOMETRY SHADER BEGIN\n\n");
958 vertexShaderD3D->appendDebugInfo(mGeometryExecutable->getDebugInfo());
959 vertexShaderD3D->appendDebugInfo("\nGEOMETRY SHADER END\n\n\n");
960 }
961
962 if (defaultVertexExecutable)
963 {
964 vertexShaderD3D->appendDebugInfo(defaultVertexExecutable->getDebugInfo());
965 }
966
967 if (defaultPixelExecutable)
968 {
969 fragmentShaderD3D->appendDebugInfo(defaultPixelExecutable->getDebugInfo());
970 }
971#endif
972
Geoff Langb543aff2014-09-30 14:52:54 -0400973 bool linkSuccess = (defaultVertexExecutable && defaultPixelExecutable && (!usesGeometryShader() || mGeometryExecutable));
Geoff Lang7dd2e102014-11-10 15:19:26 -0500974 return LinkResult(linkSuccess, gl::Error(GL_NO_ERROR));
Brandon Jones18bd4102014-09-22 14:21:44 -0700975}
976
Jamie Madillf5f4ad22015-09-02 18:32:38 +0000977LinkResult ProgramD3D::link(const gl::Data &data, gl::InfoLog &infoLog)
Brandon Jones22502d52014-08-29 16:58:36 -0700978{
Jamie Madill62d31cb2015-09-11 13:25:51 -0400979 reset();
980
981 // TODO(jmadill): structures containing samplers
982 for (const gl::LinkedUniform &linkedUniform : mData.getUniforms())
983 {
984 if (linkedUniform.isSampler() && linkedUniform.isField())
985 {
986 infoLog << "Structures containing samplers not currently supported in D3D.";
987 return LinkResult(false, gl::Error(GL_NO_ERROR));
988 }
989 }
990
Jamie Madillf5f4ad22015-09-02 18:32:38 +0000991 const gl::Shader *vertexShader = mData.getAttachedVertexShader();
992 const gl::Shader *fragmentShader = mData.getAttachedFragmentShader();
Brandon Joneseb994362014-09-24 10:27:28 -0700993
Jamie Madillf5f4ad22015-09-02 18:32:38 +0000994 const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(vertexShader);
995 const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(fragmentShader);
996
Jamie Madill63069df2015-09-01 17:26:41 +0000997 mSamplersVS.resize(data.caps->maxVertexTextureImageUnits);
Jamie Madillf5f4ad22015-09-02 18:32:38 +0000998 mSamplersPS.resize(data.caps->maxTextureImageUnits);
Brandon Jones22502d52014-08-29 16:58:36 -0700999
Jamie Madill91445bc2015-09-23 16:47:53 -04001000 mVertexHLSL = vertexShader->getTranslatedSource();
Arun Patole44efa0b2015-03-04 17:11:05 +05301001 vertexShaderD3D->generateWorkarounds(&mVertexWorkarounds);
Brandon Jones22502d52014-08-29 16:58:36 -07001002
Jamie Madill91445bc2015-09-23 16:47:53 -04001003 mPixelHLSL = fragmentShader->getTranslatedSource();
Jamie Madillf5f4ad22015-09-02 18:32:38 +00001004 fragmentShaderD3D->generateWorkarounds(&mPixelWorkarounds);
1005
Austin Kinross02df7962015-07-01 10:03:42 -07001006 if (mRenderer->getRendererLimitations().noFrontFacingSupport)
1007 {
1008 if (fragmentShaderD3D->usesFrontFacing())
1009 {
1010 infoLog << "The current renderer doesn't support gl_FrontFacing";
1011 return LinkResult(false, gl::Error(GL_NO_ERROR));
1012 }
1013 }
1014
Jamie Madillca03b352015-09-02 12:38:13 -04001015 std::vector<PackedVarying> packedVaryings =
1016 MergeVaryings(*vertexShader, *fragmentShader, mData.getTransformFeedbackVaryingNames());
1017
Brandon Jones22502d52014-08-29 16:58:36 -07001018 // Map the varyings to the register file
Jamie Madillca03b352015-09-02 12:38:13 -04001019 int registers = mDynamicHLSL->packVaryings(infoLog, &packedVaryings,
Jamie Madill31c8c562015-08-19 14:08:03 -04001020 mData.getTransformFeedbackVaryingNames());
Brandon Jones22502d52014-08-29 16:58:36 -07001021
Jamie Madill31c8c562015-08-19 14:08:03 -04001022 if (registers < 0)
Brandon Jones22502d52014-08-29 16:58:36 -07001023 {
Geoff Lang7dd2e102014-11-10 15:19:26 -05001024 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Jones22502d52014-08-29 16:58:36 -07001025 }
1026
Jamie Madillccdf74b2015-08-18 10:46:12 -04001027 std::vector<gl::LinkedVarying> linkedVaryings;
Jamie Madill4cff2472015-08-21 16:53:18 -04001028 if (!mDynamicHLSL->generateShaderLinkHLSL(data, mData, infoLog, registers, mPixelHLSL,
Jamie Madillca03b352015-09-02 12:38:13 -04001029 mVertexHLSL, packedVaryings, &linkedVaryings,
1030 &mPixelShaderKey, &mUsesFragDepth))
Brandon Jones22502d52014-08-29 16:58:36 -07001031 {
Geoff Lang7dd2e102014-11-10 15:19:26 -05001032 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Jones22502d52014-08-29 16:58:36 -07001033 }
1034
Brandon Jones44151a92014-09-10 11:32:25 -07001035 mUsesPointSize = vertexShaderD3D->usesPointSize();
1036
Jamie Madill63805b42015-08-25 13:17:39 -04001037 initSemanticIndex();
Jamie Madill437d2662014-12-05 14:23:35 -05001038
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001039 defineUniformsAndAssignRegisters();
Jamie Madille473dee2015-08-18 14:49:01 -04001040
Jamie Madillccdf74b2015-08-18 10:46:12 -04001041 gatherTransformFeedbackVaryings(linkedVaryings);
1042
Jamie Madillca03b352015-09-02 12:38:13 -04001043 LinkResult result = compileProgramExecutables(infoLog, registers, packedVaryings);
Jamie Madill31c8c562015-08-19 14:08:03 -04001044 if (result.error.isError() || !result.linkSuccess)
1045 {
1046 infoLog << "Failed to create D3D shaders.";
1047 return result;
1048 }
1049
Geoff Lang7dd2e102014-11-10 15:19:26 -05001050 return LinkResult(true, gl::Error(GL_NO_ERROR));
Brandon Jones22502d52014-08-29 16:58:36 -07001051}
1052
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001053GLboolean ProgramD3D::validate(const gl::Caps & /*caps*/, gl::InfoLog * /*infoLog*/)
Jamie Madill36cfd6a2015-08-18 10:46:20 -04001054{
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001055 // TODO(jmadill): Do something useful here?
1056 return GL_TRUE;
Jamie Madill36cfd6a2015-08-18 10:46:20 -04001057}
1058
Jamie Madill62d31cb2015-09-11 13:25:51 -04001059void ProgramD3D::gatherUniformBlockInfo(std::vector<gl::UniformBlock> *uniformBlocks,
1060 std::vector<gl::LinkedUniform> *uniforms)
1061{
1062 const gl::Shader *vertexShader = mData.getAttachedVertexShader();
1063
1064 BlockInfoMap blockInfo;
1065 std::map<std::string, size_t> blockDataSizes;
1066
1067 for (const sh::InterfaceBlock &vertexBlock : vertexShader->getInterfaceBlocks())
1068 {
1069 if (!vertexBlock.staticUse && vertexBlock.layout == sh::BLOCKLAYOUT_PACKED)
1070 continue;
1071
1072 if (blockDataSizes.count(vertexBlock.name) > 0)
1073 continue;
1074
1075 size_t dataSize = defineUniformBlock(vertexBlock, &blockInfo);
1076 blockDataSizes[vertexBlock.name] = dataSize;
1077 }
1078
1079 const gl::Shader *fragmentShader = mData.getAttachedFragmentShader();
1080
1081 for (const sh::InterfaceBlock &fragmentBlock : fragmentShader->getInterfaceBlocks())
1082 {
1083 if (!fragmentBlock.staticUse && fragmentBlock.layout == sh::BLOCKLAYOUT_PACKED)
1084 continue;
1085
1086 if (blockDataSizes.count(fragmentBlock.name) > 0)
1087 continue;
1088
1089 size_t dataSize = defineUniformBlock(fragmentBlock, &blockInfo);
1090 blockDataSizes[fragmentBlock.name] = dataSize;
1091 }
1092
1093 // Copy block info out to uniforms.
1094 for (gl::LinkedUniform &linkedUniform : *uniforms)
1095 {
1096 const auto &infoEntry = blockInfo.find(linkedUniform.name);
1097
1098 if (infoEntry != blockInfo.end())
1099 {
1100 linkedUniform.blockInfo = infoEntry->second;
1101 }
1102 }
1103
1104 // Assign registers and update sizes.
1105 const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(vertexShader);
1106 const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(fragmentShader);
1107
1108 for (gl::UniformBlock &uniformBlock : *uniformBlocks)
1109 {
1110 unsigned int uniformBlockElement = uniformBlock.isArray ? uniformBlock.arrayElement : 0;
1111
1112 if (uniformBlock.vertexStaticUse)
1113 {
1114 unsigned int baseRegister =
1115 vertexShaderD3D->getInterfaceBlockRegister(uniformBlock.name);
1116 uniformBlock.vsRegisterIndex = baseRegister + uniformBlockElement;
1117 }
1118
1119 if (uniformBlock.fragmentStaticUse)
1120 {
1121 unsigned int baseRegister =
1122 fragmentShaderD3D->getInterfaceBlockRegister(uniformBlock.name);
1123 uniformBlock.psRegisterIndex = baseRegister + uniformBlockElement;
1124 }
1125
1126 ASSERT(blockDataSizes.count(uniformBlock.name) == 1);
1127 uniformBlock.dataSize = static_cast<unsigned int>(blockDataSizes[uniformBlock.name]);
1128 }
1129}
1130
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001131void ProgramD3D::initializeUniformStorage()
Brandon Jonesc9610c52014-08-25 17:02:59 -07001132{
1133 // Compute total default block size
1134 unsigned int vertexRegisters = 0;
1135 unsigned int fragmentRegisters = 0;
Jamie Madill62d31cb2015-09-11 13:25:51 -04001136 for (const D3DUniform *d3dUniform : mD3DUniforms)
Brandon Jonesc9610c52014-08-25 17:02:59 -07001137 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001138 if (!d3dUniform->isSampler())
Brandon Jonesc9610c52014-08-25 17:02:59 -07001139 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001140 if (d3dUniform->isReferencedByVertexShader())
Brandon Jonesc9610c52014-08-25 17:02:59 -07001141 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001142 vertexRegisters = std::max(vertexRegisters,
1143 d3dUniform->vsRegisterIndex + d3dUniform->registerCount);
Brandon Jonesc9610c52014-08-25 17:02:59 -07001144 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04001145 if (d3dUniform->isReferencedByFragmentShader())
Brandon Jonesc9610c52014-08-25 17:02:59 -07001146 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001147 fragmentRegisters = std::max(
1148 fragmentRegisters, d3dUniform->psRegisterIndex + d3dUniform->registerCount);
Brandon Jonesc9610c52014-08-25 17:02:59 -07001149 }
1150 }
1151 }
1152
1153 mVertexUniformStorage = mRenderer->createUniformStorage(vertexRegisters * 16u);
1154 mFragmentUniformStorage = mRenderer->createUniformStorage(fragmentRegisters * 16u);
1155}
1156
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001157gl::Error ProgramD3D::applyUniforms()
Brandon Jones18bd4102014-09-22 14:21:44 -07001158{
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001159 updateSamplerMapping();
1160
Jamie Madill62d31cb2015-09-11 13:25:51 -04001161 gl::Error error = mRenderer->applyUniforms(*this, mD3DUniforms);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001162 if (error.isError())
1163 {
1164 return error;
1165 }
1166
Jamie Madill62d31cb2015-09-11 13:25:51 -04001167 for (D3DUniform *d3dUniform : mD3DUniforms)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001168 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001169 d3dUniform->dirty = false;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001170 }
1171
1172 return gl::Error(GL_NO_ERROR);
Brandon Jones18bd4102014-09-22 14:21:44 -07001173}
1174
Jamie Madilld1fe1642015-08-21 16:26:04 -04001175gl::Error ProgramD3D::applyUniformBuffers(const gl::Data &data)
Brandon Jones18bd4102014-09-22 14:21:44 -07001176{
Jamie Madill03260fa2015-06-22 13:57:22 -04001177 mVertexUBOCache.clear();
1178 mFragmentUBOCache.clear();
Brandon Jones18bd4102014-09-22 14:21:44 -07001179
1180 const unsigned int reservedBuffersInVS = mRenderer->getReservedVertexUniformBuffers();
1181 const unsigned int reservedBuffersInFS = mRenderer->getReservedFragmentUniformBuffers();
1182
Jamie Madill62d31cb2015-09-11 13:25:51 -04001183 const auto &uniformBlocks = mData.getUniformBlocks();
1184 for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < uniformBlocks.size();
1185 uniformBlockIndex++)
Brandon Jones18bd4102014-09-22 14:21:44 -07001186 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001187 const gl::UniformBlock &uniformBlock = uniformBlocks[uniformBlockIndex];
Jamie Madilld1fe1642015-08-21 16:26:04 -04001188 GLuint blockBinding = mData.getUniformBlockBinding(uniformBlockIndex);
Brandon Jones18bd4102014-09-22 14:21:44 -07001189
Brandon Jones18bd4102014-09-22 14:21:44 -07001190 // Unnecessary to apply an unreferenced standard or shared UBO
Jamie Madill62d31cb2015-09-11 13:25:51 -04001191 if (!uniformBlock.vertexStaticUse && !uniformBlock.fragmentStaticUse)
Brandon Jones18bd4102014-09-22 14:21:44 -07001192 {
1193 continue;
1194 }
1195
Jamie Madill62d31cb2015-09-11 13:25:51 -04001196 if (uniformBlock.vertexStaticUse)
Brandon Jones18bd4102014-09-22 14:21:44 -07001197 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001198 unsigned int registerIndex = uniformBlock.vsRegisterIndex - reservedBuffersInVS;
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00001199 ASSERT(registerIndex < data.caps->maxVertexUniformBlocks);
Jamie Madill03260fa2015-06-22 13:57:22 -04001200
Jamie Madill969194d2015-07-20 14:36:56 -04001201 if (mVertexUBOCache.size() <= registerIndex)
Jamie Madill03260fa2015-06-22 13:57:22 -04001202 {
1203 mVertexUBOCache.resize(registerIndex + 1, -1);
1204 }
1205
1206 ASSERT(mVertexUBOCache[registerIndex] == -1);
1207 mVertexUBOCache[registerIndex] = blockBinding;
Brandon Jones18bd4102014-09-22 14:21:44 -07001208 }
1209
Jamie Madill62d31cb2015-09-11 13:25:51 -04001210 if (uniformBlock.fragmentStaticUse)
Brandon Jones18bd4102014-09-22 14:21:44 -07001211 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001212 unsigned int registerIndex = uniformBlock.psRegisterIndex - reservedBuffersInFS;
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00001213 ASSERT(registerIndex < data.caps->maxFragmentUniformBlocks);
Jamie Madill03260fa2015-06-22 13:57:22 -04001214
1215 if (mFragmentUBOCache.size() <= registerIndex)
1216 {
1217 mFragmentUBOCache.resize(registerIndex + 1, -1);
1218 }
1219
1220 ASSERT(mFragmentUBOCache[registerIndex] == -1);
1221 mFragmentUBOCache[registerIndex] = blockBinding;
Brandon Jones18bd4102014-09-22 14:21:44 -07001222 }
1223 }
1224
Jamie Madill03260fa2015-06-22 13:57:22 -04001225 return mRenderer->setUniformBuffers(data, mVertexUBOCache, mFragmentUBOCache);
Brandon Jones18bd4102014-09-22 14:21:44 -07001226}
1227
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001228void ProgramD3D::dirtyAllUniforms()
Brandon Jones18bd4102014-09-22 14:21:44 -07001229{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001230 for (D3DUniform *d3dUniform : mD3DUniforms)
Brandon Jones18bd4102014-09-22 14:21:44 -07001231 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001232 d3dUniform->dirty = true;
Brandon Jones18bd4102014-09-22 14:21:44 -07001233 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001234}
1235
1236void ProgramD3D::setUniform1fv(GLint location, GLsizei count, const GLfloat* v)
1237{
1238 setUniform(location, count, v, GL_FLOAT);
1239}
1240
1241void ProgramD3D::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
1242{
1243 setUniform(location, count, v, GL_FLOAT_VEC2);
1244}
1245
1246void ProgramD3D::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
1247{
1248 setUniform(location, count, v, GL_FLOAT_VEC3);
1249}
1250
1251void ProgramD3D::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
1252{
1253 setUniform(location, count, v, GL_FLOAT_VEC4);
1254}
1255
1256void ProgramD3D::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1257{
1258 setUniformMatrixfv<2, 2>(location, count, transpose, value, GL_FLOAT_MAT2);
1259}
1260
1261void ProgramD3D::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1262{
1263 setUniformMatrixfv<3, 3>(location, count, transpose, value, GL_FLOAT_MAT3);
1264}
1265
1266void ProgramD3D::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1267{
1268 setUniformMatrixfv<4, 4>(location, count, transpose, value, GL_FLOAT_MAT4);
1269}
1270
1271void ProgramD3D::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1272{
1273 setUniformMatrixfv<2, 3>(location, count, transpose, value, GL_FLOAT_MAT2x3);
1274}
1275
1276void ProgramD3D::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1277{
1278 setUniformMatrixfv<3, 2>(location, count, transpose, value, GL_FLOAT_MAT3x2);
1279}
1280
1281void ProgramD3D::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1282{
1283 setUniformMatrixfv<2, 4>(location, count, transpose, value, GL_FLOAT_MAT2x4);
1284}
1285
1286void ProgramD3D::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1287{
1288 setUniformMatrixfv<4, 2>(location, count, transpose, value, GL_FLOAT_MAT4x2);
1289}
1290
1291void ProgramD3D::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1292{
1293 setUniformMatrixfv<3, 4>(location, count, transpose, value, GL_FLOAT_MAT3x4);
1294}
1295
1296void ProgramD3D::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1297{
1298 setUniformMatrixfv<4, 3>(location, count, transpose, value, GL_FLOAT_MAT4x3);
1299}
1300
1301void ProgramD3D::setUniform1iv(GLint location, GLsizei count, const GLint *v)
1302{
1303 setUniform(location, count, v, GL_INT);
1304}
1305
1306void ProgramD3D::setUniform2iv(GLint location, GLsizei count, const GLint *v)
1307{
1308 setUniform(location, count, v, GL_INT_VEC2);
1309}
1310
1311void ProgramD3D::setUniform3iv(GLint location, GLsizei count, const GLint *v)
1312{
1313 setUniform(location, count, v, GL_INT_VEC3);
1314}
1315
1316void ProgramD3D::setUniform4iv(GLint location, GLsizei count, const GLint *v)
1317{
1318 setUniform(location, count, v, GL_INT_VEC4);
1319}
1320
1321void ProgramD3D::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
1322{
1323 setUniform(location, count, v, GL_UNSIGNED_INT);
1324}
1325
1326void ProgramD3D::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
1327{
1328 setUniform(location, count, v, GL_UNSIGNED_INT_VEC2);
1329}
1330
1331void ProgramD3D::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
1332{
1333 setUniform(location, count, v, GL_UNSIGNED_INT_VEC3);
1334}
1335
1336void ProgramD3D::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
1337{
1338 setUniform(location, count, v, GL_UNSIGNED_INT_VEC4);
1339}
1340
Geoff Lang5d124a62015-09-15 13:03:27 -04001341void ProgramD3D::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
1342{
1343}
1344
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001345void ProgramD3D::defineUniformsAndAssignRegisters()
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001346{
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001347 D3DUniformMap uniformMap;
Jamie Madill91445bc2015-09-23 16:47:53 -04001348 const gl::Shader *vertexShader = mData.getAttachedVertexShader();
Jamie Madill62d31cb2015-09-11 13:25:51 -04001349 for (const sh::Uniform &vertexUniform : vertexShader->getUniforms())
Jamie Madillfb536032015-09-11 13:19:49 -04001350
Jamie Madilla2eb02c2015-09-11 12:31:41 +00001351 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001352 if (vertexUniform.staticUse)
Jamie Madillfb536032015-09-11 13:19:49 -04001353 {
Jamie Madill91445bc2015-09-23 16:47:53 -04001354 defineUniformBase(vertexShader, vertexUniform, &uniformMap);
Jamie Madillfb536032015-09-11 13:19:49 -04001355 }
1356 }
1357
Jamie Madill62d31cb2015-09-11 13:25:51 -04001358 const gl::Shader *fragmentShader = mData.getAttachedFragmentShader();
Jamie Madill62d31cb2015-09-11 13:25:51 -04001359 for (const sh::Uniform &fragmentUniform : fragmentShader->getUniforms())
Jamie Madillfb536032015-09-11 13:19:49 -04001360 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001361 if (fragmentUniform.staticUse)
Jamie Madillfb536032015-09-11 13:19:49 -04001362 {
Jamie Madill91445bc2015-09-23 16:47:53 -04001363 defineUniformBase(fragmentShader, fragmentUniform, &uniformMap);
Jamie Madillfb536032015-09-11 13:19:49 -04001364 }
1365 }
1366
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001367 // Initialize the D3DUniform list to mirror the indexing of the GL layer.
1368 for (const gl::LinkedUniform &glUniform : mData.getUniforms())
1369 {
1370 if (!glUniform.isInDefaultBlock())
1371 continue;
1372
1373 auto mapEntry = uniformMap.find(glUniform.name);
1374 ASSERT(mapEntry != uniformMap.end());
1375 mD3DUniforms.push_back(mapEntry->second);
1376 }
1377
Jamie Madill62d31cb2015-09-11 13:25:51 -04001378 assignAllSamplerRegisters();
Jamie Madillfb536032015-09-11 13:19:49 -04001379 initializeUniformStorage();
Jamie Madillfb536032015-09-11 13:19:49 -04001380}
1381
Jamie Madill91445bc2015-09-23 16:47:53 -04001382void ProgramD3D::defineUniformBase(const gl::Shader *shader,
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001383 const sh::Uniform &uniform,
1384 D3DUniformMap *uniformMap)
Jamie Madillfb536032015-09-11 13:19:49 -04001385{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001386 if (uniform.isBuiltIn())
Jamie Madillfb536032015-09-11 13:19:49 -04001387 {
Jamie Madill91445bc2015-09-23 16:47:53 -04001388 defineUniform(shader->getType(), uniform, uniform.name, nullptr, uniformMap);
Jamie Madill55def582015-05-04 11:24:57 -04001389 return;
1390 }
1391
Jamie Madill91445bc2015-09-23 16:47:53 -04001392 const ShaderD3D *shaderD3D = GetImplAs<ShaderD3D>(shader);
1393
1394 unsigned int startRegister = shaderD3D->getUniformRegister(uniform.name);
1395 ShShaderOutput outputType = shaderD3D->getCompilerOutputType();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001396 sh::HLSLBlockEncoder encoder(sh::HLSLBlockEncoder::GetStrategyFor(outputType));
Jamie Madill62d31cb2015-09-11 13:25:51 -04001397 encoder.skipRegisters(startRegister);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001398
Jamie Madill91445bc2015-09-23 16:47:53 -04001399 defineUniform(shader->getType(), uniform, uniform.name, &encoder, uniformMap);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001400}
1401
Jamie Madill62d31cb2015-09-11 13:25:51 -04001402D3DUniform *ProgramD3D::getD3DUniformByName(const std::string &name)
1403{
1404 for (D3DUniform *d3dUniform : mD3DUniforms)
1405 {
1406 if (d3dUniform->name == name)
1407 {
1408 return d3dUniform;
1409 }
1410 }
1411
1412 return nullptr;
1413}
1414
Jamie Madill91445bc2015-09-23 16:47:53 -04001415void ProgramD3D::defineUniform(GLenum shaderType,
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001416 const sh::ShaderVariable &uniform,
1417 const std::string &fullName,
1418 sh::HLSLBlockEncoder *encoder,
1419 D3DUniformMap *uniformMap)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001420{
1421 if (uniform.isStruct())
1422 {
1423 for (unsigned int elementIndex = 0; elementIndex < uniform.elementCount(); elementIndex++)
1424 {
1425 const std::string &elementString = (uniform.isArray() ? ArrayString(elementIndex) : "");
1426
Jamie Madill55def582015-05-04 11:24:57 -04001427 if (encoder)
1428 encoder->enterAggregateType();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001429
1430 for (size_t fieldIndex = 0; fieldIndex < uniform.fields.size(); fieldIndex++)
1431 {
1432 const sh::ShaderVariable &field = uniform.fields[fieldIndex];
1433 const std::string &fieldFullName = (fullName + elementString + "." + field.name);
1434
Jamie Madill91445bc2015-09-23 16:47:53 -04001435 defineUniform(shaderType, field, fieldFullName, encoder, uniformMap);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001436 }
1437
Jamie Madill55def582015-05-04 11:24:57 -04001438 if (encoder)
1439 encoder->exitAggregateType();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001440 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04001441 return;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001442 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04001443
1444 // Not a struct. Arrays are treated as aggregate types.
1445 if (uniform.isArray() && encoder)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001446 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001447 encoder->enterAggregateType();
1448 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001449
Jamie Madill62d31cb2015-09-11 13:25:51 -04001450 // Advance the uniform offset, to track registers allocation for structs
1451 sh::BlockMemberInfo blockInfo =
1452 encoder ? encoder->encodeType(uniform.type, uniform.arraySize, false)
1453 : sh::BlockMemberInfo::getDefaultBlockInfo();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001454
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001455 auto uniformMapEntry = uniformMap->find(fullName);
1456 D3DUniform *d3dUniform = nullptr;
Jamie Madill2857f482015-02-09 15:35:29 -05001457
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001458 if (uniformMapEntry != uniformMap->end())
Jamie Madill62d31cb2015-09-11 13:25:51 -04001459 {
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001460 d3dUniform = uniformMapEntry->second;
1461 }
1462 else
1463 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001464 d3dUniform = new D3DUniform(uniform.type, fullName, uniform.arraySize, true);
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001465 (*uniformMap)[fullName] = d3dUniform;
Jamie Madill62d31cb2015-09-11 13:25:51 -04001466 }
1467
1468 if (encoder)
1469 {
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001470 d3dUniform->registerElement =
1471 static_cast<unsigned int>(sh::HLSLBlockEncoder::getBlockRegisterElement(blockInfo));
Jamie Madill62d31cb2015-09-11 13:25:51 -04001472 unsigned int reg =
1473 static_cast<unsigned int>(sh::HLSLBlockEncoder::getBlockRegister(blockInfo));
Jamie Madill91445bc2015-09-23 16:47:53 -04001474 if (shaderType == GL_FRAGMENT_SHADER)
Jamie Madill62d31cb2015-09-11 13:25:51 -04001475 {
1476 d3dUniform->psRegisterIndex = reg;
1477 }
Jamie Madill91445bc2015-09-23 16:47:53 -04001478 else
Jamie Madill62d31cb2015-09-11 13:25:51 -04001479 {
Jamie Madill91445bc2015-09-23 16:47:53 -04001480 ASSERT(shaderType == GL_VERTEX_SHADER);
Jamie Madill62d31cb2015-09-11 13:25:51 -04001481 d3dUniform->vsRegisterIndex = reg;
1482 }
Jamie Madillfb536032015-09-11 13:19:49 -04001483
1484 // Arrays are treated as aggregate types
Jamie Madill62d31cb2015-09-11 13:25:51 -04001485 if (uniform.isArray())
Jamie Madillfb536032015-09-11 13:19:49 -04001486 {
1487 encoder->exitAggregateType();
1488 }
1489 }
1490}
1491
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001492template <typename T>
1493static inline void SetIfDirty(T *dest, const T& source, bool *dirtyFlag)
1494{
1495 ASSERT(dest != NULL);
1496 ASSERT(dirtyFlag != NULL);
1497
1498 *dirtyFlag = *dirtyFlag || (memcmp(dest, &source, sizeof(T)) != 0);
1499 *dest = source;
1500}
1501
1502template <typename T>
Jamie Madill62d31cb2015-09-11 13:25:51 -04001503void ProgramD3D::setUniform(GLint location, GLsizei countIn, const T *v, GLenum targetUniformType)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001504{
1505 const int components = gl::VariableComponentCount(targetUniformType);
1506 const GLenum targetBoolType = gl::VariableBoolVectorType(targetUniformType);
1507
Jamie Madill62d31cb2015-09-11 13:25:51 -04001508 D3DUniform *targetUniform = getD3DUniformFromLocation(location);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001509
Jamie Madill62d31cb2015-09-11 13:25:51 -04001510 unsigned int elementCount = targetUniform->elementCount();
1511 unsigned int arrayElement = mData.getUniformLocations()[location].element;
1512 unsigned int count = std::min(elementCount - arrayElement, static_cast<unsigned int>(countIn));
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001513
1514 if (targetUniform->type == targetUniformType)
1515 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001516 T *target = reinterpret_cast<T *>(targetUniform->data) + arrayElement * 4;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001517
Jamie Madill62d31cb2015-09-11 13:25:51 -04001518 for (unsigned int i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001519 {
1520 T *dest = target + (i * 4);
1521 const T *source = v + (i * components);
1522
1523 for (int c = 0; c < components; c++)
1524 {
1525 SetIfDirty(dest + c, source[c], &targetUniform->dirty);
1526 }
1527 for (int c = components; c < 4; c++)
1528 {
1529 SetIfDirty(dest + c, T(0), &targetUniform->dirty);
1530 }
1531 }
1532 }
1533 else if (targetUniform->type == targetBoolType)
1534 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001535 GLint *boolParams = reinterpret_cast<GLint *>(targetUniform->data) + arrayElement * 4;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001536
Jamie Madill62d31cb2015-09-11 13:25:51 -04001537 for (unsigned int i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001538 {
1539 GLint *dest = boolParams + (i * 4);
1540 const T *source = v + (i * components);
1541
1542 for (int c = 0; c < components; c++)
1543 {
1544 SetIfDirty(dest + c, (source[c] == static_cast<T>(0)) ? GL_FALSE : GL_TRUE, &targetUniform->dirty);
1545 }
1546 for (int c = components; c < 4; c++)
1547 {
1548 SetIfDirty(dest + c, GL_FALSE, &targetUniform->dirty);
1549 }
1550 }
1551 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04001552 else if (targetUniform->isSampler())
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001553 {
1554 ASSERT(targetUniformType == GL_INT);
1555
Jamie Madill62d31cb2015-09-11 13:25:51 -04001556 GLint *target = reinterpret_cast<GLint *>(targetUniform->data) + arrayElement * 4;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001557
1558 bool wasDirty = targetUniform->dirty;
1559
Jamie Madill62d31cb2015-09-11 13:25:51 -04001560 for (unsigned int i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001561 {
1562 GLint *dest = target + (i * 4);
1563 const GLint *source = reinterpret_cast<const GLint*>(v) + (i * components);
1564
1565 SetIfDirty(dest + 0, source[0], &targetUniform->dirty);
1566 SetIfDirty(dest + 1, 0, &targetUniform->dirty);
1567 SetIfDirty(dest + 2, 0, &targetUniform->dirty);
1568 SetIfDirty(dest + 3, 0, &targetUniform->dirty);
1569 }
1570
1571 if (!wasDirty && targetUniform->dirty)
1572 {
1573 mDirtySamplerMapping = true;
1574 }
Brandon Jones18bd4102014-09-22 14:21:44 -07001575 }
1576 else UNREACHABLE();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001577}
Brandon Jones18bd4102014-09-22 14:21:44 -07001578
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001579template<typename T>
1580bool transposeMatrix(T *target, const GLfloat *value, int targetWidth, int targetHeight, int srcWidth, int srcHeight)
1581{
1582 bool dirty = false;
1583 int copyWidth = std::min(targetHeight, srcWidth);
1584 int copyHeight = std::min(targetWidth, srcHeight);
1585
1586 for (int x = 0; x < copyWidth; x++)
1587 {
1588 for (int y = 0; y < copyHeight; y++)
1589 {
1590 SetIfDirty(target + (x * targetWidth + y), static_cast<T>(value[y * srcWidth + x]), &dirty);
1591 }
1592 }
1593 // clear unfilled right side
1594 for (int y = 0; y < copyWidth; y++)
1595 {
1596 for (int x = copyHeight; x < targetWidth; x++)
1597 {
1598 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
1599 }
1600 }
1601 // clear unfilled bottom.
1602 for (int y = copyWidth; y < targetHeight; y++)
1603 {
1604 for (int x = 0; x < targetWidth; x++)
1605 {
1606 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
1607 }
1608 }
1609
1610 return dirty;
1611}
1612
1613template<typename T>
1614bool expandMatrix(T *target, const GLfloat *value, int targetWidth, int targetHeight, int srcWidth, int srcHeight)
1615{
1616 bool dirty = false;
1617 int copyWidth = std::min(targetWidth, srcWidth);
1618 int copyHeight = std::min(targetHeight, srcHeight);
1619
1620 for (int y = 0; y < copyHeight; y++)
1621 {
1622 for (int x = 0; x < copyWidth; x++)
1623 {
1624 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(value[y * srcWidth + x]), &dirty);
1625 }
1626 }
1627 // clear unfilled right side
1628 for (int y = 0; y < copyHeight; y++)
1629 {
1630 for (int x = copyWidth; x < targetWidth; x++)
1631 {
1632 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
1633 }
1634 }
1635 // clear unfilled bottom.
1636 for (int y = copyHeight; y < targetHeight; y++)
1637 {
1638 for (int x = 0; x < targetWidth; x++)
1639 {
1640 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
1641 }
1642 }
1643
1644 return dirty;
1645}
1646
1647template <int cols, int rows>
Jamie Madill62d31cb2015-09-11 13:25:51 -04001648void ProgramD3D::setUniformMatrixfv(GLint location,
1649 GLsizei countIn,
1650 GLboolean transpose,
1651 const GLfloat *value,
1652 GLenum targetUniformType)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001653{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001654 D3DUniform *targetUniform = getD3DUniformFromLocation(location);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001655
Jamie Madill62d31cb2015-09-11 13:25:51 -04001656 unsigned int elementCount = targetUniform->elementCount();
1657 unsigned int arrayElement = mData.getUniformLocations()[location].element;
1658 unsigned int count = std::min(elementCount - arrayElement, static_cast<unsigned int>(countIn));
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001659
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001660 const unsigned int targetMatrixStride = (4 * rows);
Jamie Madill62d31cb2015-09-11 13:25:51 -04001661 GLfloat *target =
1662 (GLfloat *)(targetUniform->data + arrayElement * sizeof(GLfloat) * targetMatrixStride);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001663
Jamie Madill62d31cb2015-09-11 13:25:51 -04001664 for (unsigned int i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001665 {
1666 // Internally store matrices as transposed versions to accomodate HLSL matrix indexing
1667 if (transpose == GL_FALSE)
1668 {
1669 targetUniform->dirty = transposeMatrix<GLfloat>(target, value, 4, rows, rows, cols) || targetUniform->dirty;
1670 }
1671 else
1672 {
1673 targetUniform->dirty = expandMatrix<GLfloat>(target, value, 4, rows, cols, rows) || targetUniform->dirty;
1674 }
1675 target += targetMatrixStride;
1676 value += cols * rows;
1677 }
1678}
1679
Jamie Madill62d31cb2015-09-11 13:25:51 -04001680size_t ProgramD3D::defineUniformBlock(const sh::InterfaceBlock &interfaceBlock,
1681 BlockInfoMap *blockInfoOut)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001682{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001683 ASSERT(interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001684
Jamie Madill62d31cb2015-09-11 13:25:51 -04001685 // define member uniforms
1686 sh::Std140BlockEncoder std140Encoder;
1687 sh::HLSLBlockEncoder hlslEncoder(sh::HLSLBlockEncoder::ENCODE_PACKED);
1688 sh::BlockLayoutEncoder *encoder = nullptr;
1689
1690 if (interfaceBlock.layout == sh::BLOCKLAYOUT_STANDARD)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001691 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001692 encoder = &std140Encoder;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001693 }
1694 else
1695 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001696 encoder = &hlslEncoder;
Jamie Madill61b8dd92015-09-09 19:04:04 +00001697 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04001698
1699 GetUniformBlockInfo(interfaceBlock.fields, "", encoder, interfaceBlock.isRowMajorLayout,
1700 blockInfoOut);
1701
1702 return encoder->getBlockSize();
Jamie Madill61b8dd92015-09-09 19:04:04 +00001703}
1704
Jamie Madill62d31cb2015-09-11 13:25:51 -04001705void ProgramD3D::assignAllSamplerRegisters()
Jamie Madilla2eb02c2015-09-11 12:31:41 +00001706{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001707 for (const D3DUniform *d3dUniform : mD3DUniforms)
Jamie Madilla2eb02c2015-09-11 12:31:41 +00001708 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001709 if (d3dUniform->isSampler())
Jamie Madillfb536032015-09-11 13:19:49 -04001710 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001711 assignSamplerRegisters(d3dUniform);
Jamie Madillfb536032015-09-11 13:19:49 -04001712 }
Jamie Madilla2eb02c2015-09-11 12:31:41 +00001713 }
1714}
1715
Jamie Madill62d31cb2015-09-11 13:25:51 -04001716void ProgramD3D::assignSamplerRegisters(const D3DUniform *d3dUniform)
Jamie Madillfb536032015-09-11 13:19:49 -04001717{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001718 ASSERT(d3dUniform->isSampler());
1719 ASSERT(d3dUniform->vsRegisterIndex != GL_INVALID_INDEX ||
1720 d3dUniform->psRegisterIndex != GL_INVALID_INDEX);
Jamie Madillfb536032015-09-11 13:19:49 -04001721
Jamie Madill62d31cb2015-09-11 13:25:51 -04001722 if (d3dUniform->vsRegisterIndex != GL_INVALID_INDEX)
Jamie Madillfb536032015-09-11 13:19:49 -04001723 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001724 AssignSamplers(d3dUniform->vsRegisterIndex, d3dUniform->type, d3dUniform->arraySize,
1725 mSamplersVS, &mUsedVertexSamplerRange);
Jamie Madillfb536032015-09-11 13:19:49 -04001726 }
1727
Jamie Madill62d31cb2015-09-11 13:25:51 -04001728 if (d3dUniform->psRegisterIndex != GL_INVALID_INDEX)
Jamie Madillfb536032015-09-11 13:19:49 -04001729 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001730 AssignSamplers(d3dUniform->psRegisterIndex, d3dUniform->type, d3dUniform->arraySize,
1731 mSamplersPS, &mUsedPixelSamplerRange);
Jamie Madillfb536032015-09-11 13:19:49 -04001732 }
1733}
1734
Jamie Madill62d31cb2015-09-11 13:25:51 -04001735// static
1736void ProgramD3D::AssignSamplers(unsigned int startSamplerIndex,
Jamie Madilld3dfda22015-07-06 08:28:49 -04001737 GLenum samplerType,
1738 unsigned int samplerCount,
1739 std::vector<Sampler> &outSamplers,
1740 GLuint *outUsedRange)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001741{
1742 unsigned int samplerIndex = startSamplerIndex;
1743
1744 do
1745 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001746 ASSERT(samplerIndex < outSamplers.size());
1747 Sampler *sampler = &outSamplers[samplerIndex];
1748 sampler->active = true;
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001749 sampler->textureType = gl::SamplerTypeToTextureType(samplerType);
Jamie Madill62d31cb2015-09-11 13:25:51 -04001750 sampler->logicalTextureUnit = 0;
1751 *outUsedRange = std::max(samplerIndex + 1, *outUsedRange);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001752 samplerIndex++;
1753 } while (samplerIndex < startSamplerIndex + samplerCount);
Brandon Jones18bd4102014-09-22 14:21:44 -07001754}
1755
Brandon Jonesc9610c52014-08-25 17:02:59 -07001756void ProgramD3D::reset()
1757{
Brandon Joneseb994362014-09-24 10:27:28 -07001758 SafeDeleteContainer(mVertexExecutables);
1759 SafeDeleteContainer(mPixelExecutables);
1760 SafeDelete(mGeometryExecutable);
1761
Brandon Jones22502d52014-08-29 16:58:36 -07001762 mVertexHLSL.clear();
Geoff Lang6941a552015-07-27 11:06:45 -04001763 mVertexWorkarounds = D3DCompilerWorkarounds();
Brandon Jones22502d52014-08-29 16:58:36 -07001764
1765 mPixelHLSL.clear();
Geoff Lang6941a552015-07-27 11:06:45 -04001766 mPixelWorkarounds = D3DCompilerWorkarounds();
Brandon Jones22502d52014-08-29 16:58:36 -07001767 mUsesFragDepth = false;
1768 mPixelShaderKey.clear();
Brandon Jones44151a92014-09-10 11:32:25 -07001769 mUsesPointSize = false;
Brandon Jones22502d52014-08-29 16:58:36 -07001770
Jamie Madill62d31cb2015-09-11 13:25:51 -04001771 SafeDeleteContainer(mD3DUniforms);
1772
Brandon Jonesc9610c52014-08-25 17:02:59 -07001773 SafeDelete(mVertexUniformStorage);
1774 SafeDelete(mFragmentUniformStorage);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001775
1776 mSamplersPS.clear();
1777 mSamplersVS.clear();
1778
1779 mUsedVertexSamplerRange = 0;
1780 mUsedPixelSamplerRange = 0;
1781 mDirtySamplerMapping = true;
Jamie Madill437d2662014-12-05 14:23:35 -05001782
Jamie Madill63805b42015-08-25 13:17:39 -04001783 std::fill(mSemanticIndexes, mSemanticIndexes + ArraySize(mSemanticIndexes), -1);
Jamie Madill437d2662014-12-05 14:23:35 -05001784 std::fill(mAttributesByLayout, mAttributesByLayout + ArraySize(mAttributesByLayout), -1);
Jamie Madillccdf74b2015-08-18 10:46:12 -04001785
1786 mTransformFeedbackLinkedVaryings.clear();
Brandon Jonesc9610c52014-08-25 17:02:59 -07001787}
1788
Geoff Lang7dd2e102014-11-10 15:19:26 -05001789unsigned int ProgramD3D::getSerial() const
1790{
1791 return mSerial;
1792}
1793
1794unsigned int ProgramD3D::issueSerial()
1795{
1796 return mCurrentSerial++;
1797}
1798
Jamie Madill63805b42015-08-25 13:17:39 -04001799void ProgramD3D::initSemanticIndex()
1800{
1801 const gl::Shader *vertexShader = mData.getAttachedVertexShader();
1802 ASSERT(vertexShader != nullptr);
1803
1804 // Init semantic index
1805 for (const sh::Attribute &attribute : mData.getAttributes())
1806 {
1807 int attributeIndex = attribute.location;
1808 int index = vertexShader->getSemanticIndex(attribute.name);
1809 int regs = gl::VariableRegisterCount(attribute.type);
1810
1811 for (int reg = 0; reg < regs; ++reg)
1812 {
1813 mSemanticIndexes[attributeIndex + reg] = index + reg;
1814 }
1815 }
1816
1817 initAttributesByLayout();
1818}
1819
Jamie Madill437d2662014-12-05 14:23:35 -05001820void ProgramD3D::initAttributesByLayout()
1821{
1822 for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
1823 {
1824 mAttributesByLayout[i] = i;
1825 }
1826
Jamie Madill63805b42015-08-25 13:17:39 -04001827 std::sort(&mAttributesByLayout[0], &mAttributesByLayout[gl::MAX_VERTEX_ATTRIBS],
1828 AttributeSorter(mSemanticIndexes));
Jamie Madill437d2662014-12-05 14:23:35 -05001829}
1830
Jamie Madill476682e2015-06-30 10:04:29 -04001831void ProgramD3D::sortAttributesByLayout(const std::vector<TranslatedAttribute> &unsortedAttributes,
Jamie Madillf9327d32015-06-22 13:57:16 -04001832 int sortedSemanticIndicesOut[gl::MAX_VERTEX_ATTRIBS],
1833 const rx::TranslatedAttribute *sortedAttributesOut[gl::MAX_VERTEX_ATTRIBS]) const
Jamie Madill437d2662014-12-05 14:23:35 -05001834{
Jamie Madill476682e2015-06-30 10:04:29 -04001835 for (size_t attribIndex = 0; attribIndex < unsortedAttributes.size(); ++attribIndex)
Jamie Madill437d2662014-12-05 14:23:35 -05001836 {
Jamie Madill476682e2015-06-30 10:04:29 -04001837 int oldIndex = mAttributesByLayout[attribIndex];
Jamie Madill63805b42015-08-25 13:17:39 -04001838 sortedSemanticIndicesOut[attribIndex] = mSemanticIndexes[oldIndex];
Jamie Madill476682e2015-06-30 10:04:29 -04001839 sortedAttributesOut[attribIndex] = &unsortedAttributes[oldIndex];
Jamie Madill437d2662014-12-05 14:23:35 -05001840 }
1841}
1842
Jamie Madill63805b42015-08-25 13:17:39 -04001843void ProgramD3D::updateCachedInputLayout(const gl::State &state)
Jamie Madilld3dfda22015-07-06 08:28:49 -04001844{
Jamie Madillbd136f92015-08-10 14:51:37 -04001845 mCachedInputLayout.clear();
Jamie Madilld3dfda22015-07-06 08:28:49 -04001846 const auto &vertexAttributes = state.getVertexArray()->getVertexAttributes();
Jamie Madillf8dd7b12015-08-05 13:50:08 -04001847
Dian Xianga4928832015-09-15 10:11:17 -07001848 for (unsigned int attributeIndex : angle::IterateBitSet(mData.getActiveAttribLocationsMask()))
Jamie Madilld3dfda22015-07-06 08:28:49 -04001849 {
Jamie Madill63805b42015-08-25 13:17:39 -04001850 int semanticIndex = mSemanticIndexes[attributeIndex];
Jamie Madilld3dfda22015-07-06 08:28:49 -04001851
1852 if (semanticIndex != -1)
1853 {
Jamie Madillbd136f92015-08-10 14:51:37 -04001854 if (mCachedInputLayout.size() < static_cast<size_t>(semanticIndex + 1))
1855 {
1856 mCachedInputLayout.resize(semanticIndex + 1, gl::VERTEX_FORMAT_INVALID);
1857 }
Jamie Madilld3dfda22015-07-06 08:28:49 -04001858 mCachedInputLayout[semanticIndex] =
1859 GetVertexFormatType(vertexAttributes[attributeIndex],
1860 state.getVertexAttribCurrentValue(attributeIndex).Type);
1861 }
1862 }
1863}
1864
Jamie Madillccdf74b2015-08-18 10:46:12 -04001865void ProgramD3D::gatherTransformFeedbackVaryings(
1866 const std::vector<gl::LinkedVarying> &linkedVaryings)
1867{
1868 // Gather the linked varyings that are used for transform feedback, they should all exist.
1869 mTransformFeedbackLinkedVaryings.clear();
1870 for (const std::string &tfVaryingName : mData.getTransformFeedbackVaryingNames())
1871 {
1872 for (const gl::LinkedVarying &linkedVarying : linkedVaryings)
1873 {
1874 if (tfVaryingName == linkedVarying.name)
1875 {
1876 mTransformFeedbackLinkedVaryings.push_back(linkedVarying);
1877 break;
1878 }
1879 }
1880 }
1881}
Jamie Madill62d31cb2015-09-11 13:25:51 -04001882
1883D3DUniform *ProgramD3D::getD3DUniformFromLocation(GLint location)
1884{
1885 return mD3DUniforms[mData.getUniformLocations()[location].index];
1886}
Brandon Jonesc9610c52014-08-25 17:02:59 -07001887}