xref: /aosp_15_r20/external/swiftshader/src/Vulkan/VkTimelineSemaphore.cpp (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
1*03ce13f7SAndroid Build Coastguard Worker // Copyright 2021 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 "VkTimelineSemaphore.hpp"
16*03ce13f7SAndroid Build Coastguard Worker #include "VkSemaphore.hpp"
17*03ce13f7SAndroid Build Coastguard Worker 
18*03ce13f7SAndroid Build Coastguard Worker #include "marl/blockingcall.h"
19*03ce13f7SAndroid Build Coastguard Worker #include "marl/conditionvariable.h"
20*03ce13f7SAndroid Build Coastguard Worker 
21*03ce13f7SAndroid Build Coastguard Worker #include <vector>
22*03ce13f7SAndroid Build Coastguard Worker 
23*03ce13f7SAndroid Build Coastguard Worker namespace vk {
24*03ce13f7SAndroid Build Coastguard Worker 
TimelineSemaphore(const VkSemaphoreCreateInfo * pCreateInfo,void * mem,const VkAllocationCallbacks * pAllocator)25*03ce13f7SAndroid Build Coastguard Worker TimelineSemaphore::TimelineSemaphore(const VkSemaphoreCreateInfo *pCreateInfo, void *mem, const VkAllocationCallbacks *pAllocator)
26*03ce13f7SAndroid Build Coastguard Worker     : Semaphore(VK_SEMAPHORE_TYPE_TIMELINE)
27*03ce13f7SAndroid Build Coastguard Worker {
28*03ce13f7SAndroid Build Coastguard Worker 	SemaphoreCreateInfo info(pCreateInfo);
29*03ce13f7SAndroid Build Coastguard Worker 	ASSERT(info.semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE);
30*03ce13f7SAndroid Build Coastguard Worker 	type = info.semaphoreType;
31*03ce13f7SAndroid Build Coastguard Worker 	counter = info.initialPayload;
32*03ce13f7SAndroid Build Coastguard Worker }
33*03ce13f7SAndroid Build Coastguard Worker 
TimelineSemaphore()34*03ce13f7SAndroid Build Coastguard Worker TimelineSemaphore::TimelineSemaphore()
35*03ce13f7SAndroid Build Coastguard Worker     : Semaphore(VK_SEMAPHORE_TYPE_TIMELINE)
36*03ce13f7SAndroid Build Coastguard Worker     , counter(0)
37*03ce13f7SAndroid Build Coastguard Worker {
38*03ce13f7SAndroid Build Coastguard Worker 	type = VK_SEMAPHORE_TYPE_TIMELINE;
39*03ce13f7SAndroid Build Coastguard Worker }
40*03ce13f7SAndroid Build Coastguard Worker 
ComputeRequiredAllocationSize(const VkSemaphoreCreateInfo * pCreateInfo)41*03ce13f7SAndroid Build Coastguard Worker size_t TimelineSemaphore::ComputeRequiredAllocationSize(const VkSemaphoreCreateInfo *pCreateInfo)
42*03ce13f7SAndroid Build Coastguard Worker {
43*03ce13f7SAndroid Build Coastguard Worker 	return 0;
44*03ce13f7SAndroid Build Coastguard Worker }
45*03ce13f7SAndroid Build Coastguard Worker 
destroy(const VkAllocationCallbacks * pAllocator)46*03ce13f7SAndroid Build Coastguard Worker void TimelineSemaphore::destroy(const VkAllocationCallbacks *pAllocator)
47*03ce13f7SAndroid Build Coastguard Worker {
48*03ce13f7SAndroid Build Coastguard Worker }
49*03ce13f7SAndroid Build Coastguard Worker 
signal(uint64_t value)50*03ce13f7SAndroid Build Coastguard Worker void TimelineSemaphore::signal(uint64_t value)
51*03ce13f7SAndroid Build Coastguard Worker {
52*03ce13f7SAndroid Build Coastguard Worker 	marl::lock lock(mutex);
53*03ce13f7SAndroid Build Coastguard Worker 	if(counter < value)
54*03ce13f7SAndroid Build Coastguard Worker 	{
55*03ce13f7SAndroid Build Coastguard Worker 		counter = value;
56*03ce13f7SAndroid Build Coastguard Worker 		cv.notify_all();
57*03ce13f7SAndroid Build Coastguard Worker 		for(auto &[waitObject, waitValue] : any_waits)
58*03ce13f7SAndroid Build Coastguard Worker 		{
59*03ce13f7SAndroid Build Coastguard Worker 			if(counter >= waitValue)
60*03ce13f7SAndroid Build Coastguard Worker 			{
61*03ce13f7SAndroid Build Coastguard Worker 				waitObject->signal();
62*03ce13f7SAndroid Build Coastguard Worker 			}
63*03ce13f7SAndroid Build Coastguard Worker 		}
64*03ce13f7SAndroid Build Coastguard Worker 	}
65*03ce13f7SAndroid Build Coastguard Worker }
66*03ce13f7SAndroid Build Coastguard Worker 
wait(uint64_t value)67*03ce13f7SAndroid Build Coastguard Worker void TimelineSemaphore::wait(uint64_t value)
68*03ce13f7SAndroid Build Coastguard Worker {
69*03ce13f7SAndroid Build Coastguard Worker 	marl::lock lock(mutex);
70*03ce13f7SAndroid Build Coastguard Worker 	cv.wait(lock, [&]() { return counter >= value; });
71*03ce13f7SAndroid Build Coastguard Worker }
72*03ce13f7SAndroid Build Coastguard Worker 
getCounterValue()73*03ce13f7SAndroid Build Coastguard Worker uint64_t TimelineSemaphore::getCounterValue()
74*03ce13f7SAndroid Build Coastguard Worker {
75*03ce13f7SAndroid Build Coastguard Worker 	marl::lock lock(mutex);
76*03ce13f7SAndroid Build Coastguard Worker 	return counter;
77*03ce13f7SAndroid Build Coastguard Worker }
78*03ce13f7SAndroid Build Coastguard Worker 
WaitForAny(const VkSemaphoreWaitInfo * pWaitInfo)79*03ce13f7SAndroid Build Coastguard Worker TimelineSemaphore::WaitForAny::WaitForAny(const VkSemaphoreWaitInfo *pWaitInfo)
80*03ce13f7SAndroid Build Coastguard Worker {
81*03ce13f7SAndroid Build Coastguard Worker 	for(uint32_t i = 0; i < pWaitInfo->semaphoreCount; i++)
82*03ce13f7SAndroid Build Coastguard Worker 	{
83*03ce13f7SAndroid Build Coastguard Worker 		TimelineSemaphore *semaphore = DynamicCast<TimelineSemaphore>(pWaitInfo->pSemaphores[i]);
84*03ce13f7SAndroid Build Coastguard Worker 		uint64_t waitValue = pWaitInfo->pValues[i];
85*03ce13f7SAndroid Build Coastguard Worker 		switch(semaphore->addWait(this, waitValue))
86*03ce13f7SAndroid Build Coastguard Worker 		{
87*03ce13f7SAndroid Build Coastguard Worker 		case AddWaitResult::kWaitAdded:
88*03ce13f7SAndroid Build Coastguard Worker 			semaphores.push_back(semaphore);
89*03ce13f7SAndroid Build Coastguard Worker 			break;
90*03ce13f7SAndroid Build Coastguard Worker 		case AddWaitResult::kValueAlreadySignaled:
91*03ce13f7SAndroid Build Coastguard Worker 			signal();
92*03ce13f7SAndroid Build Coastguard Worker 			break;
93*03ce13f7SAndroid Build Coastguard Worker 		case AddWaitResult::kWaitUpdated:
94*03ce13f7SAndroid Build Coastguard Worker 			// Do nothing.
95*03ce13f7SAndroid Build Coastguard Worker 			break;
96*03ce13f7SAndroid Build Coastguard Worker 		}
97*03ce13f7SAndroid Build Coastguard Worker 	}
98*03ce13f7SAndroid Build Coastguard Worker }
99*03ce13f7SAndroid Build Coastguard Worker 
~WaitForAny()100*03ce13f7SAndroid Build Coastguard Worker TimelineSemaphore::WaitForAny::~WaitForAny()
101*03ce13f7SAndroid Build Coastguard Worker {
102*03ce13f7SAndroid Build Coastguard Worker 	for(TimelineSemaphore *semaphore : semaphores)
103*03ce13f7SAndroid Build Coastguard Worker 	{
104*03ce13f7SAndroid Build Coastguard Worker 		semaphore->removeWait(this);
105*03ce13f7SAndroid Build Coastguard Worker 	}
106*03ce13f7SAndroid Build Coastguard Worker }
107*03ce13f7SAndroid Build Coastguard Worker 
108*03ce13f7SAndroid Build Coastguard Worker TimelineSemaphore::AddWaitResult
addWait(WaitForAny * waitObject,uint64_t waitValue)109*03ce13f7SAndroid Build Coastguard Worker TimelineSemaphore::addWait(WaitForAny *waitObject, uint64_t waitValue)
110*03ce13f7SAndroid Build Coastguard Worker {
111*03ce13f7SAndroid Build Coastguard Worker 	// Lock the semaphore's mutex, so that its current state can be checked and,
112*03ce13f7SAndroid Build Coastguard Worker 	// if necessary, its list of waits can be updated.
113*03ce13f7SAndroid Build Coastguard Worker 	marl::lock lock(mutex);
114*03ce13f7SAndroid Build Coastguard Worker 	if(counter >= waitValue)
115*03ce13f7SAndroid Build Coastguard Worker 	{
116*03ce13f7SAndroid Build Coastguard Worker 		return AddWaitResult::kValueAlreadySignaled;
117*03ce13f7SAndroid Build Coastguard Worker 	}
118*03ce13f7SAndroid Build Coastguard Worker 
119*03ce13f7SAndroid Build Coastguard Worker 	auto it = any_waits.find(waitObject);
120*03ce13f7SAndroid Build Coastguard Worker 	if(it == any_waits.end())
121*03ce13f7SAndroid Build Coastguard Worker 	{
122*03ce13f7SAndroid Build Coastguard Worker 		any_waits[waitObject] = waitValue;
123*03ce13f7SAndroid Build Coastguard Worker 		return AddWaitResult::kWaitAdded;
124*03ce13f7SAndroid Build Coastguard Worker 	}
125*03ce13f7SAndroid Build Coastguard Worker 
126*03ce13f7SAndroid Build Coastguard Worker 	// If the same dependency is added more than once, only wait for the
127*03ce13f7SAndroid Build Coastguard Worker 	// lowest expected value provided.
128*03ce13f7SAndroid Build Coastguard Worker 	it->second = std::min(it->second, waitValue);
129*03ce13f7SAndroid Build Coastguard Worker 	return AddWaitResult::kWaitUpdated;
130*03ce13f7SAndroid Build Coastguard Worker }
131*03ce13f7SAndroid Build Coastguard Worker 
removeWait(WaitForAny * waitObject)132*03ce13f7SAndroid Build Coastguard Worker void TimelineSemaphore::removeWait(WaitForAny *waitObject)
133*03ce13f7SAndroid Build Coastguard Worker {
134*03ce13f7SAndroid Build Coastguard Worker 	marl::lock lock(mutex);
135*03ce13f7SAndroid Build Coastguard Worker 	any_waits.erase(waitObject);
136*03ce13f7SAndroid Build Coastguard Worker }
137*03ce13f7SAndroid Build Coastguard Worker 
wait()138*03ce13f7SAndroid Build Coastguard Worker void TimelineSemaphore::WaitForAny::wait()
139*03ce13f7SAndroid Build Coastguard Worker {
140*03ce13f7SAndroid Build Coastguard Worker 	marl::lock lock(mutex);
141*03ce13f7SAndroid Build Coastguard Worker 	cv.wait(lock, [&]() { return is_signaled; });
142*03ce13f7SAndroid Build Coastguard Worker }
143*03ce13f7SAndroid Build Coastguard Worker 
signal()144*03ce13f7SAndroid Build Coastguard Worker void TimelineSemaphore::WaitForAny::signal()
145*03ce13f7SAndroid Build Coastguard Worker {
146*03ce13f7SAndroid Build Coastguard Worker 	marl::lock lock(mutex);
147*03ce13f7SAndroid Build Coastguard Worker 	if(!is_signaled)
148*03ce13f7SAndroid Build Coastguard Worker 	{
149*03ce13f7SAndroid Build Coastguard Worker 		is_signaled = true;
150*03ce13f7SAndroid Build Coastguard Worker 		cv.notify_all();
151*03ce13f7SAndroid Build Coastguard Worker 	}
152*03ce13f7SAndroid Build Coastguard Worker }
153*03ce13f7SAndroid Build Coastguard Worker 
154*03ce13f7SAndroid Build Coastguard Worker }  // namespace vk
155