blob: 86d17cb2d4adf5c9d8c9a6399d7e24ef6de871c4 [file] [log] [blame]
Geoff Langf9a6f082015-01-22 13:32:49 -05001//
2// Copyright 2015 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// ProgramGL.cpp: Implements the class methods for ProgramGL.
8
9#include "libANGLE/renderer/gl/ProgramGL.h"
10
Sami Väisänen46eaa942016-06-29 10:26:37 +030011#include "common/angleutils.h"
Jamie Madillc564c072017-06-01 12:45:42 -040012#include "common/bitset_utils.h"
Geoff Langf9a6f082015-01-22 13:32:49 -050013#include "common/debug.h"
Sami Väisänen46eaa942016-06-29 10:26:37 +030014#include "common/string_utils.h"
Geoff Lang5ed74cf2015-04-14 13:57:07 -040015#include "common/utilities.h"
Jamie Madillc564c072017-06-01 12:45:42 -040016#include "libANGLE/Context.h"
Jamie Madill6db1c2e2017-11-08 09:17:40 -050017#include "libANGLE/ProgramLinkedResources.h"
Jamie Madillc564c072017-06-01 12:45:42 -040018#include "libANGLE/Uniform.h"
Geoff Lang92019432017-11-20 13:09:34 -050019#include "libANGLE/queryconversions.h"
Jamie Madilla7d12dc2016-12-13 15:08:19 -050020#include "libANGLE/renderer/gl/ContextGL.h"
Geoff Langb1f435e2015-02-20 10:01:01 -050021#include "libANGLE/renderer/gl/FunctionsGL.h"
22#include "libANGLE/renderer/gl/ShaderGL.h"
23#include "libANGLE/renderer/gl/StateManagerGL.h"
Philippe Hamel40911192016-04-07 16:45:50 -040024#include "libANGLE/renderer/gl/WorkaroundsGL.h"
unknownb4a3af22015-11-25 15:02:51 -050025#include "platform/Platform.h"
Geoff Langf9a6f082015-01-22 13:32:49 -050026
27namespace rx
28{
29
Jamie Madill48ef11b2016-04-27 15:21:52 -040030ProgramGL::ProgramGL(const gl::ProgramState &data,
Jamie Madill5c6b7bf2015-08-17 12:53:35 -040031 const FunctionsGL *functions,
Philippe Hamel40911192016-04-07 16:45:50 -040032 const WorkaroundsGL &workarounds,
Sami Väisänen46eaa942016-06-29 10:26:37 +030033 StateManagerGL *stateManager,
34 bool enablePathRendering)
Philippe Hamel40911192016-04-07 16:45:50 -040035 : ProgramImpl(data),
36 mFunctions(functions),
37 mWorkarounds(workarounds),
38 mStateManager(stateManager),
Sami Väisänen46eaa942016-06-29 10:26:37 +030039 mEnablePathRendering(enablePathRendering),
Martin Radev4e619f52017-08-09 11:50:06 +030040 mMultiviewBaseViewLayerIndexUniformLocation(-1),
Philippe Hamel40911192016-04-07 16:45:50 -040041 mProgramID(0)
Geoff Langb1f435e2015-02-20 10:01:01 -050042{
43 ASSERT(mFunctions);
44 ASSERT(mStateManager);
Geoff Lang0ca53782015-05-07 13:49:39 -040045
46 mProgramID = mFunctions->createProgram();
Geoff Langb1f435e2015-02-20 10:01:01 -050047}
Geoff Langf9a6f082015-01-22 13:32:49 -050048
49ProgramGL::~ProgramGL()
Geoff Langb1f435e2015-02-20 10:01:01 -050050{
Geoff Lang0ca53782015-05-07 13:49:39 -040051 mFunctions->deleteProgram(mProgramID);
52 mProgramID = 0;
Geoff Langb1f435e2015-02-20 10:01:01 -050053}
Geoff Langf9a6f082015-01-22 13:32:49 -050054
Jamie Madill9cf9e872017-06-05 12:59:25 -040055gl::LinkResult ProgramGL::load(const gl::Context *context,
56 gl::InfoLog &infoLog,
57 gl::BinaryInputStream *stream)
Geoff Langf9a6f082015-01-22 13:32:49 -050058{
Geoff Lang65a0be92015-10-02 09:57:30 -040059 preLink();
60
61 // Read the binary format, size and blob
62 GLenum binaryFormat = stream->readInt<GLenum>();
63 GLint binaryLength = stream->readInt<GLint>();
64 const uint8_t *binary = stream->data() + stream->offset();
65 stream->skip(binaryLength);
66
67 // Load the binary
68 mFunctions->programBinary(mProgramID, binaryFormat, binary, binaryLength);
69
70 // Verify that the program linked
71 if (!checkLinkStatus(infoLog))
72 {
Jamie Madillb0a838b2016-11-13 20:02:12 -050073 return false;
Geoff Lang65a0be92015-10-02 09:57:30 -040074 }
75
76 postLink();
Jamie Madill27a60632017-06-30 15:12:01 -040077 reapplyUBOBindingsIfNeeded(context);
Jamie Madilla7d12dc2016-12-13 15:08:19 -050078
Jamie Madillb0a838b2016-11-13 20:02:12 -050079 return true;
Geoff Langf9a6f082015-01-22 13:32:49 -050080}
81
Jamie Madill27a60632017-06-30 15:12:01 -040082void ProgramGL::save(const gl::Context *context, gl::BinaryOutputStream *stream)
Geoff Langf9a6f082015-01-22 13:32:49 -050083{
Geoff Lang65a0be92015-10-02 09:57:30 -040084 GLint binaryLength = 0;
85 mFunctions->getProgramiv(mProgramID, GL_PROGRAM_BINARY_LENGTH, &binaryLength);
86
Geoff Lang416a23e2017-11-20 12:34:20 -050087 std::vector<uint8_t> binary(std::max(binaryLength, 1));
Geoff Lang65a0be92015-10-02 09:57:30 -040088 GLenum binaryFormat = GL_NONE;
89 mFunctions->getProgramBinary(mProgramID, binaryLength, &binaryLength, &binaryFormat,
Geoff Lang416a23e2017-11-20 12:34:20 -050090 binary.data());
Geoff Lang65a0be92015-10-02 09:57:30 -040091
92 stream->writeInt(binaryFormat);
93 stream->writeInt(binaryLength);
Geoff Lang416a23e2017-11-20 12:34:20 -050094 stream->writeBytes(binary.data(), binaryLength);
Jamie Madill27a60632017-06-30 15:12:01 -040095
96 reapplyUBOBindingsIfNeeded(context);
97}
98
99void ProgramGL::reapplyUBOBindingsIfNeeded(const gl::Context *context)
100{
101 // Re-apply UBO bindings to work around driver bugs.
102 const WorkaroundsGL &workaroundsGL = GetImplAs<ContextGL>(context)->getWorkaroundsGL();
103 if (workaroundsGL.reapplyUBOBindingsAfterUsingBinaryProgram)
104 {
105 const auto &blocks = mState.getUniformBlocks();
106 for (size_t blockIndex : mState.getActiveUniformBlockBindingsMask())
107 {
108 setUniformBlockBinding(static_cast<GLuint>(blockIndex), blocks[blockIndex].binding);
109 }
110 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500111}
112
Geoff Langc5629752015-12-07 16:29:04 -0500113void ProgramGL::setBinaryRetrievableHint(bool retrievable)
114{
Geoff Lang65a0be92015-10-02 09:57:30 -0400115 // glProgramParameteri isn't always available on ES backends.
116 if (mFunctions->programParameteri)
117 {
118 mFunctions->programParameteri(mProgramID, GL_PROGRAM_BINARY_RETRIEVABLE_HINT,
119 retrievable ? GL_TRUE : GL_FALSE);
120 }
Geoff Langc5629752015-12-07 16:29:04 -0500121}
122
Yunchao He61afff12017-03-14 15:34:03 +0800123void ProgramGL::setSeparable(bool separable)
124{
125 mFunctions->programParameteri(mProgramID, GL_PROGRAM_SEPARABLE, separable ? GL_TRUE : GL_FALSE);
126}
127
Jamie Madill9cf9e872017-06-05 12:59:25 -0400128gl::LinkResult ProgramGL::link(const gl::Context *context,
Jamie Madillc9727f32017-11-07 12:37:07 -0500129 const gl::ProgramLinkedResources &resources,
Jamie Madill9cf9e872017-06-05 12:59:25 -0400130 gl::InfoLog &infoLog)
Geoff Langf9a6f082015-01-22 13:32:49 -0500131{
Geoff Lang65a0be92015-10-02 09:57:30 -0400132 preLink();
Geoff Langb1f435e2015-02-20 10:01:01 -0500133
Martin Radev4c4c8e72016-08-04 12:25:34 +0300134 if (mState.getAttachedComputeShader())
Geoff Lang1a683462015-09-29 15:09:59 -0400135 {
Martin Radev4c4c8e72016-08-04 12:25:34 +0300136 const ShaderGL *computeShaderGL = GetImplAs<ShaderGL>(mState.getAttachedComputeShader());
Geoff Lang1a683462015-09-29 15:09:59 -0400137
Martin Radev4c4c8e72016-08-04 12:25:34 +0300138 mFunctions->attachShader(mProgramID, computeShaderGL->getShaderID());
139
140 // Link and verify
141 mFunctions->linkProgram(mProgramID);
142
143 // Detach the shaders
144 mFunctions->detachShader(mProgramID, computeShaderGL->getShaderID());
Geoff Lang1a683462015-09-29 15:09:59 -0400145 }
146 else
147 {
Martin Radev4c4c8e72016-08-04 12:25:34 +0300148 // Set the transform feedback state
Olli Etuaho855d9642017-05-17 14:05:06 +0300149 std::vector<std::string> transformFeedbackVaryingMappedNames;
Martin Radev4c4c8e72016-08-04 12:25:34 +0300150 for (const auto &tfVarying : mState.getTransformFeedbackVaryingNames())
Geoff Lang1528e562015-08-24 15:10:58 -0400151 {
Olli Etuaho855d9642017-05-17 14:05:06 +0300152 std::string tfVaryingMappedName =
153 mState.getAttachedVertexShader()->getTransformFeedbackVaryingMappedName(tfVarying,
154 context);
155 transformFeedbackVaryingMappedNames.push_back(tfVaryingMappedName);
Geoff Lang1528e562015-08-24 15:10:58 -0400156 }
157
Olli Etuaho855d9642017-05-17 14:05:06 +0300158 if (transformFeedbackVaryingMappedNames.empty())
Martin Radev4c4c8e72016-08-04 12:25:34 +0300159 {
160 if (mFunctions->transformFeedbackVaryings)
161 {
162 mFunctions->transformFeedbackVaryings(mProgramID, 0, nullptr,
163 mState.getTransformFeedbackBufferMode());
164 }
165 }
166 else
167 {
168 ASSERT(mFunctions->transformFeedbackVaryings);
Olli Etuaho855d9642017-05-17 14:05:06 +0300169 std::vector<const GLchar *> transformFeedbackVaryings;
170 for (const auto &varying : transformFeedbackVaryingMappedNames)
171 {
172 transformFeedbackVaryings.push_back(varying.c_str());
173 }
Martin Radev4c4c8e72016-08-04 12:25:34 +0300174 mFunctions->transformFeedbackVaryings(
Olli Etuaho855d9642017-05-17 14:05:06 +0300175 mProgramID, static_cast<GLsizei>(transformFeedbackVaryingMappedNames.size()),
Martin Radev4c4c8e72016-08-04 12:25:34 +0300176 &transformFeedbackVaryings[0], mState.getTransformFeedbackBufferMode());
177 }
178
179 const ShaderGL *vertexShaderGL = GetImplAs<ShaderGL>(mState.getAttachedVertexShader());
180 const ShaderGL *fragmentShaderGL = GetImplAs<ShaderGL>(mState.getAttachedFragmentShader());
Jiawei Shao4ed05da2018-02-02 14:26:15 +0800181 const ShaderGL *geometryShaderGL =
182 rx::SafeGetImplAs<ShaderGL, gl::Shader>(mState.getAttachedGeometryShader());
Martin Radev4c4c8e72016-08-04 12:25:34 +0300183
184 // Attach the shaders
185 mFunctions->attachShader(mProgramID, vertexShaderGL->getShaderID());
186 mFunctions->attachShader(mProgramID, fragmentShaderGL->getShaderID());
Jiawei Shao4ed05da2018-02-02 14:26:15 +0800187 if (geometryShaderGL)
188 {
189 mFunctions->attachShader(mProgramID, geometryShaderGL->getShaderID());
190 }
Martin Radev4c4c8e72016-08-04 12:25:34 +0300191
192 // Bind attribute locations to match the GL layer.
193 for (const sh::Attribute &attribute : mState.getAttributes())
194 {
Corentin Wallez6c1cbf52016-11-23 12:44:35 -0500195 if (!attribute.staticUse || attribute.isBuiltIn())
Martin Radev4c4c8e72016-08-04 12:25:34 +0300196 {
197 continue;
198 }
199
Olli Etuaho855d9642017-05-17 14:05:06 +0300200 mFunctions->bindAttribLocation(mProgramID, attribute.location,
201 attribute.mappedName.c_str());
Martin Radev4c4c8e72016-08-04 12:25:34 +0300202 }
203
204 // Link and verify
205 mFunctions->linkProgram(mProgramID);
206
207 // Detach the shaders
208 mFunctions->detachShader(mProgramID, vertexShaderGL->getShaderID());
209 mFunctions->detachShader(mProgramID, fragmentShaderGL->getShaderID());
Jiawei Shao4ed05da2018-02-02 14:26:15 +0800210 if (geometryShaderGL)
211 {
212 mFunctions->detachShader(mProgramID, geometryShaderGL->getShaderID());
213 }
Geoff Lang1528e562015-08-24 15:10:58 -0400214 }
215
Geoff Lang0ca53782015-05-07 13:49:39 -0400216 // Verify the link
Geoff Lang65a0be92015-10-02 09:57:30 -0400217 if (!checkLinkStatus(infoLog))
Geoff Langb1f435e2015-02-20 10:01:01 -0500218 {
Jamie Madillb0a838b2016-11-13 20:02:12 -0500219 return false;
Geoff Langb1f435e2015-02-20 10:01:01 -0500220 }
221
Philippe Hamel40911192016-04-07 16:45:50 -0400222 if (mWorkarounds.alwaysCallUseProgramAfterLink)
223 {
224 mStateManager->forceUseProgram(mProgramID);
225 }
226
Jamie Madill6db1c2e2017-11-08 09:17:40 -0500227 linkResources(resources);
Geoff Lang65a0be92015-10-02 09:57:30 -0400228 postLink();
Geoff Langb1f435e2015-02-20 10:01:01 -0500229
Jamie Madillb0a838b2016-11-13 20:02:12 -0500230 return true;
Geoff Langf9a6f082015-01-22 13:32:49 -0500231}
232
Jamie Madill36cfd6a2015-08-18 10:46:20 -0400233GLboolean ProgramGL::validate(const gl::Caps & /*caps*/, gl::InfoLog * /*infoLog*/)
234{
235 // TODO(jmadill): implement validate
236 return true;
237}
238
Geoff Langf9a6f082015-01-22 13:32:49 -0500239void ProgramGL::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
240{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800241 if (mFunctions->programUniform1fv != nullptr)
242 {
243 mFunctions->programUniform1fv(mProgramID, uniLoc(location), count, v);
244 }
245 else
246 {
247 mStateManager->useProgram(mProgramID);
248 mFunctions->uniform1fv(uniLoc(location), count, v);
249 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500250}
251
252void ProgramGL::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
253{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800254 if (mFunctions->programUniform2fv != nullptr)
255 {
256 mFunctions->programUniform2fv(mProgramID, uniLoc(location), count, v);
257 }
258 else
259 {
260 mStateManager->useProgram(mProgramID);
261 mFunctions->uniform2fv(uniLoc(location), count, v);
262 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500263}
264
265void ProgramGL::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
266{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800267 if (mFunctions->programUniform3fv != nullptr)
268 {
269 mFunctions->programUniform3fv(mProgramID, uniLoc(location), count, v);
270 }
271 else
272 {
273 mStateManager->useProgram(mProgramID);
274 mFunctions->uniform3fv(uniLoc(location), count, v);
275 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500276}
277
278void ProgramGL::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
279{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800280 if (mFunctions->programUniform4fv != nullptr)
281 {
282 mFunctions->programUniform4fv(mProgramID, uniLoc(location), count, v);
283 }
284 else
285 {
286 mStateManager->useProgram(mProgramID);
287 mFunctions->uniform4fv(uniLoc(location), count, v);
288 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500289}
290
291void ProgramGL::setUniform1iv(GLint location, GLsizei count, const GLint *v)
292{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800293 if (mFunctions->programUniform1iv != nullptr)
294 {
295 mFunctions->programUniform1iv(mProgramID, uniLoc(location), count, v);
296 }
297 else
298 {
299 mStateManager->useProgram(mProgramID);
300 mFunctions->uniform1iv(uniLoc(location), count, v);
301 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500302}
303
304void ProgramGL::setUniform2iv(GLint location, GLsizei count, const GLint *v)
305{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800306 if (mFunctions->programUniform2iv != nullptr)
307 {
308 mFunctions->programUniform2iv(mProgramID, uniLoc(location), count, v);
309 }
310 else
311 {
312 mStateManager->useProgram(mProgramID);
313 mFunctions->uniform2iv(uniLoc(location), count, v);
314 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500315}
316
317void ProgramGL::setUniform3iv(GLint location, GLsizei count, const GLint *v)
318{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800319 if (mFunctions->programUniform3iv != nullptr)
320 {
321 mFunctions->programUniform3iv(mProgramID, uniLoc(location), count, v);
322 }
323 else
324 {
325 mStateManager->useProgram(mProgramID);
326 mFunctions->uniform3iv(uniLoc(location), count, v);
327 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500328}
329
330void ProgramGL::setUniform4iv(GLint location, GLsizei count, const GLint *v)
331{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800332 if (mFunctions->programUniform4iv != nullptr)
333 {
334 mFunctions->programUniform4iv(mProgramID, uniLoc(location), count, v);
335 }
336 else
337 {
338 mStateManager->useProgram(mProgramID);
339 mFunctions->uniform4iv(uniLoc(location), count, v);
340 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500341}
342
343void ProgramGL::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
344{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800345 if (mFunctions->programUniform1uiv != nullptr)
346 {
347 mFunctions->programUniform1uiv(mProgramID, uniLoc(location), count, v);
348 }
349 else
350 {
351 mStateManager->useProgram(mProgramID);
352 mFunctions->uniform1uiv(uniLoc(location), count, v);
353 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500354}
355
356void ProgramGL::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
357{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800358 if (mFunctions->programUniform2uiv != nullptr)
359 {
360 mFunctions->programUniform2uiv(mProgramID, uniLoc(location), count, v);
361 }
362 else
363 {
364 mStateManager->useProgram(mProgramID);
365 mFunctions->uniform2uiv(uniLoc(location), count, v);
366 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500367}
368
369void ProgramGL::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
370{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800371 if (mFunctions->programUniform3uiv != nullptr)
372 {
373 mFunctions->programUniform3uiv(mProgramID, uniLoc(location), count, v);
374 }
375 else
376 {
377 mStateManager->useProgram(mProgramID);
378 mFunctions->uniform3uiv(uniLoc(location), count, v);
379 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500380}
381
382void ProgramGL::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
383{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800384 if (mFunctions->programUniform4uiv != nullptr)
385 {
386 mFunctions->programUniform4uiv(mProgramID, uniLoc(location), count, v);
387 }
388 else
389 {
390 mStateManager->useProgram(mProgramID);
391 mFunctions->uniform4uiv(uniLoc(location), count, v);
392 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500393}
394
395void ProgramGL::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
396{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800397 if (mFunctions->programUniformMatrix2fv != nullptr)
398 {
399 mFunctions->programUniformMatrix2fv(mProgramID, uniLoc(location), count, transpose, value);
400 }
401 else
402 {
403 mStateManager->useProgram(mProgramID);
404 mFunctions->uniformMatrix2fv(uniLoc(location), count, transpose, value);
405 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500406}
407
408void ProgramGL::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
409{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800410 if (mFunctions->programUniformMatrix3fv != nullptr)
411 {
412 mFunctions->programUniformMatrix3fv(mProgramID, uniLoc(location), count, transpose, value);
413 }
414 else
415 {
416 mStateManager->useProgram(mProgramID);
417 mFunctions->uniformMatrix3fv(uniLoc(location), count, transpose, value);
418 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500419}
420
421void ProgramGL::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
422{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800423 if (mFunctions->programUniformMatrix4fv != nullptr)
424 {
425 mFunctions->programUniformMatrix4fv(mProgramID, uniLoc(location), count, transpose, value);
426 }
427 else
428 {
429 mStateManager->useProgram(mProgramID);
430 mFunctions->uniformMatrix4fv(uniLoc(location), count, transpose, value);
431 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500432}
433
434void ProgramGL::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
435{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800436 if (mFunctions->programUniformMatrix2x3fv != nullptr)
437 {
438 mFunctions->programUniformMatrix2x3fv(mProgramID, uniLoc(location), count, transpose,
439 value);
440 }
441 else
442 {
443 mStateManager->useProgram(mProgramID);
444 mFunctions->uniformMatrix2x3fv(uniLoc(location), count, transpose, value);
445 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500446}
447
448void ProgramGL::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
449{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800450 if (mFunctions->programUniformMatrix3x2fv != nullptr)
451 {
452 mFunctions->programUniformMatrix3x2fv(mProgramID, uniLoc(location), count, transpose,
453 value);
454 }
455 else
456 {
457 mStateManager->useProgram(mProgramID);
458 mFunctions->uniformMatrix3x2fv(uniLoc(location), count, transpose, value);
459 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500460}
461
462void ProgramGL::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
463{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800464 if (mFunctions->programUniformMatrix2x4fv != nullptr)
465 {
466 mFunctions->programUniformMatrix2x4fv(mProgramID, uniLoc(location), count, transpose,
467 value);
468 }
469 else
470 {
471 mStateManager->useProgram(mProgramID);
472 mFunctions->uniformMatrix2x4fv(uniLoc(location), count, transpose, value);
473 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500474}
475
476void ProgramGL::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
477{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800478 if (mFunctions->programUniformMatrix4x2fv != nullptr)
479 {
480 mFunctions->programUniformMatrix4x2fv(mProgramID, uniLoc(location), count, transpose,
481 value);
482 }
483 else
484 {
485 mStateManager->useProgram(mProgramID);
486 mFunctions->uniformMatrix4x2fv(uniLoc(location), count, transpose, value);
487 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500488}
489
490void ProgramGL::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
491{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800492 if (mFunctions->programUniformMatrix3x4fv != nullptr)
493 {
494 mFunctions->programUniformMatrix3x4fv(mProgramID, uniLoc(location), count, transpose,
495 value);
496 }
497 else
498 {
499 mStateManager->useProgram(mProgramID);
500 mFunctions->uniformMatrix3x4fv(uniLoc(location), count, transpose, value);
501 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500502}
503
504void ProgramGL::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
505{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800506 if (mFunctions->programUniformMatrix4x3fv != nullptr)
507 {
508 mFunctions->programUniformMatrix4x3fv(mProgramID, uniLoc(location), count, transpose,
509 value);
510 }
511 else
512 {
513 mStateManager->useProgram(mProgramID);
514 mFunctions->uniformMatrix4x3fv(uniLoc(location), count, transpose, value);
515 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500516}
517
Geoff Lang5d124a62015-09-15 13:03:27 -0400518void ProgramGL::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
519{
Jamie Madill4a3c2342015-10-08 12:58:45 -0400520 // Lazy init
521 if (mUniformBlockRealLocationMap.empty())
522 {
Jamie Madill48ef11b2016-04-27 15:21:52 -0400523 mUniformBlockRealLocationMap.reserve(mState.getUniformBlocks().size());
Jiajia Qin729b2c62017-08-14 09:36:11 +0800524 for (const gl::InterfaceBlock &uniformBlock : mState.getUniformBlocks())
Jamie Madill4a3c2342015-10-08 12:58:45 -0400525 {
Olli Etuaho855d9642017-05-17 14:05:06 +0300526 const std::string &mappedNameWithIndex = uniformBlock.mappedNameWithArrayIndex();
527 GLuint blockIndex =
528 mFunctions->getUniformBlockIndex(mProgramID, mappedNameWithIndex.c_str());
Jamie Madill4a3c2342015-10-08 12:58:45 -0400529 mUniformBlockRealLocationMap.push_back(blockIndex);
530 }
531 }
532
533 GLuint realBlockIndex = mUniformBlockRealLocationMap[uniformBlockIndex];
534 if (realBlockIndex != GL_INVALID_INDEX)
535 {
536 mFunctions->uniformBlockBinding(mProgramID, realBlockIndex, uniformBlockBinding);
537 }
Geoff Lang5d124a62015-09-15 13:03:27 -0400538}
539
Geoff Langb1f435e2015-02-20 10:01:01 -0500540GLuint ProgramGL::getProgramID() const
541{
542 return mProgramID;
543}
544
Olli Etuaho855d9642017-05-17 14:05:06 +0300545bool ProgramGL::getUniformBlockSize(const std::string & /* blockName */,
546 const std::string &blockMappedName,
547 size_t *sizeOut) const
Jamie Madill62d31cb2015-09-11 13:25:51 -0400548{
Jamie Madill4a3c2342015-10-08 12:58:45 -0400549 ASSERT(mProgramID != 0u);
Geoff Lang5d124a62015-09-15 13:03:27 -0400550
Olli Etuaho855d9642017-05-17 14:05:06 +0300551 GLuint blockIndex = mFunctions->getUniformBlockIndex(mProgramID, blockMappedName.c_str());
Jamie Madill4a3c2342015-10-08 12:58:45 -0400552 if (blockIndex == GL_INVALID_INDEX)
Geoff Lang5d124a62015-09-15 13:03:27 -0400553 {
Jamie Madill4a3c2342015-10-08 12:58:45 -0400554 *sizeOut = 0;
555 return false;
Geoff Lang5d124a62015-09-15 13:03:27 -0400556 }
557
Jamie Madill4a3c2342015-10-08 12:58:45 -0400558 GLint dataSize = 0;
559 mFunctions->getActiveUniformBlockiv(mProgramID, blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE,
560 &dataSize);
561 *sizeOut = static_cast<size_t>(dataSize);
562 return true;
563}
564
Olli Etuaho855d9642017-05-17 14:05:06 +0300565bool ProgramGL::getUniformBlockMemberInfo(const std::string & /* memberUniformName */,
566 const std::string &memberUniformMappedName,
Jamie Madill4a3c2342015-10-08 12:58:45 -0400567 sh::BlockMemberInfo *memberInfoOut) const
568{
569 GLuint uniformIndex;
Olli Etuaho855d9642017-05-17 14:05:06 +0300570 const GLchar *memberNameGLStr = memberUniformMappedName.c_str();
Jamie Madill4a3c2342015-10-08 12:58:45 -0400571 mFunctions->getUniformIndices(mProgramID, 1, &memberNameGLStr, &uniformIndex);
572
573 if (uniformIndex == GL_INVALID_INDEX)
Geoff Lang5d124a62015-09-15 13:03:27 -0400574 {
Jamie Madill4a3c2342015-10-08 12:58:45 -0400575 *memberInfoOut = sh::BlockMemberInfo::getDefaultBlockInfo();
576 return false;
Geoff Lang5d124a62015-09-15 13:03:27 -0400577 }
Jamie Madill4a3c2342015-10-08 12:58:45 -0400578
579 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_OFFSET,
580 &memberInfoOut->offset);
581 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_ARRAY_STRIDE,
582 &memberInfoOut->arrayStride);
583 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_MATRIX_STRIDE,
584 &memberInfoOut->matrixStride);
585
586 // TODO(jmadill): possibly determine this at the gl::Program level.
587 GLint isRowMajorMatrix = 0;
588 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_IS_ROW_MAJOR,
589 &isRowMajorMatrix);
Geoff Lang92019432017-11-20 13:09:34 -0500590 memberInfoOut->isRowMajorMatrix = gl::ConvertToBool(isRowMajorMatrix);
Jamie Madill4a3c2342015-10-08 12:58:45 -0400591 return true;
Jamie Madill62d31cb2015-09-11 13:25:51 -0400592}
Jamie Madill4a3c2342015-10-08 12:58:45 -0400593
Jiajia Qin3a9090f2017-09-27 14:37:04 +0800594bool ProgramGL::getShaderStorageBlockMemberInfo(const std::string & /* memberName */,
595 const std::string &memberUniformMappedName,
596 sh::BlockMemberInfo *memberInfoOut) const
597{
598 const GLchar *memberNameGLStr = memberUniformMappedName.c_str();
599 GLuint index =
600 mFunctions->getProgramResourceIndex(mProgramID, GL_BUFFER_VARIABLE, memberNameGLStr);
601
602 if (index == GL_INVALID_INDEX)
603 {
604 *memberInfoOut = sh::BlockMemberInfo::getDefaultBlockInfo();
605 return false;
606 }
607
608 constexpr int kPropCount = 5;
609 std::array<GLenum, kPropCount> props = {
610 {GL_ARRAY_STRIDE, GL_IS_ROW_MAJOR, GL_MATRIX_STRIDE, GL_OFFSET, GL_TOP_LEVEL_ARRAY_STRIDE}};
611 std::array<GLint, kPropCount> params;
612 GLsizei length;
613 mFunctions->getProgramResourceiv(mProgramID, GL_BUFFER_VARIABLE, index, kPropCount,
614 props.data(), kPropCount, &length, params.data());
615 ASSERT(kPropCount == length);
616 memberInfoOut->arrayStride = params[0];
Olli Etuahoc4eca922017-11-13 12:27:23 +0200617 memberInfoOut->isRowMajorMatrix = params[1] != 0;
Jiajia Qin3a9090f2017-09-27 14:37:04 +0800618 memberInfoOut->matrixStride = params[2];
619 memberInfoOut->offset = params[3];
620 memberInfoOut->topLevelArrayStride = params[4];
621
622 return true;
623}
624
625bool ProgramGL::getShaderStorageBlockSize(const std::string &name,
626 const std::string &mappedName,
627 size_t *sizeOut) const
628{
629 const GLchar *nameGLStr = mappedName.c_str();
630 GLuint index =
631 mFunctions->getProgramResourceIndex(mProgramID, GL_SHADER_STORAGE_BLOCK, nameGLStr);
632
633 if (index == GL_INVALID_INDEX)
634 {
635 *sizeOut = 0;
636 return false;
637 }
638
639 GLenum prop = GL_BUFFER_DATA_SIZE;
640 GLsizei length = 0;
641 GLint dataSize = 0;
642 mFunctions->getProgramResourceiv(mProgramID, GL_SHADER_STORAGE_BLOCK, index, 1, &prop, 1,
643 &length, &dataSize);
644 *sizeOut = static_cast<size_t>(dataSize);
645 return true;
646}
647
Jiajia Qin94f1e892017-11-20 12:14:32 +0800648void ProgramGL::getAtomicCounterBufferSizeMap(std::map<int, unsigned int> *sizeMapOut) const
649{
650 if (mFunctions->getProgramInterfaceiv == nullptr)
651 {
652 return;
653 }
654
655 int resourceCount = 0;
656 mFunctions->getProgramInterfaceiv(mProgramID, GL_ATOMIC_COUNTER_BUFFER, GL_ACTIVE_RESOURCES,
657 &resourceCount);
658
659 for (int index = 0; index < resourceCount; index++)
660 {
661 constexpr int kPropCount = 2;
662 std::array<GLenum, kPropCount> props = {{GL_BUFFER_BINDING, GL_BUFFER_DATA_SIZE}};
663 std::array<GLint, kPropCount> params;
664 GLsizei length;
665 mFunctions->getProgramResourceiv(mProgramID, GL_ATOMIC_COUNTER_BUFFER, index, kPropCount,
666 props.data(), kPropCount, &length, params.data());
667 ASSERT(kPropCount == length);
668 int bufferBinding = params[0];
669 unsigned int bufferDataSize = params[1];
670 sizeMapOut->insert(std::pair<int, unsigned int>(bufferBinding, bufferDataSize));
671 }
672}
673
Sami Väisänen46eaa942016-06-29 10:26:37 +0300674void ProgramGL::setPathFragmentInputGen(const std::string &inputName,
675 GLenum genMode,
676 GLint components,
677 const GLfloat *coeffs)
678{
679 ASSERT(mEnablePathRendering);
680
681 for (const auto &input : mPathRenderingFragmentInputs)
682 {
Olli Etuaho855d9642017-05-17 14:05:06 +0300683 if (input.mappedName == inputName)
Sami Väisänen46eaa942016-06-29 10:26:37 +0300684 {
685 mFunctions->programPathFragmentInputGenNV(mProgramID, input.location, genMode,
686 components, coeffs);
687 ASSERT(mFunctions->getError() == GL_NO_ERROR);
688 return;
689 }
690 }
691
692}
693
Geoff Lang65a0be92015-10-02 09:57:30 -0400694void ProgramGL::preLink()
695{
696 // Reset the program state
697 mUniformRealLocationMap.clear();
698 mUniformBlockRealLocationMap.clear();
Sami Väisänen46eaa942016-06-29 10:26:37 +0300699 mPathRenderingFragmentInputs.clear();
Martin Radev4e619f52017-08-09 11:50:06 +0300700
701 mMultiviewBaseViewLayerIndexUniformLocation = -1;
Geoff Lang65a0be92015-10-02 09:57:30 -0400702}
703
704bool ProgramGL::checkLinkStatus(gl::InfoLog &infoLog)
705{
706 GLint linkStatus = GL_FALSE;
707 mFunctions->getProgramiv(mProgramID, GL_LINK_STATUS, &linkStatus);
708 if (linkStatus == GL_FALSE)
709 {
710 // Linking failed, put the error into the info log
711 GLint infoLogLength = 0;
712 mFunctions->getProgramiv(mProgramID, GL_INFO_LOG_LENGTH, &infoLogLength);
713
Geoff Lang65a0be92015-10-02 09:57:30 -0400714 // Info log length includes the null terminator, so 1 means that the info log is an empty
715 // string.
716 if (infoLogLength > 1)
717 {
718 std::vector<char> buf(infoLogLength);
719 mFunctions->getProgramInfoLog(mProgramID, infoLogLength, nullptr, &buf[0]);
720
721 mFunctions->deleteProgram(mProgramID);
722 mProgramID = 0;
723
724 infoLog << buf.data();
725
Yuly Novikovbcb3f9b2017-01-27 22:45:18 -0500726 WARN() << "Program link failed unexpectedly: " << buf.data();
Geoff Lang65a0be92015-10-02 09:57:30 -0400727 }
728 else
729 {
Yuly Novikovbcb3f9b2017-01-27 22:45:18 -0500730 WARN() << "Program link failed unexpectedly with no info log.";
Geoff Lang65a0be92015-10-02 09:57:30 -0400731 }
Geoff Lang65a0be92015-10-02 09:57:30 -0400732
733 // TODO, return GL_OUT_OF_MEMORY or just fail the link? This is an unexpected case
734 return false;
735 }
736
737 return true;
738}
739
740void ProgramGL::postLink()
741{
742 // Query the uniform information
743 ASSERT(mUniformRealLocationMap.empty());
Jamie Madill48ef11b2016-04-27 15:21:52 -0400744 const auto &uniformLocations = mState.getUniformLocations();
745 const auto &uniforms = mState.getUniforms();
Geoff Lang65a0be92015-10-02 09:57:30 -0400746 mUniformRealLocationMap.resize(uniformLocations.size(), GL_INVALID_INDEX);
747 for (size_t uniformLocation = 0; uniformLocation < uniformLocations.size(); uniformLocation++)
748 {
749 const auto &entry = uniformLocations[uniformLocation];
Jamie Madillfb997ec2017-09-20 15:44:27 -0400750 if (!entry.used())
Geoff Lang65a0be92015-10-02 09:57:30 -0400751 {
752 continue;
753 }
754
Olli Etuahoc8538042017-09-27 11:20:15 +0300755 // From the GLES 3.0.5 spec:
Geoff Lang65a0be92015-10-02 09:57:30 -0400756 // "Locations for sequential array indices are not required to be sequential."
757 const gl::LinkedUniform &uniform = uniforms[entry.index];
758 std::stringstream fullNameStr;
Geoff Lang65a0be92015-10-02 09:57:30 -0400759 if (uniform.isArray())
760 {
Olli Etuahod2551232017-10-26 20:03:33 +0300761 ASSERT(angle::EndsWith(uniform.mappedName, "[0]"));
762 fullNameStr << uniform.mappedName.substr(0, uniform.mappedName.length() - 3);
Olli Etuaho1734e172017-10-27 15:30:27 +0300763 fullNameStr << "[" << entry.arrayIndex << "]";
Olli Etuahod2551232017-10-26 20:03:33 +0300764 }
765 else
766 {
767 fullNameStr << uniform.mappedName;
Geoff Lang65a0be92015-10-02 09:57:30 -0400768 }
769 const std::string &fullName = fullNameStr.str();
770
771 GLint realLocation = mFunctions->getUniformLocation(mProgramID, fullName.c_str());
772 mUniformRealLocationMap[uniformLocation] = realLocation;
773 }
774
Martin Radev4e619f52017-08-09 11:50:06 +0300775 if (mState.usesMultiview())
776 {
777 mMultiviewBaseViewLayerIndexUniformLocation =
Olli Etuaho855d9642017-05-17 14:05:06 +0300778 mFunctions->getUniformLocation(mProgramID, "multiviewBaseViewLayerIndex");
Martin Radev4e619f52017-08-09 11:50:06 +0300779 ASSERT(mMultiviewBaseViewLayerIndexUniformLocation != -1);
780 }
781
Sami Väisänen46eaa942016-06-29 10:26:37 +0300782 // Discover CHROMIUM_path_rendering fragment inputs if enabled.
783 if (!mEnablePathRendering)
784 return;
785
786 GLint numFragmentInputs = 0;
787 mFunctions->getProgramInterfaceiv(mProgramID, GL_FRAGMENT_INPUT_NV, GL_ACTIVE_RESOURCES,
788 &numFragmentInputs);
789 if (numFragmentInputs <= 0)
790 return;
791
792 GLint maxNameLength = 0;
793 mFunctions->getProgramInterfaceiv(mProgramID, GL_FRAGMENT_INPUT_NV, GL_MAX_NAME_LENGTH,
794 &maxNameLength);
795 ASSERT(maxNameLength);
796
797 for (GLint i = 0; i < numFragmentInputs; ++i)
798 {
Olli Etuaho855d9642017-05-17 14:05:06 +0300799 std::string mappedName;
800 mappedName.resize(maxNameLength);
Sami Väisänen46eaa942016-06-29 10:26:37 +0300801
802 GLsizei nameLen = 0;
803 mFunctions->getProgramResourceName(mProgramID, GL_FRAGMENT_INPUT_NV, i, maxNameLength,
Olli Etuaho855d9642017-05-17 14:05:06 +0300804 &nameLen, &mappedName[0]);
805 mappedName.resize(nameLen);
Sami Väisänen46eaa942016-06-29 10:26:37 +0300806
807 // Ignore built-ins
Olli Etuaho855d9642017-05-17 14:05:06 +0300808 if (angle::BeginsWith(mappedName, "gl_"))
Sami Väisänen46eaa942016-06-29 10:26:37 +0300809 continue;
810
811 const GLenum kQueryProperties[] = {GL_LOCATION, GL_ARRAY_SIZE};
812 GLint queryResults[ArraySize(kQueryProperties)];
813 GLsizei queryLength = 0;
814
Geoff Lang3f6a3982016-07-15 15:20:45 -0400815 mFunctions->getProgramResourceiv(
816 mProgramID, GL_FRAGMENT_INPUT_NV, i, static_cast<GLsizei>(ArraySize(kQueryProperties)),
817 kQueryProperties, static_cast<GLsizei>(ArraySize(queryResults)), &queryLength,
818 queryResults);
Sami Väisänen46eaa942016-06-29 10:26:37 +0300819
Olli Etuahoe3191712016-07-18 16:01:10 +0300820 ASSERT(queryLength == static_cast<GLsizei>(ArraySize(kQueryProperties)));
Sami Väisänen46eaa942016-06-29 10:26:37 +0300821
Geoff Lang3f6a3982016-07-15 15:20:45 -0400822 PathRenderingFragmentInput baseElementInput;
Olli Etuaho855d9642017-05-17 14:05:06 +0300823 baseElementInput.mappedName = mappedName;
Geoff Lang3f6a3982016-07-15 15:20:45 -0400824 baseElementInput.location = queryResults[0];
825 mPathRenderingFragmentInputs.push_back(std::move(baseElementInput));
Sami Väisänen46eaa942016-06-29 10:26:37 +0300826
827 // If the input is an array it's denoted by [0] suffix on the variable
828 // name. We'll then create an entry per each array index where index > 0
Olli Etuaho855d9642017-05-17 14:05:06 +0300829 if (angle::EndsWith(mappedName, "[0]"))
Sami Väisänen46eaa942016-06-29 10:26:37 +0300830 {
831 // drop the suffix
Olli Etuaho855d9642017-05-17 14:05:06 +0300832 mappedName.resize(mappedName.size() - 3);
Sami Väisänen46eaa942016-06-29 10:26:37 +0300833
834 const auto arraySize = queryResults[1];
835 const auto baseLocation = queryResults[0];
836
Geoff Lang3f6a3982016-07-15 15:20:45 -0400837 for (GLint arrayIndex = 1; arrayIndex < arraySize; ++arrayIndex)
Sami Väisänen46eaa942016-06-29 10:26:37 +0300838 {
Geoff Lang3f6a3982016-07-15 15:20:45 -0400839 PathRenderingFragmentInput arrayElementInput;
Olli Etuaho855d9642017-05-17 14:05:06 +0300840 arrayElementInput.mappedName = mappedName + "[" + ToString(arrayIndex) + "]";
Geoff Lang3f6a3982016-07-15 15:20:45 -0400841 arrayElementInput.location = baseLocation + arrayIndex;
842 mPathRenderingFragmentInputs.push_back(std::move(arrayElementInput));
Sami Väisänen46eaa942016-06-29 10:26:37 +0300843 }
844 }
845 }
Geoff Lang65a0be92015-10-02 09:57:30 -0400846}
847
Martin Radev4e619f52017-08-09 11:50:06 +0300848void ProgramGL::enableSideBySideRenderingPath() const
849{
850 ASSERT(mState.usesMultiview());
851 ASSERT(mMultiviewBaseViewLayerIndexUniformLocation != -1);
852
853 ASSERT(mFunctions->programUniform1i != nullptr);
854 mFunctions->programUniform1i(mProgramID, mMultiviewBaseViewLayerIndexUniformLocation, -1);
855}
856
857void ProgramGL::enableLayeredRenderingPath(int baseViewIndex) const
858{
859 ASSERT(mState.usesMultiview());
860 ASSERT(mMultiviewBaseViewLayerIndexUniformLocation != -1);
861
862 ASSERT(mFunctions->programUniform1i != nullptr);
863 mFunctions->programUniform1i(mProgramID, mMultiviewBaseViewLayerIndexUniformLocation,
864 baseViewIndex);
865}
866
Jamie Madill54164b02017-08-28 15:17:37 -0400867void ProgramGL::getUniformfv(const gl::Context *context, GLint location, GLfloat *params) const
868{
869 mFunctions->getUniformfv(mProgramID, uniLoc(location), params);
870}
871
872void ProgramGL::getUniformiv(const gl::Context *context, GLint location, GLint *params) const
873{
874 mFunctions->getUniformiv(mProgramID, uniLoc(location), params);
875}
876
877void ProgramGL::getUniformuiv(const gl::Context *context, GLint location, GLuint *params) const
878{
879 mFunctions->getUniformuiv(mProgramID, uniLoc(location), params);
880}
881
Jamie Madillfb997ec2017-09-20 15:44:27 -0400882void ProgramGL::markUnusedUniformLocations(std::vector<gl::VariableLocation> *uniformLocations,
883 std::vector<gl::SamplerBinding> *samplerBindings)
Jamie Madill54164b02017-08-28 15:17:37 -0400884{
885 GLint maxLocation = static_cast<GLint>(uniformLocations->size());
886 for (GLint location = 0; location < maxLocation; ++location)
887 {
888 if (uniLoc(location) == -1)
889 {
Jamie Madillfb997ec2017-09-20 15:44:27 -0400890 auto &locationRef = (*uniformLocations)[location];
891 if (mState.isSamplerUniformIndex(locationRef.index))
892 {
893 GLuint samplerIndex = mState.getSamplerIndexFromUniformIndex(locationRef.index);
894 (*samplerBindings)[samplerIndex].unreferenced = true;
895 }
896 locationRef.markUnused();
Jamie Madill54164b02017-08-28 15:17:37 -0400897 }
898 }
899}
900
Jamie Madill6db1c2e2017-11-08 09:17:40 -0500901void ProgramGL::linkResources(const gl::ProgramLinkedResources &resources)
902{
903 // Gather interface block info.
904 auto getUniformBlockSize = [this](const std::string &name, const std::string &mappedName,
905 size_t *sizeOut) {
906 return this->getUniformBlockSize(name, mappedName, sizeOut);
907 };
908
909 auto getUniformBlockMemberInfo = [this](const std::string &name, const std::string &mappedName,
910 sh::BlockMemberInfo *infoOut) {
911 return this->getUniformBlockMemberInfo(name, mappedName, infoOut);
912 };
913
914 resources.uniformBlockLinker.linkBlocks(getUniformBlockSize, getUniformBlockMemberInfo);
915
Jiajia Qin3a9090f2017-09-27 14:37:04 +0800916 auto getShaderStorageBlockSize = [this](const std::string &name, const std::string &mappedName,
917 size_t *sizeOut) {
918 return this->getShaderStorageBlockSize(name, mappedName, sizeOut);
Jamie Madill6db1c2e2017-11-08 09:17:40 -0500919 };
920
Jiajia Qin3a9090f2017-09-27 14:37:04 +0800921 auto getShaderStorageBlockMemberInfo = [this](const std::string &name,
922 const std::string &mappedName,
923 sh::BlockMemberInfo *infoOut) {
924 return this->getShaderStorageBlockMemberInfo(name, mappedName, infoOut);
925 };
Jamie Madill6db1c2e2017-11-08 09:17:40 -0500926 resources.shaderStorageBlockLinker.linkBlocks(getShaderStorageBlockSize,
927 getShaderStorageBlockMemberInfo);
Jiajia Qin94f1e892017-11-20 12:14:32 +0800928
929 // Gather atomic counter buffer info.
930 std::map<int, unsigned int> sizeMap;
931 getAtomicCounterBufferSizeMap(&sizeMap);
932 resources.atomicCounterBufferLinker.link(sizeMap);
Jamie Madill6db1c2e2017-11-08 09:17:40 -0500933}
934
Jamie Madill4a3c2342015-10-08 12:58:45 -0400935} // namespace rx