Start unifying setting of the GPU feature flags, now that thin3d has feature detection.

This commit is contained in:
Henrik Rydgård 2022-09-20 10:02:15 +02:00
parent 913ba9de88
commit 1ae7c0132c
16 changed files with 80 additions and 106 deletions

View File

@ -270,6 +270,7 @@ D3D11DrawContext::D3D11DrawContext(ID3D11Device *device, ID3D11DeviceContext *de
caps_.anisoSupported = true;
caps_.textureNPOTFullySupported = true;
caps_.fragmentShaderDepthWriteSupported = true;
caps_.blendMinMaxSupported = true;
D3D11_FEATURE_DATA_D3D11_OPTIONS options{};
HRESULT result = device_->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &options, sizeof(options));

View File

@ -665,14 +665,24 @@ D3D9Context::D3D9Context(IDirect3D9 *d3d, IDirect3D9Ex *d3dEx, int adapterId, ID
caps_.vendor = GPUVendor::VENDOR_UNKNOWN;
}
if (!FAILED(device->GetDeviceCaps(&d3dCaps_))) {
D3DCAPS9 caps;
ZeroMemory(&caps, sizeof(caps));
HRESULT result = 0;
if (deviceEx_) {
result = deviceEx_->GetDeviceCaps(&caps);
} else {
result = device_->GetDeviceCaps(&caps);
}
if (SUCCEEDED(result)) {
sprintf(shadeLangVersion_, "PS: %04x VS: %04x", d3dCaps_.PixelShaderVersion & 0xFFFF, d3dCaps_.VertexShaderVersion & 0xFFFF);
} else {
WARN_LOG(G3D, "Direct3D9: Failed to get the device caps!");
strcpy(shadeLangVersion_, "N/A");
}
caps_.deviceID = identifier_.DeviceId;
caps_.multiViewport = false;
caps_.anisoSupported = true;
caps_.depthRangeMinusOneToOne = false;
caps_.preferredDepthBufferFormat = DataFormat::D24_S8;
caps_.dualSourceBlend = false;
@ -684,8 +694,15 @@ D3D9Context::D3D9Context(IDirect3D9 *d3d, IDirect3D9Ex *d3dEx, int adapterId, ID
caps_.framebufferDepthCopySupported = false;
caps_.framebufferSeparateDepthCopySupported = false;
caps_.texture3DSupported = true;
caps_.textureNPOTFullySupported = true;
caps_.fragmentShaderDepthWriteSupported = true;
caps_.blendMinMaxSupported = true;
if ((caps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) != 0 && caps.MaxAnisotropy > 1) {
caps_.anisoSupported = true;
}
if ((caps.TextureCaps & (D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_POW2)) == 0) {
caps_.textureNPOTFullySupported = true;
}
if (d3d) {
D3DDISPLAYMODE displayMode;

View File

@ -552,6 +552,8 @@ OpenGLContext::OpenGLContext() {
caps_.framebufferDepthBlitSupported = caps_.framebufferBlitSupported;
caps_.framebufferStencilBlitSupported = caps_.framebufferBlitSupported;
caps_.depthClampSupported = gl_extensions.ARB_depth_clamp;
caps_.blendMinMaxSupported = gl_extensions.EXT_blend_minmax;
if (gl_extensions.IsGLES) {
caps_.clipDistanceSupported = gl_extensions.EXT_clip_cull_distance || gl_extensions.APPLE_clip_distance;
caps_.cullDistanceSupported = gl_extensions.EXT_clip_cull_distance;

View File

@ -788,9 +788,11 @@ VKContext::VKContext(VulkanContext *vulkan)
caps_.fragmentShaderInt32Supported = true;
caps_.textureNPOTFullySupported = true;
caps_.fragmentShaderDepthWriteSupported = true;
caps_.blendMinMaxSupported = true;
caps_.logicOpSupported = vulkan->GetDeviceFeatures().enabled.logicOp != 0;
auto deviceProps = vulkan->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDeviceIndex()).properties;
switch (deviceProps.vendorID) {
case VULKAN_VENDOR_AMD: caps_.vendor = GPUVendor::VENDOR_AMD; break;
case VULKAN_VENDOR_ARM: caps_.vendor = GPUVendor::VENDOR_ARM; break;

View File

@ -547,6 +547,7 @@ struct DeviceCaps {
bool textureNPOTFullySupported;
bool fragmentShaderDepthWriteSupported;
bool textureDepthSupported;
bool blendMinMaxSupported;
std::string deviceName; // The device name to use when creating the thin3d context, to get the same one.
};

View File

@ -82,7 +82,7 @@ GPU_D3D11::GPU_D3D11(GraphicsContext *gfxCtx, Draw::DrawContext *draw)
// No need to flush before the tex scale/offset commands if we are baking
// the tex scale/offset into the vertices anyway.
UpdateCmdInfo();
CheckGPUFeatures();
gstate_c.featureFlags = CheckGPUFeatures();
BuildReportingInfo();
@ -100,25 +100,15 @@ GPU_D3D11::~GPU_D3D11() {
stockD3D11.Destroy();
}
void GPU_D3D11::CheckGPUFeatures() {
u32 features = 0;
features |= GPU_SUPPORTS_BLEND_MINMAX;
u32 GPU_D3D11::CheckGPUFeatures() const {
u32 features = GPUCommon::CheckGPUFeatures();
// Accurate depth is required because the Direct3D API does not support inverse Z.
// So we cannot incorrectly use the viewport transform as the depth range on Direct3D.
// TODO: Breaks text in PaRappa for some reason?
features |= GPU_SUPPORTS_ACCURATE_DEPTH;
#ifndef _M_ARM
// TODO: Do proper feature detection
features |= GPU_SUPPORTS_ANISOTROPY;
#endif
features |= GPU_SUPPORTS_DEPTH_TEXTURE;
features |= GPU_SUPPORTS_TEXTURE_NPOT;
if (draw_->GetDeviceCaps().dualSourceBlend)
features |= GPU_SUPPORTS_DUALSOURCE_BLEND;
if (draw_->GetDeviceCaps().depthClampSupported)
features |= GPU_SUPPORTS_DEPTH_CLAMP;
if (draw_->GetDeviceCaps().clipDistanceSupported)
@ -146,10 +136,6 @@ void GPU_D3D11::CheckGPUFeatures() {
features |= GPU_SUPPORTS_16BIT_FORMATS;
}
if (draw_->GetDeviceCaps().logicOpSupported) {
features |= GPU_SUPPORTS_LOGIC_OP;
}
if (!g_Config.bHighQualityDepth && (features & GPU_SUPPORTS_ACCURATE_DEPTH) != 0) {
features |= GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT;
} else if (PSP_CoreParameter().compat.flags().PixelDepthRounding) {
@ -164,11 +150,7 @@ void GPU_D3D11::CheckGPUFeatures() {
features |= GPU_USE_DEPTH_RANGE_HACK;
}
if (PSP_CoreParameter().compat.flags().ClearToRAM) {
features |= GPU_USE_CLEAR_RAM_HACK;
}
gstate_c.featureFlags = features;
return features;
}
// Needs to be called on GPU thread, not reporting thread.
@ -206,7 +188,7 @@ void GPU_D3D11::BeginHostFrame() {
GPUCommon::BeginHostFrame();
UpdateCmdInfo();
if (resized_) {
CheckGPUFeatures();
gstate_c.featureFlags = CheckGPUFeatures();
framebufferManager_->Resized();
drawEngine_.Resized();
textureCache_->NotifyConfigChanged();

View File

@ -36,7 +36,7 @@ public:
GPU_D3D11(GraphicsContext *gfxCtx, Draw::DrawContext *draw);
~GPU_D3D11();
void CheckGPUFeatures() override;
u32 CheckGPUFeatures() const override;
void PreExecuteOp(u32 op, u32 diff) override;
void ExecuteOp(u32 op, u32 diff) override;

View File

@ -81,7 +81,7 @@ GPU_DX9::GPU_DX9(GraphicsContext *gfxCtx, Draw::DrawContext *draw)
// No need to flush before the tex scale/offset commands if we are baking
// the tex scale/offset into the vertices anyway.
UpdateCmdInfo();
CheckGPUFeatures();
gstate_c.featureFlags = CheckGPUFeatures();
BuildReportingInfo();
@ -155,10 +155,9 @@ static NVIDIAGeneration NVIDIAGetDeviceGeneration(int deviceID) {
return NV_PRE_KEPLER;
}
void GPU_DX9::CheckGPUFeatures() {
u32 features = 0;
u32 GPU_DX9::CheckGPUFeatures() const {
u32 features = GPUCommon::CheckGPUFeatures();
features |= GPU_SUPPORTS_16BIT_FORMATS;
features |= GPU_SUPPORTS_BLEND_MINMAX;
features |= GPU_SUPPORTS_DEPTH_TEXTURE;
features |= GPU_SUPPORTS_TEXTURE_LOD_CONTROL;
@ -187,23 +186,6 @@ void GPU_DX9::CheckGPUFeatures() {
}
}
D3DCAPS9 caps;
ZeroMemory(&caps, sizeof(caps));
HRESULT result = 0;
if (deviceEx_) {
result = deviceEx_->GetDeviceCaps(&caps);
} else {
result = device_->GetDeviceCaps(&caps);
}
if (FAILED(result)) {
WARN_LOG_REPORT(G3D, "Direct3D9: Failed to get the device caps!");
} else {
if ((caps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) != 0 && caps.MaxAnisotropy > 1)
features |= GPU_SUPPORTS_ANISOTROPY;
if ((caps.TextureCaps & (D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_POW2)) == 0)
features |= GPU_SUPPORTS_TEXTURE_NPOT;
}
if (!g_Config.bHighQualityDepth) {
features |= GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT;
} else if (PSP_CoreParameter().compat.flags().PixelDepthRounding) {
@ -213,11 +195,7 @@ void GPU_DX9::CheckGPUFeatures() {
features |= GPU_ROUND_DEPTH_TO_16BIT;
}
if (PSP_CoreParameter().compat.flags().ClearToRAM) {
features |= GPU_USE_CLEAR_RAM_HACK;
}
gstate_c.featureFlags = features;
return features;
}
GPU_DX9::~GPU_DX9() {
@ -261,7 +239,7 @@ void GPU_DX9::BeginHostFrame() {
GPUCommon::BeginHostFrame();
UpdateCmdInfo();
if (resized_) {
CheckGPUFeatures();
gstate_c.featureFlags = CheckGPUFeatures();
framebufferManager_->Resized();
drawEngine_.Resized();
shaderManagerDX9_->DirtyShader();

View File

@ -35,7 +35,7 @@ public:
GPU_DX9(GraphicsContext *gfxCtx, Draw::DrawContext *draw);
~GPU_DX9();
void CheckGPUFeatures() override;
u32 CheckGPUFeatures() const override;
void PreExecuteOp(u32 op, u32 diff) override;
void ExecuteOp(u32 op, u32 diff) override;

View File

@ -54,7 +54,7 @@
GPU_GLES::GPU_GLES(GraphicsContext *gfxCtx, Draw::DrawContext *draw)
: GPUCommon(gfxCtx, draw), drawEngine_(draw), fragmentTestCache_(draw) {
UpdateVsyncInterval(true);
CheckGPUFeatures();
gstate_c.featureFlags = CheckGPUFeatures();
shaderManagerGL_ = new ShaderManagerGLES(draw);
framebufferManagerGL_ = new FramebufferManagerGLES(draw);
@ -148,17 +148,11 @@ GPU_GLES::~GPU_GLES() {
// Take the raw GL extension and versioning data and turn into feature flags.
// TODO: This should use DrawContext::GetDeviceCaps() more and more, and eventually
// this can be shared between all the backends.
void GPU_GLES::CheckGPUFeatures() {
u32 features = 0;
u32 GPU_GLES::CheckGPUFeatures() const {
u32 features = GPUCommon::CheckGPUFeatures();
features |= GPU_SUPPORTS_16BIT_FORMATS;
if (draw_->GetDeviceCaps().dualSourceBlend) {
if (!g_Config.bVendorBugChecksEnabled || !draw_->GetBugs().Has(Draw::Bugs::DUAL_SOURCE_BLENDING_BROKEN)) {
features |= GPU_SUPPORTS_DUALSOURCE_BLEND;
}
}
if (gl_extensions.EXT_shader_framebuffer_fetch || gl_extensions.ARM_shader_framebuffer_fetch) {
// This has caused problems in the past. Let's only enable on GLES3.
if (gl_extensions.GLES3) {
@ -169,15 +163,6 @@ void GPU_GLES::CheckGPUFeatures() {
if ((gl_extensions.gpuVendor == GPU_VENDOR_NVIDIA) || (gl_extensions.gpuVendor == GPU_VENDOR_AMD))
features |= GPU_PREFER_REVERSE_COLOR_ORDER;
if (draw_->GetDeviceCaps().textureNPOTFullySupported)
features |= GPU_SUPPORTS_TEXTURE_NPOT;
if (gl_extensions.EXT_blend_minmax)
features |= GPU_SUPPORTS_BLEND_MINMAX;
if (draw_->GetDeviceCaps().logicOpSupported)
features |= GPU_SUPPORTS_LOGIC_OP;
if (gl_extensions.GLES3 || !gl_extensions.IsGLES)
features |= GPU_SUPPORTS_TEXTURE_LOD_CONTROL;
@ -245,11 +230,7 @@ void GPU_GLES::CheckGPUFeatures() {
features |= GPU_USE_DEPTH_RANGE_HACK;
}
if (PSP_CoreParameter().compat.flags().ClearToRAM) {
features |= GPU_USE_CLEAR_RAM_HACK;
}
gstate_c.featureFlags = features;
return features;
}
bool GPU_GLES::IsReady() {
@ -321,7 +302,7 @@ void GPU_GLES::BeginHostFrame() {
GPUCommon::BeginHostFrame();
UpdateCmdInfo();
if (resized_) {
CheckGPUFeatures();
gstate_c.featureFlags = CheckGPUFeatures();
framebufferManager_->Resized();
drawEngine_.Resized();
shaderManagerGL_->DirtyShader();

View File

@ -38,7 +38,7 @@ public:
~GPU_GLES();
// This gets called on startup and when we get back from settings.
void CheckGPUFeatures() override;
u32 CheckGPUFeatures() const override;
bool IsReady() override;
void CancelReady() override;

View File

@ -3153,3 +3153,30 @@ size_t GPUCommon::FormatGPUStatsCommon(char *buffer, size_t size) {
vertexAverageCycles
);
}
u32 GPUCommon::CheckGPUFeatures() const {
u32 features = 0;
if (draw_->GetDeviceCaps().logicOpSupported) {
features |= GPU_SUPPORTS_LOGIC_OP;
}
if (draw_->GetDeviceCaps().anisoSupported) {
features |= GPU_SUPPORTS_ANISOTROPY;
}
if (draw_->GetDeviceCaps().textureNPOTFullySupported) {
features |= GPU_SUPPORTS_TEXTURE_NPOT;
}
if (draw_->GetDeviceCaps().dualSourceBlend) {
if (!g_Config.bVendorBugChecksEnabled || !draw_->GetBugs().Has(Draw::Bugs::DUAL_SOURCE_BLENDING_BROKEN)) {
features |= GPU_SUPPORTS_DUALSOURCE_BLEND;
}
}
if (draw_->GetDeviceCaps().blendMinMaxSupported) {
features |= GPU_SUPPORTS_BLEND_MINMAX;
}
if (PSP_CoreParameter().compat.flags().ClearToRAM) {
features |= GPU_USE_CLEAR_RAM_HACK;
}
return features;
}

View File

@ -76,7 +76,7 @@ public:
Draw::DrawContext *GetDrawContext() override {
return draw_;
}
virtual void CheckGPUFeatures() = 0;
virtual u32 CheckGPUFeatures() const;
void UpdateCmdInfo();

View File

@ -127,7 +127,7 @@ public:
SoftGPU(GraphicsContext *gfxCtx, Draw::DrawContext *draw);
~SoftGPU();
void CheckGPUFeatures() override {}
u32 CheckGPUFeatures() const override { return 0; }
void InitClear() override {}
void ExecuteOp(u32 op, u32 diff) override;
void FinishDeferred() override;

View File

@ -52,7 +52,7 @@
GPU_Vulkan::GPU_Vulkan(GraphicsContext *gfxCtx, Draw::DrawContext *draw)
: GPUCommon(gfxCtx, draw), drawEngine_(draw) {
CheckGPUFeatures();
gstate_c.featureFlags = CheckGPUFeatures();
VulkanContext *vulkan = (VulkanContext *)gfxCtx->GetAPIContext();
@ -182,8 +182,8 @@ GPU_Vulkan::~GPU_Vulkan() {
delete framebufferManagerVulkan_;
}
void GPU_Vulkan::CheckGPUFeatures() {
uint32_t features = 0;
u32 GPU_Vulkan::CheckGPUFeatures() const {
uint32_t features = GPUCommon::CheckGPUFeatures();
VulkanContext *vulkan = (VulkanContext *)draw_->GetNativeObject(Draw::NativeObject::CONTEXT);
switch (vulkan->GetPhysicalDeviceProperties().properties.vendorID) {
@ -222,8 +222,6 @@ void GPU_Vulkan::CheckGPUFeatures() {
// Mandatory features on Vulkan, which may be checked in "centralized" code
features |= GPU_SUPPORTS_TEXTURE_LOD_CONTROL;
features |= GPU_SUPPORTS_BLEND_MINMAX;
features |= GPU_SUPPORTS_TEXTURE_NPOT;
features |= GPU_SUPPORTS_INSTANCE_RENDERING;
features |= GPU_SUPPORTS_VERTEX_TEXTURE_FETCH;
features |= GPU_SUPPORTS_TEXTURE_FLOAT;
@ -254,17 +252,6 @@ void GPU_Vulkan::CheckGPUFeatures() {
features |= GPU_SUPPORTS_VS_RANGE_CULLING;
}
}
if (enabledFeatures.dualSrcBlend) {
if (!g_Config.bVendorBugChecksEnabled || !draw_->GetBugs().Has(Draw::Bugs::DUAL_SOURCE_BLENDING_BROKEN)) {
features |= GPU_SUPPORTS_DUALSOURCE_BLEND;
}
}
if (draw_->GetDeviceCaps().logicOpSupported) {
features |= GPU_SUPPORTS_LOGIC_OP;
}
if (draw_->GetDeviceCaps().anisoSupported) {
features |= GPU_SUPPORTS_ANISOTROPY;
}
// These are VULKAN_4444_FORMAT and friends.
uint32_t fmt4444 = draw_->GetDataFormatSupport(Draw::DataFormat::B4G4R4A4_UNORM_PACK16);
@ -280,10 +267,6 @@ void GPU_Vulkan::CheckGPUFeatures() {
INFO_LOG(G3D, "Deficient texture format support: 4444: %d 1555: %d 565: %d", fmt4444, fmt1555, fmt565);
}
if (PSP_CoreParameter().compat.flags().ClearToRAM) {
features |= GPU_USE_CLEAR_RAM_HACK;
}
if (!g_Config.bHighQualityDepth && (features & GPU_SUPPORTS_ACCURATE_DEPTH) != 0) {
features |= GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT;
}
@ -295,7 +278,7 @@ void GPU_Vulkan::CheckGPUFeatures() {
features |= GPU_ROUND_DEPTH_TO_16BIT;
}
gstate_c.featureFlags = features;
return features;
}
void GPU_Vulkan::BeginHostFrame() {
@ -303,7 +286,7 @@ void GPU_Vulkan::BeginHostFrame() {
UpdateCmdInfo();
if (resized_) {
CheckGPUFeatures();
gstate_c.featureFlags = CheckGPUFeatures();
// In case the GPU changed.
BuildReportingInfo();
framebufferManager_->Resized();
@ -542,7 +525,7 @@ void GPU_Vulkan::DeviceRestore() {
GPUCommon::DeviceRestore();
InitDeviceObjects();
CheckGPUFeatures();
gstate_c.featureFlags = CheckGPUFeatures();
BuildReportingInfo();
UpdateCmdInfo();

View File

@ -38,7 +38,7 @@ public:
~GPU_Vulkan();
// This gets called on startup and when we get back from settings.
void CheckGPUFeatures() override;
u32 CheckGPUFeatures() const override;
bool IsReady() override;
void CancelReady() override;