blob: b9c451788e76947707ba65db8652794c6bc9738e [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 Madilla5e06072018-05-18 14:36:05 -040055class CommandGraphNode final : angle::NonCopyable
56{
57 public:
58 CommandGraphNode();
59 ~CommandGraphNode();
60
61 // Immutable queries for when we're walking the commands tree.
62 CommandBuffer *getOutsideRenderPassCommands();
63 CommandBuffer *getInsideRenderPassCommands();
64
65 // For outside the render pass (copies, transitions, etc).
Jamie Madill21061022018-07-12 23:56:30 -040066 angle::Result beginOutsideRenderPassRecording(Context *context,
67 const CommandPool &commandPool,
68 CommandBuffer **commandsOut);
Jamie Madilla5e06072018-05-18 14:36:05 -040069
70 // For rendering commands (draws).
Jamie Madill21061022018-07-12 23:56:30 -040071 angle::Result beginInsideRenderPassRecording(Context *context, CommandBuffer **commandsOut);
Jamie Madilla5e06072018-05-18 14:36:05 -040072
73 // storeRenderPassInfo and append*RenderTarget store info relevant to the RenderPass.
74 void storeRenderPassInfo(const Framebuffer &framebuffer,
75 const gl::Rectangle renderArea,
76 const vk::RenderPassDesc &renderPassDesc,
77 const std::vector<VkClearValue> &clearValues);
78
79 // Dependency commands order node execution in the command graph.
80 // Once a node has commands that must happen after it, recording is stopped and the node is
81 // frozen forever.
82 static void SetHappensBeforeDependency(CommandGraphNode *beforeNode,
83 CommandGraphNode *afterNode);
84 static void SetHappensBeforeDependencies(const std::vector<CommandGraphNode *> &beforeNodes,
85 CommandGraphNode *afterNode);
86 bool hasParents() const;
87 bool hasChildren() const;
88
89 // Commands for traversing the node on a flush operation.
90 VisitedState visitedState() const;
91 void visitParents(std::vector<CommandGraphNode *> *stack);
Jamie Madill21061022018-07-12 23:56:30 -040092 angle::Result visitAndExecute(Context *context,
93 Serial serial,
94 RenderPassCache *renderPassCache,
95 CommandBuffer *primaryCommandBuffer);
Jamie Madilla5e06072018-05-18 14:36:05 -040096
97 const gl::Rectangle &getRenderPassRenderArea() const;
98
99 private:
100 void setHasChildren();
101
102 // Used for testing only.
103 bool isChildOf(CommandGraphNode *parent);
104
105 // Only used if we need a RenderPass for these commands.
106 RenderPassDesc mRenderPassDesc;
107 Framebuffer mRenderPassFramebuffer;
108 gl::Rectangle mRenderPassRenderArea;
109 gl::AttachmentArray<VkClearValue> mRenderPassClearValues;
110
111 // Keep a separate buffers for commands inside and outside a RenderPass.
112 // TODO(jmadill): We might not need inside and outside RenderPass commands separate.
113 CommandBuffer mOutsideRenderPassCommands;
114 CommandBuffer mInsideRenderPassCommands;
115
116 // Parents are commands that must be submitted before 'this' CommandNode can be submitted.
117 std::vector<CommandGraphNode *> mParents;
118
119 // If this is true, other commands exist that must be submitted after 'this' command.
120 bool mHasChildren;
121
122 // Used when traversing the dependency graph.
123 VisitedState mVisitedState;
124};
125
Jamie Madill6c7ab7f2018-03-31 14:19:15 -0400126// CommandGraphResource implementation.
127CommandGraphResource::CommandGraphResource() : mCurrentWritingNode(nullptr)
128{
129}
130
Jamie Madill316c6062018-05-29 10:49:45 -0400131CommandGraphResource::~CommandGraphResource() = default;
Jamie Madill6c7ab7f2018-03-31 14:19:15 -0400132
133void CommandGraphResource::updateQueueSerial(Serial queueSerial)
134{
135 ASSERT(queueSerial >= mStoredQueueSerial);
136
137 if (queueSerial > mStoredQueueSerial)
138 {
139 mCurrentWritingNode = nullptr;
140 mCurrentReadingNodes.clear();
141 mStoredQueueSerial = queueSerial;
142 }
143}
144
Jamie Madillc57ee252018-05-30 19:53:48 -0400145bool CommandGraphResource::isResourceInUse(RendererVk *renderer) const
146{
147 return renderer->isSerialInUse(mStoredQueueSerial);
148}
149
150Serial CommandGraphResource::getStoredQueueSerial() const
Jamie Madill6c7ab7f2018-03-31 14:19:15 -0400151{
152 return mStoredQueueSerial;
153}
154
Jamie Madill9cceac42018-03-31 14:19:16 -0400155bool CommandGraphResource::hasChildlessWritingNode() const
Jamie Madill6c7ab7f2018-03-31 14:19:15 -0400156{
Jamie Madill9cceac42018-03-31 14:19:16 -0400157 return (mCurrentWritingNode != nullptr && !mCurrentWritingNode->hasChildren());
Jamie Madill6c7ab7f2018-03-31 14:19:15 -0400158}
159
Jamie Madill316c6062018-05-29 10:49:45 -0400160bool CommandGraphResource::hasStartedWriteResource() const
161{
162 return hasChildlessWritingNode() &&
163 mCurrentWritingNode->getOutsideRenderPassCommands()->valid();
164}
165
Jamie Madill21061022018-07-12 23:56:30 -0400166angle::Result CommandGraphResource::beginWriteResource(Context *context,
167 CommandBuffer **commandBufferOut)
Jamie Madill6c7ab7f2018-03-31 14:19:15 -0400168{
Jamie Madill21061022018-07-12 23:56:30 -0400169 onResourceChanged(context->getRenderer());
170 return mCurrentWritingNode->beginOutsideRenderPassRecording(
171 context, context->getRenderer()->getCommandPool(), commandBufferOut);
Jamie Madill6c7ab7f2018-03-31 14:19:15 -0400172}
173
Jamie Madill21061022018-07-12 23:56:30 -0400174angle::Result CommandGraphResource::appendWriteResource(Context *context,
175 CommandBuffer **commandBufferOut)
Jamie Madill6c7ab7f2018-03-31 14:19:15 -0400176{
Jamie Madill21061022018-07-12 23:56:30 -0400177 updateQueueSerial(context->getRenderer()->getCurrentQueueSerial());
Jamie Madill5dca6512018-05-30 10:53:51 -0400178
Jamie Madill316c6062018-05-29 10:49:45 -0400179 if (!hasChildlessWritingNode())
180 {
Jamie Madill21061022018-07-12 23:56:30 -0400181 return beginWriteResource(context, commandBufferOut);
Jamie Madill316c6062018-05-29 10:49:45 -0400182 }
183
184 CommandBuffer *outsideRenderPassCommands = mCurrentWritingNode->getOutsideRenderPassCommands();
185 if (!outsideRenderPassCommands->valid())
186 {
187 ANGLE_TRY(mCurrentWritingNode->beginOutsideRenderPassRecording(
Jamie Madill21061022018-07-12 23:56:30 -0400188 context, context->getRenderer()->getCommandPool(), commandBufferOut));
Jamie Madill316c6062018-05-29 10:49:45 -0400189 }
190 else
191 {
192 *commandBufferOut = outsideRenderPassCommands;
193 }
194
Jamie Madill21061022018-07-12 23:56:30 -0400195 return angle::Result::Continue();
Jamie Madill316c6062018-05-29 10:49:45 -0400196}
197
Jamie Madill5dca6512018-05-30 10:53:51 -0400198bool CommandGraphResource::appendToStartedRenderPass(RendererVk *renderer,
199 CommandBuffer **commandBufferOut)
Jamie Madill316c6062018-05-29 10:49:45 -0400200{
Jamie Madill5dca6512018-05-30 10:53:51 -0400201 updateQueueSerial(renderer->getCurrentQueueSerial());
202 if (hasStartedRenderPass())
203 {
204 *commandBufferOut = mCurrentWritingNode->getInsideRenderPassCommands();
205 return true;
206 }
207 else
208 {
209 return false;
210 }
Jamie Madill316c6062018-05-29 10:49:45 -0400211}
212
213bool CommandGraphResource::hasStartedRenderPass() const
214{
215 return hasChildlessWritingNode() && mCurrentWritingNode->getInsideRenderPassCommands()->valid();
216}
217
218const gl::Rectangle &CommandGraphResource::getRenderPassRenderArea() const
219{
220 ASSERT(hasStartedRenderPass());
221 return mCurrentWritingNode->getRenderPassRenderArea();
222}
223
Jamie Madill21061022018-07-12 23:56:30 -0400224angle::Result CommandGraphResource::beginRenderPass(Context *context,
225 const Framebuffer &framebuffer,
226 const gl::Rectangle &renderArea,
227 const RenderPassDesc &renderPassDesc,
228 const std::vector<VkClearValue> &clearValues,
229 CommandBuffer **commandBufferOut) const
Jamie Madill316c6062018-05-29 10:49:45 -0400230{
231 // Hard-code RenderPass to clear the first render target to the current clear value.
232 // TODO(jmadill): Proper clear value implementation. http://anglebug.com/2361
233 mCurrentWritingNode->storeRenderPassInfo(framebuffer, renderArea, renderPassDesc, clearValues);
234
Jamie Madill21061022018-07-12 23:56:30 -0400235 return mCurrentWritingNode->beginInsideRenderPassRecording(context, commandBufferOut);
Jamie Madill316c6062018-05-29 10:49:45 -0400236}
237
238void CommandGraphResource::onResourceChanged(RendererVk *renderer)
239{
Jamie Madill86ce2102018-05-22 11:54:42 -0400240 CommandGraphNode *newCommands = renderer->getCommandGraph()->allocateNode();
241 onWriteImpl(newCommands, renderer->getCurrentQueueSerial());
Jamie Madill316c6062018-05-29 10:49:45 -0400242}
243
244void CommandGraphResource::addWriteDependency(CommandGraphResource *writingResource)
245{
246 CommandGraphNode *writingNode = writingResource->mCurrentWritingNode;
247 ASSERT(writingNode);
248
Jamie Madillc57ee252018-05-30 19:53:48 -0400249 onWriteImpl(writingNode, writingResource->getStoredQueueSerial());
Jamie Madill316c6062018-05-29 10:49:45 -0400250}
251
252void CommandGraphResource::onWriteImpl(CommandGraphNode *writingNode, Serial currentSerial)
253{
254 updateQueueSerial(currentSerial);
Jamie Madill6c7ab7f2018-03-31 14:19:15 -0400255
Jamie Madill9cceac42018-03-31 14:19:16 -0400256 // Make sure any open reads and writes finish before we execute 'writingNode'.
Jamie Madill6c7ab7f2018-03-31 14:19:15 -0400257 if (!mCurrentReadingNodes.empty())
258 {
259 CommandGraphNode::SetHappensBeforeDependencies(mCurrentReadingNodes, writingNode);
260 mCurrentReadingNodes.clear();
261 }
262
263 if (mCurrentWritingNode && mCurrentWritingNode != writingNode)
264 {
265 CommandGraphNode::SetHappensBeforeDependency(mCurrentWritingNode, writingNode);
266 }
267
268 mCurrentWritingNode = writingNode;
269}
270
Jamie Madill316c6062018-05-29 10:49:45 -0400271void CommandGraphResource::addReadDependency(CommandGraphResource *readingResource)
Jamie Madill6c7ab7f2018-03-31 14:19:15 -0400272{
Jamie Madillc57ee252018-05-30 19:53:48 -0400273 updateQueueSerial(readingResource->getStoredQueueSerial());
Jamie Madill316c6062018-05-29 10:49:45 -0400274
275 CommandGraphNode *readingNode = readingResource->mCurrentWritingNode;
276 ASSERT(readingNode);
Jamie Madill9cceac42018-03-31 14:19:16 -0400277
278 if (hasChildlessWritingNode())
Jamie Madill6c7ab7f2018-03-31 14:19:15 -0400279 {
Jamie Madill9cceac42018-03-31 14:19:16 -0400280 // Ensure 'readingNode' happens after the current writing node.
281 CommandGraphNode::SetHappensBeforeDependency(mCurrentWritingNode, readingNode);
282 }
283
284 // Add the read node to the list of nodes currently reading this resource.
285 mCurrentReadingNodes.push_back(readingNode);
286}
287
Jamie Madill1f46bc12018-02-20 16:09:43 -0500288// CommandGraphNode implementation.
Jamie Madill316c6062018-05-29 10:49:45 -0400289CommandGraphNode::CommandGraphNode()
290 : mRenderPassClearValues{}, mHasChildren(false), mVisitedState(VisitedState::Unvisited)
Jamie Madill1f46bc12018-02-20 16:09:43 -0500291{
292}
293
294CommandGraphNode::~CommandGraphNode()
295{
296 mRenderPassFramebuffer.setHandle(VK_NULL_HANDLE);
297
298 // Command buffers are managed by the command pool, so don't need to be freed.
299 mOutsideRenderPassCommands.releaseHandle();
300 mInsideRenderPassCommands.releaseHandle();
301}
302
303CommandBuffer *CommandGraphNode::getOutsideRenderPassCommands()
304{
305 ASSERT(!mHasChildren);
306 return &mOutsideRenderPassCommands;
307}
308
309CommandBuffer *CommandGraphNode::getInsideRenderPassCommands()
310{
311 ASSERT(!mHasChildren);
312 return &mInsideRenderPassCommands;
313}
314
Jamie Madill21061022018-07-12 23:56:30 -0400315angle::Result CommandGraphNode::beginOutsideRenderPassRecording(Context *context,
316 const CommandPool &commandPool,
317 CommandBuffer **commandsOut)
Jamie Madill1f46bc12018-02-20 16:09:43 -0500318{
319 ASSERT(!mHasChildren);
320
321 VkCommandBufferInheritanceInfo inheritanceInfo;
322 inheritanceInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
323 inheritanceInfo.pNext = nullptr;
324 inheritanceInfo.renderPass = VK_NULL_HANDLE;
325 inheritanceInfo.subpass = 0;
326 inheritanceInfo.framebuffer = VK_NULL_HANDLE;
327 inheritanceInfo.occlusionQueryEnable = VK_FALSE;
328 inheritanceInfo.queryFlags = 0;
329 inheritanceInfo.pipelineStatistics = 0;
330
Jamie Madill21061022018-07-12 23:56:30 -0400331 ANGLE_TRY(InitAndBeginCommandBuffer(context, commandPool, inheritanceInfo, 0,
Jamie Madill1f46bc12018-02-20 16:09:43 -0500332 &mOutsideRenderPassCommands));
333
334 *commandsOut = &mOutsideRenderPassCommands;
Jamie Madill21061022018-07-12 23:56:30 -0400335 return angle::Result::Continue();
Jamie Madill1f46bc12018-02-20 16:09:43 -0500336}
337
Jamie Madill21061022018-07-12 23:56:30 -0400338angle::Result CommandGraphNode::beginInsideRenderPassRecording(Context *context,
339 CommandBuffer **commandsOut)
Jamie Madill1f46bc12018-02-20 16:09:43 -0500340{
341 ASSERT(!mHasChildren);
342
343 // Get a compatible RenderPass from the cache so we can initialize the inheritance info.
344 // TODO(jmadill): Support query for compatible/conformant render pass. htto://anglebug.com/2361
345 RenderPass *compatibleRenderPass;
Jamie Madill21061022018-07-12 23:56:30 -0400346 ANGLE_TRY(context->getRenderer()->getCompatibleRenderPass(context, mRenderPassDesc,
347 &compatibleRenderPass));
Jamie Madill1f46bc12018-02-20 16:09:43 -0500348
349 VkCommandBufferInheritanceInfo inheritanceInfo;
350 inheritanceInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
351 inheritanceInfo.pNext = nullptr;
352 inheritanceInfo.renderPass = compatibleRenderPass->getHandle();
353 inheritanceInfo.subpass = 0;
354 inheritanceInfo.framebuffer = mRenderPassFramebuffer.getHandle();
355 inheritanceInfo.occlusionQueryEnable = VK_FALSE;
356 inheritanceInfo.queryFlags = 0;
357 inheritanceInfo.pipelineStatistics = 0;
358
359 ANGLE_TRY(InitAndBeginCommandBuffer(
Jamie Madill21061022018-07-12 23:56:30 -0400360 context, context->getRenderer()->getCommandPool(), inheritanceInfo,
Jamie Madill1f46bc12018-02-20 16:09:43 -0500361 VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, &mInsideRenderPassCommands));
362
363 *commandsOut = &mInsideRenderPassCommands;
Jamie Madill21061022018-07-12 23:56:30 -0400364 return angle::Result::Continue();
Jamie Madill1f46bc12018-02-20 16:09:43 -0500365}
366
367void CommandGraphNode::storeRenderPassInfo(const Framebuffer &framebuffer,
368 const gl::Rectangle renderArea,
Jamie Madillbcf467f2018-05-23 09:46:00 -0400369 const vk::RenderPassDesc &renderPassDesc,
Jamie Madill1f46bc12018-02-20 16:09:43 -0500370 const std::vector<VkClearValue> &clearValues)
371{
Jamie Madillbcf467f2018-05-23 09:46:00 -0400372 mRenderPassDesc = renderPassDesc;
Jamie Madill1f46bc12018-02-20 16:09:43 -0500373 mRenderPassFramebuffer.setHandle(framebuffer.getHandle());
374 mRenderPassRenderArea = renderArea;
375 std::copy(clearValues.begin(), clearValues.end(), mRenderPassClearValues.begin());
376}
377
Jamie Madill1f46bc12018-02-20 16:09:43 -0500378// static
379void CommandGraphNode::SetHappensBeforeDependency(CommandGraphNode *beforeNode,
380 CommandGraphNode *afterNode)
381{
Jamie Madill9cceac42018-03-31 14:19:16 -0400382 ASSERT(beforeNode != afterNode && !beforeNode->isChildOf(afterNode));
Jamie Madill1f46bc12018-02-20 16:09:43 -0500383 afterNode->mParents.emplace_back(beforeNode);
384 beforeNode->setHasChildren();
Jamie Madill1f46bc12018-02-20 16:09:43 -0500385}
386
387// static
388void CommandGraphNode::SetHappensBeforeDependencies(
389 const std::vector<CommandGraphNode *> &beforeNodes,
390 CommandGraphNode *afterNode)
391{
392 afterNode->mParents.insert(afterNode->mParents.end(), beforeNodes.begin(), beforeNodes.end());
393
394 // TODO(jmadill): is there a faster way to do this?
395 for (CommandGraphNode *beforeNode : beforeNodes)
396 {
397 beforeNode->setHasChildren();
398
399 ASSERT(beforeNode != afterNode && !beforeNode->isChildOf(afterNode));
400 }
401}
402
403bool CommandGraphNode::hasParents() const
404{
405 return !mParents.empty();
406}
407
408void CommandGraphNode::setHasChildren()
409{
410 mHasChildren = true;
411}
412
413bool CommandGraphNode::hasChildren() const
414{
415 return mHasChildren;
416}
417
418// Do not call this in anything but testing code, since it's slow.
419bool CommandGraphNode::isChildOf(CommandGraphNode *parent)
420{
421 std::set<CommandGraphNode *> visitedList;
422 std::vector<CommandGraphNode *> openList;
423 openList.insert(openList.begin(), mParents.begin(), mParents.end());
424 while (!openList.empty())
425 {
426 CommandGraphNode *current = openList.back();
427 openList.pop_back();
428 if (visitedList.count(current) == 0)
429 {
430 if (current == parent)
431 {
432 return true;
433 }
434 visitedList.insert(current);
435 openList.insert(openList.end(), current->mParents.begin(), current->mParents.end());
436 }
437 }
438
439 return false;
440}
441
442VisitedState CommandGraphNode::visitedState() const
443{
444 return mVisitedState;
445}
446
447void CommandGraphNode::visitParents(std::vector<CommandGraphNode *> *stack)
448{
449 ASSERT(mVisitedState == VisitedState::Unvisited);
450 stack->insert(stack->end(), mParents.begin(), mParents.end());
451 mVisitedState = VisitedState::Ready;
452}
453
Jamie Madill21061022018-07-12 23:56:30 -0400454angle::Result CommandGraphNode::visitAndExecute(vk::Context *context,
455 Serial serial,
456 RenderPassCache *renderPassCache,
457 CommandBuffer *primaryCommandBuffer)
Jamie Madill1f46bc12018-02-20 16:09:43 -0500458{
459 if (mOutsideRenderPassCommands.valid())
460 {
Jamie Madill21061022018-07-12 23:56:30 -0400461 ANGLE_TRY(mOutsideRenderPassCommands.end(context));
Jamie Madill1f46bc12018-02-20 16:09:43 -0500462 primaryCommandBuffer->executeCommands(1, &mOutsideRenderPassCommands);
463 }
464
465 if (mInsideRenderPassCommands.valid())
466 {
467 // Pull a compatible RenderPass from the cache.
468 // TODO(jmadill): Insert real ops and layout transitions.
469 RenderPass *renderPass = nullptr;
Jamie Madill21061022018-07-12 23:56:30 -0400470 ANGLE_TRY(renderPassCache->getCompatibleRenderPass(context, serial, mRenderPassDesc,
471 &renderPass));
Jamie Madill1f46bc12018-02-20 16:09:43 -0500472
Jamie Madill21061022018-07-12 23:56:30 -0400473 ANGLE_TRY(mInsideRenderPassCommands.end(context));
Jamie Madill1f46bc12018-02-20 16:09:43 -0500474
475 VkRenderPassBeginInfo beginInfo;
476 beginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
477 beginInfo.pNext = nullptr;
478 beginInfo.renderPass = renderPass->getHandle();
479 beginInfo.framebuffer = mRenderPassFramebuffer.getHandle();
480 beginInfo.renderArea.offset.x = static_cast<uint32_t>(mRenderPassRenderArea.x);
481 beginInfo.renderArea.offset.y = static_cast<uint32_t>(mRenderPassRenderArea.y);
482 beginInfo.renderArea.extent.width = static_cast<uint32_t>(mRenderPassRenderArea.width);
483 beginInfo.renderArea.extent.height = static_cast<uint32_t>(mRenderPassRenderArea.height);
484 beginInfo.clearValueCount = mRenderPassDesc.attachmentCount();
485 beginInfo.pClearValues = mRenderPassClearValues.data();
486
487 primaryCommandBuffer->beginRenderPass(beginInfo,
488 VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
489 primaryCommandBuffer->executeCommands(1, &mInsideRenderPassCommands);
490 primaryCommandBuffer->endRenderPass();
491 }
492
493 mVisitedState = VisitedState::Visited;
Jamie Madill21061022018-07-12 23:56:30 -0400494 return angle::Result::Continue();
Jamie Madill1f46bc12018-02-20 16:09:43 -0500495}
496
Luc Ferron14f48172018-04-11 08:43:28 -0400497const gl::Rectangle &CommandGraphNode::getRenderPassRenderArea() const
498{
499 return mRenderPassRenderArea;
500}
501
Jamie Madill1f46bc12018-02-20 16:09:43 -0500502// CommandGraph implementation.
Jamie Madill316c6062018-05-29 10:49:45 -0400503CommandGraph::CommandGraph() = default;
Jamie Madill1f46bc12018-02-20 16:09:43 -0500504
505CommandGraph::~CommandGraph()
506{
507 ASSERT(empty());
508}
509
510CommandGraphNode *CommandGraph::allocateNode()
511{
512 // TODO(jmadill): Use a pool allocator for the CPU node allocations.
513 CommandGraphNode *newCommands = new CommandGraphNode();
514 mNodes.emplace_back(newCommands);
515 return newCommands;
516}
517
Jamie Madill21061022018-07-12 23:56:30 -0400518angle::Result CommandGraph::submitCommands(Context *context,
519 Serial serial,
520 RenderPassCache *renderPassCache,
521 CommandPool *commandPool,
522 CommandBuffer *primaryCommandBufferOut)
Jamie Madill1f46bc12018-02-20 16:09:43 -0500523{
524 VkCommandBufferAllocateInfo primaryInfo;
525 primaryInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
526 primaryInfo.pNext = nullptr;
527 primaryInfo.commandPool = commandPool->getHandle();
528 primaryInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
529 primaryInfo.commandBufferCount = 1;
530
Jamie Madill21061022018-07-12 23:56:30 -0400531 ANGLE_TRY(primaryCommandBufferOut->init(context, primaryInfo));
Jamie Madill1f46bc12018-02-20 16:09:43 -0500532
533 if (mNodes.empty())
534 {
Jamie Madill21061022018-07-12 23:56:30 -0400535 return angle::Result::Continue();
Jamie Madill1f46bc12018-02-20 16:09:43 -0500536 }
537
538 std::vector<CommandGraphNode *> nodeStack;
539
540 VkCommandBufferBeginInfo beginInfo;
541 beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
542 beginInfo.pNext = nullptr;
543 beginInfo.flags = 0;
544 beginInfo.pInheritanceInfo = nullptr;
545
Jamie Madill21061022018-07-12 23:56:30 -0400546 ANGLE_TRY(primaryCommandBufferOut->begin(context, beginInfo));
Jamie Madill1f46bc12018-02-20 16:09:43 -0500547
548 for (CommandGraphNode *topLevelNode : mNodes)
549 {
550 // Only process commands that don't have child commands. The others will be pulled in
551 // automatically. Also skip commands that have already been visited.
552 if (topLevelNode->hasChildren() || topLevelNode->visitedState() != VisitedState::Unvisited)
553 continue;
554
555 nodeStack.push_back(topLevelNode);
556
557 while (!nodeStack.empty())
558 {
559 CommandGraphNode *node = nodeStack.back();
560
561 switch (node->visitedState())
562 {
563 case VisitedState::Unvisited:
564 node->visitParents(&nodeStack);
565 break;
566 case VisitedState::Ready:
Jamie Madill21061022018-07-12 23:56:30 -0400567 ANGLE_TRY(node->visitAndExecute(context, serial, renderPassCache,
Jamie Madill1f46bc12018-02-20 16:09:43 -0500568 primaryCommandBufferOut));
569 nodeStack.pop_back();
570 break;
571 case VisitedState::Visited:
572 nodeStack.pop_back();
573 break;
574 default:
575 UNREACHABLE();
576 break;
577 }
578 }
579 }
580
Jamie Madill21061022018-07-12 23:56:30 -0400581 ANGLE_TRY(primaryCommandBufferOut->end(context));
Jamie Madill1f46bc12018-02-20 16:09:43 -0500582
583 // TODO(jmadill): Use pool allocation so we don't need to deallocate command graph.
Jamie Madill6c7ab7f2018-03-31 14:19:15 -0400584 for (CommandGraphNode *node : mNodes)
Jamie Madill1f46bc12018-02-20 16:09:43 -0500585 {
586 delete node;
587 }
588 mNodes.clear();
589
Jamie Madill21061022018-07-12 23:56:30 -0400590 return angle::Result::Continue();
Jamie Madill1f46bc12018-02-20 16:09:43 -0500591}
592
593bool CommandGraph::empty() const
594{
595 return mNodes.empty();
596}
597
598} // namespace vk
599} // namespace rx