1/* 2 * Copyright (C) 2017 Rob Clark <robclark@freedesktop.org> 3 * Copyright © 2018 Google, Inc. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice (including the next 13 * paragraph) shall be included in all copies or substantial portions of the 14 * Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 * SOFTWARE. 23 * 24 * Authors: 25 * Rob Clark <robclark@freedesktop.org> 26 */ 27 28#include "pipe/p_state.h" 29 30#include "freedreno_resource.h" 31#include "freedreno_state.h" 32 33#include "fd6_image.h" 34#include "fd6_resource.h" 35#include "fd6_texture.h" 36 37static const uint8_t swiz_identity[4] = {PIPE_SWIZZLE_X, PIPE_SWIZZLE_Y, 38 PIPE_SWIZZLE_Z, PIPE_SWIZZLE_W}; 39 40static void 41fd6_emit_single_plane_descriptor(struct fd_ringbuffer *ring, 42 struct pipe_resource *prsc, 43 uint32_t *descriptor) 44{ 45 /* If the resource isn't present (holes are allowed), zero-fill the slot. */ 46 if (!prsc) { 47 for (int i = 0; i < 16; i++) 48 OUT_RING(ring, 0); 49 return; 50 } 51 52 struct fd_resource *rsc = fd_resource(prsc); 53 for (int i = 0; i < 4; i++) 54 OUT_RING(ring, descriptor[i]); 55 56 OUT_RELOC(ring, rsc->bo, descriptor[4], (uint64_t)descriptor[5] << 32, 0); 57 58 OUT_RING(ring, descriptor[6]); 59 60 OUT_RELOC(ring, rsc->bo, descriptor[7], (uint64_t)descriptor[8] << 32, 0); 61 62 for (int i = 9; i < FDL6_TEX_CONST_DWORDS; i++) 63 OUT_RING(ring, descriptor[i]); 64} 65 66static void 67fd6_ssbo_descriptor(struct fd_context *ctx, 68 const struct pipe_shader_buffer *buf, uint32_t *descriptor) 69{ 70 fdl6_buffer_view_init( 71 descriptor, 72 ctx->screen->info->a6xx.storage_16bit ? PIPE_FORMAT_R16_UINT 73 : PIPE_FORMAT_R32_UINT, 74 swiz_identity, buf->buffer_offset, /* Using relocs for addresses */ 75 buf->buffer_size); 76} 77 78static void 79fd6_emit_image_descriptor(struct fd_context *ctx, struct fd_ringbuffer *ring, const struct pipe_image_view *buf, bool ibo) 80{ 81 struct fd_resource *rsc = fd_resource(buf->resource); 82 if (!rsc) { 83 for (int i = 0; i < FDL6_TEX_CONST_DWORDS; i++) 84 OUT_RING(ring, 0); 85 return; 86 } 87 88 if (buf->resource->target == PIPE_BUFFER) { 89 uint32_t descriptor[FDL6_TEX_CONST_DWORDS]; 90 fdl6_buffer_view_init(descriptor, buf->format, swiz_identity, 91 buf->u.buf.offset, /* Using relocs for addresses */ 92 buf->u.buf.size); 93 fd6_emit_single_plane_descriptor(ring, buf->resource, descriptor); 94 } else { 95 struct fdl_view_args args = { 96 /* Using relocs for addresses */ 97 .iova = 0, 98 99 .base_miplevel = buf->u.tex.level, 100 .level_count = 1, 101 102 .base_array_layer = buf->u.tex.first_layer, 103 .layer_count = buf->u.tex.last_layer - buf->u.tex.first_layer + 1, 104 105 .format = buf->format, 106 .swiz = {PIPE_SWIZZLE_X, PIPE_SWIZZLE_Y, PIPE_SWIZZLE_Z, 107 PIPE_SWIZZLE_W}, 108 109 .type = fdl_type_from_pipe_target(buf->resource->target), 110 .chroma_offsets = {FDL_CHROMA_LOCATION_COSITED_EVEN, 111 FDL_CHROMA_LOCATION_COSITED_EVEN}, 112 }; 113 114 /* fdl6_view makes the storage descriptor treat cubes like a 2D array (so 115 * you can reference a specific layer), but we need to do that for the 116 * texture descriptor as well to get our layer. 117 */ 118 if (args.type == FDL_VIEW_TYPE_CUBE) 119 args.type = FDL_VIEW_TYPE_2D; 120 121 struct fdl6_view view; 122 const struct fdl_layout *layouts[3] = {&rsc->layout, NULL, NULL}; 123 fdl6_view_init(&view, layouts, &args, 124 ctx->screen->info->a6xx.has_z24uint_s8uint); 125 if (ibo) 126 fd6_emit_single_plane_descriptor(ring, buf->resource, view.storage_descriptor); 127 else 128 fd6_emit_single_plane_descriptor(ring, buf->resource, view.descriptor); 129 } 130} 131 132void 133fd6_emit_image_tex(struct fd_context *ctx, struct fd_ringbuffer *ring, 134 const struct pipe_image_view *pimg) 135{ 136 fd6_emit_image_descriptor(ctx, ring, pimg, false); 137} 138 139void 140fd6_emit_ssbo_tex(struct fd_context *ctx, struct fd_ringbuffer *ring, 141 const struct pipe_shader_buffer *pbuf) 142{ 143 uint32_t descriptor[FDL6_TEX_CONST_DWORDS]; 144 fd6_ssbo_descriptor(ctx, pbuf, descriptor); 145 fd6_emit_single_plane_descriptor(ring, pbuf->buffer, descriptor); 146} 147 148/* Build combined image/SSBO "IBO" state, returns ownership of state reference */ 149struct fd_ringbuffer * 150fd6_build_ibo_state(struct fd_context *ctx, const struct ir3_shader_variant *v, 151 enum pipe_shader_type shader) 152{ 153 struct fd_shaderbuf_stateobj *bufso = &ctx->shaderbuf[shader]; 154 struct fd_shaderimg_stateobj *imgso = &ctx->shaderimg[shader]; 155 156 struct fd_ringbuffer *state = fd_submit_new_ringbuffer( 157 ctx->batch->submit, 158 ir3_shader_nibo(v) * 16 * 4, 159 FD_RINGBUFFER_STREAMING); 160 161 assert(shader == PIPE_SHADER_COMPUTE || shader == PIPE_SHADER_FRAGMENT); 162 163 uint32_t descriptor[FDL6_TEX_CONST_DWORDS]; 164 for (unsigned i = 0; i < v->num_ssbos; i++) { 165 fd6_ssbo_descriptor(ctx, &bufso->sb[i], descriptor); 166 fd6_emit_single_plane_descriptor(state, bufso->sb[i].buffer, descriptor); 167 } 168 169 for (unsigned i = v->num_ssbos; i < v->num_ibos; i++) { 170 fd6_emit_image_descriptor(ctx, state, &imgso->si[i - v->num_ssbos], true); 171 } 172 173 return state; 174} 175 176static void 177fd6_set_shader_images(struct pipe_context *pctx, enum pipe_shader_type shader, 178 unsigned start, unsigned count, 179 unsigned unbind_num_trailing_slots, 180 const struct pipe_image_view *images) in_dt 181{ 182 struct fd_context *ctx = fd_context(pctx); 183 struct fd_shaderimg_stateobj *so = &ctx->shaderimg[shader]; 184 185 fd_set_shader_images(pctx, shader, start, count, unbind_num_trailing_slots, 186 images); 187 188 if (!images) 189 return; 190 191 for (unsigned i = 0; i < count; i++) { 192 unsigned n = i + start; 193 struct pipe_image_view *buf = &so->si[n]; 194 195 if (!buf->resource) 196 continue; 197 198 fd6_validate_format(ctx, fd_resource(buf->resource), buf->format); 199 } 200} 201 202void 203fd6_image_init(struct pipe_context *pctx) 204{ 205 pctx->set_shader_images = fd6_set_shader_images; 206} 207