blob: fd8bc6d25b2dfc4e5251a8ed5520adeb60216bc6 [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);
Ben Claytonf2ab65b2020-11-20 15:12:27 +0000105 if(fence)
Alexis Hetu072dc0d2018-10-31 11:41:25 -0400106 {
Ben Claytonf2ab65b2020-11-20 15:12:27 +0000107 task.events = fence->getCountedEvent();
108 task.events->add();
Alexis Hetue1f51b92019-04-23 15:34:34 -0400109 }
110
111 pending.put(task);
112
113 return VK_SUCCESS;
114}
115
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000116void Queue::submitQueue(const Task &task)
Alexis Hetue1f51b92019-04-23 15:34:34 -0400117{
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500118 if(renderer == nullptr)
Ben Clayton1943a292019-07-20 14:42:58 +0100119 {
120 renderer.reset(new sw::Renderer(device));
121 }
122
Alexis Hetue1f51b92019-04-23 15:34:34 -0400123 for(uint32_t i = 0; i < task.submitCount; i++)
124 {
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000125 auto &submitInfo = task.pSubmits[i];
Alexis Hetu072dc0d2018-10-31 11:41:25 -0400126 for(uint32_t j = 0; j < submitInfo.waitSemaphoreCount; j++)
127 {
128 vk::Cast(submitInfo.pWaitSemaphores[j])->wait(submitInfo.pWaitDstStageMask[j]);
129 }
130
Alexis Hetu072dc0d2018-10-31 11:41:25 -0400131 {
Alexis Hetu9bc7a812018-12-07 16:13:34 -0500132 CommandBuffer::ExecutionState executionState;
Ben Clayton1943a292019-07-20 14:42:58 +0100133 executionState.renderer = renderer.get();
Ben Claytonf2ab65b2020-11-20 15:12:27 +0000134 executionState.events = task.events.get();
Alexis Hetu9bc7a812018-12-07 16:13:34 -0500135 for(uint32_t j = 0; j < submitInfo.commandBufferCount; j++)
136 {
137 vk::Cast(submitInfo.pCommandBuffers[j])->submit(executionState);
138 }
Alexis Hetu072dc0d2018-10-31 11:41:25 -0400139 }
140
141 for(uint32_t j = 0; j < submitInfo.signalSemaphoreCount; j++)
142 {
143 vk::Cast(submitInfo.pSignalSemaphores[j])->signal();
144 }
145 }
Alexis Hetuc4bd9df2018-12-07 11:28:40 -0500146
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500147 if(task.pSubmits)
Alexis Hetuc4bd9df2018-12-07 11:28:40 -0500148 {
Alexis Hetue1f51b92019-04-23 15:34:34 -0400149 toDelete.put(task.pSubmits);
150 }
151
Ben Claytonbd0ab1b2019-05-20 11:20:28 +0100152 if(task.events)
Alexis Hetue1f51b92019-04-23 15:34:34 -0400153 {
Chris Forbesab1e2b42019-05-11 10:28:37 -0700154 // TODO: fix renderer signaling so that work submitted separately from (but before) a fence
155 // is guaranteed complete by the time the fence signals.
Ben Clayton1943a292019-07-20 14:42:58 +0100156 renderer->synchronize();
Ben Claytonf2ab65b2020-11-20 15:12:27 +0000157 task.events->done();
Alexis Hetuc4bd9df2018-12-07 11:28:40 -0500158 }
Alexis Hetu072dc0d2018-10-31 11:41:25 -0400159}
160
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000161void Queue::taskLoop(marl::Scheduler *scheduler)
Hernan Liatis6b12a502019-03-01 15:06:13 -0800162{
Ben Claytone693b622019-09-05 12:48:37 +0100163 marl::Thread::setName("Queue<%p>", this);
Ben Claytond6c61362019-08-14 18:16:01 +0100164 scheduler->bind();
165 defer(scheduler->unbind());
166
Alexis Hetue1f51b92019-04-23 15:34:34 -0400167 while(true)
168 {
169 Task task = pending.take();
Hernan Liatis6b12a502019-03-01 15:06:13 -0800170
Alexis Hetue1f51b92019-04-23 15:34:34 -0400171 switch(task.type)
172 {
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000173 case Task::KILL_THREAD:
174 ASSERT_MSG(pending.count() == 0, "queue has remaining work!");
175 return;
176 case Task::SUBMIT_QUEUE:
177 submitQueue(task);
178 break;
179 default:
Nicolas Capens44bd43a2020-01-22 03:07:14 -0500180 UNREACHABLE("task.type %d", static_cast<int>(task.type));
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000181 break;
Alexis Hetue1f51b92019-04-23 15:34:34 -0400182 }
183 }
184}
Alexis Hetuf0aa9d52019-04-01 17:06:47 -0400185
Alexis Hetue1f51b92019-04-23 15:34:34 -0400186VkResult Queue::waitIdle()
187{
188 // Wait for task queue to flush.
Ben Claytonf2ab65b2020-11-20 15:12:27 +0000189 auto event = std::make_shared<sw::CountedEvent>();
190 event->add(); // done() is called at the end of submitQueue()
Alexis Hetue1f51b92019-04-23 15:34:34 -0400191
192 Task task;
Ben Claytonf2ab65b2020-11-20 15:12:27 +0000193 task.events = event;
Alexis Hetue1f51b92019-04-23 15:34:34 -0400194 pending.put(task);
195
Ben Claytonf2ab65b2020-11-20 15:12:27 +0000196 event->wait();
Alexis Hetue1f51b92019-04-23 15:34:34 -0400197
Alexis Hetue1f51b92019-04-23 15:34:34 -0400198 garbageCollect();
199
200 return VK_SUCCESS;
201}
202
203void Queue::garbageCollect()
204{
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500205 while(true)
Alexis Hetue1f51b92019-04-23 15:34:34 -0400206 {
207 auto v = toDelete.tryTake();
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500208 if(!v.second) { break; }
Alexis Hetue1f51b92019-04-23 15:34:34 -0400209 vk::deallocate(v.first, DEVICE_MEMORY);
210 }
Hernan Liatis6b12a502019-03-01 15:06:13 -0800211}
212
Chris Forbes1d667d62019-04-05 08:25:18 -0700213#ifndef __ANDROID__
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000214VkResult Queue::present(const VkPresentInfoKHR *presentInfo)
Hernan Liatis6b12a502019-03-01 15:06:13 -0800215{
Hernan Liatisd61595f2019-05-10 16:30:07 -0700216 // This is a hack to deal with screen tearing for now.
217 // Need to correctly implement threading using VkSemaphore
218 // to get rid of it. b/132458423
219 waitIdle();
Nicolas Capens023b8642020-01-16 01:46:02 -0500220
Hernan Liatis914a46d2019-03-12 11:34:24 -0700221 for(uint32_t i = 0; i < presentInfo->waitSemaphoreCount; i++)
222 {
223 vk::Cast(presentInfo->pWaitSemaphores[i])->wait();
224 }
225
Nicolas Capens023b8642020-01-16 01:46:02 -0500226 VkResult commandResult = VK_SUCCESS;
227
Hernan Liatis6b12a502019-03-01 15:06:13 -0800228 for(uint32_t i = 0; i < presentInfo->swapchainCount; i++)
229 {
Nicolas Capens023b8642020-01-16 01:46:02 -0500230 VkResult perSwapchainResult = vk::Cast(presentInfo->pSwapchains[i])->present(presentInfo->pImageIndices[i]);
231
232 if(presentInfo->pResults)
AWoloszyna59e70e2019-11-18 16:23:25 -0500233 {
Nicolas Capens023b8642020-01-16 01:46:02 -0500234 presentInfo->pResults[i] = perSwapchainResult;
AWoloszyna59e70e2019-11-18 16:23:25 -0500235 }
Nicolas Capens023b8642020-01-16 01:46:02 -0500236
Nicolas Capens748ad202020-01-16 14:48:54 -0500237 // Keep track of the worst result code. VK_SUBOPTIMAL_KHR is a success code so it should
238 // not override failure codes, but should not get replaced by a VK_SUCCESS result itself.
Nicolas Capens023b8642020-01-16 01:46:02 -0500239 if(perSwapchainResult != VK_SUCCESS)
240 {
Nicolas Capens748ad202020-01-16 14:48:54 -0500241 if(commandResult == VK_SUCCESS || commandResult == VK_SUBOPTIMAL_KHR)
242 {
243 commandResult = perSwapchainResult;
244 }
Nicolas Capens023b8642020-01-16 01:46:02 -0500245 }
Hernan Liatis6b12a502019-03-01 15:06:13 -0800246 }
Antonio Maiorano26c6c4a2019-10-17 15:33:47 -0400247
Nicolas Capens023b8642020-01-16 01:46:02 -0500248 return commandResult;
Alexis Hetucda0cf92019-01-24 15:48:55 -0500249}
Chris Forbes1d667d62019-04-05 08:25:18 -0700250#endif
Alexis Hetucda0cf92019-01-24 15:48:55 -0500251
Alexis Hetu74f6c652020-07-22 21:57:05 -0400252void Queue::beginDebugUtilsLabel(const VkDebugUtilsLabelEXT *pLabelInfo)
253{
254 // Optional debug label region
255}
256
257void Queue::endDebugUtilsLabel()
258{
259 // Close debug label region opened with beginDebugUtilsLabel()
260}
261
262void Queue::insertDebugUtilsLabel(const VkDebugUtilsLabelEXT *pLabelInfo)
263{
264 // Optional single debug label
265}
266
Nicolas Capens157ba262019-12-10 17:49:14 -0500267} // namespace vk