This adds modifier support to radeonsi. It has been tested on
- VEGA10, RAVEN, NAVI14 - weston, sway, X with xf86-video-amdgpu (i.e. legacy path still works)
and includes some basic testing of the layout code.
The main goal is to keep it somewhat simple and regression free, so on the display side this series only exposes what the current GPU can render to. While we could expose more I think that is more suitable for follow-up work as the benefit would be minimal and there are some more design discussion there to discuss that are orthogonal from the initial implementation.
Similarly this series only exposes 32-bpp displayable DCC in the cases that radeonsi would use it and any extra capabilities here should be future work.
I believe these are by far the most complicated modifiers we've seen up till now, mostly related to
- GPU identification for cases where it matters wrt tiling. - Every generation having tiling layout changes - Compression settings.
I believe the complexity is necessary as every layout should be different and all layouts should be the best in some situation (though not all combinations of GPU parameters will actually have an existing GPU).
That said, on the render side the number of modifiers actually listed for a given GPU is ~10, and in the current implementation that is the same for the display side. (we could expose more actually differing layouts on the display side for cross-GPU compatibility, but I consider that out of scope for this initial work).
This series can be found on https://github.com/BNieuwenhuizen/linux/tree/modifiers
An userspace implementation in radeonsi can be found on https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6176
Bas Nieuwenhuizen (8): drm/amd/display: Do not silently accept DCC for multiplane formats. drm/amd: Init modifier field of helper fb. drm/amd/display: Honor the offset for plane 0. drm/fourcc: Add AMD DRM modifiers. drm/amd/display: Refactor surface tiling setup. drm/amd/display: Set DC options from modifiers. drm/amd/display: Add formats for DCC with 2/3 planes. drm/amd/display: Expose modifiers.
drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c | 2 +- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 758 +++++++++++++++--- include/uapi/drm/drm_fourcc.h | 115 +++ 3 files changed, 775 insertions(+), 100 deletions(-)
Silently accepting it could result in corruption.
Signed-off-by: Bas Nieuwenhuizen bas@basnieuwenhuizen.nl --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index f348693217d8..005331c772b7 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3637,7 +3637,7 @@ fill_plane_dcc_attributes(struct amdgpu_device *adev, return 0;
if (format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) - return 0; + return -EINVAL;
if (!dc->cap_funcs.get_dcc_compression_cap) return -EINVAL;
Otherwise the field ends up being used uninitialized when enabling modifiers, failing validation with high likelihood.
Signed-off-by: Bas Nieuwenhuizen bas@basnieuwenhuizen.nl --- drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c index 25ddb482466a..c2d6952d0a7d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c @@ -201,7 +201,7 @@ static int amdgpufb_create(struct drm_fb_helper *helper, struct amdgpu_device *adev = rfbdev->adev; struct fb_info *info; struct drm_framebuffer *fb = NULL; - struct drm_mode_fb_cmd2 mode_cmd; + struct drm_mode_fb_cmd2 mode_cmd = {0}; struct drm_gem_object *gobj = NULL; struct amdgpu_bo *abo = NULL; int ret;
With modifiers I'd like to support non-dedicated buffers for images.
Signed-off-by: Bas Nieuwenhuizen bas@basnieuwenhuizen.nl --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 005331c772b7..abc70fbe176d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3623,6 +3623,7 @@ fill_plane_dcc_attributes(struct amdgpu_device *adev, struct dc *dc = adev->dm.dc; struct dc_dcc_surface_param input; struct dc_surface_dcc_cap output; + uint64_t plane_address = afb->address + afb->base.offsets[0]; uint32_t offset = AMDGPU_TILING_GET(info, DCC_OFFSET_256B); uint32_t i64b = AMDGPU_TILING_GET(info, DCC_INDEPENDENT_64B) != 0; uint64_t dcc_address; @@ -3666,7 +3667,7 @@ fill_plane_dcc_attributes(struct amdgpu_device *adev, AMDGPU_TILING_GET(info, DCC_PITCH_MAX) + 1; dcc->independent_64b_blks = i64b;
- dcc_address = get_dcc_address(afb->address, info); + dcc_address = get_dcc_address(plane_address, info); address->grph.meta_addr.low_part = lower_32_bits(dcc_address); address->grph.meta_addr.high_part = upper_32_bits(dcc_address);
@@ -3697,6 +3698,8 @@ fill_plane_buffer_attributes(struct amdgpu_device *adev, address->tmz_surface = tmz_surface;
if (format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { + uint64_t addr = afb->address + fb->offsets[0]; + plane_size->surface_size.x = 0; plane_size->surface_size.y = 0; plane_size->surface_size.width = fb->width; @@ -3705,9 +3708,10 @@ fill_plane_buffer_attributes(struct amdgpu_device *adev, fb->pitches[0] / fb->format->cpp[0];
address->type = PLN_ADDR_TYPE_GRAPHICS; - address->grph.addr.low_part = lower_32_bits(afb->address); - address->grph.addr.high_part = upper_32_bits(afb->address); + address->grph.addr.low_part = lower_32_bits(addr); + address->grph.addr.high_part = upper_32_bits(addr); } else if (format < SURFACE_PIXEL_FORMAT_INVALID) { + uint64_t luma_addr = afb->address + fb->offsets[0]; uint64_t chroma_addr = afb->address + fb->offsets[1];
plane_size->surface_size.x = 0; @@ -3728,9 +3732,9 @@ fill_plane_buffer_attributes(struct amdgpu_device *adev,
address->type = PLN_ADDR_TYPE_VIDEO_PROGRESSIVE; address->video_progressive.luma_addr.low_part = - lower_32_bits(afb->address); + lower_32_bits(luma_addr); address->video_progressive.luma_addr.high_part = - upper_32_bits(afb->address); + upper_32_bits(luma_addr); address->video_progressive.chroma_addr.low_part = lower_32_bits(chroma_addr); address->video_progressive.chroma_addr.high_part =
On Tue, Aug 04, 2020 at 11:31:14PM +0200, Bas Nieuwenhuizen wrote:
With modifiers I'd like to support non-dedicated buffers for images.
Signed-off-by: Bas Nieuwenhuizen bas@basnieuwenhuizen.nl
Uh, I think it'd be really good to preceed this with a bugfix (cc: stable) which checks that the offset is 0). And then this patch here removing that again. Or cc: stable this patch here, since we seem to have a gap in validating addfb. -Daniel
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 005331c772b7..abc70fbe176d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3623,6 +3623,7 @@ fill_plane_dcc_attributes(struct amdgpu_device *adev, struct dc *dc = adev->dm.dc; struct dc_dcc_surface_param input; struct dc_surface_dcc_cap output;
- uint64_t plane_address = afb->address + afb->base.offsets[0]; uint32_t offset = AMDGPU_TILING_GET(info, DCC_OFFSET_256B); uint32_t i64b = AMDGPU_TILING_GET(info, DCC_INDEPENDENT_64B) != 0; uint64_t dcc_address;
@@ -3666,7 +3667,7 @@ fill_plane_dcc_attributes(struct amdgpu_device *adev, AMDGPU_TILING_GET(info, DCC_PITCH_MAX) + 1; dcc->independent_64b_blks = i64b;
- dcc_address = get_dcc_address(afb->address, info);
- dcc_address = get_dcc_address(plane_address, info); address->grph.meta_addr.low_part = lower_32_bits(dcc_address); address->grph.meta_addr.high_part = upper_32_bits(dcc_address);
@@ -3697,6 +3698,8 @@ fill_plane_buffer_attributes(struct amdgpu_device *adev, address->tmz_surface = tmz_surface;
if (format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) {
uint64_t addr = afb->address + fb->offsets[0];
- plane_size->surface_size.x = 0; plane_size->surface_size.y = 0; plane_size->surface_size.width = fb->width;
@@ -3705,9 +3708,10 @@ fill_plane_buffer_attributes(struct amdgpu_device *adev, fb->pitches[0] / fb->format->cpp[0];
address->type = PLN_ADDR_TYPE_GRAPHICS;
address->grph.addr.low_part = lower_32_bits(afb->address);
address->grph.addr.high_part = upper_32_bits(afb->address);
address->grph.addr.low_part = lower_32_bits(addr);
address->grph.addr.high_part = upper_32_bits(addr);
} else if (format < SURFACE_PIXEL_FORMAT_INVALID) {
uint64_t luma_addr = afb->address + fb->offsets[0];
uint64_t chroma_addr = afb->address + fb->offsets[1];
plane_size->surface_size.x = 0;
@@ -3728,9 +3732,9 @@ fill_plane_buffer_attributes(struct amdgpu_device *adev,
address->type = PLN_ADDR_TYPE_VIDEO_PROGRESSIVE; address->video_progressive.luma_addr.low_part =
lower_32_bits(afb->address);
address->video_progressive.luma_addr.high_part =lower_32_bits(luma_addr);
upper_32_bits(afb->address);
address->video_progressive.chroma_addr.low_part = lower_32_bits(chroma_addr); address->video_progressive.chroma_addr.high_part =upper_32_bits(luma_addr);
-- 2.28.0
This adds modifiers for GFX9+ AMD GPUs.
As the modifiers need a lot of parameters I split things out in getters and setters. - Advantage: simplifies the code a lot - Disadvantage: Makes it harder to check that you're setting all the required fields.
The tiling modes seem to change every generatio, but the structure of what each tiling mode is good for stays really similar. As such the core of the modifier is - the tiling mode - a version. Not explicitly a GPU generation, but splitting out a new set of tiling equations.
Sometimes one or two tiling modes stay the same and for those we specify a canonical version.
Then we have a bunch of parameters on how the compression works. Different HW units have different requirements for these and we actually have some conflicts here.
e.g. the render backends need a specific alignment but the display unit only works with unaligned compression surfaces. To work around that we have a DCC_RETILE option where both an aligned and unaligned compression surface are allocated and a writer has to sync the aligned surface to the unaligned surface on handoff.
Finally there are some GPU parameters that participate in the tiling equations. These are constant for each GPU on the rendering/texturing side. The display unit is very flexible however and supports all of them :|
Some estimates: - Single GPU, render+texture: ~10 modifiers - All possible configs in a gen, display: ~1000 modifiers - Configs of actually existing GPUs in a gen: ~100 modifiers
For formats with a single plane everything gets put in a separate DRM plane. However, this doesn't fit for some YUV formats, so if the format has >1 plane, we let the driver pack the surfaces into 1 DRM plane per format plane.
This way we avoid X11 rendering onto the frontbuffer with DCC, but still fit into 4 DRM planes.
Signed-off-by: Bas Nieuwenhuizen bas@basnieuwenhuizen.nl --- include/uapi/drm/drm_fourcc.h | 115 ++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+)
diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h index 8bc0b31597d8..2f8d2b717285 100644 --- a/include/uapi/drm/drm_fourcc.h +++ b/include/uapi/drm/drm_fourcc.h @@ -804,6 +804,121 @@ extern "C" { */ #define DRM_FORMAT_MOD_ALLWINNER_TILED fourcc_mod_code(ALLWINNER, 1)
+/* + * AMD modifiers + * + * Memory layout: + * + * without DCC: + * - main surface + * + * with DCC & without DCC_RETILE: + * - main surface in plane 0 + * - DCC surface in plane 1 (RB-aligned, pipe-aligned if DCC_PIPE_ALIGN is set) + * + * with DCC & DCC_RETILE: + * - main surface in plane 0 + * - displayable DCC surface in plane 1 (not RB-aligned & not pipe-aligned) + * - pipe-aligned DCC surface in plane 2 (RB-aligned & pipe-aligned) + * + * For multi-plane formats the above surfaces get merged into one plane for + * each for format plane, based on the required alignment only. + */ +#define AMD_FMT_MOD fourcc_mod_code(AMD, 0) + +#define IS_AMD_FMT_MOD(val) (((val) >> 56) == DRM_FORMAT_MOD_VENDOR_AMD) + +/* Reserve 0 for GFX8 and older */ +#define AMD_FMT_MOD_TILE_VER_GFX9 1 +#define AMD_FMT_MOD_TILE_VER_GFX10 2 +#define AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS 3 + +/* + * 64K_S is the same for GFX9/GFX10/GFX10_RBPLUS and hence has GFX9 as canonical + * version. + */ +#define AMD_FMT_MOD_TILE_GFX9_64K_S 9 + +/* + * 64K_D for non-32 bpp is the same for GFX9/GFX10/GFX10_RBPLUS and hence has + * GFX9 as canonical version. + */ +#define AMD_FMT_MOD_TILE_GFX9_64K_D 10 +#define AMD_FMT_MOD_TILE_GFX9_64K_S_X 25 +#define AMD_FMT_MOD_TILE_GFX9_64K_D_X 26 +#define AMD_FMT_MOD_TILE_GFX9_64K_R_X 27 + +#define AMD_FMT_MOD_DCC_BLOCK_64B 0 +#define AMD_FMT_MOD_DCC_BLOCK_128B 1 +#define AMD_FMT_MOD_DCC_BLOCK_256B 2 + +#define AMD_FMT_MOD_TILE_VERSION_SHIFT 0 +#define AMD_FMT_MOD_TILE_VERSION_MASK 0xFF +#define AMD_FMT_MOD_TILE_SHIFT 8 +#define AMD_FMT_MOD_TILE_MASK 0x1F + +/* Whether DCC compression is enabled. */ +#define AMD_FMT_MOD_DCC_SHIFT 13 +#define AMD_FMT_MOD_DCC_MASK 0x1 + +/* + * Whether to include two DCC surfaces, one which is rb & pipe aligned, and + * one which is not-aligned. + */ +#define AMD_FMT_MOD_DCC_RETILE_SHIFT 14 +#define AMD_FMT_MOD_DCC_RETILE_MASK 0x1 + +/* Only set if DCC_RETILE = false */ +#define AMD_FMT_MOD_DCC_PIPE_ALIGN_SHIFT 15 +#define AMD_FMT_MOD_DCC_PIPE_ALIGN_MASK 0x1 + +#define AMD_FMT_MOD_DCC_INDEPENDENT_64B_SHIFT 16 +#define AMD_FMT_MOD_DCC_INDEPENDENT_64B_MASK 0x1 +#define AMD_FMT_MOD_DCC_INDEPENDENT_128B_SHIFT 17 +#define AMD_FMT_MOD_DCC_INDEPENDENT_128B_MASK 0x1 +#define AMD_FMT_MOD_DCC_MAX_COMPRESSED_BLOCK_SHIFT 18 +#define AMD_FMT_MOD_DCC_MAX_COMPRESSED_BLOCK_MASK 0x1 + +/* + * DCC supports embedding some clear colors directly in the DCC surface. + * However, on older GPUs the rendering HW ignores the embedded clear color + * and prefers the driver provided color. This necessitates doing a fastclear + * eliminate operation before a process transfers control. + * + * If this bit is set that means the fastclear eliminate is not needed for these + * embeddable colors. + */ +#define AMD_FMT_MOD_DCC_CONSTANT_ENCODE_SHIFT 19 +#define AMD_FMT_MOD_DCC_CONSTANT_ENCODE_MASK 0x1 + +/* + * The below fields are for accounting for per GPU differences. These are only + * relevant for GFX9 and later and if the tile field is *_X/_T. + * + * PIPE_XOR_BITS = always needed + * BANK_XOR_BITS = only for TILE_VER_GFX9 + * PACKERS = only for TILE_VER_GFX10_RBPLUS + * RB = only for TILE_VER_GFX9 & DCC + * PIPE = only for TILE_VER_GFX9 & DCC & (DCC_RETILE | DCC_PIPE_ALIGN) + */ +#define AMD_FMT_MOD_PIPE_XOR_BITS_SHIFT 20 +#define AMD_FMT_MOD_PIPE_XOR_BITS_MASK 0x7 +#define AMD_FMT_MOD_BANK_XOR_BITS_SHIFT 23 +#define AMD_FMT_MOD_BANK_XOR_BITS_MASK 0x7 +#define AMD_FMT_MOD_PACKERS_SHIFT 26 /* aliases with BANK_XOR_BITS */ +#define AMD_FMT_MOD_PACKERS_MASK 0x7 +#define AMD_FMT_MOD_RB_SHIFT 29 +#define AMD_FMT_MOD_RB_MASK 0x7 +#define AMD_FMT_MOD_PIPE_SHIFT 32 +#define AMD_FMT_MOD_PIPE_MASK 0x7 + +#define AMD_FMT_MOD_SET(field, value) \ + ((uint64_t)(value) << AMD_FMT_MOD_##field##_SHIFT) +#define AMD_FMT_MOD_GET(field, value) \ + (((value) >> AMD_FMT_MOD_##field##_SHIFT) & AMD_FMT_MOD_##field##_MASK) +#define AMD_FMT_MOD_CLEAR(field) \ + (~((uint64_t)AMD_FMT_MOD_##field##_MASK << AMD_FMT_MOD_##field##_SHIFT)) + #if defined(__cplusplus) } #endif
Prepare for inserting modifiers based configuration, while sharing a bunch of DCC validation & initializing the device-based configuration.
Signed-off-by: Bas Nieuwenhuizen bas@basnieuwenhuizen.nl --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 209 ++++++++++-------- 1 file changed, 116 insertions(+), 93 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index abc70fbe176d..6ef7f2f8acab 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3601,46 +3601,83 @@ static int get_fb_info(const struct amdgpu_framebuffer *amdgpu_fb, return r; }
-static inline uint64_t get_dcc_address(uint64_t address, uint64_t tiling_flags) +static void +fill_gfx8_tiling_info_from_flags(union dc_tiling_info *tiling_info, + uint64_t tiling_flags) { - uint32_t offset = AMDGPU_TILING_GET(tiling_flags, DCC_OFFSET_256B); + /* Fill GFX8 params */ + if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE) == DC_ARRAY_2D_TILED_THIN1) { + unsigned int bankw, bankh, mtaspect, tile_split, num_banks; + + bankw = AMDGPU_TILING_GET(tiling_flags, BANK_WIDTH); + bankh = AMDGPU_TILING_GET(tiling_flags, BANK_HEIGHT); + mtaspect = AMDGPU_TILING_GET(tiling_flags, MACRO_TILE_ASPECT); + tile_split = AMDGPU_TILING_GET(tiling_flags, TILE_SPLIT); + num_banks = AMDGPU_TILING_GET(tiling_flags, NUM_BANKS);
- return offset ? (address + offset * 256) : 0; + /* XXX fix me for VI */ + tiling_info->gfx8.num_banks = num_banks; + tiling_info->gfx8.array_mode = + DC_ARRAY_2D_TILED_THIN1; + tiling_info->gfx8.tile_split = tile_split; + tiling_info->gfx8.bank_width = bankw; + tiling_info->gfx8.bank_height = bankh; + tiling_info->gfx8.tile_aspect = mtaspect; + tiling_info->gfx8.tile_mode = + DC_ADDR_SURF_MICRO_TILING_DISPLAY; + } else if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE) + == DC_ARRAY_1D_TILED_THIN1) { + tiling_info->gfx8.array_mode = DC_ARRAY_1D_TILED_THIN1; + } + + tiling_info->gfx8.pipe_config = + AMDGPU_TILING_GET(tiling_flags, PIPE_CONFIG); +} + +static void +fill_gfx9_tiling_info_from_device(const struct amdgpu_device *adev, + union dc_tiling_info *tiling_info) +{ + tiling_info->gfx9.num_pipes = + adev->gfx.config.gb_addr_config_fields.num_pipes; + tiling_info->gfx9.num_banks = + adev->gfx.config.gb_addr_config_fields.num_banks; + tiling_info->gfx9.pipe_interleave = + adev->gfx.config.gb_addr_config_fields.pipe_interleave_size; + tiling_info->gfx9.num_shader_engines = + adev->gfx.config.gb_addr_config_fields.num_se; + tiling_info->gfx9.max_compressed_frags = + adev->gfx.config.gb_addr_config_fields.max_compress_frags; + tiling_info->gfx9.num_rb_per_se = + adev->gfx.config.gb_addr_config_fields.num_rb_per_se; + tiling_info->gfx9.shaderEnable = 1; +#ifdef CONFIG_DRM_AMD_DC_DCN3_0 + if (adev->asic_type == CHIP_SIENNA_CICHLID) + tiling_info->gfx9.num_pkrs = adev->gfx.config.gb_addr_config_fields.num_pkrs; +#endif }
static int -fill_plane_dcc_attributes(struct amdgpu_device *adev, - const struct amdgpu_framebuffer *afb, - const enum surface_pixel_format format, - const enum dc_rotation_angle rotation, - const struct plane_size *plane_size, - const union dc_tiling_info *tiling_info, - const uint64_t info, - struct dc_plane_dcc_param *dcc, - struct dc_plane_address *address, - bool force_disable_dcc) +validate_dcc(struct amdgpu_device *adev, + const enum surface_pixel_format format, + const enum dc_rotation_angle rotation, + const union dc_tiling_info *tiling_info, + const struct dc_plane_dcc_param *dcc, + const struct dc_plane_address *address, + const struct plane_size *plane_size) { struct dc *dc = adev->dm.dc; struct dc_dcc_surface_param input; struct dc_surface_dcc_cap output; - uint64_t plane_address = afb->address + afb->base.offsets[0]; - uint32_t offset = AMDGPU_TILING_GET(info, DCC_OFFSET_256B); - uint32_t i64b = AMDGPU_TILING_GET(info, DCC_INDEPENDENT_64B) != 0; - uint64_t dcc_address;
memset(&input, 0, sizeof(input)); memset(&output, 0, sizeof(output));
- if (force_disable_dcc) - return 0; - - if (!offset) + if (!dcc->enable) return 0;
- if (format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) - return -EINVAL; - - if (!dc->cap_funcs.get_dcc_compression_cap) + if (format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN || + !dc->cap_funcs.get_dcc_compression_cap) return -EINVAL;
input.format = format; @@ -3659,17 +3696,60 @@ fill_plane_dcc_attributes(struct amdgpu_device *adev, if (!output.capable) return -EINVAL;
- if (i64b == 0 && output.grph.rgb.independent_64b_blks != 0) + if (dcc->independent_64b_blks == 0 && + output.grph.rgb.independent_64b_blks != 0) return -EINVAL;
+ return 0; +} + +static void +fill_dcc_params_from_flags(const struct amdgpu_framebuffer *afb, + struct dc_plane_dcc_param *dcc, + struct dc_plane_address *address, + const uint64_t flags, bool force_disable_dcc) +{ + uint64_t dcc_address; + uint64_t plane_address = afb->address + afb->base.offsets[0]; + uint32_t offset = AMDGPU_TILING_GET(flags, DCC_OFFSET_256B); + uint32_t i64b = AMDGPU_TILING_GET(flags, DCC_INDEPENDENT_64B) != 0; + + if (!offset || force_disable_dcc) + return; + dcc->enable = 1; - dcc->meta_pitch = - AMDGPU_TILING_GET(info, DCC_PITCH_MAX) + 1; + dcc->meta_pitch = AMDGPU_TILING_GET(flags, DCC_PITCH_MAX) + 1; dcc->independent_64b_blks = i64b;
- dcc_address = get_dcc_address(plane_address, info); + dcc_address = plane_address + (uint64_t)offset * 256; address->grph.meta_addr.low_part = lower_32_bits(dcc_address); address->grph.meta_addr.high_part = upper_32_bits(dcc_address); +} + + +static int +fill_gfx9_plane_attributes_from_flags(struct amdgpu_device *adev, + const struct amdgpu_framebuffer *afb, + const enum surface_pixel_format format, + const enum dc_rotation_angle rotation, + const struct plane_size *plane_size, + union dc_tiling_info *tiling_info, + struct dc_plane_dcc_param *dcc, + struct dc_plane_address *address, + uint64_t tiling_flags, + bool force_disable_dcc) +{ + int ret; + + fill_gfx9_tiling_info_from_device(adev, tiling_info); + + tiling_info->gfx9.swizzle = + AMDGPU_TILING_GET(tiling_flags, SWIZZLE_MODE); + + fill_dcc_params_from_flags(afb, dcc, address, tiling_flags, force_disable_dcc); + ret = validate_dcc(adev, format, rotation, tiling_info, dcc, address, plane_size); + if (ret) + return ret;
return 0; } @@ -3741,73 +3821,16 @@ fill_plane_buffer_attributes(struct amdgpu_device *adev, upper_32_bits(chroma_addr); }
- /* Fill GFX8 params */ - if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE) == DC_ARRAY_2D_TILED_THIN1) { - unsigned int bankw, bankh, mtaspect, tile_split, num_banks; - - bankw = AMDGPU_TILING_GET(tiling_flags, BANK_WIDTH); - bankh = AMDGPU_TILING_GET(tiling_flags, BANK_HEIGHT); - mtaspect = AMDGPU_TILING_GET(tiling_flags, MACRO_TILE_ASPECT); - tile_split = AMDGPU_TILING_GET(tiling_flags, TILE_SPLIT); - num_banks = AMDGPU_TILING_GET(tiling_flags, NUM_BANKS); - - /* XXX fix me for VI */ - tiling_info->gfx8.num_banks = num_banks; - tiling_info->gfx8.array_mode = - DC_ARRAY_2D_TILED_THIN1; - tiling_info->gfx8.tile_split = tile_split; - tiling_info->gfx8.bank_width = bankw; - tiling_info->gfx8.bank_height = bankh; - tiling_info->gfx8.tile_aspect = mtaspect; - tiling_info->gfx8.tile_mode = - DC_ADDR_SURF_MICRO_TILING_DISPLAY; - } else if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE) - == DC_ARRAY_1D_TILED_THIN1) { - tiling_info->gfx8.array_mode = DC_ARRAY_1D_TILED_THIN1; - } - - tiling_info->gfx8.pipe_config = - AMDGPU_TILING_GET(tiling_flags, PIPE_CONFIG);
- if (adev->asic_type == CHIP_VEGA10 || - adev->asic_type == CHIP_VEGA12 || - adev->asic_type == CHIP_VEGA20 || - adev->asic_type == CHIP_NAVI10 || - adev->asic_type == CHIP_NAVI14 || - adev->asic_type == CHIP_NAVI12 || -#if defined(CONFIG_DRM_AMD_DC_DCN3_0) - adev->asic_type == CHIP_SIENNA_CICHLID || -#endif - adev->asic_type == CHIP_RENOIR || - adev->asic_type == CHIP_RAVEN) { - /* Fill GFX9 params */ - tiling_info->gfx9.num_pipes = - adev->gfx.config.gb_addr_config_fields.num_pipes; - tiling_info->gfx9.num_banks = - adev->gfx.config.gb_addr_config_fields.num_banks; - tiling_info->gfx9.pipe_interleave = - adev->gfx.config.gb_addr_config_fields.pipe_interleave_size; - tiling_info->gfx9.num_shader_engines = - adev->gfx.config.gb_addr_config_fields.num_se; - tiling_info->gfx9.max_compressed_frags = - adev->gfx.config.gb_addr_config_fields.max_compress_frags; - tiling_info->gfx9.num_rb_per_se = - adev->gfx.config.gb_addr_config_fields.num_rb_per_se; - tiling_info->gfx9.swizzle = - AMDGPU_TILING_GET(tiling_flags, SWIZZLE_MODE); - tiling_info->gfx9.shaderEnable = 1; - -#ifdef CONFIG_DRM_AMD_DC_DCN3_0 - if (adev->asic_type == CHIP_SIENNA_CICHLID) - tiling_info->gfx9.num_pkrs = adev->gfx.config.gb_addr_config_fields.num_pkrs; - -#endif - ret = fill_plane_dcc_attributes(adev, afb, format, rotation, - plane_size, tiling_info, - tiling_flags, dcc, address, - force_disable_dcc); + if (adev->family >= AMDGPU_FAMILY_AI) { + ret = fill_gfx9_plane_attributes_from_flags(adev, afb, format, rotation, + plane_size, tiling_info, dcc, + address, tiling_flags, + force_disable_dcc); if (ret) return ret; + } else { + fill_gfx8_tiling_info_from_flags(tiling_info, tiling_flags); }
return 0;
This sets the DC tiling options from the modifier, if modifiers are used for the FB. This patch by itself does not expose the support yet though.
There is not much validation yet to limit the scope of this patch, but the current validation is at the same level as the BO metadata path.
Signed-off-by: Bas Nieuwenhuizen bas@basnieuwenhuizen.nl --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 109 +++++++++++++++++- 1 file changed, 103 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 6ef7f2f8acab..ac913b8f10ef 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3754,6 +3754,93 @@ fill_gfx9_plane_attributes_from_flags(struct amdgpu_device *adev, return 0; }
+static bool +modifier_has_dcc(uint64_t modifier) +{ + return IS_AMD_FMT_MOD(modifier) && AMD_FMT_MOD_GET(DCC, modifier); +} + +static unsigned +modifier_gfx9_swizzle_mode(uint64_t modifier) +{ + if (modifier == DRM_FORMAT_MOD_LINEAR) + return 0; + + return AMD_FMT_MOD_GET(TILE, modifier); +} + +static void +fill_gfx9_tiling_info_from_modifier(const struct amdgpu_device *adev, + union dc_tiling_info *tiling_info, + uint64_t modifier) +{ + unsigned int mod_bank_xor_bits = AMD_FMT_MOD_GET(BANK_XOR_BITS, modifier); + unsigned int mod_pipe_xor_bits = AMD_FMT_MOD_GET(PIPE_XOR_BITS, modifier); + unsigned int pkrs_log2 = AMD_FMT_MOD_GET(PACKERS, modifier); + unsigned int pipes_log2 = min(4u, mod_pipe_xor_bits); + + fill_gfx9_tiling_info_from_device(adev, tiling_info); + + if (!IS_AMD_FMT_MOD(modifier)) + return; + + tiling_info->gfx9.num_pipes = 1u << pipes_log2; + tiling_info->gfx9.num_shader_engines = 1u << (mod_pipe_xor_bits - pipes_log2); + + if (adev->family >= AMDGPU_FAMILY_NV) { + tiling_info->gfx9.num_pkrs = 1u << pkrs_log2; + } else { + tiling_info->gfx9.num_banks = 1u << mod_bank_xor_bits; + + /* for DCC we know it isn't rb aligned, so rb_per_se doesn't matter. */ + } +} + +static void +block_alignment(unsigned int blocksize_log2, unsigned int *width, unsigned int *height) +{ + unsigned int height_log2 = blocksize_log2 / 2; + unsigned int width_log2 = blocksize_log2 - height_log2; + + *width = 1u << width_log2; + *height = 1u << height_log2; +} + +static int +fill_gfx9_plane_attributes_from_modifiers(struct amdgpu_device *adev, + const struct amdgpu_framebuffer *afb, + const enum surface_pixel_format format, + const enum dc_rotation_angle rotation, + const struct plane_size *plane_size, + union dc_tiling_info *tiling_info, + struct dc_plane_dcc_param *dcc, + struct dc_plane_address *address, + const bool force_disable_dcc) +{ + const uint64_t modifier = afb->base.modifier; + int ret; + + fill_gfx9_tiling_info_from_modifier(adev, tiling_info, modifier); + tiling_info->gfx9.swizzle = modifier_gfx9_swizzle_mode(modifier); + + if (modifier_has_dcc(modifier) && !force_disable_dcc) { + uint64_t dcc_address = afb->address + afb->base.offsets[1]; + + dcc->enable = 1; + dcc->meta_pitch = afb->base.pitches[1]; + dcc->independent_64b_blks = AMD_FMT_MOD_GET(DCC_INDEPENDENT_64B, modifier); + + address->grph.meta_addr.low_part = lower_32_bits(dcc_address); + address->grph.meta_addr.high_part = upper_32_bits(dcc_address); + } + + ret = validate_dcc(adev, format, rotation, tiling_info, dcc, address, plane_size); + if (ret) + return ret; + + return 0; +} + static int fill_plane_buffer_attributes(struct amdgpu_device *adev, const struct amdgpu_framebuffer *afb, @@ -3823,12 +3910,22 @@ fill_plane_buffer_attributes(struct amdgpu_device *adev,
if (adev->family >= AMDGPU_FAMILY_AI) { - ret = fill_gfx9_plane_attributes_from_flags(adev, afb, format, rotation, - plane_size, tiling_info, dcc, - address, tiling_flags, - force_disable_dcc); - if (ret) - return ret; + if (afb->base.flags & DRM_MODE_FB_MODIFIERS) { + ret = fill_gfx9_plane_attributes_from_modifiers(adev, afb, format, + rotation, plane_size, + tiling_info, dcc, + address, + force_disable_dcc); + if (ret) + return ret; + } else { + ret = fill_gfx9_plane_attributes_from_flags(adev, afb, format, rotation, + plane_size, tiling_info, dcc, + address, tiling_flags, + force_disable_dcc); + if (ret) + return ret; + } } else { fill_gfx8_tiling_info_from_flags(tiling_info, tiling_flags); }
On Tue, Aug 04, 2020 at 11:31:17PM +0200, Bas Nieuwenhuizen wrote:
This sets the DC tiling options from the modifier, if modifiers are used for the FB. This patch by itself does not expose the support yet though.
There is not much validation yet to limit the scope of this patch, but the current validation is at the same level as the BO metadata path.
Signed-off-by: Bas Nieuwenhuizen bas@basnieuwenhuizen.nl
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 109 +++++++++++++++++- 1 file changed, 103 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 6ef7f2f8acab..ac913b8f10ef 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3754,6 +3754,93 @@ fill_gfx9_plane_attributes_from_flags(struct amdgpu_device *adev, return 0; }
+static bool +modifier_has_dcc(uint64_t modifier) +{
- return IS_AMD_FMT_MOD(modifier) && AMD_FMT_MOD_GET(DCC, modifier);
+}
+static unsigned +modifier_gfx9_swizzle_mode(uint64_t modifier) +{
- if (modifier == DRM_FORMAT_MOD_LINEAR)
return 0;
- return AMD_FMT_MOD_GET(TILE, modifier);
+}
+static void +fill_gfx9_tiling_info_from_modifier(const struct amdgpu_device *adev,
union dc_tiling_info *tiling_info,
uint64_t modifier)
+{
- unsigned int mod_bank_xor_bits = AMD_FMT_MOD_GET(BANK_XOR_BITS, modifier);
- unsigned int mod_pipe_xor_bits = AMD_FMT_MOD_GET(PIPE_XOR_BITS, modifier);
- unsigned int pkrs_log2 = AMD_FMT_MOD_GET(PACKERS, modifier);
- unsigned int pipes_log2 = min(4u, mod_pipe_xor_bits);
- fill_gfx9_tiling_info_from_device(adev, tiling_info);
- if (!IS_AMD_FMT_MOD(modifier))
return;
- tiling_info->gfx9.num_pipes = 1u << pipes_log2;
- tiling_info->gfx9.num_shader_engines = 1u << (mod_pipe_xor_bits - pipes_log2);
- if (adev->family >= AMDGPU_FAMILY_NV) {
tiling_info->gfx9.num_pkrs = 1u << pkrs_log2;
- } else {
tiling_info->gfx9.num_banks = 1u << mod_bank_xor_bits;
/* for DCC we know it isn't rb aligned, so rb_per_se doesn't matter. */
- }
+}
+static void +block_alignment(unsigned int blocksize_log2, unsigned int *width, unsigned int *height) +{
- unsigned int height_log2 = blocksize_log2 / 2;
- unsigned int width_log2 = blocksize_log2 - height_log2;
- *width = 1u << width_log2;
- *height = 1u << height_log2;
+}
+static int +fill_gfx9_plane_attributes_from_modifiers(struct amdgpu_device *adev,
const struct amdgpu_framebuffer *afb,
const enum surface_pixel_format format,
const enum dc_rotation_angle rotation,
const struct plane_size *plane_size,
union dc_tiling_info *tiling_info,
struct dc_plane_dcc_param *dcc,
struct dc_plane_address *address,
const bool force_disable_dcc)
+{
- const uint64_t modifier = afb->base.modifier;
- int ret;
- fill_gfx9_tiling_info_from_modifier(adev, tiling_info, modifier);
- tiling_info->gfx9.swizzle = modifier_gfx9_swizzle_mode(modifier);
- if (modifier_has_dcc(modifier) && !force_disable_dcc) {
uint64_t dcc_address = afb->address + afb->base.offsets[1];
dcc->enable = 1;
dcc->meta_pitch = afb->base.pitches[1];
dcc->independent_64b_blks = AMD_FMT_MOD_GET(DCC_INDEPENDENT_64B, modifier);
address->grph.meta_addr.low_part = lower_32_bits(dcc_address);
address->grph.meta_addr.high_part = upper_32_bits(dcc_address);
- }
- ret = validate_dcc(adev, format, rotation, tiling_info, dcc, address, plane_size);
- if (ret)
return ret;
- return 0;
+}
static int fill_plane_buffer_attributes(struct amdgpu_device *adev, const struct amdgpu_framebuffer *afb, @@ -3823,12 +3910,22 @@ fill_plane_buffer_attributes(struct amdgpu_device *adev,
if (adev->family >= AMDGPU_FAMILY_AI) {
ret = fill_gfx9_plane_attributes_from_flags(adev, afb, format, rotation,
plane_size, tiling_info, dcc,
address, tiling_flags,
force_disable_dcc);
if (ret)
return ret;
if (afb->base.flags & DRM_MODE_FB_MODIFIERS) {
ret = fill_gfx9_plane_attributes_from_modifiers(adev, afb, format,
rotation, plane_size,
tiling_info, dcc,
address,
force_disable_dcc);
if (ret)
return ret;
} else {
ret = fill_gfx9_plane_attributes_from_flags(adev, afb, format, rotation,
plane_size, tiling_info, dcc,
address, tiling_flags,
force_disable_dcc);
if (ret)
return ret;
So what we've done in i915, but might be too cumbersome with the amdgpu modifiers, is to map legacy tiling information into modifiers once, at the beginning of addfb. So in amdgpu_display_user_framebuffer_create(). And once modifiers are filled in, you ofc set the DRM_MODE_FB_MODIFIERS flag too in the fb.
Then all the display code only works with modifiers, instead of having a mix and possible confusion, with breakage when people only test the legacy path. Which I kinda expect to happen, since amd probably runs with their own ddx in their CI rig only.
This also avoids a bunch of layering and locking unprettiness, since display code doesn't need to dig around in gem_bo side of things. On that, there's another amdgpu_bo_get_tiling_flags in amdgpu_dm_commit_planes which probably shouldn't be there, and should use computed stuff from plane state or fb (I changed it to a lockless version to just hack around locking issues, but still there).
This hopefully/eventually should allow us to entirely phase out the legacy magic tiling blob attached to bo (we've pulled the trigger on that for intel now, would have needed to extend the uapi to keep it working was a good excuse).
Cheers, Daniel
} else { fill_gfx8_tiling_info_from_flags(tiling_info, tiling_flags); }}
-- 2.28.0
On Wed, Aug 05, 2020 at 09:32:10AM +0200, daniel@ffwll.ch wrote:
On Tue, Aug 04, 2020 at 11:31:17PM +0200, Bas Nieuwenhuizen wrote:
This sets the DC tiling options from the modifier, if modifiers are used for the FB. This patch by itself does not expose the support yet though.
There is not much validation yet to limit the scope of this patch, but the current validation is at the same level as the BO metadata path.
Signed-off-by: Bas Nieuwenhuizen bas@basnieuwenhuizen.nl
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 109 +++++++++++++++++- 1 file changed, 103 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 6ef7f2f8acab..ac913b8f10ef 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3754,6 +3754,93 @@ fill_gfx9_plane_attributes_from_flags(struct amdgpu_device *adev, return 0; }
+static bool +modifier_has_dcc(uint64_t modifier) +{
- return IS_AMD_FMT_MOD(modifier) && AMD_FMT_MOD_GET(DCC, modifier);
+}
+static unsigned +modifier_gfx9_swizzle_mode(uint64_t modifier) +{
- if (modifier == DRM_FORMAT_MOD_LINEAR)
return 0;
- return AMD_FMT_MOD_GET(TILE, modifier);
+}
+static void +fill_gfx9_tiling_info_from_modifier(const struct amdgpu_device *adev,
union dc_tiling_info *tiling_info,
uint64_t modifier)
+{
- unsigned int mod_bank_xor_bits = AMD_FMT_MOD_GET(BANK_XOR_BITS, modifier);
- unsigned int mod_pipe_xor_bits = AMD_FMT_MOD_GET(PIPE_XOR_BITS, modifier);
- unsigned int pkrs_log2 = AMD_FMT_MOD_GET(PACKERS, modifier);
- unsigned int pipes_log2 = min(4u, mod_pipe_xor_bits);
- fill_gfx9_tiling_info_from_device(adev, tiling_info);
- if (!IS_AMD_FMT_MOD(modifier))
return;
- tiling_info->gfx9.num_pipes = 1u << pipes_log2;
- tiling_info->gfx9.num_shader_engines = 1u << (mod_pipe_xor_bits - pipes_log2);
- if (adev->family >= AMDGPU_FAMILY_NV) {
tiling_info->gfx9.num_pkrs = 1u << pkrs_log2;
- } else {
tiling_info->gfx9.num_banks = 1u << mod_bank_xor_bits;
/* for DCC we know it isn't rb aligned, so rb_per_se doesn't matter. */
- }
+}
+static void +block_alignment(unsigned int blocksize_log2, unsigned int *width, unsigned int *height) +{
- unsigned int height_log2 = blocksize_log2 / 2;
- unsigned int width_log2 = blocksize_log2 - height_log2;
- *width = 1u << width_log2;
- *height = 1u << height_log2;
+}
+static int +fill_gfx9_plane_attributes_from_modifiers(struct amdgpu_device *adev,
const struct amdgpu_framebuffer *afb,
const enum surface_pixel_format format,
const enum dc_rotation_angle rotation,
const struct plane_size *plane_size,
union dc_tiling_info *tiling_info,
struct dc_plane_dcc_param *dcc,
struct dc_plane_address *address,
const bool force_disable_dcc)
+{
- const uint64_t modifier = afb->base.modifier;
- int ret;
- fill_gfx9_tiling_info_from_modifier(adev, tiling_info, modifier);
- tiling_info->gfx9.swizzle = modifier_gfx9_swizzle_mode(modifier);
- if (modifier_has_dcc(modifier) && !force_disable_dcc) {
uint64_t dcc_address = afb->address + afb->base.offsets[1];
dcc->enable = 1;
dcc->meta_pitch = afb->base.pitches[1];
dcc->independent_64b_blks = AMD_FMT_MOD_GET(DCC_INDEPENDENT_64B, modifier);
address->grph.meta_addr.low_part = lower_32_bits(dcc_address);
address->grph.meta_addr.high_part = upper_32_bits(dcc_address);
- }
- ret = validate_dcc(adev, format, rotation, tiling_info, dcc, address, plane_size);
- if (ret)
return ret;
- return 0;
+}
static int fill_plane_buffer_attributes(struct amdgpu_device *adev, const struct amdgpu_framebuffer *afb, @@ -3823,12 +3910,22 @@ fill_plane_buffer_attributes(struct amdgpu_device *adev,
if (adev->family >= AMDGPU_FAMILY_AI) {
ret = fill_gfx9_plane_attributes_from_flags(adev, afb, format, rotation,
plane_size, tiling_info, dcc,
address, tiling_flags,
force_disable_dcc);
if (ret)
return ret;
if (afb->base.flags & DRM_MODE_FB_MODIFIERS) {
ret = fill_gfx9_plane_attributes_from_modifiers(adev, afb, format,
rotation, plane_size,
tiling_info, dcc,
address,
force_disable_dcc);
if (ret)
return ret;
} else {
ret = fill_gfx9_plane_attributes_from_flags(adev, afb, format, rotation,
plane_size, tiling_info, dcc,
address, tiling_flags,
force_disable_dcc);
if (ret)
return ret;
So what we've done in i915, but might be too cumbersome with the amdgpu modifiers, is to map legacy tiling information into modifiers once, at the beginning of addfb. So in amdgpu_display_user_framebuffer_create(). And once modifiers are filled in, you ofc set the DRM_MODE_FB_MODIFIERS flag too in the fb.
Then all the display code only works with modifiers, instead of having a mix and possible confusion, with breakage when people only test the legacy path. Which I kinda expect to happen, since amd probably runs with their own ddx in their CI rig only.
This also avoids a bunch of layering and locking unprettiness, since display code doesn't need to dig around in gem_bo side of things. On that, there's another amdgpu_bo_get_tiling_flags in amdgpu_dm_commit_planes which probably shouldn't be there, and should use computed stuff from plane state or fb (I changed it to a lockless version to just hack around locking issues, but still there).
This hopefully/eventually should allow us to entirely phase out the legacy magic tiling blob attached to bo (we've pulled the trigger on that for intel now, would have needed to extend the uapi to keep it working was a good excuse).
Ok just learned that amdgpu hat set/get_tiling, so I'm upgrading my idea here to a very strong recommendation, i.e. please do this except if there's and amd ddx which somehow wants to change tiling mode while a fb exists, and expects this to propagate.
In i915 we even disallow the set_tiling ioctl with an error if an fb exists, just to make sure userspace behaves. Even if userspace uses set_tiling, this way we can at least enforce the same semantics of "client can't pull compositor over the table with a set_tiling at the wrong time" of modifiers. -Daniel
Cheers, Daniel
} else { fill_gfx8_tiling_info_from_flags(tiling_info, tiling_flags); }}
-- 2.28.0
-- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch
On 2020-08-10 2:28 p.m., Daniel Vetter wrote:
Ok just learned that amdgpu hat set/get_tiling, so I'm upgrading my idea here to a very strong recommendation, i.e. please do this except if there's and amd ddx which somehow wants to change tiling mode while a fb exists, and expects this to propagate.
In i915 we even disallow the set_tiling ioctl with an error if an fb exists, just to make sure userspace behaves. Even if userspace uses set_tiling, this way we can at least enforce the same semantics of "client can't pull compositor over the table with a set_tiling at the wrong time" of modifiers.
FWIW, xf86-video-amdgpu doesn't have any code to set the tiling metadata, only Mesa and presumably AMD's Vulkan/OpenGL UMDs do.
On Mon, Aug 10, 2020 at 02:49:00PM +0200, Michel Dänzer wrote:
On 2020-08-10 2:28 p.m., Daniel Vetter wrote:
Ok just learned that amdgpu hat set/get_tiling, so I'm upgrading my idea here to a very strong recommendation, i.e. please do this except if there's and amd ddx which somehow wants to change tiling mode while a fb exists, and expects this to propagate.
In i915 we even disallow the set_tiling ioctl with an error if an fb exists, just to make sure userspace behaves. Even if userspace uses set_tiling, this way we can at least enforce the same semantics of "client can't pull compositor over the table with a set_tiling at the wrong time" of modifiers.
FWIW, xf86-video-amdgpu doesn't have any code to set the tiling metadata, only Mesa and presumably AMD's Vulkan/OpenGL UMDs do.
Ah right you do everything with glamour, so this should never show up as a problem. -Daniel
On Mon, Aug 10, 2020 at 3:09 PM Daniel Vetter daniel@ffwll.ch wrote:
On Mon, Aug 10, 2020 at 02:49:00PM +0200, Michel Dänzer wrote:
On 2020-08-10 2:28 p.m., Daniel Vetter wrote:
Ok just learned that amdgpu hat set/get_tiling, so I'm upgrading my idea here to a very strong recommendation, i.e. please do this except if there's and amd ddx which somehow wants to change tiling mode while a fb exists, and expects this to propagate.
In i915 we even disallow the set_tiling ioctl with an error if an fb exists, just to make sure userspace behaves. Even if userspace uses set_tiling, this way we can at least enforce the same semantics of "client can't pull compositor over the table with a set_tiling at the wrong time" of modifiers.
FWIW, xf86-video-amdgpu doesn't have any code to set the tiling metadata, only Mesa and presumably AMD's Vulkan/OpenGL UMDs do.
Ah right you do everything with glamour, so this should never show up as a problem.
I think it is a good idea to do so, but cannot do it completely in this series as we don't define modifiers for GFX6-GFX8 GPU generations yet. (wanted to leave these out for a bit to reduce the scope for the initial version)
That said, there is a series that captures the tiling flags on FB creation: https://patchwork.freedesktop.org/series/80109/
-Daniel
Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch _______________________________________________ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
On Mon, Aug 10, 2020 at 4:13 PM Bas Nieuwenhuizen bas@basnieuwenhuizen.nl wrote:
On Mon, Aug 10, 2020 at 3:09 PM Daniel Vetter daniel@ffwll.ch wrote:
On Mon, Aug 10, 2020 at 02:49:00PM +0200, Michel Dänzer wrote:
On 2020-08-10 2:28 p.m., Daniel Vetter wrote:
Ok just learned that amdgpu hat set/get_tiling, so I'm upgrading my idea here to a very strong recommendation, i.e. please do this except if there's and amd ddx which somehow wants to change tiling mode while a fb exists, and expects this to propagate.
In i915 we even disallow the set_tiling ioctl with an error if an fb exists, just to make sure userspace behaves. Even if userspace uses set_tiling, this way we can at least enforce the same semantics of "client can't pull compositor over the table with a set_tiling at the wrong time" of modifiers.
FWIW, xf86-video-amdgpu doesn't have any code to set the tiling metadata, only Mesa and presumably AMD's Vulkan/OpenGL UMDs do.
Ah right you do everything with glamour, so this should never show up as a problem.
I think it is a good idea to do so, but cannot do it completely in this series as we don't define modifiers for GFX6-GFX8 GPU generations yet. (wanted to leave these out for a bit to reduce the scope for the initial version)
Hm right, that makes it a bit awkward.
That said, there is a series that captures the tiling flags on FB creation: https://patchwork.freedesktop.org/series/80109/
Yeah, but it only pushes it down into the state objects. Good first step, what I'm proposing is to push it all the way into addfb/struct drm_framebuffer. Since drm_framebuffer is also an invariant thing it makes the most sense to keep that there. I'm also discussing with Nicholas about what would be the ideal end state.
But yeah maybe one thing at time. -Daniel
-Daniel
Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch _______________________________________________ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
For DCC we will use 2/3 planes to avoid X rendering to the frontbuffer with DCC compressed images. To make this work with the core KMS validation we need to add extra formats with the extra planes.
However, due to flexibility we set bpp = 0 for the extra planes and do the validation ourselves.
Signed-off-by: Bas Nieuwenhuizen bas@basnieuwenhuizen.nl --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index ac913b8f10ef..c38257081868 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -170,6 +170,8 @@ static bool amdgpu_dm_psr_enable(struct dc_stream_state *stream); static bool amdgpu_dm_link_setup_psr(struct dc_stream_state *stream); static bool amdgpu_dm_psr_disable(struct dc_stream_state *stream);
+static const struct drm_format_info * +amd_get_format_info(const struct drm_mode_fb_cmd2 *cmd);
/* * dm_vblank_get_counter @@ -2007,6 +2009,7 @@ const struct amdgpu_ip_block_version dm_ip_block =
static const struct drm_mode_config_funcs amdgpu_dm_mode_funcs = { .fb_create = amdgpu_display_user_framebuffer_create, + .get_format_info = amd_get_format_info, .output_poll_changed = drm_fb_helper_output_poll_changed, .atomic_check = amdgpu_dm_atomic_check, .atomic_commit = amdgpu_dm_atomic_commit, @@ -3769,6 +3772,98 @@ modifier_gfx9_swizzle_mode(uint64_t modifier) return AMD_FMT_MOD_GET(TILE, modifier); }
+static const struct drm_format_info dcc_formats[] = { + { .format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 2, + .cpp = { 4, 0, }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1, }, + { .format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 2, + .cpp = { 4, 0, }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1, }, + { .format = DRM_FORMAT_ARGB8888, .depth = 32, .num_planes = 2, + .cpp = { 4, 0, }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1, + .has_alpha = true, }, + { .format = DRM_FORMAT_ABGR8888, .depth = 32, .num_planes = 2, + .cpp = { 4, 0, }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1, + .has_alpha = true, }, + { .format = DRM_FORMAT_BGRA8888, .depth = 32, .num_planes = 2, + .cpp = { 4, 0, }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1, + .has_alpha = true, }, + { .format = DRM_FORMAT_XRGB2101010, .depth = 30, .num_planes = 2, + .cpp = { 4, 0, }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1, }, + { .format = DRM_FORMAT_XBGR2101010, .depth = 30, .num_planes = 2, + .cpp = { 4, 0, }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1, }, + { .format = DRM_FORMAT_ARGB2101010, .depth = 30, .num_planes = 2, + .cpp = { 4, 0, }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1, + .has_alpha = true, }, + { .format = DRM_FORMAT_ABGR2101010, .depth = 30, .num_planes = 2, + .cpp = { 4, 0, }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1, + .has_alpha = true, }, + { .format = DRM_FORMAT_RGB565, .depth = 16, .num_planes = 2, + .cpp = { 2, 0, }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1, }, +}; + +static const struct drm_format_info dcc_retile_formats[] = { + { .format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 3, + .cpp = { 4, 0, 0 }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1, }, + { .format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 3, + .cpp = { 4, 0, 0 }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1, }, + { .format = DRM_FORMAT_ARGB8888, .depth = 32, .num_planes = 3, + .cpp = { 4, 0, 0 }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1, + .has_alpha = true, }, + { .format = DRM_FORMAT_ABGR8888, .depth = 32, .num_planes = 3, + .cpp = { 4, 0, 0 }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1, + .has_alpha = true, }, + { .format = DRM_FORMAT_BGRA8888, .depth = 32, .num_planes = 3, + .cpp = { 4, 0, 0 }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1, + .has_alpha = true, }, + { .format = DRM_FORMAT_XRGB2101010, .depth = 30, .num_planes = 3, + .cpp = { 4, 0, 0 }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1, }, + { .format = DRM_FORMAT_XBGR2101010, .depth = 30, .num_planes = 3, + .cpp = { 4, 0, 0 }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1, }, + { .format = DRM_FORMAT_ARGB2101010, .depth = 30, .num_planes = 3, + .cpp = { 4, 0, 0 }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1, + .has_alpha = true, }, + { .format = DRM_FORMAT_ABGR2101010, .depth = 30, .num_planes = 3, + .cpp = { 4, 0, 0 }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1, + .has_alpha = true, }, + { .format = DRM_FORMAT_RGB565, .depth = 16, .num_planes = 3, + .cpp = { 2, 0, 0 }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1, }, +}; + + +static const struct drm_format_info * +lookup_format_info(const struct drm_format_info formats[], + int num_formats, u32 format) +{ + int i; + + for (i = 0; i < num_formats; i++) { + if (formats[i].format == format) + return &formats[i]; + } + + return NULL; +} + +static const struct drm_format_info * +amd_get_format_info(const struct drm_mode_fb_cmd2 *cmd) +{ + uint64_t modifier = cmd->modifier[0]; + + if (!IS_AMD_FMT_MOD(modifier)) + return NULL; + + if (AMD_FMT_MOD_GET(DCC_RETILE, modifier)) + return lookup_format_info(dcc_retile_formats, + ARRAY_SIZE(dcc_retile_formats), + cmd->pixel_format); + + if (AMD_FMT_MOD_GET(DCC, modifier)) + return lookup_format_info(dcc_formats, ARRAY_SIZE(dcc_formats), + cmd->pixel_format); + + /* returning NULL will cause the default format structs to be used. */ + return NULL; +} + static void fill_gfx9_tiling_info_from_modifier(const struct amdgpu_device *adev, union dc_tiling_info *tiling_info,
This expose modifier support on GFX9+.
Only modifiers that can be rendered on the current GPU are added. This is to reduce the number of modifiers exposed.
The HW could expose more, but the best mechanism to decide what to expose without an explosion in modifiers is still to be decided, and in the meantime this should not regress things from pre-modifiers and does not risk regressions as we make up our mind in the future.
Signed-off-by: Bas Nieuwenhuizen bas@basnieuwenhuizen.nl --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 343 +++++++++++++++++- 1 file changed, 342 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index c38257081868..6594cbe625f9 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3891,6 +3891,340 @@ fill_gfx9_tiling_info_from_modifier(const struct amdgpu_device *adev, } }
+enum dm_micro_swizzle { + MICRO_SWIZZLE_Z = 0, + MICRO_SWIZZLE_S = 1, + MICRO_SWIZZLE_D = 2, + MICRO_SWIZZLE_R = 3 +}; + +static bool dm_plane_format_mod_supported(struct drm_plane *plane, + uint32_t format, + uint64_t modifier) +{ + struct amdgpu_device *adev = plane->dev->dev_private; + const struct drm_format_info *info = drm_format_info(format); + + enum dm_micro_swizzle microtile = modifier_gfx9_swizzle_mode(modifier) & 3; + + if (!info) + return false; + + /* + * We always have to allow this modifier, because core DRM still + * checks LINEAR support if userspace does not provide modifers. + */ + if (modifier == DRM_FORMAT_MOD_LINEAR) + return true; + + /* + * The arbitrary tiling support for multiplane formats has not been hooked + * up. + */ + if (info->num_planes > 1) + return false; + + /* + * For D swizzle the canonical modifier depends on the bpp, so check + * it here. + */ + if (AMD_FMT_MOD_GET(TILE_VERSION, modifier) == AMD_FMT_MOD_TILE_VER_GFX9 && + adev->family >= AMDGPU_FAMILY_NV) { + if (microtile == MICRO_SWIZZLE_D && info->cpp[0] == 4) + return false; + } + + if (adev->family >= AMDGPU_FAMILY_RV && microtile == MICRO_SWIZZLE_D && + info->cpp[0] < 8) + return false; + + if (modifier_has_dcc(modifier)) { + /* Per radeonsi comments 16/64 bpp are more complicated. */ + if (info->cpp[0] != 4) + return false; + } + + return true; +} + +static void +add_modifier(uint64_t **mods, uint64_t *size, uint64_t *cap, uint64_t mod) +{ + if (!*mods) + return; + + if (*cap - *size < 1) { + uint64_t new_cap = *cap * 2; + uint64_t *new_mods = kmalloc(new_cap * sizeof(uint64_t), GFP_KERNEL); + + if (!new_mods) { + kfree(*mods); + *mods = NULL; + return; + } + + memcpy(new_mods, *mods, sizeof(uint64_t) * *size); + kfree(*mods); + *mods = new_mods; + *cap = new_cap; + } + + (*mods)[*size] = mod; + *size += 1; +} + +static void +add_gfx9_modifiers(const struct amdgpu_device *adev, + uint64_t **mods, uint64_t *size, uint64_t *capacity) +{ + int pipes = ilog2(adev->gfx.config.gb_addr_config_fields.num_pipes); + int pipe_xor_bits = min(8, pipes + + ilog2(adev->gfx.config.gb_addr_config_fields.num_se)); + int bank_xor_bits = min(8 - pipe_xor_bits, + ilog2(adev->gfx.config.gb_addr_config_fields.num_banks)); + int rb = ilog2(adev->gfx.config.gb_addr_config_fields.num_se) + + ilog2(adev->gfx.config.gb_addr_config_fields.num_rb_per_se); + + + if (adev->family == AMDGPU_FAMILY_RV) { + /* + * No _D DCC swizzles yet because we only allow 32bpp, which + * doesn't support _D on DCN + */ + + /* + * Always enable constant encoding, because the only unit that + * didn't support it was CB. But on texture/display we can + * always interpret it. + */ + add_modifier(mods, size, capacity, AMD_FMT_MOD | + AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) | + AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) | + AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) | + AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) | + AMD_FMT_MOD_SET(DCC, 1) | + AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) | + AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B) | + AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1)); + + add_modifier(mods, size, capacity, AMD_FMT_MOD | + AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) | + AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) | + AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) | + AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) | + AMD_FMT_MOD_SET(DCC, 1) | + AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) | + AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B) | + AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 0)); + + add_modifier(mods, size, capacity, AMD_FMT_MOD | + AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) | + AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) | + AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) | + AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) | + AMD_FMT_MOD_SET(DCC, 1) | + AMD_FMT_MOD_SET(DCC_RETILE, 1) | + AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) | + AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B) | + AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) | + AMD_FMT_MOD_SET(RB, rb) | + AMD_FMT_MOD_SET(PIPE, pipes)); + + add_modifier(mods, size, capacity, AMD_FMT_MOD | + AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) | + AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) | + AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) | + AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) | + AMD_FMT_MOD_SET(DCC, 1) | + AMD_FMT_MOD_SET(DCC_RETILE, 1) | + AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) | + AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B) | + AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 0) | + AMD_FMT_MOD_SET(RB, rb) | + AMD_FMT_MOD_SET(PIPE, pipes)); + } + + add_modifier(mods, size, capacity, AMD_FMT_MOD | + AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D_X) | + AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) | + AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) | + AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits)); + + if (adev->family == AMDGPU_FAMILY_RV) { + add_modifier(mods, size, capacity, AMD_FMT_MOD | + AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) | + AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) | + AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) | + AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits)); + } + + add_modifier(mods, size, capacity, AMD_FMT_MOD | + AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D) | + AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9)); + + if (adev->family == AMDGPU_FAMILY_RV) { + add_modifier(mods, size, capacity, AMD_FMT_MOD | + AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S) | + AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9)); + } +} + +static void +add_gfx10_1_modifiers(const struct amdgpu_device *adev, + uint64_t **mods, uint64_t *size, uint64_t *capacity) +{ + int pipe_xor_bits = ilog2(adev->gfx.config.gb_addr_config_fields.num_pipes); + + add_modifier(mods, size, capacity, AMD_FMT_MOD | + AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) | + AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10) | + AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) | + AMD_FMT_MOD_SET(DCC, 1) | + AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) | + AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) | + AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B)); + + add_modifier(mods, size, capacity, AMD_FMT_MOD | + AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) | + AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10) | + AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) | + AMD_FMT_MOD_SET(DCC, 1) | + AMD_FMT_MOD_SET(DCC_RETILE, 1) | + AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) | + AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) | + AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B)); + + add_modifier(mods, size, capacity, AMD_FMT_MOD | + AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) | + AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10) | + AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits)); + + add_modifier(mods, size, capacity, AMD_FMT_MOD | + AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D_X) | + AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10) | + AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits)); + + add_modifier(mods, size, capacity, AMD_FMT_MOD | + AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) | + AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10) | + AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits)); + + add_modifier(mods, size, capacity, AMD_FMT_MOD | + AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D) | + AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10)); + + add_modifier(mods, size, capacity, AMD_FMT_MOD | + AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D) | + AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9)); + + add_modifier(mods, size, capacity, AMD_FMT_MOD | + AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S) | + AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9)); +} + +static void +add_gfx10_3_modifiers(const struct amdgpu_device *adev, + uint64_t **mods, uint64_t *size, uint64_t *capacity) +{ + int pipe_xor_bits = ilog2(adev->gfx.config.gb_addr_config_fields.num_pipes); + int pkrs = ilog2(adev->gfx.config.gb_addr_config_fields.num_pkrs); + + add_modifier(mods, size, capacity, AMD_FMT_MOD | + AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) | + AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) | + AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) | + AMD_FMT_MOD_SET(PACKERS, pkrs) | + AMD_FMT_MOD_SET(DCC, 1) | + AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) | + AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) | + AMD_FMT_MOD_SET(DCC_INDEPENDENT_128B, 1) | + AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_128B)); + + add_modifier(mods, size, capacity, AMD_FMT_MOD | + AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) | + AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) | + AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) | + AMD_FMT_MOD_SET(PACKERS, pkrs) | + AMD_FMT_MOD_SET(DCC, 1) | + AMD_FMT_MOD_SET(DCC_RETILE, 1) | + AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) | + AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) | + AMD_FMT_MOD_SET(DCC_INDEPENDENT_128B, 1) | + AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_128B)); + + add_modifier(mods, size, capacity, AMD_FMT_MOD | + AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) | + AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) | + AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) | + AMD_FMT_MOD_SET(PACKERS, pkrs)); + + add_modifier(mods, size, capacity, AMD_FMT_MOD | + AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D_X) | + AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) | + AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) | + AMD_FMT_MOD_SET(PACKERS, pkrs)); + + add_modifier(mods, size, capacity, AMD_FMT_MOD | + AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) | + AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) | + AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) | + AMD_FMT_MOD_SET(PACKERS, pkrs)); + + add_modifier(mods, size, capacity, AMD_FMT_MOD | + AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D) | + AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS)); + + add_modifier(mods, size, capacity, AMD_FMT_MOD | + AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D) | + AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9)); + + add_modifier(mods, size, capacity, AMD_FMT_MOD | + AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S) | + AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9)); +} + +static int +get_plane_modifiers(const struct amdgpu_device *adev, unsigned int plane_type, uint64_t **mods) +{ + uint64_t size = 0, capacity = 128; + *mods = NULL; + + /* We have not hooked up any pre-GFX9 modifiers. */ + if (adev->family < AMDGPU_FAMILY_AI) + return 0; + + *mods = kmalloc(capacity * sizeof(uint64_t), GFP_KERNEL); + + if (plane_type == DRM_PLANE_TYPE_CURSOR) { + add_modifier(mods, &size, &capacity, DRM_FORMAT_MOD_LINEAR); + add_modifier(mods, &size, &capacity, DRM_FORMAT_MOD_INVALID); + return *mods ? 0 : -ENOMEM; + } + + switch (adev->family) { + case AMDGPU_FAMILY_AI: + case AMDGPU_FAMILY_RV: + add_gfx9_modifiers(adev, mods, &size, &capacity); + break; + case AMDGPU_FAMILY_NV: + if (adev->asic_type >= CHIP_SIENNA_CICHLID) + add_gfx10_3_modifiers(adev, mods, &size, &capacity); + else + add_gfx10_1_modifiers(adev, mods, &size, &capacity); + break; + } + + add_modifier(mods, &size, &capacity, DRM_FORMAT_MOD_LINEAR); + + /* INVALID marks the end of the list. */ + add_modifier(mods, &size, &capacity, DRM_FORMAT_MOD_INVALID); + + if (!*mods) + return -ENOMEM; + + return 0; +} + static void block_alignment(unsigned int blocksize_log2, unsigned int *width, unsigned int *height) { @@ -5886,6 +6220,7 @@ static const struct drm_plane_funcs dm_plane_funcs = { .reset = dm_drm_plane_reset, .atomic_duplicate_state = dm_drm_plane_duplicate_state, .atomic_destroy_state = dm_drm_plane_destroy_state, + .format_mod_supported = dm_plane_format_mod_supported, };
static int dm_plane_helper_prepare_fb(struct drm_plane *plane, @@ -6154,13 +6489,19 @@ static int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, uint32_t formats[32]; int num_formats; int res = -EPERM; + uint64_t *modifiers = NULL;
num_formats = get_plane_formats(plane, plane_cap, formats, ARRAY_SIZE(formats));
+ res = get_plane_modifiers(dm->adev, plane->type, &modifiers); + if (res) + return res; + res = drm_universal_plane_init(dm->adev->ddev, plane, possible_crtcs, &dm_plane_funcs, formats, num_formats, - NULL, plane->type, NULL); + modifiers, plane->type, NULL); + kfree(modifiers); if (res) return res;
On Tue, Aug 4, 2020 at 5:32 PM Bas Nieuwenhuizen bas@basnieuwenhuizen.nl wrote:
This expose modifier support on GFX9+.
Only modifiers that can be rendered on the current GPU are added. This is to reduce the number of modifiers exposed.
The HW could expose more, but the best mechanism to decide what to expose without an explosion in modifiers is still to be decided, and in the meantime this should not regress things from pre-modifiers and does not risk regressions as we make up our mind in the future.
Signed-off-by: Bas Nieuwenhuizen bas@basnieuwenhuizen.nl
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 343 +++++++++++++++++- 1 file changed, 342 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index c38257081868..6594cbe625f9 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3891,6 +3891,340 @@ fill_gfx9_tiling_info_from_modifier(const struct amdgpu_device *adev, } }
+enum dm_micro_swizzle {
MICRO_SWIZZLE_Z = 0,
MICRO_SWIZZLE_S = 1,
MICRO_SWIZZLE_D = 2,
MICRO_SWIZZLE_R = 3
+};
+static bool dm_plane_format_mod_supported(struct drm_plane *plane,
uint32_t format,
uint64_t modifier)
+{
struct amdgpu_device *adev = plane->dev->dev_private;
const struct drm_format_info *info = drm_format_info(format);
enum dm_micro_swizzle microtile =
modifier_gfx9_swizzle_mode(modifier) & 3;
if (!info)
return false;
/*
* We always have to allow this modifier, because core DRM still
* checks LINEAR support if userspace does not provide modifers.
*/
if (modifier == DRM_FORMAT_MOD_LINEAR)
return true;
/*
* The arbitrary tiling support for multiplane formats has not
been hooked
* up.
*/
if (info->num_planes > 1)
return false;
/*
* For D swizzle the canonical modifier depends on the bpp, so
check
* it here.
*/
if (AMD_FMT_MOD_GET(TILE_VERSION, modifier) ==
AMD_FMT_MOD_TILE_VER_GFX9 &&
adev->family >= AMDGPU_FAMILY_NV) {
if (microtile == MICRO_SWIZZLE_D && info->cpp[0] == 4)
return false;
}
if (adev->family >= AMDGPU_FAMILY_RV && microtile ==
MICRO_SWIZZLE_D &&
info->cpp[0] < 8)
return false;
if (modifier_has_dcc(modifier)) {
/* Per radeonsi comments 16/64 bpp are more complicated. */
if (info->cpp[0] != 4)
return false;
}
return true;
+}
+static void +add_modifier(uint64_t **mods, uint64_t *size, uint64_t *cap, uint64_t mod) +{
if (!*mods)
return;
if (*cap - *size < 1) {
uint64_t new_cap = *cap * 2;
uint64_t *new_mods = kmalloc(new_cap * sizeof(uint64_t),
GFP_KERNEL);
if (!new_mods) {
kfree(*mods);
*mods = NULL;
return;
}
memcpy(new_mods, *mods, sizeof(uint64_t) * *size);
kfree(*mods);
*mods = new_mods;
*cap = new_cap;
}
(*mods)[*size] = mod;
*size += 1;
+}
+static void +add_gfx9_modifiers(const struct amdgpu_device *adev,
uint64_t **mods, uint64_t *size, uint64_t *capacity)
+{
int pipes =
ilog2(adev->gfx.config.gb_addr_config_fields.num_pipes);
int pipe_xor_bits = min(8, pipes +
ilog2(adev->gfx.config.gb_addr_config_fields.num_se));
int bank_xor_bits = min(8 - pipe_xor_bits,
ilog2(adev->gfx.config.gb_addr_config_fields.num_banks));
int rb = ilog2(adev->gfx.config.gb_addr_config_fields.num_se) +
ilog2(adev->gfx.config.gb_addr_config_fields.num_rb_per_se);
if (adev->family == AMDGPU_FAMILY_RV) {
/*
* No _D DCC swizzles yet because we only allow 32bpp,
which
* doesn't support _D on DCN
*/
/*
* Always enable constant encoding, because the only unit
that
* didn't support it was CB. But on texture/display we can
* always interpret it.
*/
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE,
AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
AMD_FMT_MOD_SET(TILE_VERSION,
AMD_FMT_MOD_TILE_VER_GFX9) |
AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) |
AMD_FMT_MOD_SET(DCC, 1) |
AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK,
AMD_FMT_MOD_DCC_BLOCK_64B) |
AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1));
I don't think Raven1 can do DCC constant encoding in DCN and GL2.
+
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE,
AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
AMD_FMT_MOD_SET(TILE_VERSION,
AMD_FMT_MOD_TILE_VER_GFX9) |
AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) |
AMD_FMT_MOD_SET(DCC, 1) |
AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK,
AMD_FMT_MOD_DCC_BLOCK_64B) |
AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 0));
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE,
AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
AMD_FMT_MOD_SET(TILE_VERSION,
AMD_FMT_MOD_TILE_VER_GFX9) |
AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) |
AMD_FMT_MOD_SET(DCC, 1) |
AMD_FMT_MOD_SET(DCC_RETILE, 1) |
AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK,
AMD_FMT_MOD_DCC_BLOCK_64B) |
AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
AMD_FMT_MOD_SET(RB, rb) |
AMD_FMT_MOD_SET(PIPE, pipes));
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE,
AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
AMD_FMT_MOD_SET(TILE_VERSION,
AMD_FMT_MOD_TILE_VER_GFX9) |
AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) |
AMD_FMT_MOD_SET(DCC, 1) |
AMD_FMT_MOD_SET(DCC_RETILE, 1) |
AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK,
AMD_FMT_MOD_DCC_BLOCK_64B) |
AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 0) |
AMD_FMT_MOD_SET(RB, rb) |
AMD_FMT_MOD_SET(PIPE, pipes));
}
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D_X) |
AMD_FMT_MOD_SET(TILE_VERSION,
AMD_FMT_MOD_TILE_VER_GFX9) |
AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits));
Addrlib says that D swizzle modes are unsupported for 32bpp in DCN1. They are only supported in DCE12. The swizzle modes between the two have no intersection.
if (adev->family == AMDGPU_FAMILY_RV) {
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE,
AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
AMD_FMT_MOD_SET(TILE_VERSION,
AMD_FMT_MOD_TILE_VER_GFX9) |
AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits));
}
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D) |
AMD_FMT_MOD_SET(TILE_VERSION,
AMD_FMT_MOD_TILE_VER_GFX9));
if (adev->family == AMDGPU_FAMILY_RV) {
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE,
AMD_FMT_MOD_TILE_GFX9_64K_S) |
AMD_FMT_MOD_SET(TILE_VERSION,
AMD_FMT_MOD_TILE_VER_GFX9));
}
+}
+static void +add_gfx10_1_modifiers(const struct amdgpu_device *adev,
uint64_t **mods, uint64_t *size, uint64_t *capacity)
+{
int pipe_xor_bits =
ilog2(adev->gfx.config.gb_addr_config_fields.num_pipes);
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
AMD_FMT_MOD_SET(TILE_VERSION,
AMD_FMT_MOD_TILE_VER_GFX10) |
AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
AMD_FMT_MOD_SET(DCC, 1) |
AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK,
AMD_FMT_MOD_DCC_BLOCK_64B));
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
AMD_FMT_MOD_SET(TILE_VERSION,
AMD_FMT_MOD_TILE_VER_GFX10) |
AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
AMD_FMT_MOD_SET(DCC, 1) |
AMD_FMT_MOD_SET(DCC_RETILE, 1) |
AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK,
AMD_FMT_MOD_DCC_BLOCK_64B));
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
AMD_FMT_MOD_SET(TILE_VERSION,
AMD_FMT_MOD_TILE_VER_GFX10) |
AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits));
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D_X) |
AMD_FMT_MOD_SET(TILE_VERSION,
AMD_FMT_MOD_TILE_VER_GFX10) |
AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits));
D swizzle modes are unsupported according to Addrlib.
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
AMD_FMT_MOD_SET(TILE_VERSION,
AMD_FMT_MOD_TILE_VER_GFX10) |
AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits));
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D) |
AMD_FMT_MOD_SET(TILE_VERSION,
AMD_FMT_MOD_TILE_VER_GFX10));
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D) |
AMD_FMT_MOD_SET(TILE_VERSION,
AMD_FMT_MOD_TILE_VER_GFX9));
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S) |
AMD_FMT_MOD_SET(TILE_VERSION,
AMD_FMT_MOD_TILE_VER_GFX9)); +}
+static void +add_gfx10_3_modifiers(const struct amdgpu_device *adev,
uint64_t **mods, uint64_t *size, uint64_t *capacity)
+{
int pipe_xor_bits =
ilog2(adev->gfx.config.gb_addr_config_fields.num_pipes);
int pkrs = ilog2(adev->gfx.config.gb_addr_config_fields.num_pkrs);
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
AMD_FMT_MOD_SET(TILE_VERSION,
AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
AMD_FMT_MOD_SET(PACKERS, pkrs) |
AMD_FMT_MOD_SET(DCC, 1) |
AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
AMD_FMT_MOD_SET(DCC_INDEPENDENT_128B, 1) |
AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK,
AMD_FMT_MOD_DCC_BLOCK_128B));
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
AMD_FMT_MOD_SET(TILE_VERSION,
AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
AMD_FMT_MOD_SET(PACKERS, pkrs) |
AMD_FMT_MOD_SET(DCC, 1) |
AMD_FMT_MOD_SET(DCC_RETILE, 1) |
AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
AMD_FMT_MOD_SET(DCC_INDEPENDENT_128B, 1) |
AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK,
AMD_FMT_MOD_DCC_BLOCK_128B));
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
AMD_FMT_MOD_SET(TILE_VERSION,
AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
AMD_FMT_MOD_SET(PACKERS, pkrs));
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D_X) |
AMD_FMT_MOD_SET(TILE_VERSION,
AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
AMD_FMT_MOD_SET(PACKERS, pkrs));
D swizzle modes are unsupported.
Marek
On Fri, Aug 7, 2020 at 9:43 PM Marek Olšák maraeo@gmail.com wrote:
On Tue, Aug 4, 2020 at 5:32 PM Bas Nieuwenhuizen bas@basnieuwenhuizen.nl wrote:
This expose modifier support on GFX9+.
Only modifiers that can be rendered on the current GPU are added. This is to reduce the number of modifiers exposed.
The HW could expose more, but the best mechanism to decide what to expose without an explosion in modifiers is still to be decided, and in the meantime this should not regress things from pre-modifiers and does not risk regressions as we make up our mind in the future.
Signed-off-by: Bas Nieuwenhuizen bas@basnieuwenhuizen.nl
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 343 +++++++++++++++++- 1 file changed, 342 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index c38257081868..6594cbe625f9 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3891,6 +3891,340 @@ fill_gfx9_tiling_info_from_modifier(const struct amdgpu_device *adev, } }
+enum dm_micro_swizzle {
MICRO_SWIZZLE_Z = 0,
MICRO_SWIZZLE_S = 1,
MICRO_SWIZZLE_D = 2,
MICRO_SWIZZLE_R = 3
+};
+static bool dm_plane_format_mod_supported(struct drm_plane *plane,
uint32_t format,
uint64_t modifier)
+{
struct amdgpu_device *adev = plane->dev->dev_private;
const struct drm_format_info *info = drm_format_info(format);
enum dm_micro_swizzle microtile = modifier_gfx9_swizzle_mode(modifier) & 3;
if (!info)
return false;
/*
* We always have to allow this modifier, because core DRM still
* checks LINEAR support if userspace does not provide modifers.
*/
if (modifier == DRM_FORMAT_MOD_LINEAR)
return true;
/*
* The arbitrary tiling support for multiplane formats has not been hooked
* up.
*/
if (info->num_planes > 1)
return false;
/*
* For D swizzle the canonical modifier depends on the bpp, so check
* it here.
*/
if (AMD_FMT_MOD_GET(TILE_VERSION, modifier) == AMD_FMT_MOD_TILE_VER_GFX9 &&
adev->family >= AMDGPU_FAMILY_NV) {
if (microtile == MICRO_SWIZZLE_D && info->cpp[0] == 4)
return false;
}
if (adev->family >= AMDGPU_FAMILY_RV && microtile == MICRO_SWIZZLE_D &&
info->cpp[0] < 8)
return false;
if (modifier_has_dcc(modifier)) {
/* Per radeonsi comments 16/64 bpp are more complicated. */
if (info->cpp[0] != 4)
return false;
}
return true;
+}
+static void +add_modifier(uint64_t **mods, uint64_t *size, uint64_t *cap, uint64_t mod) +{
if (!*mods)
return;
if (*cap - *size < 1) {
uint64_t new_cap = *cap * 2;
uint64_t *new_mods = kmalloc(new_cap * sizeof(uint64_t), GFP_KERNEL);
if (!new_mods) {
kfree(*mods);
*mods = NULL;
return;
}
memcpy(new_mods, *mods, sizeof(uint64_t) * *size);
kfree(*mods);
*mods = new_mods;
*cap = new_cap;
}
(*mods)[*size] = mod;
*size += 1;
+}
+static void +add_gfx9_modifiers(const struct amdgpu_device *adev,
uint64_t **mods, uint64_t *size, uint64_t *capacity)
+{
int pipes = ilog2(adev->gfx.config.gb_addr_config_fields.num_pipes);
int pipe_xor_bits = min(8, pipes +
ilog2(adev->gfx.config.gb_addr_config_fields.num_se));
int bank_xor_bits = min(8 - pipe_xor_bits,
ilog2(adev->gfx.config.gb_addr_config_fields.num_banks));
int rb = ilog2(adev->gfx.config.gb_addr_config_fields.num_se) +
ilog2(adev->gfx.config.gb_addr_config_fields.num_rb_per_se);
if (adev->family == AMDGPU_FAMILY_RV) {
/*
* No _D DCC swizzles yet because we only allow 32bpp, which
* doesn't support _D on DCN
*/
/*
* Always enable constant encoding, because the only unit that
* didn't support it was CB. But on texture/display we can
* always interpret it.
*/
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) |
AMD_FMT_MOD_SET(DCC, 1) |
AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B) |
AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1));
I don't think Raven1 can do DCC constant encoding in DCN and GL2.
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) |
AMD_FMT_MOD_SET(DCC, 1) |
AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B) |
AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 0));
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) |
AMD_FMT_MOD_SET(DCC, 1) |
AMD_FMT_MOD_SET(DCC_RETILE, 1) |
AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B) |
AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
AMD_FMT_MOD_SET(RB, rb) |
AMD_FMT_MOD_SET(PIPE, pipes));
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) |
AMD_FMT_MOD_SET(DCC, 1) |
AMD_FMT_MOD_SET(DCC_RETILE, 1) |
AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B) |
AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 0) |
AMD_FMT_MOD_SET(RB, rb) |
AMD_FMT_MOD_SET(PIPE, pipes));
}
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D_X) |
AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits));
Addrlib says that D swizzle modes are unsupported for 32bpp in DCN1. They are only supported in DCE12. The swizzle modes between the two have no intersection.
Right, but we don't have the format here. These get further filtered by dm_plane_format_mod_supported, which does:
if (adev->family >= AMDGPU_FAMILY_RV && microtile == MICRO_SWIZZLE_D && info->cpp[0] < 8) return false;
(cpp is in bytes)
if (adev->family == AMDGPU_FAMILY_RV) {
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits));
}
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D) |
AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
if (adev->family == AMDGPU_FAMILY_RV) {
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S) |
AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
}
+}
+static void +add_gfx10_1_modifiers(const struct amdgpu_device *adev,
uint64_t **mods, uint64_t *size, uint64_t *capacity)
+{
int pipe_xor_bits = ilog2(adev->gfx.config.gb_addr_config_fields.num_pipes);
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10) |
AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
AMD_FMT_MOD_SET(DCC, 1) |
AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B));
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10) |
AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
AMD_FMT_MOD_SET(DCC, 1) |
AMD_FMT_MOD_SET(DCC_RETILE, 1) |
AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B));
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10) |
AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits));
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D_X) |
AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10) |
AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits));
D swizzle modes are unsupported according to Addrlib.
Seems to be supported for DCN2:
https://gitlab.freedesktop.org/mesa/mesa/-/blob/master/src/amd/addrlib/src/g...
which seems to be both gfx10.1 and gfx10.3 GPUs:
https://gitlab.freedesktop.org/mesa/mesa/-/blob/master/src/amd/addrlib/src/g...
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10) |
AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits));
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D) |
AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10));
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D) |
AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S) |
AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
+}
+static void +add_gfx10_3_modifiers(const struct amdgpu_device *adev,
uint64_t **mods, uint64_t *size, uint64_t *capacity)
+{
int pipe_xor_bits = ilog2(adev->gfx.config.gb_addr_config_fields.num_pipes);
int pkrs = ilog2(adev->gfx.config.gb_addr_config_fields.num_pkrs);
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
AMD_FMT_MOD_SET(PACKERS, pkrs) |
AMD_FMT_MOD_SET(DCC, 1) |
AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
AMD_FMT_MOD_SET(DCC_INDEPENDENT_128B, 1) |
AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_128B));
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
AMD_FMT_MOD_SET(PACKERS, pkrs) |
AMD_FMT_MOD_SET(DCC, 1) |
AMD_FMT_MOD_SET(DCC_RETILE, 1) |
AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
AMD_FMT_MOD_SET(DCC_INDEPENDENT_128B, 1) |
AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_128B));
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
AMD_FMT_MOD_SET(PACKERS, pkrs));
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D_X) |
AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
AMD_FMT_MOD_SET(PACKERS, pkrs));
D swizzle modes are unsupported.
Same as above.
Marek
OK. Reviewed-by: Marek Olšák marek.olsak@amd.com
Marek
On Wed, Sep 2, 2020 at 6:31 AM Bas Nieuwenhuizen bas@basnieuwenhuizen.nl wrote:
On Fri, Aug 7, 2020 at 9:43 PM Marek Olšák maraeo@gmail.com wrote:
On Tue, Aug 4, 2020 at 5:32 PM Bas Nieuwenhuizen <
bas@basnieuwenhuizen.nl> wrote:
This expose modifier support on GFX9+.
Only modifiers that can be rendered on the current GPU are added. This is to reduce the number of modifiers exposed.
The HW could expose more, but the best mechanism to decide what to expose without an explosion in modifiers is still to be decided, and in the meantime this should not regress things from pre-modifiers and does not risk regressions as we make up our mind in the future.
Signed-off-by: Bas Nieuwenhuizen bas@basnieuwenhuizen.nl
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 343 +++++++++++++++++- 1 file changed, 342 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index c38257081868..6594cbe625f9 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3891,6 +3891,340 @@ fill_gfx9_tiling_info_from_modifier(const
struct amdgpu_device *adev,
}
}
+enum dm_micro_swizzle {
MICRO_SWIZZLE_Z = 0,
MICRO_SWIZZLE_S = 1,
MICRO_SWIZZLE_D = 2,
MICRO_SWIZZLE_R = 3
+};
+static bool dm_plane_format_mod_supported(struct drm_plane *plane,
uint32_t format,
uint64_t modifier)
+{
struct amdgpu_device *adev = plane->dev->dev_private;
const struct drm_format_info *info = drm_format_info(format);
enum dm_micro_swizzle microtile =
modifier_gfx9_swizzle_mode(modifier) & 3;
if (!info)
return false;
/*
* We always have to allow this modifier, because core DRM still
* checks LINEAR support if userspace does not provide modifers.
*/
if (modifier == DRM_FORMAT_MOD_LINEAR)
return true;
/*
* The arbitrary tiling support for multiplane formats has not
been hooked
* up.
*/
if (info->num_planes > 1)
return false;
/*
* For D swizzle the canonical modifier depends on the bpp, so
check
* it here.
*/
if (AMD_FMT_MOD_GET(TILE_VERSION, modifier) ==
AMD_FMT_MOD_TILE_VER_GFX9 &&
adev->family >= AMDGPU_FAMILY_NV) {
if (microtile == MICRO_SWIZZLE_D && info->cpp[0] == 4)
return false;
}
if (adev->family >= AMDGPU_FAMILY_RV && microtile ==
MICRO_SWIZZLE_D &&
info->cpp[0] < 8)
return false;
if (modifier_has_dcc(modifier)) {
/* Per radeonsi comments 16/64 bpp are more
complicated. */
if (info->cpp[0] != 4)
return false;
}
return true;
+}
+static void +add_modifier(uint64_t **mods, uint64_t *size, uint64_t *cap, uint64_t
mod)
+{
if (!*mods)
return;
if (*cap - *size < 1) {
uint64_t new_cap = *cap * 2;
uint64_t *new_mods = kmalloc(new_cap *
sizeof(uint64_t), GFP_KERNEL);
if (!new_mods) {
kfree(*mods);
*mods = NULL;
return;
}
memcpy(new_mods, *mods, sizeof(uint64_t) * *size);
kfree(*mods);
*mods = new_mods;
*cap = new_cap;
}
(*mods)[*size] = mod;
*size += 1;
+}
+static void +add_gfx9_modifiers(const struct amdgpu_device *adev,
uint64_t **mods, uint64_t *size, uint64_t *capacity)
+{
int pipes =
ilog2(adev->gfx.config.gb_addr_config_fields.num_pipes);
int pipe_xor_bits = min(8, pipes +
ilog2(adev->gfx.config.gb_addr_config_fields.num_se));
int bank_xor_bits = min(8 - pipe_xor_bits,
ilog2(adev->gfx.config.gb_addr_config_fields.num_banks));
int rb = ilog2(adev->gfx.config.gb_addr_config_fields.num_se) +
ilog2(adev->gfx.config.gb_addr_config_fields.num_rb_per_se);
if (adev->family == AMDGPU_FAMILY_RV) {
/*
* No _D DCC swizzles yet because we only allow 32bpp,
which
* doesn't support _D on DCN
*/
/*
* Always enable constant encoding, because the only
unit that
* didn't support it was CB. But on texture/display we
can
* always interpret it.
*/
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE,
AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
AMD_FMT_MOD_SET(TILE_VERSION,
AMD_FMT_MOD_TILE_VER_GFX9) |
AMD_FMT_MOD_SET(PIPE_XOR_BITS,
pipe_xor_bits) |
AMD_FMT_MOD_SET(BANK_XOR_BITS,
bank_xor_bits) |
AMD_FMT_MOD_SET(DCC, 1) |
AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK,
AMD_FMT_MOD_DCC_BLOCK_64B) |
AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1));
I don't think Raven1 can do DCC constant encoding in DCN and GL2.
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE,
AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
AMD_FMT_MOD_SET(TILE_VERSION,
AMD_FMT_MOD_TILE_VER_GFX9) |
AMD_FMT_MOD_SET(PIPE_XOR_BITS,
pipe_xor_bits) |
AMD_FMT_MOD_SET(BANK_XOR_BITS,
bank_xor_bits) |
AMD_FMT_MOD_SET(DCC, 1) |
AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK,
AMD_FMT_MOD_DCC_BLOCK_64B) |
AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 0));
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE,
AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
AMD_FMT_MOD_SET(TILE_VERSION,
AMD_FMT_MOD_TILE_VER_GFX9) |
AMD_FMT_MOD_SET(PIPE_XOR_BITS,
pipe_xor_bits) |
AMD_FMT_MOD_SET(BANK_XOR_BITS,
bank_xor_bits) |
AMD_FMT_MOD_SET(DCC, 1) |
AMD_FMT_MOD_SET(DCC_RETILE, 1) |
AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK,
AMD_FMT_MOD_DCC_BLOCK_64B) |
AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
AMD_FMT_MOD_SET(RB, rb) |
AMD_FMT_MOD_SET(PIPE, pipes));
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE,
AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
AMD_FMT_MOD_SET(TILE_VERSION,
AMD_FMT_MOD_TILE_VER_GFX9) |
AMD_FMT_MOD_SET(PIPE_XOR_BITS,
pipe_xor_bits) |
AMD_FMT_MOD_SET(BANK_XOR_BITS,
bank_xor_bits) |
AMD_FMT_MOD_SET(DCC, 1) |
AMD_FMT_MOD_SET(DCC_RETILE, 1) |
AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK,
AMD_FMT_MOD_DCC_BLOCK_64B) |
AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 0) |
AMD_FMT_MOD_SET(RB, rb) |
AMD_FMT_MOD_SET(PIPE, pipes));
}
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE,
AMD_FMT_MOD_TILE_GFX9_64K_D_X) |
AMD_FMT_MOD_SET(TILE_VERSION,
AMD_FMT_MOD_TILE_VER_GFX9) |
AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits));
Addrlib says that D swizzle modes are unsupported for 32bpp in DCN1.
They are only supported in DCE12. The swizzle modes between the two have no intersection.
Right, but we don't have the format here. These get further filtered by dm_plane_format_mod_supported, which does:
if (adev->family >= AMDGPU_FAMILY_RV && microtile ==
MICRO_SWIZZLE_D && info->cpp[0] < 8) return false;
(cpp is in bytes)
if (adev->family == AMDGPU_FAMILY_RV) {
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE,
AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
AMD_FMT_MOD_SET(TILE_VERSION,
AMD_FMT_MOD_TILE_VER_GFX9) |
AMD_FMT_MOD_SET(PIPE_XOR_BITS,
pipe_xor_bits) |
AMD_FMT_MOD_SET(BANK_XOR_BITS,
bank_xor_bits));
}
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D) |
AMD_FMT_MOD_SET(TILE_VERSION,
AMD_FMT_MOD_TILE_VER_GFX9));
if (adev->family == AMDGPU_FAMILY_RV) {
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE,
AMD_FMT_MOD_TILE_GFX9_64K_S) |
AMD_FMT_MOD_SET(TILE_VERSION,
AMD_FMT_MOD_TILE_VER_GFX9));
}
+}
+static void +add_gfx10_1_modifiers(const struct amdgpu_device *adev,
uint64_t **mods, uint64_t *size, uint64_t
*capacity)
+{
int pipe_xor_bits =
ilog2(adev->gfx.config.gb_addr_config_fields.num_pipes);
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE,
AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
AMD_FMT_MOD_SET(TILE_VERSION,
AMD_FMT_MOD_TILE_VER_GFX10) |
AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
AMD_FMT_MOD_SET(DCC, 1) |
AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK,
AMD_FMT_MOD_DCC_BLOCK_64B));
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE,
AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
AMD_FMT_MOD_SET(TILE_VERSION,
AMD_FMT_MOD_TILE_VER_GFX10) |
AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
AMD_FMT_MOD_SET(DCC, 1) |
AMD_FMT_MOD_SET(DCC_RETILE, 1) |
AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK,
AMD_FMT_MOD_DCC_BLOCK_64B));
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE,
AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
AMD_FMT_MOD_SET(TILE_VERSION,
AMD_FMT_MOD_TILE_VER_GFX10) |
AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits));
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE,
AMD_FMT_MOD_TILE_GFX9_64K_D_X) |
AMD_FMT_MOD_SET(TILE_VERSION,
AMD_FMT_MOD_TILE_VER_GFX10) |
AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits));
D swizzle modes are unsupported according to Addrlib.
Seems to be supported for DCN2:
https://gitlab.freedesktop.org/mesa/mesa/-/blob/master/src/amd/addrlib/src/g...
which seems to be both gfx10.1 and gfx10.3 GPUs:
https://gitlab.freedesktop.org/mesa/mesa/-/blob/master/src/amd/addrlib/src/g...
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE,
AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
AMD_FMT_MOD_SET(TILE_VERSION,
AMD_FMT_MOD_TILE_VER_GFX10) |
AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits));
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D) |
AMD_FMT_MOD_SET(TILE_VERSION,
AMD_FMT_MOD_TILE_VER_GFX10));
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D) |
AMD_FMT_MOD_SET(TILE_VERSION,
AMD_FMT_MOD_TILE_VER_GFX9));
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S) |
AMD_FMT_MOD_SET(TILE_VERSION,
AMD_FMT_MOD_TILE_VER_GFX9));
+}
+static void +add_gfx10_3_modifiers(const struct amdgpu_device *adev,
uint64_t **mods, uint64_t *size, uint64_t
*capacity)
+{
int pipe_xor_bits =
ilog2(adev->gfx.config.gb_addr_config_fields.num_pipes);
int pkrs =
ilog2(adev->gfx.config.gb_addr_config_fields.num_pkrs);
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE,
AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
AMD_FMT_MOD_SET(TILE_VERSION,
AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
AMD_FMT_MOD_SET(PACKERS, pkrs) |
AMD_FMT_MOD_SET(DCC, 1) |
AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
AMD_FMT_MOD_SET(DCC_INDEPENDENT_128B, 1) |
AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK,
AMD_FMT_MOD_DCC_BLOCK_128B));
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE,
AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
AMD_FMT_MOD_SET(TILE_VERSION,
AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
AMD_FMT_MOD_SET(PACKERS, pkrs) |
AMD_FMT_MOD_SET(DCC, 1) |
AMD_FMT_MOD_SET(DCC_RETILE, 1) |
AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
AMD_FMT_MOD_SET(DCC_INDEPENDENT_128B, 1) |
AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK,
AMD_FMT_MOD_DCC_BLOCK_128B));
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE,
AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
AMD_FMT_MOD_SET(TILE_VERSION,
AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
AMD_FMT_MOD_SET(PACKERS, pkrs));
add_modifier(mods, size, capacity, AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE,
AMD_FMT_MOD_TILE_GFX9_64K_D_X) |
AMD_FMT_MOD_SET(TILE_VERSION,
AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
AMD_FMT_MOD_SET(PACKERS, pkrs));
D swizzle modes are unsupported.
Same as above.
Marek
dri-devel@lists.freedesktop.org