Commit 6db1c2e8 by Jamie Madill

Link interface blocks in ProgramImpl::link.

This allows the back-end to have access to the interface block info in the link operation, and also allows the interface block info to have direct access to the post-link Impl information. BUG=angleproject:2208 Change-Id: Ib2bfb3c9155eee715bd3d29de1c3fdd67b16eed4 Reviewed-on: https://chromium-review.googlesource.com/753521Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 8f8edd6e
...@@ -871,7 +871,7 @@ Error Program::link(const gl::Context *context) ...@@ -871,7 +871,7 @@ Error Program::link(const gl::Context *context)
} }
gatherAtomicCounterBuffers(); gatherAtomicCounterBuffers();
gatherInterfaceBlockInfo(context); initInterfaceBlockBindings();
setUniformValuesFromBindingQualifiers(); setUniformValuesFromBindingQualifiers();
...@@ -2874,55 +2874,8 @@ void Program::gatherAtomicCounterBuffers() ...@@ -2874,55 +2874,8 @@ 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::gatherUniformBlockInfo(const gl::Context *context) void Program::initInterfaceBlockBindings()
{ {
UniformBlockLinker blockLinker(&mState.mUniformBlocks, &mState.mUniforms);
InitUniformBlockLinker(context, mState, &blockLinker);
auto getImplBlockSize = [this](const std::string &name, const std::string &mappedName,
size_t *sizeOut) {
return this->mProgram->getUniformBlockSize(name, mappedName, sizeOut);
};
auto getImplMemberInfo = [this](const std::string &name, const std::string &mappedName,
sh::BlockMemberInfo *infoOut) {
return this->mProgram->getUniformBlockMemberInfo(name, mappedName, infoOut);
};
blockLinker.linkBlocks(getImplBlockSize, getImplMemberInfo);
}
void Program::gatherShaderStorageBlockInfo(const gl::Context *context)
{
ShaderStorageBlockLinker blockLinker(&mState.mShaderStorageBlocks);
InitShaderStorageBlockLinker(context, mState, &blockLinker);
// We don't have a way of determining block info for shader storage blocks yet.
// TODO(jiajia.qin@intel.com): Determine correct block size and layout.
auto getImplBlockSize = [this](const std::string &name, const std::string &mappedName,
size_t *sizeOut) {
return this->mProgram->getUniformBlockSize(name, mappedName, sizeOut);
};
auto getImplMemberInfo = [this](const std::string &name, const std::string &mappedName,
sh::BlockMemberInfo *infoOut) {
return this->mProgram->getUniformBlockMemberInfo(name, mappedName, infoOut);
};
blockLinker.linkBlocks(getImplBlockSize, getImplMemberInfo);
}
void Program::gatherInterfaceBlockInfo(const Context *context)
{
ASSERT(mState.mUniformBlocks.empty());
ASSERT(mState.mShaderStorageBlocks.empty());
gatherUniformBlockInfo(context);
if (context->getClientVersion() >= Version(3, 1))
{
gatherShaderStorageBlockInfo(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++)
{ {
......
...@@ -640,9 +640,7 @@ class Program final : angle::NonCopyable, public LabeledObject ...@@ -640,9 +640,7 @@ class Program final : angle::NonCopyable, public LabeledObject
void setUniformValuesFromBindingQualifiers(); void setUniformValuesFromBindingQualifiers();
void gatherAtomicCounterBuffers(); void gatherAtomicCounterBuffers();
void gatherUniformBlockInfo(const gl::Context *context); void initInterfaceBlockBindings();
void gatherShaderStorageBlockInfo(const gl::Context *context);
void gatherInterfaceBlockInfo(const Context *context);
// 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.
......
...@@ -637,6 +637,8 @@ void InterfaceBlockLinker::addShaderBlocks(GLenum shader, ...@@ -637,6 +637,8 @@ void InterfaceBlockLinker::addShaderBlocks(GLenum shader,
void InterfaceBlockLinker::linkBlocks(const GetBlockSize &getBlockSize, void InterfaceBlockLinker::linkBlocks(const GetBlockSize &getBlockSize,
const GetBlockMemberInfo &getMemberInfo) const const GetBlockMemberInfo &getMemberInfo) const
{ {
ASSERT(mBlocksOut->empty());
std::set<std::string> visitedList; std::set<std::string> visitedList;
for (const auto &shaderBlocks : mShaderBlocks) for (const auto &shaderBlocks : mShaderBlocks)
......
...@@ -83,17 +83,6 @@ class ProgramImpl : angle::NonCopyable ...@@ -83,17 +83,6 @@ class ProgramImpl : angle::NonCopyable
// TODO: synchronize in syncState when dirty bits exist. // TODO: synchronize in syncState when dirty bits exist.
virtual void setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) = 0; virtual void setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) = 0;
// May only be called after a successful link operation.
// Return false for inactive blocks.
virtual bool getUniformBlockSize(const std::string &blockName,
const std::string &blockMappedName,
size_t *sizeOut) const = 0;
// May only be called after a successful link operation.
// Returns false for inactive members.
virtual bool getUniformBlockMemberInfo(const std::string &memberUniformName,
const std::string &memberUniformMappedName,
sh::BlockMemberInfo *memberInfoOut) const = 0;
// CHROMIUM_path_rendering // CHROMIUM_path_rendering
// Set parameters to control fragment shader input variable interpolation // Set parameters to control fragment shader input variable interpolation
virtual void setPathFragmentInputGen(const std::string &inputName, virtual void setPathFragmentInputGen(const std::string &inputName,
......
...@@ -63,10 +63,6 @@ class MockProgramImpl : public rx::ProgramImpl ...@@ -63,10 +63,6 @@ class MockProgramImpl : public rx::ProgramImpl
MOCK_CONST_METHOD3(getUniformuiv, void(const gl::Context *, GLint, GLuint *)); MOCK_CONST_METHOD3(getUniformuiv, void(const gl::Context *, GLint, GLuint *));
MOCK_METHOD2(setUniformBlockBinding, void(GLuint, GLuint)); MOCK_METHOD2(setUniformBlockBinding, void(GLuint, GLuint));
MOCK_CONST_METHOD3(getUniformBlockSize,
bool(const std::string &, const std::string &, size_t *));
MOCK_CONST_METHOD3(getUniformBlockMemberInfo,
bool(const std::string &, const std::string &, sh::BlockMemberInfo *));
MOCK_METHOD4(setPathFragmentInputGen, MOCK_METHOD4(setPathFragmentInputGen,
void(const std::string &, GLenum, GLint, const GLfloat *)); void(const std::string &, GLenum, GLint, const GLfloat *));
......
...@@ -196,12 +196,6 @@ class ProgramD3D : public ProgramImpl ...@@ -196,12 +196,6 @@ class ProgramD3D : public ProgramImpl
gl::InfoLog &infoLog) override; gl::InfoLog &infoLog) override;
GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) override; GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) override;
bool getUniformBlockSize(const std::string &blockName,
const std::string &blockMappedName,
size_t *sizeOut) const override;
bool getUniformBlockMemberInfo(const std::string &memberUniformName,
const std::string &memberUniformMappedName,
sh::BlockMemberInfo *memberInfoOut) const override;
void setPathFragmentInputGen(const std::string &inputName, void setPathFragmentInputGen(const std::string &inputName,
GLenum genMode, GLenum genMode,
GLint components, GLint components,
...@@ -428,16 +422,15 @@ class ProgramD3D : public ProgramImpl ...@@ -428,16 +422,15 @@ class ProgramD3D : public ProgramImpl
void initAttribLocationsToD3DSemantic(const gl::Context *context); void initAttribLocationsToD3DSemantic(const gl::Context *context);
void reset(); void reset();
void ensureUniformBlocksInitialized(); void initializeUniformBlocks();
void initUniformBlockInfo(const gl::Context *context, gl::Shader *shader);
size_t getUniformBlockInfo(const sh::InterfaceBlock &interfaceBlock);
void updateCachedInputLayoutFromShader(const gl::Context *context); void updateCachedInputLayoutFromShader(const gl::Context *context);
void updateCachedOutputLayoutFromShader(); void updateCachedOutputLayoutFromShader();
void updateCachedVertexExecutableIndex(); void updateCachedVertexExecutableIndex();
void updateCachedPixelExecutableIndex(); void updateCachedPixelExecutableIndex();
void linkResources(const gl::Context *context, const gl::ProgramLinkedResources &resources);
RendererD3D *mRenderer; RendererD3D *mRenderer;
DynamicHLSL *mDynamicHLSL; DynamicHLSL *mDynamicHLSL;
...@@ -498,9 +491,6 @@ class ProgramD3D : public ProgramImpl ...@@ -498,9 +491,6 @@ class ProgramD3D : public ProgramImpl
bool mFragmentUniformsDirty; bool mFragmentUniformsDirty;
bool mComputeUniformsDirty; bool mComputeUniformsDirty;
std::map<std::string, sh::BlockMemberInfo> mBlockInfo;
std::map<std::string, size_t> mBlockDataSizes;
static unsigned int issueSerial(); static unsigned int issueSerial();
static unsigned int mCurrentSerial; static unsigned int mCurrentSerial;
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "common/string_utils.h" #include "common/string_utils.h"
#include "common/utilities.h" #include "common/utilities.h"
#include "libANGLE/Context.h" #include "libANGLE/Context.h"
#include "libANGLE/ProgramLinkedResources.h"
#include "libANGLE/Uniform.h" #include "libANGLE/Uniform.h"
#include "libANGLE/renderer/gl/ContextGL.h" #include "libANGLE/renderer/gl/ContextGL.h"
#include "libANGLE/renderer/gl/FunctionsGL.h" #include "libANGLE/renderer/gl/FunctionsGL.h"
...@@ -212,6 +213,7 @@ gl::LinkResult ProgramGL::link(const gl::Context *context, ...@@ -212,6 +213,7 @@ gl::LinkResult ProgramGL::link(const gl::Context *context,
mStateManager->forceUseProgram(mProgramID); mStateManager->forceUseProgram(mProgramID);
} }
linkResources(resources);
postLink(); postLink();
return true; return true;
...@@ -805,4 +807,35 @@ void ProgramGL::markUnusedUniformLocations(std::vector<gl::VariableLocation> *un ...@@ -805,4 +807,35 @@ void ProgramGL::markUnusedUniformLocations(std::vector<gl::VariableLocation> *un
} }
} }
void ProgramGL::linkResources(const gl::ProgramLinkedResources &resources)
{
// Gather interface block info.
auto getUniformBlockSize = [this](const std::string &name, const std::string &mappedName,
size_t *sizeOut) {
return this->getUniformBlockSize(name, mappedName, sizeOut);
};
auto getUniformBlockMemberInfo = [this](const std::string &name, const std::string &mappedName,
sh::BlockMemberInfo *infoOut) {
return this->getUniformBlockMemberInfo(name, mappedName, infoOut);
};
resources.uniformBlockLinker.linkBlocks(getUniformBlockSize, getUniformBlockMemberInfo);
// TODO(jiajia.qin@intel.com): Determine correct shader storage block info.
auto getShaderStorageBlockSize = [](const std::string &name, const std::string &mappedName,
size_t *sizeOut) {
*sizeOut = 0;
return true;
};
auto getShaderStorageBlockMemberInfo =
[](const std::string &name, const std::string &mappedName, sh::BlockMemberInfo *infoOut) {
*infoOut = sh::BlockMemberInfo::getDefaultBlockInfo();
return true;
};
resources.shaderStorageBlockLinker.linkBlocks(getShaderStorageBlockSize,
getShaderStorageBlockMemberInfo);
}
} // namespace rx } // namespace rx
...@@ -71,13 +71,6 @@ class ProgramGL : public ProgramImpl ...@@ -71,13 +71,6 @@ class ProgramGL : public ProgramImpl
void setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) override; void setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) override;
bool getUniformBlockSize(const std::string &blockName,
const std::string &blockMappedName,
size_t *sizeOut) const override;
bool getUniformBlockMemberInfo(const std::string &memberUniformName,
const std::string &memberUniformMappedName,
sh::BlockMemberInfo *memberInfoOut) const override;
void setPathFragmentInputGen(const std::string &inputName, void setPathFragmentInputGen(const std::string &inputName,
GLenum genMode, GLenum genMode,
GLint components, GLint components,
...@@ -97,6 +90,14 @@ class ProgramGL : public ProgramImpl ...@@ -97,6 +90,14 @@ class ProgramGL : public ProgramImpl
void postLink(); void postLink();
void reapplyUBOBindingsIfNeeded(const gl::Context *context); void reapplyUBOBindingsIfNeeded(const gl::Context *context);
bool getUniformBlockSize(const std::string &blockName,
const std::string &blockMappedName,
size_t *sizeOut) const;
bool getUniformBlockMemberInfo(const std::string &memberUniformName,
const std::string &memberUniformMappedName,
sh::BlockMemberInfo *memberInfoOut) const;
void linkResources(const gl::ProgramLinkedResources &resources);
// Helper function, makes it simpler to type. // Helper function, makes it simpler to type.
GLint uniLoc(GLint glLocation) const { return mUniformRealLocationMap[glLocation]; } GLint uniLoc(GLint glLocation) const { return mUniformRealLocationMap[glLocation]; }
......
...@@ -183,23 +183,6 @@ void ProgramNULL::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint unifor ...@@ -183,23 +183,6 @@ void ProgramNULL::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint unifor
{ {
} }
bool ProgramNULL::getUniformBlockSize(const std::string &blockName,
const std::string &blockMappedName,
size_t *sizeOut) const
{
// TODO(geofflang): Compute reasonable sizes?
*sizeOut = 0;
return true;
}
bool ProgramNULL::getUniformBlockMemberInfo(const std::string &memberUniformName,
const std::string &memberUniformMappedName,
sh::BlockMemberInfo *memberInfoOut) const
{
// TODO(geofflang): Compute reasonable values?
return true;
}
void ProgramNULL::setPathFragmentInputGen(const std::string &inputName, void ProgramNULL::setPathFragmentInputGen(const std::string &inputName,
GLenum genMode, GLenum genMode,
GLint components, GLint components,
......
...@@ -89,17 +89,6 @@ class ProgramNULL : public ProgramImpl ...@@ -89,17 +89,6 @@ class ProgramNULL : public ProgramImpl
// TODO: synchronize in syncState when dirty bits exist. // TODO: synchronize in syncState when dirty bits exist.
void setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) override; void setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) override;
// May only be called after a successful link operation.
// Return false for inactive blocks.
bool getUniformBlockSize(const std::string &blockName,
const std::string &blockMappedName,
size_t *sizeOut) const override;
// May only be called after a successful link operation.
// Returns false for inactive members.
bool getUniformBlockMemberInfo(const std::string &memberUniformName,
const std::string &memberUniformMappedName,
sh::BlockMemberInfo *memberInfoOut) const override;
// CHROMIUM_path_rendering // CHROMIUM_path_rendering
// Set parameters to control fragment shader input variable interpolation // Set parameters to control fragment shader input variable interpolation
void setPathFragmentInputGen(const std::string &inputName, void setPathFragmentInputGen(const std::string &inputName,
......
...@@ -528,22 +528,6 @@ void ProgramVk::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformB ...@@ -528,22 +528,6 @@ void ProgramVk::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformB
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
bool ProgramVk::getUniformBlockSize(const std::string &blockName,
const std::string &blockMappedName,
size_t *sizeOut) const
{
UNIMPLEMENTED();
return bool();
}
bool ProgramVk::getUniformBlockMemberInfo(const std::string &memberUniformName,
const std::string &memberUniformMappedName,
sh::BlockMemberInfo *memberInfoOut) const
{
UNIMPLEMENTED();
return bool();
}
void ProgramVk::setPathFragmentInputGen(const std::string &inputName, void ProgramVk::setPathFragmentInputGen(const std::string &inputName,
GLenum genMode, GLenum genMode,
GLint components, GLint components,
......
...@@ -94,18 +94,6 @@ class ProgramVk : public ProgramImpl ...@@ -94,18 +94,6 @@ class ProgramVk : public ProgramImpl
// TODO: synchronize in syncState when dirty bits exist. // TODO: synchronize in syncState when dirty bits exist.
void setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) override; void setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) override;
// May only be called after a successful link operation.
// Return false for inactive blocks.
bool getUniformBlockSize(const std::string &blockName,
const std::string &blockMappedName,
size_t *sizeOut) const override;
// May only be called after a successful link operation.
// Returns false for inactive members.
bool getUniformBlockMemberInfo(const std::string &memberUniformName,
const std::string &memberUniformMappedName,
sh::BlockMemberInfo *memberInfoOut) const override;
void setPathFragmentInputGen(const std::string &inputName, void setPathFragmentInputGen(const std::string &inputName,
GLenum genMode, GLenum genMode,
GLint components, GLint components,
......
...@@ -1156,6 +1156,46 @@ TEST_P(UniformBufferTest, Std140UniformBlockInstanceWithNestedStructsContainingV ...@@ -1156,6 +1156,46 @@ TEST_P(UniformBufferTest, Std140UniformBlockInstanceWithNestedStructsContainingV
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
} }
// Tests the detaching shaders from the program and using uniform blocks works.
// This covers a bug in ANGLE's D3D back-end.
TEST_P(UniformBufferTest, DetachShaders)
{
GLuint vertexShader = CompileShader(GL_VERTEX_SHADER, mVertexShaderSource);
ASSERT_NE(0u, vertexShader);
GLuint fragmentShader = CompileShader(GL_FRAGMENT_SHADER, mFragmentShaderSource);
ASSERT_NE(0u, fragmentShader);
GLuint program = glCreateProgram();
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
ASSERT_TRUE(LinkAttachedProgram(program));
glDetachShader(program, vertexShader);
glDetachShader(program, fragmentShader);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
glClear(GL_COLOR_BUFFER_BIT);
float floatData[4] = {0.5f, 0.75f, 0.25f, 1.0f};
glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
glBufferData(GL_UNIFORM_BUFFER, sizeof(float) * 4, floatData, GL_STATIC_DRAW);
glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
GLint uniformBufferIndex = glGetUniformBlockIndex(mProgram, "uni");
ASSERT_NE(uniformBufferIndex, -1);
glUniformBlockBinding(program, uniformBufferIndex, 0);
drawQuad(program, "position", 0.5f);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_NEAR(0, 0, 128, 191, 64, 255, 1);
glDeleteProgram(program);
}
// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against. // Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
ANGLE_INSTANTIATE_TEST(UniformBufferTest, ANGLE_INSTANTIATE_TEST(UniformBufferTest,
ES3_D3D11(), ES3_D3D11(),
......
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