Commit 72106562 by Jamie Madill Committed by Commit Bot

Vulkan: Only re-create pipeline on state change.

This speeds up the simple perf test, but it is a very simple optimization that does not have a cache of pipelines or anything sophisticated. BUG=angleproject:1898 Change-Id: Iec126bc73bf28f8bb33662a2f70670588f010d72 Reviewed-on: https://chromium-review.googlesource.com/444850Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent 5e96d74f
...@@ -35,13 +35,13 @@ namespace rx ...@@ -35,13 +35,13 @@ namespace rx
{ {
ContextVk::ContextVk(const gl::ContextState &state, RendererVk *renderer) ContextVk::ContextVk(const gl::ContextState &state, RendererVk *renderer)
: ContextImpl(state), mRenderer(renderer) : ContextImpl(state), mRenderer(renderer), mCurrentDrawMode(GL_NONE)
{ {
} }
ContextVk::~ContextVk() ContextVk::~ContextVk()
{ {
mCurrentPipeline.destroy(getDevice()); invalidateCurrentPipeline();
} }
gl::Error ContextVk::initialize() gl::Error ContextVk::initialize()
...@@ -61,8 +61,10 @@ gl::Error ContextVk::finish() ...@@ -61,8 +61,10 @@ gl::Error ContextVk::finish()
return gl::Error(GL_INVALID_OPERATION); return gl::Error(GL_INVALID_OPERATION);
} }
gl::Error ContextVk::drawArrays(GLenum mode, GLint first, GLsizei count) gl::Error ContextVk::initPipeline()
{ {
ASSERT(!mCurrentPipeline.valid());
VkDevice device = mRenderer->getDevice(); VkDevice device = mRenderer->getDevice();
const auto &state = mState.getState(); const auto &state = mState.getState();
const auto &programGL = state.getProgram(); const auto &programGL = state.getProgram();
...@@ -72,7 +74,6 @@ gl::Error ContextVk::drawArrays(GLenum mode, GLint first, GLsizei count) ...@@ -72,7 +74,6 @@ gl::Error ContextVk::drawArrays(GLenum mode, GLint first, GLsizei count)
const auto &programVk = GetImplAs<ProgramVk>(programGL); const auto &programVk = GetImplAs<ProgramVk>(programGL);
const auto *drawFBO = state.getDrawFramebuffer(); const auto *drawFBO = state.getDrawFramebuffer();
FramebufferVk *vkFBO = GetImplAs<FramebufferVk>(drawFBO); FramebufferVk *vkFBO = GetImplAs<FramebufferVk>(drawFBO);
Serial queueSerial = mRenderer->getCurrentQueueSerial();
// { vertex, fragment } // { vertex, fragment }
VkPipelineShaderStageCreateInfo shaderStages[2]; VkPipelineShaderStageCreateInfo shaderStages[2];
...@@ -97,8 +98,6 @@ gl::Error ContextVk::drawArrays(GLenum mode, GLint first, GLsizei count) ...@@ -97,8 +98,6 @@ gl::Error ContextVk::drawArrays(GLenum mode, GLint first, GLsizei count)
// TODO(jmadill): Caching with dirty bits. // TODO(jmadill): Caching with dirty bits.
std::vector<VkVertexInputBindingDescription> vertexBindings; std::vector<VkVertexInputBindingDescription> vertexBindings;
std::vector<VkVertexInputAttributeDescription> vertexAttribs; std::vector<VkVertexInputAttributeDescription> vertexAttribs;
std::vector<VkBuffer> vertexHandles;
std::vector<VkDeviceSize> vertexOffsets;
for (auto attribIndex : angle::IterateBitSet(programGL->getActiveAttribLocationsMask())) for (auto attribIndex : angle::IterateBitSet(programGL->getActiveAttribLocationsMask()))
{ {
...@@ -123,15 +122,6 @@ gl::Error ContextVk::drawArrays(GLenum mode, GLint first, GLsizei count) ...@@ -123,15 +122,6 @@ gl::Error ContextVk::drawArrays(GLenum mode, GLint first, GLsizei count)
vertexBindings.push_back(bindingDesc); vertexBindings.push_back(bindingDesc);
vertexAttribs.push_back(attribDesc); vertexAttribs.push_back(attribDesc);
// TODO(jmadill): Offset handling.
gl::Buffer *bufferGL = binding.buffer.get();
ASSERT(bufferGL);
BufferVk *bufferVk = GetImplAs<BufferVk>(bufferGL);
vertexHandles.push_back(bufferVk->getVkBuffer().getHandle());
vertexOffsets.push_back(0);
bufferVk->setQueueSerial(queueSerial);
} }
else else
{ {
...@@ -153,7 +143,7 @@ gl::Error ContextVk::drawArrays(GLenum mode, GLint first, GLsizei count) ...@@ -153,7 +143,7 @@ gl::Error ContextVk::drawArrays(GLenum mode, GLint first, GLsizei count)
inputAssemblyState.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; inputAssemblyState.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
inputAssemblyState.pNext = nullptr; inputAssemblyState.pNext = nullptr;
inputAssemblyState.flags = 0; inputAssemblyState.flags = 0;
inputAssemblyState.topology = gl_vk::GetPrimitiveTopology(mode); inputAssemblyState.topology = gl_vk::GetPrimitiveTopology(mCurrentDrawMode);
inputAssemblyState.primitiveRestartEnable = VK_FALSE; inputAssemblyState.primitiveRestartEnable = VK_FALSE;
const gl::Rectangle &viewportGL = state.getViewport(); const gl::Rectangle &viewportGL = state.getViewport();
...@@ -202,10 +192,10 @@ gl::Error ContextVk::drawArrays(GLenum mode, GLint first, GLsizei count) ...@@ -202,10 +192,10 @@ gl::Error ContextVk::drawArrays(GLenum mode, GLint first, GLsizei count)
multisampleState.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; multisampleState.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
multisampleState.pNext = nullptr; multisampleState.pNext = nullptr;
multisampleState.flags = 0; multisampleState.flags = 0;
multisampleState.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; multisampleState.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
multisampleState.sampleShadingEnable = VK_FALSE; multisampleState.sampleShadingEnable = VK_FALSE;
multisampleState.minSampleShading = 0.0f; multisampleState.minSampleShading = 0.0f;
multisampleState.pSampleMask = nullptr; multisampleState.pSampleMask = nullptr;
multisampleState.alphaToCoverageEnable = VK_FALSE; multisampleState.alphaToCoverageEnable = VK_FALSE;
multisampleState.alphaToOneEnable = VK_FALSE; multisampleState.alphaToOneEnable = VK_FALSE;
...@@ -271,6 +261,59 @@ gl::Error ContextVk::drawArrays(GLenum mode, GLint first, GLsizei count) ...@@ -271,6 +261,59 @@ gl::Error ContextVk::drawArrays(GLenum mode, GLint first, GLsizei count)
mCurrentPipeline.retain(device, std::move(newPipeline)); mCurrentPipeline.retain(device, std::move(newPipeline));
return gl::NoError();
}
gl::Error ContextVk::drawArrays(GLenum mode, GLint first, GLsizei count)
{
if (mode != mCurrentDrawMode)
{
invalidateCurrentPipeline();
mCurrentDrawMode = mode;
}
if (!mCurrentPipeline.valid())
{
ANGLE_TRY(initPipeline());
ASSERT(mCurrentPipeline.valid());
}
VkDevice device = mRenderer->getDevice();
const auto &state = mState.getState();
const auto &programGL = state.getProgram();
const auto &vao = state.getVertexArray();
const auto &attribs = vao->getVertexAttributes();
const auto &bindings = vao->getVertexBindings();
const auto *drawFBO = state.getDrawFramebuffer();
FramebufferVk *vkFBO = GetImplAs<FramebufferVk>(drawFBO);
Serial queueSerial = mRenderer->getCurrentQueueSerial();
// Process vertex attributes
// TODO(jmadill): Caching with dirty bits.
std::vector<VkBuffer> vertexHandles;
std::vector<VkDeviceSize> vertexOffsets;
for (auto attribIndex : angle::IterateBitSet(programGL->getActiveAttribLocationsMask()))
{
const auto &attrib = attribs[attribIndex];
const auto &binding = bindings[attrib.bindingIndex];
if (attrib.enabled)
{
// TODO(jmadill): Offset handling.
gl::Buffer *bufferGL = binding.buffer.get();
ASSERT(bufferGL);
BufferVk *bufferVk = GetImplAs<BufferVk>(bufferGL);
vertexHandles.push_back(bufferVk->getVkBuffer().getHandle());
vertexOffsets.push_back(0);
bufferVk->setQueueSerial(queueSerial);
}
else
{
UNIMPLEMENTED();
}
}
vk::CommandBuffer *commandBuffer = mRenderer->getCommandBuffer(); vk::CommandBuffer *commandBuffer = mRenderer->getCommandBuffer();
ANGLE_TRY(vkFBO->beginRenderPass(device, commandBuffer, queueSerial, state)); ANGLE_TRY(vkFBO->beginRenderPass(device, commandBuffer, queueSerial, state));
...@@ -280,7 +323,7 @@ gl::Error ContextVk::drawArrays(GLenum mode, GLint first, GLsizei count) ...@@ -280,7 +323,7 @@ gl::Error ContextVk::drawArrays(GLenum mode, GLint first, GLsizei count)
commandBuffer->endRenderPass(); commandBuffer->endRenderPass();
ANGLE_TRY(commandBuffer->end()); ANGLE_TRY(commandBuffer->end());
ANGLE_TRY(mRenderer->submitCommandBuffer(*commandBuffer)); ANGLE_TRY(submitCommands(*commandBuffer));
return gl::NoError(); return gl::NoError();
} }
...@@ -338,6 +381,7 @@ vk::CommandBuffer *ContextVk::getCommandBuffer() ...@@ -338,6 +381,7 @@ vk::CommandBuffer *ContextVk::getCommandBuffer()
vk::Error ContextVk::submitCommands(const vk::CommandBuffer &commandBuffer) vk::Error ContextVk::submitCommands(const vk::CommandBuffer &commandBuffer)
{ {
setQueueSerial(mRenderer->getCurrentQueueSerial());
ANGLE_TRY(mRenderer->submitCommandBuffer(commandBuffer)); ANGLE_TRY(mRenderer->submitCommandBuffer(commandBuffer));
return vk::NoError(); return vk::NoError();
} }
...@@ -387,9 +431,13 @@ void ContextVk::popGroupMarker() ...@@ -387,9 +431,13 @@ void ContextVk::popGroupMarker()
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
void ContextVk::syncState(const gl::State::DirtyBits & /*dirtyBits*/) void ContextVk::syncState(const gl::State::DirtyBits &dirtyBits)
{ {
// TODO(jmadill): Vulkan dirty bits. // TODO(jmadill): Vulkan dirty bits.
if (dirtyBits.any())
{
invalidateCurrentPipeline();
}
} }
GLint ContextVk::getGPUDisjoint() GLint ContextVk::getGPUDisjoint()
...@@ -498,4 +546,10 @@ std::vector<PathImpl *> ContextVk::createPaths(GLsizei) ...@@ -498,4 +546,10 @@ std::vector<PathImpl *> ContextVk::createPaths(GLsizei)
return std::vector<PathImpl *>(); return std::vector<PathImpl *>();
} }
// TODO(jmadill): Use pipeline cache.
void ContextVk::invalidateCurrentPipeline()
{
mRenderer->enqueueGarbageOrDeleteNow(*this, mCurrentPipeline);
}
} // namespace rx } // namespace rx
...@@ -19,7 +19,7 @@ namespace rx ...@@ -19,7 +19,7 @@ namespace rx
{ {
class RendererVk; class RendererVk;
class ContextVk : public ContextImpl class ContextVk : public ContextImpl, public ResourceVk
{ {
public: public:
ContextVk(const gl::ContextState &state, RendererVk *renderer); ContextVk(const gl::ContextState &state, RendererVk *renderer);
...@@ -128,9 +128,15 @@ class ContextVk : public ContextImpl ...@@ -128,9 +128,15 @@ class ContextVk : public ContextImpl
RendererVk *getRenderer() { return mRenderer; } RendererVk *getRenderer() { return mRenderer; }
// TODO(jmadill): Use pipeline cache.
void invalidateCurrentPipeline();
private: private:
gl::Error initPipeline();
RendererVk *mRenderer; RendererVk *mRenderer;
vk::Pipeline mCurrentPipeline; vk::Pipeline mCurrentPipeline;
GLenum mCurrentDrawMode;
}; };
} // namespace rx } // namespace rx
......
...@@ -347,6 +347,9 @@ void FramebufferVk::syncState(ContextImpl *contextImpl, const gl::Framebuffer::D ...@@ -347,6 +347,9 @@ void FramebufferVk::syncState(ContextImpl *contextImpl, const gl::Framebuffer::D
// TODO(jmadill): Smarter update. // TODO(jmadill): Smarter update.
mRenderPass.destroy(contextVk->getDevice()); mRenderPass.destroy(contextVk->getDevice());
mFramebuffer.destroy(contextVk->getDevice()); mFramebuffer.destroy(contextVk->getDevice());
// TODO(jmadill): Use pipeline cache.
contextVk->invalidateCurrentPipeline();
} }
gl::ErrorOrResult<vk::RenderPass *> FramebufferVk::getRenderPass(VkDevice device) gl::ErrorOrResult<vk::RenderPass *> FramebufferVk::getRenderPass(VkDevice device)
......
...@@ -108,6 +108,9 @@ LinkResult ProgramVk::link(ContextImpl *contextImpl, ...@@ -108,6 +108,9 @@ LinkResult ProgramVk::link(ContextImpl *contextImpl,
mLinkedVertexModule.retain(device, std::move(vertexModule)); mLinkedVertexModule.retain(device, std::move(vertexModule));
mLinkedFragmentModule.retain(device, std::move(fragmentModule)); mLinkedFragmentModule.retain(device, std::move(fragmentModule));
// TODO(jmadill): Use pipeline cache.
context->invalidateCurrentPipeline();
return true; return true;
} }
......
...@@ -78,6 +78,19 @@ class RendererVk : angle::NonCopyable ...@@ -78,6 +78,19 @@ class RendererVk : angle::NonCopyable
new vk::GarbageObject<T>(serial, std::move(object)))); new vk::GarbageObject<T>(serial, std::move(object))));
} }
template <typename T>
void enqueueGarbageOrDeleteNow(const ResourceVk &resouce, T &&object)
{
if (resouce.getDeleteSchedule(mLastCompletedQueueSerial) == DeleteSchedule::NOW)
{
object.destroy(mDevice);
}
else
{
enqueueGarbage(resouce.getStoredQueueSerial(), std::move(object));
}
}
private: private:
void ensureCapsInitialized() const; void ensureCapsInitialized() const;
void generateCaps(gl::Caps *outCaps, void generateCaps(gl::Caps *outCaps,
......
...@@ -27,6 +27,10 @@ VertexArrayVk::~VertexArrayVk() ...@@ -27,6 +27,10 @@ VertexArrayVk::~VertexArrayVk()
void VertexArrayVk::syncState(ContextImpl *contextImpl, const gl::VertexArray::DirtyBits &dirtyBits) void VertexArrayVk::syncState(ContextImpl *contextImpl, const gl::VertexArray::DirtyBits &dirtyBits)
{ {
ASSERT(dirtyBits.any()); ASSERT(dirtyBits.any());
// TODO(jmadill): Use pipeline cache.
auto contextVk = GetAs<ContextVk>(contextImpl);
contextVk->invalidateCurrentPipeline();
} }
} // namespace rx } // namespace rx
...@@ -88,7 +88,7 @@ class ResourceVk ...@@ -88,7 +88,7 @@ class ResourceVk
mStoredQueueSerial = queueSerial; mStoredQueueSerial = queueSerial;
} }
DeleteSchedule getDeleteSchedule(Serial lastCompletedQueueSerial) DeleteSchedule getDeleteSchedule(Serial lastCompletedQueueSerial) const
{ {
if (lastCompletedQueueSerial >= mStoredQueueSerial) if (lastCompletedQueueSerial >= mStoredQueueSerial)
{ {
...@@ -100,6 +100,8 @@ class ResourceVk ...@@ -100,6 +100,8 @@ class ResourceVk
} }
} }
Serial getStoredQueueSerial() const { return mStoredQueueSerial; }
private: private:
Serial mStoredQueueSerial; Serial mStoredQueueSerial;
}; };
......
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