radeonsi: Set PIPE_SHADER_CAP_MAX_SHADER_IMAGES
[mesa.git] / src / gallium / drivers / radeonsi / si_state.c
index 5d65791f844fa69c9b87fdde8efcf9c4ffc5f5e2..b9bdd47c4967301587f6275fa9e802c6bb9f0914 100644 (file)
@@ -34,6 +34,7 @@
 #include "util/u_format_s3tc.h"
 #include "util/u_memory.h"
 #include "util/u_pstipple.h"
+#include "util/u_resource.h"
 
 /* Initialize an external atom (owned by ../radeon). */
 static void
@@ -2796,7 +2797,7 @@ static void si_set_min_samples(struct pipe_context *ctx, unsigned min_samples)
  * Build the sampler view descriptor for a buffer texture.
  * @param state 256-bit descriptor; only the high 128 bits are filled in
  */
-static void
+void
 si_make_buffer_descriptor(struct si_screen *screen, struct r600_resource *buf,
                          enum pipe_format format,
                          unsigned first_element, unsigned last_element,
@@ -2835,85 +2836,32 @@ si_make_buffer_descriptor(struct si_screen *screen, struct r600_resource *buf,
 }
 
 /**
- * Create a sampler view.
- *
- * @param ctx          context
- * @param texture      texture
- * @param state                sampler view template
- * @param width0       width0 override (for compressed textures as int)
- * @param height0      height0 override (for compressed textures as int)
- * @param force_level   set the base address to the level (for compressed textures)
+ * Build the sampler view descriptor for a texture.
  */
-struct pipe_sampler_view *
-si_create_sampler_view_custom(struct pipe_context *ctx,
-                             struct pipe_resource *texture,
-                             const struct pipe_sampler_view *state,
-                             unsigned width0, unsigned height0,
-                             unsigned force_level)
-{
-       struct si_context *sctx = (struct si_context*)ctx;
-       struct si_sampler_view *view = CALLOC_STRUCT(si_sampler_view);
-       struct r600_texture *tmp = (struct r600_texture*)texture;
+void
+si_make_texture_descriptor(struct si_screen *screen,
+                          struct r600_texture *tex,
+                          bool sampler,
+                          enum pipe_texture_target target,
+                          enum pipe_format pipe_format,
+                          const unsigned char state_swizzle[4],
+                          unsigned base_level, unsigned first_level, unsigned last_level,
+                          unsigned first_layer, unsigned last_layer,
+                          unsigned width, unsigned height, unsigned depth,
+                          uint32_t *state,
+                          uint32_t *fmask_state)
+{
+       struct pipe_resource *res = &tex->resource.b.b;
+       const struct radeon_surf_level *surflevel = tex->surface.level;
        const struct util_format_description *desc;
-       unsigned format, num_format, base_level, first_level, last_level;
-       uint32_t pitch = 0;
-       unsigned char state_swizzle[4], swizzle[4];
-       unsigned height, depth, width;
-       enum pipe_format pipe_format = state->format;
-       struct radeon_surf_level *surflevel;
+       unsigned char swizzle[4];
        int first_non_void;
+       unsigned num_format, data_format, type;
+       uint32_t pitch;
        uint64_t va;
-       unsigned last_layer = state->u.tex.last_layer;
-
-       if (!view)
-               return NULL;
-
-       /* initialize base object */
-       view->base = *state;
-       view->base.texture = NULL;
-       view->base.reference.count = 1;
-       view->base.context = ctx;
-
-       /* NULL resource, obey swizzle (only ZERO and ONE make sense). */
-       if (!texture) {
-               view->state[3] = S_008F1C_DST_SEL_X(si_map_swizzle(state->swizzle_r)) |
-                                S_008F1C_DST_SEL_Y(si_map_swizzle(state->swizzle_g)) |
-                                S_008F1C_DST_SEL_Z(si_map_swizzle(state->swizzle_b)) |
-                                S_008F1C_DST_SEL_W(si_map_swizzle(state->swizzle_a)) |
-                                S_008F1C_TYPE(V_008F1C_SQ_RSRC_IMG_1D);
-               return &view->base;
-       }
-
-       pipe_resource_reference(&view->base.texture, texture);
-
-       if (state->format == PIPE_FORMAT_X24S8_UINT ||
-           state->format == PIPE_FORMAT_S8X24_UINT ||
-           state->format == PIPE_FORMAT_X32_S8X24_UINT ||
-           state->format == PIPE_FORMAT_S8_UINT)
-               view->is_stencil_sampler = true;
-
-       /* Buffer resource. */
-       if (texture->target == PIPE_BUFFER) {
-               si_make_buffer_descriptor(sctx->screen,
-                                         (struct r600_resource *)texture,
-                                         state->format,
-                                         state->u.buf.first_element,
-                                         state->u.buf.last_element,
-                                         view->state);
-
-               LIST_ADDTAIL(&view->list, &sctx->b.texture_buffers);
-               return &view->base;
-       }
-
-       state_swizzle[0] = state->swizzle_r;
-       state_swizzle[1] = state->swizzle_g;
-       state_swizzle[2] = state->swizzle_b;
-       state_swizzle[3] = state->swizzle_a;
-
-       surflevel = tmp->surface.level;
 
        /* Texturing with separate depth and stencil. */
-       if (tmp->is_depth && !tmp->is_flushing_texture) {
+       if (tex->is_depth && !tex->is_flushing_texture) {
                switch (pipe_format) {
                case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
                        pipe_format = PIPE_FORMAT_Z32_FLOAT;
@@ -2927,7 +2875,7 @@ si_create_sampler_view_custom(struct pipe_context *ctx,
                case PIPE_FORMAT_S8X24_UINT:
                case PIPE_FORMAT_X32_S8X24_UINT:
                        pipe_format = PIPE_FORMAT_S8_UINT;
-                       surflevel = tmp->surface.stencil_level;
+                       surflevel = tex->surface.stencil_level;
                        break;
                default:;
                }
@@ -3021,89 +2969,80 @@ si_create_sampler_view_custom(struct pipe_context *ctx,
                }
        }
 
-       format = si_translate_texformat(ctx->screen, pipe_format, desc, first_non_void);
-       if (format == ~0) {
-               format = 0;
+       data_format = si_translate_texformat(&screen->b.b, pipe_format, desc, first_non_void);
+       if (data_format == ~0) {
+               data_format = 0;
        }
 
-       base_level = 0;
-       first_level = state->u.tex.first_level;
-       last_level = state->u.tex.last_level;
-       width = width0;
-       height = height0;
-       depth = texture->depth0;
+       if (!sampler &&
+           (res->target == PIPE_TEXTURE_CUBE ||
+            res->target == PIPE_TEXTURE_CUBE_ARRAY ||
+            res->target == PIPE_TEXTURE_3D)) {
+               /* For the purpose of shader images, treat cube maps and 3D
+                * textures as 2D arrays. For 3D textures, the address
+                * calculations for mipmaps are different, so we rely on the
+                * caller to effectively disable mipmaps.
+                */
+               type = V_008F1C_SQ_RSRC_IMG_2D_ARRAY;
 
-       if (force_level) {
-               assert(force_level == first_level &&
-                      force_level == last_level);
-               base_level = force_level;
-               first_level = 0;
-               last_level = 0;
-               width = u_minify(width, force_level);
-               height = u_minify(height, force_level);
-               depth = u_minify(depth, force_level);
+               assert(res->target != PIPE_TEXTURE_3D || (first_level == 0 && last_level == 0));
+       } else {
+               type = si_tex_dim(res->target, target, res->nr_samples);
        }
 
-       pitch = surflevel[base_level].nblk_x * util_format_get_blockwidth(pipe_format);
-
-       if (texture->target == PIPE_TEXTURE_1D_ARRAY) {
+       if (type == V_008F1C_SQ_RSRC_IMG_1D_ARRAY) {
                height = 1;
-               depth = texture->array_size;
-       } else if (texture->target == PIPE_TEXTURE_2D_ARRAY) {
-               depth = texture->array_size;
-       } else if (texture->target == PIPE_TEXTURE_CUBE_ARRAY)
-               depth = texture->array_size / 6;
-
-       /* This is not needed if state trackers set last_layer correctly. */
-       if (state->target == PIPE_TEXTURE_1D ||
-           state->target == PIPE_TEXTURE_2D ||
-           state->target == PIPE_TEXTURE_RECT ||
-           state->target == PIPE_TEXTURE_CUBE)
-               last_layer = state->u.tex.first_layer;
+               depth = res->array_size;
+       } else if (type == V_008F1C_SQ_RSRC_IMG_2D_ARRAY) {
+               if (sampler || res->target != PIPE_TEXTURE_3D)
+                       depth = res->array_size;
+       } else if (type == V_008F1C_SQ_RSRC_IMG_CUBE)
+               depth = res->array_size / 6;
 
-       va = tmp->resource.gpu_address + surflevel[base_level].offset;
-
-       view->state[0] = va >> 8;
-       view->state[1] = (S_008F14_BASE_ADDRESS_HI(va >> 40) |
-                         S_008F14_DATA_FORMAT(format) |
-                         S_008F14_NUM_FORMAT(num_format));
-       view->state[2] = (S_008F18_WIDTH(width - 1) |
-                         S_008F18_HEIGHT(height - 1));
-       view->state[3] = (S_008F1C_DST_SEL_X(si_map_swizzle(swizzle[0])) |
-                         S_008F1C_DST_SEL_Y(si_map_swizzle(swizzle[1])) |
-                         S_008F1C_DST_SEL_Z(si_map_swizzle(swizzle[2])) |
-                         S_008F1C_DST_SEL_W(si_map_swizzle(swizzle[3])) |
-                         S_008F1C_BASE_LEVEL(texture->nr_samples > 1 ?
-                                                     0 : first_level) |
-                         S_008F1C_LAST_LEVEL(texture->nr_samples > 1 ?
-                                                     util_logbase2(texture->nr_samples) :
-                                                     last_level) |
-                         S_008F1C_TILING_INDEX(si_tile_mode_index(tmp, base_level, false)) |
-                         S_008F1C_POW2_PAD(texture->last_level > 0) |
-                         S_008F1C_TYPE(si_tex_dim(texture->target, state->target,
-                                                  texture->nr_samples)));
-       view->state[4] = (S_008F20_DEPTH(depth - 1) | S_008F20_PITCH(pitch - 1));
-       view->state[5] = (S_008F24_BASE_ARRAY(state->u.tex.first_layer) |
-                         S_008F24_LAST_ARRAY(last_layer));
-
-       if (tmp->dcc_offset) {
+       pitch = surflevel[base_level].nblk_x * util_format_get_blockwidth(pipe_format);
+       va = tex->resource.gpu_address + surflevel[base_level].offset;
+
+       state[0] = va >> 8;
+       state[1] = (S_008F14_BASE_ADDRESS_HI(va >> 40) |
+                   S_008F14_DATA_FORMAT(data_format) |
+                   S_008F14_NUM_FORMAT(num_format));
+       state[2] = (S_008F18_WIDTH(width - 1) |
+                   S_008F18_HEIGHT(height - 1));
+       state[3] = (S_008F1C_DST_SEL_X(si_map_swizzle(swizzle[0])) |
+                   S_008F1C_DST_SEL_Y(si_map_swizzle(swizzle[1])) |
+                   S_008F1C_DST_SEL_Z(si_map_swizzle(swizzle[2])) |
+                   S_008F1C_DST_SEL_W(si_map_swizzle(swizzle[3])) |
+                   S_008F1C_BASE_LEVEL(res->nr_samples > 1 ?
+                                       0 : first_level) |
+                   S_008F1C_LAST_LEVEL(res->nr_samples > 1 ?
+                                       util_logbase2(res->nr_samples) :
+                                       last_level) |
+                   S_008F1C_TILING_INDEX(si_tile_mode_index(tex, base_level, false)) |
+                   S_008F1C_POW2_PAD(res->last_level > 0) |
+                   S_008F1C_TYPE(type));
+       state[4] = (S_008F20_DEPTH(depth - 1) | S_008F20_PITCH(pitch - 1));
+       state[5] = (S_008F24_BASE_ARRAY(first_layer) |
+                   S_008F24_LAST_ARRAY(last_layer));
+
+       if (tex->dcc_offset) {
                unsigned swap = r600_translate_colorswap(pipe_format);
 
-               view->state[6] = S_008F28_COMPRESSION_EN(1) | S_008F28_ALPHA_IS_ON_MSB(swap <= 1);
-               view->state[7] = (tmp->resource.gpu_address +
-                                 tmp->dcc_offset +
-                                 surflevel[base_level].dcc_offset) >> 8;
+               state[6] = S_008F28_COMPRESSION_EN(1) | S_008F28_ALPHA_IS_ON_MSB(swap <= 1);
+               state[7] = (tex->resource.gpu_address +
+                           tex->dcc_offset +
+                           surflevel[base_level].dcc_offset) >> 8;
        } else {
-               view->state[6] = 0;
-               view->state[7] = 0;
+               state[6] = 0;
+               state[7] = 0;
        }
 
        /* Initialize the sampler view for FMASK. */
-       if (tmp->fmask.size) {
-               uint64_t va = tmp->resource.gpu_address + tmp->fmask.offset;
+       if (tex->fmask.size) {
                uint32_t fmask_format;
 
-               switch (texture->nr_samples) {
+               va = tex->resource.gpu_address + tex->fmask.offset;
+
+               switch (res->nr_samples) {
                case 2:
                        fmask_format = V_008F14_IMG_DATA_FORMAT_FMASK8_S2_F2;
                        break;
@@ -3118,27 +3057,129 @@ si_create_sampler_view_custom(struct pipe_context *ctx,
                        fmask_format = V_008F14_IMG_DATA_FORMAT_INVALID;
                }
 
-               view->fmask_state[0] = va >> 8;
-               view->fmask_state[1] = S_008F14_BASE_ADDRESS_HI(va >> 40) |
-                                      S_008F14_DATA_FORMAT(fmask_format) |
-                                      S_008F14_NUM_FORMAT(V_008F14_IMG_NUM_FORMAT_UINT);
-               view->fmask_state[2] = S_008F18_WIDTH(width - 1) |
-                                      S_008F18_HEIGHT(height - 1);
-               view->fmask_state[3] = S_008F1C_DST_SEL_X(V_008F1C_SQ_SEL_X) |
-                                      S_008F1C_DST_SEL_Y(V_008F1C_SQ_SEL_X) |
-                                      S_008F1C_DST_SEL_Z(V_008F1C_SQ_SEL_X) |
-                                      S_008F1C_DST_SEL_W(V_008F1C_SQ_SEL_X) |
-                                      S_008F1C_TILING_INDEX(tmp->fmask.tile_mode_index) |
-                                      S_008F1C_TYPE(si_tex_dim(texture->target,
-                                                               state->target, 0));
-               view->fmask_state[4] = S_008F20_DEPTH(depth - 1) |
-                                      S_008F20_PITCH(tmp->fmask.pitch_in_pixels - 1);
-               view->fmask_state[5] = S_008F24_BASE_ARRAY(state->u.tex.first_layer) |
-                                      S_008F24_LAST_ARRAY(last_layer);
-               view->fmask_state[6] = 0;
-               view->fmask_state[7] = 0;
+               fmask_state[0] = va >> 8;
+               fmask_state[1] = S_008F14_BASE_ADDRESS_HI(va >> 40) |
+                                S_008F14_DATA_FORMAT(fmask_format) |
+                                S_008F14_NUM_FORMAT(V_008F14_IMG_NUM_FORMAT_UINT);
+               fmask_state[2] = S_008F18_WIDTH(width - 1) |
+                                S_008F18_HEIGHT(height - 1);
+               fmask_state[3] = S_008F1C_DST_SEL_X(V_008F1C_SQ_SEL_X) |
+                                S_008F1C_DST_SEL_Y(V_008F1C_SQ_SEL_X) |
+                                S_008F1C_DST_SEL_Z(V_008F1C_SQ_SEL_X) |
+                                S_008F1C_DST_SEL_W(V_008F1C_SQ_SEL_X) |
+                                S_008F1C_TILING_INDEX(tex->fmask.tile_mode_index) |
+                                S_008F1C_TYPE(si_tex_dim(res->target, target, 0));
+               fmask_state[4] = S_008F20_DEPTH(depth - 1) |
+                                S_008F20_PITCH(tex->fmask.pitch_in_pixels - 1);
+               fmask_state[5] = S_008F24_BASE_ARRAY(first_layer) |
+                                S_008F24_LAST_ARRAY(last_layer);
+               fmask_state[6] = 0;
+               fmask_state[7] = 0;
+       }
+}
+
+/**
+ * Create a sampler view.
+ *
+ * @param ctx          context
+ * @param texture      texture
+ * @param state                sampler view template
+ * @param width0       width0 override (for compressed textures as int)
+ * @param height0      height0 override (for compressed textures as int)
+ * @param force_level   set the base address to the level (for compressed textures)
+ */
+struct pipe_sampler_view *
+si_create_sampler_view_custom(struct pipe_context *ctx,
+                             struct pipe_resource *texture,
+                             const struct pipe_sampler_view *state,
+                             unsigned width0, unsigned height0,
+                             unsigned force_level)
+{
+       struct si_context *sctx = (struct si_context*)ctx;
+       struct si_sampler_view *view = CALLOC_STRUCT(si_sampler_view);
+       struct r600_texture *tmp = (struct r600_texture*)texture;
+       unsigned base_level, first_level, last_level;
+       unsigned char state_swizzle[4];
+       unsigned height, depth, width;
+       unsigned last_layer = state->u.tex.last_layer;
+
+       if (!view)
+               return NULL;
+
+       /* initialize base object */
+       view->base = *state;
+       view->base.texture = NULL;
+       view->base.reference.count = 1;
+       view->base.context = ctx;
+
+       /* NULL resource, obey swizzle (only ZERO and ONE make sense). */
+       if (!texture) {
+               view->state[3] = S_008F1C_DST_SEL_X(si_map_swizzle(state->swizzle_r)) |
+                                S_008F1C_DST_SEL_Y(si_map_swizzle(state->swizzle_g)) |
+                                S_008F1C_DST_SEL_Z(si_map_swizzle(state->swizzle_b)) |
+                                S_008F1C_DST_SEL_W(si_map_swizzle(state->swizzle_a)) |
+                                S_008F1C_TYPE(V_008F1C_SQ_RSRC_IMG_1D);
+               return &view->base;
+       }
+
+       pipe_resource_reference(&view->base.texture, texture);
+
+       if (state->format == PIPE_FORMAT_X24S8_UINT ||
+           state->format == PIPE_FORMAT_S8X24_UINT ||
+           state->format == PIPE_FORMAT_X32_S8X24_UINT ||
+           state->format == PIPE_FORMAT_S8_UINT)
+               view->is_stencil_sampler = true;
+
+       /* Buffer resource. */
+       if (texture->target == PIPE_BUFFER) {
+               si_make_buffer_descriptor(sctx->screen,
+                                         (struct r600_resource *)texture,
+                                         state->format,
+                                         state->u.buf.first_element,
+                                         state->u.buf.last_element,
+                                         view->state);
+
+               LIST_ADDTAIL(&view->list, &sctx->b.texture_buffers);
+               return &view->base;
+       }
+
+       state_swizzle[0] = state->swizzle_r;
+       state_swizzle[1] = state->swizzle_g;
+       state_swizzle[2] = state->swizzle_b;
+       state_swizzle[3] = state->swizzle_a;
+
+       base_level = 0;
+       first_level = state->u.tex.first_level;
+       last_level = state->u.tex.last_level;
+       width = width0;
+       height = height0;
+       depth = texture->depth0;
+
+       if (force_level) {
+               assert(force_level == first_level &&
+                      force_level == last_level);
+               base_level = force_level;
+               first_level = 0;
+               last_level = 0;
+               width = u_minify(width, force_level);
+               height = u_minify(height, force_level);
+               depth = u_minify(depth, force_level);
        }
 
+       /* This is not needed if state trackers set last_layer correctly. */
+       if (state->target == PIPE_TEXTURE_1D ||
+           state->target == PIPE_TEXTURE_2D ||
+           state->target == PIPE_TEXTURE_RECT ||
+           state->target == PIPE_TEXTURE_CUBE)
+               last_layer = state->u.tex.first_layer;
+
+       si_make_texture_descriptor(sctx->screen, tmp, true, state->target,
+                                  state->format, state_swizzle,
+                                  base_level, first_level, last_level,
+                                  state->u.tex.first_layer, last_layer,
+                                  width, height, depth,
+                                  view->state, view->fmask_state);
+
        return &view->base;
 }
 
@@ -3480,6 +3521,42 @@ static void si_texture_barrier(struct pipe_context *ctx)
                         SI_CONTEXT_FLUSH_AND_INV_CB;
 }
 
+static void si_memory_barrier(struct pipe_context *ctx, unsigned flags)
+{
+       struct si_context *sctx = (struct si_context *)ctx;
+
+       /* Subsequent commands must wait for all shader invocations to
+        * complete. */
+       sctx->b.flags |= SI_CONTEXT_PS_PARTIAL_FLUSH;
+
+       if (flags & PIPE_BARRIER_CONSTANT_BUFFER)
+               sctx->b.flags |= SI_CONTEXT_INV_SMEM_L1 |
+                                SI_CONTEXT_INV_VMEM_L1;
+
+       if (flags & (PIPE_BARRIER_VERTEX_BUFFER |
+                    PIPE_BARRIER_SHADER_BUFFER |
+                    PIPE_BARRIER_TEXTURE |
+                    PIPE_BARRIER_IMAGE)) {
+               /* As far as I can tell, L1 contents are written back to L2
+                * automatically at end of shader, but the contents of other
+                * L1 caches might still be stale. */
+               sctx->b.flags |= SI_CONTEXT_INV_VMEM_L1;
+       }
+
+       if (flags & PIPE_BARRIER_FRAMEBUFFER)
+               sctx->b.flags |= SI_CONTEXT_FLUSH_AND_INV_FRAMEBUFFER;
+
+       if (flags & (PIPE_BARRIER_MAPPED_BUFFER |
+                    PIPE_BARRIER_FRAMEBUFFER)) {
+               /* Not sure if INV_GLOBAL_L2 is the best thing here.
+                *
+                * We need to make sure that TC L1 & L2 are written back to
+                * memory, because neither CPU accesses nor CB fetches consider
+                * TC, but there's no need to invalidate any TC cache lines. */
+               sctx->b.flags |= SI_CONTEXT_INV_GLOBAL_L2;
+       }
+}
+
 static void *si_create_blend_custom(struct si_context *sctx, unsigned mode)
 {
        struct pipe_blend_state blend;
@@ -3560,6 +3637,7 @@ void si_init_state_functions(struct si_context *sctx)
        sctx->b.b.set_index_buffer = si_set_index_buffer;
 
        sctx->b.b.texture_barrier = si_texture_barrier;
+       sctx->b.b.memory_barrier = si_memory_barrier;
        sctx->b.b.set_polygon_stipple = si_set_polygon_stipple;
        sctx->b.b.set_min_samples = si_set_min_samples;
        sctx->b.b.set_tess_state = si_set_tess_state;
@@ -3578,6 +3656,69 @@ void si_init_state_functions(struct si_context *sctx)
        si_init_config(sctx);
 }
 
+static void si_query_opaque_metadata(struct r600_common_screen *rscreen,
+                                    struct r600_texture *rtex,
+                                    struct radeon_bo_metadata *md)
+{
+       struct si_screen *sscreen = (struct si_screen*)rscreen;
+       struct pipe_resource *res = &rtex->resource.b.b;
+       static const unsigned char swizzle[] = {
+               PIPE_SWIZZLE_RED,
+               PIPE_SWIZZLE_GREEN,
+               PIPE_SWIZZLE_BLUE,
+               PIPE_SWIZZLE_ALPHA
+       };
+       uint32_t desc[8], i;
+       bool is_array = util_resource_is_array_texture(res);
+
+       /* DRM 2.x.x doesn't support this. */
+       if (rscreen->info.drm_major != 3)
+               return;
+
+       assert(rtex->fmask.size == 0);
+
+       /* Metadata image format format version 1:
+        * [0] = 1 (metadata format identifier)
+        * [1] = (VENDOR_ID << 16) | PCI_ID
+        * [2:9] = image descriptor for the whole resource
+        *         [2] is always 0, because the base address is cleared
+        *         [9] is the DCC offset bits [39:8] from the beginning of
+        *             the buffer
+        * [10:10+LAST_LEVEL] = mipmap level offset bits [39:8] for each level
+        */
+
+       md->metadata[0] = 1; /* metadata image format version 1 */
+
+       /* TILE_MODE_INDEX is ambiguous without a PCI ID. */
+       md->metadata[1] = (ATI_VENDOR_ID << 16) | rscreen->info.pci_id;
+
+       si_make_texture_descriptor(sscreen, rtex, true,
+                                  res->target, res->format,
+                                  swizzle, 0, 0, res->last_level, 0,
+                                  is_array ? res->array_size - 1 : 0,
+                                  res->width0, res->height0, res->depth0,
+                                  desc, NULL);
+
+       /* Clear the base address and set the relative DCC offset. */
+       desc[0] = 0;
+       desc[1] &= C_008F14_BASE_ADDRESS_HI;
+       desc[7] = rtex->dcc_offset >> 8;
+
+       /* Dwords [2:9] contain the image descriptor. */
+       memcpy(&md->metadata[2], desc, sizeof(desc));
+
+       /* Dwords [10:..] contain the mipmap level offsets. */
+       for (i = 0; i <= res->last_level; i++)
+               md->metadata[10+i] = rtex->surface.level[i].offset >> 8;
+
+       md->size_metadata = (11 + res->last_level) * 4;
+}
+
+void si_init_screen_state_functions(struct si_screen *sscreen)
+{
+       sscreen->b.query_opaque_metadata = si_query_opaque_metadata;
+}
+
 static void
 si_write_harvested_raster_configs(struct si_context *sctx,
                                  struct si_pm4_state *pm4,