From 1409b9c565afdf25db19750d548338aede622502 Mon Sep 17 00:00:00 2001 From: gibbed Date: Tue, 5 Jun 2018 07:51:51 -0500 Subject: [PATCH] [GPU/Vulkan] Add support for 2D image stacks. --- src/xenia/gpu/texture_info.cc | 15 +++++++++++-- src/xenia/gpu/texture_info.h | 1 + src/xenia/gpu/vulkan/texture_cache.cc | 32 ++++++++++++++++++--------- 3 files changed, 36 insertions(+), 12 deletions(-) diff --git a/src/xenia/gpu/texture_info.cc b/src/xenia/gpu/texture_info.cc index 24001dfc1..81efe57c1 100644 --- a/src/xenia/gpu/texture_info.cc +++ b/src/xenia/gpu/texture_info.cc @@ -38,24 +38,35 @@ bool TextureInfo::Prepare(const xe_gpu_texture_fetch_t& fetch, info.dimension = static_cast(fetch.dimension); info.width = info.height = info.depth = 0; + info.is_stacked = false; switch (info.dimension) { case Dimension::k1D: info.dimension = Dimension::k2D; // we treat 1D textures as 2D info.width = fetch.size_1d.width; + assert_true(!fetch.stacked); break; case Dimension::k2D: - info.width = fetch.size_2d.width; - info.height = fetch.size_2d.height; + if (!fetch.stacked) { + info.width = fetch.size_2d.width; + info.height = fetch.size_2d.height; + } else { + info.width = fetch.size_stack.width; + info.height = fetch.size_stack.height; + info.depth = fetch.size_stack.depth; + info.is_stacked = true; + } break; case Dimension::k3D: info.width = fetch.size_3d.width; info.height = fetch.size_3d.height; info.depth = fetch.size_3d.depth; + assert_true(!fetch.stacked); break; case Dimension::kCube: info.width = fetch.size_stack.width; info.height = fetch.size_stack.height; info.depth = fetch.size_stack.depth; + assert_true(!fetch.stacked); break; default: assert_unhandled_case(info.dimension); diff --git a/src/xenia/gpu/texture_info.h b/src/xenia/gpu/texture_info.h index 0fd1205d0..df81fb33a 100644 --- a/src/xenia/gpu/texture_info.h +++ b/src/xenia/gpu/texture_info.h @@ -329,6 +329,7 @@ struct TextureInfo { uint32_t pitch; // pitch in blocks uint32_t mip_min_level; uint32_t mip_max_level; + bool is_stacked; bool is_tiled; bool has_packed_mips; diff --git a/src/xenia/gpu/vulkan/texture_cache.cc b/src/xenia/gpu/vulkan/texture_cache.cc index 0afd4e911..6ca1560ac 100644 --- a/src/xenia/gpu/vulkan/texture_cache.cc +++ b/src/xenia/gpu/vulkan/texture_cache.cc @@ -191,7 +191,12 @@ TextureCache::Texture* TextureCache::AllocateTexture( switch (texture_info.dimension) { case Dimension::k1D: case Dimension::k2D: - image_info.imageType = VK_IMAGE_TYPE_2D; + if (!texture_info.is_stacked) { + image_info.imageType = VK_IMAGE_TYPE_2D; + } else { + image_info.imageType = VK_IMAGE_TYPE_3D; + image_info.flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT; + } break; case Dimension::k3D: image_info.imageType = VK_IMAGE_TYPE_3D; @@ -249,9 +254,9 @@ TextureCache::Texture* TextureCache::AllocateTexture( image_info.format = format; image_info.extent.width = texture_info.width + 1; image_info.extent.height = texture_info.height + 1; - image_info.extent.depth = !is_cube ? texture_info.depth + 1 : 1; + image_info.extent.depth = !is_cube ? 1 + texture_info.depth : 1; image_info.mipLevels = texture_info.mip_min_level + texture_info.mip_levels(); - image_info.arrayLayers = !is_cube ? 1 : 6; + image_info.arrayLayers = !is_cube ? 1 : 1 + texture_info.depth; image_info.samples = VK_SAMPLE_COUNT_1_BIT; image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; image_info.queueFamilyIndexCount = 0; @@ -263,6 +268,7 @@ TextureCache::Texture* TextureCache::AllocateTexture( assert_true(image_props.maxExtent.height >= image_info.extent.height); assert_true(image_props.maxExtent.depth >= image_info.extent.depth); assert_true(image_props.maxMipLevels >= image_info.mipLevels); + assert_true(image_props.maxArrayLayers >= image_info.arrayLayers); VmaAllocation alloc; VmaAllocationCreateInfo vma_create_info = { @@ -519,7 +525,11 @@ TextureCache::TextureView* TextureCache::DemandView(Texture* texture, switch (texture->texture_info.dimension) { case Dimension::k1D: case Dimension::k2D: - view_info.viewType = VK_IMAGE_VIEW_TYPE_2D; + if (!texture->texture_info.is_stacked) { + view_info.viewType = VK_IMAGE_VIEW_TYPE_2D; + } else { + view_info.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY; + } break; case Dimension::k3D: view_info.viewType = VK_IMAGE_VIEW_TYPE_3D; @@ -569,7 +579,8 @@ TextureCache::TextureView* TextureCache::DemandView(Texture* texture, view_info.subresourceRange.baseMipLevel = texture->texture_info.mip_min_level; view_info.subresourceRange.levelCount = texture->texture_info.mip_levels(); view_info.subresourceRange.baseArrayLayer = 0; - view_info.subresourceRange.layerCount = !is_cube ? 1 : 6; + view_info.subresourceRange.layerCount = + !is_cube ? 1 : 1 + texture->texture_info.depth; VkImageView view; auto status = vkCreateImageView(*device_, &view_info, nullptr, &view); @@ -924,7 +935,7 @@ bool TextureCache::ConvertTexture(uint8_t* dest, VkBufferImageCopy* copy_region, copy_region->imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; copy_region->imageSubresource.mipLevel = mip; copy_region->imageSubresource.baseArrayLayer = 0; - copy_region->imageSubresource.layerCount = !is_cube ? 1 : 6; + copy_region->imageSubresource.layerCount = !is_cube ? 1 : dst_extent.depth; copy_region->imageExtent.width = std::max(1u, (src.width + 1) >> mip); copy_region->imageExtent.height = std::max(1u, (src.height + 1) >> mip); copy_region->imageExtent.depth = !is_cube ? dst_extent.depth : 1; @@ -942,13 +953,14 @@ bool TextureCache::UploadTexture(VkCommandBuffer command_buffer, XELOGGPU( "Uploading texture @ 0x%.8X/0x%.8X (%ux%ux%u, format: %s, dim: %s, " - "levels: %u (%u-%u), pitch: %u, tiled: %s, packed mips: %s, unpack " - "length: 0x%.8X)", + "levels: %u (%u-%u), stacked: %s, pitch: %u, tiled: %s, packed mips: %s, " + "unpack length: 0x%.8X)", src.memory.base_address, src.memory.mip_address, src.width + 1, src.height + 1, src.depth + 1, src.format_info()->name, get_dimension_name(src.dimension), src.mip_levels(), src.mip_min_level, - src.mip_max_level, src.pitch, src.is_tiled ? "yes" : "no", - src.has_packed_mips ? "yes" : "no", unpack_length); + src.mip_max_level, src.is_stacked ? "yes" : "no", src.pitch, + src.is_tiled ? "yes" : "no", src.has_packed_mips ? "yes" : "no", + unpack_length); XELOGGPU("Extent: %ux%ux%u %u,%u,%u", src.extent.pitch, src.extent.height, src.extent.depth, src.extent.block_pitch_h, src.extent.block_height,