Commit 48705cad by Jamie Madill

Revert "Move Uniform and UBO info to the gl::Program layer."

Seems to be failing dEQP-GLES2.functional.uniform_api.value.unused_uniforms.* on Linux (possibly Win as well) BUG=angleproject:1123 This reverts commit 54f882c9. Change-Id: I7dbbf40aae8dd9ebd35895df0dd338a3b6b9cc96 Reviewed-on: https://chromium-review.googlesource.com/297051Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Tested-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 54f882c9
......@@ -26,8 +26,6 @@ struct InterfaceBlock;
struct COMPILER_EXPORT BlockMemberInfo
{
BlockMemberInfo() : offset(-1), arrayStride(-1), matrixStride(-1), isRowMajorMatrix(false) {}
BlockMemberInfo(int offset, int arrayStride, int matrixStride, bool isRowMajorMatrix)
: offset(offset),
arrayStride(arrayStride),
......
......@@ -46,65 +46,8 @@ unsigned int ParseAndStripArrayIndex(std::string* name)
return subscript;
}
void WriteShaderVar(BinaryOutputStream *stream, const sh::ShaderVariable &var)
{
stream->writeInt(var.type);
stream->writeInt(var.precision);
stream->writeString(var.name);
stream->writeString(var.mappedName);
stream->writeInt(var.arraySize);
stream->writeInt(var.staticUse);
stream->writeString(var.structName);
ASSERT(var.fields.empty());
}
void LoadShaderVar(BinaryInputStream *stream, sh::ShaderVariable *var)
{
var->type = stream->readInt<GLenum>();
var->precision = stream->readInt<GLenum>();
var->name = stream->readString();
var->mappedName = stream->readString();
var->arraySize = stream->readInt<unsigned int>();
var->staticUse = stream->readBool();
var->structName = stream->readString();
}
template <typename VarT>
void DefineUniformBlockMembers(const std::vector<VarT> &fields,
const std::string &prefix,
int blockIndex,
std::vector<LinkedUniform> *uniformsOut)
{
for (const VarT &field : fields)
{
const std::string &fieldName = (prefix.empty() ? field.name : prefix + "." + field.name);
if (field.isStruct())
{
for (unsigned int arrayElement = 0; arrayElement < field.elementCount(); arrayElement++)
{
const std::string uniformElementName =
fieldName + (field.isArray() ? ArrayString(arrayElement) : "");
DefineUniformBlockMembers(field.fields, uniformElementName, blockIndex,
uniformsOut);
}
}
else
{
// TODO(jmadill): record row-majorness?
// Block layout is recorded in the Impl.
LinkedUniform newUniform(field.type, field.precision, fieldName, field.arraySize,
blockIndex, sh::BlockMemberInfo::getDefaultBlockInfo());
// Since block uniforms have no location, we don't need to store them in the uniform
// locations list.
uniformsOut->push_back(newUniform);
}
}
}
} // anonymous namespace
AttributeBindings::AttributeBindings()
{
}
......@@ -219,68 +162,6 @@ Program::Data::~Data()
}
}
const LinkedUniform *Program::Data::getUniformByName(const std::string &name) const
{
for (const LinkedUniform &linkedUniform : mUniforms)
{
if (linkedUniform.name == name)
{
return &linkedUniform;
}
}
return nullptr;
}
GLint Program::Data::getUniformLocation(const std::string &name) const
{
size_t subscript = GL_INVALID_INDEX;
std::string baseName = gl::ParseUniformName(name, &subscript);
for (size_t location = 0; location < mUniformLocations.size(); ++location)
{
const VariableLocation &uniformLocation = mUniformLocations[location];
const LinkedUniform &uniform = mUniforms[uniformLocation.index];
if (uniform.name == baseName)
{
if ((uniform.isArray() && uniformLocation.element == subscript) ||
(subscript == GL_INVALID_INDEX))
{
return static_cast<GLint>(location);
}
}
}
return -1;
}
GLuint Program::Data::getUniformIndex(const std::string &name) const
{
size_t subscript = GL_INVALID_INDEX;
std::string baseName = gl::ParseUniformName(name, &subscript);
// The app is not allowed to specify array indices other than 0 for arrays of basic types
if (subscript != 0 && subscript != GL_INVALID_INDEX)
{
return GL_INVALID_INDEX;
}
for (size_t index = 0; index < mUniforms.size(); index++)
{
const LinkedUniform &uniform = mUniforms[index];
if (uniform.name == baseName)
{
if (uniform.isArray() || subscript == GL_INVALID_INDEX)
{
return static_cast<GLuint>(index);
}
}
}
return GL_INVALID_INDEX;
}
Program::Program(rx::ImplFactory *factory, ResourceManager *manager, GLuint handle)
: mProgram(factory->createProgram(mData)),
mValidated(false),
......@@ -438,7 +319,6 @@ Error Program::link(const gl::Data &data)
}
gatherTransformFeedbackVaryings(mergedVaryings);
mProgram->gatherUniformBlockInfo(&mData.mUniformBlocks, &mData.mUniforms);
mLinked = true;
return gl::Error(GL_NO_ERROR);
......@@ -478,11 +358,10 @@ void Program::unlink(bool destroy)
mData.mAttributes.clear();
mData.mActiveAttribLocationsMask.reset();
mData.mTransformFeedbackVaryingVars.clear();
mData.mUniforms.clear();
mData.mUniformLocations.clear();
mData.mUniformBlocks.clear();
mData.mOutputVariables.clear();
mProgram->reset();
mValidated = false;
mLinked = false;
......@@ -536,66 +415,15 @@ Error Program::loadBinary(GLenum binaryFormat, const void *binary, GLsizei lengt
for (unsigned int attribIndex = 0; attribIndex < attribCount; ++attribIndex)
{
sh::Attribute attrib;
LoadShaderVar(&stream, &attrib);
attrib.location = stream.readInt<int>();
attrib.type = stream.readInt<GLenum>();
attrib.precision = stream.readInt<GLenum>();
attrib.name = stream.readString();
attrib.arraySize = stream.readInt<GLint>();
attrib.location = stream.readInt<int>();
attrib.staticUse = stream.readBool();
mData.mAttributes.push_back(attrib);
}
unsigned int uniformCount = stream.readInt<unsigned int>();
ASSERT(mData.mUniforms.empty());
for (unsigned int uniformIndex = 0; uniformIndex < uniformCount; ++uniformIndex)
{
LinkedUniform uniform;
LoadShaderVar(&stream, &uniform);
uniform.blockIndex = stream.readInt<int>();
uniform.blockInfo.offset = stream.readInt<int>();
uniform.blockInfo.arrayStride = stream.readInt<int>();
uniform.blockInfo.matrixStride = stream.readInt<int>();
uniform.blockInfo.isRowMajorMatrix = stream.readBool();
mData.mUniforms.push_back(uniform);
}
const unsigned int uniformIndexCount = stream.readInt<unsigned int>();
ASSERT(mData.mUniformLocations.empty());
for (unsigned int uniformIndexIndex = 0; uniformIndexIndex < uniformIndexCount;
uniformIndexIndex++)
{
VariableLocation variable;
stream.readString(&variable.name);
stream.readInt(&variable.element);
stream.readInt(&variable.index);
mData.mUniformLocations.push_back(variable);
}
unsigned int uniformBlockCount = stream.readInt<unsigned int>();
ASSERT(mData.mUniformBlocks.empty());
for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < uniformBlockCount;
++uniformBlockIndex)
{
UniformBlock uniformBlock;
stream.readString(&uniformBlock.name);
stream.readBool(&uniformBlock.isArray);
stream.readInt(&uniformBlock.arrayElement);
stream.readInt(&uniformBlock.dataSize);
stream.readBool(&uniformBlock.vertexStaticUse);
stream.readBool(&uniformBlock.fragmentStaticUse);
unsigned int numMembers = stream.readInt<unsigned int>();
for (unsigned int blockMemberIndex = 0; blockMemberIndex < numMembers; blockMemberIndex++)
{
uniformBlock.memberUniformIndexes.push_back(stream.readInt<unsigned int>());
}
// TODO(jmadill): Make D3D-only
stream.readInt(&uniformBlock.psRegisterIndex);
stream.readInt(&uniformBlock.vsRegisterIndex);
mData.mUniformBlocks.push_back(uniformBlock);
}
stream.readInt(&mData.mTransformFeedbackBufferMode);
unsigned int outputVarCount = stream.readInt<unsigned int>();
......@@ -639,52 +467,12 @@ Error Program::saveBinary(GLenum *binaryFormat, void *binary, GLsizei bufSize, G
stream.writeInt(mData.mAttributes.size());
for (const sh::Attribute &attrib : mData.mAttributes)
{
WriteShaderVar(&stream, attrib);
stream.writeInt(attrib.type);
stream.writeInt(attrib.precision);
stream.writeString(attrib.name);
stream.writeInt(attrib.arraySize);
stream.writeInt(attrib.location);
}
stream.writeInt(mData.mUniforms.size());
for (const gl::LinkedUniform &uniform : mData.mUniforms)
{
WriteShaderVar(&stream, uniform);
// FIXME: referenced
stream.writeInt(uniform.blockIndex);
stream.writeInt(uniform.blockInfo.offset);
stream.writeInt(uniform.blockInfo.arrayStride);
stream.writeInt(uniform.blockInfo.matrixStride);
stream.writeInt(uniform.blockInfo.isRowMajorMatrix);
}
stream.writeInt(mData.mUniformLocations.size());
for (const auto &variable : mData.mUniformLocations)
{
stream.writeString(variable.name);
stream.writeInt(variable.element);
stream.writeInt(variable.index);
}
stream.writeInt(mData.mUniformBlocks.size());
for (const UniformBlock &uniformBlock : mData.mUniformBlocks)
{
stream.writeString(uniformBlock.name);
stream.writeInt(uniformBlock.isArray);
stream.writeInt(uniformBlock.arrayElement);
stream.writeInt(uniformBlock.dataSize);
stream.writeInt(uniformBlock.vertexStaticUse);
stream.writeInt(uniformBlock.fragmentStaticUse);
stream.writeInt(uniformBlock.memberUniformIndexes.size());
for (unsigned int memberUniformIndex : uniformBlock.memberUniformIndexes)
{
stream.writeInt(memberUniformIndex);
}
// TODO(jmadill): make D3D-only
stream.writeInt(uniformBlock.psRegisterIndex);
stream.writeInt(uniformBlock.vsRegisterIndex);
stream.writeInt(attrib.staticUse);
}
stream.writeInt(mData.mTransformFeedbackBufferMode);
......@@ -940,14 +728,13 @@ void Program::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, G
{
if (mLinked)
{
// index must be smaller than getActiveUniformCount()
ASSERT(index < mData.mUniforms.size());
const LinkedUniform &uniform = mData.mUniforms[index];
ASSERT(index < mProgram->getUniforms().size()); // index must be smaller than getActiveUniformCount()
LinkedUniform *uniform = mProgram->getUniforms()[index];
if (bufsize > 0)
{
std::string string = uniform.name;
if (uniform.isArray())
std::string string = uniform->name;
if (uniform->isArray())
{
string += "[0]";
}
......@@ -961,8 +748,8 @@ void Program::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, G
}
}
*size = uniform.elementCount();
*type = uniform.type;
*size = uniform->elementCount();
*type = uniform->type;
}
else
{
......@@ -985,7 +772,7 @@ GLint Program::getActiveUniformCount()
{
if (mLinked)
{
return static_cast<GLint>(mData.mUniforms.size());
return static_cast<GLint>(mProgram->getUniforms().size());
}
else
{
......@@ -995,16 +782,17 @@ GLint Program::getActiveUniformCount()
GLint Program::getActiveUniformMaxLength()
{
size_t maxLength = 0;
int maxLength = 0;
if (mLinked)
{
for (const LinkedUniform &uniform : mData.mUniforms)
unsigned int numUniforms = static_cast<unsigned int>(mProgram->getUniforms().size());
for (unsigned int uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++)
{
if (!uniform.name.empty())
if (!mProgram->getUniforms()[uniformIndex]->name.empty())
{
size_t length = uniform.name.length() + 1u;
if (uniform.isArray())
int length = (int)(mProgram->getUniforms()[uniformIndex]->name.length() + 1);
if (mProgram->getUniforms()[uniformIndex]->isArray())
{
length += 3; // Counting in "[0]".
}
......@@ -1013,13 +801,12 @@ GLint Program::getActiveUniformMaxLength()
}
}
return static_cast<GLint>(maxLength);
return maxLength;
}
GLint Program::getActiveUniformi(GLuint index, GLenum pname) const
{
ASSERT(static_cast<size_t>(index) < mData.mUniforms.size());
const gl::LinkedUniform &uniform = mData.mUniforms[index];
const gl::LinkedUniform& uniform = *mProgram->getUniforms()[index];
switch (pname)
{
case GL_UNIFORM_TYPE: return static_cast<GLint>(uniform.type);
......@@ -1039,24 +826,29 @@ GLint Program::getActiveUniformi(GLuint index, GLenum pname) const
bool Program::isValidUniformLocation(GLint location) const
{
ASSERT(rx::IsIntegerCastSafe<GLint>(mData.mUniformLocations.size()));
return (location >= 0 && static_cast<size_t>(location) < mData.mUniformLocations.size());
const auto &uniformIndices = mProgram->getUniformIndices();
ASSERT(rx::IsIntegerCastSafe<GLint>(uniformIndices.size()));
return (location >= 0 && uniformIndices.find(location) != uniformIndices.end());
}
LinkedUniform *Program::getUniformByLocation(GLint location) const
{
return mProgram->getUniformByLocation(location);
}
const LinkedUniform &Program::getUniformByLocation(GLint location) const
LinkedUniform *Program::getUniformByName(const std::string &name) const
{
ASSERT(location >= 0 && static_cast<size_t>(location) < mData.mUniformLocations.size());
return mData.mUniforms[mData.mUniformLocations[location].index];
return mProgram->getUniformByName(name);
}
GLint Program::getUniformLocation(const std::string &name) const
GLint Program::getUniformLocation(const std::string &name)
{
return mData.getUniformLocation(name);
return mProgram->getUniformLocation(name);
}
GLuint Program::getUniformIndex(const std::string &name) const
GLuint Program::getUniformIndex(const std::string &name)
{
return mData.getUniformIndex(name);
return mProgram->getUniformIndex(name);
}
void Program::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
......@@ -1215,23 +1007,22 @@ bool Program::isValidated() const
GLuint Program::getActiveUniformBlockCount()
{
return static_cast<GLuint>(mData.mUniformBlocks.size());
return static_cast<GLuint>(mProgram->getUniformBlocks().size());
}
void Program::getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) const
{
ASSERT(uniformBlockIndex <
mData.mUniformBlocks.size()); // index must be smaller than getActiveUniformBlockCount()
ASSERT(uniformBlockIndex < mProgram->getUniformBlocks().size()); // index must be smaller than getActiveUniformBlockCount()
const UniformBlock &uniformBlock = mData.mUniformBlocks[uniformBlockIndex];
const UniformBlock &uniformBlock = *mProgram->getUniformBlocks()[uniformBlockIndex];
if (bufSize > 0)
{
std::string string = uniformBlock.name;
if (uniformBlock.isArray)
if (uniformBlock.isArrayElement())
{
string += ArrayString(uniformBlock.arrayElement);
string += ArrayString(uniformBlock.elementIndex);
}
strncpy(uniformBlockName, string.c_str(), bufSize);
......@@ -1246,10 +1037,9 @@ void Program::getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSiz
void Program::getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pname, GLint *params) const
{
ASSERT(uniformBlockIndex <
mData.mUniformBlocks.size()); // index must be smaller than getActiveUniformBlockCount()
ASSERT(uniformBlockIndex < mProgram->getUniformBlocks().size()); // index must be smaller than getActiveUniformBlockCount()
const UniformBlock &uniformBlock = mData.mUniformBlocks[uniformBlockIndex];
const UniformBlock &uniformBlock = *mProgram->getUniformBlocks()[uniformBlockIndex];
switch (pname)
{
......@@ -1257,8 +1047,7 @@ void Program::getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pname, GL
*params = static_cast<GLint>(uniformBlock.dataSize);
break;
case GL_UNIFORM_BLOCK_NAME_LENGTH:
*params =
static_cast<GLint>(uniformBlock.name.size() + 1 + (uniformBlock.isArray ? 3 : 0));
*params = static_cast<GLint>(uniformBlock.name.size() + 1 + (uniformBlock.isArrayElement() ? 3 : 0));
break;
case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
*params = static_cast<GLint>(uniformBlock.memberUniformIndexes.size());
......@@ -1272,10 +1061,10 @@ void Program::getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pname, GL
}
break;
case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
*params = static_cast<GLint>(uniformBlock.vertexStaticUse);
*params = static_cast<GLint>(uniformBlock.isReferencedByVertexShader());
break;
case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
*params = static_cast<GLint>(uniformBlock.fragmentStaticUse);
*params = static_cast<GLint>(uniformBlock.isReferencedByFragmentShader());
break;
default: UNREACHABLE();
}
......@@ -1287,16 +1076,17 @@ GLint Program::getActiveUniformBlockMaxLength()
if (mLinked)
{
unsigned int numUniformBlocks = static_cast<unsigned int>(mData.mUniformBlocks.size());
unsigned int numUniformBlocks =
static_cast<unsigned int>(mProgram->getUniformBlocks().size());
for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < numUniformBlocks; uniformBlockIndex++)
{
const UniformBlock &uniformBlock = mData.mUniformBlocks[uniformBlockIndex];
const UniformBlock &uniformBlock = *mProgram->getUniformBlocks()[uniformBlockIndex];
if (!uniformBlock.name.empty())
{
const int length = static_cast<int>(uniformBlock.name.length()) + 1;
// Counting in "[0]".
const int arrayLength = (uniformBlock.isArray ? 3 : 0);
const int arrayLength = (uniformBlock.isArrayElement() ? 3 : 0);
maxLength = std::max(length + arrayLength, maxLength);
}
......@@ -1308,32 +1098,12 @@ GLint Program::getActiveUniformBlockMaxLength()
GLuint Program::getUniformBlockIndex(const std::string &name)
{
size_t subscript = GL_INVALID_INDEX;
std::string baseName = gl::ParseUniformName(name, &subscript);
unsigned int numUniformBlocks = static_cast<unsigned int>(mData.mUniformBlocks.size());
for (unsigned int blockIndex = 0; blockIndex < numUniformBlocks; blockIndex++)
{
const gl::UniformBlock &uniformBlock = mData.mUniformBlocks[blockIndex];
if (uniformBlock.name == baseName)
{
const bool arrayElementZero =
(subscript == GL_INVALID_INDEX &&
(!uniformBlock.isArray || uniformBlock.arrayElement == 0));
if (subscript == uniformBlock.arrayElement || arrayElementZero)
{
return blockIndex;
}
}
}
return GL_INVALID_INDEX;
return mProgram->getUniformBlockIndex(name);
}
const UniformBlock &Program::getUniformBlockByIndex(GLuint index) const
const UniformBlock *Program::getUniformBlockByIndex(GLuint index) const
{
ASSERT(index < static_cast<GLuint>(mData.mUniformBlocks.size()));
return mData.mUniformBlocks[index];
return mProgram->getUniformBlockByIndex(index);
}
void Program::bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
......@@ -1473,17 +1243,17 @@ bool Program::linkVaryings(InfoLog &infoLog,
return true;
}
bool Program::linkUniforms(gl::InfoLog &infoLog, const gl::Caps &caps)
bool Program::linkUniforms(gl::InfoLog &infoLog, const gl::Caps & /*caps*/) const
{
const std::vector<sh::Uniform> &vertexUniforms = mData.mAttachedVertexShader->getUniforms();
const std::vector<sh::Uniform> &fragmentUniforms = mData.mAttachedFragmentShader->getUniforms();
// Check that uniforms defined in the vertex and fragment shaders are identical
std::map<std::string, LinkedUniform> linkedUniforms;
std::map<std::string, const sh::Uniform *> linkedUniforms;
for (const sh::Uniform &vertexUniform : vertexUniforms)
{
linkedUniforms[vertexUniform.name] = LinkedUniform(vertexUniform);
linkedUniforms[vertexUniform.name] = &vertexUniform;
}
for (const sh::Uniform &fragmentUniform : fragmentUniforms)
......@@ -1491,45 +1261,19 @@ bool Program::linkUniforms(gl::InfoLog &infoLog, const gl::Caps &caps)
auto entry = linkedUniforms.find(fragmentUniform.name);
if (entry != linkedUniforms.end())
{
LinkedUniform *vertexUniform = &entry->second;
const std::string &uniformName = "uniform '" + vertexUniform->name + "'";
if (!linkValidateUniforms(infoLog, uniformName, *vertexUniform, fragmentUniform))
const sh::Uniform &vertexUniform = *entry->second;
const std::string &uniformName = "uniform '" + vertexUniform.name + "'";
if (!linkValidateUniforms(infoLog, uniformName, vertexUniform, fragmentUniform))
{
return false;
}
}
}
// Flatten the uniforms list (nested fields) into a simple list (no nesting).
// Also check the maximum uniform vector and sampler counts.
if (!flattenUniformsAndCheckCaps(caps, infoLog))
{
return false;
}
indexUniforms();
// TODO(jmadill): check sampler uniforms with caps
return true;
}
void Program::indexUniforms()
{
for (size_t uniformIndex = 0; uniformIndex < mData.mUniforms.size(); uniformIndex++)
{
const gl::LinkedUniform &uniform = mData.mUniforms[uniformIndex];
for (unsigned int arrayIndex = 0; arrayIndex < uniform.elementCount(); arrayIndex++)
{
if (!uniform.isBuiltIn())
{
// Assign in-order uniform locations
mData.mUniformLocations.push_back(gl::VariableLocation(
uniform.name, arrayIndex, static_cast<unsigned int>(uniformIndex)));
}
}
}
}
bool Program::linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform)
{
if (!linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform, true))
......@@ -1709,8 +1453,6 @@ bool Program::linkUniformBlocks(InfoLog &infoLog, const Caps &caps)
}
}
gatherInterfaceBlockInfo();
return true;
}
......@@ -1988,204 +1730,4 @@ void Program::linkOutputVariables()
}
}
}
bool Program::flattenUniformsAndCheckCaps(const Caps &caps, InfoLog &infoLog)
{
const gl::Shader *vertexShader = mData.getAttachedVertexShader();
VectorAndSamplerCount vsCounts;
for (const sh::Uniform &uniform : vertexShader->getUniforms())
{
if (uniform.staticUse)
{
vsCounts += flattenUniform(uniform, uniform.name);
}
}
if (vsCounts.vectorCount > caps.maxVertexUniformVectors)
{
infoLog << "Vertex shader active uniforms exceed MAX_VERTEX_UNIFORM_VECTORS ("
<< caps.maxVertexUniformVectors << ").";
return false;
}
if (vsCounts.samplerCount > caps.maxVertexTextureImageUnits)
{
infoLog << "Vertex shader sampler count exceeds MAX_VERTEX_TEXTURE_IMAGE_UNITS ("
<< caps.maxVertexTextureImageUnits << ").";
return false;
}
const gl::Shader *fragmentShader = mData.getAttachedFragmentShader();
VectorAndSamplerCount fsCounts;
for (const sh::Uniform &uniform : fragmentShader->getUniforms())
{
if (uniform.staticUse)
{
fsCounts += flattenUniform(uniform, uniform.name);
}
}
if (fsCounts.vectorCount > caps.maxFragmentUniformVectors)
{
infoLog << "Fragment shader active uniforms exceed MAX_FRAGMENT_UNIFORM_VECTORS ("
<< caps.maxFragmentUniformVectors << ").";
return false;
}
if (fsCounts.samplerCount > caps.maxTextureImageUnits)
{
infoLog << "Fragment shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS ("
<< caps.maxTextureImageUnits << ").";
return false;
}
return true;
}
Program::VectorAndSamplerCount Program::flattenUniform(const sh::ShaderVariable &uniform,
const std::string &fullName)
{
VectorAndSamplerCount vectorAndSamplerCount;
if (uniform.isStruct())
{
for (unsigned int elementIndex = 0; elementIndex < uniform.elementCount(); elementIndex++)
{
const std::string &elementString = (uniform.isArray() ? ArrayString(elementIndex) : "");
for (size_t fieldIndex = 0; fieldIndex < uniform.fields.size(); fieldIndex++)
{
const sh::ShaderVariable &field = uniform.fields[fieldIndex];
const std::string &fieldFullName = (fullName + elementString + "." + field.name);
vectorAndSamplerCount += flattenUniform(field, fieldFullName);
}
}
return vectorAndSamplerCount;
}
// Not a struct
if (mData.getUniformByName(fullName) == nullptr)
{
gl::LinkedUniform linkedUniform(uniform.type, uniform.precision, fullName,
uniform.arraySize, -1,
sh::BlockMemberInfo::getDefaultBlockInfo());
linkedUniform.staticUse = true;
mData.mUniforms.push_back(linkedUniform);
}
vectorAndSamplerCount.vectorCount =
(VariableRegisterCount(uniform.type) * uniform.elementCount());
vectorAndSamplerCount.samplerCount = (IsSamplerType(uniform.type) ? uniform.elementCount() : 0);
return vectorAndSamplerCount;
}
void Program::gatherInterfaceBlockInfo()
{
std::set<std::string> visitedList;
const gl::Shader *vertexShader = mData.getAttachedVertexShader();
ASSERT(mData.mUniformBlocks.empty());
for (const sh::InterfaceBlock &vertexBlock : vertexShader->getInterfaceBlocks())
{
// Only 'packed' blocks are allowed to be considered inacive.
if (!vertexBlock.staticUse && vertexBlock.layout == sh::BLOCKLAYOUT_PACKED)
continue;
if (visitedList.count(vertexBlock.name) > 0)
continue;
defineUniformBlock(vertexBlock, GL_VERTEX_SHADER);
visitedList.insert(vertexBlock.name);
}
const gl::Shader *fragmentShader = mData.getAttachedFragmentShader();
for (const sh::InterfaceBlock &fragmentBlock : fragmentShader->getInterfaceBlocks())
{
// Only 'packed' blocks are allowed to be considered inacive.
if (!fragmentBlock.staticUse && fragmentBlock.layout == sh::BLOCKLAYOUT_PACKED)
continue;
if (visitedList.count(fragmentBlock.name) > 0)
{
for (gl::UniformBlock &block : mData.mUniformBlocks)
{
if (block.name == fragmentBlock.name)
{
block.fragmentStaticUse = fragmentBlock.staticUse;
}
}
continue;
}
defineUniformBlock(fragmentBlock, GL_FRAGMENT_SHADER);
visitedList.insert(fragmentBlock.name);
}
}
void Program::defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, GLenum shaderType)
{
std::string baseName;
if (!interfaceBlock.instanceName.empty() && interfaceBlock.arraySize == 0)
{
baseName = interfaceBlock.instanceName;
}
int blockIndex = static_cast<int>(mData.mUniformBlocks.size());
size_t firstBlockUniformIndex = mData.mUniforms.size();
DefineUniformBlockMembers(interfaceBlock.fields, baseName, blockIndex, &mData.mUniforms);
size_t lastBlockUniformIndex = mData.mUniforms.size();
std::vector<unsigned int> blockUniformIndexes;
for (size_t blockUniformIndex = firstBlockUniformIndex;
blockUniformIndex < lastBlockUniformIndex; ++blockUniformIndex)
{
blockUniformIndexes.push_back(static_cast<unsigned int>(blockUniformIndex));
}
if (interfaceBlock.arraySize > 0)
{
for (unsigned int arrayElement = 0; arrayElement < interfaceBlock.arraySize; ++arrayElement)
{
UniformBlock block(interfaceBlock.name, true, arrayElement);
block.memberUniformIndexes = blockUniformIndexes;
if (shaderType == GL_VERTEX_SHADER)
{
block.vertexStaticUse = interfaceBlock.staticUse;
}
else
{
ASSERT(shaderType == GL_FRAGMENT_SHADER);
block.fragmentStaticUse = interfaceBlock.staticUse;
}
mData.mUniformBlocks.push_back(block);
}
}
else
{
UniformBlock block(interfaceBlock.name, false, 0);
block.memberUniformIndexes = blockUniformIndexes;
if (shaderType == GL_VERTEX_SHADER)
{
block.vertexStaticUse = interfaceBlock.staticUse;
}
else
{
ASSERT(shaderType == GL_FRAGMENT_SHADER);
block.fragmentStaticUse = interfaceBlock.staticUse;
}
mData.mUniformBlocks.push_back(block);
}
}
}
......@@ -189,16 +189,6 @@ class Program : angle::NonCopyable
{
return mOutputVariables;
}
const std::vector<LinkedUniform> &getUniforms() const { return mUniforms; }
const std::vector<VariableLocation> &getUniformLocations() const
{
return mUniformLocations;
}
const std::vector<UniformBlock> &getUniformBlocks() const { return mUniformBlocks; }
const LinkedUniform *getUniformByName(const std::string &name) const;
GLint getUniformLocation(const std::string &name) const;
GLuint getUniformIndex(const std::string &name) const;
private:
friend class Program;
......@@ -215,12 +205,10 @@ class Program : angle::NonCopyable
std::vector<sh::Attribute> mAttributes;
std::bitset<MAX_VERTEX_ATTRIBS> mActiveAttribLocationsMask;
std::vector<LinkedUniform> mUniforms;
std::vector<VariableLocation> mUniformLocations;
std::vector<UniformBlock> mUniformBlocks;
// TODO(jmadill): use unordered/hash map when available
std::map<int, VariableLocation> mOutputVariables;
// TODO(jmadill): move more state into Data.
};
Program(rx::ImplFactory *factory, ResourceManager *manager, GLuint handle);
......@@ -263,10 +251,11 @@ class Program : angle::NonCopyable
GLint getActiveUniformMaxLength();
GLint getActiveUniformi(GLuint index, GLenum pname) const;
bool isValidUniformLocation(GLint location) const;
const LinkedUniform &getUniformByLocation(GLint location) const;
LinkedUniform *getUniformByLocation(GLint location) const;
LinkedUniform *getUniformByName(const std::string &name) const;
GLint getUniformLocation(const std::string &name) const;
GLuint getUniformIndex(const std::string &name) const;
GLint getUniformLocation(const std::string &name);
GLuint getUniformIndex(const std::string &name);
void setUniform1fv(GLint location, GLsizei count, const GLfloat *v);
void setUniform2fv(GLint location, GLsizei count, const GLfloat *v);
void setUniform3fv(GLint location, GLsizei count, const GLfloat *v);
......@@ -303,7 +292,7 @@ class Program : angle::NonCopyable
void bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding);
GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const;
const UniformBlock &getUniformBlockByIndex(GLuint index) const;
const UniformBlock *getUniformBlockByIndex(GLuint index) const;
void setTransformFeedbackVaryings(GLsizei count, const GLchar *const *varyings, GLenum bufferMode);
void getTransformFeedbackVarying(GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name) const;
......@@ -341,8 +330,7 @@ class Program : angle::NonCopyable
static bool linkVaryings(InfoLog &infoLog,
const Shader *vertexShader,
const Shader *fragmentShader);
bool linkUniforms(gl::InfoLog &infoLog, const gl::Caps &caps);
void indexUniforms();
bool linkUniforms(gl::InfoLog &infoLog, const gl::Caps &caps) const;
bool areMatchingInterfaceBlocks(gl::InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock,
const sh::InterfaceBlock &fragmentInterfaceBlock);
......@@ -364,31 +352,6 @@ class Program : angle::NonCopyable
std::vector<const sh::Varying *> getMergedVaryings() const;
void linkOutputVariables();
bool flattenUniformsAndCheckCaps(const Caps &caps, InfoLog &infoLog);
struct VectorAndSamplerCount
{
VectorAndSamplerCount() : vectorCount(0), samplerCount(0) {}
VectorAndSamplerCount(const VectorAndSamplerCount &other) = default;
VectorAndSamplerCount &operator=(const VectorAndSamplerCount &other) = default;
VectorAndSamplerCount &operator+=(const VectorAndSamplerCount &other)
{
vectorCount += other.vectorCount;
samplerCount += other.samplerCount;
return *this;
}
unsigned int vectorCount;
unsigned int samplerCount;
};
VectorAndSamplerCount flattenUniform(const sh::ShaderVariable &uniform,
const std::string &fullName);
void gatherInterfaceBlockInfo();
void defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, GLenum shaderType);
Data mData;
rx::ProgramImpl *mProgram;
......
......@@ -13,32 +13,55 @@
namespace gl
{
LinkedUniform::LinkedUniform()
: blockIndex(-1), blockInfo(sh::BlockMemberInfo::getDefaultBlockInfo())
LinkedUniform::LinkedUniform(GLenum type, GLenum precision, const std::string &name, unsigned int arraySize,
const int blockIndex, const sh::BlockMemberInfo &blockInfo)
: type(type),
precision(precision),
name(name),
arraySize(arraySize),
blockIndex(blockIndex),
blockInfo(blockInfo),
data(NULL),
dirty(true),
psRegisterIndex(GL_INVALID_INDEX),
vsRegisterIndex(GL_INVALID_INDEX),
registerCount(0),
registerElement(0)
{
// We use data storage for default block uniforms to cache values that are sent to D3D during rendering
// Uniform blocks/buffers are treated separately by the Renderer (ES3 path only)
if (isInDefaultBlock())
{
size_t bytes = dataSize();
data = new unsigned char[bytes];
memset(data, 0, bytes);
registerCount = VariableRowCount(type) * elementCount();
}
}
LinkedUniform::LinkedUniform(GLenum typeIn,
GLenum precisionIn,
const std::string &nameIn,
unsigned int arraySizeIn,
const int blockIndexIn,
const sh::BlockMemberInfo &blockInfoIn)
: blockIndex(blockIndexIn), blockInfo(blockInfoIn)
LinkedUniform::~LinkedUniform()
{
type = typeIn;
precision = precisionIn;
name = nameIn;
arraySize = arraySizeIn;
delete[] data;
}
LinkedUniform::LinkedUniform(const sh::Uniform &uniform)
: sh::Uniform(uniform), blockIndex(-1), blockInfo(sh::BlockMemberInfo::getDefaultBlockInfo())
bool LinkedUniform::isArray() const
{
return arraySize > 0;
}
LinkedUniform::~LinkedUniform()
unsigned int LinkedUniform::elementCount() const
{
return arraySize > 0 ? arraySize : 1;
}
bool LinkedUniform::isReferencedByVertexShader() const
{
return vsRegisterIndex != GL_INVALID_INDEX;
}
bool LinkedUniform::isReferencedByFragmentShader() const
{
return psRegisterIndex != GL_INVALID_INDEX;
}
bool LinkedUniform::isInDefaultBlock() const
......@@ -57,32 +80,33 @@ bool LinkedUniform::isSampler() const
return IsSamplerType(type);
}
bool LinkedUniform::isField() const
bool LinkedUniform::isBuiltIn() const
{
return name.find('.') != std::string::npos;
return name.compare(0, 3, "gl_") == 0;
}
UniformBlock::UniformBlock()
: isArray(false),
arrayElement(0),
dataSize(0),
vertexStaticUse(false),
fragmentStaticUse(false),
UniformBlock::UniformBlock(const std::string &name, unsigned int elementIndex, unsigned int dataSize)
: name(name),
elementIndex(elementIndex),
dataSize(dataSize),
psRegisterIndex(GL_INVALID_INDEX),
vsRegisterIndex(GL_INVALID_INDEX)
{
}
UniformBlock::UniformBlock(const std::string &nameIn, bool isArrayIn, unsigned int arrayElementIn)
: name(nameIn),
isArray(isArrayIn),
arrayElement(arrayElementIn),
dataSize(0),
vertexStaticUse(false),
fragmentStaticUse(false),
psRegisterIndex(GL_INVALID_INDEX),
vsRegisterIndex(GL_INVALID_INDEX)
bool UniformBlock::isArrayElement() const
{
return elementIndex != GL_INVALID_INDEX;
}
bool UniformBlock::isReferencedByVertexShader() const
{
return vsRegisterIndex != GL_INVALID_INDEX;
}
bool UniformBlock::isReferencedByFragmentShader() const
{
return psRegisterIndex != GL_INVALID_INDEX;
}
}
......@@ -19,39 +19,53 @@ namespace gl
{
// Helper struct representing a single shader uniform
struct LinkedUniform : public sh::Uniform
struct LinkedUniform : angle::NonCopyable
{
LinkedUniform();
LinkedUniform(GLenum type, GLenum precision, const std::string &name, unsigned int arraySize, const int blockIndex, const sh::BlockMemberInfo &blockInfo);
LinkedUniform(const sh::Uniform &uniform);
LinkedUniform(const LinkedUniform &uniform) = default;
LinkedUniform &operator=(const LinkedUniform &uniform) = default;
~LinkedUniform();
bool isArray() const;
unsigned int elementCount() const;
bool isReferencedByVertexShader() const;
bool isReferencedByFragmentShader() const;
bool isInDefaultBlock() const;
size_t dataSize() const;
bool isSampler() const;
bool isInDefaultBlock() const;
bool isField() const;
bool isBuiltIn() const;
const GLenum type;
const GLenum precision;
const std::string name;
const unsigned int arraySize;
const int blockIndex;
const sh::BlockMemberInfo blockInfo;
unsigned char *data;
bool dirty;
int blockIndex;
sh::BlockMemberInfo blockInfo;
unsigned int psRegisterIndex;
unsigned int vsRegisterIndex;
unsigned int registerCount;
// Register "elements" are used for uniform structs in ES3, to appropriately identify single uniforms
// inside aggregate types, which are packed according C-like structure rules.
unsigned int registerElement;
};
// Helper struct representing a single shader uniform block
struct UniformBlock
struct UniformBlock : angle::NonCopyable
{
UniformBlock();
UniformBlock(const std::string &nameIn, bool isArrayIn, unsigned int arrayElementIn);
UniformBlock(const UniformBlock &other) = default;
UniformBlock &operator=(const UniformBlock &other) = default;
std::string name;
bool isArray;
unsigned int arrayElement;
unsigned int dataSize;
bool vertexStaticUse;
bool fragmentStaticUse;
// use GL_INVALID_INDEX for non-array elements
UniformBlock(const std::string &name, unsigned int elementIndex, unsigned int dataSize);
bool isArrayElement() const;
bool isReferencedByVertexShader() const;
bool isReferencedByFragmentShader() const;
const std::string name;
const unsigned int elementIndex;
const unsigned int dataSize;
std::vector<unsigned int> memberUniformIndexes;
......
//
// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// ProgramD3D.cpp: Defines the rx::ProgramD3D class which implements rx::ProgramImpl.
#include "libANGLE/renderer/ProgramImpl.h"
#include "common/utilities.h"
namespace rx
{
LinkResult::LinkResult(bool linkSuccess, const gl::Error &error)
: linkSuccess(linkSuccess),
error(error)
{
}
ProgramImpl::ProgramImpl(const gl::Program::Data &data) : mData(data)
{
}
ProgramImpl::~ProgramImpl()
{
// Ensure that reset was called by the inherited class during destruction
ASSERT(mUniformIndex.size() == 0);
}
gl::LinkedUniform *ProgramImpl::getUniformByLocation(GLint location) const
{
ASSERT(location >= 0 && mUniformIndex.find(location) != mUniformIndex.end());
return mUniforms[mUniformIndex.at(location).index];
}
gl::LinkedUniform *ProgramImpl::getUniformByName(const std::string &name) const
{
for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
{
if (mUniforms[uniformIndex]->name == name)
{
return mUniforms[uniformIndex];
}
}
return NULL;
}
gl::UniformBlock *ProgramImpl::getUniformBlockByIndex(GLuint blockIndex) const
{
ASSERT(blockIndex < mUniformBlocks.size());
return mUniformBlocks[blockIndex];
}
GLint ProgramImpl::getUniformLocation(const std::string &name) const
{
size_t subscript = GL_INVALID_INDEX;
std::string baseName = gl::ParseUniformName(name, &subscript);
for (const auto &info : mUniformIndex)
{
GLuint location = info.first;
const gl::VariableLocation &uniform = info.second;
if (uniform.name == baseName)
{
const bool isArray = mUniforms[uniform.index]->isArray();
if ((isArray && uniform.element == subscript) ||
(subscript == GL_INVALID_INDEX))
{
return location;
}
}
}
return -1;
}
GLuint ProgramImpl::getUniformIndex(const std::string &name) const
{
size_t subscript = GL_INVALID_INDEX;
std::string baseName = gl::ParseUniformName(name, &subscript);
// The app is not allowed to specify array indices other than 0 for arrays of basic types
if (subscript != 0 && subscript != GL_INVALID_INDEX)
{
return GL_INVALID_INDEX;
}
unsigned int numUniforms = static_cast<unsigned int>(mUniforms.size());
for (unsigned int index = 0; index < numUniforms; index++)
{
if (mUniforms[index]->name == baseName)
{
if (mUniforms[index]->isArray() || subscript == GL_INVALID_INDEX)
{
return index;
}
}
}
return GL_INVALID_INDEX;
}
GLuint ProgramImpl::getUniformBlockIndex(const std::string &name) const
{
size_t subscript = GL_INVALID_INDEX;
std::string baseName = gl::ParseUniformName(name, &subscript);
unsigned int numUniformBlocks = static_cast<unsigned int>(mUniformBlocks.size());
for (unsigned int blockIndex = 0; blockIndex < numUniformBlocks; blockIndex++)
{
const gl::UniformBlock &uniformBlock = *mUniformBlocks[blockIndex];
if (uniformBlock.name == baseName)
{
const bool arrayElementZero = (subscript == GL_INVALID_INDEX && uniformBlock.elementIndex == 0);
if (subscript == uniformBlock.elementIndex || arrayElementZero)
{
return blockIndex;
}
}
}
return GL_INVALID_INDEX;
}
void ProgramImpl::reset()
{
SafeDeleteContainer(mUniforms);
mUniformIndex.clear();
SafeDeleteContainer(mUniformBlocks);
}
}
......@@ -23,17 +23,16 @@ namespace rx
struct LinkResult
{
LinkResult(bool linkSuccess, const gl::Error &error) : linkSuccess(linkSuccess), error(error) {}
bool linkSuccess;
gl::Error error;
LinkResult(bool linkSuccess, const gl::Error &error);
};
class ProgramImpl : angle::NonCopyable
{
public:
ProgramImpl(const gl::Program::Data &data) : mData(data) {}
virtual ~ProgramImpl() {}
ProgramImpl(const gl::Program::Data &data);
virtual ~ProgramImpl();
virtual int getShaderVersion() const = 0;
......@@ -74,12 +73,33 @@ class ProgramImpl : angle::NonCopyable
// determine if they can be removed from this interface.
virtual bool validateSamplers(gl::InfoLog *infoLog, const gl::Caps &caps) = 0;
// Gather uniform block active uniform indices, and uniform block offset info.
virtual void gatherUniformBlockInfo(std::vector<gl::UniformBlock> *uniformBlocks,
std::vector<gl::LinkedUniform> *uniforms) = 0;
const std::vector<gl::LinkedUniform*> &getUniforms() const { return mUniforms; }
const std::map<GLuint, gl::VariableLocation> &getUniformIndices() const { return mUniformIndex; }
const std::vector<gl::UniformBlock*> &getUniformBlocks() const { return mUniformBlocks; }
std::vector<gl::LinkedUniform*> &getUniforms() { return mUniforms; }
std::map<GLuint, gl::VariableLocation> &getUniformIndices() { return mUniformIndex; }
std::vector<gl::UniformBlock*> &getUniformBlocks() { return mUniformBlocks; }
gl::LinkedUniform *getUniformByLocation(GLint location) const;
gl::LinkedUniform *getUniformByName(const std::string &name) const;
gl::UniformBlock *getUniformBlockByIndex(GLuint blockIndex) const;
GLint getUniformLocation(const std::string &name) const;
GLuint getUniformIndex(const std::string &name) const;
GLuint getUniformBlockIndex(const std::string &name) const;
virtual void reset();
protected:
const gl::Program::Data &mData;
std::vector<gl::LinkedUniform*> mUniforms;
// TODO: use a hash map
std::map<GLuint, gl::VariableLocation> mUniformIndex;
std::vector<gl::UniformBlock*> mUniformBlocks;
};
}
......
......@@ -171,92 +171,8 @@ std::vector<PackedVarying> MergeVaryings(const gl::Shader &vertexShader,
return packedVaryings;
}
template <typename VarT>
void GetUniformBlockInfo(const std::vector<VarT> &fields,
const std::string &prefix,
sh::BlockLayoutEncoder *encoder,
bool inRowMajorLayout,
std::map<std::string, sh::BlockMemberInfo> *blockInfoOut)
{
for (const VarT &field : fields)
{
const std::string &fieldName = (prefix.empty() ? field.name : prefix + "." + field.name);
if (field.isStruct())
{
bool rowMajorLayout = (inRowMajorLayout || IsRowMajorLayout(field));
for (unsigned int arrayElement = 0; arrayElement < field.elementCount(); arrayElement++)
{
encoder->enterAggregateType();
const std::string uniformElementName =
fieldName + (field.isArray() ? ArrayString(arrayElement) : "");
GetUniformBlockInfo(field.fields, uniformElementName, encoder, rowMajorLayout,
blockInfoOut);
encoder->exitAggregateType();
}
}
else
{
bool isRowMajorMatrix = (gl::IsMatrixType(field.type) && inRowMajorLayout);
(*blockInfoOut)[fieldName] =
encoder->encodeType(field.type, field.arraySize, isRowMajorMatrix);
}
}
}
} // anonymous namespace
D3DUniform::D3DUniform(GLenum typeIn,
const std::string &nameIn,
unsigned int arraySizeIn,
bool defaultBlock)
: type(typeIn),
name(nameIn),
arraySize(arraySizeIn),
data(nullptr),
dirty(true),
psRegisterIndex(GL_INVALID_INDEX),
vsRegisterIndex(GL_INVALID_INDEX),
registerCount(0),
registerElement(0)
{
// We use data storage for default block uniforms to cache values that are sent to D3D during
// rendering
// Uniform blocks/buffers are treated separately by the Renderer (ES3 path only)
if (defaultBlock)
{
size_t bytes = gl::VariableInternalSize(type) * elementCount();
data = new unsigned char[bytes];
memset(data, 0, bytes);
// TODO(jmadill): is this correct with non-square matrices?
registerCount = gl::VariableRowCount(type) * elementCount();
}
}
D3DUniform::~D3DUniform()
{
SafeDeleteArray(data);
}
bool D3DUniform::isSampler() const
{
return gl::IsSamplerType(type);
}
bool D3DUniform::isReferencedByVertexShader() const
{
return vsRegisterIndex != GL_INVALID_INDEX;
}
bool D3DUniform::isReferencedByFragmentShader() const
{
return psRegisterIndex != GL_INVALID_INDEX;
}
ProgramD3D::VertexExecutable::VertexExecutable(const gl::InputLayout &inputLayout,
const Signature &signature,
ShaderExecutableD3D *shaderExecutable)
......@@ -440,45 +356,47 @@ void ProgramD3D::updateSamplerMapping()
mDirtySamplerMapping = false;
// Retrieve sampler uniform values
for (const D3DUniform *d3dUniform : mD3DUniforms)
for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
{
if (!d3dUniform->dirty)
continue;
if (!d3dUniform->isSampler())
continue;
int count = d3dUniform->elementCount();
GLint(*v)[4] = reinterpret_cast<GLint(*)[4]>(d3dUniform->data);
gl::LinkedUniform *targetUniform = mUniforms[uniformIndex];
if (d3dUniform->isReferencedByFragmentShader())
if (targetUniform->dirty)
{
unsigned int firstIndex = d3dUniform->psRegisterIndex;
for (int i = 0; i < count; i++)
if (gl::IsSamplerType(targetUniform->type))
{
unsigned int samplerIndex = firstIndex + i;
int count = targetUniform->elementCount();
GLint (*v)[4] = reinterpret_cast<GLint(*)[4]>(targetUniform->data);
if (samplerIndex < mSamplersPS.size())
if (targetUniform->isReferencedByFragmentShader())
{
ASSERT(mSamplersPS[samplerIndex].active);
mSamplersPS[samplerIndex].logicalTextureUnit = v[i][0];
}
}
}
unsigned int firstIndex = targetUniform->psRegisterIndex;
if (d3dUniform->isReferencedByVertexShader())
{
unsigned int firstIndex = d3dUniform->vsRegisterIndex;
for (int i = 0; i < count; i++)
{
unsigned int samplerIndex = firstIndex + i;
for (int i = 0; i < count; i++)
{
unsigned int samplerIndex = firstIndex + i;
if (samplerIndex < mSamplersPS.size())
{
ASSERT(mSamplersPS[samplerIndex].active);
mSamplersPS[samplerIndex].logicalTextureUnit = v[i][0];
}
}
}
if (samplerIndex < mSamplersVS.size())
if (targetUniform->isReferencedByVertexShader())
{
ASSERT(mSamplersVS[samplerIndex].active);
mSamplersVS[samplerIndex].logicalTextureUnit = v[i][0];
unsigned int firstIndex = targetUniform->vsRegisterIndex;
for (int i = 0; i < count; i++)
{
unsigned int samplerIndex = firstIndex + i;
if (samplerIndex < mSamplersVS.size())
{
ASSERT(mSamplersVS[samplerIndex].active);
mSamplersVS[samplerIndex].logicalTextureUnit = v[i][0];
}
}
}
}
}
......@@ -587,8 +505,6 @@ bool ProgramD3D::validateSamplers(gl::InfoLog *infoLog, const gl::Caps &caps)
LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
{
reset();
DeviceIdentifier binaryDeviceIdentifier = { 0 };
stream->readBytes(reinterpret_cast<unsigned char*>(&binaryDeviceIdentifier), sizeof(DeviceIdentifier));
......@@ -643,21 +559,79 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
return LinkResult(false, gl::Error(GL_NO_ERROR));
}
const auto &linkedUniforms = mData.getUniforms();
ASSERT(mD3DUniforms.empty());
mUniforms.resize(uniformCount);
for (unsigned int uniformIndex = 0; uniformIndex < uniformCount; uniformIndex++)
{
const gl::LinkedUniform &linkedUniform = linkedUniforms[uniformIndex];
GLenum type = stream->readInt<GLenum>();
GLenum precision = stream->readInt<GLenum>();
std::string name = stream->readString();
unsigned int arraySize = stream->readInt<unsigned int>();
int blockIndex = stream->readInt<int>();
int offset = stream->readInt<int>();
int arrayStride = stream->readInt<int>();
int matrixStride = stream->readInt<int>();
bool isRowMajorMatrix = stream->readBool();
D3DUniform *d3dUniform =
new D3DUniform(linkedUniform.type, linkedUniform.name, linkedUniform.arraySize,
linkedUniform.isInDefaultBlock());
stream->readInt(&d3dUniform->psRegisterIndex);
stream->readInt(&d3dUniform->vsRegisterIndex);
stream->readInt(&d3dUniform->registerCount);
stream->readInt(&d3dUniform->registerElement);
const sh::BlockMemberInfo blockInfo(offset, arrayStride, matrixStride, isRowMajorMatrix);
mD3DUniforms.push_back(d3dUniform);
gl::LinkedUniform *uniform = new gl::LinkedUniform(type, precision, name, arraySize, blockIndex, blockInfo);
stream->readInt(&uniform->psRegisterIndex);
stream->readInt(&uniform->vsRegisterIndex);
stream->readInt(&uniform->registerCount);
stream->readInt(&uniform->registerElement);
mUniforms[uniformIndex] = uniform;
}
const unsigned int uniformIndexCount = stream->readInt<unsigned int>();
if (stream->error())
{
infoLog << "Invalid program binary.";
return LinkResult(false, gl::Error(GL_NO_ERROR));
}
for (unsigned int uniformIndexIndex = 0; uniformIndexIndex < uniformIndexCount; uniformIndexIndex++)
{
GLuint location;
stream->readInt(&location);
gl::VariableLocation variable;
stream->readString(&variable.name);
stream->readInt(&variable.element);
stream->readInt(&variable.index);
mUniformIndex[location] = variable;
}
unsigned int uniformBlockCount = stream->readInt<unsigned int>();
if (stream->error())
{
infoLog << "Invalid program binary.";
return LinkResult(false, gl::Error(GL_NO_ERROR));
}
mUniformBlocks.resize(uniformBlockCount);
for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < uniformBlockCount; ++uniformBlockIndex)
{
std::string name = stream->readString();
unsigned int elementIndex = stream->readInt<unsigned int>();
unsigned int dataSize = stream->readInt<unsigned int>();
gl::UniformBlock *uniformBlock = new gl::UniformBlock(name, elementIndex, dataSize);
stream->readInt(&uniformBlock->psRegisterIndex);
stream->readInt(&uniformBlock->vsRegisterIndex);
unsigned int numMembers = stream->readInt<unsigned int>();
uniformBlock->memberUniformIndexes.resize(numMembers);
for (unsigned int blockMemberIndex = 0; blockMemberIndex < numMembers; blockMemberIndex++)
{
stream->readInt(&uniformBlock->memberUniformIndexes[blockMemberIndex]);
}
mUniformBlocks[uniformBlockIndex] = uniformBlock;
}
const unsigned int transformFeedbackVaryingCount = stream->readInt<unsigned int>();
......@@ -831,18 +805,59 @@ gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream)
stream->writeInt(mUsedVertexSamplerRange);
stream->writeInt(mUsedPixelSamplerRange);
stream->writeInt(mD3DUniforms.size());
for (size_t uniformIndex = 0; uniformIndex < mD3DUniforms.size(); ++uniformIndex)
stream->writeInt(mUniforms.size());
for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); ++uniformIndex)
{
const D3DUniform &uniform = *mD3DUniforms[uniformIndex];
const gl::LinkedUniform &uniform = *mUniforms[uniformIndex];
stream->writeInt(uniform.type);
stream->writeInt(uniform.precision);
stream->writeString(uniform.name);
stream->writeInt(uniform.arraySize);
stream->writeInt(uniform.blockIndex);
stream->writeInt(uniform.blockInfo.offset);
stream->writeInt(uniform.blockInfo.arrayStride);
stream->writeInt(uniform.blockInfo.matrixStride);
stream->writeInt(uniform.blockInfo.isRowMajorMatrix);
// Type, name and arraySize are redundant, so aren't stored in the binary.
stream->writeInt(uniform.psRegisterIndex);
stream->writeInt(uniform.vsRegisterIndex);
stream->writeInt(uniform.registerCount);
stream->writeInt(uniform.registerElement);
}
stream->writeInt(mUniformIndex.size());
for (const auto &uniform : mUniformIndex)
{
GLuint location = uniform.first;
stream->writeInt(location);
const gl::VariableLocation &variable = uniform.second;
stream->writeString(variable.name);
stream->writeInt(variable.element);
stream->writeInt(variable.index);
}
stream->writeInt(mUniformBlocks.size());
for (size_t uniformBlockIndex = 0; uniformBlockIndex < mUniformBlocks.size(); ++uniformBlockIndex)
{
const gl::UniformBlock& uniformBlock = *mUniformBlocks[uniformBlockIndex];
stream->writeString(uniformBlock.name);
stream->writeInt(uniformBlock.elementIndex);
stream->writeInt(uniformBlock.dataSize);
stream->writeInt(uniformBlock.memberUniformIndexes.size());
for (unsigned int blockMemberIndex = 0; blockMemberIndex < uniformBlock.memberUniformIndexes.size(); blockMemberIndex++)
{
stream->writeInt(uniformBlock.memberUniformIndexes[blockMemberIndex]);
}
stream->writeInt(uniformBlock.psRegisterIndex);
stream->writeInt(uniformBlock.vsRegisterIndex);
}
stream->writeInt(mTransformFeedbackLinkedVaryings.size());
for (size_t i = 0; i < mTransformFeedbackLinkedVaryings.size(); i++)
{
......@@ -1111,18 +1126,6 @@ LinkResult ProgramD3D::compileProgramExecutables(gl::InfoLog &infoLog,
LinkResult ProgramD3D::link(const gl::Data &data, gl::InfoLog &infoLog)
{
reset();
// TODO(jmadill): structures containing samplers
for (const gl::LinkedUniform &linkedUniform : mData.getUniforms())
{
if (linkedUniform.isSampler() && linkedUniform.isField())
{
infoLog << "Structures containing samplers not currently supported in D3D.";
return LinkResult(false, gl::Error(GL_NO_ERROR));
}
}
const gl::Shader *vertexShader = mData.getAttachedVertexShader();
const gl::Shader *fragmentShader = mData.getAttachedFragmentShader();
......@@ -1172,7 +1175,12 @@ LinkResult ProgramD3D::link(const gl::Data &data, gl::InfoLog &infoLog)
initSemanticIndex();
assignUniformRegisters();
if (!defineUniforms(infoLog, *data.caps))
{
return LinkResult(false, gl::Error(GL_NO_ERROR));
}
defineUniformBlocks(*data.caps);
gatherTransformFeedbackVaryings(linkedVaryings);
......@@ -1192,96 +1200,24 @@ GLboolean ProgramD3D::validate(const gl::Caps &caps, gl::InfoLog *infoLog)
return validateSamplers(infoLog, caps);
}
void ProgramD3D::gatherUniformBlockInfo(std::vector<gl::UniformBlock> *uniformBlocks,
std::vector<gl::LinkedUniform> *uniforms)
{
const gl::Shader *vertexShader = mData.getAttachedVertexShader();
BlockInfoMap blockInfo;
std::map<std::string, size_t> blockDataSizes;
for (const sh::InterfaceBlock &vertexBlock : vertexShader->getInterfaceBlocks())
{
if (!vertexBlock.staticUse && vertexBlock.layout == sh::BLOCKLAYOUT_PACKED)
continue;
if (blockDataSizes.count(vertexBlock.name) > 0)
continue;
size_t dataSize = defineUniformBlock(vertexBlock, &blockInfo);
blockDataSizes[vertexBlock.name] = dataSize;
}
const gl::Shader *fragmentShader = mData.getAttachedFragmentShader();
for (const sh::InterfaceBlock &fragmentBlock : fragmentShader->getInterfaceBlocks())
{
if (!fragmentBlock.staticUse && fragmentBlock.layout == sh::BLOCKLAYOUT_PACKED)
continue;
if (blockDataSizes.count(fragmentBlock.name) > 0)
continue;
size_t dataSize = defineUniformBlock(fragmentBlock, &blockInfo);
blockDataSizes[fragmentBlock.name] = dataSize;
}
// Copy block info out to uniforms.
for (gl::LinkedUniform &linkedUniform : *uniforms)
{
const auto &infoEntry = blockInfo.find(linkedUniform.name);
if (infoEntry != blockInfo.end())
{
linkedUniform.blockInfo = infoEntry->second;
}
}
// Assign registers and update sizes.
const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(vertexShader);
const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(fragmentShader);
for (gl::UniformBlock &uniformBlock : *uniformBlocks)
{
unsigned int uniformBlockElement = uniformBlock.isArray ? uniformBlock.arrayElement : 0;
if (uniformBlock.vertexStaticUse)
{
unsigned int baseRegister =
vertexShaderD3D->getInterfaceBlockRegister(uniformBlock.name);
uniformBlock.vsRegisterIndex = baseRegister + uniformBlockElement;
}
if (uniformBlock.fragmentStaticUse)
{
unsigned int baseRegister =
fragmentShaderD3D->getInterfaceBlockRegister(uniformBlock.name);
uniformBlock.psRegisterIndex = baseRegister + uniformBlockElement;
}
ASSERT(blockDataSizes.count(uniformBlock.name) == 1);
uniformBlock.dataSize = static_cast<unsigned int>(blockDataSizes[uniformBlock.name]);
}
}
void ProgramD3D::initializeUniformStorage()
{
// Compute total default block size
unsigned int vertexRegisters = 0;
unsigned int fragmentRegisters = 0;
for (const D3DUniform *d3dUniform : mD3DUniforms)
for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
{
if (!d3dUniform->isSampler())
const gl::LinkedUniform &uniform = *mUniforms[uniformIndex];
if (!gl::IsSamplerType(uniform.type))
{
if (d3dUniform->isReferencedByVertexShader())
if (uniform.isReferencedByVertexShader())
{
vertexRegisters = std::max(vertexRegisters,
d3dUniform->vsRegisterIndex + d3dUniform->registerCount);
vertexRegisters = std::max(vertexRegisters, uniform.vsRegisterIndex + uniform.registerCount);
}
if (d3dUniform->isReferencedByFragmentShader())
if (uniform.isReferencedByFragmentShader())
{
fragmentRegisters = std::max(
fragmentRegisters, d3dUniform->psRegisterIndex + d3dUniform->registerCount);
fragmentRegisters = std::max(fragmentRegisters, uniform.psRegisterIndex + uniform.registerCount);
}
}
}
......@@ -1294,15 +1230,15 @@ gl::Error ProgramD3D::applyUniforms()
{
updateSamplerMapping();
gl::Error error = mRenderer->applyUniforms(*this, mD3DUniforms);
gl::Error error = mRenderer->applyUniforms(*this, mUniforms);
if (error.isError())
{
return error;
}
for (D3DUniform *d3dUniform : mD3DUniforms)
for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
{
d3dUniform->dirty = false;
mUniforms[uniformIndex]->dirty = false;
}
return gl::Error(GL_NO_ERROR);
......@@ -1316,22 +1252,22 @@ gl::Error ProgramD3D::applyUniformBuffers(const gl::Data &data)
const unsigned int reservedBuffersInVS = mRenderer->getReservedVertexUniformBuffers();
const unsigned int reservedBuffersInFS = mRenderer->getReservedFragmentUniformBuffers();
const auto &uniformBlocks = mData.getUniformBlocks();
for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < uniformBlocks.size();
uniformBlockIndex++)
for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < mUniformBlocks.size(); uniformBlockIndex++)
{
const gl::UniformBlock &uniformBlock = uniformBlocks[uniformBlockIndex];
gl::UniformBlock *uniformBlock = mUniformBlocks[uniformBlockIndex];
GLuint blockBinding = mData.getUniformBlockBinding(uniformBlockIndex);
ASSERT(uniformBlock);
// Unnecessary to apply an unreferenced standard or shared UBO
if (!uniformBlock.vertexStaticUse && !uniformBlock.fragmentStaticUse)
if (!uniformBlock->isReferencedByVertexShader() && !uniformBlock->isReferencedByFragmentShader())
{
continue;
}
if (uniformBlock.vertexStaticUse)
if (uniformBlock->isReferencedByVertexShader())
{
unsigned int registerIndex = uniformBlock.vsRegisterIndex - reservedBuffersInVS;
unsigned int registerIndex = uniformBlock->vsRegisterIndex - reservedBuffersInVS;
ASSERT(registerIndex < data.caps->maxVertexUniformBlocks);
if (mVertexUBOCache.size() <= registerIndex)
......@@ -1343,9 +1279,9 @@ gl::Error ProgramD3D::applyUniformBuffers(const gl::Data &data)
mVertexUBOCache[registerIndex] = blockBinding;
}
if (uniformBlock.fragmentStaticUse)
if (uniformBlock->isReferencedByFragmentShader())
{
unsigned int registerIndex = uniformBlock.psRegisterIndex - reservedBuffersInFS;
unsigned int registerIndex = uniformBlock->psRegisterIndex - reservedBuffersInFS;
ASSERT(registerIndex < data.caps->maxFragmentUniformBlocks);
if (mFragmentUBOCache.size() <= registerIndex)
......@@ -1361,11 +1297,31 @@ gl::Error ProgramD3D::applyUniformBuffers(const gl::Data &data)
return mRenderer->setUniformBuffers(data, mVertexUBOCache, mFragmentUBOCache);
}
void ProgramD3D::assignUniformBlockRegister(gl::UniformBlock *uniformBlock,
GLenum shader,
unsigned int registerIndex,
const gl::Caps &caps)
{
// Validation done in the GL-level Program.
if (shader == GL_VERTEX_SHADER)
{
uniformBlock->vsRegisterIndex = registerIndex;
ASSERT(registerIndex < caps.maxVertexUniformBlocks);
}
else if (shader == GL_FRAGMENT_SHADER)
{
uniformBlock->psRegisterIndex = registerIndex;
ASSERT(registerIndex < caps.maxFragmentUniformBlocks);
}
else UNREACHABLE();
}
void ProgramD3D::dirtyAllUniforms()
{
for (D3DUniform *d3dUniform : mD3DUniforms)
unsigned int numUniforms = static_cast<unsigned int>(mUniforms.size());
for (unsigned int index = 0; index < numUniforms; index++)
{
d3dUniform->dirty = true;
mUniforms[index]->dirty = true;
}
}
......@@ -1489,67 +1445,64 @@ void ProgramD3D::getUniformuiv(GLint location, GLuint *params)
getUniformv(location, params, GL_UNSIGNED_INT);
}
void ProgramD3D::assignUniformRegisters()
bool ProgramD3D::defineUniforms(gl::InfoLog &infoLog, const gl::Caps &caps)
{
const gl::Shader *vertexShader = mData.getAttachedVertexShader();
const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(vertexShader);
const gl::Shader *vertexShader = mData.getAttachedVertexShader();
const std::vector<sh::Uniform> &vertexUniforms = vertexShader->getUniforms();
const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(vertexShader);
for (const sh::Uniform &vertexUniform : vertexShader->getUniforms())
for (const sh::Uniform &uniform : vertexUniforms)
{
if (vertexUniform.staticUse)
if (uniform.staticUse)
{
assignUniformRegistersBase(vertexShaderD3D, vertexUniform);
unsigned int registerBase = uniform.isBuiltIn() ? GL_INVALID_INDEX :
vertexShaderD3D->getUniformRegister(uniform.name);
defineUniformBase(vertexShaderD3D, uniform, registerBase);
}
}
const gl::Shader *fragmentShader = mData.getAttachedFragmentShader();
const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(fragmentShader);
const gl::Shader *fragmentShader = mData.getAttachedFragmentShader();
const std::vector<sh::Uniform> &fragmentUniforms = fragmentShader->getUniforms();
const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(fragmentShader);
for (const sh::Uniform &fragmentUniform : fragmentShader->getUniforms())
for (const sh::Uniform &uniform : fragmentUniforms)
{
if (fragmentUniform.staticUse)
if (uniform.staticUse)
{
assignUniformRegistersBase(fragmentShaderD3D, fragmentUniform);
unsigned int registerBase = uniform.isBuiltIn() ? GL_INVALID_INDEX :
fragmentShaderD3D->getUniformRegister(uniform.name);
defineUniformBase(fragmentShaderD3D, uniform, registerBase);
}
}
assignAllSamplerRegisters();
// TODO(jmadill): move the validation part to gl::Program
if (!indexUniforms(infoLog, caps))
{
return false;
}
initializeUniformStorage();
return true;
}
void ProgramD3D::assignUniformRegistersBase(const ShaderD3D *shader, const sh::Uniform &uniform)
void ProgramD3D::defineUniformBase(const ShaderD3D *shader, const sh::Uniform &uniform, unsigned int uniformRegister)
{
if (uniform.isBuiltIn())
if (uniformRegister == GL_INVALID_INDEX)
{
assignUniformRegisters(shader, uniform, uniform.name, nullptr);
defineUniform(shader, uniform, uniform.name, nullptr);
return;
}
unsigned int startRegister = shader->getUniformRegister(uniform.name);
ShShaderOutput outputType = shader->getCompilerOutputType();
sh::HLSLBlockEncoder encoder(sh::HLSLBlockEncoder::GetStrategyFor(outputType));
encoder.skipRegisters(startRegister);
assignUniformRegisters(shader, uniform, uniform.name, &encoder);
}
D3DUniform *ProgramD3D::getD3DUniformByName(const std::string &name)
{
for (D3DUniform *d3dUniform : mD3DUniforms)
{
if (d3dUniform->name == name)
{
return d3dUniform;
}
}
encoder.skipRegisters(uniformRegister);
return nullptr;
defineUniform(shader, uniform, uniform.name, &encoder);
}
void ProgramD3D::assignUniformRegisters(const ShaderD3D *shader,
const sh::ShaderVariable &uniform,
const std::string &fullName,
sh::HLSLBlockEncoder *encoder)
void ProgramD3D::defineUniform(const ShaderD3D *shader, const sh::ShaderVariable &uniform,
const std::string &fullName, sh::HLSLBlockEncoder *encoder)
{
if (uniform.isStruct())
{
......@@ -1565,64 +1518,82 @@ void ProgramD3D::assignUniformRegisters(const ShaderD3D *shader,
const sh::ShaderVariable &field = uniform.fields[fieldIndex];
const std::string &fieldFullName = (fullName + elementString + "." + field.name);
assignUniformRegisters(shader, field, fieldFullName, encoder);
defineUniform(shader, field, fieldFullName, encoder);
}
if (encoder)
encoder->exitAggregateType();
}
return;
}
// Not a struct. Arrays are treated as aggregate types.
if (uniform.isArray() && encoder)
else // Not a struct
{
encoder->enterAggregateType();
}
// Arrays are treated as aggregate types
if (uniform.isArray() && encoder)
{
encoder->enterAggregateType();
}
// Advance the uniform offset, to track registers allocation for structs
sh::BlockMemberInfo blockInfo =
encoder ? encoder->encodeType(uniform.type, uniform.arraySize, false)
: sh::BlockMemberInfo::getDefaultBlockInfo();
gl::LinkedUniform *linkedUniform = getUniformByName(fullName);
D3DUniform *d3dUniform = getD3DUniformByName(fullName);
// Advance the uniform offset, to track registers allocation for structs
sh::BlockMemberInfo blockInfo = encoder ?
encoder->encodeType(uniform.type, uniform.arraySize, false) :
sh::BlockMemberInfo::getDefaultBlockInfo();
if (!d3dUniform)
{
// We're building the list twice, make sure we use the same indexing. Special case
// built-ins.
ASSERT(fullName.compare(0, 3, "gl_") == 0 ||
mData.getUniformIndex(fullName) == static_cast<GLint>(mD3DUniforms.size()));
if (!linkedUniform)
{
linkedUniform = new gl::LinkedUniform(uniform.type, uniform.precision, fullName, uniform.arraySize,
-1, sh::BlockMemberInfo::getDefaultBlockInfo());
ASSERT(linkedUniform);
d3dUniform = new D3DUniform(uniform.type, fullName, uniform.arraySize, true);
mD3DUniforms.push_back(d3dUniform);
if (encoder)
linkedUniform->registerElement = static_cast<unsigned int>(
sh::HLSLBlockEncoder::getBlockRegisterElement(blockInfo));
mUniforms.push_back(linkedUniform);
}
if (encoder)
{
d3dUniform->registerElement =
static_cast<unsigned int>(sh::HLSLBlockEncoder::getBlockRegisterElement(blockInfo));
if (shader->getShaderType() == GL_FRAGMENT_SHADER)
{
linkedUniform->psRegisterIndex =
static_cast<unsigned int>(sh::HLSLBlockEncoder::getBlockRegister(blockInfo));
}
else if (shader->getShaderType() == GL_VERTEX_SHADER)
{
linkedUniform->vsRegisterIndex =
static_cast<unsigned int>(sh::HLSLBlockEncoder::getBlockRegister(blockInfo));
}
else UNREACHABLE();
}
}
if (encoder)
{
unsigned int reg =
static_cast<unsigned int>(sh::HLSLBlockEncoder::getBlockRegister(blockInfo));
if (shader->getShaderType() == GL_FRAGMENT_SHADER)
// Arrays are treated as aggregate types
if (uniform.isArray() && encoder)
{
d3dUniform->psRegisterIndex = reg;
encoder->exitAggregateType();
}
else if (shader->getShaderType() == GL_VERTEX_SHADER)
}
}
void ProgramD3D::defineUniformBlocks(const gl::Caps &caps)
{
const gl::Shader *vertexShader = mData.getAttachedVertexShader();
for (const sh::InterfaceBlock &vertexBlock : vertexShader->getInterfaceBlocks())
{
if (vertexBlock.staticUse || vertexBlock.layout != sh::BLOCKLAYOUT_PACKED)
{
d3dUniform->vsRegisterIndex = reg;
defineUniformBlock(*vertexShader, vertexBlock, caps);
}
else
UNREACHABLE();
}
// Arrays are treated as aggregate types
if (uniform.isArray())
const gl::Shader *fragmentShader = mData.getAttachedFragmentShader();
for (const sh::InterfaceBlock &fragmentBlock : fragmentShader->getInterfaceBlocks())
{
if (fragmentBlock.staticUse || fragmentBlock.layout != sh::BLOCKLAYOUT_PACKED)
{
encoder->exitAggregateType();
defineUniformBlock(*fragmentShader, fragmentBlock, caps);
}
}
}
......@@ -1638,22 +1609,22 @@ static inline void SetIfDirty(T *dest, const T& source, bool *dirtyFlag)
}
template <typename T>
void ProgramD3D::setUniform(GLint location, GLsizei countIn, const T *v, GLenum targetUniformType)
void ProgramD3D::setUniform(GLint location, GLsizei count, const T* v, GLenum targetUniformType)
{
const int components = gl::VariableComponentCount(targetUniformType);
const GLenum targetBoolType = gl::VariableBoolVectorType(targetUniformType);
D3DUniform *targetUniform = getD3DUniformFromLocation(location);
gl::LinkedUniform *targetUniform = getUniformByLocation(location);
int elementCount = targetUniform->elementCount();
unsigned int elementCount = targetUniform->elementCount();
unsigned int arrayElement = mData.getUniformLocations()[location].element;
unsigned int count = std::min(elementCount - arrayElement, static_cast<unsigned int>(countIn));
count = std::min(elementCount - (int)mUniformIndex[location].element, count);
if (targetUniform->type == targetUniformType)
{
T *target = reinterpret_cast<T *>(targetUniform->data) + arrayElement * 4;
T *target = reinterpret_cast<T*>(targetUniform->data) + mUniformIndex[location].element * 4;
for (unsigned int i = 0; i < count; i++)
for (int i = 0; i < count; i++)
{
T *dest = target + (i * 4);
const T *source = v + (i * components);
......@@ -1670,9 +1641,9 @@ void ProgramD3D::setUniform(GLint location, GLsizei countIn, const T *v, GLenum
}
else if (targetUniform->type == targetBoolType)
{
GLint *boolParams = reinterpret_cast<GLint *>(targetUniform->data) + arrayElement * 4;
GLint *boolParams = reinterpret_cast<GLint*>(targetUniform->data) + mUniformIndex[location].element * 4;
for (unsigned int i = 0; i < count; i++)
for (int i = 0; i < count; i++)
{
GLint *dest = boolParams + (i * 4);
const T *source = v + (i * components);
......@@ -1687,15 +1658,15 @@ void ProgramD3D::setUniform(GLint location, GLsizei countIn, const T *v, GLenum
}
}
}
else if (targetUniform->isSampler())
else if (gl::IsSamplerType(targetUniform->type))
{
ASSERT(targetUniformType == GL_INT);
GLint *target = reinterpret_cast<GLint *>(targetUniform->data) + arrayElement * 4;
GLint *target = reinterpret_cast<GLint*>(targetUniform->data) + mUniformIndex[location].element * 4;
bool wasDirty = targetUniform->dirty;
for (unsigned int i = 0; i < count; i++)
for (int i = 0; i < count; i++)
{
GLint *dest = target + (i * 4);
const GLint *source = reinterpret_cast<const GLint*>(v) + (i * components);
......@@ -1783,23 +1754,17 @@ bool expandMatrix(T *target, const GLfloat *value, int targetWidth, int targetHe
}
template <int cols, int rows>
void ProgramD3D::setUniformMatrixfv(GLint location,
GLsizei countIn,
GLboolean transpose,
const GLfloat *value,
GLenum targetUniformType)
void ProgramD3D::setUniformMatrixfv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value, GLenum targetUniformType)
{
D3DUniform *targetUniform = getD3DUniformFromLocation(location);
gl::LinkedUniform *targetUniform = getUniformByLocation(location);
unsigned int elementCount = targetUniform->elementCount();
unsigned int arrayElement = mData.getUniformLocations()[location].element;
unsigned int count = std::min(elementCount - arrayElement, static_cast<unsigned int>(countIn));
int elementCount = targetUniform->elementCount();
count = std::min(elementCount - (int)mUniformIndex[location].element, count);
const unsigned int targetMatrixStride = (4 * rows);
GLfloat *target =
(GLfloat *)(targetUniform->data + arrayElement * sizeof(GLfloat) * targetMatrixStride);
GLfloat *target = (GLfloat*)(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * targetMatrixStride);
for (unsigned int i = 0; i < count; i++)
for (int i = 0; i < count; i++)
{
// Internally store matrices as transposed versions to accomodate HLSL matrix indexing
if (transpose == GL_FALSE)
......@@ -1818,20 +1783,19 @@ void ProgramD3D::setUniformMatrixfv(GLint location,
template <typename T>
void ProgramD3D::getUniformv(GLint location, T *params, GLenum uniformType)
{
D3DUniform *targetUniform = getD3DUniformFromLocation(location);
unsigned int arrayElement = mData.getUniformLocations()[location].element;
gl::LinkedUniform *targetUniform = mUniforms[mUniformIndex[location].index];
if (gl::IsMatrixType(targetUniform->type))
{
const int rows = gl::VariableRowCount(targetUniform->type);
const int cols = gl::VariableColumnCount(targetUniform->type);
transposeMatrix(params, (GLfloat *)targetUniform->data + arrayElement * 4 * rows, rows,
cols, 4, rows);
transposeMatrix(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4 * rows, rows, cols, 4, rows);
}
else if (uniformType == gl::VariableComponentType(targetUniform->type))
{
unsigned int size = gl::VariableComponentCount(targetUniform->type);
memcpy(params, targetUniform->data + arrayElement * 4 * sizeof(T), size * sizeof(T));
memcpy(params, targetUniform->data + mUniformIndex[location].element * 4 * sizeof(T),
size * sizeof(T));
}
else
{
......@@ -1840,7 +1804,7 @@ void ProgramD3D::getUniformv(GLint location, T *params, GLenum uniformType)
{
case GL_BOOL:
{
GLint *boolParams = (GLint *)targetUniform->data + arrayElement * 4;
GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
for (unsigned int i = 0; i < size; i++)
{
......@@ -1851,7 +1815,7 @@ void ProgramD3D::getUniformv(GLint location, T *params, GLenum uniformType)
case GL_FLOAT:
{
GLfloat *floatParams = (GLfloat *)targetUniform->data + arrayElement * 4;
GLfloat *floatParams = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4;
for (unsigned int i = 0; i < size; i++)
{
......@@ -1862,7 +1826,7 @@ void ProgramD3D::getUniformv(GLint location, T *params, GLenum uniformType)
case GL_INT:
{
GLint *intParams = (GLint *)targetUniform->data + arrayElement * 4;
GLint *intParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
for (unsigned int i = 0; i < size; i++)
{
......@@ -1873,7 +1837,7 @@ void ProgramD3D::getUniformv(GLint location, T *params, GLenum uniformType)
case GL_UNSIGNED_INT:
{
GLuint *uintParams = (GLuint *)targetUniform->data + arrayElement * 4;
GLuint *uintParams = (GLuint*)targetUniform->data + mUniformIndex[location].element * 4;
for (unsigned int i = 0; i < size; i++)
{
......@@ -1887,63 +1851,115 @@ void ProgramD3D::getUniformv(GLint location, T *params, GLenum uniformType)
}
}
size_t ProgramD3D::defineUniformBlock(const sh::InterfaceBlock &interfaceBlock,
BlockInfoMap *blockInfoOut)
template <typename VarT>
void ProgramD3D::defineUniformBlockMembers(const std::vector<VarT> &fields, const std::string &prefix, int blockIndex,
sh::BlockLayoutEncoder *encoder, std::vector<unsigned int> *blockUniformIndexes,
bool inRowMajorLayout)
{
ASSERT(interfaceBlock.staticUse || interfaceBlock.layout == sh::BLOCKLAYOUT_PACKED);
// define member uniforms
sh::Std140BlockEncoder std140Encoder;
sh::HLSLBlockEncoder hlslEncoder(sh::HLSLBlockEncoder::ENCODE_PACKED);
sh::BlockLayoutEncoder *encoder = nullptr;
if (interfaceBlock.layout == sh::BLOCKLAYOUT_STANDARD)
{
encoder = &std140Encoder;
}
else
for (unsigned int uniformIndex = 0; uniformIndex < fields.size(); uniformIndex++)
{
encoder = &hlslEncoder;
}
const VarT &field = fields[uniformIndex];
const std::string &fieldName = (prefix.empty() ? field.name : prefix + "." + field.name);
GetUniformBlockInfo(interfaceBlock.fields, "", encoder, interfaceBlock.isRowMajorLayout,
blockInfoOut);
if (field.isStruct())
{
bool rowMajorLayout = (inRowMajorLayout || IsRowMajorLayout(field));
return encoder->getBlockSize();
}
for (unsigned int arrayElement = 0; arrayElement < field.elementCount(); arrayElement++)
{
encoder->enterAggregateType();
void ProgramD3D::assignAllSamplerRegisters()
{
for (const D3DUniform *d3dUniform : mD3DUniforms)
{
if (d3dUniform->isSampler())
const std::string uniformElementName = fieldName + (field.isArray() ? ArrayString(arrayElement) : "");
defineUniformBlockMembers(field.fields, uniformElementName, blockIndex, encoder, blockUniformIndexes, rowMajorLayout);
encoder->exitAggregateType();
}
}
else
{
assignSamplerRegisters(d3dUniform);
bool isRowMajorMatrix = (gl::IsMatrixType(field.type) && inRowMajorLayout);
sh::BlockMemberInfo memberInfo = encoder->encodeType(field.type, field.arraySize, isRowMajorMatrix);
gl::LinkedUniform *newUniform = new gl::LinkedUniform(field.type, field.precision, fieldName, field.arraySize,
blockIndex, memberInfo);
// add to uniform list, but not index, since uniform block uniforms have no location
blockUniformIndexes->push_back(static_cast<GLenum>(mUniforms.size()));
mUniforms.push_back(newUniform);
}
}
}
void ProgramD3D::assignSamplerRegisters(const D3DUniform *d3dUniform)
void ProgramD3D::defineUniformBlock(const gl::Shader &shader,
const sh::InterfaceBlock &interfaceBlock,
const gl::Caps &caps)
{
ASSERT(d3dUniform->isSampler());
ASSERT(d3dUniform->vsRegisterIndex != GL_INVALID_INDEX ||
d3dUniform->psRegisterIndex != GL_INVALID_INDEX);
const ShaderD3D* shaderD3D = GetImplAs<ShaderD3D>(&shader);
if (d3dUniform->vsRegisterIndex != GL_INVALID_INDEX)
// create uniform block entries if they do not exist
if (getUniformBlockIndex(interfaceBlock.name) == GL_INVALID_INDEX)
{
AssignSamplers(d3dUniform->vsRegisterIndex, d3dUniform->type, d3dUniform->arraySize,
mSamplersVS, &mUsedVertexSamplerRange);
std::vector<unsigned int> blockUniformIndexes;
const unsigned int blockIndex = static_cast<unsigned int>(mUniformBlocks.size());
// define member uniforms
sh::BlockLayoutEncoder *encoder = NULL;
if (interfaceBlock.layout == sh::BLOCKLAYOUT_STANDARD)
{
encoder = new sh::Std140BlockEncoder;
}
else
{
encoder = new sh::HLSLBlockEncoder(sh::HLSLBlockEncoder::ENCODE_PACKED);
}
ASSERT(encoder);
defineUniformBlockMembers(interfaceBlock.fields, "", blockIndex, encoder, &blockUniformIndexes, interfaceBlock.isRowMajorLayout);
unsigned int dataSize = static_cast<unsigned int>(encoder->getBlockSize());
// create all the uniform blocks
if (interfaceBlock.arraySize > 0)
{
for (unsigned int uniformBlockElement = 0; uniformBlockElement < interfaceBlock.arraySize; uniformBlockElement++)
{
gl::UniformBlock *newUniformBlock = new gl::UniformBlock(interfaceBlock.name, uniformBlockElement, dataSize);
newUniformBlock->memberUniformIndexes = blockUniformIndexes;
mUniformBlocks.push_back(newUniformBlock);
}
}
else
{
gl::UniformBlock *newUniformBlock = new gl::UniformBlock(interfaceBlock.name, GL_INVALID_INDEX, dataSize);
newUniformBlock->memberUniformIndexes = blockUniformIndexes;
mUniformBlocks.push_back(newUniformBlock);
}
}
if (d3dUniform->psRegisterIndex != GL_INVALID_INDEX)
if (interfaceBlock.staticUse)
{
AssignSamplers(d3dUniform->psRegisterIndex, d3dUniform->type, d3dUniform->arraySize,
mSamplersPS, &mUsedPixelSamplerRange);
// Assign registers to the uniform blocks
const GLuint blockIndex = getUniformBlockIndex(interfaceBlock.name);
const unsigned int elementCount = std::max(1u, interfaceBlock.arraySize);
ASSERT(blockIndex != GL_INVALID_INDEX);
ASSERT(blockIndex + elementCount <= mUniformBlocks.size());
unsigned int interfaceBlockRegister = shaderD3D->getInterfaceBlockRegister(interfaceBlock.name);
for (unsigned int uniformBlockElement = 0; uniformBlockElement < elementCount; uniformBlockElement++)
{
gl::UniformBlock *uniformBlock = mUniformBlocks[blockIndex + uniformBlockElement];
ASSERT(uniformBlock->name == interfaceBlock.name);
assignUniformBlockRegister(uniformBlock, shader.getType(),
interfaceBlockRegister + uniformBlockElement, caps);
}
}
}
// static
void ProgramD3D::AssignSamplers(unsigned int startSamplerIndex,
bool ProgramD3D::assignSamplers(unsigned int startSamplerIndex,
GLenum samplerType,
unsigned int samplerCount,
std::vector<Sampler> &outSamplers,
......@@ -1953,18 +1969,103 @@ void ProgramD3D::AssignSamplers(unsigned int startSamplerIndex,
do
{
ASSERT(samplerIndex < outSamplers.size());
Sampler *sampler = &outSamplers[samplerIndex];
sampler->active = true;
sampler->textureType = GetTextureType(samplerType);
sampler->logicalTextureUnit = 0;
*outUsedRange = std::max(samplerIndex + 1, *outUsedRange);
if (samplerIndex < outSamplers.size())
{
Sampler& sampler = outSamplers[samplerIndex];
sampler.active = true;
sampler.textureType = GetTextureType(samplerType);
sampler.logicalTextureUnit = 0;
*outUsedRange = std::max(samplerIndex + 1, *outUsedRange);
}
else
{
return false;
}
samplerIndex++;
} while (samplerIndex < startSamplerIndex + samplerCount);
return true;
}
bool ProgramD3D::indexSamplerUniform(const gl::LinkedUniform &uniform, gl::InfoLog &infoLog, const gl::Caps &caps)
{
ASSERT(gl::IsSamplerType(uniform.type));
ASSERT(uniform.vsRegisterIndex != GL_INVALID_INDEX || uniform.psRegisterIndex != GL_INVALID_INDEX);
if (uniform.vsRegisterIndex != GL_INVALID_INDEX)
{
if (!assignSamplers(uniform.vsRegisterIndex, uniform.type, uniform.arraySize, mSamplersVS,
&mUsedVertexSamplerRange))
{
infoLog << "Vertex shader sampler count exceeds the maximum vertex texture units ("
<< mSamplersVS.size() << ").";
return false;
}
unsigned int maxVertexVectors = mRenderer->getReservedVertexUniformVectors() + caps.maxVertexUniformVectors;
if (uniform.vsRegisterIndex + uniform.registerCount > maxVertexVectors)
{
infoLog << "Vertex shader active uniforms exceed GL_MAX_VERTEX_UNIFORM_VECTORS ("
<< caps.maxVertexUniformVectors << ").";
return false;
}
}
if (uniform.psRegisterIndex != GL_INVALID_INDEX)
{
if (!assignSamplers(uniform.psRegisterIndex, uniform.type, uniform.arraySize, mSamplersPS,
&mUsedPixelSamplerRange))
{
infoLog << "Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS ("
<< mSamplersPS.size() << ").";
return false;
}
unsigned int maxFragmentVectors = mRenderer->getReservedFragmentUniformVectors() + caps.maxFragmentUniformVectors;
if (uniform.psRegisterIndex + uniform.registerCount > maxFragmentVectors)
{
infoLog << "Fragment shader active uniforms exceed GL_MAX_FRAGMENT_UNIFORM_VECTORS ("
<< caps.maxFragmentUniformVectors << ").";
return false;
}
}
return true;
}
bool ProgramD3D::indexUniforms(gl::InfoLog &infoLog, const gl::Caps &caps)
{
for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
{
const gl::LinkedUniform &uniform = *mUniforms[uniformIndex];
if (gl::IsSamplerType(uniform.type))
{
if (!indexSamplerUniform(uniform, infoLog, caps))
{
return false;
}
}
for (unsigned int arrayIndex = 0; arrayIndex < uniform.elementCount(); arrayIndex++)
{
if (!uniform.isBuiltIn())
{
// Assign in-order uniform locations
mUniformIndex[static_cast<GLuint>(mUniformIndex.size())] = gl::VariableLocation(
uniform.name, arrayIndex, static_cast<unsigned int>(uniformIndex));
}
}
}
return true;
}
void ProgramD3D::reset()
{
ProgramImpl::reset();
SafeDeleteContainer(mVertexExecutables);
SafeDeleteContainer(mPixelExecutables);
SafeDelete(mGeometryExecutable);
......@@ -1979,8 +2080,6 @@ void ProgramD3D::reset()
mPixelShaderKey.clear();
mUsesPointSize = false;
SafeDeleteContainer(mD3DUniforms);
SafeDelete(mVertexUniformStorage);
SafeDelete(mFragmentUniformStorage);
......@@ -2090,9 +2189,4 @@ void ProgramD3D::gatherTransformFeedbackVaryings(
}
}
}
D3DUniform *ProgramD3D::getD3DUniformFromLocation(GLint location)
{
return mD3DUniforms[mData.getUniformLocations()[location].index];
}
}
......@@ -20,6 +20,13 @@
#include "libANGLE/renderer/d3d/DynamicHLSL.h"
#include "libANGLE/renderer/d3d/WorkaroundsD3D.h"
namespace gl
{
struct LinkedUniform;
struct VariableLocation;
struct VertexFormat;
}
namespace rx
{
class RendererD3D;
......@@ -32,42 +39,6 @@ class ShaderExecutableD3D;
#define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL1
#endif
// Helper struct representing a single shader uniform
struct D3DUniform
{
D3DUniform(GLenum typeIn,
const std::string &nameIn,
unsigned int arraySizeIn,
bool defaultBlock);
~D3DUniform();
bool isSampler() const;
unsigned int elementCount() const { return std::max(1u, arraySize); }
bool isReferencedByVertexShader() const;
bool isReferencedByFragmentShader() const;
// Duplicated from the GL layer
GLenum type;
std::string name;
unsigned int arraySize;
// Pointer to a system copy of the data.
unsigned char *data;
// Has the data been updated since the last sync?
bool dirty;
// Register information.
unsigned int vsRegisterIndex;
unsigned int psRegisterIndex;
unsigned int registerCount;
// Register "elements" are used for uniform structs in ES3, to appropriately identify single
// uniforms
// inside aggregate types, which are packed according C-like structure rules.
unsigned int registerElement;
};
class ProgramD3D : public ProgramImpl
{
public:
......@@ -102,12 +73,13 @@ class ProgramD3D : public ProgramImpl
LinkResult link(const gl::Data &data, gl::InfoLog &infoLog) override;
GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) override;
void gatherUniformBlockInfo(std::vector<gl::UniformBlock> *uniformBlocks,
std::vector<gl::LinkedUniform> *uniforms) override;
void initializeUniformStorage();
gl::Error applyUniforms();
gl::Error applyUniformBuffers(const gl::Data &data);
void assignUniformBlockRegister(gl::UniformBlock *uniformBlock,
GLenum shader,
unsigned int registerIndex,
const gl::Caps &caps);
void dirtyAllUniforms();
void setUniform1fv(GLint location, GLsizei count, const GLfloat *v);
......@@ -139,6 +111,8 @@ class ProgramD3D : public ProgramImpl
const UniformStorageD3D &getVertexUniformStorage() const { return *mVertexUniformStorage; }
const UniformStorageD3D &getFragmentUniformStorage() const { return *mFragmentUniformStorage; }
void reset();
unsigned int getSerial() const;
void sortAttributesByLayout(const std::vector<TranslatedAttribute> &unsortedAttributes,
......@@ -201,24 +175,19 @@ class ProgramD3D : public ProgramImpl
GLenum textureType;
};
typedef std::map<std::string, sh::BlockMemberInfo> BlockInfoMap;
void assignUniformRegisters();
void assignUniformRegistersBase(const ShaderD3D *shader, const sh::Uniform &uniform);
void assignUniformRegisters(const ShaderD3D *shader,
const sh::ShaderVariable &uniform,
const std::string &fullName,
sh::HLSLBlockEncoder *encoder);
void assignAllSamplerRegisters();
void assignSamplerRegisters(const D3DUniform *d3dUniform);
static void AssignSamplers(unsigned int startSamplerIndex,
GLenum samplerType,
unsigned int samplerCount,
std::vector<Sampler> &outSamplers,
GLuint *outUsedRange);
bool defineUniforms(gl::InfoLog &infoLog, const gl::Caps &caps);
void defineUniformBase(const ShaderD3D *shader, const sh::Uniform &uniform, unsigned int uniformRegister);
void defineUniform(const ShaderD3D *shader, const sh::ShaderVariable &uniform, const std::string &fullName,
sh::HLSLBlockEncoder *encoder);
bool indexSamplerUniform(const gl::LinkedUniform &uniform, gl::InfoLog &infoLog, const gl::Caps &caps);
bool indexUniforms(gl::InfoLog &infoLog, const gl::Caps &caps);
static bool assignSamplers(unsigned int startSamplerIndex, GLenum samplerType, unsigned int samplerCount,
std::vector<Sampler> &outSamplers, GLuint *outUsedRange);
size_t defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, BlockInfoMap *blockInfoOut);
void defineUniformBlocks(const gl::Caps &caps);
void defineUniformBlock(const gl::Shader &shader,
const sh::InterfaceBlock &interfaceBlock,
const gl::Caps &caps);
template <typename T>
void setUniform(GLint location, GLsizei count, const T* v, GLenum targetUniformType);
......@@ -229,19 +198,20 @@ class ProgramD3D : public ProgramImpl
template <typename T>
void getUniformv(GLint location, T *params, GLenum uniformType);
template <typename VarT>
void defineUniformBlockMembers(const std::vector<VarT> &fields, const std::string &prefix, int blockIndex,
sh::BlockLayoutEncoder *encoder, std::vector<unsigned int> *blockUniformIndexes,
bool inRowMajorLayout);
LinkResult compileProgramExecutables(gl::InfoLog &infoLog,
int registers,
const std::vector<PackedVarying> &packedVaryings);
void gatherTransformFeedbackVaryings(const std::vector<gl::LinkedVarying> &varyings);
D3DUniform *getD3DUniformByName(const std::string &name);
D3DUniform *getD3DUniformFromLocation(GLint location);
void initSemanticIndex();
void initAttributesByLayout();
void reset();
RendererD3D *mRenderer;
DynamicHLSL *mDynamicHLSL;
......@@ -289,7 +259,6 @@ class ProgramD3D : public ProgramImpl
gl::InputLayout mCachedInputLayout;
std::vector<gl::LinkedVarying> mTransformFeedbackLinkedVaryings;
std::vector<D3DUniform *> mD3DUniforms;
static unsigned int issueSerial();
static unsigned int mCurrentSerial;
......
......@@ -37,10 +37,8 @@ class DebugAnnotator;
namespace rx
{
struct D3DUniform;
class ImageD3D;
class IndexBuffer;
class ProgramD3D;
class RenderTargetD3D;
class ShaderExecutableD3D;
class SwapChainD3D;
......@@ -159,8 +157,7 @@ class RendererD3D : public Renderer, public BufferFactoryD3D
const gl::Framebuffer *framebuffer,
bool rasterizerDiscard,
bool transformFeedbackActive) = 0;
virtual gl::Error applyUniforms(const ProgramD3D &programD3D,
const std::vector<D3DUniform *> &uniformArray) = 0;
virtual gl::Error applyUniforms(const ProgramImpl &program, const std::vector<gl::LinkedUniform*> &uniformArray) = 0;
virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount, bool usesPointSize) = 0;
virtual gl::Error applyVertexBuffer(const gl::State &state, GLenum mode, GLint first, GLsizei count, GLsizei instances, SourceIndexData *sourceIndexInfo) = 0;
virtual gl::Error applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo, SourceIndexData *sourceIndexInfo) = 0;
......
......@@ -2095,8 +2095,7 @@ gl::Error Renderer11::applyShaders(gl::Program *program,
return gl::Error(GL_NO_ERROR);
}
gl::Error Renderer11::applyUniforms(const ProgramD3D &programD3D,
const std::vector<D3DUniform *> &uniformArray)
gl::Error Renderer11::applyUniforms(const ProgramImpl &program, const std::vector<gl::LinkedUniform*> &uniformArray)
{
unsigned int totalRegisterCountVS = 0;
unsigned int totalRegisterCountPS = 0;
......@@ -2104,25 +2103,26 @@ gl::Error Renderer11::applyUniforms(const ProgramD3D &programD3D,
bool vertexUniformsDirty = false;
bool pixelUniformsDirty = false;
for (const D3DUniform *uniform : uniformArray)
for (size_t uniformIndex = 0; uniformIndex < uniformArray.size(); uniformIndex++)
{
if (uniform->isReferencedByVertexShader() && !uniform->isSampler())
const gl::LinkedUniform &uniform = *uniformArray[uniformIndex];
if (uniform.isReferencedByVertexShader() && !uniform.isSampler())
{
totalRegisterCountVS += uniform->registerCount;
vertexUniformsDirty = (vertexUniformsDirty || uniform->dirty);
totalRegisterCountVS += uniform.registerCount;
vertexUniformsDirty = (vertexUniformsDirty || uniform.dirty);
}
if (uniform->isReferencedByFragmentShader() && !uniform->isSampler())
if (uniform.isReferencedByFragmentShader() && !uniform.isSampler())
{
totalRegisterCountPS += uniform->registerCount;
pixelUniformsDirty = (pixelUniformsDirty || uniform->dirty);
totalRegisterCountPS += uniform.registerCount;
pixelUniformsDirty = (pixelUniformsDirty || uniform.dirty);
}
}
const UniformStorage11 *vertexUniformStorage =
GetAs<UniformStorage11>(&programD3D.getVertexUniformStorage());
const UniformStorage11 *fragmentUniformStorage =
GetAs<UniformStorage11>(&programD3D.getFragmentUniformStorage());
const ProgramD3D *programD3D = GetAs<ProgramD3D>(&program);
const UniformStorage11 *vertexUniformStorage = GetAs<UniformStorage11>(&programD3D->getVertexUniformStorage());
const UniformStorage11 *fragmentUniformStorage = GetAs<UniformStorage11>(&programD3D->getFragmentUniformStorage());
ASSERT(vertexUniformStorage);
ASSERT(fragmentUniformStorage);
......@@ -2150,26 +2150,26 @@ gl::Error Renderer11::applyUniforms(const ProgramD3D &programD3D,
mapPS = (float(*)[4])map.pData;
}
for (const D3DUniform *uniform : uniformArray)
for (size_t uniformIndex = 0; uniformIndex < uniformArray.size(); uniformIndex++)
{
if (uniform->isSampler())
continue;
gl::LinkedUniform *uniform = uniformArray[uniformIndex];
unsigned int componentCount = (4 - uniform->registerElement);
if (!uniform->isSampler())
{
unsigned int componentCount = (4 - uniform->registerElement);
// we assume that uniforms from structs are arranged in struct order in our uniforms list.
// otherwise we would overwrite previously written regions of memory.
// we assume that uniforms from structs are arranged in struct order in our uniforms list. otherwise we would
// overwrite previously written regions of memory.
if (uniform->isReferencedByVertexShader() && mapVS)
{
memcpy(&mapVS[uniform->vsRegisterIndex][uniform->registerElement], uniform->data,
uniform->registerCount * sizeof(float) * componentCount);
}
if (uniform->isReferencedByVertexShader() && mapVS)
{
memcpy(&mapVS[uniform->vsRegisterIndex][uniform->registerElement], uniform->data, uniform->registerCount * sizeof(float) * componentCount);
}
if (uniform->isReferencedByFragmentShader() && mapPS)
{
memcpy(&mapPS[uniform->psRegisterIndex][uniform->registerElement], uniform->data,
uniform->registerCount * sizeof(float) * componentCount);
if (uniform->isReferencedByFragmentShader() && mapPS)
{
memcpy(&mapPS[uniform->psRegisterIndex][uniform->registerElement], uniform->data, uniform->registerCount * sizeof(float) * componentCount);
}
}
}
......@@ -2255,7 +2255,7 @@ gl::Error Renderer11::applyUniforms(const ProgramD3D &programD3D,
}
// GSSetConstantBuffers triggers device removal on 9_3, so we should only call it if necessary
if (programD3D.usesGeometryShader())
if (programD3D->usesGeometryShader())
{
// needed for the point sprite geometry shader
if (mCurrentGeometryConstantBuffer != mDriverConstantBufferPS)
......
......@@ -137,8 +137,7 @@ class Renderer11 : public RendererD3D
bool rasterizerDiscard,
bool transformFeedbackActive) override;
gl::Error applyUniforms(const ProgramD3D &programD3D,
const std::vector<D3DUniform *> &uniformArray) override;
virtual gl::Error applyUniforms(const ProgramImpl &program, const std::vector<gl::LinkedUniform*> &uniformArray);
virtual gl::Error applyVertexBuffer(const gl::State &state, GLenum mode, GLint first, GLsizei count, GLsizei instances, SourceIndexData *sourceIndexInfo);
virtual gl::Error applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo, SourceIndexData *sourceIndexInfo);
void applyTransformFeedbackBuffers(const gl::State &state) override;
......
......@@ -1910,45 +1910,46 @@ gl::Error Renderer9::applyShaders(gl::Program *program,
return gl::Error(GL_NO_ERROR);
}
gl::Error Renderer9::applyUniforms(const ProgramD3D &programD3D,
const std::vector<D3DUniform *> &uniformArray)
gl::Error Renderer9::applyUniforms(const ProgramImpl &program, const std::vector<gl::LinkedUniform*> &uniformArray)
{
for (const D3DUniform *targetUniform : uniformArray)
for (size_t uniformIndex = 0; uniformIndex < uniformArray.size(); uniformIndex++)
{
if (!targetUniform->dirty)
continue;
gl::LinkedUniform *targetUniform = uniformArray[uniformIndex];
GLfloat *f = (GLfloat *)targetUniform->data;
GLint *i = (GLint *)targetUniform->data;
switch (targetUniform->type)
if (targetUniform->dirty)
{
case GL_SAMPLER_2D:
case GL_SAMPLER_CUBE:
GLfloat *f = (GLfloat*)targetUniform->data;
GLint *i = (GLint*)targetUniform->data;
switch (targetUniform->type)
{
case GL_SAMPLER_2D:
case GL_SAMPLER_CUBE:
break;
case GL_BOOL:
case GL_BOOL_VEC2:
case GL_BOOL_VEC3:
case GL_BOOL_VEC4:
case GL_BOOL:
case GL_BOOL_VEC2:
case GL_BOOL_VEC3:
case GL_BOOL_VEC4:
applyUniformnbv(targetUniform, i);
break;
case GL_FLOAT:
case GL_FLOAT_VEC2:
case GL_FLOAT_VEC3:
case GL_FLOAT_VEC4:
case GL_FLOAT_MAT2:
case GL_FLOAT_MAT3:
case GL_FLOAT_MAT4:
case GL_FLOAT:
case GL_FLOAT_VEC2:
case GL_FLOAT_VEC3:
case GL_FLOAT_VEC4:
case GL_FLOAT_MAT2:
case GL_FLOAT_MAT3:
case GL_FLOAT_MAT4:
applyUniformnfv(targetUniform, f);
break;
case GL_INT:
case GL_INT_VEC2:
case GL_INT_VEC3:
case GL_INT_VEC4:
case GL_INT:
case GL_INT_VEC2:
case GL_INT_VEC3:
case GL_INT_VEC4:
applyUniformniv(targetUniform, i);
break;
default:
default:
UNREACHABLE();
}
}
}
......@@ -1963,7 +1964,7 @@ gl::Error Renderer9::applyUniforms(const ProgramD3D &programD3D,
return gl::Error(GL_NO_ERROR);
}
void Renderer9::applyUniformnfv(const D3DUniform *targetUniform, const GLfloat *v)
void Renderer9::applyUniformnfv(gl::LinkedUniform *targetUniform, const GLfloat *v)
{
if (targetUniform->isReferencedByFragmentShader())
{
......@@ -1976,7 +1977,7 @@ void Renderer9::applyUniformnfv(const D3DUniform *targetUniform, const GLfloat *
}
}
void Renderer9::applyUniformniv(const D3DUniform *targetUniform, const GLint *v)
void Renderer9::applyUniformniv(gl::LinkedUniform *targetUniform, const GLint *v)
{
ASSERT(targetUniform->registerCount <= MAX_VERTEX_CONSTANT_VECTORS_D3D9);
GLfloat vector[MAX_VERTEX_CONSTANT_VECTORS_D3D9][4];
......@@ -1992,7 +1993,7 @@ void Renderer9::applyUniformniv(const D3DUniform *targetUniform, const GLint *v)
applyUniformnfv(targetUniform, (GLfloat*)vector);
}
void Renderer9::applyUniformnbv(const D3DUniform *targetUniform, const GLint *v)
void Renderer9::applyUniformnbv(gl::LinkedUniform *targetUniform, const GLint *v)
{
ASSERT(targetUniform->registerCount <= MAX_VERTEX_CONSTANT_VECTORS_D3D9);
GLfloat vector[MAX_VERTEX_CONSTANT_VECTORS_D3D9][4];
......
......@@ -32,12 +32,10 @@ namespace rx
{
class Blit9;
class IndexDataManager;
class ProgramD3D;
class StreamingIndexBufferInterface;
class StaticIndexBufferInterface;
class VertexDataManager;
struct ClearParameters;
struct D3DUniform;
struct TranslatedAttribute;
enum D3D9InitError
......@@ -113,8 +111,7 @@ class Renderer9 : public RendererD3D
const gl::Framebuffer *framebuffer,
bool rasterizerDiscard,
bool transformFeedbackActive) override;
gl::Error applyUniforms(const ProgramD3D &programD3D,
const std::vector<D3DUniform *> &uniformArray) override;
virtual gl::Error applyUniforms(const ProgramImpl &program, const std::vector<gl::LinkedUniform*> &uniformArray);
virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount, bool usesPointSize);
virtual gl::Error applyVertexBuffer(const gl::State &state, GLenum mode, GLint first, GLsizei count, GLsizei instances, SourceIndexData *sourceInfo);
virtual gl::Error applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo, SourceIndexData *sourceIndexInfo);
......@@ -261,9 +258,9 @@ class Renderer9 : public RendererD3D
void release();
void applyUniformnfv(const D3DUniform *targetUniform, const GLfloat *v);
void applyUniformniv(const D3DUniform *targetUniform, const GLint *v);
void applyUniformnbv(const D3DUniform *targetUniform, const GLint *v);
void applyUniformnfv(gl::LinkedUniform *targetUniform, const GLfloat *v);
void applyUniformniv(gl::LinkedUniform *targetUniform, const GLint *v);
void applyUniformnbv(gl::LinkedUniform *targetUniform, const GLint *v);
gl::Error drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer);
gl::Error drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer);
......
......@@ -115,41 +115,68 @@ LinkResult ProgramGL::link(const gl::Data &data, gl::InfoLog &infoLog)
}
// Query the uniform information
ASSERT(mUniformRealLocationMap.empty());
const auto &uniforms = mData.getUniforms();
for (const gl::VariableLocation &entry : mData.getUniformLocations())
// TODO: A lot of this logic should be done at the gl::Program level
GLint activeUniformMaxLength = 0;
mFunctions->getProgramiv(mProgramID, GL_ACTIVE_UNIFORM_MAX_LENGTH, &activeUniformMaxLength);
std::vector<GLchar> uniformNameBuffer(activeUniformMaxLength);
GLint uniformCount = 0;
mFunctions->getProgramiv(mProgramID, GL_ACTIVE_UNIFORMS, &uniformCount);
for (GLint i = 0; i < uniformCount; i++)
{
// From the spec:
// "Locations for sequential array indices are not required to be sequential."
const gl::LinkedUniform &uniform = uniforms[entry.index];
std::stringstream fullNameStr;
fullNameStr << uniform.name;
if (uniform.isArray())
{
fullNameStr << "[" << entry.element << "]";
}
const std::string &fullName = fullNameStr.str();
GLsizei uniformNameLength = 0;
GLint uniformSize = 0;
GLenum uniformType = GL_NONE;
mFunctions->getActiveUniform(mProgramID, i, static_cast<GLsizei>(uniformNameBuffer.size()),
&uniformNameLength, &uniformSize, &uniformType,
&uniformNameBuffer[0]);
GLint realLocation = mFunctions->getUniformLocation(mProgramID, fullName.c_str());
mUniformRealLocationMap.push_back(realLocation);
}
size_t subscript = 0;
std::string uniformName = gl::ParseUniformName(std::string(&uniformNameBuffer[0], uniformNameLength), &subscript);
mUniformIndexToSamplerIndex.resize(mData.getUniforms().size(), GL_INVALID_INDEX);
bool isArray = uniformSize > 1 || subscript != GL_INVALID_INDEX;
for (size_t uniformId = 0; uniformId < uniforms.size(); ++uniformId)
{
const gl::LinkedUniform &linkedUniform = uniforms[uniformId];
for (size_t arrayIndex = 0; arrayIndex < static_cast<size_t>(uniformSize); arrayIndex++)
{
std::string locationName = uniformName;
if (isArray)
{
locationName += "[" + Str(static_cast<int>(arrayIndex)) + "]";
}
GLint location = mFunctions->getUniformLocation(mProgramID, locationName.c_str());
if (location >= 0)
{
mUniformIndex[location] =
gl::VariableLocation(uniformName, static_cast<unsigned int>(arrayIndex),
static_cast<unsigned int>(mUniforms.size()));
// If the uniform is a sampler, track it in the sampler bindings array
if (gl::IsSamplerType(uniformType))
{
SamplerLocation samplerLoc;
samplerLoc.samplerIndex = mSamplerBindings.size();
samplerLoc.arrayIndex = arrayIndex;
mSamplerUniformMap[location] = samplerLoc;
}
}
}
if (!linkedUniform.isSampler() || !linkedUniform.staticUse)
continue;
// ANGLE uses 0 to identify an non-array uniform.
unsigned int arraySize = isArray ? static_cast<unsigned int>(uniformSize) : 0;
mUniformIndexToSamplerIndex[uniformId] = mSamplerBindings.size();
// TODO: determine uniform precision
mUniforms.push_back(new gl::LinkedUniform(uniformType, GL_NONE, uniformName, arraySize, -1, sh::BlockMemberInfo::getDefaultBlockInfo()));
// If uniform is a sampler type, insert it into the mSamplerBindings array
SamplerBindingGL samplerBinding;
samplerBinding.textureType = gl::SamplerTypeToTextureType(linkedUniform.type);
samplerBinding.boundTextureUnits.resize(linkedUniform.elementCount(), 0);
mSamplerBindings.push_back(samplerBinding);
if (gl::IsSamplerType(uniformType))
{
SamplerBindingGL samplerBinding;
samplerBinding.textureType = gl::SamplerTypeToTextureType(uniformType);
samplerBinding.boundTextureUnits.resize(uniformSize, 0);
mSamplerBindings.push_back(samplerBinding);
}
}
return LinkResult(true, gl::Error(GL_NO_ERROR));
......@@ -164,61 +191,59 @@ GLboolean ProgramGL::validate(const gl::Caps & /*caps*/, gl::InfoLog * /*infoLog
void ProgramGL::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
{
mStateManager->useProgram(mProgramID);
mFunctions->uniform1fv(uniLoc(location), count, v);
mFunctions->uniform1fv(location, count, v);
}
void ProgramGL::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
{
mStateManager->useProgram(mProgramID);
mFunctions->uniform2fv(uniLoc(location), count, v);
mFunctions->uniform2fv(location, count, v);
}
void ProgramGL::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
{
mStateManager->useProgram(mProgramID);
mFunctions->uniform3fv(uniLoc(location), count, v);
mFunctions->uniform3fv(location, count, v);
}
void ProgramGL::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
{
mStateManager->useProgram(mProgramID);
mFunctions->uniform4fv(uniLoc(location), count, v);
mFunctions->uniform4fv(location, count, v);
}
void ProgramGL::setUniform1iv(GLint location, GLsizei count, const GLint *v)
{
mStateManager->useProgram(mProgramID);
mFunctions->uniform1iv(uniLoc(location), count, v);
const gl::VariableLocation &locationEntry = mData.getUniformLocations()[location];
mFunctions->uniform1iv(location, count, v);
size_t samplerIndex = mUniformIndexToSamplerIndex[locationEntry.index];
if (samplerIndex != GL_INVALID_INDEX)
auto iter = mSamplerUniformMap.find(location);
if (iter != mSamplerUniformMap.end())
{
std::vector<GLuint> &boundTextureUnits = mSamplerBindings[samplerIndex].boundTextureUnits;
const SamplerLocation &samplerLoc = iter->second;
std::vector<GLuint> &boundTextureUnits = mSamplerBindings[samplerLoc.samplerIndex].boundTextureUnits;
size_t copyCount =
std::max<size_t>(count, boundTextureUnits.size() - locationEntry.element);
std::copy(v, v + copyCount, boundTextureUnits.begin() + locationEntry.element);
size_t copyCount = std::max<size_t>(count, boundTextureUnits.size() - samplerLoc.arrayIndex);
std::copy(v, v + copyCount, boundTextureUnits.begin() + samplerLoc.arrayIndex);
}
}
void ProgramGL::setUniform2iv(GLint location, GLsizei count, const GLint *v)
{
mStateManager->useProgram(mProgramID);
mFunctions->uniform2iv(uniLoc(location), count, v);
mFunctions->uniform2iv(location, count, v);
}
void ProgramGL::setUniform3iv(GLint location, GLsizei count, const GLint *v)
{
mStateManager->useProgram(mProgramID);
mFunctions->uniform3iv(uniLoc(location), count, v);
mFunctions->uniform3iv(location, count, v);
}
void ProgramGL::setUniform4iv(GLint location, GLsizei count, const GLint *v)
{
mStateManager->useProgram(mProgramID);
mFunctions->uniform4iv(uniLoc(location), count, v);
mFunctions->uniform4iv(location, count, v);
}
void ProgramGL::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
......@@ -230,88 +255,88 @@ void ProgramGL::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
void ProgramGL::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
{
mStateManager->useProgram(mProgramID);
mFunctions->uniform2uiv(uniLoc(location), count, v);
mFunctions->uniform2uiv(location, count, v);
}
void ProgramGL::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
{
mStateManager->useProgram(mProgramID);
mFunctions->uniform3uiv(uniLoc(location), count, v);
mFunctions->uniform3uiv(location, count, v);
}
void ProgramGL::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
{
mStateManager->useProgram(mProgramID);
mFunctions->uniform4uiv(uniLoc(location), count, v);
mFunctions->uniform4uiv(location, count, v);
}
void ProgramGL::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
{
mStateManager->useProgram(mProgramID);
mFunctions->uniformMatrix2fv(uniLoc(location), count, transpose, value);
mFunctions->uniformMatrix2fv(location, count, transpose, value);
}
void ProgramGL::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
{
mStateManager->useProgram(mProgramID);
mFunctions->uniformMatrix3fv(uniLoc(location), count, transpose, value);
mFunctions->uniformMatrix3fv(location, count, transpose, value);
}
void ProgramGL::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
{
mStateManager->useProgram(mProgramID);
mFunctions->uniformMatrix4fv(uniLoc(location), count, transpose, value);
mFunctions->uniformMatrix4fv(location, count, transpose, value);
}
void ProgramGL::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
{
mStateManager->useProgram(mProgramID);
mFunctions->uniformMatrix2x3fv(uniLoc(location), count, transpose, value);
mFunctions->uniformMatrix2x3fv(location, count, transpose, value);
}
void ProgramGL::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
{
mStateManager->useProgram(mProgramID);
mFunctions->uniformMatrix3x2fv(uniLoc(location), count, transpose, value);
mFunctions->uniformMatrix3x2fv(location, count, transpose, value);
}
void ProgramGL::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
{
mStateManager->useProgram(mProgramID);
mFunctions->uniformMatrix2x4fv(uniLoc(location), count, transpose, value);
mFunctions->uniformMatrix2x4fv(location, count, transpose, value);
}
void ProgramGL::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
{
mStateManager->useProgram(mProgramID);
mFunctions->uniformMatrix4x2fv(uniLoc(location), count, transpose, value);
mFunctions->uniformMatrix4x2fv(location, count, transpose, value);
}
void ProgramGL::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
{
mStateManager->useProgram(mProgramID);
mFunctions->uniformMatrix3x4fv(uniLoc(location), count, transpose, value);
mFunctions->uniformMatrix3x4fv(location, count, transpose, value);
}
void ProgramGL::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
{
mStateManager->useProgram(mProgramID);
mFunctions->uniformMatrix4x3fv(uniLoc(location), count, transpose, value);
mFunctions->uniformMatrix4x3fv(location, count, transpose, value);
}
void ProgramGL::getUniformfv(GLint location, GLfloat *params)
{
mFunctions->getUniformfv(mProgramID, uniLoc(location), params);
mFunctions->getUniformfv(mProgramID, location, params);
}
void ProgramGL::getUniformiv(GLint location, GLint *params)
{
mFunctions->getUniformiv(mProgramID, uniLoc(location), params);
mFunctions->getUniformiv(mProgramID, location, params);
}
void ProgramGL::getUniformuiv(GLint location, GLuint *params)
{
mFunctions->getUniformuiv(mProgramID, uniLoc(location), params);
mFunctions->getUniformuiv(mProgramID, location, params);
}
bool ProgramGL::validateSamplers(gl::InfoLog *infoLog, const gl::Caps &caps)
......@@ -322,9 +347,10 @@ bool ProgramGL::validateSamplers(gl::InfoLog *infoLog, const gl::Caps &caps)
void ProgramGL::reset()
{
mUniformRealLocationMap.clear();
ProgramImpl::reset();
mSamplerUniformMap.clear();
mSamplerBindings.clear();
mUniformIndexToSamplerIndex.clear();
}
GLuint ProgramGL::getProgramID() const
......@@ -337,9 +363,4 @@ const std::vector<SamplerBindingGL> &ProgramGL::getAppliedSamplerUniforms() cons
return mSamplerBindings;
}
void ProgramGL::gatherUniformBlockInfo(std::vector<gl::UniformBlock> * /*uniformBlocks*/,
std::vector<gl::LinkedUniform> * /*uniforms*/)
{
// TODO(jmadill): Gather uniform block layout info, and data sizes.
}
}
......@@ -68,29 +68,26 @@ class ProgramGL : public ProgramImpl
bool validateSamplers(gl::InfoLog *infoLog, const gl::Caps &caps) override;
void gatherUniformBlockInfo(std::vector<gl::UniformBlock> *uniformBlocks,
std::vector<gl::LinkedUniform> *uniforms) override;
void reset() override;
GLuint getProgramID() const;
const std::vector<SamplerBindingGL> &getAppliedSamplerUniforms() const;
private:
void reset();
// Helper function, makes it simpler to type.
GLint uniLoc(GLint glLocation) const { return mUniformRealLocationMap[glLocation]; }
const FunctionsGL *mFunctions;
StateManagerGL *mStateManager;
std::vector<GLint> mUniformRealLocationMap;
// A map from uniform location to index of mSamplerBindings and array index of the uniform
struct SamplerLocation
{
size_t samplerIndex;
size_t arrayIndex;
};
std::map<GLint, SamplerLocation> mSamplerUniformMap;
// An array of the samplers that are used by the program
std::vector<SamplerBindingGL> mSamplerBindings;
// A map from a mData.getUniforms() index to a mSamplerBindings index.
std::vector<size_t> mUniformIndexToSamplerIndex;
GLuint mProgramID;
};
......
......@@ -1096,11 +1096,8 @@ bool ValidateEndQuery(gl::Context *context, GLenum target)
return true;
}
static bool ValidateUniformCommonBase(gl::Context *context,
GLenum targetUniformType,
GLint location,
GLsizei count,
const LinkedUniform **uniformOut)
static bool ValidateUniformCommonBase(gl::Context *context, GLenum targetUniformType,
GLint location, GLsizei count, LinkedUniform **uniformOut)
{
if (count < 0)
{
......@@ -1127,16 +1124,16 @@ static bool ValidateUniformCommonBase(gl::Context *context,
return false;
}
const LinkedUniform &uniform = program->getUniformByLocation(location);
LinkedUniform *uniform = program->getUniformByLocation(location);
// attempting to write an array to a non-array uniform is an INVALID_OPERATION
if (!uniform.isArray() && count > 1)
if (!uniform->isArray() && count > 1)
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
*uniformOut = &uniform;
*uniformOut = uniform;
return true;
}
......@@ -1149,7 +1146,7 @@ bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, G
return false;
}
const LinkedUniform *uniform = nullptr;
LinkedUniform *uniform = NULL;
if (!ValidateUniformCommonBase(context, uniformType, location, count, &uniform))
{
return false;
......@@ -1184,7 +1181,7 @@ bool ValidateUniformMatrix(gl::Context *context, GLenum matrixType, GLint locati
return false;
}
const LinkedUniform *uniform = nullptr;
LinkedUniform *uniform = NULL;
if (!ValidateUniformCommonBase(context, matrixType, location, count, &uniform))
{
return false;
......@@ -1480,7 +1477,7 @@ static bool ValidateDrawBase(Context *context, GLenum mode, GLsizei count, GLsiz
// Uniform buffer validation
for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
{
const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
const gl::UniformBlock *uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
const gl::Buffer *uniformBuffer = state.getIndexedUniformBuffer(blockBinding);
......@@ -1499,7 +1496,7 @@ static bool ValidateDrawBase(Context *context, GLenum mode, GLsizei count, GLsiz
uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
}
if (uniformBufferSize < uniformBlock.dataSize)
if (uniformBufferSize < uniformBlock->dataSize)
{
// undefined behaviour
context->recordError(Error(GL_INVALID_OPERATION, "It is undefined behaviour to use a uniform buffer that is too small."));
......@@ -1899,8 +1896,8 @@ static bool ValidateSizedGetUniform(Context *context, GLuint program, GLint loca
ASSERT(programObject);
// sized queries -- ensure the provided buffer is large enough
const LinkedUniform &uniform = programObject->getUniformByLocation(location);
size_t requiredBytes = VariableExternalSize(uniform.type);
LinkedUniform *uniform = programObject->getUniformByLocation(location);
size_t requiredBytes = VariableExternalSize(uniform->type);
if (static_cast<size_t>(bufSize) < requiredBytes)
{
context->recordError(Error(GL_INVALID_OPERATION));
......
......@@ -140,6 +140,7 @@
'libANGLE/renderer/FramebufferImpl.h',
'libANGLE/renderer/ImageImpl.h',
'libANGLE/renderer/ImplFactory.h',
'libANGLE/renderer/ProgramImpl.cpp',
'libANGLE/renderer/ProgramImpl.h',
'libANGLE/renderer/QueryImpl.h',
'libANGLE/renderer/RenderbufferImpl.h',
......
......@@ -120,12 +120,9 @@
1031 WIN : dEQP-GLES2.functional.uniform_api.random.41 = FAIL
1031 WIN : dEQP-GLES2.functional.uniform_api.random.51 = FAIL
1031 WIN : dEQP-GLES2.functional.uniform_api.random.54 = FAIL
1031 WIN : dEQP-GLES2.functional.uniform_api.random.61 = FAIL
1031 WIN : dEQP-GLES2.functional.uniform_api.random.72 = FAIL
1031 WIN : dEQP-GLES2.functional.uniform_api.random.79 = FAIL
1031 WIN : dEQP-GLES2.functional.uniform_api.random.82 = FAIL
1031 WIN : dEQP-GLES2.functional.uniform_api.random.87 = FAIL
1031 WIN : dEQP-GLES2.functional.uniform_api.random.93 = FAIL
504 WIN : dEQP-GLES2.functional.uniform_api.value.initial.get_uniform.basic_struct.sampler2D_samplerCube_* = FAIL
504 WIN : dEQP-GLES2.functional.uniform_api.value.initial.get_uniform.struct_in_array.sampler2D_samplerCube_* = FAIL
504 WIN : dEQP-GLES2.functional.uniform_api.value.initial.get_uniform.array_in_struct.sampler2D_samplerCube_* = FAIL
......
......@@ -1029,14 +1029,11 @@
1098 WIN : dEQP-GLES3.functional.uniform_api.random.3 = FAIL
1098 WIN : dEQP-GLES3.functional.uniform_api.random.6 = FAIL
1098 WIN : dEQP-GLES3.functional.uniform_api.random.8 = FAIL
1098 WIN : dEQP-GLES3.functional.uniform_api.random.17 = FAIL
1098 WIN : dEQP-GLES3.functional.uniform_api.random.20 = FAIL
1098 WIN : dEQP-GLES3.functional.uniform_api.random.21 = FAIL
1098 WIN : dEQP-GLES3.functional.uniform_api.random.29 = FAIL
1098 WIN : dEQP-GLES3.functional.uniform_api.random.54 = FAIL
1098 WIN : dEQP-GLES3.functional.uniform_api.random.81 = FAIL
1098 WIN : dEQP-GLES3.functional.uniform_api.random.83 = FAIL
1098 WIN : dEQP-GLES3.functional.uniform_api.random.87 = FAIL
1099 WIN : dEQP-GLES3.functional.attribute_location.bind_aliasing.cond_float = FAIL
1099 WIN : dEQP-GLES3.functional.attribute_location.bind_aliasing.max_cond_float = FAIL
1099 WIN : dEQP-GLES3.functional.attribute_location.bind_aliasing.cond_vec2 = FAIL
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment