1
0
mirror of https://github.com/EduApps-CDG/OpenDX synced 2024-12-30 09:45:37 +01:00
OpenDX/src/dxvk/dxvk_image.cpp
Philip Rebohle d9772b0ffd
[dxvk] Create image views for all supported view types
Rather than creating just one image view per DxvkImageView, we create
views for all compatible types in an attempt to work around game bugs
in Diablo 3, Far Cry 5, Nier Automata, Dishonored 2, Trackmania etc.,
which bind incompatible resource views to some resource slots.
2018-05-24 11:44:04 +02:00

183 lines
7.1 KiB
C++

#include "dxvk_image.h"
namespace dxvk {
DxvkImage::DxvkImage(
const Rc<vk::DeviceFn>& vkd,
const DxvkImageCreateInfo& createInfo,
DxvkMemoryAllocator& memAlloc,
VkMemoryPropertyFlags memFlags)
: m_vkd(vkd), m_info(createInfo), m_memFlags(memFlags) {
VkImageCreateInfo info;
info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
info.pNext = nullptr;
info.flags = createInfo.flags;
info.imageType = createInfo.type;
info.format = createInfo.format;
info.extent = createInfo.extent;
info.mipLevels = createInfo.mipLevels;
info.arrayLayers = createInfo.numLayers;
info.samples = createInfo.sampleCount;
info.tiling = createInfo.tiling;
info.usage = createInfo.usage;
info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
info.queueFamilyIndexCount = 0;
info.pQueueFamilyIndices = nullptr;
info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
if (m_vkd->vkCreateImage(m_vkd->device(),
&info, nullptr, &m_image) != VK_SUCCESS) {
throw DxvkError(str::format(
"DxvkImage: Failed to create image:",
"\n Type: ", info.imageType,
"\n Format: ", info.format,
"\n Extent: ", "(", info.extent.width,
",", info.extent.height,
",", info.extent.depth, ")",
"\n Mip levels: ", info.mipLevels,
"\n Array layers: ", info.arrayLayers,
"\n Samples: ", info.samples,
"\n Usage: ", info.usage,
"\n Tiling: ", info.tiling));
}
// Get memory requirements for the image. We may enforce strict
// alignment on non-linear images in order not to violate the
// bufferImageGranularity limit, which may be greater than the
// required resource memory alignment on some GPUs.
VkMemoryRequirements memReq;
m_vkd->vkGetImageMemoryRequirements(
m_vkd->device(), m_image, &memReq);
if (info.tiling != VK_IMAGE_TILING_LINEAR) {
memReq.size = align(memReq.size, memAlloc.bufferImageGranularity());
memReq.alignment = align(memReq.alignment , memAlloc.bufferImageGranularity());
}
m_memory = memAlloc.alloc(memReq, memFlags);
// Try to bind the allocated memory slice to the image
if (m_vkd->vkBindImageMemory(m_vkd->device(),
m_image, m_memory.memory(), m_memory.offset()) != VK_SUCCESS)
throw DxvkError("DxvkImage::DxvkImage: Failed to bind device memory");
}
DxvkImage::DxvkImage(
const Rc<vk::DeviceFn>& vkd,
const DxvkImageCreateInfo& info,
VkImage image)
: m_vkd(vkd), m_info(info), m_image(image) {
}
DxvkImage::~DxvkImage() {
// This is a bit of a hack to determine whether
// the image is implementation-handled or not
if (m_memory.memory() != VK_NULL_HANDLE)
m_vkd->vkDestroyImage(m_vkd->device(), m_image, nullptr);
}
DxvkImageView::DxvkImageView(
const Rc<vk::DeviceFn>& vkd,
const Rc<DxvkImage>& image,
const DxvkImageViewCreateInfo& info)
: m_vkd(vkd), m_image(image), m_info(info) {
// Since applications tend to bind views
for (uint32_t i = 0; i < ViewCount; i++)
m_views[i] = VK_NULL_HANDLE;
switch (info.type) {
case VK_IMAGE_VIEW_TYPE_1D:
case VK_IMAGE_VIEW_TYPE_1D_ARRAY: {
this->createView(VK_IMAGE_VIEW_TYPE_1D, 1);
this->createView(VK_IMAGE_VIEW_TYPE_1D_ARRAY, info.numLayers);
} break;
case VK_IMAGE_VIEW_TYPE_2D:
case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
case VK_IMAGE_VIEW_TYPE_CUBE:
case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: {
this->createView(VK_IMAGE_VIEW_TYPE_2D, 1);
this->createView(VK_IMAGE_VIEW_TYPE_2D_ARRAY, info.numLayers);
if (m_image->info().flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) {
uint32_t cubeCount = info.numLayers / 6;
if (cubeCount > 0) {
this->createView(VK_IMAGE_VIEW_TYPE_CUBE, 6);
this->createView(VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, 6 * cubeCount);
}
}
} break;
case VK_IMAGE_VIEW_TYPE_3D: {
this->createView(VK_IMAGE_VIEW_TYPE_3D, 1);
if (m_image->info().flags & VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR) {
this->createView(VK_IMAGE_VIEW_TYPE_2D, 1);
this->createView(VK_IMAGE_VIEW_TYPE_2D_ARRAY, m_image->info().extent.depth);
}
} break;
default:
throw DxvkError(str::format("DxvkImageView: Invalid view type: ", info.type));
}
}
DxvkImageView::~DxvkImageView() {
for (uint32_t i = 0; i < ViewCount; i++)
m_vkd->vkDestroyImageView(m_vkd->device(), m_views[i], nullptr);
}
void DxvkImageView::createView(VkImageViewType type, uint32_t numLayers) {
VkImageSubresourceRange subresourceRange;
subresourceRange.aspectMask = m_info.aspect;
subresourceRange.baseMipLevel = m_info.minLevel;
subresourceRange.levelCount = m_info.numLevels;
subresourceRange.baseArrayLayer = m_info.minLayer;
subresourceRange.layerCount = numLayers;
VkImageViewCreateInfo viewInfo;
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
viewInfo.pNext = nullptr;
viewInfo.flags = 0;
viewInfo.image = m_image->handle();
viewInfo.viewType = type;
viewInfo.format = m_info.format;
viewInfo.components = m_info.swizzle;
viewInfo.subresourceRange = subresourceRange;
if (m_vkd->vkCreateImageView(m_vkd->device(),
&viewInfo, nullptr, &m_views[type]) != VK_SUCCESS) {
throw DxvkError(str::format(
"DxvkImageView: Failed to create image view:"
"\n View type: ", viewInfo.viewType,
"\n View format: ", viewInfo.format,
"\n Subresources: ",
"\n Aspect mask: ", std::hex, viewInfo.subresourceRange.aspectMask,
"\n Mip levels: ", viewInfo.subresourceRange.baseMipLevel, " - ",
viewInfo.subresourceRange.levelCount,
"\n Array layers: ", viewInfo.subresourceRange.baseArrayLayer, " - ",
viewInfo.subresourceRange.layerCount,
"\n Image properties:",
"\n Type: ", m_image->info().type,
"\n Format: ", m_image->info().format,
"\n Extent: ", "(", m_image->info().extent.width,
",", m_image->info().extent.height,
",", m_image->info().extent.depth, ")",
"\n Mip levels: ", m_image->info().mipLevels,
"\n Array layers: ", m_image->info().numLayers,
"\n Samples: ", m_image->info().sampleCount,
"\n Usage: ", std::hex, m_image->info().usage,
"\n Tiling: ", m_image->info().tiling));
}
}
}