• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 	shared = marl::Allocator::Default->make_shared<TimelineSemaphore::Shared>(marl::Allocator::Default, info.initialPayload);
32 }
33 
TimelineSemaphore()34 TimelineSemaphore::TimelineSemaphore()
35     : Semaphore(VK_SEMAPHORE_TYPE_TIMELINE)
36 {
37 	type = VK_SEMAPHORE_TYPE_TIMELINE;
38 	shared = marl::Allocator::Default->make_shared<TimelineSemaphore::Shared>(marl::Allocator::Default, 0);
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 	return shared->signal(value);
53 }
54 
signal(uint64_t value)55 void TimelineSemaphore::Shared::signal(uint64_t value)
56 {
57 	marl::lock lock(mutex);
58 	if(counter < value)
59 	{
60 		counter = value;
61 		cv.notify_all();
62 		for(auto dep : deps)
63 		{
64 			dep->signal(id, counter);
65 		}
66 	}
67 }
68 
wait(uint64_t value)69 void TimelineSemaphore::wait(uint64_t value)
70 {
71 	shared->wait(value);
72 }
73 
wait(uint64_t value)74 void TimelineSemaphore::Shared::wait(uint64_t value)
75 {
76 	marl::lock lock(mutex);
77 	cv.wait(lock, [&]() { return counter >= value; });
78 }
79 
getCounterValue()80 uint64_t TimelineSemaphore::getCounterValue()
81 {
82 	return shared->getCounterValue();
83 }
84 
getCounterValue()85 uint64_t TimelineSemaphore::Shared::getCounterValue()
86 {
87 	marl::lock lock(mutex);
88 	return counter;
89 }
90 
91 std::atomic<int> TimelineSemaphore::Shared::nextId;
92 
Shared(marl::Allocator * allocator,uint64_t initialState)93 TimelineSemaphore::Shared::Shared(marl::Allocator *allocator, uint64_t initialState)
94     : cv(allocator)
95     , counter(initialState)
96     , id(nextId++)
97 {
98 }
99 
signal(int parentId,uint64_t value)100 void TimelineSemaphore::Shared::signal(int parentId, uint64_t value)
101 {
102 	marl::lock lock(mutex);
103 	auto it = waitMap.find(parentId);
104 	// Either we aren't waiting for a signal, or parentId is not something we're waiting for
105 	// Reject any signals that we aren't waiting on
106 	if(counter == 0 && it != waitMap.end() && value == it->second)
107 	{
108 		// Stop waiting on all parents once we find a signal
109 		waitMap.clear();
110 		counter = 1;
111 		cv.notify_all();
112 		for(auto dep : deps)
113 		{
114 			dep->signal(id, counter);
115 		}
116 	}
117 }
118 
addDependent(TimelineSemaphore & other,uint64_t waitValue)119 void TimelineSemaphore::addDependent(TimelineSemaphore &other, uint64_t waitValue)
120 {
121 	shared->addDependent(other);
122 	other.addDependency(shared->id, waitValue);
123 }
124 
addDependent(TimelineSemaphore & other)125 void TimelineSemaphore::Shared::addDependent(TimelineSemaphore &other)
126 {
127 	marl::lock lock(mutex);
128 	deps.push_back(other.shared);
129 }
130 
addDependency(int id,uint64_t waitValue)131 void TimelineSemaphore::addDependency(int id, uint64_t waitValue)
132 {
133 	shared->addDependency(id, waitValue);
134 }
135 
addDependency(int id,uint64_t waitValue)136 void TimelineSemaphore::Shared::addDependency(int id, uint64_t waitValue)
137 {
138 	marl::lock lock(mutex);
139 	auto mapPos = waitMap.find(id);
140 	ASSERT(mapPos == waitMap.end());
141 
142 	waitMap.insert(mapPos, std::make_pair(id, waitValue));
143 }
144 
145 }  // namespace vk
146