Loading...
Searching...
No Matches
UYVY.hpp
1#pragma once
2#include <Gfx/Graph/encoders/GPUVideoEncoder.hpp>
3
4namespace score::gfx
5{
6
17{
18 // %1 = colorMatrixOut() shader defining convert_from_rgb(vec3)
19 static constexpr const char* frag = R"_(#version 450
20 layout(location = 0) in vec2 v_texcoord;
21 layout(location = 0) out vec4 fragColor;
22 layout(binding = 3) uniform sampler2D src_tex;
23 )_" "%1" R"_(
24
25 vec2 flip_y(vec2 tc) {
26 // Only OpenGL. The rest of the engine puts its geometry through
27 // renderer.clipSpaceCorrMatrix, which negates Y on Vulkan; this pass draws
28 // a hardcoded triangle in raw NDC and does not, so the correction it needs
29 // is not the same one. Flipping on Vulkan as well handed libav, GStreamer,
30 // NDI and every other consumer an upside-down picture.
31 #if defined(QSHADER_SPIRV) || defined(QSHADER_MSL) || defined(QSHADER_HLSL)
32 return tc;
33 #else
34 return vec2(tc.x, 1.0 - tc.y);
35 #endif
36 }
37
38 void main() {
39 float srcW = float(textureSize(src_tex, 0).x);
40 float srcY = flip_y(v_texcoord).y;
41
42 float halfW = srcW * 0.5;
43 float outPixel = v_texcoord.x * halfW - 0.5;
44 float srcX0 = (floor(outPixel) * 2.0 + 0.5) / srcW;
45 float srcX1 = (floor(outPixel) * 2.0 + 1.5) / srcW;
46
47 vec3 rgb0 = texture(src_tex, vec2(srcX0, srcY)).rgb;
48 vec3 rgb1 = texture(src_tex, vec2(srcX1, srcY)).rgb;
49
50 vec3 yuv0 = convert_from_rgb(rgb0);
51 vec3 yuv1 = convert_from_rgb(rgb1);
52
53 // Average chroma
54 float u = (yuv0.y + yuv1.y) * 0.5;
55 float v = (yuv0.z + yuv1.z) * 0.5;
56
57 // UYVY: U, Y0, V, Y1
58 fragColor = vec4(u, yuv0.x, v, yuv1.x);
59 }
60 )_";
61
62 QRhiTexture* m_outTexture{};
63 QRhiTextureRenderTarget* m_renderTarget{};
64 QRhiRenderPassDescriptor* m_rpDesc{};
65 QRhiSampler* m_sampler{};
66 QRhiShaderResourceBindings* m_srb{};
67 QRhiGraphicsPipeline* m_pipeline{};
68 QRhiReadbackResult m_readback{};
69 int m_width{};
70 int m_height{};
71 bool m_readbackEnabled{true};
72
73 void init(
74 QRhi& rhi, const RenderState& state, QRhiTexture* inputRGBA, int width,
75 int height, const QString& colorConversion) override
76 {
77 m_width = width;
78 m_height = height;
79
80 // Output: RGBA8 at half width (each texel = 2 source pixels packed as UYVY)
81 m_outTexture = rhi.newTexture(
82 QRhiTexture::RGBA8, QSize{width / 2, height}, 1,
83 QRhiTexture::RenderTarget | QRhiTexture::UsedAsTransferSource);
84 m_outTexture->create();
85
86 m_renderTarget = rhi.newTextureRenderTarget({m_outTexture});
87 m_rpDesc = m_renderTarget->newCompatibleRenderPassDescriptor();
88 m_renderTarget->setRenderPassDescriptor(m_rpDesc);
89 m_renderTarget->create();
90
91 m_sampler = rhi.newSampler(
92 QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
93 QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge);
94 m_sampler->create();
95
96 // Shader resource bindings — only the source texture sampler
97 m_srb = rhi.newShaderResourceBindings();
98 m_srb->setBindings({
99 QRhiShaderResourceBinding::sampledTexture(
100 3, QRhiShaderResourceBinding::FragmentStage, inputRGBA, m_sampler),
101 });
102 m_srb->create();
103
104 // Compile shaders
105 auto [vertS, fragS] = makeShaders(
106 state, QString::fromLatin1(vertex_shader),
107 QString::fromLatin1(frag).arg(colorConversion));
108
109 // Graphics pipeline
110 m_pipeline = rhi.newGraphicsPipeline();
111 m_pipeline->setShaderStages({
112 {QRhiShaderStage::Vertex, vertS},
113 {QRhiShaderStage::Fragment, fragS},
114 });
115
116 m_pipeline->setVertexInputLayout({});
117 m_pipeline->setShaderResourceBindings(m_srb);
118 m_pipeline->setRenderPassDescriptor(m_rpDesc);
119 m_pipeline->create();
121 }
122
123 void exec(QRhi& rhi, QRhiCommandBuffer& cb) override
124 {
125 cb.beginPass(m_renderTarget, Qt::black, {0.0f, 0});
126 cb.setGraphicsPipeline(m_pipeline);
127 cb.setShaderResources(m_srb);
128 cb.setViewport(QRhiViewport(0, 0, m_width / 2, m_height));
129 cb.draw(3);
130
131 if(m_readbackEnabled)
132 {
133 auto* readbackBatch = rhi.nextResourceUpdateBatch();
134 QRhiReadbackDescription rb(m_outTexture);
135 readbackBatch->readBackTexture(rb, &m_readback);
136 cb.endPass(readbackBatch);
137 }
138 else
139 {
140 cb.endPass();
142 }
144 int planeCount() const override { return 1; }
146 const QRhiReadbackResult& readback(int) const override { return m_readback; }
147 QRhiTexture* outputTexture() const noexcept override { return m_outTexture; }
148 void setReadbackEnabled(bool e) noexcept override { m_readbackEnabled = e; }
149
150 void release() override
151 {
152 delete m_pipeline;
153 m_pipeline = nullptr;
154 delete m_srb;
155 m_srb = nullptr;
156 delete m_sampler;
157 m_sampler = nullptr;
158 delete m_rpDesc;
159 m_rpDesc = nullptr;
160 delete m_renderTarget;
161 m_renderTarget = nullptr;
162 delete m_outTexture;
163 m_outTexture = nullptr;
164 }
165};
166
167} // namespace score::gfx
Graphics rendering pipeline for ossia score.
Definition Filter/PreviewWidget.hpp:11
std::pair< QShader, QShader > makeShaders(const RenderState &v, QString vert, QString frag, int multiViewCount)
Get a pair of compiled vertex / fragment shaders from GLSL 4.5 sources.
Definition score-plugin-gfx/Gfx/Graph/Utils.cpp:1238
Base class for GPU-side video format conversion (RGBA to YUV).
Definition GPUVideoEncoder.hpp:30
static constexpr const char * vertex_shader
Definition GPUVideoEncoder.hpp:74
GPU RGBA->UYVY encoder (packed 4:2:2).
Definition UYVY.hpp:17
void release() override
Release all GPU resources.
Definition UYVY.hpp:147
QRhiTexture * outputTexture() const noexcept override
Definition UYVY.hpp:144
int planeCount() const override
Number of readback planes (1 for UYVY, 2 for NV12, 3 for I420).
Definition UYVY.hpp:141
void exec(QRhi &rhi, QRhiCommandBuffer &cb) override
Definition UYVY.hpp:120
void setReadbackEnabled(bool e) noexcept override
Definition UYVY.hpp:145
const QRhiReadbackResult & readback(int) const override
Get the readback result for a given plane. Valid after endOffscreenFrame.
Definition UYVY.hpp:143
void init(QRhi &rhi, const RenderState &state, QRhiTexture *inputRGBA, int width, int height, const QString &colorConversion) override
Definition UYVY.hpp:70