1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-01-18 20:52:10 +01:00

[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.
This commit is contained in:
Philip Rebohle 2018-05-24 11:44:04 +02:00
parent 61049c33fb
commit d9772b0ffd
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
3 changed files with 95 additions and 36 deletions

View File

@ -1822,11 +1822,11 @@ namespace dxvk {
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
if (res.imageView != nullptr && res.imageView->type() == binding.view) {
if (res.imageView != nullptr && res.imageView->handle(binding.view) != VK_NULL_HANDLE) {
updatePipelineState |= bindingState.setBound(i);
m_descInfos[i].image.sampler = VK_NULL_HANDLE;
m_descInfos[i].image.imageView = res.imageView->handle();
m_descInfos[i].image.imageView = res.imageView->handle(binding.view);
m_descInfos[i].image.imageLayout = res.imageView->imageInfo().layout;
if (depthAttachment.view != nullptr

View File

@ -87,25 +87,75 @@ namespace dxvk {
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 = info.aspect;
subresourceRange.baseMipLevel = info.minLevel;
subresourceRange.levelCount = info.numLevels;
subresourceRange.baseArrayLayer = info.minLayer;
subresourceRange.layerCount = info.numLayers;
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 = image->handle();
viewInfo.viewType = info.type;
viewInfo.format = info.format;
viewInfo.components = info.swizzle;
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_view) != VK_SUCCESS) {
&viewInfo, nullptr, &m_views[type]) != VK_SUCCESS) {
throw DxvkError(str::format(
"DxvkImageView: Failed to create image view:"
"\n View type: ", viewInfo.viewType,
@ -117,23 +167,17 @@ namespace dxvk {
"\n Array layers: ", viewInfo.subresourceRange.baseArrayLayer, " - ",
viewInfo.subresourceRange.layerCount,
"\n Image properties:",
"\n Type: ", image->info().type,
"\n Format: ", image->info().format,
"\n Extent: ", "(", image->info().extent.width,
",", image->info().extent.height,
",", image->info().extent.depth, ")",
"\n Mip levels: ", image->info().mipLevels,
"\n Array layers: ", image->info().numLayers,
"\n Samples: ", image->info().sampleCount,
"\n Usage: ", std::hex, image->info().usage,
"\n Tiling: ", image->info().tiling));
"\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));
}
}
DxvkImageView::~DxvkImageView() {
m_vkd->vkDestroyImageView(
m_vkd->device(), m_view, nullptr);
}
}

View File

@ -232,7 +232,7 @@ namespace dxvk {
* \brief DXVK image view
*/
class DxvkImageView : public DxvkResource {
constexpr static uint32_t ViewCount = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY + 1;
public:
DxvkImageView(
@ -243,21 +243,34 @@ namespace dxvk {
~DxvkImageView();
/**
* \brief Image view handle
* \brief Image view handle for the default type
*
* Internal use only.
* The default view type is guaranteed to be
* supported by the image view, and should be
* preferred over picking a different type.
* \returns Image view handle
*/
VkImageView handle() const {
return m_view;
return handle(m_info.type);
}
/**
* \brief Image view handle for a given view type
*
* If the view does not support the requested image
* view type, \c VK_NULL_HANDLE will be returned.
* \param [in] viewType The requested view type
* \returns The image view handle
*/
VkImageView handle(VkImageViewType viewType) const {
return m_views[viewType];
}
/**
* \brief Image view type
*
* Convenience method to query the
* view type in order to check for
* resource compatibility.
* Convenience method to query the view type
* in order to check for resource compatibility.
* \returns Image view type
*/
VkImageViewType type() const {
@ -336,7 +349,9 @@ namespace dxvk {
Rc<DxvkImage> m_image;
DxvkImageViewCreateInfo m_info;
VkImageView m_view;
VkImageView m_views[ViewCount];
void createView(VkImageViewType type, uint32_t numLayers);
};