From d8cdfaa645e68a496f7c5957602a28cbc2db5f53 Mon Sep 17 00:00:00 2001 From: Brad Linden Date: Thu, 19 Jan 2023 14:25:14 -0800 Subject: [PATCH 01/31] Fix for SL-19010 mac crash in LLManipTranslartge::restoreGL(). Attempt to simplify and avoid use of GL_UNSIGNED_INT_8_8_8_8_REV where not needed --- indra/llrender/llimagegl.cpp | 1 + indra/newview/llmaniptranslate.cpp | 4 ---- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index db17f812bd..b3b79bd6c4 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -1428,6 +1428,7 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt { case GL_UNSIGNED_BYTE: case GL_BYTE: + case GL_UNSIGNED_INT_8_8_8_8_REV: type_width = 1; break; case GL_UNSIGNED_SHORT: diff --git a/indra/newview/llmaniptranslate.cpp b/indra/newview/llmaniptranslate.cpp index b9e68bd6a9..91f1af8f28 100644 --- a/indra/newview/llmaniptranslate.cpp +++ b/indra/newview/llmaniptranslate.cpp @@ -267,11 +267,7 @@ void LLManipTranslate::restoreGL() } } } -#ifdef LL_WINDOWS LLImageGL::setManualImage(GL_TEXTURE_2D, mip, GL_RGBA, rez, rez, GL_RGBA, GL_UNSIGNED_BYTE, d); -#else - LLImageGL::setManualImage(GL_TEXTURE_2D, mip, GL_RGBA, rez, rez, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, d); -#endif rez = rez >> 1; mip++; } From c83e66414848e468cce01d36c1054b2e9314baf9 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Fri, 20 Jan 2023 13:00:40 -0600 Subject: [PATCH 02/31] SL-18869 GL 3 compatibility pass and minor decruft. --- indra/llrender/llgl.cpp | 16 ------- indra/llrender/llshadermgr.cpp | 3 +- indra/llrender/llshadermgr.h | 1 - indra/newview/app_settings/settings.xml | 12 ------ .../shaders/class1/deferred/starsF.glsl | 1 - .../shaders/class3/deferred/softenLightF.glsl | 1 - indra/newview/featuretable.txt | 1 - indra/newview/featuretable_mac.txt | 1 - indra/newview/lldrawpoolalpha.cpp | 12 ++---- indra/newview/llviewercontrol.cpp | 43 ------------------- indra/newview/llviewershadermgr.cpp | 33 ++------------ indra/newview/pipeline.cpp | 26 +---------- indra/newview/pipeline.h | 2 - 13 files changed, 9 insertions(+), 143 deletions(-) diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index 9dfe5ef9ff..8bb83d4250 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -1018,8 +1018,6 @@ bool LLGLManager::initGL() LL_ERRS("RenderInit") << "Calling init on LLGLManager after already initialized!" << LL_ENDL; } - stop_glerror(); - #if 0 && LL_WINDOWS if (!glGetStringi) { @@ -1055,8 +1053,6 @@ bool LLGLManager::initGL() } #endif - stop_glerror(); - // Extract video card strings and convert to upper case to // work around driver-to-driver variation in capitalization. mGLVendor = ll_safe_string((const char *)glGetString(GL_VENDOR)); @@ -1128,10 +1124,8 @@ bool LLGLManager::initGL() mGLVendorShort = "MISC"; } - stop_glerror(); // This is called here because it depends on the setting of mIsGF2or4MX, and sets up mHasMultitexture. initExtensions(); - stop_glerror(); S32 old_vram = mVRAM; mVRAM = 0; @@ -1192,29 +1186,19 @@ bool LLGLManager::initGL() mVRAM = old_vram; } - stop_glerror(); - glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &mNumTextureImageUnits); - stop_glerror(); glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &mMaxColorTextureSamples); - stop_glerror(); glGetIntegerv(GL_MAX_DEPTH_TEXTURE_SAMPLES, &mMaxDepthTextureSamples); - stop_glerror(); glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &mMaxIntegerSamples); - stop_glerror(); glGetIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &mMaxSampleMaskWords); - stop_glerror(); glGetIntegerv(GL_MAX_SAMPLES, &mMaxSamples); - stop_glerror(); if (mGLVersion >= 4.59f) { glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY, &mMaxAnisotropy); - stop_glerror(); } initGLStates(); - stop_glerror(); return true; } diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index ee8ac359c7..44b8ea164b 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -1320,9 +1320,8 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("depth_cutoff"); mReservedUniforms.push_back("norm_cutoff"); mReservedUniforms.push_back("shadow_target_width"); - mReservedUniforms.push_back("view_dir"); // DEFERRED_VIEW_DIR - llassert(mReservedUniforms.size() == LLShaderMgr::DEFERRED_VIEW_DIR+1); + llassert(mReservedUniforms.size() == LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH+1); mReservedUniforms.push_back("tc_scale"); mReservedUniforms.push_back("rcp_screen_res"); diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index 90a8c2853c..f6abfe9027 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -157,7 +157,6 @@ public: DEFERRED_DEPTH_CUTOFF, // "depth_cutoff" DEFERRED_NORM_CUTOFF, // "norm_cutoff" DEFERRED_SHADOW_TARGET_WIDTH, // "shadow_target_width" - DEFERRED_VIEW_DIR, // "view_dir" FXAA_TC_SCALE, // "tc_scale" FXAA_RCP_SCREEN_RES, // "rcp_screen_res" diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index ec4125c2bf..d262a1285f 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -9668,18 +9668,6 @@ 368.0 - RenderPBR - - Comment - DEPRECATED - only true supported - Use PBR rendering pipeline (Physically Based Rendering). - Persist - 1 - Type - Boolean - Value - 1 - - RenderDeferred Comment diff --git a/indra/newview/app_settings/shaders/class1/deferred/starsF.glsl b/indra/newview/app_settings/shaders/class1/deferred/starsF.glsl index 6376527273..152316c117 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/starsF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/starsF.glsl @@ -36,7 +36,6 @@ VARYING vec2 vary_texcoord0; VARYING vec2 screenpos; uniform sampler2D diffuseMap; -uniform sampler2D altDiffuseMap; uniform float blend_factor; uniform float custom_alpha; uniform float time; diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index 5f6982746b..8e4197ae77 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -41,7 +41,6 @@ uniform sampler2D diffuseRect; uniform sampler2D specularRect; uniform sampler2D normalMap; uniform sampler2D emissiveRect; // PBR linear packed Occlusion, Roughness, Metal. See: pbropaqueF.glsl -uniform sampler2D altDiffuseMap; // PBR: irradiance, skins/default/textures/default_irradiance.png const float M_PI = 3.14159265; diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt index 21babc9e5f..cf0968dfd2 100644 --- a/indra/newview/featuretable.txt +++ b/indra/newview/featuretable.txt @@ -62,7 +62,6 @@ Disregard128DefaultDrawDistance 1 1 Disregard96DefaultDrawDistance 1 1 RenderCompressTextures 1 1 RenderShaderLightingMaxLevel 1 3 -RenderPBR 1 1 RenderReflectionProbeCount 1 256 RenderDeferred 1 1 RenderDeferredSSAO 1 1 diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt index 45e3827f60..d57a0b8105 100644 --- a/indra/newview/featuretable_mac.txt +++ b/indra/newview/featuretable_mac.txt @@ -61,7 +61,6 @@ Disregard96DefaultDrawDistance 1 1 RenderCompressTextures 1 1 RenderShaderLightingMaxLevel 1 3 RenderDeferred 1 1 -RenderPBR 1 1 RenderDeferredSSAO 1 1 RenderUseAdvancedAtmospherics 1 0 RenderShadowDetail 1 2 diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index ed952689fa..20d3818934 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -86,11 +86,6 @@ void LLDrawPoolAlpha::prerender() // TODO: is this even necessay? These are probably set to never discard LLViewerFetchedTexture::sFlatNormalImagep->addTextureStats(1024.f*1024.f); LLViewerFetchedTexture::sWhiteImagep->addTextureStats(1024.f * 1024.f); - - if (LLPipeline::sRenderPBR) - { - gPipeline.setupHWLights(NULL); - } } S32 LLDrawPoolAlpha::getNumPostDeferredPasses() @@ -659,12 +654,11 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only, bool rigged) LLRenderPass::applyModelMatrix(params); LLMaterial* mat = NULL; - LLGLTFMaterial *gltf_mat = params.mGLTFMaterial; // Also see: LLPipeline::getPoolTypeFromTE() - bool is_pbr = LLPipeline::sRenderPBR && gltf_mat; + LLGLTFMaterial *gltf_mat = params.mGLTFMaterial; - LLGLDisable cull_face(is_pbr && gltf_mat->mDoubleSided ? GL_CULL_FACE : 0); + LLGLDisable cull_face(gltf_mat && gltf_mat->mDoubleSided ? GL_CULL_FACE : 0); - if (is_pbr && gltf_mat->mAlphaMode == LLGLTFMaterial::ALPHA_MODE_BLEND) + if (gltf_mat && gltf_mat->mAlphaMode == LLGLTFMaterial::ALPHA_MODE_BLEND) { target_shader = &gDeferredPBRAlphaProgram; if (params.mAvatar != nullptr) diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 364bd830f5..8b9df88fd4 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -152,7 +152,6 @@ static bool handleSetShaderChanged(const LLSD& newvalue) // ALM depends onto atmospheric shaders, state might have changed bool old_state = LLPipeline::sRenderDeferred; LLPipeline::refreshCachedSettings(); - gPipeline.updateRenderDeferred(); if (old_state != LLPipeline::sRenderDeferred) { gPipeline.releaseGLBuffers(); @@ -208,7 +207,6 @@ bool handleRenderTransparentWaterChanged(const LLSD& newvalue) if (gPipeline.isInit()) { gPipeline.updateRenderTransparentWater(); - gPipeline.updateRenderDeferred(); gPipeline.releaseGLBuffers(); gPipeline.createGLBuffers(); gPipeline.resetVertexBuffers(); @@ -439,7 +437,6 @@ static bool handleReflectionProbeDetailChanged(const LLSD& newvalue) if (gPipeline.isInit()) { LLPipeline::refreshCachedSettings(); - gPipeline.updateRenderDeferred(); gPipeline.releaseGLBuffers(); gPipeline.createGLBuffers(); gPipeline.resetVertexBuffers(); @@ -448,46 +445,6 @@ static bool handleReflectionProbeDetailChanged(const LLSD& newvalue) return true; } -#if 0 // DEPRECATED -// NOTE: may be triggered by RenderDeferred OR RenderPBR changing, don't trust "newvalue" -static bool handleRenderDeferredChanged(const LLSD& newvalue) -{ - LLRenderTarget::sUseFBO = gSavedSettings.getBOOL("RenderDeferred"); - if (gPipeline.isInit()) - { - LLPipeline::refreshCachedSettings(); - gPipeline.updateRenderDeferred(); - gPipeline.releaseGLBuffers(); - gPipeline.createGLBuffers(); - gPipeline.resetVertexBuffers(); - if (LLPipeline::sRenderDeferred == (BOOL)LLRenderTarget::sUseFBO) - { - LLViewerShaderMgr::instance()->setShaders(); - } - } - return true; -} - -// This looks a great deal like handleRenderDeferredChanged because -// Advanced Lighting (Materials) implies bumps and shiny so disabling -// bumps should further disable that feature. -// -static bool handleRenderBumpChanged(const LLSD& newval) -{ - LLRenderTarget::sUseFBO = newval.asBoolean() && gSavedSettings.getBOOL("RenderDeferred"); - if (gPipeline.isInit()) - { - gPipeline.updateRenderBump(); - gPipeline.updateRenderDeferred(); - gPipeline.releaseGLBuffers(); - gPipeline.createGLBuffers(); - gPipeline.resetVertexBuffers(); - LLViewerShaderMgr::instance()->setShaders(); - } - return true; -} -#endif - static bool handleRenderDebugPipelineChanged(const LLSD& newvalue) { gDebugPipeline = newvalue.asBoolean(); diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index ebc6df22ac..e40c337f04 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -468,7 +468,6 @@ void LLViewerShaderMgr::setShaders() gPipeline.releaseGLBuffers(); LLPipeline::sRenderGlow = gSavedSettings.getBOOL("RenderGlow"); - LLPipeline::updateRenderDeferred(); //hack to reset buffers that change behavior with shaders gPipeline.resetVertexBuffers(); @@ -497,10 +496,8 @@ void LLViewerShaderMgr::setShaders() //bool canRenderDeferred = true; // DEPRECATED -- LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred"); //bool hasWindLightShaders = true; // DEPRECATED -- LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders"); - S32 shadow_detail = gSavedSettings.getS32("RenderShadowDetail"); - bool pbr = gSavedSettings.getBOOL("RenderPBR"); + //S32 shadow_detail = gSavedSettings.getS32("RenderShadowDetail"); bool doingWindLight = true; //DEPRECATED -- hasWindLightShaders&& gSavedSettings.getBOOL("WindLightUseAtmosShaders"); - bool useRenderDeferred = true; //DEPRECATED -- doingWindLight&& canRenderDeferred&& gSavedSettings.getBOOL("RenderDeferred"); S32 light_class = 3; S32 interface_class = 2; @@ -509,32 +506,7 @@ void LLViewerShaderMgr::setShaders() S32 effect_class = 2; S32 wl_class = 1; S32 water_class = 3; - S32 deferred_class = 0; - - if (useRenderDeferred) - { - //shadows - switch (shadow_detail) - { - case 1: - deferred_class = 2; // PCF shadows - break; - - case 2: - deferred_class = 2; // PCF shadows - break; - - case 0: - default: - deferred_class = 1; // no shadows - break; - } - } - - if (deferred_class > 0 && pbr) - { - deferred_class = 3; - } + S32 deferred_class = 3; if (doingWindLight) { @@ -3859,6 +3831,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface() { gReflectionProbeDisplayProgram.mName = "Reflection Probe Display Shader"; gReflectionProbeDisplayProgram.mFeatures.hasReflectionProbes = true; + gReflectionProbeDisplayProgram.mFeatures.hasSrgb = true; gReflectionProbeDisplayProgram.mShaderFiles.clear(); gReflectionProbeDisplayProgram.mShaderFiles.push_back(make_pair("interface/reflectionprobeV.glsl", GL_VERTEX_SHADER)); gReflectionProbeDisplayProgram.mShaderFiles.push_back(make_pair("interface/reflectionprobeF.glsl", GL_FRAGMENT_SHADER)); diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index beaa3cdb69..2a55a299ac 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -326,7 +326,6 @@ bool LLPipeline::sRenderAttachedLights = true; bool LLPipeline::sRenderAttachedParticles = true; bool LLPipeline::sRenderDeferred = false; bool LLPipeline::sReflectionProbesEnabled = false; -bool LLPipeline::sRenderPBR = false; S32 LLPipeline::sVisibleLightCount = 0; bool LLPipeline::sRenderingHUDs; F32 LLPipeline::sDistortionWaterClipPlaneMargin = 1.0125f; @@ -1008,12 +1007,6 @@ void LLPipeline::updateRenderBump() sRenderBump = TRUE; // DEPRECATED -- gSavedSettings.getBOOL("RenderObjectBump"); } -// static -void LLPipeline::updateRenderDeferred() -{ - sRenderPBR = sRenderDeferred; -} - // static void LLPipeline::refreshCachedSettings() { @@ -1103,11 +1096,9 @@ void LLPipeline::refreshCachedSettings() CameraDoFResScale = gSavedSettings.getF32("CameraDoFResScale"); RenderAutoHideSurfaceAreaLimit = gSavedSettings.getF32("RenderAutoHideSurfaceAreaLimit"); RenderScreenSpaceReflections = gSavedSettings.getBOOL("RenderScreenSpaceReflections"); - sReflectionProbesEnabled = gSavedSettings.getBOOL("RenderReflectionsEnabled"); + sReflectionProbesEnabled = LLFeatureManager::getInstance()->isFeatureAvailable("RenderReflectionsEnabled") && gSavedSettings.getBOOL("RenderReflectionsEnabled"); RenderSpotLight = nullptr; - updateRenderDeferred(); - if (gNonInteractive) { LLVOAvatar::sMaxNonImpostors = 1; @@ -1207,7 +1198,6 @@ void LLPipeline::createGLBuffers() stop_glerror(); assertInitialized(); - updateRenderDeferred(); if (LLPipeline::sRenderTransparentWater) { //water reflection texture U32 res = (U32) llmax(gSavedSettings.getS32("RenderWaterRefResolution"), 512); @@ -6881,10 +6871,9 @@ void LLPipeline::doResetVertexBuffers(bool forced) LLVOPartGroup::destroyGL(); gGL.resetVertexBuffer(); - LLVertexBuffer::unbind(); + LLVertexBuffer::unbind(); updateRenderBump(); - updateRenderDeferred(); sBakeSunlight = gSavedSettings.getBOOL("RenderBakeSunlight"); sNoAlpha = gSavedSettings.getBOOL("RenderNoAlpha"); @@ -8358,17 +8347,6 @@ void LLPipeline::renderDeferredLighting() soften_shader.uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0); soften_shader.uniform3fv(LLShaderMgr::LIGHTNORM, 1, environment.getClampedLightNorm().mV); - if (!LLPipeline::sUnderWaterRender && LLPipeline::sRenderPBR) - { - soften_shader.bindTexture(LLShaderMgr::ALTERNATE_DIFFUSE_MAP, LLViewerFetchedTexture::sDefaultIrradiancePBRp); // PBR: irradiance - } - - if(LLPipeline::sRenderPBR) - { - LLVector3 cameraAtAxis = LLViewerCamera::getInstance()->getAtAxis(); - soften_shader.uniform3fv(LLShaderMgr::DEFERRED_VIEW_DIR, 1, cameraAtAxis.mV); - } - { LLGLDepthTest depth(GL_FALSE); LLGLDisable blend(GL_BLEND); diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 689dc385ae..83d316e15f 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -428,7 +428,6 @@ public: static void updateRenderTransparentWater(); static void updateRenderBump(); - static void updateRenderDeferred(); static void refreshCachedSettings(); void addDebugBlip(const LLVector3& position, const LLColor4& color); @@ -648,7 +647,6 @@ public: static bool sRenderAttachedParticles; static bool sRenderDeferred; static bool sReflectionProbesEnabled; - static bool sRenderPBR; static S32 sVisibleLightCount; static bool sRenderingHUDs; static F32 sDistortionWaterClipPlaneMargin; From 7067a9585ae8fcaf7a5f02398130fce14995df2a Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Fri, 20 Jan 2023 14:40:45 -0600 Subject: [PATCH 03/31] SL-18869 Followup -- fix for sky being black in probes and too bright outside probes. --- indra/newview/pipeline.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 2a55a299ac..aeb7341411 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -4037,6 +4037,8 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera, bool do_occlusion) bool occlude = LLPipeline::sUseOcclusion > 1 && do_occlusion; + setupHWLights(nullptr); + { LL_PROFILE_ZONE_NAMED_CATEGORY_DRAWPOOL("deferred pools"); //LL_RECORD_BLOCK_TIME(FTM_DEFERRED_POOLS); From c2fef4b58838a617650dd40755518dd22558b42b Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Fri, 20 Jan 2023 15:48:06 -0600 Subject: [PATCH 04/31] SL-19015 Boost brightness of irradiance maps. --- .../app_settings/shaders/class1/interface/irradianceGenF.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/app_settings/shaders/class1/interface/irradianceGenF.glsl b/indra/newview/app_settings/shaders/class1/interface/irradianceGenF.glsl index feaf562686..3e056aa048 100644 --- a/indra/newview/app_settings/shaders/class1/interface/irradianceGenF.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/irradianceGenF.glsl @@ -212,7 +212,7 @@ vec4 filterColor(vec3 N) color /= float(u_sampleCount); } - return color; + return min(color*1.9, vec4(1)); } // entry point From 984bdcd9d9622cedd17d3d33ecae6b726860dd94 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Fri, 20 Jan 2023 18:25:53 -0600 Subject: [PATCH 05/31] SL-18869 Followup -- AMD compatibility pass. --- indra/llrender/llgl.cpp | 41 ++++++++++++++++++++++--------- indra/llrender/llvertexbuffer.cpp | 33 ++++++++++++++++--------- 2 files changed, 52 insertions(+), 22 deletions(-) diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index 8bb83d4250..1725990e8f 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -86,9 +86,9 @@ void APIENTRY gl_debug_callback(GLenum source, const GLchar* message, GLvoid* userParam) { - if (severity != GL_DEBUG_SEVERITY_HIGH // && - //severity != GL_DEBUG_SEVERITY_MEDIUM && - //severity != GL_DEBUG_SEVERITY_LOW + if (severity != GL_DEBUG_SEVERITY_HIGH && + severity != GL_DEBUG_SEVERITY_MEDIUM && + severity != GL_DEBUG_SEVERITY_LOW ) { //suppress out-of-spec messages sent by nvidia driver (mostly vertexbuffer hints) return; @@ -112,10 +112,28 @@ void APIENTRY gl_debug_callback(GLenum source, glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &vao); GLint vbo = 0; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &vbo); + GLint vbo_size = 0; + if (vbo != 0) + { + glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &vbo_size); + } GLint ibo = 0; glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &ibo); - - if (severity == GL_DEBUG_SEVERITY_HIGH) + GLint ibo_size = 0; + if (ibo != 0) + { + glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_SIZE, &ibo_size); + } + GLint ubo = 0; + glGetIntegerv(GL_UNIFORM_BUFFER_BINDING, &ubo); + GLint ubo_size = 0; + GLint ubo_immutable = 0; + if (ubo != 0) + { + glGetBufferParameteriv(GL_UNIFORM_BUFFER, GL_BUFFER_SIZE, &ubo_size); + glGetBufferParameteriv(GL_UNIFORM_BUFFER, GL_BUFFER_IMMUTABLE_STORAGE, &ubo_immutable); + } + //if (severity == GL_DEBUG_SEVERITY_HIGH) { LL_ERRS() << "Halting on GL Error" << LL_ENDL; } @@ -2393,12 +2411,13 @@ void LLGLState::checkStates(GLboolean writeAlpha) llassert_always(src == GL_SRC_ALPHA); llassert_always(dst == GL_ONE_MINUS_SRC_ALPHA); - GLboolean colorMask[4]; - glGetBooleanv(GL_COLOR_WRITEMASK, colorMask); - llassert_always(colorMask[0]); - llassert_always(colorMask[1]); - llassert_always(colorMask[2]); - llassert_always(colorMask[3] == writeAlpha); + // disable for now until usage is consistent + //GLboolean colorMask[4]; + //glGetBooleanv(GL_COLOR_WRITEMASK, colorMask); + //llassert_always(colorMask[0]); + //llassert_always(colorMask[1]); + //llassert_always(colorMask[2]); + // llassert_always(colorMask[3] == writeAlpha); for (boost::unordered_map::iterator iter = sStateMap.begin(); iter != sStateMap.end(); ++iter) diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index f1d71ec94d..028db79566 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -260,19 +260,30 @@ static GLWorkQueue* sQueue = nullptr; static GLuint gen_buffer() { LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX; - constexpr U32 pool_size = 4096; - thread_local static GLuint sNamePool[pool_size]; - thread_local static U32 sIndex = 0; - - if (sIndex == 0) + GLuint ret = 0; + if (!gGLManager.mIsAMD) { - LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("gen buffer"); - sIndex = pool_size; - glGenBuffers(pool_size, sNamePool); + constexpr U32 pool_size = 4096; + + thread_local static GLuint sNamePool[pool_size]; + thread_local static U32 sIndex = 0; + + if (sIndex == 0) + { + LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("gen buffer"); + sIndex = pool_size; + glGenBuffers(pool_size, sNamePool); + } + + ret = sNamePool[--sIndex]; + } + else + { + glGenBuffers(1, &ret); } - return sNamePool[--sIndex]; + return ret; } #define ANALYZE_VBO_POOL 0 @@ -725,7 +736,6 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi llassert(mGLBuffer == sGLRenderBuffer); llassert(mGLIndices == sGLRenderIndices); gGL.syncMatrices(); - glDrawRangeElements(sGLMode[mode], start, end, count, GL_UNSIGNED_SHORT, (GLvoid*) (indices_offset * sizeof(U16))); } @@ -1144,7 +1154,8 @@ static void flush_vbo(GLenum target, U32 start, U32 end, void* data) LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("glBufferSubData block"); //LL_PROFILE_GPU_ZONE("glBufferSubData"); U32 tend = llmin(i + block_size, end); - glBufferSubData(target, i, tend - i+1, (U8*) data + (i-start)); + U32 size = tend - i + 1; + glBufferSubData(target, i, size, (U8*) data + (i-start)); } } } From 3fac6115c0de172e48fbfd13753bc83b755ecf21 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Mon, 23 Jan 2023 10:01:00 -0600 Subject: [PATCH 06/31] SL-18772 Potential fix for failed shader load on Intel HD 3000 --- indra/newview/llviewershadermgr.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index e40c337f04..13161d1c28 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -3832,6 +3832,11 @@ BOOL LLViewerShaderMgr::loadShadersInterface() gReflectionProbeDisplayProgram.mName = "Reflection Probe Display Shader"; gReflectionProbeDisplayProgram.mFeatures.hasReflectionProbes = true; gReflectionProbeDisplayProgram.mFeatures.hasSrgb = true; + gReflectionProbeDisplayProgram.mFeatures.calculatesAtmospherics = true; + gReflectionProbeDisplayProgram.mFeatures.hasAtmospherics = true; + gReflectionProbeDisplayProgram.mFeatures.hasTransport = true; + gReflectionProbeDisplayProgram.mFeatures.hasGamma = true; + gReflectionProbeDisplayProgram.mFeatures.isDeferred = true; gReflectionProbeDisplayProgram.mShaderFiles.clear(); gReflectionProbeDisplayProgram.mShaderFiles.push_back(make_pair("interface/reflectionprobeV.glsl", GL_VERTEX_SHADER)); gReflectionProbeDisplayProgram.mShaderFiles.push_back(make_pair("interface/reflectionprobeF.glsl", GL_FRAGMENT_SHADER)); From 7c853be544ba2313d82ddbc6960ae1bdd806e4d2 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 19 Jan 2023 19:43:37 +0200 Subject: [PATCH 07/31] SL-19005 Fix save button for local uploads --- indra/newview/llmaterialeditor.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/indra/newview/llmaterialeditor.cpp b/indra/newview/llmaterialeditor.cpp index 9efe5dc1f1..dabc7d16ea 100644 --- a/indra/newview/llmaterialeditor.cpp +++ b/indra/newview/llmaterialeditor.cpp @@ -2156,6 +2156,7 @@ void LLMaterialEditor::loadMaterial(const tinygltf::Model &model_in, const std:: { openFloater(getKey()); setFocus(TRUE); + setCanSave(true); applyToSelection(); } From 274da636a00fd0469f7857dad7995cb11552e4ab Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Mon, 23 Jan 2023 11:48:43 -0600 Subject: [PATCH 08/31] SL-18869 Followup -- AMD optimization pass. --- indra/llcommon/llprofiler.h | 2 +- indra/llrender/llvertexbuffer.cpp | 32 ++++++++++++++++--------------- indra/newview/featuretable.txt | 5 ++++- 3 files changed, 22 insertions(+), 17 deletions(-) diff --git a/indra/llcommon/llprofiler.h b/indra/llcommon/llprofiler.h index c03b2e93f4..394fbd05f6 100644 --- a/indra/llcommon/llprofiler.h +++ b/indra/llcommon/llprofiler.h @@ -87,7 +87,7 @@ extern thread_local bool gProfilerEnabled; #include "Tracy.hpp" // Enable OpenGL profiling - #define LL_PROFILER_ENABLE_TRACY_OPENGL 1 + #define LL_PROFILER_ENABLE_TRACY_OPENGL 0 // Enable RenderDoc labeling #define LL_PROFILER_ENABLE_RENDER_DOC 0 diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 028db79566..40ab4a2e0f 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -262,27 +262,29 @@ static GLuint gen_buffer() LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX; GLuint ret = 0; - if (!gGLManager.mIsAMD) + constexpr U32 pool_size = 4096; + + thread_local static GLuint sNamePool[pool_size]; + thread_local static U32 sIndex = 0; + + if (sIndex == 0) { - constexpr U32 pool_size = 4096; - - thread_local static GLuint sNamePool[pool_size]; - thread_local static U32 sIndex = 0; - - if (sIndex == 0) + LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("gen buffer"); + sIndex = pool_size; + if (!gGLManager.mIsAMD) { - LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("gen buffer"); - sIndex = pool_size; glGenBuffers(pool_size, sNamePool); } - - ret = sNamePool[--sIndex]; - } - else - { - glGenBuffers(1, &ret); + else + { // work around for AMD driver bug + for (U32 i = 0; i < pool_size; ++i) + { + glGenBuffers(1, sNamePool + i); + } + } } + ret = sNamePool[--sIndex]; return ret; } diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt index cf0968dfd2..2821b63391 100644 --- a/indra/newview/featuretable.txt +++ b/indra/newview/featuretable.txt @@ -1,4 +1,4 @@ -version 45 +version 46 // The version number above should be incremented IF AND ONLY IF some // change has been made that is sufficiently important to justify // resetting the graphics preferences of all users to the recommended @@ -291,6 +291,9 @@ RenderAnisotropic 1 0 RenderFSAASamples 1 0 RenderGLContextCoreProfile 1 0 +list AMD +RenderGLMultiThreaded 1 1 + list GL3 RenderFSAASamples 0 0 RenderReflectionsEnabled 0 0 From 8bad6ccde406566cd6859db69c45c06eb6001386 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Mon, 23 Jan 2023 12:24:06 -0600 Subject: [PATCH 09/31] SL-19015 Fix gamma correct shader noise parameters (remove banding) --- .../class1/deferred/postDeferredGammaCorrect.glsl | 4 +++- indra/newview/pipeline.cpp | 13 ++----------- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl index a73a59bc6f..987b2d1fe8 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl @@ -84,7 +84,9 @@ void main() //this is the one of the rare spots where diffuseRect contains linear color values (not sRGB) vec4 diff = texture2D(diffuseRect, vary_fragcoord); diff.rgb = linear_to_srgb(diff.rgb); - vec3 seed = (diff.rgb+vec3(1.0))*vec3(vary_fragcoord.xy, vary_fragcoord.x+vary_fragcoord.y); + vec2 tc = vary_fragcoord.xy*screen_res; + + vec3 seed = (diff.rgb+vec3(1.0))*vec3(tc.xy, tc.x+tc.y); vec3 nz = vec3(noise(seed.rg), noise(seed.gb), noise(seed.rb)); diff.rgb += nz*0.008; //diff.rgb = nz; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index aeb7341411..e534523d3c 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -7608,17 +7608,8 @@ void LLPipeline::renderFinalize() gDeferredPostGammaCorrectProgram.uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f / 2.2f)); - gGL.begin(LLRender::TRIANGLE_STRIP); - gGL.texCoord2f(tc1.mV[0], tc1.mV[1]); - gGL.vertex2f(-1, -1); - - gGL.texCoord2f(tc1.mV[0], tc2.mV[1]); - gGL.vertex2f(-1, 3); - - gGL.texCoord2f(tc2.mV[0], tc1.mV[1]); - gGL.vertex2f(3, -1); - - gGL.end(); + mScreenTriangleVB->setBuffer(); + mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); gGL.getTexUnit(channel)->unbind(screenTarget()->getUsage()); gDeferredPostGammaCorrectProgram.unbind(); From a3f43b4b73cc8fbd48a0574ebd74bbe660f8af50 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Mon, 23 Jan 2023 19:17:46 +0200 Subject: [PATCH 10/31] SL-19014 Sanitize the override data sent for faces without GLTF materials --- indra/newview/llgltfmateriallist.cpp | 25 +++++++++++++++++-------- indra/newview/llgltfmateriallist.h | 2 +- indra/newview/llmaterialeditor.cpp | 2 +- indra/newview/llpanelface.cpp | 2 +- indra/newview/llselectmgr.cpp | 2 +- 5 files changed, 21 insertions(+), 12 deletions(-) diff --git a/indra/newview/llgltfmateriallist.cpp b/indra/newview/llgltfmateriallist.cpp index 9399342a61..4cf1562042 100644 --- a/indra/newview/llgltfmateriallist.cpp +++ b/indra/newview/llgltfmateriallist.cpp @@ -392,15 +392,18 @@ void LLGLTFMaterialList::applyQueuedOverrides(LLViewerObject* obj) } } -void LLGLTFMaterialList::queueModify(const LLUUID& id, S32 side, const LLGLTFMaterial* mat) +void LLGLTFMaterialList::queueModify(const LLViewerObject* obj, S32 side, const LLGLTFMaterial* mat) { - if (mat == nullptr) + if (obj && obj->getRenderMaterialID(side).notNull()) { - sModifyQueue.push_back({ id, side, LLGLTFMaterial(), false }); - } - else - { - sModifyQueue.push_back({ id, side, *mat, true}); + if (mat == nullptr) + { + sModifyQueue.push_back({ obj->getID(), side, LLGLTFMaterial(), false }); + } + else + { + sModifyQueue.push_back({ obj->getID(), side, *mat, true }); + } } } @@ -437,8 +440,14 @@ void LLGLTFMaterialList::flushUpdates(void(*done_callback)(bool)) S32 i = data.size(); - for (auto& e : sModifyQueue) + for (ModifyMaterialData& e : sModifyQueue) { +#ifdef SHOW_ASSERT + // validate object has a material id + LLViewerObject* obj = gObjectList.findObject(e.object_id); + llassert(obj && obj->getRenderMaterialID(e.side).notNull()); +#endif + data[i]["object_id"] = e.object_id; data[i]["side"] = e.side; diff --git a/indra/newview/llgltfmateriallist.h b/indra/newview/llgltfmateriallist.h index 70540e5e01..5ce0e324f5 100644 --- a/indra/newview/llgltfmateriallist.h +++ b/indra/newview/llgltfmateriallist.h @@ -60,7 +60,7 @@ public: // mat - material to apply as override, or nullptr to remove existing overrides and revert to asset // // NOTE: do not use to revert to asset when applying a new asset id, use queueApply below - static void queueModify(const LLUUID& id, S32 side, const LLGLTFMaterial* mat); + static void queueModify(const LLViewerObject* obj, S32 side, const LLGLTFMaterial* mat); // Queue an application of a material asset we want to send to the simulator. Call "flushUpdates" to flush pending updates. // object_id - ID of object to apply material asset to diff --git a/indra/newview/llmaterialeditor.cpp b/indra/newview/llmaterialeditor.cpp index dabc7d16ea..a36ddeb532 100644 --- a/indra/newview/llmaterialeditor.cpp +++ b/indra/newview/llmaterialeditor.cpp @@ -2674,7 +2674,7 @@ public: { mSuccess = true; } - LLGLTFMaterialList::queueModify(objectp->getID(), te, material); + LLGLTFMaterialList::queueModify(objectp, te, material); } return true; } diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index cf02f3c4e4..cb09ec9fbf 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -152,7 +152,7 @@ void LLPanelFace::updateSelectedGLTFMaterials(std::functiongetGLTFMaterialOverride(); } mFunc(&new_override); - LLGLTFMaterialList::queueModify(object->getID(), face, &new_override); + LLGLTFMaterialList::queueModify(object, face, &new_override); return true; } diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 2b6578c272..1f604f3cba 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -2219,7 +2219,7 @@ void LLSelectMgr::selectionRevertGLTFMaterials() && asset_id.notNull()) { // Restore overrides - LLGLTFMaterialList::queueModify(objectp->getID(), te, nodep->mSavedGLTFOverrideMaterials[te]); + LLGLTFMaterialList::queueModify(objectp, te, nodep->mSavedGLTFOverrideMaterials[te]); } else { From 3b891301c448a1f1bf04512b1259c74ed54e573f Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Mon, 23 Jan 2023 13:25:10 -0600 Subject: [PATCH 11/31] SL-18772 Potential fix for failed shader load on Intel HD 3000 --- indra/newview/llviewershadermgr.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 13161d1c28..ce45a04272 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -3890,6 +3890,8 @@ BOOL LLViewerShaderMgr::loadShadersInterface() { gReflectionMipProgram.mName = "Reflection Mip Shader"; gReflectionMipProgram.mFeatures.isDeferred = true; + gReflectionMipProgram.mFeatures.hasGamma = true; + gReflectionMipProgram.mFeatures.hasAtmospherics = true; gReflectionMipProgram.mShaderFiles.clear(); gReflectionMipProgram.mShaderFiles.push_back(make_pair("interface/splattexturerectV.glsl", GL_VERTEX_SHADER)); gReflectionMipProgram.mShaderFiles.push_back(make_pair("interface/reflectionmipF.glsl", GL_FRAGMENT_SHADER)); From a78e03da6e2a36107b036c4d5dd94724f6a15376 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Mon, 23 Jan 2023 13:27:13 -0600 Subject: [PATCH 12/31] SL-19015 Fix for spot light shadows. --- indra/newview/pipeline.cpp | 47 +++++++------------------------------- indra/newview/pipeline.h | 2 +- 2 files changed, 9 insertions(+), 40 deletions(-) diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index e534523d3c..379ab55354 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -8997,16 +8997,11 @@ static LLTrace::BlockTimerStatHandle FTM_SHADOW_ALPHA_TREE("Alpha Tree"); static LLTrace::BlockTimerStatHandle FTM_SHADOW_ALPHA_GRASS("Alpha Grass"); static LLTrace::BlockTimerStatHandle FTM_SHADOW_FULLBRIGHT_ALPHA_MASKED("Fullbright Alpha Masked"); -void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& shadow_cam, LLCullResult& result, bool use_shader, bool use_occlusion, U32 target_width) +void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& shadow_cam, LLCullResult& result, bool depth_clamp) { LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; //LL_RECORD_BLOCK_TIME(FTM_SHADOW_RENDER); LL_PROFILE_GPU_ZONE("renderShadow"); - //disable occlusion culling for shadow passes (save setting to restore later) - S32 occlude = LLPipeline::sUseOcclusion; - if (!use_occlusion) - { - LLPipeline::sUseOcclusion = 0; - } + LLPipeline::sShadowRender = true; static const U32 types[] = { @@ -9029,21 +9024,14 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera LLGLEnable cull(GL_CULL_FACE); //enable depth clamping if available - LLGLEnable depth_clamp(GL_DEPTH_CLAMP); + LLGLEnable clamp_depth(depth_clamp ? GL_DEPTH_CLAMP : 0); LLGLDepthTest depth_test(GL_TRUE, GL_TRUE, GL_LESS); - if (use_shader) - { - gDeferredShadowCubeProgram.bind(); - } - - updateCull(shadow_cam, result); stateSort(shadow_cam, result); - //generate shadow map gGL.matrixMode(LLRender::MM_PROJECTION); gGL.pushMatrix(); @@ -9106,25 +9094,14 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); } - if (occlude > 1) + if (LLPipeline::sUseOcclusion > 1) { // do occlusion culling against non-masked only to take advantage of hierarchical Z doOcclusion(shadow_cam); } - if (use_shader) { LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("shadow geom"); - - gDeferredShadowProgram.unbind(); - renderGeomShadow(shadow_cam); - gDeferredShadowProgram.bind(); - gDeferredShadowProgram.uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0); - } - else - { - LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("shadow geom"); - renderGeomShadow(shadow_cam); } @@ -9132,6 +9109,8 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("shadow alpha"); LL_PROFILE_GPU_ZONE("shadow alpha"); + U32 target_width = LLRenderTarget::sCurResX; + for (int i = 0; i < 2; ++i) { bool rigged = i == 1; @@ -9213,11 +9192,6 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera gGLLastMatrix = NULL; gGL.loadMatrix(gGLModelView); - if (use_shader) - { - gDeferredShadowProgram.unbind(); - } - gGL.setColorMask(true, true); gGL.matrixMode(LLRender::MM_PROJECTION); @@ -9226,7 +9200,6 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera gGL.popMatrix(); gGLLastMatrix = NULL; - LLPipeline::sUseOcclusion = occlude; LLPipeline::sShadowRender = false; } @@ -10067,11 +10040,9 @@ void LLPipeline::generateSunShadow(LLCamera& camera) mRT->shadow[j].getViewport(gGLViewport); mRT->shadow[j].clear(); - U32 target_width = mRT->shadow[j].getWidth(); - { static LLCullResult result[4]; - renderShadow(view[j], proj[j], shadow_cam, result[j], true, true, target_width); + renderShadow(view[j], proj[j], shadow_cam, result[j], true); } mRT->shadow[j].flush(); @@ -10218,15 +10189,13 @@ void LLPipeline::generateSunShadow(LLCamera& camera) mSpotShadow[i].getViewport(gGLViewport); mSpotShadow[i].clear(); - U32 target_width = mSpotShadow[i].getWidth(); - static LLCullResult result[2]; LLViewerCamera::sCurCameraID = (LLViewerCamera::eCameraID)(LLViewerCamera::CAMERA_SPOT_SHADOW0 + i); RenderSpotLight = drawable; - renderShadow(view[i + 4], proj[i + 4], shadow_cam, result[i], false, true, target_width); + renderShadow(view[i + 4], proj[i + 4], shadow_cam, result[i], false); RenderSpotLight = nullptr; diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 83d316e15f..d87387e4c3 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -318,7 +318,7 @@ public: void renderHighlight(const LLViewerObject* obj, F32 fade); - void renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& camera, LLCullResult& result, bool use_shader, bool use_occlusion, U32 target_width); + void renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& camera, LLCullResult& result, bool depth_clamp); void renderHighlights(); void renderDebug(); void renderPhysicsDisplay(); From dcf05c57c8b934baf1597fbffc3f501a8e1538b0 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Mon, 23 Jan 2023 16:16:24 -0600 Subject: [PATCH 13/31] SL-18772 Potential fix for failed shader load on Intel HD 3000 --- indra/newview/llviewershadermgr.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index ce45a04272..498410bc2c 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -3892,6 +3892,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface() gReflectionMipProgram.mFeatures.isDeferred = true; gReflectionMipProgram.mFeatures.hasGamma = true; gReflectionMipProgram.mFeatures.hasAtmospherics = true; + gReflectionMipProgram.mFeatures.calculatesAtmospherics = true; gReflectionMipProgram.mShaderFiles.clear(); gReflectionMipProgram.mShaderFiles.push_back(make_pair("interface/splattexturerectV.glsl", GL_VERTEX_SHADER)); gReflectionMipProgram.mShaderFiles.push_back(make_pair("interface/reflectionmipF.glsl", GL_FRAGMENT_SHADER)); From 6419e7f9f96ddee14c33a97eef4860efff2b2923 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Mon, 23 Jan 2023 16:17:12 -0600 Subject: [PATCH 14/31] SL-19015 Fix for ugly SSAO --- .../shaders/class1/deferred/blurLightF.glsl | 16 +- indra/newview/pipeline.cpp | 172 ++++++------------ 2 files changed, 67 insertions(+), 121 deletions(-) diff --git a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl index 9bead273ff..93a85cad40 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl @@ -39,6 +39,7 @@ uniform sampler2D lightMap; uniform float dist_factor; uniform float blur_size; uniform vec2 delta; +uniform vec2 screen_res; uniform vec3 kern[4]; uniform float kern_scale; @@ -52,8 +53,8 @@ void main() vec2 tc = vary_fragcoord.xy; vec3 norm = getNorm(tc); vec3 pos = getPosition(tc).xyz; - vec4 ccol = texture2D(lightMap, tc).rgba; - + vec4 ccol = texture(lightMap, tc).rgba; + vec2 dlt = kern_scale * delta / (1.0+norm.xy*norm.xy); dlt /= max(-pos.z*dist_factor, 1.0); @@ -64,7 +65,8 @@ void main() float pointplanedist_tolerance_pow2 = pos.z*pos.z*0.00005; // perturb sampling origin slightly in screen-space to hide edge-ghosting artifacts where smoothing radius is quite large - float tc_mod = 0.5*(tc.x + tc.y); // mod(tc.x+tc.y,2) + tc *= screen_res; + float tc_mod = 0.5*(tc.x + tc.y); tc_mod -= floor(tc_mod); tc_mod *= 2.0; tc += ( (tc_mod - 0.5) * kern[1].z * dlt * 0.5 ); @@ -83,13 +85,14 @@ void main() for (int i = 1; i < 7; i++) { vec2 samptc = tc + k[i].z*dlt*2.0; + samptc /= screen_res; vec3 samppos = getPosition(samptc).xyz; float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane if (d*d <= pointplanedist_tolerance_pow2) { - col += texture2D(lightMap, samptc)*k[i].xyxx; + col += texture(lightMap, samptc)*k[i].xyxx; defined_weight += k[i].xy; } } @@ -97,19 +100,20 @@ void main() for (int i = 1; i < 7; i++) { vec2 samptc = tc - k[i].z*dlt*2.0; + samptc /= screen_res; vec3 samppos = getPosition(samptc).xyz; float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane if (d*d <= pointplanedist_tolerance_pow2) { - col += texture2D(lightMap, samptc)*k[i].xyxx; + col += texture(lightMap, samptc)*k[i].xyxx; defined_weight += k[i].xy; } } col /= defined_weight.xyxx; - //col.y *= max(col.y, 0.75); + //col.y *= col.y; frag_color = col; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 379ab55354..1ba139cd50 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -8135,8 +8135,6 @@ LLVector4 pow4fsrgb(LLVector4 v, F32 f) void LLPipeline::renderDeferredLighting() { - - LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; LL_PROFILE_GPU_ZONE("renderDeferredLighting"); if (!sCull) @@ -8145,31 +8143,12 @@ void LLPipeline::renderDeferredLighting() } LLRenderTarget *screen_target = &mRT->screen; - //LLRenderTarget *deferred_target = &mRT->deferredScreen; - //LLRenderTarget *deferred_depth_target = &mRT->deferredDepth; LLRenderTarget* deferred_light_target = &mRT->deferredLight; { - LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("deferred"); //LL_RECORD_BLOCK_TIME(FTM_RENDER_DEFERRED); + LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("deferred"); LLViewerCamera *camera = LLViewerCamera::getInstance(); -#if 0 - { - LLGLDepthTest depth(GL_TRUE); - deferred_depth_target->copyContents(*deferred_target, - 0, - 0, - deferred_target->getWidth(), - deferred_target->getHeight(), - 0, - 0, - deferred_depth_target->getWidth(), - deferred_depth_target->getHeight(), - GL_DEPTH_BUFFER_BIT, - GL_NEAREST); - } -#endif - LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE : 0); if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD)) @@ -8177,11 +8156,6 @@ void LLPipeline::renderDeferredLighting() gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD); } - // ati doesn't seem to love actually using the stencil buffer on FBO's - //LLGLDisable stencil(GL_STENCIL_TEST); - // glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF); - // glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); - gGL.setColorMask(true, true); // draw a cube around every light @@ -8251,76 +8225,64 @@ void LLPipeline::renderDeferredLighting() if (RenderDeferredSSAO) { - /*if (gCubeSnapshot) - { // SSAO and shadows disabled in reflection maps - deferred_light_target->bindTarget(); - glClearColor(1, 1, 1, 1); - deferred_light_target->clear(); - glClearColor(0, 0, 0, 0); - deferred_light_target->flush(); - } - else*/ + // soften direct lighting lightmap + LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("renderDeferredLighting - soften shadow"); + LL_PROFILE_GPU_ZONE("soften shadow"); + // blur lightmap + screen_target->bindTarget(); + glClearColor(1, 1, 1, 1); + screen_target->clear(GL_COLOR_BUFFER_BIT); + glClearColor(0, 0, 0, 0); + + bindDeferredShader(gDeferredBlurLightProgram); + + LLVector3 go = RenderShadowGaussian; + const U32 kern_length = 4; + F32 blur_size = RenderShadowBlurSize; + F32 dist_factor = RenderShadowBlurDistFactor; + + // sample symmetrically with the middle sample falling exactly on 0.0 + F32 x = 0.f; + + LLVector3 gauss[32]; // xweight, yweight, offset + + for (U32 i = 0; i < kern_length; i++) { - // soften direct lighting lightmap - LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("renderDeferredLighting - soften shadow"); - LL_PROFILE_GPU_ZONE("soften shadow"); - // blur lightmap - screen_target->bindTarget(); - glClearColor(1, 1, 1, 1); - screen_target->clear(GL_COLOR_BUFFER_BIT); - glClearColor(0, 0, 0, 0); - - bindDeferredShader(gDeferredBlurLightProgram); - mScreenTriangleVB->setBuffer(); - LLVector3 go = RenderShadowGaussian; - const U32 kern_length = 4; - F32 blur_size = RenderShadowBlurSize; - F32 dist_factor = RenderShadowBlurDistFactor; - - // sample symmetrically with the middle sample falling exactly on 0.0 - F32 x = 0.f; - - LLVector3 gauss[32]; // xweight, yweight, offset - - F32 screenPixelSize = 1.f / screen_target->getWidth(); - - for (U32 i = 0; i < kern_length; i++) - { - gauss[i].mV[0] = llgaussian(x, go.mV[0]); - gauss[i].mV[1] = llgaussian(x, go.mV[1]); - gauss[i].mV[2] = x; - x += screenPixelSize; - } - - gDeferredBlurLightProgram.uniform2f(sDelta, screenPixelSize, 0.f); - gDeferredBlurLightProgram.uniform1f(sDistFactor, dist_factor); - gDeferredBlurLightProgram.uniform3fv(sKern, kern_length, gauss[0].mV); - gDeferredBlurLightProgram.uniform1f(sKernScale, blur_size * (kern_length / 2.f - 0.5f)); - - { - LLGLDisable blend(GL_BLEND); - LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS); - mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - } - - screen_target->flush(); - unbindDeferredShader(gDeferredBlurLightProgram); - - bindDeferredShader(gDeferredBlurLightProgram, screen_target); - - mScreenTriangleVB->setBuffer(); - deferred_light_target->bindTarget(); - - gDeferredBlurLightProgram.uniform2f(sDelta, 0.f, 1.f); - - { - LLGLDisable blend(GL_BLEND); - LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS); - mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - } - deferred_light_target->flush(); - unbindDeferredShader(gDeferredBlurLightProgram); + gauss[i].mV[0] = llgaussian(x, go.mV[0]); + gauss[i].mV[1] = llgaussian(x, go.mV[1]); + gauss[i].mV[2] = x; + x += 1.f; } + + gDeferredBlurLightProgram.uniform2f(sDelta, 1.f, 0.f); + gDeferredBlurLightProgram.uniform1f(sDistFactor, dist_factor); + gDeferredBlurLightProgram.uniform3fv(sKern, kern_length, gauss[0].mV); + gDeferredBlurLightProgram.uniform1f(sKernScale, blur_size * (kern_length / 2.f - 0.5f)); + + { + LLGLDisable blend(GL_BLEND); + LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS); + mScreenTriangleVB->setBuffer(); + mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + } + + screen_target->flush(); + unbindDeferredShader(gDeferredBlurLightProgram); + + bindDeferredShader(gDeferredBlurLightProgram, screen_target); + + deferred_light_target->bindTarget(); + + gDeferredBlurLightProgram.uniform2f(sDelta, 0.f, 1.f); + + { + LLGLDisable blend(GL_BLEND); + LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS); + mScreenTriangleVB->setBuffer(); + mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + } + deferred_light_target->flush(); + unbindDeferredShader(gDeferredBlurLightProgram); } screen_target->bindTarget(); @@ -8346,33 +8308,13 @@ void LLPipeline::renderDeferredLighting() LLGLDisable test(GL_ALPHA_TEST); // full screen blit - mScreenTriangleVB->setBuffer(); mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - } unbindDeferredShader(LLPipeline::sUnderWaterRender ? gDeferredSoftenWaterProgram : gDeferredSoftenProgram); } -#if 0 - { // render non-deferred geometry (fullbright, alpha, etc) - LLGLDisable blend(GL_BLEND); - //LLGLDisable stencil(GL_STENCIL_TEST); - gGL.setSceneBlendType(LLRender::BT_ALPHA); - - gPipeline.pushRenderTypeMask(); - - gPipeline.andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY, - LLPipeline::RENDER_TYPE_CLOUDS, - LLPipeline::RENDER_TYPE_WL_SKY, - LLPipeline::END_RENDER_TYPES); - - renderGeomPostDeferred(*LLViewerCamera::getInstance(), false); - gPipeline.popRenderTypeMask(); - } -#endif - bool render_local = RenderLocalLights; // && !gCubeSnapshot; if (render_local) From bc6424779cda6ad03dbb59c2c14b91a7aa82bca9 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Tue, 24 Jan 2023 10:09:59 -0600 Subject: [PATCH 15/31] SL-18772 Potential fix for failed shader load on Intel HD 3000 --- indra/newview/llviewershadermgr.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 498410bc2c..690c22f437 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -1710,8 +1710,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { gDeferredTreeShadowProgram.mName = "Deferred Tree Shadow Shader"; gDeferredTreeShadowProgram.mShaderFiles.clear(); - gDeferredTreeShadowProgram.mFeatures.isDeferred = true; - gDeferredTreeShadowProgram.mFeatures.hasShadows = true; gDeferredTreeShadowProgram.mShaderFiles.push_back(make_pair("deferred/treeShadowV.glsl", GL_VERTEX_SHADER)); gDeferredTreeShadowProgram.mShaderFiles.push_back(make_pair("deferred/treeShadowF.glsl", GL_FRAGMENT_SHADER)); gDeferredTreeShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; @@ -1724,8 +1722,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { gDeferredSkinnedTreeShadowProgram.mName = "Deferred Skinned Tree Shadow Shader"; gDeferredSkinnedTreeShadowProgram.mShaderFiles.clear(); - gDeferredSkinnedTreeShadowProgram.mFeatures.isDeferred = true; - gDeferredSkinnedTreeShadowProgram.mFeatures.hasShadows = true; gDeferredSkinnedTreeShadowProgram.mFeatures.hasObjectSkinning = true; gDeferredSkinnedTreeShadowProgram.mShaderFiles.push_back(make_pair("deferred/treeShadowSkinnedV.glsl", GL_VERTEX_SHADER)); gDeferredSkinnedTreeShadowProgram.mShaderFiles.push_back(make_pair("deferred/treeShadowF.glsl", GL_FRAGMENT_SHADER)); From a851aa83e705fa4a1c78919cfcac6709cfb1a875 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Tue, 24 Jan 2023 12:50:17 -0600 Subject: [PATCH 16/31] SL-18958 Fix for broken water distortion map and depth buffer. Incidental decruft. --- indra/llrender/llglslshader.cpp | 5 + indra/llrender/llglslshader.h | 3 + indra/llrender/llrender.cpp | 7 +- .../shaders/class1/deferred/shadowUtil.glsl | 22 ++ indra/newview/lldrawpoolalpha.cpp | 6 - indra/newview/lldrawpoolwater.cpp | 233 ++++++++---------- indra/newview/llviewershadermgr.cpp | 13 +- indra/newview/pipeline.cpp | 84 +++---- 8 files changed, 184 insertions(+), 189 deletions(-) diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 982b2a847a..42b7cc46b3 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -1134,6 +1134,11 @@ S32 LLGLSLShader::unbindTexture(S32 uniform, LLTexUnit::eTextureType mode) return uniform; } +S32 LLGLSLShader::getTextureChannel(S32 uniform) const +{ + return mTexture[uniform]; +} + S32 LLGLSLShader::enableTexture(S32 uniform, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace space) { LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index 0522f78614..1ec41ebd3c 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -240,6 +240,9 @@ public: S32 enableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureColorSpace space = LLTexUnit::TCS_LINEAR); S32 disableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureColorSpace space = LLTexUnit::TCS_LINEAR); + // get the texture channel of the given uniform, or -1 if uniform is not used as a texture + S32 getTextureChannel(S32 uniform) const; + // bindTexture returns the texture unit we've bound the texture to. // You can reuse the return value to unbind a texture when required. S32 bindTexture(const std::string& uniform, LLTexture* texture, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureColorSpace space = LLTexUnit::TCS_LINEAR); diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index a8db69a9a4..d6b2aa2289 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -372,11 +372,8 @@ bool LLTexUnit::bind(LLRenderTarget* renderTarget, bool bindDepth) if (bindDepth) { - - if (renderTarget->getDepth() && !renderTarget->canSampleDepth()) - { - LL_ERRS() << "Cannot bind a render buffer for sampling. Allocate render target with depth buffer sampling enabled." << LL_ENDL; - } + llassert(renderTarget->getDepth()); // target MUST have a depth buffer attachment + llassert(renderTarget->canSampleDepth()); // depth buffer attachment MUST be sampleable bindManual(renderTarget->getUsage(), renderTarget->getDepth()); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowUtil.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowUtil.glsl index 5dc219702d..cd49202f89 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/shadowUtil.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/shadowUtil.glsl @@ -25,12 +25,18 @@ uniform sampler2D normalMap; uniform sampler2D depthMap; + +#if defined(SUN_SHADOW) uniform sampler2DShadow shadowMap0; uniform sampler2DShadow shadowMap1; uniform sampler2DShadow shadowMap2; uniform sampler2DShadow shadowMap3; +#endif + +#if defined(SPOT_SHADOW) uniform sampler2DShadow shadowMap4; uniform sampler2DShadow shadowMap5; +#endif uniform vec3 sun_dir; uniform vec3 moon_dir; @@ -48,6 +54,7 @@ uniform int sun_up_factor; float pcfShadow(sampler2DShadow shadowMap, vec3 norm, vec4 stc, float bias_mul, vec2 pos_screen, vec3 light_dir) { +#if defined(SUN_SHADOW) float offset = shadow_bias * bias_mul; stc.xyz /= stc.w; stc.z += offset * 2.0; @@ -59,10 +66,14 @@ float pcfShadow(sampler2DShadow shadowMap, vec3 norm, vec4 stc, float bias_mul, shadow += shadow2D(shadowMap, stc.xyz+vec3(-1.5/shadow_res.x, -0.5/shadow_res.y, 0.0)).x; shadow += shadow2D(shadowMap, stc.xyz+vec3(-0.5/shadow_res.x, 1.5/shadow_res.y, 0.0)).x; return clamp(shadow * 0.125, 0.0, 1.0); +#else + return 1.0; +#endif } float pcfSpotShadow(sampler2DShadow shadowMap, vec4 stc, float bias_scale, vec2 pos_screen) { +#if defined(SPOT_SHADOW) stc.xyz /= stc.w; stc.z += spot_shadow_bias * bias_scale; stc.x = floor(proj_shadow_res.x * stc.x + fract(pos_screen.y*0.666666666)) / proj_shadow_res.x; // snap @@ -78,10 +89,14 @@ float pcfSpotShadow(sampler2DShadow shadowMap, vec4 stc, float bias_scale, vec2 shadow += shadow2D(shadowMap, stc.xyz+vec3(-off.x, off.y, 0.0)).x; shadow += shadow2D(shadowMap, stc.xyz+vec3(-off.x*2.0, -off.y, 0.0)).x; return shadow*0.2; +#else + return 1.0; +#endif } float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen) { +#if defined(SUN_SHADOW) float shadow = 0.0f; vec3 light_dir = normalize((sun_up_factor == 1) ? sun_dir : moon_dir); @@ -175,10 +190,14 @@ float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen) } //shadow = min(dp_directional_light,shadow); return shadow; +#else + return 1.0; +#endif } float sampleSpotShadow(vec3 pos, vec3 norm, int index, vec2 pos_screen) { +#if defined(SPOT_SHADOW) float shadow = 0.0f; pos += norm * spot_shadow_offset; @@ -217,5 +236,8 @@ float sampleSpotShadow(vec3 pos, vec3 norm, int index, vec2 pos_screen) shadow = 1.0f; } return shadow; +#else + return 1.0; +#endif } diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index 20d3818934..9f1dc979f8 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -193,10 +193,6 @@ void LLDrawPoolAlpha::renderPostDeferred(S32 pass) if (!LLPipeline::sImpostorRender && gSavedSettings.getBOOL("RenderDepthOfField") && !gCubeSnapshot) { //update depth buffer sampler - /*gPipeline.mRT->screen.flush(); - gPipeline.mRT->deferredDepth.copyContents(gPipeline.mRT->deferredScreen, 0, 0, gPipeline.mRT->deferredScreen.getWidth(), gPipeline.mRT->deferredScreen.getHeight(), - 0, 0, gPipeline.mRT->deferredDepth.getWidth(), gPipeline.mRT->deferredDepth.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST); - gPipeline.mRT->deferredDepth.bindTarget();*/ simple_shader = fullbright_shader = &gObjectFullbrightAlphaMaskProgram; simple_shader->bind(); @@ -210,8 +206,6 @@ void LLDrawPoolAlpha::renderPostDeferred(S32 pass) renderAlpha(getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX | LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2, true); // <--- discard mostly transparent faces - //gPipeline.mRT->deferredDepth.flush(); - //gPipeline.mRT->screen.bindTarget(); gGL.setColorMask(true, false); } diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp index 1808fb5987..35a2e8741f 100644 --- a/indra/newview/lldrawpoolwater.cpp +++ b/indra/newview/lldrawpoolwater.cpp @@ -50,8 +50,6 @@ #include "llsettingssky.h" #include "llsettingswater.h" -BOOL deferred_render = FALSE; - BOOL LLDrawPoolWater::sSkipScreenCopy = FALSE; BOOL LLDrawPoolWater::sNeedsReflectionUpdate = TRUE; BOOL LLDrawPoolWater::sNeedsDistortionUpdate = TRUE; @@ -110,21 +108,26 @@ S32 LLDrawPoolWater::getNumPostDeferredPasses() void LLDrawPoolWater::beginPostDeferredPass(S32 pass) { LL_PROFILE_GPU_ZONE("water beginPostDeferredPass") + gGL.setColorMask(true, true); + if (LLPipeline::sRenderTransparentWater && !gCubeSnapshot) { // copy framebuffer contents so far to a texture to be used for // reflections and refractions + LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS); + LLRenderTarget& src = gPipeline.mRT->screen; + LLRenderTarget& depth_src = gPipeline.mRT->deferredScreen; LLRenderTarget& dst = gPipeline.mWaterDis; dst.bindTarget(); gCopyDepthProgram.bind(); - S32 diff_map = gCopyDepthProgram.enableTexture(LLShaderMgr::DIFFUSE_MAP); - S32 depth_map = gCopyDepthProgram.enableTexture(LLShaderMgr::DEFERRED_DEPTH); + S32 diff_map = gCopyDepthProgram.getTextureChannel(LLShaderMgr::DIFFUSE_MAP); + S32 depth_map = gCopyDepthProgram.getTextureChannel(LLShaderMgr::DEFERRED_DEPTH); gGL.getTexUnit(diff_map)->bind(&src); - gGL.getTexUnit(depth_map)->bind(&src, true); + gGL.getTexUnit(depth_map)->bind(&depth_src, true); gPipeline.mScreenTriangleVB->setBuffer(); gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); @@ -136,12 +139,9 @@ void LLDrawPoolWater::beginPostDeferredPass(S32 pass) void LLDrawPoolWater::renderPostDeferred(S32 pass) { LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; - if (!deferred_render) - { - gGL.setColorMask(true, true); - } - LLGLDisable blend(GL_BLEND); + + gGL.setColorMask(true, true); LLColor3 light_diffuse(0, 0, 0); F32 light_exp = 0.0f; @@ -188,195 +188,174 @@ void LLDrawPoolWater::renderPostDeferred(S32 pass) LLGLSLShader *shader = nullptr; // two passes, first with standard water shader bound, second with edge water shader bound - for( int edge = 0 ; edge < 2; edge++ ) + for (int edge = 0; edge < 2; edge++) { // select shader if (underwater) { - shader = deferred_render ? &gDeferredUnderWaterProgram : &gUnderWaterProgram; + shader = &gUnderWaterProgram; } else { - if (edge && !deferred_render) + if (edge) { shader = &gWaterEdgeProgram; } else { - shader = deferred_render ? &gDeferredWaterProgram : &gWaterProgram; + shader = &gWaterProgram; } } gPipeline.bindDeferredShader(*shader); - - // bind textures for water rendering - S32 reftex = shader->enableTexture(LLShaderMgr::WATER_REFTEX); - if (reftex > -1) - { - gGL.getTexUnit(reftex)->activate(); - gGL.getTexUnit(reftex)->bind(&gPipeline.mWaterRef); - gGL.getTexUnit(0)->activate(); - } - //bind normal map - S32 bumpTex = shader->enableTexture(LLViewerShaderMgr::BUMP_MAP); - S32 bumpTex2 = shader->enableTexture(LLViewerShaderMgr::BUMP_MAP2); + //bind normal map + S32 bumpTex = shader->enableTexture(LLViewerShaderMgr::BUMP_MAP); + S32 bumpTex2 = shader->enableTexture(LLViewerShaderMgr::BUMP_MAP2); - LLViewerTexture* tex_a = mWaterNormp[0]; - LLViewerTexture* tex_b = mWaterNormp[1]; + LLViewerTexture* tex_a = mWaterNormp[0]; + LLViewerTexture* tex_b = mWaterNormp[1]; F32 blend_factor = pwater->getBlendFactor(); - - gGL.getTexUnit(bumpTex)->unbind(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(bumpTex2)->unbind(LLTexUnit::TT_TEXTURE); - if (tex_a && (!tex_b || (tex_a == tex_b))) - { - gGL.getTexUnit(bumpTex)->bind(tex_a); - blend_factor = 0; // only one tex provided, no blending - } - else if (tex_b && !tex_a) - { - gGL.getTexUnit(bumpTex)->bind(tex_b); - blend_factor = 0; // only one tex provided, no blending - } - else if (tex_b != tex_a) - { - gGL.getTexUnit(bumpTex)->bind(tex_a); - gGL.getTexUnit(bumpTex2)->bind(tex_b); - } - - // bind reflection texture from RenderTarget - S32 screentex = shader->enableTexture(LLShaderMgr::WATER_SCREENTEX); - S32 screenDepth = shader->enableTexture(LLShaderMgr::WATER_SCREENDEPTH); + gGL.getTexUnit(bumpTex)->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(bumpTex2)->unbind(LLTexUnit::TT_TEXTURE); - F32 screenRes[] = {1.f / gGLViewport[2], 1.f / gGLViewport[3]}; - - S32 diffTex = shader->enableTexture(LLShaderMgr::DIFFUSE_MAP); - - // set uniforms for shader - if (deferred_render) + if (tex_a && (!tex_b || (tex_a == tex_b))) { - if (shader->getUniformLocation(LLShaderMgr::DEFERRED_NORM_MATRIX) >= 0) - { - glh::matrix4f norm_mat = get_current_modelview().inverse().transpose(); - shader->uniformMatrix4fv(LLShaderMgr::DEFERRED_NORM_MATRIX, 1, FALSE, norm_mat.m); - } + gGL.getTexUnit(bumpTex)->bind(tex_a); + blend_factor = 0; // only one tex provided, no blending + } + else if (tex_b && !tex_a) + { + gGL.getTexUnit(bumpTex)->bind(tex_b); + blend_factor = 0; // only one tex provided, no blending + } + else if (tex_b != tex_a) + { + gGL.getTexUnit(bumpTex)->bind(tex_a); + gGL.getTexUnit(bumpTex2)->bind(tex_b); } - shader->uniform2fv(LLShaderMgr::DEFERRED_SCREEN_RES, 1, screenRes); - shader->uniform1f(LLShaderMgr::BLEND_FACTOR, blend_factor); + // bind reflection texture from RenderTarget + S32 screentex = shader->enableTexture(LLShaderMgr::WATER_SCREENTEX); + S32 screenDepth = shader->enableTexture(LLShaderMgr::WATER_SCREENDEPTH); - F32 fog_density = pwater->getModifiedWaterFogDensity(underwater); + F32 screenRes[] = { 1.f / gGLViewport[2], 1.f / gGLViewport[3] }; + + S32 diffTex = shader->enableTexture(LLShaderMgr::DIFFUSE_MAP); + + shader->uniform2fv(LLShaderMgr::DEFERRED_SCREEN_RES, 1, screenRes); + shader->uniform1f(LLShaderMgr::BLEND_FACTOR, blend_factor); + + F32 fog_density = pwater->getModifiedWaterFogDensity(underwater); + + if (screentex > -1) + { + shader->uniform1f(LLShaderMgr::WATER_FOGDENSITY, fog_density); + gGL.getTexUnit(screentex)->bind(&gPipeline.mWaterDis); + } - if (screentex > -1) - { - shader->uniform1f(LLShaderMgr::WATER_FOGDENSITY, fog_density); - gGL.getTexUnit(screentex)->bind(&gPipeline.mWaterDis); - } - if (screenDepth > -1) { gGL.getTexUnit(screenDepth)->bind(&gPipeline.mWaterDis, true); } - if (mShaderLevel == 1) - { - fog_color.mV[VW] = log(fog_density) / log(2); - } + if (mShaderLevel == 1) + { + fog_color.mV[VW] = log(fog_density) / log(2); + } - F32 water_height = environment.getWaterHeight(); + F32 water_height = environment.getWaterHeight(); F32 camera_height = LLViewerCamera::getInstance()->getOrigin().mV[2]; shader->uniform1f(LLShaderMgr::WATER_WATERHEIGHT, camera_height - water_height); shader->uniform1f(LLShaderMgr::WATER_TIME, phase_time); shader->uniform3fv(LLShaderMgr::WATER_EYEVEC, 1, LLViewerCamera::getInstance()->getOrigin().mV); shader->uniform4fv(LLShaderMgr::SPECULAR_COLOR, 1, specular.mV); - shader->uniform4fv(LLShaderMgr::WATER_FOGCOLOR, 1, fog_color.mV); + shader->uniform4fv(LLShaderMgr::WATER_FOGCOLOR, 1, fog_color.mV); shader->uniform3fv(LLShaderMgr::WATER_FOGCOLOR_LINEAR, 1, fog_color_linear.mV); - shader->uniform3fv(LLShaderMgr::WATER_SPECULAR, 1, light_diffuse.mV); - shader->uniform1f(LLShaderMgr::WATER_SPECULAR_EXP, light_exp); + shader->uniform3fv(LLShaderMgr::WATER_SPECULAR, 1, light_diffuse.mV); + shader->uniform1f(LLShaderMgr::WATER_SPECULAR_EXP, light_exp); - shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR1, 1, pwater->getWave1Dir().mV); - shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR2, 1, pwater->getWave2Dir().mV); + shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR1, 1, pwater->getWave1Dir().mV); + shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR2, 1, pwater->getWave2Dir().mV); - shader->uniform3fv(LLShaderMgr::WATER_LIGHT_DIR, 1, light_dir.mV); + shader->uniform3fv(LLShaderMgr::WATER_LIGHT_DIR, 1, light_dir.mV); - shader->uniform3fv(LLShaderMgr::WATER_NORM_SCALE, 1, pwater->getNormalScale().mV); - shader->uniform1f(LLShaderMgr::WATER_FRESNEL_SCALE, pwater->getFresnelScale()); - shader->uniform1f(LLShaderMgr::WATER_FRESNEL_OFFSET, pwater->getFresnelOffset()); - shader->uniform1f(LLShaderMgr::WATER_BLUR_MULTIPLIER, pwater->getBlurMultiplier()); + shader->uniform3fv(LLShaderMgr::WATER_NORM_SCALE, 1, pwater->getNormalScale().mV); + shader->uniform1f(LLShaderMgr::WATER_FRESNEL_SCALE, pwater->getFresnelScale()); + shader->uniform1f(LLShaderMgr::WATER_FRESNEL_OFFSET, pwater->getFresnelOffset()); + shader->uniform1f(LLShaderMgr::WATER_BLUR_MULTIPLIER, pwater->getBlurMultiplier()); - F32 sunAngle = llmax(0.f, light_dir.mV[1]); - F32 scaledAngle = 1.f - sunAngle; + F32 sunAngle = llmax(0.f, light_dir.mV[1]); + F32 scaledAngle = 1.f - sunAngle; shader->uniform1i(LLShaderMgr::SUN_UP_FACTOR, sun_up ? 1 : 0); - shader->uniform1f(LLShaderMgr::WATER_SUN_ANGLE, sunAngle); - shader->uniform1f(LLShaderMgr::WATER_SCALED_ANGLE, scaledAngle); - shader->uniform1f(LLShaderMgr::WATER_SUN_ANGLE2, 0.1f + 0.2f*sunAngle); - shader->uniform1i(LLShaderMgr::WATER_EDGE_FACTOR, edge ? 1 : 0); + shader->uniform1f(LLShaderMgr::WATER_SUN_ANGLE, sunAngle); + shader->uniform1f(LLShaderMgr::WATER_SCALED_ANGLE, scaledAngle); + shader->uniform1f(LLShaderMgr::WATER_SUN_ANGLE2, 0.1f + 0.2f * sunAngle); + shader->uniform1i(LLShaderMgr::WATER_EDGE_FACTOR, edge ? 1 : 0); - // SL-15861 This was changed from getRotatedLightNorm() as it was causing - // lightnorm in shaders\class1\windlight\atmosphericsFuncs.glsl in have inconsistent additive lighting for 180 degrees of the FOV. - LLVector4 rotated_light_direction = LLEnvironment::instance().getClampedLightNorm(); - shader->uniform3fv(LLViewerShaderMgr::LIGHTNORM, 1, rotated_light_direction.mV); + // SL-15861 This was changed from getRotatedLightNorm() as it was causing + // lightnorm in shaders\class1\windlight\atmosphericsFuncs.glsl in have inconsistent additive lighting for 180 degrees of the FOV. + LLVector4 rotated_light_direction = LLEnvironment::instance().getClampedLightNorm(); + shader->uniform3fv(LLViewerShaderMgr::LIGHTNORM, 1, rotated_light_direction.mV); - shader->uniform3fv(LLShaderMgr::WL_CAMPOSLOCAL, 1, LLViewerCamera::getInstance()->getOrigin().mV); + shader->uniform3fv(LLShaderMgr::WL_CAMPOSLOCAL, 1, LLViewerCamera::getInstance()->getOrigin().mV); - if (LLViewerCamera::getInstance()->cameraUnderWater()) - { - shader->uniform1f(LLShaderMgr::WATER_REFSCALE, pwater->getScaleBelow()); - } - else - { - shader->uniform1f(LLShaderMgr::WATER_REFSCALE, pwater->getScaleAbove()); - } + if (LLViewerCamera::getInstance()->cameraUnderWater()) + { + shader->uniform1f(LLShaderMgr::WATER_REFSCALE, pwater->getScaleBelow()); + } + else + { + shader->uniform1f(LLShaderMgr::WATER_REFSCALE, pwater->getScaleAbove()); + } - LLGLDisable cullface(GL_CULL_FACE); + LLGLDisable cullface(GL_CULL_FACE); - LLVOWater *water = nullptr; - for (LLFace *const &face : mDrawFace) + LLVOWater* water = nullptr; + for (LLFace* const& face : mDrawFace) { if (!face) continue; - water = static_cast(face->getViewerObject()); + water = static_cast(face->getViewerObject()); if (!water) continue; - gGL.getTexUnit(diffTex)->bind(face->getTexture()); + gGL.getTexUnit(diffTex)->bind(face->getTexture()); - if ((bool)edge == (bool) water->getIsEdgePatch()) - { - face->renderIndexed(); + if ((bool)edge == (bool)water->getIsEdgePatch()) + { + face->renderIndexed(); // Note non-void water being drawn, updates required if (!edge) // SL-16461 remove !LLPipeline::sUseOcclusion check - { - sNeedsReflectionUpdate = TRUE; - sNeedsDistortionUpdate = TRUE; + { + sNeedsReflectionUpdate = TRUE; + sNeedsDistortionUpdate = TRUE; } - } + } } - shader->disableTexture(LLShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP); - shader->disableTexture(LLShaderMgr::WATER_SCREENTEX); - shader->disableTexture(LLShaderMgr::BUMP_MAP); - shader->disableTexture(LLShaderMgr::DIFFUSE_MAP); - shader->disableTexture(LLShaderMgr::WATER_REFTEX); - shader->disableTexture(LLShaderMgr::WATER_SCREENDEPTH); + shader->disableTexture(LLShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP); + shader->disableTexture(LLShaderMgr::WATER_SCREENTEX); + shader->disableTexture(LLShaderMgr::BUMP_MAP); + shader->disableTexture(LLShaderMgr::DIFFUSE_MAP); + shader->disableTexture(LLShaderMgr::WATER_REFTEX); + shader->disableTexture(LLShaderMgr::WATER_SCREENDEPTH); // clean up gPipeline.unbindDeferredShader(*shader); gGL.getTexUnit(bumpTex)->unbind(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(bumpTex2)->unbind(LLTexUnit::TT_TEXTURE); - } + } gGL.getTexUnit(0)->activate(); gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); - if (!deferred_render) - { - gGL.setColorMask(true, false); - } + + gGL.setColorMask(true, false); } LLViewerTexture *LLDrawPoolWater::getDebugTexture() diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 690c22f437..874dec2c2d 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -496,7 +496,6 @@ void LLViewerShaderMgr::setShaders() //bool canRenderDeferred = true; // DEPRECATED -- LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred"); //bool hasWindLightShaders = true; // DEPRECATED -- LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders"); - //S32 shadow_detail = gSavedSettings.getS32("RenderShadowDetail"); bool doingWindLight = true; //DEPRECATED -- hasWindLightShaders&& gSavedSettings.getBOOL("WindLightUseAtmosShaders"); S32 light_class = 3; @@ -860,6 +859,18 @@ std::string LLViewerShaderMgr::loadBasicShaders() attribs["LOCAL_LIGHT_KILL"] = "1"; } + S32 shadow_detail = gSavedSettings.getS32("RenderShadowDetail"); + + if (shadow_detail >= 1) + { + attribs["SUN_SHADOW"] = "1"; + + if (shadow_detail >= 2) + { + attribs["SPOT_SHADOW"] = "1"; + } + } + // We no longer have to bind the shaders to global glhandles, they are automatically added to a map now. for (U32 i = 0; i < shaders.size(); i++) { diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 1ba139cd50..f0644cbbf5 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -841,62 +841,46 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) } } - if (LLPipeline::sRenderDeferred) - { - S32 shadow_detail = RenderShadowDetail; - bool ssao = RenderDeferredSSAO; + S32 shadow_detail = RenderShadowDetail; + bool ssao = RenderDeferredSSAO; - //allocate deferred rendering color buffers - if (!mRT->deferredScreen.allocate(resX, resY, GL_RGBA, true, true, LLTexUnit::TT_TEXTURE, false, samples)) return false; - if (!addDeferredAttachments(mRT->deferredScreen)) return false; + //allocate deferred rendering color buffers + if (!mRT->deferredScreen.allocate(resX, resY, GL_RGBA, true, true, LLTexUnit::TT_TEXTURE, false, samples)) return false; + if (!addDeferredAttachments(mRT->deferredScreen)) return false; - GLuint screenFormat = GL_RGBA16; + GLuint screenFormat = GL_RGBA16; - if (!mRT->screen.allocate(resX, resY, screenFormat, FALSE, true, LLTexUnit::TT_TEXTURE, FALSE, samples)) return false; + if (!mRT->screen.allocate(resX, resY, screenFormat, FALSE, true, LLTexUnit::TT_TEXTURE, FALSE, samples)) return false; - mRT->deferredScreen.shareDepthBuffer(mRT->screen); + mRT->deferredScreen.shareDepthBuffer(mRT->screen); - if (samples > 0) - { - if (!mRT->fxaaBuffer.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_TEXTURE, FALSE, samples)) return false; - } - else - { - mRT->fxaaBuffer.release(); - } - - if (shadow_detail > 0 || ssao || RenderDepthOfField || samples > 0) - { //only need mRT->deferredLight for shadows OR ssao OR dof OR fxaa - if (!mRT->deferredLight.allocate(resX, resY, GL_RGBA16, FALSE, FALSE, LLTexUnit::TT_TEXTURE, FALSE)) return false; - } - else - { - mRT->deferredLight.release(); - } - - allocateShadowBuffer(resX, resY); - - //HACK make screenbuffer allocations start failing after 30 seconds - if (gSavedSettings.getBOOL("SimulateFBOFailure")) - { - return false; - } - } - else - { - mRT->deferredLight.release(); - - releaseSunShadowTargets(); - releaseSpotShadowTargets(); - - mRT->fxaaBuffer.release(); - mRT->screen.release(); - mRT->deferredScreen.release(); //make sure to release any render targets that share a depth buffer with mRT->deferredScreen first - - if (!mRT->screen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_TEXTURE, FALSE)) return false; + if (samples > 0) + { + if (!mRT->fxaaBuffer.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_TEXTURE, FALSE, samples)) return false; } - - gGL.getTexUnit(0)->disable(); + else + { + mRT->fxaaBuffer.release(); + } + + if (shadow_detail > 0 || ssao || RenderDepthOfField || samples > 0) + { //only need mRT->deferredLight for shadows OR ssao OR dof OR fxaa + if (!mRT->deferredLight.allocate(resX, resY, GL_RGBA16, FALSE, FALSE, LLTexUnit::TT_TEXTURE, FALSE)) return false; + } + else + { + mRT->deferredLight.release(); + } + + allocateShadowBuffer(resX, resY); + + //HACK make screenbuffer allocations start failing after 30 seconds + if (gSavedSettings.getBOOL("SimulateFBOFailure")) + { + return false; + } + + gGL.getTexUnit(0)->disable(); stop_glerror(); From fea731ecb3fbe0472777bfafa98156ebe75a5049 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Tue, 24 Jan 2023 14:02:53 -0600 Subject: [PATCH 17/31] SL-19023 Reformat SSR shaders to match style standard. --- .../class3/deferred/screenSpaceReflPostF.glsl | 32 ++-- .../class3/deferred/screenSpaceReflUtil.glsl | 162 ++++++++++-------- 2 files changed, 109 insertions(+), 85 deletions(-) diff --git a/indra/newview/app_settings/shaders/class3/deferred/screenSpaceReflPostF.glsl b/indra/newview/app_settings/shaders/class3/deferred/screenSpaceReflPostF.glsl index d48aeb98b6..4813e6c2d9 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/screenSpaceReflPostF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/screenSpaceReflPostF.glsl @@ -58,8 +58,12 @@ vec4 getPositionWithDepth(vec2 pos_screen, float depth); vec4 getPosition(vec2 pos_screen); vec4 getNormalEnvIntensityFlags(vec2 screenpos, out vec3 n, out float envIntensity); bool traceScreenRay(vec3 position, vec3 reflection, out vec4 hitColor, out float hitDepth, float depth, sampler2D textureFrame); + float random (vec2 uv); -void main() { + + +void main() +{ vec2 tc = vary_fragcoord.xy; float depth = linearDepth01(getDepth(tc), zNear, zFar); vec3 n = vec3(0, 0, 1); @@ -74,7 +78,8 @@ void main() { vec4 diffuse = texture2D(diffuseRect, tc); vec3 specCol = spec.rgb; - if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR)) { + if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR)) + { vec3 orm = specCol.rgb; float perceptualRoughness = orm.g; float metallic = orm.b; @@ -86,12 +91,12 @@ void main() { specCol = mix(f0, baseColor.rgb, metallic); } - vec2 uv2 = tc * screen_res; - float c = (uv2.x + uv2.y) * 0.125; - float jitter = mod( c, 1.0); + vec2 uv2 = tc * screen_res; + float c = (uv2.x + uv2.y) * 0.125; + float jitter = mod( c, 1.0); vec3 firstBasis = normalize(cross(vec3(1.f, 1.f, 1.f), rayDirection)); - vec3 secondBasis = normalize(cross(rayDirection, firstBasis)); + vec3 secondBasis = normalize(cross(rayDirection, firstBasis)); frag_color = texture(diffuseMap, tc); vec4 collectedColor; @@ -100,17 +105,22 @@ void main() { float vignette = clamp((screenpos.x * screenpos.y) * 16,0, 1); vignette *= clamp((dot(normalize(viewPos), n) * 0.5 + 0.5 - 0.2) * 8, 0, 1); vignette *= min(linearDepth(getDepth(tc), zNear, zFar) / zFar, 1); + int totalSamples = 4; - for (int i = 0; i < totalSamples; i++) { - vec2 coeffs = vec2(random(tc + vec2(0, i)) + random(tc + vec2(i, 0))); - vec3 reflectionDirectionRandomized = rayDirection + firstBasis * coeffs.x + secondBasis * coeffs.y; + + for (int i = 0; i < totalSamples; i++) + { + vec2 coeffs = vec2(random(tc + vec2(0, i)) + random(tc + vec2(i, 0))); + vec3 reflectionDirectionRandomized = rayDirection + firstBasis * coeffs.x + secondBasis * coeffs.y; bool hit = traceScreenRay(pos, reflectionDirectionRandomized, hitpoint, depth, depth, diffuseMap); - if (hit) { + + if (hit) + { collectedColor += hitpoint; collectedColor.rgb *= specCol.rgb; } - } + } collectedColor *= vignette; diff --git a/indra/newview/app_settings/shaders/class3/deferred/screenSpaceReflUtil.glsl b/indra/newview/app_settings/shaders/class3/deferred/screenSpaceReflUtil.glsl index f8c6e5701a..b6c789ad40 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/screenSpaceReflUtil.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/screenSpaceReflUtil.glsl @@ -37,17 +37,19 @@ float linearDepth(float depth, float near, float far); float getDepth(vec2 pos_screen); float linearDepth01(float d, float znear, float zfar); -float random (vec2 uv) { - return fract(sin(dot(uv, vec2(12.9898, 78.233))) * 43758.5453123); //simple random function +float random (vec2 uv) +{ + return fract(sin(dot(uv, vec2(12.9898, 78.233))) * 43758.5453123); //simple random function } // Based off of https://github.com/RoundedGlint585/ScreenSpaceReflection/ // A few tweaks here and there to suit our needs. -vec2 generateProjectedPosition(vec3 pos){ - vec4 samplePosition = projection_matrix * vec4(pos, 1.f); - samplePosition.xy = (samplePosition.xy / samplePosition.w) * 0.5 + 0.5; - return samplePosition.xy; +vec2 generateProjectedPosition(vec3 pos) +{ + vec4 samplePosition = projection_matrix * vec4(pos, 1.f); + samplePosition.xy = (samplePosition.xy / samplePosition.w) * 0.5 + 0.5; + return samplePosition.xy; } bool isBinarySearchEnabled = true; @@ -60,79 +62,91 @@ float distanceBias = 0.02; float depthRejectBias = 0.001; float epsilon = 0.1; -bool traceScreenRay(vec3 position, vec3 reflection, out vec4 hitColor, out float hitDepth, float depth, sampler2D textureFrame) { - vec3 step = rayStep * reflection; - vec3 marchingPosition = position + step; - float delta; - float depthFromScreen; - vec2 screenPosition; +bool traceScreenRay(vec3 position, vec3 reflection, out vec4 hitColor, out float hitDepth, float depth, sampler2D textureFrame) +{ + vec3 step = rayStep * reflection; + vec3 marchingPosition = position + step; + float delta; + float depthFromScreen; + vec2 screenPosition; bool hit = false; hitColor = vec4(0); - - int i = 0; - if (depth > depthRejectBias) { - for (; i < iterationCount && !hit; i++) { - screenPosition = generateProjectedPosition(marchingPosition); - depthFromScreen = linearDepth(getDepth(screenPosition), zNear, zFar); - delta = abs(marchingPosition.z) - depthFromScreen; - - if (depth < depthFromScreen + epsilon && depth > depthFromScreen - epsilon) { - break; - } + + int i = 0; + if (depth > depthRejectBias) + { + for (; i < iterationCount && !hit; i++) + { + screenPosition = generateProjectedPosition(marchingPosition); + depthFromScreen = linearDepth(getDepth(screenPosition), zNear, zFar); + delta = abs(marchingPosition.z) - depthFromScreen; + + if (depth < depthFromScreen + epsilon && depth > depthFromScreen - epsilon) + { + break; + } - if (abs(delta) < distanceBias) { - vec4 color = vec4(1); - if(debugDraw) - color = vec4( 0.5+ sign(delta)/2,0.3,0.5- sign(delta)/2, 0); - hitColor = texture(textureFrame, screenPosition) * color; - hitDepth = depthFromScreen; - hit = true; - break; - } - if (isBinarySearchEnabled && delta > 0) { - break; - } - if (isAdaptiveStepEnabled){ - float directionSign = sign(abs(marchingPosition.z) - depthFromScreen); - //this is sort of adapting step, should prevent lining reflection by doing sort of iterative converging - //some implementation doing it by binary search, but I found this idea more cheaty and way easier to implement - step = step * (1.0 - rayStep * max(directionSign, 0.0)); - marchingPosition += step * (-directionSign); - } - else { - marchingPosition += step; - } + if (abs(delta) < distanceBias) + { + vec4 color = vec4(1); + if(debugDraw) + color = vec4( 0.5+ sign(delta)/2,0.3,0.5- sign(delta)/2, 0); + hitColor = texture(textureFrame, screenPosition) * color; + hitDepth = depthFromScreen; + hit = true; + break; + } + if (isBinarySearchEnabled && delta > 0) + { + break; + } + if (isAdaptiveStepEnabled) + { + float directionSign = sign(abs(marchingPosition.z) - depthFromScreen); + //this is sort of adapting step, should prevent lining reflection by doing sort of iterative converging + //some implementation doing it by binary search, but I found this idea more cheaty and way easier to implement + step = step * (1.0 - rayStep * max(directionSign, 0.0)); + marchingPosition += step * (-directionSign); + } + else + { + marchingPosition += step; + } - if (isExponentialStepEnabled){ - step *= 1.05; - } - } - if(isBinarySearchEnabled){ - for(; i < iterationCount && !hit; i++){ - - step *= 0.5; - marchingPosition = marchingPosition - step * sign(delta); - - screenPosition = generateProjectedPosition(marchingPosition); - depthFromScreen = linearDepth(getDepth(screenPosition), zNear, zFar); - delta = abs(marchingPosition.z) - depthFromScreen; + if (isExponentialStepEnabled) + { + step *= 1.05; + } + } + if(isBinarySearchEnabled) + { + for(; i < iterationCount && !hit; i++) + { + step *= 0.5; + marchingPosition = marchingPosition - step * sign(delta); + + screenPosition = generateProjectedPosition(marchingPosition); + depthFromScreen = linearDepth(getDepth(screenPosition), zNear, zFar); + delta = abs(marchingPosition.z) - depthFromScreen; - if (depth < depthFromScreen + epsilon && depth > depthFromScreen - epsilon) { - break; - } + if (depth < depthFromScreen + epsilon && depth > depthFromScreen - epsilon) + { + break; + } - if (abs(delta) < distanceBias && depthFromScreen != (depth - distanceBias)) { - vec4 color = vec4(1); - if(debugDraw) - color = vec4( 0.5+ sign(delta)/2,0.3,0.5- sign(delta)/2, 0); - hitColor = texture(textureFrame, screenPosition) * color; - hitDepth = depthFromScreen; - hit = true; - break; - } - } - } - } - + if (abs(delta) < distanceBias && depthFromScreen != (depth - distanceBias)) + { + vec4 color = vec4(1); + if(debugDraw) + color = vec4( 0.5+ sign(delta)/2,0.3,0.5- sign(delta)/2, 0); + hitColor = texture(textureFrame, screenPosition) * color; + hitDepth = depthFromScreen; + hit = true; + break; + } + } + } + } + return hit; } From 623bb4d58c197fccc8a795426c5864104301cebe Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Tue, 24 Jan 2023 14:17:36 -0600 Subject: [PATCH 18/31] SL-18772 Potential fix for failed shader load on Intel HD 3000 --- indra/llrender/llgl.cpp | 6 +- indra/llrender/llshadermgr.cpp | 2 +- .../class1/deferred/multiPointLightF.glsl | 117 +----------------- .../shaders/class1/deferred/pointLightF.glsl | 104 +--------------- 4 files changed, 8 insertions(+), 221 deletions(-) diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index 1725990e8f..72d9c14ccf 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -86,9 +86,9 @@ void APIENTRY gl_debug_callback(GLenum source, const GLchar* message, GLvoid* userParam) { - if (severity != GL_DEBUG_SEVERITY_HIGH && - severity != GL_DEBUG_SEVERITY_MEDIUM && - severity != GL_DEBUG_SEVERITY_LOW + if (severity != GL_DEBUG_SEVERITY_HIGH //&& + //severity != GL_DEBUG_SEVERITY_MEDIUM && + //severity != GL_DEBUG_SEVERITY_LOW ) { //suppress out-of-spec messages sent by nvidia driver (mostly vertexbuffer hints) return; diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 44b8ea164b..6001b011ee 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -262,7 +262,7 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) } } - if (features->hasGamma) + if (features->hasGamma || features->isDeferred) { if (!shader->attachFragmentObject("windlight/gammaF.glsl")) { diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl index 6763e2de7b..8fdb5e7154 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl @@ -23,124 +23,11 @@ * $/LicenseInfo$ */ -#extension GL_ARB_texture_rectangle : enable + // debug stub -/*[EXTRA_CODE_HERE]*/ - -#ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_color; -#else -#define frag_color gl_FragColor -#endif - -uniform sampler2D depthMap; -uniform sampler2D diffuseRect; -uniform sampler2D specularRect; -uniform sampler2D noiseMap; -uniform sampler2D lightFunc; - -uniform vec3 env_mat[3]; -uniform float sun_wash; -uniform int light_count; -uniform vec4 light[LIGHT_COUNT]; -uniform vec4 light_col[LIGHT_COUNT]; - -uniform vec2 screen_res; -uniform float far_z; -uniform mat4 inv_proj; - -VARYING vec4 vary_fragcoord; - -vec4 getPosition(vec2 pos_screen); -vec3 getNorm(vec2 pos_screen); -vec3 srgb_to_linear(vec3 c); -float getDepth(vec2 tc); -vec2 getScreenCoord(vec4 clip); void main() { -#if defined(LOCAL_LIGHT_KILL) - discard; // Bail immediately -#endif - - vec3 out_col = vec3(0, 0, 0); - vec2 frag = getScreenCoord(vary_fragcoord); - vec3 pos = getPosition(frag.xy).xyz; - if (pos.z < far_z) - { - discard; - } - - vec3 norm = getNorm(frag.xy); - - vec4 spec = texture2D(specularRect, frag.xy); - vec3 diff = texture2D(diffuseRect, frag.xy).rgb; - - float noise = texture2D(noiseMap, frag.xy).b; - vec3 npos = normalize(-pos); - - // As of OSX 10.6.7 ATI Apple's crash when using a variable size loop - for (int i = 0; i < LIGHT_COUNT; ++i) - { - vec3 lv = light[i].xyz - pos; - float dist = length(lv); - dist /= light[i].w; - if (dist <= 1.0) - { - float da = dot(norm, lv); - if (da > 0.0) - { - lv = normalize(lv); - da = dot(norm, lv); - - float fa = light_col[i].a + 1.0; - float dist_atten = clamp(1.0 - (dist - 1.0 * (1.0 - fa)) / fa, 0.0, 1.0); - dist_atten *= dist_atten; - - // Tweak falloff slightly to match pre-EEP attenuation - // NOTE: this magic number also shows up in a great many other places, search for dist_atten *= to audit - dist_atten *= 2.0; - - dist_atten *= noise; - - float lit = da * dist_atten; - - vec3 col = light_col[i].rgb * lit * diff; - - if (spec.a > 0.0) - { - lit = min(da * 6.0, 1.0) * dist_atten; - vec3 h = normalize(lv + npos); - float nh = dot(norm, h); - float nv = dot(norm, npos); - float vh = dot(npos, h); - float sa = nh; - float fres = pow(1 - dot(h, npos), 5) * 0.4 + 0.5; - - float gtdenom = 2 * nh; - float gt = max(0, min(gtdenom * nv / vh, gtdenom * da / vh)); - - if (nh > 0.0) - { - float scol = fres * texture2D(lightFunc, vec2(nh, spec.a)).r * gt / (nh * da); - col += lit * scol * light_col[i].rgb * spec.rgb; - } - } - - out_col += col; - } - } - } - - frag_color.rgb = out_col; - frag_color.a = 0.0; - -#ifdef IS_AMD_CARD - // If it's AMD make sure the GLSL compiler sees the arrays referenced once by static index. Otherwise it seems to optimise the storage - // awawy which leads to unfun crashes and artifacts. - vec4 dummy1 = light[0]; - vec4 dummy2 = light_col[0]; - vec4 dummy3 = light[LIGHT_COUNT - 1]; - vec4 dummy4 = light_col[LIGHT_COUNT - 1]; -#endif + frag_color = vec4(0.5, 0.5, 0.0, 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl index f07ef92b26..a025c4a1b4 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl @@ -22,111 +22,11 @@ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ - -#extension GL_ARB_texture_rectangle : enable -/*[EXTRA_CODE_HERE]*/ - -#ifdef DEFINE_GL_FRAGCOLOR +// debug stub out vec4 frag_color; -#else -#define frag_color gl_FragColor -#endif - -uniform sampler2D diffuseRect; -uniform sampler2D specularRect; -uniform sampler2D normalMap; -uniform sampler2D noiseMap; -uniform sampler2D lightFunc; -uniform sampler2D depthMap; - -uniform vec3 env_mat[3]; -uniform float sun_wash; - -uniform vec3 color; -uniform float falloff; -uniform float size; - -VARYING vec4 vary_fragcoord; -VARYING vec3 trans_center; - -uniform vec2 screen_res; - -uniform mat4 inv_proj; -uniform vec4 viewport; - -vec3 getNorm(vec2 pos_screen); -vec4 getPosition(vec2 pos_screen); -float getDepth(vec2 pos); -vec3 srgb_to_linear(vec3 c); void main() { - vec4 frag = vary_fragcoord; - frag.xyz /= frag.w; - frag.xyz = frag.xyz*0.5+0.5; - - vec3 pos = getPosition(frag.xy).xyz; - vec3 lv = trans_center.xyz-pos; - float dist = length(lv); - dist /= size; - if (dist > 1.0) - { - discard; - } - - vec3 norm = getNorm(frag.xy); - - float da = dot(norm, lv); - if (da < 0.0) - { - discard; - } - - lv = normalize(lv); - da = dot(norm, lv); - - float noise = texture2D(noiseMap, frag.xy).b; - - vec3 col = texture2D(diffuseRect, frag.xy).rgb; - - float fa = falloff+1.0; - float dist_atten = clamp(1.0-(dist-1.0*(1.0-fa))/fa, 0.0, 1.0); - dist_atten *= dist_atten; - dist_atten *= 2.0; - - float lit = da * dist_atten * noise; - - col = color.rgb*lit*col; - - vec4 spec = texture2D(specularRect, frag.xy); - if (spec.a > 0.0) - { - lit = min(da*6.0, 1.0) * dist_atten; - - vec3 npos = -normalize(pos); - vec3 h = normalize(lv+npos); - float nh = dot(norm, h); - float nv = dot(norm, npos); - float vh = dot(npos, h); - float sa = nh; - float fres = pow(1 - dot(h, npos), 5) * 0.4+0.5; - float gtdenom = 2 * nh; - float gt = max(0,(min(gtdenom * nv / vh, gtdenom * da / vh))); - - if (nh > 0.0) - { - float scol = fres*texture2D(lightFunc, vec2(nh, spec.a)).r*gt/(nh*da); - col += lit*scol*color.rgb*spec.rgb; - } - } - - if (dot(col, col) <= 0.0) - { - discard; - } - final_color.rgb = vec3(getDepth(frag.xy)); - - frag_color.rgb = col; - frag_color.a = 0.0; + frag_color = vec4(0.0, 0.5, 0.5, 0.0); } From 2aaa15fef15243e6b38f46426d8ebb355ccfb807 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Tue, 24 Jan 2023 17:48:18 -0800 Subject: [PATCH 19/31] SL-19012: Fix new material IDs sometimes not applying when set via LSL --- indra/newview/llfetchedgltfmaterial.cpp | 32 ++++++++++++++++++++++ indra/newview/llfetchedgltfmaterial.h | 10 ++++++- indra/newview/llgltfmateriallist.cpp | 10 ++++--- indra/newview/llgltfmateriallist.h | 2 +- indra/newview/llviewerobject.cpp | 36 ++++++++++++++++++------- indra/newview/llviewerobject.h | 1 + 6 files changed, 76 insertions(+), 15 deletions(-) diff --git a/indra/newview/llfetchedgltfmaterial.cpp b/indra/newview/llfetchedgltfmaterial.cpp index b095b74519..047f1a4965 100644 --- a/indra/newview/llfetchedgltfmaterial.cpp +++ b/indra/newview/llfetchedgltfmaterial.cpp @@ -115,3 +115,35 @@ void LLFetchedGLTFMaterial::bind() } } + +void LLFetchedGLTFMaterial::materialBegin() +{ + llassert(!mFetching); + mFetching = true; +} + +void LLFetchedGLTFMaterial::onMaterialComplete(std::function material_complete) +{ + if (!material_complete) { return; } + + if (!mFetching) + { + material_complete(); + return; + } + + materialCompleteCallbacks.push_back(material_complete); +} + +void LLFetchedGLTFMaterial::materialComplete() +{ + llassert(mFetching); + mFetching = false; + + for (std::function material_complete : materialCompleteCallbacks) + { + material_complete(); + } + materialCompleteCallbacks.clear(); + materialCompleteCallbacks.shrink_to_fit(); +} diff --git a/indra/newview/llfetchedgltfmaterial.h b/indra/newview/llfetchedgltfmaterial.h index 4f6c56012e..f784f19c4f 100644 --- a/indra/newview/llfetchedgltfmaterial.h +++ b/indra/newview/llfetchedgltfmaterial.h @@ -39,6 +39,9 @@ public: LLFetchedGLTFMaterial(); virtual ~LLFetchedGLTFMaterial(); + // If this material is loaded, fire the given function + void onMaterialComplete(std::function material_complete); + // bind this material for rendering void bind(); @@ -49,9 +52,14 @@ public: LLPointer mEmissiveTexture; protected: - //Lifetime management + // Lifetime management + + void materialBegin(); + void materialComplete(); + F64 mExpectedFlusTime; // since epoch in seconds bool mActive; bool mFetching; + std::vector> materialCompleteCallbacks; }; diff --git a/indra/newview/llgltfmateriallist.cpp b/indra/newview/llgltfmateriallist.cpp index 4cf1562042..bc094ac838 100644 --- a/indra/newview/llgltfmateriallist.cpp +++ b/indra/newview/llgltfmateriallist.cpp @@ -525,7 +525,7 @@ void LLGLTFMaterialList::onAssetLoadComplete(const LLUUID& id, LLAssetType::ETyp if (status != LL_ERR_NOERR) { LL_WARNS("GLTF") << "Error getting material asset data: " << LLAssetStorage::getErrorString(status) << " (" << status << ")" << LL_ENDL; - asset_data->mMaterial->mFetching = false; + asset_data->mMaterial->materialComplete(); delete asset_data; } else @@ -611,13 +611,15 @@ void LLGLTFMaterialList::onAssetLoadComplete(const LLUUID& id, LLAssetType::ETyp { LL_DEBUGS("GLTF") << "Failed to get material " << id << LL_ENDL; } - asset_data->mMaterial->mFetching = false; + + asset_data->mMaterial->materialComplete(); + delete asset_data; }); } } -LLGLTFMaterial* LLGLTFMaterialList::getMaterial(const LLUUID& id) +LLFetchedGLTFMaterial* LLGLTFMaterialList::getMaterial(const LLUUID& id) { LL_PROFILE_ZONE_SCOPED; uuid_mat_map_t::iterator iter = mList.find(id); @@ -629,7 +631,7 @@ LLGLTFMaterial* LLGLTFMaterialList::getMaterial(const LLUUID& id) if (!mat->mFetching) { - mat->mFetching = true; + mat->materialBegin(); AssetLoadUserData *user_data = new AssetLoadUserData(); user_data->mMaterial = mat; diff --git a/indra/newview/llgltfmateriallist.h b/indra/newview/llgltfmateriallist.h index 5ce0e324f5..85e60aa17f 100644 --- a/indra/newview/llgltfmateriallist.h +++ b/indra/newview/llgltfmateriallist.h @@ -45,7 +45,7 @@ public: LLGLTFMaterialList() {} - LLGLTFMaterial* getMaterial(const LLUUID& id); + LLFetchedGLTFMaterial* getMaterial(const LLUUID& id); void addMaterial(const LLUUID& id, LLFetchedGLTFMaterial* material); void removeMaterial(const LLUUID& id); diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index f416080f9e..5a365c79ea 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -7160,6 +7160,14 @@ const LLUUID& LLViewerObject::getRenderMaterialID(U8 te) const return LLUUID::null; } +void LLViewerObject::rebuildMaterial() +{ + llassert(!isDead()); + + faceMappingChanged(); + gPipeline.markTextured(mDrawable); +} + void LLViewerObject::setRenderMaterialID(S32 te_in, const LLUUID& id, bool update_server) { // implementation is delicate @@ -7188,17 +7196,16 @@ void LLViewerObject::setRenderMaterialID(S32 te_in, const LLUUID& id, bool updat } + LLFetchedGLTFMaterial* new_material = nullptr; + if (id.notNull()) + { + new_material = gGLTFMaterialList.getMaterial(id); + } + // update local state for (S32 te = start_idx; te < end_idx; ++te) { - - LLGLTFMaterial* new_material = nullptr; LLTextureEntry* tep = getTE(te); - - if (id.notNull()) - { - new_material = gGLTFMaterialList.getMaterial(id); - } bool material_changed = !param_block || id != param_block->getMaterial(te); @@ -7225,8 +7232,19 @@ void LLViewerObject::setRenderMaterialID(S32 te_in, const LLUUID& id, bool updat } // signal to render pipe that render batches must be rebuilt for this object - faceMappingChanged(); - gPipeline.markTextured(mDrawable); + if (!new_material) + { + rebuildMaterial(); + } + else + { + LLPointer this_ptr = this; + new_material->onMaterialComplete([this_ptr]() mutable { + if (this_ptr->isDead()) { return; } + + this_ptr->rebuildMaterial(); + }); + } if (update_server) { diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index fae29c3bc2..93b17361ab 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -226,6 +226,7 @@ public: private: void resetRotTime(); void setRenderMaterialIDs(const LLRenderMaterialParams* material_params, bool local_origin); + void rebuildMaterial(); public: void resetRot(); void applyAngularVelocity(F32 dt); From 2f1158c06f0d30ae8c5f228e3ea106a01825af3b Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Wed, 25 Jan 2023 16:56:45 -0800 Subject: [PATCH 20/31] SL-19081: Fix assert when uploading texture --- indra/newview/llfloaterimagepreview.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/indra/newview/llfloaterimagepreview.cpp b/indra/newview/llfloaterimagepreview.cpp index b2be6a925e..6b0ba44624 100644 --- a/indra/newview/llfloaterimagepreview.cpp +++ b/indra/newview/llfloaterimagepreview.cpp @@ -838,6 +838,8 @@ void LLImagePreviewSculpted::setPreviewTarget(LLImageRaw* imagep, F32 distance) { *(index_strider++) = vf.mIndices[i]; } + + mVertexBuffer->unmapBuffer(); } From 7f0fed273c0161c44704443e1cc5ac139d49edd4 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 25 Jan 2023 15:29:21 +0200 Subject: [PATCH 21/31] SL-17640 Make Materials Upload UI localizable --- .../default/xui/en/panel_gltf_material.xml | 34 ++++++++++++------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/indra/newview/skins/default/xui/en/panel_gltf_material.xml b/indra/newview/skins/default/xui/en/panel_gltf_material.xml index 2936b3cb63..6975525b3d 100644 --- a/indra/newview/skins/default/xui/en/panel_gltf_material.xml +++ b/indra/newview/skins/default/xui/en/panel_gltf_material.xml @@ -37,7 +37,8 @@ layout="topleft" left="10" top="5" - width="128"> + width="128" + name="base_color_lbl"> Base Color: + top="8" + name="base_color_tint_lbl"> Tint + width="96" + name="base_color_transparency_lbl"> Transparency + width="90" + name="alpha_mode_lbl"> Alpha mode + width="96" + name="alpha_cutoff_lbl"> Alpha Cutoff + top="5" + name="metallic_roughness_lbl"> Metallic-Roughness: + top="8" + name="metallic_factor_lbl"> Metallic Factor + width="96" + name="roughness_factor_lbl"> Roughness Factor + width="64" + name="emissive_lbl"> Emissive: + top="8" + name="emissive_tint_lbl"> Tint + width="64" + name="normal_lbl"> Normal: Date: Wed, 25 Jan 2023 15:42:27 +0200 Subject: [PATCH 22/31] SL-19005 Fix 'save as' button for local uploads --- indra/newview/llmaterialeditor.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/indra/newview/llmaterialeditor.cpp b/indra/newview/llmaterialeditor.cpp index a36ddeb532..5628327ebe 100644 --- a/indra/newview/llmaterialeditor.cpp +++ b/indra/newview/llmaterialeditor.cpp @@ -2157,6 +2157,7 @@ void LLMaterialEditor::loadMaterial(const tinygltf::Model &model_in, const std:: openFloater(getKey()); setFocus(TRUE); setCanSave(true); + setCanSaveAs(true); applyToSelection(); } From 3ef31cb9b28f7b026e109eab69d383dddc922850 Mon Sep 17 00:00:00 2001 From: RunitaiLinden Date: Fri, 27 Jan 2023 17:24:22 -0600 Subject: [PATCH 23/31] SL-19203 et al -- Integrate SSR with reflection probes, tweak probe blending. (#63) * SL-19203 WIP -- Integrate SSR with reflection probes. Decruft LLRenderTarget. * SL-19203 WIP -- Re-integrate SSR. Incidental decruft. * SL-19203 WIP -- SSR frame delta correction (still broken for Z) * SL-19203 WIP -- SSR frame delta Z fix * SL-19203 WIP -- Make SSR toggleable again and disable SSR in cube snapshots. * SL-19203 WIP -- Soften sphere probe transitions and fix reflections on void water (make fallback probe a simple terrain+water+sky probe). Remove parallax correction for automatic probes to reduce artifacts. * SL-19203 Tune probe blending. * SL-19203 Cleanup. --- indra/llrender/llgl.cpp | 3 +- indra/llrender/llrender.cpp | 7 +- indra/llrender/llrender.h | 2 + indra/llrender/llrendertarget.cpp | 712 ++++++++---------- indra/llrender/llrendertarget.h | 33 +- indra/llrender/llshadermgr.cpp | 8 +- indra/llrender/llshadermgr.h | 6 + indra/llrender/llvertexbuffer.cpp | 2 +- .../class1/deferred/reflectionProbeF.glsl | 4 +- .../class1/deferred/screenSpaceReflPostF.glsl | 32 +- .../class1/deferred/screenSpaceReflUtil.glsl | 101 +-- .../shaders/class2/deferred/alphaF.glsl | 6 +- .../shaders/class2/deferred/pbralphaF.glsl | 4 +- .../class2/deferred/reflectionProbeF.glsl | 10 +- .../class3/deferred/fullbrightShinyF.glsl | 7 +- .../shaders/class3/deferred/materialF.glsl | 6 +- .../class3/deferred/reflectionProbeF.glsl | 148 ++-- .../class3/deferred/screenSpaceReflPostF.glsl | 50 +- .../class3/deferred/screenSpaceReflUtil.glsl | 104 ++- .../shaders/class3/deferred/softenLightF.glsl | 10 +- .../shaders/class3/environment/waterF.glsl | 10 +- indra/newview/llfasttimerview.cpp | 2 +- indra/newview/llglsandbox.cpp | 2 +- indra/newview/llreflectionmapmanager.cpp | 40 +- indra/newview/llscenemonitor.cpp | 6 +- indra/newview/llviewercontrol.cpp | 1 + indra/newview/llviewerdisplay.cpp | 9 - indra/newview/llviewershadermgr.cpp | 8 +- indra/newview/llviewerwindow.cpp | 6 +- indra/newview/pipeline.cpp | 172 +++-- indra/newview/pipeline.h | 4 + 31 files changed, 755 insertions(+), 760 deletions(-) diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index 72d9c14ccf..c08c576531 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -2270,7 +2270,7 @@ void do_assert_glerror() GLenum error; error = glGetError(); BOOL quit = FALSE; - while (LL_UNLIKELY(error)) + if (LL_UNLIKELY(error)) { quit = TRUE; GLubyte const * gl_error_msg = gluErrorString(error); @@ -2295,7 +2295,6 @@ void do_assert_glerror() gFailLog << "GL Error: UNKNOWN 0x" << std::hex << error << std::dec << std::endl; } } - error = glGetError(); } if (quit) diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index d6b2aa2289..6dbde719f4 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -55,8 +55,14 @@ F32 gGLModelView[16]; F32 gGLLastModelView[16]; F32 gGLLastProjection[16]; F32 gGLProjection[16]; + +// transform from last frame's camera space to this frame's camera space (and inverse) +F32 gGLDeltaModelView[16]; +F32 gGLInverseDeltaModelView[16]; + S32 gGLViewport[4]; + U32 LLRender::sUICalls = 0; U32 LLRender::sUIVerts = 0; U32 LLTexUnit::sWhiteTexture = 0; @@ -373,7 +379,6 @@ bool LLTexUnit::bind(LLRenderTarget* renderTarget, bool bindDepth) if (bindDepth) { llassert(renderTarget->getDepth()); // target MUST have a depth buffer attachment - llassert(renderTarget->canSampleDepth()); // depth buffer attachment MUST be sampleable bindManual(renderTarget->getUsage(), renderTarget->getDepth()); } diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index cbd3de5736..e8baf6bb7e 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -507,6 +507,8 @@ extern F32 gGLLastModelView[16]; extern F32 gGLLastProjection[16]; extern F32 gGLProjection[16]; extern S32 gGLViewport[4]; +extern F32 gGLDeltaModelView[16]; +extern F32 gGLInverseDeltaModelView[16]; extern thread_local LLRender gGL; diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index 9827db8084..6dac614eea 100644 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -35,19 +35,19 @@ U32 LLRenderTarget::sBytesAllocated = 0; void check_framebuffer_status() { - if (gDebugGL) - { - GLenum status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); - switch (status) - { - case GL_FRAMEBUFFER_COMPLETE: - break; - default: - LL_WARNS() << "check_framebuffer_status failed -- " << std::hex << status << LL_ENDL; - ll_fail("check_framebuffer_status failed"); - break; - } - } + if (gDebugGL) + { + GLenum status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); + switch (status) + { + case GL_FRAMEBUFFER_COMPLETE: + break; + default: + LL_WARNS() << "check_framebuffer_status failed -- " << std::hex << status << LL_ENDL; + ll_fail("check_framebuffer_status failed"); + break; + } + } } bool LLRenderTarget::sUseFBO = false; @@ -60,112 +60,86 @@ U32 LLRenderTarget::sCurResX = 0; U32 LLRenderTarget::sCurResY = 0; LLRenderTarget::LLRenderTarget() : - mResX(0), - mResY(0), - mFBO(0), - mPreviousFBO(0), - mPreviousResX(0), - mPreviousResY(0), - mDepth(0), - mUseDepth(false), - mSampleDepth(false), - mUsage(LLTexUnit::TT_TEXTURE) + mResX(0), + mResY(0), + mFBO(0), + mDepth(0), + mUseDepth(false), + mUsage(LLTexUnit::TT_TEXTURE) { } LLRenderTarget::~LLRenderTarget() { - release(); + release(); } void LLRenderTarget::resize(U32 resx, U32 resy) { - //for accounting, get the number of pixels added/subtracted - S32 pix_diff = (resx*resy)-(mResX*mResY); - - mResX = resx; - mResY = resy; + //for accounting, get the number of pixels added/subtracted + S32 pix_diff = (resx*resy)-(mResX*mResY); + + mResX = resx; + mResY = resy; - llassert(mInternalFormat.size() == mTex.size()); + llassert(mInternalFormat.size() == mTex.size()); - for (U32 i = 0; i < mTex.size(); ++i) - { //resize color attachments - gGL.getTexUnit(0)->bindManual(mUsage, mTex[i]); - LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, mInternalFormat[i], mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL, false); - sBytesAllocated += pix_diff*4; - } + for (U32 i = 0; i < mTex.size(); ++i) + { //resize color attachments + gGL.getTexUnit(0)->bindManual(mUsage, mTex[i]); + LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, mInternalFormat[i], mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL, false); + sBytesAllocated += pix_diff*4; + } - if (mDepth) - { //resize depth attachment - if (!mSampleDepth) - { - //use render buffers where stencil buffers are in play - glBindRenderbuffer(GL_RENDERBUFFER, mDepth); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, mResX, mResY); - glBindRenderbuffer(GL_RENDERBUFFER, 0); - } - else - { - gGL.getTexUnit(0)->bindManual(mUsage, mDepth); - U32 internal_type = LLTexUnit::getInternalType(mUsage); - LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT24, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL, false); - } + if (mDepth) + { + gGL.getTexUnit(0)->bindManual(mUsage, mDepth); + U32 internal_type = LLTexUnit::getInternalType(mUsage); + LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT24, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL, false); - sBytesAllocated += pix_diff*4; - } + sBytesAllocated += pix_diff*4; + } } - + -bool LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool sample_depth, LLTexUnit::eTextureType usage, bool use_fbo, S32 samples) +bool LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, LLTexUnit::eTextureType usage) { LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; - resx = llmin(resx, (U32) gGLManager.mGLMaxTextureSize); - resy = llmin(resy, (U32) gGLManager.mGLMaxTextureSize); + llassert(usage == LLTexUnit::TT_TEXTURE); + llassert(!isBoundInStack()); - stop_glerror(); - release(); - stop_glerror(); + resx = llmin(resx, (U32) gGLManager.mGLMaxTextureSize); + resy = llmin(resy, (U32) gGLManager.mGLMaxTextureSize); - mResX = resx; - mResY = resy; + release(); + + mResX = resx; + mResY = resy; - mUsage = usage; + mUsage = usage; mUseDepth = depth; - mSampleDepth = sample_depth; + + if (depth) + { + if (!allocateDepth()) + { + LL_WARNS() << "Failed to allocate depth buffer for render target." << LL_ENDL; + return false; + } + } - if ((sUseFBO || use_fbo)) - { - if (depth) - { - if (!allocateDepth()) - { - LL_WARNS() << "Failed to allocate depth buffer for render target." << LL_ENDL; - return false; - } - } + glGenFramebuffers(1, (GLuint *) &mFBO); - glGenFramebuffers(1, (GLuint *) &mFBO); - - if (mDepth) - { - glBindFramebuffer(GL_FRAMEBUFFER, mFBO); + if (mDepth) + { + glBindFramebuffer(GL_FRAMEBUFFER, mFBO); - if (!canSampleDepth()) - { - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mDepth); - } - else - { - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), mDepth, 0); - stop_glerror(); - } - glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO); - } - - stop_glerror(); - } + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), mDepth, 0); - return addColorAttachment(color_fmt); + glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO); + } + + return addColorAttachment(color_fmt); } void LLRenderTarget::setColorAttachment(LLImageGL* img, LLGLuint use_name) @@ -175,6 +149,7 @@ void LLRenderTarget::setColorAttachment(LLImageGL* img, LLGLuint use_name) llassert(sUseFBO); // FBO support must be enabled llassert(mDepth == 0); // depth buffers not supported with this mode llassert(mTex.empty()); // mTex must be empty with this mode (binding target should be done via LLImageGL) + llassert(!isBoundInStack()); if (mFBO == 0) { @@ -205,6 +180,7 @@ void LLRenderTarget::setColorAttachment(LLImageGL* img, LLGLuint use_name) void LLRenderTarget::releaseColorAttachment() { LL_PROFILE_ZONE_SCOPED; + llassert(!isBoundInStack()); llassert(mTex.size() == 1); //cannot use releaseColorAttachment with LLRenderTarget managed color targets llassert(mFBO != 0); // mFBO must be valid @@ -218,323 +194,291 @@ void LLRenderTarget::releaseColorAttachment() bool LLRenderTarget::addColorAttachment(U32 color_fmt) { LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; - if (color_fmt == 0) - { - return true; - } + llassert(!isBoundInStack()); - U32 offset = mTex.size(); + if (color_fmt == 0) + { + return true; + } - if( offset >= 4 ) - { - LL_WARNS() << "Too many color attachments" << LL_ENDL; - llassert( offset < 4 ); - return false; - } - if( offset > 0 && (mFBO == 0) ) - { - llassert( mFBO != 0 ); - return false; - } + U32 offset = mTex.size(); - U32 tex; - LLImageGL::generateTextures(1, &tex); - gGL.getTexUnit(0)->bindManual(mUsage, tex); + if( offset >= 4 ) + { + LL_WARNS() << "Too many color attachments" << LL_ENDL; + llassert( offset < 4 ); + return false; + } + if( offset > 0 && (mFBO == 0) ) + { + llassert( mFBO != 0 ); + return false; + } - stop_glerror(); + U32 tex; + LLImageGL::generateTextures(1, &tex); + gGL.getTexUnit(0)->bindManual(mUsage, tex); + + stop_glerror(); - { - clear_glerror(); - LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL, false); - if (glGetError() != GL_NO_ERROR) - { - LL_WARNS() << "Could not allocate color buffer for render target." << LL_ENDL; - return false; - } - } - - sBytesAllocated += mResX*mResY*4; + { + clear_glerror(); + LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL, false); + if (glGetError() != GL_NO_ERROR) + { + LL_WARNS() << "Could not allocate color buffer for render target." << LL_ENDL; + return false; + } + } + + sBytesAllocated += mResX*mResY*4; - stop_glerror(); + stop_glerror(); - - if (offset == 0) - { //use bilinear filtering on single texture render targets that aren't multisampled - gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); - stop_glerror(); - } - else - { //don't filter data attachments - gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); - stop_glerror(); - } + + if (offset == 0) + { //use bilinear filtering on single texture render targets that aren't multisampled + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); + stop_glerror(); + } + else + { //don't filter data attachments + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + stop_glerror(); + } - if (mUsage != LLTexUnit::TT_RECT_TEXTURE) - { - gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_MIRROR); - stop_glerror(); - } - else - { - // ATI doesn't support mirrored repeat for rectangular textures. - gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); - stop_glerror(); - } - - if (mFBO) - { - stop_glerror(); - glBindFramebuffer(GL_FRAMEBUFFER, mFBO); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+offset, - LLTexUnit::getInternalType(mUsage), tex, 0); - stop_glerror(); + if (mUsage != LLTexUnit::TT_RECT_TEXTURE) + { + gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_MIRROR); + stop_glerror(); + } + else + { + // ATI doesn't support mirrored repeat for rectangular textures. + gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); + stop_glerror(); + } + + if (mFBO) + { + glBindFramebuffer(GL_FRAMEBUFFER, mFBO); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+offset, + LLTexUnit::getInternalType(mUsage), tex, 0); + + check_framebuffer_status(); + + glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO); + } - check_framebuffer_status(); - - glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO); - } + mTex.push_back(tex); + mInternalFormat.push_back(color_fmt); - mTex.push_back(tex); - mInternalFormat.push_back(color_fmt); - - if (gDebugGL) - { //bind and unbind to validate target - bindTarget(); - flush(); - } + if (gDebugGL) + { //bind and unbind to validate target + bindTarget(); + flush(); + } - return true; + return true; } bool LLRenderTarget::allocateDepth() { LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; - if (!mSampleDepth) - { - //use render buffers if depth buffer won't be sampled - glGenRenderbuffers(1, (GLuint *) &mDepth); - glBindRenderbuffer(GL_RENDERBUFFER, mDepth); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, mResX, mResY); - glBindRenderbuffer(GL_RENDERBUFFER, 0); - } - else - { - LLImageGL::generateTextures(1, &mDepth); - gGL.getTexUnit(0)->bindManual(mUsage, mDepth); - - U32 internal_type = LLTexUnit::getInternalType(mUsage); - stop_glerror(); - clear_glerror(); - LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT24, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL, false); - gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); - } + LLImageGL::generateTextures(1, &mDepth); + gGL.getTexUnit(0)->bindManual(mUsage, mDepth); + + U32 internal_type = LLTexUnit::getInternalType(mUsage); + stop_glerror(); + clear_glerror(); + LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT24, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL, false); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); - sBytesAllocated += mResX*mResY*4; + sBytesAllocated += mResX*mResY*4; - if (glGetError() != GL_NO_ERROR) - { - LL_WARNS() << "Unable to allocate depth buffer for render target." << LL_ENDL; - return false; - } + if (glGetError() != GL_NO_ERROR) + { + LL_WARNS() << "Unable to allocate depth buffer for render target." << LL_ENDL; + return false; + } - return true; + return true; } void LLRenderTarget::shareDepthBuffer(LLRenderTarget& target) { - if (!mFBO || !target.mFBO) - { - LL_ERRS() << "Cannot share depth buffer between non FBO render targets." << LL_ENDL; - } + llassert(!isBoundInStack()); - if (target.mDepth) - { - LL_ERRS() << "Attempting to override existing depth buffer. Detach existing buffer first." << LL_ENDL; - } + if (!mFBO || !target.mFBO) + { + LL_ERRS() << "Cannot share depth buffer between non FBO render targets." << LL_ENDL; + } - if (target.mUseDepth) - { - LL_ERRS() << "Attempting to override existing shared depth buffer. Detach existing buffer first." << LL_ENDL; - } + if (target.mDepth) + { + LL_ERRS() << "Attempting to override existing depth buffer. Detach existing buffer first." << LL_ENDL; + } - if (mDepth) - { - glBindFramebuffer(GL_FRAMEBUFFER, target.mFBO); - - if (!mSampleDepth) - { - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mDepth); - } - else - { - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), mDepth, 0); - } + if (target.mUseDepth) + { + LL_ERRS() << "Attempting to override existing shared depth buffer. Detach existing buffer first." << LL_ENDL; + } - check_framebuffer_status(); + if (mDepth) + { + glBindFramebuffer(GL_FRAMEBUFFER, target.mFBO); + + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), mDepth, 0); - glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO); + check_framebuffer_status(); - target.mUseDepth = true; - } + glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO); + + target.mUseDepth = true; + } } void LLRenderTarget::release() { LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; - if (mDepth) - { - if (!mSampleDepth) - { - glDeleteRenderbuffers(1, (GLuint*) &mDepth); - } - else - { - LLImageGL::deleteTextures(1, &mDepth); - } - mDepth = 0; + llassert(!isBoundInStack()); - sBytesAllocated -= mResX*mResY*4; - } - else if (mFBO) - { - glBindFramebuffer(GL_FRAMEBUFFER, mFBO); + if (mDepth) + { + LLImageGL::deleteTextures(1, &mDepth); + + mDepth = 0; - if (mUseDepth) - { //detach shared depth buffer - if (!mSampleDepth) - { //attached as a renderbuffer - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0); - mSampleDepth = false; - } - else - { //attached as a texture - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), 0, 0); - } - mUseDepth = false; - } - } + sBytesAllocated -= mResX*mResY*4; + } + else if (mFBO) + { + glBindFramebuffer(GL_FRAMEBUFFER, mFBO); - // Detach any extra color buffers (e.g. SRGB spec buffers) - // - if (mFBO && (mTex.size() > 1)) - { - glBindFramebuffer(GL_FRAMEBUFFER, mFBO); - S32 z; - for (z = mTex.size() - 1; z >= 1; z--) - { - sBytesAllocated -= mResX*mResY*4; - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+z, LLTexUnit::getInternalType(mUsage), 0, 0); - stop_glerror(); - LLImageGL::deleteTextures(1, &mTex[z]); - } - } + if (mUseDepth) + { //detach shared depth buffer + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), 0, 0); + mUseDepth = false; + } - if (mFBO) - { - glDeleteFramebuffers(1, (GLuint *) &mFBO); - stop_glerror(); - mFBO = 0; - } + glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO); + } - if (mTex.size() > 0) - { - sBytesAllocated -= mResX*mResY*4; - LLImageGL::deleteTextures(1, &mTex[0]); - } + // Detach any extra color buffers (e.g. SRGB spec buffers) + // + if (mFBO && (mTex.size() > 1)) + { + glBindFramebuffer(GL_FRAMEBUFFER, mFBO); + S32 z; + for (z = mTex.size() - 1; z >= 1; z--) + { + sBytesAllocated -= mResX*mResY*4; + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+z, LLTexUnit::getInternalType(mUsage), 0, 0); + LLImageGL::deleteTextures(1, &mTex[z]); + } + glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO); + } - mTex.clear(); - mInternalFormat.clear(); - - mResX = mResY = 0; + if (mFBO == sCurFBO) + { + sCurFBO = 0; + glBindFramebuffer(GL_FRAMEBUFFER, 0); + } - sBoundTarget = NULL; + if (mFBO) + { + glDeleteFramebuffers(1, (GLuint *) &mFBO); + mFBO = 0; + } + + if (mTex.size() > 0) + { + sBytesAllocated -= mResX*mResY*4; + LLImageGL::deleteTextures(1, &mTex[0]); + } + + mTex.clear(); + mInternalFormat.clear(); + + mResX = mResY = 0; } void LLRenderTarget::bindTarget() { LL_PROFILE_GPU_ZONE("bindTarget"); llassert(mFBO); + llassert(!isBoundInStack()); + + glBindFramebuffer(GL_FRAMEBUFFER, mFBO); + sCurFBO = mFBO; - if (mFBO) - { - stop_glerror(); - - mPreviousFBO = sCurFBO; - glBindFramebuffer(GL_FRAMEBUFFER, mFBO); - sCurFBO = mFBO; - - stop_glerror(); - //setup multiple render targets - GLenum drawbuffers[] = {GL_COLOR_ATTACHMENT0, - GL_COLOR_ATTACHMENT1, - GL_COLOR_ATTACHMENT2, - GL_COLOR_ATTACHMENT3}; - glDrawBuffers(mTex.size(), drawbuffers); - - if (mTex.empty()) - { //no color buffer to draw to - glDrawBuffer(GL_NONE); - glReadBuffer(GL_NONE); - } + //setup multiple render targets + GLenum drawbuffers[] = {GL_COLOR_ATTACHMENT0, + GL_COLOR_ATTACHMENT1, + GL_COLOR_ATTACHMENT2, + GL_COLOR_ATTACHMENT3}; + glDrawBuffers(mTex.size(), drawbuffers); + + if (mTex.empty()) + { //no color buffer to draw to + glDrawBuffer(GL_NONE); + glReadBuffer(GL_NONE); + } - check_framebuffer_status(); + check_framebuffer_status(); - stop_glerror(); - } + glViewport(0, 0, mResX, mResY); + sCurResX = mResX; + sCurResY = mResY; - mPreviousResX = sCurResX; - mPreviousResY = sCurResY; - glViewport(0, 0, mResX, mResY); - sCurResX = mResX; - sCurResY = mResY; - - sBoundTarget = this; + mPreviousRT = sBoundTarget; + sBoundTarget = this; } void LLRenderTarget::clear(U32 mask_in) { LL_PROFILE_GPU_ZONE("clear"); llassert(mFBO); - U32 mask = GL_COLOR_BUFFER_BIT; - if (mUseDepth) - { - mask |= GL_DEPTH_BUFFER_BIT; // stencil buffer is deprecated, performance pnealty | GL_STENCIL_BUFFER_BIT; + U32 mask = GL_COLOR_BUFFER_BIT; + if (mUseDepth) + { + mask |= GL_DEPTH_BUFFER_BIT; - } - if (mFBO) - { - check_framebuffer_status(); - stop_glerror(); - glClear(mask & mask_in); - stop_glerror(); - } - else - { - LLGLEnable scissor(GL_SCISSOR_TEST); - glScissor(0, 0, mResX, mResY); - stop_glerror(); - glClear(mask & mask_in); - } + } + if (mFBO) + { + check_framebuffer_status(); + stop_glerror(); + glClear(mask & mask_in); + stop_glerror(); + } + else + { + LLGLEnable scissor(GL_SCISSOR_TEST); + glScissor(0, 0, mResX, mResY); + stop_glerror(); + glClear(mask & mask_in); + } } U32 LLRenderTarget::getTexture(U32 attachment) const { - if (attachment > mTex.size()-1) - { - LL_ERRS() << "Invalid attachment index." << LL_ENDL; - } - if (mTex.empty()) - { - return 0; - } - return mTex[attachment]; + if (attachment > mTex.size()-1) + { + LL_ERRS() << "Invalid attachment index." << LL_ENDL; + } + if (mTex.empty()) + { + return 0; + } + return mTex[attachment]; } U32 LLRenderTarget::getNumTextures() const { - return mTex.size(); + return mTex.size(); } void LLRenderTarget::bindTexture(U32 index, S32 channel, LLTexUnit::eTextureFilterOptions filter_options) @@ -560,64 +504,54 @@ void LLRenderTarget::bindTexture(U32 index, S32 channel, LLTexUnit::eTextureFilt gGL.getTexUnit(channel)->setTextureColorSpace(isSRGB ? LLTexUnit::TCS_SRGB : LLTexUnit::TCS_LINEAR); } -void LLRenderTarget::flush(bool fetch_depth) +void LLRenderTarget::flush() { LL_PROFILE_GPU_ZONE("rt flush"); - gGL.flush(); + gGL.flush(); llassert(mFBO); - if (!mFBO) - { - gGL.getTexUnit(0)->bind(this); - glCopyTexSubImage2D(LLTexUnit::getInternalType(mUsage), 0, 0, 0, 0, 0, mResX, mResY); + llassert(sCurFBO == mFBO); + llassert(sBoundTarget == this); - if (fetch_depth) - { - if (!mDepth) - { - allocateDepth(); - } - - gGL.getTexUnit(0)->bind(this); - glCopyTexImage2D(LLTexUnit::getInternalType(mUsage), 0, GL_DEPTH24_STENCIL8, 0, 0, mResX, mResY, 0); - } - - gGL.getTexUnit(0)->disable(); - } - else - { - stop_glerror(); - glBindFramebuffer(GL_FRAMEBUFFER, mPreviousFBO); - sCurFBO = mPreviousFBO; - - if (mPreviousFBO) - { - glViewport(0, 0, mPreviousResX, mPreviousResY); - sCurResX = mPreviousResX; - sCurResY = mPreviousResY; - } - else - { - glViewport(gGLViewport[0],gGLViewport[1],gGLViewport[2],gGLViewport[3]); - sCurResX = gGLViewport[2]; - sCurResY = gGLViewport[3]; - } - - stop_glerror(); - } + if (mPreviousRT) + { + // a bit hacky -- pop the RT stack back two frames and push + // the previous frame back on to play nice with the GL state machine + sBoundTarget = mPreviousRT->mPreviousRT; + mPreviousRT->bindTarget(); + } + else + { + sBoundTarget = nullptr; + glBindFramebuffer(GL_FRAMEBUFFER, 0); + sCurFBO = 0; + glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]); + sCurResX = gGLViewport[2]; + sCurResY = gGLViewport[3]; + } } bool LLRenderTarget::isComplete() const { - return (!mTex.empty() || mDepth) ? true : false; + return (!mTex.empty() || mDepth) ? true : false; } void LLRenderTarget::getViewport(S32* viewport) { - viewport[0] = 0; - viewport[1] = 0; - viewport[2] = mResX; - viewport[3] = mResY; + viewport[0] = 0; + viewport[1] = 0; + viewport[2] = mResX; + viewport[3] = mResY; +} + +bool LLRenderTarget::isBoundInStack() const +{ + LLRenderTarget* cur = sBoundTarget; + while (cur && cur != this) + { + cur = cur->mPreviousRT; + } + + return cur == this; } - diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h index 5f3214add3..71727bf09d 100644 --- a/indra/llrender/llrendertarget.h +++ b/indra/llrender/llrendertarget.h @@ -33,6 +33,8 @@ #include "llrender.h" /* + Wrapper around OpenGL framebuffer objects for use in render-to-texture + SAMPLE USAGE: LLRenderTarget target; @@ -73,7 +75,12 @@ public: //allocate resources for rendering //must be called before use //multiple calls will release previously allocated resources - bool allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool sample_depth, LLTexUnit::eTextureType usage = LLTexUnit::TT_TEXTURE, bool use_fbo = false, S32 samples = 0); + // resX - width + // resY - height + // color_fmt - GL color format (e.g. GL_RGB) + // depth - if true, allocate a depth buffer + // usage - deprecated, should always be TT_TEXTURE + bool allocate(U32 resx, U32 resy, U32 color_fmt, bool depth = false, LLTexUnit::eTextureType usage = LLTexUnit::TT_TEXTURE); //resize existing attachments to use new resolution and color format // CAUTION: if the GL runs out of memory attempting to resize, this render target will be undefined @@ -93,7 +100,7 @@ public: // attachment -- LLImageGL to render into // use_name -- optional texture name to target instead of attachment->getTexName() // NOTE: setColorAttachment and releaseColorAttachment cannot be used in conjuction with - // addColorAttachment, allocateDepth, resize, etc. + // addColorAttachment, allocateDepth, resize, etc. void setColorAttachment(LLImageGL* attachment, LLGLuint use_name = 0); // detach from current color attachment @@ -111,14 +118,19 @@ public: //free any allocated resources //safe to call redundantly + // asserts that this target is not currently bound or present in the RT stack void release(); //bind target for rendering //applies appropriate viewport + // If an LLRenderTarget is currently bound, stores a reference to that LLRenderTarget + // and restores previous binding on flush() (maintains a stack of Render Targets) + // Asserts that this target is not currently bound in the stack void bindTarget(); //clear render targer, clears depth buffer if present, //uses scissor rect if in copy-to-texture mode + // asserts that this target is currently bound void clear(U32 mask = 0xFFFFFFFF); //get applied viewport @@ -136,7 +148,6 @@ public: U32 getNumTextures() const; U32 getDepth(void) const { return mDepth; } - bool canSampleDepth() const { return mSampleDepth; } void bindTexture(U32 index, S32 channel, LLTexUnit::eTextureFilterOptions filter_options = LLTexUnit::TFO_BILINEAR); @@ -144,15 +155,18 @@ public: //must be called when rendering is complete //should be used 1:1 with bindTarget // call bindTarget once, do all your rendering, call flush once - // if fetch_depth is TRUE, every effort will be made to copy the depth buffer into - // the current depth texture. A depth texture will be allocated if needed. - void flush(bool fetch_depth = FALSE); + // If an LLRenderTarget was bound when bindTarget was called, binds that RenderTarget for rendering (maintains RT stack) + // asserts that this target is currently bound + void flush(); //Returns TRUE if target is ready to be rendered into. //That is, if the target has been allocated with at least //one renderable attachment (i.e. color buffer, depth buffer). bool isComplete() const; + // Returns true if this RenderTarget is bound somewhere in the stack + bool isBoundInStack() const; + static LLRenderTarget* getCurrentBoundTarget() { return sBoundTarget; } protected: @@ -161,13 +175,10 @@ protected: std::vector mTex; std::vector mInternalFormat; U32 mFBO; - U32 mPreviousFBO; - U32 mPreviousResX; - U32 mPreviousResY; + LLRenderTarget* mPreviousRT = nullptr; - U32 mDepth; + U32 mDepth; bool mUseDepth; - bool mSampleDepth; LLTexUnit::eTextureType mUsage; diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 6001b011ee..27ac4053df 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -222,7 +222,7 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) } } - if (features->hasScreenSpaceReflections) + if (features->hasScreenSpaceReflections || features->hasReflectionProbes) { if (!shader->attachFragmentObject("deferred/screenSpaceReflUtil.glsl")) { @@ -1244,6 +1244,8 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("bumpMap"); mReservedUniforms.push_back("bumpMap2"); mReservedUniforms.push_back("environmentMap"); + mReservedUniforms.push_back("sceneMap"); + mReservedUniforms.push_back("sceneDepth"); mReservedUniforms.push_back("reflectionProbes"); mReservedUniforms.push_back("irradianceProbes"); mReservedUniforms.push_back("cloud_noise_texture"); @@ -1323,6 +1325,10 @@ void LLShaderMgr::initAttribsAndUniforms() llassert(mReservedUniforms.size() == LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH+1); + mReservedUniforms.push_back("modelview_delta"); + mReservedUniforms.push_back("inv_modelview_delta"); + mReservedUniforms.push_back("cube_snapshot"); + mReservedUniforms.push_back("tc_scale"); mReservedUniforms.push_back("rcp_screen_res"); mReservedUniforms.push_back("rcp_frame_opt"); diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index f6abfe9027..86ada6c132 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -90,6 +90,8 @@ public: BUMP_MAP, // "bumpMap" BUMP_MAP2, // "bumpMap2" ENVIRONMENT_MAP, // "environmentMap" + SCENE_MAP, // "sceneMap" + SCENE_DEPTH, // "sceneDepth" REFLECTION_PROBES, // "reflectionProbes" IRRADIANCE_PROBES, // "irradianceProbes" CLOUD_NOISE_MAP, // "cloud_noise_texture" @@ -158,6 +160,10 @@ public: DEFERRED_NORM_CUTOFF, // "norm_cutoff" DEFERRED_SHADOW_TARGET_WIDTH, // "shadow_target_width" + MODELVIEW_DELTA_MATRIX, // "modelview_delta" + INVERSE_MODELVIEW_DELTA_MATRIX, // "inv_modelview_delta" + CUBE_SNAPSHOT, // "cube_snapshot" + FXAA_TC_SCALE, // "tc_scale" FXAA_RCP_SCREEN_RES, // "rcp_screen_res" FXAA_RCP_FRAME_OPT, // "rcp_frame_opt" diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 40ab4a2e0f..11e2b6e5c4 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -744,7 +744,7 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const { - drawRange(mode, 0, mNumVerts, count, indices_offset); + drawRange(mode, 0, mNumVerts-1, count, indices_offset); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class1/deferred/reflectionProbeF.glsl index 95abd4d932..2ffe688524 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/reflectionProbeF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/reflectionProbeF.glsl @@ -25,14 +25,14 @@ // fallback stub -- will be used if actual reflection probe shader failed to load (output pink so it's obvious) void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv, - vec3 pos, vec3 norm, float glossiness, bool errorCorrect) + vec2 tc, vec3 pos, vec3 norm, float glossiness, bool errorCorrect) { ambenv = vec3(1,0,1); glossenv = vec3(1,0,1); } void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv, - vec3 pos, vec3 norm, float glossiness) + vec2 tc, vec3 pos, vec3 norm, float glossiness) { sampleReflectionProbes(ambenv, glossenv, pos, norm, glossiness, false); diff --git a/indra/newview/app_settings/shaders/class1/deferred/screenSpaceReflPostF.glsl b/indra/newview/app_settings/shaders/class1/deferred/screenSpaceReflPostF.glsl index 8373567bb0..df16e7f0e7 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/screenSpaceReflPostF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/screenSpaceReflPostF.glsl @@ -23,35 +23,11 @@ * $/LicenseInfo$ */ -#extension GL_ARB_texture_rectangle : enable + // debug stub -/*[EXTRA_CODE_HERE]*/ - -#ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_color; -#else -#define frag_color gl_FragColor -#endif -uniform vec2 screen_res; -uniform mat4 projection_matrix; -uniform mat4 inv_proj; -uniform float zNear; -uniform float zFar; - -VARYING vec2 vary_fragcoord; - -uniform sampler2D depthMap; -uniform sampler2D normalMap; -uniform sampler2D sceneMap; -uniform sampler2D diffuseRect; - -vec3 getNorm(vec2 screenpos); -float getDepth(vec2 pos_screen); -float linearDepth(float d, float znear, float zfar); - -void main() { - vec2 tc = vary_fragcoord.xy; - vec4 pos = getPositionWithDepth(tc, getDepth(tc)); - frag_color = pos; +void main() +{ + frag_color = vec4(0.5, 0.4, 0.1, 0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/screenSpaceReflUtil.glsl b/indra/newview/app_settings/shaders/class1/deferred/screenSpaceReflUtil.glsl index 6dfc89a6c6..b3da216b81 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/screenSpaceReflUtil.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/screenSpaceReflUtil.glsl @@ -23,98 +23,15 @@ * $/LicenseInfo$ */ -uniform sampler2D depthMap; -uniform sampler2D normalMap; -uniform sampler2D sceneMap; -uniform vec2 screen_res; -uniform mat4 projection_matrix; +// debug stub -// Shamelessly taken from http://casual-effects.blogspot.com/2014/08/screen-space-ray-tracing.html -// Original paper: https://jcgt.org/published/0003/04/04/ -// By Morgan McGuire and Michael Mara at Williams College 2014 -// Released as open source under the BSD 2-Clause License -// http://opensource.org/licenses/BSD-2-Clause - -float distanceSquared(vec2 a, vec2 b) { a -= b; return dot(a, a); } - -bool traceScreenSpaceRay1(vec3 csOrig, vec3 csDir, mat4 proj, float zThickness, - float nearPlaneZ, float stride, float jitter, const float maxSteps, float maxDistance, - out vec2 hitPixel, out vec3 hitPoint) +float random (vec2 uv) { - - // Clip to the near plane - float rayLength = ((csOrig.z + csDir.z * maxDistance) > nearPlaneZ) ? - (nearPlaneZ - csOrig.z) / csDir.z : maxDistance; - vec3 csEndPoint = csOrig + csDir * rayLength; - - // Project into homogeneous clip space - vec4 H0 = proj * vec4(csOrig, 1.0); - vec4 H1 = proj * vec4(csEndPoint, 1.0); - float k0 = 1.0 / H0.w, k1 = 1.0 / H1.w; - - // The interpolated homogeneous version of the camera-space points - vec3 Q0 = csOrig * k0, Q1 = csEndPoint * k1; - - // Screen-space endpoints - vec2 P0 = H0.xy * k0, P1 = H1.xy * k1; - - // If the line is degenerate, make it cover at least one pixel - // to avoid handling zero-pixel extent as a special case later - P1 += vec2((distanceSquared(P0, P1) < 0.0001) ? 0.01 : 0.0); - vec2 delta = P1 - P0; - - // Permute so that the primary iteration is in x to collapse - // all quadrant-specific DDA cases later - bool permute = false; - if (abs(delta.x) < abs(delta.y)) { - // This is a more-vertical line - permute = true; delta = delta.yx; P0 = P0.yx; P1 = P1.yx; - } - - float stepDir = sign(delta.x); - float invdx = stepDir / delta.x; - - // Track the derivatives of Q and k - vec3 dQ = (Q1 - Q0) * invdx; - float dk = (k1 - k0) * invdx; - vec2 dP = vec2(stepDir, delta.y * invdx); - - // Scale derivatives by the desired pixel stride and then - // offset the starting values by the jitter fraction - dP *= stride; dQ *= stride; dk *= stride; - P0 += dP * jitter; Q0 += dQ * jitter; k0 += dk * jitter; - - // Slide P from P0 to P1, (now-homogeneous) Q from Q0 to Q1, k from k0 to k1 - vec3 Q = Q0; - - // Adjust end condition for iteration direction - float end = P1.x * stepDir; - - float k = k0, stepCount = 0.0, prevZMaxEstimate = csOrig.z; - float rayZMin = prevZMaxEstimate, rayZMax = prevZMaxEstimate; - float sceneZMax = rayZMax + 100; - for (vec2 P = P0; - ((P.x * stepDir) <= end) && (stepCount < maxSteps) && - ((rayZMax < sceneZMax - zThickness) || (rayZMin > sceneZMax)) && - (sceneZMax != 0); - P += dP, Q.z += dQ.z, k += dk, ++stepCount) { - - rayZMin = prevZMaxEstimate; - rayZMax = (dQ.z * 0.5 + Q.z) / (dk * 0.5 + k); - prevZMaxEstimate = rayZMax; - if (rayZMin > rayZMax) { - float t = rayZMin; rayZMin = rayZMax; rayZMax = t; - } - - hitPixel = permute ? P.yx : P; - hitPixel.y = screen_res.y - hitPixel.y; - // You may need hitPixel.y = screen_res.y - hitPixel.y; here if your vertical axis - // is different than ours in screen space - sceneZMax = texelFetch(depthMap, ivec2(hitPixel)).r; - } - - // Advance Q based on the number of steps - Q.xy += dQ.xy * stepCount; - hitPoint = Q * (1.0 / k); - return (rayZMax >= sceneZMax - zThickness) && (rayZMin < sceneZMax); + return 0; } + +float tapScreenSpaceReflection(int totalSamples, vec2 tc, vec3 viewPos, vec3 n, inout vec4 collectedColor, sampler2D source) +{ + collectedColor = vec4(0); + return 0; +} \ No newline at end of file diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl index 076b976dc4..7435f1c0e1 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl @@ -90,8 +90,8 @@ float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen); float getAmbientClamp(); -void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv, - vec3 pos, vec3 norm, float glossiness, float envIntensity); +void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv, + vec2 tc, vec3 pos, vec3 norm, float glossiness, float envIntensity); vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 diffuse, vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight, float ambiance) { @@ -253,7 +253,7 @@ void main() vec3 irradiance; vec3 glossenv; vec3 legacyenv; - sampleReflectionProbesLegacy(irradiance, glossenv, legacyenv, pos.xyz, norm.xyz, 0.0, 0.0); + sampleReflectionProbesLegacy(irradiance, glossenv, legacyenv, frag, pos.xyz, norm.xyz, 0.0, 0.0); float da = dot(norm.xyz, light_dir.xyz); diff --git a/indra/newview/app_settings/shaders/class2/deferred/pbralphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/pbralphaF.glsl index d81102991e..ccf20942e3 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/pbralphaF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/pbralphaF.glsl @@ -84,7 +84,7 @@ void calcHalfVectors(vec3 lv, vec3 n, vec3 v, out vec3 h, out vec3 l, out float float calcLegacyDistanceAttenuation(float distance, float falloff); float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen); void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv, - vec3 pos, vec3 norm, float glossiness); + vec2 tc, vec3 pos, vec3 norm, float glossiness); void waterClip(vec3 pos); @@ -207,7 +207,7 @@ void main() float gloss = 1.0 - perceptualRoughness; vec3 irradiance = vec3(0); vec3 radiance = vec3(0); - sampleReflectionProbes(irradiance, radiance, pos.xyz, norm.xyz, gloss); + sampleReflectionProbes(irradiance, radiance, vec2(0), pos.xyz, norm.xyz, gloss); // Take maximium of legacy ambient vs irradiance sample as irradiance // NOTE: ao is applied in pbrIbl (see pbrBaseLight), do not apply here irradiance = max(amblit,irradiance); diff --git a/indra/newview/app_settings/shaders/class2/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class2/deferred/reflectionProbeF.glsl index af43c7b4e3..f1ee4b4681 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/reflectionProbeF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/reflectionProbeF.glsl @@ -34,7 +34,7 @@ uniform mat3 env_mat; vec3 srgb_to_linear(vec3 c); void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv, - vec3 pos, vec3 norm, float glossiness, bool errorCorrect) + vec2 tc, vec3 pos, vec3 norm, float glossiness, bool errorCorrect) { ambenv = vec3(reflection_probe_ambiance * 0.25); @@ -44,10 +44,10 @@ void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv, } void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv, - vec3 pos, vec3 norm, float glossiness) + vec2 tc, vec3 pos, vec3 norm, float glossiness) { sampleReflectionProbes(ambenv, glossenv, - pos, norm, glossiness, false); + tc, pos, norm, glossiness, false); } vec4 sampleReflectionProbesDebug(vec3 pos) @@ -56,8 +56,8 @@ vec4 sampleReflectionProbesDebug(vec3 pos) return vec4(0, 0, 0, 0); } -void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv, - vec3 pos, vec3 norm, float glossiness, float envIntensity) +void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv, + vec2 tc, vec3 pos, vec3 norm, float glossiness, float envIntensity) { ambenv = vec3(reflection_probe_ambiance * 0.25); diff --git a/indra/newview/app_settings/shaders/class3/deferred/fullbrightShinyF.glsl b/indra/newview/app_settings/shaders/class3/deferred/fullbrightShinyF.glsl index c0a1491446..160d360256 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/fullbrightShinyF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/fullbrightShinyF.glsl @@ -56,8 +56,9 @@ vec3 linear_to_srgb(vec3 c); vec3 srgb_to_linear(vec3 c); // reflection probe interface -void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyEnv, - vec3 pos, vec3 norm, float glossiness, float envIntensity); +void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv, + vec2 tc, vec3 pos, vec3 norm, float glossiness, float envIntensity); + void applyGlossEnv(inout vec3 color, vec3 glossenv, vec4 spec, vec3 pos, vec3 norm); void applyLegacyEnv(inout vec3 color, vec3 legacyenv, vec4 spec, vec3 pos, vec3 norm, float envIntensity); @@ -91,7 +92,7 @@ void main() vec3 legacyenv; vec3 norm = normalize(vary_texcoord1.xyz); vec4 spec = vec4(0,0,0,0); - sampleReflectionProbesLegacy(ambenv, glossenv, legacyenv, pos.xyz, norm.xyz, spec.a, env_intensity); + sampleReflectionProbesLegacy(ambenv, glossenv, legacyenv, vec2(0), pos.xyz, norm.xyz, spec.a, env_intensity); applyLegacyEnv(color.rgb, legacyenv, spec, pos, norm, env_intensity); color.rgb = fullbrightAtmosTransportFrag(color.rgb, additive, atten); diff --git a/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl index 8016022d78..8d2a65d4a9 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl @@ -61,8 +61,8 @@ out vec4 frag_color; float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen); #endif -void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv, - vec3 pos, vec3 norm, float glossiness, float envIntensity); +void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv, + vec2 tc, vec3 pos, vec3 norm, float glossiness, float envIntensity); void applyGlossEnv(inout vec3 color, vec3 glossenv, vec4 spec, vec3 pos, vec3 norm); void applyLegacyEnv(inout vec3 color, vec3 legacyenv, vec4 spec, vec3 pos, vec3 norm, float envIntensity); @@ -310,7 +310,7 @@ void main() vec3 ambenv; vec3 glossenv; vec3 legacyenv; - sampleReflectionProbesLegacy(ambenv, glossenv, legacyenv, pos.xyz, norm.xyz, final_specular.a, env_intensity); + sampleReflectionProbesLegacy(ambenv, glossenv, legacyenv, pos_screen, pos.xyz, norm.xyz, final_specular.a, env_intensity); // use sky settings ambient or irradiance map sample, whichever is brighter color = max(amblit, ambenv); diff --git a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl index 0cb966296a..9793ab13de 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl @@ -25,11 +25,17 @@ #define FLT_MAX 3.402823466e+38 +#if defined(SSR) +float tapScreenSpaceReflection(int totalSamples, vec2 tc, vec3 viewPos, vec3 n, inout vec4 collectedColor, sampler2D source); +#endif + #define REFMAP_COUNT 256 #define REF_SAMPLE_COUNT 64 //maximum number of samples to consider uniform samplerCubeArray reflectionProbes; uniform samplerCubeArray irradianceProbes; +uniform sampler2D sceneMap; +uniform int cube_snapshot; layout (std140) uniform ReflectionProbes { @@ -92,14 +98,17 @@ bool shouldSampleProbe(int i, vec3 pos) } else { - vec3 delta = pos.xyz - refSphere[i].xyz; - float d = dot(delta, delta); - float r2 = refSphere[i].w; - r2 *= r2; + if (refSphere[i].w > 0.0) // zero is special indicator to always sample this probe + { + vec3 delta = pos.xyz - refSphere[i].xyz; + float d = dot(delta, delta); + float r2 = refSphere[i].w; + r2 *= r2; - if (d > r2) - { //outside bounding sphere - return false; + if (d > r2) + { //outside bounding sphere + return false; + } } max_priority = max(max_priority, refIndex[i].w); @@ -138,13 +147,13 @@ void preProbeSample(vec3 pos) probeIndex[probeInfluences++] = idx; if (probeInfluences == REF_SAMPLE_COUNT) { - return; + break; } } count++; if (count == neighborCount) { - return; + break; } idx = refNeighbor[neighborIdx].y; @@ -153,13 +162,13 @@ void preProbeSample(vec3 pos) probeIndex[probeInfluences++] = idx; if (probeInfluences == REF_SAMPLE_COUNT) { - return; + break; } } count++; if (count == neighborCount) { - return; + break; } idx = refNeighbor[neighborIdx].z; @@ -168,13 +177,13 @@ void preProbeSample(vec3 pos) probeIndex[probeInfluences++] = idx; if (probeInfluences == REF_SAMPLE_COUNT) { - return; + break; } } count++; if (count == neighborCount) { - return; + break; } idx = refNeighbor[neighborIdx].w; @@ -183,27 +192,26 @@ void preProbeSample(vec3 pos) probeIndex[probeInfluences++] = idx; if (probeInfluences == REF_SAMPLE_COUNT) { - return; + break; } } count++; if (count == neighborCount) { - return; + break; } ++neighborIdx; } - return; + break; } } } - if (probeInfluences == 0) - { // probe at index 0 is a special fallback probe - probeIndex[0] = 0; - probeInfluences = 1; + if (max_priority <= 1) + { // probe at index 0 is a special probe for smoothing out automatic probes + probeIndex[probeInfluences++] = 0; } } @@ -330,7 +338,8 @@ return texCUBE(envMap, ReflDirectionWS); // origin - ray origin in clip space // dir - ray direction in clip space // i - probe index in refBox/refSphere -vec3 boxIntersect(vec3 origin, vec3 dir, int i) +// d - distance to nearest wall in clip space +vec3 boxIntersect(vec3 origin, vec3 dir, int i, out float d) { // Intersection with OBB convertto unit box space // Transform in local unit parallax cube space (scaled and rotated) @@ -339,6 +348,8 @@ vec3 boxIntersect(vec3 origin, vec3 dir, int i) vec3 RayLS = mat3(clipToLocal) * dir; vec3 PositionLS = (clipToLocal * vec4(origin, 1.0)).xyz; + d = 1.0-max(max(abs(PositionLS.x), abs(PositionLS.y)), abs(PositionLS.z)); + vec3 Unitary = vec3(1.0f, 1.0f, 1.0f); vec3 FirstPlaneIntersect = (Unitary - PositionLS) / RayLS; vec3 SecondPlaneIntersect = (-Unitary - PositionLS) / RayLS; @@ -413,6 +424,29 @@ void boxIntersectDebug(vec3 origin, vec3 pos, int i, inout vec4 col) } +// get the weight of a sphere probe +// pos - position to be weighted +// dir - normal to be weighted +// origin - center of sphere probe +// r - radius of probe influence volume +// min_da - minimum angular attenuation coefficient +float sphereWeight(vec3 pos, vec3 dir, vec3 origin, float r, float min_da) +{ + float r1 = r * 0.5; // 50% of radius (outer sphere to start interpolating down) + vec3 delta = pos.xyz - origin; + float d2 = max(length(delta), 0.001); + float r2 = r1; //r1 * r1; + + //float atten = 1.0 - max(d2 - r2, 0.0) / max((rr - r2), 0.001); + float atten = 1.0 - max(d2 - r2, 0.0) / max((r - r2), 0.001); + + atten *= max(dot(normalize(-delta), dir), min_da); + float w = 1.0 / d2; + w *= atten; + + return w; +} + // Tap a reflection probe // pos - position of pixel // dir - pixel normal @@ -431,27 +465,21 @@ vec3 tapRefMap(vec3 pos, vec3 dir, out float w, out vec3 vi, out vec3 wi, float if (refIndex[i].w < 0) { - v = boxIntersect(pos, dir, i); - w = 1.0; + float d = 0; + v = boxIntersect(pos, dir, i, d); + + w = max(d, 0.001); } else { float r = refSphere[i].w; // radius of sphere volume float rr = r * r; // radius squared - v = sphereIntersect(pos, dir, c, rr); + v = sphereIntersect(pos, dir, c, + refIndex[i].w <= 1 ? 4096.0*4096.0 : // <== effectively disable parallax correction for automatically placed probes to keep from bombing the world with obvious spheres + rr); - float p = float(abs(refIndex[i].w)); // priority - - float r1 = r * 0.1; // 90% of radius (outer sphere to start interpolating down) - vec3 delta = pos.xyz - refSphere[i].xyz; - float d2 = max(dot(delta, delta), 0.001); - float r2 = r1 * r1; - - float atten = 1.0 - max(d2 - r2, 0.0) / max((rr - r2), 0.001); - - w = 1.0 / d2; - w *= atten; + w = sphereWeight(pos, dir, refSphere[i].xyz, r, 0.25); } vi = v; @@ -480,8 +508,9 @@ vec3 tapIrradianceMap(vec3 pos, vec3 dir, out float w, vec3 c, int i) vec3 v; if (refIndex[i].w < 0) { - v = boxIntersect(pos, dir, i); - w = 1.0; + float d = 0.0; + v = boxIntersect(pos, dir, i, d); + w = max(d, 0.001); } else { @@ -489,17 +518,11 @@ vec3 tapIrradianceMap(vec3 pos, vec3 dir, out float w, vec3 c, int i) float p = float(abs(refIndex[i].w)); // priority float rr = r * r; // radius squred - v = sphereIntersect(pos, dir, c, rr); + v = sphereIntersect(pos, dir, c, + refIndex[i].w <= 1 ? 4096.0*4096.0 : // <== effectively disable parallax correction for automatically placed probes to keep from bombing the world with obvious spheres + rr); - float r1 = r * 0.1; // 75% of radius (outer sphere to start interpolating down) - vec3 delta = pos.xyz - refSphere[i].xyz; - float d2 = dot(delta, delta); - float r2 = r1 * r1; - - w = 1.0 / d2; - - float atten = 1.0 - max(d2 - r2, 0.0) / (rr - r2); - w *= atten; + w = sphereWeight(pos, dir, refSphere[i].xyz, r, 0.001); } v -= c; @@ -605,7 +628,7 @@ vec3 sampleProbeAmbient(vec3 pos, vec3 dir) } void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv, - vec3 pos, vec3 norm, float glossiness, bool errorCorrect) + vec2 tc, vec3 pos, vec3 norm, float glossiness, bool errorCorrect) { // TODO - don't hard code lods float reflection_lods = 6; @@ -617,6 +640,17 @@ void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv, float lod = (1.0-glossiness)*reflection_lods; glossenv = sampleProbes(pos, normalize(refnormpersp), lod, errorCorrect); + +#if defined(SSR) + if (cube_snapshot != 1) + { + vec4 ssr = vec4(0); + //float w = tapScreenSpaceReflection(errorCorrect ? 1 : 4, tc, pos, norm, ssr, sceneMap); + float w = tapScreenSpaceReflection(1, tc, pos, norm, ssr, sceneMap); + + glossenv = mix(glossenv, ssr.rgb, w); + } +#endif } void debugTapRefMap(vec3 pos, vec3 dir, float depth, int i, inout vec4 col) @@ -660,15 +694,15 @@ vec4 sampleReflectionProbesDebug(vec3 pos) } void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv, - vec3 pos, vec3 norm, float glossiness) + vec2 tc, vec3 pos, vec3 norm, float glossiness) { sampleReflectionProbes(ambenv, glossenv, - pos, norm, glossiness, false); + tc, pos, norm, glossiness, false); } void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv, - vec3 pos, vec3 norm, float glossiness, float envIntensity) + vec2 tc, vec3 pos, vec3 norm, float glossiness, float envIntensity) { // TODO - don't hard code lods float reflection_lods = 7; @@ -676,7 +710,6 @@ void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 refnormpersp = reflect(pos.xyz, norm.xyz); - ambenv = sampleProbeAmbient(pos, norm); if (glossiness > 0.0) @@ -689,6 +722,17 @@ void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout { legacyenv = sampleProbes(pos, normalize(refnormpersp), 0.0, false); } + +#if defined(SSR) + if (cube_snapshot != 1) + { + vec4 ssr = vec4(0); + float w = tapScreenSpaceReflection(1, tc, pos, norm, ssr, sceneMap); + + glossenv = mix(glossenv, ssr.rgb, w); + legacyenv = mix(legacyenv, ssr.rgb, w); + } +#endif } void applyGlossEnv(inout vec3 color, vec3 glossenv, vec4 spec, vec3 pos, vec3 norm) diff --git a/indra/newview/app_settings/shaders/class3/deferred/screenSpaceReflPostF.glsl b/indra/newview/app_settings/shaders/class3/deferred/screenSpaceReflPostF.glsl index 4813e6c2d9..742f528cb1 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/screenSpaceReflPostF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/screenSpaceReflPostF.glsl @@ -42,10 +42,7 @@ uniform float zFar; VARYING vec2 vary_fragcoord; VARYING vec3 camera_ray; -uniform sampler2D depthMap; -uniform sampler2D normalMap; uniform sampler2D specularRect; -uniform sampler2D sceneMap; uniform sampler2D diffuseRect; uniform sampler2D diffuseMap; @@ -57,27 +54,27 @@ float linearDepth01(float d, float znear, float zfar); vec4 getPositionWithDepth(vec2 pos_screen, float depth); vec4 getPosition(vec2 pos_screen); vec4 getNormalEnvIntensityFlags(vec2 screenpos, out vec3 n, out float envIntensity); -bool traceScreenRay(vec3 position, vec3 reflection, out vec4 hitColor, out float hitDepth, float depth, sampler2D textureFrame); float random (vec2 uv); +float tapScreenSpaceReflection(int totalSamples, vec2 tc, vec3 viewPos, vec3 n, inout vec4 collectedColor, sampler2D source); void main() { vec2 tc = vary_fragcoord.xy; float depth = linearDepth01(getDepth(tc), zNear, zFar); - vec3 n = vec3(0, 0, 1); float envIntensity; + vec3 n; vec4 norm = getNormalEnvIntensityFlags(tc, n, envIntensity); // need `norm.w` for GET_GBUFFER_FLAG() vec3 pos = getPositionWithDepth(tc, getDepth(tc)).xyz; vec4 spec = texture2D(specularRect, tc); - vec3 viewPos = camera_ray * depth; - vec3 rayDirection = normalize(reflect(normalize(viewPos), n)) * -viewPos.z; vec2 hitpixel; - vec4 hitpoint; + vec4 diffuse = texture2D(diffuseRect, tc); vec3 specCol = spec.rgb; + frag_color = texture(diffuseMap, tc); + if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR)) { vec3 orm = specCol.rgb; @@ -85,44 +82,17 @@ void main() float metallic = orm.b; vec3 f0 = vec3(0.04); vec3 baseColor = diffuse.rgb; - + vec3 diffuseColor = baseColor.rgb*(vec3(1.0)-f0); specCol = mix(f0, baseColor.rgb, metallic); } - vec2 uv2 = tc * screen_res; - float c = (uv2.x + uv2.y) * 0.125; - float jitter = mod( c, 1.0); + vec4 collectedColor = vec4(0); - vec3 firstBasis = normalize(cross(vec3(1.f, 1.f, 1.f), rayDirection)); - vec3 secondBasis = normalize(cross(rayDirection, firstBasis)); - - frag_color = texture(diffuseMap, tc); - vec4 collectedColor; - - vec2 screenpos = 1 - abs(tc * 2 - 1); - float vignette = clamp((screenpos.x * screenpos.y) * 16,0, 1); - vignette *= clamp((dot(normalize(viewPos), n) * 0.5 + 0.5 - 0.2) * 8, 0, 1); - vignette *= min(linearDepth(getDepth(tc), zNear, zFar) / zFar, 1); + float w = tapScreenSpaceReflection(4, tc, pos, n, collectedColor, diffuseMap); - int totalSamples = 4; + collectedColor.rgb *= specCol.rgb; - for (int i = 0; i < totalSamples; i++) - { - vec2 coeffs = vec2(random(tc + vec2(0, i)) + random(tc + vec2(i, 0))); - vec3 reflectionDirectionRandomized = rayDirection + firstBasis * coeffs.x + secondBasis * coeffs.y; - - bool hit = traceScreenRay(pos, reflectionDirectionRandomized, hitpoint, depth, depth, diffuseMap); - - if (hit) - { - collectedColor += hitpoint; - collectedColor.rgb *= specCol.rgb; - } - } - - collectedColor *= vignette; - - frag_color += collectedColor; + frag_color += collectedColor * w; } diff --git a/indra/newview/app_settings/shaders/class3/deferred/screenSpaceReflUtil.glsl b/indra/newview/app_settings/shaders/class3/deferred/screenSpaceReflUtil.glsl index b6c789ad40..570235a816 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/screenSpaceReflUtil.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/screenSpaceReflUtil.glsl @@ -23,19 +23,18 @@ * $/LicenseInfo$ */ -uniform sampler2D depthMap; -uniform sampler2D normalMap; uniform sampler2D sceneMap; +uniform sampler2D sceneDepth; + uniform vec2 screen_res; uniform mat4 projection_matrix; -uniform float zNear; -uniform float zFar; +//uniform float zNear; +//uniform float zFar; uniform mat4 inv_proj; +uniform mat4 modelview_delta; // should be transform from last camera space to current camera space +uniform mat4 inv_modelview_delta; vec4 getPositionWithDepth(vec2 pos_screen, float depth); -float linearDepth(float depth, float near, float far); -float getDepth(vec2 pos_screen); -float linearDepth01(float d, float znear, float zfar); float random (vec2 uv) { @@ -62,8 +61,25 @@ float distanceBias = 0.02; float depthRejectBias = 0.001; float epsilon = 0.1; +float getLinearDepth(vec2 tc) +{ + float depth = texture(sceneDepth, tc).r; + + vec4 pos = getPositionWithDepth(tc, depth); + + return -pos.z; +} + bool traceScreenRay(vec3 position, vec3 reflection, out vec4 hitColor, out float hitDepth, float depth, sampler2D textureFrame) { + // transform position and reflection into same coordinate frame as the sceneMap and sceneDepth + reflection += position; + position = (inv_modelview_delta * vec4(position, 1)).xyz; + reflection = (inv_modelview_delta * vec4(reflection, 1)).xyz; + reflection -= position; + + depth = -position.z; + vec3 step = rayStep * reflection; vec3 marchingPosition = position + step; float delta; @@ -72,13 +88,14 @@ bool traceScreenRay(vec3 position, vec3 reflection, out vec4 hitColor, out float bool hit = false; hitColor = vec4(0); + int i = 0; if (depth > depthRejectBias) { for (; i < iterationCount && !hit; i++) { screenPosition = generateProjectedPosition(marchingPosition); - depthFromScreen = linearDepth(getDepth(screenPosition), zNear, zFar); + depthFromScreen = getLinearDepth(screenPosition); delta = abs(marchingPosition.z) - depthFromScreen; if (depth < depthFromScreen + epsilon && depth > depthFromScreen - epsilon) @@ -91,7 +108,7 @@ bool traceScreenRay(vec3 position, vec3 reflection, out vec4 hitColor, out float vec4 color = vec4(1); if(debugDraw) color = vec4( 0.5+ sign(delta)/2,0.3,0.5- sign(delta)/2, 0); - hitColor = texture(textureFrame, screenPosition) * color; + hitColor = texture(sceneMap, screenPosition) * color; hitDepth = depthFromScreen; hit = true; break; @@ -126,7 +143,7 @@ bool traceScreenRay(vec3 position, vec3 reflection, out vec4 hitColor, out float marchingPosition = marchingPosition - step * sign(delta); screenPosition = generateProjectedPosition(marchingPosition); - depthFromScreen = linearDepth(getDepth(screenPosition), zNear, zFar); + depthFromScreen = getLinearDepth(screenPosition); delta = abs(marchingPosition.z) - depthFromScreen; if (depth < depthFromScreen + epsilon && depth > depthFromScreen - epsilon) @@ -139,7 +156,7 @@ bool traceScreenRay(vec3 position, vec3 reflection, out vec4 hitColor, out float vec4 color = vec4(1); if(debugDraw) color = vec4( 0.5+ sign(delta)/2,0.3,0.5- sign(delta)/2, 0); - hitColor = texture(textureFrame, screenPosition) * color; + hitColor = texture(sceneMap, screenPosition) * color; hitDepth = depthFromScreen; hit = true; break; @@ -150,3 +167,68 @@ bool traceScreenRay(vec3 position, vec3 reflection, out vec4 hitColor, out float return hit; } + +float tapScreenSpaceReflection(int totalSamples, vec2 tc, vec3 viewPos, vec3 n, inout vec4 collectedColor, sampler2D source) +{ + collectedColor = vec4(0); + int hits = 0; + + float depth = -viewPos.z; + + vec3 rayDirection = normalize(reflect(viewPos, normalize(n))); + + vec2 uv2 = tc * screen_res; + float c = (uv2.x + uv2.y) * 0.125; + float jitter = mod( c, 1.0); + + vec3 firstBasis = normalize(cross(vec3(1,1,1), rayDirection)); + vec3 secondBasis = normalize(cross(rayDirection, firstBasis)); + + vec2 screenpos = 1 - abs(tc * 2 - 1); + float vignette = clamp((screenpos.x * screenpos.y) * 16,0, 1); + vignette *= clamp((dot(normalize(viewPos), n) * 0.5 + 0.5 - 0.2) * 8, 0, 1); + float zFar = 64.0; + vignette *= clamp(1.0+(viewPos.z/zFar), 0.0, 1.0); + //vignette *= min(linearDepth(getDepth(tc), zNear, zFar) / zFar, 1); + + vec4 hitpoint; + + if (totalSamples > 1) + { + for (int i = 0; i < totalSamples; i++) + { + vec2 coeffs = vec2(random(tc + vec2(0, i)) + random(tc + vec2(i, 0))); + vec3 reflectionDirectionRandomized = rayDirection + firstBasis * coeffs.x + secondBasis * coeffs.y; + + //float hitDepth; + + bool hit = traceScreenRay(viewPos, normalize(reflectionDirectionRandomized), hitpoint, depth, depth, source); + + if (hit) + { + ++hits; + collectedColor += hitpoint; + } + } + } + else + { + bool hit = traceScreenRay(viewPos, normalize(rayDirection), hitpoint, depth, depth, source); + if (hit) + { + ++hits; + collectedColor += hitpoint; + } + } + + if (hits > 0) + { + collectedColor /= hits; + } + else + { + collectedColor = vec4(0); + } + + return min(float(hits), 1.0) * vignette; +} \ No newline at end of file diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index 8e4197ae77..8d48e6f596 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -75,9 +75,9 @@ vec3 fullbrightAtmosTransportFragLinear(vec3 light, vec3 additive, vec3 atten); // reflection probe interface void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv, - vec3 pos, vec3 norm, float glossiness); -void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyEnv, - vec3 pos, vec3 norm, float glossiness, float envIntensity); + vec2 tc, vec3 pos, vec3 norm, float glossiness); +void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv, + vec2 tc, vec3 pos, vec3 norm, float glossiness, float envIntensity); void applyGlossEnv(inout vec3 color, vec3 glossenv, vec4 spec, vec3 pos, vec3 norm); void applyLegacyEnv(inout vec3 color, vec3 legacyenv, vec4 spec, vec3 pos, vec3 norm, float envIntensity); float getDepth(vec2 pos_screen); @@ -166,7 +166,7 @@ void main() float gloss = 1.0 - perceptualRoughness; vec3 irradiance = vec3(0); vec3 radiance = vec3(0); - sampleReflectionProbes(irradiance, radiance, pos.xyz, norm.xyz, gloss); + sampleReflectionProbes(irradiance, radiance, tc, pos.xyz, norm.xyz, gloss); // Take maximium of legacy ambient vs irradiance sample as irradiance // NOTE: ao is applied in pbrIbl (see pbrBaseLight), do not apply here @@ -196,7 +196,7 @@ void main() vec3 glossenv = vec3(0); vec3 legacyenv = vec3(0); - sampleReflectionProbesLegacy(irradiance, glossenv, legacyenv, pos.xyz, norm.xyz, spec.a, envIntensity); + sampleReflectionProbesLegacy(irradiance, glossenv, legacyenv, tc, pos.xyz, norm.xyz, spec.a, envIntensity); // use sky settings ambient or irradiance map sample, whichever is brighter irradiance = max(amblit, irradiance); diff --git a/indra/newview/app_settings/shaders/class3/environment/waterF.glsl b/indra/newview/app_settings/shaders/class3/environment/waterF.glsl index 85c3f42801..b792feee2a 100644 --- a/indra/newview/app_settings/shaders/class3/environment/waterF.glsl +++ b/indra/newview/app_settings/shaders/class3/environment/waterF.glsl @@ -95,9 +95,6 @@ vec3 BlendNormal(vec3 bump1, vec3 bump2) vec3 srgb_to_linear(vec3 col); -void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv, - vec3 pos, vec3 norm, float glossiness, float envIntensity); - vec3 vN, vT, vB; vec3 transform_normal(vec3 vNt) @@ -106,7 +103,10 @@ vec3 transform_normal(vec3 vNt) } void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv, - vec3 pos, vec3 norm, float glossiness, bool errorCorrect); + vec2 tc, vec3 pos, vec3 norm, float glossiness); + +void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv, + vec2 tc, vec3 pos, vec3 norm, float glossiness, bool errorCorrect); vec3 getPositionWithNDC(vec3 ndc); @@ -225,7 +225,7 @@ void main() vec3 irradiance = vec3(0); vec3 radiance = vec3(0); - sampleReflectionProbes(irradiance, radiance, pos, refnorm, gloss, true); + sampleReflectionProbes(irradiance, radiance, distort, pos, refnorm, gloss, true); radiance *= 0.5; irradiance = fb.rgb; diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp index 9bb3bac104..5b8ca6c49c 100644 --- a/indra/newview/llfasttimerview.cpp +++ b/indra/newview/llfasttimerview.cpp @@ -468,7 +468,7 @@ void LLFastTimerView::exportCharts(const std::string& base, const std::string& t { //allocate render target for drawing charts LLRenderTarget buffer; - buffer.allocate(1024,512, GL_RGB, FALSE, FALSE); + buffer.allocate(1024,512, GL_RGB); LLSD cur; diff --git a/indra/newview/llglsandbox.cpp b/indra/newview/llglsandbox.cpp index fe7c1c8f2c..2e4d0f85b9 100644 --- a/indra/newview/llglsandbox.cpp +++ b/indra/newview/llglsandbox.cpp @@ -1050,7 +1050,7 @@ F32 gpu_benchmark() for (U32 i = 0; i < count; ++i) { //allocate render targets and textures - if (!dest[i].allocate(res, res, GL_RGBA, false, false, LLTexUnit::TT_TEXTURE, true)) + if (!dest[i].allocate(res, res, GL_RGBA)) { LL_WARNS("Benchmark") << "Failed to allocate render target." << LL_ENDL; // abandon the benchmark test diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp index b87406cb6e..128aa99ccc 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -39,6 +39,14 @@ extern BOOL gCubeSnapshot; extern BOOL gTeleportDisplay; +static void touch_default_probe(LLReflectionMap* probe) +{ + LLVector3 origin = LLViewerCamera::getInstance()->getOrigin(); + origin.mV[2] += 64.f; + + probe->mOrigin.load3(origin.mV); +} + LLReflectionMapManager::LLReflectionMapManager() { initCubeFree(); @@ -83,10 +91,8 @@ void LLReflectionMapManager::update() if (!mRenderTarget.isComplete()) { U32 color_fmt = GL_RGB16F; - const bool use_depth_buffer = true; - const bool use_stencil_buffer = false; U32 targetRes = LL_REFLECTION_PROBE_RESOLUTION * 2; // super sample - mRenderTarget.allocate(targetRes, targetRes, color_fmt, use_depth_buffer, use_stencil_buffer, LLTexUnit::TT_TEXTURE); + mRenderTarget.allocate(targetRes, targetRes, color_fmt, true); } if (mMipChain.empty()) @@ -97,7 +103,7 @@ void LLReflectionMapManager::update() mMipChain.resize(count); for (int i = 0; i < count; ++i) { - mMipChain[i].allocate(res, res, GL_RGBA16F, false, false, LLTexUnit::TT_TEXTURE); + mMipChain[i].allocate(res, res, GL_RGBA16F); res /= 2; } } @@ -108,9 +114,8 @@ void LLReflectionMapManager::update() mDefaultProbe = addProbe(); mDefaultProbe->mDistance = -4096.f; // hack to make sure the default probe is always first in sort order mDefaultProbe->mRadius = 4096.f; + touch_default_probe(mDefaultProbe); } - - mDefaultProbe->mOrigin.load3(LLViewerCamera::getInstance()->getOrigin().mV); LLVector4a camera_pos; camera_pos.load3(LLViewerCamera::instance().getOrigin().mV); @@ -155,6 +160,8 @@ void LLReflectionMapManager::update() doProbeUpdate(); } + //LL_INFOS() << mProbes.size() << LL_ENDL; + for (int i = 0; i < mProbes.size(); ++i) { LLReflectionMap* probe = mProbes[i]; @@ -403,7 +410,26 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) { // hacky hot-swap of camera specific render targets gPipeline.mRT = &gPipeline.mAuxillaryRT; - probe->update(mRenderTarget.getWidth(), face); + + if (probe == mDefaultProbe) + { + touch_default_probe(probe); + + gPipeline.pushRenderTypeMask(); + + //only render sky, water, terrain, and clouds + gPipeline.andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY, LLPipeline::RENDER_TYPE_WL_SKY, + LLPipeline::RENDER_TYPE_WATER, LLPipeline::RENDER_TYPE_CLOUDS, LLPipeline::RENDER_TYPE_TERRAIN, LLPipeline::END_RENDER_TYPES); + + probe->update(mRenderTarget.getWidth(), face); + + gPipeline.popRenderTypeMask(); + } + else + { + probe->update(mRenderTarget.getWidth(), face); + } + gPipeline.mRT = &gPipeline.mMainRT; S32 targetIdx = mReflectionProbeCount; diff --git a/indra/newview/llscenemonitor.cpp b/indra/newview/llscenemonitor.cpp index 49d5aa3e14..fb2577e00e 100644 --- a/indra/newview/llscenemonitor.cpp +++ b/indra/newview/llscenemonitor.cpp @@ -177,7 +177,7 @@ LLRenderTarget& LLSceneMonitor::getCaptureTarget() if(!mFrames[0]) { mFrames[0] = new LLRenderTarget(); - mFrames[0]->allocate(width, height, GL_RGB, false, false, LLTexUnit::TT_TEXTURE, true); + mFrames[0]->allocate(width, height, GL_RGB); gGL.getTexUnit(0)->bind(mFrames[0]); gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); @@ -187,7 +187,7 @@ LLRenderTarget& LLSceneMonitor::getCaptureTarget() else if(!mFrames[1]) { mFrames[1] = new LLRenderTarget(); - mFrames[1]->allocate(width, height, GL_RGB, false, false, LLTexUnit::TT_TEXTURE, true); + mFrames[1]->allocate(width, height, GL_RGB); gGL.getTexUnit(0)->bind(mFrames[1]); gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); @@ -360,7 +360,7 @@ void LLSceneMonitor::compare() if(!mDiff) { mDiff = new LLRenderTarget(); - mDiff->allocate(width, height, GL_RGBA, false, false, LLTexUnit::TT_TEXTURE, true); + mDiff->allocate(width, height, GL_RGBA); generateDitheringTexture(width, height); } diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 8b9df88fd4..5ddd8c78f7 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -682,6 +682,7 @@ void settings_setup_listeners() // DEPRECATED - setting_setup_signal_listener(gSavedSettings, "RenderDeferred", handleRenderDeferredChanged); setting_setup_signal_listener(gSavedSettings, "RenderReflectionProbeDetail", handleReflectionProbeDetailChanged); setting_setup_signal_listener(gSavedSettings, "RenderReflectionsEnabled", handleReflectionProbeDetailChanged); + setting_setup_signal_listener(gSavedSettings, "RenderScreenSpaceReflections", handleReflectionProbeDetailChanged); setting_setup_signal_listener(gSavedSettings, "RenderShadowDetail", handleSetShaderChanged); setting_setup_signal_listener(gSavedSettings, "RenderDeferredSSAO", handleSetShaderChanged); setting_setup_signal_listener(gSavedSettings, "RenderPerformanceTest", handleRenderPerfTestChanged); diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 5af03477d6..497b2373da 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -918,15 +918,6 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) gGL.setColorMask(true, true); gPipeline.renderGeomDeferred(*LLViewerCamera::getInstance(), true); - - //store this frame's modelview matrix for use - //when rendering next frame's occlusion queries - for (U32 i = 0; i < 16; i++) - { - gGLLastModelView[i] = gGLModelView[i]; - gGLLastProjection[i] = gGLProjection[i]; - } - stop_glerror(); } { diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 874dec2c2d..90b06fa133 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -843,6 +843,7 @@ std::string LLViewerShaderMgr::loadBasicShaders() BOOL ambient_kill = gSavedSettings.getBOOL("AmbientDisable"); BOOL sunlight_kill = gSavedSettings.getBOOL("SunlightDisable"); BOOL local_light_kill = gSavedSettings.getBOOL("LocalLightDisable"); + BOOL ssr = gSavedSettings.getBOOL("RenderScreenSpaceReflections"); if (ambient_kill) { @@ -871,6 +872,11 @@ std::string LLViewerShaderMgr::loadBasicShaders() } } + if (ssr) + { + attribs["SSR"] = "1"; + } + // We no longer have to bind the shaders to global glhandles, they are automatically added to a map now. for (U32 i = 0; i < shaders.size(); i++) { @@ -910,7 +916,7 @@ std::string LLViewerShaderMgr::loadBasicShaders() index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/shadowUtil.glsl", 1) ); index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/aoUtil.glsl", 1) ); index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/reflectionProbeF.glsl", has_reflection_probes ? 3 : 2) ); - index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/screenSpaceReflUtil.glsl", 3) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/screenSpaceReflUtil.glsl", ssr ? 3 : 1) ); index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightNonIndexedF.glsl", mShaderLevel[SHADER_LIGHTING] ) ); index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightAlphaMaskNonIndexedF.glsl", mShaderLevel[SHADER_LIGHTING] ) ); index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightFullbrightNonIndexedF.glsl", mShaderLevel[SHADER_LIGHTING] ) ); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index bccb2a5e77..20b5f7f394 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -4898,7 +4898,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei (image_width > window_width || image_height > window_height) && LLPipeline::sRenderDeferred && !show_ui) { U32 color_fmt = type == LLSnapshotModel::SNAPSHOT_TYPE_DEPTH ? GL_DEPTH_COMPONENT : GL_RGBA; - if (scratch_space.allocate(image_width, image_height, color_fmt, true, true)) + if (scratch_space.allocate(image_width, image_height, color_fmt, true)) { original_width = gPipeline.mRT->deferredScreen.getWidth(); original_height = gPipeline.mRT->deferredScreen.getHeight(); @@ -5162,9 +5162,7 @@ BOOL LLViewerWindow::simpleSnapshot(LLImageRaw* raw, S32 image_width, S32 image_ LLRenderTarget scratch_space; U32 color_fmt = GL_RGBA; - const bool use_depth_buffer = true; - const bool use_stencil_buffer = false; - if (scratch_space.allocate(image_width, image_height, color_fmt, use_depth_buffer, use_stencil_buffer)) + if (scratch_space.allocate(image_width, image_height, color_fmt, true)) { if (gPipeline.allocateScreenBuffer(image_width, image_height)) { diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index f0644cbbf5..64f7535f05 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -479,14 +479,9 @@ void LLPipeline::init() mBackfaceCull = true; - stop_glerror(); - // Enable features - LLViewerShaderMgr::instance()->setShaders(); - stop_glerror(); - for (U32 i = 0; i < 2; ++i) { mSpotLightFade[i] = 1.f; @@ -835,7 +830,7 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) if (RenderUIBuffer) { - if (!mRT->uiScreen.allocate(resX,resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_TEXTURE, FALSE)) + if (!mRT->uiScreen.allocate(resX,resY, GL_RGBA)) { return false; } @@ -845,18 +840,18 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) bool ssao = RenderDeferredSSAO; //allocate deferred rendering color buffers - if (!mRT->deferredScreen.allocate(resX, resY, GL_RGBA, true, true, LLTexUnit::TT_TEXTURE, false, samples)) return false; + if (!mRT->deferredScreen.allocate(resX, resY, GL_RGBA, true)) return false; if (!addDeferredAttachments(mRT->deferredScreen)) return false; GLuint screenFormat = GL_RGBA16; - if (!mRT->screen.allocate(resX, resY, screenFormat, FALSE, true, LLTexUnit::TT_TEXTURE, FALSE, samples)) return false; + if (!mRT->screen.allocate(resX, resY, screenFormat)) return false; mRT->deferredScreen.shareDepthBuffer(mRT->screen); if (samples > 0) { - if (!mRT->fxaaBuffer.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_TEXTURE, FALSE, samples)) return false; + if (!mRT->fxaaBuffer.allocate(resX, resY, GL_RGBA)) return false; } else { @@ -865,7 +860,7 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) if (shadow_detail > 0 || ssao || RenderDepthOfField || samples > 0) { //only need mRT->deferredLight for shadows OR ssao OR dof OR fxaa - if (!mRT->deferredLight.allocate(resX, resY, GL_RGBA16, FALSE, FALSE, LLTexUnit::TT_TEXTURE, FALSE)) return false; + if (!mRT->deferredLight.allocate(resX, resY, GL_RGBA16)) return false; } else { @@ -874,6 +869,11 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) allocateShadowBuffer(resX, resY); + if (!gCubeSnapshot && RenderScreenSpaceReflections) // hack to not allocate mSceneMap for cube snapshots + { + mSceneMap.allocate(resX, resY, GL_RGB, true); + } + //HACK make screenbuffer allocations start failing after 30 seconds if (gSavedSettings.getBOOL("SimulateFBOFailure")) { @@ -903,7 +903,7 @@ bool LLPipeline::allocateShadowBuffer(U32 resX, U32 resY) { //allocate 4 sun shadow maps for (U32 i = 0; i < 4; i++) { - if (!mRT->shadow[i].allocate(sun_shadow_map_width, sun_shadow_map_height, 0, true, true, LLTexUnit::TT_TEXTURE)) + if (!mRT->shadow[i].allocate(sun_shadow_map_width, sun_shadow_map_height, 0, true)) { return false; } @@ -928,7 +928,7 @@ bool LLPipeline::allocateShadowBuffer(U32 resX, U32 resY) U32 spot_shadow_map_height = height; for (U32 i = 0; i < 2; i++) { - if (!mSpotShadow[i].allocate(spot_shadow_map_width, spot_shadow_map_height, 0, true, true)) + if (!mSpotShadow[i].allocate(spot_shadow_map_width, spot_shadow_map_height, 0, true)) { return false; } @@ -1112,6 +1112,8 @@ void LLPipeline::releaseGLBuffers() mWaterDis.release(); mBake.release(); + mSceneMap.release(); + for (U32 i = 0; i < 3; i++) { mGlow[i].release(); @@ -1185,11 +1187,11 @@ void LLPipeline::createGLBuffers() if (LLPipeline::sRenderTransparentWater) { //water reflection texture U32 res = (U32) llmax(gSavedSettings.getS32("RenderWaterRefResolution"), 512); - mWaterDis.allocate(res,res,GL_RGBA,true,true,LLTexUnit::TT_TEXTURE); + mWaterDis.allocate(res,res,GL_RGBA,true); } // Use FBO for bake tex - mBake.allocate(512, 512, GL_RGBA, TRUE, FALSE, LLTexUnit::TT_TEXTURE, true); // SL-12781 Build > Upload > Model; 3D Preview + mBake.allocate(512, 512, GL_RGBA, true); // SL-12781 Build > Upload > Model; 3D Preview stop_glerror(); @@ -1200,7 +1202,7 @@ void LLPipeline::createGLBuffers() const U32 glow_res = llmax(1, llmin(512, 1 << gSavedSettings.getS32("RenderGlowResolutionPow"))); for (U32 i = 0; i < 3; i++) { - mGlow[i].allocate(512, glow_res, GL_RGBA, FALSE, FALSE); + mGlow[i].allocate(512, glow_res, GL_RGBA); } allocateScreenBuffer(resX, resY); @@ -1306,7 +1308,7 @@ void LLPipeline::createLUTBuffers() delete [] ls; } - mPbrBrdfLut.allocate(512, 512, GL_RG16F, false, false); + mPbrBrdfLut.allocate(512, 512, GL_RG16F); mPbrBrdfLut.bindTarget(); gDeferredGenBrdfLutProgram.bind(); @@ -4019,6 +4021,26 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera, bool do_occlusion) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); } + if (&camera == LLViewerCamera::getInstance()) + { // a bit hacky, this is the start of the main render frame, figure out delta between last modelview matrix and + // current modelview matrix + glh::matrix4f last_modelview(gGLLastModelView); + glh::matrix4f cur_modelview(gGLModelView); + + // goal is to have a matrix here that goes from the last frame's camera space to the current frame's camera space + glh::matrix4f m = last_modelview.inverse(); // last camera space to world space + m.mult_left(cur_modelview); // world space to camera space + + glh::matrix4f n = m.inverse(); + + for (U32 i = 0; i < 16; ++i) + { + gGLDeltaModelView[i] = m.m[i]; + gGLInverseDeltaModelView[i] = n.m[i]; + } + + } + bool occlude = LLPipeline::sUseOcclusion > 1 && do_occlusion; setupHWLights(nullptr); @@ -7529,10 +7551,11 @@ void LLPipeline::renderFinalize() if (!gCubeSnapshot) { - screenTarget()->bindTarget(); + LLRenderTarget* screen_target = screenTarget(); - if (RenderScreenSpaceReflections) + if (RenderScreenSpaceReflections && !gCubeSnapshot) { +#if 0 LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("renderDeferredLighting - screen space reflections"); LL_PROFILE_GPU_ZONE("screen space reflections"); @@ -7565,8 +7588,33 @@ void LLPipeline::renderFinalize() } unbindDeferredShader(gPostScreenSpaceReflectionProgram); +#else + LL_PROFILE_GPU_ZONE("ssr copy"); + LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS); + + LLRenderTarget& src = *screen_target; + LLRenderTarget& depth_src = mRT->deferredScreen; + LLRenderTarget& dst = mSceneMap; + + dst.bindTarget(); + dst.clear(); + gCopyDepthProgram.bind(); + + S32 diff_map = gCopyDepthProgram.getTextureChannel(LLShaderMgr::DIFFUSE_MAP); + S32 depth_map = gCopyDepthProgram.getTextureChannel(LLShaderMgr::DEFERRED_DEPTH); + + gGL.getTexUnit(diff_map)->bind(&src); + gGL.getTexUnit(depth_map)->bind(&depth_src, true); + + mScreenTriangleVB->setBuffer(); + mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + + dst.flush(); +#endif } + screenTarget()->bindTarget(); + // gamma correct lighting { LL_PROFILE_GPU_ZONE("gamma correct"); @@ -7821,56 +7869,6 @@ void LLPipeline::bindDeferredShaderFast(LLGLSLShader& shader) bindLightFunc(shader); bindShadowMaps(shader); bindReflectionProbes(shader); - -#if 0 - shader.uniform1f(LLShaderMgr::DEFERRED_SUN_WASH, RenderDeferredSunWash); - shader.uniform1f(LLShaderMgr::DEFERRED_SHADOW_NOISE, RenderShadowNoise); - shader.uniform1f(LLShaderMgr::DEFERRED_BLUR_SIZE, RenderShadowBlurSize); - - shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_RADIUS, RenderSSAOScale); - shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_MAX_RADIUS, RenderSSAOMaxScale); - - F32 ssao_factor = RenderSSAOFactor; - shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_FACTOR, ssao_factor); - shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_FACTOR_INV, 1.0 / ssao_factor); - - LLVector3 ssao_effect = RenderSSAOEffect; - F32 matrix_diag = (ssao_effect[0] + 2.0 * ssao_effect[1]) / 3.0; - F32 matrix_nondiag = (ssao_effect[0] - ssao_effect[1]) / 3.0; - // This matrix scales (proj of color onto <1/rt(3),1/rt(3),1/rt(3)>) by - // value factor, and scales remainder by saturation factor - F32 ssao_effect_mat[] = { matrix_diag, matrix_nondiag, matrix_nondiag, - matrix_nondiag, matrix_diag, matrix_nondiag, - matrix_nondiag, matrix_nondiag, matrix_diag }; - shader.uniformMatrix3fv(LLShaderMgr::DEFERRED_SSAO_EFFECT_MAT, 1, GL_FALSE, ssao_effect_mat); - - //F32 shadow_offset_error = 1.f + RenderShadowOffsetError * fabsf(LLViewerCamera::getInstance()->getOrigin().mV[2]); - F32 shadow_bias_error = RenderShadowBiasError * fabsf(LLViewerCamera::getInstance()->getOrigin().mV[2]) / 3000.f; - F32 shadow_bias = RenderShadowBias + shadow_bias_error; - - //shader.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, deferred_target->getWidth(), deferred_target->getHeight()); - shader.uniform1f(LLShaderMgr::DEFERRED_NEAR_CLIP, LLViewerCamera::getInstance()->getNear() * 2.f); - shader.uniform1f(LLShaderMgr::DEFERRED_SHADOW_OFFSET, RenderShadowOffset); //*shadow_offset_error); - shader.uniform1f(LLShaderMgr::DEFERRED_SHADOW_BIAS, shadow_bias); - shader.uniform1f(LLShaderMgr::DEFERRED_SPOT_SHADOW_OFFSET, RenderSpotShadowOffset); - shader.uniform1f(LLShaderMgr::DEFERRED_SPOT_SHADOW_BIAS, RenderSpotShadowBias); - - shader.uniform3fv(LLShaderMgr::DEFERRED_SUN_DIR, 1, mTransformedSunDir.mV); - shader.uniform3fv(LLShaderMgr::DEFERRED_MOON_DIR, 1, mTransformedMoonDir.mV); - shader.uniform2f(LLShaderMgr::DEFERRED_SHADOW_RES, mRT->shadow[0].getWidth(), mRT->shadow[0].getHeight()); - shader.uniform2f(LLShaderMgr::DEFERRED_PROJ_SHADOW_RES, mSpotShadow[0].getWidth(), mSpotShadow[0].getHeight()); - shader.uniform1f(LLShaderMgr::DEFERRED_DEPTH_CUTOFF, RenderEdgeDepthCutoff); - shader.uniform1f(LLShaderMgr::DEFERRED_NORM_CUTOFF, RenderEdgeNormCutoff); - - if (shader.getUniformLocation(LLShaderMgr::DEFERRED_NORM_MATRIX) >= 0) - { - glh::matrix4f norm_mat = get_current_modelview().inverse().transpose(); - shader.uniformMatrix4fv(LLShaderMgr::DEFERRED_NORM_MATRIX, 1, FALSE, norm_mat.m); - } - - shader.uniform3fv(LLShaderMgr::SUNLIGHT_COLOR, 1, mSunDiffuse.mV); - shader.uniform3fv(LLShaderMgr::MOONLIGHT_COLOR, 1, mMoonDiffuse.mV); -#endif } void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_target) @@ -7910,21 +7908,24 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_ gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); } -#if 0 - channel = shader.enableTexture(LLShaderMgr::DEFERRED_DEPTH, deferred_depth_target->getUsage()); - if (channel > -1) - { - gGL.getTexUnit(channel)->bind(deferred_depth_target, TRUE); - stop_glerror(); - } -#else channel = shader.enableTexture(LLShaderMgr::DEFERRED_DEPTH, deferred_target->getUsage()); if (channel > -1) { gGL.getTexUnit(channel)->bind(deferred_target, TRUE); stop_glerror(); } -#endif + + channel = shader.enableTexture(LLShaderMgr::SCENE_MAP); + if (channel > -1) + { + gGL.getTexUnit(channel)->bind(&mSceneMap); + } + + channel = shader.enableTexture(LLShaderMgr::SCENE_DEPTH); + if (channel > -1) + { + gGL.getTexUnit(channel)->bind(&mSceneMap, true); + } if (shader.getUniformLocation(LLShaderMgr::VIEWPORT) != -1) { @@ -8090,6 +8091,11 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_ shader.uniform1f(LLShaderMgr::DEFERRED_DEPTH_CUTOFF, RenderEdgeDepthCutoff); shader.uniform1f(LLShaderMgr::DEFERRED_NORM_CUTOFF, RenderEdgeNormCutoff); + shader.uniformMatrix4fv(LLShaderMgr::MODELVIEW_DELTA_MATRIX, 1, GL_FALSE, gGLDeltaModelView); + shader.uniformMatrix4fv(LLShaderMgr::INVERSE_MODELVIEW_DELTA_MATRIX, 1, GL_FALSE, gGLInverseDeltaModelView); + + shader.uniform1i(LLShaderMgr::CUBE_SNAPSHOT, gCubeSnapshot ? 1 : 0); + if (shader.getUniformLocation(LLShaderMgr::DEFERRED_NORM_MATRIX) >= 0) { glh::matrix4f norm_mat = get_current_modelview().inverse().transpose(); @@ -8584,6 +8590,16 @@ void LLPipeline::renderDeferredLighting() screen_target->flush(); + if (!gCubeSnapshot) + { + // this is the end of the 3D scene render, grab a copy of the modelview and projection + // matrix for use in off-by-one-frame effects in the next frame + for (U32 i = 0; i < 16; i++) + { + gGLLastModelView[i] = gGLModelView[i]; + gGLLastProjection[i] = gGLProjection[i]; + } + } gGL.setColorMask(true, true); } @@ -10398,7 +10414,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar, bool preview_avatar) if (!avatar->mImpostor.isComplete()) { - avatar->mImpostor.allocate(resX, resY, GL_RGBA, TRUE, FALSE); + avatar->mImpostor.allocate(resX, resY, GL_RGBA, true); if (LLPipeline::sRenderDeferred) { diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index d87387e4c3..0c11c7ef89 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -685,6 +685,10 @@ public: LLRenderTarget mPbrBrdfLut; + // copy of the color/depth buffer just before gamma correction + // for use by SSR + LLRenderTarget mSceneMap; + LLCullResult mSky; LLCullResult mReflectedObjects; LLCullResult mRefractedObjects; From 12afbacd83f07f5df11e15996b8f6357fb49b9b2 Mon Sep 17 00:00:00 2001 From: Brad Linden Date: Mon, 30 Jan 2023 10:09:04 -0800 Subject: [PATCH 24/31] Fix DRTVWR-559 EOL at EOF to pass coding policy checks --- .../shaders/class1/deferred/screenSpaceReflUtil.glsl | 2 +- .../shaders/class3/deferred/screenSpaceReflUtil.glsl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/indra/newview/app_settings/shaders/class1/deferred/screenSpaceReflUtil.glsl b/indra/newview/app_settings/shaders/class1/deferred/screenSpaceReflUtil.glsl index b3da216b81..d054305767 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/screenSpaceReflUtil.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/screenSpaceReflUtil.glsl @@ -34,4 +34,4 @@ float tapScreenSpaceReflection(int totalSamples, vec2 tc, vec3 viewPos, vec3 n, { collectedColor = vec4(0); return 0; -} \ No newline at end of file +} diff --git a/indra/newview/app_settings/shaders/class3/deferred/screenSpaceReflUtil.glsl b/indra/newview/app_settings/shaders/class3/deferred/screenSpaceReflUtil.glsl index 570235a816..c355b671c0 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/screenSpaceReflUtil.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/screenSpaceReflUtil.glsl @@ -231,4 +231,4 @@ float tapScreenSpaceReflection(int totalSamples, vec2 tc, vec3 viewPos, vec3 n, } return min(float(hits), 1.0) * vignette; -} \ No newline at end of file +} From 10b8dcc497599042655dcc4037c9ae98d494bd6f Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Mon, 30 Jan 2023 18:56:19 -0600 Subject: [PATCH 25/31] SL-19015 Bump probe resolution back to 256 by default (drop to 128 if vram < 2GB), remove irradiance map feedback loop (one bounce, but but more stable and allows for much brighter first bounce), make sky contribution to irradiance not tint the world blue. Make irradiance that appears in radiance maps match world irradiance. --- indra/llrender/llshadermgr.cpp | 1 + indra/llrender/llshadermgr.h | 1 + indra/newview/app_settings/settings.xml | 11 + .../class1/interface/irradianceGenF.glsl | 198 +-------------- .../class1/interface/radianceGenF.glsl | 4 +- .../class2/interface/irradianceGenF.glsl | 231 ++++++++++++++++++ .../class2/windlight/atmosphericsFuncs.glsl | 80 ------ .../class3/deferred/reflectionProbeF.glsl | 7 +- indra/newview/featuretable.txt | 9 +- indra/newview/llenvironment.cpp | 53 ++-- indra/newview/llfeaturemanager.cpp | 4 + indra/newview/llreflectionmapmanager.cpp | 185 ++++++++------ indra/newview/llreflectionmapmanager.h | 16 +- indra/newview/llsettingsvo.cpp | 31 ++- indra/newview/llviewerdisplay.cpp | 6 + indra/newview/pipeline.cpp | 13 +- 16 files changed, 463 insertions(+), 387 deletions(-) create mode 100644 indra/newview/app_settings/shaders/class2/interface/irradianceGenF.glsl diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 27ac4053df..421b9ee2d6 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -1431,6 +1431,7 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("moon_brightness"); mReservedUniforms.push_back("cloud_variance"); mReservedUniforms.push_back("reflection_probe_ambiance"); + mReservedUniforms.push_back("max_probe_lod"); mReservedUniforms.push_back("sh_input_r"); mReservedUniforms.push_back("sh_input_g"); diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index 86ada6c132..a224b2a19b 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -267,6 +267,7 @@ public: CLOUD_VARIANCE, // "cloud_variance" REFLECTION_PROBE_AMBIANCE, // "reflection_probe_ambiance" + REFLECTION_PROBE_MAX_LOD, // "max_probe_lod" SH_INPUT_L1R, // "sh_input_r" SH_INPUT_L1G, // "sh_input_g" SH_INPUT_L1B, // "sh_input_b" diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index d262a1285f..41afca50f6 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10382,6 +10382,17 @@ Value 256 + RenderReflectionProbeResolution + + Comment + Resolution of reflection probe radiance maps (requires restart). Will be set to the next highest power of two clamped to [64, 512]. Note that changing this value may consume a massive amount of video memory. + Persist + 1 + Type + U32 + Value + 256 + RenderReflectionProbeDrawDistance diff --git a/indra/newview/app_settings/shaders/class1/interface/irradianceGenF.glsl b/indra/newview/app_settings/shaders/class1/interface/irradianceGenF.glsl index 3e056aa048..2b1e794b52 100644 --- a/indra/newview/app_settings/shaders/class1/interface/irradianceGenF.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/irradianceGenF.glsl @@ -23,205 +23,11 @@ * $/LicenseInfo$ */ +// debug stub -/*[EXTRA_CODE_HERE]*/ - - -#ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_color; -#else -#define frag_color gl_FragColor -#endif -uniform samplerCubeArray reflectionProbes; -uniform int sourceIdx; - -VARYING vec3 vary_dir; - - -// Code below is derived from the Khronos GLTF Sample viewer: -// https://github.com/KhronosGroup/glTF-Sample-Viewer/blob/master/source/shaders/ibl_filtering.frag - - -#define MATH_PI 3.1415926535897932384626433832795 - -float u_roughness = 1.0; -int u_sampleCount = 16; -float u_lodBias = 2.0; -int u_width = 64; - -// Hammersley Points on the Hemisphere -// CC BY 3.0 (Holger Dammertz) -// http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html -// with adapted interface -float radicalInverse_VdC(uint bits) -{ - bits = (bits << 16u) | (bits >> 16u); - bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); - bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); - bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); - bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); - return float(bits) * 2.3283064365386963e-10; // / 0x100000000 -} - -// hammersley2d describes a sequence of points in the 2d unit square [0,1)^2 -// that can be used for quasi Monte Carlo integration -vec2 hammersley2d(int i, int N) { - return vec2(float(i)/float(N), radicalInverse_VdC(uint(i))); -} - -// Hemisphere Sample - -// TBN generates a tangent bitangent normal coordinate frame from the normal -// (the normal must be normalized) -mat3 generateTBN(vec3 normal) -{ - vec3 bitangent = vec3(0.0, 1.0, 0.0); - - float NdotUp = dot(normal, vec3(0.0, 1.0, 0.0)); - float epsilon = 0.0000001; - /*if (1.0 - abs(NdotUp) <= epsilon) - { - // Sampling +Y or -Y, so we need a more robust bitangent. - if (NdotUp > 0.0) - { - bitangent = vec3(0.0, 0.0, 1.0); - } - else - { - bitangent = vec3(0.0, 0.0, -1.0); - } - }*/ - - vec3 tangent = normalize(cross(bitangent, normal)); - bitangent = cross(normal, tangent); - - return mat3(tangent, bitangent, normal); -} - -struct MicrofacetDistributionSample -{ - float pdf; - float cosTheta; - float sinTheta; - float phi; -}; - -MicrofacetDistributionSample Lambertian(vec2 xi, float roughness) -{ - MicrofacetDistributionSample lambertian; - - // Cosine weighted hemisphere sampling - // http://www.pbr-book.org/3ed-2018/Monte_Carlo_Integration/2D_Sampling_with_Multidimensional_Transformations.html#Cosine-WeightedHemisphereSampling - lambertian.cosTheta = sqrt(1.0 - xi.y); - lambertian.sinTheta = sqrt(xi.y); // equivalent to `sqrt(1.0 - cosTheta*cosTheta)`; - lambertian.phi = 2.0 * MATH_PI * xi.x; - - lambertian.pdf = lambertian.cosTheta / MATH_PI; // evaluation for solid angle, therefore drop the sinTheta - - return lambertian; -} - - -// getImportanceSample returns an importance sample direction with pdf in the .w component -vec4 getImportanceSample(int sampleIndex, vec3 N, float roughness) -{ - // generate a quasi monte carlo point in the unit square [0.1)^2 - vec2 xi = hammersley2d(sampleIndex, u_sampleCount); - - MicrofacetDistributionSample importanceSample; - - // generate the points on the hemisphere with a fitting mapping for - // the distribution (e.g. lambertian uses a cosine importance) - importanceSample = Lambertian(xi, roughness); - - // transform the hemisphere sample to the normal coordinate frame - // i.e. rotate the hemisphere to the normal direction - vec3 localSpaceDirection = normalize(vec3( - importanceSample.sinTheta * cos(importanceSample.phi), - importanceSample.sinTheta * sin(importanceSample.phi), - importanceSample.cosTheta - )); - mat3 TBN = generateTBN(N); - vec3 direction = TBN * localSpaceDirection; - - return vec4(direction, importanceSample.pdf); -} - -// Mipmap Filtered Samples (GPU Gems 3, 20.4) -// https://developer.nvidia.com/gpugems/gpugems3/part-iii-rendering/chapter-20-gpu-based-importance-sampling -// https://cgg.mff.cuni.cz/~jaroslav/papers/2007-sketch-fis/Final_sap_0073.pdf -float computeLod(float pdf) -{ - // // Solid angle of current sample -- bigger for less likely samples - // float omegaS = 1.0 / (float(u_sampleCount) * pdf); - // // Solid angle of texel - // // note: the factor of 4.0 * MATH_PI - // float omegaP = 4.0 * MATH_PI / (6.0 * float(u_width) * float(u_width)); - // // Mip level is determined by the ratio of our sample's solid angle to a texel's solid angle - // // note that 0.5 * log2 is equivalent to log4 - // float lod = 0.5 * log2(omegaS / omegaP); - - // babylon introduces a factor of K (=4) to the solid angle ratio - // this helps to avoid undersampling the environment map - // this does not appear in the original formulation by Jaroslav Krivanek and Mark Colbert - // log4(4) == 1 - // lod += 1.0; - - // We achieved good results by using the original formulation from Krivanek & Colbert adapted to cubemaps - - // https://cgg.mff.cuni.cz/~jaroslav/papers/2007-sketch-fis/Final_sap_0073.pdf - float lod = 0.5 * log2( 6.0 * float(u_width) * float(u_width) / (float(u_sampleCount) * pdf)); - - - return lod; -} - -vec4 filterColor(vec3 N) -{ - //return textureLod(uCubeMap, N, 3.0).rgb; - vec4 color = vec4(0.f); - float weight = 0.0f; - - for(int i = 0; i < u_sampleCount; ++i) - { - vec4 importanceSample = getImportanceSample(i, N, 1.0); - - vec3 H = vec3(importanceSample.xyz); - float pdf = importanceSample.w; - - // mipmap filtered samples (GPU Gems 3, 20.4) - float lod = computeLod(pdf); - - // apply the bias to the lod - lod += u_lodBias; - - lod = clamp(lod, 0, 6); - // sample lambertian at a lower resolution to avoid fireflies - vec4 lambertian = textureLod(reflectionProbes, vec4(H, sourceIdx), lod); - - color += lambertian; - } - - if(weight != 0.0f) - { - color /= weight; - } - else - { - color /= float(u_sampleCount); - } - - return min(color*1.9, vec4(1)); -} - -// entry point void main() { - vec4 color = vec4(0); - - color = filterColor(vary_dir); - - frag_color = color; + frag_color = vec4(0.5, 0, 0.5, 0); } - diff --git a/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl b/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl index 858052281b..e60ddcd569 100644 --- a/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl @@ -37,6 +37,8 @@ VARYING vec3 vary_dir; uniform float mipLevel; uniform int u_width; +uniform float max_probe_lod; + // ============================================================================================================= // Parts of this file are (c) 2018 Sascha Willems @@ -128,7 +130,7 @@ vec4 prefilterEnvMap(vec3 R) float envMapDim = u_width; int numSamples = 4; - float numMips = 6.0; + float numMips = max_probe_lod; float roughness = mipLevel/numMips; diff --git a/indra/newview/app_settings/shaders/class2/interface/irradianceGenF.glsl b/indra/newview/app_settings/shaders/class2/interface/irradianceGenF.glsl new file mode 100644 index 0000000000..a4aec48c59 --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/interface/irradianceGenF.glsl @@ -0,0 +1,231 @@ +/** + * @file irradianceGenF.glsl + * + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2022, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + + +/*[EXTRA_CODE_HERE]*/ + + +#ifdef DEFINE_GL_FRAGCOLOR +out vec4 frag_color; +#else +#define frag_color gl_FragColor +#endif + +uniform samplerCubeArray reflectionProbes; +uniform int sourceIdx; + +uniform float max_probe_lod; + +VARYING vec3 vary_dir; + + +// Code below is derived from the Khronos GLTF Sample viewer: +// https://github.com/KhronosGroup/glTF-Sample-Viewer/blob/master/source/shaders/ibl_filtering.frag + + +#define MATH_PI 3.1415926535897932384626433832795 + +float u_roughness = 1.0; +int u_sampleCount = 64; +float u_lodBias = 2.0; +int u_width = 64; + +// Hammersley Points on the Hemisphere +// CC BY 3.0 (Holger Dammertz) +// http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html +// with adapted interface +float radicalInverse_VdC(uint bits) +{ + bits = (bits << 16u) | (bits >> 16u); + bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); + bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); + bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); + bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); + return float(bits) * 2.3283064365386963e-10; // / 0x100000000 +} + +// hammersley2d describes a sequence of points in the 2d unit square [0,1)^2 +// that can be used for quasi Monte Carlo integration +vec2 hammersley2d(int i, int N) { + return vec2(float(i)/float(N), radicalInverse_VdC(uint(i))); +} + +// Hemisphere Sample + +// TBN generates a tangent bitangent normal coordinate frame from the normal +// (the normal must be normalized) +mat3 generateTBN(vec3 normal) +{ + vec3 bitangent = vec3(0.0, 1.0, 0.0); + + float NdotUp = dot(normal, vec3(0.0, 1.0, 0.0)); + float epsilon = 0.0000001; + /*if (1.0 - abs(NdotUp) <= epsilon) + { + // Sampling +Y or -Y, so we need a more robust bitangent. + if (NdotUp > 0.0) + { + bitangent = vec3(0.0, 0.0, 1.0); + } + else + { + bitangent = vec3(0.0, 0.0, -1.0); + } + }*/ + + vec3 tangent = normalize(cross(bitangent, normal)); + bitangent = cross(normal, tangent); + + return mat3(tangent, bitangent, normal); +} + +struct MicrofacetDistributionSample +{ + float pdf; + float cosTheta; + float sinTheta; + float phi; +}; + +MicrofacetDistributionSample Lambertian(vec2 xi, float roughness) +{ + MicrofacetDistributionSample lambertian; + + // Cosine weighted hemisphere sampling + // http://www.pbr-book.org/3ed-2018/Monte_Carlo_Integration/2D_Sampling_with_Multidimensional_Transformations.html#Cosine-WeightedHemisphereSampling + lambertian.cosTheta = sqrt(1.0 - xi.y); + lambertian.sinTheta = sqrt(xi.y); // equivalent to `sqrt(1.0 - cosTheta*cosTheta)`; + lambertian.phi = 2.0 * MATH_PI * xi.x; + + lambertian.pdf = lambertian.cosTheta / MATH_PI; // evaluation for solid angle, therefore drop the sinTheta + + return lambertian; +} + + +// getImportanceSample returns an importance sample direction with pdf in the .w component +vec4 getImportanceSample(int sampleIndex, vec3 N, float roughness) +{ + // generate a quasi monte carlo point in the unit square [0.1)^2 + vec2 xi = hammersley2d(sampleIndex, u_sampleCount); + + MicrofacetDistributionSample importanceSample; + + // generate the points on the hemisphere with a fitting mapping for + // the distribution (e.g. lambertian uses a cosine importance) + importanceSample = Lambertian(xi, roughness); + + // transform the hemisphere sample to the normal coordinate frame + // i.e. rotate the hemisphere to the normal direction + vec3 localSpaceDirection = normalize(vec3( + importanceSample.sinTheta * cos(importanceSample.phi), + importanceSample.sinTheta * sin(importanceSample.phi), + importanceSample.cosTheta + )); + mat3 TBN = generateTBN(N); + vec3 direction = TBN * localSpaceDirection; + + return vec4(direction, importanceSample.pdf); +} + +// Mipmap Filtered Samples (GPU Gems 3, 20.4) +// https://developer.nvidia.com/gpugems/gpugems3/part-iii-rendering/chapter-20-gpu-based-importance-sampling +// https://cgg.mff.cuni.cz/~jaroslav/papers/2007-sketch-fis/Final_sap_0073.pdf +float computeLod(float pdf) +{ + // // Solid angle of current sample -- bigger for less likely samples + // float omegaS = 1.0 / (float(u_sampleCount) * pdf); + // // Solid angle of texel + // // note: the factor of 4.0 * MATH_PI + // float omegaP = 4.0 * MATH_PI / (6.0 * float(u_width) * float(u_width)); + // // Mip level is determined by the ratio of our sample's solid angle to a texel's solid angle + // // note that 0.5 * log2 is equivalent to log4 + // float lod = 0.5 * log2(omegaS / omegaP); + + // babylon introduces a factor of K (=4) to the solid angle ratio + // this helps to avoid undersampling the environment map + // this does not appear in the original formulation by Jaroslav Krivanek and Mark Colbert + // log4(4) == 1 + // lod += 1.0; + + // We achieved good results by using the original formulation from Krivanek & Colbert adapted to cubemaps + + // https://cgg.mff.cuni.cz/~jaroslav/papers/2007-sketch-fis/Final_sap_0073.pdf + float lod = 0.5 * log2( 6.0 * float(u_width) * float(u_width) / (float(u_sampleCount) * pdf)); + + + return lod; +} + +vec4 filterColor(vec3 N) +{ + //return textureLod(uCubeMap, N, 3.0).rgb; + vec4 color = vec4(0.f); + float weight = 0.0f; + + for(int i = 0; i < u_sampleCount; ++i) + { + vec4 importanceSample = getImportanceSample(i, N, 1.0); + + vec3 H = vec3(importanceSample.xyz); + float pdf = importanceSample.w; + + // mipmap filtered samples (GPU Gems 3, 20.4) + float lod = computeLod(pdf); + + // apply the bias to the lod + lod += u_lodBias; + + lod = clamp(lod, 0, max_probe_lod); + // sample lambertian at a lower resolution to avoid fireflies + vec4 lambertian = textureLod(reflectionProbes, vec4(H, sourceIdx), lod); + + color += lambertian; + } + + if(weight != 0.0f) + { + color /= weight; + } + else + { + color /= float(u_sampleCount); + } + + color = min(color*1.9, vec4(1)); + color = pow(color, vec4(0.5)); + return color; +} + +// entry point +void main() +{ + vec4 color = vec4(0); + + color = filterColor(vary_dir); + + frag_color = color; +} + diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsFuncs.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsFuncs.glsl index c69eba93b6..ba02070e45 100644 --- a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsFuncs.glsl +++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsFuncs.glsl @@ -162,90 +162,10 @@ float ambientLighting(vec3 norm, vec3 light_dir) void calcAtmosphericVarsLinear(vec3 inPositionEye, vec3 norm, vec3 light_dir, out vec3 sunlit, out vec3 amblit, out vec3 additive, out vec3 atten) { -#if 1 calcAtmosphericVars(inPositionEye, light_dir, 1.0, sunlit, amblit, additive, atten, false); sunlit = srgb_to_linear(sunlit); additive = srgb_to_linear(additive); amblit = ambient_linear; amblit *= ambientLighting(norm, light_dir); -#else - - //EXPERIMENTAL -- attempt to factor out srgb_to_linear conversions above - vec3 rel_pos = inPositionEye; - - //(TERRAIN) limit altitude - if (abs(rel_pos.y) > max_y) rel_pos *= (max_y / rel_pos.y); - - vec3 rel_pos_norm = normalize(rel_pos); - float rel_pos_len = length(rel_pos); - vec3 sunlight = (sun_up_factor == 1) ? vec3(sunlight_linear, 0.0) : vec3(moonlight_linear, 0.0); - - // sunlight attenuation effect (hue and brightness) due to atmosphere - // this is used later for sunlight modulation at various altitudes - vec3 light_atten = (blue_density + vec3(haze_density * 0.25)) * (density_multiplier * max_y); - // I had thought blue_density and haze_density should have equal weighting, - // but attenuation due to haze_density tends to seem too strong - - vec3 combined_haze = blue_density + vec3(haze_density); - vec3 blue_weight = blue_density / combined_haze; - vec3 haze_weight = vec3(haze_density) / combined_haze; - - //(TERRAIN) compute sunlight from lightnorm y component. Factor is roughly cosecant(sun elevation) (for short rays like terrain) - float above_horizon_factor = 1.0 / max(1e-6, lightnorm.y); - sunlight *= exp(-light_atten * above_horizon_factor); // for sun [horizon..overhead] this maps to an exp curve [0..1] - - // main atmospheric scattering line integral - float density_dist = rel_pos_len * density_multiplier; - - // Transparency (-> combined_haze) - // ATI Bugfix -- can't store combined_haze*density_dist*distance_multiplier in a variable because the ati - // compiler gets confused. - combined_haze = exp(-combined_haze * density_dist * distance_multiplier); - - // final atmosphere attenuation factor - atten = combined_haze.rgb; - - // compute haze glow - float haze_glow = dot(rel_pos_norm, lightnorm.xyz); - - // dampen sun additive contrib when not facing it... - // SL-13539: This "if" clause causes an "additive" white artifact at roughly 77 degreees. - // if (length(light_dir) > 0.01) - haze_glow *= max(0.0f, dot(light_dir, rel_pos_norm)); - - haze_glow = 1. - haze_glow; - // haze_glow is 0 at the sun and increases away from sun - haze_glow = max(haze_glow, .001); // set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot) - haze_glow *= glow.x; - // higher glow.x gives dimmer glow (because next step is 1 / "angle") - haze_glow = pow(haze_glow, glow.z); - // glow.z should be negative, so we're doing a sort of (1 / "angle") function - - // add "minimum anti-solar illumination" - haze_glow += .25; - - haze_glow *= sun_moon_glow_factor; - - //vec3 amb_color = vec4(ambient_linear, 0.0); - vec3 amb_color = ambient_color; - - // increase ambient when there are more clouds - vec3 tmpAmbient = amb_color + (vec3(1.) - amb_color) * cloud_shadow * 0.5; - - // Similar/Shared Algorithms: - // indra\llinventory\llsettingssky.cpp -- LLSettingsSky::calculateLightSettings() - // indra\newview\app_settings\shaders\class1\windlight\atmosphericsFuncs.glsl -- calcAtmosphericVars() - // haze color - vec3 cs = sunlight.rgb * (1. - cloud_shadow); - additive = (blue_horizon.rgb * blue_weight.rgb) * (cs + tmpAmbient.rgb) + (haze_horizon * haze_weight.rgb) * (cs * haze_glow + tmpAmbient.rgb); - - // brightness of surface both sunlight and ambient - sunlit = min(sunlight.rgb, vec3(1)); - amblit = tmpAmbient.rgb; - additive *= vec3(1.0 - combined_haze); - - //sunlit = sunlight_linear; - amblit = ambient_linear*0.8; -#endif } diff --git a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl index 9793ab13de..bb3be7260b 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl @@ -36,6 +36,7 @@ uniform samplerCubeArray reflectionProbes; uniform samplerCubeArray irradianceProbes; uniform sampler2D sceneMap; uniform int cube_snapshot; +uniform float max_probe_lod; layout (std140) uniform ReflectionProbes { @@ -623,7 +624,7 @@ vec3 sampleProbeAmbient(vec3 pos, vec3 dir) { col *= 1.0/wsum; } - + return col; } @@ -631,7 +632,7 @@ void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv, vec2 tc, vec3 pos, vec3 norm, float glossiness, bool errorCorrect) { // TODO - don't hard code lods - float reflection_lods = 6; + float reflection_lods = max_probe_lod; preProbeSample(pos); vec3 refnormpersp = reflect(pos.xyz, norm.xyz); @@ -705,7 +706,7 @@ void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec2 tc, vec3 pos, vec3 norm, float glossiness, float envIntensity) { // TODO - don't hard code lods - float reflection_lods = 7; + float reflection_lods = max_probe_lod; preProbeSample(pos); vec3 refnormpersp = reflect(pos.xyz, norm.xyz); diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt index 2821b63391..5bd74fe318 100644 --- a/indra/newview/featuretable.txt +++ b/indra/newview/featuretable.txt @@ -1,4 +1,4 @@ -version 46 +version 47 // The version number above should be incremented IF AND ONLY IF some // change has been made that is sufficiently important to justify // resetting the graphics preferences of all users to the recommended @@ -72,6 +72,7 @@ RenderFSAASamples 1 16 RenderMaxTextureIndex 1 16 RenderGLContextCoreProfile 1 1 RenderGLMultiThreaded 1 0 +RenderReflectionProbeResolution 1 256 // @@ -271,6 +272,12 @@ RenderUseAdvancedAtmospherics 1 0 list VRAMGT512 RenderCompressTextures 1 0 +// +// VRAM < 2GB +// +list VRAMLT2GB +RenderReflectionProbeResolution 1 128 + // // "Default" setups for safe, low, medium, high // diff --git a/indra/newview/llenvironment.cpp b/indra/newview/llenvironment.cpp index efe4ad2af2..6d600efe37 100644 --- a/indra/newview/llenvironment.cpp +++ b/indra/newview/llenvironment.cpp @@ -1630,28 +1630,31 @@ LLVector4 LLEnvironment::getRotatedLightNorm() const return toLightNorm(light_direction); } +extern BOOL gCubeSnapshot; + //------------------------------------------------------------------------- void LLEnvironment::update(const LLViewerCamera * cam) { LL_PROFILE_ZONE_SCOPED_CATEGORY_ENVIRONMENT; //LL_RECORD_BLOCK_TIME(FTM_ENVIRONMENT_UPDATE); //F32Seconds now(LLDate::now().secondsSinceEpoch()); - static LLFrameTimer timer; - - F32Seconds delta(timer.getElapsedTimeAndResetF32()); - + if (!gCubeSnapshot) { - DayInstance::ptr_t keeper = mCurrentEnvironment; - // make sure the current environment does not go away until applyTimeDelta is done. - mCurrentEnvironment->applyTimeDelta(delta); + static LLFrameTimer timer; + F32Seconds delta(timer.getElapsedTimeAndResetF32()); + + { + DayInstance::ptr_t keeper = mCurrentEnvironment; + // make sure the current environment does not go away until applyTimeDelta is done. + mCurrentEnvironment->applyTimeDelta(delta); + + } + // update clouds, sun, and general + updateCloudScroll(); + + // cache this for use in rotating the rotated light vec for shader param updates later... + mLastCamYaw = cam->getYaw() + SUN_DELTA_YAW; } - // update clouds, sun, and general - updateCloudScroll(); - - // cache this for use in rotating the rotated light vec for shader param updates later... - mLastCamYaw = cam->getYaw() + SUN_DELTA_YAW; - - stop_glerror(); updateSettingsUniforms(); @@ -1752,13 +1755,23 @@ void LLEnvironment::updateGLVariablesForSettings(LLShaderUniforms* uniforms, con { LLVector4 vect4(value); - switch (it.second.getShaderKey()) - { // convert to linear color space if this is a color parameter - case LLShaderMgr::BLUE_HORIZON: - case LLShaderMgr::BLUE_DENSITY: - //vect4 = LLVector4(linearColor4(LLColor4(vect4.mV)).mV); - break; + if (gCubeSnapshot && !gPipeline.mReflectionMapManager.isRadiancePass()) + { // maximize and remove tinting if this is an irradiance map render pass and the parameter feeds into the sky background color + auto max_vec = [](LLVector4 col) + { + col.mV[0] = col.mV[1] = col.mV[2] = llmax(llmax(col.mV[0], col.mV[1]), col.mV[2]); + return col; + }; + + switch (it.second.getShaderKey()) + { + case LLShaderMgr::BLUE_HORIZON: + case LLShaderMgr::BLUE_DENSITY: + vect4 = max_vec(vect4); + break; + } } + //_WARNS("RIDER") << "pushing '" << (*it).first << "' as " << vect4 << LL_ENDL; shader->uniform3fv(it.second.getShaderKey(), LLVector3(vect4.mV) ); break; diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp index 5817fdbfa0..3b1bee05af 100644 --- a/indra/newview/llfeaturemanager.cpp +++ b/indra/newview/llfeaturemanager.cpp @@ -651,6 +651,10 @@ void LLFeatureManager::applyBaseMasks() { maskFeatures("VRAMGT512"); } + if (gGLManager.mVRAM < 2048) + { + maskFeatures("VRAMLT2GB"); + } if (gGLManager.mGLVersion < 3.99f) { maskFeatures("GL3"); diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp index 128aa99ccc..ee05849130 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -39,6 +39,10 @@ extern BOOL gCubeSnapshot; extern BOOL gTeleportDisplay; +// get the next highest power of two of v (or v if v is already a power of two) +//defined in llvertexbuffer.cpp +extern U32 nhpo2(U32 v); + static void touch_default_probe(LLReflectionMap* probe) { LLVector3 origin = LLViewerCamera::getInstance()->getOrigin(); @@ -91,13 +95,13 @@ void LLReflectionMapManager::update() if (!mRenderTarget.isComplete()) { U32 color_fmt = GL_RGB16F; - U32 targetRes = LL_REFLECTION_PROBE_RESOLUTION * 2; // super sample + U32 targetRes = mProbeResolution * 2; // super sample mRenderTarget.allocate(targetRes, targetRes, color_fmt, true); } if (mMipChain.empty()) { - U32 res = LL_REFLECTION_PROBE_RESOLUTION; + U32 res = mProbeResolution; U32 count = log2((F32)res) + 0.5f; mMipChain.resize(count); @@ -401,11 +405,27 @@ void LLReflectionMapManager::doProbeUpdate() if (++mUpdatingFace == 6) { updateNeighbors(mUpdatingProbe); - mUpdatingProbe = nullptr; mUpdatingFace = 0; + if (mRadiancePass) + { + mUpdatingProbe = nullptr; + mRadiancePass = false; + } + else + { + mRadiancePass = true; + } } } +// Do the reflection map update render passes. +// For every 12 calls of this function, one complete reflection probe radiance map and irradiance map is generated +// First six passes render the scene with direct lighting only into a scratch space cube map at the end of the cube map array and generate +// a simple mip chain (not convolution filter). +// At the end of these passes, an irradiance map is generated for this probe and placed into the irradiance cube map array at the index for this probe +// The next six passes render the scene with both radiance and irradiance into the same scratch space cube map and generate a simple mip chain. +// At the end of these passes, a radiance map is generated for this probe and placed into the radiance cube map array at the index for this probe. +// In effect this simulates single-bounce lighting. void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) { // hacky hot-swap of camera specific render targets @@ -432,11 +452,11 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) gPipeline.mRT = &gPipeline.mMainRT; - S32 targetIdx = mReflectionProbeCount; + S32 sourceIdx = mReflectionProbeCount; if (probe != mUpdatingProbe) { // this is the "realtime" probe that's updating every frame, use the secondary scratch space channel - targetIdx += 1; + sourceIdx += 1; } gGL.setColorMask(true, true); @@ -457,9 +477,9 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) gGL.loadIdentity(); gGL.flush(); - U32 res = LL_REFLECTION_PROBE_RESOLUTION * 2; + U32 res = mProbeResolution * 2; - S32 mips = log2((F32)LL_REFLECTION_PROBE_RESOLUTION) + 0.5f; + S32 mips = log2((F32)mProbeResolution) + 0.5f; S32 diffuseChannel = gReflectionMipProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_TEXTURE); S32 depthChannel = gReflectionMipProgram.enableTexture(LLShaderMgr::DEFERRED_DEPTH, LLTexUnit::TT_TEXTURE); @@ -516,7 +536,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) LL_PROFILE_GPU_ZONE("probe mip copy"); mTexture->bind(0); //glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, probe->mCubeIndex * 6 + face, 0, 0, res, res); - glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, targetIdx * 6 + face, 0, 0, res, res); + glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, sourceIdx * 6 + face, 0, 0, res, res); //if (i == 0) //{ //glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, probe->mCubeIndex * 6 + face, 0, 0, res, res); @@ -537,89 +557,98 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) if (face == 5) { - //generate radiance map - gRadianceGenProgram.bind(); - mVertexBuffer->setBuffer(); - - S32 channel = gRadianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY); - mTexture->bind(channel); - static LLStaticHashedString sSourceIdx("sourceIdx"); - gRadianceGenProgram.uniform1i(sSourceIdx, targetIdx); - mMipChain[0].bindTarget(); - U32 res = mMipChain[0].getWidth(); + static LLStaticHashedString sSourceIdx("sourceIdx"); - for (int i = 0; i < mMipChain.size(); ++i) + if (mRadiancePass) { - LL_PROFILE_GPU_ZONE("probe radiance gen"); - static LLStaticHashedString sMipLevel("mipLevel"); - static LLStaticHashedString sRoughness("roughness"); - static LLStaticHashedString sWidth("u_width"); + //generate radiance map (even if this is not the irradiance map, we need the mip chain for the irradiance map) + gRadianceGenProgram.bind(); + mVertexBuffer->setBuffer(); - gRadianceGenProgram.uniform1f(sRoughness, (F32)i / (F32)(mMipChain.size() - 1)); - gRadianceGenProgram.uniform1f(sMipLevel, i); - gRadianceGenProgram.uniform1i(sWidth, mMipChain[i].getWidth()); + S32 channel = gRadianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY); + mTexture->bind(channel); + gRadianceGenProgram.uniform1i(sSourceIdx, sourceIdx); + gRadianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mMaxProbeLOD); - for (int cf = 0; cf < 6; ++cf) - { // for each cube face - LLCoordFrame frame; - frame.lookAt(LLVector3(0, 0, 0), LLCubeMapArray::sClipToCubeLookVecs[cf], LLCubeMapArray::sClipToCubeUpVecs[cf]); + U32 res = mMipChain[0].getWidth(); - F32 mat[16]; - frame.getOpenGLRotation(mat); - gGL.loadMatrix(mat); - - mVertexBuffer->drawArrays(gGL.TRIANGLE_STRIP, 0, 4); - - glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, i, 0, 0, probe->mCubeIndex * 6 + cf, 0, 0, res, res); - } - - if (i != mMipChain.size() - 1) + for (int i = 0; i < mMipChain.size(); ++i) { - res /= 2; - glViewport(0, 0, res, res); + LL_PROFILE_GPU_ZONE("probe radiance gen"); + static LLStaticHashedString sMipLevel("mipLevel"); + static LLStaticHashedString sRoughness("roughness"); + static LLStaticHashedString sWidth("u_width"); + + gRadianceGenProgram.uniform1f(sRoughness, (F32)i / (F32)(mMipChain.size() - 1)); + gRadianceGenProgram.uniform1f(sMipLevel, i); + gRadianceGenProgram.uniform1i(sWidth, mMipChain[i].getWidth()); + + for (int cf = 0; cf < 6; ++cf) + { // for each cube face + LLCoordFrame frame; + frame.lookAt(LLVector3(0, 0, 0), LLCubeMapArray::sClipToCubeLookVecs[cf], LLCubeMapArray::sClipToCubeUpVecs[cf]); + + F32 mat[16]; + frame.getOpenGLRotation(mat); + gGL.loadMatrix(mat); + + mVertexBuffer->drawArrays(gGL.TRIANGLE_STRIP, 0, 4); + + glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, i, 0, 0, probe->mCubeIndex * 6 + cf, 0, 0, res, res); + } + + if (i != mMipChain.size() - 1) + { + res /= 2; + glViewport(0, 0, res, res); + } } + + gRadianceGenProgram.unbind(); } - - gRadianceGenProgram.unbind(); - - //generate irradiance map - gIrradianceGenProgram.bind(); - channel = gIrradianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY); - mTexture->bind(channel); - - gIrradianceGenProgram.uniform1i(sSourceIdx, targetIdx); - mVertexBuffer->setBuffer(); - int start_mip = 0; - // find the mip target to start with based on irradiance map resolution - for (start_mip = 0; start_mip < mMipChain.size(); ++start_mip) + else if (!mRadiancePass) { - if (mMipChain[start_mip].getWidth() == LL_IRRADIANCE_MAP_RESOLUTION) + //generate irradiance map + gIrradianceGenProgram.bind(); + S32 channel = gIrradianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY); + mTexture->bind(channel); + + gIrradianceGenProgram.uniform1i(sSourceIdx, sourceIdx); + gIrradianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mMaxProbeLOD); + + mVertexBuffer->setBuffer(); + int start_mip = 0; + // find the mip target to start with based on irradiance map resolution + for (start_mip = 0; start_mip < mMipChain.size(); ++start_mip) { - break; + if (mMipChain[start_mip].getWidth() == LL_IRRADIANCE_MAP_RESOLUTION) + { + break; + } } - } - //for (int i = start_mip; i < mMipChain.size(); ++i) - { - int i = start_mip; - LL_PROFILE_GPU_ZONE("probe irradiance gen"); - glViewport(0, 0, mMipChain[i].getWidth(), mMipChain[i].getHeight()); - for (int cf = 0; cf < 6; ++cf) - { // for each cube face - LLCoordFrame frame; - frame.lookAt(LLVector3(0, 0, 0), LLCubeMapArray::sClipToCubeLookVecs[cf], LLCubeMapArray::sClipToCubeUpVecs[cf]); + //for (int i = start_mip; i < mMipChain.size(); ++i) + { + int i = start_mip; + LL_PROFILE_GPU_ZONE("probe irradiance gen"); + glViewport(0, 0, mMipChain[i].getWidth(), mMipChain[i].getHeight()); + for (int cf = 0; cf < 6; ++cf) + { // for each cube face + LLCoordFrame frame; + frame.lookAt(LLVector3(0, 0, 0), LLCubeMapArray::sClipToCubeLookVecs[cf], LLCubeMapArray::sClipToCubeUpVecs[cf]); - F32 mat[16]; - frame.getOpenGLRotation(mat); - gGL.loadMatrix(mat); + F32 mat[16]; + frame.getOpenGLRotation(mat); + gGL.loadMatrix(mat); - mVertexBuffer->drawArrays(gGL.TRIANGLE_STRIP, 0, 4); + mVertexBuffer->drawArrays(gGL.TRIANGLE_STRIP, 0, 4); - S32 res = mMipChain[i].getWidth(); - mIrradianceMaps->bind(channel); - glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, i - start_mip, 0, 0, probe->mCubeIndex * 6 + cf, 0, 0, res, res); - mTexture->bind(channel); + S32 res = mMipChain[i].getWidth(); + mIrradianceMaps->bind(channel); + glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, i - start_mip, 0, 0, probe->mCubeIndex * 6 + cf, 0, 0, res, res); + mTexture->bind(channel); + } } } @@ -722,7 +751,7 @@ void LLReflectionMapManager::updateUniforms() LLSettingsSky::ptr_t psky = environment.getCurrentSky(); F32 minimum_ambiance = psky->getTotalReflectionProbeAmbiance(); - F32 ambscale = gCubeSnapshot ? 0.5f : 1.f; + F32 ambscale = gCubeSnapshot && !mRadiancePass ? 0.f : 1.f; for (auto* refmap : mReflectionMaps) { @@ -912,12 +941,14 @@ void LLReflectionMapManager::initReflectionMaps() { if (mTexture.isNull()) { + mProbeResolution = nhpo2(llclamp(gSavedSettings.getU32("RenderReflectionProbeResolution"), (U32)64, (U32)512)); + mMaxProbeLOD = log2f(mProbeResolution) - 1.f; // number of mips - 1 mReflectionProbeCount = llclamp(gSavedSettings.getS32("RenderReflectionProbeCount"), 1, LL_MAX_REFLECTION_PROBE_COUNT); mTexture = new LLCubeMapArray(); // store mReflectionProbeCount+2 cube maps, final two cube maps are used for render target and radiance map generation source) - mTexture->allocate(LL_REFLECTION_PROBE_RESOLUTION, 4, mReflectionProbeCount + 2); + mTexture->allocate(mProbeResolution, 4, mReflectionProbeCount + 2); mIrradianceMaps = new LLCubeMapArray(); mIrradianceMaps->allocate(LL_IRRADIANCE_MAP_RESOLUTION, 4, mReflectionProbeCount, FALSE); diff --git a/indra/newview/llreflectionmapmanager.h b/indra/newview/llreflectionmapmanager.h index 14a6c089da..5936b26b88 100644 --- a/indra/newview/llreflectionmapmanager.h +++ b/indra/newview/llreflectionmapmanager.h @@ -38,7 +38,6 @@ class LLViewerObject; #define LL_MAX_REFLECTION_PROBE_COUNT 256 // reflection probe resolution -#define LL_REFLECTION_PROBE_RESOLUTION 128 #define LL_IRRADIANCE_MAP_RESOLUTION 64 // reflection probe mininum scale @@ -94,6 +93,9 @@ public: // call once at startup to allocate cubemap arrays void initReflectionMaps(); + // True if currently updating a radiance map, false if currently updating an irradiance map + bool isRadiancePass() { return mRadiancePass; } + private: friend class LLPipeline; @@ -161,9 +163,21 @@ private: LLReflectionMap* mUpdatingProbe = nullptr; U32 mUpdatingFace = 0; + // if true, we're generating the radiance map for the current probe, otherwise we're generating the irradiance map. + // Update sequence should be to generate the irradiance map from render of the world that has no irradiance, + // then generate the radiance map from a render of the world that includes irradiance. + // This should avoid feedback loops and ensure that the colors in the radiance maps match the colors in the environment. + bool mRadiancePass = false; + LLPointer mDefaultProbe; // default reflection probe to fall back to for pixels with no probe influences (should always be at cube index 0) // number of reflection probes to use for rendering (based on saved setting RenderReflectionProbeCount) U32 mReflectionProbeCount; + + // resolution of reflection probes + U32 mProbeResolution = 128; + + // maximum LoD of reflection probes (mip levels - 1) + F32 mMaxProbeLOD = 6.f; }; diff --git a/indra/newview/llsettingsvo.cpp b/indra/newview/llsettingsvo.cpp index 870ac6bd5a..a49bd11ffd 100644 --- a/indra/newview/llsettingsvo.cpp +++ b/indra/newview/llsettingsvo.cpp @@ -68,6 +68,8 @@ #undef VERIFY_LEGACY_CONVERSION +extern BOOL gCubeSnapshot; + //========================================================================= namespace { @@ -714,7 +716,26 @@ void LLSettingsVOSky::applySpecial(void *ptarget, bool force) LLColor3 ambient(getTotalAmbient()); shader->uniform3fv(LLShaderMgr::AMBIENT, LLVector3(ambient.mV)); - shader->uniform3fv(LLShaderMgr::AMBIENT_LINEAR, linearColor3v(getAmbientColor()/3.f)); // note magic number 3.f comes from SLIDER_SCALE_SUN_AMBIENT + + if (gCubeSnapshot && !gPipeline.mReflectionMapManager.isRadiancePass()) + { // during an irradiance map update, disable ambient lighting (direct lighting only) and desaturate sky color (avoid tinting the world blue) + shader->uniform3fv(LLShaderMgr::AMBIENT_LINEAR, LLVector3::zero.mV); + + auto max_vec = [](LLVector3 col) + { + col.mV[0] = col.mV[1] = col.mV[2] = llmax(llmax(col.mV[0], col.mV[1]), col.mV[2]); + return col; + }; + shader->uniform3fv(LLShaderMgr::BLUE_HORIZON_LINEAR, max_vec(linearColor3v(getBlueHorizon() / 2.f))); // note magic number of 2.f comes from SLIDER_SCALE_BLUE_HORIZON_DENSITY + shader->uniform3fv(LLShaderMgr::BLUE_DENSITY_LINEAR, max_vec(linearColor3v(getBlueDensity() / 2.f))); + } + else + { + shader->uniform3fv(LLShaderMgr::AMBIENT_LINEAR, linearColor3v(getAmbientColor() / 3.f)); // note magic number 3.f comes from SLIDER_SCALE_SUN_AMBIENT + shader->uniform3fv(LLShaderMgr::BLUE_HORIZON_LINEAR, linearColor3v(getBlueHorizon() / 2.f)); // note magic number of 2.f comes from SLIDER_SCALE_BLUE_HORIZON_DENSITY + shader->uniform3fv(LLShaderMgr::BLUE_DENSITY_LINEAR, linearColor3v(getBlueDensity() / 2.f)); + } + shader->uniform3fv(LLShaderMgr::SUNLIGHT_LINEAR, linearColor3v(getSunlightColor())); shader->uniform3fv(LLShaderMgr::MOONLIGHT_LINEAR,linearColor3v(getMoonlightColor())); @@ -724,16 +745,14 @@ void LLSettingsVOSky::applySpecial(void *ptarget, bool force) shader->uniform1f(LLShaderMgr::SUN_MOON_GLOW_FACTOR, getSunMoonGlowFactor()); shader->uniform1f(LLShaderMgr::DENSITY_MULTIPLIER, getDensityMultiplier()); shader->uniform1f(LLShaderMgr::DISTANCE_MULTIPLIER, getDistanceMultiplier()); - + + shader->uniform1f(LLShaderMgr::HAZE_DENSITY_LINEAR, sRGBtoLinear(getHazeDensity())); + F32 g = getGamma(); F32 display_gamma = gSavedSettings.getF32("RenderDeferredDisplayGamma"); shader->uniform1f(LLShaderMgr::GAMMA, g); shader->uniform1f(LLShaderMgr::DISPLAY_GAMMA, display_gamma); - - shader->uniform3fv(LLShaderMgr::BLUE_HORIZON_LINEAR, linearColor3v(getBlueHorizon()/2.f)); // note magic number of 2.f comes from SLIDER_SCALE_BLUE_HORIZON_DENSITY - shader->uniform3fv(LLShaderMgr::BLUE_DENSITY_LINEAR, linearColor3v(getBlueDensity()/2.f)); - shader->uniform1f(LLShaderMgr::HAZE_DENSITY_LINEAR, sRGBtoLinear(getHazeDensity())); } LLSettingsSky::parammapping_t LLSettingsVOSky::getParameterMap() const diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 497b2373da..28d6267029 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -1017,6 +1017,12 @@ void display_cube_face() display_update_camera(); + { + LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Env Update"); + // update all the sky/atmospheric/water settings + LLEnvironment::instance().update(LLViewerCamera::getInstance()); + } + LLSpatialGroup::sNoDelete = TRUE; S32 occlusion = LLPipeline::sUseOcclusion; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 64f7535f05..03ffe5da48 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -806,11 +806,12 @@ LLPipeline::eFBOStatus LLPipeline::doAllocateScreenBuffer(U32 resX, U32 resY) bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) { LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; - if (mRT == &mMainRT) + if (mRT == &mMainRT && sReflectionProbesEnabled) { // hacky -- allocate auxillary buffer gCubeSnapshot = TRUE; + mReflectionMapManager.initReflectionMaps(); mRT = &mAuxillaryRT; - U32 res = LL_REFLECTION_PROBE_RESOLUTION * 2; + U32 res = mReflectionMapManager.mProbeResolution * 2; //multiply by 2 because probes will be super sampled allocateScreenBuffer(res, res, samples); mRT = &mMainRT; gCubeSnapshot = FALSE; @@ -4172,10 +4173,16 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera) calcNearbyLights(camera); setupHWLights(NULL); + gGL.setSceneBlendType(LLRender::BT_ALPHA); gGL.setColorMask(true, false); pool_set_t::iterator iter1 = mPools.begin(); + if (gDebugGL || gDebugPipeline) + { + LLGLState::checkStates(GL_FALSE); + } + while ( iter1 != mPools.end() ) { LLDrawPool *poolp = *iter1; @@ -8104,6 +8111,8 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_ shader.uniform3fv(LLShaderMgr::SUNLIGHT_COLOR, 1, mSunDiffuse.mV); shader.uniform3fv(LLShaderMgr::MOONLIGHT_COLOR, 1, mMoonDiffuse.mV); + + shader.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mReflectionMapManager.mMaxProbeLOD); } From 473ade269628d1fb6cbc7b96a91e1c0aec1b8e59 Mon Sep 17 00:00:00 2001 From: Henri Beauchamp Date: Tue, 31 Jan 2023 17:42:51 +0100 Subject: [PATCH 26/31] SL-19110 Fast hashing classes for use in place of the slow LLMD5, where speed matters. (#64) This commit adds the HBXX64 and HBXX128 classes for use as a drop-in replacement for the slow LLMD5 hashing class, where speed matters and backward compatibility (with standard hashing algorithms) and/or cryptographic hashing qualities are not required. It also replaces LLMD5 with HBXX* in a few existing hot (well, ok, just "warm" for some) paths meeting the above requirements, while paving the way for future use cases, such as in the DRTVWR-559 and sibling branches where the slow LLMD5 is used (e.g. to hash materials and vertex buffer cache entries), and could be use such a (way) faster algorithm with very significant benefits and no negative impact. Here is the comment I added in indra/llcommon/hbxx.h: // HBXXH* classes are to be used where speed matters and cryptographic quality // is not required (no "one-way" guarantee, though they are likely not worst in // this respect than MD5 which got busted and is now considered too weak). The // xxHash code they are built upon is vectorized and about 50 times faster than // MD5. A 64 bits hash class is also provided for when 128 bits of entropy are // not needed. The hashes collision rate is similar to MD5's. // See https://github.com/Cyan4973/xxHash#readme for details. --- autobuild.xml | 30 ++ indra/cmake/CMakeLists.txt | 1 + indra/cmake/LLCommon.cmake | 1 + indra/cmake/xxHash.cmake | 8 + indra/llcommon/CMakeLists.txt | 2 + indra/llcommon/hbxxh.cpp | 377 ++++++++++++++++++ indra/llcommon/hbxxh.h | 259 ++++++++++++ indra/llcommon/lluuid.cpp | 28 +- indra/llprimitive/llmodel.cpp | 19 +- .../skins/default/xui/da/floater_about.xml | 1 + .../skins/default/xui/de/floater_about.xml | 1 + .../skins/default/xui/en/floater_about.xml | 1 + .../skins/default/xui/es/floater_about.xml | 1 + .../skins/default/xui/fr/floater_about.xml | 1 + .../skins/default/xui/it/floater_about.xml | 1 + .../skins/default/xui/ja/floater_about.xml | 1 + .../skins/default/xui/pt/floater_about.xml | 1 + .../skins/default/xui/ru/floater_about.xml | 1 + .../skins/default/xui/tr/floater_about.xml | 1 + .../skins/default/xui/zh/floater_about.xml | 1 + 20 files changed, 704 insertions(+), 32 deletions(-) create mode 100644 indra/cmake/xxHash.cmake create mode 100644 indra/llcommon/hbxxh.cpp create mode 100644 indra/llcommon/hbxxh.h diff --git a/autobuild.xml b/autobuild.xml index f749b20b5e..67c9b84af2 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -2928,6 +2928,36 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors version 0.54.1.555529 + xxhash + + copyright + Copyright 2012-2020 Yann Collet + description + xxHash Extremely fast hash algorithm + license + bsd + license_file + LICENSES/xxhash.txt + name + xxhash + platforms + + common + + archive + + hash + f54f21dda4ce25b112f0cc7b4ce38bba + url + http://sldev.free.fr/libraries/xxhash-0.8.1-20230124.tar.bz2 + + name + common + + + version + 0.8.1 + zlib-ng canonical_repo diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt index 4d70089737..fb3c7216c7 100644 --- a/indra/cmake/CMakeLists.txt +++ b/indra/cmake/CMakeLists.txt @@ -91,6 +91,7 @@ set(cmake_SOURCE_FILES VisualLeakDetector.cmake LibVLCPlugin.cmake XmlRpcEpi.cmake + xxHash.cmake ZLIBNG.cmake ) diff --git a/indra/cmake/LLCommon.cmake b/indra/cmake/LLCommon.cmake index 53871791fd..528b43c3fc 100644 --- a/indra/cmake/LLCommon.cmake +++ b/indra/cmake/LLCommon.cmake @@ -4,6 +4,7 @@ include(APR) include(Boost) include(EXPAT) include(Tracy) +include(xxHash) include(ZLIBNG) set(LLCOMMON_INCLUDE_DIRS diff --git a/indra/cmake/xxHash.cmake b/indra/cmake/xxHash.cmake new file mode 100644 index 0000000000..a7c1cba62c --- /dev/null +++ b/indra/cmake/xxHash.cmake @@ -0,0 +1,8 @@ +# -*- cmake -*- +if (XXHASH_CMAKE_INCLUDED) + return() +endif (XXHASH_CMAKE_INCLUDED) +set (XXHASH_CMAKE_INCLUDED TRUE) + +include(Prebuilt) +use_prebuilt_binary(xxhash) diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 991c3f70a1..fab7550c9a 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -119,6 +119,7 @@ set(llcommon_SOURCE_FILES lluriparser.cpp lluuid.cpp llworkerthread.cpp + hbxxh.cpp u64.cpp threadpool.cpp workqueue.cpp @@ -257,6 +258,7 @@ set(llcommon_HEADER_FILES llwin32headers.h llwin32headerslean.h llworkerthread.h + hbxxh.h lockstatic.h stdtypes.h stringize.h diff --git a/indra/llcommon/hbxxh.cpp b/indra/llcommon/hbxxh.cpp new file mode 100644 index 0000000000..e94581d415 --- /dev/null +++ b/indra/llcommon/hbxxh.cpp @@ -0,0 +1,377 @@ +/** + * @file hbxxh.cpp + * @brief High performances vectorized hashing based on xxHash. + * + * $LicenseInfo:firstyear=2023&license=viewergpl$ + * Second Life Viewer Source Code + * Copyright (c) 2023, Henri Beauchamp. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +// This define ensures that xxHash will be compiled within this module, with +// vectorized (*) and inlined functions (with no exported API symbol); our +// xxhash "pre-built library" package actually only contains the xxhash.h +// header (no library needed at link time). +// (*) SSE2 is normally used for x86(_64) builds, unless you enabled AVX2 +// in your build, in which case the latter would be used instead. For ARM64 +// builds, this would also automatically enable NEON vectorization. +#define XXH_INLINE_ALL +#include "xxhash.h" + +#include "hbxxh.h" + +// How many bytes to grab at a time when hashing files or streams +constexpr size_t BLOCK_LEN = 4096; + +/////////////////////////////////////////////////////////////////////////////// +// HBXXH64 class +/////////////////////////////////////////////////////////////////////////////// + +//static +U64 HBXXH64::digest(const void* buffer, size_t len) +{ + return XXH3_64bits(buffer, len); +} + +//static +U64 HBXXH64::digest(const char* str) +{ + return XXH3_64bits((const void*)str, strlen(str)); +} + +//static +U64 HBXXH64::digest(const std::string& str) +{ + return XXH3_64bits((const void*)str.c_str(), str.size()); +} + +// Must be called by all constructors. +void HBXXH64::init() +{ + mDigest = 0; + mState = (void*)XXH3_createState(); + if (!mState || XXH3_64bits_reset((XXH3_state_t*)mState) != XXH_OK) + { + LL_WARNS() << "Failed to initialize state !" << LL_ENDL; + } +} + +HBXXH64::~HBXXH64() +{ + if (mState) + { + XXH3_freeState((XXH3_state_t*)mState); + } +} + +void HBXXH64::update(const void* buffer, size_t len) +{ + if (mState) + { + XXH3_64bits_update((XXH3_state_t*)mState, buffer, len); + } + else + { + LL_WARNS() << "Cannot update a finalized digest !" << LL_ENDL; + } +} + +void HBXXH64::update(const std::string& str) +{ + if (mState) + { + XXH3_64bits_update((XXH3_state_t*)mState, (const void*)str.c_str(), + str.length()); + } + else + { + LL_WARNS() << "Cannot update a finalized digest !" << LL_ENDL; + } +} + +void HBXXH64::update(std::istream& stream) +{ + if (!mState) + { + LL_WARNS() << "Cannot update a finalized digest !" << LL_ENDL; + return; + } + + char buffer[BLOCK_LEN]; + size_t len; + while (stream.good()) + { + stream.read(buffer, BLOCK_LEN); + len = stream.gcount(); + XXH3_64bits_update((XXH3_state_t*)mState, (const void*)buffer, len); + } +} + +void HBXXH64::update(FILE* file) +{ + if (!mState) + { + LL_WARNS() << "Cannot update a finalized digest !" << LL_ENDL; + return; + } + + char buffer[BLOCK_LEN]; + size_t len; + while ((len = fread((void*)buffer, 1, BLOCK_LEN, file))) + { + XXH3_64bits_update((XXH3_state_t*)mState, (const void*)buffer, len); + } + fclose(file); +} + +void HBXXH64::finalize() +{ + if (!mState) + { + LL_WARNS() << "Already finalized !" << LL_ENDL; + return; + } + mDigest = XXH3_64bits_digest((XXH3_state_t*)mState); + XXH3_freeState((XXH3_state_t*)mState); + mState = NULL; +} + +U64 HBXXH64::digest() const +{ + return mState ? XXH3_64bits_digest((XXH3_state_t*)mState) : mDigest; +} + +std::ostream& operator<<(std::ostream& stream, HBXXH64 context) +{ + stream << context.digest(); + return stream; +} + +/////////////////////////////////////////////////////////////////////////////// +// HBXXH128 class +/////////////////////////////////////////////////////////////////////////////// + +//static +LLUUID HBXXH128::digest(const void* buffer, size_t len) +{ + XXH128_hash_t hash = XXH3_128bits(buffer, len); + LLUUID id; + U64* data = (U64*)id.mData; + // Note: we do not check endianness here and we just store in the same + // order as XXH128_hash_t, that is low word "first". + data[0] = hash.low64; + data[1] = hash.high64; + return id; +} + +//static +LLUUID HBXXH128::digest(const char* str) +{ + XXH128_hash_t hash = XXH3_128bits((const void*)str, strlen(str)); + LLUUID id; + U64* data = (U64*)id.mData; + // Note: we do not check endianness here and we just store in the same + // order as XXH128_hash_t, that is low word "first". + data[0] = hash.low64; + data[1] = hash.high64; + return id; +} + +//static +LLUUID HBXXH128::digest(const std::string& str) +{ + XXH128_hash_t hash = XXH3_128bits((const void*)str.c_str(), str.size()); + LLUUID id; + U64* data = (U64*)id.mData; + // Note: we do not check endianness here and we just store in the same + // order as XXH128_hash_t, that is low word "first". + data[0] = hash.low64; + data[1] = hash.high64; + return id; +} + +//static +void HBXXH128::digest(LLUUID& result, const void* buffer, size_t len) +{ + XXH128_hash_t hash = XXH3_128bits(buffer, len); + U64* data = (U64*)result.mData; + // Note: we do not check endianness here and we just store in the same + // order as XXH128_hash_t, that is low word "first". + data[0] = hash.low64; + data[1] = hash.high64; +} + +//static +void HBXXH128::digest(LLUUID& result, const char* str) +{ + XXH128_hash_t hash = XXH3_128bits((const void*)str, strlen(str)); + U64* data = (U64*)result.mData; + // Note: we do not check endianness here and we just store in the same + // order as XXH128_hash_t, that is low word "first". + data[0] = hash.low64; + data[1] = hash.high64; +} + +//static +void HBXXH128::digest(LLUUID& result, const std::string& str) +{ + XXH128_hash_t hash = XXH3_128bits((const void*)str.c_str(), str.size()); + U64* data = (U64*)result.mData; + // Note: we do not check endianness here and we just store in the same + // order as XXH128_hash_t, that is low word "first". + data[0] = hash.low64; + data[1] = hash.high64; +} + +// Must be called by all constructors. +void HBXXH128::init() +{ + mState = (void*)XXH3_createState(); + if (!mState || XXH3_128bits_reset((XXH3_state_t*)mState) != XXH_OK) + { + LL_WARNS() << "Failed to initialize state !" << LL_ENDL; + } +} + +HBXXH128::~HBXXH128() +{ + if (mState) + { + XXH3_freeState((XXH3_state_t*)mState); + } +} + +void HBXXH128::update(const void* buffer, size_t len) +{ + if (mState) + { + XXH3_128bits_update((XXH3_state_t*)mState, buffer, len); + } + else + { + LL_WARNS() << "Cannot update a finalized digest !" << LL_ENDL; + } +} + +void HBXXH128::update(const std::string& str) +{ + if (mState) + { + XXH3_128bits_update((XXH3_state_t*)mState, (const void*)str.c_str(), + str.length()); + } + else + { + LL_WARNS() << "Cannot update a finalized digest !" << LL_ENDL; + } +} + +void HBXXH128::update(std::istream& stream) +{ + if (!mState) + { + LL_WARNS() << "Cannot update a finalized digest !" << LL_ENDL; + return; + } + + char buffer[BLOCK_LEN]; + size_t len; + while (stream.good()) + { + stream.read(buffer, BLOCK_LEN); + len = stream.gcount(); + XXH3_128bits_update((XXH3_state_t*)mState, (const void*)buffer, len); + } +} + +void HBXXH128::update(FILE* file) +{ + if (!mState) + { + LL_WARNS() << "Cannot update a finalized digest !" << LL_ENDL; + return; + } + + char buffer[BLOCK_LEN]; + size_t len; + while ((len = fread((void*)buffer, 1, BLOCK_LEN, file))) + { + XXH3_128bits_update((XXH3_state_t*)mState, (const void*)buffer, len); + } + fclose(file); +} + +void HBXXH128::finalize() +{ + if (!mState) + { + LL_WARNS() << "Already finalized !" << LL_ENDL; + return; + } + XXH128_hash_t hash = XXH3_128bits_digest((XXH3_state_t*)mState); + U64* data = (U64*)mDigest.mData; + // Note: we do not check endianness here and we just store in the same + // order as XXH128_hash_t, that is low word "first". + data[0] = hash.low64; + data[1] = hash.high64; + XXH3_freeState((XXH3_state_t*)mState); + mState = NULL; +} + +const LLUUID& HBXXH128::digest() const +{ + if (mState) + { + XXH128_hash_t hash = XXH3_128bits_digest((XXH3_state_t*)mState); + // We cheat the const-ness of the method here, but this is OK, since + // mDigest is private and cannot be accessed indirectly by other + // methods than digest() ones, that do check for mState to decide + // wether mDigest's current value may be provided as is or not. This + // cheat saves us a temporary LLLUID copy. + U64* data = (U64*)mDigest.mData; + // Note: we do not check endianness here and we just store in the same + // order as XXH128_hash_t, that is low word "first". + data[0] = hash.low64; + data[1] = hash.high64; + } + return mDigest; +} + +void HBXXH128::digest(LLUUID& result) const +{ + if (!mState) + { + result = mDigest; + return; + } + XXH128_hash_t hash = XXH3_128bits_digest((XXH3_state_t*)mState); + U64* data = (U64*)result.mData; + // Note: we do not check endianness here and we just store in the same + // order as XXH128_hash_t, that is low word "first". + data[0] = hash.low64; + data[1] = hash.high64; +} + +std::ostream& operator<<(std::ostream& stream, HBXXH128 context) +{ + stream << context.digest(); + return stream; +} diff --git a/indra/llcommon/hbxxh.h b/indra/llcommon/hbxxh.h new file mode 100644 index 0000000000..8a5f977648 --- /dev/null +++ b/indra/llcommon/hbxxh.h @@ -0,0 +1,259 @@ +/** + * @file hbxxh.h + * @brief High performances vectorized hashing based on xxHash. + * + * $LicenseInfo:firstyear=2023&license=viewergpl$ + * Second Life Viewer Source Code + * Copyright (c) 2023, Henri Beauchamp. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_HBXXH_H +#define LL_HBXXH_H + +#include "lluuid.h" + +// HBXXH* classes are to be used where speed matters and cryptographic quality +// is not required (no "one-way" guarantee, though they are likely not worst in +// this respect than MD5 which got busted and is now considered too weak). The +// xxHash code they are built upon is vectorized and about 50 times faster than +// MD5. A 64 bits hash class is also provided for when 128 bits of entropy are +// not needed. The hashes collision rate is similar to MD5's. +// See https://github.com/Cyan4973/xxHash#readme for details. + +// 64 bits hashing class + +class HBXXH64 +{ + friend std::ostream& operator<<(std::ostream&, HBXXH64); + +protected: + LOG_CLASS(HBXXH64); + +public: + inline HBXXH64() { init(); } + + // Constructors for special circumstances; they all digest the first passed + // parameter. Set 'do_finalize' to false if you do not want to finalize the + // context, which is useful/needed when you want to update() it afterwards. + // Ideally, the compiler should be smart enough to get our clue and + // optimize out the const bool test during inlining... + + inline HBXXH64(const void* buffer, size_t len, + const bool do_finalize = true) + { + init(); + update(buffer, len); + if (do_finalize) + { + finalize(); + } + } + + inline HBXXH64(const std::string& str, const bool do_finalize = true) + { + init(); + update(str); + if (do_finalize) + { + finalize(); + } + } + + inline HBXXH64(std::istream& s, const bool do_finalize = true) + { + init(); + update(s); + if (do_finalize) + { + finalize(); + } + } + + inline HBXXH64(FILE* file, const bool do_finalize = true) + { + init(); + update(file); + if (do_finalize) + { + finalize(); + } + } + + ~HBXXH64(); + + void update(const void* buffer, size_t len); + void update(const std::string& str); + void update(std::istream& s); + void update(FILE* file); + + // Note that unlike what happens with LLMD5, you do not need to finalize() + // HBXXH64 before using digest(), and you may keep updating() it even after + // you got a first digest() (the next digest would of course change after + // any update). It is still useful to use finalize() when you do not want + // to store a final digest() result in a separate U64; after this method + // has been called, digest() simply returns mDigest value. + void finalize(); + + U64 digest() const; + + // Fast static methods. Use them when hashing just one contiguous block of + // data. + static U64 digest(const void* buffer, size_t len); + static U64 digest(const char* str); // str must be NUL-terminated + static U64 digest(const std::string& str); + +private: + void init(); + +private: + // We use a void pointer to avoid including xxhash.h here for XXH3_state_t + // (which cannot either be trivially forward-declared, due to complex API + // related pre-processor macros in xxhash.h). + void* mState; + U64 mDigest; +}; + +inline bool operator==(const HBXXH64& a, const HBXXH64& b) +{ + return a.digest() == b.digest(); +} + +inline bool operator!=(const HBXXH64& a, const HBXXH64& b) +{ + return a.digest() != b.digest(); +} + +// 128 bits hashing class + +class HBXXH128 +{ + friend std::ostream& operator<<(std::ostream&, HBXXH128); + +protected: + LOG_CLASS(HBXXH128); + +public: + inline HBXXH128() { init(); } + + // Constructors for special circumstances; they all digest the first passed + // parameter. Set 'do_finalize' to false if you do not want to finalize the + // context, which is useful/needed when you want to update() it afterwards. + // Ideally, the compiler should be smart enough to get our clue and + // optimize out the const bool test during inlining... + + inline HBXXH128(const void* buffer, size_t len, + const bool do_finalize = true) + { + init(); + update(buffer, len); + if (do_finalize) + { + finalize(); + } + } + + inline HBXXH128(const std::string& str, const bool do_finalize = true) + { + init(); + update(str); + if (do_finalize) + { + finalize(); + } + } + + inline HBXXH128(std::istream& s, const bool do_finalize = true) + { + init(); + update(s); + if (do_finalize) + { + finalize(); + } + } + + inline HBXXH128(FILE* file, const bool do_finalize = true) + { + init(); + update(file); + if (do_finalize) + { + finalize(); + } + } + + ~HBXXH128(); + + void update(const void* buffer, size_t len); + void update(const std::string& str); + void update(std::istream& s); + void update(FILE* file); + + // Note that unlike what happens with LLMD5, you do not need to finalize() + // HBXXH128 before using digest(), and you may keep updating() it even + // after you got a first digest() (the next digest would of course change + // after any update). It is still useful to use finalize() when you do not + // want to store a final digest() result in a separate LLUUID; after this + // method has been called, digest() simply returns a reference on mDigest. + void finalize(); + + // We use an LLUUID for the digest, since this is a 128 bits wide native + // type available in the viewer code, making it easy to manipulate. It also + // allows to use HBXXH128 efficiently in LLUUID generate() and combine() + // methods. + const LLUUID& digest() const; + + // Here, we avoid an LLUUID copy whenever we already got one to store the + // result *and* we did not yet call finalize(). + void digest(LLUUID& result) const; + + // Fast static methods. Use them when hashing just one contiguous block of + // data. + static LLUUID digest(const void* buffer, size_t len); + static LLUUID digest(const char* str); // str must be NUL-terminated + static LLUUID digest(const std::string& str); + // Same as above, but saves you from an LLUUID copy when you already got + // one for storage use. + static void digest(LLUUID& result, const void* buffer, size_t len); + static void digest(LLUUID& result, const char* str); // str NUL-terminated + static void digest(LLUUID& result, const std::string& str); + +private: + void init(); + +private: + // We use a void pointer to avoid including xxhash.h here for XXH3_state_t + // (which cannot either be trivially forward-declared, due to complex API + // related pre-processor macros in xxhash.h). + void* mState; + LLUUID mDigest; +}; + +inline bool operator==(const HBXXH128& a, const HBXXH128& b) +{ + return a.digest() == b.digest(); +} + +inline bool operator!=(const HBXXH128& a, const HBXXH128& b) +{ + return a.digest() != b.digest(); +} + +#endif // LL_HBXXH_H diff --git a/indra/llcommon/lluuid.cpp b/indra/llcommon/lluuid.cpp index acce8366ea..8ff6c45760 100644 --- a/indra/llcommon/lluuid.cpp +++ b/indra/llcommon/lluuid.cpp @@ -40,11 +40,11 @@ #include "lluuid.h" #include "llerror.h" #include "llrand.h" -#include "llmd5.h" #include "llstring.h" #include "lltimer.h" #include "llthread.h" #include "llmutex.h" +#include "hbxxh.h" const LLUUID LLUUID::null; const LLTransactionID LLTransactionID::tnull; @@ -402,11 +402,9 @@ LLUUID LLUUID::operator^(const LLUUID& rhs) const void LLUUID::combine(const LLUUID& other, LLUUID& result) const { - LLMD5 md5_uuid; - md5_uuid.update((unsigned char*)mData, 16); - md5_uuid.update((unsigned char*)other.mData, 16); - md5_uuid.finalize(); - md5_uuid.raw_digest(result.mData); + HBXXH128 hash((const void*)mData, 16, false); // false = do not finalize + hash.update((const void*)other.mData, 16); + hash.digest(result); } LLUUID LLUUID::combine(const LLUUID &other) const @@ -857,17 +855,12 @@ void LLUUID::generate() tmp >>= 8; mData[8] = (unsigned char) tmp; - LLMD5 md5_uuid; - - md5_uuid.update(mData,16); - md5_uuid.finalize(); - md5_uuid.raw_digest(mData); + HBXXH128::digest(*this, (const void*)mData, 16); } void LLUUID::generate(const std::string& hash_string) { - LLMD5 md5_uuid((U8*)hash_string.c_str()); - md5_uuid.raw_digest(mData); + HBXXH128::digest(*this, hash_string); } U32 LLUUID::getRandomSeed() @@ -885,13 +878,8 @@ U32 LLUUID::getRandomSeed() seed[7]=(unsigned char)(pid); getSystemTime((uuid_time_t *)(&seed[8])); - LLMD5 md5_seed; - - md5_seed.update(seed,16); - md5_seed.finalize(); - md5_seed.raw_digest(seed); - - return(*(U32 *)seed); + U64 seed64 = HBXXH64((const void*)seed, 16).digest(); + return U32(seed64) ^ U32(seed64 >> 32); } BOOL LLUUID::parseUUID(const std::string& buf, LLUUID* value) diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp index 206142fdd5..52fb8e3802 100644 --- a/indra/llprimitive/llmodel.cpp +++ b/indra/llprimitive/llmodel.cpp @@ -31,7 +31,7 @@ #include "llconvexdecomposition.h" #include "llsdserialize.h" #include "llvector4a.h" -#include "llmd5.h" +#include "hbxxh.h" #ifdef LL_USESYSTEMLIBS # include @@ -1564,7 +1564,7 @@ LLSD LLMeshSkinInfo::asLLSD(bool include_joints, bool lock_scale_if_joint_positi void LLMeshSkinInfo::updateHash() { // get hash of data relevant to render batches - LLMD5 hash; + HBXXH64 hash; //mJointNames for (auto& name : mJointNames) @@ -1573,24 +1573,19 @@ void LLMeshSkinInfo::updateHash() } //mJointNums - hash.update((U8*)&(mJointNums[0]), sizeof(S32) * mJointNums.size()); + hash.update((const void*)mJointNums.data(), sizeof(S32) * mJointNums.size()); //mInvBindMatrix F32* src = mInvBindMatrix[0].getF32ptr(); - for (int i = 0; i < mInvBindMatrix.size() * 16; ++i) + for (size_t i = 0, count = mInvBindMatrix.size() * 16; i < count; ++i) { S32 t = llround(src[i] * 10000.f); - hash.update((U8*)&t, sizeof(S32)); + hash.update((const void*)&t, sizeof(S32)); } - //hash.update((U8*)&(mInvBindMatrix[0]), sizeof(LLMatrix4a) * mInvBindMatrix.size()); + //hash.update((const void*)mInvBindMatrix.data(), sizeof(LLMatrix4a) * mInvBindMatrix.size()); - hash.finalize(); - - U64 digest[2]; - hash.raw_digest((U8*) digest); - - mHash = digest[0]; + mHash = hash.digest(); } U32 LLMeshSkinInfo::sizeBytes() const diff --git a/indra/newview/skins/default/xui/da/floater_about.xml b/indra/newview/skins/default/xui/da/floater_about.xml index b322e67bb7..7bcae69779 100644 --- a/indra/newview/skins/default/xui/da/floater_about.xml +++ b/indra/newview/skins/default/xui/da/floater_about.xml @@ -70,6 +70,7 @@ PCRE Copyright (c) 1997-2008 University of Cambridge SDL Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga SSLeay Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) xmlrpc-epi Copyright (C) 2000 Epinions, Inc. +xxHash Copyright (C) 2012-2020 Yann Collet. zlib Copyright (C) 1995-2002 Jean-loup Gailly and Mark Adler. google-perftools Copyright (c) 2005, Google Inc. diff --git a/indra/newview/skins/default/xui/de/floater_about.xml b/indra/newview/skins/default/xui/de/floater_about.xml index b2708f7141..10ccf0d5da 100644 --- a/indra/newview/skins/default/xui/de/floater_about.xml +++ b/indra/newview/skins/default/xui/de/floater_about.xml @@ -29,6 +29,7 @@ mit Open-Source-Beiträgen von: SDL Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga. SSLeay Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com). xmlrpc-epi Copyright (C) 2000 Epinions, Inc. + xxHash Copyright (C) 2012-2020 Yann Collet. zlib Copyright (C) 1995-2012 Jean-loup Gailly und Mark Adler. Second Life Viewer verwendet Havok (TM) Physics. (c)Copyright 1999-2010 Havok.com Inc. (und Lizenzgeber). Alle Rechte vorbehalten. Details siehe www.havok.com. diff --git a/indra/newview/skins/default/xui/en/floater_about.xml b/indra/newview/skins/default/xui/en/floater_about.xml index eb07425dfe..1ad7811d85 100644 --- a/indra/newview/skins/default/xui/en/floater_about.xml +++ b/indra/newview/skins/default/xui/en/floater_about.xml @@ -112,6 +112,7 @@ Dummy Name replaced at run time SDL Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga SSLeay Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) xmlrpc-epi Copyright (C) 2000 Epinions, Inc. + xxHash Copyright (C) 2012-2020 Yann Collet. zlib Copyright (C) 1995-2012 Jean-loup Gailly and Mark Adler. Second Life Viewer uses Havok (TM) Physics. (c)Copyright 1999-2010 Havok.com Inc. (and its Licensors). All Rights Reserved. See www.havok.com for details. diff --git a/indra/newview/skins/default/xui/es/floater_about.xml b/indra/newview/skins/default/xui/es/floater_about.xml index f59f534908..e14ba32f69 100644 --- a/indra/newview/skins/default/xui/es/floater_about.xml +++ b/indra/newview/skins/default/xui/es/floater_about.xml @@ -29,6 +29,7 @@ con contribuciones de código abierto de: SDL Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga SSLeay Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) xmlrpc-epi Copyright (C) 2000 Epinions, Inc. + xxHash Copyright (C) 2012-2020 Yann Collet. zlib Copyright (C) 1995-2012 Jean-loup Gailly y Mark Adler. El visor de Second Life usa Havok (TM) Physics. (c)Copyright 1999-2010 Havok.com Inc. (y sus licenciadores). Reservados todos los derechos. Vea los detalles en www.havok.com. diff --git a/indra/newview/skins/default/xui/fr/floater_about.xml b/indra/newview/skins/default/xui/fr/floater_about.xml index df6b61e293..09da1fb5fd 100644 --- a/indra/newview/skins/default/xui/fr/floater_about.xml +++ b/indra/newview/skins/default/xui/fr/floater_about.xml @@ -29,6 +29,7 @@ avec les contributions Open Source de : SDL Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga SSLeay Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) xmlrpc-epi Copyright (C) 2000 Epinions, Inc. + xxHash Copyright (C) 2012-2020 Yann Collet. zlib Copyright (C) 1995-2012 Jean-Loup Gailly et Mark Adler. Le client Second Life utilise Havok (TM) Physics. (c)Copyright 1999-2010 Havok.com Inc. (et ses concédants de licence). Tous droits réservés. Pour plus de détails, consultez le site Web www.havok.com. diff --git a/indra/newview/skins/default/xui/it/floater_about.xml b/indra/newview/skins/default/xui/it/floater_about.xml index edb334e13e..7e195d3ca9 100644 --- a/indra/newview/skins/default/xui/it/floater_about.xml +++ b/indra/newview/skins/default/xui/it/floater_about.xml @@ -29,6 +29,7 @@ con contributi open source da: SDL Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga SSLeay Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) xmlrpc-epi Copyright (C) 2000 Epinions, Inc. + xxHash Copyright (C) 2012-2020 Yann Collet. zlib Copyright (C) 1995-2012 Jean-loup Gailly e Mark Adler. Il Viewer Second Life utilizza Havok (TM) Physics. (c)Copyright 1999-2010 Havok.com Inc. (e licenziatari). Tutti i diritti riservati. Per informazioni dettagliate, vedere www.havok.com. diff --git a/indra/newview/skins/default/xui/ja/floater_about.xml b/indra/newview/skins/default/xui/ja/floater_about.xml index 6a39d057e2..22a65003d3 100644 --- a/indra/newview/skins/default/xui/ja/floater_about.xml +++ b/indra/newview/skins/default/xui/ja/floater_about.xml @@ -29,6 +29,7 @@ PCRE Copyright (c) 1997-2012 University of Cambridge SDL Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga SSLeay Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) xmlrpc-epi Copyright (C) 2000 Epinions, Inc. +xxHash Copyright (C) 2012-2020 Yann Collet. zlib Copyright (C) 1995-2012 Jean-loup Gailly and Mark Adler. Second Life ビューワでは Havok (TM) Physics が使用されています。(c)Copyright 1999-2010 Havok.com Inc. (and its Licensors).無断複写・複製・転載を禁じます。詳細については www.havok.com をご参照ください。 diff --git a/indra/newview/skins/default/xui/pt/floater_about.xml b/indra/newview/skins/default/xui/pt/floater_about.xml index 3c0ca332ac..aaed728f84 100644 --- a/indra/newview/skins/default/xui/pt/floater_about.xml +++ b/indra/newview/skins/default/xui/pt/floater_about.xml @@ -29,6 +29,7 @@ com contribuições de código aberto de: SDL Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga SSLeay Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) xmlrpc-epi Copyright (C) 2000 Epinions, Inc. + xxHash Copyright (C) 2012-2020 Yann Collet. zlib Copyright (C) 1995-2012 Jean-loup Gailly and Mark Adler. O Visualizador do Second Life usa Havok (TM) Physics. (c)Copyright 1999-2010 Havok.com Inc. (e seus Licenciantes). Todos os direitos reservados. Consulte www.havok.com para obter detalhes. diff --git a/indra/newview/skins/default/xui/ru/floater_about.xml b/indra/newview/skins/default/xui/ru/floater_about.xml index 44216e0430..a65a979ccd 100644 --- a/indra/newview/skins/default/xui/ru/floater_about.xml +++ b/indra/newview/skins/default/xui/ru/floater_about.xml @@ -29,6 +29,7 @@ SDL (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga SSLeay (C) 1995-1998 Eric Young (eay@cryptsoft.com) xmlrpc-epi (C) 2000 Epinions, Inc. + xxHash Copyright (C) 2012-2020 Yann Collet. zlib (C) 1995-2012 Jean-loup Gailly и Mark Adler. В клиенте Second Life используется технология Havok (TM) Physics. (C) 1999-2010 Havok.com Inc. (и лицензиары компании). Все права защищены. Подробнее см. веб-сайт www.havok.com. diff --git a/indra/newview/skins/default/xui/tr/floater_about.xml b/indra/newview/skins/default/xui/tr/floater_about.xml index faa504a996..40ca3707c3 100644 --- a/indra/newview/skins/default/xui/tr/floater_about.xml +++ b/indra/newview/skins/default/xui/tr/floater_about.xml @@ -29,6 +29,7 @@ açık kaynak kod katkısında bulunanlar şunlardır: SDL Telif Hakkı (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga SSLeay Telif Hakkı (C) 1995-1998 Eric Young (eay@cryptsoft.com) xmlrpc-epi Telif Hakkı (C) 2000 Epinions, Inc. + xxHash Copyright (C) 2012-2020 Yann Collet. zlib Telif Hakkı (C) 1995-2012 Jean-loup Gailly ve Mark Adler. Second Life Görüntüleyicisi Havok (TM) Fizik motorunu kullanmaktadır. (c)Telif Hakkı 1999-2010 Havok.com Inc. (ve Lisans Verenleri). Tüm Hakları Saklıdır. Ayrıntılı bilgi için bkz. www.havok.com diff --git a/indra/newview/skins/default/xui/zh/floater_about.xml b/indra/newview/skins/default/xui/zh/floater_about.xml index d7d2a52750..a56ae753d1 100644 --- a/indra/newview/skins/default/xui/zh/floater_about.xml +++ b/indra/newview/skins/default/xui/zh/floater_about.xml @@ -29,6 +29,7 @@ SDL Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga SSLeay Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) xmlrpc-epi Copyright (C) 2000 Epinions, Inc. + xxHash Copyright (C) 2012-2020 Yann Collet. zlib Copyright (C) 1995-2012 Jean-loup Gailly and Mark Adler. 第二人生 Viewer 採用 Havok (TM) 物理引擎。 (c)Copyright 1999-2010 Havok.com Inc.(及其放照人)。 保留一切權利。 詳情見 www.havok.com。 From b5b0a3fbf6b58c7f1a7e4377bfeb6adb3337e4bf Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 31 Jan 2023 18:48:16 +0200 Subject: [PATCH 27/31] SL-19110 Fix xxhash build link and properly register contribution --- autobuild.xml | 4 ++-- doc/contributions.txt | 2 ++ indra/llcommon/hbxxh.cpp | 4 ++-- indra/llcommon/hbxxh.h | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/autobuild.xml b/autobuild.xml index 67c9b84af2..916a2d06e8 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -2947,9 +2947,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - f54f21dda4ce25b112f0cc7b4ce38bba + e4f77ba0a9b8ec3cc3fabc51c4da81d2 url - http://sldev.free.fr/libraries/xxhash-0.8.1-20230124.tar.bz2 + https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/110070/956941/xxhash-0.8.1.578006-windows-578006.tar.bz2 name common diff --git a/doc/contributions.txt b/doc/contributions.txt index 4cabb84b10..4975039241 100755 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -582,6 +582,8 @@ Henri Beauchamp VWR-1320 VWR-1406 VWR-4157 + SL-15175 + SL-19110 herina Bode Hikkoshi Sakai VWR-429 diff --git a/indra/llcommon/hbxxh.cpp b/indra/llcommon/hbxxh.cpp index e94581d415..388269d6c8 100644 --- a/indra/llcommon/hbxxh.cpp +++ b/indra/llcommon/hbxxh.cpp @@ -2,7 +2,7 @@ * @file hbxxh.cpp * @brief High performances vectorized hashing based on xxHash. * - * $LicenseInfo:firstyear=2023&license=viewergpl$ + * $LicenseInfo:firstyear=2023&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (c) 2023, Henri Beauchamp. * @@ -34,7 +34,7 @@ // in your build, in which case the latter would be used instead. For ARM64 // builds, this would also automatically enable NEON vectorization. #define XXH_INLINE_ALL -#include "xxhash.h" +#include "xxhash/xxhash.h" #include "hbxxh.h" diff --git a/indra/llcommon/hbxxh.h b/indra/llcommon/hbxxh.h index 8a5f977648..236716722a 100644 --- a/indra/llcommon/hbxxh.h +++ b/indra/llcommon/hbxxh.h @@ -2,7 +2,7 @@ * @file hbxxh.h * @brief High performances vectorized hashing based on xxHash. * - * $LicenseInfo:firstyear=2023&license=viewergpl$ + * $LicenseInfo:firstyear=2023&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (c) 2023, Henri Beauchamp. * From c9d56e212aa0117661f9c76545ca84b39412bae7 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Tue, 31 Jan 2023 15:01:05 -0600 Subject: [PATCH 28/31] SL-19015 Balance sun/sky ambiance with punctual light ambiance. Prevent irradiance maps from being brighter than the environment. --- indra/llrender/llglslshader.cpp | 18 +----- indra/llrender/llglslshader.h | 5 +- indra/llrender/llpostprocess.cpp | 2 +- indra/newview/app_settings/settings.xml | 11 ++++ .../class2/interface/irradianceGenF.glsl | 29 +++------ indra/newview/lldrawpoolbump.cpp | 2 +- indra/newview/lldrawpoolsimple.cpp | 2 +- indra/newview/lldynamictexture.cpp | 2 +- indra/newview/llreflectionmapmanager.cpp | 49 ++++++++++---- indra/newview/llsettingsvo.cpp | 64 +++++++++---------- indra/newview/pipeline.cpp | 45 +++++++++---- 11 files changed, 124 insertions(+), 105 deletions(-) diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 42b7cc46b3..faa45d59b9 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -1041,26 +1041,10 @@ void LLGLSLShader::bind(bool rigged) } } -void LLGLSLShader::unbind() +void LLGLSLShader::unbind(void) { LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; gGL.flush(); - if (sCurBoundShaderPtr) - { - sCurBoundShaderPtr->readProfileQuery(); - } - stop_glerror(); - LLVertexBuffer::unbind(); - glUseProgram(0); - sCurBoundShader = 0; - sCurBoundShaderPtr = NULL; - stop_glerror(); -} - -void LLGLSLShader::bindNoShader(void) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - LLVertexBuffer::unbind(); if (sCurBoundShaderPtr) diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index 1ec41ebd3c..6c18282fec 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -254,10 +254,9 @@ public: void bind(); //helper to conditionally bind mRiggedVariant instead of this void bind(bool rigged); - void unbind(); - + // Unbinds any previously bound shader by explicitly binding no shader. - static void bindNoShader(void); + static void unbind(); U32 mMatHash[LLRender::NUM_MATRIX_MODES]; U32 mLightHash; diff --git a/indra/llrender/llpostprocess.cpp b/indra/llrender/llpostprocess.cpp index 0d87800690..f1e5b71207 100644 --- a/indra/llrender/llpostprocess.cpp +++ b/indra/llrender/llpostprocess.cpp @@ -376,7 +376,7 @@ void LLPostProcess::doEffects(void) checkError(); applyShaders(); - LLGLSLShader::bindNoShader(); + LLGLSLShader::unbind(); checkError(); /// Change to a perspective view diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 41afca50f6..333d764866 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10393,6 +10393,17 @@ Value 256 + RenderReflectionProbeAmbianceScale + + Comment + Scaler to apply to reflection probes to over-brighten sky contributions to indirect light + Persist + 1 + Type + F32 + Value + 8 + RenderReflectionProbeDrawDistance diff --git a/indra/newview/app_settings/shaders/class2/interface/irradianceGenF.glsl b/indra/newview/app_settings/shaders/class2/interface/irradianceGenF.glsl index a4aec48c59..c7da23fb00 100644 --- a/indra/newview/app_settings/shaders/class2/interface/irradianceGenF.glsl +++ b/indra/newview/app_settings/shaders/class2/interface/irradianceGenF.glsl @@ -26,20 +26,15 @@ /*[EXTRA_CODE_HERE]*/ - -#ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_color; -#else -#define frag_color gl_FragColor -#endif uniform samplerCubeArray reflectionProbes; uniform int sourceIdx; uniform float max_probe_lod; +uniform float ambiance_scale; -VARYING vec3 vary_dir; - +in vec3 vary_dir; // Code below is derived from the Khronos GLTF Sample viewer: // https://github.com/KhronosGroup/glTF-Sample-Viewer/blob/master/source/shaders/ibl_filtering.frag @@ -48,7 +43,7 @@ VARYING vec3 vary_dir; #define MATH_PI 3.1415926535897932384626433832795 float u_roughness = 1.0; -int u_sampleCount = 64; +int u_sampleCount = 32; float u_lodBias = 2.0; int u_width = 64; @@ -183,8 +178,7 @@ vec4 filterColor(vec3 N) { //return textureLod(uCubeMap, N, 3.0).rgb; vec4 color = vec4(0.f); - float weight = 0.0f; - + for(int i = 0; i < u_sampleCount; ++i) { vec4 importanceSample = getImportanceSample(i, N, 1.0); @@ -198,24 +192,17 @@ vec4 filterColor(vec3 N) // apply the bias to the lod lod += u_lodBias; - lod = clamp(lod, 0, max_probe_lod); + lod = clamp(lod, 0, 7); // sample lambertian at a lower resolution to avoid fireflies vec4 lambertian = textureLod(reflectionProbes, vec4(H, sourceIdx), lod); color += lambertian; } - if(weight != 0.0f) - { - color /= weight; - } - else - { - color /= float(u_sampleCount); - } + color /= float(u_sampleCount); + + color.rgb *= ambiance_scale; - color = min(color*1.9, vec4(1)); - color = pow(color, vec4(0.5)); return color; } diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index 9c871514f7..254c74df79 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -676,7 +676,7 @@ void LLDrawPoolBump::renderBump(U32 pass) //static void LLDrawPoolBump::endBump(U32 pass) { - gObjectBumpProgram.unbind(); + LLGLSLShader::unbind(); gGL.setSceneBlendType(LLRender::BT_ALPHA); } diff --git a/indra/newview/lldrawpoolsimple.cpp b/indra/newview/lldrawpoolsimple.cpp index 3a659e0efc..7a8b2b4b35 100644 --- a/indra/newview/lldrawpoolsimple.cpp +++ b/indra/newview/lldrawpoolsimple.cpp @@ -358,7 +358,7 @@ void LLDrawPoolGrass::beginRenderPass(S32 pass) else { gGL.flush(); - LLGLSLShader::bindNoShader(); + LLGLSLShader::unbind(); } } diff --git a/indra/newview/lldynamictexture.cpp b/indra/newview/lldynamictexture.cpp index d1f9e7a943..7fdb3fbdaf 100644 --- a/indra/newview/lldynamictexture.cpp +++ b/indra/newview/lldynamictexture.cpp @@ -195,7 +195,7 @@ BOOL LLViewerDynamicTexture::updateAllInstances() gPipeline.mBake.clear(); } - LLGLSLShader::bindNoShader(); + LLGLSLShader::unbind(); LLVertexBuffer::unbind(); BOOL result = FALSE; diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp index ee05849130..e622f54756 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -406,7 +406,7 @@ void LLReflectionMapManager::doProbeUpdate() { updateNeighbors(mUpdatingProbe); mUpdatingFace = 0; - if (mRadiancePass) + if (isRadiancePass()) { mUpdatingProbe = nullptr; mRadiancePass = false; @@ -460,12 +460,12 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) } gGL.setColorMask(true, true); + LLGLDepthTest depth(GL_FALSE, GL_FALSE); + LLGLDisable cull(GL_CULL_FACE); + LLGLDisable blend(GL_BLEND); // downsample to placeholder map { - LLGLDepthTest depth(GL_FALSE, GL_FALSE); - LLGLDisable cull(GL_CULL_FACE); - gReflectionMipProgram.bind(); gGL.matrixMode(gGL.MM_MODELVIEW); @@ -560,7 +560,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) mMipChain[0].bindTarget(); static LLStaticHashedString sSourceIdx("sourceIdx"); - if (mRadiancePass) + if (isRadiancePass()) { //generate radiance map (even if this is not the irradiance map, we need the mip chain for the irradiance map) gRadianceGenProgram.bind(); @@ -607,16 +607,20 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) gRadianceGenProgram.unbind(); } - else if (!mRadiancePass) + else { //generate irradiance map gIrradianceGenProgram.bind(); S32 channel = gIrradianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY); mTexture->bind(channel); + static LLCachedControl ambiance_scale(gSavedSettings, "RenderReflectionProbeAmbianceScale", 8.f); + static LLStaticHashedString ambiance_scale_str("ambiance_scale"); + + gIrradianceGenProgram.uniform1f(ambiance_scale_str, ambiance_scale); gIrradianceGenProgram.uniform1i(sSourceIdx, sourceIdx); gIrradianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mMaxProbeLOD); - + mVertexBuffer->setBuffer(); int start_mip = 0; // find the mip target to start with based on irradiance map resolution @@ -726,12 +730,28 @@ void LLReflectionMapManager::updateUniforms() // see class3/deferred/reflectionProbeF.glsl struct ReflectionProbeData { - LLMatrix4 refBox[LL_MAX_REFLECTION_PROBE_COUNT]; // object bounding box as needed - LLVector4 refSphere[LL_MAX_REFLECTION_PROBE_COUNT]; //origin and radius of refmaps in clip space - LLVector4 refParams[LL_MAX_REFLECTION_PROBE_COUNT]; //extra parameters (currently only ambiance) - GLint refIndex[LL_MAX_REFLECTION_PROBE_COUNT][4]; - GLint refNeighbor[4096]; - GLint refmapCount; + // for box probes, matrix that transforms from camera space to a [-1, 1] cube representing the bounding box of + // the box probe + LLMatrix4 refBox[LL_MAX_REFLECTION_PROBE_COUNT]; + + // for sphere probes, origin (xyz) and radius (w) of refmaps in clip space + LLVector4 refSphere[LL_MAX_REFLECTION_PROBE_COUNT]; + + // extra parameters (currently only ambiance in .x) + LLVector4 refParams[LL_MAX_REFLECTION_PROBE_COUNT]; + + // indices used by probe: + // [i][0] - cubemap array index for this probe + // [i][1] - index into "refNeighbor" for probes that intersect this probe + // [i][2] - number of probes that intersect this probe, or -1 for no neighbors + // [i][3] - priority (probe type stored in sign bit - positive for spheres, negative for boxes) + GLint refIndex[LL_MAX_REFLECTION_PROBE_COUNT][4]; + + // list of neighbor indices + GLint refNeighbor[4096]; + + // numbrer of active refmaps + GLint refmapCount; }; mReflectionMaps.resize(mReflectionProbeCount); @@ -751,7 +771,8 @@ void LLReflectionMapManager::updateUniforms() LLSettingsSky::ptr_t psky = environment.getCurrentSky(); F32 minimum_ambiance = psky->getTotalReflectionProbeAmbiance(); - F32 ambscale = gCubeSnapshot && !mRadiancePass ? 0.f : 1.f; + F32 ambscale = gCubeSnapshot && !isRadiancePass() ? 0.f : 1.f; + for (auto* refmap : mReflectionMaps) { diff --git a/indra/newview/llsettingsvo.cpp b/indra/newview/llsettingsvo.cpp index a49bd11ffd..fd27c83270 100644 --- a/indra/newview/llsettingsvo.cpp +++ b/indra/newview/llsettingsvo.cpp @@ -675,6 +675,8 @@ void LLSettingsVOSky::applySpecial(void *ptarget, bool force) LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; LLVector3 light_direction = LLVector3(LLEnvironment::instance().getClampedLightNorm().mV); + bool radiance_pass = gCubeSnapshot && !gPipeline.mReflectionMapManager.isRadiancePass(); + LLShaderUniforms* shader = &((LLShaderUniforms*)ptarget)[LLGLSLShader::SG_DEFAULT]; { shader->uniform3fv(LLViewerShaderMgr::LIGHTNORM, light_direction); @@ -682,34 +684,33 @@ void LLSettingsVOSky::applySpecial(void *ptarget, bool force) } shader = &((LLShaderUniforms*)ptarget)[LLGLSLShader::SG_SKY]; - { - shader->uniform3fv(LLViewerShaderMgr::LIGHTNORM, light_direction); - // Legacy? SETTING_CLOUD_SCROLL_RATE("cloud_scroll_rate") - LLVector4 vect_c_p_d1(mSettings[SETTING_CLOUD_POS_DENSITY1]); - LLVector4 cloud_scroll( LLEnvironment::instance().getCloudScrollDelta() ); + shader->uniform3fv(LLViewerShaderMgr::LIGHTNORM, light_direction); - // SL-13084 EEP added support for custom cloud textures -- flip them horizontally to match the preview of Clouds > Cloud Scroll - // Keep in Sync! - // * indra\newview\llsettingsvo.cpp - // * indra\newview\app_settings\shaders\class2\windlight\cloudsV.glsl - // * indra\newview\app_settings\shaders\class1\deferred\cloudsV.glsl - cloud_scroll[0] = -cloud_scroll[0]; - vect_c_p_d1 += cloud_scroll; - shader->uniform3fv(LLShaderMgr::CLOUD_POS_DENSITY1, LLVector3(vect_c_p_d1.mV)); + // Legacy? SETTING_CLOUD_SCROLL_RATE("cloud_scroll_rate") + LLVector4 vect_c_p_d1(mSettings[SETTING_CLOUD_POS_DENSITY1]); + LLVector4 cloud_scroll( LLEnvironment::instance().getCloudScrollDelta() ); - LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky(); + // SL-13084 EEP added support for custom cloud textures -- flip them horizontally to match the preview of Clouds > Cloud Scroll + // Keep in Sync! + // * indra\newview\llsettingsvo.cpp + // * indra\newview\app_settings\shaders\class2\windlight\cloudsV.glsl + // * indra\newview\app_settings\shaders\class1\deferred\cloudsV.glsl + cloud_scroll[0] = -cloud_scroll[0]; + vect_c_p_d1 += cloud_scroll; + shader->uniform3fv(LLShaderMgr::CLOUD_POS_DENSITY1, LLVector3(vect_c_p_d1.mV)); - // TODO -- make these getters return vec3s - LLVector3 sunDiffuse = LLVector3(psky->getSunlightColor().mV); - LLVector3 moonDiffuse = LLVector3(psky->getMoonlightColor().mV); + LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky(); - shader->uniform3fv(LLShaderMgr::SUNLIGHT_COLOR, sunDiffuse); - shader->uniform3fv(LLShaderMgr::MOONLIGHT_COLOR, moonDiffuse); + // TODO -- make these getters return vec3s + LLVector3 sunDiffuse = LLVector3(psky->getSunlightColor().mV); + LLVector3 moonDiffuse = LLVector3(psky->getMoonlightColor().mV); + + shader->uniform3fv(LLShaderMgr::SUNLIGHT_COLOR, sunDiffuse); + shader->uniform3fv(LLShaderMgr::MOONLIGHT_COLOR, moonDiffuse); + + shader->uniform3fv(LLShaderMgr::CLOUD_COLOR, LLVector3(psky->getCloudColor().mV)); - shader->uniform3fv(LLShaderMgr::CLOUD_COLOR, LLVector3(psky->getCloudColor().mV)); - } - shader = &((LLShaderUniforms*)ptarget)[LLGLSLShader::SG_ANY]; shader->uniform1f(LLShaderMgr::SCENE_LIGHT_STRENGTH, mSceneLightStrength); @@ -717,27 +718,20 @@ void LLSettingsVOSky::applySpecial(void *ptarget, bool force) shader->uniform3fv(LLShaderMgr::AMBIENT, LLVector3(ambient.mV)); - if (gCubeSnapshot && !gPipeline.mReflectionMapManager.isRadiancePass()) + if (radiance_pass) { // during an irradiance map update, disable ambient lighting (direct lighting only) and desaturate sky color (avoid tinting the world blue) shader->uniform3fv(LLShaderMgr::AMBIENT_LINEAR, LLVector3::zero.mV); - - auto max_vec = [](LLVector3 col) - { - col.mV[0] = col.mV[1] = col.mV[2] = llmax(llmax(col.mV[0], col.mV[1]), col.mV[2]); - return col; - }; - shader->uniform3fv(LLShaderMgr::BLUE_HORIZON_LINEAR, max_vec(linearColor3v(getBlueHorizon() / 2.f))); // note magic number of 2.f comes from SLIDER_SCALE_BLUE_HORIZON_DENSITY - shader->uniform3fv(LLShaderMgr::BLUE_DENSITY_LINEAR, max_vec(linearColor3v(getBlueDensity() / 2.f))); } else { shader->uniform3fv(LLShaderMgr::AMBIENT_LINEAR, linearColor3v(getAmbientColor() / 3.f)); // note magic number 3.f comes from SLIDER_SCALE_SUN_AMBIENT - shader->uniform3fv(LLShaderMgr::BLUE_HORIZON_LINEAR, linearColor3v(getBlueHorizon() / 2.f)); // note magic number of 2.f comes from SLIDER_SCALE_BLUE_HORIZON_DENSITY - shader->uniform3fv(LLShaderMgr::BLUE_DENSITY_LINEAR, linearColor3v(getBlueDensity() / 2.f)); } - shader->uniform3fv(LLShaderMgr::SUNLIGHT_LINEAR, linearColor3v(getSunlightColor())); - shader->uniform3fv(LLShaderMgr::MOONLIGHT_LINEAR,linearColor3v(getMoonlightColor())); + shader->uniform3fv(LLShaderMgr::BLUE_HORIZON_LINEAR, linearColor3v(getBlueHorizon() / 2.f)); // note magic number of 2.f comes from SLIDER_SCALE_BLUE_HORIZON_DENSITY + shader->uniform3fv(LLShaderMgr::BLUE_DENSITY_LINEAR, linearColor3v(getBlueDensity() / 2.f)); + + shader->uniform3fv(LLShaderMgr::SUNLIGHT_LINEAR, linearColor3v(sunDiffuse)); + shader->uniform3fv(LLShaderMgr::MOONLIGHT_LINEAR,linearColor3v(moonDiffuse)); shader->uniform1f(LLShaderMgr::REFLECTION_PROBE_AMBIANCE, getTotalReflectionProbeAmbiance()); diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 03ffe5da48..641df44aeb 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -4023,7 +4023,7 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera, bool do_occlusion) } if (&camera == LLViewerCamera::getInstance()) - { // a bit hacky, this is the start of the main render frame, figure out delta between last modelview matrix and + { // a bit hacky, this is the start of the main render frame, figure out delta between last modelview matrix and // current modelview matrix glh::matrix4f last_modelview(gGLLastModelView); glh::matrix4f cur_modelview(gGLModelView); @@ -4039,7 +4039,6 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera, bool do_occlusion) gGLDeltaModelView[i] = m.m[i]; gGLInverseDeltaModelView[i] = n.m[i]; } - } bool occlude = LLPipeline::sUseOcclusion > 1 && do_occlusion; @@ -4047,7 +4046,7 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera, bool do_occlusion) setupHWLights(nullptr); { - LL_PROFILE_ZONE_NAMED_CATEGORY_DRAWPOOL("deferred pools"); //LL_RECORD_BLOCK_TIME(FTM_DEFERRED_POOLS); + LL_PROFILE_ZONE_NAMED_CATEGORY_DRAWPOOL("deferred pools"); LLGLEnable cull(GL_CULL_FACE); @@ -4096,7 +4095,7 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera, bool do_occlusion) pool_set_t::iterator iter2 = iter1; if (hasRenderType(poolp->getType()) && poolp->getNumDeferredPasses() > 0) { - LL_PROFILE_ZONE_NAMED_CATEGORY_DRAWPOOL("deferred pool render"); //LL_RECORD_BLOCK_TIME(FTM_DEFERRED_POOLRENDER); + LL_PROFILE_ZONE_NAMED_CATEGORY_DRAWPOOL("deferred pool render"); gGLLastMatrix = NULL; gGL.loadMatrix(gGLModelView); @@ -4156,7 +4155,7 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera, bool do_occlusion) void LLPipeline::renderGeomPostDeferred(LLCamera& camera) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; //LL_RECORD_BLOCK_TIME(FTM_POST_DEFERRED_POOLS); + LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; LL_PROFILE_GPU_ZONE("renderGeomPostDeferred"); if (gUseWireframe) @@ -4192,7 +4191,7 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera) pool_set_t::iterator iter2 = iter1; if (hasRenderType(poolp->getType()) && poolp->getNumPostDeferredPasses() > 0) { - LL_PROFILE_ZONE_NAMED_CATEGORY_DRAWPOOL("deferred poolrender"); //LL_RECORD_BLOCK_TIME(FTM_POST_DEFERRED_POOLRENDER); + LL_PROFILE_ZONE_NAMED_CATEGORY_DRAWPOOL("deferred poolrender"); gGLLastMatrix = NULL; gGL.loadMatrix(gGLModelView); @@ -5766,6 +5765,15 @@ void LLPipeline::setupHWLights(LLDrawPool* pool) // Ambient LLColor4 ambient = psky->getTotalAmbient(); + static LLCachedControl ambiance_scale(gSavedSettings, "RenderReflectionProbeAmbianceScale", 8.f); + + F32 light_scale = 1.f; + + if (gCubeSnapshot && !mReflectionMapManager.isRadiancePass()) + { //darken local lights based on brightening of sky lighting + light_scale = 1.f / ambiance_scale; + } + gGL.setAmbientLightColor(ambient); bool sun_up = environment.getIsSunUp(); @@ -5859,7 +5867,7 @@ void LLPipeline::setupHWLights(LLDrawPool* pool) } //send linear light color to shader - LLColor4 light_color = light->getLightLinearColor(); + LLColor4 light_color = light->getLightLinearColor()*light_scale; light_color.mV[3] = 0.0f; F32 fade = iter->fade; @@ -8141,6 +8149,15 @@ void LLPipeline::renderDeferredLighting() return; } + static LLCachedControl ambiance_scale(gSavedSettings, "RenderReflectionProbeAmbianceScale", 8.f); + + F32 light_scale = 1.f; + + if (gCubeSnapshot && !mReflectionMapManager.isRadiancePass()) + { //darken local lights based on brightening of sky lighting + light_scale = 1.f / ambiance_scale; + } + LLRenderTarget *screen_target = &mRT->screen; LLRenderTarget* deferred_light_target = &mRT->deferredLight; @@ -8374,7 +8391,7 @@ void LLPipeline::renderDeferredLighting() F32 s = volume->getLightRadius() * 1.5f; // send light color to shader in linear space - LLColor3 col = volume->getLightLinearColor(); + LLColor3 col = volume->getLightLinearColor()*light_scale; if (col.magVecSquared() < 0.001f) { @@ -8468,7 +8485,7 @@ void LLPipeline::renderDeferredLighting() setupSpotLight(gDeferredSpotLightProgram, drawablep); // send light color to shader in linear space - LLColor3 col = volume->getLightLinearColor(); + LLColor3 col = volume->getLightLinearColor() * light_scale; gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, c); gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s); @@ -8543,7 +8560,7 @@ void LLPipeline::renderDeferredLighting() setupSpotLight(gDeferredMultiSpotLightProgram, drawablep); // send light color to shader in linear space - LLColor3 col = volume->getLightLinearColor(); + LLColor3 col = volume->getLightLinearColor() * light_scale; gDeferredMultiSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, tc.v); gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, light_size_final); @@ -8955,12 +8972,16 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera LLPipeline::sShadowRender = true; + // disable occlusion culling during shadow render + U32 saved_occlusion = sUseOcclusion; + sUseOcclusion = 0; + static const U32 types[] = { LLRenderPass::PASS_SIMPLE, LLRenderPass::PASS_FULLBRIGHT, LLRenderPass::PASS_SHINY, LLRenderPass::PASS_BUMP, - LLRenderPass::PASS_FULLBRIGHT_SHINY , + LLRenderPass::PASS_FULLBRIGHT_SHINY, LLRenderPass::PASS_MATERIAL, LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE, LLRenderPass::PASS_SPECMAP, @@ -9151,6 +9172,8 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera gGL.popMatrix(); gGLLastMatrix = NULL; + // reset occlusion culling flag + sUseOcclusion = saved_occlusion; LLPipeline::sShadowRender = false; } From 280c92b7de3fce2751d94ee98faea293bd911fd0 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Tue, 31 Jan 2023 16:45:39 -0600 Subject: [PATCH 29/31] SL-18154 Followup -- Use Henri's xxHash integration to speed up UI Vertex Buffer cache --- indra/llrender/llrender.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 6dbde719f4..cdefefd38e 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -35,7 +35,7 @@ #include "llrendertarget.h" #include "lltexture.h" #include "llshadermgr.h" -#include "llmd5.h" +#include "hbxxh.h" #if LL_WINDOWS extern void APIENTRY gl_debug_callback(GLenum source, @@ -79,7 +79,7 @@ struct LLVBCache std::chrono::steady_clock::time_point touched; }; -static std::unordered_map sVBCache; +static std::unordered_map sVBCache; static const GLenum sGLTextureType[] = { @@ -1640,7 +1640,7 @@ void LLRender::flush() if (mBuffer) { - LLMD5 hash; + HBXXH64 hash; U32 attribute_mask = LLGLSLShader::sCurBoundShaderPtr->mAttributeMask; { @@ -1660,8 +1660,8 @@ void LLRender::flush() hash.finalize(); } - size_t vhash[2]; - hash.raw_digest((unsigned char*) vhash); + + U64 vhash = hash.digest(); // check the VB cache before making a new vertex buffer // This is a giant hack to deal with (mostly) our terrible UI rendering code @@ -1672,7 +1672,7 @@ void LLRender::flush() // To leverage this, we maintain a running hash of the vertex stream being // built up before a flush, and then check that hash against a VB // cache just before creating a vertex buffer in VRAM - std::unordered_map::iterator cache = sVBCache.find(vhash[0]); + std::unordered_map::iterator cache = sVBCache.find(vhash); LLPointer vb; @@ -1705,7 +1705,7 @@ void LLRender::flush() vb->unbind(); - sVBCache[vhash[0]] = { vb , std::chrono::steady_clock::now() }; + sVBCache[vhash] = { vb , std::chrono::steady_clock::now() }; static U32 miss_count = 0; miss_count++; From 4522864f0b12d252a953441bade7fa72a53554b9 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Tue, 31 Jan 2023 17:05:58 -0600 Subject: [PATCH 30/31] SL-18772 Potential fix for failed shader load on Intel HD 3000 --- indra/llrender/llshadermgr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 421b9ee2d6..52509d3d29 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -278,7 +278,7 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) } } - if (features->hasAtmospherics) + if (features->hasAtmospherics || features->isDeferred) { if (!shader->attachFragmentObject("windlight/atmosphericsFuncs.glsl")) { return FALSE; From 4cbdc245ac7c16eb97be8ebaf0e6bd1e8fafb1ca Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Tue, 31 Jan 2023 18:34:47 -0600 Subject: [PATCH 31/31] SL-18154 Followup -- fix mac build --- indra/llrender/llrender.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index cdefefd38e..de74f2700a 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -1717,7 +1717,7 @@ void LLRender::flush() using namespace std::chrono_literals; // every 1024 misses, clean the cache of any VBs that haven't been touched in the last second - for (std::unordered_map::iterator iter = sVBCache.begin(); iter != sVBCache.end(); ) + for (std::unordered_map::iterator iter = sVBCache.begin(); iter != sVBCache.end(); ) { if (now - iter->second.touched > 1s) {