#include "r600_cs.h"
#include "r600_query.h"
#include "util/u_format.h"
+#include "util/u_log.h"
#include "util/u_memory.h"
#include "util/u_pack_color.h"
#include "util/u_surface.h"
bpe = 4; /* stencil is allocated separately on evergreen */
} else {
bpe = util_format_get_blocksize(ptex->format);
- /* align byte per element on dword */
- if (bpe == 3) {
- bpe = 4;
- }
+ assert(util_is_power_of_two(bpe));
}
if (!is_flushed_depth && is_depth) {
flags |= RADEON_SURF_SCANOUT;
}
+ if (ptex->bind & PIPE_BIND_SHARED)
+ flags |= RADEON_SURF_SHAREABLE;
if (is_imported)
- flags |= RADEON_SURF_IMPORTED;
+ flags |= RADEON_SURF_IMPORTED | RADEON_SURF_SHAREABLE;
if (!(ptex->flags & R600_RESOURCE_FLAG_FORCE_TILING))
flags |= RADEON_SURF_OPTIMIZE_FOR_SPACE;
}
}
+static void r600_surface_import_metadata(struct r600_common_screen *rscreen,
+ struct radeon_surf *surf,
+ struct radeon_bo_metadata *metadata,
+ enum radeon_surf_mode *array_mode,
+ bool *is_scanout)
+{
+ if (rscreen->chip_class >= GFX9) {
+ if (metadata->u.gfx9.swizzle_mode > 0)
+ *array_mode = RADEON_SURF_MODE_2D;
+ else
+ *array_mode = RADEON_SURF_MODE_LINEAR_ALIGNED;
+
+ *is_scanout = metadata->u.gfx9.swizzle_mode == 0 ||
+ metadata->u.gfx9.swizzle_mode % 4 == 2;
+ } else {
+ surf->u.legacy.pipe_config = metadata->u.legacy.pipe_config;
+ surf->u.legacy.bankw = metadata->u.legacy.bankw;
+ surf->u.legacy.bankh = metadata->u.legacy.bankh;
+ surf->u.legacy.tile_split = metadata->u.legacy.tile_split;
+ surf->u.legacy.mtilea = metadata->u.legacy.mtilea;
+ surf->u.legacy.num_banks = metadata->u.legacy.num_banks;
+
+ if (metadata->u.legacy.macrotile == RADEON_LAYOUT_TILED)
+ *array_mode = RADEON_SURF_MODE_2D;
+ else if (metadata->u.legacy.microtile == RADEON_LAYOUT_TILED)
+ *array_mode = RADEON_SURF_MODE_1D;
+ else
+ *array_mode = RADEON_SURF_MODE_LINEAR_ALIGNED;
+
+ *is_scanout = metadata->u.legacy.scanout;
+ }
+}
+
static void r600_eliminate_fast_color_clear(struct r600_common_context *rctx,
struct r600_texture *rtex)
{
return r600_texture_discard_dcc(rscreen, rtex);
}
-static void r600_degrade_tile_mode_to_linear(struct r600_common_context *rctx,
- struct r600_texture *rtex,
- bool invalidate_storage)
+static void r600_reallocate_texture_inplace(struct r600_common_context *rctx,
+ struct r600_texture *rtex,
+ unsigned new_bind_flag,
+ bool invalidate_storage)
{
struct pipe_screen *screen = rctx->b.screen;
struct r600_texture *new_tex;
struct pipe_resource templ = rtex->resource.b.b;
unsigned i;
- templ.bind |= PIPE_BIND_LINEAR;
+ templ.bind |= new_bind_flag;
/* r600g doesn't react to dirty_tex_descriptor_counter */
if (rctx->chip_class < SI)
return;
- if (rtex->resource.b.is_shared ||
- rtex->surface.is_linear)
+ if (rtex->resource.b.is_shared)
return;
- /* This fails with MSAA, depth, and compressed textures. */
- if (r600_choose_tiling(rctx->screen, &templ) !=
- RADEON_SURF_MODE_LINEAR_ALIGNED)
- return;
+ if (new_bind_flag == PIPE_BIND_LINEAR) {
+ if (rtex->surface.is_linear)
+ return;
+
+ /* This fails with MSAA, depth, and compressed textures. */
+ if (r600_choose_tiling(rctx->screen, &templ) !=
+ RADEON_SURF_MODE_LINEAR_ALIGNED)
+ return;
+ }
new_tex = (struct r600_texture*)screen->resource_create(screen, &templ);
if (!new_tex)
}
}
- r600_texture_discard_cmask(rctx->screen, rtex);
- r600_texture_discard_dcc(rctx->screen, rtex);
+ if (new_bind_flag == PIPE_BIND_LINEAR) {
+ r600_texture_discard_cmask(rctx->screen, rtex);
+ r600_texture_discard_dcc(rctx->screen, rtex);
+ }
/* Replace the structure fields of rtex. */
rtex->resource.b.b.bind = templ.bind;
rtex->resource.domains = new_tex->resource.domains;
rtex->resource.flags = new_tex->resource.flags;
rtex->size = new_tex->size;
+ rtex->db_render_format = new_tex->db_render_format;
+ rtex->db_compatible = new_tex->db_compatible;
+ rtex->can_sample_z = new_tex->can_sample_z;
+ rtex->can_sample_s = new_tex->can_sample_s;
rtex->surface = new_tex->surface;
- rtex->non_disp_tiling = new_tex->non_disp_tiling;
+ rtex->fmask = new_tex->fmask;
+ rtex->cmask = new_tex->cmask;
rtex->cb_color_info = new_tex->cb_color_info;
- rtex->cmask = new_tex->cmask; /* needed even without CMASK */
+ rtex->last_msaa_resolve_target_micro_mode = new_tex->last_msaa_resolve_target_micro_mode;
+ rtex->htile_offset = new_tex->htile_offset;
+ rtex->tc_compatible_htile = new_tex->tc_compatible_htile;
+ rtex->depth_cleared = new_tex->depth_cleared;
+ rtex->stencil_cleared = new_tex->stencil_cleared;
+ rtex->non_disp_tiling = new_tex->non_disp_tiling;
+ rtex->dcc_gather_statistics = new_tex->dcc_gather_statistics;
+ rtex->framebuffers_bound = new_tex->framebuffers_bound;
- assert(!rtex->htile_buffer);
- assert(!rtex->cmask.size);
- assert(!rtex->fmask.size);
- assert(!rtex->dcc_offset);
- assert(!rtex->is_depth);
+ if (new_bind_flag == PIPE_BIND_LINEAR) {
+ assert(!rtex->htile_offset);
+ assert(!rtex->cmask.size);
+ assert(!rtex->fmask.size);
+ assert(!rtex->dcc_offset);
+ assert(!rtex->is_depth);
+ }
r600_texture_reference(&new_tex, NULL);
ctx = threaded_context_unwrap_sync(ctx);
rctx = (struct r600_common_context*)(ctx ? ctx : rscreen->aux_context);
- /* This is not supported now, but it might be required for OpenCL
- * interop in the future.
- */
- if (resource->target != PIPE_BUFFER &&
- (resource->nr_samples > 1 || rtex->is_depth))
- return false;
-
if (resource->target != PIPE_BUFFER) {
+ /* This is not supported now, but it might be required for OpenCL
+ * interop in the future.
+ */
+ if (resource->nr_samples > 1 || rtex->is_depth)
+ return false;
+
+ /* Move a suballocated texture into a non-suballocated allocation. */
+ if (rscreen->ws->buffer_is_suballocated(res->buf) ||
+ rtex->surface.tile_swizzle) {
+ assert(!res->b.is_shared);
+ r600_reallocate_texture_inplace(rctx, rtex,
+ PIPE_BIND_SHARED, false);
+ rctx->b.flush(&rctx->b, NULL, 0);
+ assert(res->b.b.bind & PIPE_BIND_SHARED);
+ assert(res->flags & RADEON_FLAG_NO_SUBALLOC);
+ assert(rtex->surface.tile_swizzle == 0);
+ }
+
/* Since shader image stores don't support DCC on VI,
* disable it for external clients that want write
* access.
rscreen->ws->buffer_set_metadata(res->buf, &metadata);
}
+
+ if (rscreen->chip_class >= GFX9) {
+ offset = rtex->surface.u.gfx9.surf_offset;
+ stride = rtex->surface.u.gfx9.surf_pitch *
+ rtex->surface.bpe;
+ slice_size = rtex->surface.u.gfx9.surf_slice_size;
+ } else {
+ offset = rtex->surface.u.legacy.level[0].offset;
+ stride = rtex->surface.u.legacy.level[0].nblk_x *
+ rtex->surface.bpe;
+ slice_size = rtex->surface.u.legacy.level[0].slice_size;
+ }
+ } else {
+ /* Move a suballocated buffer into a non-suballocated allocation. */
+ if (rscreen->ws->buffer_is_suballocated(res->buf)) {
+ assert(!res->b.is_shared);
+
+ /* Allocate a new buffer with PIPE_BIND_SHARED. */
+ struct pipe_resource templ = res->b.b;
+ templ.bind |= PIPE_BIND_SHARED;
+
+ struct pipe_resource *newb =
+ screen->resource_create(screen, &templ);
+ if (!newb)
+ return false;
+
+ /* Copy the old buffer contents to the new one. */
+ struct pipe_box box;
+ u_box_1d(0, newb->width0, &box);
+ rctx->b.resource_copy_region(&rctx->b, newb, 0, 0, 0, 0,
+ &res->b.b, 0, &box);
+ /* Move the new buffer storage to the old pipe_resource. */
+ r600_replace_buffer_storage(&rctx->b, &res->b.b, newb);
+ pipe_resource_reference(&newb, NULL);
+
+ assert(res->b.b.bind & PIPE_BIND_SHARED);
+ assert(res->flags & RADEON_FLAG_NO_SUBALLOC);
+ }
+
+ /* Buffers */
+ offset = 0;
+ stride = 0;
+ slice_size = 0;
}
if (res->b.is_shared) {
res->external_usage = usage;
}
- if (rscreen->chip_class >= GFX9) {
- offset = rtex->surface.u.gfx9.surf_offset;
- stride = rtex->surface.u.gfx9.surf_pitch *
- rtex->surface.bpe;
- slice_size = rtex->surface.u.gfx9.surf_slice_size;
- } else {
- offset = rtex->surface.u.legacy.level[0].offset;
- stride = rtex->surface.u.legacy.level[0].nblk_x *
- rtex->surface.bpe;
- slice_size = rtex->surface.u.legacy.level[0].slice_size;
- }
return rscreen->ws->buffer_get_handle(res->buf, stride, offset,
slice_size, whandle);
}
r600_texture_reference(&rtex->flushed_depth_texture, NULL);
- r600_resource_reference(&rtex->htile_buffer, NULL);
if (rtex->cmask_buffer != &rtex->resource) {
r600_resource_reference(&rtex->cmask_buffer, NULL);
}
out->tile_mode_index = fmask.u.legacy.tiling_index[0];
out->pitch_in_pixels = fmask.u.legacy.level[0].nblk_x;
out->bank_height = fmask.u.legacy.bankh;
+ out->tile_swizzle = fmask.tile_swizzle;
out->alignment = MAX2(256, fmask.surf_alignment);
out->size = fmask.surf_size;
}
static void r600_texture_allocate_htile(struct r600_common_screen *rscreen,
struct r600_texture *rtex)
{
- uint32_t clear_value;
-
- if (rscreen->chip_class >= GFX9 || rtex->tc_compatible_htile) {
- clear_value = 0x0000030F;
- } else {
+ if (rscreen->chip_class <= VI && !rtex->tc_compatible_htile)
r600_texture_get_htile_size(rscreen, rtex);
- clear_value = 0;
- }
if (!rtex->surface.htile_size)
return;
- rtex->htile_buffer = (struct r600_resource*)
- r600_aligned_buffer_create(&rscreen->b,
- R600_RESOURCE_FLAG_UNMAPPABLE,
- PIPE_USAGE_DEFAULT,
- rtex->surface.htile_size,
- rtex->surface.htile_alignment);
- if (rtex->htile_buffer == NULL) {
- /* this is not a fatal error as we can still keep rendering
- * without htile buffer */
- R600_ERR("Failed to create buffer object for htile buffer.\n");
- } else {
- r600_screen_clear_buffer(rscreen, &rtex->htile_buffer->b.b,
- 0, rtex->surface.htile_size,
- clear_value);
- }
+ rtex->htile_offset = align(rtex->size, rtex->surface.htile_alignment);
+ rtex->size = rtex->htile_offset + rtex->surface.htile_size;
}
void r600_print_texture_info(struct r600_common_screen *rscreen,
- struct r600_texture *rtex, FILE *f)
+ struct r600_texture *rtex, struct u_log_context *log)
{
int i;
/* Common parameters. */
- fprintf(f, " Info: npix_x=%u, npix_y=%u, npix_z=%u, blk_w=%u, "
+ u_log_printf(log, " Info: npix_x=%u, npix_y=%u, npix_z=%u, blk_w=%u, "
"blk_h=%u, array_size=%u, last_level=%u, "
"bpe=%u, nsamples=%u, flags=0x%x, %s\n",
rtex->resource.b.b.width0, rtex->resource.b.b.height0,
rtex->surface.flags, util_format_short_name(rtex->resource.b.b.format));
if (rscreen->chip_class >= GFX9) {
- fprintf(f, " Surf: size=%"PRIu64", slice_size=%"PRIu64", "
+ u_log_printf(log, " Surf: size=%"PRIu64", slice_size=%"PRIu64", "
"alignment=%u, swmode=%u, epitch=%u, pitch=%u\n",
rtex->surface.surf_size,
rtex->surface.u.gfx9.surf_slice_size,
rtex->surface.u.gfx9.surf_pitch);
if (rtex->fmask.size) {
- fprintf(f, " FMASK: offset=%"PRIu64", size=%"PRIu64", "
+ u_log_printf(log, " FMASK: offset=%"PRIu64", size=%"PRIu64", "
"alignment=%u, swmode=%u, epitch=%u\n",
rtex->fmask.offset,
rtex->surface.u.gfx9.fmask_size,
}
if (rtex->cmask.size) {
- fprintf(f, " CMask: offset=%"PRIu64", size=%"PRIu64", "
+ u_log_printf(log, " CMask: offset=%"PRIu64", size=%"PRIu64", "
"alignment=%u, rb_aligned=%u, pipe_aligned=%u\n",
rtex->cmask.offset,
rtex->surface.u.gfx9.cmask_size,
rtex->surface.u.gfx9.cmask.pipe_aligned);
}
- if (rtex->htile_buffer) {
- fprintf(f, " HTile: size=%u, alignment=%u, "
+ if (rtex->htile_offset) {
+ u_log_printf(log, " HTile: offset=%"PRIu64", size=%"PRIu64", alignment=%u, "
"rb_aligned=%u, pipe_aligned=%u\n",
- rtex->htile_buffer->b.b.width0,
- rtex->htile_buffer->buf->alignment,
+ rtex->htile_offset,
+ rtex->surface.htile_size,
+ rtex->surface.htile_alignment,
rtex->surface.u.gfx9.htile.rb_aligned,
rtex->surface.u.gfx9.htile.pipe_aligned);
}
if (rtex->dcc_offset) {
- fprintf(f, " DCC: offset=%"PRIu64", size=%"PRIu64", "
+ u_log_printf(log, " DCC: offset=%"PRIu64", size=%"PRIu64", "
"alignment=%u, pitch_max=%u, num_dcc_levels=%u\n",
rtex->dcc_offset, rtex->surface.dcc_size,
rtex->surface.dcc_alignment,
}
if (rtex->surface.u.gfx9.stencil_offset) {
- fprintf(f, " Stencil: offset=%"PRIu64", swmode=%u, epitch=%u\n",
+ u_log_printf(log, " Stencil: offset=%"PRIu64", swmode=%u, epitch=%u\n",
rtex->surface.u.gfx9.stencil_offset,
rtex->surface.u.gfx9.stencil.swizzle_mode,
rtex->surface.u.gfx9.stencil.epitch);
return;
}
- fprintf(f, " Layout: size=%"PRIu64", alignment=%u, bankw=%u, "
+ u_log_printf(log, " Layout: size=%"PRIu64", alignment=%u, bankw=%u, "
"bankh=%u, nbanks=%u, mtilea=%u, tilesplit=%u, pipeconfig=%u, scanout=%u\n",
rtex->surface.surf_size, rtex->surface.surf_alignment, rtex->surface.u.legacy.bankw,
rtex->surface.u.legacy.bankh, rtex->surface.u.legacy.num_banks, rtex->surface.u.legacy.mtilea,
(rtex->surface.flags & RADEON_SURF_SCANOUT) != 0);
if (rtex->fmask.size)
- fprintf(f, " FMask: offset=%"PRIu64", size=%"PRIu64", alignment=%u, pitch_in_pixels=%u, "
+ u_log_printf(log, " FMask: offset=%"PRIu64", size=%"PRIu64", alignment=%u, pitch_in_pixels=%u, "
"bankh=%u, slice_tile_max=%u, tile_mode_index=%u\n",
rtex->fmask.offset, rtex->fmask.size, rtex->fmask.alignment,
rtex->fmask.pitch_in_pixels, rtex->fmask.bank_height,
rtex->fmask.slice_tile_max, rtex->fmask.tile_mode_index);
if (rtex->cmask.size)
- fprintf(f, " CMask: offset=%"PRIu64", size=%"PRIu64", alignment=%u, "
+ u_log_printf(log, " CMask: offset=%"PRIu64", size=%"PRIu64", alignment=%u, "
"slice_tile_max=%u\n",
rtex->cmask.offset, rtex->cmask.size, rtex->cmask.alignment,
rtex->cmask.slice_tile_max);
- if (rtex->htile_buffer)
- fprintf(f, " HTile: size=%u, alignment=%u, TC_compatible = %u\n",
- rtex->htile_buffer->b.b.width0,
- rtex->htile_buffer->buf->alignment,
+ if (rtex->htile_offset)
+ u_log_printf(log, " HTile: offset=%"PRIu64", size=%"PRIu64", "
+ "alignment=%u, TC_compatible = %u\n",
+ rtex->htile_offset, rtex->surface.htile_size,
+ rtex->surface.htile_alignment,
rtex->tc_compatible_htile);
if (rtex->dcc_offset) {
- fprintf(f, " DCC: offset=%"PRIu64", size=%"PRIu64", alignment=%u\n",
+ u_log_printf(log, " DCC: offset=%"PRIu64", size=%"PRIu64", alignment=%u\n",
rtex->dcc_offset, rtex->surface.dcc_size,
rtex->surface.dcc_alignment);
for (i = 0; i <= rtex->resource.b.b.last_level; i++)
- fprintf(f, " DCCLevel[%i]: enabled=%u, offset=%"PRIu64", "
+ u_log_printf(log, " DCCLevel[%i]: enabled=%u, offset=%"PRIu64", "
"fast_clear_size=%"PRIu64"\n",
i, i < rtex->surface.num_dcc_levels,
rtex->surface.u.legacy.level[i].dcc_offset,
}
for (i = 0; i <= rtex->resource.b.b.last_level; i++)
- fprintf(f, " Level[%i]: offset=%"PRIu64", slice_size=%"PRIu64", "
+ u_log_printf(log, " Level[%i]: offset=%"PRIu64", slice_size=%"PRIu64", "
"npix_x=%u, npix_y=%u, npix_z=%u, nblk_x=%u, nblk_y=%u, "
"mode=%u, tiling_index = %u\n",
i, rtex->surface.u.legacy.level[i].offset,
rtex->surface.u.legacy.tiling_index[i]);
if (rtex->surface.flags & RADEON_SURF_SBUFFER) {
- fprintf(f, " StencilLayout: tilesplit=%u\n",
+ u_log_printf(log, " StencilLayout: tilesplit=%u\n",
rtex->surface.u.legacy.stencil_tile_split);
for (i = 0; i <= rtex->resource.b.b.last_level; i++) {
- fprintf(f, " StencilLevel[%i]: offset=%"PRIu64", "
+ u_log_printf(log, " StencilLevel[%i]: offset=%"PRIu64", "
"slice_size=%"PRIu64", npix_x=%u, "
"npix_y=%u, npix_z=%u, nblk_x=%u, nblk_y=%u, "
"mode=%u, tiling_index = %u\n",
r600_init_resource_fields(rscreen, resource, rtex->size,
rtex->surface.surf_alignment);
- resource->flags |= RADEON_FLAG_HANDLE;
+ /* Displayable surfaces are not suballocated. */
+ if (resource->b.b.bind & PIPE_BIND_SCANOUT)
+ resource->flags |= RADEON_FLAG_NO_SUBALLOC;
if (!r600_alloc_resource(rscreen, resource)) {
FREE(rtex);
rtex->cmask.offset, rtex->cmask.size,
0xCCCCCCCC);
}
+ if (rtex->htile_offset) {
+ uint32_t clear_value = 0;
+
+ if (rscreen->chip_class >= GFX9 || rtex->tc_compatible_htile)
+ clear_value = 0x0000030F;
+
+ r600_screen_clear_buffer(rscreen, &rtex->resource.b.b,
+ rtex->htile_offset,
+ rtex->surface.htile_size,
+ clear_value);
+ }
/* Initialize DCC only if the texture is not being imported. */
if (!buf && rtex->dcc_offset) {
if (rscreen->debug_flags & DBG_TEX) {
puts("Texture:");
- r600_print_texture_info(rscreen, rtex, stdout);
+ struct u_log_context log;
+ u_log_context_init(&log);
+ r600_print_texture_info(rscreen, rtex, &log);
+ u_log_new_page_print(&log, stdout);
fflush(stdout);
+ u_log_context_destroy(&log);
}
return rtex;
struct r600_common_screen *rscreen = (struct r600_common_screen*)screen;
struct pb_buffer *buf = NULL;
unsigned stride = 0, offset = 0;
- unsigned array_mode;
- struct radeon_surf surface;
+ enum radeon_surf_mode array_mode;
+ struct radeon_surf surface = {};
int r;
struct radeon_bo_metadata metadata = {};
struct r600_texture *rtex;
return NULL;
rscreen->ws->buffer_get_metadata(buf, &metadata);
-
- if (rscreen->chip_class >= GFX9) {
- if (metadata.u.gfx9.swizzle_mode > 0)
- array_mode = RADEON_SURF_MODE_2D;
- else
- array_mode = RADEON_SURF_MODE_LINEAR_ALIGNED;
-
- is_scanout = metadata.u.gfx9.swizzle_mode == 0 ||
- metadata.u.gfx9.swizzle_mode % 4 == 2;
- } else {
- surface.u.legacy.pipe_config = metadata.u.legacy.pipe_config;
- surface.u.legacy.bankw = metadata.u.legacy.bankw;
- surface.u.legacy.bankh = metadata.u.legacy.bankh;
- surface.u.legacy.tile_split = metadata.u.legacy.tile_split;
- surface.u.legacy.mtilea = metadata.u.legacy.mtilea;
- surface.u.legacy.num_banks = metadata.u.legacy.num_banks;
-
- if (metadata.u.legacy.macrotile == RADEON_LAYOUT_TILED)
- array_mode = RADEON_SURF_MODE_2D;
- else if (metadata.u.legacy.microtile == RADEON_LAYOUT_TILED)
- array_mode = RADEON_SURF_MODE_1D;
- else
- array_mode = RADEON_SURF_MODE_LINEAR_ALIGNED;
-
- is_scanout = metadata.u.legacy.scanout;
- }
+ r600_surface_import_metadata(rscreen, &surface, &metadata,
+ &array_mode, &is_scanout);
r = r600_init_surface(rscreen, &surface, templ, array_mode, stride,
offset, true, is_scanout, false, false);
assert(metadata.u.gfx9.swizzle_mode == surface.u.gfx9.surf.swizzle_mode);
}
+ assert(rtex->surface.tile_swizzle == 0);
return &rtex->resource.b.b;
}
r600_can_invalidate_texture(rctx->screen, rtex,
usage, box);
- r600_degrade_tile_mode_to_linear(rctx, rtex,
- can_invalidate);
+ r600_reallocate_texture_inplace(rctx, rtex,
+ PIPE_BIND_LINEAR,
+ can_invalidate);
}
/* Tiled textures need to be converted into a linear texture for CPU
unsigned level = templ->u.tex.level;
unsigned width = u_minify(tex->width0, level);
unsigned height = u_minify(tex->height0, level);
+ unsigned width0 = tex->width0;
+ unsigned height0 = tex->height0;
if (tex->target != PIPE_BUFFER && templ->format != tex->format) {
const struct util_format_description *tex_desc
width = nblks_x * templ_desc->block.width;
height = nblks_y * templ_desc->block.height;
+
+ width0 = util_format_get_nblocksx(tex->format, width0);
+ height0 = util_format_get_nblocksy(tex->format, height0);
}
}
return r600_create_surface_custom(pipe, tex, templ,
- tex->width0, tex->height0,
+ width0, height0,
width, height);
}
bool main_value = false;
bool extra_value = false;
int extra_channel;
+
+ /* This is needed to get the correct DCC clear value for luminance formats.
+ * 1) Get the linear format (because the next step can't handle L8_SRGB).
+ * 2) Convert luminance to red. (the real hw format for luminance)
+ */
+ surface_format = util_format_linear(surface_format);
+ surface_format = util_format_luminance_to_red(surface_format);
+
const struct util_format_description *desc = util_format_description(surface_format);
if (desc->block.bits == 128 &&
if (surface_format == PIPE_FORMAT_R11G11B10_FLOAT ||
surface_format == PIPE_FORMAT_B5G6R5_UNORM ||
- surface_format == PIPE_FORMAT_B5G6R5_SRGB) {
+ surface_format == PIPE_FORMAT_B5G6R5_SRGB ||
+ util_format_is_alpha(surface_format)) {
extra_channel = -1;
} else if (desc->layout == UTIL_FORMAT_LAYOUT_PLAIN) {
if(r600_translate_colorswap(surface_format, false) <= 1)
void evergreen_do_fast_color_clear(struct r600_common_context *rctx,
struct pipe_framebuffer_state *fb,
struct r600_atom *fb_state,
- unsigned *buffers, unsigned *dirty_cbufs,
+ unsigned *buffers, ubyte *dirty_cbufs,
const union pipe_color_union *color)
{
int i;
uint32_t reset_value;
bool clear_words_needed;
- /* TODO: fix DCC clear */
- if (rctx->chip_class >= GFX9)
- continue;
-
if (rctx->screen->debug_flags & DBG_NO_DCC_CLEAR)
continue;
}
}
+static struct pipe_memory_object *
+r600_memobj_from_handle(struct pipe_screen *screen,
+ struct winsys_handle *whandle,
+ bool dedicated)
+{
+ struct r600_common_screen *rscreen = (struct r600_common_screen*)screen;
+ struct r600_memory_object *memobj = CALLOC_STRUCT(r600_memory_object);
+ struct pb_buffer *buf = NULL;
+ uint32_t stride, offset;
+
+ if (!memobj)
+ return NULL;
+
+ buf = rscreen->ws->buffer_from_handle(rscreen->ws, whandle,
+ &stride, &offset);
+ if (!buf) {
+ free(memobj);
+ return NULL;
+ }
+
+ memobj->b.dedicated = dedicated;
+ memobj->buf = buf;
+ memobj->stride = stride;
+ memobj->offset = offset;
+
+ return (struct pipe_memory_object *)memobj;
+
+}
+
+static void
+r600_memobj_destroy(struct pipe_screen *screen,
+ struct pipe_memory_object *_memobj)
+{
+ struct r600_memory_object *memobj = (struct r600_memory_object *)_memobj;
+
+ pb_reference(&memobj->buf, NULL);
+ free(memobj);
+}
+
+static struct pipe_resource *
+r600_texture_from_memobj(struct pipe_screen *screen,
+ const struct pipe_resource *templ,
+ struct pipe_memory_object *_memobj,
+ uint64_t offset)
+{
+ int r;
+ struct r600_common_screen *rscreen = (struct r600_common_screen*)screen;
+ struct r600_memory_object *memobj = (struct r600_memory_object *)_memobj;
+ struct r600_texture *rtex;
+ struct radeon_surf surface = {};
+ struct radeon_bo_metadata metadata = {};
+ enum radeon_surf_mode array_mode;
+ bool is_scanout;
+ struct pb_buffer *buf = NULL;
+
+ if (memobj->b.dedicated) {
+ rscreen->ws->buffer_get_metadata(memobj->buf, &metadata);
+ r600_surface_import_metadata(rscreen, &surface, &metadata,
+ &array_mode, &is_scanout);
+ } else {
+ /**
+ * The bo metadata is unset for un-dedicated images. So we fall
+ * back to linear. See answer to question 5 of the
+ * VK_KHX_external_memory spec for some details.
+ *
+ * It is possible that this case isn't going to work if the
+ * surface pitch isn't correctly aligned by default.
+ *
+ * In order to support it correctly we require multi-image
+ * metadata to be syncrhonized between radv and radeonsi. The
+ * semantics of associating multiple image metadata to a memory
+ * object on the vulkan export side are not concretely defined
+ * either.
+ *
+ * All the use cases we are aware of at the moment for memory
+ * objects use dedicated allocations. So lets keep the initial
+ * implementation simple.
+ *
+ * A possible alternative is to attempt to reconstruct the
+ * tiling information when the TexParameter TEXTURE_TILING_EXT
+ * is set.
+ */
+ array_mode = RADEON_SURF_MODE_LINEAR_ALIGNED;
+ is_scanout = false;
+
+ }
+
+ r = r600_init_surface(rscreen, &surface, templ,
+ array_mode, memobj->stride,
+ offset, true, is_scanout,
+ false, false);
+ if (r)
+ return NULL;
+
+ rtex = r600_texture_create_object(screen, templ, memobj->buf, &surface);
+ if (!rtex)
+ return NULL;
+
+ /* r600_texture_create_object doesn't increment refcount of
+ * memobj->buf, so increment it here.
+ */
+ pb_reference(&buf, memobj->buf);
+
+ rtex->resource.b.is_shared = true;
+ rtex->resource.external_usage = PIPE_HANDLE_USAGE_READ_WRITE;
+
+ if (rscreen->apply_opaque_metadata)
+ rscreen->apply_opaque_metadata(rscreen, rtex, &metadata);
+
+ return &rtex->resource.b.b;
+}
+
void r600_init_screen_texture_functions(struct r600_common_screen *rscreen)
{
rscreen->b.resource_from_handle = r600_texture_from_handle;
rscreen->b.resource_get_handle = r600_texture_get_handle;
+ rscreen->b.resource_from_memobj = r600_texture_from_memobj;
+ rscreen->b.memobj_create_from_handle = r600_memobj_from_handle;
+ rscreen->b.memobj_destroy = r600_memobj_destroy;
}
void r600_init_context_texture_functions(struct r600_common_context *rctx)