1 /**************************************************************************
3 * Copyright 2019 Advanced Micro Devices, Inc.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 * Authors: James Zhu <james.zhu<@amd.com>
28 **************************************************************************/
32 #include "tgsi/tgsi_text.h"
33 #include "vl_compositor_cs.h"
45 const char *compute_shader_video_buffer
=
47 "PROPERTY CS_FIXED_BLOCK_WIDTH 8\n"
48 "PROPERTY CS_FIXED_BLOCK_HEIGHT 8\n"
49 "PROPERTY CS_FIXED_BLOCK_DEPTH 1\n"
51 "DCL SV[0], THREAD_ID\n"
52 "DCL SV[1], BLOCK_ID\n"
55 "DCL SVIEW[0..2], RECT, FLOAT\n"
58 "DCL IMAGE[0], 2D, WR\n"
61 "IMM[0] UINT32 { 8, 8, 1, 0}\n"
62 "IMM[1] FLT32 { 1.0, 2.0, 0.0, 0.0}\n"
64 "UMAD TEMP[0], SV[1], IMM[0], SV[0]\n"
66 /* Drawn area check */
67 "USGE TEMP[1].xy, TEMP[0].xyxy, CONST[4].xyxy\n"
68 "USLT TEMP[1].zw, TEMP[0].xyxy, CONST[4].zwzw\n"
69 "AND TEMP[1].x, TEMP[1].xxxx, TEMP[1].yyyy\n"
70 "AND TEMP[1].x, TEMP[1].xxxx, TEMP[1].zzzz\n"
71 "AND TEMP[1].x, TEMP[1].xxxx, TEMP[1].wwww\n"
75 "UADD TEMP[2].xy, TEMP[0], -CONST[5].xyxy\n"
76 "U2F TEMP[2], TEMP[2]\n"
77 "DIV TEMP[3], TEMP[2], IMM[1].yyyy\n"
80 "DIV TEMP[2], TEMP[2], CONST[3].zwzw\n"
81 "DIV TEMP[3], TEMP[3], CONST[3].zwzw\n"
84 "TEX_LZ TEMP[4].x, TEMP[2], SAMP[0], RECT\n"
85 "TEX_LZ TEMP[4].y, TEMP[3], SAMP[1], RECT\n"
86 "TEX_LZ TEMP[4].z, TEMP[3], SAMP[2], RECT\n"
88 "MOV TEMP[4].w, IMM[1].xxxx\n"
90 /* Color Space Conversion */
91 "DP4 TEMP[7].x, CONST[0], TEMP[4]\n"
92 "DP4 TEMP[7].y, CONST[1], TEMP[4]\n"
93 "DP4 TEMP[7].z, CONST[2], TEMP[4]\n"
95 "MOV TEMP[5].w, TEMP[4].zzzz\n"
96 "SLE TEMP[6].w, TEMP[5], CONST[3].xxxx\n"
97 "SGT TEMP[5].w, TEMP[5], CONST[3].yyyy\n"
99 "MAX TEMP[7].w, TEMP[5], TEMP[6]\n"
101 "STORE IMAGE[0], TEMP[0], TEMP[7], 2D\n"
106 const char *compute_shader_weave
=
108 "PROPERTY CS_FIXED_BLOCK_WIDTH 8\n"
109 "PROPERTY CS_FIXED_BLOCK_HEIGHT 8\n"
110 "PROPERTY CS_FIXED_BLOCK_DEPTH 1\n"
112 "DCL SV[0], THREAD_ID\n"
113 "DCL SV[1], BLOCK_ID\n"
116 "DCL SVIEW[0..2], RECT, FLOAT\n"
119 "DCL IMAGE[0], 2D, WR\n"
122 "IMM[0] UINT32 { 8, 8, 1, 0}\n"
123 "IMM[1] FLT32 { 1.0, 2.0, 0.0, 0.0}\n"
124 "IMM[2] UINT32 { 1, 2, 4, 0}\n"
126 "UMAD TEMP[0], SV[1], IMM[0], SV[0]\n"
128 /* Drawn area check */
129 "USGE TEMP[1].xy, TEMP[0].xyxy, CONST[4].xyxy\n"
130 "USLT TEMP[1].zw, TEMP[0].xyxy, CONST[4].zwzw\n"
131 "AND TEMP[1].x, TEMP[1].xxxx, TEMP[1].yyyy\n"
132 "AND TEMP[1].x, TEMP[1].xxxx, TEMP[1].zzzz\n"
133 "AND TEMP[1].x, TEMP[1].xxxx, TEMP[1].wwww\n"
136 "MOV TEMP[2], TEMP[0]\n"
138 "UADD TEMP[2].xy, TEMP[2], -CONST[5].xyxy\n"
141 "UMOD TEMP[2].z, TEMP[2].yyyy, IMM[2].yyyy\n"
142 "UMOD TEMP[3].z, TEMP[2].yyyy, IMM[2].zzzz\n"
143 "USHR TEMP[3].z, TEMP[3].zzzz, IMM[2].xxxx\n"
145 "USHR TEMP[2].y, TEMP[2], IMM[2].xxxx\n"
146 "USHR TEMP[3].xy, TEMP[2], IMM[2].xxxx\n"
148 "U2F TEMP[4], TEMP[2]\n"
149 "U2F TEMP[5], TEMP[3]\n"
152 "DIV TEMP[4], TEMP[4], CONST[3].zwzw\n"
153 "DIV TEMP[5], TEMP[5], CONST[3].zwzw\n"
156 "TEX_LZ TEMP[6].x, TEMP[4], SAMP[0], RECT\n"
157 "TEX_LZ TEMP[6].y, TEMP[5], SAMP[1], RECT\n"
158 "TEX_LZ TEMP[6].z, TEMP[5], SAMP[2], RECT\n"
160 "MOV TEMP[6].w, IMM[1].xxxx\n"
162 /* Color Space Conversion */
163 "DP4 TEMP[9].x, CONST[0], TEMP[6]\n"
164 "DP4 TEMP[9].y, CONST[1], TEMP[6]\n"
165 "DP4 TEMP[9].z, CONST[2], TEMP[6]\n"
167 "MOV TEMP[7].w, TEMP[6].zzzz\n"
168 "SLE TEMP[8].w, TEMP[7], CONST[3].xxxx\n"
169 "SGT TEMP[7].w, TEMP[7], CONST[3].yyyy\n"
171 "MAX TEMP[9].w, TEMP[7], TEMP[8]\n"
173 "STORE IMAGE[0], TEMP[0], TEMP[9], 2D\n"
178 const char *compute_shader_rgba
=
180 "PROPERTY CS_FIXED_BLOCK_WIDTH 8\n"
181 "PROPERTY CS_FIXED_BLOCK_HEIGHT 8\n"
182 "PROPERTY CS_FIXED_BLOCK_DEPTH 1\n"
184 "DCL SV[0], THREAD_ID\n"
185 "DCL SV[1], BLOCK_ID\n"
188 "DCL SVIEW[0], RECT, FLOAT\n"
191 "DCL IMAGE[0], 2D, WR\n"
194 "IMM[0] UINT32 { 8, 8, 1, 0}\n"
195 "IMM[1] FLT32 { 1.0, 2.0, 0.0, 0.0}\n"
197 "UMAD TEMP[0], SV[1], IMM[0], SV[0]\n"
199 /* Drawn area check */
200 "USGE TEMP[1].xy, TEMP[0].xyxy, CONST[4].xyxy\n"
201 "USLT TEMP[1].zw, TEMP[0].xyxy, CONST[4].zwzw\n"
202 "AND TEMP[1].x, TEMP[1].xxxx, TEMP[1].yyyy\n"
203 "AND TEMP[1].x, TEMP[1].xxxx, TEMP[1].zzzz\n"
204 "AND TEMP[1].x, TEMP[1].xxxx, TEMP[1].wwww\n"
208 "UADD TEMP[2].xy, TEMP[0], -CONST[5].xyxy\n"
209 "U2F TEMP[2], TEMP[2]\n"
212 "DIV TEMP[2], TEMP[2], CONST[3].zwzw\n"
215 "TEX_LZ TEMP[3], TEMP[2], SAMP[0], RECT\n"
217 "STORE IMAGE[0], TEMP[0], TEMP[3], 2D\n"
223 cs_launch(struct vl_compositor
*c
,
225 const struct u_rect
*draw_area
)
227 struct pipe_context
*ctx
= c
->pipe
;
230 struct pipe_image_view image
= {};
231 image
.resource
= c
->fb_state
.cbufs
[0]->texture
;
232 image
.shader_access
= image
.access
= PIPE_IMAGE_ACCESS_READ_WRITE
;
233 image
.format
= c
->fb_state
.cbufs
[0]->texture
->format
;
235 ctx
->set_shader_images(c
->pipe
, PIPE_SHADER_COMPUTE
, 0, 1, &image
);
237 /* Bind compute shader */
238 ctx
->bind_compute_state(ctx
, cs
);
240 /* Dispatch compute */
241 struct pipe_grid_info info
= {};
245 info
.grid
[0] = DIV_ROUND_UP(draw_area
->x1
, info
.block
[0]);
246 info
.grid
[1] = DIV_ROUND_UP(draw_area
->y1
, info
.block
[1]);
249 ctx
->launch_grid(ctx
, &info
);
252 static inline struct u_rect
253 calc_drawn_area(struct vl_compositor_state
*s
,
254 struct vl_compositor_layer
*layer
)
256 struct vertex2f tl
, br
;
257 struct u_rect result
;
265 result
.x0
= tl
.x
* layer
->viewport
.scale
[0] + layer
->viewport
.translate
[0];
266 result
.y0
= tl
.y
* layer
->viewport
.scale
[1] + layer
->viewport
.translate
[1];
267 result
.x1
= br
.x
* layer
->viewport
.scale
[0] + layer
->viewport
.translate
[0];
268 result
.y1
= br
.y
* layer
->viewport
.scale
[1] + layer
->viewport
.translate
[1];
271 result
.x0
= MAX2(result
.x0
, s
->scissor
.minx
);
272 result
.y0
= MAX2(result
.y0
, s
->scissor
.miny
);
273 result
.x1
= MIN2(result
.x1
, s
->scissor
.maxx
);
274 result
.y1
= MIN2(result
.y1
, s
->scissor
.maxy
);
279 set_viewport(struct vl_compositor_state
*s
,
280 struct cs_viewport
*drawn
)
282 struct pipe_transfer
*buf_transfer
;
286 void *ptr
= pipe_buffer_map(s
->pipe
, s
->shader_params
,
287 PIPE_TRANSFER_READ
| PIPE_TRANSFER_WRITE
,
293 float *ptr_float
= (float *)ptr
;
294 ptr_float
+= sizeof(vl_csc_matrix
)/sizeof(float) + 2;
295 *ptr_float
++ = drawn
->scale_x
;
296 *ptr_float
++ = drawn
->scale_y
;
298 int *ptr_int
= (int *)ptr_float
;
299 *ptr_int
++ = drawn
->area
.x0
;
300 *ptr_int
++ = drawn
->area
.y0
;
301 *ptr_int
++ = drawn
->area
.x1
;
302 *ptr_int
++ = drawn
->area
.y1
;
303 *ptr_int
++ = drawn
->translate_x
;
304 *ptr_int
++ = drawn
->translate_y
;
306 ptr_float
= (float *)ptr_int
;
307 *ptr_float
++ = drawn
->sampler0_w
;
308 *ptr_float
= drawn
->sampler0_h
;
309 pipe_buffer_unmap(s
->pipe
, buf_transfer
);
315 draw_layers(struct vl_compositor
*c
,
316 struct vl_compositor_state
*s
,
317 struct u_rect
*dirty
)
320 static struct cs_viewport old_drawn
;
324 for (i
= 0; i
< VL_COMPOSITOR_MAX_LAYERS
; ++i
) {
325 if (s
->used_layers
& (1 << i
)) {
326 struct vl_compositor_layer
*layer
= &s
->layers
[i
];
327 struct pipe_sampler_view
**samplers
= &layer
->sampler_views
[0];
328 unsigned num_sampler_views
= !samplers
[1] ? 1 : !samplers
[2] ? 2 : 3;
329 struct cs_viewport drawn
;
331 drawn
.area
= calc_drawn_area(s
, layer
);
332 drawn
.scale_x
= layer
->viewport
.scale
[0] /
333 (float)layer
->sampler_views
[0]->texture
->width0
;
334 drawn
.scale_y
= drawn
.scale_x
;
335 drawn
.translate_x
= (int)layer
->viewport
.translate
[0];
336 drawn
.translate_y
= (int)layer
->viewport
.translate
[1];
337 drawn
.sampler0_w
= (float)layer
->sampler_views
[0]->texture
->width0
;
338 drawn
.sampler0_h
= (float)layer
->sampler_views
[0]->texture
->height0
;
340 if (memcmp(&drawn
, &old_drawn
, sizeof(struct cs_viewport
))) {
341 set_viewport(s
, &drawn
);
345 c
->pipe
->bind_sampler_states(c
->pipe
, PIPE_SHADER_COMPUTE
, 0,
346 num_sampler_views
, layer
->samplers
);
347 c
->pipe
->set_sampler_views(c
->pipe
, PIPE_SHADER_COMPUTE
, 0,
348 num_sampler_views
, samplers
);
350 cs_launch(c
, layer
->cs
, &(drawn
.area
));
353 struct u_rect drawn
= calc_drawn_area(s
, layer
);
354 dirty
->x0
= MIN2(drawn
.x0
, dirty
->x0
);
355 dirty
->y0
= MIN2(drawn
.y0
, dirty
->y0
);
356 dirty
->x1
= MAX2(drawn
.x1
, dirty
->x1
);
357 dirty
->y1
= MAX2(drawn
.y1
, dirty
->y1
);
364 vl_compositor_cs_create_shader(struct vl_compositor
*c
,
365 const char *compute_shader_text
)
367 assert(c
&& compute_shader_text
);
369 struct tgsi_token tokens
[1024];
370 if (!tgsi_text_translate(compute_shader_text
, tokens
, ARRAY_SIZE(tokens
))) {
375 struct pipe_compute_state state
= {};
376 state
.ir_type
= PIPE_SHADER_IR_TGSI
;
379 /* create compute shader */
380 return c
->pipe
->create_compute_state(c
->pipe
, &state
);
384 vl_compositor_cs_render(struct vl_compositor_state
*s
,
385 struct vl_compositor
*c
,
386 struct pipe_surface
*dst_surface
,
387 struct u_rect
*dirty_area
,
393 c
->fb_state
.width
= dst_surface
->width
;
394 c
->fb_state
.height
= dst_surface
->height
;
395 c
->fb_state
.cbufs
[0] = dst_surface
;
397 if (!s
->scissor_valid
) {
400 s
->scissor
.maxx
= dst_surface
->width
;
401 s
->scissor
.maxy
= dst_surface
->height
;
404 if (clear_dirty
&& dirty_area
&&
405 (dirty_area
->x0
< dirty_area
->x1
|| dirty_area
->y0
< dirty_area
->y1
)) {
407 c
->pipe
->clear_render_target(c
->pipe
, dst_surface
, &s
->clear_color
,
408 0, 0, dst_surface
->width
, dst_surface
->height
, false);
409 dirty_area
->x0
= dirty_area
->y0
= VL_COMPOSITOR_MAX_DIRTY
;
410 dirty_area
->x1
= dirty_area
->y1
= VL_COMPOSITOR_MIN_DIRTY
;
413 pipe_set_constant_buffer(c
->pipe
, PIPE_SHADER_COMPUTE
, 0, s
->shader_params
);
415 draw_layers(c
, s
, dirty_area
);