22 static constexpr const char* compute_shader = R
"_(#version 450
23 layout(local_size_x = 32, local_size_y = 1, local_size_z = 1) in;
25 layout(binding = 0) uniform sampler2D src_tex;
26 layout(std430, binding = 1) writeonly buffer UyvyBuf {
29 layout(std140, binding = 2) uniform Params {
32 uint line_stride_words; // bytes-per-row / 4
33 uint pairs_per_row; // == src_width / 2
38 uint to_byte(float v) {
39 return uint(clamp(v, 0.0, 1.0) * 255.0 + 0.5);
43 uint pair_x = gl_GlobalInvocationID.x;
44 uint y = gl_GlobalInvocationID.y;
45 if (pair_x >= pairs_per_row || int(y) >= src_size.y)
48 #if defined(QSHADER_MSL) || defined(QSHADER_HLSL)
51 int src_y = src_size.y - 1 - int(y);
54 uint x0 = pair_x * 2u;
55 vec3 a = clamp(convert_from_rgb(texelFetch(src_tex, ivec2(int(x0 ), src_y), 0).rgb), 0.0, 1.0);
56 vec3 b = clamp(convert_from_rgb(texelFetch(src_tex, ivec2(int(x0 + 1u), src_y), 0).rgb), 0.0, 1.0);
58 uint Y0 = to_byte(a.x);
59 uint Y1 = to_byte(b.x);
60 uint Cb = to_byte((a.y + b.y) * 0.5);
61 uint Cr = to_byte((a.z + b.z) * 0.5);
63 // UYVY little-endian DWORD: Cb, Y0, Cr, Y1
64 uint w = Cb | (Y0 << 8) | (Cr << 16) | (Y1 << 24);
65 uyvy[y * line_stride_words + pair_x] = w;
69 QRhiBuffer* m_paramsUBO{};
70 QRhiSampler* m_sampler{};
71 QRhiShaderResourceBindings* m_srb{};
72 QRhiComputePipeline* m_pipeline{};
75 uint32_t m_pairsPerRow{};
76 uint32_t m_lineStrideBytes{};
79 QRhi& rhi,
const RenderState& state, QRhiTexture* inputRGBA,
int width,
80 int height, QRhiBuffer* outputBuffer,
81 const QString& colorConversion = colorMatrixOut())
override
83 if(!outputBuffer || (width % 2) != 0)
85 if(!rhi.isFeatureSupported(QRhi::Compute))
90 m_pairsPerRow = width / 2;
91 m_lineStrideBytes = width * 2;
93 m_paramsUBO = rhi.newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 32);
94 m_paramsUBO->setName(
"UYVYComputeEncoder::params");
95 if(!m_paramsUBO->create())
98 m_sampler = rhi.newSampler(
99 QRhiSampler::Nearest, QRhiSampler::Nearest, QRhiSampler::None,
100 QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge);
101 if(!m_sampler->create())
104 m_srb = rhi.newShaderResourceBindings();
106 QRhiShaderResourceBinding::sampledTexture(
107 0, QRhiShaderResourceBinding::ComputeStage, inputRGBA, m_sampler),
108 QRhiShaderResourceBinding::bufferStore(
109 1, QRhiShaderResourceBinding::ComputeStage, outputBuffer),
110 QRhiShaderResourceBinding::uniformBuffer(
111 2, QRhiShaderResourceBinding::ComputeStage, m_paramsUBO),
117 state, QString::fromLatin1(compute_shader).arg(colorConversion));
118 m_pipeline = rhi.newComputePipeline();
119 m_pipeline->setShaderStage({QRhiShaderStage::Compute, cs});
120 m_pipeline->setShaderResourceBindings(m_srb);
121 if(!m_pipeline->create())
128 QRhi& rhi, QRhiCommandBuffer& cb, QRhiResourceUpdateBatch* res)
override
130 struct alignas(16) ParamsData
134 uint32_t lineStrideWords;
135 uint32_t pairsPerRow;
140 m_lineStrideBytes / 4,
143 res->updateDynamicBuffer(m_paramsUBO, 0,
sizeof(p), &p);
145 cb.beginComputePass(res);
146 cb.setComputePipeline(m_pipeline);
147 cb.setShaderResources(m_srb);
148 cb.dispatch((m_pairsPerRow + 31) / 32, m_height, 1);
152 void release()
override
154 delete m_pipeline; m_pipeline =
nullptr;
155 delete m_srb; m_srb =
nullptr;
156 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:674