2017-11-23 23:15:14 -08:00
|
|
|
/*
|
|
|
|
|
* Copyright © 2017 Intel Corporation
|
|
|
|
|
*
|
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
|
|
|
* to deal in the Software without restriction, including without limitation
|
2018-08-19 00:31:46 -07:00
|
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
|
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
|
|
|
* Software is furnished to do so, subject to the following conditions:
|
2017-11-23 23:15:14 -08:00
|
|
|
*
|
2018-08-19 00:31:46 -07:00
|
|
|
* The above copyright notice and this permission notice shall be included
|
|
|
|
|
* in all copies or substantial portions of the Software.
|
2017-11-23 23:15:14 -08:00
|
|
|
*
|
2018-08-19 00:31:46 -07:00
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
|
|
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
|
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
|
|
|
* DEALINGS IN THE SOFTWARE.
|
2017-11-23 23:15:14 -08:00
|
|
|
*/
|
2018-07-30 23:49:34 -07:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @file iris_resource.c
|
|
|
|
|
*
|
|
|
|
|
* Resources are images, buffers, and other objects used by the GPU.
|
|
|
|
|
*
|
|
|
|
|
* XXX: explain resources
|
|
|
|
|
*/
|
|
|
|
|
|
2017-11-23 23:15:14 -08:00
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
#include "pipe/p_defines.h"
|
|
|
|
|
#include "pipe/p_state.h"
|
|
|
|
|
#include "pipe/p_context.h"
|
|
|
|
|
#include "pipe/p_screen.h"
|
2018-05-28 17:14:43 -07:00
|
|
|
#include "util/os_memory.h"
|
|
|
|
|
#include "util/u_cpu_detect.h"
|
2017-11-23 23:15:14 -08:00
|
|
|
#include "util/u_inlines.h"
|
2019-06-27 15:05:31 -07:00
|
|
|
#include "util/format/u_format.h"
|
2019-03-12 14:51:22 -07:00
|
|
|
#include "util/u_threaded_context.h"
|
2018-06-07 01:25:35 -07:00
|
|
|
#include "util/u_transfer.h"
|
2018-08-08 14:54:09 -07:00
|
|
|
#include "util/u_transfer_helper.h"
|
2017-11-23 23:15:14 -08:00
|
|
|
#include "util/u_upload_mgr.h"
|
|
|
|
|
#include "util/ralloc.h"
|
2018-01-19 18:57:30 -08:00
|
|
|
#include "iris_batch.h"
|
|
|
|
|
#include "iris_context.h"
|
2017-11-23 23:15:14 -08:00
|
|
|
#include "iris_resource.h"
|
|
|
|
|
#include "iris_screen.h"
|
2018-04-28 01:58:54 -07:00
|
|
|
#include "intel/common/gen_aux_map.h"
|
2019-04-05 15:39:51 -07:00
|
|
|
#include "intel/dev/gen_debug.h"
|
2018-05-28 17:14:43 -07:00
|
|
|
#include "isl/isl.h"
|
2017-11-23 23:15:14 -08:00
|
|
|
#include "drm-uapi/drm_fourcc.h"
|
|
|
|
|
#include "drm-uapi/i915_drm.h"
|
|
|
|
|
|
|
|
|
|
enum modifier_priority {
|
|
|
|
|
MODIFIER_PRIORITY_INVALID = 0,
|
|
|
|
|
MODIFIER_PRIORITY_LINEAR,
|
|
|
|
|
MODIFIER_PRIORITY_X,
|
|
|
|
|
MODIFIER_PRIORITY_Y,
|
|
|
|
|
MODIFIER_PRIORITY_Y_CCS,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const uint64_t priority_to_modifier[] = {
|
|
|
|
|
[MODIFIER_PRIORITY_INVALID] = DRM_FORMAT_MOD_INVALID,
|
|
|
|
|
[MODIFIER_PRIORITY_LINEAR] = DRM_FORMAT_MOD_LINEAR,
|
|
|
|
|
[MODIFIER_PRIORITY_X] = I915_FORMAT_MOD_X_TILED,
|
|
|
|
|
[MODIFIER_PRIORITY_Y] = I915_FORMAT_MOD_Y_TILED,
|
|
|
|
|
[MODIFIER_PRIORITY_Y_CCS] = I915_FORMAT_MOD_Y_TILED_CCS,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
modifier_is_supported(const struct gen_device_info *devinfo,
|
2019-03-26 00:25:31 -07:00
|
|
|
enum pipe_format pfmt, uint64_t modifier)
|
2017-11-23 23:15:14 -08:00
|
|
|
{
|
|
|
|
|
/* XXX: do something real */
|
|
|
|
|
switch (modifier) {
|
2019-03-26 00:25:31 -07:00
|
|
|
case I915_FORMAT_MOD_Y_TILED_CCS: {
|
|
|
|
|
if (unlikely(INTEL_DEBUG & DEBUG_NO_RBC))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
enum isl_format rt_format =
|
|
|
|
|
iris_format_for_usage(devinfo, pfmt,
|
|
|
|
|
ISL_SURF_USAGE_RENDER_TARGET_BIT).fmt;
|
|
|
|
|
|
2020-06-09 11:10:44 -07:00
|
|
|
if (rt_format == ISL_FORMAT_UNSUPPORTED ||
|
|
|
|
|
!isl_format_supports_ccs_e(devinfo, rt_format))
|
2019-03-26 00:25:31 -07:00
|
|
|
return false;
|
|
|
|
|
|
2019-09-23 11:09:46 -07:00
|
|
|
return devinfo->gen >= 9 && devinfo->gen <= 11;
|
2019-03-26 00:25:31 -07:00
|
|
|
}
|
2017-11-23 23:15:14 -08:00
|
|
|
case I915_FORMAT_MOD_Y_TILED:
|
|
|
|
|
case I915_FORMAT_MOD_X_TILED:
|
|
|
|
|
case DRM_FORMAT_MOD_LINEAR:
|
|
|
|
|
return true;
|
|
|
|
|
case DRM_FORMAT_MOD_INVALID:
|
|
|
|
|
default:
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static uint64_t
|
2019-03-26 00:25:31 -07:00
|
|
|
select_best_modifier(struct gen_device_info *devinfo, enum pipe_format pfmt,
|
2017-11-23 23:15:14 -08:00
|
|
|
const uint64_t *modifiers,
|
|
|
|
|
int count)
|
|
|
|
|
{
|
|
|
|
|
enum modifier_priority prio = MODIFIER_PRIORITY_INVALID;
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < count; i++) {
|
2019-03-26 00:25:31 -07:00
|
|
|
if (!modifier_is_supported(devinfo, pfmt, modifiers[i]))
|
2017-11-23 23:15:14 -08:00
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
switch (modifiers[i]) {
|
|
|
|
|
case I915_FORMAT_MOD_Y_TILED_CCS:
|
|
|
|
|
prio = MAX2(prio, MODIFIER_PRIORITY_Y_CCS);
|
|
|
|
|
break;
|
|
|
|
|
case I915_FORMAT_MOD_Y_TILED:
|
|
|
|
|
prio = MAX2(prio, MODIFIER_PRIORITY_Y);
|
|
|
|
|
break;
|
|
|
|
|
case I915_FORMAT_MOD_X_TILED:
|
|
|
|
|
prio = MAX2(prio, MODIFIER_PRIORITY_X);
|
|
|
|
|
break;
|
|
|
|
|
case DRM_FORMAT_MOD_LINEAR:
|
|
|
|
|
prio = MAX2(prio, MODIFIER_PRIORITY_LINEAR);
|
|
|
|
|
break;
|
|
|
|
|
case DRM_FORMAT_MOD_INVALID:
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return priority_to_modifier[prio];
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-16 11:08:28 -07:00
|
|
|
enum isl_surf_dim
|
2017-11-23 23:15:14 -08:00
|
|
|
target_to_isl_surf_dim(enum pipe_texture_target target)
|
|
|
|
|
{
|
|
|
|
|
switch (target) {
|
|
|
|
|
case PIPE_BUFFER:
|
|
|
|
|
case PIPE_TEXTURE_1D:
|
|
|
|
|
case PIPE_TEXTURE_1D_ARRAY:
|
|
|
|
|
return ISL_SURF_DIM_1D;
|
|
|
|
|
case PIPE_TEXTURE_2D:
|
|
|
|
|
case PIPE_TEXTURE_CUBE:
|
|
|
|
|
case PIPE_TEXTURE_RECT:
|
|
|
|
|
case PIPE_TEXTURE_2D_ARRAY:
|
|
|
|
|
case PIPE_TEXTURE_CUBE_ARRAY:
|
|
|
|
|
return ISL_SURF_DIM_2D;
|
|
|
|
|
case PIPE_TEXTURE_3D:
|
|
|
|
|
return ISL_SURF_DIM_3D;
|
|
|
|
|
case PIPE_MAX_TEXTURE_TYPES:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
unreachable("invalid texture type");
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-26 00:25:31 -07:00
|
|
|
static void
|
|
|
|
|
iris_query_dmabuf_modifiers(struct pipe_screen *pscreen,
|
|
|
|
|
enum pipe_format pfmt,
|
|
|
|
|
int max,
|
|
|
|
|
uint64_t *modifiers,
|
|
|
|
|
unsigned int *external_only,
|
|
|
|
|
int *count)
|
|
|
|
|
{
|
|
|
|
|
struct iris_screen *screen = (void *) pscreen;
|
|
|
|
|
const struct gen_device_info *devinfo = &screen->devinfo;
|
|
|
|
|
|
|
|
|
|
uint64_t all_modifiers[] = {
|
|
|
|
|
DRM_FORMAT_MOD_LINEAR,
|
|
|
|
|
I915_FORMAT_MOD_X_TILED,
|
|
|
|
|
I915_FORMAT_MOD_Y_TILED,
|
2019-06-24 19:24:37 -07:00
|
|
|
I915_FORMAT_MOD_Y_TILED_CCS,
|
2019-03-26 00:25:31 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
int supported_mods = 0;
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < ARRAY_SIZE(all_modifiers); i++) {
|
2019-03-26 00:25:31 -07:00
|
|
|
if (!modifier_is_supported(devinfo, pfmt, all_modifiers[i]))
|
2019-03-26 00:25:31 -07:00
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (supported_mods < max) {
|
|
|
|
|
if (modifiers)
|
|
|
|
|
modifiers[supported_mods] = all_modifiers[i];
|
|
|
|
|
|
|
|
|
|
if (external_only)
|
|
|
|
|
external_only[supported_mods] = util_format_is_yuv(pfmt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
supported_mods++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*count = supported_mods;
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-23 23:15:14 -08:00
|
|
|
static isl_surf_usage_flags_t
|
|
|
|
|
pipe_bind_to_isl_usage(unsigned bindings)
|
|
|
|
|
{
|
|
|
|
|
isl_surf_usage_flags_t usage = 0;
|
|
|
|
|
|
|
|
|
|
if (bindings & PIPE_BIND_RENDER_TARGET)
|
|
|
|
|
usage |= ISL_SURF_USAGE_RENDER_TARGET_BIT;
|
|
|
|
|
|
2018-04-25 15:25:33 -07:00
|
|
|
if (bindings & PIPE_BIND_SAMPLER_VIEW)
|
|
|
|
|
usage |= ISL_SURF_USAGE_TEXTURE_BIT;
|
|
|
|
|
|
|
|
|
|
if (bindings & (PIPE_BIND_SHADER_IMAGE | PIPE_BIND_SHADER_BUFFER))
|
2017-11-23 23:15:14 -08:00
|
|
|
usage |= ISL_SURF_USAGE_STORAGE_BIT;
|
|
|
|
|
|
|
|
|
|
if (bindings & PIPE_BIND_DISPLAY_TARGET)
|
|
|
|
|
usage |= ISL_SURF_USAGE_DISPLAY_BIT;
|
|
|
|
|
|
|
|
|
|
return usage;
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-12 08:16:28 +02:00
|
|
|
enum isl_format
|
|
|
|
|
iris_image_view_get_format(struct iris_context *ice,
|
|
|
|
|
const struct pipe_image_view *img)
|
|
|
|
|
{
|
|
|
|
|
struct iris_screen *screen = (struct iris_screen *)ice->ctx.screen;
|
|
|
|
|
const struct gen_device_info *devinfo = &screen->devinfo;
|
|
|
|
|
|
|
|
|
|
isl_surf_usage_flags_t usage = ISL_SURF_USAGE_STORAGE_BIT;
|
|
|
|
|
enum isl_format isl_fmt =
|
|
|
|
|
iris_format_for_usage(devinfo, img->format, usage).fmt;
|
|
|
|
|
|
|
|
|
|
if (img->shader_access & PIPE_IMAGE_ACCESS_READ) {
|
|
|
|
|
/* On Gen8, try to use typed surfaces reads (which support a
|
|
|
|
|
* limited number of formats), and if not possible, fall back
|
|
|
|
|
* to untyped reads.
|
|
|
|
|
*/
|
|
|
|
|
if (devinfo->gen == 8 &&
|
|
|
|
|
!isl_has_matching_typed_storage_image_format(devinfo, isl_fmt))
|
|
|
|
|
return ISL_FORMAT_RAW;
|
|
|
|
|
else
|
|
|
|
|
return isl_lower_storage_image_format(devinfo, isl_fmt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return isl_fmt;
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-30 15:08:02 -07:00
|
|
|
struct pipe_resource *
|
|
|
|
|
iris_resource_get_separate_stencil(struct pipe_resource *p_res)
|
|
|
|
|
{
|
|
|
|
|
/* For packed depth-stencil, we treat depth as the primary resource
|
|
|
|
|
* and store S8 as the "second plane" resource.
|
|
|
|
|
*/
|
2019-05-13 15:19:03 +03:00
|
|
|
if (p_res->next && p_res->next->format == PIPE_FORMAT_S8_UINT)
|
|
|
|
|
return p_res->next;
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
|
2018-07-30 15:08:02 -07:00
|
|
|
}
|
|
|
|
|
|
2018-08-08 14:54:09 -07:00
|
|
|
static void
|
|
|
|
|
iris_resource_set_separate_stencil(struct pipe_resource *p_res,
|
|
|
|
|
struct pipe_resource *stencil)
|
|
|
|
|
{
|
|
|
|
|
assert(util_format_has_depth(util_format_description(p_res->format)));
|
2018-08-09 09:19:58 -07:00
|
|
|
pipe_resource_reference(&p_res->next, stencil);
|
2018-08-08 14:54:09 -07:00
|
|
|
}
|
|
|
|
|
|
2018-08-03 16:18:09 -07:00
|
|
|
void
|
|
|
|
|
iris_get_depth_stencil_resources(struct pipe_resource *res,
|
|
|
|
|
struct iris_resource **out_z,
|
|
|
|
|
struct iris_resource **out_s)
|
|
|
|
|
{
|
|
|
|
|
if (!res) {
|
|
|
|
|
*out_z = NULL;
|
|
|
|
|
*out_s = NULL;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-13 22:12:01 -08:00
|
|
|
if (res->format != PIPE_FORMAT_S8_UINT) {
|
2018-08-03 16:18:09 -07:00
|
|
|
*out_z = (void *) res;
|
|
|
|
|
*out_s = (void *) iris_resource_get_separate_stencil(res);
|
|
|
|
|
} else {
|
|
|
|
|
*out_z = NULL;
|
|
|
|
|
*out_s = (void *) res;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-16 10:38:00 -07:00
|
|
|
enum isl_dim_layout
|
|
|
|
|
iris_get_isl_dim_layout(const struct gen_device_info *devinfo,
|
|
|
|
|
enum isl_tiling tiling,
|
|
|
|
|
enum pipe_texture_target target)
|
|
|
|
|
{
|
|
|
|
|
switch (target) {
|
|
|
|
|
case PIPE_TEXTURE_1D:
|
|
|
|
|
case PIPE_TEXTURE_1D_ARRAY:
|
|
|
|
|
return (devinfo->gen >= 9 && tiling == ISL_TILING_LINEAR ?
|
|
|
|
|
ISL_DIM_LAYOUT_GEN9_1D : ISL_DIM_LAYOUT_GEN4_2D);
|
|
|
|
|
|
|
|
|
|
case PIPE_TEXTURE_2D:
|
|
|
|
|
case PIPE_TEXTURE_2D_ARRAY:
|
|
|
|
|
case PIPE_TEXTURE_RECT:
|
|
|
|
|
case PIPE_TEXTURE_CUBE:
|
|
|
|
|
case PIPE_TEXTURE_CUBE_ARRAY:
|
|
|
|
|
return ISL_DIM_LAYOUT_GEN4_2D;
|
|
|
|
|
|
|
|
|
|
case PIPE_TEXTURE_3D:
|
|
|
|
|
return (devinfo->gen >= 9 ?
|
|
|
|
|
ISL_DIM_LAYOUT_GEN4_2D : ISL_DIM_LAYOUT_GEN4_3D);
|
|
|
|
|
|
|
|
|
|
case PIPE_MAX_TEXTURE_TYPES:
|
|
|
|
|
case PIPE_BUFFER:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
unreachable("invalid texture type");
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-07 11:54:16 -08:00
|
|
|
void
|
2018-12-07 10:46:04 -08:00
|
|
|
iris_resource_disable_aux(struct iris_resource *res)
|
|
|
|
|
{
|
|
|
|
|
iris_bo_unreference(res->aux.bo);
|
2019-02-15 14:45:05 -08:00
|
|
|
iris_bo_unreference(res->aux.clear_color_bo);
|
2018-12-07 10:46:04 -08:00
|
|
|
free(res->aux.state);
|
|
|
|
|
|
|
|
|
|
res->aux.usage = ISL_AUX_USAGE_NONE;
|
2018-12-09 23:12:33 -08:00
|
|
|
res->aux.possible_usages = 1 << ISL_AUX_USAGE_NONE;
|
2019-03-27 14:42:12 -07:00
|
|
|
res->aux.sampler_usages = 1 << ISL_AUX_USAGE_NONE;
|
2019-08-30 14:58:54 -07:00
|
|
|
res->aux.has_hiz = 0;
|
2018-12-07 10:46:04 -08:00
|
|
|
res->aux.surf.size_B = 0;
|
|
|
|
|
res->aux.bo = NULL;
|
2019-08-07 16:02:51 -07:00
|
|
|
res->aux.extra_aux.surf.size_B = 0;
|
2019-02-15 14:45:05 -08:00
|
|
|
res->aux.clear_color_bo = NULL;
|
2018-12-07 10:46:04 -08:00
|
|
|
res->aux.state = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-23 23:15:14 -08:00
|
|
|
static void
|
|
|
|
|
iris_resource_destroy(struct pipe_screen *screen,
|
|
|
|
|
struct pipe_resource *resource)
|
|
|
|
|
{
|
|
|
|
|
struct iris_resource *res = (struct iris_resource *)resource;
|
|
|
|
|
|
2019-04-05 11:54:10 -07:00
|
|
|
if (resource->target == PIPE_BUFFER)
|
|
|
|
|
util_range_destroy(&res->valid_buffer_range);
|
|
|
|
|
|
2018-12-07 10:46:04 -08:00
|
|
|
iris_resource_disable_aux(res);
|
|
|
|
|
|
2017-11-23 23:15:14 -08:00
|
|
|
iris_bo_unreference(res->bo);
|
2020-03-06 15:58:37 +02:00
|
|
|
iris_pscreen_unref(res->base.screen);
|
|
|
|
|
|
2018-06-16 09:56:59 -07:00
|
|
|
free(res);
|
2017-11-23 23:15:14 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static struct iris_resource *
|
|
|
|
|
iris_alloc_resource(struct pipe_screen *pscreen,
|
|
|
|
|
const struct pipe_resource *templ)
|
|
|
|
|
{
|
|
|
|
|
struct iris_resource *res = calloc(1, sizeof(struct iris_resource));
|
|
|
|
|
if (!res)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
res->base = *templ;
|
2020-03-06 15:58:37 +02:00
|
|
|
res->base.screen = iris_pscreen_ref(pscreen);
|
2017-11-23 23:15:14 -08:00
|
|
|
pipe_reference_init(&res->base.reference, 1);
|
|
|
|
|
|
2018-12-07 11:02:50 -08:00
|
|
|
res->aux.possible_usages = 1 << ISL_AUX_USAGE_NONE;
|
2019-03-27 14:42:12 -07:00
|
|
|
res->aux.sampler_usages = 1 << ISL_AUX_USAGE_NONE;
|
2018-12-07 11:02:50 -08:00
|
|
|
|
2019-04-05 11:54:10 -07:00
|
|
|
if (templ->target == PIPE_BUFFER)
|
|
|
|
|
util_range_init(&res->valid_buffer_range);
|
|
|
|
|
|
2017-11-23 23:15:14 -08:00
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-07 11:54:02 -08:00
|
|
|
unsigned
|
|
|
|
|
iris_get_num_logical_layers(const struct iris_resource *res, unsigned level)
|
|
|
|
|
{
|
|
|
|
|
if (res->surf.dim == ISL_SURF_DIM_3D)
|
|
|
|
|
return minify(res->surf.logical_level0_px.depth, level);
|
|
|
|
|
else
|
|
|
|
|
return res->surf.logical_level0_px.array_len;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static enum isl_aux_state **
|
|
|
|
|
create_aux_state_map(struct iris_resource *res, enum isl_aux_state initial)
|
|
|
|
|
{
|
2019-10-24 09:14:07 -07:00
|
|
|
assert(res->aux.state == NULL);
|
|
|
|
|
|
2018-12-07 11:54:02 -08:00
|
|
|
uint32_t total_slices = 0;
|
|
|
|
|
for (uint32_t level = 0; level < res->surf.levels; level++)
|
|
|
|
|
total_slices += iris_get_num_logical_layers(res, level);
|
|
|
|
|
|
|
|
|
|
const size_t per_level_array_size =
|
|
|
|
|
res->surf.levels * sizeof(enum isl_aux_state *);
|
|
|
|
|
|
|
|
|
|
/* We're going to allocate a single chunk of data for both the per-level
|
|
|
|
|
* reference array and the arrays of aux_state. This makes cleanup
|
|
|
|
|
* significantly easier.
|
|
|
|
|
*/
|
|
|
|
|
const size_t total_size =
|
|
|
|
|
per_level_array_size + total_slices * sizeof(enum isl_aux_state);
|
|
|
|
|
|
|
|
|
|
void *data = malloc(total_size);
|
|
|
|
|
if (!data)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
enum isl_aux_state **per_level_arr = data;
|
|
|
|
|
enum isl_aux_state *s = data + per_level_array_size;
|
|
|
|
|
for (uint32_t level = 0; level < res->surf.levels; level++) {
|
|
|
|
|
per_level_arr[level] = s;
|
|
|
|
|
const unsigned level_layers = iris_get_num_logical_layers(res, level);
|
|
|
|
|
for (uint32_t a = 0; a < level_layers; a++)
|
|
|
|
|
*(s++) = initial;
|
|
|
|
|
}
|
|
|
|
|
assert((void *)s == data + total_size);
|
|
|
|
|
|
|
|
|
|
return per_level_arr;
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-23 00:53:23 -07:00
|
|
|
static unsigned
|
|
|
|
|
iris_get_aux_clear_color_state_size(struct iris_screen *screen)
|
|
|
|
|
{
|
|
|
|
|
const struct gen_device_info *devinfo = &screen->devinfo;
|
iris: Update fast clear colors on Gen9 with direct immediate writes.
Gen11 stores the fast clear color in an "indirect clear buffer", as
a packed pixel value. Gen9 hardware stores it as a float or integer
value, which is interpreted via the format. We were trying to store
that in a buffer, for similarity with Icelake, and MI_COPY_MEM_MEM
it from there to the actual SURFACE_STATE bytes where it's stored.
This unfortunately doesn't work for blorp_copy(), which does bit-for-bit
copies, and overrides the format to a CCS-compatible UINT format. This
causes the clear color to be interpreted in the overridden format.
Normally, we provide the clear color on the CPU, and blorp_blit.c:2611
converts it to a packed pixel value in the original format, then unpacks
it in the overridden format, so the clear color we use expands to the
bits we originally desired.
However, BLORP doesn't support this pack/unpack with an indirect clear
buffer, as it would need to do the math on the GPU. On Gen11+, it isn't
necessary, as the hardware does the right thing.
This patch changes Gen9 to stop using an indirect clear buffer and
simply do PIPE_CONTROLs with post-sync write immediate operations
to store the new color over the surface states for regular drawing.
BLORP continues streaming out surface states, and handles fast clear
colors on the CPU.
Fixes: 53c484ba8ac ("iris: blorp using resolve hooks")
Reviewed-by: Rafael Antognolli <rafael.antognolli@intel.com>
2019-08-19 13:57:46 -07:00
|
|
|
return devinfo->gen >= 10 ? screen->isl_dev.ss.clear_color_state_size : 0;
|
2019-06-23 00:53:23 -07:00
|
|
|
}
|
|
|
|
|
|
2018-04-28 01:58:54 -07:00
|
|
|
static void
|
|
|
|
|
map_aux_addresses(struct iris_screen *screen, struct iris_resource *res)
|
|
|
|
|
{
|
|
|
|
|
const struct gen_device_info *devinfo = &screen->devinfo;
|
|
|
|
|
if (devinfo->gen >= 12 && isl_aux_usage_has_ccs(res->aux.usage)) {
|
|
|
|
|
void *aux_map_ctx = iris_bufmgr_get_aux_map_context(screen->bufmgr);
|
|
|
|
|
assert(aux_map_ctx);
|
2019-10-25 12:05:58 -07:00
|
|
|
const unsigned aux_offset = res->aux.extra_aux.surf.size_B > 0 ?
|
2019-08-07 16:02:51 -07:00
|
|
|
res->aux.extra_aux.offset : res->aux.offset;
|
2018-04-28 01:58:54 -07:00
|
|
|
gen_aux_map_add_image(aux_map_ctx, &res->surf, res->bo->gtt_offset,
|
2019-10-25 12:05:58 -07:00
|
|
|
res->aux.bo->gtt_offset + aux_offset);
|
|
|
|
|
res->bo->aux_map_address = res->aux.bo->gtt_offset;
|
2018-04-28 01:58:54 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-01 16:49:57 -07:00
|
|
|
static bool
|
|
|
|
|
want_ccs_e_for_format(const struct gen_device_info *devinfo,
|
|
|
|
|
enum isl_format format)
|
|
|
|
|
{
|
|
|
|
|
if (!isl_format_supports_ccs_e(devinfo, format))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
const struct isl_format_layout *fmtl = isl_format_get_layout(format);
|
|
|
|
|
|
|
|
|
|
/* CCS_E seems to significantly hurt performance with 32-bit floating
|
|
|
|
|
* point formats. For example, Paraview's "Wavelet Volume" case uses
|
|
|
|
|
* both R32_FLOAT and R32G32B32A32_FLOAT, and enabling CCS_E for those
|
|
|
|
|
* formats causes a 62% FPS drop.
|
|
|
|
|
*
|
|
|
|
|
* However, many benchmarks seem to use 16-bit float with no issues.
|
|
|
|
|
*/
|
|
|
|
|
if (fmtl->channels.r.bits == 32 && fmtl->channels.r.type == ISL_SFLOAT)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-07 11:54:02 -08:00
|
|
|
/**
|
2019-06-23 00:53:23 -07:00
|
|
|
* Configure aux for the resource, but don't allocate it. For images which
|
|
|
|
|
* might be shared with modifiers, we must allocate the image and aux data in
|
|
|
|
|
* a single bo.
|
2019-10-25 15:38:18 -07:00
|
|
|
*
|
|
|
|
|
* Returns false on unexpected error (e.g. allocation failed, or invalid
|
|
|
|
|
* configuration result).
|
2018-12-07 11:54:02 -08:00
|
|
|
*/
|
|
|
|
|
static bool
|
2019-06-23 00:53:23 -07:00
|
|
|
iris_resource_configure_aux(struct iris_screen *screen,
|
2019-07-09 00:47:15 -07:00
|
|
|
struct iris_resource *res, bool imported,
|
|
|
|
|
uint64_t *aux_size_B,
|
2019-06-23 00:53:23 -07:00
|
|
|
uint32_t *alloc_flags)
|
2018-12-07 11:54:02 -08:00
|
|
|
{
|
2019-08-01 16:49:57 -07:00
|
|
|
const struct gen_device_info *devinfo = &screen->devinfo;
|
|
|
|
|
|
|
|
|
|
/* Try to create the auxiliary surfaces allowed by the modifier or by
|
|
|
|
|
* the user if no modifier is specified.
|
|
|
|
|
*/
|
2020-06-04 16:42:20 -07:00
|
|
|
assert(!res->mod_info ||
|
|
|
|
|
res->mod_info->aux_usage == ISL_AUX_USAGE_NONE ||
|
|
|
|
|
res->mod_info->aux_usage == ISL_AUX_USAGE_CCS_E ||
|
|
|
|
|
res->mod_info->aux_usage == ISL_AUX_USAGE_GEN12_CCS_E);
|
2019-08-01 16:49:57 -07:00
|
|
|
|
|
|
|
|
const bool has_mcs = !res->mod_info &&
|
|
|
|
|
isl_surf_get_mcs_surf(&screen->isl_dev, &res->surf, &res->aux.surf);
|
|
|
|
|
|
|
|
|
|
const bool has_hiz = !res->mod_info && !(INTEL_DEBUG & DEBUG_NO_HIZ) &&
|
|
|
|
|
isl_surf_get_hiz_surf(&screen->isl_dev, &res->surf, &res->aux.surf);
|
2018-12-07 11:54:02 -08:00
|
|
|
|
2019-08-01 16:49:57 -07:00
|
|
|
const bool has_ccs =
|
|
|
|
|
((!res->mod_info && !(INTEL_DEBUG & DEBUG_NO_RBC)) ||
|
|
|
|
|
(res->mod_info && res->mod_info->aux_usage != ISL_AUX_USAGE_NONE)) &&
|
|
|
|
|
isl_surf_get_ccs_surf(&screen->isl_dev, &res->surf, &res->aux.surf,
|
2019-08-07 16:02:51 -07:00
|
|
|
&res->aux.extra_aux.surf, 0);
|
|
|
|
|
|
|
|
|
|
/* Having both HIZ and MCS is impossible. */
|
|
|
|
|
assert(!has_mcs || !has_hiz);
|
|
|
|
|
|
|
|
|
|
/* Ensure aux surface creation for MCS_CCS and HIZ_CCS is correct. */
|
|
|
|
|
if (has_ccs && (has_mcs || has_hiz)) {
|
|
|
|
|
assert(res->aux.extra_aux.surf.size_B > 0 &&
|
|
|
|
|
res->aux.extra_aux.surf.usage & ISL_SURF_USAGE_CCS_BIT);
|
|
|
|
|
assert(res->aux.surf.size_B > 0 &&
|
|
|
|
|
res->aux.surf.usage &
|
|
|
|
|
(ISL_SURF_USAGE_HIZ_BIT | ISL_SURF_USAGE_MCS_BIT));
|
|
|
|
|
}
|
2019-08-01 16:49:57 -07:00
|
|
|
|
|
|
|
|
if (res->mod_info && has_ccs) {
|
|
|
|
|
/* Only allow a CCS modifier if the aux was created successfully. */
|
|
|
|
|
res->aux.possible_usages |= 1 << res->mod_info->aux_usage;
|
|
|
|
|
} else if (has_mcs) {
|
2019-09-18 13:14:31 -07:00
|
|
|
res->aux.possible_usages |=
|
|
|
|
|
1 << (has_ccs ? ISL_AUX_USAGE_MCS_CCS : ISL_AUX_USAGE_MCS);
|
2019-08-01 16:49:57 -07:00
|
|
|
} else if (has_hiz) {
|
2020-03-03 22:20:26 -06:00
|
|
|
if (!has_ccs) {
|
|
|
|
|
res->aux.possible_usages |= 1 << ISL_AUX_USAGE_HIZ;
|
|
|
|
|
} else if (res->surf.samples == 1 &&
|
|
|
|
|
(res->surf.usage & ISL_SURF_USAGE_TEXTURE_BIT)) {
|
|
|
|
|
/* If this resource is single-sampled and will be used as a texture,
|
|
|
|
|
* put the HiZ surface in write-through mode so that we can sample
|
|
|
|
|
* from it.
|
|
|
|
|
*/
|
|
|
|
|
res->aux.possible_usages |= 1 << ISL_AUX_USAGE_HIZ_CCS_WT;
|
|
|
|
|
} else {
|
|
|
|
|
res->aux.possible_usages |= 1 << ISL_AUX_USAGE_HIZ_CCS;
|
|
|
|
|
}
|
2020-03-05 11:46:51 -06:00
|
|
|
} else if (has_ccs && isl_surf_usage_is_stencil(res->surf.usage)) {
|
|
|
|
|
res->aux.possible_usages |= 1 << ISL_AUX_USAGE_STC_CCS;
|
2019-08-01 16:49:57 -07:00
|
|
|
} else if (has_ccs) {
|
2020-06-04 16:42:20 -07:00
|
|
|
if (want_ccs_e_for_format(devinfo, res->surf.format)) {
|
|
|
|
|
res->aux.possible_usages |= devinfo->gen < 12 ?
|
|
|
|
|
1 << ISL_AUX_USAGE_CCS_E : 1 << ISL_AUX_USAGE_GEN12_CCS_E;
|
|
|
|
|
} else if (isl_format_supports_ccs_d(devinfo, res->surf.format)) {
|
2019-08-01 16:49:57 -07:00
|
|
|
res->aux.possible_usages |= 1 << ISL_AUX_USAGE_CCS_D;
|
2020-06-04 16:42:20 -07:00
|
|
|
}
|
2019-08-01 16:49:57 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
res->aux.usage = util_last_bit(res->aux.possible_usages) - 1;
|
|
|
|
|
|
|
|
|
|
res->aux.sampler_usages = res->aux.possible_usages;
|
|
|
|
|
|
|
|
|
|
/* We don't always support sampling with hiz. But when we do, it must be
|
|
|
|
|
* single sampled.
|
|
|
|
|
*/
|
|
|
|
|
if (!devinfo->has_sample_with_hiz || res->surf.samples > 1)
|
|
|
|
|
res->aux.sampler_usages &= ~(1 << ISL_AUX_USAGE_HIZ);
|
|
|
|
|
|
2020-03-03 22:20:26 -06:00
|
|
|
/* ISL_AUX_USAGE_HIZ_CCS doesn't support sampling at all */
|
2019-08-09 11:08:26 -07:00
|
|
|
res->aux.sampler_usages &= ~(1 << ISL_AUX_USAGE_HIZ_CCS);
|
|
|
|
|
|
2019-08-01 16:49:57 -07:00
|
|
|
enum isl_aux_state initial_state;
|
2019-06-23 00:53:23 -07:00
|
|
|
*aux_size_B = 0;
|
|
|
|
|
*alloc_flags = 0;
|
2018-12-07 11:54:02 -08:00
|
|
|
assert(!res->aux.bo);
|
|
|
|
|
|
|
|
|
|
switch (res->aux.usage) {
|
|
|
|
|
case ISL_AUX_USAGE_NONE:
|
2019-08-01 16:49:57 -07:00
|
|
|
/* Having no aux buffer is only okay if there's no modifier with aux. */
|
|
|
|
|
return !res->mod_info || res->mod_info->aux_usage == ISL_AUX_USAGE_NONE;
|
2018-12-07 11:54:02 -08:00
|
|
|
case ISL_AUX_USAGE_HIZ:
|
2019-08-08 17:39:47 -07:00
|
|
|
case ISL_AUX_USAGE_HIZ_CCS:
|
2020-03-03 22:20:26 -06:00
|
|
|
case ISL_AUX_USAGE_HIZ_CCS_WT:
|
2018-12-07 11:54:02 -08:00
|
|
|
initial_state = ISL_AUX_STATE_AUX_INVALID;
|
|
|
|
|
break;
|
|
|
|
|
case ISL_AUX_USAGE_MCS:
|
2019-09-18 13:15:47 -07:00
|
|
|
case ISL_AUX_USAGE_MCS_CCS:
|
2018-12-07 11:54:02 -08:00
|
|
|
/* The Ivybridge PRM, Vol 2 Part 1 p326 says:
|
|
|
|
|
*
|
|
|
|
|
* "When MCS buffer is enabled and bound to MSRT, it is required
|
|
|
|
|
* that it is cleared prior to any rendering."
|
|
|
|
|
*
|
|
|
|
|
* Since we only use the MCS buffer for rendering, we just clear it
|
|
|
|
|
* immediately on allocation. The clear value for MCS buffers is all
|
|
|
|
|
* 1's, so we simply memset it to 0xff.
|
|
|
|
|
*/
|
|
|
|
|
initial_state = ISL_AUX_STATE_CLEAR;
|
|
|
|
|
break;
|
|
|
|
|
case ISL_AUX_USAGE_CCS_D:
|
|
|
|
|
case ISL_AUX_USAGE_CCS_E:
|
2020-06-04 16:42:20 -07:00
|
|
|
case ISL_AUX_USAGE_GEN12_CCS_E:
|
2020-03-05 11:46:51 -06:00
|
|
|
case ISL_AUX_USAGE_STC_CCS:
|
2018-12-07 11:54:02 -08:00
|
|
|
/* When CCS_E is used, we need to ensure that the CCS starts off in
|
|
|
|
|
* a valid state. From the Sky Lake PRM, "MCS Buffer for Render
|
|
|
|
|
* Target(s)":
|
|
|
|
|
*
|
|
|
|
|
* "If Software wants to enable Color Compression without Fast
|
|
|
|
|
* clear, Software needs to initialize MCS with zeros."
|
|
|
|
|
*
|
|
|
|
|
* A CCS value of 0 indicates that the corresponding block is in the
|
|
|
|
|
* pass-through state which is what we want.
|
|
|
|
|
*
|
|
|
|
|
* For CCS_D, do the same thing. On Gen9+, this avoids having any
|
|
|
|
|
* undefined bits in the aux buffer.
|
|
|
|
|
*/
|
2020-03-05 11:46:51 -06:00
|
|
|
if (imported) {
|
|
|
|
|
assert(res->aux.usage != ISL_AUX_USAGE_STC_CCS);
|
2019-07-09 00:47:15 -07:00
|
|
|
initial_state =
|
|
|
|
|
isl_drm_modifier_get_default_aux_state(res->mod_info->modifier);
|
2020-03-05 11:46:51 -06:00
|
|
|
} else {
|
2019-07-09 00:47:15 -07:00
|
|
|
initial_state = ISL_AUX_STATE_PASS_THROUGH;
|
2020-03-05 11:46:51 -06:00
|
|
|
}
|
2019-06-23 00:53:23 -07:00
|
|
|
*alloc_flags |= BO_ALLOC_ZEROED;
|
2018-12-07 11:54:02 -08:00
|
|
|
break;
|
2019-12-16 21:17:17 -08:00
|
|
|
case ISL_AUX_USAGE_MC:
|
|
|
|
|
unreachable("Unsupported aux mode");
|
2018-12-07 11:54:02 -08:00
|
|
|
}
|
|
|
|
|
|
2019-10-24 09:14:07 -07:00
|
|
|
/* Create the aux_state for the auxiliary buffer. */
|
|
|
|
|
res->aux.state = create_aux_state_map(res, initial_state);
|
|
|
|
|
if (!res->aux.state)
|
|
|
|
|
return false;
|
2018-12-07 11:54:02 -08:00
|
|
|
|
2019-10-25 15:07:42 -07:00
|
|
|
/* Increase the aux offset if the main and aux surfaces will share a BO. */
|
2019-10-24 09:14:07 -07:00
|
|
|
res->aux.offset =
|
|
|
|
|
!res->mod_info || res->mod_info->aux_usage == res->aux.usage ?
|
2019-10-25 15:07:42 -07:00
|
|
|
ALIGN(res->surf.size_B, res->aux.surf.alignment_B) : 0;
|
2019-02-15 14:45:05 -08:00
|
|
|
uint64_t size = res->aux.surf.size_B;
|
|
|
|
|
|
2019-08-07 16:02:51 -07:00
|
|
|
/* Allocate space in the buffer for storing the CCS. */
|
|
|
|
|
if (res->aux.extra_aux.surf.size_B > 0) {
|
2019-10-25 15:07:42 -07:00
|
|
|
const uint64_t padded_aux_size =
|
2019-08-07 16:02:51 -07:00
|
|
|
ALIGN(size, res->aux.extra_aux.surf.alignment_B);
|
2019-10-25 15:07:42 -07:00
|
|
|
res->aux.extra_aux.offset = res->aux.offset + padded_aux_size;
|
|
|
|
|
size = padded_aux_size + res->aux.extra_aux.surf.size_B;
|
2019-08-07 16:02:51 -07:00
|
|
|
}
|
|
|
|
|
|
2019-02-15 14:45:05 -08:00
|
|
|
/* Allocate space in the buffer for storing the clear color. On modern
|
|
|
|
|
* platforms (gen > 9), we can read it directly from such buffer.
|
|
|
|
|
*
|
|
|
|
|
* On gen <= 9, we are going to store the clear color on the buffer
|
|
|
|
|
* anyways, and copy it back to the surface state during state emission.
|
2019-08-13 14:47:27 -07:00
|
|
|
*
|
|
|
|
|
* Also add some padding to make sure the fast clear color state buffer
|
|
|
|
|
* starts at a 4K alignment. We believe that 256B might be enough, but due
|
|
|
|
|
* to lack of testing we will leave this as 4K for now.
|
2019-02-15 14:45:05 -08:00
|
|
|
*/
|
2019-08-13 14:47:27 -07:00
|
|
|
size = ALIGN(size, 4096);
|
2019-10-25 15:07:42 -07:00
|
|
|
res->aux.clear_color_offset = res->aux.offset + size;
|
2019-06-23 00:53:23 -07:00
|
|
|
size += iris_get_aux_clear_color_state_size(screen);
|
|
|
|
|
*aux_size_B = size;
|
2019-02-15 14:45:05 -08:00
|
|
|
|
2019-08-09 11:08:26 -07:00
|
|
|
if (isl_aux_usage_has_hiz(res->aux.usage)) {
|
2019-06-23 00:53:23 -07:00
|
|
|
for (unsigned level = 0; level < res->surf.levels; ++level) {
|
|
|
|
|
uint32_t width = u_minify(res->surf.phys_level0_sa.width, level);
|
|
|
|
|
uint32_t height = u_minify(res->surf.phys_level0_sa.height, level);
|
|
|
|
|
|
|
|
|
|
/* Disable HiZ for LOD > 0 unless the width/height are 8x4 aligned.
|
|
|
|
|
* For LOD == 0, we can grow the dimensions to make it work.
|
|
|
|
|
*/
|
|
|
|
|
if (level == 0 || ((width & 7) == 0 && (height & 3) == 0))
|
|
|
|
|
res->aux.has_hiz |= 1 << level;
|
|
|
|
|
}
|
2019-02-15 14:16:04 -08:00
|
|
|
}
|
2018-12-07 11:54:02 -08:00
|
|
|
|
2019-06-23 00:53:23 -07:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Initialize the aux buffer contents.
|
2019-10-25 15:38:18 -07:00
|
|
|
*
|
|
|
|
|
* Returns false on unexpected error (e.g. mapping a BO failed).
|
2019-06-23 00:53:23 -07:00
|
|
|
*/
|
|
|
|
|
static bool
|
|
|
|
|
iris_resource_init_aux_buf(struct iris_resource *res, uint32_t alloc_flags,
|
|
|
|
|
unsigned clear_color_state_size)
|
|
|
|
|
{
|
2019-02-15 14:45:05 -08:00
|
|
|
if (!(alloc_flags & BO_ALLOC_ZEROED)) {
|
2018-12-07 11:54:02 -08:00
|
|
|
void *map = iris_bo_map(NULL, res->aux.bo, MAP_WRITE | MAP_RAW);
|
2019-02-15 14:45:05 -08:00
|
|
|
|
2019-10-25 15:38:18 -07:00
|
|
|
if (!map)
|
2018-12-07 11:54:02 -08:00
|
|
|
return false;
|
|
|
|
|
|
2019-06-23 00:53:23 -07:00
|
|
|
if (iris_resource_get_aux_state(res, 0, 0) != ISL_AUX_STATE_AUX_INVALID) {
|
2019-09-19 08:13:15 -07:00
|
|
|
uint8_t memset_value = isl_aux_usage_has_mcs(res->aux.usage) ? 0xFF : 0;
|
2019-06-23 00:53:23 -07:00
|
|
|
memset((char*)map + res->aux.offset, memset_value,
|
|
|
|
|
res->aux.surf.size_B);
|
|
|
|
|
}
|
2019-02-15 14:45:05 -08:00
|
|
|
|
2019-09-19 08:13:15 -07:00
|
|
|
memset((char*)map + res->aux.extra_aux.offset,
|
2020-03-04 14:37:03 -06:00
|
|
|
0, res->aux.extra_aux.surf.size_B);
|
2019-08-07 16:02:51 -07:00
|
|
|
|
2019-02-15 14:45:05 -08:00
|
|
|
/* Zero the indirect clear color to match ::fast_clear_color. */
|
|
|
|
|
memset((char *)map + res->aux.clear_color_offset, 0,
|
|
|
|
|
clear_color_state_size);
|
|
|
|
|
|
2018-12-07 11:54:02 -08:00
|
|
|
iris_bo_unmap(res->aux.bo);
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-26 16:28:10 -07:00
|
|
|
if (clear_color_state_size > 0) {
|
|
|
|
|
res->aux.clear_color_bo = res->aux.bo;
|
|
|
|
|
iris_bo_reference(res->aux.clear_color_bo);
|
|
|
|
|
}
|
2019-02-15 14:45:05 -08:00
|
|
|
|
2019-06-23 00:53:23 -07:00
|
|
|
return true;
|
|
|
|
|
}
|
2018-12-10 00:35:48 -08:00
|
|
|
|
2019-06-23 00:53:23 -07:00
|
|
|
/**
|
|
|
|
|
* Allocate the initial aux surface for a resource based on aux.usage
|
2019-10-25 15:38:18 -07:00
|
|
|
*
|
|
|
|
|
* Returns false on unexpected error (e.g. allocation failed, or invalid
|
|
|
|
|
* configuration result).
|
2019-06-23 00:53:23 -07:00
|
|
|
*/
|
|
|
|
|
static bool
|
|
|
|
|
iris_resource_alloc_separate_aux(struct iris_screen *screen,
|
|
|
|
|
struct iris_resource *res)
|
|
|
|
|
{
|
|
|
|
|
uint32_t alloc_flags;
|
|
|
|
|
uint64_t size;
|
2019-07-09 00:47:15 -07:00
|
|
|
if (!iris_resource_configure_aux(screen, res, false, &size, &alloc_flags))
|
2019-06-23 00:53:23 -07:00
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (size == 0)
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
/* Allocate the auxiliary buffer. ISL has stricter set of alignment rules
|
|
|
|
|
* the drm allocator. Therefore, one can pass the ISL dimensions in terms
|
|
|
|
|
* of bytes instead of trying to recalculate based on different format
|
|
|
|
|
* block sizes.
|
|
|
|
|
*/
|
|
|
|
|
res->aux.bo = iris_bo_alloc_tiled(screen->bufmgr, "aux buffer", size, 4096,
|
2019-08-12 15:41:11 -07:00
|
|
|
IRIS_MEMZONE_OTHER,
|
|
|
|
|
isl_tiling_to_i915_tiling(res->aux.surf.tiling),
|
2019-06-23 00:53:23 -07:00
|
|
|
res->aux.surf.row_pitch_B, alloc_flags);
|
|
|
|
|
if (!res->aux.bo) {
|
|
|
|
|
return false;
|
2018-12-10 00:35:48 -08:00
|
|
|
}
|
2018-12-07 11:54:02 -08:00
|
|
|
|
2019-06-23 00:53:23 -07:00
|
|
|
if (!iris_resource_init_aux_buf(res, alloc_flags,
|
|
|
|
|
iris_get_aux_clear_color_state_size(screen)))
|
|
|
|
|
return false;
|
|
|
|
|
|
2018-04-28 01:58:54 -07:00
|
|
|
map_aux_addresses(screen, res);
|
|
|
|
|
|
2018-12-07 11:54:02 -08:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-09 00:47:15 -07:00
|
|
|
void
|
|
|
|
|
iris_resource_finish_aux_import(struct pipe_screen *pscreen,
|
|
|
|
|
struct iris_resource *res)
|
|
|
|
|
{
|
|
|
|
|
struct iris_screen *screen = (struct iris_screen *)pscreen;
|
|
|
|
|
assert(iris_resource_unfinished_aux_import(res));
|
|
|
|
|
assert(!res->mod_info->supports_clear_color);
|
|
|
|
|
|
|
|
|
|
struct iris_resource *aux_res = (void *) res->base.next;
|
|
|
|
|
assert(aux_res->aux.surf.row_pitch_B && aux_res->aux.offset &&
|
|
|
|
|
aux_res->aux.bo);
|
|
|
|
|
|
|
|
|
|
assert(res->bo == aux_res->aux.bo);
|
|
|
|
|
iris_bo_reference(aux_res->aux.bo);
|
|
|
|
|
res->aux.bo = aux_res->aux.bo;
|
|
|
|
|
|
|
|
|
|
res->aux.offset = aux_res->aux.offset;
|
|
|
|
|
|
|
|
|
|
assert(res->bo->size >= (res->aux.offset + res->aux.surf.size_B));
|
|
|
|
|
assert(res->aux.clear_color_bo == NULL);
|
|
|
|
|
res->aux.clear_color_offset = 0;
|
|
|
|
|
|
|
|
|
|
assert(aux_res->aux.surf.row_pitch_B == res->aux.surf.row_pitch_B);
|
|
|
|
|
|
|
|
|
|
unsigned clear_color_state_size =
|
|
|
|
|
iris_get_aux_clear_color_state_size(screen);
|
|
|
|
|
|
|
|
|
|
if (clear_color_state_size > 0) {
|
|
|
|
|
res->aux.clear_color_bo =
|
|
|
|
|
iris_bo_alloc(screen->bufmgr, "clear color buffer",
|
|
|
|
|
clear_color_state_size, IRIS_MEMZONE_OTHER);
|
|
|
|
|
res->aux.clear_color_offset = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
iris_resource_destroy(&screen->base, res->base.next);
|
|
|
|
|
res->base.next = NULL;
|
2019-12-05 12:19:33 -08:00
|
|
|
|
|
|
|
|
map_aux_addresses(screen, res);
|
2019-07-09 00:47:15 -07:00
|
|
|
}
|
|
|
|
|
|
2018-10-25 17:02:56 -05:00
|
|
|
static struct pipe_resource *
|
|
|
|
|
iris_resource_create_for_buffer(struct pipe_screen *pscreen,
|
|
|
|
|
const struct pipe_resource *templ)
|
|
|
|
|
{
|
|
|
|
|
struct iris_screen *screen = (struct iris_screen *)pscreen;
|
|
|
|
|
struct iris_resource *res = iris_alloc_resource(pscreen, templ);
|
|
|
|
|
|
|
|
|
|
assert(templ->target == PIPE_BUFFER);
|
|
|
|
|
assert(templ->height0 <= 1);
|
|
|
|
|
assert(templ->depth0 <= 1);
|
|
|
|
|
assert(templ->format == PIPE_FORMAT_NONE ||
|
|
|
|
|
util_format_get_blocksize(templ->format) == 1);
|
|
|
|
|
|
|
|
|
|
res->internal_format = templ->format;
|
|
|
|
|
res->surf.tiling = ISL_TILING_LINEAR;
|
|
|
|
|
|
|
|
|
|
enum iris_memory_zone memzone = IRIS_MEMZONE_OTHER;
|
|
|
|
|
const char *name = templ->target == PIPE_BUFFER ? "buffer" : "miptree";
|
|
|
|
|
if (templ->flags & IRIS_RESOURCE_FLAG_SHADER_MEMZONE) {
|
|
|
|
|
memzone = IRIS_MEMZONE_SHADER;
|
|
|
|
|
name = "shader kernels";
|
|
|
|
|
} else if (templ->flags & IRIS_RESOURCE_FLAG_SURFACE_MEMZONE) {
|
|
|
|
|
memzone = IRIS_MEMZONE_SURFACE;
|
|
|
|
|
name = "surface state";
|
|
|
|
|
} else if (templ->flags & IRIS_RESOURCE_FLAG_DYNAMIC_MEMZONE) {
|
|
|
|
|
memzone = IRIS_MEMZONE_DYNAMIC;
|
|
|
|
|
name = "dynamic state";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
res->bo = iris_bo_alloc(screen->bufmgr, name, templ->width0, memzone);
|
|
|
|
|
if (!res->bo) {
|
|
|
|
|
iris_resource_destroy(pscreen, &res->base);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-13 18:14:24 +03:00
|
|
|
if (templ->bind & PIPE_BIND_SHARED)
|
|
|
|
|
iris_bo_make_external(res->bo);
|
|
|
|
|
|
2018-10-25 17:02:56 -05:00
|
|
|
return &res->base;
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-23 23:15:14 -08:00
|
|
|
static struct pipe_resource *
|
|
|
|
|
iris_resource_create_with_modifiers(struct pipe_screen *pscreen,
|
|
|
|
|
const struct pipe_resource *templ,
|
|
|
|
|
const uint64_t *modifiers,
|
|
|
|
|
int modifiers_count)
|
|
|
|
|
{
|
|
|
|
|
struct iris_screen *screen = (struct iris_screen *)pscreen;
|
|
|
|
|
struct gen_device_info *devinfo = &screen->devinfo;
|
|
|
|
|
struct iris_resource *res = iris_alloc_resource(pscreen, templ);
|
2018-07-30 15:08:02 -07:00
|
|
|
|
2017-11-23 23:15:14 -08:00
|
|
|
if (!res)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
2018-12-07 11:02:50 -08:00
|
|
|
const struct util_format_description *format_desc =
|
|
|
|
|
util_format_description(templ->format);
|
2018-07-30 15:08:02 -07:00
|
|
|
const bool has_depth = util_format_has_depth(format_desc);
|
2018-11-28 02:30:42 -08:00
|
|
|
uint64_t modifier =
|
2019-03-26 00:25:31 -07:00
|
|
|
select_best_modifier(devinfo, templ->format, modifiers, modifiers_count);
|
2017-11-23 23:15:14 -08:00
|
|
|
|
2018-11-28 02:30:42 -08:00
|
|
|
isl_tiling_flags_t tiling_flags = ISL_TILING_ANY_MASK;
|
2017-11-23 23:15:14 -08:00
|
|
|
|
2018-11-28 02:30:42 -08:00
|
|
|
if (modifier != DRM_FORMAT_MOD_INVALID) {
|
2018-12-09 12:11:17 -08:00
|
|
|
res->mod_info = isl_drm_modifier_get_info(modifier);
|
2018-01-19 15:09:05 -08:00
|
|
|
|
2018-12-09 12:11:17 -08:00
|
|
|
tiling_flags = 1 << res->mod_info->tiling;
|
2018-11-28 02:30:42 -08:00
|
|
|
} else {
|
|
|
|
|
if (modifiers_count > 0) {
|
|
|
|
|
fprintf(stderr, "Unsupported modifier, resource creation failed.\n");
|
2019-09-25 12:48:57 -07:00
|
|
|
goto fail;
|
2018-11-28 02:30:42 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Use linear for staging buffers */
|
|
|
|
|
if (templ->usage == PIPE_USAGE_STAGING ||
|
|
|
|
|
templ->bind & (PIPE_BIND_LINEAR | PIPE_BIND_CURSOR) )
|
|
|
|
|
tiling_flags = ISL_TILING_LINEAR_BIT;
|
2019-12-11 09:49:38 -08:00
|
|
|
else if (templ->bind & PIPE_BIND_SCANOUT)
|
|
|
|
|
tiling_flags = ISL_TILING_X_BIT;
|
2018-11-28 02:30:42 -08:00
|
|
|
}
|
2018-07-30 15:08:02 -07:00
|
|
|
|
2017-11-23 23:15:14 -08:00
|
|
|
isl_surf_usage_flags_t usage = pipe_bind_to_isl_usage(templ->bind);
|
|
|
|
|
|
2018-07-27 20:25:21 -07:00
|
|
|
if (templ->target == PIPE_TEXTURE_CUBE ||
|
|
|
|
|
templ->target == PIPE_TEXTURE_CUBE_ARRAY)
|
2017-11-23 23:15:14 -08:00
|
|
|
usage |= ISL_SURF_USAGE_CUBE_BIT;
|
|
|
|
|
|
2018-07-30 15:08:02 -07:00
|
|
|
if (templ->usage != PIPE_USAGE_STAGING) {
|
|
|
|
|
if (templ->format == PIPE_FORMAT_S8_UINT)
|
|
|
|
|
usage |= ISL_SURF_USAGE_STENCIL_BIT;
|
|
|
|
|
else if (has_depth)
|
|
|
|
|
usage |= ISL_SURF_USAGE_DEPTH_BIT;
|
|
|
|
|
}
|
2018-04-25 15:25:33 -07:00
|
|
|
|
2018-08-03 01:24:51 -07:00
|
|
|
enum pipe_format pfmt = templ->format;
|
2018-08-08 14:54:09 -07:00
|
|
|
res->internal_format = pfmt;
|
2018-08-03 01:24:51 -07:00
|
|
|
|
2018-08-09 03:28:24 -07:00
|
|
|
/* Should be handled by u_transfer_helper */
|
|
|
|
|
assert(!util_format_is_depth_and_stencil(pfmt));
|
2018-04-25 15:25:33 -07:00
|
|
|
|
2018-10-07 20:31:09 -07:00
|
|
|
struct iris_format_info fmt = iris_format_for_usage(devinfo, pfmt, usage);
|
|
|
|
|
assert(fmt.fmt != ISL_FORMAT_UNSUPPORTED);
|
2018-04-25 15:25:33 -07:00
|
|
|
|
2018-04-24 23:38:10 -07:00
|
|
|
UNUSED const bool isl_surf_created_successfully =
|
|
|
|
|
isl_surf_init(&screen->isl_dev, &res->surf,
|
|
|
|
|
.dim = target_to_isl_surf_dim(templ->target),
|
2018-10-07 20:31:09 -07:00
|
|
|
.format = fmt.fmt,
|
2018-04-24 23:38:10 -07:00
|
|
|
.width = templ->width0,
|
|
|
|
|
.height = templ->height0,
|
|
|
|
|
.depth = templ->depth0,
|
|
|
|
|
.levels = templ->last_level + 1,
|
|
|
|
|
.array_len = templ->array_size,
|
|
|
|
|
.samples = MAX2(templ->nr_samples, 1),
|
|
|
|
|
.min_alignment_B = 0,
|
|
|
|
|
.row_pitch_B = 0,
|
|
|
|
|
.usage = usage,
|
2018-11-28 02:30:42 -08:00
|
|
|
.tiling_flags = tiling_flags);
|
2018-04-24 23:38:10 -07:00
|
|
|
assert(isl_surf_created_successfully);
|
2017-11-23 23:15:14 -08:00
|
|
|
|
2018-12-07 11:02:50 -08:00
|
|
|
const char *name = "miptree";
|
2018-04-03 01:40:23 -07:00
|
|
|
enum iris_memory_zone memzone = IRIS_MEMZONE_OTHER;
|
2018-10-25 17:02:56 -05:00
|
|
|
|
2019-02-22 21:24:46 +00:00
|
|
|
unsigned int flags = 0;
|
|
|
|
|
if (templ->usage == PIPE_USAGE_STAGING)
|
|
|
|
|
flags |= BO_ALLOC_COHERENT;
|
|
|
|
|
|
2018-10-25 17:02:56 -05:00
|
|
|
/* These are for u_upload_mgr buffers only */
|
|
|
|
|
assert(!(templ->flags & (IRIS_RESOURCE_FLAG_SHADER_MEMZONE |
|
|
|
|
|
IRIS_RESOURCE_FLAG_SURFACE_MEMZONE |
|
|
|
|
|
IRIS_RESOURCE_FLAG_DYNAMIC_MEMZONE)));
|
2018-04-03 01:40:23 -07:00
|
|
|
|
2019-06-23 01:16:48 -07:00
|
|
|
uint32_t aux_preferred_alloc_flags;
|
|
|
|
|
uint64_t aux_size = 0;
|
2019-10-25 15:38:18 -07:00
|
|
|
if (!iris_resource_configure_aux(screen, res, false, &aux_size,
|
|
|
|
|
&aux_preferred_alloc_flags)) {
|
|
|
|
|
goto fail;
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-24 09:14:07 -07:00
|
|
|
/* Modifiers require the aux data to be in the same buffer as the main
|
|
|
|
|
* surface, but we combine them even when a modifiers is not being used.
|
|
|
|
|
*/
|
|
|
|
|
const uint64_t bo_size =
|
|
|
|
|
MAX2(res->surf.size_B, res->aux.offset + aux_size);
|
2019-05-31 15:50:53 -07:00
|
|
|
uint32_t alignment = MAX2(4096, res->surf.alignment_B);
|
|
|
|
|
res->bo = iris_bo_alloc_tiled(screen->bufmgr, name, bo_size, alignment,
|
|
|
|
|
memzone,
|
2017-11-23 23:15:14 -08:00
|
|
|
isl_tiling_to_i915_tiling(res->surf.tiling),
|
2019-02-22 21:24:46 +00:00
|
|
|
res->surf.row_pitch_B, flags);
|
2018-12-07 11:54:02 -08:00
|
|
|
|
|
|
|
|
if (!res->bo)
|
|
|
|
|
goto fail;
|
|
|
|
|
|
2019-10-24 09:14:07 -07:00
|
|
|
if (aux_size > 0) {
|
|
|
|
|
res->aux.bo = res->bo;
|
|
|
|
|
iris_bo_reference(res->aux.bo);
|
|
|
|
|
unsigned clear_color_state_size =
|
|
|
|
|
iris_get_aux_clear_color_state_size(screen);
|
|
|
|
|
if (!iris_resource_init_aux_buf(res, flags, clear_color_state_size))
|
|
|
|
|
goto fail;
|
|
|
|
|
map_aux_addresses(screen, res);
|
2019-06-23 01:16:48 -07:00
|
|
|
}
|
|
|
|
|
|
2020-04-13 18:14:24 +03:00
|
|
|
if (templ->bind & PIPE_BIND_SHARED)
|
|
|
|
|
iris_bo_make_external(res->bo);
|
|
|
|
|
|
2017-11-23 23:15:14 -08:00
|
|
|
return &res->base;
|
2018-12-07 11:54:02 -08:00
|
|
|
|
|
|
|
|
fail:
|
|
|
|
|
fprintf(stderr, "XXX: resource creation failed\n");
|
|
|
|
|
iris_resource_destroy(pscreen, &res->base);
|
|
|
|
|
return NULL;
|
|
|
|
|
|
2017-11-23 23:15:14 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static struct pipe_resource *
|
|
|
|
|
iris_resource_create(struct pipe_screen *pscreen,
|
|
|
|
|
const struct pipe_resource *templ)
|
|
|
|
|
{
|
2018-10-25 17:02:56 -05:00
|
|
|
if (templ->target == PIPE_BUFFER)
|
|
|
|
|
return iris_resource_create_for_buffer(pscreen, templ);
|
|
|
|
|
else
|
|
|
|
|
return iris_resource_create_with_modifiers(pscreen, templ, NULL, 0);
|
2017-11-23 23:15:14 -08:00
|
|
|
}
|
|
|
|
|
|
2018-06-02 12:32:19 +01:00
|
|
|
static uint64_t
|
|
|
|
|
tiling_to_modifier(uint32_t tiling)
|
|
|
|
|
{
|
|
|
|
|
static const uint64_t map[] = {
|
|
|
|
|
[I915_TILING_NONE] = DRM_FORMAT_MOD_LINEAR,
|
|
|
|
|
[I915_TILING_X] = I915_FORMAT_MOD_X_TILED,
|
|
|
|
|
[I915_TILING_Y] = I915_FORMAT_MOD_Y_TILED,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
assert(tiling < ARRAY_SIZE(map));
|
|
|
|
|
|
|
|
|
|
return map[tiling];
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-31 14:47:02 +01:00
|
|
|
static struct pipe_resource *
|
|
|
|
|
iris_resource_from_user_memory(struct pipe_screen *pscreen,
|
|
|
|
|
const struct pipe_resource *templ,
|
|
|
|
|
void *user_memory)
|
|
|
|
|
{
|
|
|
|
|
struct iris_screen *screen = (struct iris_screen *)pscreen;
|
|
|
|
|
struct iris_bufmgr *bufmgr = screen->bufmgr;
|
|
|
|
|
struct iris_resource *res = iris_alloc_resource(pscreen, templ);
|
|
|
|
|
if (!res)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
2018-10-25 17:02:56 -05:00
|
|
|
assert(templ->target == PIPE_BUFFER);
|
|
|
|
|
|
|
|
|
|
res->internal_format = templ->format;
|
2018-07-31 14:47:02 +01:00
|
|
|
res->bo = iris_bo_create_userptr(bufmgr, "user",
|
|
|
|
|
user_memory, templ->width0,
|
|
|
|
|
IRIS_MEMZONE_OTHER);
|
|
|
|
|
if (!res->bo) {
|
2020-03-06 15:57:40 +02:00
|
|
|
iris_resource_destroy(pscreen, &res->base);
|
2018-07-31 14:47:02 +01:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-25 21:38:40 -04:00
|
|
|
util_range_add(&res->base, &res->valid_buffer_range, 0, templ->width0);
|
2019-04-05 11:54:10 -07:00
|
|
|
|
2018-07-31 14:47:02 +01:00
|
|
|
return &res->base;
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-23 23:15:14 -08:00
|
|
|
static struct pipe_resource *
|
|
|
|
|
iris_resource_from_handle(struct pipe_screen *pscreen,
|
|
|
|
|
const struct pipe_resource *templ,
|
|
|
|
|
struct winsys_handle *whandle,
|
|
|
|
|
unsigned usage)
|
|
|
|
|
{
|
|
|
|
|
struct iris_screen *screen = (struct iris_screen *)pscreen;
|
2018-10-07 20:31:09 -07:00
|
|
|
struct gen_device_info *devinfo = &screen->devinfo;
|
2017-11-23 23:15:14 -08:00
|
|
|
struct iris_bufmgr *bufmgr = screen->bufmgr;
|
|
|
|
|
struct iris_resource *res = iris_alloc_resource(pscreen, templ);
|
2019-04-04 08:27:33 -07:00
|
|
|
const struct isl_drm_modifier_info *mod_inf =
|
|
|
|
|
isl_drm_modifier_get_info(whandle->modifier);
|
|
|
|
|
uint32_t tiling;
|
|
|
|
|
|
2017-11-23 23:15:14 -08:00
|
|
|
if (!res)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
switch (whandle->type) {
|
2018-06-02 12:32:19 +01:00
|
|
|
case WINSYS_HANDLE_TYPE_FD:
|
2019-04-04 08:27:33 -07:00
|
|
|
if (mod_inf)
|
|
|
|
|
tiling = isl_tiling_to_i915_tiling(mod_inf->tiling);
|
|
|
|
|
else
|
|
|
|
|
tiling = I915_TILING_LAST + 1;
|
|
|
|
|
res->bo = iris_bo_import_dmabuf(bufmgr, whandle->handle,
|
|
|
|
|
tiling, whandle->stride);
|
2017-11-23 23:15:14 -08:00
|
|
|
break;
|
2018-06-02 12:32:19 +01:00
|
|
|
case WINSYS_HANDLE_TYPE_SHARED:
|
2017-11-23 23:15:14 -08:00
|
|
|
res->bo = iris_bo_gem_create_from_name(bufmgr, "winsys image",
|
|
|
|
|
whandle->handle);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
unreachable("invalid winsys handle type");
|
|
|
|
|
}
|
2018-06-02 12:32:19 +01:00
|
|
|
if (!res->bo)
|
2020-03-06 15:57:40 +02:00
|
|
|
goto fail;
|
2017-11-23 23:15:14 -08:00
|
|
|
|
2019-04-30 14:51:52 -04:00
|
|
|
res->offset = whandle->offset;
|
|
|
|
|
|
2019-04-04 08:27:33 -07:00
|
|
|
if (mod_inf == NULL) {
|
|
|
|
|
mod_inf =
|
|
|
|
|
isl_drm_modifier_get_info(tiling_to_modifier(res->bo->tiling_mode));
|
2018-06-02 12:32:19 +01:00
|
|
|
}
|
2019-04-04 08:27:33 -07:00
|
|
|
assert(mod_inf);
|
|
|
|
|
|
2019-11-15 09:17:23 -08:00
|
|
|
res->external_format = whandle->format;
|
2019-04-04 08:27:33 -07:00
|
|
|
res->mod_info = mod_inf;
|
2017-11-23 23:15:14 -08:00
|
|
|
|
2018-12-17 01:25:11 -05:00
|
|
|
isl_surf_usage_flags_t isl_usage = pipe_bind_to_isl_usage(templ->bind);
|
2017-11-23 23:15:14 -08:00
|
|
|
|
2018-10-07 20:31:09 -07:00
|
|
|
const struct iris_format_info fmt =
|
|
|
|
|
iris_format_for_usage(devinfo, templ->format, isl_usage);
|
2019-02-13 13:07:51 -08:00
|
|
|
res->internal_format = templ->format;
|
2018-10-07 20:31:09 -07:00
|
|
|
|
2018-10-25 17:02:56 -05:00
|
|
|
if (templ->target == PIPE_BUFFER) {
|
|
|
|
|
res->surf.tiling = ISL_TILING_LINEAR;
|
|
|
|
|
} else {
|
2019-11-15 09:17:23 -08:00
|
|
|
/* Create a surface for each plane specified by the external format. */
|
|
|
|
|
if (whandle->plane < util_format_get_num_planes(whandle->format)) {
|
2019-07-09 00:47:15 -07:00
|
|
|
UNUSED const bool isl_surf_created_successfully =
|
|
|
|
|
isl_surf_init(&screen->isl_dev, &res->surf,
|
|
|
|
|
.dim = target_to_isl_surf_dim(templ->target),
|
|
|
|
|
.format = fmt.fmt,
|
|
|
|
|
.width = templ->width0,
|
|
|
|
|
.height = templ->height0,
|
|
|
|
|
.depth = templ->depth0,
|
|
|
|
|
.levels = templ->last_level + 1,
|
|
|
|
|
.array_len = templ->array_size,
|
|
|
|
|
.samples = MAX2(templ->nr_samples, 1),
|
|
|
|
|
.min_alignment_B = 0,
|
|
|
|
|
.row_pitch_B = whandle->stride,
|
|
|
|
|
.usage = isl_usage,
|
|
|
|
|
.tiling_flags = 1 << res->mod_info->tiling);
|
|
|
|
|
assert(isl_surf_created_successfully);
|
|
|
|
|
assert(res->bo->tiling_mode ==
|
|
|
|
|
isl_tiling_to_i915_tiling(res->surf.tiling));
|
|
|
|
|
|
|
|
|
|
// XXX: create_ccs_buf_for_image?
|
|
|
|
|
if (whandle->modifier == DRM_FORMAT_MOD_INVALID) {
|
|
|
|
|
if (!iris_resource_alloc_separate_aux(screen, res))
|
|
|
|
|
goto fail;
|
|
|
|
|
} else {
|
|
|
|
|
if (res->mod_info->aux_usage != ISL_AUX_USAGE_NONE) {
|
|
|
|
|
uint32_t alloc_flags;
|
|
|
|
|
uint64_t size;
|
|
|
|
|
bool ok = iris_resource_configure_aux(screen, res, true, &size,
|
|
|
|
|
&alloc_flags);
|
|
|
|
|
assert(ok);
|
|
|
|
|
/* The gallium dri layer will create a separate plane resource
|
|
|
|
|
* for the aux image. iris_resource_finish_aux_import will
|
|
|
|
|
* merge the separate aux parameters back into a single
|
|
|
|
|
* iris_resource.
|
|
|
|
|
*/
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
/* Save modifier import information to reconstruct later. After
|
|
|
|
|
* import, this will be available under a second image accessible
|
|
|
|
|
* from the main image with res->base.next. See
|
|
|
|
|
* iris_resource_finish_aux_import.
|
|
|
|
|
*/
|
|
|
|
|
res->aux.surf.row_pitch_B = whandle->stride;
|
|
|
|
|
res->aux.offset = whandle->offset;
|
|
|
|
|
res->aux.bo = res->bo;
|
|
|
|
|
res->bo = NULL;
|
|
|
|
|
}
|
2018-10-25 17:02:56 -05:00
|
|
|
}
|
2017-11-23 23:15:14 -08:00
|
|
|
|
|
|
|
|
return &res->base;
|
|
|
|
|
|
|
|
|
|
fail:
|
|
|
|
|
iris_resource_destroy(pscreen, &res->base);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-28 10:49:45 +02:00
|
|
|
static void
|
|
|
|
|
iris_flush_resource(struct pipe_context *ctx, struct pipe_resource *resource)
|
|
|
|
|
{
|
|
|
|
|
struct iris_context *ice = (struct iris_context *)ctx;
|
|
|
|
|
struct iris_resource *res = (void *) resource;
|
|
|
|
|
const struct isl_drm_modifier_info *mod = res->mod_info;
|
|
|
|
|
|
2020-04-23 18:00:15 -07:00
|
|
|
iris_resource_prepare_access(ice, res,
|
2019-03-28 10:49:45 +02:00
|
|
|
0, INTEL_REMAINING_LEVELS,
|
|
|
|
|
0, INTEL_REMAINING_LAYERS,
|
|
|
|
|
mod ? mod->aux_usage : ISL_AUX_USAGE_NONE,
|
|
|
|
|
mod ? mod->supports_clear_color : false);
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-02 13:02:33 +03:00
|
|
|
static void
|
|
|
|
|
iris_resource_disable_aux_on_first_query(struct pipe_resource *resource,
|
|
|
|
|
unsigned usage)
|
|
|
|
|
{
|
|
|
|
|
struct iris_resource *res = (struct iris_resource *)resource;
|
|
|
|
|
bool mod_with_aux =
|
|
|
|
|
res->mod_info && res->mod_info->aux_usage != ISL_AUX_USAGE_NONE;
|
|
|
|
|
|
|
|
|
|
/* Disable aux usage if explicit flush not set and this is the first time
|
|
|
|
|
* we are dealing with this resource and the resource was not created with
|
|
|
|
|
* a modifier with aux.
|
|
|
|
|
*/
|
|
|
|
|
if (!mod_with_aux &&
|
|
|
|
|
(!(usage & PIPE_HANDLE_USAGE_EXPLICIT_FLUSH) && res->aux.usage != 0) &&
|
|
|
|
|
p_atomic_read(&resource->reference.count) == 1) {
|
|
|
|
|
iris_resource_disable_aux(res);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-02 01:21:12 -07:00
|
|
|
static bool
|
2020-05-02 16:46:47 +03:00
|
|
|
iris_resource_get_param(struct pipe_screen *pscreen,
|
2019-08-29 20:35:54 -04:00
|
|
|
struct pipe_context *context,
|
2019-08-02 01:21:12 -07:00
|
|
|
struct pipe_resource *resource,
|
2019-08-29 20:35:54 -04:00
|
|
|
unsigned plane,
|
|
|
|
|
unsigned layer,
|
2019-08-02 01:21:12 -07:00
|
|
|
enum pipe_resource_param param,
|
2019-08-29 20:35:54 -04:00
|
|
|
unsigned handle_usage,
|
2019-08-02 01:21:12 -07:00
|
|
|
uint64_t *value)
|
|
|
|
|
{
|
2020-05-02 16:46:47 +03:00
|
|
|
struct iris_screen *screen = (struct iris_screen *)pscreen;
|
2019-08-02 01:21:12 -07:00
|
|
|
struct iris_resource *res = (struct iris_resource *)resource;
|
|
|
|
|
bool mod_with_aux =
|
|
|
|
|
res->mod_info && res->mod_info->aux_usage != ISL_AUX_USAGE_NONE;
|
|
|
|
|
bool wants_aux = mod_with_aux && plane > 0;
|
|
|
|
|
bool result;
|
|
|
|
|
unsigned handle;
|
|
|
|
|
|
2019-10-14 15:55:18 -07:00
|
|
|
if (iris_resource_unfinished_aux_import(res))
|
2020-05-02 16:46:47 +03:00
|
|
|
iris_resource_finish_aux_import(pscreen, res);
|
2019-10-14 15:55:18 -07:00
|
|
|
|
|
|
|
|
struct iris_bo *bo = wants_aux ? res->aux.bo : res->bo;
|
|
|
|
|
|
2019-09-02 13:02:33 +03:00
|
|
|
iris_resource_disable_aux_on_first_query(resource, handle_usage);
|
|
|
|
|
|
2019-08-02 01:21:12 -07:00
|
|
|
switch (param) {
|
|
|
|
|
case PIPE_RESOURCE_PARAM_NPLANES:
|
2019-08-28 12:52:23 -07:00
|
|
|
if (mod_with_aux) {
|
|
|
|
|
*value = 2;
|
|
|
|
|
} else {
|
|
|
|
|
unsigned count = 0;
|
|
|
|
|
for (struct pipe_resource *cur = resource; cur; cur = cur->next)
|
|
|
|
|
count++;
|
|
|
|
|
*value = count;
|
|
|
|
|
}
|
2019-08-02 01:21:12 -07:00
|
|
|
return true;
|
|
|
|
|
case PIPE_RESOURCE_PARAM_STRIDE:
|
|
|
|
|
*value = wants_aux ? res->aux.surf.row_pitch_B : res->surf.row_pitch_B;
|
|
|
|
|
return true;
|
|
|
|
|
case PIPE_RESOURCE_PARAM_OFFSET:
|
|
|
|
|
*value = wants_aux ? res->aux.offset : 0;
|
|
|
|
|
return true;
|
|
|
|
|
case PIPE_RESOURCE_PARAM_MODIFIER:
|
|
|
|
|
*value = res->mod_info ? res->mod_info->modifier :
|
|
|
|
|
tiling_to_modifier(res->bo->tiling_mode);
|
|
|
|
|
return true;
|
|
|
|
|
case PIPE_RESOURCE_PARAM_HANDLE_TYPE_SHARED:
|
|
|
|
|
result = iris_bo_flink(bo, &handle) == 0;
|
|
|
|
|
if (result)
|
|
|
|
|
*value = handle;
|
|
|
|
|
return result;
|
2020-05-02 16:46:47 +03:00
|
|
|
case PIPE_RESOURCE_PARAM_HANDLE_TYPE_KMS: {
|
|
|
|
|
/* Because we share the same drm file across multiple iris_screen, when
|
|
|
|
|
* we export a GEM handle we must make sure it is valid in the DRM file
|
|
|
|
|
* descriptor the caller is using (this is the FD given at screen
|
|
|
|
|
* creation).
|
|
|
|
|
*/
|
|
|
|
|
uint32_t handle;
|
|
|
|
|
if (iris_bo_export_gem_handle_for_device(bo, screen->winsys_fd, &handle))
|
|
|
|
|
return false;
|
|
|
|
|
*value = handle;
|
2019-08-02 01:21:12 -07:00
|
|
|
return true;
|
2020-05-02 16:46:47 +03:00
|
|
|
}
|
|
|
|
|
|
2019-08-02 01:21:12 -07:00
|
|
|
case PIPE_RESOURCE_PARAM_HANDLE_TYPE_FD:
|
|
|
|
|
result = iris_bo_export_dmabuf(bo, (int *) &handle) == 0;
|
|
|
|
|
if (result)
|
|
|
|
|
*value = handle;
|
|
|
|
|
return result;
|
|
|
|
|
default:
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-04 11:41:41 -04:00
|
|
|
static bool
|
2017-11-23 23:15:14 -08:00
|
|
|
iris_resource_get_handle(struct pipe_screen *pscreen,
|
|
|
|
|
struct pipe_context *ctx,
|
|
|
|
|
struct pipe_resource *resource,
|
|
|
|
|
struct winsys_handle *whandle,
|
|
|
|
|
unsigned usage)
|
|
|
|
|
{
|
2020-05-02 16:46:47 +03:00
|
|
|
struct iris_screen *screen = (struct iris_screen *) pscreen;
|
2017-11-23 23:15:14 -08:00
|
|
|
struct iris_resource *res = (struct iris_resource *)resource;
|
2019-06-24 19:24:37 -07:00
|
|
|
bool mod_with_aux =
|
|
|
|
|
res->mod_info && res->mod_info->aux_usage != ISL_AUX_USAGE_NONE;
|
2017-11-23 23:15:14 -08:00
|
|
|
|
2019-09-02 13:02:33 +03:00
|
|
|
iris_resource_disable_aux_on_first_query(resource, usage);
|
2019-04-05 08:55:18 +03:00
|
|
|
|
2019-06-24 19:24:37 -07:00
|
|
|
struct iris_bo *bo;
|
|
|
|
|
if (mod_with_aux && whandle->plane > 0) {
|
|
|
|
|
assert(res->aux.bo);
|
|
|
|
|
bo = res->aux.bo;
|
|
|
|
|
whandle->stride = res->aux.surf.row_pitch_B;
|
|
|
|
|
whandle->offset = res->aux.offset;
|
|
|
|
|
} else {
|
|
|
|
|
/* If this is a buffer, stride should be 0 - no need to special case */
|
|
|
|
|
whandle->stride = res->surf.row_pitch_B;
|
|
|
|
|
bo = res->bo;
|
|
|
|
|
}
|
2019-11-15 09:17:23 -08:00
|
|
|
|
|
|
|
|
whandle->format = res->external_format;
|
2018-12-09 23:12:33 -08:00
|
|
|
whandle->modifier =
|
|
|
|
|
res->mod_info ? res->mod_info->modifier
|
|
|
|
|
: tiling_to_modifier(res->bo->tiling_mode);
|
|
|
|
|
|
2019-02-28 11:08:32 -08:00
|
|
|
#ifndef NDEBUG
|
|
|
|
|
enum isl_aux_usage allowed_usage =
|
|
|
|
|
res->mod_info ? res->mod_info->aux_usage : ISL_AUX_USAGE_NONE;
|
|
|
|
|
|
|
|
|
|
if (res->aux.usage != allowed_usage) {
|
|
|
|
|
enum isl_aux_state aux_state = iris_resource_get_aux_state(res, 0, 0);
|
|
|
|
|
assert(aux_state == ISL_AUX_STATE_RESOLVED ||
|
|
|
|
|
aux_state == ISL_AUX_STATE_PASS_THROUGH);
|
2018-12-09 23:12:33 -08:00
|
|
|
}
|
2019-02-28 11:08:32 -08:00
|
|
|
#endif
|
2017-11-23 23:15:14 -08:00
|
|
|
|
|
|
|
|
switch (whandle->type) {
|
|
|
|
|
case WINSYS_HANDLE_TYPE_SHARED:
|
2019-06-24 19:24:37 -07:00
|
|
|
return iris_bo_flink(bo, &whandle->handle) == 0;
|
2020-05-02 16:46:47 +03:00
|
|
|
case WINSYS_HANDLE_TYPE_KMS: {
|
|
|
|
|
/* Because we share the same drm file across multiple iris_screen, when
|
|
|
|
|
* we export a GEM handle we must make sure it is valid in the DRM file
|
|
|
|
|
* descriptor the caller is using (this is the FD given at screen
|
|
|
|
|
* creation).
|
|
|
|
|
*/
|
|
|
|
|
uint32_t handle;
|
|
|
|
|
if (iris_bo_export_gem_handle_for_device(bo, screen->winsys_fd, &handle))
|
|
|
|
|
return false;
|
|
|
|
|
whandle->handle = handle;
|
2018-11-13 17:55:45 +00:00
|
|
|
return true;
|
2020-05-02 16:46:47 +03:00
|
|
|
}
|
2017-11-23 23:15:14 -08:00
|
|
|
case WINSYS_HANDLE_TYPE_FD:
|
2019-06-24 19:24:37 -07:00
|
|
|
return iris_bo_export_dmabuf(bo, (int *) &whandle->handle) == 0;
|
2017-11-23 23:15:14 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2019-04-16 13:23:06 -07:00
|
|
|
static bool
|
|
|
|
|
resource_is_busy(struct iris_context *ice,
|
|
|
|
|
struct iris_resource *res)
|
|
|
|
|
{
|
|
|
|
|
bool busy = iris_bo_busy(res->bo);
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < IRIS_BATCH_COUNT; i++)
|
|
|
|
|
busy |= iris_batch_references(&ice->batches[i], res->bo);
|
|
|
|
|
|
|
|
|
|
return busy;
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-12 14:51:22 -07:00
|
|
|
static void
|
|
|
|
|
iris_invalidate_resource(struct pipe_context *ctx,
|
|
|
|
|
struct pipe_resource *resource)
|
|
|
|
|
{
|
|
|
|
|
struct iris_screen *screen = (void *) ctx->screen;
|
|
|
|
|
struct iris_context *ice = (void *) ctx;
|
|
|
|
|
struct iris_resource *res = (void *) resource;
|
|
|
|
|
|
|
|
|
|
if (resource->target != PIPE_BUFFER)
|
|
|
|
|
return;
|
|
|
|
|
|
2019-11-04 00:21:06 -08:00
|
|
|
/* If it's already invalidated, don't bother doing anything. */
|
|
|
|
|
if (res->valid_buffer_range.start > res->valid_buffer_range.end)
|
|
|
|
|
return;
|
|
|
|
|
|
2019-04-05 11:54:10 -07:00
|
|
|
if (!resource_is_busy(ice, res)) {
|
|
|
|
|
/* The resource is idle, so just mark that it contains no data and
|
|
|
|
|
* keep using the same underlying buffer object.
|
|
|
|
|
*/
|
|
|
|
|
util_range_set_empty(&res->valid_buffer_range);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Otherwise, try and replace the backing storage with a new BO. */
|
|
|
|
|
|
2019-03-12 14:51:22 -07:00
|
|
|
/* We can't reallocate memory we didn't allocate in the first place. */
|
|
|
|
|
if (res->bo->userptr)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
// XXX: We should support this.
|
|
|
|
|
if (res->bind_history & PIPE_BIND_STREAM_OUTPUT)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
struct iris_bo *old_bo = res->bo;
|
|
|
|
|
struct iris_bo *new_bo =
|
|
|
|
|
iris_bo_alloc(screen->bufmgr, res->bo->name, resource->width0,
|
|
|
|
|
iris_memzone_for_address(old_bo->gtt_offset));
|
|
|
|
|
if (!new_bo)
|
|
|
|
|
return;
|
|
|
|
|
|
2019-04-05 11:54:10 -07:00
|
|
|
/* Swap out the backing storage */
|
2019-03-12 14:51:22 -07:00
|
|
|
res->bo = new_bo;
|
2019-04-05 11:54:10 -07:00
|
|
|
|
|
|
|
|
/* Rebind the buffer, replacing any state referring to the old BO's
|
|
|
|
|
* address, and marking state dirty so it's reemitted.
|
|
|
|
|
*/
|
2020-03-30 10:37:29 -04:00
|
|
|
screen->vtbl.rebind_buffer(ice, res);
|
2019-04-05 11:54:10 -07:00
|
|
|
|
|
|
|
|
util_range_set_empty(&res->valid_buffer_range);
|
|
|
|
|
|
2019-03-12 14:51:22 -07:00
|
|
|
iris_bo_unreference(old_bo);
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-21 03:04:18 -08:00
|
|
|
static void
|
2019-04-06 23:35:49 -07:00
|
|
|
iris_flush_staging_region(struct pipe_transfer *xfer,
|
|
|
|
|
const struct pipe_box *flush_box)
|
2018-12-21 03:04:18 -08:00
|
|
|
{
|
2019-04-06 23:35:49 -07:00
|
|
|
if (!(xfer->usage & PIPE_TRANSFER_WRITE))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
struct iris_transfer *map = (void *) xfer;
|
|
|
|
|
|
|
|
|
|
struct pipe_box src_box = *flush_box;
|
|
|
|
|
|
|
|
|
|
/* Account for extra alignment padding in staging buffer */
|
|
|
|
|
if (xfer->resource->target == PIPE_BUFFER)
|
|
|
|
|
src_box.x += xfer->box.x % IRIS_MAP_BUFFER_ALIGNMENT;
|
|
|
|
|
|
|
|
|
|
struct pipe_box dst_box = (struct pipe_box) {
|
|
|
|
|
.x = xfer->box.x + flush_box->x,
|
|
|
|
|
.y = xfer->box.y + flush_box->y,
|
|
|
|
|
.z = xfer->box.z + flush_box->z,
|
|
|
|
|
.width = flush_box->width,
|
|
|
|
|
.height = flush_box->height,
|
|
|
|
|
.depth = flush_box->depth,
|
2018-12-21 03:04:18 -08:00
|
|
|
};
|
|
|
|
|
|
2019-04-06 23:35:49 -07:00
|
|
|
iris_copy_region(map->blorp, map->batch, xfer->resource, xfer->level,
|
|
|
|
|
dst_box.x, dst_box.y, dst_box.z, map->staging, 0,
|
|
|
|
|
&src_box);
|
|
|
|
|
}
|
2018-12-21 03:04:18 -08:00
|
|
|
|
2019-04-06 23:35:49 -07:00
|
|
|
static void
|
|
|
|
|
iris_unmap_copy_region(struct iris_transfer *map)
|
|
|
|
|
{
|
2018-12-21 03:04:18 -08:00
|
|
|
iris_resource_destroy(map->staging->screen, map->staging);
|
|
|
|
|
|
|
|
|
|
map->ptr = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
iris_map_copy_region(struct iris_transfer *map)
|
|
|
|
|
{
|
|
|
|
|
struct pipe_screen *pscreen = &map->batch->screen->base;
|
|
|
|
|
struct pipe_transfer *xfer = &map->base;
|
|
|
|
|
struct pipe_box *box = &xfer->box;
|
|
|
|
|
struct iris_resource *res = (void *) xfer->resource;
|
|
|
|
|
|
|
|
|
|
unsigned extra = xfer->resource->target == PIPE_BUFFER ?
|
|
|
|
|
box->x % IRIS_MAP_BUFFER_ALIGNMENT : 0;
|
|
|
|
|
|
|
|
|
|
struct pipe_resource templ = (struct pipe_resource) {
|
|
|
|
|
.usage = PIPE_USAGE_STAGING,
|
|
|
|
|
.width0 = box->width + extra,
|
|
|
|
|
.height0 = box->height,
|
|
|
|
|
.depth0 = 1,
|
|
|
|
|
.nr_samples = xfer->resource->nr_samples,
|
|
|
|
|
.nr_storage_samples = xfer->resource->nr_storage_samples,
|
|
|
|
|
.array_size = box->depth,
|
2019-04-23 20:19:37 -07:00
|
|
|
.format = res->internal_format,
|
2018-12-21 03:04:18 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (xfer->resource->target == PIPE_BUFFER)
|
|
|
|
|
templ.target = PIPE_BUFFER;
|
|
|
|
|
else if (templ.array_size > 1)
|
|
|
|
|
templ.target = PIPE_TEXTURE_2D_ARRAY;
|
|
|
|
|
else
|
|
|
|
|
templ.target = PIPE_TEXTURE_2D;
|
|
|
|
|
|
|
|
|
|
map->staging = iris_resource_create(pscreen, &templ);
|
|
|
|
|
assert(map->staging);
|
|
|
|
|
|
|
|
|
|
if (templ.target != PIPE_BUFFER) {
|
|
|
|
|
struct isl_surf *surf = &((struct iris_resource *) map->staging)->surf;
|
|
|
|
|
xfer->stride = isl_surf_get_row_pitch_B(surf);
|
|
|
|
|
xfer->layer_stride = isl_surf_get_array_pitch(surf);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!(xfer->usage & PIPE_TRANSFER_DISCARD_RANGE)) {
|
|
|
|
|
iris_copy_region(map->blorp, map->batch, map->staging, 0, extra, 0, 0,
|
|
|
|
|
xfer->resource, xfer->level, box);
|
|
|
|
|
/* Ensure writes to the staging BO land before we map it below. */
|
|
|
|
|
iris_emit_pipe_control_flush(map->batch,
|
2019-06-19 16:04:50 -05:00
|
|
|
"transfer read: flush before mapping",
|
2018-12-21 03:04:18 -08:00
|
|
|
PIPE_CONTROL_RENDER_TARGET_FLUSH |
|
|
|
|
|
PIPE_CONTROL_CS_STALL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct iris_bo *staging_bo = iris_resource_bo(map->staging);
|
|
|
|
|
|
|
|
|
|
if (iris_batch_references(map->batch, staging_bo))
|
|
|
|
|
iris_batch_flush(map->batch);
|
|
|
|
|
|
2019-04-08 00:45:41 -07:00
|
|
|
map->ptr =
|
|
|
|
|
iris_bo_map(map->dbg, staging_bo, xfer->usage & MAP_FLAGS) + extra;
|
2018-12-21 03:04:18 -08:00
|
|
|
|
|
|
|
|
map->unmap = iris_unmap_copy_region;
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-07 09:21:40 -07:00
|
|
|
static void
|
2019-03-14 01:19:59 -07:00
|
|
|
get_image_offset_el(const struct isl_surf *surf, unsigned level, unsigned z,
|
2018-08-07 09:21:40 -07:00
|
|
|
unsigned *out_x0_el, unsigned *out_y0_el)
|
|
|
|
|
{
|
|
|
|
|
if (surf->dim == ISL_SURF_DIM_3D) {
|
|
|
|
|
isl_surf_get_image_offset_el(surf, level, 0, z, out_x0_el, out_y0_el);
|
|
|
|
|
} else {
|
|
|
|
|
isl_surf_get_image_offset_el(surf, level, z, 0, out_x0_el, out_y0_el);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-16 10:48:19 -07:00
|
|
|
/**
|
|
|
|
|
* This function computes the tile_w (in bytes) and tile_h (in rows) of
|
|
|
|
|
* different tiling patterns.
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
iris_resource_get_tile_dims(enum isl_tiling tiling, uint32_t cpp,
|
|
|
|
|
uint32_t *tile_w, uint32_t *tile_h)
|
|
|
|
|
{
|
|
|
|
|
switch (tiling) {
|
|
|
|
|
case ISL_TILING_X:
|
|
|
|
|
*tile_w = 512;
|
|
|
|
|
*tile_h = 8;
|
|
|
|
|
break;
|
|
|
|
|
case ISL_TILING_Y0:
|
|
|
|
|
*tile_w = 128;
|
|
|
|
|
*tile_h = 32;
|
|
|
|
|
break;
|
|
|
|
|
case ISL_TILING_LINEAR:
|
|
|
|
|
*tile_w = cpp;
|
|
|
|
|
*tile_h = 1;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
unreachable("not reached");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* This function computes masks that may be used to select the bits of the X
|
|
|
|
|
* and Y coordinates that indicate the offset within a tile. If the BO is
|
|
|
|
|
* untiled, the masks are set to 0.
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
iris_resource_get_tile_masks(enum isl_tiling tiling, uint32_t cpp,
|
|
|
|
|
uint32_t *mask_x, uint32_t *mask_y)
|
|
|
|
|
{
|
|
|
|
|
uint32_t tile_w_bytes, tile_h;
|
|
|
|
|
|
|
|
|
|
iris_resource_get_tile_dims(tiling, cpp, &tile_w_bytes, &tile_h);
|
|
|
|
|
|
|
|
|
|
*mask_x = tile_w_bytes / cpp - 1;
|
|
|
|
|
*mask_y = tile_h - 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Compute the offset (in bytes) from the start of the BO to the given x
|
|
|
|
|
* and y coordinate. For tiled BOs, caller must ensure that x and y are
|
|
|
|
|
* multiples of the tile size.
|
|
|
|
|
*/
|
|
|
|
|
static uint32_t
|
|
|
|
|
iris_resource_get_aligned_offset(const struct iris_resource *res,
|
|
|
|
|
uint32_t x, uint32_t y)
|
|
|
|
|
{
|
|
|
|
|
const struct isl_format_layout *fmtl = isl_format_get_layout(res->surf.format);
|
|
|
|
|
unsigned cpp = fmtl->bpb / 8;
|
|
|
|
|
uint32_t pitch = res->surf.row_pitch_B;
|
|
|
|
|
|
|
|
|
|
switch (res->surf.tiling) {
|
|
|
|
|
default:
|
|
|
|
|
unreachable("not reached");
|
|
|
|
|
case ISL_TILING_LINEAR:
|
|
|
|
|
return y * pitch + x * cpp;
|
|
|
|
|
case ISL_TILING_X:
|
|
|
|
|
assert((x % (512 / cpp)) == 0);
|
|
|
|
|
assert((y % 8) == 0);
|
|
|
|
|
return y * pitch + x / (512 / cpp) * 4096;
|
|
|
|
|
case ISL_TILING_Y0:
|
|
|
|
|
assert((x % (128 / cpp)) == 0);
|
|
|
|
|
assert((y % 32) == 0);
|
|
|
|
|
return y * pitch + x / (128 / cpp) * 4096;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Rendering with tiled buffers requires that the base address of the buffer
|
|
|
|
|
* be aligned to a page boundary. For renderbuffers, and sometimes with
|
|
|
|
|
* textures, we may want the surface to point at a texture image level that
|
|
|
|
|
* isn't at a page boundary.
|
|
|
|
|
*
|
|
|
|
|
* This function returns an appropriately-aligned base offset
|
|
|
|
|
* according to the tiling restrictions, plus any required x/y offset
|
|
|
|
|
* from there.
|
|
|
|
|
*/
|
|
|
|
|
uint32_t
|
|
|
|
|
iris_resource_get_tile_offsets(const struct iris_resource *res,
|
|
|
|
|
uint32_t level, uint32_t z,
|
|
|
|
|
uint32_t *tile_x, uint32_t *tile_y)
|
|
|
|
|
{
|
|
|
|
|
uint32_t x, y;
|
|
|
|
|
uint32_t mask_x, mask_y;
|
|
|
|
|
|
|
|
|
|
const struct isl_format_layout *fmtl = isl_format_get_layout(res->surf.format);
|
|
|
|
|
const unsigned cpp = fmtl->bpb / 8;
|
|
|
|
|
|
|
|
|
|
iris_resource_get_tile_masks(res->surf.tiling, cpp, &mask_x, &mask_y);
|
|
|
|
|
get_image_offset_el(&res->surf, level, z, &x, &y);
|
|
|
|
|
|
|
|
|
|
*tile_x = x & mask_x;
|
|
|
|
|
*tile_y = y & mask_y;
|
|
|
|
|
|
|
|
|
|
return iris_resource_get_aligned_offset(res, x & ~mask_x, y & ~mask_y);
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-07 09:21:40 -07:00
|
|
|
/**
|
|
|
|
|
* Get pointer offset into stencil buffer.
|
|
|
|
|
*
|
|
|
|
|
* The stencil buffer is W tiled. Since the GTT is incapable of W fencing, we
|
|
|
|
|
* must decode the tile's layout in software.
|
|
|
|
|
*
|
|
|
|
|
* See
|
|
|
|
|
* - PRM, 2011 Sandy Bridge, Volume 1, Part 2, Section 4.5.2.1 W-Major Tile
|
|
|
|
|
* Format.
|
|
|
|
|
* - PRM, 2011 Sandy Bridge, Volume 1, Part 2, Section 4.5.3 Tiling Algorithm
|
|
|
|
|
*
|
|
|
|
|
* Even though the returned offset is always positive, the return type is
|
|
|
|
|
* signed due to
|
|
|
|
|
* commit e8b1c6d6f55f5be3bef25084fdd8b6127517e137
|
|
|
|
|
* mesa: Fix return type of _mesa_get_format_bytes() (#37351)
|
|
|
|
|
*/
|
|
|
|
|
static intptr_t
|
2019-04-23 22:18:11 -07:00
|
|
|
s8_offset(uint32_t stride, uint32_t x, uint32_t y)
|
2018-08-07 09:21:40 -07:00
|
|
|
{
|
|
|
|
|
uint32_t tile_size = 4096;
|
|
|
|
|
uint32_t tile_width = 64;
|
|
|
|
|
uint32_t tile_height = 64;
|
|
|
|
|
uint32_t row_size = 64 * stride / 2; /* Two rows are interleaved. */
|
|
|
|
|
|
|
|
|
|
uint32_t tile_x = x / tile_width;
|
|
|
|
|
uint32_t tile_y = y / tile_height;
|
|
|
|
|
|
|
|
|
|
/* The byte's address relative to the tile's base addres. */
|
|
|
|
|
uint32_t byte_x = x % tile_width;
|
|
|
|
|
uint32_t byte_y = y % tile_height;
|
|
|
|
|
|
|
|
|
|
uintptr_t u = tile_y * row_size
|
|
|
|
|
+ tile_x * tile_size
|
|
|
|
|
+ 512 * (byte_x / 8)
|
|
|
|
|
+ 64 * (byte_y / 8)
|
|
|
|
|
+ 32 * ((byte_y / 4) % 2)
|
|
|
|
|
+ 16 * ((byte_x / 4) % 2)
|
|
|
|
|
+ 8 * ((byte_y / 2) % 2)
|
|
|
|
|
+ 4 * ((byte_x / 2) % 2)
|
|
|
|
|
+ 2 * (byte_y % 2)
|
|
|
|
|
+ 1 * (byte_x % 2);
|
|
|
|
|
|
|
|
|
|
return u;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
iris_unmap_s8(struct iris_transfer *map)
|
|
|
|
|
{
|
|
|
|
|
struct pipe_transfer *xfer = &map->base;
|
2019-03-13 15:35:28 -07:00
|
|
|
const struct pipe_box *box = &xfer->box;
|
2018-08-07 09:21:40 -07:00
|
|
|
struct iris_resource *res = (struct iris_resource *) xfer->resource;
|
|
|
|
|
struct isl_surf *surf = &res->surf;
|
|
|
|
|
|
|
|
|
|
if (xfer->usage & PIPE_TRANSFER_WRITE) {
|
|
|
|
|
uint8_t *untiled_s8_map = map->ptr;
|
|
|
|
|
uint8_t *tiled_s8_map =
|
2019-04-08 00:45:41 -07:00
|
|
|
iris_bo_map(map->dbg, res->bo, (xfer->usage | MAP_RAW) & MAP_FLAGS);
|
2018-08-07 09:21:40 -07:00
|
|
|
|
2019-03-13 15:35:28 -07:00
|
|
|
for (int s = 0; s < box->depth; s++) {
|
2018-08-07 09:21:40 -07:00
|
|
|
unsigned x0_el, y0_el;
|
2019-03-13 15:35:28 -07:00
|
|
|
get_image_offset_el(surf, xfer->level, box->z + s, &x0_el, &y0_el);
|
2018-08-07 09:21:40 -07:00
|
|
|
|
2019-03-13 15:35:28 -07:00
|
|
|
for (uint32_t y = 0; y < box->height; y++) {
|
|
|
|
|
for (uint32_t x = 0; x < box->width; x++) {
|
2018-08-07 09:21:40 -07:00
|
|
|
ptrdiff_t offset = s8_offset(surf->row_pitch_B,
|
2019-03-13 15:35:28 -07:00
|
|
|
x0_el + box->x + x,
|
2019-04-23 22:18:11 -07:00
|
|
|
y0_el + box->y + y);
|
2018-08-07 09:21:40 -07:00
|
|
|
tiled_s8_map[offset] =
|
|
|
|
|
untiled_s8_map[s * xfer->layer_stride + y * xfer->stride + x];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
free(map->buffer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
iris_map_s8(struct iris_transfer *map)
|
|
|
|
|
{
|
|
|
|
|
struct pipe_transfer *xfer = &map->base;
|
2019-03-13 15:35:28 -07:00
|
|
|
const struct pipe_box *box = &xfer->box;
|
2018-08-07 09:21:40 -07:00
|
|
|
struct iris_resource *res = (struct iris_resource *) xfer->resource;
|
|
|
|
|
struct isl_surf *surf = &res->surf;
|
|
|
|
|
|
|
|
|
|
xfer->stride = surf->row_pitch_B;
|
2019-03-13 15:35:28 -07:00
|
|
|
xfer->layer_stride = xfer->stride * box->height;
|
2018-08-07 09:21:40 -07:00
|
|
|
|
|
|
|
|
/* The tiling and detiling functions require that the linear buffer has
|
|
|
|
|
* a 16-byte alignment (that is, its `x0` is 16-byte aligned). Here we
|
|
|
|
|
* over-allocate the linear buffer to get the proper alignment.
|
|
|
|
|
*/
|
2019-03-13 15:35:28 -07:00
|
|
|
map->buffer = map->ptr = malloc(xfer->layer_stride * box->depth);
|
2018-08-07 09:21:40 -07:00
|
|
|
assert(map->buffer);
|
|
|
|
|
|
|
|
|
|
/* One of either READ_BIT or WRITE_BIT or both is set. READ_BIT implies no
|
|
|
|
|
* INVALIDATE_RANGE_BIT. WRITE_BIT needs the original values read in unless
|
|
|
|
|
* invalidate is set, since we'll be writing the whole rectangle from our
|
|
|
|
|
* temporary buffer back out.
|
|
|
|
|
*/
|
|
|
|
|
if (!(xfer->usage & PIPE_TRANSFER_DISCARD_RANGE)) {
|
|
|
|
|
uint8_t *untiled_s8_map = map->ptr;
|
|
|
|
|
uint8_t *tiled_s8_map =
|
2019-04-08 00:45:41 -07:00
|
|
|
iris_bo_map(map->dbg, res->bo, (xfer->usage | MAP_RAW) & MAP_FLAGS);
|
2018-08-07 09:21:40 -07:00
|
|
|
|
2019-03-13 15:35:28 -07:00
|
|
|
for (int s = 0; s < box->depth; s++) {
|
2018-08-07 09:21:40 -07:00
|
|
|
unsigned x0_el, y0_el;
|
2019-03-13 15:35:28 -07:00
|
|
|
get_image_offset_el(surf, xfer->level, box->z + s, &x0_el, &y0_el);
|
2018-08-07 09:21:40 -07:00
|
|
|
|
2019-03-13 15:35:28 -07:00
|
|
|
for (uint32_t y = 0; y < box->height; y++) {
|
|
|
|
|
for (uint32_t x = 0; x < box->width; x++) {
|
2018-08-07 09:21:40 -07:00
|
|
|
ptrdiff_t offset = s8_offset(surf->row_pitch_B,
|
2019-03-13 15:35:28 -07:00
|
|
|
x0_el + box->x + x,
|
2019-04-23 22:18:11 -07:00
|
|
|
y0_el + box->y + y);
|
2018-08-07 09:21:40 -07:00
|
|
|
untiled_s8_map[s * xfer->layer_stride + y * xfer->stride + x] =
|
|
|
|
|
tiled_s8_map[offset];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
map->unmap = iris_unmap_s8;
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-28 17:14:43 -07:00
|
|
|
/* Compute extent parameters for use with tiled_memcpy functions.
|
|
|
|
|
* xs are in units of bytes and ys are in units of strides.
|
|
|
|
|
*/
|
|
|
|
|
static inline void
|
2019-03-14 01:19:59 -07:00
|
|
|
tile_extents(const struct isl_surf *surf,
|
2018-05-28 17:14:43 -07:00
|
|
|
const struct pipe_box *box,
|
2019-03-13 15:35:28 -07:00
|
|
|
unsigned level, int z,
|
2018-08-07 09:21:40 -07:00
|
|
|
unsigned *x1_B, unsigned *x2_B,
|
|
|
|
|
unsigned *y1_el, unsigned *y2_el)
|
2018-05-28 17:14:43 -07:00
|
|
|
{
|
|
|
|
|
const struct isl_format_layout *fmtl = isl_format_get_layout(surf->format);
|
|
|
|
|
const unsigned cpp = fmtl->bpb / 8;
|
|
|
|
|
|
|
|
|
|
assert(box->x % fmtl->bw == 0);
|
|
|
|
|
assert(box->y % fmtl->bh == 0);
|
|
|
|
|
|
|
|
|
|
unsigned x0_el, y0_el;
|
2019-03-13 15:35:28 -07:00
|
|
|
get_image_offset_el(surf, level, box->z + z, &x0_el, &y0_el);
|
2018-05-28 17:14:43 -07:00
|
|
|
|
|
|
|
|
*x1_B = (box->x / fmtl->bw + x0_el) * cpp;
|
|
|
|
|
*y1_el = box->y / fmtl->bh + y0_el;
|
|
|
|
|
*x2_B = (DIV_ROUND_UP(box->x + box->width, fmtl->bw) + x0_el) * cpp;
|
|
|
|
|
*y2_el = DIV_ROUND_UP(box->y + box->height, fmtl->bh) + y0_el;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
iris_unmap_tiled_memcpy(struct iris_transfer *map)
|
|
|
|
|
{
|
|
|
|
|
struct pipe_transfer *xfer = &map->base;
|
2019-03-13 15:35:28 -07:00
|
|
|
const struct pipe_box *box = &xfer->box;
|
2018-05-28 17:14:43 -07:00
|
|
|
struct iris_resource *res = (struct iris_resource *) xfer->resource;
|
|
|
|
|
struct isl_surf *surf = &res->surf;
|
|
|
|
|
|
2018-10-15 19:25:24 -07:00
|
|
|
const bool has_swizzling = false;
|
2018-05-28 17:14:43 -07:00
|
|
|
|
|
|
|
|
if (xfer->usage & PIPE_TRANSFER_WRITE) {
|
2019-04-08 00:45:41 -07:00
|
|
|
char *dst =
|
|
|
|
|
iris_bo_map(map->dbg, res->bo, (xfer->usage | MAP_RAW) & MAP_FLAGS);
|
2018-05-28 17:14:43 -07:00
|
|
|
|
2019-03-13 15:35:28 -07:00
|
|
|
for (int s = 0; s < box->depth; s++) {
|
2018-08-07 09:21:40 -07:00
|
|
|
unsigned x1, x2, y1, y2;
|
2019-03-13 15:35:28 -07:00
|
|
|
tile_extents(surf, box, xfer->level, s, &x1, &x2, &y1, &y2);
|
2018-07-12 14:44:55 -07:00
|
|
|
|
2018-08-14 16:44:07 -07:00
|
|
|
void *ptr = map->ptr + s * xfer->layer_stride;
|
2018-07-12 14:44:55 -07:00
|
|
|
|
|
|
|
|
isl_memcpy_linear_to_tiled(x1, x2, y1, y2, dst, ptr,
|
|
|
|
|
surf->row_pitch_B, xfer->stride,
|
|
|
|
|
has_swizzling, surf->tiling, ISL_MEMCPY);
|
|
|
|
|
}
|
2018-05-28 17:14:43 -07:00
|
|
|
}
|
|
|
|
|
os_free_aligned(map->buffer);
|
|
|
|
|
map->buffer = map->ptr = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
iris_map_tiled_memcpy(struct iris_transfer *map)
|
|
|
|
|
{
|
|
|
|
|
struct pipe_transfer *xfer = &map->base;
|
2019-03-13 15:35:28 -07:00
|
|
|
const struct pipe_box *box = &xfer->box;
|
2018-05-28 17:14:43 -07:00
|
|
|
struct iris_resource *res = (struct iris_resource *) xfer->resource;
|
|
|
|
|
struct isl_surf *surf = &res->surf;
|
|
|
|
|
|
2018-07-12 14:44:55 -07:00
|
|
|
xfer->stride = ALIGN(surf->row_pitch_B, 16);
|
2019-03-13 15:35:28 -07:00
|
|
|
xfer->layer_stride = xfer->stride * box->height;
|
2018-07-12 14:44:55 -07:00
|
|
|
|
2018-06-24 00:27:58 -07:00
|
|
|
unsigned x1, x2, y1, y2;
|
2019-03-13 15:35:28 -07:00
|
|
|
tile_extents(surf, box, xfer->level, 0, &x1, &x2, &y1, &y2);
|
2018-05-28 17:14:43 -07:00
|
|
|
|
|
|
|
|
/* The tiling and detiling functions require that the linear buffer has
|
|
|
|
|
* a 16-byte alignment (that is, its `x0` is 16-byte aligned). Here we
|
|
|
|
|
* over-allocate the linear buffer to get the proper alignment.
|
|
|
|
|
*/
|
2018-07-03 23:44:40 -07:00
|
|
|
map->buffer =
|
2019-03-13 15:35:28 -07:00
|
|
|
os_malloc_aligned(xfer->layer_stride * box->depth, 16);
|
2018-05-28 17:14:43 -07:00
|
|
|
assert(map->buffer);
|
2018-07-12 14:44:55 -07:00
|
|
|
map->ptr = (char *)map->buffer + (x1 & 0xf);
|
2018-05-28 17:14:43 -07:00
|
|
|
|
2018-10-15 19:25:24 -07:00
|
|
|
const bool has_swizzling = false;
|
2018-05-28 17:14:43 -07:00
|
|
|
|
|
|
|
|
if (!(xfer->usage & PIPE_TRANSFER_DISCARD_RANGE)) {
|
2019-04-08 00:45:41 -07:00
|
|
|
char *src =
|
|
|
|
|
iris_bo_map(map->dbg, res->bo, (xfer->usage | MAP_RAW) & MAP_FLAGS);
|
2018-05-28 17:14:43 -07:00
|
|
|
|
2019-03-13 15:35:28 -07:00
|
|
|
for (int s = 0; s < box->depth; s++) {
|
2018-08-07 09:21:40 -07:00
|
|
|
unsigned x1, x2, y1, y2;
|
2019-03-13 15:35:28 -07:00
|
|
|
tile_extents(surf, box, xfer->level, s, &x1, &x2, &y1, &y2);
|
2018-07-12 14:44:55 -07:00
|
|
|
|
2019-03-13 15:35:28 -07:00
|
|
|
/* Use 's' rather than 'box->z' to rebase the first slice to 0. */
|
2018-08-14 16:44:07 -07:00
|
|
|
void *ptr = map->ptr + s * xfer->layer_stride;
|
|
|
|
|
|
|
|
|
|
isl_memcpy_tiled_to_linear(x1, x2, y1, y2, ptr, src, xfer->stride,
|
|
|
|
|
surf->row_pitch_B, has_swizzling,
|
2019-02-22 20:53:41 +00:00
|
|
|
surf->tiling, ISL_MEMCPY_STREAMING_LOAD);
|
2018-07-12 14:44:55 -07:00
|
|
|
}
|
2018-05-28 17:14:43 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
map->unmap = iris_unmap_tiled_memcpy;
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-24 00:27:58 -07:00
|
|
|
static void
|
|
|
|
|
iris_map_direct(struct iris_transfer *map)
|
|
|
|
|
{
|
|
|
|
|
struct pipe_transfer *xfer = &map->base;
|
|
|
|
|
struct pipe_box *box = &xfer->box;
|
|
|
|
|
struct iris_resource *res = (struct iris_resource *) xfer->resource;
|
2018-08-23 02:36:18 -07:00
|
|
|
|
2019-04-08 00:45:41 -07:00
|
|
|
void *ptr = iris_bo_map(map->dbg, res->bo, xfer->usage & MAP_FLAGS);
|
2018-06-24 00:27:58 -07:00
|
|
|
|
2018-11-10 02:25:24 -08:00
|
|
|
if (res->base.target == PIPE_BUFFER) {
|
|
|
|
|
xfer->stride = 0;
|
|
|
|
|
xfer->layer_stride = 0;
|
2018-07-12 14:44:55 -07:00
|
|
|
|
2018-11-10 02:25:24 -08:00
|
|
|
map->ptr = ptr + box->x;
|
|
|
|
|
} else {
|
2018-11-29 22:23:34 -08:00
|
|
|
struct isl_surf *surf = &res->surf;
|
|
|
|
|
const struct isl_format_layout *fmtl =
|
|
|
|
|
isl_format_get_layout(surf->format);
|
|
|
|
|
const unsigned cpp = fmtl->bpb / 8;
|
|
|
|
|
unsigned x0_el, y0_el;
|
|
|
|
|
|
2018-11-10 02:25:24 -08:00
|
|
|
get_image_offset_el(surf, xfer->level, box->z, &x0_el, &y0_el);
|
2018-06-24 00:27:58 -07:00
|
|
|
|
2018-11-10 02:25:24 -08:00
|
|
|
xfer->stride = isl_surf_get_row_pitch_B(surf);
|
|
|
|
|
xfer->layer_stride = isl_surf_get_array_pitch(surf);
|
|
|
|
|
|
|
|
|
|
map->ptr = ptr + (y0_el + box->y) * xfer->stride + (x0_el + box->x) * cpp;
|
|
|
|
|
}
|
2018-06-24 00:27:58 -07:00
|
|
|
}
|
|
|
|
|
|
2019-04-05 11:54:10 -07:00
|
|
|
static bool
|
|
|
|
|
can_promote_to_async(const struct iris_resource *res,
|
|
|
|
|
const struct pipe_box *box,
|
|
|
|
|
enum pipe_transfer_usage usage)
|
|
|
|
|
{
|
|
|
|
|
/* If we're writing to a section of the buffer that hasn't even been
|
|
|
|
|
* initialized with useful data, then we can safely promote this write
|
|
|
|
|
* to be unsynchronized. This helps the common pattern of appending data.
|
|
|
|
|
*/
|
|
|
|
|
return res->base.target == PIPE_BUFFER && (usage & PIPE_TRANSFER_WRITE) &&
|
|
|
|
|
!(usage & TC_TRANSFER_MAP_NO_INFER_UNSYNCHRONIZED) &&
|
|
|
|
|
!util_ranges_intersect(&res->valid_buffer_range, box->x,
|
|
|
|
|
box->x + box->width);
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-19 18:57:30 -08:00
|
|
|
static void *
|
|
|
|
|
iris_transfer_map(struct pipe_context *ctx,
|
|
|
|
|
struct pipe_resource *resource,
|
|
|
|
|
unsigned level,
|
|
|
|
|
enum pipe_transfer_usage usage,
|
|
|
|
|
const struct pipe_box *box,
|
|
|
|
|
struct pipe_transfer **ptransfer)
|
|
|
|
|
{
|
|
|
|
|
struct iris_context *ice = (struct iris_context *)ctx;
|
|
|
|
|
struct iris_resource *res = (struct iris_resource *)resource;
|
2018-05-28 17:14:43 -07:00
|
|
|
struct isl_surf *surf = &res->surf;
|
|
|
|
|
|
2020-04-21 12:25:44 +03:00
|
|
|
if (iris_resource_unfinished_aux_import(res))
|
|
|
|
|
iris_resource_finish_aux_import(ctx->screen, res);
|
|
|
|
|
|
2019-03-12 14:51:22 -07:00
|
|
|
if (usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE) {
|
|
|
|
|
/* Replace the backing storage with a fresh buffer for non-async maps */
|
|
|
|
|
if (!(usage & (PIPE_TRANSFER_UNSYNCHRONIZED |
|
|
|
|
|
TC_TRANSFER_MAP_NO_INVALIDATE)))
|
|
|
|
|
iris_invalidate_resource(ctx, resource);
|
|
|
|
|
|
|
|
|
|
/* If we can discard the whole resource, we can discard the range. */
|
|
|
|
|
usage |= PIPE_TRANSFER_DISCARD_RANGE;
|
|
|
|
|
}
|
2018-12-31 22:03:35 -08:00
|
|
|
|
2019-04-05 11:54:10 -07:00
|
|
|
if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED) &&
|
|
|
|
|
can_promote_to_async(res, box, usage)) {
|
|
|
|
|
usage |= PIPE_TRANSFER_UNSYNCHRONIZED;
|
|
|
|
|
}
|
|
|
|
|
|
2019-04-26 10:44:18 -07:00
|
|
|
bool need_resolve = false;
|
|
|
|
|
bool need_color_resolve = false;
|
|
|
|
|
|
|
|
|
|
if (resource->target != PIPE_BUFFER) {
|
|
|
|
|
bool need_hiz_resolve = iris_resource_level_has_hiz(res, level);
|
2020-03-05 11:46:51 -06:00
|
|
|
bool need_stencil_resolve = res->aux.usage == ISL_AUX_USAGE_STC_CCS;
|
2019-04-26 10:44:18 -07:00
|
|
|
|
|
|
|
|
need_color_resolve =
|
|
|
|
|
(res->aux.usage == ISL_AUX_USAGE_CCS_D ||
|
2020-06-04 16:42:20 -07:00
|
|
|
res->aux.usage == ISL_AUX_USAGE_CCS_E ||
|
|
|
|
|
res->aux.usage == ISL_AUX_USAGE_GEN12_CCS_E) &&
|
2019-04-26 10:44:18 -07:00
|
|
|
iris_has_color_unresolved(res, level, 1, box->z, box->depth);
|
|
|
|
|
|
2020-03-05 11:46:51 -06:00
|
|
|
need_resolve = need_color_resolve ||
|
|
|
|
|
need_hiz_resolve ||
|
|
|
|
|
need_stencil_resolve;
|
2019-04-26 10:44:18 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool map_would_stall = false;
|
|
|
|
|
|
2018-11-20 09:00:22 -08:00
|
|
|
if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) {
|
2019-04-26 10:44:18 -07:00
|
|
|
map_would_stall = need_resolve || resource_is_busy(ice, res);
|
2018-12-21 03:04:18 -08:00
|
|
|
|
|
|
|
|
if (map_would_stall && (usage & PIPE_TRANSFER_DONTBLOCK) &&
|
|
|
|
|
(usage & PIPE_TRANSFER_MAP_DIRECTLY))
|
|
|
|
|
return NULL;
|
2018-09-18 15:04:14 -07:00
|
|
|
}
|
|
|
|
|
|
2018-12-21 03:04:18 -08:00
|
|
|
if (surf->tiling != ISL_TILING_LINEAR &&
|
|
|
|
|
(usage & PIPE_TRANSFER_MAP_DIRECTLY))
|
2018-06-19 19:22:47 -07:00
|
|
|
return NULL;
|
|
|
|
|
|
2018-07-06 11:29:51 -07:00
|
|
|
struct iris_transfer *map = slab_alloc(&ice->transfer_pool);
|
2018-05-28 17:14:43 -07:00
|
|
|
struct pipe_transfer *xfer = &map->base;
|
2018-01-19 18:57:30 -08:00
|
|
|
|
2018-05-28 17:14:43 -07:00
|
|
|
if (!map)
|
2018-01-19 18:57:30 -08:00
|
|
|
return NULL;
|
|
|
|
|
|
2018-07-06 11:29:51 -07:00
|
|
|
memset(map, 0, sizeof(*map));
|
2018-05-28 17:14:43 -07:00
|
|
|
map->dbg = &ice->dbg;
|
|
|
|
|
|
|
|
|
|
pipe_resource_reference(&xfer->resource, resource);
|
|
|
|
|
xfer->level = level;
|
|
|
|
|
xfer->usage = usage;
|
|
|
|
|
xfer->box = *box;
|
|
|
|
|
*ptransfer = xfer;
|
2018-01-19 18:57:30 -08:00
|
|
|
|
2019-09-07 22:51:15 -07:00
|
|
|
map->dest_had_defined_contents =
|
|
|
|
|
util_ranges_intersect(&res->valid_buffer_range, box->x,
|
|
|
|
|
box->x + box->width);
|
|
|
|
|
|
2019-04-05 11:54:10 -07:00
|
|
|
if (usage & PIPE_TRANSFER_WRITE)
|
2019-09-25 21:38:40 -04:00
|
|
|
util_range_add(&res->base, &res->valid_buffer_range, box->x, box->x + box->width);
|
2019-04-05 11:54:10 -07:00
|
|
|
|
2018-12-21 03:04:18 -08:00
|
|
|
/* Avoid using GPU copies for persistent/coherent buffers, as the idea
|
|
|
|
|
* there is to access them simultaneously on the CPU & GPU. This also
|
|
|
|
|
* avoids trying to use GPU copies for our u_upload_mgr buffers which
|
|
|
|
|
* contain state we're constructing for a GPU draw call, which would
|
|
|
|
|
* kill us with infinite stack recursion.
|
|
|
|
|
*/
|
|
|
|
|
bool no_gpu = usage & (PIPE_TRANSFER_PERSISTENT |
|
|
|
|
|
PIPE_TRANSFER_COHERENT |
|
|
|
|
|
PIPE_TRANSFER_MAP_DIRECTLY);
|
|
|
|
|
|
|
|
|
|
/* GPU copies are not useful for buffer reads. Instead of stalling to
|
|
|
|
|
* read from the original buffer, we'd simply copy it to a temporary...
|
|
|
|
|
* then stall (a bit longer) to read from that buffer.
|
|
|
|
|
*
|
|
|
|
|
* Images are less clear-cut. Color resolves are destructive, removing
|
|
|
|
|
* the underlying compression, so we'd rather blit the data to a linear
|
|
|
|
|
* temporary and map that, to avoid the resolve. (It might be better to
|
|
|
|
|
* a tiled temporary and use the tiled_memcpy paths...)
|
|
|
|
|
*/
|
2019-04-26 10:44:18 -07:00
|
|
|
if (!(usage & PIPE_TRANSFER_DISCARD_RANGE) && !need_color_resolve)
|
2018-12-21 03:04:18 -08:00
|
|
|
no_gpu = true;
|
|
|
|
|
|
2019-04-23 20:19:37 -07:00
|
|
|
const struct isl_format_layout *fmtl = isl_format_get_layout(surf->format);
|
|
|
|
|
if (fmtl->txc == ISL_TXC_ASTC)
|
|
|
|
|
no_gpu = true;
|
|
|
|
|
|
2020-06-04 16:42:20 -07:00
|
|
|
if ((map_would_stall ||
|
|
|
|
|
res->aux.usage == ISL_AUX_USAGE_CCS_E ||
|
|
|
|
|
res->aux.usage == ISL_AUX_USAGE_GEN12_CCS_E) && !no_gpu) {
|
2019-04-26 10:44:18 -07:00
|
|
|
/* If we need a synchronous mapping and the resource is busy, or needs
|
|
|
|
|
* resolving, we copy to/from a linear temporary buffer using the GPU.
|
2018-12-21 03:04:18 -08:00
|
|
|
*/
|
|
|
|
|
map->batch = &ice->batches[IRIS_BATCH_RENDER];
|
|
|
|
|
map->blorp = &ice->blorp;
|
|
|
|
|
iris_map_copy_region(map);
|
2018-05-28 17:14:43 -07:00
|
|
|
} else {
|
2019-04-26 10:44:18 -07:00
|
|
|
/* Otherwise we're free to map on the CPU. */
|
|
|
|
|
|
|
|
|
|
if (need_resolve) {
|
2020-04-23 18:00:15 -07:00
|
|
|
iris_resource_access_raw(ice, res, level, box->z, box->depth,
|
2019-04-26 10:44:18 -07:00
|
|
|
usage & PIPE_TRANSFER_WRITE);
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-18 00:18:32 -07:00
|
|
|
if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) {
|
|
|
|
|
for (int i = 0; i < IRIS_BATCH_COUNT; i++) {
|
|
|
|
|
if (iris_batch_references(&ice->batches[i], res->bo))
|
|
|
|
|
iris_batch_flush(&ice->batches[i]);
|
|
|
|
|
}
|
2018-12-21 03:04:18 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (surf->tiling == ISL_TILING_W) {
|
|
|
|
|
/* TODO: Teach iris_map_tiled_memcpy about W-tiling... */
|
|
|
|
|
iris_map_s8(map);
|
|
|
|
|
} else if (surf->tiling != ISL_TILING_LINEAR) {
|
|
|
|
|
iris_map_tiled_memcpy(map);
|
|
|
|
|
} else {
|
|
|
|
|
iris_map_direct(map);
|
|
|
|
|
}
|
2018-05-28 17:14:43 -07:00
|
|
|
}
|
2018-01-19 18:57:30 -08:00
|
|
|
|
2018-05-28 17:14:43 -07:00
|
|
|
return map->ptr;
|
2018-01-19 18:57:30 -08:00
|
|
|
}
|
|
|
|
|
|
2018-11-21 01:03:48 -08:00
|
|
|
static void
|
|
|
|
|
iris_transfer_flush_region(struct pipe_context *ctx,
|
|
|
|
|
struct pipe_transfer *xfer,
|
|
|
|
|
const struct pipe_box *box)
|
|
|
|
|
{
|
|
|
|
|
struct iris_context *ice = (struct iris_context *)ctx;
|
|
|
|
|
struct iris_resource *res = (struct iris_resource *) xfer->resource;
|
2019-04-06 23:35:49 -07:00
|
|
|
struct iris_transfer *map = (void *) xfer;
|
|
|
|
|
|
|
|
|
|
if (map->staging)
|
|
|
|
|
iris_flush_staging_region(xfer, box);
|
2018-11-21 01:03:48 -08:00
|
|
|
|
2019-06-19 23:01:21 -05:00
|
|
|
uint32_t history_flush = 0;
|
|
|
|
|
|
|
|
|
|
if (res->base.target == PIPE_BUFFER) {
|
2019-09-07 22:51:15 -07:00
|
|
|
if (map->staging)
|
|
|
|
|
history_flush |= PIPE_CONTROL_RENDER_TARGET_FLUSH;
|
|
|
|
|
|
|
|
|
|
if (map->dest_had_defined_contents)
|
|
|
|
|
history_flush |= iris_flush_bits_for_history(res);
|
|
|
|
|
|
2019-09-25 21:38:40 -04:00
|
|
|
util_range_add(&res->base, &res->valid_buffer_range, box->x, box->x + box->width);
|
2019-06-19 23:01:21 -05:00
|
|
|
}
|
|
|
|
|
|
2019-06-19 23:30:52 -05:00
|
|
|
if (history_flush & ~PIPE_CONTROL_CS_STALL) {
|
|
|
|
|
for (int i = 0; i < IRIS_BATCH_COUNT; i++) {
|
|
|
|
|
struct iris_batch *batch = &ice->batches[i];
|
|
|
|
|
if (batch->contains_draw || batch->cache.render->entries) {
|
|
|
|
|
iris_batch_maybe_flush(batch, 24);
|
|
|
|
|
iris_emit_pipe_control_flush(batch,
|
|
|
|
|
"cache history: transfer flush",
|
|
|
|
|
history_flush);
|
|
|
|
|
}
|
2018-11-21 01:03:48 -08:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-22 19:11:44 -07:00
|
|
|
|
|
|
|
|
/* Make sure we flag constants dirty even if there's no need to emit
|
|
|
|
|
* any PIPE_CONTROLs to a batch.
|
|
|
|
|
*/
|
2019-04-24 12:11:39 -07:00
|
|
|
iris_dirty_for_history(ice, res);
|
2018-11-21 01:03:48 -08:00
|
|
|
}
|
|
|
|
|
|
2018-01-19 18:57:30 -08:00
|
|
|
static void
|
2018-07-06 11:29:51 -07:00
|
|
|
iris_transfer_unmap(struct pipe_context *ctx, struct pipe_transfer *xfer)
|
2018-01-19 18:57:30 -08:00
|
|
|
{
|
2018-07-06 11:29:51 -07:00
|
|
|
struct iris_context *ice = (struct iris_context *)ctx;
|
2018-06-17 21:47:52 -07:00
|
|
|
struct iris_transfer *map = (void *) xfer;
|
2019-04-06 23:35:49 -07:00
|
|
|
|
2019-08-28 17:50:13 -07:00
|
|
|
if (!(xfer->usage & (PIPE_TRANSFER_FLUSH_EXPLICIT |
|
|
|
|
|
PIPE_TRANSFER_COHERENT))) {
|
2019-04-06 23:35:49 -07:00
|
|
|
struct pipe_box flush_box = {
|
|
|
|
|
.x = 0, .y = 0, .z = 0,
|
|
|
|
|
.width = xfer->box.width,
|
|
|
|
|
.height = xfer->box.height,
|
|
|
|
|
.depth = xfer->box.depth,
|
|
|
|
|
};
|
|
|
|
|
iris_transfer_flush_region(ctx, xfer, &flush_box);
|
|
|
|
|
}
|
2018-05-28 17:14:43 -07:00
|
|
|
|
|
|
|
|
if (map->unmap)
|
|
|
|
|
map->unmap(map);
|
|
|
|
|
|
|
|
|
|
pipe_resource_reference(&xfer->resource, NULL);
|
2018-07-06 11:29:51 -07:00
|
|
|
slab_free(&ice->transfer_pool, map);
|
2018-01-19 18:57:30 -08:00
|
|
|
}
|
|
|
|
|
|
2019-04-24 12:11:39 -07:00
|
|
|
/**
|
|
|
|
|
* Mark state dirty that needs to be re-emitted when a resource is written.
|
|
|
|
|
*/
|
2018-11-21 00:52:25 -08:00
|
|
|
void
|
2019-04-24 12:11:39 -07:00
|
|
|
iris_dirty_for_history(struct iris_context *ice,
|
|
|
|
|
struct iris_resource *res)
|
2018-11-21 00:52:25 -08:00
|
|
|
{
|
2020-05-29 16:57:01 -07:00
|
|
|
uint64_t stage_dirty = 0ull;
|
2018-11-21 00:52:25 -08:00
|
|
|
|
|
|
|
|
if (res->bind_history & PIPE_BIND_CONSTANT_BUFFER) {
|
2020-05-29 16:57:01 -07:00
|
|
|
stage_dirty |= ((uint64_t)res->bind_stages)
|
|
|
|
|
<< IRIS_SHIFT_FOR_STAGE_DIRTY_CONSTANTS;
|
2018-11-21 00:52:25 -08:00
|
|
|
}
|
|
|
|
|
|
2020-05-29 16:57:01 -07:00
|
|
|
ice->state.stage_dirty |= stage_dirty;
|
2019-04-24 12:11:39 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Produce a set of PIPE_CONTROL bits which ensure data written to a
|
|
|
|
|
* resource becomes visible, and any stale read cache data is invalidated.
|
|
|
|
|
*/
|
|
|
|
|
uint32_t
|
|
|
|
|
iris_flush_bits_for_history(struct iris_resource *res)
|
|
|
|
|
{
|
|
|
|
|
uint32_t flush = PIPE_CONTROL_CS_STALL;
|
|
|
|
|
|
|
|
|
|
if (res->bind_history & PIPE_BIND_CONSTANT_BUFFER) {
|
|
|
|
|
flush |= PIPE_CONTROL_CONST_CACHE_INVALIDATE |
|
|
|
|
|
PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE;
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-21 00:52:25 -08:00
|
|
|
if (res->bind_history & PIPE_BIND_SAMPLER_VIEW)
|
|
|
|
|
flush |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE;
|
|
|
|
|
|
|
|
|
|
if (res->bind_history & (PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER))
|
|
|
|
|
flush |= PIPE_CONTROL_VF_CACHE_INVALIDATE;
|
|
|
|
|
|
|
|
|
|
if (res->bind_history & (PIPE_BIND_SHADER_BUFFER | PIPE_BIND_SHADER_IMAGE))
|
|
|
|
|
flush |= PIPE_CONTROL_DATA_CACHE_FLUSH;
|
|
|
|
|
|
2019-04-24 12:11:39 -07:00
|
|
|
return flush;
|
|
|
|
|
}
|
2018-11-21 00:52:25 -08:00
|
|
|
|
2019-04-24 12:11:39 -07:00
|
|
|
void
|
|
|
|
|
iris_flush_and_dirty_for_history(struct iris_context *ice,
|
|
|
|
|
struct iris_batch *batch,
|
2019-06-19 16:04:50 -05:00
|
|
|
struct iris_resource *res,
|
2019-06-19 23:12:52 -05:00
|
|
|
uint32_t extra_flags,
|
2019-06-19 16:04:50 -05:00
|
|
|
const char *reason)
|
2019-04-24 12:11:39 -07:00
|
|
|
{
|
|
|
|
|
if (res->base.target != PIPE_BUFFER)
|
|
|
|
|
return;
|
|
|
|
|
|
2019-06-19 23:12:52 -05:00
|
|
|
uint32_t flush = iris_flush_bits_for_history(res) | extra_flags;
|
2019-04-24 12:11:39 -07:00
|
|
|
|
2019-06-19 16:04:50 -05:00
|
|
|
iris_emit_pipe_control_flush(batch, reason, flush);
|
2019-06-19 23:08:25 -05:00
|
|
|
|
|
|
|
|
iris_dirty_for_history(ice, res);
|
2018-11-21 00:52:25 -08:00
|
|
|
}
|
|
|
|
|
|
2019-02-15 14:45:05 -08:00
|
|
|
bool
|
|
|
|
|
iris_resource_set_clear_color(struct iris_context *ice,
|
|
|
|
|
struct iris_resource *res,
|
|
|
|
|
union isl_color_value color)
|
|
|
|
|
{
|
|
|
|
|
if (memcmp(&res->aux.clear_color, &color, sizeof(color)) != 0) {
|
|
|
|
|
res->aux.clear_color = color;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
union isl_color_value
|
|
|
|
|
iris_resource_get_clear_color(const struct iris_resource *res,
|
|
|
|
|
struct iris_bo **clear_color_bo,
|
|
|
|
|
uint64_t *clear_color_offset)
|
|
|
|
|
{
|
|
|
|
|
assert(res->aux.bo);
|
|
|
|
|
|
|
|
|
|
if (clear_color_bo)
|
|
|
|
|
*clear_color_bo = res->aux.clear_color_bo;
|
|
|
|
|
if (clear_color_offset)
|
|
|
|
|
*clear_color_offset = res->aux.clear_color_offset;
|
|
|
|
|
return res->aux.clear_color;
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-08 14:54:09 -07:00
|
|
|
static enum pipe_format
|
|
|
|
|
iris_resource_get_internal_format(struct pipe_resource *p_res)
|
|
|
|
|
{
|
|
|
|
|
struct iris_resource *res = (void *) p_res;
|
|
|
|
|
return res->internal_format;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const struct u_transfer_vtbl transfer_vtbl = {
|
|
|
|
|
.resource_create = iris_resource_create,
|
|
|
|
|
.resource_destroy = iris_resource_destroy,
|
|
|
|
|
.transfer_map = iris_transfer_map,
|
|
|
|
|
.transfer_unmap = iris_transfer_unmap,
|
2018-11-21 01:03:48 -08:00
|
|
|
.transfer_flush_region = iris_transfer_flush_region,
|
2018-08-08 14:54:09 -07:00
|
|
|
.get_internal_format = iris_resource_get_internal_format,
|
|
|
|
|
.set_stencil = iris_resource_set_separate_stencil,
|
|
|
|
|
.get_stencil = iris_resource_get_separate_stencil,
|
|
|
|
|
};
|
|
|
|
|
|
2017-11-23 23:15:14 -08:00
|
|
|
void
|
|
|
|
|
iris_init_screen_resource_functions(struct pipe_screen *pscreen)
|
|
|
|
|
{
|
2019-03-26 00:25:31 -07:00
|
|
|
pscreen->query_dmabuf_modifiers = iris_query_dmabuf_modifiers;
|
2017-11-23 23:15:14 -08:00
|
|
|
pscreen->resource_create_with_modifiers =
|
|
|
|
|
iris_resource_create_with_modifiers;
|
2018-08-08 14:54:09 -07:00
|
|
|
pscreen->resource_create = u_transfer_helper_resource_create;
|
2018-07-31 14:47:02 +01:00
|
|
|
pscreen->resource_from_user_memory = iris_resource_from_user_memory;
|
2017-11-23 23:15:14 -08:00
|
|
|
pscreen->resource_from_handle = iris_resource_from_handle;
|
|
|
|
|
pscreen->resource_get_handle = iris_resource_get_handle;
|
2019-08-02 01:21:12 -07:00
|
|
|
pscreen->resource_get_param = iris_resource_get_param;
|
2018-08-08 14:54:09 -07:00
|
|
|
pscreen->resource_destroy = u_transfer_helper_resource_destroy;
|
|
|
|
|
pscreen->transfer_helper =
|
2018-11-07 21:06:49 -08:00
|
|
|
u_transfer_helper_create(&transfer_vtbl, true, true, false, true);
|
2017-11-23 23:15:14 -08:00
|
|
|
}
|
2018-01-19 18:57:30 -08:00
|
|
|
|
|
|
|
|
void
|
|
|
|
|
iris_init_resource_functions(struct pipe_context *ctx)
|
|
|
|
|
{
|
|
|
|
|
ctx->flush_resource = iris_flush_resource;
|
2019-03-12 14:51:22 -07:00
|
|
|
ctx->invalidate_resource = iris_invalidate_resource;
|
2018-08-08 14:54:09 -07:00
|
|
|
ctx->transfer_map = u_transfer_helper_transfer_map;
|
|
|
|
|
ctx->transfer_flush_region = u_transfer_helper_transfer_flush_region;
|
|
|
|
|
ctx->transfer_unmap = u_transfer_helper_transfer_unmap;
|
2018-06-07 01:25:35 -07:00
|
|
|
ctx->buffer_subdata = u_default_buffer_subdata;
|
|
|
|
|
ctx->texture_subdata = u_default_texture_subdata;
|
2018-01-19 18:57:30 -08:00
|
|
|
}
|