Index: ps/trunk/source/renderer/PostprocManager.cpp =================================================================== --- ps/trunk/source/renderer/PostprocManager.cpp +++ ps/trunk/source/renderer/PostprocManager.cpp @@ -96,10 +96,14 @@ bool CPostprocManager::IsEnabled() const { Renderer::Backend::IDevice* device = g_VideoMode.GetBackendDevice(); + const bool isDepthStencilFormatPresent = + device->GetPreferredDepthStencilFormat( + Renderer::Backend::ITexture::Usage::DEPTH_STENCIL_ATTACHMENT, true, true) + != Renderer::Backend::Format::UNDEFINED; return g_RenderingOptions.GetPostProc() && device->GetBackend() != Renderer::Backend::Backend::GL_ARB && - device->IsTextureFormatSupported(Renderer::Backend::Format::D24_S8); + isDepthStencilFormatPresent; } void CPostprocManager::Cleanup() @@ -224,7 +228,11 @@ m_DepthTex = backendDevice->CreateTexture2D("PostProcDepthTexture", Renderer::Backend::ITexture::Usage::SAMPLED | Renderer::Backend::ITexture::Usage::DEPTH_STENCIL_ATTACHMENT, - Renderer::Backend::Format::D24_S8, m_Width, m_Height, + backendDevice->GetPreferredDepthStencilFormat( + Renderer::Backend::ITexture::Usage::SAMPLED | + Renderer::Backend::ITexture::Usage::DEPTH_STENCIL_ATTACHMENT, + true, true), + m_Width, m_Height, Renderer::Backend::Sampler::MakeDefaultSampler( Renderer::Backend::Sampler::Filter::LINEAR, Renderer::Backend::Sampler::AddressMode::CLAMP_TO_EDGE)); @@ -629,7 +637,11 @@ Renderer::Backend::ITexture::Type::TEXTURE_2D_MULTISAMPLE, Renderer::Backend::ITexture::Usage::DEPTH_STENCIL_ATTACHMENT | Renderer::Backend::ITexture::Usage::TRANSFER_SRC, - Renderer::Backend::Format::D24_S8, m_Width, m_Height, + backendDevice->GetPreferredDepthStencilFormat( + Renderer::Backend::ITexture::Usage::DEPTH_STENCIL_ATTACHMENT | + Renderer::Backend::ITexture::Usage::TRANSFER_SRC, + true, true), + m_Width, m_Height, Renderer::Backend::Sampler::MakeDefaultSampler( Renderer::Backend::Sampler::Filter::LINEAR, Renderer::Backend::Sampler::AddressMode::CLAMP_TO_EDGE), 1, m_MultisampleCount); Index: ps/trunk/source/renderer/ShadowMap.cpp =================================================================== --- ps/trunk/source/renderer/ShadowMap.cpp +++ ps/trunk/source/renderer/ShadowMap.cpp @@ -519,14 +519,14 @@ const char* formatName; Renderer::Backend::Format backendFormat = Renderer::Backend::Format::UNDEFINED; #if CONFIG2_GLES - formatName = "Format::D24"; - backendFormat = Renderer::Backend::Format::D24; + formatName = "Format::D24_UNORM"; + backendFormat = Renderer::Backend::Format::D24_UNORM; #else switch (DepthTextureBits) { - case 16: formatName = "Format::D16"; backendFormat = Renderer::Backend::Format::D16; break; - case 24: formatName = "Format::D24"; backendFormat = Renderer::Backend::Format::D24; break; - case 32: formatName = "Format::D32"; backendFormat = Renderer::Backend::Format::D32; break; + case 16: formatName = "Format::D16_UNORM"; backendFormat = Renderer::Backend::Format::D16_UNORM; break; + case 24: formatName = "Format::D24_UNORM"; backendFormat = Renderer::Backend::Format::D24_UNORM; break; + case 32: formatName = "Format::D32_SFLOAT"; backendFormat = Renderer::Backend::Format::D32_SFLOAT; break; default: formatName = "Default"; backendFormat = backendDevice->GetPreferredDepthStencilFormat( Index: ps/trunk/source/renderer/backend/Format.h =================================================================== --- ps/trunk/source/renderer/backend/Format.h +++ ps/trunk/source/renderer/backend/Format.h @@ -51,10 +51,11 @@ R32G32B32_SFLOAT, R32G32B32A32_SFLOAT, - D16, - D24, - D24_S8, - D32, + D16_UNORM, + D24_UNORM, + D24_UNORM_S8_UINT, + D32_SFLOAT, + D32_SFLOAT_S8_UINT, BC1_RGB_UNORM, BC1_RGBA_UNORM, @@ -65,10 +66,11 @@ inline bool IsDepthFormat(const Format format) { return - format == Format::D16 || - format == Format::D24 || - format == Format::D24_S8 || - format == Format::D32; + format == Format::D16_UNORM || + format == Format::D24_UNORM || + format == Format::D24_UNORM_S8_UINT || + format == Format::D32_SFLOAT || + format == Format::D32_SFLOAT_S8_UINT; } } // namespace Backend Index: ps/trunk/source/renderer/backend/dummy/Device.cpp =================================================================== --- ps/trunk/source/renderer/backend/dummy/Device.cpp +++ ps/trunk/source/renderer/backend/dummy/Device.cpp @@ -156,7 +156,7 @@ Format CDevice::GetPreferredDepthStencilFormat( const uint32_t, const bool, const bool) const { - return Format::D24_S8; + return Format::D24_UNORM_S8_UINT; } std::unique_ptr CreateDevice(SDL_Window* UNUSED(window)) Index: ps/trunk/source/renderer/backend/gl/Device.cpp =================================================================== --- ps/trunk/source/renderer/backend/gl/Device.cpp +++ ps/trunk/source/renderer/backend/gl/Device.cpp @@ -1010,17 +1010,20 @@ case Format::R32G32B32A32_SFLOAT: break; - case Format::D16: FALLTHROUGH; - case Format::D24: FALLTHROUGH; - case Format::D32: + case Format::D16_UNORM: FALLTHROUGH; + case Format::D24_UNORM: FALLTHROUGH; + case Format::D32_SFLOAT: supported = true; break; - case Format::D24_S8: + case Format::D24_UNORM_S8_UINT: #if !CONFIG2_GLES supported = true; #endif break; + case Format::D32_SFLOAT_S8_UINT: + break; + case Format::BC1_RGB_UNORM: FALLTHROUGH; case Format::BC1_RGBA_UNORM: FALLTHROUGH; case Format::BC2_UNORM: FALLTHROUGH; @@ -1063,10 +1066,10 @@ #if CONFIG2_GLES return Format::UNDEFINED; #else - return Format::D24_S8; + return Format::D24_UNORM_S8_UINT; #endif else - return Format::D24; + return Format::D24_UNORM; } std::unique_ptr CreateDevice(SDL_Window* window, const bool arb) Index: ps/trunk/source/renderer/backend/gl/DeviceCommandContext.cpp =================================================================== --- ps/trunk/source/renderer/backend/gl/DeviceCommandContext.cpp +++ ps/trunk/source/renderer/backend/gl/DeviceCommandContext.cpp @@ -111,15 +111,6 @@ return target; } -#if !CONFIG2_GLES -bool IsDepthTexture(const Format format) -{ - return - format == Format::D16 || format == Format::D24 || - format == Format::D32 || format == Format::D24_S8; -} -#endif // !CONFIG2_GLES - void UploadDynamicBufferRegionImpl( const GLenum target, const uint32_t bufferSize, const uint32_t dataOffset, const uint32_t dataSize, @@ -1211,7 +1202,7 @@ #if !CONFIG2_GLES if (textureUnit.type == GL_SAMPLER_2D_SHADOW) { - if (!IsDepthTexture(texture->GetFormat())) + if (!IsDepthFormat(texture->GetFormat())) { LOGERROR("CDeviceCommandContext::SetTexture: Invalid texture type (expected depth texture)"); return; Index: ps/trunk/source/renderer/backend/gl/Framebuffer.cpp =================================================================== --- ps/trunk/source/renderer/backend/gl/Framebuffer.cpp +++ ps/trunk/source/renderer/backend/gl/Framebuffer.cpp @@ -90,7 +90,10 @@ framebuffer->m_Width = depthStencilAttachmentTexture->GetWidth(); framebuffer->m_Height = depthStencilAttachmentTexture->GetHeight(); framebuffer->m_AttachmentMask |= GL_DEPTH_BUFFER_BIT; - if (depthStencilAttachmentTexture->GetFormat() == Format::D24_S8) + const bool hasStencil = + depthStencilAttachmentTexture->GetFormat() == Format::D24_UNORM_S8_UINT || + depthStencilAttachmentTexture->GetFormat() == Format::D32_SFLOAT_S8_UINT; + if (hasStencil) framebuffer->m_AttachmentMask |= GL_STENCIL_BUFFER_BIT; if (colorAttachment) { @@ -98,18 +101,14 @@ ENSURE(colorAttachment->texture->GetHeight() == depthStencilAttachmentTexture->GetHeight()); ENSURE(colorAttachment->texture->GetType() == depthStencilAttachmentTexture->GetType()); } - ENSURE( - depthStencilAttachmentTexture->GetFormat() == Format::D16 || - depthStencilAttachmentTexture->GetFormat() == Format::D24 || - depthStencilAttachmentTexture->GetFormat() == Format::D32 || - depthStencilAttachmentTexture->GetFormat() == Format::D24_S8); + ENSURE(IsDepthFormat(depthStencilAttachmentTexture->GetFormat())); #if CONFIG2_GLES - ENSURE(depthStencilAttachmentTexture->GetFormat() != Format::D24_S8); + ENSURE(depthStencilAttachmentTexture->GetFormat() == Format::D24_UNORM); const GLenum attachment = GL_DEPTH_ATTACHMENT; ENSURE(depthStencilAttachmentTexture->GetType() == CTexture::Type::TEXTURE_2D); const GLenum textureTarget = GL_TEXTURE_2D; #else - const GLenum attachment = depthStencilAttachmentTexture->GetFormat() == Format::D24_S8 ? + const GLenum attachment = hasStencil ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT; const GLenum textureTarget = depthStencilAttachmentTexture->GetType() == CTexture::Type::TEXTURE_2D_MULTISAMPLE ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D; Index: ps/trunk/source/renderer/backend/gl/Texture.cpp =================================================================== --- ps/trunk/source/renderer/backend/gl/Texture.cpp +++ ps/trunk/source/renderer/backend/gl/Texture.cpp @@ -211,33 +211,33 @@ break; #if CONFIG2_GLES // GLES requires pixel type == UNSIGNED_SHORT or UNSIGNED_INT for depth. - case Format::D16: FALLTHROUGH; - case Format::D24: FALLTHROUGH; - case Format::D32: + case Format::D16_UNORM: FALLTHROUGH; + case Format::D24_UNORM: FALLTHROUGH; + case Format::D32_SFLOAT: internalFormat = GL_DEPTH_COMPONENT; pixelFormat = GL_DEPTH_COMPONENT; pixelType = GL_UNSIGNED_SHORT; break; - case Format::D24_S8: + case Format::D24_UNORM_S8_UINT: debug_warn("Unsupported format"); break; #else - case Format::D16: + case Format::D16_UNORM: internalFormat = GL_DEPTH_COMPONENT16; pixelFormat = GL_DEPTH_COMPONENT; pixelType = GL_UNSIGNED_SHORT; break; - case Format::D24: + case Format::D24_UNORM: internalFormat = GL_DEPTH_COMPONENT24; pixelFormat = GL_DEPTH_COMPONENT; pixelType = GL_UNSIGNED_SHORT; break; - case Format::D32: + case Format::D32_SFLOAT: internalFormat = GL_DEPTH_COMPONENT32; pixelFormat = GL_DEPTH_COMPONENT; pixelType = GL_UNSIGNED_SHORT; break; - case Format::D24_S8: + case Format::D24_UNORM_S8_UINT: internalFormat = GL_DEPTH24_STENCIL8_EXT; pixelFormat = GL_DEPTH_STENCIL_EXT; pixelType = GL_UNSIGNED_INT_24_8_EXT; @@ -271,7 +271,7 @@ { glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, sampleCount, GL_RGBA8, width, height, GL_TRUE); } - else if (format == Format::D24_S8) + else if (format == Format::D24_UNORM_S8_UINT) { glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, sampleCount, GL_DEPTH24_STENCIL8_EXT, width, height, GL_TRUE); } @@ -284,8 +284,7 @@ #if !CONFIG2_GLES - if (format == Format::D16 || format == Format::D24 || format == Format::D32 || - format == Format::D24_S8) + if (IsDepthFormat(format)) { if (defaultSamplerDesc.compareEnabled) { Index: ps/trunk/source/renderer/backend/vulkan/DescriptorManager.cpp =================================================================== --- ps/trunk/source/renderer/backend/vulkan/DescriptorManager.cpp +++ ps/trunk/source/renderer/backend/vulkan/DescriptorManager.cpp @@ -285,10 +285,7 @@ uint32_t binding = 0; if (texture->GetType() == ITexture::Type::TEXTURE_2D && - (texture->GetFormat() == Format::D16 || - texture->GetFormat() == Format::D24 || - texture->GetFormat() == Format::D32 || - texture->GetFormat() == Format::D24_S8) && + IsDepthFormat(texture->GetFormat()) && texture->IsCompareEnabled()) binding = 2; else if (texture->GetType() == ITexture::Type::TEXTURE_CUBE) Index: ps/trunk/source/renderer/backend/vulkan/Device.h =================================================================== --- ps/trunk/source/renderer/backend/vulkan/Device.h +++ ps/trunk/source/renderer/backend/vulkan/Device.h @@ -167,6 +167,8 @@ void ProcessObjectToDestroyQueue(const bool ignoreFrameID = false); void ProcessTextureToDestroyQueue(const bool ignoreFrameID = false); + bool IsFormatSupportedForUsage(const Format format, const uint32_t usage) const; + std::string m_Name; std::string m_Version; std::string m_VendorID; Index: ps/trunk/source/renderer/backend/vulkan/Device.cpp =================================================================== --- ps/trunk/source/renderer/backend/vulkan/Device.cpp +++ ps/trunk/source/renderer/backend/vulkan/Device.cpp @@ -784,38 +784,25 @@ bool CDevice::IsTextureFormatSupported(const Format format) const { - bool supported = false; switch (format) { case Format::UNDEFINED: - break; - - case Format::R8G8B8_UNORM: FALLTHROUGH; - case Format::R8G8B8A8_UNORM: FALLTHROUGH; - case Format::A8_UNORM: FALLTHROUGH; - case Format::L8_UNORM: FALLTHROUGH; - case Format::R32_SFLOAT: FALLTHROUGH; - case Format::R32G32_SFLOAT: FALLTHROUGH; - case Format::R32G32B32_SFLOAT: FALLTHROUGH; - case Format::R32G32B32A32_SFLOAT: FALLTHROUGH; - case Format::D16: FALLTHROUGH; - case Format::D24: FALLTHROUGH; - case Format::D24_S8: FALLTHROUGH; - case Format::D32: - supported = true; - break; + return false; case Format::BC1_RGB_UNORM: FALLTHROUGH; case Format::BC1_RGBA_UNORM: FALLTHROUGH; case Format::BC2_UNORM: FALLTHROUGH; case Format::BC3_UNORM: - supported = m_Capabilities.S3TC; - break; + return m_Capabilities.S3TC; default: break; } - return supported; + + VkFormatProperties formatProperties{}; + vkGetPhysicalDeviceFormatProperties( + m_ChoosenDevice.device, Mapping::FromFormat(format), &formatProperties); + return formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT; } bool CDevice::IsFramebufferFormatSupported(const Format format) const @@ -829,28 +816,58 @@ } Format CDevice::GetPreferredDepthStencilFormat( - const uint32_t UNUSED(usage), const bool depth, const bool stencil) const + const uint32_t usage, const bool depth, const bool stencil) const { - // TODO: account usage. ENSURE(depth || stencil); Format format = Format::UNDEFINED; if (stencil) { - format = Format::D24_S8; + // https://github.com/KhronosGroup/Vulkan-Guide/blob/main/chapters/depth.adoc#depth-formats + // At least one of VK_FORMAT_D24_UNORM_S8_UINT or VK_FORMAT_D32_SFLOAT_S8_UINT + // must also be supported. + if (IsFormatSupportedForUsage(Format::D24_UNORM_S8_UINT, usage)) + format = Format::D24_UNORM_S8_UINT; + else + format = Format::D32_SFLOAT_S8_UINT; } else { + std::array formatRequestOrder; // TODO: add most known vendors to enum. // https://developer.nvidia.com/blog/vulkan-dos-donts/ if (m_ChoosenDevice.properties.vendorID == 0x10DE) - format = Format::D24; + formatRequestOrder = {Format::D24_UNORM, Format::D32_SFLOAT, Format::D16_UNORM}; else - format = Format::D24; + formatRequestOrder = {Format::D32_SFLOAT, Format::D24_UNORM, Format::D16_UNORM}; + for (const Format formatRequest : formatRequestOrder) + if (IsFormatSupportedForUsage(formatRequest, usage)) + { + format = formatRequest; + break; + } } - ENSURE(IsFramebufferFormatSupported(format)); return format; } +bool CDevice::IsFormatSupportedForUsage(const Format format, const uint32_t usage) const +{ + VkFormatProperties formatProperties{}; + vkGetPhysicalDeviceFormatProperties( + m_ChoosenDevice.device, Mapping::FromFormat(format), &formatProperties); + VkFormatFeatureFlags expectedFeatures = 0; + if (usage & ITexture::Usage::COLOR_ATTACHMENT) + expectedFeatures |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT; + if (usage & ITexture::Usage::DEPTH_STENCIL_ATTACHMENT) + expectedFeatures |= VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT; + if (usage & ITexture::Usage::SAMPLED) + expectedFeatures |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT; + if (usage & ITexture::Usage::TRANSFER_SRC) + expectedFeatures |= VK_FORMAT_FEATURE_TRANSFER_SRC_BIT; + if (usage & ITexture::Usage::TRANSFER_DST) + expectedFeatures |= VK_FORMAT_FEATURE_TRANSFER_DST_BIT; + return (formatProperties.optimalTilingFeatures & expectedFeatures) == expectedFeatures; +} + void CDevice::ScheduleObjectToDestroy( VkObjectType type, const uint64_t handle, const VmaAllocation allocation) { Index: ps/trunk/source/renderer/backend/vulkan/DeviceCommandContext.cpp =================================================================== --- ps/trunk/source/renderer/backend/vulkan/DeviceCommandContext.cpp +++ ps/trunk/source/renderer/backend/vulkan/DeviceCommandContext.cpp @@ -370,7 +370,12 @@ { ENSURE(m_Framebuffer->GetDepthStencilAttachment()); if (stencil) - ENSURE(m_Framebuffer->GetDepthStencilAttachment()->GetFormat() == Format::D24_S8); + { + const Format depthStencilFormat = + m_Framebuffer->GetDepthStencilAttachment()->GetFormat(); + ENSURE(depthStencilFormat == Format::D24_UNORM_S8_UINT || + depthStencilFormat == Format::D32_SFLOAT_S8_UINT); + } VkClearAttachment clearAttachment{}; if (depth) clearAttachment.aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT; Index: ps/trunk/source/renderer/backend/vulkan/Mapping.cpp =================================================================== --- ps/trunk/source/renderer/backend/vulkan/Mapping.cpp +++ ps/trunk/source/renderer/backend/vulkan/Mapping.cpp @@ -183,10 +183,11 @@ CASE(R32G32B32_SFLOAT) CASE(R32G32B32A32_SFLOAT) - CASE2(D16, D16_UNORM) - CASE2(D24, X8_D24_UNORM_PACK32) - CASE2(D24_S8, D24_UNORM_S8_UINT) - CASE2(D32, D32_SFLOAT) + CASE(D16_UNORM) + CASE2(D24_UNORM, X8_D24_UNORM_PACK32) + CASE(D24_UNORM_S8_UINT) + CASE(D32_SFLOAT_S8_UINT) + CASE(D32_SFLOAT) CASE2(BC1_RGB_UNORM, BC1_RGB_UNORM_BLOCK) CASE2(BC1_RGBA_UNORM, BC1_RGBA_UNORM_BLOCK) Index: ps/trunk/source/renderer/backend/vulkan/SwapChain.cpp =================================================================== --- ps/trunk/source/renderer/backend/vulkan/SwapChain.cpp +++ ps/trunk/source/renderer/backend/vulkan/SwapChain.cpp @@ -186,7 +186,10 @@ swapChain->m_DepthTexture = CTexture::Create( device, "SwapChainDepthTexture", ITexture::Type::TEXTURE_2D, - ITexture::Usage::DEPTH_STENCIL_ATTACHMENT, Format::D24_S8, + ITexture::Usage::DEPTH_STENCIL_ATTACHMENT, + device->GetPreferredDepthStencilFormat( + Renderer::Backend::ITexture::Usage::DEPTH_STENCIL_ATTACHMENT, + true, true), swapChainWidth, swapChainHeight, Sampler::MakeDefaultSampler( Sampler::Filter::NEAREST, Sampler::AddressMode::CLAMP_TO_EDGE), 1, 1); Index: ps/trunk/source/renderer/backend/vulkan/Texture.cpp =================================================================== --- ps/trunk/source/renderer/backend/vulkan/Texture.cpp +++ ps/trunk/source/renderer/backend/vulkan/Texture.cpp @@ -76,6 +76,7 @@ VkImageUsageFlags usageFlags = 0; // Vulkan 1.0 implies that TRANSFER_SRC and TRANSFER_DST are supported. + // TODO: account Vulkan 1.1. if (usage & Usage::TRANSFER_SRC) usageFlags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT; if (usage & Usage::TRANSFER_DST) @@ -115,7 +116,7 @@ { texture->m_AttachmentImageAspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; texture->m_SamplerImageAspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - if (format == Format::D24_S8) + if (format == Format::D24_UNORM_S8_UINT || format == Format::D32_SFLOAT_S8_UINT) texture->m_AttachmentImageAspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; } else