freedreno/a6xx: use single format enum
[mesa.git] / src / gallium / drivers / freedreno / a6xx / fd6_image.c
index 9c1182777c02d59408401483de073426f8868beb..6ac3cc5c4c9dc111b5a6c706d8b39e7bffad632e 100644 (file)
 #include "pipe/p_state.h"
 
 #include "freedreno_resource.h"
+#include "freedreno_state.h"
+
 #include "fd6_image.h"
 #include "fd6_format.h"
+#include "fd6_resource.h"
 #include "fd6_texture.h"
 
 struct fd6_image {
        struct pipe_resource *prsc;
        enum pipe_format pfmt;
-       enum a6xx_tex_fmt fmt;
+       enum a6xx_format fmt;
        enum a6xx_tex_fetchsize fetchsize;
        enum a6xx_tex_type type;
        bool srgb;
@@ -47,6 +50,7 @@ struct fd6_image {
        uint32_t pitch;
        uint32_t array_pitch;
        struct fd_bo *bo;
+       uint32_t ubwc_offset;
        uint32_t offset;
        bool buffer;
 };
@@ -68,7 +72,7 @@ static void translate_image(struct fd6_image *img, const struct pipe_image_view
        img->fetchsize = fd6_pipe2fetchsize(format);
        img->type      = fd6_tex_type(prsc->target);
        img->srgb      = util_format_is_srgb(format);
-       img->cpp       = rsc->cpp;
+       img->cpp       = rsc->layout.cpp;
        img->bo        = rsc->bo;
 
        /* Treat cube textures as 2d-array: */
@@ -77,6 +81,7 @@ static void translate_image(struct fd6_image *img, const struct pipe_image_view
 
        if (prsc->target == PIPE_BUFFER) {
                img->buffer = true;
+               img->ubwc_offset = 0;    /* not valid for buffers */
                img->offset = pimg->u.buf.offset;
                img->pitch  = 0;
                img->array_pitch = 0;
@@ -92,29 +97,31 @@ static void translate_image(struct fd6_image *img, const struct pipe_image_view
                img->buffer = false;
 
                unsigned lvl = pimg->u.tex.level;
+               struct fdl_slice *slice = fd_resource_slice(rsc, lvl);
                unsigned layers = pimg->u.tex.last_layer - pimg->u.tex.first_layer + 1;
 
+               img->ubwc_offset = fd_resource_ubwc_offset(rsc, lvl, pimg->u.tex.first_layer);
                img->offset = fd_resource_offset(rsc, lvl, pimg->u.tex.first_layer);
-               img->pitch  = rsc->slices[lvl].pitch * rsc->cpp;
+               img->pitch  = slice->pitch * rsc->layout.cpp;
 
                switch (prsc->target) {
                case PIPE_TEXTURE_RECT:
                case PIPE_TEXTURE_1D:
                case PIPE_TEXTURE_2D:
-                       img->array_pitch = rsc->layer_size;
+                       img->array_pitch = rsc->layout.layer_size;
                        img->depth = 1;
                        break;
                case PIPE_TEXTURE_1D_ARRAY:
                case PIPE_TEXTURE_2D_ARRAY:
                case PIPE_TEXTURE_CUBE:
                case PIPE_TEXTURE_CUBE_ARRAY:
-                       img->array_pitch = rsc->layer_size;
+                       img->array_pitch = rsc->layout.layer_size;
                        // TODO the CUBE/CUBE_ARRAY might need to be layers/6 for tex state,
                        // but empirically for ibo state it shouldn't be divided.
                        img->depth = layers;
                        break;
                case PIPE_TEXTURE_3D:
-                       img->array_pitch = rsc->slices[lvl].size0;
+                       img->array_pitch = slice->size0;
                        img->depth  = u_minify(prsc->depth0, lvl);
                        break;
                default:
@@ -144,10 +151,11 @@ static void translate_buf(struct fd6_image *img, const struct pipe_shader_buffer
        img->fetchsize = fd6_pipe2fetchsize(format);
        img->type      = fd6_tex_type(prsc->target);
        img->srgb      = util_format_is_srgb(format);
-       img->cpp       = rsc->cpp;
+       img->cpp       = rsc->layout.cpp;
        img->bo        = rsc->bo;
        img->buffer    = true;
 
+       img->ubwc_offset = 0;    /* not valid for buffers */
        img->offset = pimg->buffer_offset;
        img->pitch  = 0;
        img->array_pitch = 0;
@@ -163,6 +171,9 @@ static void translate_buf(struct fd6_image *img, const struct pipe_shader_buffer
 
 static void emit_image_tex(struct fd_ringbuffer *ring, struct fd6_image *img)
 {
+       struct fd_resource *rsc = fd_resource(img->prsc);
+       bool ubwc_enabled = fd_resource_ubwc_enabled(rsc, img->level);
+
        OUT_RING(ring, fd6_tex_const_0(img->prsc, img->level, img->pfmt,
                        PIPE_SWIZZLE_X, PIPE_SWIZZLE_Y,
                        PIPE_SWIZZLE_Z, PIPE_SWIZZLE_W));
@@ -172,7 +183,8 @@ static void emit_image_tex(struct fd_ringbuffer *ring, struct fd6_image *img)
                COND(img->buffer, A6XX_TEX_CONST_2_UNK4 | A6XX_TEX_CONST_2_UNK31) |
                A6XX_TEX_CONST_2_TYPE(img->type) |
                A6XX_TEX_CONST_2_PITCH(img->pitch));
-       OUT_RING(ring, A6XX_TEX_CONST_3_ARRAY_PITCH(img->array_pitch));
+       OUT_RING(ring, A6XX_TEX_CONST_3_ARRAY_PITCH(img->array_pitch) |
+               COND(ubwc_enabled, A6XX_TEX_CONST_3_FLAG | A6XX_TEX_CONST_3_TILE_ALL));
        if (img->bo) {
                OUT_RELOC(ring, img->bo, img->offset,
                                (uint64_t)A6XX_TEX_CONST_5_DEPTH(img->depth) << 32, 0);
@@ -180,16 +192,33 @@ static void emit_image_tex(struct fd_ringbuffer *ring, struct fd6_image *img)
                OUT_RING(ring, 0x00000000);
                OUT_RING(ring, A6XX_TEX_CONST_5_DEPTH(img->depth));
        }
-       OUT_RING(ring, 0x00000000);
-       OUT_RING(ring, 0x00000000);
-       OUT_RING(ring, 0x00000000);
-       OUT_RING(ring, 0x00000000);
-       OUT_RING(ring, 0x00000000);
-       OUT_RING(ring, 0x00000000);
-       OUT_RING(ring, 0x00000000);
-       OUT_RING(ring, 0x00000000);
-       OUT_RING(ring, 0x00000000);
-       OUT_RING(ring, 0x00000000);
+
+       OUT_RING(ring, 0x00000000);   /* texconst6 */
+
+       if (ubwc_enabled) {
+               struct fdl_slice *ubwc_slice = &rsc->layout.ubwc_slices[img->level];
+
+               uint32_t block_width, block_height;
+               fdl6_get_ubwc_blockwidth(&rsc->layout, &block_width, &block_height);
+
+               OUT_RELOC(ring, rsc->bo, img->ubwc_offset, 0, 0);
+               OUT_RING(ring, A6XX_TEX_CONST_9_FLAG_BUFFER_ARRAY_PITCH(rsc->layout.ubwc_layer_size >> 2));
+               OUT_RING(ring,
+                               A6XX_TEX_CONST_10_FLAG_BUFFER_PITCH(ubwc_slice->pitch) |
+                               A6XX_TEX_CONST_10_FLAG_BUFFER_LOGW(util_logbase2_ceil(DIV_ROUND_UP(img->width, block_width))) |
+                               A6XX_TEX_CONST_10_FLAG_BUFFER_LOGH(util_logbase2_ceil(DIV_ROUND_UP(img->height, block_height))));
+       } else {
+               OUT_RING(ring, 0x00000000);   /* texconst7 */
+               OUT_RING(ring, 0x00000000);   /* texconst8 */
+               OUT_RING(ring, 0x00000000);   /* texconst9 */
+               OUT_RING(ring, 0x00000000);   /* texconst10 */
+       }
+
+       OUT_RING(ring, 0x00000000);   /* texconst11 */
+       OUT_RING(ring, 0x00000000);   /* texconst12 */
+       OUT_RING(ring, 0x00000000);   /* texconst13 */
+       OUT_RING(ring, 0x00000000);   /* texconst14 */
+       OUT_RING(ring, 0x00000000);   /* texconst15 */
 }
 
 void
@@ -210,13 +239,19 @@ fd6_emit_ssbo_tex(struct fd_ringbuffer *ring, const struct pipe_shader_buffer *p
 
 static void emit_image_ssbo(struct fd_ringbuffer *ring, struct fd6_image *img)
 {
-       struct fd_resource *rsc = fd_resource(img->prsc);
-       enum a6xx_tile_mode tile_mode = TILE6_LINEAR;
-
-       if (rsc->tile_mode && !fd_resource_level_linear(img->prsc, img->level)) {
-               tile_mode = rsc->tile_mode;
+       /* If the SSBO isn't present (becasue gallium doesn't pack atomic
+        * counters), zero-fill the slot.
+        */
+       if (!img->prsc) {
+               for (int i = 0; i < 16; i++)
+                       OUT_RING(ring, 0);
+               return;
        }
 
+       struct fd_resource *rsc = fd_resource(img->prsc);
+       enum a6xx_tile_mode tile_mode = fd_resource_tile_mode(img->prsc, img->level);
+       bool ubwc_enabled = fd_resource_ubwc_enabled(rsc, img->level);
+
        OUT_RING(ring, A6XX_IBO_0_FMT(img->fmt) |
                A6XX_IBO_0_TILE_MODE(tile_mode));
        OUT_RING(ring, A6XX_IBO_1_WIDTH(img->width) |
@@ -224,7 +259,8 @@ static void emit_image_ssbo(struct fd_ringbuffer *ring, struct fd6_image *img)
        OUT_RING(ring, A6XX_IBO_2_PITCH(img->pitch) |
                COND(img->buffer, A6XX_IBO_2_UNK4 | A6XX_IBO_2_UNK31) |
                A6XX_IBO_2_TYPE(img->type));
-       OUT_RING(ring, A6XX_IBO_3_ARRAY_PITCH(img->array_pitch));
+       OUT_RING(ring, A6XX_IBO_3_ARRAY_PITCH(img->array_pitch) |
+               COND(ubwc_enabled, A6XX_IBO_3_FLAG | A6XX_IBO_3_UNK27));
        if (img->bo) {
                OUT_RELOCW(ring, img->bo, img->offset,
                        (uint64_t)A6XX_IBO_5_DEPTH(img->depth) << 32, 0);
@@ -233,10 +269,19 @@ static void emit_image_ssbo(struct fd_ringbuffer *ring, struct fd6_image *img)
                OUT_RING(ring, A6XX_IBO_5_DEPTH(img->depth));
        }
        OUT_RING(ring, 0x00000000);
-       OUT_RING(ring, 0x00000000);
-       OUT_RING(ring, 0x00000000);
-       OUT_RING(ring, 0x00000000);
-       OUT_RING(ring, 0x00000000);
+
+       if (ubwc_enabled) {
+               struct fdl_slice *ubwc_slice = &rsc->layout.ubwc_slices[img->level];
+               OUT_RELOCW(ring, rsc->bo, img->ubwc_offset, 0, 0);
+               OUT_RING(ring, A6XX_IBO_9_FLAG_BUFFER_ARRAY_PITCH(rsc->layout.ubwc_layer_size >> 2));
+               OUT_RING(ring, A6XX_IBO_10_FLAG_BUFFER_PITCH(ubwc_slice->pitch));
+       } else {
+               OUT_RING(ring, 0x00000000);
+               OUT_RING(ring, 0x00000000);
+               OUT_RING(ring, 0x00000000);
+               OUT_RING(ring, 0x00000000);
+       }
+
        OUT_RING(ring, 0x00000000);
        OUT_RING(ring, 0x00000000);
        OUT_RING(ring, 0x00000000);
@@ -251,26 +296,56 @@ fd6_build_ibo_state(struct fd_context *ctx, const struct ir3_shader_variant *v,
 {
        struct fd_shaderbuf_stateobj *bufso = &ctx->shaderbuf[shader];
        struct fd_shaderimg_stateobj *imgso = &ctx->shaderimg[shader];
-       const struct ir3_ibo_mapping *mapping = &v->image_mapping;
 
        struct fd_ringbuffer *state =
                fd_submit_new_ringbuffer(ctx->batch->submit,
-                       mapping->num_ibo * 16 * 4, FD_RINGBUFFER_STREAMING);
+                               (v->shader->nir->info.num_ssbos +
+                                v->shader->nir->info.num_images) * 16 * 4,
+                               FD_RINGBUFFER_STREAMING);
 
        assert(shader == PIPE_SHADER_COMPUTE || shader == PIPE_SHADER_FRAGMENT);
 
-       for (unsigned i = 0; i < mapping->num_ibo; i++) {
+       for (unsigned i = 0; i < v->shader->nir->info.num_ssbos; i++) {
                struct fd6_image img;
-               unsigned idx = mapping->ibo_to_image[i];
-
-               if (idx & IBO_SSBO) {
-                       translate_buf(&img, &bufso->sb[idx & ~IBO_SSBO]);
-               } else {
-                       translate_image(&img, &imgso->si[idx]);
-               }
+               translate_buf(&img, &bufso->sb[i]);
+               emit_image_ssbo(state, &img);
+       }
 
+       for (unsigned i = 0; i < v->shader->nir->info.num_images; i++) {
+               struct fd6_image img;
+               translate_image(&img, &imgso->si[i]);
                emit_image_ssbo(state, &img);
        }
 
        return state;
 }
+
+static void fd6_set_shader_images(struct pipe_context *pctx,
+               enum pipe_shader_type shader,
+               unsigned start, unsigned count,
+               const struct pipe_image_view *images)
+{
+       struct fd_context *ctx = fd_context(pctx);
+       struct fd_shaderimg_stateobj *so = &ctx->shaderimg[shader];
+
+       fd_set_shader_images(pctx, shader, start, count, images);
+
+       if (!images)
+               return;
+
+       for (unsigned i = 0; i < count; i++) {
+               unsigned n = i + start;
+               struct pipe_image_view *buf = &so->si[n];
+
+               if (!buf->resource)
+                       continue;
+
+               fd6_validate_format(ctx, fd_resource(buf->resource), buf->format);
+       }
+}
+
+void
+fd6_image_init(struct pipe_context *pctx)
+{
+       pctx->set_shader_images = fd6_set_shader_images;
+}