X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fradeonsi%2Fsi_texture.c;h=904a39b6fed7deb2dd70264c28c3e1232279a1c4;hb=46dae9ef587061849de24875e59e8a293182336d;hp=7b72e51065c5d6af498333bab2127b0aec2d0384;hpb=6eb219e963be879d807969d81c30618d373028f8;p=mesa.git diff --git a/src/gallium/drivers/radeonsi/si_texture.c b/src/gallium/drivers/radeonsi/si_texture.c index 7b72e51065c..904a39b6fed 100644 --- a/src/gallium/drivers/radeonsi/si_texture.c +++ b/src/gallium/drivers/radeonsi/si_texture.c @@ -289,10 +289,15 @@ static int si_init_surface(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 && @@ -703,7 +708,28 @@ static void si_set_tex_bo_metadata(struct si_screen *sscreen, /* 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)); @@ -720,30 +746,62 @@ static void si_set_tex_bo_metadata(struct si_screen *sscreen, 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 = @@ -753,14 +811,28 @@ static void si_get_opaque_metadata(struct si_screen *sscreen, 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) @@ -819,11 +891,11 @@ static void si_texture_get_info(struct pipe_screen* screen, *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; @@ -1267,6 +1339,14 @@ si_texture_create_object(struct pipe_screen *screen, 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; @@ -1300,7 +1380,7 @@ si_texture_create_object(struct pipe_screen *screen, /* 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))) && @@ -1678,7 +1758,10 @@ static struct pipe_resource *si_texture_from_winsys_buffer(struct si_screen *ssc 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 && @@ -1705,8 +1788,9 @@ static struct pipe_resource *si_texture_from_handle(struct pipe_screen *screen, 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,