blob: 7ca08e9e95be960f5b82ff0bb7719d5b4a6ca96d [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"
Geoff Langf9a6f082015-01-22 13:32:49 -050012#include "common/debug.h"
Sami Väisänen46eaa942016-06-29 10:26:37 +030013#include "common/string_utils.h"
Geoff Lang5ed74cf2015-04-14 13:57:07 -040014#include "common/utilities.h"
Geoff Langb1f435e2015-02-20 10:01:01 -050015#include "libANGLE/renderer/gl/FunctionsGL.h"
16#include "libANGLE/renderer/gl/ShaderGL.h"
17#include "libANGLE/renderer/gl/StateManagerGL.h"
Philippe Hamel40911192016-04-07 16:45:50 -040018#include "libANGLE/renderer/gl/WorkaroundsGL.h"
Jamie Madill53ea9cc2016-05-17 10:12:52 -040019#include "libANGLE/Uniform.h"
unknownb4a3af22015-11-25 15:02:51 -050020#include "platform/Platform.h"
Geoff Langf9a6f082015-01-22 13:32:49 -050021
22namespace rx
23{
24
Jamie Madill48ef11b2016-04-27 15:21:52 -040025ProgramGL::ProgramGL(const gl::ProgramState &data,
Jamie Madill5c6b7bf2015-08-17 12:53:35 -040026 const FunctionsGL *functions,
Philippe Hamel40911192016-04-07 16:45:50 -040027 const WorkaroundsGL &workarounds,
Sami Väisänen46eaa942016-06-29 10:26:37 +030028 StateManagerGL *stateManager,
29 bool enablePathRendering)
Philippe Hamel40911192016-04-07 16:45:50 -040030 : ProgramImpl(data),
31 mFunctions(functions),
32 mWorkarounds(workarounds),
33 mStateManager(stateManager),
Sami Väisänen46eaa942016-06-29 10:26:37 +030034 mEnablePathRendering(enablePathRendering),
Philippe Hamel40911192016-04-07 16:45:50 -040035 mProgramID(0)
Geoff Langb1f435e2015-02-20 10:01:01 -050036{
37 ASSERT(mFunctions);
38 ASSERT(mStateManager);
Geoff Lang0ca53782015-05-07 13:49:39 -040039
40 mProgramID = mFunctions->createProgram();
Geoff Langb1f435e2015-02-20 10:01:01 -050041}
Geoff Langf9a6f082015-01-22 13:32:49 -050042
43ProgramGL::~ProgramGL()
Geoff Langb1f435e2015-02-20 10:01:01 -050044{
Geoff Lang0ca53782015-05-07 13:49:39 -040045 mFunctions->deleteProgram(mProgramID);
46 mProgramID = 0;
Geoff Langb1f435e2015-02-20 10:01:01 -050047}
Geoff Langf9a6f082015-01-22 13:32:49 -050048
Geoff Langf9a6f082015-01-22 13:32:49 -050049LinkResult ProgramGL::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
50{
Geoff Lang65a0be92015-10-02 09:57:30 -040051 preLink();
52
53 // Read the binary format, size and blob
54 GLenum binaryFormat = stream->readInt<GLenum>();
55 GLint binaryLength = stream->readInt<GLint>();
56 const uint8_t *binary = stream->data() + stream->offset();
57 stream->skip(binaryLength);
58
59 // Load the binary
60 mFunctions->programBinary(mProgramID, binaryFormat, binary, binaryLength);
61
62 // Verify that the program linked
63 if (!checkLinkStatus(infoLog))
64 {
65 return LinkResult(false, gl::Error(GL_NO_ERROR));
66 }
67
68 postLink();
69
70 return LinkResult(true, gl::Error(GL_NO_ERROR));
Geoff Langf9a6f082015-01-22 13:32:49 -050071}
72
73gl::Error ProgramGL::save(gl::BinaryOutputStream *stream)
74{
Geoff Lang65a0be92015-10-02 09:57:30 -040075 GLint binaryLength = 0;
76 mFunctions->getProgramiv(mProgramID, GL_PROGRAM_BINARY_LENGTH, &binaryLength);
77
78 std::vector<uint8_t> binary(binaryLength);
79 GLenum binaryFormat = GL_NONE;
80 mFunctions->getProgramBinary(mProgramID, binaryLength, &binaryLength, &binaryFormat,
81 &binary[0]);
82
83 stream->writeInt(binaryFormat);
84 stream->writeInt(binaryLength);
85 stream->writeBytes(&binary[0], binaryLength);
86
87 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -050088}
89
Geoff Langc5629752015-12-07 16:29:04 -050090void ProgramGL::setBinaryRetrievableHint(bool retrievable)
91{
Geoff Lang65a0be92015-10-02 09:57:30 -040092 // glProgramParameteri isn't always available on ES backends.
93 if (mFunctions->programParameteri)
94 {
95 mFunctions->programParameteri(mProgramID, GL_PROGRAM_BINARY_RETRIEVABLE_HINT,
96 retrievable ? GL_TRUE : GL_FALSE);
97 }
Geoff Langc5629752015-12-07 16:29:04 -050098}
99
Jamie Madill9082b982016-04-27 15:21:51 -0400100LinkResult ProgramGL::link(const gl::ContextState &data, gl::InfoLog &infoLog)
Geoff Langf9a6f082015-01-22 13:32:49 -0500101{
Geoff Lang65a0be92015-10-02 09:57:30 -0400102 preLink();
Geoff Langb1f435e2015-02-20 10:01:01 -0500103
Martin Radev4c4c8e72016-08-04 12:25:34 +0300104 if (mState.getAttachedComputeShader())
Geoff Lang1a683462015-09-29 15:09:59 -0400105 {
Martin Radev4c4c8e72016-08-04 12:25:34 +0300106 const ShaderGL *computeShaderGL = GetImplAs<ShaderGL>(mState.getAttachedComputeShader());
Geoff Lang1a683462015-09-29 15:09:59 -0400107
Martin Radev4c4c8e72016-08-04 12:25:34 +0300108 mFunctions->attachShader(mProgramID, computeShaderGL->getShaderID());
109
110 // Link and verify
111 mFunctions->linkProgram(mProgramID);
112
113 // Detach the shaders
114 mFunctions->detachShader(mProgramID, computeShaderGL->getShaderID());
Geoff Lang1a683462015-09-29 15:09:59 -0400115 }
116 else
117 {
Martin Radev4c4c8e72016-08-04 12:25:34 +0300118 // Set the transform feedback state
119 std::vector<const GLchar *> transformFeedbackVaryings;
120 for (const auto &tfVarying : mState.getTransformFeedbackVaryingNames())
Geoff Lang1528e562015-08-24 15:10:58 -0400121 {
Martin Radev4c4c8e72016-08-04 12:25:34 +0300122 transformFeedbackVaryings.push_back(tfVarying.c_str());
Geoff Lang1528e562015-08-24 15:10:58 -0400123 }
124
Martin Radev4c4c8e72016-08-04 12:25:34 +0300125 if (transformFeedbackVaryings.empty())
126 {
127 if (mFunctions->transformFeedbackVaryings)
128 {
129 mFunctions->transformFeedbackVaryings(mProgramID, 0, nullptr,
130 mState.getTransformFeedbackBufferMode());
131 }
132 }
133 else
134 {
135 ASSERT(mFunctions->transformFeedbackVaryings);
136 mFunctions->transformFeedbackVaryings(
137 mProgramID, static_cast<GLsizei>(transformFeedbackVaryings.size()),
138 &transformFeedbackVaryings[0], mState.getTransformFeedbackBufferMode());
139 }
140
141 const ShaderGL *vertexShaderGL = GetImplAs<ShaderGL>(mState.getAttachedVertexShader());
142 const ShaderGL *fragmentShaderGL = GetImplAs<ShaderGL>(mState.getAttachedFragmentShader());
143
144 // Attach the shaders
145 mFunctions->attachShader(mProgramID, vertexShaderGL->getShaderID());
146 mFunctions->attachShader(mProgramID, fragmentShaderGL->getShaderID());
147
148 // Bind attribute locations to match the GL layer.
149 for (const sh::Attribute &attribute : mState.getAttributes())
150 {
151 if (!attribute.staticUse)
152 {
153 continue;
154 }
155
156 mFunctions->bindAttribLocation(mProgramID, attribute.location, attribute.name.c_str());
157 }
158
159 // Link and verify
160 mFunctions->linkProgram(mProgramID);
161
162 // Detach the shaders
163 mFunctions->detachShader(mProgramID, vertexShaderGL->getShaderID());
164 mFunctions->detachShader(mProgramID, fragmentShaderGL->getShaderID());
Geoff Lang1528e562015-08-24 15:10:58 -0400165 }
166
Geoff Lang0ca53782015-05-07 13:49:39 -0400167 // Verify the link
Geoff Lang65a0be92015-10-02 09:57:30 -0400168 if (!checkLinkStatus(infoLog))
Geoff Langb1f435e2015-02-20 10:01:01 -0500169 {
Geoff Langb1f435e2015-02-20 10:01:01 -0500170 return LinkResult(false, gl::Error(GL_NO_ERROR));
171 }
172
Philippe Hamel40911192016-04-07 16:45:50 -0400173 if (mWorkarounds.alwaysCallUseProgramAfterLink)
174 {
175 mStateManager->forceUseProgram(mProgramID);
176 }
177
Geoff Lang65a0be92015-10-02 09:57:30 -0400178 postLink();
Geoff Langb1f435e2015-02-20 10:01:01 -0500179
Geoff Langb1f435e2015-02-20 10:01:01 -0500180 return LinkResult(true, gl::Error(GL_NO_ERROR));
Geoff Langf9a6f082015-01-22 13:32:49 -0500181}
182
Jamie Madill36cfd6a2015-08-18 10:46:20 -0400183GLboolean ProgramGL::validate(const gl::Caps & /*caps*/, gl::InfoLog * /*infoLog*/)
184{
185 // TODO(jmadill): implement validate
186 return true;
187}
188
Geoff Langf9a6f082015-01-22 13:32:49 -0500189void ProgramGL::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
190{
Geoff Lang63cbace2015-02-26 10:03:12 -0500191 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400192 mFunctions->uniform1fv(uniLoc(location), count, v);
Geoff Langf9a6f082015-01-22 13:32:49 -0500193}
194
195void ProgramGL::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
196{
Geoff Lang63cbace2015-02-26 10:03:12 -0500197 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400198 mFunctions->uniform2fv(uniLoc(location), count, v);
Geoff Langf9a6f082015-01-22 13:32:49 -0500199}
200
201void ProgramGL::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
202{
Geoff Lang63cbace2015-02-26 10:03:12 -0500203 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400204 mFunctions->uniform3fv(uniLoc(location), count, v);
Geoff Langf9a6f082015-01-22 13:32:49 -0500205}
206
207void ProgramGL::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
208{
Geoff Lang63cbace2015-02-26 10:03:12 -0500209 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400210 mFunctions->uniform4fv(uniLoc(location), count, v);
Geoff Langf9a6f082015-01-22 13:32:49 -0500211}
212
213void ProgramGL::setUniform1iv(GLint location, GLsizei count, const GLint *v)
214{
Geoff Lang63cbace2015-02-26 10:03:12 -0500215 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400216 mFunctions->uniform1iv(uniLoc(location), count, v);
Geoff Langf51bc792015-05-04 14:57:03 -0400217
Jamie Madill48ef11b2016-04-27 15:21:52 -0400218 const gl::VariableLocation &locationEntry = mState.getUniformLocations()[location];
Jamie Madill62d31cb2015-09-11 13:25:51 -0400219
220 size_t samplerIndex = mUniformIndexToSamplerIndex[locationEntry.index];
221 if (samplerIndex != GL_INVALID_INDEX)
Geoff Langf51bc792015-05-04 14:57:03 -0400222 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400223 std::vector<GLuint> &boundTextureUnits = mSamplerBindings[samplerIndex].boundTextureUnits;
Geoff Langf51bc792015-05-04 14:57:03 -0400224
Jamie Madill62d31cb2015-09-11 13:25:51 -0400225 size_t copyCount =
Corentin Wallez4c5ff002016-10-25 09:32:17 -0400226 std::min<size_t>(count, boundTextureUnits.size() - locationEntry.element);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400227 std::copy(v, v + copyCount, boundTextureUnits.begin() + locationEntry.element);
Geoff Langf51bc792015-05-04 14:57:03 -0400228 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500229}
230
231void ProgramGL::setUniform2iv(GLint location, GLsizei count, const GLint *v)
232{
Geoff Lang63cbace2015-02-26 10:03:12 -0500233 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400234 mFunctions->uniform2iv(uniLoc(location), count, v);
Geoff Langf9a6f082015-01-22 13:32:49 -0500235}
236
237void ProgramGL::setUniform3iv(GLint location, GLsizei count, const GLint *v)
238{
Geoff Lang63cbace2015-02-26 10:03:12 -0500239 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400240 mFunctions->uniform3iv(uniLoc(location), count, v);
Geoff Langf9a6f082015-01-22 13:32:49 -0500241}
242
243void ProgramGL::setUniform4iv(GLint location, GLsizei count, const GLint *v)
244{
Geoff Lang63cbace2015-02-26 10:03:12 -0500245 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400246 mFunctions->uniform4iv(uniLoc(location), count, v);
Geoff Langf9a6f082015-01-22 13:32:49 -0500247}
248
249void ProgramGL::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
250{
Geoff Lang63cbace2015-02-26 10:03:12 -0500251 mStateManager->useProgram(mProgramID);
Corentin Wallez171e6a52016-06-02 09:57:13 -0400252 mFunctions->uniform1uiv(uniLoc(location), count, v);
Geoff Langf9a6f082015-01-22 13:32:49 -0500253}
254
255void ProgramGL::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
256{
Geoff Lang63cbace2015-02-26 10:03:12 -0500257 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400258 mFunctions->uniform2uiv(uniLoc(location), count, v);
Geoff Langf9a6f082015-01-22 13:32:49 -0500259}
260
261void ProgramGL::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
262{
Geoff Lang63cbace2015-02-26 10:03:12 -0500263 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400264 mFunctions->uniform3uiv(uniLoc(location), count, v);
Geoff Langf9a6f082015-01-22 13:32:49 -0500265}
266
267void ProgramGL::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
268{
Geoff Lang63cbace2015-02-26 10:03:12 -0500269 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400270 mFunctions->uniform4uiv(uniLoc(location), count, v);
Geoff Langf9a6f082015-01-22 13:32:49 -0500271}
272
273void ProgramGL::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
274{
Geoff Lang63cbace2015-02-26 10:03:12 -0500275 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400276 mFunctions->uniformMatrix2fv(uniLoc(location), count, transpose, value);
Geoff Langf9a6f082015-01-22 13:32:49 -0500277}
278
279void ProgramGL::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
280{
Geoff Lang63cbace2015-02-26 10:03:12 -0500281 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400282 mFunctions->uniformMatrix3fv(uniLoc(location), count, transpose, value);
Geoff Langf9a6f082015-01-22 13:32:49 -0500283}
284
285void ProgramGL::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
286{
Geoff Lang63cbace2015-02-26 10:03:12 -0500287 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400288 mFunctions->uniformMatrix4fv(uniLoc(location), count, transpose, value);
Geoff Langf9a6f082015-01-22 13:32:49 -0500289}
290
291void ProgramGL::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
292{
Geoff Lang63cbace2015-02-26 10:03:12 -0500293 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400294 mFunctions->uniformMatrix2x3fv(uniLoc(location), count, transpose, value);
Geoff Langf9a6f082015-01-22 13:32:49 -0500295}
296
297void ProgramGL::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
298{
Geoff Lang63cbace2015-02-26 10:03:12 -0500299 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400300 mFunctions->uniformMatrix3x2fv(uniLoc(location), count, transpose, value);
Geoff Langf9a6f082015-01-22 13:32:49 -0500301}
302
303void ProgramGL::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
304{
Geoff Lang63cbace2015-02-26 10:03:12 -0500305 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400306 mFunctions->uniformMatrix2x4fv(uniLoc(location), count, transpose, value);
Geoff Langf9a6f082015-01-22 13:32:49 -0500307}
308
309void ProgramGL::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
310{
Geoff Lang63cbace2015-02-26 10:03:12 -0500311 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400312 mFunctions->uniformMatrix4x2fv(uniLoc(location), count, transpose, value);
Geoff Langf9a6f082015-01-22 13:32:49 -0500313}
314
315void ProgramGL::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
316{
Geoff Lang63cbace2015-02-26 10:03:12 -0500317 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400318 mFunctions->uniformMatrix3x4fv(uniLoc(location), count, transpose, value);
Geoff Langf9a6f082015-01-22 13:32:49 -0500319}
320
321void ProgramGL::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
322{
Geoff Lang63cbace2015-02-26 10:03:12 -0500323 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400324 mFunctions->uniformMatrix4x3fv(uniLoc(location), count, transpose, value);
Geoff Langf9a6f082015-01-22 13:32:49 -0500325}
326
Geoff Lang5d124a62015-09-15 13:03:27 -0400327void ProgramGL::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
328{
Jamie Madill4a3c2342015-10-08 12:58:45 -0400329 // Lazy init
330 if (mUniformBlockRealLocationMap.empty())
331 {
Jamie Madill48ef11b2016-04-27 15:21:52 -0400332 mUniformBlockRealLocationMap.reserve(mState.getUniformBlocks().size());
333 for (const gl::UniformBlock &uniformBlock : mState.getUniformBlocks())
Jamie Madill4a3c2342015-10-08 12:58:45 -0400334 {
335 const std::string &nameWithIndex = uniformBlock.nameWithArrayIndex();
336 GLuint blockIndex = mFunctions->getUniformBlockIndex(mProgramID, nameWithIndex.c_str());
337 mUniformBlockRealLocationMap.push_back(blockIndex);
338 }
339 }
340
341 GLuint realBlockIndex = mUniformBlockRealLocationMap[uniformBlockIndex];
342 if (realBlockIndex != GL_INVALID_INDEX)
343 {
344 mFunctions->uniformBlockBinding(mProgramID, realBlockIndex, uniformBlockBinding);
345 }
Geoff Lang5d124a62015-09-15 13:03:27 -0400346}
347
Geoff Langb1f435e2015-02-20 10:01:01 -0500348GLuint ProgramGL::getProgramID() const
349{
350 return mProgramID;
351}
352
Geoff Langf51bc792015-05-04 14:57:03 -0400353const std::vector<SamplerBindingGL> &ProgramGL::getAppliedSamplerUniforms() const
354{
355 return mSamplerBindings;
356}
357
Jamie Madill4a3c2342015-10-08 12:58:45 -0400358bool ProgramGL::getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const
Jamie Madill62d31cb2015-09-11 13:25:51 -0400359{
Jamie Madill4a3c2342015-10-08 12:58:45 -0400360 ASSERT(mProgramID != 0u);
Geoff Lang5d124a62015-09-15 13:03:27 -0400361
Jamie Madill4a3c2342015-10-08 12:58:45 -0400362 GLuint blockIndex = mFunctions->getUniformBlockIndex(mProgramID, blockName.c_str());
363 if (blockIndex == GL_INVALID_INDEX)
Geoff Lang5d124a62015-09-15 13:03:27 -0400364 {
Jamie Madill4a3c2342015-10-08 12:58:45 -0400365 *sizeOut = 0;
366 return false;
Geoff Lang5d124a62015-09-15 13:03:27 -0400367 }
368
Jamie Madill4a3c2342015-10-08 12:58:45 -0400369 GLint dataSize = 0;
370 mFunctions->getActiveUniformBlockiv(mProgramID, blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE,
371 &dataSize);
372 *sizeOut = static_cast<size_t>(dataSize);
373 return true;
374}
375
376bool ProgramGL::getUniformBlockMemberInfo(const std::string &memberUniformName,
377 sh::BlockMemberInfo *memberInfoOut) const
378{
379 GLuint uniformIndex;
380 const GLchar *memberNameGLStr = memberUniformName.c_str();
381 mFunctions->getUniformIndices(mProgramID, 1, &memberNameGLStr, &uniformIndex);
382
383 if (uniformIndex == GL_INVALID_INDEX)
Geoff Lang5d124a62015-09-15 13:03:27 -0400384 {
Jamie Madill4a3c2342015-10-08 12:58:45 -0400385 *memberInfoOut = sh::BlockMemberInfo::getDefaultBlockInfo();
386 return false;
Geoff Lang5d124a62015-09-15 13:03:27 -0400387 }
Jamie Madill4a3c2342015-10-08 12:58:45 -0400388
389 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_OFFSET,
390 &memberInfoOut->offset);
391 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_ARRAY_STRIDE,
392 &memberInfoOut->arrayStride);
393 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_MATRIX_STRIDE,
394 &memberInfoOut->matrixStride);
395
396 // TODO(jmadill): possibly determine this at the gl::Program level.
397 GLint isRowMajorMatrix = 0;
398 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_IS_ROW_MAJOR,
399 &isRowMajorMatrix);
400 memberInfoOut->isRowMajorMatrix = isRowMajorMatrix != GL_FALSE;
401 return true;
Jamie Madill62d31cb2015-09-11 13:25:51 -0400402}
Jamie Madill4a3c2342015-10-08 12:58:45 -0400403
Sami Väisänen46eaa942016-06-29 10:26:37 +0300404void ProgramGL::setPathFragmentInputGen(const std::string &inputName,
405 GLenum genMode,
406 GLint components,
407 const GLfloat *coeffs)
408{
409 ASSERT(mEnablePathRendering);
410
411 for (const auto &input : mPathRenderingFragmentInputs)
412 {
413 if (input.name == inputName)
414 {
415 mFunctions->programPathFragmentInputGenNV(mProgramID, input.location, genMode,
416 components, coeffs);
417 ASSERT(mFunctions->getError() == GL_NO_ERROR);
418 return;
419 }
420 }
421
422}
423
Geoff Lang65a0be92015-10-02 09:57:30 -0400424void ProgramGL::preLink()
425{
426 // Reset the program state
427 mUniformRealLocationMap.clear();
428 mUniformBlockRealLocationMap.clear();
429 mSamplerBindings.clear();
430 mUniformIndexToSamplerIndex.clear();
Sami Väisänen46eaa942016-06-29 10:26:37 +0300431 mPathRenderingFragmentInputs.clear();
Geoff Lang65a0be92015-10-02 09:57:30 -0400432}
433
434bool ProgramGL::checkLinkStatus(gl::InfoLog &infoLog)
435{
436 GLint linkStatus = GL_FALSE;
437 mFunctions->getProgramiv(mProgramID, GL_LINK_STATUS, &linkStatus);
438 if (linkStatus == GL_FALSE)
439 {
440 // Linking failed, put the error into the info log
441 GLint infoLogLength = 0;
442 mFunctions->getProgramiv(mProgramID, GL_INFO_LOG_LENGTH, &infoLogLength);
443
444 std::string warning;
445
446 // Info log length includes the null terminator, so 1 means that the info log is an empty
447 // string.
448 if (infoLogLength > 1)
449 {
450 std::vector<char> buf(infoLogLength);
451 mFunctions->getProgramInfoLog(mProgramID, infoLogLength, nullptr, &buf[0]);
452
453 mFunctions->deleteProgram(mProgramID);
454 mProgramID = 0;
455
456 infoLog << buf.data();
457
458 warning = FormatString("Program link failed unexpectedly: %s", buf.data());
459 }
460 else
461 {
462 warning = "Program link failed unexpectedly with no info log.";
463 }
464 ANGLEPlatformCurrent()->logWarning(warning.c_str());
465 TRACE("\n%s", warning.c_str());
466
467 // TODO, return GL_OUT_OF_MEMORY or just fail the link? This is an unexpected case
468 return false;
469 }
470
471 return true;
472}
473
474void ProgramGL::postLink()
475{
476 // Query the uniform information
477 ASSERT(mUniformRealLocationMap.empty());
Jamie Madill48ef11b2016-04-27 15:21:52 -0400478 const auto &uniformLocations = mState.getUniformLocations();
479 const auto &uniforms = mState.getUniforms();
Geoff Lang65a0be92015-10-02 09:57:30 -0400480 mUniformRealLocationMap.resize(uniformLocations.size(), GL_INVALID_INDEX);
481 for (size_t uniformLocation = 0; uniformLocation < uniformLocations.size(); uniformLocation++)
482 {
483 const auto &entry = uniformLocations[uniformLocation];
484 if (!entry.used)
485 {
486 continue;
487 }
488
489 // From the spec:
490 // "Locations for sequential array indices are not required to be sequential."
491 const gl::LinkedUniform &uniform = uniforms[entry.index];
492 std::stringstream fullNameStr;
493 fullNameStr << uniform.name;
494 if (uniform.isArray())
495 {
496 fullNameStr << "[" << entry.element << "]";
497 }
498 const std::string &fullName = fullNameStr.str();
499
500 GLint realLocation = mFunctions->getUniformLocation(mProgramID, fullName.c_str());
501 mUniformRealLocationMap[uniformLocation] = realLocation;
502 }
503
Jamie Madill48ef11b2016-04-27 15:21:52 -0400504 mUniformIndexToSamplerIndex.resize(mState.getUniforms().size(), GL_INVALID_INDEX);
Geoff Lang65a0be92015-10-02 09:57:30 -0400505
506 for (size_t uniformId = 0; uniformId < uniforms.size(); ++uniformId)
507 {
508 const gl::LinkedUniform &linkedUniform = uniforms[uniformId];
509
510 if (!linkedUniform.isSampler() || !linkedUniform.staticUse)
511 continue;
512
513 mUniformIndexToSamplerIndex[uniformId] = mSamplerBindings.size();
514
515 // If uniform is a sampler type, insert it into the mSamplerBindings array
516 SamplerBindingGL samplerBinding;
517 samplerBinding.textureType = gl::SamplerTypeToTextureType(linkedUniform.type);
518 samplerBinding.boundTextureUnits.resize(linkedUniform.elementCount(), 0);
519 mSamplerBindings.push_back(samplerBinding);
520 }
Sami Väisänen46eaa942016-06-29 10:26:37 +0300521
522 // Discover CHROMIUM_path_rendering fragment inputs if enabled.
523 if (!mEnablePathRendering)
524 return;
525
526 GLint numFragmentInputs = 0;
527 mFunctions->getProgramInterfaceiv(mProgramID, GL_FRAGMENT_INPUT_NV, GL_ACTIVE_RESOURCES,
528 &numFragmentInputs);
529 if (numFragmentInputs <= 0)
530 return;
531
532 GLint maxNameLength = 0;
533 mFunctions->getProgramInterfaceiv(mProgramID, GL_FRAGMENT_INPUT_NV, GL_MAX_NAME_LENGTH,
534 &maxNameLength);
535 ASSERT(maxNameLength);
536
537 for (GLint i = 0; i < numFragmentInputs; ++i)
538 {
539 std::string name;
540 name.resize(maxNameLength);
541
542 GLsizei nameLen = 0;
543 mFunctions->getProgramResourceName(mProgramID, GL_FRAGMENT_INPUT_NV, i, maxNameLength,
544 &nameLen, &name[0]);
545 name.resize(nameLen);
546
547 // Ignore built-ins
548 if (angle::BeginsWith(name, "gl_"))
549 continue;
550
551 const GLenum kQueryProperties[] = {GL_LOCATION, GL_ARRAY_SIZE};
552 GLint queryResults[ArraySize(kQueryProperties)];
553 GLsizei queryLength = 0;
554
Geoff Lang3f6a3982016-07-15 15:20:45 -0400555 mFunctions->getProgramResourceiv(
556 mProgramID, GL_FRAGMENT_INPUT_NV, i, static_cast<GLsizei>(ArraySize(kQueryProperties)),
557 kQueryProperties, static_cast<GLsizei>(ArraySize(queryResults)), &queryLength,
558 queryResults);
Sami Väisänen46eaa942016-06-29 10:26:37 +0300559
Olli Etuahoe3191712016-07-18 16:01:10 +0300560 ASSERT(queryLength == static_cast<GLsizei>(ArraySize(kQueryProperties)));
Sami Väisänen46eaa942016-06-29 10:26:37 +0300561
Geoff Lang3f6a3982016-07-15 15:20:45 -0400562 PathRenderingFragmentInput baseElementInput;
563 baseElementInput.name = name;
564 baseElementInput.location = queryResults[0];
565 mPathRenderingFragmentInputs.push_back(std::move(baseElementInput));
Sami Väisänen46eaa942016-06-29 10:26:37 +0300566
567 // If the input is an array it's denoted by [0] suffix on the variable
568 // name. We'll then create an entry per each array index where index > 0
569 if (angle::EndsWith(name, "[0]"))
570 {
571 // drop the suffix
572 name.resize(name.size() - 3);
573
574 const auto arraySize = queryResults[1];
575 const auto baseLocation = queryResults[0];
576
Geoff Lang3f6a3982016-07-15 15:20:45 -0400577 for (GLint arrayIndex = 1; arrayIndex < arraySize; ++arrayIndex)
Sami Väisänen46eaa942016-06-29 10:26:37 +0300578 {
Geoff Lang3f6a3982016-07-15 15:20:45 -0400579 PathRenderingFragmentInput arrayElementInput;
Corentin Wallez054f7ed2016-09-20 17:15:59 -0400580 arrayElementInput.name = name + "[" + ToString(arrayIndex) + "]";
Geoff Lang3f6a3982016-07-15 15:20:45 -0400581 arrayElementInput.location = baseLocation + arrayIndex;
582 mPathRenderingFragmentInputs.push_back(std::move(arrayElementInput));
Sami Väisänen46eaa942016-06-29 10:26:37 +0300583 }
584 }
585 }
Geoff Lang65a0be92015-10-02 09:57:30 -0400586}
587
Jamie Madill4a3c2342015-10-08 12:58:45 -0400588} // namespace rx