Commit dc65c5bd by Jamie Madill Committed by Commit Bot

Vulkan: Cache pipelines with Shader Programs.

This allows for a few nice things. First and foremost it reduces the size of the PipelineDesc, which is now 232 bytes. It also allows us to completely forego pipeline caches for compute shaders. We also allow sharing vertex and fragment shaders among multiple programs for internal shaders. This is good for memory savings. To allow this we keep the shaders as ref counted objects. Bug: angleproject:2522 Change-Id: I2322be5061979d9669a0b25c152359561eeb80ee Reviewed-on: https://chromium-review.googlesource.com/c/1344449 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 9f379f49
...@@ -248,21 +248,9 @@ angle::Result ContextVk::initPipeline() ...@@ -248,21 +248,9 @@ angle::Result ContextVk::initPipeline()
// Ensure that the RenderPass description is updated. // Ensure that the RenderPass description is updated.
mGraphicsPipelineDesc->updateRenderPassDesc(mDrawFramebuffer->getRenderPassDesc()); mGraphicsPipelineDesc->updateRenderPassDesc(mDrawFramebuffer->getRenderPassDesc());
// Trigger draw call shader patching and fill out the pipeline desc. // Draw call shader patching, shader compilation, and pipeline cache query.
const vk::ShaderAndSerial *vertexShaderAndSerial = nullptr; return mProgram->getGraphicsPipeline(this, mCurrentDrawMode, *mGraphicsPipelineDesc,
const vk::ShaderAndSerial *fragmentShaderAndSerial = nullptr; activeAttribLocationsMask, &mCurrentPipeline);
const vk::PipelineLayout *pipelineLayout = nullptr;
ANGLE_TRY(mProgram->initShaders(this, mCurrentDrawMode, &vertexShaderAndSerial,
&fragmentShaderAndSerial, &pipelineLayout));
mGraphicsPipelineDesc->updateShaders(vertexShaderAndSerial->getSerial(),
fragmentShaderAndSerial->getSerial());
ANGLE_TRY(mRenderer->getPipeline(this, *vertexShaderAndSerial, *fragmentShaderAndSerial,
*pipelineLayout, *mGraphicsPipelineDesc,
activeAttribLocationsMask, &mCurrentPipeline));
return angle::Result::Continue();
} }
angle::Result ContextVk::setupDraw(const gl::Context *context, angle::Result ContextVk::setupDraw(const gl::Context *context,
......
...@@ -1009,20 +1009,14 @@ angle::Result FramebufferVk::clearWithClearAttachments( ...@@ -1009,20 +1009,14 @@ angle::Result FramebufferVk::clearWithClearAttachments(
angle::Result FramebufferVk::clearWithDraw(ContextVk *contextVk, angle::Result FramebufferVk::clearWithDraw(ContextVk *contextVk,
VkColorComponentFlags colorMaskFlags) VkColorComponentFlags colorMaskFlags)
{ {
RendererVk *renderer = contextVk->getRenderer(); RendererVk *renderer = contextVk->getRenderer();
vk::ShaderLibrary *shaderLibrary = renderer->getShaderLibrary();
vk::ShaderProgramHelper *fullScreenClear = nullptr;
ANGLE_TRY(renderer->getFullScreenClearShaderProgram(contextVk, &fullScreenClear));
// Trigger a new command node to ensure overlapping writes happen sequentially. // Trigger a new command node to ensure overlapping writes happen sequentially.
mFramebuffer.finishCurrentCommands(renderer); mFramebuffer.finishCurrentCommands(renderer);
const vk::ShaderAndSerial *fullScreenQuad = nullptr;
ANGLE_TRY(shaderLibrary->getShader(contextVk, vk::InternalShaderID::FullScreenQuad_vert,
&fullScreenQuad));
const vk::ShaderAndSerial *pushConstantColor = nullptr;
ANGLE_TRY(shaderLibrary->getShader(contextVk, vk::InternalShaderID::PushConstantColor_frag,
&pushConstantColor));
// The shader uses a simple pipeline layout with a push constant range. // The shader uses a simple pipeline layout with a push constant range.
vk::PipelineLayoutDesc pipelineLayoutDesc; vk::PipelineLayoutDesc pipelineLayoutDesc;
pipelineLayoutDesc.updatePushConstantRange(gl::ShaderType::Fragment, 0, pipelineLayoutDesc.updatePushConstantRange(gl::ShaderType::Fragment, 0,
...@@ -1047,12 +1041,10 @@ angle::Result FramebufferVk::clearWithDraw(ContextVk *contextVk, ...@@ -1047,12 +1041,10 @@ angle::Result FramebufferVk::clearWithDraw(ContextVk *contextVk,
pipelineDesc.initDefaults(); pipelineDesc.initDefaults();
pipelineDesc.updateColorWriteMask(colorMaskFlags, getEmulatedAlphaAttachmentMask()); pipelineDesc.updateColorWriteMask(colorMaskFlags, getEmulatedAlphaAttachmentMask());
pipelineDesc.updateRenderPassDesc(getRenderPassDesc()); pipelineDesc.updateRenderPassDesc(getRenderPassDesc());
pipelineDesc.updateShaders(fullScreenQuad->getSerial(), pushConstantColor->getSerial());
vk::PipelineAndSerial *pipeline = nullptr; vk::PipelineAndSerial *pipeline = nullptr;
ANGLE_TRY(renderer->getPipeline(contextVk, *fullScreenQuad, *pushConstantColor, ANGLE_TRY(fullScreenClear->getGraphicsPipeline(contextVk, pipelineLayout.get(), pipelineDesc,
pipelineLayout.get(), pipelineDesc, gl::AttributesMask(), gl::AttributesMask(), &pipeline));
&pipeline));
pipeline->updateSerial(renderer->getCurrentQueueSerial()); pipeline->updateSerial(renderer->getCurrentQueueSerial());
vk::CommandBuffer *writeCommands = nullptr; vk::CommandBuffer *writeCommands = nullptr;
......
...@@ -144,13 +144,10 @@ ProgramVk::ShaderInfo::ShaderInfo() ...@@ -144,13 +144,10 @@ ProgramVk::ShaderInfo::ShaderInfo()
ProgramVk::ShaderInfo::~ShaderInfo() = default; ProgramVk::ShaderInfo::~ShaderInfo() = default;
angle::Result ProgramVk::ShaderInfo::getShaders( angle::Result ProgramVk::ShaderInfo::initShaders(ContextVk *contextVk,
ContextVk *contextVk, const std::string &vertexSource,
const std::string &vertexSource, const std::string &fragmentSource,
const std::string &fragmentSource, bool enableLineRasterEmulation)
bool enableLineRasterEmulation,
const vk::ShaderAndSerial **vertexShaderAndSerialOut,
const vk::ShaderAndSerial **fragmentShaderAndSerialOut)
{ {
if (!valid()) if (!valid())
{ {
...@@ -160,26 +157,32 @@ angle::Result ProgramVk::ShaderInfo::getShaders( ...@@ -160,26 +157,32 @@ angle::Result ProgramVk::ShaderInfo::getShaders(
enableLineRasterEmulation, vertexSource, enableLineRasterEmulation, vertexSource,
fragmentSource, &vertexCode, &fragmentCode)); fragmentSource, &vertexCode, &fragmentCode));
ANGLE_TRY(vk::InitShaderAndSerial(contextVk, &mVertexShaderAndSerial, vertexCode.data(), ANGLE_TRY(vk::InitShaderAndSerial(contextVk, &mShaders[gl::ShaderType::Vertex].get(),
vertexCode.size() * sizeof(uint32_t))); vertexCode.data(), vertexCode.size() * sizeof(uint32_t)));
ANGLE_TRY(vk::InitShaderAndSerial(contextVk, &mFragmentShaderAndSerial, fragmentCode.data(), ANGLE_TRY(vk::InitShaderAndSerial(contextVk, &mShaders[gl::ShaderType::Fragment].get(),
fragmentCode.data(),
fragmentCode.size() * sizeof(uint32_t))); fragmentCode.size() * sizeof(uint32_t)));
mProgramHelper.setShader(gl::ShaderType::Vertex, &mShaders[gl::ShaderType::Vertex]);
mProgramHelper.setShader(gl::ShaderType::Fragment, &mShaders[gl::ShaderType::Fragment]);
} }
*fragmentShaderAndSerialOut = &mFragmentShaderAndSerial;
*vertexShaderAndSerialOut = &mVertexShaderAndSerial;
return angle::Result::Continue(); return angle::Result::Continue();
} }
void ProgramVk::ShaderInfo::destroy(VkDevice device) void ProgramVk::ShaderInfo::release(RendererVk *renderer)
{ {
mVertexShaderAndSerial.destroy(device); mProgramHelper.release(renderer);
mFragmentShaderAndSerial.destroy(device);
for (vk::RefCounted<vk::ShaderAndSerial> &shader : mShaders)
{
shader.get().destroy(renderer->getDevice());
}
} }
bool ProgramVk::ShaderInfo::valid() const bool ProgramVk::ShaderInfo::valid() const
{ {
return mVertexShaderAndSerial.valid(); return mShaders[gl::ShaderType::Vertex].get().valid();
} }
// ProgramVk implementation. // ProgramVk implementation.
...@@ -201,29 +204,24 @@ ProgramVk::~ProgramVk() = default; ...@@ -201,29 +204,24 @@ ProgramVk::~ProgramVk() = default;
void ProgramVk::destroy(const gl::Context *context) void ProgramVk::destroy(const gl::Context *context)
{ {
ContextVk *contextVk = vk::GetImpl(context); ContextVk *contextVk = vk::GetImpl(context);
reset(contextVk->getRenderer());
// We don't interrupt exectution in destructors.
(void)reset(contextVk);
} }
angle::Result ProgramVk::reset(ContextVk *contextVk) void ProgramVk::reset(RendererVk *renderer)
{ {
VkDevice device = contextVk->getDevice();
for (auto &descriptorSetLayout : mDescriptorSetLayouts) for (auto &descriptorSetLayout : mDescriptorSetLayouts)
{ {
descriptorSetLayout.reset(); descriptorSetLayout.reset();
} }
mPipelineLayout.reset(); mPipelineLayout.reset();
RendererVk *renderer = contextVk->getRenderer();
for (auto &uniformBlock : mDefaultUniformBlocks) for (auto &uniformBlock : mDefaultUniformBlocks)
{ {
uniformBlock.storage.release(renderer); uniformBlock.storage.release(renderer);
} }
mDefaultShaderInfo.destroy(device); mDefaultShaderInfo.release(renderer);
mLineRasterShaderInfo.destroy(device); mLineRasterShaderInfo.release(renderer);
Serial currentSerial = renderer->getCurrentQueueSerial(); Serial currentSerial = renderer->getCurrentQueueSerial();
renderer->releaseObject(currentSerial, &mEmptyUniformBlockStorage.memory); renderer->releaseObject(currentSerial, &mEmptyUniformBlockStorage.memory);
...@@ -236,8 +234,6 @@ angle::Result ProgramVk::reset(ContextVk *contextVk) ...@@ -236,8 +234,6 @@ angle::Result ProgramVk::reset(ContextVk *contextVk)
{ {
binding.reset(); binding.reset();
} }
return angle::Result::Continue();
} }
angle::Result ProgramVk::load(const gl::Context *context, angle::Result ProgramVk::load(const gl::Context *context,
...@@ -279,7 +275,7 @@ angle::Result ProgramVk::linkImpl(const gl::Context *glContext, ...@@ -279,7 +275,7 @@ angle::Result ProgramVk::linkImpl(const gl::Context *glContext,
ContextVk *contextVk = vk::GetImpl(glContext); ContextVk *contextVk = vk::GetImpl(glContext);
RendererVk *renderer = contextVk->getRenderer(); RendererVk *renderer = contextVk->getRenderer();
ANGLE_TRY(reset(contextVk)); reset(renderer);
GlslangWrapper::GetShaderSource(mState, resources, &mVertexSource, &mFragmentSource); GlslangWrapper::GetShaderSource(mState, resources, &mVertexSource, &mFragmentSource);
...@@ -743,27 +739,22 @@ void ProgramVk::setPathFragmentInputGen(const std::string &inputName, ...@@ -743,27 +739,22 @@ void ProgramVk::setPathFragmentInputGen(const std::string &inputName,
angle::Result ProgramVk::initShaders(ContextVk *contextVk, angle::Result ProgramVk::initShaders(ContextVk *contextVk,
gl::PrimitiveMode mode, gl::PrimitiveMode mode,
const vk::ShaderAndSerial **vertexShaderAndSerialOut, vk::ShaderProgramHelper **programOut)
const vk::ShaderAndSerial **fragmentShaderAndSerialOut,
const vk::PipelineLayout **pipelineLayoutOut)
{ {
if (UseLineRaster(contextVk, mode)) if (UseLineRaster(contextVk, mode))
{ {
ANGLE_TRY(mLineRasterShaderInfo.getShaders(contextVk, mVertexSource, mFragmentSource, true, ANGLE_TRY(
vertexShaderAndSerialOut, mLineRasterShaderInfo.initShaders(contextVk, mVertexSource, mFragmentSource, true));
fragmentShaderAndSerialOut));
ASSERT(mLineRasterShaderInfo.valid()); ASSERT(mLineRasterShaderInfo.valid());
*programOut = &mLineRasterShaderInfo.getShaderProgram();
} }
else else
{ {
ANGLE_TRY(mDefaultShaderInfo.getShaders(contextVk, mVertexSource, mFragmentSource, false, ANGLE_TRY(mDefaultShaderInfo.initShaders(contextVk, mVertexSource, mFragmentSource, false));
vertexShaderAndSerialOut,
fragmentShaderAndSerialOut));
ASSERT(mDefaultShaderInfo.valid()); ASSERT(mDefaultShaderInfo.valid());
*programOut = &mDefaultShaderInfo.getShaderProgram();
} }
*pipelineLayoutOut = &mPipelineLayout.get();
return angle::Result::Continue(); return angle::Result::Continue();
} }
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <array> #include <array>
#include "libANGLE/renderer/ProgramImpl.h" #include "libANGLE/renderer/ProgramImpl.h"
#include "libANGLE/renderer/vulkan/ContextVk.h"
#include "libANGLE/renderer/vulkan/RendererVk.h" #include "libANGLE/renderer/vulkan/RendererVk.h"
#include "libANGLE/renderer/vulkan/vk_helpers.h" #include "libANGLE/renderer/vulkan/vk_helpers.h"
...@@ -96,11 +97,6 @@ class ProgramVk : public ProgramImpl ...@@ -96,11 +97,6 @@ class ProgramVk : public ProgramImpl
const GLfloat *coeffs) override; const GLfloat *coeffs) override;
// Also initializes the pipeline layout, descriptor set layouts, and used descriptor ranges. // Also initializes the pipeline layout, descriptor set layouts, and used descriptor ranges.
angle::Result initShaders(ContextVk *contextVk,
gl::PrimitiveMode mode,
const vk::ShaderAndSerial **vertexShaderAndSerialOut,
const vk::ShaderAndSerial **fragmentShaderAndSerialOut,
const vk::PipelineLayout **pipelineLayoutOut);
angle::Result updateUniforms(ContextVk *contextVk); angle::Result updateUniforms(ContextVk *contextVk);
angle::Result updateTexturesDescriptorSet(ContextVk *contextVk); angle::Result updateTexturesDescriptorSet(ContextVk *contextVk);
...@@ -116,6 +112,19 @@ class ProgramVk : public ProgramImpl ...@@ -116,6 +112,19 @@ class ProgramVk : public ProgramImpl
bool dirtyUniforms() const { return mDefaultUniformBlocksDirty.any(); } bool dirtyUniforms() const { return mDefaultUniformBlocksDirty.any(); }
angle::Result getGraphicsPipeline(ContextVk *contextVk,
gl::PrimitiveMode mode,
const vk::GraphicsPipelineDesc &desc,
const gl::AttributesMask &activeAttribLocations,
vk::PipelineAndSerial **pipelineOut)
{
vk::ShaderProgramHelper *shaderProgram;
ANGLE_TRY(initShaders(contextVk, mode, &shaderProgram));
ASSERT(shaderProgram->isGraphicsProgram());
return shaderProgram->getGraphicsPipeline(contextVk, mPipelineLayout.get(), desc,
activeAttribLocations, pipelineOut);
}
private: private:
template <int cols, int rows> template <int cols, int rows>
void setUniformMatrixfv(GLint location, void setUniformMatrixfv(GLint location,
...@@ -123,7 +132,7 @@ class ProgramVk : public ProgramImpl ...@@ -123,7 +132,7 @@ class ProgramVk : public ProgramImpl
GLboolean transpose, GLboolean transpose,
const GLfloat *value); const GLfloat *value);
angle::Result reset(ContextVk *contextVk); void reset(RendererVk *renderer);
angle::Result allocateDescriptorSet(ContextVk *contextVk, uint32_t descriptorSetIndex); angle::Result allocateDescriptorSet(ContextVk *contextVk, uint32_t descriptorSetIndex);
angle::Result initDefaultUniformBlocks(const gl::Context *glContext); angle::Result initDefaultUniformBlocks(const gl::Context *glContext);
...@@ -138,6 +147,10 @@ class ProgramVk : public ProgramImpl ...@@ -138,6 +147,10 @@ class ProgramVk : public ProgramImpl
const gl::ProgramLinkedResources &resources, const gl::ProgramLinkedResources &resources,
gl::InfoLog &infoLog); gl::InfoLog &infoLog);
angle::Result initShaders(ContextVk *contextVk,
gl::PrimitiveMode mode,
vk::ShaderProgramHelper **shaderProgramOut);
// State for the default uniform blocks. // State for the default uniform blocks.
struct DefaultUniformBlock final : private angle::NonCopyable struct DefaultUniformBlock final : private angle::NonCopyable
{ {
...@@ -182,18 +195,18 @@ class ProgramVk : public ProgramImpl ...@@ -182,18 +195,18 @@ class ProgramVk : public ProgramImpl
ShaderInfo(); ShaderInfo();
~ShaderInfo(); ~ShaderInfo();
angle::Result getShaders(ContextVk *contextVk, angle::Result initShaders(ContextVk *contextVk,
const std::string &vertexSource, const std::string &vertexSource,
const std::string &fragmentSource, const std::string &fragmentSource,
bool enableLineRasterEmulation, bool enableLineRasterEmulation);
const vk::ShaderAndSerial **vertexShaderAndSerialOut, void release(RendererVk *renderer);
const vk::ShaderAndSerial **fragmentShaderAndSerialOut);
void destroy(VkDevice device);
bool valid() const; bool valid() const;
vk::ShaderProgramHelper &getShaderProgram() { return mProgramHelper; }
private: private:
vk::ShaderAndSerial mVertexShaderAndSerial; vk::ShaderProgramHelper mProgramHelper;
vk::ShaderAndSerial mFragmentShaderAndSerial; gl::ShaderMap<vk::RefCounted<vk::ShaderAndSerial>> mShaders;
}; };
ShaderInfo mDefaultShaderInfo; ShaderInfo mDefaultShaderInfo;
......
...@@ -333,9 +333,10 @@ void RendererVk::onDestroy(vk::Context *context) ...@@ -333,9 +333,10 @@ void RendererVk::onDestroy(vk::Context *context)
mPipelineLayoutCache.destroy(mDevice); mPipelineLayoutCache.destroy(mDevice);
mDescriptorSetLayoutCache.destroy(mDevice); mDescriptorSetLayoutCache.destroy(mDevice);
mFullScreenClearShaderProgram.destroy(mDevice);
mRenderPassCache.destroy(mDevice); mRenderPassCache.destroy(mDevice);
mGraphicsPipelineCache.destroy(mDevice); mPipelineCache.destroy(mDevice);
mPipelineCacheVk.destroy(mDevice);
mSubmitSemaphorePool.destroy(mDevice); mSubmitSemaphorePool.destroy(mDevice);
mShaderLibrary.destroy(mDevice); mShaderLibrary.destroy(mDevice);
mGpuEventQueryPool.destroy(mDevice); mGpuEventQueryPool.destroy(mDevice);
...@@ -637,7 +638,7 @@ angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueF ...@@ -637,7 +638,7 @@ angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueF
ANGLE_VK_TRY(displayVk, mCommandPool.init(mDevice, commandPoolInfo)); ANGLE_VK_TRY(displayVk, mCommandPool.init(mDevice, commandPoolInfo));
// Initialize the vulkan pipeline cache. // Initialize the vulkan pipeline cache.
ANGLE_TRY(initPipelineCacheVk(displayVk)); ANGLE_TRY(initPipelineCache(displayVk));
// Initialize the submission semaphore pool. // Initialize the submission semaphore pool.
ANGLE_TRY(mSubmitSemaphorePool.init(displayVk, vk::kDefaultSemaphorePoolSize)); ANGLE_TRY(mSubmitSemaphorePool.init(displayVk, vk::kDefaultSemaphorePoolSize));
...@@ -808,7 +809,7 @@ void RendererVk::initPipelineCacheVkKey() ...@@ -808,7 +809,7 @@ void RendererVk::initPipelineCacheVkKey()
hashString.length(), mPipelineCacheVkBlobKey.data()); hashString.length(), mPipelineCacheVkBlobKey.data());
} }
angle::Result RendererVk::initPipelineCacheVk(DisplayVk *display) angle::Result RendererVk::initPipelineCache(DisplayVk *display)
{ {
initPipelineCacheVkKey(); initPipelineCacheVkKey();
...@@ -823,7 +824,7 @@ angle::Result RendererVk::initPipelineCacheVk(DisplayVk *display) ...@@ -823,7 +824,7 @@ angle::Result RendererVk::initPipelineCacheVk(DisplayVk *display)
pipelineCacheCreateInfo.initialDataSize = success ? initialData.size() : 0; pipelineCacheCreateInfo.initialDataSize = success ? initialData.size() : 0;
pipelineCacheCreateInfo.pInitialData = success ? initialData.data() : nullptr; pipelineCacheCreateInfo.pInitialData = success ? initialData.data() : nullptr;
ANGLE_VK_TRY(display, mPipelineCacheVk.init(mDevice, pipelineCacheCreateInfo)); ANGLE_VK_TRY(display, mPipelineCache.init(mDevice, pipelineCacheCreateInfo));
return angle::Result::Continue(); return angle::Result::Continue();
} }
...@@ -1164,29 +1165,6 @@ Serial RendererVk::issueShaderSerial() ...@@ -1164,29 +1165,6 @@ Serial RendererVk::issueShaderSerial()
return mShaderSerialFactory.generate(); return mShaderSerialFactory.generate();
} }
angle::Result RendererVk::getPipeline(vk::Context *context,
const vk::ShaderAndSerial &vertexShader,
const vk::ShaderAndSerial &fragmentShader,
const vk::PipelineLayout &pipelineLayout,
const vk::GraphicsPipelineDesc &pipelineDesc,
const gl::AttributesMask &activeAttribLocationsMask,
vk::PipelineAndSerial **pipelineOut)
{
ASSERT(vertexShader.getSerial() ==
pipelineDesc.getShaderStageInfo()[vk::ShaderType::VertexShader].moduleSerial);
ASSERT(fragmentShader.getSerial() ==
pipelineDesc.getShaderStageInfo()[vk::ShaderType::FragmentShader].moduleSerial);
// Pull in a compatible RenderPass.
vk::RenderPass *compatibleRenderPass = nullptr;
ANGLE_TRY(
getCompatibleRenderPass(context, pipelineDesc.getRenderPassDesc(), &compatibleRenderPass));
return mGraphicsPipelineCache.getPipeline(
context, mPipelineCacheVk, *compatibleRenderPass, pipelineLayout, activeAttribLocationsMask,
vertexShader.get(), fragmentShader.get(), pipelineDesc, pipelineOut);
}
angle::Result RendererVk::getDescriptorSetLayout( angle::Result RendererVk::getDescriptorSetLayout(
vk::Context *context, vk::Context *context,
const vk::DescriptorSetLayoutDesc &desc, const vk::DescriptorSetLayoutDesc &desc,
...@@ -1207,7 +1185,7 @@ angle::Result RendererVk::getPipelineLayout( ...@@ -1207,7 +1185,7 @@ angle::Result RendererVk::getPipelineLayout(
angle::Result RendererVk::syncPipelineCacheVk(DisplayVk *displayVk) angle::Result RendererVk::syncPipelineCacheVk(DisplayVk *displayVk)
{ {
ASSERT(mPipelineCacheVk.valid()); ASSERT(mPipelineCache.valid());
if (--mPipelineCacheVkUpdateTimeout > 0) if (--mPipelineCacheVkUpdateTimeout > 0)
{ {
...@@ -1218,7 +1196,7 @@ angle::Result RendererVk::syncPipelineCacheVk(DisplayVk *displayVk) ...@@ -1218,7 +1196,7 @@ angle::Result RendererVk::syncPipelineCacheVk(DisplayVk *displayVk)
// Get the size of the cache. // Get the size of the cache.
size_t pipelineCacheSize = 0; size_t pipelineCacheSize = 0;
VkResult result = mPipelineCacheVk.getCacheData(mDevice, &pipelineCacheSize, nullptr); VkResult result = mPipelineCache.getCacheData(mDevice, &pipelineCacheSize, nullptr);
if (result != VK_INCOMPLETE) if (result != VK_INCOMPLETE)
{ {
ANGLE_VK_TRY(displayVk, result); ANGLE_VK_TRY(displayVk, result);
...@@ -1229,7 +1207,7 @@ angle::Result RendererVk::syncPipelineCacheVk(DisplayVk *displayVk) ...@@ -1229,7 +1207,7 @@ angle::Result RendererVk::syncPipelineCacheVk(DisplayVk *displayVk)
displayVk->getScratchBuffer(pipelineCacheSize, &pipelineCacheData)); displayVk->getScratchBuffer(pipelineCacheSize, &pipelineCacheData));
size_t originalPipelineCacheSize = pipelineCacheSize; size_t originalPipelineCacheSize = pipelineCacheSize;
result = mPipelineCacheVk.getCacheData(mDevice, &pipelineCacheSize, pipelineCacheData->data()); result = mPipelineCache.getCacheData(mDevice, &pipelineCacheSize, pipelineCacheData->data());
// Note: currently we don't accept incomplete as we don't expect it (the full size of cache // Note: currently we don't accept incomplete as we don't expect it (the full size of cache
// was determined just above), so receiving it hints at an implementation bug we would want // was determined just above), so receiving it hints at an implementation bug we would want
// to know about early. // to know about early.
...@@ -1276,9 +1254,25 @@ const vk::Semaphore *RendererVk::getSubmitLastSignaledSemaphore(vk::Context *con ...@@ -1276,9 +1254,25 @@ const vk::Semaphore *RendererVk::getSubmitLastSignaledSemaphore(vk::Context *con
return semaphore; return semaphore;
} }
vk::ShaderLibrary *RendererVk::getShaderLibrary() angle::Result RendererVk::getFullScreenClearShaderProgram(vk::Context *context,
vk::ShaderProgramHelper **programOut)
{ {
return &mShaderLibrary; if (!mFullScreenClearShaderProgram.valid())
{
vk::RefCounted<vk::ShaderAndSerial> *fullScreenQuad = nullptr;
ANGLE_TRY(mShaderLibrary.getShader(context, vk::InternalShaderID::FullScreenQuad_vert,
&fullScreenQuad));
vk::RefCounted<vk::ShaderAndSerial> *pushConstantColor = nullptr;
ANGLE_TRY(mShaderLibrary.getShader(context, vk::InternalShaderID::PushConstantColor_frag,
&pushConstantColor));
mFullScreenClearShaderProgram.setShader(gl::ShaderType::Vertex, fullScreenQuad);
mFullScreenClearShaderProgram.setShader(gl::ShaderType::Fragment, pushConstantColor);
}
*programOut = &mFullScreenClearShaderProgram;
return angle::Result::Continue();
} }
angle::Result RendererVk::getTimestamp(vk::Context *context, uint64_t *timestampOut) angle::Result RendererVk::getTimestamp(vk::Context *context, uint64_t *timestampOut)
......
...@@ -129,15 +129,6 @@ class RendererVk : angle::NonCopyable ...@@ -129,15 +129,6 @@ class RendererVk : angle::NonCopyable
const vk::AttachmentOpsArray &ops, const vk::AttachmentOpsArray &ops,
vk::RenderPass **renderPassOut); vk::RenderPass **renderPassOut);
// For getting a vk::Pipeline and checking the pipeline cache.
angle::Result getPipeline(vk::Context *context,
const vk::ShaderAndSerial &vertexShader,
const vk::ShaderAndSerial &fragmentShader,
const vk::PipelineLayout &pipelineLayout,
const vk::GraphicsPipelineDesc &pipelineDesc,
const gl::AttributesMask &activeAttribLocationsMask,
vk::PipelineAndSerial **pipelineOut);
// Queries the descriptor set layout cache. Creates the layout if not present. // Queries the descriptor set layout cache. Creates the layout if not present.
angle::Result getDescriptorSetLayout( angle::Result getDescriptorSetLayout(
vk::Context *context, vk::Context *context,
...@@ -169,7 +160,8 @@ class RendererVk : angle::NonCopyable ...@@ -169,7 +160,8 @@ class RendererVk : angle::NonCopyable
// Issues a new serial for linked shader modules. Used in the pipeline cache. // Issues a new serial for linked shader modules. Used in the pipeline cache.
Serial issueShaderSerial(); Serial issueShaderSerial();
vk::ShaderLibrary *getShaderLibrary(); angle::Result getFullScreenClearShaderProgram(vk::Context *context,
vk::ShaderProgramHelper **programOut);
const angle::FeaturesVk &getFeatures() const { return mFeatures; } const angle::FeaturesVk &getFeatures() const { return mFeatures; }
angle::Result getTimestamp(vk::Context *context, uint64_t *timestampOut); angle::Result getTimestamp(vk::Context *context, uint64_t *timestampOut);
...@@ -189,6 +181,8 @@ class RendererVk : angle::NonCopyable ...@@ -189,6 +181,8 @@ class RendererVk : angle::NonCopyable
bool isMockICDEnabled() const { return mEnableMockICD; } bool isMockICDEnabled() const { return mEnableMockICD; }
const vk::PipelineCache &getPipelineCache() const { return mPipelineCache; }
private: private:
// Number of semaphores for external entities to renderer to issue a wait, such as surface's // Number of semaphores for external entities to renderer to issue a wait, such as surface's
// image acquire. // image acquire.
...@@ -210,7 +204,7 @@ class RendererVk : angle::NonCopyable ...@@ -210,7 +204,7 @@ class RendererVk : angle::NonCopyable
angle::Result flushCommandGraph(vk::Context *context, vk::CommandBuffer *commandBatch); angle::Result flushCommandGraph(vk::Context *context, vk::CommandBuffer *commandBatch);
void initFeatures(); void initFeatures();
void initPipelineCacheVkKey(); void initPipelineCacheVkKey();
angle::Result initPipelineCacheVk(DisplayVk *display); angle::Result initPipelineCache(DisplayVk *display);
angle::Result synchronizeCpuGpuTime(vk::Context *context); angle::Result synchronizeCpuGpuTime(vk::Context *context);
angle::Result traceGpuEventImpl(vk::Context *context, angle::Result traceGpuEventImpl(vk::Context *context,
...@@ -269,9 +263,8 @@ class RendererVk : angle::NonCopyable ...@@ -269,9 +263,8 @@ class RendererVk : angle::NonCopyable
vk::FormatTable mFormatTable; vk::FormatTable mFormatTable;
RenderPassCache mRenderPassCache; RenderPassCache mRenderPassCache;
GraphicsPipelineCache mGraphicsPipelineCache;
vk::PipelineCache mPipelineCacheVk; vk::PipelineCache mPipelineCache;
egl::BlobCache::Key mPipelineCacheVkBlobKey; egl::BlobCache::Key mPipelineCacheVkBlobKey;
uint32_t mPipelineCacheVkUpdateTimeout; uint32_t mPipelineCacheVkUpdateTimeout;
...@@ -306,6 +299,7 @@ class RendererVk : angle::NonCopyable ...@@ -306,6 +299,7 @@ class RendererVk : angle::NonCopyable
// Internal shader library. // Internal shader library.
vk::ShaderLibrary mShaderLibrary; vk::ShaderLibrary mShaderLibrary;
vk::ShaderProgramHelper mFullScreenClearShaderProgram;
// The GpuEventQuery struct holds together a timestamp query and enough data to create a // The GpuEventQuery struct holds together a timestamp query and enough data to create a
// trace event based on that. Use traceGpuEvent to insert such queries. They will be readback // trace event based on that. Use traceGpuEvent to insert such queries. They will be readback
......
...@@ -672,21 +672,6 @@ angle::Result GraphicsPipelineDesc::initializePipeline( ...@@ -672,21 +672,6 @@ angle::Result GraphicsPipelineDesc::initializePipeline(
return angle::Result::Continue(); return angle::Result::Continue();
} }
const ShaderStageInfo &GraphicsPipelineDesc::getShaderStageInfo() const
{
return mShaderStageInfo;
}
void GraphicsPipelineDesc::updateShaders(Serial vertexSerial, Serial fragmentSerial)
{
ASSERT(vertexSerial < std::numeric_limits<uint32_t>::max());
mShaderStageInfo[ShaderType::VertexShader].moduleSerial =
static_cast<uint32_t>(vertexSerial.getValue());
ASSERT(fragmentSerial < std::numeric_limits<uint32_t>::max());
mShaderStageInfo[ShaderType::FragmentShader].moduleSerial =
static_cast<uint32_t>(fragmentSerial.getValue());
}
void GraphicsPipelineDesc::updateVertexInputInfo(const VertexInputBindings &bindings, void GraphicsPipelineDesc::updateVertexInputInfo(const VertexInputBindings &bindings,
const VertexInputAttributes &attribs) const VertexInputAttributes &attribs)
{ {
...@@ -1144,7 +1129,19 @@ void GraphicsPipelineCache::destroy(VkDevice device) ...@@ -1144,7 +1129,19 @@ void GraphicsPipelineCache::destroy(VkDevice device)
{ {
for (auto &item : mPayload) for (auto &item : mPayload)
{ {
item.second.get().destroy(device); vk::PipelineAndSerial &pipeline = item.second;
pipeline.get().destroy(device);
}
mPayload.clear();
}
void GraphicsPipelineCache::release(RendererVk *renderer)
{
for (auto &item : mPayload)
{
vk::PipelineAndSerial &pipeline = item.second;
renderer->releaseObject(pipeline.getSerial(), &pipeline.get());
} }
mPayload.clear(); mPayload.clear();
......
...@@ -230,7 +230,6 @@ constexpr size_t kPackedInputAssemblyAndColorBlendStateSize = ...@@ -230,7 +230,6 @@ constexpr size_t kPackedInputAssemblyAndColorBlendStateSize =
sizeof(PackedInputAssemblyAndColorBlendStateInfo); sizeof(PackedInputAssemblyAndColorBlendStateInfo);
static_assert(kPackedInputAssemblyAndColorBlendStateSize == 56, "Size check failed"); static_assert(kPackedInputAssemblyAndColorBlendStateSize == 56, "Size check failed");
using ShaderStageInfo = vk::ShaderMap<PackedShaderStageInfo>;
using VertexInputBindings = gl::AttribArray<PackedVertexInputBindingDesc>; using VertexInputBindings = gl::AttribArray<PackedVertexInputBindingDesc>;
struct VertexInputAttributes final struct VertexInputAttributes final
...@@ -239,7 +238,6 @@ struct VertexInputAttributes final ...@@ -239,7 +238,6 @@ struct VertexInputAttributes final
uint16_t offsets[gl::MAX_VERTEX_ATTRIBS]; // can only take 11 bits on NV uint16_t offsets[gl::MAX_VERTEX_ATTRIBS]; // can only take 11 bits on NV
}; };
constexpr size_t kShaderStageInfoSize = sizeof(ShaderStageInfo);
constexpr size_t kVertexInputBindingsSize = sizeof(VertexInputBindings); constexpr size_t kVertexInputBindingsSize = sizeof(VertexInputBindings);
constexpr size_t kVertexInputAttributesSize = sizeof(VertexInputAttributes); constexpr size_t kVertexInputAttributesSize = sizeof(VertexInputAttributes);
...@@ -269,10 +267,6 @@ class GraphicsPipelineDesc final ...@@ -269,10 +267,6 @@ class GraphicsPipelineDesc final
const ShaderModule &fragmentModule, const ShaderModule &fragmentModule,
Pipeline *pipelineOut) const; Pipeline *pipelineOut) const;
// Shader stage info
const ShaderStageInfo &getShaderStageInfo() const;
void updateShaders(Serial vertexSerial, Serial fragmentSerial);
// Vertex input state // Vertex input state
void updateVertexInputInfo(const VertexInputBindings &bindings, void updateVertexInputInfo(const VertexInputBindings &bindings,
const VertexInputAttributes &attribs); const VertexInputAttributes &attribs);
...@@ -319,8 +313,6 @@ class GraphicsPipelineDesc final ...@@ -319,8 +313,6 @@ class GraphicsPipelineDesc final
void updatePolygonOffset(const gl::RasterizerState &rasterState); void updatePolygonOffset(const gl::RasterizerState &rasterState);
private: private:
// We can consider storing the shader stage info
ShaderStageInfo mShaderStageInfo;
VertexInputBindings mVertexInputBindings; VertexInputBindings mVertexInputBindings;
VertexInputAttributes mVertexInputAttribs; VertexInputAttributes mVertexInputAttribs;
RenderPassDesc mRenderPassDesc; RenderPassDesc mRenderPassDesc;
...@@ -335,7 +327,7 @@ class GraphicsPipelineDesc final ...@@ -335,7 +327,7 @@ class GraphicsPipelineDesc final
// No gaps or padding at the end ensures that hashing and memcmp checks will not run // No gaps or padding at the end ensures that hashing and memcmp checks will not run
// into uninitialized memory regions. // into uninitialized memory regions.
constexpr size_t kGraphicsPipelineDescSumOfSizes = constexpr size_t kGraphicsPipelineDescSumOfSizes =
kShaderStageInfoSize + kVertexInputBindingsSize + kVertexInputAttributesSize + kVertexInputBindingsSize + kVertexInputAttributesSize +
kPackedInputAssemblyAndColorBlendStateSize + kPackedRasterizationAndMultisampleStateSize + kPackedInputAssemblyAndColorBlendStateSize + kPackedRasterizationAndMultisampleStateSize +
kPackedDepthStencilStateSize + kRenderPassDescSize; kPackedDepthStencilStateSize + kRenderPassDescSize;
...@@ -510,6 +502,7 @@ class GraphicsPipelineCache final : angle::NonCopyable ...@@ -510,6 +502,7 @@ class GraphicsPipelineCache final : angle::NonCopyable
~GraphicsPipelineCache(); ~GraphicsPipelineCache();
void destroy(VkDevice device); void destroy(VkDevice device);
void release(RendererVk *renderer);
void populate(const vk::GraphicsPipelineDesc &desc, vk::Pipeline &&pipeline); void populate(const vk::GraphicsPipelineDesc &desc, vk::Pipeline &&pipeline);
angle::Result getPipeline(vk::Context *context, angle::Result getPipeline(vk::Context *context,
......
...@@ -1471,5 +1471,60 @@ void FramebufferHelper::release(RendererVk *renderer) ...@@ -1471,5 +1471,60 @@ void FramebufferHelper::release(RendererVk *renderer)
{ {
renderer->releaseObject(getStoredQueueSerial(), &mFramebuffer); renderer->releaseObject(getStoredQueueSerial(), &mFramebuffer);
} }
// ShaderProgramHelper implementation.
ShaderProgramHelper::ShaderProgramHelper() = default;
ShaderProgramHelper::~ShaderProgramHelper() = default;
bool ShaderProgramHelper::valid() const
{
// This will need to be extended for compute shader support.
return mShaders[gl::ShaderType::Vertex].valid();
}
void ShaderProgramHelper::destroy(VkDevice device)
{
mGraphicsPipelines.destroy(device);
for (BindingPointer<ShaderAndSerial> &shader : mShaders)
{
shader.reset();
}
}
void ShaderProgramHelper::release(RendererVk *renderer)
{
mGraphicsPipelines.release(renderer);
for (BindingPointer<ShaderAndSerial> &shader : mShaders)
{
shader.reset();
}
}
void ShaderProgramHelper::setShader(gl::ShaderType shaderType, RefCounted<ShaderAndSerial> *shader)
{
mShaders[shaderType].set(shader);
}
angle::Result ShaderProgramHelper::getGraphicsPipeline(
Context *context,
const PipelineLayout &pipelineLayout,
const GraphicsPipelineDesc &pipelineDesc,
const gl::AttributesMask &activeAttribLocationsMask,
PipelineAndSerial **pipelineOut)
{
RendererVk *renderer = context->getRenderer();
// Pull in a compatible RenderPass.
vk::RenderPass *compatibleRenderPass = nullptr;
ANGLE_TRY(renderer->getCompatibleRenderPass(context, pipelineDesc.getRenderPassDesc(),
&compatibleRenderPass));
return mGraphicsPipelines.getPipeline(
context, renderer->getPipelineCache(), *compatibleRenderPass, pipelineLayout,
activeAttribLocationsMask, mShaders[gl::ShaderType::Vertex].get().get(),
mShaders[gl::ShaderType::Fragment].get().get(), pipelineDesc, pipelineOut);
}
} // namespace vk } // namespace vk
} // namespace rx } // namespace rx
...@@ -547,6 +547,38 @@ class FramebufferHelper : public RecordableGraphResource ...@@ -547,6 +547,38 @@ class FramebufferHelper : public RecordableGraphResource
Framebuffer mFramebuffer; Framebuffer mFramebuffer;
}; };
class ShaderProgramHelper : angle::NonCopyable
{
public:
ShaderProgramHelper();
~ShaderProgramHelper();
bool valid() const;
void destroy(VkDevice device);
void release(RendererVk *renderer);
bool isGraphicsProgram() const
{
ASSERT(mShaders[gl::ShaderType::Vertex].valid() !=
mShaders[gl::ShaderType::Compute].valid());
return mShaders[gl::ShaderType::Vertex].valid();
}
vk::ShaderAndSerial &getShader(gl::ShaderType shaderType) { return mShaders[shaderType].get(); }
void setShader(gl::ShaderType shaderType, RefCounted<ShaderAndSerial> *shader);
// For getting a vk::Pipeline and from the pipeline cache.
angle::Result getGraphicsPipeline(Context *context,
const PipelineLayout &pipelineLayout,
const GraphicsPipelineDesc &pipelineDesc,
const gl::AttributesMask &activeAttribLocationsMask,
PipelineAndSerial **pipelineOut);
private:
gl::ShaderMap<BindingPointer<ShaderAndSerial>> mShaders;
GraphicsPipelineCache mGraphicsPipelines;
};
} // namespace vk } // namespace vk
} // namespace rx } // namespace rx
......
...@@ -24,7 +24,7 @@ ShaderLibrary::~ShaderLibrary() ...@@ -24,7 +24,7 @@ ShaderLibrary::~ShaderLibrary()
void ShaderLibrary::destroy(VkDevice device) void ShaderLibrary::destroy(VkDevice device)
{ {
for (ShaderAndSerial &shader : mShaders) for (RefCounted<ShaderAndSerial> &shader : mShaders)
{ {
shader.get().destroy(device); shader.get().destroy(device);
} }
...@@ -32,10 +32,10 @@ void ShaderLibrary::destroy(VkDevice device) ...@@ -32,10 +32,10 @@ void ShaderLibrary::destroy(VkDevice device)
angle::Result ShaderLibrary::getShader(vk::Context *context, angle::Result ShaderLibrary::getShader(vk::Context *context,
InternalShaderID shaderID, InternalShaderID shaderID,
const ShaderAndSerial **shaderOut) RefCounted<ShaderAndSerial> **shaderOut)
{ {
ShaderAndSerial &shader = mShaders[shaderID]; RefCounted<ShaderAndSerial> &shader = mShaders[shaderID];
*shaderOut = &shader; *shaderOut = &shader;
if (shader.get().valid()) if (shader.get().valid())
{ {
...@@ -44,7 +44,7 @@ angle::Result ShaderLibrary::getShader(vk::Context *context, ...@@ -44,7 +44,7 @@ angle::Result ShaderLibrary::getShader(vk::Context *context,
// Create shader lazily. Access will need to be locked for multi-threading. // Create shader lazily. Access will need to be locked for multi-threading.
const priv::ShaderBlob &shaderCode = priv::GetInternalShaderBlob(shaderID); const priv::ShaderBlob &shaderCode = priv::GetInternalShaderBlob(shaderID);
return InitShaderAndSerial(context, &shader, shaderCode.code, shaderCode.codeSize); return InitShaderAndSerial(context, &shader.get(), shaderCode.code, shaderCode.codeSize);
} }
} // namespace vk } // namespace vk
} // namespace rx } // namespace rx
...@@ -25,11 +25,11 @@ class ShaderLibrary final : angle::NonCopyable ...@@ -25,11 +25,11 @@ class ShaderLibrary final : angle::NonCopyable
angle::Result getShader(Context *context, angle::Result getShader(Context *context,
InternalShaderID shaderID, InternalShaderID shaderID,
const ShaderAndSerial **shaderOut); RefCounted<ShaderAndSerial> **shaderOut);
void destroy(VkDevice device); void destroy(VkDevice device);
private: private:
angle::PackedEnumMap<InternalShaderID, ShaderAndSerial> mShaders; angle::PackedEnumMap<InternalShaderID, RefCounted<ShaderAndSerial>> mShaders;
}; };
} // namespace vk } // namespace vk
} // 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