anv: Flip around the way we reason about storage image lowering
There are roughly two cases when it comes to storage images. In the easy case, we have full hardware support and we can just emit a typed read/write message in the shader and we're done. In the more complex cases, we may need to fall back to a typed read with a different format or even to a raw (SSBO) read. The hardware has always had basically full support for typed writes all the way back to Ivy Bridge but typed reads have been harder to come by. Starting with Skylake, we finally have enough that we at least have a format of the right bit size but not necessarily the right format so we can use a typed read but may still have to do an int->unorm or similar cast in the shader. Previously, in ANV, we treated lowered images as the default and write- only as a special case that we can optimize. This flips everything around and treats the cases where we don't need to do any lowering as the default "vanilla" case and treats the lowered case as special. Importantly, this means that read-write access to surfaces where the native format handles typed writes now use the same surface state as write-only access and the only thing that uses the lowered surface state is access read-write access with a format that doesn't support typed reads. This has the added benefit that now, if someone does a read without specifying a format, we can default to the vanilla surface and it will work as long as it's a format that supports typed reads. Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/13198>
This commit is contained in:
@@ -2387,7 +2387,7 @@ anv_image_fill_surface_state(struct anv_device *device,
|
||||
anv_image_address(image, &surface->memory_range);
|
||||
|
||||
if (view_usage == ISL_SURF_USAGE_STORAGE_BIT &&
|
||||
!(flags & ANV_IMAGE_VIEW_STATE_STORAGE_WRITE_ONLY) &&
|
||||
(flags & ANV_IMAGE_VIEW_STATE_STORAGE_LOWERED) &&
|
||||
!isl_has_matching_typed_storage_image_format(&device->info,
|
||||
view.format)) {
|
||||
/* In this case, we are a writeable storage buffer which needs to be
|
||||
@@ -2407,7 +2407,7 @@ anv_image_fill_surface_state(struct anv_device *device,
|
||||
state_inout->clear_address = ANV_NULL_ADDRESS;
|
||||
} else {
|
||||
if (view_usage == ISL_SURF_USAGE_STORAGE_BIT &&
|
||||
!(flags & ANV_IMAGE_VIEW_STATE_STORAGE_WRITE_ONLY)) {
|
||||
(flags & ANV_IMAGE_VIEW_STATE_STORAGE_LOWERED)) {
|
||||
/* Typed surface reads support a very limited subset of the shader
|
||||
* image formats. Translate it into the closest format the hardware
|
||||
* supports.
|
||||
@@ -2628,37 +2628,38 @@ anv_CreateImageView(VkDevice _device,
|
||||
|
||||
/* NOTE: This one needs to go last since it may stomp isl_view.format */
|
||||
if (iview->vk.usage & VK_IMAGE_USAGE_STORAGE_BIT) {
|
||||
iview->planes[vplane].storage_surface_state.state = alloc_surface_state(device);
|
||||
anv_image_fill_surface_state(device, image, 1ULL << iaspect_bit,
|
||||
&iview->planes[vplane].isl,
|
||||
ISL_SURF_USAGE_STORAGE_BIT,
|
||||
ISL_AUX_USAGE_NONE, NULL,
|
||||
0,
|
||||
&iview->planes[vplane].storage_surface_state,
|
||||
NULL);
|
||||
|
||||
if (isl_is_storage_image_format(format.isl_format)) {
|
||||
iview->planes[vplane].storage_surface_state.state =
|
||||
iview->planes[vplane].lowered_storage_surface_state.state =
|
||||
alloc_surface_state(device);
|
||||
|
||||
anv_image_fill_surface_state(device, image, 1ULL << iaspect_bit,
|
||||
&iview->planes[vplane].isl,
|
||||
ISL_SURF_USAGE_STORAGE_BIT,
|
||||
ISL_AUX_USAGE_NONE, NULL,
|
||||
0,
|
||||
&iview->planes[vplane].storage_surface_state,
|
||||
&iview->planes[vplane].storage_image_param);
|
||||
ANV_IMAGE_VIEW_STATE_STORAGE_LOWERED,
|
||||
&iview->planes[vplane].lowered_storage_surface_state,
|
||||
&iview->planes[vplane].lowered_storage_image_param);
|
||||
} else {
|
||||
/* In this case, we support the format but, because there's no
|
||||
* SPIR-V format specifier corresponding to it, we only support
|
||||
* NonReadable (writeonly in GLSL) access. Instead of hanging in
|
||||
* these invalid cases, we give them a NULL descriptor.
|
||||
* SPIR-V format specifier corresponding to it, we only support it
|
||||
* if the hardware can do it natively. This is possible for some
|
||||
* reads but for most writes. Instead of hanging if someone gets
|
||||
* it wrong, we give them a NULL descriptor.
|
||||
*/
|
||||
assert(isl_format_supports_typed_writes(&device->info,
|
||||
format.isl_format));
|
||||
iview->planes[vplane].storage_surface_state.state =
|
||||
device->null_surface_state;
|
||||
}
|
||||
|
||||
iview->planes[vplane].writeonly_storage_surface_state.state = alloc_surface_state(device);
|
||||
anv_image_fill_surface_state(device, image, 1ULL << iaspect_bit,
|
||||
&iview->planes[vplane].isl,
|
||||
ISL_SURF_USAGE_STORAGE_BIT,
|
||||
ISL_AUX_USAGE_NONE, NULL,
|
||||
ANV_IMAGE_VIEW_STATE_STORAGE_WRITE_ONLY,
|
||||
&iview->planes[vplane].writeonly_storage_surface_state,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2697,9 +2698,9 @@ anv_DestroyImageView(VkDevice _device, VkImageView _iview,
|
||||
iview->planes[plane].storage_surface_state.state);
|
||||
}
|
||||
|
||||
if (iview->planes[plane].writeonly_storage_surface_state.state.offset) {
|
||||
if (iview->planes[plane].lowered_storage_surface_state.state.offset) {
|
||||
anv_state_pool_free(&device->surface_state_pool,
|
||||
iview->planes[plane].writeonly_storage_surface_state.state);
|
||||
iview->planes[plane].lowered_storage_surface_state.state);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2746,32 +2747,31 @@ anv_CreateBufferView(VkDevice _device,
|
||||
|
||||
if (buffer->usage & VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT) {
|
||||
view->storage_surface_state = alloc_surface_state(device);
|
||||
view->writeonly_storage_surface_state = alloc_surface_state(device);
|
||||
view->lowered_storage_surface_state = alloc_surface_state(device);
|
||||
|
||||
enum isl_format storage_format =
|
||||
anv_fill_buffer_surface_state(device, view->storage_surface_state,
|
||||
view->format, ISL_SURF_USAGE_STORAGE_BIT,
|
||||
view->address, view->range,
|
||||
isl_format_get_layout(view->format)->bpb / 8);
|
||||
|
||||
enum isl_format lowered_format =
|
||||
isl_has_matching_typed_storage_image_format(&device->info,
|
||||
view->format) ?
|
||||
isl_lower_storage_image_format(&device->info, view->format) :
|
||||
ISL_FORMAT_RAW;
|
||||
|
||||
anv_fill_buffer_surface_state(device, view->storage_surface_state,
|
||||
storage_format, ISL_SURF_USAGE_STORAGE_BIT,
|
||||
anv_fill_buffer_surface_state(device, view->lowered_storage_surface_state,
|
||||
lowered_format, ISL_SURF_USAGE_STORAGE_BIT,
|
||||
view->address, view->range,
|
||||
(storage_format == ISL_FORMAT_RAW ? 1 :
|
||||
isl_format_get_layout(storage_format)->bpb / 8));
|
||||
|
||||
/* Write-only accesses should use the original format. */
|
||||
anv_fill_buffer_surface_state(device, view->writeonly_storage_surface_state,
|
||||
view->format, ISL_SURF_USAGE_STORAGE_BIT,
|
||||
view->address, view->range,
|
||||
isl_format_get_layout(view->format)->bpb / 8);
|
||||
(lowered_format == ISL_FORMAT_RAW ? 1 :
|
||||
isl_format_get_layout(lowered_format)->bpb / 8));
|
||||
|
||||
isl_buffer_fill_image_param(&device->isl_dev,
|
||||
&view->storage_image_param,
|
||||
&view->lowered_storage_image_param,
|
||||
view->format, view->range);
|
||||
} else {
|
||||
view->storage_surface_state = (struct anv_state){ 0 };
|
||||
view->writeonly_storage_surface_state = (struct anv_state){ 0 };
|
||||
view->lowered_storage_surface_state = (struct anv_state){ 0 };
|
||||
}
|
||||
|
||||
*pView = anv_buffer_view_to_handle(view);
|
||||
@@ -2797,9 +2797,9 @@ anv_DestroyBufferView(VkDevice _device, VkBufferView bufferView,
|
||||
anv_state_pool_free(&device->surface_state_pool,
|
||||
view->storage_surface_state);
|
||||
|
||||
if (view->writeonly_storage_surface_state.alloc_size > 0)
|
||||
if (view->lowered_storage_surface_state.alloc_size > 0)
|
||||
anv_state_pool_free(&device->surface_state_pool,
|
||||
view->writeonly_storage_surface_state);
|
||||
view->lowered_storage_surface_state);
|
||||
|
||||
vk_object_free(&device->vk, pAllocator, view);
|
||||
}
|
||||
|
Reference in New Issue
Block a user