Line data Source code
1 : /**
2 : Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
3 :
4 : Permission is hereby granted, free of charge, to any person obtaining a copy
5 : of this software and associated documentation files (the "Software"), to deal
6 : in the Software without restriction, including without limitation the rights
7 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 : copies of the Software, and to permit persons to whom the Software is
9 : furnished to do so, subject to the following conditions:
10 :
11 : The above copyright notice and this permission notice shall be included in
12 : all copies or substantial portions of the Software.
13 :
14 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 : THE SOFTWARE.
21 : **/
22 :
23 : #include "XLCoreObject.h"
24 : #include "XLCoreInfo.h"
25 : #include "XLCoreDevice.h"
26 : #include "SPIRV-Reflect/spirv_reflect.h"
27 :
28 : namespace STAPPLER_VERSIONIZED stappler::xenolith::core {
29 :
30 1174410 : Object::~Object() {
31 1174410 : invalidate();
32 1174410 : }
33 :
34 1174305 : bool Object::init(Device &dev, ClearCallback cb, ObjectType type, ObjectHandle handle, void *extra) {
35 1174305 : _object.device = &dev;
36 1174305 : _object.callback = cb;
37 1174305 : _object.type = type;
38 1174305 : _object.handle = handle;
39 1174305 : _object.ptr = extra;
40 1174305 : if (_object.handle.get()) {
41 643697 : _object.device->addObject(this);
42 : }
43 1174357 : return true;
44 : }
45 :
46 1705007 : void Object::invalidate() {
47 1705007 : if (_object.callback) {
48 1174378 : if (_object.handle.get()) {
49 643701 : _object.device->removeObject(this);
50 : }
51 1174378 : if (_object.callback) {
52 1174378 : _object.callback(_object.device, _object.type, _object.handle, _object.ptr);
53 : }
54 1174378 : _object.callback = nullptr;
55 1174378 : _object.device = nullptr;
56 1174378 : _object.handle = ObjectHandle::zero();
57 : }
58 1705007 : }
59 :
60 : static std::atomic<uint64_t> s_RenderPassImplCurrentIndex = 1;
61 :
62 272 : bool RenderPass::init(Device &dev, ClearCallback cb, ObjectType type, ObjectHandle ptr, void *p) {
63 272 : if (Object::init(dev, cb, type, ptr, p)) {
64 272 : _index = s_RenderPassImplCurrentIndex.fetch_add(1);
65 272 : return true;
66 : }
67 0 : return false;
68 : }
69 :
70 0 : uint64_t Framebuffer::getViewHash(SpanView<Rc<ImageView>> views) {
71 0 : Vector<uint64_t> ids; ids.reserve(views.size());
72 0 : for (auto &it : views) {
73 0 : ids.emplace_back(it->getIndex());
74 : }
75 0 : return getViewHash(ids);
76 0 : }
77 :
78 0 : uint64_t Framebuffer::getViewHash(SpanView<uint64_t> ids) {
79 0 : return hash::hash64((const char *)ids.data(), ids.size() * sizeof(uint64_t));
80 : }
81 :
82 0 : uint64_t Framebuffer::getHash() const {
83 0 : return hash::hash64((const char *)_viewIds.data(), _viewIds.size() * sizeof(uint64_t));
84 : }
85 :
86 : static std::atomic<uint64_t> s_ImageViewCurrentIndex = 1;
87 :
88 844 : bool DataAtlas::init(Type t, uint32_t count, uint32_t objectSize, Extent2 imageSize) {
89 844 : _type = t;
90 844 : _objectSize = objectSize;
91 844 : _imageExtent = imageSize;
92 844 : _data.reserve(count * objectSize);
93 844 : return true;
94 : }
95 :
96 828 : void DataAtlas::compile() {
97 828 : makeHashIndex();
98 828 : }
99 :
100 517636 : inline uint32_t hash(uint32_t k, uint32_t capacity) {
101 517636 : k ^= k >> 16;
102 517636 : k *= 0x85ebca6b;
103 517636 : k ^= k >> 13;
104 517636 : k *= 0xc2b2ae35;
105 517636 : k ^= k >> 16;
106 517636 : return k & (capacity - 1);
107 : }
108 :
109 : struct HashTableKeyValue {
110 : uint32_t key;
111 : uint32_t value;
112 : };
113 :
114 64 : const uint8_t *DataAtlas::getObjectByName(uint32_t id) const {
115 64 : if (!_dataIndex.empty()) {
116 32 : auto size = _dataIndex.size() / sizeof(HashTableKeyValue);
117 32 : uint32_t slot = hash(id, size);
118 32 : auto data = (HashTableKeyValue *)_dataIndex.data();
119 :
120 : while (true) {
121 48 : uint32_t prev = data[slot].key;
122 48 : if (prev == id) {
123 32 : return _data.data() + _objectSize * data[slot].value;
124 16 : } else if (prev == 0xffffffffU) {
125 0 : break;
126 : }
127 16 : slot = (slot + 1) & (size - 1);
128 16 : }
129 : }
130 :
131 32 : auto it = _intNames.find(id);
132 32 : if (it != _intNames.end()) {
133 32 : if (it->second < _data.size() / _objectSize) {
134 32 : return _data.data() + _objectSize * it->second;
135 : }
136 : }
137 0 : return nullptr;
138 : }
139 :
140 16 : const uint8_t *DataAtlas::getObjectByName(StringView str) const {
141 16 : auto it = _stringNames.find(str.str<Interface>());
142 16 : if (it != _stringNames.end()) {
143 16 : if (it->second < _data.size() / _objectSize) {
144 16 : return _data.data() + _objectSize * it->second;
145 : }
146 : }
147 0 : return nullptr;
148 : }
149 :
150 32 : const uint8_t *DataAtlas::getObjectByOrder(uint32_t order) const {
151 32 : if (order < _data.size() / _objectSize) {
152 16 : return _data.data() + _objectSize * order;
153 : }
154 16 : return nullptr;
155 : }
156 :
157 517604 : void DataAtlas::addObject(uint32_t id, void *data) {
158 517604 : auto off = _data.size();
159 517604 : _data.resize(off + _objectSize);
160 517604 : memcpy(_data.data() + off, data, _objectSize);
161 :
162 517604 : _intNames.emplace(id, off / _objectSize);
163 517604 : }
164 :
165 32 : void DataAtlas::addObject(StringView name, void *data) {
166 32 : auto off = _data.size();
167 32 : _data.resize(off + _objectSize);
168 32 : memcpy(_data.data() + off, data, _objectSize);
169 :
170 32 : _stringNames.emplace(name.str<Interface>(), off / _objectSize);
171 32 : }
172 :
173 812 : void DataAtlas::setIndexBuffer(Rc<BufferObject> &&index) {
174 812 : _indexBuffer = move(index);
175 812 : }
176 :
177 812 : void DataAtlas::setDataBuffer(Rc<BufferObject> &&data) {
178 812 : _dataBuffer = move(data);
179 812 : }
180 :
181 828 : void DataAtlas::makeHashIndex() {
182 828 : auto size = math::npot(_intNames.size());
183 828 : Bytes dataStorage; dataStorage.resize(size * sizeof(HashTableKeyValue), uint8_t(0xFFU));
184 828 : auto data = (HashTableKeyValue *)dataStorage.data();
185 :
186 518432 : for (auto &it : _intNames) {
187 517604 : uint32_t slot = hash(it.first, size);
188 :
189 : while (true) {
190 1510073 : uint32_t prev = data[slot].key;
191 1510073 : if (prev == 0xffffffffU || prev == it.first) {
192 517604 : data[slot].key = it.first;
193 517604 : data[slot].value = it.second;
194 517604 : break;
195 : }
196 992469 : slot = (slot + 1) & (size - 1);
197 992469 : }
198 : }
199 :
200 828 : _dataIndex = move(dataStorage);
201 828 : }
202 :
203 1116 : ImageObject::~ImageObject() { }
204 :
205 304 : bool ImageObject::init(Device &dev, ClearCallback cb, ObjectType type, ObjectHandle ptr, void *p) {
206 304 : if (Object::init(dev, cb, type, ptr, p)) {
207 304 : _index = s_ImageViewCurrentIndex.fetch_add(1);
208 304 : return true;
209 : }
210 0 : return false;
211 : }
212 812 : bool ImageObject::init(Device &dev, ClearCallback cb, ObjectType type, ObjectHandle ptr, void *p, uint64_t idx) {
213 812 : if (Object::init(dev, cb, type, ptr, p)) {
214 812 : _index = idx;
215 812 : return true;
216 : }
217 0 : return false;
218 : }
219 :
220 0 : ImageViewInfo ImageObject::getViewInfo(const ImageViewInfo &info) const {
221 0 : return _info.getViewInfo(info);
222 : }
223 :
224 1180 : ImageView::~ImageView() {
225 1180 : if (_releaseCallback) {
226 0 : _releaseCallback();
227 0 : _releaseCallback = nullptr;
228 : }
229 1180 : }
230 :
231 1180 : bool ImageView::init(Device &dev, ClearCallback cb, ObjectType type, ObjectHandle ptr, void *p) {
232 1180 : if (Object::init(dev, cb, type, ptr, p)) {
233 1180 : _index = s_ImageViewCurrentIndex.fetch_add(1);
234 1180 : return true;
235 : }
236 0 : return false;
237 : }
238 :
239 176 : void ImageView::setReleaseCallback(Function<void()> &&cb) {
240 176 : _releaseCallback = move(cb);
241 176 : }
242 :
243 176 : void ImageView::runReleaseCallback() {
244 176 : if (_releaseCallback) {
245 176 : auto cb = move(_releaseCallback);
246 176 : _releaseCallback = nullptr;
247 176 : cb();
248 176 : }
249 176 : }
250 :
251 0 : Extent3 ImageView::getExtent() const {
252 0 : return _image->getInfo().extent;
253 : }
254 :
255 36970 : uint32_t ImageView::getLayerCount() const {
256 36970 : return _info.layerCount.get();
257 : }
258 :
259 36970 : Extent3 ImageView::getFramebufferExtent() const {
260 36970 : return Extent3(_image->getInfo().extent.width, _image->getInfo().extent.height, getLayerCount());
261 : }
262 :
263 31944 : void CommandBuffer::bindImage(ImageObject *image) {
264 31944 : _images.emplace(image);
265 31944 : }
266 :
267 1770331 : void CommandBuffer::bindBuffer(BufferObject *buffer) {
268 1770331 : _buffers.emplace(buffer);
269 1770331 : }
270 :
271 7322 : void CommandBuffer::bindFramebuffer(Framebuffer *fb) {
272 7322 : _framebuffers.emplace(fb);
273 7322 : }
274 :
275 0 : void TextureSet::write(const MaterialLayout &set) {
276 0 : _layoutIndexes.clear();
277 0 : for (uint32_t i = 0; i < set.usedImageSlots; ++ i) {
278 0 : if (set.imageSlots[i].image) {
279 0 : _layoutIndexes.emplace_back(set.imageSlots[i].image->getIndex());
280 : } else {
281 0 : _layoutIndexes.emplace_back(0);
282 : }
283 : }
284 :
285 0 : _layoutIndexes.resize(_count, 0);
286 0 : }
287 :
288 16 : String Shader::inspectShader(SpanView<uint32_t> data) {
289 : SpvReflectShaderModule shader;
290 :
291 16 : spvReflectCreateShaderModule(data.size() * sizeof(uint32_t), data.data(), &shader);
292 :
293 16 : ProgramStage stage = ProgramStage::None;
294 16 : switch (shader.spirv_execution_model) {
295 0 : case SpvExecutionModelVertex: stage = ProgramStage::Vertex; break;
296 0 : case SpvExecutionModelTessellationControl: stage = ProgramStage::TesselationControl; break;
297 0 : case SpvExecutionModelTessellationEvaluation: stage = ProgramStage::TesselationEvaluation; break;
298 0 : case SpvExecutionModelGeometry: stage = ProgramStage::Geometry; break;
299 0 : case SpvExecutionModelFragment: stage = ProgramStage::Fragment; break;
300 16 : case SpvExecutionModelGLCompute: stage = ProgramStage::Compute; break;
301 0 : case SpvExecutionModelKernel: stage = ProgramStage::Compute; break;
302 0 : case SpvExecutionModelTaskNV: stage = ProgramStage::Task; break;
303 0 : case SpvExecutionModelMeshNV: stage = ProgramStage::Mesh; break;
304 0 : case SpvExecutionModelRayGenerationKHR: stage = ProgramStage::RayGen; break;
305 0 : case SpvExecutionModelIntersectionKHR: stage = ProgramStage::Intersection; break;
306 0 : case SpvExecutionModelAnyHitKHR: stage = ProgramStage::AnyHit; break;
307 0 : case SpvExecutionModelClosestHitKHR: stage = ProgramStage::ClosestHit; break;
308 0 : case SpvExecutionModelMissKHR: stage = ProgramStage::MissHit; break;
309 0 : case SpvExecutionModelCallableKHR: stage = ProgramStage::Callable; break;
310 0 : default: break;
311 : }
312 :
313 32 : StringStream out;
314 :
315 16 : out << "[" << getProgramStageDescription(stage) << "]\n";
316 :
317 80 : for (auto &it : makeSpanView(shader.descriptor_bindings, shader.descriptor_binding_count)) {
318 64 : out << "\tBinging: [" << it.set << ":" << it.binding << "] "
319 64 : << getDescriptorTypeName(DescriptorType(it.descriptor_type)) << "\n";
320 : }
321 :
322 16 : for (auto &it : makeSpanView(shader.push_constant_blocks, shader.push_constant_block_count)) {
323 0 : out << "\tPushConstant: [" << it.absolute_offset << " - " << it.padded_size << "]\n";
324 : }
325 :
326 16 : spvReflectDestroyShaderModule(&shader);
327 :
328 32 : return out.str();
329 : }
330 :
331 0 : String Shader::inspect(SpanView<uint32_t> data) {
332 0 : return inspectShader(data);
333 : }
334 :
335 132658 : void Semaphore::setSignaled(bool value) {
336 132658 : _signaled = value;
337 132658 : }
338 :
339 132498 : void Semaphore::setWaited(bool value) {
340 132498 : _waited = value;
341 132498 : }
342 :
343 250576 : void Semaphore::setInUse(bool value, uint64_t timeline) {
344 250576 : if (timeline == _timeline) {
345 250576 : _inUse = value;
346 : }
347 250576 : }
348 :
349 30254 : bool Semaphore::reset() {
350 30254 : if (_signaled == _waited) {
351 30222 : _signaled = false;
352 30222 : _waited = false;
353 30222 : _inUse = false;
354 30222 : ++ _timeline;
355 30222 : return true;
356 : }
357 32 : return false;
358 : }
359 :
360 : }
|