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;
25 layout(binding = 0) uniform sampler2D src_tex;
26 layout(std430, binding = 1) writeonly buffer BgraBuf {
29 layout(std140, binding = 2) uniform Params {
32 uint line_stride_words; // bytes-per-row / 4 == width
36 uint to_byte(float v) {
37 return uint(clamp(v, 0.0, 1.0) * 255.0 + 0.5);
41 uint x = gl_GlobalInvocationID.x;
42 uint y = gl_GlobalInvocationID.y;
43 if (int(x) >= src_size.x || int(y) >= src_size.y)
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)
52 int src_y = src_size.y - 1 - int(y);
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);
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;
67 QRhiBuffer* m_paramsUBO{};
68 QRhiSampler* m_sampler{};
69 QRhiShaderResourceBindings* m_srb{};
70 QRhiComputePipeline* m_pipeline{};
75 QRhi& rhi,
const RenderState& state, QRhiTexture* inputRGBA,
int width,
76 int height, QRhiBuffer* outputBuffer,
77 const QString& = colorMatrixOut())
override
79 if(!outputBuffer || !rhi.isFeatureSupported(QRhi::Compute))
85 m_paramsUBO = rhi.newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 32);
86 m_paramsUBO->setName(
"BGRAComputeEncoder::params");
87 if(!m_paramsUBO->create())
90 m_sampler = rhi.newSampler(
91 QRhiSampler::Nearest, QRhiSampler::Nearest, QRhiSampler::None,
92 QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge);
93 if(!m_sampler->create())
96 m_srb = rhi.newShaderResourceBindings();
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),
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())
119 QRhi& rhi, QRhiCommandBuffer& cb, QRhiResourceUpdateBatch* res)
override
121 struct alignas(16) ParamsData
125 uint32_t lineStrideWords;
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);
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);
137 void release()
override
139 delete m_pipeline; m_pipeline =
nullptr;
140 delete m_srb; m_srb =
nullptr;
141 delete m_sampler; m_sampler =
nullptr;
QShader makeCompute(const RenderState &v, QString compute)
Compile a compute shader.
Definition score-plugin-gfx/Gfx/Graph/Utils.cpp:1327