Loading...
Searching...
No Matches
BGRACompute.hpp
1#pragma once
2#include <Gfx/Graph/Utils.hpp>
3#include <Gfx/Graph/encoders/ComputeEncoder.hpp>
4#include <Gfx/Graph/encoders/GPUVideoEncoder.hpp>
5
6#include <private/qrhi_p.h>
7
8namespace score::gfx
9{
10
21{
22 static constexpr const char* compute_shader = R"_(#version 450
23 layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
24
25 layout(binding = 0) uniform sampler2D src_tex;
26 layout(std430, binding = 1) writeonly buffer BgraBuf {
27 uint bgra[];
28 };
29 layout(std140, binding = 2) uniform Params {
30 ivec2 src_size;
31 ivec2 _pad0;
32 uint line_stride_words; // bytes-per-row / 4 == width
33 uint _pad1[3];
34 };
35
36 uint to_byte(float v) {
37 return uint(clamp(v, 0.0, 1.0) * 255.0 + 0.5);
38 }
39
40 void main() {
41 uint x = gl_GlobalInvocationID.x;
42 uint y = gl_GlobalInvocationID.y;
43 if (int(x) >= src_size.x || int(y) >= src_size.y)
44 return;
45
46 // See GPUVideoEncoder::y_flip_glsl: only OpenGL. The rest of the engine
47 // negates Y through renderer.clipSpaceCorrMatrix on Vulkan; this pass
48 // indexes texels directly and does not, so it must not flip there.
49 #if defined(QSHADER_SPIRV) || defined(QSHADER_MSL) || defined(QSHADER_HLSL)
50 int src_y = int(y);
51 #else
52 int src_y = src_size.y - 1 - int(y);
53 #endif
54
55 vec4 c = texelFetch(src_tex, ivec2(int(x), src_y), 0);
56 uint B = to_byte(c.b);
57 uint G = to_byte(c.g);
58 uint R = to_byte(c.r);
59 uint A = to_byte(c.a);
60
61 // NTV2_FBF_ARGB byte order in memory: B, G, R, A
62 uint w = B | (G << 8) | (R << 16) | (A << 24);
63 bgra[y * line_stride_words + x] = w;
64 }
65 )_";
66
67 QRhiBuffer* m_paramsUBO{};
68 QRhiSampler* m_sampler{};
69 QRhiShaderResourceBindings* m_srb{};
70 QRhiComputePipeline* m_pipeline{};
71 int m_width{};
72 int m_height{};
73
74 bool init(
75 QRhi& rhi, const RenderState& state, QRhiTexture* inputRGBA, int width,
76 int height, QRhiBuffer* outputBuffer,
77 const QString& /*colorConversion*/ = colorMatrixOut()) override
78 {
79 if(!outputBuffer || !rhi.isFeatureSupported(QRhi::Compute))
80 return false;
81
82 m_width = width;
83 m_height = height;
84
85 m_paramsUBO = rhi.newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 32);
86 m_paramsUBO->setName("BGRAComputeEncoder::params");
87 if(!m_paramsUBO->create())
88 return false;
89
90 m_sampler = rhi.newSampler(
91 QRhiSampler::Nearest, QRhiSampler::Nearest, QRhiSampler::None,
92 QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge);
93 if(!m_sampler->create())
94 return false;
95
96 m_srb = rhi.newShaderResourceBindings();
97 m_srb->setBindings({
98 QRhiShaderResourceBinding::sampledTexture(
99 0, QRhiShaderResourceBinding::ComputeStage, inputRGBA, m_sampler),
100 QRhiShaderResourceBinding::bufferStore(
101 1, QRhiShaderResourceBinding::ComputeStage, outputBuffer),
102 QRhiShaderResourceBinding::uniformBuffer(
103 2, QRhiShaderResourceBinding::ComputeStage, m_paramsUBO),
104 });
105 if(!m_srb->create())
106 return false;
107
108 QShader cs = makeCompute(state, QString::fromLatin1(compute_shader));
109 m_pipeline = rhi.newComputePipeline();
110 m_pipeline->setShaderStage({QRhiShaderStage::Compute, cs});
111 m_pipeline->setShaderResourceBindings(m_srb);
112 if(!m_pipeline->create())
113 return false;
114
115 return true;
116 }
117
118 void exec(
119 QRhi& rhi, QRhiCommandBuffer& cb, QRhiResourceUpdateBatch* res) override
120 {
121 struct alignas(16) ParamsData
122 {
123 int32_t srcW, srcH;
124 int32_t pad0[2];
125 uint32_t lineStrideWords;
126 uint32_t pad1[3];
127 } p{m_width, m_height, {0, 0}, static_cast<uint32_t>(m_width), {0, 0, 0}};
128 res->updateDynamicBuffer(m_paramsUBO, 0, sizeof(p), &p);
129
130 cb.beginComputePass(res);
131 cb.setComputePipeline(m_pipeline);
132 cb.setShaderResources(m_srb);
133 cb.dispatch((m_width + 15) / 16, (m_height + 15) / 16, 1);
134 cb.endComputePass();
135 }
136
137 void release() override
138 {
139 delete m_pipeline; m_pipeline = nullptr;
140 delete m_srb; m_srb = nullptr;
141 delete m_sampler; m_sampler = nullptr;
142 delete m_paramsUBO; m_paramsUBO = nullptr;
143 }
144};
145
146} // namespace score::gfx
Graphics rendering pipeline for ossia score.
Definition Filter/PreviewWidget.hpp:11
QShader makeCompute(const RenderState &v, QString compute)
Compile a compute shader.
Definition score-plugin-gfx/Gfx/Graph/Utils.cpp:1327
Compute-shader RGBA -> BGRA (NTV2_FBF_ARGB byte order) encoder targeting an external SSBO.
Definition BGRACompute.hpp:21
Base interface for compute-shader RGBA -> AJA-format encoders.
Definition ComputeEncoder.hpp:36
Global state associated to a rendering context.
Definition RenderState.hpp:37