diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index d9ee8a05a..17e5a055a 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -187,7 +187,9 @@ RasterizerVulkan::~RasterizerVulkan() { vmaDestroyImage(allocator, default_texture.image, default_texture.allocation); vmaDestroyImage(allocator, default_storage_texture.image, default_storage_texture.allocation); device.destroyImageView(default_texture.image_view); + device.destroyImageView(default_texture.base_view); device.destroyImageView(default_storage_texture.image_view); + device.destroyImageView(default_storage_texture.base_view); device.destroySampler(default_sampler); } @@ -1635,63 +1637,14 @@ vk::Framebuffer RasterizerVulkan::CreateFramebuffer(const FramebufferInfo& info) } void RasterizerVulkan::CreateDefaultTextures() { - default_texture.format = vk::Format::eR8G8B8A8Unorm; - default_storage_texture.format = vk::Format::eR8G8B8A8Uint; + const vk::ImageUsageFlags usage = GetImageUsage(vk::ImageAspectFlagBits::eColor); + default_texture = runtime.Allocate(1, 1, 1, 1, vk::Format::eR8G8B8A8Unorm, usage, {}); + default_storage_texture = runtime.Allocate(1, 1, 1, 1, vk::Format::eR8G8B8A8Uint, usage, {}); - vk::ImageCreateInfo image_info = {.imageType = vk::ImageType::e2D, - .format = default_texture.format, - .extent = {1, 1, 1}, - .mipLevels = 1, - .arrayLayers = 1, - .samples = vk::SampleCountFlagBits::e1, - .usage = GetImageUsage(vk::ImageAspectFlagBits::eColor)}; - - const VmaAllocationCreateInfo alloc_info = {.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE}; - - VkImage unsafe_image{}; - VkImageCreateInfo& unsafe_image_info = static_cast(image_info); - - VkResult result = vmaCreateImage(instance.GetAllocator(), &unsafe_image_info, &alloc_info, - &unsafe_image, &default_texture.allocation, nullptr); - if (result != VK_SUCCESS) { - LOG_CRITICAL(Render_Vulkan, "Failed allocating default texture with error {}", result); - UNREACHABLE(); - } - - default_texture.image = vk::Image{unsafe_image}; - vk::ImageViewCreateInfo view_info = { - .image = default_texture.image, - .viewType = vk::ImageViewType::e2D, - .format = default_texture.format, - .subresourceRange = {.aspectMask = vk::ImageAspectFlagBits::eColor, - .baseMipLevel = 0, - .levelCount = 1, - .baseArrayLayer = 0, - .layerCount = 1}}; - - vk::Device device = instance.GetDevice(); - default_texture.image_view = device.createImageView(view_info); - - // Define the default texture for storage descriptors - image_info.format = default_storage_texture.format; - result = vmaCreateImage(instance.GetAllocator(), &unsafe_image_info, &alloc_info, &unsafe_image, - &default_storage_texture.allocation, nullptr); - if (result != VK_SUCCESS) { - LOG_CRITICAL(Render_Vulkan, "Failed allocating default storage texture with error {}", - result); - UNREACHABLE(); - } - - default_storage_texture.image = vk::Image{unsafe_image}; - - view_info.format = default_storage_texture.format; - view_info.image = default_storage_texture.image; - default_storage_texture.image_view = device.createImageView(view_info); - - runtime.Transition(scheduler.GetUploadCommandBuffer(), default_texture, - vk::ImageLayout::eShaderReadOnlyOptimal, 0, 1); - runtime.Transition(scheduler.GetUploadCommandBuffer(), default_storage_texture, - vk::ImageLayout::eGeneral, 0, 1); + const vk::CommandBuffer command_buffer = scheduler.GetRenderCommandBuffer(); + runtime.Transition(command_buffer, default_texture, vk::ImageLayout::eShaderReadOnlyOptimal, 0, + 1); + runtime.Transition(command_buffer, default_storage_texture, vk::ImageLayout::eGeneral, 0, 1); } void RasterizerVulkan::FlushBuffers() { diff --git a/src/video_core/renderer_vulkan/vk_texture_runtime.cpp b/src/video_core/renderer_vulkan/vk_texture_runtime.cpp index a4ae8995c..3ea74241e 100644 --- a/src/video_core/renderer_vulkan/vk_texture_runtime.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_runtime.cpp @@ -100,8 +100,9 @@ void TextureRuntime::OnSlotSwitch(u32 new_slot) { ImageAlloc TextureRuntime::Allocate(u32 width, u32 height, VideoCore::PixelFormat format, VideoCore::TextureType type) { - + const u32 levels = std::bit_width(std::max(width, height)); const u32 layers = type == VideoCore::TextureType::CubeMap ? 6 : 1; + const VideoCore::HostTextureTag key = { .format = format, .width = width, .height = height, .layers = layers}; @@ -120,17 +121,25 @@ ImageAlloc TextureRuntime::Allocate(u32 width, u32 height, VideoCore::PixelForma const vk::Format vk_format = is_suitable ? traits.native : traits.fallback; const vk::ImageUsageFlags vk_usage = is_suitable ? traits.usage : GetImageUsage(aspect); - const u32 levels = std::bit_width(std::max(width, height)); - const vk::ImageCreateInfo image_info = {.flags = type == VideoCore::TextureType::CubeMap - ? vk::ImageCreateFlagBits::eCubeCompatible - : vk::ImageCreateFlags{}, + const vk::ImageCreateFlags flags = type == VideoCore::TextureType::CubeMap + ? vk::ImageCreateFlagBits::eCubeCompatible + : vk::ImageCreateFlags{}; + + return Allocate(width, height, layers, levels, vk_format, vk_usage, flags); +} + +ImageAlloc TextureRuntime::Allocate(u32 width, u32 height, u32 layers, u32 levels, + vk::Format format, vk::ImageUsageFlags usage, + vk::ImageCreateFlags flags) { + const vk::ImageAspectFlags aspect = GetImageAspect(format); + const vk::ImageCreateInfo image_info = {.flags = flags, .imageType = vk::ImageType::e2D, - .format = vk_format, + .format = format, .extent = {width, height, 1}, .mipLevels = levels, .arrayLayers = layers, .samples = vk::SampleCountFlagBits::e1, - .usage = vk_usage}; + .usage = usage}; const VmaAllocationCreateInfo alloc_info = {.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE}; @@ -145,12 +154,14 @@ ImageAlloc TextureRuntime::Allocate(u32 width, u32 height, VideoCore::PixelForma UNREACHABLE(); } + const vk::ImageViewType view_type = flags & vk::ImageCreateFlagBits::eCubeCompatible + ? vk::ImageViewType::eCube + : vk::ImageViewType::e2D; + vk::Image image = vk::Image{unsafe_image}; const vk::ImageViewCreateInfo view_info = {.image = image, - .viewType = type == VideoCore::TextureType::CubeMap - ? vk::ImageViewType::eCube - : vk::ImageViewType::e2D, - .format = vk_format, + .viewType = view_type, + .format = format, .subresourceRange = {.aspectMask = aspect, .baseMipLevel = 0, .levelCount = levels, @@ -158,16 +169,14 @@ ImageAlloc TextureRuntime::Allocate(u32 width, u32 height, VideoCore::PixelForma .layerCount = layers}}; // Also create a base mip view in case this is used as an attachment - const vk::ImageViewCreateInfo base_view_info = { - .image = image, - .viewType = type == VideoCore::TextureType::CubeMap ? vk::ImageViewType::eCube - : vk::ImageViewType::e2D, - .format = vk_format, - .subresourceRange = {.aspectMask = aspect, - .baseMipLevel = 0, - .levelCount = 1, - .baseArrayLayer = 0, - .layerCount = layers}}; + const vk::ImageViewCreateInfo base_view_info = {.image = image, + .viewType = view_type, + .format = format, + .subresourceRange = {.aspectMask = aspect, + .baseMipLevel = 0, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = layers}}; vk::Device device = instance.GetDevice(); vk::ImageView image_view = device.createImageView(view_info); @@ -176,12 +185,11 @@ ImageAlloc TextureRuntime::Allocate(u32 width, u32 height, VideoCore::PixelForma // Create seperate depth/stencil views in case this gets reinterpreted with a compute shader vk::ImageView depth_view; vk::ImageView stencil_view; - if (format == VideoCore::PixelFormat::D24S8) { + if (aspect & vk::ImageAspectFlagBits::eStencil) { vk::ImageViewCreateInfo view_info = { .image = image, - .viewType = type == VideoCore::TextureType::CubeMap ? vk::ImageViewType::eCube - : vk::ImageViewType::e2D, - .format = vk_format, + .viewType = view_type, + .format = format, .subresourceRange = {.aspectMask = vk::ImageAspectFlagBits::eDepth, .baseMipLevel = 0, .levelCount = levels, @@ -199,7 +207,7 @@ ImageAlloc TextureRuntime::Allocate(u32 width, u32 height, VideoCore::PixelForma .depth_view = depth_view, .stencil_view = stencil_view, .allocation = allocation, - .format = vk_format, + .format = format, .aspect = aspect, .levels = levels, .layers = layers}; diff --git a/src/video_core/renderer_vulkan/vk_texture_runtime.h b/src/video_core/renderer_vulkan/vk_texture_runtime.h index d8f992d05..2d8691e7d 100644 --- a/src/video_core/renderer_vulkan/vk_texture_runtime.h +++ b/src/video_core/renderer_vulkan/vk_texture_runtime.h @@ -61,6 +61,11 @@ public: [[nodiscard]] ImageAlloc Allocate(u32 width, u32 height, VideoCore::PixelFormat format, VideoCore::TextureType type); + /// Allocates a vulkan image + [[nodiscard]] ImageAlloc Allocate(u32 width, u32 height, u32 layers, u32 levels, + vk::Format format, vk::ImageUsageFlags usage, + vk::ImageCreateFlags flags); + /// Causes a GPU command flush void Finish();