blob: 136eafd6a183f3da3745bd81064f98a29236fb82 [file] [log] [blame]
Alexis Hetu767b41b2018-09-26 11:25:46 -04001// Copyright 2018 The SwiftShader Authors. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
Ben Clayton2ed93ab2019-12-17 20:38:03 +000015#include "VkQueue.hpp"
Alexis Hetu072dc0d2018-10-31 11:41:25 -040016#include "VkCommandBuffer.hpp"
Alexis Hetuc4bd9df2018-12-07 11:28:40 -050017#include "VkFence.hpp"
Alexis Hetu072dc0d2018-10-31 11:41:25 -040018#include "VkSemaphore.hpp"
Chris Forbesab1e2b42019-05-11 10:28:37 -070019#include "Device/Renderer.hpp"
Ben Clayton2ed93ab2019-12-17 20:38:03 +000020#include "WSI/VkSwapchainKHR.hpp"
Alexis Hetu767b41b2018-09-26 11:25:46 -040021
Ben Claytone693b622019-09-05 12:48:37 +010022#include "marl/defer.h"
23#include "marl/scheduler.h"
24#include "marl/thread.h"
25#include "marl/trace.h"
Ben Claytond6c61362019-08-14 18:16:01 +010026
Alexis Hetue1f51b92019-04-23 15:34:34 -040027#include <cstring>
28
Nicolas Capens157ba262019-12-10 17:49:14 -050029namespace {
Alexis Hetue1f51b92019-04-23 15:34:34 -040030
Ben Clayton2ed93ab2019-12-17 20:38:03 +000031VkSubmitInfo *DeepCopySubmitInfo(uint32_t submitCount, const VkSubmitInfo *pSubmits)
Alexis Hetue1f51b92019-04-23 15:34:34 -040032{
33 size_t submitSize = sizeof(VkSubmitInfo) * submitCount;
34 size_t totalSize = submitSize;
35 for(uint32_t i = 0; i < submitCount; i++)
36 {
37 totalSize += pSubmits[i].waitSemaphoreCount * sizeof(VkSemaphore);
38 totalSize += pSubmits[i].waitSemaphoreCount * sizeof(VkPipelineStageFlags);
39 totalSize += pSubmits[i].signalSemaphoreCount * sizeof(VkSemaphore);
40 totalSize += pSubmits[i].commandBufferCount * sizeof(VkCommandBuffer);
41 }
42
Ben Clayton2ed93ab2019-12-17 20:38:03 +000043 uint8_t *mem = static_cast<uint8_t *>(
44 vk::allocate(totalSize, vk::REQUIRED_MEMORY_ALIGNMENT, vk::DEVICE_MEMORY, vk::Fence::GetAllocationScope()));
Alexis Hetue1f51b92019-04-23 15:34:34 -040045
Ben Clayton2ed93ab2019-12-17 20:38:03 +000046 auto submits = new(mem) VkSubmitInfo[submitCount];
Alexis Hetue1f51b92019-04-23 15:34:34 -040047 memcpy(mem, pSubmits, submitSize);
48 mem += submitSize;
49
50 for(uint32_t i = 0; i < submitCount; i++)
51 {
52 size_t size = pSubmits[i].waitSemaphoreCount * sizeof(VkSemaphore);
Ben Clayton2ed93ab2019-12-17 20:38:03 +000053 submits[i].pWaitSemaphores = reinterpret_cast<const VkSemaphore *>(mem);
Alexis Hetue1f51b92019-04-23 15:34:34 -040054 memcpy(mem, pSubmits[i].pWaitSemaphores, size);
55 mem += size;
56
57 size = pSubmits[i].waitSemaphoreCount * sizeof(VkPipelineStageFlags);
Ben Clayton2ed93ab2019-12-17 20:38:03 +000058 submits[i].pWaitDstStageMask = reinterpret_cast<const VkPipelineStageFlags *>(mem);
Alexis Hetue1f51b92019-04-23 15:34:34 -040059 memcpy(mem, pSubmits[i].pWaitDstStageMask, size);
60 mem += size;
61
62 size = pSubmits[i].signalSemaphoreCount * sizeof(VkSemaphore);
Ben Clayton2ed93ab2019-12-17 20:38:03 +000063 submits[i].pSignalSemaphores = reinterpret_cast<const VkSemaphore *>(mem);
Alexis Hetue1f51b92019-04-23 15:34:34 -040064 memcpy(mem, pSubmits[i].pSignalSemaphores, size);
65 mem += size;
66
67 size = pSubmits[i].commandBufferCount * sizeof(VkCommandBuffer);
Ben Clayton2ed93ab2019-12-17 20:38:03 +000068 submits[i].pCommandBuffers = reinterpret_cast<const VkCommandBuffer *>(mem);
Alexis Hetue1f51b92019-04-23 15:34:34 -040069 memcpy(mem, pSubmits[i].pCommandBuffers, size);
70 mem += size;
71 }
72
73 return submits;
74}
75
Nicolas Capens157ba262019-12-10 17:49:14 -050076} // anonymous namespace
Alexis Hetue1f51b92019-04-23 15:34:34 -040077
Nicolas Capens157ba262019-12-10 17:49:14 -050078namespace vk {
Alexis Hetu767b41b2018-09-26 11:25:46 -040079
Ben Clayton2ed93ab2019-12-17 20:38:03 +000080Queue::Queue(Device *device, marl::Scheduler *scheduler)
81 : device(device)
Alexis Hetu767b41b2018-09-26 11:25:46 -040082{
Ben Claytond6c61362019-08-14 18:16:01 +010083 queueThread = std::thread(&Queue::taskLoop, this, scheduler);
Alexis Hetuaf3c1022018-12-12 13:26:15 -050084}
85
Ben Clayton7e0a0362019-05-20 11:32:35 +010086Queue::~Queue()
Alexis Hetuaf3c1022018-12-12 13:26:15 -050087{
Alexis Hetue1f51b92019-04-23 15:34:34 -040088 Task task;
89 task.type = Task::KILL_THREAD;
90 pending.put(task);
91
92 queueThread.join();
93 ASSERT_MSG(pending.count() == 0, "queue has work after worker thread shutdown");
94
95 garbageCollect();
Alexis Hetu767b41b2018-09-26 11:25:46 -040096}
97
Ben Clayton2ed93ab2019-12-17 20:38:03 +000098VkResult Queue::submit(uint32_t submitCount, const VkSubmitInfo *pSubmits, Fence *fence)
Alexis Hetu072dc0d2018-10-31 11:41:25 -040099{
Alexis Hetue1f51b92019-04-23 15:34:34 -0400100 garbageCollect();
101
102 Task task;
103 task.submitCount = submitCount;
104 task.pSubmits = DeepCopySubmitInfo(submitCount, pSubmits);
Alexis Hetu7d96f512019-06-13 18:23:56 -0400105 task.events = fence;
Alexis Hetue1f51b92019-04-23 15:34:34 -0400106
Ben Claytonbd0ab1b2019-05-20 11:20:28 +0100107 if(task.events)
Alexis Hetu072dc0d2018-10-31 11:41:25 -0400108 {
Ben Claytonbd0ab1b2019-05-20 11:20:28 +0100109 task.events->start();
Alexis Hetue1f51b92019-04-23 15:34:34 -0400110 }
111
112 pending.put(task);
113
114 return VK_SUCCESS;
115}
116
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000117void Queue::submitQueue(const Task &task)
Alexis Hetue1f51b92019-04-23 15:34:34 -0400118{
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500119 if(renderer == nullptr)
Ben Clayton1943a292019-07-20 14:42:58 +0100120 {
121 renderer.reset(new sw::Renderer(device));
122 }
123
Alexis Hetue1f51b92019-04-23 15:34:34 -0400124 for(uint32_t i = 0; i < task.submitCount; i++)
125 {
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000126 auto &submitInfo = task.pSubmits[i];
Alexis Hetu072dc0d2018-10-31 11:41:25 -0400127 for(uint32_t j = 0; j < submitInfo.waitSemaphoreCount; j++)
128 {
129 vk::Cast(submitInfo.pWaitSemaphores[j])->wait(submitInfo.pWaitDstStageMask[j]);
130 }
131
Alexis Hetu072dc0d2018-10-31 11:41:25 -0400132 {
Alexis Hetu9bc7a812018-12-07 16:13:34 -0500133 CommandBuffer::ExecutionState executionState;
Ben Clayton1943a292019-07-20 14:42:58 +0100134 executionState.renderer = renderer.get();
Ben Claytonbd0ab1b2019-05-20 11:20:28 +0100135 executionState.events = task.events;
Alexis Hetu9bc7a812018-12-07 16:13:34 -0500136 for(uint32_t j = 0; j < submitInfo.commandBufferCount; j++)
137 {
138 vk::Cast(submitInfo.pCommandBuffers[j])->submit(executionState);
139 }
Alexis Hetu072dc0d2018-10-31 11:41:25 -0400140 }
141
142 for(uint32_t j = 0; j < submitInfo.signalSemaphoreCount; j++)
143 {
144 vk::Cast(submitInfo.pSignalSemaphores[j])->signal();
145 }
146 }
Alexis Hetuc4bd9df2018-12-07 11:28:40 -0500147
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500148 if(task.pSubmits)
Alexis Hetuc4bd9df2018-12-07 11:28:40 -0500149 {
Alexis Hetue1f51b92019-04-23 15:34:34 -0400150 toDelete.put(task.pSubmits);
151 }
152
Ben Claytonbd0ab1b2019-05-20 11:20:28 +0100153 if(task.events)
Alexis Hetue1f51b92019-04-23 15:34:34 -0400154 {
Chris Forbesab1e2b42019-05-11 10:28:37 -0700155 // TODO: fix renderer signaling so that work submitted separately from (but before) a fence
156 // is guaranteed complete by the time the fence signals.
Ben Clayton1943a292019-07-20 14:42:58 +0100157 renderer->synchronize();
Ben Claytonbd0ab1b2019-05-20 11:20:28 +0100158 task.events->finish();
Alexis Hetuc4bd9df2018-12-07 11:28:40 -0500159 }
Alexis Hetu072dc0d2018-10-31 11:41:25 -0400160}
161
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000162void Queue::taskLoop(marl::Scheduler *scheduler)
Hernan Liatis6b12a502019-03-01 15:06:13 -0800163{
Ben Claytone693b622019-09-05 12:48:37 +0100164 marl::Thread::setName("Queue<%p>", this);
Ben Claytond6c61362019-08-14 18:16:01 +0100165 scheduler->bind();
166 defer(scheduler->unbind());
167
Alexis Hetue1f51b92019-04-23 15:34:34 -0400168 while(true)
169 {
170 Task task = pending.take();
Hernan Liatis6b12a502019-03-01 15:06:13 -0800171
Alexis Hetue1f51b92019-04-23 15:34:34 -0400172 switch(task.type)
173 {
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000174 case Task::KILL_THREAD:
175 ASSERT_MSG(pending.count() == 0, "queue has remaining work!");
176 return;
177 case Task::SUBMIT_QUEUE:
178 submitQueue(task);
179 break;
180 default:
Nicolas Capens44bd43a2020-01-22 03:07:14 -0500181 UNREACHABLE("task.type %d", static_cast<int>(task.type));
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000182 break;
Alexis Hetue1f51b92019-04-23 15:34:34 -0400183 }
184 }
185}
Alexis Hetuf0aa9d52019-04-01 17:06:47 -0400186
Alexis Hetue1f51b92019-04-23 15:34:34 -0400187VkResult Queue::waitIdle()
188{
189 // Wait for task queue to flush.
Ben Clayton8546d4e2019-05-20 11:27:10 +0100190 sw::WaitGroup wg;
191 wg.add();
Alexis Hetue1f51b92019-04-23 15:34:34 -0400192
193 Task task;
Ben Clayton8546d4e2019-05-20 11:27:10 +0100194 task.events = &wg;
Alexis Hetue1f51b92019-04-23 15:34:34 -0400195 pending.put(task);
196
Ben Clayton8546d4e2019-05-20 11:27:10 +0100197 wg.wait();
Alexis Hetue1f51b92019-04-23 15:34:34 -0400198
Alexis Hetue1f51b92019-04-23 15:34:34 -0400199 garbageCollect();
200
201 return VK_SUCCESS;
202}
203
204void Queue::garbageCollect()
205{
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500206 while(true)
Alexis Hetue1f51b92019-04-23 15:34:34 -0400207 {
208 auto v = toDelete.tryTake();
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500209 if(!v.second) { break; }
Alexis Hetue1f51b92019-04-23 15:34:34 -0400210 vk::deallocate(v.first, DEVICE_MEMORY);
211 }
Hernan Liatis6b12a502019-03-01 15:06:13 -0800212}
213
Chris Forbes1d667d62019-04-05 08:25:18 -0700214#ifndef __ANDROID__
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000215VkResult Queue::present(const VkPresentInfoKHR *presentInfo)
Hernan Liatis6b12a502019-03-01 15:06:13 -0800216{
Hernan Liatisd61595f2019-05-10 16:30:07 -0700217 // This is a hack to deal with screen tearing for now.
218 // Need to correctly implement threading using VkSemaphore
219 // to get rid of it. b/132458423
220 waitIdle();
Nicolas Capens023b8642020-01-16 01:46:02 -0500221
Hernan Liatis914a46d2019-03-12 11:34:24 -0700222 for(uint32_t i = 0; i < presentInfo->waitSemaphoreCount; i++)
223 {
224 vk::Cast(presentInfo->pWaitSemaphores[i])->wait();
225 }
226
Nicolas Capens023b8642020-01-16 01:46:02 -0500227 VkResult commandResult = VK_SUCCESS;
228
Hernan Liatis6b12a502019-03-01 15:06:13 -0800229 for(uint32_t i = 0; i < presentInfo->swapchainCount; i++)
230 {
Nicolas Capens023b8642020-01-16 01:46:02 -0500231 VkResult perSwapchainResult = vk::Cast(presentInfo->pSwapchains[i])->present(presentInfo->pImageIndices[i]);
232
233 if(presentInfo->pResults)
AWoloszyna59e70e2019-11-18 16:23:25 -0500234 {
Nicolas Capens023b8642020-01-16 01:46:02 -0500235 presentInfo->pResults[i] = perSwapchainResult;
AWoloszyna59e70e2019-11-18 16:23:25 -0500236 }
Nicolas Capens023b8642020-01-16 01:46:02 -0500237
Nicolas Capens748ad202020-01-16 14:48:54 -0500238 // Keep track of the worst result code. VK_SUBOPTIMAL_KHR is a success code so it should
239 // not override failure codes, but should not get replaced by a VK_SUCCESS result itself.
Nicolas Capens023b8642020-01-16 01:46:02 -0500240 if(perSwapchainResult != VK_SUCCESS)
241 {
Nicolas Capens748ad202020-01-16 14:48:54 -0500242 if(commandResult == VK_SUCCESS || commandResult == VK_SUBOPTIMAL_KHR)
243 {
244 commandResult = perSwapchainResult;
245 }
Nicolas Capens023b8642020-01-16 01:46:02 -0500246 }
Hernan Liatis6b12a502019-03-01 15:06:13 -0800247 }
Antonio Maiorano26c6c4a2019-10-17 15:33:47 -0400248
Nicolas Capens023b8642020-01-16 01:46:02 -0500249 return commandResult;
Alexis Hetucda0cf92019-01-24 15:48:55 -0500250}
Chris Forbes1d667d62019-04-05 08:25:18 -0700251#endif
Alexis Hetucda0cf92019-01-24 15:48:55 -0500252
Nicolas Capens157ba262019-12-10 17:49:14 -0500253} // namespace vk