diff --git a/src/gallium/drivers/zink/zink_kopper.c b/src/gallium/drivers/zink/zink_kopper.c index 73629aa27c2..9ee37711677 100644 --- a/src/gallium/drivers/zink/zink_kopper.c +++ b/src/gallium/drivers/zink/zink_kopper.c @@ -292,6 +292,20 @@ kopper_CreateSwapchain(struct zink_screen *screen, struct kopper_displaytarget * if (cdt->formats[1]) cswap->scci.pNext = &cdt->format_list; + cswap->comp.pFixedRateFlags = &cswap->comp_rate; + cswap->comp.sType = VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_CONTROL_EXT; + cswap->comp.pNext = cswap->scci.pNext; + cswap->comp.compressionControlPlaneCount = 0; + if (cdt->info.compression) { + if (cdt->info.compression == UINT32_MAX) { + cswap->comp.flags = VK_IMAGE_COMPRESSION_FIXED_RATE_DEFAULT_EXT; + } else { + cswap->comp.flags = VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT; + cswap->comp_rate = cdt->info.compression; + } + cswap->scci.pNext = &cswap->comp; + } + /* different display platforms have, by vulkan spec, different sizing methodologies */ switch (cdt->type) { case KOPPER_X11: diff --git a/src/gallium/drivers/zink/zink_kopper.h b/src/gallium/drivers/zink/zink_kopper.h index 8b91f38f69e..d82859d5523 100644 --- a/src/gallium/drivers/zink/zink_kopper.h +++ b/src/gallium/drivers/zink/zink_kopper.h @@ -60,6 +60,8 @@ struct kopper_swapchain { uint32_t last_present_prune; struct hash_table *presents; VkSwapchainCreateInfoKHR scci; + VkImageCompressionFixedRateFlagsEXT comp_rate; + VkImageCompressionControlEXT comp; unsigned num_acquires; unsigned max_acquires; unsigned async_presents; diff --git a/src/gallium/drivers/zink/zink_resource.c b/src/gallium/drivers/zink/zink_resource.c index c90b7d2d8bb..bc05d873884 100644 --- a/src/gallium/drivers/zink/zink_resource.c +++ b/src/gallium/drivers/zink/zink_resource.c @@ -1298,6 +1298,23 @@ create_image(struct zink_screen *screen, struct zink_resource_object *obj, } else { ici.pNext = NULL; } + VkImageCompressionFixedRateFlagsEXT rate = 0; + VkImageCompressionControlEXT compression = { + VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_CONTROL_EXT, + ici.pNext, + 0, + 1, + &rate + }; + if (templ->compression_rate != PIPE_COMPRESSION_FIXED_RATE_NONE) { + if (templ->compression_rate == PIPE_COMPRESSION_FIXED_RATE_DEFAULT) { + compression.flags = VK_IMAGE_COMPRESSION_FIXED_RATE_DEFAULT_EXT; + } else { + compression.flags = VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT; + rate = BITFIELD_BIT(templ->compression_rate - 1); + } + ici.pNext = &compression; + } init_ici(screen, &ici, templ, templ->bind, ici_modifier_count); bool success = false; diff --git a/src/gallium/drivers/zink/zink_screen.c b/src/gallium/drivers/zink/zink_screen.c index 27972d0a2fb..72c48f45036 100644 --- a/src/gallium/drivers/zink/zink_screen.c +++ b/src/gallium/drivers/zink/zink_screen.c @@ -2068,6 +2068,36 @@ check_have_device_time(struct zink_screen *screen) return false; } +static void +zink_query_compression_rates(struct pipe_screen *pscreen, enum pipe_format pformat, int max, uint32_t *rates, int *count) +{ + struct zink_screen *screen = zink_screen(pscreen); + + if (!screen->format_props[pformat].compressionRates) { + *count = 1; + if (max) + *rates = PIPE_COMPRESSION_FIXED_RATE_NONE; + return; + } + if (screen->format_props[pformat].compressionRates == UINT32_MAX) { + *count = 1; + if (max) + *rates = PIPE_COMPRESSION_FIXED_RATE_DEFAULT; + return; + } + + *count = util_bitcount(screen->format_props[pformat].compressionRates); + if (!max) + return; + + unsigned c = 0; + u_foreach_bit(r, screen->format_props[pformat].compressionRates) { + rates[c] = r + 1; + if (++c == max) + break; + } +} + static void zink_error(const char *msg) { @@ -3612,6 +3642,8 @@ zink_internal_create_screen(const struct pipe_screen_config *config, int64_t dev } } } + if (screen->info.have_EXT_image_compression_control && screen->info.have_EXT_image_compression_control_swapchain) + screen->base.query_compression_rates = zink_query_compression_rates; if (!zink_screen_resource_init(&screen->base)) goto fail;