blob: 9d91a80bf492c3d016ee48e27f54049a52a09c32 [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 Madill316c6062018-05-29 10:49:45 -040084bool CommandGraphResource::hasStartedWriteResource() const
85{
86 return hasChildlessWritingNode() &&
87 mCurrentWritingNode->getOutsideRenderPassCommands()->valid();
88}
89
Jamie Madill21061022018-07-12 23:56:30 -040090angle::Result CommandGraphResource::beginWriteResource(Context *context,
91 CommandBuffer **commandBufferOut)
Jamie Madill6c7ab7f2018-03-31 14:19:15 -040092{
Jamie Madill21061022018-07-12 23:56:30 -040093 onResourceChanged(context->getRenderer());
94 return mCurrentWritingNode->beginOutsideRenderPassRecording(
95 context, context->getRenderer()->getCommandPool(), commandBufferOut);
Jamie Madill6c7ab7f2018-03-31 14:19:15 -040096}
97
Jamie Madill21061022018-07-12 23:56:30 -040098angle::Result CommandGraphResource::appendWriteResource(Context *context,
99 CommandBuffer **commandBufferOut)
Jamie Madill6c7ab7f2018-03-31 14:19:15 -0400100{
Jamie Madill21061022018-07-12 23:56:30 -0400101 updateQueueSerial(context->getRenderer()->getCurrentQueueSerial());
Jamie Madill5dca6512018-05-30 10:53:51 -0400102
Jamie Madill316c6062018-05-29 10:49:45 -0400103 if (!hasChildlessWritingNode())
104 {
Jamie Madill21061022018-07-12 23:56:30 -0400105 return beginWriteResource(context, commandBufferOut);
Jamie Madill316c6062018-05-29 10:49:45 -0400106 }
107
108 CommandBuffer *outsideRenderPassCommands = mCurrentWritingNode->getOutsideRenderPassCommands();
109 if (!outsideRenderPassCommands->valid())
110 {
111 ANGLE_TRY(mCurrentWritingNode->beginOutsideRenderPassRecording(
Jamie Madill21061022018-07-12 23:56:30 -0400112 context, context->getRenderer()->getCommandPool(), commandBufferOut));
Jamie Madill316c6062018-05-29 10:49:45 -0400113 }
114 else
115 {
116 *commandBufferOut = outsideRenderPassCommands;
117 }
118
Jamie Madill21061022018-07-12 23:56:30 -0400119 return angle::Result::Continue();
Jamie Madill316c6062018-05-29 10:49:45 -0400120}
121
Jamie Madill5dca6512018-05-30 10:53:51 -0400122bool CommandGraphResource::appendToStartedRenderPass(RendererVk *renderer,
123 CommandBuffer **commandBufferOut)
Jamie Madill316c6062018-05-29 10:49:45 -0400124{
Jamie Madill5dca6512018-05-30 10:53:51 -0400125 updateQueueSerial(renderer->getCurrentQueueSerial());
126 if (hasStartedRenderPass())
127 {
128 *commandBufferOut = mCurrentWritingNode->getInsideRenderPassCommands();
129 return true;
130 }
131 else
132 {
133 return false;
134 }
Jamie Madill316c6062018-05-29 10:49:45 -0400135}
136
Jamie Madill316c6062018-05-29 10:49:45 -0400137const gl::Rectangle &CommandGraphResource::getRenderPassRenderArea() const
138{
139 ASSERT(hasStartedRenderPass());
140 return mCurrentWritingNode->getRenderPassRenderArea();
141}
142
Jamie Madill21061022018-07-12 23:56:30 -0400143angle::Result CommandGraphResource::beginRenderPass(Context *context,
144 const Framebuffer &framebuffer,
145 const gl::Rectangle &renderArea,
146 const RenderPassDesc &renderPassDesc,
147 const std::vector<VkClearValue> &clearValues,
148 CommandBuffer **commandBufferOut) const
Jamie Madill316c6062018-05-29 10:49:45 -0400149{
150 // Hard-code RenderPass to clear the first render target to the current clear value.
151 // TODO(jmadill): Proper clear value implementation. http://anglebug.com/2361
152 mCurrentWritingNode->storeRenderPassInfo(framebuffer, renderArea, renderPassDesc, clearValues);
153
Jamie Madill21061022018-07-12 23:56:30 -0400154 return mCurrentWritingNode->beginInsideRenderPassRecording(context, commandBufferOut);
Jamie Madill316c6062018-05-29 10:49:45 -0400155}
156
157void CommandGraphResource::onResourceChanged(RendererVk *renderer)
158{
Jamie Madill86ce2102018-05-22 11:54:42 -0400159 CommandGraphNode *newCommands = renderer->getCommandGraph()->allocateNode();
160 onWriteImpl(newCommands, renderer->getCurrentQueueSerial());
Jamie Madill316c6062018-05-29 10:49:45 -0400161}
162
163void CommandGraphResource::addWriteDependency(CommandGraphResource *writingResource)
164{
165 CommandGraphNode *writingNode = writingResource->mCurrentWritingNode;
166 ASSERT(writingNode);
167
Jamie Madillc57ee252018-05-30 19:53:48 -0400168 onWriteImpl(writingNode, writingResource->getStoredQueueSerial());
Jamie Madill316c6062018-05-29 10:49:45 -0400169}
170
171void CommandGraphResource::onWriteImpl(CommandGraphNode *writingNode, Serial currentSerial)
172{
173 updateQueueSerial(currentSerial);
Jamie Madill6c7ab7f2018-03-31 14:19:15 -0400174
Jamie Madill9cceac42018-03-31 14:19:16 -0400175 // Make sure any open reads and writes finish before we execute 'writingNode'.
Jamie Madill6c7ab7f2018-03-31 14:19:15 -0400176 if (!mCurrentReadingNodes.empty())
177 {
178 CommandGraphNode::SetHappensBeforeDependencies(mCurrentReadingNodes, writingNode);
179 mCurrentReadingNodes.clear();
180 }
181
182 if (mCurrentWritingNode && mCurrentWritingNode != writingNode)
183 {
184 CommandGraphNode::SetHappensBeforeDependency(mCurrentWritingNode, writingNode);
185 }
186
187 mCurrentWritingNode = writingNode;
188}
189
Jamie Madill316c6062018-05-29 10:49:45 -0400190void CommandGraphResource::addReadDependency(CommandGraphResource *readingResource)
Jamie Madill6c7ab7f2018-03-31 14:19:15 -0400191{
Jamie Madillc57ee252018-05-30 19:53:48 -0400192 updateQueueSerial(readingResource->getStoredQueueSerial());
Jamie Madill316c6062018-05-29 10:49:45 -0400193
194 CommandGraphNode *readingNode = readingResource->mCurrentWritingNode;
195 ASSERT(readingNode);
Jamie Madill9cceac42018-03-31 14:19:16 -0400196
197 if (hasChildlessWritingNode())
Jamie Madill6c7ab7f2018-03-31 14:19:15 -0400198 {
Jamie Madill9cceac42018-03-31 14:19:16 -0400199 // Ensure 'readingNode' happens after the current writing node.
200 CommandGraphNode::SetHappensBeforeDependency(mCurrentWritingNode, readingNode);
201 }
202
203 // Add the read node to the list of nodes currently reading this resource.
204 mCurrentReadingNodes.push_back(readingNode);
205}
206
Jamie Madill1f46bc12018-02-20 16:09:43 -0500207// CommandGraphNode implementation.
Jamie Madill316c6062018-05-29 10:49:45 -0400208CommandGraphNode::CommandGraphNode()
209 : mRenderPassClearValues{}, mHasChildren(false), mVisitedState(VisitedState::Unvisited)
Jamie Madill1f46bc12018-02-20 16:09:43 -0500210{
211}
212
213CommandGraphNode::~CommandGraphNode()
214{
215 mRenderPassFramebuffer.setHandle(VK_NULL_HANDLE);
216
217 // Command buffers are managed by the command pool, so don't need to be freed.
218 mOutsideRenderPassCommands.releaseHandle();
219 mInsideRenderPassCommands.releaseHandle();
220}
221
222CommandBuffer *CommandGraphNode::getOutsideRenderPassCommands()
223{
224 ASSERT(!mHasChildren);
225 return &mOutsideRenderPassCommands;
226}
227
Jamie Madill21061022018-07-12 23:56:30 -0400228angle::Result CommandGraphNode::beginOutsideRenderPassRecording(Context *context,
229 const CommandPool &commandPool,
230 CommandBuffer **commandsOut)
Jamie Madill1f46bc12018-02-20 16:09:43 -0500231{
232 ASSERT(!mHasChildren);
233
234 VkCommandBufferInheritanceInfo inheritanceInfo;
235 inheritanceInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
236 inheritanceInfo.pNext = nullptr;
237 inheritanceInfo.renderPass = VK_NULL_HANDLE;
238 inheritanceInfo.subpass = 0;
239 inheritanceInfo.framebuffer = VK_NULL_HANDLE;
240 inheritanceInfo.occlusionQueryEnable = VK_FALSE;
241 inheritanceInfo.queryFlags = 0;
242 inheritanceInfo.pipelineStatistics = 0;
243
Jamie Madill21061022018-07-12 23:56:30 -0400244 ANGLE_TRY(InitAndBeginCommandBuffer(context, commandPool, inheritanceInfo, 0,
Jamie Madill1f46bc12018-02-20 16:09:43 -0500245 &mOutsideRenderPassCommands));
246
247 *commandsOut = &mOutsideRenderPassCommands;
Jamie Madill21061022018-07-12 23:56:30 -0400248 return angle::Result::Continue();
Jamie Madill1f46bc12018-02-20 16:09:43 -0500249}
250
Jamie Madill21061022018-07-12 23:56:30 -0400251angle::Result CommandGraphNode::beginInsideRenderPassRecording(Context *context,
252 CommandBuffer **commandsOut)
Jamie Madill1f46bc12018-02-20 16:09:43 -0500253{
254 ASSERT(!mHasChildren);
255
256 // Get a compatible RenderPass from the cache so we can initialize the inheritance info.
257 // TODO(jmadill): Support query for compatible/conformant render pass. htto://anglebug.com/2361
258 RenderPass *compatibleRenderPass;
Jamie Madill21061022018-07-12 23:56:30 -0400259 ANGLE_TRY(context->getRenderer()->getCompatibleRenderPass(context, mRenderPassDesc,
260 &compatibleRenderPass));
Jamie Madill1f46bc12018-02-20 16:09:43 -0500261
262 VkCommandBufferInheritanceInfo inheritanceInfo;
263 inheritanceInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
264 inheritanceInfo.pNext = nullptr;
265 inheritanceInfo.renderPass = compatibleRenderPass->getHandle();
266 inheritanceInfo.subpass = 0;
267 inheritanceInfo.framebuffer = mRenderPassFramebuffer.getHandle();
268 inheritanceInfo.occlusionQueryEnable = VK_FALSE;
269 inheritanceInfo.queryFlags = 0;
270 inheritanceInfo.pipelineStatistics = 0;
271
272 ANGLE_TRY(InitAndBeginCommandBuffer(
Jamie Madill21061022018-07-12 23:56:30 -0400273 context, context->getRenderer()->getCommandPool(), inheritanceInfo,
Jamie Madill1f46bc12018-02-20 16:09:43 -0500274 VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, &mInsideRenderPassCommands));
275
276 *commandsOut = &mInsideRenderPassCommands;
Jamie Madill21061022018-07-12 23:56:30 -0400277 return angle::Result::Continue();
Jamie Madill1f46bc12018-02-20 16:09:43 -0500278}
279
280void CommandGraphNode::storeRenderPassInfo(const Framebuffer &framebuffer,
281 const gl::Rectangle renderArea,
Jamie Madillbcf467f2018-05-23 09:46:00 -0400282 const vk::RenderPassDesc &renderPassDesc,
Jamie Madill1f46bc12018-02-20 16:09:43 -0500283 const std::vector<VkClearValue> &clearValues)
284{
Jamie Madillbcf467f2018-05-23 09:46:00 -0400285 mRenderPassDesc = renderPassDesc;
Jamie Madill1f46bc12018-02-20 16:09:43 -0500286 mRenderPassFramebuffer.setHandle(framebuffer.getHandle());
287 mRenderPassRenderArea = renderArea;
288 std::copy(clearValues.begin(), clearValues.end(), mRenderPassClearValues.begin());
289}
290
Jamie Madill1f46bc12018-02-20 16:09:43 -0500291// static
292void CommandGraphNode::SetHappensBeforeDependency(CommandGraphNode *beforeNode,
293 CommandGraphNode *afterNode)
294{
Jamie Madill9cceac42018-03-31 14:19:16 -0400295 ASSERT(beforeNode != afterNode && !beforeNode->isChildOf(afterNode));
Jamie Madill1f46bc12018-02-20 16:09:43 -0500296 afterNode->mParents.emplace_back(beforeNode);
297 beforeNode->setHasChildren();
Jamie Madill1f46bc12018-02-20 16:09:43 -0500298}
299
300// static
301void CommandGraphNode::SetHappensBeforeDependencies(
302 const std::vector<CommandGraphNode *> &beforeNodes,
303 CommandGraphNode *afterNode)
304{
305 afterNode->mParents.insert(afterNode->mParents.end(), beforeNodes.begin(), beforeNodes.end());
306
307 // TODO(jmadill): is there a faster way to do this?
308 for (CommandGraphNode *beforeNode : beforeNodes)
309 {
310 beforeNode->setHasChildren();
311
312 ASSERT(beforeNode != afterNode && !beforeNode->isChildOf(afterNode));
313 }
314}
315
316bool CommandGraphNode::hasParents() const
317{
318 return !mParents.empty();
319}
320
321void CommandGraphNode::setHasChildren()
322{
323 mHasChildren = true;
324}
325
Jamie Madill1f46bc12018-02-20 16:09:43 -0500326// Do not call this in anything but testing code, since it's slow.
327bool CommandGraphNode::isChildOf(CommandGraphNode *parent)
328{
329 std::set<CommandGraphNode *> visitedList;
330 std::vector<CommandGraphNode *> openList;
331 openList.insert(openList.begin(), mParents.begin(), mParents.end());
332 while (!openList.empty())
333 {
334 CommandGraphNode *current = openList.back();
335 openList.pop_back();
336 if (visitedList.count(current) == 0)
337 {
338 if (current == parent)
339 {
340 return true;
341 }
342 visitedList.insert(current);
343 openList.insert(openList.end(), current->mParents.begin(), current->mParents.end());
344 }
345 }
346
347 return false;
348}
349
350VisitedState CommandGraphNode::visitedState() const
351{
352 return mVisitedState;
353}
354
355void CommandGraphNode::visitParents(std::vector<CommandGraphNode *> *stack)
356{
357 ASSERT(mVisitedState == VisitedState::Unvisited);
358 stack->insert(stack->end(), mParents.begin(), mParents.end());
359 mVisitedState = VisitedState::Ready;
360}
361
Jamie Madill21061022018-07-12 23:56:30 -0400362angle::Result CommandGraphNode::visitAndExecute(vk::Context *context,
363 Serial serial,
364 RenderPassCache *renderPassCache,
365 CommandBuffer *primaryCommandBuffer)
Jamie Madill1f46bc12018-02-20 16:09:43 -0500366{
367 if (mOutsideRenderPassCommands.valid())
368 {
Jamie Madill21061022018-07-12 23:56:30 -0400369 ANGLE_TRY(mOutsideRenderPassCommands.end(context));
Jamie Madill1f46bc12018-02-20 16:09:43 -0500370 primaryCommandBuffer->executeCommands(1, &mOutsideRenderPassCommands);
371 }
372
373 if (mInsideRenderPassCommands.valid())
374 {
375 // Pull a compatible RenderPass from the cache.
376 // TODO(jmadill): Insert real ops and layout transitions.
377 RenderPass *renderPass = nullptr;
Jamie Madill21061022018-07-12 23:56:30 -0400378 ANGLE_TRY(renderPassCache->getCompatibleRenderPass(context, serial, mRenderPassDesc,
379 &renderPass));
Jamie Madill1f46bc12018-02-20 16:09:43 -0500380
Jamie Madill21061022018-07-12 23:56:30 -0400381 ANGLE_TRY(mInsideRenderPassCommands.end(context));
Jamie Madill1f46bc12018-02-20 16:09:43 -0500382
383 VkRenderPassBeginInfo beginInfo;
384 beginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
385 beginInfo.pNext = nullptr;
386 beginInfo.renderPass = renderPass->getHandle();
387 beginInfo.framebuffer = mRenderPassFramebuffer.getHandle();
388 beginInfo.renderArea.offset.x = static_cast<uint32_t>(mRenderPassRenderArea.x);
389 beginInfo.renderArea.offset.y = static_cast<uint32_t>(mRenderPassRenderArea.y);
390 beginInfo.renderArea.extent.width = static_cast<uint32_t>(mRenderPassRenderArea.width);
391 beginInfo.renderArea.extent.height = static_cast<uint32_t>(mRenderPassRenderArea.height);
392 beginInfo.clearValueCount = mRenderPassDesc.attachmentCount();
393 beginInfo.pClearValues = mRenderPassClearValues.data();
394
395 primaryCommandBuffer->beginRenderPass(beginInfo,
396 VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
397 primaryCommandBuffer->executeCommands(1, &mInsideRenderPassCommands);
398 primaryCommandBuffer->endRenderPass();
399 }
400
401 mVisitedState = VisitedState::Visited;
Jamie Madill21061022018-07-12 23:56:30 -0400402 return angle::Result::Continue();
Jamie Madill1f46bc12018-02-20 16:09:43 -0500403}
404
Luc Ferron14f48172018-04-11 08:43:28 -0400405const gl::Rectangle &CommandGraphNode::getRenderPassRenderArea() const
406{
407 return mRenderPassRenderArea;
408}
409
Jamie Madill1f46bc12018-02-20 16:09:43 -0500410// CommandGraph implementation.
Jamie Madill316c6062018-05-29 10:49:45 -0400411CommandGraph::CommandGraph() = default;
Jamie Madill1f46bc12018-02-20 16:09:43 -0500412
413CommandGraph::~CommandGraph()
414{
415 ASSERT(empty());
416}
417
418CommandGraphNode *CommandGraph::allocateNode()
419{
420 // TODO(jmadill): Use a pool allocator for the CPU node allocations.
421 CommandGraphNode *newCommands = new CommandGraphNode();
422 mNodes.emplace_back(newCommands);
423 return newCommands;
424}
425
Jamie Madill21061022018-07-12 23:56:30 -0400426angle::Result CommandGraph::submitCommands(Context *context,
427 Serial serial,
428 RenderPassCache *renderPassCache,
429 CommandPool *commandPool,
430 CommandBuffer *primaryCommandBufferOut)
Jamie Madill1f46bc12018-02-20 16:09:43 -0500431{
432 VkCommandBufferAllocateInfo primaryInfo;
433 primaryInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
434 primaryInfo.pNext = nullptr;
435 primaryInfo.commandPool = commandPool->getHandle();
436 primaryInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
437 primaryInfo.commandBufferCount = 1;
438
Jamie Madill21061022018-07-12 23:56:30 -0400439 ANGLE_TRY(primaryCommandBufferOut->init(context, primaryInfo));
Jamie Madill1f46bc12018-02-20 16:09:43 -0500440
441 if (mNodes.empty())
442 {
Jamie Madill21061022018-07-12 23:56:30 -0400443 return angle::Result::Continue();
Jamie Madill1f46bc12018-02-20 16:09:43 -0500444 }
445
446 std::vector<CommandGraphNode *> nodeStack;
447
448 VkCommandBufferBeginInfo beginInfo;
449 beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
450 beginInfo.pNext = nullptr;
451 beginInfo.flags = 0;
452 beginInfo.pInheritanceInfo = nullptr;
453
Jamie Madill21061022018-07-12 23:56:30 -0400454 ANGLE_TRY(primaryCommandBufferOut->begin(context, beginInfo));
Jamie Madill1f46bc12018-02-20 16:09:43 -0500455
456 for (CommandGraphNode *topLevelNode : mNodes)
457 {
458 // Only process commands that don't have child commands. The others will be pulled in
459 // automatically. Also skip commands that have already been visited.
460 if (topLevelNode->hasChildren() || topLevelNode->visitedState() != VisitedState::Unvisited)
461 continue;
462
463 nodeStack.push_back(topLevelNode);
464
465 while (!nodeStack.empty())
466 {
467 CommandGraphNode *node = nodeStack.back();
468
469 switch (node->visitedState())
470 {
471 case VisitedState::Unvisited:
472 node->visitParents(&nodeStack);
473 break;
474 case VisitedState::Ready:
Jamie Madill21061022018-07-12 23:56:30 -0400475 ANGLE_TRY(node->visitAndExecute(context, serial, renderPassCache,
Jamie Madill1f46bc12018-02-20 16:09:43 -0500476 primaryCommandBufferOut));
477 nodeStack.pop_back();
478 break;
479 case VisitedState::Visited:
480 nodeStack.pop_back();
481 break;
482 default:
483 UNREACHABLE();
484 break;
485 }
486 }
487 }
488
Jamie Madill21061022018-07-12 23:56:30 -0400489 ANGLE_TRY(primaryCommandBufferOut->end(context));
Jamie Madill1f46bc12018-02-20 16:09:43 -0500490
491 // TODO(jmadill): Use pool allocation so we don't need to deallocate command graph.
Jamie Madill6c7ab7f2018-03-31 14:19:15 -0400492 for (CommandGraphNode *node : mNodes)
Jamie Madill1f46bc12018-02-20 16:09:43 -0500493 {
494 delete node;
495 }
496 mNodes.clear();
497
Jamie Madill21061022018-07-12 23:56:30 -0400498 return angle::Result::Continue();
Jamie Madill1f46bc12018-02-20 16:09:43 -0500499}
500
501bool CommandGraph::empty() const
502{
503 return mNodes.empty();
504}
505
506} // namespace vk
507} // namespace rx