Beispiel #1
0
static void vi_texture_alloc_dcc_separate(struct r600_common_screen *rscreen,
					      struct r600_texture *rtex)
{
	if (rscreen->debug_flags & DBG_NO_DCC)
		return;

	rtex->dcc_buffer = (struct r600_resource *)
		r600_aligned_buffer_create(&rscreen->b, PIPE_BIND_CUSTOM,
				   PIPE_USAGE_DEFAULT, rtex->surface.dcc_size, rtex->surface.dcc_alignment);
	if (rtex->dcc_buffer == NULL) {
		return;
	}

	r600_screen_clear_buffer(rscreen, &rtex->dcc_buffer->b.b, 0, rtex->surface.dcc_size,
				 0xFFFFFFFF, true);

	rtex->cb_color_info |= VI_S_028C70_DCC_ENABLE(1);
}
Beispiel #2
0
static void r600_texture_allocate_htile(struct r600_common_screen *rscreen,
					struct r600_texture *rtex)
{
	unsigned htile_size = r600_texture_get_htile_size(rscreen, rtex);

	if (!htile_size)
		return;

	rtex->htile_buffer = (struct r600_resource*)
			     pipe_buffer_create(&rscreen->b, PIPE_BIND_CUSTOM,
						PIPE_USAGE_DEFAULT, htile_size);
	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, htile_size, 0);
	}
}
Beispiel #3
0
struct pipe_screen *r600_screen_create(struct radeon_winsys *ws)
{
	struct r600_screen *rscreen = CALLOC_STRUCT(r600_screen);

	if (rscreen == NULL) {
		return NULL;
	}

	/* Set functions first. */
	rscreen->b.b.context_create = r600_create_context;
	rscreen->b.b.destroy = r600_destroy_screen;
	rscreen->b.b.get_param = r600_get_param;
	rscreen->b.b.get_shader_param = r600_get_shader_param;
	rscreen->b.b.resource_create = r600_resource_create;

	if (!r600_common_screen_init(&rscreen->b, ws)) {
		FREE(rscreen);
		return NULL;
	}

	if (rscreen->b.info.chip_class >= EVERGREEN) {
		rscreen->b.b.is_format_supported = evergreen_is_format_supported;
	} else {
		rscreen->b.b.is_format_supported = r600_is_format_supported;
	}

	rscreen->b.debug_flags |= debug_get_flags_option("R600_DEBUG", r600_debug_options, 0);
	if (debug_get_bool_option("R600_DEBUG_COMPUTE", FALSE))
		rscreen->b.debug_flags |= DBG_COMPUTE;
	if (debug_get_bool_option("R600_DUMP_SHADERS", FALSE))
		rscreen->b.debug_flags |= DBG_FS | DBG_VS | DBG_GS | DBG_PS | DBG_CS;
	if (debug_get_bool_option("R600_HYPERZ", FALSE))
		rscreen->b.debug_flags |= DBG_HYPERZ;
	if (debug_get_bool_option("R600_LLVM", FALSE))
		rscreen->b.debug_flags |= DBG_LLVM;

	if (rscreen->b.family == CHIP_UNKNOWN) {
		fprintf(stderr, "r600: Unknown chipset 0x%04X\n", rscreen->b.info.pci_id);
		FREE(rscreen);
		return NULL;
	}

	/* Figure out streamout kernel support. */
	switch (rscreen->b.chip_class) {
	case R600:
		if (rscreen->b.family < CHIP_RS780) {
			rscreen->b.has_streamout = rscreen->b.info.drm_minor >= 14;
		} else {
			rscreen->b.has_streamout = rscreen->b.info.drm_minor >= 23;
		}
		break;
	case R700:
		rscreen->b.has_streamout = rscreen->b.info.drm_minor >= 17;
		break;
	case EVERGREEN:
	case CAYMAN:
		rscreen->b.has_streamout = rscreen->b.info.drm_minor >= 14;
		break;
	default:
		rscreen->b.has_streamout = FALSE;
		break;
	}

	/* MSAA support. */
	switch (rscreen->b.chip_class) {
	case R600:
	case R700:
		rscreen->has_msaa = rscreen->b.info.drm_minor >= 22;
		rscreen->has_compressed_msaa_texturing = false;
		break;
	case EVERGREEN:
		rscreen->has_msaa = rscreen->b.info.drm_minor >= 19;
		rscreen->has_compressed_msaa_texturing = rscreen->b.info.drm_minor >= 24;
		break;
	case CAYMAN:
		rscreen->has_msaa = rscreen->b.info.drm_minor >= 19;
		rscreen->has_compressed_msaa_texturing = true;
		break;
	default:
		rscreen->has_msaa = FALSE;
		rscreen->has_compressed_msaa_texturing = false;
	}

	rscreen->b.has_cp_dma = rscreen->b.info.drm_minor >= 27 &&
			      !(rscreen->b.debug_flags & DBG_NO_CP_DMA);

	rscreen->global_pool = compute_memory_pool_new(rscreen);

	/* Create the auxiliary context. This must be done last. */
	rscreen->b.aux_context = rscreen->b.b.context_create(&rscreen->b.b, NULL);

#if 0 /* This is for testing whether aux_context and buffer clearing work correctly. */
	struct pipe_resource templ = {};

	templ.width0 = 4;
	templ.height0 = 2048;
	templ.depth0 = 1;
	templ.array_size = 1;
	templ.target = PIPE_TEXTURE_2D;
	templ.format = PIPE_FORMAT_R8G8B8A8_UNORM;
	templ.usage = PIPE_USAGE_DEFAULT;

	struct r600_resource *res = r600_resource(rscreen->screen.resource_create(&rscreen->screen, &templ));
	unsigned char *map = ws->buffer_map(res->cs_buf, NULL, PIPE_TRANSFER_WRITE);

	memset(map, 0, 256);

	r600_screen_clear_buffer(rscreen, &res->b.b, 4, 4, 0xCC);
	r600_screen_clear_buffer(rscreen, &res->b.b, 8, 4, 0xDD);
	r600_screen_clear_buffer(rscreen, &res->b.b, 12, 4, 0xEE);
	r600_screen_clear_buffer(rscreen, &res->b.b, 20, 4, 0xFF);
	r600_screen_clear_buffer(rscreen, &res->b.b, 32, 20, 0x87);

	ws->buffer_wait(res->buf, RADEON_USAGE_WRITE);

	int i;
	for (i = 0; i < 256; i++) {
		printf("%02X", map[i]);
		if (i % 16 == 15)
			printf("\n");
	}
#endif

	return &rscreen->b.b;
}
/* Common processing for r600_texture_create and r600_texture_from_handle */
static struct r600_texture *
r600_texture_create_object(struct pipe_screen *screen,
			   const struct pipe_resource *base,
			   unsigned pitch_in_bytes_override,
			   struct pb_buffer *buf,
			   struct radeon_surf *surface)
{
	struct r600_texture *rtex;
	struct r600_resource *resource;
	struct r600_common_screen *rscreen = (struct r600_common_screen*)screen;

	rtex = CALLOC_STRUCT(r600_texture);
	if (rtex == NULL)
		return NULL;

	resource = &rtex->resource;
	resource->b.b = *base;
	resource->b.vtbl = &r600_texture_vtbl;
	pipe_reference_init(&resource->b.b.reference, 1);
	resource->b.b.screen = screen;
	rtex->pitch_override = pitch_in_bytes_override;

	/* don't include stencil-only formats which we don't support for rendering */
	rtex->is_depth = util_format_has_depth(util_format_description(rtex->resource.b.b.format));

	rtex->surface = *surface;
	if (r600_setup_surface(screen, rtex, pitch_in_bytes_override)) {
		FREE(rtex);
		return NULL;
	}

	/* Tiled depth textures utilize the non-displayable tile order.
	 * This must be done after r600_setup_surface.
	 * Applies to R600-Cayman. */
	rtex->non_disp_tiling = rtex->is_depth && rtex->surface.level[0].mode >= RADEON_SURF_MODE_1D;

	if (rtex->is_depth) {
		if (!(base->flags & (R600_RESOURCE_FLAG_TRANSFER |
				     R600_RESOURCE_FLAG_FLUSHED_DEPTH)) &&
		    !(rscreen->debug_flags & DBG_NO_HYPERZ)) {

			r600_texture_allocate_htile(rscreen, rtex);
		}
	} else {
		if (base->nr_samples > 1) {
			if (!buf) {
				r600_texture_allocate_fmask(rscreen, rtex);
				r600_texture_allocate_cmask(rscreen, rtex);
				rtex->cmask_buffer = &rtex->resource;
			}
			if (!rtex->fmask.size || !rtex->cmask.size) {
				FREE(rtex);
				return NULL;
			}
		}
	}

	/* Now create the backing buffer. */
	if (!buf) {
		if (!r600_init_resource(rscreen, resource, rtex->size,
					rtex->surface.bo_alignment, TRUE)) {
			FREE(rtex);
			return NULL;
		}
	} else {
		resource->buf = buf;
		resource->cs_buf = rscreen->ws->buffer_get_cs_handle(buf);
		resource->gpu_address = rscreen->ws->buffer_get_virtual_address(resource->cs_buf);
		resource->domains = rscreen->ws->buffer_get_initial_domain(resource->cs_buf);
	}

	if (rtex->cmask.size) {
		/* Initialize the cmask to 0xCC (= compressed state). */
		r600_screen_clear_buffer(rscreen, &rtex->cmask_buffer->b.b,
					 rtex->cmask.offset, rtex->cmask.size,
					 0xCCCCCCCC, true);
	}

	/* Initialize the CMASK base register value. */
	rtex->cmask.base_address_reg =
		(rtex->resource.gpu_address + rtex->cmask.offset) >> 8;

	if (rscreen->debug_flags & DBG_VM) {
		fprintf(stderr, "VM start=0x%"PRIX64"  end=0x%"PRIX64" | Texture %ix%ix%i, %i levels, %i samples, %s\n",
			rtex->resource.gpu_address,
			rtex->resource.gpu_address + rtex->resource.buf->size,
			base->width0, base->height0, util_max_layer(base, 0)+1, base->last_level+1,
			base->nr_samples ? base->nr_samples : 1, util_format_short_name(base->format));
	}

	if (rscreen->debug_flags & DBG_TEX ||
	    (rtex->resource.b.b.last_level > 0 && rscreen->debug_flags & DBG_TEXMIP)) {
		printf("Texture: npix_x=%u, npix_y=%u, npix_z=%u, blk_w=%u, "
		       "blk_h=%u, blk_d=%u, array_size=%u, last_level=%u, "
		       "bpe=%u, nsamples=%u, flags=0x%x, %s\n",
		       rtex->surface.npix_x, rtex->surface.npix_y,
		       rtex->surface.npix_z, rtex->surface.blk_w,
		       rtex->surface.blk_h, rtex->surface.blk_d,
		       rtex->surface.array_size, rtex->surface.last_level,
		       rtex->surface.bpe, rtex->surface.nsamples,
		       rtex->surface.flags, util_format_short_name(base->format));
		for (int i = 0; i <= rtex->surface.last_level; i++) {
			printf("  L %i: offset=%"PRIu64", slice_size=%"PRIu64", npix_x=%u, "
			       "npix_y=%u, npix_z=%u, nblk_x=%u, nblk_y=%u, "
			       "nblk_z=%u, pitch_bytes=%u, mode=%u\n",
			       i, rtex->surface.level[i].offset,
			       rtex->surface.level[i].slice_size,
			       u_minify(rtex->resource.b.b.width0, i),
			       u_minify(rtex->resource.b.b.height0, i),
			       u_minify(rtex->resource.b.b.depth0, i),
			       rtex->surface.level[i].nblk_x,
			       rtex->surface.level[i].nblk_y,
			       rtex->surface.level[i].nblk_z,
			       rtex->surface.level[i].pitch_bytes,
			       rtex->surface.level[i].mode);
		}
		if (rtex->surface.flags & RADEON_SURF_SBUFFER) {
			for (int i = 0; i <= rtex->surface.last_level; i++) {
				printf("  S %i: offset=%"PRIu64", slice_size=%"PRIu64", npix_x=%u, "
				       "npix_y=%u, npix_z=%u, nblk_x=%u, nblk_y=%u, "
				       "nblk_z=%u, pitch_bytes=%u, mode=%u\n",
				       i, rtex->surface.stencil_level[i].offset,
				       rtex->surface.stencil_level[i].slice_size,
				       u_minify(rtex->resource.b.b.width0, i),
				       u_minify(rtex->resource.b.b.height0, i),
				       u_minify(rtex->resource.b.b.depth0, i),
				       rtex->surface.stencil_level[i].nblk_x,
				       rtex->surface.stencil_level[i].nblk_y,
				       rtex->surface.stencil_level[i].nblk_z,
				       rtex->surface.stencil_level[i].pitch_bytes,
				       rtex->surface.stencil_level[i].mode);
			}
		}
	}
	return rtex;
}
Beispiel #5
0
/* Common processing for r600_texture_create and r600_texture_from_handle */
static struct r600_texture *
r600_texture_create_object(struct pipe_screen *screen,
			   const struct pipe_resource *base,
			   unsigned pitch_in_bytes_override,
			   struct pb_buffer *buf,
			   struct radeon_surf *surface)
{
	struct r600_texture *rtex;
	struct r600_resource *resource;
	struct r600_common_screen *rscreen = (struct r600_common_screen*)screen;

	rtex = CALLOC_STRUCT(r600_texture);
	if (!rtex)
		return NULL;

	resource = &rtex->resource;
	resource->b.b = *base;
	resource->b.vtbl = &r600_texture_vtbl;
	pipe_reference_init(&resource->b.b.reference, 1);
	resource->b.b.screen = screen;

	/* don't include stencil-only formats which we don't support for rendering */
	rtex->is_depth = util_format_has_depth(util_format_description(rtex->resource.b.b.format));

	rtex->surface = *surface;
	if (r600_setup_surface(screen, rtex, pitch_in_bytes_override)) {
		FREE(rtex);
		return NULL;
	}

	/* Tiled depth textures utilize the non-displayable tile order.
	 * This must be done after r600_setup_surface.
	 * Applies to R600-Cayman. */
	rtex->non_disp_tiling = rtex->is_depth && rtex->surface.level[0].mode >= RADEON_SURF_MODE_1D;

	if (rtex->is_depth) {
		if (!(base->flags & (R600_RESOURCE_FLAG_TRANSFER |
				     R600_RESOURCE_FLAG_FLUSHED_DEPTH)) &&
		    !(rscreen->debug_flags & DBG_NO_HYPERZ)) {

			r600_texture_allocate_htile(rscreen, rtex);
		}
	} else {
		if (base->nr_samples > 1) {
			if (!buf) {
				r600_texture_allocate_fmask(rscreen, rtex);
				r600_texture_allocate_cmask(rscreen, rtex);
				rtex->cmask_buffer = &rtex->resource;
			}
			if (!rtex->fmask.size || !rtex->cmask.size) {
				FREE(rtex);
				return NULL;
			}
		}
		if (rtex->surface.dcc_size)
			vi_texture_alloc_dcc_separate(rscreen, rtex);
	}

	/* Now create the backing buffer. */
	if (!buf) {
		if (!r600_init_resource(rscreen, resource, rtex->size,
					rtex->surface.bo_alignment, TRUE)) {
			FREE(rtex);
			return NULL;
		}
	} else {
		resource->buf = buf;
		resource->gpu_address = rscreen->ws->buffer_get_virtual_address(resource->buf);
		resource->domains = rscreen->ws->buffer_get_initial_domain(resource->buf);
	}

	if (rtex->cmask.size) {
		/* Initialize the cmask to 0xCC (= compressed state). */
		r600_screen_clear_buffer(rscreen, &rtex->cmask_buffer->b.b,
					 rtex->cmask.offset, rtex->cmask.size,
					 0xCCCCCCCC, true);
	}

	/* Initialize the CMASK base register value. */
	rtex->cmask.base_address_reg =
		(rtex->resource.gpu_address + rtex->cmask.offset) >> 8;

	if (rscreen->debug_flags & DBG_VM) {
		fprintf(stderr, "VM start=0x%"PRIX64"  end=0x%"PRIX64" | Texture %ix%ix%i, %i levels, %i samples, %s\n",
			rtex->resource.gpu_address,
			rtex->resource.gpu_address + rtex->resource.buf->size,
			base->width0, base->height0, util_max_layer(base, 0)+1, base->last_level+1,
			base->nr_samples ? base->nr_samples : 1, util_format_short_name(base->format));
	}

	if (rscreen->debug_flags & DBG_TEX) {
		puts("Texture:");
		r600_print_texture_info(rtex, stdout);
	}

	return rtex;
}