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 // See GPUVideoEncoder::y_flip_glsl: only OpenGL. The rest of the engine
49 // negates Y through renderer.clipSpaceCorrMatrix on Vulkan; this pass
50 // indexes texels directly and does not, so it must not flip there.
51 #if defined(QSHADER_SPIRV) || defined(QSHADER_MSL) || defined(QSHADER_HLSL)
54 int src_y = src_size.y - 1 - int(y);
57 uint x0 = pair_x * 2u;
58 vec3 a = clamp(convert_from_rgb(texelFetch(src_tex, ivec2(int(x0 ), src_y), 0).rgb), 0.0, 1.0);
59 vec3 b = clamp(convert_from_rgb(texelFetch(src_tex, ivec2(int(x0 + 1u), src_y), 0).rgb), 0.0, 1.0);
61 uint Y0 = to_byte(a.x);
62 uint Y1 = to_byte(b.x);
63 uint Cb = to_byte((a.y + b.y) * 0.5);
64 uint Cr = to_byte((a.z + b.z) * 0.5);
66 // UYVY little-endian DWORD: Cb, Y0, Cr, Y1
67 uint w = Cb | (Y0 << 8) | (Cr << 16) | (Y1 << 24);
68 uyvy[y * line_stride_words + pair_x] = w;
72 QRhiBuffer* m_paramsUBO{};
73 QRhiSampler* m_sampler{};
74 QRhiShaderResourceBindings* m_srb{};
75 QRhiComputePipeline* m_pipeline{};
78 uint32_t m_pairsPerRow{};
79 uint32_t m_lineStrideBytes{};
82 QRhi& rhi,
const RenderState& state, QRhiTexture* inputRGBA,
int width,
83 int height, QRhiBuffer* outputBuffer,
84 const QString& colorConversion)
override
86 if(!outputBuffer || (width % 2) != 0)
88 if(!rhi.isFeatureSupported(QRhi::Compute))
93 m_pairsPerRow = width / 2;
94 m_lineStrideBytes = width * 2;
96 m_paramsUBO = rhi.newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 32);
97 m_paramsUBO->setName(
"UYVYComputeEncoder::params");
98 if(!m_paramsUBO->create())
101 m_sampler = rhi.newSampler(
102 QRhiSampler::Nearest, QRhiSampler::Nearest, QRhiSampler::None,
103 QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge);
104 if(!m_sampler->create())
107 m_srb = rhi.newShaderResourceBindings();
109 QRhiShaderResourceBinding::sampledTexture(
110 0, QRhiShaderResourceBinding::ComputeStage, inputRGBA, m_sampler),
111 QRhiShaderResourceBinding::bufferStore(
112 1, QRhiShaderResourceBinding::ComputeStage, outputBuffer),
113 QRhiShaderResourceBinding::uniformBuffer(
114 2, QRhiShaderResourceBinding::ComputeStage, m_paramsUBO),
120 state, QString::fromLatin1(compute_shader).arg(colorConversion));
121 m_pipeline = rhi.newComputePipeline();
122 m_pipeline->setShaderStage({QRhiShaderStage::Compute, cs});
123 m_pipeline->setShaderResourceBindings(m_srb);
124 if(!m_pipeline->create())
131 QRhi& rhi, QRhiCommandBuffer& cb, QRhiResourceUpdateBatch* res)
override
133 struct alignas(16) ParamsData
137 uint32_t lineStrideWords;
138 uint32_t pairsPerRow;
143 m_lineStrideBytes / 4,
146 res->updateDynamicBuffer(m_paramsUBO, 0,
sizeof(p), &p);
148 cb.beginComputePass(res);
149 cb.setComputePipeline(m_pipeline);
150 cb.setShaderResources(m_srb);
151 cb.dispatch((m_pairsPerRow + 31) / 32, m_height, 1);
155 void release()
override
157 delete m_pipeline; m_pipeline =
nullptr;
158 delete m_srb; m_srb =
nullptr;
159 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