1/************************************************************************** 2 * 3 * Copyright 2019 Sonny Jiang <sonnyj608@gmail.com> 4 * Copyright 2019 Advanced Micro Devices, Inc. 5 * All Rights Reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the 9 * "Software"), to deal in the Software without restriction, including 10 * without limitation the rights to use, copy, modify, merge, publish, 11 * distribute, sub license, and/or sell copies of the Software, and to 12 * permit persons to whom the Software is furnished to do so, subject to 13 * the following conditions: 14 * 15 * The above copyright notice and this permission notice (including the 16 * next paragraph) shall be included in all copies or substantial portions 17 * of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 22 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 23 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 * 27 **************************************************************************/ 28 29#include "pipe/p_context.h" 30#include "pipe/p_state.h" 31 32#include "u_bitcast.h" 33#include "util/format/u_format.h" 34#include "u_sampler.h" 35#include "tgsi/tgsi_text.h" 36#include "tgsi/tgsi_ureg.h" 37#include "u_inlines.h" 38#include "u_compute.h" 39 40static void *blit_compute_shader(struct pipe_context *ctx) 41{ 42 static const char text[] = 43 "COMP\n" 44 "PROPERTY CS_FIXED_BLOCK_WIDTH 64\n" 45 "PROPERTY CS_FIXED_BLOCK_HEIGHT 1\n" 46 "PROPERTY CS_FIXED_BLOCK_DEPTH 1\n" 47 "DCL SV[0], THREAD_ID\n" 48 "DCL SV[1], BLOCK_ID\n" 49 "DCL IMAGE[0], 2D_ARRAY, PIPE_FORMAT_R32G32B32A32_FLOAT, WR\n" 50 "DCL SAMP[0]\n" 51 "DCL SVIEW[0], 2D_ARRAY, FLOAT\n" 52 "DCL CONST[0][0..2]\n" // 0:xyzw 1:xyzw 53 "DCL TEMP[0..4], LOCAL\n" 54 "IMM[0] UINT32 {64, 1, 0, 0}\n" 55 56 "UMAD TEMP[0].xyz, SV[1].xyzz, IMM[0].xyyy, SV[0].xyzz\n" 57 "U2F TEMP[1].xyz, TEMP[0]\n" 58 "MAD TEMP[2].xyz, TEMP[1], CONST[0][1], CONST[0][0]\n" 59 "TEX_LZ TEMP[3], TEMP[2], SAMP[0], 2D_ARRAY\n" 60 "UADD TEMP[4].xyz, TEMP[0], CONST[0][2]\n" 61 "STORE IMAGE[0], TEMP[4], TEMP[3], 2D_ARRAY, PIPE_FORMAT_R32G32B32A32_FLOAT\n" 62 "END\n"; 63 64 struct tgsi_token tokens[1024]; 65 struct pipe_compute_state state = {0}; 66 67 if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) { 68 assert(false); 69 return NULL; 70 } 71 72 state.ir_type = PIPE_SHADER_IR_TGSI; 73 state.prog = tokens; 74 75 return ctx->create_compute_state(ctx, &state); 76} 77 78void util_compute_blit(struct pipe_context *ctx, struct pipe_blit_info *blit_info, 79 void **compute_state, bool half_texel_offset) 80{ 81 if (blit_info->src.box.width == 0 || blit_info->src.box.height == 0 || 82 blit_info->dst.box.width == 0 || blit_info->dst.box.height == 0) 83 return; 84 85 struct pipe_resource *src = blit_info->src.resource; 86 struct pipe_resource *dst = blit_info->dst.resource; 87 struct pipe_sampler_view src_templ = {0}, *src_view; 88 void *sampler_state_p; 89 unsigned width = blit_info->dst.box.width; 90 unsigned height = blit_info->dst.box.height; 91 float x_scale = blit_info->src.box.width / (float)blit_info->dst.box.width; 92 float y_scale = blit_info->src.box.height / (float)blit_info->dst.box.height; 93 float z_scale = blit_info->src.box.depth / (float)blit_info->dst.box.depth; 94 float offset = half_texel_offset ? 0.5 : 0.0; 95 96 unsigned data[] = {u_bitcast_f2u((blit_info->src.box.x + offset) / (float)src->width0), 97 u_bitcast_f2u((blit_info->src.box.y + offset) / (float)src->height0), 98 u_bitcast_f2u(blit_info->src.box.z), 99 u_bitcast_f2u(0), 100 u_bitcast_f2u(x_scale / src->width0), 101 u_bitcast_f2u(y_scale / src->height0), 102 u_bitcast_f2u(z_scale), 103 u_bitcast_f2u(0), 104 blit_info->dst.box.x, 105 blit_info->dst.box.y, 106 blit_info->dst.box.z, 107 0}; 108 109 struct pipe_constant_buffer cb = {0}; 110 cb.buffer_size = sizeof(data); 111 cb.user_buffer = data; 112 ctx->set_constant_buffer(ctx, PIPE_SHADER_COMPUTE, 0, false, &cb); 113 114 struct pipe_image_view image = {0}; 115 image.resource = dst; 116 image.shader_access = image.access = PIPE_IMAGE_ACCESS_WRITE; 117 image.format = util_format_linear(blit_info->dst.format); 118 image.u.tex.level = blit_info->dst.level; 119 image.u.tex.first_layer = 0; 120 image.u.tex.last_layer = (unsigned)(dst->array_size - 1); 121 122 ctx->set_shader_images(ctx, PIPE_SHADER_COMPUTE, 0, 1, 0, &image); 123 124 struct pipe_sampler_state sampler_state={0}; 125 sampler_state.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 126 sampler_state.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 127 sampler_state.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 128 sampler_state.normalized_coords = 1; 129 130 if (blit_info->filter == PIPE_TEX_FILTER_LINEAR) { 131 sampler_state.min_img_filter = PIPE_TEX_FILTER_LINEAR; 132 sampler_state.mag_img_filter = PIPE_TEX_FILTER_LINEAR; 133 } 134 135 sampler_state_p = ctx->create_sampler_state(ctx, &sampler_state); 136 ctx->bind_sampler_states(ctx, PIPE_SHADER_COMPUTE, 0, 1, &sampler_state_p); 137 138 /* Initialize the sampler view. */ 139 u_sampler_view_default_template(&src_templ, src, src->format); 140 src_templ.format = util_format_linear(blit_info->src.format); 141 src_view = ctx->create_sampler_view(ctx, src, &src_templ); 142 ctx->set_sampler_views(ctx, PIPE_SHADER_COMPUTE, 0, 1, 0, false, &src_view); 143 144 if (!*compute_state) 145 *compute_state = blit_compute_shader(ctx); 146 ctx->bind_compute_state(ctx, *compute_state); 147 148 struct pipe_grid_info grid_info = {0}; 149 grid_info.block[0] = 64; 150 grid_info.last_block[0] = width % 64; 151 grid_info.block[1] = 1; 152 grid_info.block[2] = 1; 153 grid_info.grid[0] = DIV_ROUND_UP(width, 64); 154 grid_info.grid[1] = height; 155 grid_info.grid[2] = 1; 156 157 ctx->launch_grid(ctx, &grid_info); 158 159 ctx->memory_barrier(ctx, PIPE_BARRIER_ALL); 160 161 ctx->set_shader_images(ctx, PIPE_SHADER_COMPUTE, 0, 0, 1, NULL); 162 ctx->set_constant_buffer(ctx, PIPE_SHADER_COMPUTE, 0, false, NULL); 163 ctx->set_sampler_views(ctx, PIPE_SHADER_COMPUTE, 0, 0, 1, false, NULL); 164 pipe_sampler_view_reference(&src_view, NULL); 165 ctx->delete_sampler_state(ctx, sampler_state_p); 166 ctx->bind_compute_state(ctx, NULL); 167} 168