mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-28 03:10:25 +01:00
nvk: support multiple miplevels
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24326>
This commit is contained in:
parent
d8a9d662e4
commit
e49a66c40c
5 changed files with 106 additions and 67 deletions
|
|
@ -23,61 +23,15 @@ nvk_CmdBlitImage2(
|
|||
VK_FROM_HANDLE(nvk_image, dst, pBlitImageInfo->dstImage);
|
||||
struct nouveau_ws_push *push = cmd->push;
|
||||
|
||||
uint32_t src_depth = src->vk.extent.depth * src->vk.array_layers;
|
||||
uint32_t dst_depth = dst->vk.extent.depth * dst->vk.array_layers;
|
||||
|
||||
nouveau_ws_push_ref(push, src->mem->bo, NOUVEAU_WS_BO_RD);
|
||||
nouveau_ws_push_ref(push, dst->mem->bo, NOUVEAU_WS_BO_WR);
|
||||
|
||||
VkDeviceSize src_addr = src->mem->bo->offset + src->offset;
|
||||
VkDeviceSize dst_addr = dst->mem->bo->offset + dst->offset;
|
||||
|
||||
P_IMMD(push, NV902D, SET_CLIP_ENABLE, V_FALSE);
|
||||
P_IMMD(push, NV902D, SET_COLOR_KEY_ENABLE, V_FALSE);
|
||||
P_IMMD(push, NV902D, SET_RENDER_ENABLE_C, MODE_TRUE);
|
||||
|
||||
P_IMMD(push, NV902D, SET_SRC_FORMAT, src->format->hw_format);
|
||||
if (src->tile.is_tiled) {
|
||||
P_MTHD(push, NV902D, SET_SRC_MEMORY_LAYOUT);
|
||||
P_NV902D_SET_SRC_MEMORY_LAYOUT(push, V_BLOCKLINEAR);
|
||||
P_NV902D_SET_SRC_BLOCK_SIZE(push, {
|
||||
.height = src->tile.y,
|
||||
.depth = src->tile.z,
|
||||
});
|
||||
} else {
|
||||
P_IMMD(push, NV902D, SET_SRC_MEMORY_LAYOUT, V_PITCH);
|
||||
}
|
||||
|
||||
P_MTHD(push, NV902D, SET_SRC_DEPTH);
|
||||
P_NV902D_SET_SRC_DEPTH(push, src_depth);
|
||||
|
||||
P_MTHD(push, NV902D, SET_SRC_PITCH);
|
||||
P_NV902D_SET_SRC_PITCH(push, src->row_stride);
|
||||
P_NV902D_SET_SRC_WIDTH(push, src->vk.extent.width);
|
||||
P_NV902D_SET_SRC_HEIGHT(push, src->vk.extent.height);
|
||||
P_NV902D_SET_SRC_OFFSET_UPPER(push, src_addr >> 32);
|
||||
P_NV902D_SET_SRC_OFFSET_LOWER(push, src_addr & 0xffffffff);
|
||||
|
||||
P_IMMD(push, NV902D, SET_DST_FORMAT, dst->format->hw_format);
|
||||
if (dst->tile.is_tiled) {
|
||||
P_MTHD(push, NV902D, SET_DST_MEMORY_LAYOUT);
|
||||
P_NV902D_SET_DST_MEMORY_LAYOUT(push, V_BLOCKLINEAR);
|
||||
P_NV902D_SET_DST_BLOCK_SIZE(push, {
|
||||
.height = dst->tile.y,
|
||||
.depth = dst->tile.z,
|
||||
});
|
||||
} else {
|
||||
P_IMMD(push, NV902D, SET_DST_MEMORY_LAYOUT, V_PITCH);
|
||||
}
|
||||
|
||||
P_MTHD(push, NV902D, SET_DST_DEPTH);
|
||||
P_NV902D_SET_DST_DEPTH(push, dst_depth);
|
||||
P_NV902D_SET_DST_LAYER(push, 0);
|
||||
P_NV902D_SET_DST_PITCH(push, dst->row_stride);
|
||||
P_NV902D_SET_DST_WIDTH(push, dst->vk.extent.width);
|
||||
P_NV902D_SET_DST_HEIGHT(push, dst->vk.extent.height);
|
||||
P_NV902D_SET_DST_OFFSET_UPPER(push, dst_addr >> 32);
|
||||
P_NV902D_SET_DST_OFFSET_LOWER(push, dst_addr & 0xffffffff);
|
||||
|
||||
if (pBlitImageInfo->filter == VK_FILTER_NEAREST) {
|
||||
P_IMMD(push, NV902D, SET_PIXELS_FROM_MEMORY_SAMPLE_MODE, {
|
||||
|
|
@ -113,6 +67,15 @@ nvk_CmdBlitImage2(
|
|||
for (unsigned r = 0; r < pBlitImageInfo->regionCount; r++) {
|
||||
const VkImageBlit2 *region = &pBlitImageInfo->pRegions[r];
|
||||
|
||||
struct nvk_image_level *src_level = &src->level[region->srcSubresource.mipLevel];
|
||||
struct nvk_image_level *dst_level = &dst->level[region->dstSubresource.mipLevel];
|
||||
|
||||
VkDeviceSize src_addr = nvk_image_base_address(src, region->srcSubresource.mipLevel);
|
||||
VkDeviceSize dst_addr = nvk_image_base_address(dst, region->dstSubresource.mipLevel);
|
||||
|
||||
uint32_t src_depth = src_level->extent.depth * src->vk.array_layers;
|
||||
uint32_t dst_depth = dst_level->extent.depth * dst->vk.array_layers;
|
||||
|
||||
unsigned x_i = region->dstOffsets[0].x < region->dstOffsets[1].x ? 0 : 1;
|
||||
unsigned y_i = region->dstOffsets[0].y < region->dstOffsets[1].y ? 0 : 1;
|
||||
|
||||
|
|
@ -141,6 +104,47 @@ nvk_CmdBlitImage2(
|
|||
src_start_x_fp += scaling_x_fp / 2;
|
||||
src_start_y_fp += scaling_y_fp / 2;
|
||||
|
||||
if (src_level->tile.is_tiled) {
|
||||
P_MTHD(push, NV902D, SET_SRC_MEMORY_LAYOUT);
|
||||
P_NV902D_SET_SRC_MEMORY_LAYOUT(push, V_BLOCKLINEAR);
|
||||
P_NV902D_SET_SRC_BLOCK_SIZE(push, {
|
||||
.height = src_level->tile.y,
|
||||
.depth = src_level->tile.z,
|
||||
});
|
||||
} else {
|
||||
P_IMMD(push, NV902D, SET_SRC_MEMORY_LAYOUT, V_PITCH);
|
||||
}
|
||||
|
||||
P_MTHD(push, NV902D, SET_SRC_DEPTH);
|
||||
P_NV902D_SET_SRC_DEPTH(push, src_depth);
|
||||
|
||||
P_MTHD(push, NV902D, SET_SRC_PITCH);
|
||||
P_NV902D_SET_SRC_PITCH(push, src_level->row_stride);
|
||||
P_NV902D_SET_SRC_WIDTH(push, src_level->extent.width);
|
||||
P_NV902D_SET_SRC_HEIGHT(push, src_level->extent.height);
|
||||
P_NV902D_SET_SRC_OFFSET_UPPER(push, src_addr >> 32);
|
||||
P_NV902D_SET_SRC_OFFSET_LOWER(push, src_addr & 0xffffffff);
|
||||
|
||||
if (dst_level->tile.is_tiled) {
|
||||
P_MTHD(push, NV902D, SET_DST_MEMORY_LAYOUT);
|
||||
P_NV902D_SET_DST_MEMORY_LAYOUT(push, V_BLOCKLINEAR);
|
||||
P_NV902D_SET_DST_BLOCK_SIZE(push, {
|
||||
.height = dst_level->tile.y,
|
||||
.depth = dst_level->tile.z,
|
||||
});
|
||||
} else {
|
||||
P_IMMD(push, NV902D, SET_DST_MEMORY_LAYOUT, V_PITCH);
|
||||
}
|
||||
|
||||
P_MTHD(push, NV902D, SET_DST_DEPTH);
|
||||
P_NV902D_SET_DST_DEPTH(push, dst_depth);
|
||||
P_NV902D_SET_DST_LAYER(push, 0);
|
||||
P_NV902D_SET_DST_PITCH(push, dst_level->row_stride);
|
||||
P_NV902D_SET_DST_WIDTH(push, dst_level->extent.width);
|
||||
P_NV902D_SET_DST_HEIGHT(push, dst_level->extent.height);
|
||||
P_NV902D_SET_DST_OFFSET_UPPER(push, dst_addr >> 32);
|
||||
P_NV902D_SET_DST_OFFSET_LOWER(push, dst_addr & 0xffffffff);
|
||||
|
||||
P_MTHD(push, NV902D, SET_PIXELS_FROM_MEMORY_DST_X0);
|
||||
P_NV902D_SET_PIXELS_FROM_MEMORY_DST_X0(push, dst_start_x);
|
||||
P_NV902D_SET_PIXELS_FROM_MEMORY_DST_Y0(push, dst_start_y);
|
||||
|
|
|
|||
|
|
@ -81,13 +81,15 @@ nouveau_copy_rect_image(
|
|||
VkOffset3D offset,
|
||||
const VkImageSubresourceLayers *sub_res)
|
||||
{
|
||||
struct nvk_image_level *level = &img->level[sub_res->mipLevel];
|
||||
|
||||
struct nouveau_copy_buffer buf = {
|
||||
.base_addr = nvk_image_base_address(img),
|
||||
.base_addr = nvk_image_base_address(img, sub_res->mipLevel),
|
||||
.offset = vk_image_sanitize_offset(&img->vk, offset),
|
||||
.extent = img->vk.extent,
|
||||
.row_stride = img->row_stride,
|
||||
.layer_stride = img->layer_stride,
|
||||
.tile = img->tile,
|
||||
.extent = level->extent,
|
||||
.row_stride = level->row_stride,
|
||||
.layer_stride = level->layer_stride,
|
||||
.tile = level->tile,
|
||||
};
|
||||
|
||||
buf.extent.depth *= img->vk.array_layers;
|
||||
|
|
|
|||
|
|
@ -12,11 +12,15 @@
|
|||
* This ends being quite wasteful, but it's a more or less plain copy of what gallium does
|
||||
*/
|
||||
static struct nvk_tile
|
||||
nvk_image_tile_from_create_info(const VkImageCreateInfo *pCreateInfo, uint64_t modifier)
|
||||
nvk_image_tile_from_create_info(
|
||||
VkExtent3D extent,
|
||||
const VkImageCreateInfo *pCreateInfo,
|
||||
uint64_t modifier)
|
||||
{
|
||||
VkImageTiling tiling = pCreateInfo->tiling;
|
||||
struct nvk_tile tile = {};
|
||||
|
||||
switch (pCreateInfo->tiling) {
|
||||
switch (tiling) {
|
||||
case VK_IMAGE_TILING_LINEAR:
|
||||
tile.is_tiled = false;
|
||||
return tile;
|
||||
|
|
@ -35,8 +39,8 @@ nvk_image_tile_from_create_info(const VkImageCreateInfo *pCreateInfo, uint64_t m
|
|||
break;
|
||||
}
|
||||
|
||||
uint32_t height = pCreateInfo->extent.height;
|
||||
uint32_t depth = pCreateInfo->extent.depth;
|
||||
uint32_t height = extent.height;
|
||||
uint32_t depth = extent.depth;
|
||||
|
||||
// fermi is the baseline anyway (for now)
|
||||
tile.is_fermi = true;
|
||||
|
|
@ -88,8 +92,6 @@ static VkResult nvk_image_init(struct nvk_device *device,
|
|||
const VkImageCreateInfo *pCreateInfo)
|
||||
{
|
||||
uint64_t block_size = vk_format_get_blocksizebits(pCreateInfo->format) / 8;
|
||||
struct nvk_tile tile = nvk_image_tile_from_create_info(pCreateInfo, 0);
|
||||
VkExtent3D block = nvk_image_tile_to_blocks(tile);
|
||||
|
||||
vk_image_init(&device->vk, &image->vk, pCreateInfo);
|
||||
|
||||
|
|
@ -103,10 +105,30 @@ static VkResult nvk_image_init(struct nvk_device *device,
|
|||
}
|
||||
assert(image->format);
|
||||
|
||||
image->tile = tile;
|
||||
image->row_stride = align(image->vk.extent.width * block_size, block.width);
|
||||
image->layer_stride = align(image->vk.extent.height, block.height) * image->row_stride;
|
||||
image->min_size = image->vk.array_layers * image->vk.extent.depth * image->layer_stride;
|
||||
for (uint32_t l = 0; l < pCreateInfo->mipLevels; l++) {
|
||||
struct nvk_image_level *level = &image->level[l];
|
||||
VkExtent3D extent = vk_image_mip_level_extent(&image->vk, l);
|
||||
struct nvk_tile tile = nvk_image_tile_from_create_info(
|
||||
extent,
|
||||
pCreateInfo,
|
||||
0
|
||||
);
|
||||
VkExtent3D block = nvk_image_tile_to_blocks(tile);
|
||||
|
||||
/* need to apply a minimum alignment */
|
||||
image->min_size = align(image->min_size, 0x80);
|
||||
level->offset = image->min_size;
|
||||
level->tile = tile;
|
||||
level->extent = extent;
|
||||
level->row_stride = align(extent.width * block_size, block.width);
|
||||
|
||||
/* for untiled images we need to align the row_stride to 0x80 */
|
||||
if (!tile.is_tiled)
|
||||
level->row_stride = align(level->row_stride, 0x80);
|
||||
|
||||
level->layer_stride = level->row_stride * align(extent.height, block.height);
|
||||
image->min_size += level->layer_stride * align(extent.depth * image->vk.array_layers, block.depth);
|
||||
}
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@
|
|||
#include "nouveau_push.h"
|
||||
#include "vulkan/runtime/vk_image.h"
|
||||
|
||||
#define NVK_MAX_MIP_LEVELS 7
|
||||
|
||||
/* x can either be 0x0 or 0xe
|
||||
* 0x0: 64 blocks
|
||||
* 0xe: 16 blocks (not quite sure how that's even used, so we don't use it)
|
||||
|
|
@ -27,6 +29,16 @@ struct nvk_tile {
|
|||
};
|
||||
|
||||
struct nvk_format;
|
||||
|
||||
struct nvk_image_level {
|
||||
VkDeviceSize offset;
|
||||
VkExtent3D extent;
|
||||
|
||||
uint32_t row_stride;
|
||||
uint32_t layer_stride;
|
||||
struct nvk_tile tile;
|
||||
};
|
||||
|
||||
struct nvk_image {
|
||||
struct vk_image vk;
|
||||
struct nvk_device_memory *mem;
|
||||
|
|
@ -35,9 +47,7 @@ struct nvk_image {
|
|||
VkDeviceSize min_size;
|
||||
|
||||
struct nvk_format *format;
|
||||
uint32_t row_stride;
|
||||
uint32_t layer_stride;
|
||||
struct nvk_tile tile;
|
||||
struct nvk_image_level level[NVK_MAX_MIP_LEVELS];
|
||||
};
|
||||
|
||||
VK_DEFINE_HANDLE_CASTS(nvk_image, vk.base, VkImage, VK_OBJECT_TYPE_IMAGE)
|
||||
|
|
@ -51,9 +61,9 @@ nvk_push_image_ref(struct nouveau_ws_push *push,
|
|||
}
|
||||
|
||||
static inline uint64_t
|
||||
nvk_image_base_address(struct nvk_image *image)
|
||||
nvk_image_base_address(struct nvk_image *image, uint32_t level)
|
||||
{
|
||||
return image->mem->bo->offset + image->offset;
|
||||
return image->mem->bo->offset + image->offset + image->level[level].offset;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#include "nvk_bo_sync.h"
|
||||
#include "nvk_entrypoints.h"
|
||||
#include "nvk_format.h"
|
||||
#include "nvk_image.h"
|
||||
#include "nvk_instance.h"
|
||||
#include "nvk_wsi.h"
|
||||
|
||||
|
|
@ -433,7 +434,7 @@ nvk_GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice,
|
|||
else
|
||||
return VK_ERROR_FORMAT_NOT_SUPPORTED;
|
||||
|
||||
base_props->imageFormatProperties.maxMipLevels = 1;
|
||||
base_props->imageFormatProperties.maxMipLevels = NVK_MAX_MIP_LEVELS;
|
||||
base_props->imageFormatProperties.maxArrayLayers = 2048;
|
||||
base_props->imageFormatProperties.sampleCounts = 0;
|
||||
base_props->imageFormatProperties.maxResourceSize = 0xffffffff; // TODO proper value
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue