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 "XLSnnVkSubpixelLayer.h"
24 : #include "XLCoreAttachment.h"
25 : #include "XLCoreFrameQueue.h"
26 : #include "XLCoreFrameRequest.h"
27 : #include "XLSnnVkShaders.h"
28 : #include "XLVkPipeline.h"
29 :
30 : namespace stappler::xenolith::vk::shadernn {
31 :
32 0 : SubpixelLayer::~SubpixelLayer() { }
33 :
34 0 : bool SubpixelLayer::init(Queue::Builder &queueBuilder, QueuePassBuilder &builder, Front *front,
35 : const AttachmentData *input, const AttachmentData *output) {
36 : using namespace core;
37 :
38 0 : auto precision = getAttachmentPrecision(output);
39 :
40 0 : _front = front;
41 :
42 0 : auto passInput = builder.addAttachment(input, [] (AttachmentPassBuilder &builder) {
43 0 : builder.setDependency(AttachmentDependencyInfo{
44 : PipelineStage::ComputeShader, AccessType::ShaderRead,
45 : PipelineStage::ComputeShader, AccessType::ShaderRead,
46 : FrameRenderPassState::Submitted,
47 : });
48 0 : builder.setInitialLayout(AttachmentLayout::General);
49 0 : builder.setFinalLayout(AttachmentLayout::General);
50 0 : });
51 :
52 0 : auto passOutput = builder.addAttachment(output, [] (AttachmentPassBuilder &builder) {
53 0 : builder.setDependency(AttachmentDependencyInfo{
54 : PipelineStage::ComputeShader, AccessType::ShaderWrite,
55 : PipelineStage::ComputeShader, AccessType::ShaderWrite,
56 : FrameRenderPassState::Submitted,
57 : });
58 0 : builder.setInitialLayout(AttachmentLayout::General);
59 0 : builder.setFinalLayout(AttachmentLayout::General);
60 0 : });
61 :
62 0 : auto layout = builder.addDescriptorLayout([&] (PipelineLayoutBuilder &layoutBuilder) {
63 0 : layoutBuilder.addSet([&] (DescriptorSetBuilder &setBuilder) {
64 0 : setBuilder.addDescriptor(passOutput, DescriptorType::StorageImage, AttachmentLayout::General);
65 0 : setBuilder.addDescriptor(passInput, DescriptorType::StorageImage, AttachmentLayout::General);
66 0 : });
67 0 : });
68 :
69 0 : builder.addSubpass([&] (SubpassBuilder &subpassBuilder) {
70 0 : uint32_t subPixelFactor = 2;
71 :
72 0 : SpecializationInfo spec;
73 0 : spec.data = queueBuilder.addProgramByRef(toString(front->getName(), "_shader"), getShader(LayerShader::Subpixel, precision));
74 0 : spec.constants.emplace_back(SpecializationConstant(subPixelFactor)); // 0
75 :
76 0 : subpassBuilder.addComputePipeline(toString(front->getName(), "_pipeline"), layout, move(spec));
77 0 : });
78 :
79 0 : _inputAttachment = input;
80 0 : _outputAttachment = output;
81 :
82 0 : _frameHandleCallback = [] (core::QueuePass &pass, const FrameQueue &q) {
83 0 : return Rc<LayerHandle>::create(pass, q);
84 0 : };
85 :
86 0 : return QueuePass::init(builder);
87 : }
88 :
89 0 : bool SubpixelLayer::LayerHandle::prepare(FrameQueue &q, Function<void(bool)> &&cb) {
90 0 : auto pass = (SubpixelLayer *)_queuePass.get();
91 :
92 0 : if (auto imageAttachment = q.getAttachment(pass->getInputAttachment())) {
93 0 : _inputImage = (const vk::ImageAttachmentHandle *)imageAttachment->handle.get();
94 : }
95 :
96 0 : if (auto imageAttachment = q.getAttachment(pass->getOutputAttachment())) {
97 0 : _outputImage = (const vk::ImageAttachmentHandle *)imageAttachment->handle.get();
98 : }
99 :
100 0 : _front = pass->getFront();
101 :
102 0 : return vk::QueuePassHandle::prepare(q, move(cb));
103 : }
104 :
105 0 : Vector<const vk::CommandBuffer *> SubpixelLayer::LayerHandle::doPrepareCommands(FrameHandle &frame) {
106 0 : auto buf = _pool->recordBuffer(*_device, [&] (vk::CommandBuffer &buf) {
107 0 : auto pass = _data->impl.cast<vk::RenderPass>().get();
108 0 : pass->perform(*this, buf, [&] {
109 0 : buf.cmdBindDescriptorSets(pass, 0);
110 :
111 0 : auto extent = _outputImage->getQueueData()->image->getInfo().extent;
112 :
113 0 : auto oc_4 = UP_DIV(_front->getNumOutputPlanes(), uint32_t(4));
114 :
115 0 : auto pipeline = static_cast<vk::ComputePipeline *>((*_data->subpasses[0]->computePipelines.begin())->pipeline.get());
116 :
117 0 : buf.cmdBindPipeline(pipeline);
118 0 : buf.cmdDispatch((extent.width - 1) / pipeline->getLocalX() + 1,
119 0 : (extent.height - 1) / pipeline->getLocalY() + 1,
120 0 : (oc_4 - 1) / pipeline->getLocalZ() + 1);
121 0 : }, true);
122 0 : return true;
123 : });
124 0 : return Vector<const vk::CommandBuffer *>{buf};
125 : }
126 :
127 : }
|