Commit 84c662b9 by Jamie Madill Committed by Commit Bot

Vulkan: Store program textures cache.

The program textures update needs to call into the incomplete textures cache. Moving this step into an update mechanism allows us to avoid some complexity of calling the incomplete textures cache inside the ProgramVk class. This enables further refactors for draw call shader patching and line segment raster. Bug: angleproject:2598 Change-Id: I0fd81ca58d2641572a2dd444992ccddd99ebc823 Reviewed-on: https://chromium-review.googlesource.com/1127301 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent d34aa362
...@@ -471,6 +471,7 @@ class State : public angle::ObserverInterface, angle::NonCopyable ...@@ -471,6 +471,7 @@ class State : public angle::ObserverInterface, angle::NonCopyable
GLenum format); GLenum format);
const ImageUnit &getImageUnit(GLuint unit) const; const ImageUnit &getImageUnit(GLuint unit) const;
const ActiveTextureMask &getActiveTexturesMask() const { return mActiveTexturesMask; }
const std::vector<Texture *> &getCompleteTextureCache() const { return mCompleteTextureCache; } const std::vector<Texture *> &getCompleteTextureCache() const { return mCompleteTextureCache; }
ComponentTypeMask getCurrentValuesTypeMask() const { return mCurrentValuesTypeMask; } ComponentTypeMask getCurrentValuesTypeMask() const { return mCurrentValuesTypeMask; }
...@@ -562,7 +563,6 @@ class State : public angle::ObserverInterface, angle::NonCopyable ...@@ -562,7 +563,6 @@ class State : public angle::ObserverInterface, angle::NonCopyable
std::vector<Texture *> mCompleteTextureCache; std::vector<Texture *> mCompleteTextureCache;
std::vector<angle::ObserverBinding> mCompleteTextureBindings; std::vector<angle::ObserverBinding> mCompleteTextureBindings;
InitState mCachedTexturesInitState; InitState mCachedTexturesInitState;
using ActiveTextureMask = angle::BitSet<IMPLEMENTATION_MAX_ACTIVE_TEXTURES>;
ActiveTextureMask mActiveTexturesMask; ActiveTextureMask mActiveTexturesMask;
using SamplerBindingVector = std::vector<BindingPointer<Sampler>>; using SamplerBindingVector = std::vector<BindingPointer<Sampler>>;
......
...@@ -323,6 +323,11 @@ using DrawBuffersArray = std::array<T, IMPLEMENTATION_MAX_DRAW_BUFFERS>; ...@@ -323,6 +323,11 @@ using DrawBuffersArray = std::array<T, IMPLEMENTATION_MAX_DRAW_BUFFERS>;
template <typename T> template <typename T>
using AttribArray = std::array<T, MAX_VERTEX_ATTRIBS>; using AttribArray = std::array<T, MAX_VERTEX_ATTRIBS>;
using ActiveTextureMask = angle::BitSet<IMPLEMENTATION_MAX_ACTIVE_TEXTURES>;
template <typename T>
using ActiveTextureArray = std::array<T, IMPLEMENTATION_MAX_ACTIVE_TEXTURES>;
// OffsetBindingPointer.getSize() returns the size specified by the user, which may be larger than // OffsetBindingPointer.getSize() returns the size specified by the user, which may be larger than
// the size of the bound buffer. This function reduces the returned size to fit the bound buffer if // the size of the bound buffer. This function reduces the returned size to fit the bound buffer if
// necessary. Returns 0 if no buffer is bound or if integer overflow occurs. // necessary. Returns 0 if no buffer is bound or if integer overflow occurs.
......
...@@ -75,9 +75,7 @@ ContextVk::ContextVk(const gl::ContextState &state, RendererVk *renderer) ...@@ -75,9 +75,7 @@ ContextVk::ContextVk(const gl::ContextState &state, RendererVk *renderer)
memset(&mClearDepthStencilValue, 0, sizeof(mClearDepthStencilValue)); memset(&mClearDepthStencilValue, 0, sizeof(mClearDepthStencilValue));
} }
ContextVk::~ContextVk() ContextVk::~ContextVk() = default;
{
}
void ContextVk::onDestroy(const gl::Context *context) void ContextVk::onDestroy(const gl::Context *context)
{ {
...@@ -220,29 +218,15 @@ gl::Error ContextVk::setupDraw(const gl::Context *context, ...@@ -220,29 +218,15 @@ gl::Error ContextVk::setupDraw(const gl::Context *context,
if (mTexturesDirty) if (mTexturesDirty)
{ {
mTexturesDirty = false; mTexturesDirty = false;
// TODO(jmadill): Should probably merge this for loop with programVk's descriptor update.
ContextVk *contextVk = vk::GetImpl(context);
const auto &completeTextures = state.getCompleteTextureCache();
for (const gl::SamplerBinding &samplerBinding : programGL->getSamplerBindings())
{
ASSERT(!samplerBinding.unreferenced);
for (GLuint textureUnit : samplerBinding.boundTextureUnits) // TODO(jmadill): Should probably merge this for loop with programVk's descriptor update.
{ for (size_t textureIndex : state.getActiveTexturesMask())
gl::Texture *texture = completeTextures[textureUnit];
// Null textures represent incomplete textures.
if (texture == nullptr)
{ {
ANGLE_TRY(getIncompleteTexture(context, samplerBinding.textureType, &texture)); TextureVk *textureVk = mActiveTextures[textureIndex];
} ANGLE_TRY(textureVk->ensureImageInitialized(this));
TextureVk *textureVk = vk::GetImpl(texture);
ANGLE_TRY(textureVk->ensureImageInitialized(contextVk));
textureVk->addReadDependency(framebufferVk); textureVk->addReadDependency(framebufferVk);
} }
} }
}
(*commandBufferOut)->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, mCurrentPipeline->get()); (*commandBufferOut)->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, mCurrentPipeline->get());
...@@ -252,7 +236,7 @@ gl::Error ContextVk::setupDraw(const gl::Context *context, ...@@ -252,7 +236,7 @@ gl::Error ContextVk::setupDraw(const gl::Context *context,
// TODO(jmadill): Can probably use more dirty bits here. // TODO(jmadill): Can probably use more dirty bits here.
ANGLE_TRY(programVk->updateUniforms(this)); ANGLE_TRY(programVk->updateUniforms(this));
ANGLE_TRY(programVk->updateTexturesDescriptorSet(context)); ANGLE_TRY(programVk->updateTexturesDescriptorSet(this));
// Bind the graphics descriptor sets. // Bind the graphics descriptor sets.
// TODO(jmadill): Handle multiple command buffers. // TODO(jmadill): Handle multiple command buffers.
...@@ -434,9 +418,9 @@ void ContextVk::updateColorMask(const gl::BlendState &blendState) ...@@ -434,9 +418,9 @@ void ContextVk::updateColorMask(const gl::BlendState &blendState)
framebufferVk->getEmulatedAlphaAttachmentMask()); framebufferVk->getEmulatedAlphaAttachmentMask());
} }
void ContextVk::updateScissor(const gl::State &glState) void ContextVk::updateScissor(const gl::State &glState) const
{ {
FramebufferVk *framebufferVk = vk::GetImpl(getGLState().getDrawFramebuffer()); FramebufferVk *framebufferVk = vk::GetImpl(glState.getDrawFramebuffer());
gl::Box dimensions = framebufferVk->getState().getDimensions(); gl::Box dimensions = framebufferVk->getState().getDimensions();
gl::Rectangle renderArea(0, 0, dimensions.width, dimensions.height); gl::Rectangle renderArea(0, 0, dimensions.width, dimensions.height);
...@@ -664,6 +648,8 @@ gl::Error ContextVk::syncState(const gl::Context *context, const gl::State::Dirt ...@@ -664,6 +648,8 @@ gl::Error ContextVk::syncState(const gl::Context *context, const gl::State::Dirt
if (dirtyTextures) if (dirtyTextures)
{ {
ANGLE_TRY(updateActiveTextures(context));
ProgramVk *programVk = vk::GetImpl(glState.getProgram()); ProgramVk *programVk = vk::GetImpl(glState.getProgram());
programVk->invalidateTextures(); programVk->invalidateTextures();
mTexturesDirty = true; mTexturesDirty = true;
...@@ -949,4 +935,37 @@ void ContextVk::handleError(VkResult errorCode, const char *file, unsigned int l ...@@ -949,4 +935,37 @@ void ContextVk::handleError(VkResult errorCode, const char *file, unsigned int l
mErrors->handleError(gl::Error(glErrorCode, glErrorCode, errorStream.str())); mErrors->handleError(gl::Error(glErrorCode, glErrorCode, errorStream.str()));
} }
gl::Error ContextVk::updateActiveTextures(const gl::Context *context)
{
const auto &completeTextures = mState.getState().getCompleteTextureCache();
const gl::Program *program = mState.getState().getProgram();
mActiveTextures.fill(nullptr);
for (const gl::SamplerBinding &samplerBinding : program->getSamplerBindings())
{
ASSERT(!samplerBinding.unreferenced);
for (GLuint textureUnit : samplerBinding.boundTextureUnits)
{
gl::Texture *texture = completeTextures[textureUnit];
// Null textures represent incomplete textures.
if (texture == nullptr)
{
ANGLE_TRY(getIncompleteTexture(context, samplerBinding.textureType, &texture));
}
mActiveTextures[textureUnit] = vk::GetImpl(texture);
}
}
return gl::NoError();
}
const gl::ActiveTextureArray<TextureVk *> &ContextVk::getActiveTextures() const
{
return mActiveTextures;
}
} // namespace rx } // namespace rx
...@@ -170,6 +170,7 @@ class ContextVk : public ContextImpl, public vk::Context ...@@ -170,6 +170,7 @@ class ContextVk : public ContextImpl, public vk::Context
void updateColorMask(const gl::BlendState &blendState); void updateColorMask(const gl::BlendState &blendState);
void handleError(VkResult errorCode, const char *file, unsigned int line) override; void handleError(VkResult errorCode, const char *file, unsigned int line) override;
const gl::ActiveTextureArray<TextureVk *> &getActiveTextures() const;
private: private:
gl::Error initPipeline(const gl::DrawCallParams &drawCallParams); gl::Error initPipeline(const gl::DrawCallParams &drawCallParams);
...@@ -178,11 +179,12 @@ class ContextVk : public ContextImpl, public vk::Context ...@@ -178,11 +179,12 @@ class ContextVk : public ContextImpl, public vk::Context
vk::CommandBuffer **commandBufferOut, vk::CommandBuffer **commandBufferOut,
bool *shouldApplyVertexArrayOut); bool *shouldApplyVertexArrayOut);
void updateScissor(const gl::State &glState); void updateScissor(const gl::State &glState) const;
void updateFlipViewportDrawFramebuffer(const gl::State &glState); void updateFlipViewportDrawFramebuffer(const gl::State &glState);
void updateFlipViewportReadFramebuffer(const gl::State &glState); void updateFlipViewportReadFramebuffer(const gl::State &glState);
angle::Result updateDriverUniforms(const gl::State &glState); angle::Result updateDriverUniforms(const gl::State &glState);
gl::Error updateActiveTextures(const gl::Context *context);
vk::PipelineAndSerial *mCurrentPipeline; vk::PipelineAndSerial *mCurrentPipeline;
gl::PrimitiveMode mCurrentDrawMode; gl::PrimitiveMode mCurrentDrawMode;
...@@ -224,6 +226,10 @@ class ContextVk : public ContextImpl, public vk::Context ...@@ -224,6 +226,10 @@ class ContextVk : public ContextImpl, public vk::Context
vk::DynamicBuffer mDriverUniformsBuffer; vk::DynamicBuffer mDriverUniformsBuffer;
VkDescriptorSet mDriverUniformsDescriptorSet; VkDescriptorSet mDriverUniformsDescriptorSet;
vk::BindingPointer<vk::DescriptorSetLayout> mDriverUniformsSetLayout; vk::BindingPointer<vk::DescriptorSetLayout> mDriverUniformsSetLayout;
// This cache should also probably include the texture index (shader location) and array
// index (also in the shader). This info is used in the descriptor update step.
gl::ActiveTextureArray<TextureVk *> mActiveTextures;
}; };
} // namespace rx } // namespace rx
......
...@@ -860,26 +860,23 @@ const gl::RangeUI &ProgramVk::getUsedDescriptorSetRange() const ...@@ -860,26 +860,23 @@ const gl::RangeUI &ProgramVk::getUsedDescriptorSetRange() const
return mUsedDescriptorSetRange; return mUsedDescriptorSetRange;
} }
gl::Error ProgramVk::updateTexturesDescriptorSet(const gl::Context *context) angle::Result ProgramVk::updateTexturesDescriptorSet(ContextVk *contextVk)
{ {
if (mState.getSamplerBindings().empty() || !mDirtyTextures) if (mState.getSamplerBindings().empty() || !mDirtyTextures)
{ {
return gl::NoError(); return angle::Result::Continue();
} }
ContextVk *contextVk = GetImplAs<ContextVk>(context);
ANGLE_TRY(allocateDescriptorSet(contextVk, kTextureDescriptorSetIndex)); ANGLE_TRY(allocateDescriptorSet(contextVk, kTextureDescriptorSetIndex));
ASSERT(mUsedDescriptorSetRange.contains(1)); ASSERT(mUsedDescriptorSetRange.contains(1));
VkDescriptorSet descriptorSet = mDescriptorSets[kTextureDescriptorSetIndex]; VkDescriptorSet descriptorSet = mDescriptorSets[kTextureDescriptorSetIndex];
// TODO(jmadill): Don't hard-code the texture limit. gl::ActiveTextureArray<VkDescriptorImageInfo> descriptorImageInfo;
ShaderTextureArray<VkDescriptorImageInfo> descriptorImageInfo; gl::ActiveTextureArray<VkWriteDescriptorSet> writeDescriptorInfo;
ShaderTextureArray<VkWriteDescriptorSet> writeDescriptorInfo;
uint32_t writeCount = 0; uint32_t writeCount = 0;
const gl::State &glState = contextVk->getGLState(); const gl::ActiveTextureArray<TextureVk *> &activeTextures = contextVk->getActiveTextures();
const auto &completeTextures = glState.getCompleteTextureCache();
for (uint32_t textureIndex = 0; textureIndex < mState.getSamplerBindings().size(); for (uint32_t textureIndex = 0; textureIndex < mState.getSamplerBindings().size();
++textureIndex) ++textureIndex)
...@@ -892,16 +889,7 @@ gl::Error ProgramVk::updateTexturesDescriptorSet(const gl::Context *context) ...@@ -892,16 +889,7 @@ gl::Error ProgramVk::updateTexturesDescriptorSet(const gl::Context *context)
++arrayElement) ++arrayElement)
{ {
GLuint textureUnit = samplerBinding.boundTextureUnits[arrayElement]; GLuint textureUnit = samplerBinding.boundTextureUnits[arrayElement];
gl::Texture *texture = completeTextures[textureUnit]; TextureVk *textureVk = activeTextures[textureUnit];
if (texture == nullptr)
{
// If we have an incomplete texture, fetch it from our renderer.
ANGLE_TRY(
contextVk->getIncompleteTexture(context, samplerBinding.textureType, &texture));
}
TextureVk *textureVk = vk::GetImpl(texture);
const vk::ImageHelper &image = textureVk->getImage(); const vk::ImageHelper &image = textureVk->getImage();
VkDescriptorImageInfo &imageInfo = descriptorImageInfo[writeCount]; VkDescriptorImageInfo &imageInfo = descriptorImageInfo[writeCount];
...@@ -933,7 +921,7 @@ gl::Error ProgramVk::updateTexturesDescriptorSet(const gl::Context *context) ...@@ -933,7 +921,7 @@ gl::Error ProgramVk::updateTexturesDescriptorSet(const gl::Context *context)
vkUpdateDescriptorSets(device, writeCount, writeDescriptorInfo.data(), 0, nullptr); vkUpdateDescriptorSets(device, writeCount, writeDescriptorInfo.data(), 0, nullptr);
mDirtyTextures = false; mDirtyTextures = false;
return gl::NoError(); return angle::Result::Continue();
} }
void ProgramVk::invalidateTextures() void ProgramVk::invalidateTextures()
......
...@@ -119,7 +119,7 @@ class ProgramVk : public ProgramImpl ...@@ -119,7 +119,7 @@ class ProgramVk : public ProgramImpl
// or Textures. // or Textures.
const gl::RangeUI &getUsedDescriptorSetRange() const; const gl::RangeUI &getUsedDescriptorSetRange() const;
gl::Error updateTexturesDescriptorSet(const gl::Context *context); angle::Result updateTexturesDescriptorSet(ContextVk *contextVk);
void invalidateTextures(); void invalidateTextures();
const vk::PipelineLayout &getPipelineLayout() const; const vk::PipelineLayout &getPipelineLayout() const;
...@@ -178,9 +178,6 @@ class ProgramVk : public ProgramImpl ...@@ -178,9 +178,6 @@ class ProgramVk : public ProgramImpl
gl::RangeUI mUsedDescriptorSetRange; gl::RangeUI mUsedDescriptorSetRange;
bool mDirtyTextures; bool mDirtyTextures;
template <typename T>
using ShaderTextureArray = std::array<T, gl::IMPLEMENTATION_MAX_SHADER_TEXTURES>;
// We keep a reference to the pipeline and descriptor set layouts. This ensures they don't get // We keep a reference to the pipeline and descriptor set layouts. This ensures they don't get
// deleted while this program is in use. // deleted while this program is in use.
vk::BindingPointer<vk::PipelineLayout> mPipelineLayout; vk::BindingPointer<vk::PipelineLayout> mPipelineLayout;
......
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