diff --git a/src/gallium/auxiliary/Makefile.sources b/src/gallium/auxiliary/Makefile.sources index ae0c8f39e27..f9c0b536026 100644 --- a/src/gallium/auxiliary/Makefile.sources +++ b/src/gallium/auxiliary/Makefile.sources @@ -214,6 +214,8 @@ C_SOURCES := \ util/u_box.h \ util/u_cache.c \ util/u_cache.h \ + util/u_compute.c \ + util/u_compute.h \ util/u_debug_gallium.h \ util/u_debug_gallium.c \ util/u_debug_describe.c \ diff --git a/src/gallium/auxiliary/meson.build b/src/gallium/auxiliary/meson.build index a47b2f4a9b6..e76b2ac912e 100644 --- a/src/gallium/auxiliary/meson.build +++ b/src/gallium/auxiliary/meson.build @@ -234,6 +234,8 @@ files_libgallium = files( 'util/u_box.h', 'util/u_cache.c', 'util/u_cache.h', + 'util/u_compute.c', + 'util/u_compute.h', 'util/u_debug_gallium.h', 'util/u_debug_gallium.c', 'util/u_debug_describe.c', diff --git a/src/gallium/auxiliary/util/u_compute.c b/src/gallium/auxiliary/util/u_compute.c new file mode 100644 index 00000000000..e1e24a28c2a --- /dev/null +++ b/src/gallium/auxiliary/util/u_compute.c @@ -0,0 +1,166 @@ +/************************************************************************** + * + * Copyright 2019 Sonny Jiang + * Copyright 2019 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "pipe/p_context.h" +#include "pipe/p_state.h" + +#include "u_bitcast.h" +#include "u_format.h" +#include "u_sampler.h" +#include "tgsi/tgsi_text.h" +#include "tgsi/tgsi_ureg.h" +#include "u_inlines.h" +#include "u_compute.h" + +static void *blit_compute_shader(struct pipe_context *ctx) +{ + static const char text[] = + "COMP\n" + "PROPERTY CS_FIXED_BLOCK_WIDTH 64\n" + "PROPERTY CS_FIXED_BLOCK_HEIGHT 1\n" + "PROPERTY CS_FIXED_BLOCK_DEPTH 1\n" + "DCL SV[0], THREAD_ID\n" + "DCL SV[1], BLOCK_ID\n" + "DCL IMAGE[0], 2D_ARRAY, PIPE_FORMAT_R32G32B32A32_FLOAT, WR\n" + "DCL SAMP[0]\n" + "DCL SVIEW[0], 2D_ARRAY, FLOAT\n" + "DCL CONST[0][0..2]\n" // 0:xyzw 1:xyzw + "DCL TEMP[0..4], LOCAL\n" + "IMM[0] UINT32 {64, 1, 0, 0}\n" + + "UMAD TEMP[0].xyz, SV[1].xyzz, IMM[0].xyyy, SV[0].xyzz\n" + "U2F TEMP[1].xyz, TEMP[0]\n" + "MAD TEMP[2].xyz, TEMP[1], CONST[0][1], CONST[0][0]\n" + "TEX_LZ TEMP[3], TEMP[2], SAMP[0], 2D_ARRAY\n" + "UADD TEMP[4].xyz, TEMP[0], CONST[0][2]\n" + "STORE IMAGE[0], TEMP[4], TEMP[3], 2D_ARRAY, PIPE_FORMAT_R32G32B32A32_FLOAT\n" + "END\n"; + + struct tgsi_token tokens[1024]; + struct pipe_compute_state state = {0}; + + if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) { + assert(false); + return NULL; + } + + state.ir_type = PIPE_SHADER_IR_TGSI; + state.prog = tokens; + + return ctx->create_compute_state(ctx, &state); +} + +void util_compute_blit(struct pipe_context *ctx, struct pipe_blit_info *blit_info, + void **compute_state) +{ + if (blit_info->src.box.width == 0 || blit_info->src.box.height == 0 || + blit_info->dst.box.width == 0 || blit_info->dst.box.height == 0) + return; + + struct pipe_resource *src = blit_info->src.resource; + struct pipe_resource *dst = blit_info->dst.resource; + struct pipe_sampler_view src_templ = {0}, *src_view; + void *sampler_state_p; + unsigned width = blit_info->dst.box.width; + unsigned height = blit_info->dst.box.height; + float x_scale = blit_info->src.box.width / (float)blit_info->dst.box.width; + float y_scale = blit_info->src.box.height / (float)blit_info->dst.box.height; + float z_scale = blit_info->src.box.depth / (float)blit_info->dst.box.depth; + + unsigned data[] = {u_bitcast_f2u((blit_info->src.box.x + 0.5) / (float)src->width0), + u_bitcast_f2u((blit_info->src.box.y + 0.5) / (float)src->height0), + u_bitcast_f2u(blit_info->src.box.z), + u_bitcast_f2u(0), + u_bitcast_f2u(x_scale / src->width0), + u_bitcast_f2u(y_scale / src->height0), + u_bitcast_f2u(z_scale), + u_bitcast_f2u(0), + blit_info->dst.box.x, + blit_info->dst.box.y, + blit_info->dst.box.z, + 0}; + + struct pipe_constant_buffer cb = {}; + cb.buffer_size = sizeof(data); + cb.user_buffer = data; + ctx->set_constant_buffer(ctx, PIPE_SHADER_COMPUTE, 0, &cb); + + struct pipe_image_view image = {0}; + image.resource = dst; + image.shader_access = image.access = PIPE_IMAGE_ACCESS_WRITE; + image.format = util_format_linear(blit_info->dst.format); + image.u.tex.level = blit_info->dst.level; + image.u.tex.first_layer = 0; + image.u.tex.last_layer = (unsigned)(dst->array_size - 1); + + ctx->set_shader_images(ctx, PIPE_SHADER_COMPUTE, 0, 1, &image); + + /* Initialize the sampler view. */ + u_sampler_view_default_template(&src_templ, src, src->format); + src_templ.format = util_format_linear(blit_info->src.format); + src_view = ctx->create_sampler_view(ctx, src, &src_templ); + ctx->set_sampler_views(ctx, PIPE_SHADER_COMPUTE, 0, 1, &src_view); + + struct pipe_sampler_state sampler_state={0}; + sampler_state.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + sampler_state.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + sampler_state.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + sampler_state.normalized_coords = 1; + + if (blit_info->filter == PIPE_TEX_FILTER_LINEAR) { + sampler_state.min_img_filter = PIPE_TEX_FILTER_LINEAR; + sampler_state.mag_img_filter = PIPE_TEX_FILTER_LINEAR; + } + + sampler_state_p = ctx->create_sampler_state(ctx, &sampler_state); + ctx->bind_sampler_states(ctx, PIPE_SHADER_COMPUTE, 0, 1, &sampler_state_p); + + if (!*compute_state) + *compute_state = blit_compute_shader(ctx); + ctx->bind_compute_state(ctx, *compute_state); + + struct pipe_grid_info grid_info = {0}; + grid_info.block[0] = 64; + grid_info.last_block[0] = width % 64; + grid_info.block[1] = 1; + grid_info.block[2] = 1; + grid_info.grid[0] = DIV_ROUND_UP(width, 64); + grid_info.grid[1] = height; + grid_info.grid[2] = 1; + + ctx->launch_grid(ctx, &grid_info); + + ctx->memory_barrier(ctx, PIPE_BARRIER_ALL); + + ctx->set_shader_images(ctx, PIPE_SHADER_COMPUTE, 0, 1, NULL); + ctx->set_constant_buffer(ctx, PIPE_SHADER_COMPUTE, 0, NULL); + ctx->set_sampler_views(ctx, PIPE_SHADER_COMPUTE, 0, 1, NULL); + pipe_sampler_view_reference(&src_view, NULL); + ctx->delete_sampler_state(ctx, sampler_state_p); + ctx->bind_compute_state(ctx, NULL); +} diff --git a/src/gallium/auxiliary/util/u_compute.h b/src/gallium/auxiliary/util/u_compute.h new file mode 100644 index 00000000000..8c2866af8d4 --- /dev/null +++ b/src/gallium/auxiliary/util/u_compute.h @@ -0,0 +1,45 @@ +/************************************************************************** + * Copyright 2019 Sonny Jiang + * Copyright 2019 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef U_COMPUTE_H +#define U_COMPUTE_H + +#include "pipe/p_context.h" +#include "pipe/p_state.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void util_compute_blit(struct pipe_context *ctx, struct pipe_blit_info *blit_info, + void **compute_state); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/gallium/state_trackers/va/context.c b/src/gallium/state_trackers/va/context.c index 47a5e7be230..9176b7e8c5d 100644 --- a/src/gallium/state_trackers/va/context.c +++ b/src/gallium/state_trackers/va/context.c @@ -364,6 +364,8 @@ vlVaDestroyContext(VADriverContextP ctx, VAContextID context_id) } context->decoder->destroy(context->decoder); } + if (context->blit_cs) + drv->pipe->delete_compute_state(drv->pipe, context->blit_cs); if (context->deint) { vl_deint_filter_cleanup(context->deint); FREE(context->deint); diff --git a/src/gallium/state_trackers/va/postproc.c b/src/gallium/state_trackers/va/postproc.c index 21d316c7e97..fbc55b7714b 100644 --- a/src/gallium/state_trackers/va/postproc.c +++ b/src/gallium/state_trackers/va/postproc.c @@ -27,6 +27,7 @@ #include "util/u_handle_table.h" #include "util/u_memory.h" +#include "util/u_compute.h" #include "vl/vl_defines.h" #include "vl/vl_video_buffer.h" @@ -220,7 +221,11 @@ static VAStatus vlVaPostProcBlit(vlVaDriver *drv, vlVaContext *context, blit.mask = PIPE_MASK_RGBA; blit.filter = PIPE_TEX_MIPFILTER_LINEAR; - drv->pipe->blit(drv->pipe, &blit); + if (drv->pipe->screen->get_param(drv->pipe->screen, + PIPE_CAP_PREFER_COMPUTE_BLIT_FOR_MULTIMEDIA)) + util_compute_blit(drv->pipe, &blit, &context->blit_cs); + else + drv->pipe->blit(drv->pipe, &blit); } // TODO: figure out why this is necessary for DMA-buf sharing diff --git a/src/gallium/state_trackers/va/va_private.h b/src/gallium/state_trackers/va/va_private.h index c4b49e30509..b2b997d4799 100644 --- a/src/gallium/state_trackers/va/va_private.h +++ b/src/gallium/state_trackers/va/va_private.h @@ -312,6 +312,7 @@ typedef struct { bool first_single_submitted; int gop_coeff; bool needs_begin_frame; + void *blit_cs; } vlVaContext; typedef struct {