blob: 4e35b89241c274c219f82829d36e408bafd6d063 [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
Jiawei Shao385b3e02018-03-21 09:43:28 +0800134 if (mState.getAttachedShader(gl::ShaderType::Compute))
Geoff Lang1a683462015-09-29 15:09:59 -0400135 {
Jiawei Shao385b3e02018-03-21 09:43:28 +0800136 const ShaderGL *computeShaderGL =
137 GetImplAs<ShaderGL>(mState.getAttachedShader(gl::ShaderType::Compute));
Geoff Lang1a683462015-09-29 15:09:59 -0400138
Martin Radev4c4c8e72016-08-04 12:25:34 +0300139 mFunctions->attachShader(mProgramID, computeShaderGL->getShaderID());
140
141 // Link and verify
142 mFunctions->linkProgram(mProgramID);
143
144 // Detach the shaders
145 mFunctions->detachShader(mProgramID, computeShaderGL->getShaderID());
Geoff Lang1a683462015-09-29 15:09:59 -0400146 }
147 else
148 {
Martin Radev4c4c8e72016-08-04 12:25:34 +0300149 // Set the transform feedback state
Olli Etuaho855d9642017-05-17 14:05:06 +0300150 std::vector<std::string> transformFeedbackVaryingMappedNames;
Martin Radev4c4c8e72016-08-04 12:25:34 +0300151 for (const auto &tfVarying : mState.getTransformFeedbackVaryingNames())
Geoff Lang1528e562015-08-24 15:10:58 -0400152 {
Olli Etuaho855d9642017-05-17 14:05:06 +0300153 std::string tfVaryingMappedName =
Jiawei Shao385b3e02018-03-21 09:43:28 +0800154 mState.getAttachedShader(gl::ShaderType::Vertex)
155 ->getTransformFeedbackVaryingMappedName(tfVarying, context);
Olli Etuaho855d9642017-05-17 14:05:06 +0300156 transformFeedbackVaryingMappedNames.push_back(tfVaryingMappedName);
Geoff Lang1528e562015-08-24 15:10:58 -0400157 }
158
Olli Etuaho855d9642017-05-17 14:05:06 +0300159 if (transformFeedbackVaryingMappedNames.empty())
Martin Radev4c4c8e72016-08-04 12:25:34 +0300160 {
161 if (mFunctions->transformFeedbackVaryings)
162 {
163 mFunctions->transformFeedbackVaryings(mProgramID, 0, nullptr,
164 mState.getTransformFeedbackBufferMode());
165 }
166 }
167 else
168 {
169 ASSERT(mFunctions->transformFeedbackVaryings);
Olli Etuaho855d9642017-05-17 14:05:06 +0300170 std::vector<const GLchar *> transformFeedbackVaryings;
171 for (const auto &varying : transformFeedbackVaryingMappedNames)
172 {
173 transformFeedbackVaryings.push_back(varying.c_str());
174 }
Martin Radev4c4c8e72016-08-04 12:25:34 +0300175 mFunctions->transformFeedbackVaryings(
Olli Etuaho855d9642017-05-17 14:05:06 +0300176 mProgramID, static_cast<GLsizei>(transformFeedbackVaryingMappedNames.size()),
Martin Radev4c4c8e72016-08-04 12:25:34 +0300177 &transformFeedbackVaryings[0], mState.getTransformFeedbackBufferMode());
178 }
179
Jiawei Shao385b3e02018-03-21 09:43:28 +0800180 const ShaderGL *vertexShaderGL =
181 GetImplAs<ShaderGL>(mState.getAttachedShader(gl::ShaderType::Vertex));
182 const ShaderGL *fragmentShaderGL =
183 GetImplAs<ShaderGL>(mState.getAttachedShader(gl::ShaderType::Fragment));
184 const ShaderGL *geometryShaderGL = rx::SafeGetImplAs<ShaderGL, gl::Shader>(
185 mState.getAttachedShader(gl::ShaderType::Geometry));
Martin Radev4c4c8e72016-08-04 12:25:34 +0300186
187 // Attach the shaders
188 mFunctions->attachShader(mProgramID, vertexShaderGL->getShaderID());
189 mFunctions->attachShader(mProgramID, fragmentShaderGL->getShaderID());
Jiawei Shao4ed05da2018-02-02 14:26:15 +0800190 if (geometryShaderGL)
191 {
192 mFunctions->attachShader(mProgramID, geometryShaderGL->getShaderID());
193 }
Martin Radev4c4c8e72016-08-04 12:25:34 +0300194
195 // Bind attribute locations to match the GL layer.
196 for (const sh::Attribute &attribute : mState.getAttributes())
197 {
Olli Etuaho107c7242018-03-20 15:45:35 +0200198 if (!attribute.active || attribute.isBuiltIn())
Martin Radev4c4c8e72016-08-04 12:25:34 +0300199 {
200 continue;
201 }
202
Olli Etuaho855d9642017-05-17 14:05:06 +0300203 mFunctions->bindAttribLocation(mProgramID, attribute.location,
204 attribute.mappedName.c_str());
Martin Radev4c4c8e72016-08-04 12:25:34 +0300205 }
206
207 // Link and verify
208 mFunctions->linkProgram(mProgramID);
209
210 // Detach the shaders
211 mFunctions->detachShader(mProgramID, vertexShaderGL->getShaderID());
212 mFunctions->detachShader(mProgramID, fragmentShaderGL->getShaderID());
Jiawei Shao4ed05da2018-02-02 14:26:15 +0800213 if (geometryShaderGL)
214 {
215 mFunctions->detachShader(mProgramID, geometryShaderGL->getShaderID());
216 }
Geoff Lang1528e562015-08-24 15:10:58 -0400217 }
218
Geoff Lang0ca53782015-05-07 13:49:39 -0400219 // Verify the link
Geoff Lang65a0be92015-10-02 09:57:30 -0400220 if (!checkLinkStatus(infoLog))
Geoff Langb1f435e2015-02-20 10:01:01 -0500221 {
Jamie Madillb0a838b2016-11-13 20:02:12 -0500222 return false;
Geoff Langb1f435e2015-02-20 10:01:01 -0500223 }
224
Philippe Hamel40911192016-04-07 16:45:50 -0400225 if (mWorkarounds.alwaysCallUseProgramAfterLink)
226 {
227 mStateManager->forceUseProgram(mProgramID);
228 }
229
Jamie Madill6db1c2e2017-11-08 09:17:40 -0500230 linkResources(resources);
Geoff Lang65a0be92015-10-02 09:57:30 -0400231 postLink();
Geoff Langb1f435e2015-02-20 10:01:01 -0500232
Jamie Madillb0a838b2016-11-13 20:02:12 -0500233 return true;
Geoff Langf9a6f082015-01-22 13:32:49 -0500234}
235
Jamie Madill36cfd6a2015-08-18 10:46:20 -0400236GLboolean ProgramGL::validate(const gl::Caps & /*caps*/, gl::InfoLog * /*infoLog*/)
237{
238 // TODO(jmadill): implement validate
239 return true;
240}
241
Geoff Langf9a6f082015-01-22 13:32:49 -0500242void ProgramGL::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
243{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800244 if (mFunctions->programUniform1fv != nullptr)
245 {
246 mFunctions->programUniform1fv(mProgramID, uniLoc(location), count, v);
247 }
248 else
249 {
250 mStateManager->useProgram(mProgramID);
251 mFunctions->uniform1fv(uniLoc(location), count, v);
252 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500253}
254
255void ProgramGL::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
256{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800257 if (mFunctions->programUniform2fv != nullptr)
258 {
259 mFunctions->programUniform2fv(mProgramID, uniLoc(location), count, v);
260 }
261 else
262 {
263 mStateManager->useProgram(mProgramID);
264 mFunctions->uniform2fv(uniLoc(location), count, v);
265 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500266}
267
268void ProgramGL::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
269{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800270 if (mFunctions->programUniform3fv != nullptr)
271 {
272 mFunctions->programUniform3fv(mProgramID, uniLoc(location), count, v);
273 }
274 else
275 {
276 mStateManager->useProgram(mProgramID);
277 mFunctions->uniform3fv(uniLoc(location), count, v);
278 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500279}
280
281void ProgramGL::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
282{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800283 if (mFunctions->programUniform4fv != nullptr)
284 {
285 mFunctions->programUniform4fv(mProgramID, uniLoc(location), count, v);
286 }
287 else
288 {
289 mStateManager->useProgram(mProgramID);
290 mFunctions->uniform4fv(uniLoc(location), count, v);
291 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500292}
293
294void ProgramGL::setUniform1iv(GLint location, GLsizei count, const GLint *v)
295{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800296 if (mFunctions->programUniform1iv != nullptr)
297 {
298 mFunctions->programUniform1iv(mProgramID, uniLoc(location), count, v);
299 }
300 else
301 {
302 mStateManager->useProgram(mProgramID);
303 mFunctions->uniform1iv(uniLoc(location), count, v);
304 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500305}
306
307void ProgramGL::setUniform2iv(GLint location, GLsizei count, const GLint *v)
308{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800309 if (mFunctions->programUniform2iv != nullptr)
310 {
311 mFunctions->programUniform2iv(mProgramID, uniLoc(location), count, v);
312 }
313 else
314 {
315 mStateManager->useProgram(mProgramID);
316 mFunctions->uniform2iv(uniLoc(location), count, v);
317 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500318}
319
320void ProgramGL::setUniform3iv(GLint location, GLsizei count, const GLint *v)
321{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800322 if (mFunctions->programUniform3iv != nullptr)
323 {
324 mFunctions->programUniform3iv(mProgramID, uniLoc(location), count, v);
325 }
326 else
327 {
328 mStateManager->useProgram(mProgramID);
329 mFunctions->uniform3iv(uniLoc(location), count, v);
330 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500331}
332
333void ProgramGL::setUniform4iv(GLint location, GLsizei count, const GLint *v)
334{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800335 if (mFunctions->programUniform4iv != nullptr)
336 {
337 mFunctions->programUniform4iv(mProgramID, uniLoc(location), count, v);
338 }
339 else
340 {
341 mStateManager->useProgram(mProgramID);
342 mFunctions->uniform4iv(uniLoc(location), count, v);
343 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500344}
345
346void ProgramGL::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
347{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800348 if (mFunctions->programUniform1uiv != nullptr)
349 {
350 mFunctions->programUniform1uiv(mProgramID, uniLoc(location), count, v);
351 }
352 else
353 {
354 mStateManager->useProgram(mProgramID);
355 mFunctions->uniform1uiv(uniLoc(location), count, v);
356 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500357}
358
359void ProgramGL::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
360{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800361 if (mFunctions->programUniform2uiv != nullptr)
362 {
363 mFunctions->programUniform2uiv(mProgramID, uniLoc(location), count, v);
364 }
365 else
366 {
367 mStateManager->useProgram(mProgramID);
368 mFunctions->uniform2uiv(uniLoc(location), count, v);
369 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500370}
371
372void ProgramGL::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
373{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800374 if (mFunctions->programUniform3uiv != nullptr)
375 {
376 mFunctions->programUniform3uiv(mProgramID, uniLoc(location), count, v);
377 }
378 else
379 {
380 mStateManager->useProgram(mProgramID);
381 mFunctions->uniform3uiv(uniLoc(location), count, v);
382 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500383}
384
385void ProgramGL::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
386{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800387 if (mFunctions->programUniform4uiv != nullptr)
388 {
389 mFunctions->programUniform4uiv(mProgramID, uniLoc(location), count, v);
390 }
391 else
392 {
393 mStateManager->useProgram(mProgramID);
394 mFunctions->uniform4uiv(uniLoc(location), count, v);
395 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500396}
397
398void ProgramGL::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
399{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800400 if (mFunctions->programUniformMatrix2fv != nullptr)
401 {
402 mFunctions->programUniformMatrix2fv(mProgramID, uniLoc(location), count, transpose, value);
403 }
404 else
405 {
406 mStateManager->useProgram(mProgramID);
407 mFunctions->uniformMatrix2fv(uniLoc(location), count, transpose, value);
408 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500409}
410
411void ProgramGL::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
412{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800413 if (mFunctions->programUniformMatrix3fv != nullptr)
414 {
415 mFunctions->programUniformMatrix3fv(mProgramID, uniLoc(location), count, transpose, value);
416 }
417 else
418 {
419 mStateManager->useProgram(mProgramID);
420 mFunctions->uniformMatrix3fv(uniLoc(location), count, transpose, value);
421 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500422}
423
424void ProgramGL::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
425{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800426 if (mFunctions->programUniformMatrix4fv != nullptr)
427 {
428 mFunctions->programUniformMatrix4fv(mProgramID, uniLoc(location), count, transpose, value);
429 }
430 else
431 {
432 mStateManager->useProgram(mProgramID);
433 mFunctions->uniformMatrix4fv(uniLoc(location), count, transpose, value);
434 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500435}
436
437void ProgramGL::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
438{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800439 if (mFunctions->programUniformMatrix2x3fv != nullptr)
440 {
441 mFunctions->programUniformMatrix2x3fv(mProgramID, uniLoc(location), count, transpose,
442 value);
443 }
444 else
445 {
446 mStateManager->useProgram(mProgramID);
447 mFunctions->uniformMatrix2x3fv(uniLoc(location), count, transpose, value);
448 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500449}
450
451void ProgramGL::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
452{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800453 if (mFunctions->programUniformMatrix3x2fv != nullptr)
454 {
455 mFunctions->programUniformMatrix3x2fv(mProgramID, uniLoc(location), count, transpose,
456 value);
457 }
458 else
459 {
460 mStateManager->useProgram(mProgramID);
461 mFunctions->uniformMatrix3x2fv(uniLoc(location), count, transpose, value);
462 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500463}
464
465void ProgramGL::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
466{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800467 if (mFunctions->programUniformMatrix2x4fv != nullptr)
468 {
469 mFunctions->programUniformMatrix2x4fv(mProgramID, uniLoc(location), count, transpose,
470 value);
471 }
472 else
473 {
474 mStateManager->useProgram(mProgramID);
475 mFunctions->uniformMatrix2x4fv(uniLoc(location), count, transpose, value);
476 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500477}
478
479void ProgramGL::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
480{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800481 if (mFunctions->programUniformMatrix4x2fv != nullptr)
482 {
483 mFunctions->programUniformMatrix4x2fv(mProgramID, uniLoc(location), count, transpose,
484 value);
485 }
486 else
487 {
488 mStateManager->useProgram(mProgramID);
489 mFunctions->uniformMatrix4x2fv(uniLoc(location), count, transpose, value);
490 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500491}
492
493void ProgramGL::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
494{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800495 if (mFunctions->programUniformMatrix3x4fv != nullptr)
496 {
497 mFunctions->programUniformMatrix3x4fv(mProgramID, uniLoc(location), count, transpose,
498 value);
499 }
500 else
501 {
502 mStateManager->useProgram(mProgramID);
503 mFunctions->uniformMatrix3x4fv(uniLoc(location), count, transpose, value);
504 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500505}
506
507void ProgramGL::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
508{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800509 if (mFunctions->programUniformMatrix4x3fv != nullptr)
510 {
511 mFunctions->programUniformMatrix4x3fv(mProgramID, uniLoc(location), count, transpose,
512 value);
513 }
514 else
515 {
516 mStateManager->useProgram(mProgramID);
517 mFunctions->uniformMatrix4x3fv(uniLoc(location), count, transpose, value);
518 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500519}
520
Geoff Lang5d124a62015-09-15 13:03:27 -0400521void ProgramGL::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
522{
Jamie Madill4a3c2342015-10-08 12:58:45 -0400523 // Lazy init
524 if (mUniformBlockRealLocationMap.empty())
525 {
Jamie Madill48ef11b2016-04-27 15:21:52 -0400526 mUniformBlockRealLocationMap.reserve(mState.getUniformBlocks().size());
Jiajia Qin729b2c62017-08-14 09:36:11 +0800527 for (const gl::InterfaceBlock &uniformBlock : mState.getUniformBlocks())
Jamie Madill4a3c2342015-10-08 12:58:45 -0400528 {
Olli Etuaho855d9642017-05-17 14:05:06 +0300529 const std::string &mappedNameWithIndex = uniformBlock.mappedNameWithArrayIndex();
530 GLuint blockIndex =
531 mFunctions->getUniformBlockIndex(mProgramID, mappedNameWithIndex.c_str());
Jamie Madill4a3c2342015-10-08 12:58:45 -0400532 mUniformBlockRealLocationMap.push_back(blockIndex);
533 }
534 }
535
536 GLuint realBlockIndex = mUniformBlockRealLocationMap[uniformBlockIndex];
537 if (realBlockIndex != GL_INVALID_INDEX)
538 {
539 mFunctions->uniformBlockBinding(mProgramID, realBlockIndex, uniformBlockBinding);
540 }
Geoff Lang5d124a62015-09-15 13:03:27 -0400541}
542
Geoff Langb1f435e2015-02-20 10:01:01 -0500543GLuint ProgramGL::getProgramID() const
544{
545 return mProgramID;
546}
547
Olli Etuaho855d9642017-05-17 14:05:06 +0300548bool ProgramGL::getUniformBlockSize(const std::string & /* blockName */,
549 const std::string &blockMappedName,
550 size_t *sizeOut) const
Jamie Madill62d31cb2015-09-11 13:25:51 -0400551{
Jamie Madill4a3c2342015-10-08 12:58:45 -0400552 ASSERT(mProgramID != 0u);
Geoff Lang5d124a62015-09-15 13:03:27 -0400553
Olli Etuaho855d9642017-05-17 14:05:06 +0300554 GLuint blockIndex = mFunctions->getUniformBlockIndex(mProgramID, blockMappedName.c_str());
Jamie Madill4a3c2342015-10-08 12:58:45 -0400555 if (blockIndex == GL_INVALID_INDEX)
Geoff Lang5d124a62015-09-15 13:03:27 -0400556 {
Jamie Madill4a3c2342015-10-08 12:58:45 -0400557 *sizeOut = 0;
558 return false;
Geoff Lang5d124a62015-09-15 13:03:27 -0400559 }
560
Jamie Madill4a3c2342015-10-08 12:58:45 -0400561 GLint dataSize = 0;
562 mFunctions->getActiveUniformBlockiv(mProgramID, blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE,
563 &dataSize);
564 *sizeOut = static_cast<size_t>(dataSize);
565 return true;
566}
567
Olli Etuaho855d9642017-05-17 14:05:06 +0300568bool ProgramGL::getUniformBlockMemberInfo(const std::string & /* memberUniformName */,
569 const std::string &memberUniformMappedName,
Jamie Madill4a3c2342015-10-08 12:58:45 -0400570 sh::BlockMemberInfo *memberInfoOut) const
571{
572 GLuint uniformIndex;
Olli Etuaho855d9642017-05-17 14:05:06 +0300573 const GLchar *memberNameGLStr = memberUniformMappedName.c_str();
Jamie Madill4a3c2342015-10-08 12:58:45 -0400574 mFunctions->getUniformIndices(mProgramID, 1, &memberNameGLStr, &uniformIndex);
575
576 if (uniformIndex == GL_INVALID_INDEX)
Geoff Lang5d124a62015-09-15 13:03:27 -0400577 {
Jamie Madill4a3c2342015-10-08 12:58:45 -0400578 *memberInfoOut = sh::BlockMemberInfo::getDefaultBlockInfo();
579 return false;
Geoff Lang5d124a62015-09-15 13:03:27 -0400580 }
Jamie Madill4a3c2342015-10-08 12:58:45 -0400581
582 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_OFFSET,
583 &memberInfoOut->offset);
584 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_ARRAY_STRIDE,
585 &memberInfoOut->arrayStride);
586 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_MATRIX_STRIDE,
587 &memberInfoOut->matrixStride);
588
589 // TODO(jmadill): possibly determine this at the gl::Program level.
590 GLint isRowMajorMatrix = 0;
591 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_IS_ROW_MAJOR,
592 &isRowMajorMatrix);
Geoff Lang92019432017-11-20 13:09:34 -0500593 memberInfoOut->isRowMajorMatrix = gl::ConvertToBool(isRowMajorMatrix);
Jamie Madill4a3c2342015-10-08 12:58:45 -0400594 return true;
Jamie Madill62d31cb2015-09-11 13:25:51 -0400595}
Jamie Madill4a3c2342015-10-08 12:58:45 -0400596
Jiajia Qin3a9090f2017-09-27 14:37:04 +0800597bool ProgramGL::getShaderStorageBlockMemberInfo(const std::string & /* memberName */,
598 const std::string &memberUniformMappedName,
599 sh::BlockMemberInfo *memberInfoOut) const
600{
601 const GLchar *memberNameGLStr = memberUniformMappedName.c_str();
602 GLuint index =
603 mFunctions->getProgramResourceIndex(mProgramID, GL_BUFFER_VARIABLE, memberNameGLStr);
604
605 if (index == GL_INVALID_INDEX)
606 {
607 *memberInfoOut = sh::BlockMemberInfo::getDefaultBlockInfo();
608 return false;
609 }
610
611 constexpr int kPropCount = 5;
612 std::array<GLenum, kPropCount> props = {
613 {GL_ARRAY_STRIDE, GL_IS_ROW_MAJOR, GL_MATRIX_STRIDE, GL_OFFSET, GL_TOP_LEVEL_ARRAY_STRIDE}};
614 std::array<GLint, kPropCount> params;
615 GLsizei length;
616 mFunctions->getProgramResourceiv(mProgramID, GL_BUFFER_VARIABLE, index, kPropCount,
617 props.data(), kPropCount, &length, params.data());
618 ASSERT(kPropCount == length);
619 memberInfoOut->arrayStride = params[0];
Olli Etuahoc4eca922017-11-13 12:27:23 +0200620 memberInfoOut->isRowMajorMatrix = params[1] != 0;
Jiajia Qin3a9090f2017-09-27 14:37:04 +0800621 memberInfoOut->matrixStride = params[2];
622 memberInfoOut->offset = params[3];
623 memberInfoOut->topLevelArrayStride = params[4];
624
625 return true;
626}
627
628bool ProgramGL::getShaderStorageBlockSize(const std::string &name,
629 const std::string &mappedName,
630 size_t *sizeOut) const
631{
632 const GLchar *nameGLStr = mappedName.c_str();
633 GLuint index =
634 mFunctions->getProgramResourceIndex(mProgramID, GL_SHADER_STORAGE_BLOCK, nameGLStr);
635
636 if (index == GL_INVALID_INDEX)
637 {
638 *sizeOut = 0;
639 return false;
640 }
641
642 GLenum prop = GL_BUFFER_DATA_SIZE;
643 GLsizei length = 0;
644 GLint dataSize = 0;
645 mFunctions->getProgramResourceiv(mProgramID, GL_SHADER_STORAGE_BLOCK, index, 1, &prop, 1,
646 &length, &dataSize);
647 *sizeOut = static_cast<size_t>(dataSize);
648 return true;
649}
650
Jiajia Qin94f1e892017-11-20 12:14:32 +0800651void ProgramGL::getAtomicCounterBufferSizeMap(std::map<int, unsigned int> *sizeMapOut) const
652{
653 if (mFunctions->getProgramInterfaceiv == nullptr)
654 {
655 return;
656 }
657
658 int resourceCount = 0;
659 mFunctions->getProgramInterfaceiv(mProgramID, GL_ATOMIC_COUNTER_BUFFER, GL_ACTIVE_RESOURCES,
660 &resourceCount);
661
662 for (int index = 0; index < resourceCount; index++)
663 {
664 constexpr int kPropCount = 2;
665 std::array<GLenum, kPropCount> props = {{GL_BUFFER_BINDING, GL_BUFFER_DATA_SIZE}};
666 std::array<GLint, kPropCount> params;
667 GLsizei length;
668 mFunctions->getProgramResourceiv(mProgramID, GL_ATOMIC_COUNTER_BUFFER, index, kPropCount,
669 props.data(), kPropCount, &length, params.data());
670 ASSERT(kPropCount == length);
671 int bufferBinding = params[0];
672 unsigned int bufferDataSize = params[1];
673 sizeMapOut->insert(std::pair<int, unsigned int>(bufferBinding, bufferDataSize));
674 }
675}
676
Sami Väisänen46eaa942016-06-29 10:26:37 +0300677void ProgramGL::setPathFragmentInputGen(const std::string &inputName,
678 GLenum genMode,
679 GLint components,
680 const GLfloat *coeffs)
681{
682 ASSERT(mEnablePathRendering);
683
684 for (const auto &input : mPathRenderingFragmentInputs)
685 {
Olli Etuaho855d9642017-05-17 14:05:06 +0300686 if (input.mappedName == inputName)
Sami Väisänen46eaa942016-06-29 10:26:37 +0300687 {
688 mFunctions->programPathFragmentInputGenNV(mProgramID, input.location, genMode,
689 components, coeffs);
690 ASSERT(mFunctions->getError() == GL_NO_ERROR);
691 return;
692 }
693 }
694
695}
696
Geoff Lang65a0be92015-10-02 09:57:30 -0400697void ProgramGL::preLink()
698{
699 // Reset the program state
700 mUniformRealLocationMap.clear();
701 mUniformBlockRealLocationMap.clear();
Sami Väisänen46eaa942016-06-29 10:26:37 +0300702 mPathRenderingFragmentInputs.clear();
Martin Radev4e619f52017-08-09 11:50:06 +0300703
704 mMultiviewBaseViewLayerIndexUniformLocation = -1;
Geoff Lang65a0be92015-10-02 09:57:30 -0400705}
706
707bool ProgramGL::checkLinkStatus(gl::InfoLog &infoLog)
708{
709 GLint linkStatus = GL_FALSE;
710 mFunctions->getProgramiv(mProgramID, GL_LINK_STATUS, &linkStatus);
711 if (linkStatus == GL_FALSE)
712 {
Olli Etuaho81f891d2018-08-02 15:54:55 +0300713 // Linking or program binary loading failed, put the error into the info log.
Geoff Lang65a0be92015-10-02 09:57:30 -0400714 GLint infoLogLength = 0;
715 mFunctions->getProgramiv(mProgramID, GL_INFO_LOG_LENGTH, &infoLogLength);
716
Geoff Lang65a0be92015-10-02 09:57:30 -0400717 // Info log length includes the null terminator, so 1 means that the info log is an empty
718 // string.
719 if (infoLogLength > 1)
720 {
721 std::vector<char> buf(infoLogLength);
722 mFunctions->getProgramInfoLog(mProgramID, infoLogLength, nullptr, &buf[0]);
723
Geoff Lang65a0be92015-10-02 09:57:30 -0400724 infoLog << buf.data();
725
Olli Etuaho81f891d2018-08-02 15:54:55 +0300726 WARN() << "Program link or binary loading failed: " << buf.data();
Geoff Lang65a0be92015-10-02 09:57:30 -0400727 }
728 else
729 {
Olli Etuaho81f891d2018-08-02 15:54:55 +0300730 WARN() << "Program link or binary loading failed with no info log.";
Geoff Lang65a0be92015-10-02 09:57:30 -0400731 }
Geoff Lang65a0be92015-10-02 09:57:30 -0400732
Olli Etuaho81f891d2018-08-02 15:54:55 +0300733 // This may happen under normal circumstances if we're loading program binaries and the
734 // driver or hardware has changed.
735 ASSERT(mProgramID != 0);
Geoff Lang65a0be92015-10-02 09:57:30 -0400736 return false;
737 }
738
739 return true;
740}
741
742void ProgramGL::postLink()
743{
744 // Query the uniform information
745 ASSERT(mUniformRealLocationMap.empty());
Jamie Madill48ef11b2016-04-27 15:21:52 -0400746 const auto &uniformLocations = mState.getUniformLocations();
747 const auto &uniforms = mState.getUniforms();
Geoff Lang65a0be92015-10-02 09:57:30 -0400748 mUniformRealLocationMap.resize(uniformLocations.size(), GL_INVALID_INDEX);
749 for (size_t uniformLocation = 0; uniformLocation < uniformLocations.size(); uniformLocation++)
750 {
751 const auto &entry = uniformLocations[uniformLocation];
Jamie Madillfb997ec2017-09-20 15:44:27 -0400752 if (!entry.used())
Geoff Lang65a0be92015-10-02 09:57:30 -0400753 {
754 continue;
755 }
756
Olli Etuahoc8538042017-09-27 11:20:15 +0300757 // From the GLES 3.0.5 spec:
Geoff Lang65a0be92015-10-02 09:57:30 -0400758 // "Locations for sequential array indices are not required to be sequential."
759 const gl::LinkedUniform &uniform = uniforms[entry.index];
760 std::stringstream fullNameStr;
Geoff Lang65a0be92015-10-02 09:57:30 -0400761 if (uniform.isArray())
762 {
Olli Etuahod2551232017-10-26 20:03:33 +0300763 ASSERT(angle::EndsWith(uniform.mappedName, "[0]"));
764 fullNameStr << uniform.mappedName.substr(0, uniform.mappedName.length() - 3);
Olli Etuaho1734e172017-10-27 15:30:27 +0300765 fullNameStr << "[" << entry.arrayIndex << "]";
Olli Etuahod2551232017-10-26 20:03:33 +0300766 }
767 else
768 {
769 fullNameStr << uniform.mappedName;
Geoff Lang65a0be92015-10-02 09:57:30 -0400770 }
771 const std::string &fullName = fullNameStr.str();
772
773 GLint realLocation = mFunctions->getUniformLocation(mProgramID, fullName.c_str());
774 mUniformRealLocationMap[uniformLocation] = realLocation;
775 }
776
Martin Radev4e619f52017-08-09 11:50:06 +0300777 if (mState.usesMultiview())
778 {
779 mMultiviewBaseViewLayerIndexUniformLocation =
Olli Etuaho855d9642017-05-17 14:05:06 +0300780 mFunctions->getUniformLocation(mProgramID, "multiviewBaseViewLayerIndex");
Martin Radev4e619f52017-08-09 11:50:06 +0300781 ASSERT(mMultiviewBaseViewLayerIndexUniformLocation != -1);
782 }
783
Sami Väisänen46eaa942016-06-29 10:26:37 +0300784 // Discover CHROMIUM_path_rendering fragment inputs if enabled.
785 if (!mEnablePathRendering)
786 return;
787
788 GLint numFragmentInputs = 0;
789 mFunctions->getProgramInterfaceiv(mProgramID, GL_FRAGMENT_INPUT_NV, GL_ACTIVE_RESOURCES,
790 &numFragmentInputs);
791 if (numFragmentInputs <= 0)
792 return;
793
794 GLint maxNameLength = 0;
795 mFunctions->getProgramInterfaceiv(mProgramID, GL_FRAGMENT_INPUT_NV, GL_MAX_NAME_LENGTH,
796 &maxNameLength);
797 ASSERT(maxNameLength);
798
799 for (GLint i = 0; i < numFragmentInputs; ++i)
800 {
Olli Etuaho855d9642017-05-17 14:05:06 +0300801 std::string mappedName;
802 mappedName.resize(maxNameLength);
Sami Väisänen46eaa942016-06-29 10:26:37 +0300803
804 GLsizei nameLen = 0;
805 mFunctions->getProgramResourceName(mProgramID, GL_FRAGMENT_INPUT_NV, i, maxNameLength,
Olli Etuaho855d9642017-05-17 14:05:06 +0300806 &nameLen, &mappedName[0]);
807 mappedName.resize(nameLen);
Sami Väisänen46eaa942016-06-29 10:26:37 +0300808
809 // Ignore built-ins
Olli Etuaho855d9642017-05-17 14:05:06 +0300810 if (angle::BeginsWith(mappedName, "gl_"))
Sami Väisänen46eaa942016-06-29 10:26:37 +0300811 continue;
812
813 const GLenum kQueryProperties[] = {GL_LOCATION, GL_ARRAY_SIZE};
814 GLint queryResults[ArraySize(kQueryProperties)];
815 GLsizei queryLength = 0;
816
Geoff Lang3f6a3982016-07-15 15:20:45 -0400817 mFunctions->getProgramResourceiv(
818 mProgramID, GL_FRAGMENT_INPUT_NV, i, static_cast<GLsizei>(ArraySize(kQueryProperties)),
819 kQueryProperties, static_cast<GLsizei>(ArraySize(queryResults)), &queryLength,
820 queryResults);
Sami Väisänen46eaa942016-06-29 10:26:37 +0300821
Olli Etuahoe3191712016-07-18 16:01:10 +0300822 ASSERT(queryLength == static_cast<GLsizei>(ArraySize(kQueryProperties)));
Sami Väisänen46eaa942016-06-29 10:26:37 +0300823
Geoff Lang3f6a3982016-07-15 15:20:45 -0400824 PathRenderingFragmentInput baseElementInput;
Olli Etuaho855d9642017-05-17 14:05:06 +0300825 baseElementInput.mappedName = mappedName;
Geoff Lang3f6a3982016-07-15 15:20:45 -0400826 baseElementInput.location = queryResults[0];
827 mPathRenderingFragmentInputs.push_back(std::move(baseElementInput));
Sami Väisänen46eaa942016-06-29 10:26:37 +0300828
829 // If the input is an array it's denoted by [0] suffix on the variable
830 // name. We'll then create an entry per each array index where index > 0
Olli Etuaho855d9642017-05-17 14:05:06 +0300831 if (angle::EndsWith(mappedName, "[0]"))
Sami Väisänen46eaa942016-06-29 10:26:37 +0300832 {
833 // drop the suffix
Olli Etuaho855d9642017-05-17 14:05:06 +0300834 mappedName.resize(mappedName.size() - 3);
Sami Väisänen46eaa942016-06-29 10:26:37 +0300835
836 const auto arraySize = queryResults[1];
837 const auto baseLocation = queryResults[0];
838
Geoff Lang3f6a3982016-07-15 15:20:45 -0400839 for (GLint arrayIndex = 1; arrayIndex < arraySize; ++arrayIndex)
Sami Väisänen46eaa942016-06-29 10:26:37 +0300840 {
Geoff Lang3f6a3982016-07-15 15:20:45 -0400841 PathRenderingFragmentInput arrayElementInput;
Olli Etuaho855d9642017-05-17 14:05:06 +0300842 arrayElementInput.mappedName = mappedName + "[" + ToString(arrayIndex) + "]";
Geoff Lang3f6a3982016-07-15 15:20:45 -0400843 arrayElementInput.location = baseLocation + arrayIndex;
844 mPathRenderingFragmentInputs.push_back(std::move(arrayElementInput));
Sami Väisänen46eaa942016-06-29 10:26:37 +0300845 }
846 }
847 }
Geoff Lang65a0be92015-10-02 09:57:30 -0400848}
849
Martin Radev4e619f52017-08-09 11:50:06 +0300850void ProgramGL::enableSideBySideRenderingPath() const
851{
852 ASSERT(mState.usesMultiview());
853 ASSERT(mMultiviewBaseViewLayerIndexUniformLocation != -1);
854
855 ASSERT(mFunctions->programUniform1i != nullptr);
856 mFunctions->programUniform1i(mProgramID, mMultiviewBaseViewLayerIndexUniformLocation, -1);
857}
858
859void ProgramGL::enableLayeredRenderingPath(int baseViewIndex) const
860{
861 ASSERT(mState.usesMultiview());
862 ASSERT(mMultiviewBaseViewLayerIndexUniformLocation != -1);
863
864 ASSERT(mFunctions->programUniform1i != nullptr);
865 mFunctions->programUniform1i(mProgramID, mMultiviewBaseViewLayerIndexUniformLocation,
866 baseViewIndex);
867}
868
Jamie Madill54164b02017-08-28 15:17:37 -0400869void ProgramGL::getUniformfv(const gl::Context *context, GLint location, GLfloat *params) const
870{
871 mFunctions->getUniformfv(mProgramID, uniLoc(location), params);
872}
873
874void ProgramGL::getUniformiv(const gl::Context *context, GLint location, GLint *params) const
875{
876 mFunctions->getUniformiv(mProgramID, uniLoc(location), params);
877}
878
879void ProgramGL::getUniformuiv(const gl::Context *context, GLint location, GLuint *params) const
880{
881 mFunctions->getUniformuiv(mProgramID, uniLoc(location), params);
882}
883
Jamie Madillfb997ec2017-09-20 15:44:27 -0400884void ProgramGL::markUnusedUniformLocations(std::vector<gl::VariableLocation> *uniformLocations,
885 std::vector<gl::SamplerBinding> *samplerBindings)
Jamie Madill54164b02017-08-28 15:17:37 -0400886{
887 GLint maxLocation = static_cast<GLint>(uniformLocations->size());
888 for (GLint location = 0; location < maxLocation; ++location)
889 {
890 if (uniLoc(location) == -1)
891 {
Jamie Madillfb997ec2017-09-20 15:44:27 -0400892 auto &locationRef = (*uniformLocations)[location];
893 if (mState.isSamplerUniformIndex(locationRef.index))
894 {
895 GLuint samplerIndex = mState.getSamplerIndexFromUniformIndex(locationRef.index);
896 (*samplerBindings)[samplerIndex].unreferenced = true;
897 }
898 locationRef.markUnused();
Jamie Madill54164b02017-08-28 15:17:37 -0400899 }
900 }
901}
902
Jamie Madill6db1c2e2017-11-08 09:17:40 -0500903void ProgramGL::linkResources(const gl::ProgramLinkedResources &resources)
904{
905 // Gather interface block info.
906 auto getUniformBlockSize = [this](const std::string &name, const std::string &mappedName,
907 size_t *sizeOut) {
908 return this->getUniformBlockSize(name, mappedName, sizeOut);
909 };
910
911 auto getUniformBlockMemberInfo = [this](const std::string &name, const std::string &mappedName,
912 sh::BlockMemberInfo *infoOut) {
913 return this->getUniformBlockMemberInfo(name, mappedName, infoOut);
914 };
915
916 resources.uniformBlockLinker.linkBlocks(getUniformBlockSize, getUniformBlockMemberInfo);
917
Jiajia Qin3a9090f2017-09-27 14:37:04 +0800918 auto getShaderStorageBlockSize = [this](const std::string &name, const std::string &mappedName,
919 size_t *sizeOut) {
920 return this->getShaderStorageBlockSize(name, mappedName, sizeOut);
Jamie Madill6db1c2e2017-11-08 09:17:40 -0500921 };
922
Jiajia Qin3a9090f2017-09-27 14:37:04 +0800923 auto getShaderStorageBlockMemberInfo = [this](const std::string &name,
924 const std::string &mappedName,
925 sh::BlockMemberInfo *infoOut) {
926 return this->getShaderStorageBlockMemberInfo(name, mappedName, infoOut);
927 };
Jamie Madill6db1c2e2017-11-08 09:17:40 -0500928 resources.shaderStorageBlockLinker.linkBlocks(getShaderStorageBlockSize,
929 getShaderStorageBlockMemberInfo);
Jiajia Qin94f1e892017-11-20 12:14:32 +0800930
931 // Gather atomic counter buffer info.
932 std::map<int, unsigned int> sizeMap;
933 getAtomicCounterBufferSizeMap(&sizeMap);
934 resources.atomicCounterBufferLinker.link(sizeMap);
Jamie Madill6db1c2e2017-11-08 09:17:40 -0500935}
936
Jamie Madill4a3c2342015-10-08 12:58:45 -0400937} // namespace rx