diff --git a/src/nouveau/nil/image.rs b/src/nouveau/nil/image.rs index 2bf4f8db65e..0e0b8a0d6fe 100644 --- a/src/nouveau/nil/image.rs +++ b/src/nouveau/nil/image.rs @@ -82,6 +82,7 @@ pub struct ImageInitInfo { pub samples: u32, pub usage: ImageUsageFlags, pub modifier: u64, + pub explicit_row_stride_B: u32, } /// Represents the data layout of a single slice (level + lod) of an image. @@ -203,6 +204,10 @@ impl Image { // Align the size to tiles let lvl_tiling_ext_B = lvl_tiling.extent_B(); lvl_ext_B = lvl_ext_B.align(&lvl_tiling_ext_B); + assert!( + info.explicit_row_stride_B == 0 + || info.explicit_row_stride_B == lvl_ext_B.width + ); image.levels[level as usize] = ImageLevel { offset_B: layer_size_B, @@ -217,11 +222,19 @@ impl Image { // NVIDIA can't do linear and multisampling assert!(image.sample_layout == SampleLayout::_1x1); + let row_stride = if info.explicit_row_stride_B > 0 { + assert!(info.modifier == DRM_FORMAT_MOD_LINEAR); + assert!(info.explicit_row_stride_B % 128 == 0); + info.explicit_row_stride_B + } else { + lvl_ext_B.width.next_multiple_of(128) + }; + image.levels[level as usize] = ImageLevel { offset_B: layer_size_B, tiling, // Row stride needs to be aligned to 128B for render to work - row_stride_B: lvl_ext_B.width.next_multiple_of(128), + row_stride_B: row_stride, }; assert!(lvl_ext_B.depth == 1); diff --git a/src/nouveau/vulkan/nvk_image.c b/src/nouveau/vulkan/nvk_image.c index 4ed725bcd2a..dec3b667f3c 100644 --- a/src/nouveau/vulkan/nvk_image.c +++ b/src/nouveau/vulkan/nvk_image.c @@ -728,6 +728,7 @@ nvk_image_init(struct nvk_device *dev, usage |= NIL_IMAGE_USAGE_SPARSE_RESIDENCY_BIT; } + uint32_t explicit_row_stride_B = 0; if (image->vk.tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) { /* Modifiers are not supported with YCbCr */ assert(image->plane_count == 1); @@ -737,6 +738,12 @@ nvk_image_init(struct nvk_device *dev, IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT); if (mod_explicit_info) { image->vk.drm_format_mod = mod_explicit_info->drmFormatModifier; + /* Normally with explicit modifiers, the client specifies all strides, + * however in our case, we can only really make use of this in the linear + * case, and we can only create 2D non-array linear images, so ultimately + * we only care about the row stride. + */ + explicit_row_stride_B = mod_explicit_info->pPlaneLayouts->rowPitch; } else { const struct VkImageDrmFormatModifierListCreateInfoEXT *mod_list_info = vk_find_struct_const(pCreateInfo->pNext, @@ -768,6 +775,7 @@ nvk_image_init(struct nvk_device *dev, .levels = pCreateInfo->mipLevels, .samples = pCreateInfo->samples, .usage = usage & ~NIL_IMAGE_USAGE_LINEAR_BIT, + .explicit_row_stride_B = 0, }; image->linear_tiled_shadow.nil = nil_image_new(&pdev->info, &tiled_shadow_nil_info); @@ -796,6 +804,7 @@ nvk_image_init(struct nvk_device *dev, .levels = pCreateInfo->mipLevels, .samples = pCreateInfo->samples, .usage = usage, + .explicit_row_stride_B = explicit_row_stride_B, }; image->planes[plane].nil = nil_image_new(&pdev->info, &nil_info); @@ -815,6 +824,7 @@ nvk_image_init(struct nvk_device *dev, .levels = pCreateInfo->mipLevels, .samples = pCreateInfo->samples, .usage = usage, + .explicit_row_stride_B = 0, }; image->stencil_copy_temp.nil =