Commit 729b2c6e by Jiajia Qin Committed by Commit Bot

ES31: Enable shader storage buffer support for OpenGL backend

BUG=angleproject:1951 TEST=angle_end2end_tests:ShaderStorageBuffer Change-Id: I1afc3cd005ad2e595c6ce937fc53e17423f8ec8b Reviewed-on: https://chromium-review.googlesource.com/618132 Commit-Queue: Geoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 47bf2dc5
...@@ -1237,6 +1237,12 @@ void TOutputGLSLBase::declareInterfaceBlockLayout(const TInterfaceBlock *interfa ...@@ -1237,6 +1237,12 @@ void TOutputGLSLBase::declareInterfaceBlockLayout(const TInterfaceBlock *interfa
out << ", "; out << ", ";
if (interfaceBlock->blockBinding() > 0)
{
out << "binding = " << interfaceBlock->blockBinding();
out << ", ";
}
switch (interfaceBlock->matrixPacking()) switch (interfaceBlock->matrixPacking())
{ {
case EmpUnspecified: case EmpUnspecified:
......
...@@ -120,6 +120,7 @@ Compiler::Compiler(rx::GLImplFactory *implFactory, const ContextState &state) ...@@ -120,6 +120,7 @@ Compiler::Compiler(rx::GLImplFactory *implFactory, const ContextState &state)
mResources.MaxAtomicCounterBufferSize = caps.maxAtomicCounterBufferSize; mResources.MaxAtomicCounterBufferSize = caps.maxAtomicCounterBufferSize;
mResources.MaxUniformBufferBindings = caps.maxUniformBufferBindings; mResources.MaxUniformBufferBindings = caps.maxUniformBufferBindings;
mResources.MaxShaderStorageBufferBindings = caps.maxShaderStorageBufferBindings;
// Needed by point size clamping workaround // Needed by point size clamping workaround
mResources.MaxPointSize = caps.maxAliasedPointSize; mResources.MaxPointSize = caps.maxAliasedPointSize;
......
...@@ -90,6 +90,26 @@ void LoadShaderVariableBuffer(BinaryInputStream *stream, ShaderVariableBuffer *v ...@@ -90,6 +90,26 @@ void LoadShaderVariableBuffer(BinaryInputStream *stream, ShaderVariableBuffer *v
} }
} }
void WriteInterfaceBlock(BinaryOutputStream *stream, const InterfaceBlock &block)
{
stream->writeString(block.name);
stream->writeString(block.mappedName);
stream->writeInt(block.isArray);
stream->writeInt(block.arrayElement);
WriteShaderVariableBuffer(stream, block);
}
void LoadInterfaceBlock(BinaryInputStream *stream, InterfaceBlock *block)
{
block->name = stream->readString();
block->mappedName = stream->readString();
block->isArray = stream->readBool();
block->arrayElement = stream->readInt<unsigned int>();
LoadShaderVariableBuffer(stream, block);
}
class HashStream final : angle::NonCopyable class HashStream final : angle::NonCopyable
{ {
public: public:
...@@ -232,18 +252,23 @@ LinkResult MemoryProgramCache::Deserialize(const Context *context, ...@@ -232,18 +252,23 @@ LinkResult MemoryProgramCache::Deserialize(const Context *context,
for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < uniformBlockCount; for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < uniformBlockCount;
++uniformBlockIndex) ++uniformBlockIndex)
{ {
UniformBlock uniformBlock; InterfaceBlock uniformBlock;
stream.readString(&uniformBlock.name); LoadInterfaceBlock(&stream, &uniformBlock);
stream.readString(&uniformBlock.mappedName);
stream.readBool(&uniformBlock.isArray);
stream.readInt(&uniformBlock.arrayElement);
LoadShaderVariableBuffer(&stream, &uniformBlock);
state->mUniformBlocks.push_back(uniformBlock); state->mUniformBlocks.push_back(uniformBlock);
state->mActiveUniformBlockBindings.set(uniformBlockIndex, uniformBlock.binding != 0); state->mActiveUniformBlockBindings.set(uniformBlockIndex, uniformBlock.binding != 0);
} }
unsigned int shaderStorageBlockCount = stream.readInt<unsigned int>();
ASSERT(state->mShaderStorageBlocks.empty());
for (unsigned int shaderStorageBlockIndex = 0;
shaderStorageBlockIndex < shaderStorageBlockCount; ++shaderStorageBlockIndex)
{
InterfaceBlock shaderStorageBlock;
LoadInterfaceBlock(&stream, &shaderStorageBlock);
state->mShaderStorageBlocks.push_back(shaderStorageBlock);
}
unsigned int atomicCounterBufferCount = stream.readInt<unsigned int>(); unsigned int atomicCounterBufferCount = stream.readInt<unsigned int>();
ASSERT(state->mAtomicCounterBuffers.empty()); ASSERT(state->mAtomicCounterBuffers.empty());
for (unsigned int bufferIndex = 0; bufferIndex < atomicCounterBufferCount; ++bufferIndex) for (unsigned int bufferIndex = 0; bufferIndex < atomicCounterBufferCount; ++bufferIndex)
...@@ -412,14 +437,15 @@ void MemoryProgramCache::Serialize(const Context *context, ...@@ -412,14 +437,15 @@ void MemoryProgramCache::Serialize(const Context *context,
} }
stream.writeInt(state.getUniformBlocks().size()); stream.writeInt(state.getUniformBlocks().size());
for (const UniformBlock &uniformBlock : state.getUniformBlocks()) for (const InterfaceBlock &uniformBlock : state.getUniformBlocks())
{ {
stream.writeString(uniformBlock.name); WriteInterfaceBlock(&stream, uniformBlock);
stream.writeString(uniformBlock.mappedName); }
stream.writeInt(uniformBlock.isArray);
stream.writeInt(uniformBlock.arrayElement);
WriteShaderVariableBuffer(&stream, uniformBlock); stream.writeInt(state.getShaderStorageBlocks().size());
for (const InterfaceBlock &shaderStorageBlock : state.getShaderStorageBlocks())
{
WriteInterfaceBlock(&stream, shaderStorageBlock);
} }
stream.writeInt(state.mAtomicCounterBuffers.size()); stream.writeInt(state.mAtomicCounterBuffers.size());
......
...@@ -193,6 +193,27 @@ bool IncludeSameArrayElement(const std::set<std::string> &nameSet, const std::st ...@@ -193,6 +193,27 @@ bool IncludeSameArrayElement(const std::set<std::string> &nameSet, const std::st
return false; return false;
} }
bool validateInterfaceBlocksCount(GLuint maxInterfaceBlocks,
const std::vector<sh::InterfaceBlock> &interfaceBlocks,
const std::string &errorMessage,
InfoLog &infoLog)
{
GLuint blockCount = 0;
for (const sh::InterfaceBlock &block : interfaceBlocks)
{
if (block.staticUse || block.layout != sh::BLOCKLAYOUT_PACKED)
{
blockCount += (block.arraySize ? block.arraySize : 1);
if (blockCount > maxInterfaceBlocks)
{
infoLog << errorMessage << maxInterfaceBlocks << ")";
return false;
}
}
}
return true;
}
} // anonymous namespace } // anonymous namespace
const char *const g_fakepath = "C:\\fakepath"; const char *const g_fakepath = "C:\\fakepath";
...@@ -693,7 +714,7 @@ Error Program::link(const gl::Context *context) ...@@ -693,7 +714,7 @@ Error Program::link(const gl::Context *context)
return NoError(); return NoError();
} }
if (!linkUniformBlocks(context, mInfoLog)) if (!linkInterfaceBlocks(context, mInfoLog))
{ {
return NoError(); return NoError();
} }
...@@ -740,7 +761,7 @@ Error Program::link(const gl::Context *context) ...@@ -740,7 +761,7 @@ Error Program::link(const gl::Context *context)
return NoError(); return NoError();
} }
if (!linkUniformBlocks(context, mInfoLog)) if (!linkInterfaceBlocks(context, mInfoLog))
{ {
return NoError(); return NoError();
} }
...@@ -1633,13 +1654,18 @@ GLuint Program::getActiveUniformBlockCount() const ...@@ -1633,13 +1654,18 @@ GLuint Program::getActiveUniformBlockCount() const
return static_cast<GLuint>(mState.mUniformBlocks.size()); return static_cast<GLuint>(mState.mUniformBlocks.size());
} }
GLuint Program::getActiveShaderStorageBlockCount() const
{
return static_cast<GLuint>(mState.mShaderStorageBlocks.size());
}
void Program::getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) const void Program::getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) const
{ {
ASSERT( ASSERT(
uniformBlockIndex < uniformBlockIndex <
mState.mUniformBlocks.size()); // index must be smaller than getActiveUniformBlockCount() mState.mUniformBlocks.size()); // index must be smaller than getActiveUniformBlockCount()
const UniformBlock &uniformBlock = mState.mUniformBlocks[uniformBlockIndex]; const InterfaceBlock &uniformBlock = mState.mUniformBlocks[uniformBlockIndex];
if (bufSize > 0) if (bufSize > 0)
{ {
...@@ -1662,7 +1688,7 @@ GLint Program::getActiveUniformBlockMaxLength() const ...@@ -1662,7 +1688,7 @@ GLint Program::getActiveUniformBlockMaxLength() const
unsigned int numUniformBlocks = static_cast<unsigned int>(mState.mUniformBlocks.size()); unsigned int numUniformBlocks = static_cast<unsigned int>(mState.mUniformBlocks.size());
for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < numUniformBlocks; uniformBlockIndex++) for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < numUniformBlocks; uniformBlockIndex++)
{ {
const UniformBlock &uniformBlock = mState.mUniformBlocks[uniformBlockIndex]; const InterfaceBlock &uniformBlock = mState.mUniformBlocks[uniformBlockIndex];
if (!uniformBlock.name.empty()) if (!uniformBlock.name.empty())
{ {
int length = static_cast<int>(uniformBlock.nameWithArrayIndex().length()); int length = static_cast<int>(uniformBlock.nameWithArrayIndex().length());
...@@ -1682,7 +1708,7 @@ GLuint Program::getUniformBlockIndex(const std::string &name) const ...@@ -1682,7 +1708,7 @@ GLuint Program::getUniformBlockIndex(const std::string &name) const
unsigned int numUniformBlocks = static_cast<unsigned int>(mState.mUniformBlocks.size()); unsigned int numUniformBlocks = static_cast<unsigned int>(mState.mUniformBlocks.size());
for (unsigned int blockIndex = 0; blockIndex < numUniformBlocks; blockIndex++) for (unsigned int blockIndex = 0; blockIndex < numUniformBlocks; blockIndex++)
{ {
const UniformBlock &uniformBlock = mState.mUniformBlocks[blockIndex]; const InterfaceBlock &uniformBlock = mState.mUniformBlocks[blockIndex];
if (uniformBlock.name == baseName) if (uniformBlock.name == baseName)
{ {
const bool arrayElementZero = const bool arrayElementZero =
...@@ -1698,7 +1724,7 @@ GLuint Program::getUniformBlockIndex(const std::string &name) const ...@@ -1698,7 +1724,7 @@ GLuint Program::getUniformBlockIndex(const std::string &name) const
return GL_INVALID_INDEX; return GL_INVALID_INDEX;
} }
const UniformBlock &Program::getUniformBlockByIndex(GLuint index) const const InterfaceBlock &Program::getUniformBlockByIndex(GLuint index) const
{ {
ASSERT(index < static_cast<GLuint>(mState.mUniformBlocks.size())); ASSERT(index < static_cast<GLuint>(mState.mUniformBlocks.size()));
return mState.mUniformBlocks[index]; return mState.mUniformBlocks[index];
...@@ -1716,6 +1742,11 @@ GLuint Program::getUniformBlockBinding(GLuint uniformBlockIndex) const ...@@ -1716,6 +1742,11 @@ GLuint Program::getUniformBlockBinding(GLuint uniformBlockIndex) const
return mState.getUniformBlockBinding(uniformBlockIndex); return mState.getUniformBlockBinding(uniformBlockIndex);
} }
GLuint Program::getShaderStorageBlockBinding(GLuint shaderStorageBlockIndex) const
{
return mState.getShaderStorageBlockBinding(shaderStorageBlockIndex);
}
void Program::setTransformFeedbackVaryings(GLsizei count, const GLchar *const *varyings, GLenum bufferMode) void Program::setTransformFeedbackVaryings(GLsizei count, const GLchar *const *varyings, GLenum bufferMode)
{ {
mState.mTransformFeedbackVaryingNames.resize(count); mState.mTransformFeedbackVaryingNames.resize(count);
...@@ -2110,26 +2141,6 @@ bool Program::linkAttributes(const Context *context, InfoLog &infoLog) ...@@ -2110,26 +2141,6 @@ bool Program::linkAttributes(const Context *context, InfoLog &infoLog)
return true; return true;
} }
bool Program::validateUniformBlocksCount(GLuint maxUniformBlocks,
const std::vector<sh::InterfaceBlock> &intefaceBlocks,
const std::string &errorMessage,
InfoLog &infoLog) const
{
GLuint blockCount = 0;
for (const sh::InterfaceBlock &block : intefaceBlocks)
{
if (block.staticUse || block.layout != sh::BLOCKLAYOUT_PACKED)
{
if (++blockCount > maxUniformBlocks)
{
infoLog << errorMessage << maxUniformBlocks << ")";
return false;
}
}
}
return true;
}
bool Program::validateVertexAndFragmentInterfaceBlocks( bool Program::validateVertexAndFragmentInterfaceBlocks(
const std::vector<sh::InterfaceBlock> &vertexInterfaceBlocks, const std::vector<sh::InterfaceBlock> &vertexInterfaceBlocks,
const std::vector<sh::InterfaceBlock> &fragmentInterfaceBlocks, const std::vector<sh::InterfaceBlock> &fragmentInterfaceBlocks,
...@@ -2137,18 +2148,18 @@ bool Program::validateVertexAndFragmentInterfaceBlocks( ...@@ -2137,18 +2148,18 @@ bool Program::validateVertexAndFragmentInterfaceBlocks(
bool webglCompatibility) const bool webglCompatibility) const
{ {
// Check that interface blocks defined in the vertex and fragment shaders are identical // Check that interface blocks defined in the vertex and fragment shaders are identical
typedef std::map<std::string, const sh::InterfaceBlock *> UniformBlockMap; typedef std::map<std::string, const sh::InterfaceBlock *> InterfaceBlockMap;
UniformBlockMap linkedUniformBlocks; InterfaceBlockMap linkedInterfaceBlocks;
for (const sh::InterfaceBlock &vertexInterfaceBlock : vertexInterfaceBlocks) for (const sh::InterfaceBlock &vertexInterfaceBlock : vertexInterfaceBlocks)
{ {
linkedUniformBlocks[vertexInterfaceBlock.name] = &vertexInterfaceBlock; linkedInterfaceBlocks[vertexInterfaceBlock.name] = &vertexInterfaceBlock;
} }
for (const sh::InterfaceBlock &fragmentInterfaceBlock : fragmentInterfaceBlocks) for (const sh::InterfaceBlock &fragmentInterfaceBlock : fragmentInterfaceBlocks)
{ {
auto entry = linkedUniformBlocks.find(fragmentInterfaceBlock.name); auto entry = linkedInterfaceBlocks.find(fragmentInterfaceBlock.name);
if (entry != linkedUniformBlocks.end()) if (entry != linkedInterfaceBlocks.end())
{ {
const sh::InterfaceBlock &vertexInterfaceBlock = *entry->second; const sh::InterfaceBlock &vertexInterfaceBlock = *entry->second;
if (!areMatchingInterfaceBlocks(infoLog, vertexInterfaceBlock, fragmentInterfaceBlock, if (!areMatchingInterfaceBlocks(infoLog, vertexInterfaceBlock, fragmentInterfaceBlock,
...@@ -2157,43 +2168,55 @@ bool Program::validateVertexAndFragmentInterfaceBlocks( ...@@ -2157,43 +2168,55 @@ bool Program::validateVertexAndFragmentInterfaceBlocks(
return false; return false;
} }
} }
// TODO(jiajia.qin@intel.com): Add
// MAX_COMBINED_UNIFORM_BLOCKS/MAX_COMBINED_SHADER_STORAGE_BLOCKS validation.
} }
return true; return true;
} }
bool Program::linkUniformBlocks(const Context *context, InfoLog &infoLog) bool Program::linkInterfaceBlocks(const Context *context, InfoLog &infoLog)
{ {
const auto &caps = context->getCaps(); const auto &caps = context->getCaps();
if (mState.mAttachedComputeShader) if (mState.mAttachedComputeShader)
{ {
Shader &computeShader = *mState.mAttachedComputeShader; Shader &computeShader = *mState.mAttachedComputeShader;
const auto &computeInterfaceBlocks = computeShader.getUniformBlocks(context); const auto &computeUniformBlocks = computeShader.getUniformBlocks(context);
if (!validateUniformBlocksCount( if (!validateInterfaceBlocksCount(
caps.maxComputeUniformBlocks, computeInterfaceBlocks, caps.maxComputeUniformBlocks, computeUniformBlocks,
"Compute shader uniform block count exceeds GL_MAX_COMPUTE_UNIFORM_BLOCKS (", "Compute shader uniform block count exceeds GL_MAX_COMPUTE_UNIFORM_BLOCKS (",
infoLog)) infoLog))
{ {
return false; return false;
} }
const auto &computeShaderStorageBlocks = computeShader.getShaderStorageBlocks(context);
if (!validateInterfaceBlocksCount(caps.maxComputeShaderStorageBlocks,
computeShaderStorageBlocks,
"Compute shader shader storage block count exceeds "
"GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS (",
infoLog))
{
return false;
}
return true; return true;
} }
Shader &vertexShader = *mState.mAttachedVertexShader; Shader &vertexShader = *mState.mAttachedVertexShader;
Shader &fragmentShader = *mState.mAttachedFragmentShader; Shader &fragmentShader = *mState.mAttachedFragmentShader;
const auto &vertexInterfaceBlocks = vertexShader.getUniformBlocks(context); const auto &vertexUniformBlocks = vertexShader.getUniformBlocks(context);
const auto &fragmentInterfaceBlocks = fragmentShader.getUniformBlocks(context); const auto &fragmentUniformBlocks = fragmentShader.getUniformBlocks(context);
if (!validateUniformBlocksCount( if (!validateInterfaceBlocksCount(
caps.maxVertexUniformBlocks, vertexInterfaceBlocks, caps.maxVertexUniformBlocks, vertexUniformBlocks,
"Vertex shader uniform block count exceeds GL_MAX_VERTEX_UNIFORM_BLOCKS (", infoLog)) "Vertex shader uniform block count exceeds GL_MAX_VERTEX_UNIFORM_BLOCKS (", infoLog))
{ {
return false; return false;
} }
if (!validateUniformBlocksCount( if (!validateInterfaceBlocksCount(
caps.maxFragmentUniformBlocks, fragmentInterfaceBlocks, caps.maxFragmentUniformBlocks, fragmentUniformBlocks,
"Fragment shader uniform block count exceeds GL_MAX_FRAGMENT_UNIFORM_BLOCKS (", "Fragment shader uniform block count exceeds GL_MAX_FRAGMENT_UNIFORM_BLOCKS (",
infoLog)) infoLog))
{ {
...@@ -2202,12 +2225,42 @@ bool Program::linkUniformBlocks(const Context *context, InfoLog &infoLog) ...@@ -2202,12 +2225,42 @@ bool Program::linkUniformBlocks(const Context *context, InfoLog &infoLog)
} }
bool webglCompatibility = context->getExtensions().webglCompatibility; bool webglCompatibility = context->getExtensions().webglCompatibility;
if (!validateVertexAndFragmentInterfaceBlocks(vertexInterfaceBlocks, fragmentInterfaceBlocks, if (!validateVertexAndFragmentInterfaceBlocks(vertexUniformBlocks, fragmentUniformBlocks,
infoLog, webglCompatibility)) infoLog, webglCompatibility))
{ {
return false; return false;
} }
if (context->getClientVersion() >= Version(3, 1))
{
const auto &vertexShaderStorageBlocks = vertexShader.getShaderStorageBlocks(context);
const auto &fragmentShaderStorageBlocks = fragmentShader.getShaderStorageBlocks(context);
if (!validateInterfaceBlocksCount(caps.maxVertexShaderStorageBlocks,
vertexShaderStorageBlocks,
"Vertex shader shader storage block count exceeds "
"GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS (",
infoLog))
{
return false;
}
if (!validateInterfaceBlocksCount(caps.maxFragmentShaderStorageBlocks,
fragmentShaderStorageBlocks,
"Fragment shader shader storage block count exceeds "
"GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS (",
infoLog))
{
return false;
}
if (!validateVertexAndFragmentInterfaceBlocks(vertexShaderStorageBlocks,
fragmentShaderStorageBlocks, infoLog,
webglCompatibility))
{
return false;
}
}
return true; return true;
} }
...@@ -2741,54 +2794,36 @@ void Program::gatherAtomicCounterBuffers() ...@@ -2741,54 +2794,36 @@ void Program::gatherAtomicCounterBuffers()
// TODO(jie.a.chen@intel.com): Get the actual BUFFER_DATA_SIZE from backend for each buffer. // TODO(jie.a.chen@intel.com): Get the actual BUFFER_DATA_SIZE from backend for each buffer.
} }
void Program::gatherInterfaceBlockInfo(const Context *context) void Program::gatherComputeBlockInfo(const std::vector<sh::InterfaceBlock> &computeBlocks)
{ {
ASSERT(mState.mUniformBlocks.empty()); for (const sh::InterfaceBlock &computeBlock : computeBlocks)
if (mState.mAttachedComputeShader)
{ {
Shader *computeShader = mState.getAttachedComputeShader();
for (const sh::InterfaceBlock &computeBlock : computeShader->getUniformBlocks(context)) // Only 'packed' blocks are allowed to be considered inactive.
{ if (!computeBlock.staticUse && computeBlock.layout == sh::BLOCKLAYOUT_PACKED)
continue;
// Only 'packed' blocks are allowed to be considered inactive.
if (!computeBlock.staticUse && computeBlock.layout == sh::BLOCKLAYOUT_PACKED)
continue;
for (UniformBlock &block : mState.mUniformBlocks)
{
if (block.name == computeBlock.name)
{
block.computeStaticUse = computeBlock.staticUse;
}
}
defineUniformBlock(computeBlock, GL_COMPUTE_SHADER); defineInterfaceBlock(computeBlock, GL_COMPUTE_SHADER);
}
return;
} }
}
void Program::gatherVertexAndFragmentBlockInfo(
const std::vector<sh::InterfaceBlock> &vertexInterfaceBlocks,
const std::vector<sh::InterfaceBlock> &fragmentInterfaceBlocks)
{
std::set<std::string> visitedList; std::set<std::string> visitedList;
Shader *vertexShader = mState.getAttachedVertexShader(); for (const sh::InterfaceBlock &vertexBlock : vertexInterfaceBlocks)
for (const sh::InterfaceBlock &vertexBlock : vertexShader->getUniformBlocks(context))
{ {
// Only 'packed' blocks are allowed to be considered inactive. // Only 'packed' blocks are allowed to be considered inactive.
if (!vertexBlock.staticUse && vertexBlock.layout == sh::BLOCKLAYOUT_PACKED) if (!vertexBlock.staticUse && vertexBlock.layout == sh::BLOCKLAYOUT_PACKED)
continue; continue;
if (visitedList.count(vertexBlock.name) > 0) defineInterfaceBlock(vertexBlock, GL_VERTEX_SHADER);
continue;
defineUniformBlock(vertexBlock, GL_VERTEX_SHADER);
visitedList.insert(vertexBlock.name); visitedList.insert(vertexBlock.name);
} }
Shader *fragmentShader = mState.getAttachedFragmentShader(); for (const sh::InterfaceBlock &fragmentBlock : fragmentInterfaceBlocks)
for (const sh::InterfaceBlock &fragmentBlock : fragmentShader->getUniformBlocks(context))
{ {
// Only 'packed' blocks are allowed to be considered inactive. // Only 'packed' blocks are allowed to be considered inactive.
if (!fragmentBlock.staticUse && fragmentBlock.layout == sh::BLOCKLAYOUT_PACKED) if (!fragmentBlock.staticUse && fragmentBlock.layout == sh::BLOCKLAYOUT_PACKED)
...@@ -2796,24 +2831,65 @@ void Program::gatherInterfaceBlockInfo(const Context *context) ...@@ -2796,24 +2831,65 @@ void Program::gatherInterfaceBlockInfo(const Context *context)
if (visitedList.count(fragmentBlock.name) > 0) if (visitedList.count(fragmentBlock.name) > 0)
{ {
for (UniformBlock &block : mState.mUniformBlocks) if (fragmentBlock.blockType == sh::BlockType::BLOCK_UNIFORM)
{
for (InterfaceBlock &block : mState.mUniformBlocks)
{
if (block.name == fragmentBlock.name)
{
block.fragmentStaticUse = fragmentBlock.staticUse;
}
}
}
else
{ {
if (block.name == fragmentBlock.name) ASSERT(fragmentBlock.blockType == sh::BlockType::BLOCK_BUFFER);
for (InterfaceBlock &block : mState.mShaderStorageBlocks)
{ {
block.fragmentStaticUse = fragmentBlock.staticUse; if (block.name == fragmentBlock.name)
{
block.fragmentStaticUse = fragmentBlock.staticUse;
}
} }
} }
continue; continue;
} }
defineUniformBlock(fragmentBlock, GL_FRAGMENT_SHADER); defineInterfaceBlock(fragmentBlock, GL_FRAGMENT_SHADER);
visitedList.insert(fragmentBlock.name); visitedList.insert(fragmentBlock.name);
} }
}
void Program::gatherInterfaceBlockInfo(const Context *context)
{
ASSERT(mState.mUniformBlocks.empty());
ASSERT(mState.mShaderStorageBlocks.empty());
if (mState.mAttachedComputeShader)
{
Shader *computeShader = mState.getAttachedComputeShader();
gatherComputeBlockInfo(computeShader->getUniformBlocks(context));
gatherComputeBlockInfo(computeShader->getShaderStorageBlocks(context));
return;
}
Shader *vertexShader = mState.getAttachedVertexShader();
Shader *fragmentShader = mState.getAttachedFragmentShader();
gatherVertexAndFragmentBlockInfo(vertexShader->getUniformBlocks(context),
fragmentShader->getUniformBlocks(context));
if (context->getClientVersion() >= Version(3, 1))
{
gatherVertexAndFragmentBlockInfo(vertexShader->getShaderStorageBlocks(context),
fragmentShader->getShaderStorageBlocks(context));
}
// Set initial bindings from shader. // Set initial bindings from shader.
for (unsigned int blockIndex = 0; blockIndex < mState.mUniformBlocks.size(); blockIndex++) for (unsigned int blockIndex = 0; blockIndex < mState.mUniformBlocks.size(); blockIndex++)
{ {
UniformBlock &uniformBlock = mState.mUniformBlocks[blockIndex]; InterfaceBlock &uniformBlock = mState.mUniformBlocks[blockIndex];
bindUniformBlock(blockIndex, uniformBlock.binding); bindUniformBlock(blockIndex, uniformBlock.binding);
} }
} }
...@@ -2863,23 +2939,31 @@ void Program::defineUniformBlockMembers(const std::vector<VarT> &fields, ...@@ -2863,23 +2939,31 @@ void Program::defineUniformBlockMembers(const std::vector<VarT> &fields,
} }
} }
void Program::defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, GLenum shaderType) void Program::defineInterfaceBlock(const sh::InterfaceBlock &interfaceBlock, GLenum shaderType)
{ {
int blockIndex = static_cast<int>(mState.mUniformBlocks.size());
size_t blockSize = 0; size_t blockSize = 0;
std::vector<unsigned int> blockIndexes;
// Track the first and last uniform index to determine the range of active uniforms in the if (interfaceBlock.blockType == sh::BlockType::BLOCK_UNIFORM)
// block. {
size_t firstBlockUniformIndex = mState.mUniforms.size(); int blockIndex = static_cast<int>(mState.mUniformBlocks.size());
defineUniformBlockMembers(interfaceBlock.fields, interfaceBlock.fieldPrefix(), // Track the first and last uniform index to determine the range of active uniforms in the
interfaceBlock.fieldMappedPrefix(), blockIndex); // block.
size_t lastBlockUniformIndex = mState.mUniforms.size(); size_t firstBlockUniformIndex = mState.mUniforms.size();
defineUniformBlockMembers(interfaceBlock.fields, interfaceBlock.fieldPrefix(),
interfaceBlock.fieldMappedPrefix(), blockIndex);
size_t lastBlockUniformIndex = mState.mUniforms.size();
std::vector<unsigned int> blockUniformIndexes; for (size_t blockUniformIndex = firstBlockUniformIndex;
for (size_t blockUniformIndex = firstBlockUniformIndex; blockUniformIndex < lastBlockUniformIndex; ++blockUniformIndex)
blockUniformIndex < lastBlockUniformIndex; ++blockUniformIndex) {
blockIndexes.push_back(static_cast<unsigned int>(blockUniformIndex));
}
}
else
{ {
blockUniformIndexes.push_back(static_cast<unsigned int>(blockUniformIndex)); // TODO(jiajia.qin@intel.com) : Add buffer variables support and calculate the block index.
ASSERT(interfaceBlock.blockType == sh::BlockType::BLOCK_BUFFER);
} }
// ESSL 3.10 section 4.4.4 page 58: // ESSL 3.10 section 4.4.4 page 58:
// Any uniform or shader storage block declared without a binding qualifier is initially // Any uniform or shader storage block declared without a binding qualifier is initially
...@@ -2889,16 +2973,22 @@ void Program::defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, GLenu ...@@ -2889,16 +2973,22 @@ void Program::defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, GLenu
{ {
for (unsigned int arrayElement = 0; arrayElement < interfaceBlock.arraySize; ++arrayElement) for (unsigned int arrayElement = 0; arrayElement < interfaceBlock.arraySize; ++arrayElement)
{ {
// Don't define this block at all if it's not active in the implementation. // TODO(jiajia.qin@intel.com) : use GetProgramResourceiv to calculate BUFFER_DATA_SIZE
if (!mProgram->getUniformBlockSize( // of UniformBlock and ShaderStorageBlock.
interfaceBlock.name + ArrayString(arrayElement), if (interfaceBlock.blockType == sh::BlockType::BLOCK_UNIFORM)
interfaceBlock.mappedName + ArrayString(arrayElement), &blockSize))
{ {
continue; // Don't define this block at all if it's not active in the implementation.
if (!mProgram->getUniformBlockSize(
interfaceBlock.name + ArrayString(arrayElement),
interfaceBlock.mappedName + ArrayString(arrayElement), &blockSize))
{
continue;
}
} }
UniformBlock block(interfaceBlock.name, interfaceBlock.mappedName, true, arrayElement,
blockBinding + arrayElement); InterfaceBlock block(interfaceBlock.name, interfaceBlock.mappedName, true, arrayElement,
block.memberIndexes = blockUniformIndexes; blockBinding + arrayElement);
block.memberIndexes = blockIndexes;
switch (shaderType) switch (shaderType)
{ {
...@@ -2921,22 +3011,37 @@ void Program::defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, GLenu ...@@ -2921,22 +3011,37 @@ void Program::defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, GLenu
UNREACHABLE(); UNREACHABLE();
} }
// Since all block elements in an array share the same active uniforms, they will all be // Since all block elements in an array share the same active interface blocks, they
// active once any uniform member is used. So, since interfaceBlock.name[0] was active, // will all be active once any block member is used. So, since interfaceBlock.name[0]
// here we will add every block element in the array. // was active, here we will add every block element in the array.
block.dataSize = static_cast<unsigned int>(blockSize); block.dataSize = static_cast<unsigned int>(blockSize);
mState.mUniformBlocks.push_back(block); if (interfaceBlock.blockType == sh::BlockType::BLOCK_UNIFORM)
{
mState.mUniformBlocks.push_back(block);
}
else
{
ASSERT(interfaceBlock.blockType == sh::BlockType::BLOCK_BUFFER);
mState.mShaderStorageBlocks.push_back(block);
}
} }
} }
else else
{ {
if (!mProgram->getUniformBlockSize(interfaceBlock.name, interfaceBlock.mappedName, // TODO(jiajia.qin@intel.com) : use GetProgramResourceiv to calculate BUFFER_DATA_SIZE
&blockSize)) // of UniformBlock and ShaderStorageBlock.
if (interfaceBlock.blockType == sh::BlockType::BLOCK_UNIFORM)
{ {
return; if (!mProgram->getUniformBlockSize(interfaceBlock.name, interfaceBlock.mappedName,
&blockSize))
{
return;
}
} }
UniformBlock block(interfaceBlock.name, interfaceBlock.mappedName, false, 0, blockBinding);
block.memberIndexes = blockUniformIndexes; InterfaceBlock block(interfaceBlock.name, interfaceBlock.mappedName, false, 0,
blockBinding);
block.memberIndexes = blockIndexes;
switch (shaderType) switch (shaderType)
{ {
...@@ -2960,7 +3065,15 @@ void Program::defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, GLenu ...@@ -2960,7 +3065,15 @@ void Program::defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, GLenu
} }
block.dataSize = static_cast<unsigned int>(blockSize); block.dataSize = static_cast<unsigned int>(blockSize);
mState.mUniformBlocks.push_back(block); if (interfaceBlock.blockType == sh::BlockType::BLOCK_UNIFORM)
{
mState.mUniformBlocks.push_back(block);
}
else
{
ASSERT(interfaceBlock.blockType == sh::BlockType::BLOCK_BUFFER);
mState.mShaderStorageBlocks.push_back(block);
}
} }
} }
......
...@@ -246,6 +246,11 @@ class ProgramState final : angle::NonCopyable ...@@ -246,6 +246,11 @@ class ProgramState final : angle::NonCopyable
ASSERT(uniformBlockIndex < mUniformBlocks.size()); ASSERT(uniformBlockIndex < mUniformBlocks.size());
return mUniformBlocks[uniformBlockIndex].binding; return mUniformBlocks[uniformBlockIndex].binding;
} }
GLuint getShaderStorageBlockBinding(GLuint blockIndex) const
{
ASSERT(blockIndex < mShaderStorageBlocks.size());
return mShaderStorageBlocks[blockIndex].binding;
}
const UniformBlockBindingMask &getActiveUniformBlockBindingsMask() const const UniformBlockBindingMask &getActiveUniformBlockBindingsMask() const
{ {
return mActiveUniformBlockBindings; return mActiveUniformBlockBindings;
...@@ -260,7 +265,11 @@ class ProgramState final : angle::NonCopyable ...@@ -260,7 +265,11 @@ class ProgramState final : angle::NonCopyable
const std::map<int, VariableLocation> &getOutputLocations() const { return mOutputLocations; } const std::map<int, VariableLocation> &getOutputLocations() const { return mOutputLocations; }
const std::vector<LinkedUniform> &getUniforms() const { return mUniforms; } const std::vector<LinkedUniform> &getUniforms() const { return mUniforms; }
const std::vector<VariableLocation> &getUniformLocations() const { return mUniformLocations; } const std::vector<VariableLocation> &getUniformLocations() const { return mUniformLocations; }
const std::vector<UniformBlock> &getUniformBlocks() const { return mUniformBlocks; } const std::vector<InterfaceBlock> &getUniformBlocks() const { return mUniformBlocks; }
const std::vector<InterfaceBlock> &getShaderStorageBlocks() const
{
return mShaderStorageBlocks;
}
const std::vector<SamplerBinding> &getSamplerBindings() const { return mSamplerBindings; } const std::vector<SamplerBinding> &getSamplerBindings() const { return mSamplerBindings; }
const std::vector<ImageBinding> &getImageBindings() const { return mImageBindings; } const std::vector<ImageBinding> &getImageBindings() const { return mImageBindings; }
const sh::WorkGroupSize &getComputeShaderLocalSize() const { return mComputeShaderLocalSize; } const sh::WorkGroupSize &getComputeShaderLocalSize() const { return mComputeShaderLocalSize; }
...@@ -319,7 +328,8 @@ class ProgramState final : angle::NonCopyable ...@@ -319,7 +328,8 @@ class ProgramState final : angle::NonCopyable
// This makes opaque uniform validation easier, since we don't need a separate list. // This makes opaque uniform validation easier, since we don't need a separate list.
std::vector<LinkedUniform> mUniforms; std::vector<LinkedUniform> mUniforms;
std::vector<VariableLocation> mUniformLocations; std::vector<VariableLocation> mUniformLocations;
std::vector<UniformBlock> mUniformBlocks; std::vector<InterfaceBlock> mUniformBlocks;
std::vector<InterfaceBlock> mShaderStorageBlocks;
std::vector<AtomicCounterBuffer> mAtomicCounterBuffers; std::vector<AtomicCounterBuffer> mAtomicCounterBuffers;
RangeUI mSamplerUniformRange; RangeUI mSamplerUniformRange;
RangeUI mImageUniformRange; RangeUI mImageUniformRange;
...@@ -474,14 +484,16 @@ class Program final : angle::NonCopyable, public LabeledObject ...@@ -474,14 +484,16 @@ class Program final : angle::NonCopyable, public LabeledObject
void getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) const; void getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) const;
GLuint getActiveUniformBlockCount() const; GLuint getActiveUniformBlockCount() const;
GLuint getActiveShaderStorageBlockCount() const;
GLint getActiveUniformBlockMaxLength() const; GLint getActiveUniformBlockMaxLength() const;
GLuint getUniformBlockIndex(const std::string &name) const; GLuint getUniformBlockIndex(const std::string &name) const;
void bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding); void bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding);
GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const; GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const;
GLuint getShaderStorageBlockBinding(GLuint shaderStorageBlockIndex) const;
const UniformBlock &getUniformBlockByIndex(GLuint index) const; const InterfaceBlock &getUniformBlockByIndex(GLuint index) const;
void setTransformFeedbackVaryings(GLsizei count, const GLchar *const *varyings, GLenum bufferMode); 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; void getTransformFeedbackVarying(GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name) const;
...@@ -570,16 +582,12 @@ class Program final : angle::NonCopyable, public LabeledObject ...@@ -570,16 +582,12 @@ class Program final : angle::NonCopyable, public LabeledObject
void unlink(); void unlink();
bool linkAttributes(const Context *context, InfoLog &infoLog); bool linkAttributes(const Context *context, InfoLog &infoLog);
bool validateUniformBlocksCount(GLuint maxUniformBlocks,
const std::vector<sh::InterfaceBlock> &block,
const std::string &errorMessage,
InfoLog &infoLog) const;
bool validateVertexAndFragmentInterfaceBlocks( bool validateVertexAndFragmentInterfaceBlocks(
const std::vector<sh::InterfaceBlock> &vertexInterfaceBlocks, const std::vector<sh::InterfaceBlock> &vertexInterfaceBlocks,
const std::vector<sh::InterfaceBlock> &fragmentInterfaceBlocks, const std::vector<sh::InterfaceBlock> &fragmentInterfaceBlocks,
InfoLog &infoLog, InfoLog &infoLog,
bool webglCompatibility) const; bool webglCompatibility) const;
bool linkUniformBlocks(const Context *context, InfoLog &infoLog); bool linkInterfaceBlocks(const Context *context, InfoLog &infoLog);
bool linkVaryings(const Context *context, InfoLog &infoLog) const; bool linkVaryings(const Context *context, InfoLog &infoLog) const;
bool linkUniforms(const Context *context, bool linkUniforms(const Context *context,
...@@ -614,6 +622,10 @@ class Program final : angle::NonCopyable, public LabeledObject ...@@ -614,6 +622,10 @@ class Program final : angle::NonCopyable, public LabeledObject
void setUniformValuesFromBindingQualifiers(); void setUniformValuesFromBindingQualifiers();
void gatherAtomicCounterBuffers(); void gatherAtomicCounterBuffers();
void gatherComputeBlockInfo(const std::vector<sh::InterfaceBlock> &computeBlocks);
void gatherVertexAndFragmentBlockInfo(
const std::vector<sh::InterfaceBlock> &vertexInterfaceBlocks,
const std::vector<sh::InterfaceBlock> &fragmentInterfaceBlocks);
void gatherInterfaceBlockInfo(const Context *context); void gatherInterfaceBlockInfo(const Context *context);
template <typename VarT> template <typename VarT>
void defineUniformBlockMembers(const std::vector<VarT> &fields, void defineUniformBlockMembers(const std::vector<VarT> &fields,
...@@ -621,7 +633,7 @@ class Program final : angle::NonCopyable, public LabeledObject ...@@ -621,7 +633,7 @@ class Program final : angle::NonCopyable, public LabeledObject
const std::string &mappedPrefix, const std::string &mappedPrefix,
int blockIndex); int blockIndex);
void defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, GLenum shaderType); void defineInterfaceBlock(const sh::InterfaceBlock &interfaceBlock, GLenum shaderType);
// Both these function update the cached uniform values and return a modified "count" // Both these function update the cached uniform values and return a modified "count"
// so that the uniform update doesn't overflow the uniform. // so that the uniform update doesn't overflow the uniform.
......
...@@ -116,21 +116,21 @@ ShaderVariableBuffer::~ShaderVariableBuffer() ...@@ -116,21 +116,21 @@ ShaderVariableBuffer::~ShaderVariableBuffer()
{ {
} }
UniformBlock::UniformBlock() : isArray(false), arrayElement(0) InterfaceBlock::InterfaceBlock() : isArray(false), arrayElement(0)
{ {
} }
UniformBlock::UniformBlock(const std::string &nameIn, InterfaceBlock::InterfaceBlock(const std::string &nameIn,
const std::string &mappedNameIn, const std::string &mappedNameIn,
bool isArrayIn, bool isArrayIn,
unsigned int arrayElementIn, unsigned int arrayElementIn,
int bindingIn) int bindingIn)
: name(nameIn), mappedName(mappedNameIn), isArray(isArrayIn), arrayElement(arrayElementIn) : name(nameIn), mappedName(mappedNameIn), isArray(isArrayIn), arrayElement(arrayElementIn)
{ {
binding = bindingIn; binding = bindingIn;
} }
std::string UniformBlock::nameWithArrayIndex() const std::string InterfaceBlock::nameWithArrayIndex() const
{ {
std::stringstream fullNameStr; std::stringstream fullNameStr;
fullNameStr << name; fullNameStr << name;
...@@ -142,7 +142,7 @@ std::string UniformBlock::nameWithArrayIndex() const ...@@ -142,7 +142,7 @@ std::string UniformBlock::nameWithArrayIndex() const
return fullNameStr.str(); return fullNameStr.str();
} }
std::string UniformBlock::mappedNameWithArrayIndex() const std::string InterfaceBlock::mappedNameWithArrayIndex() const
{ {
std::stringstream fullNameStr; std::stringstream fullNameStr;
fullNameStr << mappedName; fullNameStr << mappedName;
......
...@@ -74,17 +74,17 @@ struct ShaderVariableBuffer ...@@ -74,17 +74,17 @@ struct ShaderVariableBuffer
using AtomicCounterBuffer = ShaderVariableBuffer; using AtomicCounterBuffer = ShaderVariableBuffer;
// Helper struct representing a single shader uniform block // Helper struct representing a single shader interface block
struct UniformBlock : public ShaderVariableBuffer struct InterfaceBlock : public ShaderVariableBuffer
{ {
UniformBlock(); InterfaceBlock();
UniformBlock(const std::string &nameIn, InterfaceBlock(const std::string &nameIn,
const std::string &mappedNameIn, const std::string &mappedNameIn,
bool isArrayIn, bool isArrayIn,
unsigned int arrayElementIn, unsigned int arrayElementIn,
int bindingIn); int bindingIn);
UniformBlock(const UniformBlock &other) = default; InterfaceBlock(const InterfaceBlock &other) = default;
UniformBlock &operator=(const UniformBlock &other) = default; InterfaceBlock &operator=(const InterfaceBlock &other) = default;
std::string nameWithArrayIndex() const; std::string nameWithArrayIndex() const;
std::string mappedNameWithArrayIndex() const; std::string mappedNameWithArrayIndex() const;
......
...@@ -588,7 +588,7 @@ GLint QueryProgramInterfaceMaxNameLength(const Program *program, GLenum programI ...@@ -588,7 +588,7 @@ GLint QueryProgramInterfaceMaxNameLength(const Program *program, GLenum programI
case GL_UNIFORM_BLOCK: case GL_UNIFORM_BLOCK:
maxNameLength = maxNameLength =
FindMaxSize(program->getState().getUniformBlocks(), &UniformBlock::name); FindMaxSize(program->getState().getUniformBlocks(), &InterfaceBlock::name);
break; break;
// TODO(jie.a.chen@intel.com): more interfaces. // TODO(jie.a.chen@intel.com): more interfaces.
...@@ -612,7 +612,7 @@ GLint QueryProgramInterfaceMaxNumActiveVariables(const Program *program, GLenum ...@@ -612,7 +612,7 @@ GLint QueryProgramInterfaceMaxNumActiveVariables(const Program *program, GLenum
{ {
case GL_UNIFORM_BLOCK: case GL_UNIFORM_BLOCK:
return FindMaxSize(program->getState().getUniformBlocks(), return FindMaxSize(program->getState().getUniformBlocks(),
&UniformBlock::memberIndexes); &InterfaceBlock::memberIndexes);
// TODO(jie.a.chen@intel.com): more interfaces. // TODO(jie.a.chen@intel.com): more interfaces.
case GL_SHADER_STORAGE_BLOCK: case GL_SHADER_STORAGE_BLOCK:
...@@ -1010,7 +1010,7 @@ void QueryActiveUniformBlockiv(const Program *program, ...@@ -1010,7 +1010,7 @@ void QueryActiveUniformBlockiv(const Program *program,
GLenum pname, GLenum pname,
GLint *params) GLint *params)
{ {
const UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex); const InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
switch (pname) switch (pname)
{ {
case GL_UNIFORM_BLOCK_BINDING: case GL_UNIFORM_BLOCK_BINDING:
......
...@@ -1670,7 +1670,7 @@ void ProgramD3D::ensureUniformBlocksInitialized() ...@@ -1670,7 +1670,7 @@ void ProgramD3D::ensureUniformBlocksInitialized()
SafeGetImplAs<ShaderD3D>(mState.getAttachedFragmentShader()); SafeGetImplAs<ShaderD3D>(mState.getAttachedFragmentShader());
const ShaderD3D *computeShaderD3D = SafeGetImplAs<ShaderD3D>(mState.getAttachedComputeShader()); const ShaderD3D *computeShaderD3D = SafeGetImplAs<ShaderD3D>(mState.getAttachedComputeShader());
for (const gl::UniformBlock &uniformBlock : mState.getUniformBlocks()) for (const gl::InterfaceBlock &uniformBlock : mState.getUniformBlocks())
{ {
unsigned int uniformBlockElement = uniformBlock.isArray ? uniformBlock.arrayElement : 0; unsigned int uniformBlockElement = uniformBlock.isArray ? uniformBlock.arrayElement : 0;
......
...@@ -508,7 +508,7 @@ void ProgramGL::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformB ...@@ -508,7 +508,7 @@ void ProgramGL::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformB
if (mUniformBlockRealLocationMap.empty()) if (mUniformBlockRealLocationMap.empty())
{ {
mUniformBlockRealLocationMap.reserve(mState.getUniformBlocks().size()); mUniformBlockRealLocationMap.reserve(mState.getUniformBlocks().size());
for (const gl::UniformBlock &uniformBlock : mState.getUniformBlocks()) for (const gl::InterfaceBlock &uniformBlock : mState.getUniformBlocks())
{ {
const std::string &mappedNameWithIndex = uniformBlock.mappedNameWithArrayIndex(); const std::string &mappedNameWithIndex = uniformBlock.mappedNameWithArrayIndex();
GLuint blockIndex = GLuint blockIndex =
......
...@@ -180,6 +180,7 @@ StateManagerGL::StateManagerGL(const FunctionsGL *functions, ...@@ -180,6 +180,7 @@ StateManagerGL::StateManagerGL(const FunctionsGL *functions,
mIndexedBuffers[GL_UNIFORM_BUFFER].resize(rendererCaps.maxCombinedUniformBlocks); mIndexedBuffers[GL_UNIFORM_BUFFER].resize(rendererCaps.maxCombinedUniformBlocks);
mIndexedBuffers[GL_ATOMIC_COUNTER_BUFFER].resize(rendererCaps.maxCombinedAtomicCounterBuffers); mIndexedBuffers[GL_ATOMIC_COUNTER_BUFFER].resize(rendererCaps.maxCombinedAtomicCounterBuffers);
mIndexedBuffers[GL_SHADER_STORAGE_BUFFER].resize(rendererCaps.maxCombinedShaderStorageBlocks);
for (GLenum queryType : QueryTypes) for (GLenum queryType : QueryTypes)
{ {
...@@ -980,6 +981,28 @@ void StateManagerGL::updateProgramTextureAndSamplerBindings(const gl::Context *c ...@@ -980,6 +981,28 @@ void StateManagerGL::updateProgramTextureAndSamplerBindings(const gl::Context *c
} }
} }
} }
for (size_t blockIndex = 0; blockIndex < program->getActiveShaderStorageBlockCount();
blockIndex++)
{
GLuint binding = program->getShaderStorageBlockBinding(static_cast<GLuint>(blockIndex));
const auto &shaderStorageBuffer = glState.getIndexedShaderStorageBuffer(binding);
if (shaderStorageBuffer.get() != nullptr)
{
BufferGL *bufferGL = GetImplAs<BufferGL>(shaderStorageBuffer.get());
if (shaderStorageBuffer.getSize() == 0)
{
bindBufferBase(GL_SHADER_STORAGE_BUFFER, binding, bufferGL->getBufferID());
}
else
{
bindBufferRange(GL_SHADER_STORAGE_BUFFER, binding, bufferGL->getBufferID(),
shaderStorageBuffer.getOffset(), shaderStorageBuffer.getSize());
}
}
}
} }
gl::Error StateManagerGL::setGenericDrawState(const gl::Context *context) gl::Error StateManagerGL::setGenericDrawState(const gl::Context *context)
......
...@@ -2617,7 +2617,7 @@ bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count) ...@@ -2617,7 +2617,7 @@ bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
for (unsigned int uniformBlockIndex = 0; for (unsigned int uniformBlockIndex = 0;
uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++) uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
{ {
const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex); const gl::InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex); GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
const OffsetBindingPointer<Buffer> &uniformBuffer = const OffsetBindingPointer<Buffer> &uniformBuffer =
state.getIndexedUniformBuffer(blockBinding); state.getIndexedUniformBuffer(blockBinding);
...@@ -5584,7 +5584,7 @@ bool ValidateGetActiveUniformBlockivBase(Context *context, ...@@ -5584,7 +5584,7 @@ bool ValidateGetActiveUniformBlockivBase(Context *context,
{ {
if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES) if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
{ {
const UniformBlock &uniformBlock = const InterfaceBlock &uniformBlock =
programObject->getUniformBlockByIndex(uniformBlockIndex); programObject->getUniformBlockByIndex(uniformBlockIndex);
*length = static_cast<GLsizei>(uniformBlock.memberIndexes.size()); *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
} }
......
...@@ -74,6 +74,7 @@ ...@@ -74,6 +74,7 @@
'<(angle_path)/src/tests/gl_tests/RobustBufferAccessBehaviorTest.cpp', '<(angle_path)/src/tests/gl_tests/RobustBufferAccessBehaviorTest.cpp',
'<(angle_path)/src/tests/gl_tests/RobustClientMemoryTest.cpp', '<(angle_path)/src/tests/gl_tests/RobustClientMemoryTest.cpp',
'<(angle_path)/src/tests/gl_tests/RobustResourceInitTest.cpp', '<(angle_path)/src/tests/gl_tests/RobustResourceInitTest.cpp',
'<(angle_path)/src/tests/gl_tests/ShaderStorageBufferTest.cpp',
'<(angle_path)/src/tests/gl_tests/SimpleOperationTest.cpp', '<(angle_path)/src/tests/gl_tests/SimpleOperationTest.cpp',
'<(angle_path)/src/tests/gl_tests/SixteenBppTextureTest.cpp', '<(angle_path)/src/tests/gl_tests/SixteenBppTextureTest.cpp',
'<(angle_path)/src/tests/gl_tests/SRGBFramebufferTest.cpp', '<(angle_path)/src/tests/gl_tests/SRGBFramebufferTest.cpp',
......
//
// Copyright 2017 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.
//
// ShaderStorageBufferTest:
// Various tests related for shader storage buffers.
//
#include "test_utils/ANGLETest.h"
#include "test_utils/gl_raii.h"
using namespace angle;
namespace
{
class ShaderStorageBufferTest31 : public ANGLETest
{
protected:
ShaderStorageBufferTest31()
{
setWindowWidth(128);
setWindowHeight(128);
setConfigRedBits(8);
setConfigGreenBits(8);
setConfigBlueBits(8);
setConfigAlphaBits(8);
}
};
// Matched block names within a shader interface must match in terms of having the same number of
// declarations with the same sequence of types.
TEST_P(ShaderStorageBufferTest31, MatchedBlockNameWithDifferentMemberType)
{
const std::string &vertexShaderSource =
"#version 310 es\n"
"buffer blockName {\n"
" float data;\n"
"};\n"
"void main()\n"
"{\n"
"}\n";
const std::string &fragmentShaderSource =
"#version 310 es\n"
"buffer blockName {\n"
" uint data;\n"
"};\n"
"void main()\n"
"{\n"
"}\n";
GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
EXPECT_EQ(0u, program);
}
// Linking should fail if blocks in vertex shader exceed GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS.
TEST_P(ShaderStorageBufferTest31, ExceedMaxVertexShaderStorageBlocks)
{
std::ostringstream instanceCount;
GLint maxVertexShaderStorageBlocks;
glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &maxVertexShaderStorageBlocks);
instanceCount << maxVertexShaderStorageBlocks;
const std::string &vertexShaderSource =
"#version 310 es\n"
"layout(shared) buffer blockName {\n"
" uint data;\n"
"} instance[" +
instanceCount.str() +
" + 1];\n"
"void main()\n"
"{\n"
"}\n";
const std::string &fragmentShaderSource =
"#version 310 es\n"
"void main()\n"
"{\n"
"}\n";
GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
EXPECT_EQ(0u, program);
}
// Test shader storage buffer read write.
TEST_P(ShaderStorageBufferTest31, ShaderStorageBufferReadWrite)
{
// TODO(jiajia.qin@intel.com): Figure out why it fails on AMD platform.
ANGLE_SKIP_TEST_IF(IsAMD() && IsDesktopOpenGL());
const std::string &csSource =
"#version 310 es\n"
"layout(local_size_x=1, local_size_y=1, local_size_z=1) in;\n"
"layout(binding = 1) buffer blockName {\n"
" uint data[2];\n"
"} instanceName;\n"
"void main()\n"
"{\n"
" instanceName.data[0] = 3u;\n"
" if (instanceName.data[0] == 3u)\n"
" instanceName.data[1] = 4u;\n"
" else\n"
" instanceName.data[1] = 5u;\n"
"}\n";
ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
glUseProgram(program.get());
unsigned int bufferData[2] = {0u};
// Create shader storage buffer
GLBuffer shaderStorageBuffer;
glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer);
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(bufferData), nullptr, GL_STATIC_DRAW);
// Bind shader storage buffer
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, shaderStorageBuffer);
// Dispath compute
glDispatchCompute(1, 1, 1);
glFinish();
// Read back shader storage buffer
glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer);
void *ptr = glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(bufferData), GL_MAP_READ_BIT);
memcpy(bufferData, ptr, sizeof(bufferData));
glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
EXPECT_EQ(3u, bufferData[0]);
EXPECT_EQ(4u, bufferData[1]);
EXPECT_GL_NO_ERROR();
}
ANGLE_INSTANTIATE_TEST(ShaderStorageBufferTest31, ES31_OPENGL(), ES31_OPENGLES());
} // namespace
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