Commit f414121d by Jamie Madill Committed by Commit Bot

D3D11: Fix program uniform buffer dity bits.

There were actually three missing state synchronization points: 1. When re-binding a uniform buffer, we had no dirty bits. 2. When modifying the Program bindings, we also had no update. 3. When triggering a dependent state update via BufferData. This fixes all the missing syncs and adds tests for the cases. Bug: angleproject:1390 Change-Id: I2f05766545784248bcca8308ae34ac5720237ab1 Reviewed-on: https://chromium-review.googlesource.com/823150 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarYuly Novikov <ynovikov@chromium.org> Reviewed-by: 's avatarKai Ninomiya <kainino@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent bd924af1
...@@ -1295,6 +1295,7 @@ void State::setIndexedBufferBinding(const Context *context, ...@@ -1295,6 +1295,7 @@ void State::setIndexedBufferBinding(const Context *context,
break; break;
case BufferBinding::Uniform: case BufferBinding::Uniform:
mUniformBuffers[index].set(context, buffer, offset, size); mUniformBuffers[index].set(context, buffer, offset, size);
mDirtyBits.set(DIRTY_BIT_UNIFORM_BUFFER_BINDINGS);
break; break;
case BufferBinding::AtomicCounter: case BufferBinding::AtomicCounter:
mAtomicCounterBuffers[index].set(context, buffer, offset, size); mAtomicCounterBuffers[index].set(context, buffer, offset, size);
......
...@@ -396,6 +396,8 @@ class State : public OnAttachmentDirtyReceiver, angle::NonCopyable ...@@ -396,6 +396,8 @@ class State : public OnAttachmentDirtyReceiver, angle::NonCopyable
DIRTY_BIT_DRAW_INDIRECT_BUFFER_BINDING, DIRTY_BIT_DRAW_INDIRECT_BUFFER_BINDING,
DIRTY_BIT_DISPATCH_INDIRECT_BUFFER_BINDING, DIRTY_BIT_DISPATCH_INDIRECT_BUFFER_BINDING,
DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING, DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING,
// TODO(jmadill): Fine-grained dirty bits for each index.
DIRTY_BIT_UNIFORM_BUFFER_BINDINGS,
DIRTY_BIT_PROGRAM_BINDING, DIRTY_BIT_PROGRAM_BINDING,
DIRTY_BIT_PROGRAM_EXECUTABLE, DIRTY_BIT_PROGRAM_EXECUTABLE,
// TODO(jmadill): Fine-grained dirty bits for each texture/sampler. // TODO(jmadill): Fine-grained dirty bits for each texture/sampler.
......
...@@ -2008,9 +2008,9 @@ void ProgramD3D::setUniform4uiv(GLint location, GLsizei count, const GLuint *v) ...@@ -2008,9 +2008,9 @@ void ProgramD3D::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
setUniformInternal(location, count, v, GL_UNSIGNED_INT_VEC4); setUniformInternal(location, count, v, GL_UNSIGNED_INT_VEC4);
} }
void ProgramD3D::setUniformBlockBinding(GLuint /*uniformBlockIndex*/, void ProgramD3D::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint /*uniformBlockBinding*/)
GLuint /*uniformBlockBinding*/)
{ {
mRenderer->onDirtyUniformBlockBinding(uniformBlockIndex);
} }
void ProgramD3D::defineUniformsAndAssignRegisters(const gl::Context *context) void ProgramD3D::defineUniformsAndAssignRegisters(const gl::Context *context)
......
...@@ -216,6 +216,11 @@ gl::Error RendererD3D::initializeMultisampleTextureToBlack(const gl::Context *co ...@@ -216,6 +216,11 @@ gl::Error RendererD3D::initializeMultisampleTextureToBlack(const gl::Context *co
return clearRenderTarget(renderTarget, gl::ColorF(0.0f, 0.0f, 0.0f, 1.0f), 1.0f, 0); return clearRenderTarget(renderTarget, gl::ColorF(0.0f, 0.0f, 0.0f, 1.0f), 1.0f, 0);
} }
void RendererD3D::onDirtyUniformBlockBinding(GLuint /*uniformBlockIndex*/)
{
// No-op by default. Only implemented in D3D11.
}
unsigned int GetBlendSampleMask(const gl::State &glState, int samples) unsigned int GetBlendSampleMask(const gl::State &glState, int samples)
{ {
unsigned int mask = 0; unsigned int mask = 0;
......
...@@ -312,6 +312,9 @@ class RendererD3D : public BufferFactoryD3D, public MultisampleTextureInitialize ...@@ -312,6 +312,9 @@ class RendererD3D : public BufferFactoryD3D, public MultisampleTextureInitialize
gl::Error initializeMultisampleTextureToBlack(const gl::Context *context, gl::Error initializeMultisampleTextureToBlack(const gl::Context *context,
gl::Texture *glTexture) override; gl::Texture *glTexture) override;
// Should really be handled by Program dirty bits, but that requires splitting Program9/11.
virtual void onDirtyUniformBlockBinding(GLuint uniformBlockIndex);
protected: protected:
virtual bool getLUID(LUID *adapterLuid) const = 0; virtual bool getLUID(LUID *adapterLuid) const = 0;
virtual void generateCaps(gl::Caps *outCaps, virtual void generateCaps(gl::Caps *outCaps,
......
...@@ -4050,4 +4050,9 @@ gl::Error Renderer11::markTransformFeedbackUsage(const gl::Context *context) ...@@ -4050,4 +4050,9 @@ gl::Error Renderer11::markTransformFeedbackUsage(const gl::Context *context)
return gl::NoError(); return gl::NoError();
} }
void Renderer11::onDirtyUniformBlockBinding(GLuint /*uniformBlockIndex*/)
{
mStateManager.invalidateProgramUniformBuffers();
}
} // namespace rx } // namespace rx
...@@ -459,6 +459,8 @@ class Renderer11 : public RendererD3D ...@@ -459,6 +459,8 @@ class Renderer11 : public RendererD3D
bool canSelectViewInVertexShader() const override; bool canSelectViewInVertexShader() const override;
void onDirtyUniformBlockBinding(GLuint uniformBlockIndex) override;
private: private:
void generateCaps(gl::Caps *outCaps, void generateCaps(gl::Caps *outCaps,
gl::TextureCapsMap *outTextureCaps, gl::TextureCapsMap *outTextureCaps,
......
...@@ -956,6 +956,9 @@ void StateManager11::syncState(const gl::Context *context, const gl::State::Dirt ...@@ -956,6 +956,9 @@ void StateManager11::syncState(const gl::Context *context, const gl::State::Dirt
// Invalidate the cached index buffer. // Invalidate the cached index buffer.
mIndexBufferIsDirty = true; mIndexBufferIsDirty = true;
break; break;
case gl::State::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS:
invalidateProgramUniformBuffers();
break;
case gl::State::DIRTY_BIT_TEXTURE_BINDINGS: case gl::State::DIRTY_BIT_TEXTURE_BINDINGS:
invalidateTexturesAndSamplers(); invalidateTexturesAndSamplers();
break; break;
...@@ -1937,9 +1940,6 @@ gl::Error StateManager11::updateState(const gl::Context *context, GLenum drawMod ...@@ -1937,9 +1940,6 @@ gl::Error StateManager11::updateState(const gl::Context *context, GLenum drawMod
auto dirtyBitsCopy = mInternalDirtyBits; auto dirtyBitsCopy = mInternalDirtyBits;
mInternalDirtyBits.reset(); mInternalDirtyBits.reset();
// TODO(crbug.com/792966): Workaround for bug in this dirty bit
dirtyBitsCopy.set(DIRTY_BIT_PROGRAM_UNIFORM_BUFFERS);
for (auto dirtyBit : dirtyBitsCopy) for (auto dirtyBit : dirtyBitsCopy)
{ {
switch (dirtyBit) switch (dirtyBit)
...@@ -2864,6 +2864,8 @@ gl::Error StateManager11::syncUniformBuffers(const gl::Context *context, Program ...@@ -2864,6 +2864,8 @@ gl::Error StateManager11::syncUniformBuffers(const gl::Context *context, Program
ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported(); ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported();
mOnConstantBufferDirtyReceiver.reset();
for (size_t bufferIndex = 0; bufferIndex < vertexUniformBuffers.size(); bufferIndex++) for (size_t bufferIndex = 0; bufferIndex < vertexUniformBuffers.size(); bufferIndex++)
{ {
GLint binding = vertexUniformBuffers[bufferIndex]; GLint binding = vertexUniformBuffers[bufferIndex];
...@@ -2916,6 +2918,8 @@ gl::Error StateManager11::syncUniformBuffers(const gl::Context *context, Program ...@@ -2916,6 +2918,8 @@ gl::Error StateManager11::syncUniformBuffers(const gl::Context *context, Program
mCurrentConstantBufferVS[appliedIndex] = constantBuffer->getSerial(); mCurrentConstantBufferVS[appliedIndex] = constantBuffer->getSerial();
mCurrentConstantBufferVSOffset[appliedIndex] = uniformBufferOffset; mCurrentConstantBufferVSOffset[appliedIndex] = uniformBufferOffset;
mCurrentConstantBufferVSSize[appliedIndex] = uniformBufferSize; mCurrentConstantBufferVSSize[appliedIndex] = uniformBufferSize;
mOnConstantBufferDirtyReceiver.bindVS(bufferIndex, bufferStorage);
} }
for (size_t bufferIndex = 0; bufferIndex < fragmentUniformBuffers.size(); bufferIndex++) for (size_t bufferIndex = 0; bufferIndex < fragmentUniformBuffers.size(); bufferIndex++)
...@@ -2969,6 +2973,8 @@ gl::Error StateManager11::syncUniformBuffers(const gl::Context *context, Program ...@@ -2969,6 +2973,8 @@ gl::Error StateManager11::syncUniformBuffers(const gl::Context *context, Program
mCurrentConstantBufferPS[appliedIndex] = constantBuffer->getSerial(); mCurrentConstantBufferPS[appliedIndex] = constantBuffer->getSerial();
mCurrentConstantBufferPSOffset[appliedIndex] = uniformBufferOffset; mCurrentConstantBufferPSOffset[appliedIndex] = uniformBufferOffset;
mCurrentConstantBufferPSSize[appliedIndex] = uniformBufferSize; mCurrentConstantBufferPSSize[appliedIndex] = uniformBufferSize;
mOnConstantBufferDirtyReceiver.bindPS(bufferIndex, bufferStorage);
} }
return gl::NoError(); return gl::NoError();
...@@ -3074,4 +3080,58 @@ void DrawCallVertexParams::ensureResolved() const ...@@ -3074,4 +3080,58 @@ void DrawCallVertexParams::ensureResolved() const
} }
} }
// OnConstantBufferDirtyReceiver implementation.
StateManager11::OnConstantBufferDirtyReceiver::OnConstantBufferDirtyReceiver()
{
for (size_t vsIndex = 0; vsIndex < gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS;
++vsIndex)
{
mBindingsVS.emplace_back(this, vsIndex);
}
for (size_t fsIndex = 0; fsIndex < gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS;
++fsIndex)
{
mBindingsPS.emplace_back(this, fsIndex);
}
}
StateManager11::OnConstantBufferDirtyReceiver::~OnConstantBufferDirtyReceiver()
{
}
void StateManager11::OnConstantBufferDirtyReceiver::signal(size_t messageID,
const gl::Context *context)
{
StateManager11 *stateManager = GetImplAs<Context11>(context)->getRenderer()->getStateManager();
stateManager->invalidateProgramUniformBuffers();
}
void StateManager11::OnConstantBufferDirtyReceiver::bindVS(size_t index, Buffer11 *buffer)
{
ASSERT(buffer);
ASSERT(index < mBindingsVS.size());
mBindingsVS[index].bind(buffer->getDirectBroadcastChannel());
}
void StateManager11::OnConstantBufferDirtyReceiver::bindPS(size_t index, Buffer11 *buffer)
{
ASSERT(buffer);
ASSERT(index < mBindingsPS.size());
mBindingsPS[index].bind(buffer->getDirectBroadcastChannel());
}
void StateManager11::OnConstantBufferDirtyReceiver::reset()
{
for (OnBufferDataDirtyBinding &vsBinding : mBindingsVS)
{
vsBinding.bind(nullptr);
}
for (OnBufferDataDirtyBinding &psBinding : mBindingsPS)
{
psBinding.bind(nullptr);
}
}
} // namespace rx } // namespace rx
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
namespace rx namespace rx
{ {
class Buffer11;
struct RenderTargetDesc; struct RenderTargetDesc;
struct Renderer11DeviceCaps; struct Renderer11DeviceCaps;
...@@ -215,6 +215,9 @@ class StateManager11 final : angle::NonCopyable ...@@ -215,6 +215,9 @@ class StateManager11 final : angle::NonCopyable
// Called by VertexArray11 to trigger attribute translation. // Called by VertexArray11 to trigger attribute translation.
void invalidateVertexAttributeTranslation(); void invalidateVertexAttributeTranslation();
// Called by the Program on Uniform Buffer change. Also called internally.
void invalidateProgramUniformBuffers();
void setRenderTarget(ID3D11RenderTargetView *rtv, ID3D11DepthStencilView *dsv); void setRenderTarget(ID3D11RenderTargetView *rtv, ID3D11DepthStencilView *dsv);
void setRenderTargets(ID3D11RenderTargetView **rtvs, UINT numRtvs, ID3D11DepthStencilView *dsv); void setRenderTargets(ID3D11RenderTargetView **rtvs, UINT numRtvs, ID3D11DepthStencilView *dsv);
...@@ -352,7 +355,6 @@ class StateManager11 final : angle::NonCopyable ...@@ -352,7 +355,6 @@ class StateManager11 final : angle::NonCopyable
void invalidateTexturesAndSamplers(); void invalidateTexturesAndSamplers();
void invalidateDriverUniforms(); void invalidateDriverUniforms();
void invalidateProgramUniforms(); void invalidateProgramUniforms();
void invalidateProgramUniformBuffers();
void invalidateConstantBuffer(unsigned int slot); void invalidateConstantBuffer(unsigned int slot);
// Called by the Framebuffer11 directly. // Called by the Framebuffer11 directly.
...@@ -545,6 +547,24 @@ class StateManager11 final : angle::NonCopyable ...@@ -545,6 +547,24 @@ class StateManager11 final : angle::NonCopyable
FragmentConstantBufferArray<GLintptr> mCurrentConstantBufferPSOffset; FragmentConstantBufferArray<GLintptr> mCurrentConstantBufferPSOffset;
FragmentConstantBufferArray<GLsizeiptr> mCurrentConstantBufferPSSize; FragmentConstantBufferArray<GLsizeiptr> mCurrentConstantBufferPSSize;
class OnConstantBufferDirtyReceiver : public OnBufferDataDirtyReceiver
{
public:
OnConstantBufferDirtyReceiver();
~OnConstantBufferDirtyReceiver() override;
void signal(size_t messageID, const gl::Context *context) override;
void reset();
void bindVS(size_t index, Buffer11 *buffer);
void bindPS(size_t index, Buffer11 *buffer);
private:
std::vector<OnBufferDataDirtyBinding> mBindingsVS;
std::vector<OnBufferDataDirtyBinding> mBindingsPS;
};
OnConstantBufferDirtyReceiver mOnConstantBufferDirtyReceiver;
// Currently applied transform feedback buffers // Currently applied transform feedback buffers
Serial mAppliedTFSerial; Serial mAppliedTFSerial;
......
...@@ -1966,6 +1966,9 @@ void StateManagerGL::syncState(const gl::Context *context, const gl::State::Dirt ...@@ -1966,6 +1966,9 @@ void StateManagerGL::syncState(const gl::Context *context, const gl::State::Dirt
case gl::State::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING: case gl::State::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING:
mProgramStorageBuffersDirty = true; mProgramStorageBuffersDirty = true;
break; break;
case gl::State::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS:
// TODO(jmadll): State update.
break;
case gl::State::DIRTY_BIT_MULTISAMPLING: case gl::State::DIRTY_BIT_MULTISAMPLING:
setMultisamplingStateEnabled(state.isMultisamplingEnabled()); setMultisamplingStateEnabled(state.isMultisamplingEnabled());
break; break;
......
...@@ -718,6 +718,9 @@ void ContextVk::syncState(const gl::Context *context, const gl::State::DirtyBits ...@@ -718,6 +718,9 @@ void ContextVk::syncState(const gl::Context *context, const gl::State::DirtyBits
case gl::State::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING: case gl::State::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING:
WARN() << "DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING unimplemented"; WARN() << "DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING unimplemented";
break; break;
case gl::State::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS:
WARN() << "DIRTY_BIT_UNIFORM_BUFFER_BINDINGS unimplemented";
break;
case gl::State::DIRTY_BIT_MULTISAMPLING: case gl::State::DIRTY_BIT_MULTISAMPLING:
WARN() << "DIRTY_BIT_MULTISAMPLING unimplemented"; WARN() << "DIRTY_BIT_MULTISAMPLING unimplemented";
break; break;
......
...@@ -1390,6 +1390,159 @@ TEST_P(UniformBufferTest, Std140UniformBlockWithRowMajorQualifierOnStruct) ...@@ -1390,6 +1390,159 @@ TEST_P(UniformBufferTest, Std140UniformBlockWithRowMajorQualifierOnStruct)
EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 64, 128, 32), 5); EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 64, 128, 32), 5);
} }
constexpr char kVertexShader[] = R"(#version 300 es
in vec4 a_vertex;
void main()
{
gl_Position = a_vertex;
})";
constexpr char kFragmentShader[] = R"(#version 300 es
precision mediump float;
layout (std140) uniform color_ubo
{
vec4 color;
};
out vec4 fragColor;
void main()
{
fragColor = color;
})";
// Regression test for a dirty bit bug in ANGLE. See http://crbug.com/792966
TEST_P(UniformBufferTest, SimpleBindingChange)
{
ANGLE_GL_PROGRAM(program, kVertexShader, kFragmentShader);
glBindAttribLocation(program, 0, "a_vertex");
glUseProgram(program);
GLint uboIndex = glGetUniformBlockIndex(program, "color_ubo");
std::array<GLfloat, 12> vertices{{-1, -1, 0, 1, -1, 0, -1, 1, 0, 1, 1, 0}};
GLBuffer vertexBuf;
glBindBuffer(GL_ARRAY_BUFFER, vertexBuf);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(GLfloat), vertices.data(),
GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
std::array<GLshort, 12> indexData = {{0, 1, 2, 2, 1, 3, 0, 1, 2, 2, 1, 3}};
GLBuffer indexBuf;
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuf);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexData.size() * sizeof(GLshort), indexData.data(),
GL_STATIC_DRAW);
// Bind a first buffer with red.
GLBuffer uboBuf1;
glBindBufferBase(GL_UNIFORM_BUFFER, 0, uboBuf1);
glBufferData(GL_UNIFORM_BUFFER, sizeof(GLColor32F), &kFloatRed, GL_STATIC_DRAW);
glUniformBlockBinding(program, uboIndex, 0);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);
// Bind a second buffer with green, updating the buffer binding.
GLBuffer uboBuf2;
glBindBufferBase(GL_UNIFORM_BUFFER, 1, uboBuf2);
glBufferData(GL_UNIFORM_BUFFER, sizeof(GLColor32F), &kFloatGreen, GL_STATIC_DRAW);
glUniformBlockBinding(program, uboIndex, 1);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, reinterpret_cast<const GLvoid *>(12));
// Verify we get the second buffer.
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
}
// Regression test for a dirty bit bug in ANGLE. Same as above but for the indexed bindings.
TEST_P(UniformBufferTest, SimpleBufferChange)
{
ANGLE_GL_PROGRAM(program, kVertexShader, kFragmentShader);
glBindAttribLocation(program, 0, "a_vertex");
glUseProgram(program);
GLint uboIndex = glGetUniformBlockIndex(program, "color_ubo");
std::array<GLfloat, 12> vertices{{-1, -1, 0, 1, -1, 0, -1, 1, 0, 1, 1, 0}};
GLBuffer vertexBuf;
glBindBuffer(GL_ARRAY_BUFFER, vertexBuf);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(GLfloat), vertices.data(),
GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
std::array<GLshort, 12> indexData = {{0, 1, 2, 2, 1, 3, 0, 1, 2, 2, 1, 3}};
GLBuffer indexBuf;
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuf);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexData.size() * sizeof(GLshort), indexData.data(),
GL_STATIC_DRAW);
// Bind a first buffer with red.
GLBuffer uboBuf1;
glBindBufferBase(GL_UNIFORM_BUFFER, 0, uboBuf1);
glBufferData(GL_UNIFORM_BUFFER, sizeof(GLColor32F), &kFloatRed, GL_STATIC_DRAW);
glUniformBlockBinding(program, uboIndex, 0);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);
// Bind a second buffer to the same binding point (0). This should set to draw green.
GLBuffer uboBuf2;
glBindBufferBase(GL_UNIFORM_BUFFER, 0, uboBuf2);
glBufferData(GL_UNIFORM_BUFFER, sizeof(GLColor32F), &kFloatGreen, GL_STATIC_DRAW);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, reinterpret_cast<const GLvoid *>(12));
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
}
// Tests a bug in the D3D11 back-end where re-creating the buffer storage should trigger a state
// update in the State Manager class.
TEST_P(UniformBufferTest, DependentBufferChange)
{
ANGLE_GL_PROGRAM(program, kVertexShader, kFragmentShader);
glBindAttribLocation(program, 0, "a_vertex");
glUseProgram(program);
GLint uboIndex = glGetUniformBlockIndex(program, "color_ubo");
std::array<GLfloat, 12> vertices{{-1, -1, 0, 1, -1, 0, -1, 1, 0, 1, 1, 0}};
GLBuffer vertexBuf;
glBindBuffer(GL_ARRAY_BUFFER, vertexBuf);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(GLfloat), vertices.data(),
GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
std::array<GLshort, 6> indexData = {{0, 1, 2, 2, 1, 3}};
GLBuffer indexBuf;
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuf);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexData.size() * sizeof(GLshort), indexData.data(),
GL_STATIC_DRAW);
GLBuffer ubo;
glBindBufferBase(GL_UNIFORM_BUFFER, 0, ubo);
glBufferData(GL_UNIFORM_BUFFER, sizeof(GLColor32F), &kFloatRed, GL_STATIC_DRAW);
glUniformBlockBinding(program, uboIndex, 0);
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, 0);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
// Resize the buffer - triggers a re-allocation in the D3D11 back-end.
std::vector<GLColor32F> bigData(128, kFloatGreen);
glBufferData(GL_UNIFORM_BUFFER, sizeof(GLColor32F) * bigData.size(), bigData.data(),
GL_STATIC_DRAW);
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, 0);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
}
// 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