#include <inttypes.h>
#include "state_tracker/drm_driver.h"
#include "sid.h"
+#include "amd/addrlib/inc/addrinterface.h"
static enum radeon_surf_mode
si_choose_tiling(struct si_screen *sscreen,
flags |= RADEON_SURF_DISABLE_DCC;
/* GFX9: DCC clear for 4x and 8x MSAA textures unimplemented. */
- if (sscreen->info.chip_class >= GFX9 &&
+ if (sscreen->info.chip_class == GFX9 &&
ptex->nr_storage_samples >= 4)
flags |= RADEON_SURF_DISABLE_DCC;
+ /* TODO: GFX10: DCC causes corruption with MSAA. */
+ if (sscreen->info.chip_class >= GFX10 &&
+ ptex->nr_storage_samples >= 2)
+ flags |= RADEON_SURF_DISABLE_DCC;
+
if (ptex->bind & PIPE_BIND_SCANOUT || is_scanout) {
/* This should catch bugs in gallium users setting incorrect flags. */
assert(ptex->nr_samples <= 1 &&
if (!(ptex->flags & SI_RESOURCE_FLAG_FORCE_MSAA_TILING))
flags |= RADEON_SURF_OPTIMIZE_FOR_SPACE;
+ if (sscreen->info.chip_class >= GFX10 &&
+ (ptex->flags & SI_RESOURCE_FLAG_FORCE_MSAA_TILING)) {
+ flags |= RADEON_SURF_FORCE_SWIZZLE_MODE;
+ surface->u.gfx9.surf.swizzle_mode = ADDR_SW_64KB_R_X;
+ }
+
r = sscreen->ws->surface_init(sscreen->ws, ptex, flags, bpe,
array_mode, surface);
if (r) {
bool is_array = util_texture_is_array(res->target);
uint32_t desc[8];
- si_make_texture_descriptor(sscreen, tex, true,
+ sscreen->make_texture_descriptor(sscreen, tex, true,
res->target, res->format,
swizzle, 0, res->last_level, 0,
is_array ? res->array_size - 1 : 0,
/* Clear the base address and set the relative DCC offset. */
desc[0] = 0;
desc[1] &= C_008F14_BASE_ADDRESS_HI;
- desc[7] = tex->dcc_offset >> 8;
+
+ switch (sscreen->info.chip_class) {
+ case GFX6:
+ case GFX7:
+ break;
+ case GFX8:
+ desc[7] = tex->dcc_offset >> 8;
+ break;
+ case GFX9:
+ desc[7] = tex->dcc_offset >> 8;
+ desc[5] &= C_008F24_META_DATA_ADDRESS;
+ desc[5] |= S_008F24_META_DATA_ADDRESS(tex->dcc_offset >> 40);
+ break;
+ case GFX10:
+ desc[6] &= C_00A018_META_DATA_ADDRESS_LO;
+ desc[6] |= S_00A018_META_DATA_ADDRESS_LO(tex->dcc_offset >> 8);
+ desc[7] = tex->dcc_offset >> 16;
+ break;
+ default:
+ assert(0);
+ }
+
/* Dwords [2:9] contain the image descriptor. */
memcpy(&md.metadata[2], desc, sizeof(desc));
sscreen->ws->buffer_set_metadata(tex->buffer.buf, &md);
}
-static void si_get_opaque_metadata(struct si_screen *sscreen,
- struct si_texture *tex,
- struct radeon_bo_metadata *md)
+static bool si_read_tex_bo_metadata(struct si_screen *sscreen,
+ struct si_texture *tex,
+ struct radeon_bo_metadata *md)
{
uint32_t *desc = &md->metadata[2];
- if (sscreen->info.chip_class < GFX8)
- return;
+ if (md->size_metadata < 10 * 4 || /* at least 2(header) + 8(desc) dwords */
+ md->metadata[0] == 0 || /* invalid version number */
+ md->metadata[1] != si_get_bo_metadata_word1(sscreen)) /* invalid PCI ID */ {
+ /* Don't report an error if the texture comes from an incompatible driver,
+ * but this might not work.
+ */
+ return true;
+ }
- /* Return if DCC is enabled. The texture should be set up with it
- * already.
- */
- if (md->size_metadata >= 10 * 4 && /* at least 2(header) + 8(desc) dwords */
- md->metadata[0] != 0 &&
- md->metadata[1] == si_get_bo_metadata_word1(sscreen) &&
+ /* Validate that sample counts and the number of mipmap levels match. */
+ unsigned last_level = G_008F1C_LAST_LEVEL(desc[3]);
+ unsigned type = G_008F1C_TYPE(desc[3]);
+
+ if (type == V_008F1C_SQ_RSRC_IMG_2D_MSAA ||
+ type == V_008F1C_SQ_RSRC_IMG_2D_MSAA_ARRAY) {
+ unsigned log_samples =
+ util_logbase2(MAX2(1, tex->buffer.b.b.nr_storage_samples));
+
+ if (last_level != log_samples) {
+ fprintf(stderr, "radeonsi: invalid MSAA texture import, "
+ "metadata has log2(samples) = %u, the caller set %u\n",
+ last_level, log_samples);
+ return false;
+ }
+ } else {
+ if (last_level != tex->buffer.b.b.last_level) {
+ fprintf(stderr, "radeonsi: invalid mipmapped texture import, "
+ "metadata has last_level = %u, the caller set %u\n",
+ last_level, tex->buffer.b.b.last_level);
+ return false;
+ }
+ }
+
+ if (sscreen->info.chip_class >= GFX8 &&
G_008F28_COMPRESSION_EN(desc[6])) {
- tex->dcc_offset = (uint64_t)desc[7] << 8;
+ /* Read DCC information.
+ *
+ * Some state trackers don't set the SCANOUT flag when
+ * importing displayable images, which affects PIPE_ALIGNED
+ * and RB_ALIGNED, so we need to recover them here.
+ */
+ switch (sscreen->info.chip_class) {
+ case GFX8:
+ tex->dcc_offset = (uint64_t)desc[7] << 8;
+ break;
- if (sscreen->info.chip_class >= GFX9) {
- /* Fix up parameters for displayable DCC. Some state
- * trackers don't set the SCANOUT flag when importing
- * displayable images, so we have to recover the correct
- * parameters here.
- */
+ case GFX9:
+ tex->dcc_offset =
+ ((uint64_t)desc[7] << 8) |
+ ((uint64_t)G_008F24_META_DATA_ADDRESS(desc[5]) << 40);
tex->surface.u.gfx9.dcc.pipe_aligned =
G_008F24_META_PIPE_ALIGNED(desc[5]);
tex->surface.u.gfx9.dcc.rb_aligned =
if (!tex->surface.u.gfx9.dcc.pipe_aligned &&
!tex->surface.u.gfx9.dcc.rb_aligned)
tex->surface.is_displayable = true;
+ break;
+
+ case GFX10:
+ tex->dcc_offset =
+ ((uint64_t)G_00A018_META_DATA_ADDRESS_LO(desc[6]) << 8) |
+ ((uint64_t)desc[7] << 16);
+ tex->surface.u.gfx9.dcc.pipe_aligned =
+ G_00A018_META_PIPE_ALIGNED(desc[6]);
+ break;
+
+ default:
+ assert(0);
+ return false;
}
- return;
+ } else {
+ /* Disable DCC. dcc_offset is always set by texture_from_handle
+ * and must be cleared here.
+ */
+ tex->dcc_offset = 0;
}
- /* Disable DCC. These are always set by texture_from_handle and must
- * be cleared here.
- */
- tex->dcc_offset = 0;
+ return true;
}
static bool si_has_displayable_dcc(struct si_texture *tex)
*poffset = offset;
}
-static boolean si_texture_get_handle(struct pipe_screen* screen,
- struct pipe_context *ctx,
- struct pipe_resource *resource,
- struct winsys_handle *whandle,
- unsigned usage)
+static bool si_texture_get_handle(struct pipe_screen* screen,
+ struct pipe_context *ctx,
+ struct pipe_resource *resource,
+ struct winsys_handle *whandle,
+ unsigned usage)
{
struct si_screen *sscreen = (struct si_screen*)screen;
struct si_context *sctx;
if (sscreen->info.chip_class >= GFX9) {
tex->can_sample_z = true;
tex->can_sample_s = true;
+
+ /* Stencil texturing with HTILE doesn't work
+ * with mipmapping on Navi10-14. */
+ if ((sscreen->info.family == CHIP_NAVI10 ||
+ sscreen->info.family == CHIP_NAVI12 ||
+ sscreen->info.family == CHIP_NAVI14) &&
+ base->last_level > 0)
+ tex->htile_stencil_disabled = true;
} else {
tex->can_sample_z = !tex->surface.u.legacy.depth_adjusted;
tex->can_sample_s = !tex->surface.u.legacy.stencil_adjusted;
/* Shared textures must always set up DCC here.
* If it's not present, it will be disabled by
- * apply_opaque_metadata later.
+ * si_get_opaque_metadata later.
*/
if (tex->surface.dcc_size &&
(buf || !(sscreen->debug_flags & DBG(NO_DCC))) &&
tex->buffer.b.is_shared = true;
tex->buffer.external_usage = usage;
- si_get_opaque_metadata(sscreen, tex, &metadata);
+ if (!si_read_tex_bo_metadata(sscreen, tex, &metadata)) {
+ si_texture_reference(&tex, NULL);
+ return NULL;
+ }
/* Displayable DCC requires an explicit flush. */
if (dedicated &&
unsigned stride = 0, offset = 0;
/* Support only 2D textures without mipmaps */
- if ((templ->target != PIPE_TEXTURE_2D && templ->target != PIPE_TEXTURE_RECT) ||
- templ->depth0 != 1 || templ->last_level != 0)
+ if ((templ->target != PIPE_TEXTURE_2D && templ->target != PIPE_TEXTURE_RECT &&
+ templ->target != PIPE_TEXTURE_2D_ARRAY) ||
+ templ->last_level != 0)
return NULL;
buf = sscreen->ws->buffer_from_handle(sscreen->ws, whandle,
/* Return if it's allowed to reinterpret one format as another with DCC enabled.
*/
-bool vi_dcc_formats_compatible(enum pipe_format format1,
+bool vi_dcc_formats_compatible(struct si_screen *sscreen,
+ enum pipe_format format1,
enum pipe_format format2)
{
const struct util_format_description *desc1, *desc2;
/* If the clear values are all 1 or all 0, this constraint can be
* ignored. */
- if (vi_alpha_is_on_msb(format1) != vi_alpha_is_on_msb(format2))
+ if (vi_alpha_is_on_msb(sscreen, format1) != vi_alpha_is_on_msb(sscreen, format2))
return false;
/* Channel types must match if the clear value of 1 is used.
struct si_texture *stex = (struct si_texture *)tex;
return vi_dcc_enabled(stex, level) &&
- !vi_dcc_formats_compatible(tex->format, view_format);
+ !vi_dcc_formats_compatible((struct si_screen*)tex->screen,
+ tex->format, view_format);
}
/* This can't be merged with the above function, because