mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-13 09:39:33 +01:00
Merge pull request #16059 from hrydgard/unify-gpu-feature-flags
Unify many GPU feature flags
This commit is contained in:
16 files changed
+181
-244
No files matched your search
@@ -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));
|
||||
|
||||
@@ -646,6 +646,63 @@ void D3D9Context::InvalidateCachedState() {
|
||||
curPipeline_ = nullptr;
|
||||
}
|
||||
|
||||
// TODO: Move this detection elsewhere when it's needed elsewhere, not before. It's ugly.
|
||||
// Source: https://envytools.readthedocs.io/en/latest/hw/pciid.html#gf100
|
||||
enum NVIDIAGeneration {
|
||||
NV_PRE_KEPLER,
|
||||
NV_KEPLER,
|
||||
NV_MAXWELL,
|
||||
NV_PASCAL,
|
||||
NV_VOLTA,
|
||||
NV_TURING, // or later
|
||||
};
|
||||
|
||||
static NVIDIAGeneration NVIDIAGetDeviceGeneration(int deviceID) {
|
||||
if (deviceID >= 0x1180 && deviceID <= 0x11bf)
|
||||
return NV_KEPLER; // GK104
|
||||
if (deviceID >= 0x11c0 && deviceID <= 0x11fa)
|
||||
return NV_KEPLER; // GK106
|
||||
if (deviceID >= 0x0fc0 && deviceID <= 0x0fff)
|
||||
return NV_KEPLER; // GK107
|
||||
if (deviceID >= 0x1003 && deviceID <= 0x1028)
|
||||
return NV_KEPLER; // GK110(B)
|
||||
if (deviceID >= 0x1280 && deviceID <= 0x12ba)
|
||||
return NV_KEPLER; // GK208
|
||||
if (deviceID >= 0x1381 && deviceID <= 0x13b0)
|
||||
return NV_MAXWELL; // GM107
|
||||
if (deviceID >= 0x1340 && deviceID <= 0x134d)
|
||||
return NV_MAXWELL; // GM108
|
||||
if (deviceID >= 0x13c0 && deviceID <= 0x13d9)
|
||||
return NV_MAXWELL; // GM204
|
||||
if (deviceID >= 0x1401 && deviceID <= 0x1427)
|
||||
return NV_MAXWELL; // GM206
|
||||
if (deviceID >= 0x15f7 && deviceID <= 0x15f9)
|
||||
return NV_PASCAL; // GP100
|
||||
if (deviceID >= 0x15f7 && deviceID <= 0x15f9)
|
||||
return NV_PASCAL; // GP100
|
||||
if (deviceID >= 0x1b00 && deviceID <= 0x1b38)
|
||||
return NV_PASCAL; // GP102
|
||||
if (deviceID >= 0x1b80 && deviceID <= 0x1be1)
|
||||
return NV_PASCAL; // GP104
|
||||
if (deviceID >= 0x1c02 && deviceID <= 0x1c62)
|
||||
return NV_PASCAL; // GP106
|
||||
if (deviceID >= 0x1c81 && deviceID <= 0x1c92)
|
||||
return NV_PASCAL; // GP107
|
||||
if (deviceID >= 0x1d01 && deviceID <= 0x1d12)
|
||||
return NV_PASCAL; // GP108
|
||||
if (deviceID >= 0x1d81 && deviceID <= 0x1dba)
|
||||
return NV_VOLTA; // GV100
|
||||
if (deviceID >= 0x1e02 && deviceID <= 0x1e3c)
|
||||
return NV_TURING; // TU102
|
||||
if (deviceID >= 0x1e82 && deviceID <= 0x1ed0)
|
||||
return NV_TURING; // TU104
|
||||
if (deviceID >= 0x1f02 && deviceID <= 0x1f51)
|
||||
return NV_TURING; // TU104
|
||||
if (deviceID >= 0x1e02)
|
||||
return NV_TURING; // More TU models or later, probably.
|
||||
return NV_PRE_KEPLER;
|
||||
}
|
||||
|
||||
#define FB_DIV 1
|
||||
#define FOURCC_INTZ ((D3DFORMAT)(MAKEFOURCC('I', 'N', 'T', 'Z')))
|
||||
|
||||
@@ -665,14 +722,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 +751,30 @@ 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;
|
||||
}
|
||||
|
||||
// VS range culling (killing triangles in the vertex shader using NaN) causes problems on Intel.
|
||||
// Also causes problems on old NVIDIA.
|
||||
switch (caps_.vendor) {
|
||||
case Draw::GPUVendor::VENDOR_INTEL:
|
||||
bugs_.Infest(Bugs::BROKEN_NAN_IN_CONDITIONAL);
|
||||
break;
|
||||
case Draw::GPUVendor::VENDOR_NVIDIA:
|
||||
// Older NVIDIAs don't seem to like NaNs in their DX9 vertex shaders.
|
||||
// No idea if KEPLER is the right cutoff, but let's go with it.
|
||||
if (NVIDIAGetDeviceGeneration(caps_.deviceID) < NV_KEPLER) {
|
||||
bugs_.Infest(Bugs::BROKEN_NAN_IN_CONDITIONAL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (d3d) {
|
||||
D3DDISPLAYMODE displayMode;
|
||||
|
||||
@@ -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;
|
||||
@@ -711,8 +713,10 @@ OpenGLContext::OpenGLContext() {
|
||||
}
|
||||
}
|
||||
|
||||
if (gl_extensions.IsGLES) {
|
||||
// NOTE: We only support framebuffer fetch on ES3 due to past issues..
|
||||
if (gl_extensions.IsGLES && gl_extensions.GLES3) {
|
||||
caps_.framebufferFetchSupported = (gl_extensions.EXT_shader_framebuffer_fetch || gl_extensions.ARM_shader_framebuffer_fetch);
|
||||
|
||||
if (gl_extensions.EXT_shader_framebuffer_fetch) {
|
||||
shaderLanguageDesc_.framebufferFetchExtension = "#extension GL_EXT_shader_framebuffer_fetch : require";
|
||||
shaderLanguageDesc_.lastFragData = gl_extensions.GLES3 ? "fragColor0" : "gl_LastFragData[0]";
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
};
|
||||
|
||||
+5
-37
@@ -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,40 +100,16 @@ 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)
|
||||
features |= GPU_SUPPORTS_CLIP_DISTANCE;
|
||||
if (draw_->GetDeviceCaps().cullDistanceSupported)
|
||||
features |= GPU_SUPPORTS_CULL_DISTANCE;
|
||||
if (!draw_->GetBugs().Has(Draw::Bugs::BROKEN_NAN_IN_CONDITIONAL)) {
|
||||
// Ignore the compat setting if clip and cull are both enabled.
|
||||
// When supported, we can do the depth side of range culling more correctly.
|
||||
const bool supported = draw_->GetDeviceCaps().clipDistanceSupported && draw_->GetDeviceCaps().cullDistanceSupported;
|
||||
const bool disabled = PSP_CoreParameter().compat.flags().DisableRangeCulling;
|
||||
if (supported || !disabled) {
|
||||
features |= GPU_SUPPORTS_VS_RANGE_CULLING;
|
||||
}
|
||||
}
|
||||
|
||||
features |= GPU_SUPPORTS_TEXTURE_FLOAT;
|
||||
features |= GPU_SUPPORTS_INSTANCE_RENDERING;
|
||||
@@ -146,10 +122,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 +136,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 +174,7 @@ void GPU_D3D11::BeginHostFrame() {
|
||||
GPUCommon::BeginHostFrame();
|
||||
UpdateCmdInfo();
|
||||
if (resized_) {
|
||||
CheckGPUFeatures();
|
||||
gstate_c.featureFlags = CheckGPUFeatures();
|
||||
framebufferManager_->Resized();
|
||||
drawEngine_.Resized();
|
||||
textureCache_->NotifyConfigChanged();
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
+5
-103
@@ -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();
|
||||
|
||||
@@ -98,68 +98,9 @@ GPU_DX9::GPU_DX9(GraphicsContext *gfxCtx, Draw::DrawContext *draw)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Move this detection elsewhere when it's needed elsewhere, not before. It's ugly.
|
||||
// Source: https://envytools.readthedocs.io/en/latest/hw/pciid.html#gf100
|
||||
enum NVIDIAGeneration {
|
||||
NV_PRE_KEPLER,
|
||||
NV_KEPLER,
|
||||
NV_MAXWELL,
|
||||
NV_PASCAL,
|
||||
NV_VOLTA,
|
||||
NV_TURING, // or later
|
||||
};
|
||||
|
||||
static NVIDIAGeneration NVIDIAGetDeviceGeneration(int deviceID) {
|
||||
if (deviceID >= 0x1180 && deviceID <= 0x11bf)
|
||||
return NV_KEPLER; // GK104
|
||||
if (deviceID >= 0x11c0 && deviceID <= 0x11fa)
|
||||
return NV_KEPLER; // GK106
|
||||
if (deviceID >= 0x0fc0 && deviceID <= 0x0fff)
|
||||
return NV_KEPLER; // GK107
|
||||
if (deviceID >= 0x1003 && deviceID <= 0x1028)
|
||||
return NV_KEPLER; // GK110(B)
|
||||
if (deviceID >= 0x1280 && deviceID <= 0x12ba)
|
||||
return NV_KEPLER; // GK208
|
||||
if (deviceID >= 0x1381 && deviceID <= 0x13b0)
|
||||
return NV_MAXWELL; // GM107
|
||||
if (deviceID >= 0x1340 && deviceID <= 0x134d)
|
||||
return NV_MAXWELL; // GM108
|
||||
if (deviceID >= 0x13c0 && deviceID <= 0x13d9)
|
||||
return NV_MAXWELL; // GM204
|
||||
if (deviceID >= 0x1401 && deviceID <= 0x1427)
|
||||
return NV_MAXWELL; // GM206
|
||||
if (deviceID >= 0x15f7 && deviceID <= 0x15f9)
|
||||
return NV_PASCAL; // GP100
|
||||
if (deviceID >= 0x15f7 && deviceID <= 0x15f9)
|
||||
return NV_PASCAL; // GP100
|
||||
if (deviceID >= 0x1b00 && deviceID <= 0x1b38)
|
||||
return NV_PASCAL; // GP102
|
||||
if (deviceID >= 0x1b80 && deviceID <= 0x1be1)
|
||||
return NV_PASCAL; // GP104
|
||||
if (deviceID >= 0x1c02 && deviceID <= 0x1c62)
|
||||
return NV_PASCAL; // GP106
|
||||
if (deviceID >= 0x1c81 && deviceID <= 0x1c92)
|
||||
return NV_PASCAL; // GP107
|
||||
if (deviceID >= 0x1d01 && deviceID <= 0x1d12)
|
||||
return NV_PASCAL; // GP108
|
||||
if (deviceID >= 0x1d81 && deviceID <= 0x1dba)
|
||||
return NV_VOLTA; // GV100
|
||||
if (deviceID >= 0x1e02 && deviceID <= 0x1e3c)
|
||||
return NV_TURING; // TU102
|
||||
if (deviceID >= 0x1e82 && deviceID <= 0x1ed0)
|
||||
return NV_TURING; // TU104
|
||||
if (deviceID >= 0x1f02 && deviceID <= 0x1f51)
|
||||
return NV_TURING; // TU104
|
||||
if (deviceID >= 0x1e02)
|
||||
return NV_TURING; // More TU models or later, probably.
|
||||
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;
|
||||
|
||||
// Accurate depth is required because the Direct3D API does not support inverse Z.
|
||||
@@ -168,41 +109,6 @@ void GPU_DX9::CheckGPUFeatures() {
|
||||
features |= GPU_SUPPORTS_ACCURATE_DEPTH;
|
||||
|
||||
auto vendor = draw_->GetDeviceCaps().vendor;
|
||||
if (!PSP_CoreParameter().compat.flags().DisableRangeCulling) {
|
||||
// VS range culling (killing triangles in the vertex shader using NaN) causes problems on Intel.
|
||||
// Also causes problems on old NVIDIA.
|
||||
switch (vendor) {
|
||||
case Draw::GPUVendor::VENDOR_INTEL:
|
||||
break;
|
||||
case Draw::GPUVendor::VENDOR_NVIDIA:
|
||||
// Older NVIDIAs don't seem to like NaNs in their DX9 vertex shaders.
|
||||
// No idea if KEPLER is the right cutoff, but let's go with it.
|
||||
if (NVIDIAGetDeviceGeneration(draw_->GetDeviceCaps().deviceID) >= NV_KEPLER) {
|
||||
features |= GPU_SUPPORTS_VS_RANGE_CULLING;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
features |= GPU_SUPPORTS_VS_RANGE_CULLING;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -213,11 +119,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 +163,7 @@ void GPU_DX9::BeginHostFrame() {
|
||||
GPUCommon::BeginHostFrame();
|
||||
UpdateCmdInfo();
|
||||
if (resized_) {
|
||||
CheckGPUFeatures();
|
||||
gstate_c.featureFlags = CheckGPUFeatures();
|
||||
framebufferManager_->Resized();
|
||||
drawEngine_.Resized();
|
||||
shaderManagerDX9_->DirtyShader();
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
+5
-49
@@ -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,42 +148,17 @@ 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) {
|
||||
features |= GPU_SUPPORTS_ANY_FRAMEBUFFER_FETCH;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (draw_->GetDeviceCaps().anisoSupported)
|
||||
features |= GPU_SUPPORTS_ANISOTROPY;
|
||||
|
||||
bool canUseInstanceID = gl_extensions.EXT_draw_instanced || gl_extensions.ARB_draw_instanced;
|
||||
bool canDefInstanceID = gl_extensions.IsGLES || gl_extensions.EXT_gpu_shader4 || gl_extensions.VersionGEThan(3, 1);
|
||||
bool instanceRendering = gl_extensions.GLES3 || (canUseInstanceID && canDefInstanceID);
|
||||
@@ -202,21 +177,6 @@ void GPU_GLES::CheckGPUFeatures() {
|
||||
// Our implementation of depth texturing needs simple Z range, so can't
|
||||
// use the extension hacks (yet).
|
||||
}
|
||||
if (draw_->GetDeviceCaps().textureDepthSupported)
|
||||
features |= GPU_SUPPORTS_DEPTH_TEXTURE;
|
||||
if (draw_->GetDeviceCaps().clipDistanceSupported)
|
||||
features |= GPU_SUPPORTS_CLIP_DISTANCE;
|
||||
if (draw_->GetDeviceCaps().cullDistanceSupported)
|
||||
features |= GPU_SUPPORTS_CULL_DISTANCE;
|
||||
if (!draw_->GetBugs().Has(Draw::Bugs::BROKEN_NAN_IN_CONDITIONAL)) {
|
||||
// Ignore the compat setting if clip and cull are both enabled.
|
||||
// When supported, we can do the depth side of range culling more correctly.
|
||||
const bool supported = draw_->GetDeviceCaps().clipDistanceSupported && draw_->GetDeviceCaps().cullDistanceSupported;
|
||||
const bool disabled = PSP_CoreParameter().compat.flags().DisableRangeCulling;
|
||||
if (supported || !disabled) {
|
||||
features |= GPU_SUPPORTS_VS_RANGE_CULLING;
|
||||
}
|
||||
}
|
||||
|
||||
// If we already have a 16-bit depth buffer, we don't need to round.
|
||||
bool prefer24 = draw_->GetDeviceCaps().preferredDepthBufferFormat == Draw::DataFormat::D24_S8;
|
||||
@@ -245,11 +205,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 +277,7 @@ void GPU_GLES::BeginHostFrame() {
|
||||
GPUCommon::BeginHostFrame();
|
||||
UpdateCmdInfo();
|
||||
if (resized_) {
|
||||
CheckGPUFeatures();
|
||||
gstate_c.featureFlags = CheckGPUFeatures();
|
||||
framebufferManager_->Resized();
|
||||
drawEngine_.Resized();
|
||||
shaderManagerGL_->DirtyShader();
|
||||
|
||||
+1
-1
@@ -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;
|
||||
|
||||
@@ -3153,3 +3153,56 @@ 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 (draw_->GetDeviceCaps().clipDistanceSupported) {
|
||||
features |= GPU_SUPPORTS_CLIP_DISTANCE;
|
||||
}
|
||||
|
||||
if (draw_->GetDeviceCaps().cullDistanceSupported) {
|
||||
features |= GPU_SUPPORTS_CULL_DISTANCE;
|
||||
}
|
||||
|
||||
if (draw_->GetDeviceCaps().textureDepthSupported) {
|
||||
features |= GPU_SUPPORTS_DEPTH_TEXTURE;
|
||||
}
|
||||
|
||||
if (!draw_->GetBugs().Has(Draw::Bugs::BROKEN_NAN_IN_CONDITIONAL)) {
|
||||
// Ignore the compat setting if clip and cull are both enabled.
|
||||
// When supported, we can do the depth side of range culling more correctly.
|
||||
const bool supported = draw_->GetDeviceCaps().clipDistanceSupported && draw_->GetDeviceCaps().cullDistanceSupported;
|
||||
const bool disabled = PSP_CoreParameter().compat.flags().DisableRangeCulling;
|
||||
if (supported || !disabled) {
|
||||
features |= GPU_SUPPORTS_VS_RANGE_CULLING;
|
||||
}
|
||||
}
|
||||
|
||||
if (draw_->GetDeviceCaps().framebufferFetchSupported) {
|
||||
features |= GPU_SUPPORTS_ANY_FRAMEBUFFER_FETCH;
|
||||
}
|
||||
|
||||
if (PSP_CoreParameter().compat.flags().ClearToRAM) {
|
||||
features |= GPU_USE_CLEAR_RAM_HACK;
|
||||
}
|
||||
|
||||
return features;
|
||||
}
|
||||
+1
-1
@@ -76,7 +76,7 @@ public:
|
||||
Draw::DrawContext *GetDrawContext() override {
|
||||
return draw_;
|
||||
}
|
||||
virtual void CheckGPUFeatures() = 0;
|
||||
virtual u32 CheckGPUFeatures() const;
|
||||
|
||||
void UpdateCmdInfo();
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,49 +222,14 @@ 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;
|
||||
features |= GPU_SUPPORTS_DEPTH_TEXTURE;
|
||||
|
||||
// through input attachments, when not broken.
|
||||
if (draw_->GetDeviceCaps().framebufferFetchSupported) {
|
||||
features |= GPU_SUPPORTS_ANY_FRAMEBUFFER_FETCH;
|
||||
}
|
||||
|
||||
auto &enabledFeatures = vulkan->GetDeviceFeatures().enabled;
|
||||
if (enabledFeatures.depthClamp) {
|
||||
features |= GPU_SUPPORTS_DEPTH_CLAMP;
|
||||
}
|
||||
if (enabledFeatures.shaderClipDistance) {
|
||||
features |= GPU_SUPPORTS_CLIP_DISTANCE;
|
||||
}
|
||||
if (enabledFeatures.shaderCullDistance) {
|
||||
// Must support at least 8 if feature supported, so we're fine.
|
||||
features |= GPU_SUPPORTS_CULL_DISTANCE;
|
||||
}
|
||||
if (!draw_->GetBugs().Has(Draw::Bugs::BROKEN_NAN_IN_CONDITIONAL)) {
|
||||
// Ignore the compat setting if clip and cull are both enabled.
|
||||
// When supported, we can do the depth side of range culling more correctly.
|
||||
const bool supported = draw_->GetDeviceCaps().clipDistanceSupported && draw_->GetDeviceCaps().cullDistanceSupported;
|
||||
const bool disabled = PSP_CoreParameter().compat.flags().DisableRangeCulling;
|
||||
if (supported || !disabled) {
|
||||
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 +245,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 +256,7 @@ void GPU_Vulkan::CheckGPUFeatures() {
|
||||
features |= GPU_ROUND_DEPTH_TO_16BIT;
|
||||
}
|
||||
|
||||
gstate_c.featureFlags = features;
|
||||
return features;
|
||||
}
|
||||
|
||||
void GPU_Vulkan::BeginHostFrame() {
|
||||
@@ -303,7 +264,7 @@ void GPU_Vulkan::BeginHostFrame() {
|
||||
UpdateCmdInfo();
|
||||
|
||||
if (resized_) {
|
||||
CheckGPUFeatures();
|
||||
gstate_c.featureFlags = CheckGPUFeatures();
|
||||
// In case the GPU changed.
|
||||
BuildReportingInfo();
|
||||
framebufferManager_->Resized();
|
||||
@@ -542,7 +503,7 @@ void GPU_Vulkan::DeviceRestore() {
|
||||
GPUCommon::DeviceRestore();
|
||||
InitDeviceObjects();
|
||||
|
||||
CheckGPUFeatures();
|
||||
gstate_c.featureFlags = CheckGPUFeatures();
|
||||
BuildReportingInfo();
|
||||
UpdateCmdInfo();
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in new issue
Block a user