diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index bb966228..afad9756 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -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 diff --git a/src/dxvk/dxvk_image.cpp b/src/dxvk/dxvk_image.cpp index 3f9937dc..3227c9da 100644 --- a/src/dxvk/dxvk_image.cpp +++ b/src/dxvk/dxvk_image.cpp @@ -87,25 +87,75 @@ namespace dxvk { const Rc& 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); - } - } \ No newline at end of file diff --git a/src/dxvk/dxvk_image.h b/src/dxvk/dxvk_image.h index 9802d81e..395213bc 100644 --- a/src/dxvk/dxvk_image.h +++ b/src/dxvk/dxvk_image.h @@ -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 m_image; DxvkImageViewCreateInfo m_info; - VkImageView m_view; + VkImageView m_views[ViewCount]; + + void createView(VkImageViewType type, uint32_t numLayers); };