mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-01 14:58:14 +00:00
OpenGL: Improve checks for fragment shader float precision.
Fixes #22001 (although there may be other artifacts).
This commit is contained in:
1 parent
683704d61d
commit
10a5d2f810
10 files changed
+49
-17
No files matched your search
@@ -297,6 +297,7 @@ D3D11DrawContext::D3D11DrawContext(ComPtr<ID3D11Device> device, ComPtr<ID3D11Dev
|
||||
_assert_(featureLevel_ >= D3D_FEATURE_LEVEL_9_3);
|
||||
|
||||
caps_.coordConvention = CoordConvention::Direct3D11;
|
||||
caps_.fragmentShaderFullPrecisionFloat = true;
|
||||
|
||||
switch (featureLevel_) {
|
||||
case D3D_FEATURE_LEVEL_11_1:
|
||||
|
||||
@@ -494,7 +494,7 @@ bool CheckGLExtensions() {
|
||||
GL_LOW_FLOAT, GL_MEDIUM_FLOAT, GL_HIGH_FLOAT,
|
||||
GL_LOW_INT, GL_MEDIUM_INT, GL_HIGH_INT
|
||||
};
|
||||
GLint shaderTypes[2] = {
|
||||
const GLint shaderTypes[2] = {
|
||||
GL_VERTEX_SHADER, GL_FRAGMENT_SHADER
|
||||
};
|
||||
for (int st = 0; st < 2; st++) {
|
||||
|
||||
@@ -138,6 +138,15 @@ struct GLExtensions {
|
||||
// greater-or-equal than
|
||||
bool VersionGEThan(int major, int minor, int sub = 0);
|
||||
int GLSLVersion();
|
||||
|
||||
bool FullPrecisionIntInFragment() const {
|
||||
return range[1][5][0] >= 30 && range[1][5][1] >= 30;
|
||||
}
|
||||
|
||||
// If 23, normal floats are supported.
|
||||
int HighpFragmentFloatMantissaBits() const {
|
||||
return precision[1][2];
|
||||
}
|
||||
};
|
||||
|
||||
extern GLExtensions gl_extensions;
|
||||
|
||||
@@ -561,11 +561,11 @@ OpenGLContext::OpenGLContext(bool canChangeSwapInterval) : renderManager_(frameT
|
||||
} else {
|
||||
caps_.preferredDepthBufferFormat = DataFormat::D16;
|
||||
}
|
||||
if (gl_extensions.FullPrecisionIntInFragment()) {
|
||||
caps_.fragmentShaderInt32Supported = true;
|
||||
}
|
||||
if (gl_extensions.GLES3) {
|
||||
// Mali reports 30 but works fine...
|
||||
if (gl_extensions.range[1][5][1] >= 30) {
|
||||
caps_.fragmentShaderInt32Supported = true;
|
||||
}
|
||||
// 30 is an ok value for the max since it's 2^31-1, which is the max value for a signed int. NVIDIA also reports this.
|
||||
caps_.samplerLodControl = true;
|
||||
}
|
||||
caps_.texture3DSupported = gl_extensions.GLES3 || gl_extensions.OES_texture_3D;
|
||||
@@ -574,12 +574,17 @@ OpenGLContext::OpenGLContext(bool canChangeSwapInterval) : renderManager_(frameT
|
||||
if (gl_extensions.VersionGEThan(3, 3, 0)) {
|
||||
caps_.fragmentShaderInt32Supported = true;
|
||||
}
|
||||
caps_.fragmentShaderFullPrecisionFloat = true;
|
||||
caps_.preferredDepthBufferFormat = DataFormat::D24_S8;
|
||||
caps_.texture3DSupported = true;
|
||||
caps_.textureDepthSupported = true;
|
||||
caps_.samplerLodControl = true;
|
||||
}
|
||||
|
||||
if (gl_extensions.HighpFragmentFloatMantissaBits() >= 23 && !(gl_extensions.bugs & BUG_PVR_SHADER_PRECISION_TERRIBLE)) {
|
||||
caps_.fragmentShaderFullPrecisionFloat = true;
|
||||
}
|
||||
|
||||
caps_.maxTextureSize = gl_extensions.maxTextureSize;
|
||||
caps_.coordConvention = CoordConvention::OpenGL;
|
||||
caps_.setMaxFrameLatencySupported = true;
|
||||
|
||||
@@ -918,6 +918,7 @@ VKContext::VKContext(VulkanContext *vulkan, bool useRenderThread)
|
||||
// Make sure that the surface has been initialized.
|
||||
_dbg_assert_(vulkan->GetAvailablePresentModes().size() > 0);
|
||||
|
||||
caps_.fragmentShaderFullPrecisionFloat = true;
|
||||
caps_.coordConvention = CoordConvention::Vulkan;
|
||||
caps_.setMaxFrameLatencySupported = true;
|
||||
caps_.anisoSupported = vulkan->GetDeviceFeatures().enabled.standard.samplerAnisotropy != 0;
|
||||
|
||||
@@ -612,6 +612,7 @@ struct DeviceCaps {
|
||||
bool framebufferStencilBlitSupported;
|
||||
bool framebufferFetchSupported;
|
||||
bool texture3DSupported;
|
||||
bool fragmentShaderFullPrecisionFloat; // Without this, our clip plane workaround doesn't work
|
||||
bool fragmentShaderInt32Supported;
|
||||
bool fragmentShaderDepthWriteSupported;
|
||||
bool fragmentShaderStencilWriteSupported;
|
||||
|
||||
+18
-10
@@ -138,11 +138,15 @@ void ComputeVertexShaderID(VShaderID *id_out, u32 vertType, bool useHWTransform,
|
||||
id.SetBit(VS_BIT_NORM_REVERSE, gstate.areNormalsReversed());
|
||||
}
|
||||
|
||||
if (clipInfoFlags & ClipInfoFlags::DepthClampFragment) {
|
||||
id.SetBit(VS_BIT_FS_DEPTH_CLAMP);
|
||||
}
|
||||
if (clipInfoFlags & ClipInfoFlags::MinMaxZDiscard) {
|
||||
id.SetBit(VS_BIT_FS_MINMAX_DISCARD);
|
||||
if (gstate_c.Use(GPU_USE_FULL_PRECISION_IN_FRAGMENT)) {
|
||||
if (clipInfoFlags & ClipInfoFlags::DepthClampFragment) {
|
||||
id.SetBit(VS_BIT_FS_DEPTH_CLAMP);
|
||||
}
|
||||
if (clipInfoFlags & ClipInfoFlags::MinMaxZDiscard) {
|
||||
id.SetBit(VS_BIT_FS_MINMAX_DISCARD);
|
||||
}
|
||||
} else {
|
||||
// TODO: We're gonna need to soft-clip... Ugh.
|
||||
}
|
||||
|
||||
id.SetBit(VS_BIT_FLATSHADE, doFlatShading);
|
||||
@@ -286,11 +290,15 @@ void ComputeFragmentShaderID(FShaderID *id_out, const ComputedPipelineState &pip
|
||||
|
||||
// NOTE: This check MUST be identical to the one in ComputeVertexShaderID, otherwise we might get mismatches between VS and FS and end up with no shader at all.
|
||||
if (!isModeThrough) {
|
||||
if (clipInfoFlags & ClipInfoFlags::DepthClampFragment) {
|
||||
id.SetBit(FS_BIT_DEPTH_CLAMP);
|
||||
}
|
||||
if (clipInfoFlags & ClipInfoFlags::MinMaxZDiscard) {
|
||||
id.SetBit(FS_BIT_MINMAX_DISCARD);
|
||||
if (gstate_c.Use(GPU_USE_FULL_PRECISION_IN_FRAGMENT)) {
|
||||
if (clipInfoFlags & ClipInfoFlags::DepthClampFragment) {
|
||||
id.SetBit(FS_BIT_DEPTH_CLAMP);
|
||||
}
|
||||
if (clipInfoFlags & ClipInfoFlags::MinMaxZDiscard) {
|
||||
id.SetBit(FS_BIT_MINMAX_DISCARD);
|
||||
}
|
||||
} else {
|
||||
// TODO: We're gonna need to soft-clip... Ugh.
|
||||
}
|
||||
} else {
|
||||
_dbg_assert_(0 == (clipInfoFlags & (ClipInfoFlags::DepthClampFragment | ClipInfoFlags::MinMaxZDiscard)));
|
||||
|
||||
@@ -578,6 +578,10 @@ u32 GPUCommonHW::CheckGPUFeatures() const {
|
||||
features |= GPU_USE_CULL_DISTANCE;
|
||||
}
|
||||
|
||||
if (draw_->GetDeviceCaps().fragmentShaderFullPrecisionFloat) {
|
||||
features |= GPU_USE_FULL_PRECISION_IN_FRAGMENT;
|
||||
}
|
||||
|
||||
if (draw_->GetDeviceCaps().depthClampSupported) {
|
||||
features |= GPU_USE_DEPTH_CLAMP;
|
||||
}
|
||||
|
||||
+1
-1
@@ -483,7 +483,7 @@ enum : u32 {
|
||||
// Free bit: 18
|
||||
GPU_USE_FRAMEBUFFER_ARRAYS = FLAG_BIT(19),
|
||||
GPU_USE_FRAMEBUFFER_FETCH = FLAG_BIT(20),
|
||||
// Free bit: 21
|
||||
GPU_USE_FULL_PRECISION_IN_FRAGMENT = FLAG_BIT(21), // Required for the min-max/depthclamp in fragment shader stuff
|
||||
GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT = FLAG_BIT(22),
|
||||
GPU_ROUND_DEPTH_TO_16BIT = FLAG_BIT(23), // Can be disabled either per game or if we use a real 16-bit depth buffer
|
||||
GPU_USE_CLIP_DISTANCE = FLAG_BIT(24),
|
||||
|
||||
@@ -184,6 +184,8 @@ void SystemInfoScreen::CreateDeviceInfoTab(UI::LinearLayout *deviceSpecs) {
|
||||
const int highp_int_max = gl_extensions.range[1][5][1];
|
||||
const int highp_float_min = gl_extensions.range[1][2][0];
|
||||
const int highp_float_max = gl_extensions.range[1][2][1];
|
||||
const int highp_int_precision = gl_extensions.precision[1][5];
|
||||
const int highp_float_precision = gl_extensions.precision[1][2];
|
||||
if (highp_int_max != 0) {
|
||||
char temp[128];
|
||||
snprintf(temp, sizeof(temp), "%d-%d", highp_int_min, highp_int_max);
|
||||
@@ -191,7 +193,8 @@ void SystemInfoScreen::CreateDeviceInfoTab(UI::LinearLayout *deviceSpecs) {
|
||||
}
|
||||
if (highp_float_max != 0) {
|
||||
char temp[128];
|
||||
snprintf(temp, sizeof(temp), "%d-%d", highp_float_min, highp_float_max);
|
||||
// if highp_float_precision is 23, full floats are available which is good.
|
||||
snprintf(temp, sizeof(temp), "%d-%d (%d bits)", highp_float_min, highp_float_max, highp_float_precision);
|
||||
gpuInfo->Add(new InfoItem(si->T("High precision float range"), temp));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user