Commit ffa4cbb6 by Jamie Madill Committed by Commit Bot

Vulkan: Implement the Pipeline cache.

This currently keeps a cache of every PSO compiled and does not trim the cache or evict old members on memory pressure. This will be done as a follow-up. Improves the speed of the Draw Call microbenchmark 50x when using a single state change. Bug: angleproject:2163 Change-Id: I2cceb38ca57ae639f36a944f4571b627481b92da Reviewed-on: https://chromium-review.googlesource.com/876954Reviewed-by: 's avatarFrank Henigman <fjhenigman@chromium.org> Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent 1436d434
...@@ -73,7 +73,6 @@ ContextVk::ContextVk(const gl::ContextState &state, RendererVk *renderer) ...@@ -73,7 +73,6 @@ ContextVk::ContextVk(const gl::ContextState &state, RendererVk *renderer)
ContextVk::~ContextVk() ContextVk::~ContextVk()
{ {
invalidateCurrentPipeline();
} }
void ContextVk::onDestroy(const gl::Context *context) void ContextVk::onDestroy(const gl::Context *context)
...@@ -127,7 +126,7 @@ gl::Error ContextVk::finish(const gl::Context *context) ...@@ -127,7 +126,7 @@ gl::Error ContextVk::finish(const gl::Context *context)
gl::Error ContextVk::initPipeline(const gl::Context *context) gl::Error ContextVk::initPipeline(const gl::Context *context)
{ {
ASSERT(!mCurrentPipeline.valid()); ASSERT(!mCurrentPipeline);
const gl::State &state = mState.getState(); const gl::State &state = mState.getState();
VertexArrayVk *vertexArrayVk = vk::GetImpl(state.getVertexArray()); VertexArrayVk *vertexArrayVk = vk::GetImpl(state.getVertexArray());
...@@ -144,7 +143,7 @@ gl::Error ContextVk::initPipeline(const gl::Context *context) ...@@ -144,7 +143,7 @@ gl::Error ContextVk::initPipeline(const gl::Context *context)
mPipelineDesc->updateRenderPassDesc(framebufferVk->getRenderPassDesc(context)); mPipelineDesc->updateRenderPassDesc(framebufferVk->getRenderPassDesc(context));
// TODO(jmadill): Validate with ASSERT against physical device limits/caps? // TODO(jmadill): Validate with ASSERT against physical device limits/caps?
ANGLE_TRY(mPipelineDesc->initializePipeline(mRenderer, programVk, &mCurrentPipeline)); ANGLE_TRY(mRenderer->getPipeline(programVk, *mPipelineDesc, &mCurrentPipeline));
return gl::NoError(); return gl::NoError();
} }
...@@ -160,10 +159,9 @@ gl::Error ContextVk::setupDraw(const gl::Context *context, ...@@ -160,10 +159,9 @@ gl::Error ContextVk::setupDraw(const gl::Context *context,
mCurrentDrawMode = mode; mCurrentDrawMode = mode;
} }
if (!mCurrentPipeline.valid()) if (!mCurrentPipeline)
{ {
ANGLE_TRY(initPipeline(context)); ANGLE_TRY(initPipeline(context));
ASSERT(mCurrentPipeline.valid());
} }
const auto &state = mState.getState(); const auto &state = mState.getState();
...@@ -229,14 +227,14 @@ gl::Error ContextVk::setupDraw(const gl::Context *context, ...@@ -229,14 +227,14 @@ gl::Error ContextVk::setupDraw(const gl::Context *context,
} }
} }
(*commandBuffer)->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, mCurrentPipeline); (*commandBuffer)->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, mCurrentPipeline->get());
(*commandBuffer) (*commandBuffer)
->bindVertexBuffers(0, maxAttrib, vertexHandles.data(), ->bindVertexBuffers(0, maxAttrib, vertexHandles.data(),
reinterpret_cast<const VkDeviceSize *>(zeroBuf->data())); reinterpret_cast<const VkDeviceSize *>(zeroBuf->data()));
// Update the queue serial for the pipeline object. // Update the queue serial for the pipeline object.
// TODO(jmadill): the queue serial should be bound to the pipeline. ASSERT(mCurrentPipeline && mCurrentPipeline->valid());
updateQueueSerial(queueSerial); mCurrentPipeline->updateSerial(queueSerial);
// 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));
...@@ -731,10 +729,9 @@ std::vector<PathImpl *> ContextVk::createPaths(GLsizei) ...@@ -731,10 +729,9 @@ std::vector<PathImpl *> ContextVk::createPaths(GLsizei)
return std::vector<PathImpl *>(); return std::vector<PathImpl *>();
} }
// TODO(jmadill): Use pipeline cache.
void ContextVk::invalidateCurrentPipeline() void ContextVk::invalidateCurrentPipeline()
{ {
mRenderer->releaseResource(*this, &mCurrentPipeline); mCurrentPipeline = nullptr;
} }
void ContextVk::onVertexArrayChange() void ContextVk::onVertexArrayChange()
......
...@@ -19,7 +19,7 @@ namespace rx ...@@ -19,7 +19,7 @@ namespace rx
{ {
class RendererVk; class RendererVk;
class ContextVk : public ContextImpl, public ResourceVk class ContextVk : public ContextImpl
{ {
public: public:
ContextVk(const gl::ContextState &state, RendererVk *renderer); ContextVk(const gl::ContextState &state, RendererVk *renderer);
...@@ -152,9 +152,7 @@ class ContextVk : public ContextImpl, public ResourceVk ...@@ -152,9 +152,7 @@ class ContextVk : public ContextImpl, public ResourceVk
VkDevice getDevice() const; VkDevice getDevice() const;
RendererVk *getRenderer() { return mRenderer; } RendererVk *getRenderer() { return mRenderer; }
// TODO(jmadill): Use pipeline cache.
void invalidateCurrentPipeline(); void invalidateCurrentPipeline();
void onVertexArrayChange(); void onVertexArrayChange();
vk::DescriptorPool *getDescriptorPool(); vk::DescriptorPool *getDescriptorPool();
...@@ -167,7 +165,7 @@ class ContextVk : public ContextImpl, public ResourceVk ...@@ -167,7 +165,7 @@ class ContextVk : public ContextImpl, public ResourceVk
vk::CommandBuffer **commandBuffer); vk::CommandBuffer **commandBuffer);
RendererVk *mRenderer; RendererVk *mRenderer;
vk::Pipeline mCurrentPipeline; vk::PipelineAndSerial *mCurrentPipeline;
GLenum mCurrentDrawMode; GLenum mCurrentDrawMode;
// Keep a cached pipeline description structure that can be used to query the pipeline cache. // Keep a cached pipeline description structure that can be used to query the pipeline cache.
......
...@@ -353,7 +353,6 @@ void FramebufferVk::syncState(const gl::Context *context, ...@@ -353,7 +353,6 @@ void FramebufferVk::syncState(const gl::Context *context,
// Trigger a new set of secondary commands next time we render to this FBO,. // Trigger a new set of secondary commands next time we render to this FBO,.
mLastRenderNodeSerial = Serial(); mLastRenderNodeSerial = Serial();
// TODO(jmadill): Use pipeline cache.
contextVk->invalidateCurrentPipeline(); contextVk->invalidateCurrentPipeline();
} }
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "libANGLE/renderer/vulkan/CompilerVk.h" #include "libANGLE/renderer/vulkan/CompilerVk.h"
#include "libANGLE/renderer/vulkan/FramebufferVk.h" #include "libANGLE/renderer/vulkan/FramebufferVk.h"
#include "libANGLE/renderer/vulkan/GlslangWrapper.h" #include "libANGLE/renderer/vulkan/GlslangWrapper.h"
#include "libANGLE/renderer/vulkan/ProgramVk.h"
#include "libANGLE/renderer/vulkan/TextureVk.h" #include "libANGLE/renderer/vulkan/TextureVk.h"
#include "libANGLE/renderer/vulkan/VertexArrayVk.h" #include "libANGLE/renderer/vulkan/VertexArrayVk.h"
#include "libANGLE/renderer/vulkan/vk_format_utils.h" #include "libANGLE/renderer/vulkan/vk_format_utils.h"
...@@ -144,6 +145,7 @@ RendererVk::~RendererVk() ...@@ -144,6 +145,7 @@ RendererVk::~RendererVk()
mGraphicsPipelineLayout.destroy(mDevice); mGraphicsPipelineLayout.destroy(mDevice);
mRenderPassCache.destroy(mDevice); mRenderPassCache.destroy(mDevice);
mPipelineCache.destroy(mDevice);
if (mGlslangWrapper) if (mGlslangWrapper)
{ {
...@@ -982,4 +984,20 @@ Serial RendererVk::issueProgramSerial() ...@@ -982,4 +984,20 @@ Serial RendererVk::issueProgramSerial()
return mProgramSerialFactory.generate(); return mProgramSerialFactory.generate();
} }
vk::Error RendererVk::getPipeline(const ProgramVk *programVk,
const vk::PipelineDesc &desc,
vk::PipelineAndSerial **pipelineOut)
{
ASSERT(programVk->getVertexModuleSerial() == desc.getShaderStageInfo()[0].moduleSerial);
ASSERT(programVk->getFragmentModuleSerial() == desc.getShaderStageInfo()[1].moduleSerial);
// Pull in a compatible RenderPass.
vk::RenderPass *compatibleRenderPass = nullptr;
ANGLE_TRY(getCompatibleRenderPass(desc.getRenderPassDesc(), &compatibleRenderPass));
return mPipelineCache.getPipeline(mDevice, *compatibleRenderPass, mGraphicsPipelineLayout,
programVk->getLinkedVertexModule(),
programVk->getLinkedFragmentModule(), desc, pipelineOut);
}
} // namespace rx } // namespace rx
...@@ -112,6 +112,10 @@ class RendererVk : angle::NonCopyable ...@@ -112,6 +112,10 @@ class RendererVk : angle::NonCopyable
const vk::AttachmentOpsArray &ops, const vk::AttachmentOpsArray &ops,
vk::RenderPass **renderPassOut); vk::RenderPass **renderPassOut);
vk::Error getPipeline(const ProgramVk *programVk,
const vk::PipelineDesc &desc,
vk::PipelineAndSerial **pipelineOut);
// This should only be called from ResourceVk. // This should only be called from ResourceVk.
// TODO(jmadill): Keep in ContextVk to enable threaded rendering. // TODO(jmadill): Keep in ContextVk to enable threaded rendering.
vk::CommandBufferNode *allocateCommandNode(); vk::CommandBufferNode *allocateCommandNode();
...@@ -176,6 +180,7 @@ class RendererVk : angle::NonCopyable ...@@ -176,6 +180,7 @@ class RendererVk : angle::NonCopyable
vk::FormatTable mFormatTable; vk::FormatTable mFormatTable;
RenderPassCache mRenderPassCache; RenderPassCache mRenderPassCache;
PipelineCache mPipelineCache;
std::vector<vk::CommandBufferNode *> mOpenCommandGraph; std::vector<vk::CommandBufferNode *> mOpenCommandGraph;
// ANGLE uses a single pipeline layout for all GL programs. It is owned here in the Renderer. // ANGLE uses a single pipeline layout for all GL programs. It is owned here in the Renderer.
......
...@@ -47,7 +47,6 @@ void VertexArrayVk::syncState(const gl::Context *context, ...@@ -47,7 +47,6 @@ void VertexArrayVk::syncState(const gl::Context *context,
ASSERT(dirtyBits.any()); ASSERT(dirtyBits.any());
// Invalidate current pipeline. // Invalidate current pipeline.
// TODO(jmadill): Use pipeline cache.
ContextVk *contextVk = vk::GetImpl(context); ContextVk *contextVk = vk::GetImpl(context);
contextVk->onVertexArrayChange(); contextVk->onVertexArrayChange();
......
...@@ -73,7 +73,7 @@ void UnpackStencilState(const vk::PackedStencilOpState &packedState, VkStencilOp ...@@ -73,7 +73,7 @@ void UnpackStencilState(const vk::PackedStencilOpState &packedState, VkStencilOp
stateOut->reference = packedState.reference; stateOut->reference = packedState.reference;
} }
void UnpackBlendAttachmentState(vk::PackedColorBlendAttachmentState &packedState, void UnpackBlendAttachmentState(const vk::PackedColorBlendAttachmentState &packedState,
VkPipelineColorBlendAttachmentState *stateOut) VkPipelineColorBlendAttachmentState *stateOut)
{ {
stateOut->blendEnable = static_cast<VkBool32>(packedState.blendEnable); stateOut->blendEnable = static_cast<VkBool32>(packedState.blendEnable);
...@@ -350,9 +350,12 @@ void PipelineDesc::initDefaults() ...@@ -350,9 +350,12 @@ void PipelineDesc::initDefaults()
blendAttachmentState); blendAttachmentState);
} }
Error PipelineDesc::initializePipeline(RendererVk *renderer, Error PipelineDesc::initializePipeline(VkDevice device,
ProgramVk *programVk, const RenderPass &compatibleRenderPass,
Pipeline *pipelineOut) const PipelineLayout &pipelineLayout,
const ShaderModule &vertexModule,
const ShaderModule &fragmentModule,
Pipeline *pipelineOut) const
{ {
VkPipelineShaderStageCreateInfo shaderStages[2]; VkPipelineShaderStageCreateInfo shaderStages[2];
VkPipelineVertexInputStateCreateInfo vertexInputState; VkPipelineVertexInputStateCreateInfo vertexInputState;
...@@ -366,21 +369,19 @@ Error PipelineDesc::initializePipeline(RendererVk *renderer, ...@@ -366,21 +369,19 @@ Error PipelineDesc::initializePipeline(RendererVk *renderer,
VkPipelineColorBlendStateCreateInfo blendState; VkPipelineColorBlendStateCreateInfo blendState;
VkGraphicsPipelineCreateInfo createInfo; VkGraphicsPipelineCreateInfo createInfo;
ASSERT(programVk->getVertexModuleSerial() == mShaderStageInfo[0].moduleSerial);
shaderStages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; shaderStages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
shaderStages[0].pNext = nullptr; shaderStages[0].pNext = nullptr;
shaderStages[0].flags = 0; shaderStages[0].flags = 0;
shaderStages[0].stage = VK_SHADER_STAGE_VERTEX_BIT; shaderStages[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
shaderStages[0].module = programVk->getLinkedVertexModule().getHandle(); shaderStages[0].module = vertexModule.getHandle();
shaderStages[0].pName = "main"; shaderStages[0].pName = "main";
shaderStages[0].pSpecializationInfo = nullptr; shaderStages[0].pSpecializationInfo = nullptr;
ASSERT(programVk->getFragmentModuleSerial() == mShaderStageInfo[1].moduleSerial);
shaderStages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; shaderStages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
shaderStages[1].pNext = nullptr; shaderStages[1].pNext = nullptr;
shaderStages[1].flags = 0; shaderStages[1].flags = 0;
shaderStages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; shaderStages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
shaderStages[1].module = programVk->getLinkedFragmentModule().getHandle(); shaderStages[1].module = fragmentModule.getHandle();
shaderStages[1].pName = "main"; shaderStages[1].pName = "main";
shaderStages[1].pSpecializationInfo = nullptr; shaderStages[1].pSpecializationInfo = nullptr;
...@@ -512,11 +513,6 @@ Error PipelineDesc::initializePipeline(RendererVk *renderer, ...@@ -512,11 +513,6 @@ Error PipelineDesc::initializePipeline(RendererVk *renderer,
// TODO(jmadill): Dynamic state. // TODO(jmadill): Dynamic state.
// Pull in a compatible RenderPass.
RenderPass *compatibleRenderPass = nullptr;
ANGLE_TRY(renderer->getCompatibleRenderPass(mRenderPassDesc, &compatibleRenderPass));
createInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; createInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
createInfo.pNext = nullptr; createInfo.pNext = nullptr;
createInfo.flags = 0; createInfo.flags = 0;
...@@ -531,17 +527,22 @@ Error PipelineDesc::initializePipeline(RendererVk *renderer, ...@@ -531,17 +527,22 @@ Error PipelineDesc::initializePipeline(RendererVk *renderer,
createInfo.pDepthStencilState = &depthStencilState; createInfo.pDepthStencilState = &depthStencilState;
createInfo.pColorBlendState = &blendState; createInfo.pColorBlendState = &blendState;
createInfo.pDynamicState = nullptr; createInfo.pDynamicState = nullptr;
createInfo.layout = renderer->getGraphicsPipelineLayout().getHandle(); createInfo.layout = pipelineLayout.getHandle();
createInfo.renderPass = compatibleRenderPass->getHandle(); createInfo.renderPass = compatibleRenderPass.getHandle();
createInfo.subpass = 0; createInfo.subpass = 0;
createInfo.basePipelineHandle = VK_NULL_HANDLE; createInfo.basePipelineHandle = VK_NULL_HANDLE;
createInfo.basePipelineIndex = 0; createInfo.basePipelineIndex = 0;
ANGLE_TRY(pipelineOut->initGraphics(renderer->getDevice(), createInfo)); ANGLE_TRY(pipelineOut->initGraphics(device, createInfo));
return NoError(); return NoError();
} }
const ShaderStageInfo &PipelineDesc::getShaderStageInfo() const
{
return mShaderStageInfo;
}
void PipelineDesc::updateShaders(ProgramVk *programVk) void PipelineDesc::updateShaders(ProgramVk *programVk)
{ {
ASSERT(programVk->getVertexModuleSerial() < std::numeric_limits<uint32_t>::max()); ASSERT(programVk->getVertexModuleSerial() < std::numeric_limits<uint32_t>::max());
...@@ -596,6 +597,11 @@ void PipelineDesc::updateLineWidth(float lineWidth) ...@@ -596,6 +597,11 @@ void PipelineDesc::updateLineWidth(float lineWidth)
mRasterizationStateInfo.lineWidth = lineWidth; mRasterizationStateInfo.lineWidth = lineWidth;
} }
const RenderPassDesc &PipelineDesc::getRenderPassDesc() const
{
return mRenderPassDesc;
}
void PipelineDesc::updateRenderPassDesc(const RenderPassDesc &renderPassDesc) void PipelineDesc::updateRenderPassDesc(const RenderPassDesc &renderPassDesc)
{ {
mRenderPassDesc = renderPassDesc; mRenderPassDesc = renderPassDesc;
...@@ -689,6 +695,7 @@ vk::Error RenderPassCache::getCompatibleRenderPass(VkDevice device, ...@@ -689,6 +695,7 @@ vk::Error RenderPassCache::getCompatibleRenderPass(VkDevice device,
ASSERT(!innerCache.empty()); ASSERT(!innerCache.empty());
// Find the first element and return it. // Find the first element and return it.
innerCache.begin()->second.updateSerial(serial);
*renderPassOut = &innerCache.begin()->second.get(); *renderPassOut = &innerCache.begin()->second.get();
return vk::NoError(); return vk::NoError();
} }
...@@ -750,4 +757,51 @@ vk::Error RenderPassCache::getRenderPassWithOps(VkDevice device, ...@@ -750,4 +757,51 @@ vk::Error RenderPassCache::getRenderPassWithOps(VkDevice device,
return vk::NoError(); return vk::NoError();
} }
// PipelineCache implementation.
PipelineCache::PipelineCache()
{
}
PipelineCache::~PipelineCache()
{
ASSERT(mPayload.empty());
}
void PipelineCache::destroy(VkDevice device)
{
for (auto &item : mPayload)
{
item.second.get().destroy(device);
}
mPayload.clear();
}
vk::Error PipelineCache::getPipeline(VkDevice device,
const vk::RenderPass &compatibleRenderPass,
const vk::PipelineLayout &pipelineLayout,
const vk::ShaderModule &vertexModule,
const vk::ShaderModule &fragmentModule,
const vk::PipelineDesc &desc,
vk::PipelineAndSerial **pipelineOut)
{
auto item = mPayload.find(desc);
if (item != mPayload.end())
{
*pipelineOut = &item->second;
return vk::NoError();
}
vk::Pipeline newPipeline;
ANGLE_TRY(desc.initializePipeline(device, compatibleRenderPass, pipelineLayout, vertexModule,
fragmentModule, &newPipeline));
// The Serial will be updated outside of this query.
auto insertedItem =
mPayload.emplace(desc, vk::PipelineAndSerial(std::move(newPipeline), Serial()));
*pipelineOut = &insertedItem.first->second;
return vk::NoError();
}
} // namespace rx } // namespace rx
...@@ -256,11 +256,18 @@ class PipelineDesc final ...@@ -256,11 +256,18 @@ class PipelineDesc final
bool operator==(const PipelineDesc &other) const; bool operator==(const PipelineDesc &other) const;
void initDefaults(); void initDefaults();
Error initializePipeline(RendererVk *renderer, ProgramVk *programVk, Pipeline *pipelineOut);
Error initializePipeline(VkDevice device,
const RenderPass &compatibleRenderPass,
const PipelineLayout &pipelineLayout,
const ShaderModule &vertexModule,
const ShaderModule &fragmentModule,
Pipeline *pipelineOut) const;
void updateViewport(const gl::Rectangle &viewport, float nearPlane, float farPlane); void updateViewport(const gl::Rectangle &viewport, float nearPlane, float farPlane);
// Shader stage info // Shader stage info
const ShaderStageInfo &getShaderStageInfo() const;
void updateShaders(ProgramVk *programVk); void updateShaders(ProgramVk *programVk);
// Vertex input state // Vertex input state
...@@ -276,6 +283,7 @@ class PipelineDesc final ...@@ -276,6 +283,7 @@ class PipelineDesc final
void updateLineWidth(float lineWidth); void updateLineWidth(float lineWidth);
// RenderPass description. // RenderPass description.
const RenderPassDesc &getRenderPassDesc() const;
void updateRenderPassDesc(const RenderPassDesc &renderPassDesc); void updateRenderPassDesc(const RenderPassDesc &renderPassDesc);
private: private:
...@@ -308,6 +316,9 @@ constexpr size_t PipelineDescSumOfSizes = ...@@ -308,6 +316,9 @@ constexpr size_t PipelineDescSumOfSizes =
sizeof(RenderPassDesc); sizeof(RenderPassDesc);
static_assert(sizeof(PipelineDesc) == PipelineDescSumOfSizes, "Size mismatch"); static_assert(sizeof(PipelineDesc) == PipelineDescSumOfSizes, "Size mismatch");
using RenderPassAndSerial = ObjectAndSerial<RenderPass>;
using PipelineAndSerial = ObjectAndSerial<Pipeline>;
} // namespace vk } // namespace vk
} // namespace rx } // namespace rx
...@@ -325,12 +336,19 @@ struct hash<rx::vk::AttachmentOpsArray> ...@@ -325,12 +336,19 @@ struct hash<rx::vk::AttachmentOpsArray>
{ {
size_t operator()(const rx::vk::AttachmentOpsArray &key) const { return key.hash(); } size_t operator()(const rx::vk::AttachmentOpsArray &key) const { return key.hash(); }
}; };
template <>
struct hash<rx::vk::PipelineDesc>
{
size_t operator()(const rx::vk::PipelineDesc &key) const { return key.hash(); }
};
} // namespace std } // namespace std
namespace rx namespace rx
{ {
// TODO(jmadill): Add cache trimming. // TODO(jmadill): Add cache trimming/eviction.
class RenderPassCache class RenderPassCache final : angle::NonCopyable
{ {
public: public:
RenderPassCache(); RenderPassCache();
...@@ -357,6 +375,27 @@ class RenderPassCache ...@@ -357,6 +375,27 @@ class RenderPassCache
OuterCache mPayload; OuterCache mPayload;
}; };
// TODO(jmadill): Add cache trimming/eviction.
class PipelineCache final : angle::NonCopyable
{
public:
PipelineCache();
~PipelineCache();
void destroy(VkDevice device);
vk::Error getPipeline(VkDevice device,
const vk::RenderPass &compatibleRenderPass,
const vk::PipelineLayout &pipelineLayout,
const vk::ShaderModule &vertexModule,
const vk::ShaderModule &fragmentModule,
const vk::PipelineDesc &desc,
vk::PipelineAndSerial **pipelineOut);
private:
std::unordered_map<vk::PipelineDesc, vk::PipelineAndSerial> mPayload;
};
} // namespace rx } // namespace rx
#endif // LIBANGLE_RENDERER_VULKAN_VK_CACHE_UTILS_H_ #endif // LIBANGLE_RENDERER_VULKAN_VK_CACHE_UTILS_H_
...@@ -631,6 +631,8 @@ class ObjectAndSerial final : angle::NonCopyable ...@@ -631,6 +631,8 @@ class ObjectAndSerial final : angle::NonCopyable
const ObjT &get() const { return mObject; } const ObjT &get() const { return mObject; }
ObjT &get() { return mObject; } ObjT &get() { return mObject; }
bool valid() const { return mObject.valid(); }
private: private:
ObjT mObject; ObjT mObject;
Serial mQueueSerial; Serial mQueueSerial;
...@@ -652,8 +654,6 @@ struct BufferAndMemory final : private angle::NonCopyable ...@@ -652,8 +654,6 @@ struct BufferAndMemory final : private angle::NonCopyable
vk::DeviceMemory memory; vk::DeviceMemory memory;
}; };
using RenderPassAndSerial = ObjectAndSerial<RenderPass>;
} // namespace vk } // namespace vk
namespace gl_vk namespace gl_vk
......
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