From d98540c6457c1b4a6a8f651a97b57a575e8cc251 Mon Sep 17 00:00:00 2001 From: Karol Herbst Date: Mon, 6 Jun 2022 03:26:54 +0200 Subject: [PATCH] nvk: add basic support for images enough to get basic operations working Part-of: --- src/nouveau/vulkan/meson.build | 2 + src/nouveau/vulkan/nvk_cmd_buffer.c | 54 +----- src/nouveau/vulkan/nvk_cmd_buffer.h | 2 + src/nouveau/vulkan/nvk_cmd_copy.c | 347 ++++++++++++++++++++++++++++++++++++ src/nouveau/vulkan/nvk_image.c | 116 ++++++++++++ src/nouveau/vulkan/nvk_image.h | 26 +++ src/nouveau/winsys/push906f.h | 1 + 7 files changed, 495 insertions(+), 53 deletions(-) create mode 100644 src/nouveau/vulkan/nvk_cmd_copy.c diff --git a/src/nouveau/vulkan/meson.build b/src/nouveau/vulkan/meson.build index 683a747..3640fb5 100644 --- a/src/nouveau/vulkan/meson.build +++ b/src/nouveau/vulkan/meson.build @@ -5,6 +5,7 @@ nvk_files = files( 'nvk_buffer.h', 'nvk_cmd_buffer.c', 'nvk_cmd_buffer.h', + 'nvk_cmd_copy.c', 'nvk_descriptor_set.h', 'nvk_descriptor_set.c', 'nvk_descriptor_set_layout.c', @@ -78,6 +79,7 @@ libvulkan_nouveau = shared_library( nvk_files, ], include_directories : [ + inc_gallium, inc_include, inc_src, ], diff --git a/src/nouveau/vulkan/nvk_cmd_buffer.c b/src/nouveau/vulkan/nvk_cmd_buffer.c index e808797..faa754b 100644 --- a/src/nouveau/vulkan/nvk_cmd_buffer.c +++ b/src/nouveau/vulkan/nvk_cmd_buffer.c @@ -1,16 +1,10 @@ #include "nvk_cmd_buffer.h" -#include "nvk_buffer.h" #include "nvk_device.h" -#include "nvk_device_memory.h" #include "nvk_physical_device.h" -#include "nouveau_bo.h" #include "nouveau_push.h" -#include "classes/cl90b5.h" -#include "push906f.h" - static void nvk_destroy_cmd_buffer(struct nvk_cmd_buffer *cmd_buffer) { @@ -77,6 +71,7 @@ nvk_CreateCommandPool(VkDevice _device, const VkCommandPoolCreateInfo *pCreateIn list_inithead(&pool->cmd_buffers); list_inithead(&pool->free_cmd_buffers); + pool->dev = device; *pCmdPool = nvk_cmd_pool_to_handle(pool); return VK_SUCCESS; @@ -227,52 +222,5 @@ nvk_EndCommandBuffer(VkCommandBuffer commandBuffer) } VKAPI_ATTR void VKAPI_CALL -nvk_CmdCopyBuffer(VkCommandBuffer commandBuffer, - VkBuffer srcBuffer, VkBuffer dstBuffer, - uint32_t regionCount, const VkBufferCopy* pRegions) -{ - VK_FROM_HANDLE(nvk_cmd_buffer, cmd, commandBuffer); - VK_FROM_HANDLE(nvk_buffer, src, srcBuffer); - VK_FROM_HANDLE(nvk_buffer, dst, dstBuffer); - struct nouveau_ws_push *push = cmd->push; - - nouveau_ws_push_ref(push, src->mem->bo, NOUVEAU_WS_BO_RD); - nouveau_ws_push_ref(push, dst->mem->bo, NOUVEAU_WS_BO_WR); - - for (unsigned r = 0; r < regionCount; r++) { - const VkBufferCopy *region = &pRegions[r]; - VkDeviceSize dstoff = dst->mem->bo->offset + dst->offset + region->dstOffset; - VkDeviceSize srcoff = src->mem->bo->offset + src->offset + region->srcOffset; - VkDeviceSize size = region->size; - - while (size) { - unsigned bytes = MIN2(size, 1 << 17); - - PUSH_MTHD(push, NV90B5, OFFSET_IN_UPPER, - NVVAL(NV90B5, OFFSET_IN_UPPER, UPPER, srcoff >> 32), - OFFSET_IN_LOWER, srcoff & 0xffffffff, - - OFFSET_OUT_UPPER, - NVVAL(NV90B5, OFFSET_OUT_UPPER, UPPER, dstoff >> 32), - OFFSET_OUT_LOWER, dstoff & 0xffffffff); - - PUSH_MTHD(push, NV90B5, LINE_LENGTH_IN, bytes, - LINE_COUNT, 1); - - PUSH_IMMD(push, NV90B5, LAUNCH_DMA, - NVDEF(NV90B5, LAUNCH_DMA, DATA_TRANSFER_TYPE, NON_PIPELINED) | - NVDEF(NV90B5, LAUNCH_DMA, FLUSH_ENABLE, TRUE) | - NVDEF(NV90B5, LAUNCH_DMA, SRC_MEMORY_LAYOUT, PITCH) | - NVDEF(NV90B5, LAUNCH_DMA, DST_MEMORY_LAYOUT, PITCH)); - - srcoff += bytes; - dstoff += bytes; - size -= bytes; - } - } -} - - -VKAPI_ATTR void VKAPI_CALL nvk_CmdPipelineBarrier2(VkCommandBuffer commandBuffer, const VkDependencyInfo *pDependencyInfo) { } diff --git a/src/nouveau/vulkan/nvk_cmd_buffer.h b/src/nouveau/vulkan/nvk_cmd_buffer.h index c7db064..f720c2a 100644 --- a/src/nouveau/vulkan/nvk_cmd_buffer.h +++ b/src/nouveau/vulkan/nvk_cmd_buffer.h @@ -12,6 +12,8 @@ struct nvk_cmd_pool { struct vk_command_pool vk; struct list_head cmd_buffers; struct list_head free_cmd_buffers; + + struct nvk_device *dev; }; struct nvk_cmd_buffer { diff --git a/src/nouveau/vulkan/nvk_cmd_copy.c b/src/nouveau/vulkan/nvk_cmd_copy.c new file mode 100644 index 0000000..ea51dd4 --- /dev/null +++ b/src/nouveau/vulkan/nvk_cmd_copy.c @@ -0,0 +1,347 @@ +#include "nvk_cmd_buffer.h" + +#include "vulkan/util/vk_format.h" + +#include "nvk_buffer.h" +#include "nvk_device.h" +#include "nvk_device_memory.h" +#include "nvk_image.h" +#include "nvk_physical_device.h" + +#include "nouveau_bo.h" +#include "nouveau_push.h" + +#include "nvtypes.h" +#include "classes/cl90b5.h" +#include "classes/clc1b5.h" +#include "push906f.h" + +static void +nouveau_copy_linear( + struct nouveau_ws_push *push, + struct nouveau_ws_bo *src, uint64_t src_offset, + struct nouveau_ws_bo *dst, uint64_t dst_offset, + uint64_t size) +{ + VkDeviceSize src_addr = src->offset + src_offset; + VkDeviceSize dst_addr = dst->offset + dst_offset; + + nouveau_ws_push_ref(push, src, NOUVEAU_WS_BO_RD); + nouveau_ws_push_ref(push, dst, NOUVEAU_WS_BO_WR); + + while (size) { + unsigned bytes = MIN2(size, 1 << 17); + + PUSH_MTHD(push, NV90B5, OFFSET_IN_UPPER, + NVVAL(NV90B5, OFFSET_IN_UPPER, UPPER, src_addr >> 32), + OFFSET_IN_LOWER, src_addr & 0xffffffff, + + OFFSET_OUT_UPPER, + NVVAL(NV90B5, OFFSET_OUT_UPPER, UPPER, dst_addr >> 32), + OFFSET_OUT_LOWER, dst_addr & 0xffffffff); + + PUSH_MTHD(push, NV90B5, LINE_LENGTH_IN, bytes, + LINE_COUNT, 1); + PUSH_IMMD(push, NV90B5, LAUNCH_DMA, + NVDEF(NV90B5, LAUNCH_DMA, DATA_TRANSFER_TYPE, NON_PIPELINED) | + NVDEF(NV90B5, LAUNCH_DMA, MULTI_LINE_ENABLE, FALSE) | + NVDEF(NV90B5, LAUNCH_DMA, FLUSH_ENABLE, TRUE) | + NVDEF(NV90B5, LAUNCH_DMA, SRC_MEMORY_LAYOUT, PITCH) | + NVDEF(NV90B5, LAUNCH_DMA, DST_MEMORY_LAYOUT, PITCH)); + + src_addr += bytes; + dst_addr += bytes; + size -= bytes; + } +} + +struct nouveau_copy_buffer { + struct nouveau_ws_bo *bo; + uint64_t bo_offset; + VkOffset3D offset; + VkExtent3D extent; + uint32_t row_stride; + uint32_t layer_stride; + struct nvk_tile tile; +}; + +struct nouveau_copy { + struct nouveau_copy_buffer src; + struct nouveau_copy_buffer dst; + uint32_t bpp; + VkExtent3D extent; +}; + +static struct nouveau_copy_buffer +nouveau_copy_rect_buffer( + struct nvk_buffer *buf, + VkDeviceSize offset, + struct vk_image_buffer_layout buffer_layout) +{ + return (struct nouveau_copy_buffer) { + .bo = buf->mem->bo, + .bo_offset = buf->offset + offset, + .row_stride = buffer_layout.row_stride_B, + .layer_stride = buffer_layout.image_stride_B, + }; +} + +static struct nouveau_copy_buffer +nouveau_copy_rect_image( + struct nvk_image *img, + VkOffset3D offset, + const VkImageSubresourceLayers *sub_res) +{ + struct nouveau_copy_buffer buf = { + .bo = img->mem->bo, + .bo_offset = img->offset, + .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, + }; + + buf.extent.depth *= img->vk.array_layers; + buf.offset.z += sub_res->baseArrayLayer; + + return buf; +} + +static void +nouveau_copy_rect(struct nvk_cmd_buffer *cmd, struct nouveau_copy *copy) +{ + VkDeviceSize src_addr = copy->src.bo->offset + copy->src.bo_offset; + VkDeviceSize dst_addr = copy->dst.bo->offset + copy->dst.bo_offset; + + if (!copy->src.tile.is_tiled) { + src_addr += + copy->src.offset.x * copy->bpp + + copy->src.offset.y * copy->src.row_stride + + copy->src.offset.z * copy->src.layer_stride; + } + + if (!copy->dst.tile.is_tiled) { + dst_addr += + copy->dst.offset.x * copy->bpp + + copy->dst.offset.y * copy->dst.row_stride + + copy->dst.offset.z * copy->dst.layer_stride; + } + + struct nouveau_ws_push *push = cmd->push; + + nouveau_ws_push_ref(push, copy->src.bo, NOUVEAU_WS_BO_RD); + nouveau_ws_push_ref(push, copy->dst.bo, NOUVEAU_WS_BO_WR); + + for (unsigned z = 0; z < copy->extent.depth; z++) { + PUSH_MTHD(push, NV90B5, OFFSET_IN_UPPER, + NVVAL(NV90B5, OFFSET_IN_UPPER, UPPER, src_addr >> 32), + OFFSET_IN_LOWER, src_addr & 0xffffffff, + + OFFSET_OUT_UPPER, + NVVAL(NV90B5, OFFSET_OUT_UPPER, UPPER, dst_addr >> 32), + OFFSET_OUT_LOWER, dst_addr & 0xffffffff, + PITCH_IN, copy->src.row_stride, + PITCH_OUT, copy->dst.row_stride, + LINE_LENGTH_IN, copy->extent.width * copy->bpp, + LINE_COUNT, copy->extent.height); + + uint32_t pitch_cmd = 0; + if (copy->src.tile.is_tiled) { + assert(copy->src.tile.is_fermi); + PUSH_MTHD(push, NV90B5, SET_SRC_BLOCK_SIZE, + NVVAL(NV90B5, SET_SRC_BLOCK_SIZE, WIDTH, copy->src.tile.x) | + NVVAL(NV90B5, SET_SRC_BLOCK_SIZE, HEIGHT, copy->src.tile.y) | + NVVAL(NV90B5, SET_SRC_BLOCK_SIZE, DEPTH, copy->src.tile.z) | + NVDEF(NV90B5, SET_SRC_BLOCK_SIZE, GOB_HEIGHT, GOB_HEIGHT_FERMI_8), + + SET_SRC_WIDTH, copy->src.extent.width * copy->bpp, + SET_SRC_HEIGHT, copy->src.extent.height, + SET_SRC_DEPTH, copy->src.extent.depth, + SET_SRC_LAYER, z + copy->src.offset.z); + + if (cmd->pool->dev->pdev->dev->cls >= 0xc1) { + PUSH_MTHD(push, NVC1B5, SRC_ORIGIN_X, + NVVAL(NVC1B5, SRC_ORIGIN_X, VALUE, copy->src.offset.x * copy->bpp), + SRC_ORIGIN_Y, + NVVAL(NVC1B5, SRC_ORIGIN_Y, VALUE, copy->src.offset.y)); + } else { + PUSH_MTHD(push, NV90B5, SET_SRC_ORIGIN, + NVVAL(NV90B5, SET_SRC_ORIGIN, X, copy->src.offset.x * copy->bpp) | + NVVAL(NV90B5, SET_SRC_ORIGIN, Y, copy->src.offset.y)); + } + + pitch_cmd |= NVDEF(NV90B5, LAUNCH_DMA, SRC_MEMORY_LAYOUT, BLOCKLINEAR); + } else { + src_addr += copy->src.layer_stride; + pitch_cmd |= NVDEF(NV90B5, LAUNCH_DMA, SRC_MEMORY_LAYOUT, PITCH); + } + + if (copy->dst.tile.is_tiled) { + assert(copy->dst.tile.is_fermi); + PUSH_MTHD(push, NV90B5, SET_DST_BLOCK_SIZE, + NVVAL(NV90B5, SET_DST_BLOCK_SIZE, WIDTH, copy->dst.tile.x) | + NVVAL(NV90B5, SET_DST_BLOCK_SIZE, HEIGHT, copy->dst.tile.y) | + NVVAL(NV90B5, SET_DST_BLOCK_SIZE, DEPTH, copy->dst.tile.z) | + NVDEF(NV90B5, SET_DST_BLOCK_SIZE, GOB_HEIGHT, GOB_HEIGHT_FERMI_8), + + SET_DST_WIDTH, copy->dst.extent.width * copy->bpp, + SET_DST_HEIGHT, copy->dst.extent.height, + SET_DST_DEPTH, copy->dst.extent.depth, + SET_DST_LAYER, z + copy->dst.offset.z); + + if (cmd->pool->dev->pdev->dev->cls >= 0xc1) { + PUSH_MTHD(push, NVC1B5, DST_ORIGIN_X, + NVVAL(NVC1B5, DST_ORIGIN_X, VALUE, copy->dst.offset.x * copy->bpp), + DST_ORIGIN_Y, + NVVAL(NVC1B5, DST_ORIGIN_Y, VALUE, copy->dst.offset.y)); + } else { + PUSH_MTHD(push, NV90B5, SET_DST_ORIGIN, + NVVAL(NV90B5, SET_DST_ORIGIN, X, copy->dst.offset.x * copy->bpp) | + NVVAL(NV90B5, SET_DST_ORIGIN, Y, copy->dst.offset.y)); + } + + pitch_cmd |= NVDEF(NV90B5, LAUNCH_DMA, DST_MEMORY_LAYOUT, BLOCKLINEAR); + } else { + dst_addr += copy->dst.layer_stride; + pitch_cmd |= NVDEF(NV90B5, LAUNCH_DMA, DST_MEMORY_LAYOUT, PITCH); + } + + PUSH_IMMD(push, NV90B5, LAUNCH_DMA, + NVDEF(NV90B5, LAUNCH_DMA, DATA_TRANSFER_TYPE, NON_PIPELINED) | + NVDEF(NV90B5, LAUNCH_DMA, MULTI_LINE_ENABLE, TRUE) | + NVDEF(NV90B5, LAUNCH_DMA, FLUSH_ENABLE, TRUE) | + pitch_cmd); + } +} + +VKAPI_ATTR void VKAPI_CALL +nvk_CmdCopyBuffer(VkCommandBuffer commandBuffer, + VkBuffer srcBuffer, VkBuffer dstBuffer, + uint32_t regionCount, const VkBufferCopy* pRegions) +{ + VK_FROM_HANDLE(nvk_cmd_buffer, cmd, commandBuffer); + VK_FROM_HANDLE(nvk_buffer, src, srcBuffer); + VK_FROM_HANDLE(nvk_buffer, dst, dstBuffer); + struct nouveau_ws_push *push = cmd->push; + + for (unsigned r = 0; r < regionCount; r++) { + const VkBufferCopy *region = &pRegions[r]; + + nouveau_copy_linear( + push, + src->mem->bo, src->offset + region->srcOffset, + dst->mem->bo, dst->offset + region->dstOffset, + region->size); + } +} + +VKAPI_ATTR void VKAPI_CALL +nvk_CmdCopyBufferToImage2( + VkCommandBuffer commandBuffer, + const VkCopyBufferToImageInfo2 *pCopyBufferToImageInfo) +{ + VK_FROM_HANDLE(nvk_cmd_buffer, cmd, commandBuffer); + VK_FROM_HANDLE(nvk_buffer, src, pCopyBufferToImageInfo->srcBuffer); + VK_FROM_HANDLE(nvk_image, dst, pCopyBufferToImageInfo->dstImage); + + for (unsigned r = 0; r < pCopyBufferToImageInfo->regionCount; r++) { + const VkBufferImageCopy2 *region = &pCopyBufferToImageInfo->pRegions[r]; + struct vk_image_buffer_layout buffer_layout = vk_image_buffer_copy_layout(&dst->vk, region); + + struct nouveau_copy copy = { + .src = nouveau_copy_rect_buffer(src, region->bufferOffset, buffer_layout), + .dst = nouveau_copy_rect_image(dst, region->imageOffset, ®ion->imageSubresource), + .bpp = buffer_layout.element_size_B, + .extent = vk_image_sanitize_extent(&dst->vk, region->imageExtent), + }; + copy.extent.depth *= region->imageSubresource.layerCount; + + nouveau_copy_rect(cmd, ©); + + vk_foreach_struct_const(ext, region->pNext) { + switch (ext->sType) { + default: + nvk_debug_ignored_stype(ext->sType); + break; + } + } + } + + vk_foreach_struct_const(ext, pCopyBufferToImageInfo->pNext) { + switch (ext->sType) { + default: + nvk_debug_ignored_stype(ext->sType); + break; + } + } +} + +VKAPI_ATTR void VKAPI_CALL +nvk_CmdCopyImageToBuffer2( + VkCommandBuffer commandBuffer, + const VkCopyImageToBufferInfo2 *pCopyImageToBufferInfo) +{ + VK_FROM_HANDLE(nvk_cmd_buffer, cmd, commandBuffer); + VK_FROM_HANDLE(nvk_image, src, pCopyImageToBufferInfo->srcImage); + VK_FROM_HANDLE(nvk_buffer, dst, pCopyImageToBufferInfo->dstBuffer); + + for (unsigned r = 0; r < pCopyImageToBufferInfo->regionCount; r++) { + const VkBufferImageCopy2 *region = &pCopyImageToBufferInfo->pRegions[r]; + struct vk_image_buffer_layout buffer_layout = vk_image_buffer_copy_layout(&src->vk, region); + + struct nouveau_copy copy = { + .src = nouveau_copy_rect_image(src, region->imageOffset, ®ion->imageSubresource), + .dst = nouveau_copy_rect_buffer(dst, region->bufferOffset, buffer_layout), + .bpp = buffer_layout.element_size_B, + .extent = vk_image_sanitize_extent(&src->vk, region->imageExtent), + }; + copy.extent.depth *= region->imageSubresource.layerCount; + + nouveau_copy_rect(cmd, ©); + + vk_foreach_struct_const(ext, region->pNext) { + switch (ext->sType) { + default: + nvk_debug_ignored_stype(ext->sType); + break; + } + } + } + + vk_foreach_struct_const(ext, pCopyImageToBufferInfo->pNext) { + switch (ext->sType) { + default: + nvk_debug_ignored_stype(ext->sType); + break; + } + } +} + +VKAPI_ATTR void VKAPI_CALL +nvk_CmdCopyImage2( + VkCommandBuffer commandBuffer, + const VkCopyImageInfo2 *pCopyImageInfo) +{ + VK_FROM_HANDLE(nvk_cmd_buffer, cmd, commandBuffer); + VK_FROM_HANDLE(nvk_image, src, pCopyImageInfo->srcImage); + VK_FROM_HANDLE(nvk_image, dst, pCopyImageInfo->dstImage); + + uint16_t bpp = vk_format_description(src->vk.format)->block.bits; + assert(bpp == vk_format_description(dst->vk.format)->block.bits); + bpp /= 8; + + for (unsigned r = 0; r < pCopyImageInfo->regionCount; r++) { + const VkImageCopy2 *region = &pCopyImageInfo->pRegions[r]; + + struct nouveau_copy copy = { + .src = nouveau_copy_rect_image(src, region->srcOffset, ®ion->srcSubresource), + .dst = nouveau_copy_rect_image(dst, region->dstOffset, ®ion->dstSubresource), + .bpp = bpp, + .extent = vk_image_sanitize_extent(&src->vk, region->extent), + }; + copy.extent.depth *= region->srcSubresource.layerCount; + + nouveau_copy_rect(cmd, ©); + } +} diff --git a/src/nouveau/vulkan/nvk_image.c b/src/nouveau/vulkan/nvk_image.c index 74df875..7f634d8 100644 --- a/src/nouveau/vulkan/nvk_image.c +++ b/src/nouveau/vulkan/nvk_image.c @@ -1,12 +1,102 @@ #include "nvk_image.h" +#include "vulkan/util/vk_format.h" + #include "nvk_device.h" +#include "nvk_device_memory.h" +#include "nvk_physical_device.h" + +/* calculates optimal tiling for a given CreateInfo + * + * 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) +{ + struct nvk_tile tile = {}; + + switch (pCreateInfo->tiling) { + case VK_IMAGE_TILING_LINEAR: + tile.is_tiled = false; + return tile; + case VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT: + tile.is_fermi = true; + tile.is_tiled = true; + tile.x = 0; + tile.y = modifier & 0xf; + tile.z = 0; + return tile; + case VK_IMAGE_TILING_OPTIMAL: + /* code is below */ + break; + default: + assert(!"unknown image tiling"); + break; + } + + uint32_t height = pCreateInfo->extent.height; + uint32_t depth = pCreateInfo->extent.depth; + + // fermi is the baseline anyway (for now) + tile.is_fermi = true; + tile.is_tiled = true; + + // always 0 for now + tile.x = 0; + + if (height >= 256) tile.y = 5; + else if (height >= 128) tile.y = 4; + else if (height >= 64) tile.y = 3; + else if (height >= 32) tile.y = 2; + else if (height >= 16) tile.y = 1; + else tile.y = 0; + + // not quite sure why, but gallium does the same + if (pCreateInfo->imageType == VK_IMAGE_TYPE_3D) + tile.y = MIN2(tile.y, 2); + + if (depth >= 32) tile.z = 5; + else if (depth >= 16) tile.z = 4; + else if (depth >= 8) tile.z = 3; + else if (depth >= 4) tile.z = 2; + else if (depth >= 2) tile.z = 1; + else tile.z = 0; + + return tile; +} + +static VkExtent3D +nvk_image_tile_to_blocks(struct nvk_tile tile) +{ + if (!tile.is_tiled) { + return (VkExtent3D){1, 1, 1}; + } else { + uint32_t height = tile.is_fermi ? 8 : 4; + + return (VkExtent3D){ + .width = 64 << tile.x, + .height = height << tile.y, + .depth = 1 << tile.z, + }; + + } +} static VkResult nvk_image_init(struct nvk_device *device, struct nvk_image *image, 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); + + 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; + return VK_SUCCESS; } @@ -59,6 +149,16 @@ VKAPI_ATTR void VKAPI_CALL nvk_GetImageMemoryRequirements2( const VkImageMemoryRequirementsInfo2 *pInfo, VkMemoryRequirements2 *pMemoryRequirements) { + VK_FROM_HANDLE(nvk_device, device, _device); + VK_FROM_HANDLE(nvk_image, image, pInfo->image); + + uint32_t memory_types = (1 << device->pdev->mem_type_cnt) - 1; + + // TODO hope for the best? + pMemoryRequirements->memoryRequirements.memoryTypeBits = memory_types; + pMemoryRequirements->memoryRequirements.alignment = 0x1000; + pMemoryRequirements->memoryRequirements.size = image->min_size; + vk_foreach_struct_const(ext, pInfo->pNext) { switch (ext->sType) { default: @@ -67,3 +167,19 @@ VKAPI_ATTR void VKAPI_CALL nvk_GetImageMemoryRequirements2( } } } + +VKAPI_ATTR VkResult VKAPI_CALL +nvk_BindImageMemory2( + VkDevice _device, + uint32_t bindInfoCount, + const VkBindImageMemoryInfo *pBindInfos) +{ + for (uint32_t i = 0; i < bindInfoCount; ++i) { + VK_FROM_HANDLE(nvk_device_memory, mem, pBindInfos[i].memory); + VK_FROM_HANDLE(nvk_image, image, pBindInfos[i].image); + + image->mem = mem; + image->offset = pBindInfos[i].memoryOffset; + } + return VK_SUCCESS; +} diff --git a/src/nouveau/vulkan/nvk_image.h b/src/nouveau/vulkan/nvk_image.h index b015e2a..86f4792 100644 --- a/src/nouveau/vulkan/nvk_image.h +++ b/src/nouveau/vulkan/nvk_image.h @@ -5,8 +5,34 @@ #include "vulkan/runtime/vk_image.h" +/* 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) + * + * tile size on y depends on the is_fermi flag: + * !is_fermi: 4 << y + * is_fermi: 8 << y (required Pascal+) + * + * tile size on z is 1 << z + */ +struct nvk_tile { + uint8_t z:4; + uint8_t y:4; + uint8_t x:4; + bool is_fermi:1; + bool is_tiled:1; +}; + struct nvk_image { struct vk_image vk; + struct nvk_device_memory *mem; + VkDeviceSize offset; + + VkDeviceSize min_size; + + uint32_t row_stride; + uint32_t layer_stride; + struct nvk_tile tile; }; VK_DEFINE_HANDLE_CASTS(nvk_image, vk.base, VkImage, VK_OBJECT_TYPE_IMAGE) diff --git a/src/nouveau/winsys/push906f.h b/src/nouveau/winsys/push906f.h index c9cb156..d9fa93b 100644 --- a/src/nouveau/winsys/push906f.h +++ b/src/nouveau/winsys/push906f.h @@ -17,6 +17,7 @@ // DmaCopy #define PUSH906F_SUBC_NV90B5 4 #define PUSH906F_SUBC_NVA0B5 4 +#define PUSH906F_SUBC_NVC1B5 4 #endif #define PUSH_HDR(p,o,n,f,s,m,c) do { \ -- 2.7.4