Path: blob/21.2-virgl/src/gallium/drivers/freedreno/a6xx/fd6_image.c
4574 views
/*1* Copyright (C) 2017 Rob Clark <[email protected]>2* Copyright © 2018 Google, Inc.3*4* Permission is hereby granted, free of charge, to any person obtaining a5* copy of this software and associated documentation files (the "Software"),6* to deal in the Software without restriction, including without limitation7* the rights to use, copy, modify, merge, publish, distribute, sublicense,8* and/or sell copies of the Software, and to permit persons to whom the9* Software is furnished to do so, subject to the following conditions:10*11* The above copyright notice and this permission notice (including the next12* paragraph) shall be included in all copies or substantial portions of the13* Software.14*15* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR16* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,17* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL18* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER19* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,20* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE21* SOFTWARE.22*23* Authors:24* Rob Clark <[email protected]>25*/2627#include "pipe/p_state.h"2829#include "freedreno_resource.h"30#include "freedreno_state.h"3132#include "fd6_format.h"33#include "fd6_image.h"34#include "fd6_resource.h"35#include "fd6_texture.h"3637struct fd6_image {38struct pipe_resource *prsc;39enum pipe_format pfmt;40enum a6xx_tex_type type;41bool srgb;42uint32_t cpp;43uint32_t level;44uint32_t width;45uint32_t height;46uint32_t depth;47uint32_t pitch;48uint32_t array_pitch;49struct fd_bo *bo;50uint32_t ubwc_offset;51uint32_t offset;52bool buffer;53};5455static void56translate_image(struct fd6_image *img, const struct pipe_image_view *pimg)57{58enum pipe_format format = pimg->format;59struct pipe_resource *prsc = pimg->resource;60struct fd_resource *rsc = fd_resource(prsc);6162if (!prsc) {63memset(img, 0, sizeof(*img));64return;65}6667img->prsc = prsc;68img->pfmt = format;69img->type = fd6_tex_type(prsc->target);70img->srgb = util_format_is_srgb(format);71img->cpp = rsc->layout.cpp;72img->bo = rsc->bo;7374/* Treat cube textures as 2d-array: */75if (img->type == A6XX_TEX_CUBE)76img->type = A6XX_TEX_2D;7778if (prsc->target == PIPE_BUFFER) {79img->buffer = true;80img->ubwc_offset = 0; /* not valid for buffers */81img->offset = pimg->u.buf.offset;82img->pitch = 0;83img->array_pitch = 0;8485/* size is encoded with low 15b in WIDTH and high bits in86* HEIGHT, in units of elements:87*/88unsigned sz = pimg->u.buf.size / util_format_get_blocksize(format);89img->width = sz & MASK(15);90img->height = sz >> 15;91img->depth = 0;92img->level = 0;93} else {94img->buffer = false;9596unsigned lvl = pimg->u.tex.level;97unsigned layers = pimg->u.tex.last_layer - pimg->u.tex.first_layer + 1;9899img->ubwc_offset =100fd_resource_ubwc_offset(rsc, lvl, pimg->u.tex.first_layer);101img->offset = fd_resource_offset(rsc, lvl, pimg->u.tex.first_layer);102img->pitch = fd_resource_pitch(rsc, lvl);103104switch (prsc->target) {105case PIPE_TEXTURE_RECT:106case PIPE_TEXTURE_1D:107case PIPE_TEXTURE_2D:108img->array_pitch = rsc->layout.layer_size;109img->depth = 1;110break;111case PIPE_TEXTURE_1D_ARRAY:112case PIPE_TEXTURE_2D_ARRAY:113case PIPE_TEXTURE_CUBE:114case PIPE_TEXTURE_CUBE_ARRAY:115img->array_pitch = rsc->layout.layer_size;116// TODO the CUBE/CUBE_ARRAY might need to be layers/6 for tex state,117// but empirically for ibo state it shouldn't be divided.118img->depth = layers;119break;120case PIPE_TEXTURE_3D:121img->array_pitch = fd_resource_slice(rsc, lvl)->size0;122img->depth = u_minify(prsc->depth0, lvl);123break;124default:125break;126}127128img->level = lvl;129img->width = u_minify(prsc->width0, lvl);130img->height = u_minify(prsc->height0, lvl);131}132}133134static void135translate_buf(struct fd6_image *img, const struct pipe_shader_buffer *pimg)136{137enum pipe_format format = PIPE_FORMAT_R32_UINT;138struct pipe_resource *prsc = pimg->buffer;139struct fd_resource *rsc = fd_resource(prsc);140141if (!prsc) {142memset(img, 0, sizeof(*img));143return;144}145146img->prsc = prsc;147img->pfmt = format;148img->type = fd6_tex_type(prsc->target);149img->srgb = util_format_is_srgb(format);150img->cpp = rsc->layout.cpp;151img->bo = rsc->bo;152img->buffer = true;153154img->ubwc_offset = 0; /* not valid for buffers */155img->offset = pimg->buffer_offset;156img->pitch = 0;157img->array_pitch = 0;158img->level = 0;159160/* size is encoded with low 15b in WIDTH and high bits in HEIGHT,161* in units of elements:162*/163unsigned sz = pimg->buffer_size / 4;164img->width = sz & MASK(15);165img->height = sz >> 15;166img->depth = 0;167}168169static void170emit_image_tex(struct fd_ringbuffer *ring, struct fd6_image *img)171{172struct fd_resource *rsc = fd_resource(img->prsc);173bool ubwc_enabled = fd_resource_ubwc_enabled(rsc, img->level);174175OUT_RING(ring,176fd6_tex_const_0(img->prsc, img->level, img->pfmt, PIPE_SWIZZLE_X,177PIPE_SWIZZLE_Y, PIPE_SWIZZLE_Z, PIPE_SWIZZLE_W));178OUT_RING(ring, A6XX_TEX_CONST_1_WIDTH(img->width) |179A6XX_TEX_CONST_1_HEIGHT(img->height));180OUT_RING(ring,181COND(img->buffer, A6XX_TEX_CONST_2_UNK4 | A6XX_TEX_CONST_2_UNK31) |182A6XX_TEX_CONST_2_TYPE(img->type) |183A6XX_TEX_CONST_2_PITCH(img->pitch));184OUT_RING(ring, A6XX_TEX_CONST_3_ARRAY_PITCH(img->array_pitch) |185COND(ubwc_enabled, A6XX_TEX_CONST_3_FLAG) |186COND(rsc->layout.tile_all, A6XX_TEX_CONST_3_TILE_ALL));187if (img->bo) {188OUT_RELOC(ring, img->bo, img->offset,189(uint64_t)A6XX_TEX_CONST_5_DEPTH(img->depth) << 32, 0);190} else {191OUT_RING(ring, 0x00000000);192OUT_RING(ring, A6XX_TEX_CONST_5_DEPTH(img->depth));193}194195OUT_RING(ring, 0x00000000); /* texconst6 */196197if (ubwc_enabled) {198uint32_t block_width, block_height;199fdl6_get_ubwc_blockwidth(&rsc->layout, &block_width, &block_height);200201OUT_RELOC(ring, rsc->bo, img->ubwc_offset, 0, 0);202OUT_RING(ring, A6XX_TEX_CONST_9_FLAG_BUFFER_ARRAY_PITCH(203rsc->layout.ubwc_layer_size >> 2));204OUT_RING(ring, A6XX_TEX_CONST_10_FLAG_BUFFER_PITCH(205fdl_ubwc_pitch(&rsc->layout, img->level)) |206A6XX_TEX_CONST_10_FLAG_BUFFER_LOGW(util_logbase2_ceil(207DIV_ROUND_UP(img->width, block_width))) |208A6XX_TEX_CONST_10_FLAG_BUFFER_LOGH(util_logbase2_ceil(209DIV_ROUND_UP(img->height, block_height))));210} else {211OUT_RING(ring, 0x00000000); /* texconst7 */212OUT_RING(ring, 0x00000000); /* texconst8 */213OUT_RING(ring, 0x00000000); /* texconst9 */214OUT_RING(ring, 0x00000000); /* texconst10 */215}216217OUT_RING(ring, 0x00000000); /* texconst11 */218OUT_RING(ring, 0x00000000); /* texconst12 */219OUT_RING(ring, 0x00000000); /* texconst13 */220OUT_RING(ring, 0x00000000); /* texconst14 */221OUT_RING(ring, 0x00000000); /* texconst15 */222}223224void225fd6_emit_image_tex(struct fd_ringbuffer *ring,226const struct pipe_image_view *pimg)227{228struct fd6_image img;229translate_image(&img, pimg);230emit_image_tex(ring, &img);231}232233void234fd6_emit_ssbo_tex(struct fd_ringbuffer *ring,235const struct pipe_shader_buffer *pbuf)236{237struct fd6_image img;238translate_buf(&img, pbuf);239emit_image_tex(ring, &img);240}241242static void243emit_image_ssbo(struct fd_ringbuffer *ring, struct fd6_image *img)244{245/* If the SSBO isn't present (becasue gallium doesn't pack atomic246* counters), zero-fill the slot.247*/248if (!img->prsc) {249for (int i = 0; i < 16; i++)250OUT_RING(ring, 0);251return;252}253254struct fd_resource *rsc = fd_resource(img->prsc);255enum a6xx_tile_mode tile_mode = fd_resource_tile_mode(img->prsc, img->level);256bool ubwc_enabled = fd_resource_ubwc_enabled(rsc, img->level);257258OUT_RING(ring, A6XX_IBO_0_FMT(fd6_pipe2tex(img->pfmt)) |259A6XX_IBO_0_TILE_MODE(tile_mode));260OUT_RING(ring,261A6XX_IBO_1_WIDTH(img->width) | A6XX_IBO_1_HEIGHT(img->height));262OUT_RING(ring, A6XX_IBO_2_PITCH(img->pitch) |263COND(img->buffer, A6XX_IBO_2_UNK4 | A6XX_IBO_2_UNK31) |264A6XX_IBO_2_TYPE(img->type));265OUT_RING(ring, A6XX_IBO_3_ARRAY_PITCH(img->array_pitch) |266COND(ubwc_enabled, A6XX_IBO_3_FLAG | A6XX_IBO_3_UNK27));267if (img->bo) {268OUT_RELOC(ring, img->bo, img->offset,269(uint64_t)A6XX_IBO_5_DEPTH(img->depth) << 32, 0);270} else {271OUT_RING(ring, 0x00000000);272OUT_RING(ring, A6XX_IBO_5_DEPTH(img->depth));273}274OUT_RING(ring, 0x00000000);275276if (ubwc_enabled) {277OUT_RELOC(ring, rsc->bo, img->ubwc_offset, 0, 0);278OUT_RING(ring, A6XX_IBO_9_FLAG_BUFFER_ARRAY_PITCH(279rsc->layout.ubwc_layer_size >> 2));280OUT_RING(ring, A6XX_IBO_10_FLAG_BUFFER_PITCH(281fdl_ubwc_pitch(&rsc->layout, img->level)));282} else {283OUT_RING(ring, 0x00000000);284OUT_RING(ring, 0x00000000);285OUT_RING(ring, 0x00000000);286OUT_RING(ring, 0x00000000);287}288289OUT_RING(ring, 0x00000000);290OUT_RING(ring, 0x00000000);291OUT_RING(ring, 0x00000000);292OUT_RING(ring, 0x00000000);293OUT_RING(ring, 0x00000000);294}295296/* Build combined image/SSBO "IBO" state, returns ownership of state reference */297struct fd_ringbuffer *298fd6_build_ibo_state(struct fd_context *ctx, const struct ir3_shader_variant *v,299enum pipe_shader_type shader)300{301struct fd_shaderbuf_stateobj *bufso = &ctx->shaderbuf[shader];302struct fd_shaderimg_stateobj *imgso = &ctx->shaderimg[shader];303304struct fd_ringbuffer *state = fd_submit_new_ringbuffer(305ctx->batch->submit,306(v->shader->nir->info.num_ssbos + v->shader->nir->info.num_images) * 16 *3074,308FD_RINGBUFFER_STREAMING);309310assert(shader == PIPE_SHADER_COMPUTE || shader == PIPE_SHADER_FRAGMENT);311312for (unsigned i = 0; i < v->shader->nir->info.num_ssbos; i++) {313struct fd6_image img;314translate_buf(&img, &bufso->sb[i]);315emit_image_ssbo(state, &img);316}317318for (unsigned i = 0; i < v->shader->nir->info.num_images; i++) {319struct fd6_image img;320translate_image(&img, &imgso->si[i]);321emit_image_ssbo(state, &img);322}323324return state;325}326327static void328fd6_set_shader_images(struct pipe_context *pctx, enum pipe_shader_type shader,329unsigned start, unsigned count,330unsigned unbind_num_trailing_slots,331const struct pipe_image_view *images) in_dt332{333struct fd_context *ctx = fd_context(pctx);334struct fd_shaderimg_stateobj *so = &ctx->shaderimg[shader];335336fd_set_shader_images(pctx, shader, start, count, unbind_num_trailing_slots,337images);338339if (!images)340return;341342for (unsigned i = 0; i < count; i++) {343unsigned n = i + start;344struct pipe_image_view *buf = &so->si[n];345346if (!buf->resource)347continue;348349fd6_validate_format(ctx, fd_resource(buf->resource), buf->format);350}351}352353void354fd6_image_init(struct pipe_context *pctx)355{356pctx->set_shader_images = fd6_set_shader_images;357}358359360