blob: 3dd74678b0ad2e59c3227229bb6faf23a0772e5c [file] [log] [blame]
Jamie Madill1f46bc12018-02-20 16:09:43 -05001//
2// Copyright 2017 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6// CommandGraph:
7// Deferred work constructed by GL calls, that will later be flushed to Vulkan.
8//
9
10#include "libANGLE/renderer/vulkan/CommandGraph.h"
11
12#include "libANGLE/renderer/vulkan/RenderTargetVk.h"
13#include "libANGLE/renderer/vulkan/RendererVk.h"
14#include "libANGLE/renderer/vulkan/vk_format_utils.h"
Jamie Madill26084d02018-04-09 13:44:04 -040015#include "libANGLE/renderer/vulkan/vk_helpers.h"
Jamie Madill1f46bc12018-02-20 16:09:43 -050016
17namespace rx
18{
19
20namespace vk
21{
22
23namespace
24{
25
Jamie Madill21061022018-07-12 23:56:30 -040026angle::Result InitAndBeginCommandBuffer(vk::Context *context,
27 const CommandPool &commandPool,
28 const VkCommandBufferInheritanceInfo &inheritanceInfo,
29 VkCommandBufferUsageFlags flags,
30 CommandBuffer *commandBuffer)
Jamie Madill1f46bc12018-02-20 16:09:43 -050031{
32 ASSERT(!commandBuffer->valid());
33
34 VkCommandBufferAllocateInfo createInfo;
35 createInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
36 createInfo.pNext = nullptr;
37 createInfo.commandPool = commandPool.getHandle();
38 createInfo.level = VK_COMMAND_BUFFER_LEVEL_SECONDARY;
39 createInfo.commandBufferCount = 1;
40
Jamie Madill21061022018-07-12 23:56:30 -040041 ANGLE_TRY(commandBuffer->init(context, createInfo));
Jamie Madill1f46bc12018-02-20 16:09:43 -050042
43 VkCommandBufferBeginInfo beginInfo;
44 beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
45 beginInfo.pNext = nullptr;
46 beginInfo.flags = flags | VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
47 beginInfo.pInheritanceInfo = &inheritanceInfo;
48
Jamie Madill21061022018-07-12 23:56:30 -040049 ANGLE_TRY(commandBuffer->begin(context, beginInfo));
50 return angle::Result::Continue();
Jamie Madill1f46bc12018-02-20 16:09:43 -050051}
52
53} // anonymous namespace
54
Jamie Madill6c7ab7f2018-03-31 14:19:15 -040055// CommandGraphResource implementation.
56CommandGraphResource::CommandGraphResource() : mCurrentWritingNode(nullptr)
57{
58}
59
Jamie Madill316c6062018-05-29 10:49:45 -040060CommandGraphResource::~CommandGraphResource() = default;
Jamie Madill6c7ab7f2018-03-31 14:19:15 -040061
62void CommandGraphResource::updateQueueSerial(Serial queueSerial)
63{
64 ASSERT(queueSerial >= mStoredQueueSerial);
65
66 if (queueSerial > mStoredQueueSerial)
67 {
68 mCurrentWritingNode = nullptr;
69 mCurrentReadingNodes.clear();
70 mStoredQueueSerial = queueSerial;
71 }
72}
73
Jamie Madillc57ee252018-05-30 19:53:48 -040074bool CommandGraphResource::isResourceInUse(RendererVk *renderer) const
75{
76 return renderer->isSerialInUse(mStoredQueueSerial);
77}
78
79Serial CommandGraphResource::getStoredQueueSerial() const
Jamie Madill6c7ab7f2018-03-31 14:19:15 -040080{
81 return mStoredQueueSerial;
82}
83
Jamie Madille2d22702018-09-19 08:11:48 -040084angle::Result CommandGraphResource::recordCommands(Context *context,
85 CommandBuffer **commandBufferOut)
Jamie Madill6c7ab7f2018-03-31 14:19:15 -040086{
Jamie Madill21061022018-07-12 23:56:30 -040087 updateQueueSerial(context->getRenderer()->getCurrentQueueSerial());
Jamie Madill5dca6512018-05-30 10:53:51 -040088
Jamie Madille2d22702018-09-19 08:11:48 -040089 if (!hasChildlessWritingNode() || hasStartedRenderPass())
Jamie Madill316c6062018-05-29 10:49:45 -040090 {
Jamie Madille2d22702018-09-19 08:11:48 -040091 finishCurrentCommands(context->getRenderer());
92 return mCurrentWritingNode->beginOutsideRenderPassRecording(
93 context, context->getRenderer()->getCommandPool(), commandBufferOut);
Jamie Madill316c6062018-05-29 10:49:45 -040094 }
95
96 CommandBuffer *outsideRenderPassCommands = mCurrentWritingNode->getOutsideRenderPassCommands();
97 if (!outsideRenderPassCommands->valid())
98 {
99 ANGLE_TRY(mCurrentWritingNode->beginOutsideRenderPassRecording(
Jamie Madill21061022018-07-12 23:56:30 -0400100 context, context->getRenderer()->getCommandPool(), commandBufferOut));
Jamie Madill316c6062018-05-29 10:49:45 -0400101 }
102 else
103 {
104 *commandBufferOut = outsideRenderPassCommands;
105 }
106
Jamie Madill21061022018-07-12 23:56:30 -0400107 return angle::Result::Continue();
Jamie Madill316c6062018-05-29 10:49:45 -0400108}
109
Jamie Madill5dca6512018-05-30 10:53:51 -0400110bool CommandGraphResource::appendToStartedRenderPass(RendererVk *renderer,
111 CommandBuffer **commandBufferOut)
Jamie Madill316c6062018-05-29 10:49:45 -0400112{
Jamie Madill5dca6512018-05-30 10:53:51 -0400113 updateQueueSerial(renderer->getCurrentQueueSerial());
114 if (hasStartedRenderPass())
115 {
116 *commandBufferOut = mCurrentWritingNode->getInsideRenderPassCommands();
117 return true;
118 }
119 else
120 {
121 return false;
122 }
Jamie Madill316c6062018-05-29 10:49:45 -0400123}
124
Jamie Madill316c6062018-05-29 10:49:45 -0400125const gl::Rectangle &CommandGraphResource::getRenderPassRenderArea() const
126{
127 ASSERT(hasStartedRenderPass());
128 return mCurrentWritingNode->getRenderPassRenderArea();
129}
130
Jamie Madill21061022018-07-12 23:56:30 -0400131angle::Result CommandGraphResource::beginRenderPass(Context *context,
132 const Framebuffer &framebuffer,
133 const gl::Rectangle &renderArea,
134 const RenderPassDesc &renderPassDesc,
135 const std::vector<VkClearValue> &clearValues,
136 CommandBuffer **commandBufferOut) const
Jamie Madill316c6062018-05-29 10:49:45 -0400137{
138 // Hard-code RenderPass to clear the first render target to the current clear value.
139 // TODO(jmadill): Proper clear value implementation. http://anglebug.com/2361
140 mCurrentWritingNode->storeRenderPassInfo(framebuffer, renderArea, renderPassDesc, clearValues);
141
Jamie Madill21061022018-07-12 23:56:30 -0400142 return mCurrentWritingNode->beginInsideRenderPassRecording(context, commandBufferOut);
Jamie Madill316c6062018-05-29 10:49:45 -0400143}
144
Jamie Madille2d22702018-09-19 08:11:48 -0400145void CommandGraphResource::finishCurrentCommands(RendererVk *renderer)
Jamie Madill316c6062018-05-29 10:49:45 -0400146{
Jamie Madill86ce2102018-05-22 11:54:42 -0400147 CommandGraphNode *newCommands = renderer->getCommandGraph()->allocateNode();
148 onWriteImpl(newCommands, renderer->getCurrentQueueSerial());
Jamie Madill316c6062018-05-29 10:49:45 -0400149}
150
151void CommandGraphResource::addWriteDependency(CommandGraphResource *writingResource)
152{
153 CommandGraphNode *writingNode = writingResource->mCurrentWritingNode;
154 ASSERT(writingNode);
155
Jamie Madillc57ee252018-05-30 19:53:48 -0400156 onWriteImpl(writingNode, writingResource->getStoredQueueSerial());
Jamie Madill316c6062018-05-29 10:49:45 -0400157}
158
159void CommandGraphResource::onWriteImpl(CommandGraphNode *writingNode, Serial currentSerial)
160{
161 updateQueueSerial(currentSerial);
Jamie Madill6c7ab7f2018-03-31 14:19:15 -0400162
Jamie Madill9cceac42018-03-31 14:19:16 -0400163 // Make sure any open reads and writes finish before we execute 'writingNode'.
Jamie Madill6c7ab7f2018-03-31 14:19:15 -0400164 if (!mCurrentReadingNodes.empty())
165 {
166 CommandGraphNode::SetHappensBeforeDependencies(mCurrentReadingNodes, writingNode);
167 mCurrentReadingNodes.clear();
168 }
169
170 if (mCurrentWritingNode && mCurrentWritingNode != writingNode)
171 {
172 CommandGraphNode::SetHappensBeforeDependency(mCurrentWritingNode, writingNode);
173 }
174
175 mCurrentWritingNode = writingNode;
176}
177
Jamie Madill316c6062018-05-29 10:49:45 -0400178void CommandGraphResource::addReadDependency(CommandGraphResource *readingResource)
Jamie Madill6c7ab7f2018-03-31 14:19:15 -0400179{
Jamie Madillc57ee252018-05-30 19:53:48 -0400180 updateQueueSerial(readingResource->getStoredQueueSerial());
Jamie Madill316c6062018-05-29 10:49:45 -0400181
182 CommandGraphNode *readingNode = readingResource->mCurrentWritingNode;
183 ASSERT(readingNode);
Jamie Madill9cceac42018-03-31 14:19:16 -0400184
185 if (hasChildlessWritingNode())
Jamie Madill6c7ab7f2018-03-31 14:19:15 -0400186 {
Jamie Madill9cceac42018-03-31 14:19:16 -0400187 // Ensure 'readingNode' happens after the current writing node.
188 CommandGraphNode::SetHappensBeforeDependency(mCurrentWritingNode, readingNode);
189 }
190
191 // Add the read node to the list of nodes currently reading this resource.
192 mCurrentReadingNodes.push_back(readingNode);
193}
194
Jamie Madill1f46bc12018-02-20 16:09:43 -0500195// CommandGraphNode implementation.
Jamie Madill316c6062018-05-29 10:49:45 -0400196CommandGraphNode::CommandGraphNode()
197 : mRenderPassClearValues{}, mHasChildren(false), mVisitedState(VisitedState::Unvisited)
Jamie Madill1f46bc12018-02-20 16:09:43 -0500198{
199}
200
201CommandGraphNode::~CommandGraphNode()
202{
203 mRenderPassFramebuffer.setHandle(VK_NULL_HANDLE);
204
205 // Command buffers are managed by the command pool, so don't need to be freed.
206 mOutsideRenderPassCommands.releaseHandle();
207 mInsideRenderPassCommands.releaseHandle();
208}
209
210CommandBuffer *CommandGraphNode::getOutsideRenderPassCommands()
211{
212 ASSERT(!mHasChildren);
213 return &mOutsideRenderPassCommands;
214}
215
Jamie Madill21061022018-07-12 23:56:30 -0400216angle::Result CommandGraphNode::beginOutsideRenderPassRecording(Context *context,
217 const CommandPool &commandPool,
218 CommandBuffer **commandsOut)
Jamie Madill1f46bc12018-02-20 16:09:43 -0500219{
220 ASSERT(!mHasChildren);
221
222 VkCommandBufferInheritanceInfo inheritanceInfo;
223 inheritanceInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
224 inheritanceInfo.pNext = nullptr;
225 inheritanceInfo.renderPass = VK_NULL_HANDLE;
226 inheritanceInfo.subpass = 0;
227 inheritanceInfo.framebuffer = VK_NULL_HANDLE;
228 inheritanceInfo.occlusionQueryEnable = VK_FALSE;
229 inheritanceInfo.queryFlags = 0;
230 inheritanceInfo.pipelineStatistics = 0;
231
Jamie Madill21061022018-07-12 23:56:30 -0400232 ANGLE_TRY(InitAndBeginCommandBuffer(context, commandPool, inheritanceInfo, 0,
Jamie Madill1f46bc12018-02-20 16:09:43 -0500233 &mOutsideRenderPassCommands));
234
235 *commandsOut = &mOutsideRenderPassCommands;
Jamie Madill21061022018-07-12 23:56:30 -0400236 return angle::Result::Continue();
Jamie Madill1f46bc12018-02-20 16:09:43 -0500237}
238
Jamie Madill21061022018-07-12 23:56:30 -0400239angle::Result CommandGraphNode::beginInsideRenderPassRecording(Context *context,
240 CommandBuffer **commandsOut)
Jamie Madill1f46bc12018-02-20 16:09:43 -0500241{
242 ASSERT(!mHasChildren);
243
244 // Get a compatible RenderPass from the cache so we can initialize the inheritance info.
245 // TODO(jmadill): Support query for compatible/conformant render pass. htto://anglebug.com/2361
246 RenderPass *compatibleRenderPass;
Jamie Madill21061022018-07-12 23:56:30 -0400247 ANGLE_TRY(context->getRenderer()->getCompatibleRenderPass(context, mRenderPassDesc,
248 &compatibleRenderPass));
Jamie Madill1f46bc12018-02-20 16:09:43 -0500249
250 VkCommandBufferInheritanceInfo inheritanceInfo;
251 inheritanceInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
252 inheritanceInfo.pNext = nullptr;
253 inheritanceInfo.renderPass = compatibleRenderPass->getHandle();
254 inheritanceInfo.subpass = 0;
255 inheritanceInfo.framebuffer = mRenderPassFramebuffer.getHandle();
256 inheritanceInfo.occlusionQueryEnable = VK_FALSE;
257 inheritanceInfo.queryFlags = 0;
258 inheritanceInfo.pipelineStatistics = 0;
259
260 ANGLE_TRY(InitAndBeginCommandBuffer(
Jamie Madill21061022018-07-12 23:56:30 -0400261 context, context->getRenderer()->getCommandPool(), inheritanceInfo,
Jamie Madill1f46bc12018-02-20 16:09:43 -0500262 VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, &mInsideRenderPassCommands));
263
264 *commandsOut = &mInsideRenderPassCommands;
Jamie Madill21061022018-07-12 23:56:30 -0400265 return angle::Result::Continue();
Jamie Madill1f46bc12018-02-20 16:09:43 -0500266}
267
268void CommandGraphNode::storeRenderPassInfo(const Framebuffer &framebuffer,
269 const gl::Rectangle renderArea,
Jamie Madillbcf467f2018-05-23 09:46:00 -0400270 const vk::RenderPassDesc &renderPassDesc,
Jamie Madill1f46bc12018-02-20 16:09:43 -0500271 const std::vector<VkClearValue> &clearValues)
272{
Jamie Madillbcf467f2018-05-23 09:46:00 -0400273 mRenderPassDesc = renderPassDesc;
Jamie Madill1f46bc12018-02-20 16:09:43 -0500274 mRenderPassFramebuffer.setHandle(framebuffer.getHandle());
275 mRenderPassRenderArea = renderArea;
276 std::copy(clearValues.begin(), clearValues.end(), mRenderPassClearValues.begin());
277}
278
Jamie Madill1f46bc12018-02-20 16:09:43 -0500279// static
280void CommandGraphNode::SetHappensBeforeDependency(CommandGraphNode *beforeNode,
281 CommandGraphNode *afterNode)
282{
Jamie Madill9cceac42018-03-31 14:19:16 -0400283 ASSERT(beforeNode != afterNode && !beforeNode->isChildOf(afterNode));
Jamie Madill1f46bc12018-02-20 16:09:43 -0500284 afterNode->mParents.emplace_back(beforeNode);
285 beforeNode->setHasChildren();
Jamie Madill1f46bc12018-02-20 16:09:43 -0500286}
287
288// static
289void CommandGraphNode::SetHappensBeforeDependencies(
290 const std::vector<CommandGraphNode *> &beforeNodes,
291 CommandGraphNode *afterNode)
292{
293 afterNode->mParents.insert(afterNode->mParents.end(), beforeNodes.begin(), beforeNodes.end());
294
295 // TODO(jmadill): is there a faster way to do this?
296 for (CommandGraphNode *beforeNode : beforeNodes)
297 {
298 beforeNode->setHasChildren();
299
300 ASSERT(beforeNode != afterNode && !beforeNode->isChildOf(afterNode));
301 }
302}
303
304bool CommandGraphNode::hasParents() const
305{
306 return !mParents.empty();
307}
308
309void CommandGraphNode::setHasChildren()
310{
311 mHasChildren = true;
312}
313
Jamie Madill1f46bc12018-02-20 16:09:43 -0500314// Do not call this in anything but testing code, since it's slow.
315bool CommandGraphNode::isChildOf(CommandGraphNode *parent)
316{
317 std::set<CommandGraphNode *> visitedList;
318 std::vector<CommandGraphNode *> openList;
319 openList.insert(openList.begin(), mParents.begin(), mParents.end());
320 while (!openList.empty())
321 {
322 CommandGraphNode *current = openList.back();
323 openList.pop_back();
324 if (visitedList.count(current) == 0)
325 {
326 if (current == parent)
327 {
328 return true;
329 }
330 visitedList.insert(current);
331 openList.insert(openList.end(), current->mParents.begin(), current->mParents.end());
332 }
333 }
334
335 return false;
336}
337
338VisitedState CommandGraphNode::visitedState() const
339{
340 return mVisitedState;
341}
342
343void CommandGraphNode::visitParents(std::vector<CommandGraphNode *> *stack)
344{
345 ASSERT(mVisitedState == VisitedState::Unvisited);
346 stack->insert(stack->end(), mParents.begin(), mParents.end());
347 mVisitedState = VisitedState::Ready;
348}
349
Jamie Madill21061022018-07-12 23:56:30 -0400350angle::Result CommandGraphNode::visitAndExecute(vk::Context *context,
351 Serial serial,
352 RenderPassCache *renderPassCache,
353 CommandBuffer *primaryCommandBuffer)
Jamie Madill1f46bc12018-02-20 16:09:43 -0500354{
355 if (mOutsideRenderPassCommands.valid())
356 {
Jamie Madill21061022018-07-12 23:56:30 -0400357 ANGLE_TRY(mOutsideRenderPassCommands.end(context));
Jamie Madill1f46bc12018-02-20 16:09:43 -0500358 primaryCommandBuffer->executeCommands(1, &mOutsideRenderPassCommands);
359 }
360
361 if (mInsideRenderPassCommands.valid())
362 {
363 // Pull a compatible RenderPass from the cache.
364 // TODO(jmadill): Insert real ops and layout transitions.
365 RenderPass *renderPass = nullptr;
Jamie Madill21061022018-07-12 23:56:30 -0400366 ANGLE_TRY(renderPassCache->getCompatibleRenderPass(context, serial, mRenderPassDesc,
367 &renderPass));
Jamie Madill1f46bc12018-02-20 16:09:43 -0500368
Jamie Madill21061022018-07-12 23:56:30 -0400369 ANGLE_TRY(mInsideRenderPassCommands.end(context));
Jamie Madill1f46bc12018-02-20 16:09:43 -0500370
371 VkRenderPassBeginInfo beginInfo;
372 beginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
373 beginInfo.pNext = nullptr;
374 beginInfo.renderPass = renderPass->getHandle();
375 beginInfo.framebuffer = mRenderPassFramebuffer.getHandle();
376 beginInfo.renderArea.offset.x = static_cast<uint32_t>(mRenderPassRenderArea.x);
377 beginInfo.renderArea.offset.y = static_cast<uint32_t>(mRenderPassRenderArea.y);
378 beginInfo.renderArea.extent.width = static_cast<uint32_t>(mRenderPassRenderArea.width);
379 beginInfo.renderArea.extent.height = static_cast<uint32_t>(mRenderPassRenderArea.height);
380 beginInfo.clearValueCount = mRenderPassDesc.attachmentCount();
381 beginInfo.pClearValues = mRenderPassClearValues.data();
382
383 primaryCommandBuffer->beginRenderPass(beginInfo,
384 VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
385 primaryCommandBuffer->executeCommands(1, &mInsideRenderPassCommands);
386 primaryCommandBuffer->endRenderPass();
387 }
388
389 mVisitedState = VisitedState::Visited;
Jamie Madill21061022018-07-12 23:56:30 -0400390 return angle::Result::Continue();
Jamie Madill1f46bc12018-02-20 16:09:43 -0500391}
392
Luc Ferron14f48172018-04-11 08:43:28 -0400393const gl::Rectangle &CommandGraphNode::getRenderPassRenderArea() const
394{
395 return mRenderPassRenderArea;
396}
397
Jamie Madill1f46bc12018-02-20 16:09:43 -0500398// CommandGraph implementation.
Jamie Madill316c6062018-05-29 10:49:45 -0400399CommandGraph::CommandGraph() = default;
Jamie Madill1f46bc12018-02-20 16:09:43 -0500400
401CommandGraph::~CommandGraph()
402{
403 ASSERT(empty());
404}
405
406CommandGraphNode *CommandGraph::allocateNode()
407{
408 // TODO(jmadill): Use a pool allocator for the CPU node allocations.
409 CommandGraphNode *newCommands = new CommandGraphNode();
410 mNodes.emplace_back(newCommands);
411 return newCommands;
412}
413
Jamie Madill21061022018-07-12 23:56:30 -0400414angle::Result CommandGraph::submitCommands(Context *context,
415 Serial serial,
416 RenderPassCache *renderPassCache,
417 CommandPool *commandPool,
418 CommandBuffer *primaryCommandBufferOut)
Jamie Madill1f46bc12018-02-20 16:09:43 -0500419{
420 VkCommandBufferAllocateInfo primaryInfo;
421 primaryInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
422 primaryInfo.pNext = nullptr;
423 primaryInfo.commandPool = commandPool->getHandle();
424 primaryInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
425 primaryInfo.commandBufferCount = 1;
426
Jamie Madill21061022018-07-12 23:56:30 -0400427 ANGLE_TRY(primaryCommandBufferOut->init(context, primaryInfo));
Jamie Madill1f46bc12018-02-20 16:09:43 -0500428
429 if (mNodes.empty())
430 {
Jamie Madill21061022018-07-12 23:56:30 -0400431 return angle::Result::Continue();
Jamie Madill1f46bc12018-02-20 16:09:43 -0500432 }
433
434 std::vector<CommandGraphNode *> nodeStack;
435
436 VkCommandBufferBeginInfo beginInfo;
437 beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
438 beginInfo.pNext = nullptr;
439 beginInfo.flags = 0;
440 beginInfo.pInheritanceInfo = nullptr;
441
Jamie Madill21061022018-07-12 23:56:30 -0400442 ANGLE_TRY(primaryCommandBufferOut->begin(context, beginInfo));
Jamie Madill1f46bc12018-02-20 16:09:43 -0500443
444 for (CommandGraphNode *topLevelNode : mNodes)
445 {
446 // Only process commands that don't have child commands. The others will be pulled in
447 // automatically. Also skip commands that have already been visited.
448 if (topLevelNode->hasChildren() || topLevelNode->visitedState() != VisitedState::Unvisited)
449 continue;
450
451 nodeStack.push_back(topLevelNode);
452
453 while (!nodeStack.empty())
454 {
455 CommandGraphNode *node = nodeStack.back();
456
457 switch (node->visitedState())
458 {
459 case VisitedState::Unvisited:
460 node->visitParents(&nodeStack);
461 break;
462 case VisitedState::Ready:
Jamie Madill21061022018-07-12 23:56:30 -0400463 ANGLE_TRY(node->visitAndExecute(context, serial, renderPassCache,
Jamie Madill1f46bc12018-02-20 16:09:43 -0500464 primaryCommandBufferOut));
465 nodeStack.pop_back();
466 break;
467 case VisitedState::Visited:
468 nodeStack.pop_back();
469 break;
470 default:
471 UNREACHABLE();
472 break;
473 }
474 }
475 }
476
Jamie Madill21061022018-07-12 23:56:30 -0400477 ANGLE_TRY(primaryCommandBufferOut->end(context));
Jamie Madill1f46bc12018-02-20 16:09:43 -0500478
479 // TODO(jmadill): Use pool allocation so we don't need to deallocate command graph.
Jamie Madill6c7ab7f2018-03-31 14:19:15 -0400480 for (CommandGraphNode *node : mNodes)
Jamie Madill1f46bc12018-02-20 16:09:43 -0500481 {
482 delete node;
483 }
484 mNodes.clear();
485
Jamie Madill21061022018-07-12 23:56:30 -0400486 return angle::Result::Continue();
Jamie Madill1f46bc12018-02-20 16:09:43 -0500487}
488
489bool CommandGraph::empty() const
490{
491 return mNodes.empty();
492}
493
494} // namespace vk
495} // namespace rx