1*03ce13f7SAndroid Build Coastguard Worker // Copyright 2018 The SwiftShader Authors. All Rights Reserved.
2*03ce13f7SAndroid Build Coastguard Worker //
3*03ce13f7SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*03ce13f7SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*03ce13f7SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*03ce13f7SAndroid Build Coastguard Worker //
7*03ce13f7SAndroid Build Coastguard Worker // http://www.apache.org/licenses/LICENSE-2.0
8*03ce13f7SAndroid Build Coastguard Worker //
9*03ce13f7SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*03ce13f7SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*03ce13f7SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*03ce13f7SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*03ce13f7SAndroid Build Coastguard Worker // limitations under the License.
14*03ce13f7SAndroid Build Coastguard Worker
15*03ce13f7SAndroid Build Coastguard Worker #include "VkQueue.hpp"
16*03ce13f7SAndroid Build Coastguard Worker
17*03ce13f7SAndroid Build Coastguard Worker #include "VkCommandBuffer.hpp"
18*03ce13f7SAndroid Build Coastguard Worker #include "VkFence.hpp"
19*03ce13f7SAndroid Build Coastguard Worker #include "VkSemaphore.hpp"
20*03ce13f7SAndroid Build Coastguard Worker #include "VkStringify.hpp"
21*03ce13f7SAndroid Build Coastguard Worker #include "VkStructConversion.hpp"
22*03ce13f7SAndroid Build Coastguard Worker #include "VkTimelineSemaphore.hpp"
23*03ce13f7SAndroid Build Coastguard Worker #include "Device/Renderer.hpp"
24*03ce13f7SAndroid Build Coastguard Worker #include "WSI/VkSwapchainKHR.hpp"
25*03ce13f7SAndroid Build Coastguard Worker
26*03ce13f7SAndroid Build Coastguard Worker #include "marl/defer.h"
27*03ce13f7SAndroid Build Coastguard Worker #include "marl/scheduler.h"
28*03ce13f7SAndroid Build Coastguard Worker #include "marl/thread.h"
29*03ce13f7SAndroid Build Coastguard Worker #include "marl/trace.h"
30*03ce13f7SAndroid Build Coastguard Worker
31*03ce13f7SAndroid Build Coastguard Worker #include <cstring>
32*03ce13f7SAndroid Build Coastguard Worker
33*03ce13f7SAndroid Build Coastguard Worker namespace vk {
34*03ce13f7SAndroid Build Coastguard Worker
Queue(Device * device,marl::Scheduler * scheduler)35*03ce13f7SAndroid Build Coastguard Worker Queue::Queue(Device *device, marl::Scheduler *scheduler)
36*03ce13f7SAndroid Build Coastguard Worker : device(device)
37*03ce13f7SAndroid Build Coastguard Worker {
38*03ce13f7SAndroid Build Coastguard Worker queueThread = std::thread(&Queue::taskLoop, this, scheduler);
39*03ce13f7SAndroid Build Coastguard Worker }
40*03ce13f7SAndroid Build Coastguard Worker
~Queue()41*03ce13f7SAndroid Build Coastguard Worker Queue::~Queue()
42*03ce13f7SAndroid Build Coastguard Worker {
43*03ce13f7SAndroid Build Coastguard Worker Task task;
44*03ce13f7SAndroid Build Coastguard Worker task.type = Task::KILL_THREAD;
45*03ce13f7SAndroid Build Coastguard Worker pending.put(task);
46*03ce13f7SAndroid Build Coastguard Worker
47*03ce13f7SAndroid Build Coastguard Worker queueThread.join();
48*03ce13f7SAndroid Build Coastguard Worker ASSERT_MSG(pending.count() == 0, "queue has work after worker thread shutdown");
49*03ce13f7SAndroid Build Coastguard Worker
50*03ce13f7SAndroid Build Coastguard Worker garbageCollect();
51*03ce13f7SAndroid Build Coastguard Worker }
52*03ce13f7SAndroid Build Coastguard Worker
submit(uint32_t submitCount,SubmitInfo * pSubmits,Fence * fence)53*03ce13f7SAndroid Build Coastguard Worker VkResult Queue::submit(uint32_t submitCount, SubmitInfo *pSubmits, Fence *fence)
54*03ce13f7SAndroid Build Coastguard Worker {
55*03ce13f7SAndroid Build Coastguard Worker garbageCollect();
56*03ce13f7SAndroid Build Coastguard Worker
57*03ce13f7SAndroid Build Coastguard Worker Task task;
58*03ce13f7SAndroid Build Coastguard Worker task.submitCount = submitCount;
59*03ce13f7SAndroid Build Coastguard Worker task.pSubmits = pSubmits;
60*03ce13f7SAndroid Build Coastguard Worker if(fence)
61*03ce13f7SAndroid Build Coastguard Worker {
62*03ce13f7SAndroid Build Coastguard Worker task.events = fence->getCountedEvent();
63*03ce13f7SAndroid Build Coastguard Worker task.events->add();
64*03ce13f7SAndroid Build Coastguard Worker }
65*03ce13f7SAndroid Build Coastguard Worker
66*03ce13f7SAndroid Build Coastguard Worker pending.put(task);
67*03ce13f7SAndroid Build Coastguard Worker
68*03ce13f7SAndroid Build Coastguard Worker return VK_SUCCESS;
69*03ce13f7SAndroid Build Coastguard Worker }
70*03ce13f7SAndroid Build Coastguard Worker
submitQueue(const Task & task)71*03ce13f7SAndroid Build Coastguard Worker void Queue::submitQueue(const Task &task)
72*03ce13f7SAndroid Build Coastguard Worker {
73*03ce13f7SAndroid Build Coastguard Worker if(renderer == nullptr)
74*03ce13f7SAndroid Build Coastguard Worker {
75*03ce13f7SAndroid Build Coastguard Worker renderer.reset(new sw::Renderer(device));
76*03ce13f7SAndroid Build Coastguard Worker }
77*03ce13f7SAndroid Build Coastguard Worker
78*03ce13f7SAndroid Build Coastguard Worker for(uint32_t i = 0; i < task.submitCount; i++)
79*03ce13f7SAndroid Build Coastguard Worker {
80*03ce13f7SAndroid Build Coastguard Worker SubmitInfo &submitInfo = task.pSubmits[i];
81*03ce13f7SAndroid Build Coastguard Worker for(uint32_t j = 0; j < submitInfo.waitSemaphoreCount; j++)
82*03ce13f7SAndroid Build Coastguard Worker {
83*03ce13f7SAndroid Build Coastguard Worker if(auto *sem = DynamicCast<TimelineSemaphore>(submitInfo.pWaitSemaphores[j]))
84*03ce13f7SAndroid Build Coastguard Worker {
85*03ce13f7SAndroid Build Coastguard Worker ASSERT(j < submitInfo.waitSemaphoreValueCount);
86*03ce13f7SAndroid Build Coastguard Worker sem->wait(submitInfo.pWaitSemaphoreValues[j]);
87*03ce13f7SAndroid Build Coastguard Worker }
88*03ce13f7SAndroid Build Coastguard Worker else if(auto *sem = DynamicCast<BinarySemaphore>(submitInfo.pWaitSemaphores[j]))
89*03ce13f7SAndroid Build Coastguard Worker {
90*03ce13f7SAndroid Build Coastguard Worker sem->wait(submitInfo.pWaitDstStageMask[j]);
91*03ce13f7SAndroid Build Coastguard Worker }
92*03ce13f7SAndroid Build Coastguard Worker else
93*03ce13f7SAndroid Build Coastguard Worker {
94*03ce13f7SAndroid Build Coastguard Worker UNSUPPORTED("Unknown semaphore type");
95*03ce13f7SAndroid Build Coastguard Worker }
96*03ce13f7SAndroid Build Coastguard Worker }
97*03ce13f7SAndroid Build Coastguard Worker
98*03ce13f7SAndroid Build Coastguard Worker {
99*03ce13f7SAndroid Build Coastguard Worker CommandBuffer::ExecutionState executionState;
100*03ce13f7SAndroid Build Coastguard Worker executionState.renderer = renderer.get();
101*03ce13f7SAndroid Build Coastguard Worker executionState.events = task.events.get();
102*03ce13f7SAndroid Build Coastguard Worker for(uint32_t j = 0; j < submitInfo.commandBufferCount; j++)
103*03ce13f7SAndroid Build Coastguard Worker {
104*03ce13f7SAndroid Build Coastguard Worker Cast(submitInfo.pCommandBuffers[j])->submit(executionState);
105*03ce13f7SAndroid Build Coastguard Worker }
106*03ce13f7SAndroid Build Coastguard Worker }
107*03ce13f7SAndroid Build Coastguard Worker
108*03ce13f7SAndroid Build Coastguard Worker for(uint32_t j = 0; j < submitInfo.signalSemaphoreCount; j++)
109*03ce13f7SAndroid Build Coastguard Worker {
110*03ce13f7SAndroid Build Coastguard Worker if(auto *sem = DynamicCast<TimelineSemaphore>(submitInfo.pSignalSemaphores[j]))
111*03ce13f7SAndroid Build Coastguard Worker {
112*03ce13f7SAndroid Build Coastguard Worker ASSERT(j < submitInfo.signalSemaphoreValueCount);
113*03ce13f7SAndroid Build Coastguard Worker sem->signal(submitInfo.pSignalSemaphoreValues[j]);
114*03ce13f7SAndroid Build Coastguard Worker }
115*03ce13f7SAndroid Build Coastguard Worker else if(auto *sem = DynamicCast<BinarySemaphore>(submitInfo.pSignalSemaphores[j]))
116*03ce13f7SAndroid Build Coastguard Worker {
117*03ce13f7SAndroid Build Coastguard Worker sem->signal();
118*03ce13f7SAndroid Build Coastguard Worker }
119*03ce13f7SAndroid Build Coastguard Worker else
120*03ce13f7SAndroid Build Coastguard Worker {
121*03ce13f7SAndroid Build Coastguard Worker UNSUPPORTED("Unknown semaphore type");
122*03ce13f7SAndroid Build Coastguard Worker }
123*03ce13f7SAndroid Build Coastguard Worker }
124*03ce13f7SAndroid Build Coastguard Worker }
125*03ce13f7SAndroid Build Coastguard Worker
126*03ce13f7SAndroid Build Coastguard Worker if(task.pSubmits)
127*03ce13f7SAndroid Build Coastguard Worker {
128*03ce13f7SAndroid Build Coastguard Worker toDelete.put(task.pSubmits);
129*03ce13f7SAndroid Build Coastguard Worker }
130*03ce13f7SAndroid Build Coastguard Worker
131*03ce13f7SAndroid Build Coastguard Worker if(task.events)
132*03ce13f7SAndroid Build Coastguard Worker {
133*03ce13f7SAndroid Build Coastguard Worker // TODO: fix renderer signaling so that work submitted separately from (but before) a fence
134*03ce13f7SAndroid Build Coastguard Worker // is guaranteed complete by the time the fence signals.
135*03ce13f7SAndroid Build Coastguard Worker renderer->synchronize();
136*03ce13f7SAndroid Build Coastguard Worker task.events->done();
137*03ce13f7SAndroid Build Coastguard Worker }
138*03ce13f7SAndroid Build Coastguard Worker }
139*03ce13f7SAndroid Build Coastguard Worker
taskLoop(marl::Scheduler * scheduler)140*03ce13f7SAndroid Build Coastguard Worker void Queue::taskLoop(marl::Scheduler *scheduler)
141*03ce13f7SAndroid Build Coastguard Worker {
142*03ce13f7SAndroid Build Coastguard Worker marl::Thread::setName("Queue<%p>", this);
143*03ce13f7SAndroid Build Coastguard Worker scheduler->bind();
144*03ce13f7SAndroid Build Coastguard Worker defer(scheduler->unbind());
145*03ce13f7SAndroid Build Coastguard Worker
146*03ce13f7SAndroid Build Coastguard Worker while(true)
147*03ce13f7SAndroid Build Coastguard Worker {
148*03ce13f7SAndroid Build Coastguard Worker Task task = pending.take();
149*03ce13f7SAndroid Build Coastguard Worker
150*03ce13f7SAndroid Build Coastguard Worker switch(task.type)
151*03ce13f7SAndroid Build Coastguard Worker {
152*03ce13f7SAndroid Build Coastguard Worker case Task::KILL_THREAD:
153*03ce13f7SAndroid Build Coastguard Worker ASSERT_MSG(pending.count() == 0, "queue has remaining work!");
154*03ce13f7SAndroid Build Coastguard Worker return;
155*03ce13f7SAndroid Build Coastguard Worker case Task::SUBMIT_QUEUE:
156*03ce13f7SAndroid Build Coastguard Worker submitQueue(task);
157*03ce13f7SAndroid Build Coastguard Worker break;
158*03ce13f7SAndroid Build Coastguard Worker default:
159*03ce13f7SAndroid Build Coastguard Worker UNREACHABLE("task.type %d", static_cast<int>(task.type));
160*03ce13f7SAndroid Build Coastguard Worker break;
161*03ce13f7SAndroid Build Coastguard Worker }
162*03ce13f7SAndroid Build Coastguard Worker }
163*03ce13f7SAndroid Build Coastguard Worker }
164*03ce13f7SAndroid Build Coastguard Worker
waitIdle()165*03ce13f7SAndroid Build Coastguard Worker VkResult Queue::waitIdle()
166*03ce13f7SAndroid Build Coastguard Worker {
167*03ce13f7SAndroid Build Coastguard Worker // Wait for task queue to flush.
168*03ce13f7SAndroid Build Coastguard Worker auto event = std::make_shared<sw::CountedEvent>();
169*03ce13f7SAndroid Build Coastguard Worker event->add(); // done() is called at the end of submitQueue()
170*03ce13f7SAndroid Build Coastguard Worker
171*03ce13f7SAndroid Build Coastguard Worker Task task;
172*03ce13f7SAndroid Build Coastguard Worker task.events = event;
173*03ce13f7SAndroid Build Coastguard Worker pending.put(task);
174*03ce13f7SAndroid Build Coastguard Worker
175*03ce13f7SAndroid Build Coastguard Worker event->wait();
176*03ce13f7SAndroid Build Coastguard Worker
177*03ce13f7SAndroid Build Coastguard Worker garbageCollect();
178*03ce13f7SAndroid Build Coastguard Worker
179*03ce13f7SAndroid Build Coastguard Worker return VK_SUCCESS;
180*03ce13f7SAndroid Build Coastguard Worker }
181*03ce13f7SAndroid Build Coastguard Worker
garbageCollect()182*03ce13f7SAndroid Build Coastguard Worker void Queue::garbageCollect()
183*03ce13f7SAndroid Build Coastguard Worker {
184*03ce13f7SAndroid Build Coastguard Worker while(true)
185*03ce13f7SAndroid Build Coastguard Worker {
186*03ce13f7SAndroid Build Coastguard Worker auto v = toDelete.tryTake();
187*03ce13f7SAndroid Build Coastguard Worker if(!v.second) { break; }
188*03ce13f7SAndroid Build Coastguard Worker SubmitInfo::Release(v.first);
189*03ce13f7SAndroid Build Coastguard Worker }
190*03ce13f7SAndroid Build Coastguard Worker }
191*03ce13f7SAndroid Build Coastguard Worker
192*03ce13f7SAndroid Build Coastguard Worker #ifndef __ANDROID__
present(const VkPresentInfoKHR * presentInfo)193*03ce13f7SAndroid Build Coastguard Worker VkResult Queue::present(const VkPresentInfoKHR *presentInfo)
194*03ce13f7SAndroid Build Coastguard Worker {
195*03ce13f7SAndroid Build Coastguard Worker // This is a hack to deal with screen tearing for now.
196*03ce13f7SAndroid Build Coastguard Worker // Need to correctly implement threading using VkSemaphore
197*03ce13f7SAndroid Build Coastguard Worker // to get rid of it. b/132458423
198*03ce13f7SAndroid Build Coastguard Worker waitIdle();
199*03ce13f7SAndroid Build Coastguard Worker
200*03ce13f7SAndroid Build Coastguard Worker // Note: VkSwapchainPresentModeInfoEXT can be used to override the present mode, but present
201*03ce13f7SAndroid Build Coastguard Worker // mode is currently ignored by SwiftShader.
202*03ce13f7SAndroid Build Coastguard Worker
203*03ce13f7SAndroid Build Coastguard Worker for(uint32_t i = 0; i < presentInfo->waitSemaphoreCount; i++)
204*03ce13f7SAndroid Build Coastguard Worker {
205*03ce13f7SAndroid Build Coastguard Worker auto *semaphore = vk::DynamicCast<BinarySemaphore>(presentInfo->pWaitSemaphores[i]);
206*03ce13f7SAndroid Build Coastguard Worker semaphore->wait();
207*03ce13f7SAndroid Build Coastguard Worker }
208*03ce13f7SAndroid Build Coastguard Worker
209*03ce13f7SAndroid Build Coastguard Worker const auto *presentFences = vk::GetExtendedStruct<VkSwapchainPresentFenceInfoEXT>(presentInfo->pNext, VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_FENCE_INFO_EXT);
210*03ce13f7SAndroid Build Coastguard Worker
211*03ce13f7SAndroid Build Coastguard Worker VkResult commandResult = VK_SUCCESS;
212*03ce13f7SAndroid Build Coastguard Worker
213*03ce13f7SAndroid Build Coastguard Worker for(uint32_t i = 0; i < presentInfo->swapchainCount; i++)
214*03ce13f7SAndroid Build Coastguard Worker {
215*03ce13f7SAndroid Build Coastguard Worker auto *swapchain = vk::Cast(presentInfo->pSwapchains[i]);
216*03ce13f7SAndroid Build Coastguard Worker VkResult perSwapchainResult = swapchain->present(presentInfo->pImageIndices[i]);
217*03ce13f7SAndroid Build Coastguard Worker
218*03ce13f7SAndroid Build Coastguard Worker if(presentInfo->pResults)
219*03ce13f7SAndroid Build Coastguard Worker {
220*03ce13f7SAndroid Build Coastguard Worker presentInfo->pResults[i] = perSwapchainResult;
221*03ce13f7SAndroid Build Coastguard Worker }
222*03ce13f7SAndroid Build Coastguard Worker
223*03ce13f7SAndroid Build Coastguard Worker // Keep track of the worst result code. VK_SUBOPTIMAL_KHR is a success code so it should
224*03ce13f7SAndroid Build Coastguard Worker // not override failure codes, but should not get replaced by a VK_SUCCESS result itself.
225*03ce13f7SAndroid Build Coastguard Worker if(perSwapchainResult != VK_SUCCESS)
226*03ce13f7SAndroid Build Coastguard Worker {
227*03ce13f7SAndroid Build Coastguard Worker if(commandResult == VK_SUCCESS || commandResult == VK_SUBOPTIMAL_KHR)
228*03ce13f7SAndroid Build Coastguard Worker {
229*03ce13f7SAndroid Build Coastguard Worker commandResult = perSwapchainResult;
230*03ce13f7SAndroid Build Coastguard Worker }
231*03ce13f7SAndroid Build Coastguard Worker }
232*03ce13f7SAndroid Build Coastguard Worker
233*03ce13f7SAndroid Build Coastguard Worker // The wait semaphores and the swapchain are no longer accessed
234*03ce13f7SAndroid Build Coastguard Worker if(presentFences)
235*03ce13f7SAndroid Build Coastguard Worker {
236*03ce13f7SAndroid Build Coastguard Worker vk::Cast(presentFences->pFences[i])->complete();
237*03ce13f7SAndroid Build Coastguard Worker }
238*03ce13f7SAndroid Build Coastguard Worker }
239*03ce13f7SAndroid Build Coastguard Worker
240*03ce13f7SAndroid Build Coastguard Worker return commandResult;
241*03ce13f7SAndroid Build Coastguard Worker }
242*03ce13f7SAndroid Build Coastguard Worker #endif
243*03ce13f7SAndroid Build Coastguard Worker
beginDebugUtilsLabel(const VkDebugUtilsLabelEXT * pLabelInfo)244*03ce13f7SAndroid Build Coastguard Worker void Queue::beginDebugUtilsLabel(const VkDebugUtilsLabelEXT *pLabelInfo)
245*03ce13f7SAndroid Build Coastguard Worker {
246*03ce13f7SAndroid Build Coastguard Worker // Optional debug label region
247*03ce13f7SAndroid Build Coastguard Worker }
248*03ce13f7SAndroid Build Coastguard Worker
endDebugUtilsLabel()249*03ce13f7SAndroid Build Coastguard Worker void Queue::endDebugUtilsLabel()
250*03ce13f7SAndroid Build Coastguard Worker {
251*03ce13f7SAndroid Build Coastguard Worker // Close debug label region opened with beginDebugUtilsLabel()
252*03ce13f7SAndroid Build Coastguard Worker }
253*03ce13f7SAndroid Build Coastguard Worker
insertDebugUtilsLabel(const VkDebugUtilsLabelEXT * pLabelInfo)254*03ce13f7SAndroid Build Coastguard Worker void Queue::insertDebugUtilsLabel(const VkDebugUtilsLabelEXT *pLabelInfo)
255*03ce13f7SAndroid Build Coastguard Worker {
256*03ce13f7SAndroid Build Coastguard Worker // Optional single debug label
257*03ce13f7SAndroid Build Coastguard Worker }
258*03ce13f7SAndroid Build Coastguard Worker
259*03ce13f7SAndroid Build Coastguard Worker } // namespace vk
260