Commit 10ade024 by Tim Van Patten Committed by Commit Bot

Create the ProgramExecutableVk Class

The ProgramExecutableVk class is being created to collect data structures that are common to both ProgramVks and ProgramPipelineVks, as well as any shared functions. This allows callers to make Program-/ProgramPipeline- specific queries without needing to know exactly which responded by querying the current ProgramExecutableVk. This will also allow the necessary data structures to only be populated and stored within the ProgramExecutableVk when necessary and reused as often as necessary. A few things are being moved into this class: - mVariableInfoMap This information will be required to defer translating the SPIR-V until when the vulkan pipeline layout is determined and the actual locations are known.   This will also allow removing determining these locations twice (during GLSL->SPIR-V compilation and pipeline layout). - createPipelineLayout() - update*DescriptorSet() - Descriptor Set Layout lists - Pipeline Layout - Various other functions/members related to pipeplines, descriptor sets, etc. Bug: angleproject:3570 Change-Id: I4b5ababeafec865148783c8ffd4c15f659f4856d Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2055656 Commit-Queue: Tim Van Patten <timvp@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent b19000f3
...@@ -43,6 +43,8 @@ _vulkan_backend_sources = [ ...@@ -43,6 +43,8 @@ _vulkan_backend_sources = [
"OverlayVk.h", "OverlayVk.h",
"PersistentCommandPool.cpp", "PersistentCommandPool.cpp",
"PersistentCommandPool.h", "PersistentCommandPool.h",
"ProgramExecutableVk.cpp",
"ProgramExecutableVk.h",
"ProgramPipelineVk.cpp", "ProgramPipelineVk.cpp",
"ProgramPipelineVk.h", "ProgramPipelineVk.h",
"ProgramVk.cpp", "ProgramVk.cpp",
......
...@@ -1267,7 +1267,8 @@ ANGLE_INLINE angle::Result ContextVk::handleDirtyTexturesImpl( ...@@ -1267,7 +1267,8 @@ ANGLE_INLINE angle::Result ContextVk::handleDirtyTexturesImpl(
if (executable->hasTextures(mState)) if (executable->hasTextures(mState))
{ {
ANGLE_TRY(mProgram->updateTexturesDescriptorSet(this)); ANGLE_TRY(
mProgram->getExecutable().updateTexturesDescriptorSet(mProgram->getState(), this));
} }
return angle::Result::Continue; return angle::Result::Continue;
...@@ -1345,8 +1346,8 @@ ANGLE_INLINE angle::Result ContextVk::handleDirtyShaderResourcesImpl( ...@@ -1345,8 +1346,8 @@ ANGLE_INLINE angle::Result ContextVk::handleDirtyShaderResourcesImpl(
if (executable->hasUniformBuffers(mState) || executable->hasStorageBuffers(mState) || if (executable->hasUniformBuffers(mState) || executable->hasStorageBuffers(mState) ||
executable->hasAtomicCounterBuffers(mState) || executable->hasImages(mState)) executable->hasAtomicCounterBuffers(mState) || executable->hasImages(mState))
{ {
ANGLE_TRY(mProgram->updateShaderResourcesDescriptorSet(this, &mResourceUseList, ANGLE_TRY(mProgram->getExecutable().updateShaderResourcesDescriptorSet(
commandBufferHelper)); mProgram->getState(), this, &mResourceUseList, commandBufferHelper));
} }
return angle::Result::Continue; return angle::Result::Continue;
} }
...@@ -1388,7 +1389,8 @@ angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackBuffersEmulation( ...@@ -1388,7 +1389,8 @@ angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackBuffersEmulation(
&mResourceUseList, VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, &bufferHelper); &mResourceUseList, VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, &bufferHelper);
} }
ANGLE_TRY(mProgram->updateTransformFeedbackDescriptorSet(this)); ANGLE_TRY(mProgram->getExecutable().updateTransformFeedbackDescriptorSet(
mProgram->getState(), mProgram->getDefaultUniformBlocks(), this));
} }
return angle::Result::Continue; return angle::Result::Continue;
} }
...@@ -1466,7 +1468,7 @@ angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackState(const gl::Con ...@@ -1466,7 +1468,7 @@ angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackState(const gl::Con
angle::Result ContextVk::handleDirtyDescriptorSets(const gl::Context *context, angle::Result ContextVk::handleDirtyDescriptorSets(const gl::Context *context,
vk::CommandBuffer *commandBuffer) vk::CommandBuffer *commandBuffer)
{ {
ANGLE_TRY(mProgram->updateDescriptorSets(this, commandBuffer)); ANGLE_TRY(mProgram->getExecutable().updateDescriptorSets(this, commandBuffer));
return angle::Result::Continue; return angle::Result::Continue;
} }
......
//
// Copyright 2020 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// ProgramExecutableVk.h: Collects the information and interfaces common to both ProgramVks and
// ProgramPipelineVks in order to execute/draw with either.
#ifndef LIBANGLE_RENDERER_VULKAN_PROGRAMEXECUTABLEVK_H_
#define LIBANGLE_RENDERER_VULKAN_PROGRAMEXECUTABLEVK_H_
#include "common/utilities.h"
#include "libANGLE/Context.h"
#include "libANGLE/InfoLog.h"
#include "libANGLE/renderer/glslang_wrapper_utils.h"
#include "libANGLE/renderer/vulkan/ContextVk.h"
#include "libANGLE/renderer/vulkan/vk_helpers.h"
namespace rx
{
// State for the default uniform blocks.
struct DefaultUniformBlock final : private angle::NonCopyable
{
DefaultUniformBlock();
~DefaultUniformBlock();
vk::DynamicBuffer storage;
// Shadow copies of the shader uniform data.
angle::MemoryBuffer uniformData;
// Since the default blocks are laid out in std140, this tells us where to write on a call
// to a setUniform method. They are arranged in uniform location order.
std::vector<sh::BlockMemberInfo> uniformLayout;
};
class ProgramExecutableVk
{
public:
ProgramExecutableVk();
virtual ~ProgramExecutableVk();
void reset(ContextVk *contextVk);
void clearVariableInfoMap();
ShaderInterfaceVariableInfoMap &getShaderInterfaceVariableInfoMap() { return mVariableInfoMap; }
angle::Result createPipelineLayout(const gl::Context *glContext,
const gl::ProgramExecutable &glExecutable,
const gl::ProgramState &programState);
angle::Result updateTexturesDescriptorSet(const gl::ProgramState &programState,
ContextVk *contextVk);
angle::Result updateShaderResourcesDescriptorSet(const gl::ProgramState &programState,
ContextVk *contextVk,
vk::ResourceUseList *resourceUseList,
CommandBufferHelper *commandBufferHelper);
angle::Result updateTransformFeedbackDescriptorSet(
const gl::ProgramState &programState,
gl::ShaderMap<DefaultUniformBlock> &defaultUniformBlocks,
ContextVk *contextVk);
angle::Result updateDescriptorSets(ContextVk *contextVk, vk::CommandBuffer *commandBuffer);
private:
friend class ProgramVk;
friend class ProgramPipelineVk;
void updateBindingOffsets(const gl::ProgramState &programState);
uint32_t getUniformBlockBindingsOffset() const { return 0; }
uint32_t getStorageBlockBindingsOffset() const { return mStorageBlockBindingsOffset; }
uint32_t getAtomicCounterBufferBindingsOffset() const
{
return mAtomicCounterBufferBindingsOffset;
}
uint32_t getImageBindingsOffset() const { return mImageBindingsOffset; }
angle::Result allocateDescriptorSet(ContextVk *contextVk, uint32_t descriptorSetIndex);
angle::Result allocateDescriptorSetAndGetInfo(ContextVk *contextVk,
uint32_t descriptorSetIndex,
bool *newPoolAllocatedOut);
void updateDefaultUniformsDescriptorSet(
const gl::ProgramState &programState,
gl::ShaderMap<DefaultUniformBlock> &defaultUniformBlocks,
ContextVk *contextVk);
void updateTransformFeedbackDescriptorSetImpl(const gl::ProgramState &programState,
ContextVk *contextVk);
void updateBuffersDescriptorSet(ContextVk *contextVk,
vk::ResourceUseList *resourceUseList,
CommandBufferHelper *commandBufferHelper,
const std::vector<gl::InterfaceBlock> &blocks,
VkDescriptorType descriptorType);
void updateAtomicCounterBuffersDescriptorSet(const gl::ProgramState &programState,
ContextVk *contextVk,
vk::ResourceUseList *resourceUseList,
CommandBufferHelper *commandBufferHelper);
angle::Result updateImagesDescriptorSet(const gl::ProgramState &programState,
ContextVk *contextVk);
// In their descriptor set, uniform buffers are placed first, then storage buffers, then atomic
// counter buffers and then images. These cached values contain the offsets where storage
// buffer, atomic counter buffer and image bindings start.
uint32_t mStorageBlockBindingsOffset;
uint32_t mAtomicCounterBufferBindingsOffset;
uint32_t mImageBindingsOffset;
// This is a special "empty" placeholder buffer for when a shader has no uniforms or doesn't
// use all slots in the atomic counter buffer array.
//
// It is necessary because we want to keep a compatible pipeline layout in all cases,
// and Vulkan does not tolerate having null handles in a descriptor set.
vk::BufferHelper mEmptyBuffer;
// Descriptor sets for uniform blocks and textures for this program.
std::vector<VkDescriptorSet> mDescriptorSets;
vk::DescriptorSetLayoutArray<VkDescriptorSet> mEmptyDescriptorSets;
std::vector<vk::BufferHelper *> mDescriptorBuffersCache;
std::unordered_map<vk::TextureDescriptorDesc, VkDescriptorSet> mTextureDescriptorsCache;
// 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;
vk::DescriptorSetLayoutPointerArray mDescriptorSetLayouts;
// Keep bindings to the descriptor pools. This ensures the pools stay valid while the Program
// is in use.
vk::DescriptorSetLayoutArray<vk::RefCountedDescriptorPoolBinding> mDescriptorPoolBindings;
// Store descriptor pools here. We store the descriptors in the Program to facilitate descriptor
// cache management. It can also allow fewer descriptors for shaders which use fewer
// textures/buffers.
vk::DescriptorSetLayoutArray<vk::DynamicDescriptorPool> mDynamicDescriptorPools;
gl::ShaderVector<uint32_t> mDynamicBufferOffsets;
ShaderInterfaceVariableInfoMap mVariableInfoMap;
};
} // namespace rx
#endif // LIBANGLE_RENDERER_VULKAN_PROGRAMEXECUTABLEVK_H_
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "libANGLE/renderer/ProgramImpl.h" #include "libANGLE/renderer/ProgramImpl.h"
#include "libANGLE/renderer/glslang_wrapper_utils.h" #include "libANGLE/renderer/glslang_wrapper_utils.h"
#include "libANGLE/renderer/vulkan/ContextVk.h" #include "libANGLE/renderer/vulkan/ContextVk.h"
#include "libANGLE/renderer/vulkan/ProgramExecutableVk.h"
#include "libANGLE/renderer/vulkan/RendererVk.h" #include "libANGLE/renderer/vulkan/RendererVk.h"
#include "libANGLE/renderer/vulkan/TransformFeedbackVk.h" #include "libANGLE/renderer/vulkan/TransformFeedbackVk.h"
#include "libANGLE/renderer/vulkan/vk_helpers.h" #include "libANGLE/renderer/vulkan/vk_helpers.h"
...@@ -99,31 +100,14 @@ class ProgramVk : public ProgramImpl ...@@ -99,31 +100,14 @@ class ProgramVk : public ProgramImpl
void getUniformiv(const gl::Context *context, GLint location, GLint *params) const override; void getUniformiv(const gl::Context *context, GLint location, GLint *params) const override;
void getUniformuiv(const gl::Context *context, GLint location, GLuint *params) const override; void getUniformuiv(const gl::Context *context, GLint location, GLuint *params) const override;
// Also initializes the pipeline layout, descriptor set layouts, and used descriptor ranges.
angle::Result updateUniforms(ContextVk *contextVk); angle::Result updateUniforms(ContextVk *contextVk);
angle::Result updateTexturesDescriptorSet(ContextVk *contextVk);
angle::Result updateShaderResourcesDescriptorSet(ContextVk *contextVk,
vk::ResourceUseList *resourceUseList,
CommandBufferHelper *commandBufferHelper);
angle::Result updateTransformFeedbackDescriptorSet(ContextVk *contextVk);
angle::Result updateDescriptorSets(ContextVk *contextVk, vk::CommandBuffer *commandBuffer);
// For testing only. // For testing only.
void setDefaultUniformBlocksMinSizeForTesting(size_t minSize); void setDefaultUniformBlocksMinSizeForTesting(size_t minSize);
const vk::PipelineLayout &getPipelineLayout() const { return mPipelineLayout.get(); } const vk::PipelineLayout &getPipelineLayout() const
bool hasDefaultUniforms() const { return !mState.getDefaultUniformRange().empty(); }
bool hasTextures() const { return !mState.getSamplerBindings().empty(); }
bool hasUniformBuffers() const { return !mState.getUniformBlocks().empty(); }
bool hasStorageBuffers() const { return !mState.getShaderStorageBlocks().empty(); }
bool hasAtomicCounterBuffers() const { return !mState.getAtomicCounterBuffers().empty(); }
bool hasImages() const { return !mState.getImageBindings().empty(); }
bool hasTransformFeedbackOutput() const
{ {
return !mState.getLinkedTransformFeedbackVaryings().empty(); return mExecutable.mPipelineLayout.get();
} }
bool dirtyUniforms() const { return mDefaultUniformBlocksDirty.any(); } bool dirtyUniforms() const { return mDefaultUniformBlocksDirty.any(); }
...@@ -143,8 +127,9 @@ class ProgramVk : public ProgramImpl ...@@ -143,8 +127,9 @@ class ProgramVk : public ProgramImpl
ANGLE_TRY(renderer->getPipelineCache(&pipelineCache)); ANGLE_TRY(renderer->getPipelineCache(&pipelineCache));
return shaderProgram->getGraphicsPipeline( return shaderProgram->getGraphicsPipeline(
contextVk, &contextVk->getRenderPassCache(), *pipelineCache, contextVk, &contextVk->getRenderPassCache(), *pipelineCache,
contextVk->getCurrentQueueSerial(), mPipelineLayout.get(), desc, activeAttribLocations, contextVk->getCurrentQueueSerial(), mExecutable.mPipelineLayout.get(), desc,
mState.getProgramExecutable().getAttributesTypeMask(), descPtrOut, pipelineOut); activeAttribLocations, mState.getProgramExecutable().getAttributesTypeMask(),
descPtrOut, pipelineOut);
} }
angle::Result getComputePipeline(ContextVk *contextVk, vk::PipelineAndSerial **pipelineOut) angle::Result getComputePipeline(ContextVk *contextVk, vk::PipelineAndSerial **pipelineOut)
...@@ -152,15 +137,21 @@ class ProgramVk : public ProgramImpl ...@@ -152,15 +137,21 @@ class ProgramVk : public ProgramImpl
vk::ShaderProgramHelper *shaderProgram; vk::ShaderProgramHelper *shaderProgram;
ANGLE_TRY(initComputeProgram(contextVk, &shaderProgram)); ANGLE_TRY(initComputeProgram(contextVk, &shaderProgram));
ASSERT(!shaderProgram->isGraphicsProgram()); ASSERT(!shaderProgram->isGraphicsProgram());
return shaderProgram->getComputePipeline(contextVk, mPipelineLayout.get(), pipelineOut); return shaderProgram->getComputePipeline(contextVk, mExecutable.mPipelineLayout.get(),
pipelineOut);
} }
// Used in testing only. // Used in testing only.
vk::DynamicDescriptorPool *getDynamicDescriptorPool(uint32_t poolIndex) vk::DynamicDescriptorPool *getDynamicDescriptorPool(uint32_t poolIndex)
{ {
return &mDynamicDescriptorPools[poolIndex]; return &mExecutable.mDynamicDescriptorPools[poolIndex];
} }
const ProgramExecutableVk &getExecutable() const { return mExecutable; }
ProgramExecutableVk &getExecutable() { return mExecutable; }
gl::ShaderMap<DefaultUniformBlock> &getDefaultUniformBlocks() { return mDefaultUniformBlocks; }
private: private:
template <int cols, int rows> template <int cols, int rows>
void setUniformMatrixfv(GLint location, void setUniformMatrixfv(GLint location,
...@@ -169,10 +160,6 @@ class ProgramVk : public ProgramImpl ...@@ -169,10 +160,6 @@ class ProgramVk : public ProgramImpl
const GLfloat *value); const GLfloat *value);
void reset(ContextVk *contextVk); void reset(ContextVk *contextVk);
angle::Result allocateDescriptorSet(ContextVk *contextVk, uint32_t descriptorSetIndex);
angle::Result allocateDescriptorSetAndGetInfo(ContextVk *contextVk,
uint32_t descriptorSetIndex,
bool *newPoolAllocatedOut);
angle::Result initDefaultUniformBlocks(const gl::Context *glContext); angle::Result initDefaultUniformBlocks(const gl::Context *glContext);
void generateUniformLayoutMapping(gl::ShaderMap<sh::BlockLayoutMap> &layoutMap, void generateUniformLayoutMapping(gl::ShaderMap<sh::BlockLayoutMap> &layoutMap,
gl::ShaderMap<size_t> &requiredBufferSize); gl::ShaderMap<size_t> &requiredBufferSize);
...@@ -180,18 +167,6 @@ class ProgramVk : public ProgramImpl ...@@ -180,18 +167,6 @@ class ProgramVk : public ProgramImpl
angle::Result resizeUniformBlockMemory(ContextVk *contextVk, angle::Result resizeUniformBlockMemory(ContextVk *contextVk,
gl::ShaderMap<size_t> &requiredBufferSize); gl::ShaderMap<size_t> &requiredBufferSize);
void updateDefaultUniformsDescriptorSet(ContextVk *contextVk);
void updateTransformFeedbackDescriptorSetImpl(ContextVk *contextVk);
void updateBuffersDescriptorSet(ContextVk *contextVk,
vk::ResourceUseList *resourceUseList,
CommandBufferHelper *commandBufferHelper,
const std::vector<gl::InterfaceBlock> &blocks,
VkDescriptorType descriptorType);
void updateAtomicCounterBuffersDescriptorSet(ContextVk *contextVk,
vk::ResourceUseList *resourceUseList,
CommandBufferHelper *commandBufferHelper);
angle::Result updateImagesDescriptorSet(ContextVk *contextVk);
template <class T> template <class T>
void getUniformImpl(GLint location, T *v, GLenum entryPointType) const; void getUniformImpl(GLint location, T *v, GLenum entryPointType) const;
...@@ -200,15 +175,6 @@ class ProgramVk : public ProgramImpl ...@@ -200,15 +175,6 @@ class ProgramVk : public ProgramImpl
angle::Result linkImpl(const gl::Context *glContext, gl::InfoLog &infoLog); angle::Result linkImpl(const gl::Context *glContext, gl::InfoLog &infoLog);
void linkResources(const gl::ProgramLinkedResources &resources); void linkResources(const gl::ProgramLinkedResources &resources);
void updateBindingOffsets();
uint32_t getUniformBlockBindingsOffset() const { return 0; }
uint32_t getStorageBlockBindingsOffset() const { return mStorageBlockBindingsOffset; }
uint32_t getAtomicCounterBufferBindingsOffset() const
{
return mAtomicCounterBufferBindingsOffset;
}
uint32_t getImageBindingsOffset() const { return mImageBindingsOffset; }
class ProgramInfo; class ProgramInfo;
ANGLE_INLINE angle::Result initProgram(ContextVk *contextVk, ANGLE_INLINE angle::Result initProgram(ContextVk *contextVk,
bool enableLineRasterEmulation, bool enableLineRasterEmulation,
...@@ -247,50 +213,9 @@ class ProgramVk : public ProgramImpl ...@@ -247,50 +213,9 @@ class ProgramVk : public ProgramImpl
return initProgram(contextVk, false, &mDefaultProgramInfo, shaderProgramOut); return initProgram(contextVk, false, &mDefaultProgramInfo, shaderProgramOut);
} }
// State for the default uniform blocks.
struct DefaultUniformBlock final : private angle::NonCopyable
{
DefaultUniformBlock();
~DefaultUniformBlock();
vk::DynamicBuffer storage;
// Shadow copies of the shader uniform data.
angle::MemoryBuffer uniformData;
// Since the default blocks are laid out in std140, this tells us where to write on a call
// to a setUniform method. They are arranged in uniform location order.
std::vector<sh::BlockMemberInfo> uniformLayout;
};
gl::ShaderMap<DefaultUniformBlock> mDefaultUniformBlocks; gl::ShaderMap<DefaultUniformBlock> mDefaultUniformBlocks;
gl::ShaderBitSet mDefaultUniformBlocksDirty; gl::ShaderBitSet mDefaultUniformBlocksDirty;
gl::ShaderVector<uint32_t> mDynamicBufferOffsets;
// This is a special "empty" placeholder buffer for when a shader has no uniforms or doesn't
// use all slots in the atomic counter buffer array.
//
// It is necessary because we want to keep a compatible pipeline layout in all cases,
// and Vulkan does not tolerate having null handles in a descriptor set.
vk::BufferHelper mEmptyBuffer;
// Descriptor sets for uniform blocks and textures for this program.
std::vector<VkDescriptorSet> mDescriptorSets;
vk::DescriptorSetLayoutArray<VkDescriptorSet> mEmptyDescriptorSets;
std::vector<vk::BufferHelper *> mDescriptorBuffersCache;
std::unordered_map<vk::TextureDescriptorDesc, VkDescriptorSet> mTextureDescriptorsCache;
// 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;
vk::DescriptorSetLayoutPointerArray mDescriptorSetLayouts;
// Keep bindings to the descriptor pools. This ensures the pools stay valid while the Program
// is in use.
vk::DescriptorSetLayoutArray<vk::RefCountedDescriptorPoolBinding> mDescriptorPoolBindings;
class ShaderInfo final : angle::NonCopyable class ShaderInfo final : angle::NonCopyable
{ {
public: public:
...@@ -341,19 +266,9 @@ class ProgramVk : public ProgramImpl ...@@ -341,19 +266,9 @@ class ProgramVk : public ProgramImpl
// We keep the SPIR-V code to use for draw call pipeline creation. // We keep the SPIR-V code to use for draw call pipeline creation.
ShaderInfo mShaderInfo; ShaderInfo mShaderInfo;
// In their descriptor set, uniform buffers are placed first, then storage buffers, then atomic
// counter buffers and then images. These cached values contain the offsets where storage
// buffer, atomic counter buffer and image bindings start.
uint32_t mStorageBlockBindingsOffset;
uint32_t mAtomicCounterBufferBindingsOffset;
uint32_t mImageBindingsOffset;
// Store descriptor pools here. We store the descriptors in the Program to facilitate descriptor
// cache management. It can also allow fewer descriptors for shaders which use fewer
// textures/buffers.
vk::DescriptorSetLayoutArray<vk::DynamicDescriptorPool> mDynamicDescriptorPools;
GlslangProgramInterfaceInfo mGlslangProgramInterfaceInfo; GlslangProgramInterfaceInfo mGlslangProgramInterfaceInfo;
ProgramExecutableVk mExecutable;
}; };
} // namespace rx } // namespace rx
......
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