LCOV - code coverage report
Current view: top level - xenolith/renderer/basic2d/backend/vk - XL2dVkShadow.cc (source / functions) Hit Total Coverage
Test: coverage.info Lines: 381 429 88.8 %
Date: 2024-05-12 00:16:13 Functions: 49 50 98.0 %

          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             : }

Generated by: LCOV version 1.14