diff --git a/src/engine/renderer/DetectGLVendors.cpp b/src/engine/renderer/DetectGLVendors.cpp index 93326acb72..1166569a26 100644 --- a/src/engine/renderer/DetectGLVendors.cpp +++ b/src/engine/renderer/DetectGLVendors.cpp @@ -44,9 +44,11 @@ std::string GetGLHardwareVendorName( glHardwareVendor_t hardwareVendor ) "Arm", "AMD/ATI", "Broadcom", + "Imagination", "Intel", - "Nvidia", "Moore Threads", + "Nvidia", + "Zhaoxin", "OutOfRange", }; @@ -69,10 +71,13 @@ std::string GetGLDriverVendorName( glDriverVendor_t driverVendor ) "Unknown", "Apple", "AMD/ATI", + "GL4ES", + "Imagination", "Intel", "Mesa", - "Nvidia", "Moore Threads", + "Nvidia", + "Zhaoxin", "OutOfRange", }; @@ -89,6 +94,16 @@ std::string GetGLDriverVendorName( glDriverVendor_t driverVendor ) return driverVendorNames[ index ]; } +static std::string StripPrefix( const std::string &prefix, const std::string &string ) +{ + if ( Str::IsPrefix( prefix, string ) ) + { + return string.substr( prefix.length() ); + } + + return string; +} + void DetectGLVendors( const std::string& vendorString, const std::string& versionString, @@ -123,15 +138,19 @@ void DetectGLVendors( { "nouveau", { glDriverVendor_t::MESA, glHardwareVendor_t::NVIDIA } }, // Proprietary Nvidia drivers on all systems like Linux, Windows, and macOS. { "NVIDIA Corporation", { glDriverVendor_t::NVIDIA, glHardwareVendor_t::NVIDIA } }, - // Moore Threads drivers on Linux and Windows. + // Proprietary Moore Threads drivers on Linux and Windows. { "Moore Threads", { glDriverVendor_t::MTHREADS, glHardwareVendor_t::MTHREADS } }, + // Proprietary Zhaoxin driver on Linux. + { "Shanghai Zhaoxin Semiconductor Co., Ltd.", { glDriverVendor_t::ZHAOXIN, glHardwareVendor_t::ZHAOXIN } }, + // Proprietary Imagination driver for PowerVR. + { "Imagination Technologies", { glDriverVendor_t::IMAGINATION, glHardwareVendor_t::IMAGINATION } }, }; auto it = vendorDriverHardware.find( vendorString ); if ( it != vendorDriverHardware.end() ) { - driverVendor = it->second.first; - hardwareVendor = it->second.second; + driverVendor = it->second.first; + hardwareVendor = it->second.second; return; } @@ -309,4 +328,39 @@ void DetectGLVendors( hardwareVendor = glHardwareVendor_t::INTEL; return; } + + // Newer GL4ES strings disclosing the underlying technology. + if ( Str::IsPrefix( "GL4ES wrapping ", vendorString ) ) + { + std::string subVendorString = StripPrefix( "GL4ES wrapping ", vendorString ); + std::string subRendererString = StripPrefix( "GL4ES using ", rendererString ); + DetectGLVendors( subVendorString, versionString, subRendererString, hardwareVendor, driverVendor ); + driverVendor = glDriverVendor_t::GL4ES; + } + + /* Older GL4ES string not disclosing the underlying technology, + also had “ptitSeb” as vendorString. */ + if ( rendererString == "GL4ES wrapper" ) + { + driverVendor = glDriverVendor_t::GL4ES; + // Older GL4ES doesn't disclose the underlying hardware. + if ( hardwareVendor == glHardwareVendor_t::UNKNOWN ) + { + hardwareVendor = glHardwareVendor_t::TRANSLATION; + } + return; + } + + /* GL4ES always use such kind of version string: + > 2.1 gl4es wrapper 1.1.7 + And this is unlikely to change. */ + if ( versionString.find( "gl4es wrapper" ) != std::string::npos ) + { + driverVendor = glDriverVendor_t::GL4ES; + if ( hardwareVendor == glHardwareVendor_t::UNKNOWN ) + { + hardwareVendor = glHardwareVendor_t::TRANSLATION; + } + return; + } } diff --git a/src/engine/renderer/DetectGLVendors.h b/src/engine/renderer/DetectGLVendors.h index 414372b381..20434172d5 100644 --- a/src/engine/renderer/DetectGLVendors.h +++ b/src/engine/renderer/DetectGLVendors.h @@ -54,9 +54,11 @@ enum class glHardwareVendor_t ARM, ATI, BROADCOM, + IMAGINATION, INTEL, - NVIDIA, MTHREADS, + NVIDIA, + ZHAOXIN, NUM_HARDWARE_VENDORS, }; @@ -65,10 +67,13 @@ enum class glDriverVendor_t UNKNOWN, APPLE, ATI, + GL4ES, + IMAGINATION, INTEL, MESA, - NVIDIA, MTHREADS, + NVIDIA, + ZHAOXIN, NUM_DRIVER_VENDORS, }; diff --git a/src/engine/renderer/tr_shade.cpp b/src/engine/renderer/tr_shade.cpp index d3d04dba3b..73dea5a345 100644 --- a/src/engine/renderer/tr_shade.cpp +++ b/src/engine/renderer/tr_shade.cpp @@ -30,192 +30,12 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA /* ================================================================================= THIS ENTIRE FILE IS BACK END! -^ Not true, EnableAvailableFeatures() right below this isn't. +^ Not true, The next 5 functions below are frontend. This file deals with applying shaders to surface data in the tess struct. ================================================================================= */ -static void EnableAvailableFeatures() -{ - glConfig.realtimeLighting = r_realtimeLighting.Get(); - - if ( glConfig.realtimeLighting ) - { - if ( !glConfig.uniformBufferObjectAvailable ) { - Log::Warn( "Tiled dynamic light renderer disabled because GL_ARB_uniform_buffer_object is not available." ); - glConfig.realtimeLighting = false; - } - - if ( !glConfig.textureIntegerAvailable ) { - Log::Warn( "Tiled dynamic light renderer disabled because GL_EXT_texture_integer is not available." ); - glConfig.realtimeLighting = false; - } - - if ( !glConfig.textureFloatAvailable ) - { - Log::Warn( "Tiled dynamic light renderer disabled because GL_ARB_texture_float is not available." ); - glConfig.realtimeLighting = false; - } - - if ( glConfig.max3DTextureSize == 0 ) - { - Log::Warn( "Tiled dynamic light renderer disabled because of missing 3D texture support." ); - glConfig.realtimeLighting = false; - } - - // See below about ALU instructions on ATI R300 and Intel GMA 3. - if ( !glConfig.glCoreProfile && glConfig.maxAluInstructions < 128 ) - { - Log::Warn( "Tiled dynamic light rendered disabled because GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB is too small: %d", glConfig.maxAluInstructions ); - glConfig.realtimeLighting = false; - } - } - - if ( glConfig.realtimeLighting ) { - // Minimum possible is 16384 / 48 = 341 - glConfig.maxRealtimeLights = - std::min( MAX_REF_LIGHTS, glConfig.maxUniformBlockSize / sizeof( shaderLight_t ) ); - - glConfig.realtimeLightLayers = r_realtimeLightLayers.Get(); - - if ( glConfig.realtimeLightLayers > glConfig.max3DTextureSize ) { - glConfig.realtimeLightLayers = glConfig.max3DTextureSize; - Log::Notice( "r_realtimeLightLayers exceeds maximum 3D texture size, using %i instead.", glConfig.max3DTextureSize ); - } - - Log::Notice( "Using %i dynamic light layers, %i dynamic lights available per tile, max %d lights", - glConfig.realtimeLightLayers, glConfig.realtimeLightLayers * 16, glConfig.maxRealtimeLights ); - } - - glConfig.colorGrading = r_colorGrading.Get(); - - if ( glConfig.colorGrading ) - { - if ( glConfig.max3DTextureSize == 0 ) - { - Log::Warn( "Color grading disabled because of missing 3D texture support." ); - glConfig.colorGrading = false; - } - } - - glConfig.deluxeMapping = r_deluxeMapping->integer; - glConfig.normalMapping = r_normalMapping->integer; - glConfig.specularMapping = r_specularMapping->integer; - glConfig.physicalMapping = r_physicalMapping->integer; - glConfig.reliefMapping = r_reliefMapping->integer; - - /* ATI R300 and Intel GMA 3 only have 64 ALU instructions, which is not enough for some shader - variants. For example the lightMapping shader permutation with macros USE_GRID_LIGHTING and - USE_GRID_DELUXE_MAPPING from the medium graphics preset requires 67 ALU. - For comparison, ATI R400 and R500 have 512 of them. */ - if ( !glConfig.glCoreProfile && glConfig.maxAluInstructions < 128 ) - { - static const std::pair aluFeatures[] = { - /* Normal mapping, specular mapping and physical mapping does nothing when deluxe mapping - is disabled. Hardware that can't do deluxe mapping or normal mapping is not powerful - enoough to do relief mapping. */ - { &glConfig.deluxeMapping, "Deluxe mapping" }, - { &glConfig.normalMapping, "Normal mapping" }, - { &glConfig.specularMapping, "Specular mapping" }, - { &glConfig.physicalMapping, "Physical mapping" }, - { &glConfig.reliefMapping, "Relief mapping" }, - }; - - for ( auto& f : aluFeatures ) - { - if ( *f.first ) - { - Log::Warn( "%s disabled because GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB is too small: %d", f.second, glConfig.maxAluInstructions ); - *f.first = false; - } - } - } - - // Disable features that require deluxe mapping to be enabled. - glConfig.normalMapping = glConfig.deluxeMapping && glConfig.normalMapping; - glConfig.specularMapping = glConfig.deluxeMapping && glConfig.specularMapping; - glConfig.physicalMapping = glConfig.deluxeMapping && glConfig.physicalMapping; - - glConfig.bloom = r_bloom.Get(); - - glConfig.SSAO = r_SSAO.Get() != Util::ordinal( ssaoMode::DISABLED ); - - static const std::pair ssaoRequiredExtensions[] = { - { &glConfig.textureGatherAvailable, "ARB_texture_gather" }, - { &glConfig.gpuShader4Available, "EXT_gpu_shader4" }, - }; - - for ( auto& e: ssaoRequiredExtensions ) - { - if ( !*e.first ) - { - Log::Warn( "SSAO disabled because %s is not available.", e.second ); - glConfig.SSAO = false; - } - } - - /* Motion blur is enabled by cg_motionblur which is a client cvar so we have to build it in all cases, - unless unsupported by the hardware which is the only condition when the engine knows it is not used. */ - glConfig.motionBlur = true; - - // This will be enabled later on by R_BuildCubeMaps() - glConfig.reflectionMapping = false; - - /* Intel GMA 3 only has 4 tex indirections, which is not enough for some shaders. - For example blurX requires 6, contrast requires 5, motionblur requires 5… - For comparison, ATI R300, R400 and R500 have 16 of them. We don't need a finer check as early R300 - hardware with 16 indirections would better not run that code for performance, so disabling the shader - by mistake on an hypothetical lower-end hardware only supporting 8 indirections can't do harm. */ - if ( !glConfig.glCoreProfile && glConfig.maxTexIndirections < 16 ) - { - static const std::pair indirectFeatures[] = { - { &glConfig.bloom, "Bloom" }, - { &glConfig.motionBlur, "Motion blur" }, - }; - - for ( auto& f : indirectFeatures ) - { - if ( *f.first ) - { - Log::Warn( "%s disabled because GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB is too small: %d", f.second, glConfig.maxTexIndirections ); - *f.first = false; - } - } - } - - if ( std::make_pair( glConfig.glMajor, glConfig.glMinor ) >= std::make_pair( 3, 2 ) ) { - glConfig.MSAA = r_MSAA.Get(); - const int maxSamples = std::min( glConfig.maxColorTextureSamples, glConfig.maxDepthTextureSamples ); - - if ( glConfig.MSAA > maxSamples ) { - Log::Warn( "MSAA samples %i > %i, setting to %i", r_MSAA.Get(), maxSamples, maxSamples ); - glConfig.MSAA = maxSamples; - } - } else if ( r_MSAA.Get() ) { - Log::Warn( "MSAA unavailable because GL version is lower than required (%i.%i < %i.%i)", glConfig.glMajor, glConfig.glMinor, 3, 2 ); - } - - glConfig.FXAA = r_FXAA.Get(); - - if ( glConfig.FXAA && glConfig.MSAA ) - { - Log::Notice( "FXAA disabled because MSAA is enabled." ); - glConfig.FXAA = false; - } - - if ( glConfig.FXAA && !glConfig.samplerObjectsAvailable ) - { - Log::Warn( "FXAA disabled because ARB_sampler_objects is not available." ); - glConfig.FXAA = false; - } - - glConfig.usingMaterialSystem = r_materialSystem.Get() && glConfig.materialSystemAvailable; - glConfig.usingBindlessTextures = glConfig.usingMaterialSystem || - ( r_preferBindlessTextures.Get() && glConfig.bindlessTexturesAvailable ); - glConfig.usingGeometryCache = glConfig.usingMaterialSystem && glConfig.geometryCacheAvailable; -} - // For shaders that require map data for compile-time values void GLSL_InitWorldShaders() { // make sure the render thread is stopped @@ -244,10 +64,6 @@ static void GLSL_InitGPUShadersOrError() gl_shaderManager.InitDriverInfo(); - /* It must be done before GenerateBuiltinHeaders() because glConfig.realtimeLighting - is read in GenEngineConstants(). */ - EnableAvailableFeatures(); - gl_shaderManager.GenerateBuiltinHeaders(); // single texture rendering diff --git a/src/engine/sys/sdl_glimp.cpp b/src/engine/sys/sdl_glimp.cpp index c15add9f0e..b6c93e2bf3 100644 --- a/src/engine/sys/sdl_glimp.cpp +++ b/src/engine/sys/sdl_glimp.cpp @@ -171,6 +171,10 @@ static Cvar::Cvar workaround_glDriver_nvidia_v340_disableTextureGather( "workaround.glDriver.nvidia.v340.disableTextureGather", "Disable ARB_texture_gather on Nvidia 340 driver", Cvar::NONE, true ); +static Cvar::Cvar workaround_glDriver_zhaoxin_disableRealtimeLighting( + "workaround.glDriver.zhaoxin.disableRealtimeLighting", + "Disable realtime lighting on Zhaoxin driver", + Cvar::NONE, true ); static Cvar::Cvar workaround_glExtension_missingArbFbo_useExtFbo( "workaround.glExtension.missingArbFbo.useExtFbo", "Use EXT_framebuffer_object and EXT_framebuffer_blit when ARB_framebuffer_object is not available", @@ -2675,6 +2679,192 @@ static void GLimp_InitExtensions() GL_CheckErrors(); } +static void GLimp_EnableAvailableFeatures() +{ + glConfig.realtimeLighting = r_realtimeLighting.Get(); + + if ( glConfig.realtimeLighting ) + { + if ( workaround_glDriver_zhaoxin_disableRealtimeLighting.Get() ) + { + Log::Warn("Tiled dynamic light renderer disabled because of buggy Zhaoxin driver."); + glConfig.realtimeLighting = false; + } + + if ( !glConfig.uniformBufferObjectAvailable ) { + Log::Warn( "Tiled dynamic light renderer disabled because GL_ARB_uniform_buffer_object is not available." ); + glConfig.realtimeLighting = false; + } + + if ( !glConfig.textureIntegerAvailable ) { + Log::Warn( "Tiled dynamic light renderer disabled because GL_EXT_texture_integer is not available." ); + glConfig.realtimeLighting = false; + } + + if ( !glConfig.textureFloatAvailable ) + { + Log::Warn( "Tiled dynamic light renderer disabled because GL_ARB_texture_float is not available." ); + glConfig.realtimeLighting = false; + } + + if ( glConfig.max3DTextureSize == 0 ) + { + Log::Warn( "Tiled dynamic light renderer disabled because of missing 3D texture support." ); + glConfig.realtimeLighting = false; + } + + // See below about ALU instructions on ATI R300 and Intel GMA 3. + if ( !glConfig.glCoreProfile && glConfig.maxAluInstructions < 128 ) + { + Log::Warn( "Tiled dynamic light rendered disabled because GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB is too small: %d", glConfig.maxAluInstructions ); + glConfig.realtimeLighting = false; + } + } + + if ( glConfig.realtimeLighting ) { + // Minimum possible is 16384 / 48 = 341 + glConfig.maxRealtimeLights = + std::min( MAX_REF_LIGHTS, glConfig.maxUniformBlockSize / sizeof( shaderLight_t ) ); + + glConfig.realtimeLightLayers = r_realtimeLightLayers.Get(); + + if ( glConfig.realtimeLightLayers > glConfig.max3DTextureSize ) { + glConfig.realtimeLightLayers = glConfig.max3DTextureSize; + Log::Notice( "r_realtimeLightLayers exceeds maximum 3D texture size, using %i instead.", glConfig.max3DTextureSize ); + } + + Log::Notice( "Using %i dynamic light layers, %i dynamic lights available per tile, max %d lights", + glConfig.realtimeLightLayers, glConfig.realtimeLightLayers * 16, glConfig.maxRealtimeLights ); + } + + glConfig.colorGrading = r_colorGrading.Get(); + + if ( glConfig.colorGrading ) + { + if ( glConfig.max3DTextureSize == 0 ) + { + Log::Warn( "Color grading disabled because of missing 3D texture support." ); + glConfig.colorGrading = false; + } + } + + glConfig.deluxeMapping = r_deluxeMapping->integer; + glConfig.normalMapping = r_normalMapping->integer; + glConfig.specularMapping = r_specularMapping->integer; + glConfig.physicalMapping = r_physicalMapping->integer; + glConfig.reliefMapping = r_reliefMapping->integer; + + /* ATI R300 and Intel GMA 3 only have 64 ALU instructions, which is not enough for some shader + variants. For example the lightMapping shader permutation with macros USE_GRID_LIGHTING and + USE_GRID_DELUXE_MAPPING from the medium graphics preset requires 67 ALU. + For comparison, ATI R400 and R500 have 512 of them. */ + if ( !glConfig.glCoreProfile && glConfig.maxAluInstructions < 128 ) + { + static const std::pair aluFeatures[] = { + /* Normal mapping, specular mapping and physical mapping does nothing when deluxe mapping + is disabled. Hardware that can't do deluxe mapping or normal mapping is not powerful + enoough to do relief mapping. */ + { &glConfig.deluxeMapping, "Deluxe mapping" }, + { &glConfig.normalMapping, "Normal mapping" }, + { &glConfig.specularMapping, "Specular mapping" }, + { &glConfig.physicalMapping, "Physical mapping" }, + { &glConfig.reliefMapping, "Relief mapping" }, + }; + + for ( auto& f : aluFeatures ) + { + if ( *f.first ) + { + Log::Warn( "%s disabled because GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB is too small: %d", f.second, glConfig.maxAluInstructions ); + *f.first = false; + } + } + } + + // Disable features that require deluxe mapping to be enabled. + glConfig.normalMapping = glConfig.deluxeMapping && glConfig.normalMapping; + glConfig.specularMapping = glConfig.deluxeMapping && glConfig.specularMapping; + glConfig.physicalMapping = glConfig.deluxeMapping && glConfig.physicalMapping; + + glConfig.bloom = r_bloom.Get(); + + glConfig.SSAO = r_SSAO.Get() != Util::ordinal( ssaoMode::DISABLED ); + + static const std::pair ssaoRequiredExtensions[] = { + { &glConfig.textureGatherAvailable, "ARB_texture_gather" }, + { &glConfig.gpuShader4Available, "EXT_gpu_shader4" }, + }; + + for ( auto& e: ssaoRequiredExtensions ) + { + if ( !*e.first ) + { + Log::Warn( "SSAO disabled because %s is not available.", e.second ); + glConfig.SSAO = false; + } + } + + /* Motion blur is enabled by cg_motionblur which is a client cvar so we have to build it in all cases, + unless unsupported by the hardware which is the only condition when the engine knows it is not used. */ + glConfig.motionBlur = true; + + // This will be enabled later on by R_BuildCubeMaps() + glConfig.reflectionMapping = false; + + /* Intel GMA 3 only has 4 tex indirections, which is not enough for some shaders. + For example blurX requires 6, contrast requires 5, motionblur requires 5… + For comparison, ATI R300, R400 and R500 have 16 of them. We don't need a finer check as early R300 + hardware with 16 indirections would better not run that code for performance, so disabling the shader + by mistake on an hypothetical lower-end hardware only supporting 8 indirections can't do harm. */ + if ( !glConfig.glCoreProfile && glConfig.maxTexIndirections < 16 ) + { + static const std::pair indirectFeatures[] = { + { &glConfig.bloom, "Bloom" }, + { &glConfig.motionBlur, "Motion blur" }, + }; + + for ( auto& f : indirectFeatures ) + { + if ( *f.first ) + { + Log::Warn( "%s disabled because GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB is too small: %d", f.second, glConfig.maxTexIndirections ); + *f.first = false; + } + } + } + + if ( std::make_pair( glConfig.glMajor, glConfig.glMinor ) >= std::make_pair( 3, 2 ) ) { + glConfig.MSAA = r_MSAA.Get(); + const int maxSamples = std::min( glConfig.maxColorTextureSamples, glConfig.maxDepthTextureSamples ); + + if ( glConfig.MSAA > maxSamples ) { + Log::Warn( "MSAA samples %i > %i, setting to %i", r_MSAA.Get(), maxSamples, maxSamples ); + glConfig.MSAA = maxSamples; + } + } else if ( r_MSAA.Get() ) { + Log::Warn( "MSAA unavailable because GL version is lower than required (%i.%i < %i.%i)", glConfig.glMajor, glConfig.glMinor, 3, 2 ); + } + + glConfig.FXAA = r_FXAA.Get(); + + if ( glConfig.FXAA && glConfig.MSAA ) + { + Log::Notice( "FXAA disabled because MSAA is enabled." ); + glConfig.FXAA = false; + } + + if ( glConfig.FXAA && !glConfig.samplerObjectsAvailable ) + { + Log::Warn( "FXAA disabled because ARB_sampler_objects is not available." ); + glConfig.FXAA = false; + } + + glConfig.usingMaterialSystem = r_materialSystem.Get() && glConfig.materialSystemAvailable; + glConfig.usingBindlessTextures = glConfig.usingMaterialSystem || + ( r_preferBindlessTextures.Get() && glConfig.bindlessTexturesAvailable ); + glConfig.usingGeometryCache = glConfig.usingMaterialSystem && glConfig.geometryCacheAvailable; +} + static const int R_MODE_FALLBACK = 3; // 640 * 480 /* Support code for GLimp_Init */ @@ -2716,6 +2906,7 @@ bool GLimp_Init() Cvar::Latch( workaround_glDriver_mesa_intel_gma3_stubOcclusionQuery ); Cvar::Latch( workaround_glDriver_mesa_v241_disableBindlessTexture ); Cvar::Latch( workaround_glDriver_nvidia_v340_disableTextureGather ); + Cvar::Latch( workaround_glDriver_zhaoxin_disableRealtimeLighting ); Cvar::Latch( workaround_glExtension_missingArbFbo_useExtFbo ); Cvar::Latch( workaround_glExtension_glsl120_disableShaderDrawParameters ); Cvar::Latch( workaround_glExtension_glsl120_disableTextureBarrier ); @@ -2923,6 +3114,8 @@ bool GLimp_Init() // initialize extensions GLimp_InitExtensions(); + GLimp_EnableAvailableFeatures(); + // This depends on SDL_INIT_VIDEO, hence having it here ri.IN_Init( window );