Path: blob/21.2-virgl/src/gallium/drivers/softpipe/sp_image.c
4570 views
/*1* Copyright 2016 Red Hat.2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* on the rights to use, copy, modify, merge, publish, distribute, sub7* license, and/or sell copies of the Software, and to permit persons to whom8* the Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL17* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,18* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR19* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE20* USE OR OTHER DEALINGS IN THE SOFTWARE.21*/2223#include "sp_context.h"24#include "sp_image.h"25#include "sp_texture.h"2627#include "util/format/u_format.h"2829/*30* Get the offset into the base image31* first element for a buffer or layer/level for texture.32*/33static uint32_t34get_image_offset(const struct softpipe_resource *spr,35const struct pipe_image_view *iview,36enum pipe_format format, unsigned r_coord)37{38int base_layer = 0;3940if (spr->base.target == PIPE_BUFFER)41return iview->u.buf.offset;4243if (spr->base.target == PIPE_TEXTURE_1D_ARRAY ||44spr->base.target == PIPE_TEXTURE_2D_ARRAY ||45spr->base.target == PIPE_TEXTURE_CUBE_ARRAY ||46spr->base.target == PIPE_TEXTURE_CUBE ||47spr->base.target == PIPE_TEXTURE_3D)48base_layer = r_coord + iview->u.tex.first_layer;49return softpipe_get_tex_image_offset(spr, iview->u.tex.level, base_layer);50}5152/*53* Does this texture instruction have a layer or depth parameter.54*/55static inline bool56has_layer_or_depth(unsigned tgsi_tex_instr)57{58return (tgsi_tex_instr == TGSI_TEXTURE_3D ||59tgsi_tex_instr == TGSI_TEXTURE_CUBE ||60tgsi_tex_instr == TGSI_TEXTURE_1D_ARRAY ||61tgsi_tex_instr == TGSI_TEXTURE_2D_ARRAY ||62tgsi_tex_instr == TGSI_TEXTURE_CUBE_ARRAY ||63tgsi_tex_instr == TGSI_TEXTURE_2D_ARRAY_MSAA);64}6566/*67* Is this texture instruction a single non-array coordinate.68*/69static inline bool70has_1coord(unsigned tgsi_tex_instr)71{72return (tgsi_tex_instr == TGSI_TEXTURE_BUFFER ||73tgsi_tex_instr == TGSI_TEXTURE_1D ||74tgsi_tex_instr == TGSI_TEXTURE_1D_ARRAY);75}7677/*78* check the bounds vs w/h/d79*/80static inline bool81bounds_check(int width, int height, int depth,82int s, int t, int r)83{84if (s < 0 || s >= width)85return false;86if (t < 0 || t >= height)87return false;88if (r < 0 || r >= depth)89return false;90return true;91}9293/*94* Checks if the texture target compatible with the image resource95* pipe target.96*/97static inline bool98has_compat_target(unsigned pipe_target, unsigned tgsi_target)99{100switch (pipe_target) {101case PIPE_TEXTURE_1D:102if (tgsi_target == TGSI_TEXTURE_1D)103return true;104break;105case PIPE_TEXTURE_2D:106if (tgsi_target == TGSI_TEXTURE_2D)107return true;108break;109case PIPE_TEXTURE_RECT:110if (tgsi_target == TGSI_TEXTURE_RECT)111return true;112break;113case PIPE_TEXTURE_3D:114if (tgsi_target == TGSI_TEXTURE_3D ||115tgsi_target == TGSI_TEXTURE_2D)116return true;117break;118case PIPE_TEXTURE_CUBE:119if (tgsi_target == TGSI_TEXTURE_CUBE ||120tgsi_target == TGSI_TEXTURE_2D)121return true;122break;123case PIPE_TEXTURE_1D_ARRAY:124if (tgsi_target == TGSI_TEXTURE_1D ||125tgsi_target == TGSI_TEXTURE_1D_ARRAY)126return true;127break;128case PIPE_TEXTURE_2D_ARRAY:129if (tgsi_target == TGSI_TEXTURE_2D ||130tgsi_target == TGSI_TEXTURE_2D_ARRAY)131return true;132break;133case PIPE_TEXTURE_CUBE_ARRAY:134if (tgsi_target == TGSI_TEXTURE_CUBE ||135tgsi_target == TGSI_TEXTURE_CUBE_ARRAY ||136tgsi_target == TGSI_TEXTURE_2D)137return true;138break;139case PIPE_BUFFER:140return (tgsi_target == TGSI_TEXTURE_BUFFER);141}142return false;143}144145static bool146get_dimensions(const struct pipe_image_view *iview,147const struct softpipe_resource *spr,148unsigned tgsi_tex_instr,149enum pipe_format pformat,150unsigned *width,151unsigned *height,152unsigned *depth)153{154if (tgsi_tex_instr == TGSI_TEXTURE_BUFFER) {155*width = iview->u.buf.size / util_format_get_blocksize(pformat);156*height = 1;157*depth = 1;158/*159* Bounds check the buffer size from the view160* and the buffer size from the underlying buffer.161*/162if (util_format_get_stride(pformat, *width) >163util_format_get_stride(spr->base.format, spr->base.width0))164return false;165} else {166unsigned level;167168level = spr->base.target == PIPE_BUFFER ? 0 : iview->u.tex.level;169*width = u_minify(spr->base.width0, level);170*height = u_minify(spr->base.height0, level);171172if (spr->base.target == PIPE_TEXTURE_3D)173*depth = u_minify(spr->base.depth0, level);174else175*depth = spr->base.array_size;176177/* Make sure the resource and view have compatible formats */178if (util_format_get_blocksize(pformat) >179util_format_get_blocksize(spr->base.format))180return false;181}182return true;183}184185static void186fill_coords(const struct tgsi_image_params *params,187unsigned index,188const int s[TGSI_QUAD_SIZE],189const int t[TGSI_QUAD_SIZE],190const int r[TGSI_QUAD_SIZE],191int *s_coord, int *t_coord, int *r_coord)192{193*s_coord = s[index];194*t_coord = has_1coord(params->tgsi_tex_instr) ? 0 : t[index];195*r_coord = has_layer_or_depth(params->tgsi_tex_instr) ?196(params->tgsi_tex_instr == TGSI_TEXTURE_1D_ARRAY ? t[index] : r[index]) : 0;197}198/*199* Implement the image LOAD operation.200*/201static void202sp_tgsi_load(const struct tgsi_image *image,203const struct tgsi_image_params *params,204const int s[TGSI_QUAD_SIZE],205const int t[TGSI_QUAD_SIZE],206const int r[TGSI_QUAD_SIZE],207const int sample[TGSI_QUAD_SIZE],208float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])209{210struct sp_tgsi_image *sp_img = (struct sp_tgsi_image *)image;211struct pipe_image_view *iview;212struct softpipe_resource *spr;213unsigned width, height, depth;214unsigned stride;215int c, j;216char *data_ptr;217unsigned offset = 0;218219if (params->unit >= PIPE_MAX_SHADER_IMAGES)220goto fail_write_all_zero;221iview = &sp_img->sp_iview[params->unit];222spr = (struct softpipe_resource *)iview->resource;223if (!spr)224goto fail_write_all_zero;225226if (!has_compat_target(spr->base.target, params->tgsi_tex_instr))227goto fail_write_all_zero;228229if (!get_dimensions(iview, spr, params->tgsi_tex_instr,230params->format, &width, &height, &depth))231return;232233stride = util_format_get_stride(params->format, width);234235for (j = 0; j < TGSI_QUAD_SIZE; j++) {236int s_coord, t_coord, r_coord;237bool fill_zero = false;238239if (!(params->execmask & (1 << j)))240fill_zero = true;241242fill_coords(params, j, s, t, r, &s_coord, &t_coord, &r_coord);243if (!bounds_check(width, height, depth,244s_coord, t_coord, r_coord))245fill_zero = true;246247if (fill_zero) {248int nc = util_format_get_nr_components(params->format);249int ival = util_format_is_pure_integer(params->format);250for (c = 0; c < 4; c++) {251rgba[c][j] = 0;252if (c == 3 && nc < 4) {253if (ival)254((int32_t *)rgba[c])[j] = 1;255else256rgba[c][j] = 1.0;257}258}259continue;260}261offset = get_image_offset(spr, iview, params->format, r_coord);262data_ptr = (char *)spr->data + offset;263264uint32_t sdata[4];265util_format_read_4(params->format,266sdata, 0,267data_ptr, stride,268s_coord, t_coord, 1, 1);269for (c = 0; c < 4; c++)270((uint32_t *)rgba[c])[j] = sdata[c];271}272return;273fail_write_all_zero:274for (j = 0; j < TGSI_QUAD_SIZE; j++) {275for (c = 0; c < 4; c++)276rgba[c][j] = 0;277}278return;279}280281/*282* Implement the image STORE operation.283*/284static void285sp_tgsi_store(const struct tgsi_image *image,286const struct tgsi_image_params *params,287const int s[TGSI_QUAD_SIZE],288const int t[TGSI_QUAD_SIZE],289const int r[TGSI_QUAD_SIZE],290const int sample[TGSI_QUAD_SIZE],291float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])292{293struct sp_tgsi_image *sp_img = (struct sp_tgsi_image *)image;294struct pipe_image_view *iview;295struct softpipe_resource *spr;296unsigned width, height, depth;297unsigned stride;298char *data_ptr;299int j, c;300unsigned offset = 0;301unsigned pformat = params->format;302303if (params->unit >= PIPE_MAX_SHADER_IMAGES)304return;305iview = &sp_img->sp_iview[params->unit];306spr = (struct softpipe_resource *)iview->resource;307if (!spr)308return;309if (!has_compat_target(spr->base.target, params->tgsi_tex_instr))310return;311312if (params->format == PIPE_FORMAT_NONE)313pformat = spr->base.format;314315if (!get_dimensions(iview, spr, params->tgsi_tex_instr,316pformat, &width, &height, &depth))317return;318319stride = util_format_get_stride(pformat, width);320321for (j = 0; j < TGSI_QUAD_SIZE; j++) {322int s_coord, t_coord, r_coord;323324if (!(params->execmask & (1 << j)))325continue;326327fill_coords(params, j, s, t, r, &s_coord, &t_coord, &r_coord);328if (!bounds_check(width, height, depth,329s_coord, t_coord, r_coord))330continue;331332offset = get_image_offset(spr, iview, pformat, r_coord);333data_ptr = (char *)spr->data + offset;334335uint32_t sdata[4];336for (c = 0; c < 4; c++)337sdata[c] = ((uint32_t *)rgba[c])[j];338util_format_write_4(pformat, sdata, 0, data_ptr, stride,339s_coord, t_coord, 1, 1);340}341}342343/*344* Implement atomic operations on unsigned integers.345*/346static void347handle_op_uint(const struct pipe_image_view *iview,348const struct tgsi_image_params *params,349bool just_read,350char *data_ptr,351uint qi,352unsigned stride,353enum tgsi_opcode opcode,354int s,355int t,356float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE],357float rgba2[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])358{359uint c;360int nc = util_format_get_nr_components(params->format);361unsigned sdata[4];362363util_format_read_4(params->format,364sdata, 0,365data_ptr, stride,366s, t, 1, 1);367368if (just_read) {369for (c = 0; c < nc; c++) {370((uint32_t *)rgba[c])[qi] = sdata[c];371}372return;373}374switch (opcode) {375case TGSI_OPCODE_ATOMUADD:376for (c = 0; c < nc; c++) {377unsigned temp = sdata[c];378sdata[c] += ((uint32_t *)rgba[c])[qi];379((uint32_t *)rgba[c])[qi] = temp;380}381break;382case TGSI_OPCODE_ATOMXCHG:383for (c = 0; c < nc; c++) {384unsigned temp = sdata[c];385sdata[c] = ((uint32_t *)rgba[c])[qi];386((uint32_t *)rgba[c])[qi] = temp;387}388break;389case TGSI_OPCODE_ATOMCAS:390for (c = 0; c < nc; c++) {391unsigned dst_x = sdata[c];392unsigned cmp_x = ((uint32_t *)rgba[c])[qi];393unsigned src_x = ((uint32_t *)rgba2[c])[qi];394unsigned temp = sdata[c];395sdata[c] = (dst_x == cmp_x) ? src_x : dst_x;396((uint32_t *)rgba[c])[qi] = temp;397}398break;399case TGSI_OPCODE_ATOMAND:400for (c = 0; c < nc; c++) {401unsigned temp = sdata[c];402sdata[c] &= ((uint32_t *)rgba[c])[qi];403((uint32_t *)rgba[c])[qi] = temp;404}405break;406case TGSI_OPCODE_ATOMOR:407for (c = 0; c < nc; c++) {408unsigned temp = sdata[c];409sdata[c] |= ((uint32_t *)rgba[c])[qi];410((uint32_t *)rgba[c])[qi] = temp;411}412break;413case TGSI_OPCODE_ATOMXOR:414for (c = 0; c < nc; c++) {415unsigned temp = sdata[c];416sdata[c] ^= ((uint32_t *)rgba[c])[qi];417((uint32_t *)rgba[c])[qi] = temp;418}419break;420case TGSI_OPCODE_ATOMUMIN:421for (c = 0; c < nc; c++) {422unsigned dst_x = sdata[c];423unsigned src_x = ((uint32_t *)rgba[c])[qi];424sdata[c] = MIN2(dst_x, src_x);425((uint32_t *)rgba[c])[qi] = dst_x;426}427break;428case TGSI_OPCODE_ATOMUMAX:429for (c = 0; c < nc; c++) {430unsigned dst_x = sdata[c];431unsigned src_x = ((uint32_t *)rgba[c])[qi];432sdata[c] = MAX2(dst_x, src_x);433((uint32_t *)rgba[c])[qi] = dst_x;434}435break;436case TGSI_OPCODE_ATOMIMIN:437for (c = 0; c < nc; c++) {438int dst_x = sdata[c];439int src_x = ((uint32_t *)rgba[c])[qi];440sdata[c] = MIN2(dst_x, src_x);441((uint32_t *)rgba[c])[qi] = dst_x;442}443break;444case TGSI_OPCODE_ATOMIMAX:445for (c = 0; c < nc; c++) {446int dst_x = sdata[c];447int src_x = ((uint32_t *)rgba[c])[qi];448sdata[c] = MAX2(dst_x, src_x);449((uint32_t *)rgba[c])[qi] = dst_x;450}451break;452default:453assert(!"Unexpected TGSI opcode in sp_tgsi_op");454break;455}456util_format_write_4(params->format, sdata, 0, data_ptr, stride,457s, t, 1, 1);458}459460/*461* Implement atomic operations on signed integers.462*/463static void464handle_op_int(const struct pipe_image_view *iview,465const struct tgsi_image_params *params,466bool just_read,467char *data_ptr,468uint qi,469unsigned stride,470enum tgsi_opcode opcode,471int s,472int t,473float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE],474float rgba2[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])475{476uint c;477int nc = util_format_get_nr_components(params->format);478int sdata[4];479util_format_read_4(params->format,480sdata, 0,481data_ptr, stride,482s, t, 1, 1);483484if (just_read) {485for (c = 0; c < nc; c++) {486((int32_t *)rgba[c])[qi] = sdata[c];487}488return;489}490switch (opcode) {491case TGSI_OPCODE_ATOMUADD:492for (c = 0; c < nc; c++) {493int temp = sdata[c];494sdata[c] += ((int32_t *)rgba[c])[qi];495((int32_t *)rgba[c])[qi] = temp;496}497break;498case TGSI_OPCODE_ATOMXCHG:499for (c = 0; c < nc; c++) {500int temp = sdata[c];501sdata[c] = ((int32_t *)rgba[c])[qi];502((int32_t *)rgba[c])[qi] = temp;503}504break;505case TGSI_OPCODE_ATOMCAS:506for (c = 0; c < nc; c++) {507int dst_x = sdata[c];508int cmp_x = ((int32_t *)rgba[c])[qi];509int src_x = ((int32_t *)rgba2[c])[qi];510int temp = sdata[c];511sdata[c] = (dst_x == cmp_x) ? src_x : dst_x;512((int32_t *)rgba[c])[qi] = temp;513}514break;515case TGSI_OPCODE_ATOMAND:516for (c = 0; c < nc; c++) {517int temp = sdata[c];518sdata[c] &= ((int32_t *)rgba[c])[qi];519((int32_t *)rgba[c])[qi] = temp;520}521break;522case TGSI_OPCODE_ATOMOR:523for (c = 0; c < nc; c++) {524int temp = sdata[c];525sdata[c] |= ((int32_t *)rgba[c])[qi];526((int32_t *)rgba[c])[qi] = temp;527}528break;529case TGSI_OPCODE_ATOMXOR:530for (c = 0; c < nc; c++) {531int temp = sdata[c];532sdata[c] ^= ((int32_t *)rgba[c])[qi];533((int32_t *)rgba[c])[qi] = temp;534}535break;536case TGSI_OPCODE_ATOMUMIN:537for (c = 0; c < nc; c++) {538int dst_x = sdata[c];539int src_x = ((int32_t *)rgba[c])[qi];540sdata[c] = MIN2(dst_x, src_x);541((int32_t *)rgba[c])[qi] = dst_x;542}543break;544case TGSI_OPCODE_ATOMUMAX:545for (c = 0; c < nc; c++) {546int dst_x = sdata[c];547int src_x = ((int32_t *)rgba[c])[qi];548sdata[c] = MAX2(dst_x, src_x);549((int32_t *)rgba[c])[qi] = dst_x;550}551break;552case TGSI_OPCODE_ATOMIMIN:553for (c = 0; c < nc; c++) {554int dst_x = sdata[c];555int src_x = ((int32_t *)rgba[c])[qi];556sdata[c] = MIN2(dst_x, src_x);557((int32_t *)rgba[c])[qi] = dst_x;558}559break;560case TGSI_OPCODE_ATOMIMAX:561for (c = 0; c < nc; c++) {562int dst_x = sdata[c];563int src_x = ((int32_t *)rgba[c])[qi];564sdata[c] = MAX2(dst_x, src_x);565((int32_t *)rgba[c])[qi] = dst_x;566}567break;568default:569assert(!"Unexpected TGSI opcode in sp_tgsi_op");570break;571}572util_format_write_4(params->format, sdata, 0, data_ptr, stride,573s, t, 1, 1);574}575576/* GLES OES_shader_image_atomic.txt allows XCHG on R32F */577static void578handle_op_r32f_xchg(const struct pipe_image_view *iview,579const struct tgsi_image_params *params,580bool just_read,581char *data_ptr,582uint qi,583unsigned stride,584enum tgsi_opcode opcode,585int s,586int t,587float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])588{589float sdata[4];590uint c;591int nc = 1;592util_format_read_4(params->format,593sdata, 0,594data_ptr, stride,595s, t, 1, 1);596if (just_read) {597for (c = 0; c < nc; c++) {598((int32_t *)rgba[c])[qi] = sdata[c];599}600return;601}602603for (c = 0; c < nc; c++) {604int temp = sdata[c];605sdata[c] = ((float *)rgba[c])[qi];606((float *)rgba[c])[qi] = temp;607}608util_format_write_4(params->format, sdata, 0, data_ptr, stride,609s, t, 1, 1);610}611612/*613* Implement atomic image operations.614*/615static void616sp_tgsi_op(const struct tgsi_image *image,617const struct tgsi_image_params *params,618enum tgsi_opcode opcode,619const int s[TGSI_QUAD_SIZE],620const int t[TGSI_QUAD_SIZE],621const int r[TGSI_QUAD_SIZE],622const int sample[TGSI_QUAD_SIZE],623float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE],624float rgba2[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])625{626struct sp_tgsi_image *sp_img = (struct sp_tgsi_image *)image;627struct pipe_image_view *iview;628struct softpipe_resource *spr;629unsigned width, height, depth;630unsigned stride;631int j, c;632unsigned offset;633char *data_ptr;634635if (params->unit >= PIPE_MAX_SHADER_IMAGES)636return;637iview = &sp_img->sp_iview[params->unit];638spr = (struct softpipe_resource *)iview->resource;639if (!spr)640goto fail_write_all_zero;641if (!has_compat_target(spr->base.target, params->tgsi_tex_instr))642goto fail_write_all_zero;643644if (!get_dimensions(iview, spr, params->tgsi_tex_instr,645params->format, &width, &height, &depth))646goto fail_write_all_zero;647648stride = util_format_get_stride(spr->base.format, width);649650for (j = 0; j < TGSI_QUAD_SIZE; j++) {651int s_coord, t_coord, r_coord;652bool just_read = false;653654fill_coords(params, j, s, t, r, &s_coord, &t_coord, &r_coord);655if (!bounds_check(width, height, depth,656s_coord, t_coord, r_coord)) {657int nc = util_format_get_nr_components(params->format);658int ival = util_format_is_pure_integer(params->format);659int c;660for (c = 0; c < 4; c++) {661rgba[c][j] = 0;662if (c == 3 && nc < 4) {663if (ival)664((int32_t *)rgba[c])[j] = 1;665else666rgba[c][j] = 1.0;667}668}669continue;670}671672/* just readback the value for atomic if execmask isn't set */673if (!(params->execmask & (1 << j))) {674just_read = true;675}676677offset = get_image_offset(spr, iview, params->format, r_coord);678data_ptr = (char *)spr->data + offset;679680/* we should see atomic operations on r32 formats */681if (util_format_is_pure_uint(params->format))682handle_op_uint(iview, params, just_read, data_ptr, j, stride,683opcode, s_coord, t_coord, rgba, rgba2);684else if (util_format_is_pure_sint(params->format))685handle_op_int(iview, params, just_read, data_ptr, j, stride,686opcode, s_coord, t_coord, rgba, rgba2);687else if (params->format == PIPE_FORMAT_R32_FLOAT &&688opcode == TGSI_OPCODE_ATOMXCHG)689handle_op_r32f_xchg(iview, params, just_read, data_ptr, j, stride,690opcode, s_coord, t_coord, rgba);691else692assert(0);693}694return;695fail_write_all_zero:696for (j = 0; j < TGSI_QUAD_SIZE; j++) {697for (c = 0; c < 4; c++)698rgba[c][j] = 0;699}700return;701}702703static void704sp_tgsi_get_dims(const struct tgsi_image *image,705const struct tgsi_image_params *params,706int dims[4])707{708struct sp_tgsi_image *sp_img = (struct sp_tgsi_image *)image;709struct pipe_image_view *iview;710struct softpipe_resource *spr;711int level;712713if (params->unit >= PIPE_MAX_SHADER_IMAGES)714return;715iview = &sp_img->sp_iview[params->unit];716spr = (struct softpipe_resource *)iview->resource;717if (!spr)718return;719720if (params->tgsi_tex_instr == TGSI_TEXTURE_BUFFER) {721dims[0] = iview->u.buf.size / util_format_get_blocksize(iview->format);722dims[1] = dims[2] = dims[3] = 0;723return;724}725726level = iview->u.tex.level;727dims[0] = u_minify(spr->base.width0, level);728switch (params->tgsi_tex_instr) {729case TGSI_TEXTURE_1D_ARRAY:730dims[1] = iview->u.tex.last_layer - iview->u.tex.first_layer + 1;731FALLTHROUGH;732case TGSI_TEXTURE_1D:733return;734case TGSI_TEXTURE_2D_ARRAY:735dims[2] = iview->u.tex.last_layer - iview->u.tex.first_layer + 1;736FALLTHROUGH;737case TGSI_TEXTURE_2D:738case TGSI_TEXTURE_CUBE:739case TGSI_TEXTURE_RECT:740dims[1] = u_minify(spr->base.height0, level);741return;742case TGSI_TEXTURE_3D:743dims[1] = u_minify(spr->base.height0, level);744dims[2] = u_minify(spr->base.depth0, level);745return;746case TGSI_TEXTURE_CUBE_ARRAY:747dims[1] = u_minify(spr->base.height0, level);748dims[2] = (iview->u.tex.last_layer - iview->u.tex.first_layer + 1) / 6;749break;750default:751assert(!"unexpected texture target in sp_get_dims()");752return;753}754}755756struct sp_tgsi_image *757sp_create_tgsi_image(void)758{759struct sp_tgsi_image *img = CALLOC_STRUCT(sp_tgsi_image);760if (!img)761return NULL;762763img->base.load = sp_tgsi_load;764img->base.store = sp_tgsi_store;765img->base.op = sp_tgsi_op;766img->base.get_dims = sp_tgsi_get_dims;767return img;768};769770771