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()
// Ensure that the RenderPass description is updated.
mGraphicsPipelineDesc->updateRenderPassDesc(mDrawFramebuffer->getRenderPassDesc());
// Trigger draw call shader patching and fill out the pipeline desc.
const vk::ShaderAndSerial *vertexShaderAndSerial = nullptr;
const vk::ShaderAndSerial *fragmentShaderAndSerial = nullptr;
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();
// Draw call shader patching, shader compilation, and pipeline cache query.
return mProgram->getGraphicsPipeline(this, mCurrentDrawMode, *mGraphicsPipelineDesc,
activeAttribLocationsMask, &mCurrentPipeline);
}
angle::Result ContextVk::setupDraw(const gl::Context *context,
......
......@@ -1009,20 +1009,14 @@ angle::Result FramebufferVk::clearWithClearAttachments(
angle::Result FramebufferVk::clearWithDraw(ContextVk *contextVk,
VkColorComponentFlags colorMaskFlags)
{
RendererVk *renderer = contextVk->getRenderer();
vk::ShaderLibrary *shaderLibrary = renderer->getShaderLibrary();
RendererVk *renderer = contextVk->getRenderer();
vk::ShaderProgramHelper *fullScreenClear = nullptr;
ANGLE_TRY(renderer->getFullScreenClearShaderProgram(contextVk, &fullScreenClear));
// Trigger a new command node to ensure overlapping writes happen sequentially.
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.
vk::PipelineLayoutDesc pipelineLayoutDesc;
pipelineLayoutDesc.updatePushConstantRange(gl::ShaderType::Fragment, 0,
......@@ -1047,12 +1041,10 @@ angle::Result FramebufferVk::clearWithDraw(ContextVk *contextVk,
pipelineDesc.initDefaults();
pipelineDesc.updateColorWriteMask(colorMaskFlags, getEmulatedAlphaAttachmentMask());
pipelineDesc.updateRenderPassDesc(getRenderPassDesc());
pipelineDesc.updateShaders(fullScreenQuad->getSerial(), pushConstantColor->getSerial());
vk::PipelineAndSerial *pipeline = nullptr;
ANGLE_TRY(renderer->getPipeline(contextVk, *fullScreenQuad, *pushConstantColor,
pipelineLayout.get(), pipelineDesc, gl::AttributesMask(),
&pipeline));
ANGLE_TRY(fullScreenClear->getGraphicsPipeline(contextVk, pipelineLayout.get(), pipelineDesc,
gl::AttributesMask(), &pipeline));
pipeline->updateSerial(renderer->getCurrentQueueSerial());
vk::CommandBuffer *writeCommands = nullptr;
......
......@@ -144,13 +144,10 @@ ProgramVk::ShaderInfo::ShaderInfo()
ProgramVk::ShaderInfo::~ShaderInfo() = default;
angle::Result ProgramVk::ShaderInfo::getShaders(
ContextVk *contextVk,
const std::string &vertexSource,
const std::string &fragmentSource,
bool enableLineRasterEmulation,
const vk::ShaderAndSerial **vertexShaderAndSerialOut,
const vk::ShaderAndSerial **fragmentShaderAndSerialOut)
angle::Result ProgramVk::ShaderInfo::initShaders(ContextVk *contextVk,
const std::string &vertexSource,
const std::string &fragmentSource,
bool enableLineRasterEmulation)
{
if (!valid())
{
......@@ -160,26 +157,32 @@ angle::Result ProgramVk::ShaderInfo::getShaders(
enableLineRasterEmulation, vertexSource,
fragmentSource, &vertexCode, &fragmentCode));
ANGLE_TRY(vk::InitShaderAndSerial(contextVk, &mVertexShaderAndSerial, vertexCode.data(),
vertexCode.size() * sizeof(uint32_t)));
ANGLE_TRY(vk::InitShaderAndSerial(contextVk, &mFragmentShaderAndSerial, fragmentCode.data(),
ANGLE_TRY(vk::InitShaderAndSerial(contextVk, &mShaders[gl::ShaderType::Vertex].get(),
vertexCode.data(), vertexCode.size() * sizeof(uint32_t)));
ANGLE_TRY(vk::InitShaderAndSerial(contextVk, &mShaders[gl::ShaderType::Fragment].get(),
fragmentCode.data(),
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();
}
void ProgramVk::ShaderInfo::destroy(VkDevice device)
void ProgramVk::ShaderInfo::release(RendererVk *renderer)
{
mVertexShaderAndSerial.destroy(device);
mFragmentShaderAndSerial.destroy(device);
mProgramHelper.release(renderer);
for (vk::RefCounted<vk::ShaderAndSerial> &shader : mShaders)
{
shader.get().destroy(renderer->getDevice());
}
}
bool ProgramVk::ShaderInfo::valid() const
{
return mVertexShaderAndSerial.valid();
return mShaders[gl::ShaderType::Vertex].get().valid();
}
// ProgramVk implementation.
......@@ -201,29 +204,24 @@ ProgramVk::~ProgramVk() = default;
void ProgramVk::destroy(const gl::Context *context)
{
ContextVk *contextVk = vk::GetImpl(context);
// We don't interrupt exectution in destructors.
(void)reset(contextVk);
reset(contextVk->getRenderer());
}
angle::Result ProgramVk::reset(ContextVk *contextVk)
void ProgramVk::reset(RendererVk *renderer)
{
VkDevice device = contextVk->getDevice();
for (auto &descriptorSetLayout : mDescriptorSetLayouts)
{
descriptorSetLayout.reset();
}
mPipelineLayout.reset();
RendererVk *renderer = contextVk->getRenderer();
for (auto &uniformBlock : mDefaultUniformBlocks)
{
uniformBlock.storage.release(renderer);
}
mDefaultShaderInfo.destroy(device);
mLineRasterShaderInfo.destroy(device);
mDefaultShaderInfo.release(renderer);
mLineRasterShaderInfo.release(renderer);
Serial currentSerial = renderer->getCurrentQueueSerial();
renderer->releaseObject(currentSerial, &mEmptyUniformBlockStorage.memory);
......@@ -236,8 +234,6 @@ angle::Result ProgramVk::reset(ContextVk *contextVk)
{
binding.reset();
}
return angle::Result::Continue();
}
angle::Result ProgramVk::load(const gl::Context *context,
......@@ -279,7 +275,7 @@ angle::Result ProgramVk::linkImpl(const gl::Context *glContext,
ContextVk *contextVk = vk::GetImpl(glContext);
RendererVk *renderer = contextVk->getRenderer();
ANGLE_TRY(reset(contextVk));
reset(renderer);
GlslangWrapper::GetShaderSource(mState, resources, &mVertexSource, &mFragmentSource);
......@@ -743,27 +739,22 @@ void ProgramVk::setPathFragmentInputGen(const std::string &inputName,
angle::Result ProgramVk::initShaders(ContextVk *contextVk,
gl::PrimitiveMode mode,
const vk::ShaderAndSerial **vertexShaderAndSerialOut,
const vk::ShaderAndSerial **fragmentShaderAndSerialOut,
const vk::PipelineLayout **pipelineLayoutOut)
vk::ShaderProgramHelper **programOut)
{
if (UseLineRaster(contextVk, mode))
{
ANGLE_TRY(mLineRasterShaderInfo.getShaders(contextVk, mVertexSource, mFragmentSource, true,
vertexShaderAndSerialOut,
fragmentShaderAndSerialOut));
ANGLE_TRY(
mLineRasterShaderInfo.initShaders(contextVk, mVertexSource, mFragmentSource, true));
ASSERT(mLineRasterShaderInfo.valid());
*programOut = &mLineRasterShaderInfo.getShaderProgram();
}
else
{
ANGLE_TRY(mDefaultShaderInfo.getShaders(contextVk, mVertexSource, mFragmentSource, false,
vertexShaderAndSerialOut,
fragmentShaderAndSerialOut));
ANGLE_TRY(mDefaultShaderInfo.initShaders(contextVk, mVertexSource, mFragmentSource, false));
ASSERT(mDefaultShaderInfo.valid());
*programOut = &mDefaultShaderInfo.getShaderProgram();
}
*pipelineLayoutOut = &mPipelineLayout.get();
return angle::Result::Continue();
}
......
......@@ -13,6 +13,7 @@
#include <array>
#include "libANGLE/renderer/ProgramImpl.h"
#include "libANGLE/renderer/vulkan/ContextVk.h"
#include "libANGLE/renderer/vulkan/RendererVk.h"
#include "libANGLE/renderer/vulkan/vk_helpers.h"
......@@ -96,11 +97,6 @@ class ProgramVk : public ProgramImpl
const GLfloat *coeffs) override;
// 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 updateTexturesDescriptorSet(ContextVk *contextVk);
......@@ -116,6 +112,19 @@ class ProgramVk : public ProgramImpl
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:
template <int cols, int rows>
void setUniformMatrixfv(GLint location,
......@@ -123,7 +132,7 @@ class ProgramVk : public ProgramImpl
GLboolean transpose,
const GLfloat *value);
angle::Result reset(ContextVk *contextVk);
void reset(RendererVk *renderer);
angle::Result allocateDescriptorSet(ContextVk *contextVk, uint32_t descriptorSetIndex);
angle::Result initDefaultUniformBlocks(const gl::Context *glContext);
......@@ -138,6 +147,10 @@ class ProgramVk : public ProgramImpl
const gl::ProgramLinkedResources &resources,
gl::InfoLog &infoLog);
angle::Result initShaders(ContextVk *contextVk,
gl::PrimitiveMode mode,
vk::ShaderProgramHelper **shaderProgramOut);
// State for the default uniform blocks.
struct DefaultUniformBlock final : private angle::NonCopyable
{
......@@ -182,18 +195,18 @@ class ProgramVk : public ProgramImpl
ShaderInfo();
~ShaderInfo();
angle::Result getShaders(ContextVk *contextVk,
const std::string &vertexSource,
const std::string &fragmentSource,
bool enableLineRasterEmulation,
const vk::ShaderAndSerial **vertexShaderAndSerialOut,
const vk::ShaderAndSerial **fragmentShaderAndSerialOut);
void destroy(VkDevice device);
angle::Result initShaders(ContextVk *contextVk,
const std::string &vertexSource,
const std::string &fragmentSource,
bool enableLineRasterEmulation);
void release(RendererVk *renderer);
bool valid() const;
vk::ShaderProgramHelper &getShaderProgram() { return mProgramHelper; }
private:
vk::ShaderAndSerial mVertexShaderAndSerial;
vk::ShaderAndSerial mFragmentShaderAndSerial;
vk::ShaderProgramHelper mProgramHelper;
gl::ShaderMap<vk::RefCounted<vk::ShaderAndSerial>> mShaders;
};
ShaderInfo mDefaultShaderInfo;
......
......@@ -333,9 +333,10 @@ void RendererVk::onDestroy(vk::Context *context)
mPipelineLayoutCache.destroy(mDevice);
mDescriptorSetLayoutCache.destroy(mDevice);
mFullScreenClearShaderProgram.destroy(mDevice);
mRenderPassCache.destroy(mDevice);
mGraphicsPipelineCache.destroy(mDevice);
mPipelineCacheVk.destroy(mDevice);
mPipelineCache.destroy(mDevice);
mSubmitSemaphorePool.destroy(mDevice);
mShaderLibrary.destroy(mDevice);
mGpuEventQueryPool.destroy(mDevice);
......@@ -637,7 +638,7 @@ angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueF
ANGLE_VK_TRY(displayVk, mCommandPool.init(mDevice, commandPoolInfo));
// Initialize the vulkan pipeline cache.
ANGLE_TRY(initPipelineCacheVk(displayVk));
ANGLE_TRY(initPipelineCache(displayVk));
// Initialize the submission semaphore pool.
ANGLE_TRY(mSubmitSemaphorePool.init(displayVk, vk::kDefaultSemaphorePoolSize));
......@@ -808,7 +809,7 @@ void RendererVk::initPipelineCacheVkKey()
hashString.length(), mPipelineCacheVkBlobKey.data());
}
angle::Result RendererVk::initPipelineCacheVk(DisplayVk *display)
angle::Result RendererVk::initPipelineCache(DisplayVk *display)
{
initPipelineCacheVkKey();
......@@ -823,7 +824,7 @@ angle::Result RendererVk::initPipelineCacheVk(DisplayVk *display)
pipelineCacheCreateInfo.initialDataSize = success ? initialData.size() : 0;
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();
}
......@@ -1164,29 +1165,6 @@ Serial RendererVk::issueShaderSerial()
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(
vk::Context *context,
const vk::DescriptorSetLayoutDesc &desc,
......@@ -1207,7 +1185,7 @@ angle::Result RendererVk::getPipelineLayout(
angle::Result RendererVk::syncPipelineCacheVk(DisplayVk *displayVk)
{
ASSERT(mPipelineCacheVk.valid());
ASSERT(mPipelineCache.valid());
if (--mPipelineCacheVkUpdateTimeout > 0)
{
......@@ -1218,7 +1196,7 @@ angle::Result RendererVk::syncPipelineCacheVk(DisplayVk *displayVk)
// Get the size of the cache.
size_t pipelineCacheSize = 0;
VkResult result = mPipelineCacheVk.getCacheData(mDevice, &pipelineCacheSize, nullptr);
VkResult result = mPipelineCache.getCacheData(mDevice, &pipelineCacheSize, nullptr);
if (result != VK_INCOMPLETE)
{
ANGLE_VK_TRY(displayVk, result);
......@@ -1229,7 +1207,7 @@ angle::Result RendererVk::syncPipelineCacheVk(DisplayVk *displayVk)
displayVk->getScratchBuffer(pipelineCacheSize, &pipelineCacheData));
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
// was determined just above), so receiving it hints at an implementation bug we would want
// to know about early.
......@@ -1276,9 +1254,25 @@ const vk::Semaphore *RendererVk::getSubmitLastSignaledSemaphore(vk::Context *con
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)
......
......@@ -129,15 +129,6 @@ class RendererVk : angle::NonCopyable
const vk::AttachmentOpsArray &ops,
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.
angle::Result getDescriptorSetLayout(
vk::Context *context,
......@@ -169,7 +160,8 @@ class RendererVk : angle::NonCopyable
// Issues a new serial for linked shader modules. Used in the pipeline cache.
Serial issueShaderSerial();
vk::ShaderLibrary *getShaderLibrary();
angle::Result getFullScreenClearShaderProgram(vk::Context *context,
vk::ShaderProgramHelper **programOut);
const angle::FeaturesVk &getFeatures() const { return mFeatures; }
angle::Result getTimestamp(vk::Context *context, uint64_t *timestampOut);
......@@ -189,6 +181,8 @@ class RendererVk : angle::NonCopyable
bool isMockICDEnabled() const { return mEnableMockICD; }
const vk::PipelineCache &getPipelineCache() const { return mPipelineCache; }
private:
// Number of semaphores for external entities to renderer to issue a wait, such as surface's
// image acquire.
......@@ -210,7 +204,7 @@ class RendererVk : angle::NonCopyable
angle::Result flushCommandGraph(vk::Context *context, vk::CommandBuffer *commandBatch);
void initFeatures();
void initPipelineCacheVkKey();
angle::Result initPipelineCacheVk(DisplayVk *display);
angle::Result initPipelineCache(DisplayVk *display);
angle::Result synchronizeCpuGpuTime(vk::Context *context);
angle::Result traceGpuEventImpl(vk::Context *context,
......@@ -269,9 +263,8 @@ class RendererVk : angle::NonCopyable
vk::FormatTable mFormatTable;
RenderPassCache mRenderPassCache;
GraphicsPipelineCache mGraphicsPipelineCache;
vk::PipelineCache mPipelineCacheVk;
vk::PipelineCache mPipelineCache;
egl::BlobCache::Key mPipelineCacheVkBlobKey;
uint32_t mPipelineCacheVkUpdateTimeout;
......@@ -306,6 +299,7 @@ class RendererVk : angle::NonCopyable
// Internal shader library.
vk::ShaderLibrary mShaderLibrary;
vk::ShaderProgramHelper mFullScreenClearShaderProgram;
// 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
......
......@@ -672,21 +672,6 @@ angle::Result GraphicsPipelineDesc::initializePipeline(
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,
const VertexInputAttributes &attribs)
{
......@@ -1144,7 +1129,19 @@ void GraphicsPipelineCache::destroy(VkDevice device)
{
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();
......
......@@ -230,7 +230,6 @@ constexpr size_t kPackedInputAssemblyAndColorBlendStateSize =
sizeof(PackedInputAssemblyAndColorBlendStateInfo);
static_assert(kPackedInputAssemblyAndColorBlendStateSize == 56, "Size check failed");
using ShaderStageInfo = vk::ShaderMap<PackedShaderStageInfo>;
using VertexInputBindings = gl::AttribArray<PackedVertexInputBindingDesc>;
struct VertexInputAttributes final
......@@ -239,7 +238,6 @@ struct VertexInputAttributes final
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 kVertexInputAttributesSize = sizeof(VertexInputAttributes);
......@@ -269,10 +267,6 @@ class GraphicsPipelineDesc final
const ShaderModule &fragmentModule,
Pipeline *pipelineOut) const;
// Shader stage info
const ShaderStageInfo &getShaderStageInfo() const;
void updateShaders(Serial vertexSerial, Serial fragmentSerial);
// Vertex input state
void updateVertexInputInfo(const VertexInputBindings &bindings,
const VertexInputAttributes &attribs);
......@@ -319,8 +313,6 @@ class GraphicsPipelineDesc final
void updatePolygonOffset(const gl::RasterizerState &rasterState);
private:
// We can consider storing the shader stage info
ShaderStageInfo mShaderStageInfo;
VertexInputBindings mVertexInputBindings;
VertexInputAttributes mVertexInputAttribs;
RenderPassDesc mRenderPassDesc;
......@@ -335,7 +327,7 @@ class GraphicsPipelineDesc final
// No gaps or padding at the end ensures that hashing and memcmp checks will not run
// into uninitialized memory regions.
constexpr size_t kGraphicsPipelineDescSumOfSizes =
kShaderStageInfoSize + kVertexInputBindingsSize + kVertexInputAttributesSize +
kVertexInputBindingsSize + kVertexInputAttributesSize +
kPackedInputAssemblyAndColorBlendStateSize + kPackedRasterizationAndMultisampleStateSize +
kPackedDepthStencilStateSize + kRenderPassDescSize;
......@@ -510,6 +502,7 @@ class GraphicsPipelineCache final : angle::NonCopyable
~GraphicsPipelineCache();
void destroy(VkDevice device);
void release(RendererVk *renderer);
void populate(const vk::GraphicsPipelineDesc &desc, vk::Pipeline &&pipeline);
angle::Result getPipeline(vk::Context *context,
......
......@@ -1471,5 +1471,60 @@ void FramebufferHelper::release(RendererVk *renderer)
{
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 rx
......@@ -547,6 +547,38 @@ class FramebufferHelper : public RecordableGraphResource
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 rx
......
......@@ -24,7 +24,7 @@ ShaderLibrary::~ShaderLibrary()
void ShaderLibrary::destroy(VkDevice device)
{
for (ShaderAndSerial &shader : mShaders)
for (RefCounted<ShaderAndSerial> &shader : mShaders)
{
shader.get().destroy(device);
}
......@@ -32,10 +32,10 @@ void ShaderLibrary::destroy(VkDevice device)
angle::Result ShaderLibrary::getShader(vk::Context *context,
InternalShaderID shaderID,
const ShaderAndSerial **shaderOut)
RefCounted<ShaderAndSerial> **shaderOut)
{
ShaderAndSerial &shader = mShaders[shaderID];
*shaderOut = &shader;
RefCounted<ShaderAndSerial> &shader = mShaders[shaderID];
*shaderOut = &shader;
if (shader.get().valid())
{
......@@ -44,7 +44,7 @@ angle::Result ShaderLibrary::getShader(vk::Context *context,
// Create shader lazily. Access will need to be locked for multi-threading.
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 rx
......@@ -25,11 +25,11 @@ class ShaderLibrary final : angle::NonCopyable
angle::Result getShader(Context *context,
InternalShaderID shaderID,
const ShaderAndSerial **shaderOut);
RefCounted<ShaderAndSerial> **shaderOut);
void destroy(VkDevice device);
private:
angle::PackedEnumMap<InternalShaderID, ShaderAndSerial> mShaders;
angle::PackedEnumMap<InternalShaderID, RefCounted<ShaderAndSerial>> mShaders;
};
} // namespace vk
} // 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