GS/Vulkan: Support rendering without D32S8

This commit is contained in:
Connor McLaughlin 2022-01-21 20:09:47 +10:00 committed by refractionpcsx2
parent 6b32e00097
commit a6b4ca69db
8 changed files with 70 additions and 50 deletions

View File

@ -580,6 +580,7 @@ public:
bool bptc_textures : 1; ///< Supports BC6/7 texture compression.
bool framebuffer_fetch : 1; ///< Can sample from the framebuffer without texture barriers.
bool dual_source_blend : 1; ///< Can use alpha output as a blend factor.
bool stencil_buffer : 1; ///< Supports stencil buffer, and can use for DATE.
FeatureSupport()
{
memset(this, 0, sizeof(*this));

View File

@ -55,6 +55,7 @@ GSDevice11::GSDevice11()
m_features.bptc_textures = false;
m_features.framebuffer_fetch = false;
m_features.dual_source_blend = true;
m_features.stencil_buffer = true;
}
bool GSDevice11::Create(HostDisplay* display)

View File

@ -1445,13 +1445,13 @@ void GSRendererNew::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour
// Performance note: check alpha range with GetAlphaMinMax()
// Note: all my dump are already above 120fps, but it seems to reduce GPU load
// with big upscaling
if (m_context->TEST.DATM && GetAlphaMinMax().max < 128)
if (m_context->TEST.DATM && GetAlphaMinMax().max < 128 && features.stencil_buffer)
{
// Only first pixel (write 0) will pass (alpha is 1)
GL_PERF("DATE: Fast with alpha %d-%d", GetAlphaMinMax().min, GetAlphaMinMax().max);
DATE_one = true;
}
else if (!m_context->TEST.DATM && GetAlphaMinMax().min >= 128)
else if (!m_context->TEST.DATM && GetAlphaMinMax().min >= 128 && features.stencil_buffer)
{
// Only first pixel (write 1) will pass (alpha is 0)
GL_PERF("DATE: Fast with alpha %d-%d", GetAlphaMinMax().min, GetAlphaMinMax().max);
@ -1462,7 +1462,7 @@ void GSRendererNew::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour
// texture barrier will split the draw call into n draw call. It is very efficient for
// few primitive draws. Otherwise it sucks.
GL_PERF("DATE: Accurate with alpha %d-%d", GetAlphaMinMax().min, GetAlphaMinMax().max);
if (g_gs_device->Features().texture_barrier)
if (features.texture_barrier)
{
m_conf.require_full_barrier = true;
DATE_BARRIER = true;
@ -1472,16 +1472,16 @@ void GSRendererNew::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour
{
// Note: Fast level (DATE_one) was removed as it's less accurate.
GL_PERF("DATE: Accurate with alpha %d-%d", GetAlphaMinMax().min, GetAlphaMinMax().max);
if (g_gs_device->Features().image_load_store)
if (features.image_load_store)
{
DATE_PRIMID = true;
}
else if (g_gs_device->Features().texture_barrier)
else if (features.texture_barrier)
{
m_conf.require_full_barrier = true;
DATE_BARRIER = true;
}
else
else if (features.stencil_buffer)
{
DATE_one = true;
}
@ -1545,7 +1545,7 @@ void GSRendererNew::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour
m_conf.destination_alpha = GSHWDrawConfig::DestinationAlphaMode::PrimIDTracking;
else if (DATE_BARRIER)
m_conf.destination_alpha = GSHWDrawConfig::DestinationAlphaMode::Full;
else
else if (features.stencil_buffer)
m_conf.destination_alpha = GSHWDrawConfig::DestinationAlphaMode::Stencil;
m_conf.datm = m_context->TEST.DATM;

View File

@ -225,6 +225,7 @@ bool GSDeviceOGL::Create(HostDisplay* display)
m_features.prefer_new_textures = false;
m_features.framebuffer_fetch = GLLoader::found_framebuffer_fetch;
m_features.dual_source_blend = GLLoader::has_dual_source_blend && !GSConfig.DisableDualSourceBlend;
m_features.stencil_buffer = true;
GLint point_range[2] = {};
GLint line_range[2] = {};

View File

@ -252,6 +252,13 @@ bool GSDeviceVK::CheckFeatures()
if (!m_features.texture_barrier)
Console.Warning("Texture buffers are disabled. This may break some graphical effects.");
// Test for D32S8 support.
{
VkFormatProperties props = {};
vkGetPhysicalDeviceFormatProperties(g_vulkan_context->GetPhysicalDevice(), VK_FORMAT_D32_SFLOAT_S8_UINT, &props);
m_features.stencil_buffer = ((props.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0);
}
// whether we can do point/line expand depends on the range of the device
const float f_upscale = static_cast<float>(GSConfig.UpscaleMultiplier);
m_features.point_expand =
@ -265,7 +272,7 @@ bool GSDeviceVK::CheckFeatures()
// Check texture format support before we try to create them.
for (u32 fmt = static_cast<u32>(GSTexture::Format::Color); fmt < static_cast<u32>(GSTexture::Format::Int32); fmt++)
{
const VkFormat vkfmt = GSTextureVK::LookupNativeFormat(static_cast<GSTexture::Format>(fmt));
const VkFormat vkfmt = LookupNativeFormat(static_cast<GSTexture::Format>(fmt));
const VkFormatFeatureFlags bits = (static_cast<GSTexture::Format>(fmt) == GSTexture::Format::DepthStencil) ?
(VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) :
(VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT);
@ -283,6 +290,13 @@ bool GSDeviceVK::CheckFeatures()
m_features.dxt_textures = g_vulkan_context->GetDeviceFeatures().textureCompressionBC;
m_features.bptc_textures = g_vulkan_context->GetDeviceFeatures().textureCompressionBC;
if (!m_features.texture_barrier && !m_features.stencil_buffer)
{
Host::AddKeyedOSDMessage("GSDeviceVK_NoTextureBarrierOrStencilBuffer",
"Stencil buffers and texture barriers are both unavailable, this will break some graphical effects.", 10.0f);
}
return true;
}
@ -358,6 +372,28 @@ void GSDeviceVK::ClearStencil(GSTexture* t, u8 c)
static_cast<GSTextureVK*>(t)->TransitionToLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
}
VkFormat GSDeviceVK::LookupNativeFormat(GSTexture::Format format) const
{
static constexpr std::array<VkFormat, static_cast<int>(GSTexture::Format::BC7) + 1> s_format_mapping = {{
VK_FORMAT_UNDEFINED, // Invalid
VK_FORMAT_R8G8B8A8_UNORM, // Color
VK_FORMAT_R32G32B32A32_SFLOAT, // FloatColor
VK_FORMAT_D32_SFLOAT_S8_UINT, // DepthStencil
VK_FORMAT_R8_UNORM, // UNorm8
VK_FORMAT_R16_UINT, // UInt16
VK_FORMAT_R32_UINT, // UInt32
VK_FORMAT_R32_SFLOAT, // Int32
VK_FORMAT_BC1_RGBA_UNORM_BLOCK, // BC1
VK_FORMAT_BC2_UNORM_BLOCK, // BC2
VK_FORMAT_BC3_UNORM_BLOCK, // BC3
VK_FORMAT_BC7_UNORM_BLOCK, // BC7
}};
return (format != GSTexture::Format::DepthStencil || m_features.stencil_buffer) ?
s_format_mapping[static_cast<int>(format)] :
VK_FORMAT_D32_SFLOAT;
}
GSTexture* GSDeviceVK::CreateSurface(GSTexture::Type type, int width, int height, int levels, GSTexture::Format format)
{
pxAssert(type != GSTexture::Type::Offscreen && type != GSTexture::Type::SparseRenderTarget &&
@ -366,7 +402,7 @@ GSTexture* GSDeviceVK::CreateSurface(GSTexture::Type type, int width, int height
const u32 clamped_width = static_cast<u32>(std::clamp<int>(1, width, g_vulkan_context->GetMaxImageDimension2D()));
const u32 clamped_height = static_cast<u32>(std::clamp<int>(1, height, g_vulkan_context->GetMaxImageDimension2D()));
return GSTextureVK::Create(type, clamped_width, clamped_height, levels, format).release();
return GSTextureVK::Create(type, clamped_width, clamped_height, levels, format, LookupNativeFormat(format)).release();
}
bool GSDeviceVK::DownloadTexture(GSTexture* src, const GSVector4i& rect, GSTexture::GSMap& out_map)
@ -1161,9 +1197,9 @@ bool GSDeviceVK::CreateRenderPasses()
return false; \
} while (0)
const VkFormat rt_format = GSTextureVK::LookupNativeFormat(GSTexture::Format::Color);
const VkFormat hdr_rt_format = GSTextureVK::LookupNativeFormat(GSTexture::Format::FloatColor);
const VkFormat depth_format = GSTextureVK::LookupNativeFormat(GSTexture::Format::DepthStencil);
const VkFormat rt_format = LookupNativeFormat(GSTexture::Format::Color);
const VkFormat hdr_rt_format = LookupNativeFormat(GSTexture::Format::FloatColor);
const VkFormat depth_format = LookupNativeFormat(GSTexture::Format::DepthStencil);
for (u32 rt = 0; rt < 2; rt++)
{
@ -1183,7 +1219,7 @@ bool GSDeviceVK::CreateRenderPasses()
(rt != 0) ? ((hdr != 0) ? hdr_rt_format : rt_format) : VK_FORMAT_UNDEFINED;
const VkFormat rp_depth_format = (ds != 0) ? depth_format : VK_FORMAT_UNDEFINED;
const VkAttachmentLoadOp opc =
((date == DATE_RENDER_PASS_NONE) ?
((date == DATE_RENDER_PASS_NONE || !m_features.stencil_buffer) ?
VK_ATTACHMENT_LOAD_OP_DONT_CARE :
(date == DATE_RENDER_PASS_STENCIL_ONE ? VK_ATTACHMENT_LOAD_OP_CLEAR :
VK_ATTACHMENT_LOAD_OP_LOAD));
@ -1212,8 +1248,9 @@ bool GSDeviceVK::CreateRenderPasses()
VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_LOAD_OP_DONT_CARE);
m_date_setup_render_pass = g_vulkan_context->GetRenderPass(VK_FORMAT_UNDEFINED, depth_format,
VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_LOAD_OP_LOAD,
VK_ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_STORE);
VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE,
m_features.stencil_buffer ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_DONT_CARE,
m_features.stencil_buffer ? VK_ATTACHMENT_STORE_OP_STORE : VK_ATTACHMENT_STORE_OP_DONT_CARE);
if (m_date_setup_render_pass == VK_NULL_HANDLE)
return false;
@ -1271,13 +1308,13 @@ bool GSDeviceVK::CompileConvertPipelines()
case ShaderConvert::RGBA8_TO_16_BITS:
case ShaderConvert::FLOAT32_TO_16_BITS:
{
rp = g_vulkan_context->GetRenderPass(GSTextureVK::LookupNativeFormat(GSTexture::Format::UInt16),
rp = g_vulkan_context->GetRenderPass(LookupNativeFormat(GSTexture::Format::UInt16),
VK_FORMAT_UNDEFINED, VK_ATTACHMENT_LOAD_OP_DONT_CARE);
}
break;
case ShaderConvert::FLOAT32_TO_32_BITS:
{
rp = g_vulkan_context->GetRenderPass(GSTextureVK::LookupNativeFormat(GSTexture::Format::UInt32),
rp = g_vulkan_context->GetRenderPass(LookupNativeFormat(GSTexture::Format::UInt32),
VK_FORMAT_UNDEFINED, VK_ATTACHMENT_LOAD_OP_DONT_CARE);
}
break;
@ -1290,8 +1327,8 @@ bool GSDeviceVK::CompileConvertPipelines()
default:
{
rp = g_vulkan_context->GetRenderPass(
GSTextureVK::LookupNativeFormat(depth ? GSTexture::Format::Invalid : GSTexture::Format::Color),
GSTextureVK::LookupNativeFormat(
LookupNativeFormat(depth ? GSTexture::Format::Invalid : GSTexture::Format::Color),
LookupNativeFormat(
depth ? GSTexture::Format::DepthStencil : GSTexture::Format::Invalid),
VK_ATTACHMENT_LOAD_OP_DONT_CARE);
}
@ -1411,8 +1448,8 @@ bool GSDeviceVK::CompileConvertPipelines()
for (u32 clear = 0; clear < 2; clear++)
{
m_date_image_setup_render_passes[ds][clear] =
g_vulkan_context->GetRenderPass(GSTextureVK::LookupNativeFormat(GSTexture::Format::Int32),
ds ? GSTextureVK::LookupNativeFormat(GSTexture::Format::DepthStencil) : VK_FORMAT_UNDEFINED,
g_vulkan_context->GetRenderPass(LookupNativeFormat(GSTexture::Format::Int32),
ds ? LookupNativeFormat(GSTexture::Format::DepthStencil) : VK_FORMAT_UNDEFINED,
VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_STORE,
ds ? (clear ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD) :
VK_ATTACHMENT_LOAD_OP_DONT_CARE,
@ -1462,7 +1499,7 @@ bool GSDeviceVK::CompileInterlacePipelines()
}
VkRenderPass rp = g_vulkan_context->GetRenderPass(
GSTextureVK::LookupNativeFormat(GSTexture::Format::Color), VK_FORMAT_UNDEFINED, VK_ATTACHMENT_LOAD_OP_LOAD);
LookupNativeFormat(GSTexture::Format::Color), VK_FORMAT_UNDEFINED, VK_ATTACHMENT_LOAD_OP_LOAD);
if (!rp)
return false;
@ -1516,7 +1553,7 @@ bool GSDeviceVK::CompileMergePipelines()
}
VkRenderPass rp = g_vulkan_context->GetRenderPass(
GSTextureVK::LookupNativeFormat(GSTexture::Format::Color), VK_FORMAT_UNDEFINED, VK_ATTACHMENT_LOAD_OP_LOAD);
LookupNativeFormat(GSTexture::Format::Color), VK_FORMAT_UNDEFINED, VK_ATTACHMENT_LOAD_OP_LOAD);
if (!rp)
return false;

View File

@ -146,6 +146,8 @@ private:
std::string m_tfx_source;
VkFormat LookupNativeFormat(GSTexture::Format format) const;
GSTexture* CreateSurface(GSTexture::Type type, int width, int height, int levels, GSTexture::Format format) override;
void DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, GSVector4* dRect, const GSRegPMODE& PMODE,

View File

@ -59,7 +59,7 @@ GSTextureVK::~GSTextureVK()
}
}
std::unique_ptr<GSTextureVK> GSTextureVK::Create(Type type, u32 width, u32 height, u32 levels, Format format)
std::unique_ptr<GSTextureVK> GSTextureVK::Create(Type type, u32 width, u32 height, u32 levels, Format format, VkFormat vk_format)
{
switch (type)
{
@ -77,7 +77,7 @@ std::unique_ptr<GSTextureVK> GSTextureVK::Create(Type type, u32 width, u32 heigh
}
Vulkan::Texture texture;
if (!texture.Create(width, height, levels, 1, LookupNativeFormat(format), VK_SAMPLE_COUNT_1_BIT,
if (!texture.Create(width, height, levels, 1, vk_format, VK_SAMPLE_COUNT_1_BIT,
VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, usage, swizzle))
{
return {};
@ -93,7 +93,7 @@ std::unique_ptr<GSTextureVK> GSTextureVK::Create(Type type, u32 width, u32 heigh
pxAssert(levels == 1);
Vulkan::Texture texture;
if (!texture.Create(width, height, levels, 1, LookupNativeFormat(format), VK_SAMPLE_COUNT_1_BIT,
if (!texture.Create(width, height, levels, 1, vk_format, VK_SAMPLE_COUNT_1_BIT,
VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT |
@ -112,7 +112,7 @@ std::unique_ptr<GSTextureVK> GSTextureVK::Create(Type type, u32 width, u32 heigh
pxAssert(levels == 1);
Vulkan::Texture texture;
if (!texture.Create(width, height, levels, 1, LookupNativeFormat(format), VK_SAMPLE_COUNT_1_BIT,
if (!texture.Create(width, height, levels, 1, vk_format, VK_SAMPLE_COUNT_1_BIT,
VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT))
@ -130,27 +130,6 @@ std::unique_ptr<GSTextureVK> GSTextureVK::Create(Type type, u32 width, u32 heigh
}
}
VkFormat GSTextureVK::LookupNativeFormat(Format format)
{
static constexpr std::array<VkFormat, static_cast<int>(GSTexture::Format::BC7) + 1> s_format_mapping = {{
VK_FORMAT_UNDEFINED, // Invalid
VK_FORMAT_R8G8B8A8_UNORM, // Color
VK_FORMAT_R32G32B32A32_SFLOAT, // FloatColor
VK_FORMAT_D32_SFLOAT_S8_UINT, // DepthStencil
VK_FORMAT_R8_UNORM, // UNorm8
VK_FORMAT_R16_UINT, // UInt16
VK_FORMAT_R32_UINT, // UInt32
VK_FORMAT_R32_SFLOAT, // Int32
VK_FORMAT_BC1_RGBA_UNORM_BLOCK, // BC1
VK_FORMAT_BC2_UNORM_BLOCK, // BC2
VK_FORMAT_BC3_UNORM_BLOCK, // BC3
VK_FORMAT_BC7_UNORM_BLOCK, // BC7
}};
return s_format_mapping[static_cast<int>(format)];
}
void* GSTextureVK::GetNativeHandle() const { return const_cast<Vulkan::Texture*>(&m_texture); }
VkCommandBuffer GSTextureVK::GetCommandBufferForUpdate()

View File

@ -33,8 +33,7 @@ public:
GSTextureVK(Type type, Format format, Vulkan::Texture texture);
~GSTextureVK() override;
static std::unique_ptr<GSTextureVK> Create(Type type, u32 width, u32 height, u32 levels, Format format);
static VkFormat LookupNativeFormat(Format format);
static std::unique_ptr<GSTextureVK> Create(Type type, u32 width, u32 height, u32 levels, Format format, VkFormat vk_format);
__fi Vulkan::Texture& GetTexture() { return m_texture; }
__fi VkFormat GetNativeFormat() const { return m_texture.GetFormat(); }