mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-01-19 05:52:11 +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:
parent
61049c33fb
commit
d9772b0ffd
@ -1822,11 +1822,11 @@ namespace dxvk {
|
|||||||
|
|
||||||
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
|
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
|
||||||
case VK_DESCRIPTOR_TYPE_STORAGE_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);
|
updatePipelineState |= bindingState.setBound(i);
|
||||||
|
|
||||||
m_descInfos[i].image.sampler = VK_NULL_HANDLE;
|
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;
|
m_descInfos[i].image.imageLayout = res.imageView->imageInfo().layout;
|
||||||
|
|
||||||
if (depthAttachment.view != nullptr
|
if (depthAttachment.view != nullptr
|
||||||
|
@ -87,25 +87,75 @@ namespace dxvk {
|
|||||||
const Rc<DxvkImage>& image,
|
const Rc<DxvkImage>& image,
|
||||||
const DxvkImageViewCreateInfo& info)
|
const DxvkImageViewCreateInfo& info)
|
||||||
: m_vkd(vkd), m_image(image), m_info(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;
|
VkImageSubresourceRange subresourceRange;
|
||||||
subresourceRange.aspectMask = info.aspect;
|
subresourceRange.aspectMask = m_info.aspect;
|
||||||
subresourceRange.baseMipLevel = info.minLevel;
|
subresourceRange.baseMipLevel = m_info.minLevel;
|
||||||
subresourceRange.levelCount = info.numLevels;
|
subresourceRange.levelCount = m_info.numLevels;
|
||||||
subresourceRange.baseArrayLayer = info.minLayer;
|
subresourceRange.baseArrayLayer = m_info.minLayer;
|
||||||
subresourceRange.layerCount = info.numLayers;
|
subresourceRange.layerCount = numLayers;
|
||||||
|
|
||||||
VkImageViewCreateInfo viewInfo;
|
VkImageViewCreateInfo viewInfo;
|
||||||
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||||
viewInfo.pNext = nullptr;
|
viewInfo.pNext = nullptr;
|
||||||
viewInfo.flags = 0;
|
viewInfo.flags = 0;
|
||||||
viewInfo.image = image->handle();
|
viewInfo.image = m_image->handle();
|
||||||
viewInfo.viewType = info.type;
|
viewInfo.viewType = type;
|
||||||
viewInfo.format = info.format;
|
viewInfo.format = m_info.format;
|
||||||
viewInfo.components = info.swizzle;
|
viewInfo.components = m_info.swizzle;
|
||||||
viewInfo.subresourceRange = subresourceRange;
|
viewInfo.subresourceRange = subresourceRange;
|
||||||
|
|
||||||
if (m_vkd->vkCreateImageView(m_vkd->device(),
|
if (m_vkd->vkCreateImageView(m_vkd->device(),
|
||||||
&viewInfo, nullptr, &m_view) != VK_SUCCESS) {
|
&viewInfo, nullptr, &m_views[type]) != VK_SUCCESS) {
|
||||||
throw DxvkError(str::format(
|
throw DxvkError(str::format(
|
||||||
"DxvkImageView: Failed to create image view:"
|
"DxvkImageView: Failed to create image view:"
|
||||||
"\n View type: ", viewInfo.viewType,
|
"\n View type: ", viewInfo.viewType,
|
||||||
@ -117,23 +167,17 @@ namespace dxvk {
|
|||||||
"\n Array layers: ", viewInfo.subresourceRange.baseArrayLayer, " - ",
|
"\n Array layers: ", viewInfo.subresourceRange.baseArrayLayer, " - ",
|
||||||
viewInfo.subresourceRange.layerCount,
|
viewInfo.subresourceRange.layerCount,
|
||||||
"\n Image properties:",
|
"\n Image properties:",
|
||||||
"\n Type: ", image->info().type,
|
"\n Type: ", m_image->info().type,
|
||||||
"\n Format: ", image->info().format,
|
"\n Format: ", m_image->info().format,
|
||||||
"\n Extent: ", "(", image->info().extent.width,
|
"\n Extent: ", "(", m_image->info().extent.width,
|
||||||
",", image->info().extent.height,
|
",", m_image->info().extent.height,
|
||||||
",", image->info().extent.depth, ")",
|
",", m_image->info().extent.depth, ")",
|
||||||
"\n Mip levels: ", image->info().mipLevels,
|
"\n Mip levels: ", m_image->info().mipLevels,
|
||||||
"\n Array layers: ", image->info().numLayers,
|
"\n Array layers: ", m_image->info().numLayers,
|
||||||
"\n Samples: ", image->info().sampleCount,
|
"\n Samples: ", m_image->info().sampleCount,
|
||||||
"\n Usage: ", std::hex, image->info().usage,
|
"\n Usage: ", std::hex, m_image->info().usage,
|
||||||
"\n Tiling: ", image->info().tiling));
|
"\n Tiling: ", m_image->info().tiling));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DxvkImageView::~DxvkImageView() {
|
|
||||||
m_vkd->vkDestroyImageView(
|
|
||||||
m_vkd->device(), m_view, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@ -232,7 +232,7 @@ namespace dxvk {
|
|||||||
* \brief DXVK image view
|
* \brief DXVK image view
|
||||||
*/
|
*/
|
||||||
class DxvkImageView : public DxvkResource {
|
class DxvkImageView : public DxvkResource {
|
||||||
|
constexpr static uint32_t ViewCount = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY + 1;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DxvkImageView(
|
DxvkImageView(
|
||||||
@ -243,21 +243,34 @@ namespace dxvk {
|
|||||||
~DxvkImageView();
|
~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
|
* \returns Image view handle
|
||||||
*/
|
*/
|
||||||
VkImageView handle() const {
|
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
|
* \brief Image view type
|
||||||
*
|
*
|
||||||
* Convenience method to query the
|
* Convenience method to query the view type
|
||||||
* view type in order to check for
|
* in order to check for resource compatibility.
|
||||||
* resource compatibility.
|
|
||||||
* \returns Image view type
|
* \returns Image view type
|
||||||
*/
|
*/
|
||||||
VkImageViewType type() const {
|
VkImageViewType type() const {
|
||||||
@ -336,7 +349,9 @@ namespace dxvk {
|
|||||||
Rc<DxvkImage> m_image;
|
Rc<DxvkImage> m_image;
|
||||||
|
|
||||||
DxvkImageViewCreateInfo m_info;
|
DxvkImageViewCreateInfo m_info;
|
||||||
VkImageView m_view;
|
VkImageView m_views[ViewCount];
|
||||||
|
|
||||||
|
void createView(VkImageViewType type, uint32_t numLayers);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user