renderer_vulkan: Allow direct allocation of images

This commit is contained in:
emufan4568
2022-10-14 14:17:10 +03:00
committed by GPUCode
parent 96d5bb553b
commit 2601a1df6c
3 changed files with 48 additions and 82 deletions

View File

@@ -187,7 +187,9 @@ RasterizerVulkan::~RasterizerVulkan() {
vmaDestroyImage(allocator, default_texture.image, default_texture.allocation); vmaDestroyImage(allocator, default_texture.image, default_texture.allocation);
vmaDestroyImage(allocator, default_storage_texture.image, default_storage_texture.allocation); vmaDestroyImage(allocator, default_storage_texture.image, default_storage_texture.allocation);
device.destroyImageView(default_texture.image_view); device.destroyImageView(default_texture.image_view);
device.destroyImageView(default_texture.base_view);
device.destroyImageView(default_storage_texture.image_view); device.destroyImageView(default_storage_texture.image_view);
device.destroyImageView(default_storage_texture.base_view);
device.destroySampler(default_sampler); device.destroySampler(default_sampler);
} }
@@ -1635,63 +1637,14 @@ vk::Framebuffer RasterizerVulkan::CreateFramebuffer(const FramebufferInfo& info)
} }
void RasterizerVulkan::CreateDefaultTextures() { void RasterizerVulkan::CreateDefaultTextures() {
default_texture.format = vk::Format::eR8G8B8A8Unorm; const vk::ImageUsageFlags usage = GetImageUsage(vk::ImageAspectFlagBits::eColor);
default_storage_texture.format = vk::Format::eR8G8B8A8Uint; 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, const vk::CommandBuffer command_buffer = scheduler.GetRenderCommandBuffer();
.format = default_texture.format, runtime.Transition(command_buffer, default_texture, vk::ImageLayout::eShaderReadOnlyOptimal, 0,
.extent = {1, 1, 1}, 1);
.mipLevels = 1, runtime.Transition(command_buffer, default_storage_texture, vk::ImageLayout::eGeneral, 0, 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<VkImageCreateInfo&>(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);
} }
void RasterizerVulkan::FlushBuffers() { void RasterizerVulkan::FlushBuffers() {

View File

@@ -100,8 +100,9 @@ void TextureRuntime::OnSlotSwitch(u32 new_slot) {
ImageAlloc TextureRuntime::Allocate(u32 width, u32 height, VideoCore::PixelFormat format, ImageAlloc TextureRuntime::Allocate(u32 width, u32 height, VideoCore::PixelFormat format,
VideoCore::TextureType type) { VideoCore::TextureType type) {
const u32 levels = std::bit_width(std::max(width, height));
const u32 layers = type == VideoCore::TextureType::CubeMap ? 6 : 1; const u32 layers = type == VideoCore::TextureType::CubeMap ? 6 : 1;
const VideoCore::HostTextureTag key = { const VideoCore::HostTextureTag key = {
.format = format, .width = width, .height = height, .layers = layers}; .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::Format vk_format = is_suitable ? traits.native : traits.fallback;
const vk::ImageUsageFlags vk_usage = is_suitable ? traits.usage : GetImageUsage(aspect); const vk::ImageUsageFlags vk_usage = is_suitable ? traits.usage : GetImageUsage(aspect);
const u32 levels = std::bit_width(std::max(width, height)); const vk::ImageCreateFlags flags = type == VideoCore::TextureType::CubeMap
const vk::ImageCreateInfo image_info = {.flags = type == VideoCore::TextureType::CubeMap ? vk::ImageCreateFlagBits::eCubeCompatible
? vk::ImageCreateFlagBits::eCubeCompatible : vk::ImageCreateFlags{};
: 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, .imageType = vk::ImageType::e2D,
.format = vk_format, .format = format,
.extent = {width, height, 1}, .extent = {width, height, 1},
.mipLevels = levels, .mipLevels = levels,
.arrayLayers = layers, .arrayLayers = layers,
.samples = vk::SampleCountFlagBits::e1, .samples = vk::SampleCountFlagBits::e1,
.usage = vk_usage}; .usage = usage};
const VmaAllocationCreateInfo alloc_info = {.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE}; 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(); UNREACHABLE();
} }
const vk::ImageViewType view_type = flags & vk::ImageCreateFlagBits::eCubeCompatible
? vk::ImageViewType::eCube
: vk::ImageViewType::e2D;
vk::Image image = vk::Image{unsafe_image}; vk::Image image = vk::Image{unsafe_image};
const vk::ImageViewCreateInfo view_info = {.image = image, const vk::ImageViewCreateInfo view_info = {.image = image,
.viewType = type == VideoCore::TextureType::CubeMap .viewType = view_type,
? vk::ImageViewType::eCube .format = format,
: vk::ImageViewType::e2D,
.format = vk_format,
.subresourceRange = {.aspectMask = aspect, .subresourceRange = {.aspectMask = aspect,
.baseMipLevel = 0, .baseMipLevel = 0,
.levelCount = levels, .levelCount = levels,
@@ -158,16 +169,14 @@ ImageAlloc TextureRuntime::Allocate(u32 width, u32 height, VideoCore::PixelForma
.layerCount = layers}}; .layerCount = layers}};
// Also create a base mip view in case this is used as an attachment // Also create a base mip view in case this is used as an attachment
const vk::ImageViewCreateInfo base_view_info = { const vk::ImageViewCreateInfo base_view_info = {.image = image,
.image = image, .viewType = view_type,
.viewType = type == VideoCore::TextureType::CubeMap ? vk::ImageViewType::eCube .format = format,
: vk::ImageViewType::e2D, .subresourceRange = {.aspectMask = aspect,
.format = vk_format, .baseMipLevel = 0,
.subresourceRange = {.aspectMask = aspect, .levelCount = 1,
.baseMipLevel = 0, .baseArrayLayer = 0,
.levelCount = 1, .layerCount = layers}};
.baseArrayLayer = 0,
.layerCount = layers}};
vk::Device device = instance.GetDevice(); vk::Device device = instance.GetDevice();
vk::ImageView image_view = device.createImageView(view_info); 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 // Create seperate depth/stencil views in case this gets reinterpreted with a compute shader
vk::ImageView depth_view; vk::ImageView depth_view;
vk::ImageView stencil_view; vk::ImageView stencil_view;
if (format == VideoCore::PixelFormat::D24S8) { if (aspect & vk::ImageAspectFlagBits::eStencil) {
vk::ImageViewCreateInfo view_info = { vk::ImageViewCreateInfo view_info = {
.image = image, .image = image,
.viewType = type == VideoCore::TextureType::CubeMap ? vk::ImageViewType::eCube .viewType = view_type,
: vk::ImageViewType::e2D, .format = format,
.format = vk_format,
.subresourceRange = {.aspectMask = vk::ImageAspectFlagBits::eDepth, .subresourceRange = {.aspectMask = vk::ImageAspectFlagBits::eDepth,
.baseMipLevel = 0, .baseMipLevel = 0,
.levelCount = levels, .levelCount = levels,
@@ -199,7 +207,7 @@ ImageAlloc TextureRuntime::Allocate(u32 width, u32 height, VideoCore::PixelForma
.depth_view = depth_view, .depth_view = depth_view,
.stencil_view = stencil_view, .stencil_view = stencil_view,
.allocation = allocation, .allocation = allocation,
.format = vk_format, .format = format,
.aspect = aspect, .aspect = aspect,
.levels = levels, .levels = levels,
.layers = layers}; .layers = layers};

View File

@@ -61,6 +61,11 @@ public:
[[nodiscard]] ImageAlloc Allocate(u32 width, u32 height, VideoCore::PixelFormat format, [[nodiscard]] ImageAlloc Allocate(u32 width, u32 height, VideoCore::PixelFormat format,
VideoCore::TextureType type); 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 /// Causes a GPU command flush
void Finish(); void Finish();