xref: /aosp_15_r20/external/swiftshader/src/Vulkan/VkQueue.cpp (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
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