Commit 99118c1c by jchen10 Committed by Commit Bot

Improve dirtybits for compute

For D3D11 backend, dirtybits are used to sync and update state for compute. For GL backend, mProgramUniformBuffersDirty, mProgramAtomicCounterBuffersDirty, mProgramImagesDirty are newly applied. Bug: angleproject:2814 Change-Id: Ia459ca26705b7c685179d64e0c934535bf16741f Reviewed-on: https://chromium-review.googlesource.com/1215245Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Jie A Chen <jie.a.chen@intel.com>
parent a155bacf
...@@ -517,12 +517,14 @@ void Context::initialize() ...@@ -517,12 +517,14 @@ void Context::initialize()
mBlitDirtyObjects.set(State::DIRTY_OBJECT_READ_FRAMEBUFFER); mBlitDirtyObjects.set(State::DIRTY_OBJECT_READ_FRAMEBUFFER);
mBlitDirtyObjects.set(State::DIRTY_OBJECT_DRAW_FRAMEBUFFER); mBlitDirtyObjects.set(State::DIRTY_OBJECT_DRAW_FRAMEBUFFER);
// TODO(xinghua.cao@intel.com): add other dirty bits and dirty objects.
mComputeDirtyBits.set(State::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING); mComputeDirtyBits.set(State::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING);
mComputeDirtyBits.set(State::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS);
mComputeDirtyBits.set(State::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING);
mComputeDirtyBits.set(State::DIRTY_BIT_PROGRAM_BINDING); mComputeDirtyBits.set(State::DIRTY_BIT_PROGRAM_BINDING);
mComputeDirtyBits.set(State::DIRTY_BIT_PROGRAM_EXECUTABLE); mComputeDirtyBits.set(State::DIRTY_BIT_PROGRAM_EXECUTABLE);
mComputeDirtyBits.set(State::DIRTY_BIT_TEXTURE_BINDINGS); mComputeDirtyBits.set(State::DIRTY_BIT_TEXTURE_BINDINGS);
mComputeDirtyBits.set(State::DIRTY_BIT_SAMPLER_BINDINGS); mComputeDirtyBits.set(State::DIRTY_BIT_SAMPLER_BINDINGS);
mComputeDirtyBits.set(State::DIRTY_BIT_IMAGE_BINDINGS);
mComputeDirtyBits.set(State::DIRTY_BIT_DISPATCH_INDIRECT_BUFFER_BINDING); mComputeDirtyBits.set(State::DIRTY_BIT_DISPATCH_INDIRECT_BUFFER_BINDING);
mComputeDirtyObjects.set(State::DIRTY_OBJECT_PROGRAM_TEXTURES); mComputeDirtyObjects.set(State::DIRTY_OBJECT_PROGRAM_TEXTURES);
mComputeDirtyObjects.set(State::DIRTY_OBJECT_PROGRAM); mComputeDirtyObjects.set(State::DIRTY_OBJECT_PROGRAM);
......
...@@ -1467,6 +1467,14 @@ void State::setBufferBinding(const Context *context, BufferBinding target, Buffe ...@@ -1467,6 +1467,14 @@ void State::setBufferBinding(const Context *context, BufferBinding target, Buffe
UpdateNonTFBufferBinding(context, &mBoundBuffers[target], buffer); UpdateNonTFBufferBinding(context, &mBoundBuffers[target], buffer);
mDirtyBits.set(DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING); mDirtyBits.set(DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING);
break; break;
case BufferBinding::Uniform:
UpdateBufferBinding(context, &mBoundBuffers[target], buffer, target);
mDirtyBits.set(DIRTY_BIT_UNIFORM_BUFFER_BINDINGS);
break;
case BufferBinding::AtomicCounter:
UpdateBufferBinding(context, &mBoundBuffers[target], buffer, target);
mDirtyBits.set(DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING);
break;
default: default:
UpdateBufferBinding(context, &mBoundBuffers[target], buffer, target); UpdateBufferBinding(context, &mBoundBuffers[target], buffer, target);
break; break;
...@@ -1491,7 +1499,6 @@ void State::setIndexedBufferBinding(const Context *context, ...@@ -1491,7 +1499,6 @@ void State::setIndexedBufferBinding(const Context *context,
case BufferBinding::Uniform: case BufferBinding::Uniform:
UpdateIndexedBufferBinding(context, &mUniformBuffers[index], buffer, target, offset, UpdateIndexedBufferBinding(context, &mUniformBuffers[index], buffer, target, offset,
size); size);
mDirtyBits.set(DIRTY_BIT_UNIFORM_BUFFER_BINDINGS);
break; break;
case BufferBinding::AtomicCounter: case BufferBinding::AtomicCounter:
UpdateIndexedBufferBinding(context, &mAtomicCounterBuffers[index], buffer, target, UpdateIndexedBufferBinding(context, &mAtomicCounterBuffers[index], buffer, target,
...@@ -2872,6 +2879,7 @@ void State::setImageUnit(const Context *context, ...@@ -2872,6 +2879,7 @@ void State::setImageUnit(const Context *context,
mImageUnits[unit].layer = layer; mImageUnits[unit].layer = layer;
mImageUnits[unit].access = access; mImageUnits[unit].access = access;
mImageUnits[unit].format = format; mImageUnits[unit].format = format;
mDirtyBits.set(DIRTY_BIT_IMAGE_BINDINGS);
} }
const ImageUnit &State::getImageUnit(size_t unit) const const ImageUnit &State::getImageUnit(size_t unit) const
......
...@@ -413,6 +413,7 @@ class State : angle::NonCopyable ...@@ -413,6 +413,7 @@ class State : 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,
DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING,
// TODO(jmadill): Fine-grained dirty bits for each index. // TODO(jmadill): Fine-grained dirty bits for each index.
DIRTY_BIT_UNIFORM_BUFFER_BINDINGS, DIRTY_BIT_UNIFORM_BUFFER_BINDINGS,
DIRTY_BIT_PROGRAM_BINDING, DIRTY_BIT_PROGRAM_BINDING,
...@@ -420,6 +421,7 @@ class State : angle::NonCopyable ...@@ -420,6 +421,7 @@ class State : angle::NonCopyable
// TODO(jmadill): Fine-grained dirty bits for each texture/sampler. // TODO(jmadill): Fine-grained dirty bits for each texture/sampler.
DIRTY_BIT_TEXTURE_BINDINGS, DIRTY_BIT_TEXTURE_BINDINGS,
DIRTY_BIT_SAMPLER_BINDINGS, DIRTY_BIT_SAMPLER_BINDINGS,
DIRTY_BIT_IMAGE_BINDINGS,
DIRTY_BIT_TRANSFORM_FEEDBACK_BINDING, DIRTY_BIT_TRANSFORM_FEEDBACK_BINDING,
DIRTY_BIT_MULTISAMPLING, DIRTY_BIT_MULTISAMPLING,
DIRTY_BIT_SAMPLE_ALPHA_TO_ONE, DIRTY_BIT_SAMPLE_ALPHA_TO_ONE,
......
...@@ -3663,31 +3663,12 @@ gl::DebugAnnotator *Renderer11::getAnnotator() ...@@ -3663,31 +3663,12 @@ gl::DebugAnnotator *Renderer11::getAnnotator()
return mAnnotator; return mAnnotator;
} }
angle::Result Renderer11::applyComputeShader(const gl::Context *context)
{
ANGLE_TRY(ensureHLSLCompilerInitialized(context));
const auto &glState = context->getGLState();
ProgramD3D *programD3D = GetImplAs<ProgramD3D>(glState.getProgram());
ShaderExecutableD3D *computeExe = nullptr;
ANGLE_TRY(programD3D->getComputeExecutable(&computeExe));
ASSERT(computeExe != nullptr);
mStateManager.setComputeShader(&GetAs<ShaderExecutable11>(computeExe)->getComputeShader());
ANGLE_TRY(mStateManager.applyComputeUniforms(context, programD3D));
return angle::Result::Continue();
}
angle::Result Renderer11::dispatchCompute(const gl::Context *context, angle::Result Renderer11::dispatchCompute(const gl::Context *context,
GLuint numGroupsX, GLuint numGroupsX,
GLuint numGroupsY, GLuint numGroupsY,
GLuint numGroupsZ) GLuint numGroupsZ)
{ {
ANGLE_TRY(mStateManager.updateStateForCompute(context, numGroupsX, numGroupsY, numGroupsZ)); ANGLE_TRY(mStateManager.updateStateForCompute(context, numGroupsX, numGroupsY, numGroupsZ));
ANGLE_TRY(applyComputeShader(context));
mDeviceContext->Dispatch(numGroupsX, numGroupsY, numGroupsZ); mDeviceContext->Dispatch(numGroupsX, numGroupsY, numGroupsZ);
return angle::Result::Continue(); return angle::Result::Continue();
...@@ -3703,13 +3684,11 @@ angle::Result Renderer11::dispatchComputeIndirect(const gl::Context *context, GL ...@@ -3703,13 +3684,11 @@ angle::Result Renderer11::dispatchComputeIndirect(const gl::Context *context, GL
// TODO(jie.a.chen@intel.com): num_groups_x,y,z have to be written into the driver constant // TODO(jie.a.chen@intel.com): num_groups_x,y,z have to be written into the driver constant
// buffer for the built-in variable gl_NumWorkGroups. There is an opportunity for optimization // buffer for the built-in variable gl_NumWorkGroups. There is an opportunity for optimization
// to use GPU->GPU copy instead. // to use GPU->GPU copy instead.
// https://bugs.chromium.org/p/angleproject/issues/detail?id=2807 // http://anglebug.com/2807
ANGLE_TRY(storage->getData(context, &bufferData)); ANGLE_TRY(storage->getData(context, &bufferData));
const GLuint *groups = reinterpret_cast<const GLuint *>(bufferData + indirect); const GLuint *groups = reinterpret_cast<const GLuint *>(bufferData + indirect);
ANGLE_TRY(mStateManager.updateStateForCompute(context, groups[0], groups[1], groups[2])); ANGLE_TRY(mStateManager.updateStateForCompute(context, groups[0], groups[1], groups[2]));
ANGLE_TRY(applyComputeShader(context));
ID3D11Buffer *buffer = nullptr; ID3D11Buffer *buffer = nullptr;
ANGLE_TRY(storage->getBuffer(context, BUFFER_USAGE_INDIRECT, &buffer)); ANGLE_TRY(storage->getBuffer(context, BUFFER_USAGE_INDIRECT, &buffer));
......
...@@ -418,7 +418,6 @@ class Renderer11 : public RendererD3D ...@@ -418,7 +418,6 @@ class Renderer11 : public RendererD3D
GLuint numGroupsY, GLuint numGroupsY,
GLuint numGroupsZ); GLuint numGroupsZ);
angle::Result dispatchComputeIndirect(const gl::Context *context, GLintptr indirect); angle::Result dispatchComputeIndirect(const gl::Context *context, GLintptr indirect);
angle::Result applyComputeShader(const gl::Context *context);
angle::Result createStagingTexture(const gl::Context *context, angle::Result createStagingTexture(const gl::Context *context,
ResourceType textureType, ResourceType textureType,
......
...@@ -608,6 +608,14 @@ StateManager11::StateManager11(Renderer11 *renderer) ...@@ -608,6 +608,14 @@ StateManager11::StateManager11(Renderer11 *renderer)
// Start with all internal dirty bits set. // Start with all internal dirty bits set.
mInternalDirtyBits.set(); mInternalDirtyBits.set();
mComputeDirtyBitsMask.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE);
mComputeDirtyBitsMask.set(DIRTY_BIT_PROGRAM_UNIFORMS);
mComputeDirtyBitsMask.set(DIRTY_BIT_DRIVER_UNIFORMS);
mComputeDirtyBitsMask.set(DIRTY_BIT_PROGRAM_UNIFORM_BUFFERS);
mComputeDirtyBitsMask.set(DIRTY_BIT_PROGRAM_ATOMIC_COUNTER_BUFFERS);
mComputeDirtyBitsMask.set(DIRTY_BIT_PROGRAM_SHADER_STORAGE_BUFFERS);
mComputeDirtyBitsMask.set(DIRTY_BIT_SHADERS);
// Initially all current value attributes must be updated on first use. // Initially all current value attributes must be updated on first use.
mDirtyCurrentValueAttribs.set(); mDirtyCurrentValueAttribs.set();
...@@ -722,17 +730,47 @@ angle::Result StateManager11::updateStateForCompute(const gl::Context *context, ...@@ -722,17 +730,47 @@ angle::Result StateManager11::updateStateForCompute(const gl::Context *context,
{ {
mShaderConstants.setComputeWorkGroups(numGroupsX, numGroupsY, numGroupsZ); mShaderConstants.setComputeWorkGroups(numGroupsX, numGroupsY, numGroupsZ);
// TODO(jmadill): Use dirty bits. if (mProgramD3D->updateSamplerMapping() == ProgramD3D::SamplerMapping::WasDirty)
mProgramD3D->updateSamplerMapping(); {
invalidateTexturesAndSamplers();
// TODO(jmadill): Use dirty bits. }
ANGLE_TRY(generateSwizzlesForShader(context, gl::ShaderType::Compute));
// TODO(jmadill): More complete implementation. if (mDirtySwizzles)
ANGLE_TRY(syncTexturesForCompute(context)); {
ANGLE_TRY(generateSwizzlesForShader(context, gl::ShaderType::Compute));
mDirtySwizzles = false;
}
// TODO(Xinghua): Use dirty bits. auto dirtyBitsCopy = mInternalDirtyBits & mComputeDirtyBitsMask;
ANGLE_TRY(syncUniformBuffers(context)); mInternalDirtyBits &= ~mComputeDirtyBitsMask;
for (auto dirtyBit : dirtyBitsCopy)
{
switch (dirtyBit)
{
case DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE:
ANGLE_TRY(syncTexturesForCompute(context));
break;
case DIRTY_BIT_PROGRAM_UNIFORMS:
case DIRTY_BIT_DRIVER_UNIFORMS:
ANGLE_TRY(applyComputeUniforms(context, mProgramD3D));
break;
case DIRTY_BIT_PROGRAM_UNIFORM_BUFFERS:
ANGLE_TRY(syncUniformBuffers(context));
break;
case DIRTY_BIT_PROGRAM_ATOMIC_COUNTER_BUFFERS:
ANGLE_TRY(syncAtomicCounterBuffers(context));
break;
case DIRTY_BIT_PROGRAM_SHADER_STORAGE_BUFFERS:
ANGLE_TRY(syncShaderStorageBuffers(context));
break;
case DIRTY_BIT_SHADERS:
ANGLE_TRY(syncProgramForCompute(context));
break;
default:
UNREACHABLE();
break;
}
}
return angle::Result::Continue(); return angle::Result::Continue();
} }
...@@ -989,12 +1027,25 @@ void StateManager11::syncState(const gl::Context *context, const gl::State::Dirt ...@@ -989,12 +1027,25 @@ void StateManager11::syncState(const gl::Context *context, const gl::State::Dirt
case gl::State::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS: case gl::State::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS:
invalidateProgramUniformBuffers(); invalidateProgramUniformBuffers();
break; break;
case gl::State::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING:
invalidateProgramAtomicCounterBuffers();
break;
case gl::State::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING:
invalidateProgramShaderStorageBuffers();
break;
case gl::State::DIRTY_BIT_TEXTURE_BINDINGS: case gl::State::DIRTY_BIT_TEXTURE_BINDINGS:
invalidateTexturesAndSamplers(); invalidateTexturesAndSamplers();
break; break;
case gl::State::DIRTY_BIT_SAMPLER_BINDINGS: case gl::State::DIRTY_BIT_SAMPLER_BINDINGS:
invalidateTexturesAndSamplers(); invalidateTexturesAndSamplers();
break; break;
case gl::State::DIRTY_BIT_IMAGE_BINDINGS:
// TODO(jie.a.chen@intel.com): More fine-grained update.
// Currently images are updated together with textures and samplers. It would be
// better to update them separately.
// http://anglebug.com/2814
invalidateTexturesAndSamplers();
break;
case gl::State::DIRTY_BIT_TRANSFORM_FEEDBACK_BINDING: case gl::State::DIRTY_BIT_TRANSFORM_FEEDBACK_BINDING:
invalidateTransformFeedback(); invalidateTransformFeedback();
break; break;
...@@ -1010,6 +1061,8 @@ void StateManager11::syncState(const gl::Context *context, const gl::State::Dirt ...@@ -1010,6 +1061,8 @@ void StateManager11::syncState(const gl::Context *context, const gl::State::Dirt
invalidateTexturesAndSamplers(); invalidateTexturesAndSamplers();
invalidateProgramUniforms(); invalidateProgramUniforms();
invalidateProgramUniformBuffers(); invalidateProgramUniformBuffers();
invalidateProgramAtomicCounterBuffers();
invalidateProgramShaderStorageBuffers();
invalidateDriverUniforms(); invalidateDriverUniforms();
// If ANGLE_multiview is enabled, the attribute divisor has to be updated for each // If ANGLE_multiview is enabled, the attribute divisor has to be updated for each
// binding. When using compute, there could be no vertex array. // binding. When using compute, there could be no vertex array.
...@@ -1473,6 +1526,16 @@ void StateManager11::invalidateProgramUniformBuffers() ...@@ -1473,6 +1526,16 @@ void StateManager11::invalidateProgramUniformBuffers()
mInternalDirtyBits.set(DIRTY_BIT_PROGRAM_UNIFORM_BUFFERS); mInternalDirtyBits.set(DIRTY_BIT_PROGRAM_UNIFORM_BUFFERS);
} }
void StateManager11::invalidateProgramAtomicCounterBuffers()
{
mInternalDirtyBits.set(DIRTY_BIT_PROGRAM_ATOMIC_COUNTER_BUFFERS);
}
void StateManager11::invalidateProgramShaderStorageBuffers()
{
mInternalDirtyBits.set(DIRTY_BIT_PROGRAM_SHADER_STORAGE_BUFFERS);
}
void StateManager11::invalidateConstantBuffer(unsigned int slot) void StateManager11::invalidateConstantBuffer(unsigned int slot)
{ {
if (slot == d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER) if (slot == d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER)
...@@ -2085,6 +2148,12 @@ angle::Result StateManager11::updateState(const gl::Context *context, ...@@ -2085,6 +2148,12 @@ angle::Result StateManager11::updateState(const gl::Context *context,
case DIRTY_BIT_PROGRAM_UNIFORM_BUFFERS: case DIRTY_BIT_PROGRAM_UNIFORM_BUFFERS:
ANGLE_TRY(syncUniformBuffers(context)); ANGLE_TRY(syncUniformBuffers(context));
break; break;
case DIRTY_BIT_PROGRAM_ATOMIC_COUNTER_BUFFERS:
// TODO(jie.a.chen@intel.com): http://anglebug.com/1729
break;
case DIRTY_BIT_PROGRAM_SHADER_STORAGE_BUFFERS:
// TODO(jie.a.chen@intel.com): http://anglebug.com/1951
break;
case DIRTY_BIT_SHADERS: case DIRTY_BIT_SHADERS:
ANGLE_TRY(syncProgram(context, drawCallParams.mode())); ANGLE_TRY(syncProgram(context, drawCallParams.mode()));
break; break;
...@@ -2211,7 +2280,7 @@ void StateManager11::setComputeShader(const d3d11::ComputeShader *shader) ...@@ -2211,7 +2280,7 @@ void StateManager11::setComputeShader(const d3d11::ComputeShader *shader)
ID3D11ComputeShader *appliedShader = shader ? shader->get() : nullptr; ID3D11ComputeShader *appliedShader = shader ? shader->get() : nullptr;
mRenderer->getDeviceContext()->CSSetShader(appliedShader, nullptr, 0); mRenderer->getDeviceContext()->CSSetShader(appliedShader, nullptr, 0);
mAppliedShaders[gl::ShaderType::Compute] = serial; mAppliedShaders[gl::ShaderType::Compute] = serial;
// TODO(jmadill): Dirty bits for compute. invalidateShaders();
} }
} }
...@@ -2699,6 +2768,18 @@ angle::Result StateManager11::syncProgram(const gl::Context *context, gl::Primit ...@@ -2699,6 +2768,18 @@ angle::Result StateManager11::syncProgram(const gl::Context *context, gl::Primit
return angle::Result::Continue(); return angle::Result::Continue();
} }
angle::Result StateManager11::syncProgramForCompute(const gl::Context *context)
{
ShaderExecutableD3D *computeExe = nullptr;
ANGLE_TRY(mProgramD3D->getComputeExecutable(&computeExe));
ASSERT(computeExe != nullptr);
setComputeShader(&GetAs<ShaderExecutable11>(computeExe)->getComputeShader());
// Explicitly clear the shaders dirty bit.
mInternalDirtyBits.reset(DIRTY_BIT_SHADERS);
return angle::Result::Continue();
}
angle::Result StateManager11::syncVertexBuffersAndInputLayout( angle::Result StateManager11::syncVertexBuffersAndInputLayout(
const gl::Context *context, const gl::Context *context,
const gl::DrawCallParams &drawCallParams) const gl::DrawCallParams &drawCallParams)
...@@ -3391,6 +3472,18 @@ angle::Result StateManager11::syncUniformBuffers(const gl::Context *context) ...@@ -3391,6 +3472,18 @@ angle::Result StateManager11::syncUniformBuffers(const gl::Context *context)
return angle::Result::Continue(); return angle::Result::Continue();
} }
angle::Result StateManager11::syncAtomicCounterBuffers(const gl::Context *context)
{
// TODO(jie.a.chen@intel.com): http://anglebug.com/1729
return angle::Result::Continue();
}
angle::Result StateManager11::syncShaderStorageBuffers(const gl::Context *context)
{
// TODO(jie.a.chen@intel.com): http://anglebug.com/1951
return angle::Result::Continue();
}
angle::Result StateManager11::syncTransformFeedbackBuffers(const gl::Context *context) angle::Result StateManager11::syncTransformFeedbackBuffers(const gl::Context *context)
{ {
const auto &glState = context->getGLState(); const auto &glState = context->getGLState();
......
...@@ -287,6 +287,7 @@ class StateManager11 final : angle::NonCopyable ...@@ -287,6 +287,7 @@ class StateManager11 final : angle::NonCopyable
angle::Result syncFramebuffer(const gl::Context *context); angle::Result syncFramebuffer(const gl::Context *context);
angle::Result syncProgram(const gl::Context *context, gl::PrimitiveMode drawMode); angle::Result syncProgram(const gl::Context *context, gl::PrimitiveMode drawMode);
angle::Result syncProgramForCompute(const gl::Context *context);
angle::Result syncTextures(const gl::Context *context); angle::Result syncTextures(const gl::Context *context);
angle::Result applyTexturesForSRVs(const gl::Context *context, gl::ShaderType shaderType); angle::Result applyTexturesForSRVs(const gl::Context *context, gl::ShaderType shaderType);
...@@ -331,6 +332,8 @@ class StateManager11 final : angle::NonCopyable ...@@ -331,6 +332,8 @@ class StateManager11 final : angle::NonCopyable
angle::Result syncUniformBuffers(const gl::Context *context); angle::Result syncUniformBuffers(const gl::Context *context);
angle::Result syncUniformBuffersForShader(const gl::Context *context, angle::Result syncUniformBuffersForShader(const gl::Context *context,
gl::ShaderType shaderType); gl::ShaderType shaderType);
angle::Result syncAtomicCounterBuffers(const gl::Context *context);
angle::Result syncShaderStorageBuffers(const gl::Context *context);
angle::Result syncTransformFeedbackBuffers(const gl::Context *context); angle::Result syncTransformFeedbackBuffers(const gl::Context *context);
// These are currently only called internally. // These are currently only called internally.
...@@ -338,6 +341,8 @@ class StateManager11 final : angle::NonCopyable ...@@ -338,6 +341,8 @@ class StateManager11 final : angle::NonCopyable
void invalidateDriverUniforms(); void invalidateDriverUniforms();
void invalidateProgramUniforms(); void invalidateProgramUniforms();
void invalidateConstantBuffer(unsigned int slot); void invalidateConstantBuffer(unsigned int slot);
void invalidateProgramAtomicCounterBuffers();
void invalidateProgramShaderStorageBuffers();
// Called by the Framebuffer11 directly. // Called by the Framebuffer11 directly.
void processFramebufferInvalidation(const gl::Context *context); void processFramebufferInvalidation(const gl::Context *context);
...@@ -375,6 +380,8 @@ class StateManager11 final : angle::NonCopyable ...@@ -375,6 +380,8 @@ class StateManager11 final : angle::NonCopyable
DIRTY_BIT_PROGRAM_UNIFORMS, DIRTY_BIT_PROGRAM_UNIFORMS,
DIRTY_BIT_DRIVER_UNIFORMS, DIRTY_BIT_DRIVER_UNIFORMS,
DIRTY_BIT_PROGRAM_UNIFORM_BUFFERS, DIRTY_BIT_PROGRAM_UNIFORM_BUFFERS,
DIRTY_BIT_PROGRAM_ATOMIC_COUNTER_BUFFERS,
DIRTY_BIT_PROGRAM_SHADER_STORAGE_BUFFERS,
DIRTY_BIT_SHADERS, DIRTY_BIT_SHADERS,
DIRTY_BIT_CURRENT_VALUE_ATTRIBS, DIRTY_BIT_CURRENT_VALUE_ATTRIBS,
DIRTY_BIT_TRANSFORM_FEEDBACK, DIRTY_BIT_TRANSFORM_FEEDBACK,
...@@ -390,6 +397,7 @@ class StateManager11 final : angle::NonCopyable ...@@ -390,6 +397,7 @@ class StateManager11 final : angle::NonCopyable
// Internal dirty bits. // Internal dirty bits.
DirtyBits mInternalDirtyBits; DirtyBits mInternalDirtyBits;
DirtyBits mComputeDirtyBitsMask;
// Blend State // Blend State
gl::BlendState mCurBlendState; gl::BlendState mCurBlendState;
......
...@@ -164,7 +164,10 @@ StateManagerGL::StateManagerGL(const FunctionsGL *functions, ...@@ -164,7 +164,10 @@ StateManagerGL::StateManagerGL(const FunctionsGL *functions,
mLocalDirtyBits(), mLocalDirtyBits(),
mMultiviewDirtyBits(), mMultiviewDirtyBits(),
mProgramTexturesAndSamplersDirty(true), mProgramTexturesAndSamplersDirty(true),
mProgramStorageBuffersDirty(true) mProgramStorageBuffersDirty(true),
mProgramUniformBuffersDirty(true),
mProgramAtomicCounterBuffersDirty(true),
mProgramImagesDirty(true)
{ {
ASSERT(mFunctions); ASSERT(mFunctions);
ASSERT(extensions.maxViews >= 1u); ASSERT(extensions.maxViews >= 1u);
...@@ -865,30 +868,10 @@ gl::Error StateManagerGL::onMakeCurrent(const gl::Context *context) ...@@ -865,30 +868,10 @@ gl::Error StateManagerGL::onMakeCurrent(const gl::Context *context)
void StateManagerGL::setGenericShaderState(const gl::Context *context) void StateManagerGL::setGenericShaderState(const gl::Context *context)
{ {
const gl::State &glState = context->getGLState(); if (mProgramUniformBuffersDirty)
// Sync the current program state
const gl::Program *program = glState.getProgram();
for (size_t uniformBlockIndex = 0; uniformBlockIndex < program->getActiveUniformBlockCount();
uniformBlockIndex++)
{ {
GLuint binding = program->getUniformBlockBinding(static_cast<GLuint>(uniformBlockIndex)); updateProgramUniformBufferBindings(context);
const auto &uniformBuffer = glState.getIndexedUniformBuffer(binding); mProgramUniformBuffersDirty = false;
if (uniformBuffer.get() != nullptr)
{
BufferGL *bufferGL = GetImplAs<BufferGL>(uniformBuffer.get());
if (uniformBuffer.getSize() == 0)
{
bindBufferBase(gl::BufferBinding::Uniform, binding, bufferGL->getBufferID());
}
else
{
bindBufferRange(gl::BufferBinding::Uniform, binding, bufferGL->getBufferID(),
uniformBuffer.getOffset(), uniformBuffer.getSize());
}
}
} }
if (mProgramTexturesAndSamplersDirty) if (mProgramTexturesAndSamplersDirty)
...@@ -903,45 +886,16 @@ void StateManagerGL::setGenericShaderState(const gl::Context *context) ...@@ -903,45 +886,16 @@ void StateManagerGL::setGenericShaderState(const gl::Context *context)
mProgramStorageBuffersDirty = false; mProgramStorageBuffersDirty = false;
} }
// TODO(xinghua.cao@intel.com): Track image units state with dirty bits to if (mProgramImagesDirty)
// avoid update every draw call.
ASSERT(context->getClientVersion() >= gl::ES_3_1 || program->getImageBindings().size() == 0);
for (size_t imageUnitIndex : program->getActiveImagesMask())
{ {
const gl::ImageUnit &imageUnit = glState.getImageUnit(imageUnitIndex); updateProgramImageBindings(context);
const TextureGL *textureGL = SafeGetImplAs<TextureGL>(imageUnit.texture.get()); mProgramImagesDirty = false;
if (textureGL)
{
bindImageTexture(imageUnitIndex, textureGL->getTextureID(), imageUnit.level,
imageUnit.layered, imageUnit.layer, imageUnit.access,
imageUnit.format);
}
else
{
bindImageTexture(imageUnitIndex, 0, imageUnit.level, imageUnit.layered, imageUnit.layer,
imageUnit.access, imageUnit.format);
}
} }
for (const auto &atomicCounterBuffer : program->getState().getAtomicCounterBuffers()) if (mProgramAtomicCounterBuffersDirty)
{ {
GLuint binding = atomicCounterBuffer.binding; updateProgramAtomicCounterBufferBindings(context);
const auto &buffer = glState.getIndexedAtomicCounterBuffer(binding); mProgramAtomicCounterBuffersDirty = false;
if (buffer.get() != nullptr)
{
BufferGL *bufferGL = GetImplAs<BufferGL>(buffer.get());
if (buffer.getSize() == 0)
{
bindBufferBase(gl::BufferBinding::AtomicCounter, binding, bufferGL->getBufferID());
}
else
{
bindBufferRange(gl::BufferBinding::AtomicCounter, binding, bufferGL->getBufferID(),
buffer.getOffset(), buffer.getSize());
}
}
} }
} }
...@@ -1022,6 +976,85 @@ void StateManagerGL::updateProgramStorageBufferBindings(const gl::Context *conte ...@@ -1022,6 +976,85 @@ void StateManagerGL::updateProgramStorageBufferBindings(const gl::Context *conte
} }
} }
void StateManagerGL::updateProgramUniformBufferBindings(const gl::Context *context)
{
// Sync the current program state
const gl::State &glState = context->getGLState();
const gl::Program *program = glState.getProgram();
for (size_t uniformBlockIndex = 0; uniformBlockIndex < program->getActiveUniformBlockCount();
uniformBlockIndex++)
{
GLuint binding = program->getUniformBlockBinding(static_cast<GLuint>(uniformBlockIndex));
const auto &uniformBuffer = glState.getIndexedUniformBuffer(binding);
if (uniformBuffer.get() != nullptr)
{
BufferGL *bufferGL = GetImplAs<BufferGL>(uniformBuffer.get());
if (uniformBuffer.getSize() == 0)
{
bindBufferBase(gl::BufferBinding::Uniform, binding, bufferGL->getBufferID());
}
else
{
bindBufferRange(gl::BufferBinding::Uniform, binding, bufferGL->getBufferID(),
uniformBuffer.getOffset(), uniformBuffer.getSize());
}
}
}
}
void StateManagerGL::updateProgramAtomicCounterBufferBindings(const gl::Context *context)
{
const gl::State &glState = context->getGLState();
const gl::Program *program = glState.getProgram();
for (const auto &atomicCounterBuffer : program->getState().getAtomicCounterBuffers())
{
GLuint binding = atomicCounterBuffer.binding;
const auto &buffer = glState.getIndexedAtomicCounterBuffer(binding);
if (buffer.get() != nullptr)
{
BufferGL *bufferGL = GetImplAs<BufferGL>(buffer.get());
if (buffer.getSize() == 0)
{
bindBufferBase(gl::BufferBinding::AtomicCounter, binding, bufferGL->getBufferID());
}
else
{
bindBufferRange(gl::BufferBinding::AtomicCounter, binding, bufferGL->getBufferID(),
buffer.getOffset(), buffer.getSize());
}
}
}
}
void StateManagerGL::updateProgramImageBindings(const gl::Context *context)
{
const gl::State &glState = context->getGLState();
const gl::Program *program = glState.getProgram();
ASSERT(context->getClientVersion() >= gl::ES_3_1 || program->getImageBindings().size() == 0);
for (size_t imageUnitIndex : program->getActiveImagesMask())
{
const gl::ImageUnit &imageUnit = glState.getImageUnit(imageUnitIndex);
const TextureGL *textureGL = SafeGetImplAs<TextureGL>(imageUnit.texture.get());
if (textureGL)
{
bindImageTexture(imageUnitIndex, textureGL->getTextureID(), imageUnit.level,
imageUnit.layered, imageUnit.layer, imageUnit.access,
imageUnit.format);
}
else
{
bindImageTexture(imageUnitIndex, 0, imageUnit.level, imageUnit.layered, imageUnit.layer,
imageUnit.access, imageUnit.format);
}
}
}
gl::Error StateManagerGL::setGenericDrawState(const gl::Context *context) gl::Error StateManagerGL::setGenericDrawState(const gl::Context *context)
{ {
setGenericShaderState(context); setGenericShaderState(context);
...@@ -1955,8 +1988,6 @@ void StateManagerGL::syncState(const gl::Context *context, const gl::State::Dirt ...@@ -1955,8 +1988,6 @@ void StateManagerGL::syncState(const gl::Context *context, const gl::State::Dirt
break; break;
case gl::State::DIRTY_BIT_PROGRAM_BINDING: case gl::State::DIRTY_BIT_PROGRAM_BINDING:
{ {
mProgramTexturesAndSamplersDirty = true;
mProgramStorageBuffersDirty = true;
gl::Program *program = state.getProgram(); gl::Program *program = state.getProgram();
if (program != nullptr) if (program != nullptr)
{ {
...@@ -1970,12 +2001,18 @@ void StateManagerGL::syncState(const gl::Context *context, const gl::State::Dirt ...@@ -1970,12 +2001,18 @@ void StateManagerGL::syncState(const gl::Context *context, const gl::State::Dirt
case gl::State::DIRTY_BIT_SAMPLER_BINDINGS: case gl::State::DIRTY_BIT_SAMPLER_BINDINGS:
mProgramTexturesAndSamplersDirty = true; mProgramTexturesAndSamplersDirty = true;
break; break;
case gl::State::DIRTY_BIT_IMAGE_BINDINGS:
mProgramImagesDirty = true;
break;
case gl::State::DIRTY_BIT_TRANSFORM_FEEDBACK_BINDING: case gl::State::DIRTY_BIT_TRANSFORM_FEEDBACK_BINDING:
syncTransformFeedbackState(context); syncTransformFeedbackState(context);
break; break;
case gl::State::DIRTY_BIT_PROGRAM_EXECUTABLE: case gl::State::DIRTY_BIT_PROGRAM_EXECUTABLE:
mProgramTexturesAndSamplersDirty = true; mProgramTexturesAndSamplersDirty = true;
mProgramImagesDirty = true;
mProgramStorageBuffersDirty = true; mProgramStorageBuffersDirty = true;
mProgramUniformBuffersDirty = true;
mProgramAtomicCounterBuffersDirty = true;
propagateProgramToVAO(state.getProgram(), propagateProgramToVAO(state.getProgram(),
GetImplAs<VertexArrayGL>(state.getVertexArray())); GetImplAs<VertexArrayGL>(state.getVertexArray()));
updateMultiviewBaseViewLayerIndexUniform( updateMultiviewBaseViewLayerIndexUniform(
...@@ -1986,7 +2023,10 @@ void StateManagerGL::syncState(const gl::Context *context, const gl::State::Dirt ...@@ -1986,7 +2023,10 @@ void StateManagerGL::syncState(const gl::Context *context, const gl::State::Dirt
mProgramStorageBuffersDirty = true; mProgramStorageBuffersDirty = true;
break; break;
case gl::State::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS: case gl::State::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS:
// TODO(jmadll): State update. mProgramUniformBuffersDirty = true;
break;
case gl::State::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING:
mProgramAtomicCounterBuffersDirty = true;
break; break;
case gl::State::DIRTY_BIT_MULTISAMPLING: case gl::State::DIRTY_BIT_MULTISAMPLING:
setMultisamplingStateEnabled(state.isMultisamplingEnabled()); setMultisamplingStateEnabled(state.isMultisamplingEnabled());
......
...@@ -197,6 +197,9 @@ class StateManagerGL final : angle::NonCopyable ...@@ -197,6 +197,9 @@ class StateManagerGL final : angle::NonCopyable
void updateProgramTextureAndSamplerBindings(const gl::Context *context); void updateProgramTextureAndSamplerBindings(const gl::Context *context);
void updateProgramStorageBufferBindings(const gl::Context *context); void updateProgramStorageBufferBindings(const gl::Context *context);
void updateProgramUniformBufferBindings(const gl::Context *context);
void updateProgramAtomicCounterBufferBindings(const gl::Context *context);
void updateProgramImageBindings(const gl::Context *context);
void updateDispatchIndirectBufferBinding(const gl::Context *context); void updateDispatchIndirectBufferBinding(const gl::Context *context);
void updateDrawIndirectBufferBinding(const gl::Context *context); void updateDrawIndirectBufferBinding(const gl::Context *context);
...@@ -363,6 +366,9 @@ class StateManagerGL final : angle::NonCopyable ...@@ -363,6 +366,9 @@ class StateManagerGL final : angle::NonCopyable
bool mProgramTexturesAndSamplersDirty; bool mProgramTexturesAndSamplersDirty;
bool mProgramStorageBuffersDirty; bool mProgramStorageBuffersDirty;
bool mProgramUniformBuffersDirty;
bool mProgramAtomicCounterBuffersDirty;
bool mProgramImagesDirty;
}; };
} }
......
...@@ -847,6 +847,10 @@ gl::Error ContextVk::syncState(const gl::Context *context, const gl::State::Dirt ...@@ -847,6 +847,10 @@ gl::Error ContextVk::syncState(const gl::Context *context, const gl::State::Dirt
break; break;
case gl::State::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS: case gl::State::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS:
break; break;
case gl::State::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING:
break;
case gl::State::DIRTY_BIT_IMAGE_BINDINGS:
break;
case gl::State::DIRTY_BIT_MULTISAMPLING: case gl::State::DIRTY_BIT_MULTISAMPLING:
break; break;
case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_ONE: case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_ONE:
......
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