diff --git a/src/nouveau/vulkan/nvk_descriptor_set.c b/src/nouveau/vulkan/nvk_descriptor_set.c index a55f21d10c9..e3d5822bee2 100644 --- a/src/nouveau/vulkan/nvk_descriptor_set.c +++ b/src/nouveau/vulkan/nvk_descriptor_set.c @@ -114,6 +114,11 @@ write_storage_image_view_desc(struct nvk_descriptor_set *set, assert(view->planes[plane].storage_desc_index < (1 << 20)); desc.image_index = view->planes[plane].storage_desc_index; + + const struct nil_extent4d px_extent_sa = + nil_px_extent_sa(view->planes[plane].sample_layout); + desc.sw_log2 = util_logbase2(px_extent_sa.w); + desc.sh_log2 = util_logbase2(px_extent_sa.h); } write_desc(set, binding, elem, &desc, sizeof(desc)); diff --git a/src/nouveau/vulkan/nvk_descriptor_set.h b/src/nouveau/vulkan/nvk_descriptor_set.h index 9e777a99ad5..419675b2b93 100644 --- a/src/nouveau/vulkan/nvk_descriptor_set.h +++ b/src/nouveau/vulkan/nvk_descriptor_set.h @@ -26,7 +26,9 @@ static_assert(sizeof(struct nvk_sampled_image_descriptor) == 4, struct nvk_storage_image_descriptor { unsigned image_index:20; - unsigned pad:12; + unsigned sw_log2:2; + unsigned sh_log2:2; + unsigned pad:8; }; static_assert(sizeof(struct nvk_storage_image_descriptor) == 4, "nvk_storage_image_descriptor has no holes"); diff --git a/src/nouveau/vulkan/nvk_image.c b/src/nouveau/vulkan/nvk_image.c index b3544a881b5..05afbeede18 100644 --- a/src/nouveau/vulkan/nvk_image.c +++ b/src/nouveau/vulkan/nvk_image.c @@ -294,8 +294,7 @@ nvk_GetPhysicalDeviceImageFormatProperties2( ycbcr_info == NULL && (features & (VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT)) && - !(pImageFormatInfo->flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) && - !(pImageFormatInfo->usage & VK_IMAGE_USAGE_STORAGE_BIT)) { + !(pImageFormatInfo->flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT)) { sampleCounts = VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_2_BIT | VK_SAMPLE_COUNT_4_BIT | diff --git a/src/nouveau/vulkan/nvk_image_view.c b/src/nouveau/vulkan/nvk_image_view.c index c5efe7ef82b..219530b22c5 100644 --- a/src/nouveau/vulkan/nvk_image_view.c +++ b/src/nouveau/vulkan/nvk_image_view.c @@ -172,6 +172,8 @@ nvk_image_view_init(struct nvk_device *dev, nil_view.type != NIL_VIEW_TYPE_3D) image_3d_view_as_2d_array(&nil_image, &nil_view, &base_addr); + view->planes[view_plane].sample_layout = nil_image.sample_layout; + if (view->vk.usage & (VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) { uint32_t tic[8]; @@ -209,6 +211,9 @@ nvk_image_view_init(struct nvk_device *dev, } } + if (image->vk.samples != VK_SAMPLE_COUNT_1_BIT) + nil_msaa_image_as_sa(&nil_image, &nil_image); + uint32_t tic[8]; nil_image_fill_tic(&nvk_device_physical(dev)->info, &nil_image, &nil_view, base_addr, tic); diff --git a/src/nouveau/vulkan/nvk_image_view.h b/src/nouveau/vulkan/nvk_image_view.h index 1ed3c057903..f20f95fcfab 100644 --- a/src/nouveau/vulkan/nvk_image_view.h +++ b/src/nouveau/vulkan/nvk_image_view.h @@ -9,6 +9,8 @@ #include "vk_image.h" +#include "nil_image.h" + struct nvk_device; struct nvk_image_view { @@ -18,6 +20,8 @@ struct nvk_image_view { struct { uint8_t image_plane; + enum nil_sample_layout sample_layout; + /** Index in the image descriptor table for the sampled image descriptor */ uint32_t sampled_desc_index; diff --git a/src/nouveau/vulkan/nvk_nir_lower_descriptors.c b/src/nouveau/vulkan/nvk_nir_lower_descriptors.c index abbe5b45a6e..a7ba2bffb72 100644 --- a/src/nouveau/vulkan/nvk_nir_lower_descriptors.c +++ b/src/nouveau/vulkan/nvk_nir_lower_descriptors.c @@ -800,6 +800,80 @@ load_resource_deref_desc(nir_builder *b, set, binding, index, offset_B, ctx); } +static void +lower_msaa_image_intrin(nir_builder *b, nir_intrinsic_instr *intrin) +{ + assert(nir_intrinsic_image_dim(intrin) == GLSL_SAMPLER_DIM_MS); + + b->cursor = nir_before_instr(&intrin->instr); + + nir_def *desc = intrin->src[0].ssa; + nir_def *sw_log2 = nir_ubitfield_extract_imm(b, desc, 20, 2); + nir_def *sh_log2 = nir_ubitfield_extract_imm(b, desc, 22, 2); + + nir_def *sw = nir_ishl(b, nir_imm_int(b, 1), sw_log2); + nir_def *sh = nir_ishl(b, nir_imm_int(b, 1), sh_log2); + nir_def *num_samples = nir_imul(b, sw, sh); + + switch (intrin->intrinsic) { + case nir_intrinsic_bindless_image_load: + case nir_intrinsic_bindless_image_store: + case nir_intrinsic_bindless_image_atomic: + case nir_intrinsic_bindless_image_atomic_swap: { + nir_def *x = nir_channel(b, intrin->src[1].ssa, 0); + nir_def *y = nir_channel(b, intrin->src[1].ssa, 1); + nir_def *z = nir_channel(b, intrin->src[1].ssa, 2); + nir_def *w = nir_channel(b, intrin->src[1].ssa, 3); + nir_def *s = intrin->src[2].ssa; + + nir_def *sw_mask = nir_iadd_imm(b, sw, -1); + nir_def *sx = nir_iand(b, s, sw_mask); + nir_def *sy = nir_ishr(b, s, sw_log2); + + x = nir_imad(b, x, sw, sx); + y = nir_imad(b, y, sh, sy); + + /* Make OOB sample indices OOB X/Y indices */ + x = nir_bcsel(b, nir_ult(b, s, num_samples), x, nir_imm_int(b, -1)); + + nir_src_rewrite(&intrin->src[1], nir_vec4(b, x, y, z, w)); + nir_src_rewrite(&intrin->src[2], nir_undef(b, 1, 32)); + break; + } + + case nir_intrinsic_bindless_image_size: { + b->cursor = nir_after_instr(&intrin->instr); + + nir_def *size = &intrin->def; + nir_def *w = nir_channel(b, size, 0); + nir_def *h = nir_channel(b, size, 1); + + w = nir_ushr(b, w, sw_log2); + h = nir_ushr(b, h, sh_log2); + + size = nir_vector_insert_imm(b, size, w, 0); + size = nir_vector_insert_imm(b, size, h, 1); + + nir_def_rewrite_uses_after(&intrin->def, size, size->parent_instr); + break; + } + + case nir_intrinsic_bindless_image_samples: { + /* We need to handle NULL descriptors explicitly */ + nir_def *samples = + nir_bcsel(b, nir_ieq(b, desc, nir_imm_int(b, 0)), + nir_imm_int(b, 0), num_samples); + nir_def_rewrite_uses(&intrin->def, samples); + break; + } + + default: + unreachable("Unknown image intrinsic"); + } + + nir_intrinsic_set_image_dim(intrin, GLSL_SAMPLER_DIM_2D); +} + static bool lower_image_intrin(nir_builder *b, nir_intrinsic_instr *intrin, const struct lower_descriptors_ctx *ctx) @@ -809,6 +883,9 @@ lower_image_intrin(nir_builder *b, nir_intrinsic_instr *intrin, nir_def *desc = load_resource_deref_desc(b, 1, 32, deref, 0, ctx); nir_rewrite_image_intrinsic(intrin, desc, true); + if (nir_intrinsic_image_dim(intrin) == GLSL_SAMPLER_DIM_MS) + lower_msaa_image_intrin(b, intrin); + return true; } diff --git a/src/nouveau/vulkan/nvk_physical_device.c b/src/nouveau/vulkan/nvk_physical_device.c index 55f75fca0fc..ec6afd2afd0 100644 --- a/src/nouveau/vulkan/nvk_physical_device.c +++ b/src/nouveau/vulkan/nvk_physical_device.c @@ -266,7 +266,7 @@ nvk_get_device_features(const struct nv_device_info *info, .shaderTessellationAndGeometryPointSize = true, .shaderImageGatherExtended = true, .shaderStorageImageExtendedFormats = true, - /* TODO: shaderStorageImageMultisample */ + .shaderStorageImageMultisample = true, .shaderStorageImageReadWithoutFormat = info->cls_eng3d >= MAXWELL_A, .shaderStorageImageWriteWithoutFormat = true, .shaderUniformBufferArrayDynamicIndexing = true, @@ -693,7 +693,7 @@ nvk_get_device_properties(const struct nvk_instance *instance, .sampledImageIntegerSampleCounts = sample_counts, .sampledImageDepthSampleCounts = sample_counts, .sampledImageStencilSampleCounts = sample_counts, - .storageImageSampleCounts = VK_SAMPLE_COUNT_1_BIT, + .storageImageSampleCounts = sample_counts, .maxSampleMaskWords = 1, .timestampComputeAndGraphics = true, .timestampPeriod = 1, diff --git a/src/nouveau/vulkan/nvk_shader.c b/src/nouveau/vulkan/nvk_shader.c index 1fb59288263..c7ac41a80ca 100644 --- a/src/nouveau/vulkan/nvk_shader.c +++ b/src/nouveau/vulkan/nvk_shader.c @@ -133,6 +133,7 @@ nvk_get_spirv_options(struct vk_physical_device *vk_pdev, .fragment_barycentric = true, .geometry_streams = true, .image_atomic_int64 = true, + .image_ms_array = true, .image_read_without_format = true, .image_write_without_format = true, .int8 = true, @@ -149,6 +150,7 @@ nvk_get_spirv_options(struct vk_physical_device *vk_pdev, .sparse_residency = true, .storage_8bit = true, .storage_16bit = true, + .storage_image_ms = true, .subgroup_arithmetic = true, .subgroup_ballot = true, .subgroup_basic = true,