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