2018-01-20 02:57:30 +00: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 08:31:46 +01: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:
|
2018-01-20 02:57:30 +00:00
|
|
|
*
|
2018-08-19 08:31:46 +01:00
|
|
|
* The above copyright notice and this permission notice shall be included
|
|
|
|
* in all copies or substantial portions of the Software.
|
2018-01-20 02:57:30 +00:00
|
|
|
*
|
2018-08-19 08:31:46 +01: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.
|
2018-01-20 02:57:30 +00:00
|
|
|
*/
|
2018-08-19 08:31:46 +01:00
|
|
|
|
2018-01-20 02:57:30 +00: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"
|
|
|
|
#include "util/u_inlines.h"
|
2019-06-27 23:05:31 +01:00
|
|
|
#include "util/format/u_format.h"
|
2018-01-20 02:57:30 +00:00
|
|
|
#include "util/u_upload_mgr.h"
|
|
|
|
#include "util/ralloc.h"
|
|
|
|
#include "iris_context.h"
|
|
|
|
#include "iris_resource.h"
|
|
|
|
#include "iris_screen.h"
|
|
|
|
#include "intel/compiler/brw_compiler.h"
|
2019-02-28 19:11:24 +00:00
|
|
|
|
2019-02-20 00:07:09 +00:00
|
|
|
static bool
|
|
|
|
iris_is_color_fast_clear_compatible(struct iris_context *ice,
|
|
|
|
enum isl_format format,
|
|
|
|
const union isl_color_value color)
|
|
|
|
{
|
|
|
|
struct iris_batch *batch = &ice->batches[IRIS_BATCH_RENDER];
|
2021-04-05 21:19:39 +01:00
|
|
|
const struct intel_device_info *devinfo = &batch->screen->devinfo;
|
2019-02-20 00:07:09 +00:00
|
|
|
|
|
|
|
if (isl_format_has_int_channel(format)) {
|
2020-08-20 01:12:10 +01:00
|
|
|
perf_debug(&ice->dbg, "Integer fast clear not enabled for %s\n",
|
2019-02-20 00:07:09 +00:00
|
|
|
isl_format_get_name(format));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
|
|
if (!isl_format_has_color_component(format, i)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2021-03-29 22:41:58 +01:00
|
|
|
if (devinfo->ver < 9 &&
|
2019-02-20 00:07:09 +00:00
|
|
|
color.f32[i] != 0.0f && color.f32[i] != 1.0f) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool
|
|
|
|
can_fast_clear_color(struct iris_context *ice,
|
|
|
|
struct pipe_resource *p_res,
|
|
|
|
unsigned level,
|
|
|
|
const struct pipe_box *box,
|
2021-01-08 17:43:52 +00:00
|
|
|
bool render_condition_enabled,
|
2019-02-20 00:07:09 +00:00
|
|
|
enum isl_format render_format,
|
|
|
|
union isl_color_value color)
|
|
|
|
{
|
|
|
|
struct iris_resource *res = (void *) p_res;
|
|
|
|
|
2021-10-13 10:21:41 +01:00
|
|
|
if (INTEL_DEBUG(DEBUG_NO_FAST_CLEAR))
|
2019-10-08 01:12:14 +01:00
|
|
|
return false;
|
|
|
|
|
2019-11-08 23:07:34 +00:00
|
|
|
if (!isl_aux_usage_has_fast_clears(res->aux.usage))
|
2019-02-20 00:07:09 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
/* Check for partial clear */
|
|
|
|
if (box->x > 0 || box->y > 0 ||
|
2021-12-07 06:05:56 +00:00
|
|
|
box->width < u_minify(p_res->width0, level) ||
|
|
|
|
box->height < u_minify(p_res->height0, level)) {
|
2019-02-20 00:07:09 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-01-08 17:43:52 +00:00
|
|
|
/* Avoid conditional fast clears to maintain correct tracking of the aux
|
|
|
|
* state (see iris_resource_finish_write for more info). Note that partial
|
|
|
|
* fast clears (if they existed) would not pose a problem with conditional
|
|
|
|
* rendering.
|
|
|
|
*/
|
|
|
|
if (render_condition_enabled &&
|
|
|
|
ice->state.predicate == IRIS_PREDICATE_STATE_USE_BIT) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-05-14 16:48:30 +01:00
|
|
|
/* Disable sRGB fast-clears for non-0/1 color values. For texturing and
|
|
|
|
* draw calls, HW expects the clear color to be in two different color
|
|
|
|
* spaces after sRGB fast-clears - sRGB in the former and linear in the
|
|
|
|
* latter. By limiting the allowable values to 0/1, both color space
|
|
|
|
* requirements are satisfied.
|
|
|
|
*/
|
|
|
|
if (isl_format_is_srgb(render_format) &&
|
|
|
|
!isl_color_value_is_zero_one(color, render_format)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-02-20 00:07:09 +00:00
|
|
|
/* We store clear colors as floats or uints as needed. If there are
|
|
|
|
* texture views in play, the formats will not properly be respected
|
|
|
|
* during resolves because the resolve operations only know about the
|
|
|
|
* resource and not the renderbuffer.
|
|
|
|
*/
|
2020-05-05 23:33:29 +01:00
|
|
|
if (!iris_render_formats_color_compatible(render_format, res->surf.format,
|
2021-07-26 20:59:42 +01:00
|
|
|
color, false)) {
|
2019-02-20 00:07:09 +00:00
|
|
|
return false;
|
2019-04-19 01:47:36 +01:00
|
|
|
}
|
2019-02-20 00:07:09 +00:00
|
|
|
|
2020-05-20 19:46:46 +01:00
|
|
|
if (!iris_is_color_fast_clear_compatible(ice, res->surf.format, color))
|
2019-02-20 00:07:09 +00:00
|
|
|
return false;
|
|
|
|
|
2020-10-09 18:07:51 +01:00
|
|
|
/* The RENDER_SURFACE_STATE page for TGL says:
|
|
|
|
*
|
|
|
|
* For an 8 bpp surface with NUM_MULTISAMPLES = 1, Surface Width not
|
|
|
|
* multiple of 64 pixels and more than 1 mip level in the view, Fast Clear
|
|
|
|
* is not supported when AUX_CCS_E is set in this field.
|
|
|
|
*
|
|
|
|
* The granularity of a fast-clear is one CCS element. For an 8 bpp primary
|
|
|
|
* surface, this maps to 32px x 4rows. Due to the surface layout parameters,
|
|
|
|
* if LOD0's width isn't a multiple of 64px, LOD1 and LOD2+ will share CCS
|
|
|
|
* elements. Assuming LOD2 exists, don't fast-clear any level above LOD0
|
|
|
|
* to avoid stomping on other LODs.
|
|
|
|
*/
|
|
|
|
if (level > 0 && util_format_get_blocksizebits(p_res->format) == 8 &&
|
2021-03-30 00:02:30 +01:00
|
|
|
res->aux.usage == ISL_AUX_USAGE_GFX12_CCS_E && p_res->width0 % 64) {
|
2020-10-09 18:07:51 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-02-20 00:07:09 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-02-28 19:11:24 +00:00
|
|
|
static union isl_color_value
|
2020-10-14 18:45:57 +01:00
|
|
|
convert_clear_color(enum pipe_format format,
|
|
|
|
const union pipe_color_union *color)
|
2019-02-28 19:11:24 +00:00
|
|
|
{
|
2020-10-26 00:08:20 +00:00
|
|
|
uint32_t pixel[4];
|
|
|
|
util_format_pack_rgba(format, pixel, color, 1);
|
2019-02-28 19:11:24 +00:00
|
|
|
|
2020-10-26 00:08:20 +00:00
|
|
|
union isl_color_value converted_color;
|
|
|
|
util_format_unpack_rgba(format, &converted_color, pixel, 1);
|
2019-02-28 19:11:24 +00:00
|
|
|
|
2020-10-26 00:08:20 +00:00
|
|
|
/* The converted clear color has channels that are:
|
|
|
|
* - clamped
|
|
|
|
* - quantized
|
|
|
|
* - filled with 0/1 if missing from the format
|
|
|
|
* - swizzled for luminance and intensity formats
|
|
|
|
*/
|
|
|
|
return converted_color;
|
2019-02-28 19:11:24 +00:00
|
|
|
}
|
2018-01-20 02:57:30 +00:00
|
|
|
|
2019-02-20 00:07:09 +00:00
|
|
|
static void
|
|
|
|
fast_clear_color(struct iris_context *ice,
|
|
|
|
struct iris_resource *res,
|
|
|
|
unsigned level,
|
|
|
|
const struct pipe_box *box,
|
2020-11-24 22:18:31 +00:00
|
|
|
union isl_color_value color)
|
2019-02-20 00:07:09 +00:00
|
|
|
{
|
|
|
|
struct iris_batch *batch = &ice->batches[IRIS_BATCH_RENDER];
|
2021-10-08 18:48:08 +01:00
|
|
|
const struct intel_device_info *devinfo = &batch->screen->devinfo;
|
2019-02-20 00:07:09 +00:00
|
|
|
struct pipe_resource *p_res = (void *) res;
|
|
|
|
|
2021-07-26 20:59:42 +01:00
|
|
|
bool color_changed = res->aux.clear_color_unknown ||
|
|
|
|
memcmp(&res->aux.clear_color, &color, sizeof(color)) != 0;
|
2019-03-08 18:58:41 +00:00
|
|
|
|
|
|
|
if (color_changed) {
|
2019-06-25 22:14:22 +01:00
|
|
|
/* If we are clearing to a new clear value, we need to resolve fast
|
|
|
|
* clears from other levels/layers first, since we can't have different
|
|
|
|
* levels/layers with different fast clear colors.
|
|
|
|
*/
|
|
|
|
for (unsigned res_lvl = 0; res_lvl < res->surf.levels; res_lvl++) {
|
|
|
|
const unsigned level_layers =
|
|
|
|
iris_get_num_logical_layers(res, res_lvl);
|
|
|
|
for (unsigned layer = 0; layer < level_layers; layer++) {
|
|
|
|
if (res_lvl == level &&
|
|
|
|
layer >= box->z &&
|
|
|
|
layer < box->z + box->depth) {
|
|
|
|
/* We're going to clear this layer anyway. Leave it alone. */
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
enum isl_aux_state aux_state =
|
|
|
|
iris_resource_get_aux_state(res, res_lvl, layer);
|
|
|
|
|
|
|
|
if (aux_state != ISL_AUX_STATE_CLEAR &&
|
|
|
|
aux_state != ISL_AUX_STATE_PARTIAL_CLEAR &&
|
|
|
|
aux_state != ISL_AUX_STATE_COMPRESSED_CLEAR) {
|
|
|
|
/* This slice doesn't have any fast-cleared bits. */
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If we got here, then the level may have fast-clear bits that use
|
|
|
|
* the old clear value. We need to do a color resolve to get rid
|
|
|
|
* of their use of the clear color before we can change it.
|
|
|
|
* Fortunately, few applications ever change their clear color at
|
|
|
|
* different levels/layers, so this shouldn't happen often.
|
|
|
|
*/
|
2020-04-24 02:00:15 +01:00
|
|
|
iris_resource_prepare_access(ice, res,
|
2019-06-25 22:14:22 +01:00
|
|
|
res_lvl, 1, layer, 1,
|
|
|
|
res->aux.usage,
|
|
|
|
false);
|
2021-07-26 20:59:42 +01:00
|
|
|
if (res->aux.clear_color_unknown) {
|
|
|
|
perf_debug(&ice->dbg,
|
|
|
|
"Resolving resource (%p) level %d, layer %d: color changing from "
|
|
|
|
"(unknown) to (%0.2f, %0.2f, %0.2f, %0.2f)\n",
|
|
|
|
res, res_lvl, layer,
|
|
|
|
color.f32[0], color.f32[1], color.f32[2], color.f32[3]);
|
|
|
|
} else {
|
|
|
|
perf_debug(&ice->dbg,
|
|
|
|
"Resolving resource (%p) level %d, layer %d: color changing from "
|
|
|
|
"(%0.2f, %0.2f, %0.2f, %0.2f) to "
|
|
|
|
"(%0.2f, %0.2f, %0.2f, %0.2f)\n",
|
|
|
|
res, res_lvl, layer,
|
|
|
|
res->aux.clear_color.f32[0],
|
|
|
|
res->aux.clear_color.f32[1],
|
|
|
|
res->aux.clear_color.f32[2],
|
|
|
|
res->aux.clear_color.f32[3],
|
|
|
|
color.f32[0], color.f32[1], color.f32[2], color.f32[3]);
|
|
|
|
}
|
2019-06-25 22:14:22 +01:00
|
|
|
}
|
|
|
|
}
|
2019-03-07 01:06:13 +00:00
|
|
|
}
|
|
|
|
|
2019-02-20 00:07:09 +00:00
|
|
|
iris_resource_set_clear_color(ice, res, color);
|
|
|
|
|
2019-03-08 18:58:41 +00:00
|
|
|
/* If the buffer is already in ISL_AUX_STATE_CLEAR, and the color hasn't
|
|
|
|
* changed, the clear is redundant and can be skipped.
|
2019-02-20 00:07:09 +00:00
|
|
|
*/
|
2020-09-29 13:49:54 +01:00
|
|
|
const enum isl_aux_state aux_state =
|
|
|
|
iris_resource_get_aux_state(res, level, box->z);
|
|
|
|
if (!color_changed && box->depth == 1 && aux_state == ISL_AUX_STATE_CLEAR)
|
2019-02-20 00:07:09 +00:00
|
|
|
return;
|
|
|
|
|
2021-02-25 06:11:12 +00:00
|
|
|
/* Ivybridge PRM Vol 2, Part 1, "11.7 MCS Buffer for Render Target(s)":
|
2019-02-20 00:07:09 +00:00
|
|
|
*
|
|
|
|
* "Any transition from any value in {Clear, Render, Resolve} to a
|
|
|
|
* different value in {Clear, Render, Resolve} requires end of pipe
|
|
|
|
* synchronization."
|
|
|
|
*
|
|
|
|
* In other words, fast clear ops are not properly synchronized with
|
|
|
|
* other drawing. We need to use a PIPE_CONTROL to ensure that the
|
|
|
|
* contents of the previous draw hit the render target before we resolve
|
|
|
|
* and again afterwards to ensure that the resolve is complete before we
|
|
|
|
* do any more regular drawing.
|
|
|
|
*/
|
2019-06-19 22:04:50 +01:00
|
|
|
iris_emit_end_of_pipe_sync(batch,
|
|
|
|
"fast clear: pre-flush",
|
2021-03-30 01:11:42 +01:00
|
|
|
PIPE_CONTROL_RENDER_TARGET_FLUSH |
|
2021-11-08 16:33:19 +00:00
|
|
|
PIPE_CONTROL_TILE_CACHE_FLUSH |
|
|
|
|
(devinfo->verx10 == 120 ?
|
2021-10-08 19:16:35 +01:00
|
|
|
PIPE_CONTROL_DEPTH_STALL : 0) |
|
2021-11-08 16:41:20 +00:00
|
|
|
(devinfo->verx10 == 125 ?
|
2022-07-28 21:34:32 +01:00
|
|
|
PIPE_CONTROL_FLUSH_HDC |
|
|
|
|
PIPE_CONTROL_DATA_CACHE_FLUSH : 0) |
|
2021-10-08 19:16:35 +01:00
|
|
|
PIPE_CONTROL_PSS_STALL_SYNC);
|
2019-02-20 00:07:09 +00:00
|
|
|
|
2020-04-24 01:58:48 +01:00
|
|
|
iris_batch_sync_region_start(batch);
|
|
|
|
|
2019-03-08 18:58:41 +00:00
|
|
|
/* If we reach this point, we need to fast clear to change the state to
|
|
|
|
* ISL_AUX_STATE_CLEAR, or to update the fast clear color (or both).
|
|
|
|
*/
|
2020-11-24 22:18:31 +00:00
|
|
|
enum blorp_batch_flags blorp_flags = 0;
|
2019-03-08 18:58:41 +00:00
|
|
|
blorp_flags |= color_changed ? 0 : BLORP_BATCH_NO_UPDATE_CLEAR_COLOR;
|
|
|
|
|
2019-02-20 00:07:09 +00:00
|
|
|
struct blorp_batch blorp_batch;
|
|
|
|
blorp_batch_init(&ice->blorp, &blorp_batch, batch, blorp_flags);
|
|
|
|
|
|
|
|
struct blorp_surf surf;
|
2020-03-30 15:37:29 +01:00
|
|
|
iris_blorp_surf_for_resource(&batch->screen->isl_dev, &surf,
|
2019-11-05 23:08:01 +00:00
|
|
|
p_res, res->aux.usage, level, true);
|
2019-02-20 00:07:09 +00:00
|
|
|
|
2021-12-27 15:15:19 +00:00
|
|
|
blorp_fast_clear(&blorp_batch, &surf, res->surf.format,
|
|
|
|
ISL_SWIZZLE_IDENTITY,
|
2019-02-20 00:07:09 +00:00
|
|
|
level, box->z, box->depth,
|
|
|
|
box->x, box->y, box->x + box->width,
|
|
|
|
box->y + box->height);
|
|
|
|
blorp_batch_finish(&blorp_batch);
|
2019-06-19 22:04:50 +01:00
|
|
|
iris_emit_end_of_pipe_sync(batch,
|
|
|
|
"fast clear: post flush",
|
2021-10-08 18:48:08 +01:00
|
|
|
PIPE_CONTROL_RENDER_TARGET_FLUSH |
|
|
|
|
(devinfo->verx10 == 120 ?
|
2021-11-08 16:33:19 +00:00
|
|
|
PIPE_CONTROL_TILE_CACHE_FLUSH |
|
2021-10-08 19:16:35 +01:00
|
|
|
PIPE_CONTROL_DEPTH_STALL : 0) |
|
|
|
|
PIPE_CONTROL_PSS_STALL_SYNC);
|
2020-04-24 01:58:48 +01:00
|
|
|
iris_batch_sync_region_end(batch);
|
2019-02-20 00:07:09 +00:00
|
|
|
|
|
|
|
iris_resource_set_aux_state(ice, res, level, box->z,
|
|
|
|
box->depth, ISL_AUX_STATE_CLEAR);
|
2020-05-30 00:57:01 +01:00
|
|
|
ice->state.dirty |= IRIS_DIRTY_RENDER_BUFFER;
|
|
|
|
ice->state.stage_dirty |= IRIS_ALL_STAGE_DIRTY_BINDINGS;
|
2019-02-20 00:07:09 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-02-11 01:13:29 +00:00
|
|
|
static void
|
|
|
|
clear_color(struct iris_context *ice,
|
|
|
|
struct pipe_resource *p_res,
|
|
|
|
unsigned level,
|
|
|
|
const struct pipe_box *box,
|
|
|
|
bool render_condition_enabled,
|
|
|
|
enum isl_format format,
|
iris: Properly support alpha and luminance-alpha formats
For texturing, we map alpha formats to the corresponding red format,
as many alpha formats are outright missing, and red is more efficient
when sampling anyway.
When rendering to A8_UNORM, we use that format directly, so the image
gets the shader output's .a/.w channel, rather than the .r/.x channel.
All other A* formats are non-renderable, so we can't do much and just
mark them as unsupported for rendering. Fortunately, GL only requires
rendering to A8_UNORM, so that works out.
According to Andre Heider and Timur Kristóf, this fixes font rendering
in Witcher 1 (via nine). Andre also reported that it fixes Unigine
Heaven (presumably via nine).
v2: Use the same swizzle for both sampler views and "render targets".
BLORP expects the read swizzle, and will take the inverse when
setting up the destination swizzle (and actually applying it in
the shaders). We ignore the format swizzle when setting up normal
rendering SURFACE_STATEs, which is necessary because it would be
an illegal shader channel select combination. Thanks to Jason
Ekstrand for pointing out that BLORP took an inverse swizzle.
Tested-by: Timur Kristóf <timur.kristof@gmail.com>
Tested-by: Andre Heider <a.heider@gmail.com>
Reviewed-by: Jason Ekstrand <jason@jlekstrand.net>
2019-02-22 06:49:40 +00:00
|
|
|
struct isl_swizzle swizzle,
|
2019-02-11 01:13:29 +00:00
|
|
|
union isl_color_value color)
|
|
|
|
{
|
|
|
|
struct iris_resource *res = (void *) p_res;
|
|
|
|
|
|
|
|
struct iris_batch *batch = &ice->batches[IRIS_BATCH_RENDER];
|
2021-04-05 21:19:39 +01:00
|
|
|
const struct intel_device_info *devinfo = &batch->screen->devinfo;
|
2021-10-01 10:06:45 +01:00
|
|
|
enum blorp_batch_flags blorp_flags = iris_blorp_flags_for_batch(batch);
|
2019-02-11 01:13:29 +00:00
|
|
|
|
|
|
|
if (render_condition_enabled) {
|
|
|
|
if (ice->state.predicate == IRIS_PREDICATE_STATE_DONT_RENDER)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (ice->state.predicate == IRIS_PREDICATE_STATE_USE_BIT)
|
|
|
|
blorp_flags |= BLORP_BATCH_PREDICATE_ENABLE;
|
|
|
|
}
|
|
|
|
|
2019-04-05 19:54:10 +01:00
|
|
|
if (p_res->target == PIPE_BUFFER)
|
2021-02-09 00:39:42 +00:00
|
|
|
util_range_add(&res->base.b, &res->valid_buffer_range, box->x, box->x + box->width);
|
2019-04-05 19:54:10 +01:00
|
|
|
|
2019-02-11 01:13:29 +00:00
|
|
|
iris_batch_maybe_flush(batch, 1500);
|
|
|
|
|
2019-02-20 00:07:09 +00:00
|
|
|
bool can_fast_clear = can_fast_clear_color(ice, p_res, level, box,
|
2021-01-08 17:43:52 +00:00
|
|
|
render_condition_enabled,
|
2020-05-20 19:46:46 +01:00
|
|
|
format, color);
|
2019-02-20 00:07:09 +00:00
|
|
|
if (can_fast_clear) {
|
2022-01-14 18:16:45 +00:00
|
|
|
fast_clear_color(ice, res, level, box, color);
|
2019-02-20 00:07:09 +00:00
|
|
|
return;
|
|
|
|
}
|
2019-02-11 01:13:29 +00:00
|
|
|
|
2018-12-07 21:33:25 +00:00
|
|
|
enum isl_aux_usage aux_usage =
|
2020-12-17 22:41:19 +00:00
|
|
|
iris_resource_render_aux_usage(ice, res, level, format, false);
|
2018-12-07 21:33:25 +00:00
|
|
|
|
2020-12-17 23:05:51 +00:00
|
|
|
iris_resource_prepare_render(ice, res, level, box->z, box->depth,
|
|
|
|
aux_usage);
|
2020-05-06 23:40:30 +01:00
|
|
|
iris_emit_buffer_barrier_for(batch, res->bo, IRIS_DOMAIN_RENDER_WRITE);
|
2018-12-07 21:33:25 +00:00
|
|
|
|
2019-02-11 01:13:29 +00:00
|
|
|
struct blorp_surf surf;
|
2020-03-30 15:37:29 +01:00
|
|
|
iris_blorp_surf_for_resource(&batch->screen->isl_dev, &surf,
|
2019-11-05 23:08:01 +00:00
|
|
|
p_res, aux_usage, level, true);
|
2019-02-11 01:13:29 +00:00
|
|
|
|
2020-04-24 01:58:48 +01:00
|
|
|
iris_batch_sync_region_start(batch);
|
|
|
|
|
2019-02-20 00:07:09 +00:00
|
|
|
struct blorp_batch blorp_batch;
|
|
|
|
blorp_batch_init(&ice->blorp, &blorp_batch, batch, blorp_flags);
|
|
|
|
|
2019-02-11 01:13:29 +00:00
|
|
|
if (!isl_format_supports_rendering(devinfo, format) &&
|
|
|
|
isl_format_is_rgbx(format))
|
|
|
|
format = isl_format_rgbx_to_rgba(format);
|
|
|
|
|
iris: Properly support alpha and luminance-alpha formats
For texturing, we map alpha formats to the corresponding red format,
as many alpha formats are outright missing, and red is more efficient
when sampling anyway.
When rendering to A8_UNORM, we use that format directly, so the image
gets the shader output's .a/.w channel, rather than the .r/.x channel.
All other A* formats are non-renderable, so we can't do much and just
mark them as unsupported for rendering. Fortunately, GL only requires
rendering to A8_UNORM, so that works out.
According to Andre Heider and Timur Kristóf, this fixes font rendering
in Witcher 1 (via nine). Andre also reported that it fixes Unigine
Heaven (presumably via nine).
v2: Use the same swizzle for both sampler views and "render targets".
BLORP expects the read swizzle, and will take the inverse when
setting up the destination swizzle (and actually applying it in
the shaders). We ignore the format swizzle when setting up normal
rendering SURFACE_STATEs, which is necessary because it would be
an illegal shader channel select combination. Thanks to Jason
Ekstrand for pointing out that BLORP took an inverse swizzle.
Tested-by: Timur Kristóf <timur.kristof@gmail.com>
Tested-by: Andre Heider <a.heider@gmail.com>
Reviewed-by: Jason Ekstrand <jason@jlekstrand.net>
2019-02-22 06:49:40 +00:00
|
|
|
blorp_clear(&blorp_batch, &surf, format, swizzle,
|
2019-02-11 01:13:29 +00:00
|
|
|
level, box->z, box->depth, box->x, box->y,
|
|
|
|
box->x + box->width, box->y + box->height,
|
2021-09-16 22:25:42 +01:00
|
|
|
color, 0 /* color_write_disable */);
|
2019-02-11 01:13:29 +00:00
|
|
|
|
|
|
|
blorp_batch_finish(&blorp_batch);
|
2020-04-24 01:58:48 +01:00
|
|
|
iris_batch_sync_region_end(batch);
|
|
|
|
|
2020-04-30 23:11:19 +01:00
|
|
|
iris_dirty_for_history(ice, res);
|
2018-12-07 21:33:25 +00:00
|
|
|
|
|
|
|
iris_resource_finish_render(ice, res, level,
|
|
|
|
box->z, box->depth, aux_usage);
|
2019-02-11 01:13:29 +00:00
|
|
|
}
|
|
|
|
|
2019-02-26 20:08:23 +00:00
|
|
|
static bool
|
|
|
|
can_fast_clear_depth(struct iris_context *ice,
|
|
|
|
struct iris_resource *res,
|
|
|
|
unsigned level,
|
|
|
|
const struct pipe_box *box,
|
2021-01-08 17:43:52 +00:00
|
|
|
bool render_condition_enabled,
|
2019-02-26 20:08:23 +00:00
|
|
|
float depth)
|
|
|
|
{
|
|
|
|
struct pipe_resource *p_res = (void *) res;
|
2019-10-07 23:52:21 +01:00
|
|
|
struct pipe_context *ctx = (void *) ice;
|
|
|
|
struct iris_screen *screen = (void *) ctx->screen;
|
2021-04-05 21:19:39 +01:00
|
|
|
const struct intel_device_info *devinfo = &screen->devinfo;
|
2019-02-26 20:08:23 +00:00
|
|
|
|
2021-10-13 10:21:41 +01:00
|
|
|
if (INTEL_DEBUG(DEBUG_NO_FAST_CLEAR))
|
2019-10-08 01:12:14 +01:00
|
|
|
return false;
|
|
|
|
|
2019-02-26 20:08:23 +00:00
|
|
|
/* Check for partial clears */
|
|
|
|
if (box->x > 0 || box->y > 0 ||
|
|
|
|
box->width < u_minify(p_res->width0, level) ||
|
|
|
|
box->height < u_minify(p_res->height0, level)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-01-08 17:43:52 +00:00
|
|
|
/* Avoid conditional fast clears to maintain correct tracking of the aux
|
|
|
|
* state (see iris_resource_finish_write for more info). Note that partial
|
|
|
|
* fast clears would not pose a problem with conditional rendering.
|
|
|
|
*/
|
|
|
|
if (render_condition_enabled &&
|
|
|
|
ice->state.predicate == IRIS_PREDICATE_STATE_USE_BIT) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-12-14 19:36:29 +00:00
|
|
|
if (!iris_resource_level_has_hiz(res, level))
|
2019-02-26 20:08:23 +00:00
|
|
|
return false;
|
|
|
|
|
2020-11-19 00:17:42 +00:00
|
|
|
if (!blorp_can_hiz_clear_depth(devinfo, &res->surf, res->aux.usage,
|
|
|
|
level, box->z, box->x, box->y,
|
|
|
|
box->x + box->width,
|
|
|
|
box->y + box->height)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
2019-02-26 20:08:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
fast_clear_depth(struct iris_context *ice,
|
|
|
|
struct iris_resource *res,
|
|
|
|
unsigned level,
|
|
|
|
const struct pipe_box *box,
|
|
|
|
float depth)
|
|
|
|
{
|
|
|
|
struct iris_batch *batch = &ice->batches[IRIS_BATCH_RENDER];
|
|
|
|
|
2019-03-08 18:58:41 +00:00
|
|
|
bool update_clear_depth = false;
|
|
|
|
|
2019-02-26 20:08:23 +00:00
|
|
|
/* If we're clearing to a new clear value, then we need to resolve any clear
|
|
|
|
* flags out of the HiZ buffer into the real depth buffer.
|
|
|
|
*/
|
2021-07-26 20:59:42 +01:00
|
|
|
if (res->aux.clear_color_unknown || res->aux.clear_color.f32[0] != depth) {
|
2019-02-26 20:08:23 +00:00
|
|
|
for (unsigned res_level = 0; res_level < res->surf.levels; res_level++) {
|
|
|
|
const unsigned level_layers =
|
|
|
|
iris_get_num_logical_layers(res, res_level);
|
|
|
|
for (unsigned layer = 0; layer < level_layers; layer++) {
|
|
|
|
if (res_level == level &&
|
|
|
|
layer >= box->z &&
|
|
|
|
layer < box->z + box->depth) {
|
|
|
|
/* We're going to clear this layer anyway. Leave it alone. */
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
enum isl_aux_state aux_state =
|
|
|
|
iris_resource_get_aux_state(res, res_level, layer);
|
|
|
|
|
|
|
|
if (aux_state != ISL_AUX_STATE_CLEAR &&
|
|
|
|
aux_state != ISL_AUX_STATE_COMPRESSED_CLEAR) {
|
|
|
|
/* This slice doesn't have any fast-cleared bits. */
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If we got here, then the level may have fast-clear bits that
|
|
|
|
* use the old clear value. We need to do a depth resolve to get
|
|
|
|
* rid of their use of the clear value before we can change it.
|
|
|
|
* Fortunately, few applications ever change their depth clear
|
|
|
|
* value so this shouldn't happen often.
|
|
|
|
*/
|
|
|
|
iris_hiz_exec(ice, batch, res, res_level, layer, 1,
|
2019-03-08 18:58:41 +00:00
|
|
|
ISL_AUX_OP_FULL_RESOLVE, false);
|
2019-02-26 20:08:23 +00:00
|
|
|
iris_resource_set_aux_state(ice, res, res_level, layer, 1,
|
|
|
|
ISL_AUX_STATE_RESOLVED);
|
|
|
|
}
|
|
|
|
}
|
2019-02-20 00:07:09 +00:00
|
|
|
const union isl_color_value clear_value = { .f32 = {depth, } };
|
|
|
|
iris_resource_set_clear_color(ice, res, clear_value);
|
2019-03-08 18:58:41 +00:00
|
|
|
update_clear_depth = true;
|
2019-02-26 20:08:23 +00:00
|
|
|
}
|
|
|
|
|
2021-06-22 18:24:31 +01:00
|
|
|
if (res->aux.usage == ISL_AUX_USAGE_HIZ_CCS_WT) {
|
|
|
|
/* From Bspec 47010 (Depth Buffer Clear):
|
|
|
|
*
|
|
|
|
* Since the fast clear cycles to CCS are not cached in TileCache,
|
|
|
|
* any previous depth buffer writes to overlapping pixels must be
|
|
|
|
* flushed out of TileCache before a succeeding Depth Buffer Clear.
|
|
|
|
* This restriction only applies to Depth Buffer with write-thru
|
|
|
|
* enabled, since fast clears to CCS only occur for write-thru mode.
|
|
|
|
*
|
|
|
|
* There may have been a write to this depth buffer. Flush it from the
|
|
|
|
* tile cache just in case.
|
|
|
|
*/
|
|
|
|
iris_emit_pipe_control_flush(batch, "hiz_ccs_wt: before fast clear",
|
|
|
|
PIPE_CONTROL_DEPTH_CACHE_FLUSH |
|
|
|
|
PIPE_CONTROL_TILE_CACHE_FLUSH);
|
|
|
|
}
|
|
|
|
|
2019-02-26 20:08:23 +00:00
|
|
|
for (unsigned l = 0; l < box->depth; l++) {
|
|
|
|
enum isl_aux_state aux_state =
|
|
|
|
iris_resource_get_aux_state(res, level, box->z + l);
|
2020-03-05 23:17:40 +00:00
|
|
|
if (update_clear_depth || aux_state != ISL_AUX_STATE_CLEAR) {
|
|
|
|
if (aux_state == ISL_AUX_STATE_CLEAR) {
|
|
|
|
perf_debug(&ice->dbg, "Performing HiZ clear just to update the "
|
|
|
|
"depth clear value\n");
|
|
|
|
}
|
2019-02-26 20:08:23 +00:00
|
|
|
iris_hiz_exec(ice, batch, res, level,
|
2019-03-08 18:58:41 +00:00
|
|
|
box->z + l, 1, ISL_AUX_OP_FAST_CLEAR,
|
|
|
|
update_clear_depth);
|
2019-02-26 20:08:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
iris_resource_set_aux_state(ice, res, level, box->z, box->depth,
|
|
|
|
ISL_AUX_STATE_CLEAR);
|
|
|
|
ice->state.dirty |= IRIS_DIRTY_DEPTH_BUFFER;
|
2020-11-30 18:15:10 +00:00
|
|
|
ice->state.stage_dirty |= IRIS_ALL_STAGE_DIRTY_BINDINGS;
|
2019-02-26 20:08:23 +00:00
|
|
|
}
|
2019-02-11 01:13:29 +00:00
|
|
|
|
|
|
|
static void
|
|
|
|
clear_depth_stencil(struct iris_context *ice,
|
|
|
|
struct pipe_resource *p_res,
|
|
|
|
unsigned level,
|
|
|
|
const struct pipe_box *box,
|
|
|
|
bool render_condition_enabled,
|
|
|
|
bool clear_depth,
|
|
|
|
bool clear_stencil,
|
|
|
|
float depth,
|
|
|
|
uint8_t stencil)
|
|
|
|
{
|
|
|
|
struct iris_resource *res = (void *) p_res;
|
|
|
|
|
|
|
|
struct iris_batch *batch = &ice->batches[IRIS_BATCH_RENDER];
|
|
|
|
enum blorp_batch_flags blorp_flags = 0;
|
|
|
|
|
|
|
|
if (render_condition_enabled) {
|
|
|
|
if (ice->state.predicate == IRIS_PREDICATE_STATE_DONT_RENDER)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (ice->state.predicate == IRIS_PREDICATE_STATE_USE_BIT)
|
|
|
|
blorp_flags |= BLORP_BATCH_PREDICATE_ENABLE;
|
|
|
|
}
|
|
|
|
|
|
|
|
iris_batch_maybe_flush(batch, 1500);
|
|
|
|
|
|
|
|
struct iris_resource *z_res;
|
|
|
|
struct iris_resource *stencil_res;
|
|
|
|
struct blorp_surf z_surf;
|
|
|
|
struct blorp_surf stencil_surf;
|
|
|
|
|
|
|
|
iris_get_depth_stencil_resources(p_res, &z_res, &stencil_res);
|
2019-02-26 20:08:23 +00:00
|
|
|
if (z_res && clear_depth &&
|
2021-01-08 17:43:52 +00:00
|
|
|
can_fast_clear_depth(ice, z_res, level, box, render_condition_enabled,
|
|
|
|
depth)) {
|
2019-02-26 20:08:23 +00:00
|
|
|
fast_clear_depth(ice, z_res, level, box, depth);
|
2020-04-30 23:11:19 +01:00
|
|
|
iris_dirty_for_history(ice, res);
|
2019-02-26 20:08:23 +00:00
|
|
|
clear_depth = false;
|
|
|
|
z_res = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* At this point, we might have fast cleared the depth buffer. So if there's
|
|
|
|
* no stencil clear pending, return early.
|
|
|
|
*/
|
2020-07-02 09:39:25 +01:00
|
|
|
if (!(clear_depth || (clear_stencil && stencil_res))) {
|
2019-02-26 20:08:23 +00:00
|
|
|
return;
|
|
|
|
}
|
2019-02-11 01:13:29 +00:00
|
|
|
|
2019-08-28 08:21:20 +01:00
|
|
|
if (clear_depth && z_res) {
|
2020-12-14 19:10:02 +00:00
|
|
|
const enum isl_aux_usage aux_usage =
|
|
|
|
iris_resource_render_aux_usage(ice, z_res, level, z_res->surf.format,
|
|
|
|
false);
|
|
|
|
iris_resource_prepare_render(ice, z_res, level, box->z, box->depth,
|
|
|
|
aux_usage);
|
2020-05-06 23:40:30 +01:00
|
|
|
iris_emit_buffer_barrier_for(batch, z_res->bo, IRIS_DOMAIN_DEPTH_WRITE);
|
2020-12-14 19:10:02 +00:00
|
|
|
iris_blorp_surf_for_resource(&batch->screen->isl_dev, &z_surf,
|
2021-02-09 00:39:42 +00:00
|
|
|
&z_res->base.b, aux_usage, level, true);
|
2019-02-11 01:13:29 +00:00
|
|
|
}
|
|
|
|
|
2019-08-14 21:58:57 +01:00
|
|
|
uint8_t stencil_mask = clear_stencil && stencil_res ? 0xff : 0;
|
|
|
|
if (stencil_mask) {
|
2020-04-24 02:00:15 +01:00
|
|
|
iris_resource_prepare_access(ice, stencil_res, level, 1, box->z,
|
2019-08-14 21:58:57 +01:00
|
|
|
box->depth, stencil_res->aux.usage, false);
|
2020-05-06 23:40:30 +01:00
|
|
|
iris_emit_buffer_barrier_for(batch, stencil_res->bo,
|
|
|
|
IRIS_DOMAIN_DEPTH_WRITE);
|
2020-03-30 15:37:29 +01:00
|
|
|
iris_blorp_surf_for_resource(&batch->screen->isl_dev,
|
2021-02-09 00:39:42 +00:00
|
|
|
&stencil_surf, &stencil_res->base.b,
|
2019-11-05 23:08:01 +00:00
|
|
|
stencil_res->aux.usage, level, true);
|
2019-02-11 01:13:29 +00:00
|
|
|
}
|
|
|
|
|
2020-04-24 01:58:48 +01:00
|
|
|
iris_batch_sync_region_start(batch);
|
|
|
|
|
|
|
|
struct blorp_batch blorp_batch;
|
|
|
|
blorp_batch_init(&ice->blorp, &blorp_batch, batch, blorp_flags);
|
|
|
|
|
2019-02-11 01:13:29 +00:00
|
|
|
blorp_clear_depth_stencil(&blorp_batch, &z_surf, &stencil_surf,
|
|
|
|
level, box->z, box->depth,
|
|
|
|
box->x, box->y,
|
|
|
|
box->x + box->width,
|
|
|
|
box->y + box->height,
|
|
|
|
clear_depth && z_res, depth,
|
2019-08-14 21:58:57 +01:00
|
|
|
stencil_mask, stencil);
|
2019-02-11 01:13:29 +00:00
|
|
|
|
|
|
|
blorp_batch_finish(&blorp_batch);
|
2020-04-24 01:58:48 +01:00
|
|
|
iris_batch_sync_region_end(batch);
|
|
|
|
|
2020-04-30 23:11:19 +01:00
|
|
|
iris_dirty_for_history(ice, res);
|
2018-12-07 21:33:25 +00:00
|
|
|
|
2019-08-28 08:21:20 +01:00
|
|
|
if (clear_depth && z_res) {
|
2020-12-14 19:10:02 +00:00
|
|
|
iris_resource_finish_render(ice, z_res, level, box->z, box->depth,
|
|
|
|
z_surf.aux_usage);
|
2018-12-07 21:33:25 +00:00
|
|
|
}
|
2019-08-14 21:58:57 +01:00
|
|
|
|
|
|
|
if (stencil_mask) {
|
|
|
|
iris_resource_finish_write(ice, stencil_res, level, box->z, box->depth,
|
|
|
|
stencil_res->aux.usage);
|
|
|
|
}
|
2019-02-11 01:13:29 +00:00
|
|
|
}
|
|
|
|
|
2018-07-31 07:49:34 +01:00
|
|
|
/**
|
|
|
|
* The pipe->clear() driver hook.
|
|
|
|
*
|
|
|
|
* This clears buffers attached to the current draw framebuffer.
|
|
|
|
*/
|
2018-01-20 02:57:30 +00:00
|
|
|
static void
|
|
|
|
iris_clear(struct pipe_context *ctx,
|
|
|
|
unsigned buffers,
|
2020-03-24 16:02:51 +00:00
|
|
|
const struct pipe_scissor_state *scissor_state,
|
2018-06-24 23:16:34 +01:00
|
|
|
const union pipe_color_union *p_color,
|
2018-01-20 02:57:30 +00:00
|
|
|
double depth,
|
|
|
|
unsigned stencil)
|
|
|
|
{
|
2018-06-24 23:16:34 +01:00
|
|
|
struct iris_context *ice = (void *) ctx;
|
2018-06-27 06:41:07 +01:00
|
|
|
struct pipe_framebuffer_state *cso_fb = &ice->state.framebuffer;
|
2018-11-27 04:55:59 +00:00
|
|
|
|
2019-02-11 01:13:29 +00:00
|
|
|
assert(buffers != 0);
|
2018-06-24 23:16:34 +01:00
|
|
|
|
2020-03-24 15:58:29 +00:00
|
|
|
struct pipe_box box = {
|
|
|
|
.width = cso_fb->width,
|
|
|
|
.height = cso_fb->height,
|
|
|
|
};
|
|
|
|
|
|
|
|
if (scissor_state) {
|
|
|
|
box.x = scissor_state->minx;
|
|
|
|
box.y = scissor_state->miny;
|
|
|
|
box.width = MIN2(box.width, scissor_state->maxx - scissor_state->minx);
|
|
|
|
box.height = MIN2(box.height, scissor_state->maxy - scissor_state->miny);
|
|
|
|
}
|
|
|
|
|
2018-06-24 23:16:34 +01:00
|
|
|
if (buffers & PIPE_CLEAR_DEPTHSTENCIL) {
|
2018-06-27 06:41:07 +01:00
|
|
|
struct pipe_surface *psurf = cso_fb->zsbuf;
|
2019-02-11 01:13:29 +00:00
|
|
|
|
2020-03-24 15:58:29 +00:00
|
|
|
box.depth = psurf->u.tex.last_layer - psurf->u.tex.first_layer + 1;
|
|
|
|
box.z = psurf->u.tex.first_layer,
|
2019-02-11 01:13:29 +00:00
|
|
|
clear_depth_stencil(ice, psurf->texture, psurf->u.tex.level, &box, true,
|
|
|
|
buffers & PIPE_CLEAR_DEPTH,
|
|
|
|
buffers & PIPE_CLEAR_STENCIL,
|
2020-11-17 00:33:39 +00:00
|
|
|
depth, stencil);
|
2018-06-24 23:16:34 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (buffers & PIPE_CLEAR_COLOR) {
|
|
|
|
for (unsigned i = 0; i < cso_fb->nr_cbufs; i++) {
|
|
|
|
if (buffers & (PIPE_CLEAR_COLOR0 << i)) {
|
|
|
|
struct pipe_surface *psurf = cso_fb->cbufs[i];
|
|
|
|
struct iris_surface *isurf = (void *) psurf;
|
2020-03-24 15:58:29 +00:00
|
|
|
box.depth = psurf->u.tex.last_layer - psurf->u.tex.first_layer + 1,
|
|
|
|
box.z = psurf->u.tex.first_layer,
|
2019-02-11 01:13:29 +00:00
|
|
|
|
|
|
|
clear_color(ice, psurf->texture, psurf->u.tex.level, &box,
|
iris: Properly support alpha and luminance-alpha formats
For texturing, we map alpha formats to the corresponding red format,
as many alpha formats are outright missing, and red is more efficient
when sampling anyway.
When rendering to A8_UNORM, we use that format directly, so the image
gets the shader output's .a/.w channel, rather than the .r/.x channel.
All other A* formats are non-renderable, so we can't do much and just
mark them as unsupported for rendering. Fortunately, GL only requires
rendering to A8_UNORM, so that works out.
According to Andre Heider and Timur Kristóf, this fixes font rendering
in Witcher 1 (via nine). Andre also reported that it fixes Unigine
Heaven (presumably via nine).
v2: Use the same swizzle for both sampler views and "render targets".
BLORP expects the read swizzle, and will take the inverse when
setting up the destination swizzle (and actually applying it in
the shaders). We ignore the format swizzle when setting up normal
rendering SURFACE_STATEs, which is necessary because it would be
an illegal shader channel select combination. Thanks to Jason
Ekstrand for pointing out that BLORP took an inverse swizzle.
Tested-by: Timur Kristóf <timur.kristof@gmail.com>
Tested-by: Andre Heider <a.heider@gmail.com>
Reviewed-by: Jason Ekstrand <jason@jlekstrand.net>
2019-02-22 06:49:40 +00:00
|
|
|
true, isurf->view.format, isurf->view.swizzle,
|
2020-10-14 18:45:57 +01:00
|
|
|
convert_clear_color(psurf->format, p_color));
|
2018-06-24 23:16:34 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-01-20 02:57:30 +00:00
|
|
|
}
|
|
|
|
|
2019-02-11 01:13:29 +00:00
|
|
|
/**
|
|
|
|
* The pipe->clear_texture() driver hook.
|
|
|
|
*
|
|
|
|
* This clears the given texture resource.
|
|
|
|
*/
|
2018-08-15 09:34:10 +01:00
|
|
|
static void
|
|
|
|
iris_clear_texture(struct pipe_context *ctx,
|
|
|
|
struct pipe_resource *p_res,
|
|
|
|
unsigned level,
|
|
|
|
const struct pipe_box *box,
|
|
|
|
const void *data)
|
|
|
|
{
|
|
|
|
struct iris_context *ice = (void *) ctx;
|
2019-02-11 01:13:29 +00:00
|
|
|
struct iris_screen *screen = (void *) ctx->screen;
|
2021-04-05 21:19:39 +01:00
|
|
|
const struct intel_device_info *devinfo = &screen->devinfo;
|
2018-08-15 09:34:10 +01:00
|
|
|
|
|
|
|
if (util_format_is_depth_or_stencil(p_res->format)) {
|
2020-07-01 21:19:47 +01:00
|
|
|
const struct util_format_unpack_description *unpack =
|
|
|
|
util_format_unpack_description(p_res->format);
|
2018-08-15 09:34:10 +01:00
|
|
|
|
|
|
|
float depth = 0.0;
|
|
|
|
uint8_t stencil = 0;
|
|
|
|
|
2020-07-01 21:19:47 +01:00
|
|
|
if (unpack->unpack_z_float)
|
2019-11-08 20:30:02 +00:00
|
|
|
util_format_unpack_z_float(p_res->format, &depth, data, 1);
|
2018-08-15 09:34:10 +01:00
|
|
|
|
2020-07-01 21:19:47 +01:00
|
|
|
if (unpack->unpack_s_8uint)
|
2019-11-08 20:30:02 +00:00
|
|
|
util_format_unpack_s_8uint(p_res->format, &stencil, data, 1);
|
2018-08-15 09:34:10 +01:00
|
|
|
|
2019-02-11 01:13:29 +00:00
|
|
|
clear_depth_stencil(ice, p_res, level, box, true, true, true,
|
|
|
|
depth, stencil);
|
2018-08-15 09:34:10 +01:00
|
|
|
} else {
|
|
|
|
union isl_color_value color;
|
2019-02-11 01:13:29 +00:00
|
|
|
struct iris_resource *res = (void *) p_res;
|
2018-08-15 09:34:10 +01:00
|
|
|
enum isl_format format = res->surf.format;
|
|
|
|
|
|
|
|
if (!isl_format_supports_rendering(devinfo, format)) {
|
|
|
|
const struct isl_format_layout *fmtl = isl_format_get_layout(format);
|
|
|
|
// XXX: actually just get_copy_format_for_bpb from BLORP
|
|
|
|
// XXX: don't cut and paste this
|
|
|
|
switch (fmtl->bpb) {
|
|
|
|
case 8: format = ISL_FORMAT_R8_UINT; break;
|
|
|
|
case 16: format = ISL_FORMAT_R8G8_UINT; break;
|
|
|
|
case 24: format = ISL_FORMAT_R8G8B8_UINT; break;
|
|
|
|
case 32: format = ISL_FORMAT_R8G8B8A8_UINT; break;
|
|
|
|
case 48: format = ISL_FORMAT_R16G16B16_UINT; break;
|
|
|
|
case 64: format = ISL_FORMAT_R16G16B16A16_UINT; break;
|
|
|
|
case 96: format = ISL_FORMAT_R32G32B32_UINT; break;
|
|
|
|
case 128: format = ISL_FORMAT_R32G32B32A32_UINT; break;
|
|
|
|
default:
|
|
|
|
unreachable("Unknown format bpb");
|
|
|
|
}
|
2018-12-07 21:33:25 +00:00
|
|
|
|
|
|
|
/* No aux surfaces for non-renderable surfaces */
|
|
|
|
assert(res->aux.usage == ISL_AUX_USAGE_NONE);
|
2018-08-15 09:34:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
isl_color_value_unpack(&color, format, data);
|
|
|
|
|
iris: Properly support alpha and luminance-alpha formats
For texturing, we map alpha formats to the corresponding red format,
as many alpha formats are outright missing, and red is more efficient
when sampling anyway.
When rendering to A8_UNORM, we use that format directly, so the image
gets the shader output's .a/.w channel, rather than the .r/.x channel.
All other A* formats are non-renderable, so we can't do much and just
mark them as unsupported for rendering. Fortunately, GL only requires
rendering to A8_UNORM, so that works out.
According to Andre Heider and Timur Kristóf, this fixes font rendering
in Witcher 1 (via nine). Andre also reported that it fixes Unigine
Heaven (presumably via nine).
v2: Use the same swizzle for both sampler views and "render targets".
BLORP expects the read swizzle, and will take the inverse when
setting up the destination swizzle (and actually applying it in
the shaders). We ignore the format swizzle when setting up normal
rendering SURFACE_STATEs, which is necessary because it would be
an illegal shader channel select combination. Thanks to Jason
Ekstrand for pointing out that BLORP took an inverse swizzle.
Tested-by: Timur Kristóf <timur.kristof@gmail.com>
Tested-by: Andre Heider <a.heider@gmail.com>
Reviewed-by: Jason Ekstrand <jason@jlekstrand.net>
2019-02-22 06:49:40 +00:00
|
|
|
clear_color(ice, p_res, level, box, true, format,
|
|
|
|
ISL_SWIZZLE_IDENTITY, color);
|
2018-08-15 09:34:10 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-11 01:13:29 +00:00
|
|
|
/**
|
|
|
|
* The pipe->clear_render_target() driver hook.
|
|
|
|
*
|
|
|
|
* This clears the given render target surface.
|
|
|
|
*/
|
2018-01-20 02:57:30 +00:00
|
|
|
static void
|
|
|
|
iris_clear_render_target(struct pipe_context *ctx,
|
2019-02-11 01:13:29 +00:00
|
|
|
struct pipe_surface *psurf,
|
|
|
|
const union pipe_color_union *p_color,
|
2018-01-20 02:57:30 +00:00
|
|
|
unsigned dst_x, unsigned dst_y,
|
|
|
|
unsigned width, unsigned height,
|
|
|
|
bool render_condition_enabled)
|
|
|
|
{
|
2019-02-11 01:13:29 +00:00
|
|
|
struct iris_context *ice = (void *) ctx;
|
|
|
|
struct iris_surface *isurf = (void *) psurf;
|
|
|
|
struct pipe_box box = {
|
|
|
|
.x = dst_x,
|
|
|
|
.y = dst_y,
|
|
|
|
.z = psurf->u.tex.first_layer,
|
|
|
|
.width = width,
|
|
|
|
.height = height,
|
|
|
|
.depth = psurf->u.tex.last_layer - psurf->u.tex.first_layer + 1
|
|
|
|
};
|
|
|
|
|
2019-02-15 23:23:56 +00:00
|
|
|
clear_color(ice, psurf->texture, psurf->u.tex.level, &box,
|
|
|
|
render_condition_enabled,
|
2020-10-14 18:45:57 +01:00
|
|
|
isurf->view.format, isurf->view.swizzle,
|
|
|
|
convert_clear_color(psurf->format, p_color));
|
2018-01-20 02:57:30 +00:00
|
|
|
}
|
|
|
|
|
2019-02-11 01:13:29 +00:00
|
|
|
/**
|
|
|
|
* The pipe->clear_depth_stencil() driver hook.
|
|
|
|
*
|
|
|
|
* This clears the given depth/stencil surface.
|
|
|
|
*/
|
2018-01-20 02:57:30 +00:00
|
|
|
static void
|
|
|
|
iris_clear_depth_stencil(struct pipe_context *ctx,
|
2019-02-11 01:13:29 +00:00
|
|
|
struct pipe_surface *psurf,
|
|
|
|
unsigned flags,
|
2018-01-20 02:57:30 +00:00
|
|
|
double depth,
|
|
|
|
unsigned stencil,
|
|
|
|
unsigned dst_x, unsigned dst_y,
|
|
|
|
unsigned width, unsigned height,
|
|
|
|
bool render_condition_enabled)
|
|
|
|
{
|
2019-02-11 01:13:29 +00:00
|
|
|
struct iris_context *ice = (void *) ctx;
|
|
|
|
struct pipe_box box = {
|
|
|
|
.x = dst_x,
|
|
|
|
.y = dst_y,
|
|
|
|
.z = psurf->u.tex.first_layer,
|
|
|
|
.width = width,
|
|
|
|
.height = height,
|
|
|
|
.depth = psurf->u.tex.last_layer - psurf->u.tex.first_layer + 1
|
|
|
|
};
|
|
|
|
|
|
|
|
assert(util_format_is_depth_or_stencil(psurf->texture->format));
|
|
|
|
|
2019-02-15 23:23:56 +00:00
|
|
|
clear_depth_stencil(ice, psurf->texture, psurf->u.tex.level, &box,
|
|
|
|
render_condition_enabled,
|
2019-02-11 01:13:29 +00:00
|
|
|
flags & PIPE_CLEAR_DEPTH, flags & PIPE_CLEAR_STENCIL,
|
2020-11-17 00:33:39 +00:00
|
|
|
depth, stencil);
|
2018-01-20 02:57:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
iris_init_clear_functions(struct pipe_context *ctx)
|
|
|
|
{
|
|
|
|
ctx->clear = iris_clear;
|
2018-08-15 09:34:10 +01:00
|
|
|
ctx->clear_texture = iris_clear_texture;
|
2018-01-20 02:57:30 +00:00
|
|
|
ctx->clear_render_target = iris_clear_render_target;
|
|
|
|
ctx->clear_depth_stencil = iris_clear_depth_stencil;
|
|
|
|
}
|