35 static constexpr const char* frag_template = R
"_(#version 450
36 layout(location = 0) in vec2 v_texcoord;
37 layout(location = 0) out vec4 fragColor;
38 layout(binding = 3) uniform sampler2D src_tex;
40 vec2 flip_y_uv(vec2 tc) {
41 // Only OpenGL. The rest of the engine puts its geometry through
42 // renderer.clipSpaceCorrMatrix, which negates Y on Vulkan; this pass draws
43 // a hardcoded triangle in raw NDC and does not, so the correction it needs
44 // is not the same one. Flipping on Vulkan as well handed libav, GStreamer,
45 // NDI and every other consumer an upside-down picture.
46 #if defined(QSHADER_SPIRV) || defined(QSHADER_MSL) || defined(QSHADER_HLSL)
49 return vec2(tc.x, 1.0 - tc.y);
53 const uint MAXV = %1u;
54 const uint ALPHA = %2u;
57 // Source pixel components quantised to [0..MAXV], .a == ALPHA.
58 uvec4 rgb_at(int x, int srcY) {
59 x = clamp(x, 0, g_srcSize.x - 1);
60 vec3 c = clamp(texelFetch(src_tex, ivec2(x, srcY), 0).rgb, 0.0, 1.0);
61 uvec3 v = uvec3(c * float(MAXV) + 0.5);
62 return uvec4(v, ALPHA);
65 uint rowByte(int b, int srcY) {
70 g_srcSize = textureSize(src_tex, 0);
72 int(flip_y_uv(v_texcoord).y * float(g_srcSize.y)), 0, g_srcSize.y - 1);
73 int o = int(gl_FragCoord.x) * 4;
75 float(rowByte(o, srcY)),
76 float(rowByte(o + 1, srcY)),
77 float(rowByte(o + 2, srcY)),
78 float(rowByte(o + 3, srcY))) / 255.0;
82 int m_bytesPerGroup{4};
83 int m_pixelsPerGroup{1};
86 QString m_rowByteBody;
89 int bytesPerGroup,
int pixelsPerGroup,
int maxVal,
int alphaVal,
91 : m_bytesPerGroup{bytesPerGroup}
92 , m_pixelsPerGroup{pixelsPerGroup}
94 , m_alphaVal{alphaVal}
95 , m_rowByteBody{std::move(rowByteBody)}
99 QRhiTexture* m_outTexture{};
100 QRhiTextureRenderTarget* m_renderTarget{};
101 QRhiRenderPassDescriptor* m_rpDesc{};
102 QRhiSampler* m_sampler{};
103 QRhiShaderResourceBindings* m_srb{};
104 QRhiGraphicsPipeline* m_pipeline{};
105 QRhiReadbackResult m_readback{};
109 bool m_readbackEnabled{
true};
112 QRhi& rhi,
const RenderState& state, QRhiTexture* inputRGBA,
int width,
113 int height,
const QString& = colorMatrixOut())
override
117 m_outW = (width * m_bytesPerGroup) / (m_pixelsPerGroup * 4);
119 m_outTexture = rhi.newTexture(
120 QRhiTexture::RGBA8, QSize{m_outW, height}, 1,
121 QRhiTexture::RenderTarget | QRhiTexture::UsedAsTransferSource);
122 m_outTexture->create();
124 m_renderTarget = rhi.newTextureRenderTarget({m_outTexture});
125 m_rpDesc = m_renderTarget->newCompatibleRenderPassDescriptor();
126 m_renderTarget->setRenderPassDescriptor(m_rpDesc);
127 m_renderTarget->create();
129 m_sampler = rhi.newSampler(
130 QRhiSampler::Nearest, QRhiSampler::Nearest, QRhiSampler::None,
131 QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge);
134 m_srb = rhi.newShaderResourceBindings();
136 QRhiShaderResourceBinding::sampledTexture(
137 3, QRhiShaderResourceBinding::FragmentStage, inputRGBA, m_sampler),
141 const QString fragSrc = QString::fromLatin1(frag_template)
148 m_pipeline = rhi.newGraphicsPipeline();
149 m_pipeline->setShaderStages({
150 {QRhiShaderStage::Vertex, vertS},
151 {QRhiShaderStage::Fragment, fragS},
153 m_pipeline->setVertexInputLayout({});
154 m_pipeline->setShaderResourceBindings(m_srb);
155 m_pipeline->setRenderPassDescriptor(m_rpDesc);
156 m_pipeline->create();
159 void exec(QRhi& rhi, QRhiCommandBuffer& cb)
override
161 cb.beginPass(m_renderTarget, Qt::black, {0.0f, 0});
162 cb.setGraphicsPipeline(m_pipeline);
163 cb.setShaderResources(m_srb);
164 cb.setViewport(QRhiViewport(0, 0, m_outW, m_height));
167 if(m_readbackEnabled)
169 auto* readbackBatch = rhi.nextResourceUpdateBatch();
170 readbackBatch->readBackTexture(QRhiReadbackDescription{m_outTexture}, &m_readback);
171 cb.endPass(readbackBatch);
180 const QRhiReadbackResult&
readback(
int)
const override {
return m_readback; }
181 QRhiTexture*
outputTexture() const noexcept
override {
return m_outTexture; }
186 delete m_pipeline; m_pipeline =
nullptr;
187 delete m_srb; m_srb =
nullptr;
188 delete m_sampler; m_sampler =
nullptr;
189 delete m_rpDesc; m_rpDesc =
nullptr;
190 delete m_renderTarget; m_renderTarget =
nullptr;
191 delete m_outTexture; m_outTexture =
nullptr;
198 static std::unique_ptr<PackedRGBEncoder> rgb10()
200 return std::make_unique<PackedRGBEncoder>(4, 1, 1023, 0, R
"_(
201 int px = b >> 2; int k = b & 3;
202 uvec4 c = rgb_at(px, srcY);
203 uint w = c.r | (c.g << 10) | (c.b << 20);
204 return (w >> uint(8 * k)) & 0xFFu;
211 static std::unique_ptr<PackedRGBEncoder> r210be()
213 return std::make_unique<PackedRGBEncoder>(4, 1, 1023, 0, R
"_(
214 int px = b >> 2; int k = b & 3;
215 uvec4 c = rgb_at(px, srcY);
216 uint w = (c.r << 20) | (c.g << 10) | c.b;
217 return (w >> uint(8 * (3 - k))) & 0xFFu;
222 static std::unique_ptr<PackedRGBEncoder> dpx10be()
224 return std::make_unique<PackedRGBEncoder>(4, 1, 1023, 0, R
"_(
225 int px = b >> 2; int k = b & 3;
226 uvec4 c = rgb_at(px, srcY);
227 uint w = (c.r << 22) | (c.g << 12) | (c.b << 2);
228 return (w >> uint(8 * (3 - k))) & 0xFFu;
233 static std::unique_ptr<PackedRGBEncoder> dpx10le()
235 return std::make_unique<PackedRGBEncoder>(4, 1, 1023, 0, R
"_(
236 int px = b >> 2; int k = b & 3;
237 uvec4 c = rgb_at(px, srcY);
238 uint w = (c.r << 22) | (c.g << 12) | (c.b << 2);
239 return (w >> uint(8 * k)) & 0xFFu;
244 static std::unique_ptr<PackedRGBEncoder> rgb24()
246 return std::make_unique<PackedRGBEncoder>(3, 1, 255, 0, R
"_(
247 int px = b / 3; int k = b - px * 3;
248 uvec4 c = rgb_at(px, srcY);
249 if (k == 0) return c.r;
250 if (k == 1) return c.g;
256 static std::unique_ptr<PackedRGBEncoder> bgr24()
258 return std::make_unique<PackedRGBEncoder>(3, 1, 255, 0, R
"_(
259 int px = b / 3; int k = b - px * 3;
260 uvec4 c = rgb_at(px, srcY);
261 if (k == 0) return c.b;
262 if (k == 1) return c.g;
270 static std::unique_ptr<PackedRGBEncoder> rgb48()
272 return std::make_unique<PackedRGBEncoder>(6, 1, 65535, 0, R
"_(
273 int px = b / 6; int k = b - px * 6;
274 uvec4 c = rgb_at(px, srcY);
275 int comp = k >> 1; int hi = k & 1;
276 uint v = comp == 0 ? c.r : (comp == 1 ? c.g : c.b);
277 return hi == 1 ? ((v >> 8) & 0xFFu) : (v & 0xFFu);
283 static std::unique_ptr<PackedRGBEncoder> rgb12packed()
285 return std::make_unique<PackedRGBEncoder>(9, 2, 4095, 0, R
"_(
286 int grp = b / 9; int k = b - grp * 9; int px0 = grp * 2;
287 uvec4 c0 = rgb_at(px0, srcY);
288 uvec4 c1 = rgb_at(px0 + 1, srcY);
289 uint VR0 = c0.r << 4, VG0 = c0.g << 4, VB0 = c0.b << 4;
290 uint VR1 = c1.r << 4, VG1 = c1.g << 4, VB1 = c1.b << 4;
291 if (k == 0) return (VR0 >> 8) & 0xFFu;
292 if (k == 1) return (VR0 & 0xF0u) | ((VG0 >> 12) & 0x0Fu);
293 if (k == 2) return (VG0 >> 4) & 0xFFu;
294 if (k == 3) return (VB0 >> 8) & 0xFFu;
295 if (k == 4) return (VB0 & 0xF0u) | ((VR1 >> 12) & 0x0Fu);
296 if (k == 5) return (VR1 >> 4) & 0xFFu;
297 if (k == 6) return (VG1 >> 8) & 0xFFu;
298 if (k == 7) return (VG1 & 0xF0u) | ((VB1 >> 12) & 0x0Fu);
299 return (VB1 >> 4) & 0xFFu;
304 static std::unique_ptr<PackedRGBEncoder> argb10()
306 return std::make_unique<PackedRGBEncoder>(5, 1, 1023, 1023, R
"_(
307 int px = b / 5; int k = b - px * 5;
308 uvec4 c = rgb_at(px, srcY);
309 uint R = c.r, G = c.g, B = c.b, A = c.a;
310 if (k == 0) return B & 0xFFu;
311 if (k == 1) return ((B >> 8) & 0x03u) | ((G & 0x3Fu) << 2);
312 if (k == 2) return ((G >> 6) & 0x0Fu) | ((R & 0x0Fu) << 4);
313 if (k == 3) return ((R >> 4) & 0x3Fu) | ((A & 0x03u) << 6);
314 return (A >> 2) & 0xFFu;
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
void init(QRhi &rhi, const RenderState &state, QRhiTexture *inputRGBA, int width, int height, const QString &=colorMatrixOut()) override
Definition PackedRGB.hpp:108