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 "XL2dVkShadow.h"
24 : #include "XLCoreFrameHandle.h"
25 : #include "XLCoreFrameQueue.h"
26 : #include "XLCoreFrameCache.h"
27 : #include "XLCoreFrameRequest.h"
28 :
29 : namespace STAPPLER_VERSIONIZED stappler::xenolith::basic2d::vk {
30 :
31 9300 : ShadowLightDataAttachmentHandle::~ShadowLightDataAttachmentHandle() { }
32 :
33 4640 : void ShadowLightDataAttachmentHandle::submitInput(FrameQueue &q, Rc<core::AttachmentInputData> &&data, Function<void(bool)> &&cb) {
34 4640 : auto d = data.cast<FrameContextHandle2d>();
35 4640 : if (!d || q.isFinalized()) {
36 0 : cb(false);
37 0 : return;
38 : }
39 :
40 4640 : q.getFrame()->waitForDependencies(data->waitDependencies, [this, d = move(d), cb = move(cb)] (FrameHandle &handle, bool success) mutable {
41 4640 : if (!success || !handle.isValidFlag()) {
42 0 : cb(false);
43 0 : return;
44 : }
45 :
46 4640 : auto devFrame = static_cast<DeviceFrameHandle *>(&handle);
47 :
48 4640 : _input = move(d);
49 13920 : _data = devFrame->getMemPool(devFrame)->spawn(AllocationUsage::DeviceLocalHostVisible,
50 13920 : BufferInfo(static_cast<BufferAttachment *>(_attachment.get())->getInfo(), sizeof(ShadowData)));
51 4640 : cb(true);
52 : });
53 4640 : }
54 :
55 9280 : bool ShadowLightDataAttachmentHandle::isDescriptorDirty(const PassHandle &, const PipelineDescriptor &,
56 : uint32_t, bool isExternal) const {
57 9280 : if (_data) {
58 9280 : return true;
59 : }
60 0 : return false;
61 : }
62 :
63 9280 : bool ShadowLightDataAttachmentHandle::writeDescriptor(const core::QueuePassHandle &, DescriptorBufferInfo &info) {
64 9280 : switch (info.index) {
65 9280 : case 0:
66 9280 : info.buffer = _data;
67 9280 : info.offset = 0;
68 9280 : info.range = _data->getSize();
69 9280 : return true;
70 : break;
71 0 : default:
72 0 : break;
73 : }
74 0 : return false;
75 : }
76 :
77 4640 : void ShadowLightDataAttachmentHandle::allocateBuffer(DeviceFrameHandle *devFrame, const ShadowVertexAttachmentHandle *vertexes, uint32_t gridSize) {
78 4640 : _data->map([&, this] (uint8_t *buf, VkDeviceSize size) {
79 4640 : ShadowData *data = reinterpret_cast<ShadowData *>(buf);
80 :
81 4640 : if (isnan(_input->lights.luminosity)) {
82 4640 : float l = _input->lights.globalColor.a;
83 13920 : for (uint32_t i = 0; i < _input->lights.ambientLightCount; ++ i) {
84 9280 : l += _input->lights.ambientLights[i].color.a;
85 : }
86 4640 : for (uint32_t i = 0; i < _input->lights.directLightCount; ++ i) {
87 0 : l += _input->lights.directLights[i].color.a;
88 : }
89 4640 : _shadowData.luminosity = data->luminosity = 1.0f / l;
90 : } else {
91 0 : _shadowData.luminosity = data->luminosity = 1.0f / _input->lights.luminosity;
92 : }
93 :
94 4640 : float fullDensity = _input->lights.sceneDensity;
95 4640 : auto screenSize = devFrame->getFrameConstraints().getScreenSize();
96 :
97 4640 : Extent2 scaledExtent(ceilf(screenSize.width / fullDensity), ceilf(screenSize.height / fullDensity));
98 :
99 : //float shadowDensity = _input->lights.sceneDensity / _input->lights.shadowDensity;
100 : //Extent2 shadowExtent(ceilf(screenSize.width / shadowDensity), ceilf(screenSize.height / shadowDensity));
101 : //Vec2 shadowOffset( screenSize.width / shadowDensity - shadowExtent.width, screenSize.height / shadowDensity - shadowExtent.height);
102 : //shadowOffset *= shadowDensity;
103 4640 : _shadowData.globalColor = data->globalColor = _input->lights.globalColor * data->luminosity;
104 :
105 : // pre-calculated color with no shadows
106 4640 : Color4F discardColor = _shadowData.globalColor;
107 13920 : for (uint32_t i = 0; i < _input->lights.ambientLightCount; ++ i) {
108 9280 : auto a = _input->lights.ambientLights[i].color.a * data->luminosity;
109 9280 : auto ncolor = (_input->lights.ambientLights[i].color * _input->lights.ambientLights[i].color.a) * data->luminosity;
110 9280 : ncolor.a = a;
111 9280 : discardColor = discardColor + ncolor;
112 : }
113 4640 : discardColor.a = 1.0f;
114 4640 : _shadowData.discardColor = data->discardColor = discardColor;
115 :
116 4640 : _shadowData.gridSize = data->gridSize = ceilf(gridSize / fullDensity);
117 4640 : _shadowData.gridWidth = data->gridWidth = (scaledExtent.width - 1) / data->gridSize + 1;
118 4640 : _shadowData.gridHeight = data->gridHeight = (scaledExtent.height - 1) / data->gridSize + 1;
119 4640 : _shadowData.objectsCount = data->objectsCount = vertexes->getTrianglesCount() + vertexes->getCirclesCount()
120 4640 : + vertexes->getRectsCount() + vertexes->getRoundedRectsCount() + vertexes->getPolygonsCount();
121 :
122 4640 : _shadowData.trianglesFirst = data->trianglesFirst = 0;
123 4640 : _shadowData.trianglesCount = data->trianglesCount = vertexes->getTrianglesCount();
124 :
125 4640 : _shadowData.circlesFirst = data->circlesFirst = _shadowData.trianglesFirst + _shadowData.trianglesCount;
126 4640 : _shadowData.circlesCount = data->circlesCount = vertexes->getCirclesCount();
127 :
128 4640 : _shadowData.rectsFirst = data->rectsFirst = _shadowData.circlesFirst + _shadowData.circlesCount;
129 4640 : _shadowData.rectsCount = data->rectsCount = vertexes->getRectsCount();
130 :
131 4640 : _shadowData.roundedRectsFirst = data->roundedRectsFirst = _shadowData.rectsFirst + _shadowData.rectsCount;
132 4640 : _shadowData.roundedRectsCount = data->roundedRectsCount = vertexes->getRoundedRectsCount();
133 :
134 4640 : _shadowData.polygonsFirst = data->polygonsFirst = _shadowData.roundedRectsFirst + _shadowData.roundedRectsCount;
135 4640 : _shadowData.polygonsCount = data->polygonsCount = vertexes->getPolygonsCount();
136 :
137 4640 : _shadowData.ambientLightCount = data->ambientLightCount = _input->lights.ambientLightCount;
138 4640 : _shadowData.directLightCount = data->directLightCount = _input->lights.directLightCount;
139 4640 : _shadowData.maxValue = data->maxValue = vertexes->getMaxValue();
140 4640 : _shadowData.bbOffset = data->bbOffset = getBoxOffset(_shadowData.maxValue);
141 4640 : _shadowData.density = data->density = _input->lights.sceneDensity;
142 4640 : _shadowData.shadowSdfDensity = data->shadowSdfDensity = 1.0f / _input->lights.shadowDensity;
143 4640 : _shadowData.shadowDensity = data->shadowDensity = 1.0f / _input->lights.sceneDensity;
144 4640 : _shadowData.pix = data->pix = Vec2(1.0f / float(screenSize.width), 1.0f / float(screenSize.height));
145 :
146 4640 : memcpy(data->ambientLights, _input->lights.ambientLights, sizeof(AmbientLightData) * config::MaxAmbientLights);
147 4640 : memcpy(data->directLights, _input->lights.directLights, sizeof(DirectLightData) * config::MaxDirectLights);
148 4640 : memcpy(_shadowData.ambientLights, _input->lights.ambientLights, sizeof(AmbientLightData) * config::MaxAmbientLights);
149 4640 : memcpy(_shadowData.directLights, _input->lights.directLights, sizeof(DirectLightData) * config::MaxDirectLights);
150 4640 : });
151 4640 : }
152 :
153 4640 : float ShadowLightDataAttachmentHandle::getBoxOffset(float value) const {
154 4640 : value = std::max(value, 2.0f);
155 4640 : float bbox = 0.0f;
156 13920 : for (size_t i = 0; i < _input->lights.ambientLightCount; ++ i) {
157 9280 : auto &l = _input->lights.ambientLights[i];
158 9280 : float n_2 = l.normal.x * l.normal.x + l.normal.y * l.normal.y;
159 9280 : float m = std::sqrt(n_2) / std::sqrt(1 - n_2);
160 :
161 9280 : bbox = std::max((m * value * 2.0f) + (std::ceil(l.normal.w * value)), bbox);
162 : }
163 4640 : return bbox;
164 : }
165 :
166 13920 : uint32_t ShadowLightDataAttachmentHandle::getLightsCount() const {
167 13920 : return _input->lights.ambientLightCount + _input->lights.directLightCount;
168 : }
169 :
170 13920 : uint32_t ShadowLightDataAttachmentHandle::getObjectsCount() const {
171 13920 : return _shadowData.objectsCount;
172 : }
173 :
174 9300 : ShadowVertexAttachmentHandle::~ShadowVertexAttachmentHandle() { }
175 :
176 4640 : void ShadowVertexAttachmentHandle::submitInput(FrameQueue &q, Rc<core::AttachmentInputData> &&data, Function<void(bool)> &&cb) {
177 4640 : auto d = data.cast<FrameContextHandle2d>();
178 4640 : if (!d || q.isFinalized()) {
179 0 : cb(false);
180 0 : return;
181 : }
182 :
183 4640 : q.getFrame()->waitForDependencies(data->waitDependencies, [this, d = move(d), cb = move(cb)] (FrameHandle &handle, bool success) {
184 4640 : if (!success || !handle.isValidFlag()) {
185 0 : cb(false);
186 0 : return;
187 : }
188 :
189 9280 : handle.performInQueue([this, d = move(d)] (FrameHandle &handle) {
190 4640 : return loadVertexes(handle, d);
191 4640 : }, [cb = move(cb)] (FrameHandle &handle, bool success) {
192 4640 : cb(success);
193 4640 : }, this, "VertexMaterialAttachmentHandle::submitInput");
194 : });
195 4640 : }
196 :
197 0 : bool ShadowVertexAttachmentHandle::empty() const {
198 0 : return !_indexes || !_vertexes || !_transforms || !_circles || !_rects || !_roundedRects || !_polygons;
199 : }
200 :
201 : struct ShadowDrawPlan {
202 : struct PlanCommandInfo {
203 : const CmdShadow *cmd;
204 : SpanView<TransformVertexData> vertexes;
205 : };
206 :
207 : struct PladSdfCommand {
208 : const CmdSdfGroup2D *cmd;
209 : uint32_t triangles = 0;
210 : uint32_t objects = 0;
211 : };
212 :
213 4640 : ShadowDrawPlan(core::FrameHandle &fhandle) : pool(fhandle.getPool()->getPool()) {
214 :
215 4640 : }
216 :
217 3170 : void emplaceWritePlan(const Command *c, const CmdShadow *cmd, SpanView<TransformVertexData> v) {
218 6340 : for (auto &iit : v) {
219 3170 : vertexes += iit.data->data.size();
220 3170 : indexes += iit.data->indexes.size();
221 3170 : ++ transforms;
222 : }
223 :
224 3170 : commands.emplace_front(PlanCommandInfo{cmd, v});
225 3170 : }
226 :
227 3170 : void pushDeferred(const Command *c, const CmdShadowDeferred *cmd) {
228 3170 : if (!cmd->deferred->isWaitOnReady()) {
229 0 : if (!cmd->deferred->isReady()) {
230 0 : return;
231 : }
232 : }
233 :
234 3170 : auto vertexes = cmd->deferred->getData().pdup(pool);
235 :
236 : // apply transforms;
237 3170 : if (cmd->normalized) {
238 0 : for (auto &it : vertexes) {
239 0 : auto modelTransform = cmd->modelTransform * it.transform;
240 :
241 0 : Mat4 newMV;
242 0 : newMV.m[12] = floorf(modelTransform.m[12]);
243 0 : newMV.m[13] = floorf(modelTransform.m[13]);
244 0 : newMV.m[14] = floorf(modelTransform.m[14]);
245 :
246 0 : const_cast<TransformVertexData &>(it).transform = newMV;
247 : }
248 : } else {
249 6340 : for (auto &it : vertexes) {
250 3170 : const_cast<TransformVertexData &>(it).transform = cmd->modelTransform * it.transform;
251 : }
252 : }
253 :
254 3170 : emplaceWritePlan(c, cmd, vertexes);
255 : }
256 :
257 4691 : void pushSdf(const Command *c, const CmdSdfGroup2D *cmd) {
258 4691 : uint32_t objects = 0;
259 4691 : uint32_t triangles = 0;
260 9382 : for (auto &it : cmd->data) {
261 4691 : switch (it.type) {
262 634 : case SdfShape::Circle2D: ++ circles; ++ objects; ++ vertexes; break;
263 984 : case SdfShape::Rect2D: ++ rects; ++ objects; ++ vertexes; break;
264 1435 : case SdfShape::RoundedRect2D: ++ roundedRects; ++ objects; vertexes += 2; break;
265 634 : case SdfShape::Triangle2D: vertexes += 3; indexes += 3; ++ triangles; break;
266 1004 : case SdfShape::Polygon2D: {
267 1004 : auto data = reinterpret_cast<const SdfPolygon2D *>(it.bytes.data());
268 1004 : vertexes += data->points.size(); ++ triangles;
269 1004 : ++ polygons;
270 1004 : break;
271 : }
272 0 : default: break;
273 : }
274 : }
275 4691 : if (objects > 0 || triangles > 0) {
276 4691 : if (objects > 0) {
277 3053 : ++ transforms;
278 : }
279 4691 : if (triangles > 0) {
280 1638 : ++ transforms;
281 : }
282 4691 : sdfCommands.emplace_front(PladSdfCommand{cmd, triangles, objects});
283 : }
284 4691 : }
285 :
286 : memory::pool_t *pool = nullptr;
287 : uint32_t vertexes = 0;
288 : uint32_t indexes = 0;
289 : uint32_t transforms = 0;
290 : uint32_t circles = 0;
291 : uint32_t rects = 0;
292 : uint32_t roundedRects = 0;
293 : uint32_t polygons = 0;
294 : std::forward_list<PlanCommandInfo> commands;
295 : std::forward_list<PladSdfCommand> sdfCommands;
296 : };
297 :
298 : struct ShadowBufferMap {
299 : uint8_t *region;
300 : Bytes external;
301 : Buffer *buffer;
302 : bool isPersistent = false;
303 :
304 7735 : ~ShadowBufferMap() {
305 7735 : if (isPersistent) {
306 7735 : buffer->flushMappedRegion();
307 : } else {
308 0 : buffer->setData(external);
309 : }
310 7735 : }
311 :
312 7735 : ShadowBufferMap(Buffer *b, bool persistent) : buffer(b), isPersistent(persistent) {
313 7735 : if (isPersistent) {
314 7735 : region = buffer->getPersistentMappedRegion();
315 : } else {
316 0 : external.resize(buffer->getSize());
317 0 : region = external.data();
318 : }
319 7735 : }
320 : };
321 :
322 4640 : bool ShadowVertexAttachmentHandle::loadVertexes(FrameHandle &fhandle, const Rc<FrameContextHandle2d> &commands) {
323 4640 : auto handle = dynamic_cast<DeviceFrameHandle *>(&fhandle);
324 4640 : if (!handle) {
325 0 : return false;
326 : }
327 :
328 : // fill write plan
329 :
330 4640 : ShadowDrawPlan plan(fhandle);
331 :
332 4640 : auto cmd = commands->shadows->getFirst();
333 12501 : while (cmd) {
334 7861 : switch (cmd->type) {
335 0 : case CommandType::CommandGroup:
336 : case CommandType::VertexArray:
337 : case CommandType::Deferred:
338 0 : break;
339 0 : case CommandType::ShadowArray:
340 0 : plan.emplaceWritePlan(cmd, reinterpret_cast<const CmdShadowArray *>(cmd->data),
341 0 : reinterpret_cast<const CmdShadowArray *>(cmd->data)->vertexes);
342 0 : break;
343 3170 : case CommandType::ShadowDeferred:
344 3170 : plan.pushDeferred(cmd, reinterpret_cast<const CmdShadowDeferred *>(cmd->data));
345 3170 : break;
346 4691 : case CommandType::SdfGroup2D:
347 4691 : plan.pushSdf(cmd, reinterpret_cast<const CmdSdfGroup2D *>(cmd->data));
348 4691 : break;
349 : }
350 7861 : cmd = cmd->next;
351 : }
352 :
353 4640 : if (plan.vertexes == 0 && plan.indexes == 0 && plan.circles == 0) {
354 3535 : return true;
355 : }
356 :
357 1105 : auto &info = reinterpret_cast<BufferAttachment *>(_attachment.get())->getInfo();
358 :
359 : // create buffers
360 1105 : auto &pool = handle->getMemPool(handle);
361 3315 : _indexes = pool->spawn(AllocationUsage::DeviceLocalHostVisible,
362 3315 : BufferInfo(info, std::max((plan.indexes / 3), uint32_t(1)) * sizeof(Triangle2DIndex)));
363 :
364 3315 : _vertexes = pool->spawn(AllocationUsage::DeviceLocalHostVisible,
365 3315 : BufferInfo(info, std::max(plan.vertexes, uint32_t(1)) * sizeof(Vec4)));
366 :
367 3315 : _transforms = pool->spawn(AllocationUsage::DeviceLocalHostVisible,
368 3315 : BufferInfo(info, std::max((plan.transforms + 1), uint32_t(1)) * sizeof(TransformData)));
369 :
370 3315 : _circles = pool->spawn(AllocationUsage::DeviceLocalHostVisible,
371 3315 : BufferInfo(info, std::max(plan.circles, uint32_t(1)) * sizeof(Circle2DIndex)));
372 :
373 3315 : _rects = pool->spawn(AllocationUsage::DeviceLocalHostVisible,
374 3315 : BufferInfo(info, std::max(plan.rects, uint32_t(1)) * sizeof(Rect2DIndex)));
375 :
376 3315 : _roundedRects = pool->spawn(AllocationUsage::DeviceLocalHostVisible,
377 3315 : BufferInfo(info, std::max(plan.roundedRects, uint32_t(1)) * sizeof(RoundedRect2DIndex)));
378 :
379 3315 : _polygons = pool->spawn(AllocationUsage::DeviceLocalHostVisible,
380 3315 : BufferInfo(info, std::max(plan.polygons, uint32_t(1)) * sizeof(Polygon2DIndex)));
381 :
382 1105 : if (!_vertexes || !_indexes || !_transforms || !_circles || !_rects || !_roundedRects || !_polygons) {
383 0 : return false;
384 : }
385 :
386 2210 : ShadowBufferMap vertexesMap(_vertexes, fhandle.isPersistentMapping());
387 2210 : ShadowBufferMap indexesMap(_indexes, fhandle.isPersistentMapping());
388 2210 : ShadowBufferMap transformMap(_transforms, fhandle.isPersistentMapping());
389 2210 : ShadowBufferMap circlesMap(_circles, fhandle.isPersistentMapping());
390 2210 : ShadowBufferMap rectsMap(_rects, fhandle.isPersistentMapping());
391 2210 : ShadowBufferMap roundedRectsMap(_roundedRects, fhandle.isPersistentMapping());
392 1105 : ShadowBufferMap polygonsMap(_polygons, fhandle.isPersistentMapping());
393 :
394 1105 : TransformData val;
395 1105 : memcpy(transformMap.region, &val, sizeof(TransformData));
396 :
397 1105 : uint32_t vertexOffset = 0;
398 1105 : uint32_t indexOffset = 0;
399 1105 : uint32_t circleOffset = 0;
400 1105 : uint32_t rectOffset = 0;
401 1105 : uint32_t roundedRectOffset = 0;
402 1105 : uint32_t polygonsOffset = 0;
403 :
404 1105 : uint32_t materialVertexes = 0;
405 1105 : uint32_t materialIndexes = 0;
406 1105 : uint32_t transformIdx = 1;
407 :
408 300902 : auto pushVertexes = [&, this] (const CmdShadow *cmd, const TransformData &transform, VertexData *vertexes) {
409 452938 : auto target = reinterpret_cast<Vec4 *>(vertexesMap.region) + vertexOffset;
410 :
411 155206 : memcpy(transformMap.region + sizeof(TransformData) * transformIdx, &transform, sizeof(TransformData));
412 :
413 108754 : for (size_t idx = 0; idx < vertexes->data.size(); ++ idx) {
414 105584 : memcpy(target++, &vertexes->data[idx].pos, sizeof(Vec4));
415 : }
416 :
417 6340 : auto indexTarget = reinterpret_cast<Triangle2DIndex *>(indexesMap.region) + indexOffset;
418 :
419 152036 : for (size_t idx = 0; idx < vertexes->indexes.size() / 3; ++ idx) {
420 148866 : Triangle2DIndex data({
421 148866 : vertexes->indexes[idx * 3 + 0] + vertexOffset,
422 297732 : vertexes->indexes[idx * 3 + 1] + vertexOffset,
423 297732 : vertexes->indexes[idx * 3 + 2] + vertexOffset,
424 148866 : transformIdx,
425 148866 : cmd->value,
426 : 1.0f
427 148866 : });
428 148866 : memcpy(indexTarget++, &data, sizeof(Triangle2DIndex));
429 :
430 148866 : _maxValue = std::max(_maxValue, cmd->value);
431 : }
432 :
433 3170 : vertexOffset += vertexes->data.size();
434 3170 : indexOffset += vertexes->indexes.size() / 3;
435 3170 : ++ transformIdx;
436 :
437 3170 : materialVertexes += vertexes->data.size();
438 3170 : materialIndexes += vertexes->indexes.size();
439 4275 : };
440 :
441 4275 : for (auto &cmd : plan.commands) {
442 6340 : for (auto &iit : cmd.vertexes) {
443 3170 : pushVertexes(cmd.cmd, iit.transform, iit.data);
444 : }
445 : }
446 :
447 14073 : auto pushSdf = [&, this] (const CmdSdfGroup2D *cmd, uint32_t triangles, uint32_t objects) {
448 10386 : auto target = reinterpret_cast<Vec4 *>(vertexesMap.region) + vertexOffset;
449 :
450 4691 : uint32_t transformTriangles = 0;
451 4691 : uint32_t transformObjects = 0;
452 :
453 4691 : if (triangles > 0) {
454 1638 : TransformData transform(cmd->modelTransform);
455 4691 : memcpy(transformMap.region + sizeof(TransformData) * transformIdx, &transform, sizeof(TransformData));
456 1638 : transformTriangles = transformIdx;
457 1638 : ++ transformIdx;
458 : }
459 :
460 4691 : if (objects > 0) {
461 3053 : TransformData transform(cmd->modelTransform.getInversed());
462 3053 : cmd->modelTransform.getScale(&transform.padding.x);
463 3053 : memcpy(transformMap.region + sizeof(TransformData) * transformIdx, &transform, sizeof(TransformData));
464 3053 : transformObjects = transformIdx;
465 3053 : ++ transformIdx;
466 : }
467 :
468 9382 : for (auto &it : cmd->data) {
469 4691 : switch (it.type) {
470 634 : case SdfShape::Circle2D: {
471 634 : auto data = reinterpret_cast<const SdfCircle2D *>(it.bytes.data());
472 634 : auto pos = Vec4(data->origin, 0.0f, data->radius);
473 :
474 634 : memcpy(target++, &pos, sizeof(Vec4));
475 :
476 : Circle2DIndex index;
477 634 : index.origin = vertexOffset;
478 634 : index.transform = transformObjects;
479 634 : index.value = cmd->value;
480 634 : index.opacity = cmd->opacity;
481 :
482 634 : memcpy(reinterpret_cast<Circle2DIndex *>(circlesMap.region) + circleOffset, &index, sizeof(Circle2DIndex));
483 :
484 634 : ++ circleOffset;
485 634 : ++ vertexOffset;
486 634 : break;
487 : }
488 984 : case SdfShape::Rect2D: {
489 984 : auto data = reinterpret_cast<const SdfRect2D *>(it.bytes.data());
490 984 : auto pos = Vec4(data->origin, data->size);
491 :
492 984 : memcpy(target++, &pos, sizeof(Vec4));
493 :
494 : Rect2DIndex index;
495 984 : index.origin = vertexOffset;
496 984 : index.transform = transformObjects;
497 984 : index.value = cmd->value;
498 984 : index.opacity = cmd->opacity;
499 :
500 984 : memcpy(reinterpret_cast<Rect2DIndex *>(rectsMap.region) + rectOffset, &index, sizeof(Rect2DIndex));
501 :
502 984 : ++ rectOffset;
503 984 : ++ vertexOffset;
504 984 : break;
505 : }
506 1435 : case SdfShape::RoundedRect2D: {
507 1435 : auto data = reinterpret_cast<const SdfRoundedRect2D *>(it.bytes.data());
508 1435 : auto pos = Vec4(data->origin, data->size);
509 :
510 1435 : memcpy(target++, &pos, sizeof(Vec4));
511 1435 : memcpy(target++, &data->radius, sizeof(Vec4));
512 :
513 : RoundedRect2DIndex index;
514 1435 : index.origin = vertexOffset;
515 1435 : index.transform = transformObjects;
516 1435 : index.value = cmd->value;
517 1435 : index.opacity = cmd->opacity;
518 :
519 1435 : memcpy(reinterpret_cast<RoundedRect2DIndex *>(roundedRectsMap.region) + roundedRectOffset, &index, sizeof(RoundedRect2DIndex));
520 :
521 1435 : ++ roundedRectOffset;
522 1435 : vertexOffset += 2;
523 1435 : break;
524 : }
525 634 : case SdfShape::Triangle2D: {
526 634 : auto data = reinterpret_cast<const SdfTriangle2D *>(it.bytes.data());
527 : Vec4 vertexes[3] = {
528 1268 : Vec4(data->origin + data->a, 0.0f, 1.0f),
529 1268 : Vec4(data->origin + data->b, 0.0f, 1.0f),
530 1268 : Vec4(data->origin + data->c, 0.0f, 1.0f),
531 634 : };
532 634 : memcpy(target, vertexes, sizeof(Vec4) * 3);
533 634 : target += 3;
534 :
535 : Triangle2DIndex triangle({
536 634 : vertexOffset,
537 634 : vertexOffset + 1,
538 634 : vertexOffset + 2,
539 : transformTriangles,
540 634 : cmd->value,
541 634 : cmd->opacity
542 634 : });
543 :
544 634 : memcpy(reinterpret_cast<Triangle2DIndex *>(indexesMap.region) + indexOffset, &triangle, sizeof(Triangle2DIndex));
545 :
546 634 : ++ indexOffset;
547 634 : vertexOffset += 3;
548 634 : break;
549 : }
550 1004 : case SdfShape::Polygon2D: {
551 1004 : auto data = reinterpret_cast<const SdfPolygon2D *>(it.bytes.data());
552 6500 : for (auto &it : data->points) {
553 5496 : Vec4 pt(it, 0, 1);
554 5496 : memcpy(target++, &pt, sizeof(Vec4));
555 : }
556 :
557 1004 : Polygon2DIndex polygon({
558 1004 : vertexOffset,
559 1004 : uint32_t(data->points.size()),
560 : transformTriangles,
561 : uint32_t(0),
562 1004 : cmd->value,
563 1004 : cmd->opacity
564 1004 : });
565 :
566 2008 : memcpy(reinterpret_cast<Polygon2DIndex *>(polygonsMap.region) + polygonsOffset, &polygon, sizeof(Polygon2DIndex));
567 :
568 1004 : vertexOffset += data->points.size();
569 1004 : ++ polygonsOffset;
570 1004 : break;
571 : }
572 0 : default: break;
573 : }
574 : }
575 :
576 4691 : _maxValue = std::max(_maxValue, cmd->value);
577 4691 : };
578 :
579 5796 : for (auto &cmd : plan.sdfCommands) {
580 4691 : pushSdf(cmd.cmd, cmd.triangles, cmd.objects);
581 : }
582 :
583 1105 : _trianglesCount = plan.indexes / 3;
584 1105 : _circlesCount = plan.circles;
585 1105 : _rectsCount = plan.rects;
586 1105 : _roundedRectsCount = plan.roundedRects;
587 1105 : _polygonsCount = plan.polygons;
588 :
589 1105 : addBufferView(_indexes);
590 1105 : addBufferView(_vertexes);
591 1105 : addBufferView(_transforms);
592 1105 : addBufferView(_circles);
593 1105 : addBufferView(_rects);
594 1105 : addBufferView(_roundedRects);
595 1105 : addBufferView(_polygons);
596 :
597 1105 : return true;
598 4640 : }
599 :
600 9300 : ShadowPrimitivesAttachmentHandle::~ShadowPrimitivesAttachmentHandle() { }
601 :
602 1105 : void ShadowPrimitivesAttachmentHandle::allocateBuffer(DeviceFrameHandle *devFrame, const ShadowData &data) {
603 1105 : auto &pool = devFrame->getMemPool(devFrame);
604 :
605 3315 : _objects = pool->spawn(AllocationUsage::DeviceLocal, BufferInfo(core::BufferUsage::StorageBuffer,
606 2210 : std::max(uint32_t(1), data.objectsCount) * sizeof(Sdf2DObjectData)));
607 3315 : _gridSize = pool->spawn(AllocationUsage::DeviceLocal, BufferInfo(core::BufferUsage::StorageBuffer,
608 2210 : data.gridWidth * data.gridHeight * sizeof(uint32_t)));
609 3315 : _gridIndex = pool->spawn(AllocationUsage::DeviceLocal, BufferInfo(core::BufferUsage::StorageBuffer,
610 2210 : std::max(uint32_t(1), data.objectsCount) * data.gridWidth * data.gridHeight * sizeof(uint32_t)));
611 :
612 1105 : addBufferView(_objects);
613 1105 : addBufferView(_gridSize);
614 1105 : addBufferView(_gridIndex);
615 1105 : }
616 :
617 :
618 20 : ShadowLightDataAttachment::~ShadowLightDataAttachment() { }
619 :
620 10 : bool ShadowLightDataAttachment::init(AttachmentBuilder &builder) {
621 10 : if (BufferAttachment::init(builder, BufferInfo(core::BufferUsage::UniformBuffer, size_t(sizeof(ShadowData))))) {
622 10 : return true;
623 : }
624 0 : return false;
625 : }
626 :
627 4650 : bool ShadowLightDataAttachment::validateInput(const Rc<core::AttachmentInputData> &data) const {
628 4650 : if (dynamic_cast<FrameContextHandle2d *>(data.get())) {
629 4650 : return true;
630 : }
631 0 : return false;
632 : }
633 :
634 4650 : auto ShadowLightDataAttachment::makeFrameHandle(const FrameQueue &handle) -> Rc<AttachmentHandle> {
635 9300 : return Rc<ShadowLightDataAttachmentHandle>::create(this, handle);
636 : }
637 :
638 20 : ShadowVertexAttachment::~ShadowVertexAttachment() { }
639 :
640 10 : bool ShadowVertexAttachment::init(AttachmentBuilder &builder) {
641 10 : if (BufferAttachment::init(builder, BufferInfo(core::BufferUsage::StorageBuffer))) {
642 10 : return true;
643 : }
644 0 : return false;
645 : }
646 :
647 4650 : bool ShadowVertexAttachment::validateInput(const Rc<core::AttachmentInputData> &data) const {
648 4650 : if (dynamic_cast<FrameContextHandle2d *>(data.get())) {
649 4650 : return true;
650 : }
651 0 : return false;
652 : }
653 :
654 4650 : auto ShadowVertexAttachment::makeFrameHandle(const FrameQueue &handle) -> Rc<AttachmentHandle> {
655 9300 : return Rc<ShadowVertexAttachmentHandle>::create(this, handle);
656 : }
657 :
658 20 : ShadowPrimitivesAttachment::~ShadowPrimitivesAttachment() { }
659 :
660 10 : bool ShadowPrimitivesAttachment::init(AttachmentBuilder &builder) {
661 10 : if (BufferAttachment::init(builder, BufferInfo(core::BufferUsage::StorageBuffer))) {
662 10 : return true;
663 : }
664 0 : return false;
665 : }
666 :
667 4650 : auto ShadowPrimitivesAttachment::makeFrameHandle(const FrameQueue &handle) -> Rc<AttachmentHandle> {
668 9300 : return Rc<ShadowPrimitivesAttachmentHandle>::create(this, handle);
669 : }
670 :
671 20 : ShadowSdfImageAttachment::~ShadowSdfImageAttachment() { }
672 :
673 10 : bool ShadowSdfImageAttachment::init(AttachmentBuilder &builder, Extent2 extent) {
674 20 : return ImageAttachment::init(builder, ImageInfo(
675 : extent,
676 10 : core::ForceImageUsage(core::ImageUsage::Storage | core::ImageUsage::Sampled | core::ImageUsage::TransferDst | core::ImageUsage::TransferSrc),
677 0 : core::PassType::Compute,
678 10 : core::ImageFormat::R16G16_SFLOAT),
679 20 : ImageAttachment::AttachmentInfo{
680 : .initialLayout = core::AttachmentLayout::Undefined,
681 : .finalLayout = core::AttachmentLayout::ShaderReadOnlyOptimal,
682 : .clearOnLoad = false,
683 : .clearColor = Color4F(1.0f, 0.0f, 0.0f, 0.0f)
684 20 : });
685 : }
686 :
687 4650 : Rc<ShadowSdfImageAttachment::AttachmentHandle> ShadowSdfImageAttachment::makeFrameHandle(const FrameQueue &handle) {
688 9300 : return Rc<ShadowSdfImageAttachmentHandle>::create(this, handle);
689 : }
690 :
691 4640 : void ShadowSdfImageAttachmentHandle::submitInput(FrameQueue &q, Rc<core::AttachmentInputData> &&data, Function<void(bool)> &&cb) {
692 4640 : auto d = data.cast<FrameContextHandle2d>();
693 4640 : if (!d || q.isFinalized()) {
694 0 : cb(false);
695 0 : return;
696 : }
697 :
698 4640 : q.getFrame()->waitForDependencies(data->waitDependencies, [this, d = move(d), cb = move(cb)] (FrameHandle &handle, bool success) mutable {
699 4640 : if (!success || !handle.isValidFlag()) {
700 0 : cb(false);
701 0 : return;
702 : }
703 :
704 4640 : _shadowDensity = d->lights.shadowDensity;
705 4640 : _sceneDensity = d->lights.sceneDensity;
706 :
707 4640 : _currentImageInfo = static_cast<ImageAttachment *>(_attachment.get())->getImageInfo();
708 4640 : _currentImageInfo.extent = d->lights.getShadowExtent( handle.getFrameConstraints().getScreenSize());
709 4640 : handle.getRequest()->addImageSpecialization(static_cast<const ImageAttachment *>(_attachment.get()), ImageInfoData(_currentImageInfo));
710 4640 : cb(true);
711 : });
712 4640 : }
713 :
714 : }
|