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());
......
...@@ -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