diff --git a/src/d3d11/d3d11_device.cpp b/src/d3d11/d3d11_device.cpp index f58cc02c..b576143e 100644 --- a/src/d3d11/d3d11_device.cpp +++ b/src/d3d11/d3d11_device.cpp @@ -413,9 +413,6 @@ namespace dxvk { viewInfo.numLevels = desc.Texture2D.MipLevels; viewInfo.minLayer = 0; viewInfo.numLayers = 1; - - if (m_dxbcOptions.test(DxbcOption::ForceTex2DArray)) - viewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY; break; case D3D11_SRV_DIMENSION_TEXTURE2DARRAY: @@ -432,9 +429,6 @@ namespace dxvk { viewInfo.numLevels = 1; viewInfo.minLayer = 0; viewInfo.numLayers = 1; - - if (m_dxbcOptions.test(DxbcOption::ForceTex2DArray)) - viewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY; break; case D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY: @@ -624,9 +618,6 @@ namespace dxvk { viewInfo.numLevels = 1; viewInfo.minLayer = 0; viewInfo.numLayers = 1; - - if (m_dxbcOptions.test(DxbcOption::ForceTex2DArray)) - viewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY; break; case D3D11_UAV_DIMENSION_TEXTURE2DARRAY: diff --git a/src/dxbc/dxbc_compiler.cpp b/src/dxbc/dxbc_compiler.cpp index 73c7bba1..8d918b24 100644 --- a/src/dxbc/dxbc_compiler.cpp +++ b/src/dxbc/dxbc_compiler.cpp @@ -828,7 +828,6 @@ namespace dxvk { case DxbcResourceDim::Buffer: m_module.enableCapability(spv::CapabilityImageBuffer); break; case DxbcResourceDim::Texture1D: m_module.enableCapability(spv::CapabilityImage1D); break; case DxbcResourceDim::Texture1DArr: m_module.enableCapability(spv::CapabilityImage1D); break; - case DxbcResourceDim::TextureCube: m_module.enableCapability(spv::CapabilityImageCubeArray); break; case DxbcResourceDim::TextureCubeArr: m_module.enableCapability(spv::CapabilityImageCubeArray); break; case DxbcResourceDim::Texture2DMs: m_module.enableCapability(spv::CapabilityImageMSArray); break; case DxbcResourceDim::Texture2DMsArr: m_module.enableCapability(spv::CapabilityImageMSArray); break; @@ -964,7 +963,7 @@ namespace dxvk { const DxbcScalarType sampledType = DxbcScalarType::Uint32; const uint32_t sampledTypeId = getScalarTypeId(sampledType); - const DxbcImageInfo typeInfo = { spv::DimBuffer, 0, 0, isUav ? 2u : 1u, 0u, VK_IMAGE_VIEW_TYPE_MAX_ENUM }; + const DxbcImageInfo typeInfo = { spv::DimBuffer, 0, 0, isUav ? 2u : 1u, VK_IMAGE_VIEW_TYPE_MAX_ENUM }; // Declare the resource type const uint32_t resTypeId = m_module.defImageType(sampledTypeId, @@ -4590,15 +4589,6 @@ namespace dxvk { m_module.opLoad(info.typeId, info.varId)); } - if (info.image.array && !info.image.layered) { - const uint32_t index = result.type.ccount - 1; - const uint32_t zero = m_module.constu32(0); - - result.id = m_module.opCompositeInsert( - getVectorTypeId(result.type), - zero, result.id, 1, &index); - } - return result; } @@ -4643,22 +4633,6 @@ namespace dxvk { coordVector, DxbcRegMask::firstN(dim)); } - if (imageInfo.array && !imageInfo.layered) { - const uint32_t index = dim - 1; - const uint32_t zero = [&] { - switch (coordVector.type.ctype) { - case DxbcScalarType::Sint32: return m_module.consti32(0); - case DxbcScalarType::Uint32: return m_module.constu32(0); - case DxbcScalarType::Float32: return m_module.constf32(0.0f); - default: throw DxvkError("Dxbc: Invalid tex coord type"); - } - }(); - - coordVector.id = m_module.opCompositeInsert( - getVectorTypeId(coordVector.type), - zero, coordVector.id, 1, &index); - } - return coordVector; } @@ -6276,25 +6250,20 @@ namespace dxvk { bool isUav) const { DxbcImageInfo typeInfo = [resourceType, isUav] () -> DxbcImageInfo { switch (resourceType) { - case DxbcResourceDim::Buffer: return { spv::DimBuffer, 0, 0, isUav ? 2u : 1u, 0u, VK_IMAGE_VIEW_TYPE_MAX_ENUM }; - case DxbcResourceDim::Texture1D: return { spv::Dim1D, 0, 0, isUav ? 2u : 1u, 0u, VK_IMAGE_VIEW_TYPE_1D }; - case DxbcResourceDim::Texture1DArr: return { spv::Dim1D, 1, 0, isUav ? 2u : 1u, 1u, VK_IMAGE_VIEW_TYPE_1D_ARRAY }; - case DxbcResourceDim::Texture2D: return { spv::Dim2D, 0, 0, isUav ? 2u : 1u, 0u, VK_IMAGE_VIEW_TYPE_2D }; - case DxbcResourceDim::Texture2DArr: return { spv::Dim2D, 1, 0, isUav ? 2u : 1u, 1u, VK_IMAGE_VIEW_TYPE_2D_ARRAY }; - case DxbcResourceDim::Texture2DMs: return { spv::Dim2D, 0, 1, isUav ? 2u : 1u, 0u, VK_IMAGE_VIEW_TYPE_2D }; - case DxbcResourceDim::Texture2DMsArr: return { spv::Dim2D, 1, 1, isUav ? 2u : 1u, 1u, VK_IMAGE_VIEW_TYPE_2D_ARRAY }; - case DxbcResourceDim::Texture3D: return { spv::Dim3D, 0, 0, isUav ? 2u : 1u, 0u, VK_IMAGE_VIEW_TYPE_3D }; - case DxbcResourceDim::TextureCube: return { spv::DimCube, 1, 0, isUav ? 2u : 1u, 0u, VK_IMAGE_VIEW_TYPE_CUBE_ARRAY }; - case DxbcResourceDim::TextureCubeArr: return { spv::DimCube, 1, 0, isUav ? 2u : 1u, 1u, VK_IMAGE_VIEW_TYPE_CUBE_ARRAY }; + case DxbcResourceDim::Buffer: return { spv::DimBuffer, 0, 0, isUav ? 2u : 1u, VK_IMAGE_VIEW_TYPE_MAX_ENUM }; + case DxbcResourceDim::Texture1D: return { spv::Dim1D, 0, 0, isUav ? 2u : 1u, VK_IMAGE_VIEW_TYPE_1D }; + case DxbcResourceDim::Texture1DArr: return { spv::Dim1D, 1, 0, isUav ? 2u : 1u, VK_IMAGE_VIEW_TYPE_1D_ARRAY }; + case DxbcResourceDim::Texture2D: return { spv::Dim2D, 0, 0, isUav ? 2u : 1u, VK_IMAGE_VIEW_TYPE_2D }; + case DxbcResourceDim::Texture2DArr: return { spv::Dim2D, 1, 0, isUav ? 2u : 1u, VK_IMAGE_VIEW_TYPE_2D_ARRAY }; + case DxbcResourceDim::Texture2DMs: return { spv::Dim2D, 0, 1, isUav ? 2u : 1u, VK_IMAGE_VIEW_TYPE_2D }; + case DxbcResourceDim::Texture2DMsArr: return { spv::Dim2D, 1, 1, isUav ? 2u : 1u, VK_IMAGE_VIEW_TYPE_2D_ARRAY }; + case DxbcResourceDim::Texture3D: return { spv::Dim3D, 0, 0, isUav ? 2u : 1u, VK_IMAGE_VIEW_TYPE_3D }; + case DxbcResourceDim::TextureCube: return { spv::DimCube, 0, 0, isUav ? 2u : 1u, VK_IMAGE_VIEW_TYPE_CUBE }; + case DxbcResourceDim::TextureCubeArr: return { spv::DimCube, 1, 0, isUav ? 2u : 1u, VK_IMAGE_VIEW_TYPE_CUBE_ARRAY }; default: throw DxvkError(str::format("DxbcCompiler: Unsupported resource type: ", resourceType)); } }(); - if (typeInfo.dim == spv::Dim2D && m_options.test(DxbcOption::ForceTex2DArray)) { - typeInfo.array = 1; - typeInfo.vtype = VK_IMAGE_VIEW_TYPE_2D_ARRAY; - } - return typeInfo; } diff --git a/src/dxbc/dxbc_decoder.h b/src/dxbc/dxbc_decoder.h index e0b15e4d..df21fcbc 100644 --- a/src/dxbc/dxbc_decoder.h +++ b/src/dxbc/dxbc_decoder.h @@ -60,7 +60,6 @@ namespace dxvk { uint32_t array = 0; uint32_t ms = 0; uint32_t sampled = 0; - uint32_t layered = 0; VkImageViewType vtype = VK_IMAGE_VIEW_TYPE_MAX_ENUM; }; diff --git a/src/dxbc/dxbc_options.cpp b/src/dxbc/dxbc_options.cpp index 22b925b7..6ccfd565 100644 --- a/src/dxbc/dxbc_options.cpp +++ b/src/dxbc/dxbc_options.cpp @@ -5,8 +5,7 @@ namespace dxvk { const static std::unordered_map g_dxbcAppOptions = {{ - { "Dishonored2.exe", DxbcOptions(DxbcOption::ForceTex2DArray) }, - { "ManiaPlanet.exe", DxbcOptions(DxbcOption::ForceTex2DArray) }, + }}; diff --git a/src/dxbc/dxbc_options.h b/src/dxbc/dxbc_options.h index abe29521..1a8e575c 100644 --- a/src/dxbc/dxbc_options.h +++ b/src/dxbc/dxbc_options.h @@ -17,11 +17,6 @@ namespace dxvk { /// Use FMin/FMax/FClamp instead of NMin/NMax/NClamp. /// Workaround for bugs in older Nvidia drivers. UseSimpleMinMaxClamp, - - /// Enforces the use of array views even when dealing - /// with non-array texture types. Some games do not - /// bind the correct texture type to the pipeline. - ForceTex2DArray, }; using DxbcOptions = Flags; 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); };