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
GLenum format);
const ImageUnit &getImageUnit(GLuint unit) const;
const ActiveTextureMask &getActiveTexturesMask() const { return mActiveTexturesMask; }
const std::vector<Texture *> &getCompleteTextureCache() const { return mCompleteTextureCache; }
ComponentTypeMask getCurrentValuesTypeMask() const { return mCurrentValuesTypeMask; }
......@@ -562,7 +563,6 @@ class State : public angle::ObserverInterface, angle::NonCopyable
std::vector<Texture *> mCompleteTextureCache;
std::vector<angle::ObserverBinding> mCompleteTextureBindings;
InitState mCachedTexturesInitState;
using ActiveTextureMask = angle::BitSet<IMPLEMENTATION_MAX_ACTIVE_TEXTURES>;
ActiveTextureMask mActiveTexturesMask;
using SamplerBindingVector = std::vector<BindingPointer<Sampler>>;
......
......@@ -323,6 +323,11 @@ using DrawBuffersArray = std::array<T, IMPLEMENTATION_MAX_DRAW_BUFFERS>;
template <typename T>
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
// 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.
......
......@@ -75,9 +75,7 @@ ContextVk::ContextVk(const gl::ContextState &state, RendererVk *renderer)
memset(&mClearDepthStencilValue, 0, sizeof(mClearDepthStencilValue));
}
ContextVk::~ContextVk()
{
}
ContextVk::~ContextVk() = default;
void ContextVk::onDestroy(const gl::Context *context)
{
......@@ -220,27 +218,13 @@ gl::Error ContextVk::setupDraw(const gl::Context *context,
if (mTexturesDirty)
{
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())
for (size_t textureIndex : state.getActiveTexturesMask())
{
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));
}
TextureVk *textureVk = vk::GetImpl(texture);
ANGLE_TRY(textureVk->ensureImageInitialized(contextVk));
textureVk->addReadDependency(framebufferVk);
}
TextureVk *textureVk = mActiveTextures[textureIndex];
ANGLE_TRY(textureVk->ensureImageInitialized(this));
textureVk->addReadDependency(framebufferVk);
}
}
......@@ -252,7 +236,7 @@ gl::Error ContextVk::setupDraw(const gl::Context *context,
// TODO(jmadill): Can probably use more dirty bits here.
ANGLE_TRY(programVk->updateUniforms(this));
ANGLE_TRY(programVk->updateTexturesDescriptorSet(context));
ANGLE_TRY(programVk->updateTexturesDescriptorSet(this));
// Bind the graphics descriptor sets.
// TODO(jmadill): Handle multiple command buffers.
......@@ -434,9 +418,9 @@ void ContextVk::updateColorMask(const gl::BlendState &blendState)
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::Rectangle renderArea(0, 0, dimensions.width, dimensions.height);
......@@ -664,6 +648,8 @@ gl::Error ContextVk::syncState(const gl::Context *context, const gl::State::Dirt
if (dirtyTextures)
{
ANGLE_TRY(updateActiveTextures(context));
ProgramVk *programVk = vk::GetImpl(glState.getProgram());
programVk->invalidateTextures();
mTexturesDirty = true;
......@@ -949,4 +935,37 @@ void ContextVk::handleError(VkResult errorCode, const char *file, unsigned int l
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
......@@ -170,6 +170,7 @@ class ContextVk : public ContextImpl, public vk::Context
void updateColorMask(const gl::BlendState &blendState);
void handleError(VkResult errorCode, const char *file, unsigned int line) override;
const gl::ActiveTextureArray<TextureVk *> &getActiveTextures() const;
private:
gl::Error initPipeline(const gl::DrawCallParams &drawCallParams);
......@@ -178,11 +179,12 @@ class ContextVk : public ContextImpl, public vk::Context
vk::CommandBuffer **commandBufferOut,
bool *shouldApplyVertexArrayOut);
void updateScissor(const gl::State &glState);
void updateScissor(const gl::State &glState) const;
void updateFlipViewportDrawFramebuffer(const gl::State &glState);
void updateFlipViewportReadFramebuffer(const gl::State &glState);
angle::Result updateDriverUniforms(const gl::State &glState);
gl::Error updateActiveTextures(const gl::Context *context);
vk::PipelineAndSerial *mCurrentPipeline;
gl::PrimitiveMode mCurrentDrawMode;
......@@ -224,6 +226,10 @@ class ContextVk : public ContextImpl, public vk::Context
vk::DynamicBuffer mDriverUniformsBuffer;
VkDescriptorSet mDriverUniformsDescriptorSet;
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
......
......@@ -860,26 +860,23 @@ const gl::RangeUI &ProgramVk::getUsedDescriptorSetRange() const
return mUsedDescriptorSetRange;
}
gl::Error ProgramVk::updateTexturesDescriptorSet(const gl::Context *context)
angle::Result ProgramVk::updateTexturesDescriptorSet(ContextVk *contextVk)
{
if (mState.getSamplerBindings().empty() || !mDirtyTextures)
{
return gl::NoError();
return angle::Result::Continue();
}
ContextVk *contextVk = GetImplAs<ContextVk>(context);
ANGLE_TRY(allocateDescriptorSet(contextVk, kTextureDescriptorSetIndex));
ASSERT(mUsedDescriptorSetRange.contains(1));
VkDescriptorSet descriptorSet = mDescriptorSets[kTextureDescriptorSetIndex];
// TODO(jmadill): Don't hard-code the texture limit.
ShaderTextureArray<VkDescriptorImageInfo> descriptorImageInfo;
ShaderTextureArray<VkWriteDescriptorSet> writeDescriptorInfo;
gl::ActiveTextureArray<VkDescriptorImageInfo> descriptorImageInfo;
gl::ActiveTextureArray<VkWriteDescriptorSet> writeDescriptorInfo;
uint32_t writeCount = 0;
const gl::State &glState = contextVk->getGLState();
const auto &completeTextures = glState.getCompleteTextureCache();
const gl::ActiveTextureArray<TextureVk *> &activeTextures = contextVk->getActiveTextures();
for (uint32_t textureIndex = 0; textureIndex < mState.getSamplerBindings().size();
++textureIndex)
......@@ -891,17 +888,8 @@ gl::Error ProgramVk::updateTexturesDescriptorSet(const gl::Context *context)
for (uint32_t arrayElement = 0; arrayElement < samplerBinding.boundTextureUnits.size();
++arrayElement)
{
GLuint textureUnit = samplerBinding.boundTextureUnits[arrayElement];
gl::Texture *texture = completeTextures[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);
GLuint textureUnit = samplerBinding.boundTextureUnits[arrayElement];
TextureVk *textureVk = activeTextures[textureUnit];
const vk::ImageHelper &image = textureVk->getImage();
VkDescriptorImageInfo &imageInfo = descriptorImageInfo[writeCount];
......@@ -933,7 +921,7 @@ gl::Error ProgramVk::updateTexturesDescriptorSet(const gl::Context *context)
vkUpdateDescriptorSets(device, writeCount, writeDescriptorInfo.data(), 0, nullptr);
mDirtyTextures = false;
return gl::NoError();
return angle::Result::Continue();
}
void ProgramVk::invalidateTextures()
......
......@@ -119,7 +119,7 @@ class ProgramVk : public ProgramImpl
// or Textures.
const gl::RangeUI &getUsedDescriptorSetRange() const;
gl::Error updateTexturesDescriptorSet(const gl::Context *context);
angle::Result updateTexturesDescriptorSet(ContextVk *contextVk);
void invalidateTextures();
const vk::PipelineLayout &getPipelineLayout() const;
......@@ -178,9 +178,6 @@ class ProgramVk : public ProgramImpl
gl::RangeUI mUsedDescriptorSetRange;
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
// deleted while this program is in use.
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