Alexis Hetu | 767b41b | 2018-09-26 11:25:46 -0400 | [diff] [blame] | 1 | // 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 Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 15 | #include "VkQueue.hpp" |
Alexis Hetu | 072dc0d | 2018-10-31 11:41:25 -0400 | [diff] [blame] | 16 | #include "VkCommandBuffer.hpp" |
Alexis Hetu | c4bd9df | 2018-12-07 11:28:40 -0500 | [diff] [blame] | 17 | #include "VkFence.hpp" |
Alexis Hetu | 072dc0d | 2018-10-31 11:41:25 -0400 | [diff] [blame] | 18 | #include "VkSemaphore.hpp" |
Chris Forbes | ab1e2b4 | 2019-05-11 10:28:37 -0700 | [diff] [blame] | 19 | #include "Device/Renderer.hpp" |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 20 | #include "WSI/VkSwapchainKHR.hpp" |
Alexis Hetu | 767b41b | 2018-09-26 11:25:46 -0400 | [diff] [blame] | 21 | |
Ben Clayton | e693b62 | 2019-09-05 12:48:37 +0100 | [diff] [blame] | 22 | #include "marl/defer.h" |
| 23 | #include "marl/scheduler.h" |
| 24 | #include "marl/thread.h" |
| 25 | #include "marl/trace.h" |
Ben Clayton | d6c6136 | 2019-08-14 18:16:01 +0100 | [diff] [blame] | 26 | |
Alexis Hetu | e1f51b9 | 2019-04-23 15:34:34 -0400 | [diff] [blame] | 27 | #include <cstring> |
| 28 | |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 29 | namespace { |
Alexis Hetu | e1f51b9 | 2019-04-23 15:34:34 -0400 | [diff] [blame] | 30 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 31 | VkSubmitInfo *DeepCopySubmitInfo(uint32_t submitCount, const VkSubmitInfo *pSubmits) |
Alexis Hetu | e1f51b9 | 2019-04-23 15:34:34 -0400 | [diff] [blame] | 32 | { |
| 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 Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 43 | uint8_t *mem = static_cast<uint8_t *>( |
| 44 | vk::allocate(totalSize, vk::REQUIRED_MEMORY_ALIGNMENT, vk::DEVICE_MEMORY, vk::Fence::GetAllocationScope())); |
Alexis Hetu | e1f51b9 | 2019-04-23 15:34:34 -0400 | [diff] [blame] | 45 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 46 | auto submits = new(mem) VkSubmitInfo[submitCount]; |
Alexis Hetu | e1f51b9 | 2019-04-23 15:34:34 -0400 | [diff] [blame] | 47 | 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 Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 53 | submits[i].pWaitSemaphores = reinterpret_cast<const VkSemaphore *>(mem); |
Alexis Hetu | e1f51b9 | 2019-04-23 15:34:34 -0400 | [diff] [blame] | 54 | memcpy(mem, pSubmits[i].pWaitSemaphores, size); |
| 55 | mem += size; |
| 56 | |
| 57 | size = pSubmits[i].waitSemaphoreCount * sizeof(VkPipelineStageFlags); |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 58 | submits[i].pWaitDstStageMask = reinterpret_cast<const VkPipelineStageFlags *>(mem); |
Alexis Hetu | e1f51b9 | 2019-04-23 15:34:34 -0400 | [diff] [blame] | 59 | memcpy(mem, pSubmits[i].pWaitDstStageMask, size); |
| 60 | mem += size; |
| 61 | |
| 62 | size = pSubmits[i].signalSemaphoreCount * sizeof(VkSemaphore); |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 63 | submits[i].pSignalSemaphores = reinterpret_cast<const VkSemaphore *>(mem); |
Alexis Hetu | e1f51b9 | 2019-04-23 15:34:34 -0400 | [diff] [blame] | 64 | memcpy(mem, pSubmits[i].pSignalSemaphores, size); |
| 65 | mem += size; |
| 66 | |
| 67 | size = pSubmits[i].commandBufferCount * sizeof(VkCommandBuffer); |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 68 | submits[i].pCommandBuffers = reinterpret_cast<const VkCommandBuffer *>(mem); |
Alexis Hetu | e1f51b9 | 2019-04-23 15:34:34 -0400 | [diff] [blame] | 69 | memcpy(mem, pSubmits[i].pCommandBuffers, size); |
| 70 | mem += size; |
| 71 | } |
| 72 | |
| 73 | return submits; |
| 74 | } |
| 75 | |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 76 | } // anonymous namespace |
Alexis Hetu | e1f51b9 | 2019-04-23 15:34:34 -0400 | [diff] [blame] | 77 | |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 78 | namespace vk { |
Alexis Hetu | 767b41b | 2018-09-26 11:25:46 -0400 | [diff] [blame] | 79 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 80 | Queue::Queue(Device *device, marl::Scheduler *scheduler) |
| 81 | : device(device) |
Alexis Hetu | 767b41b | 2018-09-26 11:25:46 -0400 | [diff] [blame] | 82 | { |
Ben Clayton | d6c6136 | 2019-08-14 18:16:01 +0100 | [diff] [blame] | 83 | queueThread = std::thread(&Queue::taskLoop, this, scheduler); |
Alexis Hetu | af3c102 | 2018-12-12 13:26:15 -0500 | [diff] [blame] | 84 | } |
| 85 | |
Ben Clayton | 7e0a036 | 2019-05-20 11:32:35 +0100 | [diff] [blame] | 86 | Queue::~Queue() |
Alexis Hetu | af3c102 | 2018-12-12 13:26:15 -0500 | [diff] [blame] | 87 | { |
Alexis Hetu | e1f51b9 | 2019-04-23 15:34:34 -0400 | [diff] [blame] | 88 | 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 Hetu | 767b41b | 2018-09-26 11:25:46 -0400 | [diff] [blame] | 96 | } |
| 97 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 98 | VkResult Queue::submit(uint32_t submitCount, const VkSubmitInfo *pSubmits, Fence *fence) |
Alexis Hetu | 072dc0d | 2018-10-31 11:41:25 -0400 | [diff] [blame] | 99 | { |
Alexis Hetu | e1f51b9 | 2019-04-23 15:34:34 -0400 | [diff] [blame] | 100 | garbageCollect(); |
| 101 | |
| 102 | Task task; |
| 103 | task.submitCount = submitCount; |
| 104 | task.pSubmits = DeepCopySubmitInfo(submitCount, pSubmits); |
Ben Clayton | f2ab65b | 2020-11-20 15:12:27 +0000 | [diff] [blame] | 105 | if(fence) |
Alexis Hetu | 072dc0d | 2018-10-31 11:41:25 -0400 | [diff] [blame] | 106 | { |
Ben Clayton | f2ab65b | 2020-11-20 15:12:27 +0000 | [diff] [blame] | 107 | task.events = fence->getCountedEvent(); |
| 108 | task.events->add(); |
Alexis Hetu | e1f51b9 | 2019-04-23 15:34:34 -0400 | [diff] [blame] | 109 | } |
| 110 | |
| 111 | pending.put(task); |
| 112 | |
| 113 | return VK_SUCCESS; |
| 114 | } |
| 115 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 116 | void Queue::submitQueue(const Task &task) |
Alexis Hetu | e1f51b9 | 2019-04-23 15:34:34 -0400 | [diff] [blame] | 117 | { |
Nicolas Capens | 81bc9d9 | 2019-12-16 15:05:57 -0500 | [diff] [blame] | 118 | if(renderer == nullptr) |
Ben Clayton | 1943a29 | 2019-07-20 14:42:58 +0100 | [diff] [blame] | 119 | { |
| 120 | renderer.reset(new sw::Renderer(device)); |
| 121 | } |
| 122 | |
Alexis Hetu | e1f51b9 | 2019-04-23 15:34:34 -0400 | [diff] [blame] | 123 | for(uint32_t i = 0; i < task.submitCount; i++) |
| 124 | { |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 125 | auto &submitInfo = task.pSubmits[i]; |
Alexis Hetu | 072dc0d | 2018-10-31 11:41:25 -0400 | [diff] [blame] | 126 | for(uint32_t j = 0; j < submitInfo.waitSemaphoreCount; j++) |
| 127 | { |
| 128 | vk::Cast(submitInfo.pWaitSemaphores[j])->wait(submitInfo.pWaitDstStageMask[j]); |
| 129 | } |
| 130 | |
Alexis Hetu | 072dc0d | 2018-10-31 11:41:25 -0400 | [diff] [blame] | 131 | { |
Alexis Hetu | 9bc7a81 | 2018-12-07 16:13:34 -0500 | [diff] [blame] | 132 | CommandBuffer::ExecutionState executionState; |
Ben Clayton | 1943a29 | 2019-07-20 14:42:58 +0100 | [diff] [blame] | 133 | executionState.renderer = renderer.get(); |
Ben Clayton | f2ab65b | 2020-11-20 15:12:27 +0000 | [diff] [blame] | 134 | executionState.events = task.events.get(); |
Alexis Hetu | 9bc7a81 | 2018-12-07 16:13:34 -0500 | [diff] [blame] | 135 | for(uint32_t j = 0; j < submitInfo.commandBufferCount; j++) |
| 136 | { |
| 137 | vk::Cast(submitInfo.pCommandBuffers[j])->submit(executionState); |
| 138 | } |
Alexis Hetu | 072dc0d | 2018-10-31 11:41:25 -0400 | [diff] [blame] | 139 | } |
| 140 | |
| 141 | for(uint32_t j = 0; j < submitInfo.signalSemaphoreCount; j++) |
| 142 | { |
| 143 | vk::Cast(submitInfo.pSignalSemaphores[j])->signal(); |
| 144 | } |
| 145 | } |
Alexis Hetu | c4bd9df | 2018-12-07 11:28:40 -0500 | [diff] [blame] | 146 | |
Nicolas Capens | 81bc9d9 | 2019-12-16 15:05:57 -0500 | [diff] [blame] | 147 | if(task.pSubmits) |
Alexis Hetu | c4bd9df | 2018-12-07 11:28:40 -0500 | [diff] [blame] | 148 | { |
Alexis Hetu | e1f51b9 | 2019-04-23 15:34:34 -0400 | [diff] [blame] | 149 | toDelete.put(task.pSubmits); |
| 150 | } |
| 151 | |
Ben Clayton | bd0ab1b | 2019-05-20 11:20:28 +0100 | [diff] [blame] | 152 | if(task.events) |
Alexis Hetu | e1f51b9 | 2019-04-23 15:34:34 -0400 | [diff] [blame] | 153 | { |
Chris Forbes | ab1e2b4 | 2019-05-11 10:28:37 -0700 | [diff] [blame] | 154 | // 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 Clayton | 1943a29 | 2019-07-20 14:42:58 +0100 | [diff] [blame] | 156 | renderer->synchronize(); |
Ben Clayton | f2ab65b | 2020-11-20 15:12:27 +0000 | [diff] [blame] | 157 | task.events->done(); |
Alexis Hetu | c4bd9df | 2018-12-07 11:28:40 -0500 | [diff] [blame] | 158 | } |
Alexis Hetu | 072dc0d | 2018-10-31 11:41:25 -0400 | [diff] [blame] | 159 | } |
| 160 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 161 | void Queue::taskLoop(marl::Scheduler *scheduler) |
Hernan Liatis | 6b12a50 | 2019-03-01 15:06:13 -0800 | [diff] [blame] | 162 | { |
Ben Clayton | e693b62 | 2019-09-05 12:48:37 +0100 | [diff] [blame] | 163 | marl::Thread::setName("Queue<%p>", this); |
Ben Clayton | d6c6136 | 2019-08-14 18:16:01 +0100 | [diff] [blame] | 164 | scheduler->bind(); |
| 165 | defer(scheduler->unbind()); |
| 166 | |
Alexis Hetu | e1f51b9 | 2019-04-23 15:34:34 -0400 | [diff] [blame] | 167 | while(true) |
| 168 | { |
| 169 | Task task = pending.take(); |
Hernan Liatis | 6b12a50 | 2019-03-01 15:06:13 -0800 | [diff] [blame] | 170 | |
Alexis Hetu | e1f51b9 | 2019-04-23 15:34:34 -0400 | [diff] [blame] | 171 | switch(task.type) |
| 172 | { |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 173 | 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 Capens | 44bd43a | 2020-01-22 03:07:14 -0500 | [diff] [blame] | 180 | UNREACHABLE("task.type %d", static_cast<int>(task.type)); |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 181 | break; |
Alexis Hetu | e1f51b9 | 2019-04-23 15:34:34 -0400 | [diff] [blame] | 182 | } |
| 183 | } |
| 184 | } |
Alexis Hetu | f0aa9d5 | 2019-04-01 17:06:47 -0400 | [diff] [blame] | 185 | |
Alexis Hetu | e1f51b9 | 2019-04-23 15:34:34 -0400 | [diff] [blame] | 186 | VkResult Queue::waitIdle() |
| 187 | { |
| 188 | // Wait for task queue to flush. |
Ben Clayton | f2ab65b | 2020-11-20 15:12:27 +0000 | [diff] [blame] | 189 | auto event = std::make_shared<sw::CountedEvent>(); |
| 190 | event->add(); // done() is called at the end of submitQueue() |
Alexis Hetu | e1f51b9 | 2019-04-23 15:34:34 -0400 | [diff] [blame] | 191 | |
| 192 | Task task; |
Ben Clayton | f2ab65b | 2020-11-20 15:12:27 +0000 | [diff] [blame] | 193 | task.events = event; |
Alexis Hetu | e1f51b9 | 2019-04-23 15:34:34 -0400 | [diff] [blame] | 194 | pending.put(task); |
| 195 | |
Ben Clayton | f2ab65b | 2020-11-20 15:12:27 +0000 | [diff] [blame] | 196 | event->wait(); |
Alexis Hetu | e1f51b9 | 2019-04-23 15:34:34 -0400 | [diff] [blame] | 197 | |
Alexis Hetu | e1f51b9 | 2019-04-23 15:34:34 -0400 | [diff] [blame] | 198 | garbageCollect(); |
| 199 | |
| 200 | return VK_SUCCESS; |
| 201 | } |
| 202 | |
| 203 | void Queue::garbageCollect() |
| 204 | { |
Nicolas Capens | 81bc9d9 | 2019-12-16 15:05:57 -0500 | [diff] [blame] | 205 | while(true) |
Alexis Hetu | e1f51b9 | 2019-04-23 15:34:34 -0400 | [diff] [blame] | 206 | { |
| 207 | auto v = toDelete.tryTake(); |
Nicolas Capens | 81bc9d9 | 2019-12-16 15:05:57 -0500 | [diff] [blame] | 208 | if(!v.second) { break; } |
Alexis Hetu | e1f51b9 | 2019-04-23 15:34:34 -0400 | [diff] [blame] | 209 | vk::deallocate(v.first, DEVICE_MEMORY); |
| 210 | } |
Hernan Liatis | 6b12a50 | 2019-03-01 15:06:13 -0800 | [diff] [blame] | 211 | } |
| 212 | |
Chris Forbes | 1d667d6 | 2019-04-05 08:25:18 -0700 | [diff] [blame] | 213 | #ifndef __ANDROID__ |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 214 | VkResult Queue::present(const VkPresentInfoKHR *presentInfo) |
Hernan Liatis | 6b12a50 | 2019-03-01 15:06:13 -0800 | [diff] [blame] | 215 | { |
Hernan Liatis | d61595f | 2019-05-10 16:30:07 -0700 | [diff] [blame] | 216 | // 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 Capens | 023b864 | 2020-01-16 01:46:02 -0500 | [diff] [blame] | 220 | |
Hernan Liatis | 914a46d | 2019-03-12 11:34:24 -0700 | [diff] [blame] | 221 | for(uint32_t i = 0; i < presentInfo->waitSemaphoreCount; i++) |
| 222 | { |
| 223 | vk::Cast(presentInfo->pWaitSemaphores[i])->wait(); |
| 224 | } |
| 225 | |
Nicolas Capens | 023b864 | 2020-01-16 01:46:02 -0500 | [diff] [blame] | 226 | VkResult commandResult = VK_SUCCESS; |
| 227 | |
Hernan Liatis | 6b12a50 | 2019-03-01 15:06:13 -0800 | [diff] [blame] | 228 | for(uint32_t i = 0; i < presentInfo->swapchainCount; i++) |
| 229 | { |
Nicolas Capens | 023b864 | 2020-01-16 01:46:02 -0500 | [diff] [blame] | 230 | VkResult perSwapchainResult = vk::Cast(presentInfo->pSwapchains[i])->present(presentInfo->pImageIndices[i]); |
| 231 | |
| 232 | if(presentInfo->pResults) |
AWoloszyn | a59e70e | 2019-11-18 16:23:25 -0500 | [diff] [blame] | 233 | { |
Nicolas Capens | 023b864 | 2020-01-16 01:46:02 -0500 | [diff] [blame] | 234 | presentInfo->pResults[i] = perSwapchainResult; |
AWoloszyn | a59e70e | 2019-11-18 16:23:25 -0500 | [diff] [blame] | 235 | } |
Nicolas Capens | 023b864 | 2020-01-16 01:46:02 -0500 | [diff] [blame] | 236 | |
Nicolas Capens | 748ad20 | 2020-01-16 14:48:54 -0500 | [diff] [blame] | 237 | // 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 Capens | 023b864 | 2020-01-16 01:46:02 -0500 | [diff] [blame] | 239 | if(perSwapchainResult != VK_SUCCESS) |
| 240 | { |
Nicolas Capens | 748ad20 | 2020-01-16 14:48:54 -0500 | [diff] [blame] | 241 | if(commandResult == VK_SUCCESS || commandResult == VK_SUBOPTIMAL_KHR) |
| 242 | { |
| 243 | commandResult = perSwapchainResult; |
| 244 | } |
Nicolas Capens | 023b864 | 2020-01-16 01:46:02 -0500 | [diff] [blame] | 245 | } |
Hernan Liatis | 6b12a50 | 2019-03-01 15:06:13 -0800 | [diff] [blame] | 246 | } |
Antonio Maiorano | 26c6c4a | 2019-10-17 15:33:47 -0400 | [diff] [blame] | 247 | |
Nicolas Capens | 023b864 | 2020-01-16 01:46:02 -0500 | [diff] [blame] | 248 | return commandResult; |
Alexis Hetu | cda0cf9 | 2019-01-24 15:48:55 -0500 | [diff] [blame] | 249 | } |
Chris Forbes | 1d667d6 | 2019-04-05 08:25:18 -0700 | [diff] [blame] | 250 | #endif |
Alexis Hetu | cda0cf9 | 2019-01-24 15:48:55 -0500 | [diff] [blame] | 251 | |
Alexis Hetu | 74f6c65 | 2020-07-22 21:57:05 -0400 | [diff] [blame] | 252 | void Queue::beginDebugUtilsLabel(const VkDebugUtilsLabelEXT *pLabelInfo) |
| 253 | { |
| 254 | // Optional debug label region |
| 255 | } |
| 256 | |
| 257 | void Queue::endDebugUtilsLabel() |
| 258 | { |
| 259 | // Close debug label region opened with beginDebugUtilsLabel() |
| 260 | } |
| 261 | |
| 262 | void Queue::insertDebugUtilsLabel(const VkDebugUtilsLabelEXT *pLabelInfo) |
| 263 | { |
| 264 | // Optional single debug label |
| 265 | } |
| 266 | |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 267 | } // namespace vk |