summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rw-r--r--indra/cmake/00-Common.cmake1
-rw-r--r--indra/cmake/CMakeLists.txt1
-rw-r--r--indra/cmake/GLEXT.cmake4
-rw-r--r--indra/cmake/LLCommon.cmake1
-rw-r--r--indra/cmake/LLMath.cmake4
-rw-r--r--indra/cmake/LLRender.cmake2
-rw-r--r--indra/cmake/Mikktspace.cmake6
-rw-r--r--indra/cmake/TinyGLTF.cmake7
-rw-r--r--indra/cmake/Tracy.cmake1
-rw-r--r--indra/cmake/VulkanGltf.cmake5
-rw-r--r--indra/cmake/xxHash.cmake8
-rw-r--r--indra/llappearance/lltexlayer.cpp9
-rw-r--r--indra/llappearance/lltexlayerparams.cpp2
-rw-r--r--indra/llappearance/lltexlayerparams.h2
-rw-r--r--indra/llcommon/CMakeLists.txt6
-rw-r--r--indra/llcommon/commoncontrol.cpp106
-rw-r--r--indra/llcommon/commoncontrol.h75
-rw-r--r--indra/llcommon/hbxxh.cpp377
-rw-r--r--indra/llcommon/hbxxh.h259
-rw-r--r--indra/llcommon/llapr.cpp2
-rw-r--r--indra/llcommon/llassettype.cpp1
-rw-r--r--indra/llcommon/llassettype.h5
-rw-r--r--indra/llcommon/llframetimer.cpp5
-rw-r--r--indra/llcommon/llinstancetracker.h97
-rw-r--r--indra/llcommon/llinstancetrackersubclass.h98
-rw-r--r--indra/llcommon/llmemory.cpp45
-rw-r--r--indra/llcommon/llpointer.h24
-rw-r--r--indra/llcommon/llprofiler.h49
-rw-r--r--indra/llcommon/llqueuedthread.cpp304
-rw-r--r--indra/llcommon/llqueuedthread.h51
-rw-r--r--indra/llcommon/llsys.cpp24
-rw-r--r--indra/llcommon/llsys.h5
-rw-r--r--indra/llcommon/llthread.cpp10
-rw-r--r--indra/llcommon/lltimer.cpp43
-rw-r--r--indra/llcommon/lluuid.cpp28
-rw-r--r--indra/llcommon/llworkerthread.cpp29
-rw-r--r--indra/llcommon/llworkerthread.h11
-rw-r--r--indra/llcommon/tests/workqueue_test.cpp26
-rw-r--r--indra/llcommon/threadpool.cpp122
-rw-r--r--indra/llcommon/threadpool.h80
-rw-r--r--indra/llcommon/threadpool_fwd.h25
-rw-r--r--indra/llcommon/workqueue.cpp194
-rw-r--r--indra/llcommon/workqueue.h410
-rw-r--r--indra/llcorehttp/_httplibcurl.cpp59
-rw-r--r--indra/llcorehttp/_httpoperation.cpp1
-rw-r--r--indra/llcorehttp/_httpoperation.h1
-rw-r--r--indra/llcorehttp/_httpoprequest.cpp48
-rw-r--r--indra/llcorehttp/_httpoprequest.h22
-rw-r--r--indra/llcorehttp/_httpopsetpriority.cpp3
-rw-r--r--indra/llcorehttp/_httpopsetpriority.h6
-rw-r--r--indra/llcorehttp/_httppolicy.cpp31
-rw-r--r--indra/llcorehttp/_httppolicy.h6
-rw-r--r--indra/llcorehttp/_httpservice.cpp32
-rw-r--r--indra/llcorehttp/_httpservice.h9
-rw-r--r--indra/llcorehttp/examples/http_texture_load.cpp4
-rw-r--r--indra/llcorehttp/httprequest.cpp45
-rw-r--r--indra/llcorehttp/httprequest.h30
-rw-r--r--indra/llcorehttp/tests/test_httprequest.hpp20
-rw-r--r--indra/llcrashlogger/llcrashlogger.cpp2
-rw-r--r--indra/llfilesystem/lldiskcache.cpp1
-rw-r--r--indra/llfilesystem/lllfsthread.cpp29
-rw-r--r--indra/llfilesystem/lllfsthread.h13
-rw-r--r--indra/llimage/llimage.cpp51
-rw-r--r--indra/llimage/llimage.h6
-rw-r--r--indra/llimage/llimagej2c.cpp2
-rw-r--r--indra/llimage/llimageworker.cpp122
-rw-r--r--indra/llimage/llimageworker.h65
-rw-r--r--indra/llimage/tests/llimageworker_test.cpp99
-rw-r--r--indra/llimagej2coj/llimagej2coj.cpp1
-rw-r--r--indra/llinventory/llfoldertype.cpp1
-rw-r--r--indra/llinventory/llfoldertype.h4
-rw-r--r--indra/llinventory/llinventorytype.cpp4
-rw-r--r--indra/llinventory/llinventorytype.h5
-rw-r--r--indra/llinventory/llsettingssky.cpp27
-rw-r--r--indra/llinventory/llsettingssky.h10
-rw-r--r--indra/llkdu/llimagej2ckdu.cpp29
-rw-r--r--indra/llmath/llvolume.cpp486
-rw-r--r--indra/llmath/llvolume.h18
-rw-r--r--indra/llmath/v3color.h51
-rw-r--r--indra/llmath/v4color.h41
-rw-r--r--indra/llmessage/llavatarnamecache.cpp2
-rw-r--r--indra/llmessage/llcorehttputil.cpp27
-rw-r--r--indra/llmessage/llcorehttputil.h25
-rw-r--r--indra/llmessage/tests/llcoproceduremanager_test.cpp2
-rw-r--r--indra/llprimitive/CMakeLists.txt9
-rw-r--r--indra/llprimitive/lldaeloader.cpp45
-rw-r--r--indra/llprimitive/lldaeloader.h3
-rw-r--r--indra/llprimitive/llgltfloader.cpp402
-rw-r--r--indra/llprimitive/llgltfloader.h206
-rw-r--r--indra/llprimitive/llgltfmaterial.cpp699
-rw-r--r--indra/llprimitive/llgltfmaterial.h201
-rw-r--r--indra/llprimitive/llmaterial.cpp24
-rw-r--r--indra/llprimitive/llmaterial.h7
-rw-r--r--indra/llprimitive/llmaterialid.cpp7
-rw-r--r--indra/llprimitive/llmaterialid.h1
-rw-r--r--indra/llprimitive/llmodel.cpp64
-rw-r--r--indra/llprimitive/llmodelloader.cpp13
-rw-r--r--indra/llprimitive/llprimitive.cpp264
-rw-r--r--indra/llprimitive/llprimitive.h79
-rw-r--r--indra/llprimitive/lltextureentry.cpp121
-rw-r--r--indra/llprimitive/lltextureentry.h29
-rw-r--r--indra/llprimitive/tests/llmessagesystem_stub.cpp2
-rw-r--r--indra/llprimitive/tests/llprimitive_test.cpp40
-rw-r--r--indra/llrender/CMakeLists.txt2
-rw-r--r--indra/llrender/llatmosphere.cpp8
-rw-r--r--indra/llrender/llcubemap.cpp275
-rw-r--r--indra/llrender/llcubemap.h24
-rw-r--r--indra/llrender/llcubemaparray.cpp177
-rw-r--r--indra/llrender/llcubemaparray.h68
-rw-r--r--indra/llrender/llgl.cpp2831
-rw-r--r--indra/llrender/llgl.h70
-rw-r--r--indra/llrender/llglcommonfunc.cpp5
-rw-r--r--indra/llrender/llglheaders.h1282
-rw-r--r--indra/llrender/llglslshader.cpp1118
-rw-r--r--indra/llrender/llglslshader.h369
-rw-r--r--indra/llrender/llglstates.h41
-rw-r--r--indra/llrender/llimagegl.cpp274
-rw-r--r--indra/llrender/llimagegl.h29
-rw-r--r--indra/llrender/llpostprocess.cpp74
-rw-r--r--indra/llrender/llpostprocess.h4
-rw-r--r--indra/llrender/llrender.cpp299
-rw-r--r--indra/llrender/llrender.h57
-rw-r--r--indra/llrender/llrender2dutils.cpp10
-rw-r--r--indra/llrender/llrendernavprim.cpp2
-rw-r--r--indra/llrender/llrendertarget.cpp904
-rw-r--r--indra/llrender/llrendertarget.h45
-rw-r--r--indra/llrender/llshadermgr.cpp219
-rw-r--r--indra/llrender/llshadermgr.h43
-rw-r--r--indra/llrender/llvertexbuffer.cpp2685
-rw-r--r--indra/llrender/llvertexbuffer.h301
-rw-r--r--indra/llui/llfloater.h1
-rw-r--r--indra/llui/llui.h3
-rw-r--r--indra/llwindow/CMakeLists.txt2
-rw-r--r--indra/llwindow/llopenglview-objc.mm8
-rw-r--r--indra/llwindow/llwindow.cpp7
-rw-r--r--indra/llwindow/llwindow.h10
-rw-r--r--indra/llwindow/llwindowheadless.h135
-rw-r--r--indra/llwindow/llwindowmacosx.cpp10
-rw-r--r--indra/llwindow/llwindowmacosx.h3
-rw-r--r--indra/llwindow/llwindowwin32.cpp428
-rw-r--r--indra/llwindow/llwindowwin32.h8
-rw-r--r--indra/newview/CMakeLists.txt44
-rw-r--r--indra/newview/VIEWER_VERSION.txt2
-rw-r--r--indra/newview/app_settings/high_graphics.xml41
-rw-r--r--indra/newview/app_settings/logcontrol.xml1
-rw-r--r--indra/newview/app_settings/low_graphics.xml41
-rw-r--r--indra/newview/app_settings/mid_graphics.xml41
-rw-r--r--indra/newview/app_settings/settings.xml397
-rw-r--r--indra/newview/app_settings/settings_per_account.xml11
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl298
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/aoUtil.glsl18
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/attachmentAlphaMaskShadowF.glsl64
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/attachmentAlphaShadowF.glsl68
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/attachmentAlphaShadowV.glsl74
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/attachmentShadowV.glsl50
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/avatarAlphaMaskShadowF.glsl10
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/avatarAlphaNoColorV.glsl112
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowF.glsl9
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowV.glsl11
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl12
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl10
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl43
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/blurLightV.glsl6
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/cloudShadowF.glsl127
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/cloudShadowV.glsl63
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl18
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl38
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/cofF.glsl10
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl515
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskNoColorF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/dofCombineF.glsl18
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl37
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyF.glsl4
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyV.glsl11
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl4
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/fxaaF.glsl12
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/genbrdflutF.glsl141
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/genbrdflutV.glsl (renamed from indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl)19
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/highlightF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl3
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl4
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/luminanceV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/materialF.glsl419
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/materialV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/moonF.glsl13
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl116
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/multiPointLightV.glsl4
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl19
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/pbralphaF.glsl34
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/pbralphaV.glsl120
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl103
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/pbropaqueV.glsl97
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl106
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl16
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl49
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl6
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/postDeferredNoTCV.glsl6
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/postDeferredV.glsl6
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl14
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/reflectionProbeF.glsl64
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/screenSpaceReflPostF.glsl (renamed from indra/newview/app_settings/shaders/class1/objects/indexedTextureF.glsl)20
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/screenSpaceReflPostV.glsl (renamed from indra/newview/app_settings/shaders/class3/deferred/sunLightV.glsl)24
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/screenSpaceReflUtil.glsl37
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/shadowAlphaBlendF.glsl55
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/shadowAlphaBlendV.glsl67
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskF.glsl32
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskSkinnedV.glsl4
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskV.glsl4
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/shadowCubeV.glsl10
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl11
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/shadowSkinnedV.glsl9
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/shadowUtil.glsl26
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl15
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/skyF.glsl6
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/skyV.glsl34
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl27
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/softenLightV.glsl6
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl17
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/starsF.glsl10
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/sunDiscF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/sunLightV.glsl6
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/treeF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/treeShadowF.glsl10
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/treeShadowSkinnedV.glsl9
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/treeShadowV.glsl13
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/underWaterF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/waterF.glsl164
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/waterV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl4
-rw-r--r--indra/newview/app_settings/shaders/class1/effects/glowExtractV.glsl4
-rw-r--r--indra/newview/app_settings/shaders/class1/effects/glowV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/environment/moonF.glsl (renamed from indra/newview/app_settings/shaders/class3/deferred/treeShadowF.glsl)38
-rw-r--r--indra/newview/app_settings/shaders/class1/environment/moonV.glsl (renamed from indra/newview/app_settings/shaders/class3/deferred/skyV.glsl)17
-rw-r--r--indra/newview/app_settings/shaders/class1/environment/starsF.glsl (renamed from indra/newview/app_settings/shaders/class3/deferred/shadowAlphaBlendF.glsl)33
-rw-r--r--indra/newview/app_settings/shaders/class1/environment/starsV.glsl (renamed from indra/newview/app_settings/shaders/class3/windlight/advancedAtmoV.glsl)22
-rw-r--r--indra/newview/app_settings/shaders/class1/environment/underWaterF.glsl49
-rw-r--r--indra/newview/app_settings/shaders/class1/environment/waterF.glsl141
-rw-r--r--indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl56
-rw-r--r--indra/newview/app_settings/shaders/class1/environment/waterV.glsl20
-rw-r--r--indra/newview/app_settings/shaders/class1/interface/copyF.glsl (renamed from indra/newview/app_settings/shaders/class1/deferred/attachmentShadowF.glsl)23
-rw-r--r--indra/newview/app_settings/shaders/class1/interface/copyV.glsl (renamed from indra/newview/app_settings/shaders/class3/deferred/pointShadowBlurF.glsl)17
-rw-r--r--indra/newview/app_settings/shaders/class1/interface/downsampleDepthRectF.glsl20
-rw-r--r--indra/newview/app_settings/shaders/class1/interface/downsampleDepthV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/interface/glowcombineF.glsl18
-rw-r--r--indra/newview/app_settings/shaders/class1/interface/glowcombineFXAAF.glsl15
-rw-r--r--indra/newview/app_settings/shaders/class1/interface/glowcombineFXAAV.glsl3
-rw-r--r--indra/newview/app_settings/shaders/class1/interface/glowcombineV.glsl12
-rw-r--r--indra/newview/app_settings/shaders/class1/interface/irradianceGenF.glsl33
-rw-r--r--indra/newview/app_settings/shaders/class1/interface/irradianceGenV.glsl (renamed from indra/newview/app_settings/shaders/class3/deferred/genSkyShV.glsl)19
-rw-r--r--indra/newview/app_settings/shaders/class1/interface/occlusionF.glsl12
-rw-r--r--indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl172
-rw-r--r--indra/newview/app_settings/shaders/class1/interface/radianceGenV.glsl38
-rw-r--r--indra/newview/app_settings/shaders/class1/interface/reflectionmipF.glsl100
-rw-r--r--indra/newview/app_settings/shaders/class1/interface/reflectionprobeF.glsl32
-rw-r--r--indra/newview/app_settings/shaders/class1/interface/reflectionprobeV.glsl (renamed from indra/newview/app_settings/shaders/class3/deferred/shVisV.glsl)15
-rw-r--r--indra/newview/app_settings/shaders/class1/interface/splattexturerectF.glsl4
-rw-r--r--indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl117
-rw-r--r--indra/newview/app_settings/shaders/class1/windlight/cloudShadowF.glsl127
-rw-r--r--indra/newview/app_settings/shaders/class1/windlight/cloudShadowV.glsl61
-rw-r--r--indra/newview/app_settings/shaders/class1/windlight/moonF.glsl10
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl305
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl21
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/pbralphaF.glsl239
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/reflectionProbeF.glsl81
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl27
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl6
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl21
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/sunLightV.glsl6
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/waterF.glsl192
-rw-r--r--indra/newview/app_settings/shaders/class2/environment/waterF.glsl (renamed from indra/newview/app_settings/shaders/class3/deferred/waterF.glsl)68
-rw-r--r--indra/newview/app_settings/shaders/class2/interface/irradianceGenF.glsl218
-rw-r--r--indra/newview/app_settings/shaders/class2/interface/reflectionprobeF.glsl (renamed from indra/newview/app_settings/shaders/class3/deferred/shadowF.glsl)33
-rw-r--r--indra/newview/app_settings/shaders/class2/interface/reflectionprobeV.glsl38
-rw-r--r--indra/newview/app_settings/shaders/class2/windlight/atmosphericsF.glsl10
-rw-r--r--indra/newview/app_settings/shaders/class2/windlight/atmosphericsFuncs.glsl171
-rw-r--r--indra/newview/app_settings/shaders/class2/windlight/cloudsF.glsl20
-rw-r--r--indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl38
-rw-r--r--indra/newview/app_settings/shaders/class2/windlight/gammaF.glsl15
-rw-r--r--indra/newview/app_settings/shaders/class2/windlight/skyF.glsl4
-rw-r--r--indra/newview/app_settings/shaders/class2/windlight/skyV.glsl38
-rw-r--r--indra/newview/app_settings/shaders/class2/windlight/transportF.glsl10
-rw-r--r--indra/newview/app_settings/shaders/class3/avatar/avatarV.glsl134
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/attachmentShadowF.glsl44
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/avatarShadowF.glsl52
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/avatarShadowV.glsl68
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/cloudShadowF.glsl119
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/cloudShadowV.glsl63
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/cloudsF.glsl166
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/cloudsV.glsl70
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/deferredUtil.glsl79
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/depthToShadowVolumeG.glsl202
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/fullbrightShinyF.glsl107
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/gatherSkyShF.glsl70
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/gatherSkyShV.glsl40
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/genSkyShF.glsl111
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/indirect.glsl44
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/materialF.glsl380
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/multiPointLightF.glsl196
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/multiPointLightV.glsl37
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/multiSpotLightF.glsl334
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/pointLightF.glsl158
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/pointLightV.glsl (renamed from indra/newview/app_settings/shaders/class3/deferred/shadowCubeV.glsl)29
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl760
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/screenSpaceReflPostF.glsl98
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/screenSpaceReflPostV.glsl (renamed from indra/newview/app_settings/shaders/class3/deferred/attachmentShadowV.glsl)39
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/screenSpaceReflUtil.glsl234
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/shVisF.glsl73
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/shadowAlphaBlendV.glsl66
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/shadowAlphaMaskF.glsl74
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/shadowAlphaMaskV.glsl67
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/shadowUtil.glsl157
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/shadowV.glsl62
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/skyF.glsl126
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl271
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/spotLightF.glsl362
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/sunLightF.glsl57
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/sunLightSSAOF.glsl61
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/treeShadowV.glsl43
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/waterV.glsl95
-rw-r--r--indra/newview/app_settings/shaders/class3/environment/underWaterF.glsl (renamed from indra/newview/app_settings/shaders/class3/deferred/underWaterF.glsl)70
-rw-r--r--indra/newview/app_settings/shaders/class3/environment/waterF.glsl268
-rw-r--r--indra/newview/app_settings/shaders/class3/windlight/advancedAtmoF.glsl73
-rw-r--r--indra/newview/app_settings/shaders/class3/windlight/atmosphericsV.glsl51
-rw-r--r--indra/newview/app_settings/shaders/class3/windlight/transportF.glsl68
-rw-r--r--indra/newview/app_settings/shaders/shader_hierarchy.txt184
-rw-r--r--indra/newview/app_settings/ultra_graphics.xml42
-rw-r--r--indra/newview/featuretable.txt106
-rw-r--r--indra/newview/featuretable_mac.txt79
-rw-r--r--indra/newview/licenses-mac.txt52
-rw-r--r--indra/newview/licenses-win32.txt49
-rw-r--r--indra/newview/llagentcamera.cpp13
-rw-r--r--indra/newview/llappviewer.cpp187
-rw-r--r--indra/newview/llappviewer.h7
-rw-r--r--indra/newview/llcompilequeue.cpp2
-rw-r--r--indra/newview/llcontrolavatar.cpp5
-rw-r--r--indra/newview/llcontrolavatar.h1
-rw-r--r--indra/newview/lldrawable.cpp16
-rw-r--r--indra/newview/lldrawable.h4
-rw-r--r--indra/newview/lldrawpool.cpp231
-rw-r--r--indra/newview/lldrawpool.h184
-rw-r--r--indra/newview/lldrawpoolalpha.cpp487
-rw-r--r--indra/newview/lldrawpoolalpha.h15
-rw-r--r--indra/newview/lldrawpoolavatar.cpp19
-rw-r--r--indra/newview/lldrawpoolavatar.h6
-rw-r--r--indra/newview/lldrawpoolbump.cpp121
-rw-r--r--indra/newview/lldrawpoolbump.h8
-rw-r--r--indra/newview/lldrawpoolmaterials.cpp234
-rw-r--r--indra/newview/lldrawpoolmaterials.h5
-rw-r--r--indra/newview/lldrawpoolpbropaque.cpp (renamed from indra/newview/app_settings/shaders/class3/windlight/atmosphericsF.glsl)41
-rw-r--r--indra/newview/lldrawpoolpbropaque.h55
-rw-r--r--indra/newview/lldrawpoolsimple.cpp101
-rw-r--r--indra/newview/lldrawpoolsky.cpp28
-rw-r--r--indra/newview/lldrawpoolterrain.cpp22
-rw-r--r--indra/newview/lldrawpoolterrain.h14
-rw-r--r--indra/newview/lldrawpooltree.cpp6
-rw-r--r--indra/newview/lldrawpoolwater.cpp500
-rw-r--r--indra/newview/lldrawpoolwater.h26
-rw-r--r--indra/newview/lldrawpoolwlsky.cpp36
-rw-r--r--indra/newview/lldynamictexture.cpp33
-rw-r--r--indra/newview/llenvironment.cpp62
-rw-r--r--indra/newview/llface.cpp490
-rw-r--r--indra/newview/llface.h16
-rw-r--r--indra/newview/llfasttimerview.cpp2
-rw-r--r--indra/newview/llfeaturemanager.cpp56
-rw-r--r--indra/newview/llfetchedgltfmaterial.cpp149
-rw-r--r--indra/newview/llfetchedgltfmaterial.h65
-rw-r--r--indra/newview/llfilepicker.cpp67
-rw-r--r--indra/newview/llfilepicker.h12
-rw-r--r--indra/newview/llflexibleobject.cpp1
-rw-r--r--indra/newview/llfloaterautoreplacesettings.cpp4
-rw-r--r--indra/newview/llfloaterbulkpermission.cpp1
-rw-r--r--indra/newview/llfloatereditextdaycycle.cpp2
-rw-r--r--indra/newview/llfloaterenvironmentadjust.cpp12
-rw-r--r--indra/newview/llfloaterenvironmentadjust.h2
-rw-r--r--indra/newview/llfloaterfixedenvironment.cpp4
-rw-r--r--indra/newview/llfloaterimagepreview.cpp8
-rw-r--r--indra/newview/llfloaterlagmeter.cpp2
-rw-r--r--indra/newview/llfloaterland.cpp1
-rw-r--r--indra/newview/llfloatermodelpreview.cpp6
-rw-r--r--indra/newview/llfloaterperms.cpp1
-rw-r--r--indra/newview/llfloaterpreference.cpp159
-rw-r--r--indra/newview/llfloaterpreference.h1
-rw-r--r--indra/newview/llfloaterspellchecksettings.cpp2
-rw-r--r--indra/newview/llfloatertexturefetchdebugger.cpp480
-rw-r--r--indra/newview/llfloatertexturefetchdebugger.h77
-rw-r--r--indra/newview/llfloateruipreview.cpp4
-rw-r--r--indra/newview/llglsandbox.cpp40
-rw-r--r--indra/newview/llgltfmateriallist.cpp769
-rw-r--r--indra/newview/llgltfmateriallist.h151
-rw-r--r--indra/newview/llhudeffectlookat.cpp2
-rw-r--r--indra/newview/llhudeffectpointat.cpp2
-rw-r--r--indra/newview/llhudicon.cpp54
-rw-r--r--indra/newview/llhudicon.h5
-rw-r--r--indra/newview/llhudnametag.cpp2
-rw-r--r--indra/newview/llhudobject.cpp8
-rw-r--r--indra/newview/llhudtext.cpp8
-rw-r--r--indra/newview/llinspectobject.cpp14
-rw-r--r--indra/newview/llinventorybridge.cpp85
-rw-r--r--indra/newview/llinventorybridge.h11
-rw-r--r--indra/newview/llinventoryfilter.cpp12
-rw-r--r--indra/newview/llinventoryicon.cpp5
-rw-r--r--indra/newview/llinventorymodel.cpp15
-rw-r--r--indra/newview/llinventorymodel.h2
-rw-r--r--indra/newview/llinventorypanel.cpp67
-rw-r--r--indra/newview/llinventorypanel.h7
-rw-r--r--indra/newview/lllocalbitmaps.cpp66
-rw-r--r--indra/newview/lllocalbitmaps.h4
-rw-r--r--indra/newview/lllocalgltfmaterials.cpp465
-rw-r--r--indra/newview/lllocalgltfmaterials.h118
-rw-r--r--indra/newview/llmaniprotate.cpp2
-rw-r--r--indra/newview/llmanipscale.cpp2
-rw-r--r--indra/newview/llmaniptranslate.cpp26
-rw-r--r--indra/newview/llmaterialeditor.cpp3289
-rw-r--r--indra/newview/llmaterialeditor.h312
-rw-r--r--indra/newview/llmaterialmgr.cpp7
-rw-r--r--indra/newview/llmaterialmgr.h1
-rw-r--r--indra/newview/llmediadataclient.cpp2
-rw-r--r--indra/newview/llmeshrepository.cpp8
-rw-r--r--indra/newview/llmeshrepository.h2
-rw-r--r--indra/newview/llmodelpreview.cpp95
-rw-r--r--indra/newview/lloutfitgallery.cpp3
-rw-r--r--indra/newview/llpaneleditsky.cpp15
-rw-r--r--indra/newview/llpaneleditsky.h1
-rw-r--r--indra/newview/llpaneleditwearable.cpp1
-rw-r--r--indra/newview/llpanelface.cpp1014
-rw-r--r--indra/newview/llpanelface.h84
-rw-r--r--indra/newview/llpanelgroupnotices.cpp1
-rw-r--r--indra/newview/llpanellandmedia.cpp1
-rw-r--r--indra/newview/llpanelmaininventory.cpp18
-rw-r--r--indra/newview/llpanelmaininventory.h1
-rw-r--r--indra/newview/llpanelobject.cpp2
-rw-r--r--indra/newview/llpanelobjectinventory.cpp59
-rw-r--r--indra/newview/llpanelprofile.cpp2
-rw-r--r--indra/newview/llpanelvolume.cpp167
-rw-r--r--indra/newview/llpanelvolume.h3
-rw-r--r--indra/newview/llplacesinventorypanel.h2
-rw-r--r--indra/newview/llpreview.cpp7
-rw-r--r--indra/newview/llpreview.h2
-rw-r--r--indra/newview/llpreviewgesture.cpp8
-rw-r--r--indra/newview/llpreviewnotecard.cpp6
-rw-r--r--indra/newview/llpreviewscript.cpp36
-rw-r--r--indra/newview/llpreviewscript.h1
-rw-r--r--indra/newview/llpreviewtexture.cpp2
-rw-r--r--indra/newview/llreflectionmap.cpp240
-rw-r--r--indra/newview/llreflectionmap.h102
-rw-r--r--indra/newview/llreflectionmapmanager.cpp1024
-rw-r--r--indra/newview/llreflectionmapmanager.h183
-rw-r--r--indra/newview/llscenemonitor.cpp14
-rw-r--r--indra/newview/llselectmgr.cpp331
-rw-r--r--indra/newview/llselectmgr.h21
-rw-r--r--indra/newview/llsettingsvo.cpp102
-rw-r--r--indra/newview/llsidepaneltaskinfo.cpp7
-rw-r--r--indra/newview/llsidepaneltaskinfo.h2
-rw-r--r--indra/newview/llspatialpartition.cpp505
-rw-r--r--indra/newview/llspatialpartition.h170
-rw-r--r--indra/newview/llsprite.cpp7
-rw-r--r--indra/newview/llstartup.cpp8
-rw-r--r--indra/newview/llsurface.cpp7
-rw-r--r--indra/newview/lltexturecache.cpp110
-rw-r--r--indra/newview/lltexturecache.h6
-rw-r--r--indra/newview/lltexturectrl.cpp547
-rw-r--r--indra/newview/lltexturectrl.h41
-rw-r--r--indra/newview/lltexturefetch.cpp1312
-rw-r--r--indra/newview/lltexturefetch.h235
-rw-r--r--indra/newview/lltextureview.cpp52
-rw-r--r--indra/newview/lltinygltfhelper.cpp358
-rw-r--r--indra/newview/lltinygltfhelper.h65
-rw-r--r--indra/newview/lltooldraganddrop.cpp240
-rw-r--r--indra/newview/lltooldraganddrop.h12
-rw-r--r--indra/newview/lltoolpie.cpp9
-rw-r--r--indra/newview/lltoolselect.cpp9
-rw-r--r--indra/newview/llviewerassettype.cpp1
-rw-r--r--indra/newview/llviewerassetupload.cpp114
-rw-r--r--indra/newview/llviewerassetupload.h53
-rw-r--r--indra/newview/llviewercamera.h13
-rw-r--r--indra/newview/llviewercontrol.cpp66
-rw-r--r--indra/newview/llviewerdisplay.cpp406
-rw-r--r--indra/newview/llviewerfloaterreg.cpp9
-rw-r--r--indra/newview/llviewerfoldertype.cpp1
-rw-r--r--indra/newview/llviewerinventory.cpp33
-rw-r--r--indra/newview/llviewerjointmesh.cpp19
-rw-r--r--indra/newview/llviewermenu.cpp267
-rw-r--r--indra/newview/llviewermenu.h5
-rw-r--r--indra/newview/llviewermenufile.cpp136
-rw-r--r--indra/newview/llviewermenufile.h12
-rw-r--r--indra/newview/llviewermessage.cpp6
-rw-r--r--indra/newview/llviewerobject.cpp410
-rw-r--r--indra/newview/llviewerobject.h57
-rw-r--r--indra/newview/llviewerobjectlist.cpp221
-rw-r--r--indra/newview/llviewerobjectlist.h8
-rw-r--r--indra/newview/llvieweroctree.cpp43
-rwxr-xr-xindra/newview/llviewerregion.cpp92
-rw-r--r--indra/newview/llviewerregion.h16
-rw-r--r--indra/newview/llviewershadermgr.cpp1492
-rw-r--r--indra/newview/llviewershadermgr.h31
-rw-r--r--indra/newview/llviewerstats.cpp139
-rw-r--r--indra/newview/llviewerstats.h8
-rw-r--r--indra/newview/llviewertexteditor.cpp26
-rw-r--r--indra/newview/llviewertexteditor.h1
-rw-r--r--indra/newview/llviewertexture.cpp529
-rw-r--r--indra/newview/llviewertexture.h73
-rw-r--r--indra/newview/llviewertexturelist.cpp576
-rw-r--r--indra/newview/llviewertexturelist.h29
-rw-r--r--indra/newview/llviewerwindow.cpp286
-rw-r--r--indra/newview/llviewerwindow.h19
-rw-r--r--indra/newview/llvlcomposition.cpp2
-rw-r--r--indra/newview/llvoavatar.cpp31
-rw-r--r--indra/newview/llvoavatar.h2
-rw-r--r--indra/newview/llvoavatarself.cpp9
-rw-r--r--indra/newview/llvocache.cpp82
-rw-r--r--indra/newview/llvocache.h28
-rw-r--r--indra/newview/llvograss.cpp22
-rw-r--r--indra/newview/llvograss.h1
-rw-r--r--indra/newview/llvoground.cpp6
-rw-r--r--indra/newview/llvoicevisualizer.cpp2
-rw-r--r--indra/newview/llvopartgroup.cpp204
-rw-r--r--indra/newview/llvopartgroup.h10
-rw-r--r--indra/newview/llvosky.cpp28
-rw-r--r--indra/newview/llvosurfacepatch.cpp31
-rw-r--r--indra/newview/llvosurfacepatch.h1
-rw-r--r--indra/newview/llvotree.cpp24
-rw-r--r--indra/newview/llvotree.h1
-rw-r--r--indra/newview/llvovolume.cpp961
-rw-r--r--indra/newview/llvovolume.h192
-rw-r--r--indra/newview/llvowater.cpp21
-rw-r--r--indra/newview/llvowlsky.cpp32
-rw-r--r--indra/newview/llworld.cpp5
-rw-r--r--indra/newview/llxmlrpctransaction.cpp8
-rw-r--r--indra/newview/pipeline.cpp4717
-rw-r--r--indra/newview/pipeline.h192
-rw-r--r--indra/newview/skins/default/textures/default_irradiance.pngbin0 -> 48853 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Material.pngbin0 -> 684 bytes
-rw-r--r--indra/newview/skins/default/textures/textures.xml1
-rw-r--r--indra/newview/skins/default/xui/da/floater_about.xml1
-rw-r--r--indra/newview/skins/default/xui/de/floater_about.xml1
-rw-r--r--indra/newview/skins/default/xui/en/floater_about.xml1
-rw-r--r--indra/newview/skins/default/xui/en/floater_adjust_environment.xml19
-rw-r--r--indra/newview/skins/default/xui/en/floater_build_options.xml4
-rw-r--r--indra/newview/skins/default/xui/en/floater_combobox_ok_cancel.xml48
-rw-r--r--indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml43
-rw-r--r--indra/newview/skins/default/xui/en/floater_live_material_editor.xml39
-rw-r--r--indra/newview/skins/default/xui/en/floater_material_editor.xml123
-rw-r--r--indra/newview/skins/default/xui/en/floater_my_environments.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_perms_default.xml68
-rw-r--r--indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml294
-rw-r--r--indra/newview/skins/default/xui/en/floater_settings_picker.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_stats.xml6
-rw-r--r--indra/newview/skins/default/xui/en/floater_texture_ctrl.xml39
-rw-r--r--indra/newview/skins/default/xui/en/floater_texture_fetch_debugger.xml440
-rw-r--r--indra/newview/skins/default/xui/en/floater_tools.xml71
-rw-r--r--indra/newview/skins/default/xui/en/menu_attachment_self.xml16
-rw-r--r--indra/newview/skins/default/xui/en/menu_inventory.xml537
-rw-r--r--indra/newview/skins/default/xui/en/menu_inventory_add.xml34
-rw-r--r--indra/newview/skins/default/xui/en/menu_object.xml16
-rw-r--r--indra/newview/skins/default/xui/en/menu_viewer.xml95
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml119
-rw-r--r--indra/newview/skins/default/xui/en/panel_gltf_material.xml392
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml30
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_uploads.xml25
-rw-r--r--indra/newview/skins/default/xui/en/panel_settings_sky_atmos.xml23
-rw-r--r--indra/newview/skins/default/xui/en/panel_tools_texture.xml169
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml14
-rw-r--r--indra/newview/skins/default/xui/es/floater_about.xml1
-rw-r--r--indra/newview/skins/default/xui/fr/floater_about.xml1
-rw-r--r--indra/newview/skins/default/xui/it/floater_about.xml1
-rw-r--r--indra/newview/skins/default/xui/ja/floater_about.xml1
-rw-r--r--indra/newview/skins/default/xui/pt/floater_about.xml1
-rw-r--r--indra/newview/skins/default/xui/ru/floater_about.xml1
-rw-r--r--indra/newview/skins/default/xui/tr/floater_about.xml1
-rw-r--r--indra/newview/skins/default/xui/zh/floater_about.xml1
-rw-r--r--indra/newview/tests/llviewercontrollistener_test.cpp174
-rw-r--r--indra/test/test.cpp2
580 files changed, 37185 insertions, 25651 deletions
diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake
index 572422d080..d81d3ac1f0 100644
--- a/indra/cmake/00-Common.cmake
+++ b/indra/cmake/00-Common.cmake
@@ -232,3 +232,4 @@ else (USESYSTEMLIBS)
endif (USESYSTEMLIBS)
endif(NOT DEFINED ${CMAKE_CURRENT_LIST_FILE}_INCLUDED)
+
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/GLEXT.cmake b/indra/cmake/GLEXT.cmake
index 9fd3923bfd..a749644202 100644
--- a/indra/cmake/GLEXT.cmake
+++ b/indra/cmake/GLEXT.cmake
@@ -2,9 +2,7 @@
include(Prebuilt)
if (NOT USESYSTEMLIBS)
- if (WINDOWS OR LINUX)
- use_prebuilt_binary(glext)
- endif (WINDOWS OR LINUX)
+ use_prebuilt_binary(glext)
use_prebuilt_binary(glh_linear)
set(GLEXT_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include)
endif (NOT USESYSTEMLIBS)
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/LLMath.cmake b/indra/cmake/LLMath.cmake
index 893920ae6f..513ff9f81d 100644
--- a/indra/cmake/LLMath.cmake
+++ b/indra/cmake/LLMath.cmake
@@ -1,5 +1,9 @@
# -*- cmake -*-
+include(Variables)
+include(Mikktspace)
+include(MESHOPTIMIZER)
+
set(LLMATH_INCLUDE_DIRS
${LIBS_OPEN_DIR}/llmath
)
diff --git a/indra/cmake/LLRender.cmake b/indra/cmake/LLRender.cmake
index 868922451f..2d9d3725ad 100644
--- a/indra/cmake/LLRender.cmake
+++ b/indra/cmake/LLRender.cmake
@@ -3,10 +3,12 @@
include(Variables)
include(FreeType)
include(GLH)
+include(GLEXT)
set(LLRENDER_INCLUDE_DIRS
${LIBS_OPEN_DIR}/llrender
${GLH_INCLUDE_DIR}
+ ${GLEXT_INCLUDE_DIR}
)
if (BUILD_HEADLESS)
diff --git a/indra/cmake/Mikktspace.cmake b/indra/cmake/Mikktspace.cmake
new file mode 100644
index 0000000000..9fd2becba4
--- /dev/null
+++ b/indra/cmake/Mikktspace.cmake
@@ -0,0 +1,6 @@
+# -*- cmake -*-
+include(Prebuilt)
+
+if (NOT USESYSTEMLIBS)
+ use_prebuilt_binary(mikktspace)
+endif (NOT USESYSTEMLIBS)
diff --git a/indra/cmake/TinyGLTF.cmake b/indra/cmake/TinyGLTF.cmake
new file mode 100644
index 0000000000..bb731637a0
--- /dev/null
+++ b/indra/cmake/TinyGLTF.cmake
@@ -0,0 +1,7 @@
+# -*- cmake -*-
+include(Prebuilt)
+
+use_prebuilt_binary(tinygltf)
+
+set(TINYGLTF_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/tinygltf)
+
diff --git a/indra/cmake/Tracy.cmake b/indra/cmake/Tracy.cmake
index cfff956bcf..dba57eb920 100644
--- a/indra/cmake/Tracy.cmake
+++ b/indra/cmake/Tracy.cmake
@@ -12,6 +12,7 @@ if (USE_TRACY)
if (WINDOWS)
MESSAGE(STATUS "Including Tracy for Windows: '${TRACY_INCLUDE_DIR}'")
+ set(TRACY_LIBRARY "TracyClient")
endif (WINDOWS)
if (DARWIN)
diff --git a/indra/cmake/VulkanGltf.cmake b/indra/cmake/VulkanGltf.cmake
new file mode 100644
index 0000000000..94541d5307
--- /dev/null
+++ b/indra/cmake/VulkanGltf.cmake
@@ -0,0 +1,5 @@
+# -*- cmake -*-
+include(Prebuilt)
+
+use_prebuilt_binary(vulkan_gltf)
+
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/llappearance/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp
index 3430a25536..e1a3a83841 100644
--- a/indra/llappearance/lltexlayer.cpp
+++ b/indra/llappearance/lltexlayer.cpp
@@ -1509,7 +1509,14 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
}
else
{ // platforms with working drivers...
- glReadPixels(x, y, width, height, GL_ALPHA, GL_UNSIGNED_BYTE, alpha_data);
+ // We just want GL_ALPHA, but that isn't supported in OGL core profile 4.
+ static const size_t TEMP_BYTES_PER_PIXEL = 4;
+ U8* temp_data = (U8*)ll_aligned_malloc_32(mem_size * TEMP_BYTES_PER_PIXEL);
+ glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, temp_data);
+ for (size_t pixel = 0; pixel < pixels; pixel++) {
+ alpha_data[pixel] = temp_data[(pixel * TEMP_BYTES_PER_PIXEL) + 3];
+ }
+ ll_aligned_free_32(temp_data);
}
}
else
diff --git a/indra/llappearance/lltexlayerparams.cpp b/indra/llappearance/lltexlayerparams.cpp
index ce5c7142d5..06b4f6c75a 100644
--- a/indra/llappearance/lltexlayerparams.cpp
+++ b/indra/llappearance/lltexlayerparams.cpp
@@ -151,7 +151,7 @@ LLTexLayerParamAlpha::LLTexLayerParamAlpha(const LLTexLayerParamAlpha& pOther)
mCachedProcessedTexture(pOther.mCachedProcessedTexture),
mStaticImageTGA(pOther.mStaticImageTGA),
mStaticImageRaw(pOther.mStaticImageRaw),
- mNeedsCreateTexture(pOther.mNeedsCreateTexture),
+ mNeedsCreateTexture(pOther.mNeedsCreateTexture.load()),
mStaticImageInvalid(pOther.mStaticImageInvalid),
mAvgDistortionVec(pOther.mAvgDistortionVec),
mCachedEffectiveWeight(pOther.mCachedEffectiveWeight)
diff --git a/indra/llappearance/lltexlayerparams.h b/indra/llappearance/lltexlayerparams.h
index e2440998b3..000f55685e 100644
--- a/indra/llappearance/lltexlayerparams.h
+++ b/indra/llappearance/lltexlayerparams.h
@@ -100,7 +100,7 @@ private:
LLPointer<LLGLTexture> mCachedProcessedTexture;
LLPointer<LLImageTGA> mStaticImageTGA;
LLPointer<LLImageRaw> mStaticImageRaw;
- BOOL mNeedsCreateTexture;
+ std::atomic<BOOL> mNeedsCreateTexture;
BOOL mStaticImageInvalid;
LL_ALIGN_16(LLVector4a mAvgDistortionVec);
F32 mCachedEffectiveWeight;
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 108149b5f7..fab7550c9a 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -29,6 +29,7 @@ include_directories(
# ${LLCOMMON_LIBRARIES})
set(llcommon_SOURCE_FILES
+ commoncontrol.cpp
indra_constants.cpp
llallocator.cpp
llallocator_heap_profile.cpp
@@ -118,6 +119,7 @@ set(llcommon_SOURCE_FILES
lluriparser.cpp
lluuid.cpp
llworkerthread.cpp
+ hbxxh.cpp
u64.cpp
threadpool.cpp
workqueue.cpp
@@ -129,6 +131,7 @@ set(llcommon_HEADER_FILES
chrono.h
classic_callback.h
+ commoncontrol.h
ctype_workaround.h
fix_macros.h
indra_constants.h
@@ -186,6 +189,7 @@ set(llcommon_HEADER_FILES
llinitdestroyclass.h
llinitparam.h
llinstancetracker.h
+ llinstancetrackersubclass.h
llkeybind.h
llkeythrottle.h
llleap.h
@@ -254,10 +258,12 @@ set(llcommon_HEADER_FILES
llwin32headers.h
llwin32headerslean.h
llworkerthread.h
+ hbxxh.h
lockstatic.h
stdtypes.h
stringize.h
threadpool.h
+ threadpool_fwd.h
threadsafeschedule.h
timer.h
tuple.h
diff --git a/indra/llcommon/commoncontrol.cpp b/indra/llcommon/commoncontrol.cpp
new file mode 100644
index 0000000000..81e66baf8c
--- /dev/null
+++ b/indra/llcommon/commoncontrol.cpp
@@ -0,0 +1,106 @@
+/**
+ * @file commoncontrol.cpp
+ * @author Nat Goodspeed
+ * @date 2022-06-08
+ * @brief Implementation for commoncontrol.
+ *
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
+ * Copyright (c) 2022, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "commoncontrol.h"
+// STL headers
+// std headers
+// external library headers
+// other Linden headers
+#include "llevents.h"
+#include "llsdutil.h"
+
+LLSD LL::CommonControl::access(const LLSD& params)
+{
+ // We can't actually introduce a link-time dependency on llxml, or on any
+ // global LLControlGroup (*koff* gSavedSettings *koff*) but we can issue a
+ // runtime query. If we're running as part of a viewer with
+ // LLViewerControlListener, we can use that to interact with any
+ // instantiated LLControGroup.
+ LLSD response;
+ {
+ LLEventStream reply("reply");
+ LLTempBoundListener connection = reply.listen("listener",
+ [&response] (const LLSD& event)
+ {
+ response = event;
+ return false;
+ });
+ LLSD rparams{ params };
+ rparams["reply"] = reply.getName();
+ LLEventPumps::instance().obtain("LLViewerControl").post(rparams);
+ }
+ // LLViewerControlListener responds immediately. If it's listening at all,
+ // it will already have set response.
+ if (! response.isDefined())
+ {
+ LLTHROW(NoListener("No LLViewerControl listener instantiated"));
+ }
+ LLSD error{ response["error"] };
+ if (error.isDefined())
+ {
+ LLTHROW(ParamError(error));
+ }
+ response.erase("error");
+ response.erase("reqid");
+ return response;
+}
+
+/// set control group.key to defined default value
+LLSD LL::CommonControl::set_default(const std::string& group, const std::string& key)
+{
+ return access(llsd::map("op", "set",
+ "group", group, "key", key))["value"];
+}
+
+/// set control group.key to specified value
+LLSD LL::CommonControl::set(const std::string& group, const std::string& key, const LLSD& value)
+{
+ return access(llsd::map("op", "set",
+ "group", group, "key", key, "value", value))["value"];
+}
+
+/// toggle boolean control group.key
+LLSD LL::CommonControl::toggle(const std::string& group, const std::string& key)
+{
+ return access(llsd::map("op", "toggle",
+ "group", group, "key", key))["value"];
+}
+
+/// get the definition for control group.key, (! isDefined()) if bad
+/// ["name"], ["type"], ["value"], ["comment"]
+LLSD LL::CommonControl::get_def(const std::string& group, const std::string& key)
+{
+ return access(llsd::map("op", "get",
+ "group", group, "key", key));
+}
+
+/// get the value of control group.key
+LLSD LL::CommonControl::get(const std::string& group, const std::string& key)
+{
+ return access(llsd::map("op", "get",
+ "group", group, "key", key))["value"];
+}
+
+/// get defined groups
+std::vector<std::string> LL::CommonControl::get_groups()
+{
+ auto groups{ access(llsd::map("op", "groups"))["groups"] };
+ return { groups.beginArray(), groups.endArray() };
+}
+
+/// get definitions for all variables in group
+LLSD LL::CommonControl::get_vars(const std::string& group)
+{
+ return access(llsd::map("op", "vars", "group", group))["vars"];
+}
diff --git a/indra/llcommon/commoncontrol.h b/indra/llcommon/commoncontrol.h
new file mode 100644
index 0000000000..07d4a45ac5
--- /dev/null
+++ b/indra/llcommon/commoncontrol.h
@@ -0,0 +1,75 @@
+/**
+ * @file commoncontrol.h
+ * @author Nat Goodspeed
+ * @date 2022-06-08
+ * @brief Access LLViewerControl LLEventAPI, if process has one.
+ *
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
+ * Copyright (c) 2022, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_COMMONCONTROL_H)
+#define LL_COMMONCONTROL_H
+
+#include <vector>
+#include "llexception.h"
+#include "llsd.h"
+
+namespace LL
+{
+ class CommonControl
+ {
+ public:
+ struct Error: public LLException
+ {
+ Error(const std::string& what): LLException(what) {}
+ };
+
+ /// Exception thrown if there's no LLViewerControl LLEventAPI
+ struct NoListener: public Error
+ {
+ NoListener(const std::string& what): Error(what) {}
+ };
+
+ struct ParamError: public Error
+ {
+ ParamError(const std::string& what): Error(what) {}
+ };
+
+ /// set control group.key to defined default value
+ static
+ LLSD set_default(const std::string& group, const std::string& key);
+
+ /// set control group.key to specified value
+ static
+ LLSD set(const std::string& group, const std::string& key, const LLSD& value);
+
+ /// toggle boolean control group.key
+ static
+ LLSD toggle(const std::string& group, const std::string& key);
+
+ /// get the definition for control group.key, (! isDefined()) if bad
+ /// ["name"], ["type"], ["value"], ["comment"]
+ static
+ LLSD get_def(const std::string& group, const std::string& key);
+
+ /// get the value of control group.key
+ static
+ LLSD get(const std::string& group, const std::string& key);
+
+ /// get defined groups
+ static
+ std::vector<std::string> get_groups();
+
+ /// get definitions for all variables in group
+ static
+ LLSD get_vars(const std::string& group);
+
+ private:
+ static
+ LLSD access(const LLSD& params);
+ };
+} // namespace LL
+
+#endif /* ! defined(LL_COMMONCONTROL_H) */
diff --git a/indra/llcommon/hbxxh.cpp b/indra/llcommon/hbxxh.cpp
new file mode 100644
index 0000000000..388269d6c8
--- /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=viewerlgpl$
+ * 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/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..236716722a
--- /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=viewerlgpl$
+ * 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/llapr.cpp b/indra/llcommon/llapr.cpp
index 435531f86f..e49f72722b 100644
--- a/indra/llcommon/llapr.cpp
+++ b/indra/llcommon/llapr.cpp
@@ -522,6 +522,7 @@ S32 LLAPRFile::seek(apr_file_t* file_handle, apr_seek_where_t where, S32 offset)
//static
S32 LLAPRFile::readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool)
{
+ LL_PROFILE_ZONE_SCOPED;
//*****************************************
LLAPRFilePoolScope scope(pool);
apr_file_t* file_handle = open(filename, scope.getVolatileAPRPool(), APR_READ|APR_BINARY);
@@ -566,6 +567,7 @@ S32 LLAPRFile::readEx(const std::string& filename, void *buf, S32 offset, S32 nb
//static
S32 LLAPRFile::writeEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool)
{
+ LL_PROFILE_ZONE_SCOPED;
apr_int32_t flags = APR_CREATE|APR_WRITE|APR_BINARY;
if (offset < 0)
{
diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp
index e6cc06e8d0..f08cc18036 100644
--- a/indra/llcommon/llassettype.cpp
+++ b/indra/llcommon/llassettype.cpp
@@ -96,6 +96,7 @@ LLAssetDictionary::LLAssetDictionary()
addEntry(LLAssetType::AT_WIDGET, new AssetEntry("WIDGET", "widget", "widget", false, false, false));
addEntry(LLAssetType::AT_PERSON, new AssetEntry("PERSON", "person", "person", false, false, false));
addEntry(LLAssetType::AT_SETTINGS, new AssetEntry("SETTINGS", "settings", "settings blob", true, true, true));
+ addEntry(LLAssetType::AT_MATERIAL, new AssetEntry("MATERIAL", "material", "render material", true, true, true));
addEntry(LLAssetType::AT_UNKNOWN, new AssetEntry("UNKNOWN", "invalid", NULL, false, false, false));
addEntry(LLAssetType::AT_NONE, new AssetEntry("NONE", "-1", NULL, FALSE, FALSE, FALSE));
diff --git a/indra/llcommon/llassettype.h b/indra/llcommon/llassettype.h
index 652c548d59..e8df8574f7 100644
--- a/indra/llcommon/llassettype.h
+++ b/indra/llcommon/llassettype.h
@@ -127,8 +127,9 @@ public:
AT_RESERVED_6 = 55,
AT_SETTINGS = 56, // Collection of settings
-
- AT_COUNT = 57,
+ AT_MATERIAL = 57, // Render Material
+
+ AT_COUNT = 58,
// +*********************************************************+
// | TO ADD AN ELEMENT TO THIS ENUM: |
diff --git a/indra/llcommon/llframetimer.cpp b/indra/llcommon/llframetimer.cpp
index c54029e8b4..1e9920746b 100644
--- a/indra/llcommon/llframetimer.cpp
+++ b/indra/llcommon/llframetimer.cpp
@@ -29,11 +29,6 @@
#include "llframetimer.h"
-// We don't bother building a stand alone lib; we just need to include the one source file for Tracy support
-#if LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY || LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY_FAST_TIMER
- #include "TracyClient.cpp"
-#endif // LL_PROFILER_CONFIGURATION
-
// Static members
//LLTimer LLFrameTimer::sInternalTimer;
U64 LLFrameTimer::sStartTotalTime = totalTime();
diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h
index 02535a59e7..97f7817e74 100644
--- a/indra/llcommon/llinstancetracker.h
+++ b/indra/llcommon/llinstancetracker.h
@@ -104,22 +104,26 @@ public:
return LockStatic()->mMap.size();
}
- // snapshot of std::pair<const KEY, std::shared_ptr<T>> pairs
- class snapshot
+ // snapshot of std::pair<const KEY, std::shared_ptr<SUBCLASS>> pairs, for
+ // some SUBCLASS derived from T
+ template <typename SUBCLASS>
+ class snapshot_of
{
// It's very important that what we store in this snapshot are
// weak_ptrs, NOT shared_ptrs. That's how we discover whether any
// instance has been deleted during the lifespan of a snapshot.
typedef std::vector<std::pair<const KEY, weak_t>> VectorType;
- // Dereferencing our iterator produces a std::shared_ptr for each
- // instance that still exists. Since we store weak_ptrs, that involves
- // two chained transformations:
+ // Dereferencing the iterator we publish produces a
+ // std::shared_ptr<SUBCLASS> for each instance that still exists.
+ // Since we store weak_ptr<T>, that involves two chained
+ // transformations:
// - a transform_iterator to lock the weak_ptr and return a shared_ptr
- // - a filter_iterator to skip any shared_ptr that has become invalid.
+ // - a filter_iterator to skip any shared_ptr<T> that has become
+ // invalid or references any T instance that isn't SUBCLASS.
// It is very important that we filter lazily, that is, during
// traversal. Any one of our stored weak_ptrs might expire during
// traversal.
- typedef std::pair<const KEY, ptr_t> strong_pair;
+ typedef std::pair<const KEY, std::shared_ptr<SUBCLASS>> strong_pair;
// Note for future reference: nat has not yet had any luck (up to
// Boost 1.67) trying to use boost::transform_iterator with a hand-
// coded functor, only with actual functions. In my experience, an
@@ -127,7 +131,7 @@ public:
// result_type typedef. But this works.
static strong_pair strengthen(typename VectorType::value_type& pair)
{
- return { pair.first, pair.second.lock() };
+ return { pair.first, std::dynamic_pointer_cast<SUBCLASS>(pair.second.lock()) };
}
static bool dead_skipper(const strong_pair& pair)
{
@@ -135,7 +139,7 @@ public:
}
public:
- snapshot():
+ snapshot_of():
// populate our vector with a snapshot of (locked!) InstanceMap
// note, this assigns pair<KEY, shared_ptr> to pair<KEY, weak_ptr>
mData(mLock->mMap.begin(), mLock->mMap.end())
@@ -184,44 +188,51 @@ public:
#endif // LL_WINDOWS
VectorType mData;
};
+ using snapshot = snapshot_of<T>;
- // iterate over this for references to each instance
- class instance_snapshot: public snapshot
+ // iterate over this for references to each SUBCLASS instance
+ template <typename SUBCLASS>
+ class instance_snapshot_of: public snapshot_of<SUBCLASS>
{
private:
- static T& instance_getter(typename snapshot::iterator::reference pair)
+ using super = snapshot_of<SUBCLASS>;
+ static T& instance_getter(typename super::iterator::reference pair)
{
return *pair.second;
}
public:
typedef boost::transform_iterator<decltype(instance_getter)*,
- typename snapshot::iterator> iterator;
- iterator begin() { return iterator(snapshot::begin(), instance_getter); }
- iterator end() { return iterator(snapshot::end(), instance_getter); }
+ typename super::iterator> iterator;
+ iterator begin() { return iterator(super::begin(), instance_getter); }
+ iterator end() { return iterator(super::end(), instance_getter); }
void deleteAll()
{
- for (auto it(snapshot::begin()), end(snapshot::end()); it != end; ++it)
+ for (auto it(super::begin()), end(super::end()); it != end; ++it)
{
delete it->second.get();
}
}
- };
+ };
+ using instance_snapshot = instance_snapshot_of<T>;
// iterate over this for each key
- class key_snapshot: public snapshot
+ template <typename SUBCLASS>
+ class key_snapshot_of: public snapshot_of<SUBCLASS>
{
private:
- static KEY key_getter(typename snapshot::iterator::reference pair)
+ using super = snapshot_of<SUBCLASS>;
+ static KEY key_getter(typename super::iterator::reference pair)
{
return pair.first;
}
public:
typedef boost::transform_iterator<decltype(key_getter)*,
- typename snapshot::iterator> iterator;
- iterator begin() { return iterator(snapshot::begin(), key_getter); }
- iterator end() { return iterator(snapshot::end(), key_getter); }
+ typename super::iterator> iterator;
+ iterator begin() { return iterator(super::begin(), key_getter); }
+ iterator end() { return iterator(super::end(), key_getter); }
};
+ using key_snapshot = key_snapshot_of<T>;
static ptr_t getInstance(const KEY& k)
{
@@ -368,22 +379,25 @@ public:
return LockStatic()->mSet.size();
}
- // snapshot of std::shared_ptr<T> pointers
- class snapshot
+ // snapshot of std::shared_ptr<SUBCLASS> pointers
+ template <typename SUBCLASS>
+ class snapshot_of
{
// It's very important that what we store in this snapshot are
// weak_ptrs, NOT shared_ptrs. That's how we discover whether any
// instance has been deleted during the lifespan of a snapshot.
typedef std::vector<weak_t> VectorType;
- // Dereferencing our iterator produces a std::shared_ptr for each
- // instance that still exists. Since we store weak_ptrs, that involves
- // two chained transformations:
+ // Dereferencing the iterator we publish produces a
+ // std::shared_ptr<SUBCLASS> for each instance that still exists.
+ // Since we store weak_ptrs, that involves two chained
+ // transformations:
// - a transform_iterator to lock the weak_ptr and return a shared_ptr
- // - a filter_iterator to skip any shared_ptr that has become invalid.
- typedef std::shared_ptr<T> strong_ptr;
+ // - a filter_iterator to skip any shared_ptr that has become invalid
+ // or references any T instance that isn't SUBCLASS.
+ typedef std::shared_ptr<SUBCLASS> strong_ptr;
static strong_ptr strengthen(typename VectorType::value_type& ptr)
{
- return ptr.lock();
+ return std::dynamic_pointer_cast<SUBCLASS>(ptr.lock());
}
static bool dead_skipper(const strong_ptr& ptr)
{
@@ -391,7 +405,7 @@ public:
}
public:
- snapshot():
+ snapshot_of():
// populate our vector with a snapshot of (locked!) InstanceSet
// note, this assigns stored shared_ptrs to weak_ptrs for snapshot
mData(mLock->mSet.begin(), mLock->mSet.end())
@@ -437,22 +451,33 @@ public:
#endif // LL_WINDOWS
VectorType mData;
};
+ using snapshot = snapshot_of<T>;
// iterate over this for references to each instance
- struct instance_snapshot: public snapshot
+ template <typename SUBCLASS>
+ class instance_snapshot_of: public snapshot_of<SUBCLASS>
{
- typedef boost::indirect_iterator<typename snapshot::iterator> iterator;
- iterator begin() { return iterator(snapshot::begin()); }
- iterator end() { return iterator(snapshot::end()); }
+ private:
+ using super = snapshot_of<SUBCLASS>;
+
+ public:
+ typedef boost::indirect_iterator<typename super::iterator> iterator;
+ iterator begin() { return iterator(super::begin()); }
+ iterator end() { return iterator(super::end()); }
void deleteAll()
{
- for (auto it(snapshot::begin()), end(snapshot::end()); it != end; ++it)
+ for (auto it(super::begin()), end(super::end()); it != end; ++it)
{
delete it->get();
}
}
};
+ using instance_snapshot = instance_snapshot_of<T>;
+ // key_snapshot_of isn't really meaningful, but define it anyway to avoid
+ // requiring two different LLInstanceTrackerSubclass implementations.
+ template <typename SUBCLASS>
+ using key_snapshot_of = instance_snapshot_of<SUBCLASS>;
protected:
LLInstanceTracker()
diff --git a/indra/llcommon/llinstancetrackersubclass.h b/indra/llcommon/llinstancetrackersubclass.h
new file mode 100644
index 0000000000..ea9a38200f
--- /dev/null
+++ b/indra/llcommon/llinstancetrackersubclass.h
@@ -0,0 +1,98 @@
+/**
+ * @file llinstancetrackersubclass.h
+ * @author Nat Goodspeed
+ * @date 2022-12-09
+ * @brief Intermediate class to get subclass-specific types from
+ * LLInstanceTracker instance-retrieval methods.
+ *
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
+ * Copyright (c) 2022, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLINSTANCETRACKERSUBCLASS_H)
+#define LL_LLINSTANCETRACKERSUBCLASS_H
+
+#include <memory> // std::shared_ptr, std::weak_ptr
+
+/**
+ * Derive your subclass S of a subclass T of LLInstanceTracker<T> from
+ * LLInstanceTrackerSubclass<S, T> to perform appropriate downcasting and
+ * filtering for LLInstanceTracker access methods.
+ *
+ * LLInstanceTracker<T> uses CRTP, so that getWeak(), getInstance(), snapshot
+ * and instance_snapshot return pointers and references to T. The trouble is
+ * that subclasses T0 and T1 derived from T also get pointers and references
+ * to their base class T, requiring explicit downcasting. Moreover,
+ * T0::getInstance() shouldn't find an instance of any T subclass other than
+ * T0. Nor should T0::snapshot.
+ *
+ * @code
+ * class Tracked: public LLInstanceTracker<Tracked, std::string>
+ * {
+ * private:
+ * using super = LLInstanceTracker<Tracked, std::string>;
+ * public:
+ * Tracked(const std::string& name): super(name) {}
+ * // All references to Tracked::ptr_t, Tracked::getInstance() etc.
+ * // appropriately use Tracked.
+ * // ...
+ * };
+ *
+ * // But now we derive SubTracked from Tracked. We need SubTracked::ptr_t,
+ * // SubTracked::getInstance() etc. to use SubTracked, not Tracked.
+ * // This LLInstanceTrackerSubclass specialization is itself derived from
+ * // Tracked.
+ * class SubTracked: public LLInstanceTrackerSubclass<SubTracked, Tracked>
+ * {
+ * private:
+ * using super = LLInstanceTrackerSubclass<SubTracked, Tracked>;
+ * public:
+ * // LLInstanceTrackerSubclass's constructor forwards to Tracked's.
+ * SubTracked(const std::string& name): super(name) {}
+ * // SubTracked::getInstance() returns std::shared_ptr<SubTracked>, etc.
+ * // ...
+ * @endcode
+ */
+template <typename SUBCLASS, typename T>
+class LLInstanceTrackerSubclass: public T
+{
+public:
+ using ptr_t = std::shared_ptr<SUBCLASS>;
+ using weak_t = std::weak_ptr<SUBCLASS>;
+
+ // forward any constructor call to the corresponding T ctor
+ template <typename... ARGS>
+ LLInstanceTrackerSubclass(ARGS&&... args):
+ T(std::forward<ARGS>(args)...)
+ {}
+
+ weak_t getWeak()
+ {
+ // call base-class getWeak(), try to lock, downcast to SUBCLASS
+ return std::dynamic_pointer_cast<SUBCLASS>(T::getWeak().lock());
+ }
+
+ template <typename KEY>
+ static ptr_t getInstance(const KEY& k)
+ {
+ return std::dynamic_pointer_cast<SUBCLASS>(T::getInstance(k));
+ }
+
+ using snapshot = typename T::template snapshot_of<SUBCLASS>;
+ using instance_snapshot = typename T::template instance_snapshot_of<SUBCLASS>;
+ using key_snapshot = typename T::template key_snapshot_of<SUBCLASS>;
+
+ static size_t instanceCount()
+ {
+ // T::instanceCount() lies because our snapshot, et al., won't
+ // necessarily return all the T instances -- only those that are also
+ // SUBCLASS instances. Count those.
+ size_t count = 0;
+ for (const auto& pair : snapshot())
+ ++count;
+ return count;
+ }
+};
+
+#endif /* ! defined(LL_LLINSTANCETRACKERSUBCLASS_H) */
diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp
index d6ae1284d3..7cdf7254ff 100644
--- a/indra/llcommon/llmemory.cpp
+++ b/indra/llcommon/llmemory.cpp
@@ -35,6 +35,7 @@
# include <sys/types.h>
# include <mach/task.h>
# include <mach/mach_init.h>
+#include <mach/mach_host.h>
#elif LL_LINUX
# include <unistd.h>
#endif
@@ -109,6 +110,50 @@ void LLMemory::updateMemoryInfo()
{
sAvailPhysicalMemInKB = U32Kilobytes(0);
}
+
+#elif defined(LL_DARWIN)
+ task_vm_info info;
+ mach_msg_type_number_t infoCount = TASK_VM_INFO_COUNT;
+ // MACH_TASK_BASIC_INFO reports the same resident_size, but does not tell us the reusable bytes or phys_footprint.
+ if (task_info(mach_task_self(), TASK_VM_INFO, reinterpret_cast<task_info_t>(&info), &infoCount) == KERN_SUCCESS)
+ {
+ // Our Windows definition of PagefileUsage is documented by Microsoft as "the total amount of
+ // memory that the memory manager has committed for a running process", which is rss.
+ sAllocatedPageSizeInKB = U32Bytes(info.resident_size);
+
+ // Activity Monitor => Inspect Process => Real Memory Size appears to report resident_size
+ // Activity monitor => main window memory column appears to report phys_footprint, which spot checks as at least 30% less.
+ // I think that is because of compression, which isn't going to give us a consistent measurement. We want uncompressed totals.
+ //
+ // In between is resident_size - reusable. This is what Chrome source code uses, with source comments saying it is 'the "Real Memory" value
+ // reported for the app by the Memory Monitor in Instruments.' It is still about 8% bigger than phys_footprint.
+ //
+ // (On Windows, we use WorkingSetSize.)
+ sAllocatedMemInKB = U32Bytes(info.resident_size - info.reusable);
+ }
+ else
+ {
+ LL_WARNS() << "task_info failed" << LL_ENDL;
+ }
+
+ // Total installed and available physical memory are properties of the host, not just our process.
+ vm_statistics64_data_t vmstat;
+ mach_msg_type_number_t count = HOST_VM_INFO64_COUNT;
+ mach_port_t host = mach_host_self();
+ vm_size_t page_size;
+ host_page_size(host, &page_size);
+ kern_return_t result = host_statistics64(host, HOST_VM_INFO64, reinterpret_cast<host_info_t>(&vmstat), &count);
+ if (result == KERN_SUCCESS) {
+ // This is what Chrome reports as 'the "Physical Memory Free" value reported by the Memory Monitor in Instruments.'
+ // Note though that inactive pages are not included here and not yet free, but could become so under memory pressure.
+ sAvailPhysicalMemInKB = U32Bytes(vmstat.free_count * page_size);
+ sMaxPhysicalMemInKB = LLMemoryInfo::getHardwareMemSize();
+ }
+ else
+ {
+ LL_WARNS() << "task_info failed" << LL_ENDL;
+ }
+
#else
//not valid for other systems for now.
sAllocatedMemInKB = U64Bytes(LLMemory::getCurrentRSS());
diff --git a/indra/llcommon/llpointer.h b/indra/llcommon/llpointer.h
index 9a6453ea48..f9de0c7929 100644
--- a/indra/llcommon/llpointer.h
+++ b/indra/llcommon/llpointer.h
@@ -340,4 +340,28 @@ private:
bool mStayUnique;
};
+
+// boost hash adapter
+template <class Type>
+struct boost::hash<LLPointer<Type>>
+{
+ typedef LLPointer<Type> argument_type;
+ typedef std::size_t result_type;
+ result_type operator()(argument_type const& s) const
+ {
+ return (std::size_t) s.get();
+ }
+};
+
+// Adapt boost hash to std hash
+namespace std
+{
+ template<class Type> struct hash<LLPointer<Type>>
+ {
+ std::size_t operator()(LLPointer<Type> const& s) const noexcept
+ {
+ return boost::hash<LLPointer<Type>>()(s);
+ }
+ };
+}
#endif
diff --git a/indra/llcommon/llprofiler.h b/indra/llcommon/llprofiler.h
index f9d7ae7ce4..394fbd05f6 100644
--- a/indra/llcommon/llprofiler.h
+++ b/indra/llcommon/llprofiler.h
@@ -86,8 +86,12 @@ extern thread_local bool gProfilerEnabled;
#define TRACY_ONLY_IPV4 1
#include "Tracy.hpp"
- // Mutually exclusive with detailed memory tracing
+ // Enable OpenGL profiling
#define LL_PROFILER_ENABLE_TRACY_OPENGL 0
+
+ // Enable RenderDoc labeling
+ #define LL_PROFILER_ENABLE_RENDER_DOC 0
+
#endif
#if LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY
@@ -104,8 +108,6 @@ extern thread_local bool gProfilerEnabled;
#define LL_PROFILE_ZONE_ERR(name) LL_PROFILE_ZONE_NAMED_COLOR( name, 0XFF0000 ) // RGB yellow
#define LL_PROFILE_ZONE_INFO(name) LL_PROFILE_ZONE_NAMED_COLOR( name, 0X00FFFF ) // RGB cyan
#define LL_PROFILE_ZONE_WARN(name) LL_PROFILE_ZONE_NAMED_COLOR( name, 0x0FFFF00 ) // RGB red
- #define LL_PROFILE_ALLOC(ptr, size) TracyAlloc(ptr, size)
- #define LL_PROFILE_FREE(ptr) TracyFree(ptr)
#endif
#if LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_FAST_TIMER
#define LL_PROFILER_FRAME_END
@@ -121,8 +123,6 @@ extern thread_local bool gProfilerEnabled;
#define LL_PROFILE_ZONE_ERR(name) (void)(name); // Not supported
#define LL_PROFILE_ZONE_INFO(name) (void)(name); // Not supported
#define LL_PROFILE_ZONE_WARN(name) (void)(name); // Not supported
- #define LL_PROFILE_ALLOC(ptr, size) (void)(ptr); (void)(size);
- #define LL_PROFILE_FREE(ptr) (void)(ptr);
#endif
#if LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY_FAST_TIMER
#define LL_PROFILER_FRAME_END FrameMark
@@ -138,14 +138,49 @@ extern thread_local bool gProfilerEnabled;
#define LL_PROFILE_ZONE_ERR(name) LL_PROFILE_ZONE_NAMED_COLOR( name, 0XFF0000 ) // RGB yellow
#define LL_PROFILE_ZONE_INFO(name) LL_PROFILE_ZONE_NAMED_COLOR( name, 0X00FFFF ) // RGB cyan
#define LL_PROFILE_ZONE_WARN(name) LL_PROFILE_ZONE_NAMED_COLOR( name, 0x0FFFF00 ) // RGB red
- #define LL_PROFILE_ALLOC(ptr, size) TracyAlloc(ptr, size)
- #define LL_PROFILE_FREE(ptr) TracyFree(ptr)
+ //#define LL_PROFILE_ALLOC(ptr, size) TracyAlloc(ptr, size) // memory allocation tracking currently not working
+ //#define LL_PROFILE_FREE(ptr) TracyFree(ptr)
+ #define LL_PROFILE_ALLOC(ptr, size) (void)(ptr); (void)(size);
+ #define LL_PROFILE_FREE(ptr) (void)(ptr);
#endif
#else
#define LL_PROFILER_FRAME_END
#define LL_PROFILER_SET_THREAD_NAME( name ) (void)(name)
#endif // LL_PROFILER
+#if LL_PROFILER_ENABLE_TRACY_OPENGL
+#define LL_PROFILE_GPU_ZONE(name) TracyGpuZone(name)
+#define LL_PROFILE_GPU_ZONEC(name,color) TracyGpuZoneC(name,color)
+#define LL_PROFILER_GPU_COLLECT TracyGpuCollect
+#define LL_PROFILER_GPU_CONTEXT TracyGpuContext
+
+// disable memory tracking (incompatible with GPU tracing
+#define LL_PROFILE_ALLOC(ptr, size) (void)(ptr); (void)(size);
+#define LL_PROFILE_FREE(ptr) (void)(ptr);
+#else
+#define LL_PROFILE_GPU_ZONE(name) (void)name;
+#define LL_PROFILE_GPU_ZONEC(name,color) (void)name;(void)color;
+#define LL_PROFILER_GPU_COLLECT
+#define LL_PROFILER_GPU_CONTEXT
+
+#define LL_LABEL_OBJECT_GL(type, name, length, label)
+
+#if LL_PROFILER_CONFIG > 1
+#define LL_PROFILE_ALLOC(ptr, size) TracyAlloc(ptr, size)
+#define LL_PROFILE_FREE(ptr) TracyFree(ptr)
+#else
+#define LL_PROFILE_ALLOC(ptr, size) (void)(ptr); (void)(size);
+#define LL_PROFILE_FREE(ptr) (void)(ptr);
+#endif
+
+#endif
+
+#if LL_PROFILER_ENABLE_RENDER_DOC
+#define LL_LABEL_OBJECT_GL(type, name, length, label) glObjectLabel(type, name, length, label)
+#else
+#define LL_LABEL_OBJECT_GL(type, name, length, label)
+#endif
+
#include "llprofilercategories.h"
#endif // LL_PROFILER_H
diff --git a/indra/llcommon/llqueuedthread.cpp b/indra/llcommon/llqueuedthread.cpp
index 8cef4293cd..9b1de2e9a5 100644
--- a/indra/llcommon/llqueuedthread.cpp
+++ b/indra/llcommon/llqueuedthread.cpp
@@ -26,20 +26,26 @@
#include "linden_common.h"
#include "llqueuedthread.h"
+#include <chrono>
+
#include "llstl.h"
#include "lltimer.h" // ms_sleep()
-#include "lltracethreadrecorder.h"
+#include "llmutex.h"
//============================================================================
// MAIN THREAD
LLQueuedThread::LLQueuedThread(const std::string& name, bool threaded, bool should_pause) :
- LLThread(name),
- mThreaded(threaded),
- mIdleThread(TRUE),
- mNextHandle(0),
- mStarted(FALSE)
+ LLThread(name),
+ mIdleThread(TRUE),
+ mNextHandle(0),
+ mStarted(FALSE),
+ mThreaded(threaded),
+ mRequestQueue(name, 1024 * 1024)
{
+ llassert(threaded); // not threaded implementation is deprecated
+ mMainQueue = LL::WorkQueue::getInstance("mainloop");
+
if (mThreaded)
{
if(should_pause)
@@ -69,6 +75,11 @@ void LLQueuedThread::shutdown()
unpause(); // MAIN THREAD
if (mThreaded)
{
+ if (mRequestQueue.size() == 0)
+ {
+ mRequestQueue.close();
+ }
+
S32 timeout = 100;
for ( ; timeout>0; timeout--)
{
@@ -104,6 +115,8 @@ void LLQueuedThread::shutdown()
{
LL_WARNS() << "~LLQueuedThread() called with active requests: " << active_count << LL_ENDL;
}
+
+ mRequestQueue.close();
}
//----------------------------------------------------------------------------
@@ -112,6 +125,7 @@ void LLQueuedThread::shutdown()
// virtual
S32 LLQueuedThread::update(F32 max_time_ms)
{
+ LL_PROFILE_ZONE_SCOPED;
if (!mStarted)
{
if (!mThreaded)
@@ -125,29 +139,34 @@ S32 LLQueuedThread::update(F32 max_time_ms)
S32 LLQueuedThread::updateQueue(F32 max_time_ms)
{
- F64 max_time = (F64)max_time_ms * .001;
- LLTimer timer;
- S32 pending = 1;
-
+ LL_PROFILE_ZONE_SCOPED;
// Frame Update
if (mThreaded)
{
- pending = getPending();
- if(pending > 0)
+ // schedule a call to threadedUpdate for every call to updateQueue
+ if (!isQuitting())
+ {
+ mRequestQueue.postIfOpen([=]()
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("qt - update");
+ mIdleThread = FALSE;
+ threadedUpdate();
+ mIdleThread = TRUE;
+ }
+ );
+ }
+
+ if(getPending() > 0)
{
- unpause();
- }
+ unpause();
+ }
}
else
{
- while (pending > 0)
- {
- pending = processNextRequest();
- if (max_time && timer.getElapsedTimeF64() > max_time)
- break;
- }
+ mRequestQueue.runFor(std::chrono::microseconds((int) (max_time_ms*1000.f)));
+ threadedUpdate();
}
- return pending;
+ return getPending();
}
void LLQueuedThread::incQueue()
@@ -166,11 +185,7 @@ void LLQueuedThread::incQueue()
// May be called from any thread
S32 LLQueuedThread::getPending()
{
- S32 res;
- lockData();
- res = mRequestQueue.size();
- unlockData();
- return res;
+ return mRequestQueue.size();
}
// MAIN thread
@@ -195,35 +210,28 @@ void LLQueuedThread::waitOnPending()
// MAIN thread
void LLQueuedThread::printQueueStats()
{
- lockData();
- if (!mRequestQueue.empty())
+ U32 size = mRequestQueue.size();
+ if (size > 0)
{
- QueuedRequest *req = *mRequestQueue.begin();
- LL_INFOS() << llformat("Pending Requests:%d Current status:%d", mRequestQueue.size(), req->getStatus()) << LL_ENDL;
+ LL_INFOS() << llformat("Pending Requests:%d ", mRequestQueue.size()) << LL_ENDL;
}
else
{
LL_INFOS() << "Queued Thread Idle" << LL_ENDL;
}
- unlockData();
}
// MAIN thread
LLQueuedThread::handle_t LLQueuedThread::generateHandle()
{
- lockData();
- while ((mNextHandle == nullHandle()) || (mRequestHash.find(mNextHandle)))
- {
- mNextHandle++;
- }
- const LLQueuedThread::handle_t res = mNextHandle++;
- unlockData();
+ U32 res = ++mNextHandle;
return res;
}
// MAIN thread
bool LLQueuedThread::addRequest(QueuedRequest* req)
{
+ LL_PROFILE_ZONE_SCOPED;
if (mStatus == QUITTING)
{
return false;
@@ -231,14 +239,14 @@ bool LLQueuedThread::addRequest(QueuedRequest* req)
lockData();
req->setStatus(STATUS_QUEUED);
- mRequestQueue.insert(req);
- mRequestHash.insert(req);
+ mRequestHash.insert(req);
#if _DEBUG
// LL_INFOS() << llformat("LLQueuedThread::Added req [%08d]",handle) << LL_ENDL;
#endif
unlockData();
- incQueue();
+ llassert(!mDataLock->isSelfLocked());
+ mRequestQueue.post([this, req]() { processRequest(req); });
return true;
}
@@ -246,6 +254,7 @@ bool LLQueuedThread::addRequest(QueuedRequest* req)
// MAIN thread
bool LLQueuedThread::waitForResult(LLQueuedThread::handle_t handle, bool auto_complete)
{
+ LL_PROFILE_ZONE_SCOPED;
llassert (handle != nullHandle());
bool res = false;
bool waspaused = isPaused();
@@ -312,6 +321,7 @@ LLQueuedThread::status_t LLQueuedThread::getRequestStatus(handle_t handle)
void LLQueuedThread::abortRequest(handle_t handle, bool autocomplete)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD;
lockData();
QueuedRequest* req = (QueuedRequest*)mRequestHash.find(handle);
if (req)
@@ -333,30 +343,9 @@ void LLQueuedThread::setFlags(handle_t handle, U32 flags)
unlockData();
}
-void LLQueuedThread::setPriority(handle_t handle, U32 priority)
-{
- lockData();
- QueuedRequest* req = (QueuedRequest*)mRequestHash.find(handle);
- if (req)
- {
- if(req->getStatus() == STATUS_INPROGRESS)
- {
- // not in list
- req->setPriority(priority);
- }
- else if(req->getStatus() == STATUS_QUEUED)
- {
- // remove from list then re-insert
- llverify(mRequestQueue.erase(req) == 1);
- req->setPriority(priority);
- mRequestQueue.insert(req);
- }
- }
- unlockData();
-}
-
bool LLQueuedThread::completeRequest(handle_t handle)
{
+ LL_PROFILE_ZONE_SCOPED;
bool res = false;
lockData();
QueuedRequest* req = (QueuedRequest*)mRequestHash.find(handle);
@@ -399,89 +388,120 @@ bool LLQueuedThread::check()
//============================================================================
// Runs on its OWN thread
-S32 LLQueuedThread::processNextRequest()
+void LLQueuedThread::processRequest(LLQueuedThread::QueuedRequest* req)
{
- QueuedRequest *req;
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD;
+
+ mIdleThread = FALSE;
+ //threadedUpdate();
+
// Get next request from pool
lockData();
- while(1)
+ if ((req->getFlags() & FLAG_ABORT) || (mStatus == QUITTING))
{
- req = NULL;
- if (mRequestQueue.empty())
+ LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("qtpr - abort");
+ req->setStatus(STATUS_ABORTED);
+ req->finishRequest(false);
+ if (req->getFlags() & FLAG_AUTO_COMPLETE)
{
- break;
- }
- req = *mRequestQueue.begin();
- mRequestQueue.erase(mRequestQueue.begin());
- if ((req->getFlags() & FLAG_ABORT) || (mStatus == QUITTING))
- {
- req->setStatus(STATUS_ABORTED);
- req->finishRequest(false);
- if (req->getFlags() & FLAG_AUTO_COMPLETE)
- {
- mRequestHash.erase(req);
- req->deleteRequest();
-// check();
- }
- continue;
- }
- llassert_always(req->getStatus() == STATUS_QUEUED);
- break;
- }
- U32 start_priority = 0 ;
- if (req)
- {
- req->setStatus(STATUS_INPROGRESS);
- start_priority = req->getPriority();
- }
- unlockData();
-
- // This is the only place we will call req->setStatus() after
- // it has initially been seet to STATUS_QUEUED, so it is
- // safe to access req.
- if (req)
- {
- // process request
- bool complete = req->processRequest();
-
- if (complete)
- {
- lockData();
- req->setStatus(STATUS_COMPLETE);
- req->finishRequest(true);
- if (req->getFlags() & FLAG_AUTO_COMPLETE)
- {
- mRequestHash.erase(req);
- req->deleteRequest();
+ mRequestHash.erase(req);
+ req->deleteRequest();
// check();
- }
- unlockData();
}
- else
- {
- lockData();
- req->setStatus(STATUS_QUEUED);
- mRequestQueue.insert(req);
- unlockData();
- if (mThreaded && start_priority < PRIORITY_NORMAL)
- {
- ms_sleep(1); // sleep the thread a little
- }
- }
-
- LLTrace::get_thread_recorder()->pushToParent();
+ unlockData();
}
+ else
+ {
+ llassert_always(req->getStatus() == STATUS_QUEUED);
+
+ if (req)
+ {
+ req->setStatus(STATUS_INPROGRESS);
+ }
+ unlockData();
+
+ // This is the only place we will call req->setStatus() after
+ // it has initially been seet to STATUS_QUEUED, so it is
+ // safe to access req.
+ if (req)
+ {
+ // process request
+ bool complete = req->processRequest();
+
+ if (complete)
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("qtpr - complete");
+ lockData();
+ req->setStatus(STATUS_COMPLETE);
+ req->finishRequest(true);
+ if (req->getFlags() & FLAG_AUTO_COMPLETE)
+ {
+ mRequestHash.erase(req);
+ req->deleteRequest();
+ // check();
+ }
+ unlockData();
+ }
+ else
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("qtpr - retry");
+ //put back on queue and try again in 0.1ms
+ lockData();
+ req->setStatus(STATUS_QUEUED);
+
+ unlockData();
+
+ llassert(!mDataLock->isSelfLocked());
+
+#if 0
+ // try again on next frame
+ // NOTE: tried using "post" with a time in the future, but this
+ // would invariably cause this thread to wait for a long time (10+ ms)
+ // while work is pending
+ bool ret = LL::WorkQueue::postMaybe(
+ mMainQueue,
+ [=]()
+ {
+ LL_PROFILE_ZONE_NAMED("processRequest - retry");
+ mRequestQueue.post([=]()
+ {
+ LL_PROFILE_ZONE_NAMED("processRequest - retry"); // <-- not redundant, track retry on both queues
+ processRequest(req);
+ });
+ });
+ llassert(ret);
+#else
+ using namespace std::chrono_literals;
+ auto retry_time = LL::WorkQueue::TimePoint::clock::now() + 16ms;
+ mRequestQueue.post([=]
+ {
+ LL_PROFILE_ZONE_NAMED("processRequest - retry");
+ if (LL::WorkQueue::TimePoint::clock::now() < retry_time)
+ {
+ auto sleep_time = std::chrono::duration_cast<std::chrono::milliseconds>(retry_time - LL::WorkQueue::TimePoint::clock::now());
+
+ if (sleep_time.count() > 0)
+ {
+ ms_sleep(sleep_time.count());
+ }
+ }
+ processRequest(req);
+ });
+#endif
+
+ }
+ }
+ }
- S32 pending = getPending();
- return pending;
+ mIdleThread = TRUE;
}
// virtual
bool LLQueuedThread::runCondition()
{
// mRunCondition must be locked here
- if (mRequestQueue.empty() && mIdleThread)
+ if (mRequestQueue.size() == 0 && mIdleThread)
return false;
else
return true;
@@ -495,18 +515,13 @@ void LLQueuedThread::run()
startThread();
mStarted = TRUE;
- while (1)
+
+ /*while (1)
{
+ LL_PROFILE_ZONE_SCOPED;
// this will block on the condition until runCondition() returns true, the thread is unpaused, or the thread leaves the RUNNING state.
checkPause();
- if (isQuitting())
- {
- LLTrace::get_thread_recorder()->pushToParent();
- endThread();
- break;
- }
-
mIdleThread = FALSE;
threadedUpdate();
@@ -515,12 +530,18 @@ void LLQueuedThread::run()
if (pending_work == 0)
{
+ //LL_PROFILE_ZONE_NAMED("LLQueuedThread - sleep");
mIdleThread = TRUE;
- ms_sleep(1);
+ //ms_sleep(1);
}
//LLThread::yield(); // thread should yield after each request
- }
+ }*/
+ mRequestQueue.runUntilClose();
+
+ endThread();
LL_INFOS() << "LLQueuedThread " << mName << " EXITING." << LL_ENDL;
+
+
}
// virtual
@@ -540,10 +561,9 @@ void LLQueuedThread::threadedUpdate()
//============================================================================
-LLQueuedThread::QueuedRequest::QueuedRequest(LLQueuedThread::handle_t handle, U32 priority, U32 flags) :
+LLQueuedThread::QueuedRequest::QueuedRequest(LLQueuedThread::handle_t handle, U32 flags) :
LLSimpleHashEntry<LLQueuedThread::handle_t>(handle),
mStatus(STATUS_UNKNOWN),
- mPriority(priority),
mFlags(flags)
{
}
diff --git a/indra/llcommon/llqueuedthread.h b/indra/llcommon/llqueuedthread.h
index 5d3f873646..6b82ccc434 100644
--- a/indra/llcommon/llqueuedthread.h
+++ b/indra/llcommon/llqueuedthread.h
@@ -36,6 +36,7 @@
#include "llthread.h"
#include "llsimplehash.h"
+#include "workqueue.h"
//============================================================================
// Note: ~LLQueuedThread is O(N) N=# of queued threads, assumed to be small
@@ -45,15 +46,6 @@ class LL_COMMON_API LLQueuedThread : public LLThread
{
//------------------------------------------------------------------------
public:
- enum priority_t {
- PRIORITY_IMMEDIATE = 0x7FFFFFFF,
- PRIORITY_URGENT = 0x40000000,
- PRIORITY_HIGH = 0x30000000,
- PRIORITY_NORMAL = 0x20000000,
- PRIORITY_LOW = 0x10000000,
- PRIORITY_LOWBITS = 0x0FFFFFFF,
- PRIORITY_HIGHBITS = 0x70000000
- };
enum status_t {
STATUS_EXPIRED = -1,
STATUS_UNKNOWN = 0,
@@ -82,28 +74,17 @@ public:
virtual ~QueuedRequest(); // use deleteRequest()
public:
- QueuedRequest(handle_t handle, U32 priority, U32 flags = 0);
+ QueuedRequest(handle_t handle, U32 flags = 0);
status_t getStatus()
{
return mStatus;
}
- U32 getPriority() const
- {
- return mPriority;
- }
U32 getFlags() const
{
return mFlags;
}
- bool higherPriority(const QueuedRequest& second) const
- {
- if ( mPriority == second.mPriority)
- return mHashKey < second.mHashKey;
- else
- return mPriority > second.mPriority;
- }
-
+
protected:
status_t setStatus(status_t newstatus)
{
@@ -121,28 +102,11 @@ public:
virtual void finishRequest(bool completed); // Always called from thread after request has completed or aborted
virtual void deleteRequest(); // Only method to delete a request
- void setPriority(U32 pri)
- {
- // Only do this on a request that is not in a queued list!
- mPriority = pri;
- };
-
protected:
LLAtomicBase<status_t> mStatus;
- U32 mPriority;
U32 mFlags;
};
-protected:
- struct queued_request_less
- {
- bool operator()(const QueuedRequest* lhs, const QueuedRequest* rhs) const
- {
- return lhs->higherPriority(*rhs); // higher priority in front of queue (set)
- }
- };
-
-
//------------------------------------------------------------------------
public:
@@ -167,7 +131,7 @@ private:
protected:
handle_t generateHandle();
bool addRequest(QueuedRequest* req);
- S32 processNextRequest(void);
+ void processRequest(QueuedRequest* req);
void incQueue();
public:
@@ -186,7 +150,6 @@ public:
status_t getRequestStatus(handle_t handle);
void abortRequest(handle_t handle, bool autocomplete);
void setFlags(handle_t handle, U32 flags);
- void setPriority(handle_t handle, U32 priority);
bool completeRequest(handle_t handle);
// This is public for support classes like LLWorkerThread,
// but generally the methods above should be used.
@@ -200,8 +163,10 @@ protected:
BOOL mStarted; // required when mThreaded is false to call startThread() from update()
LLAtomicBool mIdleThread; // request queue is empty (or we are quitting) and the thread is idle
- typedef std::set<QueuedRequest*, queued_request_less> request_queue_t;
- request_queue_t mRequestQueue;
+ //typedef std::set<QueuedRequest*, queued_request_less> request_queue_t;
+ //request_queue_t mRequestQueue;
+ LL::WorkQueue mRequestQueue;
+ LL::WorkQueue::weak_t mMainQueue;
enum { REQUEST_HASH_SIZE = 512 }; // must be power of 2
typedef LLSimpleHash<handle_t, REQUEST_HASH_SIZE> request_hash_t;
diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp
index a8b5c7b3a8..aeb8c530f4 100644
--- a/indra/llcommon/llsys.cpp
+++ b/indra/llcommon/llsys.cpp
@@ -771,20 +771,28 @@ static U32Kilobytes LLMemoryAdjustKBResult(U32Kilobytes inKB)
}
#endif
+#if LL_DARWIN
+// static
+U32Kilobytes LLMemoryInfo::getHardwareMemSize()
+{
+ // This might work on Linux as well. Someone check...
+ uint64_t phys = 0;
+ int mib[2] = { CTL_HW, HW_MEMSIZE };
+
+ size_t len = sizeof(phys);
+ sysctl(mib, 2, &phys, &len, NULL, 0);
+
+ return U64Bytes(phys);
+}
+#endif
+
U32Kilobytes LLMemoryInfo::getPhysicalMemoryKB() const
{
#if LL_WINDOWS
return LLMemoryAdjustKBResult(U32Kilobytes(mStatsMap["Total Physical KB"].asInteger()));
#elif LL_DARWIN
- // This might work on Linux as well. Someone check...
- uint64_t phys = 0;
- int mib[2] = { CTL_HW, HW_MEMSIZE };
-
- size_t len = sizeof(phys);
- sysctl(mib, 2, &phys, &len, NULL, 0);
-
- return U64Bytes(phys);
+ return getHardwareMemSize();
#elif LL_LINUX
U64 phys = 0;
diff --git a/indra/llcommon/llsys.h b/indra/llcommon/llsys.h
index 5ffbf5a732..0f768938cb 100644
--- a/indra/llcommon/llsys.h
+++ b/indra/llcommon/llsys.h
@@ -129,7 +129,10 @@ public:
LLMemoryInfo(); ///< Default constructor
void stream(std::ostream& s) const; ///< output text info to s
- U32Kilobytes getPhysicalMemoryKB() const;
+ U32Kilobytes getPhysicalMemoryKB() const;
+#if LL_DARWIN
+ static U32Kilobytes getHardwareMemSize(); // Because some Mac linkers won't let us reference extern gSysMemory from a different lib.
+#endif
//get the available memory infomation in KiloBytes.
static void getAvailableMemoryKB(U32Kilobytes& avail_physical_mem_kb, U32Kilobytes& avail_virtual_mem_kb);
diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index a807acc56e..4eaa05c335 100644
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -42,6 +42,7 @@
#ifdef LL_WINDOWS
+
const DWORD MS_VC_EXCEPTION=0x406D1388;
#pragma pack(push,8)
@@ -133,6 +134,15 @@ void LLThread::threadRun()
{
#ifdef LL_WINDOWS
set_thread_name(-1, mName.c_str());
+
+#if 0 // probably a bad idea, see usage of SetThreadIdealProcessor in LLWindowWin32)
+ HANDLE hThread = GetCurrentThread();
+ if (hThread)
+ {
+ SetThreadAffinityMask(hThread, (DWORD_PTR) 0xFFFFFFFFFFFFFFFE);
+ }
+#endif
+
#endif
LL_PROFILER_SET_THREAD_NAME( mName.c_str() );
diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp
index aaa6df325c..24eaa4c1a9 100644
--- a/indra/llcommon/lltimer.cpp
+++ b/indra/llcommon/lltimer.cpp
@@ -30,6 +30,9 @@
#include "u64.h"
+#include <chrono>
+#include <thread>
+
#if LL_WINDOWS
# include "llwin32headerslean.h"
#elif LL_LINUX || LL_DARWIN
@@ -62,9 +65,18 @@ LLTimer* LLTimer::sTimer = NULL;
//---------------------------------------------------------------------------
#if LL_WINDOWS
+
+
+#if 0
void ms_sleep(U32 ms)
{
- Sleep(ms);
+ LL_PROFILE_ZONE_SCOPED;
+ using TimePoint = std::chrono::steady_clock::time_point;
+ auto resume_time = TimePoint::clock::now() + std::chrono::milliseconds(ms);
+ while (TimePoint::clock::now() < resume_time)
+ {
+ std::this_thread::yield(); //note: don't use LLThread::yield here to avoid yielding for too long
+ }
}
U32 micro_sleep(U64 us, U32 max_yields)
@@ -74,6 +86,35 @@ U32 micro_sleep(U64 us, U32 max_yields)
ms_sleep((U32)(us / 1000));
return 0;
}
+
+#else
+
+U32 micro_sleep(U64 us, U32 max_yields)
+{
+ LL_PROFILE_ZONE_SCOPED
+#if 0
+ LARGE_INTEGER ft;
+ ft.QuadPart = -static_cast<S64>(us * 10); // '-' using relative time
+
+ HANDLE timer = CreateWaitableTimer(NULL, TRUE, NULL);
+ SetWaitableTimer(timer, &ft, 0, NULL, NULL, 0);
+ WaitForSingleObject(timer, INFINITE);
+ CloseHandle(timer);
+#else
+ Sleep(us / 1000);
+#endif
+
+ return 0;
+}
+
+void ms_sleep(U32 ms)
+{
+ LL_PROFILE_ZONE_SCOPED
+ micro_sleep(ms * 1000, 0);
+}
+
+#endif
+
#elif LL_LINUX || LL_DARWIN
static void _sleep_loop(struct timespec& thiswait)
{
diff --git a/indra/llcommon/lluuid.cpp b/indra/llcommon/lluuid.cpp
index 6f9e09a587..47c6bc71c8 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/llcommon/llworkerthread.cpp b/indra/llcommon/llworkerthread.cpp
index 4b91b2caca..cd4d587752 100644
--- a/indra/llcommon/llworkerthread.cpp
+++ b/indra/llcommon/llworkerthread.cpp
@@ -73,6 +73,7 @@ void LLWorkerThread::clearDeleteList()
{
(*iter)->mRequestHandle = LLWorkerThread::nullHandle();
(*iter)->clearFlags(LLWorkerClass::WCF_HAVE_WORK);
+ (*iter)->clearFlags(LLWorkerClass::WCF_WORKING);
delete *iter ;
}
mDeleteList.clear() ;
@@ -97,6 +98,7 @@ S32 LLWorkerThread::update(F32 max_time_ms)
{
if (worker->getFlags(LLWorkerClass::WCF_WORK_FINISHED))
{
+ worker->setFlags(LLWorkerClass::WCF_DELETE_REQUESTED);
delete_list.push_back(worker);
mDeleteList.erase(curiter);
}
@@ -133,11 +135,11 @@ S32 LLWorkerThread::update(F32 max_time_ms)
//----------------------------------------------------------------------------
-LLWorkerThread::handle_t LLWorkerThread::addWorkRequest(LLWorkerClass* workerclass, S32 param, U32 priority)
+LLWorkerThread::handle_t LLWorkerThread::addWorkRequest(LLWorkerClass* workerclass, S32 param)
{
handle_t handle = generateHandle();
- WorkRequest* req = new WorkRequest(handle, priority, workerclass, param);
+ WorkRequest* req = new WorkRequest(handle, workerclass, param);
bool res = addRequest(req);
if (!res)
@@ -160,8 +162,8 @@ void LLWorkerThread::deleteWorker(LLWorkerClass* workerclass)
//============================================================================
// Runs on its OWN thread
-LLWorkerThread::WorkRequest::WorkRequest(handle_t handle, U32 priority, LLWorkerClass* workerclass, S32 param) :
- LLQueuedThread::QueuedRequest(handle, priority),
+LLWorkerThread::WorkRequest::WorkRequest(handle_t handle, LLWorkerClass* workerclass, S32 param) :
+ LLQueuedThread::QueuedRequest(handle),
mWorkerClass(workerclass),
mParam(param)
{
@@ -180,6 +182,7 @@ void LLWorkerThread::WorkRequest::deleteRequest()
// virtual
bool LLWorkerThread::WorkRequest::processRequest()
{
+ LL_PROFILE_ZONE_SCOPED;
LLWorkerClass* workerclass = getWorkerClass();
workerclass->setWorking(true);
bool complete = workerclass->doWork(getParam());
@@ -190,6 +193,7 @@ bool LLWorkerThread::WorkRequest::processRequest()
// virtual
void LLWorkerThread::WorkRequest::finishRequest(bool completed)
{
+ LL_PROFILE_ZONE_SCOPED;
LLWorkerClass* workerclass = getWorkerClass();
workerclass->finishWork(getParam(), completed);
U32 flags = LLWorkerClass::WCF_WORK_FINISHED | (completed ? 0 : LLWorkerClass::WCF_WORK_ABORTED);
@@ -203,7 +207,6 @@ LLWorkerClass::LLWorkerClass(LLWorkerThread* workerthread, const std::string& na
: mWorkerThread(workerthread),
mWorkerClassName(name),
mRequestHandle(LLWorkerThread::nullHandle()),
- mRequestPriority(LLWorkerThread::PRIORITY_NORMAL),
mMutex(),
mWorkFlags(0)
{
@@ -292,7 +295,7 @@ bool LLWorkerClass::yield()
//----------------------------------------------------------------------------
// calls startWork, adds doWork() to queue
-void LLWorkerClass::addWork(S32 param, U32 priority)
+void LLWorkerClass::addWork(S32 param)
{
mMutex.lock();
llassert_always(!(mWorkFlags & (WCF_WORKING|WCF_HAVE_WORK)));
@@ -306,7 +309,7 @@ void LLWorkerClass::addWork(S32 param, U32 priority)
startWork(param);
clearFlags(WCF_WORK_FINISHED|WCF_WORK_ABORTED);
setFlags(WCF_HAVE_WORK);
- mRequestHandle = mWorkerThread->addWorkRequest(this, param, priority);
+ mRequestHandle = mWorkerThread->addWorkRequest(this, param);
mMutex.unlock();
}
@@ -321,7 +324,6 @@ void LLWorkerClass::abortWork(bool autocomplete)
if (mRequestHandle != LLWorkerThread::nullHandle())
{
mWorkerThread->abortRequest(mRequestHandle, autocomplete);
- mWorkerThread->setPriority(mRequestHandle, LLQueuedThread::PRIORITY_IMMEDIATE);
setFlags(WCF_ABORT_REQUESTED);
}
mMutex.unlock();
@@ -395,16 +397,5 @@ void LLWorkerClass::scheduleDelete()
}
}
-void LLWorkerClass::setPriority(U32 priority)
-{
- mMutex.lock();
- if (mRequestHandle != LLWorkerThread::nullHandle() && mRequestPriority != priority)
- {
- mRequestPriority = priority;
- mWorkerThread->setPriority(mRequestHandle, priority);
- }
- mMutex.unlock();
-}
-
//============================================================================
diff --git a/indra/llcommon/llworkerthread.h b/indra/llcommon/llworkerthread.h
index 0387e75c65..06bbb7369e 100644
--- a/indra/llcommon/llworkerthread.h
+++ b/indra/llcommon/llworkerthread.h
@@ -56,7 +56,7 @@ public:
virtual ~WorkRequest(); // use deleteRequest()
public:
- WorkRequest(handle_t handle, U32 priority, LLWorkerClass* workerclass, S32 param);
+ WorkRequest(handle_t handle, LLWorkerClass* workerclass, S32 param);
S32 getParam()
{
@@ -90,7 +90,7 @@ public:
/*virtual*/ S32 update(F32 max_time_ms);
- handle_t addWorkRequest(LLWorkerClass* workerclass, S32 param, U32 priority = PRIORITY_NORMAL);
+ handle_t addWorkRequest(LLWorkerClass* workerclass, S32 param);
S32 getNumDeletes() { return (S32)mDeleteList.size(); } // debug
@@ -151,10 +151,6 @@ public:
bool isWorking() { return getFlags(WCF_WORKING); }
bool wasAborted() { return getFlags(WCF_ABORT_REQUESTED); }
- // setPriority(): changes the priority of a request
- void setPriority(U32 priority);
- U32 getPriority() { return mRequestPriority; }
-
const std::string& getName() const { return mWorkerClassName; }
protected:
@@ -169,7 +165,7 @@ protected:
void setWorkerThread(LLWorkerThread* workerthread);
// addWork(): calls startWork, adds doWork() to queue
- void addWork(S32 param, U32 priority = LLWorkerThread::PRIORITY_NORMAL);
+ void addWork(S32 param);
// abortWork(): requests that work be aborted
void abortWork(bool autocomplete);
@@ -193,7 +189,6 @@ protected:
LLWorkerThread* mWorkerThread;
std::string mWorkerClassName;
handle_t mRequestHandle;
- U32 mRequestPriority; // last priority set
private:
LLMutex mMutex;
diff --git a/indra/llcommon/tests/workqueue_test.cpp b/indra/llcommon/tests/workqueue_test.cpp
index 1d73f7aa0d..41aa858084 100644
--- a/indra/llcommon/tests/workqueue_test.cpp
+++ b/indra/llcommon/tests/workqueue_test.cpp
@@ -38,7 +38,7 @@ namespace tut
{
struct workqueue_data
{
- WorkQueue queue{"queue"};
+ WorkSchedule queue{"queue"};
};
typedef test_group<workqueue_data> workqueue_group;
typedef workqueue_group::object object;
@@ -49,8 +49,8 @@ namespace tut
{
set_test_name("name");
ensure_equals("didn't capture name", queue.getKey(), "queue");
- ensure("not findable", WorkQueue::getInstance("queue") == queue.getWeak().lock());
- WorkQueue q2;
+ ensure("not findable", WorkSchedule::getInstance("queue") == queue.getWeak().lock());
+ WorkSchedule q2;
ensure("has no name", LLStringUtil::startsWith(q2.getKey(), "WorkQueue"));
}
@@ -73,16 +73,16 @@ namespace tut
{
set_test_name("postEvery");
// record of runs
- using Shared = std::deque<WorkQueue::TimePoint>;
+ using Shared = std::deque<WorkSchedule::TimePoint>;
// This is an example of how to share data between the originator of
- // postEvery(work) and the work item itself, since usually a WorkQueue
+ // postEvery(work) and the work item itself, since usually a WorkSchedule
// is used to dispatch work to a different thread. Neither of them
// should call any of LLCond's wait methods: you don't want to stall
// either the worker thread or the originating thread (conventionally
// main). Use LLCond or a subclass even if all you want to do is
// signal the work item that it can quit; consider LLOneShotCond.
LLCond<Shared> data;
- auto start = WorkQueue::TimePoint::clock::now();
+ auto start = WorkSchedule::TimePoint::clock::now();
auto interval = 100ms;
queue.postEvery(
interval,
@@ -93,7 +93,7 @@ namespace tut
data.update_one(
[](Shared& data)
{
- data.push_back(WorkQueue::TimePoint::clock::now());
+ data.push_back(WorkSchedule::TimePoint::clock::now());
});
// by the 3rd call, return false to stop
return (++count < 3);
@@ -102,7 +102,7 @@ namespace tut
// postEvery() running, so run until we have exhausted the iterations
// or we time out waiting
for (auto finish = start + 10*interval;
- WorkQueue::TimePoint::clock::now() < finish &&
+ WorkSchedule::TimePoint::clock::now() < finish &&
data.get([](const Shared& data){ return data.size(); }) < 3; )
{
queue.runPending();
@@ -139,8 +139,8 @@ namespace tut
void object::test<4>()
{
set_test_name("postTo");
- WorkQueue main("main");
- auto qptr = WorkQueue::getInstance("queue");
+ WorkSchedule main("main");
+ auto qptr = WorkSchedule::getInstance("queue");
int result = 0;
main.postTo(
qptr,
@@ -171,8 +171,8 @@ namespace tut
void object::test<5>()
{
set_test_name("postTo with void return");
- WorkQueue main("main");
- auto qptr = WorkQueue::getInstance("queue");
+ WorkSchedule main("main");
+ auto qptr = WorkSchedule::getInstance("queue");
std::string observe;
main.postTo(
qptr,
@@ -194,7 +194,7 @@ namespace tut
std::string stored;
// Try to call waitForResult() on this thread's main coroutine. It
// should throw because the main coroutine must service the queue.
- auto what{ catch_what<WorkQueue::Error>(
+ auto what{ catch_what<WorkSchedule::Error>(
[this, &stored](){ stored = queue.waitForResult(
[](){ return "should throw"; }); }) };
ensure("lambda should not have run", stored.empty());
diff --git a/indra/llcommon/threadpool.cpp b/indra/llcommon/threadpool.cpp
index d5adf11264..3a9a5a2062 100644
--- a/indra/llcommon/threadpool.cpp
+++ b/indra/llcommon/threadpool.cpp
@@ -17,18 +17,58 @@
// std headers
// external library headers
// other Linden headers
+#include "commoncontrol.h"
#include "llerror.h"
#include "llevents.h"
+#include "llsd.h"
#include "stringize.h"
-LL::ThreadPool::ThreadPool(const std::string& name, size_t threads, size_t capacity):
+#include <boost/fiber/algo/round_robin.hpp>
+
+/*****************************************************************************
+* Custom fiber scheduler for worker threads
+*****************************************************************************/
+// As of 2022-12-06, each of our worker threads only runs a single (default)
+// fiber: we don't launch explicit fibers within worker threads, nor do we
+// anticipate doing so. So a worker thread that's simply waiting for incoming
+// tasks should really sleep a little. Override the default fiber scheduler to
+// implement that.
+struct sleepy_robin: public boost::fibers::algo::round_robin
+{
+ virtual void suspend_until( std::chrono::steady_clock::time_point const&) noexcept
+ {
+#if LL_WINDOWS
+ // round_robin holds a std::condition_variable, and
+ // round_robin::suspend_until() calls
+ // std::condition_variable::wait_until(). On Windows, that call seems
+ // busier than it ought to be. Try just sleeping.
+ Sleep(1);
+#else
+ // currently unused other than windows, but might as well have something here
+ // different units than Sleep(), but we actually just want to sleep for any de-minimis duration
+ usleep(1);
+#endif
+ }
+
+ virtual void notify() noexcept
+ {
+ // Since our Sleep() call above will wake up on its own, we need not
+ // take any special action to wake it.
+ }
+};
+
+/*****************************************************************************
+* ThreadPoolBase
+*****************************************************************************/
+LL::ThreadPoolBase::ThreadPoolBase(const std::string& name, size_t threads,
+ WorkQueueBase* queue):
super(name),
- mQueue(name, capacity),
mName("ThreadPool:" + name),
- mThreadCount(threads)
+ mThreadCount(getConfiguredWidth(name, threads)),
+ mQueue(queue)
{}
-void LL::ThreadPool::start()
+void LL::ThreadPoolBase::start()
{
for (size_t i = 0; i < mThreadCount; ++i)
{
@@ -56,17 +96,17 @@ void LL::ThreadPool::start()
});
}
-LL::ThreadPool::~ThreadPool()
+LL::ThreadPoolBase::~ThreadPoolBase()
{
close();
}
-void LL::ThreadPool::close()
+void LL::ThreadPoolBase::close()
{
- if (! mQueue.isClosed())
+ if (! mQueue->isClosed())
{
LL_DEBUGS("ThreadPool") << mName << " closing queue and joining threads" << LL_ENDL;
- mQueue.close();
+ mQueue->close();
for (auto& pair: mThreads)
{
LL_DEBUGS("ThreadPool") << mName << " waiting on thread " << pair.first << LL_ENDL;
@@ -76,14 +116,74 @@ void LL::ThreadPool::close()
}
}
-void LL::ThreadPool::run(const std::string& name)
+void LL::ThreadPoolBase::run(const std::string& name)
{
+#if LL_WINDOWS
+ // Try using sleepy_robin fiber scheduler.
+ boost::fibers::use_scheduling_algorithm<sleepy_robin>();
+#endif // LL_WINDOWS
+
LL_DEBUGS("ThreadPool") << name << " starting" << LL_ENDL;
run();
LL_DEBUGS("ThreadPool") << name << " stopping" << LL_ENDL;
}
-void LL::ThreadPool::run()
+void LL::ThreadPoolBase::run()
+{
+ mQueue->runUntilClose();
+}
+
+//static
+size_t LL::ThreadPoolBase::getConfiguredWidth(const std::string& name, size_t dft)
+{
+ LLSD poolSizes;
+ try
+ {
+ poolSizes = LL::CommonControl::get("Global", "ThreadPoolSizes");
+ // "ThreadPoolSizes" is actually a map containing the sizes of
+ // interest -- or should be, if this process has an
+ // LLViewerControlListener instance and its settings include
+ // "ThreadPoolSizes". If we failed to retrieve it, perhaps we're in a
+ // program that doesn't define that, or perhaps there's no such
+ // setting, or perhaps we're asking too early, before the LLEventAPI
+ // itself has been instantiated. In any of those cases, it seems worth
+ // warning.
+ if (! poolSizes.isDefined())
+ {
+ // Note: we don't warn about absence of an override key for a
+ // particular ThreadPool name, that's fine. This warning is about
+ // complete absence of a ThreadPoolSizes setting, which we expect
+ // in a normal viewer session.
+ LL_WARNS("ThreadPool") << "No 'ThreadPoolSizes' setting for ThreadPool '"
+ << name << "'" << LL_ENDL;
+ }
+ }
+ catch (const LL::CommonControl::Error& exc)
+ {
+ // We don't want ThreadPool to *require* LLViewerControlListener.
+ // Just log it and carry on.
+ LL_WARNS("ThreadPool") << "Can't check 'ThreadPoolSizes': " << exc.what() << LL_ENDL;
+ }
+
+ LL_DEBUGS("ThreadPool") << "ThreadPoolSizes = " << poolSizes << LL_ENDL;
+ // LLSD treats an undefined value as an empty map when asked to retrieve a
+ // key, so we don't need this to be conditional.
+ LLSD sizeSpec{ poolSizes[name] };
+ // We retrieve sizeSpec as LLSD, rather than immediately as LLSD::Integer,
+ // so we can distinguish the case when it's undefined.
+ return sizeSpec.isInteger() ? sizeSpec.asInteger() : dft;
+}
+
+//static
+size_t LL::ThreadPoolBase::getWidth(const std::string& name, size_t dft)
{
- mQueue.runUntilClose();
+ auto instance{ getInstance(name) };
+ if (instance)
+ {
+ return instance->getWidth();
+ }
+ else
+ {
+ return getConfiguredWidth(name, dft);
+ }
}
diff --git a/indra/llcommon/threadpool.h b/indra/llcommon/threadpool.h
index f8eec3b457..60f4a0ce1b 100644
--- a/indra/llcommon/threadpool.h
+++ b/indra/llcommon/threadpool.h
@@ -13,7 +13,9 @@
#if ! defined(LL_THREADPOOL_H)
#define LL_THREADPOOL_H
+#include "threadpool_fwd.h"
#include "workqueue.h"
+#include <memory> // std::unique_ptr
#include <string>
#include <thread>
#include <utility> // std::pair
@@ -22,17 +24,24 @@
namespace LL
{
- class ThreadPool: public LLInstanceTracker<ThreadPool, std::string>
+ class ThreadPoolBase: public LLInstanceTracker<ThreadPoolBase, std::string>
{
private:
- using super = LLInstanceTracker<ThreadPool, std::string>;
+ using super = LLInstanceTracker<ThreadPoolBase, std::string>;
+
public:
/**
- * Pass ThreadPool a string name. This can be used to look up the
+ * Pass ThreadPoolBase a string name. This can be used to look up the
* relevant WorkQueue.
+ *
+ * The number of threads you pass sets the compile-time default. But
+ * if the user has overridden the LLSD map in the "ThreadPoolSizes"
+ * setting with a key matching this ThreadPool name, that setting
+ * overrides this parameter.
*/
- ThreadPool(const std::string& name, size_t threads=1, size_t capacity=1024);
- virtual ~ThreadPool();
+ ThreadPoolBase(const std::string& name, size_t threads,
+ WorkQueueBase* queue);
+ virtual ~ThreadPoolBase();
/**
* Launch the ThreadPool. Until this call, a constructed ThreadPool
@@ -50,8 +59,6 @@ namespace LL
std::string getName() const { return mName; }
size_t getWidth() const { return mThreads.size(); }
- /// obtain a non-const reference to the WorkQueue to post work to it
- WorkQueue& getQueue() { return mQueue; }
/**
* Override run() if you need special processing. The default run()
@@ -59,15 +66,72 @@ namespace LL
*/
virtual void run();
+ /**
+ * getConfiguredWidth() returns the setting, if any, for the specified
+ * ThreadPool name. Returns dft if the "ThreadPoolSizes" map does not
+ * contain the specified name.
+ */
+ static
+ size_t getConfiguredWidth(const std::string& name, size_t dft=0);
+
+ /**
+ * This getWidth() returns the width of the instantiated ThreadPool
+ * with the specified name, if any. If no instance exists, returns its
+ * getConfiguredWidth() if any. If there's no instance and no relevant
+ * override, return dft. Presumably dft should match the threads
+ * parameter passed to the ThreadPool constructor call that will
+ * eventually instantiate the ThreadPool with that name.
+ */
+ static
+ size_t getWidth(const std::string& name, size_t dft);
+
+ protected:
+ std::unique_ptr<WorkQueueBase> mQueue;
+
private:
void run(const std::string& name);
- WorkQueue mQueue;
std::string mName;
size_t mThreadCount;
std::vector<std::pair<std::string, std::thread>> mThreads;
};
+ /**
+ * Specialize with WorkQueue or, for timestamped tasks, WorkSchedule
+ */
+ template <class QUEUE>
+ struct ThreadPoolUsing: public ThreadPoolBase
+ {
+ using queue_t = QUEUE;
+
+ /**
+ * Pass ThreadPoolUsing a string name. This can be used to look up the
+ * relevant WorkQueue.
+ *
+ * The number of threads you pass sets the compile-time default. But
+ * if the user has overridden the LLSD map in the "ThreadPoolSizes"
+ * setting with a key matching this ThreadPool name, that setting
+ * overrides this parameter.
+ *
+ * Pass an explicit capacity to limit the size of the queue.
+ * Constraining the queue can cause a submitter to block. Do not
+ * constrain any ThreadPool accepting work from the main thread.
+ */
+ ThreadPoolUsing(const std::string& name, size_t threads=1, size_t capacity=1024*1024):
+ ThreadPoolBase(name, threads, new queue_t(name, capacity))
+ {}
+ ~ThreadPoolUsing() override {}
+
+ /**
+ * obtain a non-const reference to the specific WorkQueue subclass to
+ * post work to it
+ */
+ queue_t& getQueue() { return static_cast<queue_t&>(*mQueue); }
+ };
+
+ /// ThreadPool is shorthand for using the simpler WorkQueue
+ using ThreadPool = ThreadPoolUsing<WorkQueue>;
+
} // namespace LL
#endif /* ! defined(LL_THREADPOOL_H) */
diff --git a/indra/llcommon/threadpool_fwd.h b/indra/llcommon/threadpool_fwd.h
new file mode 100644
index 0000000000..1aa3c4a0e2
--- /dev/null
+++ b/indra/llcommon/threadpool_fwd.h
@@ -0,0 +1,25 @@
+/**
+ * @file threadpool_fwd.h
+ * @author Nat Goodspeed
+ * @date 2022-12-09
+ * @brief Forward declarations for ThreadPool et al.
+ *
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
+ * Copyright (c) 2022, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_THREADPOOL_FWD_H)
+#define LL_THREADPOOL_FWD_H
+
+#include "workqueue.h"
+
+namespace LL
+{
+ template <class QUEUE>
+ struct ThreadPoolUsing;
+
+ using ThreadPool = ThreadPoolUsing<WorkQueue>;
+} // namespace LL
+
+#endif /* ! defined(LL_THREADPOOL_FWD_H) */
diff --git a/indra/llcommon/workqueue.cpp b/indra/llcommon/workqueue.cpp
index eb06890468..83e0216ae7 100644
--- a/indra/llcommon/workqueue.cpp
+++ b/indra/llcommon/workqueue.cpp
@@ -26,83 +26,65 @@
using Mutex = LLCoros::Mutex;
using Lock = LLCoros::LockType;
-LL::WorkQueue::WorkQueue(const std::string& name, size_t capacity):
- super(makeName(name)),
- mQueue(capacity)
+/*****************************************************************************
+* WorkQueueBase
+*****************************************************************************/
+LL::WorkQueueBase::WorkQueueBase(const std::string& name):
+ super(makeName(name))
{
// TODO: register for "LLApp" events so we can implicitly close() on
// viewer shutdown.
}
-void LL::WorkQueue::close()
-{
- mQueue.close();
-}
-
-size_t LL::WorkQueue::size()
-{
- return mQueue.size();
-}
-
-bool LL::WorkQueue::isClosed()
-{
- return mQueue.isClosed();
-}
-
-bool LL::WorkQueue::done()
-{
- return mQueue.done();
-}
-
-void LL::WorkQueue::runUntilClose()
+void LL::WorkQueueBase::runUntilClose()
{
try
{
for (;;)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD;
- callWork(mQueue.pop());
+ callWork(pop_());
}
}
- catch (const Queue::Closed&)
+ catch (const Closed&)
{
}
}
-bool LL::WorkQueue::runPending()
+bool LL::WorkQueueBase::runPending()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD;
- for (Work work; mQueue.tryPop(work); )
+ for (Work work; tryPop_(work); )
{
callWork(work);
}
- return ! mQueue.done();
+ return ! done();
}
-bool LL::WorkQueue::runOne()
+bool LL::WorkQueueBase::runOne()
{
Work work;
- if (mQueue.tryPop(work))
+ if (tryPop_(work))
{
callWork(work);
}
- return ! mQueue.done();
+ return ! done();
}
-bool LL::WorkQueue::runUntil(const TimePoint& until)
+bool LL::WorkQueueBase::runUntil(const TimePoint& until)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD;
// Should we subtract some slop to allow for typical Work execution time?
// How much slop?
// runUntil() is simply a time-bounded runPending().
- for (Work work; TimePoint::clock::now() < until && mQueue.tryPop(work); )
+ for (Work work; TimePoint::clock::now() < until && tryPop_(work); )
{
callWork(work);
}
- return ! mQueue.done();
+ return ! done();
}
-std::string LL::WorkQueue::makeName(const std::string& name)
+std::string LL::WorkQueueBase::makeName(const std::string& name)
{
if (! name.empty())
return name;
@@ -120,14 +102,7 @@ std::string LL::WorkQueue::makeName(const std::string& name)
return STRINGIZE("WorkQueue" << num);
}
-void LL::WorkQueue::callWork(const Queue::DataTuple& work)
-{
- // ThreadSafeSchedule::pop() always delivers a tuple, even when
- // there's only one data field per item, as for us.
- callWork(std::get<0>(work));
-}
-
-void LL::WorkQueue::callWork(const Work& work)
+void LL::WorkQueueBase::callWork(const Work& work)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD;
try
@@ -142,12 +117,12 @@ void LL::WorkQueue::callWork(const Work& work)
}
}
-void LL::WorkQueue::error(const std::string& msg)
+void LL::WorkQueueBase::error(const std::string& msg)
{
LL_ERRS("WorkQueue") << msg << LL_ENDL;
}
-void LL::WorkQueue::checkCoroutine(const std::string& method)
+void LL::WorkQueueBase::checkCoroutine(const std::string& method)
{
// By convention, the default coroutine on each thread has an empty name
// string. See also LLCoros::logname().
@@ -156,3 +131,130 @@ void LL::WorkQueue::checkCoroutine(const std::string& method)
LLTHROW(Error("Do not call " + method + " from a thread's default coroutine"));
}
}
+
+/*****************************************************************************
+* WorkQueue
+*****************************************************************************/
+LL::WorkQueue::WorkQueue(const std::string& name, size_t capacity):
+ super(name),
+ mQueue(capacity)
+{
+}
+
+void LL::WorkQueue::close()
+{
+ mQueue.close();
+}
+
+size_t LL::WorkQueue::size()
+{
+ return mQueue.size();
+}
+
+bool LL::WorkQueue::isClosed()
+{
+ return mQueue.isClosed();
+}
+
+bool LL::WorkQueue::done()
+{
+ return mQueue.done();
+}
+
+void LL::WorkQueue::post(const Work& callable)
+{
+ mQueue.push(callable);
+}
+
+bool LL::WorkQueue::postIfOpen(const Work& callable)
+{
+ return mQueue.pushIfOpen(callable);
+}
+
+bool LL::WorkQueue::tryPost(const Work& callable)
+{
+ return mQueue.tryPush(callable);
+}
+
+LL::WorkQueue::Work LL::WorkQueue::pop_()
+{
+ return mQueue.pop();
+}
+
+bool LL::WorkQueue::tryPop_(Work& work)
+{
+ return mQueue.tryPop(work);
+}
+
+/*****************************************************************************
+* WorkSchedule
+*****************************************************************************/
+LL::WorkSchedule::WorkSchedule(const std::string& name, size_t capacity):
+ super(name),
+ mQueue(capacity)
+{
+}
+
+void LL::WorkSchedule::close()
+{
+ mQueue.close();
+}
+
+size_t LL::WorkSchedule::size()
+{
+ return mQueue.size();
+}
+
+bool LL::WorkSchedule::isClosed()
+{
+ return mQueue.isClosed();
+}
+
+bool LL::WorkSchedule::done()
+{
+ return mQueue.done();
+}
+
+void LL::WorkSchedule::post(const Work& callable)
+{
+ // Use TimePoint::clock::now() instead of TimePoint's representation of
+ // the epoch because this WorkSchedule may contain a mix of past-due
+ // TimedWork items and TimedWork items scheduled for the future. Sift this
+ // new item into the correct place.
+ post(callable, TimePoint::clock::now());
+}
+
+void LL::WorkSchedule::post(const Work& callable, const TimePoint& time)
+{
+ mQueue.push(TimedWork(time, callable));
+}
+
+bool LL::WorkSchedule::postIfOpen(const Work& callable)
+{
+ return postIfOpen(callable, TimePoint::clock::now());
+}
+
+bool LL::WorkSchedule::postIfOpen(const Work& callable, const TimePoint& time)
+{
+ return mQueue.pushIfOpen(TimedWork(time, callable));
+}
+
+bool LL::WorkSchedule::tryPost(const Work& callable)
+{
+ return tryPost(callable, TimePoint::clock::now());
+}
+
+bool LL::WorkSchedule::tryPost(const Work& callable, const TimePoint& time)
+{
+ return mQueue.tryPush(TimedWork(time, callable));
+}
+
+LL::WorkSchedule::Work LL::WorkSchedule::pop_()
+{
+ return std::get<0>(mQueue.pop());
+}
+
+bool LL::WorkSchedule::tryPop_(Work& work)
+{
+ return mQueue.tryPop(work);
+}
diff --git a/indra/llcommon/workqueue.h b/indra/llcommon/workqueue.h
index 70fd65bd0c..5461ce6c23 100644
--- a/indra/llcommon/workqueue.h
+++ b/indra/llcommon/workqueue.h
@@ -15,6 +15,7 @@
#include "llcoros.h"
#include "llexception.h"
#include "llinstancetracker.h"
+#include "llinstancetrackersubclass.h"
#include "threadsafeschedule.h"
#include <chrono>
#include <exception> // std::current_exception
@@ -23,27 +24,23 @@
namespace LL
{
+
+/*****************************************************************************
+* WorkQueueBase: API for WorkQueue and WorkSchedule
+*****************************************************************************/
/**
* A typical WorkQueue has a string name that can be used to find it.
*/
- class WorkQueue: public LLInstanceTracker<WorkQueue, std::string>
+ class WorkQueueBase: public LLInstanceTracker<WorkQueueBase, std::string>
{
private:
- using super = LLInstanceTracker<WorkQueue, std::string>;
+ using super = LLInstanceTracker<WorkQueueBase, std::string>;
public:
using Work = std::function<void()>;
-
- private:
- using Queue = ThreadSafeSchedule<Work>;
- // helper for postEvery()
- template <typename Rep, typename Period, typename CALLABLE>
- class BackJack;
-
- public:
- using TimePoint = Queue::TimePoint;
- using TimedWork = Queue::TimeTuple;
- using Closed = Queue::Closed;
+ using Closed = LLThreadSafeQueueInterrupt;
+ // for runFor()
+ using TimePoint = std::chrono::steady_clock::time_point;
struct Error: public LLException
{
@@ -51,18 +48,18 @@ namespace LL
};
/**
- * You may omit the WorkQueue name, in which case a unique name is
+ * You may omit the WorkQueueBase name, in which case a unique name is
* synthesized; for practical purposes that makes it anonymous.
*/
- WorkQueue(const std::string& name = std::string(), size_t capacity=1024);
+ WorkQueueBase(const std::string& name);
/**
* Since the point of WorkQueue is to pass work to some other worker
- * thread(s) asynchronously, it's important that the WorkQueue continue
- * to exist until the worker thread(s) have drained it. To communicate
- * that it's time for them to quit, close() the queue.
+ * thread(s) asynchronously, it's important that it continue to exist
+ * until the worker thread(s) have drained it. To communicate that
+ * it's time for them to quit, close() the queue.
*/
- void close();
+ virtual void close() = 0;
/**
* WorkQueue supports multiple producers and multiple consumers. In
@@ -78,152 +75,60 @@ namespace LL
* * If you're the only consumer, noticing that size() > 0 is
* meaningful.
*/
- size_t size();
+ virtual size_t size() = 0;
/// producer end: are we prevented from pushing any additional items?
- bool isClosed();
+ virtual bool isClosed() = 0;
/// consumer end: are we done, is the queue entirely drained?
- bool done();
+ virtual bool done() = 0;
/*---------------------- fire and forget API -----------------------*/
- /// fire-and-forget, but at a particular (future?) time
- template <typename CALLABLE>
- void post(const TimePoint& time, CALLABLE&& callable)
- {
- // Defer reifying an arbitrary CALLABLE until we hit this or
- // postIfOpen(). All other methods should accept CALLABLEs of
- // arbitrary type to avoid multiple levels of std::function
- // indirection.
- mQueue.push(TimedWork(time, std::move(callable)));
- }
-
/// fire-and-forget
- template <typename CALLABLE>
- void post(CALLABLE&& callable)
- {
- // We use TimePoint::clock::now() instead of TimePoint's
- // representation of the epoch because this WorkQueue may contain
- // a mix of past-due TimedWork items and TimedWork items scheduled
- // for the future. Sift this new item into the correct place.
- post(TimePoint::clock::now(), std::move(callable));
- }
-
- /**
- * post work for a particular time, unless the queue is closed before
- * we can post
- */
- template <typename CALLABLE>
- bool postIfOpen(const TimePoint& time, CALLABLE&& callable)
- {
- // Defer reifying an arbitrary CALLABLE until we hit this or
- // post(). All other methods should accept CALLABLEs of arbitrary
- // type to avoid multiple levels of std::function indirection.
- return mQueue.pushIfOpen(TimedWork(time, std::move(callable)));
- }
+ virtual void post(const Work&) = 0;
/**
* post work, unless the queue is closed before we can post
*/
- template <typename CALLABLE>
- bool postIfOpen(CALLABLE&& callable)
- {
- return postIfOpen(TimePoint::clock::now(), std::move(callable));
- }
+ virtual bool postIfOpen(const Work&) = 0;
/**
- * Post work to be run at a specified time to another WorkQueue, which
- * may or may not still exist and be open. Return true if we were able
- * to post.
+ * post work, unless the queue is full
*/
- template <typename CALLABLE>
- static bool postMaybe(weak_t target, const TimePoint& time, CALLABLE&& callable);
+ virtual bool tryPost(const Work&) = 0;
/**
* Post work to another WorkQueue, which may or may not still exist
- * and be open. Return true if we were able to post.
+ * and be open. Support any post() overload. Return true if we were
+ * able to post.
*/
- template <typename CALLABLE>
- static bool postMaybe(weak_t target, CALLABLE&& callable)
- {
- return postMaybe(target, TimePoint::clock::now(),
- std::forward<CALLABLE>(callable));
- }
-
- /**
- * Launch a callable returning bool that will trigger repeatedly at
- * specified interval, until the callable returns false.
- *
- * If you need to signal that callable from outside, DO NOT bind a
- * reference to a simple bool! That's not thread-safe. Instead, bind
- * an LLCond variant, e.g. LLOneShotCond or LLBoolCond.
- */
- template <typename Rep, typename Period, typename CALLABLE>
- void postEvery(const std::chrono::duration<Rep, Period>& interval,
- CALLABLE&& callable);
-
- template <typename CALLABLE>
- bool tryPost(CALLABLE&& callable)
- {
- return mQueue.tryPush(TimedWork(TimePoint::clock::now(), std::move(callable)));
- }
+ template <typename... ARGS>
+ static bool postMaybe(weak_t target, ARGS&&... args);
/*------------------------- handshake API --------------------------*/
/**
- * Post work to another WorkQueue to be run at a specified time,
- * requesting a specific callback to be run on this WorkQueue on
- * completion.
- *
- * Returns true if able to post, false if the other WorkQueue is
- * inaccessible.
- */
- // Apparently some Microsoft header file defines a macro CALLBACK? The
- // natural template argument name CALLBACK produces very weird Visual
- // Studio compile errors that seem utterly unrelated to this source
- // code.
- template <typename CALLABLE, typename FOLLOWUP>
- bool postTo(weak_t target,
- const TimePoint& time, CALLABLE&& callable, FOLLOWUP&& callback);
-
- /**
* Post work to another WorkQueue, requesting a specific callback to
- * be run on this WorkQueue on completion.
+ * be run on this WorkQueue on completion. Optional final argument is
+ * TimePoint for WorkSchedule.
*
* Returns true if able to post, false if the other WorkQueue is
* inaccessible.
*/
- template <typename CALLABLE, typename FOLLOWUP>
- bool postTo(weak_t target, CALLABLE&& callable, FOLLOWUP&& callback)
- {
- return postTo(target, TimePoint::clock::now(),
- std::move(callable), std::move(callback));
- }
-
- /**
- * Post work to another WorkQueue to be run at a specified time,
- * blocking the calling coroutine until then, returning the result to
- * caller on completion.
- *
- * In general, we assume that each thread's default coroutine is busy
- * servicing its WorkQueue or whatever. To try to prevent mistakes, we
- * forbid calling waitForResult() from a thread's default coroutine.
- */
- template <typename CALLABLE>
- auto waitForResult(const TimePoint& time, CALLABLE&& callable);
+ template <typename CALLABLE, typename FOLLOWUP, typename... ARGS>
+ bool postTo(weak_t target, CALLABLE&& callable, FOLLOWUP&& callback,
+ ARGS&&... args);
/**
* Post work to another WorkQueue, blocking the calling coroutine
- * until then, returning the result to caller on completion.
+ * until then, returning the result to caller on completion. Optional
+ * final argument is TimePoint for WorkSchedule.
*
* In general, we assume that each thread's default coroutine is busy
* servicing its WorkQueue or whatever. To try to prevent mistakes, we
* forbid calling waitForResult() from a thread's default coroutine.
*/
- template <typename CALLABLE>
- auto waitForResult(CALLABLE&& callable)
- {
- return waitForResult(TimePoint::clock::now(), std::move(callable));
- }
+ template <typename CALLABLE, typename... ARGS>
+ auto waitForResult(CALLABLE&& callable, ARGS&&... args);
/*--------------------------- worker API ---------------------------*/
@@ -270,7 +175,7 @@ namespace LL
*/
bool runUntil(const TimePoint& until);
- private:
+ protected:
template <typename CALLABLE, typename FOLLOWUP>
static auto makeReplyLambda(CALLABLE&& callable, FOLLOWUP&& callback);
/// general case: arbitrary C++ return type
@@ -290,13 +195,179 @@ namespace LL
static void checkCoroutine(const std::string& method);
static void error(const std::string& msg);
static std::string makeName(const std::string& name);
- void callWork(const Queue::DataTuple& work);
void callWork(const Work& work);
+
+ private:
+ virtual Work pop_() = 0;
+ virtual bool tryPop_(Work&) = 0;
+ };
+
+/*****************************************************************************
+* WorkQueue: no timestamped task support
+*****************************************************************************/
+ class WorkQueue: public LLInstanceTrackerSubclass<WorkQueue, WorkQueueBase>
+ {
+ private:
+ using super = LLInstanceTrackerSubclass<WorkQueue, WorkQueueBase>;
+
+ public:
+ /**
+ * You may omit the WorkQueue name, in which case a unique name is
+ * synthesized; for practical purposes that makes it anonymous.
+ */
+ WorkQueue(const std::string& name = std::string(), size_t capacity=1024);
+
+ /**
+ * Since the point of WorkQueue is to pass work to some other worker
+ * thread(s) asynchronously, it's important that it continue to exist
+ * until the worker thread(s) have drained it. To communicate that
+ * it's time for them to quit, close() the queue.
+ */
+ void close() override;
+
+ /**
+ * WorkQueue supports multiple producers and multiple consumers. In
+ * the general case it's misleading to test size(), since any other
+ * thread might change it the nanosecond the lock is released. On that
+ * basis, some might argue against publishing a size() method at all.
+ *
+ * But there are two specific cases in which a test based on size()
+ * might be reasonable:
+ *
+ * * If you're the only producer, noticing that size() == 0 is
+ * meaningful.
+ * * If you're the only consumer, noticing that size() > 0 is
+ * meaningful.
+ */
+ size_t size() override;
+ /// producer end: are we prevented from pushing any additional items?
+ bool isClosed() override;
+ /// consumer end: are we done, is the queue entirely drained?
+ bool done() override;
+
+ /*---------------------- fire and forget API -----------------------*/
+
+ /// fire-and-forget
+ void post(const Work&) override;
+
+ /**
+ * post work, unless the queue is closed before we can post
+ */
+ bool postIfOpen(const Work&) override;
+
+ /**
+ * post work, unless the queue is full
+ */
+ bool tryPost(const Work&) override;
+
+ private:
+ using Queue = LLThreadSafeQueue<Work>;
Queue mQueue;
+
+ Work pop_() override;
+ bool tryPop_(Work&) override;
+ };
+
+/*****************************************************************************
+* WorkSchedule: add support for timestamped tasks
+*****************************************************************************/
+ class WorkSchedule: public LLInstanceTrackerSubclass<WorkSchedule, WorkQueueBase>
+ {
+ private:
+ using super = LLInstanceTrackerSubclass<WorkSchedule, WorkQueueBase>;
+ using Queue = ThreadSafeSchedule<Work>;
+ // helper for postEvery()
+ template <typename Rep, typename Period, typename CALLABLE>
+ class BackJack;
+
+ public:
+ using TimePoint = Queue::TimePoint;
+ using TimedWork = Queue::TimeTuple;
+
+ /**
+ * You may omit the WorkSchedule name, in which case a unique name is
+ * synthesized; for practical purposes that makes it anonymous.
+ */
+ WorkSchedule(const std::string& name = std::string(), size_t capacity=1024);
+
+ /**
+ * Since the point of WorkSchedule is to pass work to some other worker
+ * thread(s) asynchronously, it's important that the WorkSchedule continue
+ * to exist until the worker thread(s) have drained it. To communicate
+ * that it's time for them to quit, close() the queue.
+ */
+ void close() override;
+
+ /**
+ * WorkSchedule supports multiple producers and multiple consumers. In
+ * the general case it's misleading to test size(), since any other
+ * thread might change it the nanosecond the lock is released. On that
+ * basis, some might argue against publishing a size() method at all.
+ *
+ * But there are two specific cases in which a test based on size()
+ * might be reasonable:
+ *
+ * * If you're the only producer, noticing that size() == 0 is
+ * meaningful.
+ * * If you're the only consumer, noticing that size() > 0 is
+ * meaningful.
+ */
+ size_t size() override;
+ /// producer end: are we prevented from pushing any additional items?
+ bool isClosed() override;
+ /// consumer end: are we done, is the queue entirely drained?
+ bool done() override;
+
+ /*---------------------- fire and forget API -----------------------*/
+
+ /// fire-and-forget
+ void post(const Work& callable) override;
+
+ /// fire-and-forget, but at a particular (future?) time
+ void post(const Work& callable, const TimePoint& time);
+
+ /**
+ * post work, unless the queue is closed before we can post
+ */
+ bool postIfOpen(const Work& callable) override;
+
+ /**
+ * post work for a particular time, unless the queue is closed before
+ * we can post
+ */
+ bool postIfOpen(const Work& callable, const TimePoint& time);
+
+ /**
+ * post work, unless the queue is full
+ */
+ bool tryPost(const Work& callable) override;
+
+ /**
+ * post work for a particular time, unless the queue is full
+ */
+ bool tryPost(const Work& callable, const TimePoint& time);
+
+ /**
+ * Launch a callable returning bool that will trigger repeatedly at
+ * specified interval, until the callable returns false.
+ *
+ * If you need to signal that callable from outside, DO NOT bind a
+ * reference to a simple bool! That's not thread-safe. Instead, bind
+ * an LLCond variant, e.g. LLOneShotCond or LLBoolCond.
+ */
+ template <typename Rep, typename Period, typename CALLABLE>
+ void postEvery(const std::chrono::duration<Rep, Period>& interval,
+ CALLABLE&& callable);
+
+ private:
+ Queue mQueue;
+
+ Work pop_() override;
+ bool tryPop_(Work&) override;
};
/**
- * BackJack is, in effect, a hand-rolled lambda, binding a WorkQueue, a
+ * BackJack is, in effect, a hand-rolled lambda, binding a WorkSchedule, a
* CALLABLE that returns bool, a TimePoint and an interval at which to
* relaunch it. As long as the callable continues returning true, BackJack
* keeps resubmitting it to the target WorkQueue.
@@ -305,7 +376,7 @@ namespace LL
// class method gets its own 'this' pointer -- which we need to resubmit
// the whole BackJack callable.
template <typename Rep, typename Period, typename CALLABLE>
- class WorkQueue::BackJack
+ class WorkSchedule::BackJack
{
public:
// bind the desired data
@@ -319,9 +390,10 @@ namespace LL
mCallable(std::move(callable))
{}
- // Call by target WorkQueue -- note that although WE require a
- // callable returning bool, WorkQueue wants a void callable. We
- // consume the bool.
+ // This operator() method, called by target WorkSchedule, is what
+ // makes this object a Work item. Although WE require a callable
+ // returning bool, WorkSchedule wants a void callable. We consume the
+ // bool.
void operator()()
{
// If mCallable() throws an exception, don't catch it here: if it
@@ -337,7 +409,7 @@ namespace LL
// register our intent to fire at exact mIntervals.
mStart += mInterval;
- // We're being called at this moment by the target WorkQueue.
+ // We're being called at this moment by the target WorkSchedule.
// Assume it still exists, rather than checking the result of
// lock().
// Resubmit the whole *this callable: that's why we're a class
@@ -347,7 +419,8 @@ namespace LL
// moved-from.
try
{
- mTarget.lock()->post(mStart, std::move(*this));
+ auto target{ std::dynamic_pointer_cast<WorkSchedule>(mTarget.lock()) };
+ target->post(std::move(*this), mStart);
}
catch (const Closed&)
{
@@ -364,8 +437,8 @@ namespace LL
};
template <typename Rep, typename Period, typename CALLABLE>
- void WorkQueue::postEvery(const std::chrono::duration<Rep, Period>& interval,
- CALLABLE&& callable)
+ void WorkSchedule::postEvery(const std::chrono::duration<Rep, Period>& interval,
+ CALLABLE&& callable)
{
if (interval.count() <= 0)
{
@@ -388,7 +461,7 @@ namespace LL
/// general case: arbitrary C++ return type
template <typename CALLABLE, typename FOLLOWUP, typename RETURNTYPE>
- struct WorkQueue::MakeReplyLambda
+ struct WorkQueueBase::MakeReplyLambda
{
auto operator()(CALLABLE&& callable, FOLLOWUP&& callback)
{
@@ -409,7 +482,7 @@ namespace LL
/// specialize for CALLABLE returning void
template <typename CALLABLE, typename FOLLOWUP>
- struct WorkQueue::MakeReplyLambda<CALLABLE, FOLLOWUP, void>
+ struct WorkQueueBase::MakeReplyLambda<CALLABLE, FOLLOWUP, void>
{
auto operator()(CALLABLE&& callable, FOLLOWUP&& callback)
{
@@ -421,16 +494,16 @@ namespace LL
};
template <typename CALLABLE, typename FOLLOWUP>
- auto WorkQueue::makeReplyLambda(CALLABLE&& callable, FOLLOWUP&& callback)
+ auto WorkQueueBase::makeReplyLambda(CALLABLE&& callable, FOLLOWUP&& callback)
{
return MakeReplyLambda<CALLABLE, FOLLOWUP,
decltype(std::forward<CALLABLE>(callable)())>()
(std::move(callable), std::move(callback));
}
- template <typename CALLABLE, typename FOLLOWUP>
- bool WorkQueue::postTo(weak_t target,
- const TimePoint& time, CALLABLE&& callable, FOLLOWUP&& callback)
+ template <typename CALLABLE, typename FOLLOWUP, typename... ARGS>
+ bool WorkQueueBase::postTo(weak_t target, CALLABLE&& callable, FOLLOWUP&& callback,
+ ARGS&&... args)
{
LL_PROFILE_ZONE_SCOPED;
// We're being asked to post to the WorkQueue at target.
@@ -444,12 +517,11 @@ namespace LL
// lambda that packages our callable, our callback and a weak_ptr
// to this originating WorkQueue.
tptr->post(
- time,
[reply = super::getWeak(),
callable = std::move(callable),
callback = std::move(callback)]
- ()
- mutable {
+ () mutable
+ {
// Use postMaybe() below in case this originating WorkQueue
// has been closed or destroyed. Remember, the outer lambda is
// now running on a thread servicing the target WorkQueue, and
@@ -472,14 +544,16 @@ namespace LL
// originating WorkQueue. Once there, rethrow it.
[exc = std::current_exception()](){ std::rethrow_exception(exc); });
}
- });
+ },
+ // if caller passed a TimePoint, pass it along to post()
+ std::forward<ARGS>(args)...);
// looks like we were able to post()
return true;
}
- template <typename CALLABLE>
- bool WorkQueue::postMaybe(weak_t target, const TimePoint& time, CALLABLE&& callable)
+ template <typename... ARGS>
+ bool WorkQueueBase::postMaybe(weak_t target, ARGS&&... args)
{
LL_PROFILE_ZONE_SCOPED;
// target is a weak_ptr: have to lock it to check it
@@ -488,7 +562,7 @@ namespace LL
{
try
{
- tptr->post(time, std::forward<CALLABLE>(callable));
+ tptr->post(std::forward<ARGS>(args)...);
// we were able to post()
return true;
}
@@ -503,13 +577,13 @@ namespace LL
/// general case: arbitrary C++ return type
template <typename CALLABLE, typename RETURNTYPE>
- struct WorkQueue::WaitForResult
+ struct WorkQueueBase::WaitForResult
{
- auto operator()(WorkQueue* self, const TimePoint& time, CALLABLE&& callable)
+ template <typename... ARGS>
+ auto operator()(WorkQueueBase* self, CALLABLE&& callable, ARGS&&... args)
{
LLCoros::Promise<RETURNTYPE> promise;
self->post(
- time,
// We dare to bind a reference to Promise because it's
// specifically designed for cross-thread communication.
[&promise, callable = std::move(callable)]()
@@ -523,7 +597,9 @@ namespace LL
{
promise.set_exception(std::current_exception());
}
- });
+ },
+ // if caller passed a TimePoint, pass it to post()
+ std::forward<ARGS>(args)...);
auto future{ LLCoros::getFuture(promise) };
// now, on the calling thread, wait for that result
LLCoros::TempStatus st("waiting for WorkQueue::waitForResult()");
@@ -533,13 +609,13 @@ namespace LL
/// specialize for CALLABLE returning void
template <typename CALLABLE>
- struct WorkQueue::WaitForResult<CALLABLE, void>
+ struct WorkQueueBase::WaitForResult<CALLABLE, void>
{
- void operator()(WorkQueue* self, const TimePoint& time, CALLABLE&& callable)
+ template <typename... ARGS>
+ void operator()(WorkQueueBase* self, CALLABLE&& callable, ARGS&&... args)
{
LLCoros::Promise<void> promise;
self->post(
- time,
// &promise is designed for cross-thread access
[&promise, callable = std::move(callable)]()
mutable {
@@ -552,7 +628,9 @@ namespace LL
{
promise.set_exception(std::current_exception());
}
- });
+ },
+ // if caller passed a TimePoint, pass it to post()
+ std::forward<ARGS>(args)...);
auto future{ LLCoros::getFuture(promise) };
// block until set_value()
LLCoros::TempStatus st("waiting for void WorkQueue::waitForResult()");
@@ -560,13 +638,13 @@ namespace LL
}
};
- template <typename CALLABLE>
- auto WorkQueue::waitForResult(const TimePoint& time, CALLABLE&& callable)
+ template <typename CALLABLE, typename... ARGS>
+ auto WorkQueueBase::waitForResult(CALLABLE&& callable, ARGS&&... args)
{
checkCoroutine("waitForResult()");
// derive callable's return type so we can specialize for void
return WaitForResult<CALLABLE, decltype(std::forward<CALLABLE>(callable)())>()
- (this, time, std::forward<CALLABLE>(callable));
+ (this, std::forward<CALLABLE>(callable), std::forward<ARGS>(args)...);
}
} // namespace LL
diff --git a/indra/llcorehttp/_httplibcurl.cpp b/indra/llcorehttp/_httplibcurl.cpp
index 975ce8a4d5..bd0ac740db 100644
--- a/indra/llcorehttp/_httplibcurl.cpp
+++ b/indra/llcorehttp/_httplibcurl.cpp
@@ -113,6 +113,7 @@ void HttpLibcurl::shutdown()
void HttpLibcurl::start(int policy_count)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
llassert_always(policy_count <= HTTP_POLICY_CLASS_LIMIT);
llassert_always(! mMultiHandles); // One-time call only
@@ -143,6 +144,7 @@ void HttpLibcurl::start(int policy_count)
// sleep otherwise ask for a normal polling interval.
HttpService::ELoopSpeed HttpLibcurl::processTransport()
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
HttpService::ELoopSpeed ret(HttpService::REQUEST_SLEEP);
// Give libcurl some cycles to do I/O & callbacks
@@ -168,6 +170,7 @@ HttpService::ELoopSpeed HttpLibcurl::processTransport()
CURLMcode status(CURLM_CALL_MULTI_PERFORM);
do
{
+ LL_PROFILE_ZONE_NAMED_CATEGORY_NETWORK("httppt - curl_multi_perform");
running = 0;
status = curl_multi_perform(mMultiHandles[policy_class], &running);
}
@@ -176,31 +179,34 @@ HttpService::ELoopSpeed HttpLibcurl::processTransport()
// Run completion on anything done
CURLMsg * msg(NULL);
int msgs_in_queue(0);
- while ((msg = curl_multi_info_read(mMultiHandles[policy_class], &msgs_in_queue)))
- {
- if (CURLMSG_DONE == msg->msg)
- {
- CURL * handle(msg->easy_handle);
- CURLcode result(msg->data.result);
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_NETWORK("httppt - curl_multi_info_read");
+ while ((msg = curl_multi_info_read(mMultiHandles[policy_class], &msgs_in_queue)))
+ {
+ if (CURLMSG_DONE == msg->msg)
+ {
+ CURL* handle(msg->easy_handle);
+ CURLcode result(msg->data.result);
- completeRequest(mMultiHandles[policy_class], handle, result);
- handle = NULL; // No longer valid on return
- ret = HttpService::NORMAL; // If anything completes, we may have a free slot.
- // Turning around quickly reduces connection gap by 7-10mS.
- }
- else if (CURLMSG_NONE == msg->msg)
- {
- // Ignore this... it shouldn't mean anything.
- ;
- }
- else
- {
- LL_WARNS_ONCE(LOG_CORE) << "Unexpected message from libcurl. Msg code: "
- << msg->msg
- << LL_ENDL;
- }
- msgs_in_queue = 0;
- }
+ completeRequest(mMultiHandles[policy_class], handle, result);
+ handle = NULL; // No longer valid on return
+ ret = HttpService::NORMAL; // If anything completes, we may have a free slot.
+ // Turning around quickly reduces connection gap by 7-10mS.
+ }
+ else if (CURLMSG_NONE == msg->msg)
+ {
+ // Ignore this... it shouldn't mean anything.
+ ;
+ }
+ else
+ {
+ LL_WARNS_ONCE(LOG_CORE) << "Unexpected message from libcurl. Msg code: "
+ << msg->msg
+ << LL_ENDL;
+ }
+ msgs_in_queue = 0;
+ }
+ }
}
if (! mActiveOps.empty())
@@ -214,6 +220,7 @@ HttpService::ELoopSpeed HttpLibcurl::processTransport()
// Caller has provided us with a ref count on op.
void HttpLibcurl::addOp(const HttpOpRequest::ptr_t &op)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
llassert_always(op->mReqPolicy < mPolicyCount);
llassert_always(mMultiHandles[op->mReqPolicy] != NULL);
@@ -257,6 +264,7 @@ void HttpLibcurl::addOp(const HttpOpRequest::ptr_t &op)
// method to kill the request.
bool HttpLibcurl::cancel(HttpHandle handle)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
HttpOpRequest::ptr_t op = HttpOpRequest::fromHandle<HttpOpRequest>(handle);
active_set_t::iterator it(mActiveOps.find(op));
if (mActiveOps.end() == it)
@@ -282,6 +290,7 @@ bool HttpLibcurl::cancel(HttpHandle handle)
// op to the reply queue with refcount intact.
void HttpLibcurl::cancelRequest(const HttpOpRequest::ptr_t &op)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
// Deactivate request
op->mCurlActive = false;
@@ -308,6 +317,7 @@ void HttpLibcurl::cancelRequest(const HttpOpRequest::ptr_t &op)
// Keep them synchronized as necessary.
bool HttpLibcurl::completeRequest(CURLM * multi_handle, CURL * handle, CURLcode status)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
HttpHandle ophandle(NULL);
CURLcode ccode(CURLE_OK);
@@ -445,6 +455,7 @@ int HttpLibcurl::getActiveCountInClass(int policy_class) const
void HttpLibcurl::policyUpdated(int policy_class)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
if (policy_class < 0 || policy_class >= mPolicyCount || ! mMultiHandles)
{
return;
diff --git a/indra/llcorehttp/_httpoperation.cpp b/indra/llcorehttp/_httpoperation.cpp
index 3fc4e28910..3b64018132 100644
--- a/indra/llcorehttp/_httpoperation.cpp
+++ b/indra/llcorehttp/_httpoperation.cpp
@@ -62,7 +62,6 @@ HttpOperation::HttpOperation():
mReplyQueue(),
mUserHandler(),
mReqPolicy(HttpRequest::DEFAULT_POLICY_ID),
- mReqPriority(0U),
mTracing(HTTP_TRACE_OFF),
mMyHandle(LLCORE_HTTP_HANDLE_INVALID)
{
diff --git a/indra/llcorehttp/_httpoperation.h b/indra/llcorehttp/_httpoperation.h
index 1a75921c09..8c1364bab4 100644
--- a/indra/llcorehttp/_httpoperation.h
+++ b/indra/llcorehttp/_httpoperation.h
@@ -181,7 +181,6 @@ protected:
public:
// Request Data
HttpRequest::policy_t mReqPolicy;
- HttpRequest::priority_t mReqPriority;
// Reply Data
HttpStatus mStatus;
diff --git a/indra/llcorehttp/_httpoprequest.cpp b/indra/llcorehttp/_httpoprequest.cpp
index ba31290c24..d60eb6c95f 100644
--- a/indra/llcorehttp/_httpoprequest.cpp
+++ b/indra/llcorehttp/_httpoprequest.cpp
@@ -200,6 +200,7 @@ HttpOpRequest::~HttpOpRequest()
void HttpOpRequest::stageFromRequest(HttpService * service)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
HttpOpRequest::ptr_t self(boost::dynamic_pointer_cast<HttpOpRequest>(shared_from_this()));
service->getPolicy().addOp(self); // transfers refcount
}
@@ -207,6 +208,7 @@ void HttpOpRequest::stageFromRequest(HttpService * service)
void HttpOpRequest::stageFromReady(HttpService * service)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
HttpOpRequest::ptr_t self(boost::dynamic_pointer_cast<HttpOpRequest>(shared_from_this()));
service->getTransport().addOp(self); // transfers refcount
}
@@ -214,6 +216,7 @@ void HttpOpRequest::stageFromReady(HttpService * service)
void HttpOpRequest::stageFromActive(HttpService * service)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
if (mReplyLength)
{
// If non-zero, we received and processed a Content-Range
@@ -250,6 +253,7 @@ void HttpOpRequest::stageFromActive(HttpService * service)
void HttpOpRequest::visitNotifier(HttpRequest * request)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
if (mUserHandler)
{
HttpResponse * response = new HttpResponse();
@@ -292,6 +296,7 @@ void HttpOpRequest::visitNotifier(HttpRequest * request)
HttpStatus HttpOpRequest::cancel()
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
mStatus = HttpStatus(HttpStatus::LLCORE, HE_OP_CANCELED);
addAsReply();
@@ -301,12 +306,12 @@ HttpStatus HttpOpRequest::cancel()
HttpStatus HttpOpRequest::setupGet(HttpRequest::policy_t policy_id,
- HttpRequest::priority_t priority,
const std::string & url,
const HttpOptions::ptr_t & options,
const HttpHeaders::ptr_t & headers)
{
- setupCommon(policy_id, priority, url, NULL, options, headers);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
+ setupCommon(policy_id, url, NULL, options, headers);
mReqMethod = HOR_GET;
return HttpStatus();
@@ -314,14 +319,14 @@ HttpStatus HttpOpRequest::setupGet(HttpRequest::policy_t policy_id,
HttpStatus HttpOpRequest::setupGetByteRange(HttpRequest::policy_t policy_id,
- HttpRequest::priority_t priority,
const std::string & url,
size_t offset,
size_t len,
const HttpOptions::ptr_t & options,
const HttpHeaders::ptr_t & headers)
{
- setupCommon(policy_id, priority, url, NULL, options, headers);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
+ setupCommon(policy_id, url, NULL, options, headers);
mReqMethod = HOR_GET;
mReqOffset = offset;
mReqLength = len;
@@ -335,13 +340,13 @@ HttpStatus HttpOpRequest::setupGetByteRange(HttpRequest::policy_t policy_id,
HttpStatus HttpOpRequest::setupPost(HttpRequest::policy_t policy_id,
- HttpRequest::priority_t priority,
const std::string & url,
BufferArray * body,
const HttpOptions::ptr_t & options,
const HttpHeaders::ptr_t & headers)
{
- setupCommon(policy_id, priority, url, body, options, headers);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
+ setupCommon(policy_id, url, body, options, headers);
mReqMethod = HOR_POST;
return HttpStatus();
@@ -349,13 +354,13 @@ HttpStatus HttpOpRequest::setupPost(HttpRequest::policy_t policy_id,
HttpStatus HttpOpRequest::setupPut(HttpRequest::policy_t policy_id,
- HttpRequest::priority_t priority,
const std::string & url,
BufferArray * body,
const HttpOptions::ptr_t & options,
const HttpHeaders::ptr_t & headers)
{
- setupCommon(policy_id, priority, url, body, options, headers);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
+ setupCommon(policy_id, url, body, options, headers);
mReqMethod = HOR_PUT;
return HttpStatus();
@@ -363,12 +368,12 @@ HttpStatus HttpOpRequest::setupPut(HttpRequest::policy_t policy_id,
HttpStatus HttpOpRequest::setupDelete(HttpRequest::policy_t policy_id,
- HttpRequest::priority_t priority,
const std::string & url,
const HttpOptions::ptr_t & options,
const HttpHeaders::ptr_t & headers)
{
- setupCommon(policy_id, priority, url, NULL, options, headers);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
+ setupCommon(policy_id, url, NULL, options, headers);
mReqMethod = HOR_DELETE;
return HttpStatus();
@@ -376,13 +381,13 @@ HttpStatus HttpOpRequest::setupDelete(HttpRequest::policy_t policy_id,
HttpStatus HttpOpRequest::setupPatch(HttpRequest::policy_t policy_id,
- HttpRequest::priority_t priority,
const std::string & url,
BufferArray * body,
const HttpOptions::ptr_t & options,
const HttpHeaders::ptr_t & headers)
{
- setupCommon(policy_id, priority, url, body, options, headers);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
+ setupCommon(policy_id, url, body, options, headers);
mReqMethod = HOR_PATCH;
return HttpStatus();
@@ -390,12 +395,12 @@ HttpStatus HttpOpRequest::setupPatch(HttpRequest::policy_t policy_id,
HttpStatus HttpOpRequest::setupCopy(HttpRequest::policy_t policy_id,
- HttpRequest::priority_t priority,
const std::string & url,
const HttpOptions::ptr_t & options,
const HttpHeaders::ptr_t &headers)
{
- setupCommon(policy_id, priority, url, NULL, options, headers);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
+ setupCommon(policy_id, url, NULL, options, headers);
mReqMethod = HOR_COPY;
return HttpStatus();
@@ -403,12 +408,12 @@ HttpStatus HttpOpRequest::setupCopy(HttpRequest::policy_t policy_id,
HttpStatus HttpOpRequest::setupMove(HttpRequest::policy_t policy_id,
- HttpRequest::priority_t priority,
const std::string & url,
const HttpOptions::ptr_t & options,
const HttpHeaders::ptr_t &headers)
{
- setupCommon(policy_id, priority, url, NULL, options, headers);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
+ setupCommon(policy_id, url, NULL, options, headers);
mReqMethod = HOR_MOVE;
return HttpStatus();
@@ -416,15 +421,14 @@ HttpStatus HttpOpRequest::setupMove(HttpRequest::policy_t policy_id,
void HttpOpRequest::setupCommon(HttpRequest::policy_t policy_id,
- HttpRequest::priority_t priority,
const std::string & url,
BufferArray * body,
const HttpOptions::ptr_t & options,
const HttpHeaders::ptr_t & headers)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
mProcFlags = 0U;
mReqPolicy = policy_id;
- mReqPriority = priority;
mReqURL = url;
if (body)
{
@@ -465,6 +469,7 @@ void HttpOpRequest::setupCommon(HttpRequest::policy_t policy_id,
// *TODO: Move this to _httplibcurl where it belongs.
HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
// Scrub transport and result data for retried op case
mCurlActive = false;
mCurlHandle = NULL;
@@ -773,6 +778,7 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
size_t HttpOpRequest::writeCallback(void * data, size_t size, size_t nmemb, void * userdata)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
HttpOpRequest::ptr_t op(HttpOpRequest::fromHandle<HttpOpRequest>(userdata));
if (! op->mReplyBody)
@@ -788,6 +794,7 @@ size_t HttpOpRequest::writeCallback(void * data, size_t size, size_t nmemb, void
size_t HttpOpRequest::readCallback(void * data, size_t size, size_t nmemb, void * userdata)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
HttpOpRequest::ptr_t op(HttpOpRequest::fromHandle<HttpOpRequest>(userdata));
if (! op->mReqBody)
@@ -819,6 +826,7 @@ size_t HttpOpRequest::readCallback(void * data, size_t size, size_t nmemb, void
int HttpOpRequest::seekCallback(void *userdata, curl_off_t offset, int origin)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
HttpOpRequest::ptr_t op(HttpOpRequest::fromHandle<HttpOpRequest>(userdata));
if (!op->mReqBody)
@@ -850,6 +858,7 @@ int HttpOpRequest::seekCallback(void *userdata, curl_off_t offset, int origin)
size_t HttpOpRequest::headerCallback(void * data, size_t size, size_t nmemb, void * userdata)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
static const char status_line[] = "HTTP/";
static const size_t status_line_len = sizeof(status_line) - 1;
static const char con_ran_line[] = "content-range";
@@ -999,6 +1008,7 @@ size_t HttpOpRequest::headerCallback(void * data, size_t size, size_t nmemb, voi
CURLcode HttpOpRequest::curlSslCtxCallback(CURL *curl, void *sslctx, void *userdata)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
HttpOpRequest::ptr_t op(HttpOpRequest::fromHandle<HttpOpRequest>(userdata));
if (op->mCallbackSSLVerify)
@@ -1025,6 +1035,7 @@ CURLcode HttpOpRequest::curlSslCtxCallback(CURL *curl, void *sslctx, void *userd
int HttpOpRequest::sslCertVerifyCallback(X509_STORE_CTX *ctx, void *param)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
HttpOpRequest::ptr_t op(HttpOpRequest::fromHandle<HttpOpRequest>(param));
if (op->mCallbackSSLVerify)
@@ -1037,6 +1048,7 @@ int HttpOpRequest::sslCertVerifyCallback(X509_STORE_CTX *ctx, void *param)
int HttpOpRequest::debugCallback(CURL * handle, curl_infotype info, char * buffer, size_t len, void * userdata)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
HttpOpRequest::ptr_t op(HttpOpRequest::fromHandle<HttpOpRequest>(userdata));
std::string safe_line;
diff --git a/indra/llcorehttp/_httpoprequest.h b/indra/llcorehttp/_httpoprequest.h
index cdbe350785..ec84822cf4 100644
--- a/indra/llcorehttp/_httpoprequest.h
+++ b/indra/llcorehttp/_httpoprequest.h
@@ -105,13 +105,11 @@ public:
/// Threading: called by application thread
///
HttpStatus setupGet(HttpRequest::policy_t policy_id,
- HttpRequest::priority_t priority,
const std::string & url,
const HttpOptions::ptr_t & options,
const HttpHeaders::ptr_t & headers);
HttpStatus setupGetByteRange(HttpRequest::policy_t policy_id,
- HttpRequest::priority_t priority,
const std::string & url,
size_t offset,
size_t len,
@@ -119,40 +117,34 @@ public:
const HttpHeaders::ptr_t & headers);
HttpStatus setupPost(HttpRequest::policy_t policy_id,
- HttpRequest::priority_t priority,
const std::string & url,
BufferArray * body,
const HttpOptions::ptr_t & options,
const HttpHeaders::ptr_t & headers);
HttpStatus setupPut(HttpRequest::policy_t policy_id,
- HttpRequest::priority_t priority,
const std::string & url,
BufferArray * body,
const HttpOptions::ptr_t & options,
const HttpHeaders::ptr_t & headers);
HttpStatus setupDelete(HttpRequest::policy_t policy_id,
- HttpRequest::priority_t priority,
const std::string & url,
const HttpOptions::ptr_t & options,
const HttpHeaders::ptr_t & headers);
HttpStatus setupPatch(HttpRequest::policy_t policy_id,
- HttpRequest::priority_t priority,
const std::string & url,
BufferArray * body,
const HttpOptions::ptr_t & options,
const HttpHeaders::ptr_t & headers);
HttpStatus setupCopy(HttpRequest::policy_t policy_id,
- HttpRequest::priority_t priority,
const std::string & url,
const HttpOptions::ptr_t & options,
const HttpHeaders::ptr_t & headers);
HttpStatus setupMove(HttpRequest::policy_t policy_id,
- HttpRequest::priority_t priority,
const std::string & url,
const HttpOptions::ptr_t & options,
const HttpHeaders::ptr_t & headers);
@@ -172,7 +164,6 @@ protected:
// Threading: called by application thread
//
void setupCommon(HttpRequest::policy_t policy_id,
- HttpRequest::priority_t priority,
const std::string & url,
BufferArray * body,
const HttpOptions::ptr_t & options,
@@ -239,19 +230,6 @@ public:
-/// HttpOpRequestCompare isn't an operation but a uniform comparison
-/// functor for STL containers that order by priority. Mainly
-/// used for the ready queue container but defined here.
-class HttpOpRequestCompare
-{
-public:
- bool operator()(const HttpOpRequest * lhs, const HttpOpRequest * rhs)
- {
- return lhs->mReqPriority > rhs->mReqPriority;
- }
-}; // end class HttpOpRequestCompare
-
-
// ---------------------------------------
// Free functions
// ---------------------------------------
diff --git a/indra/llcorehttp/_httpopsetpriority.cpp b/indra/llcorehttp/_httpopsetpriority.cpp
index d48c7a0b7d..b99b4e9e4a 100644
--- a/indra/llcorehttp/_httpopsetpriority.cpp
+++ b/indra/llcorehttp/_httpopsetpriority.cpp
@@ -24,6 +24,7 @@
* $/LicenseInfo$
*/
+#if 0 // DEPRECATED
#include "_httpopsetpriority.h"
#include "httpresponse.h"
@@ -61,3 +62,5 @@ void HttpOpSetPriority::stageFromRequest(HttpService * service)
} // end namespace LLCore
+
+#endif
diff --git a/indra/llcorehttp/_httpopsetpriority.h b/indra/llcorehttp/_httpopsetpriority.h
index 43e2aa081b..fd543f37cc 100644
--- a/indra/llcorehttp/_httpopsetpriority.h
+++ b/indra/llcorehttp/_httpopsetpriority.h
@@ -27,7 +27,7 @@
#ifndef _LLCORE_HTTP_SETPRIORITY_H_
#define _LLCORE_HTTP_SETPRIORITY_H_
-
+#if 0 // DEPRECATED
#include "httpcommon.h"
#include "httprequest.h"
#include "_httpoperation.h"
@@ -49,7 +49,7 @@ namespace LLCore
class HttpOpSetPriority : public HttpOperation
{
public:
- HttpOpSetPriority(HttpHandle handle, HttpRequest::priority_t priority);
+ HttpOpSetPriority(HttpHandle handle);
virtual ~HttpOpSetPriority();
@@ -63,10 +63,10 @@ public:
protected:
// Request Data
HttpHandle mHandle;
- HttpRequest::priority_t mPriority;
}; // end class HttpOpSetPriority
} // end namespace LLCore
+#endif
#endif // _LLCORE_HTTP_SETPRIORITY_H_
diff --git a/indra/llcorehttp/_httppolicy.cpp b/indra/llcorehttp/_httppolicy.cpp
index 885f0ed61d..29f50c1693 100644
--- a/indra/llcorehttp/_httppolicy.cpp
+++ b/indra/llcorehttp/_httppolicy.cpp
@@ -330,37 +330,6 @@ HttpService::ELoopSpeed HttpPolicy::processReadyQueue()
return result;
}
-
-bool HttpPolicy::changePriority(HttpHandle handle, HttpRequest::priority_t priority)
-{
- for (int policy_class(0); policy_class < mClasses.size(); ++policy_class)
- {
- ClassState & state(*mClasses[policy_class]);
- // We don't scan retry queue because a priority change there
- // is meaningless. The request will be issued based on retry
- // intervals not priority value, which is now moot.
-
- // Scan ready queue for requests that match policy
- HttpReadyQueue::container_type & c(state.mReadyQueue.get_container());
- for (HttpReadyQueue::container_type::iterator iter(c.begin()); c.end() != iter;)
- {
- HttpReadyQueue::container_type::iterator cur(iter++);
-
- if ((*cur)->getHandle() == handle)
- {
- HttpOpRequest::ptr_t op(*cur);
- c.erase(cur); // All iterators are now invalidated
- op->mReqPriority = priority;
- state.mReadyQueue.push(op); // Re-insert using adapter class
- return true;
- }
- }
- }
-
- return false;
-}
-
-
bool HttpPolicy::cancel(HttpHandle handle)
{
for (int policy_class(0); policy_class < mClasses.size(); ++policy_class)
diff --git a/indra/llcorehttp/_httppolicy.h b/indra/llcorehttp/_httppolicy.h
index 3c4126e14b..0b8806a3e2 100644
--- a/indra/llcorehttp/_httppolicy.h
+++ b/indra/llcorehttp/_httppolicy.h
@@ -110,12 +110,6 @@ public:
/// Threading: called by worker thread
void retryOp(const opReqPtr_t &);
- /// Attempt to change the priority of an earlier request.
- /// Request that Shadows HttpService's method
- ///
- /// Threading: called by worker thread
- bool changePriority(HttpHandle handle, HttpRequest::priority_t priority);
-
/// Attempt to cancel a previous request.
/// Shadows HttpService's method as well
///
diff --git a/indra/llcorehttp/_httpservice.cpp b/indra/llcorehttp/_httpservice.cpp
index 56f52f1b09..294acd7f63 100644
--- a/indra/llcorehttp/_httpservice.cpp
+++ b/indra/llcorehttp/_httpservice.cpp
@@ -80,6 +80,7 @@ HttpService::HttpService()
HttpService::~HttpService()
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
mExitRequested = 1U;
if (RUNNING == sState)
{
@@ -131,6 +132,7 @@ HttpService::~HttpService()
void HttpService::init(HttpRequestQueue * queue)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
llassert_always(! sInstance);
llassert_always(NOT_INITIALIZED == sState);
sInstance = new HttpService();
@@ -145,6 +147,7 @@ void HttpService::init(HttpRequestQueue * queue)
void HttpService::term()
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
if (sInstance)
{
if (RUNNING == sState && sInstance->mThread)
@@ -196,6 +199,7 @@ bool HttpService::isStopped()
/// Threading: callable by consumer thread *once*.
void HttpService::startThread()
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
llassert_always(! mThread || STOPPED == sState);
llassert_always(INITIALIZED == sState || STOPPED == sState);
@@ -220,22 +224,6 @@ void HttpService::stopRequested()
}
-/// Threading: callable by worker thread.
-bool HttpService::changePriority(HttpHandle handle, HttpRequest::priority_t priority)
-{
- bool found(false);
-
- // Skip the request queue as we currently don't leave earlier
- // requests sitting there. Start with the ready queue...
- found = mPolicy->changePriority(handle, priority);
-
- // If not there, we could try the transport/active queue but priority
- // doesn't really have much effect there so we don't waste cycles.
-
- return found;
-}
-
-
/// Try to find the given request handle on any of the request
/// queues and cancel the operation.
///
@@ -244,6 +232,7 @@ bool HttpService::changePriority(HttpHandle handle, HttpRequest::priority_t prio
/// Threading: callable by worker thread.
bool HttpService::cancel(HttpHandle handle)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
bool canceled(false);
// Request can't be on request queue so skip that.
@@ -264,6 +253,7 @@ bool HttpService::cancel(HttpHandle handle)
/// Threading: callable by worker thread.
void HttpService::shutdown()
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
// Disallow future enqueue of requests
mRequestQueue->stopQueue();
@@ -293,6 +283,8 @@ void HttpService::shutdown()
// requested to stop.
void HttpService::threadRun(LLCoreInt::HttpThread * thread)
{
+ LL_PROFILER_SET_THREAD_NAME("HttpService");
+
boost::this_thread::disable_interruption di;
LLThread::registerThreadID();
@@ -300,6 +292,7 @@ void HttpService::threadRun(LLCoreInt::HttpThread * thread)
ELoopSpeed loop(REQUEST_SLEEP);
while (! mExitRequested)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
try
{
loop = processRequestQueue(loop);
@@ -344,6 +337,7 @@ void HttpService::threadRun(LLCoreInt::HttpThread * thread)
HttpService::ELoopSpeed HttpService::processRequestQueue(ELoopSpeed loop)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
HttpRequestQueue::OpContainer ops;
const bool wait_for_req(REQUEST_SLEEP == loop);
@@ -384,6 +378,7 @@ HttpService::ELoopSpeed HttpService::processRequestQueue(ELoopSpeed loop)
HttpStatus HttpService::getPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t pclass,
long * ret_value)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
if (opt < HttpRequest::PO_CONNECTION_LIMIT // option must be in range
|| opt >= HttpRequest::PO_LAST // ditto
|| (! sOptionDesc[opt].mIsLong) // datatype is long
@@ -416,6 +411,7 @@ HttpStatus HttpService::getPolicyOption(HttpRequest::EPolicyOption opt, HttpRequ
HttpStatus HttpService::getPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t pclass,
std::string * ret_value)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
HttpStatus status(HttpStatus::LLCORE, LLCore::HE_INVALID_ARG);
if (opt < HttpRequest::PO_CONNECTION_LIMIT // option must be in range
@@ -443,6 +439,7 @@ HttpStatus HttpService::getPolicyOption(HttpRequest::EPolicyOption opt, HttpRequ
HttpStatus HttpService::getPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t pclass,
HttpRequest::policyCallback_t * ret_value)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
HttpStatus status(HttpStatus::LLCORE, LLCore::HE_INVALID_ARG);
if (opt < HttpRequest::PO_CONNECTION_LIMIT // option must be in range
@@ -472,6 +469,7 @@ HttpStatus HttpService::getPolicyOption(HttpRequest::EPolicyOption opt, HttpRequ
HttpStatus HttpService::setPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t pclass,
long value, long * ret_value)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
HttpStatus status(HttpStatus::LLCORE, LLCore::HE_INVALID_ARG);
if (opt < HttpRequest::PO_CONNECTION_LIMIT // option must be in range
@@ -517,6 +515,7 @@ HttpStatus HttpService::setPolicyOption(HttpRequest::EPolicyOption opt, HttpRequ
HttpStatus HttpService::setPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t pclass,
const std::string & value, std::string * ret_value)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
HttpStatus status(HttpStatus::LLCORE, LLCore::HE_INVALID_ARG);
if (opt < HttpRequest::PO_CONNECTION_LIMIT // option must be in range
@@ -548,6 +547,7 @@ HttpStatus HttpService::setPolicyOption(HttpRequest::EPolicyOption opt, HttpRequ
HttpStatus HttpService::setPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t pclass,
HttpRequest::policyCallback_t value, HttpRequest::policyCallback_t * ret_value)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
HttpStatus status(HttpStatus::LLCORE, LLCore::HE_INVALID_ARG);
if (opt < HttpRequest::PO_CONNECTION_LIMIT // option must be in range
diff --git a/indra/llcorehttp/_httpservice.h b/indra/llcorehttp/_httpservice.h
index d0c37ac195..551a718f20 100644
--- a/indra/llcorehttp/_httpservice.h
+++ b/indra/llcorehttp/_httpservice.h
@@ -147,15 +147,6 @@ public:
void shutdown();
/// Try to find the given request handle on any of the request
- /// queues and reset the priority (and queue position) of the
- /// request if found.
- ///
- /// @return True if the request was found somewhere.
- ///
- /// Threading: callable by worker thread.
- bool changePriority(HttpHandle handle, HttpRequest::priority_t priority);
-
- /// Try to find the given request handle on any of the request
/// queues and cancel the operation.
///
/// @return True if the request was found and canceled.
diff --git a/indra/llcorehttp/examples/http_texture_load.cpp b/indra/llcorehttp/examples/http_texture_load.cpp
index c7376042b3..cc53b20add 100644
--- a/indra/llcorehttp/examples/http_texture_load.cpp
+++ b/indra/llcorehttp/examples/http_texture_load.cpp
@@ -469,11 +469,11 @@ bool WorkingSet::reload(LLCore::HttpRequest * hr, LLCore::HttpOptions::ptr_t & o
LLCore::HttpHandle handle;
if (offset || length)
{
- handle = hr->requestGetByteRange(0, 0, buffer, offset, length, opt, mHeaders, LLCore::HttpHandler::ptr_t(this, NoOpDeletor));
+ handle = hr->requestGetByteRange(0, buffer, offset, length, opt, mHeaders, LLCore::HttpHandler::ptr_t(this, NoOpDeletor));
}
else
{
- handle = hr->requestGet(0, 0, buffer, opt, mHeaders, LLCore::HttpHandler::ptr_t(this, NoOpDeletor));
+ handle = hr->requestGet(0, buffer, opt, mHeaders, LLCore::HttpHandler::ptr_t(this, NoOpDeletor));
}
if (! handle)
{
diff --git a/indra/llcorehttp/httprequest.cpp b/indra/llcorehttp/httprequest.cpp
index 2687f77217..de3854a101 100644
--- a/indra/llcorehttp/httprequest.cpp
+++ b/indra/llcorehttp/httprequest.cpp
@@ -32,7 +32,6 @@
#include "_httppolicy.h"
#include "_httpoperation.h"
#include "_httpoprequest.h"
-#include "_httpopsetpriority.h"
#include "_httpopcancel.h"
#include "_httpopsetget.h"
@@ -183,16 +182,16 @@ HttpStatus HttpRequest::getStatus() const
HttpHandle HttpRequest::requestGet(policy_t policy_id,
- priority_t priority,
const std::string & url,
const HttpOptions::ptr_t & options,
const HttpHeaders::ptr_t & headers,
HttpHandler::ptr_t user_handler)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
HttpStatus status;
HttpOpRequest::ptr_t op(new HttpOpRequest());
- if (! (status = op->setupGet(policy_id, priority, url, options, headers)))
+ if (! (status = op->setupGet(policy_id, url, options, headers)))
{
mLastReqStatus = status;
return LLCORE_HTTP_HANDLE_INVALID;
@@ -210,7 +209,6 @@ HttpHandle HttpRequest::requestGet(policy_t policy_id,
HttpHandle HttpRequest::requestGetByteRange(policy_t policy_id,
- priority_t priority,
const std::string & url,
size_t offset,
size_t len,
@@ -218,10 +216,11 @@ HttpHandle HttpRequest::requestGetByteRange(policy_t policy_id,
const HttpHeaders::ptr_t & headers,
HttpHandler::ptr_t user_handler)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
HttpStatus status;
HttpOpRequest::ptr_t op(new HttpOpRequest());
- if (! (status = op->setupGetByteRange(policy_id, priority, url, offset, len, options, headers)))
+ if (! (status = op->setupGetByteRange(policy_id, url, offset, len, options, headers)))
{
mLastReqStatus = status;
return LLCORE_HTTP_HANDLE_INVALID;
@@ -239,7 +238,6 @@ HttpHandle HttpRequest::requestGetByteRange(policy_t policy_id,
HttpHandle HttpRequest::requestPost(policy_t policy_id,
- priority_t priority,
const std::string & url,
BufferArray * body,
const HttpOptions::ptr_t & options,
@@ -249,7 +247,7 @@ HttpHandle HttpRequest::requestPost(policy_t policy_id,
HttpStatus status;
HttpOpRequest::ptr_t op(new HttpOpRequest());
- if (! (status = op->setupPost(policy_id, priority, url, body, options, headers)))
+ if (! (status = op->setupPost(policy_id, url, body, options, headers)))
{
mLastReqStatus = status;
return LLCORE_HTTP_HANDLE_INVALID;
@@ -267,7 +265,6 @@ HttpHandle HttpRequest::requestPost(policy_t policy_id,
HttpHandle HttpRequest::requestPut(policy_t policy_id,
- priority_t priority,
const std::string & url,
BufferArray * body,
const HttpOptions::ptr_t & options,
@@ -277,7 +274,7 @@ HttpHandle HttpRequest::requestPut(policy_t policy_id,
HttpStatus status;
HttpOpRequest::ptr_t op (new HttpOpRequest());
- if (! (status = op->setupPut(policy_id, priority, url, body, options, headers)))
+ if (! (status = op->setupPut(policy_id, url, body, options, headers)))
{
mLastReqStatus = status;
return LLCORE_HTTP_HANDLE_INVALID;
@@ -294,7 +291,6 @@ HttpHandle HttpRequest::requestPut(policy_t policy_id,
}
HttpHandle HttpRequest::requestDelete(policy_t policy_id,
- priority_t priority,
const std::string & url,
const HttpOptions::ptr_t & options,
const HttpHeaders::ptr_t & headers,
@@ -303,7 +299,7 @@ HttpHandle HttpRequest::requestDelete(policy_t policy_id,
HttpStatus status;
HttpOpRequest::ptr_t op(new HttpOpRequest());
- if (!(status = op->setupDelete(policy_id, priority, url, options, headers)))
+ if (!(status = op->setupDelete(policy_id, url, options, headers)))
{
mLastReqStatus = status;
return LLCORE_HTTP_HANDLE_INVALID;
@@ -320,7 +316,6 @@ HttpHandle HttpRequest::requestDelete(policy_t policy_id,
}
HttpHandle HttpRequest::requestPatch(policy_t policy_id,
- priority_t priority,
const std::string & url,
BufferArray * body,
const HttpOptions::ptr_t & options,
@@ -330,7 +325,7 @@ HttpHandle HttpRequest::requestPatch(policy_t policy_id,
HttpStatus status;
HttpOpRequest::ptr_t op (new HttpOpRequest());
- if (!(status = op->setupPatch(policy_id, priority, url, body, options, headers)))
+ if (!(status = op->setupPatch(policy_id, url, body, options, headers)))
{
mLastReqStatus = status;
return LLCORE_HTTP_HANDLE_INVALID;
@@ -347,7 +342,6 @@ HttpHandle HttpRequest::requestPatch(policy_t policy_id,
}
HttpHandle HttpRequest::requestCopy(policy_t policy_id,
- priority_t priority,
const std::string & url,
const HttpOptions::ptr_t & options,
const HttpHeaders::ptr_t & headers,
@@ -356,7 +350,7 @@ HttpHandle HttpRequest::requestCopy(policy_t policy_id,
HttpStatus status;
HttpOpRequest::ptr_t op(new HttpOpRequest());
- if (!(status = op->setupCopy(policy_id, priority, url, options, headers)))
+ if (!(status = op->setupCopy(policy_id, url, options, headers)))
{
mLastReqStatus = status;
return LLCORE_HTTP_HANDLE_INVALID;
@@ -374,7 +368,6 @@ HttpHandle HttpRequest::requestCopy(policy_t policy_id,
}
HttpHandle HttpRequest::requestMove(policy_t policy_id,
- priority_t priority,
const std::string & url,
const HttpOptions::ptr_t & options,
const HttpHeaders::ptr_t & headers,
@@ -383,7 +376,7 @@ HttpHandle HttpRequest::requestMove(policy_t policy_id,
HttpStatus status;
HttpOpRequest::ptr_t op (new HttpOpRequest());
- if (!(status = op->setupMove(policy_id, priority, url, options, headers)))
+ if (!(status = op->setupMove(policy_id, url, options, headers)))
{
mLastReqStatus = status;
return LLCORE_HTTP_HANDLE_INVALID;
@@ -483,24 +476,6 @@ HttpHandle HttpRequest::requestCancel(HttpHandle request, HttpHandler::ptr_t use
}
-HttpHandle HttpRequest::requestSetPriority(HttpHandle request, priority_t priority,
- HttpHandler::ptr_t handler)
-{
- HttpStatus status;
-
- HttpOperation::ptr_t op (new HttpOpSetPriority(request, priority));
- op->setReplyPath(mReplyQueue, handler);
- if (! (status = mRequestQueue->addOp(op))) // transfers refcount
- {
- mLastReqStatus = status;
- return LLCORE_HTTP_HANDLE_INVALID;
- }
-
- mLastReqStatus = status;
- return op->getHandle();
-}
-
-
// ====================================
// Utility Methods
// ====================================
diff --git a/indra/llcorehttp/httprequest.h b/indra/llcorehttp/httprequest.h
index a418eb6a7a..ca4b9e92bc 100644
--- a/indra/llcorehttp/httprequest.h
+++ b/indra/llcorehttp/httprequest.h
@@ -95,7 +95,6 @@ private:
public:
typedef unsigned int policy_t;
- typedef unsigned int priority_t;
typedef boost::shared_ptr<HttpRequest> ptr_t;
typedef boost::weak_ptr<HttpRequest> wptr_t;
@@ -316,8 +315,6 @@ public:
///
/// @param policy_id Default or user-defined policy class under
/// which this request is to be serviced.
- /// @param priority Standard priority scheme inherited from
- /// Indra code base (U32-type scheme).
/// @param url URL with any encoded query parameters to
/// be accessed.
/// @param options Optional instance of an HttpOptions object
@@ -346,7 +343,6 @@ public:
/// case, @see getStatus() will return more info.
///
HttpHandle requestGet(policy_t policy_id,
- priority_t priority,
const std::string & url,
const HttpOptions::ptr_t & options,
const HttpHeaders::ptr_t & headers,
@@ -377,7 +373,6 @@ public:
/// - Referer:
///
/// @param policy_id @see requestGet()
- /// @param priority "
/// @param url "
/// @param offset Offset of first byte into resource to be returned.
/// @param len Count of bytes to be returned
@@ -387,7 +382,6 @@ public:
/// @return "
///
HttpHandle requestGetByteRange(policy_t policy_id,
- priority_t priority,
const std::string & url,
size_t offset,
size_t len,
@@ -418,7 +412,6 @@ public:
/// - Expect:
///
/// @param policy_id @see requestGet()
- /// @param priority "
/// @param url "
/// @param body Byte stream to be sent as the body. No
/// further encoding or escaping will be done
@@ -429,7 +422,6 @@ public:
/// @return "
///
HttpHandle requestPost(policy_t policy_id,
- priority_t priority,
const std::string & url,
BufferArray * body,
const HttpOptions::ptr_t & options,
@@ -459,7 +451,6 @@ public:
/// - Content-Type:
///
/// @param policy_id @see requestGet()
- /// @param priority "
/// @param url "
/// @param body Byte stream to be sent as the body. No
/// further encoding or escaping will be done
@@ -470,7 +461,6 @@ public:
/// @return "
///
HttpHandle requestPut(policy_t policy_id,
- priority_t priority,
const std::string & url,
BufferArray * body,
const HttpOptions::ptr_t & options,
@@ -483,7 +473,6 @@ public:
/// encoding and communicating the content types.
///
/// @param policy_id @see requestGet()
- /// @param priority "
/// @param url "
/// @param options @see requestGet()K(optional)
/// @param headers "
@@ -491,7 +480,6 @@ public:
/// @return "
///
HttpHandle requestDelete(policy_t policy_id,
- priority_t priority,
const std::string & url,
const HttpOptions::ptr_t & options,
const HttpHeaders::ptr_t & headers,
@@ -502,7 +490,6 @@ public:
/// encoding and communicating the content types.
///
/// @param policy_id @see requestGet()
- /// @param priority "
/// @param url "
/// @param body Byte stream to be sent as the body. No
/// further encoding or escaping will be done
@@ -513,7 +500,6 @@ public:
/// @return "
///
HttpHandle requestPatch(policy_t policy_id,
- priority_t priority,
const std::string & url,
BufferArray * body,
const HttpOptions::ptr_t & options,
@@ -525,7 +511,6 @@ public:
/// encoding and communicating the content types.
///
/// @param policy_id @see requestGet()
- /// @param priority "
/// @param url "
/// @param options @see requestGet()K(optional)
/// @param headers "
@@ -533,7 +518,6 @@ public:
/// @return "
///
HttpHandle requestCopy(policy_t policy_id,
- priority_t priority,
const std::string & url,
const HttpOptions::ptr_t & options,
const HttpHeaders::ptr_t & headers,
@@ -544,7 +528,6 @@ public:
/// encoding and communicating the content types.
///
/// @param policy_id @see requestGet()
- /// @param priority "
/// @param url "
/// @param options @see requestGet()K(optional)
/// @param headers "
@@ -552,7 +535,6 @@ public:
/// @return "
///
HttpHandle requestMove(policy_t policy_id,
- priority_t priority,
const std::string & url,
const HttpOptions::ptr_t & options,
const HttpHeaders::ptr_t & headers,
@@ -593,18 +575,6 @@ public:
HttpHandle requestCancel(HttpHandle request, HttpHandler::ptr_t);
- /// Request that a previously-issued request be reprioritized.
- /// The status of whether the change itself succeeded arrives
- /// via notification.
- ///
- /// @param request Handle of previously-issued request to
- /// be changed.
- /// @param priority New priority value.
- /// @param handler @see requestGet()
- /// @return "
- ///
- HttpHandle requestSetPriority(HttpHandle request, priority_t priority, HttpHandler::ptr_t handler);
-
/// @}
/// @name UtilityMethods
diff --git a/indra/llcorehttp/tests/test_httprequest.hpp b/indra/llcorehttp/tests/test_httprequest.hpp
index 154f6b12e9..3eaac10aeb 100644
--- a/indra/llcorehttp/tests/test_httprequest.hpp
+++ b/indra/llcorehttp/tests/test_httprequest.hpp
@@ -614,7 +614,6 @@ void HttpRequestTestObjectType::test<7>()
// Issue a GET that can't connect
mStatus = HttpStatus(HttpStatus::EXT_CURL_EASY, CURLE_COULDNT_CONNECT);
HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID,
- 0U,
"http://127.0.0.1:2/nothing/here",
0,
0,
@@ -716,7 +715,6 @@ void HttpRequestTestObjectType::test<8>()
// Issue a GET that *can* connect
mStatus = HttpStatus(200);
HttpHandle handle = req->requestGet(HttpRequest::DEFAULT_POLICY_ID,
- 0U,
url_base,
HttpOptions::ptr_t(),
HttpHeaders::ptr_t(),
@@ -812,7 +810,6 @@ void HttpRequestTestObjectType::test<9>()
// Issue a GET that *can* connect
mStatus = HttpStatus(200);
HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID,
- 0U,
url_base,
0,
0,
@@ -913,7 +910,6 @@ void HttpRequestTestObjectType::test<10>()
body->append(body_text, strlen(body_text));
mStatus = HttpStatus(200);
HttpHandle handle = req->requestPut(HttpRequest::DEFAULT_POLICY_ID,
- 0U,
url_base,
body,
HttpOptions::ptr_t(),
@@ -1020,7 +1016,6 @@ void HttpRequestTestObjectType::test<11>()
body->append(body_text, strlen(body_text));
mStatus = HttpStatus(200);
HttpHandle handle = req->requestPost(HttpRequest::DEFAULT_POLICY_ID,
- 0U,
url_base,
body,
HttpOptions::ptr_t(),
@@ -1127,7 +1122,6 @@ void HttpRequestTestObjectType::test<12>()
// Issue a GET that *can* connect
mStatus = HttpStatus(200);
HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID,
- 0U,
url_base,
0,
0,
@@ -1240,7 +1234,6 @@ void HttpRequestTestObjectType::test<13>()
regex_container_t::value_type(boost::regex("X-LL-Special", boost::regex::icase),
boost::regex(".*", boost::regex::icase)));
HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID,
- 0U,
url_base,
0,
0,
@@ -1346,7 +1339,6 @@ void HttpRequestTestObjectType::test<14>()
// Issue a GET that sleeps
mStatus = HttpStatus(HttpStatus::EXT_CURL_EASY, CURLE_OPERATION_TIMEDOUT);
HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID,
- 0U,
url_base,
0,
0,
@@ -1454,7 +1446,6 @@ void HttpRequestTestObjectType::test<15>()
mStatus = HttpStatus(200);
handler.mCheckContentType = "application/llsd+xml";
HttpHandle handle = req->requestGet(HttpRequest::DEFAULT_POLICY_ID,
- 0U,
url_base,
HttpOptions::ptr_t(),
HttpHeaders::ptr_t(),
@@ -1609,7 +1600,6 @@ void HttpRequestTestObjectType::test<16>()
boost::regex("X-Reflect-content-encoding", boost::regex::icase),
boost::regex(".*", boost::regex::icase)));
HttpHandle handle = req->requestGet(HttpRequest::DEFAULT_POLICY_ID,
- 0U,
url_base + "reflect/",
options,
HttpHeaders::ptr_t(),
@@ -1684,7 +1674,6 @@ void HttpRequestTestObjectType::test<16>()
boost::regex("X-Reflect-content-encoding", boost::regex::icase),
boost::regex(".*", boost::regex::icase)));
handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID,
- 0U,
url_base + "reflect/",
0,
47,
@@ -1863,7 +1852,6 @@ void HttpRequestTestObjectType::test<17>()
boost::regex("X-Reflect-transfer_encoding", boost::regex::icase),
boost::regex(".*chunked.*", boost::regex::icase)));
HttpHandle handle = req->requestPost(HttpRequest::DEFAULT_POLICY_ID,
- 0U,
url_base + "reflect/",
ba,
options,
@@ -2049,7 +2037,6 @@ void HttpRequestTestObjectType::test<18>()
boost::regex(".*", boost::regex::icase)));
HttpHandle handle = req->requestPut(HttpRequest::DEFAULT_POLICY_ID,
- 0U,
url_base + "reflect/",
ba,
options,
@@ -2249,7 +2236,6 @@ void HttpRequestTestObjectType::test<19>()
boost::regex("X-Reflect-content-encoding", boost::regex::icase),
boost::regex(".*", boost::regex::icase)));
HttpHandle handle = req->requestGet(HttpRequest::DEFAULT_POLICY_ID,
- 0U,
url_base + "reflect/",
options,
headers,
@@ -2457,7 +2443,6 @@ void HttpRequestTestObjectType::test<20>()
boost::regex(".*", boost::regex::icase)));
HttpHandle handle = req->requestPost(HttpRequest::DEFAULT_POLICY_ID,
- 0U,
url_base + "reflect/",
ba,
options,
@@ -2666,7 +2651,6 @@ void HttpRequestTestObjectType::test<21>()
boost::regex("X-Reflect-content-type", boost::regex::icase),
boost::regex("text/html", boost::regex::icase)));
HttpHandle handle = req->requestPut(HttpRequest::DEFAULT_POLICY_ID,
- 0U,
url_base + "reflect/",
ba,
options,
@@ -2797,7 +2781,6 @@ void HttpRequestTestObjectType::test<22>()
char buffer[128];
sprintf(buffer, "/bug2295/%d/", i);
HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID,
- 0U,
url_base + buffer,
0,
25,
@@ -2829,7 +2812,6 @@ void HttpRequestTestObjectType::test<22>()
char buffer[128];
sprintf(buffer, "/bug2295/00000012/%d/", i);
HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID,
- 0U,
url_base + buffer,
0,
25,
@@ -2861,7 +2843,6 @@ void HttpRequestTestObjectType::test<22>()
char buffer[128];
sprintf(buffer, "/bug2295/inv_cont_range/%d/", i);
HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID,
- 0U,
url_base + buffer,
0,
25,
@@ -2984,7 +2965,6 @@ void HttpRequestTestObjectType::test<23>()
std::ostringstream url;
url << url_base << i << "/";
HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID,
- 0U,
url.str(),
0,
0,
diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp
index 0d8fb4863b..bb603d3d7f 100644
--- a/indra/llcrashlogger/llcrashlogger.cpp
+++ b/indra/llcrashlogger/llcrashlogger.cpp
@@ -418,7 +418,7 @@ bool LLCrashLogger::runCrashLogPost(std::string host, LLSD data, std::string msg
updateApplication(llformat("%s, try %d...", msg.c_str(), i+1));
LL_INFOS("CRASHREPORT") << "POST crash data to " << host << LL_ENDL;
- LLCore::HttpHandle handle = LLCoreHttpUtil::requestPostWithLLSD(httpRequest.get(), LLCore::HttpRequest::DEFAULT_POLICY_ID, 0,
+ LLCore::HttpHandle handle = LLCoreHttpUtil::requestPostWithLLSD(httpRequest.get(), LLCore::HttpRequest::DEFAULT_POLICY_ID,
host, data, httpOpts, LLCore::HttpHeaders::ptr_t(), LLCore::HttpHandler::ptr_t(new LLCrashLoggerHandler));
if (handle == LLCORE_HTTP_HANDLE_INVALID)
diff --git a/indra/llfilesystem/lldiskcache.cpp b/indra/llfilesystem/lldiskcache.cpp
index 6de99dfbff..dd3852fb93 100644
--- a/indra/llfilesystem/lldiskcache.cpp
+++ b/indra/llfilesystem/lldiskcache.cpp
@@ -220,6 +220,7 @@ const std::string LLDiskCache::assetTypeToString(LLAssetType::EType at)
{ LLAssetType::AT_PERSON, "PERSON" },
{ LLAssetType::AT_MESH, "MESH" },
{ LLAssetType::AT_SETTINGS, "SETTINGS" },
+ { LLAssetType::AT_MATERIAL, "MATERIAL" },
{ LLAssetType::AT_UNKNOWN, "UNKNOWN" }
};
diff --git a/indra/llfilesystem/lllfsthread.cpp b/indra/llfilesystem/lllfsthread.cpp
index be8e83a56f..dbb69cd605 100644
--- a/indra/llfilesystem/lllfsthread.cpp
+++ b/indra/llfilesystem/lllfsthread.cpp
@@ -45,8 +45,7 @@ void LLLFSThread::initClass(bool local_is_threaded)
//static
S32 LLLFSThread::updateClass(U32 ms_elapsed)
{
- sLocal->update((F32)ms_elapsed);
- return sLocal->getPending();
+ return sLocal->update((F32)ms_elapsed);
}
//static
@@ -58,6 +57,7 @@ void LLLFSThread::cleanupClass()
{
sLocal->update(0);
}
+ sLocal->shutdown();
delete sLocal;
sLocal = NULL;
}
@@ -65,8 +65,7 @@ void LLLFSThread::cleanupClass()
//----------------------------------------------------------------------------
LLLFSThread::LLLFSThread(bool threaded) :
- LLQueuedThread("LFS", threaded),
- mPriorityCounter(PRIORITY_LOWBITS)
+ LLQueuedThread("LFS", threaded)
{
if(!mLocalAPRFilePoolp)
{
@@ -84,14 +83,12 @@ LLLFSThread::~LLLFSThread()
LLLFSThread::handle_t LLLFSThread::read(const std::string& filename, /* Flawfinder: ignore */
U8* buffer, S32 offset, S32 numbytes,
- Responder* responder, U32 priority)
+ Responder* responder)
{
+ LL_PROFILE_ZONE_SCOPED;
handle_t handle = generateHandle();
- if (priority == 0) priority = PRIORITY_NORMAL | priorityCounter();
- else if (priority < PRIORITY_LOW) priority |= PRIORITY_LOW; // All reads are at least PRIORITY_LOW
-
- Request* req = new Request(this, handle, priority,
+ Request* req = new Request(this, handle,
FILE_READ, filename,
buffer, offset, numbytes,
responder);
@@ -107,13 +104,12 @@ LLLFSThread::handle_t LLLFSThread::read(const std::string& filename, /* Flawfind
LLLFSThread::handle_t LLLFSThread::write(const std::string& filename,
U8* buffer, S32 offset, S32 numbytes,
- Responder* responder, U32 priority)
+ Responder* responder)
{
+ LL_PROFILE_ZONE_SCOPED;
handle_t handle = generateHandle();
- if (priority == 0) priority = PRIORITY_LOW | priorityCounter();
-
- Request* req = new Request(this, handle, priority,
+ Request* req = new Request(this, handle,
FILE_WRITE, filename,
buffer, offset, numbytes,
responder);
@@ -130,11 +126,11 @@ LLLFSThread::handle_t LLLFSThread::write(const std::string& filename,
//============================================================================
LLLFSThread::Request::Request(LLLFSThread* thread,
- handle_t handle, U32 priority,
+ handle_t handle,
operation_t op, const std::string& filename,
U8* buffer, S32 offset, S32 numbytes,
Responder* responder) :
- QueuedRequest(handle, priority, FLAG_AUTO_COMPLETE),
+ QueuedRequest(handle, FLAG_AUTO_COMPLETE),
mThread(thread),
mOperation(op),
mFileName(filename),
@@ -157,6 +153,7 @@ LLLFSThread::Request::~Request()
// virtual, called from own thread
void LLLFSThread::Request::finishRequest(bool completed)
{
+ LL_PROFILE_ZONE_SCOPED;
if (mResponder.notNull())
{
mResponder->completed(completed ? mBytesRead : 0);
@@ -166,6 +163,7 @@ void LLLFSThread::Request::finishRequest(bool completed)
void LLLFSThread::Request::deleteRequest()
{
+ LL_PROFILE_ZONE_SCOPED;
if (getStatus() == STATUS_QUEUED)
{
LL_ERRS() << "Attempt to delete a queued LLLFSThread::Request!" << LL_ENDL;
@@ -180,6 +178,7 @@ void LLLFSThread::Request::deleteRequest()
bool LLLFSThread::Request::processRequest()
{
+ LL_PROFILE_ZONE_SCOPED;
bool complete = false;
if (mOperation == FILE_READ)
{
diff --git a/indra/llfilesystem/lllfsthread.h b/indra/llfilesystem/lllfsthread.h
index 58f658f7ba..f2693a1172 100644
--- a/indra/llfilesystem/lllfsthread.h
+++ b/indra/llfilesystem/lllfsthread.h
@@ -68,7 +68,7 @@ public:
public:
Request(LLLFSThread* thread,
- handle_t handle, U32 priority,
+ handle_t handle,
operation_t op, const std::string& filename,
U8* buffer, S32 offset, S32 numbytes,
Responder* responder);
@@ -120,22 +120,15 @@ public:
// Return a Request handle
handle_t read(const std::string& filename, /* Flawfinder: ignore */
U8* buffer, S32 offset, S32 numbytes,
- Responder* responder, U32 pri=0);
+ Responder* responder);
handle_t write(const std::string& filename,
U8* buffer, S32 offset, S32 numbytes,
- Responder* responder, U32 pri=0);
-
- // Misc
- U32 priorityCounter() { return mPriorityCounter-- & PRIORITY_LOWBITS; } // Use to order IO operations
+ Responder* responder);
// static initializers
static void initClass(bool local_is_threaded = TRUE); // Setup sLocal
static S32 updateClass(U32 ms_elapsed);
static void cleanupClass(); // Delete sLocal
-
-
-private:
- U32 mPriorityCounter;
public:
static LLLFSThread* sLocal; // Default local file thread
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index 0fa027c9c3..031471d1fe 100644
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -798,7 +798,6 @@ U8* LLImageBase::allocateDataSize(S32 width, S32 height, S32 ncomponents, S32 si
// LLImageRaw
//---------------------------------------------------------------------------
-S32 LLImageRaw::sGlobalRawMemory = 0;
S32 LLImageRaw::sRawImageCount = 0;
LLImageRaw::LLImageRaw()
@@ -815,6 +814,15 @@ LLImageRaw::LLImageRaw(U16 width, U16 height, S8 components)
++sRawImageCount;
}
+LLImageRaw::LLImageRaw(const U8* data, U16 width, U16 height, S8 components)
+ : LLImageBase()
+{
+ if (allocateDataSize(width, height, components))
+ {
+ memcpy(getData(), data, width * height * components);
+ }
+}
+
LLImageRaw::LLImageRaw(U8 *data, U16 width, U16 height, S8 components, bool no_copy)
: LLImageBase()
{
@@ -847,16 +855,13 @@ LLImageRaw::~LLImageRaw()
U8* LLImageRaw::allocateData(S32 size)
{
U8* res = LLImageBase::allocateData(size);
- sGlobalRawMemory += getDataSize();
return res;
}
// virtual
U8* LLImageRaw::reallocateData(S32 size)
{
- sGlobalRawMemory -= getDataSize();
U8* res = LLImageBase::reallocateData(size);
- sGlobalRawMemory += getDataSize();
return res;
}
@@ -869,7 +874,6 @@ void LLImageRaw::releaseData()
// virtual
void LLImageRaw::deleteData()
{
- sGlobalRawMemory -= getDataSize();
LLImageBase::deleteData();
}
@@ -985,6 +989,43 @@ void LLImageRaw::verticalFlip()
}
+bool LLImageRaw::optimizeAwayAlpha()
+{
+ if (getComponents() == 4)
+ {
+ U8* data = getData();
+ U32 pixels = getWidth() * getHeight();
+
+ // check alpha channel for all 255
+ for (U32 i = 0; i < pixels; ++i)
+ {
+ if (data[i * 4 + 3] != 255)
+ {
+ return false;
+ }
+ }
+
+ // alpha channel is all 255, make a new copy of data without alpha channel
+ U8* new_data = (U8*) ll_aligned_malloc_16(getWidth() * getHeight() * 3);
+
+ for (U32 i = 0; i < pixels; ++i)
+ {
+ U32 di = i * 3;
+ U32 si = i * 4;
+ for (U32 j = 0; j < 3; ++j)
+ {
+ new_data[di+j] = data[si+j];
+ }
+ }
+
+ setDataAndSize(new_data, getWidth(), getHeight(), 3);
+
+ return true;
+ }
+
+ return false;
+}
+
void LLImageRaw::expandToPowerOfTwo(S32 max_dim, bool scale_image)
{
// Find new sizes
diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h
index 7a588cfb03..8f9e1b3c54 100644
--- a/indra/llimage/llimage.h
+++ b/indra/llimage/llimage.h
@@ -184,6 +184,7 @@ protected:
public:
LLImageRaw();
LLImageRaw(U16 width, U16 height, S8 components);
+ LLImageRaw(const U8* data, U16 width, U16 height, S8 components);
LLImageRaw(U8 *data, U16 width, U16 height, S8 components, bool no_copy = false);
// Construct using createFromFile (used by tools)
//LLImageRaw(const std::string& filename, bool j2c_lowest_mip_only = false);
@@ -207,6 +208,10 @@ public:
void clear(U8 r=0, U8 g=0, U8 b=0, U8 a=255);
void verticalFlip();
+
+ // if the alpha channel is all 100% opaque, delete it
+ // returns true if alpha channel was deleted
+ bool optimizeAwayAlpha();
static S32 biasedDimToPowerOfTwo(S32 curr_dim, S32 max_dim = MAX_IMAGE_SIZE);
static S32 expandDimToPowerOfTwo(S32 curr_dim, S32 max_dim = MAX_IMAGE_SIZE);
@@ -275,7 +280,6 @@ protected:
void setDataAndSize(U8 *data, S32 width, S32 height, S8 components) ;
public:
- static S32 sGlobalRawMemory;
static S32 sRawImageCount;
private:
diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp
index e1809dbe59..8dba1641a6 100644
--- a/indra/llimage/llimagej2c.cpp
+++ b/indra/llimage/llimagej2c.cpp
@@ -146,6 +146,7 @@ bool LLImageJ2C::initEncode(LLImageRaw &raw_image, int blocks_size, int precinct
bool LLImageJ2C::decode(LLImageRaw *raw_imagep, F32 decode_time)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
return decodeChannels(raw_imagep, decode_time, 0, 4);
}
@@ -153,6 +154,7 @@ bool LLImageJ2C::decode(LLImageRaw *raw_imagep, F32 decode_time)
// Returns true to mean done, whether successful or not.
bool LLImageJ2C::decodeChannels(LLImageRaw *raw_imagep, F32 decode_time, S32 first_channel, S32 max_channel_count )
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
LLTimer elapsed;
bool res = true;
diff --git a/indra/llimage/llimageworker.cpp b/indra/llimage/llimageworker.cpp
index 0dbb744bcf..0093958e6d 100644
--- a/indra/llimage/llimageworker.cpp
+++ b/indra/llimage/llimageworker.cpp
@@ -28,64 +28,88 @@
#include "llimageworker.h"
#include "llimagedxt.h"
+#include "threadpool.h"
+
+/*--------------------------------------------------------------------------*/
+class ImageRequest
+{
+public:
+ ImageRequest(const LLPointer<LLImageFormatted>& image,
+ S32 discard, BOOL needs_aux,
+ const LLPointer<LLImageDecodeThread::Responder>& responder);
+ virtual ~ImageRequest();
+
+ /*virtual*/ bool processRequest();
+ /*virtual*/ void finishRequest(bool completed);
+
+private:
+ // LLPointers stored in ImageRequest MUST be LLPointer instances rather
+ // than references: we need to increment the refcount when storing these.
+ // input
+ LLPointer<LLImageFormatted> mFormattedImage;
+ S32 mDiscardLevel;
+ BOOL mNeedsAux;
+ // output
+ LLPointer<LLImageRaw> mDecodedImageRaw;
+ LLPointer<LLImageRaw> mDecodedImageAux;
+ BOOL mDecodedRaw;
+ BOOL mDecodedAux;
+ LLPointer<LLImageDecodeThread::Responder> mResponder;
+};
+
//----------------------------------------------------------------------------
// MAIN THREAD
-LLImageDecodeThread::LLImageDecodeThread(bool threaded)
- : LLQueuedThread("imagedecode", threaded)
+LLImageDecodeThread::LLImageDecodeThread(bool /*threaded*/)
{
- mCreationMutex = new LLMutex();
+ mThreadPool.reset(new LL::ThreadPool("ImageDecode", 8));
+ mThreadPool->start();
}
//virtual
LLImageDecodeThread::~LLImageDecodeThread()
-{
- delete mCreationMutex ;
-}
+{}
// MAIN THREAD
// virtual
S32 LLImageDecodeThread::update(F32 max_time_ms)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
- LLMutexLock lock(mCreationMutex);
- for (creation_list_t::iterator iter = mCreationList.begin();
- iter != mCreationList.end(); ++iter)
- {
- creation_info& info = *iter;
- ImageRequest* req = new ImageRequest(info.handle, info.image,
- info.priority, info.discard, info.needs_aux,
- info.responder);
+ return getPending();
+}
- bool res = addRequest(req);
- if (!res)
- {
- LL_ERRS() << "request added after LLLFSThread::cleanupClass()" << LL_ENDL;
- }
- }
- mCreationList.clear();
- S32 res = LLQueuedThread::update(max_time_ms);
- return res;
+S32 LLImageDecodeThread::getPending()
+{
+ return mThreadPool->getQueue().size();
}
-LLImageDecodeThread::handle_t LLImageDecodeThread::decodeImage(LLImageFormatted* image,
- U32 priority, S32 discard, BOOL needs_aux, Responder* responder)
+LLImageDecodeThread::handle_t LLImageDecodeThread::decodeImage(
+ const LLPointer<LLImageFormatted>& image,
+ S32 discard,
+ BOOL needs_aux,
+ const LLPointer<LLImageDecodeThread::Responder>& responder)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
- LLMutexLock lock(mCreationMutex);
- handle_t handle = generateHandle();
- mCreationList.push_back(creation_info(handle, image, priority, discard, needs_aux, responder));
- return handle;
+
+ // Instantiate the ImageRequest right in the lambda, why not?
+ mThreadPool->getQueue().post(
+ [req = ImageRequest(image, discard, needs_aux, responder)]
+ () mutable
+ {
+ auto done = req.processRequest();
+ req.finishRequest(done);
+ });
+
+ // It's important to our consumer (LLTextureFetchWorker) that we return a
+ // nonzero handle. It is NOT important that the nonzero handle be unique:
+ // nothing is ever done with it except to compare it to zero, or zero it.
+ return 17;
}
-// Used by unit test only
-// Returns the size of the mutex guarded list as an indication of sanity
-S32 LLImageDecodeThread::tut_size()
+void LLImageDecodeThread::shutdown()
{
- LLMutexLock lock(mCreationMutex);
- S32 res = mCreationList.size();
- return res;
+ mThreadPool->close();
}
LLImageDecodeThread::Responder::~Responder()
@@ -94,11 +118,10 @@ LLImageDecodeThread::Responder::~Responder()
//----------------------------------------------------------------------------
-LLImageDecodeThread::ImageRequest::ImageRequest(handle_t handle, LLImageFormatted* image,
- U32 priority, S32 discard, BOOL needs_aux,
- LLImageDecodeThread::Responder* responder)
- : LLQueuedThread::QueuedRequest(handle, priority, FLAG_AUTO_COMPLETE),
- mFormattedImage(image),
+ImageRequest::ImageRequest(const LLPointer<LLImageFormatted>& image,
+ S32 discard, BOOL needs_aux,
+ const LLPointer<LLImageDecodeThread::Responder>& responder)
+ : mFormattedImage(image),
mDiscardLevel(discard),
mNeedsAux(needs_aux),
mDecodedRaw(FALSE),
@@ -107,7 +130,7 @@ LLImageDecodeThread::ImageRequest::ImageRequest(handle_t handle, LLImageFormatte
{
}
-LLImageDecodeThread::ImageRequest::~ImageRequest()
+ImageRequest::~ImageRequest()
{
mDecodedImageRaw = NULL;
mDecodedImageAux = NULL;
@@ -118,10 +141,10 @@ LLImageDecodeThread::ImageRequest::~ImageRequest()
// Returns true when done, whether or not decode was successful.
-bool LLImageDecodeThread::ImageRequest::processRequest()
+bool ImageRequest::processRequest()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
- const F32 decode_time_slice = .1f;
+ const F32 decode_time_slice = 0.f; //disable time slicing
bool done = true;
if (!mDecodedRaw && mFormattedImage.notNull())
{
@@ -145,7 +168,7 @@ bool LLImageDecodeThread::ImageRequest::processRequest()
mFormattedImage->getHeight(),
mFormattedImage->getComponents());
}
- done = mFormattedImage->decode(mDecodedImageRaw, decode_time_slice); // 1ms
+ done = mFormattedImage->decode(mDecodedImageRaw, decode_time_slice);
// some decoders are removing data when task is complete and there were errors
mDecodedRaw = done && mDecodedImageRaw->getData();
}
@@ -158,14 +181,14 @@ bool LLImageDecodeThread::ImageRequest::processRequest()
mFormattedImage->getHeight(),
1);
}
- done = mFormattedImage->decodeChannels(mDecodedImageAux, decode_time_slice, 4, 4); // 1ms
+ done = mFormattedImage->decodeChannels(mDecodedImageAux, decode_time_slice, 4, 4);
mDecodedAux = done && mDecodedImageAux->getData();
}
return done;
}
-void LLImageDecodeThread::ImageRequest::finishRequest(bool completed)
+void ImageRequest::finishRequest(bool completed)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
if (mResponder.notNull())
@@ -175,10 +198,3 @@ void LLImageDecodeThread::ImageRequest::finishRequest(bool completed)
}
// Will automatically be deleted
}
-
-// Used by unit test only
-// Checks that a responder exists for this instance so that something can happen when completion is reached
-bool LLImageDecodeThread::ImageRequest::tut_isOK()
-{
- return mResponder.notNull();
-}
diff --git a/indra/llimage/llimageworker.h b/indra/llimage/llimageworker.h
index 1bfb0ddfd3..fb35108a7a 100644
--- a/indra/llimage/llimageworker.h
+++ b/indra/llimage/llimageworker.h
@@ -29,9 +29,9 @@
#include "llimage.h"
#include "llpointer.h"
-#include "llworkerthread.h"
+#include "threadpool_fwd.h"
-class LLImageDecodeThread : public LLQueuedThread
+class LLImageDecodeThread
{
public:
class Responder : public LLThreadSafeRefCount
@@ -42,63 +42,24 @@ public:
virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux) = 0;
};
- class ImageRequest : public LLQueuedThread::QueuedRequest
- {
- protected:
- virtual ~ImageRequest(); // use deleteRequest()
-
- public:
- ImageRequest(handle_t handle, LLImageFormatted* image,
- U32 priority, S32 discard, BOOL needs_aux,
- LLImageDecodeThread::Responder* responder);
-
- /*virtual*/ bool processRequest();
- /*virtual*/ void finishRequest(bool completed);
-
- // Used by unit tests to check the consitency of the request instance
- bool tut_isOK();
-
- private:
- // input
- LLPointer<LLImageFormatted> mFormattedImage;
- S32 mDiscardLevel;
- BOOL mNeedsAux;
- // output
- LLPointer<LLImageRaw> mDecodedImageRaw;
- LLPointer<LLImageRaw> mDecodedImageAux;
- BOOL mDecodedRaw;
- BOOL mDecodedAux;
- LLPointer<LLImageDecodeThread::Responder> mResponder;
- };
-
public:
LLImageDecodeThread(bool threaded = true);
virtual ~LLImageDecodeThread();
- handle_t decodeImage(LLImageFormatted* image,
- U32 priority, S32 discard, BOOL needs_aux,
- Responder* responder);
+ // meant to resemble LLQueuedThread::handle_t
+ typedef U32 handle_t;
+ handle_t decodeImage(const LLPointer<LLImageFormatted>& image,
+ S32 discard, BOOL needs_aux,
+ const LLPointer<Responder>& responder);
+ S32 getPending();
S32 update(F32 max_time_ms);
+ void shutdown();
- // Used by unit tests to check the consistency of the thread instance
- S32 tut_size();
-
private:
- struct creation_info
- {
- handle_t handle;
- LLPointer<LLImageFormatted> image;
- U32 priority;
- S32 discard;
- BOOL needs_aux;
- LLPointer<Responder> responder;
- creation_info(handle_t h, LLImageFormatted* i, U32 p, S32 d, BOOL aux, Responder* r)
- : handle(h), image(i), priority(p), discard(d), needs_aux(aux), responder(r)
- {}
- };
- typedef std::list<creation_info> creation_list_t;
- creation_list_t mCreationList;
- LLMutex* mCreationMutex;
+ // As of SL-17483, LLImageDecodeThread is no longer itself an
+ // LLQueuedThread - instead this is the API by which we submit work to the
+ // "ImageDecode" ThreadPool.
+ std::unique_ptr<LL::ThreadPool> mThreadPool;
};
#endif
diff --git a/indra/llimage/tests/llimageworker_test.cpp b/indra/llimage/tests/llimageworker_test.cpp
index 9011ac615c..0a97b739b0 100644
--- a/indra/llimage/tests/llimageworker_test.cpp
+++ b/indra/llimage/tests/llimageworker_test.cpp
@@ -125,42 +125,11 @@ namespace tut
}
};
- // Test wrapper declaration : image worker
- // Note: this class is not meant to be instantiated outside an LLImageDecodeThread instance
- // but it's not a bad idea to get its public API a good shake as part of a thorough unit test set.
- // Some gotcha with the destructor though (see below).
- struct imagerequest_test
- {
- // Instance to be tested
- LLImageDecodeThread::ImageRequest* mRequest;
- bool done;
-
- // Constructor and destructor of the test wrapper
- imagerequest_test()
- {
- done = false;
-
- mRequest = new LLImageDecodeThread::ImageRequest(0, 0,
- LLQueuedThread::PRIORITY_NORMAL, 0, FALSE,
- new responder_test(&done));
- }
- ~imagerequest_test()
- {
- // We should delete the object *but*, because its destructor is protected, that cannot be
- // done from outside an LLImageDecodeThread instance... So we leak memory here... It's fine...
- //delete mRequest;
- }
- };
-
// Tut templating thingamagic: test group, object and test instance
typedef test_group<imagedecodethread_test> imagedecodethread_t;
typedef imagedecodethread_t::object imagedecodethread_object_t;
tut::imagedecodethread_t tut_imagedecodethread("LLImageDecodeThread");
- typedef test_group<imagerequest_test> imagerequest_t;
- typedef imagerequest_t::object imagerequest_object_t;
- tut::imagerequest_t tut_imagerequest("LLImageRequest");
-
// ---------------------------------------------------------------------------------------
// Test functions
// Notes:
@@ -172,64 +141,18 @@ namespace tut
// ---------------------------------------------------------------------------------------
// Test the LLImageDecodeThread interface
// ---------------------------------------------------------------------------------------
- //
- // Note on Unit Testing Queued Thread Classes
- //
- // Since methods on such a class are called on a separate loop and that we can't insert tut
- // ensure() calls in there, we exercise the class with 2 sets of tests:
- // - 1: Test as a single threaded instance: We declare the class but ask for no thread
- // to be spawned (easy with LLThreads since there's a boolean argument on the constructor
- // just for that). We can then unit test each public method like we do on a normal class.
- // - 2: Test as a threaded instance: We let the thread launch and check that its external
- // behavior is as expected (i.e. it runs, can accept a work order and processes
- // it). Typically though there's no guarantee that this exercises all the methods of the
- // class which is why we also need the previous "non threaded" set of unit tests for
- // complete coverage.
- //
- // ---------------------------------------------------------------------------------------
template<> template<>
void imagedecodethread_object_t::test<1>()
{
- // Test a *non threaded* instance of the class
- mThread = new LLImageDecodeThread(false);
- ensure("LLImageDecodeThread: non threaded constructor failed", mThread != NULL);
- // Test that we start with an empty list right at creation
- ensure("LLImageDecodeThread: non threaded init state incorrect", mThread->tut_size() == 0);
- // Insert something in the queue
- bool done = false;
- LLImageDecodeThread::handle_t decodeHandle = mThread->decodeImage(NULL, LLQueuedThread::PRIORITY_NORMAL, 0, FALSE, new responder_test(&done));
- // Verifies we got a valid handle
- ensure("LLImageDecodeThread: non threaded decodeImage(), returned handle is null", decodeHandle != 0);
- // Verifies that we do now have something in the queued list
- ensure("LLImageDecodeThread: non threaded decodeImage() insertion in threaded list failed", mThread->tut_size() == 1);
- // Trigger queue handling "manually" (on a threaded instance, this is done on the thread loop)
- S32 res = mThread->update(0);
- // Verifies that we successfully handled the list
- ensure("LLImageDecodeThread: non threaded update() list handling test failed", res == 0);
- // Verifies that the list is now empty
- ensure("LLImageDecodeThread: non threaded update() list emptying test failed", mThread->tut_size() == 0);
- }
-
- template<> template<>
- void imagedecodethread_object_t::test<2>()
- {
// Test a *threaded* instance of the class
mThread = new LLImageDecodeThread(true);
ensure("LLImageDecodeThread: threaded constructor failed", mThread != NULL);
- // Test that we start with an empty list right at creation
- ensure("LLImageDecodeThread: threaded init state incorrect", mThread->tut_size() == 0);
// Insert something in the queue
bool done = false;
- LLImageDecodeThread::handle_t decodeHandle = mThread->decodeImage(NULL, LLQueuedThread::PRIORITY_NORMAL, 0, FALSE, new responder_test(&done));
+ LLImageDecodeThread::handle_t decodeHandle = mThread->decodeImage(NULL, 0, FALSE, new responder_test(&done));
// Verifies we get back a valid handle
ensure("LLImageDecodeThread: threaded decodeImage(), returned handle is null", decodeHandle != 0);
- // Wait a little so to simulate the main thread doing something on its main loop...
- ms_sleep(500); // 500 milliseconds
- // Verifies that the responder has *not* been called yet in the meantime
- ensure("LLImageDecodeThread: responder creation failed", done == false);
- // Ask the thread to update: that means tells the queue to check itself and creates work requests
- mThread->update(1);
// Wait till the thread has time to handle the work order (though it doesn't do much per work order...)
const U32 INCREMENT_TIME = 500; // 500 milliseconds
const U32 MAX_TIME = 20 * INCREMENT_TIME; // Do the loop 20 times max, i.e. wait 10 seconds but no more
@@ -242,24 +165,4 @@ namespace tut
// Verifies that the responder has now been called
ensure("LLImageDecodeThread: threaded work unit not processed", done == true);
}
-
- // ---------------------------------------------------------------------------------------
- // Test the LLImageDecodeThread::ImageRequest interface
- // ---------------------------------------------------------------------------------------
-
- template<> template<>
- void imagerequest_object_t::test<1>()
- {
- // Test that we start with a correct request at creation
- ensure("LLImageDecodeThread::ImageRequest::ImageRequest() constructor test failed", mRequest->tut_isOK());
- bool res = mRequest->processRequest();
- // Verifies that we processed the request successfully
- ensure("LLImageDecodeThread::ImageRequest::processRequest() processing request test failed", res == true);
- // Check that we can call the finishing call safely
- try {
- mRequest->finishRequest(false);
- } catch (...) {
- fail("LLImageDecodeThread::ImageRequest::finishRequest() test failed");
- }
- }
}
diff --git a/indra/llimagej2coj/llimagej2coj.cpp b/indra/llimagej2coj/llimagej2coj.cpp
index 12985c3c7f..98500c671b 100644
--- a/indra/llimagej2coj/llimagej2coj.cpp
+++ b/indra/llimagej2coj/llimagej2coj.cpp
@@ -169,6 +169,7 @@ static OPJ_SIZE_T opj_write(void * buffer, OPJ_SIZE_T bytes, void* user_data)
static OPJ_OFF_T opj_skip(OPJ_OFF_T bytes, void* user_data)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
JPEG2KBase* jpeg_codec = static_cast<JPEG2KBase*>(user_data);
jpeg_codec->offset += bytes;
diff --git a/indra/llinventory/llfoldertype.cpp b/indra/llinventory/llfoldertype.cpp
index 675da65af2..d2c3b419ab 100644
--- a/indra/llinventory/llfoldertype.cpp
+++ b/indra/llinventory/llfoldertype.cpp
@@ -122,6 +122,7 @@ LLFolderDictionary::LLFolderDictionary()
addEntry(LLFolderType::FT_MARKETPLACE_VERSION, new FolderEntry("version", FALSE, FALSE, FALSE));
addEntry(LLFolderType::FT_SETTINGS, new FolderEntry("settings", TRUE, FALSE, TRUE));
+ addEntry(LLFolderType::FT_MATERIAL, new FolderEntry("material", TRUE, FALSE, TRUE));
addEntry(LLFolderType::FT_NONE, new FolderEntry("-1", FALSE, FALSE, FALSE));
};
diff --git a/indra/llinventory/llfoldertype.h b/indra/llinventory/llfoldertype.h
index 1f174520da..19f4d61b5b 100644
--- a/indra/llinventory/llfoldertype.h
+++ b/indra/llinventory/llfoldertype.h
@@ -93,9 +93,13 @@ public:
FT_SETTINGS = 56,
+ FT_MATERIAL = 57,
+
FT_COUNT,
FT_NONE = -1
+
+ // When adding, see note at bottom of LLAssetType::Etype
};
static EType lookup(const std::string& type_name);
diff --git a/indra/llinventory/llinventorytype.cpp b/indra/llinventory/llinventorytype.cpp
index 853ed655f5..ceda2f3caf 100644
--- a/indra/llinventory/llinventorytype.cpp
+++ b/indra/llinventory/llinventorytype.cpp
@@ -86,6 +86,7 @@ LLInventoryDictionary::LLInventoryDictionary()
addEntry(LLInventoryType::IT_WIDGET, new InventoryEntry("widget", "widget", 1, LLAssetType::AT_WIDGET));
addEntry(LLInventoryType::IT_PERSON, new InventoryEntry("person", "person", 1, LLAssetType::AT_PERSON));
addEntry(LLInventoryType::IT_SETTINGS, new InventoryEntry("settings", "settings", 1, LLAssetType::AT_SETTINGS));
+ addEntry(LLInventoryType::IT_MATERIAL, new InventoryEntry("material", "render material", 1, LLAssetType::AT_MATERIAL));
}
@@ -153,7 +154,8 @@ DEFAULT_ASSET_FOR_INV_TYPE[LLAssetType::AT_COUNT] =
LLInventoryType::IT_NONE, // 53 AT_RESERVED_4
LLInventoryType::IT_NONE, // 54 AT_RESERVED_5
- LLInventoryType::IT_SETTINGS, // 55 AT_SETTINGS
+ LLInventoryType::IT_SETTINGS, // 55 AT_SETTINGS <- why doesnt this match the value in llassettype.h? -brad
+ LLInventoryType::IT_MATERIAL, // 57 AT_MATERIAL
};
// static
diff --git a/indra/llinventory/llinventorytype.h b/indra/llinventory/llinventorytype.h
index b6e7fb047f..a5543814d8 100644
--- a/indra/llinventory/llinventorytype.h
+++ b/indra/llinventory/llinventorytype.h
@@ -65,7 +65,8 @@ public:
IT_WIDGET = 23,
IT_PERSON = 24,
IT_SETTINGS = 25,
- IT_COUNT = 26,
+ IT_MATERIAL = 26,
+ IT_COUNT = 27,
IT_UNKNOWN = 255,
IT_NONE = -1
@@ -118,6 +119,8 @@ public:
ICONNAME_SETTINGS_WATER,
ICONNAME_SETTINGS_DAY,
+ ICONNAME_MATERIAL,
+
ICONNAME_INVALID,
ICONNAME_UNKNOWN,
ICONNAME_COUNT,
diff --git a/indra/llinventory/llsettingssky.cpp b/indra/llinventory/llsettingssky.cpp
index 83a92f08d0..4004793ffd 100644
--- a/indra/llinventory/llsettingssky.cpp
+++ b/indra/llinventory/llsettingssky.cpp
@@ -131,6 +131,8 @@ const std::string LLSettingsSky::SETTING_SKY_MOISTURE_LEVEL("moisture_level");
const std::string LLSettingsSky::SETTING_SKY_DROPLET_RADIUS("droplet_radius");
const std::string LLSettingsSky::SETTING_SKY_ICE_LEVEL("ice_level");
+const std::string LLSettingsSky::SETTING_REFLECTION_PROBE_AMBIANCE("reflection_probe_ambiance");
+
const LLUUID LLSettingsSky::DEFAULT_ASSET_ID("3ae23978-ac82-bcf3-a9cb-ba6e52dcb9ad");
static const LLUUID DEFAULT_SUN_ID("32bfbcea-24b1-fb9d-1ef9-48a28a63730f"); // dataserver
@@ -630,6 +632,9 @@ LLSettingsSky::validation_list_t LLSettingsSky::validationList()
validation.push_back(Validator(SETTING_SKY_ICE_LEVEL, false, LLSD::TypeReal,
boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(1.0f)))));
+ validation.push_back(Validator(SETTING_REFLECTION_PROBE_AMBIANCE, false, LLSD::TypeReal,
+ boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(1.0f)))));
+
validation.push_back(Validator(SETTING_RAYLEIGH_CONFIG, true, LLSD::TypeArray, &validateRayleighLayers));
validation.push_back(Validator(SETTING_ABSORPTION_CONFIG, true, LLSD::TypeArray, &validateAbsorptionLayers));
validation.push_back(Validator(SETTING_MIE_CONFIG, true, LLSD::TypeArray, &validateMieLayers));
@@ -755,6 +760,8 @@ LLSD LLSettingsSky::defaults(const LLSettingsBase::TrackPosition& position)
dfltsetting[SETTING_SKY_DROPLET_RADIUS] = 800.0f;
dfltsetting[SETTING_SKY_ICE_LEVEL] = 0.0f;
+ dfltsetting[SETTING_REFLECTION_PROBE_AMBIANCE] = 0.0f;
+
dfltsetting[SETTING_RAYLEIGH_CONFIG] = rayleighConfigDefault();
dfltsetting[SETTING_MIE_CONFIG] = mieConfigDefault();
dfltsetting[SETTING_ABSORPTION_CONFIG] = absorptionConfigDefault();
@@ -1132,6 +1139,11 @@ void LLSettingsSky::setSkyIceLevel(F32 ice_level)
setValue(SETTING_SKY_ICE_LEVEL, ice_level);
}
+void LLSettingsSky::setReflectionProbeAmbiance(F32 ambiance)
+{
+ setValue(SETTING_REFLECTION_PROBE_AMBIANCE, ambiance);
+}
+
void LLSettingsSky::setAmbientColor(const LLColor3 &val)
{
mSettings[SETTING_LEGACY_HAZE][SETTING_AMBIENT] = val.getValue();
@@ -1420,6 +1432,21 @@ F32 LLSettingsSky::getSkyIceLevel() const
return mSettings[SETTING_SKY_ICE_LEVEL].asReal();
}
+F32 LLSettingsSky::getReflectionProbeAmbiance() const
+{
+ return mSettings[SETTING_REFLECTION_PROBE_AMBIANCE].asReal();
+}
+
+F32 LLSettingsSky::getTotalReflectionProbeAmbiance() const
+{
+ // feed cloud shadow back into reflection probe ambiance to mimic pre-reflection-probe behavior
+ // without brightening dark/interior spaces
+ F32 probe_ambiance = getReflectionProbeAmbiance();
+ probe_ambiance += (1.f - probe_ambiance) * getCloudShadow()*0.5f;
+
+ return probe_ambiance;
+}
+
F32 LLSettingsSky::getSkyBottomRadius() const
{
return mSettings[SETTING_SKY_BOTTOM_RADIUS].asReal();
diff --git a/indra/llinventory/llsettingssky.h b/indra/llinventory/llsettingssky.h
index fa9326f006..b17b32ebb1 100644
--- a/indra/llinventory/llsettingssky.h
+++ b/indra/llinventory/llsettingssky.h
@@ -97,6 +97,8 @@ public:
static const std::string SETTING_SKY_DROPLET_RADIUS;
static const std::string SETTING_SKY_ICE_LEVEL;
+ static const std::string SETTING_REFLECTION_PROBE_AMBIANCE;
+
static const std::string SETTING_LEGACY_HAZE;
static const LLUUID DEFAULT_ASSET_ID;
@@ -131,6 +133,12 @@ public:
F32 getSkyDropletRadius() const;
F32 getSkyIceLevel() const;
+ // get the probe ambiance setting as stored in the sky settings asset
+ F32 getReflectionProbeAmbiance() const;
+
+ // get the probe ambiance setting to use for rendering (adjusted by cloud shadow, aka cloud coverage)
+ F32 getTotalReflectionProbeAmbiance() const;
+
// Return first (only) profile layer represented in LLSD
LLSD getRayleighConfig() const;
LLSD getMieConfig() const;
@@ -159,6 +167,8 @@ public:
void setSkyDropletRadius(F32 radius);
void setSkyIceLevel(F32 ice_level);
+ void setReflectionProbeAmbiance(F32 ambiance);
+
//---------------------------------------------------------------------
LLColor3 getAmbientColor() const;
void setAmbientColor(const LLColor3 &val);
diff --git a/indra/llkdu/llimagej2ckdu.cpp b/indra/llkdu/llimagej2ckdu.cpp
index dac5349f57..2ad42d6b87 100644
--- a/indra/llkdu/llimagej2ckdu.cpp
+++ b/indra/llkdu/llimagej2ckdu.cpp
@@ -379,6 +379,7 @@ void LLImageJ2CKDU::setupCodeStream(LLImageJ2C &base, bool keep_codestream, ECod
void LLImageJ2CKDU::cleanupCodeStream()
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
mInputp.reset();
mDecodeState.reset();
mCodeStreamp.reset();
@@ -426,6 +427,7 @@ bool LLImageJ2CKDU::initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int bloc
// decodeImpl() usage matters for production.
bool LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, ECodeStreamMode mode, S32 first_channel, S32 max_channel_count, int discard_level, int* region)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
base.resetLastError();
// *FIX: kdu calls our callback function if there's an error, and then bombs.
@@ -509,6 +511,7 @@ bool LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco
// Returns true to mean done, whether successful or not.
bool LLImageJ2CKDU::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
ECodeStreamMode mode = MODE_FAST;
LLTimer decode_timer;
@@ -1332,6 +1335,7 @@ the `buf' pointer may actually point into a larger buffer representing
multiple tiles. For this reason, `row_gap' is needed to identify the
separation between consecutive rows in the real buffer. */
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
S32 c;
// Now walk through the lines of the buffer, recovering them from the
// relevant tile-component processing engines.
@@ -1339,18 +1343,27 @@ separation between consecutive rows in the real buffer. */
LLTimer decode_timer;
while (mDims.size.y--)
{
- for (c = 0; c < mNumComponents; c++)
- {
- mEngines[c].pull(mLines[c]);
- }
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("kduptc - pull");
+ for (c = 0; c < mNumComponents; c++)
+ {
+ mEngines[c].pull(mLines[c]);
+ }
+ }
+
if ((mNumComponents >= 3) && mUseYCC)
{
+ LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("kduptc - convert");
kdu_convert_ycc_to_rgb(mLines[0],mLines[1],mLines[2]);
}
- for (c = 0; c < mNumComponents; c++)
- {
- transfer_bytes(mBuf+c,mLines[c],mNumComponents,mBitDepths[c]);
- }
+
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("kduptc - transfer");
+ for (c = 0; c < mNumComponents; c++)
+ {
+ transfer_bytes(mBuf + c, mLines[c], mNumComponents, mBitDepths[c]);
+ }
+ }
mBuf += mRowGap;
if (mDims.size.y % 10)
{
diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp
index 281f1bd87a..9919af5368 100644
--- a/indra/llmath/llvolume.cpp
+++ b/indra/llmath/llvolume.cpp
@@ -32,6 +32,7 @@
#include <stdint.h>
#endif
#include <cmath>
+#include <unordered_map>
#include "llerror.h"
@@ -52,6 +53,11 @@
#include "llmeshoptimizer.h"
#include "lltimer.h"
+#include "mikktspace/mikktspace.h"
+#include "mikktspace/mikktspace.c" // insert mikktspace implementation into llvolume object file
+
+#include "meshoptimizer/meshoptimizer.h"
+
#define DEBUG_SILHOUETTE_BINORMALS 0
#define DEBUG_SILHOUETTE_NORMALS 0 // TomY: Use this to display normals using the silhouette
#define DEBUG_SILHOUETTE_EDGE_MAP 0 // DaveP: Use this to display edge map using the silhouette
@@ -2093,7 +2099,9 @@ void LLVolume::regen()
void LLVolume::genTangents(S32 face)
{
- mVolumeFaces[face].createTangents();
+ // generate legacy tangents for the specified face
+ llassert(!isMeshAssetLoaded() || mVolumeFaces[face].mTangents != nullptr); // if this is a complete mesh asset, we should already have tangents
+ mVolumeFaces[face].createTangents();
}
LLVolume::~LLVolume()
@@ -2433,11 +2441,10 @@ bool LLVolume::unpackVolumeFacesInternal(const LLSD& mdl)
LLSD::Binary pos = mdl[i]["Position"];
LLSD::Binary norm = mdl[i]["Normal"];
+ LLSD::Binary tangent = mdl[i]["Tangent"];
LLSD::Binary tc = mdl[i]["TexCoord0"];
LLSD::Binary idx = mdl[i]["TriangleList"];
-
-
//copy out indices
S32 num_indices = idx.size() / 2;
const S32 indices_to_discard = num_indices % 3;
@@ -2492,6 +2499,16 @@ bool LLVolume::unpackVolumeFacesInternal(const LLSD& mdl)
min_tc.setValue(mdl[i]["TexCoord0Domain"]["Min"]);
max_tc.setValue(mdl[i]["TexCoord0Domain"]["Max"]);
+ //unpack normalized scale/translation
+ if (mdl[i].has("NormalizedScale"))
+ {
+ face.mNormalizedScale.setValue(mdl[i]["NormalizedScale"]);
+ }
+ else
+ {
+ face.mNormalizedScale.set(1, 1, 1);
+ }
+
LLVector4a pos_range;
pos_range.setSub(max_pos, min_pos);
LLVector2 tc_range2 = max_tc - min_tc;
@@ -2542,6 +2559,34 @@ bool LLVolume::unpackVolumeFacesInternal(const LLSD& mdl)
}
}
+#if 0 // keep this code for now in case we decide to add support for on-the-wire tangents
+ {
+ if (!tangent.empty())
+ {
+ face.allocateTangents(face.mNumVertices);
+ U16* t = (U16*)&(tangent[0]);
+
+ // NOTE: tangents coming from the asset may not be mikkt space, but they should always be used by the GLTF shaders to
+ // maintain compliance with the GLTF spec
+ LLVector4a* t_out = face.mTangents;
+
+ for (U32 j = 0; j < num_verts; ++j)
+ {
+ t_out->set((F32)t[0], (F32)t[1], (F32)t[2], (F32) t[3]);
+ t_out->div(65535.f);
+ t_out->mul(2.f);
+ t_out->sub(1.f);
+
+ F32* tp = t_out->getF32ptr();
+ tp[3] = tp[3] < 0.f ? -1.f : 1.f;
+
+ t_out++;
+ t += 4;
+ }
+ }
+ }
+#endif
+
{
if (!tc.empty())
{
@@ -2745,7 +2790,7 @@ bool LLVolume::unpackVolumeFacesInternal(const LLSD& mdl)
}
}
- if (!cacheOptimize())
+ if (!cacheOptimize(true))
{
// Out of memory?
LL_WARNS() << "Failed to optimize!" << LL_ENDL;
@@ -2786,11 +2831,11 @@ void LLVolume::copyVolumeFaces(const LLVolume* volume)
mSculptLevel = 0;
}
-bool LLVolume::cacheOptimize()
+bool LLVolume::cacheOptimize(bool gen_tangents)
{
for (S32 i = 0; i < mVolumeFaces.size(); ++i)
{
- if (!mVolumeFaces[i].cacheOptimize())
+ if (!mVolumeFaces[i].cacheOptimize(gen_tangents))
{
return false;
}
@@ -4073,7 +4118,7 @@ S32 LLVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& en
{
if (tangent_out != NULL) // if the caller wants tangents, we may need to generate them
{
- genTangents(i);
+ genTangents(i);
}
if (isUnique())
@@ -4818,6 +4863,17 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src)
mTangents = NULL;
}
+ if (src.mTangents)
+ {
+ allocateTangents(src.mNumVertices);
+ LLVector4a::memcpyNonAliased16((F32*)mTangents, (F32*)src.mTangents, vert_size);
+ }
+ else
+ {
+ ll_aligned_free_16(mTangents);
+ mTangents = nullptr;
+ }
+
if (src.mWeights)
{
llassert(!mWeights); // don't orphan an old alloc here accidentally
@@ -4861,6 +4917,7 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src)
}
mOptimized = src.mOptimized;
+ mNormalizedScale = src.mNormalizedScale;
//delete
return *this;
@@ -5383,256 +5440,211 @@ public:
}
};
+// data structures for tangent generation
-bool LLVolumeFace::cacheOptimize()
-{ //optimize for vertex cache according to Forsyth method:
- // http://home.comcast.net/~tom_forsyth/papers/fast_vert_cache_opt.html
-
- llassert(!mOptimized);
- mOptimized = TRUE;
+struct MikktData
+{
+ LLVolumeFace* face;
+ std::vector<LLVector3> p;
+ std::vector<LLVector3> n;
+ std::vector<LLVector2> tc;
+ std::vector<LLVector4> w;
+ std::vector<LLVector4> t;
- LLVCacheLRU cache;
-
- if (mNumVertices < 3 || mNumIndices < 3)
- { //nothing to do
- return true;
- }
+ MikktData(LLVolumeFace* f)
+ : face(f)
+ {
+ U32 count = face->mNumIndices;
- //mapping of vertices to triangles and indices
- std::vector<LLVCacheVertexData> vertex_data;
+ p.resize(count);
+ n.resize(count);
+ tc.resize(count);
+ t.resize(count);
- //mapping of triangles do vertices
- std::vector<LLVCacheTriangleData> triangle_data;
+ if (face->mWeights)
+ {
+ w.resize(count);
+ }
- try
- {
- triangle_data.resize(mNumIndices / 3);
- vertex_data.resize(mNumVertices);
- for (U32 i = 0; i < mNumIndices; i++)
- { //populate vertex data and triangle data arrays
- U16 idx = mIndices[i];
- U32 tri_idx = i / 3;
+ LLVector3 inv_scale(1.f / face->mNormalizedScale.mV[0], 1.f / face->mNormalizedScale.mV[1], 1.f / face->mNormalizedScale.mV[2]);
+
+
+ for (int i = 0; i < face->mNumIndices; ++i)
+ {
+ U32 idx = face->mIndices[i];
+
+ p[i].set(face->mPositions[idx].getF32ptr());
+ p[i].scaleVec(face->mNormalizedScale); //put mesh in original coordinate frame when reconstructing tangents
+ n[i].set(face->mNormals[idx].getF32ptr());
+ n[i].scaleVec(inv_scale);
+ n[i].normalize();
+ tc[i].set(face->mTexCoords[idx]);
- if (idx >= mNumVertices)
+ if (idx >= face->mNumVertices)
{
// invalid index
// replace with a valid index to avoid crashes
- idx = mNumVertices - 1;
- mIndices[i] = idx;
+ idx = face->mNumVertices - 1;
+ face->mIndices[i] = idx;
// Needs better logging
LL_DEBUGS_ONCE("LLVOLUME") << "Invalid index, substituting" << LL_ENDL;
}
- vertex_data[idx].mTriangles.push_back(&(triangle_data[tri_idx]));
- vertex_data[idx].mIdx = idx;
- triangle_data[tri_idx].mVertex[i % 3] = &(vertex_data[idx]);
+ if (face->mWeights)
+ {
+ w[i].set(face->mWeights[idx].getF32ptr());
+ }
}
}
- catch (std::bad_alloc&)
- {
- // resize or push_back failed
- LL_WARNS("LLVOLUME") << "Resize for " << mNumVertices << " vertices failed" << LL_ENDL;
- return false;
- }
+};
- /*F32 pre_acmr = 1.f;
- //measure cache misses from before rebuild
- {
- LLVCacheFIFO test_cache;
- for (U32 i = 0; i < mNumIndices; ++i)
- {
- test_cache.addVertex(&vertex_data[mIndices[i]]);
- }
- for (U32 i = 0; i < mNumVertices; i++)
- {
- vertex_data[i].mCacheTag = -1;
- }
+bool LLVolumeFace::cacheOptimize(bool gen_tangents)
+{ //optimize for vertex cache according to Forsyth method:
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME;
+ llassert(!mOptimized);
+ mOptimized = TRUE;
- pre_acmr = (F32) test_cache.mMisses/(mNumIndices/3);
- }*/
+ if (gen_tangents && mNormals && mTexCoords)
+ { // generate mikkt space tangents before cache optimizing since the index buffer may change
+ // a bit of a hack to do this here, but this function gets called exactly once for the lifetime of a mesh
+ // and is executed on a background thread
+ SMikkTSpaceInterface ms;
- for (U32 i = 0; i < mNumVertices; i++)
- { //initialize score values (no cache -- might try a fifo cache here)
- LLVCacheVertexData& data = vertex_data[i];
+ ms.m_getNumFaces = [](const SMikkTSpaceContext* pContext)
+ {
+ MikktData* data = (MikktData*)pContext->m_pUserData;
+ LLVolumeFace* face = data->face;
+ return face->mNumIndices / 3;
+ };
- data.mScore = find_vertex_score(data);
- data.mActiveTriangles = data.mTriangles.size();
+ ms.m_getNumVerticesOfFace = [](const SMikkTSpaceContext* pContext, const int iFace)
+ {
+ return 3;
+ };
- for (U32 j = 0; j < data.mActiveTriangles; ++j)
- {
- data.mTriangles[j]->mScore += data.mScore;
- }
- }
+ ms.m_getPosition = [](const SMikkTSpaceContext* pContext, float fvPosOut[], const int iFace, const int iVert)
+ {
+ MikktData* data = (MikktData*)pContext->m_pUserData;
+ F32* v = data->p[iFace * 3 + iVert].mV;
+ fvPosOut[0] = v[0];
+ fvPosOut[1] = v[1];
+ fvPosOut[2] = v[2];
+ };
+
+ ms.m_getNormal = [](const SMikkTSpaceContext* pContext, float fvNormOut[], const int iFace, const int iVert)
+ {
+ MikktData* data = (MikktData*)pContext->m_pUserData;
+ F32* n = data->n[iFace * 3 + iVert].mV;
+ fvNormOut[0] = n[0];
+ fvNormOut[1] = n[1];
+ fvNormOut[2] = n[2];
+ };
+
+ ms.m_getTexCoord = [](const SMikkTSpaceContext* pContext, float fvTexcOut[], const int iFace, const int iVert)
+ {
+ MikktData* data = (MikktData*)pContext->m_pUserData;
+ F32* tc = data->tc[iFace * 3 + iVert].mV;
+ fvTexcOut[0] = tc[0];
+ fvTexcOut[1] = tc[1];
+ };
- //sort triangle data by score
- std::sort(triangle_data.begin(), triangle_data.end());
+ ms.m_setTSpaceBasic = [](const SMikkTSpaceContext* pContext, const float fvTangent[], const float fSign, const int iFace, const int iVert)
+ {
+ MikktData* data = (MikktData*)pContext->m_pUserData;
+ S32 i = iFace * 3 + iVert;
+
+ data->t[i].set(fvTangent);
+ data->t[i].mV[3] = fSign;
+ };
- std::vector<U16> new_indices;
+ ms.m_setTSpace = nullptr;
- LLVCacheTriangleData* tri;
+ MikktData data(this);
- //prime pump by adding first triangle to cache;
- tri = &(triangle_data[0]);
- cache.addTriangle(tri);
- new_indices.push_back(tri->mVertex[0]->mIdx);
- new_indices.push_back(tri->mVertex[1]->mIdx);
- new_indices.push_back(tri->mVertex[2]->mIdx);
- tri->complete();
+ SMikkTSpaceContext ctx = { &ms, &data };
- U32 breaks = 0;
- for (U32 i = 1; i < mNumIndices/3; ++i)
- {
- cache.updateScores();
- tri = cache.mBestTriangle;
- if (!tri)
- {
- breaks++;
- for (U32 j = 0; j < triangle_data.size(); ++j)
- {
- if (triangle_data[j].mActive)
- {
- tri = &(triangle_data[j]);
- break;
- }
- }
- }
-
- cache.addTriangle(tri);
- new_indices.push_back(tri->mVertex[0]->mIdx);
- new_indices.push_back(tri->mVertex[1]->mIdx);
- new_indices.push_back(tri->mVertex[2]->mIdx);
- tri->complete();
- }
+ genTangSpaceDefault(&ctx);
- for (U32 i = 0; i < mNumIndices; ++i)
- {
- mIndices[i] = new_indices[i];
- }
+ //re-weld
+ meshopt_Stream mos[] =
+ {
+ { &data.p[0], sizeof(LLVector3), sizeof(LLVector3) },
+ { &data.n[0], sizeof(LLVector3), sizeof(LLVector3) },
+ { &data.t[0], sizeof(LLVector4), sizeof(LLVector4) },
+ { &data.tc[0], sizeof(LLVector2), sizeof(LLVector2) },
+ { data.w.empty() ? nullptr : &data.w[0], sizeof(LLVector4), sizeof(LLVector4) }
+ };
- /*F32 post_acmr = 1.f;
- //measure cache misses from after rebuild
- {
- LLVCacheFIFO test_cache;
- for (U32 i = 0; i < mNumVertices; i++)
- {
- vertex_data[i].mCacheTag = -1;
- }
+ std::vector<U32> remap;
+ remap.resize(data.p.size());
- for (U32 i = 0; i < mNumIndices; ++i)
- {
- test_cache.addVertex(&vertex_data[mIndices[i]]);
- }
-
- post_acmr = (F32) test_cache.mMisses/(mNumIndices/3);
- }*/
+ U32 stream_count = data.w.empty() ? 4 : 5;
- //optimize for pre-TnL cache
-
- //allocate space for new buffer
- S32 num_verts = mNumVertices;
- S32 size = ((num_verts*sizeof(LLVector2)) + 0xF) & ~0xF;
- LLVector4a* pos = (LLVector4a*) ll_aligned_malloc<64>(sizeof(LLVector4a)*2*num_verts+size);
- if (pos == NULL)
- {
- LL_WARNS("LLVOLUME") << "Allocation of positions vector[" << sizeof(LLVector4a) * 2 * num_verts + size << "] failed. " << LL_ENDL;
- return false;
- }
- LLVector4a* norm = pos + num_verts;
- LLVector2* tc = (LLVector2*) (norm + num_verts);
+ U32 vert_count = meshopt_generateVertexRemapMulti(&remap[0], nullptr, data.p.size(), data.p.size(), mos, stream_count);
- LLVector4a* wght = NULL;
- if (mWeights)
- {
- wght = (LLVector4a*)ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts);
- if (wght == NULL)
- {
- ll_aligned_free<64>(pos);
- LL_WARNS("LLVOLUME") << "Allocation of weights[" << sizeof(LLVector4a) * num_verts << "] failed" << LL_ENDL;
- return false;
- }
- }
+ std::vector<U32> indices;
+ indices.resize(mNumIndices);
- LLVector4a* binorm = NULL;
- if (mTangents)
- {
- binorm = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts);
- if (binorm == NULL)
- {
- ll_aligned_free<64>(pos);
- ll_aligned_free_16(wght);
- LL_WARNS("LLVOLUME") << "Allocation of binormals[" << sizeof(LLVector4a)*num_verts << "] failed" << LL_ENDL;
- return false;
- }
- }
+ //copy results back into volume
+ resizeVertices(vert_count);
- //allocate mapping of old indices to new indices
- std::vector<S32> new_idx;
+ if (!data.w.empty())
+ {
+ allocateWeights(vert_count);
+ }
- try
- {
- new_idx.resize(mNumVertices, -1);
- }
- catch (std::bad_alloc&)
- {
- ll_aligned_free<64>(pos);
- ll_aligned_free_16(wght);
- ll_aligned_free_16(binorm);
- LL_WARNS("LLVOLUME") << "Resize failed: " << mNumVertices << LL_ENDL;
- return false;
- }
+ allocateTangents(mNumVertices);
- S32 cur_idx = 0;
- for (U32 i = 0; i < mNumIndices; ++i)
- {
- U16 idx = mIndices[i];
- if (new_idx[idx] == -1)
- { //this vertex hasn't been added yet
- new_idx[idx] = cur_idx;
+ for (int i = 0; i < mNumIndices; ++i)
+ {
+ U32 src_idx = i;
+ U32 dst_idx = remap[i];
+ mIndices[i] = dst_idx;
- //copy vertex data
- pos[cur_idx] = mPositions[idx];
- norm[cur_idx] = mNormals[idx];
- tc[cur_idx] = mTexCoords[idx];
- if (mWeights)
- {
- wght[cur_idx] = mWeights[idx];
- }
- if (mTangents)
- {
- binorm[cur_idx] = mTangents[idx];
- }
+ mPositions[dst_idx].load3(data.p[src_idx].mV);
+ mNormals[dst_idx].load3(data.n[src_idx].mV);
+ mTexCoords[dst_idx] = data.tc[src_idx];
- cur_idx++;
- }
- }
+ mTangents[dst_idx].loadua(data.t[src_idx].mV);
+
+ if (mWeights)
+ {
+ mWeights[dst_idx].loadua(data.w[src_idx].mV);
+ }
+ }
- for (U32 i = 0; i < mNumIndices; ++i)
- {
- mIndices[i] = new_idx[mIndices[i]];
- }
-
- ll_aligned_free<64>(mPositions);
- // DO NOT free mNormals and mTexCoords as they are part of mPositions buffer
- ll_aligned_free_16(mWeights);
- ll_aligned_free_16(mTangents);
-#if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS
- ll_aligned_free_16(mJointIndices);
- ll_aligned_free_16(mJustWeights);
- mJustWeights = NULL;
- mJointIndices = NULL; // filled in later as necessary by skinning code for acceleration
-#endif
- mPositions = pos;
- mNormals = norm;
- mTexCoords = tc;
- mWeights = wght;
- mTangents = binorm;
+ // put back in normalized coordinate frame
+ LLVector4a inv_scale(1.f/mNormalizedScale.mV[0], 1.f / mNormalizedScale.mV[1], 1.f / mNormalizedScale.mV[2]);
+ LLVector4a scale;
+ scale.load3(mNormalizedScale.mV);
+ scale.getF32ptr()[3] = 1.f;
+
+ for (int i = 0; i < mNumVertices; ++i)
+ {
+ mPositions[i].mul(inv_scale);
+ mNormals[i].mul(scale);
+ mNormals[i].normalize3();
+ F32 w = mTangents[i].getF32ptr()[3];
+ mTangents[i].mul(scale);
+ mTangents[i].normalize3();
+ mTangents[i].getF32ptr()[3] = w;
+ }
+ }
- //std::string result = llformat("ACMR pre/post: %.3f/%.3f -- %d triangles %d breaks", pre_acmr, post_acmr, mNumIndices/3, breaks);
- //LL_INFOS() << result << LL_ENDL;
+ // cache optimize index buffer
+
+ // meshopt needs scratch space, do some pointer shuffling to avoid an extra index buffer copy
+ U16* src_indices = mIndices;
+ mIndices = nullptr;
+ resizeIndices(mNumIndices);
+
+ meshopt_optimizeVertexCache<U16>(mIndices, src_indices, mNumIndices, mNumVertices);
+
+ ll_aligned_free_16(src_indices);
return true;
}
@@ -6442,35 +6454,31 @@ void CalculateTangentArray(U32 vertexCount, const LLVector4a *vertex, const LLVe
void LLVolumeFace::createTangents()
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME;
- if (!mTangents)
- {
- allocateTangents(mNumVertices);
-
- //generate tangents
- //LLVector4a* pos = mPositions;
- //LLVector2* tc = (LLVector2*) mTexCoords;
- LLVector4a* binorm = (LLVector4a*) mTangents;
+ if (!mTangents)
+ {
+ allocateTangents(mNumVertices);
+
+ //generate tangents
+ LLVector4a* ptr = (LLVector4a*)mTangents;
- LLVector4a* end = mTangents+mNumVertices;
- while (binorm < end)
- {
- (*binorm++).clear();
- }
+ LLVector4a* end = mTangents + mNumVertices;
+ while (ptr < end)
+ {
+ (*ptr++).clear();
+ }
- binorm = mTangents;
+ CalculateTangentArray(mNumVertices, mPositions, mNormals, mTexCoords, mNumIndices / 3, mIndices, mTangents);
- CalculateTangentArray(mNumVertices, mPositions, mNormals, mTexCoords, mNumIndices/3, mIndices, mTangents);
+ //normalize normals
+ for (U32 i = 0; i < mNumVertices; i++)
+ {
+ //bump map/planar projection code requires normals to be normalized
+ mNormals[i].normalize3fast();
+ }
+ }
- //normalize tangents
- for (U32 i = 0; i < mNumVertices; i++)
- {
- //binorm[i].normalize3fast();
- //bump map/planar projection code requires normals to be normalized
- mNormals[i].normalize3fast();
- }
- }
}
void LLVolumeFace::resizeVertices(S32 num_verts)
diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h
index 1509241623..ad6a669531 100644
--- a/indra/llmath/llvolume.h
+++ b/indra/llmath/llvolume.h
@@ -908,7 +908,7 @@ public:
void remap();
void optimize(F32 angle_cutoff = 2.f);
- bool cacheOptimize();
+ bool cacheOptimize(bool gen_tangents = false);
void createOctree(F32 scaler = 0.25f, const LLVector4a& center = LLVector4a(0,0,0), const LLVector4a& size = LLVector4a(0.5f,0.5f,0.5f));
void destroyOctree();
@@ -960,10 +960,6 @@ public:
// indexes for mPositions/mNormals/mTexCoords
U16* mIndices;
- // vertex buffer filled in by LLFace to cache this volume face geometry in vram
- // (declared as a LLPointer to LLRefCount to avoid dependency on LLVertexBuffer)
- mutable LLPointer<LLRefCount> mVertexBuffer;
-
std::vector<S32> mEdge;
//list of skin weights for rigged volumes
@@ -985,6 +981,11 @@ public:
//whether or not face has been cache optimized
BOOL mOptimized;
+ // if this is a mesh asset, scale and translation that were applied
+ // when encoding the source mesh into a unit cube
+ // used for regenerating tangents
+ LLVector3 mNormalizedScale = LLVector3(1,1,1);
+
private:
LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* mOctree;
LLVolumeTriangle* mOctreeTriangles;
@@ -1033,7 +1034,7 @@ public:
void setDirty() { mPathp->setDirty(); mProfilep->setDirty(); }
void regen();
- void genTangents(S32 face);
+ void genTangents(S32 face);
BOOL isConvex() const;
BOOL isCap(S32 face);
@@ -1087,7 +1088,10 @@ public:
void copyVolumeFaces(const LLVolume* volume);
void copyFacesTo(std::vector<LLVolumeFace> &faces) const;
void copyFacesFrom(const std::vector<LLVolumeFace> &faces);
- bool cacheOptimize();
+
+ // use meshoptimizer to optimize index buffer for vertex shader cache
+ // gen_tangents - if true, generate MikkTSpace tangents if needed before optimizing index buffer
+ bool cacheOptimize(bool gen_tangents = false);
private:
void sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, U8 sculpt_type);
diff --git a/indra/llmath/v3color.h b/indra/llmath/v3color.h
index 43a632408c..d925f56e97 100644
--- a/indra/llmath/v3color.h
+++ b/indra/llmath/v3color.h
@@ -33,6 +33,7 @@ class LLVector4;
#include "llerror.h"
#include "llmath.h"
#include "llsd.h"
+#include "v3math.h" // needed for linearColor3v implemtation below
#include <string.h>
// LLColor3 = |r g b|
@@ -87,6 +88,16 @@ public:
const LLColor3& set(F32 x, F32 y, F32 z); // Sets LLColor3 to (x, y, z)
const LLColor3& set(const LLColor3 &vec); // Sets LLColor3 to vec
const LLColor3& set(const F32 *vec); // Sets LLColor3 to vec
+
+ // set from a vector of unknown type and size
+ // may leave some data unmodified
+ template<typename T>
+ const LLColor3& set(const std::vector<T>& v);
+
+ // write to a vector of unknown type and size
+ // maye leave some data unmodified
+ template<typename T>
+ void write(std::vector<T>& v) const;
F32 magVec() const; // deprecated
F32 magVecSquared() const; // deprecated
@@ -484,13 +495,45 @@ inline const LLColor3 srgbColor3(const LLColor3 &a) {
return srgbColor;
}
-inline const LLColor3 linearColor3(const LLColor3 &a) {
+inline const LLColor3 linearColor3p(const F32* v) {
LLColor3 linearColor;
- linearColor.mV[0] = sRGBtoLinear(a.mV[0]);
- linearColor.mV[1] = sRGBtoLinear(a.mV[1]);
- linearColor.mV[2] = sRGBtoLinear(a.mV[2]);
+ linearColor.mV[0] = sRGBtoLinear(v[0]);
+ linearColor.mV[1] = sRGBtoLinear(v[1]);
+ linearColor.mV[2] = sRGBtoLinear(v[2]);
return linearColor;
}
+template<class T>
+inline const LLColor3 linearColor3(const T& a) {
+ return linearColor3p(a.mV);
+}
+
+template<class T>
+inline const LLVector3 linearColor3v(const T& a) {
+ return LLVector3(linearColor3p(a.mV).mV);
+}
+
+template<typename T>
+const LLColor3& LLColor3::set(const std::vector<T>& v)
+{
+ for (S32 i = 0; i < llmin((S32)v.size(), 3); ++i)
+ {
+ mV[i] = v[i];
+ }
+
+ return *this;
+}
+
+// write to a vector of unknown type and size
+// maye leave some data unmodified
+template<typename T>
+void LLColor3::write(std::vector<T>& v) const
+{
+ for (int i = 0; i < llmin((S32)v.size(), 3); ++i)
+ {
+ v[i] = mV[i];
+ }
+}
+
#endif
diff --git a/indra/llmath/v4color.h b/indra/llmath/v4color.h
index 175edf1471..daa61594fb 100644
--- a/indra/llmath/v4color.h
+++ b/indra/llmath/v4color.h
@@ -88,8 +88,18 @@ class LLColor4
const LLColor4& set(const LLColor3 &vec); // Sets LLColor4 to LLColor3 vec (no change in alpha)
const LLColor4& set(const LLColor3 &vec, F32 a); // Sets LLColor4 to LLColor3 vec, with alpha specified
const LLColor4& set(const F32 *vec); // Sets LLColor4 to vec
- const LLColor4& set(const LLColor4U& color4u); // Sets LLColor4 to color4u, rescaled.
+ const LLColor4& set(const F64 *vec); // Sets LLColor4 to (double)vec
+ const LLColor4& set(const LLColor4U& color4u); // Sets LLColor4 to color4u, rescaled.
+ // set from a vector of unknown type and size
+ // may leave some data unmodified
+ template<typename T>
+ const LLColor4& set(const std::vector<T>& v);
+
+ // write to a vector of unknown type and size
+ // maye leave some data unmodified
+ template<typename T>
+ void write(std::vector<T>& v) const;
const LLColor4& setAlpha(F32 a);
@@ -334,6 +344,15 @@ inline const LLColor4& LLColor4::set(const F32 *vec)
return (*this);
}
+inline const LLColor4& LLColor4::set(const F64 *vec)
+{
+ mV[VX] = static_cast<F32>(vec[VX]);
+ mV[VY] = static_cast<F32>(vec[VY]);
+ mV[VZ] = static_cast<F32>(vec[VZ]);
+ mV[VW] = static_cast<F32>(vec[VW]);
+ return (*this);
+}
+
// deprecated
inline const LLColor4& LLColor4::setVec(F32 x, F32 y, F32 z)
{
@@ -680,5 +699,25 @@ inline const LLColor4 linearColor4(const LLColor4 &a)
return linearColor;
}
+template<typename T>
+const LLColor4& LLColor4::set(const std::vector<T>& v)
+{
+ for (S32 i = 0; i < llmin((S32)v.size(), 4); ++i)
+ {
+ mV[i] = v[i];
+ }
+
+ return *this;
+}
+
+template<typename T>
+void LLColor4::write(std::vector<T>& v) const
+{
+ for (int i = 0; i < llmin((S32)v.size(), 4); ++i)
+ {
+ v[i] = mV[i];
+ }
+}
+
#endif
diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp
index 846549b368..33a0b6abdb 100644
--- a/indra/llmessage/llavatarnamecache.cpp
+++ b/indra/llmessage/llavatarnamecache.cpp
@@ -64,7 +64,6 @@ LLCore::HttpRequest::ptr_t sHttpRequest;
LLCore::HttpHeaders::ptr_t sHttpHeaders;
LLCore::HttpOptions::ptr_t sHttpOptions;
LLCore::HttpRequest::policy_t sHttpPolicy;
-LLCore::HttpRequest::priority_t sHttpPriority;
/* Sample response:
<?xml version="1.0"?>
@@ -121,7 +120,6 @@ LLAvatarNameCache::LLAvatarNameCache()
sHttpHeaders = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders());
sHttpOptions = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions());
sHttpPolicy = LLCore::HttpRequest::DEFAULT_POLICY_ID;
- sHttpPriority = 0;
}
LLAvatarNameCache::~LLAvatarNameCache()
diff --git a/indra/llmessage/llcorehttputil.cpp b/indra/llmessage/llcorehttputil.cpp
index 7031f1aa8c..96af8bacee 100644
--- a/indra/llmessage/llcorehttputil.cpp
+++ b/indra/llmessage/llcorehttputil.cpp
@@ -131,7 +131,6 @@ bool responseToLLSD(HttpResponse * response, bool log, LLSD & out_llsd)
HttpHandle requestPostWithLLSD(HttpRequest * request,
HttpRequest::policy_t policy_id,
- HttpRequest::priority_t priority,
const std::string & url,
const LLSD & body,
const HttpOptions::ptr_t &options,
@@ -145,7 +144,6 @@ HttpHandle requestPostWithLLSD(HttpRequest * request,
LLSDSerialize::toXML(body, bas);
handle = request->requestPost(policy_id,
- priority,
url,
ba,
options,
@@ -158,7 +156,6 @@ HttpHandle requestPostWithLLSD(HttpRequest * request,
HttpHandle requestPutWithLLSD(HttpRequest * request,
HttpRequest::policy_t policy_id,
- HttpRequest::priority_t priority,
const std::string & url,
const LLSD & body,
const HttpOptions::ptr_t &options,
@@ -172,7 +169,6 @@ HttpHandle requestPutWithLLSD(HttpRequest * request,
LLSDSerialize::toXML(body, bas);
handle = request->requestPut(policy_id,
- priority,
url,
ba,
options,
@@ -184,7 +180,6 @@ HttpHandle requestPutWithLLSD(HttpRequest * request,
HttpHandle requestPatchWithLLSD(HttpRequest * request,
HttpRequest::policy_t policy_id,
- HttpRequest::priority_t priority,
const std::string & url,
const LLSD & body,
const HttpOptions::ptr_t &options,
@@ -198,7 +193,6 @@ HttpHandle requestPatchWithLLSD(HttpRequest * request,
LLSDSerialize::toXML(body, bas);
handle = request->requestPatch(policy_id,
- priority,
url,
ba,
options,
@@ -672,10 +666,9 @@ const std::string HttpCoroutineAdapter::HTTP_RESULTS_CONTENT("content");
const std::string HttpCoroutineAdapter::HTTP_RESULTS_RAW("raw");
HttpCoroutineAdapter::HttpCoroutineAdapter(const std::string &name,
- LLCore::HttpRequest::policy_t policyId, LLCore::HttpRequest::priority_t priority) :
+ LLCore::HttpRequest::policy_t policyId) :
mAdapterName(name),
mPolicyId(policyId),
- mPriority(priority),
mYieldingHandle(LLCORE_HTTP_HANDLE_INVALID),
mWeakRequest(),
mWeakHandler()
@@ -709,7 +702,7 @@ LLSD HttpCoroutineAdapter::postAndSuspend_(LLCore::HttpRequest::ptr_t &request,
// The HTTPCoroHandler does not self delete, so retrieval of a the contained
// pointer from the smart pointer is safe in this case.
LLCore::HttpHandle hhandle = requestPostWithLLSD(request,
- mPolicyId, mPriority, url, body, options, headers,
+ mPolicyId, url, body, options, headers,
handler);
if (hhandle == LLCORE_HTTP_HANDLE_INVALID)
@@ -832,7 +825,7 @@ LLSD HttpCoroutineAdapter::postAndSuspend_(LLCore::HttpRequest::ptr_t &request,
// The HTTPCoroHandler does not self delete, so retrieval of a the contained
// pointer from the smart pointer is safe in this case.
- LLCore::HttpHandle hhandle = request->requestPost(mPolicyId, mPriority, url, rawbody.get(),
+ LLCore::HttpHandle hhandle = request->requestPost(mPolicyId, url, rawbody.get(),
options, headers, handler);
if (hhandle == LLCORE_HTTP_HANDLE_INVALID)
@@ -890,7 +883,7 @@ LLSD HttpCoroutineAdapter::putAndSuspend_(LLCore::HttpRequest::ptr_t &request,
// The HTTPCoroHandler does not self delete, so retrieval of a the contained
// pointer from the smart pointer is safe in this case.
LLCore::HttpHandle hhandle = requestPutWithLLSD(request,
- mPolicyId, mPriority, url, body, options, headers,
+ mPolicyId, url, body, options, headers,
handler);
if (hhandle == LLCORE_HTTP_HANDLE_INVALID)
@@ -916,7 +909,7 @@ LLSD HttpCoroutineAdapter::putAndSuspend_(LLCore::HttpRequest::ptr_t &request,
// The HTTPCoroHandler does not self delete, so retrieval of a the contained
// pointer from the smart pointer is safe in this case.
- LLCore::HttpHandle hhandle = request->requestPut(mPolicyId, mPriority,
+ LLCore::HttpHandle hhandle = request->requestPut(mPolicyId,
url, rawbody.get(), options, headers, handler);
if (hhandle == LLCORE_HTTP_HANDLE_INVALID)
@@ -972,7 +965,7 @@ LLSD HttpCoroutineAdapter::getAndSuspend_(LLCore::HttpRequest::ptr_t &request,
// The HTTPCoroHandler does not self delete, so retrieval of a the contained
// pointer from the smart pointer is safe in this case.
- LLCore::HttpHandle hhandle = request->requestGet(mPolicyId, mPriority,
+ LLCore::HttpHandle hhandle = request->requestGet(mPolicyId,
url, options, headers, handler);
if (hhandle == LLCORE_HTTP_HANDLE_INVALID)
@@ -1018,7 +1011,7 @@ LLSD HttpCoroutineAdapter::deleteAndSuspend_(LLCore::HttpRequest::ptr_t &request
checkDefaultHeaders(headers);
// The HTTPCoroHandler does not self delete, so retrieval of a the contained
// pointer from the smart pointer is safe in this case.
- LLCore::HttpHandle hhandle = request->requestDelete(mPolicyId, mPriority,
+ LLCore::HttpHandle hhandle = request->requestDelete(mPolicyId,
url, options, headers, handler);
if (hhandle == LLCORE_HTTP_HANDLE_INVALID)
@@ -1056,7 +1049,7 @@ LLSD HttpCoroutineAdapter::patchAndSuspend_(LLCore::HttpRequest::ptr_t &request,
// The HTTPCoroHandler does not self delete, so retrieval of a the contained
// pointer from the smart pointer is safe in this case.
LLCore::HttpHandle hhandle = requestPatchWithLLSD(request,
- mPolicyId, mPriority, url, body, options, headers,
+ mPolicyId, url, body, options, headers,
handler);
if (hhandle == LLCORE_HTTP_HANDLE_INVALID)
@@ -1098,7 +1091,7 @@ LLSD HttpCoroutineAdapter::copyAndSuspend_(LLCore::HttpRequest::ptr_t &request,
// The HTTPCoroHandler does not self delete, so retrieval of a the contained
// pointer from the smart pointer is safe in this case.
//
- LLCore::HttpHandle hhandle = request->requestCopy(mPolicyId, mPriority, url,
+ LLCore::HttpHandle hhandle = request->requestCopy(mPolicyId, url,
options, headers, handler);
if (hhandle == LLCORE_HTTP_HANDLE_INVALID)
@@ -1140,7 +1133,7 @@ LLSD HttpCoroutineAdapter::moveAndSuspend_(LLCore::HttpRequest::ptr_t &request,
// The HTTPCoroHandler does not self delete, so retrieval of a the contained
// pointer from the smart pointer is safe in this case.
//
- LLCore::HttpHandle hhandle = request->requestMove(mPolicyId, mPriority, url,
+ LLCore::HttpHandle hhandle = request->requestMove(mPolicyId, url,
options, headers, handler);
if (hhandle == LLCORE_HTTP_HANDLE_INVALID)
diff --git a/indra/llmessage/llcorehttputil.h b/indra/llmessage/llcorehttputil.h
index 6f0b865f83..430dc417ac 100644
--- a/indra/llmessage/llcorehttputil.h
+++ b/indra/llmessage/llcorehttputil.h
@@ -116,7 +116,6 @@ std::string responseToString(LLCore::HttpResponse * response);
///
LLCore::HttpHandle requestPostWithLLSD(LLCore::HttpRequest * request,
LLCore::HttpRequest::policy_t policy_id,
- LLCore::HttpRequest::priority_t priority,
const std::string & url,
const LLSD & body,
const LLCore::HttpOptions::ptr_t &options,
@@ -125,20 +124,18 @@ LLCore::HttpHandle requestPostWithLLSD(LLCore::HttpRequest * request,
inline LLCore::HttpHandle requestPostWithLLSD(LLCore::HttpRequest::ptr_t & request,
LLCore::HttpRequest::policy_t policy_id,
- LLCore::HttpRequest::priority_t priority,
const std::string & url,
const LLSD & body,
const LLCore::HttpOptions::ptr_t & options,
const LLCore::HttpHeaders::ptr_t & headers,
const LLCore::HttpHandler::ptr_t & handler)
{
- return requestPostWithLLSD(request.get(), policy_id, priority,
+ return requestPostWithLLSD(request.get(), policy_id,
url, body, options, headers, handler);
}
inline LLCore::HttpHandle requestPostWithLLSD(LLCore::HttpRequest::ptr_t & request,
LLCore::HttpRequest::policy_t policy_id,
- LLCore::HttpRequest::priority_t priority,
const std::string & url,
const LLSD & body,
const LLCore::HttpHandler::ptr_t &handler)
@@ -146,7 +143,7 @@ inline LLCore::HttpHandle requestPostWithLLSD(LLCore::HttpRequest::ptr_t & reque
LLCore::HttpOptions::ptr_t options;
LLCore::HttpHeaders::ptr_t headers;
- return requestPostWithLLSD(request.get(), policy_id, priority,
+ return requestPostWithLLSD(request.get(), policy_id,
url, body, options, headers, handler);
}
@@ -169,7 +166,6 @@ inline LLCore::HttpHandle requestPostWithLLSD(LLCore::HttpRequest::ptr_t & reque
///
LLCore::HttpHandle requestPutWithLLSD(LLCore::HttpRequest * request,
LLCore::HttpRequest::policy_t policy_id,
- LLCore::HttpRequest::priority_t priority,
const std::string & url,
const LLSD & body,
const LLCore::HttpOptions::ptr_t &options,
@@ -178,20 +174,18 @@ LLCore::HttpHandle requestPutWithLLSD(LLCore::HttpRequest * request,
inline LLCore::HttpHandle requestPutWithLLSD(LLCore::HttpRequest::ptr_t & request,
LLCore::HttpRequest::policy_t policy_id,
- LLCore::HttpRequest::priority_t priority,
const std::string & url,
const LLSD & body,
const LLCore::HttpOptions::ptr_t & options,
const LLCore::HttpHeaders::ptr_t & headers,
LLCore::HttpHandler::ptr_t handler)
{
- return requestPutWithLLSD(request.get(), policy_id, priority,
+ return requestPutWithLLSD(request.get(), policy_id,
url, body, options, headers, handler);
}
inline LLCore::HttpHandle requestPutWithLLSD(LLCore::HttpRequest::ptr_t & request,
LLCore::HttpRequest::policy_t policy_id,
- LLCore::HttpRequest::priority_t priority,
const std::string & url,
const LLSD & body,
LLCore::HttpHandler::ptr_t handler)
@@ -199,7 +193,7 @@ inline LLCore::HttpHandle requestPutWithLLSD(LLCore::HttpRequest::ptr_t & reques
LLCore::HttpOptions::ptr_t options;
LLCore::HttpHeaders::ptr_t headers;
- return requestPutWithLLSD(request.get(), policy_id, priority,
+ return requestPutWithLLSD(request.get(), policy_id,
url, body, options, headers, handler);
}
@@ -221,7 +215,6 @@ inline LLCore::HttpHandle requestPutWithLLSD(LLCore::HttpRequest::ptr_t & reques
///
LLCore::HttpHandle requestPatchWithLLSD(LLCore::HttpRequest * request,
LLCore::HttpRequest::policy_t policy_id,
- LLCore::HttpRequest::priority_t priority,
const std::string & url,
const LLSD & body,
const LLCore::HttpOptions::ptr_t &options,
@@ -230,20 +223,18 @@ LLCore::HttpHandle requestPatchWithLLSD(LLCore::HttpRequest * request,
inline LLCore::HttpHandle requestPatchWithLLSD(LLCore::HttpRequest::ptr_t & request,
LLCore::HttpRequest::policy_t policy_id,
- LLCore::HttpRequest::priority_t priority,
const std::string & url,
const LLSD & body,
const LLCore::HttpOptions::ptr_t & options,
const LLCore::HttpHeaders::ptr_t & headers,
const LLCore::HttpHandler::ptr_t & handler)
{
- return requestPatchWithLLSD(request.get(), policy_id, priority,
+ return requestPatchWithLLSD(request.get(), policy_id,
url, body, options, headers, handler);
}
inline LLCore::HttpHandle requestPatchWithLLSD(LLCore::HttpRequest::ptr_t & request,
LLCore::HttpRequest::policy_t policy_id,
- LLCore::HttpRequest::priority_t priority,
const std::string & url,
const LLSD & body,
const LLCore::HttpHandler::ptr_t &handler)
@@ -251,7 +242,7 @@ inline LLCore::HttpHandle requestPatchWithLLSD(LLCore::HttpRequest::ptr_t & requ
LLCore::HttpOptions::ptr_t options;
LLCore::HttpHeaders::ptr_t headers;
- return requestPatchWithLLSD(request.get(), policy_id, priority,
+ return requestPatchWithLLSD(request.get(), policy_id,
url, body, options, headers, handler);
}
@@ -329,8 +320,7 @@ public:
typedef boost::shared_ptr<HttpCoroutineAdapter> ptr_t;
typedef boost::weak_ptr<HttpCoroutineAdapter> wptr_t;
- HttpCoroutineAdapter(const std::string &name, LLCore::HttpRequest::policy_t policyId,
- LLCore::HttpRequest::priority_t priority = 0L);
+ HttpCoroutineAdapter(const std::string &name, LLCore::HttpRequest::policy_t policyId);
~HttpCoroutineAdapter();
/// Execute a Post transaction on the supplied URL and yield execution of
@@ -673,7 +663,6 @@ private:
void checkDefaultHeaders(LLCore::HttpHeaders::ptr_t &headers);
std::string mAdapterName;
- LLCore::HttpRequest::priority_t mPriority;
LLCore::HttpRequest::policy_t mPolicyId;
LLCore::HttpHandle mYieldingHandle;
diff --git a/indra/llmessage/tests/llcoproceduremanager_test.cpp b/indra/llmessage/tests/llcoproceduremanager_test.cpp
index a1a4ce0520..d6481d4eea 100644
--- a/indra/llmessage/tests/llcoproceduremanager_test.cpp
+++ b/indra/llmessage/tests/llcoproceduremanager_test.cpp
@@ -48,7 +48,7 @@
#pragma warning(disable: 4702)
#endif
-LLCoreHttpUtil::HttpCoroutineAdapter::HttpCoroutineAdapter(std::string const&, unsigned int, unsigned int)
+LLCoreHttpUtil::HttpCoroutineAdapter::HttpCoroutineAdapter(std::string const&, unsigned int)
{
}
diff --git a/indra/llprimitive/CMakeLists.txt b/indra/llprimitive/CMakeLists.txt
index 7b6d04b096..328b22f900 100644
--- a/indra/llprimitive/CMakeLists.txt
+++ b/indra/llprimitive/CMakeLists.txt
@@ -10,15 +10,19 @@ include(LLCoreHttp)
include(LLXML)
include(LLPhysicsExtensions)
include(LLCharacter)
+include(LLRender)
+include(TinyGLTF)
include_directories(
${LLCOMMON_INCLUDE_DIRS}
${LLMATH_INCLUDE_DIRS}
${LLMESSAGE_INCLUDE_DIRS}
${LLXML_INCLUDE_DIRS}
+ ${LLRENDER_INCLUDE_DIRS}
${LIBS_PREBUILT_DIR}/include/collada
${LIBS_PREBUILT_DIR}/include/collada/1.4
${LLCHARACTER_INCLUDE_DIRS}
+ ${TINYGLTF_INCLUDE_DIR}
)
include_directories(SYSTEM
${LLCOMMON_SYSTEM_INCLUDE_DIRS}
@@ -28,6 +32,8 @@ include_directories(SYSTEM
set(llprimitive_SOURCE_FILES
lldaeloader.cpp
+ llgltfloader.cpp
+ llgltfmaterial.cpp
llmaterialid.cpp
llmaterial.cpp
llmaterialtable.cpp
@@ -46,6 +52,8 @@ set(llprimitive_SOURCE_FILES
set(llprimitive_HEADER_FILES
CMakeLists.txt
lldaeloader.h
+ llgltfloader.h
+ llgltfmaterial.h
legacy_object_types.h
llmaterial.h
llmaterialid.h
@@ -90,6 +98,7 @@ if (LL_TESTS)
INCLUDE(LLAddBuildTest)
SET(llprimitive_TEST_SOURCE_FILES
llmediaentry.cpp
+ llprimitive.cpp
)
LL_ADD_PROJECT_UNIT_TESTS(llprimitive "${llprimitive_TEST_SOURCE_FILES}")
endif (LL_TESTS)
diff --git a/indra/llprimitive/lldaeloader.cpp b/indra/llprimitive/lldaeloader.cpp
index 752a850d42..46e1cb4922 100644
--- a/indra/llprimitive/lldaeloader.cpp
+++ b/indra/llprimitive/lldaeloader.cpp
@@ -2507,20 +2507,6 @@ bool LLDAELoader::addVolumeFacesFromDomMesh(LLModel* pModel,domMesh* mesh, LLSD&
return (status == LLModel::NO_ERRORS);
}
-//static
-LLModel* LLDAELoader::loadModelFromDomMesh(domMesh *mesh)
-{
- LLVolumeParams volume_params;
- volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE);
- LLModel* ret = new LLModel(volume_params, 0.f);
- createVolumeFacesFromDomMesh(ret, mesh);
- if (ret->mLabel.empty())
- {
- ret->mLabel = getElementLabel(mesh);
- }
- return ret;
-}
-
//static diff version supports creating multiple models when material counts spill
// over the 8 face server-side limit
//
@@ -2578,6 +2564,7 @@ bool LLDAELoader::loadModelsFromDomMesh(domMesh* mesh, std::vector<LLModel*>& mo
ret->trimVolumeFacesToSize(LL_SCULPT_MESH_MAX_FACES, &remainder);
+ // remove unused/redundant vertices after normalizing
if (!mNoOptimize)
{
ret->remapVolumeFaces();
@@ -2597,7 +2584,7 @@ bool LLDAELoader::loadModelsFromDomMesh(domMesh* mesh, std::vector<LLModel*>& mo
next->mLabel = model_name + (char)((int)'a' + next->mSubmodelID) + lod_suffix[mLod];
next->getVolumeFaces() = remainder;
next->mNormalizedScale = ret->mNormalizedScale;
- next->mNormalizedTranslation = ret->mNormalizedTranslation;
+
if ( ret->mMaterialList.size() > LL_SCULPT_MESH_MAX_FACES)
{
next->mMaterialList.assign(ret->mMaterialList.begin() + LL_SCULPT_MESH_MAX_FACES, ret->mMaterialList.end());
@@ -2611,31 +2598,3 @@ bool LLDAELoader::loadModelsFromDomMesh(domMesh* mesh, std::vector<LLModel*>& mo
return true;
}
-
-bool LLDAELoader::createVolumeFacesFromDomMesh(LLModel* pModel, domMesh* mesh)
-{
- if (mesh)
- {
- pModel->ClearFacesAndMaterials();
-
- LLSD placeholder;
- addVolumeFacesFromDomMesh(pModel, mesh, placeholder);
-
- if (pModel->getNumVolumeFaces() > 0)
- {
- pModel->normalizeVolumeFaces();
- pModel->optimizeVolumeFaces();
-
- if (pModel->getNumVolumeFaces() > 0)
- {
- return true;
- }
- }
- }
- else
- {
- LL_WARNS() << "no mesh found" << LL_ENDL;
- }
-
- return false;
-}
diff --git a/indra/llprimitive/lldaeloader.h b/indra/llprimitive/lldaeloader.h
index 2b211343e1..52ad908870 100644
--- a/indra/llprimitive/lldaeloader.h
+++ b/indra/llprimitive/lldaeloader.h
@@ -90,9 +90,6 @@ protected:
bool verifyController( domController* pController );
static bool addVolumeFacesFromDomMesh(LLModel* model, domMesh* mesh, LLSD& log_msg);
- static bool createVolumeFacesFromDomMesh(LLModel* model, domMesh *mesh);
-
- static LLModel* loadModelFromDomMesh(domMesh* mesh);
// Loads a mesh breaking it into one or more models as necessary
// to get around volume face limitations while retaining >8 materials
diff --git a/indra/llprimitive/llgltfloader.cpp b/indra/llprimitive/llgltfloader.cpp
new file mode 100644
index 0000000000..6041c9c273
--- /dev/null
+++ b/indra/llprimitive/llgltfloader.cpp
@@ -0,0 +1,402 @@
+/**
+ * @file LLGLTFLoader.cpp
+ * @brief LLGLTFLoader class implementation
+ *
+ * $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$
+ */
+
+#include "llgltfloader.h"
+
+// Import & define single-header gltf import/export lib
+#define TINYGLTF_IMPLEMENTATION
+#define TINYGLTF_USE_CPP14 // default is C++ 11
+
+// tinygltf by default loads image files using STB
+#define STB_IMAGE_IMPLEMENTATION
+// to use our own image loading:
+// 1. replace this definition with TINYGLTF_NO_STB_IMAGE
+// 2. provide image loader callback with TinyGLTF::SetImageLoader(LoadimageDataFunction LoadImageData, void *user_data)
+
+// tinygltf saves image files using STB
+#define STB_IMAGE_WRITE_IMPLEMENTATION
+// similarly, can override with TINYGLTF_NO_STB_IMAGE_WRITE and TinyGLTF::SetImageWriter(fxn, data)
+
+// Additionally, disable inclusion of STB header files entirely with
+// TINYGLTF_NO_INCLUDE_STB_IMAGE
+// TINYGLTF_NO_INCLUDE_STB_IMAGE_WRITE
+#include "tinygltf/tiny_gltf.h"
+
+
+// TODO: includes inherited from dae loader. Validate / prune
+
+#include <boost/lexical_cast.hpp>
+
+#include "llsdserialize.h"
+#include "lljoint.h"
+
+#include "glh/glh_linear.h"
+#include "llmatrix4a.h"
+
+#include <boost/regex.hpp>
+#include <boost/algorithm/string/replace.hpp>
+
+static const std::string lod_suffix[LLModel::NUM_LODS] =
+{
+ "_LOD0",
+ "_LOD1",
+ "_LOD2",
+ "",
+ "_PHYS",
+};
+
+
+LLGLTFLoader::LLGLTFLoader(std::string filename,
+ S32 lod,
+ LLModelLoader::load_callback_t load_cb,
+ LLModelLoader::joint_lookup_func_t joint_lookup_func,
+ LLModelLoader::texture_load_func_t texture_load_func,
+ LLModelLoader::state_callback_t state_cb,
+ void * opaque_userdata,
+ JointTransformMap & jointTransformMap,
+ JointNameSet & jointsFromNodes,
+ std::map<std::string, std::string> &jointAliasMap,
+ U32 maxJointsPerMesh,
+ U32 modelLimit) //,
+ //bool preprocess)
+ : LLModelLoader( filename,
+ lod,
+ load_cb,
+ joint_lookup_func,
+ texture_load_func,
+ state_cb,
+ opaque_userdata,
+ jointTransformMap,
+ jointsFromNodes,
+ jointAliasMap,
+ maxJointsPerMesh ),
+ //mPreprocessGLTF(preprocess),
+ mMeshesLoaded(false),
+ mMaterialsLoaded(false)
+{
+}
+
+LLGLTFLoader::~LLGLTFLoader() {}
+
+bool LLGLTFLoader::OpenFile(const std::string &filename)
+{
+ tinygltf::TinyGLTF loader;
+ std::string error_msg;
+ std::string warn_msg;
+
+ // Load a tinygltf model fom a file. Assumes that the input filename has already been
+ // been sanitized to one of (.gltf , .glb) extensions, so does a simple find to distinguish.
+ if (std::string::npos == filename.rfind(".gltf"))
+ { // file is binary
+ mGltfLoaded = loader.LoadBinaryFromFile(&mGltfModel, &error_msg, &warn_msg, filename);
+ }
+ else
+ { // file is ascii
+ mGltfLoaded = loader.LoadASCIIFromFile(&mGltfModel, &error_msg, &warn_msg, filename);
+ }
+
+ if (!mGltfLoaded)
+ {
+ if (!warn_msg.empty())
+ LL_WARNS("GLTF_IMPORT") << "gltf load warning: " << warn_msg.c_str() << LL_ENDL;
+ if (!error_msg.empty())
+ LL_WARNS("GLTF_IMPORT") << "gltf load error: " << error_msg.c_str() << LL_ENDL;
+ return false;
+ }
+
+ mMeshesLoaded = parseMeshes();
+ if (mMeshesLoaded) uploadMeshes();
+
+ mMaterialsLoaded = parseMaterials();
+ if (mMaterialsLoaded) uploadMaterials();
+
+ return (mMeshesLoaded || mMaterialsLoaded);
+}
+
+bool LLGLTFLoader::parseMeshes()
+{
+ if (!mGltfLoaded) return false;
+
+ // 2022-04 DJH Volume params from dae example. TODO understand PCODE
+ LLVolumeParams volume_params;
+ volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE);
+
+ for (tinygltf::Mesh mesh : mGltfModel.meshes)
+ {
+ LLModel *pModel = new LLModel(volume_params, 0.f);
+
+ if (populateModelFromMesh(pModel, mesh) &&
+ (LLModel::NO_ERRORS == pModel->getStatus()) &&
+ validate_model(pModel))
+ {
+ mModelList.push_back(pModel);
+ }
+ else
+ {
+ setLoadState(ERROR_MODEL + pModel->getStatus());
+ delete(pModel);
+ return false;
+ }
+ }
+ return true;
+}
+
+bool LLGLTFLoader::populateModelFromMesh(LLModel* pModel, const tinygltf::Mesh &mesh)
+{
+ pModel->mLabel = mesh.name;
+ int pos_idx, norm_idx, tan_idx, uv0_idx, uv1_idx, color0_idx, color1_idx;
+ tinygltf::Accessor indices_a, positions_a, normals_a, uv0_a, color0_a;
+
+ auto prims = mesh.primitives;
+ for (auto prim : prims)
+ {
+ if (prim.indices >= 0) indices_a = mGltfModel.accessors[prim.indices];
+
+ pos_idx = (prim.attributes.count("POSITION") > 0) ? prim.attributes.at("POSITION") : -1;
+ if (pos_idx >= 0)
+ {
+ positions_a = mGltfModel.accessors[pos_idx];
+ if (TINYGLTF_COMPONENT_TYPE_FLOAT != positions_a.componentType)
+ continue;
+ auto positions_bv = mGltfModel.bufferViews[positions_a.bufferView];
+ auto positions_buf = mGltfModel.buffers[positions_bv.buffer];
+ //auto type = positions_vb.
+ //if (positions_buf.name
+ }
+
+ norm_idx = (prim.attributes.count("NORMAL") > 0) ? prim.attributes.at("NORMAL") : -1;
+ tan_idx = (prim.attributes.count("TANGENT") > 0) ? prim.attributes.at("TANGENT") : -1;
+ uv0_idx = (prim.attributes.count("TEXCOORDS_0") > 0) ? prim.attributes.at("TEXCOORDS_0") : -1;
+ uv1_idx = (prim.attributes.count("TEXCOORDS_1") > 0) ? prim.attributes.at("TEXCOORDS_1") : -1;
+ color0_idx = (prim.attributes.count("COLOR_0") > 0) ? prim.attributes.at("COLOR_0") : -1;
+ color1_idx = (prim.attributes.count("COLOR_1") > 0) ? prim.attributes.at("COLOR_1") : -1;
+
+ if (prim.mode == TINYGLTF_MODE_TRIANGLES)
+ {
+ //auto pos = mesh. TODO resume here DJH 2022-04
+ }
+ }
+
+ //pModel->addFace()
+ return false;
+}
+
+bool LLGLTFLoader::parseMaterials()
+{
+ if (!mGltfLoaded) return false;
+
+ // fill local texture data structures
+ mSamplers.clear();
+ for (auto in_sampler : mGltfModel.samplers)
+ {
+ gltf_sampler sampler;
+ sampler.magFilter = in_sampler.magFilter > 0 ? in_sampler.magFilter : GL_LINEAR;
+ sampler.minFilter = in_sampler.minFilter > 0 ? in_sampler.minFilter : GL_LINEAR;;
+ sampler.wrapS = in_sampler.wrapS;
+ sampler.wrapT = in_sampler.wrapT;
+ sampler.name = in_sampler.name; // unused
+ mSamplers.push_back(sampler);
+ }
+
+ mImages.clear();
+ for (auto in_image : mGltfModel.images)
+ {
+ gltf_image image;
+ image.numChannels = in_image.component;
+ image.bytesPerChannel = in_image.bits >> 3; // Convert bits to bytes
+ image.pixelType = in_image.pixel_type; // Maps exactly, i.e. TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE == GL_UNSIGNED_BYTE, etc
+ image.size = in_image.image.size();
+ image.height = in_image.height;
+ image.width = in_image.width;
+ image.data = in_image.image.data();
+
+ if (in_image.as_is)
+ {
+ LL_WARNS("GLTF_IMPORT") << "Unsupported image encoding" << LL_ENDL;
+ return false;
+ }
+
+ if (image.size != image.height * image.width * image.numChannels * image.bytesPerChannel)
+ {
+ LL_WARNS("GLTF_IMPORT") << "Image size error" << LL_ENDL;
+ return false;
+ }
+
+ mImages.push_back(image);
+ }
+
+ mTextures.clear();
+ for (auto in_tex : mGltfModel.textures)
+ {
+ gltf_texture tex;
+ tex.imageIdx = in_tex.source;
+ tex.samplerIdx = in_tex.sampler;
+ tex.imageUuid.setNull();
+
+ if (tex.imageIdx >= mImages.size() || tex.samplerIdx >= mSamplers.size())
+ {
+ LL_WARNS("GLTF_IMPORT") << "Texture sampler/image index error" << LL_ENDL;
+ return false;
+ }
+
+ mTextures.push_back(tex);
+ }
+
+ // parse each material
+ for (tinygltf::Material gltf_material : mGltfModel.materials)
+ {
+ gltf_render_material mat;
+ mat.name = gltf_material.name;
+
+ tinygltf::PbrMetallicRoughness& pbr = gltf_material.pbrMetallicRoughness;
+ mat.hasPBR = true; // Always true, for now
+
+ mat.baseColor.set(pbr.baseColorFactor.data());
+ mat.hasBaseTex = pbr.baseColorTexture.index >= 0;
+ mat.baseColorTexIdx = pbr.baseColorTexture.index;
+ mat.baseColorTexCoords = pbr.baseColorTexture.texCoord;
+
+ mat.metalness = pbr.metallicFactor;
+ mat.roughness = pbr.roughnessFactor;
+ mat.hasMRTex = pbr.metallicRoughnessTexture.index >= 0;
+ mat.metalRoughTexIdx = pbr.metallicRoughnessTexture.index;
+ mat.metalRoughTexCoords = pbr.metallicRoughnessTexture.texCoord;
+
+ mat.normalScale = gltf_material.normalTexture.scale;
+ mat.hasNormalTex = gltf_material.normalTexture.index >= 0;
+ mat.normalTexIdx = gltf_material.normalTexture.index;
+ mat.normalTexCoords = gltf_material.normalTexture.texCoord;
+
+ mat.occlusionScale = gltf_material.occlusionTexture.strength;
+ mat.hasOcclusionTex = gltf_material.occlusionTexture.index >= 0;
+ mat.occlusionTexIdx = gltf_material.occlusionTexture.index;
+ mat.occlusionTexCoords = gltf_material.occlusionTexture.texCoord;
+
+ mat.emissiveColor.set(gltf_material.emissiveFactor.data());
+ mat.hasEmissiveTex = gltf_material.emissiveTexture.index >= 0;
+ mat.emissiveTexIdx = gltf_material.emissiveTexture.index;
+ mat.emissiveTexCoords = gltf_material.emissiveTexture.texCoord;
+
+ mat.alphaMode = gltf_material.alphaMode;
+ mat.alphaMask = gltf_material.alphaCutoff;
+
+ if ((mat.hasNormalTex && (mat.normalTexIdx >= mTextures.size())) ||
+ (mat.hasOcclusionTex && (mat.occlusionTexIdx >= mTextures.size())) ||
+ (mat.hasEmissiveTex && (mat.emissiveTexIdx >= mTextures.size())) ||
+ (mat.hasBaseTex && (mat.baseColorTexIdx >= mTextures.size())) ||
+ (mat.hasMRTex && (mat.metalRoughTexIdx >= mTextures.size())))
+ {
+ LL_WARNS("GLTF_IMPORT") << "Texture resource index error" << LL_ENDL;
+ return false;
+ }
+
+ if ((mat.hasNormalTex && (mat.normalTexCoords > 2)) || // mesh can have up to 3 sets of UV
+ (mat.hasOcclusionTex && (mat.occlusionTexCoords > 2)) ||
+ (mat.hasEmissiveTex && (mat.emissiveTexCoords > 2)) ||
+ (mat.hasBaseTex && (mat.baseColorTexCoords > 2)) ||
+ (mat.hasMRTex && (mat.metalRoughTexCoords > 2)))
+ {
+ LL_WARNS("GLTF_IMPORT") << "Image texcoord index error" << LL_ENDL;
+ return false;
+ }
+
+ mMaterials.push_back(mat);
+ }
+
+ return true;
+}
+
+// TODO: convert raw vertex buffers to UUIDs
+void LLGLTFLoader::uploadMeshes()
+{
+ llassert(0);
+}
+
+// convert raw image buffers to texture UUIDs & assemble into a render material
+void LLGLTFLoader::uploadMaterials()
+{
+ for (gltf_render_material mat : mMaterials) // Initially 1 material per gltf file, but design for multiple
+ {
+ if (mat.hasBaseTex)
+ {
+ gltf_texture& gtex = mTextures[mat.baseColorTexIdx];
+ if (gtex.imageUuid.isNull())
+ {
+ gtex.imageUuid = imageBufferToTextureUUID(gtex);
+ }
+ }
+
+ if (mat.hasMRTex)
+ {
+ gltf_texture& gtex = mTextures[mat.metalRoughTexIdx];
+ if (gtex.imageUuid.isNull())
+ {
+ gtex.imageUuid = imageBufferToTextureUUID(gtex);
+ }
+ }
+
+ if (mat.hasNormalTex)
+ {
+ gltf_texture& gtex = mTextures[mat.normalTexIdx];
+ if (gtex.imageUuid.isNull())
+ {
+ gtex.imageUuid = imageBufferToTextureUUID(gtex);
+ }
+ }
+
+ if (mat.hasOcclusionTex)
+ {
+ gltf_texture& gtex = mTextures[mat.occlusionTexIdx];
+ if (gtex.imageUuid.isNull())
+ {
+ gtex.imageUuid = imageBufferToTextureUUID(gtex);
+ }
+ }
+
+ if (mat.hasEmissiveTex)
+ {
+ gltf_texture& gtex = mTextures[mat.emissiveTexIdx];
+ if (gtex.imageUuid.isNull())
+ {
+ gtex.imageUuid = imageBufferToTextureUUID(gtex);
+ }
+ }
+ }
+}
+
+LLUUID LLGLTFLoader::imageBufferToTextureUUID(const gltf_texture& tex)
+{
+ //gltf_image& image = mImages[tex.imageIdx];
+ //gltf_sampler& sampler = mSamplers[tex.samplerIdx];
+
+ // fill an LLSD container with image+sampler data
+
+ // upload texture
+
+ // retrieve UUID
+
+ return LLUUID::null;
+}
diff --git a/indra/llprimitive/llgltfloader.h b/indra/llprimitive/llgltfloader.h
new file mode 100644
index 0000000000..b4d6ca1940
--- /dev/null
+++ b/indra/llprimitive/llgltfloader.h
@@ -0,0 +1,206 @@
+/**
+ * @file LLGLTFLoader.h
+ * @brief LLGLTFLoader class definition
+ *
+ * $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$
+ */
+
+#ifndef LL_LLGLTFLoader_H
+#define LL_LLGLTFLoader_H
+
+#include "tinygltf/tiny_gltf.h"
+
+#include "llglheaders.h"
+#include "llmodelloader.h"
+
+// gltf_* structs are temporary, used to organize the subset of data that eventually goes into the material LLSD
+
+class gltf_sampler
+{
+public:
+ // Uses GL enums
+ S32 minFilter; // GL_NEAREST, GL_LINEAR, GL_NEAREST_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR or GL_LINEAR_MIPMAP_LINEAR
+ S32 magFilter; // GL_NEAREST or GL_LINEAR
+ S32 wrapS; // GL_CLAMP_TO_EDGE, GL_MIRRORED_REPEAT or GL_REPEAT
+ S32 wrapT; // GL_CLAMP_TO_EDGE, GL_MIRRORED_REPEAT or GL_REPEAT
+ //S32 wrapR; // Found in some sample files, but not part of glTF 2.0 spec. Ignored.
+ std::string name; // optional, currently unused
+ // extensions and extras are sampler optional fields that we don't support - at least initially
+};
+
+class gltf_image
+{
+public:// Note that glTF images are defined with row 0 at the top (opposite of OpenGL)
+ U8* data; // ptr to decoded image data
+ U32 size; // in bytes, regardless of channel width
+ U32 width;
+ U32 height;
+ U32 numChannels; // range 1..4
+ U32 bytesPerChannel; // converted from gltf "bits", expects only 8, 16 or 32 as input
+ U32 pixelType; // one of (TINYGLTF_COMPONENT_TYPE)_UNSIGNED_BYTE, _UNSIGNED_SHORT, _UNSIGNED_INT, or _FLOAT
+};
+
+class gltf_texture
+{
+public:
+ U32 imageIdx;
+ U32 samplerIdx;
+ LLUUID imageUuid = LLUUID::null;
+};
+
+class gltf_render_material
+{
+public:
+ std::string name;
+
+ // scalar values
+ LLColor4 baseColor; // linear encoding. Multiplied with vertex color, if present.
+ double metalness;
+ double roughness;
+ double normalScale; // scale applies only to X,Y components of normal
+ double occlusionScale; // strength multiplier for occlusion
+ LLColor4 emissiveColor; // emissive mulitiplier, assumed linear encoding (spec 2.0 is silent)
+ std::string alphaMode; // "OPAQUE", "MASK" or "BLEND"
+ double alphaMask; // alpha cut-off
+
+ // textures
+ U32 baseColorTexIdx; // always sRGB encoded
+ U32 metalRoughTexIdx; // always linear, roughness in G channel, metalness in B channel
+ U32 normalTexIdx; // linear, valid range R[0-1], G[0-1], B[0.5-1]. Normal = texel * 2 - vec3(1.0)
+ U32 occlusionTexIdx; // linear, occlusion in R channel, 0 meaning fully occluded, 1 meaning not occluded
+ U32 emissiveTexIdx; // always stored as sRGB, in nits (candela / meter^2)
+
+ // texture coordinates
+ U32 baseColorTexCoords;
+ U32 metalRoughTexCoords;
+ U32 normalTexCoords;
+ U32 occlusionTexCoords;
+ U32 emissiveTexCoords;
+
+ // TODO: Add traditional (diffuse, normal, specular) UUIDs here, or add this struct to LL_TextureEntry??
+
+ bool hasPBR;
+ bool hasBaseTex, hasMRTex, hasNormalTex, hasOcclusionTex, hasEmissiveTex;
+
+ // This field is populated after upload
+ LLUUID material_uuid = LLUUID::null;
+
+};
+
+class gltf_mesh
+{
+public:
+ std::string name;
+
+ // TODO add mesh import DJH 2022-04
+
+};
+
+class LLGLTFLoader : public LLModelLoader
+{
+ public:
+ typedef std::map<std::string, LLImportMaterial> material_map;
+
+ LLGLTFLoader(std::string filename,
+ S32 lod,
+ LLModelLoader::load_callback_t load_cb,
+ LLModelLoader::joint_lookup_func_t joint_lookup_func,
+ LLModelLoader::texture_load_func_t texture_load_func,
+ LLModelLoader::state_callback_t state_cb,
+ void * opaque_userdata,
+ JointTransformMap & jointTransformMap,
+ JointNameSet & jointsFromNodes,
+ std::map<std::string, std::string> &jointAliasMap,
+ U32 maxJointsPerMesh,
+ U32 modelLimit); //,
+ //bool preprocess );
+ virtual ~LLGLTFLoader();
+
+ virtual bool OpenFile(const std::string &filename);
+
+protected:
+ tinygltf::Model mGltfModel;
+ bool mGltfLoaded;
+ bool mMeshesLoaded;
+ bool mMaterialsLoaded;
+
+ std::vector<gltf_mesh> mMeshes;
+ std::vector<gltf_render_material> mMaterials;
+
+ std::vector<gltf_texture> mTextures;
+ std::vector<gltf_image> mImages;
+ std::vector<gltf_sampler> mSamplers;
+
+private:
+ bool parseMeshes();
+ void uploadMeshes();
+ bool parseMaterials();
+ void uploadMaterials();
+ bool populateModelFromMesh(LLModel* pModel, const tinygltf::Mesh &mesh);
+ LLUUID imageBufferToTextureUUID(const gltf_texture& tex);
+
+ // bool mPreprocessGLTF;
+
+ /* Below inherited from dae loader - unknown if/how useful here
+
+ void processElement(gltfElement *element, bool &badElement, GLTF *gltf);
+ void processGltfModel(LLModel *model, GLTF *gltf, gltfElement *pRoot, gltfMesh *mesh, gltfSkin *skin);
+
+ material_map getMaterials(LLModel *model, gltfInstance_geometry *instance_geo, GLTF *gltf);
+ LLImportMaterial profileToMaterial(gltfProfile_COMMON *material, GLTF *gltf);
+ LLColor4 getGltfColor(gltfElement *element);
+
+ gltfElement *getChildFromElement(gltfElement *pElement, std::string const &name);
+
+ bool isNodeAJoint(gltfNode *pNode);
+ void processJointNode(gltfNode *pNode, std::map<std::string, LLMatrix4> &jointTransforms);
+ void extractTranslation(gltfTranslate *pTranslate, LLMatrix4 &transform);
+ void extractTranslationViaElement(gltfElement *pTranslateElement, LLMatrix4 &transform);
+ void extractTranslationViaSID(gltfElement *pElement, LLMatrix4 &transform);
+ void buildJointToNodeMappingFromScene(gltfElement *pRoot);
+ void processJointToNodeMapping(gltfNode *pNode);
+ void processChildJoints(gltfNode *pParentNode);
+
+ bool verifyCount(int expected, int result);
+
+ // Verify that a controller matches vertex counts
+ bool verifyController(gltfController *pController);
+
+ static bool addVolumeFacesFromGltfMesh(LLModel *model, gltfMesh *mesh, LLSD &log_msg);
+ static bool createVolumeFacesFromGltfMesh(LLModel *model, gltfMesh *mesh);
+
+ static LLModel *loadModelFromGltfMesh(gltfMesh *mesh);
+
+ // Loads a mesh breaking it into one or more models as necessary
+ // to get around volume face limitations while retaining >8 materials
+ //
+ bool loadModelsFromGltfMesh(gltfMesh *mesh, std::vector<LLModel *> &models_out, U32 submodel_limit);
+
+ static std::string getElementLabel(gltfElement *element);
+ static size_t getSuffixPosition(std::string label);
+ static std::string getLodlessLabel(gltfElement *element);
+
+ static std::string preprocessGLTF(std::string filename);
+ */
+
+};
+#endif // LL_LLGLTFLLOADER_H
diff --git a/indra/llprimitive/llgltfmaterial.cpp b/indra/llprimitive/llgltfmaterial.cpp
new file mode 100644
index 0000000000..a8dad89292
--- /dev/null
+++ b/indra/llprimitive/llgltfmaterial.cpp
@@ -0,0 +1,699 @@
+/**
+ * @file llgltfmaterial.cpp
+ * @brief Material definition
+ *
+ * $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$
+ */
+
+#include "linden_common.h"
+
+#include "llgltfmaterial.h"
+
+// NOTE -- this should be the one and only place tiny_gltf.h is included
+#include "tinygltf/tiny_gltf.h"
+
+const char* GLTF_FILE_EXTENSION_TRANSFORM = "KHR_texture_transform";
+const char* GLTF_FILE_EXTENSION_TRANSFORM_SCALE = "scale";
+const char* GLTF_FILE_EXTENSION_TRANSFORM_OFFSET = "offset";
+const char* GLTF_FILE_EXTENSION_TRANSFORM_ROTATION = "rotation";
+
+// special UUID that indicates a null UUID in override data
+static const LLUUID GLTF_OVERRIDE_NULL_UUID = LLUUID("ffffffff-ffff-ffff-ffff-ffffffffffff");
+
+// https://github.com/KhronosGroup/glTF/tree/main/extensions/3.0/Khronos/KHR_texture_transform
+LLMatrix3 LLGLTFMaterial::TextureTransform::asMatrix()
+{
+ LLMatrix3 scale;
+ scale.mMatrix[0][0] = mScale[0];
+ scale.mMatrix[1][1] = mScale[1];
+
+ LLMatrix3 rotation;
+ const F32 cos_r = cos(mRotation);
+ const F32 sin_r = sin(mRotation);
+ rotation.mMatrix[0][0] = cos_r;
+ rotation.mMatrix[0][1] = sin_r;
+ rotation.mMatrix[1][0] = -sin_r;
+ rotation.mMatrix[1][1] = cos_r;
+
+ LLMatrix3 offset;
+ offset.mMatrix[2][0] = mOffset[0];
+ offset.mMatrix[2][1] = mOffset[1];
+
+ return offset * rotation * scale;
+}
+
+bool LLGLTFMaterial::TextureTransform::operator==(const TextureTransform& other) const
+{
+ return mOffset == other.mOffset && mScale == other.mScale && mRotation == other.mRotation;
+}
+
+LLGLTFMaterial::LLGLTFMaterial(const LLGLTFMaterial& rhs)
+{
+ *this = rhs;
+}
+
+LLGLTFMaterial& LLGLTFMaterial::operator=(const LLGLTFMaterial& rhs)
+{
+ LL_PROFILE_ZONE_SCOPED;
+ //have to do a manual operator= because of LLRefCount
+ mBaseColorId = rhs.mBaseColorId;
+ mNormalId = rhs.mNormalId;
+ mMetallicRoughnessId = rhs.mMetallicRoughnessId;
+ mEmissiveId = rhs.mEmissiveId;
+
+ mBaseColor = rhs.mBaseColor;
+ mEmissiveColor = rhs.mEmissiveColor;
+
+ mMetallicFactor = rhs.mMetallicFactor;
+ mRoughnessFactor = rhs.mRoughnessFactor;
+ mAlphaCutoff = rhs.mAlphaCutoff;
+
+ mDoubleSided = rhs.mDoubleSided;
+ mAlphaMode = rhs.mAlphaMode;
+
+ mTextureTransform = rhs.mTextureTransform;
+
+ mOverrideDoubleSided = rhs.mOverrideDoubleSided;
+ mOverrideAlphaMode = rhs.mOverrideAlphaMode;
+
+ return *this;
+}
+
+bool LLGLTFMaterial::operator==(const LLGLTFMaterial& rhs) const
+{
+ return mBaseColorId == rhs.mBaseColorId &&
+ mNormalId == rhs.mNormalId &&
+ mMetallicRoughnessId == rhs.mMetallicRoughnessId &&
+ mEmissiveId == rhs.mEmissiveId &&
+
+ mBaseColor == rhs.mBaseColor &&
+ mEmissiveColor == rhs.mEmissiveColor &&
+
+ mMetallicFactor == rhs.mMetallicFactor &&
+ mRoughnessFactor == rhs.mRoughnessFactor &&
+ mAlphaCutoff == rhs.mAlphaCutoff &&
+
+ mDoubleSided == rhs.mDoubleSided &&
+ mAlphaMode == rhs.mAlphaMode &&
+
+ mTextureTransform == rhs.mTextureTransform &&
+
+ mOverrideDoubleSided == rhs.mOverrideDoubleSided &&
+ mOverrideAlphaMode == rhs.mOverrideAlphaMode;
+}
+
+bool LLGLTFMaterial::fromJSON(const std::string& json, std::string& warn_msg, std::string& error_msg)
+{
+ LL_PROFILE_ZONE_SCOPED;
+ tinygltf::TinyGLTF gltf;
+
+ tinygltf::Model model_in;
+
+ if (gltf.LoadASCIIFromString(&model_in, &error_msg, &warn_msg, json.c_str(), json.length(), ""))
+ {
+ setFromModel(model_in, 0);
+
+ return true;
+ }
+ return false;
+}
+
+std::string LLGLTFMaterial::asJSON(bool prettyprint) const
+{
+ LL_PROFILE_ZONE_SCOPED;
+ tinygltf::TinyGLTF gltf;
+
+ tinygltf::Model model_out;
+
+ std::ostringstream str;
+
+ writeToModel(model_out, 0);
+
+ gltf.WriteGltfSceneToStream(&model_out, str, prettyprint, false);
+
+ return str.str();
+}
+
+void LLGLTFMaterial::setFromModel(const tinygltf::Model& model, S32 mat_index)
+{
+ LL_PROFILE_ZONE_SCOPED;
+ if (model.materials.size() <= mat_index)
+ {
+ return;
+ }
+
+ const tinygltf::Material& material_in = model.materials[mat_index];
+
+ // Apply base color texture
+ setFromTexture(model, material_in.pbrMetallicRoughness.baseColorTexture, GLTF_TEXTURE_INFO_BASE_COLOR, mBaseColorId);
+ // Apply normal map
+ setFromTexture(model, material_in.normalTexture, GLTF_TEXTURE_INFO_NORMAL, mNormalId);
+ // Apply metallic-roughness texture
+ setFromTexture(model, material_in.pbrMetallicRoughness.metallicRoughnessTexture, GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS, mMetallicRoughnessId);
+ // Apply emissive texture
+ setFromTexture(model, material_in.emissiveTexture, GLTF_TEXTURE_INFO_EMISSIVE, mEmissiveId);
+
+ setAlphaMode(material_in.alphaMode);
+ mAlphaCutoff = llclamp((F32)material_in.alphaCutoff, 0.f, 1.f);
+
+ mBaseColor.set(material_in.pbrMetallicRoughness.baseColorFactor);
+ mEmissiveColor.set(material_in.emissiveFactor);
+
+ mMetallicFactor = llclamp((F32)material_in.pbrMetallicRoughness.metallicFactor, 0.f, 1.f);
+ mRoughnessFactor = llclamp((F32)material_in.pbrMetallicRoughness.roughnessFactor, 0.f, 1.f);
+
+ mDoubleSided = material_in.doubleSided;
+
+ if (material_in.extras.IsObject())
+ {
+ tinygltf::Value::Object extras = material_in.extras.Get<tinygltf::Value::Object>();
+ const auto& alpha_mode = extras.find("override_alpha_mode");
+ if (alpha_mode != extras.end())
+ {
+ mOverrideAlphaMode = alpha_mode->second.Get<bool>();
+ }
+
+ const auto& double_sided = extras.find("override_double_sided");
+ if (double_sided != extras.end())
+ {
+ mOverrideDoubleSided = double_sided->second.Get<bool>();
+ }
+ }
+}
+
+LLVector2 vec2_from_json(const tinygltf::Value::Object& object, const char* key, const LLVector2& default_value)
+{
+ const auto it = object.find(key);
+ if (it == object.end())
+ {
+ return default_value;
+ }
+ const tinygltf::Value& vec2_json = std::get<1>(*it);
+ if (!vec2_json.IsArray() || vec2_json.ArrayLen() < LENGTHOFVECTOR2)
+ {
+ return default_value;
+ }
+ LLVector2 value;
+ for (U32 i = 0; i < LENGTHOFVECTOR2; ++i)
+ {
+ const tinygltf::Value& real_json = vec2_json.Get(i);
+ if (!real_json.IsReal())
+ {
+ return default_value;
+ }
+ value.mV[i] = (F32)real_json.Get<double>();
+ }
+ return value;
+}
+
+F32 float_from_json(const tinygltf::Value::Object& object, const char* key, const F32 default_value)
+{
+ const auto it = object.find(key);
+ if (it == object.end())
+ {
+ return default_value;
+ }
+ const tinygltf::Value& real_json = std::get<1>(*it);
+ if (!real_json.IsReal())
+ {
+ return default_value;
+ }
+ return (F32)real_json.GetNumberAsDouble();
+}
+
+template<typename T>
+std::string gltf_get_texture_image(const tinygltf::Model& model, const T& texture_info)
+{
+ const S32 texture_idx = texture_info.index;
+ if (texture_idx < 0 || texture_idx >= model.textures.size())
+ {
+ return "";
+ }
+ const tinygltf::Texture& texture = model.textures[texture_idx];
+
+ // Ignore texture.sampler for now
+
+ const S32 image_idx = texture.source;
+ if (image_idx < 0 || image_idx >= model.images.size())
+ {
+ return "";
+ }
+ const tinygltf::Image& image = model.images[image_idx];
+
+ return image.uri;
+}
+
+// *NOTE: Use template here as workaround for the different similar texture info classes
+template<typename T>
+void LLGLTFMaterial::setFromTexture(const tinygltf::Model& model, const T& texture_info, TextureInfo texture_info_id, LLUUID& texture_id_out)
+{
+ LL_PROFILE_ZONE_SCOPED;
+ const std::string uri = gltf_get_texture_image(model, texture_info);
+ texture_id_out.set(uri);
+
+ const tinygltf::Value::Object& extensions_object = texture_info.extensions;
+ const auto transform_it = extensions_object.find(GLTF_FILE_EXTENSION_TRANSFORM);
+ if (transform_it != extensions_object.end())
+ {
+ const tinygltf::Value& transform_json = std::get<1>(*transform_it);
+ if (transform_json.IsObject())
+ {
+ const tinygltf::Value::Object& transform_object = transform_json.Get<tinygltf::Value::Object>();
+ TextureTransform& transform = mTextureTransform[texture_info_id];
+ transform.mOffset = vec2_from_json(transform_object, GLTF_FILE_EXTENSION_TRANSFORM_OFFSET, getDefaultTextureOffset());
+ transform.mScale = vec2_from_json(transform_object, GLTF_FILE_EXTENSION_TRANSFORM_SCALE, getDefaultTextureScale());
+ transform.mRotation = float_from_json(transform_object, GLTF_FILE_EXTENSION_TRANSFORM_ROTATION, getDefaultTextureRotation());
+ }
+ }
+}
+
+void LLGLTFMaterial::writeToModel(tinygltf::Model& model, S32 mat_index) const
+{
+ LL_PROFILE_ZONE_SCOPED;
+ if (model.materials.size() < mat_index+1)
+ {
+ model.materials.resize(mat_index + 1);
+ }
+
+ tinygltf::Material& material_out = model.materials[mat_index];
+
+ // set base color texture
+ writeToTexture(model, material_out.pbrMetallicRoughness.baseColorTexture, GLTF_TEXTURE_INFO_BASE_COLOR, mBaseColorId);
+ // set normal texture
+ writeToTexture(model, material_out.normalTexture, GLTF_TEXTURE_INFO_NORMAL, mNormalId);
+ // set metallic-roughness texture
+ writeToTexture(model, material_out.pbrMetallicRoughness.metallicRoughnessTexture, GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS, mMetallicRoughnessId);
+ // set emissive texture
+ writeToTexture(model, material_out.emissiveTexture, GLTF_TEXTURE_INFO_EMISSIVE, mEmissiveId);
+
+ material_out.alphaMode = getAlphaMode();
+ material_out.alphaCutoff = mAlphaCutoff;
+
+ mBaseColor.write(material_out.pbrMetallicRoughness.baseColorFactor);
+
+ material_out.emissiveFactor.resize(3); // 0 size by default
+
+ if (mEmissiveColor != LLGLTFMaterial::getDefaultEmissiveColor())
+ {
+ material_out.emissiveFactor.resize(3);
+ mEmissiveColor.write(material_out.emissiveFactor);
+ }
+
+ material_out.pbrMetallicRoughness.metallicFactor = mMetallicFactor;
+ material_out.pbrMetallicRoughness.roughnessFactor = mRoughnessFactor;
+
+ material_out.doubleSided = mDoubleSided;
+
+
+ // generate "extras" string
+ tinygltf::Value::Object extras;
+ bool write_extras = false;
+ if (mOverrideAlphaMode && mAlphaMode == getDefaultAlphaMode())
+ {
+ extras["override_alpha_mode"] = tinygltf::Value(mOverrideAlphaMode);
+ write_extras = true;
+ }
+
+ if (mOverrideDoubleSided && mDoubleSided == getDefaultDoubleSided())
+ {
+ extras["override_double_sided"] = tinygltf::Value(mOverrideDoubleSided);
+ write_extras = true;
+ }
+
+ if (write_extras)
+ {
+ material_out.extras = tinygltf::Value(extras);
+ }
+
+ model.asset.version = "2.0";
+}
+
+template<typename T>
+void gltf_allocate_texture_image(tinygltf::Model& model, T& texture_info, const std::string& uri)
+{
+ const S32 image_idx = model.images.size();
+ model.images.emplace_back();
+ model.images[image_idx].uri = uri;
+
+ // The texture, not to be confused with the texture info
+ const S32 texture_idx = model.textures.size();
+ model.textures.emplace_back();
+ tinygltf::Texture& texture = model.textures[texture_idx];
+ texture.source = image_idx;
+
+ texture_info.index = texture_idx;
+}
+
+template<typename T>
+void LLGLTFMaterial::writeToTexture(tinygltf::Model& model, T& texture_info, TextureInfo texture_info_id, const LLUUID& texture_id) const
+{
+ LL_PROFILE_ZONE_SCOPED;
+ const TextureTransform& transform = mTextureTransform[texture_info_id];
+ if (texture_id.isNull() && transform == sDefault.mTextureTransform[0])
+ {
+ return;
+ }
+
+ gltf_allocate_texture_image(model, texture_info, texture_id.asString());
+
+ tinygltf::Value::Object transform_map;
+ transform_map[GLTF_FILE_EXTENSION_TRANSFORM_OFFSET] = tinygltf::Value(tinygltf::Value::Array({
+ tinygltf::Value(transform.mOffset.mV[VX]),
+ tinygltf::Value(transform.mOffset.mV[VY])
+ }));
+ transform_map[GLTF_FILE_EXTENSION_TRANSFORM_SCALE] = tinygltf::Value(tinygltf::Value::Array({
+ tinygltf::Value(transform.mScale.mV[VX]),
+ tinygltf::Value(transform.mScale.mV[VY])
+ }));
+ transform_map[GLTF_FILE_EXTENSION_TRANSFORM_ROTATION] = tinygltf::Value(transform.mRotation);
+ texture_info.extensions[GLTF_FILE_EXTENSION_TRANSFORM] = tinygltf::Value(transform_map);
+}
+
+bool LLGLTFMaterial::setBaseMaterial()
+{
+ const LLGLTFMaterial old_override = *this;
+ *this = sDefault;
+ setBaseMaterial(old_override);
+ return *this != old_override;
+}
+
+bool LLGLTFMaterial::isClearedForBaseMaterial()
+{
+ LLGLTFMaterial cleared_override = sDefault;
+ cleared_override.setBaseMaterial(*this);
+ return *this == cleared_override;
+}
+
+// For material overrides only. Copies transforms from the old override.
+void LLGLTFMaterial::setBaseMaterial(const LLGLTFMaterial& old_override_mat)
+{
+ mTextureTransform = old_override_mat.mTextureTransform;
+}
+
+
+// static
+void LLGLTFMaterial::hackOverrideUUID(LLUUID& id)
+{
+ if (id == LLUUID::null)
+ {
+ id = GLTF_OVERRIDE_NULL_UUID;
+ }
+}
+
+void LLGLTFMaterial::setBaseColorId(const LLUUID& id, bool for_override)
+{
+ mBaseColorId = id;
+ if (for_override)
+ {
+ hackOverrideUUID(mBaseColorId);
+ }
+}
+
+void LLGLTFMaterial::setNormalId(const LLUUID& id, bool for_override)
+{
+ mNormalId = id;
+ if (for_override)
+ {
+ hackOverrideUUID(mNormalId);
+ }
+}
+
+void LLGLTFMaterial::setMetallicRoughnessId(const LLUUID& id, bool for_override)
+{
+ mMetallicRoughnessId = id;
+ if (for_override)
+ {
+ hackOverrideUUID(mMetallicRoughnessId);
+ }
+}
+
+void LLGLTFMaterial::setEmissiveId(const LLUUID& id, bool for_override)
+{
+ mEmissiveId = id;
+ if (for_override)
+ {
+ hackOverrideUUID(mEmissiveId);
+ }
+}
+
+void LLGLTFMaterial::setBaseColorFactor(const LLColor4& baseColor, bool for_override)
+{
+ mBaseColor.set(baseColor);
+ mBaseColor.clamp();
+
+ if (for_override)
+ { // hack -- nudge off of default value
+ if (mBaseColor == getDefaultBaseColor())
+ {
+ mBaseColor.mV[3] -= FLT_EPSILON;
+ }
+ }
+}
+
+void LLGLTFMaterial::setAlphaCutoff(F32 cutoff, bool for_override)
+{
+ mAlphaCutoff = llclamp(cutoff, 0.f, 1.f);
+ if (for_override)
+ { // hack -- nudge off of default value
+ if (mAlphaCutoff == getDefaultAlphaCutoff())
+ {
+ mAlphaCutoff -= FLT_EPSILON;
+ }
+ }
+}
+
+void LLGLTFMaterial::setEmissiveColorFactor(const LLColor3& emissiveColor, bool for_override)
+{
+ mEmissiveColor = emissiveColor;
+ mEmissiveColor.clamp();
+
+ if (for_override)
+ { // hack -- nudge off of default value
+ if (mEmissiveColor == getDefaultEmissiveColor())
+ {
+ mEmissiveColor.mV[0] += FLT_EPSILON;
+ }
+ }
+}
+
+void LLGLTFMaterial::setMetallicFactor(F32 metallic, bool for_override)
+{
+ mMetallicFactor = llclamp(metallic, 0.f, for_override ? 1.f - FLT_EPSILON : 1.f);
+}
+
+void LLGLTFMaterial::setRoughnessFactor(F32 roughness, bool for_override)
+{
+ mRoughnessFactor = llclamp(roughness, 0.f, for_override ? 1.f - FLT_EPSILON : 1.f);
+}
+
+void LLGLTFMaterial::setAlphaMode(const std::string& mode, bool for_override)
+{
+ S32 m = getDefaultAlphaMode();
+ if (mode == "MASK")
+ {
+ m = ALPHA_MODE_MASK;
+ }
+ else if (mode == "BLEND")
+ {
+ m = ALPHA_MODE_BLEND;
+ }
+
+ setAlphaMode(m, for_override);
+}
+
+const char* LLGLTFMaterial::getAlphaMode() const
+{
+ switch (mAlphaMode)
+ {
+ case ALPHA_MODE_MASK: return "MASK";
+ case ALPHA_MODE_BLEND: return "BLEND";
+ default: return "OPAQUE";
+ }
+}
+
+void LLGLTFMaterial::setAlphaMode(S32 mode, bool for_override)
+{
+ mAlphaMode = (AlphaMode) llclamp(mode, (S32) ALPHA_MODE_OPAQUE, (S32) ALPHA_MODE_MASK);
+ if (for_override)
+ {
+ mOverrideAlphaMode = true;
+ }
+}
+
+void LLGLTFMaterial::setDoubleSided(bool double_sided, bool for_override)
+{
+ // sure, no clamping will ever be needed for a bool, but include the
+ // setter for consistency with the clamping API
+ mDoubleSided = double_sided;
+ if (for_override)
+ {
+ mOverrideDoubleSided = true;
+ }
+}
+
+void LLGLTFMaterial::setTextureOffset(TextureInfo texture_info, const LLVector2& offset)
+{
+ mTextureTransform[texture_info].mOffset = offset;
+}
+
+void LLGLTFMaterial::setTextureScale(TextureInfo texture_info, const LLVector2& scale)
+{
+ mTextureTransform[texture_info].mScale = scale;
+}
+
+void LLGLTFMaterial::setTextureRotation(TextureInfo texture_info, float rotation)
+{
+ mTextureTransform[texture_info].mRotation = rotation;
+}
+
+// Default value accessors (NOTE: these MUST match the GLTF specification)
+
+// Make a static default material for accessors
+const LLGLTFMaterial LLGLTFMaterial::sDefault;
+
+F32 LLGLTFMaterial::getDefaultAlphaCutoff()
+{
+ return sDefault.mAlphaCutoff;
+}
+
+S32 LLGLTFMaterial::getDefaultAlphaMode()
+{
+ return (S32) sDefault.mAlphaMode;
+}
+
+F32 LLGLTFMaterial::getDefaultMetallicFactor()
+{
+ return sDefault.mMetallicFactor;
+}
+
+F32 LLGLTFMaterial::getDefaultRoughnessFactor()
+{
+ return sDefault.mRoughnessFactor;
+}
+
+LLColor4 LLGLTFMaterial::getDefaultBaseColor()
+{
+ return sDefault.mBaseColor;
+}
+
+LLColor3 LLGLTFMaterial::getDefaultEmissiveColor()
+{
+ return sDefault.mEmissiveColor;
+}
+
+bool LLGLTFMaterial::getDefaultDoubleSided()
+{
+ return sDefault.mDoubleSided;
+}
+
+LLVector2 LLGLTFMaterial::getDefaultTextureOffset()
+{
+ return sDefault.mTextureTransform[0].mOffset;
+}
+
+LLVector2 LLGLTFMaterial::getDefaultTextureScale()
+{
+ return sDefault.mTextureTransform[0].mScale;
+}
+
+F32 LLGLTFMaterial::getDefaultTextureRotation()
+{
+ return sDefault.mTextureTransform[0].mRotation;
+}
+
+// static
+void LLGLTFMaterial::applyOverrideUUID(LLUUID& dst_id, const LLUUID& override_id)
+{
+ if (override_id != GLTF_OVERRIDE_NULL_UUID)
+ {
+ if (override_id != LLUUID::null)
+ {
+ dst_id = override_id;
+ }
+ }
+ else
+ {
+ dst_id = LLUUID::null;
+ }
+}
+
+void LLGLTFMaterial::applyOverride(const LLGLTFMaterial& override_mat)
+{
+ LL_PROFILE_ZONE_SCOPED;
+
+ applyOverrideUUID(mBaseColorId, override_mat.mBaseColorId);
+ applyOverrideUUID(mNormalId, override_mat.mNormalId);
+ applyOverrideUUID(mMetallicRoughnessId, override_mat.mMetallicRoughnessId);
+ applyOverrideUUID(mEmissiveId, override_mat.mEmissiveId);
+
+ if (override_mat.mBaseColor != getDefaultBaseColor())
+ {
+ mBaseColor = override_mat.mBaseColor;
+ }
+
+ if (override_mat.mEmissiveColor != getDefaultEmissiveColor())
+ {
+ mEmissiveColor = override_mat.mEmissiveColor;
+ }
+
+ if (override_mat.mMetallicFactor != getDefaultMetallicFactor())
+ {
+ mMetallicFactor = override_mat.mMetallicFactor;
+ }
+
+ if (override_mat.mRoughnessFactor != getDefaultRoughnessFactor())
+ {
+ mRoughnessFactor = override_mat.mRoughnessFactor;
+ }
+
+ if (override_mat.mAlphaMode != getDefaultAlphaMode() || override_mat.mOverrideAlphaMode)
+ {
+ mAlphaMode = override_mat.mAlphaMode;
+ }
+ if (override_mat.mAlphaCutoff != getDefaultAlphaCutoff())
+ {
+ mAlphaCutoff = override_mat.mAlphaCutoff;
+ }
+
+ if (override_mat.mDoubleSided != getDefaultDoubleSided() || override_mat.mOverrideDoubleSided)
+ {
+ mDoubleSided = override_mat.mDoubleSided;
+ }
+
+ for (int i = 0; i < GLTF_TEXTURE_INFO_COUNT; ++i)
+ {
+ if (override_mat.mTextureTransform[i].mOffset != getDefaultTextureOffset())
+ {
+ mTextureTransform[i].mOffset = override_mat.mTextureTransform[i].mOffset;
+ }
+
+ if (override_mat.mTextureTransform[i].mScale != getDefaultTextureScale())
+ {
+ mTextureTransform[i].mScale = override_mat.mTextureTransform[i].mScale;
+ }
+
+ if (override_mat.mTextureTransform[i].mRotation != getDefaultTextureRotation())
+ {
+ mTextureTransform[i].mRotation = override_mat.mTextureTransform[i].mRotation;
+ }
+ }
+}
diff --git a/indra/llprimitive/llgltfmaterial.h b/indra/llprimitive/llgltfmaterial.h
new file mode 100644
index 0000000000..dec7b696f8
--- /dev/null
+++ b/indra/llprimitive/llgltfmaterial.h
@@ -0,0 +1,201 @@
+/**
+ * @file llgltfmaterial.h
+ * @brief Material definition
+ *
+ * $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$
+ */
+
+#pragma once
+
+#include "llrefcount.h"
+#include "llmemory.h"
+#include "m3math.h"
+#include "v4color.h"
+#include "v3color.h"
+#include "v2math.h"
+#include "lluuid.h"
+#include "llmd5.h"
+
+#include <string>
+
+namespace tinygltf
+{
+ class Model;
+}
+
+class LLGLTFMaterial : public LLRefCount
+{
+public:
+
+ // default material for reference
+ static const LLGLTFMaterial sDefault;
+
+ struct TextureTransform
+ {
+ LLVector2 mOffset = { 0.f, 0.f };
+ LLVector2 mScale = { 1.f, 1.f };
+ F32 mRotation = 0.f;
+
+ LLMatrix3 asMatrix();
+
+ bool operator==(const TextureTransform& other) const;
+ };
+
+ enum AlphaMode
+ {
+ ALPHA_MODE_OPAQUE = 0,
+ ALPHA_MODE_BLEND,
+ ALPHA_MODE_MASK
+ };
+
+ LLGLTFMaterial() {}
+ LLGLTFMaterial(const LLGLTFMaterial& rhs);
+
+ LLGLTFMaterial& operator=(const LLGLTFMaterial& rhs);
+ bool operator==(const LLGLTFMaterial& rhs) const;
+ bool operator!=(const LLGLTFMaterial& rhs) const { return !(*this == rhs); }
+
+ LLUUID mBaseColorId;
+ LLUUID mNormalId;
+ LLUUID mMetallicRoughnessId;
+ LLUUID mEmissiveId;
+
+ // NOTE : initialize values to defaults according to the GLTF spec
+ LLColor4 mBaseColor = LLColor4(1, 1, 1, 1);
+ LLColor3 mEmissiveColor = LLColor3(0, 0, 0);
+
+ F32 mMetallicFactor = 1.f;
+ F32 mRoughnessFactor = 1.f;
+ F32 mAlphaCutoff = 0.5f;
+
+ bool mDoubleSided = false;
+ AlphaMode mAlphaMode = ALPHA_MODE_OPAQUE;
+
+ // override specific flags for state that can't use off-by-epsilon or UUID hack
+ bool mOverrideDoubleSided = false;
+ bool mOverrideAlphaMode = false;
+
+ // get a UUID based on a hash of this LLGLTFMaterial
+ LLUUID getHash() const
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
+ LLMD5 md5;
+ md5.update((unsigned char*)this, sizeof(this));
+ md5.finalize();
+ LLUUID id;
+ md5.raw_digest(id.mData);
+ return id;
+ }
+
+ enum TextureInfo : U32
+ {
+ GLTF_TEXTURE_INFO_BASE_COLOR,
+ GLTF_TEXTURE_INFO_NORMAL,
+ GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS,
+ GLTF_TEXTURE_INFO_EMISSIVE,
+
+ GLTF_TEXTURE_INFO_COUNT
+ };
+
+ std::array<TextureTransform, GLTF_TEXTURE_INFO_COUNT> mTextureTransform;
+
+ //setters for various members (will clamp to acceptable ranges)
+ // for_override - set to true if this value is being set as part of an override (important for handling override to default value)
+
+ void setBaseColorId(const LLUUID& id, bool for_override = false);
+ void setNormalId(const LLUUID& id, bool for_override = false);
+ void setMetallicRoughnessId(const LLUUID& id, bool for_override = false);
+ void setEmissiveId(const LLUUID& id, bool for_override = false);
+
+ void setBaseColorFactor(const LLColor4& baseColor, bool for_override = false);
+ void setAlphaCutoff(F32 cutoff, bool for_override = false);
+ void setEmissiveColorFactor(const LLColor3& emissiveColor, bool for_override = false);
+ void setMetallicFactor(F32 metallic, bool for_override = false);
+ void setRoughnessFactor(F32 roughness, bool for_override = false);
+ void setAlphaMode(S32 mode, bool for_override = false);
+ void setDoubleSided(bool double_sided, bool for_override = false);
+
+ //NOTE: texture offsets only exist in overrides, so "for_override" is not needed
+
+ void setTextureOffset(TextureInfo texture_info, const LLVector2& offset);
+ void setTextureScale(TextureInfo texture_info, const LLVector2& scale);
+ void setTextureRotation(TextureInfo texture_info, float rotation);
+
+ // Default value accessors
+ static F32 getDefaultAlphaCutoff();
+ static S32 getDefaultAlphaMode();
+ static F32 getDefaultMetallicFactor();
+ static F32 getDefaultRoughnessFactor();
+ static LLColor4 getDefaultBaseColor();
+ static LLColor3 getDefaultEmissiveColor();
+ static bool getDefaultDoubleSided();
+ static LLVector2 getDefaultTextureOffset();
+ static LLVector2 getDefaultTextureScale();
+ static F32 getDefaultTextureRotation();
+
+
+ static void hackOverrideUUID(LLUUID& id);
+ static void applyOverrideUUID(LLUUID& dst_id, const LLUUID& override_id);
+
+ // set mAlphaMode from string.
+ // Anything otherthan "MASK" or "BLEND" sets mAlphaMode to ALPHA_MODE_OPAQUE
+ void setAlphaMode(const std::string& mode, bool for_override = false);
+
+ const char* getAlphaMode() const;
+
+ // set the contents of this LLGLTFMaterial from the given json
+ // returns true if successful
+ // json - the json text to load from
+ // warn_msg - warning message from TinyGLTF if any
+ // error_msg - error_msg from TinyGLTF if any
+ bool fromJSON(const std::string& json, std::string& warn_msg, std::string& error_msg);
+
+ // get the contents of this LLGLTFMaterial as a json string
+ std::string asJSON(bool prettyprint = false) const;
+
+ // initialize from given tinygltf::Model
+ // model - the model to reference
+ // mat_index - index of material in model's material array
+ void setFromModel(const tinygltf::Model& model, S32 mat_index);
+
+ // write to given tinygltf::Model
+ void writeToModel(tinygltf::Model& model, S32 mat_index) const;
+
+ void applyOverride(const LLGLTFMaterial& override_mat);
+
+ // For material overrides only. Clears most properties to
+ // default/fallthrough, but preserves the transforms.
+ bool setBaseMaterial();
+ // True if setBaseMaterial() was just called
+ bool isClearedForBaseMaterial();
+
+private:
+
+ template<typename T>
+ void setFromTexture(const tinygltf::Model& model, const T& texture_info, TextureInfo texture_info_id, LLUUID& texture_id_out);
+
+ template<typename T>
+ void writeToTexture(tinygltf::Model& model, T& texture_info, TextureInfo texture_info_id, const LLUUID& texture_id) const;
+
+ void setBaseMaterial(const LLGLTFMaterial& old_override_mat);
+};
+
diff --git a/indra/llprimitive/llmaterial.cpp b/indra/llprimitive/llmaterial.cpp
index a219ac1450..0ab97a0df3 100644
--- a/indra/llprimitive/llmaterial.cpp
+++ b/indra/llprimitive/llmaterial.cpp
@@ -27,6 +27,7 @@
#include "linden_common.h"
#include "llmaterial.h"
+#include "llmd5.h"
/**
* Materials cap parameters
@@ -331,6 +332,17 @@ void LLMaterial::setAlphaMaskCutoff(U8 cutoff)
mAlphaMaskCutoff = cutoff;
}
+LLUUID LLMaterial::getMaterialID() const
+{
+ // TODO - not null
+ return LLUUID::null;
+}
+
+void LLMaterial::setMaterialID(const LLUUID &material_id)
+{
+ // TODO - set
+}
+
LLSD LLMaterial::asLLSD() const
{
LLSD material_data;
@@ -464,4 +476,16 @@ U32 LLMaterial::getShaderMask(U32 alpha_mode)
return ret;
}
+LLUUID LLMaterial::getHash() const
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
+ LLMD5 md5;
+ // HACK - hash the bytes of this LLMaterial, but trim off the S32 in LLRefCount
+ md5.update((unsigned char*)this + sizeof(S32), sizeof(this) - sizeof(S32));
+ md5.finalize();
+ LLUUID id;
+ md5.raw_digest(id.mData);
+ // *TODO: Hash the overrides
+ return id;
+}
diff --git a/indra/llprimitive/llmaterial.h b/indra/llprimitive/llmaterial.h
index d58b7ee812..d715671ae1 100644
--- a/indra/llprimitive/llmaterial.h
+++ b/indra/llprimitive/llmaterial.h
@@ -27,8 +27,6 @@
#ifndef LL_LLMATERIAL_H
#define LL_LLMATERIAL_H
-#include <boost/shared_ptr.hpp>
-
#include "llmaterialid.h"
#include "llsd.h"
#include "v4coloru.h"
@@ -54,8 +52,6 @@ public:
ALPHA_SHADER_COUNT = 4
} eShaderCount;
-
-
static const U8 DEFAULT_SPECULAR_LIGHT_EXPONENT = ((U8)(0.2f * 255));
static const LLColor4U DEFAULT_SPECULAR_LIGHT_COLOR;
static const U8 DEFAULT_ENV_INTENSITY = 0;
@@ -119,6 +115,8 @@ public:
void setDiffuseAlphaMode(U8 alpha_mode);
U8 getAlphaMaskCutoff() const;
void setAlphaMaskCutoff(U8 cutoff);
+ LLUUID getMaterialID() const;
+ void setMaterialID(LLUUID const & material_id);
bool isNull() const;
static const LLMaterial null;
@@ -127,6 +125,7 @@ public:
bool operator != (const LLMaterial& rhs) const;
U32 getShaderMask(U32 alpha_mode = DIFFUSE_ALPHA_MODE_DEFAULT);
+ LLUUID getHash() const;
protected:
LLUUID mNormalID;
diff --git a/indra/llprimitive/llmaterialid.cpp b/indra/llprimitive/llmaterialid.cpp
index f88a607c4f..340a83801c 100644
--- a/indra/llprimitive/llmaterialid.cpp
+++ b/indra/llprimitive/llmaterialid.cpp
@@ -155,6 +155,13 @@ std::string LLMaterialID::asString() const
return materialIDString;
}
+LLUUID LLMaterialID::asUUID() const
+{
+ LLUUID ret;
+ memcpy(ret.mData, mID, MATERIAL_ID_SIZE);
+ return ret;
+}
+
std::ostream& operator<<(std::ostream& s, const LLMaterialID &material_id)
{
s << material_id.asString();
diff --git a/indra/llprimitive/llmaterialid.h b/indra/llprimitive/llmaterialid.h
index ee663f8f99..e6165dfc91 100644
--- a/indra/llprimitive/llmaterialid.h
+++ b/indra/llprimitive/llmaterialid.h
@@ -61,6 +61,7 @@ public:
LLSD asLLSD() const;
std::string asString() const;
+ LLUUID asUUID() const;
friend std::ostream& operator<<(std::ostream& s, const LLMaterialID &material_id);
diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp
index 765a8cda22..dba4bee6e2 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 <zlib.h>
@@ -53,7 +53,6 @@ const int MODEL_NAMES_LENGTH = sizeof(model_names) / sizeof(std::string);
LLModel::LLModel(LLVolumeParams& params, F32 detail)
: LLVolume(params, detail),
mNormalizedScale(1,1,1),
- mNormalizedTranslation(0,0,0),
mPelvisOffset( 0.0f ),
mStatus(NO_ERRORS),
mSubmodelID(0)
@@ -296,6 +295,7 @@ void LLModel::normalizeVolumeFaces()
// the positions to fit within the unit cube.
LLVector4a* pos = (LLVector4a*) face.mPositions;
LLVector4a* norm = (LLVector4a*) face.mNormals;
+ LLVector4a* t = (LLVector4a*)face.mTangents;
for (U32 j = 0; j < face.mNumVertices; ++j)
{
@@ -306,6 +306,14 @@ void LLModel::normalizeVolumeFaces()
norm[j].mul(inv_scale);
norm[j].normalize3();
}
+
+ if (t)
+ {
+ F32 w = t[j].getF32ptr()[3];
+ t[j].mul(inv_scale);
+ t[j].normalize3();
+ t[j].getF32ptr()[3] = w;
+ }
}
}
@@ -319,6 +327,12 @@ void LLModel::normalizeVolumeFaces()
mNormalizedScale.set(normalized_scale.getF32ptr());
mNormalizedTranslation.set(trans.getF32ptr());
mNormalizedTranslation *= -1.f;
+
+ // remember normalized scale so original dimensions can be recovered for mesh processing (i.e. tangent generation)
+ for (auto& face : mVolumeFaces)
+ {
+ face.mNormalizedScale = mNormalizedScale;
+ }
}
}
@@ -728,10 +742,12 @@ LLSD LLModel::writeModel(
LLSD::Binary verts(face.mNumVertices*3*2);
LLSD::Binary tc(face.mNumVertices*2*2);
LLSD::Binary normals(face.mNumVertices*3*2);
+ LLSD::Binary tangents(face.mNumVertices * 4 * 2);
LLSD::Binary indices(face.mNumIndices*2);
U32 vert_idx = 0;
U32 norm_idx = 0;
+ //U32 tan_idx = 0;
U32 tc_idx = 0;
LLVector2* ftc = (LLVector2*) face.mTexCoords;
@@ -784,6 +800,24 @@ LLSD LLModel::writeModel(
normals[norm_idx++] = buff[1];
}
}
+
+#if 0 // keep this code for now in case we want to support transporting tangents with mesh assets
+ if (face.mTangents)
+ { //normals
+ F32* tangent = face.mTangents[j].getF32ptr();
+
+ for (U32 k = 0; k < 4; ++k)
+ { //for each component
+ //convert to 16-bit normalized
+ U16 val = (U16)((tangent[k] + 1.f) * 0.5f * 65535);
+ U8* buff = (U8*)&val;
+
+ //write to binary buffer
+ tangents[tan_idx++] = buff[0];
+ tangents[tan_idx++] = buff[1];
+ }
+ }
+#endif
//texcoord
if (face.mTexCoords)
@@ -814,6 +848,8 @@ LLSD LLModel::writeModel(
//write out face data
mdl[model_names[idx]][i]["PositionDomain"]["Min"] = min_pos.getValue();
mdl[model_names[idx]][i]["PositionDomain"]["Max"] = max_pos.getValue();
+ mdl[model_names[idx]][i]["NormalizedScale"] = face.mNormalizedScale.getValue();
+
mdl[model_names[idx]][i]["Position"] = verts;
if (face.mNormals)
@@ -821,6 +857,13 @@ LLSD LLModel::writeModel(
mdl[model_names[idx]][i]["Normal"] = normals;
}
+#if 0 // keep this code for now in case we decide to transport tangents with mesh assets
+ if (face.mTangents)
+ {
+ mdl[model_names[idx]][i]["Tangent"] = tangents;
+ }
+#endif
+
if (face.mTexCoords)
{
mdl[model_names[idx]][i]["TexCoord0Domain"]["Min"] = min_tc.getValue();
@@ -1531,7 +1574,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)
@@ -1540,24 +1583,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.finalize();
-
- U64 digest[2];
- hash.raw_digest((U8*) digest);
+ //hash.update((const void*)mInvBindMatrix.data(), sizeof(LLMatrix4a) * mInvBindMatrix.size());
- mHash = digest[0];
+ mHash = hash.digest();
}
U32 LLMeshSkinInfo::sizeBytes() const
diff --git a/indra/llprimitive/llmodelloader.cpp b/indra/llprimitive/llmodelloader.cpp
index 5171621007..554ed54de1 100644
--- a/indra/llprimitive/llmodelloader.cpp
+++ b/indra/llprimitive/llmodelloader.cpp
@@ -160,7 +160,8 @@ bool LLModelLoader::getSLMFilename(const std::string& model_filename, std::strin
std::string::size_type i = model_filename.rfind(".");
if (i != std::string::npos)
{
- slm_filename.replace(i, model_filename.size()-1, ".slm");
+ slm_filename.resize(i, '\0');
+ slm_filename.append(".slm");
return true;
}
else
@@ -172,7 +173,7 @@ bool LLModelLoader::getSLMFilename(const std::string& model_filename, std::strin
bool LLModelLoader::doLoadModel()
{
//first, look for a .slm file of the same name that was modified later
- //than the .dae
+ //than the specified model file
if (mTrySLM)
{
@@ -182,13 +183,13 @@ bool LLModelLoader::doLoadModel()
llstat slm_status;
if (LLFile::stat(slm_filename, &slm_status) == 0)
{ //slm file exists
- llstat dae_status;
- if (LLFile::stat(mFilename, &dae_status) != 0 ||
- dae_status.st_mtime < slm_status.st_mtime)
+ llstat model_file_status;
+ if (LLFile::stat(mFilename, &model_file_status) != 0 ||
+ model_file_status.st_mtime < slm_status.st_mtime)
{
if (loadFromSLM(slm_filename))
{ //slm successfully loaded, if this fails, fall through and
- //try loading from dae
+ //try loading from model file
mLod = -1; //successfully loading from an slm implicitly sets all
//LoDs
diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp
index 67c225d25d..8b470d235c 100644
--- a/indra/llprimitive/llprimitive.cpp
+++ b/indra/llprimitive/llprimitive.cpp
@@ -39,6 +39,7 @@
#include "llsdutil_math.h"
#include "llprimtexturelist.h"
#include "llmaterialid.h"
+#include "llsdutil.h"
/**
* exported constants
@@ -80,6 +81,14 @@ const F32 LIGHT_MIN_CUTOFF = 0.0f;
const F32 LIGHT_DEFAULT_CUTOFF = 0.0f;
const F32 LIGHT_MAX_CUTOFF = 180.f;
+// reflection probes
+const F32 REFLECTION_PROBE_MIN_AMBIANCE = 0.f;
+const F32 REFLECTION_PROBE_MAX_AMBIANCE = 1.f;
+const F32 REFLECTION_PROBE_DEFAULT_AMBIANCE = 0.f;
+const F32 REFLECTION_PROBE_MIN_CLIP_DISTANCE = 0.f;
+const F32 REFLECTION_PROBE_MAX_CLIP_DISTANCE = 1024.f;
+const F32 REFLECTION_PROBE_DEFAULT_CLIP_DISTANCE = 0.f;
+
// "Tension" => [0,10], increments of 0.1
const F32 FLEXIBLE_OBJECT_MIN_TENSION = 0.0f;
const F32 FLEXIBLE_OBJECT_DEFAULT_TENSION = 1.0f;
@@ -1690,6 +1699,10 @@ BOOL LLNetworkData::isValid(U16 param_type, U32 size)
return (size == 28);
case PARAMS_EXTENDED_MESH:
return (size == 4);
+ case PARAMS_RENDER_MATERIAL:
+ return (size > 1);
+ case PARAMS_REFLECTION_PROBE:
+ return (size == 9);
}
return FALSE;
@@ -1808,6 +1821,118 @@ bool LLLightParams::fromLLSD(LLSD& sd)
//============================================================================
+//============================================================================
+
+LLReflectionProbeParams::LLReflectionProbeParams()
+{
+ mType = PARAMS_REFLECTION_PROBE;
+}
+
+BOOL LLReflectionProbeParams::pack(LLDataPacker &dp) const
+{
+ dp.packF32(mAmbiance, "ambiance");
+ dp.packF32(mClipDistance, "clip_distance");
+ dp.packU8(mFlags, "flags");
+ return TRUE;
+}
+
+BOOL LLReflectionProbeParams::unpack(LLDataPacker &dp)
+{
+ F32 ambiance;
+ F32 clip_distance;
+
+ dp.unpackF32(ambiance, "ambiance");
+ setAmbiance(ambiance);
+
+ dp.unpackF32(clip_distance, "clip_distance");
+ setClipDistance(clip_distance);
+
+ dp.unpackU8(mFlags, "flags");
+
+ return TRUE;
+}
+
+bool LLReflectionProbeParams::operator==(const LLNetworkData& data) const
+{
+ if (data.mType != PARAMS_REFLECTION_PROBE)
+ {
+ return false;
+ }
+ const LLReflectionProbeParams *param = (const LLReflectionProbeParams*)&data;
+ if (param->mAmbiance != mAmbiance)
+ {
+ return false;
+ }
+ if (param->mClipDistance != mClipDistance)
+ {
+ return false;
+ }
+ if (param->mFlags != mFlags)
+ {
+ return false;
+ }
+ return true;
+}
+
+void LLReflectionProbeParams::copy(const LLNetworkData& data)
+{
+ const LLReflectionProbeParams *param = (LLReflectionProbeParams*)&data;
+ mType = param->mType;
+ mAmbiance = param->mAmbiance;
+ mClipDistance = param->mClipDistance;
+ mFlags = param->mFlags;
+}
+
+LLSD LLReflectionProbeParams::asLLSD() const
+{
+ LLSD sd;
+ sd["ambiance"] = getAmbiance();
+ sd["clip_distance"] = getClipDistance();
+ sd["flags"] = mFlags;
+ return sd;
+}
+
+bool LLReflectionProbeParams::fromLLSD(LLSD& sd)
+{
+ if (!sd.has("ambiance") ||
+ !sd.has("clip_distance") ||
+ !sd.has("flags"))
+ {
+ return false;
+ }
+
+ setAmbiance((F32)sd["ambiance"].asReal());
+ setClipDistance((F32)sd["clip_distance"].asReal());
+ mFlags = (U8) sd["flags"].asInteger();
+
+ return true;
+}
+
+void LLReflectionProbeParams::setIsBox(bool is_box)
+{
+ if (is_box)
+ {
+ mFlags |= FLAG_BOX_VOLUME;
+ }
+ else
+ {
+ mFlags &= ~FLAG_BOX_VOLUME;
+ }
+}
+
+void LLReflectionProbeParams::setIsDynamic(bool is_dynamic)
+{
+ if (is_dynamic)
+ {
+ mFlags |= FLAG_DYNAMIC;
+ }
+ else
+ {
+ mFlags &= ~FLAG_DYNAMIC;
+ }
+}
+
+//============================================================================
LLFlexibleObjectData::LLFlexibleObjectData()
{
mSimulateLOD = FLEXIBLE_OBJECT_DEFAULT_NUM_SECTIONS;
@@ -2181,3 +2306,142 @@ bool LLExtendedMeshParams::fromLLSD(LLSD& sd)
return false;
}
+
+//============================================================================
+
+LLRenderMaterialParams::LLRenderMaterialParams()
+{
+ mType = PARAMS_RENDER_MATERIAL;
+}
+
+BOOL LLRenderMaterialParams::pack(LLDataPacker& dp) const
+{
+ U8 count = (U8)llmin((S32)mEntries.size(), 14); //limited to 255 bytes, no more than 14 material ids
+
+ dp.packU8(count, "count");
+ for (auto& entry : mEntries)
+ {
+ dp.packU8(entry.te_idx, "te_idx");
+ dp.packUUID(entry.id, "id");
+ }
+
+ return TRUE;
+}
+
+BOOL LLRenderMaterialParams::unpack(LLDataPacker& dp)
+{
+ U8 count;
+ dp.unpackU8(count, "count");
+ mEntries.resize(count);
+ for (auto& entry : mEntries)
+ {
+ dp.unpackU8(entry.te_idx, "te_idx");
+ dp.unpackUUID(entry.id, "te_id");
+ }
+
+ return TRUE;
+}
+
+bool LLRenderMaterialParams::operator==(const LLNetworkData& data) const
+{
+ if (data.mType != PARAMS_RENDER_MATERIAL)
+ {
+ return false;
+ }
+
+ const LLRenderMaterialParams& param = static_cast<const LLRenderMaterialParams&>(data);
+
+ if (param.mEntries.size() != mEntries.size())
+ {
+ return false;
+ }
+
+ for (auto& entry : mEntries)
+ {
+ if (param.getMaterial(entry.te_idx) != entry.id)
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void LLRenderMaterialParams::copy(const LLNetworkData& data)
+{
+ llassert_always(data.mType == PARAMS_RENDER_MATERIAL);
+ const LLRenderMaterialParams& param = static_cast<const LLRenderMaterialParams&>(data);
+ mEntries = param.mEntries;
+}
+
+LLSD LLRenderMaterialParams::asLLSD() const
+{
+ LLSD ret;
+
+ for (int i = 0; i < mEntries.size(); ++i)
+ {
+ ret[i]["te_idx"] = mEntries[i].te_idx;
+ ret[i]["id"] = mEntries[i].id;
+ }
+
+ return ret;
+}
+
+bool LLRenderMaterialParams::fromLLSD(LLSD& sd)
+{
+ if (sd.isArray())
+ {
+ mEntries.resize(sd.size());
+ for (int i = 0; i < sd.size(); ++i)
+ {
+ if (sd[i].has("te_idx") && sd.has("id"))
+ {
+ mEntries[i].te_idx = sd[i]["te_idx"].asInteger();
+ mEntries[i].id = sd[i]["id"].asUUID();
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+void LLRenderMaterialParams::setMaterial(U8 te, const LLUUID& id)
+{
+ for (int i = 0; i < mEntries.size(); ++i)
+ {
+ if (mEntries[i].te_idx == te)
+ {
+ if (id.isNull())
+ {
+ mEntries.erase(mEntries.begin() + i);
+ }
+ else
+ {
+ mEntries[i].id = id;
+ }
+ return;
+ }
+ }
+
+ mEntries.push_back({ te, id });
+}
+
+const LLUUID& LLRenderMaterialParams::getMaterial(U8 te) const
+{
+ for (int i = 0; i < mEntries.size(); ++i)
+ {
+ if (mEntries[i].te_idx == te)
+ {
+ return mEntries[i].id;
+ }
+ }
+
+ return LLUUID::null;
+}
+
diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h
index 309b18faa9..d2adfa4a3d 100644
--- a/indra/llprimitive/llprimitive.h
+++ b/indra/llprimitive/llprimitive.h
@@ -107,6 +107,8 @@ public:
PARAMS_RESERVED = 0x50, // Used on server-side
PARAMS_MESH = 0x60,
PARAMS_EXTENDED_MESH = 0x70,
+ PARAMS_RENDER_MATERIAL = 0x80,
+ PARAMS_REFLECTION_PROBE = 0x90,
};
public:
@@ -170,6 +172,50 @@ public:
F32 getCutoff() const { return mCutoff; }
};
+extern const F32 REFLECTION_PROBE_MIN_AMBIANCE;
+extern const F32 REFLECTION_PROBE_MAX_AMBIANCE;
+extern const F32 REFLECTION_PROBE_DEFAULT_AMBIANCE;
+extern const F32 REFLECTION_PROBE_MIN_CLIP_DISTANCE;
+extern const F32 REFLECTION_PROBE_MAX_CLIP_DISTANCE;
+extern const F32 REFLECTION_PROBE_DEFAULT_CLIP_DISTANCE;
+
+class LLReflectionProbeParams : public LLNetworkData
+{
+public:
+ enum EFlags : U8
+ {
+ FLAG_BOX_VOLUME = 0x01, // use a box influence volume
+ FLAG_DYNAMIC = 0x02, // render dynamic objects (avatars) into this Reflection Probe
+ };
+
+protected:
+ F32 mAmbiance = REFLECTION_PROBE_DEFAULT_AMBIANCE;
+ F32 mClipDistance = REFLECTION_PROBE_DEFAULT_CLIP_DISTANCE;
+ U8 mFlags = 0;
+
+public:
+ LLReflectionProbeParams();
+ /*virtual*/ BOOL pack(LLDataPacker& dp) const;
+ /*virtual*/ BOOL unpack(LLDataPacker& dp);
+ /*virtual*/ bool operator==(const LLNetworkData& data) const;
+ /*virtual*/ void copy(const LLNetworkData& data);
+ // LLSD implementations here are provided by Eddy Stryker.
+ // NOTE: there are currently unused in protocols
+ LLSD asLLSD() const;
+ operator LLSD() const { return asLLSD(); }
+ bool fromLLSD(LLSD& sd);
+
+ void setAmbiance(F32 ambiance) { mAmbiance = llclamp(ambiance, REFLECTION_PROBE_MIN_AMBIANCE, REFLECTION_PROBE_MAX_AMBIANCE); }
+ void setClipDistance(F32 distance) { mClipDistance = llclamp(distance, REFLECTION_PROBE_MIN_CLIP_DISTANCE, REFLECTION_PROBE_MAX_CLIP_DISTANCE); }
+ void setIsBox(bool is_box);
+ void setIsDynamic(bool is_dynamic);
+
+ F32 getAmbiance() const { return mAmbiance; }
+ F32 getClipDistance() const { return mClipDistance; }
+ bool getIsBox() const { return (mFlags & FLAG_BOX_VOLUME) != 0; }
+ bool getIsDynamic() const { return (mFlags & FLAG_DYNAMIC) != 0; }
+};
+
//-------------------------------------------------
// This structure is also used in the part of the
// code that creates new flexible objects.
@@ -320,6 +366,33 @@ public:
};
+class LLRenderMaterialParams : public LLNetworkData
+{
+private:
+ struct Entry
+ {
+ U8 te_idx;
+ LLUUID id;
+ };
+ std::vector< Entry > mEntries;
+
+public:
+ LLRenderMaterialParams();
+ BOOL pack(LLDataPacker& dp) const override;
+ BOOL unpack(LLDataPacker& dp) override;
+ bool operator==(const LLNetworkData& data) const override;
+ void copy(const LLNetworkData& data) override;
+ LLSD asLLSD() const;
+ operator LLSD() const { return asLLSD(); }
+ bool fromLLSD(LLSD& sd);
+
+ void setMaterial(U8 te_idx, const LLUUID& id);
+ const LLUUID& getMaterial(U8 te_idx) const;
+
+ bool isEmpty() { return mEntries.empty(); }
+};
+
+
// This code is not naming-standards compliant. Leaving it like this for
// now to make the connection to code in
// BOOL packTEMessage(LLDataPacker &dp) const;
@@ -415,12 +488,12 @@ public:
virtual S32 setTEMediaFlags(const U8 te, const U8 flags);
virtual S32 setTEGlow(const U8 te, const F32 glow);
virtual S32 setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID);
- virtual S32 setTEMaterialParams(const U8 index, const LLMaterialPtr pMaterialParams);
+ virtual S32 setTEMaterialParams(const U8 index, const LLMaterialPtr pMaterialParams);
virtual BOOL setMaterial(const U8 material); // returns TRUE if material changed
virtual void setTESelected(const U8 te, bool sel);
LLMaterialPtr getTEMaterialParams(const U8 index);
-
+
void copyTEs(const LLPrimitive *primitive);
S32 packTEField(U8 *cur_ptr, U8 *data_ptr, U8 data_size, U8 last_face_index, EMsgVariableType type) const;
BOOL packTEMessage(LLMessageSystem *mesgsys) const;
@@ -498,6 +571,8 @@ public:
static LLPCode legacyToPCode(const U8 legacy);
static U8 pCodeToLegacy(const LLPCode pcode);
static bool getTESTAxes(const U8 face, U32* s_axis, U32* t_axis);
+
+ BOOL hasRenderMaterialParams() const;
inline static BOOL isPrimitive(const LLPCode pcode);
inline static BOOL isApp(const LLPCode pcode);
diff --git a/indra/llprimitive/lltextureentry.cpp b/indra/llprimitive/lltextureentry.cpp
index 284dfc15f4..49f67918f8 100644
--- a/indra/llprimitive/lltextureentry.cpp
+++ b/indra/llprimitive/lltextureentry.cpp
@@ -80,22 +80,7 @@ LLTextureEntry::LLTextureEntry(const LLTextureEntry &rhs)
, mSelected(false)
, mMaterialUpdatePending(false)
{
- mID = rhs.mID;
- mScaleS = rhs.mScaleS;
- mScaleT = rhs.mScaleT;
- mOffsetS = rhs.mOffsetS;
- mOffsetT = rhs.mOffsetT;
- mRotation = rhs.mRotation;
- mColor = rhs.mColor;
- mBump = rhs.mBump;
- mMediaFlags = rhs.mMediaFlags;
- mGlow = rhs.mGlow;
- mMaterialID = rhs.mMaterialID;
- mMaterial = rhs.mMaterial;
- if (rhs.mMediaEntry != NULL) {
- // Make a copy
- mMediaEntry = new LLMediaEntry(*rhs.mMediaEntry);
- }
+ *this = rhs;
}
LLTextureEntry &LLTextureEntry::operator=(const LLTextureEntry &rhs)
@@ -124,6 +109,19 @@ LLTextureEntry &LLTextureEntry::operator=(const LLTextureEntry &rhs)
else {
mMediaEntry = NULL;
}
+
+ mMaterialID = rhs.mMaterialID;
+
+ mGLTFMaterial = rhs.mGLTFMaterial;
+
+ if (rhs.mGLTFMaterialOverrides.notNull())
+ {
+ mGLTFMaterialOverrides = new LLGLTFMaterial(*rhs.mGLTFMaterialOverrides);
+ }
+ else
+ {
+ mGLTFMaterialOverrides = nullptr;
+ }
}
return *this;
@@ -200,6 +198,7 @@ LLSD LLTextureEntry::asLLSD() const
void LLTextureEntry::asLLSD(LLSD& sd) const
{
+ LL_PROFILE_ZONE_SCOPED;
sd["imageid"] = mID;
sd["colors"] = ll_sd_from_color4(mColor);
sd["scales"] = mScaleS;
@@ -218,10 +217,16 @@ void LLTextureEntry::asLLSD(LLSD& sd) const
sd[TEXTURE_MEDIA_DATA_KEY] = mediaData;
}
sd["glow"] = mGlow;
+
+ if (mGLTFMaterialOverrides.notNull())
+ {
+ sd["gltf_override"] = mGLTFMaterialOverrides->asJSON();
+ }
}
bool LLTextureEntry::fromLLSD(const LLSD& sd)
{
+ LL_PROFILE_ZONE_SCOPED;
const char *w, *x;
w = "imageid";
if (sd.has(w))
@@ -282,6 +287,24 @@ bool LLTextureEntry::fromLLSD(const LLSD& sd)
setGlow((F32)sd[w].asReal() );
}
+ w = "gltf_override";
+ if (sd.has(w))
+ {
+ if (mGLTFMaterialOverrides.isNull())
+ {
+ mGLTFMaterialOverrides = new LLGLTFMaterial();
+ }
+
+ std::string warn_msg, error_msg;
+ if (!mGLTFMaterialOverrides->fromJSON(sd[w].asString(), warn_msg, error_msg))
+ {
+ LL_WARNS() << llformat("Failed to parse GLTF json: %s -- %s", warn_msg.c_str(), error_msg.c_str()) << LL_ENDL;
+ LL_WARNS() << sd[w].asString() << LL_ENDL;
+
+ mGLTFMaterialOverrides = nullptr;
+ }
+ }
+
return true;
fail:
return false;
@@ -491,6 +514,72 @@ S32 LLTextureEntry::setBumpShiny(U8 bump_shiny)
return TEM_CHANGE_NONE;
}
+void LLTextureEntry::setGLTFMaterial(LLGLTFMaterial* material, bool local_origin)
+{
+ if (material != getGLTFMaterial())
+ {
+ // assert on precondtion:
+ // whether or not mGLTFMaterial is null, any existing override should have been cleared
+ // before calling setGLTFMaterial
+ // NOTE: if you're hitting this assert, try to make sure calling code is using LLViewerObject::setRenderMaterialID
+ llassert(!local_origin || getGLTFMaterialOverride() == nullptr || getGLTFMaterialOverride()->isClearedForBaseMaterial());
+
+ mGLTFMaterial = material;
+ if (mGLTFMaterial == nullptr)
+ {
+ setGLTFRenderMaterial(nullptr);
+ }
+ }
+}
+
+void LLTextureEntry::setGLTFMaterialOverride(LLGLTFMaterial* mat)
+{
+ llassert(mat == nullptr || getGLTFMaterial() != nullptr); // if override is not null, base material must not be null
+ mGLTFMaterialOverrides = mat;
+}
+
+S32 LLTextureEntry::setBaseMaterial()
+{
+ S32 changed = TEM_CHANGE_NONE;
+
+ if (mGLTFMaterialOverrides)
+ {
+ if (mGLTFMaterialOverrides->setBaseMaterial())
+ {
+ changed = TEM_CHANGE_TEXTURE;
+ }
+
+ if (LLGLTFMaterial::sDefault == *mGLTFMaterialOverrides)
+ {
+ mGLTFMaterialOverrides = nullptr;
+ changed = TEM_CHANGE_TEXTURE;
+ }
+ }
+
+ return changed;
+}
+
+LLGLTFMaterial* LLTextureEntry::getGLTFRenderMaterial() const
+{
+ if (mGLTFRenderMaterial.notNull())
+ {
+ return mGLTFRenderMaterial;
+ }
+
+ llassert(getGLTFMaterialOverride() == nullptr || getGLTFMaterialOverride()->isClearedForBaseMaterial());
+ return getGLTFMaterial();
+}
+
+S32 LLTextureEntry::setGLTFRenderMaterial(LLGLTFMaterial* mat)
+{
+ if (mGLTFRenderMaterial != mat)
+ {
+ mGLTFRenderMaterial = mat;
+ return TEM_CHANGE_TEXTURE;
+ }
+ return TEM_CHANGE_NONE;
+}
+
S32 LLTextureEntry::setMediaFlags(U8 media_flags)
{
media_flags &= TEM_MEDIA_MASK;
diff --git a/indra/llprimitive/lltextureentry.h b/indra/llprimitive/lltextureentry.h
index dc2e201044..9a81181f3a 100644
--- a/indra/llprimitive/lltextureentry.h
+++ b/indra/llprimitive/lltextureentry.h
@@ -32,6 +32,7 @@
#include "llsd.h"
#include "llmaterialid.h"
#include "llmaterial.h"
+#include "llgltfmaterial.h"
// These bits are used while unpacking TEM messages to tell which aspects of
// the texture entry changed.
@@ -193,6 +194,23 @@ public:
// Media flags
enum { MF_NONE = 0x0, MF_HAS_MEDIA = 0x1 };
+ // GLTF asset
+ void setGLTFMaterial(LLGLTFMaterial* material, bool local_origin = true);
+ LLGLTFMaterial* getGLTFMaterial() const { return mGLTFMaterial; }
+
+ // GLTF override
+ LLGLTFMaterial* getGLTFMaterialOverride() const { return mGLTFMaterialOverrides; }
+ void setGLTFMaterialOverride(LLGLTFMaterial* mat);
+ // Clear most overrides so the render material better matches the material
+ // ID (preserve transforms). If the overrides become passthrough, set the
+ // overrides to nullptr.
+ S32 setBaseMaterial();
+
+ // GLTF render material
+ // nuanced behavior here -- if there is no render material, fall back to getGLTFMaterial, but ONLY for the getter, not the setter
+ LLGLTFMaterial* getGLTFRenderMaterial() const;
+ S32 setGLTFRenderMaterial(LLGLTFMaterial* mat);
+
public:
F32 mScaleS; // S, T offset
F32 mScaleT; // S, T offset
@@ -219,6 +237,17 @@ protected:
bool mMaterialUpdatePending;
LLMaterialID mMaterialID;
LLMaterialPtr mMaterial;
+
+ // Reference to GLTF material asset state
+ // On the viewer, this should be the same LLGLTFMaterial instance that exists in LLGLTFMaterialList
+ LLPointer<LLGLTFMaterial> mGLTFMaterial;
+
+ // GLTF material parameter overrides -- the viewer will use this data to override material parameters
+ // set by the asset and store the results in mRenderGLTFMaterial
+ LLPointer<LLGLTFMaterial> mGLTFMaterialOverrides;
+
+ // GLTF material to use for rendering -- will always be an LLFetchedGLTFMaterial
+ LLPointer<LLGLTFMaterial> mGLTFRenderMaterial;
// Note the media data is not sent via the same message structure as the rest of the TE
LLMediaEntry* mMediaEntry; // The media data for the face
diff --git a/indra/llprimitive/tests/llmessagesystem_stub.cpp b/indra/llprimitive/tests/llmessagesystem_stub.cpp
index 04e70945c4..9006833054 100644
--- a/indra/llprimitive/tests/llmessagesystem_stub.cpp
+++ b/indra/llprimitive/tests/llmessagesystem_stub.cpp
@@ -25,7 +25,7 @@
#include "linden_common.h"
-char * _PREHASH_TextureEntry;
+const char * const _PREHASH_TextureEntry = "TextureEntry";
S32 LLMessageSystem::getSizeFast(char const*, char const*) const
{
diff --git a/indra/llprimitive/tests/llprimitive_test.cpp b/indra/llprimitive/tests/llprimitive_test.cpp
index 0d60c7cd15..0ff0795fdc 100644
--- a/indra/llprimitive/tests/llprimitive_test.cpp
+++ b/indra/llprimitive/tests/llprimitive_test.cpp
@@ -71,6 +71,46 @@ private:
S32 mCurrDetailTest;
};
+LLMaterialID::LLMaterialID() {}
+LLMaterialID::LLMaterialID(LLMaterialID const &m) = default;
+LLMaterialID::~LLMaterialID() {}
+void LLMaterialID::set(void const*) { }
+U8 const * LLMaterialID::get() const { return mID; }
+
+LLPrimTextureList::LLPrimTextureList() { }
+LLPrimTextureList::~LLPrimTextureList() { }
+S32 LLPrimTextureList::setBumpMap(const U8 index, const U8 bump) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setOffsetS(const U8 index, const F32 s) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setOffsetT(const U8 index, const F32 t) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::copyTexture(const U8 index, const LLTextureEntry &te) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setRotation(const U8 index, const F32 r) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setBumpShiny(const U8 index, const U8 bump_shiny) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setFullbright(const U8 index, const U8 t) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setMaterialID(const U8 index, const LLMaterialID& pMaterialID) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setMediaFlags(const U8 index, const U8 media_flags) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setMediaTexGen(const U8 index, const U8 media) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setMaterialParams(const U8 index, const LLMaterialPtr pMaterialParams) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setBumpShinyFullbright(const U8 index, const U8 bump) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setID(const U8 index, const LLUUID& id) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setGlow(const U8 index, const F32 glow) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setAlpha(const U8 index, const F32 alpha) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setColor(const U8 index, const LLColor3& color) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setColor(const U8 index, const LLColor4& color) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setScale(const U8 index, const F32 s, const F32 t) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setScaleS(const U8 index, const F32 s) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setScaleT(const U8 index, const F32 t) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setShiny(const U8 index, const U8 shiny) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setOffset(const U8 index, const F32 s, const F32 t) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setTexGen(const U8 index, const U8 texgen) { return TEM_CHANGE_NONE; }
+
+LLMaterialPtr LLPrimTextureList::getMaterialParams(const U8 index) { return LLMaterialPtr(); }
+void LLPrimTextureList::copy(LLPrimTextureList const & ptl) { mEntryList = ptl.mEntryList; } // do we need to call getTexture()->newCopy()?
+void LLPrimTextureList::take(LLPrimTextureList &other_list) { }
+void LLPrimTextureList::setSize(S32 new_size) { mEntryList.resize(new_size); }
+void LLPrimTextureList::setAllIDs(const LLUUID &id) { }
+LLTextureEntry * LLPrimTextureList::getTexture(const U8 index) const { return nullptr; }
+S32 LLPrimTextureList::size() const { return mEntryList.size(); }
+
class PRIMITIVE_TEST_SETUP
{
public:
diff --git a/indra/llrender/CMakeLists.txt b/indra/llrender/CMakeLists.txt
index baab09a104..a30f47f1d9 100644
--- a/indra/llrender/CMakeLists.txt
+++ b/indra/llrender/CMakeLists.txt
@@ -31,6 +31,7 @@ include_directories(SYSTEM
set(llrender_SOURCE_FILES
llatmosphere.cpp
llcubemap.cpp
+ llcubemaparray.cpp
llfontbitmapcache.cpp
llfontfreetype.cpp
llfontgl.cpp
@@ -58,6 +59,7 @@ set(llrender_HEADER_FILES
llatmosphere.h
llcubemap.h
+ llcubemaparray.h
llfontgl.h
llfontfreetype.h
llfontbitmapcache.h
diff --git a/indra/llrender/llatmosphere.cpp b/indra/llrender/llatmosphere.cpp
index ffc17c89f8..8e37ca9b90 100644
--- a/indra/llrender/llatmosphere.cpp
+++ b/indra/llrender/llatmosphere.cpp
@@ -241,7 +241,7 @@ LLGLTexture* LLAtmosphere::getTransmittance()
m_transmittance->generateGLTexture();
m_transmittance->setAddressMode(LLTexUnit::eTextureAddressMode::TAM_CLAMP);
m_transmittance->setFilteringOption(LLTexUnit::eTextureFilterOptions::TFO_BILINEAR);
- m_transmittance->setExplicitFormat(GL_RGB32F_ARB, GL_RGB, GL_FLOAT);
+ m_transmittance->setExplicitFormat(GL_RGB32F, GL_RGB, GL_FLOAT);
m_transmittance->setTarget(GL_TEXTURE_2D, LLTexUnit::TT_TEXTURE);
}
return m_transmittance;
@@ -255,7 +255,7 @@ LLGLTexture* LLAtmosphere::getScattering()
m_scattering->generateGLTexture();
m_scattering->setAddressMode(LLTexUnit::eTextureAddressMode::TAM_CLAMP);
m_scattering->setFilteringOption(LLTexUnit::eTextureFilterOptions::TFO_BILINEAR);
- m_scattering->setExplicitFormat(GL_RGB16F_ARB, GL_RGB, GL_FLOAT);
+ m_scattering->setExplicitFormat(GL_RGB16F, GL_RGB, GL_FLOAT);
m_scattering->setTarget(GL_TEXTURE_3D, LLTexUnit::TT_TEXTURE_3D);
}
return m_scattering;
@@ -269,7 +269,7 @@ LLGLTexture* LLAtmosphere::getMieScattering()
m_mie_scatter_texture->generateGLTexture();
m_mie_scatter_texture->setAddressMode(LLTexUnit::eTextureAddressMode::TAM_CLAMP);
m_mie_scatter_texture->setFilteringOption(LLTexUnit::eTextureFilterOptions::TFO_BILINEAR);
- m_mie_scatter_texture->setExplicitFormat(GL_RGB16F_ARB, GL_RGB, GL_FLOAT);
+ m_mie_scatter_texture->setExplicitFormat(GL_RGB16F, GL_RGB, GL_FLOAT);
m_mie_scatter_texture->setTarget(GL_TEXTURE_3D, LLTexUnit::TT_TEXTURE_3D);
}
return m_mie_scatter_texture;
@@ -283,7 +283,7 @@ LLGLTexture* LLAtmosphere::getIlluminance()
m_illuminance->generateGLTexture();
m_illuminance->setAddressMode(LLTexUnit::eTextureAddressMode::TAM_CLAMP);
m_illuminance->setFilteringOption(LLTexUnit::eTextureFilterOptions::TFO_BILINEAR);
- m_illuminance->setExplicitFormat(GL_RGB32F_ARB, GL_RGB, GL_FLOAT);
+ m_illuminance->setExplicitFormat(GL_RGB32F, GL_RGB, GL_FLOAT);
m_illuminance->setTarget(GL_TEXTURE_2D, LLTexUnit::TT_TEXTURE);
}
return m_illuminance;
diff --git a/indra/llrender/llcubemap.cpp b/indra/llrender/llcubemap.cpp
index 834084674e..254288a86e 100644
--- a/indra/llrender/llcubemap.cpp
+++ b/indra/llrender/llcubemap.cpp
@@ -40,8 +40,9 @@
#include "llglheaders.h"
-const F32 epsilon = 1e-7f;
-const U16 RESOLUTION = 64;
+namespace {
+ const U16 RESOLUTION = 64;
+}
bool LLCubeMap::sUseCubeMaps = true;
@@ -50,12 +51,12 @@ LLCubeMap::LLCubeMap(bool init_as_srgb)
mMatrixStage(0),
mIssRGB(init_as_srgb)
{
- mTargets[0] = GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB;
- mTargets[1] = GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB;
- mTargets[2] = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB;
- mTargets[3] = GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB;
- mTargets[4] = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB;
- mTargets[5] = GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB;
+ mTargets[0] = GL_TEXTURE_CUBE_MAP_NEGATIVE_X;
+ mTargets[1] = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
+ mTargets[2] = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y;
+ mTargets[3] = GL_TEXTURE_CUBE_MAP_POSITIVE_Y;
+ mTargets[4] = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
+ mTargets[5] = GL_TEXTURE_CUBE_MAP_POSITIVE_Z;
}
LLCubeMap::~LLCubeMap()
@@ -66,7 +67,7 @@ void LLCubeMap::initGL()
{
llassert(gGLManager.mInited);
- if (gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps)
+ if (LLCubeMap::sUseCubeMaps)
{
// Not initialized, do stuff.
if (mImages[0].isNull())
@@ -166,6 +167,73 @@ void LLCubeMap::init(const std::vector<LLPointer<LLImageRaw> >& rawimages)
}
}
+void LLCubeMap::initReflectionMap(U32 resolution, U32 components)
+{
+ U32 texname = 0;
+
+ LLImageGL::generateTextures(1, &texname);
+
+ mImages[0] = new LLImageGL(resolution, resolution, components, TRUE);
+ mImages[0]->setTexName(texname);
+ mImages[0]->setTarget(mTargets[0], LLTexUnit::TT_CUBE_MAP);
+ gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_CUBE_MAP, texname);
+ mImages[0]->setAddressMode(LLTexUnit::TAM_CLAMP);
+}
+
+void LLCubeMap::initEnvironmentMap(const std::vector<LLPointer<LLImageRaw> >& rawimages)
+{
+ llassert(rawimages.size() == 6);
+
+ U32 texname = 0;
+
+ LLImageGL::generateTextures(1, &texname);
+
+ U32 resolution = rawimages[0]->getWidth();
+ U32 components = rawimages[0]->getComponents();
+
+ for (int i = 0; i < 6; i++)
+ {
+ llassert(rawimages[i]->getWidth() == resolution);
+ llassert(rawimages[i]->getHeight() == resolution);
+ llassert(rawimages[i]->getComponents() == components);
+
+ mImages[i] = new LLImageGL(resolution, resolution, components, TRUE);
+ mImages[i]->setTarget(mTargets[i], LLTexUnit::TT_CUBE_MAP);
+ mRawImages[i] = rawimages[i];
+ mImages[i]->createGLTexture(0, mRawImages[i], texname);
+
+ gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_CUBE_MAP, texname);
+ mImages[i]->setAddressMode(LLTexUnit::TAM_CLAMP);
+ stop_glerror();
+
+ mImages[i]->setSubImage(mRawImages[i], 0, 0, resolution, resolution);
+ }
+ enableTexture(0);
+ bind();
+ mImages[0]->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
+ glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
+ glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
+ gGL.getTexUnit(0)->disable();
+ disable();
+}
+
+void LLCubeMap::generateMipMaps()
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
+
+ mImages[0]->setUseMipMaps(TRUE);
+ mImages[0]->setHasMipMaps(TRUE);
+ enableTexture(0);
+ bind();
+ mImages[0]->setFilteringOption(LLTexUnit::TFO_BILINEAR);
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("cmgmm - glGenerateMipmap");
+ glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
+ }
+ gGL.getTexUnit(0)->disable();
+ disable();
+}
+
GLuint LLCubeMap::getGLName()
{
return mImages[0]->getTexName();
@@ -184,7 +252,7 @@ void LLCubeMap::enable(S32 stage)
void LLCubeMap::enableTexture(S32 stage)
{
mTextureStage = stage;
- if (gGLManager.mHasCubeMap && stage >= 0 && LLCubeMap::sUseCubeMaps)
+ if (stage >= 0 && LLCubeMap::sUseCubeMaps)
{
gGL.getTexUnit(stage)->enable(LLTexUnit::TT_CUBE_MAP);
}
@@ -197,7 +265,7 @@ void LLCubeMap::disable(void)
void LLCubeMap::disableTexture(void)
{
- if (gGLManager.mHasCubeMap && mTextureStage >= 0 && LLCubeMap::sUseCubeMaps)
+ if (mTextureStage >= 0 && LLCubeMap::sUseCubeMaps)
{
gGL.getTexUnit(mTextureStage)->disable();
if (mTextureStage == 0)
@@ -256,191 +324,6 @@ void LLCubeMap::restoreMatrix()
}*/
}
-void LLCubeMap::setReflection (void)
-{
- gGL.getTexUnit(mTextureStage)->bindManual(LLTexUnit::TT_CUBE_MAP, getGLName());
- mImages[0]->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
- mImages[0]->setAddressMode(LLTexUnit::TAM_CLAMP);
-}
-
-LLVector3 LLCubeMap::map(U8 side, U16 v_val, U16 h_val) const
-{
- LLVector3 dir;
-
- const U8 curr_coef = side >> 1; // 0/1 = X axis, 2/3 = Y, 4/5 = Z
- const S8 side_dir = (((side & 1) << 1) - 1); // even = -1, odd = 1
- const U8 i_coef = (curr_coef + 1) % 3;
- const U8 j_coef = (i_coef + 1) % 3;
-
- dir.mV[curr_coef] = side_dir;
-
- switch (side)
- {
- case 0: // negative X
- dir.mV[i_coef] = -F32((v_val<<1) + 1) / RESOLUTION + 1;
- dir.mV[j_coef] = F32((h_val<<1) + 1) / RESOLUTION - 1;
- break;
- case 1: // positive X
- dir.mV[i_coef] = -F32((v_val<<1) + 1) / RESOLUTION + 1;
- dir.mV[j_coef] = -F32((h_val<<1) + 1) / RESOLUTION + 1;
- break;
- case 2: // negative Y
- dir.mV[i_coef] = -F32((v_val<<1) + 1) / RESOLUTION + 1;
- dir.mV[j_coef] = F32((h_val<<1) + 1) / RESOLUTION - 1;
- break;
- case 3: // positive Y
- dir.mV[i_coef] = F32((v_val<<1) + 1) / RESOLUTION - 1;
- dir.mV[j_coef] = F32((h_val<<1) + 1) / RESOLUTION - 1;
- break;
- case 4: // negative Z
- dir.mV[i_coef] = -F32((h_val<<1) + 1) / RESOLUTION + 1;
- dir.mV[j_coef] = -F32((v_val<<1) + 1) / RESOLUTION + 1;
- break;
- case 5: // positive Z
- dir.mV[i_coef] = -F32((h_val<<1) + 1) / RESOLUTION + 1;
- dir.mV[j_coef] = F32((v_val<<1) + 1) / RESOLUTION - 1;
- break;
- default:
- dir.mV[i_coef] = F32((v_val<<1) + 1) / RESOLUTION - 1;
- dir.mV[j_coef] = F32((h_val<<1) + 1) / RESOLUTION - 1;
- }
-
- dir.normVec();
- return dir;
-}
-
-
-BOOL LLCubeMap::project(F32& v_val, F32& h_val, BOOL& outside,
- U8 side, const LLVector3& dir) const
-{
- const U8 curr_coef = side >> 1; // 0/1 = X axis, 2/3 = Y, 4/5 = Z
- const S8 side_dir = (((side & 1) << 1) - 1); // even = -1, odd = 1
- const U8 i_coef = (curr_coef + 1) % 3;
- const U8 j_coef = (i_coef + 1) % 3;
-
- outside = TRUE;
- if (side_dir * dir.mV[curr_coef] < 0)
- return FALSE;
-
- LLVector3 ray;
-
- F32 norm_val = fabs(dir.mV[curr_coef]);
-
- if (norm_val < epsilon)
- norm_val = 1e-5f;
-
- ray.mV[curr_coef] = side_dir;
- ray.mV[i_coef] = dir.mV[i_coef] / norm_val;
- ray.mV[j_coef] = dir.mV[j_coef] / norm_val;
-
-
- const F32 i_val = (ray.mV[i_coef] + 1) * 0.5f * RESOLUTION;
- const F32 j_val = (ray.mV[j_coef] + 1) * 0.5f * RESOLUTION;
-
- switch (side)
- {
- case 0: // negative X
- v_val = RESOLUTION - i_val;
- h_val = j_val;
- break;
- case 1: // positive X
- v_val = RESOLUTION - i_val;
- h_val = RESOLUTION - j_val;
- break;
- case 2: // negative Y
- v_val = RESOLUTION - i_val;
- h_val = j_val;
- break;
- case 3: // positive Y
- v_val = i_val;
- h_val = j_val;
- break;
- case 4: // negative Z
- v_val = RESOLUTION - j_val;
- h_val = RESOLUTION - i_val;
- break;
- case 5: // positive Z
- v_val = RESOLUTION - j_val;
- h_val = i_val;
- break;
- default:
- v_val = i_val;
- h_val = j_val;
- }
-
- outside = ((v_val < 0) || (v_val > RESOLUTION) ||
- (h_val < 0) || (h_val > RESOLUTION));
-
- return TRUE;
-}
-
-BOOL LLCubeMap::project(F32& v_min, F32& v_max, F32& h_min, F32& h_max,
- U8 side, LLVector3 dir[4]) const
-{
- v_min = h_min = RESOLUTION;
- v_max = h_max = 0;
-
- BOOL fully_outside = TRUE;
- for (U8 vtx = 0; vtx < 4; ++vtx)
- {
- F32 v_val, h_val;
- BOOL outside;
- BOOL consider = project(v_val, h_val, outside, side, dir[vtx]);
- if (!outside)
- fully_outside = FALSE;
- if (consider)
- {
- if (v_val < v_min) v_min = v_val;
- if (v_val > v_max) v_max = v_val;
- if (h_val < h_min) h_min = h_val;
- if (h_val > h_max) h_max = h_val;
- }
- }
-
- v_min = llmax(0.0f, v_min);
- v_max = llmin(RESOLUTION - epsilon, v_max);
- h_min = llmax(0.0f, h_min);
- h_max = llmin(RESOLUTION - epsilon, h_max);
-
- return !fully_outside;
-}
-
-
-void LLCubeMap::paintIn(LLVector3 dir[4], const LLColor4U& col)
-{
- LL_PROFILE_ZONE_SCOPED;
- F32 v_min, v_max, h_min, h_max;
- LLVector3 center = dir[0] + dir[1] + dir[2] + dir[3];
- center.normVec();
-
- for (U8 side = 0; side < 6; ++side)
- {
- if (!project(v_min, v_max, h_min, h_max, side, dir))
- continue;
-
- U8 *td = mRawImages[side]->getData();
-
- U16 v_minu = (U16) v_min;
- U16 v_maxu = (U16) (ceil(v_max) + 0.5);
- U16 h_minu = (U16) h_min;
- U16 h_maxu = (U16) (ceil(h_max) + 0.5);
-
- for (U16 v = v_minu; v < v_maxu; ++v)
- for (U16 h = h_minu; h < h_maxu; ++h)
- //for (U16 v = 0; v < RESOLUTION; ++v)
- // for (U16 h = 0; h < RESOLUTION; ++h)
- {
- const LLVector3 ray = map(side, v, h);
- if (ray * center > 0.999)
- {
- const U32 offset = (RESOLUTION * v + h) * 4;
- for (U8 cc = 0; cc < 3; ++cc)
- td[offset + cc] = U8((td[offset + cc] + col.mV[cc]) * 0.5);
- }
- }
- mImages[side]->setSubImage(mRawImages[side], 0, 0, RESOLUTION, RESOLUTION);
- }
-}
void LLCubeMap::destroyGL()
{
diff --git a/indra/llrender/llcubemap.h b/indra/llrender/llcubemap.h
index a01636d8d4..b9e081cea3 100644
--- a/indra/llrender/llcubemap.h
+++ b/indra/llrender/llcubemap.h
@@ -40,6 +40,17 @@ class LLCubeMap : public LLRefCount
public:
LLCubeMap(bool init_as_srgb);
void init(const std::vector<LLPointer<LLImageRaw> >& rawimages);
+
+ // initialize as an undefined cubemap at the given resolution
+ // used for render-to-cubemap operations
+ // avoids usage of LLImageRaw
+ void initReflectionMap(U32 resolution, U32 components = 3);
+
+ // init from environment map images
+ // Similar to init, but takes ownership of rawimages and makes this cubemap
+ // respect the resolution of rawimages
+ // Raw images must point to array of six square images that are all the same resolution
+ void initEnvironmentMap(const std::vector<LLPointer<LLImageRaw> >& rawimages);
void initGL();
void initRawData(const std::vector<LLPointer<LLImageRaw> >& rawimages);
void initGLData();
@@ -54,18 +65,15 @@ public:
void disableTexture(void);
void setMatrix(S32 stage);
void restoreMatrix();
- void setReflection (void);
- void finishPaint();
+ U32 getResolution() { return mImages[0].notNull() ? mImages[0]->getWidth(0) : 0; }
+
+ // generate mip maps for this Cube Map using GL
+ // NOTE: Cube Map MUST already be resident in VRAM
+ void generateMipMaps();
GLuint getGLName();
- LLVector3 map(U8 side, U16 v_val, U16 h_val) const;
- BOOL project(F32& v_val, F32& h_val, BOOL& outside,
- U8 side, const LLVector3& dir) const;
- BOOL project(F32& v_min, F32& v_max, F32& h_min, F32& h_max,
- U8 side, LLVector3 dir[4]) const;
- void paintIn(LLVector3 dir[4], const LLColor4U& col);
void destroyGL();
public:
diff --git a/indra/llrender/llcubemaparray.cpp b/indra/llrender/llcubemaparray.cpp
new file mode 100644
index 0000000000..52118172c0
--- /dev/null
+++ b/indra/llrender/llcubemaparray.cpp
@@ -0,0 +1,177 @@
+/**
+ * @file llcubemaparray.cpp
+ * @brief LLCubeMap class implementation
+ *
+ * $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$
+ */
+#include "linden_common.h"
+
+#include "llworkerthread.h"
+
+#include "llcubemaparray.h"
+
+#include "v4coloru.h"
+#include "v3math.h"
+#include "v3dmath.h"
+#include "m3math.h"
+#include "m4math.h"
+
+#include "llrender.h"
+#include "llglslshader.h"
+
+#include "llglheaders.h"
+
+//#pragma optimize("", off)
+
+// MUST match order of OpenGL face-layers
+GLenum LLCubeMapArray::sTargets[6] =
+{
+ GL_TEXTURE_CUBE_MAP_POSITIVE_X,
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
+ GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
+ GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
+};
+
+LLVector3 LLCubeMapArray::sLookVecs[6] =
+{
+ LLVector3(1, 0, 0),
+ LLVector3(-1, 0, 0),
+ LLVector3(0, 1, 0),
+ LLVector3(0, -1, 0),
+ LLVector3(0, 0, 1),
+ LLVector3(0, 0, -1)
+};
+
+LLVector3 LLCubeMapArray::sUpVecs[6] =
+{
+ LLVector3(0, -1, 0),
+ LLVector3(0, -1, 0),
+ LLVector3(0, 0, 1),
+ LLVector3(0, 0, -1),
+ LLVector3(0, -1, 0),
+ LLVector3(0, -1, 0)
+};
+
+LLVector3 LLCubeMapArray::sClipToCubeLookVecs[6] =
+{
+ LLVector3(0, 0, -1), //GOOD
+ LLVector3(0, 0, 1), //GOOD
+
+ LLVector3(1, 0, 0), // GOOD
+ LLVector3(1, 0, 0), // GOOD
+
+ LLVector3(1, 0, 0),
+ LLVector3(-1, 0, 0),
+};
+
+LLVector3 LLCubeMapArray::sClipToCubeUpVecs[6] =
+{
+ LLVector3(-1, 0, 0), //GOOD
+ LLVector3(1, 0, 0), //GOOD
+
+ LLVector3(0, 1, 0), // GOOD
+ LLVector3(0, -1, 0), // GOOD
+
+ LLVector3(0, 0, -1),
+ LLVector3(0, 0, 1)
+};
+
+LLCubeMapArray::LLCubeMapArray()
+ : mTextureStage(0)
+{
+
+}
+
+LLCubeMapArray::~LLCubeMapArray()
+{
+}
+
+void LLCubeMapArray::allocate(U32 resolution, U32 components, U32 count, BOOL use_mips)
+{
+ U32 texname = 0;
+
+ LLImageGL::generateTextures(1, &texname);
+
+ mImage = new LLImageGL(resolution, resolution, components, use_mips);
+ mImage->setTexName(texname);
+ mImage->setTarget(sTargets[0], LLTexUnit::TT_CUBE_MAP_ARRAY);
+
+ mImage->setUseMipMaps(use_mips);
+ mImage->setHasMipMaps(use_mips);
+
+ bind(0);
+
+ U32 format = components == 4 ? GL_RGBA12 : GL_RGB10;
+
+ U32 mip = 0;
+
+ while (resolution >= 1)
+ {
+ glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, format, resolution, resolution, count * 6, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+
+ if (!use_mips)
+ {
+ break;
+ }
+ resolution /= 2;
+ ++mip;
+ }
+
+ mImage->setAddressMode(LLTexUnit::TAM_CLAMP);
+
+ if (use_mips)
+ {
+ mImage->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
+ //glGenerateMipmap(GL_TEXTURE_CUBE_MAP_ARRAY); // <=== latest AMD drivers do not appreciate this method of allocating mipmaps
+ }
+ else
+ {
+ mImage->setFilteringOption(LLTexUnit::TFO_BILINEAR);
+ }
+
+ unbind();
+}
+
+void LLCubeMapArray::bind(S32 stage)
+{
+ mTextureStage = stage;
+ gGL.getTexUnit(stage)->bindManual(LLTexUnit::TT_CUBE_MAP_ARRAY, getGLName(), mImage->getUseMipMaps());
+}
+
+void LLCubeMapArray::unbind()
+{
+ gGL.getTexUnit(mTextureStage)->unbind(LLTexUnit::TT_CUBE_MAP_ARRAY);
+ mTextureStage = -1;
+}
+
+GLuint LLCubeMapArray::getGLName()
+{
+ return mImage->getTexName();
+}
+
+void LLCubeMapArray::destroyGL()
+{
+ mImage = NULL;
+}
diff --git a/indra/llrender/llcubemaparray.h b/indra/llrender/llcubemaparray.h
new file mode 100644
index 0000000000..19c86278a1
--- /dev/null
+++ b/indra/llrender/llcubemaparray.h
@@ -0,0 +1,68 @@
+/**
+ * @file llcubemaparray.h
+ * @brief LLCubeMap class definition
+ *
+ * $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$
+ */
+
+#pragma once
+
+#include "llgl.h"
+
+#include <vector>
+
+class LLVector3;
+
+class LLCubeMapArray : public LLRefCount
+{
+public:
+ LLCubeMapArray();
+
+ static GLenum sTargets[6];
+
+ // look and up vectors for each cube face (agent space)
+ static LLVector3 sLookVecs[6];
+ static LLVector3 sUpVecs[6];
+
+ // look and up vectors for each cube face (clip space)
+ static LLVector3 sClipToCubeLookVecs[6];
+ static LLVector3 sClipToCubeUpVecs[6];
+
+ // allocate a cube map array
+ // res - resolution of each cube face
+ // components - number of components per pixel
+ // count - number of cube maps in the array
+ // use_mips - if TRUE, mipmaps will be allocated for this cube map array and anisotropic filtering will be used
+ void allocate(U32 res, U32 components, U32 count, BOOL use_mips = TRUE);
+ void bind(S32 stage);
+ void unbind();
+
+ GLuint getGLName();
+
+ void destroyGL();
+
+protected:
+ friend class LLTexUnit;
+ ~LLCubeMapArray();
+ LLPointer<LLImageGL> mImage;
+ S32 mTextureStage;
+};
diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp
index 193cfa64b8..c08c576531 100644
--- a/indra/llrender/llgl.cpp
+++ b/indra/llrender/llgl.cpp
@@ -86,30 +86,57 @@ void APIENTRY gl_debug_callback(GLenum source,
const GLchar* message,
GLvoid* userParam)
{
- if (severity != GL_DEBUG_SEVERITY_HIGH_ARB &&
- severity != GL_DEBUG_SEVERITY_MEDIUM_ARB &&
- severity != GL_DEBUG_SEVERITY_LOW_ARB)
+ 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;
}
- if (severity == GL_DEBUG_SEVERITY_HIGH_ARB)
- {
- LL_WARNS() << "----- GL ERROR --------" << LL_ENDL;
- }
- else
- {
- LL_WARNS() << "----- GL WARNING -------" << LL_ENDL;
- }
- LL_WARNS() << "Type: " << std::hex << type << LL_ENDL;
- LL_WARNS() << "ID: " << std::hex << id << LL_ENDL;
- LL_WARNS() << "Severity: " << std::hex << severity << LL_ENDL;
- LL_WARNS() << "Message: " << message << LL_ENDL;
- LL_WARNS() << "-----------------------" << LL_ENDL;
- if (severity == GL_DEBUG_SEVERITY_HIGH_ARB)
- {
- LL_ERRS() << "Halting on GL Error" << LL_ENDL;
- }
+ if (severity == GL_DEBUG_SEVERITY_HIGH)
+ {
+ LL_WARNS() << "----- GL ERROR --------" << LL_ENDL;
+ }
+ else
+ {
+ LL_WARNS() << "----- GL WARNING -------" << LL_ENDL;
+ }
+ LL_WARNS() << "Type: " << std::hex << type << LL_ENDL;
+ LL_WARNS() << "ID: " << std::hex << id << LL_ENDL;
+ LL_WARNS() << "Severity: " << std::hex << severity << LL_ENDL;
+ LL_WARNS() << "Message: " << message << LL_ENDL;
+ LL_WARNS() << "-----------------------" << LL_ENDL;
+
+ GLint vao = 0;
+ 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);
+ 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;
+ }
}
#endif
@@ -159,246 +186,770 @@ std::list<LLGLUpdate*> LLGLUpdate::sGLQ;
#if (LL_WINDOWS || LL_LINUX) && !LL_MESA_HEADLESS
#if LL_WINDOWS
-PFNGLGETSTRINGIPROC glGetStringi = NULL;
-#endif
-
-// vertex blending prototypes
-PFNGLWEIGHTPOINTERARBPROC glWeightPointerARB = NULL;
-PFNGLVERTEXBLENDARBPROC glVertexBlendARB = NULL;
-PFNGLWEIGHTFVARBPROC glWeightfvARB = NULL;
-
-// Vertex buffer object prototypes
-PFNGLBINDBUFFERARBPROC glBindBufferARB = NULL;
-PFNGLDELETEBUFFERSARBPROC glDeleteBuffersARB = NULL;
-PFNGLGENBUFFERSARBPROC glGenBuffersARB = NULL;
-PFNGLISBUFFERARBPROC glIsBufferARB = NULL;
-PFNGLBUFFERDATAARBPROC glBufferDataARB = NULL;
-PFNGLBUFFERSUBDATAARBPROC glBufferSubDataARB = NULL;
-PFNGLGETBUFFERSUBDATAARBPROC glGetBufferSubDataARB = NULL;
-PFNGLMAPBUFFERARBPROC glMapBufferARB = NULL;
-PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB = NULL;
-PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB = NULL;
-PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB = NULL;
-
-//GL_ARB_vertex_array_object
-PFNGLBINDVERTEXARRAYPROC glBindVertexArray = NULL;
-PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays = NULL;
-PFNGLGENVERTEXARRAYSPROC glGenVertexArrays = NULL;
-PFNGLISVERTEXARRAYPROC glIsVertexArray = NULL;
-
-// GL_ARB_map_buffer_range
-PFNGLMAPBUFFERRANGEPROC glMapBufferRange = NULL;
-PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange = NULL;
-
-// GL_ARB_sync
-PFNGLFENCESYNCPROC glFenceSync = NULL;
-PFNGLISSYNCPROC glIsSync = NULL;
-PFNGLDELETESYNCPROC glDeleteSync = NULL;
-PFNGLCLIENTWAITSYNCPROC glClientWaitSync = NULL;
-PFNGLWAITSYNCPROC glWaitSync = NULL;
-PFNGLGETINTEGER64VPROC glGetInteger64v = NULL;
-PFNGLGETSYNCIVPROC glGetSynciv = NULL;
-
-// GL_APPLE_flush_buffer_range
-PFNGLBUFFERPARAMETERIAPPLEPROC glBufferParameteriAPPLE = NULL;
-PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC glFlushMappedBufferRangeAPPLE = NULL;
-
-// GL_ARB_occlusion_query
-PFNGLGENQUERIESARBPROC glGenQueriesARB = NULL;
-PFNGLDELETEQUERIESARBPROC glDeleteQueriesARB = NULL;
-PFNGLISQUERYARBPROC glIsQueryARB = NULL;
-PFNGLBEGINQUERYARBPROC glBeginQueryARB = NULL;
-PFNGLENDQUERYARBPROC glEndQueryARB = NULL;
-PFNGLGETQUERYIVARBPROC glGetQueryivARB = NULL;
-PFNGLGETQUERYOBJECTIVARBPROC glGetQueryObjectivARB = NULL;
-PFNGLGETQUERYOBJECTUIVARBPROC glGetQueryObjectuivARB = NULL;
-
-// GL_ARB_timer_query
-PFNGLQUERYCOUNTERPROC glQueryCounter = NULL;
-PFNGLGETQUERYOBJECTI64VPROC glGetQueryObjecti64v = NULL;
-PFNGLGETQUERYOBJECTUI64VPROC glGetQueryObjectui64v = NULL;
-
-// GL_ARB_point_parameters
-PFNGLPOINTPARAMETERFARBPROC glPointParameterfARB = NULL;
-PFNGLPOINTPARAMETERFVARBPROC glPointParameterfvARB = NULL;
-
-// GL_ARB_framebuffer_object
-PFNGLISRENDERBUFFERPROC glIsRenderbuffer = NULL;
-PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer = NULL;
-PFNGLDELETERENDERBUFFERSPROC glDeleteRenderbuffers = NULL;
-PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers = NULL;
-PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage = NULL;
-PFNGLGETRENDERBUFFERPARAMETERIVPROC glGetRenderbufferParameteriv = NULL;
-PFNGLISFRAMEBUFFERPROC glIsFramebuffer = NULL;
-PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer = NULL;
-PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers = NULL;
-PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers = NULL;
-PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus = NULL;
-PFNGLFRAMEBUFFERTEXTURE1DPROC glFramebufferTexture1D = NULL;
-PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D = NULL;
-PFNGLFRAMEBUFFERTEXTURE3DPROC glFramebufferTexture3D = NULL;
-PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer = NULL;
-PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glGetFramebufferAttachmentParameteriv = NULL;
-PFNGLGENERATEMIPMAPPROC glGenerateMipmap = NULL;
-PFNGLBLITFRAMEBUFFERPROC glBlitFramebuffer = NULL;
-PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glRenderbufferStorageMultisample = NULL;
-PFNGLFRAMEBUFFERTEXTURELAYERPROC glFramebufferTextureLayer = NULL;
-
-//GL_ARB_texture_multisample
-PFNGLTEXIMAGE2DMULTISAMPLEPROC glTexImage2DMultisample = NULL;
-PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample = NULL;
-PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv = NULL;
-PFNGLSAMPLEMASKIPROC glSampleMaski = NULL;
-
-//transform feedback (4.0 core)
-PFNGLBEGINTRANSFORMFEEDBACKPROC glBeginTransformFeedback = NULL;
-PFNGLENDTRANSFORMFEEDBACKPROC glEndTransformFeedback = NULL;
-PFNGLTRANSFORMFEEDBACKVARYINGSPROC glTransformFeedbackVaryings = NULL;
-PFNGLBINDBUFFERRANGEPROC glBindBufferRange = NULL;
-PFNGLBINDBUFFERBASEPROC glBindBufferBase = NULL;
-
-//GL_ARB_debug_output
-PFNGLDEBUGMESSAGECONTROLARBPROC glDebugMessageControlARB = NULL;
-PFNGLDEBUGMESSAGEINSERTARBPROC glDebugMessageInsertARB = NULL;
-PFNGLDEBUGMESSAGECALLBACKARBPROC glDebugMessageCallbackARB = NULL;
-PFNGLGETDEBUGMESSAGELOGARBPROC glGetDebugMessageLogARB = NULL;
-
-// GL_EXT_blend_func_separate
-PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT = NULL;
-
-// GL_ARB_draw_buffers
-PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB = NULL;
-
-//shader object prototypes
-PFNGLDELETEOBJECTARBPROC glDeleteObjectARB = NULL;
-PFNGLGETHANDLEARBPROC glGetHandleARB = NULL;
-PFNGLDETACHOBJECTARBPROC glDetachObjectARB = NULL;
-PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB = NULL;
-PFNGLSHADERSOURCEARBPROC glShaderSourceARB = NULL;
-PFNGLCOMPILESHADERARBPROC glCompileShaderARB = NULL;
-PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB = NULL;
-PFNGLATTACHOBJECTARBPROC glAttachObjectARB = NULL;
-PFNGLLINKPROGRAMARBPROC glLinkProgramARB = NULL;
-PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB = NULL;
-PFNGLVALIDATEPROGRAMARBPROC glValidateProgramARB = NULL;
-PFNGLUNIFORM1FARBPROC glUniform1fARB = NULL;
-PFNGLUNIFORM2FARBPROC glUniform2fARB = NULL;
-PFNGLUNIFORM3FARBPROC glUniform3fARB = NULL;
-PFNGLUNIFORM4FARBPROC glUniform4fARB = NULL;
-PFNGLUNIFORM1IARBPROC glUniform1iARB = NULL;
-PFNGLUNIFORM2IARBPROC glUniform2iARB = NULL;
-PFNGLUNIFORM3IARBPROC glUniform3iARB = NULL;
-PFNGLUNIFORM4IARBPROC glUniform4iARB = NULL;
-PFNGLUNIFORM1FVARBPROC glUniform1fvARB = NULL;
-PFNGLUNIFORM2FVARBPROC glUniform2fvARB = NULL;
-PFNGLUNIFORM3FVARBPROC glUniform3fvARB = NULL;
-PFNGLUNIFORM4FVARBPROC glUniform4fvARB = NULL;
-PFNGLUNIFORM1IVARBPROC glUniform1ivARB = NULL;
-PFNGLUNIFORM2IVARBPROC glUniform2ivARB = NULL;
-PFNGLUNIFORM3IVARBPROC glUniform3ivARB = NULL;
-PFNGLUNIFORM4IVARBPROC glUniform4ivARB = NULL;
-PFNGLUNIFORMMATRIX2FVARBPROC glUniformMatrix2fvARB = NULL;
-PFNGLUNIFORMMATRIX3FVARBPROC glUniformMatrix3fvARB = NULL;
-PFNGLUNIFORMMATRIX3X4FVPROC glUniformMatrix3x4fv = NULL;
-PFNGLUNIFORMMATRIX4FVARBPROC glUniformMatrix4fvARB = NULL;
-PFNGLGETOBJECTPARAMETERFVARBPROC glGetObjectParameterfvARB = NULL;
-PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB = NULL;
-PFNGLGETINFOLOGARBPROC glGetInfoLogARB = NULL;
-PFNGLGETATTACHEDOBJECTSARBPROC glGetAttachedObjectsARB = NULL;
-PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB = NULL;
-PFNGLGETACTIVEUNIFORMARBPROC glGetActiveUniformARB = NULL;
-PFNGLGETUNIFORMFVARBPROC glGetUniformfvARB = NULL;
-PFNGLGETUNIFORMIVARBPROC glGetUniformivARB = NULL;
-PFNGLGETSHADERSOURCEARBPROC glGetShaderSourceARB = NULL;
-PFNGLVERTEXATTRIBIPOINTERPROC glVertexAttribIPointer = NULL;
+// WGL_ARB_create_context
+PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = nullptr;
+
+// WGL_AMD_gpu_association
+PFNWGLGETGPUIDSAMDPROC wglGetGPUIDsAMD = nullptr;
+PFNWGLGETGPUINFOAMDPROC wglGetGPUInfoAMD = nullptr;
+PFNWGLGETCONTEXTGPUIDAMDPROC wglGetContextGPUIDAMD = nullptr;
+PFNWGLCREATEASSOCIATEDCONTEXTAMDPROC wglCreateAssociatedContextAMD = nullptr;
+PFNWGLCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC wglCreateAssociatedContextAttribsAMD = nullptr;
+PFNWGLDELETEASSOCIATEDCONTEXTAMDPROC wglDeleteAssociatedContextAMD = nullptr;
+PFNWGLMAKEASSOCIATEDCONTEXTCURRENTAMDPROC wglMakeAssociatedContextCurrentAMD = nullptr;
+PFNWGLGETCURRENTASSOCIATEDCONTEXTAMDPROC wglGetCurrentAssociatedContextAMD = nullptr;
+PFNWGLBLITCONTEXTFRAMEBUFFERAMDPROC wglBlitContextFramebufferAMD = nullptr;
+
+// WGL_EXT_swap_control
+PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = nullptr;
+PFNWGLGETSWAPINTERVALEXTPROC wglGetSwapIntervalEXT = nullptr;
-#if LL_WINDOWS
-PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = NULL;
#endif
-// vertex shader prototypes
-#if LL_LINUX
-PFNGLVERTEXATTRIB1DARBPROC glVertexAttrib1dARB = NULL;
-PFNGLVERTEXATTRIB1DVARBPROC glVertexAttrib1dvARB = NULL;
-PFNGLVERTEXATTRIB1FARBPROC glVertexAttrib1fARB = NULL;
-PFNGLVERTEXATTRIB1FVARBPROC glVertexAttrib1fvARB = NULL;
-PFNGLVERTEXATTRIB1SARBPROC glVertexAttrib1sARB = NULL;
-PFNGLVERTEXATTRIB1SVARBPROC glVertexAttrib1svARB = NULL;
-PFNGLVERTEXATTRIB2DARBPROC glVertexAttrib2dARB = NULL;
-PFNGLVERTEXATTRIB2DVARBPROC glVertexAttrib2dvARB = NULL;
-PFNGLVERTEXATTRIB2FARBPROC glVertexAttrib2fARB = NULL;
-PFNGLVERTEXATTRIB2FVARBPROC glVertexAttrib2fvARB = NULL;
-PFNGLVERTEXATTRIB2SARBPROC glVertexAttrib2sARB = NULL;
-PFNGLVERTEXATTRIB2SVARBPROC glVertexAttrib2svARB = NULL;
-PFNGLVERTEXATTRIB3DARBPROC glVertexAttrib3dARB = NULL;
-PFNGLVERTEXATTRIB3DVARBPROC glVertexAttrib3dvARB = NULL;
-PFNGLVERTEXATTRIB3FARBPROC glVertexAttrib3fARB = NULL;
-PFNGLVERTEXATTRIB3FVARBPROC glVertexAttrib3fvARB = NULL;
-PFNGLVERTEXATTRIB3SARBPROC glVertexAttrib3sARB = NULL;
-PFNGLVERTEXATTRIB3SVARBPROC glVertexAttrib3svARB = NULL;
-#endif // LL_LINUX
-PFNGLVERTEXATTRIB4NBVARBPROC glVertexAttrib4nbvARB = NULL;
-PFNGLVERTEXATTRIB4NIVARBPROC glVertexAttrib4nivARB = NULL;
-PFNGLVERTEXATTRIB4NSVARBPROC glVertexAttrib4nsvARB = NULL;
-PFNGLVERTEXATTRIB4NUBARBPROC glVertexAttrib4nubARB = NULL;
-PFNGLVERTEXATTRIB4NUBVARBPROC glVertexAttrib4nubvARB = NULL;
-PFNGLVERTEXATTRIB4NUIVARBPROC glVertexAttrib4nuivARB = NULL;
-PFNGLVERTEXATTRIB4NUSVARBPROC glVertexAttrib4nusvARB = NULL;
-#if LL_LINUX
-PFNGLVERTEXATTRIB4BVARBPROC glVertexAttrib4bvARB = NULL;
-PFNGLVERTEXATTRIB4DARBPROC glVertexAttrib4dARB = NULL;
-PFNGLVERTEXATTRIB4DVARBPROC glVertexAttrib4dvARB = NULL;
-PFNGLVERTEXATTRIB4FARBPROC glVertexAttrib4fARB = NULL;
-PFNGLVERTEXATTRIB4FVARBPROC glVertexAttrib4fvARB = NULL;
-PFNGLVERTEXATTRIB4IVARBPROC glVertexAttrib4ivARB = NULL;
-PFNGLVERTEXATTRIB4SARBPROC glVertexAttrib4sARB = NULL;
-PFNGLVERTEXATTRIB4SVARBPROC glVertexAttrib4svARB = NULL;
-PFNGLVERTEXATTRIB4UBVARBPROC glVertexAttrib4ubvARB = NULL;
-PFNGLVERTEXATTRIB4UIVARBPROC glVertexAttrib4uivARB = NULL;
-PFNGLVERTEXATTRIB4USVARBPROC glVertexAttrib4usvARB = NULL;
-PFNGLVERTEXATTRIBPOINTERARBPROC glVertexAttribPointerARB = NULL;
-PFNGLENABLEVERTEXATTRIBARRAYARBPROC glEnableVertexAttribArrayARB = NULL;
-PFNGLDISABLEVERTEXATTRIBARRAYARBPROC glDisableVertexAttribArrayARB = NULL;
-PFNGLPROGRAMSTRINGARBPROC glProgramStringARB = NULL;
-PFNGLBINDPROGRAMARBPROC glBindProgramARB = NULL;
-PFNGLDELETEPROGRAMSARBPROC glDeleteProgramsARB = NULL;
-PFNGLGENPROGRAMSARBPROC glGenProgramsARB = NULL;
-PFNGLPROGRAMENVPARAMETER4DARBPROC glProgramEnvParameter4dARB = NULL;
-PFNGLPROGRAMENVPARAMETER4DVARBPROC glProgramEnvParameter4dvARB = NULL;
-PFNGLPROGRAMENVPARAMETER4FARBPROC glProgramEnvParameter4fARB = NULL;
-PFNGLPROGRAMENVPARAMETER4FVARBPROC glProgramEnvParameter4fvARB = NULL;
-PFNGLPROGRAMLOCALPARAMETER4DARBPROC glProgramLocalParameter4dARB = NULL;
-PFNGLPROGRAMLOCALPARAMETER4DVARBPROC glProgramLocalParameter4dvARB = NULL;
-PFNGLPROGRAMLOCALPARAMETER4FARBPROC glProgramLocalParameter4fARB = NULL;
-PFNGLPROGRAMLOCALPARAMETER4FVARBPROC glProgramLocalParameter4fvARB = NULL;
-PFNGLGETPROGRAMENVPARAMETERDVARBPROC glGetProgramEnvParameterdvARB = NULL;
-PFNGLGETPROGRAMENVPARAMETERFVARBPROC glGetProgramEnvParameterfvARB = NULL;
-PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC glGetProgramLocalParameterdvARB = NULL;
-PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC glGetProgramLocalParameterfvARB = NULL;
-PFNGLGETPROGRAMIVARBPROC glGetProgramivARB = NULL;
-PFNGLGETPROGRAMSTRINGARBPROC glGetProgramStringARB = NULL;
-PFNGLGETVERTEXATTRIBDVARBPROC glGetVertexAttribdvARB = NULL;
-PFNGLGETVERTEXATTRIBFVARBPROC glGetVertexAttribfvARB = NULL;
-PFNGLGETVERTEXATTRIBIVARBPROC glGetVertexAttribivARB = NULL;
-PFNGLGETVERTEXATTRIBPOINTERVARBPROC glGetVertexAttribPointervARB = NULL;
-PFNGLISPROGRAMARBPROC glIsProgramARB = NULL;
-#endif // LL_LINUX
-PFNGLBINDATTRIBLOCATIONARBPROC glBindAttribLocationARB = NULL;
-PFNGLGETACTIVEATTRIBARBPROC glGetActiveAttribARB = NULL;
-PFNGLGETATTRIBLOCATIONARBPROC glGetAttribLocationARB = NULL;
-
-#if LL_WINDOWS
-PFNWGLGETGPUIDSAMDPROC wglGetGPUIDsAMD = NULL;
-PFNWGLGETGPUINFOAMDPROC wglGetGPUInfoAMD = NULL;
-PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = NULL;
-#endif
+// GL_VERSION_1_2
+//PFNGLDRAWRANGEELEMENTSPROC glDrawRangeElements = nullptr;
+//PFNGLTEXIMAGE3DPROC glTexImage3D = nullptr;
+//PFNGLTEXSUBIMAGE3DPROC glTexSubImage3D = nullptr;
+//PFNGLCOPYTEXSUBIMAGE3DPROC glCopyTexSubImage3D = nullptr;
+
+// GL_VERSION_1_3
+PFNGLACTIVETEXTUREPROC glActiveTexture = nullptr;
+PFNGLSAMPLECOVERAGEPROC glSampleCoverage = nullptr;
+PFNGLCOMPRESSEDTEXIMAGE3DPROC glCompressedTexImage3D = nullptr;
+PFNGLCOMPRESSEDTEXIMAGE2DPROC glCompressedTexImage2D = nullptr;
+PFNGLCOMPRESSEDTEXIMAGE1DPROC glCompressedTexImage1D = nullptr;
+PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC glCompressedTexSubImage3D = nullptr;
+PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glCompressedTexSubImage2D = nullptr;
+PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC glCompressedTexSubImage1D = nullptr;
+PFNGLGETCOMPRESSEDTEXIMAGEPROC glGetCompressedTexImage = nullptr;
+PFNGLCLIENTACTIVETEXTUREPROC glClientActiveTexture = nullptr;
+PFNGLMULTITEXCOORD1DPROC glMultiTexCoord1d = nullptr;
+PFNGLMULTITEXCOORD1DVPROC glMultiTexCoord1dv = nullptr;
+PFNGLMULTITEXCOORD1FPROC glMultiTexCoord1f = nullptr;
+PFNGLMULTITEXCOORD1FVPROC glMultiTexCoord1fv = nullptr;
+PFNGLMULTITEXCOORD1IPROC glMultiTexCoord1i = nullptr;
+PFNGLMULTITEXCOORD1IVPROC glMultiTexCoord1iv = nullptr;
+PFNGLMULTITEXCOORD1SPROC glMultiTexCoord1s = nullptr;
+PFNGLMULTITEXCOORD1SVPROC glMultiTexCoord1sv = nullptr;
+PFNGLMULTITEXCOORD2DPROC glMultiTexCoord2d = nullptr;
+PFNGLMULTITEXCOORD2DVPROC glMultiTexCoord2dv = nullptr;
+PFNGLMULTITEXCOORD2FPROC glMultiTexCoord2f = nullptr;
+PFNGLMULTITEXCOORD2FVPROC glMultiTexCoord2fv = nullptr;
+PFNGLMULTITEXCOORD2IPROC glMultiTexCoord2i = nullptr;
+PFNGLMULTITEXCOORD2IVPROC glMultiTexCoord2iv = nullptr;
+PFNGLMULTITEXCOORD2SPROC glMultiTexCoord2s = nullptr;
+PFNGLMULTITEXCOORD2SVPROC glMultiTexCoord2sv = nullptr;
+PFNGLMULTITEXCOORD3DPROC glMultiTexCoord3d = nullptr;
+PFNGLMULTITEXCOORD3DVPROC glMultiTexCoord3dv = nullptr;
+PFNGLMULTITEXCOORD3FPROC glMultiTexCoord3f = nullptr;
+PFNGLMULTITEXCOORD3FVPROC glMultiTexCoord3fv = nullptr;
+PFNGLMULTITEXCOORD3IPROC glMultiTexCoord3i = nullptr;
+PFNGLMULTITEXCOORD3IVPROC glMultiTexCoord3iv = nullptr;
+PFNGLMULTITEXCOORD3SPROC glMultiTexCoord3s = nullptr;
+PFNGLMULTITEXCOORD3SVPROC glMultiTexCoord3sv = nullptr;
+PFNGLMULTITEXCOORD4DPROC glMultiTexCoord4d = nullptr;
+PFNGLMULTITEXCOORD4DVPROC glMultiTexCoord4dv = nullptr;
+PFNGLMULTITEXCOORD4FPROC glMultiTexCoord4f = nullptr;
+PFNGLMULTITEXCOORD4FVPROC glMultiTexCoord4fv = nullptr;
+PFNGLMULTITEXCOORD4IPROC glMultiTexCoord4i = nullptr;
+PFNGLMULTITEXCOORD4IVPROC glMultiTexCoord4iv = nullptr;
+PFNGLMULTITEXCOORD4SPROC glMultiTexCoord4s = nullptr;
+PFNGLMULTITEXCOORD4SVPROC glMultiTexCoord4sv = nullptr;
+PFNGLLOADTRANSPOSEMATRIXFPROC glLoadTransposeMatrixf = nullptr;
+PFNGLLOADTRANSPOSEMATRIXDPROC glLoadTransposeMatrixd = nullptr;
+PFNGLMULTTRANSPOSEMATRIXFPROC glMultTransposeMatrixf = nullptr;
+PFNGLMULTTRANSPOSEMATRIXDPROC glMultTransposeMatrixd = nullptr;
+
+// GL_VERSION_1_4
+PFNGLBLENDFUNCSEPARATEPROC glBlendFuncSeparate = nullptr;
+PFNGLMULTIDRAWARRAYSPROC glMultiDrawArrays = nullptr;
+PFNGLMULTIDRAWELEMENTSPROC glMultiDrawElements = nullptr;
+PFNGLPOINTPARAMETERFPROC glPointParameterf = nullptr;
+PFNGLPOINTPARAMETERFVPROC glPointParameterfv = nullptr;
+PFNGLPOINTPARAMETERIPROC glPointParameteri = nullptr;
+PFNGLPOINTPARAMETERIVPROC glPointParameteriv = nullptr;
+PFNGLFOGCOORDFPROC glFogCoordf = nullptr;
+PFNGLFOGCOORDFVPROC glFogCoordfv = nullptr;
+PFNGLFOGCOORDDPROC glFogCoordd = nullptr;
+PFNGLFOGCOORDDVPROC glFogCoorddv = nullptr;
+PFNGLFOGCOORDPOINTERPROC glFogCoordPointer = nullptr;
+PFNGLSECONDARYCOLOR3BPROC glSecondaryColor3b = nullptr;
+PFNGLSECONDARYCOLOR3BVPROC glSecondaryColor3bv = nullptr;
+PFNGLSECONDARYCOLOR3DPROC glSecondaryColor3d = nullptr;
+PFNGLSECONDARYCOLOR3DVPROC glSecondaryColor3dv = nullptr;
+PFNGLSECONDARYCOLOR3FPROC glSecondaryColor3f = nullptr;
+PFNGLSECONDARYCOLOR3FVPROC glSecondaryColor3fv = nullptr;
+PFNGLSECONDARYCOLOR3IPROC glSecondaryColor3i = nullptr;
+PFNGLSECONDARYCOLOR3IVPROC glSecondaryColor3iv = nullptr;
+PFNGLSECONDARYCOLOR3SPROC glSecondaryColor3s = nullptr;
+PFNGLSECONDARYCOLOR3SVPROC glSecondaryColor3sv = nullptr;
+PFNGLSECONDARYCOLOR3UBPROC glSecondaryColor3ub = nullptr;
+PFNGLSECONDARYCOLOR3UBVPROC glSecondaryColor3ubv = nullptr;
+PFNGLSECONDARYCOLOR3UIPROC glSecondaryColor3ui = nullptr;
+PFNGLSECONDARYCOLOR3UIVPROC glSecondaryColor3uiv = nullptr;
+PFNGLSECONDARYCOLOR3USPROC glSecondaryColor3us = nullptr;
+PFNGLSECONDARYCOLOR3USVPROC glSecondaryColor3usv = nullptr;
+PFNGLSECONDARYCOLORPOINTERPROC glSecondaryColorPointer = nullptr;
+PFNGLWINDOWPOS2DPROC glWindowPos2d = nullptr;
+PFNGLWINDOWPOS2DVPROC glWindowPos2dv = nullptr;
+PFNGLWINDOWPOS2FPROC glWindowPos2f = nullptr;
+PFNGLWINDOWPOS2FVPROC glWindowPos2fv = nullptr;
+PFNGLWINDOWPOS2IPROC glWindowPos2i = nullptr;
+PFNGLWINDOWPOS2IVPROC glWindowPos2iv = nullptr;
+PFNGLWINDOWPOS2SPROC glWindowPos2s = nullptr;
+PFNGLWINDOWPOS2SVPROC glWindowPos2sv = nullptr;
+PFNGLWINDOWPOS3DPROC glWindowPos3d = nullptr;
+PFNGLWINDOWPOS3DVPROC glWindowPos3dv = nullptr;
+PFNGLWINDOWPOS3FPROC glWindowPos3f = nullptr;
+PFNGLWINDOWPOS3FVPROC glWindowPos3fv = nullptr;
+PFNGLWINDOWPOS3IPROC glWindowPos3i = nullptr;
+PFNGLWINDOWPOS3IVPROC glWindowPos3iv = nullptr;
+PFNGLWINDOWPOS3SPROC glWindowPos3s = nullptr;
+PFNGLWINDOWPOS3SVPROC glWindowPos3sv = nullptr;
+
+// GL_VERSION_1_5
+PFNGLGENQUERIESPROC glGenQueries = nullptr;
+PFNGLDELETEQUERIESPROC glDeleteQueries = nullptr;
+PFNGLISQUERYPROC glIsQuery = nullptr;
+PFNGLBEGINQUERYPROC glBeginQuery = nullptr;
+PFNGLENDQUERYPROC glEndQuery = nullptr;
+PFNGLGETQUERYIVPROC glGetQueryiv = nullptr;
+PFNGLGETQUERYOBJECTIVPROC glGetQueryObjectiv = nullptr;
+PFNGLGETQUERYOBJECTUIVPROC glGetQueryObjectuiv = nullptr;
+PFNGLBINDBUFFERPROC glBindBuffer = nullptr;
+PFNGLDELETEBUFFERSPROC glDeleteBuffers = nullptr;
+PFNGLGENBUFFERSPROC glGenBuffers = nullptr;
+PFNGLISBUFFERPROC glIsBuffer = nullptr;
+PFNGLBUFFERDATAPROC glBufferData = nullptr;
+PFNGLBUFFERSUBDATAPROC glBufferSubData = nullptr;
+PFNGLGETBUFFERSUBDATAPROC glGetBufferSubData = nullptr;
+PFNGLMAPBUFFERPROC glMapBuffer = nullptr;
+PFNGLUNMAPBUFFERPROC glUnmapBuffer = nullptr;
+PFNGLGETBUFFERPARAMETERIVPROC glGetBufferParameteriv = nullptr;
+PFNGLGETBUFFERPOINTERVPROC glGetBufferPointerv = nullptr;
+
+// GL_VERSION_2_0
+PFNGLBLENDEQUATIONSEPARATEPROC glBlendEquationSeparate = nullptr;
+PFNGLDRAWBUFFERSPROC glDrawBuffers = nullptr;
+PFNGLSTENCILOPSEPARATEPROC glStencilOpSeparate = nullptr;
+PFNGLSTENCILFUNCSEPARATEPROC glStencilFuncSeparate = nullptr;
+PFNGLSTENCILMASKSEPARATEPROC glStencilMaskSeparate = nullptr;
+PFNGLATTACHSHADERPROC glAttachShader = nullptr;
+PFNGLBINDATTRIBLOCATIONPROC glBindAttribLocation = nullptr;
+PFNGLCOMPILESHADERPROC glCompileShader = nullptr;
+PFNGLCREATEPROGRAMPROC glCreateProgram = nullptr;
+PFNGLCREATESHADERPROC glCreateShader = nullptr;
+PFNGLDELETEPROGRAMPROC glDeleteProgram = nullptr;
+PFNGLDELETESHADERPROC glDeleteShader = nullptr;
+PFNGLDETACHSHADERPROC glDetachShader = nullptr;
+PFNGLDISABLEVERTEXATTRIBARRAYPROC glDisableVertexAttribArray = nullptr;
+PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray = nullptr;
+PFNGLGETACTIVEATTRIBPROC glGetActiveAttrib = nullptr;
+PFNGLGETACTIVEUNIFORMPROC glGetActiveUniform = nullptr;
+PFNGLGETATTACHEDSHADERSPROC glGetAttachedShaders = nullptr;
+PFNGLGETATTRIBLOCATIONPROC glGetAttribLocation = nullptr;
+PFNGLGETPROGRAMIVPROC glGetProgramiv = nullptr;
+PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog = nullptr;
+PFNGLGETSHADERIVPROC glGetShaderiv = nullptr;
+PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog = nullptr;
+PFNGLGETSHADERSOURCEPROC glGetShaderSource = nullptr;
+PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation = nullptr;
+PFNGLGETUNIFORMFVPROC glGetUniformfv = nullptr;
+PFNGLGETUNIFORMIVPROC glGetUniformiv = nullptr;
+PFNGLGETVERTEXATTRIBDVPROC glGetVertexAttribdv = nullptr;
+PFNGLGETVERTEXATTRIBFVPROC glGetVertexAttribfv = nullptr;
+PFNGLGETVERTEXATTRIBIVPROC glGetVertexAttribiv = nullptr;
+PFNGLGETVERTEXATTRIBPOINTERVPROC glGetVertexAttribPointerv = nullptr;
+PFNGLISPROGRAMPROC glIsProgram = nullptr;
+PFNGLISSHADERPROC glIsShader = nullptr;
+PFNGLLINKPROGRAMPROC glLinkProgram = nullptr;
+PFNGLSHADERSOURCEPROC glShaderSource = nullptr;
+PFNGLUSEPROGRAMPROC glUseProgram = nullptr;
+PFNGLUNIFORM1FPROC glUniform1f = nullptr;
+PFNGLUNIFORM2FPROC glUniform2f = nullptr;
+PFNGLUNIFORM3FPROC glUniform3f = nullptr;
+PFNGLUNIFORM4FPROC glUniform4f = nullptr;
+PFNGLUNIFORM1IPROC glUniform1i = nullptr;
+PFNGLUNIFORM2IPROC glUniform2i = nullptr;
+PFNGLUNIFORM3IPROC glUniform3i = nullptr;
+PFNGLUNIFORM4IPROC glUniform4i = nullptr;
+PFNGLUNIFORM1FVPROC glUniform1fv = nullptr;
+PFNGLUNIFORM2FVPROC glUniform2fv = nullptr;
+PFNGLUNIFORM3FVPROC glUniform3fv = nullptr;
+PFNGLUNIFORM4FVPROC glUniform4fv = nullptr;
+PFNGLUNIFORM1IVPROC glUniform1iv = nullptr;
+PFNGLUNIFORM2IVPROC glUniform2iv = nullptr;
+PFNGLUNIFORM3IVPROC glUniform3iv = nullptr;
+PFNGLUNIFORM4IVPROC glUniform4iv = nullptr;
+PFNGLUNIFORMMATRIX2FVPROC glUniformMatrix2fv = nullptr;
+PFNGLUNIFORMMATRIX3FVPROC glUniformMatrix3fv = nullptr;
+PFNGLUNIFORMMATRIX4FVPROC glUniformMatrix4fv = nullptr;
+PFNGLVALIDATEPROGRAMPROC glValidateProgram = nullptr;
+PFNGLVERTEXATTRIB1DPROC glVertexAttrib1d = nullptr;
+PFNGLVERTEXATTRIB1DVPROC glVertexAttrib1dv = nullptr;
+PFNGLVERTEXATTRIB1FPROC glVertexAttrib1f = nullptr;
+PFNGLVERTEXATTRIB1FVPROC glVertexAttrib1fv = nullptr;
+PFNGLVERTEXATTRIB1SPROC glVertexAttrib1s = nullptr;
+PFNGLVERTEXATTRIB1SVPROC glVertexAttrib1sv = nullptr;
+PFNGLVERTEXATTRIB2DPROC glVertexAttrib2d = nullptr;
+PFNGLVERTEXATTRIB2DVPROC glVertexAttrib2dv = nullptr;
+PFNGLVERTEXATTRIB2FPROC glVertexAttrib2f = nullptr;
+PFNGLVERTEXATTRIB2FVPROC glVertexAttrib2fv = nullptr;
+PFNGLVERTEXATTRIB2SPROC glVertexAttrib2s = nullptr;
+PFNGLVERTEXATTRIB2SVPROC glVertexAttrib2sv = nullptr;
+PFNGLVERTEXATTRIB3DPROC glVertexAttrib3d = nullptr;
+PFNGLVERTEXATTRIB3DVPROC glVertexAttrib3dv = nullptr;
+PFNGLVERTEXATTRIB3FPROC glVertexAttrib3f = nullptr;
+PFNGLVERTEXATTRIB3FVPROC glVertexAttrib3fv = nullptr;
+PFNGLVERTEXATTRIB3SPROC glVertexAttrib3s = nullptr;
+PFNGLVERTEXATTRIB3SVPROC glVertexAttrib3sv = nullptr;
+PFNGLVERTEXATTRIB4NBVPROC glVertexAttrib4Nbv = nullptr;
+PFNGLVERTEXATTRIB4NIVPROC glVertexAttrib4Niv = nullptr;
+PFNGLVERTEXATTRIB4NSVPROC glVertexAttrib4Nsv = nullptr;
+PFNGLVERTEXATTRIB4NUBPROC glVertexAttrib4Nub = nullptr;
+PFNGLVERTEXATTRIB4NUBVPROC glVertexAttrib4Nubv = nullptr;
+PFNGLVERTEXATTRIB4NUIVPROC glVertexAttrib4Nuiv = nullptr;
+PFNGLVERTEXATTRIB4NUSVPROC glVertexAttrib4Nusv = nullptr;
+PFNGLVERTEXATTRIB4BVPROC glVertexAttrib4bv = nullptr;
+PFNGLVERTEXATTRIB4DPROC glVertexAttrib4d = nullptr;
+PFNGLVERTEXATTRIB4DVPROC glVertexAttrib4dv = nullptr;
+PFNGLVERTEXATTRIB4FPROC glVertexAttrib4f = nullptr;
+PFNGLVERTEXATTRIB4FVPROC glVertexAttrib4fv = nullptr;
+PFNGLVERTEXATTRIB4IVPROC glVertexAttrib4iv = nullptr;
+PFNGLVERTEXATTRIB4SPROC glVertexAttrib4s = nullptr;
+PFNGLVERTEXATTRIB4SVPROC glVertexAttrib4sv = nullptr;
+PFNGLVERTEXATTRIB4UBVPROC glVertexAttrib4ubv = nullptr;
+PFNGLVERTEXATTRIB4UIVPROC glVertexAttrib4uiv = nullptr;
+PFNGLVERTEXATTRIB4USVPROC glVertexAttrib4usv = nullptr;
+PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer = nullptr;
+
+// GL_VERSION_2_1
+PFNGLUNIFORMMATRIX2X3FVPROC glUniformMatrix2x3fv = nullptr;
+PFNGLUNIFORMMATRIX3X2FVPROC glUniformMatrix3x2fv = nullptr;
+PFNGLUNIFORMMATRIX2X4FVPROC glUniformMatrix2x4fv = nullptr;
+PFNGLUNIFORMMATRIX4X2FVPROC glUniformMatrix4x2fv = nullptr;
+PFNGLUNIFORMMATRIX3X4FVPROC glUniformMatrix3x4fv = nullptr;
+PFNGLUNIFORMMATRIX4X3FVPROC glUniformMatrix4x3fv = nullptr;
+
+// GL_VERSION_3_0
+PFNGLCOLORMASKIPROC glColorMaski = nullptr;
+PFNGLGETBOOLEANI_VPROC glGetBooleani_v = nullptr;
+PFNGLGETINTEGERI_VPROC glGetIntegeri_v = nullptr;
+PFNGLENABLEIPROC glEnablei = nullptr;
+PFNGLDISABLEIPROC glDisablei = nullptr;
+PFNGLISENABLEDIPROC glIsEnabledi = nullptr;
+PFNGLBEGINTRANSFORMFEEDBACKPROC glBeginTransformFeedback = nullptr;
+PFNGLENDTRANSFORMFEEDBACKPROC glEndTransformFeedback = nullptr;
+PFNGLBINDBUFFERRANGEPROC glBindBufferRange = nullptr;
+PFNGLBINDBUFFERBASEPROC glBindBufferBase = nullptr;
+PFNGLTRANSFORMFEEDBACKVARYINGSPROC glTransformFeedbackVaryings = nullptr;
+PFNGLGETTRANSFORMFEEDBACKVARYINGPROC glGetTransformFeedbackVarying = nullptr;
+PFNGLCLAMPCOLORPROC glClampColor = nullptr;
+PFNGLBEGINCONDITIONALRENDERPROC glBeginConditionalRender = nullptr;
+PFNGLENDCONDITIONALRENDERPROC glEndConditionalRender = nullptr;
+PFNGLVERTEXATTRIBIPOINTERPROC glVertexAttribIPointer = nullptr;
+PFNGLGETVERTEXATTRIBIIVPROC glGetVertexAttribIiv = nullptr;
+PFNGLGETVERTEXATTRIBIUIVPROC glGetVertexAttribIuiv = nullptr;
+PFNGLVERTEXATTRIBI1IPROC glVertexAttribI1i = nullptr;
+PFNGLVERTEXATTRIBI2IPROC glVertexAttribI2i = nullptr;
+PFNGLVERTEXATTRIBI3IPROC glVertexAttribI3i = nullptr;
+PFNGLVERTEXATTRIBI4IPROC glVertexAttribI4i = nullptr;
+PFNGLVERTEXATTRIBI1UIPROC glVertexAttribI1ui = nullptr;
+PFNGLVERTEXATTRIBI2UIPROC glVertexAttribI2ui = nullptr;
+PFNGLVERTEXATTRIBI3UIPROC glVertexAttribI3ui = nullptr;
+PFNGLVERTEXATTRIBI4UIPROC glVertexAttribI4ui = nullptr;
+PFNGLVERTEXATTRIBI1IVPROC glVertexAttribI1iv = nullptr;
+PFNGLVERTEXATTRIBI2IVPROC glVertexAttribI2iv = nullptr;
+PFNGLVERTEXATTRIBI3IVPROC glVertexAttribI3iv = nullptr;
+PFNGLVERTEXATTRIBI4IVPROC glVertexAttribI4iv = nullptr;
+PFNGLVERTEXATTRIBI1UIVPROC glVertexAttribI1uiv = nullptr;
+PFNGLVERTEXATTRIBI2UIVPROC glVertexAttribI2uiv = nullptr;
+PFNGLVERTEXATTRIBI3UIVPROC glVertexAttribI3uiv = nullptr;
+PFNGLVERTEXATTRIBI4UIVPROC glVertexAttribI4uiv = nullptr;
+PFNGLVERTEXATTRIBI4BVPROC glVertexAttribI4bv = nullptr;
+PFNGLVERTEXATTRIBI4SVPROC glVertexAttribI4sv = nullptr;
+PFNGLVERTEXATTRIBI4UBVPROC glVertexAttribI4ubv = nullptr;
+PFNGLVERTEXATTRIBI4USVPROC glVertexAttribI4usv = nullptr;
+PFNGLGETUNIFORMUIVPROC glGetUniformuiv = nullptr;
+PFNGLBINDFRAGDATALOCATIONPROC glBindFragDataLocation = nullptr;
+PFNGLGETFRAGDATALOCATIONPROC glGetFragDataLocation = nullptr;
+PFNGLUNIFORM1UIPROC glUniform1ui = nullptr;
+PFNGLUNIFORM2UIPROC glUniform2ui = nullptr;
+PFNGLUNIFORM3UIPROC glUniform3ui = nullptr;
+PFNGLUNIFORM4UIPROC glUniform4ui = nullptr;
+PFNGLUNIFORM1UIVPROC glUniform1uiv = nullptr;
+PFNGLUNIFORM2UIVPROC glUniform2uiv = nullptr;
+PFNGLUNIFORM3UIVPROC glUniform3uiv = nullptr;
+PFNGLUNIFORM4UIVPROC glUniform4uiv = nullptr;
+PFNGLTEXPARAMETERIIVPROC glTexParameterIiv = nullptr;
+PFNGLTEXPARAMETERIUIVPROC glTexParameterIuiv = nullptr;
+PFNGLGETTEXPARAMETERIIVPROC glGetTexParameterIiv = nullptr;
+PFNGLGETTEXPARAMETERIUIVPROC glGetTexParameterIuiv = nullptr;
+PFNGLCLEARBUFFERIVPROC glClearBufferiv = nullptr;
+PFNGLCLEARBUFFERUIVPROC glClearBufferuiv = nullptr;
+PFNGLCLEARBUFFERFVPROC glClearBufferfv = nullptr;
+PFNGLCLEARBUFFERFIPROC glClearBufferfi = nullptr;
+PFNGLGETSTRINGIPROC glGetStringi = nullptr;
+PFNGLISRENDERBUFFERPROC glIsRenderbuffer = nullptr;
+PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer = nullptr;
+PFNGLDELETERENDERBUFFERSPROC glDeleteRenderbuffers = nullptr;
+PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers = nullptr;
+PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage = nullptr;
+PFNGLGETRENDERBUFFERPARAMETERIVPROC glGetRenderbufferParameteriv = nullptr;
+PFNGLISFRAMEBUFFERPROC glIsFramebuffer = nullptr;
+PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer = nullptr;
+PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers = nullptr;
+PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers = nullptr;
+PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus = nullptr;
+PFNGLFRAMEBUFFERTEXTURE1DPROC glFramebufferTexture1D = nullptr;
+PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D = nullptr;
+PFNGLFRAMEBUFFERTEXTURE3DPROC glFramebufferTexture3D = nullptr;
+PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer = nullptr;
+PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glGetFramebufferAttachmentParameteriv = nullptr;
+PFNGLGENERATEMIPMAPPROC glGenerateMipmap = nullptr;
+PFNGLBLITFRAMEBUFFERPROC glBlitFramebuffer = nullptr;
+PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glRenderbufferStorageMultisample = nullptr;
+PFNGLFRAMEBUFFERTEXTURELAYERPROC glFramebufferTextureLayer = nullptr;
+PFNGLMAPBUFFERRANGEPROC glMapBufferRange = nullptr;
+PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange = nullptr;
+PFNGLBINDVERTEXARRAYPROC glBindVertexArray = nullptr;
+PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays = nullptr;
+PFNGLGENVERTEXARRAYSPROC glGenVertexArrays = nullptr;
+PFNGLISVERTEXARRAYPROC glIsVertexArray = nullptr;
+
+// GL_VERSION_3_1
+PFNGLDRAWARRAYSINSTANCEDPROC glDrawArraysInstanced = nullptr;
+PFNGLDRAWELEMENTSINSTANCEDPROC glDrawElementsInstanced = nullptr;
+PFNGLTEXBUFFERPROC glTexBuffer = nullptr;
+PFNGLPRIMITIVERESTARTINDEXPROC glPrimitiveRestartIndex = nullptr;
+PFNGLCOPYBUFFERSUBDATAPROC glCopyBufferSubData = nullptr;
+PFNGLGETUNIFORMINDICESPROC glGetUniformIndices = nullptr;
+PFNGLGETACTIVEUNIFORMSIVPROC glGetActiveUniformsiv = nullptr;
+PFNGLGETACTIVEUNIFORMNAMEPROC glGetActiveUniformName = nullptr;
+PFNGLGETUNIFORMBLOCKINDEXPROC glGetUniformBlockIndex = nullptr;
+PFNGLGETACTIVEUNIFORMBLOCKIVPROC glGetActiveUniformBlockiv = nullptr;
+PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC glGetActiveUniformBlockName = nullptr;
+PFNGLUNIFORMBLOCKBINDINGPROC glUniformBlockBinding = nullptr;
+
+// GL_VERSION_3_2
+PFNGLDRAWELEMENTSBASEVERTEXPROC glDrawElementsBaseVertex = nullptr;
+PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC glDrawRangeElementsBaseVertex = nullptr;
+PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC glDrawElementsInstancedBaseVertex = nullptr;
+PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC glMultiDrawElementsBaseVertex = nullptr;
+PFNGLPROVOKINGVERTEXPROC glProvokingVertex = nullptr;
+PFNGLFENCESYNCPROC glFenceSync = nullptr;
+PFNGLISSYNCPROC glIsSync = nullptr;
+PFNGLDELETESYNCPROC glDeleteSync = nullptr;
+PFNGLCLIENTWAITSYNCPROC glClientWaitSync = nullptr;
+PFNGLWAITSYNCPROC glWaitSync = nullptr;
+PFNGLGETINTEGER64VPROC glGetInteger64v = nullptr;
+PFNGLGETSYNCIVPROC glGetSynciv = nullptr;
+PFNGLGETINTEGER64I_VPROC glGetInteger64i_v = nullptr;
+PFNGLGETBUFFERPARAMETERI64VPROC glGetBufferParameteri64v = nullptr;
+PFNGLFRAMEBUFFERTEXTUREPROC glFramebufferTexture = nullptr;
+PFNGLTEXIMAGE2DMULTISAMPLEPROC glTexImage2DMultisample = nullptr;
+PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample = nullptr;
+PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv = nullptr;
+PFNGLSAMPLEMASKIPROC glSampleMaski = nullptr;
+
+// GL_VERSION_3_3
+PFNGLBINDFRAGDATALOCATIONINDEXEDPROC glBindFragDataLocationIndexed = nullptr;
+PFNGLGETFRAGDATAINDEXPROC glGetFragDataIndex = nullptr;
+PFNGLGENSAMPLERSPROC glGenSamplers = nullptr;
+PFNGLDELETESAMPLERSPROC glDeleteSamplers = nullptr;
+PFNGLISSAMPLERPROC glIsSampler = nullptr;
+PFNGLBINDSAMPLERPROC glBindSampler = nullptr;
+PFNGLSAMPLERPARAMETERIPROC glSamplerParameteri = nullptr;
+PFNGLSAMPLERPARAMETERIVPROC glSamplerParameteriv = nullptr;
+PFNGLSAMPLERPARAMETERFPROC glSamplerParameterf = nullptr;
+PFNGLSAMPLERPARAMETERFVPROC glSamplerParameterfv = nullptr;
+PFNGLSAMPLERPARAMETERIIVPROC glSamplerParameterIiv = nullptr;
+PFNGLSAMPLERPARAMETERIUIVPROC glSamplerParameterIuiv = nullptr;
+PFNGLGETSAMPLERPARAMETERIVPROC glGetSamplerParameteriv = nullptr;
+PFNGLGETSAMPLERPARAMETERIIVPROC glGetSamplerParameterIiv = nullptr;
+PFNGLGETSAMPLERPARAMETERFVPROC glGetSamplerParameterfv = nullptr;
+PFNGLGETSAMPLERPARAMETERIUIVPROC glGetSamplerParameterIuiv = nullptr;
+PFNGLQUERYCOUNTERPROC glQueryCounter = nullptr;
+PFNGLGETQUERYOBJECTI64VPROC glGetQueryObjecti64v = nullptr;
+PFNGLGETQUERYOBJECTUI64VPROC glGetQueryObjectui64v = nullptr;
+PFNGLVERTEXATTRIBDIVISORPROC glVertexAttribDivisor = nullptr;
+PFNGLVERTEXATTRIBP1UIPROC glVertexAttribP1ui = nullptr;
+PFNGLVERTEXATTRIBP1UIVPROC glVertexAttribP1uiv = nullptr;
+PFNGLVERTEXATTRIBP2UIPROC glVertexAttribP2ui = nullptr;
+PFNGLVERTEXATTRIBP2UIVPROC glVertexAttribP2uiv = nullptr;
+PFNGLVERTEXATTRIBP3UIPROC glVertexAttribP3ui = nullptr;
+PFNGLVERTEXATTRIBP3UIVPROC glVertexAttribP3uiv = nullptr;
+PFNGLVERTEXATTRIBP4UIPROC glVertexAttribP4ui = nullptr;
+PFNGLVERTEXATTRIBP4UIVPROC glVertexAttribP4uiv = nullptr;
+PFNGLVERTEXP2UIPROC glVertexP2ui = nullptr;
+PFNGLVERTEXP2UIVPROC glVertexP2uiv = nullptr;
+PFNGLVERTEXP3UIPROC glVertexP3ui = nullptr;
+PFNGLVERTEXP3UIVPROC glVertexP3uiv = nullptr;
+PFNGLVERTEXP4UIPROC glVertexP4ui = nullptr;
+PFNGLVERTEXP4UIVPROC glVertexP4uiv = nullptr;
+PFNGLTEXCOORDP1UIPROC glTexCoordP1ui = nullptr;
+PFNGLTEXCOORDP1UIVPROC glTexCoordP1uiv = nullptr;
+PFNGLTEXCOORDP2UIPROC glTexCoordP2ui = nullptr;
+PFNGLTEXCOORDP2UIVPROC glTexCoordP2uiv = nullptr;
+PFNGLTEXCOORDP3UIPROC glTexCoordP3ui = nullptr;
+PFNGLTEXCOORDP3UIVPROC glTexCoordP3uiv = nullptr;
+PFNGLTEXCOORDP4UIPROC glTexCoordP4ui = nullptr;
+PFNGLTEXCOORDP4UIVPROC glTexCoordP4uiv = nullptr;
+PFNGLMULTITEXCOORDP1UIPROC glMultiTexCoordP1ui = nullptr;
+PFNGLMULTITEXCOORDP1UIVPROC glMultiTexCoordP1uiv = nullptr;
+PFNGLMULTITEXCOORDP2UIPROC glMultiTexCoordP2ui = nullptr;
+PFNGLMULTITEXCOORDP2UIVPROC glMultiTexCoordP2uiv = nullptr;
+PFNGLMULTITEXCOORDP3UIPROC glMultiTexCoordP3ui = nullptr;
+PFNGLMULTITEXCOORDP3UIVPROC glMultiTexCoordP3uiv = nullptr;
+PFNGLMULTITEXCOORDP4UIPROC glMultiTexCoordP4ui = nullptr;
+PFNGLMULTITEXCOORDP4UIVPROC glMultiTexCoordP4uiv = nullptr;
+PFNGLNORMALP3UIPROC glNormalP3ui = nullptr;
+PFNGLNORMALP3UIVPROC glNormalP3uiv = nullptr;
+PFNGLCOLORP3UIPROC glColorP3ui = nullptr;
+PFNGLCOLORP3UIVPROC glColorP3uiv = nullptr;
+PFNGLCOLORP4UIPROC glColorP4ui = nullptr;
+PFNGLCOLORP4UIVPROC glColorP4uiv = nullptr;
+PFNGLSECONDARYCOLORP3UIPROC glSecondaryColorP3ui = nullptr;
+PFNGLSECONDARYCOLORP3UIVPROC glSecondaryColorP3uiv = nullptr;
+
+// GL_VERSION_4_0
+PFNGLMINSAMPLESHADINGPROC glMinSampleShading = nullptr;
+PFNGLBLENDEQUATIONIPROC glBlendEquationi = nullptr;
+PFNGLBLENDEQUATIONSEPARATEIPROC glBlendEquationSeparatei = nullptr;
+PFNGLBLENDFUNCIPROC glBlendFunci = nullptr;
+PFNGLBLENDFUNCSEPARATEIPROC glBlendFuncSeparatei = nullptr;
+PFNGLDRAWARRAYSINDIRECTPROC glDrawArraysIndirect = nullptr;
+PFNGLDRAWELEMENTSINDIRECTPROC glDrawElementsIndirect = nullptr;
+PFNGLUNIFORM1DPROC glUniform1d = nullptr;
+PFNGLUNIFORM2DPROC glUniform2d = nullptr;
+PFNGLUNIFORM3DPROC glUniform3d = nullptr;
+PFNGLUNIFORM4DPROC glUniform4d = nullptr;
+PFNGLUNIFORM1DVPROC glUniform1dv = nullptr;
+PFNGLUNIFORM2DVPROC glUniform2dv = nullptr;
+PFNGLUNIFORM3DVPROC glUniform3dv = nullptr;
+PFNGLUNIFORM4DVPROC glUniform4dv = nullptr;
+PFNGLUNIFORMMATRIX2DVPROC glUniformMatrix2dv = nullptr;
+PFNGLUNIFORMMATRIX3DVPROC glUniformMatrix3dv = nullptr;
+PFNGLUNIFORMMATRIX4DVPROC glUniformMatrix4dv = nullptr;
+PFNGLUNIFORMMATRIX2X3DVPROC glUniformMatrix2x3dv = nullptr;
+PFNGLUNIFORMMATRIX2X4DVPROC glUniformMatrix2x4dv = nullptr;
+PFNGLUNIFORMMATRIX3X2DVPROC glUniformMatrix3x2dv = nullptr;
+PFNGLUNIFORMMATRIX3X4DVPROC glUniformMatrix3x4dv = nullptr;
+PFNGLUNIFORMMATRIX4X2DVPROC glUniformMatrix4x2dv = nullptr;
+PFNGLUNIFORMMATRIX4X3DVPROC glUniformMatrix4x3dv = nullptr;
+PFNGLGETUNIFORMDVPROC glGetUniformdv = nullptr;
+PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC glGetSubroutineUniformLocation = nullptr;
+PFNGLGETSUBROUTINEINDEXPROC glGetSubroutineIndex = nullptr;
+PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC glGetActiveSubroutineUniformiv = nullptr;
+PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC glGetActiveSubroutineUniformName = nullptr;
+PFNGLGETACTIVESUBROUTINENAMEPROC glGetActiveSubroutineName = nullptr;
+PFNGLUNIFORMSUBROUTINESUIVPROC glUniformSubroutinesuiv = nullptr;
+PFNGLGETUNIFORMSUBROUTINEUIVPROC glGetUniformSubroutineuiv = nullptr;
+PFNGLGETPROGRAMSTAGEIVPROC glGetProgramStageiv = nullptr;
+PFNGLPATCHPARAMETERIPROC glPatchParameteri = nullptr;
+PFNGLPATCHPARAMETERFVPROC glPatchParameterfv = nullptr;
+PFNGLBINDTRANSFORMFEEDBACKPROC glBindTransformFeedback = nullptr;
+PFNGLDELETETRANSFORMFEEDBACKSPROC glDeleteTransformFeedbacks = nullptr;
+PFNGLGENTRANSFORMFEEDBACKSPROC glGenTransformFeedbacks = nullptr;
+PFNGLISTRANSFORMFEEDBACKPROC glIsTransformFeedback = nullptr;
+PFNGLPAUSETRANSFORMFEEDBACKPROC glPauseTransformFeedback = nullptr;
+PFNGLRESUMETRANSFORMFEEDBACKPROC glResumeTransformFeedback = nullptr;
+PFNGLDRAWTRANSFORMFEEDBACKPROC glDrawTransformFeedback = nullptr;
+PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC glDrawTransformFeedbackStream = nullptr;
+PFNGLBEGINQUERYINDEXEDPROC glBeginQueryIndexed = nullptr;
+PFNGLENDQUERYINDEXEDPROC glEndQueryIndexed = nullptr;
+PFNGLGETQUERYINDEXEDIVPROC glGetQueryIndexediv = nullptr;
+
+// GL_VERSION_4_1
+PFNGLRELEASESHADERCOMPILERPROC glReleaseShaderCompiler = nullptr;
+PFNGLSHADERBINARYPROC glShaderBinary = nullptr;
+PFNGLGETSHADERPRECISIONFORMATPROC glGetShaderPrecisionFormat = nullptr;
+PFNGLDEPTHRANGEFPROC glDepthRangef = nullptr;
+PFNGLCLEARDEPTHFPROC glClearDepthf = nullptr;
+PFNGLGETPROGRAMBINARYPROC glGetProgramBinary = nullptr;
+PFNGLPROGRAMBINARYPROC glProgramBinary = nullptr;
+PFNGLPROGRAMPARAMETERIPROC glProgramParameteri = nullptr;
+PFNGLUSEPROGRAMSTAGESPROC glUseProgramStages = nullptr;
+PFNGLACTIVESHADERPROGRAMPROC glActiveShaderProgram = nullptr;
+PFNGLCREATESHADERPROGRAMVPROC glCreateShaderProgramv = nullptr;
+PFNGLBINDPROGRAMPIPELINEPROC glBindProgramPipeline = nullptr;
+PFNGLDELETEPROGRAMPIPELINESPROC glDeleteProgramPipelines = nullptr;
+PFNGLGENPROGRAMPIPELINESPROC glGenProgramPipelines = nullptr;
+PFNGLISPROGRAMPIPELINEPROC glIsProgramPipeline = nullptr;
+PFNGLGETPROGRAMPIPELINEIVPROC glGetProgramPipelineiv = nullptr;
+PFNGLPROGRAMUNIFORM1IPROC glProgramUniform1i = nullptr;
+PFNGLPROGRAMUNIFORM1IVPROC glProgramUniform1iv = nullptr;
+PFNGLPROGRAMUNIFORM1FPROC glProgramUniform1f = nullptr;
+PFNGLPROGRAMUNIFORM1FVPROC glProgramUniform1fv = nullptr;
+PFNGLPROGRAMUNIFORM1DPROC glProgramUniform1d = nullptr;
+PFNGLPROGRAMUNIFORM1DVPROC glProgramUniform1dv = nullptr;
+PFNGLPROGRAMUNIFORM1UIPROC glProgramUniform1ui = nullptr;
+PFNGLPROGRAMUNIFORM1UIVPROC glProgramUniform1uiv = nullptr;
+PFNGLPROGRAMUNIFORM2IPROC glProgramUniform2i = nullptr;
+PFNGLPROGRAMUNIFORM2IVPROC glProgramUniform2iv = nullptr;
+PFNGLPROGRAMUNIFORM2FPROC glProgramUniform2f = nullptr;
+PFNGLPROGRAMUNIFORM2FVPROC glProgramUniform2fv = nullptr;
+PFNGLPROGRAMUNIFORM2DPROC glProgramUniform2d = nullptr;
+PFNGLPROGRAMUNIFORM2DVPROC glProgramUniform2dv = nullptr;
+PFNGLPROGRAMUNIFORM2UIPROC glProgramUniform2ui = nullptr;
+PFNGLPROGRAMUNIFORM2UIVPROC glProgramUniform2uiv = nullptr;
+PFNGLPROGRAMUNIFORM3IPROC glProgramUniform3i = nullptr;
+PFNGLPROGRAMUNIFORM3IVPROC glProgramUniform3iv = nullptr;
+PFNGLPROGRAMUNIFORM3FPROC glProgramUniform3f = nullptr;
+PFNGLPROGRAMUNIFORM3FVPROC glProgramUniform3fv = nullptr;
+PFNGLPROGRAMUNIFORM3DPROC glProgramUniform3d = nullptr;
+PFNGLPROGRAMUNIFORM3DVPROC glProgramUniform3dv = nullptr;
+PFNGLPROGRAMUNIFORM3UIPROC glProgramUniform3ui = nullptr;
+PFNGLPROGRAMUNIFORM3UIVPROC glProgramUniform3uiv = nullptr;
+PFNGLPROGRAMUNIFORM4IPROC glProgramUniform4i = nullptr;
+PFNGLPROGRAMUNIFORM4IVPROC glProgramUniform4iv = nullptr;
+PFNGLPROGRAMUNIFORM4FPROC glProgramUniform4f = nullptr;
+PFNGLPROGRAMUNIFORM4FVPROC glProgramUniform4fv = nullptr;
+PFNGLPROGRAMUNIFORM4DPROC glProgramUniform4d = nullptr;
+PFNGLPROGRAMUNIFORM4DVPROC glProgramUniform4dv = nullptr;
+PFNGLPROGRAMUNIFORM4UIPROC glProgramUniform4ui = nullptr;
+PFNGLPROGRAMUNIFORM4UIVPROC glProgramUniform4uiv = nullptr;
+PFNGLPROGRAMUNIFORMMATRIX2FVPROC glProgramUniformMatrix2fv = nullptr;
+PFNGLPROGRAMUNIFORMMATRIX3FVPROC glProgramUniformMatrix3fv = nullptr;
+PFNGLPROGRAMUNIFORMMATRIX4FVPROC glProgramUniformMatrix4fv = nullptr;
+PFNGLPROGRAMUNIFORMMATRIX2DVPROC glProgramUniformMatrix2dv = nullptr;
+PFNGLPROGRAMUNIFORMMATRIX3DVPROC glProgramUniformMatrix3dv = nullptr;
+PFNGLPROGRAMUNIFORMMATRIX4DVPROC glProgramUniformMatrix4dv = nullptr;
+PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC glProgramUniformMatrix2x3fv = nullptr;
+PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC glProgramUniformMatrix3x2fv = nullptr;
+PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC glProgramUniformMatrix2x4fv = nullptr;
+PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC glProgramUniformMatrix4x2fv = nullptr;
+PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC glProgramUniformMatrix3x4fv = nullptr;
+PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC glProgramUniformMatrix4x3fv = nullptr;
+PFNGLPROGRAMUNIFORMMATRIX2X3DVPROC glProgramUniformMatrix2x3dv = nullptr;
+PFNGLPROGRAMUNIFORMMATRIX3X2DVPROC glProgramUniformMatrix3x2dv = nullptr;
+PFNGLPROGRAMUNIFORMMATRIX2X4DVPROC glProgramUniformMatrix2x4dv = nullptr;
+PFNGLPROGRAMUNIFORMMATRIX4X2DVPROC glProgramUniformMatrix4x2dv = nullptr;
+PFNGLPROGRAMUNIFORMMATRIX3X4DVPROC glProgramUniformMatrix3x4dv = nullptr;
+PFNGLPROGRAMUNIFORMMATRIX4X3DVPROC glProgramUniformMatrix4x3dv = nullptr;
+PFNGLVALIDATEPROGRAMPIPELINEPROC glValidateProgramPipeline = nullptr;
+PFNGLGETPROGRAMPIPELINEINFOLOGPROC glGetProgramPipelineInfoLog = nullptr;
+PFNGLVERTEXATTRIBL1DPROC glVertexAttribL1d = nullptr;
+PFNGLVERTEXATTRIBL2DPROC glVertexAttribL2d = nullptr;
+PFNGLVERTEXATTRIBL3DPROC glVertexAttribL3d = nullptr;
+PFNGLVERTEXATTRIBL4DPROC glVertexAttribL4d = nullptr;
+PFNGLVERTEXATTRIBL1DVPROC glVertexAttribL1dv = nullptr;
+PFNGLVERTEXATTRIBL2DVPROC glVertexAttribL2dv = nullptr;
+PFNGLVERTEXATTRIBL3DVPROC glVertexAttribL3dv = nullptr;
+PFNGLVERTEXATTRIBL4DVPROC glVertexAttribL4dv = nullptr;
+PFNGLVERTEXATTRIBLPOINTERPROC glVertexAttribLPointer = nullptr;
+PFNGLGETVERTEXATTRIBLDVPROC glGetVertexAttribLdv = nullptr;
+PFNGLVIEWPORTARRAYVPROC glViewportArrayv = nullptr;
+PFNGLVIEWPORTINDEXEDFPROC glViewportIndexedf = nullptr;
+PFNGLVIEWPORTINDEXEDFVPROC glViewportIndexedfv = nullptr;
+PFNGLSCISSORARRAYVPROC glScissorArrayv = nullptr;
+PFNGLSCISSORINDEXEDPROC glScissorIndexed = nullptr;
+PFNGLSCISSORINDEXEDVPROC glScissorIndexedv = nullptr;
+PFNGLDEPTHRANGEARRAYVPROC glDepthRangeArrayv = nullptr;
+PFNGLDEPTHRANGEINDEXEDPROC glDepthRangeIndexed = nullptr;
+PFNGLGETFLOATI_VPROC glGetFloati_v = nullptr;
+PFNGLGETDOUBLEI_VPROC glGetDoublei_v = nullptr;
+
+// GL_VERSION_4_2
+PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC glDrawArraysInstancedBaseInstance = nullptr;
+PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC glDrawElementsInstancedBaseInstance = nullptr;
+PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC glDrawElementsInstancedBaseVertexBaseInstance = nullptr;
+PFNGLGETINTERNALFORMATIVPROC glGetInternalformativ = nullptr;
+PFNGLGETACTIVEATOMICCOUNTERBUFFERIVPROC glGetActiveAtomicCounterBufferiv = nullptr;
+PFNGLBINDIMAGETEXTUREPROC glBindImageTexture = nullptr;
+PFNGLMEMORYBARRIERPROC glMemoryBarrier = nullptr;
+PFNGLTEXSTORAGE1DPROC glTexStorage1D = nullptr;
+PFNGLTEXSTORAGE2DPROC glTexStorage2D = nullptr;
+PFNGLTEXSTORAGE3DPROC glTexStorage3D = nullptr;
+PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDPROC glDrawTransformFeedbackInstanced = nullptr;
+PFNGLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC glDrawTransformFeedbackStreamInstanced = nullptr;
+
+// GL_VERSION_4_3
+PFNGLCLEARBUFFERDATAPROC glClearBufferData = nullptr;
+PFNGLCLEARBUFFERSUBDATAPROC glClearBufferSubData = nullptr;
+PFNGLDISPATCHCOMPUTEPROC glDispatchCompute = nullptr;
+PFNGLDISPATCHCOMPUTEINDIRECTPROC glDispatchComputeIndirect = nullptr;
+PFNGLCOPYIMAGESUBDATAPROC glCopyImageSubData = nullptr;
+PFNGLFRAMEBUFFERPARAMETERIPROC glFramebufferParameteri = nullptr;
+PFNGLGETFRAMEBUFFERPARAMETERIVPROC glGetFramebufferParameteriv = nullptr;
+PFNGLGETINTERNALFORMATI64VPROC glGetInternalformati64v = nullptr;
+PFNGLINVALIDATETEXSUBIMAGEPROC glInvalidateTexSubImage = nullptr;
+PFNGLINVALIDATETEXIMAGEPROC glInvalidateTexImage = nullptr;
+PFNGLINVALIDATEBUFFERSUBDATAPROC glInvalidateBufferSubData = nullptr;
+PFNGLINVALIDATEBUFFERDATAPROC glInvalidateBufferData = nullptr;
+PFNGLINVALIDATEFRAMEBUFFERPROC glInvalidateFramebuffer = nullptr;
+PFNGLINVALIDATESUBFRAMEBUFFERPROC glInvalidateSubFramebuffer = nullptr;
+PFNGLMULTIDRAWARRAYSINDIRECTPROC glMultiDrawArraysIndirect = nullptr;
+PFNGLMULTIDRAWELEMENTSINDIRECTPROC glMultiDrawElementsIndirect = nullptr;
+PFNGLGETPROGRAMINTERFACEIVPROC glGetProgramInterfaceiv = nullptr;
+PFNGLGETPROGRAMRESOURCEINDEXPROC glGetProgramResourceIndex = nullptr;
+PFNGLGETPROGRAMRESOURCENAMEPROC glGetProgramResourceName = nullptr;
+PFNGLGETPROGRAMRESOURCEIVPROC glGetProgramResourceiv = nullptr;
+PFNGLGETPROGRAMRESOURCELOCATIONPROC glGetProgramResourceLocation = nullptr;
+PFNGLGETPROGRAMRESOURCELOCATIONINDEXPROC glGetProgramResourceLocationIndex = nullptr;
+PFNGLSHADERSTORAGEBLOCKBINDINGPROC glShaderStorageBlockBinding = nullptr;
+PFNGLTEXBUFFERRANGEPROC glTexBufferRange = nullptr;
+PFNGLTEXSTORAGE2DMULTISAMPLEPROC glTexStorage2DMultisample = nullptr;
+PFNGLTEXSTORAGE3DMULTISAMPLEPROC glTexStorage3DMultisample = nullptr;
+PFNGLTEXTUREVIEWPROC glTextureView = nullptr;
+PFNGLBINDVERTEXBUFFERPROC glBindVertexBuffer = nullptr;
+PFNGLVERTEXATTRIBFORMATPROC glVertexAttribFormat = nullptr;
+PFNGLVERTEXATTRIBIFORMATPROC glVertexAttribIFormat = nullptr;
+PFNGLVERTEXATTRIBLFORMATPROC glVertexAttribLFormat = nullptr;
+PFNGLVERTEXATTRIBBINDINGPROC glVertexAttribBinding = nullptr;
+PFNGLVERTEXBINDINGDIVISORPROC glVertexBindingDivisor = nullptr;
+PFNGLDEBUGMESSAGECONTROLPROC glDebugMessageControl = nullptr;
+PFNGLDEBUGMESSAGEINSERTPROC glDebugMessageInsert = nullptr;
+PFNGLDEBUGMESSAGECALLBACKPROC glDebugMessageCallback = nullptr;
+PFNGLGETDEBUGMESSAGELOGPROC glGetDebugMessageLog = nullptr;
+PFNGLPUSHDEBUGGROUPPROC glPushDebugGroup = nullptr;
+PFNGLPOPDEBUGGROUPPROC glPopDebugGroup = nullptr;
+PFNGLOBJECTLABELPROC glObjectLabel = nullptr;
+PFNGLGETOBJECTLABELPROC glGetObjectLabel = nullptr;
+PFNGLOBJECTPTRLABELPROC glObjectPtrLabel = nullptr;
+PFNGLGETOBJECTPTRLABELPROC glGetObjectPtrLabel = nullptr;
+
+// GL_VERSION_4_4
+PFNGLBUFFERSTORAGEPROC glBufferStorage = nullptr;
+PFNGLCLEARTEXIMAGEPROC glClearTexImage = nullptr;
+PFNGLCLEARTEXSUBIMAGEPROC glClearTexSubImage = nullptr;
+PFNGLBINDBUFFERSBASEPROC glBindBuffersBase = nullptr;
+PFNGLBINDBUFFERSRANGEPROC glBindBuffersRange = nullptr;
+PFNGLBINDTEXTURESPROC glBindTextures = nullptr;
+PFNGLBINDSAMPLERSPROC glBindSamplers = nullptr;
+PFNGLBINDIMAGETEXTURESPROC glBindImageTextures = nullptr;
+PFNGLBINDVERTEXBUFFERSPROC glBindVertexBuffers = nullptr;
+
+// GL_VERSION_4_5
+PFNGLCLIPCONTROLPROC glClipControl = nullptr;
+PFNGLCREATETRANSFORMFEEDBACKSPROC glCreateTransformFeedbacks = nullptr;
+PFNGLTRANSFORMFEEDBACKBUFFERBASEPROC glTransformFeedbackBufferBase = nullptr;
+PFNGLTRANSFORMFEEDBACKBUFFERRANGEPROC glTransformFeedbackBufferRange = nullptr;
+PFNGLGETTRANSFORMFEEDBACKIVPROC glGetTransformFeedbackiv = nullptr;
+PFNGLGETTRANSFORMFEEDBACKI_VPROC glGetTransformFeedbacki_v = nullptr;
+PFNGLGETTRANSFORMFEEDBACKI64_VPROC glGetTransformFeedbacki64_v = nullptr;
+PFNGLCREATEBUFFERSPROC glCreateBuffers = nullptr;
+PFNGLNAMEDBUFFERSTORAGEPROC glNamedBufferStorage = nullptr;
+PFNGLNAMEDBUFFERDATAPROC glNamedBufferData = nullptr;
+PFNGLNAMEDBUFFERSUBDATAPROC glNamedBufferSubData = nullptr;
+PFNGLCOPYNAMEDBUFFERSUBDATAPROC glCopyNamedBufferSubData = nullptr;
+PFNGLCLEARNAMEDBUFFERDATAPROC glClearNamedBufferData = nullptr;
+PFNGLCLEARNAMEDBUFFERSUBDATAPROC glClearNamedBufferSubData = nullptr;
+PFNGLMAPNAMEDBUFFERPROC glMapNamedBuffer = nullptr;
+PFNGLMAPNAMEDBUFFERRANGEPROC glMapNamedBufferRange = nullptr;
+PFNGLUNMAPNAMEDBUFFERPROC glUnmapNamedBuffer = nullptr;
+PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEPROC glFlushMappedNamedBufferRange = nullptr;
+PFNGLGETNAMEDBUFFERPARAMETERIVPROC glGetNamedBufferParameteriv = nullptr;
+PFNGLGETNAMEDBUFFERPARAMETERI64VPROC glGetNamedBufferParameteri64v = nullptr;
+PFNGLGETNAMEDBUFFERPOINTERVPROC glGetNamedBufferPointerv = nullptr;
+PFNGLGETNAMEDBUFFERSUBDATAPROC glGetNamedBufferSubData = nullptr;
+PFNGLCREATEFRAMEBUFFERSPROC glCreateFramebuffers = nullptr;
+PFNGLNAMEDFRAMEBUFFERRENDERBUFFERPROC glNamedFramebufferRenderbuffer = nullptr;
+PFNGLNAMEDFRAMEBUFFERPARAMETERIPROC glNamedFramebufferParameteri = nullptr;
+PFNGLNAMEDFRAMEBUFFERTEXTUREPROC glNamedFramebufferTexture = nullptr;
+PFNGLNAMEDFRAMEBUFFERTEXTURELAYERPROC glNamedFramebufferTextureLayer = nullptr;
+PFNGLNAMEDFRAMEBUFFERDRAWBUFFERPROC glNamedFramebufferDrawBuffer = nullptr;
+PFNGLNAMEDFRAMEBUFFERDRAWBUFFERSPROC glNamedFramebufferDrawBuffers = nullptr;
+PFNGLNAMEDFRAMEBUFFERREADBUFFERPROC glNamedFramebufferReadBuffer = nullptr;
+PFNGLINVALIDATENAMEDFRAMEBUFFERDATAPROC glInvalidateNamedFramebufferData = nullptr;
+PFNGLINVALIDATENAMEDFRAMEBUFFERSUBDATAPROC glInvalidateNamedFramebufferSubData = nullptr;
+PFNGLCLEARNAMEDFRAMEBUFFERIVPROC glClearNamedFramebufferiv = nullptr;
+PFNGLCLEARNAMEDFRAMEBUFFERUIVPROC glClearNamedFramebufferuiv = nullptr;
+PFNGLCLEARNAMEDFRAMEBUFFERFVPROC glClearNamedFramebufferfv = nullptr;
+PFNGLCLEARNAMEDFRAMEBUFFERFIPROC glClearNamedFramebufferfi = nullptr;
+PFNGLBLITNAMEDFRAMEBUFFERPROC glBlitNamedFramebuffer = nullptr;
+PFNGLCHECKNAMEDFRAMEBUFFERSTATUSPROC glCheckNamedFramebufferStatus = nullptr;
+PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVPROC glGetNamedFramebufferParameteriv = nullptr;
+PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVPROC glGetNamedFramebufferAttachmentParameteriv = nullptr;
+PFNGLCREATERENDERBUFFERSPROC glCreateRenderbuffers = nullptr;
+PFNGLNAMEDRENDERBUFFERSTORAGEPROC glNamedRenderbufferStorage = nullptr;
+PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEPROC glNamedRenderbufferStorageMultisample = nullptr;
+PFNGLGETNAMEDRENDERBUFFERPARAMETERIVPROC glGetNamedRenderbufferParameteriv = nullptr;
+PFNGLCREATETEXTURESPROC glCreateTextures = nullptr;
+PFNGLTEXTUREBUFFERPROC glTextureBuffer = nullptr;
+PFNGLTEXTUREBUFFERRANGEPROC glTextureBufferRange = nullptr;
+PFNGLTEXTURESTORAGE1DPROC glTextureStorage1D = nullptr;
+PFNGLTEXTURESTORAGE2DPROC glTextureStorage2D = nullptr;
+PFNGLTEXTURESTORAGE3DPROC glTextureStorage3D = nullptr;
+PFNGLTEXTURESTORAGE2DMULTISAMPLEPROC glTextureStorage2DMultisample = nullptr;
+PFNGLTEXTURESTORAGE3DMULTISAMPLEPROC glTextureStorage3DMultisample = nullptr;
+PFNGLTEXTURESUBIMAGE1DPROC glTextureSubImage1D = nullptr;
+PFNGLTEXTURESUBIMAGE2DPROC glTextureSubImage2D = nullptr;
+PFNGLTEXTURESUBIMAGE3DPROC glTextureSubImage3D = nullptr;
+PFNGLCOMPRESSEDTEXTURESUBIMAGE1DPROC glCompressedTextureSubImage1D = nullptr;
+PFNGLCOMPRESSEDTEXTURESUBIMAGE2DPROC glCompressedTextureSubImage2D = nullptr;
+PFNGLCOMPRESSEDTEXTURESUBIMAGE3DPROC glCompressedTextureSubImage3D = nullptr;
+PFNGLCOPYTEXTURESUBIMAGE1DPROC glCopyTextureSubImage1D = nullptr;
+PFNGLCOPYTEXTURESUBIMAGE2DPROC glCopyTextureSubImage2D = nullptr;
+PFNGLCOPYTEXTURESUBIMAGE3DPROC glCopyTextureSubImage3D = nullptr;
+PFNGLTEXTUREPARAMETERFPROC glTextureParameterf = nullptr;
+PFNGLTEXTUREPARAMETERFVPROC glTextureParameterfv = nullptr;
+PFNGLTEXTUREPARAMETERIPROC glTextureParameteri = nullptr;
+PFNGLTEXTUREPARAMETERIIVPROC glTextureParameterIiv = nullptr;
+PFNGLTEXTUREPARAMETERIUIVPROC glTextureParameterIuiv = nullptr;
+PFNGLTEXTUREPARAMETERIVPROC glTextureParameteriv = nullptr;
+PFNGLGENERATETEXTUREMIPMAPPROC glGenerateTextureMipmap = nullptr;
+PFNGLBINDTEXTUREUNITPROC glBindTextureUnit = nullptr;
+PFNGLGETTEXTUREIMAGEPROC glGetTextureImage = nullptr;
+PFNGLGETCOMPRESSEDTEXTUREIMAGEPROC glGetCompressedTextureImage = nullptr;
+PFNGLGETTEXTURELEVELPARAMETERFVPROC glGetTextureLevelParameterfv = nullptr;
+PFNGLGETTEXTURELEVELPARAMETERIVPROC glGetTextureLevelParameteriv = nullptr;
+PFNGLGETTEXTUREPARAMETERFVPROC glGetTextureParameterfv = nullptr;
+PFNGLGETTEXTUREPARAMETERIIVPROC glGetTextureParameterIiv = nullptr;
+PFNGLGETTEXTUREPARAMETERIUIVPROC glGetTextureParameterIuiv = nullptr;
+PFNGLGETTEXTUREPARAMETERIVPROC glGetTextureParameteriv = nullptr;
+PFNGLCREATEVERTEXARRAYSPROC glCreateVertexArrays = nullptr;
+PFNGLDISABLEVERTEXARRAYATTRIBPROC glDisableVertexArrayAttrib = nullptr;
+PFNGLENABLEVERTEXARRAYATTRIBPROC glEnableVertexArrayAttrib = nullptr;
+PFNGLVERTEXARRAYELEMENTBUFFERPROC glVertexArrayElementBuffer = nullptr;
+PFNGLVERTEXARRAYVERTEXBUFFERPROC glVertexArrayVertexBuffer = nullptr;
+PFNGLVERTEXARRAYVERTEXBUFFERSPROC glVertexArrayVertexBuffers = nullptr;
+PFNGLVERTEXARRAYATTRIBBINDINGPROC glVertexArrayAttribBinding = nullptr;
+PFNGLVERTEXARRAYATTRIBFORMATPROC glVertexArrayAttribFormat = nullptr;
+PFNGLVERTEXARRAYATTRIBIFORMATPROC glVertexArrayAttribIFormat = nullptr;
+PFNGLVERTEXARRAYATTRIBLFORMATPROC glVertexArrayAttribLFormat = nullptr;
+PFNGLVERTEXARRAYBINDINGDIVISORPROC glVertexArrayBindingDivisor = nullptr;
+PFNGLGETVERTEXARRAYIVPROC glGetVertexArrayiv = nullptr;
+PFNGLGETVERTEXARRAYINDEXEDIVPROC glGetVertexArrayIndexediv = nullptr;
+PFNGLGETVERTEXARRAYINDEXED64IVPROC glGetVertexArrayIndexed64iv = nullptr;
+PFNGLCREATESAMPLERSPROC glCreateSamplers = nullptr;
+PFNGLCREATEPROGRAMPIPELINESPROC glCreateProgramPipelines = nullptr;
+PFNGLCREATEQUERIESPROC glCreateQueries = nullptr;
+PFNGLGETQUERYBUFFEROBJECTI64VPROC glGetQueryBufferObjecti64v = nullptr;
+PFNGLGETQUERYBUFFEROBJECTIVPROC glGetQueryBufferObjectiv = nullptr;
+PFNGLGETQUERYBUFFEROBJECTUI64VPROC glGetQueryBufferObjectui64v = nullptr;
+PFNGLGETQUERYBUFFEROBJECTUIVPROC glGetQueryBufferObjectuiv = nullptr;
+PFNGLMEMORYBARRIERBYREGIONPROC glMemoryBarrierByRegion = nullptr;
+PFNGLGETTEXTURESUBIMAGEPROC glGetTextureSubImage = nullptr;
+PFNGLGETCOMPRESSEDTEXTURESUBIMAGEPROC glGetCompressedTextureSubImage = nullptr;
+PFNGLGETGRAPHICSRESETSTATUSPROC glGetGraphicsResetStatus = nullptr;
+PFNGLGETNCOMPRESSEDTEXIMAGEPROC glGetnCompressedTexImage = nullptr;
+PFNGLGETNTEXIMAGEPROC glGetnTexImage = nullptr;
+PFNGLGETNUNIFORMDVPROC glGetnUniformdv = nullptr;
+PFNGLGETNUNIFORMFVPROC glGetnUniformfv = nullptr;
+PFNGLGETNUNIFORMIVPROC glGetnUniformiv = nullptr;
+PFNGLGETNUNIFORMUIVPROC glGetnUniformuiv = nullptr;
+PFNGLREADNPIXELSPROC glReadnPixels = nullptr;
+PFNGLGETNMAPDVPROC glGetnMapdv = nullptr;
+PFNGLGETNMAPFVPROC glGetnMapfv = nullptr;
+PFNGLGETNMAPIVPROC glGetnMapiv = nullptr;
+PFNGLGETNPIXELMAPFVPROC glGetnPixelMapfv = nullptr;
+PFNGLGETNPIXELMAPUIVPROC glGetnPixelMapuiv = nullptr;
+PFNGLGETNPIXELMAPUSVPROC glGetnPixelMapusv = nullptr;
+PFNGLGETNPOLYGONSTIPPLEPROC glGetnPolygonStipple = nullptr;
+PFNGLGETNCOLORTABLEPROC glGetnColorTable = nullptr;
+PFNGLGETNCONVOLUTIONFILTERPROC glGetnConvolutionFilter = nullptr;
+PFNGLGETNSEPARABLEFILTERPROC glGetnSeparableFilter = nullptr;
+PFNGLGETNHISTOGRAMPROC glGetnHistogram = nullptr;
+PFNGLGETNMINMAXPROC glGetnMinmax = nullptr;
+PFNGLTEXTUREBARRIERPROC glTextureBarrier = nullptr;
+
+// GL_VERSION_4_6
+PFNGLSPECIALIZESHADERPROC glSpecializeShader = nullptr;
+PFNGLMULTIDRAWARRAYSINDIRECTCOUNTPROC glMultiDrawArraysIndirectCount = nullptr;
+PFNGLMULTIDRAWELEMENTSINDIRECTCOUNTPROC glMultiDrawElementsIndirectCount = nullptr;
+PFNGLPOLYGONOFFSETCLAMPPROC glPolygonOffsetClamp = nullptr;
-#if LL_LINUX_NV_GL_HEADERS
-// linux nvidia headers. these define these differently to mesa's. ugh.
-PFNGLACTIVETEXTUREARBPROC glActiveTextureARB = NULL;
-PFNGLCLIENTACTIVETEXTUREARBPROC glClientActiveTextureARB = NULL;
-PFNGLDRAWRANGEELEMENTSPROC glDrawRangeElements = NULL;
-#endif // LL_LINUX_NV_GL_HEADERS
#endif
LLGLManager gGLManager;
@@ -406,42 +957,12 @@ LLGLManager gGLManager;
LLGLManager::LLGLManager() :
mInited(FALSE),
mIsDisabled(FALSE),
-
- mHasMultitexture(FALSE),
- mHasATIMemInfo(FALSE),
- mHasAMDAssociations(FALSE),
- mHasNVXMemInfo(FALSE),
- mNumTextureUnits(1),
- mHasMipMapGeneration(FALSE),
- mHasCompressedTextures(FALSE),
- mHasFramebufferObject(FALSE),
mMaxSamples(0),
- mHasBlendFuncSeparate(FALSE),
- mHasSync(FALSE),
- mHasVertexBufferObject(FALSE),
- mHasVertexArrayObject(FALSE),
- mHasMapBufferRange(FALSE),
- mHasFlushBufferRange(FALSE),
- mHasPBuffer(FALSE),
- mNumTextureImageUnits(0),
- mHasOcclusionQuery(FALSE),
- mHasTimerQuery(FALSE),
- mHasOcclusionQuery2(FALSE),
- mHasPointParameters(FALSE),
- mHasDrawBuffers(FALSE),
- mHasTextureRectangle(FALSE),
- mHasTextureMultisample(FALSE),
- mHasTransformFeedback(FALSE),
+ mNumTextureImageUnits(1),
mMaxSampleMaskWords(0),
mMaxColorTextureSamples(0),
mMaxDepthTextureSamples(0),
mMaxIntegerSamples(0),
-
- mHasAnisotropic(FALSE),
- mHasARBEnvCombine(FALSE),
- mHasCubeMap(FALSE),
- mHasDebugOutput(FALSE),
-
mIsAMD(FALSE),
mIsNVIDIA(FALSE),
mIsIntel(FALSE),
@@ -449,9 +970,6 @@ LLGLManager::LLGLManager() :
mIsMobileGF(FALSE),
#endif
mHasRequirements(TRUE),
-
- mHasSeparateSpecularColor(FALSE),
-
mDriverVersionMajor(1),
mDriverVersionMinor(0),
mDriverVersionRelease(0),
@@ -469,7 +987,6 @@ LLGLManager::LLGLManager() :
//---------------------------------------------------------------------
void LLGLManager::initWGL()
{
- mHasPBuffer = FALSE;
#if LL_WINDOWS && !LL_MESA_HEADLESS
if (!glh_init_extensions("WGL_ARB_pixel_format"))
{
@@ -508,10 +1025,6 @@ void LLGLManager::initWGL()
{
LL_WARNS("RenderInit") << "No ARB WGL render texture extensions" << LL_ENDL;
}
-
- mHasPBuffer = ExtensionExists("WGL_ARB_pbuffer", gGLHExts.mSysExts) &&
- ExtensionExists("WGL_ARB_render_texture", gGLHExts.mSysExts) &&
- ExtensionExists("WGL_ARB_pixel_format", gGLHExts.mSysExts);
#endif
}
@@ -523,9 +1036,7 @@ bool LLGLManager::initGL()
LL_ERRS("RenderInit") << "Calling init on LLGLManager after already initialized!" << LL_ENDL;
}
- stop_glerror();
-
-#if LL_WINDOWS
+#if 0 && LL_WINDOWS
if (!glGetStringi)
{
glGetStringi = (PFNGLGETSTRINGIPROC) GLH_EXT_GET_PROC_ADDRESS("glGetStringi");
@@ -560,8 +1071,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));
@@ -582,12 +1091,14 @@ bool LLGLManager::initGL()
{
parse_glsl_version(mGLSLVersionMajor, mGLSLVersionMinor);
-#if LL_DARWIN
+#if 0 && LL_DARWIN
+ // TODO maybe switch to using a core profile for GL 3.2?
+ // https://stackoverflow.com/a/19868861
//never use GLSL greater than 1.20 on OSX
- if (mGLSLVersionMajor > 1 || mGLSLVersionMinor >= 30)
+ if (mGLSLVersionMajor > 1 || mGLSLVersionMinor > 30)
{
mGLSLVersionMajor = 1;
- mGLSLVersionMinor = 20;
+ mGLSLVersionMinor = 30;
}
#endif
}
@@ -631,10 +1142,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;
@@ -670,23 +1179,6 @@ bool LLGLManager::initGL()
}
#endif
- if (mHasATIMemInfo && mVRAM == 0)
- { //ask the gl how much vram is free at startup and attempt to use no more than half of that
- S32 meminfo[4];
- glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, meminfo);
-
- mVRAM = meminfo[0] / 1024;
- LL_WARNS("RenderInit") << "VRAM Detected (ATIMemInfo):" << mVRAM << LL_ENDL;
- }
-
- if (mHasNVXMemInfo && mVRAM == 0)
- {
- S32 dedicated_memory;
- glGetIntegerv(GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX, &dedicated_memory);
- mVRAM = dedicated_memory/1024;
- LL_WARNS("RenderInit") << "VRAM Detected (NVXMemInfo):" << mVRAM << LL_ENDL;
- }
-
#if LL_WINDOWS
if (mVRAM < 256)
{
@@ -712,72 +1204,20 @@ bool LLGLManager::initGL()
mVRAM = old_vram;
}
- stop_glerror();
-
- GLint num_tex_image_units;
- glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &num_tex_image_units);
- mNumTextureImageUnits = llmin(num_tex_image_units, 32);
+ glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &mNumTextureImageUnits);
+ glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &mMaxColorTextureSamples);
+ glGetIntegerv(GL_MAX_DEPTH_TEXTURE_SAMPLES, &mMaxDepthTextureSamples);
+ glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &mMaxIntegerSamples);
+ glGetIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &mMaxSampleMaskWords);
+ glGetIntegerv(GL_MAX_SAMPLES, &mMaxSamples);
- if (mHasMultitexture)
+ if (mGLVersion >= 4.59f)
{
- if (LLRender::sGLCoreProfile)
- {
- mNumTextureUnits = llmin(mNumTextureImageUnits, MAX_GL_TEXTURE_UNITS);
- }
- else
- {
- GLint num_tex_units;
- glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &num_tex_units);
- mNumTextureUnits = llmin(num_tex_units, (GLint)MAX_GL_TEXTURE_UNITS);
- if (mIsIntel)
- {
- mNumTextureUnits = llmin(mNumTextureUnits, 2);
- }
- }
+ glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY, &mMaxAnisotropy);
}
- else
- {
- mHasRequirements = FALSE;
- // We don't support cards that don't support the GL_ARB_multitexture extension
- LL_WARNS("RenderInit") << "GL Drivers do not support GL_ARB_multitexture" << LL_ENDL;
- return false;
- }
-
- if (!mHasFramebufferObject)
- {
- mHasRequirements = FALSE;
-
- LL_WARNS("RenderInit") << "GL Drivers do not support GL_ARB_framebuffer_object" << LL_ENDL;
- return false;
- }
-
- stop_glerror();
-
- if (mHasTextureMultisample)
- {
- glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &mMaxColorTextureSamples);
- glGetIntegerv(GL_MAX_DEPTH_TEXTURE_SAMPLES, &mMaxDepthTextureSamples);
- glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &mMaxIntegerSamples);
- glGetIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &mMaxSampleMaskWords);
- }
-
- stop_glerror();
-
- //HACK always disable texture multisample, use FXAA instead
- mHasTextureMultisample = FALSE;
-
- if (mHasFramebufferObject)
- {
- glGetIntegerv(GL_MAX_SAMPLES, &mMaxSamples);
- }
-
- stop_glerror();
-
initGLStates();
- stop_glerror();
-
return true;
}
@@ -879,62 +1319,22 @@ void LLGLManager::asLLSD(LLSD& info)
info["vram"] = mVRAM;
- // Extensions used by everyone
- info["has_multitexture"] = mHasMultitexture;
- info["has_ati_mem_info"] = mHasATIMemInfo;
- info["has_nvx_mem_info"] = mHasNVXMemInfo;
- info["num_texture_units"] = mNumTextureUnits;
- info["has_mip_map_generation"] = mHasMipMapGeneration;
- info["has_compressed_textures"] = mHasCompressedTextures;
- info["has_framebuffer_object"] = mHasFramebufferObject;
+ // OpenGL limits
info["max_samples"] = mMaxSamples;
- info["has_blend_func_separate"] = mHasBlendFuncSeparate;
-
- // ARB Extensions
- info["has_vertex_buffer_object"] = mHasVertexBufferObject;
- info["has_vertex_array_object"] = mHasVertexArrayObject;
- info["has_sync"] = mHasSync;
- info["has_map_buffer_range"] = mHasMapBufferRange;
- info["has_flush_buffer_range"] = mHasFlushBufferRange;
- info["has_pbuffer"] = mHasPBuffer;
- info["has_shader_objects"] = std::string("Assumed TRUE"); // was mHasShaderObjects;
- info["has_vertex_shader"] = std::string("Assumed TRUE"); // was mHasVertexShader;
- info["has_fragment_shader"] = std::string("Assumed TRUE"); // was mHasFragmentShader;
info["num_texture_image_units"] = mNumTextureImageUnits;
- info["has_occlusion_query"] = mHasOcclusionQuery;
- info["has_timer_query"] = mHasTimerQuery;
- info["has_occlusion_query2"] = mHasOcclusionQuery2;
- info["has_point_parameters"] = mHasPointParameters;
- info["has_draw_buffers"] = mHasDrawBuffers;
- info["has_depth_clamp"] = mHasDepthClamp;
- info["has_texture_rectangle"] = mHasTextureRectangle;
- info["has_texture_multisample"] = mHasTextureMultisample;
- info["has_transform_feedback"] = mHasTransformFeedback;
info["max_sample_mask_words"] = mMaxSampleMaskWords;
info["max_color_texture_samples"] = mMaxColorTextureSamples;
info["max_depth_texture_samples"] = mMaxDepthTextureSamples;
info["max_integer_samples"] = mMaxIntegerSamples;
+ info["max_vertex_range"] = mGLMaxVertexRange;
+ info["max_index_range"] = mGLMaxIndexRange;
+ info["max_texture_size"] = mGLMaxTextureSize;
- // Other extensions.
- info["has_anisotropic"] = mHasAnisotropic;
- info["has_arb_env_combine"] = mHasARBEnvCombine;
- info["has_cube_map"] = mHasCubeMap;
- info["has_debug_output"] = mHasDebugOutput;
- info["has_srgb_texture"] = mHassRGBTexture;
- info["has_srgb_framebuffer"] = mHassRGBFramebuffer;
- info["has_texture_srgb_decode"] = mHasTexturesRGBDecode;
-
- // Vendor-specific extensions
+ // Which vendor
info["is_ati"] = mIsAMD; // note, do not rename is_ati to is_amd without coordinating with DW
info["is_nvidia"] = mIsNVIDIA;
info["is_intel"] = mIsIntel;
- // Other fields
- info["has_requirements"] = mHasRequirements;
- info["has_separate_specular_color"] = mHasSeparateSpecularColor;
- info["max_vertex_range"] = mGLMaxVertexRange;
- info["max_index_range"] = mGLMaxIndexRange;
- info["max_texture_size"] = mGLMaxTextureSize;
info["gl_renderer"] = mGLRenderer;
}
@@ -953,498 +1353,876 @@ void LLGLManager::shutdownGL()
void LLGLManager::initExtensions()
{
-#if LL_MESA_HEADLESS
-# ifdef GL_ARB_multitexture
- mHasMultitexture = TRUE;
-# else
- mHasMultitexture = FALSE;
-# endif // GL_ARB_multitexture
-# ifdef GL_ARB_texture_env_combine
- mHasARBEnvCombine = TRUE;
-# else
- mHasARBEnvCombine = FALSE;
-# endif // GL_ARB_texture_env_combine
-# ifdef GL_ARB_texture_compression
- mHasCompressedTextures = TRUE;
-# else
- mHasCompressedTextures = FALSE;
-# endif // GL_ARB_texture_compression
-# ifdef GL_ARB_vertex_buffer_object
- mHasVertexBufferObject = TRUE;
-# else
- mHasVertexBufferObject = FALSE;
-# endif // GL_ARB_vertex_buffer_object
-# ifdef GL_EXT_framebuffer_object
- mHasFramebufferObject = TRUE;
-# else
- mHasFramebufferObject = FALSE;
-# endif // GL_EXT_framebuffer_object
-# ifdef GL_ARB_draw_buffers
- mHasDrawBuffers = TRUE;
-#else
- mHasDrawBuffers = FALSE;
-# endif // GL_ARB_draw_buffers
-# if defined(GL_NV_depth_clamp) || defined(GL_ARB_depth_clamp)
- mHasDepthClamp = TRUE;
-#else
- mHasDepthClamp = FALSE;
-#endif // defined(GL_NV_depth_clamp) || defined(GL_ARB_depth_clamp)
-# if GL_EXT_blend_func_separate
- mHasBlendFuncSeparate = TRUE;
-#else
- mHasBlendFuncSeparate = FALSE;
-# endif // GL_EXT_blend_func_separate
- mHasMipMapGeneration = FALSE;
- mHasSeparateSpecularColor = FALSE;
- mHasAnisotropic = FALSE;
- mHasCubeMap = FALSE;
- mHasOcclusionQuery = FALSE;
- mHasPointParameters = FALSE;
- mHasTextureRectangle = FALSE;
-#else // LL_MESA_HEADLESS //important, gGLHExts.mSysExts is uninitialized until after glh_init_extensions is called
- mHasMultitexture = glh_init_extensions("GL_ARB_multitexture");
- mHasATIMemInfo = ExtensionExists("GL_ATI_meminfo", gGLHExts.mSysExts); //Basic AMD method, also see mHasAMDAssociations
- mHasNVXMemInfo = ExtensionExists("GL_NVX_gpu_memory_info", gGLHExts.mSysExts);
- mHasSeparateSpecularColor = glh_init_extensions("GL_EXT_separate_specular_color");
- mHasAnisotropic = glh_init_extensions("GL_EXT_texture_filter_anisotropic");
- glh_init_extensions("GL_ARB_texture_cube_map");
- mHasCubeMap = ExtensionExists("GL_ARB_texture_cube_map", gGLHExts.mSysExts);
- mHasARBEnvCombine = ExtensionExists("GL_ARB_texture_env_combine", gGLHExts.mSysExts);
- mHasCompressedTextures = glh_init_extensions("GL_ARB_texture_compression");
- mHasOcclusionQuery = ExtensionExists("GL_ARB_occlusion_query", gGLHExts.mSysExts);
- mHasTimerQuery = ExtensionExists("GL_ARB_timer_query", gGLHExts.mSysExts);
- mHasOcclusionQuery2 = ExtensionExists("GL_ARB_occlusion_query2", gGLHExts.mSysExts);
- mHasVertexBufferObject = ExtensionExists("GL_ARB_vertex_buffer_object", gGLHExts.mSysExts);
- mHasVertexArrayObject = ExtensionExists("GL_ARB_vertex_array_object", gGLHExts.mSysExts);
- mHasSync = ExtensionExists("GL_ARB_sync", gGLHExts.mSysExts);
- mHasMapBufferRange = ExtensionExists("GL_ARB_map_buffer_range", gGLHExts.mSysExts);
- mHasFlushBufferRange = ExtensionExists("GL_APPLE_flush_buffer_range", gGLHExts.mSysExts);
- // NOTE: Using extensions breaks reflections when Shadows are set to projector. See: SL-16727
- //mHasDepthClamp = ExtensionExists("GL_ARB_depth_clamp", gGLHExts.mSysExts) || ExtensionExists("GL_NV_depth_clamp", gGLHExts.mSysExts);
- mHasDepthClamp = FALSE;
- // mask out FBO support when packed_depth_stencil isn't there 'cause we need it for LLRenderTarget -Brad
-#ifdef GL_ARB_framebuffer_object
- mHasFramebufferObject = ExtensionExists("GL_ARB_framebuffer_object", gGLHExts.mSysExts);
-#else
- mHasFramebufferObject = ExtensionExists("GL_EXT_framebuffer_object", gGLHExts.mSysExts) &&
- ExtensionExists("GL_EXT_framebuffer_blit", gGLHExts.mSysExts) &&
- ExtensionExists("GL_EXT_framebuffer_multisample", gGLHExts.mSysExts) &&
- ExtensionExists("GL_EXT_packed_depth_stencil", gGLHExts.mSysExts);
-#endif
-#ifdef GL_EXT_texture_sRGB
- mHassRGBTexture = ExtensionExists("GL_EXT_texture_sRGB", gGLHExts.mSysExts);
-#endif
-
-#ifdef GL_ARB_framebuffer_sRGB
- mHassRGBFramebuffer = ExtensionExists("GL_ARB_framebuffer_sRGB", gGLHExts.mSysExts);
-#else
- mHassRGBFramebuffer = ExtensionExists("GL_EXT_framebuffer_sRGB", gGLHExts.mSysExts);
-#endif
-
-#ifdef GL_EXT_texture_sRGB_decode
- mHasTexturesRGBDecode = ExtensionExists("GL_EXT_texture_sRGB_decode", gGLHExts.mSysExts);
-#else
- mHasTexturesRGBDecode = ExtensionExists("GL_ARB_texture_sRGB_decode", gGLHExts.mSysExts);
-#endif
-
- mHasMipMapGeneration = mHasFramebufferObject || mGLVersion >= 1.4f;
-
- mHasDrawBuffers = ExtensionExists("GL_ARB_draw_buffers", gGLHExts.mSysExts);
- mHasBlendFuncSeparate = ExtensionExists("GL_EXT_blend_func_separate", gGLHExts.mSysExts);
- mHasTextureRectangle = ExtensionExists("GL_ARB_texture_rectangle", gGLHExts.mSysExts);
- mHasTextureMultisample = ExtensionExists("GL_ARB_texture_multisample", gGLHExts.mSysExts);
- mHasDebugOutput = ExtensionExists("GL_ARB_debug_output", gGLHExts.mSysExts);
- mHasTransformFeedback = mGLVersion >= 4.f ? TRUE : FALSE;
-#if !LL_DARWIN
- mHasPointParameters = ExtensionExists("GL_ARB_point_parameters", gGLHExts.mSysExts);
-#endif
+#if LL_DARWIN
+ GLint num_extensions = 0;
+ std::string all_extensions{""};
+ glGetIntegerv(GL_NUM_EXTENSIONS, &num_extensions);
+ for(GLint i = 0; i < num_extensions; ++i) {
+ char const * extension = (char const *)glGetStringi(GL_EXTENSIONS, i);
+ all_extensions += extension;
+ all_extensions += ' ';
+ }
+ if (num_extensions)
+ {
+ all_extensions += "GL_ARB_multitexture GL_ARB_texture_cube_map GL_ARB_texture_compression "; // These are in 3.2 core, but not listed by OSX
+ gGLHExts.mSysExts = strdup(all_extensions.data());
+ }
#endif
-#if LL_LINUX
- LL_INFOS() << "initExtensions() checking shell variables to adjust features..." << LL_ENDL;
- // Our extension support for the Linux Client is very young with some
- // potential driver gotchas, so offer a semi-secret way to turn it off.
- if (getenv("LL_GL_NOEXT"))
- {
- //mHasMultitexture = FALSE; // NEEDED!
- mHasDepthClamp = FALSE;
- mHasARBEnvCombine = FALSE;
- mHasCompressedTextures = FALSE;
- mHasVertexBufferObject = FALSE;
- mHasFramebufferObject = FALSE;
- mHasDrawBuffers = FALSE;
- mHasBlendFuncSeparate = FALSE;
- mHasMipMapGeneration = FALSE;
- mHasSeparateSpecularColor = FALSE;
- mHasAnisotropic = FALSE;
- mHasCubeMap = FALSE;
- mHasOcclusionQuery = FALSE;
- mHasPointParameters = FALSE;
- LL_WARNS("RenderInit") << "GL extension support DISABLED via LL_GL_NOEXT" << LL_ENDL;
- }
- else if (getenv("LL_GL_BASICEXT")) /* Flawfinder: ignore */
- {
- // This switch attempts to turn off all support for exotic
- // extensions which I believe correspond to fatal driver
- // bug reports. This should be the default until we get a
- // proper blacklist/whitelist on Linux.
- mHasMipMapGeneration = FALSE;
- mHasAnisotropic = FALSE;
- //mHasCubeMap = FALSE; // apparently fatal on Intel 915 & similar
- //mHasOcclusionQuery = FALSE; // source of many ATI system hangs
- mHasBlendFuncSeparate = FALSE;
- LL_WARNS("RenderInit") << "GL extension support forced to SIMPLE level via LL_GL_BASICEXT" << LL_ENDL;
- }
- if (getenv("LL_GL_BLACKLIST")) /* Flawfinder: ignore */
- {
- // This lets advanced troubleshooters disable specific
- // GL extensions to isolate problems with their hardware.
- // SL-28126
- const char *const blacklist = getenv("LL_GL_BLACKLIST"); /* Flawfinder: ignore */
- LL_WARNS("RenderInit") << "GL extension support partially disabled via LL_GL_BLACKLIST: " << blacklist << LL_ENDL;
- if (strchr(blacklist,'a')) mHasARBEnvCombine = FALSE;
- if (strchr(blacklist,'b')) mHasCompressedTextures = FALSE;
- if (strchr(blacklist,'c')) mHasVertexBufferObject = FALSE;
- if (strchr(blacklist,'d')) mHasMipMapGeneration = FALSE;//S
-// if (strchr(blacklist,'f')) mHasNVVertexArrayRange = FALSE;//S
-// if (strchr(blacklist,'g')) mHasNVFence = FALSE;//S
- if (strchr(blacklist,'h')) mHasSeparateSpecularColor = FALSE;
- if (strchr(blacklist,'i')) mHasAnisotropic = FALSE;//S
- if (strchr(blacklist,'j')) mHasCubeMap = FALSE;//S
-// if (strchr(blacklist,'k')) mHasATIVAO = FALSE;//S
- if (strchr(blacklist,'l')) mHasOcclusionQuery = FALSE;
- if (strchr(blacklist,'p')) mHasPointParameters = FALSE;//S
- if (strchr(blacklist,'q')) mHasFramebufferObject = FALSE;//S
- if (strchr(blacklist,'r')) mHasDrawBuffers = FALSE;//S
- if (strchr(blacklist,'s')) mHasTextureRectangle = FALSE;
- if (strchr(blacklist,'t')) mHasBlendFuncSeparate = FALSE;//S
- if (strchr(blacklist,'u')) mHasDepthClamp = FALSE;
-
- }
-#endif // LL_LINUX
-
- if (!mHasMultitexture)
- {
- LL_INFOS("RenderInit") << "Couldn't initialize multitexturing" << LL_ENDL;
- }
- if (!mHasMipMapGeneration)
- {
- LL_INFOS("RenderInit") << "Couldn't initialize mipmap generation" << LL_ENDL;
- }
- if (!mHasARBEnvCombine)
- {
- LL_INFOS("RenderInit") << "Couldn't initialize GL_ARB_texture_env_combine" << LL_ENDL;
- }
- if (!mHasSeparateSpecularColor)
- {
- LL_INFOS("RenderInit") << "Couldn't initialize separate specular color" << LL_ENDL;
- }
- if (!mHasAnisotropic)
- {
- LL_INFOS("RenderInit") << "Couldn't initialize anisotropic filtering" << LL_ENDL;
- }
- if (!mHasCompressedTextures)
- {
- LL_INFOS("RenderInit") << "Couldn't initialize GL_ARB_texture_compression" << LL_ENDL;
- }
- if (!mHasOcclusionQuery)
- {
- LL_INFOS("RenderInit") << "Couldn't initialize GL_ARB_occlusion_query" << LL_ENDL;
- }
- if (!mHasOcclusionQuery2)
- {
- LL_INFOS("RenderInit") << "Couldn't initialize GL_ARB_occlusion_query2" << LL_ENDL;
- }
- if (!mHasPointParameters)
- {
- LL_INFOS("RenderInit") << "Couldn't initialize GL_ARB_point_parameters" << LL_ENDL;
- }
- if (!mHasBlendFuncSeparate)
- {
- LL_INFOS("RenderInit") << "Couldn't initialize GL_EXT_blend_func_separate" << LL_ENDL;
- }
- if (!mHasDrawBuffers)
- {
- LL_INFOS("RenderInit") << "Couldn't initialize GL_ARB_draw_buffers" << LL_ENDL;
- }
-
- // Disable certain things due to known bugs
- if (mIsIntel && mHasMipMapGeneration)
- {
- LL_INFOS("RenderInit") << "Disabling mip-map generation for Intel GPUs" << LL_ENDL;
- mHasMipMapGeneration = FALSE;
- }
+ // NOTE: version checks against mGLVersion should bias down by 0.01 because of F32 errors
+
+ // OpenGL 4.x capabilities
+ mHasCubeMapArray = mGLVersion >= 3.99f;
+ mHasTransformFeedback = mGLVersion >= 3.99f;
+ mHasDebugOutput = mGLVersion >= 4.29f;
- // Misc
+ // Misc
glGetIntegerv(GL_MAX_ELEMENTS_VERTICES, (GLint*) &mGLMaxVertexRange);
glGetIntegerv(GL_MAX_ELEMENTS_INDICES, (GLint*) &mGLMaxIndexRange);
glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint*) &mGLMaxTextureSize);
+ mInited = TRUE;
+
#if (LL_WINDOWS || LL_LINUX) && !LL_MESA_HEADLESS
LL_DEBUGS("RenderInit") << "GL Probe: Getting symbols" << LL_ENDL;
- if (mHasVertexBufferObject)
- {
- glBindBufferARB = (PFNGLBINDBUFFERARBPROC)GLH_EXT_GET_PROC_ADDRESS("glBindBufferARB");
- if (glBindBufferARB)
- {
- glDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC)GLH_EXT_GET_PROC_ADDRESS("glDeleteBuffersARB");
- glGenBuffersARB = (PFNGLGENBUFFERSARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGenBuffersARB");
- glIsBufferARB = (PFNGLISBUFFERARBPROC)GLH_EXT_GET_PROC_ADDRESS("glIsBufferARB");
- glBufferDataARB = (PFNGLBUFFERDATAARBPROC)GLH_EXT_GET_PROC_ADDRESS("glBufferDataARB");
- glBufferSubDataARB = (PFNGLBUFFERSUBDATAARBPROC)GLH_EXT_GET_PROC_ADDRESS("glBufferSubDataARB");
- glGetBufferSubDataARB = (PFNGLGETBUFFERSUBDATAARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetBufferSubDataARB");
- glMapBufferARB = (PFNGLMAPBUFFERARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMapBufferARB");
- glUnmapBufferARB = (PFNGLUNMAPBUFFERARBPROC)GLH_EXT_GET_PROC_ADDRESS("glUnmapBufferARB");
- glGetBufferParameterivARB = (PFNGLGETBUFFERPARAMETERIVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetBufferParameterivARB");
- glGetBufferPointervARB = (PFNGLGETBUFFERPOINTERVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetBufferPointervARB");
- }
- else
- {
- mHasVertexBufferObject = FALSE;
- }
- }
- if (mHasVertexArrayObject)
- {
- glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC) GLH_EXT_GET_PROC_ADDRESS("glBindVertexArray");
- glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSPROC) GLH_EXT_GET_PROC_ADDRESS("glDeleteVertexArrays");
- glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC) GLH_EXT_GET_PROC_ADDRESS("glGenVertexArrays");
- glIsVertexArray = (PFNGLISVERTEXARRAYPROC) GLH_EXT_GET_PROC_ADDRESS("glIsVertexArray");
- }
- if (mHasSync)
- {
- glFenceSync = (PFNGLFENCESYNCPROC) GLH_EXT_GET_PROC_ADDRESS("glFenceSync");
- glIsSync = (PFNGLISSYNCPROC) GLH_EXT_GET_PROC_ADDRESS("glIsSync");
- glDeleteSync = (PFNGLDELETESYNCPROC) GLH_EXT_GET_PROC_ADDRESS("glDeleteSync");
- glClientWaitSync = (PFNGLCLIENTWAITSYNCPROC) GLH_EXT_GET_PROC_ADDRESS("glClientWaitSync");
- glWaitSync = (PFNGLWAITSYNCPROC) GLH_EXT_GET_PROC_ADDRESS("glWaitSync");
- glGetInteger64v = (PFNGLGETINTEGER64VPROC) GLH_EXT_GET_PROC_ADDRESS("glGetInteger64v");
- glGetSynciv = (PFNGLGETSYNCIVPROC) GLH_EXT_GET_PROC_ADDRESS("glGetSynciv");
- }
- if (mHasMapBufferRange)
- {
- glMapBufferRange = (PFNGLMAPBUFFERRANGEPROC) GLH_EXT_GET_PROC_ADDRESS("glMapBufferRange");
- glFlushMappedBufferRange = (PFNGLFLUSHMAPPEDBUFFERRANGEPROC) GLH_EXT_GET_PROC_ADDRESS("glFlushMappedBufferRange");
- }
- if (mHasFramebufferObject)
- {
- LL_INFOS() << "initExtensions() FramebufferObject-related procs..." << LL_ENDL;
- glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC) GLH_EXT_GET_PROC_ADDRESS("glIsRenderbuffer");
- glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC) GLH_EXT_GET_PROC_ADDRESS("glBindRenderbuffer");
- glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC) GLH_EXT_GET_PROC_ADDRESS("glDeleteRenderbuffers");
- glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC) GLH_EXT_GET_PROC_ADDRESS("glGenRenderbuffers");
- glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC) GLH_EXT_GET_PROC_ADDRESS("glRenderbufferStorage");
- glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC) GLH_EXT_GET_PROC_ADDRESS("glGetRenderbufferParameteriv");
- glIsFramebuffer = (PFNGLISFRAMEBUFFERPROC) GLH_EXT_GET_PROC_ADDRESS("glIsFramebuffer");
- glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC) GLH_EXT_GET_PROC_ADDRESS("glBindFramebuffer");
- glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC) GLH_EXT_GET_PROC_ADDRESS("glDeleteFramebuffers");
- glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC) GLH_EXT_GET_PROC_ADDRESS("glGenFramebuffers");
- glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC) GLH_EXT_GET_PROC_ADDRESS("glCheckFramebufferStatus");
- glFramebufferTexture1D = (PFNGLFRAMEBUFFERTEXTURE1DPROC) GLH_EXT_GET_PROC_ADDRESS("glFramebufferTexture1D");
- glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC) GLH_EXT_GET_PROC_ADDRESS("glFramebufferTexture2D");
- glFramebufferTexture3D = (PFNGLFRAMEBUFFERTEXTURE3DPROC) GLH_EXT_GET_PROC_ADDRESS("glFramebufferTexture3D");
- glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC) GLH_EXT_GET_PROC_ADDRESS("glFramebufferRenderbuffer");
- glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) GLH_EXT_GET_PROC_ADDRESS("glGetFramebufferAttachmentParameteriv");
- glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC) GLH_EXT_GET_PROC_ADDRESS("glGenerateMipmap");
- glBlitFramebuffer = (PFNGLBLITFRAMEBUFFERPROC) GLH_EXT_GET_PROC_ADDRESS("glBlitFramebuffer");
- glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) GLH_EXT_GET_PROC_ADDRESS("glRenderbufferStorageMultisample");
- glFramebufferTextureLayer = (PFNGLFRAMEBUFFERTEXTURELAYERPROC) GLH_EXT_GET_PROC_ADDRESS("glFramebufferTextureLayer");
- }
- if (mHasDrawBuffers)
- {
- glDrawBuffersARB = (PFNGLDRAWBUFFERSARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDrawBuffersARB");
- }
- if (mHasBlendFuncSeparate)
- {
- glBlendFuncSeparateEXT = (PFNGLBLENDFUNCSEPARATEEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glBlendFuncSeparateEXT");
- }
- if (mHasTextureMultisample)
- {
- glTexImage2DMultisample = (PFNGLTEXIMAGE2DMULTISAMPLEPROC) GLH_EXT_GET_PROC_ADDRESS("glTexImage2DMultisample");
- glTexImage3DMultisample = (PFNGLTEXIMAGE3DMULTISAMPLEPROC) GLH_EXT_GET_PROC_ADDRESS("glTexImage3DMultisample");
- glGetMultisamplefv = (PFNGLGETMULTISAMPLEFVPROC) GLH_EXT_GET_PROC_ADDRESS("glGetMultisamplefv");
- glSampleMaski = (PFNGLSAMPLEMASKIPROC) GLH_EXT_GET_PROC_ADDRESS("glSampleMaski");
- }
- if (mHasTransformFeedback)
- {
- glBeginTransformFeedback = (PFNGLBEGINTRANSFORMFEEDBACKPROC) GLH_EXT_GET_PROC_ADDRESS("glBeginTransformFeedback");
- glEndTransformFeedback = (PFNGLENDTRANSFORMFEEDBACKPROC) GLH_EXT_GET_PROC_ADDRESS("glEndTransformFeedback");
- glTransformFeedbackVaryings = (PFNGLTRANSFORMFEEDBACKVARYINGSPROC) GLH_EXT_GET_PROC_ADDRESS("glTransformFeedbackVaryings");
- glBindBufferRange = (PFNGLBINDBUFFERRANGEPROC) GLH_EXT_GET_PROC_ADDRESS("glBindBufferRange");
- glBindBufferBase = (PFNGLBINDBUFFERBASEPROC) GLH_EXT_GET_PROC_ADDRESS("glBindBufferBase");
- }
- if (mHasDebugOutput)
- {
- glDebugMessageControlARB = (PFNGLDEBUGMESSAGECONTROLARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDebugMessageControlARB");
- glDebugMessageInsertARB = (PFNGLDEBUGMESSAGEINSERTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDebugMessageInsertARB");
- glDebugMessageCallbackARB = (PFNGLDEBUGMESSAGECALLBACKARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDebugMessageCallbackARB");
- glGetDebugMessageLogARB = (PFNGLGETDEBUGMESSAGELOGARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetDebugMessageLogARB");
- }
-#if (!LL_LINUX) || LL_LINUX_NV_GL_HEADERS
- // This is expected to be a static symbol on Linux GL implementations, except if we use the nvidia headers - bah
- glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawRangeElements");
- if (!glDrawRangeElements)
- {
- mGLMaxVertexRange = 0;
- mGLMaxIndexRange = 0;
- }
-#endif // !LL_LINUX || LL_LINUX_NV_GL_HEADERS
-#if LL_LINUX_NV_GL_HEADERS
- // nvidia headers are critically different from mesa-esque
- glActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC)GLH_EXT_GET_PROC_ADDRESS("glActiveTextureARB");
- glClientActiveTextureARB = (PFNGLCLIENTACTIVETEXTUREARBPROC)GLH_EXT_GET_PROC_ADDRESS("glClientActiveTextureARB");
-#endif // LL_LINUX_NV_GL_HEADERS
-
- if (mHasOcclusionQuery)
- {
- LL_INFOS() << "initExtensions() OcclusionQuery-related procs..." << LL_ENDL;
- glGenQueriesARB = (PFNGLGENQUERIESARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGenQueriesARB");
- glDeleteQueriesARB = (PFNGLDELETEQUERIESARBPROC)GLH_EXT_GET_PROC_ADDRESS("glDeleteQueriesARB");
- glIsQueryARB = (PFNGLISQUERYARBPROC)GLH_EXT_GET_PROC_ADDRESS("glIsQueryARB");
- glBeginQueryARB = (PFNGLBEGINQUERYARBPROC)GLH_EXT_GET_PROC_ADDRESS("glBeginQueryARB");
- glEndQueryARB = (PFNGLENDQUERYARBPROC)GLH_EXT_GET_PROC_ADDRESS("glEndQueryARB");
- glGetQueryivARB = (PFNGLGETQUERYIVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetQueryivARB");
- glGetQueryObjectivARB = (PFNGLGETQUERYOBJECTIVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetQueryObjectivARB");
- glGetQueryObjectuivARB = (PFNGLGETQUERYOBJECTUIVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetQueryObjectuivARB");
- }
- if (mHasTimerQuery)
- {
- LL_INFOS() << "initExtensions() TimerQuery-related procs..." << LL_ENDL;
- glQueryCounter = (PFNGLQUERYCOUNTERPROC) GLH_EXT_GET_PROC_ADDRESS("glQueryCounter");
- glGetQueryObjecti64v = (PFNGLGETQUERYOBJECTI64VPROC) GLH_EXT_GET_PROC_ADDRESS("glGetQueryObjecti64v");
- glGetQueryObjectui64v = (PFNGLGETQUERYOBJECTUI64VPROC) GLH_EXT_GET_PROC_ADDRESS("glGetQueryObjectui64v");
- }
- if (mHasPointParameters)
- {
- LL_INFOS() << "initExtensions() PointParameters-related procs..." << LL_ENDL;
- glPointParameterfARB = (PFNGLPOINTPARAMETERFARBPROC)GLH_EXT_GET_PROC_ADDRESS("glPointParameterfARB");
- glPointParameterfvARB = (PFNGLPOINTPARAMETERFVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glPointParameterfvARB");
- }
-
- // Assume shader capabilities
- glDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDeleteObjectARB");
- glGetHandleARB = (PFNGLGETHANDLEARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetHandleARB");
- glDetachObjectARB = (PFNGLDETACHOBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDetachObjectARB");
- glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glCreateShaderObjectARB");
- glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC) GLH_EXT_GET_PROC_ADDRESS("glShaderSourceARB");
- glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC) GLH_EXT_GET_PROC_ADDRESS("glCompileShaderARB");
- glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glCreateProgramObjectARB");
- glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glAttachObjectARB");
- glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC) GLH_EXT_GET_PROC_ADDRESS("glLinkProgramARB");
- glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUseProgramObjectARB");
- glValidateProgramARB = (PFNGLVALIDATEPROGRAMARBPROC) GLH_EXT_GET_PROC_ADDRESS("glValidateProgramARB");
- glUniform1fARB = (PFNGLUNIFORM1FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform1fARB");
- glUniform2fARB = (PFNGLUNIFORM2FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform2fARB");
- glUniform3fARB = (PFNGLUNIFORM3FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform3fARB");
- glUniform4fARB = (PFNGLUNIFORM4FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform4fARB");
- glUniform1iARB = (PFNGLUNIFORM1IARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform1iARB");
- glUniform2iARB = (PFNGLUNIFORM2IARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform2iARB");
- glUniform3iARB = (PFNGLUNIFORM3IARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform3iARB");
- glUniform4iARB = (PFNGLUNIFORM4IARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform4iARB");
- glUniform1fvARB = (PFNGLUNIFORM1FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform1fvARB");
- glUniform2fvARB = (PFNGLUNIFORM2FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform2fvARB");
- glUniform3fvARB = (PFNGLUNIFORM3FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform3fvARB");
- glUniform4fvARB = (PFNGLUNIFORM4FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform4fvARB");
- glUniform1ivARB = (PFNGLUNIFORM1IVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform1ivARB");
- glUniform2ivARB = (PFNGLUNIFORM2IVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform2ivARB");
- glUniform3ivARB = (PFNGLUNIFORM3IVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform3ivARB");
- glUniform4ivARB = (PFNGLUNIFORM4IVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform4ivARB");
- glUniformMatrix2fvARB = (PFNGLUNIFORMMATRIX2FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix2fvARB");
- glUniformMatrix3fvARB = (PFNGLUNIFORMMATRIX3FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix3fvARB");
- glUniformMatrix3x4fv = (PFNGLUNIFORMMATRIX3X4FVPROC) GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix3x4fv");
- glUniformMatrix4fvARB = (PFNGLUNIFORMMATRIX4FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix4fvARB");
- glGetObjectParameterfvARB = (PFNGLGETOBJECTPARAMETERFVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetObjectParameterfvARB");
- glGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetObjectParameterivARB");
- glGetInfoLogARB = (PFNGLGETINFOLOGARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetInfoLogARB");
- glGetAttachedObjectsARB = (PFNGLGETATTACHEDOBJECTSARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetAttachedObjectsARB");
- glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetUniformLocationARB");
- glGetActiveUniformARB = (PFNGLGETACTIVEUNIFORMARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetActiveUniformARB");
- glGetUniformfvARB = (PFNGLGETUNIFORMFVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetUniformfvARB");
- glGetUniformivARB = (PFNGLGETUNIFORMIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetUniformivARB");
- glGetShaderSourceARB = (PFNGLGETSHADERSOURCEARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetShaderSourceARB");
-
- LL_INFOS() << "initExtensions() VertexShader-related procs..." << LL_ENDL;
-
- // nSight doesn't support use of ARB funcs that have been normalized in the API
- if (!LLRender::sNsightDebugSupport)
+
+#if LL_WINDOWS
+ // WGL_AMD_gpu_association
+ wglGetGPUIDsAMD = (PFNWGLGETGPUIDSAMDPROC)GLH_EXT_GET_PROC_ADDRESS("wglGetGPUIDsAMD");
+ wglGetGPUInfoAMD = (PFNWGLGETGPUINFOAMDPROC)GLH_EXT_GET_PROC_ADDRESS("wglGetGPUInfoAMD");
+ wglGetContextGPUIDAMD = (PFNWGLGETCONTEXTGPUIDAMDPROC)GLH_EXT_GET_PROC_ADDRESS("wglGetContextGPUIDAMD");
+ wglCreateAssociatedContextAMD = (PFNWGLCREATEASSOCIATEDCONTEXTAMDPROC)GLH_EXT_GET_PROC_ADDRESS("wglCreateAssociatedContextAMD");
+ wglCreateAssociatedContextAttribsAMD = (PFNWGLCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC)GLH_EXT_GET_PROC_ADDRESS("wglCreateAssociatedContextAttribsAMD");
+ wglDeleteAssociatedContextAMD = (PFNWGLDELETEASSOCIATEDCONTEXTAMDPROC)GLH_EXT_GET_PROC_ADDRESS("wglDeleteAssociatedContextAMD");
+ wglMakeAssociatedContextCurrentAMD = (PFNWGLMAKEASSOCIATEDCONTEXTCURRENTAMDPROC)GLH_EXT_GET_PROC_ADDRESS("wglMakeAssociatedContextCurrentAMD");
+ wglGetCurrentAssociatedContextAMD = (PFNWGLGETCURRENTASSOCIATEDCONTEXTAMDPROC)GLH_EXT_GET_PROC_ADDRESS("wglGetCurrentAssociatedContextAMD");
+ wglBlitContextFramebufferAMD = (PFNWGLBLITCONTEXTFRAMEBUFFERAMDPROC)GLH_EXT_GET_PROC_ADDRESS("wglBlitContextFramebufferAMD");
+
+ // WGL_EXT_swap_control
+ wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)GLH_EXT_GET_PROC_ADDRESS("wglSwapIntervalEXT");
+ wglGetSwapIntervalEXT = (PFNWGLGETSWAPINTERVALEXTPROC)GLH_EXT_GET_PROC_ADDRESS("wglGetSwapIntervalEXT");
+
+ // WGL_ARB_create_context
+ wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)GLH_EXT_GET_PROC_ADDRESS("wglCreateContextAttribsARB");
+#endif
+
+
+ // Load entire OpenGL API through GetProcAddress, leaving sections beyond mGLVersion unloaded
+
+ // GL_VERSION_1_2
+ if (mGLVersion < 1.19f)
{
- glGetAttribLocationARB = (PFNGLGETATTRIBLOCATIONARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetAttribLocationARB");
- glBindAttribLocationARB = (PFNGLBINDATTRIBLOCATIONARBPROC) GLH_EXT_GET_PROC_ADDRESS("glBindAttribLocationARB");
+ return;
}
- else
+ glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawRangeElements");
+ glTexImage3D = (PFNGLTEXIMAGE3DPROC)GLH_EXT_GET_PROC_ADDRESS("glTexImage3D");
+ glTexSubImage3D = (PFNGLTEXSUBIMAGE3DPROC)GLH_EXT_GET_PROC_ADDRESS("glTexSubImage3D");
+ glCopyTexSubImage3D = (PFNGLCOPYTEXSUBIMAGE3DPROC)GLH_EXT_GET_PROC_ADDRESS("glCopyTexSubImage3D");
+
+
+ // GL_VERSION_1_3
+ if (mGLVersion < 1.29f)
{
- glGetAttribLocationARB = (PFNGLGETATTRIBLOCATIONARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetAttribLocation");
- glBindAttribLocationARB = (PFNGLBINDATTRIBLOCATIONARBPROC) GLH_EXT_GET_PROC_ADDRESS("glBindAttribLocation");
+ return;
}
-
- glGetActiveAttribARB = (PFNGLGETACTIVEATTRIBARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetActiveAttribARB");
- glVertexAttrib1dARB = (PFNGLVERTEXATTRIB1DARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1dARB");
- glVertexAttrib1dvARB = (PFNGLVERTEXATTRIB1DVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1dvARB");
- glVertexAttrib1fARB = (PFNGLVERTEXATTRIB1FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1fARB");
- glVertexAttrib1fvARB = (PFNGLVERTEXATTRIB1FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1fvARB");
- glVertexAttrib1sARB = (PFNGLVERTEXATTRIB1SARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1sARB");
- glVertexAttrib1svARB = (PFNGLVERTEXATTRIB1SVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1svARB");
- glVertexAttrib2dARB = (PFNGLVERTEXATTRIB2DARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2dARB");
- glVertexAttrib2dvARB = (PFNGLVERTEXATTRIB2DVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2dvARB");
- glVertexAttrib2fARB = (PFNGLVERTEXATTRIB2FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2fARB");
- glVertexAttrib2fvARB = (PFNGLVERTEXATTRIB2FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2fvARB");
- glVertexAttrib2sARB = (PFNGLVERTEXATTRIB2SARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2sARB");
- glVertexAttrib2svARB = (PFNGLVERTEXATTRIB2SVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2svARB");
- glVertexAttrib3dARB = (PFNGLVERTEXATTRIB3DARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3dARB");
- glVertexAttrib3dvARB = (PFNGLVERTEXATTRIB3DVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3dvARB");
- glVertexAttrib3fARB = (PFNGLVERTEXATTRIB3FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3fARB");
- glVertexAttrib3fvARB = (PFNGLVERTEXATTRIB3FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3fvARB");
- glVertexAttrib3sARB = (PFNGLVERTEXATTRIB3SARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3sARB");
- glVertexAttrib3svARB = (PFNGLVERTEXATTRIB3SVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3svARB");
- glVertexAttrib4nbvARB = (PFNGLVERTEXATTRIB4NBVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nbvARB");
- glVertexAttrib4nivARB = (PFNGLVERTEXATTRIB4NIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nivARB");
- glVertexAttrib4nsvARB = (PFNGLVERTEXATTRIB4NSVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nsvARB");
- glVertexAttrib4nubARB = (PFNGLVERTEXATTRIB4NUBARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nubARB");
- glVertexAttrib4nubvARB = (PFNGLVERTEXATTRIB4NUBVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nubvARB");
- glVertexAttrib4nuivARB = (PFNGLVERTEXATTRIB4NUIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nuivARB");
- glVertexAttrib4nusvARB = (PFNGLVERTEXATTRIB4NUSVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nusvARB");
- glVertexAttrib4bvARB = (PFNGLVERTEXATTRIB4BVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4bvARB");
- glVertexAttrib4dARB = (PFNGLVERTEXATTRIB4DARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4dARB");
- glVertexAttrib4dvARB = (PFNGLVERTEXATTRIB4DVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4dvARB");
- glVertexAttrib4fARB = (PFNGLVERTEXATTRIB4FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4fARB");
- glVertexAttrib4fvARB = (PFNGLVERTEXATTRIB4FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4fvARB");
- glVertexAttrib4ivARB = (PFNGLVERTEXATTRIB4IVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4ivARB");
- glVertexAttrib4sARB = (PFNGLVERTEXATTRIB4SARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4sARB");
- glVertexAttrib4svARB = (PFNGLVERTEXATTRIB4SVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4svARB");
- glVertexAttrib4ubvARB = (PFNGLVERTEXATTRIB4UBVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4ubvARB");
- glVertexAttrib4uivARB = (PFNGLVERTEXATTRIB4UIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4uivARB");
- glVertexAttrib4usvARB = (PFNGLVERTEXATTRIB4USVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4usvARB");
- glVertexAttribPointerARB = (PFNGLVERTEXATTRIBPOINTERARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttribPointerARB");
- glVertexAttribIPointer = (PFNGLVERTEXATTRIBIPOINTERPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttribIPointer");
- glEnableVertexAttribArrayARB = (PFNGLENABLEVERTEXATTRIBARRAYARBPROC) GLH_EXT_GET_PROC_ADDRESS("glEnableVertexAttribArrayARB");
- glDisableVertexAttribArrayARB = (PFNGLDISABLEVERTEXATTRIBARRAYARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDisableVertexAttribArrayARB");
- glProgramStringARB = (PFNGLPROGRAMSTRINGARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramStringARB");
- glBindProgramARB = (PFNGLBINDPROGRAMARBPROC) GLH_EXT_GET_PROC_ADDRESS("glBindProgramARB");
- glDeleteProgramsARB = (PFNGLDELETEPROGRAMSARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDeleteProgramsARB");
- glGenProgramsARB = (PFNGLGENPROGRAMSARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGenProgramsARB");
- glProgramEnvParameter4dARB = (PFNGLPROGRAMENVPARAMETER4DARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramEnvParameter4dARB");
- glProgramEnvParameter4dvARB = (PFNGLPROGRAMENVPARAMETER4DVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramEnvParameter4dvARB");
- glProgramEnvParameter4fARB = (PFNGLPROGRAMENVPARAMETER4FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramEnvParameter4fARB");
- glProgramEnvParameter4fvARB = (PFNGLPROGRAMENVPARAMETER4FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramEnvParameter4fvARB");
- glProgramLocalParameter4dARB = (PFNGLPROGRAMLOCALPARAMETER4DARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramLocalParameter4dARB");
- glProgramLocalParameter4dvARB = (PFNGLPROGRAMLOCALPARAMETER4DVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramLocalParameter4dvARB");
- glProgramLocalParameter4fARB = (PFNGLPROGRAMLOCALPARAMETER4FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramLocalParameter4fARB");
- glProgramLocalParameter4fvARB = (PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramLocalParameter4fvARB");
- glGetProgramEnvParameterdvARB = (PFNGLGETPROGRAMENVPARAMETERDVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetProgramEnvParameterdvARB");
- glGetProgramEnvParameterfvARB = (PFNGLGETPROGRAMENVPARAMETERFVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetProgramEnvParameterfvARB");
- glGetProgramLocalParameterdvARB = (PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetProgramLocalParameterdvARB");
- glGetProgramLocalParameterfvARB = (PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetProgramLocalParameterfvARB");
- glGetProgramivARB = (PFNGLGETPROGRAMIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetProgramivARB");
- glGetProgramStringARB = (PFNGLGETPROGRAMSTRINGARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetProgramStringARB");
- glGetVertexAttribdvARB = (PFNGLGETVERTEXATTRIBDVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribdvARB");
- glGetVertexAttribfvARB = (PFNGLGETVERTEXATTRIBFVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribfvARB");
- glGetVertexAttribivARB = (PFNGLGETVERTEXATTRIBIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribivARB");
- glGetVertexAttribPointervARB = (PFNGLGETVERTEXATTRIBPOINTERVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glgetVertexAttribPointervARB");
- glIsProgramARB = (PFNGLISPROGRAMARBPROC) GLH_EXT_GET_PROC_ADDRESS("glIsProgramARB");
-
- LL_DEBUGS("RenderInit") << "GL Probe: Got symbols" << LL_ENDL;
+ glActiveTexture = (PFNGLACTIVETEXTUREPROC)GLH_EXT_GET_PROC_ADDRESS("glActiveTexture");
+ glSampleCoverage = (PFNGLSAMPLECOVERAGEPROC)GLH_EXT_GET_PROC_ADDRESS("glSampleCoverage");
+ glCompressedTexImage3D = (PFNGLCOMPRESSEDTEXIMAGE3DPROC)GLH_EXT_GET_PROC_ADDRESS("glCompressedTexImage3D");
+ glCompressedTexImage2D = (PFNGLCOMPRESSEDTEXIMAGE2DPROC)GLH_EXT_GET_PROC_ADDRESS("glCompressedTexImage2D");
+ glCompressedTexImage1D = (PFNGLCOMPRESSEDTEXIMAGE1DPROC)GLH_EXT_GET_PROC_ADDRESS("glCompressedTexImage1D");
+ glCompressedTexSubImage3D = (PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC)GLH_EXT_GET_PROC_ADDRESS("glCompressedTexSubImage3D");
+ glCompressedTexSubImage2D = (PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC)GLH_EXT_GET_PROC_ADDRESS("glCompressedTexSubImage2D");
+ glCompressedTexSubImage1D = (PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC)GLH_EXT_GET_PROC_ADDRESS("glCompressedTexSubImage1D");
+ glGetCompressedTexImage = (PFNGLGETCOMPRESSEDTEXIMAGEPROC)GLH_EXT_GET_PROC_ADDRESS("glGetCompressedTexImage");
+ glClientActiveTexture = (PFNGLCLIENTACTIVETEXTUREPROC)GLH_EXT_GET_PROC_ADDRESS("glClientActiveTexture");
+ glMultiTexCoord1d = (PFNGLMULTITEXCOORD1DPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord1d");
+ glMultiTexCoord1dv = (PFNGLMULTITEXCOORD1DVPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord1dv");
+ glMultiTexCoord1f = (PFNGLMULTITEXCOORD1FPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord1f");
+ glMultiTexCoord1fv = (PFNGLMULTITEXCOORD1FVPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord1fv");
+ glMultiTexCoord1i = (PFNGLMULTITEXCOORD1IPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord1i");
+ glMultiTexCoord1iv = (PFNGLMULTITEXCOORD1IVPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord1iv");
+ glMultiTexCoord1s = (PFNGLMULTITEXCOORD1SPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord1s");
+ glMultiTexCoord1sv = (PFNGLMULTITEXCOORD1SVPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord1sv");
+ glMultiTexCoord2d = (PFNGLMULTITEXCOORD2DPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord2d");
+ glMultiTexCoord2dv = (PFNGLMULTITEXCOORD2DVPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord2dv");
+ glMultiTexCoord2f = (PFNGLMULTITEXCOORD2FPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord2f");
+ glMultiTexCoord2fv = (PFNGLMULTITEXCOORD2FVPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord2fv");
+ glMultiTexCoord2i = (PFNGLMULTITEXCOORD2IPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord2i");
+ glMultiTexCoord2iv = (PFNGLMULTITEXCOORD2IVPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord2iv");
+ glMultiTexCoord2s = (PFNGLMULTITEXCOORD2SPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord2s");
+ glMultiTexCoord2sv = (PFNGLMULTITEXCOORD2SVPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord2sv");
+ glMultiTexCoord3d = (PFNGLMULTITEXCOORD3DPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord3d");
+ glMultiTexCoord3dv = (PFNGLMULTITEXCOORD3DVPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord3dv");
+ glMultiTexCoord3f = (PFNGLMULTITEXCOORD3FPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord3f");
+ glMultiTexCoord3fv = (PFNGLMULTITEXCOORD3FVPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord3fv");
+ glMultiTexCoord3i = (PFNGLMULTITEXCOORD3IPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord3i");
+ glMultiTexCoord3iv = (PFNGLMULTITEXCOORD3IVPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord3iv");
+ glMultiTexCoord3s = (PFNGLMULTITEXCOORD3SPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord3s");
+ glMultiTexCoord3sv = (PFNGLMULTITEXCOORD3SVPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord3sv");
+ glMultiTexCoord4d = (PFNGLMULTITEXCOORD4DPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord4d");
+ glMultiTexCoord4dv = (PFNGLMULTITEXCOORD4DVPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord4dv");
+ glMultiTexCoord4f = (PFNGLMULTITEXCOORD4FPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord4f");
+ glMultiTexCoord4fv = (PFNGLMULTITEXCOORD4FVPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord4fv");
+ glMultiTexCoord4i = (PFNGLMULTITEXCOORD4IPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord4i");
+ glMultiTexCoord4iv = (PFNGLMULTITEXCOORD4IVPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord4iv");
+ glMultiTexCoord4s = (PFNGLMULTITEXCOORD4SPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord4s");
+ glMultiTexCoord4sv = (PFNGLMULTITEXCOORD4SVPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord4sv");
+ glLoadTransposeMatrixf = (PFNGLLOADTRANSPOSEMATRIXFPROC)GLH_EXT_GET_PROC_ADDRESS("glLoadTransposeMatrixf");
+ glLoadTransposeMatrixd = (PFNGLLOADTRANSPOSEMATRIXDPROC)GLH_EXT_GET_PROC_ADDRESS("glLoadTransposeMatrixd");
+ glMultTransposeMatrixf = (PFNGLMULTTRANSPOSEMATRIXFPROC)GLH_EXT_GET_PROC_ADDRESS("glMultTransposeMatrixf");
+ glMultTransposeMatrixd = (PFNGLMULTTRANSPOSEMATRIXDPROC)GLH_EXT_GET_PROC_ADDRESS("glMultTransposeMatrixd");
+
+ // GL_VERSION_1_4
+ if (mGLVersion < 1.39f)
+ {
+ return;
+ }
+ glBlendFuncSeparate = (PFNGLBLENDFUNCSEPARATEPROC)GLH_EXT_GET_PROC_ADDRESS("glBlendFuncSeparate");
+ glMultiDrawArrays = (PFNGLMULTIDRAWARRAYSPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiDrawArrays");
+ glMultiDrawElements = (PFNGLMULTIDRAWELEMENTSPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiDrawElements");
+ glPointParameterf = (PFNGLPOINTPARAMETERFPROC)GLH_EXT_GET_PROC_ADDRESS("glPointParameterf");
+ glPointParameterfv = (PFNGLPOINTPARAMETERFVPROC)GLH_EXT_GET_PROC_ADDRESS("glPointParameterfv");
+ glPointParameteri = (PFNGLPOINTPARAMETERIPROC)GLH_EXT_GET_PROC_ADDRESS("glPointParameteri");
+ glPointParameteriv = (PFNGLPOINTPARAMETERIVPROC)GLH_EXT_GET_PROC_ADDRESS("glPointParameteriv");
+ glFogCoordf = (PFNGLFOGCOORDFPROC)GLH_EXT_GET_PROC_ADDRESS("glFogCoordf");
+ glFogCoordfv = (PFNGLFOGCOORDFVPROC)GLH_EXT_GET_PROC_ADDRESS("glFogCoordfv");
+ glFogCoordd = (PFNGLFOGCOORDDPROC)GLH_EXT_GET_PROC_ADDRESS("glFogCoordd");
+ glFogCoorddv = (PFNGLFOGCOORDDVPROC)GLH_EXT_GET_PROC_ADDRESS("glFogCoorddv");
+ glFogCoordPointer = (PFNGLFOGCOORDPOINTERPROC)GLH_EXT_GET_PROC_ADDRESS("glFogCoordPointer");
+ glSecondaryColor3b = (PFNGLSECONDARYCOLOR3BPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3b");
+ glSecondaryColor3bv = (PFNGLSECONDARYCOLOR3BVPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3bv");
+ glSecondaryColor3d = (PFNGLSECONDARYCOLOR3DPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3d");
+ glSecondaryColor3dv = (PFNGLSECONDARYCOLOR3DVPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3dv");
+ glSecondaryColor3f = (PFNGLSECONDARYCOLOR3FPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3f");
+ glSecondaryColor3fv = (PFNGLSECONDARYCOLOR3FVPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3fv");
+ glSecondaryColor3i = (PFNGLSECONDARYCOLOR3IPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3i");
+ glSecondaryColor3iv = (PFNGLSECONDARYCOLOR3IVPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3iv");
+ glSecondaryColor3s = (PFNGLSECONDARYCOLOR3SPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3s");
+ glSecondaryColor3sv = (PFNGLSECONDARYCOLOR3SVPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3sv");
+ glSecondaryColor3ub = (PFNGLSECONDARYCOLOR3UBPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3ub");
+ glSecondaryColor3ubv = (PFNGLSECONDARYCOLOR3UBVPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3ubv");
+ glSecondaryColor3ui = (PFNGLSECONDARYCOLOR3UIPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3ui");
+ glSecondaryColor3uiv = (PFNGLSECONDARYCOLOR3UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3uiv");
+ glSecondaryColor3us = (PFNGLSECONDARYCOLOR3USPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3us");
+ glSecondaryColor3usv = (PFNGLSECONDARYCOLOR3USVPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3usv");
+ glSecondaryColorPointer = (PFNGLSECONDARYCOLORPOINTERPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColorPointer");
+ glWindowPos2d = (PFNGLWINDOWPOS2DPROC)GLH_EXT_GET_PROC_ADDRESS("glWindowPos2d");
+ glWindowPos2dv = (PFNGLWINDOWPOS2DVPROC)GLH_EXT_GET_PROC_ADDRESS("glWindowPos2dv");
+ glWindowPos2f = (PFNGLWINDOWPOS2FPROC)GLH_EXT_GET_PROC_ADDRESS("glWindowPos2f");
+ glWindowPos2fv = (PFNGLWINDOWPOS2FVPROC)GLH_EXT_GET_PROC_ADDRESS("glWindowPos2fv");
+ glWindowPos2i = (PFNGLWINDOWPOS2IPROC)GLH_EXT_GET_PROC_ADDRESS("glWindowPos2i");
+ glWindowPos2iv = (PFNGLWINDOWPOS2IVPROC)GLH_EXT_GET_PROC_ADDRESS("glWindowPos2iv");
+ glWindowPos2s = (PFNGLWINDOWPOS2SPROC)GLH_EXT_GET_PROC_ADDRESS("glWindowPos2s");
+ glWindowPos2sv = (PFNGLWINDOWPOS2SVPROC)GLH_EXT_GET_PROC_ADDRESS("glWindowPos2sv");
+ glWindowPos3d = (PFNGLWINDOWPOS3DPROC)GLH_EXT_GET_PROC_ADDRESS("glWindowPos3d");
+ glWindowPos3dv = (PFNGLWINDOWPOS3DVPROC)GLH_EXT_GET_PROC_ADDRESS("glWindowPos3dv");
+ glWindowPos3f = (PFNGLWINDOWPOS3FPROC)GLH_EXT_GET_PROC_ADDRESS("glWindowPos3f");
+ glWindowPos3fv = (PFNGLWINDOWPOS3FVPROC)GLH_EXT_GET_PROC_ADDRESS("glWindowPos3fv");
+ glWindowPos3i = (PFNGLWINDOWPOS3IPROC)GLH_EXT_GET_PROC_ADDRESS("glWindowPos3i");
+ glWindowPos3iv = (PFNGLWINDOWPOS3IVPROC)GLH_EXT_GET_PROC_ADDRESS("glWindowPos3iv");
+ glWindowPos3s = (PFNGLWINDOWPOS3SPROC)GLH_EXT_GET_PROC_ADDRESS("glWindowPos3s");
+ glWindowPos3sv = (PFNGLWINDOWPOS3SVPROC)GLH_EXT_GET_PROC_ADDRESS("glWindowPos3sv");
+
+ // GL_VERSION_1_5
+ if (mGLVersion < 1.49f)
+ {
+ return;
+ }
+ glGenQueries = (PFNGLGENQUERIESPROC)GLH_EXT_GET_PROC_ADDRESS("glGenQueries");
+ glDeleteQueries = (PFNGLDELETEQUERIESPROC)GLH_EXT_GET_PROC_ADDRESS("glDeleteQueries");
+ glIsQuery = (PFNGLISQUERYPROC)GLH_EXT_GET_PROC_ADDRESS("glIsQuery");
+ glBeginQuery = (PFNGLBEGINQUERYPROC)GLH_EXT_GET_PROC_ADDRESS("glBeginQuery");
+ glEndQuery = (PFNGLENDQUERYPROC)GLH_EXT_GET_PROC_ADDRESS("glEndQuery");
+ glGetQueryiv = (PFNGLGETQUERYIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetQueryiv");
+ glGetQueryObjectiv = (PFNGLGETQUERYOBJECTIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetQueryObjectiv");
+ glGetQueryObjectuiv = (PFNGLGETQUERYOBJECTUIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetQueryObjectuiv");
+ glBindBuffer = (PFNGLBINDBUFFERPROC)GLH_EXT_GET_PROC_ADDRESS("glBindBuffer");
+ glDeleteBuffers = (PFNGLDELETEBUFFERSPROC)GLH_EXT_GET_PROC_ADDRESS("glDeleteBuffers");
+ glGenBuffers = (PFNGLGENBUFFERSPROC)GLH_EXT_GET_PROC_ADDRESS("glGenBuffers");
+ glIsBuffer = (PFNGLISBUFFERPROC)GLH_EXT_GET_PROC_ADDRESS("glIsBuffer");
+ glBufferData = (PFNGLBUFFERDATAPROC)GLH_EXT_GET_PROC_ADDRESS("glBufferData");
+ glBufferSubData = (PFNGLBUFFERSUBDATAPROC)GLH_EXT_GET_PROC_ADDRESS("glBufferSubData");
+ glGetBufferSubData = (PFNGLGETBUFFERSUBDATAPROC)GLH_EXT_GET_PROC_ADDRESS("glGetBufferSubData");
+ glMapBuffer = (PFNGLMAPBUFFERPROC)GLH_EXT_GET_PROC_ADDRESS("glMapBuffer");
+ glUnmapBuffer = (PFNGLUNMAPBUFFERPROC)GLH_EXT_GET_PROC_ADDRESS("glUnmapBuffer");
+ glGetBufferParameteriv = (PFNGLGETBUFFERPARAMETERIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetBufferParameteriv");
+ glGetBufferPointerv = (PFNGLGETBUFFERPOINTERVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetBufferPointerv");
+
+ // GL_VERSION_2_0
+ if (mGLVersion < 1.9f)
+ {
+ return;
+ }
+ glBlendEquationSeparate = (PFNGLBLENDEQUATIONSEPARATEPROC)GLH_EXT_GET_PROC_ADDRESS("glBlendEquationSeparate");
+ glDrawBuffers = (PFNGLDRAWBUFFERSPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawBuffers");
+ glStencilOpSeparate = (PFNGLSTENCILOPSEPARATEPROC)GLH_EXT_GET_PROC_ADDRESS("glStencilOpSeparate");
+ glStencilFuncSeparate = (PFNGLSTENCILFUNCSEPARATEPROC)GLH_EXT_GET_PROC_ADDRESS("glStencilFuncSeparate");
+ glStencilMaskSeparate = (PFNGLSTENCILMASKSEPARATEPROC)GLH_EXT_GET_PROC_ADDRESS("glStencilMaskSeparate");
+ glAttachShader = (PFNGLATTACHSHADERPROC)GLH_EXT_GET_PROC_ADDRESS("glAttachShader");
+ glBindAttribLocation = (PFNGLBINDATTRIBLOCATIONPROC)GLH_EXT_GET_PROC_ADDRESS("glBindAttribLocation");
+ glCompileShader = (PFNGLCOMPILESHADERPROC)GLH_EXT_GET_PROC_ADDRESS("glCompileShader");
+ glCreateProgram = (PFNGLCREATEPROGRAMPROC)GLH_EXT_GET_PROC_ADDRESS("glCreateProgram");
+ glCreateShader = (PFNGLCREATESHADERPROC)GLH_EXT_GET_PROC_ADDRESS("glCreateShader");
+ glDeleteProgram = (PFNGLDELETEPROGRAMPROC)GLH_EXT_GET_PROC_ADDRESS("glDeleteProgram");
+ glDeleteShader = (PFNGLDELETESHADERPROC)GLH_EXT_GET_PROC_ADDRESS("glDeleteShader");
+ glDetachShader = (PFNGLDETACHSHADERPROC)GLH_EXT_GET_PROC_ADDRESS("glDetachShader");
+ glDisableVertexAttribArray = (PFNGLDISABLEVERTEXATTRIBARRAYPROC)GLH_EXT_GET_PROC_ADDRESS("glDisableVertexAttribArray");
+ glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC)GLH_EXT_GET_PROC_ADDRESS("glEnableVertexAttribArray");
+ glGetActiveAttrib = (PFNGLGETACTIVEATTRIBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetActiveAttrib");
+ glGetActiveUniform = (PFNGLGETACTIVEUNIFORMPROC)GLH_EXT_GET_PROC_ADDRESS("glGetActiveUniform");
+ glGetAttachedShaders = (PFNGLGETATTACHEDSHADERSPROC)GLH_EXT_GET_PROC_ADDRESS("glGetAttachedShaders");
+ glGetAttribLocation = (PFNGLGETATTRIBLOCATIONPROC)GLH_EXT_GET_PROC_ADDRESS("glGetAttribLocation");
+ glGetProgramiv = (PFNGLGETPROGRAMIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetProgramiv");
+ glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC)GLH_EXT_GET_PROC_ADDRESS("glGetProgramInfoLog");
+ glGetShaderiv = (PFNGLGETSHADERIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetShaderiv");
+ glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)GLH_EXT_GET_PROC_ADDRESS("glGetShaderInfoLog");
+ glGetShaderSource = (PFNGLGETSHADERSOURCEPROC)GLH_EXT_GET_PROC_ADDRESS("glGetShaderSource");
+ glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC)GLH_EXT_GET_PROC_ADDRESS("glGetUniformLocation");
+ glGetUniformfv = (PFNGLGETUNIFORMFVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetUniformfv");
+ glGetUniformiv = (PFNGLGETUNIFORMIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetUniformiv");
+ glGetVertexAttribdv = (PFNGLGETVERTEXATTRIBDVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribdv");
+ glGetVertexAttribfv = (PFNGLGETVERTEXATTRIBFVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribfv");
+ glGetVertexAttribiv = (PFNGLGETVERTEXATTRIBIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribiv");
+ glGetVertexAttribPointerv = (PFNGLGETVERTEXATTRIBPOINTERVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribPointerv");
+ glIsProgram = (PFNGLISPROGRAMPROC)GLH_EXT_GET_PROC_ADDRESS("glIsProgram");
+ glIsShader = (PFNGLISSHADERPROC)GLH_EXT_GET_PROC_ADDRESS("glIsShader");
+ glLinkProgram = (PFNGLLINKPROGRAMPROC)GLH_EXT_GET_PROC_ADDRESS("glLinkProgram");
+ glShaderSource = (PFNGLSHADERSOURCEPROC)GLH_EXT_GET_PROC_ADDRESS("glShaderSource");
+ glUseProgram = (PFNGLUSEPROGRAMPROC)GLH_EXT_GET_PROC_ADDRESS("glUseProgram");
+ glUniform1f = (PFNGLUNIFORM1FPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform1f");
+ glUniform2f = (PFNGLUNIFORM2FPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform2f");
+ glUniform3f = (PFNGLUNIFORM3FPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform3f");
+ glUniform4f = (PFNGLUNIFORM4FPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform4f");
+ glUniform1i = (PFNGLUNIFORM1IPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform1i");
+ glUniform2i = (PFNGLUNIFORM2IPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform2i");
+ glUniform3i = (PFNGLUNIFORM3IPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform3i");
+ glUniform4i = (PFNGLUNIFORM4IPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform4i");
+ glUniform1fv = (PFNGLUNIFORM1FVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform1fv");
+ glUniform2fv = (PFNGLUNIFORM2FVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform2fv");
+ glUniform3fv = (PFNGLUNIFORM3FVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform3fv");
+ glUniform4fv = (PFNGLUNIFORM4FVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform4fv");
+ glUniform1iv = (PFNGLUNIFORM1IVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform1iv");
+ glUniform2iv = (PFNGLUNIFORM2IVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform2iv");
+ glUniform3iv = (PFNGLUNIFORM3IVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform3iv");
+ glUniform4iv = (PFNGLUNIFORM4IVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform4iv");
+ glUniformMatrix2fv = (PFNGLUNIFORMMATRIX2FVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix2fv");
+ glUniformMatrix3fv = (PFNGLUNIFORMMATRIX3FVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix3fv");
+ glUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix4fv");
+ glValidateProgram = (PFNGLVALIDATEPROGRAMPROC)GLH_EXT_GET_PROC_ADDRESS("glValidateProgram");
+ glVertexAttrib1d = (PFNGLVERTEXATTRIB1DPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1d");
+ glVertexAttrib1dv = (PFNGLVERTEXATTRIB1DVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1dv");
+ glVertexAttrib1f = (PFNGLVERTEXATTRIB1FPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1f");
+ glVertexAttrib1fv = (PFNGLVERTEXATTRIB1FVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1fv");
+ glVertexAttrib1s = (PFNGLVERTEXATTRIB1SPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1s");
+ glVertexAttrib1sv = (PFNGLVERTEXATTRIB1SVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1sv");
+ glVertexAttrib2d = (PFNGLVERTEXATTRIB2DPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2d");
+ glVertexAttrib2dv = (PFNGLVERTEXATTRIB2DVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2dv");
+ glVertexAttrib2f = (PFNGLVERTEXATTRIB2FPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2f");
+ glVertexAttrib2fv = (PFNGLVERTEXATTRIB2FVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2fv");
+ glVertexAttrib2s = (PFNGLVERTEXATTRIB2SPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2s");
+ glVertexAttrib2sv = (PFNGLVERTEXATTRIB2SVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2sv");
+ glVertexAttrib3d = (PFNGLVERTEXATTRIB3DPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3d");
+ glVertexAttrib3dv = (PFNGLVERTEXATTRIB3DVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3dv");
+ glVertexAttrib3f = (PFNGLVERTEXATTRIB3FPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3f");
+ glVertexAttrib3fv = (PFNGLVERTEXATTRIB3FVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3fv");
+ glVertexAttrib3s = (PFNGLVERTEXATTRIB3SPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3s");
+ glVertexAttrib3sv = (PFNGLVERTEXATTRIB3SVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3sv");
+ glVertexAttrib4Nbv = (PFNGLVERTEXATTRIB4NBVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4Nbv");
+ glVertexAttrib4Niv = (PFNGLVERTEXATTRIB4NIVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4Niv");
+ glVertexAttrib4Nsv = (PFNGLVERTEXATTRIB4NSVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4Nsv");
+ glVertexAttrib4Nub = (PFNGLVERTEXATTRIB4NUBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4Nub");
+ glVertexAttrib4Nubv = (PFNGLVERTEXATTRIB4NUBVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4Nubv");
+ glVertexAttrib4Nuiv = (PFNGLVERTEXATTRIB4NUIVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4Nuiv");
+ glVertexAttrib4Nusv = (PFNGLVERTEXATTRIB4NUSVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4Nusv");
+ glVertexAttrib4bv = (PFNGLVERTEXATTRIB4BVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4bv");
+ glVertexAttrib4d = (PFNGLVERTEXATTRIB4DPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4d");
+ glVertexAttrib4dv = (PFNGLVERTEXATTRIB4DVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4dv");
+ glVertexAttrib4f = (PFNGLVERTEXATTRIB4FPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4f");
+ glVertexAttrib4fv = (PFNGLVERTEXATTRIB4FVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4fv");
+ glVertexAttrib4iv = (PFNGLVERTEXATTRIB4IVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4iv");
+ glVertexAttrib4s = (PFNGLVERTEXATTRIB4SPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4s");
+ glVertexAttrib4sv = (PFNGLVERTEXATTRIB4SVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4sv");
+ glVertexAttrib4ubv = (PFNGLVERTEXATTRIB4UBVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4ubv");
+ glVertexAttrib4uiv = (PFNGLVERTEXATTRIB4UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4uiv");
+ glVertexAttrib4usv = (PFNGLVERTEXATTRIB4USVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4usv");
+ glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribPointer");
+
+ // GL_VERSION_2_1
+ if (mGLVersion < 2.09f)
+ {
+ return;
+ }
+ glUniformMatrix2x3fv = (PFNGLUNIFORMMATRIX2X3FVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix2x3fv");
+ glUniformMatrix3x2fv = (PFNGLUNIFORMMATRIX3X2FVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix3x2fv");
+ glUniformMatrix2x4fv = (PFNGLUNIFORMMATRIX2X4FVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix2x4fv");
+ glUniformMatrix4x2fv = (PFNGLUNIFORMMATRIX4X2FVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix4x2fv");
+ glUniformMatrix3x4fv = (PFNGLUNIFORMMATRIX3X4FVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix3x4fv");
+ glUniformMatrix4x3fv = (PFNGLUNIFORMMATRIX4X3FVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix4x3fv");
+
+ // GL_VERSION_3_0
+ if (mGLVersion < 2.99f)
+ {
+ return;
+ }
+ glColorMaski = (PFNGLCOLORMASKIPROC)GLH_EXT_GET_PROC_ADDRESS("glColorMaski");
+ glGetBooleani_v = (PFNGLGETBOOLEANI_VPROC)GLH_EXT_GET_PROC_ADDRESS("glGetBooleani_v");
+ glGetIntegeri_v = (PFNGLGETINTEGERI_VPROC)GLH_EXT_GET_PROC_ADDRESS("glGetIntegeri_v");
+ glEnablei = (PFNGLENABLEIPROC)GLH_EXT_GET_PROC_ADDRESS("glEnablei");
+ glDisablei = (PFNGLDISABLEIPROC)GLH_EXT_GET_PROC_ADDRESS("glDisablei");
+ glIsEnabledi = (PFNGLISENABLEDIPROC)GLH_EXT_GET_PROC_ADDRESS("glIsEnabledi");
+ glBeginTransformFeedback = (PFNGLBEGINTRANSFORMFEEDBACKPROC)GLH_EXT_GET_PROC_ADDRESS("glBeginTransformFeedback");
+ glEndTransformFeedback = (PFNGLENDTRANSFORMFEEDBACKPROC)GLH_EXT_GET_PROC_ADDRESS("glEndTransformFeedback");
+ glBindBufferRange = (PFNGLBINDBUFFERRANGEPROC)GLH_EXT_GET_PROC_ADDRESS("glBindBufferRange");
+ glBindBufferBase = (PFNGLBINDBUFFERBASEPROC)GLH_EXT_GET_PROC_ADDRESS("glBindBufferBase");
+ glTransformFeedbackVaryings = (PFNGLTRANSFORMFEEDBACKVARYINGSPROC)GLH_EXT_GET_PROC_ADDRESS("glTransformFeedbackVaryings");
+ glGetTransformFeedbackVarying = (PFNGLGETTRANSFORMFEEDBACKVARYINGPROC)GLH_EXT_GET_PROC_ADDRESS("glGetTransformFeedbackVarying");
+ glClampColor = (PFNGLCLAMPCOLORPROC)GLH_EXT_GET_PROC_ADDRESS("glClampColor");
+ glBeginConditionalRender = (PFNGLBEGINCONDITIONALRENDERPROC)GLH_EXT_GET_PROC_ADDRESS("glBeginConditionalRender");
+ glEndConditionalRender = (PFNGLENDCONDITIONALRENDERPROC)GLH_EXT_GET_PROC_ADDRESS("glEndConditionalRender");
+ glVertexAttribIPointer = (PFNGLVERTEXATTRIBIPOINTERPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribIPointer");
+ glGetVertexAttribIiv = (PFNGLGETVERTEXATTRIBIIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribIiv");
+ glGetVertexAttribIuiv = (PFNGLGETVERTEXATTRIBIUIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribIuiv");
+ glVertexAttribI1i = (PFNGLVERTEXATTRIBI1IPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribI1i");
+ glVertexAttribI2i = (PFNGLVERTEXATTRIBI2IPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribI2i");
+ glVertexAttribI3i = (PFNGLVERTEXATTRIBI3IPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribI3i");
+ glVertexAttribI4i = (PFNGLVERTEXATTRIBI4IPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribI4i");
+ glVertexAttribI1ui = (PFNGLVERTEXATTRIBI1UIPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribI1ui");
+ glVertexAttribI2ui = (PFNGLVERTEXATTRIBI2UIPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribI2ui");
+ glVertexAttribI3ui = (PFNGLVERTEXATTRIBI3UIPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribI3ui");
+ glVertexAttribI4ui = (PFNGLVERTEXATTRIBI4UIPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribI4ui");
+ glVertexAttribI1iv = (PFNGLVERTEXATTRIBI1IVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribI1iv");
+ glVertexAttribI2iv = (PFNGLVERTEXATTRIBI2IVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribI2iv");
+ glVertexAttribI3iv = (PFNGLVERTEXATTRIBI3IVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribI3iv");
+ glVertexAttribI4iv = (PFNGLVERTEXATTRIBI4IVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribI4iv");
+ glVertexAttribI1uiv = (PFNGLVERTEXATTRIBI1UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribI1uiv");
+ glVertexAttribI2uiv = (PFNGLVERTEXATTRIBI2UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribI2uiv");
+ glVertexAttribI3uiv = (PFNGLVERTEXATTRIBI3UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribI3uiv");
+ glVertexAttribI4uiv = (PFNGLVERTEXATTRIBI4UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribI4uiv");
+ glVertexAttribI4bv = (PFNGLVERTEXATTRIBI4BVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribI4bv");
+ glVertexAttribI4sv = (PFNGLVERTEXATTRIBI4SVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribI4sv");
+ glVertexAttribI4ubv = (PFNGLVERTEXATTRIBI4UBVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribI4ubv");
+ glVertexAttribI4usv = (PFNGLVERTEXATTRIBI4USVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribI4usv");
+ glGetUniformuiv = (PFNGLGETUNIFORMUIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetUniformuiv");
+ glBindFragDataLocation = (PFNGLBINDFRAGDATALOCATIONPROC)GLH_EXT_GET_PROC_ADDRESS("glBindFragDataLocation");
+ glGetFragDataLocation = (PFNGLGETFRAGDATALOCATIONPROC)GLH_EXT_GET_PROC_ADDRESS("glGetFragDataLocation");
+ glUniform1ui = (PFNGLUNIFORM1UIPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform1ui");
+ glUniform2ui = (PFNGLUNIFORM2UIPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform2ui");
+ glUniform3ui = (PFNGLUNIFORM3UIPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform3ui");
+ glUniform4ui = (PFNGLUNIFORM4UIPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform4ui");
+ glUniform1uiv = (PFNGLUNIFORM1UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform1uiv");
+ glUniform2uiv = (PFNGLUNIFORM2UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform2uiv");
+ glUniform3uiv = (PFNGLUNIFORM3UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform3uiv");
+ glUniform4uiv = (PFNGLUNIFORM4UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform4uiv");
+ glTexParameterIiv = (PFNGLTEXPARAMETERIIVPROC)GLH_EXT_GET_PROC_ADDRESS("glTexParameterIiv");
+ glTexParameterIuiv = (PFNGLTEXPARAMETERIUIVPROC)GLH_EXT_GET_PROC_ADDRESS("glTexParameterIuiv");
+ glGetTexParameterIiv = (PFNGLGETTEXPARAMETERIIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetTexParameterIiv");
+ glGetTexParameterIuiv = (PFNGLGETTEXPARAMETERIUIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetTexParameterIuiv");
+ glClearBufferiv = (PFNGLCLEARBUFFERIVPROC)GLH_EXT_GET_PROC_ADDRESS("glClearBufferiv");
+ glClearBufferuiv = (PFNGLCLEARBUFFERUIVPROC)GLH_EXT_GET_PROC_ADDRESS("glClearBufferuiv");
+ glClearBufferfv = (PFNGLCLEARBUFFERFVPROC)GLH_EXT_GET_PROC_ADDRESS("glClearBufferfv");
+ glClearBufferfi = (PFNGLCLEARBUFFERFIPROC)GLH_EXT_GET_PROC_ADDRESS("glClearBufferfi");
+ glGetStringi = (PFNGLGETSTRINGIPROC)GLH_EXT_GET_PROC_ADDRESS("glGetStringi");
+ glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC)GLH_EXT_GET_PROC_ADDRESS("glIsRenderbuffer");
+ glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC)GLH_EXT_GET_PROC_ADDRESS("glBindRenderbuffer");
+ glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC)GLH_EXT_GET_PROC_ADDRESS("glDeleteRenderbuffers");
+ glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC)GLH_EXT_GET_PROC_ADDRESS("glGenRenderbuffers");
+ glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC)GLH_EXT_GET_PROC_ADDRESS("glRenderbufferStorage");
+ glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetRenderbufferParameteriv");
+ glIsFramebuffer = (PFNGLISFRAMEBUFFERPROC)GLH_EXT_GET_PROC_ADDRESS("glIsFramebuffer");
+ glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC)GLH_EXT_GET_PROC_ADDRESS("glBindFramebuffer");
+ glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC)GLH_EXT_GET_PROC_ADDRESS("glDeleteFramebuffers");
+ glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC)GLH_EXT_GET_PROC_ADDRESS("glGenFramebuffers");
+ glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC)GLH_EXT_GET_PROC_ADDRESS("glCheckFramebufferStatus");
+ glFramebufferTexture1D = (PFNGLFRAMEBUFFERTEXTURE1DPROC)GLH_EXT_GET_PROC_ADDRESS("glFramebufferTexture1D");
+ glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC)GLH_EXT_GET_PROC_ADDRESS("glFramebufferTexture2D");
+ glFramebufferTexture3D = (PFNGLFRAMEBUFFERTEXTURE3DPROC)GLH_EXT_GET_PROC_ADDRESS("glFramebufferTexture3D");
+ glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC)GLH_EXT_GET_PROC_ADDRESS("glFramebufferRenderbuffer");
+ glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetFramebufferAttachmentParameteriv");
+ glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC)GLH_EXT_GET_PROC_ADDRESS("glGenerateMipmap");
+ glBlitFramebuffer = (PFNGLBLITFRAMEBUFFERPROC)GLH_EXT_GET_PROC_ADDRESS("glBlitFramebuffer");
+ glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC)GLH_EXT_GET_PROC_ADDRESS("glRenderbufferStorageMultisample");
+ glFramebufferTextureLayer = (PFNGLFRAMEBUFFERTEXTURELAYERPROC)GLH_EXT_GET_PROC_ADDRESS("glFramebufferTextureLayer");
+ glMapBufferRange = (PFNGLMAPBUFFERRANGEPROC)GLH_EXT_GET_PROC_ADDRESS("glMapBufferRange");
+ glFlushMappedBufferRange = (PFNGLFLUSHMAPPEDBUFFERRANGEPROC)GLH_EXT_GET_PROC_ADDRESS("glFlushMappedBufferRange");
+ glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC)GLH_EXT_GET_PROC_ADDRESS("glBindVertexArray");
+ glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSPROC)GLH_EXT_GET_PROC_ADDRESS("glDeleteVertexArrays");
+ glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC)GLH_EXT_GET_PROC_ADDRESS("glGenVertexArrays");
+ glIsVertexArray = (PFNGLISVERTEXARRAYPROC)GLH_EXT_GET_PROC_ADDRESS("glIsVertexArray");
+
+ // GL_VERSION_3_1
+ if (mGLVersion < 3.09f)
+ {
+ return;
+ }
+ glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawArraysInstanced");
+ glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawElementsInstanced");
+ glTexBuffer = (PFNGLTEXBUFFERPROC)GLH_EXT_GET_PROC_ADDRESS("glTexBuffer");
+ glPrimitiveRestartIndex = (PFNGLPRIMITIVERESTARTINDEXPROC)GLH_EXT_GET_PROC_ADDRESS("glPrimitiveRestartIndex");
+ glCopyBufferSubData = (PFNGLCOPYBUFFERSUBDATAPROC)GLH_EXT_GET_PROC_ADDRESS("glCopyBufferSubData");
+ glGetUniformIndices = (PFNGLGETUNIFORMINDICESPROC)GLH_EXT_GET_PROC_ADDRESS("glGetUniformIndices");
+ glGetActiveUniformsiv = (PFNGLGETACTIVEUNIFORMSIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetActiveUniformsiv");
+ glGetActiveUniformName = (PFNGLGETACTIVEUNIFORMNAMEPROC)GLH_EXT_GET_PROC_ADDRESS("glGetActiveUniformName");
+ glGetUniformBlockIndex = (PFNGLGETUNIFORMBLOCKINDEXPROC)GLH_EXT_GET_PROC_ADDRESS("glGetUniformBlockIndex");
+ glGetActiveUniformBlockiv = (PFNGLGETACTIVEUNIFORMBLOCKIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetActiveUniformBlockiv");
+ glGetActiveUniformBlockName = (PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC)GLH_EXT_GET_PROC_ADDRESS("glGetActiveUniformBlockName");
+ glUniformBlockBinding = (PFNGLUNIFORMBLOCKBINDINGPROC)GLH_EXT_GET_PROC_ADDRESS("glUniformBlockBinding");
+
+ // GL_VERSION_3_2
+ if (mGLVersion < 3.19f)
+ {
+ return;
+ }
+ glDrawElementsBaseVertex = (PFNGLDRAWELEMENTSBASEVERTEXPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawElementsBaseVertex");
+ glDrawRangeElementsBaseVertex = (PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawRangeElementsBaseVertex");
+ glDrawElementsInstancedBaseVertex = (PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawElementsInstancedBaseVertex");
+ glMultiDrawElementsBaseVertex = (PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiDrawElementsBaseVertex");
+ glProvokingVertex = (PFNGLPROVOKINGVERTEXPROC)GLH_EXT_GET_PROC_ADDRESS("glProvokingVertex");
+ glFenceSync = (PFNGLFENCESYNCPROC)GLH_EXT_GET_PROC_ADDRESS("glFenceSync");
+ glIsSync = (PFNGLISSYNCPROC)GLH_EXT_GET_PROC_ADDRESS("glIsSync");
+ glDeleteSync = (PFNGLDELETESYNCPROC)GLH_EXT_GET_PROC_ADDRESS("glDeleteSync");
+ glClientWaitSync = (PFNGLCLIENTWAITSYNCPROC)GLH_EXT_GET_PROC_ADDRESS("glClientWaitSync");
+ glWaitSync = (PFNGLWAITSYNCPROC)GLH_EXT_GET_PROC_ADDRESS("glWaitSync");
+ glGetInteger64v = (PFNGLGETINTEGER64VPROC)GLH_EXT_GET_PROC_ADDRESS("glGetInteger64v");
+ glGetSynciv = (PFNGLGETSYNCIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetSynciv");
+ glGetInteger64i_v = (PFNGLGETINTEGER64I_VPROC)GLH_EXT_GET_PROC_ADDRESS("glGetInteger64i_v");
+ glGetBufferParameteri64v = (PFNGLGETBUFFERPARAMETERI64VPROC)GLH_EXT_GET_PROC_ADDRESS("glGetBufferParameteri64v");
+ glFramebufferTexture = (PFNGLFRAMEBUFFERTEXTUREPROC)GLH_EXT_GET_PROC_ADDRESS("glFramebufferTexture");
+ glTexImage2DMultisample = (PFNGLTEXIMAGE2DMULTISAMPLEPROC)GLH_EXT_GET_PROC_ADDRESS("glTexImage2DMultisample");
+ glTexImage3DMultisample = (PFNGLTEXIMAGE3DMULTISAMPLEPROC)GLH_EXT_GET_PROC_ADDRESS("glTexImage3DMultisample");
+ glGetMultisamplefv = (PFNGLGETMULTISAMPLEFVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetMultisamplefv");
+ glSampleMaski = (PFNGLSAMPLEMASKIPROC)GLH_EXT_GET_PROC_ADDRESS("glSampleMaski");
+
+ // GL_VERSION_3_3
+ if (mGLVersion < 3.29f)
+ {
+ return;
+ }
+ glBindFragDataLocationIndexed = (PFNGLBINDFRAGDATALOCATIONINDEXEDPROC)GLH_EXT_GET_PROC_ADDRESS("glBindFragDataLocationIndexed");
+ glGetFragDataIndex = (PFNGLGETFRAGDATAINDEXPROC)GLH_EXT_GET_PROC_ADDRESS("glGetFragDataIndex");
+ glGenSamplers = (PFNGLGENSAMPLERSPROC)GLH_EXT_GET_PROC_ADDRESS("glGenSamplers");
+ glDeleteSamplers = (PFNGLDELETESAMPLERSPROC)GLH_EXT_GET_PROC_ADDRESS("glDeleteSamplers");
+ glIsSampler = (PFNGLISSAMPLERPROC)GLH_EXT_GET_PROC_ADDRESS("glIsSampler");
+ glBindSampler = (PFNGLBINDSAMPLERPROC)GLH_EXT_GET_PROC_ADDRESS("glBindSampler");
+ glSamplerParameteri = (PFNGLSAMPLERPARAMETERIPROC)GLH_EXT_GET_PROC_ADDRESS("glSamplerParameteri");
+ glSamplerParameteriv = (PFNGLSAMPLERPARAMETERIVPROC)GLH_EXT_GET_PROC_ADDRESS("glSamplerParameteriv");
+ glSamplerParameterf = (PFNGLSAMPLERPARAMETERFPROC)GLH_EXT_GET_PROC_ADDRESS("glSamplerParameterf");
+ glSamplerParameterfv = (PFNGLSAMPLERPARAMETERFVPROC)GLH_EXT_GET_PROC_ADDRESS("glSamplerParameterfv");
+ glSamplerParameterIiv = (PFNGLSAMPLERPARAMETERIIVPROC)GLH_EXT_GET_PROC_ADDRESS("glSamplerParameterIiv");
+ glSamplerParameterIuiv = (PFNGLSAMPLERPARAMETERIUIVPROC)GLH_EXT_GET_PROC_ADDRESS("glSamplerParameterIuiv");
+ glGetSamplerParameteriv = (PFNGLGETSAMPLERPARAMETERIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetSamplerParameteriv");
+ glGetSamplerParameterIiv = (PFNGLGETSAMPLERPARAMETERIIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetSamplerParameterIiv");
+ glGetSamplerParameterfv = (PFNGLGETSAMPLERPARAMETERFVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetSamplerParameterfv");
+ glGetSamplerParameterIuiv = (PFNGLGETSAMPLERPARAMETERIUIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetSamplerParameterIuiv");
+ glQueryCounter = (PFNGLQUERYCOUNTERPROC)GLH_EXT_GET_PROC_ADDRESS("glQueryCounter");
+ glGetQueryObjecti64v = (PFNGLGETQUERYOBJECTI64VPROC)GLH_EXT_GET_PROC_ADDRESS("glGetQueryObjecti64v");
+ glGetQueryObjectui64v = (PFNGLGETQUERYOBJECTUI64VPROC)GLH_EXT_GET_PROC_ADDRESS("glGetQueryObjectui64v");
+ glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISORPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribDivisor");
+ glVertexAttribP1ui = (PFNGLVERTEXATTRIBP1UIPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribP1ui");
+ glVertexAttribP1uiv = (PFNGLVERTEXATTRIBP1UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribP1uiv");
+ glVertexAttribP2ui = (PFNGLVERTEXATTRIBP2UIPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribP2ui");
+ glVertexAttribP2uiv = (PFNGLVERTEXATTRIBP2UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribP2uiv");
+ glVertexAttribP3ui = (PFNGLVERTEXATTRIBP3UIPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribP3ui");
+ glVertexAttribP3uiv = (PFNGLVERTEXATTRIBP3UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribP3uiv");
+ glVertexAttribP4ui = (PFNGLVERTEXATTRIBP4UIPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribP4ui");
+ glVertexAttribP4uiv = (PFNGLVERTEXATTRIBP4UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribP4uiv");
+ glVertexP2ui = (PFNGLVERTEXP2UIPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexP2ui");
+ glVertexP2uiv = (PFNGLVERTEXP2UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexP2uiv");
+ glVertexP3ui = (PFNGLVERTEXP3UIPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexP3ui");
+ glVertexP3uiv = (PFNGLVERTEXP3UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexP3uiv");
+ glVertexP4ui = (PFNGLVERTEXP4UIPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexP4ui");
+ glVertexP4uiv = (PFNGLVERTEXP4UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexP4uiv");
+ glTexCoordP1ui = (PFNGLTEXCOORDP1UIPROC)GLH_EXT_GET_PROC_ADDRESS("glTexCoordP1ui");
+ glTexCoordP1uiv = (PFNGLTEXCOORDP1UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glTexCoordP1uiv");
+ glTexCoordP2ui = (PFNGLTEXCOORDP2UIPROC)GLH_EXT_GET_PROC_ADDRESS("glTexCoordP2ui");
+ glTexCoordP2uiv = (PFNGLTEXCOORDP2UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glTexCoordP2uiv");
+ glTexCoordP3ui = (PFNGLTEXCOORDP3UIPROC)GLH_EXT_GET_PROC_ADDRESS("glTexCoordP3ui");
+ glTexCoordP3uiv = (PFNGLTEXCOORDP3UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glTexCoordP3uiv");
+ glTexCoordP4ui = (PFNGLTEXCOORDP4UIPROC)GLH_EXT_GET_PROC_ADDRESS("glTexCoordP4ui");
+ glTexCoordP4uiv = (PFNGLTEXCOORDP4UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glTexCoordP4uiv");
+ glMultiTexCoordP1ui = (PFNGLMULTITEXCOORDP1UIPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoordP1ui");
+ glMultiTexCoordP1uiv = (PFNGLMULTITEXCOORDP1UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoordP1uiv");
+ glMultiTexCoordP2ui = (PFNGLMULTITEXCOORDP2UIPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoordP2ui");
+ glMultiTexCoordP2uiv = (PFNGLMULTITEXCOORDP2UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoordP2uiv");
+ glMultiTexCoordP3ui = (PFNGLMULTITEXCOORDP3UIPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoordP3ui");
+ glMultiTexCoordP3uiv = (PFNGLMULTITEXCOORDP3UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoordP3uiv");
+ glMultiTexCoordP4ui = (PFNGLMULTITEXCOORDP4UIPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoordP4ui");
+ glMultiTexCoordP4uiv = (PFNGLMULTITEXCOORDP4UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoordP4uiv");
+ glNormalP3ui = (PFNGLNORMALP3UIPROC)GLH_EXT_GET_PROC_ADDRESS("glNormalP3ui");
+ glNormalP3uiv = (PFNGLNORMALP3UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glNormalP3uiv");
+ glColorP3ui = (PFNGLCOLORP3UIPROC)GLH_EXT_GET_PROC_ADDRESS("glColorP3ui");
+ glColorP3uiv = (PFNGLCOLORP3UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glColorP3uiv");
+ glColorP4ui = (PFNGLCOLORP4UIPROC)GLH_EXT_GET_PROC_ADDRESS("glColorP4ui");
+ glColorP4uiv = (PFNGLCOLORP4UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glColorP4uiv");
+ glSecondaryColorP3ui = (PFNGLSECONDARYCOLORP3UIPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColorP3ui");
+ glSecondaryColorP3uiv = (PFNGLSECONDARYCOLORP3UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColorP3uiv");
+
+ // GL_VERSION_4_0
+ if (mGLVersion < 3.99f)
+ {
+ return;
+ }
+ glMinSampleShading = (PFNGLMINSAMPLESHADINGPROC)GLH_EXT_GET_PROC_ADDRESS("glMinSampleShading");
+ glBlendEquationi = (PFNGLBLENDEQUATIONIPROC)GLH_EXT_GET_PROC_ADDRESS("glBlendEquationi");
+ glBlendEquationSeparatei = (PFNGLBLENDEQUATIONSEPARATEIPROC)GLH_EXT_GET_PROC_ADDRESS("glBlendEquationSeparatei");
+ glBlendFunci = (PFNGLBLENDFUNCIPROC)GLH_EXT_GET_PROC_ADDRESS("glBlendFunci");
+ glBlendFuncSeparatei = (PFNGLBLENDFUNCSEPARATEIPROC)GLH_EXT_GET_PROC_ADDRESS("glBlendFuncSeparatei");
+ glDrawArraysIndirect = (PFNGLDRAWARRAYSINDIRECTPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawArraysIndirect");
+ glDrawElementsIndirect = (PFNGLDRAWELEMENTSINDIRECTPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawElementsIndirect");
+ glUniform1d = (PFNGLUNIFORM1DPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform1d");
+ glUniform2d = (PFNGLUNIFORM2DPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform2d");
+ glUniform3d = (PFNGLUNIFORM3DPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform3d");
+ glUniform4d = (PFNGLUNIFORM4DPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform4d");
+ glUniform1dv = (PFNGLUNIFORM1DVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform1dv");
+ glUniform2dv = (PFNGLUNIFORM2DVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform2dv");
+ glUniform3dv = (PFNGLUNIFORM3DVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform3dv");
+ glUniform4dv = (PFNGLUNIFORM4DVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniform4dv");
+ glUniformMatrix2dv = (PFNGLUNIFORMMATRIX2DVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix2dv");
+ glUniformMatrix3dv = (PFNGLUNIFORMMATRIX3DVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix3dv");
+ glUniformMatrix4dv = (PFNGLUNIFORMMATRIX4DVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix4dv");
+ glUniformMatrix2x3dv = (PFNGLUNIFORMMATRIX2X3DVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix2x3dv");
+ glUniformMatrix2x4dv = (PFNGLUNIFORMMATRIX2X4DVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix2x4dv");
+ glUniformMatrix3x2dv = (PFNGLUNIFORMMATRIX3X2DVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix3x2dv");
+ glUniformMatrix3x4dv = (PFNGLUNIFORMMATRIX3X4DVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix3x4dv");
+ glUniformMatrix4x2dv = (PFNGLUNIFORMMATRIX4X2DVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix4x2dv");
+ glUniformMatrix4x3dv = (PFNGLUNIFORMMATRIX4X3DVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix4x3dv");
+ glGetUniformdv = (PFNGLGETUNIFORMDVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetUniformdv");
+ glGetSubroutineUniformLocation = (PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC)GLH_EXT_GET_PROC_ADDRESS("glGetSubroutineUniformLocation");
+ glGetSubroutineIndex = (PFNGLGETSUBROUTINEINDEXPROC)GLH_EXT_GET_PROC_ADDRESS("glGetSubroutineIndex");
+ glGetActiveSubroutineUniformiv = (PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetActiveSubroutineUniformiv");
+ glGetActiveSubroutineUniformName = (PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC)GLH_EXT_GET_PROC_ADDRESS("glGetActiveSubroutineUniformName");
+ glGetActiveSubroutineName = (PFNGLGETACTIVESUBROUTINENAMEPROC)GLH_EXT_GET_PROC_ADDRESS("glGetActiveSubroutineName");
+ glUniformSubroutinesuiv = (PFNGLUNIFORMSUBROUTINESUIVPROC)GLH_EXT_GET_PROC_ADDRESS("glUniformSubroutinesuiv");
+ glGetUniformSubroutineuiv = (PFNGLGETUNIFORMSUBROUTINEUIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetUniformSubroutineuiv");
+ glGetProgramStageiv = (PFNGLGETPROGRAMSTAGEIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetProgramStageiv");
+ glPatchParameteri = (PFNGLPATCHPARAMETERIPROC)GLH_EXT_GET_PROC_ADDRESS("glPatchParameteri");
+ glPatchParameterfv = (PFNGLPATCHPARAMETERFVPROC)GLH_EXT_GET_PROC_ADDRESS("glPatchParameterfv");
+ glBindTransformFeedback = (PFNGLBINDTRANSFORMFEEDBACKPROC)GLH_EXT_GET_PROC_ADDRESS("glBindTransformFeedback");
+ glDeleteTransformFeedbacks = (PFNGLDELETETRANSFORMFEEDBACKSPROC)GLH_EXT_GET_PROC_ADDRESS("glDeleteTransformFeedbacks");
+ glGenTransformFeedbacks = (PFNGLGENTRANSFORMFEEDBACKSPROC)GLH_EXT_GET_PROC_ADDRESS("glGenTransformFeedbacks");
+ glIsTransformFeedback = (PFNGLISTRANSFORMFEEDBACKPROC)GLH_EXT_GET_PROC_ADDRESS("glIsTransformFeedback");
+ glPauseTransformFeedback = (PFNGLPAUSETRANSFORMFEEDBACKPROC)GLH_EXT_GET_PROC_ADDRESS("glPauseTransformFeedback");
+ glResumeTransformFeedback = (PFNGLRESUMETRANSFORMFEEDBACKPROC)GLH_EXT_GET_PROC_ADDRESS("glResumeTransformFeedback");
+ glDrawTransformFeedback = (PFNGLDRAWTRANSFORMFEEDBACKPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawTransformFeedback");
+ glDrawTransformFeedbackStream = (PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawTransformFeedbackStream");
+ glBeginQueryIndexed = (PFNGLBEGINQUERYINDEXEDPROC)GLH_EXT_GET_PROC_ADDRESS("glBeginQueryIndexed");
+ glEndQueryIndexed = (PFNGLENDQUERYINDEXEDPROC)GLH_EXT_GET_PROC_ADDRESS("glEndQueryIndexed");
+ glGetQueryIndexediv = (PFNGLGETQUERYINDEXEDIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetQueryIndexediv");
+
+ // GL_VERSION_4_1
+ if (mGLVersion < 4.09f)
+ {
+ return;
+ }
+ glReleaseShaderCompiler = (PFNGLRELEASESHADERCOMPILERPROC)GLH_EXT_GET_PROC_ADDRESS("glReleaseShaderCompiler");
+ glShaderBinary = (PFNGLSHADERBINARYPROC)GLH_EXT_GET_PROC_ADDRESS("glShaderBinary");
+ glGetShaderPrecisionFormat = (PFNGLGETSHADERPRECISIONFORMATPROC)GLH_EXT_GET_PROC_ADDRESS("glGetShaderPrecisionFormat");
+ glDepthRangef = (PFNGLDEPTHRANGEFPROC)GLH_EXT_GET_PROC_ADDRESS("glDepthRangef");
+ glClearDepthf = (PFNGLCLEARDEPTHFPROC)GLH_EXT_GET_PROC_ADDRESS("glClearDepthf");
+ glGetProgramBinary = (PFNGLGETPROGRAMBINARYPROC)GLH_EXT_GET_PROC_ADDRESS("glGetProgramBinary");
+ glProgramBinary = (PFNGLPROGRAMBINARYPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramBinary");
+ glProgramParameteri = (PFNGLPROGRAMPARAMETERIPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramParameteri");
+ glUseProgramStages = (PFNGLUSEPROGRAMSTAGESPROC)GLH_EXT_GET_PROC_ADDRESS("glUseProgramStages");
+ glActiveShaderProgram = (PFNGLACTIVESHADERPROGRAMPROC)GLH_EXT_GET_PROC_ADDRESS("glActiveShaderProgram");
+ glCreateShaderProgramv = (PFNGLCREATESHADERPROGRAMVPROC)GLH_EXT_GET_PROC_ADDRESS("glCreateShaderProgramv");
+ glBindProgramPipeline = (PFNGLBINDPROGRAMPIPELINEPROC)GLH_EXT_GET_PROC_ADDRESS("glBindProgramPipeline");
+ glDeleteProgramPipelines = (PFNGLDELETEPROGRAMPIPELINESPROC)GLH_EXT_GET_PROC_ADDRESS("glDeleteProgramPipelines");
+ glGenProgramPipelines = (PFNGLGENPROGRAMPIPELINESPROC)GLH_EXT_GET_PROC_ADDRESS("glGenProgramPipelines");
+ glIsProgramPipeline = (PFNGLISPROGRAMPIPELINEPROC)GLH_EXT_GET_PROC_ADDRESS("glIsProgramPipeline");
+ glGetProgramPipelineiv = (PFNGLGETPROGRAMPIPELINEIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetProgramPipelineiv");
+ glProgramUniform1i = (PFNGLPROGRAMUNIFORM1IPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform1i");
+ glProgramUniform1iv = (PFNGLPROGRAMUNIFORM1IVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform1iv");
+ glProgramUniform1f = (PFNGLPROGRAMUNIFORM1FPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform1f");
+ glProgramUniform1fv = (PFNGLPROGRAMUNIFORM1FVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform1fv");
+ glProgramUniform1d = (PFNGLPROGRAMUNIFORM1DPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform1d");
+ glProgramUniform1dv = (PFNGLPROGRAMUNIFORM1DVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform1dv");
+ glProgramUniform1ui = (PFNGLPROGRAMUNIFORM1UIPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform1ui");
+ glProgramUniform1uiv = (PFNGLPROGRAMUNIFORM1UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform1uiv");
+ glProgramUniform2i = (PFNGLPROGRAMUNIFORM2IPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform2i");
+ glProgramUniform2iv = (PFNGLPROGRAMUNIFORM2IVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform2iv");
+ glProgramUniform2f = (PFNGLPROGRAMUNIFORM2FPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform2f");
+ glProgramUniform2fv = (PFNGLPROGRAMUNIFORM2FVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform2fv");
+ glProgramUniform2d = (PFNGLPROGRAMUNIFORM2DPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform2d");
+ glProgramUniform2dv = (PFNGLPROGRAMUNIFORM2DVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform2dv");
+ glProgramUniform2ui = (PFNGLPROGRAMUNIFORM2UIPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform2ui");
+ glProgramUniform2uiv = (PFNGLPROGRAMUNIFORM2UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform2uiv");
+ glProgramUniform3i = (PFNGLPROGRAMUNIFORM3IPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform3i");
+ glProgramUniform3iv = (PFNGLPROGRAMUNIFORM3IVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform3iv");
+ glProgramUniform3f = (PFNGLPROGRAMUNIFORM3FPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform3f");
+ glProgramUniform3fv = (PFNGLPROGRAMUNIFORM3FVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform3fv");
+ glProgramUniform3d = (PFNGLPROGRAMUNIFORM3DPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform3d");
+ glProgramUniform3dv = (PFNGLPROGRAMUNIFORM3DVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform3dv");
+ glProgramUniform3ui = (PFNGLPROGRAMUNIFORM3UIPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform3ui");
+ glProgramUniform3uiv = (PFNGLPROGRAMUNIFORM3UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform3uiv");
+ glProgramUniform4i = (PFNGLPROGRAMUNIFORM4IPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform4i");
+ glProgramUniform4iv = (PFNGLPROGRAMUNIFORM4IVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform4iv");
+ glProgramUniform4f = (PFNGLPROGRAMUNIFORM4FPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform4f");
+ glProgramUniform4fv = (PFNGLPROGRAMUNIFORM4FVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform4fv");
+ glProgramUniform4d = (PFNGLPROGRAMUNIFORM4DPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform4d");
+ glProgramUniform4dv = (PFNGLPROGRAMUNIFORM4DVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform4dv");
+ glProgramUniform4ui = (PFNGLPROGRAMUNIFORM4UIPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform4ui");
+ glProgramUniform4uiv = (PFNGLPROGRAMUNIFORM4UIVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniform4uiv");
+ glProgramUniformMatrix2fv = (PFNGLPROGRAMUNIFORMMATRIX2FVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniformMatrix2fv");
+ glProgramUniformMatrix3fv = (PFNGLPROGRAMUNIFORMMATRIX3FVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniformMatrix3fv");
+ glProgramUniformMatrix4fv = (PFNGLPROGRAMUNIFORMMATRIX4FVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniformMatrix4fv");
+ glProgramUniformMatrix2dv = (PFNGLPROGRAMUNIFORMMATRIX2DVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniformMatrix2dv");
+ glProgramUniformMatrix3dv = (PFNGLPROGRAMUNIFORMMATRIX3DVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniformMatrix3dv");
+ glProgramUniformMatrix4dv = (PFNGLPROGRAMUNIFORMMATRIX4DVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniformMatrix4dv");
+ glProgramUniformMatrix2x3fv = (PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniformMatrix2x3fv");
+ glProgramUniformMatrix3x2fv = (PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniformMatrix3x2fv");
+ glProgramUniformMatrix2x4fv = (PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniformMatrix2x4fv");
+ glProgramUniformMatrix4x2fv = (PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniformMatrix4x2fv");
+ glProgramUniformMatrix3x4fv = (PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniformMatrix3x4fv");
+ glProgramUniformMatrix4x3fv = (PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniformMatrix4x3fv");
+ glProgramUniformMatrix2x3dv = (PFNGLPROGRAMUNIFORMMATRIX2X3DVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniformMatrix2x3dv");
+ glProgramUniformMatrix3x2dv = (PFNGLPROGRAMUNIFORMMATRIX3X2DVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniformMatrix3x2dv");
+ glProgramUniformMatrix2x4dv = (PFNGLPROGRAMUNIFORMMATRIX2X4DVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniformMatrix2x4dv");
+ glProgramUniformMatrix4x2dv = (PFNGLPROGRAMUNIFORMMATRIX4X2DVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniformMatrix4x2dv");
+ glProgramUniformMatrix3x4dv = (PFNGLPROGRAMUNIFORMMATRIX3X4DVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniformMatrix3x4dv");
+ glProgramUniformMatrix4x3dv = (PFNGLPROGRAMUNIFORMMATRIX4X3DVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramUniformMatrix4x3dv");
+ glValidateProgramPipeline = (PFNGLVALIDATEPROGRAMPIPELINEPROC)GLH_EXT_GET_PROC_ADDRESS("glValidateProgramPipeline");
+ glGetProgramPipelineInfoLog = (PFNGLGETPROGRAMPIPELINEINFOLOGPROC)GLH_EXT_GET_PROC_ADDRESS("glGetProgramPipelineInfoLog");
+ glVertexAttribL1d = (PFNGLVERTEXATTRIBL1DPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribL1d");
+ glVertexAttribL2d = (PFNGLVERTEXATTRIBL2DPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribL2d");
+ glVertexAttribL3d = (PFNGLVERTEXATTRIBL3DPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribL3d");
+ glVertexAttribL4d = (PFNGLVERTEXATTRIBL4DPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribL4d");
+ glVertexAttribL1dv = (PFNGLVERTEXATTRIBL1DVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribL1dv");
+ glVertexAttribL2dv = (PFNGLVERTEXATTRIBL2DVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribL2dv");
+ glVertexAttribL3dv = (PFNGLVERTEXATTRIBL3DVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribL3dv");
+ glVertexAttribL4dv = (PFNGLVERTEXATTRIBL4DVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribL4dv");
+ glVertexAttribLPointer = (PFNGLVERTEXATTRIBLPOINTERPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribLPointer");
+ glGetVertexAttribLdv = (PFNGLGETVERTEXATTRIBLDVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribLdv");
+ glViewportArrayv = (PFNGLVIEWPORTARRAYVPROC)GLH_EXT_GET_PROC_ADDRESS("glViewportArrayv");
+ glViewportIndexedf = (PFNGLVIEWPORTINDEXEDFPROC)GLH_EXT_GET_PROC_ADDRESS("glViewportIndexedf");
+ glViewportIndexedfv = (PFNGLVIEWPORTINDEXEDFVPROC)GLH_EXT_GET_PROC_ADDRESS("glViewportIndexedfv");
+ glScissorArrayv = (PFNGLSCISSORARRAYVPROC)GLH_EXT_GET_PROC_ADDRESS("glScissorArrayv");
+ glScissorIndexed = (PFNGLSCISSORINDEXEDPROC)GLH_EXT_GET_PROC_ADDRESS("glScissorIndexed");
+ glScissorIndexedv = (PFNGLSCISSORINDEXEDVPROC)GLH_EXT_GET_PROC_ADDRESS("glScissorIndexedv");
+ glDepthRangeArrayv = (PFNGLDEPTHRANGEARRAYVPROC)GLH_EXT_GET_PROC_ADDRESS("glDepthRangeArrayv");
+ glDepthRangeIndexed = (PFNGLDEPTHRANGEINDEXEDPROC)GLH_EXT_GET_PROC_ADDRESS("glDepthRangeIndexed");
+ glGetFloati_v = (PFNGLGETFLOATI_VPROC)GLH_EXT_GET_PROC_ADDRESS("glGetFloati_v");
+ glGetDoublei_v = (PFNGLGETDOUBLEI_VPROC)GLH_EXT_GET_PROC_ADDRESS("glGetDoublei_v");
+
+ // GL_VERSION_4_2
+ if (mGLVersion < 4.19f)
+ {
+ return;
+ }
+ glDrawArraysInstancedBaseInstance = (PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawArraysInstancedBaseInstance");
+ glDrawElementsInstancedBaseInstance = (PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawElementsInstancedBaseInstance");
+ glDrawElementsInstancedBaseVertexBaseInstance = (PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawElementsInstancedBaseVertexBaseInstance");
+ glGetInternalformativ = (PFNGLGETINTERNALFORMATIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetInternalformativ");
+ glGetActiveAtomicCounterBufferiv = (PFNGLGETACTIVEATOMICCOUNTERBUFFERIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetActiveAtomicCounterBufferiv");
+ glBindImageTexture = (PFNGLBINDIMAGETEXTUREPROC)GLH_EXT_GET_PROC_ADDRESS("glBindImageTexture");
+ glMemoryBarrier = (PFNGLMEMORYBARRIERPROC)GLH_EXT_GET_PROC_ADDRESS("glMemoryBarrier");
+ glTexStorage1D = (PFNGLTEXSTORAGE1DPROC)GLH_EXT_GET_PROC_ADDRESS("glTexStorage1D");
+ glTexStorage2D = (PFNGLTEXSTORAGE2DPROC)GLH_EXT_GET_PROC_ADDRESS("glTexStorage2D");
+ glTexStorage3D = (PFNGLTEXSTORAGE3DPROC)GLH_EXT_GET_PROC_ADDRESS("glTexStorage3D");
+ glDrawTransformFeedbackInstanced = (PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawTransformFeedbackInstanced");
+ glDrawTransformFeedbackStreamInstanced = (PFNGLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawTransformFeedbackStreamInstanced");
+
+ // GL_VERSION_4_3
+ if (mGLVersion < 4.29f)
+ {
+ return;
+ }
+ glClearBufferData = (PFNGLCLEARBUFFERDATAPROC)GLH_EXT_GET_PROC_ADDRESS("glClearBufferData");
+ glClearBufferSubData = (PFNGLCLEARBUFFERSUBDATAPROC)GLH_EXT_GET_PROC_ADDRESS("glClearBufferSubData");
+ glDispatchCompute = (PFNGLDISPATCHCOMPUTEPROC)GLH_EXT_GET_PROC_ADDRESS("glDispatchCompute");
+ glDispatchComputeIndirect = (PFNGLDISPATCHCOMPUTEINDIRECTPROC)GLH_EXT_GET_PROC_ADDRESS("glDispatchComputeIndirect");
+ glCopyImageSubData = (PFNGLCOPYIMAGESUBDATAPROC)GLH_EXT_GET_PROC_ADDRESS("glCopyImageSubData");
+ glFramebufferParameteri = (PFNGLFRAMEBUFFERPARAMETERIPROC)GLH_EXT_GET_PROC_ADDRESS("glFramebufferParameteri");
+ glGetFramebufferParameteriv = (PFNGLGETFRAMEBUFFERPARAMETERIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetFramebufferParameteriv");
+ glGetInternalformati64v = (PFNGLGETINTERNALFORMATI64VPROC)GLH_EXT_GET_PROC_ADDRESS("glGetInternalformati64v");
+ glInvalidateTexSubImage = (PFNGLINVALIDATETEXSUBIMAGEPROC)GLH_EXT_GET_PROC_ADDRESS("glInvalidateTexSubImage");
+ glInvalidateTexImage = (PFNGLINVALIDATETEXIMAGEPROC)GLH_EXT_GET_PROC_ADDRESS("glInvalidateTexImage");
+ glInvalidateBufferSubData = (PFNGLINVALIDATEBUFFERSUBDATAPROC)GLH_EXT_GET_PROC_ADDRESS("glInvalidateBufferSubData");
+ glInvalidateBufferData = (PFNGLINVALIDATEBUFFERDATAPROC)GLH_EXT_GET_PROC_ADDRESS("glInvalidateBufferData");
+ glInvalidateFramebuffer = (PFNGLINVALIDATEFRAMEBUFFERPROC)GLH_EXT_GET_PROC_ADDRESS("glInvalidateFramebuffer");
+ glInvalidateSubFramebuffer = (PFNGLINVALIDATESUBFRAMEBUFFERPROC)GLH_EXT_GET_PROC_ADDRESS("glInvalidateSubFramebuffer");
+ glMultiDrawArraysIndirect = (PFNGLMULTIDRAWARRAYSINDIRECTPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiDrawArraysIndirect");
+ glMultiDrawElementsIndirect = (PFNGLMULTIDRAWELEMENTSINDIRECTPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiDrawElementsIndirect");
+ glGetProgramInterfaceiv = (PFNGLGETPROGRAMINTERFACEIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetProgramInterfaceiv");
+ glGetProgramResourceIndex = (PFNGLGETPROGRAMRESOURCEINDEXPROC)GLH_EXT_GET_PROC_ADDRESS("glGetProgramResourceIndex");
+ glGetProgramResourceName = (PFNGLGETPROGRAMRESOURCENAMEPROC)GLH_EXT_GET_PROC_ADDRESS("glGetProgramResourceName");
+ glGetProgramResourceiv = (PFNGLGETPROGRAMRESOURCEIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetProgramResourceiv");
+ glGetProgramResourceLocation = (PFNGLGETPROGRAMRESOURCELOCATIONPROC)GLH_EXT_GET_PROC_ADDRESS("glGetProgramResourceLocation");
+ glGetProgramResourceLocationIndex = (PFNGLGETPROGRAMRESOURCELOCATIONINDEXPROC)GLH_EXT_GET_PROC_ADDRESS("glGetProgramResourceLocationIndex");
+ glShaderStorageBlockBinding = (PFNGLSHADERSTORAGEBLOCKBINDINGPROC)GLH_EXT_GET_PROC_ADDRESS("glShaderStorageBlockBinding");
+ glTexBufferRange = (PFNGLTEXBUFFERRANGEPROC)GLH_EXT_GET_PROC_ADDRESS("glTexBufferRange");
+ glTexStorage2DMultisample = (PFNGLTEXSTORAGE2DMULTISAMPLEPROC)GLH_EXT_GET_PROC_ADDRESS("glTexStorage2DMultisample");
+ glTexStorage3DMultisample = (PFNGLTEXSTORAGE3DMULTISAMPLEPROC)GLH_EXT_GET_PROC_ADDRESS("glTexStorage3DMultisample");
+ glTextureView = (PFNGLTEXTUREVIEWPROC)GLH_EXT_GET_PROC_ADDRESS("glTextureView");
+ glBindVertexBuffer = (PFNGLBINDVERTEXBUFFERPROC)GLH_EXT_GET_PROC_ADDRESS("glBindVertexBuffer");
+ glVertexAttribFormat = (PFNGLVERTEXATTRIBFORMATPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribFormat");
+ glVertexAttribIFormat = (PFNGLVERTEXATTRIBIFORMATPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribIFormat");
+ glVertexAttribLFormat = (PFNGLVERTEXATTRIBLFORMATPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribLFormat");
+ glVertexAttribBinding = (PFNGLVERTEXATTRIBBINDINGPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribBinding");
+ glVertexBindingDivisor = (PFNGLVERTEXBINDINGDIVISORPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexBindingDivisor");
+ glDebugMessageControl = (PFNGLDEBUGMESSAGECONTROLPROC)GLH_EXT_GET_PROC_ADDRESS("glDebugMessageControl");
+ glDebugMessageInsert = (PFNGLDEBUGMESSAGEINSERTPROC)GLH_EXT_GET_PROC_ADDRESS("glDebugMessageInsert");
+ glDebugMessageCallback = (PFNGLDEBUGMESSAGECALLBACKPROC)GLH_EXT_GET_PROC_ADDRESS("glDebugMessageCallback");
+ glGetDebugMessageLog = (PFNGLGETDEBUGMESSAGELOGPROC)GLH_EXT_GET_PROC_ADDRESS("glGetDebugMessageLog");
+ glPushDebugGroup = (PFNGLPUSHDEBUGGROUPPROC)GLH_EXT_GET_PROC_ADDRESS("glPushDebugGroup");
+ glPopDebugGroup = (PFNGLPOPDEBUGGROUPPROC)GLH_EXT_GET_PROC_ADDRESS("glPopDebugGroup");
+ glObjectLabel = (PFNGLOBJECTLABELPROC)GLH_EXT_GET_PROC_ADDRESS("glObjectLabel");
+ glGetObjectLabel = (PFNGLGETOBJECTLABELPROC)GLH_EXT_GET_PROC_ADDRESS("glGetObjectLabel");
+ glObjectPtrLabel = (PFNGLOBJECTPTRLABELPROC)GLH_EXT_GET_PROC_ADDRESS("glObjectPtrLabel");
+ glGetObjectPtrLabel = (PFNGLGETOBJECTPTRLABELPROC)GLH_EXT_GET_PROC_ADDRESS("glGetObjectPtrLabel");
+
+ // GL_VERSION_4_4
+ if (mGLVersion < 4.39f)
+ {
+ return;
+ }
+ glBufferStorage = (PFNGLBUFFERSTORAGEPROC)GLH_EXT_GET_PROC_ADDRESS("glBufferStorage");
+ glClearTexImage = (PFNGLCLEARTEXIMAGEPROC)GLH_EXT_GET_PROC_ADDRESS("glClearTexImage");
+ glClearTexSubImage = (PFNGLCLEARTEXSUBIMAGEPROC)GLH_EXT_GET_PROC_ADDRESS("glClearTexSubImage");
+ glBindBuffersBase = (PFNGLBINDBUFFERSBASEPROC)GLH_EXT_GET_PROC_ADDRESS("glBindBuffersBase");
+ glBindBuffersRange = (PFNGLBINDBUFFERSRANGEPROC)GLH_EXT_GET_PROC_ADDRESS("glBindBuffersRange");
+ glBindTextures = (PFNGLBINDTEXTURESPROC)GLH_EXT_GET_PROC_ADDRESS("glBindTextures");
+ glBindSamplers = (PFNGLBINDSAMPLERSPROC)GLH_EXT_GET_PROC_ADDRESS("glBindSamplers");
+ glBindImageTextures = (PFNGLBINDIMAGETEXTURESPROC)GLH_EXT_GET_PROC_ADDRESS("glBindImageTextures");
+ glBindVertexBuffers = (PFNGLBINDVERTEXBUFFERSPROC)GLH_EXT_GET_PROC_ADDRESS("glBindVertexBuffers");
+
+ // GL_VERSION_4_5
+ if (mGLVersion < 4.49f)
+ {
+ return;
+ }
+ glClipControl = (PFNGLCLIPCONTROLPROC)GLH_EXT_GET_PROC_ADDRESS("glClipControl");
+ glCreateTransformFeedbacks = (PFNGLCREATETRANSFORMFEEDBACKSPROC)GLH_EXT_GET_PROC_ADDRESS("glCreateTransformFeedbacks");
+ glTransformFeedbackBufferBase = (PFNGLTRANSFORMFEEDBACKBUFFERBASEPROC)GLH_EXT_GET_PROC_ADDRESS("glTransformFeedbackBufferBase");
+ glTransformFeedbackBufferRange = (PFNGLTRANSFORMFEEDBACKBUFFERRANGEPROC)GLH_EXT_GET_PROC_ADDRESS("glTransformFeedbackBufferRange");
+ glGetTransformFeedbackiv = (PFNGLGETTRANSFORMFEEDBACKIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetTransformFeedbackiv");
+ glGetTransformFeedbacki_v = (PFNGLGETTRANSFORMFEEDBACKI_VPROC)GLH_EXT_GET_PROC_ADDRESS("glGetTransformFeedbacki_v");
+ glGetTransformFeedbacki64_v = (PFNGLGETTRANSFORMFEEDBACKI64_VPROC)GLH_EXT_GET_PROC_ADDRESS("glGetTransformFeedbacki64_v");
+ glCreateBuffers = (PFNGLCREATEBUFFERSPROC)GLH_EXT_GET_PROC_ADDRESS("glCreateBuffers");
+ glNamedBufferStorage = (PFNGLNAMEDBUFFERSTORAGEPROC)GLH_EXT_GET_PROC_ADDRESS("glNamedBufferStorage");
+ glNamedBufferData = (PFNGLNAMEDBUFFERDATAPROC)GLH_EXT_GET_PROC_ADDRESS("glNamedBufferData");
+ glNamedBufferSubData = (PFNGLNAMEDBUFFERSUBDATAPROC)GLH_EXT_GET_PROC_ADDRESS("glNamedBufferSubData");
+ glCopyNamedBufferSubData = (PFNGLCOPYNAMEDBUFFERSUBDATAPROC)GLH_EXT_GET_PROC_ADDRESS("glCopyNamedBufferSubData");
+ glClearNamedBufferData = (PFNGLCLEARNAMEDBUFFERDATAPROC)GLH_EXT_GET_PROC_ADDRESS("glClearNamedBufferData");
+ glClearNamedBufferSubData = (PFNGLCLEARNAMEDBUFFERSUBDATAPROC)GLH_EXT_GET_PROC_ADDRESS("glClearNamedBufferSubData");
+ glMapNamedBuffer = (PFNGLMAPNAMEDBUFFERPROC)GLH_EXT_GET_PROC_ADDRESS("glMapNamedBuffer");
+ glMapNamedBufferRange = (PFNGLMAPNAMEDBUFFERRANGEPROC)GLH_EXT_GET_PROC_ADDRESS("glMapNamedBufferRange");
+ glUnmapNamedBuffer = (PFNGLUNMAPNAMEDBUFFERPROC)GLH_EXT_GET_PROC_ADDRESS("glUnmapNamedBuffer");
+ glFlushMappedNamedBufferRange = (PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEPROC)GLH_EXT_GET_PROC_ADDRESS("glFlushMappedNamedBufferRange");
+ glGetNamedBufferParameteriv = (PFNGLGETNAMEDBUFFERPARAMETERIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetNamedBufferParameteriv");
+ glGetNamedBufferParameteri64v = (PFNGLGETNAMEDBUFFERPARAMETERI64VPROC)GLH_EXT_GET_PROC_ADDRESS("glGetNamedBufferParameteri64v");
+ glGetNamedBufferPointerv = (PFNGLGETNAMEDBUFFERPOINTERVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetNamedBufferPointerv");
+ glGetNamedBufferSubData = (PFNGLGETNAMEDBUFFERSUBDATAPROC)GLH_EXT_GET_PROC_ADDRESS("glGetNamedBufferSubData");
+ glCreateFramebuffers = (PFNGLCREATEFRAMEBUFFERSPROC)GLH_EXT_GET_PROC_ADDRESS("glCreateFramebuffers");
+ glNamedFramebufferRenderbuffer = (PFNGLNAMEDFRAMEBUFFERRENDERBUFFERPROC)GLH_EXT_GET_PROC_ADDRESS("glNamedFramebufferRenderbuffer");
+ glNamedFramebufferParameteri = (PFNGLNAMEDFRAMEBUFFERPARAMETERIPROC)GLH_EXT_GET_PROC_ADDRESS("glNamedFramebufferParameteri");
+ glNamedFramebufferTexture = (PFNGLNAMEDFRAMEBUFFERTEXTUREPROC)GLH_EXT_GET_PROC_ADDRESS("glNamedFramebufferTexture");
+ glNamedFramebufferTextureLayer = (PFNGLNAMEDFRAMEBUFFERTEXTURELAYERPROC)GLH_EXT_GET_PROC_ADDRESS("glNamedFramebufferTextureLayer");
+ glNamedFramebufferDrawBuffer = (PFNGLNAMEDFRAMEBUFFERDRAWBUFFERPROC)GLH_EXT_GET_PROC_ADDRESS("glNamedFramebufferDrawBuffer");
+ glNamedFramebufferDrawBuffers = (PFNGLNAMEDFRAMEBUFFERDRAWBUFFERSPROC)GLH_EXT_GET_PROC_ADDRESS("glNamedFramebufferDrawBuffers");
+ glNamedFramebufferReadBuffer = (PFNGLNAMEDFRAMEBUFFERREADBUFFERPROC)GLH_EXT_GET_PROC_ADDRESS("glNamedFramebufferReadBuffer");
+ glInvalidateNamedFramebufferData = (PFNGLINVALIDATENAMEDFRAMEBUFFERDATAPROC)GLH_EXT_GET_PROC_ADDRESS("glInvalidateNamedFramebufferData");
+ glInvalidateNamedFramebufferSubData = (PFNGLINVALIDATENAMEDFRAMEBUFFERSUBDATAPROC)GLH_EXT_GET_PROC_ADDRESS("glInvalidateNamedFramebufferSubData");
+ glClearNamedFramebufferiv = (PFNGLCLEARNAMEDFRAMEBUFFERIVPROC)GLH_EXT_GET_PROC_ADDRESS("glClearNamedFramebufferiv");
+ glClearNamedFramebufferuiv = (PFNGLCLEARNAMEDFRAMEBUFFERUIVPROC)GLH_EXT_GET_PROC_ADDRESS("glClearNamedFramebufferuiv");
+ glClearNamedFramebufferfv = (PFNGLCLEARNAMEDFRAMEBUFFERFVPROC)GLH_EXT_GET_PROC_ADDRESS("glClearNamedFramebufferfv");
+ glClearNamedFramebufferfi = (PFNGLCLEARNAMEDFRAMEBUFFERFIPROC)GLH_EXT_GET_PROC_ADDRESS("glClearNamedFramebufferfi");
+ glBlitNamedFramebuffer = (PFNGLBLITNAMEDFRAMEBUFFERPROC)GLH_EXT_GET_PROC_ADDRESS("glBlitNamedFramebuffer");
+ glCheckNamedFramebufferStatus = (PFNGLCHECKNAMEDFRAMEBUFFERSTATUSPROC)GLH_EXT_GET_PROC_ADDRESS("glCheckNamedFramebufferStatus");
+ glGetNamedFramebufferParameteriv = (PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetNamedFramebufferParameteriv");
+ glGetNamedFramebufferAttachmentParameteriv = (PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetNamedFramebufferAttachmentParameteriv");
+ glCreateRenderbuffers = (PFNGLCREATERENDERBUFFERSPROC)GLH_EXT_GET_PROC_ADDRESS("glCreateRenderbuffers");
+ glNamedRenderbufferStorage = (PFNGLNAMEDRENDERBUFFERSTORAGEPROC)GLH_EXT_GET_PROC_ADDRESS("glNamedRenderbufferStorage");
+ glNamedRenderbufferStorageMultisample = (PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEPROC)GLH_EXT_GET_PROC_ADDRESS("glNamedRenderbufferStorageMultisample");
+ glGetNamedRenderbufferParameteriv = (PFNGLGETNAMEDRENDERBUFFERPARAMETERIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetNamedRenderbufferParameteriv");
+ glCreateTextures = (PFNGLCREATETEXTURESPROC)GLH_EXT_GET_PROC_ADDRESS("glCreateTextures");
+ glTextureBuffer = (PFNGLTEXTUREBUFFERPROC)GLH_EXT_GET_PROC_ADDRESS("glTextureBuffer");
+ glTextureBufferRange = (PFNGLTEXTUREBUFFERRANGEPROC)GLH_EXT_GET_PROC_ADDRESS("glTextureBufferRange");
+ glTextureStorage1D = (PFNGLTEXTURESTORAGE1DPROC)GLH_EXT_GET_PROC_ADDRESS("glTextureStorage1D");
+ glTextureStorage2D = (PFNGLTEXTURESTORAGE2DPROC)GLH_EXT_GET_PROC_ADDRESS("glTextureStorage2D");
+ glTextureStorage3D = (PFNGLTEXTURESTORAGE3DPROC)GLH_EXT_GET_PROC_ADDRESS("glTextureStorage3D");
+ glTextureStorage2DMultisample = (PFNGLTEXTURESTORAGE2DMULTISAMPLEPROC)GLH_EXT_GET_PROC_ADDRESS("glTextureStorage2DMultisample");
+ glTextureStorage3DMultisample = (PFNGLTEXTURESTORAGE3DMULTISAMPLEPROC)GLH_EXT_GET_PROC_ADDRESS("glTextureStorage3DMultisample");
+ glTextureSubImage1D = (PFNGLTEXTURESUBIMAGE1DPROC)GLH_EXT_GET_PROC_ADDRESS("glTextureSubImage1D");
+ glTextureSubImage2D = (PFNGLTEXTURESUBIMAGE2DPROC)GLH_EXT_GET_PROC_ADDRESS("glTextureSubImage2D");
+ glTextureSubImage3D = (PFNGLTEXTURESUBIMAGE3DPROC)GLH_EXT_GET_PROC_ADDRESS("glTextureSubImage3D");
+ glCompressedTextureSubImage1D = (PFNGLCOMPRESSEDTEXTURESUBIMAGE1DPROC)GLH_EXT_GET_PROC_ADDRESS("glCompressedTextureSubImage1D");
+ glCompressedTextureSubImage2D = (PFNGLCOMPRESSEDTEXTURESUBIMAGE2DPROC)GLH_EXT_GET_PROC_ADDRESS("glCompressedTextureSubImage2D");
+ glCompressedTextureSubImage3D = (PFNGLCOMPRESSEDTEXTURESUBIMAGE3DPROC)GLH_EXT_GET_PROC_ADDRESS("glCompressedTextureSubImage3D");
+ glCopyTextureSubImage1D = (PFNGLCOPYTEXTURESUBIMAGE1DPROC)GLH_EXT_GET_PROC_ADDRESS("glCopyTextureSubImage1D");
+ glCopyTextureSubImage2D = (PFNGLCOPYTEXTURESUBIMAGE2DPROC)GLH_EXT_GET_PROC_ADDRESS("glCopyTextureSubImage2D");
+ glCopyTextureSubImage3D = (PFNGLCOPYTEXTURESUBIMAGE3DPROC)GLH_EXT_GET_PROC_ADDRESS("glCopyTextureSubImage3D");
+ glTextureParameterf = (PFNGLTEXTUREPARAMETERFPROC)GLH_EXT_GET_PROC_ADDRESS("glTextureParameterf");
+ glTextureParameterfv = (PFNGLTEXTUREPARAMETERFVPROC)GLH_EXT_GET_PROC_ADDRESS("glTextureParameterfv");
+ glTextureParameteri = (PFNGLTEXTUREPARAMETERIPROC)GLH_EXT_GET_PROC_ADDRESS("glTextureParameteri");
+ glTextureParameterIiv = (PFNGLTEXTUREPARAMETERIIVPROC)GLH_EXT_GET_PROC_ADDRESS("glTextureParameterIiv");
+ glTextureParameterIuiv = (PFNGLTEXTUREPARAMETERIUIVPROC)GLH_EXT_GET_PROC_ADDRESS("glTextureParameterIuiv");
+ glTextureParameteriv = (PFNGLTEXTUREPARAMETERIVPROC)GLH_EXT_GET_PROC_ADDRESS("glTextureParameteriv");
+ glGenerateTextureMipmap = (PFNGLGENERATETEXTUREMIPMAPPROC)GLH_EXT_GET_PROC_ADDRESS("glGenerateTextureMipmap");
+ glBindTextureUnit = (PFNGLBINDTEXTUREUNITPROC)GLH_EXT_GET_PROC_ADDRESS("glBindTextureUnit");
+ glGetTextureImage = (PFNGLGETTEXTUREIMAGEPROC)GLH_EXT_GET_PROC_ADDRESS("glGetTextureImage");
+ glGetCompressedTextureImage = (PFNGLGETCOMPRESSEDTEXTUREIMAGEPROC)GLH_EXT_GET_PROC_ADDRESS("glGetCompressedTextureImage");
+ glGetTextureLevelParameterfv = (PFNGLGETTEXTURELEVELPARAMETERFVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetTextureLevelParameterfv");
+ glGetTextureLevelParameteriv = (PFNGLGETTEXTURELEVELPARAMETERIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetTextureLevelParameteriv");
+ glGetTextureParameterfv = (PFNGLGETTEXTUREPARAMETERFVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetTextureParameterfv");
+ glGetTextureParameterIiv = (PFNGLGETTEXTUREPARAMETERIIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetTextureParameterIiv");
+ glGetTextureParameterIuiv = (PFNGLGETTEXTUREPARAMETERIUIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetTextureParameterIuiv");
+ glGetTextureParameteriv = (PFNGLGETTEXTUREPARAMETERIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetTextureParameteriv");
+ glCreateVertexArrays = (PFNGLCREATEVERTEXARRAYSPROC)GLH_EXT_GET_PROC_ADDRESS("glCreateVertexArrays");
+ glDisableVertexArrayAttrib = (PFNGLDISABLEVERTEXARRAYATTRIBPROC)GLH_EXT_GET_PROC_ADDRESS("glDisableVertexArrayAttrib");
+ glEnableVertexArrayAttrib = (PFNGLENABLEVERTEXARRAYATTRIBPROC)GLH_EXT_GET_PROC_ADDRESS("glEnableVertexArrayAttrib");
+ glVertexArrayElementBuffer = (PFNGLVERTEXARRAYELEMENTBUFFERPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexArrayElementBuffer");
+ glVertexArrayVertexBuffer = (PFNGLVERTEXARRAYVERTEXBUFFERPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexArrayVertexBuffer");
+ glVertexArrayVertexBuffers = (PFNGLVERTEXARRAYVERTEXBUFFERSPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexArrayVertexBuffers");
+ glVertexArrayAttribBinding = (PFNGLVERTEXARRAYATTRIBBINDINGPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexArrayAttribBinding");
+ glVertexArrayAttribFormat = (PFNGLVERTEXARRAYATTRIBFORMATPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexArrayAttribFormat");
+ glVertexArrayAttribIFormat = (PFNGLVERTEXARRAYATTRIBIFORMATPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexArrayAttribIFormat");
+ glVertexArrayAttribLFormat = (PFNGLVERTEXARRAYATTRIBLFORMATPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexArrayAttribLFormat");
+ glVertexArrayBindingDivisor = (PFNGLVERTEXARRAYBINDINGDIVISORPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexArrayBindingDivisor");
+ glGetVertexArrayiv = (PFNGLGETVERTEXARRAYIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetVertexArrayiv");
+ glGetVertexArrayIndexediv = (PFNGLGETVERTEXARRAYINDEXEDIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetVertexArrayIndexediv");
+ glGetVertexArrayIndexed64iv = (PFNGLGETVERTEXARRAYINDEXED64IVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetVertexArrayIndexed64iv");
+ glCreateSamplers = (PFNGLCREATESAMPLERSPROC)GLH_EXT_GET_PROC_ADDRESS("glCreateSamplers");
+ glCreateProgramPipelines = (PFNGLCREATEPROGRAMPIPELINESPROC)GLH_EXT_GET_PROC_ADDRESS("glCreateProgramPipelines");
+ glCreateQueries = (PFNGLCREATEQUERIESPROC)GLH_EXT_GET_PROC_ADDRESS("glCreateQueries");
+ glGetQueryBufferObjecti64v = (PFNGLGETQUERYBUFFEROBJECTI64VPROC)GLH_EXT_GET_PROC_ADDRESS("glGetQueryBufferObjecti64v");
+ glGetQueryBufferObjectiv = (PFNGLGETQUERYBUFFEROBJECTIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetQueryBufferObjectiv");
+ glGetQueryBufferObjectui64v = (PFNGLGETQUERYBUFFEROBJECTUI64VPROC)GLH_EXT_GET_PROC_ADDRESS("glGetQueryBufferObjectui64v");
+ glGetQueryBufferObjectuiv = (PFNGLGETQUERYBUFFEROBJECTUIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetQueryBufferObjectuiv");
+ glMemoryBarrierByRegion = (PFNGLMEMORYBARRIERBYREGIONPROC)GLH_EXT_GET_PROC_ADDRESS("glMemoryBarrierByRegion");
+ glGetTextureSubImage = (PFNGLGETTEXTURESUBIMAGEPROC)GLH_EXT_GET_PROC_ADDRESS("glGetTextureSubImage");
+ glGetCompressedTextureSubImage = (PFNGLGETCOMPRESSEDTEXTURESUBIMAGEPROC)GLH_EXT_GET_PROC_ADDRESS("glGetCompressedTextureSubImage");
+ glGetGraphicsResetStatus = (PFNGLGETGRAPHICSRESETSTATUSPROC)GLH_EXT_GET_PROC_ADDRESS("glGetGraphicsResetStatus");
+ glGetnCompressedTexImage = (PFNGLGETNCOMPRESSEDTEXIMAGEPROC)GLH_EXT_GET_PROC_ADDRESS("glGetnCompressedTexImage");
+ glGetnTexImage = (PFNGLGETNTEXIMAGEPROC)GLH_EXT_GET_PROC_ADDRESS("glGetnTexImage");
+ glGetnUniformdv = (PFNGLGETNUNIFORMDVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetnUniformdv");
+ glGetnUniformfv = (PFNGLGETNUNIFORMFVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetnUniformfv");
+ glGetnUniformiv = (PFNGLGETNUNIFORMIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetnUniformiv");
+ glGetnUniformuiv = (PFNGLGETNUNIFORMUIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetnUniformuiv");
+ glReadnPixels = (PFNGLREADNPIXELSPROC)GLH_EXT_GET_PROC_ADDRESS("glReadnPixels");
+ glGetnMapdv = (PFNGLGETNMAPDVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetnMapdv");
+ glGetnMapfv = (PFNGLGETNMAPFVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetnMapfv");
+ glGetnMapiv = (PFNGLGETNMAPIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetnMapiv");
+ glGetnPixelMapfv = (PFNGLGETNPIXELMAPFVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetnPixelMapfv");
+ glGetnPixelMapuiv = (PFNGLGETNPIXELMAPUIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetnPixelMapuiv");
+ glGetnPixelMapusv = (PFNGLGETNPIXELMAPUSVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetnPixelMapusv");
+ glGetnPolygonStipple = (PFNGLGETNPOLYGONSTIPPLEPROC)GLH_EXT_GET_PROC_ADDRESS("glGetnPolygonStipple");
+ glGetnColorTable = (PFNGLGETNCOLORTABLEPROC)GLH_EXT_GET_PROC_ADDRESS("glGetnColorTable");
+ glGetnConvolutionFilter = (PFNGLGETNCONVOLUTIONFILTERPROC)GLH_EXT_GET_PROC_ADDRESS("glGetnConvolutionFilter");
+ glGetnSeparableFilter = (PFNGLGETNSEPARABLEFILTERPROC)GLH_EXT_GET_PROC_ADDRESS("glGetnSeparableFilter");
+ glGetnHistogram = (PFNGLGETNHISTOGRAMPROC)GLH_EXT_GET_PROC_ADDRESS("glGetnHistogram");
+ glGetnMinmax = (PFNGLGETNMINMAXPROC)GLH_EXT_GET_PROC_ADDRESS("glGetnMinmax");
+ glTextureBarrier = (PFNGLTEXTUREBARRIERPROC)GLH_EXT_GET_PROC_ADDRESS("glTextureBarrier");
+
+ // GL_VERSION_4_6
+ if (mGLVersion < 4.59f)
+ {
+ return;
+ }
+ glSpecializeShader = (PFNGLSPECIALIZESHADERPROC)GLH_EXT_GET_PROC_ADDRESS("glSpecializeShader");
+ glMultiDrawArraysIndirectCount = (PFNGLMULTIDRAWARRAYSINDIRECTCOUNTPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiDrawArraysIndirectCount");
+ glMultiDrawElementsIndirectCount = (PFNGLMULTIDRAWELEMENTSINDIRECTCOUNTPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiDrawElementsIndirectCount");
+ glPolygonOffsetClamp = (PFNGLPOLYGONOFFSETCLAMPPROC)GLH_EXT_GET_PROC_ADDRESS("glPolygonOffsetClamp");
+
#endif
-
- mInited = TRUE;
}
void rotate_quat(LLQuaternion& rotation)
@@ -1492,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);
@@ -1517,7 +2295,6 @@ void do_assert_glerror()
gFailLog << "GL Error: UNKNOWN 0x" << std::hex << error << std::dec << std::endl;
}
}
- error = glGetError();
}
if (quit)
@@ -1582,8 +2359,8 @@ void LLGLState::initClass()
// sStateMap[GL_TEXTURE_2D] = GL_TRUE;
//make sure multisample defaults to disabled
- sStateMap[GL_MULTISAMPLE_ARB] = GL_FALSE;
- glDisable(GL_MULTISAMPLE_ARB);
+ sStateMap[GL_MULTISAMPLE] = GL_FALSE;
+ glDisable(GL_MULTISAMPLE);
}
//static
@@ -1604,7 +2381,7 @@ void LLGLState::resetTextureStates()
for (S32 j = maxTextureUnits-1; j >=0; j--)
{
gGL.getTexUnit(j)->activate();
- glClientActiveTextureARB(GL_TEXTURE0_ARB+j);
+ glClientActiveTexture(GL_TEXTURE0+j);
j == 0 ? gGL.getTexUnit(j)->enable(LLTexUnit::TT_TEXTURE) : gGL.getTexUnit(j)->disable();
}
}
@@ -1619,240 +2396,40 @@ void LLGLState::dumpStates()
}
}
-void LLGLState::checkStates(const std::string& msg)
+void LLGLState::checkStates(GLboolean writeAlpha)
{
if (!gDebugGL)
{
return;
}
- stop_glerror();
-
GLint src;
GLint dst;
glGetIntegerv(GL_BLEND_SRC, &src);
glGetIntegerv(GL_BLEND_DST, &dst);
-
- stop_glerror();
-
- BOOL error = FALSE;
-
- if (src != GL_SRC_ALPHA || dst != GL_ONE_MINUS_SRC_ALPHA)
- {
- if (gDebugSession)
- {
- gFailLog << "Blend function corrupted: " << std::hex << src << " " << std::hex << dst << " " << msg << std::dec << std::endl;
- error = TRUE;
- }
- else
- {
- LL_GL_ERRS << "Blend function corrupted: " << std::hex << src << " " << std::hex << dst << " " << msg << std::dec << LL_ENDL;
- }
- }
+ llassert_always(src == GL_SRC_ALPHA);
+ llassert_always(dst == GL_ONE_MINUS_SRC_ALPHA);
+
+ // 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<LLGLenum, LLGLboolean>::iterator iter = sStateMap.begin();
iter != sStateMap.end(); ++iter)
{
LLGLenum state = iter->first;
LLGLboolean cur_state = iter->second;
- stop_glerror();
LLGLboolean gl_state = glIsEnabled(state);
- stop_glerror();
if(cur_state != gl_state)
{
dumpStates();
- if (gDebugSession)
- {
- gFailLog << llformat("LLGLState error. State: 0x%04x",state) << std::endl;
- error = TRUE;
- }
- else
- {
- LL_GL_ERRS << llformat("LLGLState error. State: 0x%04x",state) << LL_ENDL;
- }
- }
- }
-
- if (error)
- {
- ll_fail("LLGLState::checkStates failed.");
- }
- stop_glerror();
-}
-
-void LLGLState::checkTextureChannels(const std::string& msg)
-{
-#if 0
- if (!gDebugGL)
- {
- return;
- }
- stop_glerror();
-
- GLint activeTexture;
- glGetIntegerv(GL_ACTIVE_TEXTURE_ARB, &activeTexture);
- stop_glerror();
-
- BOOL error = FALSE;
-
- if (activeTexture == GL_TEXTURE0_ARB)
- {
- GLint tex_env_mode = 0;
-
- glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &tex_env_mode);
- stop_glerror();
-
- if (tex_env_mode != GL_MODULATE)
- {
- error = TRUE;
- LL_WARNS("RenderState") << "GL_TEXTURE_ENV_MODE invalid: " << std::hex << tex_env_mode << std::dec << LL_ENDL;
- if (gDebugSession)
- {
- gFailLog << "GL_TEXTURE_ENV_MODE invalid: " << std::hex << tex_env_mode << std::dec << std::endl;
- }
+ LL_GL_ERRS << llformat("LLGLState error. State: 0x%04x",state) << LL_ENDL;
}
}
-
- static const char* label[] =
- {
- "GL_TEXTURE_2D",
- "GL_TEXTURE_COORD_ARRAY",
- "GL_TEXTURE_1D",
- "GL_TEXTURE_CUBE_MAP_ARB",
- "GL_TEXTURE_GEN_S",
- "GL_TEXTURE_GEN_T",
- "GL_TEXTURE_GEN_Q",
- "GL_TEXTURE_GEN_R",
- "GL_TEXTURE_RECTANGLE_ARB",
- "GL_TEXTURE_2D_MULTISAMPLE"
- };
-
- static GLint value[] =
- {
- GL_TEXTURE_2D,
- GL_TEXTURE_COORD_ARRAY,
- GL_TEXTURE_1D,
- GL_TEXTURE_CUBE_MAP_ARB,
- GL_TEXTURE_GEN_S,
- GL_TEXTURE_GEN_T,
- GL_TEXTURE_GEN_Q,
- GL_TEXTURE_GEN_R,
- GL_TEXTURE_RECTANGLE_ARB,
- GL_TEXTURE_2D_MULTISAMPLE
- };
-
- GLint stackDepth = 0;
-
- glh::matrix4f mat;
- glh::matrix4f identity;
- identity.identity();
-
- for (GLint i = 1; i < gGLManager.mNumTextureUnits; i++)
- {
- gGL.getTexUnit(i)->activate();
-
- if (i < gGLManager.mNumTextureUnits)
- {
- glClientActiveTextureARB(GL_TEXTURE0_ARB+i);
- stop_glerror();
- glGetIntegerv(GL_TEXTURE_STACK_DEPTH, &stackDepth);
- stop_glerror();
-
- if (stackDepth != 1)
- {
- error = TRUE;
- LL_WARNS("RenderState") << "Texture matrix stack corrupted." << LL_ENDL;
-
- if (gDebugSession)
- {
- gFailLog << "Texture matrix stack corrupted." << std::endl;
- }
- }
-
- glGetFloatv(GL_TEXTURE_MATRIX, (GLfloat*) mat.m);
- stop_glerror();
-
- if (mat != identity)
- {
- error = TRUE;
- LL_WARNS("RenderState") << "Texture matrix in channel " << i << " corrupt." << LL_ENDL;
- if (gDebugSession)
- {
- gFailLog << "Texture matrix in channel " << i << " corrupt." << std::endl;
- }
- }
-
- for (S32 j = (i == 0 ? 1 : 0);
- j < 9; j++)
- {
- if (j == 8 && !gGLManager.mHasTextureRectangle ||
- j == 9 && !gGLManager.mHasTextureMultisample)
- {
- continue;
- }
-
- if (glIsEnabled(value[j]))
- {
- error = TRUE;
- LL_WARNS("RenderState") << "Texture channel " << i << " still has " << label[j] << " enabled." << LL_ENDL;
- if (gDebugSession)
- {
- gFailLog << "Texture channel " << i << " still has " << label[j] << " enabled." << std::endl;
- }
- }
- stop_glerror();
- }
-
- glGetFloatv(GL_TEXTURE_MATRIX, mat.m);
- stop_glerror();
-
- if (mat != identity)
- {
- error = TRUE;
- LL_WARNS("RenderState") << "Texture matrix " << i << " is not identity." << LL_ENDL;
- if (gDebugSession)
- {
- gFailLog << "Texture matrix " << i << " is not identity." << std::endl;
- }
- }
- }
-
- {
- GLint tex = 0;
- stop_glerror();
- glGetIntegerv(GL_TEXTURE_BINDING_2D, &tex);
- stop_glerror();
-
- if (tex != 0)
- {
- error = TRUE;
- LL_WARNS("RenderState") << "Texture channel " << i << " still has texture " << tex << " bound." << LL_ENDL;
-
- if (gDebugSession)
- {
- gFailLog << "Texture channel " << i << " still has texture " << tex << " bound." << std::endl;
- }
- }
- }
- }
-
- stop_glerror();
- gGL.getTexUnit(0)->activate();
- glClientActiveTextureARB(GL_TEXTURE0_ARB);
- stop_glerror();
-
- if (error)
- {
- if (gDebugSession)
- {
- ll_fail("LLGLState::checkTextureChannels failed.");
- }
- else
- {
- LL_GL_ERRS << "GL texture state corruption detected. " << msg << LL_ENDL;
- }
- }
-#endif
}
///////////////////////////////////////////////////////////////////////
@@ -2281,36 +2858,29 @@ LLGLSquashToFarClip::~LLGLSquashToFarClip()
LLGLSyncFence::LLGLSyncFence()
{
-#ifdef GL_ARB_sync
mSync = 0;
-#endif
}
LLGLSyncFence::~LLGLSyncFence()
{
-#ifdef GL_ARB_sync
if (mSync)
{
glDeleteSync(mSync);
}
-#endif
}
void LLGLSyncFence::placeFence()
{
-#ifdef GL_ARB_sync
if (mSync)
{
glDeleteSync(mSync);
}
mSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
-#endif
}
bool LLGLSyncFence::isCompleted()
{
bool ret = true;
-#ifdef GL_ARB_sync
if (mSync)
{
GLenum status = glClientWaitSync(mSync, 0, 1);
@@ -2319,13 +2889,11 @@ bool LLGLSyncFence::isCompleted()
ret = false;
}
}
-#endif
return ret;
}
void LLGLSyncFence::wait()
{
-#ifdef GL_ARB_sync
if (mSync)
{
while (glClientWaitSync(mSync, 0, FENCE_WAIT_TIME_NANOSECONDS) == GL_TIMEOUT_EXPIRED)
@@ -2334,7 +2902,6 @@ void LLGLSyncFence::wait()
waits++;
}
}
-#endif
}
LLGLSPipelineSkyBox::LLGLSPipelineSkyBox()
diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h
index 33cb0706c4..eb0650d998 100644
--- a/indra/llrender/llgl.h
+++ b/indra/llrender/llgl.h
@@ -76,50 +76,27 @@ public:
BOOL mInited;
BOOL mIsDisabled;
- // Extensions used by everyone
- BOOL mHasMultitexture;
- BOOL mHasATIMemInfo;
- BOOL mHasAMDAssociations;
- BOOL mHasNVXMemInfo;
- S32 mNumTextureUnits;
- BOOL mHasMipMapGeneration;
- BOOL mHasCompressedTextures;
- BOOL mHasFramebufferObject;
+ // OpenGL limits
S32 mMaxSamples;
- BOOL mHasBlendFuncSeparate;
-
- // ARB Extensions
- BOOL mHasVertexBufferObject;
- BOOL mHasVertexArrayObject;
- BOOL mHasSync;
- BOOL mHasMapBufferRange;
- BOOL mHasFlushBufferRange;
- BOOL mHasPBuffer;
- S32 mNumTextureImageUnits;
- BOOL mHasOcclusionQuery;
- BOOL mHasTimerQuery;
- BOOL mHasOcclusionQuery2;
- BOOL mHasPointParameters;
- BOOL mHasDrawBuffers;
- BOOL mHasDepthClamp;
- BOOL mHasTextureRectangle;
- BOOL mHasTextureMultisample;
- BOOL mHasTransformFeedback;
+ S32 mNumTextureImageUnits;
S32 mMaxSampleMaskWords;
S32 mMaxColorTextureSamples;
S32 mMaxDepthTextureSamples;
S32 mMaxIntegerSamples;
-
- // Other extensions.
- BOOL mHasAnisotropic;
- BOOL mHasARBEnvCombine;
- BOOL mHasCubeMap;
- BOOL mHasDebugOutput;
- BOOL mHassRGBTexture;
- BOOL mHassRGBFramebuffer;
- BOOL mHasTexturesRGBDecode;
-
+ S32 mGLMaxVertexRange;
+ S32 mGLMaxIndexRange;
+ S32 mGLMaxTextureSize;
+ F32 mMaxAnisotropy = 0.f;
+
+ // GL 4.x capabilities
+ bool mHasCubeMapArray = false;
+ bool mHasDebugOutput = false;
+ bool mHasTransformFeedback = false;
+ bool mHasAnisotropic = false;
+
// Vendor-specific extensions
+ bool mHasAMDAssociations = false;
+
BOOL mIsAMD;
BOOL mIsNVIDIA;
BOOL mIsIntel;
@@ -132,9 +109,6 @@ public:
// Whether this version of GL is good enough for SL to use
BOOL mHasRequirements;
- // Misc extensions
- BOOL mHasSeparateSpecularColor;
-
S32 mDriverVersionMajor;
S32 mDriverVersionMinor;
S32 mDriverVersionRelease;
@@ -145,9 +119,6 @@ public:
std::string mGLVersionString;
S32 mVRAM; // VRAM in MB
- S32 mGLMaxVertexRange;
- S32 mGLMaxIndexRange;
- S32 mGLMaxTextureSize;
void getPixelFormat(); // Get the best pixel format
@@ -260,9 +231,12 @@ public:
static void resetTextureStates();
static void dumpStates();
- static void checkStates(const std::string& msg = "");
- static void checkTextureChannels(const std::string& msg = "");
-
+
+ // make sure GL blend function, GL states, and GL color mask match
+ // what we expect
+ // writeAlpha - whether or not writing to alpha channel is expected
+ static void checkStates(GLboolean writeAlpha = GL_TRUE);
+
protected:
static boost::unordered_map<LLGLenum, LLGLboolean> sStateMap;
@@ -413,9 +387,7 @@ public:
class LLGLSyncFence : public LLGLFence
{
public:
-#ifdef GL_ARB_sync
GLsync mSync;
-#endif
LLGLSyncFence();
virtual ~LLGLSyncFence();
diff --git a/indra/llrender/llglcommonfunc.cpp b/indra/llrender/llglcommonfunc.cpp
index e9ec28927f..04d29b9430 100644
--- a/indra/llrender/llglcommonfunc.cpp
+++ b/indra/llrender/llglcommonfunc.cpp
@@ -31,7 +31,8 @@ namespace LLGLCommonFunc
{
void selected_stencil_test()
{
- glStencilFunc(GL_ALWAYS, 2, 0xffff);
- glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
+ // deprecated
+ //glStencilFunc(GL_ALWAYS, 2, 0xffff);
+ //glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
}
}
diff --git a/indra/llrender/llglheaders.h b/indra/llrender/llglheaders.h
index 3d93cc0762..b80680a3d2 100644
--- a/indra/llrender/llglheaders.h
+++ b/indra/llrender/llglheaders.h
@@ -41,278 +41,6 @@
# include "GL/glh_extensions.h"
# undef __APPLE__
-#elif LL_LINUX
-//----------------------------------------------------------------------------
-// LL_LINUX
-
-//----------------------------------------------------------------------------
-// Linux, MESA headers, but not necessarily assuming MESA runtime.
-// quotes so we get libraries/.../GL/ version
-#include "GL/gl.h"
-#include "GL/glext.h"
-#include "GL/glu.h"
-
-
-#if LL_LINUX && !LL_MESA_HEADLESS
-// The __APPLE__ kludge is to make glh_extensions.h not symbol-clash horribly
-# define __APPLE__
-# include "GL/glh_extensions.h"
-# undef __APPLE__
-
-/* Although SDL very likely ends up calling glXGetProcAddress() itself,
- if we use SDL_GL_GetProcAddress() then we get bogus addresses back on
- some systems. Weird. */
-/*# include "SDL/SDL.h"
- # define GLH_EXT_GET_PROC_ADDRESS(p) SDL_GL_GetProcAddress(p) */
-#define GLX_GLXEXT_PROTOTYPES 1
-# include "GL/glx.h"
-# include "GL/glxext.h"
-// Use glXGetProcAddressARB instead of glXGetProcAddress - the ARB symbol
-// is considered 'legacy' but works on more machines.
-# define GLH_EXT_GET_PROC_ADDRESS(p) glXGetProcAddressARB((const GLubyte*)(p))
-#endif // LL_LINUX && !LL_MESA_HEADLESS
-
-#if LL_LINUX && defined(WINGDIAPI)
-// WINGDIAPI gets set if we are using the linux nvidia gl.h header which needs
-// the functions below setting up.
-# define LL_LINUX_NV_GL_HEADERS 1
-#else
-# define LL_LINUX_NV_GL_HEADERS 0
-#endif // LL_LINUX && defined(WINGDIAPI)
-
-
-#if LL_LINUX_NV_GL_HEADERS
-// Missing functions when using nvidia headers:
-extern PFNGLACTIVETEXTUREARBPROC glActiveTextureARB;
-extern PFNGLCLIENTACTIVETEXTUREARBPROC glClientActiveTextureARB;
-extern PFNGLDRAWRANGEELEMENTSPROC glDrawRangeElements;
-#endif // LL_LINUX_NV_GL_HEADERS
-
-// GL_ARB_vertex_array_object
-extern PFNGLBINDVERTEXARRAYPROC glBindVertexArray;
-extern PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays;
-extern PFNGLGENVERTEXARRAYSPROC glGenVertexArrays;
-extern PFNGLISVERTEXARRAYPROC glIsVertexArray;
-
-// GL_ARB_vertex_buffer_object
-extern PFNGLBINDBUFFERARBPROC glBindBufferARB;
-extern PFNGLDELETEBUFFERSARBPROC glDeleteBuffersARB;
-extern PFNGLGENBUFFERSARBPROC glGenBuffersARB;
-extern PFNGLISBUFFERARBPROC glIsBufferARB;
-extern PFNGLBUFFERDATAARBPROC glBufferDataARB;
-extern PFNGLBUFFERSUBDATAARBPROC glBufferSubDataARB;
-extern PFNGLGETBUFFERSUBDATAARBPROC glGetBufferSubDataARB;
-extern PFNGLMAPBUFFERARBPROC glMapBufferARB;
-extern PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB;
-extern PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB;
-extern PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB;
-
-// GL_ARB_sync
-extern PFNGLFENCESYNCPROC glFenceSync;
-extern PFNGLISSYNCPROC glIsSync;
-extern PFNGLDELETESYNCPROC glDeleteSync;
-extern PFNGLCLIENTWAITSYNCPROC glClientWaitSync;
-extern PFNGLWAITSYNCPROC glWaitSync;
-extern PFNGLGETINTEGER64VPROC glGetInteger64v;
-extern PFNGLGETSYNCIVPROC glGetSynciv;
-
-// GL_APPLE_flush_buffer_range
-extern PFNGLBUFFERPARAMETERIAPPLEPROC glBufferParameteriAPPLE;
-extern PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC glFlushMappedBufferRangeAPPLE;
-
-// GL_ARB_map_buffer_range
-extern PFNGLMAPBUFFERRANGEPROC glMapBufferRange;
-extern PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange;
-
-// GL_ATI_vertex_array_object
-extern PFNGLNEWOBJECTBUFFERATIPROC glNewObjectBufferATI;
-extern PFNGLISOBJECTBUFFERATIPROC glIsObjectBufferATI;
-extern PFNGLUPDATEOBJECTBUFFERATIPROC glUpdateObjectBufferATI;
-extern PFNGLGETOBJECTBUFFERFVATIPROC glGetObjectBufferfvATI;
-extern PFNGLGETOBJECTBUFFERIVATIPROC glGetObjectBufferivATI;
-extern PFNGLFREEOBJECTBUFFERATIPROC glFreeObjectBufferATI;
-extern PFNGLARRAYOBJECTATIPROC glArrayObjectATI;
-extern PFNGLVERTEXATTRIBARRAYOBJECTATIPROC glVertexAttribArrayObjectATI;
-extern PFNGLGETARRAYOBJECTFVATIPROC glGetArrayObjectfvATI;
-extern PFNGLGETARRAYOBJECTIVATIPROC glGetArrayObjectivATI;
-extern PFNGLVARIANTARRAYOBJECTATIPROC glVariantObjectArrayATI;
-extern PFNGLGETVARIANTARRAYOBJECTFVATIPROC glGetVariantArrayObjectfvATI;
-extern PFNGLGETVARIANTARRAYOBJECTIVATIPROC glGetVariantArrayObjectivATI;
-
-// GL_ARB_occlusion_query
-extern PFNGLGENQUERIESARBPROC glGenQueriesARB;
-extern PFNGLDELETEQUERIESARBPROC glDeleteQueriesARB;
-extern PFNGLISQUERYARBPROC glIsQueryARB;
-extern PFNGLBEGINQUERYARBPROC glBeginQueryARB;
-extern PFNGLENDQUERYARBPROC glEndQueryARB;
-extern PFNGLGETQUERYIVARBPROC glGetQueryivARB;
-extern PFNGLGETQUERYOBJECTIVARBPROC glGetQueryObjectivARB;
-extern PFNGLGETQUERYOBJECTUIVARBPROC glGetQueryObjectuivARB;
-
-// GL_ARB_timer_query
-extern PFNGLQUERYCOUNTERPROC glQueryCounter;
-extern PFNGLGETQUERYOBJECTI64VPROC glGetQueryObjecti64v;
-extern PFNGLGETQUERYOBJECTUI64VPROC glGetQueryObjectui64v;
-
-// GL_ARB_point_parameters
-extern PFNGLPOINTPARAMETERFARBPROC glPointParameterfARB;
-extern PFNGLPOINTPARAMETERFVARBPROC glPointParameterfvARB;
-
-// GL_ARB_shader_objects
-extern PFNGLDELETEOBJECTARBPROC glDeleteObjectARB;
-extern PFNGLGETHANDLEARBPROC glGetHandleARB;
-extern PFNGLDETACHOBJECTARBPROC glDetachObjectARB;
-extern PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB;
-extern PFNGLSHADERSOURCEARBPROC glShaderSourceARB;
-extern PFNGLCOMPILESHADERARBPROC glCompileShaderARB;
-extern PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB;
-extern PFNGLATTACHOBJECTARBPROC glAttachObjectARB;
-extern PFNGLLINKPROGRAMARBPROC glLinkProgramARB;
-extern PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB;
-extern PFNGLVALIDATEPROGRAMARBPROC glValidateProgramARB;
-extern PFNGLUNIFORM1FARBPROC glUniform1fARB;
-extern PFNGLUNIFORM2FARBPROC glUniform2fARB;
-extern PFNGLUNIFORM3FARBPROC glUniform3fARB;
-extern PFNGLUNIFORM4FARBPROC glUniform4fARB;
-extern PFNGLUNIFORM1IARBPROC glUniform1iARB;
-extern PFNGLUNIFORM2IARBPROC glUniform2iARB;
-extern PFNGLUNIFORM3IARBPROC glUniform3iARB;
-extern PFNGLUNIFORM4IARBPROC glUniform4iARB;
-extern PFNGLUNIFORM1FVARBPROC glUniform1fvARB;
-extern PFNGLUNIFORM2FVARBPROC glUniform2fvARB;
-extern PFNGLUNIFORM3FVARBPROC glUniform3fvARB;
-extern PFNGLUNIFORM4FVARBPROC glUniform4fvARB;
-extern PFNGLUNIFORM1IVARBPROC glUniform1ivARB;
-extern PFNGLUNIFORM2IVARBPROC glUniform2ivARB;
-extern PFNGLUNIFORM3IVARBPROC glUniform3ivARB;
-extern PFNGLUNIFORM4IVARBPROC glUniform4ivARB;
-extern PFNGLUNIFORMMATRIX2FVARBPROC glUniformMatrix2fvARB;
-extern PFNGLUNIFORMMATRIX3FVARBPROC glUniformMatrix3fvARB;
-extern PFNGLUNIFORMMATRIX3X4FVPROC glUniformMatrix3x4fv;
-extern PFNGLUNIFORMMATRIX4FVARBPROC glUniformMatrix4fvARB;
-extern PFNGLGETOBJECTPARAMETERFVARBPROC glGetObjectParameterfvARB;
-extern PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB;
-extern PFNGLGETINFOLOGARBPROC glGetInfoLogARB;
-extern PFNGLGETATTACHEDOBJECTSARBPROC glGetAttachedObjectsARB;
-extern PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB;
-extern PFNGLGETACTIVEUNIFORMARBPROC glGetActiveUniformARB;
-extern PFNGLGETUNIFORMFVARBPROC glGetUniformfvARB;
-extern PFNGLGETUNIFORMIVARBPROC glGetUniformivARB;
-extern PFNGLGETSHADERSOURCEARBPROC glGetShaderSourceARB;
-
-// GL_ARB_vertex_shader
-extern PFNGLVERTEXATTRIB1DARBPROC glVertexAttrib1dARB;
-extern PFNGLVERTEXATTRIB1DVARBPROC glVertexAttrib1dvARB;
-extern PFNGLVERTEXATTRIB1FARBPROC glVertexAttrib1fARB;
-extern PFNGLVERTEXATTRIB1FVARBPROC glVertexAttrib1fvARB;
-extern PFNGLVERTEXATTRIB1SARBPROC glVertexAttrib1sARB;
-extern PFNGLVERTEXATTRIB1SVARBPROC glVertexAttrib1svARB;
-extern PFNGLVERTEXATTRIB2DARBPROC glVertexAttrib2dARB;
-extern PFNGLVERTEXATTRIB2DVARBPROC glVertexAttrib2dvARB;
-extern PFNGLVERTEXATTRIB2FARBPROC glVertexAttrib2fARB;
-extern PFNGLVERTEXATTRIB2FVARBPROC glVertexAttrib2fvARB;
-extern PFNGLVERTEXATTRIB2SARBPROC glVertexAttrib2sARB;
-extern PFNGLVERTEXATTRIB2SVARBPROC glVertexAttrib2svARB;
-extern PFNGLVERTEXATTRIB3DARBPROC glVertexAttrib3dARB;
-extern PFNGLVERTEXATTRIB3DVARBPROC glVertexAttrib3dvARB;
-extern PFNGLVERTEXATTRIB3FARBPROC glVertexAttrib3fARB;
-extern PFNGLVERTEXATTRIB3FVARBPROC glVertexAttrib3fvARB;
-extern PFNGLVERTEXATTRIB3SARBPROC glVertexAttrib3sARB;
-extern PFNGLVERTEXATTRIB3SVARBPROC glVertexAttrib3svARB;
-extern PFNGLVERTEXATTRIB4NBVARBPROC glVertexAttrib4nbvARB;
-extern PFNGLVERTEXATTRIB4NIVARBPROC glVertexAttrib4nivARB;
-extern PFNGLVERTEXATTRIB4NSVARBPROC glVertexAttrib4nsvARB;
-extern PFNGLVERTEXATTRIB4NUBARBPROC glVertexAttrib4nubARB;
-extern PFNGLVERTEXATTRIB4NUBVARBPROC glVertexAttrib4nubvARB;
-extern PFNGLVERTEXATTRIB4NUIVARBPROC glVertexAttrib4nuivARB;
-extern PFNGLVERTEXATTRIB4NUSVARBPROC glVertexAttrib4nusvARB;
-extern PFNGLVERTEXATTRIB4BVARBPROC glVertexAttrib4bvARB;
-extern PFNGLVERTEXATTRIB4DARBPROC glVertexAttrib4dARB;
-extern PFNGLVERTEXATTRIB4DVARBPROC glVertexAttrib4dvARB;
-extern PFNGLVERTEXATTRIB4FARBPROC glVertexAttrib4fARB;
-extern PFNGLVERTEXATTRIB4FVARBPROC glVertexAttrib4fvARB;
-extern PFNGLVERTEXATTRIB4IVARBPROC glVertexAttrib4ivARB;
-extern PFNGLVERTEXATTRIB4SARBPROC glVertexAttrib4sARB;
-extern PFNGLVERTEXATTRIB4SVARBPROC glVertexAttrib4svARB;
-extern PFNGLVERTEXATTRIB4UBVARBPROC glVertexAttrib4ubvARB;
-extern PFNGLVERTEXATTRIB4UIVARBPROC glVertexAttrib4uivARB;
-extern PFNGLVERTEXATTRIB4USVARBPROC glVertexAttrib4usvARB;
-extern PFNGLVERTEXATTRIBPOINTERARBPROC glVertexAttribPointerARB;
-extern PFNGLVERTEXATTRIBIPOINTERPROC glVertexAttribIPointer;
-extern PFNGLENABLEVERTEXATTRIBARRAYARBPROC glEnableVertexAttribArrayARB;
-extern PFNGLDISABLEVERTEXATTRIBARRAYARBPROC glDisableVertexAttribArrayARB;
-extern PFNGLPROGRAMSTRINGARBPROC glProgramStringARB;
-extern PFNGLBINDPROGRAMARBPROC glBindProgramARB;
-extern PFNGLDELETEPROGRAMSARBPROC glDeleteProgramsARB;
-extern PFNGLGENPROGRAMSARBPROC glGenProgramsARB;
-extern PFNGLPROGRAMENVPARAMETER4DARBPROC glProgramEnvParameter4dARB;
-extern PFNGLPROGRAMENVPARAMETER4DVARBPROC glProgramEnvParameter4dvARB;
-extern PFNGLPROGRAMENVPARAMETER4FARBPROC glProgramEnvParameter4fARB;
-extern PFNGLPROGRAMENVPARAMETER4FVARBPROC glProgramEnvParameter4fvARB;
-extern PFNGLPROGRAMLOCALPARAMETER4DARBPROC glProgramLocalParameter4dARB;
-extern PFNGLPROGRAMLOCALPARAMETER4DVARBPROC glProgramLocalParameter4dvARB;
-extern PFNGLPROGRAMLOCALPARAMETER4FARBPROC glProgramLocalParameter4fARB;
-extern PFNGLPROGRAMLOCALPARAMETER4FVARBPROC glProgramLocalParameter4fvARB;
-extern PFNGLGETPROGRAMENVPARAMETERDVARBPROC glGetProgramEnvParameterdvARB;
-extern PFNGLGETPROGRAMENVPARAMETERFVARBPROC glGetProgramEnvParameterfvARB;
-extern PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC glGetProgramLocalParameterdvARB;
-extern PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC glGetProgramLocalParameterfvARB;
-extern PFNGLGETPROGRAMIVARBPROC glGetProgramivARB;
-extern PFNGLGETPROGRAMSTRINGARBPROC glGetProgramStringARB;
-extern PFNGLGETVERTEXATTRIBDVARBPROC glGetVertexAttribdvARB;
-extern PFNGLGETVERTEXATTRIBFVARBPROC glGetVertexAttribfvARB;
-extern PFNGLGETVERTEXATTRIBIVARBPROC glGetVertexAttribivARB;
-extern PFNGLGETVERTEXATTRIBPOINTERVARBPROC glGetVertexAttribPointervARB;
-extern PFNGLISPROGRAMARBPROC glIsProgramARB;
-extern PFNGLBINDATTRIBLOCATIONARBPROC glBindAttribLocationARB;
-extern PFNGLGETACTIVEATTRIBARBPROC glGetActiveAttribARB;
-extern PFNGLGETATTRIBLOCATIONARBPROC glGetAttribLocationARB;
-
-extern PFNGLCOMPRESSEDTEXIMAGE2DARBPROC glCompressedTexImage2DARB;
-extern PFNGLGETCOMPRESSEDTEXIMAGEARBPROC glGetCompressedTexImageARB;
-
-//GL_EXT_blend_func_separate
-extern PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT;
-
-//GL_ARB_framebuffer_object
-extern PFNGLISRENDERBUFFERPROC glIsRenderbuffer;
-extern PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer;
-extern PFNGLDELETERENDERBUFFERSPROC glDeleteRenderbuffers;
-extern PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers;
-extern PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage;
-extern PFNGLGETRENDERBUFFERPARAMETERIVPROC glGetRenderbufferParameteriv;
-extern PFNGLISFRAMEBUFFERPROC glIsFramebuffer;
-extern PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer;
-extern PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers;
-extern PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers;
-extern PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus;
-extern PFNGLFRAMEBUFFERTEXTURE1DPROC glFramebufferTexture1D;
-extern PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D;
-extern PFNGLFRAMEBUFFERTEXTURE3DPROC glFramebufferTexture3D;
-extern PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer;
-extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glGetFramebufferAttachmentParameteriv;
-extern PFNGLGENERATEMIPMAPPROC glGenerateMipmap;
-extern PFNGLBLITFRAMEBUFFERPROC glBlitFramebuffer;
-extern PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glRenderbufferStorageMultisample;
-extern PFNGLFRAMEBUFFERTEXTURELAYERPROC glFramebufferTextureLayer;
-
-//GL_ARB_draw_buffers
-extern PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB;
-
-//GL_ARB_texture_multisample
-extern PFNGLTEXIMAGE2DMULTISAMPLEPROC glTexImage2DMultisample;
-extern PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample;
-extern PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv;
-extern PFNGLSAMPLEMASKIPROC glSampleMaski;
-
-//transform feedback (4.0 core)
-extern PFNGLBEGINTRANSFORMFEEDBACKPROC glBeginTransformFeedback;
-extern PFNGLENDTRANSFORMFEEDBACKPROC glEndTransformFeedback;
-extern PFNGLTRANSFORMFEEDBACKVARYINGSPROC glTransformFeedbackVaryings;
-extern PFNGLBINDBUFFERRANGEPROC glBindBufferRange;
-extern PFNGLBINDBUFFERBASEPROC glBindBufferBase;
-
-
#elif LL_WINDOWS
//----------------------------------------------------------------------------
// LL_WINDOWS
@@ -328,251 +56,774 @@ extern PFNGLBINDBUFFERBASEPROC glBindBufferBase;
#include "GL/glext.h"
#include "GL/glh_extensions.h"
+// WGL_AMD_gpu_association
+extern PFNWGLGETGPUIDSAMDPROC wglGetGPUIDsAMD;
+extern PFNWGLGETGPUINFOAMDPROC wglGetGPUInfoAMD;
+extern PFNWGLGETCONTEXTGPUIDAMDPROC wglGetContextGPUIDAMD;
+extern PFNWGLCREATEASSOCIATEDCONTEXTAMDPROC wglCreateAssociatedContextAMD;
+extern PFNWGLCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC wglCreateAssociatedContextAttribsAMD;
+extern PFNWGLDELETEASSOCIATEDCONTEXTAMDPROC wglDeleteAssociatedContextAMD;
+extern PFNWGLMAKEASSOCIATEDCONTEXTCURRENTAMDPROC wglMakeAssociatedContextCurrentAMD;
+extern PFNWGLGETCURRENTASSOCIATEDCONTEXTAMDPROC wglGetCurrentAssociatedContextAMD;
+extern PFNWGLBLITCONTEXTFRAMEBUFFERAMDPROC wglBlitContextFramebufferAMD;
+
+// WGL_EXT_swap_control
+extern PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT;
+extern PFNWGLGETSWAPINTERVALEXTPROC wglGetSwapIntervalEXT;
+
// WGL_ARB_create_context
extern PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB;
-extern PFNGLGETSTRINGIPROC glGetStringi;
-
-// GL_ARB_vertex_buffer_object
-extern PFNGLBINDBUFFERARBPROC glBindBufferARB;
-extern PFNGLDELETEBUFFERSARBPROC glDeleteBuffersARB;
-extern PFNGLGENBUFFERSARBPROC glGenBuffersARB;
-extern PFNGLISBUFFERARBPROC glIsBufferARB;
-extern PFNGLBUFFERDATAARBPROC glBufferDataARB;
-extern PFNGLBUFFERSUBDATAARBPROC glBufferSubDataARB;
-extern PFNGLGETBUFFERSUBDATAARBPROC glGetBufferSubDataARB;
-extern PFNGLMAPBUFFERARBPROC glMapBufferARB;
-extern PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB;
-extern PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB;
-extern PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB;
-
-// GL_ARB_vertex_array_object
-extern PFNGLBINDVERTEXARRAYPROC glBindVertexArray;
-extern PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays;
-extern PFNGLGENVERTEXARRAYSPROC glGenVertexArrays;
-extern PFNGLISVERTEXARRAYPROC glIsVertexArray;
-
-// GL_ARB_sync
-extern PFNGLFENCESYNCPROC glFenceSync;
-extern PFNGLISSYNCPROC glIsSync;
-extern PFNGLDELETESYNCPROC glDeleteSync;
-extern PFNGLCLIENTWAITSYNCPROC glClientWaitSync;
-extern PFNGLWAITSYNCPROC glWaitSync;
-extern PFNGLGETINTEGER64VPROC glGetInteger64v;
-extern PFNGLGETSYNCIVPROC glGetSynciv;
-
-// GL_APPLE_flush_buffer_range
-extern PFNGLBUFFERPARAMETERIAPPLEPROC glBufferParameteriAPPLE;
-extern PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC glFlushMappedBufferRangeAPPLE;
-
-// GL_ARB_map_buffer_range
-extern PFNGLMAPBUFFERRANGEPROC glMapBufferRange;
-extern PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange;
-
-// GL_ATI_vertex_array_object
-extern PFNGLNEWOBJECTBUFFERATIPROC glNewObjectBufferATI;
-extern PFNGLISOBJECTBUFFERATIPROC glIsObjectBufferATI;
-extern PFNGLUPDATEOBJECTBUFFERATIPROC glUpdateObjectBufferATI;
-extern PFNGLGETOBJECTBUFFERFVATIPROC glGetObjectBufferfvATI;
-extern PFNGLGETOBJECTBUFFERIVATIPROC glGetObjectBufferivATI;
-extern PFNGLFREEOBJECTBUFFERATIPROC glFreeObjectBufferATI;
-extern PFNGLARRAYOBJECTATIPROC glArrayObjectATI;
-extern PFNGLVERTEXATTRIBARRAYOBJECTATIPROC glVertexAttribArrayObjectATI;
-extern PFNGLGETARRAYOBJECTFVATIPROC glGetArrayObjectfvATI;
-extern PFNGLGETARRAYOBJECTIVATIPROC glGetArrayObjectivATI;
-extern PFNGLVARIANTARRAYOBJECTATIPROC glVariantObjectArrayATI;
-extern PFNGLGETVARIANTARRAYOBJECTFVATIPROC glGetVariantArrayObjectfvATI;
-extern PFNGLGETVARIANTARRAYOBJECTIVATIPROC glGetVariantArrayObjectivATI;
-
-extern PFNWGLGETGPUIDSAMDPROC wglGetGPUIDsAMD;
-extern PFNWGLGETGPUINFOAMDPROC wglGetGPUInfoAMD;
-extern PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT;
-
-// GL_ARB_occlusion_query
-extern PFNGLGENQUERIESARBPROC glGenQueriesARB;
-extern PFNGLDELETEQUERIESARBPROC glDeleteQueriesARB;
-extern PFNGLISQUERYARBPROC glIsQueryARB;
-extern PFNGLBEGINQUERYARBPROC glBeginQueryARB;
-extern PFNGLENDQUERYARBPROC glEndQueryARB;
-extern PFNGLGETQUERYIVARBPROC glGetQueryivARB;
-extern PFNGLGETQUERYOBJECTIVARBPROC glGetQueryObjectivARB;
-extern PFNGLGETQUERYOBJECTUIVARBPROC glGetQueryObjectuivARB;
-
-// GL_ARB_timer_query
-extern PFNGLQUERYCOUNTERPROC glQueryCounter;
-extern PFNGLGETQUERYOBJECTI64VPROC glGetQueryObjecti64v;
-extern PFNGLGETQUERYOBJECTUI64VPROC glGetQueryObjectui64v;
-
-
-// GL_ARB_point_parameters
-extern PFNGLPOINTPARAMETERFARBPROC glPointParameterfARB;
-extern PFNGLPOINTPARAMETERFVARBPROC glPointParameterfvARB;
-
-// GL_ARB_shader_objects
-extern PFNGLDELETEOBJECTARBPROC glDeleteObjectARB;
-extern PFNGLGETHANDLEARBPROC glGetHandleARB;
-extern PFNGLDETACHOBJECTARBPROC glDetachObjectARB;
-extern PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB;
-extern PFNGLSHADERSOURCEARBPROC glShaderSourceARB;
-extern PFNGLCOMPILESHADERARBPROC glCompileShaderARB;
-extern PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB;
-extern PFNGLATTACHOBJECTARBPROC glAttachObjectARB;
-extern PFNGLLINKPROGRAMARBPROC glLinkProgramARB;
-extern PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB;
-extern PFNGLVALIDATEPROGRAMARBPROC glValidateProgramARB;
-extern PFNGLUNIFORM1FARBPROC glUniform1fARB;
-extern PFNGLUNIFORM2FARBPROC glUniform2fARB;
-extern PFNGLUNIFORM3FARBPROC glUniform3fARB;
-extern PFNGLUNIFORM4FARBPROC glUniform4fARB;
-extern PFNGLUNIFORM1IARBPROC glUniform1iARB;
-extern PFNGLUNIFORM2IARBPROC glUniform2iARB;
-extern PFNGLUNIFORM3IARBPROC glUniform3iARB;
-extern PFNGLUNIFORM4IARBPROC glUniform4iARB;
-extern PFNGLUNIFORM1FVARBPROC glUniform1fvARB;
-extern PFNGLUNIFORM2FVARBPROC glUniform2fvARB;
-extern PFNGLUNIFORM3FVARBPROC glUniform3fvARB;
-extern PFNGLUNIFORM4FVARBPROC glUniform4fvARB;
-extern PFNGLUNIFORM1IVARBPROC glUniform1ivARB;
-extern PFNGLUNIFORM2IVARBPROC glUniform2ivARB;
-extern PFNGLUNIFORM3IVARBPROC glUniform3ivARB;
-extern PFNGLUNIFORM4IVARBPROC glUniform4ivARB;
-extern PFNGLUNIFORMMATRIX2FVARBPROC glUniformMatrix2fvARB;
-extern PFNGLUNIFORMMATRIX3FVARBPROC glUniformMatrix3fvARB;
+
+// GL_VERSION_1_3
+extern PFNGLACTIVETEXTUREPROC glActiveTexture;
+extern PFNGLSAMPLECOVERAGEPROC glSampleCoverage;
+extern PFNGLCOMPRESSEDTEXIMAGE3DPROC glCompressedTexImage3D;
+extern PFNGLCOMPRESSEDTEXIMAGE2DPROC glCompressedTexImage2D;
+extern PFNGLCOMPRESSEDTEXIMAGE1DPROC glCompressedTexImage1D;
+extern PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC glCompressedTexSubImage3D;
+extern PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glCompressedTexSubImage2D;
+extern PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC glCompressedTexSubImage1D;
+extern PFNGLGETCOMPRESSEDTEXIMAGEPROC glGetCompressedTexImage;
+extern PFNGLCLIENTACTIVETEXTUREPROC glClientActiveTexture;
+extern PFNGLMULTITEXCOORD1DPROC glMultiTexCoord1d;
+extern PFNGLMULTITEXCOORD1DVPROC glMultiTexCoord1dv;
+extern PFNGLMULTITEXCOORD1FPROC glMultiTexCoord1f;
+extern PFNGLMULTITEXCOORD1FVPROC glMultiTexCoord1fv;
+extern PFNGLMULTITEXCOORD1IPROC glMultiTexCoord1i;
+extern PFNGLMULTITEXCOORD1IVPROC glMultiTexCoord1iv;
+extern PFNGLMULTITEXCOORD1SPROC glMultiTexCoord1s;
+extern PFNGLMULTITEXCOORD1SVPROC glMultiTexCoord1sv;
+extern PFNGLMULTITEXCOORD2DPROC glMultiTexCoord2d;
+extern PFNGLMULTITEXCOORD2DVPROC glMultiTexCoord2dv;
+extern PFNGLMULTITEXCOORD2FPROC glMultiTexCoord2f;
+extern PFNGLMULTITEXCOORD2FVPROC glMultiTexCoord2fv;
+extern PFNGLMULTITEXCOORD2IPROC glMultiTexCoord2i;
+extern PFNGLMULTITEXCOORD2IVPROC glMultiTexCoord2iv;
+extern PFNGLMULTITEXCOORD2SPROC glMultiTexCoord2s;
+extern PFNGLMULTITEXCOORD2SVPROC glMultiTexCoord2sv;
+extern PFNGLMULTITEXCOORD3DPROC glMultiTexCoord3d;
+extern PFNGLMULTITEXCOORD3DVPROC glMultiTexCoord3dv;
+extern PFNGLMULTITEXCOORD3FPROC glMultiTexCoord3f;
+extern PFNGLMULTITEXCOORD3FVPROC glMultiTexCoord3fv;
+extern PFNGLMULTITEXCOORD3IPROC glMultiTexCoord3i;
+extern PFNGLMULTITEXCOORD3IVPROC glMultiTexCoord3iv;
+extern PFNGLMULTITEXCOORD3SPROC glMultiTexCoord3s;
+extern PFNGLMULTITEXCOORD3SVPROC glMultiTexCoord3sv;
+extern PFNGLMULTITEXCOORD4DPROC glMultiTexCoord4d;
+extern PFNGLMULTITEXCOORD4DVPROC glMultiTexCoord4dv;
+extern PFNGLMULTITEXCOORD4FPROC glMultiTexCoord4f;
+extern PFNGLMULTITEXCOORD4FVPROC glMultiTexCoord4fv;
+extern PFNGLMULTITEXCOORD4IPROC glMultiTexCoord4i;
+extern PFNGLMULTITEXCOORD4IVPROC glMultiTexCoord4iv;
+extern PFNGLMULTITEXCOORD4SPROC glMultiTexCoord4s;
+extern PFNGLMULTITEXCOORD4SVPROC glMultiTexCoord4sv;
+extern PFNGLLOADTRANSPOSEMATRIXFPROC glLoadTransposeMatrixf;
+extern PFNGLLOADTRANSPOSEMATRIXDPROC glLoadTransposeMatrixd;
+extern PFNGLMULTTRANSPOSEMATRIXFPROC glMultTransposeMatrixf;
+extern PFNGLMULTTRANSPOSEMATRIXDPROC glMultTransposeMatrixd;
+
+// GL_VERSION_1_4
+extern PFNGLBLENDFUNCSEPARATEPROC glBlendFuncSeparate;
+extern PFNGLMULTIDRAWARRAYSPROC glMultiDrawArrays;
+extern PFNGLMULTIDRAWELEMENTSPROC glMultiDrawElements;
+extern PFNGLPOINTPARAMETERFPROC glPointParameterf;
+extern PFNGLPOINTPARAMETERFVPROC glPointParameterfv;
+extern PFNGLPOINTPARAMETERIPROC glPointParameteri;
+extern PFNGLPOINTPARAMETERIVPROC glPointParameteriv;
+extern PFNGLFOGCOORDFPROC glFogCoordf;
+extern PFNGLFOGCOORDFVPROC glFogCoordfv;
+extern PFNGLFOGCOORDDPROC glFogCoordd;
+extern PFNGLFOGCOORDDVPROC glFogCoorddv;
+extern PFNGLFOGCOORDPOINTERPROC glFogCoordPointer;
+extern PFNGLSECONDARYCOLOR3BPROC glSecondaryColor3b;
+extern PFNGLSECONDARYCOLOR3BVPROC glSecondaryColor3bv;
+extern PFNGLSECONDARYCOLOR3DPROC glSecondaryColor3d;
+extern PFNGLSECONDARYCOLOR3DVPROC glSecondaryColor3dv;
+extern PFNGLSECONDARYCOLOR3FPROC glSecondaryColor3f;
+extern PFNGLSECONDARYCOLOR3FVPROC glSecondaryColor3fv;
+extern PFNGLSECONDARYCOLOR3IPROC glSecondaryColor3i;
+extern PFNGLSECONDARYCOLOR3IVPROC glSecondaryColor3iv;
+extern PFNGLSECONDARYCOLOR3SPROC glSecondaryColor3s;
+extern PFNGLSECONDARYCOLOR3SVPROC glSecondaryColor3sv;
+extern PFNGLSECONDARYCOLOR3UBPROC glSecondaryColor3ub;
+extern PFNGLSECONDARYCOLOR3UBVPROC glSecondaryColor3ubv;
+extern PFNGLSECONDARYCOLOR3UIPROC glSecondaryColor3ui;
+extern PFNGLSECONDARYCOLOR3UIVPROC glSecondaryColor3uiv;
+extern PFNGLSECONDARYCOLOR3USPROC glSecondaryColor3us;
+extern PFNGLSECONDARYCOLOR3USVPROC glSecondaryColor3usv;
+extern PFNGLSECONDARYCOLORPOINTERPROC glSecondaryColorPointer;
+extern PFNGLWINDOWPOS2DPROC glWindowPos2d;
+extern PFNGLWINDOWPOS2DVPROC glWindowPos2dv;
+extern PFNGLWINDOWPOS2FPROC glWindowPos2f;
+extern PFNGLWINDOWPOS2FVPROC glWindowPos2fv;
+extern PFNGLWINDOWPOS2IPROC glWindowPos2i;
+extern PFNGLWINDOWPOS2IVPROC glWindowPos2iv;
+extern PFNGLWINDOWPOS2SPROC glWindowPos2s;
+extern PFNGLWINDOWPOS2SVPROC glWindowPos2sv;
+extern PFNGLWINDOWPOS3DPROC glWindowPos3d;
+extern PFNGLWINDOWPOS3DVPROC glWindowPos3dv;
+extern PFNGLWINDOWPOS3FPROC glWindowPos3f;
+extern PFNGLWINDOWPOS3FVPROC glWindowPos3fv;
+extern PFNGLWINDOWPOS3IPROC glWindowPos3i;
+extern PFNGLWINDOWPOS3IVPROC glWindowPos3iv;
+extern PFNGLWINDOWPOS3SPROC glWindowPos3s;
+extern PFNGLWINDOWPOS3SVPROC glWindowPos3sv;
+
+// GL_VERSION_1_5
+extern PFNGLGENQUERIESPROC glGenQueries;
+extern PFNGLDELETEQUERIESPROC glDeleteQueries;
+extern PFNGLISQUERYPROC glIsQuery;
+extern PFNGLBEGINQUERYPROC glBeginQuery;
+extern PFNGLENDQUERYPROC glEndQuery;
+extern PFNGLGETQUERYIVPROC glGetQueryiv;
+extern PFNGLGETQUERYOBJECTIVPROC glGetQueryObjectiv;
+extern PFNGLGETQUERYOBJECTUIVPROC glGetQueryObjectuiv;
+extern PFNGLBINDBUFFERPROC glBindBuffer;
+extern PFNGLDELETEBUFFERSPROC glDeleteBuffers;
+extern PFNGLGENBUFFERSPROC glGenBuffers;
+extern PFNGLISBUFFERPROC glIsBuffer;
+extern PFNGLBUFFERDATAPROC glBufferData;
+extern PFNGLBUFFERSUBDATAPROC glBufferSubData;
+extern PFNGLGETBUFFERSUBDATAPROC glGetBufferSubData;
+extern PFNGLMAPBUFFERPROC glMapBuffer;
+extern PFNGLUNMAPBUFFERPROC glUnmapBuffer;
+extern PFNGLGETBUFFERPARAMETERIVPROC glGetBufferParameteriv;
+extern PFNGLGETBUFFERPOINTERVPROC glGetBufferPointerv;
+
+// GL_VERSION_2_0
+extern PFNGLBLENDEQUATIONSEPARATEPROC glBlendEquationSeparate;
+extern PFNGLDRAWBUFFERSPROC glDrawBuffers;
+extern PFNGLSTENCILOPSEPARATEPROC glStencilOpSeparate;
+extern PFNGLSTENCILFUNCSEPARATEPROC glStencilFuncSeparate;
+extern PFNGLSTENCILMASKSEPARATEPROC glStencilMaskSeparate;
+extern PFNGLATTACHSHADERPROC glAttachShader;
+extern PFNGLBINDATTRIBLOCATIONPROC glBindAttribLocation;
+extern PFNGLCOMPILESHADERPROC glCompileShader;
+extern PFNGLCREATEPROGRAMPROC glCreateProgram;
+extern PFNGLCREATESHADERPROC glCreateShader;
+extern PFNGLDELETEPROGRAMPROC glDeleteProgram;
+extern PFNGLDELETESHADERPROC glDeleteShader;
+extern PFNGLDETACHSHADERPROC glDetachShader;
+extern PFNGLDISABLEVERTEXATTRIBARRAYPROC glDisableVertexAttribArray;
+extern PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray;
+extern PFNGLGETACTIVEATTRIBPROC glGetActiveAttrib;
+extern PFNGLGETACTIVEUNIFORMPROC glGetActiveUniform;
+extern PFNGLGETATTACHEDSHADERSPROC glGetAttachedShaders;
+extern PFNGLGETATTRIBLOCATIONPROC glGetAttribLocation;
+extern PFNGLGETPROGRAMIVPROC glGetProgramiv;
+extern PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog;
+extern PFNGLGETSHADERIVPROC glGetShaderiv;
+extern PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog;
+extern PFNGLGETSHADERSOURCEPROC glGetShaderSource;
+extern PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation;
+extern PFNGLGETUNIFORMFVPROC glGetUniformfv;
+extern PFNGLGETUNIFORMIVPROC glGetUniformiv;
+extern PFNGLGETVERTEXATTRIBDVPROC glGetVertexAttribdv;
+extern PFNGLGETVERTEXATTRIBFVPROC glGetVertexAttribfv;
+extern PFNGLGETVERTEXATTRIBIVPROC glGetVertexAttribiv;
+extern PFNGLGETVERTEXATTRIBPOINTERVPROC glGetVertexAttribPointerv;
+extern PFNGLISPROGRAMPROC glIsProgram;
+extern PFNGLISSHADERPROC glIsShader;
+extern PFNGLLINKPROGRAMPROC glLinkProgram;
+extern PFNGLSHADERSOURCEPROC glShaderSource;
+extern PFNGLUSEPROGRAMPROC glUseProgram;
+extern PFNGLUNIFORM1FPROC glUniform1f;
+extern PFNGLUNIFORM2FPROC glUniform2f;
+extern PFNGLUNIFORM3FPROC glUniform3f;
+extern PFNGLUNIFORM4FPROC glUniform4f;
+extern PFNGLUNIFORM1IPROC glUniform1i;
+extern PFNGLUNIFORM2IPROC glUniform2i;
+extern PFNGLUNIFORM3IPROC glUniform3i;
+extern PFNGLUNIFORM4IPROC glUniform4i;
+extern PFNGLUNIFORM1FVPROC glUniform1fv;
+extern PFNGLUNIFORM2FVPROC glUniform2fv;
+extern PFNGLUNIFORM3FVPROC glUniform3fv;
+extern PFNGLUNIFORM4FVPROC glUniform4fv;
+extern PFNGLUNIFORM1IVPROC glUniform1iv;
+extern PFNGLUNIFORM2IVPROC glUniform2iv;
+extern PFNGLUNIFORM3IVPROC glUniform3iv;
+extern PFNGLUNIFORM4IVPROC glUniform4iv;
+extern PFNGLUNIFORMMATRIX2FVPROC glUniformMatrix2fv;
+extern PFNGLUNIFORMMATRIX3FVPROC glUniformMatrix3fv;
+extern PFNGLUNIFORMMATRIX4FVPROC glUniformMatrix4fv;
+extern PFNGLVALIDATEPROGRAMPROC glValidateProgram;
+extern PFNGLVERTEXATTRIB1DPROC glVertexAttrib1d;
+extern PFNGLVERTEXATTRIB1DVPROC glVertexAttrib1dv;
+extern PFNGLVERTEXATTRIB1FPROC glVertexAttrib1f;
+extern PFNGLVERTEXATTRIB1FVPROC glVertexAttrib1fv;
+extern PFNGLVERTEXATTRIB1SPROC glVertexAttrib1s;
+extern PFNGLVERTEXATTRIB1SVPROC glVertexAttrib1sv;
+extern PFNGLVERTEXATTRIB2DPROC glVertexAttrib2d;
+extern PFNGLVERTEXATTRIB2DVPROC glVertexAttrib2dv;
+extern PFNGLVERTEXATTRIB2FPROC glVertexAttrib2f;
+extern PFNGLVERTEXATTRIB2FVPROC glVertexAttrib2fv;
+extern PFNGLVERTEXATTRIB2SPROC glVertexAttrib2s;
+extern PFNGLVERTEXATTRIB2SVPROC glVertexAttrib2sv;
+extern PFNGLVERTEXATTRIB3DPROC glVertexAttrib3d;
+extern PFNGLVERTEXATTRIB3DVPROC glVertexAttrib3dv;
+extern PFNGLVERTEXATTRIB3FPROC glVertexAttrib3f;
+extern PFNGLVERTEXATTRIB3FVPROC glVertexAttrib3fv;
+extern PFNGLVERTEXATTRIB3SPROC glVertexAttrib3s;
+extern PFNGLVERTEXATTRIB3SVPROC glVertexAttrib3sv;
+extern PFNGLVERTEXATTRIB4NBVPROC glVertexAttrib4Nbv;
+extern PFNGLVERTEXATTRIB4NIVPROC glVertexAttrib4Niv;
+extern PFNGLVERTEXATTRIB4NSVPROC glVertexAttrib4Nsv;
+extern PFNGLVERTEXATTRIB4NUBPROC glVertexAttrib4Nub;
+extern PFNGLVERTEXATTRIB4NUBVPROC glVertexAttrib4Nubv;
+extern PFNGLVERTEXATTRIB4NUIVPROC glVertexAttrib4Nuiv;
+extern PFNGLVERTEXATTRIB4NUSVPROC glVertexAttrib4Nusv;
+extern PFNGLVERTEXATTRIB4BVPROC glVertexAttrib4bv;
+extern PFNGLVERTEXATTRIB4DPROC glVertexAttrib4d;
+extern PFNGLVERTEXATTRIB4DVPROC glVertexAttrib4dv;
+extern PFNGLVERTEXATTRIB4FPROC glVertexAttrib4f;
+extern PFNGLVERTEXATTRIB4FVPROC glVertexAttrib4fv;
+extern PFNGLVERTEXATTRIB4IVPROC glVertexAttrib4iv;
+extern PFNGLVERTEXATTRIB4SPROC glVertexAttrib4s;
+extern PFNGLVERTEXATTRIB4SVPROC glVertexAttrib4sv;
+extern PFNGLVERTEXATTRIB4UBVPROC glVertexAttrib4ubv;
+extern PFNGLVERTEXATTRIB4UIVPROC glVertexAttrib4uiv;
+extern PFNGLVERTEXATTRIB4USVPROC glVertexAttrib4usv;
+extern PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer;
+
+// GL_VERSION_2_1
+extern PFNGLUNIFORMMATRIX2X3FVPROC glUniformMatrix2x3fv;
+extern PFNGLUNIFORMMATRIX3X2FVPROC glUniformMatrix3x2fv;
+extern PFNGLUNIFORMMATRIX2X4FVPROC glUniformMatrix2x4fv;
+extern PFNGLUNIFORMMATRIX4X2FVPROC glUniformMatrix4x2fv;
extern PFNGLUNIFORMMATRIX3X4FVPROC glUniformMatrix3x4fv;
-extern PFNGLUNIFORMMATRIX4FVARBPROC glUniformMatrix4fvARB;
-extern PFNGLGETOBJECTPARAMETERFVARBPROC glGetObjectParameterfvARB;
-extern PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB;
-extern PFNGLGETINFOLOGARBPROC glGetInfoLogARB;
-extern PFNGLGETATTACHEDOBJECTSARBPROC glGetAttachedObjectsARB;
-extern PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB;
-extern PFNGLGETACTIVEUNIFORMARBPROC glGetActiveUniformARB;
-extern PFNGLGETUNIFORMFVARBPROC glGetUniformfvARB;
-extern PFNGLGETUNIFORMIVARBPROC glGetUniformivARB;
-extern PFNGLGETSHADERSOURCEARBPROC glGetShaderSourceARB;
-
-// GL_ARB_vertex_shader
-extern PFNGLVERTEXATTRIB1DARBPROC glVertexAttrib1dARB;
-extern PFNGLVERTEXATTRIB1DVARBPROC glVertexAttrib1dvARB;
-extern PFNGLVERTEXATTRIB1FARBPROC glVertexAttrib1fARB;
-extern PFNGLVERTEXATTRIB1FVARBPROC glVertexAttrib1fvARB;
-extern PFNGLVERTEXATTRIB1SARBPROC glVertexAttrib1sARB;
-extern PFNGLVERTEXATTRIB1SVARBPROC glVertexAttrib1svARB;
-extern PFNGLVERTEXATTRIB2DARBPROC glVertexAttrib2dARB;
-extern PFNGLVERTEXATTRIB2DVARBPROC glVertexAttrib2dvARB;
-extern PFNGLVERTEXATTRIB2FARBPROC glVertexAttrib2fARB;
-extern PFNGLVERTEXATTRIB2FVARBPROC glVertexAttrib2fvARB;
-extern PFNGLVERTEXATTRIB2SARBPROC glVertexAttrib2sARB;
-extern PFNGLVERTEXATTRIB2SVARBPROC glVertexAttrib2svARB;
-extern PFNGLVERTEXATTRIB3DARBPROC glVertexAttrib3dARB;
-extern PFNGLVERTEXATTRIB3DVARBPROC glVertexAttrib3dvARB;
-extern PFNGLVERTEXATTRIB3FARBPROC glVertexAttrib3fARB;
-extern PFNGLVERTEXATTRIB3FVARBPROC glVertexAttrib3fvARB;
-extern PFNGLVERTEXATTRIB3SARBPROC glVertexAttrib3sARB;
-extern PFNGLVERTEXATTRIB3SVARBPROC glVertexAttrib3svARB;
-extern PFNGLVERTEXATTRIB4NBVARBPROC glVertexAttrib4nbvARB;
-extern PFNGLVERTEXATTRIB4NIVARBPROC glVertexAttrib4nivARB;
-extern PFNGLVERTEXATTRIB4NSVARBPROC glVertexAttrib4nsvARB;
-extern PFNGLVERTEXATTRIB4NUBARBPROC glVertexAttrib4nubARB;
-extern PFNGLVERTEXATTRIB4NUBVARBPROC glVertexAttrib4nubvARB;
-extern PFNGLVERTEXATTRIB4NUIVARBPROC glVertexAttrib4nuivARB;
-extern PFNGLVERTEXATTRIB4NUSVARBPROC glVertexAttrib4nusvARB;
-extern PFNGLVERTEXATTRIB4BVARBPROC glVertexAttrib4bvARB;
-extern PFNGLVERTEXATTRIB4DARBPROC glVertexAttrib4dARB;
-extern PFNGLVERTEXATTRIB4DVARBPROC glVertexAttrib4dvARB;
-extern PFNGLVERTEXATTRIB4FARBPROC glVertexAttrib4fARB;
-extern PFNGLVERTEXATTRIB4FVARBPROC glVertexAttrib4fvARB;
-extern PFNGLVERTEXATTRIB4IVARBPROC glVertexAttrib4ivARB;
-extern PFNGLVERTEXATTRIB4SARBPROC glVertexAttrib4sARB;
-extern PFNGLVERTEXATTRIB4SVARBPROC glVertexAttrib4svARB;
-extern PFNGLVERTEXATTRIB4UBVARBPROC glVertexAttrib4ubvARB;
-extern PFNGLVERTEXATTRIB4UIVARBPROC glVertexAttrib4uivARB;
-extern PFNGLVERTEXATTRIB4USVARBPROC glVertexAttrib4usvARB;
-extern PFNGLVERTEXATTRIBPOINTERARBPROC glVertexAttribPointerARB;
-extern PFNGLVERTEXATTRIBIPOINTERPROC glVertexAttribIPointer;
-extern PFNGLENABLEVERTEXATTRIBARRAYARBPROC glEnableVertexAttribArrayARB;
-extern PFNGLDISABLEVERTEXATTRIBARRAYARBPROC glDisableVertexAttribArrayARB;
-extern PFNGLPROGRAMSTRINGARBPROC glProgramStringARB;
-extern PFNGLBINDPROGRAMARBPROC glBindProgramARB;
-extern PFNGLDELETEPROGRAMSARBPROC glDeleteProgramsARB;
-extern PFNGLGENPROGRAMSARBPROC glGenProgramsARB;
-extern PFNGLPROGRAMENVPARAMETER4DARBPROC glProgramEnvParameter4dARB;
-extern PFNGLPROGRAMENVPARAMETER4DVARBPROC glProgramEnvParameter4dvARB;
-extern PFNGLPROGRAMENVPARAMETER4FARBPROC glProgramEnvParameter4fARB;
-extern PFNGLPROGRAMENVPARAMETER4FVARBPROC glProgramEnvParameter4fvARB;
-extern PFNGLPROGRAMLOCALPARAMETER4DARBPROC glProgramLocalParameter4dARB;
-extern PFNGLPROGRAMLOCALPARAMETER4DVARBPROC glProgramLocalParameter4dvARB;
-extern PFNGLPROGRAMLOCALPARAMETER4FARBPROC glProgramLocalParameter4fARB;
-extern PFNGLPROGRAMLOCALPARAMETER4FVARBPROC glProgramLocalParameter4fvARB;
-extern PFNGLGETPROGRAMENVPARAMETERDVARBPROC glGetProgramEnvParameterdvARB;
-extern PFNGLGETPROGRAMENVPARAMETERFVARBPROC glGetProgramEnvParameterfvARB;
-extern PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC glGetProgramLocalParameterdvARB;
-extern PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC glGetProgramLocalParameterfvARB;
-extern PFNGLGETPROGRAMIVARBPROC glGetProgramivARB;
-extern PFNGLGETPROGRAMSTRINGARBPROC glGetProgramStringARB;
-extern PFNGLGETVERTEXATTRIBDVARBPROC glGetVertexAttribdvARB;
-extern PFNGLGETVERTEXATTRIBFVARBPROC glGetVertexAttribfvARB;
-extern PFNGLGETVERTEXATTRIBIVARBPROC glGetVertexAttribivARB;
-extern PFNGLGETVERTEXATTRIBPOINTERVARBPROC glGetVertexAttribPointervARB;
-extern PFNGLISPROGRAMARBPROC glIsProgramARB;
-extern PFNGLBINDATTRIBLOCATIONARBPROC glBindAttribLocationARB;
-extern PFNGLGETACTIVEATTRIBARBPROC glGetActiveAttribARB;
-extern PFNGLGETATTRIBLOCATIONARBPROC glGetAttribLocationARB;
+extern PFNGLUNIFORMMATRIX4X3FVPROC glUniformMatrix4x3fv;
+
+// GL_VERSION_3_0
+extern PFNGLCOLORMASKIPROC glColorMaski;
+extern PFNGLGETBOOLEANI_VPROC glGetBooleani_v;
+extern PFNGLGETINTEGERI_VPROC glGetIntegeri_v;
+extern PFNGLENABLEIPROC glEnablei;
+extern PFNGLDISABLEIPROC glDisablei;
+extern PFNGLISENABLEDIPROC glIsEnabledi;
+extern PFNGLBEGINTRANSFORMFEEDBACKPROC glBeginTransformFeedback;
+extern PFNGLENDTRANSFORMFEEDBACKPROC glEndTransformFeedback;
+extern PFNGLBINDBUFFERRANGEPROC glBindBufferRange;
+extern PFNGLBINDBUFFERBASEPROC glBindBufferBase;
+extern PFNGLTRANSFORMFEEDBACKVARYINGSPROC glTransformFeedbackVaryings;
+extern PFNGLGETTRANSFORMFEEDBACKVARYINGPROC glGetTransformFeedbackVarying;
+extern PFNGLCLAMPCOLORPROC glClampColor;
+extern PFNGLBEGINCONDITIONALRENDERPROC glBeginConditionalRender;
+extern PFNGLENDCONDITIONALRENDERPROC glEndConditionalRender;
+extern PFNGLVERTEXATTRIBIPOINTERPROC glVertexAttribIPointer;
+extern PFNGLGETVERTEXATTRIBIIVPROC glGetVertexAttribIiv;
+extern PFNGLGETVERTEXATTRIBIUIVPROC glGetVertexAttribIuiv;
+extern PFNGLVERTEXATTRIBI1IPROC glVertexAttribI1i;
+extern PFNGLVERTEXATTRIBI2IPROC glVertexAttribI2i;
+extern PFNGLVERTEXATTRIBI3IPROC glVertexAttribI3i;
+extern PFNGLVERTEXATTRIBI4IPROC glVertexAttribI4i;
+extern PFNGLVERTEXATTRIBI1UIPROC glVertexAttribI1ui;
+extern PFNGLVERTEXATTRIBI2UIPROC glVertexAttribI2ui;
+extern PFNGLVERTEXATTRIBI3UIPROC glVertexAttribI3ui;
+extern PFNGLVERTEXATTRIBI4UIPROC glVertexAttribI4ui;
+extern PFNGLVERTEXATTRIBI1IVPROC glVertexAttribI1iv;
+extern PFNGLVERTEXATTRIBI2IVPROC glVertexAttribI2iv;
+extern PFNGLVERTEXATTRIBI3IVPROC glVertexAttribI3iv;
+extern PFNGLVERTEXATTRIBI4IVPROC glVertexAttribI4iv;
+extern PFNGLVERTEXATTRIBI1UIVPROC glVertexAttribI1uiv;
+extern PFNGLVERTEXATTRIBI2UIVPROC glVertexAttribI2uiv;
+extern PFNGLVERTEXATTRIBI3UIVPROC glVertexAttribI3uiv;
+extern PFNGLVERTEXATTRIBI4UIVPROC glVertexAttribI4uiv;
+extern PFNGLVERTEXATTRIBI4BVPROC glVertexAttribI4bv;
+extern PFNGLVERTEXATTRIBI4SVPROC glVertexAttribI4sv;
+extern PFNGLVERTEXATTRIBI4UBVPROC glVertexAttribI4ubv;
+extern PFNGLVERTEXATTRIBI4USVPROC glVertexAttribI4usv;
+extern PFNGLGETUNIFORMUIVPROC glGetUniformuiv;
+extern PFNGLBINDFRAGDATALOCATIONPROC glBindFragDataLocation;
+extern PFNGLGETFRAGDATALOCATIONPROC glGetFragDataLocation;
+extern PFNGLUNIFORM1UIPROC glUniform1ui;
+extern PFNGLUNIFORM2UIPROC glUniform2ui;
+extern PFNGLUNIFORM3UIPROC glUniform3ui;
+extern PFNGLUNIFORM4UIPROC glUniform4ui;
+extern PFNGLUNIFORM1UIVPROC glUniform1uiv;
+extern PFNGLUNIFORM2UIVPROC glUniform2uiv;
+extern PFNGLUNIFORM3UIVPROC glUniform3uiv;
+extern PFNGLUNIFORM4UIVPROC glUniform4uiv;
+extern PFNGLTEXPARAMETERIIVPROC glTexParameterIiv;
+extern PFNGLTEXPARAMETERIUIVPROC glTexParameterIuiv;
+extern PFNGLGETTEXPARAMETERIIVPROC glGetTexParameterIiv;
+extern PFNGLGETTEXPARAMETERIUIVPROC glGetTexParameterIuiv;
+extern PFNGLCLEARBUFFERIVPROC glClearBufferiv;
+extern PFNGLCLEARBUFFERUIVPROC glClearBufferuiv;
+extern PFNGLCLEARBUFFERFVPROC glClearBufferfv;
+extern PFNGLCLEARBUFFERFIPROC glClearBufferfi;
+extern PFNGLGETSTRINGIPROC glGetStringi;
+extern PFNGLISRENDERBUFFERPROC glIsRenderbuffer;
+extern PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer;
+extern PFNGLDELETERENDERBUFFERSPROC glDeleteRenderbuffers;
+extern PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers;
+extern PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage;
+extern PFNGLGETRENDERBUFFERPARAMETERIVPROC glGetRenderbufferParameteriv;
+extern PFNGLISFRAMEBUFFERPROC glIsFramebuffer;
+extern PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer;
+extern PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers;
+extern PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers;
+extern PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus;
+extern PFNGLFRAMEBUFFERTEXTURE1DPROC glFramebufferTexture1D;
+extern PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D;
+extern PFNGLFRAMEBUFFERTEXTURE3DPROC glFramebufferTexture3D;
+extern PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer;
+extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glGetFramebufferAttachmentParameteriv;
+extern PFNGLGENERATEMIPMAPPROC glGenerateMipmap;
+extern PFNGLBLITFRAMEBUFFERPROC glBlitFramebuffer;
+extern PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glRenderbufferStorageMultisample;
+extern PFNGLFRAMEBUFFERTEXTURELAYERPROC glFramebufferTextureLayer;
+extern PFNGLMAPBUFFERRANGEPROC glMapBufferRange;
+extern PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange;
+extern PFNGLBINDVERTEXARRAYPROC glBindVertexArray;
+extern PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays;
+extern PFNGLGENVERTEXARRAYSPROC glGenVertexArrays;
+extern PFNGLISVERTEXARRAYPROC glIsVertexArray;
+
+// GL_VERSION_3_1
+extern PFNGLDRAWARRAYSINSTANCEDPROC glDrawArraysInstanced;
+extern PFNGLDRAWELEMENTSINSTANCEDPROC glDrawElementsInstanced;
+extern PFNGLTEXBUFFERPROC glTexBuffer;
+extern PFNGLPRIMITIVERESTARTINDEXPROC glPrimitiveRestartIndex;
+extern PFNGLCOPYBUFFERSUBDATAPROC glCopyBufferSubData;
+extern PFNGLGETUNIFORMINDICESPROC glGetUniformIndices;
+extern PFNGLGETACTIVEUNIFORMSIVPROC glGetActiveUniformsiv;
+extern PFNGLGETACTIVEUNIFORMNAMEPROC glGetActiveUniformName;
+extern PFNGLGETUNIFORMBLOCKINDEXPROC glGetUniformBlockIndex;
+extern PFNGLGETACTIVEUNIFORMBLOCKIVPROC glGetActiveUniformBlockiv;
+extern PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC glGetActiveUniformBlockName;
+extern PFNGLUNIFORMBLOCKBINDINGPROC glUniformBlockBinding;
+
+// GL_VERSION_3_2
+extern PFNGLDRAWELEMENTSBASEVERTEXPROC glDrawElementsBaseVertex;
+extern PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC glDrawRangeElementsBaseVertex;
+extern PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC glDrawElementsInstancedBaseVertex;
+extern PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC glMultiDrawElementsBaseVertex;
+extern PFNGLPROVOKINGVERTEXPROC glProvokingVertex;
+extern PFNGLFENCESYNCPROC glFenceSync;
+extern PFNGLISSYNCPROC glIsSync;
+extern PFNGLDELETESYNCPROC glDeleteSync;
+extern PFNGLCLIENTWAITSYNCPROC glClientWaitSync;
+extern PFNGLWAITSYNCPROC glWaitSync;
+extern PFNGLGETINTEGER64VPROC glGetInteger64v;
+extern PFNGLGETSYNCIVPROC glGetSynciv;
+extern PFNGLGETINTEGER64I_VPROC glGetInteger64i_v;
+extern PFNGLGETBUFFERPARAMETERI64VPROC glGetBufferParameteri64v;
+extern PFNGLFRAMEBUFFERTEXTUREPROC glFramebufferTexture;
+extern PFNGLTEXIMAGE2DMULTISAMPLEPROC glTexImage2DMultisample;
+extern PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample;
+extern PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv;
+extern PFNGLSAMPLEMASKIPROC glSampleMaski;
+
+// GL_VERSION_3_3
+extern PFNGLBINDFRAGDATALOCATIONINDEXEDPROC glBindFragDataLocationIndexed;
+extern PFNGLGETFRAGDATAINDEXPROC glGetFragDataIndex;
+extern PFNGLGENSAMPLERSPROC glGenSamplers;
+extern PFNGLDELETESAMPLERSPROC glDeleteSamplers;
+extern PFNGLISSAMPLERPROC glIsSampler;
+extern PFNGLBINDSAMPLERPROC glBindSampler;
+extern PFNGLSAMPLERPARAMETERIPROC glSamplerParameteri;
+extern PFNGLSAMPLERPARAMETERIVPROC glSamplerParameteriv;
+extern PFNGLSAMPLERPARAMETERFPROC glSamplerParameterf;
+extern PFNGLSAMPLERPARAMETERFVPROC glSamplerParameterfv;
+extern PFNGLSAMPLERPARAMETERIIVPROC glSamplerParameterIiv;
+extern PFNGLSAMPLERPARAMETERIUIVPROC glSamplerParameterIuiv;
+extern PFNGLGETSAMPLERPARAMETERIVPROC glGetSamplerParameteriv;
+extern PFNGLGETSAMPLERPARAMETERIIVPROC glGetSamplerParameterIiv;
+extern PFNGLGETSAMPLERPARAMETERFVPROC glGetSamplerParameterfv;
+extern PFNGLGETSAMPLERPARAMETERIUIVPROC glGetSamplerParameterIuiv;
+extern PFNGLQUERYCOUNTERPROC glQueryCounter;
+extern PFNGLGETQUERYOBJECTI64VPROC glGetQueryObjecti64v;
+extern PFNGLGETQUERYOBJECTUI64VPROC glGetQueryObjectui64v;
+extern PFNGLVERTEXATTRIBDIVISORPROC glVertexAttribDivisor;
+extern PFNGLVERTEXATTRIBP1UIPROC glVertexAttribP1ui;
+extern PFNGLVERTEXATTRIBP1UIVPROC glVertexAttribP1uiv;
+extern PFNGLVERTEXATTRIBP2UIPROC glVertexAttribP2ui;
+extern PFNGLVERTEXATTRIBP2UIVPROC glVertexAttribP2uiv;
+extern PFNGLVERTEXATTRIBP3UIPROC glVertexAttribP3ui;
+extern PFNGLVERTEXATTRIBP3UIVPROC glVertexAttribP3uiv;
+extern PFNGLVERTEXATTRIBP4UIPROC glVertexAttribP4ui;
+extern PFNGLVERTEXATTRIBP4UIVPROC glVertexAttribP4uiv;
+extern PFNGLVERTEXP2UIPROC glVertexP2ui;
+extern PFNGLVERTEXP2UIVPROC glVertexP2uiv;
+extern PFNGLVERTEXP3UIPROC glVertexP3ui;
+extern PFNGLVERTEXP3UIVPROC glVertexP3uiv;
+extern PFNGLVERTEXP4UIPROC glVertexP4ui;
+extern PFNGLVERTEXP4UIVPROC glVertexP4uiv;
+extern PFNGLTEXCOORDP1UIPROC glTexCoordP1ui;
+extern PFNGLTEXCOORDP1UIVPROC glTexCoordP1uiv;
+extern PFNGLTEXCOORDP2UIPROC glTexCoordP2ui;
+extern PFNGLTEXCOORDP2UIVPROC glTexCoordP2uiv;
+extern PFNGLTEXCOORDP3UIPROC glTexCoordP3ui;
+extern PFNGLTEXCOORDP3UIVPROC glTexCoordP3uiv;
+extern PFNGLTEXCOORDP4UIPROC glTexCoordP4ui;
+extern PFNGLTEXCOORDP4UIVPROC glTexCoordP4uiv;
+extern PFNGLMULTITEXCOORDP1UIPROC glMultiTexCoordP1ui;
+extern PFNGLMULTITEXCOORDP1UIVPROC glMultiTexCoordP1uiv;
+extern PFNGLMULTITEXCOORDP2UIPROC glMultiTexCoordP2ui;
+extern PFNGLMULTITEXCOORDP2UIVPROC glMultiTexCoordP2uiv;
+extern PFNGLMULTITEXCOORDP3UIPROC glMultiTexCoordP3ui;
+extern PFNGLMULTITEXCOORDP3UIVPROC glMultiTexCoordP3uiv;
+extern PFNGLMULTITEXCOORDP4UIPROC glMultiTexCoordP4ui;
+extern PFNGLMULTITEXCOORDP4UIVPROC glMultiTexCoordP4uiv;
+extern PFNGLNORMALP3UIPROC glNormalP3ui;
+extern PFNGLNORMALP3UIVPROC glNormalP3uiv;
+extern PFNGLCOLORP3UIPROC glColorP3ui;
+extern PFNGLCOLORP3UIVPROC glColorP3uiv;
+extern PFNGLCOLORP4UIPROC glColorP4ui;
+extern PFNGLCOLORP4UIVPROC glColorP4uiv;
+extern PFNGLSECONDARYCOLORP3UIPROC glSecondaryColorP3ui;
+extern PFNGLSECONDARYCOLORP3UIVPROC glSecondaryColorP3uiv;
+
+// GL_VERSION_4_0
+extern PFNGLMINSAMPLESHADINGPROC glMinSampleShading;
+extern PFNGLBLENDEQUATIONIPROC glBlendEquationi;
+extern PFNGLBLENDEQUATIONSEPARATEIPROC glBlendEquationSeparatei;
+extern PFNGLBLENDFUNCIPROC glBlendFunci;
+extern PFNGLBLENDFUNCSEPARATEIPROC glBlendFuncSeparatei;
+extern PFNGLDRAWARRAYSINDIRECTPROC glDrawArraysIndirect;
+extern PFNGLDRAWELEMENTSINDIRECTPROC glDrawElementsIndirect;
+extern PFNGLUNIFORM1DPROC glUniform1d;
+extern PFNGLUNIFORM2DPROC glUniform2d;
+extern PFNGLUNIFORM3DPROC glUniform3d;
+extern PFNGLUNIFORM4DPROC glUniform4d;
+extern PFNGLUNIFORM1DVPROC glUniform1dv;
+extern PFNGLUNIFORM2DVPROC glUniform2dv;
+extern PFNGLUNIFORM3DVPROC glUniform3dv;
+extern PFNGLUNIFORM4DVPROC glUniform4dv;
+extern PFNGLUNIFORMMATRIX2DVPROC glUniformMatrix2dv;
+extern PFNGLUNIFORMMATRIX3DVPROC glUniformMatrix3dv;
+extern PFNGLUNIFORMMATRIX4DVPROC glUniformMatrix4dv;
+extern PFNGLUNIFORMMATRIX2X3DVPROC glUniformMatrix2x3dv;
+extern PFNGLUNIFORMMATRIX2X4DVPROC glUniformMatrix2x4dv;
+extern PFNGLUNIFORMMATRIX3X2DVPROC glUniformMatrix3x2dv;
+extern PFNGLUNIFORMMATRIX3X4DVPROC glUniformMatrix3x4dv;
+extern PFNGLUNIFORMMATRIX4X2DVPROC glUniformMatrix4x2dv;
+extern PFNGLUNIFORMMATRIX4X3DVPROC glUniformMatrix4x3dv;
+extern PFNGLGETUNIFORMDVPROC glGetUniformdv;
+extern PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC glGetSubroutineUniformLocation;
+extern PFNGLGETSUBROUTINEINDEXPROC glGetSubroutineIndex;
+extern PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC glGetActiveSubroutineUniformiv;
+extern PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC glGetActiveSubroutineUniformName;
+extern PFNGLGETACTIVESUBROUTINENAMEPROC glGetActiveSubroutineName;
+extern PFNGLUNIFORMSUBROUTINESUIVPROC glUniformSubroutinesuiv;
+extern PFNGLGETUNIFORMSUBROUTINEUIVPROC glGetUniformSubroutineuiv;
+extern PFNGLGETPROGRAMSTAGEIVPROC glGetProgramStageiv;
+extern PFNGLPATCHPARAMETERIPROC glPatchParameteri;
+extern PFNGLPATCHPARAMETERFVPROC glPatchParameterfv;
+extern PFNGLBINDTRANSFORMFEEDBACKPROC glBindTransformFeedback;
+extern PFNGLDELETETRANSFORMFEEDBACKSPROC glDeleteTransformFeedbacks;
+extern PFNGLGENTRANSFORMFEEDBACKSPROC glGenTransformFeedbacks;
+extern PFNGLISTRANSFORMFEEDBACKPROC glIsTransformFeedback;
+extern PFNGLPAUSETRANSFORMFEEDBACKPROC glPauseTransformFeedback;
+extern PFNGLRESUMETRANSFORMFEEDBACKPROC glResumeTransformFeedback;
+extern PFNGLDRAWTRANSFORMFEEDBACKPROC glDrawTransformFeedback;
+extern PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC glDrawTransformFeedbackStream;
+extern PFNGLBEGINQUERYINDEXEDPROC glBeginQueryIndexed;
+extern PFNGLENDQUERYINDEXEDPROC glEndQueryIndexed;
+extern PFNGLGETQUERYINDEXEDIVPROC glGetQueryIndexediv;
+
+ // GL_VERSION_4_1
+extern PFNGLRELEASESHADERCOMPILERPROC glReleaseShaderCompiler;
+extern PFNGLSHADERBINARYPROC glShaderBinary;
+extern PFNGLGETSHADERPRECISIONFORMATPROC glGetShaderPrecisionFormat;
+extern PFNGLDEPTHRANGEFPROC glDepthRangef;
+extern PFNGLCLEARDEPTHFPROC glClearDepthf;
+extern PFNGLGETPROGRAMBINARYPROC glGetProgramBinary;
+extern PFNGLPROGRAMBINARYPROC glProgramBinary;
+extern PFNGLPROGRAMPARAMETERIPROC glProgramParameteri;
+extern PFNGLUSEPROGRAMSTAGESPROC glUseProgramStages;
+extern PFNGLACTIVESHADERPROGRAMPROC glActiveShaderProgram;
+extern PFNGLCREATESHADERPROGRAMVPROC glCreateShaderProgramv;
+extern PFNGLBINDPROGRAMPIPELINEPROC glBindProgramPipeline;
+extern PFNGLDELETEPROGRAMPIPELINESPROC glDeleteProgramPipelines;
+extern PFNGLGENPROGRAMPIPELINESPROC glGenProgramPipelines;
+extern PFNGLISPROGRAMPIPELINEPROC glIsProgramPipeline;
+extern PFNGLGETPROGRAMPIPELINEIVPROC glGetProgramPipelineiv;
+extern PFNGLPROGRAMUNIFORM1IPROC glProgramUniform1i;
+extern PFNGLPROGRAMUNIFORM1IVPROC glProgramUniform1iv;
+extern PFNGLPROGRAMUNIFORM1FPROC glProgramUniform1f;
+extern PFNGLPROGRAMUNIFORM1FVPROC glProgramUniform1fv;
+extern PFNGLPROGRAMUNIFORM1DPROC glProgramUniform1d;
+extern PFNGLPROGRAMUNIFORM1DVPROC glProgramUniform1dv;
+extern PFNGLPROGRAMUNIFORM1UIPROC glProgramUniform1ui;
+extern PFNGLPROGRAMUNIFORM1UIVPROC glProgramUniform1uiv;
+extern PFNGLPROGRAMUNIFORM2IPROC glProgramUniform2i;
+extern PFNGLPROGRAMUNIFORM2IVPROC glProgramUniform2iv;
+extern PFNGLPROGRAMUNIFORM2FPROC glProgramUniform2f;
+extern PFNGLPROGRAMUNIFORM2FVPROC glProgramUniform2fv;
+extern PFNGLPROGRAMUNIFORM2DPROC glProgramUniform2d;
+extern PFNGLPROGRAMUNIFORM2DVPROC glProgramUniform2dv;
+extern PFNGLPROGRAMUNIFORM2UIPROC glProgramUniform2ui;
+extern PFNGLPROGRAMUNIFORM2UIVPROC glProgramUniform2uiv;
+extern PFNGLPROGRAMUNIFORM3IPROC glProgramUniform3i;
+extern PFNGLPROGRAMUNIFORM3IVPROC glProgramUniform3iv;
+extern PFNGLPROGRAMUNIFORM3FPROC glProgramUniform3f;
+extern PFNGLPROGRAMUNIFORM3FVPROC glProgramUniform3fv;
+extern PFNGLPROGRAMUNIFORM3DPROC glProgramUniform3d;
+extern PFNGLPROGRAMUNIFORM3DVPROC glProgramUniform3dv;
+extern PFNGLPROGRAMUNIFORM3UIPROC glProgramUniform3ui;
+extern PFNGLPROGRAMUNIFORM3UIVPROC glProgramUniform3uiv;
+extern PFNGLPROGRAMUNIFORM4IPROC glProgramUniform4i;
+extern PFNGLPROGRAMUNIFORM4IVPROC glProgramUniform4iv;
+extern PFNGLPROGRAMUNIFORM4FPROC glProgramUniform4f;
+extern PFNGLPROGRAMUNIFORM4FVPROC glProgramUniform4fv;
+extern PFNGLPROGRAMUNIFORM4DPROC glProgramUniform4d;
+extern PFNGLPROGRAMUNIFORM4DVPROC glProgramUniform4dv;
+extern PFNGLPROGRAMUNIFORM4UIPROC glProgramUniform4ui;
+extern PFNGLPROGRAMUNIFORM4UIVPROC glProgramUniform4uiv;
+extern PFNGLPROGRAMUNIFORMMATRIX2FVPROC glProgramUniformMatrix2fv;
+extern PFNGLPROGRAMUNIFORMMATRIX3FVPROC glProgramUniformMatrix3fv;
+extern PFNGLPROGRAMUNIFORMMATRIX4FVPROC glProgramUniformMatrix4fv;
+extern PFNGLPROGRAMUNIFORMMATRIX2DVPROC glProgramUniformMatrix2dv;
+extern PFNGLPROGRAMUNIFORMMATRIX3DVPROC glProgramUniformMatrix3dv;
+extern PFNGLPROGRAMUNIFORMMATRIX4DVPROC glProgramUniformMatrix4dv;
+extern PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC glProgramUniformMatrix2x3fv;
+extern PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC glProgramUniformMatrix3x2fv;
+extern PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC glProgramUniformMatrix2x4fv;
+extern PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC glProgramUniformMatrix4x2fv;
+extern PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC glProgramUniformMatrix3x4fv;
+extern PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC glProgramUniformMatrix4x3fv;
+extern PFNGLPROGRAMUNIFORMMATRIX2X3DVPROC glProgramUniformMatrix2x3dv;
+extern PFNGLPROGRAMUNIFORMMATRIX3X2DVPROC glProgramUniformMatrix3x2dv;
+extern PFNGLPROGRAMUNIFORMMATRIX2X4DVPROC glProgramUniformMatrix2x4dv;
+extern PFNGLPROGRAMUNIFORMMATRIX4X2DVPROC glProgramUniformMatrix4x2dv;
+extern PFNGLPROGRAMUNIFORMMATRIX3X4DVPROC glProgramUniformMatrix3x4dv;
+extern PFNGLPROGRAMUNIFORMMATRIX4X3DVPROC glProgramUniformMatrix4x3dv;
+extern PFNGLVALIDATEPROGRAMPIPELINEPROC glValidateProgramPipeline;
+extern PFNGLGETPROGRAMPIPELINEINFOLOGPROC glGetProgramPipelineInfoLog;
+extern PFNGLVERTEXATTRIBL1DPROC glVertexAttribL1d;
+extern PFNGLVERTEXATTRIBL2DPROC glVertexAttribL2d;
+extern PFNGLVERTEXATTRIBL3DPROC glVertexAttribL3d;
+extern PFNGLVERTEXATTRIBL4DPROC glVertexAttribL4d;
+extern PFNGLVERTEXATTRIBL1DVPROC glVertexAttribL1dv;
+extern PFNGLVERTEXATTRIBL2DVPROC glVertexAttribL2dv;
+extern PFNGLVERTEXATTRIBL3DVPROC glVertexAttribL3dv;
+extern PFNGLVERTEXATTRIBL4DVPROC glVertexAttribL4dv;
+extern PFNGLVERTEXATTRIBLPOINTERPROC glVertexAttribLPointer;
+extern PFNGLGETVERTEXATTRIBLDVPROC glGetVertexAttribLdv;
+extern PFNGLVIEWPORTARRAYVPROC glViewportArrayv;
+extern PFNGLVIEWPORTINDEXEDFPROC glViewportIndexedf;
+extern PFNGLVIEWPORTINDEXEDFVPROC glViewportIndexedfv;
+extern PFNGLSCISSORARRAYVPROC glScissorArrayv;
+extern PFNGLSCISSORINDEXEDPROC glScissorIndexed;
+extern PFNGLSCISSORINDEXEDVPROC glScissorIndexedv;
+extern PFNGLDEPTHRANGEARRAYVPROC glDepthRangeArrayv;
+extern PFNGLDEPTHRANGEINDEXEDPROC glDepthRangeIndexed;
+extern PFNGLGETFLOATI_VPROC glGetFloati_v;
+extern PFNGLGETDOUBLEI_VPROC glGetDoublei_v;
+
+// GL_VERSION_4_2
+extern PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC glDrawArraysInstancedBaseInstance;
+extern PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC glDrawElementsInstancedBaseInstance;
+extern PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC glDrawElementsInstancedBaseVertexBaseInstance;
+extern PFNGLGETINTERNALFORMATIVPROC glGetInternalformativ;
+extern PFNGLGETACTIVEATOMICCOUNTERBUFFERIVPROC glGetActiveAtomicCounterBufferiv;
+extern PFNGLBINDIMAGETEXTUREPROC glBindImageTexture;
+extern PFNGLMEMORYBARRIERPROC glMemoryBarrier;
+extern PFNGLTEXSTORAGE1DPROC glTexStorage1D;
+extern PFNGLTEXSTORAGE2DPROC glTexStorage2D;
+extern PFNGLTEXSTORAGE3DPROC glTexStorage3D;
+extern PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDPROC glDrawTransformFeedbackInstanced;
+extern PFNGLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC glDrawTransformFeedbackStreamInstanced;
+
+// GL_VERSION_4_3
+extern PFNGLCLEARBUFFERDATAPROC glClearBufferData;
+extern PFNGLCLEARBUFFERSUBDATAPROC glClearBufferSubData;
+extern PFNGLDISPATCHCOMPUTEPROC glDispatchCompute;
+extern PFNGLDISPATCHCOMPUTEINDIRECTPROC glDispatchComputeIndirect;
+extern PFNGLCOPYIMAGESUBDATAPROC glCopyImageSubData;
+extern PFNGLFRAMEBUFFERPARAMETERIPROC glFramebufferParameteri;
+extern PFNGLGETFRAMEBUFFERPARAMETERIVPROC glGetFramebufferParameteriv;
+extern PFNGLGETINTERNALFORMATI64VPROC glGetInternalformati64v;
+extern PFNGLINVALIDATETEXSUBIMAGEPROC glInvalidateTexSubImage;
+extern PFNGLINVALIDATETEXIMAGEPROC glInvalidateTexImage;
+extern PFNGLINVALIDATEBUFFERSUBDATAPROC glInvalidateBufferSubData;
+extern PFNGLINVALIDATEBUFFERDATAPROC glInvalidateBufferData;
+extern PFNGLINVALIDATEFRAMEBUFFERPROC glInvalidateFramebuffer;
+extern PFNGLINVALIDATESUBFRAMEBUFFERPROC glInvalidateSubFramebuffer;
+extern PFNGLMULTIDRAWARRAYSINDIRECTPROC glMultiDrawArraysIndirect;
+extern PFNGLMULTIDRAWELEMENTSINDIRECTPROC glMultiDrawElementsIndirect;
+extern PFNGLGETPROGRAMINTERFACEIVPROC glGetProgramInterfaceiv;
+extern PFNGLGETPROGRAMRESOURCEINDEXPROC glGetProgramResourceIndex;
+extern PFNGLGETPROGRAMRESOURCENAMEPROC glGetProgramResourceName;
+extern PFNGLGETPROGRAMRESOURCEIVPROC glGetProgramResourceiv;
+extern PFNGLGETPROGRAMRESOURCELOCATIONPROC glGetProgramResourceLocation;
+extern PFNGLGETPROGRAMRESOURCELOCATIONINDEXPROC glGetProgramResourceLocationIndex;
+extern PFNGLSHADERSTORAGEBLOCKBINDINGPROC glShaderStorageBlockBinding;
+extern PFNGLTEXBUFFERRANGEPROC glTexBufferRange;
+extern PFNGLTEXSTORAGE2DMULTISAMPLEPROC glTexStorage2DMultisample;
+extern PFNGLTEXSTORAGE3DMULTISAMPLEPROC glTexStorage3DMultisample;
+extern PFNGLTEXTUREVIEWPROC glTextureView;
+extern PFNGLBINDVERTEXBUFFERPROC glBindVertexBuffer;
+extern PFNGLVERTEXATTRIBFORMATPROC glVertexAttribFormat;
+extern PFNGLVERTEXATTRIBIFORMATPROC glVertexAttribIFormat;
+extern PFNGLVERTEXATTRIBLFORMATPROC glVertexAttribLFormat;
+extern PFNGLVERTEXATTRIBBINDINGPROC glVertexAttribBinding;
+extern PFNGLVERTEXBINDINGDIVISORPROC glVertexBindingDivisor;
+extern PFNGLDEBUGMESSAGECONTROLPROC glDebugMessageControl;
+extern PFNGLDEBUGMESSAGEINSERTPROC glDebugMessageInsert;
+extern PFNGLDEBUGMESSAGECALLBACKPROC glDebugMessageCallback;
+extern PFNGLGETDEBUGMESSAGELOGPROC glGetDebugMessageLog;
+extern PFNGLPUSHDEBUGGROUPPROC glPushDebugGroup;
+extern PFNGLPOPDEBUGGROUPPROC glPopDebugGroup;
+extern PFNGLOBJECTLABELPROC glObjectLabel;
+extern PFNGLGETOBJECTLABELPROC glGetObjectLabel;
+extern PFNGLOBJECTPTRLABELPROC glObjectPtrLabel;
+extern PFNGLGETOBJECTPTRLABELPROC glGetObjectPtrLabel;
+
+// GL_VERSION_4_4
+extern PFNGLBUFFERSTORAGEPROC glBufferStorage;
+extern PFNGLCLEARTEXIMAGEPROC glClearTexImage;
+extern PFNGLCLEARTEXSUBIMAGEPROC glClearTexSubImage;
+extern PFNGLBINDBUFFERSBASEPROC glBindBuffersBase;
+extern PFNGLBINDBUFFERSRANGEPROC glBindBuffersRange;
+extern PFNGLBINDTEXTURESPROC glBindTextures;
+extern PFNGLBINDSAMPLERSPROC glBindSamplers;
+extern PFNGLBINDIMAGETEXTURESPROC glBindImageTextures;
+extern PFNGLBINDVERTEXBUFFERSPROC glBindVertexBuffers;
+
+// GL_VERSION_4_5
+extern PFNGLCLIPCONTROLPROC glClipControl;
+extern PFNGLCREATETRANSFORMFEEDBACKSPROC glCreateTransformFeedbacks;
+extern PFNGLTRANSFORMFEEDBACKBUFFERBASEPROC glTransformFeedbackBufferBase;
+extern PFNGLTRANSFORMFEEDBACKBUFFERRANGEPROC glTransformFeedbackBufferRange;
+extern PFNGLGETTRANSFORMFEEDBACKIVPROC glGetTransformFeedbackiv;
+extern PFNGLGETTRANSFORMFEEDBACKI_VPROC glGetTransformFeedbacki_v;
+extern PFNGLGETTRANSFORMFEEDBACKI64_VPROC glGetTransformFeedbacki64_v;
+extern PFNGLCREATEBUFFERSPROC glCreateBuffers;
+extern PFNGLNAMEDBUFFERSTORAGEPROC glNamedBufferStorage;
+extern PFNGLNAMEDBUFFERDATAPROC glNamedBufferData;
+extern PFNGLNAMEDBUFFERSUBDATAPROC glNamedBufferSubData;
+extern PFNGLCOPYNAMEDBUFFERSUBDATAPROC glCopyNamedBufferSubData;
+extern PFNGLCLEARNAMEDBUFFERDATAPROC glClearNamedBufferData;
+extern PFNGLCLEARNAMEDBUFFERSUBDATAPROC glClearNamedBufferSubData;
+extern PFNGLMAPNAMEDBUFFERPROC glMapNamedBuffer;
+extern PFNGLMAPNAMEDBUFFERRANGEPROC glMapNamedBufferRange;
+extern PFNGLUNMAPNAMEDBUFFERPROC glUnmapNamedBuffer;
+extern PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEPROC glFlushMappedNamedBufferRange;
+extern PFNGLGETNAMEDBUFFERPARAMETERIVPROC glGetNamedBufferParameteriv;
+extern PFNGLGETNAMEDBUFFERPARAMETERI64VPROC glGetNamedBufferParameteri64v;
+extern PFNGLGETNAMEDBUFFERPOINTERVPROC glGetNamedBufferPointerv;
+extern PFNGLGETNAMEDBUFFERSUBDATAPROC glGetNamedBufferSubData;
+extern PFNGLCREATEFRAMEBUFFERSPROC glCreateFramebuffers;
+extern PFNGLNAMEDFRAMEBUFFERRENDERBUFFERPROC glNamedFramebufferRenderbuffer;
+extern PFNGLNAMEDFRAMEBUFFERPARAMETERIPROC glNamedFramebufferParameteri;
+extern PFNGLNAMEDFRAMEBUFFERTEXTUREPROC glNamedFramebufferTexture;
+extern PFNGLNAMEDFRAMEBUFFERTEXTURELAYERPROC glNamedFramebufferTextureLayer;
+extern PFNGLNAMEDFRAMEBUFFERDRAWBUFFERPROC glNamedFramebufferDrawBuffer;
+extern PFNGLNAMEDFRAMEBUFFERDRAWBUFFERSPROC glNamedFramebufferDrawBuffers;
+extern PFNGLNAMEDFRAMEBUFFERREADBUFFERPROC glNamedFramebufferReadBuffer;
+extern PFNGLINVALIDATENAMEDFRAMEBUFFERDATAPROC glInvalidateNamedFramebufferData;
+extern PFNGLINVALIDATENAMEDFRAMEBUFFERSUBDATAPROC glInvalidateNamedFramebufferSubData;
+extern PFNGLCLEARNAMEDFRAMEBUFFERIVPROC glClearNamedFramebufferiv;
+extern PFNGLCLEARNAMEDFRAMEBUFFERUIVPROC glClearNamedFramebufferuiv;
+extern PFNGLCLEARNAMEDFRAMEBUFFERFVPROC glClearNamedFramebufferfv;
+extern PFNGLCLEARNAMEDFRAMEBUFFERFIPROC glClearNamedFramebufferfi;
+extern PFNGLBLITNAMEDFRAMEBUFFERPROC glBlitNamedFramebuffer;
+extern PFNGLCHECKNAMEDFRAMEBUFFERSTATUSPROC glCheckNamedFramebufferStatus;
+extern PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVPROC glGetNamedFramebufferParameteriv;
+extern PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVPROC glGetNamedFramebufferAttachmentParameteriv;
+extern PFNGLCREATERENDERBUFFERSPROC glCreateRenderbuffers;
+extern PFNGLNAMEDRENDERBUFFERSTORAGEPROC glNamedRenderbufferStorage;
+extern PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEPROC glNamedRenderbufferStorageMultisample;
+extern PFNGLGETNAMEDRENDERBUFFERPARAMETERIVPROC glGetNamedRenderbufferParameteriv;
+extern PFNGLCREATETEXTURESPROC glCreateTextures;
+extern PFNGLTEXTUREBUFFERPROC glTextureBuffer;
+extern PFNGLTEXTUREBUFFERRANGEPROC glTextureBufferRange;
+extern PFNGLTEXTURESTORAGE1DPROC glTextureStorage1D;
+extern PFNGLTEXTURESTORAGE2DPROC glTextureStorage2D;
+extern PFNGLTEXTURESTORAGE3DPROC glTextureStorage3D;
+extern PFNGLTEXTURESTORAGE2DMULTISAMPLEPROC glTextureStorage2DMultisample;
+extern PFNGLTEXTURESTORAGE3DMULTISAMPLEPROC glTextureStorage3DMultisample;
+extern PFNGLTEXTURESUBIMAGE1DPROC glTextureSubImage1D;
+extern PFNGLTEXTURESUBIMAGE2DPROC glTextureSubImage2D;
+extern PFNGLTEXTURESUBIMAGE3DPROC glTextureSubImage3D;
+extern PFNGLCOMPRESSEDTEXTURESUBIMAGE1DPROC glCompressedTextureSubImage1D;
+extern PFNGLCOMPRESSEDTEXTURESUBIMAGE2DPROC glCompressedTextureSubImage2D;
+extern PFNGLCOMPRESSEDTEXTURESUBIMAGE3DPROC glCompressedTextureSubImage3D;
+extern PFNGLCOPYTEXTURESUBIMAGE1DPROC glCopyTextureSubImage1D;
+extern PFNGLCOPYTEXTURESUBIMAGE2DPROC glCopyTextureSubImage2D;
+extern PFNGLCOPYTEXTURESUBIMAGE3DPROC glCopyTextureSubImage3D;
+extern PFNGLTEXTUREPARAMETERFPROC glTextureParameterf;
+extern PFNGLTEXTUREPARAMETERFVPROC glTextureParameterfv;
+extern PFNGLTEXTUREPARAMETERIPROC glTextureParameteri;
+extern PFNGLTEXTUREPARAMETERIIVPROC glTextureParameterIiv;
+extern PFNGLTEXTUREPARAMETERIUIVPROC glTextureParameterIuiv;
+extern PFNGLTEXTUREPARAMETERIVPROC glTextureParameteriv;
+extern PFNGLGENERATETEXTUREMIPMAPPROC glGenerateTextureMipmap;
+extern PFNGLBINDTEXTUREUNITPROC glBindTextureUnit;
+extern PFNGLGETTEXTUREIMAGEPROC glGetTextureImage;
+extern PFNGLGETCOMPRESSEDTEXTUREIMAGEPROC glGetCompressedTextureImage;
+extern PFNGLGETTEXTURELEVELPARAMETERFVPROC glGetTextureLevelParameterfv;
+extern PFNGLGETTEXTURELEVELPARAMETERIVPROC glGetTextureLevelParameteriv;
+extern PFNGLGETTEXTUREPARAMETERFVPROC glGetTextureParameterfv;
+extern PFNGLGETTEXTUREPARAMETERIIVPROC glGetTextureParameterIiv;
+extern PFNGLGETTEXTUREPARAMETERIUIVPROC glGetTextureParameterIuiv;
+extern PFNGLGETTEXTUREPARAMETERIVPROC glGetTextureParameteriv;
+extern PFNGLCREATEVERTEXARRAYSPROC glCreateVertexArrays;
+extern PFNGLDISABLEVERTEXARRAYATTRIBPROC glDisableVertexArrayAttrib;
+extern PFNGLENABLEVERTEXARRAYATTRIBPROC glEnableVertexArrayAttrib;
+extern PFNGLVERTEXARRAYELEMENTBUFFERPROC glVertexArrayElementBuffer;
+extern PFNGLVERTEXARRAYVERTEXBUFFERPROC glVertexArrayVertexBuffer;
+extern PFNGLVERTEXARRAYVERTEXBUFFERSPROC glVertexArrayVertexBuffers;
+extern PFNGLVERTEXARRAYATTRIBBINDINGPROC glVertexArrayAttribBinding;
+extern PFNGLVERTEXARRAYATTRIBFORMATPROC glVertexArrayAttribFormat;
+extern PFNGLVERTEXARRAYATTRIBIFORMATPROC glVertexArrayAttribIFormat;
+extern PFNGLVERTEXARRAYATTRIBLFORMATPROC glVertexArrayAttribLFormat;
+extern PFNGLVERTEXARRAYBINDINGDIVISORPROC glVertexArrayBindingDivisor;
+extern PFNGLGETVERTEXARRAYIVPROC glGetVertexArrayiv;
+extern PFNGLGETVERTEXARRAYINDEXEDIVPROC glGetVertexArrayIndexediv;
+extern PFNGLGETVERTEXARRAYINDEXED64IVPROC glGetVertexArrayIndexed64iv;
+extern PFNGLCREATESAMPLERSPROC glCreateSamplers;
+extern PFNGLCREATEPROGRAMPIPELINESPROC glCreateProgramPipelines;
+extern PFNGLCREATEQUERIESPROC glCreateQueries;
+extern PFNGLGETQUERYBUFFEROBJECTI64VPROC glGetQueryBufferObjecti64v;
+extern PFNGLGETQUERYBUFFEROBJECTIVPROC glGetQueryBufferObjectiv;
+extern PFNGLGETQUERYBUFFEROBJECTUI64VPROC glGetQueryBufferObjectui64v;
+extern PFNGLGETQUERYBUFFEROBJECTUIVPROC glGetQueryBufferObjectuiv;
+extern PFNGLMEMORYBARRIERBYREGIONPROC glMemoryBarrierByRegion;
+extern PFNGLGETTEXTURESUBIMAGEPROC glGetTextureSubImage;
+extern PFNGLGETCOMPRESSEDTEXTURESUBIMAGEPROC glGetCompressedTextureSubImage;
+extern PFNGLGETGRAPHICSRESETSTATUSPROC glGetGraphicsResetStatus;
+extern PFNGLGETNCOMPRESSEDTEXIMAGEPROC glGetnCompressedTexImage;
+extern PFNGLGETNTEXIMAGEPROC glGetnTexImage;
+extern PFNGLGETNUNIFORMDVPROC glGetnUniformdv;
+extern PFNGLGETNUNIFORMFVPROC glGetnUniformfv;
+extern PFNGLGETNUNIFORMIVPROC glGetnUniformiv;
+extern PFNGLGETNUNIFORMUIVPROC glGetnUniformuiv;
+extern PFNGLREADNPIXELSPROC glReadnPixels;
+extern PFNGLGETNMAPDVPROC glGetnMapdv;
+extern PFNGLGETNMAPFVPROC glGetnMapfv;
+extern PFNGLGETNMAPIVPROC glGetnMapiv;
+extern PFNGLGETNPIXELMAPFVPROC glGetnPixelMapfv;
+extern PFNGLGETNPIXELMAPUIVPROC glGetnPixelMapuiv;
+extern PFNGLGETNPIXELMAPUSVPROC glGetnPixelMapusv;
+extern PFNGLGETNPOLYGONSTIPPLEPROC glGetnPolygonStipple;
+extern PFNGLGETNCOLORTABLEPROC glGetnColorTable;
+extern PFNGLGETNCONVOLUTIONFILTERPROC glGetnConvolutionFilter;
+extern PFNGLGETNSEPARABLEFILTERPROC glGetnSeparableFilter;
+extern PFNGLGETNHISTOGRAMPROC glGetnHistogram;
+extern PFNGLGETNMINMAXPROC glGetnMinmax;
+extern PFNGLTEXTUREBARRIERPROC glTextureBarrier;
+
+// GL_VERSION_4_6
+extern PFNGLSPECIALIZESHADERPROC glSpecializeShader;
+extern PFNGLMULTIDRAWARRAYSINDIRECTCOUNTPROC glMultiDrawArraysIndirectCount;
+extern PFNGLMULTIDRAWELEMENTSINDIRECTCOUNTPROC glMultiDrawElementsIndirectCount;
+extern PFNGLPOLYGONOFFSETCLAMPPROC glPolygonOffsetClamp;
-//GL_EXT_blend_func_separate
-extern PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT;
-
-//GL_ARB_framebuffer_object
-extern PFNGLISRENDERBUFFERPROC glIsRenderbuffer;
-extern PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer;
-extern PFNGLDELETERENDERBUFFERSPROC glDeleteRenderbuffers;
-extern PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers;
-extern PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage;
-extern PFNGLGETRENDERBUFFERPARAMETERIVPROC glGetRenderbufferParameteriv;
-extern PFNGLISFRAMEBUFFERPROC glIsFramebuffer;
-extern PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer;
-extern PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers;
-extern PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers;
-extern PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus;
-extern PFNGLFRAMEBUFFERTEXTURE1DPROC glFramebufferTexture1D;
-extern PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D;
-extern PFNGLFRAMEBUFFERTEXTURE3DPROC glFramebufferTexture3D;
-extern PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer;
-extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glGetFramebufferAttachmentParameteriv;
-extern PFNGLGENERATEMIPMAPPROC glGenerateMipmap;
-extern PFNGLBLITFRAMEBUFFERPROC glBlitFramebuffer;
-extern PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glRenderbufferStorageMultisample;
-extern PFNGLFRAMEBUFFERTEXTURELAYERPROC glFramebufferTextureLayer;
-
-//GL_ARB_draw_buffers
-extern PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB;
-
-//GL_ARB_texture_multisample
-extern PFNGLTEXIMAGE2DMULTISAMPLEPROC glTexImage2DMultisample;
-extern PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample;
-extern PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv;
-extern PFNGLSAMPLEMASKIPROC glSampleMaski;
-
-//transform feedback (4.0 core)
-extern PFNGLBEGINTRANSFORMFEEDBACKPROC glBeginTransformFeedback;
-extern PFNGLENDTRANSFORMFEEDBACKPROC glEndTransformFeedback;
-extern PFNGLTRANSFORMFEEDBACKVARYINGSPROC glTransformFeedbackVaryings;
-extern PFNGLBINDBUFFERRANGEPROC glBindBufferRange;
-extern PFNGLBINDBUFFERBASEPROC glBindBufferBase;
-
-//GL_ARB_debug_output
-extern PFNGLDEBUGMESSAGECONTROLARBPROC glDebugMessageControlARB;
-extern PFNGLDEBUGMESSAGEINSERTARBPROC glDebugMessageInsertARB;
-extern PFNGLDEBUGMESSAGECALLBACKARBPROC glDebugMessageCallbackARB;
-extern PFNGLGETDEBUGMESSAGELOGARBPROC glGetDebugMessageLogARB;
#elif LL_DARWIN
//----------------------------------------------------------------------------
// LL_DARWIN
+#define GL_GLEXT_LEGACY
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#define GL_EXT_separate_specular_color 1
-#include <OpenGL/glext.h>
+#define GL_GLEXT_PROTOTYPES
+#include "GL/glext.h"
#include "GL/glh_extensions.h"
@@ -607,9 +858,6 @@ extern void glGenerateMipmapEXT(GLenum target) AVAILABLE_MAC_OS_X_VERSION_10_4_A
#define GL_MAX_SAMPLES 0x8D57
#endif
-// GL_ARB_draw_buffers
-extern void glDrawBuffersARB(GLsizei n, const GLenum* bufs) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -694,8 +942,8 @@ extern "C" {
#ifndef GL_ARB_vertex_buffer_object
/* GL types for handling large vertex buffer objects */
-typedef intptr_t GLintptrARB;
-typedef intptr_t GLsizeiptrARB;
+typedef intptr_t GLintptr;
+typedef intptr_t GLsizeiptr;
#endif
@@ -813,22 +1061,8 @@ extern void glGetBufferPointervARB (GLenum, GLenum, GLvoid* *);
#endif
#if defined(TRACY_ENABLE) && LL_PROFILER_ENABLE_TRACY_OPENGL
- // Tracy uses the following:
- // glGenQueries
- // glGetQueryiv
- // glGetQueryObjectiv
- #define glGenQueries glGenQueriesARB
- #define glGetQueryiv glGetQueryivARB
- #define glGetQueryObjectiv glGetQueryObjectivARB
#include <tracy/TracyOpenGL.hpp>
-
- #define LL_PROFILER_GPU_ZONEC(name,color) TracyGpuZoneC(name,color);
- #define LL_PROFILER_GPU_COLLECT TracyGpuCollect
- #define LL_PROFILER_GPU_CONTEXT TracyGpuContext
-#else
- #define LL_PROFILER_GPU_ZONEC(name,color) (void)name;(void)color;
- #define LL_PROFILER_GPU_COLLECT
- #define LL_PROFILER_GPU_CONTEXT
#endif
+
#endif // LL_LLGLHEADERS_H
diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp
index 185c1450c8..faa45d59b9 100644
--- a/indra/llrender/llglslshader.cpp
+++ b/indra/llrender/llglslshader.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llglslshader.cpp
* @brief GLSL helper functions and state.
*
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, 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$
*/
@@ -37,8 +37,8 @@
#include "OpenGL/OpenGL.h"
#endif
-// Print-print list of shader included source files that are linked together via glAttachObjectARB()
-// i.e. On macOS / OSX the AMD GLSL linker will display an error if a varying is left in an undefined state.
+ // Print-print list of shader included source files that are linked together via glAttachShader()
+ // i.e. On macOS / OSX the AMD GLSL linker will display an error if a varying is left in an undefined state.
#define DEBUG_SHADER_INCLUDES 0
// Lots of STL stuff in here, using namespace std to keep things more readable
@@ -47,7 +47,7 @@ using std::pair;
using std::make_pair;
using std::string;
-GLhandleARB LLGLSLShader::sCurBoundShader = 0;
+GLuint LLGLSLShader::sCurBoundShader = 0;
LLGLSLShader* LLGLSLShader::sCurBoundShaderPtr = NULL;
S32 LLGLSLShader::sIndexedTextureChannels = 0;
bool LLGLSLShader::sProfileEnabled = false;
@@ -55,12 +55,27 @@ std::set<LLGLSLShader*> LLGLSLShader::sInstances;
U64 LLGLSLShader::sTotalTimeElapsed = 0;
U32 LLGLSLShader::sTotalTrianglesDrawn = 0;
U64 LLGLSLShader::sTotalSamplesDrawn = 0;
-U32 LLGLSLShader::sTotalDrawCalls = 0;
+U32 LLGLSLShader::sTotalBinds = 0;
//UI shader -- declared here so llui_libtest will link properly
LLGLSLShader gUIProgram;
LLGLSLShader gSolidColorProgram;
+// NOTE: Keep gShaderConsts* and LLGLSLShader::ShaderConsts_e in sync!
+const std::string gShaderConstsKey[LLGLSLShader::NUM_SHADER_CONSTS] =
+{
+ "LL_SHADER_CONST_CLOUD_MOON_DEPTH"
+ , "LL_SHADER_CONST_STAR_DEPTH"
+};
+
+// NOTE: Keep gShaderConsts* and LLGLSLShader::ShaderConsts_e in sync!
+const std::string gShaderConstsVal[LLGLSLShader::NUM_SHADER_CONSTS] =
+{
+ "0.99998" // SHADER_CONST_CLOUD_MOON_DEPTH // SL-14113
+ , "0.99999" // SHADER_CONST_STAR_DEPTH // SL-14113
+};
+
+
BOOL shouldChange(const LLVector4& v1, const LLVector4& v2)
{
return v1 != v2;
@@ -84,6 +99,7 @@ LLShaderFeatures::LLShaderFeatures()
, hasSrgb(false)
, encodesNormal(false)
, isDeferred(false)
+ , hasScreenSpaceReflections(false)
, hasIndirect(false)
, hasShadows(false)
, hasAmbientOcclusion(false)
@@ -105,7 +121,7 @@ void LLGLSLShader::initProfile()
sTotalTimeElapsed = 0;
sTotalTrianglesDrawn = 0;
sTotalSamplesDrawn = 0;
- sTotalDrawCalls = 0;
+ sTotalBinds = 0;
for (std::set<LLGLSLShader*>::iterator iter = sInstances.begin(); iter != sInstances.end(); ++iter)
{
@@ -116,10 +132,10 @@ void LLGLSLShader::initProfile()
struct LLGLSLShaderCompareTimeElapsed
{
- bool operator()(const LLGLSLShader* const& lhs, const LLGLSLShader* const& rhs)
- {
- return lhs->mTimeElapsed < rhs->mTimeElapsed;
- }
+ bool operator()(const LLGLSLShader* const& lhs, const LLGLSLShader* const& rhs)
+ {
+ return lhs->mTimeElapsed < rhs->mTimeElapsed;
+ }
};
//static
@@ -138,15 +154,33 @@ void LLGLSLShader::finishProfile(bool emit_report)
std::sort(sorted.begin(), sorted.end(), LLGLSLShaderCompareTimeElapsed());
+ bool unbound = false;
for (std::vector<LLGLSLShader*>::iterator iter = sorted.begin(); iter != sorted.end(); ++iter)
{
(*iter)->dumpStats();
+ if ((*iter)->mBinds == 0)
+ {
+ unbound = true;
+ }
+ }
+
+ LL_INFOS() << "-----------------------------------" << LL_ENDL;
+ LL_INFOS() << "Total rendering time: " << llformat("%.4f ms", sTotalTimeElapsed / 1000000.f) << LL_ENDL;
+ LL_INFOS() << "Total samples drawn: " << llformat("%.4f million", sTotalSamplesDrawn / 1000000.f) << LL_ENDL;
+ LL_INFOS() << "Total triangles drawn: " << llformat("%.3f million", sTotalTrianglesDrawn / 1000000.f) << LL_ENDL;
+ LL_INFOS() << "-----------------------------------" << LL_ENDL;
+
+ if (unbound)
+ {
+ LL_INFOS() << "The following shaders were unused: " << LL_ENDL;
+ for (std::vector<LLGLSLShader*>::iterator iter = sorted.begin(); iter != sorted.end(); ++iter)
+ {
+ if ((*iter)->mBinds == 0)
+ {
+ LL_INFOS() << (*iter)->mName << LL_ENDL;
+ }
+ }
}
-
- LL_INFOS() << "-----------------------------------" << LL_ENDL;
- LL_INFOS() << "Total rendering time: " << llformat("%.4f ms", sTotalTimeElapsed/1000000.f) << LL_ENDL;
- LL_INFOS() << "Total samples drawn: " << llformat("%.4f million", sTotalSamplesDrawn/1000000.f) << LL_ENDL;
- LL_INFOS() << "Total triangles drawn: " << llformat("%.3f million", sTotalTrianglesDrawn/1000000.f) << LL_ENDL;
}
}
@@ -155,15 +189,12 @@ void LLGLSLShader::clearStats()
mTrianglesDrawn = 0;
mTimeElapsed = 0;
mSamplesDrawn = 0;
- mDrawCalls = 0;
- mTextureStateFetched = false;
- mTextureMagFilter.clear();
- mTextureMinFilter.clear();
+ mBinds = 0;
}
void LLGLSLShader::dumpStats()
{
- if (mDrawCalls > 0)
+ if (mBinds > 0)
{
LL_INFOS() << "=============================================" << LL_ENDL;
LL_INFOS() << mName << LL_ENDL;
@@ -171,36 +202,25 @@ void LLGLSLShader::dumpStats()
{
LL_INFOS() << mShaderFiles[i].first << LL_ENDL;
}
- for (U32 i = 0; i < mTexture.size(); ++i)
- {
- GLint idx = mTexture[i];
-
- if (idx >= 0)
- {
- GLint uniform_idx = getUniformLocation(i);
- LL_INFOS() << mUniformNameMap[uniform_idx] << " - " << std::hex << mTextureMagFilter[i] << "/" << mTextureMinFilter[i] << std::dec << LL_ENDL;
- }
- }
LL_INFOS() << "=============================================" << LL_ENDL;
-
- F32 ms = mTimeElapsed/1000000.f;
- F32 seconds = ms/1000.f;
- F32 pct_tris = (F32) mTrianglesDrawn/(F32)sTotalTrianglesDrawn*100.f;
- F32 tris_sec = (F32) (mTrianglesDrawn/1000000.0);
+ F32 ms = mTimeElapsed / 1000000.f;
+ F32 seconds = ms / 1000.f;
+
+ F32 pct_tris = (F32)mTrianglesDrawn / (F32)sTotalTrianglesDrawn * 100.f;
+ F32 tris_sec = (F32)(mTrianglesDrawn / 1000000.0);
tris_sec /= seconds;
- F32 pct_samples = (F32) ((F64)mSamplesDrawn/(F64)sTotalSamplesDrawn)*100.f;
- F32 samples_sec = (F32) mSamplesDrawn/1000000000.0;
+ F32 pct_samples = (F32)((F64)mSamplesDrawn / (F64)sTotalSamplesDrawn) * 100.f;
+ F32 samples_sec = (F32)mSamplesDrawn / 1000000000.0;
samples_sec /= seconds;
- F32 pct_calls = (F32) mDrawCalls/(F32)sTotalDrawCalls*100.f;
- U32 avg_batch = mTrianglesDrawn/mDrawCalls;
+ F32 pct_binds = (F32)mBinds / (F32)sTotalBinds * 100.f;
- LL_INFOS() << "Triangles Drawn: " << mTrianglesDrawn << " " << llformat("(%.2f pct of total, %.3f million/sec)", pct_tris, tris_sec ) << LL_ENDL;
- LL_INFOS() << "Draw Calls: " << mDrawCalls << " " << llformat("(%.2f pct of total, avg %d tris/call)", pct_calls, avg_batch) << LL_ENDL;
+ LL_INFOS() << "Triangles Drawn: " << mTrianglesDrawn << " " << llformat("(%.2f pct of total, %.3f million/sec)", pct_tris, tris_sec) << LL_ENDL;
+ LL_INFOS() << "Binds: " << mBinds << " " << llformat("(%.2f pct of total)", pct_binds) << LL_ENDL;
LL_INFOS() << "SamplesDrawn: " << mSamplesDrawn << " " << llformat("(%.2f pct of total, %.3f billion/sec)", pct_samples, samples_sec) << LL_ENDL;
- LL_INFOS() << "Time Elapsed: " << mTimeElapsed << " " << llformat("(%.2f pct of total, %.5f ms)\n", (F32) ((F64)mTimeElapsed/(F64)sTotalTimeElapsed)*100.f, ms) << LL_ENDL;
+ LL_INFOS() << "Time Elapsed: " << mTimeElapsed << " " << llformat("(%.2f pct of total, %.5f ms)\n", (F32)((F64)mTimeElapsed / (F64)sTotalTimeElapsed) * 100.f, ms) << LL_ENDL;
}
}
@@ -216,112 +236,80 @@ void LLGLSLShader::startProfile()
}
//static
-void LLGLSLShader::stopProfile(U32 count, U32 mode)
+void LLGLSLShader::stopProfile()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+
if (sProfileEnabled && sCurBoundShaderPtr)
{
- sCurBoundShaderPtr->readProfileQuery(count, mode);
+ sCurBoundShaderPtr->unbind();
}
}
void LLGLSLShader::placeProfileQuery()
{
-#if !LL_DARWIN
- if (mTimerQuery == 0)
+ if (sProfileEnabled)
{
- glGenQueriesARB(1, &mSamplesQuery);
- glGenQueriesARB(1, &mTimerQuery);
- }
-
- if (!mTextureStateFetched)
- {
- mTextureStateFetched = true;
- mTextureMagFilter.resize(mTexture.size());
- mTextureMinFilter.resize(mTexture.size());
-
- U32 cur_active = gGL.getCurrentTexUnitIndex();
-
- for (U32 i = 0; i < mTexture.size(); ++i)
+ if (mTimerQuery == 0)
{
- GLint idx = mTexture[i];
-
- if (idx >= 0)
- {
- gGL.getTexUnit(idx)->activate();
-
- U32 mag = 0xFFFFFFFF;
- U32 min = 0xFFFFFFFF;
-
- U32 type = LLTexUnit::getInternalType(gGL.getTexUnit(idx)->getCurrType());
-
- glGetTexParameteriv(type, GL_TEXTURE_MAG_FILTER, (GLint*) &mag);
- glGetTexParameteriv(type, GL_TEXTURE_MIN_FILTER, (GLint*) &min);
-
- mTextureMagFilter[i] = mag;
- mTextureMinFilter[i] = min;
- }
+ glGenQueries(1, &mSamplesQuery);
+ glGenQueries(1, &mTimerQuery);
+ glGenQueries(1, &mPrimitivesQuery);
}
- gGL.getTexUnit(cur_active)->activate();
+ glBeginQuery(GL_SAMPLES_PASSED, mSamplesQuery);
+ glBeginQuery(GL_TIME_ELAPSED, mTimerQuery);
+ glBeginQuery(GL_PRIMITIVES_GENERATED, mPrimitivesQuery);
}
-
-
- glBeginQueryARB(GL_SAMPLES_PASSED, mSamplesQuery);
- glBeginQueryARB(GL_TIME_ELAPSED, mTimerQuery);
-#endif
}
-void LLGLSLShader::readProfileQuery(U32 count, U32 mode)
+void LLGLSLShader::readProfileQuery()
{
-#if !LL_DARWIN
- glEndQueryARB(GL_TIME_ELAPSED);
- glEndQueryARB(GL_SAMPLES_PASSED);
-
- U64 time_elapsed = 0;
- glGetQueryObjectui64v(mTimerQuery, GL_QUERY_RESULT, &time_elapsed);
+ if (sProfileEnabled)
+ {
+ glEndQuery(GL_TIME_ELAPSED);
+ glEndQuery(GL_SAMPLES_PASSED);
+ glEndQuery(GL_PRIMITIVES_GENERATED);
- U64 samples_passed = 0;
- glGetQueryObjectui64v(mSamplesQuery, GL_QUERY_RESULT, &samples_passed);
+ U64 time_elapsed = 0;
+ glGetQueryObjectui64v(mTimerQuery, GL_QUERY_RESULT, &time_elapsed);
- sTotalTimeElapsed += time_elapsed;
- mTimeElapsed += time_elapsed;
+ U64 samples_passed = 0;
+ glGetQueryObjectui64v(mSamplesQuery, GL_QUERY_RESULT, &samples_passed);
- sTotalSamplesDrawn += samples_passed;
- mSamplesDrawn += samples_passed;
+ U64 primitives_generated = 0;
+ glGetQueryObjectui64v(mPrimitivesQuery, GL_QUERY_RESULT, &primitives_generated);
+ sTotalTimeElapsed += time_elapsed;
+ mTimeElapsed += time_elapsed;
- U32 tri_count = 0;
- switch (mode)
- {
- case LLRender::TRIANGLES: tri_count = count/3; break;
- case LLRender::TRIANGLE_FAN: tri_count = count-2; break;
- case LLRender::TRIANGLE_STRIP: tri_count = count-2; break;
- default: tri_count = count; break; //points lines etc just use primitive count
- }
+ sTotalSamplesDrawn += samples_passed;
+ mSamplesDrawn += samples_passed;
- mTrianglesDrawn += tri_count;
- sTotalTrianglesDrawn += tri_count;
+ U32 tri_count = (U32)primitives_generated / 3;
- sTotalDrawCalls++;
- mDrawCalls++;
-#endif
+ mTrianglesDrawn += tri_count;
+ sTotalTrianglesDrawn += tri_count;
+
+ sTotalBinds++;
+ mBinds++;
+ }
}
LLGLSLShader::LLGLSLShader()
- : mProgramObject(0),
- mAttributeMask(0),
- mTotalUniformSize(0),
- mActiveTextureChannels(0),
- mShaderLevel(0),
- mShaderGroup(SG_DEFAULT),
- mUniformsDirty(FALSE),
- mTimerQuery(0),
- mSamplesQuery(0)
-
+ : mProgramObject(0),
+ mAttributeMask(0),
+ mTotalUniformSize(0),
+ mActiveTextureChannels(0),
+ mShaderLevel(0),
+ mShaderGroup(SG_DEFAULT),
+ mUniformsDirty(FALSE),
+ mTimerQuery(0),
+ mSamplesQuery(0),
+ mPrimitivesQuery(0)
{
-
+
}
LLGLSLShader::~LLGLSLShader()
@@ -347,30 +335,37 @@ void LLGLSLShader::unloadInternal()
if (mProgramObject)
{
- GLhandleARB obj[1024];
- GLsizei count;
- glGetAttachedObjectsARB(mProgramObject, 1024, &count, obj);
+ GLuint obj[1024];
+ GLsizei count = 0;
+ glGetAttachedShaders(mProgramObject, 1024, &count, obj);
for (GLsizei i = 0; i < count; i++)
{
- glDetachObjectARB(mProgramObject, obj[i]);
- glDeleteObjectARB(obj[i]);
+ glDetachShader(mProgramObject, obj[i]);
}
- glDeleteObjectARB(mProgramObject);
+ for (GLsizei i = 0; i < count; i++)
+ {
+ if (glIsShader(obj[i]))
+ {
+ glDeleteShader(obj[i]);
+ }
+ }
+
+ glDeleteProgram(mProgramObject);
mProgramObject = 0;
}
if (mTimerQuery)
{
- glDeleteQueriesARB(1, &mTimerQuery);
+ glDeleteQueries(1, &mTimerQuery);
mTimerQuery = 0;
}
if (mSamplesQuery)
{
- glDeleteQueriesARB(1, &mSamplesQuery);
+ glDeleteQueries(1, &mSamplesQuery);
mSamplesQuery = 0;
}
@@ -380,10 +375,10 @@ void LLGLSLShader::unloadInternal()
stop_glerror();
}
-BOOL LLGLSLShader::createShader(std::vector<LLStaticHashedString> * attributes,
- std::vector<LLStaticHashedString> * uniforms,
- U32 varying_count,
- const char** varyings)
+BOOL LLGLSLShader::createShader(std::vector<LLStaticHashedString>* attributes,
+ std::vector<LLStaticHashedString>* uniforms,
+ U32 varying_count,
+ const char** varyings)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
@@ -401,7 +396,7 @@ BOOL LLGLSLShader::createShader(std::vector<LLStaticHashedString> * attributes,
llassert_always(!mShaderFiles.empty());
// Create program
- mProgramObject = glCreateProgramObjectARB();
+ mProgramObject = glCreateProgram();
if (mProgramObject == 0)
{
// Shouldn't happen if shader related extensions, like ARB_vertex_shader, exist.
@@ -411,21 +406,21 @@ BOOL LLGLSLShader::createShader(std::vector<LLStaticHashedString> * attributes,
}
BOOL success = TRUE;
-
+
#if LL_DARWIN
// work-around missing mix(vec3,vec3,bvec3)
mDefines["OLD_SELECT"] = "1";
#endif
-
+
#if DEBUG_SHADER_INCLUDES
fprintf(stderr, "--- %s ---\n", mName.c_str());
#endif // DEBUG_SHADER_INCLUDES
//compile new source
- vector< pair<string,GLenum> >::iterator fileIter = mShaderFiles.begin();
- for ( ; fileIter != mShaderFiles.end(); fileIter++ )
+ vector< pair<string, GLenum> >::iterator fileIter = mShaderFiles.begin();
+ for (; fileIter != mShaderFiles.end(); fileIter++)
{
- GLhandleARB shaderhandle = LLShaderMgr::instance()->loadShaderFile((*fileIter).first, mShaderLevel, (*fileIter).second, &mDefines, mFeatures.mIndexedTextureChannels);
+ GLuint shaderhandle = LLShaderMgr::instance()->loadShaderFile((*fileIter).first, mShaderLevel, (*fileIter).second, &mDefines, mFeatures.mIndexedTextureChannels);
LL_DEBUGS("ShaderLoading") << "SHADER FILE: " << (*fileIter).first << " mShaderLevel=" << mShaderLevel << LL_ENDL;
if (shaderhandle)
{
@@ -452,7 +447,7 @@ BOOL LLGLSLShader::createShader(std::vector<LLStaticHashedString> * attributes,
#ifdef GL_INTERLEAVED_ATTRIBS
if (varying_count > 0 && varyings)
{
- glTransformFeedbackVaryings(mProgramObject, varying_count, varyings, GL_INTERLEAVED_ATTRIBS);
+ glTransformFeedbackVaryings((GLuint64)mProgramObject, varying_count, varyings, GL_INTERLEAVED_ATTRIBS);
}
#endif
@@ -465,7 +460,7 @@ BOOL LLGLSLShader::createShader(std::vector<LLStaticHashedString> * attributes,
{
success = mapUniforms(uniforms);
}
- if( !success )
+ if (!success)
{
LL_SHADER_LOADING_WARNS() << "Failed to link shader: " << mName << LL_ENDL;
@@ -474,7 +469,7 @@ BOOL LLGLSLShader::createShader(std::vector<LLStaticHashedString> * attributes,
{
LL_SHADER_LOADING_WARNS() << "Failed to link using shader level " << mShaderLevel << " trying again using shader level " << (mShaderLevel - 1) << LL_ENDL;
mShaderLevel--;
- return createShader(attributes,uniforms);
+ return createShader(attributes, uniforms);
}
}
else if (mFeatures.mIndexedTextureChannels > 0)
@@ -501,26 +496,30 @@ BOOL LLGLSLShader::createShader(std::vector<LLStaticHashedString> * attributes,
unbind();
}
+#ifdef LL_PROFILER_ENABLE_RENDER_DOC
+ setLabel(mName.c_str());
+#endif
+
return success;
}
#if DEBUG_SHADER_INCLUDES
-void dumpAttachObject( const char *func_name, GLhandleARB program_object, const std::string &object_path )
+void dumpAttachObject(const char* func_name, GLuint program_object, const std::string& object_path)
{
- GLcharARB* info_log;
+ GLchar* info_log;
GLint info_len_expect = 0;
GLint info_len_actual = 0;
- glGetObjectParameterivARB(program_object, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_len_expect);
+ glGetShaderiv(program_object, GL_INFO_LOG_LENGTH, , &info_len_expect);
fprintf(stderr, " * %-20s(), log size: %d, %s\n", func_name, info_len_expect, object_path.c_str());
if (info_len_expect > 0)
{
fprintf(stderr, " ========== %s() ========== \n", func_name);
- info_log = new GLcharARB [ info_len_expect ];
- glGetInfoLogARB(program_object, info_len_expect, &info_len_actual, info_log);
- fprintf(stderr, "%s\n", info_log);
- delete [] info_log;
+ info_log = new GLchar[info_len_expect];
+ glGetProgramInfoLog(program_object, info_len_expect, &info_len_actual, info_log);
+ fprintf(stderr, "%s\n", info_log);
+ delete[] info_log;
}
}
#endif // DEBUG_SHADER_INCLUDES
@@ -530,7 +529,7 @@ BOOL LLGLSLShader::attachVertexObject(std::string object_path)
if (LLShaderMgr::instance()->mVertexShaderObjects.count(object_path) > 0)
{
stop_glerror();
- glAttachObjectARB(mProgramObject, LLShaderMgr::instance()->mVertexShaderObjects[object_path]);
+ glAttachShader(mProgramObject, LLShaderMgr::instance()->mVertexShaderObjects[object_path]);
#if DEBUG_SHADER_INCLUDES
dumpAttachObject("attachVertexObject", mProgramObject, object_path);
#endif // DEBUG_SHADER_INCLUDES
@@ -549,7 +548,7 @@ BOOL LLGLSLShader::attachFragmentObject(std::string object_path)
if (LLShaderMgr::instance()->mFragmentShaderObjects.count(object_path) > 0)
{
stop_glerror();
- glAttachObjectARB(mProgramObject, LLShaderMgr::instance()->mFragmentShaderObjects[object_path]);
+ glAttachShader(mProgramObject, LLShaderMgr::instance()->mFragmentShaderObjects[object_path]);
#if DEBUG_SHADER_INCLUDES
dumpAttachObject("attachFragmentObject", mProgramObject, object_path);
#endif // DEBUG_SHADER_INCLUDES
@@ -563,12 +562,12 @@ BOOL LLGLSLShader::attachFragmentObject(std::string object_path)
}
}
-void LLGLSLShader::attachObject(GLhandleARB object)
+void LLGLSLShader::attachObject(GLuint object)
{
if (object != 0)
{
stop_glerror();
- glAttachObjectARB(mProgramObject, object);
+ glAttachShader(mProgramObject, object);
#if DEBUG_SHADER_INCLUDES
std::string object_path("???");
dumpAttachObject("attachObject", mProgramObject, object_path);
@@ -581,7 +580,7 @@ void LLGLSLShader::attachObject(GLhandleARB object)
}
}
-void LLGLSLShader::attachObjects(GLhandleARB* objects, S32 count)
+void LLGLSLShader::attachObjects(GLuint* objects, S32 count)
{
for (S32 i = 0; i < count; i++)
{
@@ -589,7 +588,7 @@ void LLGLSLShader::attachObjects(GLhandleARB* objects, S32 count)
}
}
-BOOL LLGLSLShader::mapAttributes(const std::vector<LLStaticHashedString> * attributes)
+BOOL LLGLSLShader::mapAttributes(const std::vector<LLStaticHashedString>* attributes)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
@@ -597,9 +596,9 @@ BOOL LLGLSLShader::mapAttributes(const std::vector<LLStaticHashedString> * attri
for (U32 i = 0; i < LLShaderMgr::instance()->mReservedAttribs.size(); i++)
{
const char* name = LLShaderMgr::instance()->mReservedAttribs[i].c_str();
- glBindAttribLocationARB(mProgramObject, i, (const GLcharARB *) name);
+ glBindAttribLocation(mProgramObject, i, (const GLchar*)name);
}
-
+
//link the program
BOOL res = link();
@@ -610,7 +609,7 @@ BOOL LLGLSLShader::mapAttributes(const std::vector<LLStaticHashedString> * attri
#else
mAttribute.resize(LLShaderMgr::instance()->mReservedAttribs.size() + numAttributes, -1);
#endif
-
+
if (res)
{ //read back channel locations
@@ -620,7 +619,7 @@ BOOL LLGLSLShader::mapAttributes(const std::vector<LLStaticHashedString> * attri
for (U32 i = 0; i < LLShaderMgr::instance()->mReservedAttribs.size(); i++)
{
const char* name = LLShaderMgr::instance()->mReservedAttribs[i].c_str();
- S32 index = glGetAttribLocationARB(mProgramObject, (const GLcharARB *)name);
+ S32 index = glGetAttribLocation(mProgramObject, (const GLchar*)name);
if (index != -1)
{
#if LL_RELEASE_WITH_DEBUG_INFO
@@ -637,7 +636,7 @@ BOOL LLGLSLShader::mapAttributes(const std::vector<LLStaticHashedString> * attri
for (U32 i = 0; i < numAttributes; i++)
{
const char* name = (*attributes)[i].String().c_str();
- S32 index = glGetAttribLocationARB(mProgramObject, name);
+ S32 index = glGetAttribLocation(mProgramObject, name);
if (index != -1)
{
mAttribute[LLShaderMgr::instance()->mReservedAttribs.size() + i] = index;
@@ -648,11 +647,11 @@ BOOL LLGLSLShader::mapAttributes(const std::vector<LLStaticHashedString> * attri
return TRUE;
}
-
+
return FALSE;
}
-void LLGLSLShader::mapUniform(GLint index, const vector<LLStaticHashedString> * uniforms)
+void LLGLSLShader::mapUniform(GLint index, const vector<LLStaticHashedString>* uniforms)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
@@ -668,52 +667,50 @@ void LLGLSLShader::mapUniform(GLint index, const vector<LLStaticHashedString> *
name[0] = 0;
- glGetActiveUniformARB(mProgramObject, index, 1024, &length, &size, &type, (GLcharARB *)name);
-#if !LL_DARWIN
+ glGetActiveUniform(mProgramObject, index, 1024, &length, &size, &type, (GLchar*)name);
if (size > 0)
{
- switch(type)
- {
- case GL_FLOAT_VEC2: size *= 2; break;
- case GL_FLOAT_VEC3: size *= 3; break;
- case GL_FLOAT_VEC4: size *= 4; break;
- case GL_DOUBLE: size *= 2; break;
- case GL_DOUBLE_VEC2: size *= 2; break;
- case GL_DOUBLE_VEC3: size *= 6; break;
- case GL_DOUBLE_VEC4: size *= 8; break;
- case GL_INT_VEC2: size *= 2; break;
- case GL_INT_VEC3: size *= 3; break;
- case GL_INT_VEC4: size *= 4; break;
- case GL_UNSIGNED_INT_VEC2: size *= 2; break;
- case GL_UNSIGNED_INT_VEC3: size *= 3; break;
- case GL_UNSIGNED_INT_VEC4: size *= 4; break;
- case GL_BOOL_VEC2: size *= 2; break;
- case GL_BOOL_VEC3: size *= 3; break;
- case GL_BOOL_VEC4: size *= 4; break;
- case GL_FLOAT_MAT2: size *= 4; break;
- case GL_FLOAT_MAT3: size *= 9; break;
- case GL_FLOAT_MAT4: size *= 16; break;
- case GL_FLOAT_MAT2x3: size *= 6; break;
- case GL_FLOAT_MAT2x4: size *= 8; break;
- case GL_FLOAT_MAT3x2: size *= 6; break;
- case GL_FLOAT_MAT3x4: size *= 12; break;
- case GL_FLOAT_MAT4x2: size *= 8; break;
- case GL_FLOAT_MAT4x3: size *= 12; break;
- case GL_DOUBLE_MAT2: size *= 8; break;
- case GL_DOUBLE_MAT3: size *= 18; break;
- case GL_DOUBLE_MAT4: size *= 32; break;
- case GL_DOUBLE_MAT2x3: size *= 12; break;
- case GL_DOUBLE_MAT2x4: size *= 16; break;
- case GL_DOUBLE_MAT3x2: size *= 12; break;
- case GL_DOUBLE_MAT3x4: size *= 24; break;
- case GL_DOUBLE_MAT4x2: size *= 16; break;
- case GL_DOUBLE_MAT4x3: size *= 24; break;
+ switch (type)
+ {
+ case GL_FLOAT_VEC2: size *= 2; break;
+ case GL_FLOAT_VEC3: size *= 3; break;
+ case GL_FLOAT_VEC4: size *= 4; break;
+ case GL_DOUBLE: size *= 2; break;
+ case GL_DOUBLE_VEC2: size *= 2; break;
+ case GL_DOUBLE_VEC3: size *= 6; break;
+ case GL_DOUBLE_VEC4: size *= 8; break;
+ case GL_INT_VEC2: size *= 2; break;
+ case GL_INT_VEC3: size *= 3; break;
+ case GL_INT_VEC4: size *= 4; break;
+ case GL_UNSIGNED_INT_VEC2: size *= 2; break;
+ case GL_UNSIGNED_INT_VEC3: size *= 3; break;
+ case GL_UNSIGNED_INT_VEC4: size *= 4; break;
+ case GL_BOOL_VEC2: size *= 2; break;
+ case GL_BOOL_VEC3: size *= 3; break;
+ case GL_BOOL_VEC4: size *= 4; break;
+ case GL_FLOAT_MAT2: size *= 4; break;
+ case GL_FLOAT_MAT3: size *= 9; break;
+ case GL_FLOAT_MAT4: size *= 16; break;
+ case GL_FLOAT_MAT2x3: size *= 6; break;
+ case GL_FLOAT_MAT2x4: size *= 8; break;
+ case GL_FLOAT_MAT3x2: size *= 6; break;
+ case GL_FLOAT_MAT3x4: size *= 12; break;
+ case GL_FLOAT_MAT4x2: size *= 8; break;
+ case GL_FLOAT_MAT4x3: size *= 12; break;
+ case GL_DOUBLE_MAT2: size *= 8; break;
+ case GL_DOUBLE_MAT3: size *= 18; break;
+ case GL_DOUBLE_MAT4: size *= 32; break;
+ case GL_DOUBLE_MAT2x3: size *= 12; break;
+ case GL_DOUBLE_MAT2x4: size *= 16; break;
+ case GL_DOUBLE_MAT3x2: size *= 12; break;
+ case GL_DOUBLE_MAT3x4: size *= 24; break;
+ case GL_DOUBLE_MAT4x2: size *= 16; break;
+ case GL_DOUBLE_MAT4x3: size *= 24; break;
}
mTotalUniformSize += size;
}
-#endif
- S32 location = glGetUniformLocationARB(mProgramObject, name);
+ S32 location = glGetUniformLocation(mProgramObject, name);
if (location != -1)
{
//chop off "[0]" so we can always access the first element
@@ -729,16 +726,16 @@ void LLGLSLShader::mapUniform(GLint index, const vector<LLStaticHashedString> *
mUniformMap[hashedName] = location;
LL_DEBUGS("ShaderUniform") << "Uniform " << name << " is at location " << location << LL_ENDL;
-
+
//find the index of this uniform
- for (S32 i = 0; i < (S32) LLShaderMgr::instance()->mReservedUniforms.size(); i++)
+ for (S32 i = 0; i < (S32)LLShaderMgr::instance()->mReservedUniforms.size(); i++)
{
- if ( (mUniform[i] == -1)
+ if ((mUniform[i] == -1)
&& (LLShaderMgr::instance()->mReservedUniforms[i] == name))
{
//found it
mUniform[i] = location;
- mTexture[i] = mapUniformTextureChannel(location, type);
+ mTexture[i] = mapUniformTextureChannel(location, type, size);
return;
}
}
@@ -747,12 +744,12 @@ void LLGLSLShader::mapUniform(GLint index, const vector<LLStaticHashedString> *
{
for (U32 i = 0; i < uniforms->size(); i++)
{
- if ( (mUniform[i+LLShaderMgr::instance()->mReservedUniforms.size()] == -1)
+ if ((mUniform[i + LLShaderMgr::instance()->mReservedUniforms.size()] == -1)
&& ((*uniforms)[i].String() == name))
{
//found it
- mUniform[i+LLShaderMgr::instance()->mReservedUniforms.size()] = location;
- mTexture[i+LLShaderMgr::instance()->mReservedUniforms.size()] = mapUniformTextureChannel(location, type);
+ mUniform[i + LLShaderMgr::instance()->mReservedUniforms.size()] = location;
+ mTexture[i + LLShaderMgr::instance()->mReservedUniforms.size()] = mapUniformTextureChannel(location, type, size);
return;
}
}
@@ -770,167 +767,221 @@ void LLGLSLShader::addPermutation(std::string name, std::string value)
mDefines[name] = value;
}
+void LLGLSLShader::addConstant(const LLGLSLShader::eShaderConsts shader_const)
+{
+ addPermutation(gShaderConstsKey[shader_const], gShaderConstsVal[shader_const]);
+}
+
void LLGLSLShader::removePermutation(std::string name)
{
mDefines[name].erase();
}
-GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type)
+GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type, GLint size)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
- if ((type >= GL_SAMPLER_1D_ARB && type <= GL_SAMPLER_2D_RECT_SHADOW_ARB) ||
- type == GL_SAMPLER_2D_MULTISAMPLE)
+ if ((type >= GL_SAMPLER_1D && type <= GL_SAMPLER_2D_RECT_SHADOW) ||
+ type == GL_SAMPLER_2D_MULTISAMPLE ||
+ type == GL_SAMPLER_CUBE_MAP_ARRAY)
{ //this here is a texture
- glUniform1iARB(location, mActiveTextureChannels);
- LL_DEBUGS("ShaderUniform") << "Assigned to texture channel " << mActiveTextureChannels << LL_ENDL;
- return mActiveTextureChannels++;
+ GLint ret = mActiveTextureChannels;
+ if (size == 1)
+ {
+ glUniform1i(location, mActiveTextureChannels);
+ LL_DEBUGS("ShaderUniform") << "Assigned to texture channel " << mActiveTextureChannels << LL_ENDL;
+ mActiveTextureChannels++;
+ }
+ else
+ {
+ //is array of textures, make sequential after this texture
+ GLint channel[32]; // <=== only support up to 32 texture channels
+ llassert(size <= 32);
+ size = llmin(size, 32);
+ for (int i = 0; i < size; ++i)
+ {
+ channel[i] = mActiveTextureChannels++;
+ }
+ glUniform1iv(location, size, channel);
+ LL_DEBUGS("ShaderUniform") << "Assigned to texture channel " <<
+ (mActiveTextureChannels - size) << " through " << (mActiveTextureChannels - 1) << LL_ENDL;
+ }
+
+ llassert(mActiveTextureChannels <= 32); // too many textures (probably)
+ return ret;
}
return -1;
}
-BOOL LLGLSLShader::mapUniforms(const vector<LLStaticHashedString> * uniforms)
+BOOL LLGLSLShader::mapUniforms(const vector<LLStaticHashedString>* uniforms)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
BOOL res = TRUE;
- mTotalUniformSize = 0;
- mActiveTextureChannels = 0;
- mUniform.clear();
- mUniformMap.clear();
- mUniformNameMap.clear();
- mTexture.clear();
- mValue.clear();
- //initialize arrays
- U32 numUniforms = (uniforms == NULL) ? 0 : uniforms->size();
- mUniform.resize(numUniforms + LLShaderMgr::instance()->mReservedUniforms.size(), -1);
- mTexture.resize(numUniforms + LLShaderMgr::instance()->mReservedUniforms.size(), -1);
-
- bind();
-
- //get the number of active uniforms
- GLint activeCount;
- glGetObjectParameterivARB(mProgramObject, GL_OBJECT_ACTIVE_UNIFORMS_ARB, &activeCount);
-
- //........................................................................................................................................
- //........................................................................................
-
- /*
- EXPLANATION:
- This is part of code is temporary because as the final result the mapUniform() should be rewrited.
- But it's a huge a volume of work which is need to be a more carefully performed for avoid possible
- regression's (i.e. it should be formalized a separate ticket in JIRA).
-
- RESON:
- The reason of this code is that SL engine is very sensitive to fact that "diffuseMap" should be appear
- first as uniform parameter which is should get 0-"texture channel" index (see mapUniformTextureChannel() and mActiveTextureChannels)
- it influence to which is texture matrix will be updated during rendering.
-
- But, order of indexe's of uniform variables is not defined and GLSL compiler can change it as want
- , even if the "diffuseMap" will be appear and use first in shader code.
-
- As example where this situation appear see: "Deferred Material Shader 28/29/30/31"
- And tickets: MAINT-4165, MAINT-4839, MAINT-3568, MAINT-6437
- */
-
-
- S32 diffuseMap = glGetUniformLocationARB(mProgramObject, "diffuseMap");
- S32 specularMap = glGetUniformLocationARB(mProgramObject, "specularMap");
- S32 bumpMap = glGetUniformLocationARB(mProgramObject, "bumpMap");
- S32 altDiffuseMap = glGetUniformLocationARB(mProgramObject, "altDiffuseMap");
- S32 environmentMap = glGetUniformLocationARB(mProgramObject, "environmentMap");
-
- std::set<S32> skip_index;
-
- if (-1 != diffuseMap && (-1 != specularMap || -1 != bumpMap || -1 != environmentMap || -1 != altDiffuseMap))
- {
- GLenum type;
- GLsizei length;
- GLint size = -1;
- char name[1024];
-
- diffuseMap = altDiffuseMap = specularMap = bumpMap = environmentMap = -1;
-
- for (S32 i = 0; i < activeCount; i++)
- {
- name[0] = '\0';
-
- glGetActiveUniformARB(mProgramObject, i, 1024, &length, &size, &type, (GLcharARB *)name);
-
- if (-1 == diffuseMap && std::string(name) == "diffuseMap")
- {
- diffuseMap = i;
- continue;
- }
-
- if (-1 == specularMap && std::string(name) == "specularMap")
- {
- specularMap = i;
- continue;
- }
-
- if (-1 == bumpMap && std::string(name) == "bumpMap")
- {
- bumpMap = i;
- continue;
- }
-
- if (-1 == environmentMap && std::string(name) == "environmentMap")
- {
- environmentMap = i;
- continue;
- }
+ mTotalUniformSize = 0;
+ mActiveTextureChannels = 0;
+ mUniform.clear();
+ mUniformMap.clear();
+ mUniformNameMap.clear();
+ mTexture.clear();
+ mValue.clear();
+ //initialize arrays
+ U32 numUniforms = (uniforms == NULL) ? 0 : uniforms->size();
+ mUniform.resize(numUniforms + LLShaderMgr::instance()->mReservedUniforms.size(), -1);
+ mTexture.resize(numUniforms + LLShaderMgr::instance()->mReservedUniforms.size(), -1);
+
+ bind();
+
+ //get the number of active uniforms
+ GLint activeCount;
+ glGetProgramiv(mProgramObject, GL_ACTIVE_UNIFORMS, &activeCount);
+
+ //........................................................................................................................................
+ //........................................................................................
+
+ /*
+ EXPLANATION:
+ This is part of code is temporary because as the final result the mapUniform() should be rewrited.
+ But it's a huge a volume of work which is need to be a more carefully performed for avoid possible
+ regression's (i.e. it should be formalized a separate ticket in JIRA).
+
+ RESON:
+ The reason of this code is that SL engine is very sensitive to fact that "diffuseMap" should be appear
+ first as uniform parameter which is should get 0-"texture channel" index (see mapUniformTextureChannel() and mActiveTextureChannels)
+ it influence to which is texture matrix will be updated during rendering.
+
+ But, order of indexe's of uniform variables is not defined and GLSL compiler can change it as want
+ , even if the "diffuseMap" will be appear and use first in shader code.
+
+ As example where this situation appear see: "Deferred Material Shader 28/29/30/31"
+ And tickets: MAINT-4165, MAINT-4839, MAINT-3568, MAINT-6437
+
+ --- davep TODO -- pretty sure the entire block here is superstitious and that the uniform index has nothing to do with the texture channel
+ texture channel should follow the uniform VALUE
+ */
+
+
+ S32 diffuseMap = glGetUniformLocation(mProgramObject, "diffuseMap");
+ S32 specularMap = glGetUniformLocation(mProgramObject, "specularMap");
+ S32 bumpMap = glGetUniformLocation(mProgramObject, "bumpMap");
+ S32 altDiffuseMap = glGetUniformLocation(mProgramObject, "altDiffuseMap");
+ S32 environmentMap = glGetUniformLocation(mProgramObject, "environmentMap");
+ S32 reflectionMap = glGetUniformLocation(mProgramObject, "reflectionMap");
+
+ std::set<S32> skip_index;
+
+ if (-1 != diffuseMap && (-1 != specularMap || -1 != bumpMap || -1 != environmentMap || -1 != altDiffuseMap))
+ {
+ GLenum type;
+ GLsizei length;
+ GLint size = -1;
+ char name[1024];
+
+ diffuseMap = altDiffuseMap = specularMap = bumpMap = environmentMap = -1;
+
+ for (S32 i = 0; i < activeCount; i++)
+ {
+ name[0] = '\0';
+
+ glGetActiveUniform(mProgramObject, i, 1024, &length, &size, &type, (GLchar*)name);
+
+ if (-1 == diffuseMap && std::string(name) == "diffuseMap")
+ {
+ diffuseMap = i;
+ continue;
+ }
+
+ if (-1 == specularMap && std::string(name) == "specularMap")
+ {
+ specularMap = i;
+ continue;
+ }
+
+ if (-1 == bumpMap && std::string(name) == "bumpMap")
+ {
+ bumpMap = i;
+ continue;
+ }
+
+ if (-1 == environmentMap && std::string(name) == "environmentMap")
+ {
+ environmentMap = i;
+ continue;
+ }
+
+ if (-1 == reflectionMap && std::string(name) == "reflectionMap")
+ {
+ reflectionMap = i;
+ continue;
+ }
if (-1 == altDiffuseMap && std::string(name) == "altDiffuseMap")
- {
- altDiffuseMap = i;
- continue;
- }
- }
+ {
+ altDiffuseMap = i;
+ continue;
+ }
+ }
- bool specularDiff = specularMap < diffuseMap && -1 != specularMap;
- bool bumpLessDiff = bumpMap < diffuseMap && -1 != bumpMap;
- bool envLessDiff = environmentMap < diffuseMap && -1 != environmentMap;
+ bool specularDiff = specularMap < diffuseMap && -1 != specularMap;
+ bool bumpLessDiff = bumpMap < diffuseMap && -1 != bumpMap;
+ bool envLessDiff = environmentMap < diffuseMap && -1 != environmentMap;
+ bool refLessDiff = reflectionMap < diffuseMap && -1 != reflectionMap;
- if (specularDiff || bumpLessDiff || envLessDiff)
- {
- mapUniform(diffuseMap, uniforms);
- skip_index.insert(diffuseMap);
+ if (specularDiff || bumpLessDiff || envLessDiff || refLessDiff)
+ {
+ mapUniform(diffuseMap, uniforms);
+ skip_index.insert(diffuseMap);
- if (-1 != specularMap) {
- mapUniform(specularMap, uniforms);
- skip_index.insert(specularMap);
- }
+ if (-1 != specularMap) {
+ mapUniform(specularMap, uniforms);
+ skip_index.insert(specularMap);
+ }
- if (-1 != bumpMap) {
- mapUniform(bumpMap, uniforms);
- skip_index.insert(bumpMap);
- }
+ if (-1 != bumpMap) {
+ mapUniform(bumpMap, uniforms);
+ skip_index.insert(bumpMap);
+ }
- if (-1 != environmentMap) {
- mapUniform(environmentMap, uniforms);
- skip_index.insert(environmentMap);
- }
- }
- }
+ if (-1 != environmentMap) {
+ mapUniform(environmentMap, uniforms);
+ skip_index.insert(environmentMap);
+ }
- //........................................................................................
+ if (-1 != reflectionMap) {
+ mapUniform(reflectionMap, uniforms);
+ skip_index.insert(reflectionMap);
+ }
+ }
+ }
- for (S32 i = 0; i < activeCount; i++)
- {
- //........................................................................................
- if (skip_index.end() != skip_index.find(i)) continue;
- //........................................................................................
+ //........................................................................................
- mapUniform(i, uniforms);
- }
- //........................................................................................................................................
+ for (S32 i = 0; i < activeCount; i++)
+ {
+ //........................................................................................
+ if (skip_index.end() != skip_index.find(i)) continue;
+ //........................................................................................
- unbind();
+ mapUniform(i, uniforms);
+ }
+ //........................................................................................................................................
- LL_DEBUGS("ShaderUniform") << "Total Uniform Size: " << mTotalUniformSize << LL_ENDL;
- return res;
+ if (mFeatures.hasReflectionProbes) // Set up block binding, in a way supported by Apple (rather than binding = 1 in .glsl).
+ { // See slide 35 and more of https://docs.huihoo.com/apple/wwdc/2011/session_420__advances_in_opengl_for_mac_os_x_lion.pdf
+ static const GLuint BLOCKBINDING = 1; //picked by us
+ //Get the index, similar to a uniform location
+ GLuint UBOBlockIndex = glGetUniformBlockIndex(mProgramObject, "ReflectionProbes");
+ if (UBOBlockIndex != GL_INVALID_INDEX)
+ {
+ //Set this index to a binding index
+ glUniformBlockBinding(mProgramObject, UBOBlockIndex, BLOCKBINDING);
+ }
+ }
+ unbind();
+
+ LL_DEBUGS("ShaderUniform") << "Total Uniform Size: " << mTotalUniformSize << LL_ENDL;
+ return res;
}
@@ -952,14 +1003,22 @@ void LLGLSLShader::bind()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ llassert(mProgramObject != 0);
+
gGL.flush();
if (sCurBoundShader != mProgramObject) // Don't re-bind current shader
{
+ if (sCurBoundShaderPtr)
+ {
+ sCurBoundShaderPtr->readProfileQuery();
+ }
LLVertexBuffer::unbind();
- glUseProgramObjectARB(mProgramObject);
+ glUseProgram(mProgramObject);
sCurBoundShader = mProgramObject;
sCurBoundShaderPtr = this;
+ placeProfileQuery();
+ LLVertexBuffer::setupClientArrays(mAttributeMask);
}
if (mUniformsDirty)
@@ -982,40 +1041,33 @@ void LLGLSLShader::bind(bool rigged)
}
}
-void LLGLSLShader::unbind()
+void LLGLSLShader::unbind(void)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
-
gGL.flush();
- stop_glerror();
LLVertexBuffer::unbind();
- glUseProgramObjectARB(0);
- sCurBoundShader = 0;
- sCurBoundShaderPtr = NULL;
- stop_glerror();
-}
-void LLGLSLShader::bindNoShader(void)
-{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ if (sCurBoundShaderPtr)
+ {
+ sCurBoundShaderPtr->readProfileQuery();
+ }
- LLVertexBuffer::unbind();
- glUseProgramObjectARB(0);
+ glUseProgram(0);
sCurBoundShader = 0;
sCurBoundShaderPtr = NULL;
}
-S32 LLGLSLShader::bindTexture(const std::string &uniform, LLTexture *texture, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace colorspace)
+S32 LLGLSLShader::bindTexture(const std::string& uniform, LLTexture* texture, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace colorspace)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
S32 channel = 0;
channel = getUniformLocation(uniform);
-
+
return bindTexture(channel, texture, mode, colorspace);
}
-S32 LLGLSLShader::bindTexture(S32 uniform, LLTexture *texture, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace colorspace)
+S32 LLGLSLShader::bindTexture(S32 uniform, LLTexture* texture, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace colorspace)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
@@ -1024,25 +1076,25 @@ S32 LLGLSLShader::bindTexture(S32 uniform, LLTexture *texture, LLTexUnit::eTextu
LL_SHADER_UNIFORM_ERRS() << "Uniform out of range: " << uniform << LL_ENDL;
return -1;
}
-
+
uniform = mTexture[uniform];
-
+
if (uniform > -1)
{
gGL.getTexUnit(uniform)->bindFast(texture);
gGL.getTexUnit(uniform)->setTextureColorSpace(colorspace);
}
-
+
return uniform;
}
-S32 LLGLSLShader::unbindTexture(const std::string &uniform, LLTexUnit::eTextureType mode)
+S32 LLGLSLShader::unbindTexture(const std::string& uniform, LLTexUnit::eTextureType mode)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
S32 channel = 0;
channel = getUniformLocation(uniform);
-
+
return unbindTexture(channel);
}
@@ -1055,17 +1107,22 @@ S32 LLGLSLShader::unbindTexture(S32 uniform, LLTexUnit::eTextureType mode)
LL_SHADER_UNIFORM_ERRS() << "Uniform out of range: " << uniform << LL_ENDL;
return -1;
}
-
+
uniform = mTexture[uniform];
-
+
if (uniform > -1)
{
gGL.getTexUnit(uniform)->unbindFast(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;
@@ -1116,9 +1173,10 @@ S32 LLGLSLShader::disableTexture(S32 uniform, LLTexUnit::eTextureType mode, LLTe
void LLGLSLShader::uniform1i(U32 index, GLint x)
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ llassert(sCurBoundShaderPtr == this);
if (mProgramObject)
- {
+ {
if (mUniform.size() <= index)
{
LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
@@ -1130,8 +1188,8 @@ void LLGLSLShader::uniform1i(U32 index, GLint x)
const auto& iter = mValue.find(mUniform[index]);
if (iter == mValue.end() || iter->second.mV[0] != x)
{
- glUniform1iARB(mUniform[index], x);
- mValue[mUniform[index]] = LLVector4(x,0.f,0.f,0.f);
+ glUniform1i(mUniform[index], x);
+ mValue[mUniform[index]] = LLVector4(x, 0.f, 0.f, 0.f);
}
}
}
@@ -1139,9 +1197,11 @@ void LLGLSLShader::uniform1i(U32 index, GLint x)
void LLGLSLShader::uniform1f(U32 index, GLfloat x)
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ llassert(sCurBoundShaderPtr == this);
+
if (mProgramObject)
- {
+ {
if (mUniform.size() <= index)
{
LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
@@ -1153,17 +1213,30 @@ void LLGLSLShader::uniform1f(U32 index, GLfloat x)
const auto& iter = mValue.find(mUniform[index]);
if (iter == mValue.end() || iter->second.mV[0] != x)
{
- glUniform1fARB(mUniform[index], x);
- mValue[mUniform[index]] = LLVector4(x,0.f,0.f,0.f);
+ glUniform1f(mUniform[index], x);
+ mValue[mUniform[index]] = LLVector4(x, 0.f, 0.f, 0.f);
}
}
}
}
+void LLGLSLShader::fastUniform1f(U32 index, GLfloat x)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ llassert(sCurBoundShaderPtr == this);
+ llassert(mProgramObject);
+ llassert(mUniform.size() <= index);
+ llassert(mUniform[index] >= 0);
+ glUniform1f(mUniform[index], x);
+}
+
void LLGLSLShader::uniform2f(U32 index, GLfloat x, GLfloat y)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ llassert(sCurBoundShaderPtr == this);
+
if (mProgramObject)
- {
+ {
if (mUniform.size() <= index)
{
LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
@@ -1173,10 +1246,10 @@ void LLGLSLShader::uniform2f(U32 index, GLfloat x, GLfloat y)
if (mUniform[index] >= 0)
{
const auto& iter = mValue.find(mUniform[index]);
- LLVector4 vec(x,y,0.f,0.f);
- if (iter == mValue.end() || shouldChange(iter->second,vec))
+ LLVector4 vec(x, y, 0.f, 0.f);
+ if (iter == mValue.end() || shouldChange(iter->second, vec))
{
- glUniform2fARB(mUniform[index], x, y);
+ glUniform2f(mUniform[index], x, y);
mValue[mUniform[index]] = vec;
}
}
@@ -1185,8 +1258,11 @@ void LLGLSLShader::uniform2f(U32 index, GLfloat x, GLfloat y)
void LLGLSLShader::uniform3f(U32 index, GLfloat x, GLfloat y, GLfloat z)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ llassert(sCurBoundShaderPtr == this);
+
if (mProgramObject)
- {
+ {
if (mUniform.size() <= index)
{
LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
@@ -1196,10 +1272,10 @@ void LLGLSLShader::uniform3f(U32 index, GLfloat x, GLfloat y, GLfloat z)
if (mUniform[index] >= 0)
{
const auto& iter = mValue.find(mUniform[index]);
- LLVector4 vec(x,y,z,0.f);
- if (iter == mValue.end() || shouldChange(iter->second,vec))
+ LLVector4 vec(x, y, z, 0.f);
+ if (iter == mValue.end() || shouldChange(iter->second, vec))
{
- glUniform3fARB(mUniform[index], x, y, z);
+ glUniform3f(mUniform[index], x, y, z);
mValue[mUniform[index]] = vec;
}
}
@@ -1208,8 +1284,11 @@ void LLGLSLShader::uniform3f(U32 index, GLfloat x, GLfloat y, GLfloat z)
void LLGLSLShader::uniform4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ llassert(sCurBoundShaderPtr == this);
+
if (mProgramObject)
- {
+ {
if (mUniform.size() <= index)
{
LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
@@ -1219,10 +1298,10 @@ void LLGLSLShader::uniform4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat
if (mUniform[index] >= 0)
{
const auto& iter = mValue.find(mUniform[index]);
- LLVector4 vec(x,y,z,w);
- if (iter == mValue.end() || shouldChange(iter->second,vec))
+ LLVector4 vec(x, y, z, w);
+ if (iter == mValue.end() || shouldChange(iter->second, vec))
{
- glUniform4fARB(mUniform[index], x, y, z, w);
+ glUniform4f(mUniform[index], x, y, z, w);
mValue[mUniform[index]] = vec;
}
}
@@ -1231,8 +1310,37 @@ void LLGLSLShader::uniform4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat
void LLGLSLShader::uniform1iv(U32 index, U32 count, const GLint* v)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ llassert(sCurBoundShaderPtr == this);
+
+ if (mProgramObject)
+ {
+ if (mUniform.size() <= index)
+ {
+ LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
+ return;
+ }
+
+ if (mUniform[index] >= 0)
+ {
+ const auto& iter = mValue.find(mUniform[index]);
+ LLVector4 vec(v[0], 0.f, 0.f, 0.f);
+ if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1)
+ {
+ glUniform1iv(mUniform[index], count, v);
+ mValue[mUniform[index]] = vec;
+ }
+ }
+ }
+}
+
+void LLGLSLShader::uniform4iv(U32 index, U32 count, const GLint* v)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ llassert(sCurBoundShaderPtr == this);
+
if (mProgramObject)
- {
+ {
if (mUniform.size() <= index)
{
LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
@@ -1242,20 +1350,24 @@ void LLGLSLShader::uniform1iv(U32 index, U32 count, const GLint* v)
if (mUniform[index] >= 0)
{
const auto& iter = mValue.find(mUniform[index]);
- LLVector4 vec(v[0],0.f,0.f,0.f);
- if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1)
+ LLVector4 vec(v[0], v[1], v[2], v[3]);
+ if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1)
{
- glUniform1ivARB(mUniform[index], count, v);
+ glUniform1iv(mUniform[index], count, v);
mValue[mUniform[index]] = vec;
}
}
}
}
+
void LLGLSLShader::uniform1fv(U32 index, U32 count, const GLfloat* v)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ llassert(sCurBoundShaderPtr == this);
+
if (mProgramObject)
- {
+ {
if (mUniform.size() <= index)
{
LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
@@ -1265,10 +1377,10 @@ void LLGLSLShader::uniform1fv(U32 index, U32 count, const GLfloat* v)
if (mUniform[index] >= 0)
{
const auto& iter = mValue.find(mUniform[index]);
- LLVector4 vec(v[0],0.f,0.f,0.f);
- if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1)
+ LLVector4 vec(v[0], 0.f, 0.f, 0.f);
+ if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1)
{
- glUniform1fvARB(mUniform[index], count, v);
+ glUniform1fv(mUniform[index], count, v);
mValue[mUniform[index]] = vec;
}
}
@@ -1277,8 +1389,11 @@ void LLGLSLShader::uniform1fv(U32 index, U32 count, const GLfloat* v)
void LLGLSLShader::uniform2fv(U32 index, U32 count, const GLfloat* v)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ llassert(sCurBoundShaderPtr == this);
+
if (mProgramObject)
- {
+ {
if (mUniform.size() <= index)
{
LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
@@ -1288,10 +1403,10 @@ void LLGLSLShader::uniform2fv(U32 index, U32 count, const GLfloat* v)
if (mUniform[index] >= 0)
{
const auto& iter = mValue.find(mUniform[index]);
- LLVector4 vec(v[0],v[1],0.f,0.f);
- if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1)
+ LLVector4 vec(v[0], v[1], 0.f, 0.f);
+ if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1)
{
- glUniform2fvARB(mUniform[index], count, v);
+ glUniform2fv(mUniform[index], count, v);
mValue[mUniform[index]] = vec;
}
}
@@ -1300,8 +1415,11 @@ void LLGLSLShader::uniform2fv(U32 index, U32 count, const GLfloat* v)
void LLGLSLShader::uniform3fv(U32 index, U32 count, const GLfloat* v)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ llassert(sCurBoundShaderPtr == this);
+
if (mProgramObject)
- {
+ {
if (mUniform.size() <= index)
{
LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
@@ -1311,10 +1429,10 @@ void LLGLSLShader::uniform3fv(U32 index, U32 count, const GLfloat* v)
if (mUniform[index] >= 0)
{
const auto& iter = mValue.find(mUniform[index]);
- LLVector4 vec(v[0],v[1],v[2],0.f);
- if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1)
+ LLVector4 vec(v[0], v[1], v[2], 0.f);
+ if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1)
{
- glUniform3fvARB(mUniform[index], count, v);
+ glUniform3fv(mUniform[index], count, v);
mValue[mUniform[index]] = vec;
}
}
@@ -1323,8 +1441,11 @@ void LLGLSLShader::uniform3fv(U32 index, U32 count, const GLfloat* v)
void LLGLSLShader::uniform4fv(U32 index, U32 count, const GLfloat* v)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ llassert(sCurBoundShaderPtr == this);
+
if (mProgramObject)
- {
+ {
if (mUniform.size() <= index)
{
LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
@@ -1334,21 +1455,24 @@ void LLGLSLShader::uniform4fv(U32 index, U32 count, const GLfloat* v)
if (mUniform[index] >= 0)
{
const auto& iter = mValue.find(mUniform[index]);
- LLVector4 vec(v[0],v[1],v[2],v[3]);
- if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1)
+ LLVector4 vec(v[0], v[1], v[2], v[3]);
+ if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
- glUniform4fvARB(mUniform[index], count, v);
+ glUniform4fv(mUniform[index], count, v);
mValue[mUniform[index]] = vec;
}
}
}
}
-void LLGLSLShader::uniformMatrix2fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v)
+void LLGLSLShader::uniformMatrix2fv(U32 index, U32 count, GLboolean transpose, const GLfloat* v)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ llassert(sCurBoundShaderPtr == this);
+
if (mProgramObject)
- {
+ {
if (mUniform.size() <= index)
{
LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
@@ -1357,15 +1481,18 @@ void LLGLSLShader::uniformMatrix2fv(U32 index, U32 count, GLboolean transpose, c
if (mUniform[index] >= 0)
{
- glUniformMatrix2fvARB(mUniform[index], count, transpose, v);
+ glUniformMatrix2fv(mUniform[index], count, transpose, v);
}
}
}
-void LLGLSLShader::uniformMatrix3fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v)
+void LLGLSLShader::uniformMatrix3fv(U32 index, U32 count, GLboolean transpose, const GLfloat* v)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ llassert(sCurBoundShaderPtr == this);
+
if (mProgramObject)
- {
+ {
if (mUniform.size() <= index)
{
LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
@@ -1374,34 +1501,38 @@ void LLGLSLShader::uniformMatrix3fv(U32 index, U32 count, GLboolean transpose, c
if (mUniform[index] >= 0)
{
- glUniformMatrix3fvARB(mUniform[index], count, transpose, v);
+ glUniformMatrix3fv(mUniform[index], count, transpose, v);
}
}
}
-void LLGLSLShader::uniformMatrix3x4fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v)
+void LLGLSLShader::uniformMatrix3x4fv(U32 index, U32 count, GLboolean transpose, const GLfloat* v)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ llassert(sCurBoundShaderPtr == this);
- if (mProgramObject)
- {
- if (mUniform.size() <= index)
- {
- LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
- return;
- }
+ if (mProgramObject)
+ {
+ if (mUniform.size() <= index)
+ {
+ LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
+ return;
+ }
- if (mUniform[index] >= 0)
- {
- glUniformMatrix3x4fv(mUniform[index], count, transpose, v);
- }
- }
+ if (mUniform[index] >= 0)
+ {
+ glUniformMatrix3x4fv(mUniform[index], count, transpose, v);
+ }
+ }
}
-void LLGLSLShader::uniformMatrix4fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v)
+void LLGLSLShader::uniformMatrix4fv(U32 index, U32 count, GLboolean transpose, const GLfloat* v)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ llassert(sCurBoundShaderPtr == this);
+
if (mProgramObject)
- {
+ {
if (mUniform.size() <= index)
{
LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
@@ -1410,7 +1541,7 @@ void LLGLSLShader::uniformMatrix4fv(U32 index, U32 count, GLboolean transpose, c
if (mUniform[index] >= 0)
{
- glUniformMatrix4fvARB(mUniform[index], count, transpose, v);
+ glUniformMatrix4fv(mUniform[index], count, transpose, v);
}
}
}
@@ -1428,7 +1559,7 @@ GLint LLGLSLShader::getUniformLocation(const LLStaticHashedString& uniform)
if (gDebugGL)
{
stop_glerror();
- if (iter->second != glGetUniformLocationARB(mProgramObject, uniform.String().c_str()))
+ if (iter->second != glGetUniformLocation(mProgramObject, uniform.String().c_str()))
{
LL_ERRS() << "Uniform does not match." << LL_ENDL;
}
@@ -1475,15 +1606,52 @@ GLint LLGLSLShader::getAttribLocation(U32 attrib)
void LLGLSLShader::uniform1i(const LLStaticHashedString& uniform, GLint v)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ GLint location = getUniformLocation(uniform);
+
+ if (location >= 0)
+ {
+ const auto& iter = mValue.find(location);
+ LLVector4 vec(v, 0.f, 0.f, 0.f);
+ if (iter == mValue.end() || shouldChange(iter->second, vec))
+ {
+ glUniform1i(location, v);
+ mValue[location] = vec;
+ }
+ }
+}
+
+void LLGLSLShader::uniform1iv(const LLStaticHashedString& uniform, U32 count, const GLint* v)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ GLint location = getUniformLocation(uniform);
+
+ if (location >= 0)
+ {
+ LLVector4 vec(v[0], 0, 0, 0);
+ const auto& iter = mValue.find(location);
+ if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1)
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ glUniform1iv(location, count, v);
+ mValue[location] = vec;
+ }
+ }
+}
+
+void LLGLSLShader::uniform4iv(const LLStaticHashedString& uniform, U32 count, const GLint* v)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
GLint location = getUniformLocation(uniform);
-
+
if (location >= 0)
{
+ LLVector4 vec(v[0], v[1], v[2], v[3]);
const auto& iter = mValue.find(location);
- LLVector4 vec(v,0.f,0.f,0.f);
- if (iter == mValue.end() || shouldChange(iter->second,vec))
+ if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1)
{
- glUniform1iARB(location, v);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ glUniform4iv(location, count, v);
mValue[location] = vec;
}
}
@@ -1491,15 +1659,16 @@ void LLGLSLShader::uniform1i(const LLStaticHashedString& uniform, GLint v)
void LLGLSLShader::uniform2i(const LLStaticHashedString& uniform, GLint i, GLint j)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
GLint location = getUniformLocation(uniform);
-
+
if (location >= 0)
{
const auto& iter = mValue.find(location);
- LLVector4 vec(i,j,0.f,0.f);
- if (iter == mValue.end() || shouldChange(iter->second,vec))
+ LLVector4 vec(i, j, 0.f, 0.f);
+ if (iter == mValue.end() || shouldChange(iter->second, vec))
{
- glUniform2iARB(location, i, j);
+ glUniform2i(location, i, j);
mValue[location] = vec;
}
}
@@ -1508,15 +1677,16 @@ void LLGLSLShader::uniform2i(const LLStaticHashedString& uniform, GLint i, GLint
void LLGLSLShader::uniform1f(const LLStaticHashedString& uniform, GLfloat v)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
GLint location = getUniformLocation(uniform);
-
+
if (location >= 0)
{
const auto& iter = mValue.find(location);
- LLVector4 vec(v,0.f,0.f,0.f);
- if (iter == mValue.end() || shouldChange(iter->second,vec))
+ LLVector4 vec(v, 0.f, 0.f, 0.f);
+ if (iter == mValue.end() || shouldChange(iter->second, vec))
{
- glUniform1fARB(location, v);
+ glUniform1f(location, v);
mValue[location] = vec;
}
}
@@ -1524,15 +1694,16 @@ void LLGLSLShader::uniform1f(const LLStaticHashedString& uniform, GLfloat v)
void LLGLSLShader::uniform2f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
GLint location = getUniformLocation(uniform);
-
+
if (location >= 0)
{
const auto& iter = mValue.find(location);
- LLVector4 vec(x,y,0.f,0.f);
- if (iter == mValue.end() || shouldChange(iter->second,vec))
+ LLVector4 vec(x, y, 0.f, 0.f);
+ if (iter == mValue.end() || shouldChange(iter->second, vec))
{
- glUniform2fARB(location, x,y);
+ glUniform2f(location, x, y);
mValue[location] = vec;
}
}
@@ -1541,15 +1712,16 @@ void LLGLSLShader::uniform2f(const LLStaticHashedString& uniform, GLfloat x, GLf
void LLGLSLShader::uniform3f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y, GLfloat z)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
GLint location = getUniformLocation(uniform);
-
+
if (location >= 0)
{
const auto& iter = mValue.find(location);
- LLVector4 vec(x,y,z,0.f);
- if (iter == mValue.end() || shouldChange(iter->second,vec))
+ LLVector4 vec(x, y, z, 0.f);
+ if (iter == mValue.end() || shouldChange(iter->second, vec))
{
- glUniform3fARB(location, x,y,z);
+ glUniform3f(location, x, y, z);
mValue[location] = vec;
}
}
@@ -1557,15 +1729,16 @@ void LLGLSLShader::uniform3f(const LLStaticHashedString& uniform, GLfloat x, GLf
void LLGLSLShader::uniform1fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
GLint location = getUniformLocation(uniform);
if (location >= 0)
{
const auto& iter = mValue.find(location);
- LLVector4 vec(v[0],0.f,0.f,0.f);
- if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1)
+ LLVector4 vec(v[0], 0.f, 0.f, 0.f);
+ if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1)
{
- glUniform1fvARB(location, count, v);
+ glUniform1fv(location, count, v);
mValue[location] = vec;
}
}
@@ -1573,15 +1746,16 @@ void LLGLSLShader::uniform1fv(const LLStaticHashedString& uniform, U32 count, co
void LLGLSLShader::uniform2fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
GLint location = getUniformLocation(uniform);
-
+
if (location >= 0)
{
const auto& iter = mValue.find(location);
- LLVector4 vec(v[0],v[1],0.f,0.f);
- if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1)
+ LLVector4 vec(v[0], v[1], 0.f, 0.f);
+ if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1)
{
- glUniform2fvARB(location, count, v);
+ glUniform2fv(location, count, v);
mValue[location] = vec;
}
}
@@ -1589,15 +1763,16 @@ void LLGLSLShader::uniform2fv(const LLStaticHashedString& uniform, U32 count, co
void LLGLSLShader::uniform3fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
GLint location = getUniformLocation(uniform);
-
+
if (location >= 0)
{
const auto& iter = mValue.find(location);
- LLVector4 vec(v[0],v[1],v[2],0.f);
- if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1)
+ LLVector4 vec(v[0], v[1], v[2], 0.f);
+ if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1)
{
- glUniform3fvARB(location, count, v);
+ glUniform3fv(location, count, v);
mValue[location] = vec;
}
}
@@ -1605,16 +1780,17 @@ void LLGLSLShader::uniform3fv(const LLStaticHashedString& uniform, U32 count, co
void LLGLSLShader::uniform4fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
GLint location = getUniformLocation(uniform);
if (location >= 0)
{
LLVector4 vec(v);
const auto& iter = mValue.find(location);
- if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1)
+ if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
- glUniform4fvARB(location, count, v);
+ glUniform4fv(location, count, v);
mValue[location] = vec;
}
}
@@ -1622,12 +1798,13 @@ void LLGLSLShader::uniform4fv(const LLStaticHashedString& uniform, U32 count, co
void LLGLSLShader::uniformMatrix4fv(const LLStaticHashedString& uniform, U32 count, GLboolean transpose, const GLfloat* v)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
GLint location = getUniformLocation(uniform);
-
+
if (location >= 0)
{
stop_glerror();
- glUniformMatrix4fvARB(location, count, transpose, v);
+ glUniformMatrix4fv(location, count, transpose, v);
stop_glerror();
}
}
@@ -1637,7 +1814,7 @@ void LLGLSLShader::vertexAttrib4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GL
{
if (mAttribute[index] > 0)
{
- glVertexAttrib4fARB(mAttribute[index], x, y, z, w);
+ glVertexAttrib4f(mAttribute[index], x, y, z, w);
}
}
@@ -1645,12 +1822,13 @@ void LLGLSLShader::vertexAttrib4fv(U32 index, GLfloat* v)
{
if (mAttribute[index] > 0)
{
- glVertexAttrib4fvARB(mAttribute[index], v);
+ glVertexAttrib4fv(mAttribute[index], v);
}
}
void LLGLSLShader::setMinimumAlpha(F32 minimum)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
gGL.flush();
uniform1f(LLShaderMgr::MINIMUM_ALPHA, minimum);
}
@@ -1678,3 +1856,9 @@ void LLShaderUniforms::apply(LLGLSLShader* shader)
shader->uniform3fv(uniform.mUniform, 1, uniform.mValue.mV);
}
}
+
+#ifdef LL_PROFILER_ENABLE_RENDER_DOC
+void LLGLSLShader::setLabel(const char* label) {
+ LL_LABEL_OBJECT_GL(GL_PROGRAM, mProgramObject, strlen(label), label);
+}
+#endif
diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h
index 85e83dbcb9..6c18282fec 100644
--- a/indra/llrender/llglslshader.h
+++ b/indra/llrender/llglslshader.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llglslshader.h
* @brief GLSL shader wrappers
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, 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$
*/
@@ -35,34 +35,36 @@
class LLShaderFeatures
{
public:
- bool atmosphericHelpers;
- bool calculatesLighting;
- bool calculatesAtmospherics;
- bool hasLighting; // implies no transport (it's possible to have neither though)
- bool isAlphaLighting; // indicates lighting shaders need not be linked in (lighting performed directly in alpha shader to match deferred lighting functions)
- bool isShiny;
- bool isFullbright; // implies no lighting
- bool isSpecular;
- bool hasWaterFog; // implies no gamma
- bool hasTransport; // implies no lighting (it's possible to have neither though)
- bool hasSkinning;
- bool hasObjectSkinning;
- bool hasAtmospherics;
- bool hasGamma;
+ bool atmosphericHelpers;
+ bool calculatesLighting;
+ bool calculatesAtmospherics;
+ bool hasLighting; // implies no transport (it's possible to have neither though)
+ bool isAlphaLighting; // indicates lighting shaders need not be linked in (lighting performed directly in alpha shader to match deferred lighting functions)
+ bool isShiny;
+ bool isFullbright; // implies no lighting
+ bool isSpecular;
+ bool hasWaterFog; // implies no gamma
+ bool hasTransport; // implies no lighting (it's possible to have neither though)
+ bool hasSkinning;
+ bool hasObjectSkinning;
+ bool hasAtmospherics;
+ bool hasGamma;
bool hasShadows;
bool hasAmbientOcclusion;
- bool hasSrgb;
- bool encodesNormal;
+ bool hasSrgb;
+ bool encodesNormal; // include: shaders\class1\environment\encodeNormF.glsl
bool isDeferred;
+ bool hasScreenSpaceReflections;
bool hasIndirect;
- S32 mIndexedTextureChannels;
- bool disableTextureIndex;
- bool hasAlphaMask;
- bool attachNothing;
-
- // char numLights;
-
- LLShaderFeatures();
+ S32 mIndexedTextureChannels;
+ bool disableTextureIndex;
+ bool hasAlphaMask;
+ bool hasReflectionProbes = false;
+ bool attachNothing;
+
+ // char numLights;
+
+ LLShaderFeatures();
};
// ============= Structure for caching shader uniforms ===============
@@ -106,7 +108,7 @@ public:
{
mVectors.push_back({ index, value });
}
-
+
void uniform4fv(S32 index, const F32* value)
{
mVectors.push_back({ index, LLVector4(value) });
@@ -117,8 +119,13 @@ public:
mVector3s.push_back({ index, value });
}
+ void uniform3fv(S32 index, const F32* value)
+ {
+ mVector3s.push_back({ index, LLVector3(value) });
+ }
+
void apply(LLGLSLShader* shader);
-
+
std::vector<IntSetting> mIntegers;
std::vector<FloatSetting> mFloats;
@@ -128,170 +135,187 @@ public:
class LLGLSLShader
{
public:
+ // NOTE: Keep gShaderConsts and LLGLSLShader::ShaderConsts_e in sync!
+ enum eShaderConsts
+ {
+ SHADER_CONST_CLOUD_MOON_DEPTH
+ , SHADER_CONST_STAR_DEPTH
+ , NUM_SHADER_CONSTS
+ };
// enum primarily used to control application sky settings uniforms
- typedef enum
- {
- SG_DEFAULT = 0, // not sky or water specific
- SG_SKY, //
- SG_WATER,
+ typedef enum
+ {
+ SG_DEFAULT = 0, // not sky or water specific
+ SG_SKY, //
+ SG_WATER,
SG_ANY,
SG_COUNT
- } eGroup;
-
- static std::set<LLGLSLShader*> sInstances;
- static bool sProfileEnabled;
-
- LLGLSLShader();
- ~LLGLSLShader();
-
- static GLhandleARB sCurBoundShader;
- static LLGLSLShader* sCurBoundShaderPtr;
- static S32 sIndexedTextureChannels;
-
- static void initProfile();
- static void finishProfile(bool emit_report = true);
-
- static void startProfile();
- static void stopProfile(U32 count, U32 mode);
-
- void unload();
- void clearStats();
- void dumpStats();
- void placeProfileQuery();
- void readProfileQuery(U32 count, U32 mode);
-
- BOOL createShader(std::vector<LLStaticHashedString> * attributes,
- std::vector<LLStaticHashedString> * uniforms,
- U32 varying_count = 0,
- const char** varyings = NULL);
+ } eGroup;
+
+ static std::set<LLGLSLShader*> sInstances;
+ static bool sProfileEnabled;
+
+ LLGLSLShader();
+ ~LLGLSLShader();
+
+ static GLuint sCurBoundShader;
+ static LLGLSLShader* sCurBoundShaderPtr;
+ static S32 sIndexedTextureChannels;
+
+ static void initProfile();
+ static void finishProfile(bool emit_report = true);
+
+ static void startProfile();
+ static void stopProfile();
+
+ void unload();
+ void clearStats();
+ void dumpStats();
+ void placeProfileQuery();
+ void readProfileQuery();
+
+ BOOL createShader(std::vector<LLStaticHashedString>* attributes,
+ std::vector<LLStaticHashedString>* uniforms,
+ U32 varying_count = 0,
+ const char** varyings = NULL);
BOOL attachFragmentObject(std::string object);
BOOL attachVertexObject(std::string object);
- void attachObject(GLhandleARB object);
- void attachObjects(GLhandleARB* objects = NULL, S32 count = 0);
- BOOL mapAttributes(const std::vector<LLStaticHashedString> * attributes);
- BOOL mapUniforms(const std::vector<LLStaticHashedString> *);
- void mapUniform(GLint index, const std::vector<LLStaticHashedString> *);
- void uniform1i(U32 index, GLint i);
- void uniform1f(U32 index, GLfloat v);
- void uniform2f(U32 index, GLfloat x, GLfloat y);
- void uniform3f(U32 index, GLfloat x, GLfloat y, GLfloat z);
- void uniform4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
- void uniform1iv(U32 index, U32 count, const GLint* i);
- void uniform1fv(U32 index, U32 count, const GLfloat* v);
- void uniform2fv(U32 index, U32 count, const GLfloat* v);
- void uniform3fv(U32 index, U32 count, const GLfloat* v);
- void uniform4fv(U32 index, U32 count, const GLfloat* v);
- void uniform2i(const LLStaticHashedString& uniform, GLint i, GLint j);
- void uniformMatrix2fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v);
- void uniformMatrix3fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v);
- void uniformMatrix3x4fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v);
- void uniformMatrix4fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v);
- void uniform1i(const LLStaticHashedString& uniform, GLint i);
- void uniform1f(const LLStaticHashedString& uniform, GLfloat v);
- void uniform2f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y);
- void uniform3f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y, GLfloat z);
- void uniform1fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v);
- void uniform2fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v);
- void uniform3fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v);
- void uniform4fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v);
- void uniformMatrix4fv(const LLStaticHashedString& uniform, U32 count, GLboolean transpose, const GLfloat *v);
-
- void setMinimumAlpha(F32 minimum);
-
- void vertexAttrib4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
- void vertexAttrib4fv(U32 index, GLfloat* v);
-
- //GLint getUniformLocation(const std::string& uniform);
- GLint getUniformLocation(const LLStaticHashedString& uniform);
- GLint getUniformLocation(U32 index);
-
- GLint getAttribLocation(U32 attrib);
- GLint mapUniformTextureChannel(GLint location, GLenum type);
-
+ void attachObject(GLuint object);
+ void attachObjects(GLuint* objects = NULL, S32 count = 0);
+ BOOL mapAttributes(const std::vector<LLStaticHashedString>* attributes);
+ BOOL mapUniforms(const std::vector<LLStaticHashedString>*);
+ void mapUniform(GLint index, const std::vector<LLStaticHashedString>*);
+ void uniform1i(U32 index, GLint i);
+ void uniform1f(U32 index, GLfloat v);
+ void fastUniform1f(U32 index, GLfloat v);
+ void uniform2f(U32 index, GLfloat x, GLfloat y);
+ void uniform3f(U32 index, GLfloat x, GLfloat y, GLfloat z);
+ void uniform4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+ void uniform1iv(U32 index, U32 count, const GLint* i);
+ void uniform4iv(U32 index, U32 count, const GLint* i);
+ void uniform1fv(U32 index, U32 count, const GLfloat* v);
+ void uniform2fv(U32 index, U32 count, const GLfloat* v);
+ void uniform3fv(U32 index, U32 count, const GLfloat* v);
+ void uniform4fv(U32 index, U32 count, const GLfloat* v);
+ void uniform2i(const LLStaticHashedString& uniform, GLint i, GLint j);
+ void uniformMatrix2fv(U32 index, U32 count, GLboolean transpose, const GLfloat* v);
+ void uniformMatrix3fv(U32 index, U32 count, GLboolean transpose, const GLfloat* v);
+ void uniformMatrix3x4fv(U32 index, U32 count, GLboolean transpose, const GLfloat* v);
+ void uniformMatrix4fv(U32 index, U32 count, GLboolean transpose, const GLfloat* v);
+ void uniform1i(const LLStaticHashedString& uniform, GLint i);
+ void uniform1iv(const LLStaticHashedString& uniform, U32 count, const GLint* v);
+ void uniform4iv(const LLStaticHashedString& uniform, U32 count, const GLint* v);
+ void uniform1f(const LLStaticHashedString& uniform, GLfloat v);
+ void uniform2f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y);
+ void uniform3f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y, GLfloat z);
+ void uniform1fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v);
+ void uniform2fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v);
+ void uniform3fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v);
+ void uniform4fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v);
+ void uniformMatrix4fv(const LLStaticHashedString& uniform, U32 count, GLboolean transpose, const GLfloat* v);
+
+ void setMinimumAlpha(F32 minimum);
+
+ void vertexAttrib4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+ void vertexAttrib4fv(U32 index, GLfloat* v);
+
+ //GLint getUniformLocation(const std::string& uniform);
+ GLint getUniformLocation(const LLStaticHashedString& uniform);
+ GLint getUniformLocation(U32 index);
+
+ GLint getAttribLocation(U32 attrib);
+ GLint mapUniformTextureChannel(GLint location, GLenum type, GLint size);
+
void clearPermutations();
- void addPermutation(std::string name, std::string value);
- void removePermutation(std::string name);
-
- //enable/disable texture channel for specified uniform
- //if given texture uniform is active in the shader,
- //the corresponding channel will be active upon return
- //returns channel texture is enabled in from [0-MAX)
- S32 enableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureColorSpace space = LLTexUnit::TCS_LINEAR);
+ void addPermutation(std::string name, std::string value);
+ void removePermutation(std::string name);
+
+ void addConstant(const LLGLSLShader::eShaderConsts shader_const);
+
+ //enable/disable texture channel for specified uniform
+ //if given texture uniform is active in the shader,
+ //the corresponding channel will be active upon return
+ //returns channel texture is enabled in from [0-MAX)
+ 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);
-
- // 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);
- S32 bindTexture(S32 uniform, LLTexture *texture, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureColorSpace space = LLTexUnit::TCS_LINEAR);
- S32 unbindTexture(const std::string& uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
- S32 unbindTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
-
+
+ // 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);
+ S32 bindTexture(S32 uniform, LLTexture* texture, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureColorSpace space = LLTexUnit::TCS_LINEAR);
+ S32 unbindTexture(const std::string& uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
+ S32 unbindTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
+
BOOL link(BOOL suppress_errors = FALSE);
- void bind();
+ 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);
+
+ // Unbinds any previously bound shader by explicitly binding no shader.
+ static void unbind();
- U32 mMatHash[LLRender::NUM_MATRIX_MODES];
- U32 mLightHash;
+ U32 mMatHash[LLRender::NUM_MATRIX_MODES];
+ U32 mLightHash;
- GLhandleARB mProgramObject;
+ GLuint mProgramObject;
#if LL_RELEASE_WITH_DEBUG_INFO
- struct attr_name
- {
- GLint loc;
- const char *name;
- void operator = (GLint _loc) { loc = _loc; }
- operator GLint () { return loc; }
- };
- std::vector<attr_name> mAttribute; //lookup table of attribute enum to attribute channel
+ struct attr_name
+ {
+ GLint loc;
+ const char* name;
+ void operator = (GLint _loc) { loc = _loc; }
+ operator GLint () { return loc; }
+ };
+ std::vector<attr_name> mAttribute; //lookup table of attribute enum to attribute channel
#else
- std::vector<GLint> mAttribute; //lookup table of attribute enum to attribute channel
+ std::vector<GLint> mAttribute; //lookup table of attribute enum to attribute channel
#endif
- U32 mAttributeMask; //mask of which reserved attributes are set (lines up with LLVertexBuffer::getTypeMask())
- std::vector<GLint> mUniform; //lookup table of uniform enum to uniform location
- LLStaticStringTable<GLint> mUniformMap; //lookup map of uniform name to uniform location
+ U32 mAttributeMask; //mask of which reserved attributes are set (lines up with LLVertexBuffer::getTypeMask())
+ std::vector<GLint> mUniform; //lookup table of uniform enum to uniform location
+ LLStaticStringTable<GLint> mUniformMap; //lookup map of uniform name to uniform location
typedef std::unordered_map<GLint, std::string> uniform_name_map_t;
typedef std::unordered_map<GLint, LLVector4> uniform_value_map_t;
uniform_name_map_t mUniformNameMap; //lookup map of uniform location to uniform name
- uniform_value_map_t mValue; //lookup map of uniform location to last known value
- std::vector<GLint> mTexture;
- S32 mTotalUniformSize;
- S32 mActiveTextureChannels;
- S32 mShaderLevel;
- S32 mShaderGroup; // see LLGLSLShader::eGroup
- BOOL mUniformsDirty;
- LLShaderFeatures mFeatures;
- std::vector< std::pair< std::string, GLenum > > mShaderFiles;
- std::string mName;
+ uniform_value_map_t mValue; //lookup map of uniform location to last known value
+ std::vector<GLint> mTexture;
+ S32 mTotalUniformSize;
+ S32 mActiveTextureChannels;
+ S32 mShaderLevel;
+ S32 mShaderGroup; // see LLGLSLShader::eGroup
+ BOOL mUniformsDirty;
+ LLShaderFeatures mFeatures;
+ std::vector< std::pair< std::string, GLenum > > mShaderFiles;
+ std::string mName;
typedef std::unordered_map<std::string, std::string> defines_map_t;
- defines_map_t mDefines;
-
- //statistcis for profiling shader performance
- U32 mTimerQuery;
- U32 mSamplesQuery;
- U64 mTimeElapsed;
- static U64 sTotalTimeElapsed;
- U32 mTrianglesDrawn;
- static U32 sTotalTrianglesDrawn;
- U64 mSamplesDrawn;
- static U64 sTotalSamplesDrawn;
- U32 mDrawCalls;
- static U32 sTotalDrawCalls;
-
- bool mTextureStateFetched;
- std::vector<U32> mTextureMagFilter;
- std::vector<U32> mTextureMinFilter;
+ defines_map_t mDefines;
+
+ //statistics for profiling shader performance
+ U32 mTimerQuery;
+ U32 mSamplesQuery;
+ U32 mPrimitivesQuery;
+
+ U64 mTimeElapsed;
+ static U64 sTotalTimeElapsed;
+ U32 mTrianglesDrawn;
+ static U32 sTotalTrianglesDrawn;
+ U64 mSamplesDrawn;
+ static U64 sTotalSamplesDrawn;
+ U32 mBinds;
+ static U32 sTotalBinds;
// this pointer should be set to whichever shader represents this shader's rigged variant
LLGLSLShader* mRiggedVariant = nullptr;
+#ifdef LL_PROFILER_ENABLE_RENDER_DOC
+ void setLabel(const char* label);
+#endif
+
private:
- void unloadInternal();
+ void unloadInternal();
};
//UI shader (declared here so llui_libtest will link properly)
@@ -301,5 +325,10 @@ extern LLGLSLShader gSolidColorProgram;
//Alpha mask shader (declared here so llappearance can access properly)
extern LLGLSLShader gAlphaMaskProgram;
+#ifdef LL_PROFILER_ENABLE_RENDER_DOC
+#define LL_SET_SHADER_LABEL(shader) shader.setLabel(#shader)
+#else
+#define LL_SET_SHADER_LABEL(shader, label)
+#endif
#endif
diff --git a/indra/llrender/llglstates.h b/indra/llrender/llglstates.h
index a4924eba14..c46585eab4 100644
--- a/indra/llrender/llglstates.h
+++ b/indra/llrender/llglstates.h
@@ -57,7 +57,7 @@ class LLGLSDefault
{
protected:
LLGLEnable mColorMaterial;
- LLGLDisable mAlphaTest, mBlend, mCullFace, mDither, mFog,
+ LLGLDisable mAlphaTest, mBlend, mCullFace, mDither,
mLineSmooth, mLineStipple, mNormalize, mPolygonSmooth,
mGLMultisample;
public:
@@ -70,23 +70,22 @@ public:
mBlend(GL_BLEND),
mCullFace(GL_CULL_FACE),
mDither(GL_DITHER),
- mFog(GL_FOG),
mLineSmooth(GL_LINE_SMOOTH),
mLineStipple(GL_LINE_STIPPLE),
mNormalize(GL_NORMALIZE),
mPolygonSmooth(GL_POLYGON_SMOOTH),
- mGLMultisample(GL_MULTISAMPLE_ARB)
+ mGLMultisample(GL_MULTISAMPLE)
{ }
};
class LLGLSObjectSelect
{
protected:
- LLGLDisable mBlend, mFog, mAlphaTest;
+ LLGLDisable mBlend, mAlphaTest;
LLGLEnable mCullFace;
public:
LLGLSObjectSelect()
- : mBlend(GL_BLEND), mFog(GL_FOG),
+ : mBlend(GL_BLEND),
mAlphaTest(GL_ALPHA_TEST),
mCullFace(GL_CULL_FACE)
{ }
@@ -130,28 +129,6 @@ public:
//----------------------------------------------------------------------------
-class LLGLSFog
-{
-protected:
- LLGLEnable mFog;
-public:
- LLGLSFog()
- : mFog(GL_FOG)
- {}
-};
-
-class LLGLSNoFog
-{
-protected:
- LLGLDisable mFog;
-public:
- LLGLSNoFog()
- : mFog(GL_FOG)
- {}
-};
-
-//----------------------------------------------------------------------------
-
class LLGLSPipeline
{
protected:
@@ -175,16 +152,6 @@ public:
{ }
};
-class LLGLSPipelineEmbossBump
-{
-protected:
- LLGLDisable mFog;
-public:
- LLGLSPipelineEmbossBump()
- : mFog(GL_FOG)
- { }
-};
-
class LLGLSPipelineSelection
{
protected:
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index 9dc140b5b9..b3b79bd6c4 100644
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -53,13 +53,75 @@ const F32 MIN_TEXTURE_LIFETIME = 10.f;
//assumes i is a power of 2 > 0
U32 wpo2(U32 i);
+
+// texture memory accounting (for OS X)
+static LLMutex sTexMemMutex;
+static std::unordered_map<U32, U32> sTextureAllocs;
+static U64 sTextureBytes = 0;
+
+// track a texture alloc on the currently bound texture.
+// asserts that no currently tracked alloc exists
+static void alloc_tex_image(U32 width, U32 height, U32 pixformat)
+{
+ U32 texUnit = gGL.getCurrentTexUnitIndex();
+ U32 texName = gGL.getTexUnit(texUnit)->getCurrTexture();
+ S32 size = LLImageGL::dataFormatBytes(pixformat, width, height);
+
+ llassert(size >= 0);
+
+ sTexMemMutex.lock();
+ llassert(sTextureAllocs.find(texName) == sTextureAllocs.end());
+
+ sTextureAllocs[texName] = size;
+ sTextureBytes += size;
+
+ sTexMemMutex.unlock();
+}
+
+// track texture free on given texName
+static void free_tex_image(U32 texName)
+{
+ sTexMemMutex.lock();
+ auto iter = sTextureAllocs.find(texName);
+ if (iter != sTextureAllocs.end())
+ {
+ llassert(iter->second <= sTextureBytes); // sTextureBytes MUST NOT go below zero
+
+ sTextureBytes -= iter->second;
+
+ sTextureAllocs.erase(iter);
+ }
+
+ sTexMemMutex.unlock();
+}
+
+// track texture free on given texNames
+static void free_tex_images(U32 count, const U32* texNames)
+{
+ for (int i = 0; i < count; ++i)
+ {
+ free_tex_image(texNames[i]);
+ }
+}
+
+// track texture free on currently bound texture
+static void free_cur_tex_image()
+{
+ U32 texUnit = gGL.getCurrentTexUnitIndex();
+ U32 texName = gGL.getTexUnit(texUnit)->getCurrTexture();
+ free_tex_image(texName);
+}
+
+// static
+U64 LLImageGL::getTextureBytesAllocated()
+{
+ return sTextureBytes;
+}
+
//statics
U32 LLImageGL::sUniqueCount = 0;
U32 LLImageGL::sBindCount = 0;
-S32Bytes LLImageGL::sGlobalTextureMemory(0);
-S32Bytes LLImageGL::sBoundTextureMemory(0);
-S32Bytes LLImageGL::sCurBoundTextureMemory(0);
S32 LLImageGL::sCount = 0;
BOOL LLImageGL::sGlobalUseAnisotropic = FALSE;
@@ -220,6 +282,7 @@ S32 LLImageGL::dataFormatBits(S32 dataformat)
case GL_RGBA: return 32;
case GL_SRGB_ALPHA: return 32;
case GL_BGRA: return 32; // Used for QuickTime media textures on the Mac
+ case GL_DEPTH_COMPONENT: return 24;
default:
LL_ERRS() << "LLImageGL::Unknown format: " << dataformat << LL_ENDL;
return 0;
@@ -282,15 +345,6 @@ void LLImageGL::updateStats(F32 current_time)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
sLastFrameTime = current_time;
- sBoundTextureMemory = sCurBoundTextureMemory;
- sCurBoundTextureMemory = S32Bytes(0);
-}
-
-//static
-S32 LLImageGL::updateBoundTexMem(const S32Bytes mem, const S32 ncomponents, S32 category)
-{
- LLImageGL::sCurBoundTextureMemory += mem ;
- return LLImageGL::sCurBoundTextureMemory.value();
}
//----------------------------------------------------------------------------
@@ -298,7 +352,7 @@ S32 LLImageGL::updateBoundTexMem(const S32Bytes mem, const S32 ncomponents, S32
//static
void LLImageGL::destroyGL(BOOL save_state)
{
- for (S32 stage = 0; stage < gGLManager.mNumTextureUnits; stage++)
+ for (S32 stage = 0; stage < gGLManager.mNumTextureImageUnits; stage++)
{
gGL.getTexUnit(stage)->unbind(LLTexUnit::TT_TEXTURE);
}
@@ -466,7 +520,6 @@ void LLImageGL::init(BOOL usemipmaps)
mPickMaskHeight = 0;
mUseMipMaps = usemipmaps;
mHasExplicitFormat = FALSE;
- mAutoGenMips = FALSE;
mIsMask = FALSE;
mNeedsAlphaAndPickMask = TRUE ;
@@ -623,7 +676,7 @@ void LLImageGL::forceUpdateBindStats(void) const
mLastBindTime = sLastFrameTime;
}
-BOOL LLImageGL::updateBindStats(S32Bytes tex_mem) const
+BOOL LLImageGL::updateBindStats() const
{
if (mTexName != 0)
{
@@ -635,7 +688,6 @@ BOOL LLImageGL::updateBindStats(S32Bytes tex_mem) const
{
// we haven't accounted for this texture yet this frame
sUniqueCount++;
- updateBoundTexMem(tex_mem, mComponents, mCategory);
mLastBindTime = sLastFrameTime;
return TRUE ;
@@ -741,7 +793,7 @@ BOOL LLImageGL::setImage(const U8* data_in, BOOL data_hasmips /* = FALSE */, S32
if (is_compressed)
{
S32 tex_size = dataFormatBytes(mFormatPrimary, w, h);
- glCompressedTexImage2DARB(mTarget, gl_level, mFormatPrimary, w, h, 0, tex_size, (GLvoid *)data_in);
+ glCompressedTexImage2D(mTarget, gl_level, mFormatPrimary, w, h, 0, tex_size, (GLvoid *)data_in);
stop_glerror();
}
else
@@ -812,6 +864,7 @@ BOOL LLImageGL::setImage(const U8* data_in, BOOL data_hasmips /* = FALSE */, S32
if (LLRender::sGLCoreProfile)
{
+ LL_PROFILE_GPU_ZONE("generate mip map");
glGenerateMipmap(mTarget);
}
stop_glerror();
@@ -936,7 +989,7 @@ BOOL LLImageGL::setImage(const U8* data_in, BOOL data_hasmips /* = FALSE */, S32
if (is_compressed)
{
S32 tex_size = dataFormatBytes(mFormatPrimary, w, h);
- glCompressedTexImage2DARB(mTarget, 0, mFormatPrimary, w, h, 0, tex_size, (GLvoid *)data_in);
+ glCompressedTexImage2D(mTarget, 0, mFormatPrimary, w, h, 0, tex_size, (GLvoid *)data_in);
stop_glerror();
}
else
@@ -1015,30 +1068,12 @@ BOOL LLImageGL::preAddToAtlas(S32 discard_level, const LLImageRaw* raw_image)
mFormatType = GL_UNSIGNED_BYTE;
break;
case 3:
-#if USE_SRGB_DECODE
- if (gGLManager.mHasTexturesRGBDecode)
- {
- mFormatInternal = GL_SRGB8;
- }
- else
-#endif
- {
- mFormatInternal = GL_RGB8;
- }
+ mFormatInternal = GL_RGB8;
mFormatPrimary = GL_RGB;
mFormatType = GL_UNSIGNED_BYTE;
break;
case 4:
-#if USE_SRGB_DECODE
- if (gGLManager.mHasTexturesRGBDecode)
- {
- mFormatInternal = GL_SRGB8_ALPHA8;
- }
- else
-#endif
- {
- mFormatInternal = GL_RGBA8;
- }
+ mFormatInternal = GL_RGBA8;
mFormatPrimary = GL_RGBA;
mFormatType = GL_UNSIGNED_BYTE;
break;
@@ -1231,6 +1266,7 @@ void LLImageGL::deleteTextures(S32 numTextures, const U32 *textures)
{
if (gGLManager.mInited)
{
+ free_tex_images(numTextures, textures);
glDeleteTextures(numTextures, textures);
}
}
@@ -1368,7 +1404,55 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt
stop_glerror();
{
LL_PROFILE_ZONE_NAMED("glTexImage2D");
+ LL_PROFILE_ZONE_NUM(width);
+ LL_PROFILE_ZONE_NUM(height);
+
+ free_cur_tex_image();
+#if 0
glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, use_scratch ? scratch : pixels);
+#else
+ // break up calls to a manageable size for the GL command buffer
+ {
+ LL_PROFILE_ZONE_NAMED("glTexImage2D alloc");
+ glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, nullptr);
+ }
+
+ U8* src = (U8*)(use_scratch ? scratch : pixels);
+ if (src)
+ {
+ LL_PROFILE_ZONE_NAMED("glTexImage2D copy");
+ U32 components = dataFormatComponents(pixformat);
+ U32 type_width = 0;
+
+ switch (pixtype)
+ {
+ case GL_UNSIGNED_BYTE:
+ case GL_BYTE:
+ case GL_UNSIGNED_INT_8_8_8_8_REV:
+ type_width = 1;
+ break;
+ case GL_UNSIGNED_SHORT:
+ case GL_SHORT:
+ type_width = 2;
+ break;
+ case GL_UNSIGNED_INT:
+ case GL_INT:
+ case GL_FLOAT:
+ type_width = 4;
+ break;
+ default:
+ LL_ERRS() << "Unknown type: " << pixtype << LL_ENDL;
+ }
+
+ U32 line_width = width * components * type_width;
+ for (U32 y = 0; y < height; ++y)
+ {
+ glTexSubImage2D(target, miplevel, 0, y, width, 1, pixformat, pixtype, src);
+ src += line_width;
+ }
+ }
+#endif
+ alloc_tex_image(width, height, pixformat);
}
stop_glerror();
@@ -1482,30 +1566,12 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S
mFormatType = GL_UNSIGNED_BYTE;
break;
case 3:
- #if USE_SRGB_DECODE
- if (gGLManager.mHasTexturesRGBDecode)
- {
- mFormatInternal = GL_SRGB8;
- }
- else
- #endif
- {
- mFormatInternal = GL_RGB8;
- }
+ mFormatInternal = GL_RGB8;
mFormatPrimary = GL_RGB;
mFormatType = GL_UNSIGNED_BYTE;
break;
case 4:
- #if USE_SRGB_DECODE
- if (gGLManager.mHasTexturesRGBDecode)
- {
- mFormatInternal = GL_SRGB8_ALPHA8;
- }
- else
- #endif
- {
- mFormatInternal = GL_RGBA8;
- }
+ mFormatInternal = GL_RGBA8;
mFormatPrimary = GL_RGBA;
mFormatType = GL_UNSIGNED_BYTE;
break;
@@ -1534,6 +1600,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_
// Call with void data, vmem is allocated but unitialized
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
+ LL_PROFILE_GPU_ZONE("createGLTexture");
checkActiveThread();
bool main_thread = on_main_thread();
@@ -1593,7 +1660,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_
if (mUseMipMaps)
{
- mAutoGenMips = gGLManager.mHasMipMapGeneration;
+ mAutoGenMips = true;
}
mCurrentDiscardLevel = discard_level;
@@ -1614,11 +1681,6 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_
// things will break if we don't unbind after creation
gGL.getTexUnit(0)->unbind(mBindTarget);
- if (old_texname != 0)
- {
- sGlobalTextureMemory -= mTextureMemory;
- }
-
//if we're on the image loading thread, be sure to delete old_texname and update mTexName on the main thread
if (!defer_copy)
{
@@ -1639,7 +1701,6 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_
mTextureMemory = (S32Bytes)getMipBytes(mCurrentDiscardLevel);
- sGlobalTextureMemory += mTextureMemory;
mTexelsInGLTexture = getWidth() * getHeight();
// mark this as bound at this point, so we don't throw it out immediately
@@ -1649,51 +1710,6 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_
return TRUE;
}
-void LLImageGLThread::updateClass()
-{
- LL_PROFILE_ZONE_SCOPED;
-
- // update available vram one per second
- static LLFrameTimer sTimer;
-
- if (sTimer.getElapsedSeconds() < 1.f)
- {
- return;
- }
-
- sTimer.reset();
-
- auto func = []()
- {
- if (gGLManager.mHasATIMemInfo)
- {
- S32 meminfo[4];
- glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, meminfo);
- LLImageGLThread::sFreeVRAMMegabytes = meminfo[0];
-
- }
- else if (gGLManager.mHasNVXMemInfo)
- {
- S32 free_memory;
- glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &free_memory);
- LLImageGLThread::sFreeVRAMMegabytes = free_memory / 1024;
- }
- };
-
-
- // post update to background thread if available, otherwise execute immediately
- auto queue = LL::WorkQueue::getInstance("LLImageGL");
- if (sEnabled)
- {
- queue->post(func);
- }
- else
- {
- llassert(queue == nullptr);
- func();
- }
-}
-
void LLImageGL::syncToMainThread(LLGLuint new_tex_name)
{
LL_PROFILE_ZONE_SCOPED;
@@ -1701,7 +1717,16 @@ void LLImageGL::syncToMainThread(LLGLuint new_tex_name)
{
LL_PROFILE_ZONE_NAMED("cglt - sync");
- if (gGLManager.mHasSync)
+ if (gGLManager.mIsNVIDIA)
+ {
+ // wait for texture upload to finish before notifying main thread
+ // upload is complete
+ auto sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+ glFlush();
+ glClientWaitSync(sync, 0, GL_TIMEOUT_IGNORED);
+ glDeleteSync(sync);
+ }
+ else
{
// post a sync to the main thread (will execute before tex name swap lambda below)
// glFlush calls here are partly superstitious and partly backed by observation
@@ -1724,10 +1749,6 @@ void LLImageGL::syncToMainThread(LLGLuint new_tex_name)
}
});
}
- else
- {
- glFinish();
- }
}
ref();
@@ -1739,8 +1760,11 @@ void LLImageGL::syncToMainThread(LLGLuint new_tex_name)
syncTexName(new_tex_name);
unref();
});
+
+ LL_PROFILER_GPU_COLLECT;
}
+
void LLImageGL::syncTexName(LLGLuint texname)
{
if (texname != 0)
@@ -1830,7 +1854,7 @@ BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre
return FALSE ;
}
- glGetCompressedTexImageARB(mTarget, gl_discard, (GLvoid*)(imageraw->getData()));
+ glGetCompressedTexImage(mTarget, gl_discard, (GLvoid*)(imageraw->getData()));
//stop_glerror();
}
else
@@ -1872,7 +1896,6 @@ void LLImageGL::destroyGLTexture()
{
if(mTextureMemory != S32Bytes(0))
{
- sGlobalTextureMemory -= mTextureMemory;
mTextureMemory = (S32Bytes)0;
}
@@ -2424,13 +2447,9 @@ void LLImageGL::checkActiveThread()
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, nummips);
*/
-std::atomic<S32> LLImageGLThread::sFreeVRAMMegabytes(4096); //if free vram is unknown, default to 4GB
-
LLImageGLThread::LLImageGLThread(LLWindow* window)
- // We want exactly one thread, but a very large capacity: we never want
- // anyone, especially inner-loop render code, to have to block on post()
- // because we're full.
- : ThreadPool("LLImageGL", 1, 1024*1024)
+ // We want exactly one thread.
+ : LL::ThreadPool("LLImageGL", 1)
, mWindow(window)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
@@ -2438,7 +2457,7 @@ LLImageGLThread::LLImageGLThread(LLWindow* window)
mFinished = false;
mContext = mWindow->createSharedContext();
- ThreadPool::start();
+ LL::ThreadPool::start();
}
void LLImageGLThread::run()
@@ -2448,13 +2467,8 @@ void LLImageGLThread::run()
// WorkQueue, likewise cleanup afterwards.
mWindow->makeContextCurrent(mContext);
gGL.init(false);
- ThreadPool::run();
+ LL::ThreadPool::run();
gGL.shutdown();
mWindow->destroySharedContext(mContext);
}
-S32 LLImageGLThread::getFreeVRAMMegabytes()
-{
- return sFreeVRAMMegabytes;
-}
-
diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h
index 4d5b60d6bc..bbd024abd9 100644
--- a/indra/llrender/llimagegl.h
+++ b/indra/llrender/llimagegl.h
@@ -52,6 +52,13 @@ class LLImageGL : public LLRefCount
{
friend class LLTexUnit;
public:
+
+ // Get an estimate of how many bytes have been allocated in vram for textures.
+ // Does not include mipmaps.
+ // NOTE: multiplying this number by two gives a good estimate for total
+ // video memory usage based on testing in lagland against an NVIDIA GPU.
+ static U64 getTextureBytesAllocated();
+
// These 2 functions replace glGenTextures() and glDeleteTextures()
static void generateTextures(S32 numTextures, U32 *textures);
static void deleteTextures(S32 numTextures, const U32 *textures);
@@ -61,7 +68,7 @@ public:
static S32 dataFormatBytes(S32 dataformat, S32 width, S32 height);
static S32 dataFormatComponents(S32 dataformat);
- BOOL updateBindStats(S32Bytes tex_mem) const ;
+ BOOL updateBindStats() const ;
F32 getTimePassedSinceLastBound();
void forceUpdateBindStats(void) const;
@@ -73,9 +80,6 @@ public:
static void restoreGL();
static void dirtyTexOptions();
- // Sometimes called externally for textures not using LLImageGL (should go away...)
- static S32 updateBoundTexMem(const S32Bytes mem, const S32 ncomponents, S32 category) ;
-
static bool checkSize(S32 width, S32 height);
//for server side use only.
@@ -161,11 +165,11 @@ public:
BOOL getUseMipMaps() const { return mUseMipMaps; }
void setUseMipMaps(BOOL usemips) { mUseMipMaps = usemips; }
-
+ void setHasMipMaps(BOOL hasmips) { mHasMipMaps = hasmips; }
void updatePickMask(S32 width, S32 height, const U8* data_in);
BOOL getMask(const LLVector2 &tc);
- void checkTexSize(bool forced = false) const ;
+ void checkTexSize(bool forced = false) const ;
// Sets the addressing mode used to sample the texture
// (such as wrapping, mirrored wrapping, and clamp)
@@ -215,7 +219,7 @@ private:
U16 mPickMaskHeight;
S8 mUseMipMaps;
BOOL mHasExplicitFormat; // If false (default), GL format is f(mComponents)
- S8 mAutoGenMips;
+ bool mAutoGenMips = false;
BOOL mIsMask;
BOOL mNeedsAlphaAndPickMask;
@@ -265,9 +269,6 @@ public:
static F32 sLastFrameTime;
// Global memory statistics
- static S32Bytes sGlobalTextureMemory; // Tracks main memory texmem
- static S32Bytes sBoundTextureMemory; // Tracks bound texmem for last completed frame
- static S32Bytes sCurBoundTextureMemory; // Tracks bound texmem for current frame
static U32 sBindCount; // Tracks number of texture binds for current frame
static U32 sUniqueCount; // Tracks number of unique texture binds for current frame
static BOOL sGlobalUseAnisotropic;
@@ -327,12 +328,6 @@ public:
// follows gSavedSettings "RenderGLMultiThreaded"
static bool sEnabled;
- // app should call this function periodically
- static void updateClass();
-
- // free video memory in megabytes
- static std::atomic<S32> sFreeVRAMMegabytes;
-
LLImageGLThread(LLWindow* window);
// post a function to be executed on the LLImageGL background thread
@@ -344,8 +339,6 @@ public:
void run() override;
- static S32 getFreeVRAMMegabytes();
-
private:
LLWindow* mWindow;
void* mContext = nullptr;
diff --git a/indra/llrender/llpostprocess.cpp b/indra/llrender/llpostprocess.cpp
index b6ea5aa7f1..f1e5b71207 100644
--- a/indra/llrender/llpostprocess.cpp
+++ b/indra/llrender/llpostprocess.cpp
@@ -239,17 +239,17 @@ void LLPostProcess::applyColorFilterShader(void)
gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_RECT_TEXTURE, sceneRenderTexture);
getShaderUniforms(colorFilterUniforms, gPostColorFilterProgram.mProgramObject);
- glUniform1iARB(colorFilterUniforms["RenderTexture"], 0);
- glUniform1fARB(colorFilterUniforms["brightness"], tweaks.getBrightness());
- glUniform1fARB(colorFilterUniforms["contrast"], tweaks.getContrast());
+ glUniform1i(colorFilterUniforms["RenderTexture"], 0);
+ glUniform1f(colorFilterUniforms["brightness"], tweaks.getBrightness());
+ glUniform1f(colorFilterUniforms["contrast"], tweaks.getContrast());
float baseI = (tweaks.getContrastBaseR() + tweaks.getContrastBaseG() + tweaks.getContrastBaseB()) / 3.0f;
baseI = tweaks.getContrastBaseIntensity() / ((baseI < 0.001f) ? 0.001f : baseI);
float baseR = tweaks.getContrastBaseR() * baseI;
float baseG = tweaks.getContrastBaseG() * baseI;
float baseB = tweaks.getContrastBaseB() * baseI;
- glUniform3fARB(colorFilterUniforms["contrastBase"], baseR, baseG, baseB);
- glUniform1fARB(colorFilterUniforms["saturation"], tweaks.getSaturation());
- glUniform3fARB(colorFilterUniforms["lumWeights"], LUMINANCE_R, LUMINANCE_G, LUMINANCE_B);
+ glUniform3f(colorFilterUniforms["contrastBase"], baseR, baseG, baseB);
+ glUniform1f(colorFilterUniforms["saturation"], tweaks.getSaturation());
+ glUniform3f(colorFilterUniforms["lumWeights"], LUMINANCE_R, LUMINANCE_G, LUMINANCE_B);
LLGLEnable blend(GL_BLEND);
gGL.setSceneBlendType(LLRender::BT_REPLACE);
@@ -282,22 +282,22 @@ void LLPostProcess::applyNightVisionShader(void)
getShaderUniforms(nightVisionUniforms, gPostNightVisionProgram.mProgramObject);
gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_RECT_TEXTURE, sceneRenderTexture);
- glUniform1iARB(nightVisionUniforms["RenderTexture"], 0);
+ glUniform1i(nightVisionUniforms["RenderTexture"], 0);
gGL.getTexUnit(1)->activate();
gGL.getTexUnit(1)->enable(LLTexUnit::TT_TEXTURE);
gGL.getTexUnit(1)->bindManual(LLTexUnit::TT_TEXTURE, noiseTexture);
- glUniform1iARB(nightVisionUniforms["NoiseTexture"], 1);
+ glUniform1i(nightVisionUniforms["NoiseTexture"], 1);
- glUniform1fARB(nightVisionUniforms["brightMult"], tweaks.getBrightMult());
- glUniform1fARB(nightVisionUniforms["noiseStrength"], tweaks.getNoiseStrength());
+ glUniform1f(nightVisionUniforms["brightMult"], tweaks.getBrightMult());
+ glUniform1f(nightVisionUniforms["noiseStrength"], tweaks.getNoiseStrength());
noiseTextureScale = 0.01f + ((101.f - tweaks.getNoiseSize()) / 100.f);
noiseTextureScale *= (screenH / NOISE_SIZE);
- glUniform3fARB(nightVisionUniforms["lumWeights"], LUMINANCE_R, LUMINANCE_G, LUMINANCE_B);
+ glUniform3f(nightVisionUniforms["lumWeights"], LUMINANCE_R, LUMINANCE_G, LUMINANCE_B);
LLGLEnable blend(GL_BLEND);
gGL.setSceneBlendType(LLRender::BT_REPLACE);
@@ -345,12 +345,12 @@ void LLPostProcess::createBloomShader(void)
bloomBlurUniforms[sBlurWidth] = 0;
}
-void LLPostProcess::getShaderUniforms(glslUniforms & uniforms, GLhandleARB & prog)
+void LLPostProcess::getShaderUniforms(glslUniforms & uniforms, GLuint & prog)
{
/// Find uniform locations and insert into map
glslUniforms::iterator i;
for (i = uniforms.begin(); i != uniforms.end(); ++i){
- i->second = glGetUniformLocationARB(prog, i->first.String().c_str());
+ i->second = glGetUniformLocation(prog, i->first.String().c_str());
}
}
@@ -376,7 +376,7 @@ void LLPostProcess::doEffects(void)
checkError();
applyShaders();
- LLGLSLShader::bindNoShader();
+ LLGLSLShader::unbind();
checkError();
/// Change to a perspective view
@@ -390,8 +390,8 @@ void LLPostProcess::doEffects(void)
void LLPostProcess::copyFrameBuffer(U32 & texture, unsigned int width, unsigned int height)
{
- gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_RECT_TEXTURE, texture);
- glCopyTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, 0, 0, width, height, 0);
+ gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, texture);
+ glCopyTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA, 0, 0, width, height, 0);
}
void LLPostProcess::drawOrthoQuad(unsigned int width, unsigned int height, QuadType type)
@@ -410,60 +410,60 @@ void LLPostProcess::drawOrthoQuad(unsigned int width, unsigned int height, QuadT
glBegin(GL_QUADS);
if (type != QUAD_BLOOM_EXTRACT){
- glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.f, (GLfloat) height);
+ glMultiTexCoord2f(GL_TEXTURE0, 0.f, (GLfloat) height);
} else {
- glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.f, (GLfloat) height * 2.0f);
+ glMultiTexCoord2f(GL_TEXTURE0, 0.f, (GLfloat) height * 2.0f);
}
if (type == QUAD_NOISE){
- glMultiTexCoord2fARB(GL_TEXTURE1_ARB,
+ glMultiTexCoord2f(GL_TEXTURE1,
noiseX,
noiseTextureScale + noiseY);
} else if (type == QUAD_BLOOM_COMBINE){
- glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0.f, (GLfloat) height * 0.5f);
+ glMultiTexCoord2f(GL_TEXTURE1, 0.f, (GLfloat) height * 0.5f);
}
glVertex2f(0.f, (GLfloat) screenH - height);
if (type != QUAD_BLOOM_EXTRACT){
- glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.f, 0.f);
+ glMultiTexCoord2f(GL_TEXTURE0, 0.f, 0.f);
} else {
- glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.f, 0.f);
+ glMultiTexCoord2f(GL_TEXTURE0, 0.f, 0.f);
}
if (type == QUAD_NOISE){
- glMultiTexCoord2fARB(GL_TEXTURE1_ARB,
+ glMultiTexCoord2f(GL_TEXTURE1,
noiseX,
noiseY);
} else if (type == QUAD_BLOOM_COMBINE){
- glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0.f, 0.f);
+ glMultiTexCoord2f(GL_TEXTURE1, 0.f, 0.f);
}
glVertex2f(0.f, (GLfloat) height + (screenH - height));
if (type != QUAD_BLOOM_EXTRACT){
- glMultiTexCoord2fARB(GL_TEXTURE0_ARB, (GLfloat) width, 0.f);
+ glMultiTexCoord2f(GL_TEXTURE0, (GLfloat) width, 0.f);
} else {
- glMultiTexCoord2fARB(GL_TEXTURE0_ARB, (GLfloat) width * 2.0f, 0.f);
+ glMultiTexCoord2f(GL_TEXTURE0, (GLfloat) width * 2.0f, 0.f);
}
if (type == QUAD_NOISE){
- glMultiTexCoord2fARB(GL_TEXTURE1_ARB,
+ glMultiTexCoord2f(GL_TEXTURE1,
screenRatio * noiseTextureScale + noiseX,
noiseY);
} else if (type == QUAD_BLOOM_COMBINE){
- glMultiTexCoord2fARB(GL_TEXTURE1_ARB, (GLfloat) width * 0.5f, 0.f);
+ glMultiTexCoord2f(GL_TEXTURE1, (GLfloat) width * 0.5f, 0.f);
}
glVertex2f((GLfloat) width, (GLfloat) height + (screenH - height));
if (type != QUAD_BLOOM_EXTRACT){
- glMultiTexCoord2fARB(GL_TEXTURE0_ARB, (GLfloat) width, (GLfloat) height);
+ glMultiTexCoord2f(GL_TEXTURE0, (GLfloat) width, (GLfloat) height);
} else {
- glMultiTexCoord2fARB(GL_TEXTURE0_ARB, (GLfloat) width * 2.0f, (GLfloat) height * 2.0f);
+ glMultiTexCoord2f(GL_TEXTURE0, (GLfloat) width * 2.0f, (GLfloat) height * 2.0f);
}
if (type == QUAD_NOISE){
- glMultiTexCoord2fARB(GL_TEXTURE1_ARB,
+ glMultiTexCoord2f(GL_TEXTURE1,
screenRatio * noiseTextureScale + noiseX,
noiseTextureScale + noiseY);
} else if (type == QUAD_BLOOM_COMBINE){
- glMultiTexCoord2fARB(GL_TEXTURE1_ARB, (GLfloat) width * 0.5f, (GLfloat) height * 0.5f);
+ glMultiTexCoord2f(GL_TEXTURE1, (GLfloat) width * 0.5f, (GLfloat) height * 0.5f);
}
glVertex2f((GLfloat) width, (GLfloat) screenH - height);
glEnd();
@@ -502,8 +502,8 @@ void LLPostProcess::createTexture(LLPointer<LLImageGL>& texture, unsigned int wi
texture = new LLImageGL(FALSE) ;
if(texture->createGLTexture())
{
- gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_RECT_TEXTURE, texture->getTexName());
- glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, width, height, 0,
+ gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, texture->getTexName());
+ glTexImage2D(GL_TEXTURE_RECTANGLE, 0, 4, width, height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
@@ -557,7 +557,7 @@ bool LLPostProcess::checkError(void)
return retCode;
}
-void LLPostProcess::checkShaderError(GLhandleARB shader)
+void LLPostProcess::checkShaderError(GLuint shader)
{
GLint infologLength = 0;
GLint charsWritten = 0;
@@ -565,7 +565,7 @@ void LLPostProcess::checkShaderError(GLhandleARB shader)
checkError(); // Check for OpenGL errors
- glGetObjectParameterivARB(shader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &infologLength);
+ glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infologLength);
checkError(); // Check for OpenGL errors
@@ -577,7 +577,7 @@ void LLPostProcess::checkShaderError(GLhandleARB shader)
/// Could not allocate infolog buffer
return;
}
- glGetInfoLogARB(shader, infologLength, &charsWritten, infoLog);
+ glGetProgramInfoLog(shader, infologLength, &charsWritten, infoLog);
// shaderErrorLog << (char *) infoLog << std::endl;
mShaderErrorString = (char *) infoLog;
free(infoLog);
diff --git a/indra/llrender/llpostprocess.h b/indra/llrender/llpostprocess.h
index ce17b6693d..bdfc632831 100644
--- a/indra/llrender/llpostprocess.h
+++ b/indra/llrender/llpostprocess.h
@@ -249,12 +249,12 @@ private:
void applyColorFilterShader(void);
/// OpenGL Helper Functions
- void getShaderUniforms(glslUniforms & uniforms, GLhandleARB & prog);
+ void getShaderUniforms(glslUniforms & uniforms, GLuint & prog);
void createTexture(LLPointer<LLImageGL>& texture, unsigned int width, unsigned int height);
void copyFrameBuffer(U32 & texture, unsigned int width, unsigned int height);
void createNoiseTexture(LLPointer<LLImageGL>& texture);
bool checkError(void);
- void checkShaderError(GLhandleARB shader);
+ void checkShaderError(GLuint shader);
void drawOrthoQuad(unsigned int width, unsigned int height, QuadType type);
void viewOrthogonal(unsigned int width, unsigned int height);
void changeOrthogonal(unsigned int width, unsigned int height);
diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp
index 72cca1f2a2..de74f2700a 100644
--- a/indra/llrender/llrender.cpp
+++ b/indra/llrender/llrender.cpp
@@ -35,6 +35,7 @@
#include "llrendertarget.h"
#include "lltexture.h"
#include "llshadermgr.h"
+#include "hbxxh.h"
#if LL_WINDOWS
extern void APIENTRY gl_debug_callback(GLenum source,
@@ -54,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;
@@ -66,11 +73,20 @@ LLVector2 LLRender::sUIGLScaleFactor = LLVector2(1.f, 1.f);
static const U32 LL_NUM_TEXTURE_LAYERS = 32;
static const U32 LL_NUM_LIGHT_UNITS = 8;
+struct LLVBCache
+{
+ LLPointer<LLVertexBuffer> vb;
+ std::chrono::steady_clock::time_point touched;
+};
+
+static std::unordered_map<U64, LLVBCache> sVBCache;
+
static const GLenum sGLTextureType[] =
{
GL_TEXTURE_2D,
- GL_TEXTURE_RECTANGLE_ARB,
- GL_TEXTURE_CUBE_MAP_ARB,
+ GL_TEXTURE_RECTANGLE,
+ GL_TEXTURE_CUBE_MAP,
+ GL_TEXTURE_CUBE_MAP_ARRAY,
GL_TEXTURE_2D_MULTISAMPLE,
GL_TEXTURE_3D
};
@@ -122,7 +138,7 @@ void LLTexUnit::refreshState(void)
gGL.flush();
- glActiveTextureARB(GL_TEXTURE0_ARB + mIndex);
+ glActiveTexture(GL_TEXTURE0 + mIndex);
if (mCurrTexType != TT_NONE)
{
@@ -143,7 +159,7 @@ void LLTexUnit::activate(void)
if ((S32)gGL.mCurrTextureUnitIndex != mIndex || gGL.mDirty)
{
gGL.flush();
- glActiveTextureARB(GL_TEXTURE0_ARB + mIndex);
+ glActiveTexture(GL_TEXTURE0 + mIndex);
gGL.mCurrTextureUnitIndex = mIndex;
}
}
@@ -154,13 +170,10 @@ void LLTexUnit::enable(eTextureType type)
if ( (mCurrTexType != type || gGL.mDirty) && (type != TT_NONE) )
{
- stop_glerror();
activate();
- stop_glerror();
if (mCurrTexType != TT_NONE && !gGL.mDirty)
{
disable(); // Force a disable of a previous texture type if it's enabled.
- stop_glerror();
}
mCurrTexType = type;
@@ -174,11 +187,7 @@ void LLTexUnit::disable(void)
if (mCurrTexType != TT_NONE)
{
- activate();
unbind(mCurrTexType);
- gGL.flush();
- setTextureColorSpace(TCS_LINEAR);
-
mCurrTexType = TT_NONE;
}
}
@@ -186,8 +195,8 @@ void LLTexUnit::disable(void)
void LLTexUnit::bindFast(LLTexture* texture)
{
LLImageGL* gl_tex = texture->getGLTexture();
-
- glActiveTextureARB(GL_TEXTURE0_ARB + mIndex);
+ texture->setActive();
+ glActiveTexture(GL_TEXTURE0 + mIndex);
gGL.mCurrTextureUnitIndex = mIndex;
mCurrTexture = gl_tex->getTexName();
if (!mCurrTexture)
@@ -223,7 +232,7 @@ bool LLTexUnit::bind(LLTexture* texture, bool for_rendering, bool forceBind)
enable(gl_tex->getTarget());
mCurrTexture = gl_tex->getTexName();
glBindTexture(sGLTextureType[gl_tex->getTarget()], mCurrTexture);
- if(gl_tex->updateBindStats(gl_tex->mTextureMemory))
+ if(gl_tex->updateBindStats())
{
texture->setActive() ;
texture->updateBindStatsForTester() ;
@@ -302,7 +311,7 @@ bool LLTexUnit::bind(LLImageGL* texture, bool for_rendering, bool forceBind, S32
mCurrTexture = texname;
glBindTexture(sGLTextureType[texture->getTarget()], mCurrTexture);
stop_glerror();
- texture->updateBindStats(texture->mTextureMemory);
+ texture->updateBindStats();
mHasMipMaps = texture->mHasMipMaps;
if (texture->mTexOptionsDirty)
{
@@ -334,14 +343,14 @@ bool LLTexUnit::bind(LLCubeMap* cubeMap)
if (mCurrTexture != cubeMap->mImages[0]->getTexName())
{
- if (gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps)
+ if (LLCubeMap::sUseCubeMaps)
{
activate();
enable(LLTexUnit::TT_CUBE_MAP);
mCurrTexture = cubeMap->mImages[0]->getTexName();
- glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, mCurrTexture);
+ glBindTexture(GL_TEXTURE_CUBE_MAP, mCurrTexture);
mHasMipMaps = cubeMap->mImages[0]->mHasMipMaps;
- cubeMap->mImages[0]->updateBindStats(cubeMap->mImages[0]->mTextureMemory);
+ cubeMap->mImages[0]->updateBindStats();
if (cubeMap->mImages[0]->mTexOptionsDirty)
{
cubeMap->mImages[0]->mTexOptionsDirty = false;
@@ -369,10 +378,7 @@ bool LLTexUnit::bind(LLRenderTarget* renderTarget, bool bindDepth)
if (bindDepth)
{
- if (renderTarget->hasStencil())
- {
- LL_ERRS() << "Cannot bind a render buffer for sampling. Allocate render target without a stencil buffer if sampling of depth buffer is required." << LL_ENDL;
- }
+ llassert(renderTarget->getDepth()); // target MUST have a depth buffer attachment
bindManual(renderTarget->getUsage(), renderTarget->getDepth());
}
@@ -469,7 +475,7 @@ void LLTexUnit::setTextureAddressMode(eTextureAddressMode mode)
glTexParameteri (sGLTextureType[mCurrTexType], GL_TEXTURE_WRAP_T, sGLAddressMode[mode]);
if (mCurrTexType == TT_CUBE_MAP)
{
- glTexParameteri (GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_R, sGLAddressMode[mode]);
+ glTexParameteri (GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, sGLAddressMode[mode]);
}
}
@@ -515,22 +521,15 @@ void LLTexUnit::setTextureFilteringOption(LLTexUnit::eTextureFilterOptions optio
}
}
- if (gGLManager.mHasAnisotropic)
+ if (gGLManager.mGLVersion >= 4.59f)
{
if (LLImageGL::sGlobalUseAnisotropic && option == TFO_ANISOTROPIC)
{
- if (gGL.mMaxAnisotropy < 1.f)
- {
- glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gGL.mMaxAnisotropy);
-
- LL_INFOS() << "gGL.mMaxAnisotropy: " << gGL.mMaxAnisotropy << LL_ENDL ;
- gGL.mMaxAnisotropy = llmax(1.f, gGL.mMaxAnisotropy) ;
- }
- glTexParameterf(sGLTextureType[mCurrTexType], GL_TEXTURE_MAX_ANISOTROPY_EXT, gGL.mMaxAnisotropy);
+ glTexParameterf(sGLTextureType[mCurrTexType], GL_TEXTURE_MAX_ANISOTROPY, gGLManager.mMaxAnisotropy);
}
else
{
- glTexParameterf(sGLTextureType[mCurrTexType], GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.f);
+ glTexParameterf(sGLTextureType[mCurrTexType], GL_TEXTURE_MAX_ANISOTROPY, 1.f);
}
}
}
@@ -544,7 +543,7 @@ GLint LLTexUnit::getTextureSource(eTextureBlendSrc src)
case TBS_PREV_ALPHA:
case TBS_ONE_MINUS_PREV_COLOR:
case TBS_ONE_MINUS_PREV_ALPHA:
- return GL_PREVIOUS_ARB;
+ return GL_PREVIOUS;
// All four cases should return the same value.
case TBS_TEX_COLOR:
@@ -558,18 +557,18 @@ GLint LLTexUnit::getTextureSource(eTextureBlendSrc src)
case TBS_VERT_ALPHA:
case TBS_ONE_MINUS_VERT_COLOR:
case TBS_ONE_MINUS_VERT_ALPHA:
- return GL_PRIMARY_COLOR_ARB;
+ return GL_PRIMARY_COLOR;
// All four cases should return the same value.
case TBS_CONST_COLOR:
case TBS_CONST_ALPHA:
case TBS_ONE_MINUS_CONST_COLOR:
case TBS_ONE_MINUS_CONST_ALPHA:
- return GL_CONSTANT_ARB;
+ return GL_CONSTANT;
default:
LL_WARNS() << "Unknown eTextureBlendSrc: " << src << ". Using Vertex Color instead." << LL_ENDL;
- return GL_PRIMARY_COLOR_ARB;
+ return GL_PRIMARY_COLOR;
}
}
@@ -638,10 +637,10 @@ void LLTexUnit::debugTextureUnit(void)
if (mIndex < 0) return;
GLint activeTexture;
- glGetIntegerv(GL_ACTIVE_TEXTURE_ARB, &activeTexture);
- if ((GL_TEXTURE0_ARB + mIndex) != activeTexture)
+ glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTexture);
+ if ((GL_TEXTURE0 + mIndex) != activeTexture)
{
- U32 set_unit = (activeTexture - GL_TEXTURE0_ARB);
+ U32 set_unit = (activeTexture - GL_TEXTURE0);
LL_WARNS() << "Incorrect Texture Unit! Expected: " << set_unit << " Actual: " << mIndex << LL_ENDL;
}
}
@@ -649,29 +648,6 @@ void LLTexUnit::debugTextureUnit(void)
void LLTexUnit::setTextureColorSpace(eTextureColorSpace space)
{
mTexColorSpace = space;
-
-#if USE_SRGB_DECODE
- if (gGLManager.mHasTexturesRGBDecode)
- {
- if (space == TCS_SRGB)
- {
- glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT);
- }
- else
- {
- glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
- }
-
- if (gDebugGL)
- {
- assert_glerror();
- }
- }
- else
- {
- glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
- }
-#endif
}
LLLightState::LLLightState(S32 index)
@@ -734,6 +710,24 @@ void LLLightState::setSunPrimary(bool v)
}
}
+void LLLightState::setSize(F32 v)
+{
+ if (mSize != v)
+ {
+ ++gGL.mLightHash;
+ mSize = v;
+ }
+}
+
+void LLLightState::setFalloff(F32 v)
+{
+ if (mFalloff != v)
+ {
+ ++gGL.mLightHash;
+ mFalloff = v;
+ }
+}
+
void LLLightState::setAmbient(const LLColor4& ambient)
{
if (mAmbient != ambient)
@@ -827,8 +821,7 @@ LLRender::LLRender()
mCount(0),
mQuadCycle(0),
mMode(LLRender::TRIANGLES),
- mCurrTextureUnitIndex(0),
- mMaxAnisotropy(0.f)
+ mCurrTextureUnitIndex(0)
{
mTexUnits.reserve(LL_NUM_TEXTURE_LAYERS);
for (U32 i = 0; i < LL_NUM_TEXTURE_LAYERS; i++)
@@ -874,9 +867,9 @@ void LLRender::init(bool needs_vertex_buffer)
#if LL_WINDOWS
if (gGLManager.mHasDebugOutput && gDebugGL)
{ //setup debug output callback
- //glDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_LOW_ARB, 0, NULL, GL_TRUE);
- glDebugMessageCallbackARB((GLDEBUGPROCARB) gl_debug_callback, NULL);
- glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
+ //glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_LOW_ARB, 0, NULL, GL_TRUE);
+ glDebugMessageCallback((GLDEBUGPROC) gl_debug_callback, NULL);
+ glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
}
#endif
@@ -888,14 +881,14 @@ void LLRender::init(bool needs_vertex_buffer)
glCullFace(GL_BACK);
- if (sGLCoreProfile && !LLVertexBuffer::sUseVAO)
- { //bind a dummy vertex array object so we're core profile compliant
-#ifdef GL_ARB_vertex_array_object
- U32 ret;
- glGenVertexArrays(1, &ret);
- glBindVertexArray(ret);
-#endif
- }
+ // necessary for reflection maps
+ glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
+
+ { //bind a dummy vertex array object so we're core profile compliant
+ U32 ret;
+ glGenVertexArrays(1, &ret);
+ glBindVertexArray(ret);
+ }
if (needs_vertex_buffer)
{
@@ -907,8 +900,8 @@ void LLRender::initVertexBuffer()
{
llassert_always(mBuffer.isNull());
stop_glerror();
- mBuffer = new LLVertexBuffer(immediate_mask, 0);
- mBuffer->allocateBuffer(4096, 0, TRUE);
+ mBuffer = new LLVertexBuffer(immediate_mask);
+ mBuffer->allocateBuffer(4096, 0);
mBuffer->getVertexStrider(mVerticesp);
mBuffer->getTexCoord0Strider(mTexcoordsp);
mBuffer->getColorStrider(mColorsp);
@@ -977,6 +970,7 @@ void LLRender::syncLightState()
LLVector3 diffuse[LL_NUM_LIGHT_UNITS];
LLVector3 diffuse_b[LL_NUM_LIGHT_UNITS];
bool sun_primary[LL_NUM_LIGHT_UNITS];
+ LLVector2 size[LL_NUM_LIGHT_UNITS];
for (U32 i = 0; i < LL_NUM_LIGHT_UNITS; i++)
{
@@ -988,17 +982,19 @@ void LLRender::syncLightState()
diffuse[i].set(light->mDiffuse.mV);
diffuse_b[i].set(light->mDiffuseB.mV);
sun_primary[i] = light->mSunIsPrimary;
+ size[i].set(light->mSize, light->mFalloff);
}
shader->uniform4fv(LLShaderMgr::LIGHT_POSITION, LL_NUM_LIGHT_UNITS, position[0].mV);
shader->uniform3fv(LLShaderMgr::LIGHT_DIRECTION, LL_NUM_LIGHT_UNITS, direction[0].mV);
shader->uniform4fv(LLShaderMgr::LIGHT_ATTENUATION, LL_NUM_LIGHT_UNITS, attenuation[0].mV);
+ shader->uniform2fv(LLShaderMgr::LIGHT_DEFERRED_ATTENUATION, LL_NUM_LIGHT_UNITS, size[0].mV);
shader->uniform3fv(LLShaderMgr::LIGHT_DIFFUSE, LL_NUM_LIGHT_UNITS, diffuse[0].mV);
- shader->uniform4fv(LLShaderMgr::LIGHT_AMBIENT, 1, mAmbientLightColor.mV);
+ shader->uniform3fv(LLShaderMgr::LIGHT_AMBIENT, 1, mAmbientLightColor.mV);
shader->uniform1i(LLShaderMgr::SUN_UP_FACTOR, sun_primary[0] ? 1 : 0);
- shader->uniform4fv(LLShaderMgr::AMBIENT, 1, mAmbientLightColor.mV);
- shader->uniform4fv(LLShaderMgr::SUNLIGHT_COLOR, 1, diffuse[0].mV);
- shader->uniform4fv(LLShaderMgr::MOONLIGHT_COLOR, 1, diffuse_b[0].mV);
+ shader->uniform3fv(LLShaderMgr::AMBIENT, 1, mAmbientLightColor.mV);
+ shader->uniform3fv(LLShaderMgr::SUNLIGHT_COLOR, 1, diffuse[0].mV);
+ shader->uniform3fv(LLShaderMgr::MOONLIGHT_COLOR, 1, diffuse_b[0].mV);
}
}
@@ -1095,13 +1091,20 @@ void LLRender::syncMatrices()
{ //update projection matrix, normal, and MVP
glh::matrix4f& mat = mMatrix[MM_PROJECTION][mMatIdx[MM_PROJECTION]];
- // it would be nice to have this automatically track the state of the proj matrix
- // but certain render paths (deferred lighting) require it to be mismatched *sigh*
- //if (shader->getUniformLocation(LLShaderMgr::INVERSE_PROJECTION_MATRIX))
- //{
- // glh::matrix4f inv_proj = mat.inverse();
- // shader->uniformMatrix4fv(LLShaderMgr::INVERSE_PROJECTION_MATRIX, 1, FALSE, inv_proj.m);
- //}
+ // GZ: This was previously disabled seemingly due to a bug involving the deferred renderer's regular pushing and popping of mats.
+ // We're reenabling this and cleaning up the code around that - that would've been the appropriate course initially.
+ // Anything beyond the standard proj and inv proj mats are special cases. Please setup special uniforms accordingly in the future.
+ if (shader->getUniformLocation(LLShaderMgr::INVERSE_PROJECTION_MATRIX))
+ {
+ glh::matrix4f inv_proj = mat.inverse();
+ shader->uniformMatrix4fv(LLShaderMgr::INVERSE_PROJECTION_MATRIX, 1, FALSE, inv_proj.m);
+ }
+
+ // Used by some full screen effects - such as full screen lights, glow, etc.
+ if (shader->getUniformLocation(LLShaderMgr::IDENTITY_MATRIX))
+ {
+ shader->uniformMatrix4fv(LLShaderMgr::IDENTITY_MATRIX, 1, GL_FALSE, glh::matrix4f::identity().m);
+ }
shader->uniformMatrix4fv(name[MM_PROJECTION], 1, GL_FALSE, mat.m);
shader->mMatHash[MM_PROJECTION] = mMatHash[MM_PROJECTION];
@@ -1479,12 +1482,7 @@ void LLRender::blendFunc(eBlendFactor color_sfactor, eBlendFactor color_dfactor,
llassert(color_dfactor < BF_UNDEF);
llassert(alpha_sfactor < BF_UNDEF);
llassert(alpha_dfactor < BF_UNDEF);
- if (!gGLManager.mHasBlendFuncSeparate)
- {
- LL_WARNS_ONCE("render") << "no glBlendFuncSeparateEXT(), using color-only blend func" << LL_ENDL;
- blendFunc(color_sfactor, color_dfactor);
- return;
- }
+
if (mCurrBlendColorSFactor != color_sfactor || mCurrBlendColorDFactor != color_dfactor ||
mCurrBlendAlphaSFactor != alpha_sfactor || mCurrBlendAlphaDFactor != alpha_dfactor)
{
@@ -1493,8 +1491,9 @@ void LLRender::blendFunc(eBlendFactor color_sfactor, eBlendFactor color_dfactor,
mCurrBlendColorDFactor = color_dfactor;
mCurrBlendAlphaDFactor = alpha_dfactor;
flush();
- glBlendFuncSeparateEXT(sGLBlendFactor[color_sfactor], sGLBlendFactor[color_dfactor],
- sGLBlendFactor[alpha_sfactor], sGLBlendFactor[alpha_dfactor]);
+
+ glBlendFuncSeparate(sGLBlendFactor[color_sfactor], sGLBlendFactor[color_dfactor],
+ sGLBlendFactor[alpha_sfactor], sGLBlendFactor[alpha_dfactor]);
}
}
@@ -1599,6 +1598,7 @@ void LLRender::flush()
if (mCount > 0)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
+ llassert(LLGLSLShader::sCurBoundShaderPtr != nullptr);
if (!mUIOffset.empty())
{
sUICalls++;
@@ -1639,24 +1639,108 @@ void LLRender::flush()
if (mBuffer)
{
- if (mBuffer->useVBOs() && !mBuffer->isLocked())
- { //hack to only flush the part of the buffer that was updated (relies on stream draw using buffersubdata)
- mBuffer->getVertexStrider(mVerticesp, 0, count);
- mBuffer->getTexCoord0Strider(mTexcoordsp, 0, count);
- mBuffer->getColorStrider(mColorsp, 0, count);
+
+ HBXXH64 hash;
+ U32 attribute_mask = LLGLSLShader::sCurBoundShaderPtr->mAttributeMask;
+
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vb cache hash");
+
+ hash.update((U8*)mVerticesp.get(), count * sizeof(LLVector4a));
+ if (attribute_mask & LLVertexBuffer::MAP_TEXCOORD0)
+ {
+ hash.update((U8*)mTexcoordsp.get(), count * sizeof(LLVector2));
+ }
+
+ if (attribute_mask & LLVertexBuffer::MAP_COLOR)
+ {
+ hash.update((U8*)mColorsp.get(), count * sizeof(LLColor4U));
+ }
+
+ hash.finalize();
+ }
+
+
+ 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
+ // that was built on top of OpenGL immediate mode. Huge performance wins
+ // can be had by not uploading geometry to VRAM unless absolutely necessary.
+ // Most of our usage of the "immediate mode" style draw calls is actually
+ // sending the same geometry over and over again.
+ // 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<U64, LLVBCache>::iterator cache = sVBCache.find(vhash);
+
+ LLPointer<LLVertexBuffer> vb;
+
+ if (cache != sVBCache.end())
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vb cache hit");
+ // cache hit, just use the cached buffer
+ vb = cache->second.vb;
+ cache->second.touched = std::chrono::steady_clock::now();
+ }
+ else
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vb cache miss");
+ vb = new LLVertexBuffer(attribute_mask);
+ vb->allocateBuffer(count, 0);
+
+ vb->setBuffer();
+
+ vb->setPositionData((LLVector4a*) mVerticesp.get());
+
+ if (attribute_mask & LLVertexBuffer::MAP_TEXCOORD0)
+ {
+ vb->setTexCoordData(mTexcoordsp.get());
+ }
+
+ if (attribute_mask & LLVertexBuffer::MAP_COLOR)
+ {
+ vb->setColorData(mColorsp.get());
+ }
+
+ vb->unbind();
+
+ sVBCache[vhash] = { vb , std::chrono::steady_clock::now() };
+
+ static U32 miss_count = 0;
+ miss_count++;
+ if (miss_count > 1024)
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vb cache clean");
+ miss_count = 0;
+ auto now = std::chrono::steady_clock::now();
+
+ 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<U64, LLVBCache>::iterator iter = sVBCache.begin(); iter != sVBCache.end(); )
+ {
+ if (now - iter->second.touched > 1s)
+ {
+ iter = sVBCache.erase(iter);
+ }
+ else
+ {
+ ++iter;
+ }
+ }
+ }
}
- mBuffer->flush();
- mBuffer->setBuffer(immediate_mask);
+ vb->setBuffer();
if (mMode == LLRender::QUADS && sGLCoreProfile)
{
- mBuffer->drawArrays(LLRender::TRIANGLES, 0, count);
+ vb->drawArrays(LLRender::TRIANGLES, 0, count);
mQuadCycle = 1;
}
else
{
- mBuffer->drawArrays(mMode, 0, count);
+ vb->drawArrays(mMode, 0, count);
}
}
else
@@ -1948,8 +2032,7 @@ void LLRender::texCoord2fv(const GLfloat* tc)
void LLRender::color4ub(const GLubyte& r, const GLubyte& g, const GLubyte& b, const GLubyte& a)
{
- if (!LLGLSLShader::sCurBoundShaderPtr ||
- LLGLSLShader::sCurBoundShaderPtr->mAttributeMask & LLVertexBuffer::MAP_COLOR)
+ if (!LLGLSLShader::sCurBoundShaderPtr || LLGLSLShader::sCurBoundShaderPtr->mAttributeMask & LLVertexBuffer::MAP_COLOR)
{
mColorsp[mCount] = LLColor4U(r,g,b,a);
}
diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h
index 9c36c230fb..e8baf6bb7e 100644
--- a/indra/llrender/llrender.h
+++ b/indra/llrender/llrender.h
@@ -52,7 +52,7 @@ class LLTexture ;
#define LL_MATRIX_STACK_DEPTH 32
-class LLTexUnit
+class LLTexUnit
{
friend class LLRender;
public:
@@ -63,6 +63,7 @@ public:
TT_TEXTURE = 0, // Standard 2D Texture
TT_RECT_TEXTURE, // Non power of 2 texture
TT_CUBE_MAP, // 6-sided cube map texture
+ TT_CUBE_MAP_ARRAY, // Array of cube maps
TT_MULTISAMPLE_TEXTURE, // see GL_ARB_texture_multisample
TT_TEXTURE_3D, // standard 3D Texture
TT_NONE, // No texture type is currently enabled
@@ -245,6 +246,8 @@ public:
void setSpotCutoff(const F32& cutoff);
void setSpotDirection(const LLVector3& direction);
void setSunPrimary(bool v);
+ void setSize(F32 size);
+ void setFalloff(F32 falloff);
protected:
friend class LLRender;
@@ -265,6 +268,8 @@ protected:
F32 mSpotExponent;
F32 mSpotCutoff;
+ F32 mSize = 0.f;
+ F32 mFalloff = 0.f;
};
class LLRender
@@ -272,7 +277,7 @@ class LLRender
friend class LLTexUnit;
public:
- enum eTexIndex
+ enum eTexIndex : U8
{
DIFFUSE_MAP = 0,
ALTERNATE_DIFFUSE_MAP = 1,
@@ -281,14 +286,15 @@ public:
NUM_TEXTURE_CHANNELS = 3,
};
- enum eVolumeTexIndex
+ enum eVolumeTexIndex : U8
{
LIGHT_TEX = 0,
SCULPT_TEX,
NUM_VOLUME_TEXTURE_CHANNELS,
};
- typedef enum {
+ enum eGeomModes : U8
+ {
TRIANGLES = 0,
TRIANGLE_STRIP,
TRIANGLE_FAN,
@@ -298,9 +304,9 @@ public:
QUADS,
LINE_LOOP,
NUM_MODES
- } eGeomModes;
+ };
- typedef enum
+ enum eCompareFunc : U8
{
CF_NEVER = 0,
CF_ALWAYS,
@@ -311,9 +317,9 @@ public:
CF_GREATER_EQUAL,
CF_GREATER,
CF_DEFAULT
- } eCompareFunc;
+ };
- typedef enum
+ enum eBlendType : U8
{
BT_ALPHA = 0,
BT_ADD,
@@ -322,25 +328,26 @@ public:
BT_MULT_ALPHA,
BT_MULT_X2,
BT_REPLACE
- } eBlendType;
+ };
- typedef enum
+ // WARNING: this MUST match the LL_PART_BF enum in LLPartData, so set values explicitly in case someone
+ // decides to add more or reorder them
+ enum eBlendFactor : U8
{
BF_ONE = 0,
- BF_ZERO,
- BF_DEST_COLOR,
- BF_SOURCE_COLOR,
- BF_ONE_MINUS_DEST_COLOR,
- BF_ONE_MINUS_SOURCE_COLOR,
- BF_DEST_ALPHA,
- BF_SOURCE_ALPHA,
- BF_ONE_MINUS_DEST_ALPHA,
- BF_ONE_MINUS_SOURCE_ALPHA,
-
+ BF_ZERO = 1,
+ BF_DEST_COLOR = 2,
+ BF_SOURCE_COLOR = 3,
+ BF_ONE_MINUS_DEST_COLOR = 4,
+ BF_ONE_MINUS_SOURCE_COLOR = 5,
+ BF_DEST_ALPHA = 6,
+ BF_SOURCE_ALPHA = 7,
+ BF_ONE_MINUS_DEST_ALPHA = 8,
+ BF_ONE_MINUS_SOURCE_ALPHA = 9,
BF_UNDEF
- } eBlendFactor;
+ };
- typedef enum
+ enum eMatrixMode : U8
{
MM_MODELVIEW = 0,
MM_PROJECTION,
@@ -350,7 +357,7 @@ public:
MM_TEXTURE3,
NUM_MATRIX_MODES,
MM_TEXTURE
- } eMatrixMode;
+ };
LLRender();
~LLRender();
@@ -490,8 +497,6 @@ private:
eBlendFactor mCurrBlendAlphaSFactor;
eBlendFactor mCurrBlendAlphaDFactor;
- F32 mMaxAnisotropy;
-
std::vector<LLVector3> mUIOffset;
std::vector<LLVector3> mUIScale;
@@ -502,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/llrender2dutils.cpp b/indra/llrender/llrender2dutils.cpp
index 5cb1dc6b25..3d32d3ca31 100644
--- a/indra/llrender/llrender2dutils.cpp
+++ b/indra/llrender/llrender2dutils.cpp
@@ -1516,7 +1516,15 @@ void LLRender2D::loadIdentity()
void LLRender2D::setLineWidth(F32 width)
{
gGL.flush();
- glLineWidth(width * lerp(LLRender::sUIGLScaleFactor.mV[VX], LLRender::sUIGLScaleFactor.mV[VY], 0.5f));
+ // If outside the allowed range, glLineWidth fails with "invalid value".
+ // On Darwin, the range is [1, 1].
+ static GLfloat range[2]{0.0};
+ if (range[1] == 0)
+ {
+ glGetFloatv(GL_SMOOTH_LINE_WIDTH_RANGE, range);
+ }
+ width *= lerp(LLRender::sUIGLScaleFactor.mV[VX], LLRender::sUIGLScaleFactor.mV[VY], 0.5f);
+ glLineWidth(llclamp(width, range[0], range[1]));
}
LLPointer<LLUIImage> LLRender2D::getUIImageByID(const LLUUID& image_id, S32 priority)
diff --git a/indra/llrender/llrendernavprim.cpp b/indra/llrender/llrendernavprim.cpp
index ca72964832..d610a44bc6 100644
--- a/indra/llrender/llrendernavprim.cpp
+++ b/indra/llrender/llrendernavprim.cpp
@@ -53,7 +53,7 @@ void LLRenderNavPrim::renderLLTri( const LLVector3& a, const LLVector3& b, const
//=============================================================================
void LLRenderNavPrim::renderNavMeshVB( U32 mode, LLVertexBuffer* pVBO, int vertCnt )
{
- pVBO->setBuffer( LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_NORMAL );
+ pVBO->setBuffer();
pVBO->drawArrays( mode, 0, vertCnt );
}
//=============================================================================
diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp
index fffc15efc3..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,114 +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),
- mStencil(0),
- mUseDepth(false),
- mRenderDepth(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;
-
- 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;
- }
-
- if (mDepth)
- { //resize depth attachment
- if (mStencil)
- {
- //use render buffers where stencil buffers are in play
- glBindRenderbuffer(GL_RENDERBUFFER, mDepth);
- glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 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);
- }
-
- sBytesAllocated += pix_diff*4;
- }
+ //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());
+
+ 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)
+ {
+ 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;
+ }
}
-
+
-bool LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo, S32 samples)
+bool LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, LLTexUnit::eTextureType usage)
{
- resx = llmin(resx, (U32) gGLManager.mGLMaxTextureSize);
- resy = llmin(resy, (U32) gGLManager.mGLMaxTextureSize);
-
- stop_glerror();
- release();
- stop_glerror();
-
- mResX = resx;
- mResY = resy;
-
- mStencil = stencil;
- mUsage = usage;
- mUseDepth = depth;
-
- 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);
-
- if (mDepth)
- {
- glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
- if (mStencil)
- {
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mDepth);
- stop_glerror();
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, mDepth);
- stop_glerror();
- }
- else
- {
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), mDepth, 0);
- stop_glerror();
- }
- glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
- }
-
- stop_glerror();
- }
-
- return addColorAttachment(color_fmt);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+ llassert(usage == LLTexUnit::TT_TEXTURE);
+ llassert(!isBoundInStack());
+
+ resx = llmin(resx, (U32) gGLManager.mGLMaxTextureSize);
+ resy = llmin(resy, (U32) gGLManager.mGLMaxTextureSize);
+
+ release();
+
+ mResX = resx;
+ mResY = resy;
+
+ mUsage = usage;
+ mUseDepth = depth;
+
+ if (depth)
+ {
+ if (!allocateDepth())
+ {
+ LL_WARNS() << "Failed to allocate depth buffer for render target." << LL_ENDL;
+ return false;
+ }
+ }
+
+ glGenFramebuffers(1, (GLuint *) &mFBO);
+
+ if (mDepth)
+ {
+ glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
+
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), mDepth, 0);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
+ }
+
+ return addColorAttachment(color_fmt);
}
void LLRenderTarget::setColorAttachment(LLImageGL* img, LLGLuint use_name)
@@ -177,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)
{
@@ -207,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
@@ -219,335 +193,292 @@ void LLRenderTarget::releaseColorAttachment()
bool LLRenderTarget::addColorAttachment(U32 color_fmt)
{
- if (color_fmt == 0)
- {
- return true;
- }
-
- U32 offset = mTex.size();
-
- if( offset >= 4 )
- {
- LL_WARNS() << "Too many color attachments" << LL_ENDL;
- llassert( offset < 4 );
- return false;
- }
- if( offset > 0 && (mFBO == 0 || !gGLManager.mHasDrawBuffers) )
- {
- LL_WARNS() << "FBO not used or no drawbuffers available; mFBO=" << (U32)mFBO << " gGLManager.mHasDrawBuffers=" << (U32)gGLManager.mHasDrawBuffers << LL_ENDL;
- llassert( mFBO != 0 );
- llassert( gGLManager.mHasDrawBuffers );
- return false;
- }
-
- 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;
-
- 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();
-
- check_framebuffer_status();
-
- glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
- }
-
- mTex.push_back(tex);
- mInternalFormat.push_back(color_fmt);
-
-#if !LL_DARWIN
- if (gDebugGL)
- { //bind and unbind to validate target
- bindTarget();
- flush();
- }
-#endif
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+ llassert(!isBoundInStack());
+
+ if (color_fmt == 0)
+ {
+ return true;
+ }
+
+ U32 offset = mTex.size();
+
+ 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 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;
+
+ stop_glerror();
+
- return true;
+ 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)
+ {
+ glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+offset,
+ LLTexUnit::getInternalType(mUsage), tex, 0);
+
+ check_framebuffer_status();
+
+ glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
+ }
+
+ mTex.push_back(tex);
+ mInternalFormat.push_back(color_fmt);
+
+ if (gDebugGL)
+ { //bind and unbind to validate target
+ bindTarget();
+ flush();
+ }
+
+
+ return true;
}
bool LLRenderTarget::allocateDepth()
{
- if (mStencil)
- {
- //use render buffers where stencil buffers are in play
- glGenRenderbuffers(1, (GLuint *) &mDepth);
- glBindRenderbuffer(GL_RENDERBUFFER, mDepth);
- stop_glerror();
- clear_glerror();
- glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 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);
- }
-
- sBytesAllocated += mResX*mResY*4;
-
- if (glGetError() != GL_NO_ERROR)
- {
- LL_WARNS() << "Unable to allocate depth buffer for render target." << LL_ENDL;
- return false;
- }
-
- return true;
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+ 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;
+
+ if (glGetError() != GL_NO_ERROR)
+ {
+ LL_WARNS() << "Unable to allocate depth buffer for render target." << LL_ENDL;
+ return false;
+ }
+
+ return true;
}
void LLRenderTarget::shareDepthBuffer(LLRenderTarget& target)
{
- if (!mFBO || !target.mFBO)
- {
- LL_ERRS() << "Cannot share depth buffer between non FBO render targets." << LL_ENDL;
- }
-
- if (target.mDepth)
- {
- LL_ERRS() << "Attempting to override existing depth buffer. Detach existing buffer first." << LL_ENDL;
- }
-
- if (target.mUseDepth)
- {
- LL_ERRS() << "Attempting to override existing shared depth buffer. Detach existing buffer first." << LL_ENDL;
- }
-
- if (mDepth)
- {
- stop_glerror();
- glBindFramebuffer(GL_FRAMEBUFFER, target.mFBO);
- stop_glerror();
-
- if (mStencil)
- {
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mDepth);
- stop_glerror();
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, mDepth);
- stop_glerror();
- target.mStencil = true;
- }
- else
- {
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), mDepth, 0);
- stop_glerror();
- }
-
- check_framebuffer_status();
-
- glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
-
- target.mUseDepth = true;
- }
+ llassert(!isBoundInStack());
+
+ if (!mFBO || !target.mFBO)
+ {
+ LL_ERRS() << "Cannot share depth buffer between non FBO render targets." << LL_ENDL;
+ }
+
+ if (target.mDepth)
+ {
+ LL_ERRS() << "Attempting to override existing depth buffer. Detach existing buffer first." << LL_ENDL;
+ }
+
+ if (target.mUseDepth)
+ {
+ LL_ERRS() << "Attempting to override existing shared depth buffer. Detach existing buffer first." << LL_ENDL;
+ }
+
+ if (mDepth)
+ {
+ glBindFramebuffer(GL_FRAMEBUFFER, target.mFBO);
+
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), mDepth, 0);
+
+ check_framebuffer_status();
+
+ glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
+
+ target.mUseDepth = true;
+ }
}
void LLRenderTarget::release()
{
- if (mDepth)
- {
- if (mStencil)
- {
- glDeleteRenderbuffers(1, (GLuint*) &mDepth);
- stop_glerror();
- }
- else
- {
- LLImageGL::deleteTextures(1, &mDepth);
- stop_glerror();
- }
- mDepth = 0;
-
- sBytesAllocated -= mResX*mResY*4;
- }
- else if (mFBO)
- {
- glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
-
- if (mUseDepth)
- { //detach shared depth buffer
- if (mStencil)
- { //attached as a renderbuffer
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0);
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
- mStencil = false;
- }
- else
- { //attached as a texture
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), 0, 0);
- }
- mUseDepth = false;
- }
- }
-
- // 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 (mFBO)
- {
- glDeleteFramebuffers(1, (GLuint *) &mFBO);
- stop_glerror();
- mFBO = 0;
- }
-
- if (mTex.size() > 0)
- {
- sBytesAllocated -= mResX*mResY*4;
- LLImageGL::deleteTextures(1, &mTex[0]);
- }
-
- mTex.clear();
- mInternalFormat.clear();
-
- mResX = mResY = 0;
-
- sBoundTarget = NULL;
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+ llassert(!isBoundInStack());
+
+ if (mDepth)
+ {
+ LLImageGL::deleteTextures(1, &mDepth);
+
+ mDepth = 0;
+
+ sBytesAllocated -= mResX*mResY*4;
+ }
+ else if (mFBO)
+ {
+ glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
+
+ if (mUseDepth)
+ { //detach shared depth buffer
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), 0, 0);
+ mUseDepth = false;
+ }
+
+ glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
+ }
+
+ // 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);
+ }
+
+ if (mFBO == sCurFBO)
+ {
+ sCurFBO = 0;
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ }
+
+ 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()
{
- if (mFBO)
- {
- stop_glerror();
-
- mPreviousFBO = sCurFBO;
- glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
- sCurFBO = mFBO;
-
- stop_glerror();
- if (gGLManager.mHasDrawBuffers)
- { //setup multiple render targets
- GLenum drawbuffers[] = {GL_COLOR_ATTACHMENT0,
- GL_COLOR_ATTACHMENT1,
- GL_COLOR_ATTACHMENT2,
- GL_COLOR_ATTACHMENT3};
- LL_PROFILER_GPU_ZONEC( "gl.DrawBuffersARB", 0x4000FF )
- glDrawBuffersARB(mTex.size(), drawbuffers);
- }
-
- if (mTex.empty())
- { //no color buffer to draw to
- LL_PROFILER_GPU_ZONEC( "gl.DrawBuffer", 0x0000FF )
- glDrawBuffer(GL_NONE);
- glReadBuffer(GL_NONE);
- }
-
- check_framebuffer_status();
-
- stop_glerror();
- }
-
- mPreviousResX = sCurResX;
- mPreviousResY = sCurResY;
- glViewport(0, 0, mResX, mResY);
- sCurResX = mResX;
- sCurResY = mResY;
-
- sBoundTarget = this;
+ LL_PROFILE_GPU_ZONE("bindTarget");
+ llassert(mFBO);
+ llassert(!isBoundInStack());
+
+ glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
+ sCurFBO = mFBO;
+
+ //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();
+
+ glViewport(0, 0, mResX, mResY);
+ sCurResX = mResX;
+ sCurResY = mResY;
+
+ mPreviousRT = sBoundTarget;
+ sBoundTarget = this;
}
void LLRenderTarget::clear(U32 mask_in)
{
- U32 mask = GL_COLOR_BUFFER_BIT;
- if (mUseDepth)
- {
- mask |= GL_DEPTH_BUFFER_BIT | GL_STENCIL_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);
- }
+ LL_PROFILE_GPU_ZONE("clear");
+ llassert(mFBO);
+ 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);
+ }
}
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)
@@ -573,137 +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)
-{
- gGL.flush();
- if (!mFBO)
- {
- gGL.getTexUnit(0)->bind(this);
- glCopyTexSubImage2D(LLTexUnit::getInternalType(mUsage), 0, 0, 0, 0, 0, mResX, mResY);
-
- 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();
- }
-}
-
-void LLRenderTarget::copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 srcX1, S32 srcY1,
- S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter)
+void LLRenderTarget::flush()
{
- GLboolean write_depth = mask & GL_DEPTH_BUFFER_BIT ? TRUE : FALSE;
-
- LLGLDepthTest depth(write_depth, write_depth);
-
- gGL.flush();
- if (!source.mFBO || !mFBO)
- {
- LL_WARNS() << "Cannot copy framebuffer contents for non FBO render targets." << LL_ENDL;
- return;
- }
-
-
- if (mask == GL_DEPTH_BUFFER_BIT && source.mStencil != mStencil)
- {
- stop_glerror();
-
- glBindFramebuffer(GL_FRAMEBUFFER, source.mFBO);
- check_framebuffer_status();
- gGL.getTexUnit(0)->bind(this, true);
- stop_glerror();
- glCopyTexSubImage2D(LLTexUnit::getInternalType(mUsage), 0, srcX0, srcY0, dstX0, dstY0, dstX1, dstY1);
- stop_glerror();
- glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
- stop_glerror();
- }
- else
- {
- glBindFramebuffer(GL_READ_FRAMEBUFFER, source.mFBO);
- stop_glerror();
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFBO);
- stop_glerror();
- check_framebuffer_status();
- stop_glerror();
- glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
- stop_glerror();
- glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
- stop_glerror();
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
- stop_glerror();
- glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
- stop_glerror();
- }
-}
+ LL_PROFILE_GPU_ZONE("rt flush");
+ gGL.flush();
+ llassert(mFBO);
+ llassert(sCurFBO == mFBO);
+ llassert(sBoundTarget == this);
-//static
-void LLRenderTarget::copyContentsToFramebuffer(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 srcX1, S32 srcY1,
- S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter)
-{
- if (!source.mFBO)
- {
- LL_WARNS() << "Cannot copy framebuffer contents for non FBO render targets." << LL_ENDL;
- return;
- }
-
- {
- GLboolean write_depth = mask & GL_DEPTH_BUFFER_BIT ? TRUE : FALSE;
-
- LLGLDepthTest depth(write_depth, write_depth);
-
- glBindFramebuffer(GL_READ_FRAMEBUFFER, source.mFBO);
- stop_glerror();
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
- stop_glerror();
- check_framebuffer_status();
- stop_glerror();
- glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
- stop_glerror();
- glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
- 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 584f224dca..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 stencil, 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 hasStencil() const { return mStencil; }
void bindTexture(U32 index, S32 channel, LLTexUnit::eTextureFilterOptions filter_options = LLTexUnit::TFO_BILINEAR);
@@ -144,21 +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);
-
- void copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 srcX1, S32 srcY1,
- S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter);
-
- static void copyContentsToFramebuffer(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 srcX1, S32 srcY1,
- S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter);
+ // 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:
@@ -167,14 +175,11 @@ protected:
std::vector<U32> mTex;
std::vector<U32> mInternalFormat;
U32 mFBO;
- U32 mPreviousFBO;
- U32 mPreviousResX;
- U32 mPreviousResY;
-
- U32 mDepth;
- bool mStencil;
- bool mUseDepth;
- bool mRenderDepth;
+ LLRenderTarget* mPreviousRT = nullptr;
+
+ U32 mDepth;
+ bool mUseDepth;
+
LLTexUnit::eTextureType mUsage;
static LLRenderTarget* sBoundTarget;
diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp
index c64f46f38a..6e3d89eedc 100644
--- a/indra/llrender/llshadermgr.cpp
+++ b/indra/llrender/llshadermgr.cpp
@@ -145,6 +145,11 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
// NOTE order of shader object attaching is VERY IMPORTANT!!!
if (features->calculatesAtmospherics)
{
+ if (!shader->attachVertexObject("environment/srgbF.glsl")) // NOTE -- "F" suffix is superfluous here, there is nothing fragment specific in srgbF
+ {
+ return FALSE;
+ }
+
if (!shader->attachVertexObject("windlight/atmosphericsFuncs.glsl")) {
return FALSE;
}
@@ -177,8 +182,15 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
///////////////////////////////////////
// NOTE order of shader object attaching is VERY IMPORTANT!!!
+ if (features->hasSrgb || features->hasAtmospherics || features->calculatesAtmospherics)
+ {
+ if (!shader->attachFragmentObject("environment/srgbF.glsl"))
+ {
+ return FALSE;
+ }
+ }
- if(features->calculatesAtmospherics)
+ if(features->calculatesAtmospherics || features->hasGamma || features->isDeferred)
{
if (features->hasWaterFog)
{
@@ -202,7 +214,7 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
}
// we want this BEFORE shadows and AO because those facilities use pos/norm access
- if (features->isDeferred)
+ if (features->isDeferred || features->hasReflectionProbes)
{
if (!shader->attachFragmentObject("deferred/deferredUtil.glsl"))
{
@@ -210,6 +222,14 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
}
}
+ if (features->hasScreenSpaceReflections || features->hasReflectionProbes)
+ {
+ if (!shader->attachFragmentObject("deferred/screenSpaceReflUtil.glsl"))
+ {
+ return FALSE;
+ }
+ }
+
if (features->hasShadows)
{
if (!shader->attachFragmentObject("deferred/shadowUtil.glsl"))
@@ -218,6 +238,14 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
}
}
+ if (features->hasReflectionProbes)
+ {
+ if (!shader->attachFragmentObject("deferred/reflectionProbeF.glsl"))
+ {
+ return FALSE;
+ }
+ }
+
if (features->hasAmbientOcclusion)
{
if (!shader->attachFragmentObject("deferred/aoUtil.glsl"))
@@ -234,7 +262,7 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
}
}
- if (features->hasGamma)
+ if (features->hasGamma || features->isDeferred)
{
if (!shader->attachFragmentObject("windlight/gammaF.glsl"))
{
@@ -242,14 +270,6 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
}
}
- if (features->hasSrgb)
- {
- if (!shader->attachFragmentObject("environment/srgbF.glsl"))
- {
- return FALSE;
- }
- }
-
if (features->encodesNormal)
{
if (!shader->attachFragmentObject("environment/encodeNormF.glsl"))
@@ -258,7 +278,7 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
}
}
- if (features->hasAtmospherics)
+ if (features->hasAtmospherics || features->isDeferred)
{
if (!shader->attachFragmentObject("windlight/atmosphericsFuncs.glsl")) {
return FALSE;
@@ -550,26 +570,60 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
//============================================================================
// Load Shader
-static std::string get_object_log(GLhandleARB ret)
+static std::string get_shader_log(GLuint ret)
{
std::string res;
//get log length
GLint length;
- glGetObjectParameterivARB(ret, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
+ glGetShaderiv(ret, GL_INFO_LOG_LENGTH, &length);
if (length > 0)
{
//the log could be any size, so allocate appropriately
- GLcharARB* log = new GLcharARB[length];
- glGetInfoLogARB(ret, length, &length, log);
+ GLchar* log = new GLchar[length];
+ glGetShaderInfoLog(ret, length, &length, log);
res = std::string((char *)log);
delete[] log;
}
return res;
}
+static std::string get_program_log(GLuint ret)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ std::string res;
+
+ //get log length
+ GLint length;
+ glGetProgramiv(ret, GL_INFO_LOG_LENGTH, &length);
+ if (length > 0)
+ {
+ //the log could be any size, so allocate appropriately
+ GLchar* log = new GLchar[length];
+ glGetProgramInfoLog(ret, length, &length, log);
+ res = std::string((char*)log);
+ delete[] log;
+ }
+ return res;
+}
+
+// get the info log for the given object, be it a shader or program object
+// NOTE: ret MUST be a shader OR a program object
+static std::string get_object_log(GLuint ret)
+{
+ if (glIsProgram(ret))
+ {
+ return get_program_log(ret);
+ }
+ else
+ {
+ llassert(glIsShader(ret));
+ return get_shader_log(ret);
+ }
+}
+
//dump shader source for debugging
-void LLShaderMgr::dumpShaderSource(U32 shader_code_count, GLcharARB** shader_code_text)
+void LLShaderMgr::dumpShaderSource(U32 shader_code_count, GLchar** shader_code_text)
{
char num_str[16]; // U32 = max 10 digits
@@ -584,9 +638,10 @@ void LLShaderMgr::dumpShaderSource(U32 shader_code_count, GLcharARB** shader_cod
LL_CONT << LL_ENDL;
}
-void LLShaderMgr::dumpObjectLog(GLhandleARB ret, BOOL warns, const std::string& filename)
+void LLShaderMgr::dumpObjectLog(GLuint ret, BOOL warns, const std::string& filename)
{
- std::string log = get_object_log(ret);
+ std::string log;
+ log = get_object_log(ret);
std::string fname = filename;
if (filename.empty())
{
@@ -600,7 +655,7 @@ void LLShaderMgr::dumpObjectLog(GLhandleARB ret, BOOL warns, const std::string&
}
}
-GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, std::unordered_map<std::string, std::string>* defines, S32 texture_index_channels)
+GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, std::unordered_map<std::string, std::string>* defines, S32 texture_index_channels)
{
// endsure work-around for missing GLSL funcs gets propogated to feature shader files (e.g. srgbF.glsl)
@@ -671,9 +726,9 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
//we can't have any lines longer than 1024 characters
//or any shaders longer than 4096 lines... deal - DaveP
- GLcharARB buff[1024];
- GLcharARB *extra_code_text[1024];
- GLcharARB *shader_code_text[4096 + LL_ARRAY_SIZE(extra_code_text)] = { NULL };
+ GLchar buff[1024];
+ GLchar *extra_code_text[1024];
+ GLchar *shader_code_text[4096 + LL_ARRAY_SIZE(extra_code_text)] = { NULL };
GLuint extra_code_count = 0, shader_code_count = 0;
BOOST_STATIC_ASSERT(LL_ARRAY_SIZE(extra_code_text) < LL_ARRAY_SIZE(shader_code_text));
@@ -712,8 +767,15 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
{
if (major_version >= 4)
{
- //set version to 400
- shader_code_text[shader_code_count++] = strdup("#version 400\n");
+ //set version to 400 or 420
+ if (minor_version >= 20)
+ {
+ shader_code_text[shader_code_count++] = strdup("#version 420\n");
+ }
+ else
+ {
+ shader_code_text[shader_code_count++] = strdup("#version 400\n");
+ }
}
else if (major_version == 3)
{
@@ -748,7 +810,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
extra_code_text[extra_code_count++] = strdup("#define ATTRIBUTE in\n");
- if (type == GL_VERTEX_SHADER_ARB)
+ if (type == GL_VERTEX_SHADER)
{ //"varying" state is "out" in a vertex program, "in" in a fragment program
// ("varying" is deprecated after version 1.20)
extra_code_text[extra_code_count++] = strdup("#define VARYING out\n");
@@ -772,13 +834,20 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
extra_code_text[extra_code_count++] = strdup("#define shadow2DRect(a,b) vec2(texture(a,b))\n");
}
}
-
+
+ // Use alpha float to store bit flags
+ // See: C++: addDeferredAttachment(), shader: frag_data[2]
+ extra_code_text[extra_code_count++] = strdup("#define GBUFFER_FLAG_SKIP_ATMOS 0.0 \n"); // atmo kill
+ extra_code_text[extra_code_count++] = strdup("#define GBUFFER_FLAG_HAS_ATMOS 0.34\n"); // bit 0
+ extra_code_text[extra_code_count++] = strdup("#define GBUFFER_FLAG_HAS_PBR 0.67\n"); // bit 1
+ extra_code_text[extra_code_count++] = strdup("#define GET_GBUFFER_FLAG(flag) (abs(norm.w-flag)< 0.1)\n");
+
if (defines)
{
for (std::unordered_map<std::string,std::string>::iterator iter = defines->begin(); iter != defines->end(); ++iter)
{
std::string define = "#define " + iter->first + " " + iter->second + "\n";
- extra_code_text[extra_code_count++] = (GLcharARB *) strdup(define.c_str());
+ extra_code_text[extra_code_count++] = (GLchar *) strdup(define.c_str());
}
}
@@ -787,7 +856,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
extra_code_text[extra_code_count++] = strdup( "#define IS_AMD_CARD 1\n" );
}
- if (texture_index_channels > 0 && type == GL_FRAGMENT_SHADER_ARB)
+ if (texture_index_channels > 0 && type == GL_FRAGMENT_SHADER)
{
//use specified number of texture channels for indexed texture rendering
@@ -927,7 +996,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
}
else
{
- shader_code_text[shader_code_count] = (GLcharARB *)strdup((char *)buff);
+ shader_code_text[shader_code_count] = (GLchar *)strdup((char *)buff);
if(flag_write_to_out_of_extra_block_area & flags)
{
@@ -964,40 +1033,40 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
fclose(file);
//create shader object
- GLhandleARB ret = glCreateShaderObjectARB(type);
+ GLuint ret = glCreateShader(type);
error = glGetError();
if (error != GL_NO_ERROR)
{
- LL_WARNS("ShaderLoading") << "GL ERROR in glCreateShaderObjectARB: " << error << " for file: " << open_file_name << LL_ENDL;
+ LL_WARNS("ShaderLoading") << "GL ERROR in glCreateShader: " << error << " for file: " << open_file_name << LL_ENDL;
}
//load source
- glShaderSourceARB(ret, shader_code_count, (const GLcharARB**) shader_code_text, NULL);
+ glShaderSource(ret, shader_code_count, (const GLchar**) shader_code_text, NULL);
error = glGetError();
if (error != GL_NO_ERROR)
{
- LL_WARNS("ShaderLoading") << "GL ERROR in glShaderSourceARB: " << error << " for file: " << open_file_name << LL_ENDL;
+ LL_WARNS("ShaderLoading") << "GL ERROR in glShaderSource: " << error << " for file: " << open_file_name << LL_ENDL;
}
//compile source
- glCompileShaderARB(ret);
+ glCompileShader(ret);
error = glGetError();
if (error != GL_NO_ERROR)
{
- LL_WARNS("ShaderLoading") << "GL ERROR in glCompileShaderARB: " << error << " for file: " << open_file_name << LL_ENDL;
+ LL_WARNS("ShaderLoading") << "GL ERROR in glCompileShader: " << error << " for file: " << open_file_name << LL_ENDL;
}
if (error == GL_NO_ERROR)
{
//check for errors
GLint success = GL_TRUE;
- glGetObjectParameterivARB(ret, GL_OBJECT_COMPILE_STATUS_ARB, &success);
+ glGetShaderiv(ret, GL_COMPILE_STATUS, &success);
error = glGetError();
- if (error != GL_NO_ERROR || success == GL_FALSE)
+ if (error != GL_NO_ERROR || success == GL_FALSE)
{
//an error occured, print log
LL_WARNS("ShaderLoading") << "GLSL Compilation Error:" << LL_ENDL;
@@ -1022,10 +1091,10 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
if (ret)
{
// Add shader file to map
- if (type == GL_VERTEX_SHADER_ARB) {
+ if (type == GL_VERTEX_SHADER) {
mVertexShaderObjects[filename] = ret;
}
- else if (type == GL_FRAGMENT_SHADER_ARB) {
+ else if (type == GL_FRAGMENT_SHADER) {
mFragmentShaderObjects[filename] = ret;
}
shader_level = try_gpu_class;
@@ -1042,19 +1111,29 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
return ret;
}
-BOOL LLShaderMgr::linkProgramObject(GLhandleARB obj, BOOL suppress_errors)
+BOOL LLShaderMgr::linkProgramObject(GLuint obj, BOOL suppress_errors)
{
//check for errors
- glLinkProgramARB(obj);
- GLint success = GL_TRUE;
- glGetObjectParameterivARB(obj, GL_OBJECT_LINK_STATUS_ARB, &success);
- if (!suppress_errors && success == GL_FALSE)
- {
- //an error occured, print log
- LL_SHADER_LOADING_WARNS() << "GLSL Linker Error:" << LL_ENDL;
- }
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_SHADER("glLinkProgram");
+ glLinkProgram(obj);
+ }
+
+ GLint success = GL_TRUE;
- std::string log = get_object_log(obj);
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_SHADER("glsl check link status");
+ glGetProgramiv(obj, GL_LINK_STATUS, &success);
+ if (!suppress_errors && success == GL_FALSE)
+ {
+ //an error occured, print log
+ LL_SHADER_LOADING_WARNS() << "GLSL Linker Error:" << LL_ENDL;
+ dumpObjectLog(obj, TRUE, "linker");
+ return success;
+ }
+ }
+
+ std::string log = get_program_log(obj);
LLStringUtil::toLower(log);
if (log.find("software") != std::string::npos)
{
@@ -1065,12 +1144,12 @@ BOOL LLShaderMgr::linkProgramObject(GLhandleARB obj, BOOL suppress_errors)
return success;
}
-BOOL LLShaderMgr::validateProgramObject(GLhandleARB obj)
+BOOL LLShaderMgr::validateProgramObject(GLuint obj)
{
//check program validity against current GL
- glValidateProgramARB(obj);
+ glValidateProgram(obj);
GLint success = GL_TRUE;
- glGetObjectParameterivARB(obj, GL_OBJECT_VALIDATE_STATUS_ARB, &success);
+ glGetProgramiv(obj, GL_LINK_STATUS, &success);
if (success == GL_FALSE)
{
LL_SHADER_LOADING_WARNS() << "GLSL program not valid: " << LL_ENDL;
@@ -1108,6 +1187,7 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("inv_proj");
mReservedUniforms.push_back("modelview_projection_matrix");
mReservedUniforms.push_back("inv_modelview");
+ mReservedUniforms.push_back("identity_matrix");
mReservedUniforms.push_back("normal_matrix");
mReservedUniforms.push_back("texture_matrix0");
mReservedUniforms.push_back("texture_matrix1");
@@ -1115,13 +1195,18 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("texture_matrix3");
mReservedUniforms.push_back("object_plane_s");
mReservedUniforms.push_back("object_plane_t");
- llassert(mReservedUniforms.size() == LLShaderMgr::OBJECT_PLANE_T+1);
+ mReservedUniforms.push_back("texture_basecolor_matrix"); // GLTF
+ mReservedUniforms.push_back("texture_normal_matrix"); // GLTF
+ mReservedUniforms.push_back("texture_metallic_roughness_matrix"); // GLTF
+ mReservedUniforms.push_back("texture_emissive_matrix"); // GLTF
+ llassert(mReservedUniforms.size() == LLShaderMgr::TEXTURE_EMISSIVE_MATRIX+1);
mReservedUniforms.push_back("viewport");
mReservedUniforms.push_back("light_position");
mReservedUniforms.push_back("light_direction");
mReservedUniforms.push_back("light_attenuation");
+ mReservedUniforms.push_back("light_deferred_attenuation");
mReservedUniforms.push_back("light_diffuse");
mReservedUniforms.push_back("light_ambient");
mReservedUniforms.push_back("light_count");
@@ -1148,13 +1233,21 @@ void LLShaderMgr::initAttribsAndUniforms()
llassert(mReservedUniforms.size() == LLShaderMgr::PROJECTOR_AMBIENT_LOD+1);
mReservedUniforms.push_back("color");
-
+ mReservedUniforms.push_back("emissiveColor");
+ mReservedUniforms.push_back("metallicFactor");
+ mReservedUniforms.push_back("roughnessFactor");
+
mReservedUniforms.push_back("diffuseMap");
mReservedUniforms.push_back("altDiffuseMap");
mReservedUniforms.push_back("specularMap");
+ mReservedUniforms.push_back("emissiveMap");
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");
mReservedUniforms.push_back("cloud_noise_texture_next");
mReservedUniforms.push_back("fullbright");
@@ -1162,9 +1255,12 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("sunlight_color");
mReservedUniforms.push_back("ambient_color");
mReservedUniforms.push_back("blue_horizon");
+ mReservedUniforms.push_back("blue_horizon_linear");
mReservedUniforms.push_back("blue_density");
+ mReservedUniforms.push_back("blue_density_linear");
mReservedUniforms.push_back("haze_horizon");
mReservedUniforms.push_back("haze_density");
+ mReservedUniforms.push_back("haze_density_linear");
mReservedUniforms.push_back("cloud_shadow");
mReservedUniforms.push_back("density_multiplier");
mReservedUniforms.push_back("distance_multiplier");
@@ -1201,6 +1297,7 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("minimum_alpha");
mReservedUniforms.push_back("emissive_brightness");
+ // Deferred
mReservedUniforms.push_back("shadow_matrix");
mReservedUniforms.push_back("env_mat");
mReservedUniforms.push_back("shadow_clip");
@@ -1228,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");
@@ -1256,6 +1357,8 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("positionMap");
mReservedUniforms.push_back("diffuseRect");
mReservedUniforms.push_back("specularRect");
+ mReservedUniforms.push_back("emissiveRect");
+ mReservedUniforms.push_back("brdfLut");
mReservedUniforms.push_back("noiseMap");
mReservedUniforms.push_back("lightFunc");
mReservedUniforms.push_back("lightMap");
@@ -1281,6 +1384,7 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("specular");
mReservedUniforms.push_back("lightExp");
mReservedUniforms.push_back("waterFogColor");
+ mReservedUniforms.push_back("waterFogColorLinear");
mReservedUniforms.push_back("waterFogDensity");
mReservedUniforms.push_back("waterFogKS");
mReservedUniforms.push_back("refScale");
@@ -1326,6 +1430,8 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("halo_map");
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");
@@ -1335,6 +1441,9 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("water_edge");
mReservedUniforms.push_back("sun_up_factor");
mReservedUniforms.push_back("moonlight_color");
+ mReservedUniforms.push_back("moonlight_linear");
+ mReservedUniforms.push_back("sunlight_linear");
+ mReservedUniforms.push_back("ambient_linear");
llassert(mReservedUniforms.size() == END_RESERVED_UNIFORMS);
diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h
index 67c0d6ab10..a224b2a19b 100644
--- a/indra/llrender/llshadermgr.h
+++ b/indra/llrender/llshadermgr.h
@@ -44,6 +44,7 @@ public:
INVERSE_PROJECTION_MATRIX, // "inv_proj"
MODELVIEW_PROJECTION_MATRIX, // "modelview_projection_matrix"
INVERSE_MODELVIEW_MATRIX, // "inv_modelview"
+ IDENTITY_MATRIX, // "identity_matrix"
NORMAL_MATRIX, // "normal_matrix"
TEXTURE_MATRIX0, // "texture_matrix0"
TEXTURE_MATRIX1, // "texture_matrix1"
@@ -51,10 +52,15 @@ public:
TEXTURE_MATRIX3, // "texture_matrix3"
OBJECT_PLANE_S, // "object_plane_s"
OBJECT_PLANE_T, // "object_plane_t"
+ TEXTURE_BASECOLOR_MATRIX, // "texture_basecolor_matrix" (GLTF)
+ TEXTURE_NORMAL_MATRIX, // "texture_normal_matrix" (GLTF)
+ TEXTURE_METALLIC_ROUGHNESS_MATRIX, // "texture_metallic_roughness_matrix" (GLTF)
+ TEXTURE_EMISSIVE_MATRIX, // "texture_emissive_matrix" (GLTF)
VIEWPORT, // "viewport"
LIGHT_POSITION, // "light_position"
LIGHT_DIRECTION, // "light_direction"
LIGHT_ATTENUATION, // "light_attenuation"
+ LIGHT_DEFERRED_ATTENUATION, // "light_deferred_attenuation"
LIGHT_DIFFUSE, // "light_diffuse"
LIGHT_AMBIENT, // "light_ambient"
MULTI_LIGHT_COUNT, // "light_count"
@@ -74,12 +80,20 @@ public:
PROJECTOR_LOD, // "proj_lod"
PROJECTOR_AMBIENT_LOD, // "proj_ambient_lod"
DIFFUSE_COLOR, // "color"
+ EMISSIVE_COLOR, // "emissiveColor"
+ METALLIC_FACTOR, // "metallicFactor"
+ ROUGHNESS_FACTOR, // "roughnessFactor"
DIFFUSE_MAP, // "diffuseMap"
ALTERNATE_DIFFUSE_MAP, // "altDiffuseMap"
SPECULAR_MAP, // "specularMap"
+ EMISSIVE_MAP, // "emissiveMap"
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"
CLOUD_NOISE_MAP_NEXT, // "cloud_noise_texture_next"
FULLBRIGHT, // "fullbright"
@@ -87,9 +101,12 @@ public:
SUNLIGHT_COLOR, // "sunlight_color"
AMBIENT, // "ambient_color"
BLUE_HORIZON, // "blue_horizon"
+ BLUE_HORIZON_LINEAR, // "blue_horizon_linear"
BLUE_DENSITY, // "blue_density"
+ BLUE_DENSITY_LINEAR, // "blue_density_linear"
HAZE_HORIZON, // "haze_horizon"
HAZE_DENSITY, // "haze_density"
+ HAZE_DENSITY_LINEAR, // "haze_density_linear"
CLOUD_SHADOW, // "cloud_shadow"
DENSITY_MULTIPLIER, // "density_multiplier"
DISTANCE_MULTIPLIER, // "distance_multiplier"
@@ -143,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"
@@ -168,6 +189,8 @@ public:
DEFERRED_POSITION, // "positionMap"
DEFERRED_DIFFUSE, // "diffuseRect"
DEFERRED_SPECULAR, // "specularRect"
+ DEFERRED_EMISSIVE, // "emissiveRect"
+ DEFERRED_BRDF_LUT, // "brdfLut"
DEFERRED_NOISE, // "noiseMap"
DEFERRED_LIGHTFUNC, // "lightFunc"
DEFERRED_LIGHT, // "lightMap"
@@ -192,6 +215,7 @@ public:
WATER_SPECULAR, // "specular"
WATER_SPECULAR_EXP, // "lightExp"
WATER_FOGCOLOR, // "waterFogColor"
+ WATER_FOGCOLOR_LINEAR, // "waterFogColorLinear"
WATER_FOGDENSITY, // "waterFogDensity"
WATER_FOGKS, // "waterFogKS"
WATER_REFSCALE, // "refScale"
@@ -242,6 +266,8 @@ 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"
@@ -250,6 +276,9 @@ public:
WATER_EDGE_FACTOR, // "water_edge"
SUN_UP_FACTOR, // "sun_up_factor"
MOONLIGHT_COLOR, // "moonlight_color"
+ MOONLIGHT_LINEAR, // "moonlight_LINEAR"
+ SUNLIGHT_LINEAR, // "sunlight_linear"
+ AMBIENT_LINEAR, // "ambient_linear"
END_RESERVED_UNIFORMS
} eGLSLReservedUniforms;
// clang-format on
@@ -260,11 +289,11 @@ public:
virtual void initAttribsAndUniforms(void);
BOOL attachShaderFeatures(LLGLSLShader * shader);
- void dumpObjectLog(GLhandleARB ret, BOOL warns = TRUE, const std::string& filename = "");
- void dumpShaderSource(U32 shader_code_count, GLcharARB** shader_code_text);
- BOOL linkProgramObject(GLhandleARB obj, BOOL suppress_errors = FALSE);
- BOOL validateProgramObject(GLhandleARB obj);
- GLhandleARB loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, std::unordered_map<std::string, std::string>* defines = NULL, S32 texture_index_channels = -1);
+ void dumpObjectLog(GLuint ret, BOOL warns = TRUE, const std::string& filename = "");
+ void dumpShaderSource(U32 shader_code_count, GLchar** shader_code_text);
+ BOOL linkProgramObject(GLuint obj, BOOL suppress_errors = FALSE);
+ BOOL validateProgramObject(GLuint obj);
+ GLuint loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, std::unordered_map<std::string, std::string>* defines = NULL, S32 texture_index_channels = -1);
// Implemented in the application to actually point to the shader directory.
virtual std::string getShaderDirPrefix(void) = 0; // Pure Virtual
@@ -274,8 +303,8 @@ public:
public:
// Map of shader names to compiled
- std::map<std::string, GLhandleARB> mVertexShaderObjects;
- std::map<std::string, GLhandleARB> mFragmentShaderObjects;
+ std::map<std::string, GLuint> mVertexShaderObjects;
+ std::map<std::string, GLuint> mFragmentShaderObjects;
//global (reserved slot) shader parameters
std::vector<std::string> mReservedAttribs;
diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp
index be3e6ddff0..11e2b6e5c4 100644
--- a/indra/llrender/llvertexbuffer.cpp
+++ b/indra/llrender/llvertexbuffer.cpp
@@ -62,288 +62,483 @@ U32 wpo2(U32 i)
return r;
}
+struct CompareMappedRegion
+{
+ bool operator()(const LLVertexBuffer::MappedRegion& lhs, const LLVertexBuffer::MappedRegion& rhs)
+ {
+ return lhs.mStart < rhs.mStart;
+ }
+};
-const U32 LL_VBO_BLOCK_SIZE = 2048;
-const U32 LL_VBO_POOL_MAX_SEED_SIZE = 256*1024;
+#define ENABLE_GL_WORK_QUEUE 0
-U32 vbo_block_size(U32 size)
-{ //what block size will fit size?
- U32 mod = size % LL_VBO_BLOCK_SIZE;
- return mod == 0 ? size : size + (LL_VBO_BLOCK_SIZE-mod);
-}
+#if ENABLE_GL_WORK_QUEUE
+
+#define THREAD_COUNT 1
+
+//============================================================================
-U32 vbo_block_index(U32 size)
+// High performance WorkQueue for usage in real-time rendering work
+class GLWorkQueue
{
- return vbo_block_size(size)/LL_VBO_BLOCK_SIZE;
-}
+public:
+ using Work = std::function<void()>;
-const U32 LL_VBO_POOL_SEED_COUNT = vbo_block_index(LL_VBO_POOL_MAX_SEED_SIZE);
+ GLWorkQueue();
+ void post(const Work& value);
-//============================================================================
+ size_t size();
-//static
-LLVBOPool LLVertexBuffer::sStreamVBOPool(GL_STREAM_DRAW_ARB, GL_ARRAY_BUFFER_ARB);
-LLVBOPool LLVertexBuffer::sDynamicVBOPool(GL_DYNAMIC_DRAW_ARB, GL_ARRAY_BUFFER_ARB);
-LLVBOPool LLVertexBuffer::sDynamicCopyVBOPool(GL_DYNAMIC_COPY_ARB, GL_ARRAY_BUFFER_ARB);
-LLVBOPool LLVertexBuffer::sStreamIBOPool(GL_STREAM_DRAW_ARB, GL_ELEMENT_ARRAY_BUFFER_ARB);
-LLVBOPool LLVertexBuffer::sDynamicIBOPool(GL_DYNAMIC_DRAW_ARB, GL_ELEMENT_ARRAY_BUFFER_ARB);
-
-U32 LLVBOPool::sBytesPooled = 0;
-U32 LLVBOPool::sIndexBytesPooled = 0;
-U32 LLVBOPool::sNameIdx = 0;
-U32 LLVBOPool::sNamePool[1024];
-
-std::list<U32> LLVertexBuffer::sAvailableVAOName;
-U32 LLVertexBuffer::sCurVAOName = 1;
-
-U32 LLVertexBuffer::sAllocatedIndexBytes = 0;
-U32 LLVertexBuffer::sIndexCount = 0;
-
-U32 LLVertexBuffer::sBindCount = 0;
-U32 LLVertexBuffer::sSetCount = 0;
-S32 LLVertexBuffer::sCount = 0;
-S32 LLVertexBuffer::sGLCount = 0;
-S32 LLVertexBuffer::sMappedCount = 0;
-bool LLVertexBuffer::sDisableVBOMapping = false;
-bool LLVertexBuffer::sEnableVBOs = true;
-U32 LLVertexBuffer::sGLRenderBuffer = 0;
-U32 LLVertexBuffer::sGLRenderArray = 0;
-U32 LLVertexBuffer::sGLRenderIndices = 0;
-U32 LLVertexBuffer::sLastMask = 0;
-bool LLVertexBuffer::sVBOActive = false;
-bool LLVertexBuffer::sIBOActive = false;
-U32 LLVertexBuffer::sAllocatedBytes = 0;
-U32 LLVertexBuffer::sVertexCount = 0;
-bool LLVertexBuffer::sMapped = false;
-bool LLVertexBuffer::sUseStreamDraw = true;
-bool LLVertexBuffer::sUseVAO = false;
-bool LLVertexBuffer::sPreferStreamDraw = false;
+ bool done();
+
+ // Get the next element from the queue
+ Work pop();
+
+ void runOne();
+
+ bool runPending();
+
+ void runUntilClose();
+
+ void close();
+
+ bool isClosed();
+ void syncGL();
-U32 LLVBOPool::genBuffer()
+private:
+ std::mutex mMutex;
+ std::condition_variable mCondition;
+ std::queue<Work> mQueue;
+ bool mClosed = false;
+};
+
+GLWorkQueue::GLWorkQueue()
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX
- if (sNameIdx == 0)
- {
- glGenBuffersARB(1024, sNamePool);
- sNameIdx = 1024;
- }
+}
+
+void GLWorkQueue::syncGL()
+{
+ /*if (mSync)
+ {
+ std::lock_guard<std::mutex> lock(mMutex);
+ glWaitSync(mSync, 0, GL_TIMEOUT_IGNORED);
+ mSync = 0;
+ }*/
+}
- return sNamePool[--sNameIdx];
+size_t GLWorkQueue::size()
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD;
+ std::lock_guard<std::mutex> lock(mMutex);
+ return mQueue.size();
}
-void LLVBOPool::deleteBuffer(U32 name)
+bool GLWorkQueue::done()
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX
- if (gGLManager.mInited)
- {
- LLVertexBuffer::unbind();
+ return size() == 0 && isClosed();
+}
- glBindBufferARB(mType, name);
- glBufferDataARB(mType, 0, NULL, mUsage);
- glBindBufferARB(mType, 0);
+void GLWorkQueue::post(const GLWorkQueue::Work& value)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD;
+ {
+ std::lock_guard<std::mutex> lock(mMutex);
+ mQueue.push(std::move(value));
+ }
- glDeleteBuffersARB(1, &name);
- }
+ mCondition.notify_one();
}
+// Get the next element from the queue
+GLWorkQueue::Work GLWorkQueue::pop()
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD;
+ // Lock the mutex
+ {
+ std::unique_lock<std::mutex> lock(mMutex);
+
+ // Wait for a new element to become available or for the queue to close
+ {
+ mCondition.wait(lock, [=] { return !mQueue.empty() || mClosed; });
+ }
+ }
+
+ Work ret;
+
+ {
+ std::lock_guard<std::mutex> lock(mMutex);
+
+ // Get the next element from the queue
+ if (mQueue.size() > 0)
+ {
+ ret = mQueue.front();
+ mQueue.pop();
+ }
+ else
+ {
+ ret = []() {};
+ }
+ }
+
+ return ret;
+}
-LLVBOPool::LLVBOPool(U32 vboUsage, U32 vboType)
-: mUsage(vboUsage), mType(vboType)
+void GLWorkQueue::runOne()
{
- mMissCount.resize(LL_VBO_POOL_SEED_COUNT);
- std::fill(mMissCount.begin(), mMissCount.end(), 0);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD;
+ Work w = pop();
+ w();
+ //mSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
}
-U8* LLVBOPool::allocate(U32& name, U32 size, bool for_seed)
+void GLWorkQueue::runUntilClose()
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX
- llassert(vbo_block_size(size) == size);
-
- U8* ret = NULL;
+ while (!isClosed())
+ {
+ runOne();
+ }
+}
- U32 i = vbo_block_index(size);
+void GLWorkQueue::close()
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD;
+ {
+ std::lock_guard<std::mutex> lock(mMutex);
+ mClosed = true;
+ }
- if (mFreeList.size() <= i)
- {
- mFreeList.resize(i+1);
- }
+ mCondition.notify_all();
+}
- if (mFreeList[i].empty() || for_seed)
- {
- //make a new buffer
- name = genBuffer();
-
- glBindBufferARB(mType, name);
-
- if (!for_seed && i < LL_VBO_POOL_SEED_COUNT)
- { //record this miss
- mMissCount[i]++;
- }
+bool GLWorkQueue::isClosed()
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD;
+ std::lock_guard<std::mutex> lock(mMutex);
+ return mClosed;
+}
- if (mType == GL_ARRAY_BUFFER_ARB)
- {
- LLVertexBuffer::sAllocatedBytes += size;
- }
- else
- {
- LLVertexBuffer::sAllocatedIndexBytes += size;
- }
+#include "llwindow.h"
- if (LLVertexBuffer::sDisableVBOMapping || mUsage != GL_DYNAMIC_DRAW_ARB)
- {
- glBufferDataARB(mType, size, 0, mUsage);
- if (mUsage != GL_DYNAMIC_COPY_ARB)
- { //data will be provided by application
- ret = (U8*) ll_aligned_malloc<64>(size);
- if (!ret)
- {
- LL_ERRS() << "Failed to allocate "<< size << " bytes for LLVBOPool buffer " << name <<"." << LL_NEWLINE
- << "Free list size: " << mFreeList.size() // this happens if we are out of memory so a solution might be to clear some from freelist
- << " Allocated Bytes: " << LLVertexBuffer::sAllocatedBytes
- << " Allocated Index Bytes: " << LLVertexBuffer::sAllocatedIndexBytes
- << " Pooled Bytes: " << sBytesPooled
- << " Pooled Index Bytes: " << sIndexBytesPooled
- << LL_ENDL;
- }
- }
- }
- else
- { //always use a true hint of static draw when allocating non-client-backed buffers
- glBufferDataARB(mType, size, 0, GL_STATIC_DRAW_ARB);
- }
+class LLGLWorkerThread : public LLThread
+{
+public:
+ LLGLWorkerThread(const std::string& name, GLWorkQueue* queue, LLWindow* window)
+ : LLThread(name)
+ {
+ mWindow = window;
+ mContext = mWindow->createSharedContext();
+ mQueue = queue;
+ }
- glBindBufferARB(mType, 0);
+ void run() override
+ {
+ mWindow->makeContextCurrent(mContext);
+ gGL.init(false);
+ mQueue->runUntilClose();
+ gGL.shutdown();
+ mWindow->destroySharedContext(mContext);
+ }
- if (for_seed)
- { //put into pool for future use
- llassert(mFreeList.size() > i);
+ GLWorkQueue* mQueue;
+ LLWindow* mWindow;
+ void* mContext = nullptr;
+};
- Record rec;
- rec.mGLName = name;
- rec.mClientData = ret;
-
- if (mType == GL_ARRAY_BUFFER_ARB)
- {
- sBytesPooled += size;
- }
- else
- {
- sIndexBytesPooled += size;
- }
- mFreeList[i].push_back(rec);
- }
- }
- else
- {
- name = mFreeList[i].front().mGLName;
- ret = mFreeList[i].front().mClientData;
- if (mType == GL_ARRAY_BUFFER_ARB)
- {
- sBytesPooled -= size;
- }
- else
- {
- sIndexBytesPooled -= size;
- }
+static LLGLWorkerThread* sVBOThread[THREAD_COUNT];
+static GLWorkQueue* sQueue = nullptr;
- mFreeList[i].pop_front();
- }
+#endif
- return ret;
-}
+//============================================================================
+// Pool of reusable VertexBuffer state
-void LLVBOPool::release(U32 name, U8* buffer, U32 size)
+// batch calls to glGenBuffers
+static GLuint gen_buffer()
{
- llassert(vbo_block_size(size) == size);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX;
- deleteBuffer(name);
- ll_aligned_free_fallback((U8*) buffer);
+ GLuint ret = 0;
+ constexpr U32 pool_size = 4096;
- if (mType == GL_ARRAY_BUFFER_ARB)
- {
- LLVertexBuffer::sAllocatedBytes -= size;
- }
- else
- {
- LLVertexBuffer::sAllocatedIndexBytes -= size;
- }
+ 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)
+ {
+ glGenBuffers(pool_size, sNamePool);
+ }
+ else
+ { // work around for AMD driver bug
+ for (U32 i = 0; i < pool_size; ++i)
+ {
+ glGenBuffers(1, sNamePool + i);
+ }
+ }
+ }
+
+ ret = sNamePool[--sIndex];
+ return ret;
}
-void LLVBOPool::seedPool()
+#define ANALYZE_VBO_POOL 0
+
+class LLVBOPool
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX
- U32 dummy_name = 0;
+public:
+ typedef std::chrono::steady_clock::time_point Time;
- if (mFreeList.size() < LL_VBO_POOL_SEED_COUNT)
- {
- LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("VBOPool Resize");
- mFreeList.resize(LL_VBO_POOL_SEED_COUNT);
- }
+ struct Entry
+ {
+ U8* mData;
+ GLuint mGLName;
+ Time mAge;
+ };
- for (U32 i = 0; i < LL_VBO_POOL_SEED_COUNT; i++)
- {
- if (mMissCount[i] > mFreeList[i].size())
- {
- U32 size = i*LL_VBO_BLOCK_SIZE;
-
- S32 count = mMissCount[i] - mFreeList[i].size();
- for (U32 j = 0; j < count; ++j)
- {
- allocate(dummy_name, size, true);
- }
- }
- }
-}
+ ~LLVBOPool()
+ {
+ clear();
+ }
+ typedef std::unordered_map<U32, std::list<Entry>> Pool;
+ Pool mVBOPool;
+ Pool mIBOPool;
-void LLVBOPool::cleanup()
-{
- U32 size = LL_VBO_BLOCK_SIZE;
+ U32 mTouchCount = 0;
- for (U32 i = 0; i < mFreeList.size(); ++i)
- {
- record_list_t& l = mFreeList[i];
+#if ANALYZE_VBO_POOL
+ U64 mDistributed = 0;
+ U64 mAllocated = 0;
+ U64 mReserved = 0;
+ U32 mMisses = 0;
+ U32 mHits = 0;
+#endif
- while (!l.empty())
- {
- Record& r = l.front();
+ // increase the size to some common value (e.g. a power of two) to increase hit rate
+ void adjustSize(U32& size)
+ {
+ // size = nhpo2(size); // (193/303)/580 MB (distributed/allocated)/reserved in VBO Pool. Overhead: 66 percent. Hit rate: 77 percent
- deleteBuffer(r.mGLName);
-
- if (r.mClientData)
- {
- ll_aligned_free<64>((void*) r.mClientData);
- }
+ //(245/276)/385 MB (distributed/allocated)/reserved in VBO Pool. Overhead: 57 percent. Hit rate: 69 percent
+ //(187/209)/397 MB (distributed/allocated)/reserved in VBO Pool. Overhead: 112 percent. Hit rate: 76 percent
+ U32 block_size = llmax(nhpo2(size) / 8, (U32) 16);
+ size += block_size - (size % block_size);
+ }
- l.pop_front();
+ void allocate(GLenum type, U32 size, GLuint& name, U8*& data)
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX;
+ llassert(type == GL_ARRAY_BUFFER || type == GL_ELEMENT_ARRAY_BUFFER);
+ llassert(name == 0); // non zero name indicates a gl name that wasn't freed
+ llassert(data == nullptr); // non null data indicates a buffer that wasn't freed
+ llassert(size >= 2); // any buffer size smaller than a single index is nonsensical
+
+#if ANALYZE_VBO_POOL
+ mDistributed += size;
+ adjustSize(size);
+ mAllocated += size;
+#else
+ adjustSize(size);
+#endif
- if (mType == GL_ARRAY_BUFFER_ARB)
- {
- sBytesPooled -= size;
- LLVertexBuffer::sAllocatedBytes -= size;
- }
- else
- {
- sIndexBytesPooled -= size;
- LLVertexBuffer::sAllocatedIndexBytes -= size;
- }
- }
+ auto& pool = type == GL_ELEMENT_ARRAY_BUFFER ? mIBOPool : mVBOPool;
- size += LL_VBO_BLOCK_SIZE;
- }
+ Pool::iterator iter = pool.find(size);
+ if (iter == pool.end())
+ { // cache miss, allocate a new buffer
+ LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vbo pool miss");
+ LL_PROFILE_GPU_ZONE("vbo alloc");
- //reset miss counts
- std::fill(mMissCount.begin(), mMissCount.end(), 0);
-}
+#if ANALYZE_VBO_POOL
+ mMisses++;
+#endif
+ name = gen_buffer();
+ glBindBuffer(type, name);
+ glBufferData(type, size, nullptr, GL_DYNAMIC_DRAW);
+ if (type == GL_ELEMENT_ARRAY_BUFFER)
+ {
+ LLVertexBuffer::sGLRenderIndices = name;
+ }
+ else
+ {
+ LLVertexBuffer::sGLRenderBuffer = name;
+ }
+
+ data = (U8*)ll_aligned_malloc_16(size);
+ }
+ else
+ {
+#if ANALYZE_VBO_POOL
+ mHits++;
+ llassert(mReserved >= size); // assert if accounting gets messed up
+ mReserved -= size;
+#endif
+
+ std::list<Entry>& entries = iter->second;
+ Entry& entry = entries.back();
+ name = entry.mGLName;
+ data = entry.mData;
+
+ entries.pop_back();
+ if (entries.empty())
+ {
+ pool.erase(iter);
+ }
+ }
+
+ clean();
+ }
+
+ void free(GLenum type, U32 size, GLuint name, U8* data)
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX;
+ llassert(type == GL_ARRAY_BUFFER || type == GL_ELEMENT_ARRAY_BUFFER);
+ llassert(size >= 2);
+ llassert(name != 0);
+ llassert(data != nullptr);
+
+ clean();
+
+#if ANALYZE_VBO_POOL
+ llassert(mDistributed >= size);
+ mDistributed -= size;
+ adjustSize(size);
+ llassert(mAllocated >= size);
+ mAllocated -= size;
+ mReserved += size;
+#else
+ adjustSize(size);
+#endif
+
+ auto& pool = type == GL_ELEMENT_ARRAY_BUFFER ? mIBOPool : mVBOPool;
+
+ Pool::iterator iter = pool.find(size);
+
+ if (iter == pool.end())
+ {
+ std::list<Entry> newlist;
+ newlist.push_front({ data, name, std::chrono::steady_clock::now() });
+ pool[size] = newlist;
+ }
+ else
+ {
+ iter->second.push_front({ data, name, std::chrono::steady_clock::now() });
+ }
+
+ }
+
+ // clean periodically (clean gets called for every alloc/free)
+ void clean()
+ {
+ mTouchCount++;
+ if (mTouchCount < 1024) // clean every 1k touches
+ {
+ return;
+ }
+ mTouchCount = 0;
+
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX;
+
+ std::unordered_map<U32, std::list<Entry>>* pools[] = { &mVBOPool, &mIBOPool };
+
+ using namespace std::chrono_literals;
+
+ Time cutoff = std::chrono::steady_clock::now() - 5s;
+
+ for (auto* pool : pools)
+ {
+ for (Pool::iterator iter = pool->begin(); iter != pool->end(); )
+ {
+ auto& entries = iter->second;
+
+ while (!entries.empty() && entries.back().mAge < cutoff)
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vbo cache timeout");
+ auto& entry = entries.back();
+ ll_aligned_free_16(entry.mData);
+ glDeleteBuffers(1, &entry.mGLName);
+#if ANALYZE_VBO_POOL
+ llassert(mReserved >= iter->first);
+ mReserved -= iter->first;
+#endif
+ entries.pop_back();
+
+ }
+
+ if (entries.empty())
+ {
+ iter = pool->erase(iter);
+ }
+ else
+ {
+ ++iter;
+ }
+ }
+ }
+
+#if ANALYZE_VBO_POOL
+ LL_INFOS() << llformat("(%d/%d)/%d MB (distributed/allocated)/total in VBO Pool. Overhead: %d percent. Hit rate: %d percent",
+ mDistributed / 1000000,
+ mAllocated / 1000000,
+ (mAllocated + mReserved) / 1000000, // total bytes
+ ((mAllocated+mReserved-mDistributed)*100)/llmax(mDistributed, (U64) 1), // overhead percent
+ (mHits*100)/llmax(mMisses+mHits, (U32)1)) // hit rate percent
+ << LL_ENDL;
+#endif
+ }
+
+ void clear()
+ {
+ for (auto& entries : mIBOPool)
+ {
+ for (auto& entry : entries.second)
+ {
+ ll_aligned_free_16(entry.mData);
+ glDeleteBuffers(1, &entry.mGLName);
+ }
+ }
+
+ for (auto& entries : mVBOPool)
+ {
+ for (auto& entry : entries.second)
+ {
+ ll_aligned_free_16(entry.mData);
+ glDeleteBuffers(1, &entry.mGLName);
+ }
+ }
+
+#if ANALYZE_VBO_POOL
+ mReserved = 0;
+#endif
+
+ mIBOPool.clear();
+ mVBOPool.clear();
+ }
+
+
+};
+
+static LLVBOPool* sVBOPool = nullptr;
+
+//============================================================================
+//
+//static
+U32 LLVertexBuffer::sGLRenderBuffer = 0;
+U32 LLVertexBuffer::sGLRenderIndices = 0;
+U32 LLVertexBuffer::sLastMask = 0;
+U32 LLVertexBuffer::sVertexCount = 0;
//NOTE: each component must be AT LEAST 4 bytes in size to avoid a performance penalty on AMD hardware
-const S32 LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_MAX] =
+const U32 LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_MAX] =
{
sizeof(LLVector4), // TYPE_VERTEX,
sizeof(LLVector4), // TYPE_NORMAL,
@@ -392,79 +587,34 @@ const U32 LLVertexBuffer::sGLMode[LLRender::NUM_MODES] =
};
//static
-U32 LLVertexBuffer::getVAOName()
-{
- U32 ret = 0;
-
- if (!sAvailableVAOName.empty())
- {
- ret = sAvailableVAOName.front();
- sAvailableVAOName.pop_front();
- }
- else
- {
-#ifdef GL_ARB_vertex_array_object
- glGenVertexArrays(1, &ret);
-#endif
- }
-
- return ret;
-}
-
-//static
-void LLVertexBuffer::releaseVAOName(U32 name)
-{
- sAvailableVAOName.push_back(name);
-}
-
-
-//static
-void LLVertexBuffer::seedPools()
-{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX
- sStreamVBOPool.seedPool();
- sDynamicVBOPool.seedPool();
- sDynamicCopyVBOPool.seedPool();
- sStreamIBOPool.seedPool();
- sDynamicIBOPool.seedPool();
-}
-
-//static
void LLVertexBuffer::setupClientArrays(U32 data_mask)
{
- if (sLastMask != data_mask)
- {
+ if (sLastMask != data_mask)
+ {
+ for (U32 i = 0; i < TYPE_MAX; ++i)
+ {
+ S32 loc = i;
- if (gGLManager.mGLSLVersionMajor < 2 && gGLManager.mGLSLVersionMinor < 30)
- {
- //make sure texture index is disabled
- data_mask = data_mask & ~MAP_TEXTURE_INDEX;
- }
+ U32 mask = 1 << i;
- for (U32 i = 0; i < TYPE_MAX; ++i)
- {
- S32 loc = i;
-
- U32 mask = 1 << i;
-
- if (sLastMask & (1 << i))
- { //was enabled
- if (!(data_mask & mask))
- { //needs to be disabled
- glDisableVertexAttribArrayARB(loc);
- }
- }
- else
- { //was disabled
- if (data_mask & mask)
- { //needs to be enabled
- glEnableVertexAttribArrayARB(loc);
- }
- }
- }
-
- sLastMask = data_mask;
- }
+ if (sLastMask & (1 << i))
+ { //was enabled
+ if (!(data_mask & mask))
+ { //needs to be disabled
+ glDisableVertexAttribArray(loc);
+ }
+ }
+ else
+ { //was disabled
+ if (data_mask & mask)
+ { //needs to be enabled
+ glEnableVertexAttribArray(loc);
+ }
+ }
+ }
+ }
+
+ sLastMask = data_mask;
}
//static
@@ -481,7 +631,7 @@ void LLVertexBuffer::drawArrays(U32 mode, const std::vector<LLVector3>& pos)
}
//static
-void LLVertexBuffer::drawElements(U32 mode, const LLVector4a* pos, const LLVector2* tc, S32 num_indices, const U16* indicesp)
+void LLVertexBuffer::drawElements(U32 mode, const LLVector4a* pos, const LLVector2* tc, U32 num_indices, const U16* indicesp)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX;
llassert(LLGLSLShader::sCurBoundShaderPtr != NULL);
@@ -514,13 +664,18 @@ void LLVertexBuffer::drawElements(U32 mode, const LLVector4a* pos, const LLVecto
U16 idx = indicesp[i];
gGL.vertex3fv(pos[idx].getF32ptr());
}
- }
+}
gGL.end();
gGL.flush();
}
-void LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_offset) const
+bool LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_offset) const
{
+ if (!gDebugGL)
+ {
+ return true;
+ }
+
llassert(start < (U32)mNumVerts);
llassert(end < (U32)mNumVerts);
@@ -538,9 +693,8 @@ void LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_of
LL_ERRS() << "Bad index buffer draw range: [" << indices_offset << ", " << indices_offset+count << "]" << LL_ENDL;
}
- if (gDebugGL && !useVBOs())
{
- U16* idx = ((U16*) getIndicesPointer())+indices_offset;
+ U16* idx = (U16*) mMappedIndexData+indices_offset;
for (U32 i = 0; i < count; ++i)
{
llassert(idx[i] >= start);
@@ -556,230 +710,79 @@ void LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_of
if (shader && shader->mFeatures.mIndexedTextureChannels > 1)
{
- LLStrider<LLVector4a> v;
- //hack to get non-const reference
- LLVertexBuffer* vb = (LLVertexBuffer*) this;
- vb->getVertexStrider(v);
-
+ LLVector4a* v = (LLVector4a*) mMappedData;
+
for (U32 i = start; i < end; i++)
{
- S32 idx = (S32) (v[i][3]+0.25f);
- llassert(idx >= 0);
- if (idx < 0 || idx >= shader->mFeatures.mIndexedTextureChannels)
+ U32 idx = (U32) (v[i][3]+0.25f);
+ if (idx >= shader->mFeatures.mIndexedTextureChannels)
{
LL_ERRS() << "Bad texture index found in vertex data stream." << LL_ENDL;
}
}
}
}
-}
-
-void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const
-{
- validateRange(start, end, count, indices_offset);
- mMappable = false;
- gGL.syncMatrices();
-
- llassert(mNumVerts >= 0);
- llassert(LLGLSLShader::sCurBoundShaderPtr != NULL);
-
- if (mGLArray)
- {
- if (mGLArray != sGLRenderArray)
- {
- LL_ERRS() << "Wrong vertex array bound." << LL_ENDL;
- }
- }
- else
- {
- if (mGLIndices != sGLRenderIndices)
- {
- LL_ERRS() << "Wrong index buffer bound." << LL_ENDL;
- }
-
- if (mGLBuffer != sGLRenderBuffer)
- {
- LL_ERRS() << "Wrong vertex buffer bound." << LL_ENDL;
- }
- }
-
- if (gDebugGL && !mGLArray && useVBOs())
- {
- GLint elem = 0;
- glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &elem);
- if (elem != mGLIndices)
- {
- LL_ERRS() << "Wrong index buffer bound!" << LL_ENDL;
- }
- }
-
- if (mode >= LLRender::NUM_MODES)
- {
- LL_ERRS() << "Invalid draw mode: " << mode << LL_ENDL;
- return;
- }
-
- U16* idx = ((U16*) getIndicesPointer())+indices_offset;
-
- stop_glerror();
- LLGLSLShader::startProfile();
- LL_PROFILER_GPU_ZONEC( "gl.DrawRangeElements", 0xFFFF00 )
- glDrawRangeElements(sGLMode[mode], start, end, count, GL_UNSIGNED_SHORT,
- idx);
- LLGLSLShader::stopProfile(count, mode);
- stop_glerror();
-
-
+ return true;
+}
- placeFence();
+#ifdef LL_PROFILER_ENABLE_RENDER_DOC
+void LLVertexBuffer::setLabel(const char* label) {
+ LL_LABEL_OBJECT_GL(GL_BUFFER, mGLBuffer, strlen(label), label);
}
+#endif
-void LLVertexBuffer::drawRangeFast(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const
+void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const
{
- mMappable = false;
+ llassert(validateRange(start, end, count, indices_offset));
+ llassert(mGLBuffer == sGLRenderBuffer);
+ llassert(mGLIndices == sGLRenderIndices);
gGL.syncMatrices();
-
- U16* idx = ((U16*)getIndicesPointer()) + indices_offset;
-
- LL_PROFILER_GPU_ZONEC("gl.DrawRangeElements", 0xFFFF00)
- glDrawRangeElements(sGLMode[mode], start, end, count, GL_UNSIGNED_SHORT,
- idx);
+ glDrawRangeElements(sGLMode[mode], start, end, count, GL_UNSIGNED_SHORT,
+ (GLvoid*) (indices_offset * sizeof(U16)));
}
void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const
{
- llassert(LLGLSLShader::sCurBoundShaderPtr != NULL);
- mMappable = false;
- gGL.syncMatrices();
-
- llassert(mNumIndices >= 0);
- if (indices_offset >= (U32) mNumIndices ||
- indices_offset + count > (U32) mNumIndices)
- {
- LL_ERRS() << "Bad index buffer draw range: [" << indices_offset << ", " << indices_offset+count << "]" << LL_ENDL;
- }
-
- if (mGLArray)
- {
- if (mGLArray != sGLRenderArray)
- {
- LL_ERRS() << "Wrong vertex array bound." << LL_ENDL;
- }
- }
- else
- {
- if (mGLIndices != sGLRenderIndices)
- {
- LL_ERRS() << "Wrong index buffer bound." << LL_ENDL;
- }
-
- if (mGLBuffer != sGLRenderBuffer)
- {
- LL_ERRS() << "Wrong vertex buffer bound." << LL_ENDL;
- }
- }
-
- if (mode >= LLRender::NUM_MODES)
- {
- LL_ERRS() << "Invalid draw mode: " << mode << LL_ENDL;
- return;
- }
-
- stop_glerror();
- LLGLSLShader::startProfile();
- LL_PROFILER_GPU_ZONEC( "gl.DrawElements", 0xA0FFA0 )
- glDrawElements(sGLMode[mode], count, GL_UNSIGNED_SHORT,
- ((U16*) getIndicesPointer()) + indices_offset);
- LLGLSLShader::stopProfile(count, mode);
- stop_glerror();
- placeFence();
+ drawRange(mode, 0, mNumVerts-1, count, indices_offset);
}
void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX;
- llassert(LLGLSLShader::sCurBoundShaderPtr != NULL);
- mMappable = false;
+ llassert(first + count <= mNumVerts);
+ llassert(mGLBuffer == sGLRenderBuffer);
+ llassert(mGLIndices == sGLRenderIndices);
+
gGL.syncMatrices();
+ glDrawArrays(sGLMode[mode], first, count);
+}
-#ifndef LL_RELEASE_FOR_DOWNLOAD
- llassert(mNumVerts >= 0);
- if (first >= (U32)mNumVerts ||
- first + count > (U32)mNumVerts)
- {
- LL_ERRS() << "Bad vertex buffer draw range: [" << first << ", " << first + count << "]" << LL_ENDL;
- }
+//static
+void LLVertexBuffer::initClass(LLWindow* window)
+{
+ llassert(sVBOPool == nullptr);
+ sVBOPool = new LLVBOPool();
- if (mGLArray)
- {
- if (mGLArray != sGLRenderArray)
- {
- LL_ERRS() << "Wrong vertex array bound." << LL_ENDL;
- }
- }
- else
- {
- if (mGLBuffer != sGLRenderBuffer || useVBOs() != sVBOActive)
- {
- LL_ERRS() << "Wrong vertex buffer bound." << LL_ENDL;
- }
- }
+#if ENABLE_GL_WORK_QUEUE
+ sQueue = new GLWorkQueue();
- if (mode >= LLRender::NUM_MODES)
+ for (int i = 0; i < THREAD_COUNT; ++i)
{
- LL_ERRS() << "Invalid draw mode: " << mode << LL_ENDL;
- return;
+ sVBOThread[i] = new LLGLWorkerThread("VBO Worker", sQueue, window);
+ sVBOThread[i]->start();
}
#endif
-
- LLGLSLShader::startProfile();
- {
- LL_PROFILER_GPU_ZONEC("gl.DrawArrays", 0xFF4040)
- glDrawArrays(sGLMode[mode], first, count);
- }
- LLGLSLShader::stopProfile(count, mode);
-
- stop_glerror();
- placeFence();
-}
-
-//static
-void LLVertexBuffer::initClass(bool use_vbo, bool no_vbo_mapping)
-{
- sEnableVBOs = use_vbo && gGLManager.mHasVertexBufferObject;
- sDisableVBOMapping = sEnableVBOs && no_vbo_mapping;
}
//static
void LLVertexBuffer::unbind()
{
- if (sGLRenderArray)
- {
-#if GL_ARB_vertex_array_object
- glBindVertexArray(0);
-#endif
- sGLRenderArray = 0;
- sGLRenderIndices = 0;
- sIBOActive = false;
- }
-
- if (sVBOActive)
- {
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
- sVBOActive = false;
- }
- if (sIBOActive)
- {
- glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
- sIBOActive = false;
- }
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
sGLRenderBuffer = 0;
sGLRenderIndices = 0;
-
- setupClientArrays(0);
}
//static
@@ -787,98 +790,41 @@ void LLVertexBuffer::cleanupClass()
{
unbind();
- sStreamIBOPool.cleanup();
- sDynamicIBOPool.cleanup();
- sStreamVBOPool.cleanup();
- sDynamicVBOPool.cleanup();
- sDynamicCopyVBOPool.cleanup();
-}
+ delete sVBOPool;
+ sVBOPool = nullptr;
-//----------------------------------------------------------------------------
-
-S32 LLVertexBuffer::determineUsage(S32 usage)
-{
- S32 ret_usage = usage;
+#if ENABLE_GL_WORK_QUEUE
+ sQueue->close();
+ for (int i = 0; i < THREAD_COUNT; ++i)
+ {
+ sVBOThread[i]->shutdown();
+ delete sVBOThread[i];
+ sVBOThread[i] = nullptr;
+ }
- if (!sEnableVBOs)
- {
- ret_usage = 0;
- }
-
- if (ret_usage == GL_STREAM_DRAW_ARB && !sUseStreamDraw)
- {
- ret_usage = 0;
- }
-
- if (ret_usage == GL_DYNAMIC_DRAW_ARB && sPreferStreamDraw)
- {
- ret_usage = GL_STREAM_DRAW_ARB;
- }
-
- if (ret_usage == 0 && LLRender::sGLCoreProfile)
- { //MUST use VBOs for all rendering
- ret_usage = GL_STREAM_DRAW_ARB;
- }
-
- if (ret_usage && ret_usage != GL_STREAM_DRAW_ARB)
- { //only stream_draw and dynamic_draw are supported when using VBOs, dynamic draw is the default
- if (ret_usage != GL_DYNAMIC_COPY_ARB)
- {
- if (sDisableVBOMapping)
- { //always use stream draw if VBO mapping is disabled
- ret_usage = GL_STREAM_DRAW_ARB;
- }
- else
- {
- ret_usage = GL_DYNAMIC_DRAW_ARB;
- }
- }
- }
-
- return ret_usage;
+ delete sQueue;
+ sQueue = nullptr;
+#endif
}
-LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage)
-: LLRefCount(),
-
- mNumVerts(0),
- mNumIndices(0),
- mAlignedOffset(0),
- mAlignedIndexOffset(0),
- mSize(0),
- mIndicesSize(0),
- mTypeMask(typemask),
- mUsage(LLVertexBuffer::determineUsage(usage)),
- mGLBuffer(0),
- mGLIndices(0),
- mGLArray(0),
- mMappedData(NULL),
- mMappedIndexData(NULL),
- mMappedDataUsingVBOs(false),
- mMappedIndexDataUsingVBOs(false),
- mVertexLocked(false),
- mIndexLocked(false),
- mFinal(false),
- mEmpty(true),
- mMappable(false),
- mFence(NULL)
-{
- mMappable = (mUsage == GL_DYNAMIC_DRAW_ARB && !sDisableVBOMapping);
+//----------------------------------------------------------------------------
+LLVertexBuffer::LLVertexBuffer(U32 typemask)
+: LLRefCount(),
+ mTypeMask(typemask)
+{
//zero out offsets
for (U32 i = 0; i < TYPE_MAX; i++)
{
mOffsets[i] = 0;
}
-
- sCount++;
}
//static
-S32 LLVertexBuffer::calcOffsets(const U32& typemask, S32* offsets, S32 num_vertices)
+U32 LLVertexBuffer::calcOffsets(const U32& typemask, U32* offsets, U32 num_vertices)
{
- S32 offset = 0;
- for (S32 i=0; i<TYPE_TEXTURE_INDEX; i++)
+ U32 offset = 0;
+ for (U32 i=0; i<TYPE_TEXTURE_INDEX; i++)
{
U32 mask = 1<<i;
if (typemask & mask)
@@ -894,14 +840,14 @@ S32 LLVertexBuffer::calcOffsets(const U32& typemask, S32* offsets, S32 num_verti
offsets[TYPE_TEXTURE_INDEX] = offsets[TYPE_VERTEX] + 12;
- return offset+16;
+ return offset;
}
//static
-S32 LLVertexBuffer::calcVertexSize(const U32& typemask)
+U32 LLVertexBuffer::calcVertexSize(const U32& typemask)
{
- S32 size = 0;
- for (S32 i = 0; i < TYPE_TEXTURE_INDEX; i++)
+ U32 size = 0;
+ for (U32 i = 0; i < TYPE_TEXTURE_INDEX; i++)
{
U32 mask = 1<<i;
if (typemask & mask)
@@ -913,11 +859,6 @@ S32 LLVertexBuffer::calcVertexSize(const U32& typemask)
return size;
}
-S32 LLVertexBuffer::getSize() const
-{
- return mSize;
-}
-
// protected, use unref()
//virtual
LLVertexBuffer::~LLVertexBuffer()
@@ -925,27 +866,6 @@ LLVertexBuffer::~LLVertexBuffer()
destroyGLBuffer();
destroyGLIndices();
- if (mGLArray)
- {
-#if GL_ARB_vertex_array_object
- releaseVAOName(mGLArray);
-#endif
- }
-
- sCount--;
-
- if (mFence)
- {
- // Sanity check. We have weird crashes in this destructor (on delete). Yet mFence is disabled.
- // TODO: mFence was added in scope of SH-2038, but was never enabled, consider removing mFence.
- LL_ERRS() << "LLVertexBuffer destruction failed" << LL_ENDL;
- delete mFence;
- mFence = NULL;
- }
-
- sVertexCount -= mNumVerts;
- sIndexCount -= mNumIndices;
-
if (mMappedData)
{
LL_ERRS() << "Failed to clear vertex buffer's vertices" << LL_ENDL;
@@ -956,101 +876,37 @@ LLVertexBuffer::~LLVertexBuffer()
}
};
-void LLVertexBuffer::placeFence() const
-{
- /*if (!mFence && useVBOs())
- {
- if (gGLManager.mHasSync)
- {
- mFence = new LLGLSyncFence();
- }
- }
-
- if (mFence)
- {
- mFence->placeFence();
- }*/
-}
-
-void LLVertexBuffer::waitFence() const
-{
- /*if (mFence)
- {
- mFence->wait();
- }*/
-}
-
//----------------------------------------------------------------------------
void LLVertexBuffer::genBuffer(U32 size)
{
- mSize = vbo_block_size(size);
-
- if (mUsage == GL_STREAM_DRAW_ARB)
- {
- mMappedData = sStreamVBOPool.allocate(mGLBuffer, mSize);
- }
- else if (mUsage == GL_DYNAMIC_DRAW_ARB)
- {
- mMappedData = sDynamicVBOPool.allocate(mGLBuffer, mSize);
- }
- else
- {
- mMappedData = sDynamicCopyVBOPool.allocate(mGLBuffer, mSize);
- }
-
-
- sGLCount++;
-}
-
-void LLVertexBuffer::genIndices(U32 size)
-{
- mIndicesSize = vbo_block_size(size);
-
- if (mUsage == GL_STREAM_DRAW_ARB)
- {
- mMappedIndexData = sStreamIBOPool.allocate(mGLIndices, mIndicesSize);
- }
- else
- {
- mMappedIndexData = sDynamicIBOPool.allocate(mGLIndices, mIndicesSize);
- }
-
- sGLCount++;
-}
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX;
+ llassert(sVBOPool);
-void LLVertexBuffer::releaseBuffer()
-{
- if (mUsage == GL_STREAM_DRAW_ARB)
- {
- sStreamVBOPool.release(mGLBuffer, mMappedData, mSize);
- }
- else
- {
- sDynamicVBOPool.release(mGLBuffer, mMappedData, mSize);
- }
-
- mGLBuffer = 0;
- mMappedData = NULL;
+ if (sVBOPool)
+ {
+ llassert(mSize == 0);
+ llassert(mGLBuffer == 0);
+ llassert(mMappedData == nullptr);
- sGLCount--;
+ mSize = size;
+ sVBOPool->allocate(GL_ARRAY_BUFFER, mSize, mGLBuffer, mMappedData);
+ }
}
-void LLVertexBuffer::releaseIndices()
+void LLVertexBuffer::genIndices(U32 size)
{
- if (mUsage == GL_STREAM_DRAW_ARB)
- {
- sStreamIBOPool.release(mGLIndices, mMappedIndexData, mIndicesSize);
- }
- else
- {
- sDynamicIBOPool.release(mGLIndices, mMappedIndexData, mIndicesSize);
- }
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX;
+ llassert(sVBOPool);
- mGLIndices = 0;
- mMappedIndexData = NULL;
-
- sGLCount--;
+ if (sVBOPool)
+ {
+ llassert(mIndicesSize == 0);
+ llassert(mGLIndices == 0);
+ llassert(mMappedIndexData == nullptr);
+ mIndicesSize = size;
+ sVBOPool->allocate(GL_ELEMENT_ARRAY_BUFFER, mIndicesSize, mGLIndices, mMappedIndexData);
+ }
}
bool LLVertexBuffer::createGLBuffer(U32 size)
@@ -1067,22 +923,8 @@ bool LLVertexBuffer::createGLBuffer(U32 size)
bool success = true;
- mEmpty = true;
-
- mMappedDataUsingVBOs = useVBOs();
+ genBuffer(size);
- if (mMappedDataUsingVBOs)
- {
- genBuffer(size);
- }
- else
- {
- static int gl_buffer_idx = 0;
- mGLBuffer = ++gl_buffer_idx;
- mMappedData = (U8*)ll_aligned_malloc_16(size);
- mSize = size;
- }
-
if (!mMappedData)
{
success = false;
@@ -1104,27 +946,8 @@ bool LLVertexBuffer::createGLIndices(U32 size)
bool success = true;
- mEmpty = true;
-
- //pad by 16 bytes for aligned copies
- size += 16;
-
- mMappedIndexDataUsingVBOs = useVBOs();
-
- if (mMappedIndexDataUsingVBOs)
- {
- //pad by another 16 bytes for VBO pointer adjustment
- size += 16;
- genIndices(size);
- }
- else
- {
- mMappedIndexData = (U8*)ll_aligned_malloc_16(size);
- static int gl_buffer_idx = 0;
- mGLIndices = ++gl_buffer_idx;
- mIndicesSize = size;
- }
-
+ genIndices(size);
+
if (!mMappedIndexData)
{
success = false;
@@ -1136,43 +959,37 @@ void LLVertexBuffer::destroyGLBuffer()
{
if (mGLBuffer || mMappedData)
{
- if (mMappedDataUsingVBOs)
- {
- releaseBuffer();
- }
- else
- {
- ll_aligned_free_16((void*)mMappedData);
- mMappedData = NULL;
- mEmpty = true;
- }
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX;
+ //llassert(sVBOPool);
+ if (sVBOPool)
+ {
+ sVBOPool->free(GL_ARRAY_BUFFER, mSize, mGLBuffer, mMappedData);
+ }
+
+ mSize = 0;
+ mGLBuffer = 0;
+ mMappedData = nullptr;
}
-
- mGLBuffer = 0;
- //unbind();
}
void LLVertexBuffer::destroyGLIndices()
{
if (mGLIndices || mMappedIndexData)
{
- if (mMappedIndexDataUsingVBOs)
- {
- releaseIndices();
- }
- else
- {
- ll_aligned_free_16((void*)mMappedIndexData);
- mMappedIndexData = NULL;
- mEmpty = true;
- }
- }
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX;
+ //llassert(sVBOPool);
+ if (sVBOPool)
+ {
+ sVBOPool->free(GL_ELEMENT_ARRAY_BUFFER, mIndicesSize, mGLIndices, mMappedIndexData);
+ }
- mGLIndices = 0;
- //unbind();
+ mIndicesSize = 0;
+ mGLIndices = 0;
+ mMappedIndexData = nullptr;
+ }
}
-bool LLVertexBuffer::updateNumVerts(S32 nverts)
+bool LLVertexBuffer::updateNumVerts(U32 nverts)
{
llassert(nverts >= 0);
@@ -1186,19 +1003,17 @@ bool LLVertexBuffer::updateNumVerts(S32 nverts)
U32 needed_size = calcOffsets(mTypeMask, mOffsets, nverts);
- if (needed_size > mSize || needed_size <= mSize/2)
- {
- success &= createGLBuffer(needed_size);
- }
+ if (needed_size != mSize)
+ {
+ success &= createGLBuffer(needed_size);
+ }
- sVertexCount -= mNumVerts;
+ llassert(mSize == needed_size);
mNumVerts = nverts;
- sVertexCount += mNumVerts;
-
return success;
}
-bool LLVertexBuffer::updateNumIndices(S32 nindices)
+bool LLVertexBuffer::updateNumIndices(U32 nindices)
{
llassert(nindices >= 0);
@@ -1206,22 +1021,18 @@ bool LLVertexBuffer::updateNumIndices(S32 nindices)
U32 needed_size = sizeof(U16) * nindices;
- if (needed_size > mIndicesSize || needed_size <= mIndicesSize/2)
+ if (needed_size != mIndicesSize)
{
success &= createGLIndices(needed_size);
}
- sIndexCount -= mNumIndices;
+ llassert(mIndicesSize == needed_size);
mNumIndices = nindices;
- sIndexCount += mNumIndices;
-
return success;
}
-bool LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create)
+bool LLVertexBuffer::allocateBuffer(U32 nverts, U32 nindices)
{
- stop_glerror();
-
if (nverts < 0 || nindices < 0 ||
nverts > 65536)
{
@@ -1233,735 +1044,215 @@ bool LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create)
success &= updateNumVerts(nverts);
success &= updateNumIndices(nindices);
- if (create && (nverts || nindices))
- {
- //actually allocate space for the vertex buffer if using VBO mapping
- flush(); //unmap
-
- if (gGLManager.mHasVertexArrayObject && useVBOs() && sUseVAO)
- {
-#if GL_ARB_vertex_array_object
- mGLArray = getVAOName();
-#endif
- setupVertexArray();
- }
- }
-
return success;
}
-void LLVertexBuffer::setupVertexArray()
-{
- if (!mGLArray)
- {
- return;
- }
-
- LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX;
-#if GL_ARB_vertex_array_object
- glBindVertexArray(mGLArray);
-#endif
- sGLRenderArray = mGLArray;
-
- static const U32 attrib_size[] =
- {
- 3, //TYPE_VERTEX,
- 3, //TYPE_NORMAL,
- 2, //TYPE_TEXCOORD0,
- 2, //TYPE_TEXCOORD1,
- 2, //TYPE_TEXCOORD2,
- 2, //TYPE_TEXCOORD3,
- 4, //TYPE_COLOR,
- 4, //TYPE_EMISSIVE,
- 4, //TYPE_TANGENT,
- 1, //TYPE_WEIGHT,
- 4, //TYPE_WEIGHT4,
- 4, //TYPE_CLOTHWEIGHT,
- 1, //TYPE_TEXTURE_INDEX
- };
-
- static const U32 attrib_type[] =
- {
- GL_FLOAT, //TYPE_VERTEX,
- GL_FLOAT, //TYPE_NORMAL,
- GL_FLOAT, //TYPE_TEXCOORD0,
- GL_FLOAT, //TYPE_TEXCOORD1,
- GL_FLOAT, //TYPE_TEXCOORD2,
- GL_FLOAT, //TYPE_TEXCOORD3,
- GL_UNSIGNED_BYTE, //TYPE_COLOR,
- GL_UNSIGNED_BYTE, //TYPE_EMISSIVE,
- GL_FLOAT, //TYPE_TANGENT,
- GL_FLOAT, //TYPE_WEIGHT,
- GL_FLOAT, //TYPE_WEIGHT4,
- GL_FLOAT, //TYPE_CLOTHWEIGHT,
- GL_UNSIGNED_INT, //TYPE_TEXTURE_INDEX
- };
-
- static const bool attrib_integer[] =
- {
- false, //TYPE_VERTEX,
- false, //TYPE_NORMAL,
- false, //TYPE_TEXCOORD0,
- false, //TYPE_TEXCOORD1,
- false, //TYPE_TEXCOORD2,
- false, //TYPE_TEXCOORD3,
- false, //TYPE_COLOR,
- false, //TYPE_EMISSIVE,
- false, //TYPE_TANGENT,
- false, //TYPE_WEIGHT,
- false, //TYPE_WEIGHT4,
- false, //TYPE_CLOTHWEIGHT,
- true, //TYPE_TEXTURE_INDEX
- };
-
- static const U32 attrib_normalized[] =
- {
- GL_FALSE, //TYPE_VERTEX,
- GL_FALSE, //TYPE_NORMAL,
- GL_FALSE, //TYPE_TEXCOORD0,
- GL_FALSE, //TYPE_TEXCOORD1,
- GL_FALSE, //TYPE_TEXCOORD2,
- GL_FALSE, //TYPE_TEXCOORD3,
- GL_TRUE, //TYPE_COLOR,
- GL_TRUE, //TYPE_EMISSIVE,
- GL_FALSE, //TYPE_TANGENT,
- GL_FALSE, //TYPE_WEIGHT,
- GL_FALSE, //TYPE_WEIGHT4,
- GL_FALSE, //TYPE_CLOTHWEIGHT,
- GL_FALSE, //TYPE_TEXTURE_INDEX
- };
-
- bindGLBuffer(true);
- bindGLIndices(true);
-
- for (U32 i = 0; i < TYPE_MAX; ++i)
- {
- if (mTypeMask & (1 << i))
- {
- glEnableVertexAttribArrayARB(i);
-
- if (attrib_integer[i])
- {
-#if !LL_DARWIN
- //glVertexattribIPointer requires GLSL 1.30 or later
- if (gGLManager.mGLSLVersionMajor > 1 || gGLManager.mGLSLVersionMinor >= 30)
- {
- // nat 2018-10-24: VS 2017 also notices the issue
- // described below, and warns even with reinterpret_cast.
- // Cast via intptr_t to make it painfully obvious to the
- // compiler that we're doing this intentionally.
- glVertexAttribIPointer(i, attrib_size[i], attrib_type[i], sTypeSize[i],
- reinterpret_cast<const GLvoid*>(intptr_t(mOffsets[i])));
- }
-#endif
- }
- else
- {
- // nat 2016-12-16: With 64-bit clang compile, the compiler
- // produces an error if we simply cast mOffsets[i] -- an S32
- // -- to (GLvoid *), the type of the parameter. It correctly
- // points out that there's no way an S32 could fit a real
- // pointer value. Ruslan asserts that in this case the last
- // param is interpreted as an array data offset within the VBO
- // rather than as an actual pointer, so it's okay.
- glVertexAttribPointerARB(i, attrib_size[i], attrib_type[i],
- attrib_normalized[i], sTypeSize[i],
- reinterpret_cast<GLvoid*>(intptr_t(mOffsets[i])));
- }
- }
- else
- {
- glDisableVertexAttribArrayARB(i);
- }
- }
-
- //draw a dummy triangle to set index array pointer
- //glDrawElements(GL_TRIANGLES, 0, GL_UNSIGNED_SHORT, NULL);
-
- unbind();
-}
-
-bool LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices)
-{
- llassert(newnverts >= 0);
- llassert(newnindices >= 0);
-
- bool success = true;
-
- success &= updateNumVerts(newnverts);
- success &= updateNumIndices(newnindices);
-
- if (useVBOs())
- {
- flush(); //unmap
-
- if (mGLArray)
- { //if size changed, offsets changed
- setupVertexArray();
- }
- }
-
- return success;
-}
-
-bool LLVertexBuffer::useVBOs() const
-{
- //it's generally ineffective to use VBO for things that are streaming on apple
- return (mUsage != 0);
-}
-
//----------------------------------------------------------------------------
-bool expand_region(LLVertexBuffer::MappedRegion& region, S32 index, S32 count)
+// if no gap between region and given range exists, expand region to cover given range and return true
+// otherwise return false
+bool expand_region(LLVertexBuffer::MappedRegion& region, U32 start, U32 end)
{
- S32 end = index+count;
- S32 region_end = region.mIndex+region.mCount;
- if (end < region.mIndex ||
- index > region_end)
+ if (end < region.mStart ||
+ start > region.mEnd)
{ //gap exists, do not merge
return false;
}
- S32 new_end = llmax(end, region_end);
- S32 new_index = llmin(index, region.mIndex);
- region.mIndex = new_index;
- region.mCount = new_end-new_index;
+ region.mStart = llmin(region.mStart, start);
+ region.mEnd = llmax(region.mEnd, end);
+
return true;
}
// Map for data access
-U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range)
+U8* LLVertexBuffer::mapVertexBuffer(LLVertexBuffer::AttributeType type, U32 index, S32 count)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX;
- bindGLBuffer(true);
- if (mFinal)
- {
- LL_ERRS() << "LLVertexBuffer::mapVeretxBuffer() called on a finalized buffer." << LL_ENDL;
- }
- if (!useVBOs() && !mMappedData && !mMappedIndexData)
- {
- LL_ERRS() << "LLVertexBuffer::mapVertexBuffer() called on unallocated buffer." << LL_ENDL;
- }
-
- if (useVBOs())
- {
- if (!mMappable || gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange)
- {
- if (count == -1)
- {
- count = mNumVerts-index;
- }
-
- bool mapped = false;
- //see if range is already mapped
- for (U32 i = 0; i < mMappedVertexRegions.size(); ++i)
- {
- MappedRegion& region = mMappedVertexRegions[i];
- if (region.mType == type)
- {
- if (expand_region(region, index, count))
- {
- mapped = true;
- break;
- }
- }
- }
-
- if (!mapped)
- {
- //not already mapped, map new region
- MappedRegion region(type, mMappable && map_range ? -1 : index, count);
- mMappedVertexRegions.push_back(region);
- }
- }
-
- if (mVertexLocked && map_range)
- {
- LL_ERRS() << "Attempted to map a specific range of a buffer that was already mapped." << LL_ENDL;
- }
-
- if (!mVertexLocked)
- {
- mVertexLocked = true;
- sMappedCount++;
- stop_glerror();
-
- if(!mMappable)
- {
- map_range = false;
- }
- else
- {
- U8* src = NULL;
- waitFence();
- if (gGLManager.mHasMapBufferRange)
- {
- if (map_range)
- {
-#ifdef GL_ARB_map_buffer_range
- S32 offset = mOffsets[type] + sTypeSize[type]*index;
- S32 length = (sTypeSize[type]*count+0xF) & ~0xF;
- src = (U8*) glMapBufferRange(GL_ARRAY_BUFFER_ARB, offset, length,
- GL_MAP_WRITE_BIT |
- GL_MAP_FLUSH_EXPLICIT_BIT |
- GL_MAP_INVALIDATE_RANGE_BIT);
-#endif
- }
- else
- {
-#ifdef GL_ARB_map_buffer_range
-
- if (gDebugGL)
- {
- GLint size = 0;
- glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_SIZE_ARB, &size);
-
- if (size < mSize)
- {
- LL_ERRS() << "Invalid buffer size." << LL_ENDL;
- }
- }
-
- src = (U8*) glMapBufferRange(GL_ARRAY_BUFFER_ARB, 0, mSize,
- GL_MAP_WRITE_BIT |
- GL_MAP_FLUSH_EXPLICIT_BIT);
-#endif
- }
- }
- else if (gGLManager.mHasFlushBufferRange)
- {
- if (map_range)
- {
-#ifndef LL_MESA_HEADLESS
- glBufferParameteriAPPLE(GL_ARRAY_BUFFER_ARB, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_FALSE);
- glBufferParameteriAPPLE(GL_ARRAY_BUFFER_ARB, GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE);
-#endif
- src = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
- }
- else
- {
- src = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
- }
- }
- else
- {
- map_range = false;
- src = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
- }
-
- llassert(src != NULL);
+
+ if (count == -1)
+ {
+ count = mNumVerts - index;
+ }
- mMappedData = LL_NEXT_ALIGNED_ADDRESS<U8>(src);
- mAlignedOffset = mMappedData - src;
-
- stop_glerror();
- }
-
- if (!mMappedData)
- {
- log_glerror();
+ U32 start = mOffsets[type] + sTypeSize[type] * index;
+ U32 end = start + sTypeSize[type] * count-1;
- //check the availability of memory
- LLMemory::logMemoryInfo(true);
-
- if(mMappable)
- {
- //--------------------
- //print out more debug info before crash
- LL_INFOS() << "vertex buffer size: (num verts : num indices) = " << getNumVerts() << " : " << getNumIndices() << LL_ENDL;
- GLint size;
- glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_SIZE_ARB, &size);
- LL_INFOS() << "GL_ARRAY_BUFFER_ARB size is " << size << LL_ENDL;
- //--------------------
-
- GLint buff;
- glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &buff);
- if ((GLuint)buff != mGLBuffer)
- {
- LL_ERRS() << "Invalid GL vertex buffer bound: " << buff << LL_ENDL;
- }
-
-
- LL_ERRS() << "glMapBuffer returned NULL (no vertex data)" << LL_ENDL;
- }
- else
- {
- LL_ERRS() << "memory allocation for vertex data failed." << LL_ENDL;
- }
- }
- }
- }
- else
+ bool flagged = false;
+ // flag region as mapped
+ for (U32 i = 0; i < mMappedVertexRegions.size(); ++i)
{
- map_range = false;
- }
-
- if (map_range && gGLManager.mHasMapBufferRange && mMappable)
- {
- return mMappedData;
+ MappedRegion& region = mMappedVertexRegions[i];
+ if (expand_region(region, start, end))
+ {
+ flagged = true;
+ break;
+ }
}
- else
+
+ if (!flagged)
{
- return mMappedData+mOffsets[type]+sTypeSize[type]*index;
+ //didn't expand an existing region, make a new one
+ mMappedVertexRegions.push_back({ start, end });
}
+
+ return mMappedData+mOffsets[type]+sTypeSize[type]*index;
}
-U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range)
+U8* LLVertexBuffer::mapIndexBuffer(U32 index, S32 count)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX;
- bindGLIndices(true);
- if (mFinal)
- {
- LL_ERRS() << "LLVertexBuffer::mapIndexBuffer() called on a finalized buffer." << LL_ENDL;
- }
- if (!useVBOs() && !mMappedData && !mMappedIndexData)
+
+ if (count == -1)
{
- LL_ERRS() << "LLVertexBuffer::mapIndexBuffer() called on unallocated buffer." << LL_ENDL;
+ count = mNumIndices-index;
}
- if (useVBOs())
- {
- if (!mMappable || gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange)
- {
- if (count == -1)
- {
- count = mNumIndices-index;
- }
-
- bool mapped = false;
- //see if range is already mapped
- for (U32 i = 0; i < mMappedIndexRegions.size(); ++i)
- {
- MappedRegion& region = mMappedIndexRegions[i];
- if (expand_region(region, index, count))
- {
- mapped = true;
- break;
- }
- }
-
- if (!mapped)
- {
- //not already mapped, map new region
- MappedRegion region(TYPE_INDEX, mMappable && map_range ? -1 : index, count);
- mMappedIndexRegions.push_back(region);
- }
- }
-
- if (mIndexLocked && map_range)
- {
- LL_ERRS() << "Attempted to map a specific range of a buffer that was already mapped." << LL_ENDL;
- }
-
- if (!mIndexLocked)
- {
- mIndexLocked = true;
- sMappedCount++;
- stop_glerror();
-
- if (gDebugGL && useVBOs())
- {
- GLint elem = 0;
- glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &elem);
-
- if (elem != mGLIndices)
- {
- LL_ERRS() << "Wrong index buffer bound!" << LL_ENDL;
- }
- }
-
- if(!mMappable)
- {
- map_range = false;
- }
- else
- {
- U8* src = NULL;
- waitFence();
- if (gGLManager.mHasMapBufferRange)
- {
- if (map_range)
- {
-#ifdef GL_ARB_map_buffer_range
- S32 offset = sizeof(U16)*index;
- S32 length = sizeof(U16)*count;
- src = (U8*) glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length,
- GL_MAP_WRITE_BIT |
- GL_MAP_FLUSH_EXPLICIT_BIT |
- GL_MAP_INVALIDATE_RANGE_BIT);
-#endif
- }
- else
- {
-#ifdef GL_ARB_map_buffer_range
- src = (U8*) glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, sizeof(U16)*mNumIndices,
- GL_MAP_WRITE_BIT |
- GL_MAP_FLUSH_EXPLICIT_BIT);
-#endif
- }
- }
- else if (gGLManager.mHasFlushBufferRange)
- {
- if (map_range)
- {
-#ifndef LL_MESA_HEADLESS
- glBufferParameteriAPPLE(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_FALSE);
- glBufferParameteriAPPLE(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE);
-#endif
- src = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
- }
- else
- {
- src = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
- }
- }
- else
- {
- map_range = false;
- src = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
- }
-
- llassert(src != NULL);
+ U32 start = sizeof(U16) * index;
+ U32 end = start + sizeof(U16) * count-1;
+ bool flagged = false;
+ // flag region as mapped
+ for (U32 i = 0; i < mMappedIndexRegions.size(); ++i)
+ {
+ MappedRegion& region = mMappedIndexRegions[i];
+ if (expand_region(region, start, end))
+ {
+ flagged = true;
+ break;
+ }
+ }
- mMappedIndexData = src; //LL_NEXT_ALIGNED_ADDRESS<U8>(src);
- mAlignedIndexOffset = mMappedIndexData - src;
- stop_glerror();
- }
- }
+ if (!flagged)
+ {
+ //didn't expand an existing region, make a new one
+ mMappedIndexRegions.push_back({ start, end });
+ }
- if (!mMappedIndexData)
- {
- log_glerror();
- LLMemory::logMemoryInfo(true);
+ return mMappedIndexData + sizeof(U16)*index;
+}
- if(mMappable)
- {
- GLint buff;
- glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &buff);
- if ((GLuint)buff != mGLIndices)
- {
- LL_ERRS() << "Invalid GL index buffer bound: " << buff << LL_ENDL;
- }
+// flush the given byte range
+// target -- "targret" parameter for glBufferSubData
+// start -- first byte to copy
+// end -- last byte to copy (NOT last byte + 1)
+// data -- mMappedData or mMappedIndexData
+static void flush_vbo(GLenum target, U32 start, U32 end, void* data)
+{
+ if (end != 0)
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("glBufferSubData");
+ LL_PROFILE_ZONE_NUM(start);
+ LL_PROFILE_ZONE_NUM(end);
+ LL_PROFILE_ZONE_NUM(end-start);
- LL_ERRS() << "glMapBuffer returned NULL (no index data)" << LL_ENDL;
- }
- else
- {
- LL_ERRS() << "memory allocation for Index data failed. " << LL_ENDL;
- }
- }
- }
- else
- {
- map_range = false;
- }
+ constexpr U32 block_size = 8192;
- if (map_range && gGLManager.mHasMapBufferRange && mMappable)
- {
- return mMappedIndexData;
- }
- else
- {
- return mMappedIndexData + sizeof(U16)*index;
- }
+ for (U32 i = start; i <= end; i += block_size)
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("glBufferSubData block");
+ //LL_PROFILE_GPU_ZONE("glBufferSubData");
+ U32 tend = llmin(i + block_size, end);
+ U32 size = tend - i + 1;
+ glBufferSubData(target, i, size, (U8*) data + (i-start));
+ }
+ }
}
void LLVertexBuffer::unmapBuffer()
{
- if (!useVBOs())
- {
- return; //nothing to unmap
- }
+ struct SortMappedRegion
+ {
+ bool operator()(const MappedRegion& lhs, const MappedRegion& rhs)
+ {
+ return lhs.mStart < rhs.mStart;
+ }
+ };
- bool updated_all = false;
- LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX;
- if (mMappedData && mVertexLocked)
+ if (!mMappedVertexRegions.empty())
{
LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("unmapBuffer - vertex");
- bindGLBuffer(true);
- updated_all = mIndexLocked; //both vertex and index buffers done updating
+ if (sGLRenderBuffer != mGLBuffer)
+ {
+ glBindBuffer(GL_ARRAY_BUFFER, mGLBuffer);
+ sGLRenderBuffer = mGLBuffer;
+ }
+
+ U32 start = 0;
+ U32 end = 0;
- if(!mMappable)
- {
- if (!mMappedVertexRegions.empty())
- {
- stop_glerror();
- for (U32 i = 0; i < mMappedVertexRegions.size(); ++i)
- {
- const MappedRegion& region = mMappedVertexRegions[i];
- S32 offset = region.mIndex >= 0 ? mOffsets[region.mType]+sTypeSize[region.mType]*region.mIndex : 0;
- S32 length = sTypeSize[region.mType]*region.mCount;
- if (mSize >= length + offset)
- {
- glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, offset, length, (U8*)mMappedData + offset);
- }
- else
- {
- GLint size = 0;
- glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_SIZE_ARB, &size);
- LL_WARNS() << "Attempted to map regions to a buffer that is too small, "
- << "mapped size: " << mSize
- << ", gl buffer size: " << size
- << ", length: " << length
- << ", offset: " << offset
- << LL_ENDL;
- }
- stop_glerror();
- }
+ std::sort(mMappedVertexRegions.begin(), mMappedVertexRegions.end(), SortMappedRegion());
- mMappedVertexRegions.clear();
- }
- else
- {
- stop_glerror();
- glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, getSize(), (U8*) mMappedData);
- stop_glerror();
- }
- }
- else
+ for (U32 i = 0; i < mMappedVertexRegions.size(); ++i)
{
- if (gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange)
- {
- if (!mMappedVertexRegions.empty())
- {
- LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("unmapBuffer - flush vertex");
- for (U32 i = 0; i < mMappedVertexRegions.size(); ++i)
- {
- const MappedRegion& region = mMappedVertexRegions[i];
- S32 offset = region.mIndex >= 0 ? mOffsets[region.mType]+sTypeSize[region.mType]*region.mIndex : 0;
- S32 length = sTypeSize[region.mType]*region.mCount;
- if (gGLManager.mHasMapBufferRange)
- {
-#ifdef GL_ARB_map_buffer_range
- glFlushMappedBufferRange(GL_ARRAY_BUFFER_ARB, offset, length);
-#endif
- }
- else if (gGLManager.mHasFlushBufferRange)
- {
-#ifndef LL_MESA_HEADLESS
- glFlushMappedBufferRangeAPPLE(GL_ARRAY_BUFFER_ARB, offset, length);
-#endif
- }
- }
-
- mMappedVertexRegions.clear();
- }
- }
- stop_glerror();
- glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
- stop_glerror();
-
- mMappedData = NULL;
+ const MappedRegion& region = mMappedVertexRegions[i];
+ if (region.mStart == end + 1)
+ {
+ end = region.mEnd;
+ }
+ else
+ {
+ flush_vbo(GL_ARRAY_BUFFER, start, end, (U8*)mMappedData + start);
+ start = region.mStart;
+ end = region.mEnd;
+ }
}
- mVertexLocked = false;
- sMappedCount--;
+ flush_vbo(GL_ARRAY_BUFFER, start, end, (U8*)mMappedData + start);
+
+ mMappedVertexRegions.clear();
}
- if (mMappedIndexData && mIndexLocked)
+ if (!mMappedIndexRegions.empty())
{
LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("unmapBuffer - index");
- bindGLIndices();
- if(!mMappable)
- {
- if (!mMappedIndexRegions.empty())
- {
- for (U32 i = 0; i < mMappedIndexRegions.size(); ++i)
- {
- const MappedRegion& region = mMappedIndexRegions[i];
- S32 offset = region.mIndex >= 0 ? sizeof(U16)*region.mIndex : 0;
- S32 length = sizeof(U16)*region.mCount;
- if (mIndicesSize >= length + offset)
- {
- glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length, (U8*) mMappedIndexData+offset);
- }
- else
- {
- GLint size = 0;
- glGetBufferParameterivARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_BUFFER_SIZE_ARB, &size);
- LL_WARNS() << "Attempted to map regions to a buffer that is too small, "
- << "mapped size: " << mIndicesSize
- << ", gl buffer size: " << size
- << ", length: " << length
- << ", offset: " << offset
- << LL_ENDL;
- }
- stop_glerror();
- }
- mMappedIndexRegions.clear();
- }
- else
- {
- stop_glerror();
- glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, getIndicesSize(), (U8*) mMappedIndexData);
- stop_glerror();
- }
- }
- else
- {
- if (gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange)
- {
- if (!mMappedIndexRegions.empty())
- {
- for (U32 i = 0; i < mMappedIndexRegions.size(); ++i)
- {
- LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("unmapBuffer - flush index");
- const MappedRegion& region = mMappedIndexRegions[i];
- S32 offset = region.mIndex >= 0 ? sizeof(U16)*region.mIndex : 0;
- S32 length = sizeof(U16)*region.mCount;
- if (gGLManager.mHasMapBufferRange)
- {
-#ifdef GL_ARB_map_buffer_range
- glFlushMappedBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length);
-#endif
- }
- else if (gGLManager.mHasFlushBufferRange)
- {
-#ifdef GL_APPLE_flush_buffer_range
-#ifndef LL_MESA_HEADLESS
- glFlushMappedBufferRangeAPPLE(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length);
-#endif
-#endif
- }
- stop_glerror();
- }
+ if (mGLIndices != sGLRenderIndices)
+ {
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mGLIndices);
+ sGLRenderIndices = mGLIndices;
+ }
+ U32 start = 0;
+ U32 end = 0;
- mMappedIndexRegions.clear();
- }
- }
-
- glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB);
+ std::sort(mMappedIndexRegions.begin(), mMappedIndexRegions.end(), SortMappedRegion());
- mMappedIndexData = NULL;
- }
+ for (U32 i = 0; i < mMappedIndexRegions.size(); ++i)
+ {
+ const MappedRegion& region = mMappedIndexRegions[i];
+ if (region.mStart == end + 1)
+ {
+ end = region.mEnd;
+ }
+ else
+ {
+ flush_vbo(GL_ELEMENT_ARRAY_BUFFER, start, end, (U8*)mMappedIndexData + start);
+ start = region.mStart;
+ end = region.mEnd;
+ }
+ }
- mIndexLocked = false;
- sMappedCount--;
- }
+ flush_vbo(GL_ELEMENT_ARRAY_BUFFER, start, end, (U8*)mMappedIndexData + start);
- if(updated_all)
- {
- mEmpty = false;
+ mMappedIndexRegions.clear();
}
}
//----------------------------------------------------------------------------
-template <class T,S32 type> struct VertexBufferStrider
+template <class T,LLVertexBuffer::AttributeType type> struct VertexBufferStrider
{
typedef LLStrider<T> strider_t;
static bool get(LLVertexBuffer& vbo,
strider_t& strider,
- S32 index, S32 count, bool map_range)
+ S32 index, S32 count)
{
if (type == LLVertexBuffer::TYPE_INDEX)
{
- U8* ptr = vbo.mapIndexBuffer(index, count, map_range);
+ U8* ptr = vbo.mapIndexBuffer(index, count);
if (ptr == NULL)
{
@@ -1975,9 +1266,9 @@ template <class T,S32 type> struct VertexBufferStrider
}
else if (vbo.hasDataType(type))
{
- S32 stride = LLVertexBuffer::sTypeSize[type];
+ U32 stride = LLVertexBuffer::sTypeSize[type];
- U8* ptr = vbo.mapVertexBuffer(type, index, count, map_range);
+ U8* ptr = vbo.mapVertexBuffer(type, index, count);
if (ptr == NULL)
{
@@ -1997,590 +1288,214 @@ template <class T,S32 type> struct VertexBufferStrider
}
};
-bool LLVertexBuffer::getVertexStrider(LLStrider<LLVector3>& strider, S32 index, S32 count, bool map_range)
+bool LLVertexBuffer::getVertexStrider(LLStrider<LLVector3>& strider, U32 index, S32 count)
{
- return VertexBufferStrider<LLVector3,TYPE_VERTEX>::get(*this, strider, index, count, map_range);
+ return VertexBufferStrider<LLVector3,TYPE_VERTEX>::get(*this, strider, index, count);
}
-bool LLVertexBuffer::getVertexStrider(LLStrider<LLVector4a>& strider, S32 index, S32 count, bool map_range)
+bool LLVertexBuffer::getVertexStrider(LLStrider<LLVector4a>& strider, U32 index, S32 count)
{
- return VertexBufferStrider<LLVector4a,TYPE_VERTEX>::get(*this, strider, index, count, map_range);
+ return VertexBufferStrider<LLVector4a,TYPE_VERTEX>::get(*this, strider, index, count);
}
-bool LLVertexBuffer::getIndexStrider(LLStrider<U16>& strider, S32 index, S32 count, bool map_range)
+bool LLVertexBuffer::getIndexStrider(LLStrider<U16>& strider, U32 index, S32 count)
{
- return VertexBufferStrider<U16,TYPE_INDEX>::get(*this, strider, index, count, map_range);
+ return VertexBufferStrider<U16,TYPE_INDEX>::get(*this, strider, index, count);
}
-bool LLVertexBuffer::getTexCoord0Strider(LLStrider<LLVector2>& strider, S32 index, S32 count, bool map_range)
+bool LLVertexBuffer::getTexCoord0Strider(LLStrider<LLVector2>& strider, U32 index, S32 count)
{
- return VertexBufferStrider<LLVector2,TYPE_TEXCOORD0>::get(*this, strider, index, count, map_range);
+ return VertexBufferStrider<LLVector2,TYPE_TEXCOORD0>::get(*this, strider, index, count);
}
-bool LLVertexBuffer::getTexCoord1Strider(LLStrider<LLVector2>& strider, S32 index, S32 count, bool map_range)
+bool LLVertexBuffer::getTexCoord1Strider(LLStrider<LLVector2>& strider, U32 index, S32 count)
{
- return VertexBufferStrider<LLVector2,TYPE_TEXCOORD1>::get(*this, strider, index, count, map_range);
+ return VertexBufferStrider<LLVector2,TYPE_TEXCOORD1>::get(*this, strider, index, count);
}
-bool LLVertexBuffer::getTexCoord2Strider(LLStrider<LLVector2>& strider, S32 index, S32 count, bool map_range)
+bool LLVertexBuffer::getTexCoord2Strider(LLStrider<LLVector2>& strider, U32 index, S32 count)
{
- return VertexBufferStrider<LLVector2,TYPE_TEXCOORD2>::get(*this, strider, index, count, map_range);
+ return VertexBufferStrider<LLVector2,TYPE_TEXCOORD2>::get(*this, strider, index, count);
}
-bool LLVertexBuffer::getNormalStrider(LLStrider<LLVector3>& strider, S32 index, S32 count, bool map_range)
+bool LLVertexBuffer::getNormalStrider(LLStrider<LLVector3>& strider, U32 index, S32 count)
{
- return VertexBufferStrider<LLVector3,TYPE_NORMAL>::get(*this, strider, index, count, map_range);
+ return VertexBufferStrider<LLVector3,TYPE_NORMAL>::get(*this, strider, index, count);
}
-bool LLVertexBuffer::getTangentStrider(LLStrider<LLVector3>& strider, S32 index, S32 count, bool map_range)
+bool LLVertexBuffer::getTangentStrider(LLStrider<LLVector3>& strider, U32 index, S32 count)
{
- return VertexBufferStrider<LLVector3,TYPE_TANGENT>::get(*this, strider, index, count, map_range);
+ return VertexBufferStrider<LLVector3,TYPE_TANGENT>::get(*this, strider, index, count);
}
-bool LLVertexBuffer::getTangentStrider(LLStrider<LLVector4a>& strider, S32 index, S32 count, bool map_range)
+bool LLVertexBuffer::getTangentStrider(LLStrider<LLVector4a>& strider, U32 index, S32 count)
{
- return VertexBufferStrider<LLVector4a,TYPE_TANGENT>::get(*this, strider, index, count, map_range);
+ return VertexBufferStrider<LLVector4a,TYPE_TANGENT>::get(*this, strider, index, count);
}
-bool LLVertexBuffer::getColorStrider(LLStrider<LLColor4U>& strider, S32 index, S32 count, bool map_range)
+bool LLVertexBuffer::getColorStrider(LLStrider<LLColor4U>& strider, U32 index, S32 count)
{
- return VertexBufferStrider<LLColor4U,TYPE_COLOR>::get(*this, strider, index, count, map_range);
+ return VertexBufferStrider<LLColor4U,TYPE_COLOR>::get(*this, strider, index, count);
}
-bool LLVertexBuffer::getEmissiveStrider(LLStrider<LLColor4U>& strider, S32 index, S32 count, bool map_range)
+bool LLVertexBuffer::getEmissiveStrider(LLStrider<LLColor4U>& strider, U32 index, S32 count)
{
- return VertexBufferStrider<LLColor4U,TYPE_EMISSIVE>::get(*this, strider, index, count, map_range);
+ return VertexBufferStrider<LLColor4U,TYPE_EMISSIVE>::get(*this, strider, index, count);
}
-bool LLVertexBuffer::getWeightStrider(LLStrider<F32>& strider, S32 index, S32 count, bool map_range)
+bool LLVertexBuffer::getWeightStrider(LLStrider<F32>& strider, U32 index, S32 count)
{
- return VertexBufferStrider<F32,TYPE_WEIGHT>::get(*this, strider, index, count, map_range);
+ return VertexBufferStrider<F32,TYPE_WEIGHT>::get(*this, strider, index, count);
}
-bool LLVertexBuffer::getWeight4Strider(LLStrider<LLVector4>& strider, S32 index, S32 count, bool map_range)
+bool LLVertexBuffer::getWeight4Strider(LLStrider<LLVector4>& strider, U32 index, S32 count)
{
- return VertexBufferStrider<LLVector4,TYPE_WEIGHT4>::get(*this, strider, index, count, map_range);
+ return VertexBufferStrider<LLVector4,TYPE_WEIGHT4>::get(*this, strider, index, count);
}
-bool LLVertexBuffer::getClothWeightStrider(LLStrider<LLVector4>& strider, S32 index, S32 count, bool map_range)
+bool LLVertexBuffer::getClothWeightStrider(LLStrider<LLVector4>& strider, U32 index, S32 count)
{
- return VertexBufferStrider<LLVector4,TYPE_CLOTHWEIGHT>::get(*this, strider, index, count, map_range);
+ return VertexBufferStrider<LLVector4,TYPE_CLOTHWEIGHT>::get(*this, strider, index, count);
}
//----------------------------------------------------------------------------
-bool LLVertexBuffer::bindGLArray()
-{
- if (mGLArray && sGLRenderArray != mGLArray)
- {
- {
- LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX;
-#if GL_ARB_vertex_array_object
- glBindVertexArray(mGLArray);
-#endif
- sGLRenderArray = mGLArray;
- }
- //really shouldn't be necessary, but some drivers don't properly restore the
- //state of GL_ELEMENT_ARRAY_BUFFER_BINDING
- bindGLIndices();
-
- return true;
- }
-
- return false;
-}
-
-bool LLVertexBuffer::bindGLBuffer(bool force_bind)
+// Set for rendering
+void LLVertexBuffer::setBuffer()
{
- bindGLArray();
+ // no data may be pending
+ llassert(mMappedVertexRegions.empty());
+ llassert(mMappedIndexRegions.empty());
- bool ret = false;
+ // a shader must be bound
+ llassert(LLGLSLShader::sCurBoundShaderPtr);
- if (useVBOs() && (force_bind || (mGLBuffer && (mGLBuffer != sGLRenderBuffer || !sVBOActive))))
- {
- LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX;
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, mGLBuffer);
- sGLRenderBuffer = mGLBuffer;
- sBindCount++;
- sVBOActive = true;
-
- llassert(!mGLArray || sGLRenderArray == mGLArray);
-
- ret = true;
- }
+ U32 data_mask = LLGLSLShader::sCurBoundShaderPtr->mAttributeMask;
- return ret;
-}
+ // this Vertex Buffer must provide all necessary attributes for currently bound shader
+ llassert(((~data_mask & mTypeMask) > 0) || (mTypeMask == data_mask));
-bool LLVertexBuffer::bindGLBufferFast()
-{
- if (mGLBuffer != sGLRenderBuffer || !sVBOActive)
+ if (sGLRenderBuffer != mGLBuffer)
{
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, mGLBuffer);
+ glBindBuffer(GL_ARRAY_BUFFER, mGLBuffer);
sGLRenderBuffer = mGLBuffer;
- sBindCount++;
- sVBOActive = true;
-
- return true;
- }
-
- return false;
-}
-bool LLVertexBuffer::bindGLIndices(bool force_bind)
-{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX;
- bindGLArray();
-
- bool ret = false;
- if (useVBOs() && (force_bind || (mGLIndices && (mGLIndices != sGLRenderIndices || !sIBOActive))))
- {
- /*if (sMapped)
- {
- LL_ERRS() << "VBO bound while another VBO mapped!" << LL_ENDL;
- }*/
- glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, mGLIndices);
- sGLRenderIndices = mGLIndices;
- stop_glerror();
- sBindCount++;
- sIBOActive = true;
- ret = true;
- }
-
- return ret;
-}
-
-bool LLVertexBuffer::bindGLIndicesFast()
-{
- if (mGLIndices != sGLRenderIndices || !sIBOActive)
- {
- glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, mGLIndices);
- sGLRenderIndices = mGLIndices;
- sBindCount++;
- sIBOActive = true;
-
- return true;
+ setupVertexBuffer();
}
-
- return false;
-}
-
-void LLVertexBuffer::flush()
-{
- if (useVBOs())
- {
- unmapBuffer();
- }
-}
-
-// bind for transform feedback (quick 'n dirty)
-void LLVertexBuffer::bindForFeedback(U32 channel, U32 type, U32 index, U32 count)
-{
-#ifdef GL_TRANSFORM_FEEDBACK_BUFFER
- U32 offset = mOffsets[type] + sTypeSize[type]*index;
- U32 size= (sTypeSize[type]*count);
- glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, channel, mGLBuffer, offset, size);
-#endif
-}
-
-// Set for rendering
-void LLVertexBuffer::setBuffer(U32 data_mask)
-{
- flush();
-
- //set up pointers if the data mask is different ...
- bool setup = (sLastMask != data_mask);
-
- if (gDebugGL && data_mask != 0)
- { //make sure data requirements are fulfilled
- LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
- if (shader)
- {
- U32 required_mask = 0;
- for (U32 i = 0; i < LLVertexBuffer::TYPE_TEXTURE_INDEX; ++i)
- {
- if (shader->getAttribLocation(i) > -1)
- {
- U32 required = 1 << i;
- if ((data_mask & required) == 0)
- {
- LL_WARNS() << "Missing attribute: " << LLShaderMgr::instance()->mReservedAttribs[i] << LL_ENDL;
- }
-
- required_mask |= required;
- }
- }
-
- if ((data_mask & required_mask) != required_mask)
- {
-
- U32 unsatisfied_mask = (required_mask & ~data_mask);
-
- for (U32 i = 0; i < TYPE_MAX; i++)
- {
- U32 unsatisfied_flag = unsatisfied_mask & (1 << i);
- switch (unsatisfied_flag)
- {
- case 0: break;
- case MAP_VERTEX: LL_INFOS() << "Missing vert pos" << LL_ENDL; break;
- case MAP_NORMAL: LL_INFOS() << "Missing normals" << LL_ENDL; break;
- case MAP_TEXCOORD0: LL_INFOS() << "Missing TC 0" << LL_ENDL; break;
- case MAP_TEXCOORD1: LL_INFOS() << "Missing TC 1" << LL_ENDL; break;
- case MAP_TEXCOORD2: LL_INFOS() << "Missing TC 2" << LL_ENDL; break;
- case MAP_TEXCOORD3: LL_INFOS() << "Missing TC 3" << LL_ENDL; break;
- case MAP_COLOR: LL_INFOS() << "Missing vert color" << LL_ENDL; break;
- case MAP_EMISSIVE: LL_INFOS() << "Missing emissive" << LL_ENDL; break;
- case MAP_TANGENT: LL_INFOS() << "Missing tangent" << LL_ENDL; break;
- case MAP_WEIGHT: LL_INFOS() << "Missing weight" << LL_ENDL; break;
- case MAP_WEIGHT4: LL_INFOS() << "Missing weightx4" << LL_ENDL; break;
- case MAP_CLOTHWEIGHT: LL_INFOS() << "Missing clothweight" << LL_ENDL; break;
- case MAP_TEXTURE_INDEX: LL_INFOS() << "Missing tex index" << LL_ENDL; break;
- default: LL_INFOS() << "Missing who effin knows: " << unsatisfied_flag << LL_ENDL;
- }
- }
-
- // TYPE_INDEX is beyond TYPE_MAX, so check for it individually
- if (unsatisfied_mask & (1 << TYPE_INDEX))
- {
- LL_INFOS() << "Missing indices" << LL_ENDL;
- }
-
- LL_ERRS() << "Shader consumption mismatches data provision." << LL_ENDL;
- }
- }
- }
-
- if (useVBOs())
- {
- if (mGLArray)
- {
- bindGLArray();
- setup = false; //do NOT perform pointer setup if using VAO
- }
- else
- {
- const bool bindBuffer = bindGLBuffer();
- const bool bindIndices = bindGLIndices();
-
- setup = setup || bindBuffer || bindIndices;
- }
-
- if (gDebugGL && !mGLArray)
- {
- GLint buff;
- glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &buff);
- if ((GLuint)buff != mGLBuffer)
- {
- if (gDebugSession)
- {
- gFailLog << "Invalid GL vertex buffer bound: " << buff << std::endl;
- }
- else
- {
- LL_ERRS() << "Invalid GL vertex buffer bound: " << buff << LL_ENDL;
- }
- }
-
- if (mGLIndices)
- {
- glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &buff);
- if ((GLuint)buff != mGLIndices)
- {
- if (gDebugSession)
- {
- gFailLog << "Invalid GL index buffer bound: " << buff << std::endl;
- }
- else
- {
- LL_ERRS() << "Invalid GL index buffer bound: " << buff << LL_ENDL;
- }
- }
- }
- }
-
-
- }
- else
- {
- if (sGLRenderArray)
- {
-#if GL_ARB_vertex_array_object
- glBindVertexArray(0);
-#endif
- sGLRenderArray = 0;
- sGLRenderIndices = 0;
- sIBOActive = false;
- }
-
- if (mGLBuffer)
- {
- if (sVBOActive)
- {
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
- sBindCount++;
- sVBOActive = false;
- setup = true; // ... or a VBO is deactivated
- }
- if (sGLRenderBuffer != mGLBuffer)
- {
- sGLRenderBuffer = mGLBuffer;
- setup = true; // ... or a client memory pointer changed
- }
- }
- if (mGLIndices)
- {
- if (sIBOActive)
- {
- glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
- sBindCount++;
- sIBOActive = false;
- }
-
- sGLRenderIndices = mGLIndices;
- }
- }
-
- if (!mGLArray)
- {
- setupClientArrays(data_mask);
- }
-
- if (mGLBuffer)
- {
- if (data_mask && setup)
- {
- setupVertexBuffer(data_mask); // subclass specific setup (virtual function)
- sSetCount++;
- }
- }
-}
-
-void LLVertexBuffer::setBufferFast(U32 data_mask)
-{
- if (useVBOs())
+ else if (sLastMask != data_mask)
{
- //set up pointers if the data mask is different ...
- bool setup = (sLastMask != data_mask);
-
- const bool bindBuffer = bindGLBufferFast();
- const bool bindIndices = bindGLIndicesFast();
-
- setup = setup || bindBuffer || bindIndices;
-
- setupClientArrays(data_mask);
-
- if (data_mask && setup)
- {
- setupVertexBufferFast(data_mask);
- sSetCount++;
- }
+ setupVertexBuffer();
+ sLastMask = data_mask;
}
- else
+
+ if (mGLIndices != sGLRenderIndices)
{
- //fallback to slow path when not using VBOs
- setBuffer(data_mask);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mGLIndices);
+ sGLRenderIndices = mGLIndices;
}
}
// virtual (default)
-void LLVertexBuffer::setupVertexBuffer(U32 data_mask)
+void LLVertexBuffer::setupVertexBuffer()
{
- stop_glerror();
- U8* base = useVBOs() ? (U8*) mAlignedOffset : mMappedData;
+ U8* base = nullptr;
- if (gDebugGL && ((data_mask & mTypeMask) != data_mask))
- {
- for (U32 i = 0; i < LLVertexBuffer::TYPE_MAX; ++i)
- {
- U32 mask = 1 << i;
- if (mask & data_mask && !(mask & mTypeMask))
- { //bit set in data_mask, but not set in mTypeMask
- LL_WARNS() << "Missing required component " << vb_type_name[i] << LL_ENDL;
- }
- }
- LL_ERRS() << "LLVertexBuffer::setupVertexBuffer missing required components for supplied data mask." << LL_ENDL;
- }
-
- if (data_mask & MAP_NORMAL)
- {
- S32 loc = TYPE_NORMAL;
- void* ptr = (void*)(base + mOffsets[TYPE_NORMAL]);
- glVertexAttribPointerARB(loc, 3, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_NORMAL], ptr);
- }
- if (data_mask & MAP_TEXCOORD3)
- {
- S32 loc = TYPE_TEXCOORD3;
- void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD3]);
- glVertexAttribPointerARB(loc,2,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD3], ptr);
- }
- if (data_mask & MAP_TEXCOORD2)
- {
- S32 loc = TYPE_TEXCOORD2;
- void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD2]);
- glVertexAttribPointerARB(loc,2,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD2], ptr);
- }
- if (data_mask & MAP_TEXCOORD1)
- {
- S32 loc = TYPE_TEXCOORD1;
- void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD1]);
- glVertexAttribPointerARB(loc,2,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD1], ptr);
- }
- if (data_mask & MAP_TANGENT)
- {
- S32 loc = TYPE_TANGENT;
- void* ptr = (void*)(base + mOffsets[TYPE_TANGENT]);
- glVertexAttribPointerARB(loc, 4,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TANGENT], ptr);
- }
- if (data_mask & MAP_TEXCOORD0)
- {
- S32 loc = TYPE_TEXCOORD0;
- void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD0]);
- glVertexAttribPointerARB(loc,2,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD0], ptr);
- }
- if (data_mask & MAP_COLOR)
- {
- S32 loc = TYPE_COLOR;
- //bind emissive instead of color pointer if emissive is present
- void* ptr = (data_mask & MAP_EMISSIVE) ? (void*)(base + mOffsets[TYPE_EMISSIVE]) : (void*)(base + mOffsets[TYPE_COLOR]);
- glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_COLOR], ptr);
- }
- if (data_mask & MAP_EMISSIVE)
- {
- S32 loc = TYPE_EMISSIVE;
- void* ptr = (void*)(base + mOffsets[TYPE_EMISSIVE]);
- glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_EMISSIVE], ptr);
-
- if (!(data_mask & MAP_COLOR))
- { //map emissive to color channel when color is not also being bound to avoid unnecessary shader swaps
- loc = TYPE_COLOR;
- glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_EMISSIVE], ptr);
- }
- }
- if (data_mask & MAP_WEIGHT)
- {
- S32 loc = TYPE_WEIGHT;
- void* ptr = (void*)(base + mOffsets[TYPE_WEIGHT]);
- glVertexAttribPointerARB(loc, 1, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT], ptr);
- }
- if (data_mask & MAP_WEIGHT4)
- {
- S32 loc = TYPE_WEIGHT4;
- void* ptr = (void*)(base+mOffsets[TYPE_WEIGHT4]);
- glVertexAttribPointerARB(loc, 4, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT4], ptr);
- }
- if (data_mask & MAP_CLOTHWEIGHT)
- {
- S32 loc = TYPE_CLOTHWEIGHT;
- void* ptr = (void*)(base + mOffsets[TYPE_CLOTHWEIGHT]);
- glVertexAttribPointerARB(loc, 4, GL_FLOAT, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_CLOTHWEIGHT], ptr);
- }
- if (data_mask & MAP_TEXTURE_INDEX &&
- (gGLManager.mGLSLVersionMajor >= 2 || gGLManager.mGLSLVersionMinor >= 30)) //indexed texture rendering requires GLSL 1.30 or later
- {
-#if !LL_DARWIN
- S32 loc = TYPE_TEXTURE_INDEX;
- void *ptr = (void*) (base + mOffsets[TYPE_VERTEX] + 12);
- glVertexAttribIPointer(loc, 1, GL_UNSIGNED_INT, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr);
-#endif
- }
- if (data_mask & MAP_VERTEX)
- {
- S32 loc = TYPE_VERTEX;
- void* ptr = (void*)(base + mOffsets[TYPE_VERTEX]);
- glVertexAttribPointerARB(loc, 3,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr);
- }
-
- llglassertok();
-}
-
-void LLVertexBuffer::setupVertexBufferFast(U32 data_mask)
-{
- U8* base = (U8*)mAlignedOffset;
+ U32 data_mask = LLGLSLShader::sCurBoundShaderPtr->mAttributeMask;
if (data_mask & MAP_NORMAL)
{
- S32 loc = TYPE_NORMAL;
+ AttributeType loc = TYPE_NORMAL;
void* ptr = (void*)(base + mOffsets[TYPE_NORMAL]);
- glVertexAttribPointerARB(loc, 3, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_NORMAL], ptr);
+ glVertexAttribPointer(loc, 3, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_NORMAL], ptr);
}
if (data_mask & MAP_TEXCOORD3)
{
- S32 loc = TYPE_TEXCOORD3;
+ AttributeType loc = TYPE_TEXCOORD3;
void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD3]);
- glVertexAttribPointerARB(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD3], ptr);
+ glVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD3], ptr);
}
if (data_mask & MAP_TEXCOORD2)
{
- S32 loc = TYPE_TEXCOORD2;
+ AttributeType loc = TYPE_TEXCOORD2;
void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD2]);
- glVertexAttribPointerARB(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD2], ptr);
+ glVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD2], ptr);
}
if (data_mask & MAP_TEXCOORD1)
{
- S32 loc = TYPE_TEXCOORD1;
+ AttributeType loc = TYPE_TEXCOORD1;
void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD1]);
- glVertexAttribPointerARB(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD1], ptr);
+ glVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD1], ptr);
}
if (data_mask & MAP_TANGENT)
{
- S32 loc = TYPE_TANGENT;
+ AttributeType loc = TYPE_TANGENT;
void* ptr = (void*)(base + mOffsets[TYPE_TANGENT]);
- glVertexAttribPointerARB(loc, 4, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TANGENT], ptr);
+ glVertexAttribPointer(loc, 4, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TANGENT], ptr);
}
if (data_mask & MAP_TEXCOORD0)
{
- S32 loc = TYPE_TEXCOORD0;
+ AttributeType loc = TYPE_TEXCOORD0;
void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD0]);
- glVertexAttribPointerARB(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD0], ptr);
+ glVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD0], ptr);
}
if (data_mask & MAP_COLOR)
{
- S32 loc = TYPE_COLOR;
+ AttributeType loc = TYPE_COLOR;
//bind emissive instead of color pointer if emissive is present
void* ptr = (data_mask & MAP_EMISSIVE) ? (void*)(base + mOffsets[TYPE_EMISSIVE]) : (void*)(base + mOffsets[TYPE_COLOR]);
- glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_COLOR], ptr);
+ glVertexAttribPointer(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_COLOR], ptr);
}
if (data_mask & MAP_EMISSIVE)
{
- S32 loc = TYPE_EMISSIVE;
+ AttributeType loc = TYPE_EMISSIVE;
void* ptr = (void*)(base + mOffsets[TYPE_EMISSIVE]);
- glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_EMISSIVE], ptr);
+ glVertexAttribPointer(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_EMISSIVE], ptr);
if (!(data_mask & MAP_COLOR))
{ //map emissive to color channel when color is not also being bound to avoid unnecessary shader swaps
loc = TYPE_COLOR;
- glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_EMISSIVE], ptr);
+ glVertexAttribPointer(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_EMISSIVE], ptr);
}
}
if (data_mask & MAP_WEIGHT)
{
- S32 loc = TYPE_WEIGHT;
+ AttributeType loc = TYPE_WEIGHT;
void* ptr = (void*)(base + mOffsets[TYPE_WEIGHT]);
- glVertexAttribPointerARB(loc, 1, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT], ptr);
+ glVertexAttribPointer(loc, 1, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT], ptr);
}
if (data_mask & MAP_WEIGHT4)
{
- S32 loc = TYPE_WEIGHT4;
+ AttributeType loc = TYPE_WEIGHT4;
void* ptr = (void*)(base + mOffsets[TYPE_WEIGHT4]);
- glVertexAttribPointerARB(loc, 4, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT4], ptr);
+ glVertexAttribPointer(loc, 4, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT4], ptr);
}
if (data_mask & MAP_CLOTHWEIGHT)
{
- S32 loc = TYPE_CLOTHWEIGHT;
+ AttributeType loc = TYPE_CLOTHWEIGHT;
void* ptr = (void*)(base + mOffsets[TYPE_CLOTHWEIGHT]);
- glVertexAttribPointerARB(loc, 4, GL_FLOAT, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_CLOTHWEIGHT], ptr);
+ glVertexAttribPointer(loc, 4, GL_FLOAT, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_CLOTHWEIGHT], ptr);
}
if (data_mask & MAP_TEXTURE_INDEX)
{
-#if !LL_DARWIN
- S32 loc = TYPE_TEXTURE_INDEX;
+ AttributeType loc = TYPE_TEXTURE_INDEX;
void* ptr = (void*)(base + mOffsets[TYPE_VERTEX] + 12);
glVertexAttribIPointer(loc, 1, GL_UNSIGNED_INT, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr);
-#endif
}
if (data_mask & MAP_VERTEX)
{
- S32 loc = TYPE_VERTEX;
+ AttributeType loc = TYPE_VERTEX;
void* ptr = (void*)(base + mOffsets[TYPE_VERTEX]);
- glVertexAttribPointerARB(loc, 3, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr);
+ glVertexAttribPointer(loc, 3, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr);
}
}
-LLVertexBuffer::MappedRegion::MappedRegion(S32 type, S32 index, S32 count)
-: mType(type), mIndex(index), mCount(count)
-{
- mEnd = mIndex+mCount;
-}
+void LLVertexBuffer::setPositionData(const LLVector4a* data)
+{
+ llassert(sGLRenderBuffer == mGLBuffer);
+ flush_vbo(GL_ARRAY_BUFFER, 0, sizeof(LLVector4a) * getNumVerts()-1, (U8*) data);
+}
+
+void LLVertexBuffer::setTexCoordData(const LLVector2* data)
+{
+ llassert(sGLRenderBuffer == mGLBuffer);
+ flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_TEXCOORD0], mOffsets[TYPE_TEXCOORD0] + sTypeSize[TYPE_TEXCOORD0] * getNumVerts() - 1, (U8*)data);
+}
+
+void LLVertexBuffer::setColorData(const LLColor4U* data)
+{
+ llassert(sGLRenderBuffer == mGLBuffer);
+ flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_COLOR], mOffsets[TYPE_COLOR] + sTypeSize[TYPE_COLOR] * getNumVerts() - 1, (U8*) data);
+}
diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h
index 3b3fe44984..571856f013 100644
--- a/indra/llrender/llvertexbuffer.h
+++ b/indra/llrender/llvertexbuffer.h
@@ -51,69 +51,18 @@
//============================================================================
-// gl name pools for dynamic and streaming buffers
-class LLVBOPool
-{
-public:
- static U32 sBytesPooled;
- static U32 sIndexBytesPooled;
-
- LLVBOPool(U32 vboUsage, U32 vboType);
-
- const U32 mUsage;
- const U32 mType;
-
- //size MUST be a power of 2
- U8* allocate(U32& name, U32 size, bool for_seed = false);
-
- //size MUST be the size provided to allocate that returned the given name
- void release(U32 name, U8* buffer, U32 size);
-
- //batch allocate buffers to be provided to the application on demand
- void seedPool();
-
- //destroy all records in mFreeList
- void cleanup();
-
- U32 genBuffer();
- void deleteBuffer(U32 name);
-
- class Record
- {
- public:
- U32 mGLName;
- U8* mClientData;
- };
-
- typedef std::list<Record> record_list_t;
- std::vector<record_list_t> mFreeList;
- std::vector<U32> mMissCount;
-
- //used to avoid calling glGenBuffers for every VBO creation
- static U32 sNamePool[1024];
- static U32 sNameIdx;
-};
-
-
-//============================================================================
// base class
class LLPrivateMemoryPool;
-class LLVertexBuffer : public LLRefCount
+class LLVertexBuffer final : public LLRefCount
{
public:
- class MappedRegion
+ struct MappedRegion
{
- public:
- S32 mType;
- S32 mIndex;
- S32 mCount;
- S32 mEnd;
-
- MappedRegion(S32 type, S32 index, S32 count);
+ U32 mStart;
+ U32 mEnd;
};
LLVertexBuffer(const LLVertexBuffer& rhs)
- : mUsage(rhs.mUsage)
{
*this = rhs;
}
@@ -124,50 +73,31 @@ public:
return *this;
}
- static LLVBOPool sStreamVBOPool;
- static LLVBOPool sDynamicVBOPool;
- static LLVBOPool sDynamicCopyVBOPool;
- static LLVBOPool sStreamIBOPool;
- static LLVBOPool sDynamicIBOPool;
-
- static std::list<U32> sAvailableVAOName;
- static U32 sCurVAOName;
-
- static bool sUseStreamDraw;
- static bool sUseVAO;
- static bool sPreferStreamDraw;
-
- static void seedPools();
-
- static U32 getVAOName();
- static void releaseVAOName(U32 name);
-
- static void initClass(bool use_vbo, bool no_vbo_mapping);
+ static void initClass(LLWindow* window);
static void cleanupClass();
static void setupClientArrays(U32 data_mask);
static void drawArrays(U32 mode, const std::vector<LLVector3>& pos);
- static void drawElements(U32 mode, const LLVector4a* pos, const LLVector2* tc, S32 num_indices, const U16* indicesp);
+ static void drawElements(U32 mode, const LLVector4a* pos, const LLVector2* tc, U32 num_indices, const U16* indicesp);
static void unbind(); //unbind any bound vertex buffer
//get the size of a vertex with the given typemask
- static S32 calcVertexSize(const U32& typemask);
+ static U32 calcVertexSize(const U32& typemask);
//get the size of a buffer with the given typemask and vertex count
//fill offsets with the offset of each vertex component array into the buffer
// indexed by the following enum
- static S32 calcOffsets(const U32& typemask, S32* offsets, S32 num_vertices);
+ static U32 calcOffsets(const U32& typemask, U32* offsets, U32 num_vertices);
//WARNING -- when updating these enums you MUST
// 1 - update LLVertexBuffer::sTypeSize
- // 2 - add a strider accessor
- // 3 - modify LLVertexBuffer::setupVertexBuffer
- // 4 - modify LLVertexBuffer::setupClientArray
- // 5 - modify LLViewerShaderMgr::mReservedAttribs
- // 6 - update LLVertexBuffer::setupVertexArray
-
+ // 2 - update LLVertexBuffer::vb_type_name
+ // 3 - add a strider accessor
+ // 4 - modify LLVertexBuffer::setupVertexBuffer
+ // 6 - modify LLViewerShaderMgr::mReservedAttribs
+
// clang-format off
- enum { // Shader attribute name, set in LLShaderMgr::initAttribsAndUniforms()
+ enum AttributeType { // Shader attribute name, set in LLShaderMgr::initAttribsAndUniforms()
TYPE_VERTEX = 0, // "position"
TYPE_NORMAL, // "normal"
TYPE_TEXCOORD0, // "texcoord0"
@@ -195,7 +125,6 @@ public:
MAP_TEXCOORD3 = (1<<TYPE_TEXCOORD3),
MAP_COLOR = (1<<TYPE_COLOR),
MAP_EMISSIVE = (1<<TYPE_EMISSIVE),
- // These use VertexAttribPointer and should possibly be made generic
MAP_TANGENT = (1<<TYPE_TANGENT),
MAP_WEIGHT = (1<<TYPE_WEIGHT),
MAP_WEIGHT4 = (1<<TYPE_WEIGHT4),
@@ -206,48 +135,37 @@ public:
protected:
friend class LLRender;
- virtual ~LLVertexBuffer(); // use unref()
+ ~LLVertexBuffer(); // use unref()
- virtual void setupVertexBuffer(U32 data_mask);
- void setupVertexBufferFast(U32 data_mask);
+ void setupVertexBuffer();
- void setupVertexArray();
-
void genBuffer(U32 size);
void genIndices(U32 size);
- bool bindGLBuffer(bool force_bind = false);
- bool bindGLBufferFast();
- bool bindGLIndices(bool force_bind = false);
- bool bindGLIndicesFast();
- bool bindGLArray();
- void releaseBuffer();
- void releaseIndices();
bool createGLBuffer(U32 size);
bool createGLIndices(U32 size);
void destroyGLBuffer();
void destroyGLIndices();
- bool updateNumVerts(S32 nverts);
- bool updateNumIndices(S32 nindices);
- void unmapBuffer();
-
+ bool updateNumVerts(U32 nverts);
+ bool updateNumIndices(U32 nindices);
+
public:
- LLVertexBuffer(U32 typemask, S32 usage);
+ LLVertexBuffer(U32 typemask);
- // map for data access
- U8* mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range);
- U8* mapIndexBuffer(S32 index, S32 count, bool map_range);
+ // allocate buffer
+ bool allocateBuffer(U32 nverts, U32 nindices);
- void bindForFeedback(U32 channel, U32 type, U32 index, U32 count);
+ // map for data access (see also getFooStrider below)
+ U8* mapVertexBuffer(AttributeType type, U32 index, S32 count = -1);
+ U8* mapIndexBuffer(U32 index, S32 count = -1);
+ void unmapBuffer();
// set for rendering
- virtual void setBuffer(U32 data_mask); // calls setupVertexBuffer() if data_mask is not 0
- void setBufferFast(U32 data_mask); // calls setupVertexBufferFast(), assumes data_mask is not 0 among other assumptions
-
- void flush(); //flush pending data to GL memory
- // allocate buffer
- bool allocateBuffer(S32 nverts, S32 nindices, bool create);
- virtual bool resizeBuffer(S32 newnverts, S32 newnindices);
-
+ // assumes (and will assert on) the following:
+ // - this buffer has no pending unampBuffer call
+ // - a shader is currently bound
+ // - This buffer has sufficient attributes within it to satisfy the needs of the currently bound shader
+ void setBuffer();
+
// Only call each getVertexPointer, etc, once before calling unmapBuffer()
// call unmapBuffer() after calls to getXXXStrider() before any cals to setBuffer()
// example:
@@ -255,119 +173,102 @@ public:
// vb->getNormalStrider(norms);
// setVertsNorms(verts, norms);
// vb->unmapBuffer();
- bool getVertexStrider(LLStrider<LLVector3>& strider, S32 index=0, S32 count = -1, bool map_range = false);
- bool getVertexStrider(LLStrider<LLVector4a>& strider, S32 index=0, S32 count = -1, bool map_range = false);
- bool getIndexStrider(LLStrider<U16>& strider, S32 index=0, S32 count = -1, bool map_range = false);
- bool getTexCoord0Strider(LLStrider<LLVector2>& strider, S32 index=0, S32 count = -1, bool map_range = false);
- bool getTexCoord1Strider(LLStrider<LLVector2>& strider, S32 index=0, S32 count = -1, bool map_range = false);
- bool getTexCoord2Strider(LLStrider<LLVector2>& strider, S32 index=0, S32 count = -1, bool map_range = false);
- bool getNormalStrider(LLStrider<LLVector3>& strider, S32 index=0, S32 count = -1, bool map_range = false);
- bool getTangentStrider(LLStrider<LLVector3>& strider, S32 index=0, S32 count = -1, bool map_range = false);
- bool getTangentStrider(LLStrider<LLVector4a>& strider, S32 index=0, S32 count = -1, bool map_range = false);
- bool getColorStrider(LLStrider<LLColor4U>& strider, S32 index=0, S32 count = -1, bool map_range = false);
- bool getEmissiveStrider(LLStrider<LLColor4U>& strider, S32 index=0, S32 count = -1, bool map_range = false);
- bool getWeightStrider(LLStrider<F32>& strider, S32 index=0, S32 count = -1, bool map_range = false);
- bool getWeight4Strider(LLStrider<LLVector4>& strider, S32 index=0, S32 count = -1, bool map_range = false);
- bool getClothWeightStrider(LLStrider<LLVector4>& strider, S32 index=0, S32 count = -1, bool map_range = false);
+ bool getVertexStrider(LLStrider<LLVector3>& strider, U32 index=0, S32 count = -1);
+ bool getVertexStrider(LLStrider<LLVector4a>& strider, U32 index=0, S32 count = -1);
+ bool getIndexStrider(LLStrider<U16>& strider, U32 index=0, S32 count = -1);
+ bool getTexCoord0Strider(LLStrider<LLVector2>& strider, U32 index=0, S32 count = -1);
+ bool getTexCoord1Strider(LLStrider<LLVector2>& strider, U32 index=0, S32 count = -1);
+ bool getTexCoord2Strider(LLStrider<LLVector2>& strider, U32 index=0, S32 count = -1);
+ bool getNormalStrider(LLStrider<LLVector3>& strider, U32 index=0, S32 count = -1);
+ bool getTangentStrider(LLStrider<LLVector3>& strider, U32 index=0, S32 count = -1);
+ bool getTangentStrider(LLStrider<LLVector4a>& strider, U32 index=0, S32 count = -1);
+ bool getColorStrider(LLStrider<LLColor4U>& strider, U32 index=0, S32 count = -1);
+ bool getEmissiveStrider(LLStrider<LLColor4U>& strider, U32 index=0, S32 count = -1);
+ bool getWeightStrider(LLStrider<F32>& strider, U32 index=0, S32 count = -1);
+ bool getWeight4Strider(LLStrider<LLVector4>& strider, U32 index=0, S32 count = -1);
+ bool getClothWeightStrider(LLStrider<LLVector4>& strider, U32 index=0, S32 count = -1);
+ bool getBasecolorTexcoordStrider(LLStrider<LLVector2>& strider, U32 index=0, S32 count = -1);
+ bool getNormalTexcoordStrider(LLStrider<LLVector2>& strider, U32 index=0, S32 count = -1);
+ bool getMetallicRoughnessTexcoordStrider(LLStrider<LLVector2>& strider, U32 index=0, S32 count = -1);
+ bool getEmissiveTexcoordStrider(LLStrider<LLVector2>& strider, U32 index=0, S32 count = -1);
+ void setPositionData(const LLVector4a* data);
+ void setTexCoordData(const LLVector2* data);
+ void setColorData(const LLColor4U* data);
+
- bool useVBOs() const;
- bool isEmpty() const { return mEmpty; }
- bool isLocked() const { return mVertexLocked || mIndexLocked; }
- S32 getNumVerts() const { return mNumVerts; }
- S32 getNumIndices() const { return mNumIndices; }
+ U32 getNumVerts() const { return mNumVerts; }
+ U32 getNumIndices() const { return mNumIndices; }
- U8* getIndicesPointer() const { return useVBOs() ? (U8*) mAlignedIndexOffset : mMappedIndexData; }
- U8* getVerticesPointer() const { return useVBOs() ? (U8*) mAlignedOffset : mMappedData; }
U32 getTypeMask() const { return mTypeMask; }
- bool hasDataType(S32 type) const { return ((1 << type) & getTypeMask()); }
- S32 getSize() const;
- S32 getIndicesSize() const { return mIndicesSize; }
+ bool hasDataType(AttributeType type) const { return ((1 << type) & getTypeMask()); }
+ U32 getSize() const { return mSize; }
+ U32 getIndicesSize() const { return mIndicesSize; }
U8* getMappedData() const { return mMappedData; }
U8* getMappedIndices() const { return mMappedIndexData; }
- S32 getOffset(S32 type) const { return mOffsets[type]; }
- S32 getUsage() const { return mUsage; }
- bool isWriteable() const { return (mMappable || mUsage == GL_STREAM_DRAW_ARB) ? true : false; }
-
+ U32 getOffset(AttributeType type) const { return mOffsets[type]; }
+
+ // these functions assume (and assert on) the current VBO being bound
+ // Detailed error checking can be enabled by setting gDebugGL to true
void draw(U32 mode, U32 count, U32 indices_offset) const;
void drawArrays(U32 mode, U32 offset, U32 count) const;
- void drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const;
-
- //implementation for inner loops that does no safety checking
- void drawRangeFast(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const;
+ void drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const;
//for debugging, validate data in given range is valid
- void validateRange(U32 start, U32 end, U32 count, U32 offset) const;
+ bool validateRange(U32 start, U32 end, U32 count, U32 offset) const;
+ #ifdef LL_PROFILER_ENABLE_RENDER_DOC
+ void setLabel(const char* label);
+ #endif
protected:
- S32 mNumVerts; // Number of vertices allocated
- S32 mNumIndices; // Number of indices allocated
-
- ptrdiff_t mAlignedOffset;
- ptrdiff_t mAlignedIndexOffset;
- S32 mSize;
- S32 mIndicesSize;
- U32 mTypeMask;
-
- const S32 mUsage; // GL usage
-
- U32 mGLBuffer; // GL VBO handle
- U32 mGLIndices; // GL IBO handle
- U32 mGLArray; // GL VAO handle
-
- U8* mMappedData; // pointer to currently mapped data (NULL if unmapped)
- U8* mMappedIndexData; // pointer to currently mapped indices (NULL if unmapped)
-
- U32 mMappedDataUsingVBOs : 1;
- U32 mMappedIndexDataUsingVBOs : 1;
- U32 mVertexLocked : 1; // if true, vertex buffer is being or has been written to in client memory
- U32 mIndexLocked : 1; // if true, index buffer is being or has been written to in client memory
- U32 mFinal : 1; // if true, buffer can not be mapped again
- U32 mEmpty : 1; // if true, client buffer is empty (or NULL). Old values have been discarded.
-
- mutable bool mMappable; // if true, use memory mapping to upload data (otherwise doublebuffer and use glBufferSubData)
+ U32 mGLBuffer = 0; // GL VBO handle
+ U32 mGLIndices = 0; // GL IBO handle
+ U32 mNumVerts = 0; // Number of vertices allocated
+ U32 mNumIndices = 0; // Number of indices allocated
+ U32 mOffsets[TYPE_MAX]; // byte offsets into mMappedData of each attribute
- S32 mOffsets[TYPE_MAX];
+ U8* mMappedData = nullptr; // pointer to currently mapped data (NULL if unmapped)
+ U8* mMappedIndexData = nullptr; // pointer to currently mapped indices (NULL if unmapped)
- std::vector<MappedRegion> mMappedVertexRegions;
- std::vector<MappedRegion> mMappedIndexRegions;
-
- mutable LLGLFence* mFence;
-
- void placeFence() const;
- void waitFence() const;
+ U32 mTypeMask = 0; // bitmask of present vertex attributes
+
+ U32 mSize = 0; // size in bytes of mMappedData
+ U32 mIndicesSize = 0; // size in bytes of mMappedIndexData
- static S32 determineUsage(S32 usage);
+ std::vector<MappedRegion> mMappedVertexRegions; // list of mMappedData byte ranges that must be sent to GL
+ std::vector<MappedRegion> mMappedIndexRegions; // list of mMappedIndexData byte ranges that must be sent to GL
private:
- static LLPrivateMemoryPool* sPrivatePoolp;
+ // DEPRECATED
+ // These function signatures are deprecated, but for some reason
+ // there are classes in an external package that depend on LLVertexBuffer
+
+ // TODO: move these classes into viewer repository
+ friend class LLNavShapeVBOManager;
+ friend class LLNavMeshVBOManager;
+
+ LLVertexBuffer(U32 typemask, U32 usage)
+ : LLVertexBuffer(typemask)
+ {}
+
+ bool allocateBuffer(S32 nverts, S32 nindices, BOOL create) { return allocateBuffer(nverts, nindices); }
public:
- static S32 sCount;
- static S32 sGLCount;
- static S32 sMappedCount;
- static bool sMapped;
- typedef std::list<LLVertexBuffer*> buffer_list_t;
-
- static bool sDisableVBOMapping; //disable glMapBufferARB
- static bool sEnableVBOs;
- static const S32 sTypeSize[TYPE_MAX];
+ static const U32 sTypeSize[TYPE_MAX];
static const U32 sGLMode[LLRender::NUM_MODES];
static U32 sGLRenderBuffer;
- static U32 sGLRenderArray;
static U32 sGLRenderIndices;
- static bool sVBOActive;
- static bool sIBOActive;
static U32 sLastMask;
- static U32 sAllocatedBytes;
- static U32 sAllocatedIndexBytes;
static U32 sVertexCount;
- static U32 sIndexCount;
- static U32 sBindCount;
- static U32 sSetCount;
};
+#ifdef LL_PROFILER_ENABLE_RENDER_DOC
+#define LL_LABEL_VERTEX_BUFFER(buf, name) buf->setLabel(name)
+#else
+#define LL_LABEL_VERTEX_BUFFER(buf, name)
+#endif
+
#endif // LL_LLVERTEXBUFFER_H
diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h
index 668cd208a9..3d15708295 100644
--- a/indra/llui/llfloater.h
+++ b/indra/llui/llfloater.h
@@ -225,6 +225,7 @@ public:
/*virtual*/ void setIsChrome(BOOL is_chrome);
/*virtual*/ void setRect(const LLRect &rect);
void setIsSingleInstance(BOOL is_single_instance);
+ BOOL getIsSingleInstance() { return mSingleInstance; }
void initFloater(const Params& p);
diff --git a/indra/llui/llui.h b/indra/llui/llui.h
index 30dbd7248f..86b23c8c93 100644
--- a/indra/llui/llui.h
+++ b/indra/llui/llui.h
@@ -76,7 +76,8 @@ enum EDragAndDropType
DAD_WIDGET = 16,
DAD_PERSON = 17,
DAD_SETTINGS = 18,
- DAD_COUNT = 19, // number of types in this enum
+ DAD_MATERIAL = 19,
+ DAD_COUNT = 20, // number of types in this enum
};
// Reasons for drags to be denied.
diff --git a/indra/llwindow/CMakeLists.txt b/indra/llwindow/CMakeLists.txt
index 55befaef51..5fbb88400b 100644
--- a/indra/llwindow/CMakeLists.txt
+++ b/indra/llwindow/CMakeLists.txt
@@ -145,6 +145,8 @@ if (WINDOWS)
list(APPEND llwindow_LINK_LIBRARIES
comdlg32 # Common Dialogs for ChooseColor
ole32
+ dxgi
+ d3d9
)
endif (WINDOWS)
diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm
index 7936245744..9d497691d8 100644
--- a/indra/llwindow/llopenglview-objc.mm
+++ b/indra/llwindow/llopenglview-objc.mm
@@ -141,7 +141,12 @@ attributedStringInfo getSegments(NSAttributedString *str)
CGLError the_err = CGLQueryRendererInfo (CGDisplayIDToOpenGLDisplayMask(kCGDirectMainDisplay), &info, &num_renderers);
if(0 == the_err)
{
- CGLDescribeRenderer (info, 0, kCGLRPTextureMemoryMegabytes, &vram_megabytes);
+ // The name, uses, and other platform definitions of gGLManager.mVRAM suggest that this is supposed to be total vram in MB,
+ // rather than, say, just the texture memory. The two exceptions are:
+ // 1. LLAppViewer::getViewerInfo() puts the value in a field labeled "TEXTURE_MEMORY"
+ // 2. For years, this present function used kCGLRPTextureMemoryMegabytes
+ // Now we use kCGLRPVideoMemoryMegabytes to bring it in line with everything else (except thatone label).
+ CGLDescribeRenderer (info, 0, kCGLRPVideoMemoryMegabytes, &vram_megabytes);
CGLDestroyRendererInfo (info);
}
else
@@ -256,6 +261,7 @@ attributedStringInfo getSegments(NSAttributedString *str)
NSOpenGLPFADepthSize, 24,
NSOpenGLPFAAlphaSize, 8,
NSOpenGLPFAColorSize, 24,
+ NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion4_1Core,
0
};
diff --git a/indra/llwindow/llwindow.cpp b/indra/llwindow/llwindow.cpp
index f4678a70c5..66be3efffc 100644
--- a/indra/llwindow/llwindow.cpp
+++ b/indra/llwindow/llwindow.cpp
@@ -406,7 +406,10 @@ LLWindow* LLWindowManager::createWindow(
BOOL enable_vsync,
BOOL use_gl,
BOOL ignore_pixel_depth,
- U32 fsaa_samples)
+ U32 fsaa_samples,
+ U32 max_cores,
+ U32 max_vram,
+ F32 max_gl_version)
{
LLWindow* new_window;
@@ -423,7 +426,7 @@ LLWindow* LLWindowManager::createWindow(
#elif LL_WINDOWS
new_window = new LLWindowWin32(callbacks,
title, name, x, y, width, height, flags,
- fullscreen, clearBg, enable_vsync, use_gl, ignore_pixel_depth, fsaa_samples);
+ fullscreen, clearBg, enable_vsync, use_gl, ignore_pixel_depth, fsaa_samples, max_cores, max_vram, max_gl_version);
#elif LL_DARWIN
new_window = new LLWindowMacOSX(callbacks,
title, name, x, y, width, height, flags,
diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h
index 0edf39f6ef..862897a48c 100644
--- a/indra/llwindow/llwindow.h
+++ b/indra/llwindow/llwindow.h
@@ -162,7 +162,10 @@ public:
virtual F32 getNativeAspectRatio() = 0;
virtual F32 getPixelAspectRatio() = 0;
virtual void setNativeAspectRatio(F32 aspect) = 0;
-
+
+ // query VRAM usage
+ virtual U32 getAvailableVRAMMegabytes() = 0;
+
virtual void beforeDialog() {}; // prepare to put up an OS dialog (if special measures are required, such as in fullscreen mode)
virtual void afterDialog() {}; // undo whatever was done in beforeDialog()
@@ -299,7 +302,10 @@ public:
BOOL enable_vsync = FALSE,
BOOL use_gl = TRUE,
BOOL ignore_pixel_depth = FALSE,
- U32 fsaa_samples = 0);
+ U32 fsaa_samples = 0,
+ U32 max_cores = 0,
+ U32 max_vram = 0,
+ F32 max_gl_version = 4.6f);
static BOOL destroyWindow(LLWindow* window);
static BOOL isWindowValid(LLWindow *window);
};
diff --git a/indra/llwindow/llwindowheadless.h b/indra/llwindow/llwindowheadless.h
index 410da79623..2f2c0de5bd 100644
--- a/indra/llwindow/llwindowheadless.h
+++ b/indra/llwindow/llwindowheadless.h
@@ -32,72 +32,79 @@
class LLWindowHeadless : public LLWindow
{
public:
- /*virtual*/ void show() {};
- /*virtual*/ void hide() {};
- /*virtual*/ void close() {};
- /*virtual*/ BOOL getVisible() {return FALSE;};
- /*virtual*/ BOOL getMinimized() {return FALSE;};
- /*virtual*/ BOOL getMaximized() {return FALSE;};
- /*virtual*/ BOOL maximize() {return FALSE;};
- /*virtual*/ void minimize() {};
- /*virtual*/ void restore() {};
- /*virtual*/ BOOL getFullscreen() {return FALSE;};
- /*virtual*/ BOOL getPosition(LLCoordScreen *position) {return FALSE;};
- /*virtual*/ BOOL getSize(LLCoordScreen *size) {return FALSE;};
- /*virtual*/ BOOL getSize(LLCoordWindow *size) {return FALSE;};
- /*virtual*/ BOOL setPosition(LLCoordScreen position) {return FALSE;};
- /*virtual*/ BOOL setSizeImpl(LLCoordScreen size) {return FALSE;};
- /*virtual*/ BOOL setSizeImpl(LLCoordWindow size) {return FALSE;};
- /*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL enable_vsync, const LLCoordScreen * const posp = NULL) {return FALSE;};
- void* createSharedContext() { return nullptr; }
- void makeContextCurrent(void*) {}
- void destroySharedContext(void*) {}
- /*virtual*/ void toggleVSync(bool enable_vsync) { }
- /*virtual*/ BOOL setCursorPosition(LLCoordWindow position) {return FALSE;};
- /*virtual*/ BOOL getCursorPosition(LLCoordWindow *position) {return FALSE;};
+ /*virtual*/ void show() override {}
+ /*virtual*/ void hide() override {}
+ /*virtual*/ void close() override {}
+ /*virtual*/ BOOL getVisible() override {return FALSE;}
+ /*virtual*/ BOOL getMinimized() override {return FALSE;}
+ /*virtual*/ BOOL getMaximized() override {return FALSE;}
+ /*virtual*/ BOOL maximize() override {return FALSE;}
+ /*virtual*/ void minimize() override {}
+ /*virtual*/ void restore() override {}
+ // TODO: LLWindow::getFullscreen() is (intentionally?) NOT virtual.
+ // Apparently the coder of LLWindowHeadless didn't realize that. Is it a
+ // mistake to shadow the base-class method with an LLWindowHeadless
+ // override when called on the subclass, yet call the base-class method
+ // when indirecting through a polymorphic pointer or reference?
+ BOOL getFullscreen() {return FALSE;}
+ /*virtual*/ BOOL getPosition(LLCoordScreen *position) override {return FALSE;}
+ /*virtual*/ BOOL getSize(LLCoordScreen *size) override {return FALSE;}
+ /*virtual*/ BOOL getSize(LLCoordWindow *size) override {return FALSE;}
+ /*virtual*/ BOOL setPosition(LLCoordScreen position) override {return FALSE;}
+ /*virtual*/ BOOL setSizeImpl(LLCoordScreen size) override {return FALSE;}
+ /*virtual*/ BOOL setSizeImpl(LLCoordWindow size) override {return FALSE;}
+ /*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL enable_vsync, const LLCoordScreen * const posp = NULL) override {return FALSE;}
+ void* createSharedContext() override { return nullptr; }
+ void makeContextCurrent(void*) override {}
+ void destroySharedContext(void*) override {}
+ /*virtual*/ void toggleVSync(bool enable_vsync) override { }
+ /*virtual*/ BOOL setCursorPosition(LLCoordWindow position) override {return FALSE;}
+ /*virtual*/ BOOL getCursorPosition(LLCoordWindow *position) override {return FALSE;}
#if LL_WINDOWS
- /*virtual*/ BOOL getCursorDelta(LLCoordCommon* delta) { return FALSE; }
+ /*virtual*/ BOOL getCursorDelta(LLCoordCommon* delta) override { return FALSE; }
#endif
- /*virtual*/ void showCursor() {};
- /*virtual*/ void hideCursor() {};
- /*virtual*/ void showCursorFromMouseMove() {};
- /*virtual*/ void hideCursorUntilMouseMove() {};
- /*virtual*/ BOOL isCursorHidden() {return FALSE;};
- /*virtual*/ void updateCursor() {};
- //virtual ECursorType getCursor() { return mCurrentCursor; };
- /*virtual*/ void captureMouse() {};
- /*virtual*/ void releaseMouse() {};
- /*virtual*/ void setMouseClipping( BOOL b ) {};
- /*virtual*/ BOOL isClipboardTextAvailable() {return FALSE; };
- /*virtual*/ BOOL pasteTextFromClipboard(LLWString &dst) {return FALSE; };
- /*virtual*/ BOOL copyTextToClipboard(const LLWString &src) {return FALSE; };
- /*virtual*/ void flashIcon(F32 seconds) {};
- /*virtual*/ F32 getGamma() {return 1.0f; };
- /*virtual*/ BOOL setGamma(const F32 gamma) {return FALSE; }; // Set the gamma
- /*virtual*/ void setFSAASamples(const U32 fsaa_samples) { }
- /*virtual*/ U32 getFSAASamples() { return 0; }
- /*virtual*/ BOOL restoreGamma() {return FALSE; }; // Restore original gamma table (before updating gamma)
- //virtual ESwapMethod getSwapMethod() { return mSwapMethod; }
- /*virtual*/ void gatherInput() {};
- /*virtual*/ void delayInputProcessing() {};
- /*virtual*/ void swapBuffers();
+ /*virtual*/ void showCursor() override {}
+ /*virtual*/ void hideCursor() override {}
+ /*virtual*/ void showCursorFromMouseMove() override {}
+ /*virtual*/ void hideCursorUntilMouseMove() override {}
+ /*virtual*/ BOOL isCursorHidden() override {return FALSE;}
+ /*virtual*/ void updateCursor() override {}
+ //virtual ECursorType getCursor() override { return mCurrentCursor; }
+ /*virtual*/ void captureMouse() override {}
+ /*virtual*/ void releaseMouse() override {}
+ /*virtual*/ void setMouseClipping( BOOL b ) override {}
+ /*virtual*/ BOOL isClipboardTextAvailable() override {return FALSE; }
+ /*virtual*/ BOOL pasteTextFromClipboard(LLWString &dst) override {return FALSE; }
+ /*virtual*/ BOOL copyTextToClipboard(const LLWString &src) override {return FALSE; }
+ /*virtual*/ void flashIcon(F32 seconds) override {}
+ /*virtual*/ F32 getGamma() override {return 1.0f; }
+ /*virtual*/ BOOL setGamma(const F32 gamma) override {return FALSE; } // Set the gamma
+ /*virtual*/ void setFSAASamples(const U32 fsaa_samples) override { }
+ /*virtual*/ U32 getFSAASamples() override { return 0; }
+ /*virtual*/ BOOL restoreGamma() override {return FALSE; } // Restore original gamma table (before updating gamma)
+ //virtual ESwapMethod getSwapMethod() override { return mSwapMethod; }
+ /*virtual*/ void gatherInput() override {}
+ /*virtual*/ void delayInputProcessing() override {}
+ /*virtual*/ void swapBuffers() override;
// handy coordinate space conversion routines
- /*virtual*/ BOOL convertCoords(LLCoordScreen from, LLCoordWindow *to) { return FALSE; };
- /*virtual*/ BOOL convertCoords(LLCoordWindow from, LLCoordScreen *to) { return FALSE; };
- /*virtual*/ BOOL convertCoords(LLCoordWindow from, LLCoordGL *to) { return FALSE; };
- /*virtual*/ BOOL convertCoords(LLCoordGL from, LLCoordWindow *to) { return FALSE; };
- /*virtual*/ BOOL convertCoords(LLCoordScreen from, LLCoordGL *to) { return FALSE; };
- /*virtual*/ BOOL convertCoords(LLCoordGL from, LLCoordScreen *to) { return FALSE; };
+ /*virtual*/ BOOL convertCoords(LLCoordScreen from, LLCoordWindow *to) override { return FALSE; }
+ /*virtual*/ BOOL convertCoords(LLCoordWindow from, LLCoordScreen *to) override { return FALSE; }
+ /*virtual*/ BOOL convertCoords(LLCoordWindow from, LLCoordGL *to) override { return FALSE; }
+ /*virtual*/ BOOL convertCoords(LLCoordGL from, LLCoordWindow *to) override { return FALSE; }
+ /*virtual*/ BOOL convertCoords(LLCoordScreen from, LLCoordGL *to) override { return FALSE; }
+ /*virtual*/ BOOL convertCoords(LLCoordGL from, LLCoordScreen *to) override { return FALSE; }
- /*virtual*/ LLWindowResolution* getSupportedResolutions(S32 &num_resolutions) { return NULL; };
- /*virtual*/ F32 getNativeAspectRatio() { return 1.0f; };
- /*virtual*/ F32 getPixelAspectRatio() { return 1.0f; };
- /*virtual*/ void setNativeAspectRatio(F32 ratio) {}
+ /*virtual*/ LLWindowResolution* getSupportedResolutions(S32 &num_resolutions) override { return NULL; }
+ /*virtual*/ F32 getNativeAspectRatio() override { return 1.0f; }
+ /*virtual*/ F32 getPixelAspectRatio() override { return 1.0f; }
+ /*virtual*/ void setNativeAspectRatio(F32 ratio) override {}
- /*virtual*/ void *getPlatformWindow() { return 0; };
- /*virtual*/ void bringToFront() {};
+ U32 getAvailableVRAMMegabytes() override { return 4096; }
+
+ /*virtual*/ void *getPlatformWindow() override { return 0; }
+ /*virtual*/ void bringToFront() override {}
LLWindowHeadless(LLWindowCallbacks* callbacks,
const std::string& title, const std::string& name,
@@ -113,12 +120,12 @@ private:
class LLSplashScreenHeadless : public LLSplashScreen
{
public:
- LLSplashScreenHeadless() {};
- virtual ~LLSplashScreenHeadless() {};
+ LLSplashScreenHeadless() {}
+ virtual ~LLSplashScreenHeadless() {}
- /*virtual*/ void showImpl() {};
- /*virtual*/ void updateImpl(const std::string& mesg) {};
- /*virtual*/ void hideImpl() {};
+ /*virtual*/ void showImpl() override {}
+ /*virtual*/ void updateImpl(const std::string& mesg) override {}
+ /*virtual*/ void hideImpl() override {}
};
diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp
index f924b17090..3d9963897c 100644
--- a/indra/llwindow/llwindowmacosx.cpp
+++ b/indra/llwindow/llwindowmacosx.cpp
@@ -1217,6 +1217,16 @@ F32 LLWindowMacOSX::getPixelAspectRatio()
return 1.f;
}
+U32 LLWindowMacOSX::getAvailableVRAMMegabytes() {
+ // MTL (and MoltenVK) has some additional gpu data, such as recommendedMaxWorkingSetSize and currentAllocatedSize.
+ // But these are not available for OpenGL and/or our current mimimum OS version.
+ // So we will estimate.
+ static const U32 mb = 1024*1024;
+ // We're asked for total available gpu memory, but we only have allocation info on texture usage. So estimate by doubling that.
+ static const U32 total_factor = 2; // estimated total/textures
+ return gGLManager.mVRAM - (LLImageGL::getTextureBytesAllocated() * total_factor/mb);
+}
+
//static SInt32 oldWindowLevel;
// MBW -- XXX -- There's got to be a better way than this. Find it, please...
diff --git a/indra/llwindow/llwindowmacosx.h b/indra/llwindow/llwindowmacosx.h
index 851c860017..7614167213 100644
--- a/indra/llwindow/llwindowmacosx.h
+++ b/indra/llwindow/llwindowmacosx.h
@@ -100,6 +100,9 @@ public:
F32 getPixelAspectRatio() override;
void setNativeAspectRatio(F32 ratio) override { mOverrideAspectRatio = ratio; }
+ // query VRAM usage
+ /*virtual*/ U32 getAvailableVRAMMegabytes() override;
+
void beforeDialog() override;
void afterDialog() override;
diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index 41f3042ace..a195964bb1 100644
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -47,6 +47,7 @@
#include "llglslshader.h"
#include "llthreadsafequeue.h"
#include "stringize.h"
+#include "llframetimer.h"
// System includes
#include <commdlg.h>
@@ -61,6 +62,10 @@
#include <sstream>
#include <utility> // std::pair
+#include <d3d9.h>
+#include <dxgi1_4.h>
+#include <timeapi.h>
+
// Require DirectInput version 8
#define DIRECTINPUT_VERSION 0x0800
@@ -347,6 +352,20 @@ struct LLWindowWin32::LLWindowWin32Thread : public LL::ThreadPool
void run() override;
+ // initialzie DXGI adapter (for querying available VRAM)
+ void initDX();
+
+ // initialize D3D (if DXGI cannot be used)
+ void initD3D();
+
+ // call periodically to update available VRAM
+ void updateVRAMUsage();
+
+ U32 getAvailableVRAMMegabytes()
+ {
+ return mAvailableVRAM;
+ }
+
/// called by main thread to post work to this window thread
template <typename CALLABLE>
void post(CALLABLE&& func)
@@ -395,6 +414,15 @@ struct LLWindowWin32::LLWindowWin32Thread : public LL::ThreadPool
void gatherInput();
HWND mWindowHandle = NULL;
HDC mhDC = 0;
+
+ // best guess at available video memory in MB
+ std::atomic<U32> mAvailableVRAM;
+
+ U32 mMaxVRAM = 0; // maximum amount of vram to allow in the "budget", or 0 for no maximum (see updateVRAMUsage)
+
+ IDXGIAdapter3* mDXGIAdapter = nullptr;
+ LPDIRECT3D9 mD3D = nullptr;
+ LPDIRECT3DDEVICE9 mD3DDevice = nullptr;
};
@@ -404,13 +432,93 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
BOOL fullscreen, BOOL clearBg,
BOOL enable_vsync, BOOL use_gl,
BOOL ignore_pixel_depth,
- U32 fsaa_samples)
- : LLWindow(callbacks, fullscreen, flags)
+ U32 fsaa_samples,
+ U32 max_cores,
+ U32 max_vram,
+ F32 max_gl_version)
+ :
+ LLWindow(callbacks, fullscreen, flags),
+ mMaxGLVersion(max_gl_version),
+ mMaxCores(max_cores)
{
sMainThreadId = LLThread::currentID();
mWindowThread = new LLWindowWin32Thread();
+ mWindowThread->mMaxVRAM = max_vram;
+
//MAINT-516 -- force a load of opengl32.dll just in case windows went sideways
LoadLibrary(L"opengl32.dll");
+
+
+ if (mMaxCores != 0)
+ {
+ HANDLE hProcess = GetCurrentProcess();
+ mMaxCores = llmin(mMaxCores, (U32) 64);
+ DWORD_PTR mask = 0;
+
+ for (int i = 0; i < mMaxCores; ++i)
+ {
+ mask |= ((DWORD_PTR) 1) << i;
+ }
+
+ SetProcessAffinityMask(hProcess, mask);
+ }
+
+#if 0 // this is probably a bad idea, but keep it in your back pocket if you see what looks like
+ // process deprioritization during profiles
+ // force high thread priority
+ HANDLE hProcess = GetCurrentProcess();
+
+ if (hProcess)
+ {
+ int priority = GetPriorityClass(hProcess);
+ if (priority < REALTIME_PRIORITY_CLASS)
+ {
+ if (SetPriorityClass(hProcess, REALTIME_PRIORITY_CLASS))
+ {
+ LL_INFOS() << "Set process priority to REALTIME_PRIORITY_CLASS" << LL_ENDL;
+ }
+ else
+ {
+ LL_INFOS() << "Failed to set process priority: " << std::hex << GetLastError() << LL_ENDL;
+ }
+ }
+ }
+#endif
+
+#if 0 // this is also probably a bad idea, but keep it in your back pocket for getting main thread off of background thread cores (see also LLThread::threadRun)
+ HANDLE hThread = GetCurrentThread();
+
+ SYSTEM_INFO sysInfo;
+
+ GetSystemInfo(&sysInfo);
+ U32 core_count = sysInfo.dwNumberOfProcessors;
+
+ if (max_cores != 0)
+ {
+ core_count = llmin(core_count, max_cores);
+ }
+
+ if (hThread)
+ {
+ int priority = GetThreadPriority(hThread);
+
+ if (priority < THREAD_PRIORITY_TIME_CRITICAL)
+ {
+ if (SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL))
+ {
+ LL_INFOS() << "Set thread priority to THREAD_PRIORITY_TIME_CRITICAL" << LL_ENDL;
+ }
+ else
+ {
+ LL_INFOS() << "Failed to set thread priority: " << std::hex << GetLastError() << LL_ENDL;
+ }
+
+ // tell main thread to prefer core 0
+ SetThreadIdealProcessor(hThread, 0);
+ }
+ }
+#endif
+
mFSAASamples = fsaa_samples;
mIconResource = gIconResource;
@@ -943,16 +1051,19 @@ BOOL LLWindowWin32::maximize()
BOOL success = FALSE;
if (!mWindowHandle) return success;
- WINDOWPLACEMENT placement;
- placement.length = sizeof(WINDOWPLACEMENT);
-
- success = GetWindowPlacement(mWindowHandle, &placement);
- if (!success) return success;
+ mWindowThread->post([=]
+ {
+ WINDOWPLACEMENT placement;
+ placement.length = sizeof(WINDOWPLACEMENT);
- placement.showCmd = SW_MAXIMIZE;
+ if (GetWindowPlacement(mWindowHandle, &placement))
+ {
+ placement.showCmd = SW_MAXIMIZE;
+ SetWindowPlacement(mWindowHandle, &placement);
+ }
+ });
- success = SetWindowPlacement(mWindowHandle, &placement);
- return success;
+ return TRUE;
}
BOOL LLWindowWin32::getFullscreen()
@@ -1300,14 +1411,6 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen& size, BO
return FALSE;
}
- if (pfd.cAlphaBits < 8)
- {
- OSMessageBox(mCallbacks->translateString("MBAlpha"),
- mCallbacks->translateString("MBError"), OSMB_OK);
- close();
- return FALSE;
- }
-
if (!SetPixelFormat(mhDC, pixel_format, &pfd))
{
OSMessageBox(mCallbacks->translateString("MBPixelFmtSetErr"),
@@ -1347,8 +1450,8 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen& size, BO
attrib_list[cur_attrib++] = WGL_DEPTH_BITS_ARB;
attrib_list[cur_attrib++] = 24;
- attrib_list[cur_attrib++] = WGL_STENCIL_BITS_ARB;
- attrib_list[cur_attrib++] = 8;
+ //attrib_list[cur_attrib++] = WGL_STENCIL_BITS_ARB; //stencil buffer is deprecated (performance penalty)
+ //attrib_list[cur_attrib++] = 8;
attrib_list[cur_attrib++] = WGL_DRAW_TO_WINDOW_ARB;
attrib_list[cur_attrib++] = GL_TRUE;
@@ -1366,7 +1469,7 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen& size, BO
attrib_list[cur_attrib++] = 24;
attrib_list[cur_attrib++] = WGL_ALPHA_BITS_ARB;
- attrib_list[cur_attrib++] = 8;
+ attrib_list[cur_attrib++] = 0;
U32 end_attrib = 0;
if (mFSAASamples > 0)
@@ -1597,13 +1700,6 @@ const S32 max_format = (S32)num_formats - 1;
return FALSE;
}
- if (pfd.cAlphaBits < 8)
- {
- OSMessageBox(mCallbacks->translateString("MBAlpha"), mCallbacks->translateString("MBError"), OSMB_OK);
- close();
- return FALSE;
- }
-
mhRC = 0;
if (wglCreateContextAttribsARB)
{ //attempt to create a specific versioned context
@@ -1621,8 +1717,6 @@ const S32 max_format = (S32)num_formats - 1;
return FALSE;
}
- LL_PROFILER_GPU_CONTEXT
-
if (!gGLManager.initGL())
{
OSMessageBox(mCallbacks->translateString("MBVideoDrvErr"), mCallbacks->translateString("MBError"), OSMB_OK);
@@ -1654,6 +1748,8 @@ const S32 max_format = (S32)num_formats - 1;
swapBuffers();
}
+ LL_PROFILER_GPU_CONTEXT;
+
return TRUE;
}
@@ -1766,10 +1862,15 @@ void LLWindowWin32::recreateWindow(RECT window_rect, DWORD dw_ex_style, DWORD dw
void* LLWindowWin32::createSharedContext()
{
+ mMaxGLVersion = llclamp(mMaxGLVersion, 3.f, 4.6f);
+
+ S32 version_major = llfloor(mMaxGLVersion);
+ S32 version_minor = llround((mMaxGLVersion-version_major)*10);
+
S32 attribs[] =
{
- WGL_CONTEXT_MAJOR_VERSION_ARB, 4,
- WGL_CONTEXT_MINOR_VERSION_ARB, 6,
+ WGL_CONTEXT_MAJOR_VERSION_ARB, version_major,
+ WGL_CONTEXT_MINOR_VERSION_ARB, version_minor,
WGL_CONTEXT_PROFILE_MASK_ARB, LLRender::sGLCoreProfile ? WGL_CONTEXT_CORE_PROFILE_BIT_ARB : WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
WGL_CONTEXT_FLAGS_ARB, gDebugGL ? WGL_CONTEXT_DEBUG_BIT_ARB : 0,
0
@@ -1818,6 +1919,7 @@ void* LLWindowWin32::createSharedContext()
void LLWindowWin32::makeContextCurrent(void* contextPtr)
{
wglMakeCurrent(mhDC, (HGLRC) contextPtr);
+ LL_PROFILER_GPU_CONTEXT;
}
void LLWindowWin32::destroySharedContext(void* contextPtr)
@@ -3563,7 +3665,7 @@ BOOL LLWindowWin32::setDisplayResolution(S32 width, S32 height, S32 bits, S32 re
// Don't change anything if we don't have to
if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode))
{
- if (dev_mode.dmPelsWidth == width &&
+ if (dev_mode.dmPelsWidth == width &&
dev_mode.dmPelsHeight == height &&
dev_mode.dmBitsPerPel == bits &&
dev_mode.dmDisplayFrequency == refresh )
@@ -3629,12 +3731,15 @@ BOOL LLWindowWin32::resetDisplayResolution()
void LLWindowWin32::swapBuffers()
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_WIN32;
- ASSERT_MAIN_THREAD();
- glFlush(); //superstitious flush for maybe frame stall removal?
- SwapBuffers(mhDC);
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_WIN32;
+ SwapBuffers(mhDC);
+ }
- LL_PROFILER_GPU_COLLECT
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("GPU Collect");
+ LL_PROFILER_GPU_COLLECT;
+ }
}
@@ -4575,13 +4680,17 @@ std::vector<std::string> LLWindowWin32::getDynamicFallbackFontList()
return std::vector<std::string>();
}
+U32 LLWindowWin32::getAvailableVRAMMegabytes()
+{
+ return mWindowThread ? mWindowThread->getAvailableVRAMMegabytes() : 0;
+}
#endif // LL_WINDOWS
inline LLWindowWin32::LLWindowWin32Thread::LLWindowWin32Thread()
- : ThreadPool("Window Thread", 1, MAX_QUEUE_SIZE)
+ : LL::ThreadPool("Window Thread", 1, MAX_QUEUE_SIZE)
{
- ThreadPool::start();
+ LL::ThreadPool::start();
}
/**
@@ -4630,17 +4739,229 @@ private:
std::string mPrev;
};
+// Print hardware debug info about available graphics adapters in ordinal order
+void debugEnumerateGraphicsAdapters()
+{
+ LL_INFOS("Window") << "Enumerating graphics adapters..." << LL_ENDL;
+
+ IDXGIFactory1* factory;
+ HRESULT res = CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)&factory);
+ if (FAILED(res) || !factory)
+ {
+ LL_WARNS() << "CreateDXGIFactory1 failed: 0x" << std::hex << res << LL_ENDL;
+ }
+ else
+ {
+ UINT graphics_adapter_index = 0;
+ IDXGIAdapter3* dxgi_adapter;
+ while (true)
+ {
+ res = factory->EnumAdapters(graphics_adapter_index, reinterpret_cast<IDXGIAdapter**>(&dxgi_adapter));
+ if (FAILED(res))
+ {
+ if (graphics_adapter_index == 0)
+ {
+ LL_WARNS() << "EnumAdapters failed: 0x" << std::hex << res << LL_ENDL;
+ }
+ else
+ {
+ LL_INFOS("Window") << "Done enumerating graphics adapters" << LL_ENDL;
+ }
+ }
+ else
+ {
+ DXGI_ADAPTER_DESC desc;
+ dxgi_adapter->GetDesc(&desc);
+ std::wstring description_w((wchar_t*)desc.Description);
+ std::string description(description_w.begin(), description_w.end());
+ LL_INFOS("Window") << "Graphics adapter index: " << graphics_adapter_index << ", "
+ << "Description: " << description << ", "
+ << "DeviceId: " << desc.DeviceId << ", "
+ << "SubSysId: " << desc.SubSysId << ", "
+ << "AdapterLuid: " << desc.AdapterLuid.HighPart << "_" << desc.AdapterLuid.LowPart << ", "
+ << "DedicatedVideoMemory: " << desc.DedicatedVideoMemory / 1024 / 1024 << ", "
+ << "DedicatedSystemMemory: " << desc.DedicatedSystemMemory / 1024 / 1024 << ", "
+ << "SharedSystemMemory: " << desc.SharedSystemMemory / 1024 / 1024 << LL_ENDL;
+ }
+
+ if (dxgi_adapter)
+ {
+ dxgi_adapter->Release();
+ dxgi_adapter = NULL;
+ }
+ else
+ {
+ break;
+ }
+
+ graphics_adapter_index++;
+ }
+ }
+
+ if (factory)
+ {
+ factory->Release();
+ }
+}
+
+void LLWindowWin32::LLWindowWin32Thread::initDX()
+{
+ if (mDXGIAdapter == NULL)
+ {
+ debugEnumerateGraphicsAdapters();
+
+ IDXGIFactory4* pFactory = nullptr;
+
+ HRESULT res = CreateDXGIFactory1(__uuidof(IDXGIFactory4), (void**)&pFactory);
+
+ if (FAILED(res))
+ {
+ LL_WARNS() << "CreateDXGIFactory1 failed: 0x" << std::hex << res << LL_ENDL;
+ }
+ else
+ {
+ res = pFactory->EnumAdapters(0, reinterpret_cast<IDXGIAdapter**>(&mDXGIAdapter));
+ if (FAILED(res))
+ {
+ LL_WARNS() << "EnumAdapters failed: 0x" << std::hex << res << LL_ENDL;
+ }
+ else
+ {
+ LL_INFOS() << "EnumAdapters success" << LL_ENDL;
+ }
+ }
+
+ if (pFactory)
+ {
+ pFactory->Release();
+ }
+ }
+}
+
+void LLWindowWin32::LLWindowWin32Thread::initD3D()
+{
+ if (mDXGIAdapter == NULL && mD3DDevice == NULL && mWindowHandle != 0)
+ {
+ mD3D = Direct3DCreate9(D3D_SDK_VERSION);
+
+ D3DPRESENT_PARAMETERS d3dpp;
+
+ ZeroMemory(&d3dpp, sizeof(d3dpp));
+ d3dpp.Windowed = TRUE;
+ d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
+
+ HRESULT res = mD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, mWindowHandle, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &mD3DDevice);
+
+ if (FAILED(res))
+ {
+ LL_WARNS() << "(fallback) CreateDevice failed: 0x" << std::hex << res << LL_ENDL;
+ }
+ else
+ {
+ LL_INFOS() << "(fallback) CreateDevice success" << LL_ENDL;
+ }
+ }
+}
+
+void LLWindowWin32::LLWindowWin32Thread::updateVRAMUsage()
+{
+ LL_PROFILE_ZONE_SCOPED;
+ if (mDXGIAdapter != nullptr)
+ {
+ // NOTE: what lies below is hand wavy math based on compatibility testing and observation against a variety of hardware
+ // It doesn't make sense, but please don't refactor it to make sense. -- davep
+
+ DXGI_QUERY_VIDEO_MEMORY_INFO info;
+ mDXGIAdapter->QueryVideoMemoryInfo(0, DXGI_MEMORY_SEGMENT_GROUP_LOCAL, &info);
+
+#if 0 // debug 0 budget and 0 CU
+ info.Budget = 0;
+ info.CurrentUsage = 0;
+#endif
+
+ U32 budget_mb = info.Budget / 1024 / 1024;
+ U32 afr_mb = info.AvailableForReservation / 1024 / 1024;
+ // correct for systems that misreport budget
+ if (budget_mb == 0)
+ {
+ // fall back to available for reservation clamped between 512MB and 2GB
+ budget_mb = llclamp(afr_mb, (U32) 512, (U32) 2048);
+ }
+
+ if ( mMaxVRAM != 0)
+ {
+ budget_mb = llmin(budget_mb, mMaxVRAM);
+ }
+
+ U32 cu_mb = info.CurrentUsage / 1024 / 1024;
+
+ // get an estimated usage based on texture bytes allocated
+ U32 eu_mb = LLImageGL::getTextureBytesAllocated() * 2 / 1024 / 1024;
+
+ if (cu_mb == 0)
+ { // current usage is sometimes unreliable on Intel GPUs, fall back to estimated usage
+ cu_mb = llmax((U32)1, eu_mb);
+ }
+ F32 eu_error = (F32)((S32)eu_mb - (S32)cu_mb) / (F32)cu_mb;
+
+ U32 target_mb = budget_mb;
+
+ if (target_mb > 4096) // if 4GB are installed, try to leave 2GB free
+ {
+ target_mb -= 2048;
+ }
+ else // if less than 4GB are installed, try not to use more than half of it
+ {
+ target_mb /= 2;
+ }
+
+ mAvailableVRAM = cu_mb < target_mb ? target_mb - cu_mb : 0;
+
+ LL_INFOS("Window") << "\nLocal\nAFR: " << info.AvailableForReservation / 1024 / 1024
+ << "\nBudget: " << info.Budget / 1024 / 1024
+ << "\nCR: " << info.CurrentReservation / 1024 / 1024
+ << "\nCU: " << info.CurrentUsage / 1024 / 1024
+ << "\nEU: " << eu_mb << llformat(" (%.2f)", eu_error)
+ << "\nTU: " << target_mb
+ << "\nAM: " << mAvailableVRAM << LL_ENDL;
+
+ /*mDXGIAdapter->QueryVideoMemoryInfo(0, DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL, &info);
+ LL_INFOS("Window") << "\nNon-Local\nAFR: " << info.AvailableForReservation / 1024 / 1024
+ << "\nBudget: " << info.Budget / 1024 / 1024
+ << "\nCR: " << info.CurrentReservation / 1024 / 1024
+ << "\nCU: " << info.CurrentUsage / 1024 / 1024 << LL_ENDL;*/
+ }
+ else if (mD3DDevice != NULL)
+ { // fallback to D3D9
+ mAvailableVRAM = mD3DDevice->GetAvailableTextureMem() / 1024 / 1024;
+ }
+}
+
void LLWindowWin32::LLWindowWin32Thread::run()
{
sWindowThreadId = std::this_thread::get_id();
LogChange logger("Window");
+ initDX();
+
+ //as good a place as any to up the MM timer resolution (see ms_sleep)
+ //attempt to set timer resolution to 1ms
+ TIMECAPS tc;
+ if (timeGetDevCaps(&tc, sizeof(TIMECAPS)) == TIMERR_NOERROR)
+ {
+ timeBeginPeriod(llclamp((U32) 1, tc.wPeriodMin, tc.wPeriodMax));
+ }
+
while (! getQueue().done())
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_WIN32;
if (mWindowHandle != 0)
{
+ // lazily call initD3D inside this loop to catch when mWindowHandle has been set
+ // *TODO: Shutdown if this fails when mWindowHandle exists
+ initD3D();
+
MSG msg;
BOOL status;
if (mhDC == 0)
@@ -4673,6 +4994,13 @@ void LLWindowWin32::LLWindowWin32Thread::run()
getQueue().runPending();
}
+ // update available vram once every 3 seconds
+ static LLFrameTimer vramTimer;
+ if (vramTimer.getElapsedTimeF32() > 3.f)
+ {
+ updateVRAMUsage();
+ vramTimer.reset();
+ }
#if 0
{
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("w32t - Sleep");
@@ -4681,6 +5009,26 @@ void LLWindowWin32::LLWindowWin32Thread::run()
}
#endif
}
+
+ //clean up DXGI/D3D resources
+ if (mDXGIAdapter)
+ {
+ mDXGIAdapter->Release();
+ mDXGIAdapter = nullptr;
+ }
+
+ if (mD3DDevice)
+ {
+ mD3DDevice->Release();
+ mD3DDevice = nullptr;
+ }
+
+ if (mD3D)
+ {
+ mD3D->Release();
+ mD3D = nullptr;
+ }
+
}
void LLWindowWin32::post(const std::function<void()>& func)
diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h
index b391acc12d..ff287a140e 100644
--- a/indra/llwindow/llwindowwin32.h
+++ b/indra/llwindow/llwindowwin32.h
@@ -108,7 +108,9 @@ public:
/*virtual*/ F32 getPixelAspectRatio();
/*virtual*/ void setNativeAspectRatio(F32 ratio) { mOverrideAspectRatio = ratio; }
- /*virtual*/ BOOL dialogColorPicker(F32 *r, F32 *g, F32 *b );
+ U32 getAvailableVRAMMegabytes() override;
+
+ /*virtual*/ BOOL dialogColorPicker(F32 *r, F32 *g, F32 *b );
/*virtual*/ void *getPlatformWindow();
/*virtual*/ void bringToFront();
@@ -137,7 +139,7 @@ protected:
LLWindowWin32(LLWindowCallbacks* callbacks,
const std::string& title, const std::string& name, int x, int y, int width, int height, U32 flags,
BOOL fullscreen, BOOL clearBg, BOOL enable_vsync, BOOL use_gl,
- BOOL ignore_pixel_depth, U32 fsaa_samples);
+ BOOL ignore_pixel_depth, U32 fsaa_samples, U32 max_cores, U32 max_vram, F32 max_gl_version);
~LLWindowWin32();
void initCursors();
@@ -208,6 +210,8 @@ protected:
F32 mCurrentGamma;
U32 mFSAASamples;
+ U32 mMaxCores; // for debugging only -- maximum number of CPU cores to use, or 0 for no limit
+ F32 mMaxGLVersion; // maximum OpenGL version to attempt to use (clamps to 3.2 - 4.6)
WORD mPrevGammaRamp[3][256];
WORD mCurrentGammaRamp[3][256];
BOOL mCustomGammaSet;
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 837efee7b1..085bac0042 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -56,6 +56,7 @@ include(UnixInstall)
include(ViewerMiscLibs)
include(ViewerManager)
include(VisualLeakDetector)
+include(VulkanGltf)
include(ZLIBNG)
include(URIPARSER)
@@ -187,6 +188,7 @@ set(viewer_SOURCE_FILES
lldrawpoolbump.cpp
lldrawpoolground.cpp
lldrawpoolmaterials.cpp
+ lldrawpoolpbropaque.cpp
lldrawpoolsimple.cpp
lldrawpoolsky.cpp
lldrawpoolterrain.cpp
@@ -206,6 +208,7 @@ set(viewer_SOURCE_FILES
llfasttimerview.cpp
llfavoritesbar.cpp
llfeaturemanager.cpp
+ llfetchedgltfmaterial.cpp
llfilepicker.cpp
llfilteredwearablelist.cpp
llfirstuse.cpp
@@ -323,7 +326,6 @@ set(viewer_SOURCE_FILES
llfloatertelehub.cpp
llfloatertestinspectors.cpp
llfloatertestlistview.cpp
- llfloatertexturefetchdebugger.cpp
llfloatertools.cpp
llfloatertopobjects.cpp
llfloatertos.cpp
@@ -345,6 +347,7 @@ set(viewer_SOURCE_FILES
llgesturemgr.cpp
llgiveinventory.cpp
llglsandbox.cpp
+ llgltfmateriallist.cpp
llgroupactions.cpp
llgroupiconctrl.cpp
llgrouplist.cpp
@@ -394,6 +397,7 @@ set(viewer_SOURCE_FILES
lllistcontextmenu.cpp
lllistview.cpp
lllocalbitmaps.cpp
+ lllocalgltfmaterials.cpp
lllocationhistory.cpp
lllocationinputctrl.cpp
lllogchat.cpp
@@ -406,6 +410,7 @@ set(viewer_SOURCE_FILES
llmaniptranslate.cpp
llmarketplacefunctions.cpp
llmarketplacenotifications.cpp
+ llmaterialeditor.cpp
llmaterialmgr.cpp
llmediactrl.cpp
llmediadataclient.cpp
@@ -547,6 +552,8 @@ set(viewer_SOURCE_FILES
llproductinforequest.cpp
llprogressview.cpp
llrecentpeople.cpp
+ llreflectionmap.cpp
+ llreflectionmapmanager.cpp
llregioninfomodel.cpp
llregionposition.cpp
llremoteparcelrequest.cpp
@@ -603,6 +610,7 @@ set(viewer_SOURCE_FILES
lltextureinfodetails.cpp
lltexturestats.cpp
lltextureview.cpp
+ lltinygltfhelper.cpp
lltoast.cpp
lltoastalertpanel.cpp
lltoastgroupnotifypanel.cpp
@@ -825,6 +833,7 @@ set(viewer_HEADER_FILES
lldrawpoolavatar.h
lldrawpoolbump.h
lldrawpoolmaterials.h
+ lldrawpoolpbropaque.h
lldrawpoolground.h
lldrawpoolsimple.h
lldrawpoolsky.h
@@ -845,6 +854,7 @@ set(viewer_HEADER_FILES
llfasttimerview.h
llfavoritesbar.h
llfeaturemanager.h
+ llfetchedgltfmaterial.h
llfilepicker.h
llfilteredwearablelist.h
llfirstuse.h
@@ -965,7 +975,6 @@ set(viewer_HEADER_FILES
llfloatertelehub.h
llfloatertestinspectors.h
llfloatertestlistview.h
- llfloatertexturefetchdebugger.h
llfloatertools.h
llfloatertopobjects.h
llfloatertos.h
@@ -986,6 +995,7 @@ set(viewer_HEADER_FILES
llgesturelistener.h
llgesturemgr.h
llgiveinventory.h
+ llgltfmateriallist.h
llgroupactions.h
llgroupiconctrl.h
llgrouplist.h
@@ -1034,6 +1044,7 @@ set(viewer_HEADER_FILES
lllistcontextmenu.h
lllistview.h
lllocalbitmaps.h
+ lllocalgltfmaterials.h
lllocationhistory.h
lllocationinputctrl.h
lllogchat.h
@@ -1046,6 +1057,7 @@ set(viewer_HEADER_FILES
llmaniptranslate.h
llmarketplacefunctions.h
llmarketplacenotifications.h
+ llmaterialeditor.h
llmaterialmgr.h
llmediactrl.h
llmediadataclient.h
@@ -1174,6 +1186,8 @@ set(viewer_HEADER_FILES
llproductinforequest.h
llprogressview.h
llrecentpeople.h
+ llreflectionmap.h
+ llreflectionmapmanager.h
llregioninfomodel.h
llregionposition.h
llremoteparcelrequest.h
@@ -1234,6 +1248,7 @@ set(viewer_HEADER_FILES
lltextureinfodetails.h
lltexturestats.h
lltextureview.h
+ lltinygltfhelper.h
lltoast.h
lltoastalertpanel.h
lltoastgroupnotifypanel.h
@@ -1675,18 +1690,23 @@ set_source_files_properties(${viewer_XUI_FILES}
list(APPEND viewer_SOURCE_FILES ${viewer_XUI_FILES})
+file(GLOB_RECURSE viewer_SHADER_FILES LIST_DIRECTORIES TRUE
+ ${CMAKE_CURRENT_SOURCE_DIR}/app_settings/shaders/*.glsl)
+source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR}/app_settings/shaders PREFIX "Shaders" FILES ${viewer_SHADER_FILES})
+set_source_files_properties(${viewer_SHADER_FILES}
+ PROPERTIES HEADER_FILE_ONLY TRUE)
+list(APPEND viewer_SOURCE_FILES ${viewer_SHADER_FILES})
+
+
set(viewer_APPSETTINGS_FILES
app_settings/anim.ini
app_settings/cmd_line.xml
app_settings/commands.xml
app_settings/grass.xml
- app_settings/high_graphics.xml
app_settings/ignorable_dialogs.xml
app_settings/key_bindings.xml
app_settings/keywords_lsl_default.xml
app_settings/logcontrol.xml
- app_settings/low_graphics.xml
- app_settings/mid_graphics.xml
app_settings/settings.xml
app_settings/settings_crash_behavior.xml
app_settings/settings_files.xml
@@ -1694,7 +1714,6 @@ set(viewer_APPSETTINGS_FILES
app_settings/std_bump.ini
app_settings/toolbars.xml
app_settings/trees.xml
- app_settings/ultra_graphics.xml
app_settings/viewerart.xml
${CMAKE_SOURCE_DIR}/../etc/message.xml
${CMAKE_SOURCE_DIR}/../scripts/messages/message_template.msg
@@ -2510,6 +2529,19 @@ if (LL_TESTS)
"${test_libs}"
)
+ set(llviewercontrollistener_test_sources
+ llviewercontrollistener.cpp
+ ../llxml/llcontrol.cpp
+ ../llxml/llxmltree.cpp
+ ../llxml/llxmlparser.cpp
+ ../llcommon/commoncontrol.cpp
+ )
+
+ LL_ADD_INTEGRATION_TEST(llviewercontrollistener
+ "${llviewercontrollistener_test_sources}"
+ "${test_libs}"
+ )
+
LL_ADD_INTEGRATION_TEST(llviewernetwork
llviewernetwork.cpp
"${test_libs}"
diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt
index 0673dfa857..66ce77b7ea 100644
--- a/indra/newview/VIEWER_VERSION.txt
+++ b/indra/newview/VIEWER_VERSION.txt
@@ -1 +1 @@
-6.6.10
+7.0.0
diff --git a/indra/newview/app_settings/high_graphics.xml b/indra/newview/app_settings/high_graphics.xml
deleted file mode 100644
index f64937f443..0000000000
--- a/indra/newview/app_settings/high_graphics.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<settings version = "101">
- <!--NO SHADERS-->
- <RenderAvatarCloth value="FALSE"/>
- <!--Default for now-->
- <RenderAvatarLODFactor value="1.0"/>
- <!--Default for now-->
- <RenderAvatarPhysicsLODFactor value="0.9"/>
- <!--Short Range-->
- <RenderFarClip value="128"/>
- <!--Default for now-->
- <RenderFlexTimeFactor value="1"/>
- <!--256... but they do not use this-->
- <RenderGlowResolutionPow value="9"/>
- <!--Low number-->
- <RenderMaxPartCount value="4096"/>
- <!--bump okay-->
- <RenderObjectBump value="TRUE"/>
- <!--NO SHADERS-->
- <RenderReflectionDetail value="2"/>
- <!--Simple-->
- <RenderTerrainDetail value="1"/>
- <!--Default for now-->
- <RenderTerrainLODFactor value="2"/>
- <!--Default for now-->
- <RenderTreeLODFactor value="0.5"/>
- <!--Avater Impostors and Visual Muting Limits-->
- <RenderAvatarMaxNonImpostors value="20"/>
- <RenderAvatarMaxComplexity value="350000"/>
- <RenderAutoMuteSurfaceAreaLimit value="1250.0"/>
- <!--Default for now-->
- <RenderVolumeLODFactor value="1.125"/>
- <!--NO SHADERS-->
- <WindLightUseAtmosShaders value="TRUE"/>
- <!--Deferred Shading-->
- <RenderDeferred value="FALSE"/>
- <!--SSAO Disabled-->
- <RenderDeferredSSAO value="FALSE"/>
- <!--Sun Shadows-->
- <RenderShadowDetail value="0"/>
-</settings>
diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml
index 482012cdd6..2a26cb9a43 100644
--- a/indra/newview/app_settings/logcontrol.xml
+++ b/indra/newview/app_settings/logcontrol.xml
@@ -73,6 +73,7 @@
<string>Avatar</string>
<string>Voice</string>
-->
+ <string>Capabilities</string>
</array>
</map>
</array>
diff --git a/indra/newview/app_settings/low_graphics.xml b/indra/newview/app_settings/low_graphics.xml
deleted file mode 100644
index b31a040d67..0000000000
--- a/indra/newview/app_settings/low_graphics.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<settings version = "101">
- <!--NO SHADERS-->
- <RenderAvatarCloth value="FALSE"/>
- <!--Default for now-->
- <RenderAvatarLODFactor value="0.5"/>
- <!--Default for now-->
- <RenderAvatarPhysicsLODFactor value="0.0"/>
- <!--Short Range-->
- <RenderFarClip value="64"/>
- <!--Default for now-->
- <RenderFlexTimeFactor value="0.5"/>
- <!--256... but they do not use this-->
- <RenderGlowResolutionPow value="8"/>
- <!--Low number-->
- <RenderMaxPartCount value="1024"/>
- <!--bump okay-->
- <RenderObjectBump value="FALSE"/>
- <!--NO SHADERS-->
- <RenderReflectionDetail value="0"/>
- <!--Simple-->
- <RenderTerrainDetail value="0"/>
- <!--Default for now-->
- <RenderTerrainLODFactor value="1.0"/>
- <!--Default for now-->
- <RenderTreeLODFactor value="0.5"/>
- <!--Avater Impostors and Visual Muting Limits-->
- <RenderAvatarMaxNonImpostors value="12"/>
- <RenderAvatarMaxComplexity value="80000"/>
- <RenderAutoMuteSurfaceAreaLimit value="750.0"/>
- <!--Default for now-->
- <RenderVolumeLODFactor value="1.125"/>
- <!--NO SHADERS-->
- <WindLightUseAtmosShaders value="FALSE"/>
- <!--No Deferred Shading-->
- <RenderDeferred value="FALSE"/>
- <!--SSAO Disabled-->
- <RenderDeferredSSAO value="FALSE"/>
- <!--No Shadows-->
- <RenderShadowDetail value="0"/>
-</settings>
diff --git a/indra/newview/app_settings/mid_graphics.xml b/indra/newview/app_settings/mid_graphics.xml
deleted file mode 100644
index 9c2c17fc60..0000000000
--- a/indra/newview/app_settings/mid_graphics.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<settings version = "101">
- <!--NO SHADERS-->
- <RenderAvatarCloth value="FALSE"/>
- <!--Default for now-->
- <RenderAvatarLODFactor value="0.5"/>
- <!--Default for now-->
- <RenderAvatarPhysicsLODFactor value="0.75"/>
- <!--Short Range-->
- <RenderFarClip value="96"/>
- <!--Default for now-->
- <RenderFlexTimeFactor value="1"/>
- <!--256... but they do not use this-->
- <RenderGlowResolutionPow value="8"/>
- <!--Low number-->
- <RenderMaxPartCount value="2048"/>
- <!--bump okay-->
- <RenderObjectBump value="TRUE"/>
- <!--NO SHADERS-->
- <RenderReflectionDetail value="0"/>
- <!--Simple-->
- <RenderTerrainDetail value="1"/>
- <!--Default for now-->
- <RenderTerrainLODFactor value="1.0"/>
- <!--Default for now-->
- <RenderTreeLODFactor value="0.5"/>
- <!--Avater Impostors and Visual Muting Limits-->
- <RenderAvatarMaxNonImpostors value="18"/>
- <RenderAvatarMaxComplexity value="150000"/>
- <RenderAutoMuteSurfaceAreaLimit value="1000.0"/>
- <!--Default for now-->
- <RenderVolumeLODFactor value="1.125"/>
- <!--NO SHADERS-->
- <WindLightUseAtmosShaders value="FALSE"/>
- <!--No Deferred Shading-->
- <RenderDeferred value="FALSE"/>
- <!--SSAO Disabled-->
- <RenderDeferredSSAO value="FALSE"/>
- <!--No Shadows-->
- <RenderShadowDetail value="0"/>
-</settings>
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 411f77e6a7..4a12d239ed 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -1241,6 +1241,17 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>BulkChangeIncludeMaterials</key>
+ <map>
+ <key>Comment</key>
+ <string>Bulk permission changes affect materials</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>BulkChangeEveryoneCopy</key>
<map>
<key>Comment</key>
@@ -3902,7 +3913,7 @@
<key>Type</key>
<string>F32</string>
<key>Value</key>
- <real>0.1</real>
+ <real>1.0</real>
</map>
<key>QueueInventoryFetchTimeout</key>
<map>
@@ -8734,7 +8745,7 @@
<string>Vector3</string>
<key>Value</key>
<array>
- <real>0.01</real>
+ <real>0.25</real>
<real>0.0</real>
<real>0.0</real>
</array>
@@ -8809,13 +8820,13 @@
<key>RenderAvatarCloth</key>
<map>
<key>Comment</key>
- <string>Controls if avatars use wavy cloth</string>
+ <string>DEPRECATED - only false supported - Controls if avatars use wavy cloth</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
- <integer>1</integer>
+ <integer>0</integer>
</map>
<key>RenderComplexityColorMin</key>
<map>
@@ -9122,6 +9133,17 @@
<real>0.00</real>
</array>
</map>
+ <key>RenderScreenSpaceReflections</key>
+ <map>
+ <key>Comment</key>
+ <string>Renders screen space reflections to better account for dynamic objects with reflection probes.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>RenderBumpmapMinDistanceSquared</key>
<map>
<key>Comment</key>
@@ -9199,6 +9221,28 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>RenderMaxOpenGLVersion</key>
+ <map>
+ <key>Comment</key>
+ <string>Maximum OpenGL version to attempt use (minimum 3.2 maximum 4.6). Requires restart.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>4.6</real>
+ </map>
+ <key>RenderMaxVRAMBudget</key>
+ <map>
+ <key>Comment</key>
+ <string>Maximum amount of texture memory to budget for (in MB), or 0 for autodetect. Requires restart.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>U32</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>RenderMaxTextureIndex</key>
<map>
<key>Comment</key>
@@ -9514,7 +9558,7 @@
<key>RenderHoverGlowEnable</key>
<map>
<key>Comment</key>
- <string>Show glow effect when hovering on interactive objects.</string>
+ <string>DEPRECATED --- Show glow effect when hovering on interactive objects.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -9627,13 +9671,13 @@
<key>RenderDeferred</key>
<map>
<key>Comment</key>
- <string>Use deferred rendering pipeline (Advanced Lighting Model).</string>
+ <string>DEPRECATED (only true supported) - Use deferred rendering pipeline (Advanced Lighting Model).</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
- <integer>0</integer>
+ <integer>1</integer>
</map>
<key>RenderDeferredSun</key>
@@ -9848,7 +9892,7 @@
<key>RenderFogRatio</key>
<map>
<key>Comment</key>
- <string>Distance from camera where fog reaches maximum density (fraction or multiple of far clip distance)</string>
+ <string>DEPRECATED - Distance from camera where fog reaches maximum density (fraction or multiple of far clip distance)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -9859,7 +9903,7 @@
<key>RenderGamma</key>
<map>
<key>Comment</key>
- <string>Sets gamma exponent for renderer</string>
+ <string>DEPRECATED - Sets gamma exponent for renderer</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -9892,7 +9936,7 @@
<key>RenderGLContextCoreProfile</key>
<map>
<key>Comment</key>
- <string>Don't use a compatibility profile OpenGL context. Requires restart. Basic shaders MUST be enabled.</string>
+ <string>Don't use a compatibility profile OpenGL context. Requires restart.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -10183,6 +10227,17 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>RenderReflectionProbeVolumes</key>
+ <map>
+ <key>Comment</key>
+ <string>Render influence volumes of Reflection Probes</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>RenderMaxPartCount</key>
<map>
<key>Comment</key>
@@ -10252,7 +10307,7 @@
<key>RenderObjectBump</key>
<map>
<key>Comment</key>
- <string>Show bumpmapping on primitives</string>
+ <string>DEPRECATED (only TRUE supported) Show bumpmapping on primitives</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -10271,10 +10326,11 @@
<key>Value</key>
<integer>1</integer>
</map>
- <key>RenderReflectionDetail</key>
+
+ <key>RenderReflectionDetail</key>
<map>
<key>Comment</key>
- <string>Detail of reflection render pass.</string>
+ <string>DEPRECATED -- use RenderTransparentWater and RenderReflectionProbeDetail -- Detail of reflection render pass.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -10293,8 +10349,97 @@
<key>Value</key>
<integer>2</integer>
</map>
+ <key>RenderReflectionsEnabled</key>
+ <map>
+ <key>Comment</key>
+ <string>Enable/disable reflection probes</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>RenderReflectionProbeDetail</key>
+ <map>
+ <key>Comment</key>
+ <string>Detail of reflections. (-1 - Disabled, 0 - Static Only, 1 - Static + Dynamic, 2 - Realtime)</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>RenderReflectionProbeCount</key>
+ <map>
+ <key>Comment</key>
+ <string>Number of reflection probes (maximum is 256, requires restart)</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>256</integer>
+ </map>
+ <key>RenderReflectionProbeResolution</key>
+ <map>
+ <key>Comment</key>
+ <string>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.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>U32</string>
+ <key>Value</key>
+ <integer>256</integer>
+ </map>
+ <key>RenderReflectionProbeAmbianceScale</key>
+ <map>
+ <key>Comment</key>
+ <string>Scaler to apply to reflection probes to over-brighten sky contributions to indirect light</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <integer>8</integer>
+ </map>
- <key>RenderReflectionRes</key>
+ <key>RenderReflectionProbeDrawDistance</key>
+ <map>
+ <key>Comment</key>
+ <string>Camera far clip to use when updating reflection probes.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>64</real>
+ </map>
+ <key>RenderReflectionProbeAmbiance</key>
+ <map>
+ <key>Comment</key>
+ <string>Amount reflection probes contribute to ambient light.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0</real>
+ </map>
+ <key>RenderReflectionProbeTextureHackID</key>
+ <map>
+ <key>Comment</key>
+ <string>HACK -- Any object with a diffuse texture with this ID will be treated as a user override reflection probe. (default is "Violet Info Hub" photo from Library)</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>String</string>
+ <key>Value</key>
+ <string>6b186931-05da-eafa-a3ed-a012a33bbfb6</string>
+ </map>
+
+ <key>RenderReflectionRes</key>
<map>
<key>Comment</key>
<string>Reflection map resolution.</string>
@@ -10393,17 +10538,6 @@
<key>Value</key>
<real>12.0</real>
</map>
- <key>RenderTextureMemoryMultiple</key>
- <map>
- <key>Comment</key>
- <string>Multiple of texture memory value to use (should fit: 0 &lt; value &lt;= 1.0)</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>F32</string>
- <key>Value</key>
- <real>1.0</real>
- </map>
<key>RenderTrackerBeacon</key>
<map>
<key>Comment</key>
@@ -10484,7 +10618,7 @@
<key>RenderUseTriStrips</key>
<map>
<key>Comment</key>
- <string>Use triangle strips for rendering prims.</string>
+ <string>DEPRECATED - now always assumed to be false - Use triangle strips for rendering prims.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -10696,18 +10830,6 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>RenderUseTransformFeedback</key>
- <map>
- <key>Comment</key>
- <string>[EXPERIMENTAL] Use transform feedback shaders for LoD updates</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>0</integer>
- </map>
-
<key>RenderVBOMappingDisable</key>
<map>
<key>Comment</key>
@@ -11170,6 +11292,17 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>SelectInvisibleObjects</key>
+ <map>
+ <key>Comment</key>
+ <string>Select invisible objects</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>SelectOwnedOnly</key>
<map>
<key>Comment</key>
@@ -12472,17 +12605,6 @@
<key>Value</key>
<real>20.0</real>
</map>
- <key>TexelPixelRatio</key>
- <map>
- <key>Comment</key>
- <string>texel pixel ratio = texel / pixel</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>F32</string>
- <key>Value</key>
- <real>1.0</real>
- </map>
<key>TextureCameraMotionThreshold</key>
<map>
<key>Comment</key>
@@ -12582,17 +12704,6 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>TextureFetchDebuggerEnabled</key>
- <map>
- <key>Comment</key>
- <string>Enable the texture fetching debugger if set</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>0</integer>
- </map>
<key>TextureFetchMinTimeToLog</key>
<map>
<key>Comment</key>
@@ -12615,43 +12726,10 @@
<key>Value</key>
<real>0.0</real>
</map>
- <key>TextureFetchSource</key>
- <map>
- <key>Comment</key>
- <string>Debug use: Source to fetch textures</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>S32</string>
- <key>Value</key>
- <integer>0</integer>
- </map>
- <key>TextureFetchUpdateHighPriority</key>
- <map>
- <key>Comment</key>
- <string>Number of high priority textures to update per frame</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>S32</string>
- <key>Value</key>
- <integer>32</integer>
- </map>
- <key>TextureFetchUpdateMaxMediumPriority</key>
+ <key>TextureFetchUpdateMinCount</key>
<map>
<key>Comment</key>
- <string>Maximum number of medium priority textures to update per frame</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>S32</string>
- <key>Value</key>
- <integer>256</integer>
- </map>
- <key>TextureFetchUpdateMinMediumPriority</key>
- <map>
- <key>Comment</key>
- <string>Minimum number of medium priority textures to update per frame</string>
+ <string>Minimum number of textures to update per frame</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -12659,69 +12737,14 @@
<key>Value</key>
<integer>32</integer>
</map>
- <key>TextureFetchUpdatePriorityThreshold</key>
- <map>
- <key>Comment</key>
- <string>Threshold under which textures will be considered too low priority and skipped for update</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>F32</string>
- <key>Value</key>
- <real>0.0</real>
- </map>
- <key>TextureFetchUpdateSkipLowPriority</key>
- <map>
- <key>Comment</key>
- <string>Flag indicating if we want to skip textures with too low of a priority</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>0</integer>
- </map>
- <key>TextureFetchUpdatePriorities</key>
- <map>
- <key>Comment</key>
- <string>Number of priority texture to update per frame</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>S32</string>
- <key>Value</key>
- <integer>32</integer>
- </map>
- <key>TextureListFetchingThreshold</key>
- <map>
- <key>Comment</key>
- <string>If the ratio between fetched and all textures in the list is greater than this threshold, which we assume that almost all textures are fetched</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>F32</string>
- <key>Value</key>
- <real>0.97</real>
- </map>
<key>TextureLoadFullRes</key>
<map>
<key>Comment</key>
<string>If TRUE, always load textures at full resolution (discard = 0)</string>
<key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>0</integer>
- </map>
- <key>TextureMemory</key>
- <map>
- <key>Comment</key>
- <string>Amount of memory to use for textures in MB (0 = autodetect)</string>
- <key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>S32</string>
+ <string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
@@ -12791,7 +12814,9 @@
<key>Value</key>
<map>
<key>General</key>
- <integer>4</integer>
+ <integer>1</integer>
+ <key>ImageDecode</key>
+ <integer>9</integer>
</map>
</map>
<key>ThrottleBandwidthKBPS</key>
@@ -14890,7 +14915,7 @@
<key>WindLightUseAtmosShaders</key>
<map>
<key>Comment</key>
- <string>Whether to enable or disable WindLight atmospheric shaders.</string>
+ <string>DEPRECATED (only true supported) - Whether to enable or disable WindLight atmospheric shaders.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -16179,6 +16204,61 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>MaterialsNextOwnerCopy</key>
+ <map>
+ <key>Comment</key>
+ <string>Newly created GLTF material can be copied by next owner</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>MaterialsNextOwnerModify</key>
+ <map>
+ <key>Comment</key>
+ <string>Newly created GLTF material can be modified by next owner</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>MaterialsNextOwnerTransfer</key>
+ <map>
+ <key>Comment</key>
+ <string>Newly created GLTF material can be resold or given away by next owner</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>MaterialsEveryoneCopy</key>
+ <map>
+ <key>Comment</key>
+ <string>Everyone can copy the newly created GLTF material</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>MaterialsShareWithGroup</key>
+ <map>
+ <key>Comment</key>
+ <string>Newly created GLTF materials are shared with the currently active group</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>DefaultUploadPermissionsConverted</key>
<map>
<key>Comment</key>
@@ -16887,6 +16967,17 @@
<key>Value</key>
<string></string>
</map>
+ <key>EmulateCoreCount</key>
+ <map>
+ <key>Comment</key>
+ <string>For debugging -- number of cores to restrict the main process to, or 0 for no limit. Requires restart.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>U32</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>DebugSettingsHideDefault</key>
<map>
<key>Comment</key>
diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml
index 537744b44c..eb3528b9b7 100644
--- a/indra/newview/app_settings/settings_per_account.xml
+++ b/indra/newview/app_settings/settings_per_account.xml
@@ -370,6 +370,17 @@
<key>Value</key>
<string></string>
</map>
+ <key>PBRUploadFolder</key>
+ <map>
+ <key>Comment</key>
+ <string>All pbr uploads will be stored in this directory (UUID)</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>String</string>
+ <key>Value</key>
+ <string></string>
+ </map>
<key>TextureUploadFolder</key>
<map>
<key>Comment</key>
diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
index 02b2daf0ac..f4ec1ec532 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
@@ -25,305 +25,11 @@
//class1/deferred/alphaF.glsl
-#extension GL_ARB_texture_rectangle : enable
-/*[EXTRA_CODE_HERE]*/
-
-#define INDEXED 1
-#define NON_INDEXED 2
-#define NON_INDEXED_NO_COLOR 3
-
-#ifdef DEFINE_GL_FRAGCOLOR
out vec4 frag_color;
-#else
-#define frag_color gl_FragColor
-#endif
-
-uniform mat3 env_mat;
-uniform vec3 sun_dir;
-uniform vec3 moon_dir;
-
-#ifdef USE_DIFFUSE_TEX
-uniform sampler2D diffuseMap;
-#endif
-
-VARYING vec3 vary_fragcoord;
-VARYING vec3 vary_position;
-VARYING vec2 vary_texcoord0;
-VARYING vec3 vary_norm;
-
-#ifdef USE_VERTEX_COLOR
-VARYING vec4 vertex_color; //vertex color should be treated as sRGB
-#endif
-
-#ifdef HAS_ALPHA_MASK
-uniform float minimum_alpha;
-#endif
-
-uniform mat4 proj_mat;
-uniform mat4 inv_proj;
-uniform vec2 screen_res;
-uniform int sun_up_factor;
-uniform vec4 light_position[8];
-uniform vec3 light_direction[8];
-uniform vec4 light_attenuation[8];
-uniform vec3 light_diffuse[8];
-
-#ifdef WATER_FOG
-vec4 applyWaterFogView(vec3 pos, vec4 color);
-#endif
-
-vec3 srgb_to_linear(vec3 c);
-vec3 linear_to_srgb(vec3 c);
-
-vec2 encode_normal (vec3 n);
-vec3 scaleSoftClipFrag(vec3 l);
-vec3 atmosFragLighting(vec3 light, vec3 additive, vec3 atten);
-
-void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, out vec3 sunlit, out vec3 amblit, out vec3 atten, out vec3 additive, bool use_ao);
-
-#ifdef HAS_SHADOW
-float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen);
-#endif
-
-float getAmbientClamp();
-
-vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 diffuse, vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight, float ambiance)
-{
- // SL-14895 inverted attenuation work-around
- // This routine is tweaked to match deferred lighting, but previously used an inverted la value. To reconstruct
- // that previous value now that the inversion is corrected, we reverse the calculations in LLPipeline::setupHWLights()
- // to recover the `adjusted_radius` value previously being sent as la.
- float falloff_factor = (12.0 * fa) - 9.0;
- float inverted_la = falloff_factor / la;
- // Yes, it makes me want to cry as well. DJH
-
- vec3 col = vec3(0);
-
- //get light vector
- vec3 lv = lp.xyz-v;
-
- //get distance
- float dist = length(lv);
- float da = 1.0;
- /*if (dist > inverted_la)
- {
- return col;
- }
-
- clip to projector bounds
- vec4 proj_tc = proj_mat * lp;
-
- if (proj_tc.z < 0
- || proj_tc.z > 1
- || proj_tc.x < 0
- || proj_tc.x > 1
- || proj_tc.y < 0
- || proj_tc.y > 1)
- {
- return col;
- }*/
-
- if (dist > 0.0 && inverted_la > 0.0)
- {
- dist /= inverted_la;
-
- //normalize light vector
- lv = normalize(lv);
-
- //distance attenuation
- float dist_atten = clamp(1.0-(dist-1.0*(1.0-fa))/fa, 0.0, 1.0);
- dist_atten *= dist_atten;
- dist_atten *= 2.0f;
-
- if (dist_atten <= 0.0)
- {
- return col;
- }
-
- // spotlight coefficient.
- float spot = max(dot(-ln, lv), is_pointlight);
- da *= spot*spot; // GL_SPOT_EXPONENT=2
-
- //angular attenuation
- da *= dot(n, lv);
- da = max(0.0, da);
-
- float lit = 0.0f;
-
- float amb_da = 0.0;//ambiance;
- if (da > 0)
- {
- lit = max(da * dist_atten,0.0);
- col = lit * light_col * diffuse;
- amb_da += (da*0.5+0.5) * ambiance;
- }
- amb_da += (da*da*0.5 + 0.5) * ambiance;
- amb_da *= dist_atten;
- amb_da = min(amb_da, 1.0f - lit);
-
- // SL-10969 ... need to work out why this blows out in many setups...
- //col.rgb += amb_da * light_col * diffuse;
-
- // no spec for alpha shader...
- }
- col = max(col, vec3(0));
- return col;
-}
-
-void main()
+void main()
{
- vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5;
- frag *= screen_res;
-
- vec4 pos = vec4(vary_position, 1.0);
- vec3 norm = vary_norm;
-
- float shadow = 1.0f;
-
-#ifdef HAS_SHADOW
- shadow = sampleDirectionalShadow(pos.xyz, norm.xyz, frag);
-#endif
-
-#ifdef USE_DIFFUSE_TEX
- vec4 diffuse_tap = texture2D(diffuseMap,vary_texcoord0.xy);
-#endif
-
-#ifdef USE_INDEXED_TEX
- vec4 diffuse_tap = diffuseLookup(vary_texcoord0.xy);
-#endif
-
- vec4 diffuse_srgb = diffuse_tap;
-
-#ifdef FOR_IMPOSTOR
- vec4 color;
- color.rgb = diffuse_srgb.rgb;
- color.a = 1.0;
-
- float final_alpha = diffuse_srgb.a * vertex_color.a;
- diffuse_srgb.rgb *= vertex_color.rgb;
-
- // Insure we don't pollute depth with invis pixels in impostor rendering
- //
- if (final_alpha < minimum_alpha)
- {
- discard;
- }
-
- color.rgb = diffuse_srgb.rgb;
- color.a = final_alpha;
-
-#else // FOR_IMPOSTOR
-
- vec4 diffuse_linear = vec4(srgb_to_linear(diffuse_srgb.rgb), diffuse_srgb.a);
-
- vec3 light_dir = (sun_up_factor == 1) ? sun_dir: moon_dir;
-
- float final_alpha = diffuse_linear.a;
-
-#ifdef USE_VERTEX_COLOR
- final_alpha *= vertex_color.a;
-
- if (final_alpha < minimum_alpha)
- { // TODO: figure out how to get invisible faces out of
- // render batches without breaking glow
- discard;
- }
-
- diffuse_srgb.rgb *= vertex_color.rgb;
- diffuse_linear.rgb = srgb_to_linear(diffuse_srgb.rgb);
-#endif // USE_VERTEX_COLOR
-
- vec3 sunlit;
- vec3 amblit;
- vec3 additive;
- vec3 atten;
-
- calcAtmosphericVars(pos.xyz, light_dir, 1.0, sunlit, amblit, additive, atten, false);
-
- vec2 abnormal = encode_normal(norm.xyz);
-
- float da = dot(norm.xyz, light_dir.xyz);
- da = clamp(da, -1.0, 1.0);
- da = pow(da, 1.0/1.3);
-
- float final_da = da;
- final_da = clamp(final_da, 0.0f, 1.0f);
-
- vec4 color = vec4(0.0);
-
- color.a = final_alpha;
-
- float ambient = min(abs(dot(norm.xyz, sun_dir.xyz)), 1.0);
- ambient *= 0.5;
- ambient *= ambient;
- ambient = (1.0 - ambient);
-
- vec3 sun_contrib = min(final_da, shadow) * sunlit;
-
-#if !defined(AMBIENT_KILL)
- color.rgb = amblit;
- color.rgb *= ambient;
-#endif // !defined(AMBIENT_KILL)
-
-vec3 post_ambient = color.rgb;
-
-#if !defined(SUNLIGHT_KILL)
- color.rgb += sun_contrib;
-#endif // !defined(SUNLIGHT_KILL)
-
-vec3 post_sunlight = color.rgb;
-
- color.rgb *= diffuse_srgb.rgb;
-
-vec3 post_diffuse = color.rgb;
-
- color.rgb = atmosFragLighting(color.rgb, additive, atten);
-
-vec3 post_atmo = color.rgb;
-
- vec4 light = vec4(0,0,0,0);
-
- color.rgb = scaleSoftClipFrag(color.rgb);
-
- //convert to linear before applying local lights
- color.rgb = srgb_to_linear(color.rgb);
-
- #define LIGHT_LOOP(i) light.rgb += calcPointLightOrSpotLight(light_diffuse[i].rgb, diffuse_linear.rgb, pos.xyz, norm, light_position[i], light_direction[i].xyz, light_attenuation[i].x, light_attenuation[i].y, light_attenuation[i].z, light_attenuation[i].w);
-
- LIGHT_LOOP(1)
- LIGHT_LOOP(2)
- LIGHT_LOOP(3)
- LIGHT_LOOP(4)
- LIGHT_LOOP(5)
- LIGHT_LOOP(6)
- LIGHT_LOOP(7)
-
- // sum local light contrib in linear colorspace
-#if !defined(LOCAL_LIGHT_KILL)
- color.rgb += light.rgb;
-#endif // !defined(LOCAL_LIGHT_KILL)
- // back to sRGB as we're going directly to the final RT post-deferred gamma correction
- color.rgb = linear_to_srgb(color.rgb);
-
-//color.rgb = amblit;
-//color.rgb = vec3(ambient);
-//color.rgb = sunlit;
-//color.rgb = vec3(final_da);
-//color.rgb = post_ambient;
-//color.rgb = post_sunlight;
-//color.rgb = sun_contrib;
-//color.rgb = diffuse_srgb.rgb;
-//color.rgb = post_diffuse;
-//color.rgb = post_atmo;
-
-#ifdef WATER_FOG
- color = applyWaterFogView(pos.xyz, color);
-#endif // WATER_FOG
-
-#endif // #else // FOR_IMPOSTOR
-
- frag_color = color;
+ frag_color = vec4(1,0,1,0.5);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/aoUtil.glsl b/indra/newview/app_settings/shaders/class1/deferred/aoUtil.glsl
index 23adbded5e..37fe8287be 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/aoUtil.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/aoUtil.glsl
@@ -24,8 +24,8 @@
*/
uniform sampler2D noiseMap;
-uniform sampler2DRect normalMap;
-uniform sampler2DRect depthMap;
+uniform sampler2D normalMap;
+uniform sampler2D depthMap;
uniform float ssao_radius;
uniform float ssao_max_radius;
@@ -38,16 +38,12 @@ uniform vec2 screen_res;
vec2 getScreenCoordinateAo(vec2 screenpos)
{
vec2 sc = screenpos.xy * 2.0;
- if (screen_res.x > 0 && screen_res.y > 0)
- {
- sc /= screen_res;
- }
return sc - vec2(1.0, 1.0);
}
float getDepthAo(vec2 pos_screen)
{
- float depth = texture2DRect(depthMap, pos_screen).r;
+ float depth = texture2D(depthMap, pos_screen).r;
return depth;
}
@@ -75,7 +71,7 @@ vec2 getKern(int i)
kern[6] = vec2(-0.7071, 0.7071) * 0.875*0.875;
kern[7] = vec2(0.7071, -0.7071) * 1.000*1.000;
- return kern[i];
+ return kern[i] / screen_res;
}
//calculate decreases in ambient lighting when crowded out (SSAO)
@@ -83,8 +79,8 @@ float calcAmbientOcclusion(vec4 pos, vec3 norm, vec2 pos_screen)
{
float ret = 1.0;
vec3 pos_world = pos.xyz;
- vec2 noise_reflect = texture2D(noiseMap, pos_screen.xy/128.0).xy;
-
+ vec2 noise_reflect = texture2D(noiseMap, pos_screen.xy * (screen_res / 128)).xy;
+
float angle_hidden = 0.0;
float points = 0;
@@ -95,7 +91,7 @@ float calcAmbientOcclusion(vec4 pos, vec3 norm, vec2 pos_screen)
{
vec2 samppos_screen = pos_screen + scale * reflect(getKern(i), noise_reflect);
vec3 samppos_world = getPositionAo(samppos_screen).xyz;
-
+
vec3 diff = pos_world - samppos_world;
float dist2 = dot(diff, diff);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/attachmentAlphaMaskShadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/attachmentAlphaMaskShadowF.glsl
deleted file mode 100644
index c64b6ba240..0000000000
--- a/indra/newview/app_settings/shaders/class1/deferred/attachmentAlphaMaskShadowF.glsl
+++ /dev/null
@@ -1,64 +0,0 @@
-/**
- * @file attachmentAlphaMaskShadowF.glsl
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2005, 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$
- */
-
-#ifdef DEFINE_GL_FRAGCOLOR
-out vec4 frag_color;
-#else
-#define frag_color gl_FragColor
-#endif
-
-uniform float minimum_alpha;
-
-uniform sampler2D diffuseMap;
-
-VARYING vec4 post_pos;
-VARYING vec2 vary_texcoord0;
-VARYING float pos_w;
-VARYING float target_pos_x;
-VARYING vec4 vertex_color;
-
-void main()
-{
- float alpha = texture2D(diffuseMap, vary_texcoord0.xy).a;
-
- if (alpha < 0.05) // treat as totally transparent
- {
- discard;
- }
-
- if (alpha < minimum_alpha) // treat as semi-transparent
- {
- //if (fract(0.5*floor(target_pos_x / pos_w )) < 0.25)
- {
- discard;
- }
- }
-
- frag_color = vec4(1,1,1,1);
-
-#if !DEPTH_CLAMP
- gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0);
-#endif
-}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/attachmentAlphaShadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/attachmentAlphaShadowF.glsl
deleted file mode 100644
index b54c580ce9..0000000000
--- a/indra/newview/app_settings/shaders/class1/deferred/attachmentAlphaShadowF.glsl
+++ /dev/null
@@ -1,68 +0,0 @@
-/**
- * @file attachmentAlphaShadowF.glsl
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2005, 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$
- */
-
-#ifdef DEFINE_GL_FRAGCOLOR
-out vec4 frag_color;
-#else
-#define frag_color gl_FragColor
-#endif
-
-uniform float minimum_alpha;
-uniform sampler2D diffuseMap;
-
-VARYING float pos_w;
-VARYING float target_pos_x;
-
-#if !DEPTH_CLAMP
-VARYING vec4 post_pos;
-#endif
-
-VARYING vec2 vary_texcoord0;
-VARYING vec4 vertex_color;
-
-void main()
-{
- float alpha = texture2D(diffuseMap, vary_texcoord0.xy).a * vertex_color.a;
-
- if (alpha < 0.05) // treat as totally transparent
- {
- discard;
- }
-
- if (alpha < minimum_alpha)
- {
- if (fract(0.5*floor(target_pos_x / pos_w )) < 0.25)
- {
- discard;
- }
- }
-
- frag_color = vec4(1,1,1,1);
-
-#if !DEPTH_CLAMP
- gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0);
-#endif
-
-}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/attachmentAlphaShadowV.glsl b/indra/newview/app_settings/shaders/class1/deferred/attachmentAlphaShadowV.glsl
deleted file mode 100644
index 31b93dc36a..0000000000
--- a/indra/newview/app_settings/shaders/class1/deferred/attachmentAlphaShadowV.glsl
+++ /dev/null
@@ -1,74 +0,0 @@
-/**
- * @file attachmentShadowV.glsl
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2007, 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$
- */
-
-uniform mat4 projection_matrix;
-uniform mat4 modelview_matrix;
-uniform mat4 texture_matrix0;
-uniform float shadow_target_width;
-
-ATTRIBUTE vec4 diffuse_color;
-ATTRIBUTE vec3 position;
-ATTRIBUTE vec3 normal;
-ATTRIBUTE vec2 texcoord0;
-
-mat4 getObjectSkinnedTransform();
-void passTextureIndex();
-
-#if !DEPTH_CLAMP
-VARYING vec4 post_pos;
-#endif
-VARYING vec2 vary_texcoord0;
-VARYING float pos_w;
-VARYING float target_pos_x;
-VARYING vec4 vertex_color;
-
-void main()
-{
- //transform vertex
- mat4 mat = getObjectSkinnedTransform();
-
- mat = modelview_matrix * mat;
- vec3 pos = (mat*vec4(position.xyz, 1.0)).xyz;
-
- vec4 p = projection_matrix * vec4(pos, 1.0);
-
- pos_w = p.w;
-
- target_pos_x = 0.5 * (shadow_target_width - 1.0) * pos.x;
-
- vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
-
- vertex_color = diffuse_color;
-
-#if !DEPTH_CLAMP
- p.z = max(p.z, -p.w+0.01);
- post_pos = p;
- gl_Position = p;
-#else
- gl_Position = p;
-#endif
-
- passTextureIndex();
-}
-
diff --git a/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowV.glsl b/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowV.glsl
deleted file mode 100644
index 0fa0edfd67..0000000000
--- a/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowV.glsl
+++ /dev/null
@@ -1,50 +0,0 @@
-/**
- * @file attachmentShadowV.glsl
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2007, 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$
- */
-
-uniform mat4 projection_matrix;
-uniform mat4 modelview_matrix;
-uniform mat4 texture_matrix0;
-
-ATTRIBUTE vec3 position;
-ATTRIBUTE vec2 texcoord0;
-
-mat4 getObjectSkinnedTransform();
-
-void main()
-{
- //transform vertex
- mat4 mat = getObjectSkinnedTransform();
-
- mat = modelview_matrix * mat;
- vec3 pos = (mat*vec4(position.xyz, 1.0)).xyz;
-
-
- vec4 p = projection_matrix * vec4(pos, 1.0);
-#if !defined(DEPTH_CLAMP)
- p.z = max(p.z, -p.w+0.01);
- gl_Position = p;
-#else
- gl_Position = p;
-#endif
-}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaMaskShadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaMaskShadowF.glsl
index b8ce54bcb1..44f67899e4 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaMaskShadowF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaMaskShadowF.glsl
@@ -1,5 +1,5 @@
/**
- * @file treeShadowF.glsl
+ * @file avatarAlphaMaskShadowF.glsl
*
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
@@ -32,10 +32,6 @@ out vec4 frag_color;
uniform float minimum_alpha;
uniform sampler2D diffuseMap;
-#if !DEPTH_CLAMP
-VARYING vec4 post_pos;
-#endif
-
VARYING float target_pos_x;
VARYING float pos_w;
VARYING vec2 vary_texcoord0;
@@ -58,8 +54,4 @@ void main()
}
frag_color = vec4(1,1,1,1);
-
-#if !DEPTH_CLAMP
- gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0);
-#endif
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaNoColorV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaNoColorV.glsl
deleted file mode 100644
index bbdc8fdd1c..0000000000
--- a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaNoColorV.glsl
+++ /dev/null
@@ -1,112 +0,0 @@
-/**
- * @file avatarAlphaNoColorV.glsl
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2007, 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$
- */
-
-uniform mat4 projection_matrix;
-
-ATTRIBUTE vec3 position;
-ATTRIBUTE vec3 normal;
-ATTRIBUTE vec2 texcoord0;
-
-mat4 getSkinnedTransform();
-void calcAtmospherics(vec3 inPositionEye);
-
-float calcDirectionalLight(vec3 n, vec3 l);
-
-vec3 atmosAmbient();
-vec3 atmosAffectDirectionalLight(float lightIntensity);
-
-VARYING vec3 vary_position;
-VARYING vec3 vary_ambient;
-VARYING vec3 vary_directional;
-VARYING vec3 vary_fragcoord;
-VARYING vec3 vary_pointlight_col;
-VARYING vec2 vary_texcoord0;
-VARYING vec3 vary_norm;
-
-
-uniform float near_clip;
-
-uniform vec4 color;
-
-uniform vec4 light_position[8];
-uniform vec3 light_direction[8];
-uniform vec3 light_attenuation[8];
-uniform vec3 light_diffuse[8];
-
-float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight);
-
-void main()
-{
- vary_texcoord0 = texcoord0;
-
- vec4 pos;
- vec3 norm;
-
- mat4 trans = getSkinnedTransform();
- vec4 pos_in = vec4(position.xyz, 1.0);
- pos.x = dot(trans[0], pos_in);
- pos.y = dot(trans[1], pos_in);
- pos.z = dot(trans[2], pos_in);
- pos.w = 1.0;
-
- norm.x = dot(trans[0].xyz, normal);
- norm.y = dot(trans[1].xyz, normal);
- norm.z = dot(trans[2].xyz, normal);
- norm = normalize(norm);
- vary_norm = norm;
-
- vec4 frag_pos = projection_matrix * pos;
- gl_Position = frag_pos;
-
- vary_position = pos.xyz;
-
- calcAtmospherics(pos.xyz);
-
- vec4 col = vec4(0.0, 0.0, 0.0, 1.0);
-
- // Collect normal lights
- col.rgb += light_diffuse[2].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[2], light_direction[2], light_attenuation[2].x, light_attenuation[2].y, light_attenuation[2].z);
- col.rgb += light_diffuse[3].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[3], light_direction[3], light_attenuation[3].x, light_attenuation[3].y, light_attenuation[3].z);
- col.rgb += light_diffuse[4].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[4], light_direction[4], light_attenuation[4].x, light_attenuation[4].y, light_attenuation[4].z);
- col.rgb += light_diffuse[5].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[5], light_direction[5], light_attenuation[5].x, light_attenuation[5].y, light_attenuation[5].z);
- col.rgb += light_diffuse[6].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[6], light_direction[6], light_attenuation[6].x, light_attenuation[6].y, light_attenuation[6].z);
- col.rgb += light_diffuse[7].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[7], light_direction[7], light_attenuation[7].x, light_attenuation[7].y, light_attenuation[7].z);
-
- vary_pointlight_col = col.rgb*color.rgb;
-
- col.rgb = vec3(0,0,0);
-
- // Add windlight lights
- col.rgb = atmosAmbient();
-
- vary_ambient = col.rgb*color.rgb;
- vary_directional = color.rgb*atmosAffectDirectionalLight(max(calcDirectionalLight(norm, light_position[0].xyz), 0.0));
-
- col.rgb = col.rgb * color.rgb;
-
- vary_fragcoord.xyz = frag_pos.xyz + vec3(0,0,near_clip);
-}
-
-
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowF.glsl
index 1b16e4eb09..9a0024ede9 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowF.glsl
@@ -33,10 +33,6 @@ uniform float minimum_alpha;
uniform sampler2D diffuseMap;
-#if !DEPTH_CLAMP
-VARYING vec4 post_pos;
-#endif
-
VARYING float pos_w;
VARYING float target_pos_x;
VARYING vec2 vary_texcoord0;
@@ -60,9 +56,4 @@ void main()
}
frag_color = vec4(1,1,1,1);
-
-#if !DEPTH_CLAMP
- gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0);
-#endif
-
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowV.glsl
index 1c5b142ebd..dfe7077db5 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowV.glsl
@@ -1,5 +1,5 @@
/**
- * @file avatarShadowV.glsl
+ * @file avatarAlphaShadowV.glsl
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
@@ -34,9 +34,6 @@ ATTRIBUTE vec3 position;
ATTRIBUTE vec3 normal;
ATTRIBUTE vec2 texcoord0;
-#if !DEPTH_CLAMP
-VARYING vec4 post_pos;
-#endif
VARYING float pos_w;
VARYING float target_pos_x;
VARYING vec2 vary_texcoord0;
@@ -66,13 +63,7 @@ void main()
vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
-#if !DEPTH_CLAMP
- post_pos = pos;
-
- gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
-#else
gl_Position = pos;
-#endif
passTextureIndex();
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl
index 60d83cc623..22b3bd1463 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl
@@ -52,6 +52,6 @@ void main()
frag_data[0] = vec4(diff.rgb, 0.0);
frag_data[1] = vec4(0,0,0,0);
vec3 nvn = normalize(vary_normal);
- frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, 0.0);
+ frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, GBUFFER_FLAG_HAS_ATMOS);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl
index 50020a50d8..0c386ade6c 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl
@@ -25,24 +25,12 @@
/*[EXTRA_CODE_HERE]*/
-#ifdef DEFINE_GL_FRAGCOLOR
out vec4 frag_color;
-#else
-#define frag_color gl_FragColor
-#endif
uniform sampler2D diffuseMap;
-#if !defined(DEPTH_CLAMP)
-VARYING vec4 post_pos;
-#endif
-
void main()
{
frag_color = vec4(1,1,1,1);
-
-#if !defined(DEPTH_CLAMP)
- gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0);
-#endif
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl
index 91b25613e0..ac8a483a6a 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl
@@ -31,10 +31,6 @@ ATTRIBUTE vec3 position;
ATTRIBUTE vec3 normal;
ATTRIBUTE vec2 texcoord0;
-#if !defined(DEPTH_CLAMP)
-VARYING vec4 post_pos;
-#endif
-
void main()
{
vec4 pos;
@@ -53,13 +49,7 @@ void main()
norm = normalize(norm);
pos = projection_matrix * pos;
-#if !defined(DEPTH_CLAMP)
- post_pos = pos;
-
- gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
-#else
gl_Position = pos;
-#endif
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl
index 596d0274af..93a85cad40 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl
@@ -33,12 +33,13 @@ out vec4 frag_color;
#define frag_color gl_FragColor
#endif
-uniform sampler2DRect normalMap;
-uniform sampler2DRect lightMap;
+uniform sampler2D normalMap;
+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 = texture2DRect(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,41 +65,55 @@ 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 );
- for (int i = 1; i < 4; i++)
+ // TODO: move this to kern instead of building kernel per pixel
+ vec3 k[7];
+ k[0] = kern[0];
+ k[2] = kern[1];
+ k[4] = kern[2];
+ k[6] = kern[3];
+
+ k[1] = (k[0]+k[2])*0.5f;
+ k[3] = (k[2]+k[4])*0.5f;
+ k[5] = (k[4]+k[6])*0.5f;
+
+ for (int i = 1; i < 7; i++)
{
- vec2 samptc = tc + kern[i].z*dlt;
+ 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 += texture2DRect(lightMap, samptc)*kern[i].xyxx;
- defined_weight += kern[i].xy;
+ col += texture(lightMap, samptc)*k[i].xyxx;
+ defined_weight += k[i].xy;
}
}
- for (int i = 1; i < 4; i++)
+ for (int i = 1; i < 7; i++)
{
- vec2 samptc = tc - kern[i].z*dlt;
+ 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 += texture2DRect(lightMap, samptc)*kern[i].xyxx;
- defined_weight += kern[i].xy;
+ col += texture(lightMap, samptc)*k[i].xyxx;
+ defined_weight += k[i].xy;
}
}
col /= defined_weight.xyxx;
- col.y *= col.y;
+ //col.y *= col.y;
frag_color = col;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/blurLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/blurLightV.glsl
index 212f7e56ad..5e0f01981b 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/blurLightV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/blurLightV.glsl
@@ -23,8 +23,6 @@
* $/LicenseInfo$
*/
-uniform mat4 modelview_projection_matrix;
-
ATTRIBUTE vec3 position;
VARYING vec2 vary_fragcoord;
@@ -33,7 +31,7 @@ uniform vec2 screen_res;
void main()
{
//transform vertex
- vec4 pos = modelview_projection_matrix * vec4(position.xyz, 1.0);
+ vec4 pos = vec4(position.xyz, 1.0);
gl_Position = pos;
- vary_fragcoord = (pos.xy*0.5+0.5)*screen_res;
+ vary_fragcoord = (pos.xy*0.5+0.5);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl
index b5677a07ee..749ec3a6ac 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl
@@ -64,5 +64,5 @@ void main()
frag_data[1] = vertex_color.aaaa; // spec
//frag_data[1] = vec4(vec3(vertex_color.a), vertex_color.a+(1.0-vertex_color.a)*vertex_color.a); // spec - from former class3 - maybe better, but not so well tested
vec3 nvn = normalize(tnorm);
- frag_data[2] = vec4(encode_normal(nvn), vertex_color.a, 0.0);
+ frag_data[2] = vec4(encode_normal(nvn), vertex_color.a, GBUFFER_FLAG_HAS_ATMOS);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/cloudShadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/cloudShadowF.glsl
deleted file mode 100644
index 0157d166e0..0000000000
--- a/indra/newview/app_settings/shaders/class1/deferred/cloudShadowF.glsl
+++ /dev/null
@@ -1,127 +0,0 @@
-/**
- * @file class3/deferred/cloudsF.glsl
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2005, 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$
- */
-
-#ifdef DEFINE_GL_FRAGCOLOR
-out vec4 frag_color;
-#else
-#define frag_color gl_FragColor
-#endif
-
-uniform sampler2D diffuseMap;
-
-VARYING vec4 pos;
-VARYING float target_pos_x;
-VARYING float vary_CloudDensity;
-VARYING vec2 vary_texcoord0;
-VARYING vec2 vary_texcoord1;
-VARYING vec2 vary_texcoord2;
-VARYING vec2 vary_texcoord3;
-
-uniform sampler2D cloud_noise_texture;
-uniform sampler2D cloud_noise_texture_next;
-uniform float blend_factor;
-uniform vec4 cloud_pos_density1;
-uniform vec4 cloud_pos_density2;
-uniform vec4 sunlight_color;
-uniform vec4 cloud_color;
-uniform float cloud_shadow;
-uniform float cloud_scale;
-uniform float cloud_variance;
-uniform vec3 camPosLocal;
-uniform vec3 sun_dir;
-uniform float sun_size;
-uniform float far_z;
-
-#if !defined(DEPTH_CLAMP)
-VARYING vec4 post_pos;
-#endif
-
-vec4 cloudNoise(vec2 uv)
-{
- vec4 a = texture2D(cloud_noise_texture, uv);
- vec4 b = texture2D(cloud_noise_texture_next, uv);
- vec4 cloud_noise_sample = mix(a, b, blend_factor);
- return normalize(cloud_noise_sample);
-}
-
-void main()
-{
- // Set variables
- vec2 uv1 = vary_texcoord0.xy;
- vec2 uv2 = vary_texcoord1.xy;
- vec2 uv3 = vary_texcoord2.xy;
- float cloudDensity = 2.0 * (cloud_shadow - 0.25);
-
- if (cloud_scale >= 0.0001)
- {
- vec2 uv4 = vary_texcoord3.xy;
-
- vec2 disturbance = vec2(cloudNoise(uv1 / 8.0f).x, cloudNoise((uv3 + uv1) / 16.0f).x) * cloud_variance * (1.0f - cloud_scale * 0.25f);
- vec2 disturbance2 = vec2(cloudNoise((uv1 + uv3) / 4.0f).x, cloudNoise((uv4 + uv2) / 8.0f).x) * cloud_variance * (1.0f - cloud_scale * 0.25f);
-
- // Offset texture coords
- uv1 += cloud_pos_density1.xy + (disturbance * 0.2); //large texture, visible density
- uv2 += cloud_pos_density1.xy; //large texture, self shadow
- uv3 += cloud_pos_density2.xy; //small texture, visible density
- uv4 += cloud_pos_density2.xy; //small texture, self shadow
-
- float density_variance = min(1.0, (disturbance.x* 2.0 + disturbance.y* 2.0 + disturbance2.x + disturbance2.y) * 4.0);
-
- cloudDensity *= 1.0 - (density_variance * density_variance);
-
- // Compute alpha1, the main cloud opacity
- float alpha1 = (cloudNoise(uv1).x - 0.5) + (cloudNoise(uv3).x - 0.5) * cloud_pos_density2.z;
- alpha1 = min(max(alpha1 + cloudDensity, 0.) * 10 * cloud_pos_density1.z, 1.);
-
- // And smooth
- alpha1 = 1. - alpha1 * alpha1;
- alpha1 = 1. - alpha1 * alpha1;
-
- if (alpha1 < 0.001f)
- {
- discard;
- }
-
- // Compute alpha2, for self shadowing effect
- // (1 - alpha2) will later be used as percentage of incoming sunlight
- float alpha2 = (cloudNoise(uv2).x - 0.5);
- alpha2 = min(max(alpha2 + cloudDensity, 0.) * 2.5 * cloud_pos_density1.z, 1.);
-
- // And smooth
- alpha2 = 1. - alpha2;
- alpha2 = 1. - alpha2 * alpha2;
-
- frag_color = vec4(alpha1, alpha1, alpha1, 1);
- }
- else
- {
- frag_color = vec4(1);
- }
-
-#if !defined(DEPTH_CLAMP)
- gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0);
-#endif
-
-}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/cloudShadowV.glsl b/indra/newview/app_settings/shaders/class1/deferred/cloudShadowV.glsl
deleted file mode 100644
index effb070f93..0000000000
--- a/indra/newview/app_settings/shaders/class1/deferred/cloudShadowV.glsl
+++ /dev/null
@@ -1,63 +0,0 @@
-/**
- * @file cloudShadowV.glsl
- *
- * $LicenseInfo:firstyear=2011&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2011, 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$
- */
-
-uniform mat4 texture_matrix0;
-uniform mat4 modelview_projection_matrix;
-uniform float shadow_target_width;
-
-ATTRIBUTE vec3 position;
-ATTRIBUTE vec4 diffuse_color;
-ATTRIBUTE vec2 texcoord0;
-
-#if !defined(DEPTH_CLAMP)
-VARYING float pos_zd2;
-#endif
-
-VARYING vec4 pos;
-VARYING float target_pos_x;
-VARYING vec2 vary_texcoord0;
-VARYING vec4 vertex_color;
-
-void passTextureIndex();
-
-void main()
-{
- //transform vertex
- vec4 pre_pos = vec4(position.xyz, 1.0);
- pos = modelview_projection_matrix * pre_pos;
- target_pos_x = 0.5 * (shadow_target_width - 1.0) * pos.x;
-
-#if !defined(DEPTH_CLAMP)
- pos_zd2 = pos.z * 0.5;
- gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
-#else
- gl_Position = pos;
-#endif
-
- passTextureIndex();
-
- vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
- vertex_color = diffuse_color;
-}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl b/indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl
index ae1ac5de7f..b45dfcd550 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl
@@ -34,15 +34,15 @@ out vec4 frag_data[3];
// The fragment shader for the sky
/////////////////////////////////////////////////////////////////////////
-VARYING vec4 vary_CloudColorSun;
-VARYING vec4 vary_CloudColorAmbient;
+VARYING vec3 vary_CloudColorSun;
+VARYING vec3 vary_CloudColorAmbient;
VARYING float vary_CloudDensity;
uniform sampler2D cloud_noise_texture;
uniform sampler2D cloud_noise_texture_next;
uniform float blend_factor;
-uniform vec4 cloud_pos_density1;
-uniform vec4 cloud_pos_density2;
+uniform vec3 cloud_pos_density1;
+uniform vec3 cloud_pos_density2;
uniform float cloud_scale;
uniform float cloud_variance;
@@ -69,8 +69,8 @@ void main()
vec2 uv1 = vary_texcoord0.xy;
vec2 uv2 = vary_texcoord1.xy;
- vec4 cloudColorSun = vary_CloudColorSun;
- vec4 cloudColorAmbient = vary_CloudColorAmbient;
+ vec3 cloudColorSun = vary_CloudColorSun;
+ vec3 cloudColorAmbient = vary_CloudColorAmbient;
float cloudDensity = vary_CloudDensity;
vec2 uv3 = vary_texcoord2.xy;
vec2 uv4 = vary_texcoord3.xy;
@@ -115,7 +115,7 @@ void main()
alpha2 = 1. - alpha2 * alpha2;
// Combine
- vec4 color;
+ vec3 color;
color = (cloudColorSun*(1.-alpha2) + cloudColorAmbient);
color.rgb= max(vec3(0), color.rgb);
color.rgb *= 2.0;
@@ -124,8 +124,8 @@ void main()
/// Gamma correct for WL (soft clip effect).
frag_data[0] = vec4(color.rgb, alpha1);
frag_data[1] = vec4(0.0,0.0,0.0,0.0);
- frag_data[2] = vec4(0,0,0,1);
+ frag_data[2] = vec4(0,0,0,GBUFFER_FLAG_SKIP_ATMOS);
- gl_FragDepth = 0.99995f;
+ gl_FragDepth = LL_SHADER_CONST_CLOUD_MOON_DEPTH; // SL-14113 Stars and Clouds need same depth
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl b/indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl
index 8e0a001403..5ca210863e 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl
@@ -33,8 +33,8 @@ ATTRIBUTE vec2 texcoord0;
///////////////////////////////////////////////////////////////////////////////
// Output parameters
-VARYING vec4 vary_CloudColorSun;
-VARYING vec4 vary_CloudColorAmbient;
+VARYING vec3 vary_CloudColorSun;
+VARYING vec3 vary_CloudColorAmbient;
VARYING float vary_CloudDensity;
VARYING vec2 vary_texcoord0;
@@ -46,13 +46,13 @@ VARYING float altitude_blend_factor;
// Inputs
uniform vec3 camPosLocal;
-uniform vec4 lightnorm;
-uniform vec4 sunlight_color;
-uniform vec4 moonlight_color;
+uniform vec3 lightnorm;
+uniform vec3 sunlight_color;
+uniform vec3 moonlight_color;
uniform int sun_up_factor;
-uniform vec4 ambient_color;
-uniform vec4 blue_horizon;
-uniform vec4 blue_density;
+uniform vec3 ambient_color;
+uniform vec3 blue_horizon;
+uniform vec3 blue_density;
uniform float haze_horizon;
uniform float haze_density;
@@ -60,10 +60,10 @@ uniform float cloud_shadow;
uniform float density_multiplier;
uniform float max_y;
-uniform vec4 glow;
+uniform vec3 glow;
uniform float sun_moon_glow_factor;
-uniform vec4 cloud_color;
+uniform vec3 cloud_color;
uniform float cloud_scale;
@@ -114,17 +114,17 @@ void main()
float rel_pos_len = length(rel_pos);
// Initialize temp variables
- vec4 sunlight = sunlight_color;
- vec4 light_atten;
+ vec3 sunlight = sunlight_color;
+ vec3 light_atten;
// Sunlight attenuation effect (hue and brightness) due to atmosphere
// this is used later for sunlight modulation at various altitudes
- light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y);
+ light_atten = (blue_density + vec3(haze_density * 0.25)) * (density_multiplier * max_y);
// Calculate relative weights
- vec4 combined_haze = abs(blue_density) + vec4(abs(haze_density));
- vec4 blue_weight = blue_density / combined_haze;
- vec4 haze_weight = haze_density / combined_haze;
+ vec3 combined_haze = abs(blue_density) + vec3(abs(haze_density));
+ vec3 blue_weight = blue_density / combined_haze;
+ vec3 haze_weight = haze_density / combined_haze;
// Compute sunlight from rel_pos & lightnorm (for long rays like sky)
float off_axis = 1.0 / max(1e-6, max(0., rel_pos_norm.y) + lightnorm.y);
@@ -155,14 +155,14 @@ void main()
haze_glow = (sun_moon_glow_factor < 1.0) ? 0.0 : (haze_glow + 0.25);
// Increase ambient when there are more clouds
- vec4 tmpAmbient = ambient_color;
+ vec3 tmpAmbient = ambient_color;
tmpAmbient += (1. - tmpAmbient) * cloud_shadow * 0.5;
// Dim sunlight by cloud shadow percentage
sunlight *= (1. - cloud_shadow);
// Haze color below cloud
- vec4 additiveColorBelowCloud =
+ vec3 additiveColorBelowCloud =
(blue_horizon * blue_weight * (sunlight + tmpAmbient) + (haze_horizon * haze_weight) * (sunlight * haze_glow + tmpAmbient));
// CLOUDS
@@ -178,7 +178,7 @@ void main()
combined_haze = sqrt(combined_haze); // less atmos opacity (more transparency) below clouds
vary_CloudColorSun *= combined_haze;
vary_CloudColorAmbient *= combined_haze;
- vec4 oHazeColorBelowCloud = additiveColorBelowCloud * (1. - combined_haze);
+ vec3 oHazeColorBelowCloud = additiveColorBelowCloud * (1. - combined_haze);
// Make a nice cloud density based on the cloud_shadow value that was passed in.
vary_CloudDensity = 2. * (cloud_shadow - 0.25);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/cofF.glsl b/indra/newview/app_settings/shaders/class1/deferred/cofF.glsl
index 079d8458c9..1e640d95ae 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/cofF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/cofF.glsl
@@ -33,8 +33,8 @@ out vec4 frag_color;
#define frag_color gl_FragColor
#endif
-uniform sampler2DRect diffuseRect;
-uniform sampler2DRect depthMap;
+uniform sampler2D diffuseRect;
+uniform sampler2D depthMap;
uniform sampler2D bloomMap;
uniform float depth_cutoff;
@@ -69,19 +69,19 @@ void main()
{
vec2 tc = vary_fragcoord.xy;
- float z = texture2DRect(depthMap, tc).r;
+ float z = texture2D(depthMap, tc).r;
z = z*2.0-1.0;
vec4 ndc = vec4(0.0, 0.0, z, 1.0);
vec4 p = inv_proj*ndc;
float depth = p.z/p.w;
- vec4 diff = texture2DRect(diffuseRect, vary_fragcoord.xy);
+ vec4 diff = texture2D(diffuseRect, vary_fragcoord.xy);
float sc = calc_cof(depth);
sc = min(sc, max_cof);
sc = max(sc, -max_cof);
- vec4 bloom = texture2D(bloomMap, vary_fragcoord.xy/screen_res);
+ vec4 bloom = texture2D(bloomMap, vary_fragcoord.xy);
frag_color.rgb = diff.rgb + bloom.rgb;
frag_color.a = sc/max_cof*0.5+0.5;
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl b/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl
index e27bbce094..c87e754eca 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl
@@ -23,25 +23,129 @@
* $/LicenseInfo$
*/
-uniform sampler2DRect normalMap;
-uniform sampler2DRect depthMap;
+
+/* Parts of this file are taken from Sascha Willem's Vulkan GLTF refernce implementation
+MIT License
+
+Copyright (c) 2018 Sascha Willems
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+uniform sampler2D normalMap;
+uniform sampler2D depthMap;
+uniform sampler2D projectionMap; // rgba
+uniform sampler2D brdfLut;
+
+// projected lighted params
+uniform mat4 proj_mat; //screen space to light space projector
+uniform vec3 proj_n; // projector normal
+uniform vec3 proj_p; //plane projection is emitting from (in screen space)
+uniform float proj_focus; // distance from plane to begin blurring
+uniform float proj_lod ; // (number of mips in proj map)
+uniform float proj_range; // range between near clip and far clip plane of projection
+uniform float proj_ambiance;
+
+// light params
+uniform vec3 color; // light_color
+uniform float size; // light_size
uniform mat4 inv_proj;
uniform vec2 screen_res;
-vec2 getScreenCoordinate(vec2 screenpos)
+const float M_PI = 3.14159265;
+const float ONE_OVER_PI = 0.3183098861;
+
+vec3 srgb_to_linear(vec3 cs);
+vec3 atmosFragLightingLinear(vec3 light, vec3 additive, vec3 atten);
+vec3 scaleSoftClipFragLinear(vec3 light);
+
+float calcLegacyDistanceAttenuation(float distance, float falloff)
{
- vec2 sc = screenpos.xy * 2.0;
- if (screen_res.x > 0 && screen_res.y > 0)
+ float dist_atten = 1.0 - clamp((distance + falloff)/(1.0 + falloff), 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;
+ return dist_atten;
+}
+
+// In:
+// lv unnormalized surface to light vector
+// n normal of the surface
+// pos unnormalized camera to surface vector
+// Out:
+// l normalized surace to light vector
+// nl diffuse angle
+// nh specular angle
+void calcHalfVectors(vec3 lv, vec3 n, vec3 v,
+ out vec3 h, out vec3 l, out float nh, out float nl, out float nv, out float vh, out float lightDist)
+{
+ l = normalize(lv);
+ h = normalize(l + v);
+ nh = clamp(dot(n, h), 0.0, 1.0);
+ nl = clamp(dot(n, l), 0.0, 1.0);
+ nv = clamp(dot(n, v), 0.0, 1.0);
+ vh = clamp(dot(v, h), 0.0, 1.0);
+
+ lightDist = length(lv);
+}
+
+// In:
+// light_center
+// pos
+// Out:
+// dist
+// l_dist
+// lv
+// proj_tc Projector Textue Coordinates
+bool clipProjectedLightVars(vec3 light_center, vec3 pos, out float dist, out float l_dist, out vec3 lv, out vec4 proj_tc )
+{
+ lv = light_center - pos.xyz;
+ dist = length(lv);
+ bool clipped = (dist >= size);
+ if ( !clipped )
{
- sc /= screen_res;
+ dist /= size;
+
+ l_dist = -dot(lv, proj_n);
+ vec4 projected_point = (proj_mat * vec4(pos.xyz, 1.0));
+ clipped = (projected_point.z < 0.0);
+ projected_point.xyz /= projected_point.w;
+ proj_tc = projected_point;
}
+
+ return clipped;
+}
+
+vec2 getScreenCoordinate(vec2 screenpos)
+{
+ vec2 sc = screenpos.xy * 2.0;
return sc - vec2(1.0, 1.0);
}
+// See: https://aras-p.info/texts/CompactNormalStorage.html
+// Method #4: Spheremap Transform, Lambert Azimuthal Equal-Area projection
vec3 getNorm(vec2 screenpos)
{
- vec2 enc = texture2DRect(normalMap, screenpos.xy).xy;
+ vec2 enc = texture2D(normalMap, screenpos.xy).xy;
vec2 fenc = enc*4-2;
float f = dot(fenc,fenc);
float g = sqrt(1-f/4);
@@ -51,12 +155,160 @@ vec3 getNorm(vec2 screenpos)
return n;
}
+vec3 getNormalFromPacked(vec4 packedNormalEnvIntensityFlags)
+{
+ vec2 enc = packedNormalEnvIntensityFlags.xy;
+ vec2 fenc = enc*4-2;
+ float f = dot(fenc,fenc);
+ float g = sqrt(1-f/4);
+ vec3 n;
+ n.xy = fenc*g;
+ n.z = 1-f/2;
+ return normalize(n); // TODO: Is this normalize redundant?
+}
+
+// return packedNormalEnvIntensityFlags since GBUFFER_FLAG_HAS_PBR needs .w
+// See: C++: addDeferredAttachments(), GLSL: softenLightF
+vec4 getNormalEnvIntensityFlags(vec2 screenpos, out vec3 n, out float envIntensity)
+{
+ vec4 packedNormalEnvIntensityFlags = texture2D(normalMap, screenpos.xy);
+ n = getNormalFromPacked( packedNormalEnvIntensityFlags );
+ envIntensity = packedNormalEnvIntensityFlags.z;
+ return packedNormalEnvIntensityFlags;
+}
+
+// get linear depth value given a depth buffer sample d and znear and zfar values
+float linearDepth(float d, float znear, float zfar)
+{
+ d = d * 2.0 - 1.0;
+ return znear * 2.0 * zfar / (zfar + znear - d * (zfar - znear));
+}
+
+float linearDepth01(float d, float znear, float zfar)
+{
+ return linearDepth(d, znear, zfar) / zfar;
+}
+
float getDepth(vec2 pos_screen)
{
- float depth = texture2DRect(depthMap, pos_screen).r;
+ float depth = texture2D(depthMap, pos_screen).r;
return depth;
}
+vec4 getTexture2DLodAmbient(vec2 tc, float lod)
+{
+#ifndef FXAA_GLSL_120
+ vec4 ret = textureLod(projectionMap, tc, lod);
+#else
+ vec4 ret = texture2D(projectionMap, tc);
+#endif
+ ret.rgb = srgb_to_linear(ret.rgb);
+
+ vec2 dist = tc-vec2(0.5);
+ float d = dot(dist,dist);
+ ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0), 1.0);
+
+ return ret;
+}
+
+vec4 getTexture2DLodDiffuse(vec2 tc, float lod)
+{
+#ifndef FXAA_GLSL_120
+ vec4 ret = textureLod(projectionMap, tc, lod);
+#else
+ vec4 ret = texture2D(projectionMap, tc);
+#endif
+ ret.rgb = srgb_to_linear(ret.rgb);
+
+ vec2 dist = vec2(0.5) - abs(tc-vec2(0.5));
+ float det = min(lod/(proj_lod*0.5), 1.0);
+ float d = min(dist.x, dist.y);
+ float edge = 0.25*det;
+ ret *= clamp(d/edge, 0.0, 1.0);
+
+ return ret;
+}
+
+// lit This is set by the caller: if (nl > 0.0) { lit = attenuation * nl * noise; }
+// Uses:
+// color Projected spotlight color
+vec3 getProjectedLightAmbiance(float amb_da, float attenuation, float lit, float nl, float noise, vec2 projected_uv)
+{
+ vec4 amb_plcol = getTexture2DLodAmbient(projected_uv, proj_lod);
+ vec3 amb_rgb = amb_plcol.rgb * amb_plcol.a;
+
+ amb_da += proj_ambiance;
+ amb_da += (nl*nl*0.5+0.5) * proj_ambiance;
+ amb_da *= attenuation * noise;
+ amb_da = min(amb_da, 1.0-lit);
+
+ return (amb_da * color.rgb * amb_rgb);
+}
+
+// Returns projected light in Linear
+// Uses global spotlight color:
+// color
+// NOTE: projected.a will be pre-multiplied with projected.rgb
+vec3 getProjectedLightDiffuseColor(float light_distance, vec2 projected_uv)
+{
+ float diff = clamp((light_distance - proj_focus)/proj_range, 0.0, 1.0);
+ float lod = diff * proj_lod;
+ vec4 plcol = getTexture2DLodDiffuse(projected_uv.xy, lod);
+
+ return color.rgb * plcol.rgb * plcol.a;
+}
+
+vec4 texture2DLodSpecular(vec2 tc, float lod)
+{
+#ifndef FXAA_GLSL_120
+ vec4 ret = textureLod(projectionMap, tc, lod);
+#else
+ vec4 ret = texture2D(projectionMap, tc);
+#endif
+ ret.rgb = srgb_to_linear(ret.rgb);
+
+ vec2 dist = vec2(0.5) - abs(tc-vec2(0.5));
+ float det = min(lod/(proj_lod*0.5), 1.0);
+ float d = min(dist.x, dist.y);
+ d *= min(1, d * (proj_lod - lod)); // BUG? extra factor compared to diffuse causes N repeats
+ float edge = 0.25*det;
+ ret *= clamp(d/edge, 0.0, 1.0);
+
+ return ret;
+}
+
+// See: clipProjectedLightVars()
+vec3 getProjectedLightSpecularColor(vec3 pos, vec3 n )
+{
+ vec3 slit = vec3(0);
+ vec3 ref = reflect(normalize(pos), n);
+
+ //project from point pos in direction ref to plane proj_p, proj_n
+ vec3 pdelta = proj_p-pos;
+ float l_dist = length(pdelta);
+ float ds = dot(ref, proj_n);
+ if (ds < 0.0)
+ {
+ vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds;
+ vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0));
+ if (stc.z > 0.0)
+ {
+ stc /= stc.w;
+ slit = getProjectedLightDiffuseColor( l_dist, stc.xy ); // NOTE: Using diffuse due to texture2DLodSpecular() has extra: d *= min(1, d * (proj_lod - lod));
+ }
+ }
+ return slit; // specular light
+}
+
+vec3 getProjectedLightSpecularColor(float light_distance, vec2 projected_uv)
+{
+ float diff = clamp((light_distance - proj_focus)/proj_range, 0.0, 1.0);
+ float lod = diff * proj_lod;
+ vec4 plcol = getTexture2DLodDiffuse(projected_uv.xy, lod); // NOTE: Using diffuse due to texture2DLodSpecular() has extra: d *= min(1, d * (proj_lod - lod));
+
+ return color.rgb * plcol.rgb * plcol.a;
+}
+
vec4 getPosition(vec2 pos_screen)
{
float depth = getDepth(pos_screen);
@@ -68,12 +320,249 @@ vec4 getPosition(vec2 pos_screen)
return pos;
}
+// get position given a normalized device coordinate
+vec3 getPositionWithNDC(vec3 ndc)
+{
+ vec4 pos = inv_proj * vec4(ndc, 1.0);
+ return pos.xyz / pos.w;
+}
+
vec4 getPositionWithDepth(vec2 pos_screen, float depth)
{
vec2 sc = getScreenCoordinate(pos_screen);
- vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
- vec4 pos = inv_proj * ndc;
- pos /= pos.w;
- pos.w = 1.0;
- return pos;
+ vec3 ndc = vec3(sc.x, sc.y, 2.0*depth-1.0);
+ return vec4(getPositionWithNDC(ndc), 1.0);
+}
+
+vec2 getScreenCoord(vec4 clip)
+{
+ vec4 ndc = clip;
+ ndc.xyz /= clip.w;
+ vec2 screen = vec2( ndc.xy * 0.5 );
+ screen += 0.5;
+ return screen;
+}
+
+vec2 getScreenXY(vec4 clip)
+{
+ vec4 ndc = clip;
+ ndc.xyz /= clip.w;
+ vec2 screen = vec2( ndc.xy * 0.5 );
+ screen += 0.5;
+ screen *= screen_res;
+ return screen;
+}
+
+// Color utils
+
+vec3 colorize_dot(float x)
+{
+ if (x > 0.0) return vec3( 0, x, 0 );
+ if (x < 0.0) return vec3(-x, 0, 0 );
+ return vec3( 0, 0, 1 );
+}
+
+vec3 hue_to_rgb(float hue)
+{
+ if (hue > 1.0) return vec3(0.5);
+ vec3 rgb = abs(hue * 6. - vec3(3, 2, 4)) * vec3(1, -1, -1) + vec3(-1, 2, 2);
+ return clamp(rgb, 0.0, 1.0);
+}
+
+// PBR Utils
+
+vec2 BRDF(float NoV, float roughness)
+{
+ return texture(brdfLut, vec2(NoV, roughness)).rg;
+}
+
+// set colorDiffuse and colorSpec to the results of GLTF PBR style IBL
+vec3 pbrIbl(vec3 diffuseColor,
+ vec3 specularColor,
+ vec3 radiance, // radiance map sample
+ vec3 irradiance, // irradiance map sample
+ float ao, // ambient occlusion factor
+ float nv, // normal dot view vector
+ float perceptualRough)
+{
+ // retrieve a scale and bias to F0. See [1], Figure 3
+ vec2 brdf = BRDF(clamp(nv, 0, 1), 1.0-perceptualRough);
+ vec3 diffuseLight = irradiance;
+ vec3 specularLight = radiance;
+
+ vec3 diffuse = diffuseLight * diffuseColor;
+ vec3 specular = specularLight * (specularColor * brdf.x + brdf.y);
+
+ return (diffuse + specular*0.5) * ao; //reduce by half to place in appropriate color space for atmospherics
+}
+
+// Encapsulate the various inputs used by the various functions in the shading equation
+// We store values in this struct to simplify the integration of alternative implementations
+// of the shading terms, outlined in the Readme.MD Appendix.
+struct PBRInfo
+{
+ float NdotL; // cos angle between normal and light direction
+ float NdotV; // cos angle between normal and view direction
+ float NdotH; // cos angle between normal and half vector
+ float LdotH; // cos angle between light direction and half vector
+ float VdotH; // cos angle between view direction and half vector
+ float perceptualRoughness; // roughness value, as authored by the model creator (input to shader)
+ float metalness; // metallic value at the surface
+ vec3 reflectance0; // full reflectance color (normal incidence angle)
+ vec3 reflectance90; // reflectance color at grazing angle
+ float alphaRoughness; // roughness mapped to a more linear change in the roughness (proposed by [2])
+ vec3 diffuseColor; // color contribution from diffuse lighting
+ vec3 specularColor; // color contribution from specular lighting
+};
+
+// Basic Lambertian diffuse
+// Implementation from Lambert's Photometria https://archive.org/details/lambertsphotome00lambgoog
+// See also [1], Equation 1
+vec3 diffuse(PBRInfo pbrInputs)
+{
+ return pbrInputs.diffuseColor / M_PI;
+}
+
+// The following equation models the Fresnel reflectance term of the spec equation (aka F())
+// Implementation of fresnel from [4], Equation 15
+vec3 specularReflection(PBRInfo pbrInputs)
+{
+ return pbrInputs.reflectance0 + (pbrInputs.reflectance90 - pbrInputs.reflectance0) * pow(clamp(1.0 - pbrInputs.VdotH, 0.0, 1.0), 5.0);
}
+
+// This calculates the specular geometric attenuation (aka G()),
+// where rougher material will reflect less light back to the viewer.
+// This implementation is based on [1] Equation 4, and we adopt their modifications to
+// alphaRoughness as input as originally proposed in [2].
+float geometricOcclusion(PBRInfo pbrInputs)
+{
+ float NdotL = pbrInputs.NdotL;
+ float NdotV = pbrInputs.NdotV;
+ float r = pbrInputs.alphaRoughness;
+
+ float attenuationL = 2.0 * NdotL / (NdotL + sqrt(r * r + (1.0 - r * r) * (NdotL * NdotL)));
+ float attenuationV = 2.0 * NdotV / (NdotV + sqrt(r * r + (1.0 - r * r) * (NdotV * NdotV)));
+ return attenuationL * attenuationV;
+}
+
+// The following equation(s) model the distribution of microfacet normals across the area being drawn (aka D())
+// Implementation from "Average Irregularity Representation of a Roughened Surface for Ray Reflection" by T. S. Trowbridge, and K. P. Reitz
+// Follows the distribution function recommended in the SIGGRAPH 2013 course notes from EPIC Games [1], Equation 3.
+float microfacetDistribution(PBRInfo pbrInputs)
+{
+ float roughnessSq = pbrInputs.alphaRoughness * pbrInputs.alphaRoughness;
+ float f = (pbrInputs.NdotH * roughnessSq - pbrInputs.NdotH) * pbrInputs.NdotH + 1.0;
+ return roughnessSq / (M_PI * f * f);
+}
+
+vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor,
+ float perceptualRoughness,
+ float metallic,
+ vec3 n, // normal
+ vec3 v, // surface point to camera
+ vec3 l) //surface point to light
+{
+ // make sure specular highlights from punctual lights don't fall off of polished surfaces
+ perceptualRoughness = max(perceptualRoughness, 8.0/255.0);
+
+ float alphaRoughness = perceptualRoughness * perceptualRoughness;
+
+ // Compute reflectance.
+ float reflectance = max(max(specularColor.r, specularColor.g), specularColor.b);
+
+ // For typical incident reflectance range (between 4% to 100%) set the grazing reflectance to 100% for typical fresnel effect.
+ // For very low reflectance range on highly diffuse objects (below 4%), incrementally reduce grazing reflecance to 0%.
+ float reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0);
+ vec3 specularEnvironmentR0 = specularColor.rgb;
+ vec3 specularEnvironmentR90 = vec3(1.0, 1.0, 1.0) * reflectance90;
+
+ vec3 h = normalize(l+v); // Half vector between both l and v
+ vec3 reflection = -normalize(reflect(v, n));
+ reflection.y *= -1.0f;
+
+ float NdotL = clamp(dot(n, l), 0.001, 1.0);
+ float NdotV = clamp(abs(dot(n, v)), 0.001, 1.0);
+ float NdotH = clamp(dot(n, h), 0.0, 1.0);
+ float LdotH = clamp(dot(l, h), 0.0, 1.0);
+ float VdotH = clamp(dot(v, h), 0.0, 1.0);
+
+ PBRInfo pbrInputs = PBRInfo(
+ NdotL,
+ NdotV,
+ NdotH,
+ LdotH,
+ VdotH,
+ perceptualRoughness,
+ metallic,
+ specularEnvironmentR0,
+ specularEnvironmentR90,
+ alphaRoughness,
+ diffuseColor,
+ specularColor
+ );
+
+ // Calculate the shading terms for the microfacet specular shading model
+ vec3 F = specularReflection(pbrInputs);
+ float G = geometricOcclusion(pbrInputs);
+ float D = microfacetDistribution(pbrInputs);
+
+ const vec3 u_LightColor = vec3(1.0);
+
+ // Calculation of analytical lighting contribution
+ vec3 diffuseContrib = (1.0 - F) * diffuse(pbrInputs);
+ vec3 specContrib = F * G * D / (4.0 * NdotL * NdotV);
+ // Obtain final intensity as reflectance (BRDF) scaled by the energy of the light (cosine law)
+ vec3 color = NdotL * u_LightColor * (diffuseContrib + specContrib);
+
+ return color;
+}
+
+void calcDiffuseSpecular(vec3 baseColor, float metallic, inout vec3 diffuseColor, inout vec3 specularColor)
+{
+ vec3 f0 = vec3(0.04);
+ diffuseColor = baseColor*(vec3(1.0)-f0);
+ diffuseColor *= 1.0 - metallic;
+ specularColor = mix(f0, baseColor, metallic);
+}
+
+vec3 pbrBaseLight(vec3 diffuseColor, vec3 specularColor, float metallic, vec3 v, vec3 norm, float perceptualRoughness, vec3 light_dir, vec3 sunlit, float scol, vec3 radiance, vec3 irradiance, vec3 colorEmissive, float ao, vec3 additive, vec3 atten)
+{
+ vec3 color = vec3(0);
+
+ float NdotV = clamp(abs(dot(norm, v)), 0.001, 1.0);
+
+ color += pbrIbl(diffuseColor, specularColor, radiance, irradiance, ao, NdotV, perceptualRoughness);
+
+ color += pbrPunctual(diffuseColor, specularColor, perceptualRoughness, metallic, norm, v, normalize(light_dir)) * sunlit * 2.75 * scol;
+ color += colorEmissive*0.5;
+
+ color = atmosFragLightingLinear(color, additive, atten);
+ color = scaleSoftClipFragLinear(color);
+
+ return color;
+}
+
+uniform vec4 waterPlane;
+uniform float waterSign;
+
+// discard if given position in eye space is on the wrong side of the waterPlane according to waterSign
+void waterClip(vec3 pos)
+{
+ // TODO: make this less branchy
+ if (waterSign > 0)
+ {
+ if ((dot(pos.xyz, waterPlane.xyz) + waterPlane.w) < -0.1)
+ {
+ discard;
+ }
+ }
+ else
+ {
+ if ((dot(pos.xyz, waterPlane.xyz) + waterPlane.w) > -0.1)
+ {
+ discard;
+ }
+ }
+
+}
+
diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl
index b328ee9483..3bf148502c 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl
@@ -53,6 +53,6 @@ void main()
frag_data[0] = vec4(col.rgb, 0.0);
frag_data[1] = vec4(0,0,0,0); // spec
vec3 nvn = normalize(vary_normal);
- frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, 0.0);
+ frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, GBUFFER_FLAG_HAS_ATMOS);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl
index fc5c86b4d6..e15239b59d 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl
@@ -52,5 +52,5 @@ void main()
frag_data[0] = vec4(col.rgb, 0.0);
frag_data[1] = vec4(0,0,0,0);
vec3 nvn = normalize(vary_normal);
- frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, 0.0);
+ frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, GBUFFER_FLAG_HAS_ATMOS);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskNoColorF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskNoColorF.glsl
index 1bb8eb8bd0..b0ff233414 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskNoColorF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskNoColorF.glsl
@@ -52,6 +52,6 @@ void main()
frag_data[0] = vec4(col.rgb, 0.0);
frag_data[1] = vec4(0,0,0,0); // spec
vec3 nvn = normalize(vary_normal);
- frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, 0.0);
+ frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, GBUFFER_FLAG_HAS_ATMOS);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl
index 8319e61242..b2d2e2fa71 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl
@@ -46,6 +46,6 @@ void main()
frag_data[1] = vertex_color.aaaa; // spec
//frag_data[1] = vec4(vec3(vertex_color.a), vertex_color.a+(1.0-vertex_color.a)*vertex_color.a); // spec - from former class3 - maybe better, but not so well tested
vec3 nvn = normalize(vary_normal);
- frag_data[2] = vec4(encode_normal(nvn.xyz), vertex_color.a, 0.0);
+ frag_data[2] = vec4(encode_normal(nvn.xyz), vertex_color.a, GBUFFER_FLAG_HAS_ATMOS);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl
index ccd1df84f9..b4bc114dd5 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl
@@ -48,5 +48,5 @@ void main()
frag_data[0] = vec4(col, 0.0);
frag_data[1] = vec4(spec, vertex_color.a); // spec
vec3 nvn = normalize(vary_normal);
- frag_data[2] = vec4(encode_normal(nvn.xyz), vertex_color.a, 0.0);
+ frag_data[2] = vec4(encode_normal(nvn.xyz), vertex_color.a, GBUFFER_FLAG_HAS_ATMOS);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/dofCombineF.glsl b/indra/newview/app_settings/shaders/class1/deferred/dofCombineF.glsl
index 8d48bb016b..d9c0e590c8 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/dofCombineF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/dofCombineF.glsl
@@ -33,8 +33,8 @@ out vec4 frag_color;
#define frag_color gl_FragColor
#endif
-uniform sampler2DRect diffuseRect;
-uniform sampler2DRect lightMap;
+uniform sampler2D diffuseRect;
+uniform sampler2D lightMap;
uniform mat4 inv_proj;
uniform vec2 screen_res;
@@ -46,12 +46,12 @@ uniform float dof_height;
VARYING vec2 vary_fragcoord;
-vec4 dofSample(sampler2DRect tex, vec2 tc)
+vec4 dofSample(sampler2D tex, vec2 tc)
{
tc.x = min(tc.x, dof_width);
tc.y = min(tc.y, dof_height);
- return texture2DRect(tex, tc);
+ return texture2D(tex, tc);
}
void main()
@@ -60,7 +60,7 @@ void main()
vec4 dof = dofSample(diffuseRect, vary_fragcoord.xy*res_scale);
- vec4 diff = texture2DRect(lightMap, vary_fragcoord.xy);
+ vec4 diff = texture2D(lightMap, vary_fragcoord.xy);
float a = min(abs(diff.a*2.0-1.0) * max_cof*res_scale*res_scale, 1.0);
@@ -69,10 +69,10 @@ void main()
float sc = a/res_scale;
vec4 col;
- col = texture2DRect(lightMap, vary_fragcoord.xy+vec2(sc,sc));
- col += texture2DRect(lightMap, vary_fragcoord.xy+vec2(-sc,sc));
- col += texture2DRect(lightMap, vary_fragcoord.xy+vec2(sc,-sc));
- col += texture2DRect(lightMap, vary_fragcoord.xy+vec2(-sc,-sc));
+ col = texture2D(lightMap, vary_fragcoord.xy+vec2(sc,sc)/screen_res);
+ col += texture2D(lightMap, vary_fragcoord.xy+vec2(-sc,sc)/screen_res);
+ col += texture2D(lightMap, vary_fragcoord.xy+vec2(sc,-sc)/screen_res);
+ col += texture2D(lightMap, vary_fragcoord.xy+vec2(-sc,-sc)/screen_res);
diff = mix(diff, col*0.25, a);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl
index 57420158ca..73e5b401c0 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl
@@ -54,35 +54,44 @@ vec3 fullbrightScaleSoftClip(vec3 light);
uniform float minimum_alpha;
#endif
+#ifdef IS_ALPHA
+void waterClip(vec3 pos);
+#endif
+
void main()
{
+
+#ifdef IS_ALPHA
+ waterClip(vary_position.xyz);
+#endif
+
#ifdef HAS_DIFFUSE_LOOKUP
- vec4 color = diffuseLookup(vary_texcoord0.xy);
+ vec4 color = diffuseLookup(vary_texcoord0.xy);
#else
- vec4 color = texture2D(diffuseMap, vary_texcoord0.xy);
+ vec4 color = texture2D(diffuseMap, vary_texcoord0.xy);
#endif
- float final_alpha = color.a * vertex_color.a;
+ float final_alpha = color.a * vertex_color.a;
#ifdef HAS_ALPHA_MASK
- if (color.a < minimum_alpha)
- {
- discard;
- }
+ if (color.a < minimum_alpha)
+ {
+ discard;
+ }
#endif
- color.rgb *= vertex_color.rgb;
+ color.rgb *= vertex_color.rgb;
#ifdef WATER_FOG
- vec3 pos = vary_position;
- vec4 fogged = applyWaterFogView(pos, vec4(color.rgb, final_alpha));
- color.rgb = fogged.rgb;
- color.a = fogged.a;
+ vec3 pos = vary_position;
+ vec4 fogged = applyWaterFogView(pos, vec4(color.rgb, final_alpha));
+ color.rgb = fogged.rgb;
+ color.a = fogged.a;
#else
color.a = final_alpha;
#endif
- frag_color.rgb = color.rgb;
- frag_color.a = color.a;
+ frag_color.rgb = srgb_to_linear(color.rgb);
+ frag_color.a = color.a;
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyF.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyF.glsl
index 9fcee04c32..f693323d45 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyF.glsl
@@ -38,7 +38,7 @@ uniform sampler2D diffuseMap;
VARYING vec4 vertex_color;
VARYING vec2 vary_texcoord0;
VARYING vec3 vary_texcoord1;
-VARYING vec4 vary_position;
+VARYING vec3 vary_position;
uniform samplerCube environmentMap;
@@ -74,7 +74,7 @@ void main()
vec3 amblit;
vec3 additive;
vec3 atten;
- vec3 pos = vary_position.xyz/vary_position.w;
+ vec3 pos = vary_position.xyz;
calcAtmosphericVars(pos.xyz, vec3(0), 1.0, sunlit, amblit, additive, atten, false);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyV.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyV.glsl
index 3bd6b693fa..0e461b4004 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyV.glsl
@@ -45,7 +45,7 @@ ATTRIBUTE vec2 texcoord0;
VARYING vec4 vertex_color;
VARYING vec2 vary_texcoord0;
VARYING vec3 vary_texcoord1;
-VARYING vec4 vary_position;
+VARYING vec3 vary_position;
#ifdef HAS_SKIN
mat4 getObjectSkinnedTransform();
@@ -62,17 +62,18 @@ void main()
mat4 mat = getObjectSkinnedTransform();
mat = modelview_matrix * mat;
vec4 pos = mat * vert;
- vary_position = gl_Position = projection_matrix * pos;
+ gl_Position = projection_matrix * pos;
vec3 norm = normalize((mat*vec4(normal.xyz+position.xyz,1.0)).xyz-pos.xyz);
#else
vec4 pos = (modelview_matrix * vert);
- vary_position = gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0);
+ gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0);
vec3 norm = normalize(normal_matrix * normal);
#endif
- vec3 ref = reflect(pos.xyz, -norm);
+ vary_position = pos.xyz;
vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
- vary_texcoord1 = (texture_matrix1 * vec4(ref,1.0)).xyz;
+
+ vary_texcoord1 = norm;
calcAtmospherics(pos.xyz);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl
index e71636f2c9..e565722164 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl
@@ -38,9 +38,7 @@ void calcAtmospherics(vec3 inPositionEye);
vec3 atmosAmbient();
vec3 atmosAffectDirectionalLight(float lightIntensity);
-#ifdef WATER_FOG
VARYING vec3 vary_position;
-#endif
VARYING vec4 vertex_color;
VARYING vec2 vary_texcoord0;
@@ -66,9 +64,7 @@ void main()
gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0);
#endif
-#ifdef WATER_FOG
vary_position = pos.xyz;
-#endif
vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/fxaaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/fxaaF.glsl
index 226e63cdda..50d697ae12 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/fxaaF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/fxaaF.glsl
@@ -28,11 +28,7 @@
/*[EXTRA_CODE_HERE]*/
-#ifdef DEFINE_GL_FRAGCOLOR
out vec4 frag_color;
-#else
-#define frag_color gl_FragColor
-#endif
#define FXAA_PC 1
//#define FXAA_GLSL_130 1
@@ -2092,6 +2088,7 @@ half4 FxaaPixelShader(
#endif
uniform sampler2D diffuseMap;
+uniform sampler2D depthMap;
uniform vec2 rcp_screen_res;
uniform vec4 rcp_frame_opt;
@@ -2120,8 +2117,7 @@ void main()
- //diff = texture2D(diffuseMap, vary_tc);
-
- frag_color = diff;
-
+ frag_color = diff;
+
+ gl_FragDepth = texture(depthMap, vary_fragcoord.xy).r;
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/genbrdflutF.glsl b/indra/newview/app_settings/shaders/class1/deferred/genbrdflutF.glsl
new file mode 100644
index 0000000000..9e6c853015
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/genbrdflutF.glsl
@@ -0,0 +1,141 @@
+/**
+ * @file class1/deferred/genbrdflut.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$
+ */
+
+/* Taken from Sascha Willem's Vulkan GLTF refernce implementation
+MIT License
+
+Copyright (c) 2018 Sascha Willems
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+/*[EXTRA_CODE_HERE]*/
+
+VARYING vec2 vary_uv;
+
+out vec4 outColor;
+
+#define NUM_SAMPLES 1024u
+
+const float PI = 3.1415926536;
+
+// Based omn http://byteblacksmith.com/improvements-to-the-canonical-one-liner-glsl-rand-for-opengl-es-2-0/
+float random(vec2 co)
+{
+ float a = 12.9898;
+ float b = 78.233;
+ float c = 43758.5453;
+ float dt= dot(co.xy ,vec2(a,b));
+ float sn= mod(dt,3.14);
+ return fract(sin(sn) * c);
+}
+
+vec2 hammersley2d(uint i, uint N)
+{
+ // Radical inverse based on http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html
+ uint bits = (i << 16u) | (i >> 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);
+ float rdi = float(bits) * 2.3283064365386963e-10;
+ return vec2(float(i) /float(N), rdi);
+}
+
+// Based on http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_slides.pdf
+vec3 importanceSample_GGX(vec2 Xi, float roughness, vec3 normal)
+{
+ // Maps a 2D point to a hemisphere with spread based on roughness
+ float alpha = roughness * roughness;
+ float phi = 2.0 * PI * Xi.x + random(normal.xz) * 0.1;
+ float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (alpha*alpha - 1.0) * Xi.y));
+ float sinTheta = sqrt(1.0 - cosTheta * cosTheta);
+ vec3 H = vec3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta);
+
+ // Tangent space
+ vec3 up = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
+ vec3 tangentX = normalize(cross(up, normal));
+ vec3 tangentY = normalize(cross(normal, tangentX));
+
+ // Convert to world Space
+ return normalize(tangentX * H.x + tangentY * H.y + normal * H.z);
+}
+
+// Geometric Shadowing function
+float G_SchlicksmithGGX(float dotNL, float dotNV, float roughness)
+{
+ float k = (roughness * roughness) / 2.0;
+ float GL = dotNL / (dotNL * (1.0 - k) + k);
+ float GV = dotNV / (dotNV * (1.0 - k) + k);
+ return GL * GV;
+}
+
+vec2 BRDF(float NoV, float roughness)
+{
+ // Normal always points along z-axis for the 2D lookup
+ const vec3 N = vec3(0.0, 0.0, 1.0);
+ vec3 V = vec3(sqrt(1.0 - NoV*NoV), 0.0, NoV);
+
+ vec2 LUT = vec2(0.0);
+ for(uint i = 0u; i < NUM_SAMPLES; i++) {
+ vec2 Xi = hammersley2d(i, NUM_SAMPLES);
+ vec3 H = importanceSample_GGX(Xi, roughness, N);
+ vec3 L = 2.0 * dot(V, H) * H - V;
+
+ float dotNL = max(dot(N, L), 0.0);
+ float dotNV = max(dot(N, V), 0.0);
+ float dotVH = max(dot(V, H), 0.0);
+ float dotNH = max(dot(H, N), 0.0);
+
+ if (dotNL > 0.0) {
+ float G = G_SchlicksmithGGX(dotNL, dotNV, roughness);
+ float G_Vis = (G * dotVH) / (dotNH * dotNV);
+ float Fc = pow(1.0 - dotVH, 5.0);
+ LUT += vec2((1.0 - Fc) * G_Vis, Fc * G_Vis);
+ }
+ }
+ return LUT / float(NUM_SAMPLES);
+}
+
+void main()
+{
+ outColor = vec4(BRDF(vary_uv.s, 1.0-vary_uv.t), 0.0, 1.0);
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/genbrdflutV.glsl
index 9d872b8df8..682244478b 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/genbrdflutV.glsl
@@ -1,9 +1,9 @@
/**
- * @file class3/deferred/softenLightV.glsl
+ * @file class3\deferred\genbrdflutV.glsl
*
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2007, Linden Research, Inc.
+ * 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
@@ -22,17 +22,18 @@
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
-ATTRIBUTE vec3 position;
-
-VARYING vec2 vary_fragcoord;
uniform mat4 modelview_projection_matrix;
-uniform vec2 screen_res;
+
+ATTRIBUTE vec3 position;
+
+VARYING vec2 vary_uv;
void main()
{
//transform vertex
vec4 pos = modelview_projection_matrix * vec4(position.xyz, 1.0);
- gl_Position = pos;
- vary_fragcoord = (pos.xy*0.5+0.5)*screen_res;
+ vary_uv = position.xy*0.5+0.5;
+
+ gl_Position = vec4(position.xyz, 1.0);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/highlightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/highlightF.glsl
index 90566393d2..75f914cb02 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/highlightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/highlightF.glsl
@@ -38,5 +38,5 @@ void main()
{
frag_data[0] = color*texture2D(diffuseMap, vary_texcoord0.xy);
frag_data[1] = vec4(0.0);
- frag_data[2] = vec4(0.0, 1.0, 0.0, 1.0);
+ frag_data[2] = vec4(0.0, 1.0, 0.0, GBUFFER_FLAG_SKIP_ATMOS);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl
index a58cc3d12d..51afda2791 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl
@@ -41,6 +41,7 @@ uniform sampler2D specularMap;
VARYING vec2 vary_texcoord0;
vec3 linear_to_srgb(vec3 c);
+vec2 encode_normal (vec3 n);
void main()
{
@@ -56,5 +57,5 @@ void main()
frag_data[0] = vec4(col.rgb, 0.0);
frag_data[1] = spec;
- frag_data[2] = norm;
+ frag_data[2] = vec4(encode_normal(norm.xyz),0,GBUFFER_FLAG_HAS_ATMOS);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl b/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl
index be1003a7e0..185c1150ef 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl
@@ -31,10 +31,10 @@ out vec4 frag_color;
#define frag_color gl_FragColor
#endif
-uniform sampler2DRect diffuseMap;
+uniform sampler2D diffuseMap;
VARYING vec2 vary_fragcoord;
void main()
{
- frag_color = texture2DRect(diffuseMap, vary_fragcoord.xy);
+ frag_color = texture2D(diffuseMap, vary_fragcoord.xy);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/luminanceV.glsl b/indra/newview/app_settings/shaders/class1/deferred/luminanceV.glsl
index f2dc60aa5d..5488a63c6a 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/luminanceV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/luminanceV.glsl
@@ -39,7 +39,7 @@ void main()
vec4 pos = modelview_projection_matrix * vec4(position.xyz, 1.0);
gl_Position = pos;
- vary_fragcoord = (pos.xy * 0.5 + 0.5)*screen_res;
+ vary_fragcoord = (pos.xy * 0.5 + 0.5);
vertex_color = diffuse_color;
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl
index b30d7655db..51a36935f2 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl
@@ -23,431 +23,30 @@
* $/LicenseInfo$
*/
+
/*[EXTRA_CODE_HERE]*/
//class1/deferred/materialF.glsl
-// This shader is used for both writing opaque/masked content to the gbuffer and writing blended content to the framebuffer during the alpha pass.
+// Debug stub for non-pbr material
-#define DIFFUSE_ALPHA_MODE_NONE 0
#define DIFFUSE_ALPHA_MODE_BLEND 1
-#define DIFFUSE_ALPHA_MODE_MASK 2
-#define DIFFUSE_ALPHA_MODE_EMISSIVE 3
-
-uniform float emissive_brightness; // fullbright flag, 1.0 == fullbright, 0.0 otherwise
-uniform int sun_up_factor;
-
-#ifdef WATER_FOG
-vec4 applyWaterFogView(vec3 pos, vec4 color);
-#endif
-
-vec3 atmosFragLighting(vec3 l, vec3 additive, vec3 atten);
-vec3 scaleSoftClipFrag(vec3 l);
-
-vec3 fullbrightAtmosTransportFrag(vec3 light, vec3 additive, vec3 atten);
-vec3 fullbrightScaleSoftClip(vec3 light);
-
-void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, out vec3 sunlit, out vec3 amblit, out vec3 additive, out vec3 atten, bool use_ao);
-
-vec3 srgb_to_linear(vec3 cs);
-vec3 linear_to_srgb(vec3 cs);
#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
-
-#ifdef DEFINE_GL_FRAGCOLOR
out vec4 frag_color;
#else
-#define frag_color gl_FragColor
-#endif
-
-#ifdef HAS_SUN_SHADOW
-float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen);
+out vec4 frag_data[4];
#endif
-uniform samplerCube environmentMap;
-uniform sampler2D lightFunc;
-
-// Inputs
-uniform vec4 morphFactor;
-uniform vec3 camPosLocal;
-uniform mat3 env_mat;
-
-uniform vec3 sun_dir;
-uniform vec3 moon_dir;
-VARYING vec2 vary_fragcoord;
-
-VARYING vec3 vary_position;
-
-uniform mat4 proj_mat;
-uniform mat4 inv_proj;
-uniform vec2 screen_res;
-
-uniform vec4 light_position[8];
-uniform vec3 light_direction[8];
-uniform vec4 light_attenuation[8];
-uniform vec3 light_diffuse[8];
-
-float getAmbientClamp();
-
-vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 npos, vec3 diffuse, vec4 spec, vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight, inout float glare, float ambiance)
-{
- // SL-14895 inverted attenuation work-around
- // This routine is tweaked to match deferred lighting, but previously used an inverted la value. To reconstruct
- // that previous value now that the inversion is corrected, we reverse the calculations in LLPipeline::setupHWLights()
- // to recover the `adjusted_radius` value previously being sent as la.
- float falloff_factor = (12.0 * fa) - 9.0;
- float inverted_la = falloff_factor / la;
- // Yes, it makes me want to cry as well. DJH
-
- vec3 col = vec3(0);
-
- //get light vector
- vec3 lv = lp.xyz - v;
-
- //get distance
- float dist = length(lv);
- float da = 1.0;
-
- dist /= inverted_la;
-
- if (dist > 0.0 && inverted_la > 0.0)
- {
- //normalize light vector
- lv = normalize(lv);
-
- //distance attenuation
- float dist_atten = clamp(1.0 - (dist - 1.0*(1.0 - fa)) / fa, 0.0, 1.0);
- dist_atten *= dist_atten;
- dist_atten *= 2.0f;
-
- if (dist_atten <= 0.0)
- {
- return col;
- }
-
- // spotlight coefficient.
- float spot = max(dot(-ln, lv), is_pointlight);
- da *= spot*spot; // GL_SPOT_EXPONENT=2
-
- //angular attenuation
- da *= dot(n, lv);
-
- float lit = 0.0f;
-
- float amb_da = ambiance;
- if (da >= 0)
- {
- lit = max(da * dist_atten, 0.0);
- col = lit * light_col * diffuse;
- amb_da += (da*0.5 + 0.5) * ambiance;
- }
- amb_da += (da*da*0.5 + 0.5) * ambiance;
- amb_da *= dist_atten;
- amb_da = min(amb_da, 1.0f - lit);
-
- // SL-10969 need to see why these are blown out
- //col.rgb += amb_da * light_col * diffuse;
-
- if (spec.a > 0.0)
- {
- //vec3 ref = dot(pos+lv, norm);
- vec3 h = normalize(lv + npos);
- float nh = dot(n, h);
- float nv = dot(n, 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);
- vec3 speccol = lit*scol*light_col.rgb*spec.rgb;
- speccol = clamp(speccol, vec3(0), vec3(1));
- col += speccol;
-
- float cur_glare = max(speccol.r, speccol.g);
- cur_glare = max(cur_glare, speccol.b);
- glare = max(glare, speccol.r);
- glare += max(cur_glare, 0.0);
- }
- }
- }
-
- return max(col, vec3(0.0, 0.0, 0.0));
-}
-
-#else
-#ifdef DEFINE_GL_FRAGCOLOR
-out vec4 frag_data[3];
-#else
-#define frag_data gl_FragData
-#endif
-#endif
-
-uniform sampler2D diffuseMap; //always in sRGB space
-
-#ifdef HAS_NORMAL_MAP
-uniform sampler2D bumpMap;
-#endif
-
-#ifdef HAS_SPECULAR_MAP
-uniform sampler2D specularMap;
-
-VARYING vec2 vary_texcoord2;
-#endif
-
-uniform float env_intensity;
-uniform vec4 specular_color; // specular color RGB and specular exponent (glossiness) in alpha
-
-#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_MASK)
-uniform float minimum_alpha;
-#endif
-
-#ifdef HAS_NORMAL_MAP
-VARYING vec3 vary_mat0;
-VARYING vec3 vary_mat1;
-VARYING vec3 vary_mat2;
-VARYING vec2 vary_texcoord1;
-#else
-VARYING vec3 vary_normal;
-#endif
-
-VARYING vec4 vertex_color;
-VARYING vec2 vary_texcoord0;
-
-vec2 encode_normal(vec3 n);
-
void main()
{
- vec2 pos_screen = vary_texcoord0.xy;
-
- vec4 diffcol = texture2D(diffuseMap, vary_texcoord0.xy);
- diffcol.rgb *= vertex_color.rgb;
-
-#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_MASK)
-
- // Comparing floats cast from 8-bit values, produces acne right at the 8-bit transition points
- float bias = 0.001953125; // 1/512, or half an 8-bit quantization (SL-18637)
- if (diffcol.a < minimum_alpha-bias)
- {
- discard;
- }
-#endif
-
#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
- vec3 gamma_diff = diffcol.rgb;
- diffcol.rgb = srgb_to_linear(diffcol.rgb);
-#endif
-
-#ifdef HAS_SPECULAR_MAP
- vec4 spec = texture2D(specularMap, vary_texcoord2.xy);
- spec.rgb *= specular_color.rgb;
+ frag_color = vec4(1, 0, 0, 0.5);
#else
- vec4 spec = vec4(specular_color.rgb, 1.0);
-#endif
-
-#ifdef HAS_NORMAL_MAP
- vec4 norm = texture2D(bumpMap, vary_texcoord1.xy);
-
- norm.xyz = norm.xyz * 2 - 1;
-
- vec3 tnorm = vec3(dot(norm.xyz,vary_mat0),
- dot(norm.xyz,vary_mat1),
- dot(norm.xyz,vary_mat2));
-#else
- vec4 norm = vec4(0,0,0,1.0);
- vec3 tnorm = vary_normal;
-#endif
-
- norm.xyz = normalize(tnorm.xyz);
-
- vec2 abnormal = encode_normal(norm.xyz);
-
- vec4 final_color = diffcol;
-
-#if (DIFFUSE_ALPHA_MODE != DIFFUSE_ALPHA_MODE_EMISSIVE)
- final_color.a = emissive_brightness;
-#else
- final_color.a = max(final_color.a, emissive_brightness);
-#endif
-
- vec4 final_specular = spec;
-
-#ifdef HAS_SPECULAR_MAP
- vec4 final_normal = vec4(encode_normal(normalize(tnorm)), env_intensity * spec.a, 0.0);
- final_specular.a = specular_color.a * norm.a;
-#else
- vec4 final_normal = vec4(encode_normal(normalize(tnorm)), env_intensity, 0.0);
- final_specular.a = specular_color.a;
-#endif
-
-#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
-
- //forward rendering, output just lit sRGBA
- vec3 pos = vary_position;
-
- float shadow = 1.0f;
-
-#ifdef HAS_SUN_SHADOW
- shadow = sampleDirectionalShadow(pos.xyz, norm.xyz, pos_screen);
-#endif
-
- spec = final_specular;
- vec4 diffuse = final_color;
- float envIntensity = final_normal.z;
-
- vec3 color = vec3(0,0,0);
-
- vec3 light_dir = (sun_up_factor == 1) ? sun_dir : moon_dir;
-
- float bloom = 0.0;
- vec3 sunlit;
- vec3 amblit;
- vec3 additive;
- vec3 atten;
-
- calcAtmosphericVars(pos.xyz, light_dir, 1.0, sunlit, amblit, additive, atten, false);
-
- // This call breaks the Mac GLSL compiler/linker for unknown reasons (17Mar2020)
- // The call is either a no-op or a pure (pow) gamma adjustment, depending on GPU level
- // TODO: determine if we want to re-apply the gamma adjustment, and if so understand & fix Mac breakage
- //color = fullbrightScaleSoftClip(color);
-
- vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
-
- //we're in sRGB space, so gamma correct this dot product so
- // lighting from the sun stays sharp
- float da = clamp(dot(normalize(norm.xyz), light_dir.xyz), 0.0, 1.0);
- da = pow(da, 1.0 / 1.3);
-
- color = amblit;
-
- //darken ambient for normals perpendicular to light vector so surfaces in shadow
- // and facing away from light still have some definition to them.
- // do NOT gamma correct this dot product so ambient lighting stays soft
- float ambient = min(abs(dot(norm.xyz, sun_dir.xyz)), 1.0);
- ambient *= 0.5;
- ambient *= ambient;
- ambient = (1.0 - ambient);
-
- vec3 sun_contrib = min(da, shadow) * sunlit;
-
- color *= ambient;
-
- color += sun_contrib;
-
- color *= gamma_diff.rgb;
-
- float glare = 0.0;
-
- if (spec.a > 0.0) // specular reflection
- {
- /* // Reverting this specular calculation to previous 'dumbshiny' version - DJH 6/17/2020
- // Preserving the refactored version as a comment for potential reconsideration,
- // overriding the general rule to avoid pollutiong the source with commented code.
- //
- // If you're reading this in 2021+, feel free to obliterate.
-
- vec3 npos = -normalize(pos.xyz);
-
- //vec3 ref = dot(pos+lv, norm);
- vec3 h = normalize(light_dir.xyz + npos);
- float nh = dot(norm.xyz, h);
- float nv = dot(norm.xyz, 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);
- vec3 sp = sun_contrib*scol / 6.0f;
- sp = clamp(sp, vec3(0), vec3(1));
- bloom = dot(sp, sp) / 4.0;
- color += sp * spec.rgb;
- }
- */
-
- float sa = dot(refnormpersp, sun_dir.xyz);
- vec3 dumbshiny = sunlit * shadow * (texture2D(lightFunc, vec2(sa, spec.a)).r);
-
- // add the two types of shiny together
- vec3 spec_contrib = dumbshiny * spec.rgb;
- bloom = dot(spec_contrib, spec_contrib) / 6;
-
- glare = max(spec_contrib.r, spec_contrib.g);
- glare = max(glare, spec_contrib.b);
-
- color += spec_contrib;
- }
-
- color = mix(color.rgb, diffcol.rgb, diffuse.a);
-
- if (envIntensity > 0.0)
- {
- //add environmentmap
- vec3 env_vec = env_mat * refnormpersp;
-
- vec3 reflected_color = textureCube(environmentMap, env_vec).rgb;
-
- color = mix(color, reflected_color, envIntensity);
-
- float cur_glare = max(reflected_color.r, reflected_color.g);
- cur_glare = max(cur_glare, reflected_color.b);
- cur_glare *= envIntensity*4.0;
- glare += cur_glare;
- }
-
- color = atmosFragLighting(color, additive, atten);
- color = scaleSoftClipFrag(color);
-
- //convert to linear before adding local lights
- color = srgb_to_linear(color);
-
- vec3 npos = normalize(-pos.xyz);
-
- vec3 light = vec3(0, 0, 0);
-
- final_specular.rgb = srgb_to_linear(final_specular.rgb); // SL-14035
-
-#define LIGHT_LOOP(i) light.rgb += calcPointLightOrSpotLight(light_diffuse[i].rgb, npos, diffuse.rgb, final_specular, pos.xyz, norm.xyz, light_position[i], light_direction[i].xyz, light_attenuation[i].x, light_attenuation[i].y, light_attenuation[i].z, glare, light_attenuation[i].w );
-
- LIGHT_LOOP(1)
- LIGHT_LOOP(2)
- LIGHT_LOOP(3)
- LIGHT_LOOP(4)
- LIGHT_LOOP(5)
- LIGHT_LOOP(6)
- LIGHT_LOOP(7)
-
- color += light;
-
- glare = min(glare, 1.0);
- float al = max(diffcol.a, glare)*vertex_color.a;
-
- //convert to srgb as this color is being written post gamma correction
- color = linear_to_srgb(color);
-
-#ifdef WATER_FOG
- vec4 temp = applyWaterFogView(pos, vec4(color, al));
- color = temp.rgb;
- al = temp.a;
-#endif
-
- frag_color = vec4(color, al);
-
-#else // mode is not DIFFUSE_ALPHA_MODE_BLEND, encode to gbuffer
-
- // deferred path
- frag_data[0] = final_color; //gbuffer is sRGB
- frag_data[1] = final_specular; // XYZ = Specular color. W = Specular exponent.
- frag_data[2] = final_normal; // XY = Normal. Z = Env. intensity.
+ // emissive red PBR material
+ frag_data[0] = vec4(0, 0, 0, 0);
+ frag_data[1] = vec4(0, 0, 0, 0);
+ frag_data[2] = vec4(1, 0, 0, GBUFFER_FLAG_HAS_PBR);
+ frag_data[3] = vec4(1, 0, 0, 0);
#endif
}
-
diff --git a/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl b/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl
index 7e29ada205..a1cab87092 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl
@@ -1,5 +1,5 @@
/**
- * @file bumpV.glsl
+ * @file materialV.glsl
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
diff --git a/indra/newview/app_settings/shaders/class1/deferred/moonF.glsl b/indra/newview/app_settings/shaders/class1/deferred/moonF.glsl
index 35068899ee..7032c45603 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/moonF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/moonF.glsl
@@ -34,8 +34,7 @@ out vec4 frag_data[3];
#endif
uniform vec4 color;
-uniform vec4 sunlight_color;
-uniform vec4 moonlight_color;
+uniform vec3 moonlight_color;
uniform vec3 moon_dir;
uniform float moon_brightness;
uniform sampler2D diffuseMap;
@@ -55,6 +54,12 @@ void main()
fade = clamp( moon_dir.z*moon_dir.z*4.0, 0.0, 1.0 );
vec4 c = texture2D(diffuseMap, vary_texcoord0.xy);
+
+ // SL-14113 Don't write to depth; prevent moon's quad from hiding stars which should be visible
+ // Moon texture has transparent pixels <0x55,0x55,0x55,0x00>
+ if (c.a <= 2./255.) // 0.00784
+ discard;
+
// c.rgb = srgb_to_linear(c.rgb);
c.rgb *= moonlight_color.rgb;
c.rgb *= moon_brightness;
@@ -66,8 +71,8 @@ void main()
frag_data[0] = vec4(c.rgb, c.a);
frag_data[1] = vec4(0.0);
- frag_data[2] = vec4(0.0f);
+ frag_data[2] = vec4(0.0, 0.0, 0.0, GBUFFER_FLAG_HAS_ATMOS);
- gl_FragDepth = 0.999985f;
+ gl_FragDepth = LL_SHADER_CONST_CLOUD_MOON_DEPTH; // SL-14113
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
index 09c47165dd..8fdb5e7154 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
@@ -23,123 +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 sampler2DRect depthMap;
-uniform sampler2DRect diffuseRect;
-uniform sampler2DRect specularRect;
-uniform samplerCube environmentMap;
-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);
void main()
{
-#if defined(LOCAL_LIGHT_KILL)
- discard; // Bail immediately
-#endif
-
- vec3 out_col = vec3(0, 0, 0);
- vec2 frag = (vary_fragcoord.xy * 0.5 + 0.5) * screen_res;
- vec3 pos = getPosition(frag.xy).xyz;
- if (pos.z < far_z)
- {
- discard;
- }
-
- vec3 norm = getNorm(frag.xy);
-
- vec4 spec = texture2DRect(specularRect, frag.xy);
- vec3 diff = texture2DRect(diffuseRect, frag.xy).rgb;
-
- float noise = texture2D(noiseMap, frag.xy / 128.0).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/multiPointLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightV.glsl
index eefefa640d..d71dc76423 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightV.glsl
@@ -23,8 +23,6 @@
* $/LicenseInfo$
*/
-uniform mat4 modelview_projection_matrix;
-
ATTRIBUTE vec3 position;
VARYING vec4 vary_fragcoord;
@@ -32,7 +30,7 @@ VARYING vec4 vary_fragcoord;
void main()
{
//transform vertex
- vec4 pos = modelview_projection_matrix * vec4(position.xyz, 1.0);
+ vec4 pos = vec4(position.xyz, 1.0);
vary_fragcoord = pos;
gl_Position = pos;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl
index ec3fb9c543..e9dac711c3 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl
@@ -38,11 +38,10 @@ out vec4 frag_color;
#define frag_color gl_FragColor
#endif
-uniform sampler2DRect diffuseRect;
-uniform sampler2DRect specularRect;
-uniform sampler2DRect depthMap;
-uniform sampler2DRect normalMap;
-uniform samplerCube environmentMap;
+uniform sampler2D diffuseRect;
+uniform sampler2D specularRect;
+uniform sampler2D depthMap;
+uniform sampler2D normalMap;
uniform sampler2D noiseMap;
uniform sampler2D projectionMap;
uniform sampler2D lightFunc;
@@ -73,6 +72,7 @@ uniform vec2 screen_res;
uniform mat4 inv_proj;
vec3 getNorm(vec2 pos_screen);
vec3 srgb_to_linear(vec3 c);
+float getDepth(vec2 tc);
vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod)
{
@@ -138,7 +138,6 @@ void main()
vec4 frag = vary_fragcoord;
frag.xyz /= frag.w;
frag.xyz = frag.xyz*0.5+0.5;
- frag.xy *= screen_res;
vec3 pos = getPosition(frag.xy).xyz;
vec3 lv = center.xyz-pos.xyz;
@@ -149,7 +148,7 @@ void main()
discard;
}
- float envIntensity = texture2DRect(normalMap, frag.xy).z;
+ float envIntensity = texture2D(normalMap, frag.xy).z;
vec3 norm = getNorm(frag.xy);
float l_dist = -dot(lv, proj_n);
@@ -173,7 +172,7 @@ void main()
discard;
}
- float noise = texture2D(noiseMap, frag.xy/128.0).b;
+ float noise = texture2D(noiseMap, frag.xy).b;
dist_atten *= noise;
lv = proj_origin-pos.xyz;
@@ -181,7 +180,7 @@ void main()
float da = dot(norm, lv);
- vec3 diff_tex = texture2DRect(diffuseRect, frag.xy).rgb;
+ vec3 diff_tex = texture2D(diffuseRect, frag.xy).rgb;
vec3 dlit = vec3(0, 0, 0);
@@ -221,7 +220,7 @@ void main()
}
- vec4 spec = texture2DRect(specularRect, frag.xy);
+ vec4 spec = texture2D(specularRect, frag.xy);
if (spec.a > 0.0)
{
diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbralphaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbralphaF.glsl
new file mode 100644
index 0000000000..fc1024f4f1
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/pbralphaF.glsl
@@ -0,0 +1,34 @@
+/**
+ * @file class1\deferred\pbralphaF.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]*/
+
+out vec4 frag_color;
+
+void main()
+{
+ frag_color = vec4(0,1,0,0.5);
+}
+
diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbralphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbralphaV.glsl
new file mode 100644
index 0000000000..a2ad1b70fb
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/pbralphaV.glsl
@@ -0,0 +1,120 @@
+/**
+ * @file class1\deferred\pbralphaV.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$
+ */
+
+#define DIFFUSE_ALPHA_MODE_IGNORE 0
+#define DIFFUSE_ALPHA_MODE_BLEND 1
+#define DIFFUSE_ALPHA_MODE_MASK 2
+#define DIFFUSE_ALPHA_MODE_EMISSIVE 3
+
+#ifdef HAS_SKIN
+uniform mat4 modelview_matrix;
+uniform mat4 projection_matrix;
+mat4 getObjectSkinnedTransform();
+#else
+uniform mat3 normal_matrix;
+uniform mat4 modelview_projection_matrix;
+#endif
+uniform mat4 texture_matrix0;
+
+#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
+ #if !defined(HAS_SKIN)
+ uniform mat4 modelview_matrix;
+ #endif
+ VARYING vec3 vary_position;
+#endif
+
+uniform mat3 texture_basecolor_matrix;
+uniform mat3 texture_normal_matrix;
+uniform mat3 texture_metallic_roughness_matrix;
+uniform mat3 texture_emissive_matrix;
+
+#ifdef HAS_SUN_SHADOW
+out vec3 vary_fragcoord;
+uniform float near_clip;
+#endif
+
+in vec3 position;
+in vec4 diffuse_color;
+in vec3 normal;
+in vec4 tangent;
+in vec2 texcoord0;
+
+out vec2 basecolor_texcoord;
+out vec2 normal_texcoord;
+out vec2 metallic_roughness_texcoord;
+out vec2 emissive_texcoord;
+
+out vec4 vertex_color;
+
+out vec3 vary_tangent;
+flat out float vary_sign;
+out vec3 vary_normal;
+
+
+void main()
+{
+#ifdef HAS_SKIN
+ mat4 mat = getObjectSkinnedTransform();
+ mat = modelview_matrix * mat;
+ vec3 pos = (mat*vec4(position.xyz,1.0)).xyz;
+#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
+ vary_position = pos;
+#endif
+ vec4 vert = projection_matrix * vec4(pos,1.0);
+#else
+ //transform vertex
+ vec4 vert = modelview_projection_matrix * vec4(position.xyz, 1.0);
+#endif
+ gl_Position = vert;
+
+#ifdef HAS_SUN_SHADOW
+ vary_fragcoord.xyz = vert.xyz + vec3(0,0,near_clip);
+#endif
+
+ basecolor_texcoord = (texture_matrix0 * vec4(texture_basecolor_matrix * vec3(texcoord0,1), 1)).xy;
+ normal_texcoord = (texture_matrix0 * vec4(texture_normal_matrix * vec3(texcoord0,1), 1)).xy;
+ metallic_roughness_texcoord = (texture_matrix0 * vec4(texture_metallic_roughness_matrix * vec3(texcoord0,1), 1)).xy;
+ emissive_texcoord = (texture_matrix0 * vec4(texture_emissive_matrix * vec3(texcoord0,1), 1)).xy;
+
+#ifdef HAS_SKIN
+ vec3 n = (mat*vec4(normal.xyz+position.xyz,1.0)).xyz-pos.xyz;
+ vec3 t = (mat*vec4(tangent.xyz+position.xyz,1.0)).xyz-pos.xyz;
+#else //HAS_SKIN
+ vec3 n = normal_matrix * normal;
+ vec3 t = normal_matrix * tangent.xyz;
+#endif //HAS_SKIN
+
+ vary_tangent = normalize(t);
+ vary_sign = tangent.w;
+ vary_normal = normalize(n);
+
+ vertex_color = diffuse_color;
+
+#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
+ #if !defined(HAS_SKIN)
+ vary_position = (modelview_matrix*vec4(position.xyz, 1.0)).xyz;
+ #endif
+#endif
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl
new file mode 100644
index 0000000000..39419e9d78
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl
@@ -0,0 +1,103 @@
+/**
+ * @file pbropaqueF.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]*/
+
+uniform sampler2D diffuseMap; //always in sRGB space
+
+uniform float metallicFactor;
+uniform float roughnessFactor;
+uniform vec3 emissiveColor;
+uniform sampler2D bumpMap;
+uniform sampler2D emissiveMap;
+uniform sampler2D specularMap; // Packed: Occlusion, Metal, Roughness
+
+out vec4 frag_data[4];
+
+in vec3 vary_position;
+in vec4 vertex_color;
+in vec3 vary_normal;
+in vec3 vary_tangent;
+flat in float vary_sign;
+
+in vec2 basecolor_texcoord;
+in vec2 normal_texcoord;
+in vec2 metallic_roughness_texcoord;
+in vec2 emissive_texcoord;
+
+uniform float minimum_alpha; // PBR alphaMode: MASK, See: mAlphaCutoff, setAlphaCutoff()
+
+vec2 encode_normal(vec3 n);
+vec3 linear_to_srgb(vec3 c);
+vec3 srgb_to_linear(vec3 c);
+
+uniform mat3 normal_matrix;
+
+void main()
+{
+ vec4 basecolor = texture2D(diffuseMap, basecolor_texcoord.xy).rgba;
+ if (basecolor.a < minimum_alpha)
+ {
+ discard;
+ }
+
+ vec3 col = vertex_color.rgb * srgb_to_linear(basecolor.rgb);
+
+ // from mikktspace.com
+ vec3 vNt = texture2D(bumpMap, normal_texcoord.xy).xyz*2.0-1.0;
+ float sign = vary_sign;
+ vec3 vN = vary_normal;
+ vec3 vT = vary_tangent.xyz;
+
+ vec3 vB = sign * cross(vN, vT);
+ vec3 tnorm = normalize( vNt.x * vT + vNt.y * vB + vNt.z * vN );
+
+ // RGB = Occlusion, Roughness, Metal
+ // default values, see LLViewerTexture::sDefaultPBRORMImagep
+ // occlusion 1.0
+ // roughness 0.0
+ // metal 0.0
+ vec3 spec = texture2D(specularMap, metallic_roughness_texcoord.xy).rgb;
+
+ spec.g *= roughnessFactor;
+ spec.b *= metallicFactor;
+
+ vec3 emissive = emissiveColor;
+ emissive *= srgb_to_linear(texture2D(emissiveMap, emissive_texcoord.xy).rgb);
+
+ tnorm *= gl_FrontFacing ? 1.0 : -1.0;
+
+ //spec.rgb = vec3(1,1,0);
+ //col = vec3(0,0,0);
+ //emissive = vary_tangent.xyz*0.5+0.5;
+ //emissive = vec3(sign*0.5+0.5);
+ //emissive = vNt * 0.5 + 0.5;
+ //emissive = tnorm*0.5+0.5;
+ // See: C++: addDeferredAttachments(), GLSL: softenLightF
+ frag_data[0] = vec4(col, 0.0); // Diffuse
+ frag_data[1] = vec4(spec.rgb,vertex_color.a); // PBR linear packed Occlusion, Roughness, Metal.
+ frag_data[2] = vec4(encode_normal(tnorm), vertex_color.a, GBUFFER_FLAG_HAS_PBR); // normal, environment intensity, flags
+ frag_data[3] = vec4(emissive,0); // PBR sRGB Emissive
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueV.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueV.glsl
new file mode 100644
index 0000000000..5a69da641a
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueV.glsl
@@ -0,0 +1,97 @@
+/**
+ * @file pbropaqueV.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$
+ */
+
+#define DIFFUSE_ALPHA_MODE_IGNORE 0
+#define DIFFUSE_ALPHA_MODE_BLEND 1
+#define DIFFUSE_ALPHA_MODE_MASK 2
+#define DIFFUSE_ALPHA_MODE_EMISSIVE 3
+
+#ifdef HAS_SKIN
+uniform mat4 modelview_matrix;
+uniform mat4 projection_matrix;
+mat4 getObjectSkinnedTransform();
+#else
+uniform mat3 normal_matrix;
+uniform mat4 modelview_projection_matrix;
+#endif
+uniform mat4 texture_matrix0;
+
+uniform mat3 texture_basecolor_matrix;
+uniform mat3 texture_normal_matrix;
+uniform mat3 texture_metallic_roughness_matrix;
+uniform mat3 texture_emissive_matrix;
+
+in vec3 position;
+in vec4 diffuse_color;
+in vec3 normal;
+in vec4 tangent;
+in vec2 texcoord0;
+
+out vec2 basecolor_texcoord;
+out vec2 normal_texcoord;
+out vec2 metallic_roughness_texcoord;
+out vec2 emissive_texcoord;
+
+out vec4 vertex_color;
+
+out vec3 vary_tangent;
+flat out float vary_sign;
+out vec3 vary_normal;
+
+void main()
+{
+#ifdef HAS_SKIN
+ mat4 mat = getObjectSkinnedTransform();
+
+ mat = modelview_matrix * mat;
+
+ vec3 pos = (mat*vec4(position.xyz,1.0)).xyz;
+
+ gl_Position = projection_matrix*vec4(pos,1.0);
+
+#else
+ //transform vertex
+ gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
+#endif
+
+ basecolor_texcoord = (texture_matrix0 * vec4(texture_basecolor_matrix * vec3(texcoord0,1), 1)).xy;
+ normal_texcoord = (texture_matrix0 * vec4(texture_normal_matrix * vec3(texcoord0,1), 1)).xy;
+ metallic_roughness_texcoord = (texture_matrix0 * vec4(texture_metallic_roughness_matrix * vec3(texcoord0,1), 1)).xy;
+ emissive_texcoord = (texture_matrix0 * vec4(texture_emissive_matrix * vec3(texcoord0,1), 1)).xy;
+
+#ifdef HAS_SKIN
+ vec3 n = (mat*vec4(normal.xyz+position.xyz,1.0)).xyz-pos.xyz;
+ vec3 t = (mat*vec4(tangent.xyz+position.xyz,1.0)).xyz-pos.xyz;
+#else //HAS_SKIN
+ vec3 n = normal_matrix * normal;
+ vec3 t = normal_matrix * tangent.xyz;
+#endif
+
+ vary_tangent = normalize(t);
+ vary_sign = tangent.w;
+ vary_normal = normalize(n);
+
+ vertex_color = diffuse_color;
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl
index 18616a9bb3..a025c4a1b4 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl
@@ -1,5 +1,5 @@
/**
- * @file pointLightF.glsl
+ * @file class1\deferred\pointLightF.glsl
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
@@ -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 sampler2DRect diffuseRect;
-uniform sampler2DRect specularRect;
-uniform sampler2DRect normalMap;
-uniform samplerCube environmentMap;
-uniform sampler2D noiseMap;
-uniform sampler2D lightFunc;
-uniform sampler2DRect 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);
-vec3 srgb_to_linear(vec3 c);
void main()
{
- vec4 frag = vary_fragcoord;
- frag.xyz /= frag.w;
- frag.xyz = frag.xyz*0.5+0.5;
- frag.xy *= screen_res;
-
- 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/128.0).b;
-
- vec3 col = texture2DRect(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 = texture2DRect(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;
- }
-
- frag_color.rgb = col;
- frag_color.a = 0.0;
+ frag_color = vec4(0.0, 0.5, 0.5, 0.0);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl
index f06f8c870b..5ca39d6966 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl
@@ -33,7 +33,7 @@ out vec4 frag_color;
#define frag_color gl_FragColor
#endif
-uniform sampler2DRect diffuseRect;
+uniform sampler2D diffuseRect;
uniform mat4 inv_proj;
uniform vec2 screen_res;
@@ -44,7 +44,7 @@ VARYING vec2 vary_fragcoord;
void dofSample(inout vec4 diff, inout float w, float min_sc, vec2 tc)
{
- vec4 s = texture2DRect(diffuseRect, tc);
+ vec4 s = texture2D(diffuseRect, tc);
float sc = abs(s.a*2.0-1.0)*max_cof;
@@ -63,7 +63,7 @@ void dofSample(inout vec4 diff, inout float w, float min_sc, vec2 tc)
void dofSampleNear(inout vec4 diff, inout float w, float min_sc, vec2 tc)
{
- vec4 s = texture2DRect(diffuseRect, tc);
+ vec4 s = texture2D(diffuseRect, tc);
float wg = 0.25;
@@ -79,7 +79,7 @@ void main()
{
vec2 tc = vary_fragcoord.xy;
- vec4 diff = texture2DRect(diffuseRect, vary_fragcoord.xy);
+ vec4 diff = texture2D(diffuseRect, vary_fragcoord.xy);
{
float w = 1.0;
@@ -93,14 +93,14 @@ void main()
{
while (sc > 0.5)
{
- int its = int(max(1.0,(sc*3.7)));
+ int its = int(max(1.0,(sc*3.7)));
for (int i=0; i<its; ++i)
{
float ang = sc+i*2*PI/its; // sc is added for rotary perturbance
float samp_x = sc*sin(ang);
float samp_y = sc*cos(ang);
// you could test sample coords against an interesting non-circular aperture shape here, if desired.
- dofSampleNear(diff, w, sc, vary_fragcoord.xy + vec2(samp_x,samp_y));
+ dofSampleNear(diff, w, sc, vary_fragcoord.xy + (vec2(samp_x,samp_y) / screen_res));
}
sc -= 1.0;
}
@@ -117,7 +117,7 @@ void main()
float samp_x = sc*sin(ang);
float samp_y = sc*cos(ang);
// you could test sample coords against an interesting non-circular aperture shape here, if desired.
- dofSample(diff, w, sc, vary_fragcoord.xy + vec2(samp_x,samp_y));
+ dofSample(diff, w, sc, vary_fragcoord.xy + (vec2(samp_x,samp_y) / screen_res));
}
sc -= 1.0;
}
@@ -125,6 +125,6 @@ void main()
diff /= w;
}
-
+
frag_color = diff;
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl
index cd37a34e0d..987b2d1fe8 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl
@@ -33,7 +33,7 @@ out vec4 frag_color;
#define frag_color gl_FragColor
#endif
-uniform sampler2DRect diffuseRect;
+uniform sampler2D diffuseRect;
uniform vec2 screen_res;
VARYING vec2 vary_fragcoord;
@@ -41,12 +41,55 @@ uniform float display_gamma;
vec3 linear_to_srgb(vec3 cl);
+//=================================
+// borrowed noise from:
+// <https://www.shadertoy.com/view/4dS3Wd>
+// By Morgan McGuire @morgan3d, http://graphicscodex.com
+//
+float hash(float n) { return fract(sin(n) * 1e4); }
+float hash(vec2 p) { return fract(1e4 * sin(17.0 * p.x + p.y * 0.1) * (0.1 + abs(sin(p.y * 13.0 + p.x)))); }
+
+float noise(float x) {
+ float i = floor(x);
+ float f = fract(x);
+ float u = f * f * (3.0 - 2.0 * f);
+ return mix(hash(i), hash(i + 1.0), u);
+}
+
+float noise(vec2 x) {
+ vec2 i = floor(x);
+ vec2 f = fract(x);
+
+ // Four corners in 2D of a tile
+ float a = hash(i);
+ float b = hash(i + vec2(1.0, 0.0));
+ float c = hash(i + vec2(0.0, 1.0));
+ float d = hash(i + vec2(1.0, 1.0));
+
+ // Simple 2D lerp using smoothstep envelope between the values.
+ // return vec3(mix(mix(a, b, smoothstep(0.0, 1.0, f.x)),
+ // mix(c, d, smoothstep(0.0, 1.0, f.x)),
+ // smoothstep(0.0, 1.0, f.y)));
+
+ // Same code, with the clamps in smoothstep and common subexpressions
+ // optimized away.
+ vec2 u = f * f * (3.0 - 2.0 * f);
+ return mix(a, b, u.x) + (c - a) * u.y * (1.0 - u.x) + (d - b) * u.x * u.y;
+}
+
+//=============================
+
void main()
{
//this is the one of the rare spots where diffuseRect contains linear color values (not sRGB)
- vec4 diff = texture2DRect(diffuseRect, vary_fragcoord);
- //diff.rgb = pow(diff.rgb, vec3(display_gamma));
+ vec4 diff = texture2D(diffuseRect, vary_fragcoord);
diff.rgb = linear_to_srgb(diff.rgb);
+ 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;
frag_color = diff;
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl
index 058941bfb2..a79f644aef 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl
@@ -33,7 +33,7 @@ out vec4 frag_color;
#define frag_color gl_FragColor
#endif
-uniform sampler2DRect diffuseRect;
+uniform sampler2D diffuseRect;
uniform sampler2D bloomMap;
uniform vec2 screen_res;
@@ -41,9 +41,9 @@ VARYING vec2 vary_fragcoord;
void main()
{
- vec4 diff = texture2DRect(diffuseRect, vary_fragcoord.xy);
+ vec4 diff = texture2D(diffuseRect, vary_fragcoord.xy);
- vec4 bloom = texture2D(bloomMap, vary_fragcoord.xy/screen_res);
+ vec4 bloom = texture2D(bloomMap, vary_fragcoord.xy);
frag_color = diff + bloom;
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoTCV.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoTCV.glsl
index bd0cb50464..4d24b4de9a 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoTCV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoTCV.glsl
@@ -23,8 +23,6 @@
* $/LicenseInfo$
*/
-uniform mat4 modelview_projection_matrix;
-
ATTRIBUTE vec3 position;
VARYING vec2 vary_fragcoord;
@@ -34,7 +32,7 @@ uniform vec2 screen_res;
void main()
{
//transform vertex
- vec4 pos = modelview_projection_matrix * vec4(position.xyz, 1.0);
+ vec4 pos = vec4(position.xyz, 1.0);
gl_Position = pos;
- vary_fragcoord = (pos.xy*0.5+0.5)*screen_res;
+ vary_fragcoord = (pos.xy*0.5+0.5);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredV.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredV.glsl
index 8edf5b2723..86f0077edb 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredV.glsl
@@ -23,8 +23,6 @@
* $/LicenseInfo$
*/
-uniform mat4 modelview_projection_matrix;
-
ATTRIBUTE vec3 position;
VARYING vec2 vary_fragcoord;
@@ -37,8 +35,8 @@ uniform vec2 screen_res;
void main()
{
//transform vertex
- vec4 pos = modelview_projection_matrix * vec4(position.xyz, 1.0);
+ vec4 pos = vec4(position.xyz, 1.0);
gl_Position = pos;
vary_tc = (pos.xy*0.5+0.5)*tc_scale;
- vary_fragcoord = (pos.xy*0.5+0.5)*screen_res;
+ vary_fragcoord = (pos.xy*0.5+0.5);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl
index cf994d3547..8111f43c28 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl
@@ -31,9 +31,9 @@ out vec4 frag_color;
#define frag_color gl_FragColor
#endif
-uniform sampler2DRect depthMap;
-uniform sampler2DRect normalMap;
-uniform sampler2DRect giLightMap;
+uniform sampler2D depthMap;
+uniform sampler2D normalMap;
+uniform sampler2D giLightMap;
uniform sampler2D noiseMap;
uniform vec2 kern[32];
@@ -53,11 +53,11 @@ vec4 getPosition(vec2 pos_screen);
void main()
{
- vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz;
+ vec3 norm = texture2D(normalMap, vary_fragcoord.xy).xyz;
norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
vec3 pos = getPosition(vary_fragcoord.xy).xyz;
- vec3 ccol = texture2DRect(giLightMap, vary_fragcoord.xy).rgb;
+ vec3 ccol = texture2D(giLightMap, vary_fragcoord.xy).rgb;
vec2 dlt = kern_scale * delta/(1.0+norm.xy*norm.xy);
dlt /= max(-pos.z*dist_factor, 1.0);
float defined_weight = kern[0].x;
@@ -66,7 +66,7 @@ void main()
for (int i = 0; i < kern_length; i++)
{
vec2 tc = vary_fragcoord.xy + kern[i].y*dlt;
- vec3 sampNorm = texture2DRect(normalMap, tc.xy).xyz;
+ vec3 sampNorm = texture2D(normalMap, tc.xy).xyz;
sampNorm = vec3((sampNorm.xy-0.5)*2.0,sampNorm.z); // unpack norm
float d = dot(norm.xyz, sampNorm);
@@ -77,7 +77,7 @@ void main()
samppos -= pos;
if (dot(samppos,samppos) < -0.05*pos.z)
{
- col += texture2DRect(giLightMap, tc).rgb*kern[i].x;
+ col += texture2D(giLightMap, tc).rgb*kern[i].x;
defined_weight += kern[i].x;
}
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class1/deferred/reflectionProbeF.glsl
new file mode 100644
index 0000000000..2ffe688524
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/reflectionProbeF.glsl
@@ -0,0 +1,64 @@
+/**
+ * @file class1/deferred/reflectionProbeF.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$
+ */
+
+// 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,
+ 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,
+ vec2 tc, vec3 pos, vec3 norm, float glossiness)
+{
+ sampleReflectionProbes(ambenv, glossenv,
+ pos, norm, glossiness, false);
+}
+
+vec4 sampleReflectionProbesDebug(vec3 pos)
+{
+ //output green to debug display
+ return vec4(0, 1, 0, 0.5);
+}
+
+void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv,
+ vec3 pos, vec3 norm, float glossiness, float envIntensity)
+{
+ ambenv = vec3(1,0,1);
+ glossenv = vec3(1,0,1);
+ legacyenv = vec3(1,0,1);
+}
+
+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)
+{
+
+}
+
diff --git a/indra/newview/app_settings/shaders/class1/objects/indexedTextureF.glsl b/indra/newview/app_settings/shaders/class1/deferred/screenSpaceReflPostF.glsl
index 254c1d4fc2..df16e7f0e7 100644
--- a/indra/newview/app_settings/shaders/class1/objects/indexedTextureF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/screenSpaceReflPostF.glsl
@@ -1,33 +1,33 @@
-/**
- * @file fullbrightF.glsl
+/**
+ * @file class3/deferred/screenSpaceReflPostF.glsl
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2007, 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$
*/
-
-
+ // debug stub
+
+out vec4 frag_color;
void main()
{
- fullbright_lighting();
+ frag_color = vec4(0.5, 0.4, 0.1, 0);
}
-
diff --git a/indra/newview/app_settings/shaders/class3/deferred/sunLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/screenSpaceReflPostV.glsl
index bc5eb5181d..966e7e1cbb 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/sunLightV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/screenSpaceReflPostV.glsl
@@ -1,41 +1,39 @@
-/**
- * @file sunLightV.glsl
+/**
+ * @file class3/deferred/screenSpaceReflPostV.glsl
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2007, 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$
*/
-uniform mat4 modelview_projection_matrix;
-
ATTRIBUTE vec3 position;
-VARYING vec2 vary_fragcoord;
-
uniform vec2 screen_res;
+VARYING vec2 vary_fragcoord;
+
void main()
{
//transform vertex
- vec4 pos = modelview_projection_matrix * vec4(position.xyz, 1.0);
+ vec4 pos = vec4(position.xyz, 1.0);
gl_Position = pos;
-
- vary_fragcoord = (pos.xy * 0.5 + 0.5)*screen_res;
+
+ vary_fragcoord = pos.xy * 0.5 + 0.5;
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/screenSpaceReflUtil.glsl b/indra/newview/app_settings/shaders/class1/deferred/screenSpaceReflUtil.glsl
new file mode 100644
index 0000000000..d054305767
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/screenSpaceReflUtil.glsl
@@ -0,0 +1,37 @@
+/**
+ * @file class3/deferred/screenSpaceReflUtil.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2007, 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$
+ */
+
+// debug stub
+
+float random (vec2 uv)
+{
+ return 0;
+}
+
+float tapScreenSpaceReflection(int totalSamples, vec2 tc, vec3 viewPos, vec3 n, inout vec4 collectedColor, sampler2D source)
+{
+ collectedColor = vec4(0);
+ return 0;
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaBlendF.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaBlendF.glsl
deleted file mode 100644
index 44f2a73e1f..0000000000
--- a/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaBlendF.glsl
+++ /dev/null
@@ -1,55 +0,0 @@
-/**
- * @file shadowAlphaMaskF.glsl
- *
- * $LicenseInfo:firstyear=2011&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2011, 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 sampler2D diffuseMap;
-
-#if !defined(DEPTH_CLAMP)
-VARYING float pos_zd2;
-#endif
-
-VARYING float pos_w;
-
-VARYING float target_pos_x;
-VARYING vec4 vertex_color;
-VARYING vec2 vary_texcoord0;
-
-void main()
-{
- float alpha = diffuseLookup(vary_texcoord0.xy).a * vertex_color.a;
-
- frag_color = vec4(alpha, alpha, alpha, 1);
-
-#if !defined(DEPTH_CLAMP)
- gl_FragDepth = max(pos_zd2/pos_w+0.5, 0.0);
-#endif
-}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaBlendV.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaBlendV.glsl
deleted file mode 100644
index f45c343066..0000000000
--- a/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaBlendV.glsl
+++ /dev/null
@@ -1,67 +0,0 @@
-/**
- * @file shadowAlphaMaskV.glsl
- *
- * $LicenseInfo:firstyear=2011&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2011, 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$
- */
-
-uniform mat4 texture_matrix0;
-uniform mat4 modelview_projection_matrix;
-uniform float shadow_target_width;
-
-ATTRIBUTE vec3 position;
-ATTRIBUTE vec4 diffuse_color;
-ATTRIBUTE vec2 texcoord0;
-
-#if !defined(DEPTH_CLAMP)
-VARYING float pos_zd2;
-#endif
-
-VARYING float pos_w;
-
-VARYING float target_pos_x;
-VARYING vec4 vertex_color;
-VARYING vec2 vary_texcoord0;
-
-void passTextureIndex();
-
-void main()
-{
- //transform vertex
- vec4 pre_pos = vec4(position.xyz, 1.0);
- vec4 pos = modelview_projection_matrix * pre_pos;
- target_pos_x = 0.5 * (shadow_target_width - 1.0) * pos.x;
-
- pos_w = pos.w;
-
-#if !defined(DEPTH_CLAMP)
- pos_zd2 = pos.z * 0.5;
-
- gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
-#else
- gl_Position = pos;
-#endif
-
- passTextureIndex();
-
- vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
- vertex_color = diffuse_color;
-}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskF.glsl
index 9b8df0a5a4..68e9addc1b 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskF.glsl
@@ -43,32 +43,30 @@ void main()
{
float alpha = diffuseLookup(vary_texcoord0.xy).a;
- // mask cutoff 0 -> no shadow SL-11051
- if (minimum_alpha == 0)
+ if (alpha < minimum_alpha)
{
discard;
}
+#if !defined(GLTF)
+
#if !defined(IS_FULLBRIGHT)
alpha *= vertex_color.a;
#endif
- if (alpha < 0.05) // treat as totally transparent
- {
- discard;
- }
+ if (alpha < 0.05) // treat as totally transparent
+ {
+ discard;
+ }
- if (alpha < 0.88) // treat as semi-transparent
- {
- if (fract(0.5*floor(target_pos_x / post_pos.w )) < 0.25)
- {
- discard;
- }
- }
+ if (alpha < 0.88) // treat as semi-transparent
+ {
+ if (fract(0.5*floor(target_pos_x / post_pos.w )) < 0.25)
+ {
+ discard;
+ }
+ }
+#endif
frag_color = vec4(1,1,1,1);
-
-#if !defined(DEPTH_CLAMP)
- gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0);
-#endif
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskSkinnedV.glsl
index 2b17aea75a..61c9e60744 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskSkinnedV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskSkinnedV.glsl
@@ -57,11 +57,7 @@ void main()
post_pos = pos;
-#if !defined(DEPTH_CLAMP)
- gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
-#else
gl_Position = pos;
-#endif
passTextureIndex();
diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskV.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskV.glsl
index b6a0f0b165..40f8fc9894 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskV.glsl
@@ -47,11 +47,7 @@ void main()
post_pos = pos;
-#if !defined(DEPTH_CLAMP)
- gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
-#else
gl_Position = pos;
-#endif
passTextureIndex();
diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowCubeV.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowCubeV.glsl
index 0e74d2eb8a..9608e89169 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/shadowCubeV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/shadowCubeV.glsl
@@ -27,10 +27,6 @@ uniform mat4 modelview_projection_matrix;
ATTRIBUTE vec3 position;
-#if !defined(DEPTH_CLAMP)
-VARYING vec4 post_pos;
-#endif
-
uniform vec3 box_center;
uniform vec3 box_size;
@@ -40,11 +36,5 @@ void main()
vec3 p = position*box_size+box_center;
vec4 pos = modelview_projection_matrix*vec4(p.xyz, 1.0);
-#if !defined(DEPTH_CLAMP)
- post_pos = pos;
-
- gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
-#else
gl_Position = pos;
-#endif
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl
index 1ea96918bb..406a7ef3b3 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl
@@ -25,20 +25,9 @@
/*[EXTRA_CODE_HERE]*/
-#ifdef DEFINE_GL_FRAGCOLOR
out vec4 frag_color;
-#else
-#define frag_color gl_FragColor
-#endif
-
-VARYING vec4 post_pos;
void main()
{
frag_color = vec4(1,1,1,1);
-
-#if !defined(DEPTH_CLAMP)
- gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0);
-#endif
-
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowSkinnedV.glsl
index bdf8e0854d..186ba49969 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/shadowSkinnedV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/shadowSkinnedV.glsl
@@ -28,8 +28,6 @@ uniform mat4 projection_matrix;
ATTRIBUTE vec3 position;
-VARYING vec4 post_pos;
-
mat4 getObjectSkinnedTransform();
void main()
@@ -41,12 +39,5 @@ void main()
vec4 pos = (mat*vec4(position.xyz, 1.0));
pos = projection_matrix*pos;
- post_pos = pos;
-
-#if !defined(DEPTH_CLAMP)
- gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
-#else
gl_Position = pos;
-#endif
-
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowUtil.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowUtil.glsl
index 4134220306..cd49202f89 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/shadowUtil.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/shadowUtil.glsl
@@ -23,14 +23,20 @@
* $/LicenseInfo$
*/
-uniform sampler2DRect normalMap;
-uniform sampler2DRect depthMap;
+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/app_settings/shaders/class1/deferred/shadowV.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl
index 72bd0f0f34..bd62954ff8 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl
@@ -25,21 +25,10 @@
uniform mat4 modelview_projection_matrix;
-ATTRIBUTE vec3 position;
-
-VARYING vec4 post_pos;
+in vec3 position;
void main()
{
//transform vertex
- vec4 pos = modelview_projection_matrix*vec4(position.xyz, 1.0);
-
- post_pos = pos;
-
-#if !defined(DEPTH_CLAMP)
- gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
-#else
- gl_Position = pos;
-#endif
-
+ gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl b/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl
index de22312d3c..849e1c4893 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl
@@ -46,6 +46,8 @@ out vec4 frag_data[3];
// The fragment shader for the sky
/////////////////////////////////////////////////////////////////////////
+VARYING vec3 vary_HazeColor;
+
vec3 rainbow(float d)
{
// 'Interesting' values of d are -0.75 .. -0.825, i.e. when view vec nearly opposite of sun vec
@@ -82,7 +84,7 @@ void main()
// the fragment) if the sky wouldn't show up because the clouds
// are fully opaque.
- vec4 color = vary_HazeColor;
+ vec3 color = vary_HazeColor;
float rel_pos_lightnorm = vary_LightNormPosDot;
float optic_d = rel_pos_lightnorm;
@@ -95,7 +97,7 @@ void main()
// Gamma correct for WL (soft clip effect).
frag_data[0] = vec4(color.rgb, 1.0);
frag_data[1] = vec4(0.0,0.0,0.0,0.0);
- frag_data[2] = vec4(0.0,0.0,0.0,1.0); //1.0 in norm.w masks off fog
+ frag_data[2] = vec4(0.0,0.0,0.0,GBUFFER_FLAG_SKIP_ATMOS); //1.0 in norm.w masks off fog
gl_FragDepth = 0.99999f;
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl b/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl
index 6db4690bff..3b24311f2b 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl
@@ -32,19 +32,19 @@ ATTRIBUTE vec3 position;
///////////////////////////////////////////////////////////////////////////////
// Output parameters
-VARYING vec4 vary_HazeColor;
+VARYING vec3 vary_HazeColor;
VARYING float vary_LightNormPosDot;
// Inputs
uniform vec3 camPosLocal;
-uniform vec4 lightnorm;
-uniform vec4 sunlight_color;
-uniform vec4 moonlight_color;
+uniform vec3 lightnorm;
+uniform vec3 sunlight_color;
+uniform vec3 moonlight_color;
uniform int sun_up_factor;
-uniform vec4 ambient_color;
-uniform vec4 blue_horizon;
-uniform vec4 blue_density;
+uniform vec3 ambient_color;
+uniform vec3 blue_horizon;
+uniform vec3 blue_density;
uniform float haze_horizon;
uniform float haze_density;
@@ -53,11 +53,9 @@ uniform float density_multiplier;
uniform float distance_multiplier;
uniform float max_y;
-uniform vec4 glow;
+uniform vec3 glow;
uniform float sun_moon_glow_factor;
-uniform vec4 cloud_color;
-
// NOTE: Keep these in sync!
// indra\newview\app_settings\shaders\class1\deferred\skyV.glsl
// indra\newview\app_settings\shaders\class1\deferred\cloudsV.glsl
@@ -91,16 +89,16 @@ void main()
vary_LightNormPosDot = rel_pos_lightnorm_dot;
// Initialize temp variables
- vec4 sunlight = (sun_up_factor == 1) ? sunlight_color : moonlight_color;
+ vec3 sunlight = (sun_up_factor == 1) ? sunlight_color : moonlight_color;
// Sunlight attenuation effect (hue and brightness) due to atmosphere
// this is used later for sunlight modulation at various altitudes
- vec4 light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y);
+ vec3 light_atten = (blue_density + vec3(haze_density * 0.25)) * (density_multiplier * max_y);
// Calculate relative weights
- vec4 combined_haze = abs(blue_density) + vec4(abs(haze_density));
- vec4 blue_weight = blue_density / combined_haze;
- vec4 haze_weight = haze_density / combined_haze;
+ vec3 combined_haze = abs(blue_density) + vec4(abs(haze_density));
+ vec3 blue_weight = blue_density / combined_haze;
+ vec3 haze_weight = haze_density / combined_haze;
// Compute sunlight from rel_pos & lightnorm (for long rays like sky)
float off_axis = 1.0 / max(1e-6, max(0., rel_pos_norm.y) + lightnorm.y);
@@ -129,20 +127,20 @@ void main()
haze_glow = (sun_moon_glow_factor < 1.0) ? 0.0 : (sun_moon_glow_factor * (haze_glow + 0.25));
// Haze color above cloud
- vec4 color = (blue_horizon * blue_weight * (sunlight + ambient_color)
+ vec3 color = (blue_horizon * blue_weight * (sunlight + ambient_color)
+ (haze_horizon * haze_weight) * (sunlight * haze_glow + ambient_color));
// Final atmosphere additive
color *= (1. - combined_haze);
// Increase ambient when there are more clouds
- vec4 ambient = ambient_color + max(vec4(0), (1. - ambient_color)) * cloud_shadow * 0.5;
+ vec3 ambient = ambient_color + max(vec3(0), (1. - ambient_color)) * cloud_shadow * 0.5;
// Dim sunlight by cloud shadow percentage
sunlight *= max(0.0, (1. - cloud_shadow));
// Haze color below cloud
- vec4 add_below_cloud = (blue_horizon * blue_weight * (sunlight + ambient)
+ vec3 add_below_cloud = (blue_horizon * blue_weight * (sunlight + ambient)
+ (haze_horizon * haze_weight) * (sunlight * haze_glow + ambient));
// Attenuate cloud color by atmosphere
diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
index 7f2c603f87..152402907b 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
@@ -34,11 +34,11 @@ out vec4 frag_color;
#define frag_color gl_FragColor
#endif
-uniform sampler2DRect diffuseRect;
-uniform sampler2DRect specularRect;
-uniform sampler2DRect normalMap;
-uniform sampler2DRect lightMap;
-uniform sampler2DRect depthMap;
+uniform sampler2D diffuseRect;
+uniform sampler2D specularRect;
+uniform sampler2D normalMap;
+uniform sampler2D lightMap;
+uniform sampler2D depthMap;
uniform samplerCube environmentMap;
uniform sampler2D lightFunc;
@@ -58,6 +58,7 @@ uniform vec2 screen_res;
vec3 getNorm(vec2 pos_screen);
vec4 getPositionWithDepth(vec2 pos_screen, float depth);
+float getDepth(vec2 pos_screen);
void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, out vec3 sunlit, out vec3 amblit, out vec3 additive, out vec3 atten, bool use_ao);
float getAmbientClamp();
@@ -76,9 +77,9 @@ vec4 applyWaterFogView(vec3 pos, vec4 color);
void main()
{
vec2 tc = vary_fragcoord.xy;
- float depth = texture2DRect(depthMap, tc.xy).r;
+ float depth = getDepth(tc);
vec4 pos = getPositionWithDepth(tc, depth);
- vec4 norm = texture2DRect(normalMap, tc);
+ vec4 norm = texture2D(normalMap, tc);
float envIntensity = norm.z;
norm.xyz = getNorm(tc);
@@ -87,12 +88,12 @@ void main()
float light_gamma = 1.0/1.3;
da = pow(da, light_gamma);
- vec4 diffuse = texture2DRect(diffuseRect, tc);
+ vec4 diffuse = texture2D(diffuseRect, tc);
//convert to gamma space
diffuse.rgb = linear_to_srgb(diffuse.rgb); // SL-14035
- vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy);
+ vec4 spec = texture2D(specularRect, vary_fragcoord.xy);
vec3 color = vec3(0);
float bloom = 0.0;
{
@@ -142,7 +143,7 @@ void main()
color = mix(color.rgb, reflected_color, envIntensity);
}
- if (norm.w < 0.5)
+ if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_ATMOS))
{
color = mix(atmosFragLighting(color, additive, atten), fullbrightAtmosTransportFrag(color, additive, atten), diffuse.a);
color = mix(scaleSoftClipFrag(color), fullbrightScaleSoftClip(color), diffuse.a);
@@ -156,12 +157,6 @@ void main()
}
-// linear debuggables
-//color.rgb = vec3(final_da);
-//color.rgb = vec3(ambient);
-//color.rgb = vec3(scol);
-//color.rgb = diffuse_srgb.rgb;
-
// convert to linear as fullscreen lights need to sum in linear colorspace
// and will be gamma (re)corrected downstream...
diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightV.glsl
index 8891315e15..23ad332db4 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/softenLightV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightV.glsl
@@ -22,8 +22,6 @@
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
-
-uniform mat4 modelview_projection_matrix;
ATTRIBUTE vec3 position;
@@ -36,10 +34,10 @@ VARYING vec2 vary_fragcoord;
void main()
{
//transform vertex
- vec4 pos = modelview_projection_matrix * vec4(position.xyz, 1.0);
+ vec4 pos = vec4(position.xyz, 1.0);
gl_Position = pos;
// appease OSX GLSL compiler/linker by touching all the varyings we said we would
setAtmosAttenuation(vec3(1));
setAdditiveColor(vec3(0));
- vary_fragcoord = (pos.xy*0.5+0.5)*screen_res;
+ vary_fragcoord = (pos.xy*0.5+0.5);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl
index 694b19cdfb..0376f42319 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl
@@ -36,10 +36,10 @@ out vec4 frag_color;
//class 1 -- no shadows
-uniform sampler2DRect diffuseRect;
-uniform sampler2DRect specularRect;
-uniform sampler2DRect depthMap;
-uniform sampler2DRect normalMap;
+uniform sampler2D diffuseRect;
+uniform sampler2D specularRect;
+uniform sampler2D depthMap;
+uniform sampler2D normalMap;
uniform samplerCube environmentMap;
uniform sampler2D noiseMap;
uniform sampler2D projectionMap;
@@ -137,7 +137,6 @@ void main()
vec4 frag = vary_fragcoord;
frag.xyz /= frag.w;
frag.xyz = frag.xyz*0.5+0.5;
- frag.xy *= screen_res;
vec3 pos = getPosition(frag.xy).xyz;
vec3 lv = trans_center.xyz-pos.xyz;
@@ -148,7 +147,7 @@ void main()
discard;
}
- vec3 norm = texture2DRect(normalMap, frag.xy).xyz;
+ vec3 norm = texture2D(normalMap, frag.xy).xyz;
float envIntensity = norm.z;
norm = getNorm(frag.xy);
norm = normalize(norm);
@@ -176,13 +175,13 @@ void main()
lv = normalize(lv);
float da = dot(norm, lv);
- vec3 diff_tex = texture2DRect(diffuseRect, frag.xy).rgb;
+ vec3 diff_tex = texture2D(diffuseRect, frag.xy).rgb;
//light shaders output linear and are gamma corrected later in postDeferredGammaCorrectF.glsl
diff_tex.rgb = srgb_to_linear(diff_tex.rgb);
- vec4 spec = texture2DRect(specularRect, frag.xy);
+ vec4 spec = texture2D(specularRect, frag.xy);
- float noise = texture2D(noiseMap, frag.xy/128.0).b;
+ float noise = texture2D(noiseMap, frag.xy).b;
vec3 dlit = vec3(0, 0, 0);
if (proj_tc.z > 0.0 &&
diff --git a/indra/newview/app_settings/shaders/class1/deferred/starsF.glsl b/indra/newview/app_settings/shaders/class1/deferred/starsF.glsl
index bac79a9fdc..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;
@@ -46,8 +45,13 @@ float twinkle(){
return abs(d);
}
+// See:
+// ALM off: class1/environment/starsF.glsl
+// ALM on : class1/deferred/starsF.glsl
void main()
{
+ // camera above water: class1\deferred\starsF.glsl
+ // camera below water: class1\environment\starsF.glsl
vec4 col_a = texture2D(diffuseMap, vary_texcoord0.xy);
vec4 col_b = texture2D(diffuseMap, vary_texcoord0.xy);
vec4 col = mix(col_b, col_a, blend_factor);
@@ -60,8 +64,8 @@ void main()
frag_data[0] = col;
frag_data[1] = vec4(0.0f);
- frag_data[2] = vec4(0.0, 1.0, 0.0, 1.0);
+ frag_data[2] = vec4(0.0, 1.0, 0.0, GBUFFER_FLAG_SKIP_ATMOS);
- gl_FragDepth = 0.99995f;
+ gl_FragDepth = LL_SHADER_CONST_STAR_DEPTH; // SL-14113 Moon Haze -- Stars need to depth test behind the moon
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunDiscF.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunDiscF.glsl
index b2fa5d8a25..4ab8747629 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/sunDiscF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/sunDiscF.glsl
@@ -57,7 +57,7 @@ void main()
frag_data[0] = c;
frag_data[1] = vec4(0.0f);
- frag_data[2] = vec4(0.0, 1.0, 0.0, 1.0);
+ frag_data[2] = vec4(0.0, 1.0, 0.0, GBUFFER_FLAG_SKIP_ATMOS);
gl_FragDepth = 0.999988f;
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl
index 15f141cbe5..d9a0b6c702 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl
@@ -35,7 +35,7 @@ out vec4 frag_color;
//class 1 -- no shadow, SSAO only
-uniform sampler2DRect normalMap;
+uniform sampler2D normalMap;
// Inputs
VARYING vec2 vary_fragcoord;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightV.glsl
index 473d6df8fa..9d70b9d98d 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/sunLightV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightV.glsl
@@ -22,8 +22,6 @@
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
-
-uniform mat4 modelview_projection_matrix;
ATTRIBUTE vec3 position;
@@ -34,8 +32,8 @@ uniform vec2 screen_res;
void main()
{
//transform vertex
- vec4 pos = modelview_projection_matrix * vec4(position.xyz, 1.0);
+ vec4 pos = vec4(position.xyz, 1.0);
gl_Position = pos;
- vary_fragcoord = (pos.xy * 0.5 + 0.5)*screen_res;
+ vary_fragcoord = (pos.xy * 0.5 + 0.5);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl
index 6b6eed9db8..d6c14c48c9 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl
@@ -63,6 +63,6 @@ void main()
frag_data[0] = outColor;
frag_data[1] = vec4(0.0,0.0,0.0,-1.0);
vec3 nvn = normalize(vary_normal);
- frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, 0.0);
+ frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, GBUFFER_FLAG_HAS_ATMOS);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl
index 89e354558a..dc0e5b0ce3 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl
@@ -52,5 +52,5 @@ void main()
frag_data[0] = vec4(vertex_color.rgb*col.rgb, 0.0);
frag_data[1] = vec4(0,0,0,0);
vec3 nvn = normalize(vary_normal);
- frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, 0.0);
+ frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, GBUFFER_FLAG_HAS_ATMOS);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/treeShadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/treeShadowF.glsl
index e34d75ba1d..c850a39d6f 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/treeShadowF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/treeShadowF.glsl
@@ -25,18 +25,14 @@
/*[EXTRA_CODE_HERE]*/
-#ifdef DEFINE_GL_FRAGCOLOR
+
out vec4 frag_color;
-#else
-#define frag_color gl_FragColor
-#endif
uniform float minimum_alpha;
uniform sampler2D diffuseMap;
-VARYING vec4 post_pos;
-VARYING vec2 vary_texcoord0;
+in vec2 vary_texcoord0;
void main()
{
@@ -48,6 +44,4 @@ void main()
}
frag_color = vec4(1,1,1,1);
-
- gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/treeShadowSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/deferred/treeShadowSkinnedV.glsl
index d9ca6d3a46..5a7cf369b5 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/treeShadowSkinnedV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/treeShadowSkinnedV.glsl
@@ -30,8 +30,7 @@ uniform mat4 projection_matrix;
ATTRIBUTE vec3 position;
ATTRIBUTE vec2 texcoord0;
-VARYING vec4 post_pos;
-VARYING vec2 vary_texcoord0;
+out vec2 vary_texcoord0;
mat4 getObjectSkinnedTransform();
@@ -43,11 +42,7 @@ void main()
mat = modelview_matrix * mat;
vec4 pos = mat * vec4(position.xyz, 1.0);
- pos = projection_matrix * pos;
-
- post_pos = pos;
-
- gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
+ gl_Position = projection_matrix * pos;
vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/treeShadowV.glsl b/indra/newview/app_settings/shaders/class1/deferred/treeShadowV.glsl
index e472a75304..3102c870fc 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/treeShadowV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/treeShadowV.glsl
@@ -26,20 +26,15 @@
uniform mat4 texture_matrix0;
uniform mat4 modelview_projection_matrix;
-ATTRIBUTE vec3 position;
-ATTRIBUTE vec2 texcoord0;
+in vec3 position;
+in vec2 texcoord0;
-VARYING vec4 post_pos;
-VARYING vec2 vary_texcoord0;
+out vec2 vary_texcoord0;
void main()
{
//transform vertex
- vec4 pos = modelview_projection_matrix*vec4(position.xyz, 1.0);
-
- post_pos = pos;
-
- gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
+ gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0);
vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/underWaterF.glsl b/indra/newview/app_settings/shaders/class1/deferred/underWaterF.glsl
index 9a5debb3c1..14c337e608 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/underWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/underWaterF.glsl
@@ -78,5 +78,5 @@ void main()
frag_data[0] = vec4(fb.rgb, 1.0); // diffuse
frag_data[1] = vec4(0.5,0.5,0.5, 0.95); // speccolor*spec, spec
- frag_data[2] = vec4(encode_normal(wavef), 0.0, 0.0); // normalxyz, env intens, atmo kill
+ frag_data[2] = vec4(encode_normal(wavef), 0.0, GBUFFER_FLAG_HAS_ATMOS); // normalxyz, env intens, flags (atmo kill)
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl
index a157e9c017..876422f86b 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl
@@ -22,163 +22,15 @@
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
-
-#extension GL_ARB_texture_rectangle : enable
-/*[EXTRA_CODE_HERE]*/
+// debug stub
+out vec4 frag_data[4];
-#ifdef DEFINE_GL_FRAGCOLOR
-out vec4 frag_data[3];
-#else
-#define frag_data gl_FragData
-#endif
-
-vec3 scaleSoftClip(vec3 inColor);
-vec3 atmosTransport(vec3 inColor);
-
-uniform sampler2D bumpMap;
-uniform sampler2D bumpMap2;
-uniform float blend_factor;
-uniform sampler2D screenTex;
-uniform sampler2D refTex;
-uniform float sunAngle;
-uniform float sunAngle2;
-uniform vec3 lightDir;
-uniform vec3 specular;
-uniform float lightExp;
-uniform float refScale;
-uniform float kd;
-uniform vec2 screenRes;
-uniform vec3 normScale;
-uniform float fresnelScale;
-uniform float fresnelOffset;
-uniform float blurMultiplier;
-uniform vec2 screen_res;
-uniform mat4 norm_mat; //region space to screen space
-uniform int water_edge;
-
-//bigWave is (refCoord.w, view.w);
-VARYING vec4 refCoord;
-VARYING vec4 littleWave;
-VARYING vec4 view;
-VARYING vec4 vary_position;
-
-vec2 encode_normal(vec3 n);
-vec3 scaleSoftClip(vec3 l);
-vec3 srgb_to_linear(vec3 c);
-vec3 linear_to_srgb(vec3 c);
-
-vec3 BlendNormal(vec3 bump1, vec3 bump2)
+void main()
{
- vec3 n = mix(bump1, bump2, blend_factor);
- return n;
-}
-
-void main()
-{
- vec4 color;
- float dist = length(view.xyz);
-
- //normalize view vector
- vec3 viewVec = normalize(view.xyz);
-
- //get wave normals
- vec3 wave1_a = texture2D(bumpMap, vec2(refCoord.w, view.w)).xyz*2.0-1.0;
- vec3 wave2_a = texture2D(bumpMap, littleWave.xy).xyz*2.0-1.0;
- vec3 wave3_a = texture2D(bumpMap, littleWave.zw).xyz*2.0-1.0;
-
-
- vec3 wave1_b = texture2D(bumpMap2, vec2(refCoord.w, view.w)).xyz*2.0-1.0;
- vec3 wave2_b = texture2D(bumpMap2, littleWave.xy).xyz*2.0-1.0;
- vec3 wave3_b = texture2D(bumpMap2, littleWave.zw).xyz*2.0-1.0;
-
- vec3 wave1 = BlendNormal(wave1_a, wave1_b);
- vec3 wave2 = BlendNormal(wave2_a, wave2_b);
- vec3 wave3 = BlendNormal(wave3_a, wave3_b);
-
- //get base fresnel components
-
- vec3 df = vec3(
- dot(viewVec, wave1),
- dot(viewVec, (wave2 + wave3) * 0.5),
- dot(viewVec, wave3)
- ) * fresnelScale + fresnelOffset;
- df *= df;
-
- vec2 distort = (refCoord.xy/refCoord.z) * 0.5 + 0.5;
-
- float dist2 = dist;
- dist = max(dist, 5.0);
-
- float dmod = sqrt(dist);
-
- vec2 dmod_scale = vec2(dmod*dmod, dmod);
-
- //get reflected color
- vec2 refdistort1 = wave1.xy*normScale.x;
- vec2 refvec1 = distort+refdistort1/dmod_scale;
- vec4 refcol1 = texture2D(refTex, refvec1);
-
- vec2 refdistort2 = wave2.xy*normScale.y;
- vec2 refvec2 = distort+refdistort2/dmod_scale;
- vec4 refcol2 = texture2D(refTex, refvec2);
-
- vec2 refdistort3 = wave3.xy*normScale.z;
- vec2 refvec3 = distort+refdistort3/dmod_scale;
- vec4 refcol3 = texture2D(refTex, refvec3);
-
- vec4 refcol = refcol1 + refcol2 + refcol3;
- float df1 = df.x + df.y + df.z;
- refcol *= df1 * 0.333;
-
- vec3 wavef = (wave1 + wave2 * 0.4 + wave3 * 0.6) * 0.5;
- wavef.z *= max(-viewVec.z, 0.1);
- wavef = normalize(wavef);
-
- float df2 = dot(viewVec, wavef) * fresnelScale+fresnelOffset;
-
- vec2 refdistort4 = wavef.xy*0.125;
- refdistort4.y -= abs(refdistort4.y);
- vec2 refvec4 = distort+refdistort4/dmod;
- float dweight = min(dist2*blurMultiplier, 1.0);
- vec4 baseCol = texture2D(refTex, refvec4);
-
- refcol = mix(baseCol*df2, refcol, dweight);
-
- //get specular component
- float spec = clamp(dot(lightDir, (reflect(viewVec,wavef))),0.0,1.0);
-
- //harden specular
- spec = pow(spec, 128.0);
-
- //figure out distortion vector (ripply)
- vec2 distort2 = distort+wavef.xy*refScale/max(dmod*df1, 1.0);
-
- vec4 fb = texture2D(screenTex, distort2);
-
- //mix with reflection
- // Note we actually want to use just df1, but multiplying by 0.999999 gets around an nvidia compiler bug
- color.rgb = mix(fb.rgb, refcol.rgb, df1 * 0.99999f);
-
- vec4 pos = vary_position;
-
- color.rgb += spec * specular;
-
- color.rgb = atmosTransport(color.rgb);
- color.rgb = scaleSoftClip(color.rgb);
-
- color.a = spec * sunAngle2;
-
- vec3 screenspacewavef = normalize((norm_mat*vec4(wavef, 1.0)).xyz);
-
- //frag_data[0] = color;
-
- // TODO: The non-obvious assignment below is copied from the pre-EEP WL shader code
- // Unfortunately, fixing it causes a mismatch for EEP, and so it remains... for now
- // SL-12975 (unfix pre-EEP broken alpha)
- frag_data[0] = vec4(color.rgb, color); // Effectively, color.rgbr
-
-
- frag_data[1] = vec4(0); // speccolor, spec
- frag_data[2] = vec4(encode_normal(screenspacewavef.xyz), 0.05, 0);// normalxy, 0, 0
+ // emissive blue PBR material
+ frag_data[0] = vec4(0, 0, 0, 0);
+ frag_data[1] = vec4(0, 0, 0, 0);
+ frag_data[2] = vec4(1, 0, 0, GBUFFER_FLAG_HAS_PBR);
+ frag_data[3] = vec4(0, 0, 1, 0);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/waterV.glsl b/indra/newview/app_settings/shaders/class1/deferred/waterV.glsl
index 8863869e44..38276859a0 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/waterV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/waterV.glsl
@@ -70,7 +70,7 @@ void main()
d *= d;
oPosition = vec4(position, 1.0);
- oPosition.z = mix(oPosition.z, max(eyeVec.z*0.75, 0.0), d);
+// oPosition.z = mix(oPosition.z, max(eyeVec.z*0.75, 0.0), d); // SL-11589 remove "U" shaped horizon
vary_position = modelview_matrix * oPosition;
oPosition = modelViewProj * oPosition;
diff --git a/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl b/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl
index 36563982ba..4e535f7e18 100644
--- a/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl
+++ b/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl
@@ -33,7 +33,7 @@ out vec4 frag_color;
#define frag_color gl_FragColor
#endif
-uniform sampler2DRect diffuseMap;
+uniform sampler2D diffuseMap;
uniform float minLuminance;
uniform float maxExtractAlpha;
uniform vec3 lumWeights;
@@ -44,7 +44,7 @@ VARYING vec2 vary_texcoord0;
void main()
{
- vec4 col = texture2DRect(diffuseMap, vary_texcoord0.xy);
+ vec4 col = texture2D(diffuseMap, vary_texcoord0.xy);
/// CALCULATING LUMINANCE (Using NTSC lum weights)
/// http://en.wikipedia.org/wiki/Luma_%28video%29
float lum = smoothstep(minLuminance, minLuminance+1.0, dot(col.rgb, lumWeights ) );
diff --git a/indra/newview/app_settings/shaders/class1/effects/glowExtractV.glsl b/indra/newview/app_settings/shaders/class1/effects/glowExtractV.glsl
index 1396dc6973..db0662ad89 100644
--- a/indra/newview/app_settings/shaders/class1/effects/glowExtractV.glsl
+++ b/indra/newview/app_settings/shaders/class1/effects/glowExtractV.glsl
@@ -32,7 +32,7 @@ VARYING vec2 vary_texcoord0;
void main()
{
- gl_Position = modelview_projection_matrix * vec4(position, 1.0);
+ gl_Position = vec4(position, 1.0);
- vary_texcoord0.xy = texcoord0;
+ vary_texcoord0.xy = position.xy * 0.5 + 0.5;
}
diff --git a/indra/newview/app_settings/shaders/class1/effects/glowV.glsl b/indra/newview/app_settings/shaders/class1/effects/glowV.glsl
index cdb2281578..ea66e8271b 100644
--- a/indra/newview/app_settings/shaders/class1/effects/glowV.glsl
+++ b/indra/newview/app_settings/shaders/class1/effects/glowV.glsl
@@ -37,7 +37,7 @@ VARYING vec4 vary_texcoord3;
void main()
{
- gl_Position = modelview_projection_matrix * vec4(position, 1.0);
+ gl_Position = vec4(position, 1.0);
vary_texcoord0.xy = texcoord0 + glowDelta*(-3.5);
vary_texcoord1.xy = texcoord0 + glowDelta*(-2.5);
diff --git a/indra/newview/app_settings/shaders/class3/deferred/treeShadowF.glsl b/indra/newview/app_settings/shaders/class1/environment/moonF.glsl
index 41673d1669..a220971f06 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/treeShadowF.glsl
+++ b/indra/newview/app_settings/shaders/class1/environment/moonF.glsl
@@ -1,9 +1,9 @@
/**
- * @file treeShadowF.glsl
+ * @file class1/environment/moonF.glsl
*
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
+ * $LicenseInfo:firstyear=2021&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2005, Linden Research, Inc.
+ * Copyright (C) 2021, 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
@@ -23,37 +23,29 @@
* $/LicenseInfo$
*/
-/*[EXTRA_CODE_HERE]*/
-
#ifdef DEFINE_GL_FRAGCOLOR
out vec4 frag_color;
#else
#define frag_color gl_FragColor
#endif
-uniform float minimum_alpha;
-
-uniform sampler2D diffuseMap;
+uniform sampler2D tex0;
-VARYING vec4 pos;
VARYING vec2 vary_texcoord0;
-vec4 computeMoments(float d, float a);
-
+// See:
+// AS off: class1/environment/moonF.glsl
+// ALM off: class1/windlight/moonF.glsl
+// ALM on : class1/deferred/moonF.glsl
void main()
{
- float alpha = texture2D(diffuseMap, vary_texcoord0.xy).a;
-
- if (alpha < minimum_alpha)
- {
- discard;
- }
+ vec4 color = texture2D(tex0, vary_texcoord0.xy);
- frag_color = computeMoments(length(pos), 1.0);
-
-#if !defined(DEPTH_CLAMP)
- gl_FragDepth = max(pos.z/pos.w*0.5+0.5, 0.0);
-#endif
+ // SL-14113 Don't write to depth; prevent moon's quad from hiding stars which should be visible
+ // Moon texture has transparent pixels <0x55,0x55,0x55,0x00>
+ if (color.a <= 2./255.) // 0.00784
+ discard;
+ frag_color = color;
+ gl_FragDepth = LL_SHADER_CONST_CLOUD_MOON_DEPTH; // SL-14113 Moon is infront of stars
}
-
diff --git a/indra/newview/app_settings/shaders/class3/deferred/skyV.glsl b/indra/newview/app_settings/shaders/class1/environment/moonV.glsl
index 2eb222ada4..c00f202c23 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/skyV.glsl
+++ b/indra/newview/app_settings/shaders/class1/environment/moonV.glsl
@@ -1,9 +1,9 @@
/**
- * @file class3/deferred/skyV.glsl
+ * @file class1\environment\moonV.glsl
*
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
+ * $LicenseInfo:firstyear=2021&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2005, Linden Research, Inc.
+ * Copyright (C) 2021, 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
@@ -22,16 +22,17 @@
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
-
+
+uniform mat4 modelview_projection_matrix;
+
ATTRIBUTE vec3 position;
ATTRIBUTE vec2 texcoord0;
-VARYING vec2 vary_frag;
+VARYING vec2 vary_texcoord0;
void main()
{
- // pass through untransformed fullscreen pos at back of frustum for proper sky depth testing
- gl_Position = vec4(position.xy, 1.0f, 1.0);
- vary_frag = texcoord0;
+ gl_Position = modelview_projection_matrix * vec4(position, 1);
+ vary_texcoord0 = texcoord0;
}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/shadowAlphaBlendF.glsl b/indra/newview/app_settings/shaders/class1/environment/starsF.glsl
index 345c07a354..e1a9cc6387 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/shadowAlphaBlendF.glsl
+++ b/indra/newview/app_settings/shaders/class1/environment/starsF.glsl
@@ -1,9 +1,9 @@
/**
- * @file shadowAlphaMaskF.glsl
+ * @file class1/environment/starsF.glsl
*
- * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * $LicenseInfo:firstyear=2021&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2011, Linden Research, Inc.
+ * Copyright (C) 2021, 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
@@ -23,8 +23,6 @@
* $/LicenseInfo$
*/
-/*[EXTRA_CODE_HERE]*/
-
#ifdef DEFINE_GL_FRAGCOLOR
out vec4 frag_color;
#else
@@ -33,26 +31,21 @@ out vec4 frag_color;
uniform sampler2D diffuseMap;
-#if !defined(DEPTH_CLAMP)
-VARYING float pos_zd2;
-#endif
-
-VARYING float pos_w;
+uniform float custom_alpha;
-VARYING float target_pos_x;
VARYING vec4 vertex_color;
VARYING vec2 vary_texcoord0;
-VARYING vec3 pos;
-
-vec4 computeMoments(float depth, float a);
+// See:
+// ALM off: class1/environment/starsF.glsl
+// ALM on : class1/deferred/starsF.glsl
void main()
{
- float alpha = diffuseLookup(vary_texcoord0.xy).a * vertex_color.a;
-
- frag_color = computeMoments(length(pos), float a);
+ vec4 color = texture2D(diffuseMap, vary_texcoord0.xy);
+ color.rgb = pow(color.rgb, vec3(0.45));
+ color.rgb *= vertex_color.rgb;
+ color.a *= max(custom_alpha, vertex_color.a);
-#if !defined(DEPTH_CLAMP)
- gl_FragDepth = max(pos_zd2/pos_w+0.5, 0.0);
-#endif
+ frag_color = color;
+ gl_FragDepth = LL_SHADER_CONST_STAR_DEPTH; // SL-14113 Moon Haze -- Stars need to depth test behind the moon
}
diff --git a/indra/newview/app_settings/shaders/class3/windlight/advancedAtmoV.glsl b/indra/newview/app_settings/shaders/class1/environment/starsV.glsl
index 65bb00b1f6..6fcfec6b6a 100644
--- a/indra/newview/app_settings/shaders/class3/windlight/advancedAtmoV.glsl
+++ b/indra/newview/app_settings/shaders/class1/environment/starsV.glsl
@@ -1,9 +1,9 @@
/**
- * @file class3\wl\advancedAtmoV.glsl
+ * @file class1/environment/starsV.glsl
*
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
+ * $LicenseInfo:firstyear=2021&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2005, Linden Research, Inc.
+ * Copyright (C) 2021, 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
@@ -22,22 +22,20 @@
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
-
+
uniform mat4 modelview_projection_matrix;
ATTRIBUTE vec3 position;
+ATTRIBUTE vec4 diffuse_color;
+ATTRIBUTE vec2 texcoord0;
-// Inputs
-uniform vec3 camPosLocal;
-
-out vec3 view_dir;
+VARYING vec4 vertex_color;
+VARYING vec2 vary_texcoord0;
void main()
{
- // World / view / projection
gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
-
- // this will be normalized in the frag shader...
- view_dir = position.xyz - camPosLocal.xyz;
+ vary_texcoord0 = texcoord0;
+ vertex_color = diffuse_color;
}
diff --git a/indra/newview/app_settings/shaders/class1/environment/underWaterF.glsl b/indra/newview/app_settings/shaders/class1/environment/underWaterF.glsl
index 8c8bd6d0d5..ad105c616c 100644
--- a/indra/newview/app_settings/shaders/class1/environment/underWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/environment/underWaterF.glsl
@@ -23,55 +23,10 @@
* $/LicenseInfo$
*/
-#ifdef DEFINE_GL_FRAGCOLOR
out vec4 frag_color;
-#else
-#define frag_color gl_FragColor
-#endif
-
-uniform sampler2D diffuseMap;
-uniform sampler2D bumpMap;
-uniform sampler2D screenTex;
-uniform sampler2D refTex;
-uniform sampler2D screenDepth;
-
-uniform vec4 fogCol;
-uniform vec3 lightDir;
-uniform vec3 specular;
-uniform float lightExp;
-uniform vec2 fbScale;
-uniform float refScale;
-uniform float znear;
-uniform float zfar;
-uniform float kd;
-uniform vec4 waterPlane;
-uniform vec3 eyeVec;
-uniform vec4 waterFogColor;
-uniform float waterFogKS;
-uniform vec2 screenRes;
-
-//bigWave is (refCoord.w, view.w);
-VARYING vec4 refCoord;
-VARYING vec4 littleWave;
-VARYING vec4 view;
-
-vec4 applyWaterFogView(vec3 pos, vec4 color);
+// debug stub
void main()
{
- vec4 color;
-
- //get detail normals
- vec3 wave1 = texture2D(bumpMap, vec2(refCoord.w, view.w)).xyz*2.0-1.0;
- vec3 wave2 = texture2D(bumpMap, littleWave.xy).xyz*2.0-1.0;
- vec3 wave3 = texture2D(bumpMap, littleWave.zw).xyz*2.0-1.0;
- vec3 wavef = normalize(wave1+wave2+wave3);
-
- //figure out distortion vector (ripply)
- vec2 distort = (refCoord.xy/refCoord.z) * 0.5 + 0.5;
- distort = distort+wavef.xy*refScale;
-
- vec4 fb = texture2D(screenTex, distort);
-
- frag_color = applyWaterFogView(view.xyz, fb);
+ frag_color = vec4(0, 1, 1, 0);
}
diff --git a/indra/newview/app_settings/shaders/class1/environment/waterF.glsl b/indra/newview/app_settings/shaders/class1/environment/waterF.glsl
index d370997123..46a6c2021d 100644
--- a/indra/newview/app_settings/shaders/class1/environment/waterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/environment/waterF.glsl
@@ -23,146 +23,9 @@
* $/LicenseInfo$
*/
-#ifdef DEFINE_GL_FRAGCOLOR
out vec4 frag_color;
-#else
-#define frag_color gl_FragColor
-#endif
-vec3 scaleSoftClip(vec3 inColor);
-vec3 atmosTransport(vec3 inColor);
-
-uniform sampler2D bumpMap;
-uniform sampler2D bumpMap2;
-uniform float blend_factor;
-uniform sampler2D screenTex;
-uniform sampler2D refTex;
-
-uniform float sunAngle;
-uniform float sunAngle2;
-uniform vec3 lightDir;
-uniform vec3 specular;
-uniform float lightExp;
-uniform float refScale;
-uniform float kd;
-uniform vec2 screenRes;
-uniform vec3 normScale;
-uniform float fresnelScale;
-uniform float fresnelOffset;
-uniform float blurMultiplier;
-
-
-//bigWave is (refCoord.w, view.w);
-VARYING vec4 refCoord;
-VARYING vec4 littleWave;
-VARYING vec4 view;
-
-vec3 BlendNormal(vec3 bump1, vec3 bump2)
+void main()
{
- vec3 n = mix(bump1, bump2, blend_factor);
- return n;
+ frag_color = vec4(0, 0, 1, 0);
}
-
-
-void main()
-{
- vec4 color;
-
- float dist = length(view.xy);
-
- //normalize view vector
- vec3 viewVec = normalize(view.xyz);
-
- //get wave normals
- vec2 bigwave = vec2(refCoord.w, view.w);
- vec3 wave1_a = texture2D(bumpMap, bigwave ).xyz*2.0-1.0;
- vec3 wave2_a = texture2D(bumpMap, littleWave.xy).xyz*2.0-1.0;
- vec3 wave3_a = texture2D(bumpMap, littleWave.zw).xyz*2.0-1.0;
-
-
- vec3 wave1_b = texture2D(bumpMap2, bigwave ).xyz*2.0-1.0;
- vec3 wave2_b = texture2D(bumpMap2, littleWave.xy).xyz*2.0-1.0;
- vec3 wave3_b = texture2D(bumpMap2, littleWave.zw).xyz*2.0-1.0;
-
- vec3 wave1 = BlendNormal(wave1_a, wave1_b);
- vec3 wave2 = BlendNormal(wave2_a, wave2_b);
- vec3 wave3 = BlendNormal(wave3_a, wave3_b);
-
-
- //get base fresnel components
-
- vec3 df = vec3(
- dot(viewVec, wave1),
- dot(viewVec, (wave2 + wave3) * 0.5),
- dot(viewVec, wave3)
- ) * fresnelScale + fresnelOffset;
- df *= df;
-
- vec2 distort = (refCoord.xy/refCoord.z) * 0.5 + 0.5;
-
- float dist2 = dist;
- dist = max(dist, 5.0);
-
- float dmod = sqrt(dist);
-
- vec2 dmod_scale = vec2(dmod*dmod, dmod);
-
- //get reflected color
- vec2 refdistort1 = wave1.xy*normScale.x;
- vec2 refvec1 = distort+refdistort1/dmod_scale;
- vec4 refcol1 = texture2D(refTex, refvec1);
-
- vec2 refdistort2 = wave2.xy*normScale.y;
- vec2 refvec2 = distort+refdistort2/dmod_scale;
- vec4 refcol2 = texture2D(refTex, refvec2);
-
- vec2 refdistort3 = wave3.xy*normScale.z;
- vec2 refvec3 = distort+refdistort3/dmod_scale;
- vec4 refcol3 = texture2D(refTex, refvec3);
-
- vec4 refcol = refcol1 + refcol2 + refcol3;
- float df1 = df.x + df.y + df.z;
- refcol *= df1 * 0.333;
-
- vec3 wavef = (wave1 + wave2 * 0.4 + wave3 * 0.6) * 0.5;
-
- wavef.z *= max(-viewVec.z, 0.1);
- wavef = normalize(wavef);
-
- float df2 = dot(viewVec, wavef) * fresnelScale+fresnelOffset;
-
- vec2 refdistort4 = wavef.xy*0.125;
- refdistort4.y -= abs(refdistort4.y);
- vec2 refvec4 = distort+refdistort4/dmod;
- float dweight = min(dist2*blurMultiplier, 1.0);
- vec4 baseCol = texture2D(refTex, refvec4);
- refcol = mix(baseCol*df2, refcol, dweight);
-
- //get specular component
- float spec = clamp(dot(lightDir, (reflect(viewVec,wavef))),0.0,1.0);
-
- //harden specular
- spec = pow(spec, 128.0);
-
- //figure out distortion vector (ripply)
- vec2 distort2 = distort+wavef.xy*refScale/max(dmod*df1, 1.0);
-
- vec4 fb = texture2D(screenTex, distort2);
-
- //mix with reflection
- // Note we actually want to use just df1, but multiplying by 0.999999 gets around and nvidia compiler bug
- color.rgb = mix(fb.rgb, refcol.rgb, df1 * 0.99999);
- color.rgb += spec * specular;
-
- color.rgb = atmosTransport(color.rgb);
- color.rgb = scaleSoftClip(color.rgb);
- color.a = spec * sunAngle2;
-
- frag_color = color;
-
-#if defined(WATER_EDGE)
- gl_FragDepth = 0.9999847f;
-#endif
-
-}
-
diff --git a/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl b/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl
index df640cba05..e1cdeddcea 100644
--- a/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl
+++ b/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl
@@ -32,6 +32,8 @@ uniform float waterFogKS;
vec3 getPositionEye();
+vec3 srgb_to_linear(vec3 col);
+
vec4 applyWaterFogView(vec3 pos, vec4 color)
{
vec3 view = normalize(pos);
@@ -66,14 +68,64 @@ vec4 applyWaterFogView(vec3 pos, vec4 color)
float D = pow(0.98, l*kd);
color.rgb = color.rgb * D + kc.rgb * L;
- color.a = kc.a + color.a;
return color;
}
+vec4 applyWaterFogViewLinear(vec3 pos, vec4 color, vec3 sunlit)
+{
+ if (dot(pos, waterPlane.xyz) + waterPlane.w > 0.0)
+ {
+ return color;
+ }
+
+ vec3 view = normalize(pos);
+ //normalize view vector
+ float es = -(dot(view, waterPlane.xyz));
+
+
+ //find intersection point with water plane and eye vector
+
+ //get eye depth
+ float e0 = max(-waterPlane.w, 0.0);
+
+ vec3 int_v = waterPlane.w > 0.0 ? view * waterPlane.w / es : vec3(0.0, 0.0, 0.0);
+
+ //get object depth
+ float depth = length(pos - int_v);
+
+ //get "thickness" of water
+ float l = max(depth, 0.1);
+
+ float kd = waterFogDensity;
+ float ks = waterFogKS;
+ vec4 kc = waterFogColor;
+ kc.rgb = srgb_to_linear(kc.rgb); // TODO -- pass in waterFogColor linear
+ kc.rgb *= sunlit;
+
+ float F = 0.98;
+
+ float t1 = -kd * pow(F, ks * e0);
+ float t2 = kd + ks * es;
+ float t3 = pow(F, t2 * l) - 1.0;
+
+ float L = min(t1 / t2 * t3, 1.0);
+
+ float D = pow(0.98, l * kd);
+
+ color.rgb = color.rgb * D + kc.rgb * L;
+
+ return color;
+}
+
+vec4 applyWaterFogViewLinear(vec3 pos, vec4 color)
+{
+ return applyWaterFogViewLinear(pos, color, vec3(1));
+}
+
vec4 applyWaterFog(vec4 color)
{
//normalize view vector
- return applyWaterFogView(getPositionEye(), color);
+ return applyWaterFogViewLinear(getPositionEye(), color);
}
diff --git a/indra/newview/app_settings/shaders/class1/environment/waterV.glsl b/indra/newview/app_settings/shaders/class1/environment/waterV.glsl
index cc41e3f740..ac400aa2a6 100644
--- a/indra/newview/app_settings/shaders/class1/environment/waterV.glsl
+++ b/indra/newview/app_settings/shaders/class1/environment/waterV.glsl
@@ -24,6 +24,7 @@
*/
uniform mat4 modelview_matrix;
+uniform mat3 normal_matrix;
uniform mat4 modelview_projection_matrix;
ATTRIBUTE vec3 position;
@@ -36,10 +37,16 @@ uniform vec2 waveDir2;
uniform float time;
uniform vec3 eyeVec;
uniform float waterHeight;
+uniform vec3 lightDir;
VARYING vec4 refCoord;
VARYING vec4 littleWave;
VARYING vec4 view;
+out vec3 vary_position;
+out vec3 vary_light_dir;
+out vec3 vary_tangent;
+out vec3 vary_normal;
+out vec2 vary_fragcoord;
float wave(vec2 v, float t, float f, vec2 d, float s)
{
@@ -52,6 +59,11 @@ void main()
vec4 pos = vec4(position.xyz, 1.0);
mat4 modelViewProj = modelview_projection_matrix;
+ vary_position = (modelview_matrix * pos).xyz;
+ vary_light_dir = normal_matrix * lightDir;
+ vary_normal = normal_matrix * vec3(0, 0, 1);
+ vary_tangent = normal_matrix * vec3(1, 0, 0);
+
vec4 oPosition;
//get view vector
@@ -63,12 +75,13 @@ void main()
pos.xy = eyeVec.xy + oEyeVec.xy/d*ld;
view.xyz = oEyeVec;
-
+
d = clamp(ld/1536.0-0.5, 0.0, 1.0);
d *= d;
oPosition = vec4(position, 1.0);
- oPosition.z = mix(oPosition.z, max(eyeVec.z*0.75, 0.0), d);
+// oPosition.z = mix(oPosition.z, max(eyeVec.z*0.75, 0.0), d); // SL-11589 remove "U" shaped horizon
+
oPosition = modelViewProj * oPosition;
refCoord.xyz = oPosition.xyz + vec3(0,0,0.2);
@@ -83,8 +96,7 @@ void main()
pos = modelview_matrix*pos;
calcAtmospherics(pos.xyz);
-
-
+
//pass wave parameters to pixel shader
vec2 bigWave = (v.xy) * vec2(0.04,0.04) + waveDir1 * time * 0.055;
//get two normal map (detail map) texture coordinates
diff --git a/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowF.glsl b/indra/newview/app_settings/shaders/class1/interface/copyF.glsl
index 8e9a5fcd41..65d3c20091 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowF.glsl
+++ b/indra/newview/app_settings/shaders/class1/interface/copyF.glsl
@@ -1,8 +1,9 @@
/**
- * @file avatarShadowF.glsl
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * @file copyF.glsl
+ *
+ * $LicenseInfo:firstyear=2023&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2007, Linden Research, Inc.
+ * Copyright (C) 2023, 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
@@ -22,20 +23,18 @@
* $/LicenseInfo$
*/
-/*[EXTRA_CODE_HERE]*/
-
-#ifdef DEFINE_GL_FRAGCOLOR
-out vec4 frag_color;
-#else
-#define frag_color gl_FragColor
-#endif
+in vec2 tc;
+uniform sampler2D depthMap;
uniform sampler2D diffuseMap;
-VARYING vec2 vary_texcoord0;
+out vec4 frag_color;
void main()
{
- frag_color = vec4(1,1,1,1);
+ frag_color = texture(diffuseMap, tc);
+#if defined(COPY_DEPTH)
+ gl_FragDepth = texture(depthMap, tc).r;
+#endif
}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/pointShadowBlurF.glsl b/indra/newview/app_settings/shaders/class1/interface/copyV.glsl
index ca9ce3a2e1..ace5da6578 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/pointShadowBlurF.glsl
+++ b/indra/newview/app_settings/shaders/class1/interface/copyV.glsl
@@ -1,9 +1,9 @@
/**
- * @file pointShadowBlur.glsl
+ * @file copyV.glsl
*
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $LicenseInfo:firstyear=2023&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2007, Linden Research, Inc.
+ * Copyright (C) 2023, 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
@@ -23,15 +23,12 @@
* $/LicenseInfo$
*/
-uniform samplerCube cube_map;
-in vec3 to_vec;
-
-out vec4 fragColor;
+in vec3 position;
+out vec2 tc;
void main()
{
- vec4 vcol = texture(cube_map, to_vec);
- fragColor = vec4(vcol.rgb, 1.0);
+ tc = position.xy * 0.5 + 0.5;
+ gl_Position = vec4(position, 1.0);
}
-
diff --git a/indra/newview/app_settings/shaders/class1/interface/downsampleDepthRectF.glsl b/indra/newview/app_settings/shaders/class1/interface/downsampleDepthRectF.glsl
index cff8d9d50f..99662097bb 100644
--- a/indra/newview/app_settings/shaders/class1/interface/downsampleDepthRectF.glsl
+++ b/indra/newview/app_settings/shaders/class1/interface/downsampleDepthRectF.glsl
@@ -33,7 +33,7 @@ out vec4 frag_color;
#define frag_color gl_FragColor
#endif
-uniform sampler2DRect depthMap;
+uniform sampler2D depthMap;
VARYING vec2 tc0;
VARYING vec2 tc1;
@@ -48,22 +48,22 @@ VARYING vec2 tc8;
void main()
{
vec4 depth1 =
- vec4(texture2DRect(depthMap, tc0).r,
- texture2DRect(depthMap, tc1).r,
- texture2DRect(depthMap, tc2).r,
- texture2DRect(depthMap, tc3).r);
+ vec4(texture2D(depthMap, tc0).r,
+ texture2D(depthMap, tc1).r,
+ texture2D(depthMap, tc2).r,
+ texture2D(depthMap, tc3).r);
vec4 depth2 =
- vec4(texture2DRect(depthMap, tc4).r,
- texture2DRect(depthMap, tc5).r,
- texture2DRect(depthMap, tc6).r,
- texture2DRect(depthMap, tc7).r);
+ vec4(texture2D(depthMap, tc4).r,
+ texture2D(depthMap, tc5).r,
+ texture2D(depthMap, tc6).r,
+ texture2D(depthMap, tc7).r);
depth1 = min(depth1, depth2);
float depth = min(depth1.x, depth1.y);
depth = min(depth, depth1.z);
depth = min(depth, depth1.w);
- depth = min(depth, texture2DRect(depthMap, tc8).r);
+ depth = min(depth, texture2D(depthMap, tc8).r);
gl_FragDepth = depth;
}
diff --git a/indra/newview/app_settings/shaders/class1/interface/downsampleDepthV.glsl b/indra/newview/app_settings/shaders/class1/interface/downsampleDepthV.glsl
index 71d80911d6..e104377037 100644
--- a/indra/newview/app_settings/shaders/class1/interface/downsampleDepthV.glsl
+++ b/indra/newview/app_settings/shaders/class1/interface/downsampleDepthV.glsl
@@ -45,7 +45,7 @@ void main()
{
gl_Position = vec4(position, 1.0);
- vec2 tc = (position.xy*0.5+0.5)*screen_res;
+ vec2 tc = (position.xy*0.5+0.5);
tc0 = tc+vec2(-delta.x,-delta.y);
tc1 = tc+vec2(0,-delta.y);
tc2 = tc+vec2(delta.x,-delta.y);
diff --git a/indra/newview/app_settings/shaders/class1/interface/glowcombineF.glsl b/indra/newview/app_settings/shaders/class1/interface/glowcombineF.glsl
index b5bbbb5c73..3ead2149f5 100644
--- a/indra/newview/app_settings/shaders/class1/interface/glowcombineF.glsl
+++ b/indra/newview/app_settings/shaders/class1/interface/glowcombineF.glsl
@@ -27,20 +27,18 @@
/*[EXTRA_CODE_HERE]*/
-#ifdef DEFINE_GL_FRAGCOLOR
out vec4 frag_color;
-#else
-#define frag_color gl_FragColor
-#endif
-uniform sampler2D glowMap;
-uniform sampler2DRect screenMap;
+uniform sampler2D emissiveRect;
+uniform sampler2D diffuseRect;
+uniform sampler2D depthMap;
-VARYING vec2 vary_texcoord0;
-VARYING vec2 vary_texcoord1;
+in vec2 tc;
void main()
{
- frag_color = texture2D(glowMap, vary_texcoord0.xy) +
- texture2DRect(screenMap, vary_texcoord1.xy);
+ frag_color = texture2D(emissiveRect, tc) +
+ texture2D(diffuseRect, tc);
+
+ gl_FragDepth = texture(depthMap, tc).r;
}
diff --git a/indra/newview/app_settings/shaders/class1/interface/glowcombineFXAAF.glsl b/indra/newview/app_settings/shaders/class1/interface/glowcombineFXAAF.glsl
index a9e7ea1de8..c50548d528 100644
--- a/indra/newview/app_settings/shaders/class1/interface/glowcombineFXAAF.glsl
+++ b/indra/newview/app_settings/shaders/class1/interface/glowcombineFXAAF.glsl
@@ -27,20 +27,17 @@
/*[EXTRA_CODE_HERE]*/
-#ifdef DEFINE_GL_FRAGCOLOR
out vec4 frag_color;
-#else
-#define frag_color gl_FragColor
-#endif
-uniform sampler2DRect diffuseRect;
+uniform sampler2D diffuseRect;
uniform vec2 screen_res;
-VARYING vec2 vary_tc;
+
+in vec2 vary_tc;
void main()
{
- vec3 col = texture2DRect(diffuseRect, vary_tc*screen_res).rgb;
-
- frag_color = vec4(col.rgb, dot(col.rgb, vec3(0.299, 0.587, 0.144)));
+ vec3 col = texture(diffuseRect, vary_tc).rgb;
+
+ frag_color = vec4(col.rgb, dot(col.rgb, vec3(0.299, 0.587, 0.144)));
}
diff --git a/indra/newview/app_settings/shaders/class1/interface/glowcombineFXAAV.glsl b/indra/newview/app_settings/shaders/class1/interface/glowcombineFXAAV.glsl
index 058f3b1b82..48aab1ce21 100644
--- a/indra/newview/app_settings/shaders/class1/interface/glowcombineFXAAV.glsl
+++ b/indra/newview/app_settings/shaders/class1/interface/glowcombineFXAAV.glsl
@@ -23,7 +23,6 @@
* $/LicenseInfo$
*/
-uniform mat4 modelview_projection_matrix;
ATTRIBUTE vec3 position;
@@ -31,7 +30,7 @@ VARYING vec2 vary_tc;
void main()
{
- vec4 pos = modelview_projection_matrix*vec4(position.xyz, 1.0);
+ vec4 pos = vec4(position.xyz, 1.0);
gl_Position = pos;
vary_tc = pos.xy*0.5+0.5;
diff --git a/indra/newview/app_settings/shaders/class1/interface/glowcombineV.glsl b/indra/newview/app_settings/shaders/class1/interface/glowcombineV.glsl
index f7970b7f78..8fa08a18c3 100644
--- a/indra/newview/app_settings/shaders/class1/interface/glowcombineV.glsl
+++ b/indra/newview/app_settings/shaders/class1/interface/glowcombineV.glsl
@@ -25,17 +25,13 @@
uniform mat4 modelview_projection_matrix;
-ATTRIBUTE vec3 position;
-ATTRIBUTE vec2 texcoord0;
-ATTRIBUTE vec2 texcoord1;
+in vec3 position;
-VARYING vec2 vary_texcoord0;
-VARYING vec2 vary_texcoord1;
+out vec2 tc;
void main()
{
- gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
- vary_texcoord0 = texcoord0;
- vary_texcoord1 = texcoord1;
+ gl_Position = vec4(position.xyz, 1.0);
+ tc = position.xy * 0.5 + 0.5;
}
diff --git a/indra/newview/app_settings/shaders/class1/interface/irradianceGenF.glsl b/indra/newview/app_settings/shaders/class1/interface/irradianceGenF.glsl
new file mode 100644
index 0000000000..2b1e794b52
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/interface/irradianceGenF.glsl
@@ -0,0 +1,33 @@
+/**
+ * @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$
+ */
+
+// debug stub
+
+out vec4 frag_color;
+
+void main()
+{
+ frag_color = vec4(0.5, 0, 0.5, 0);
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/genSkyShV.glsl b/indra/newview/app_settings/shaders/class1/interface/irradianceGenV.glsl
index b466883dc7..5190abf17c 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/genSkyShV.glsl
+++ b/indra/newview/app_settings/shaders/class1/interface/irradianceGenV.glsl
@@ -1,9 +1,9 @@
/**
- * @file genSkyShV.glsl
+ * @file irradianceGenV.glsl
*
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2005, Linden Research, Inc.
+ * Copyright (C) 2011, 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
@@ -22,16 +22,17 @@
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
-
+
+uniform mat4 modelview_matrix;
+
ATTRIBUTE vec3 position;
-ATTRIBUTE vec2 texcoord0;
-VARYING vec2 vary_frag;
+VARYING vec3 vary_dir;
void main()
{
- // pass through untransformed fullscreen pos
- gl_Position = vec4(position.xyz, 1.0);
- vary_frag = texcoord0;
+ gl_Position = vec4(position, 1.0);
+
+ vary_dir = vec3(modelview_matrix * vec4(position, 1.0)).xyz;
}
diff --git a/indra/newview/app_settings/shaders/class1/interface/occlusionF.glsl b/indra/newview/app_settings/shaders/class1/interface/occlusionF.glsl
index db130e456c..f5d2804c7f 100644
--- a/indra/newview/app_settings/shaders/class1/interface/occlusionF.glsl
+++ b/indra/newview/app_settings/shaders/class1/interface/occlusionF.glsl
@@ -23,13 +23,13 @@
* $/LicenseInfo$
*/
-#ifdef DEFINE_GL_FRAGCOLOR
-out vec4 frag_color;
-#else
-#define frag_color gl_FragColor
-#endif
+out vec4 frag_data[4];
void main()
{
- frag_color = vec4(1,1,1,1);
+ // emissive red PBR material for debugging
+ frag_data[0] = vec4(0, 0, 0, 0);
+ frag_data[1] = vec4(0, 0, 0, 0);
+ frag_data[2] = vec4(1, 0, 0, GBUFFER_FLAG_HAS_PBR);
+ frag_data[3] = vec4(1, 0, 0, 0);
}
diff --git a/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl b/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl
new file mode 100644
index 0000000000..e60ddcd569
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl
@@ -0,0 +1,172 @@
+/**
+ * @file radianceGenF.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]*/
+
+out vec4 frag_color;
+
+uniform samplerCubeArray reflectionProbes;
+uniform int sourceIdx;
+
+VARYING vec3 vary_dir;
+
+//uniform float roughness;
+
+uniform float mipLevel;
+uniform int u_width;
+uniform float max_probe_lod;
+
+
+// =============================================================================================================
+// Parts of this file are (c) 2018 Sascha Willems
+// SNIPPED FROM https://github.com/SaschaWillems/Vulkan-glTF-PBR/blob/master/data/shaders/prefilterenvmap.frag
+/*
+MIT License
+
+Copyright (c) 2018 Sascha Willems
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+// =============================================================================================================
+
+const float PI = 3.1415926536;
+
+// Based omn http://byteblacksmith.com/improvements-to-the-canonical-one-liner-glsl-rand-for-opengl-es-2-0/
+float random(vec2 co)
+{
+ float a = 12.9898;
+ float b = 78.233;
+ float c = 43758.5453;
+ float dt= dot(co.xy ,vec2(a,b));
+ float sn= mod(dt,3.14);
+ return fract(sin(sn) * c);
+}
+
+vec2 hammersley2d(uint i, uint N)
+{
+ // Radical inverse based on http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html
+ uint bits = (i << 16u) | (i >> 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);
+ float rdi = float(bits) * 2.3283064365386963e-10;
+ return vec2(float(i) /float(N), rdi);
+}
+
+// Based on http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_slides.pdf
+vec3 importanceSample_GGX(vec2 Xi, float roughness, vec3 normal)
+{
+ // Maps a 2D point to a hemisphere with spread based on roughness
+ float alpha = roughness * roughness;
+ float phi = 2.0 * PI * Xi.x + random(normal.xz) * 0.1;
+ float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (alpha*alpha - 1.0) * Xi.y));
+ float sinTheta = sqrt(1.0 - cosTheta * cosTheta);
+ vec3 H = vec3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta);
+
+ // Tangent space
+ vec3 up = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
+ vec3 tangentX = normalize(cross(up, normal));
+ vec3 tangentY = normalize(cross(normal, tangentX));
+
+ // Convert to world Space
+ return normalize(tangentX * H.x + tangentY * H.y + normal * H.z);
+}
+
+// Normal Distribution function
+float D_GGX(float dotNH, float roughness)
+{
+ float alpha = roughness * roughness;
+ float alpha2 = alpha * alpha;
+ float denom = dotNH * dotNH * (alpha2 - 1.0) + 1.0;
+ return (alpha2)/(PI * denom*denom);
+}
+
+vec4 prefilterEnvMap(vec3 R)
+{
+ vec3 N = R;
+ vec3 V = R;
+ vec4 color = vec4(0.0);
+ float totalWeight = 0.0;
+ float envMapDim = u_width;
+ int numSamples = 4;
+
+ float numMips = max_probe_lod;
+
+ float roughness = mipLevel/numMips;
+
+ numSamples = max(int(numSamples*roughness), 1);
+
+ for(uint i = 0u; i < numSamples; i++) {
+ vec2 Xi = hammersley2d(i, numSamples);
+ vec3 H = importanceSample_GGX(Xi, roughness, N);
+ vec3 L = 2.0 * dot(V, H) * H - V;
+ float dotNL = clamp(dot(N, L), 0.0, 1.0);
+ if(dotNL > 0.0) {
+ // Filtering based on https://placeholderart.wordpress.com/2015/07/28/implementation-notes-runtime-environment-map-filtering-for-image-based-lighting/
+
+ float dotNH = clamp(dot(N, H), 0.0, 1.0);
+ float dotVH = clamp(dot(V, H), 0.0, 1.0);
+
+ // Probability Distribution Function
+ float pdf = D_GGX(dotNH, roughness) * dotNH / (4.0 * dotVH) + 0.0001;
+ // Slid angle of current smple
+ float omegaS = 1.0 / (float(numSamples) * pdf);
+ // Solid angle of 1 pixel across all cube faces
+ float omegaP = 4.0 * PI / (6.0 * envMapDim * envMapDim);
+ // Biased (+1.0) mip level for better result
+ float mip = roughness == 0.0 ? 0.0 : clamp(0.5 * log2(omegaS / omegaP) + 1.0, 0.0f, numMips);
+ //float mip = clamp(0.5 * log2(omegaS / omegaP) + 1.0, 0.0f, 7.f);
+ color += textureLod(reflectionProbes, vec4(L,sourceIdx), mip) * dotNL;
+ totalWeight += dotNL;
+
+ }
+ }
+ return (color / totalWeight);
+}
+
+void main()
+{
+ vec3 N = normalize(vary_dir);
+ frag_color = prefilterEnvMap(N);
+}
+// =============================================================================================================
diff --git a/indra/newview/app_settings/shaders/class1/interface/radianceGenV.glsl b/indra/newview/app_settings/shaders/class1/interface/radianceGenV.glsl
new file mode 100644
index 0000000000..5f5d9396ff
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/interface/radianceGenV.glsl
@@ -0,0 +1,38 @@
+/**
+ * @file radianceGenV.glsl
+ *
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, 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$
+ */
+
+uniform mat4 modelview_matrix;
+
+ATTRIBUTE vec3 position;
+
+VARYING vec3 vary_dir;
+
+void main()
+{
+ gl_Position = vec4(position, 1.0);
+
+ vary_dir = vec3(modelview_matrix * vec4(position, 1.0)).xyz;
+}
+
diff --git a/indra/newview/app_settings/shaders/class1/interface/reflectionmipF.glsl b/indra/newview/app_settings/shaders/class1/interface/reflectionmipF.glsl
new file mode 100644
index 0000000000..a9c28b2974
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/interface/reflectionmipF.glsl
@@ -0,0 +1,100 @@
+/**
+ * @file reflectionmipF.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$
+ */
+
+#extension GL_ARB_texture_rectangle : enable
+
+/*[EXTRA_CODE_HERE]*/
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_color;
+#else
+#define frag_color gl_FragColor
+#endif
+
+// NOTE screenMap should always be texture channel 0 and
+// depthmap should always be channel 1
+uniform sampler2D diffuseRect;
+uniform sampler2D depthMap;
+
+uniform float resScale;
+uniform float znear;
+uniform float zfar;
+
+VARYING vec2 vary_texcoord0;
+
+// get linear depth value given a depth buffer sample d and znear and zfar values
+float linearDepth(float d, float znear, float zfar);
+
+void main()
+{
+#if 0
+ float w[9];
+
+ float c = 1.0/16.0; //corner weight
+ float e = 1.0/8.0; //edge weight
+ float m = 1.0/4.0; //middle weight
+
+ //float wsum = c*4+e*4+m;
+
+ w[0] = c; w[1] = e; w[2] = c;
+ w[3] = e; w[4] = m; w[5] = e;
+ w[6] = c; w[7] = e; w[8] = c;
+
+ vec2 tc[9];
+
+ float ed = 1;
+ float cd = 1;
+
+
+ tc[0] = vec2(-cd, cd); tc[1] = vec2(0, ed); tc[2] = vec2(cd, cd);
+ tc[3] = vec2(-ed, 0); tc[4] = vec2(0, 0); tc[5] = vec2(ed, 0);
+ tc[6] = vec2(-cd, -cd); tc[7] = vec2(0, -ed); tc[8] = vec2(cd, -1);
+
+ vec3 color = vec3(0,0,0);
+
+ for (int i = 0; i < 9; ++i)
+ {
+ color += texture2D(screenMap, vary_texcoord0.xy+tc[i]).rgb * w[i];
+ //color += texture2D(screenMap, vary_texcoord0.xy+tc[i]*2.0).rgb * w[i]*0.5;
+ }
+
+ //color /= wsum;
+
+ frag_color = vec4(color, 1.0);
+#else
+ float depth = texture(depthMap, vary_texcoord0.xy).r;
+ float dist = linearDepth(depth, znear, zfar);
+
+ // convert linear depth to distance
+ vec3 v;
+ v.xy = vary_texcoord0.xy / 512.0 * 2.0 - 1.0;
+ v.z = 1.0;
+ v = normalize(v);
+ dist /= v.z;
+
+ vec3 col = texture2D(diffuseRect, vary_texcoord0.xy).rgb;
+ frag_color = vec4(col, dist/256.0);
+#endif
+}
diff --git a/indra/newview/app_settings/shaders/class1/interface/reflectionprobeF.glsl b/indra/newview/app_settings/shaders/class1/interface/reflectionprobeF.glsl
new file mode 100644
index 0000000000..e2e0a2002b
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/interface/reflectionprobeF.glsl
@@ -0,0 +1,32 @@
+/**
+ * @file reflectionprobeF.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$
+ */
+
+// debug stub
+out vec4 frag_color;
+
+void main()
+{
+ frag_color = vec4(0,1,0,0.5);
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/shVisV.glsl b/indra/newview/app_settings/shaders/class1/interface/reflectionprobeV.glsl
index 8f32dfde79..0efbd63944 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/shVisV.glsl
+++ b/indra/newview/app_settings/shaders/class1/interface/reflectionprobeV.glsl
@@ -1,9 +1,9 @@
/**
- * @file class3/deferred/shVisV.glsl
+ * @file reflectionprobeV.glsl
*
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2007, Linden Research, Inc.
+ * Copyright (C) 2011, 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
@@ -22,12 +22,13 @@
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
+
+ // Debug stub
+
ATTRIBUTE vec3 position;
-VARYING vec4 vary_pos;
void main()
{
- // Output
- vary_pos = vec4(position, 1);
- gl_Position = vary_pos;
+ gl_Position = vec4(position, 1.0);
}
+
diff --git a/indra/newview/app_settings/shaders/class1/interface/splattexturerectF.glsl b/indra/newview/app_settings/shaders/class1/interface/splattexturerectF.glsl
index 7614075cfd..bf6c1b355c 100644
--- a/indra/newview/app_settings/shaders/class1/interface/splattexturerectF.glsl
+++ b/indra/newview/app_settings/shaders/class1/interface/splattexturerectF.glsl
@@ -33,12 +33,12 @@ out vec4 frag_color;
#define frag_color gl_FragColor
#endif
-uniform sampler2DRect screenMap;
+uniform sampler2D screenMap;
VARYING vec4 vertex_color;
VARYING vec2 vary_texcoord0;
void main()
{
- frag_color = texture2DRect(screenMap, vary_texcoord0.xy) * vertex_color;
+ frag_color = texture2D(screenMap, vary_texcoord0.xy) * vertex_color;
}
diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl
index ea2690ba09..12f500e224 100644
--- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl
+++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl
@@ -22,113 +22,26 @@
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
-uniform vec4 lightnorm;
-uniform vec4 sunlight_color;
-uniform vec4 moonlight_color;
-uniform int sun_up_factor;
-uniform vec4 ambient_color;
-uniform vec4 blue_horizon;
-uniform vec4 blue_density;
-uniform float haze_horizon;
-uniform float haze_density;
-uniform float cloud_shadow;
-uniform float density_multiplier;
-uniform float distance_multiplier;
-uniform float max_y;
-uniform vec4 glow;
-uniform float scene_light_strength;
-uniform mat3 ssao_effect_mat;
-uniform int no_atmo;
-uniform float sun_moon_glow_factor;
+
+// debug stub
float getAmbientClamp() { return 1.0f; }
+// Returns colors in sRGB
void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, out vec3 sunlit, out vec3 amblit, out vec3 additive,
out vec3 atten, bool use_ao)
{
- 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);
- vec4 sunlight = (sun_up_factor == 1) ? sunlight_color : moonlight_color;
-
- // sunlight attenuation effect (hue and brightness) due to atmosphere
- // this is used later for sunlight modulation at various altitudes
- vec4 light_atten = (blue_density + vec4(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
-
- vec4 combined_haze = blue_density + vec4(haze_density);
- vec4 blue_weight = blue_density / combined_haze;
- vec4 haze_weight = vec4(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;
-
- vec4 amb_color = ambient_color;
-
- // increase ambient when there are more clouds
- vec4 tmpAmbient = amb_color + (vec4(1.) - amb_color) * cloud_shadow * 0.5;
-
- /* decrease value and saturation (that in HSV, not HSL) for occluded areas
- * // for HSV color/geometry used here, see http://gimp-savvy.com/BOOK/index.html?node52.html
- * // The following line of code performs the equivalent of:
- * float ambAlpha = tmpAmbient.a;
- * float ambValue = dot(vec3(tmpAmbient), vec3(0.577)); // projection onto <1/rt(3), 1/rt(3), 1/rt(3)>, the neutral white-black axis
- * vec3 ambHueSat = vec3(tmpAmbient) - vec3(ambValue);
- * tmpAmbient = vec4(RenderSSAOEffect.valueFactor * vec3(ambValue) + RenderSSAOEffect.saturationFactor *(1.0 - ambFactor) * ambHueSat,
- * ambAlpha);
- */
- if (use_ao)
- {
- tmpAmbient = vec4(mix(ssao_effect_mat * tmpAmbient.rgb, tmpAmbient.rgb, ambFactor), tmpAmbient.a);
- }
-
- // 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);
+ amblit = vec3(0.2, 0, 0.2);
+ sunlit = vec3(1,0,1);
+ additive = vec3(0.5,0.5,0.5);
+ atten = vec3(1,0,1);
+}
- // brightness of surface both sunlight and ambient
- sunlit = sunlight.rgb * 0.5;
- amblit = tmpAmbient.rgb * .25;
- additive *= vec3(1.0 - combined_haze);
+void calcAtmosphericVarsLinear(vec3 inPositionEye, vec3 norm, vec3 light_dir, out vec3 sunlit, out vec3 amblit, out vec3 additive,
+ out vec3 atten)
+{
+ amblit = vec3(0.2, 0, 0.2);
+ sunlit = vec3(1,0,1);
+ additive = vec3(0.5,0.5,0.5);
+ atten = vec3(1,0,1);
}
diff --git a/indra/newview/app_settings/shaders/class1/windlight/cloudShadowF.glsl b/indra/newview/app_settings/shaders/class1/windlight/cloudShadowF.glsl
deleted file mode 100644
index 82fad4db5a..0000000000
--- a/indra/newview/app_settings/shaders/class1/windlight/cloudShadowF.glsl
+++ /dev/null
@@ -1,127 +0,0 @@
-/**
- * @file class1/windlight/cloudShadowF.glsl
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2005, 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$
- */
-
-#ifdef DEFINE_GL_FRAGCOLOR
-out vec4 frag_color;
-#else
-#define frag_color gl_FragColor
-#endif
-
-uniform sampler2D diffuseMap;
-
-VARYING vec4 pos;
-VARYING float target_pos_x;
-VARYING float vary_CloudDensity;
-VARYING vec2 vary_texcoord0;
-VARYING vec2 vary_texcoord1;
-VARYING vec2 vary_texcoord2;
-VARYING vec2 vary_texcoord3;
-
-uniform sampler2D cloud_noise_texture;
-uniform sampler2D cloud_noise_texture_next;
-uniform float blend_factor;
-uniform vec4 cloud_pos_density1;
-uniform vec4 cloud_pos_density2;
-uniform vec4 sunlight_color;
-uniform vec4 cloud_color;
-uniform float cloud_shadow;
-uniform float cloud_scale;
-uniform float cloud_variance;
-uniform vec3 camPosLocal;
-uniform vec3 sun_dir;
-uniform float sun_size;
-uniform float far_z;
-
-#if !defined(DEPTH_CLAMP)
-VARYING vec4 post_pos;
-#endif
-
-vec4 cloudNoise(vec2 uv)
-{
- vec4 a = texture2D(cloud_noise_texture, uv);
- vec4 b = texture2D(cloud_noise_texture_next, uv);
- vec4 cloud_noise_sample = mix(a, b, blend_factor);
- return normalize(cloud_noise_sample);
-}
-
-void main()
-{
- if (cloud_scale >= 0.0001)
- {
- // Set variables
- vec2 uv1 = vary_texcoord0.xy;
- vec2 uv2 = vary_texcoord1.xy;
- vec2 uv3 = vary_texcoord2.xy;
- float cloudDensity = 2.0 * (cloud_shadow - 0.25);
-
- vec2 uv4 = vary_texcoord3.xy;
-
- vec2 disturbance = vec2(cloudNoise(uv1 / 8.0f).x, cloudNoise((uv3 + uv1) / 16.0f).x) * cloud_variance * (1.0f - cloud_scale * 0.25f);
- vec2 disturbance2 = vec2(cloudNoise((uv1 + uv3) / 4.0f).x, cloudNoise((uv4 + uv2) / 8.0f).x) * cloud_variance * (1.0f - cloud_scale * 0.25f);
-
- // Offset texture coords
- uv1 += cloud_pos_density1.xy + (disturbance * 0.2); //large texture, visible density
- uv2 += cloud_pos_density1.xy; //large texture, self shadow
- uv3 += cloud_pos_density2.xy; //small texture, visible density
- uv4 += cloud_pos_density2.xy; //small texture, self shadow
-
- float density_variance = min(1.0, (disturbance.x* 2.0 + disturbance.y* 2.0 + disturbance2.x + disturbance2.y) * 4.0);
-
- cloudDensity *= 1.0 - (density_variance * density_variance);
-
- // Compute alpha1, the main cloud opacity
- float alpha1 = (cloudNoise(uv1).x - 0.5) + (cloudNoise(uv3).x - 0.5) * cloud_pos_density2.z;
- alpha1 = min(max(alpha1 + cloudDensity, 0.) * 10 * cloud_pos_density1.z, 1.);
-
- // And smooth
- alpha1 = 1. - alpha1 * alpha1;
- alpha1 = 1. - alpha1 * alpha1;
-
- if (alpha1 < 0.001f)
- {
- discard;
- }
-
- // Compute alpha2, for self shadowing effect
- // (1 - alpha2) will later be used as percentage of incoming sunlight
- float alpha2 = (cloudNoise(uv2).x - 0.5);
- alpha2 = min(max(alpha2 + cloudDensity, 0.) * 2.5 * cloud_pos_density1.z, 1.);
-
- // And smooth
- alpha2 = 1. - alpha2;
- alpha2 = 1. - alpha2 * alpha2;
-
- frag_color = vec4(alpha1, alpha1, alpha1, 1);
- }
- else
- {
- frag_color = vec4(1);
- }
-
-#if !defined(DEPTH_CLAMP)
- gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0);
-#endif
-
-}
diff --git a/indra/newview/app_settings/shaders/class1/windlight/cloudShadowV.glsl b/indra/newview/app_settings/shaders/class1/windlight/cloudShadowV.glsl
deleted file mode 100644
index 09b6004481..0000000000
--- a/indra/newview/app_settings/shaders/class1/windlight/cloudShadowV.glsl
+++ /dev/null
@@ -1,61 +0,0 @@
-/**
- * @file class1\windlight\cloudShadowV.glsl
- *
- * $LicenseInfo:firstyear=2011&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2011, 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$
- */
-
-uniform mat4 texture_matrix0;
-uniform mat4 modelview_projection_matrix;
-uniform float shadow_target_width;
-
-ATTRIBUTE vec3 position;
-ATTRIBUTE vec4 diffuse_color;
-ATTRIBUTE vec2 texcoord0;
-
-#if !defined(DEPTH_CLAMP)
-VARYING float pos_zd2;
-#endif
-
-VARYING vec4 pos;
-VARYING float target_pos_x;
-VARYING vec2 vary_texcoord0;
-
-void passTextureIndex();
-
-void main()
-{
- //transform vertex
- vec4 pre_pos = vec4(position.xyz, 1.0);
- pos = modelview_projection_matrix * pre_pos;
- target_pos_x = 0.5 * (shadow_target_width - 1.0) * pos.x;
-
-#if !defined(DEPTH_CLAMP)
- pos_zd2 = pos.z * 0.5;
- gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
-#else
- gl_Position = pos;
-#endif
-
- passTextureIndex();
-
- vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
-}
diff --git a/indra/newview/app_settings/shaders/class1/windlight/moonF.glsl b/indra/newview/app_settings/shaders/class1/windlight/moonF.glsl
index 2425a2ad04..c4ab0c95dc 100644
--- a/indra/newview/app_settings/shaders/class1/windlight/moonF.glsl
+++ b/indra/newview/app_settings/shaders/class1/windlight/moonF.glsl
@@ -34,8 +34,7 @@ out vec4 frag_color;
#endif
uniform vec4 color;
-uniform vec4 sunlight_color;
-uniform vec4 moonlight_color;
+uniform vec3 moonlight_color;
uniform vec3 moon_dir;
uniform float moon_brightness;
uniform sampler2D diffuseMap;
@@ -52,6 +51,12 @@ void main()
fade = clamp( moon_dir.z*moon_dir.z*4.0, 0.0, 1.0 );
vec4 c = texture2D(diffuseMap, vary_texcoord0.xy);
+
+ // SL-14113 Don't write to depth; prevent moon's quad from hiding stars which should be visible
+ // Moon texture has transparent pixels <0x55,0x55,0x55,0x00>
+ if (c.a <= 2./255.) // 0.00784
+ discard;
+
// c.rgb = pow(c.rgb, vec3(0.7f)); // can't use "srgb_to_linear(color.rgb)" as that is a deferred only function
c.rgb *= moonlight_color.rgb;
c.rgb *= moon_brightness;
@@ -62,5 +67,6 @@ void main()
c.rgb = scaleSoftClip(c.rgb);
frag_color = vec4(c.rgb, c.a);
+ gl_FragDepth = LL_SHADER_CONST_CLOUD_MOON_DEPTH; // SL-14113
}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl
new file mode 100644
index 0000000000..7435f1c0e1
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl
@@ -0,0 +1,305 @@
+/**
+ * @file alphaF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2007, 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$
+ */
+
+//class2/deferred/alphaF.glsl
+
+#extension GL_ARB_texture_rectangle : enable
+
+/*[EXTRA_CODE_HERE]*/
+
+#define INDEXED 1
+#define NON_INDEXED 2
+#define NON_INDEXED_NO_COLOR 3
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_color;
+#else
+#define frag_color gl_FragColor
+#endif
+
+uniform mat3 env_mat;
+uniform vec3 sun_dir;
+uniform vec3 moon_dir;
+
+#ifdef USE_DIFFUSE_TEX
+uniform sampler2D diffuseMap;
+#endif
+
+VARYING vec3 vary_fragcoord;
+VARYING vec3 vary_position;
+VARYING vec2 vary_texcoord0;
+VARYING vec3 vary_norm;
+
+#ifdef USE_VERTEX_COLOR
+VARYING vec4 vertex_color; //vertex color should be treated as sRGB
+#endif
+
+#ifdef HAS_ALPHA_MASK
+uniform float minimum_alpha;
+#endif
+
+uniform mat4 proj_mat;
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+uniform int sun_up_factor;
+uniform vec4 light_position[8];
+uniform vec3 light_direction[8];
+uniform vec4 light_attenuation[8];
+uniform vec3 light_diffuse[8];
+
+void waterClip(vec3 pos);
+
+#ifdef WATER_FOG
+vec4 applyWaterFogViewLinear(vec3 pos, vec4 color, vec3 sunlit);
+#endif
+
+vec3 srgb_to_linear(vec3 c);
+vec3 linear_to_srgb(vec3 c);
+
+vec2 encode_normal (vec3 n);
+vec3 scaleSoftClipFragLinear(vec3 l);
+vec3 atmosFragLightingLinear(vec3 light, vec3 additive, vec3 atten);
+
+void calcAtmosphericVarsLinear(vec3 inPositionEye, vec3 norm, vec3 light_dir, out vec3 sunlit, out vec3 amblit, out vec3 atten, out vec3 additive);
+
+#ifdef HAS_SUN_SHADOW
+float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen);
+#endif
+
+float getAmbientClamp();
+
+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)
+{
+ // SL-14895 inverted attenuation work-around
+ // This routine is tweaked to match deferred lighting, but previously used an inverted la value. To reconstruct
+ // that previous value now that the inversion is corrected, we reverse the calculations in LLPipeline::setupHWLights()
+ // to recover the `adjusted_radius` value previously being sent as la.
+ float falloff_factor = (12.0 * fa) - 9.0;
+ float inverted_la = falloff_factor / la;
+ // Yes, it makes me want to cry as well. DJH
+
+ vec3 col = vec3(0);
+
+ //get light vector
+ vec3 lv = lp.xyz-v;
+
+ //get distance
+ float dist = length(lv);
+ float da = 1.0;
+
+ /*if (dist > inverted_la)
+ {
+ return col;
+ }
+
+ clip to projector bounds
+ vec4 proj_tc = proj_mat * lp;
+
+ if (proj_tc.z < 0
+ || proj_tc.z > 1
+ || proj_tc.x < 0
+ || proj_tc.x > 1
+ || proj_tc.y < 0
+ || proj_tc.y > 1)
+ {
+ return col;
+ }*/
+
+ if (dist > 0.0 && inverted_la > 0.0)
+ {
+ dist /= inverted_la;
+
+ //normalize light vector
+ lv = normalize(lv);
+
+ //distance attenuation
+ float dist_atten = clamp(1.0-(dist-1.0*(1.0-fa))/fa, 0.0, 1.0);
+ dist_atten *= dist_atten;
+ dist_atten *= 2.0f;
+
+ if (dist_atten <= 0.0)
+ {
+ return col;
+ }
+
+ // spotlight coefficient.
+ float spot = max(dot(-ln, lv), is_pointlight);
+ da *= spot*spot; // GL_SPOT_EXPONENT=2
+
+ //angular attenuation
+ da *= dot(n, lv);
+ da = max(0.0, da);
+
+ float lit = 0.0f;
+
+ float amb_da = 0.0;//ambiance;
+ if (da > 0)
+ {
+ lit = max(da * dist_atten,0.0);
+ col = lit * light_col * diffuse;
+ amb_da += (da*0.5+0.5) * ambiance;
+ }
+ amb_da += (da*da*0.5 + 0.5) * ambiance;
+ amb_da *= dist_atten;
+ amb_da = min(amb_da, 1.0f - lit);
+
+ // SL-10969 ... need to work out why this blows out in many setups...
+ //col.rgb += amb_da * light_col * diffuse;
+
+ // no spec for alpha shader...
+ }
+ col = max(col, vec3(0));
+ return col;
+}
+
+void main()
+{
+ vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5;
+
+ vec4 pos = vec4(vary_position, 1.0);
+#ifndef IS_AVATAR_SKIN
+ // clip against water plane unless this is a legacy avatar skin
+ waterClip(pos.xyz);
+#endif
+ vec3 norm = vary_norm;
+
+ float shadow = 1.0f;
+
+#ifdef HAS_SUN_SHADOW
+ shadow = sampleDirectionalShadow(pos.xyz, norm.xyz, frag);
+#endif
+
+#ifdef USE_DIFFUSE_TEX
+ vec4 diffuse_tap = texture2D(diffuseMap,vary_texcoord0.xy);
+#endif
+
+#ifdef USE_INDEXED_TEX
+ vec4 diffuse_tap = diffuseLookup(vary_texcoord0.xy);
+#endif
+
+ vec4 diffuse_srgb = diffuse_tap;
+
+#ifdef FOR_IMPOSTOR
+ vec4 color;
+ color.rgb = diffuse_srgb.rgb;
+ color.a = 1.0;
+
+ float final_alpha = diffuse_srgb.a * vertex_color.a;
+ diffuse_srgb.rgb *= vertex_color.rgb;
+
+ // Insure we don't pollute depth with invis pixels in impostor rendering
+ //
+ if (final_alpha < minimum_alpha)
+ {
+ discard;
+ }
+
+ color.rgb = diffuse_srgb.rgb;
+ color.a = final_alpha;
+
+#else // FOR_IMPOSTOR
+
+ vec4 diffuse_linear = vec4(srgb_to_linear(diffuse_srgb.rgb), diffuse_srgb.a);
+
+ vec3 light_dir = (sun_up_factor == 1) ? sun_dir: moon_dir; // TODO -- factor out "sun_up_factor" and just send in the appropriate light vector
+
+ float final_alpha = diffuse_linear.a;
+
+#ifdef USE_VERTEX_COLOR
+ final_alpha *= vertex_color.a;
+
+ if (final_alpha < minimum_alpha)
+ { // TODO: figure out how to get invisible faces out of
+ // render batches without breaking glow
+ discard;
+ }
+
+ diffuse_srgb.rgb *= vertex_color.rgb;
+ diffuse_linear.rgb = srgb_to_linear(diffuse_srgb.rgb);
+#endif // USE_VERTEX_COLOR
+
+ vec3 sunlit;
+ vec3 amblit;
+ vec3 additive;
+ vec3 atten;
+
+ calcAtmosphericVarsLinear(pos.xyz, norm, light_dir, sunlit, amblit, additive, atten);
+
+ vec3 irradiance;
+ vec3 glossenv;
+ vec3 legacyenv;
+ sampleReflectionProbesLegacy(irradiance, glossenv, legacyenv, frag, pos.xyz, norm.xyz, 0.0, 0.0);
+
+
+ float da = dot(norm.xyz, light_dir.xyz);
+ da = clamp(da, -1.0, 1.0);
+
+ float final_da = da;
+ final_da = clamp(final_da, 0.0f, 1.0f);
+
+ vec4 color = vec4(0.0);
+
+ color.a = final_alpha;
+
+ vec3 sun_contrib = min(final_da, shadow) * sunlit;
+
+ color.rgb = max(amblit, irradiance);
+
+ color.rgb += sun_contrib;
+
+ color.rgb *= diffuse_linear.rgb;
+
+ color.rgb = atmosFragLightingLinear(color.rgb, additive, atten);
+ color.rgb = scaleSoftClipFragLinear(color.rgb);
+
+ vec4 light = vec4(0,0,0,0);
+
+ #define LIGHT_LOOP(i) light.rgb += calcPointLightOrSpotLight(light_diffuse[i].rgb, diffuse_linear.rgb, pos.xyz, norm, light_position[i], light_direction[i].xyz, light_attenuation[i].x, light_attenuation[i].y, light_attenuation[i].z, light_attenuation[i].w);
+
+ LIGHT_LOOP(1)
+ LIGHT_LOOP(2)
+ LIGHT_LOOP(3)
+ LIGHT_LOOP(4)
+ LIGHT_LOOP(5)
+ LIGHT_LOOP(6)
+ LIGHT_LOOP(7)
+
+ // sum local light contrib in linear colorspace
+#if !defined(LOCAL_LIGHT_KILL)
+ color.rgb += light.rgb;
+#endif // !defined(LOCAL_LIGHT_KILL)
+
+#ifdef WATER_FOG
+ color = applyWaterFogViewLinear(pos.xyz, color, sunlit);
+#endif // WATER_FOG
+
+#endif // #else // FOR_IMPOSTOR
+
+ frag_color = color;
+}
+
diff --git a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl
index 1b7a1cc6ec..ba419e7a65 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl
@@ -34,12 +34,12 @@ out vec4 frag_color;
#define frag_color gl_FragColor
#endif
-uniform sampler2DRect diffuseRect;
-uniform sampler2DRect specularRect;
-uniform sampler2DRect depthMap;
-uniform sampler2DRect normalMap;
+uniform sampler2D diffuseRect;
+uniform sampler2D specularRect;
+uniform sampler2D depthMap;
+uniform sampler2D normalMap;
uniform samplerCube environmentMap;
-uniform sampler2DRect lightMap;
+uniform sampler2D lightMap;
uniform sampler2D noiseMap;
uniform sampler2D projectionMap;
uniform sampler2D lightFunc;
@@ -138,7 +138,6 @@ void main()
vec4 frag = vary_fragcoord;
frag.xyz /= frag.w;
frag.xyz = frag.xyz*0.5+0.5;
- frag.xy *= screen_res;
vec3 pos = getPosition(frag.xy).xyz;
vec3 lv = center.xyz-pos.xyz;
@@ -154,13 +153,13 @@ void main()
if (proj_shadow_idx >= 0)
{
- vec4 shd = texture2DRect(lightMap, frag.xy);
+ vec4 shd = texture2D(lightMap, frag.xy);
shadow = (proj_shadow_idx==0)?shd.b:shd.a;
shadow += shadow_fade;
shadow = clamp(shadow, 0.0, 1.0);
}
- vec3 norm = texture2DRect(normalMap, frag.xy).xyz;
+ vec3 norm = texture2D(normalMap, frag.xy).xyz;
float envIntensity = norm.z;
@@ -190,13 +189,13 @@ void main()
lv = normalize(lv);
float da = dot(norm, lv);
- vec3 diff_tex = texture2DRect(diffuseRect, frag.xy).rgb;
+ vec3 diff_tex = texture2D(diffuseRect, frag.xy).rgb;
- vec4 spec = texture2DRect(specularRect, frag.xy);
+ vec4 spec = texture2D(specularRect, frag.xy);
vec3 dlit = vec3(0, 0, 0);
- float noise = texture2D(noiseMap, frag.xy/128.0).b;
+ float noise = texture2D(noiseMap, frag.xy).b;
if (proj_tc.z > 0.0 &&
proj_tc.x < 1.0 &&
proj_tc.y < 1.0 &&
diff --git a/indra/newview/app_settings/shaders/class2/deferred/pbralphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/pbralphaF.glsl
new file mode 100644
index 0000000000..ccf20942e3
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/pbralphaF.glsl
@@ -0,0 +1,239 @@
+/**
+ * @file class1\deferred\pbralphaF.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]*/
+
+uniform sampler2D diffuseMap; //always in sRGB space
+uniform sampler2D bumpMap;
+uniform sampler2D emissiveMap;
+uniform sampler2D specularMap; // PBR: Packed: Occlusion, Metal, Roughness
+
+uniform float metallicFactor;
+uniform float roughnessFactor;
+uniform vec3 emissiveColor;
+
+#if defined(HAS_SUN_SHADOW) || defined(HAS_SSAO)
+uniform sampler2D lightMap;
+#endif
+
+uniform int sun_up_factor;
+uniform vec3 sun_dir;
+uniform vec3 moon_dir;
+
+out vec4 frag_color;
+
+#ifdef HAS_SUN_SHADOW
+ in vec3 vary_fragcoord;
+ uniform vec2 screen_res;
+#endif
+
+in vec3 vary_position;
+
+in vec2 basecolor_texcoord;
+in vec2 normal_texcoord;
+in vec2 metallic_roughness_texcoord;
+in vec2 emissive_texcoord;
+
+in vec4 vertex_color;
+
+in vec3 vary_normal;
+in vec3 vary_tangent;
+flat in float vary_sign;
+
+
+#ifdef HAS_ALPHA_MASK
+uniform float minimum_alpha; // PBR alphaMode: MASK, See: mAlphaCutoff, setAlphaCutoff()
+#endif
+
+// Lights
+// See: LLRender::syncLightState()
+uniform vec4 light_position[8];
+uniform vec3 light_direction[8]; // spot direction
+uniform vec4 light_attenuation[8]; // linear, quadratic, is omni, unused, See: LLPipeline::setupHWLights() and syncLightState()
+uniform vec3 light_diffuse[8];
+uniform vec2 light_deferred_attenuation[8]; // light size and falloff
+
+vec3 srgb_to_linear(vec3 c);
+vec3 linear_to_srgb(vec3 c);
+
+void calcAtmosphericVarsLinear(vec3 inPositionEye, vec3 norm, vec3 light_dir, out vec3 sunlit, out vec3 amblit, out vec3 atten, out vec3 additive);
+
+void calcHalfVectors(vec3 lv, vec3 n, vec3 v, out vec3 h, out vec3 l, out float nh, out float nl, out float nv, out float vh, out float lightDist);
+float calcLegacyDistanceAttenuation(float distance, float falloff);
+float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen);
+void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv,
+ vec2 tc, vec3 pos, vec3 norm, float glossiness);
+
+void waterClip(vec3 pos);
+
+void calcDiffuseSpecular(vec3 baseColor, float metallic, inout vec3 diffuseColor, inout vec3 specularColor);
+
+vec3 pbrBaseLight(vec3 diffuseColor,
+ vec3 specularColor,
+ float metallic,
+ vec3 pos,
+ vec3 norm,
+ float perceptualRoughness,
+ vec3 light_dir,
+ vec3 sunlit,
+ float scol,
+ vec3 radiance,
+ vec3 irradiance,
+ vec3 colorEmissive,
+ float ao,
+ vec3 additive,
+ vec3 atten);
+
+vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor,
+ float perceptualRoughness,
+ float metallic,
+ vec3 n, // normal
+ vec3 v, // surface point to camera
+ vec3 l); //surface point to light
+
+vec3 calcPointLightOrSpotLight(vec3 diffuseColor, vec3 specularColor,
+ float perceptualRoughness,
+ float metallic,
+ vec3 n, // normal
+ vec3 p, // pixel position
+ vec3 v, // view vector (negative normalized pixel position)
+ vec3 lp, // light position
+ vec3 ld, // light direction (for spotlights)
+ vec3 lightColor,
+ float lightSize, float falloff, float is_pointlight, float ambiance)
+{
+ vec3 color = vec3(0,0,0);
+
+ vec3 lv = lp.xyz - p;
+
+ float lightDist = length(lv);
+
+ float dist = lightDist / lightSize;
+ if (dist <= 1.0)
+ {
+ lv /= lightDist;
+
+ float dist_atten = calcLegacyDistanceAttenuation(dist, falloff);
+
+ // spotlight coefficient.
+ float spot = max(dot(-ld, lv), is_pointlight);
+ // spot*spot => GL_SPOT_EXPONENT=2
+ float spot_atten = spot*spot;
+
+ vec3 intensity = spot_atten * dist_atten * lightColor * 3.0;
+
+ color = intensity*pbrPunctual(diffuseColor, specularColor, perceptualRoughness, metallic, n.xyz, v, lv);
+ }
+
+ return color;
+}
+
+void main()
+{
+ vec3 color = vec3(0,0,0);
+
+ vec3 light_dir = (sun_up_factor == 1) ? sun_dir : moon_dir;
+ vec3 pos = vary_position;
+
+ waterClip(pos);
+
+ vec4 basecolor = texture(diffuseMap, basecolor_texcoord.xy).rgba;
+ basecolor.rgb = srgb_to_linear(basecolor.rgb);
+#ifdef HAS_ALPHA_MASK
+ if (basecolor.a < minimum_alpha)
+ {
+ discard;
+ }
+#endif
+
+ vec3 col = vertex_color.rgb * basecolor.rgb;
+
+ vec3 vNt = texture(bumpMap, normal_texcoord.xy).xyz*2.0-1.0;
+ float sign = vary_sign;
+ vec3 vN = vary_normal;
+ vec3 vT = vary_tangent.xyz;
+
+ vec3 vB = sign * cross(vN, vT);
+ vec3 norm = normalize( vNt.x * vT + vNt.y * vB + vNt.z * vN );
+
+ norm *= gl_FrontFacing ? 1.0 : -1.0;
+
+ float scol = 1.0;
+ vec3 sunlit;
+ vec3 amblit;
+ vec3 additive;
+ vec3 atten;
+ calcAtmosphericVarsLinear(pos.xyz, norm, light_dir, sunlit, amblit, additive, atten);
+
+#ifdef HAS_SUN_SHADOW
+ vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5;
+ scol = sampleDirectionalShadow(pos.xyz, norm.xyz, frag);
+#endif
+
+ vec3 orm = texture(specularMap, metallic_roughness_texcoord.xy).rgb; //orm is packed into "emissiveRect" to keep the data in linear color space
+
+ float perceptualRoughness = orm.g * roughnessFactor;
+ float metallic = orm.b * metallicFactor;
+ float ao = orm.r;
+
+ // emissiveColor is the emissive color factor from GLTF and is already in linear space
+ vec3 colorEmissive = emissiveColor;
+ // emissiveMap here is a vanilla RGB texture encoded as sRGB, manually convert to linear
+ colorEmissive *= srgb_to_linear(texture2D(emissiveMap, emissive_texcoord.xy).rgb);
+
+ // PBR IBL
+ float gloss = 1.0 - perceptualRoughness;
+ vec3 irradiance = vec3(0);
+ vec3 radiance = vec3(0);
+ 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);
+
+ vec3 diffuseColor;
+ vec3 specularColor;
+ calcDiffuseSpecular(col.rgb, metallic, diffuseColor, specularColor);
+
+ vec3 v = -normalize(pos.xyz);
+ color = pbrBaseLight(diffuseColor, specularColor, metallic, v, norm.xyz, perceptualRoughness, light_dir, sunlit, scol, radiance, irradiance, colorEmissive, ao, additive, atten);
+
+ vec3 light = vec3(0);
+
+ // Punctual lights
+#define LIGHT_LOOP(i) light += calcPointLightOrSpotLight(diffuseColor, specularColor, perceptualRoughness, metallic, norm.xyz, pos.xyz, v, light_position[i].xyz, light_direction[i].xyz, light_diffuse[i].rgb, light_deferred_attenuation[i].x, light_deferred_attenuation[i].y, light_attenuation[i].z, light_attenuation[i].w);
+
+ LIGHT_LOOP(1)
+ LIGHT_LOOP(2)
+ LIGHT_LOOP(3)
+ LIGHT_LOOP(4)
+ LIGHT_LOOP(5)
+ LIGHT_LOOP(6)
+ LIGHT_LOOP(7)
+
+ color.rgb += light.rgb;
+
+
+ frag_color = vec4(color.rgb,basecolor.a * vertex_color.a);
+}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class2/deferred/reflectionProbeF.glsl
new file mode 100644
index 0000000000..f1ee4b4681
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/reflectionProbeF.glsl
@@ -0,0 +1,81 @@
+/**
+ * @file class2/deferred/reflectionProbeF.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$
+ */
+
+// Implementation for when reflection probes are disabled
+
+uniform float reflection_probe_ambiance;
+
+uniform samplerCube environmentMap;
+
+uniform mat3 env_mat;
+
+vec3 srgb_to_linear(vec3 c);
+
+void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv,
+ vec2 tc, vec3 pos, vec3 norm, float glossiness, bool errorCorrect)
+{
+ ambenv = vec3(reflection_probe_ambiance * 0.25);
+
+ vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
+ vec3 env_vec = env_mat * refnormpersp;
+ glossenv = srgb_to_linear(textureCube(environmentMap, env_vec).rgb);
+}
+
+void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv,
+ vec2 tc, vec3 pos, vec3 norm, float glossiness)
+{
+ sampleReflectionProbes(ambenv, glossenv,
+ tc, pos, norm, glossiness, false);
+}
+
+vec4 sampleReflectionProbesDebug(vec3 pos)
+{
+ // show nothing in debug display
+ return vec4(0, 0, 0, 0);
+}
+
+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);
+
+ vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
+ vec3 env_vec = env_mat * refnormpersp;
+
+ legacyenv = srgb_to_linear(textureCube(environmentMap, env_vec).rgb);
+
+ glossenv = legacyenv;
+}
+
+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)
+{
+ color = mix(color.rgb, legacyenv*1.5, envIntensity);
+}
+
diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
index 7700d16007..fab227f5a4 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
@@ -34,11 +34,11 @@ out vec4 frag_color;
#define frag_color gl_FragColor
#endif
-uniform sampler2DRect diffuseRect;
-uniform sampler2DRect specularRect;
-uniform sampler2DRect normalMap;
-uniform sampler2DRect lightMap;
-uniform sampler2DRect depthMap;
+uniform sampler2D diffuseRect;
+uniform sampler2D specularRect;
+uniform sampler2D normalMap;
+uniform sampler2D lightMap;
+uniform sampler2D depthMap;
uniform samplerCube environmentMap;
uniform sampler2D lightFunc;
@@ -58,6 +58,7 @@ uniform vec2 screen_res;
vec3 getNorm(vec2 pos_screen);
vec4 getPositionWithDepth(vec2 pos_screen, float depth);
+float getDepth(vec2 pos_screen);
void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, out vec3 sunlit, out vec3 amblit, out vec3 additive, out vec3 atten, bool use_ao);
float getAmbientClamp();
@@ -76,9 +77,9 @@ vec4 applyWaterFogView(vec3 pos, vec4 color);
void main()
{
vec2 tc = vary_fragcoord.xy;
- float depth = texture2DRect(depthMap, tc.xy).r;
+ float depth = getDepth(tc.xy);
vec4 pos = getPositionWithDepth(tc, depth);
- vec4 norm = texture2DRect(normalMap, tc);
+ vec4 norm = texture2D(normalMap, tc);
float envIntensity = norm.z;
norm.xyz = getNorm(tc);
@@ -87,11 +88,11 @@ void main()
float light_gamma = 1.0 / 1.3;
da = pow(da, light_gamma);
- vec4 diffuse = texture2DRect(diffuseRect, tc);
- diffuse.rgb = linear_to_srgb(diffuse.rgb); // SL-14025
- vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy);
+ vec4 diffuse = texture2D(diffuseRect, tc);
+ diffuse.rgb = linear_to_srgb(diffuse.rgb); // SL-14035
+ vec4 spec = texture2D(specularRect, vary_fragcoord.xy);
- vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg;
+ vec2 scol_ambocc = texture2D(lightMap, vary_fragcoord.xy).rg;
scol_ambocc = pow(scol_ambocc, vec2(light_gamma));
float scol = max(scol_ambocc.r, diffuse.a);
float ambocc = scol_ambocc.g;
@@ -139,7 +140,7 @@ void main()
color = mix(color.rgb, reflected_color, envIntensity);
}
- if (norm.w < 0.5)
+ if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_ATMOS))
{
color = mix(atmosFragLighting(color, additive, atten), fullbrightAtmosTransportFrag(color, additive, atten), diffuse.a);
color = mix(scaleSoftClipFrag(color), fullbrightScaleSoftClip(color), diffuse.a);
@@ -153,6 +154,6 @@ void main()
// convert to linear as fullscreen lights need to sum in linear colorspace
// and will be gamma (re)corrected downstream...
- frag_color.rgb = srgb_to_linear(color.rgb);
+ frag_color.rgb = pos.xyz;// srgb_to_linear(color.rgb);
frag_color.a = bloom;
}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl
index bd11aa3f05..1e7ccb747a 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl
@@ -23,8 +23,6 @@
* $/LicenseInfo$
*/
-uniform mat4 modelview_projection_matrix;
-
ATTRIBUTE vec3 position;
uniform vec2 screen_res;
@@ -38,12 +36,12 @@ void setAdditiveColor(vec3 c);
void main()
{
//transform vertex
- vec4 pos = modelview_projection_matrix * vec4(position.xyz, 1.0);
+ vec4 pos = vec4(position.xyz, 1.0);
gl_Position = pos;
// appease OSX GLSL compiler/linker by touching all the varyings we said we would
setAtmosAttenuation(vec3(1));
setAdditiveColor(vec3(0));
- vary_fragcoord = (pos.xy*0.5+0.5)*screen_res;
+ vary_fragcoord = (pos.xy*0.5+0.5);
}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl
index 774f537821..e6a627fbf7 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl
@@ -34,12 +34,12 @@ out vec4 frag_color;
#define frag_color gl_FragColor
#endif
-uniform sampler2DRect diffuseRect;
-uniform sampler2DRect specularRect;
-uniform sampler2DRect depthMap;
-uniform sampler2DRect normalMap;
+uniform sampler2D diffuseRect;
+uniform sampler2D specularRect;
+uniform sampler2D depthMap;
+uniform sampler2D normalMap;
uniform samplerCube environmentMap;
-uniform sampler2DRect lightMap;
+uniform sampler2D lightMap;
uniform sampler2D noiseMap;
uniform sampler2D projectionMap;
uniform sampler2D lightFunc;
@@ -138,7 +138,6 @@ void main()
vec4 frag = vary_fragcoord;
frag.xyz /= frag.w;
frag.xyz = frag.xyz*0.5+0.5;
- frag.xy *= screen_res;
vec3 pos = getPosition(frag.xy).xyz;
vec3 lv = trans_center.xyz-pos.xyz;
@@ -154,13 +153,13 @@ void main()
if (proj_shadow_idx >= 0)
{
- vec4 shd = texture2DRect(lightMap, frag.xy);
+ vec4 shd = texture2D(lightMap, frag.xy);
shadow = (proj_shadow_idx == 0) ? shd.b : shd.a;
shadow += shadow_fade;
shadow = clamp(shadow, 0.0, 1.0);
}
- vec3 norm = texture2DRect(normalMap, frag.xy).xyz;
+ vec3 norm = texture2D(normalMap, frag.xy).xyz;
float envIntensity = norm.z;
norm = getNorm(frag.xy);
@@ -189,11 +188,11 @@ void main()
lv = normalize(lv);
float da = dot(norm, lv);
- vec3 diff_tex = texture2DRect(diffuseRect, frag.xy).rgb;
- vec4 spec = texture2DRect(specularRect, frag.xy);
+ vec3 diff_tex = texture2D(diffuseRect, frag.xy).rgb;
+ vec4 spec = texture2D(specularRect, frag.xy);
vec3 dlit = vec3(0, 0, 0);
- float noise = texture2D(noiseMap, frag.xy/128.0).b;
+ float noise = texture2D(noiseMap, frag.xy).b;
if (proj_tc.z > 0.0 &&
proj_tc.x < 1.0 &&
proj_tc.y < 1.0 &&
diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightV.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightV.glsl
index bc5eb5181d..3dfca0f655 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/sunLightV.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightV.glsl
@@ -23,8 +23,6 @@
* $/LicenseInfo$
*/
-uniform mat4 modelview_projection_matrix;
-
ATTRIBUTE vec3 position;
VARYING vec2 vary_fragcoord;
@@ -34,8 +32,8 @@ uniform vec2 screen_res;
void main()
{
//transform vertex
- vec4 pos = modelview_projection_matrix * vec4(position.xyz, 1.0);
+ vec4 pos = vec4(position.xyz, 1.0);
gl_Position = pos;
- vary_fragcoord = (pos.xy * 0.5 + 0.5)*screen_res;
+ vary_fragcoord = (pos.xy * 0.5 + 0.5);
}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/waterF.glsl b/indra/newview/app_settings/shaders/class2/deferred/waterF.glsl
new file mode 100644
index 0000000000..96739d91d7
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/waterF.glsl
@@ -0,0 +1,192 @@
+/**
+ * @file class1/deferred/waterF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2007, 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$
+ */
+
+#extension GL_ARB_texture_rectangle : enable
+
+/*[EXTRA_CODE_HERE]*/
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_data[4];
+#else
+#define frag_data gl_FragData
+#endif
+
+vec3 scaleSoftClip(vec3 inColor);
+vec3 atmosTransport(vec3 inColor);
+
+uniform sampler2D bumpMap;
+uniform sampler2D bumpMap2;
+uniform float blend_factor;
+uniform sampler2D screenTex;
+uniform sampler2D refTex;
+uniform float sunAngle;
+uniform float sunAngle2;
+uniform vec3 lightDir;
+uniform vec3 specular;
+uniform float lightExp;
+uniform float refScale;
+uniform float kd;
+uniform vec2 screenRes;
+uniform vec3 normScale;
+uniform float fresnelScale;
+uniform float fresnelOffset;
+uniform float blurMultiplier;
+uniform vec2 screen_res;
+uniform mat4 norm_mat; //region space to screen space
+uniform int water_edge;
+
+//bigWave is (refCoord.w, view.w);
+VARYING vec4 refCoord;
+VARYING vec4 littleWave;
+VARYING vec4 view;
+VARYING vec4 vary_position;
+
+vec2 encode_normal(vec3 n);
+vec3 scaleSoftClip(vec3 l);
+vec3 srgb_to_linear(vec3 c);
+vec3 linear_to_srgb(vec3 c);
+
+vec3 BlendNormal(vec3 bump1, vec3 bump2)
+{
+ vec3 n = mix(bump1, bump2, blend_factor);
+ return n;
+}
+
+void main()
+{
+ vec4 color;
+ float dist = length(view.xyz);
+
+ //normalize view vector
+ vec3 viewVec = normalize(view.xyz);
+
+ //get wave normals
+ vec3 wave1_a = texture2D(bumpMap, vec2(refCoord.w, view.w)).xyz*2.0-1.0;
+ vec3 wave2_a = texture2D(bumpMap, littleWave.xy).xyz*2.0-1.0;
+ vec3 wave3_a = texture2D(bumpMap, littleWave.zw).xyz*2.0-1.0;
+
+
+ vec3 wave1_b = texture2D(bumpMap2, vec2(refCoord.w, view.w)).xyz*2.0-1.0;
+ vec3 wave2_b = texture2D(bumpMap2, littleWave.xy).xyz*2.0-1.0;
+ vec3 wave3_b = texture2D(bumpMap2, littleWave.zw).xyz*2.0-1.0;
+
+ vec3 wave1 = BlendNormal(wave1_a, wave1_b);
+ vec3 wave2 = BlendNormal(wave2_a, wave2_b);
+ vec3 wave3 = BlendNormal(wave3_a, wave3_b);
+
+ //get base fresnel components
+
+ vec3 df = vec3(
+ dot(viewVec, wave1),
+ dot(viewVec, (wave2 + wave3) * 0.5),
+ dot(viewVec, wave3)
+ ) * fresnelScale + fresnelOffset;
+ df *= df;
+
+ vec2 distort = (refCoord.xy/refCoord.z) * 0.5 + 0.5;
+
+ float dist2 = dist;
+ dist = max(dist, 5.0);
+
+ float dmod = sqrt(dist);
+
+ vec2 dmod_scale = vec2(dmod*dmod, dmod);
+
+ //get reflected color
+ vec2 refdistort1 = wave1.xy*normScale.x;
+ vec2 refvec1 = distort+refdistort1/dmod_scale;
+ vec4 refcol1 = texture2D(refTex, refvec1);
+
+ vec2 refdistort2 = wave2.xy*normScale.y;
+ vec2 refvec2 = distort+refdistort2/dmod_scale;
+ vec4 refcol2 = texture2D(refTex, refvec2);
+
+ vec2 refdistort3 = wave3.xy*normScale.z;
+ vec2 refvec3 = distort+refdistort3/dmod_scale;
+ vec4 refcol3 = texture2D(refTex, refvec3);
+
+ vec4 refcol = refcol1 + refcol2 + refcol3;
+ float df1 = df.x + df.y + df.z;
+ refcol *= df1 * 0.333;
+
+ vec3 wavef = (wave1 + wave2 * 0.4 + wave3 * 0.6) * 0.5;
+ wavef.z *= max(-viewVec.z, 0.1);
+ wavef = normalize(wavef);
+
+ float df2 = dot(viewVec, wavef) * fresnelScale+fresnelOffset;
+
+ vec2 refdistort4 = wavef.xy*0.125;
+ refdistort4.y -= abs(refdistort4.y);
+ vec2 refvec4 = distort+refdistort4/dmod;
+ float dweight = min(dist2*blurMultiplier, 1.0);
+ vec4 baseCol = texture2D(refTex, refvec4);
+
+ refcol = mix(baseCol*df2, refcol, dweight);
+
+ //get specular component
+ float spec = clamp(dot(lightDir, (reflect(viewVec,wavef))),0.0,1.0);
+
+ //harden specular
+ spec = pow(spec, 128.0);
+
+ //figure out distortion vector (ripply)
+ vec2 distort2 = distort+wavef.xy*refScale/max(dmod*df1, 1.0);
+
+ vec4 fb = texture2D(screenTex, distort2);
+
+ //mix with reflection
+ // Note we actually want to use just df1, but multiplying by 0.999999 gets around an nvidia compiler bug
+ color.rgb = mix(fb.rgb, refcol.rgb, df1 * 0.99999f);
+
+ vec4 pos = vary_position;
+
+ //color.rgb += spec * specular;
+
+ //color.rgb = atmosTransport(color.rgb);
+ //color.rgb = scaleSoftClip(color.rgb);
+
+ //color.rgb = refcol.rgb;
+ color.rgb = vec3(0.0);
+ color.a = spec * sunAngle2;
+
+ vec3 screenspacewavef = normalize((norm_mat*vec4(wavef, 1.0)).xyz);
+
+ //frag_data[0] = color;
+
+ // TODO: The non-obvious assignment below is copied from the pre-EEP WL shader code
+ // Unfortunately, fixing it causes a mismatch for EEP, and so it remains... for now
+ // SL-12975 (unfix pre-EEP broken alpha)
+ frag_data[0] = vec4(srgb_to_linear(color.rgb), 0.0);
+
+ frag_data[1] = vec4(1.0, 0.1, 0.0, 0.0); // occlusion, roughness, metalness
+ frag_data[2] = vec4(encode_normal(screenspacewavef.xyz), 0.0, GBUFFER_FLAG_HAS_PBR);// normalxy, env intens, flags (atmo kill)
+ //frag_data[3] = vec4(srgb_to_linear(refcol.rgb),0);
+ frag_data[3] = vec4(0, 0, 0, 0);
+
+
+ //frag_data[0] = vec4(0.0,0,0,0);
+ //frag_data[1] = vec4(0, 1.0, 0.0, 0.0);
+ //frag_data[3] = vec4(0);
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/waterF.glsl b/indra/newview/app_settings/shaders/class2/environment/waterF.glsl
index c65cf48c67..d485379a56 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/waterF.glsl
+++ b/indra/newview/app_settings/shaders/class2/environment/waterF.glsl
@@ -22,20 +22,21 @@
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
-
-#extension GL_ARB_texture_rectangle : enable
-/*[EXTRA_CODE_HERE]*/
+//class2/environment/waterF.glsl
#ifdef DEFINE_GL_FRAGCOLOR
-out vec4 frag_data[3];
+out vec4 frag_color;
#else
-#define frag_data gl_FragData
+#define frag_color gl_FragColor
#endif
-uniform sampler2D bumpMap;
+vec3 scaleSoftClip(vec3 inColor);
+vec3 atmosTransport(vec3 inColor);
+
+uniform sampler2D bumpMap;
uniform sampler2D bumpMap2;
-uniform float blend_factor;
+uniform float blend_factor;
uniform sampler2D screenTex;
uniform sampler2D refTex;
@@ -51,49 +52,45 @@ uniform vec3 normScale;
uniform float fresnelScale;
uniform float fresnelOffset;
uniform float blurMultiplier;
-uniform vec2 screen_res;
-uniform mat4 norm_mat; //region space to screen space
+
//bigWave is (refCoord.w, view.w);
VARYING vec4 refCoord;
VARYING vec4 littleWave;
VARYING vec4 view;
-VARYING vec4 vary_position;
-
-vec3 scaleSoftClip(vec3 c);
-vec2 encode_normal(vec3 n);
vec3 BlendNormal(vec3 bump1, vec3 bump2)
{
- //vec3 normal = bump1.xyz * vec3( 2.0, 2.0, 2.0) - vec3(1.0, 1.0, 0.0);
- //vec3 normal2 = bump2.xyz * vec3(-2.0, -2.0, 2.0) + vec3(1.0, 1.0, -1.0);
- //vec3 n = normalize(normal * dot(normal, normal2) - (normal2 * normal.z));
- vec3 n = normalize(mix(bump1, bump2, blend_factor));
+ vec3 n = mix(bump1, bump2, blend_factor);
return n;
}
+
void main()
{
vec4 color;
+
float dist = length(view.xy);
//normalize view vector
vec3 viewVec = normalize(view.xyz);
//get wave normals
- vec3 wave1_a = texture2D(bumpMap, vec2(refCoord.w, view.w)).xyz*2.0-1.0;
- vec3 wave2_a = texture2D(bumpMap, littleWave.xy).xyz*2.0-1.0;
- vec3 wave3_a = texture2D(bumpMap, littleWave.zw).xyz*2.0-1.0;
+ vec2 bigwave = vec2(refCoord.w, view.w);
+ vec3 wave1_a = texture2D(bumpMap, bigwave ).xyz*2.0-1.0;
+ vec3 wave2_a = texture2D(bumpMap, littleWave.xy).xyz*2.0-1.0;
+ vec3 wave3_a = texture2D(bumpMap, littleWave.zw).xyz*2.0-1.0;
- vec3 wave1_b = texture2D(bumpMap2, vec2(refCoord.w, view.w)).xyz*2.0-1.0;
- vec3 wave2_b = texture2D(bumpMap2, littleWave.xy).xyz*2.0-1.0;
- vec3 wave3_b = texture2D(bumpMap2, littleWave.zw).xyz*2.0-1.0;
+ vec3 wave1_b = texture2D(bumpMap2, bigwave ).xyz*2.0-1.0;
+ vec3 wave2_b = texture2D(bumpMap2, littleWave.xy).xyz*2.0-1.0;
+ vec3 wave3_b = texture2D(bumpMap2, littleWave.zw).xyz*2.0-1.0;
vec3 wave1 = BlendNormal(wave1_a, wave1_b);
vec3 wave2 = BlendNormal(wave2_a, wave2_b);
vec3 wave3 = BlendNormal(wave3_a, wave3_b);
+
//get base fresnel components
vec3 df = vec3(
@@ -130,6 +127,7 @@ void main()
refcol *= df1 * 0.333;
vec3 wavef = (wave1 + wave2 * 0.4 + wave3 * 0.6) * 0.5;
+
wavef.z *= max(-viewVec.z, 0.1);
wavef = normalize(wavef);
@@ -140,7 +138,6 @@ void main()
vec2 refvec4 = distort+refdistort4/dmod;
float dweight = min(dist2*blurMultiplier, 1.0);
vec4 baseCol = texture2D(refTex, refvec4);
-
refcol = mix(baseCol*df2, refcol, dweight);
//get specular component
@@ -155,20 +152,19 @@ void main()
vec4 fb = texture2D(screenTex, distort2);
//mix with reflection
- // Note we actually want to use just df1, but multiplying by 0.999999 gets around an nvidia compiler bug
+ // Note we actually want to use just df1, but multiplying by 0.999999 gets around and nvidia compiler bug
color.rgb = mix(fb.rgb, refcol.rgb, df1 * 0.99999);
-
- color.rgb *= 2.0f;
- color.rgb = scaleSoftClip(color.rgb);
+ color.rgb += spec * specular;
- vec4 pos = vary_position;
+ color.rgb = atmosTransport(color.rgb);
+ color.rgb = scaleSoftClip(color.rgb);
+ color.a = spec * sunAngle2;
- color.rgb += spec * specular;
- color.a = spec * sunAngle2;
-
- vec3 screenspacewavef = normalize((norm_mat*vec4(wavef, 1.0)).xyz);
+ frag_color = color;
+
+#if defined(WATER_EDGE)
+ gl_FragDepth = 0.9999847f;
+#endif
- frag_data[0] = vec4(color.rgb, color); // diffuse
- frag_data[1] = vec4(spec * specular, spec); // speccolor, spec
- frag_data[2] = vec4(encode_normal(wavef.xyz), 0.05, 0);// normalxy, 0, 0
}
+
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..c7da23fb00
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/interface/irradianceGenF.glsl
@@ -0,0 +1,218 @@
+/**
+ * @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]*/
+
+out vec4 frag_color;
+
+uniform samplerCubeArray reflectionProbes;
+uniform int sourceIdx;
+
+uniform float max_probe_lod;
+uniform float ambiance_scale;
+
+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
+
+
+#define MATH_PI 3.1415926535897932384626433832795
+
+float u_roughness = 1.0;
+int u_sampleCount = 32;
+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);
+
+ 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, 7);
+ // sample lambertian at a lower resolution to avoid fireflies
+ vec4 lambertian = textureLod(reflectionProbes, vec4(H, sourceIdx), lod);
+
+ color += lambertian;
+ }
+
+ color /= float(u_sampleCount);
+
+ color.rgb *= ambiance_scale;
+
+ 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/class3/deferred/shadowF.glsl b/indra/newview/app_settings/shaders/class2/interface/reflectionprobeF.glsl
index 3350267130..986b233e0b 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/shadowF.glsl
+++ b/indra/newview/app_settings/shaders/class2/interface/reflectionprobeF.glsl
@@ -1,9 +1,9 @@
/**
- * @file class3/deferred/shadowF.glsl
+ * @file reflectionprobeF.glsl
*
- * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2011, Linden Research, Inc.
+ * 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
@@ -23,27 +23,20 @@
* $/LicenseInfo$
*/
-/*[EXTRA_CODE_HERE]*/
-
-#ifdef DEFINE_GL_FRAGCOLOR
out vec4 frag_color;
-#else
-#define frag_color gl_FragColor
-#endif
-
-uniform sampler2D diffuseMap;
-#if !defined(DEPTH_CLAMP)
-VARYING float pos_zd2;
-#endif
+in vec2 vary_fragcoord;
-VARYING vec4 pos;
-VARYING float target_pos_x;
+vec4 getPositionWithDepth(vec2 pos_screen, float depth);
+float getDepth(vec2 pos_screen);
-vec4 computeMoments(float depth, float a);
+vec4 sampleReflectionProbesDebug(vec3 pos);
-void main()
+void main()
{
- frag_color = computeMoments(length(pos), 1.0);
-}
+ vec2 tc = vary_fragcoord.xy;
+ float depth = getDepth(tc.xy);
+ vec4 pos = getPositionWithDepth(tc, depth);
+ frag_color = sampleReflectionProbesDebug(pos.xyz);
+}
diff --git a/indra/newview/app_settings/shaders/class2/interface/reflectionprobeV.glsl b/indra/newview/app_settings/shaders/class2/interface/reflectionprobeV.glsl
new file mode 100644
index 0000000000..e45b1c288b
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/interface/reflectionprobeV.glsl
@@ -0,0 +1,38 @@
+/**
+ * @file reflectionprobeV.glsl
+ *
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, 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$
+ */
+
+
+in vec3 position;
+
+out vec2 vary_fragcoord;
+
+void main()
+{
+ //transform vertex
+ vec4 pos = vec4(position.xyz, 1.0);
+ gl_Position = pos;
+
+ vary_fragcoord = (pos.xy*0.5+0.5);
+}
diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsF.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsF.glsl
index ee9c990b12..1463d507bc 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsF.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsF.glsl
@@ -29,8 +29,11 @@ vec3 scaleSoftClipFrag(vec3 light);
uniform int no_atmo;
+vec3 srgb_to_linear(vec3 col);
+vec3 linear_to_srgb(vec3 col);
+
vec3 atmosFragLighting(vec3 light, vec3 additive, vec3 atten)
-{
+{
if (no_atmo == 1)
{
return light;
@@ -40,6 +43,11 @@ vec3 atmosFragLighting(vec3 light, vec3 additive, vec3 atten)
return light * 2.0;
}
+vec3 atmosFragLightingLinear(vec3 light, vec3 additive, vec3 atten)
+{
+ return atmosFragLighting(light, additive, atten);
+}
+
vec3 atmosLighting(vec3 light)
{
return atmosFragLighting(light, getAdditiveColor(), getAtmosAttenuation());
diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsFuncs.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsFuncs.glsl
new file mode 100644
index 0000000000..ba02070e45
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsFuncs.glsl
@@ -0,0 +1,171 @@
+/**
+ * @file class2\windlight\atmosphericsFuncs.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$
+ */
+
+uniform vec3 lightnorm;
+uniform vec3 sunlight_color;
+uniform vec3 sunlight_linear;
+uniform vec3 moonlight_color;
+uniform vec3 moonlight_linear;
+uniform int sun_up_factor;
+uniform vec3 ambient_color;
+uniform vec3 ambient_linear;
+uniform vec3 blue_horizon;
+uniform vec3 blue_horizon_linear;
+uniform vec3 blue_density;
+uniform vec3 blue_density_linear;
+uniform float haze_horizon;
+uniform float haze_density;
+uniform float haze_density_linear;
+uniform float cloud_shadow;
+uniform float density_multiplier;
+uniform float distance_multiplier;
+uniform float max_y;
+uniform vec3 glow;
+uniform float scene_light_strength;
+uniform mat3 ssao_effect_mat;
+uniform int no_atmo;
+uniform float sun_moon_glow_factor;
+
+float getAmbientClamp() { return 1.0f; }
+
+vec3 srgb_to_linear(vec3 col);
+
+// return colors in sRGB space
+void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, out vec3 sunlit, out vec3 amblit, out vec3 additive,
+ out vec3 atten, bool use_ao)
+{
+ 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) ? sunlight_color : moonlight_color;
+
+ // 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 = ambient_color;
+
+ // increase ambient when there are more clouds
+ vec3 tmpAmbient = amb_color + (vec3(1.) - amb_color) * cloud_shadow * 0.5;
+
+ /* decrease value and saturation (that in HSV, not HSL) for occluded areas
+ * // for HSV color/geometry used here, see http://gimp-savvy.com/BOOK/index.html?node52.html
+ * // The following line of code performs the equivalent of:
+ * float ambAlpha = tmpAmbient.a;
+ * float ambValue = dot(vec3(tmpAmbient), vec3(0.577)); // projection onto <1/rt(3), 1/rt(3), 1/rt(3)>, the neutral white-black axis
+ * vec3 ambHueSat = vec3(tmpAmbient) - vec3(ambValue);
+ * tmpAmbient = vec4(RenderSSAOEffect.valueFactor * vec3(ambValue) + RenderSSAOEffect.saturationFactor *(1.0 - ambFactor) * ambHueSat,
+ * ambAlpha);
+ */
+ if (use_ao)
+ {
+ tmpAmbient = mix(ssao_effect_mat * tmpAmbient.rgb, tmpAmbient.rgb, ambFactor);
+ }
+
+ // 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 = sunlight.rgb;
+ amblit = tmpAmbient.rgb;
+ additive *= vec3(1.0 - combined_haze);
+}
+
+
+vec3 srgb_to_linear(vec3 col);
+
+// provide a touch of lighting in the opposite direction of the sun light
+ // so areas in shadow don't lose all detail
+float ambientLighting(vec3 norm, vec3 light_dir)
+{
+ float ambient = min(abs(dot(norm.xyz, light_dir.xyz)), 1.0);
+ ambient *= 0.56;
+ ambient *= ambient;
+ ambient = (1.0 - ambient);
+ return ambient;
+}
+
+
+// return colors in linear space
+void calcAtmosphericVarsLinear(vec3 inPositionEye, vec3 norm, vec3 light_dir, out vec3 sunlit, out vec3 amblit, out vec3 additive,
+ out vec3 atten)
+{
+ 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);
+}
diff --git a/indra/newview/app_settings/shaders/class2/windlight/cloudsF.glsl b/indra/newview/app_settings/shaders/class2/windlight/cloudsF.glsl
index fa928d993e..6f4bdbde28 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/cloudsF.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/cloudsF.glsl
@@ -35,15 +35,15 @@ out vec4 frag_color;
// The fragment shader for the sky
/////////////////////////////////////////////////////////////////////////
-VARYING vec4 vary_CloudColorSun;
-VARYING vec4 vary_CloudColorAmbient;
+VARYING vec3 vary_CloudColorSun;
+VARYING vec3 vary_CloudColorAmbient;
VARYING float vary_CloudDensity;
uniform sampler2D cloud_noise_texture;
uniform sampler2D cloud_noise_texture_next;
uniform float blend_factor;
-uniform vec4 cloud_pos_density1;
-uniform vec4 cloud_pos_density2;
+uniform vec3 cloud_pos_density1;
+uniform vec3 cloud_pos_density2;
uniform float cloud_scale;
uniform float cloud_variance;
@@ -70,8 +70,8 @@ void main()
vec2 uv1 = vary_texcoord0.xy;
vec2 uv2 = vary_texcoord1.xy;
- vec4 cloudColorSun = vary_CloudColorSun;
- vec4 cloudColorAmbient = vary_CloudColorAmbient;
+ vec3 cloudColorSun = vary_CloudColorSun;
+ vec3 cloudColorAmbient = vary_CloudColorAmbient;
float cloudDensity = vary_CloudDensity;
vec2 uv3 = vary_texcoord2.xy;
vec2 uv4 = vary_texcoord3.xy;
@@ -120,12 +120,18 @@ void main()
alpha2 = 1. - alpha2 * alpha2;
// Combine
- vec4 color;
+ vec3 color;
color = (cloudColorSun*(1.-alpha2) + cloudColorAmbient);
color.rgb *= 2.;
color.rgb = scaleSoftClip(color.rgb);
/// Gamma correct for WL (soft clip effect).
frag_color = vec4(color.rgb, alpha1);
+
+ // SL-14113 Moon Haze -- When the camera is underwater fix clouds clipping into moon
+ // camera above water: class1\deferred\cloudsF.glsl
+ // camera below water: class2\windlight\coudsV.glsl
+ // See: starsV.glsl, cloudsV.glsl, moonF.glsl
+ gl_FragDepth = LL_SHADER_CONST_CLOUD_MOON_DEPTH;
}
diff --git a/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl b/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl
index 97ffa9feef..650009d393 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl
@@ -33,8 +33,8 @@ ATTRIBUTE vec2 texcoord0;
///////////////////////////////////////////////////////////////////////////////
// Output parameters
-VARYING vec4 vary_CloudColorSun;
-VARYING vec4 vary_CloudColorAmbient;
+VARYING vec3 vary_CloudColorSun;
+VARYING vec3 vary_CloudColorAmbient;
VARYING float vary_CloudDensity;
VARYING vec2 vary_texcoord0;
@@ -46,13 +46,13 @@ VARYING float altitude_blend_factor;
// Inputs
uniform vec3 camPosLocal;
-uniform vec4 lightnorm;
-uniform vec4 sunlight_color;
-uniform vec4 moonlight_color;
+uniform vec3 lightnorm;
+uniform vec3 sunlight_color;
+uniform vec3 moonlight_color;
uniform int sun_up_factor;
-uniform vec4 ambient_color;
-uniform vec4 blue_horizon;
-uniform vec4 blue_density;
+uniform vec3 ambient_color;
+uniform vec3 blue_horizon;
+uniform vec3 blue_density;
uniform float haze_horizon;
uniform float haze_density;
@@ -60,10 +60,10 @@ uniform float cloud_shadow;
uniform float density_multiplier;
uniform float max_y;
-uniform vec4 glow;
+uniform vec3 glow;
uniform float sun_moon_glow_factor;
-uniform vec4 cloud_color;
+uniform vec3 cloud_color;
uniform float cloud_scale;
@@ -114,17 +114,17 @@ void main()
float rel_pos_len = length(rel_pos);
// Initialize temp variables
- vec4 sunlight = sunlight_color;
- vec4 light_atten;
+ vec3 sunlight = sunlight_color;
+ vec3 light_atten;
// Sunlight attenuation effect (hue and brightness) due to atmosphere
// this is used later for sunlight modulation at various altitudes
- light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y);
+ light_atten = (blue_density + vec3(haze_density * 0.25)) * (density_multiplier * max_y);
// Calculate relative weights
- vec4 combined_haze = abs(blue_density) + vec4(abs(haze_density));
- vec4 blue_weight = blue_density / combined_haze;
- vec4 haze_weight = haze_density / combined_haze;
+ vec3 combined_haze = abs(blue_density) + vec3(abs(haze_density));
+ vec3 blue_weight = blue_density / combined_haze;
+ vec3 haze_weight = haze_density / combined_haze;
// Compute sunlight from rel_pos & lightnorm (for long rays like sky)
float off_axis = 1.0 / max(1e-6, max(0., rel_pos_norm.y) + lightnorm.y);
@@ -155,14 +155,14 @@ void main()
haze_glow = (sun_moon_glow_factor < 1.0) ? 0.0 : (haze_glow + 0.25);
// Increase ambient when there are more clouds
- vec4 tmpAmbient = ambient_color;
+ vec3 tmpAmbient = ambient_color;
tmpAmbient += (1. - tmpAmbient) * cloud_shadow * 0.5;
// Dim sunlight by cloud shadow percentage
sunlight *= (1. - cloud_shadow);
// Haze color below cloud
- vec4 additiveColorBelowCloud =
+ vec3 additiveColorBelowCloud =
(blue_horizon * blue_weight * (sunlight + tmpAmbient) + (haze_horizon * haze_weight) * (sunlight * haze_glow + tmpAmbient));
// CLOUDS
@@ -178,7 +178,7 @@ void main()
combined_haze = sqrt(combined_haze); // less atmos opacity (more transparency) below clouds
vary_CloudColorSun *= combined_haze;
vary_CloudColorAmbient *= combined_haze;
- vec4 oHazeColorBelowCloud = additiveColorBelowCloud * (1. - combined_haze);
+ vec3 oHazeColorBelowCloud = additiveColorBelowCloud * (1. - combined_haze);
// Make a nice cloud density based on the cloud_shadow value that was passed in.
vary_CloudDensity = 2. * (cloud_shadow - 0.25);
diff --git a/indra/newview/app_settings/shaders/class2/windlight/gammaF.glsl b/indra/newview/app_settings/shaders/class2/windlight/gammaF.glsl
index 68db7fcbb1..a32a572461 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/gammaF.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/gammaF.glsl
@@ -28,6 +28,21 @@ uniform int no_atmo;
vec3 getAtmosAttenuation();
vec3 getAdditiveColor();
+vec3 srgb_to_linear(vec3 col);
+vec3 linear_to_srgb(vec3 col);
+
+vec3 scaleSoftClipFragLinear(vec3 light)
+{ // identical to non-linear version and that's probably close enough
+ if (no_atmo == 1)
+ {
+ return light;
+ }
+ //soft clip effect:
+ light = 1. - clamp(light, vec3(0.), vec3(1.));
+ light = 1. - pow(light, vec3(gamma)); // s/b inverted already CPU-side
+ return light;
+}
+
vec3 scaleSoftClipFrag(vec3 light)
{
if (no_atmo == 1)
diff --git a/indra/newview/app_settings/shaders/class2/windlight/skyF.glsl b/indra/newview/app_settings/shaders/class2/windlight/skyF.glsl
index 7146349453..7a229e0f5e 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/skyF.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/skyF.glsl
@@ -33,7 +33,7 @@ out vec4 frag_color;
// The fragment shader for the sky
/////////////////////////////////////////////////////////////////////////
-VARYING vec4 vary_HazeColor;
+VARYING vec3 vary_HazeColor;
/// Soft clips the light with a gamma correction
vec3 scaleSoftClip(vec3 light);
@@ -45,7 +45,7 @@ void main()
// the fragment) if the sky wouldn't show up because the clouds
// are fully opaque.
- vec4 color;
+ vec3 color;
color = vary_HazeColor;
color.rgb *= 2.;
/// Gamma correct for WL (soft clip effect).
diff --git a/indra/newview/app_settings/shaders/class2/windlight/skyV.glsl b/indra/newview/app_settings/shaders/class2/windlight/skyV.glsl
index a0a33b8642..8f7726bb0b 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/skyV.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/skyV.glsl
@@ -32,18 +32,18 @@ ATTRIBUTE vec3 position;
///////////////////////////////////////////////////////////////////////////////
// Output parameters
-VARYING vec4 vary_HazeColor;
+VARYING vec3 vary_HazeColor;
// Inputs
uniform vec3 camPosLocal;
-uniform vec4 lightnorm;
-uniform vec4 sunlight_color;
-uniform vec4 moonlight_color;
+uniform vec3 lightnorm;
+uniform vec3 sunlight_color;
+uniform vec3 moonlight_color;
uniform int sun_up_factor;
-uniform vec4 ambient_color;
-uniform vec4 blue_horizon;
-uniform vec4 blue_density;
+uniform vec3 ambient_color;
+uniform vec3 blue_horizon;
+uniform vec3 blue_density;
uniform float haze_horizon;
uniform float haze_density;
@@ -52,11 +52,9 @@ uniform float density_multiplier;
uniform float distance_multiplier;
uniform float max_y;
-uniform vec4 glow;
+uniform vec3 glow;
uniform float sun_moon_glow_factor;
-uniform vec4 cloud_color;
-
void main()
{
// World / view / projection
@@ -83,17 +81,17 @@ void main()
float rel_pos_len = length(rel_pos);
// Initialize temp variables
- vec4 sunlight = (sun_up_factor == 1) ? sunlight_color : moonlight_color;
- vec4 light_atten;
+ vec3 sunlight = (sun_up_factor == 1) ? sunlight_color : moonlight_color;
+ vec3 light_atten;
// Sunlight attenuation effect (hue and brightness) due to atmosphere
// this is used later for sunlight modulation at various altitudes
- light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y);
+ light_atten = (blue_density + vec3(haze_density * 0.25)) * (density_multiplier * max_y);
// Calculate relative weights
- vec4 combined_haze = abs(blue_density) + vec4(abs(haze_density));
- vec4 blue_weight = blue_density / combined_haze;
- vec4 haze_weight = haze_density / combined_haze;
+ vec3 combined_haze = abs(blue_density) + vec3(abs(haze_density));
+ vec3 blue_weight = blue_density / combined_haze;
+ vec3 haze_weight = haze_density / combined_haze;
// Compute sunlight from rel_pos & lightnorm (for long rays like sky)
float off_axis = 1.0 / max(1e-6, max(0., rel_pos_norm.y) + lightnorm.y);
@@ -121,21 +119,21 @@ void main()
// For sun, add to glow. For moon, remove glow entirely. SL-13768
haze_glow = (sun_moon_glow_factor < 1.0) ? 0.0 : (haze_glow + 0.25);
- vec4 color =
+ vec3 color =
(blue_horizon * blue_weight * (sunlight + ambient_color) + (haze_horizon * haze_weight) * (sunlight * haze_glow + ambient_color));
// Final atmosphere additive
color *= (1. - combined_haze);
// Increase ambient when there are more clouds
- vec4 tmpAmbient = ambient_color;
- tmpAmbient += max(vec4(0), (1. - ambient_color)) * cloud_shadow * 0.5;
+ vec3 tmpAmbient = ambient_color;
+ tmpAmbient += max(vec3(0), (1. - ambient_color)) * cloud_shadow * 0.5;
// Dim sunlight by cloud shadow percentage
sunlight *= max(0.0, (1. - cloud_shadow));
// Haze color below cloud
- vec4 additiveColorBelowCloud =
+ vec3 additiveColorBelowCloud =
(blue_horizon * blue_weight * (sunlight + tmpAmbient) + (haze_horizon * haze_weight) * (sunlight * haze_glow + tmpAmbient));
// Attenuate cloud color by atmosphere
diff --git a/indra/newview/app_settings/shaders/class2/windlight/transportF.glsl b/indra/newview/app_settings/shaders/class2/windlight/transportF.glsl
index b53a2e237f..ecf0430a88 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/transportF.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/transportF.glsl
@@ -32,6 +32,9 @@ vec3 getAtmosAttenuation();
uniform int no_atmo;
+vec3 srgb_to_linear(vec3 col);
+vec3 linear_to_srgb(vec3 col);
+
vec3 atmosTransportFrag(vec3 light, vec3 additive, vec3 atten)
{
light *= atten.r;
@@ -44,6 +47,13 @@ vec3 atmosTransport(vec3 light)
return atmosTransportFrag(light, getAdditiveColor(), getAtmosAttenuation());
}
+vec3 fullbrightAtmosTransportFragLinear(vec3 light, vec3 additive, vec3 atten)
+{
+ // same as non-linear version, probably fine
+ float brightness = dot(light.rgb * 0.5, vec3(0.3333)) + 0.1;
+ return mix(atmosTransportFrag(light.rgb, additive, atten), light.rgb + additive, brightness * brightness);
+}
+
vec3 fullbrightAtmosTransportFrag(vec3 light, vec3 additive, vec3 atten)
{
float brightness = dot(light.rgb * 0.5, vec3(0.3333)) + 0.1;
diff --git a/indra/newview/app_settings/shaders/class3/avatar/avatarV.glsl b/indra/newview/app_settings/shaders/class3/avatar/avatarV.glsl
deleted file mode 100644
index df9704ec25..0000000000
--- a/indra/newview/app_settings/shaders/class3/avatar/avatarV.glsl
+++ /dev/null
@@ -1,134 +0,0 @@
-/**
- * @file avatarV.glsl
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2007, 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$
- */
-
-uniform mat4 projection_matrix;
-
-ATTRIBUTE vec3 position;
-ATTRIBUTE vec3 normal;
-ATTRIBUTE vec2 texcoord0;
-ATTRIBUTE vec4 clothing;
-
-VARYING vec4 vertex_color;
-VARYING vec2 vary_texcoord0;
-
-vec4 calcLighting(vec3 pos, vec3 norm, vec4 color);
-mat4 getSkinnedTransform();
-void calcAtmospherics(vec3 inPositionEye);
-
-uniform vec4 color;
-
-uniform vec4 gWindDir;
-uniform vec4 gSinWaveParams;
-uniform vec4 gGravity;
-
-const vec4 gMinMaxConstants = vec4(1.0, 0.166666, 0.0083143, .00018542); // #minimax-generated coefficients
-const vec4 gPiConstants = vec4(0.159154943, 6.28318530, 3.141592653, 1.5707963); // # {1/2PI, 2PI, PI, PI/2}
-
-void main()
-{
- vary_texcoord0 = texcoord0;
-
- vec4 pos;
- mat4 trans = getSkinnedTransform();
-
- vec3 norm;
- norm.x = dot(trans[0].xyz, normal);
- norm.y = dot(trans[1].xyz, normal);
- norm.z = dot(trans[2].xyz, normal);
- norm = normalize(norm);
-
- //wind
- vec4 windEffect;
- windEffect = vec4(dot(norm, gWindDir.xyz));
- pos.x = dot(trans[2].xyz, position.xyz);
- windEffect.xyz = pos.x * vec3(0.015, 0.015, 0.015)
- + windEffect.xyz;
- windEffect.w = windEffect.w * 2.0 + 1.0; // move wind offset value to [-1, 3]
- windEffect.w = windEffect.w*gWindDir.w; // modulate wind strength
-
- windEffect.xyz = windEffect.xyz*gSinWaveParams.xyz
- +vec3(gSinWaveParams.w); // use sin wave params to scale and offset input
-
-
- //reduce to period of 2 PI
- vec4 temp1, temp0, temp2, offsetPos;
- temp1.xyz = windEffect.xyz * gPiConstants.x; // change input as multiple of [0-2PI] to [0-1]
- temp0.y = mod(temp1.x,1.0);
- windEffect.x = temp0.y * gPiConstants.y; // scale from [0,1] to [0, 2PI]
- temp1.z = temp1.z - gPiConstants.w; // shift normal oscillation by PI/2
- temp0.y = mod(temp1.z,1.0);
-
- windEffect.z = temp0.y * gPiConstants.y; // scale from [0,1] to [0, 2PI]
- windEffect.xyz = windEffect.xyz + vec3(-3.141592); // offset to [-PI, PI]
-
-
- //calculate sinusoid
- vec4 sinWave;
- temp1 = windEffect*windEffect;
- sinWave = -temp1 * gMinMaxConstants.w
- + vec4(gMinMaxConstants.z); // y = -(x^2)/7! + 1/5!
- sinWave = sinWave * -temp1 + vec4(gMinMaxConstants.y); // y = -(x^2) * (-(x^2)/7! + 1/5!) + 1/3!
- sinWave = sinWave * -temp1 + vec4(gMinMaxConstants.x); // y = -(x^2) * (-(x^2) * (-(x^2)/7! + 1/5!) + 1/3!) + 1
- sinWave = sinWave * windEffect; // y = x * (-(x^2) * (-(x^2) * (-(x^2)/7! + 1/5!) + 1/3!) + 1)
-
- // sinWave.x holds sin(norm . wind_direction) with primary frequency
- // sinWave.y holds sin(norm . wind_direction) with secondary frequency
- // sinWave.z hold cos(norm . wind_direction) with primary frequency
- sinWave.xyz = sinWave.xyz * gWindDir.w
- + vec3(windEffect.w); // multiply by wind strength in gWindDir.w [-wind, wind]
-
- // add normal facing bias offset [-wind,wind] -> [-wind - .25, wind + 1]
- temp1 = vec4(dot(norm, gGravity.xyz)); // how much is this normal facing in direction of gGravity?
- temp1 = min(temp1, vec4(0.2,0.0,0.0,0.0)); // clamp [-1, 1] to [-1, 0.2]
- temp1 = temp1*vec4(1.5,0.0,0.0,0.0); // scale from [-1,0.2] to [-1.5, 0.3]
- sinWave.x = sinWave.x + temp1.x; // add gGravity effect to sinwave (only primary frequency)
- sinWave.xyz = sinWave.xyz * clothing.w; // modulate by clothing coverage
-
- sinWave.xyz = max(sinWave.xyz, vec3(-1.0, -1.0, -1.0)); // clamp to underlying body shape
- offsetPos = clothing * sinWave.x; // multiply wind effect times clothing displacement
- temp2 = gWindDir*sinWave.z + vec4(norm,0); // calculate normal offset due to wind oscillation
- offsetPos = vec4(1.0,1.0,1.0,0.0)*offsetPos+vec4(position.xyz, 1.0); // add to offset vertex position, and zero out effect from w
- norm += temp2.xyz*2.0; // add sin wave effect on normals (exaggerated)
-
- //add "backlighting" effect
- float colorAcc;
- colorAcc = 1.0 - clothing.w;
- norm.z -= colorAcc * 0.2;
-
- //renormalize normal (again)
- norm = normalize(norm);
-
- pos.x = dot(trans[0], offsetPos);
- pos.y = dot(trans[1], offsetPos);
- pos.z = dot(trans[2], offsetPos);
- pos.w = 1.0;
-
- calcAtmospherics(pos.xyz);
-
- vec4 col = calcLighting(pos.xyz, norm, color);
- vertex_color = col;
-
- gl_Position = projection_matrix * pos;
-}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/attachmentShadowF.glsl b/indra/newview/app_settings/shaders/class3/deferred/attachmentShadowF.glsl
deleted file mode 100644
index d973326f93..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/attachmentShadowF.glsl
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
- * @file avatarShadowF.glsl
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2007, 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 sampler2D diffuseMap;
-
-VARYING vec4 pos;
-VARYING vec2 vary_texcoord0;
-
-vec4 computeMoments(float depth, float a);
-
-void main()
-{
- frag_color = computeMoments(length(pos), 1.0);
-}
-
diff --git a/indra/newview/app_settings/shaders/class3/deferred/avatarShadowF.glsl b/indra/newview/app_settings/shaders/class3/deferred/avatarShadowF.glsl
deleted file mode 100644
index 48eefc7a73..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/avatarShadowF.glsl
+++ /dev/null
@@ -1,52 +0,0 @@
-/**
- * @file avatarShadowF.glsl
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2007, 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 sampler2D diffuseMap;
-
-#if !defined(DEPTH_CLAMP)
-VARYING vec4 post_pos;
-#endif
-
-VARYING vec4 pos;
-
-vec4 computeMoments(float depth, float a);
-
-void main()
-{
- frag_color = computeMoments(length(pos), 1.0);
-
-#if !defined(DEPTH_CLAMP)
- gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0);
-#endif
-}
-
diff --git a/indra/newview/app_settings/shaders/class3/deferred/avatarShadowV.glsl b/indra/newview/app_settings/shaders/class3/deferred/avatarShadowV.glsl
deleted file mode 100644
index 164b355f20..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/avatarShadowV.glsl
+++ /dev/null
@@ -1,68 +0,0 @@
-/**
- * @file avatarShadowV.glsl
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2007, 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$
- */
-
-uniform mat4 projection_matrix;
-
-mat4 getSkinnedTransform();
-
-ATTRIBUTE vec3 position;
-ATTRIBUTE vec3 normal;
-ATTRIBUTE vec2 texcoord0;
-
-#if !defined(DEPTH_CLAMP)
-VARYING vec4 post_pos;
-#endif
-
-VARYING vec4 pos;
-
-void main()
-{
- vec3 norm;
-
- vec4 pos_in = vec4(position.xyz, 1.0);
- mat4 trans = getSkinnedTransform();
-
- pos.x = dot(trans[0], pos_in);
- pos.y = dot(trans[1], pos_in);
- pos.z = dot(trans[2], pos_in);
- pos.w = 1.0;
-
- norm.x = dot(trans[0].xyz, normal);
- norm.y = dot(trans[1].xyz, normal);
- norm.z = dot(trans[2].xyz, normal);
- norm = normalize(norm);
-
- pos = projection_matrix * pos;
-
-#if !defined(DEPTH_CLAMP)
- post_pos = pos;
- gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
-#else
- gl_Position = pos;
-#endif
-
-}
-
-
diff --git a/indra/newview/app_settings/shaders/class3/deferred/cloudShadowF.glsl b/indra/newview/app_settings/shaders/class3/deferred/cloudShadowF.glsl
deleted file mode 100644
index 32210f60dc..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/cloudShadowF.glsl
+++ /dev/null
@@ -1,119 +0,0 @@
-/**
- * @file class3/deferred/cloudsF.glsl
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2005, 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$
- */
-
-#ifdef DEFINE_GL_FRAGCOLOR
-out vec4 frag_color;
-#else
-#define frag_color gl_FragColor
-#endif
-
-uniform sampler2D diffuseMap;
-
-VARYING vec4 pos;
-VARYING float target_pos_x;
-VARYING float vary_CloudDensity;
-VARYING vec2 vary_texcoord0;
-VARYING vec2 vary_texcoord1;
-VARYING vec2 vary_texcoord2;
-VARYING vec2 vary_texcoord3;
-
-uniform sampler2D cloud_noise_texture;
-uniform sampler2D cloud_noise_texture_next;
-uniform float blend_factor;
-uniform vec4 cloud_pos_density1;
-uniform vec4 cloud_pos_density2;
-uniform vec4 cloud_color;
-uniform float cloud_shadow;
-uniform float cloud_scale;
-uniform float cloud_variance;
-uniform vec3 camPosLocal;
-uniform vec3 sun_dir;
-uniform float sun_size;
-uniform float far_z;
-
-vec4 cloudNoise(vec2 uv)
-{
- vec4 a = texture2D(cloud_noise_texture, uv);
- vec4 b = texture2D(cloud_noise_texture_next, uv);
- vec4 cloud_noise_sample = mix(a, b, blend_factor);
- return normalize(cloud_noise_sample);
-}
-
-vec4 computeMoments(float depth, float alpha);
-
-void main()
-{
- if (cloud_scale >= 0.001)
- {
- // Set variables
- vec2 uv1 = vary_texcoord0.xy;
- vec2 uv2 = vary_texcoord1.xy;
- vec2 uv3 = vary_texcoord2.xy;
- float cloudDensity = 2.0 * (cloud_shadow - 0.25);
-
- vec2 uv4 = vary_texcoord3.xy;
-
- vec2 disturbance = vec2(cloudNoise(uv1 / 8.0f).x, cloudNoise((uv3 + uv1) / 16.0f).x) * cloud_variance * (1.0f - cloud_scale * 0.25f);
- vec2 disturbance2 = vec2(cloudNoise((uv1 + uv3) / 4.0f).x, cloudNoise((uv4 + uv2) / 8.0f).x) * cloud_variance * (1.0f - cloud_scale * 0.25f);
-
- // Offset texture coords
- uv1 += cloud_pos_density1.xy + (disturbance * 0.2); //large texture, visible density
- uv2 += cloud_pos_density1.xy; //large texture, self shadow
- uv3 += cloud_pos_density2.xy; //small texture, visible density
- uv4 += cloud_pos_density2.xy; //small texture, self shadow
-
- float density_variance = min(1.0, (disturbance.x* 2.0 + disturbance.y* 2.0 + disturbance2.x + disturbance2.y) * 4.0);
-
- cloudDensity *= 1.0 - (density_variance * density_variance);
-
- // Compute alpha1, the main cloud opacity
- float alpha1 = (cloudNoise(uv1).x - 0.5) + (cloudNoise(uv3).x - 0.5) * cloud_pos_density2.z;
- alpha1 = min(max(alpha1 + cloudDensity, 0.) * 10 * cloud_pos_density1.z, 1.);
-
- // And smooth
- alpha1 = 1. - alpha1 * alpha1;
- alpha1 = 1. - alpha1 * alpha1;
-
- if (alpha1 < 0.001f)
- {
- discard;
- }
-
- // Compute alpha2, for self shadowing effect
- // (1 - alpha2) will later be used as percentage of incoming sunlight
- float alpha2 = (cloudNoise(uv2).x - 0.5);
- alpha2 = min(max(alpha2 + cloudDensity, 0.) * 2.5 * cloud_pos_density1.z, 1.);
-
- // And smooth
- alpha2 = 1. - alpha2;
- alpha2 = 1. - alpha2 * alpha2;
-
- frag_color = computeMoments(length(pos), alpha1);
- }
- else
- {
- frag_color = vec4(0);
- }
-}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/cloudShadowV.glsl b/indra/newview/app_settings/shaders/class3/deferred/cloudShadowV.glsl
deleted file mode 100644
index effb070f93..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/cloudShadowV.glsl
+++ /dev/null
@@ -1,63 +0,0 @@
-/**
- * @file cloudShadowV.glsl
- *
- * $LicenseInfo:firstyear=2011&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2011, 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$
- */
-
-uniform mat4 texture_matrix0;
-uniform mat4 modelview_projection_matrix;
-uniform float shadow_target_width;
-
-ATTRIBUTE vec3 position;
-ATTRIBUTE vec4 diffuse_color;
-ATTRIBUTE vec2 texcoord0;
-
-#if !defined(DEPTH_CLAMP)
-VARYING float pos_zd2;
-#endif
-
-VARYING vec4 pos;
-VARYING float target_pos_x;
-VARYING vec2 vary_texcoord0;
-VARYING vec4 vertex_color;
-
-void passTextureIndex();
-
-void main()
-{
- //transform vertex
- vec4 pre_pos = vec4(position.xyz, 1.0);
- pos = modelview_projection_matrix * pre_pos;
- target_pos_x = 0.5 * (shadow_target_width - 1.0) * pos.x;
-
-#if !defined(DEPTH_CLAMP)
- pos_zd2 = pos.z * 0.5;
- gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
-#else
- gl_Position = pos;
-#endif
-
- passTextureIndex();
-
- vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
- vertex_color = diffuse_color;
-}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/cloudsF.glsl b/indra/newview/app_settings/shaders/class3/deferred/cloudsF.glsl
deleted file mode 100644
index e40d7e7c75..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/cloudsF.glsl
+++ /dev/null
@@ -1,166 +0,0 @@
-/**
- * @file class3/deferred/cloudsF.glsl
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2005, 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$
- */
-
-#ifdef DEFINE_GL_FRAGCOLOR
-out vec4 frag_data[3];
-#else
-#define frag_data gl_FragData
-#endif
-
-/////////////////////////////////////////////////////////////////////////
-// The fragment shader for the sky
-/////////////////////////////////////////////////////////////////////////
-
-VARYING vec4 vary_CloudColorSun;
-VARYING vec4 vary_CloudColorAmbient;
-VARYING float vary_CloudDensity;
-VARYING vec2 vary_texcoord0;
-VARYING vec2 vary_texcoord1;
-VARYING vec2 vary_texcoord2;
-VARYING vec2 vary_texcoord3;
-VARYING vec3 vary_pos;
-
-uniform sampler2D cloud_noise_texture;
-uniform sampler2D cloud_noise_texture_next;
-uniform float blend_factor;
-uniform vec4 cloud_pos_density1;
-uniform vec4 cloud_pos_density2;
-uniform vec4 cloud_color;
-uniform float cloud_shadow;
-uniform float cloud_scale;
-uniform float cloud_variance;
-uniform vec3 camPosLocal;
-uniform vec3 sun_dir;
-uniform float sun_size;
-uniform float far_z;
-
-uniform sampler2D transmittance_texture;
-uniform sampler3D scattering_texture;
-uniform sampler3D single_mie_scattering_texture;
-uniform sampler2D irradiance_texture;
-uniform sampler2D sh_input_r;
-uniform sampler2D sh_input_g;
-uniform sampler2D sh_input_b;
-
-vec3 GetSkyLuminance(vec3 camPos, vec3 view_dir, float shadow_length, vec3 dir, out vec3 transmittance);
-
-/// Soft clips the light with a gamma correction
-vec3 scaleSoftClip(vec3 light);
-
-vec4 cloudNoise(vec2 uv)
-{
- vec4 a = texture2D(cloud_noise_texture, uv);
- vec4 b = texture2D(cloud_noise_texture_next, uv);
- vec4 cloud_noise_sample = mix(a, b, blend_factor);
- return cloud_noise_sample;
-}
-
-void main()
-{
- // Set variables
- vec2 uv1 = vary_texcoord0.xy;
- vec2 uv2 = vary_texcoord1.xy;
- vec2 uv3 = vary_texcoord2.xy;
- float cloudDensity = 2.0 * (cloud_shadow - 0.25);
-
- if (cloud_scale < 0.001)
- {
- discard;
- }
-
- vec2 uv4 = vary_texcoord3.xy;
-
- vec2 disturbance = vec2(cloudNoise(uv1 / 16.0f).x, cloudNoise((uv3 + uv1) / 16.0f).x) * cloud_variance * (1.0f - cloud_scale * 0.25f);
-
- // Offset texture coords
- uv1 += cloud_pos_density1.xy + (disturbance * 0.2); //large texture, visible density
- uv2 += cloud_pos_density1.xy; //large texture, self shadow
- uv3 += cloud_pos_density2.xy; //small texture, visible density
- uv4 += cloud_pos_density2.xy; //small texture, self shadow
-
- float density_variance = min(1.0, (disturbance.x* 2.0 + disturbance.y* 2.0) * 4.0);
-
- cloudDensity *= 1.0 - (density_variance * density_variance);
-
- // Compute alpha1, the main cloud opacity
- float alpha1 = (cloudNoise(uv1).x - 0.5) + (cloudNoise(uv3).x - 0.5) * cloud_pos_density2.z;
- alpha1 = min(max(alpha1 + cloudDensity, 0.) * 10 * cloud_pos_density1.z, 1.);
-
- // And smooth
- alpha1 = 1. - alpha1 * alpha1;
- alpha1 = 1. - alpha1 * alpha1;
-
- if (alpha1 < 0.001f)
- {
- discard;
- }
-
- // Compute alpha2, for self shadowing effect
- // (1 - alpha2) will later be used as percentage of incoming sunlight
- float alpha2 = (cloudNoise(uv2).x - 0.5);
- alpha2 = min(max(alpha2 + cloudDensity, 0.) * 2.5 * cloud_pos_density1.z, 1.);
-
- // And smooth
- alpha2 = 1. - alpha2;
- alpha2 = 1. - alpha2 * alpha2;
-
- vec3 view_ray = vary_pos.xyz + camPosLocal;
-
- vec3 view_direction = normalize(view_ray);
- vec3 sun_direction = normalize(sun_dir);
- vec3 earth_center = vec3(0, 0, -6360.0f);
- vec3 camPos = (camPosLocal / 1000.0f) - earth_center;
-
- vec3 transmittance;
- vec3 radiance_sun = GetSkyLuminance(camPos, view_direction, 1.0 - alpha1, sun_direction, transmittance);
-
- vec3 sun_color = vec3(1.0) - exp(-radiance_sun * 0.0001);
-
- // Combine
- vec4 color;
-
- vec4 l1tap = vec4(1.0/sqrt(4*3.14159265), sqrt(3)/sqrt(4*3.14159265), sqrt(3)/sqrt(4*3.14159265), sqrt(3)/sqrt(4*3.14159265));
-
- vec4 l1r = texture2D(sh_input_r, vec2(0,0));
- vec4 l1g = texture2D(sh_input_g, vec2(0,0));
- vec4 l1b = texture2D(sh_input_b, vec2(0,0));
-
- vec3 sun_indir = vec3(-view_direction.xy, view_direction.z);
- vec3 amb = vec3(dot(l1r, l1tap * vec4(1, sun_indir)),
- dot(l1g, l1tap * vec4(1, sun_indir)),
- dot(l1b, l1tap * vec4(1, sun_indir)));
-
-
- amb = max(vec3(0), amb);
-
- color.rgb = sun_color * cloud_color.rgb * (1. - alpha2);
- color.rgb = pow(color.rgb, vec3(1.0 / 2.2));
- color.rgb += amb;
-
- frag_data[0] = vec4(color.rgb, alpha1);
- frag_data[1] = vec4(0);
- frag_data[2] = vec4(0,1,0,1);
-}
-
diff --git a/indra/newview/app_settings/shaders/class3/deferred/cloudsV.glsl b/indra/newview/app_settings/shaders/class3/deferred/cloudsV.glsl
deleted file mode 100644
index 71e422ddf0..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/cloudsV.glsl
+++ /dev/null
@@ -1,70 +0,0 @@
-/**
- * @file WLCloudsV.glsl
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2005, 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$
- */
-
-uniform mat4 modelview_projection_matrix;
-uniform mat4 modelview_matrix;
-
-ATTRIBUTE vec3 position;
-ATTRIBUTE vec2 texcoord0;
-
-//////////////////////////////////////////////////////////////////////////
-// The vertex shader for creating the atmospheric sky
-///////////////////////////////////////////////////////////////////////////////
-
-// Output parameters
-VARYING vec2 vary_texcoord0;
-VARYING vec2 vary_texcoord1;
-VARYING vec2 vary_texcoord2;
-VARYING vec2 vary_texcoord3;
-VARYING vec3 vary_pos;
-
-// Inputs
-uniform float cloud_scale;
-uniform vec4 lightnorm;
-uniform vec3 camPosLocal;
-
-void main()
-{
- vary_pos = position;
-
- // World / view / projection
- gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
-
- // Texture coords
- vary_texcoord0 = texcoord0;
- vary_texcoord0.xy -= 0.5;
- vary_texcoord0.xy /= max(0.001, cloud_scale);
- vary_texcoord0.xy += 0.5;
-
- vary_texcoord1 = vary_texcoord0;
- vary_texcoord1.x += lightnorm.x * 0.0125;
- vary_texcoord1.y += lightnorm.z * 0.0125;
-
- vary_texcoord2 = vary_texcoord0 * 16.;
- vary_texcoord3 = vary_texcoord1 * 16.;
-
- // END CLOUDS
-}
-
diff --git a/indra/newview/app_settings/shaders/class3/deferred/deferredUtil.glsl b/indra/newview/app_settings/shaders/class3/deferred/deferredUtil.glsl
deleted file mode 100644
index e27bbce094..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/deferredUtil.glsl
+++ /dev/null
@@ -1,79 +0,0 @@
-/**
- * @file class1/deferred/deferredUtil.glsl
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2007, 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$
- */
-
-uniform sampler2DRect normalMap;
-uniform sampler2DRect depthMap;
-
-uniform mat4 inv_proj;
-uniform vec2 screen_res;
-
-vec2 getScreenCoordinate(vec2 screenpos)
-{
- vec2 sc = screenpos.xy * 2.0;
- if (screen_res.x > 0 && screen_res.y > 0)
- {
- sc /= screen_res;
- }
- return sc - vec2(1.0, 1.0);
-}
-
-vec3 getNorm(vec2 screenpos)
-{
- vec2 enc = texture2DRect(normalMap, screenpos.xy).xy;
- vec2 fenc = enc*4-2;
- float f = dot(fenc,fenc);
- float g = sqrt(1-f/4);
- vec3 n;
- n.xy = fenc*g;
- n.z = 1-f/2;
- return n;
-}
-
-float getDepth(vec2 pos_screen)
-{
- float depth = texture2DRect(depthMap, pos_screen).r;
- return depth;
-}
-
-vec4 getPosition(vec2 pos_screen)
-{
- float depth = getDepth(pos_screen);
- vec2 sc = getScreenCoordinate(pos_screen);
- vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
- vec4 pos = inv_proj * ndc;
- pos /= pos.w;
- pos.w = 1.0;
- return pos;
-}
-
-vec4 getPositionWithDepth(vec2 pos_screen, float depth)
-{
- vec2 sc = getScreenCoordinate(pos_screen);
- vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
- vec4 pos = inv_proj * ndc;
- pos /= pos.w;
- pos.w = 1.0;
- return pos;
-}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/depthToShadowVolumeG.glsl b/indra/newview/app_settings/shaders/class3/deferred/depthToShadowVolumeG.glsl
deleted file mode 100644
index cdaff4b09f..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/depthToShadowVolumeG.glsl
+++ /dev/null
@@ -1,202 +0,0 @@
-/**
- * @file depthToShadowVolumeG.glsl
- *
- * $LicenseInfo:firstyear=2011&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2011, 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$
- */
-#extension GL_ARB_geometry_shader4 : enable
-#extension GL_ARB_texture_rectangle : enable
-
-/*[EXTRA_CODE_HERE]*/
-
-layout (triangles) in;
-layout (triangle_strip, max_vertices = 128) out;
-
-uniform sampler2DRect depthMap;
-uniform mat4 shadowMatrix[6];
-uniform vec4 lightpos;
-
-VARYING vec2 vary_texcoord0;
-
-out vec3 to_vec;
-
-void cross_products(out vec4 ns[3], int a, int b, int c)
-{
- ns[0] = cross(gl_PositionIn[b].xyz - gl_PositionIn[a].xyz, gl_PositionIn[c].xyz - gl_PositionIn[a].xyz);
- ns[1] = cross(gl_PositionIn[c].xyz - gl_PositionIn[b].xyz, gl_PositionIn[a].xyz - gl_PositionIn[b].xyz);
- ns[2] = cross(gl_PositionIn[a].xyz - gl_PositionIn[c].xyz, gl_PositionIn[b].xyz - gl_PositionIn[c].xyz);
-}
-
-vec3 getLightDirection(vec4 lightpos, vec3 pos)
-{
-
- vec3 lightdir = lightpos.xyz - lightpos.w * pos;
- return lightdir;
-}
-
-void emitTri(vec4 v[3])
-{
- gl_Position = proj_matrix * v[0];
- EmitVertex();
-
- gl_Position = proj_matrix * v[1];
- EmitVertex();
-
- gl_Position = proj_matrix * v[2];
- EmitVertex();
-
- EndPrimitive();
-}
-
-void emitQuad(vec4 v[4]
-{
- // Emit a quad as a triangle strip.
- gl_Position = proj_matrix*v[0];
- EmitVertex();
-
- gl_Position = proj_matrix*v[1];
- EmitVertex();
-
- gl_Position = proj_matrix*v[2];
- EmitVertex();
-
- gl_Position = proj_matrix*v[3];
- EmitVertex();
-
- EndPrimitive();
-}
-
-void emitPrimitives(int layer)
-{
- int i = layer;
- gl_Layer = i;
-
- vec4 depth1 = vec4(texture2DRect(depthMap, tc0).rg, texture2DRect(depthMap, tc1).rg));
- vec3 depth2 = vec4(texture2DRect(depthMap, tc2).rg, texture2DRect(depthMap, tc3).rg));
- vec3 depth3 = vec4(texture2DRect(depthMap, tc4).rg, texture2DRect(depthMap, tc5).rg));
- vec3 depth4 = vec4(texture2DRect(depthMap, tc6).rg, texture2DRect(depthMap, tc7).rg));
-
- depth1 = min(depth1, depth2);
- depth1 = min(depth1, depth3);
- depth1 = min(depth1, depth4);
-
- vec2 depth = min(depth1.xy, depth1.zw);
-
- int side = sqrt(gl_VerticesIn);
-
- for (int j = 0; j < side; j++)
- {
- for (int k = 0; k < side; ++k)
- {
- vec3 pos = gl_PositionIn[(j * side) + k].xyz;
- vec4 v = shadowMatrix[i] * vec4(pos, 1.0);
- gl_Position = v;
- to_vec = pos - light_position.xyz * depth;
- EmitVertex();
- }
-
- EndPrimitive();
- }
-
- vec3 norms[3]; // Normals
- vec3 lightdir3]; // Directions toward light
-
- vec4 v[4]; // Temporary vertices
-
- vec4 or_pos[3] =
- { // Triangle oriented toward light source
- gl_PositionIn[0],
- gl_PositionIn[2],
- gl_PositionIn[4]
- };
-
- // Compute normal at each vertex.
- cross_products(n, 0, 2, 4);
-
- // Compute direction from vertices to light.
- lightdir[0] = getLightDirection(lightpos, gl_PositionIn[0].xyz);
- lightdir[1] = getLightDirection(lightpos, gl_PositionIn[2].xyz);
- lightdir[2] = getLightDirection(lightpos, gl_PositionIn[4].xyz);
-
- // Check if the main triangle faces the light.
- bool faces_light = true;
- if (!(dot(ns[0],d[0]) > 0
- |dot(ns[1],d[1]) > 0
- |dot(ns[2],d[2]) > 0))
- {
- // Flip vertex winding order in or_pos.
- or_pos[1] = gl_PositionIn[4];
- or_pos[2] = gl_PositionIn[2];
- faces_light = false;
- }
-
- // Near cap: simply render triangle.
- emitTri(or_pos);
-
- // Far cap: extrude positions to infinity.
- v[0] =vec4(lightpos.w * or_pos[0].xyz - lightpos.xyz,0);
- v[1] =vec4(lightpos.w * or_pos[2].xyz - lightpos.xyz,0);
- v[2] =vec4(lightpos.w * or_pos[1].xyz - lightpos.xyz,0);
-
- emitTri(v);
-
- // Loop over all edges and extrude if needed.
- for ( int i=0; i<3; i++ )
- {
- // Compute indices of neighbor triangle.
- int v0 = i*2;
- int nb = (i*2+1);
- int v1 = (i*2+2) % 6;
- cross_products(n, v0, nb, v1);
-
- // Compute direction to light, again as above.
- d[0] =lightpos.xyz-lightpos.w*gl_PositionIn[v0].xyz;
- d[1] =lightpos.xyz-lightpos.w*gl_PositionIn[nb].xyz;
- d[2] =lightpos.xyz-lightpos.w*gl_PositionIn[v1].xyz;
-
- bool is_parallel = gl_PositionIn[nb].w < 1e-5;
-
- // Extrude the edge if it does not have a
- // neighbor, or if it's a possible silhouette.
- if (is_parallel ||
- ( faces_light != (dot(ns[0],d[0])>0 ||
- dot(ns[1],d[1])>0 ||
- dot(ns[2],d[2])>0) ))
- {
- // Make sure sides are oriented correctly.
- int i0 = faces_light ? v0 : v1;
- int i1 = faces_light ? v1 : v0;
-
- v[0] = gl_PositionIn[i0];
- v[1] = vec4(lightpos.w*gl_PositionIn[i0].xyz - lightpos.xyz, 0);
- v[2] = gl_PositionIn[i1];
- v[3] = vec4(lightpos.w*gl_PositionIn[i1].xyz - lightpos.xyz, 0);
-
- emitQuad(v);
- }
- }
-}
-
-void main()
-{
- // Output
- emitPrimitives(0);
-}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/fullbrightShinyF.glsl b/indra/newview/app_settings/shaders/class3/deferred/fullbrightShinyF.glsl
new file mode 100644
index 0000000000..160d360256
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/fullbrightShinyF.glsl
@@ -0,0 +1,107 @@
+/**
+ * @file fullbrightShinyF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2007, 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
+
+#ifndef HAS_DIFFUSE_LOOKUP
+uniform sampler2D diffuseMap;
+#endif
+
+
+VARYING vec4 vertex_color;
+VARYING vec2 vary_texcoord0;
+VARYING vec3 vary_texcoord1;
+VARYING vec3 vary_position;
+
+uniform samplerCube environmentMap;
+
+// render_hud_attachments() -> HUD objects set LLShaderMgr::NO_ATMO; used in LLDrawPoolAlpha::beginRenderPass()
+uniform int no_atmo;
+
+vec3 fullbrightShinyAtmosTransport(vec3 light);
+vec3 fullbrightAtmosTransportFrag(vec3 light, vec3 additive, vec3 atten);
+vec3 fullbrightScaleSoftClip(vec3 light);
+
+void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, out vec3 sunlit, out vec3 amblit, out vec3 additive, out vec3 atten, bool use_ao);
+
+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,
+ 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);
+
+// See:
+// class1\deferred\fullbrightShinyF.glsl
+// class1\lighting\lightFullbrightShinyF.glsl
+void main()
+{
+#ifdef HAS_DIFFUSE_LOOKUP
+ vec4 color = diffuseLookup(vary_texcoord0.xy);
+#else
+ vec4 color = texture2D(diffuseMap, vary_texcoord0.xy);
+#endif
+
+ color.rgb *= vertex_color.rgb;
+
+ // SL-9632 HUDs are affected by Atmosphere
+ if (no_atmo == 0)
+ {
+ vec3 sunlit;
+ vec3 amblit;
+ vec3 additive;
+ vec3 atten;
+ vec3 pos = vary_position;
+ calcAtmosphericVars(pos.xyz, vec3(0), 1.0, sunlit, amblit, additive, atten, false);
+
+ float env_intensity = vertex_color.a;
+
+ vec3 ambenv;
+ vec3 glossenv;
+ vec3 legacyenv;
+ vec3 norm = normalize(vary_texcoord1.xyz);
+ vec4 spec = vec4(0,0,0,0);
+ 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);
+ color.rgb = fullbrightScaleSoftClip(color.rgb);
+ }
+
+ color.a = 1.0;
+
+ color.rgb = srgb_to_linear(color.rgb);
+ frag_color = color;
+}
+
diff --git a/indra/newview/app_settings/shaders/class3/deferred/gatherSkyShF.glsl b/indra/newview/app_settings/shaders/class3/deferred/gatherSkyShF.glsl
deleted file mode 100644
index 34d26cddea..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/gatherSkyShF.glsl
+++ /dev/null
@@ -1,70 +0,0 @@
-/**
- * @file class3/deferred/gatherSkyShF.glsl
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2005, 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$
- */
-
-#ifdef DEFINE_GL_FRAGCOLOR
-out vec4 frag_data[3];
-#else
-#define frag_data gl_FragData
-#endif
-
-VARYING vec2 vary_frag;
-
-uniform vec2 screen_res;
-uniform sampler2D sh_input_r;
-uniform sampler2D sh_input_g;
-uniform sampler2D sh_input_b;
-
-void main()
-{
- vec2 offset = vec2(2.0) / screen_res;
-
- vec4 r = vec4(0);
- vec4 g = vec4(0);
- vec4 b = vec4(0);
-
- vec2 tc = vary_frag * 2.0;
-
- r += texture2D(sh_input_r, tc + vec2(0, 0));
- r += texture2D(sh_input_r, tc + vec2(offset.x, 0));
- r += texture2D(sh_input_r, tc + vec2(0, offset.y));
- r += texture2D(sh_input_r, tc + vec2(offset.x, offset.y));
- r /= 4.0f;
-
- g += texture2D(sh_input_g, tc + vec2(0, 0));
- g += texture2D(sh_input_g, tc + vec2(offset.x, 0));
- g += texture2D(sh_input_g, tc + vec2(0, offset.y));
- g += texture2D(sh_input_g, tc + vec2(offset.x, offset.y));
- g /= 4.0f;
-
- b += texture2D(sh_input_b, tc + vec2(0, 0));
- b += texture2D(sh_input_b, tc + vec2(offset.x, 0));
- b += texture2D(sh_input_b, tc + vec2(0, offset.y));
- b += texture2D(sh_input_b, tc + vec2(offset.x, offset.y));
- b /= 4.0f;
-
- frag_data[0] = r;
- frag_data[1] = g;
- frag_data[2] = b;
-}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/gatherSkyShV.glsl b/indra/newview/app_settings/shaders/class3/deferred/gatherSkyShV.glsl
deleted file mode 100644
index 337c8a50fe..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/gatherSkyShV.glsl
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * @file gatherSkyShV.glsl
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2005, 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$
- */
-
-ATTRIBUTE vec3 position;
-ATTRIBUTE vec2 texcoord0;
-
-VARYING vec2 vary_frag;
-uniform vec2 screen_res;
-
-void main()
-{
- // pass through untransformed fullscreen pos
- float oo_divisor = screen_res.x / 64.0;
- vec3 pos = (position.xyz * oo_divisor) + vec3(oo_divisor - 1, oo_divisor - 1, 0);
- gl_Position = vec4(pos.xyz, 1.0);
- vary_frag = texcoord0 * oo_divisor;
-}
-
diff --git a/indra/newview/app_settings/shaders/class3/deferred/genSkyShF.glsl b/indra/newview/app_settings/shaders/class3/deferred/genSkyShF.glsl
deleted file mode 100644
index d5d91c88f0..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/genSkyShF.glsl
+++ /dev/null
@@ -1,111 +0,0 @@
-/**
- * @file class3/deferred/genSkyShF.glsl
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2005, 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$
- */
-
-#ifdef DEFINE_GL_FRAGCOLOR
-out vec4 frag_data[3];
-#else
-#define frag_data gl_FragData
-#endif
-
-VARYING vec2 vary_frag;
-
-uniform vec3 sun_dir;
-
-uniform sampler2D transmittance_texture;
-uniform sampler3D scattering_texture;
-uniform sampler3D single_mie_scattering_texture;
-uniform sampler2D irradiance_texture;
-
-vec3 GetSkyLuminance(vec3 camPos, vec3 view_dir, float shadow_length, vec3 dir, out vec3 transmittance);
-
-vec3 calcDirection(vec2 tc)
-{
- float phi = tc.y * 2.0 * 3.14159265;
- float cosTheta = sqrt(1.0 - tc.x);
- float sinTheta = sqrt(1.0 - cosTheta * cosTheta);
- return vec3(cos(phi) * sinTheta, sin(phi) * sinTheta, cosTheta);
-}
-
-// reverse mapping above to convert a hemisphere direction into phi/theta values
-void getPhiAndThetaFromDirection(vec3 dir, out float phi, out float theta)
-{
- float sin_theta;
- float cos_theta;
- cos_theta = dir.z;
- theta = acos(cos_theta);
- sin_theta = sin(theta);
- phi = abs(sin_theta) > 0.0001 ? acos(dir.x / sin_theta) : 1.0;
-}
-
-// reverse mapping above to convert a hemisphere direction into an SH texture sample pos
-vec2 calcShUvFromDirection(vec3 dir)
-{
- vec2 uv;
- float phi;
- float theta;
- getPhiAndThetaFromDirection(dir, phi, theta);
- uv.y = phi / 2.0 * 3.14159265;
- uv.x = theta / 2.0 * 3.14159265;
- return uv;
-}
-
-void projectToL1(vec3 n, vec3 c, vec4 basis, out vec4 coeffs[3])
-{
- coeffs[0] = vec4(basis.x, n * basis.yzw * c.r);
- coeffs[1] = vec4(basis.x, n * basis.yzw * c.g);
- coeffs[2] = vec4(basis.x, n * basis.yzw * c.b);
-}
-
-void main()
-{
- float Y00 = sqrt(1.0 / 3.14159265) * 0.5;
- float Y1x = sqrt(3.0 / 3.14159265) * 0.5;
- float Y1y = Y1x;
- float Y1z = Y1x;
-
- vec4 L1 = vec4(Y00, Y1x, Y1y, Y1z);
-
- vec3 view_direction = calcDirection(vary_frag);
- vec3 sun_direction = normalize(sun_dir);
- vec3 cam_pos = vec3(0, 0, 6360);
-
- vec3 transmittance;
- vec3 radiance = GetSkyLuminance(cam_pos, view_direction, 0.0f, sun_direction, transmittance);
-
- vec3 color = vec3(1.0) - exp(-radiance * 0.0001);
-
- color = pow(color, vec3(1.0/2.2));
-
- vec4 coeffs[3];
- coeffs[0] = vec4(0);
- coeffs[1] = vec4(0);
- coeffs[2] = vec4(0);
-
- projectToL1(view_direction, color.rgb, L1, coeffs);
-
- frag_data[0] = coeffs[0];
- frag_data[1] = coeffs[1];
- frag_data[2] = coeffs[2];
-}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/indirect.glsl b/indra/newview/app_settings/shaders/class3/deferred/indirect.glsl
deleted file mode 100644
index 33c5667cae..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/indirect.glsl
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
- * @file class3/deferred/indirect.glsl
- *
- * $LicenseInfo:firstyear=2011&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2011, 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]*/
-
-uniform sampler2D sh_input_r;
-uniform sampler2D sh_input_g;
-uniform sampler2D sh_input_b;
-
-vec3 GetIndirect(vec3 norm)
-{
- vec4 l1tap = vec4(1.0/sqrt(4*3.14159265), sqrt(3)/sqrt(4*3.14159265), sqrt(3)/sqrt(4*3.14159265), sqrt(3)/sqrt(4*3.14159265));
- vec4 l1r = texture2D(sh_input_r, vec2(0,0));
- vec4 l1g = texture2D(sh_input_g, vec2(0,0));
- vec4 l1b = texture2D(sh_input_b, vec2(0,0));
- vec3 indirect = vec3(dot(l1r, l1tap * vec4(1, norm.xyz)),
- dot(l1g, l1tap * vec4(1, norm.xyz)),
- dot(l1b, l1tap * vec4(1, norm.xyz)));
- indirect = clamp(indirect, vec3(0), vec3(1.0));
- return indirect;
-}
-
diff --git a/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl
new file mode 100644
index 0000000000..8d2a65d4a9
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl
@@ -0,0 +1,380 @@
+/**
+* @file materialF.glsl
+*
+* $LicenseInfo:firstyear=2007&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2007, 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]*/
+
+//class1/deferred/materialF.glsl
+
+// This shader is used for both writing opaque/masked content to the gbuffer and writing blended content to the framebuffer during the alpha pass.
+
+#define DIFFUSE_ALPHA_MODE_NONE 0
+#define DIFFUSE_ALPHA_MODE_BLEND 1
+#define DIFFUSE_ALPHA_MODE_MASK 2
+#define DIFFUSE_ALPHA_MODE_EMISSIVE 3
+
+uniform float emissive_brightness; // fullbright flag, 1.0 == fullbright, 0.0 otherwise
+uniform int sun_up_factor;
+
+#ifdef WATER_FOG
+vec4 applyWaterFogView(vec3 pos, vec4 color);
+#endif
+
+vec3 atmosFragLightingLinear(vec3 l, vec3 additive, vec3 atten);
+vec3 scaleSoftClipFragLinear(vec3 l);
+void calcAtmosphericVarsLinear(vec3 inPositionEye, vec3 norm, vec3 light_dir, out vec3 sunlit, out vec3 amblit, out vec3 atten, out vec3 additive);
+vec3 fullbrightAtmosTransportFragLinear(vec3 light, vec3 additive, vec3 atten);
+
+vec3 srgb_to_linear(vec3 cs);
+vec3 linear_to_srgb(vec3 cs);
+
+#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_color;
+#else
+#define frag_color gl_FragColor
+#endif
+
+#ifdef HAS_SUN_SHADOW
+float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen);
+#endif
+
+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);
+
+uniform samplerCube environmentMap;
+uniform sampler2D lightFunc;
+
+// Inputs
+uniform vec4 morphFactor;
+uniform vec3 camPosLocal;
+uniform mat3 env_mat;
+
+uniform vec3 sun_dir;
+uniform vec3 moon_dir;
+VARYING vec2 vary_fragcoord;
+
+VARYING vec3 vary_position;
+
+uniform mat4 proj_mat;
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+
+uniform vec4 light_position[8];
+uniform vec3 light_direction[8];
+uniform vec4 light_attenuation[8];
+uniform vec3 light_diffuse[8];
+
+float getAmbientClamp();
+void waterClip(vec3 pos);
+
+vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 npos, vec3 diffuse, vec4 spec, vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight, float ambiance)
+{
+ // SL-14895 inverted attenuation work-around
+ // This routine is tweaked to match deferred lighting, but previously used an inverted la value. To reconstruct
+ // that previous value now that the inversion is corrected, we reverse the calculations in LLPipeline::setupHWLights()
+ // to recover the `adjusted_radius` value previously being sent as la.
+ float falloff_factor = (12.0 * fa) - 9.0;
+ float inverted_la = falloff_factor / la;
+ // Yes, it makes me want to cry as well. DJH
+
+ vec3 col = vec3(0);
+
+ //get light vector
+ vec3 lv = lp.xyz - v;
+
+ //get distance
+ float dist = length(lv);
+ float da = 1.0;
+
+ dist /= inverted_la;
+
+ if (dist > 0.0 && inverted_la > 0.0)
+ {
+ //normalize light vector
+ lv = normalize(lv);
+
+ //distance attenuation
+ float dist_atten = clamp(1.0 - (dist - 1.0*(1.0 - fa)) / fa, 0.0, 1.0);
+ dist_atten *= dist_atten;
+ dist_atten *= 2.0f;
+
+ if (dist_atten <= 0.0)
+ {
+ return col;
+ }
+
+ // spotlight coefficient.
+ float spot = max(dot(-ln, lv), is_pointlight);
+ da *= spot*spot; // GL_SPOT_EXPONENT=2
+
+ //angular attenuation
+ da *= dot(n, lv);
+
+ float lit = 0.0f;
+
+ float amb_da = ambiance;
+ if (da >= 0)
+ {
+ lit = max(da * dist_atten, 0.0);
+ col = lit * light_col * diffuse;
+ amb_da += (da*0.5 + 0.5) * ambiance;
+ }
+ amb_da += (da*da*0.5 + 0.5) * ambiance;
+ amb_da *= dist_atten;
+ amb_da = min(amb_da, 1.0f - lit);
+
+ // SL-10969 need to see why these are blown out
+ //col.rgb += amb_da * light_col * diffuse;
+
+ if (spec.a > 0.0)
+ {
+ //vec3 ref = dot(pos+lv, norm);
+ vec3 h = normalize(lv + npos);
+ float nh = dot(n, h);
+ float nv = dot(n, 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);
+ vec3 speccol = lit*scol*light_col.rgb*spec.rgb;
+ speccol = clamp(speccol, vec3(0), vec3(1));
+ col += speccol;
+ }
+ }
+ }
+
+ return max(col, vec3(0.0, 0.0, 0.0));
+}
+
+#else
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_data[3];
+#else
+#define frag_data gl_FragData
+#endif
+#endif
+
+uniform sampler2D diffuseMap; //always in sRGB space
+
+#ifdef HAS_NORMAL_MAP
+uniform sampler2D bumpMap;
+#endif
+
+#ifdef HAS_SPECULAR_MAP
+uniform sampler2D specularMap;
+
+VARYING vec2 vary_texcoord2;
+#endif
+
+uniform float env_intensity;
+uniform vec4 specular_color; // specular color RGB and specular exponent (glossiness) in alpha
+
+#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_MASK)
+uniform float minimum_alpha;
+#endif
+
+#ifdef HAS_NORMAL_MAP
+VARYING vec3 vary_mat0;
+VARYING vec3 vary_mat1;
+VARYING vec3 vary_mat2;
+VARYING vec2 vary_texcoord1;
+#else
+VARYING vec3 vary_normal;
+#endif
+
+VARYING vec4 vertex_color;
+VARYING vec2 vary_texcoord0;
+
+vec2 encode_normal(vec3 n);
+
+void main()
+{
+#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
+ waterClip(vary_position.xyz);
+#endif
+
+ vec2 pos_screen = vary_texcoord0.xy;
+
+ vec4 diffcol = texture2D(diffuseMap, vary_texcoord0.xy);
+ diffcol.rgb *= vertex_color.rgb;
+
+#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_MASK)
+
+ // Comparing floats cast from 8-bit values, produces acne right at the 8-bit transition points
+ float bias = 0.001953125; // 1/512, or half an 8-bit quantization
+ if (diffcol.a < minimum_alpha-bias)
+ {
+ discard;
+ }
+#endif
+
+#ifdef HAS_SPECULAR_MAP
+ vec4 spec = texture2D(specularMap, vary_texcoord2.xy);
+ spec.rgb *= specular_color.rgb;
+#else
+ vec4 spec = vec4(specular_color.rgb, 1.0);
+#endif
+
+#ifdef HAS_NORMAL_MAP
+ vec4 norm = texture2D(bumpMap, vary_texcoord1.xy);
+
+ norm.xyz = norm.xyz * 2 - 1;
+
+ vec3 tnorm = vec3(dot(norm.xyz,vary_mat0),
+ dot(norm.xyz,vary_mat1),
+ dot(norm.xyz,vary_mat2));
+#else
+ vec4 norm = vec4(0,0,0,1.0);
+ vec3 tnorm = vary_normal;
+#endif
+
+ norm.xyz = normalize(tnorm.xyz);
+
+ vec2 abnormal = encode_normal(norm.xyz);
+
+ vec4 final_color = diffcol;
+
+#if (DIFFUSE_ALPHA_MODE != DIFFUSE_ALPHA_MODE_EMISSIVE)
+ final_color.a = emissive_brightness;
+#else
+ final_color.a = max(final_color.a, emissive_brightness);
+#endif
+
+ vec4 final_specular = spec;
+
+#ifdef HAS_SPECULAR_MAP
+ vec4 final_normal = vec4(encode_normal(normalize(tnorm)), env_intensity * spec.a, GBUFFER_FLAG_HAS_ATMOS);
+ final_specular.a = specular_color.a * norm.a;
+#else
+ vec4 final_normal = vec4(encode_normal(normalize(tnorm)), env_intensity, GBUFFER_FLAG_HAS_ATMOS);
+ final_specular.a = specular_color.a;
+#endif
+
+#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
+ //forward rendering, output lit linear color
+ diffcol.rgb = srgb_to_linear(diffcol.rgb);
+ final_specular.rgb = srgb_to_linear(final_specular.rgb);
+
+ vec3 pos = vary_position;
+
+ float shadow = 1.0f;
+
+#ifdef HAS_SUN_SHADOW
+ shadow = sampleDirectionalShadow(pos.xyz, norm.xyz, pos_screen);
+#endif
+
+ vec4 diffuse = final_color;
+
+ vec3 color = vec3(0,0,0);
+
+ vec3 light_dir = (sun_up_factor == 1) ? sun_dir : moon_dir;
+
+ float bloom = 0.0;
+ vec3 sunlit;
+ vec3 amblit;
+ vec3 additive;
+ vec3 atten;
+ calcAtmosphericVarsLinear(pos.xyz, norm.xyz, light_dir, sunlit, amblit, additive, atten);
+
+ vec3 ambenv;
+ vec3 glossenv;
+ vec3 legacyenv;
+ 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);
+
+ float da = clamp(dot(norm.xyz, light_dir.xyz), 0.0, 1.0);
+ vec3 sun_contrib = min(da, shadow) * sunlit;
+ color.rgb += sun_contrib;
+ color *= diffcol.rgb;
+
+ vec3 refnormpersp = reflect(pos.xyz, norm.xyz);
+
+ if (final_specular.a > 0.0) // specular reflection
+ {
+ float sa = dot(normalize(refnormpersp), light_dir.xyz);
+ vec3 dumbshiny = sunlit * shadow * (texture2D(lightFunc, vec2(sa, final_specular.a)).r);
+
+ // add the two types of shiny together
+ vec3 spec_contrib = dumbshiny * final_specular.rgb;
+ bloom = dot(spec_contrib, spec_contrib) / 6;
+
+ color += spec_contrib;
+
+ applyGlossEnv(color, glossenv, final_specular, pos.xyz, norm.xyz);
+ }
+
+ color = mix(color.rgb, diffcol.rgb, diffuse.a);
+
+ if (env_intensity > 0.0)
+ { // add environmentmap
+ applyLegacyEnv(color, legacyenv, final_specular, pos.xyz, norm.xyz, env_intensity);
+ }
+
+ color.rgb = mix(atmosFragLightingLinear(color.rgb, additive, atten), fullbrightAtmosTransportFragLinear(color, additive, atten), diffuse.a);
+ color.rgb = scaleSoftClipFragLinear(color.rgb);
+
+#ifdef WATER_FOG
+ vec4 temp = applyWaterFogView(pos, vec4(color, 0.0));
+ color = temp.rgb;
+#endif
+
+ vec3 npos = normalize(-pos.xyz);
+ vec3 light = vec3(0, 0, 0);
+
+#define LIGHT_LOOP(i) light.rgb += calcPointLightOrSpotLight(light_diffuse[i].rgb, npos, diffuse.rgb, final_specular, pos.xyz, norm.xyz, light_position[i], light_direction[i].xyz, light_attenuation[i].x, light_attenuation[i].y, light_attenuation[i].z, light_attenuation[i].w );
+
+ LIGHT_LOOP(1)
+ LIGHT_LOOP(2)
+ LIGHT_LOOP(3)
+ LIGHT_LOOP(4)
+ LIGHT_LOOP(5)
+ LIGHT_LOOP(6)
+ LIGHT_LOOP(7)
+
+ color += light;
+
+ float al = diffcol.a*vertex_color.a;
+
+ frag_color = vec4(color, al);
+#else // mode is not DIFFUSE_ALPHA_MODE_BLEND, encode to gbuffer
+
+ // deferred path // See: C++: addDeferredAttachment(), shader: softenLightF.glsl
+ frag_data[0] = final_color; // gbuffer is sRGB for legacy materials
+ frag_data[1] = final_specular; // XYZ = Specular color. W = Specular exponent.
+ frag_data[2] = final_normal; // XY = Normal. Z = Env. intensity. W = 1 skip atmos (mask off fog)
+#endif
+}
+
diff --git a/indra/newview/app_settings/shaders/class3/deferred/multiPointLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/multiPointLightF.glsl
new file mode 100644
index 0000000000..7d8f9c218d
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/multiPointLightF.glsl
@@ -0,0 +1,196 @@
+/**
+ * @file class3\deferred\multiPointLightF.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$
+ */
+
+#extension GL_ARB_texture_rectangle : enable
+
+/*[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 emissiveRect; // PBR linear packed Occlusion, Roughness, Metal. See: pbropaqueF.glsl
+uniform sampler2D noiseMap;
+uniform sampler2D lightFunc;
+
+uniform vec3 env_mat[3];
+uniform float sun_wash;
+uniform int light_count;
+uniform vec4 light[LIGHT_COUNT]; // .w = size; see C++ fullscreen_lights.push_back()
+uniform vec4 light_col[LIGHT_COUNT]; // .a = falloff
+
+uniform vec2 screen_res;
+uniform float far_z;
+uniform mat4 inv_proj;
+
+VARYING vec4 vary_fragcoord;
+
+void calcHalfVectors(vec3 lv, vec3 n, vec3 v, out vec3 h, out vec3 l, out float nh, out float nl, out float nv, out float vh, out float lightDist);
+float calcLegacyDistanceAttenuation(float distance, float falloff);
+vec4 getPosition(vec2 pos_screen);
+vec4 getNormalEnvIntensityFlags(vec2 screenpos, out vec3 n, out float envIntensity);
+vec2 getScreenXY(vec4 clip);
+vec2 getScreenCoord(vec4 clip);
+vec3 srgb_to_linear(vec3 c);
+
+// Util
+vec3 hue_to_rgb(float hue);
+
+vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor,
+ float perceptualRoughness,
+ float metallic,
+ vec3 n, // normal
+ vec3 v, // surface point to camera
+ vec3 l); //surface point to light
+
+
+void main()
+{
+#if defined(LOCAL_LIGHT_KILL)
+ discard; // Bail immediately
+#else
+ vec3 final_color = vec3(0, 0, 0);
+ vec2 tc = getScreenCoord(vary_fragcoord);
+ vec3 pos = getPosition(tc).xyz;
+ if (pos.z < far_z)
+ {
+ discard;
+ }
+
+ float envIntensity; // not used for this shader
+ vec3 n;
+ vec4 norm = getNormalEnvIntensityFlags(tc, n, envIntensity); // need `norm.w` for GET_GBUFFER_FLAG()
+
+ vec4 spec = texture2D(specularRect, tc);
+ vec3 diffuse = texture2D(diffuseRect, tc).rgb;
+
+ vec3 h, l, v = -normalize(pos);
+ float nh, nv, vh, lightDist;
+
+ if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR))
+ {
+ vec3 colorEmissive = texture2D(emissiveRect, tc).rgb;
+ vec3 orm = spec.rgb;
+ float perceptualRoughness = orm.g;
+ float metallic = orm.b;
+ vec3 f0 = vec3(0.04);
+ vec3 baseColor = diffuse.rgb;
+
+ vec3 diffuseColor = baseColor.rgb*(vec3(1.0)-f0);
+ diffuseColor *= 1.0 - metallic;
+
+ vec3 specularColor = mix(f0, baseColor.rgb, metallic);
+
+ for (int light_idx = 0; light_idx < LIGHT_COUNT; ++light_idx)
+ {
+ vec3 lightColor = light_col[ light_idx ].rgb; // Already in linear, see pipeline.cpp: volume->getLightLinearColor();
+ float falloff = light_col[ light_idx ].a;
+ float lightSize = light[ light_idx ].w;
+ vec3 lv = light[ light_idx ].xyz - pos;
+
+ lightDist = length(lv);
+
+ float dist = lightDist / lightSize;
+ if (dist <= 1.0)
+ {
+ lv /= lightDist;
+
+ float dist_atten = calcLegacyDistanceAttenuation(dist, falloff);
+
+ vec3 intensity = dist_atten * lightColor * 3.0;
+
+ final_color += intensity*pbrPunctual(diffuseColor, specularColor, perceptualRoughness, metallic, n.xyz, v, lv);
+ }
+ }
+ }
+ else
+ {
+
+ float noise = texture2D(noiseMap, tc).b;
+
+ diffuse = srgb_to_linear(diffuse);
+ spec.rgb = srgb_to_linear(spec.rgb);
+
+ // 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 nl = dot(n, lv);
+ if (nl > 0.0)
+ {
+ float lightDist;
+ calcHalfVectors(lv, n, v, h, l, nh, nl, nv, vh, lightDist);
+
+ float fa = light_col[i].a;
+ float dist_atten = calcLegacyDistanceAttenuation(dist, fa);
+ dist_atten *= noise;
+
+ float lit = nl * dist_atten;
+
+ vec3 col = light_col[i].rgb * lit * diffuse;
+
+ if (spec.a > 0.0)
+ {
+ lit = min(nl * 6.0, 1.0) * dist_atten;
+ float fres = pow(1 - vh, 5) * 0.4 + 0.5;
+
+ float gtdenom = 2 * nh;
+ float gt = max(0, min(gtdenom * nv / vh, gtdenom * nl / vh));
+
+ if (nh > 0.0)
+ {
+ float scol = fres * texture2D(lightFunc, vec2(nh, spec.a)).r * gt / (nh * nl);
+ col += lit * scol * light_col[i].rgb * spec.rgb;
+ }
+ }
+
+ final_color += col;
+ }
+ }
+ }
+ }
+
+ frag_color.rgb = final_color;
+ frag_color.a = 0.0;
+#endif // LOCAL_LIGHT_KILL
+
+#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
+ // away 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
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/multiPointLightV.glsl b/indra/newview/app_settings/shaders/class3/deferred/multiPointLightV.glsl
new file mode 100644
index 0000000000..831b3b2684
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/multiPointLightV.glsl
@@ -0,0 +1,37 @@
+/**
+ * @file class3\deferred\multiPointLightV.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$
+ */
+
+ATTRIBUTE vec3 position;
+
+VARYING vec4 vary_fragcoord;
+
+void main()
+{
+ //transform vertex
+ vec4 pos = vec4(position.xyz, 1.0);
+ vary_fragcoord = pos;
+
+ gl_Position = pos;
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/multiSpotLightF.glsl
index 9d62b9d180..5ed8a75e0e 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/multiSpotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/multiSpotLightF.glsl
@@ -1,9 +1,9 @@
/**
- * @file multiSpotLightF.glsl
+ * @file class3\deferred\multiSpotLightF.glsl
*
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2007, Linden Research, Inc.
+ * 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
@@ -34,14 +34,15 @@ out vec4 frag_color;
#define frag_color gl_FragColor
#endif
-uniform sampler2DRect diffuseRect;
-uniform sampler2DRect specularRect;
-uniform sampler2DRect depthMap;
-uniform sampler2DRect normalMap;
+uniform sampler2D diffuseRect;
+uniform sampler2D specularRect;
+uniform sampler2D depthMap;
+uniform sampler2D normalMap;
+uniform sampler2D emissiveRect; // PBR linear packed Occlusion, Roughness, Metal. See: pbropaqueF.glsl
uniform samplerCube environmentMap;
-uniform sampler2DRect lightMap;
+uniform sampler2D lightMap;
uniform sampler2D noiseMap;
-uniform sampler2D projectionMap;
+uniform sampler2D projectionMap; // rgba
uniform sampler2D lightFunc;
uniform mat4 proj_mat; //screen space to light space
@@ -61,6 +62,7 @@ uniform float sun_wash;
uniform int proj_shadow_idx;
uniform float shadow_fade;
+// Light params
uniform vec3 center;
uniform float size;
uniform vec3 color;
@@ -71,221 +73,199 @@ uniform vec2 screen_res;
uniform mat4 inv_proj;
-vec3 getNorm(vec2 pos_screen);
+void calcHalfVectors(vec3 lv, vec3 n, vec3 v, out vec3 h, out vec3 l, out float nh, out float nl, out float nv, out float vh, out float lightDist);
+float calcLegacyDistanceAttenuation(float distance, float falloff);
+vec3 colorized_dot(float x);
+bool clipProjectedLightVars(vec3 center, vec3 pos, out float dist, out float l_dist, out vec3 lv, out vec4 proj_tc );
+vec4 getNormalEnvIntensityFlags(vec2 screenpos, out vec3 n, out float envIntensity);
+vec3 getProjectedLightAmbiance(float amb_da, float attenuation, float lit, float nl, float noise, vec2 projected_uv);
+vec3 getProjectedLightDiffuseColor(float light_distance, vec2 projected_uv );
+vec3 getProjectedLightSpecularColor(vec3 pos, vec3 n);
+vec2 getScreenXY(vec4 clip);
+vec2 getScreenCoord(vec4 clip);
+vec3 srgb_to_linear(vec3 cs);
+vec4 texture2DLodSpecular(vec2 tc, float lod);
-vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod)
-{
- vec4 ret = texture2DLod(projectionMap, tc, lod);
-
- vec2 dist = vec2(0.5) - abs(tc-vec2(0.5));
-
- float det = min(lod/(proj_lod*0.5), 1.0);
-
- float d = min(dist.x, dist.y);
-
- d *= min(1, d * (proj_lod - lod));
-
- float edge = 0.25*det;
-
- ret *= clamp(d/edge, 0.0, 1.0);
-
- return ret;
-}
+vec4 getPosition(vec2 pos_screen);
-vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod)
-{
- vec4 ret = texture2DLod(projectionMap, tc, lod);
+const float M_PI = 3.14159265;
- vec2 dist = vec2(0.5) - abs(tc-vec2(0.5));
-
- float det = min(lod/(proj_lod*0.5), 1.0);
-
- float d = min(dist.x, dist.y);
-
- float edge = 0.25*det;
-
- ret *= clamp(d/edge, 0.0, 1.0);
-
- return ret;
-}
+vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor,
+ float perceptualRoughness,
+ float metallic,
+ vec3 n, // normal
+ vec3 v, // surface point to camera
+ vec3 l); //surface point to light
-vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod)
+void main()
{
- vec4 ret = texture2DLod(projectionMap, tc, lod);
-
- vec2 dist = tc-vec2(0.5);
-
- float d = dot(dist,dist);
-
- ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0), 1.0);
-
- return ret;
-}
-
-
-vec4 getPosition(vec2 pos_screen);
+#if defined(LOCAL_LIGHT_KILL)
+ discard;
+#else
+ vec3 final_color = vec3(0,0,0);
+ vec2 tc = getScreenCoord(vary_fragcoord);
+ vec3 pos = getPosition(tc).xyz;
-void main()
-{
- vec4 frag = vary_fragcoord;
- frag.xyz /= frag.w;
- frag.xyz = frag.xyz*0.5+0.5;
- frag.xy *= screen_res;
-
- vec3 pos = getPosition(frag.xy).xyz;
- vec3 lv = center.xyz-pos.xyz;
- float dist = length(lv);
- dist /= size;
- if (dist > 1.0)
+ vec3 lv;
+ vec4 proj_tc;
+ float dist, l_dist;
+ if (clipProjectedLightVars(center, pos, dist, l_dist, lv, proj_tc))
{
discard;
}
-
+
float shadow = 1.0;
if (proj_shadow_idx >= 0)
{
- vec4 shd = texture2DRect(lightMap, frag.xy);
- shadow = (proj_shadow_idx == 0) ? shd.b : shd.a;
+ vec4 shd = texture2D(lightMap, tc);
+ shadow = (proj_shadow_idx==0)?shd.b:shd.a;
shadow += shadow_fade;
shadow = clamp(shadow, 0.0, 1.0);
}
-
- vec3 norm = texture2DRect(normalMap, frag.xy).xyz;
-
- float envIntensity = norm.z;
- norm = getNorm(frag.xy);
-
- norm = normalize(norm);
- float l_dist = -dot(lv, proj_n);
-
- vec4 proj_tc = (proj_mat * vec4(pos.xyz, 1.0));
- if (proj_tc.z < 0.0)
- {
- discard;
- }
-
- proj_tc.xyz /= proj_tc.w;
-
- float fa = (falloff*0.5)+1.0;
- float dist_atten = min(1.0-(dist-1.0*(1.0-fa))/fa, 1.0);
- dist_atten *= dist_atten;
- dist_atten *= 2.0;
+ float envIntensity;
+ vec3 n;
+ vec4 norm = getNormalEnvIntensityFlags(tc, n, envIntensity);
+
+ float dist_atten = calcLegacyDistanceAttenuation(dist, falloff);
if (dist_atten <= 0.0)
{
discard;
}
-
+
lv = proj_origin-pos.xyz;
- lv = normalize(lv);
- float da = dot(norm, lv);
+ vec3 h, l, v = -normalize(pos);
+ float nh, nl, nv, vh, lightDist;
+ calcHalfVectors(lv, n, v, h, l, nh, nl, nv, vh, lightDist);
- vec3 col = vec3(0,0,0);
+ vec3 diffuse = texture2D(diffuseRect, tc).rgb;
+ vec4 spec = texture2D(specularRect, tc);
+ vec3 dlit = vec3(0, 0, 0);
+ vec3 slit = vec3(0, 0, 0);
+
+ vec3 amb_rgb = vec3(0);
+
+ if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR))
+ {
+ vec3 colorEmissive = texture2D(emissiveRect, tc).rgb;
+ vec3 orm = spec.rgb;
+ float perceptualRoughness = orm.g;
+ float metallic = orm.b;
+ vec3 f0 = vec3(0.04);
+ vec3 baseColor = diffuse.rgb;
- vec3 diff_tex = srgb_to_linear(texture2DRect(diffuseRect, frag.xy).rgb);
-
- vec4 spec = texture2DRect(specularRect, frag.xy);
+ vec3 diffuseColor = baseColor.rgb*(vec3(1.0)-f0);
+ diffuseColor *= 1.0 - metallic;
+
+ vec3 specularColor = mix(f0, baseColor.rgb, metallic);
- vec3 dlit = vec3(0, 0, 0);
+ // We need this additional test inside a light's frustum since a spotlight's ambiance can be applied
+ if (proj_tc.x > 0.0 && proj_tc.x < 1.0
+ && proj_tc.y > 0.0 && proj_tc.y < 1.0)
+ {
+ float lit = 0.0;
+ float amb_da = 0.0;
+
+ if (nl > 0.0)
+ {
+ amb_da += (nl*0.5 + 0.5) * proj_ambiance;
+
+ dlit = getProjectedLightDiffuseColor( l_dist, proj_tc.xy );
+
+ vec3 intensity = dist_atten * dlit * 3.0 * shadow; // Legacy attenuation
+ final_color += intensity*pbrPunctual(diffuseColor, specularColor, perceptualRoughness, metallic, n.xyz, v, normalize(lv));
+ }
- float noise = texture2D(noiseMap, frag.xy/128.0).b;
- if (proj_tc.z > 0.0 &&
- proj_tc.x < 1.0 &&
- proj_tc.y < 1.0 &&
- proj_tc.x > 0.0 &&
- proj_tc.y > 0.0)
+ amb_rgb = getProjectedLightAmbiance( amb_da, dist_atten, lit, nl, 1.0, proj_tc.xy );
+ final_color += diffuse.rgb * amb_rgb;
+ }
+ }
+ else
{
- float amb_da = proj_ambiance;
- float lit = 0.0;
- if (da > 0.0)
+ diffuse = srgb_to_linear(diffuse);
+ spec.rgb = srgb_to_linear(spec.rgb);
+
+ float noise = texture2D(noiseMap, tc).b;
+ if (proj_tc.z > 0.0 &&
+ proj_tc.x < 1.0 &&
+ proj_tc.y < 1.0 &&
+ proj_tc.x > 0.0 &&
+ proj_tc.y > 0.0)
{
- lit = da * dist_atten * noise;
+ float amb_da = 0;
+ float lit = 0.0;
- float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0);
- float lod = diff * proj_lod;
-
- vec4 plcol = texture2DLodDiffuse(projectionMap, proj_tc.xy, lod);
+ if (nl > 0.0)
+ {
+ lit = nl * dist_atten * noise;
+
+ dlit = getProjectedLightDiffuseColor( l_dist, proj_tc.xy );
+
+ final_color = dlit*lit*diffuse*shadow;
+
+ // unshadowed for consistency between forward and deferred?
+ amb_da += (nl*0.5+0.5) /* * (1.0-shadow) */ * proj_ambiance;
+ }
- dlit = color.rgb * plcol.rgb * plcol.a;
-
- col = dlit*lit*diff_tex*shadow;
- amb_da += (da*0.5)*(1.0-shadow)*proj_ambiance;
+ amb_rgb = getProjectedLightAmbiance( amb_da, dist_atten, lit, nl, noise, proj_tc.xy );
+ final_color += diffuse.rgb * amb_rgb;
}
-
- //float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0);
- vec4 amb_plcol = texture2DLodAmbient(projectionMap, proj_tc.xy, proj_lod);
-
- amb_da += (da*da*0.5+0.5)*(1.0-shadow)*proj_ambiance;
-
- amb_da *= dist_atten * noise;
-
- amb_da = min(amb_da, 1.0-lit);
-
- col += amb_da*color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a;
- }
+ if (spec.a > 0.0)
+ {
+ dlit *= min(nl*6.0, 1.0) * dist_atten;
- if (spec.a > 0.0)
- {
- vec3 npos = -normalize(pos);
- dlit *= min(da*6.0, 1.0) * dist_atten;
-
- //vec3 ref = dot(pos+lv, norm);
- 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));
+ float fres = pow(1 - vh, 5)*0.4+0.5;
+
+ float gtdenom = 2 * nh;
+ float gt = max(0, min(gtdenom * nv / vh, gtdenom * nl / vh));
- if (nh > 0.0)
- {
- float scol = fres*texture2D(lightFunc, vec2(nh, spec.a)).r*gt/(nh*da);
- col += dlit*scol*spec.rgb*shadow;
- //col += spec.rgb;
- }
- }
+ if (nh > 0.0)
+ {
+ float scol = fres*texture2D(lightFunc, vec2(nh, spec.a)).r*gt/(nh*nl);
+ vec3 speccol = dlit*scol*spec.rgb*shadow;
+ speccol = clamp(speccol, vec3(0), vec3(1));
+ final_color += speccol;
+ }
+ }
- if (envIntensity > 0.0)
- {
- vec3 ref = reflect(normalize(pos), norm);
+ if (envIntensity > 0.0)
+ {
+ vec3 ref = reflect(normalize(pos), n);
- //project from point pos in direction ref to plane proj_p, proj_n
- vec3 pdelta = proj_p-pos;
- float ds = dot(ref, proj_n);
+ //project from point pos in direction ref to plane proj_p, proj_n
+ vec3 pdelta = proj_p-pos;
+ float ds = dot(ref, proj_n);
- if (ds < 0.0)
- {
- vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds;
+ if (ds < 0.0)
+ {
+ vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds;
- vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0));
+ vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0));
- if (stc.z > 0.0)
- {
- stc /= stc.w;
-
- if (stc.x < 1.0 &&
- stc.y < 1.0 &&
- stc.x > 0.0 &&
- stc.y > 0.0)
+ if (stc.z > 0.0)
{
- col += color.rgb * texture2DLodSpecular(projectionMap, stc.xy, (1 - spec.a) * (proj_lod * 0.6)).rgb * shadow * envIntensity;
+ stc /= stc.w;
+
+ if (stc.x < 1.0 &&
+ stc.y < 1.0 &&
+ stc.x > 0.0 &&
+ stc.y > 0.0)
+ {
+ final_color += color.rgb * texture2DLodSpecular(stc.xy, (1 - spec.a) * (proj_lod * 0.6)).rgb * shadow * envIntensity;
+ }
}
}
}
}
//not sure why, but this line prevents MATBUG-194
- col = max(col, vec3(0.0));
-
- col = scaleDownLight(col);
+ final_color = max(final_color, vec3(0.0));
- //output linear space color as gamma correction happens down stream
- frag_color.rgb = col;
+ //output linear
+ frag_color.rgb = final_color;
frag_color.a = 0.0;
+#endif // LOCAL_LIGHT_KILL
}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/pointLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/pointLightF.glsl
new file mode 100644
index 0000000000..d9cbae45a6
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/pointLightF.glsl
@@ -0,0 +1,158 @@
+/**
+ * @file class3\deferred\pointLightF.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$
+ */
+
+#extension GL_ARB_texture_rectangle : enable
+
+/*[EXTRA_CODE_HERE]*/
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_color;
+#else
+#define frag_color gl_FragColor
+#endif
+
+uniform sampler2D diffuseRect;
+uniform sampler2D specularRect;
+uniform sampler2D normalMap;
+uniform sampler2D emissiveRect; // PBR linear packed Occlusion, Roughness, Metal. See: pbropaqueF.glsl
+uniform sampler2D noiseMap;
+uniform sampler2D lightFunc;
+uniform sampler2D depthMap;
+
+uniform vec3 env_mat[3];
+uniform float sun_wash;
+
+// light params
+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;
+
+void calcHalfVectors(vec3 lv, vec3 n, vec3 v, out vec3 h, out vec3 l, out float nh, out float nl, out float nv, out float vh, out float lightDist);
+float calcLegacyDistanceAttenuation(float distance, float falloff);
+vec4 getNormalEnvIntensityFlags(vec2 screenpos, out vec3 n, out float envIntensity);
+vec4 getPosition(vec2 pos_screen);
+vec2 getScreenXY(vec4 clip);
+vec2 getScreenCoord(vec4 clip);
+vec3 srgb_to_linear(vec3 c);
+float getDepth(vec2 tc);
+
+vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor,
+ float perceptualRoughness,
+ float metallic,
+ vec3 n, // normal
+ vec3 v, // surface point to camera
+ vec3 l); //surface point to light
+
+void main()
+{
+ vec3 final_color = vec3(0);
+ vec2 tc = getScreenCoord(vary_fragcoord);
+ vec3 pos = getPosition(tc).xyz;
+
+ float envIntensity;
+ vec3 n;
+ vec4 norm = getNormalEnvIntensityFlags(tc, n, envIntensity); // need `norm.w` for GET_GBUFFER_FLAG()
+
+ vec3 diffuse = texture2D(diffuseRect, tc).rgb;
+ vec4 spec = texture2D(specularRect, tc);
+
+ // Common half vectors calcs
+ vec3 lv = trans_center.xyz-pos;
+ vec3 h, l, v = -normalize(pos);
+ float nh, nl, nv, vh, lightDist;
+ calcHalfVectors(lv, n, v, h, l, nh, nl, nv, vh, lightDist);
+
+ if (lightDist >= size)
+ {
+ discard;
+ }
+ float dist = lightDist / size;
+ float dist_atten = calcLegacyDistanceAttenuation(dist, falloff);
+
+ if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR))
+ {
+ vec3 colorEmissive = texture2D(emissiveRect, tc).rgb;
+ vec3 orm = spec.rgb;
+ float perceptualRoughness = orm.g;
+ float metallic = orm.b;
+ vec3 f0 = vec3(0.04);
+ vec3 baseColor = diffuse.rgb;
+
+ vec3 diffuseColor = baseColor.rgb*(vec3(1.0)-f0);
+ diffuseColor *= 1.0 - metallic;
+
+ vec3 specularColor = mix(f0, baseColor.rgb, metallic);
+
+ vec3 intensity = dist_atten * color * 3.0; // Legacy attenuation
+ final_color += intensity*pbrPunctual(diffuseColor, specularColor, perceptualRoughness, metallic, n.xyz, v, normalize(lv));
+ }
+ else
+ {
+ if (nl < 0.0)
+ {
+ discard;
+ }
+
+ diffuse = srgb_to_linear(diffuse);
+ spec.rgb = srgb_to_linear(spec.rgb);
+
+ float noise = texture2D(noiseMap, tc).b;
+ float lit = nl * dist_atten * noise;
+
+ final_color = color.rgb*lit*diffuse;
+
+ if (spec.a > 0.0)
+ {
+ lit = min(nl*6.0, 1.0) * dist_atten;
+
+ float sa = nh;
+ float fres = pow(1 - vh, 5) * 0.4+0.5;
+ float gtdenom = 2 * nh;
+ float gt = max(0,(min(gtdenom * nv / vh, gtdenom * nl / vh)));
+
+ if (nh > 0.0)
+ {
+ float scol = fres*texture2D(lightFunc, vec2(nh, spec.a)).r*gt/(nh*nl);
+ final_color += lit*scol*color.rgb*spec.rgb;
+ }
+ }
+
+ if (dot(final_color, final_color) <= 0.0)
+ {
+ discard;
+ }
+ }
+
+ frag_color.rgb = final_color;
+ frag_color.a = 0.0;
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/shadowCubeV.glsl b/indra/newview/app_settings/shaders/class3/deferred/pointLightV.glsl
index db8c75fb8a..d42c8f6cf6 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/shadowCubeV.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/pointLightV.glsl
@@ -1,9 +1,9 @@
/**
- * @file class3/deferred/shadowCubeV.glsl
+ * @file class3\deferred\pointLightV.glsl
*
- * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2007, Linden Research, Inc.
+ * 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
@@ -24,27 +24,22 @@
*/
uniform mat4 modelview_projection_matrix;
+uniform mat4 modelview_matrix;
ATTRIBUTE vec3 position;
-#if !defined(DEPTH_CLAMP)
-VARYING vec4 post_pos;
-#endif
+uniform vec3 center;
+uniform float size;
-uniform vec3 box_center;
-uniform vec3 box_size;
+VARYING vec4 vary_fragcoord;
+VARYING vec3 trans_center;
void main()
{
//transform vertex
- vec3 p = position*box_size+box_center;
- vec4 pos = modelview_projection_matrix*vec4(p.xyz, 1.0);
-
-#if !defined(DEPTH_CLAMP)
- post_pos = pos;
-
- gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
-#else
+ vec3 p = position*size+center;
+ vec4 pos = modelview_projection_matrix * vec4(p.xyz, 1.0);
+ vary_fragcoord = pos;
+ trans_center = (modelview_matrix*vec4(center.xyz, 1.0)).xyz;
gl_Position = pos;
-#endif
}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl
new file mode 100644
index 0000000000..bb3be7260b
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl
@@ -0,0 +1,760 @@
+/**
+ * @file class3/deferred/reflectionProbeF.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$
+ */
+
+#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;
+uniform float max_probe_lod;
+
+layout (std140) uniform ReflectionProbes
+{
+ // list of OBBs for user override probes
+ // box is a set of 3 planes outward facing planes and the depth of the box along that plane
+ // for each box refBox[i]...
+ /// box[0..2] - plane 0 .. 2 in [A,B,C,D] notation
+ // box[3][0..2] - plane thickness
+ mat4 refBox[REFMAP_COUNT];
+ // list of bounding spheres for reflection probes sorted by distance to camera (closest first)
+ vec4 refSphere[REFMAP_COUNT];
+ // extra parameters (currently only .x used for probe ambiance)
+ vec4 refParams[REFMAP_COUNT];
+ // index of cube map in reflectionProbes for a corresponding reflection probe
+ // e.g. cube map channel of refSphere[2] is stored in refIndex[2]
+ // refIndex.x - cubemap channel in reflectionProbes
+ // refIndex.y - index in refNeighbor of neighbor list (index is ivec4 index, not int index)
+ // refIndex.z - number of neighbors
+ // refIndex.w - priority, if negative, this probe has a box influence
+ ivec4 refIndex[REFMAP_COUNT];
+
+ // neighbor list data (refSphere indices, not cubemap array layer)
+ ivec4 refNeighbor[1024];
+
+ // number of reflection probes present in refSphere
+ int refmapCount;
+};
+
+// Inputs
+uniform mat3 env_mat;
+
+// list of probeIndexes shader will actually use after "getRefIndex" is called
+// (stores refIndex/refSphere indices, NOT rerflectionProbes layer)
+int probeIndex[REF_SAMPLE_COUNT];
+
+// number of probes stored in probeIndex
+int probeInfluences = 0;
+
+bool isAbove(vec3 pos, vec4 plane)
+{
+ return (dot(plane.xyz, pos) + plane.w) > 0;
+}
+
+int max_priority = 0;
+
+// return true if probe at index i influences position pos
+bool shouldSampleProbe(int i, vec3 pos)
+{
+ if (refIndex[i].w < 0)
+ {
+ vec4 v = refBox[i] * vec4(pos, 1.0);
+ if (abs(v.x) > 1 ||
+ abs(v.y) > 1 ||
+ abs(v.z) > 1)
+ {
+ return false;
+ }
+
+ max_priority = max(max_priority, -refIndex[i].w);
+ }
+ else
+ {
+ 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;
+ }
+ }
+
+ max_priority = max(max_priority, refIndex[i].w);
+ }
+
+ return true;
+}
+
+// call before sampleRef
+// populate "probeIndex" with N probe indices that influence pos where N is REF_SAMPLE_COUNT
+// overall algorithm --
+void preProbeSample(vec3 pos)
+{
+ // TODO: make some sort of structure that reduces the number of distance checks
+ for (int i = 1; i < refmapCount; ++i)
+ {
+ // found an influencing probe
+ if (shouldSampleProbe(i, pos))
+ {
+ probeIndex[probeInfluences] = i;
+ ++probeInfluences;
+
+ int neighborIdx = refIndex[i].y;
+ if (neighborIdx != -1)
+ {
+ int neighborCount = min(refIndex[i].z, REF_SAMPLE_COUNT-1);
+
+ int count = 0;
+ while (count < neighborCount)
+ {
+ // check up to REF_SAMPLE_COUNT-1 neighbors (neighborIdx is ivec4 index)
+
+ int idx = refNeighbor[neighborIdx].x;
+ if (shouldSampleProbe(idx, pos))
+ {
+ probeIndex[probeInfluences++] = idx;
+ if (probeInfluences == REF_SAMPLE_COUNT)
+ {
+ break;
+ }
+ }
+ count++;
+ if (count == neighborCount)
+ {
+ break;
+ }
+
+ idx = refNeighbor[neighborIdx].y;
+ if (shouldSampleProbe(idx, pos))
+ {
+ probeIndex[probeInfluences++] = idx;
+ if (probeInfluences == REF_SAMPLE_COUNT)
+ {
+ break;
+ }
+ }
+ count++;
+ if (count == neighborCount)
+ {
+ break;
+ }
+
+ idx = refNeighbor[neighborIdx].z;
+ if (shouldSampleProbe(idx, pos))
+ {
+ probeIndex[probeInfluences++] = idx;
+ if (probeInfluences == REF_SAMPLE_COUNT)
+ {
+ break;
+ }
+ }
+ count++;
+ if (count == neighborCount)
+ {
+ break;
+ }
+
+ idx = refNeighbor[neighborIdx].w;
+ if (shouldSampleProbe(idx, pos))
+ {
+ probeIndex[probeInfluences++] = idx;
+ if (probeInfluences == REF_SAMPLE_COUNT)
+ {
+ break;
+ }
+ }
+ count++;
+ if (count == neighborCount)
+ {
+ break;
+ }
+
+ ++neighborIdx;
+ }
+
+ break;
+ }
+ }
+ }
+
+ if (max_priority <= 1)
+ { // probe at index 0 is a special probe for smoothing out automatic probes
+ probeIndex[probeInfluences++] = 0;
+ }
+}
+
+// from https://www.scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-sphere-intersection
+
+// original reference implementation:
+/*
+bool intersect(const Ray &ray) const
+{
+ float t0, t1; // solutions for t if the ray intersects
+#if 0
+ // geometric solution
+ Vec3f L = center - orig;
+ float tca = L.dotProduct(dir);
+ // if (tca < 0) return false;
+ float d2 = L.dotProduct(L) - tca * tca;
+ if (d2 > radius2) return false;
+ float thc = sqrt(radius2 - d2);
+ t0 = tca - thc;
+ t1 = tca + thc;
+#else
+ // analytic solution
+ Vec3f L = orig - center;
+ float a = dir.dotProduct(dir);
+ float b = 2 * dir.dotProduct(L);
+ float c = L.dotProduct(L) - radius2;
+ if (!solveQuadratic(a, b, c, t0, t1)) return false;
+#endif
+ if (t0 > t1) std::swap(t0, t1);
+
+ if (t0 < 0) {
+ t0 = t1; // if t0 is negative, let's use t1 instead
+ if (t0 < 0) return false; // both t0 and t1 are negative
+ }
+
+ t = t0;
+
+ return true;
+} */
+
+// adapted -- assume that origin is inside sphere, return intersection of ray with edge of sphere
+vec3 sphereIntersect(vec3 origin, vec3 dir, vec3 center, float radius2)
+{
+ float t0, t1; // solutions for t if the ray intersects
+
+ vec3 L = center - origin;
+ float tca = dot(L,dir);
+
+ float d2 = dot(L,L) - tca * tca;
+
+ float thc = sqrt(radius2 - d2);
+ t0 = tca - thc;
+ t1 = tca + thc;
+
+ vec3 v = origin + dir * t1;
+ return v;
+}
+
+void swap(inout float a, inout float b)
+{
+ float t = a;
+ a = b;
+ b = a;
+}
+
+// debug implementation, make no assumptions about origin
+void sphereIntersectDebug(vec3 origin, vec3 dir, vec3 center, float radius2, float depth, inout vec4 col)
+{
+ float t[2]; // solutions for t if the ray intersects
+
+ // geometric solution
+ vec3 L = center - origin;
+ float tca = dot(L, dir);
+ // if (tca < 0) return false;
+ float d2 = dot(L, L) - tca * tca;
+ if (d2 > radius2) return;
+ float thc = sqrt(radius2 - d2);
+ t[0] = tca - thc;
+ t[1] = tca + thc;
+
+ for (int i = 0; i < 2; ++i)
+ {
+ if (t[i] > 0)
+ {
+ if (t[i] > depth)
+ {
+ float w = 0.125/((t[i]-depth)*0.125 + 1.0);
+ col += vec4(0, 0, w, w)*(1.0-min(col.a, 1.0));
+ }
+ else
+ {
+ float w = 0.25;
+ col += vec4(w,w,0,w)*(1.0-min(col.a, 1.0));
+ }
+ }
+ }
+
+}
+
+// from https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/
+/*
+vec3 DirectionWS = normalize(PositionWS - CameraWS);
+vec3 ReflDirectionWS = reflect(DirectionWS, NormalWS);
+
+// Intersection with OBB convertto unit box space
+// Transform in local unit parallax cube space (scaled and rotated)
+vec3 RayLS = MulMatrix( float(3x3)WorldToLocal, ReflDirectionWS);
+vec3 PositionLS = MulMatrix( WorldToLocal, PositionWS);
+
+vec3 Unitary = vec3(1.0f, 1.0f, 1.0f);
+vec3 FirstPlaneIntersect = (Unitary - PositionLS) / RayLS;
+vec3 SecondPlaneIntersect = (-Unitary - PositionLS) / RayLS;
+vec3 FurthestPlane = max(FirstPlaneIntersect, SecondPlaneIntersect);
+float Distance = min(FurthestPlane.x, min(FurthestPlane.y, FurthestPlane.z));
+
+// Use Distance in WS directly to recover intersection
+vec3 IntersectPositionWS = PositionWS + ReflDirectionWS * Distance;
+vec3 ReflDirectionWS = IntersectPositionWS - CubemapPositionWS;
+
+return texCUBE(envMap, ReflDirectionWS);
+*/
+
+// get point of intersection with given probe's box influence volume
+// origin - ray origin in clip space
+// dir - ray direction in clip space
+// i - probe index in refBox/refSphere
+// 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)
+ mat4 clipToLocal = refBox[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;
+ vec3 FurthestPlane = max(FirstPlaneIntersect, SecondPlaneIntersect);
+ float Distance = min(FurthestPlane.x, min(FurthestPlane.y, FurthestPlane.z));
+
+ // Use Distance in CS directly to recover intersection
+ vec3 IntersectPositionCS = origin + dir * Distance;
+
+ return IntersectPositionCS;
+}
+
+void debugBoxCol(vec3 ro, vec3 rd, float t, vec3 p, inout vec4 col)
+{
+ vec3 v = ro + rd * t;
+
+ v -= ro;
+ vec3 pos = p - ro;
+
+
+ bool behind = dot(v,v) > dot(pos,pos);
+
+ float w = 0.25;
+
+ if (behind)
+ {
+ w *= 0.5;
+ w /= (length(v)-length(pos))*0.5+1.0;
+ col += vec4(0,0,w,w)*(1.0-min(col.a, 1.0));
+ }
+ else
+ {
+ col += vec4(w,w,0,w)*(1.0-min(col.a, 1.0));
+ }
+}
+
+// cribbed from https://iquilezles.org/articles/intersectors/
+// axis aligned box centered at the origin, with size boxSize
+void boxIntersectionDebug( in vec3 ro, in vec3 p, vec3 boxSize, inout vec4 col)
+{
+ vec3 rd = normalize(p-ro);
+
+ vec3 m = 1.0/rd; // can precompute if traversing a set of aligned boxes
+ vec3 n = m*ro; // can precompute if traversing a set of aligned boxes
+ vec3 k = abs(m)*boxSize;
+ vec3 t1 = -n - k;
+ vec3 t2 = -n + k;
+ float tN = max( max( t1.x, t1.y ), t1.z );
+ float tF = min( min( t2.x, t2.y ), t2.z );
+ if( tN>tF || tF<0.0) return ; // no intersection
+
+ float t = tN < 0 ? tF : tN;
+
+ debugBoxCol(ro, rd, t, p, col);
+
+ if (tN > 0) // eye is outside box, check backside, too
+ {
+ debugBoxCol(ro, rd, tF, p, col);
+ }
+}
+
+
+void boxIntersectDebug(vec3 origin, vec3 pos, int i, inout vec4 col)
+{
+ mat4 clipToLocal = refBox[i];
+
+ // transform into unit cube space
+ origin = (clipToLocal * vec4(origin, 1.0)).xyz;
+ pos = (clipToLocal * vec4(pos, 1.0)).xyz;
+
+ boxIntersectionDebug(origin, pos, vec3(1), 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
+// vi - return value of intersection point with influence volume
+// wi - return value of approximate world space position of sampled pixel
+// lod - which mip to bias towards (lower is higher res, sharper reflections)
+// c - center of probe
+// r2 - radius of probe squared
+// i - index of probe
+vec3 tapRefMap(vec3 pos, vec3 dir, out float w, out vec3 vi, out vec3 wi, float lod, vec3 c, int i)
+{
+ //lod = max(lod, 1);
+ // parallax adjustment
+
+ vec3 v;
+
+ if (refIndex[i].w < 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,
+ 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);
+
+ w = sphereWeight(pos, dir, refSphere[i].xyz, r, 0.25);
+ }
+
+ vi = v;
+
+ v -= c;
+ vec3 d = normalize(v);
+
+ v = env_mat * v;
+
+ vec4 ret = textureLod(reflectionProbes, vec4(v.xyz, refIndex[i].x), lod);
+
+ wi = d * ret.a * 256.0+c;
+
+ return ret.rgb;
+}
+
+// Tap an irradiance map
+// pos - position of pixel
+// dir - pixel normal
+// c - center of probe
+// r2 - radius of probe squared
+// i - index of probe
+vec3 tapIrradianceMap(vec3 pos, vec3 dir, out float w, vec3 c, int i)
+{
+ // parallax adjustment
+ vec3 v;
+ if (refIndex[i].w < 0)
+ {
+ float d = 0.0;
+ v = boxIntersect(pos, dir, i, d);
+ w = max(d, 0.001);
+ }
+ else
+ {
+ float r = refSphere[i].w; // radius of sphere volume
+ float p = float(abs(refIndex[i].w)); // priority
+ float rr = r * r; // radius squred
+
+ 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);
+
+ w = sphereWeight(pos, dir, refSphere[i].xyz, r, 0.001);
+ }
+
+ v -= c;
+ v = env_mat * v;
+ {
+ return textureLod(irradianceProbes, vec4(v.xyz, refIndex[i].x), 0).rgb * refParams[i].x;
+ }
+}
+
+vec3 sampleProbes(vec3 pos, vec3 dir, float lod, bool errorCorrect)
+{
+ float wsum = 0.0;
+ vec3 col = vec3(0,0,0);
+ float vd2 = dot(pos,pos); // view distance squared
+
+ for (int idx = 0; idx < probeInfluences; ++idx)
+ {
+ int i = probeIndex[idx];
+ if (abs(refIndex[i].w) < max_priority)
+ {
+ continue;
+ }
+
+ float w;
+ vec3 vi, wi;
+ vec3 refcol;
+
+
+ {
+ if (errorCorrect && refIndex[i].w >= 0)
+ { // error correction is on and this probe is a sphere
+ //take a sample to get depth value, then error correct
+ refcol = tapRefMap(pos, dir, w, vi, wi, abs(lod + 2), refSphere[i].xyz, i);
+
+ //adjust lookup by distance result
+ float d = length(vi - wi);
+ vi += dir * d;
+
+ vi -= refSphere[i].xyz;
+
+ vi = env_mat * vi;
+
+ refcol = textureLod(reflectionProbes, vec4(vi, refIndex[i].x), lod).rgb;
+
+ // weight by vector correctness
+ vec3 pi = normalize(wi - pos);
+ w *= max(dot(pi, dir), 0.1);
+ //w = pow(w, 32.0);
+ }
+ else
+ {
+ refcol = tapRefMap(pos, dir, w, vi, wi, lod, refSphere[i].xyz, i);
+ }
+
+ col += refcol.rgb*w;
+
+ wsum += w;
+ }
+ }
+
+ if (wsum > 0.0)
+ {
+ col *= 1.0/wsum;
+ }
+
+ return col;
+}
+
+vec3 sampleProbeAmbient(vec3 pos, vec3 dir)
+{
+ // modified copy/paste of sampleProbes follows, will likely diverge from sampleProbes further
+ // as irradiance map mixing is tuned independently of radiance map mixing
+ float wsum = 0.0;
+ vec3 col = vec3(0,0,0);
+ float vd2 = dot(pos,pos); // view distance squared
+
+ float minweight = 1.0;
+
+ for (int idx = 0; idx < probeInfluences; ++idx)
+ {
+ int i = probeIndex[idx];
+ if (abs(refIndex[i].w) < max_priority)
+ {
+ continue;
+ }
+
+ {
+ float w;
+ vec3 refcol = tapIrradianceMap(pos, dir, w, refSphere[i].xyz, i);
+
+ col += refcol*w;
+
+ wsum += w;
+ }
+ }
+
+ if (wsum > 0.0)
+ {
+ col *= 1.0/wsum;
+ }
+
+ return col;
+}
+
+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 = max_probe_lod;
+ preProbeSample(pos);
+
+ vec3 refnormpersp = reflect(pos.xyz, norm.xyz);
+
+ ambenv = sampleProbeAmbient(pos, norm);
+
+ 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)
+{
+ vec3 origin = vec3(0,0,0);
+
+ bool manual_probe = abs(refIndex[i].w) > 2;
+
+ if (manual_probe)
+ {
+ if (refIndex[i].w < 0)
+ {
+ boxIntersectDebug(origin, pos, i, col);
+ }
+ else
+ {
+ float r = refSphere[i].w; // radius of sphere volume
+ float rr = r * r; // radius squared
+
+ float t = 0.0;
+
+ sphereIntersectDebug(origin, dir, refSphere[i].xyz, rr, depth, col);
+ }
+ }
+}
+
+vec4 sampleReflectionProbesDebug(vec3 pos)
+{
+ vec4 col = vec4(0,0,0,0);
+
+ vec3 dir = normalize(pos);
+
+ float d = length(pos);
+
+ for (int i = 1; i < refmapCount; ++i)
+ {
+ debugTapRefMap(pos, dir, d, i, col);
+ }
+
+ return col;
+}
+
+void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv,
+ vec2 tc, vec3 pos, vec3 norm, float glossiness)
+{
+ sampleReflectionProbes(ambenv, glossenv,
+ tc, pos, norm, glossiness, false);
+}
+
+
+void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv,
+ vec2 tc, vec3 pos, vec3 norm, float glossiness, float envIntensity)
+{
+ // TODO - don't hard code lods
+ float reflection_lods = max_probe_lod;
+ preProbeSample(pos);
+
+ vec3 refnormpersp = reflect(pos.xyz, norm.xyz);
+
+ ambenv = sampleProbeAmbient(pos, norm);
+
+ if (glossiness > 0.0)
+ {
+ float lod = (1.0-glossiness)*reflection_lods;
+ glossenv = sampleProbes(pos, normalize(refnormpersp), lod, false);
+ }
+
+ if (envIntensity > 0.0)
+ {
+ 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)
+{
+ glossenv *= 0.5; // fudge darker
+ float fresnel = clamp(1.0+dot(normalize(pos.xyz), norm.xyz), 0.3, 1.0);
+ fresnel *= fresnel;
+ fresnel *= spec.a;
+ glossenv *= spec.rgb*fresnel;
+ glossenv *= vec3(1.0) - color; // fake energy conservation
+ color.rgb += glossenv*0.5;
+}
+
+ void applyLegacyEnv(inout vec3 color, vec3 legacyenv, vec4 spec, vec3 pos, vec3 norm, float envIntensity)
+ {
+ vec3 reflected_color = legacyenv;
+ vec3 lookAt = normalize(pos);
+ float fresnel = 1.0+dot(lookAt, norm.xyz);
+ fresnel *= fresnel;
+ fresnel = min(fresnel+envIntensity, 1.0);
+ reflected_color *= (envIntensity*fresnel);
+ color = mix(color.rgb, reflected_color*0.5, envIntensity);
+ }
+
diff --git a/indra/newview/app_settings/shaders/class3/deferred/screenSpaceReflPostF.glsl b/indra/newview/app_settings/shaders/class3/deferred/screenSpaceReflPostF.glsl
new file mode 100644
index 0000000000..742f528cb1
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/screenSpaceReflPostF.glsl
@@ -0,0 +1,98 @@
+/**
+ * @file class3/deferred/screenSpaceReflPostF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2007, 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$
+ */
+
+#extension GL_ARB_texture_rectangle : enable
+
+/*[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;
+VARYING vec3 camera_ray;
+
+uniform sampler2D specularRect;
+uniform sampler2D diffuseRect;
+uniform sampler2D diffuseMap;
+
+vec3 getNorm(vec2 screenpos);
+float getDepth(vec2 pos_screen);
+float linearDepth(float d, float znear, float zfar);
+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);
+
+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);
+ 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);
+ vec2 hitpixel;
+
+ 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;
+ float perceptualRoughness = orm.g;
+ 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);
+ }
+
+ vec4 collectedColor = vec4(0);
+
+ float w = tapScreenSpaceReflection(4, tc, pos, n, collectedColor, diffuseMap);
+
+ collectedColor.rgb *= specCol.rgb;
+
+ frag_color += collectedColor * w;
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/attachmentShadowV.glsl b/indra/newview/app_settings/shaders/class3/deferred/screenSpaceReflPostV.glsl
index 1a655e6467..b084094d4d 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/attachmentShadowV.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/screenSpaceReflPostV.glsl
@@ -1,49 +1,48 @@
-/**
- * @file attachmentShadowV.glsl
+/**
+ * @file class3/deferred/screenSpaceReflPostV.glsl
+ *
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2007, 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$
*/
uniform mat4 projection_matrix;
-uniform mat4 modelview_matrix;
-uniform mat4 texture_matrix0;
+uniform mat4 inv_proj;
ATTRIBUTE vec3 position;
-ATTRIBUTE vec2 texcoord0;
-mat4 getObjectSkinnedTransform();
+uniform vec2 screen_res;
+
+VARYING vec2 vary_fragcoord;
+VARYING vec3 camera_ray;
-VARYING vec4 pos;
void main()
{
//transform vertex
- mat4 mat = getObjectSkinnedTransform();
+ vec4 pos = vec4(position.xyz, 1.0);
+ gl_Position = pos;
- mat = modelview_matrix * mat;
- pos = (mat*vec4(position.xyz, 1.0));
- pos = projection_matrix * vec4(pos.xyz, 1.0);
-
-#if !defined(DEPTH_CLAMP)
- pos.z = max(pos.z, -pos.w+0.01);
-#endif
- gl_Position = pos;
+ vary_fragcoord = pos.xy * 0.5 + 0.5;
+
+ vec4 rayOrig = inv_proj * vec4(pos.xy, 1, 1);
+ camera_ray = rayOrig.xyz / rayOrig.w;
+
}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/screenSpaceReflUtil.glsl b/indra/newview/app_settings/shaders/class3/deferred/screenSpaceReflUtil.glsl
new file mode 100644
index 0000000000..c355b671c0
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/screenSpaceReflUtil.glsl
@@ -0,0 +1,234 @@
+/**
+ * @file class3/deferred/screenSpaceReflUtil.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2007, 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$
+ */
+
+uniform sampler2D sceneMap;
+uniform sampler2D sceneDepth;
+
+uniform vec2 screen_res;
+uniform mat4 projection_matrix;
+//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 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;
+}
+
+bool isBinarySearchEnabled = true;
+bool isAdaptiveStepEnabled = true;
+bool isExponentialStepEnabled = true;
+bool debugDraw = false;
+int iterationCount = 40;
+float rayStep = 0.1;
+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;
+ 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 = getLinearDepth(screenPosition);
+ 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(sceneMap, 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 = getLinearDepth(screenPosition);
+ delta = abs(marchingPosition.z) - depthFromScreen;
+
+ 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(sceneMap, screenPosition) * color;
+ hitDepth = depthFromScreen;
+ hit = true;
+ break;
+ }
+ }
+ }
+ }
+
+ 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;
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/shVisF.glsl b/indra/newview/app_settings/shaders/class3/deferred/shVisF.glsl
deleted file mode 100644
index c8991f7a18..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/shVisF.glsl
+++ /dev/null
@@ -1,73 +0,0 @@
-/**
- * @file class3/deferred/shVisF.glsl
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2007, 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$
- */
-
-#ifdef DEFINE_GL_FRAGCOLOR
- out vec4 frag_color;
-#else
- #define frag_color gl_FragColor
-#endif
-
-/////////////////////////////////////////////////////////////////////////
-// Fragment shader for L1 SH debug rendering
-/////////////////////////////////////////////////////////////////////////
-
-uniform sampler2D sh_input_r;
-uniform sampler2D sh_input_g;
-uniform sampler2D sh_input_b;
-
-uniform mat3 inv_modelviewprojection;
-
-VARYING vec4 vary_pos;
-
-void main(void)
-{
- vec2 coord = vary_pos.xy + vec2(0.5,0.5);
-
- coord.x *= (1.6/0.9);
-
- if (dot(coord, coord) > 0.25)
- {
- discard;
- }
-
- vec4 n = vec4(coord*2.0, 0.0, 1);
- //n.y = -n.y;
- n.z = sqrt(max(1.0-n.x*n.x-n.y*n.y, 0.0));
- //n.xyz = inv_modelviewprojection * n.xyz;
-
- vec4 l1tap = vec4(1.0/sqrt(4*3.14159265), sqrt(3)/sqrt(4*3.14159265), sqrt(3)/sqrt(4*3.14159265), sqrt(3)/sqrt(4*3.14159265));
- vec4 l1r = texture2D(sh_input_r, vec2(0,0));
- vec4 l1g = texture2D(sh_input_g, vec2(0,0));
- vec4 l1b = texture2D(sh_input_b, vec2(0,0));
- vec3 indirect = vec3(
- dot(l1r, l1tap * n),
- dot(l1g, l1tap * n),
- dot(l1b, l1tap * n));
-
- //indirect = pow(indirect, vec3(0.45));
- indirect *= 3.0;
-
- frag_color = vec4(indirect, 1.0);
-}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/shadowAlphaBlendV.glsl b/indra/newview/app_settings/shaders/class3/deferred/shadowAlphaBlendV.glsl
deleted file mode 100644
index af1461c297..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/shadowAlphaBlendV.glsl
+++ /dev/null
@@ -1,66 +0,0 @@
-/**
- * @file shadowAlphaMaskV.glsl
- *
- * $LicenseInfo:firstyear=2011&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2011, 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$
- */
-
-uniform mat4 texture_matrix0;
-uniform mat4 modelview_projection_matrix;
-uniform float shadow_target_width;
-
-ATTRIBUTE vec3 position;
-ATTRIBUTE vec4 diffuse_color;
-ATTRIBUTE vec2 texcoord0;
-
-#if !defined(DEPTH_CLAMP)
-VARYING float pos_zd2;
-#endif
-
-VARYING float target_pos_x;
-VARYING vec4 pos;
-VARYING vec4 vertex_color;
-VARYING vec2 vary_texcoord0;
-
-void passTextureIndex();
-
-void main()
-{
- //transform vertex
- vec4 pre_pos = vec4(position.xyz, 1.0);
- vec4 pos = modelview_projection_matrix * pre_pos;
- target_pos_x = 0.5 * (shadow_target_width - 1.0) * pos.x;
-
- pos_w = pos.w;
-
-#if !defined(DEPTH_CLAMP)
- pos_zd2 = pos.z * 0.5;
-
- gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
-#else
- gl_Position = pos;
-#endif
-
- passTextureIndex();
-
- vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
- vertex_color = diffuse_color;
-}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/shadowAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class3/deferred/shadowAlphaMaskF.glsl
deleted file mode 100644
index 50f1ffd626..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/shadowAlphaMaskF.glsl
+++ /dev/null
@@ -1,74 +0,0 @@
-/**
- * @file class3/deferred/shadowAlphaMaskF.glsl
- *
- * $LicenseInfo:firstyear=2011&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2011, 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 sampler2D diffuseMap;
-
-#if !defined(DEPTH_CLAMP)
-VARYING float pos_zd2;
-#endif
-
-VARYING float pos_w;
-
-VARYING float target_pos_x;
-VARYING vec4 vertex_color;
-VARYING vec2 vary_texcoord0;
-
-vec4 getPosition(vec2 screen_coord);
-vec4 computeMoments(float depth, float a);
-
-void main()
-{
- vec4 pos = getPosition(vary_texcoord0.xy);
-
- float alpha = diffuseLookup(vary_texcoord0.xy).a * vertex_color.a;
-
- if (alpha < 0.05) // treat as totally transparent
- {
- discard;
- }
-
- if (alpha < 0.88) // treat as semi-transparent
- {
- if (fract(0.5*floor(target_pos_x / pos_w )) < 0.25)
- {
- discard;
- }
- }
-
- frag_color = computeMoments(length(pos.xyz), alpha);
-
-#if !defined(DEPTH_CLAMP)
- gl_FragDepth = max(pos_zd2/pos_w+0.5, 0.0);
-#endif
-
-}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/shadowAlphaMaskV.glsl b/indra/newview/app_settings/shaders/class3/deferred/shadowAlphaMaskV.glsl
deleted file mode 100644
index 6a646f5e9e..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/shadowAlphaMaskV.glsl
+++ /dev/null
@@ -1,67 +0,0 @@
-/**
- * @file class3/deferred/shadowAlphaMaskV.glsl
- *
- * $LicenseInfo:firstyear=2011&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2011, 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$
- */
-
-uniform mat4 texture_matrix0;
-uniform mat4 modelview_projection_matrix;
-uniform float shadow_target_width;
-
-ATTRIBUTE vec3 position;
-ATTRIBUTE vec4 diffuse_color;
-ATTRIBUTE vec2 texcoord0;
-
-#if !defined(DEPTH_CLAMP)
-VARYING float pos_zd2;
-#endif
-
-VARYING vec4 pos;
-VARYING float target_pos_x;
-VARYING vec4 vertex_color;
-VARYING vec2 vary_texcoord0;
-
-void passTextureIndex();
-
-void main()
-{
- //transform vertex
- vec4 pre_pos = vec4(position.xyz, 1.0);
-
- pos = modelview_projection_matrix * pre_pos;
-
- target_pos_x = 0.5 * (shadow_target_width - 1.0) * pos.x;
-
-#if !defined(DEPTH_CLAMP)
- pos_zd2 = pos.z * 0.5;
-
- gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
-#else
- gl_Position = pos;
-#endif
-
- passTextureIndex();
-
- vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
-
- vertex_color = diffuse_color;
-}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/shadowUtil.glsl b/indra/newview/app_settings/shaders/class3/deferred/shadowUtil.glsl
deleted file mode 100644
index 2f69a353e8..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/shadowUtil.glsl
+++ /dev/null
@@ -1,157 +0,0 @@
-/**
- * @file class3/deferred/shadowUtil.glsl
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2007, 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$
- */
-
-uniform sampler2D shadowMap0;
-uniform sampler2D shadowMap1;
-uniform sampler2D shadowMap2;
-uniform sampler2D shadowMap3;
-uniform sampler2D shadowMap4;
-uniform sampler2D shadowMap5;
-
-uniform vec3 sun_dir;
-uniform vec3 moon_dir;
-uniform vec2 shadow_res;
-uniform vec2 proj_shadow_res;
-uniform mat4 shadow_matrix[6];
-uniform vec4 shadow_clip;
-uniform float shadow_bias;
-
-uniform float spot_shadow_bias;
-uniform float spot_shadow_offset;
-
-float getDepth(vec2 screenpos);
-vec3 getNorm(vec2 screenpos);
-vec4 getPosition(vec2 pos_screen);
-
-float ReduceLightBleeding(float p_max, float Amount)
-{
- return smoothstep(Amount, 1, p_max);
-}
-
-float ChebyshevUpperBound(vec2 m, float t, float min_v, float Amount)
-{
- float p = (t <= m.x) ? 1.0 : 0.0;
-
- float v = m.y - (m.x*m.x);
- v = max(v, min_v);
-
- float d = t - m.x;
-
- float p_max = v / (v + d*d);
-
- p_max = ReduceLightBleeding(p_max, Amount);
-
- return max(p, p_max);
-}
-
-vec4 computeMoments(float depth, float a)
-{
- float m1 = depth;
- float dx = dFdx(depth);
- float dy = dFdy(depth);
- float m2 = m1*m1 + 0.25 * a * (dx*dx + dy*dy);
- return vec4(m1, m2, a, max(dx, dy));
-}
-
-float vsmDirectionalSample(vec4 stc, float depth, sampler2D shadowMap, mat4 shadowMatrix)
-{
- vec4 lpos = shadowMatrix * stc;
- vec4 moments = texture2D(shadowMap, lpos.xy);
- return ChebyshevUpperBound(moments.rg, depth - shadow_bias * 256.0f, 0.125, 0.9);
-}
-
-float vsmSpotSample(vec4 stc, float depth, sampler2D shadowMap, mat4 shadowMatrix)
-{
- vec4 lpos = shadowMatrix * stc;
- vec4 moments = texture2D(shadowMap, lpos.xy);
- lpos.xyz /= lpos.w;
- lpos.xy *= 0.5;
- lpos.xy += 0.5;
- return ChebyshevUpperBound(moments.rg, depth - spot_shadow_bias * 16.0f, 0.125, 0.9);
-}
-
-#if VSM_POINT_SHADOWS
-float vsmPointSample(float lightDistance, vec3 lightDirection, samplerCube shadow_cube_map)
-{
- vec4 moments = textureCube(shadow_cube_map, light_direction);
- return ChebyshevUpperBound(moments.rg, light_distance, 0.01, 0.25);
-}
-#endif
-
-float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen)
-{
- if (pos.z < -shadow_clip.w)
- {
- discard;
- }
-
- float depth = getDepth(pos_screen);
-
- vec4 spos = vec4(pos,1.0);
- vec4 near_split = shadow_clip*-0.75;
- vec4 far_split = shadow_clip*-1.25;
-
- float shadow = 0.0f;
- float weight = 1.0;
-
- if (spos.z < near_split.z)
- {
- shadow += vsmDirectionalSample(spos, depth, shadowMap3, shadow_matrix[3]);
- weight += 1.0f;
- }
- if (spos.z < near_split.y)
- {
- shadow += vsmDirectionalSample(spos, depth, shadowMap2, shadow_matrix[2]);
- weight += 1.0f;
- }
- if (spos.z < near_split.x)
- {
- shadow += vsmDirectionalSample(spos, depth, shadowMap1, shadow_matrix[1]);
- weight += 1.0f;
- }
- if (spos.z > far_split.x)
- {
- shadow += vsmDirectionalSample(spos, depth, shadowMap0, shadow_matrix[0]);
- weight += 1.0f;
- }
-
- shadow /= weight;
-
- return shadow;
-}
-
-float sampleSpotShadow(vec3 pos, vec3 norm, int index, vec2 pos_screen)
-{
- if (pos.z < -shadow_clip.w)
- {
- discard;
- }
-
- float depth = getDepth(pos_screen);
-
- pos += norm * spot_shadow_offset;
- return vsmSpotSample(vec4(pos, 1.0), depth, (index == 0) ? shadowMap4 : shadowMap5, shadow_matrix[4 + index]);
-}
-
diff --git a/indra/newview/app_settings/shaders/class3/deferred/shadowV.glsl b/indra/newview/app_settings/shaders/class3/deferred/shadowV.glsl
deleted file mode 100644
index 6577fe0ecf..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/shadowV.glsl
+++ /dev/null
@@ -1,62 +0,0 @@
-/**
- * @file class3/deferred/shadowV.glsl
- *
- * $LicenseInfo:firstyear=2011&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2011, 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$
- */
-
-uniform mat4 modelview_projection_matrix;
-uniform float shadow_target_width;
-uniform mat4 texture_matrix0;
-
-ATTRIBUTE vec3 position;
-ATTRIBUTE vec2 texcoord0;
-
-#if !defined(DEPTH_CLAMP)
-VARYING float pos_zd2;
-#endif
-
-VARYING vec4 pos;
-VARYING float target_pos_x;
-VARYING vec4 vertex_color;
-VARYING vec2 vary_texcoord0;
-
-void passTextureIndex();
-
-void main()
-{
- //transform vertex
- vec4 pre_pos = vec4(position.xyz, 1.0);
-
- pos = modelview_projection_matrix * pre_pos;
-
- target_pos_x = 0.5 * (shadow_target_width - 1.0) * pos.x;
-
-#if !defined(DEPTH_CLAMP)
- pos_zd2 = pos.z * 0.5;
-
- gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
-#else
- gl_Position = pos;
-#endif
-
- vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
-}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/skyF.glsl b/indra/newview/app_settings/shaders/class3/deferred/skyF.glsl
deleted file mode 100644
index a0b082ed7c..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/skyF.glsl
+++ /dev/null
@@ -1,126 +0,0 @@
-/**
- * @file class3/deferred/skyF.glsl
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2005, 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$
- */
-
-#ifdef DEFINE_GL_FRAGCOLOR
-out vec4 frag_data[3];
-#else
-#define frag_data gl_FragData
-#endif
-
-VARYING vec2 vary_frag;
-
-uniform vec3 camPosLocal;
-uniform vec3 sun_dir;
-uniform float sun_size;
-uniform float far_z;
-uniform mat4 inv_proj;
-uniform mat4 inv_modelview;
-
-uniform sampler2D transmittance_texture;
-uniform sampler3D scattering_texture;
-uniform sampler3D single_mie_scattering_texture;
-uniform sampler2D irradiance_texture;
-uniform sampler2D rainbow_map;
-uniform sampler2D halo_map;
-
-uniform float moisture_level;
-uniform float droplet_radius;
-uniform float ice_level;
-
-vec3 GetSolarLuminance();
-vec3 GetSkyLuminance(vec3 camPos, vec3 view_dir, float shadow_length, vec3 dir, out vec3 transmittance);
-vec3 GetSkyLuminanceToPoint(vec3 camPos, vec3 pos, float shadow_length, vec3 dir, out vec3 transmittance);
-
-vec3 ColorFromRadiance(vec3 radiance);
-vec3 rainbow(float d)
-{
- // d is the dot product of view and sun directions, so ranging -1.0..1.0
- // 'interesting' values of d are the range -0.75..-0.825, when view is nearly opposite of sun vec
- // Rainbox texture mode is GL_REPEAT, so tc of -.75 is equiv to 0.25, -0.825 equiv to 0.175.
-
- // SL-13629 Rainbow texture has colors within the correct .175...250 range, but order is inverted.
- // Rather than replace the texture, we mirror and translate the y tc to keep the colors within the
- // interesting range, but in reversed order: i.e. d = (1 - d) - 1.575
- d = clamp(-0.575 - d, 0.0, 1.0);
-
- // With the colors in the lower 1/4 of the texture, inverting the coords leaves most of it inaccessible.
- // So, we can stretch the texcoord above the colors (ie > 0.25) to fill the entire remaining coordinate
- // space. This improves gradation, reduces banding within the rainbow interior. (1-0.25) / (0.425/0.25) = 4.2857
- float interior_coord = max(0.0, d - 0.25) * 4.2857;
- d = clamp(d, 0.0, 0.25) + interior_coord;
-
- float rad = (droplet_radius - 5.0f) / 1024.0f;
- return pow(texture2D(rainbow_map, vec2(rad, d)).rgb, vec3(1.8)) * moisture_level;
-}
-
-vec3 halo22(float d)
-{
- float v = sqrt(max(0, 1 - (d*d)));
- return texture2D(halo_map, vec2(0, v)).rgb * ice_level;
-}
-
-void main()
-{
- vec3 pos = vec3((vary_frag * 2.0) - vec2(1.0, 1.0f), 1.0);
- vec4 view_pos = (inv_proj * vec4(pos, 1.0f));
-
- view_pos /= view_pos.w;
-
- vec3 view_ray = (inv_modelview * vec4(view_pos.xyz, 0.0f)).xyz + camPosLocal;
-
- vec3 view_direction = normalize(view_ray);
- vec3 sun_direction = normalize(sun_dir);
- vec3 earth_center = vec3(0, 0, -6360.0f);
- vec3 camPos = (camPosLocal / 1000.0f) - earth_center;
-
- vec3 transmittance;
- vec3 radiance_sun = GetSkyLuminance(camPos, view_direction, 0.0f, sun_direction, transmittance);
- vec3 solar_luminance = GetSolarLuminance();
-
- // If the view ray intersects the Sun, add the Sun radiance.
- float s = dot(view_direction, sun_direction);
-
- // cheesy solar disc...
- if (s >= (sun_size * 0.999))
- {
- radiance_sun += pow(smoothstep(0.0, 1.3, (s - (sun_size * 0.9))), 2.0) * solar_luminance * transmittance;
- }
- s = smoothstep(0.9, 1.0, s) * 16.0f;
-
- vec3 color = ColorFromRadiance(radiance_sun);
-
- float optic_d = dot(view_direction, sun_direction);
- vec3 halo_22 = halo22(optic_d);
-
- color.rgb += rainbow(optic_d) * optic_d;
- color.rgb += halo_22;
-
- color = pow(color, vec3(1.0/2.2));
-
- frag_data[0] = vec4(color, 1.0 + s);
- frag_data[1] = vec4(0.0);
- frag_data[2] = vec4(0.0, 1.0, 0.0, 1.0);
-}
-
diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
index 7ed9e7b4fc..8d48e6f596 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
@@ -1,31 +1,35 @@
-/**
+/**
* @file class3/deferred/softenLightF.glsl
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2007, 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$
*/
-
+
#extension GL_ARB_texture_rectangle : enable
+#extension GL_ARB_shader_texture_lod : enable
-/*[EXTRA_CODE_HERE]*/
+#define FLT_MAX 3.402823466e+38
+
+#define REFMAP_COUNT 256
+#define REF_SAMPLE_COUNT 64 //maximum number of samples to consider
#ifdef DEFINE_GL_FRAGCOLOR
out vec4 frag_color;
@@ -33,145 +37,208 @@ out vec4 frag_color;
#define frag_color gl_FragColor
#endif
-uniform sampler2DRect diffuseRect;
-uniform sampler2DRect specularRect;
-uniform sampler2DRect normalMap;
-uniform sampler2DRect lightMap;
-uniform sampler2DRect depthMap;
+uniform sampler2D diffuseRect;
+uniform sampler2D specularRect;
+uniform sampler2D normalMap;
+uniform sampler2D emissiveRect; // PBR linear packed Occlusion, Roughness, Metal. See: pbropaqueF.glsl
+
+const float M_PI = 3.14159265;
+
+#if defined(HAS_SUN_SHADOW) || defined(HAS_SSAO)
+uniform sampler2D lightMap;
+#endif
+
+uniform sampler2D depthMap;
uniform sampler2D lightFunc;
-uniform samplerCube environmentMap;
uniform float blur_size;
uniform float blur_fidelity;
// Inputs
-uniform vec4 morphFactor;
-uniform vec3 camPosLocal;
-uniform float cloud_shadow;
-uniform float max_y;
-uniform vec4 glow;
uniform mat3 env_mat;
-uniform vec4 shadow_clip;
uniform vec3 sun_dir;
+uniform vec3 moon_dir;
+uniform int sun_up_factor;
VARYING vec2 vary_fragcoord;
uniform mat4 inv_proj;
-uniform mat4 inv_modelview;
-
uniform vec2 screen_res;
-uniform sampler2D transmittance_texture;
-uniform sampler3D scattering_texture;
-uniform sampler3D single_mie_scattering_texture;
-uniform sampler2D irradiance_texture;
+vec3 getNorm(vec2 pos_screen);
+vec4 getPositionWithDepth(vec2 pos_screen, float depth);
-uniform sampler2D sh_input_r;
-uniform sampler2D sh_input_g;
-uniform sampler2D sh_input_b;
+void calcAtmosphericVarsLinear(vec3 inPositionEye, vec3 norm, vec3 light_dir, out vec3 sunlit, out vec3 amblit, out vec3 atten, out vec3 additive);
+vec3 atmosFragLightingLinear(vec3 l, vec3 additive, vec3 atten);
+vec3 scaleSoftClipFragLinear(vec3 l);
+vec3 fullbrightAtmosTransportFragLinear(vec3 light, vec3 additive, vec3 atten);
-vec3 GetSunAndSkyIrradiance(vec3 camPos, vec3 norm, vec3 dir, out vec3 sky_irradiance);
-vec3 GetSkyLuminance(vec3 camPos, vec3 view_dir, float shadow_length, vec3 dir, out vec3 transmittance);
-vec3 GetSkyLuminanceToPoint(vec3 camPos, vec3 pos, float shadow_length, vec3 dir, out vec3 transmittance);
+// reflection probe interface
+void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv,
+ 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);
-vec3 ColorFromRadiance(vec3 radiance);
-vec4 getPositionWithDepth(vec2 pos_screen, float depth);
-vec4 getPosition(vec2 pos_screen);
-vec3 getNorm(vec2 pos_screen);
+vec3 linear_to_srgb(vec3 c);
+vec3 srgb_to_linear(vec3 c);
#ifdef WATER_FOG
-vec4 applyWaterFogView(vec3 pos, vec4 color);
+vec4 applyWaterFogViewLinear(vec3 pos, vec4 color);
#endif
-void main()
+void calcDiffuseSpecular(vec3 baseColor, float metallic, inout vec3 diffuseColor, inout vec3 specularColor);
+
+vec3 pbrBaseLight(vec3 diffuseColor,
+ vec3 specularColor,
+ float metallic,
+ vec3 pos,
+ vec3 norm,
+ float perceptualRoughness,
+ vec3 light_dir,
+ vec3 sunlit,
+ float scol,
+ vec3 radiance,
+ vec3 irradiance,
+ vec3 colorEmissive,
+ float ao,
+ vec3 additive,
+ vec3 atten);
+
+vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor,
+ float perceptualRoughness,
+ float metallic,
+ vec3 n, // normal
+ vec3 v, // surface point to camera
+ vec3 l); //surface point to light
+
+
+void main()
{
- vec2 tc = vary_fragcoord.xy;
- float depth = texture2DRect(depthMap, tc.xy).r;
- vec3 pos = getPositionWithDepth(tc, depth).xyz;
- vec4 norm = texture2DRect(normalMap, tc);
+ vec2 tc = vary_fragcoord.xy;
+ float depth = getDepth(tc.xy);
+ vec4 pos = getPositionWithDepth(tc, depth);
+ vec4 norm = texture2D(normalMap, tc);
float envIntensity = norm.z;
- norm.xyz = getNorm(tc);
+ norm.xyz = getNorm(tc);
+ vec3 light_dir = (sun_up_factor == 1) ? sun_dir : moon_dir;
- float da = max(dot(norm.xyz, sun_dir.xyz), 0.0);
+ vec4 baseColor = texture2D(diffuseRect, tc);
+ vec4 spec = texture2D(specularRect, vary_fragcoord.xy); // NOTE: PBR linear Emissive
- vec4 diffuse = texture2DRect(diffuseRect, tc); // sRGB
- diffuse.rgb = srgb_to_linear(diffuse.rgb);
+#if defined(HAS_SUN_SHADOW) || defined(HAS_SSAO)
+ vec2 scol_ambocc = texture2D(lightMap, vary_fragcoord.xy).rg;
+#endif
+
+#if defined(HAS_SUN_SHADOW)
+ float scol = max(scol_ambocc.r, baseColor.a);
+#else
+ float scol = 1.0;
+#endif
+#if defined(HAS_SSAO)
+ float ambocc = scol_ambocc.g;
+#else
+ float ambocc = 1.0;
+#endif
- vec3 col;
+ vec3 color = vec3(0);
float bloom = 0.0;
- {
- vec3 camPos = (camPosLocal / 1000.0f) + vec3(0, 0, 6360.0f);
- vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy);
-
- vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg;
+ vec3 sunlit;
+ vec3 amblit;
+ vec3 additive;
+ vec3 atten;
- float scol = max(scol_ambocc.r, diffuse.a);
+ calcAtmosphericVarsLinear(pos.xyz, norm.xyz, light_dir, sunlit, amblit, additive, atten);
- float ambocc = scol_ambocc.g;
+ if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR))
+ {
+ vec3 orm = texture2D(specularRect, tc).rgb;
+ float perceptualRoughness = orm.g;
+ float metallic = orm.b;
+ float ao = orm.r * ambocc;
+
+ vec3 colorEmissive = texture2D(emissiveRect, tc).rgb;
+
+ // PBR IBL
+ float gloss = 1.0 - perceptualRoughness;
+ vec3 irradiance = vec3(0);
+ vec3 radiance = vec3(0);
+ 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
+ irradiance = max(amblit,irradiance);
- vec4 l1tap = vec4(1.0/sqrt(4*3.14159265), sqrt(3)/sqrt(4*3.14159265), sqrt(3)/sqrt(4*3.14159265), sqrt(3)/sqrt(4*3.14159265));
- vec4 l1r = texture2D(sh_input_r, vec2(0,0));
- vec4 l1g = texture2D(sh_input_g, vec2(0,0));
- vec4 l1b = texture2D(sh_input_b, vec2(0,0));
+ vec3 diffuseColor;
+ vec3 specularColor;
+ calcDiffuseSpecular(baseColor.rgb, metallic, diffuseColor, specularColor);
- vec3 indirect = vec3(dot(l1r, l1tap * vec4(1, norm.xyz)),
- dot(l1g, l1tap * vec4(1, norm.xyz)),
- dot(l1b, l1tap * vec4(1, norm.xyz)));
+ vec3 v = -normalize(pos.xyz);
+ color = pbrBaseLight(diffuseColor, specularColor, metallic, v, norm.xyz, perceptualRoughness, light_dir, sunlit, scol, radiance, irradiance, colorEmissive, ao, additive, atten);
+ }
+ else if (!GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_ATMOS))
+ {
+ //should only be true of WL sky, just port over base color value
+ color = srgb_to_linear(baseColor.rgb);
+ }
+ else
+ {
+ // legacy shaders are still writng sRGB to gbuffer
+ baseColor.rgb = srgb_to_linear(baseColor.rgb);
+ spec.rgb = srgb_to_linear(spec.rgb);
- indirect = clamp(indirect, vec3(0), vec3(1.0));
+ float da = clamp(dot(norm.xyz, light_dir.xyz), 0.0, 1.0);
- vec3 transmittance;
- vec3 sky_irradiance;
- vec3 sun_irradiance = GetSunAndSkyIrradiance(camPos, norm.xyz, sun_dir, sky_irradiance);
- vec3 inscatter = GetSkyLuminanceToPoint(camPos, (pos / 1000.f) + vec3(0, 0, 6360.0f), scol, sun_dir, transmittance);
+ vec3 irradiance = vec3(0);
+ vec3 glossenv = vec3(0);
+ vec3 legacyenv = vec3(0);
- vec3 radiance = scol * (sun_irradiance + sky_irradiance) + inscatter;
- vec3 atmo_color = ColorFromRadiance(radiance);
+ 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);
- col = atmo_color + indirect;
- col *= transmittance;
- col *= diffuse.rgb;
+ // apply lambertian IBL only (see pbrIbl)
+ color.rgb = irradiance * ambocc;
- vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
+ vec3 sun_contrib = min(da, scol) * sunlit;
+ color.rgb += sun_contrib;
+ color.rgb *= baseColor.rgb;
+
+ vec3 refnormpersp = reflect(pos.xyz, norm.xyz);
- if (spec.a > 0.0) // specular reflection
+ if (spec.a > 0.0) // specular reflection
{
- // the old infinite-sky shiny reflection
- //
- float sa = dot(refnormpersp, sun_dir.xyz);
- vec3 dumbshiny = scol * texture2D(lightFunc, vec2(sa, spec.a)).r * atmo_color;
-
+ float sa = dot(normalize(refnormpersp), light_dir.xyz);
+ vec3 dumbshiny = sunlit * scol * (texture2D(lightFunc, vec2(sa, spec.a)).r);
+
// add the two types of shiny together
- vec3 spec_contrib = dumbshiny * spec.rgb * 0.25;
- bloom = dot(spec_contrib, spec_contrib);
- col += spec_contrib;
- }
+ vec3 spec_contrib = dumbshiny * spec.rgb;
+ color.rgb += spec_contrib;
- col = mix(col, diffuse.rgb, diffuse.a);
+ // add radiance map
+ applyGlossEnv(color, glossenv, spec, pos.xyz, norm.xyz);
+ }
+ color.rgb = mix(color.rgb, baseColor.rgb, baseColor.a);
+
if (envIntensity > 0.0)
- { //add environmentmap
- vec3 env_vec = env_mat * refnormpersp;
- vec3 sun_direction = (inv_modelview * vec4(sun_dir, 1.0)).xyz;
- vec3 radiance_sun = GetSkyLuminance(camPos, env_vec, 0.0f, sun_direction, transmittance);
- vec3 refcol = ColorFromRadiance(radiance_sun);
- col = mix(col.rgb, refcol, envIntensity);
+ { // add environment map
+ applyLegacyEnv(color, legacyenv, spec, pos.xyz, norm.xyz, envIntensity);
}
-
- /*if (norm.w < 0.5)
- {
- col = scaleSoftClipFrag(col);
- }*/
-
- #ifdef WATER_FOG
- vec4 fogged = applyWaterFogView(pos,vec4(col, bloom));
- col = fogged.rgb;
- bloom = fogged.a;
- #endif
+
+ color = mix(atmosFragLightingLinear(color, additive, atten), fullbrightAtmosTransportFragLinear(color, additive, atten), baseColor.a);
+ color = scaleSoftClipFragLinear(color);
}
- //output linear since gamma correction happens down stream
- frag_color.rgb = col;
- frag_color.a = bloom;
+ #ifdef WATER_FOG
+ vec4 fogged = applyWaterFogViewLinear(pos.xyz, vec4(color, bloom));
+ color = fogged.rgb;
+ #endif
+
+ frag_color.rgb = color.rgb; //output linear since local lights will be added to this shader's results
+ frag_color.a = 0.0;
}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/spotLightF.glsl
index 56b0f4e5ce..3d8b95b882 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/spotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/spotLightF.glsl
@@ -1,9 +1,9 @@
/**
- * @file spotLightF.glsl
+ * @file class3\deferred\spotLightF.glsl
*
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2007, Linden Research, Inc.
+ * 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
@@ -28,20 +28,31 @@
/*[EXTRA_CODE_HERE]*/
+#define DEBUG_ANY_LIGHT_TYPE 0 // Output green light cone
+#define DEBUG_LEG_LIGHT_TYPE 0 // Show Legacy objects in green
+#define DEBUG_PBR_LIGHT_TYPE 0 // Show PBR objects in green
+#define DEBUG_PBR_SPOT 0
+#define DEBUG_PBR_SPOT_DIFFUSE 0
+#define DEBUG_PBR_SPOT_SPECULAR 0
+
+#define DEBUG_SPOT_NL 0 // monochome area effected by light
+#define DEBUG_SPOT_ZERO 0 // Output zero for spotlight
+
#ifdef DEFINE_GL_FRAGCOLOR
out vec4 frag_color;
#else
#define frag_color gl_FragColor
#endif
-uniform sampler2DRect diffuseRect;
-uniform sampler2DRect specularRect;
-uniform sampler2DRect depthMap;
-uniform sampler2DRect normalMap;
+uniform sampler2D diffuseRect;
+uniform sampler2D specularRect;
+uniform sampler2D depthMap;
+uniform sampler2D normalMap;
+uniform sampler2D emissiveRect; // PBR linear packed Occlusion, Roughness, Metal. See: pbropaqueF.glsl
uniform samplerCube environmentMap;
-uniform sampler2DRect lightMap;
+uniform sampler2D lightMap;
uniform sampler2D noiseMap;
-uniform sampler2D projectionMap;
+uniform sampler2D projectionMap; // rgba
uniform sampler2D lightFunc;
uniform mat4 proj_mat; //screen space to light space
@@ -71,217 +82,210 @@ uniform vec2 screen_res;
uniform mat4 inv_proj;
-vec3 getNorm(vec2 pos_screen);
-
-vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod)
-{
- vec4 ret = texture2DLod(projectionMap, tc, lod);
-
- vec2 dist = vec2(0.5) - abs(tc-vec2(0.5));
-
- float det = min(lod/(proj_lod*0.5), 1.0);
-
- float d = min(dist.x, dist.y);
-
- d *= min(1, d * (proj_lod - lod));
-
- float edge = 0.25*det;
-
- ret *= clamp(d/edge, 0.0, 1.0);
-
- return ret;
-}
-
-vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod)
-{
- vec4 ret = texture2DLod(projectionMap, tc, lod);
-
- vec2 dist = vec2(0.5) - abs(tc-vec2(0.5));
-
- float det = min(lod/(proj_lod*0.5), 1.0);
-
- float d = min(dist.x, dist.y);
-
- float edge = 0.25*det;
-
- ret *= clamp(d/edge, 0.0, 1.0);
-
- return ret;
-}
+void calcHalfVectors(vec3 lv, vec3 n, vec3 v, out vec3 h, out vec3 l, out float nh, out float nl, out float nv, out float vh, out float lightDist);
+float calcLegacyDistanceAttenuation(float distance, float falloff);
+bool clipProjectedLightVars(vec3 center, vec3 pos, out float dist, out float l_dist, out vec3 lv, out vec4 proj_tc );
+vec4 getNormalEnvIntensityFlags(vec2 screenpos, out vec3 n, out float envIntensity);
+vec3 getProjectedLightAmbiance(float amb_da, float attenuation, float lit, float nl, float noise, vec2 projected_uv);
+vec3 getProjectedLightDiffuseColor(float light_distance, vec2 projected_uv );
+vec3 getProjectedLightSpecularColor(vec3 pos, vec3 n);
+vec2 getScreenXY(vec4 clip_point);
+vec2 getScreenCoord(vec4 clip_point);
+vec3 srgb_to_linear(vec3 c);
+vec4 texture2DLodSpecular(vec2 tc, float lod);
-vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod)
-{
- vec4 ret = texture2DLod(projectionMap, tc, lod);
-
- vec2 dist = tc-vec2(0.5);
-
- float d = dot(dist,dist);
-
- ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0), 1.0);
-
- return ret;
-}
+vec4 getPosition(vec2 pos_screen);
+const float M_PI = 3.14159265;
-vec4 getPosition(vec2 pos_screen);
+vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor,
+ float perceptualRoughness,
+ float metallic,
+ vec3 n, // normal
+ vec3 v, // surface point to camera
+ vec3 l); //surface point to light
-void main()
+void main()
{
- vec4 frag = vary_fragcoord;
- frag.xyz /= frag.w;
- frag.xyz = frag.xyz*0.5+0.5;
- frag.xy *= screen_res;
-
- vec3 pos = getPosition(frag.xy).xyz;
- vec3 lv = trans_center.xyz-pos.xyz;
- float dist = length(lv);
- dist /= size;
- if (dist > 1.0)
+#if defined(LOCAL_LIGHT_KILL)
+ discard;
+#else
+ vec3 final_color = vec3(0,0,0);
+ vec2 tc = getScreenCoord(vary_fragcoord);
+ vec3 pos = getPosition(tc).xyz;
+
+ vec3 lv;
+ vec4 proj_tc;
+ float dist, l_dist;
+ if (clipProjectedLightVars(trans_center, pos, dist, l_dist, lv, proj_tc))
{
discard;
}
-
+
float shadow = 1.0;
-
+
if (proj_shadow_idx >= 0)
{
- vec4 shd = texture2DRect(lightMap, frag.xy);
+ vec4 shd = texture2D(lightMap, tc);
shadow = (proj_shadow_idx == 0) ? shd.b : shd.a;
shadow += shadow_fade;
shadow = clamp(shadow, 0.0, 1.0);
}
-
- vec3 norm = texture2DRect(normalMap, frag.xy).xyz;
- float envIntensity = norm.z;
- norm = getNorm(frag.xy);
-
- norm = normalize(norm);
- float l_dist = -dot(lv, proj_n);
-
- vec4 proj_tc = (proj_mat * vec4(pos.xyz, 1.0));
- if (proj_tc.z < 0.0)
- {
- discard;
- }
-
- proj_tc.xyz /= proj_tc.w;
-
- float fa = (falloff*0.5) + 1.0;
- float dist_atten = min(1.0 - (dist - 1.0 * (1.0 - fa)) / fa, 1.0);
- dist_atten *= dist_atten;
- dist_atten *= 2.0;
+ float envIntensity;
+ vec3 n;
+ vec4 norm = getNormalEnvIntensityFlags(tc, n, envIntensity); // need `norm.w` for GET_GBUFFER_FLAG()
+
+ float dist_atten = calcLegacyDistanceAttenuation(dist, falloff);
if (dist_atten <= 0.0)
{
discard;
}
-
- lv = proj_origin-pos.xyz;
- lv = normalize(lv);
- float da = dot(norm, lv);
-
- vec3 col = vec3(0,0,0);
-
- vec3 diff_tex = srgb_to_linear(texture2DRect(diffuseRect, frag.xy).rgb);
-
- vec4 spec = texture2DRect(specularRect, frag.xy);
- vec3 dlit = vec3(0, 0, 0);
+ lv = proj_origin-pos.xyz; // NOTE: Re-using lv
+ vec3 h, l, v = -normalize(pos);
+ float nh, nl, nv, vh, lightDist;
+ calcHalfVectors(lv, n, v, h, l, nh, nl, nv, vh, lightDist);
- float noise = texture2D(noiseMap, frag.xy/128.0).b;
- if (proj_tc.z > 0.0 &&
- proj_tc.x < 1.0 &&
- proj_tc.y < 1.0 &&
- proj_tc.x > 0.0 &&
- proj_tc.y > 0.0)
+ vec3 diffuse = texture2D(diffuseRect, tc).rgb;
+ vec4 spec = texture2D(specularRect, tc);
+ vec3 dlit = vec3(0, 0, 0);
+ vec3 slit = vec3(0, 0, 0);
+
+ vec3 amb_rgb = vec3(0);
+ if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR))
{
- float amb_da = proj_ambiance;
- float lit = 0.0;
+ vec3 colorEmissive = texture2D(emissiveRect, tc).rgb;
+ vec3 orm = spec.rgb;
+ float perceptualRoughness = orm.g;
+ float metallic = orm.b;
+ vec3 f0 = vec3(0.04);
+ vec3 baseColor = diffuse.rgb;
- if (da > 0.0)
+ vec3 diffuseColor = baseColor.rgb*(vec3(1.0)-f0);
+ diffuseColor *= 1.0 - metallic;
+
+ vec3 specularColor = mix(f0, baseColor.rgb, metallic);
+
+ // We need this additional test inside a light's frustum since a spotlight's ambiance can be applied
+ if (proj_tc.x > 0.0 && proj_tc.x < 1.0
+ && proj_tc.y > 0.0 && proj_tc.y < 1.0)
{
- lit = da * dist_atten * noise;
+ float lit = 0.0;
+ float amb_da = 0.0;
- float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0);
- float lod = diff * proj_lod;
-
- vec4 plcol = texture2DLodDiffuse(projectionMap, proj_tc.xy, lod);
-
- dlit = color.rgb * plcol.rgb * plcol.a;
-
- col = dlit*lit*diff_tex*shadow;
- amb_da += (da*0.5)*(1.0-shadow)*proj_ambiance;
- }
-
- //float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0);
- vec4 amb_plcol = texture2DLodAmbient(projectionMap, proj_tc.xy, proj_lod);
-
- amb_da += (da*da*0.5+0.5)*(1.0-shadow)*proj_ambiance;
+ if (nl > 0.0)
+ {
+ amb_da += (nl*0.5 + 0.5) * proj_ambiance;
- amb_da *= dist_atten * noise;
-
- amb_da = min(amb_da, 1.0-lit);
-
- col += amb_da*color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a;
- }
-
+ dlit = getProjectedLightDiffuseColor( l_dist, proj_tc.xy );
- if (spec.a > 0.0)
+ vec3 intensity = dist_atten * dlit * 3.0 * shadow; // Legacy attenuation
+ final_color += intensity*pbrPunctual(diffuseColor, specularColor, perceptualRoughness, metallic, n.xyz, v, normalize(lv));
+ }
+
+ amb_rgb = getProjectedLightAmbiance( amb_da, dist_atten, lit, nl, 1.0, proj_tc.xy );
+ final_color += diffuse.rgb * amb_rgb;
+ }
+ }
+ else
{
- dlit *= min(da*6.0, 1.0) * dist_atten;
- vec3 npos = -normalize(pos);
-
- //vec3 ref = dot(pos+lv, norm);
- 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)
+ diffuse = srgb_to_linear(diffuse);
+ spec.rgb = srgb_to_linear(spec.rgb);
+
+ float noise = texture2D(noiseMap, tc).b;
+ if (proj_tc.z > 0.0 &&
+ proj_tc.x < 1.0 &&
+ proj_tc.y < 1.0 &&
+ proj_tc.x > 0.0 &&
+ proj_tc.y > 0.0)
{
- float scol = fres*texture2D(lightFunc, vec2(nh, spec.a)).r*gt/(nh*da);
- col += dlit*scol*spec.rgb*shadow;
+ float amb_da = proj_ambiance;
+ float lit = 0.0;
+
+ if (nl > 0.0)
+ {
+ lit = nl * dist_atten * noise;
+
+ dlit = getProjectedLightDiffuseColor( l_dist, proj_tc.xy );
+
+ final_color = dlit*lit*diffuse*shadow;
+
+ amb_da += (nl*0.5+0.5) /* * (1.0-shadow) */ * proj_ambiance;
+ }
+
+ vec3 amb_rgb = getProjectedLightAmbiance( amb_da, dist_atten, lit, nl, noise, proj_tc.xy );
+ final_color += diffuse.rgb*amb_rgb;
+ #if DEBUG_LEG_LIGHT_TYPE
+ final_color = vec3(0,0.5,0);
+ #endif
}
- }
-
- if (envIntensity > 0.0)
- {
- vec3 ref = reflect(normalize(pos), norm);
-
- //project from point pos in direction ref to plane proj_p, proj_n
- vec3 pdelta = proj_p-pos;
- float ds = dot(ref, proj_n);
-
- if (ds < 0.0)
+ if (spec.a > 0.0)
+ {
+ dlit *= min(nl*6.0, 1.0) * dist_atten;
+ float fres = pow(1 - dot(h, v), 5)*0.4+0.5;
+
+ float gtdenom = 2 * nh;
+ float gt = max(0, min(gtdenom * nv / vh, gtdenom * nl / vh));
+
+ if (nh > 0.0)
+ {
+ float scol = fres*texture2D(lightFunc, vec2(nh, spec.a)).r*gt/(nh*nl);
+ vec3 speccol = dlit*scol*spec.rgb*shadow;
+ speccol = clamp(speccol, vec3(0), vec3(1));
+ final_color += speccol;
+ }
+ }
+
+ if (envIntensity > 0.0)
{
- vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds;
-
- vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0));
+ vec3 ref = reflect(normalize(pos), n);
- if (stc.z > 0.0)
+ //project from point pos in direction ref to plane proj_p, proj_n
+ vec3 pdelta = proj_p-pos;
+ float ds = dot(ref, proj_n);
+
+ if (ds < 0.0)
{
- stc /= stc.w;
-
- if (stc.x < 1.0 &&
- stc.y < 1.0 &&
- stc.x > 0.0 &&
- stc.y > 0.0)
+ vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds;
+
+ vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0));
+
+ if (stc.z > 0.0)
{
- col += color.rgb * texture2DLodSpecular(projectionMap, stc.xy, (1 - spec.a) * (proj_lod * 0.6)).rgb * shadow * envIntensity;
+ stc /= stc.w;
+
+ if (stc.x < 1.0 &&
+ stc.y < 1.0 &&
+ stc.x > 0.0 &&
+ stc.y > 0.0)
+ {
+ final_color += color.rgb * texture2DLodSpecular(stc.xy, (1 - spec.a) * (proj_lod * 0.6)).rgb * shadow * envIntensity;
+ }
}
}
}
}
-
+
+#if DEBUG_PBR_SPOT_DIFFUSE
+ final_color = vec3(nl * dist_atten);
+#endif
+#if DEBUG_SPOT_NL
+ final_color = vec3(nl);
+#endif
+#if DEBUG_SPOT_ZERO
+ final_color = vec3(0,0,0);
+#endif
+#if DEBUG_ANY_LIGHT_TYPE
+ final_color = vec3(0,0.3333,0);
+#endif
+
//not sure why, but this line prevents MATBUG-194
- col = max(col, vec3(0.0));
+ final_color = max(final_color, vec3(0.0));
- frag_color.rgb = col;
+ //output linear colors as gamma correction happens down stream
+ frag_color.rgb = final_color;
frag_color.a = 0.0;
+#endif // LOCAL_LIGHT_KILL
}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/sunLightF.glsl
deleted file mode 100644
index 112b498c90..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/sunLightF.glsl
+++ /dev/null
@@ -1,57 +0,0 @@
-/**
- * @file class3\deferred\sunLightF.glsl
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2007, 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$
- */
-
-#extension GL_ARB_texture_rectangle : enable
-
-/*[EXTRA_CODE_HERE]*/
-
-#ifdef DEFINE_GL_FRAGCOLOR
-out vec4 frag_color;
-#else
-#define frag_color gl_FragColor
-#endif
-
-//class 2, shadows, no SSAO
-
-// Inputs
-VARYING vec2 vary_fragcoord;
-
-vec4 getPosition(vec2 pos_screen);
-vec3 getNorm(vec2 pos_screen);
-
-float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen);
-float sampleSpotShadow(vec3 pos, vec3 norm, int index, vec2 pos_screen);
-
-void main()
-{
- vec2 pos_screen = vary_fragcoord.xy;
- vec4 pos = getPosition(pos_screen);
- vec3 norm = getNorm(pos_screen);
-
- frag_color.r = sampleDirectionalShadow(pos.xyz, norm, pos_screen);
- frag_color.g = 1.0f;
- frag_color.b = sampleSpotShadow(pos.xyz, norm, 0, pos_screen);
- frag_color.a = sampleSpotShadow(pos.xyz, norm, 1, pos_screen);
-}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class3/deferred/sunLightSSAOF.glsl
deleted file mode 100644
index 342a2ff3ed..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/sunLightSSAOF.glsl
+++ /dev/null
@@ -1,61 +0,0 @@
-/**
- * @file class3\deferred\sunLightSSAOF.glsl
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2007, 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$
- */
-
-#extension GL_ARB_texture_rectangle : enable
-
-/*[EXTRA_CODE_HERE]*/
-
-#ifdef DEFINE_GL_FRAGCOLOR
-out vec4 frag_color;
-#else
-#define frag_color gl_FragColor
-#endif
-
-//class 2 -- shadows and SSAO
-
-// Inputs
-VARYING vec2 vary_fragcoord;
-
-uniform vec3 sun_dir;
-
-vec4 getPosition(vec2 pos_screen);
-vec3 getNorm(vec2 pos_screen);
-
-float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen);
-float sampleSpotShadow(vec3 pos, vec3 norm, int index, vec2 pos_screen);
-
-//calculate decreases in ambient lighting when crowded out (SSAO)
-float calcAmbientOcclusion(vec4 pos, vec3 norm, vec2 pos_screen);
-
-void main()
-{
- vec2 pos_screen = vary_fragcoord.xy;
- vec4 pos = getPosition(pos_screen);
- vec3 norm = getNorm(pos_screen);
-
- frag_color.r = sampleDirectionalShadow(pos.xyz, norm, pos_screen);
- frag_color.b = calcAmbientOcclusion(pos, norm, pos_screen);
- frag_color.b = sampleSpotShadow(pos.xyz, norm, 0, pos_screen);
- frag_color.a = sampleSpotShadow(pos.xyz, norm, 1, pos_screen);
-}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/treeShadowV.glsl b/indra/newview/app_settings/shaders/class3/deferred/treeShadowV.glsl
deleted file mode 100644
index 15e769ac10..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/treeShadowV.glsl
+++ /dev/null
@@ -1,43 +0,0 @@
-/**
- * @file treeShadowV.glsl
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2007, 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$
- */
-
-uniform mat4 texture_matrix0;
-uniform mat4 modelview_projection_matrix;
-
-ATTRIBUTE vec3 position;
-ATTRIBUTE vec2 texcoord0;
-
-VARYING vec4 pos;
-VARYING vec2 vary_texcoord0;
-
-void main()
-{
- //transform vertex
- pos = modelview_projection_matrix*vec4(position.xyz, 1.0);
-
- gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
-
- vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
-}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/waterV.glsl b/indra/newview/app_settings/shaders/class3/deferred/waterV.glsl
deleted file mode 100644
index 02000d90ca..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/waterV.glsl
+++ /dev/null
@@ -1,95 +0,0 @@
-/**
- * @file waterV.glsl
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2007, 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$
- */
-
-uniform mat4 modelview_matrix;
-uniform mat4 modelview_projection_matrix;
-
-ATTRIBUTE vec3 position;
-
-
-uniform vec2 d1;
-uniform vec2 d2;
-uniform float time;
-uniform vec3 eyeVec;
-uniform float waterHeight;
-
-VARYING vec4 refCoord;
-VARYING vec4 littleWave;
-VARYING vec4 view;
-
-VARYING vec4 vary_position;
-
-float wave(vec2 v, float t, float f, vec2 d, float s)
-{
- return (dot(d, v)*f + t*s)*f;
-}
-
-void main()
-{
- //transform vertex
- vec4 pos = vec4(position.xyz, 1.0);
- mat4 modelViewProj = modelview_projection_matrix;
-
- vec4 oPosition;
-
- //get view vector
- vec3 oEyeVec;
- oEyeVec.xyz = pos.xyz-eyeVec;
-
- float d = length(oEyeVec.xy);
- float ld = min(d, 2560.0);
-
- pos.xy = eyeVec.xy + oEyeVec.xy/d*ld;
- view.xyz = oEyeVec;
-
- d = clamp(ld/1536.0-0.5, 0.0, 1.0);
- d *= d;
-
- oPosition = vec4(position, 1.0);
- oPosition.z = mix(oPosition.z, max(eyeVec.z*0.75, 0.0), d);
- vary_position = modelview_matrix * oPosition;
- oPosition = modelViewProj * oPosition;
-
- refCoord.xyz = oPosition.xyz + vec3(0,0,0.2);
-
- //get wave position parameter (create sweeping horizontal waves)
- vec3 v = pos.xyz;
- v.x += (cos(v.x*0.08/*+time*0.01*/)+sin(v.y*0.02))*6.0;
-
- //push position for further horizon effect.
- pos.xyz = oEyeVec.xyz*(waterHeight/oEyeVec.z);
- pos.w = 1.0;
- pos = modelview_matrix*pos;
-
- //pass wave parameters to pixel shader
- vec2 bigWave = (v.xy) * vec2(0.04,0.04) + d1 * time * 0.055;
- //get two normal map (detail map) texture coordinates
- littleWave.xy = (v.xy) * vec2(0.45, 0.9) + d2 * time * 0.13;
- littleWave.zw = (v.xy) * vec2(0.1, 0.2) + d1 * time * 0.1;
- view.w = bigWave.y;
- refCoord.w = bigWave.x;
-
- gl_Position = oPosition;
-}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/underWaterF.glsl b/indra/newview/app_settings/shaders/class3/environment/underWaterF.glsl
index 540226e672..a5e0adf8fa 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/underWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class3/environment/underWaterF.glsl
@@ -1,5 +1,5 @@
/**
- * @file underWaterF.glsl
+ * @file class3\environment\underWaterF.glsl
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
@@ -23,19 +23,15 @@
* $/LicenseInfo$
*/
-/*[EXTRA_CODE_HERE]*/
-
-#ifdef DEFINE_GL_FRAGCOLOR
-out vec4 frag_data[3];
-#else
-#define frag_data gl_FragData
-#endif
+out vec4 frag_color;
uniform sampler2D diffuseMap;
-uniform sampler2D bumpMap;
+uniform sampler2D bumpMap;
+
+#ifdef TRANSPARENT_WATER
uniform sampler2D screenTex;
-uniform sampler2D refTex;
uniform sampler2D screenDepth;
+#endif
uniform vec4 fogCol;
uniform vec3 lightDir;
@@ -49,7 +45,7 @@ uniform float kd;
uniform vec4 waterPlane;
uniform vec3 eyeVec;
uniform vec4 waterFogColor;
-uniform float waterFogDensity;
+uniform vec3 waterFogColorLinear;
uniform float waterFogKS;
uniform vec2 screenRes;
@@ -57,47 +53,15 @@ uniform vec2 screenRes;
VARYING vec4 refCoord;
VARYING vec4 littleWave;
VARYING vec4 view;
+in vec3 vary_position;
-vec2 encode_normal(vec3 n);
-
-vec4 applyWaterFog(vec4 color, vec3 viewVec)
-{
- //normalize view vector
- vec3 view = normalize(viewVec);
- float es = -view.z;
-
- //find intersection point with water plane and eye vector
-
- //get eye depth
- float e0 = max(-waterPlane.w, 0.0);
-
- //get object depth
- float depth = length(viewVec);
-
- //get "thickness" of water
- float l = max(depth, 0.1);
-
- float kd = waterFogDensity;
- float ks = waterFogKS;
- vec4 kc = waterFogColor;
-
- float F = 0.98;
-
- float t1 = -kd * pow(F, ks * e0);
- float t2 = kd + ks * es;
- float t3 = pow(F, t2*l) - 1.0;
-
- float L = min(t1/t2*t3, 1.0);
-
- float D = pow(0.98, l*kd);
- return color * D + kc * L;
-}
+vec4 applyWaterFogViewLinear(vec3 pos, vec4 color);
void main()
{
vec4 color;
-
- //get detail normals
+
+ //get detail normals
vec3 wave1 = texture2D(bumpMap, vec2(refCoord.w, view.w)).xyz*2.0-1.0;
vec3 wave2 = texture2D(bumpMap, littleWave.xy).xyz*2.0-1.0;
vec3 wave3 = texture2D(bumpMap, littleWave.zw).xyz*2.0-1.0;
@@ -106,10 +70,12 @@ void main()
//figure out distortion vector (ripply)
vec2 distort = (refCoord.xy/refCoord.z) * 0.5 + 0.5;
distort = distort+wavef.xy*refScale;
-
- vec4 fb = texture2D(screenTex, distort);
- frag_data[0] = vec4(fb.rgb, 1.0); // diffuse
- frag_data[1] = vec4(0.5,0.5,0.5, 0.95); // speccolor*spec, spec
- frag_data[2] = vec4(encode_normal(wavef), 0.0, 0.0); // normalxyz, displace
+#ifdef TRANSPARENT_WATER
+ vec4 fb = texture2D(screenTex, distort);
+#else
+ vec4 fb = vec4(waterFogColorLinear, 0.0);
+#endif
+
+ frag_color = applyWaterFogViewLinear(vary_position, fb);
}
diff --git a/indra/newview/app_settings/shaders/class3/environment/waterF.glsl b/indra/newview/app_settings/shaders/class3/environment/waterF.glsl
new file mode 100644
index 0000000000..b792feee2a
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/environment/waterF.glsl
@@ -0,0 +1,268 @@
+/**
+ * @file waterF.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$
+ */
+
+// class3/environment/waterF.glsl
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_color;
+#else
+#define frag_color gl_FragColor
+#endif
+
+vec3 scaleSoftClipFragLinear(vec3 l);
+vec3 atmosFragLightingLinear(vec3 light, vec3 additive, vec3 atten);
+void calcAtmosphericVarsLinear(vec3 inPositionEye, vec3 norm, vec3 light_dir, out vec3 sunlit, out vec3 amblit, out vec3 atten, out vec3 additive);
+vec4 applyWaterFogViewLinear(vec3 pos, vec4 color, vec3 sunlit);
+
+// PBR interface
+vec3 pbrIbl(vec3 diffuseColor,
+ vec3 specularColor,
+ vec3 radiance, // radiance map sample
+ vec3 irradiance, // irradiance map sample
+ float ao, // ambient occlusion factor
+ float nv, // normal dot view vector
+ float perceptualRoughness);
+
+vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor,
+ float perceptualRoughness,
+ float metallic,
+ vec3 n, // normal
+ vec3 v, // surface point to camera
+ vec3 l); //surface point to light
+
+uniform sampler2D bumpMap;
+uniform sampler2D bumpMap2;
+uniform float blend_factor;
+#ifdef TRANSPARENT_WATER
+uniform sampler2D screenTex;
+uniform sampler2D screenDepth;
+#endif
+
+uniform sampler2D refTex;
+
+uniform float sunAngle;
+uniform float sunAngle2;
+uniform vec3 lightDir;
+uniform vec3 specular;
+uniform float lightExp;
+uniform float refScale;
+uniform float kd;
+uniform vec2 screenRes;
+uniform vec3 normScale;
+uniform float fresnelScale;
+uniform float fresnelOffset;
+uniform float blurMultiplier;
+uniform vec4 waterFogColor;
+uniform vec3 waterFogColorLinear;
+
+
+//bigWave is (refCoord.w, view.w);
+VARYING vec4 refCoord;
+VARYING vec4 littleWave;
+VARYING vec4 view;
+in vec3 vary_position;
+in vec3 vary_normal;
+in vec3 vary_tangent;
+in vec3 vary_light_dir;
+
+vec3 BlendNormal(vec3 bump1, vec3 bump2)
+{
+ vec3 n = mix(bump1, bump2, blend_factor);
+ return n;
+}
+
+vec3 srgb_to_linear(vec3 col);
+
+vec3 vN, vT, vB;
+
+vec3 transform_normal(vec3 vNt)
+{
+ return normalize(vNt.x * vT + vNt.y * vB + vNt.z * vN);
+}
+
+void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv,
+ 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);
+
+void main()
+{
+ vec4 color;
+
+ vN = vary_normal;
+ vT = vary_tangent;
+ vB = cross(vN, vT);
+
+ vec3 pos = vary_position.xyz;
+
+ float dist = length(pos.xyz);
+
+ //normalize view vector
+ vec3 viewVec = normalize(pos.xyz);
+
+ //get wave normals
+ vec2 bigwave = vec2(refCoord.w, view.w);
+ vec3 wave1_a = texture(bumpMap, bigwave, -2 ).xyz*2.0-1.0;
+ vec3 wave2_a = texture2D(bumpMap, littleWave.xy).xyz*2.0-1.0;
+ vec3 wave3_a = texture2D(bumpMap, littleWave.zw).xyz*2.0-1.0;
+
+ vec3 wave1_b = texture(bumpMap2, bigwave ).xyz*2.0-1.0;
+ vec3 wave2_b = texture2D(bumpMap2, littleWave.xy).xyz*2.0-1.0;
+ vec3 wave3_b = texture2D(bumpMap2, littleWave.zw).xyz*2.0-1.0;
+
+ //wave1_a = wave2_a = wave3_a = wave1_b = wave2_b = wave3_b = vec3(0,0,1);
+
+ vec3 wave1 = BlendNormal(wave1_a, wave1_b);
+ vec3 wave2 = BlendNormal(wave2_a, wave2_b);
+ vec3 wave3 = BlendNormal(wave3_a, wave3_b);
+
+ vec2 distort = (refCoord.xy/refCoord.z) * 0.5 + 0.5;
+
+ //wave1 = transform_normal(wave1);
+ //wave2 = transform_normal(wave2);
+ //wave3 = transform_normal(wave3);
+
+ vec3 wavef = (wave1 + wave2 * 0.4 + wave3 * 0.6) * 0.5;
+
+ vec3 waver = wavef*3;
+
+ wavef = transform_normal(wavef);
+
+ //wavef.z *= max(-viewVec.z, 0.1);
+
+ wavef = normalize(wavef);
+
+ //get base fresnel components
+
+ vec3 df = vec3(
+ dot(viewVec, wave1),
+ dot(viewVec, (wave2 + wave3) * 0.5),
+ dot(viewVec, wave3)
+ ) * fresnelScale + fresnelOffset;
+
+ float dist2 = dist;
+ dist = max(dist, 5.0);
+
+ float dmod = sqrt(dist);
+
+ float df1 = df.x + df.y + df.z;
+
+
+
+
+ //figure out distortion vector (ripply)
+ vec2 distort2 = distort + waver.xy * refScale / max(dmod, 1.0);
+
+ distort2 = clamp(distort2, vec2(0), vec2(0.999));
+
+ vec3 sunlit;
+ vec3 amblit;
+ vec3 additive;
+ vec3 atten;
+
+ calcAtmosphericVarsLinear(pos.xyz, wavef, vary_light_dir, sunlit, amblit, additive, atten);
+
+#ifdef TRANSPARENT_WATER
+ vec4 fb = texture2D(screenTex, distort2);
+ float depth = texture2D(screenDepth, distort2).r;
+ vec3 refPos = getPositionWithNDC(vec3(distort2*2.0-vec2(1.0), depth*2.0-1.0));
+
+ if (refPos.z > pos.z-0.05)
+ {
+ //we sampled an above water sample, don't distort
+ distort2 = distort;
+ fb = texture2D(screenTex, distort2);
+ depth = texture2D(screenDepth, distort2).r;
+ refPos = getPositionWithNDC(vec3(distort2 * 2.0 - vec2(1.0), depth * 2.0 - 1.0));
+ }
+
+ fb = applyWaterFogViewLinear(refPos, fb, sunlit);
+#else
+ vec4 fb = vec4(waterFogColorLinear.rgb, 0.0);
+#endif
+
+ vec3 v = -viewVec;
+ float NdotV = clamp(abs(dot(wavef.xyz, v)), 0.001, 1.0);
+
+ float metallic = fresnelOffset * 0.1; // fudge -- use fresnelOffset as metalness
+ float roughness = 0.1;
+ float gloss = 1.0 - roughness;
+
+ vec3 baseColor = vec3(0.25);
+ vec3 f0 = vec3(0.04);
+ vec3 diffuseColor = baseColor.rgb * (vec3(1.0) - f0);
+ diffuseColor *= gloss;
+
+ vec3 specularColor = mix(f0, baseColor.rgb, metallic);
+
+ vec3 refnorm = normalize(wavef + vary_normal);
+ //vec3 refnorm = wavef;
+
+ vec3 irradiance = vec3(0);
+ vec3 radiance = vec3(0);
+ sampleReflectionProbes(irradiance, radiance, distort, pos, refnorm, gloss, true);
+ radiance *= 0.5;
+ irradiance = fb.rgb;
+
+ color.rgb = pbrIbl(diffuseColor, specularColor, radiance, irradiance, gloss, NdotV, 0.0);
+
+ // fudge -- for punctual lighting, pretend water is metallic
+ diffuseColor = vec3(0);
+ specularColor = vec3(1);
+ roughness = 0.1;
+ float scol = 1.0; // TODO -- incorporate shadow map
+
+ //color.rgb += pbrPunctual(diffuseColor, specularColor, roughness, metallic, wavef, v, vary_light_dir) * sunlit * 2.75 * scol;
+
+ //get specular component
+ float spec = clamp(dot(vary_light_dir, (reflect(viewVec, wavef))), 0.0, 1.0);
+
+ //harden specular
+ spec = pow(spec, 128.0);
+
+ color.rgb += spec * specular;
+
+ color.rgb = atmosFragLightingLinear(color.rgb, additive, atten);
+ color.rgb = scaleSoftClipFragLinear(color.rgb);
+
+ color.a = 0.f;
+ //color.rgb = fb.rgb;
+ //color.rgb = vec3(depth*depth*depth*depth);
+ //color.rgb = srgb_to_linear(normalize(refPos) * 0.5 + 0.5);
+ //color.rgb = srgb_to_linear(normalize(pos) * 0.5 + 0.5);
+ //color.rgb = srgb_to_linear(wavef * 0.5 + 0.5);
+
+ //color.rgb = radiance;
+ frag_color = color;
+
+#if defined(WATER_EDGE)
+ gl_FragDepth = 0.9999847f;
+#endif
+
+}
+
diff --git a/indra/newview/app_settings/shaders/class3/windlight/advancedAtmoF.glsl b/indra/newview/app_settings/shaders/class3/windlight/advancedAtmoF.glsl
deleted file mode 100644
index c6ea3ec9d4..0000000000
--- a/indra/newview/app_settings/shaders/class3/windlight/advancedAtmoF.glsl
+++ /dev/null
@@ -1,73 +0,0 @@
-/**
- * @file class3\wl\advancedAtmoF.glsl
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2005, 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$
- */
-
-#ifdef DEFINE_GL_FRAGCOLOR
-out vec4 frag_color;
-#else
-#define frag_color gl_FragColor
-#endif
-
-in vec3 view_dir;
-
-uniform vec3 cameraPosLocal;
-uniform vec3 sun_dir;
-uniform float sun_size;
-
-uniform sampler2D transmittance_texture;
-uniform sampler3D scattering_texture;
-uniform sampler3D mie_scattering_texture;
-uniform sampler2D irradiance_texture;
-
-vec3 GetSolarLuminance();
-vec3 GetSkyLuminance(vec3 camPos, vec3 view_dir, float shadow_length, vec3 sun_dir, out vec3 transmittance);
-vec3 GetSkyLuminanceToPoint(vec3 camPos, vec3 pos, float shadow_length, vec3 sun_dir, out vec3 transmittance);
-vec3 GetSunAndSkyIlluminance(vec3 pos, vec3 norm, vec3 sun_dir, out vec3 sky_irradiance);
-
-void main()
-{
- vec3 view_direction = normalize(view_dir);
-
- vec3 camPos = cameraPosLocal;
- vec3 transmittance;
- vec3 sky_illum;
- vec3 radiance = GetSkyLuminance(camPos, view_direction, 0.0f, sun_dir, transmittance);
- vec3 radiance2 = GetSunAndSkyIlluminance(camPos, view_direction, sun_dir, sky_illum);
-
- //radiance *= transmittance;
-
- // If the view ray intersects the Sun, add the Sun radiance.
- if (dot(view_direction, sun_dir) >= sun_size)
- {
- radiance = radiance + transmittance * GetSolarLuminance();
- }
-
- //vec3 color = vec3(1.0) - exp(-radiance);
- //color = pow(color, vec3(1.0 / 2.2));
-
- frag_color.rgb = radiance;
-
- frag_color.a = 1.0;
-}
-
diff --git a/indra/newview/app_settings/shaders/class3/windlight/atmosphericsV.glsl b/indra/newview/app_settings/shaders/class3/windlight/atmosphericsV.glsl
deleted file mode 100644
index b76192d73f..0000000000
--- a/indra/newview/app_settings/shaders/class3/windlight/atmosphericsV.glsl
+++ /dev/null
@@ -1,51 +0,0 @@
-/**
- * @file class3\wl\atmosphericsV.glsl
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2005, 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$
- */
-
-// VARYING param funcs
-void setSunlitColor(vec3 v);
-void setAmblitColor(vec3 v);
-void setAdditiveColor(vec3 v);
-void setAtmosAttenuation(vec3 v);
-void setPositionEye(vec3 v);
-
-vec3 getAdditiveColor();
-
-void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, out vec3 sunlit, out vec3 amblit, out vec3 additive, out vec3 atten, bool use_ao);
-
-void calcAtmospherics(vec3 inPositionEye) {
-
- vec3 P = inPositionEye;
- setPositionEye(P);
- vec3 tmpsunlit = vec3(1);
- vec3 tmpamblit = vec3(1);
- vec3 tmpaddlit = vec3(1);
- vec3 tmpattenlit = vec3(1);
- calcAtmosphericVars(inPositionEye, vec3(0), 1, tmpsunlit, tmpamblit, tmpaddlit, tmpattenlit, true);
- setSunlitColor(tmpsunlit);
- setAmblitColor(tmpamblit);
- setAdditiveColor(tmpaddlit);
- setAtmosAttenuation(tmpattenlit);
-}
-
diff --git a/indra/newview/app_settings/shaders/class3/windlight/transportF.glsl b/indra/newview/app_settings/shaders/class3/windlight/transportF.glsl
deleted file mode 100644
index 545a32a227..0000000000
--- a/indra/newview/app_settings/shaders/class3/windlight/transportF.glsl
+++ /dev/null
@@ -1,68 +0,0 @@
-/**
- * @file class3\wl\transportF.glsl
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2007, 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$
- */
-
-//////////////////////////////////////////////////////////
-// The fragment shader for the terrain atmospherics
-//////////////////////////////////////////////////////////
-
-vec3 getAdditiveColor();
-vec3 getAtmosAttenuation();
-
-uniform int no_atmo;
-
-vec3 atmosTransportFrag(vec3 light, vec3 additive, vec3 atten)
-{
- if (no_atmo == 1)
- {
- return light;
- }
- // fullbright responds minimally to atmos scatter effects
- light *= min(15.0 * atten.r, 1.0);
- light += (0.1 * additive);
- return light * 2.0;
-}
-
-vec3 atmosTransport(vec3 light)
-{
- return atmosTransportFrag(light, getAdditiveColor(), getAtmosAttenuation());
-}
-
-vec3 fullbrightAtmosTransportFrag(vec3 light, vec3 additive, vec3 atten)
-{
- float brightness = dot(light.rgb, vec3(0.33333));
- return vec3(1,0,1);
- //return atmosTransportFrag(light * 0.5, additive * (brightness * 0.5 + 0.5), atten);
-}
-
-vec3 fullbrightAtmosTransport(vec3 light)
-{
- return atmosTransportFrag(light, getAdditiveColor(), getAtmosAttenuation());
-}
-
-vec3 fullbrightShinyAtmosTransport(vec3 light)
-{
- float brightness = dot(light.rgb, vec3(0.33333));
- return atmosTransportFrag(light * 0.5, getAdditiveColor() * (brightness * brightness), getAtmosAttenuation());
-}
diff --git a/indra/newview/app_settings/shaders/shader_hierarchy.txt b/indra/newview/app_settings/shaders/shader_hierarchy.txt
index 8ef04d8e1f..81e1327178 100644
--- a/indra/newview/app_settings/shaders/shader_hierarchy.txt
+++ b/indra/newview/app_settings/shaders/shader_hierarchy.txt
@@ -1,177 +1,15 @@
-Class 3 is highest quality / lowest performance
-Class 2 is medium quality / medium performance
-Class 1 is lowest quality / highest performance
+Second Life shader variants are referred to as "classes."
-Shaders WILL fall back to "lower" classes for functionality.
+When a shader of a particular class is loaded, a lower class may
+be loaded if the class requested doesn't exist or fails to load
+for any reason. In general, shaders that require more resources
+or later hardware capabilities should be higher class and
+lower classes can be used for fallback implementations or lower
+detail settings.
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-avatar/avatarV.glsl - gAvatarProgram, gAvatarWaterProgram
- main() - avatar/avatarV.glsl
- getSkinnedTransform() - avatarSkinV.glsl
- calcAtmospherics() - windlight/atmosphericsV.glsl
- calcLighting() - lighting/lightV.glsl
- sumLights() - lighting/sumLightsV.glsl
- calcDirectionalLight() - lighting/lightFuncV.glsl
- calcPointLight() - lighting/lightFuncV.glsl
- atmosAmbient() - windlight/atmosphericsHelpersV.glsl
- atmosAffectDirectionalLight() - windlight/atmosphericsHelpersV.glsl
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-avatar/avatarF.glsl - gAvatarProgram
- main() - avatar/avatarF.glsl
- default_lighting() - lighting/lightF.glsl
- calc_default_lighting() - lighting/lightF.glsl
- atmosLighting() - windlight/atmosphericsF.glsl
- scaleSoftClip() - windlight/gammaF.glsl
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-avatar/eyeballV.glsl - gAvatarEyeballProgram
- main() - avatar/eyeballV.glsl
- calcAtmospherics() - windlight/atmosphericsV.glsl
- calcLightingSpecular() - lighting/lightSpecularV.glsl
- sumLightsSpecular() - lighting/sumLightsSpecularV.glsl
- calcDirectionalLightSpecular() - lighting/lightFuncSpecularV.glsl
- calcPointLightSpecular() - lighting/lightFuncSpecularV.glsl
- atmosAmbient() - windlight/atmosphericsHelpersV.glsl
- atmosAffectDirectionalLight() - windlight/atmosphericsHelpersV.glsl
- atmosGetDiffuseSunlightColor() - windlight/atmosphericsHelpersV.glsl
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-avatar/eyeballF.glsl - gAvatarEyeballProgram
- main() - avatar/eyeballF.glsl
- default_lighting() - lighting/lightF.glsl
- calc_default_lighting() - lighting/lightF.glsl
- atmosLighting() - windlight/atmosphericsF.glsl
- scaleSoftClip() - windlight/gammaF.glsl
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-avatar/pickAvatarV.glsl - gAvatarPickProgram
- main() - avatar/pickAvatarV.glsl
- getSkinnedTransform() - avatarSkinV.glsl
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-avatar/pickAvatarF.glsl - gAvatarPickProgram
- main() - avatar/pickAvatarF.glsl
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-environment/terrainV.glsl - gTerrainProgram, gTerrainWaterProgram
- texgen_object() - environment/terrainV.glsl
- main() - environment/terrainV.glsl
- texgen_object() - environment/terrainV.glsl
- calcAtmospherics() - windlight/atmosphericsV.glsl
- calcLighting() - lighting/lightV.glsl
- sumLights() - lighting/sumLightsV.glsl
- calcDirectionalLight() - lighting/lightFuncV.glsl
- calcPointLight() - lighting/lightFuncV.glsl
- atmosAmbient() - windlight/atmosphericsHelpersV.glsl
- atmosAffectDirectionalLight() - windlight/atmosphericsHelpersV.glsl
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-environment/terrainF.glsl - gTerrainProgram
- main() - environment/terrainF.glsl
- atmosLighting() - windlight/atmosphericsF.glsl
- scaleSoftClip() - windlight/gammaF.glsl
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-environment/terrainWaterF.glsl - gTerrainWaterProgram
- main() - environment/terrainWaterF.glsl
- atmosLighting() - windlight/atmosphericsF.glsl
- applyWaterFog() - environment/waterFogF.glsl
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-environment/underWaterF.glsl - gUnderWaterProgram
- applyWaterFog() - environment/underWaterF.glsl (NOTE: different than one in waterFogF.glsl)
- main() - environment/underWaterF.glsl
- applyWaterFog() - environment/underWaterF.glsl
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-environment/waterV.glsl - gWaterProgram, gUnderWaterProgram
- main() - environment/waterV.glsl
- calcAtmospherics() - windlight/atmosphericsV.glsl
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-environment/waterF.glsl - gWaterProgram
- main() - environment/waterF.glsl
- atmosTransport() - windlight/transportF.glsl
- scaleSoftClip() - windlight/gammaF.glsl
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-objects/fullbrightV.glsl - gObjectFullbrightProgram, gObjectFullbrightWaterProgram
- main() - objects/fullbrightV.glsl
- calcAtmospherics() - windlight/atmosphericsV.glsl
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-objects/fullbrightF.glsl - gObjectFullbrightProgram
- main() - objects/fullbrightF.glsl
- fullbright_lighting() - lighting/lightFullbrightF.glsl
- fullbrightAtmosTransport() - windlight/transportF.glsl
- atmosTransport() - windlight/transportF.glsl
- fullbrightScaleSoftClip() - windlight/gammaF.glsl
- scaleSoftClip() - windlight/gammaF.glsl
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-objects/fullbrightShinyV.glsl - gObjectFullbrightShinyProgram
- main() - objects/fullbrightShinyV.glsl
- calcAtmospherics() - windlight/atmosphericsV.glsl
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-objects/fullbrightShinyF.glsl - gObjectFullbrightShinyProgram
- main() - objects/fullbrightShinyF.glsl
- fullbright_shiny_lighting() - lighting/lightFullbrightShinyF.glsl
- fullbrightShinyAtmosTransport() - windlight/transportF.glsl
- atmosTransport() - windlight/transportF.glsl
- fullbrightScaleSoftClip() - windlight/gammaF.glsl
- scaleSoftClip() - windlight/gammaF.glsl
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-objects/fullbrightWaterF.glsl - gObjectFullbrightWaterProgram
- main() - objects/fullbrightWaterF.glsl
- fullbright_lighting_water() - lighting/lightFullbrightWaterF.glsl
- fullbrightAtmosTransport() - windlight/transportF.glsl
- atmosTransport() - windlight/transportF.glsl
- applyWaterFog() - environment/waterFogF.glsl
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-objects/shinyV.glsl - gObjectShinyProgram, gObjectShinyWaterProgram
- main() - objects/shinyV.glsl
- calcAtmospherics() - windlight/atmosphericsV.glsl
- calcLighting() - lighting/lightV.glsl
- calcLighting(vec4) - lighting/lightV.glsl
- sumLights() - lighting/sumLightsV.glsl
- calcDirectionalLight() - lighting/lightFuncV.glsl
- calcPointLight() - lighting/lightFuncV.glsl
- atmosAmbient() - windlight/atmosphericsHelpersV.glsl
- atmosAffectDirectionalLight() - windlight/atmosphericsHelpersV.glsl
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-objects/shinyF.glsl - gObjectShinyProgram
- main() - objects/shinyF.glsl
- shiny_lighting() - lighting/lightShinyF.glsl
- atmosLighting() - windlight/atmosphericsF.glsl
- scaleSoftClip() - windlight/gammaF.glsl
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-objects/shinyWaterF.glsl - gObjectShinyWaterProgram
- main() - objects/shinyWaterF.glsl
- shiny_lighting_water() - lighting/lightShinyWaterF.glsl
- atmosLighting() - windlight/atmosphericsF.glsl
- applyWaterFog() - environment/waterFogF.glsl
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-objects/simpleV.glsl - gObjectSimpleProgram, gObjectSimpleWaterProgram
- main() - objects/simpleV.glsl
- calcAtmospherics() - windlight/atmosphericsV.glsl
- calcLighting() - lighting/lightV.glsl
- sumLights() - lighting/sumLightsV.glsl
- calcDirectionalLight() - lighting/lightFuncV.glsl
- calcPointLight() - lighting/lightFuncV.glsl
- atmosAmbient() - windlight/atmosphericsHelpersV.glsl
- atmosAffectDirectionalLight() - windlight/atmosphericsHelpersV.glsl
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-objects/simpleF.glsl - gObjectSimpleProgram
- main() - objects/simpleF.glsl
- default_lighting() - lighting/lightF.glsl
- atmosLighting() - windlight/atmosphericsF.glsl
- scaleSoftClip() - windlight/gammaF.glsl
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-objects/simpleWaterF.glsl - gObjectSimpleWaterProgram, gAvatarWaterProgram
- main() - objects/simpleWaterF.glsl
- default_lighting_water() - lighting/lightWaterF.glsl
- atmosLighting() - windlight/atmosphericsF.glsl
- applyWaterFog() - environment/waterFogF.glsl
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-windlight/skyV.glsl - gWLSkyProgram
- main() - windlight/skyV.glsl
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-windlight/skyF.glsl - gWLSkyProgram
- main() - windlight/skyF.glsl
- scaleSoftClip() - windlight/gammaF.glsl
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-windlight/cloudsV.glsl - gWLCloudProgram
- main() - windlight/cloudsV.glsl
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-windlight/cloudsF.glsl - gWLCloudProgram
- main() - windlight/cloudsF.glsl
- scaleSoftClip() - windlight/gammaF.glsl
+Which class is chosen will generally depend on graphics preferences.
+
+Previously, someone tried to enumerate the shaders here, but don't do
+that. It messes with searches and the shader hierarchy changes often.
diff --git a/indra/newview/app_settings/ultra_graphics.xml b/indra/newview/app_settings/ultra_graphics.xml
deleted file mode 100644
index 8462df207b..0000000000
--- a/indra/newview/app_settings/ultra_graphics.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<settings version = "101">
- <!--NO SHADERS-->
- <RenderAvatarCloth value="TRUE"/>
- <!--Default for now-->
- <RenderAvatarLODFactor value="1.0"/>
- <!--Default for now-->
- <RenderAvatarPhysicsLODFactor value="1.0"/>
- <!--Short Range-->
- <RenderFarClip value="256"/>
- <!--Default for now-->
- <RenderFlexTimeFactor value="1"/>
- <!--256... but they do not use this-->
- <RenderGlowResolutionPow value="9"/>
- <!--Low number-->
- <RenderMaxPartCount value="4096"/>
- <!--bump okay-->
- <RenderObjectBump value="TRUE"/>
- <!--NO SHADERS-->
- <RenderReflectionDetail value="4"/>
- <!--Simple-->
- <RenderTerrainDetail value="1"/>
- <!--Default for now-->
- <RenderTerrainLODFactor value="2.0"/>
- <!--Default for now-->
- <RenderTreeLODFactor value="1.0"/>
- <!--Avater Impostors and Visual Muting Limits (real defaults set
- based on default graphics setting -->
- <RenderAvatarMaxNonImpostors value="0"/>
- <RenderAvatarMaxComplexity value="350000"/>
- <RenderAutoMuteSurfaceAreaLimit value="1500.0"/>
- <!--Default for now-->
- <RenderVolumeLODFactor value="2.0"/>
- <!--NO SHADERS-->
- <WindLightUseAtmosShaders value="TRUE"/>
- <!--Deferred Shading-->
- <RenderDeferred value="TRUE"/>
- <!--SSAO Enabled-->
- <RenderDeferredSSAO value="TRUE"/>
- <!--Full Shadows-->
- <RenderShadowDetail value="2"/>
-</settings>
diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt
index 93dd5e7e70..360f4d5fc4 100644
--- a/indra/newview/featuretable.txt
+++ b/indra/newview/featuretable.txt
@@ -1,4 +1,4 @@
-version 34
+version 48
// 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
@@ -28,7 +28,7 @@ version 34
//
list all
RenderAnisotropic 1 1
-RenderAvatarCloth 1 1
+RenderAvatarCloth 0 0
RenderAvatarLODFactor 1 1.0
RenderAvatarPhysicsLODFactor 1 1.0
RenderAvatarMaxNonImpostors 1 16
@@ -45,10 +45,11 @@ RenderGround 1 1
RenderMaxPartCount 1 8192
RenderObjectBump 1 1
RenderLocalLights 1 1
-RenderReflectionDetail 1 4
+RenderTransparentWater 1 1
+RenderReflectionsEnabled 1 1
+RenderReflectionProbeDetail 1 2
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
-RenderTransparentWater 1 1
RenderTreeLODFactor 1 1.0
RenderVBOEnable 1 1
RenderVBOMappingDisable 1 1
@@ -59,9 +60,9 @@ WindLightUseAtmosShaders 1 1
WLSkyDetail 1 128
Disregard128DefaultDrawDistance 1 1
Disregard96DefaultDrawDistance 1 1
-RenderTextureMemoryMultiple 1 1.0
RenderCompressTextures 1 1
RenderShaderLightingMaxLevel 1 3
+RenderReflectionProbeCount 1 256
RenderDeferred 1 1
RenderDeferredSSAO 1 1
RenderUseAdvancedAtmospherics 1 0
@@ -70,7 +71,9 @@ RenderUseStreamVBO 1 1
RenderFSAASamples 1 16
RenderMaxTextureIndex 1 16
RenderGLContextCoreProfile 1 1
-RenderGLMultiThreaded 1 1
+RenderGLMultiThreaded 1 0
+RenderReflectionProbeResolution 1 256
+RenderScreenSpaceReflections 1 1
//
@@ -78,7 +81,6 @@ RenderGLMultiThreaded 1 1
//
list Low
RenderAnisotropic 1 0
-RenderAvatarCloth 1 0
RenderAvatarLODFactor 1 0
RenderAvatarPhysicsLODFactor 1 0
RenderAvatarMaxNonImpostors 1 3
@@ -88,27 +90,25 @@ RenderFlexTimeFactor 1 0
RenderGlowResolutionPow 1 8
RenderLocalLights 1 0
RenderMaxPartCount 1 0
-RenderObjectBump 1 0
-RenderReflectionDetail 1 0
+RenderTransparentWater 1 0
+RenderReflectionsEnabled 1 0
+RenderReflectionProbeDetail 1 0
RenderTerrainDetail 1 0
RenderTerrainLODFactor 1 1
-RenderTransparentWater 1 0
RenderTreeLODFactor 1 0
RenderVolumeLODFactor 1 1.125
-WindLightUseAtmosShaders 1 0
-RenderDeferred 1 0
RenderDeferredSSAO 1 0
RenderUseAdvancedAtmospherics 1 0
RenderShadowDetail 1 0
WLSkyDetail 1 48
RenderFSAASamples 1 0
+RenderScreenSpaceReflections 1 0
//
// Medium Low Graphics Settings
//
list LowMid
RenderAnisotropic 1 0
-RenderAvatarCloth 1 0
RenderAvatarLODFactor 1 0.5
RenderAvatarMaxComplexity 1 100000
RenderAvatarPhysicsLODFactor 1 0.75
@@ -116,28 +116,26 @@ RenderFarClip 1 96
RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 8
RenderMaxPartCount 1 2048
-RenderObjectBump 1 1
RenderLocalLights 1 1
-RenderReflectionDetail 1 0
+RenderTransparentWater 1 0
+RenderReflectionsEnabled 1 0
+RenderReflectionProbeDetail 1 0
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 1.0
-RenderTransparentWater 1 1
RenderTreeLODFactor 1 0.5
RenderVolumeLODFactor 1 1.125
-WindLightUseAtmosShaders 1 0
-RenderDeferred 1 0
RenderDeferredSSAO 1 0
RenderUseAdvancedAtmospherics 1 0
RenderShadowDetail 1 0
WLSkyDetail 1 48
RenderFSAASamples 1 0
+RenderScreenSpaceReflections 1 0
//
// Medium Graphics Settings (standard)
//
list Mid
RenderAnisotropic 1 1
-RenderAvatarCloth 1 0
RenderAvatarLODFactor 1 1.0
RenderAvatarMaxComplexity 1 200000
RenderAvatarPhysicsLODFactor 1 1.0
@@ -145,28 +143,26 @@ RenderFarClip 1 128
RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 9
RenderMaxPartCount 1 4096
-RenderObjectBump 1 1
RenderLocalLights 1 1
-RenderReflectionDetail 1 0
+RenderTransparentWater 1 0
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
-RenderTransparentWater 1 1
RenderTreeLODFactor 1 0.5
RenderVolumeLODFactor 1 1.125
-WindLightUseAtmosShaders 1 1
-RenderDeferred 1 0
RenderDeferredSSAO 1 0
RenderUseAdvancedAtmospherics 1 0
RenderShadowDetail 1 0
WLSkyDetail 1 48
RenderFSAASamples 1 2
+RenderReflectionsEnabled 1 1
+RenderReflectionProbeDetail 1 0
+RenderScreenSpaceReflections 1 0
//
// Medium High Graphics Settings (deferred enabled)
//
list MidHigh
RenderAnisotropic 1 1
-RenderAvatarCloth 1 0
RenderAvatarLODFactor 1 1.0
RenderAvatarMaxComplexity 1 250000
RenderAvatarPhysicsLODFactor 1 1.0
@@ -174,28 +170,26 @@ RenderFarClip 1 128
RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 9
RenderMaxPartCount 1 4096
-RenderObjectBump 1 1
RenderLocalLights 1 1
-RenderReflectionDetail 1 0
+RenderTransparentWater 1 1
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
-RenderTransparentWater 1 1
RenderTreeLODFactor 1 0.5
RenderVolumeLODFactor 1 1.125
-WindLightUseAtmosShaders 1 1
-RenderDeferred 1 1
RenderDeferredSSAO 1 0
RenderUseAdvancedAtmospherics 1 0
RenderShadowDetail 1 0
WLSkyDetail 1 48
RenderFSAASamples 1 2
+RenderReflectionsEnabled 1 1
+RenderReflectionProbeDetail 1 1
+RenderScreenSpaceReflections 1 0
//
// High Graphics Settings (deferred + SSAO)
//
list High
RenderAnisotropic 1 1
-RenderAvatarCloth 1 0
RenderAvatarLODFactor 1 1.0
RenderAvatarMaxComplexity 1 300000
RenderAvatarPhysicsLODFactor 1 1.0
@@ -203,28 +197,26 @@ RenderFarClip 1 128
RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 9
RenderMaxPartCount 1 4096
-RenderObjectBump 1 1
RenderLocalLights 1 1
-RenderReflectionDetail 1 0
+RenderTransparentWater 1 1
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
-RenderTransparentWater 1 1
RenderTreeLODFactor 1 0.5
RenderVolumeLODFactor 1 1.125
-WindLightUseAtmosShaders 1 1
-RenderDeferred 1 1
RenderDeferredSSAO 1 1
RenderUseAdvancedAtmospherics 1 0
RenderShadowDetail 1 0
WLSkyDetail 1 48
RenderFSAASamples 1 2
+RenderReflectionsEnabled 1 1
+RenderReflectionProbeDetail 1 1
+RenderScreenSpaceReflections 1 0
//
// High Ultra Graphics Settings (deferred + SSAO + shadows)
//
list HighUltra
RenderAnisotropic 1 1
-RenderAvatarCloth 1 0
RenderAvatarLODFactor 1 1.0
RenderAvatarMaxComplexity 1 350000
RenderAvatarPhysicsLODFactor 1 1.0
@@ -232,28 +224,26 @@ RenderFarClip 1 128
RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 9
RenderMaxPartCount 1 4096
-RenderObjectBump 1 1
RenderLocalLights 1 1
-RenderReflectionDetail 1 0
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
RenderTransparentWater 1 1
RenderTreeLODFactor 1 0.5
RenderVolumeLODFactor 1 1.125
-WindLightUseAtmosShaders 1 1
-RenderDeferred 1 1
RenderDeferredSSAO 1 1
RenderUseAdvancedAtmospherics 1 0
RenderShadowDetail 1 2
WLSkyDetail 1 48
RenderFSAASamples 1 2
+RenderReflectionsEnabled 1 1
+RenderReflectionProbeDetail 1 1
+RenderScreenSpaceReflections 1 0
//
// Ultra graphics (REALLY PURTY!)
//
list Ultra
RenderAnisotropic 1 1
-RenderAvatarCloth 1 1
RenderAvatarLODFactor 1 1.0
RenderAvatarPhysicsLODFactor 1 1.0
RenderFarClip 1 256
@@ -261,8 +251,6 @@ RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 9
RenderLocalLights 1 1
RenderMaxPartCount 1 8192
-RenderObjectBump 1 1
-RenderReflectionDetail 1 4
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
RenderTransparentWater 1 1
@@ -270,18 +258,19 @@ RenderTreeLODFactor 1 1.0
RenderVolumeLODFactor 1 2.0
WindLightUseAtmosShaders 1 1
WLSkyDetail 1 128
-RenderDeferred 1 1
RenderDeferredSSAO 1 1
RenderUseAdvancedAtmospherics 1 0
RenderShadowDetail 1 2
RenderFSAASamples 1 2
+RenderReflectionsEnabled 1 1
+RenderReflectionProbeDetail 1 1
+RenderScreenSpaceReflections 1 1
//
// Class Unknown Hardware (unknown)
//
list Unknown
RenderShadowDetail 1 0
-RenderDeferred 1 0
RenderDeferredSSAO 1 0
RenderUseAdvancedAtmospherics 1 0
@@ -292,33 +281,36 @@ list VRAMGT512
RenderCompressTextures 1 0
//
+// VRAM < 2GB
+//
+list VRAMLT2GB
+RenderReflectionProbeResolution 1 128
+
+//
// "Default" setups for safe, low, medium, high
//
list safe
RenderAnisotropic 1 0
-RenderAvatarCloth 0 0
RenderAvatarMaxNonImpostors 1 16
RenderAvatarMaxComplexity 1 80000
-RenderObjectBump 0 0
RenderLocalLights 1 0
RenderMaxPartCount 1 1024
RenderTerrainDetail 1 0
-RenderReflectionDetail 0 0
-WindLightUseAtmosShaders 0 0
-RenderDeferred 0 0
+RenderTransparentWater 1 0
RenderDeferredSSAO 0 0
RenderShadowDetail 0 0
+RenderReflectionProbeDetail 0 -1
list Intel
RenderAnisotropic 1 0
RenderFSAASamples 1 0
-RenderGLMultiThreaded 1 0
-RenderGLContextCoreProfile 1 0
+RenderGLContextCoreProfile 1 0
-// AMD cards generally perform better when not using VBOs for streaming data
-// AMD cards also prefer an OpenGL Compatibility Profile Context
list AMD
-RenderUseStreamVBO 1 0
-RenderGLContextCoreProfile 1 0
+RenderGLMultiThreaded 1 1
+list GL3
+RenderFSAASamples 0 0
+RenderReflectionsEnabled 0 0
+RenderReflectionProbeDetail 0 0
diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt
index fed035c7fa..40e4436763 100644
--- a/indra/newview/featuretable_mac.txt
+++ b/indra/newview/featuretable_mac.txt
@@ -1,4 +1,4 @@
-version 38
+version 44
// 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
@@ -28,7 +28,7 @@ version 38
//
list all
RenderAnisotropic 1 0
-RenderAvatarCloth 1 1
+RenderAvatarCloth 0 0
RenderAvatarLODFactor 1 1.0
RenderAvatarPhysicsLODFactor 1 1.0
RenderAvatarMaxNonImpostors 1 16
@@ -45,7 +45,6 @@ RenderGround 1 1
RenderMaxPartCount 1 8192
RenderObjectBump 1 1
RenderLocalLights 1 1
-RenderReflectionDetail 1 4
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
RenderTransparentWater 1 1
@@ -59,7 +58,6 @@ WindLightUseAtmosShaders 1 1
WLSkyDetail 1 128
Disregard128DefaultDrawDistance 1 1
Disregard96DefaultDrawDistance 1 1
-RenderTextureMemoryMultiple 1 1.0
RenderCompressTextures 1 1
RenderShaderLightingMaxLevel 1 3
RenderDeferred 1 1
@@ -69,15 +67,17 @@ RenderShadowDetail 1 2
RenderUseStreamVBO 1 1
RenderFSAASamples 1 16
RenderMaxTextureIndex 1 16
-RenderGLContextCoreProfile 1 0
+RenderGLContextCoreProfile 1 1
RenderGLMultiThreaded 1 0
+RenderReflectionsEnabled 1 1
+RenderReflectionProbeDetail 1 2
+RenderScreenSpaceReflections 1 1
//
// Low Graphics Settings
//
list Low
RenderAnisotropic 1 0
-RenderAvatarCloth 1 0
RenderAvatarLODFactor 1 0
RenderAvatarPhysicsLODFactor 1 0
RenderAvatarMaxNonImpostors 1 3
@@ -87,27 +87,25 @@ RenderFlexTimeFactor 1 0
RenderGlowResolutionPow 1 8
RenderLocalLights 1 0
RenderMaxPartCount 1 0
-RenderObjectBump 1 0
-RenderReflectionDetail 1 0
RenderTerrainDetail 1 0
RenderTerrainLODFactor 1 1
RenderTransparentWater 1 0
RenderTreeLODFactor 1 0
RenderVolumeLODFactor 1 0.5
-WindLightUseAtmosShaders 1 0
-RenderDeferred 1 0
RenderDeferredSSAO 1 0
RenderUseAdvancedAtmospherics 1 0
RenderShadowDetail 1 0
WLSkyDetail 1 48
RenderFSAASamples 1 0
+RenderReflectionsEnabled 1 0
+RenderReflectionProbeDetail 1 0
+RenderScreenSpaceReflections 1 0
//
// Medium Low Graphics Settings
//
list LowMid
RenderAnisotropic 1 0
-RenderAvatarCloth 1 0
RenderAvatarLODFactor 1 0.5
RenderAvatarMaxComplexity 1 100000
RenderAvatarPhysicsLODFactor 1 0.75
@@ -115,28 +113,26 @@ RenderFarClip 1 96
RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 8
RenderMaxPartCount 1 2048
-RenderObjectBump 1 1
RenderLocalLights 1 1
-RenderReflectionDetail 1 0
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 1.0
RenderTransparentWater 1 1
RenderTreeLODFactor 1 0.5
RenderVolumeLODFactor 1 1.125
-WindLightUseAtmosShaders 1 0
-RenderDeferred 1 0
RenderDeferredSSAO 1 0
RenderUseAdvancedAtmospherics 1 0
RenderShadowDetail 1 0
WLSkyDetail 1 48
RenderFSAASamples 1 0
+RenderReflectionsEnabled 1 0
+RenderReflectionProbeDetail 1 0
+RenderScreenSpaceReflections 1 0
//
// Medium Graphics Settings (standard)
//
list Mid
RenderAnisotropic 1 1
-RenderAvatarCloth 1 0
RenderAvatarLODFactor 1 1.0
RenderAvatarMaxComplexity 1 200000
RenderAvatarPhysicsLODFactor 1 1.0
@@ -144,28 +140,26 @@ RenderFarClip 1 128
RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 9
RenderMaxPartCount 1 4096
-RenderObjectBump 1 1
RenderLocalLights 1 1
-RenderReflectionDetail 1 0
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
RenderTransparentWater 1 1
RenderTreeLODFactor 1 0.5
RenderVolumeLODFactor 1 1.125
-WindLightUseAtmosShaders 1 1
-RenderDeferred 1 0
RenderDeferredSSAO 1 0
RenderUseAdvancedAtmospherics 1 0
RenderShadowDetail 1 0
WLSkyDetail 1 48
RenderFSAASamples 1 2
+RenderReflectionsEnabled 1 1
+RenderReflectionProbeDetail 1 0
+RenderScreenSpaceReflections 1 0
//
// Medium High Graphics Settings (deferred enabled)
//
list MidHigh
RenderAnisotropic 1 1
-RenderAvatarCloth 1 0
RenderAvatarLODFactor 1 1.0
RenderAvatarMaxComplexity 1 250000
RenderAvatarPhysicsLODFactor 1 1.0
@@ -173,28 +167,26 @@ RenderFarClip 1 128
RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 9
RenderMaxPartCount 1 4096
-RenderObjectBump 1 1
RenderLocalLights 1 1
-RenderReflectionDetail 1 0
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
RenderTransparentWater 1 1
RenderTreeLODFactor 1 0.5
RenderVolumeLODFactor 1 1.125
-WindLightUseAtmosShaders 1 1
-RenderDeferred 1 1
RenderDeferredSSAO 1 0
RenderUseAdvancedAtmospherics 1 0
RenderShadowDetail 1 0
WLSkyDetail 1 48
RenderFSAASamples 1 2
+RenderReflectionsEnabled 1 1
+RenderReflectionProbeDetail 1 0
+RenderScreenSpaceReflections 1 0
//
// High Graphics Settings (deferred + SSAO)
//
list High
RenderAnisotropic 1 1
-RenderAvatarCloth 1 0
RenderAvatarLODFactor 1 1.0
RenderAvatarMaxComplexity 1 300000
RenderAvatarPhysicsLODFactor 1 1.0
@@ -202,28 +194,26 @@ RenderFarClip 1 128
RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 9
RenderMaxPartCount 1 4096
-RenderObjectBump 1 1
RenderLocalLights 1 1
-RenderReflectionDetail 1 0
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
RenderTransparentWater 1 1
RenderTreeLODFactor 1 0.5
RenderVolumeLODFactor 1 1.125
-WindLightUseAtmosShaders 1 1
-RenderDeferred 1 1
RenderDeferredSSAO 1 1
RenderUseAdvancedAtmospherics 1 0
RenderShadowDetail 1 0
WLSkyDetail 1 48
RenderFSAASamples 1 2
+RenderReflectionsEnabled 1 1
+RenderReflectionProbeDetail 1 1
+RenderScreenSpaceReflections 1 0
//
// High Ultra Graphics Settings (deferred + SSAO + shadows)
//
list HighUltra
RenderAnisotropic 1 1
-RenderAvatarCloth 1 0
RenderAvatarLODFactor 1 1.0
RenderAvatarMaxComplexity 1 350000
RenderAvatarPhysicsLODFactor 1 1.0
@@ -231,28 +221,26 @@ RenderFarClip 1 128
RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 9
RenderMaxPartCount 1 4096
-RenderObjectBump 1 1
RenderLocalLights 1 1
-RenderReflectionDetail 1 0
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
RenderTransparentWater 1 1
RenderTreeLODFactor 1 0.5
RenderVolumeLODFactor 1 1.125
-WindLightUseAtmosShaders 1 1
-RenderDeferred 1 1
RenderDeferredSSAO 1 1
RenderShadowDetail 1 2
RenderUseAdvancedAtmospherics 1 0
WLSkyDetail 1 48
RenderFSAASamples 1 2
+RenderReflectionsEnabled 1 1
+RenderReflectionProbeDetail 1 1
+RenderScreenSpaceReflections 1 0
//
// Ultra graphics (REALLY PURTY!)
//
list Ultra
RenderAnisotropic 1 1
-RenderAvatarCloth 1 1
RenderAvatarLODFactor 1 1.0
RenderAvatarPhysicsLODFactor 1 1.0
RenderFarClip 1 256
@@ -260,8 +248,6 @@ RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 9
RenderLocalLights 1 1
RenderMaxPartCount 1 8192
-RenderObjectBump 1 1
-RenderReflectionDetail 1 4
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
RenderTransparentWater 1 1
@@ -269,18 +255,19 @@ RenderTreeLODFactor 1 1.0
RenderVolumeLODFactor 1 2.0
WindLightUseAtmosShaders 1 1
WLSkyDetail 1 128
-RenderDeferred 1 1
RenderDeferredSSAO 1 1
RenderUseAdvancedAtmospherics 1 0
RenderShadowDetail 1 2
RenderFSAASamples 1 2
+RenderReflectionsEnabled 1 1
+RenderReflectionProbeDetail 1 1
+RenderScreenSpaceReflections 1 1
//
// Class Unknown Hardware (unknown)
//
list Unknown
RenderShadowDetail 1 0
-RenderDeferred 1 0
RenderDeferredSSAO 1 0
RenderUseAdvancedAtmospherics 1 0
@@ -296,16 +283,11 @@ RenderCompressTextures 1 0
//
list safe
RenderAnisotropic 1 0
-RenderAvatarCloth 0 0
RenderAvatarMaxNonImpostors 1 16
RenderAvatarMaxComplexity 1 80000
-RenderObjectBump 0 0
RenderLocalLights 1 0
RenderMaxPartCount 1 1024
RenderTerrainDetail 1 0
-RenderReflectionDetail 0 0
-WindLightUseAtmosShaders 0 0
-RenderDeferred 0 0
RenderDeferredSSAO 0 0
RenderUseAdvancedAtmospherics 0 0
RenderShadowDetail 0 0
@@ -321,6 +303,7 @@ RenderAnisotropic 1 0
RenderLocalLights 1 0
RenderFSAASamples 1 0
-list OSX_10_6_8
-RenderDeferred 0 0
-
+list GL3
+RenderFSAASamples 0 0
+RenderReflectionProbeDetail 0 0
+RenderReflectionsEnabled 0 0
diff --git a/indra/newview/licenses-mac.txt b/indra/newview/licenses-mac.txt
index fba6a55da3..29b5a919bd 100644
--- a/indra/newview/licenses-mac.txt
+++ b/indra/newview/licenses-mac.txt
@@ -719,3 +719,55 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+
+
+============
+tinygltf
+============
+MIT License
+
+Copyright (c) 2017 Syoyo Fujita, Aurélien Chatelain and many contributors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+==============
+Vulkan GLTF
+==============
+MIT License
+
+Copyright (c) 2018 Sascha Willems
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
diff --git a/indra/newview/licenses-win32.txt b/indra/newview/licenses-win32.txt
index 837d92139d..eddc9a4475 100644
--- a/indra/newview/licenses-win32.txt
+++ b/indra/newview/licenses-win32.txt
@@ -796,3 +796,52 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+============
+tinygltf
+============
+MIT License
+
+Copyright (c) 2017 Syoyo Fujita, Aurélien Chatelain and many contributors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+==============
+Vulkan GLTF
+==============
+MIT License
+
+Copyright (c) 2018 Sascha Willems
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp
index 8d2e3905d1..5de52c1daf 100644
--- a/indra/newview/llagentcamera.cpp
+++ b/indra/newview/llagentcamera.cpp
@@ -1186,12 +1186,18 @@ void LLAgentCamera::updateLookAt(const S32 mouse_x, const S32 mouse_y)
static LLTrace::BlockTimerStatHandle FTM_UPDATE_CAMERA("Camera");
+extern BOOL gCubeSnapshot;
+
//-----------------------------------------------------------------------------
// updateCamera()
//-----------------------------------------------------------------------------
void LLAgentCamera::updateCamera()
{
LL_RECORD_BLOCK_TIME(FTM_UPDATE_CAMERA);
+ if (gCubeSnapshot)
+ {
+ return;
+ }
// - changed camera_skyward to the new global "mCameraUpVector"
mCameraUpVector = LLVector3::z_axis;
@@ -2037,6 +2043,13 @@ LLVector3d LLAgentCamera::getFocusOffsetInitial()
F32 LLAgentCamera::getCameraMaxZoomDistance()
{
+ // SL-14706 / SL-14885 TPV have relaxed camera constraints allowing you to mousewheeel zoom WAY out.
+ static LLCachedControl<bool> s_disable_camera_constraints(gSavedSettings, "DisableCameraConstraints", false);
+ if (s_disable_camera_constraints)
+ {
+ return (F32)INT_MAX;
+ }
+
// Ignore "DisableCameraConstraints", we don't want to be out of draw range when we focus onto objects or avatars
return llmin(MAX_CAMERA_DISTANCE_FROM_OBJECT,
mDrawDistance - 1, // convenience, don't hit draw limit when focusing on something
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index c9f5f62c41..061feba0a4 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -103,11 +103,11 @@
#include "lldiskcache.h"
#include "llvopartgroup.h"
#include "llweb.h"
-#include "llfloatertexturefetchdebugger.h"
#include "llspellcheck.h"
#include "llscenemonitor.h"
#include "llavatarrenderinfoaccountant.h"
#include "lllocalbitmaps.h"
+#include "llgltfmateriallist.h"
// Linden library includes
#include "llavatarnamecache.h"
@@ -343,9 +343,6 @@ LLFrameTimer gRestoreGLTimer;
BOOL gRestoreGL = FALSE;
bool gUseWireframe = FALSE;
-//use for remember deferred mode in wireframe switch
-bool gInitialDeferredModeForWireframe = FALSE;
-
LLMemoryInfo gSysMemory;
U64Bytes gMemoryAllocated(0); // updated in display_stats() in llviewerdisplay.cpp
@@ -536,9 +533,12 @@ static void settings_to_globals()
LLSurface::setTextureSize(gSavedSettings.getU32("RegionTextureSize"));
- LLRender::sGLCoreProfile = gSavedSettings.getBOOL("RenderGLContextCoreProfile");
+#if LL_DARWIN
+ LLRender::sGLCoreProfile = true;
+#else
+ LLRender::sGLCoreProfile = gSavedSettings.getBOOL("RenderGLContextCoreProfile");
+#endif
LLRender::sNsightDebugSupport = gSavedSettings.getBOOL("RenderNsightDebugSupport");
- LLVertexBuffer::sUseVAO = gSavedSettings.getBOOL("RenderUseVAO");
LLImageGL::sGlobalUseAnisotropic = gSavedSettings.getBOOL("RenderAnisotropic");
LLImageGL::sCompressTextures = gSavedSettings.getBOOL("RenderCompressTextures");
LLVOVolume::sLODFactor = llclamp(gSavedSettings.getF32("RenderVolumeLODFactor"), 0.01f, MAX_LOD_FACTOR);
@@ -572,11 +572,11 @@ static void settings_to_globals()
static void settings_modify()
{
LLPipeline::sRenderTransparentWater = gSavedSettings.getBOOL("RenderTransparentWater");
- LLPipeline::sRenderBump = gSavedSettings.getBOOL("RenderObjectBump");
- LLPipeline::sRenderDeferred = LLPipeline::sRenderBump && gSavedSettings.getBOOL("RenderDeferred");
+ LLPipeline::sRenderBump = TRUE; // FALSE is deprecated -- gSavedSettings.getBOOL("RenderObjectBump");
+ LLPipeline::sRenderDeferred = TRUE; // FALSE is deprecated -- LLPipeline::sRenderBump&& gSavedSettings.getBOOL("RenderDeferred");
LLRenderTarget::sUseFBO = LLPipeline::sRenderDeferred;
LLVOSurfacePatch::sLODFactor = gSavedSettings.getF32("RenderTerrainLODFactor");
- LLVOSurfacePatch::sLODFactor *= LLVOSurfacePatch::sLODFactor; // square lod factor to get exponential range of [1,4]
+ LLVOSurfacePatch::sLODFactor *= LLVOSurfacePatch::sLODFactor; //square lod factor to get exponential range of [1,4]
gDebugGL = gDebugGLSession || gDebugSession;
gDebugPipeline = gSavedSettings.getBOOL("RenderDebugPipeline");
}
@@ -1318,23 +1318,6 @@ void LLAppViewer::initMaxHeapSize()
LLMemory::initMaxHeapSizeGB(max_heap_size_gb);
}
-static LLTrace::BlockTimerStatHandle FTM_MESSAGES("System Messages");
-static LLTrace::BlockTimerStatHandle FTM_SLEEP1("Sleep1");
-static LLTrace::BlockTimerStatHandle FTM_SLEEP2("Sleep2");
-static LLTrace::BlockTimerStatHandle FTM_YIELD("Yield");
-
-static LLTrace::BlockTimerStatHandle FTM_TEXTURE_CACHE("Texture Cache");
-static LLTrace::BlockTimerStatHandle FTM_DECODE("Image Decode");
-static LLTrace::BlockTimerStatHandle FTM_FETCH("Image Fetch");
-
-static LLTrace::BlockTimerStatHandle FTM_LFS("LFS Thread");
-static LLTrace::BlockTimerStatHandle FTM_PAUSE_THREADS("Pause Threads");
-static LLTrace::BlockTimerStatHandle FTM_IDLE("Idle");
-static LLTrace::BlockTimerStatHandle FTM_PUMP("Pump");
-static LLTrace::BlockTimerStatHandle FTM_PUMP_SERVICE("Service");
-static LLTrace::BlockTimerStatHandle FTM_SERVICE_CALLBACK("Callback");
-static LLTrace::BlockTimerStatHandle FTM_AGENT_AUTOPILOT("Autopilot");
-static LLTrace::BlockTimerStatHandle FTM_AGENT_UPDATE("Update");
// externally visible timers
LLTrace::BlockTimerStatHandle FTM_FRAME("Frame");
@@ -1413,7 +1396,7 @@ bool LLAppViewer::doFrame()
if (gViewerWindow)
{
- LL_RECORD_BLOCK_TIME(FTM_MESSAGES);
+ LL_PROFILE_ZONE_NAMED_CATEGORY_APP("System Messages");
gViewerWindow->getWindow()->processMiscNativeEvents();
}
@@ -1424,7 +1407,7 @@ bool LLAppViewer::doFrame()
if (gViewerWindow)
{
- LL_RECORD_BLOCK_TIME(FTM_MESSAGES);
+ LL_PROFILE_ZONE_NAMED_CATEGORY_APP("System Messages");
if (!restoreErrorTrap())
{
LL_WARNS() << " Someone took over my signal/exception handler (post messagehandling)!" << LL_ENDL;
@@ -1487,7 +1470,7 @@ bool LLAppViewer::doFrame()
}
{
- LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df idle"); //LL_RECORD_BLOCK_TIME(FTM_IDLE);
+ LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df idle");
idle();
}
@@ -1513,22 +1496,23 @@ bool LLAppViewer::doFrame()
// Render scene.
// *TODO: Should we run display() even during gHeadlessClient? DK 2011-02-18
- if (!LLApp::isExiting() && !gHeadlessClient && gViewerWindow)
- {
- LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df Display" )
- pingMainloopTimeout("Main:Display");
- gGLActive = TRUE;
+ if (!LLApp::isExiting() && !gHeadlessClient && gViewerWindow)
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df Display");
+ pingMainloopTimeout("Main:Display");
+ gGLActive = TRUE;
- display();
+ display();
- {
- LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df Snapshot" )
- pingMainloopTimeout("Main:Snapshot");
- LLFloaterSnapshot::update(); // take snapshots
- LLFloaterSimpleOutfitSnapshot::update();
- gGLActive = FALSE;
- }
- }
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df Snapshot");
+ pingMainloopTimeout("Main:Snapshot");
+ gPipeline.mReflectionMapManager.update();
+ LLFloaterSnapshot::update(); // take snapshots
+ LLFloaterSimpleOutfitSnapshot::update();
+ gGLActive = FALSE;
+ }
+ }
}
{
@@ -1547,7 +1531,7 @@ bool LLAppViewer::doFrame()
static LLCachedControl<S32> yield_time(gSavedSettings, "YieldTime", -1);
if(yield_time >= 0)
{
- LL_RECORD_BLOCK_TIME(FTM_YIELD);
+ LL_PROFILE_ZONE_NAMED_CATEGORY_APP("Yield");
LL_PROFILE_ZONE_NUM( yield_time )
ms_sleep(yield_time);
}
@@ -1556,7 +1540,6 @@ bool LLAppViewer::doFrame()
{
S32 non_interactive_ms_sleep_time = 100;
LLAppViewer::getTextureCache()->pause();
- LLAppViewer::getImageDecodeThread()->pause();
ms_sleep(non_interactive_ms_sleep_time);
}
@@ -1576,7 +1559,6 @@ bool LLAppViewer::doFrame()
ms_sleep(milliseconds_to_sleep);
// also pause worker threads during this wait period
LLAppViewer::getTextureCache()->pause();
- LLAppViewer::getImageDecodeThread()->pause();
}
}
@@ -1602,7 +1584,7 @@ bool LLAppViewer::doFrame()
work_pending += updateTextureThreads(max_time);
{
- LL_RECORD_BLOCK_TIME(FTM_LFS);
+ LL_PROFILE_ZONE_NAMED_CATEGORY_APP("LFS Thread");
io_pending += LLLFSThread::updateClass(1);
}
@@ -1625,7 +1607,6 @@ bool LLAppViewer::doFrame()
{
LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df getTextureCache" )
LLAppViewer::getTextureCache()->pause();
- LLAppViewer::getImageDecodeThread()->pause();
LLAppViewer::getTextureFetch()->pause();
}
if(!total_io_pending) //pause file threads if nothing to process.
@@ -1634,21 +1615,9 @@ bool LLAppViewer::doFrame()
LLLFSThread::sLocal->pause();
}
- //texture fetching debugger
- if(LLTextureFetchDebugger::isEnabled())
- {
- LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df tex_fetch_debugger_instance" )
- LLFloaterTextureFetchDebugger* tex_fetch_debugger_instance =
- LLFloaterReg::findTypedInstance<LLFloaterTextureFetchDebugger>("tex_fetch_debugger");
- if(tex_fetch_debugger_instance)
- {
- tex_fetch_debugger_instance->idle() ;
- }
- }
-
{
LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df resumeMainloopTimeout" )
- resumeMainloopTimeout();
+ resumeMainloopTimeout();
}
pingMainloopTimeout("Main:End");
}
@@ -1684,15 +1653,15 @@ S32 LLAppViewer::updateTextureThreads(F32 max_time)
{
S32 work_pending = 0;
{
- LL_RECORD_BLOCK_TIME(FTM_TEXTURE_CACHE);
+ LL_PROFILE_ZONE_NAMED_CATEGORY_APP("Texture Cache");
work_pending += LLAppViewer::getTextureCache()->update(max_time); // unpauses the texture cache thread
}
{
- LL_RECORD_BLOCK_TIME(FTM_DECODE);
+ LL_PROFILE_ZONE_NAMED_CATEGORY_APP("Image Decode");
work_pending += LLAppViewer::getImageDecodeThread()->update(max_time); // unpauses the image thread
}
{
- LL_RECORD_BLOCK_TIME(FTM_FETCH);
+ LL_PROFILE_ZONE_NAMED_CATEGORY_APP("Image Fetch");
work_pending += LLAppViewer::getTextureFetch()->update(max_time); // unpauses the texture fetch thread
}
return work_pending;
@@ -1700,16 +1669,20 @@ S32 LLAppViewer::updateTextureThreads(F32 max_time)
void LLAppViewer::flushLFSIO()
{
- while (1)
- {
- S32 pending = LLLFSThread::updateClass(0);
- if (!pending)
- {
- break;
- }
- LL_INFOS() << "Waiting for pending IO to finish: " << pending << LL_ENDL;
- ms_sleep(100);
- }
+ S32 pending = LLLFSThread::updateClass(0);
+ if (pending > 0)
+ {
+ LL_INFOS() << "Waiting for pending IO to finish: " << pending << LL_ENDL;
+ while (1)
+ {
+ pending = LLLFSThread::updateClass(0);
+ if (!pending)
+ {
+ break;
+ }
+ ms_sleep(100);
+ }
+ }
}
bool LLAppViewer::cleanup()
@@ -1867,8 +1840,6 @@ bool LLAppViewer::cleanup()
LL_INFOS() << "Cache files removed" << LL_ENDL;
- // Wait for any pending LFS IO
- flushLFSIO();
LL_INFOS() << "Shutting down Views" << LL_ENDL;
// Destroy the UI
@@ -2068,13 +2039,13 @@ bool LLAppViewer::cleanup()
sTextureCache->shutdown();
sImageDecodeThread->shutdown();
sPurgeDiskCacheThread->shutdown();
- if (mGeneralThreadPool)
- {
- mGeneralThreadPool->close();
- }
+ if (mGeneralThreadPool)
+ {
+ mGeneralThreadPool->close();
+ }
sTextureFetch->shutDownTextureCacheThread() ;
- sTextureFetch->shutDownImageDecodeThread() ;
+ LLLFSThread::sLocal->shutdown();
LL_INFOS() << "Shutting down message system" << LL_ENDL;
end_messaging_system();
@@ -2088,8 +2059,13 @@ bool LLAppViewer::cleanup()
//MUST happen AFTER SUBSYSTEM_CLEANUP(LLCurl)
delete sTextureCache;
sTextureCache = NULL;
- delete sTextureFetch;
- sTextureFetch = NULL;
+ if (sTextureFetch)
+ {
+ sTextureFetch->shutdown();
+ sTextureFetch->waitOnPending();
+ delete sTextureFetch;
+ sTextureFetch = NULL;
+ }
delete sImageDecodeThread;
sImageDecodeThread = NULL;
delete mFastTimerLogThread;
@@ -2191,14 +2167,7 @@ void LLAppViewer::initGeneralThread()
return;
}
- LLSD poolSizes{ gSavedSettings.getLLSD("ThreadPoolSizes") };
- LLSD sizeSpec{ poolSizes["General"] };
- LLSD::Integer poolSize{ sizeSpec.isInteger() ? sizeSpec.asInteger() : 3 };
- LL_DEBUGS("ThreadPool") << "Instantiating General pool with "
- << poolSize << " threads" << LL_ENDL;
- // We don't want anyone, especially the main thread, to have to block
- // due to this ThreadPool being full.
- mGeneralThreadPool = new LL::ThreadPool("General", poolSize, 1024 * 1024);
+ mGeneralThreadPool = new LL::ThreadPool("General", 3);
mGeneralThreadPool->start();
}
@@ -2208,13 +2177,31 @@ bool LLAppViewer::initThreads()
LLImage::initClass(gSavedSettings.getBOOL("TextureNewByteRange"),gSavedSettings.getS32("TextureReverseByteRange"));
- LLLFSThread::initClass(enable_threads && false);
+ LLLFSThread::initClass(enable_threads && true); // TODO: fix crashes associated with this shutdo
+
+ //auto configure thread count
+ LLSD threadCounts = gSavedSettings.getLLSD("ThreadPoolSizes");
+
+ // get the number of concurrent threads that can run
+ S32 cores = std::thread::hardware_concurrency();
+
+ U32 max_cores = gSavedSettings.getU32("EmulateCoreCount");
+ if (max_cores != 0)
+ {
+ cores = llmin(cores, (S32) max_cores);
+ }
+
+ // The only configurable thread count right now is ImageDecode
+ // The viewer typically starts around 8 threads not including image decode,
+ // so try to leave at least one core free
+ S32 image_decode_count = llclamp(cores - 9, 1, 8);
+ threadCounts["ImageDecode"] = image_decode_count;
+ gSavedSettings.setLLSD("ThreadPoolSizes", threadCounts);
// Image decoding
LLAppViewer::sImageDecodeThread = new LLImageDecodeThread(enable_threads && true);
LLAppViewer::sTextureCache = new LLTextureCache(enable_threads && true);
LLAppViewer::sTextureFetch = new LLTextureFetch(LLAppViewer::getTextureCache(),
- sImageDecodeThread,
enable_threads && true,
app_metrics_qa_mode);
LLAppViewer::sPurgeDiskCacheThread = new LLPurgeDiskCacheThread();
@@ -3299,7 +3286,7 @@ LLSD LLAppViewer::getViewerInfo() const
info["LOD_FACTOR"] = gSavedSettings.getF32("RenderVolumeLODFactor");
info["RENDER_QUALITY"] = (F32)gSavedSettings.getU32("RenderQualityPerformance");
info["GPU_SHADERS"] = gSavedSettings.getBOOL("RenderDeferred") ? "Enabled" : "Disabled";
- info["TEXTURE_MEMORY"] = gSavedSettings.getS32("TextureMemory");
+ info["TEXTURE_MEMORY"] = gGLManager.mVRAM;
#if LL_DARWIN
info["HIDPI"] = gHiDPISupport;
@@ -4716,6 +4703,8 @@ void LLAppViewer::idle()
LLDirPickerThread::clearDead();
F32 dt_raw = idle_timer.getElapsedTimeAndResetF32();
+ LLGLTFMaterialList::flushUpdates();
+
// Service the WorkQueue we use for replies from worker threads.
// Use function statics for the timeslice setting so we only have to fetch
// and convert MainWorkTime once.
@@ -4762,10 +4751,6 @@ void LLAppViewer::idle()
//
// Special case idle if still starting up
//
- if (LLStartUp::getStartupState() >= STATE_WORLD_INIT)
- {
- update_texture_time();
- }
if (LLStartUp::getStartupState() < STATE_STARTED)
{
// Skip rest if idle startup returns false (essentially, no world yet)
@@ -4799,7 +4784,7 @@ void LLAppViewer::idle()
}
{
- LL_RECORD_BLOCK_TIME(FTM_AGENT_AUTOPILOT);
+ LL_PROFILE_ZONE_NAMED_CATEGORY_APP("Autopilot");
// Handle automatic walking towards points
gAgentPilot.updateTarget();
gAgent.autoPilot(&yaw);
@@ -4815,7 +4800,7 @@ void LLAppViewer::idle()
|| (agent_force_update_time > (1.0f / (F32) AGENT_FORCE_UPDATES_PER_SECOND));
if (force_update || (agent_update_time > (1.0f / (F32) AGENT_UPDATES_PER_SECOND)))
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; //LL_RECORD_BLOCK_TIME(FTM_AGENT_UPDATE);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
// Send avatar and camera info
mLastAgentControlFlags = gAgent.getControlFlags();
mLastAgentForceUpdate = force_update ? 0 : agent_force_update_time;
@@ -4866,7 +4851,7 @@ void LLAppViewer::idle()
if (!gDisconnected)
{
- LL_RECORD_BLOCK_TIME(FTM_NETWORK);
+ LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Network");
////////////////////////////////////////////////
//
diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h
index f28a90c703..6e35da1b10 100644
--- a/indra/newview/llappviewer.h
+++ b/indra/newview/llappviewer.h
@@ -49,6 +49,7 @@
#include "llsys.h" // for LLOSInfo
#include "lltimer.h"
#include "llappcorehttp.h"
+#include "threadpool_fwd.h"
#include <boost/signals2.hpp>
@@ -63,11 +64,6 @@ class LLViewerJoystick;
class LLPurgeDiskCacheThread;
class LLViewerRegion;
-namespace LL
-{
- class ThreadPool;
-}
-
extern LLTrace::BlockTimerStatHandle FTM_FRAME;
class LLAppViewer : public LLApp
@@ -392,7 +388,6 @@ extern BOOL gDisconnected;
extern LLFrameTimer gRestoreGLTimer;
extern BOOL gRestoreGL;
extern bool gUseWireframe;
-extern bool gInitialDeferredModeForWireframe;
extern LLMemoryInfo gSysMemory;
extern U64Bytes gMemoryAllocated;
diff --git a/indra/newview/llcompilequeue.cpp b/indra/newview/llcompilequeue.cpp
index 9031ea5b1b..eb2c156ca5 100644
--- a/indra/newview/llcompilequeue.cpp
+++ b/indra/newview/llcompilequeue.cpp
@@ -124,7 +124,7 @@ public:
LLQueuedScriptAssetUpload(LLUUID taskId, LLUUID itemId, LLUUID assetId, TargetType_t targetType,
bool isRunning, std::string scriptName, LLUUID queueId, LLUUID exerienceId, taskUploadFinish_f finish) :
LLScriptAssetUpload(taskId, itemId, targetType, isRunning,
- exerienceId, std::string(), finish),
+ exerienceId, std::string(), finish, nullptr),
mScriptName(scriptName),
mQueueId(queueId)
{
diff --git a/indra/newview/llcontrolavatar.cpp b/indra/newview/llcontrolavatar.cpp
index 4a87273372..d4d4f641cf 100644
--- a/indra/newview/llcontrolavatar.cpp
+++ b/indra/newview/llcontrolavatar.cpp
@@ -610,6 +610,7 @@ LLViewerObject* LLControlAvatar::lineSegmentIntersectRiggedAttachments(const LLV
S32 face,
BOOL pick_transparent,
BOOL pick_rigged,
+ BOOL pick_unselectable,
S32* face_hit,
LLVector4a* intersection,
LLVector2* tex_coord,
@@ -627,7 +628,7 @@ LLViewerObject* LLControlAvatar::lineSegmentIntersectRiggedAttachments(const LLV
{
LLVector4a local_end = end;
LLVector4a local_intersection;
- if (mRootVolp->lineSegmentIntersect(start, local_end, face, pick_transparent, pick_rigged, face_hit, &local_intersection, tex_coord, normal, tangent))
+ if (mRootVolp->lineSegmentIntersect(start, local_end, face, pick_transparent, pick_rigged, pick_unselectable, face_hit, &local_intersection, tex_coord, normal, tangent))
{
local_end = local_intersection;
if (intersection)
@@ -644,7 +645,7 @@ LLViewerObject* LLControlAvatar::lineSegmentIntersectRiggedAttachments(const LLV
for (std::vector<LLVOVolume*>::iterator vol_it = volumes.begin(); vol_it != volumes.end(); ++vol_it)
{
LLVOVolume *volp = *vol_it;
- if (mRootVolp != volp && volp->lineSegmentIntersect(start, local_end, face, pick_transparent, pick_rigged, face_hit, &local_intersection, tex_coord, normal, tangent))
+ if (mRootVolp != volp && volp->lineSegmentIntersect(start, local_end, face, pick_transparent, pick_rigged, pick_unselectable, face_hit, &local_intersection, tex_coord, normal, tangent))
{
local_end = local_intersection;
if (intersection)
diff --git a/indra/newview/llcontrolavatar.h b/indra/newview/llcontrolavatar.h
index 8e87299f3e..ea91d70e69 100644
--- a/indra/newview/llcontrolavatar.h
+++ b/indra/newview/llcontrolavatar.h
@@ -68,6 +68,7 @@ public:
S32 face = -1, // which face to check, -1 = ALL_SIDES
BOOL pick_transparent = FALSE,
BOOL pick_rigged = FALSE,
+ BOOL pick_unselectable = TRUE,
S32* face_hit = NULL, // which face was hit
LLVector4a* intersection = NULL, // return the intersection point
LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point
diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp
index 4a0c9d399f..7d869562ca 100644
--- a/indra/newview/lldrawable.cpp
+++ b/indra/newview/lldrawable.cpp
@@ -249,12 +249,9 @@ void LLDrawable::cleanupReferences()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWABLE;
-
std::for_each(mFaces.begin(), mFaces.end(), DeletePointer());
mFaces.clear();
- gObjectList.removeDrawable(this);
-
gPipeline.unlinkDrawable(this);
removeFromOctree();
@@ -705,7 +702,8 @@ F32 LLDrawable::updateXform(BOOL undamped)
((dist_vec_squared(old_pos, target_pos) > 0.f)
|| (1.f - dot(old_rot, target_rot)) > 0.f))
{ //fix for BUG-840, MAINT-2275, MAINT-1742, MAINT-2247
- gPipeline.markRebuild(this, LLDrawable::REBUILD_POSITION, TRUE);
+ mVObjp->shrinkWrap();
+ gPipeline.markRebuild(this, LLDrawable::REBUILD_POSITION, TRUE);
}
else if (!getVOVolume() && !isAvatar())
{
@@ -885,7 +883,7 @@ void LLDrawable::updateDistance(LLCamera& camera, bool force_update)
{
LLFace* facep = getFace(i);
if (facep &&
- (force_update || facep->getPoolType() == LLDrawPool::POOL_ALPHA))
+ (force_update || facep->isInAlphaPool()))
{
LLVector4a box;
box.setSub(facep->mExtents[1], facep->mExtents[0]);
@@ -1255,10 +1253,10 @@ LLSpatialPartition* LLDrawable::getSpatialPartition()
LLSpatialBridge::LLSpatialBridge(LLDrawable* root, BOOL render_by_group, U32 data_mask, LLViewerRegion* regionp) :
LLDrawable(root->getVObj(), true),
- LLSpatialPartition(data_mask, render_by_group, GL_STREAM_DRAW_ARB, regionp)
+ LLSpatialPartition(data_mask, render_by_group, regionp)
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWABLE
-
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWABLE;
+ mOcclusionEnabled = false;
mBridge = this;
mDrawable = root;
root->setSpatialBridge(this);
@@ -1761,7 +1759,7 @@ LLDrawable* LLDrawable::getRoot()
}
LLBridgePartition::LLBridgePartition(LLViewerRegion* regionp)
-: LLSpatialPartition(0, FALSE, 0, regionp)
+: LLSpatialPartition(0, false, regionp)
{
mDrawableType = LLPipeline::RENDER_TYPE_VOLUME;
mPartitionType = LLViewerRegion::PARTITION_BRIDGE;
diff --git a/indra/newview/lldrawable.h b/indra/newview/lldrawable.h
index 2a0f4c93ac..cdd8ae88bb 100644
--- a/indra/newview/lldrawable.h
+++ b/indra/newview/lldrawable.h
@@ -42,6 +42,7 @@
#include "llrect.h"
#include "llappviewer.h" // for gFrameTimeSeconds
#include "llvieweroctree.h"
+#include <unordered_set>
class LLCamera;
class LLDrawPool;
@@ -223,7 +224,8 @@ public:
friend class LLDrawPool;
friend class LLSpatialBridge;
- typedef std::set<LLPointer<LLDrawable> > drawable_set_t;
+ typedef std::unordered_set<LLPointer<LLDrawable> > drawable_set_t;
+ typedef std::set<LLPointer<LLDrawable> > ordered_drawable_set_t;
typedef std::vector<LLPointer<LLDrawable> > drawable_vector_t;
typedef std::list<LLPointer<LLDrawable> > drawable_list_t;
typedef std::queue<LLPointer<LLDrawable> > drawable_queue_t;
diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp
index a3837fe10c..a5990492b1 100644
--- a/indra/newview/lldrawpool.cpp
+++ b/indra/newview/lldrawpool.cpp
@@ -37,6 +37,7 @@
#include "lldrawpoolbump.h"
#include "lldrawpoolmaterials.h"
#include "lldrawpoolground.h"
+#include "lldrawpoolpbropaque.h"
#include "lldrawpoolsimple.h"
#include "lldrawpoolsky.h"
#include "lldrawpooltree.h"
@@ -85,9 +86,12 @@ LLDrawPool *LLDrawPool::createPool(const U32 type, LLViewerTexture *tex0)
case POOL_GLOW:
poolp = new LLDrawPoolGlow();
break;
- case POOL_ALPHA:
- poolp = new LLDrawPoolAlpha();
+ case POOL_ALPHA_PRE_WATER:
+ poolp = new LLDrawPoolAlpha(LLDrawPool::POOL_ALPHA_PRE_WATER);
break;
+ case POOL_ALPHA_POST_WATER:
+ poolp = new LLDrawPoolAlpha(LLDrawPool::POOL_ALPHA_POST_WATER);
+ break;
case POOL_AVATAR:
case POOL_CONTROL_AV:
poolp = new LLDrawPoolAvatar(type);
@@ -117,6 +121,9 @@ LLDrawPool *LLDrawPool::createPool(const U32 type, LLViewerTexture *tex0)
case POOL_WL_SKY:
poolp = new LLDrawPoolWLSky();
break;
+ case POOL_GLTF_PBR:
+ poolp = new LLDrawPoolGLTFPBR();
+ break;
default:
LL_ERRS() << "Unknown draw pool type!" << LL_ENDL;
return NULL;
@@ -207,15 +214,6 @@ void LLDrawPool::renderPostDeferred(S32 pass)
//virtual
void LLDrawPool::endRenderPass( S32 pass )
{
- /*for (U32 i = 0; i < gGLManager.mNumTextureImageUnits; i++)
- { //dummy cleanup of any currently bound textures
- if (gGL.getTexUnit(i)->getCurrType() != LLTexUnit::TT_NONE)
- {
- gGL.getTexUnit(i)->unbind(gGL.getTexUnit(i)->getCurrType());
- gGL.getTexUnit(i)->disable();
- }
- }*/
-
//make sure channel 0 is active channel
gGL.getTexUnit(0)->activate();
}
@@ -387,7 +385,7 @@ LLRenderPass::~LLRenderPass()
}
-void LLRenderPass::renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture)
+void LLRenderPass::renderGroup(LLSpatialGroup* group, U32 type, bool texture)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[type];
@@ -397,19 +395,18 @@ void LLRenderPass::renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL t
LLDrawInfo *pparams = *k;
if (pparams)
{
- pushBatch(*pparams, mask, texture);
+ pushBatch(*pparams, texture);
}
}
}
-void LLRenderPass::renderRiggedGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture)
+void LLRenderPass::renderRiggedGroup(LLSpatialGroup* group, U32 type, bool texture)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[type];
LLVOAvatar* lastAvatar = nullptr;
U64 lastMeshId = 0;
- mask |= LLVertexBuffer::MAP_WEIGHT4;
-
+
for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k)
{
LLDrawInfo* pparams = *k;
@@ -422,89 +419,179 @@ void LLRenderPass::renderRiggedGroup(LLSpatialGroup* group, U32 type, U32 mask,
lastMeshId = pparams->mSkinInfo->mHash;
}
- pushBatch(*pparams, mask, texture);
+ pushBatch(*pparams, texture);
}
}
}
-void LLRenderPass::pushBatches(U32 type, U32 mask, BOOL texture, BOOL batch_textures)
+void setup_texture_matrix(LLDrawInfo& params)
+{
+ if (params.mTextureMatrix)
+ { //special case implementation of texture animation here because of special handling of textures for PBR batches
+ gGL.getTexUnit(0)->activate();
+ gGL.matrixMode(LLRender::MM_TEXTURE);
+ gGL.loadMatrix((GLfloat*)params.mTextureMatrix->mMatrix);
+ gPipeline.mTextureMatrixOps++;
+ }
+}
+
+void teardown_texture_matrix(LLDrawInfo& params)
+{
+ if (params.mTextureMatrix)
+ {
+ gGL.matrixMode(LLRender::MM_TEXTURE0);
+ gGL.loadIdentity();
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
+ }
+}
+
+void LLRenderPass::pushGLTFBatches(U32 type)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
- for (LLCullResult::drawinfo_iterator i = gPipeline.beginRenderMap(type); i != gPipeline.endRenderMap(type); ++i)
- {
- LLDrawInfo* pparams = *i;
- if (pparams)
- {
- pushBatch(*pparams, mask, texture, batch_textures);
- }
+ auto* begin = gPipeline.beginRenderMap(type);
+ auto* end = gPipeline.endRenderMap(type);
+ for (LLCullResult::drawinfo_iterator i = begin; i != end; )
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_DRAWPOOL("pushGLTFBatch");
+ LLDrawInfo& params = **i;
+ LLCullResult::increment_iterator(i, end);
+
+ auto& mat = params.mGLTFMaterial;
+
+ mat->bind();
+
+ LLGLDisable cull_face(mat->mDoubleSided ? GL_CULL_FACE : 0);
+
+ setup_texture_matrix(params);
+
+ applyModelMatrix(params);
+
+ params.mVertexBuffer->setBuffer();
+ params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset);
+
+ teardown_texture_matrix(params);
+ }
+}
+
+void LLRenderPass::pushRiggedGLTFBatches(U32 type)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
+ LLVOAvatar* lastAvatar = nullptr;
+ U64 lastMeshId = 0;
+
+ auto* begin = gPipeline.beginRenderMap(type);
+ auto* end = gPipeline.endRenderMap(type);
+ for (LLCullResult::drawinfo_iterator i = begin; i != end; )
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_DRAWPOOL("pushRiggedGLTFBatch");
+ LLDrawInfo& params = **i;
+ LLCullResult::increment_iterator(i, end);
+
+ auto& mat = params.mGLTFMaterial;
+
+ mat->bind();
+
+ LLGLDisable cull_face(mat->mDoubleSided ? GL_CULL_FACE : 0);
+
+ setup_texture_matrix(params);
+
+ applyModelMatrix(params);
+
+ if (params.mAvatar.notNull() && (lastAvatar != params.mAvatar || lastMeshId != params.mSkinInfo->mHash))
+ {
+ uploadMatrixPalette(params);
+ lastAvatar = params.mAvatar;
+ lastMeshId = params.mSkinInfo->mHash;
+ }
+
+ params.mVertexBuffer->setBuffer();
+ params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset);
+
+ teardown_texture_matrix(params);
+ }
+}
+
+void LLRenderPass::pushBatches(U32 type, bool texture, bool batch_textures)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
+ auto* begin = gPipeline.beginRenderMap(type);
+ auto* end = gPipeline.endRenderMap(type);
+ for (LLCullResult::drawinfo_iterator i = begin; i != end; )
+ {
+ LLDrawInfo* pparams = *i;
+ LLCullResult::increment_iterator(i, end);
+
+ pushBatch(*pparams, texture, batch_textures);
}
}
-void LLRenderPass::pushRiggedBatches(U32 type, U32 mask, BOOL texture, BOOL batch_textures)
+void LLRenderPass::pushRiggedBatches(U32 type, bool texture, bool batch_textures)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
LLVOAvatar* lastAvatar = nullptr;
U64 lastMeshId = 0;
- mask |= LLVertexBuffer::MAP_WEIGHT4;
- for (LLCullResult::drawinfo_iterator i = gPipeline.beginRenderMap(type); i != gPipeline.endRenderMap(type); ++i)
+ auto* begin = gPipeline.beginRenderMap(type);
+ auto* end = gPipeline.endRenderMap(type);
+ for (LLCullResult::drawinfo_iterator i = begin; i != end; )
{
LLDrawInfo* pparams = *i;
- if (pparams)
- {
- if (pparams->mAvatar.notNull() && (lastAvatar != pparams->mAvatar || lastMeshId != pparams->mSkinInfo->mHash))
- {
- uploadMatrixPalette(*pparams);
- lastAvatar = pparams->mAvatar;
- lastMeshId = pparams->mSkinInfo->mHash;
- }
+ LLCullResult::increment_iterator(i, end);
- pushBatch(*pparams, mask, texture, batch_textures);
+ if (pparams->mAvatar.notNull() && (lastAvatar != pparams->mAvatar || lastMeshId != pparams->mSkinInfo->mHash))
+ {
+ uploadMatrixPalette(*pparams);
+ lastAvatar = pparams->mAvatar;
+ lastMeshId = pparams->mSkinInfo->mHash;
}
+
+ pushBatch(*pparams, texture, batch_textures);
}
}
-void LLRenderPass::pushMaskBatches(U32 type, U32 mask, BOOL texture, BOOL batch_textures)
+void LLRenderPass::pushMaskBatches(U32 type, bool texture, bool batch_textures)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
- for (LLCullResult::drawinfo_iterator i = gPipeline.beginRenderMap(type); i != gPipeline.endRenderMap(type); ++i)
+ auto* begin = gPipeline.beginRenderMap(type);
+ auto* end = gPipeline.endRenderMap(type);
+ for (LLCullResult::drawinfo_iterator i = begin; i != end; )
{
- LLDrawInfo* pparams = *i;
- if (pparams)
- {
- LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(pparams->mAlphaMaskCutoff);
- pushBatch(*pparams, mask, texture, batch_textures);
- }
+ LLDrawInfo* pparams = *i;
+ LLCullResult::increment_iterator(i, end);
+ LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(pparams->mAlphaMaskCutoff);
+ pushBatch(*pparams, texture, batch_textures);
}
}
-void LLRenderPass::pushRiggedMaskBatches(U32 type, U32 mask, BOOL texture, BOOL batch_textures)
+void LLRenderPass::pushRiggedMaskBatches(U32 type, bool texture, bool batch_textures)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
LLVOAvatar* lastAvatar = nullptr;
U64 lastMeshId = 0;
- for (LLCullResult::drawinfo_iterator i = gPipeline.beginRenderMap(type); i != gPipeline.endRenderMap(type); ++i)
+ auto* begin = gPipeline.beginRenderMap(type);
+ auto* end = gPipeline.endRenderMap(type);
+ for (LLCullResult::drawinfo_iterator i = begin; i != end; )
{
LLDrawInfo* pparams = *i;
- if (pparams)
- {
- if (LLGLSLShader::sCurBoundShaderPtr)
- {
- LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(pparams->mAlphaMaskCutoff);
- }
- else
- {
- gGL.flush();
- }
- if (lastAvatar != pparams->mAvatar || lastMeshId != pparams->mSkinInfo->mHash)
- {
- uploadMatrixPalette(*pparams);
- lastAvatar = pparams->mAvatar;
- lastMeshId = pparams->mSkinInfo->mHash;
- }
+ LLCullResult::increment_iterator(i, end);
- pushBatch(*pparams, mask | LLVertexBuffer::MAP_WEIGHT4, texture, batch_textures);
+ if (LLGLSLShader::sCurBoundShaderPtr)
+ {
+ LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(pparams->mAlphaMaskCutoff);
+ }
+ else
+ {
+ gGL.flush();
+ }
+
+ if (lastAvatar != pparams->mAvatar || lastMeshId != pparams->mSkinInfo->mHash)
+ {
+ uploadMatrixPalette(*pparams);
+ lastAvatar = pparams->mAvatar;
+ lastMeshId = pparams->mSkinInfo->mHash;
}
+
+ pushBatch(*pparams, texture, batch_textures);
}
}
@@ -523,7 +610,7 @@ void LLRenderPass::applyModelMatrix(const LLDrawInfo& params)
}
}
-void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures)
+void LLRenderPass::pushBatch(LLDrawInfo& params, bool texture, bool batch_textures)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
if (!params.mCount)
@@ -568,15 +655,13 @@ void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL ba
}
}
- if (params.mGroup)
- {
- params.mGroup->rebuildMesh();
- }
-
- LLGLEnableFunc stencil_test(GL_STENCIL_TEST, params.mSelected, &LLGLCommonFunc::selected_stencil_test);
+ //if (params.mGroup) // TOO LATE!
+ //{
+ // params.mGroup->rebuildMesh();
+ //}
- params.mVertexBuffer->setBufferFast(mask);
- params.mVertexBuffer->drawRangeFast(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
+ params.mVertexBuffer->setBuffer();
+ params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset);
if (tex_setup)
{
diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h
index fd1b022e5b..7050723116 100644
--- a/indra/newview/lldrawpool.h
+++ b/indra/newview/lldrawpool.h
@@ -48,25 +48,33 @@ public:
enum
{
// Correspond to LLPipeline render type
+ // Also controls render order, so passes that don't use alpha masking/blending should come before
+ // other passes to preserve hierarchical Z for occlusion queries. Occlusion queries happen just
+ // before grass, so grass should be the first alpha masked pool. Other ordering should be done
+ // based on fill rate and likelihood to occlude future passes (faster, large occluders first).
+ //
POOL_SIMPLE = 1,
POOL_GROUND,
POOL_FULLBRIGHT,
POOL_BUMP,
- POOL_MATERIALS,
- POOL_TERRAIN,
- POOL_SKY,
- POOL_WL_SKY,
+ POOL_TERRAIN,
+ POOL_MATERIALS,
+ POOL_GRASS,
+ POOL_GLTF_PBR,
POOL_TREE,
POOL_ALPHA_MASK,
POOL_FULLBRIGHT_ALPHA_MASK,
- POOL_GRASS,
+ POOL_SKY,
+ POOL_WL_SKY,
POOL_INVISIBLE, // see below *
POOL_AVATAR,
POOL_CONTROL_AV, // Animesh
- POOL_VOIDWATER,
- POOL_WATER,
POOL_GLOW,
- POOL_ALPHA,
+ POOL_ALPHA_PRE_WATER,
+ POOL_VOIDWATER,
+ POOL_WATER,
+ POOL_ALPHA_POST_WATER,
+ POOL_ALPHA, // note there is no actual "POOL_ALPHA" but pre-water and post-water pools consume POOL_ALPHA faces
NUM_POOL_TYPES,
// * invisiprims work by rendering to the depth buffer but not the color buffer, occluding anything rendered after them
// - and the LLDrawPool types enum controls what order things are rendered in
@@ -106,8 +114,8 @@ public:
virtual S32 getNumShadowPasses();
virtual void renderShadow(S32 pass = 0);
- virtual void render(S32 pass = 0) = 0;
- virtual void prerender() = 0;
+ virtual void render(S32 pass = 0) {};
+ virtual void prerender() {};
virtual U32 getVertexDataMask() = 0;
virtual BOOL verify() const { return TRUE; } // Verify that all data in the draw pool is correct!
virtual S32 getShaderLevel() const { return mShaderLevel; }
@@ -129,6 +137,7 @@ class LLRenderPass : public LLDrawPool
public:
// list of possible LLRenderPass types to assign a render batch to
// NOTE: "rigged" variant MUST be non-rigged variant + 1
+ // see LLVolumeGeometryManager::registerFace()
enum
{
PASS_SIMPLE = NUM_POOL_TYPES,
@@ -190,9 +199,148 @@ public:
PASS_FULLBRIGHT_ALPHA_MASK_RIGGED,
PASS_ALPHA_INVISIBLE,
PASS_ALPHA_INVISIBLE_RIGGED,
+ PASS_GLTF_PBR,
+ PASS_GLTF_PBR_RIGGED,
+ PASS_GLTF_PBR_ALPHA_MASK,
+ PASS_GLTF_PBR_ALPHA_MASK_RIGGED,
NUM_RENDER_TYPES,
};
+ #ifdef LL_PROFILER_ENABLE_RENDER_DOC
+ static inline const char* lookupPassName(U32 pass)
+ {
+ switch (pass)
+ {
+ case PASS_SIMPLE:
+ return "PASS_SIMPLE";
+ case PASS_SIMPLE_RIGGED:
+ return "PASS_SIMPLE_RIGGED";
+ case PASS_GRASS:
+ return "PASS_GRASS";
+ case PASS_FULLBRIGHT:
+ return "PASS_FULLBRIGHT";
+ case PASS_FULLBRIGHT_RIGGED:
+ return "PASS_FULLBRIGHT_RIGGED";
+ case PASS_INVISIBLE:
+ return "PASS_INVISIBLE";
+ case PASS_INVISIBLE_RIGGED:
+ return "PASS_INVISIBLE_RIGGED";
+ case PASS_INVISI_SHINY:
+ return "PASS_INVISI_SHINY";
+ case PASS_INVISI_SHINY_RIGGED:
+ return "PASS_INVISI_SHINY_RIGGED";
+ case PASS_FULLBRIGHT_SHINY:
+ return "PASS_FULLBRIGHT_SHINY";
+ case PASS_FULLBRIGHT_SHINY_RIGGED:
+ return "PASS_FULLBRIGHT_SHINY_RIGGED";
+ case PASS_SHINY:
+ return "PASS_SHINY";
+ case PASS_SHINY_RIGGED:
+ return "PASS_SHINY_RIGGED";
+ case PASS_BUMP:
+ return "PASS_BUMP";
+ case PASS_BUMP_RIGGED:
+ return "PASS_BUMP_RIGGED";
+ case PASS_POST_BUMP:
+ return "PASS_POST_BUMP";
+ case PASS_POST_BUMP_RIGGED:
+ return "PASS_POST_BUMP_RIGGED";
+ case PASS_MATERIAL:
+ return "PASS_MATERIAL";
+ case PASS_MATERIAL_RIGGED:
+ return "PASS_MATERIAL_RIGGED";
+ case PASS_MATERIAL_ALPHA:
+ return "PASS_MATERIAL_ALPHA";
+ case PASS_MATERIAL_ALPHA_RIGGED:
+ return "PASS_MATERIAL_ALPHA_RIGGED";
+ case PASS_MATERIAL_ALPHA_MASK:
+ return "PASS_MATERIAL_ALPHA_MASK";
+ case PASS_MATERIAL_ALPHA_MASK_RIGGED:
+ return "PASS_MATERIAL_ALPHA_MASK_RIGGED";
+ case PASS_MATERIAL_ALPHA_EMISSIVE:
+ return "PASS_MATERIAL_ALPHA_EMISSIVE";
+ case PASS_MATERIAL_ALPHA_EMISSIVE_RIGGED:
+ return "PASS_MATERIAL_ALPHA_EMISSIVE_RIGGED";
+ case PASS_SPECMAP:
+ return "PASS_SPECMAP";
+ case PASS_SPECMAP_RIGGED:
+ return "PASS_SPECMAP_RIGGED";
+ case PASS_SPECMAP_BLEND:
+ return "PASS_SPECMAP_BLEND";
+ case PASS_SPECMAP_BLEND_RIGGED:
+ return "PASS_SPECMAP_BLEND_RIGGED";
+ case PASS_SPECMAP_MASK:
+ return "PASS_SPECMAP_MASK";
+ case PASS_SPECMAP_MASK_RIGGED:
+ return "PASS_SPECMAP_MASK_RIGGED";
+ case PASS_SPECMAP_EMISSIVE:
+ return "PASS_SPECMAP_EMISSIVE";
+ case PASS_SPECMAP_EMISSIVE_RIGGED:
+ return "PASS_SPECMAP_EMISSIVE_RIGGED";
+ case PASS_NORMMAP:
+ return "PASS_NORMAMAP";
+ case PASS_NORMMAP_RIGGED:
+ return "PASS_NORMMAP_RIGGED";
+ case PASS_NORMMAP_BLEND:
+ return "PASS_NORMMAP_BLEND";
+ case PASS_NORMMAP_BLEND_RIGGED:
+ return "PASS_NORMMAP_BLEND_RIGGED";
+ case PASS_NORMMAP_MASK:
+ return "PASS_NORMMAP_MASK";
+ case PASS_NORMMAP_MASK_RIGGED:
+ return "PASS_NORMMAP_MASK_RIGGED";
+ case PASS_NORMMAP_EMISSIVE:
+ return "PASS_NORMMAP_EMISSIVE";
+ case PASS_NORMMAP_EMISSIVE_RIGGED:
+ return "PASS_NORMMAP_EMISSIVE_RIGGED";
+ case PASS_NORMSPEC:
+ return "PASS_NORMSPEC";
+ case PASS_NORMSPEC_RIGGED:
+ return "PASS_NORMSPEC_RIGGED";
+ case PASS_NORMSPEC_BLEND:
+ return "PASS_NORMSPEC_BLEND";
+ case PASS_NORMSPEC_BLEND_RIGGED:
+ return "PASS_NORMSPEC_BLEND_RIGGED";
+ case PASS_NORMSPEC_MASK:
+ return "PASS_NORMSPEC_MASK";
+ case PASS_NORMSPEC_MASK_RIGGED:
+ return "PASS_NORMSPEC_MASK_RIGGED";
+ case PASS_NORMSPEC_EMISSIVE:
+ return "PASS_NORMSPEC_EMISSIVE";
+ case PASS_NORMSPEC_EMISSIVE_RIGGED:
+ return "PASS_NORMSPEC_EMISSIVE_RIGGED";
+ case PASS_GLOW:
+ return "PASS_GLOW";
+ case PASS_GLOW_RIGGED:
+ return "PASS_GLOW_RIGGED";
+ case PASS_ALPHA:
+ return "PASS_ALPHA";
+ case PASS_ALPHA_RIGGED:
+ return "PASS_ALPHA_RIGGED";
+ case PASS_ALPHA_MASK:
+ return "PASS_ALPHA_MASK";
+ case PASS_ALPHA_MASK_RIGGED:
+ return "PASS_ALPHA_MASK_RIGGED";
+ case PASS_FULLBRIGHT_ALPHA_MASK:
+ return "PASS_FULLBRIGHT_ALPHA_MASK";
+ case PASS_FULLBRIGHT_ALPHA_MASK_RIGGED:
+ return "PASS_FULLBRIGHT_ALPHA_MASK_RIGGED";
+ case PASS_ALPHA_INVISIBLE:
+ return "PASS_ALPHA_INVISIBLE";
+ case PASS_ALPHA_INVISIBLE_RIGGED:
+ return "PASS_ALPHA_INVISIBLE_RIGGED";
+ case PASS_GLTF_PBR:
+ return "PASS_GLTF_PBR";
+ case PASS_GLTF_PBR_RIGGED:
+ return "PASS_GLTF_PBR_RIGGED";
+ default:
+ return "Unknown pass";
+ }
+ }
+ #else
+ static inline const char* lookupPass(U32 pass) { return ""; }
+ #endif
+
LLRenderPass(const U32 type);
virtual ~LLRenderPass();
/*virtual*/ LLViewerTexture* getDebugTexture() { return NULL; }
@@ -201,15 +349,17 @@ public:
void resetDrawOrders() { }
static void applyModelMatrix(const LLDrawInfo& params);
- virtual void pushBatches(U32 type, U32 mask, BOOL texture = TRUE, BOOL batch_textures = FALSE);
- virtual void pushRiggedBatches(U32 type, U32 mask, BOOL texture = TRUE, BOOL batch_textures = FALSE);
- virtual void pushMaskBatches(U32 type, U32 mask, BOOL texture = TRUE, BOOL batch_textures = FALSE);
- virtual void pushRiggedMaskBatches(U32 type, U32 mask, BOOL texture = TRUE, BOOL batch_textures = FALSE);
- virtual void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures = FALSE);
+ virtual void pushBatches(U32 type, bool texture = true, bool batch_textures = false);
+ virtual void pushRiggedBatches(U32 type, bool texture = true, bool batch_textures = false);
+ void pushGLTFBatches(U32 type);
+ void pushRiggedGLTFBatches(U32 type);
+ virtual void pushMaskBatches(U32 type, bool texture = true, bool batch_textures = false);
+ virtual void pushRiggedMaskBatches(U32 type, bool texture = true, bool batch_textures = false);
+ virtual void pushBatch(LLDrawInfo& params, bool texture, bool batch_textures = false);
static bool uploadMatrixPalette(LLDrawInfo& params);
static bool uploadMatrixPalette(LLVOAvatar* avatar, LLMeshSkinInfo* skinInfo);
- virtual void renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture = TRUE);
- virtual void renderRiggedGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture = TRUE);
+ virtual void renderGroup(LLSpatialGroup* group, U32 type, bool texture = true);
+ virtual void renderRiggedGroup(LLSpatialGroup* group, U32 type, bool texture = true);
};
class LLFacePool : public LLDrawPool
diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp
index 6c1abb24c9..4c8d32fad2 100644
--- a/indra/newview/lldrawpoolalpha.cpp
+++ b/indra/newview/lldrawpoolalpha.cpp
@@ -50,10 +50,14 @@
#include "llglcommonfunc.h"
#include "llvoavatar.h"
+#include "llenvironment.h"
+
BOOL LLDrawPoolAlpha::sShowDebugAlpha = FALSE;
#define current_shader (LLGLSLShader::sCurBoundShaderPtr)
+LLVector4 LLDrawPoolAlpha::sWaterPlane;
+
static BOOL deferred_render = FALSE;
// minimum alpha before discarding a fragment
@@ -90,11 +94,13 @@ S32 LLDrawPoolAlpha::getNumPostDeferredPasses()
}
// set some common parameters on the given shader to prepare for alpha rendering
-static void prepare_alpha_shader(LLGLSLShader* shader, bool textureGamma, bool deferredEnvironment)
+static void prepare_alpha_shader(LLGLSLShader* shader, bool textureGamma, bool deferredEnvironment, F32 water_sign)
{
static LLCachedControl<F32> displayGamma(gSavedSettings, "RenderDeferredDisplayGamma");
F32 gamma = displayGamma;
+ static LLStaticHashedString waterSign("waterSign");
+
// Does this deferred shader need environment uniforms set such as sun_dir, etc. ?
// NOTE: We don't actually need a gbuffer since we are doing forward rendering (for transparency) post deferred rendering
// TODO: bindDeferredShader() probably should have the updating of the environment uniforms factored out into updateShaderEnvironmentUniforms()
@@ -110,6 +116,18 @@ static void prepare_alpha_shader(LLGLSLShader* shader, bool textureGamma, bool d
shader->uniform1i(LLShaderMgr::NO_ATMO, (LLPipeline::sRenderingHUDs) ? 1 : 0);
shader->uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f / 2.2f));
+ if (LLPipeline::sRenderingHUDs)
+ { // for HUD attachments, only the pre-water pass is executed and we never want to clip anything
+ LLVector4 near_clip(0, 0, -1, 0);
+ shader->uniform1f(waterSign, 1.f);
+ shader->uniform4fv(LLShaderMgr::WATER_WATERPLANE, 1, near_clip.mV);
+ }
+ else
+ {
+ shader->uniform1f(waterSign, water_sign);
+ shader->uniform4fv(LLShaderMgr::WATER_WATERPLANE, 1, LLDrawPoolAlpha::sWaterPlane.mV);
+ }
+
if (LLPipeline::sImpostorRender)
{
shader->setMinimumAlpha(MINIMUM_IMPOSTOR_ALPHA);
@@ -126,33 +144,55 @@ static void prepare_alpha_shader(LLGLSLShader* shader, bool textureGamma, bool d
//also prepare rigged variant
if (shader->mRiggedVariant && shader->mRiggedVariant != shader)
{
- prepare_alpha_shader(shader->mRiggedVariant, textureGamma, deferredEnvironment);
+ prepare_alpha_shader(shader->mRiggedVariant, textureGamma, deferredEnvironment, water_sign);
}
}
+extern BOOL gCubeSnapshot;
+
void LLDrawPoolAlpha::renderPostDeferred(S32 pass)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
+
+ if ((!LLPipeline::sRenderTransparentWater || gCubeSnapshot) && getType() == LLDrawPool::POOL_ALPHA_PRE_WATER)
+ { // don't render alpha objects on the other side of the water plane if water is opaque
+ return;
+ }
deferred_render = TRUE;
+ F32 water_sign = 1.f;
+
+ if (getType() == LLDrawPool::POOL_ALPHA_PRE_WATER)
+ {
+ water_sign = -1.f;
+ }
+
+ if (LLPipeline::sUnderWaterRender)
+ {
+ water_sign *= -1.f;
+ }
+
// prepare shaders
emissive_shader = (LLPipeline::sRenderDeferred) ? &gDeferredEmissiveProgram :
(LLPipeline::sUnderWaterRender) ? &gObjectEmissiveWaterProgram : &gObjectEmissiveProgram;
- prepare_alpha_shader(emissive_shader, true, false);
+ prepare_alpha_shader(emissive_shader, true, false, water_sign);
fullbright_shader = (LLPipeline::sImpostorRender) ? &gDeferredFullbrightAlphaMaskProgram :
- (LLPipeline::sUnderWaterRender) ? &gDeferredFullbrightWaterProgram : &gDeferredFullbrightAlphaMaskProgram;
- prepare_alpha_shader(fullbright_shader, true, false);
+ (LLPipeline::sUnderWaterRender) ? &gDeferredFullbrightWaterAlphaProgram : &gDeferredFullbrightAlphaMaskAlphaProgram;
+ prepare_alpha_shader(fullbright_shader, true, true, water_sign);
simple_shader = (LLPipeline::sImpostorRender) ? &gDeferredAlphaImpostorProgram :
(LLPipeline::sUnderWaterRender) ? &gDeferredAlphaWaterProgram : &gDeferredAlphaProgram;
- prepare_alpha_shader(simple_shader, false, true); //prime simple shader (loads shadow relevant uniforms)
+ prepare_alpha_shader(simple_shader, false, true, water_sign); //prime simple shader (loads shadow relevant uniforms)
- for (int i = 0; i < LLMaterial::SHADER_COUNT; ++i)
+ LLGLSLShader* materialShader = LLPipeline::sUnderWaterRender ? gDeferredMaterialWaterProgram : gDeferredMaterialProgram;
+ for (int i = 0; i < LLMaterial::SHADER_COUNT*2; ++i)
{
- prepare_alpha_shader(LLPipeline::sUnderWaterRender ? &gDeferredMaterialWaterProgram[i] : &gDeferredMaterialProgram[i], false, false); // note: bindDeferredShader will get called during render loop for materials
+ prepare_alpha_shader(&materialShader[i], false, true, water_sign);
}
+ prepare_alpha_shader(&gDeferredPBRAlphaProgram, false, true, water_sign);
+
// first pass, render rigged objects only and render to depth buffer
forwardRender(true);
@@ -160,13 +200,9 @@ void LLDrawPoolAlpha::renderPostDeferred(S32 pass)
forwardRender();
// final pass, render to depth for depth of field effects
- if (!LLPipeline::sImpostorRender && gSavedSettings.getBOOL("RenderDepthOfField"))
+ if (!LLPipeline::sImpostorRender && gSavedSettings.getBOOL("RenderDepthOfField") && !gCubeSnapshot)
{
//update depth buffer sampler
- gPipeline.mScreen.flush();
- gPipeline.mDeferredDepth.copyContents(gPipeline.mDeferredScreen, 0, 0, gPipeline.mDeferredScreen.getWidth(), gPipeline.mDeferredScreen.getHeight(),
- 0, 0, gPipeline.mDeferredDepth.getWidth(), gPipeline.mDeferredDepth.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST);
- gPipeline.mDeferredDepth.bindTarget();
simple_shader = fullbright_shader = &gObjectFullbrightAlphaMaskProgram;
simple_shader->bind();
@@ -180,8 +216,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.mDeferredDepth.flush();
- gPipeline.mScreen.bindTarget();
gGL.setColorMask(true, false);
}
@@ -280,42 +314,44 @@ void LLDrawPoolAlpha::renderDebugAlpha()
{
gHighlightProgram.bind();
gGL.diffuseColor4f(1, 0, 0, 1);
- LLViewerFetchedTexture::sSmokeImagep->addTextureStats(1024.f * 1024.f);
- gGL.getTexUnit(0)->bindFast(LLViewerFetchedTexture::sSmokeImagep);
+ gGL.getTexUnit(0)->bindFast(LLViewerFetchedTexture::getSmokeImage());
+
+ U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0;
- renderAlphaHighlight(LLVertexBuffer::MAP_VERTEX |
- LLVertexBuffer::MAP_TEXCOORD0);
+ renderAlphaHighlight(mask);
- pushBatches(LLRenderPass::PASS_ALPHA_MASK, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE);
- pushBatches(LLRenderPass::PASS_ALPHA_INVISIBLE, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE);
+ pushBatches(LLRenderPass::PASS_ALPHA_MASK, mask, FALSE);
+ pushBatches(LLRenderPass::PASS_ALPHA_INVISIBLE, mask, FALSE);
// Material alpha mask
gGL.diffuseColor4f(0, 0, 1, 1);
- pushBatches(LLRenderPass::PASS_MATERIAL_ALPHA_MASK, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE);
- pushBatches(LLRenderPass::PASS_NORMMAP_MASK, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE);
- pushBatches(LLRenderPass::PASS_SPECMAP_MASK, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE);
- pushBatches(LLRenderPass::PASS_NORMSPEC_MASK, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE);
- pushBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE);
+ pushBatches(LLRenderPass::PASS_MATERIAL_ALPHA_MASK, mask, FALSE);
+ pushBatches(LLRenderPass::PASS_NORMMAP_MASK, mask, FALSE);
+ pushBatches(LLRenderPass::PASS_SPECMAP_MASK, mask, FALSE);
+ pushBatches(LLRenderPass::PASS_NORMSPEC_MASK, mask, FALSE);
+ pushBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, mask, FALSE);
+ pushBatches(LLRenderPass::PASS_GLTF_PBR_ALPHA_MASK, mask, FALSE);
gGL.diffuseColor4f(0, 1, 0, 1);
- pushBatches(LLRenderPass::PASS_INVISIBLE, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE);
+ pushBatches(LLRenderPass::PASS_INVISIBLE, mask, FALSE);
gHighlightProgram.mRiggedVariant->bind();
gGL.diffuseColor4f(1, 0, 0, 1);
- pushRiggedBatches(LLRenderPass::PASS_ALPHA_MASK_RIGGED, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE);
- pushRiggedBatches(LLRenderPass::PASS_ALPHA_INVISIBLE_RIGGED, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE);
+ pushRiggedBatches(LLRenderPass::PASS_ALPHA_MASK_RIGGED, mask, FALSE);
+ pushRiggedBatches(LLRenderPass::PASS_ALPHA_INVISIBLE_RIGGED, mask, FALSE);
// Material alpha mask
gGL.diffuseColor4f(0, 0, 1, 1);
- pushRiggedBatches(LLRenderPass::PASS_MATERIAL_ALPHA_MASK_RIGGED, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE);
- pushRiggedBatches(LLRenderPass::PASS_NORMMAP_MASK_RIGGED, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE);
- pushRiggedBatches(LLRenderPass::PASS_SPECMAP_MASK_RIGGED, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE);
- pushRiggedBatches(LLRenderPass::PASS_NORMSPEC_MASK_RIGGED, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE);
- pushRiggedBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK_RIGGED, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE);
+ pushRiggedBatches(LLRenderPass::PASS_MATERIAL_ALPHA_MASK_RIGGED, mask, FALSE);
+ pushRiggedBatches(LLRenderPass::PASS_NORMMAP_MASK_RIGGED, mask, FALSE);
+ pushRiggedBatches(LLRenderPass::PASS_SPECMAP_MASK_RIGGED, mask, FALSE);
+ pushRiggedBatches(LLRenderPass::PASS_NORMSPEC_MASK_RIGGED, mask, FALSE);
+ pushRiggedBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK_RIGGED, mask, FALSE);
+ pushRiggedBatches(LLRenderPass::PASS_GLTF_PBR_ALPHA_MASK_RIGGED, mask, FALSE);
gGL.diffuseColor4f(0, 1, 0, 1);
- pushRiggedBatches(LLRenderPass::PASS_INVISIBLE_RIGGED, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE);
+ pushRiggedBatches(LLRenderPass::PASS_INVISIBLE_RIGGED, mask, FALSE);
LLGLSLShader::sCurBoundShaderPtr->unbind();
}
}
@@ -342,11 +378,6 @@ void LLDrawPoolAlpha::renderAlphaHighlight(U32 mask)
{
LLDrawInfo& params = **k;
- if (params.mParticle)
- {
- continue;
- }
-
bool rigged = (params.mAvatar != nullptr);
gHighlightProgram.bind(rigged);
gGL.diffuseColor4f(1, 0, 0, 1);
@@ -366,12 +397,8 @@ void LLDrawPoolAlpha::renderAlphaHighlight(U32 mask)
}
LLRenderPass::applyModelMatrix(params);
- if (params.mGroup)
- {
- params.mGroup->rebuildMesh();
- }
- params.mVertexBuffer->setBufferFast(rigged ? mask | LLVertexBuffer::MAP_WEIGHT4 : mask);
- params.mVertexBuffer->drawRangeFast(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
+ params.mVertexBuffer->setBuffer();
+ params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset);
}
}
}
@@ -398,71 +425,83 @@ inline bool IsEmissive(LLDrawInfo& params)
inline void Draw(LLDrawInfo* draw, U32 mask)
{
- draw->mVertexBuffer->setBufferFast(mask);
+ draw->mVertexBuffer->setBuffer();
LLRenderPass::applyModelMatrix(*draw);
- draw->mVertexBuffer->drawRangeFast(draw->mDrawMode, draw->mStart, draw->mEnd, draw->mCount, draw->mOffset);
+ draw->mVertexBuffer->drawRange(LLRender::TRIANGLES, draw->mStart, draw->mEnd, draw->mCount, draw->mOffset);
}
bool LLDrawPoolAlpha::TexSetup(LLDrawInfo* draw, bool use_material)
{
bool tex_setup = false;
- if (deferred_render && use_material && current_shader)
+ if (draw->mGLTFMaterial)
{
- if (draw->mNormalMap)
- {
- draw->mNormalMap->addTextureStats(draw->mVSize);
- current_shader->bindTexture(LLShaderMgr::BUMP_MAP, draw->mNormalMap);
- }
-
- if (draw->mSpecularMap)
- {
- draw->mSpecularMap->addTextureStats(draw->mVSize);
- current_shader->bindTexture(LLShaderMgr::SPECULAR_MAP, draw->mSpecularMap);
- }
+ if (draw->mTextureMatrix)
+ {
+ tex_setup = true;
+ gGL.getTexUnit(0)->activate();
+ gGL.matrixMode(LLRender::MM_TEXTURE);
+ gGL.loadMatrix((GLfloat*)draw->mTextureMatrix->mMatrix);
+ gPipeline.mTextureMatrixOps++;
+ }
}
- else if (current_shader == simple_shader || current_shader == simple_shader->mRiggedVariant)
+ else
{
- current_shader->bindTexture(LLShaderMgr::BUMP_MAP, LLViewerFetchedTexture::sFlatNormalImagep);
- current_shader->bindTexture(LLShaderMgr::SPECULAR_MAP, LLViewerFetchedTexture::sWhiteImagep);
- }
- if (draw->mTextureList.size() > 1)
- {
- for (U32 i = 0; i < draw->mTextureList.size(); ++i)
- {
- if (draw->mTextureList[i].notNull())
- {
- gGL.getTexUnit(i)->bindFast(draw->mTextureList[i]);
- }
- }
- }
- else
- { //not batching textures or batch has only 1 texture -- might need a texture matrix
- if (draw->mTexture.notNull())
- {
- if (use_material)
- {
- current_shader->bindTexture(LLShaderMgr::DIFFUSE_MAP, draw->mTexture);
- }
- else
- {
- gGL.getTexUnit(0)->bindFast(draw->mTexture);
- }
+ if (deferred_render && use_material && current_shader)
+ {
+ if (draw->mNormalMap)
+ {
+ current_shader->bindTexture(LLShaderMgr::BUMP_MAP, draw->mNormalMap);
+ }
- if (draw->mTextureMatrix)
- {
- tex_setup = true;
- gGL.getTexUnit(0)->activate();
- gGL.matrixMode(LLRender::MM_TEXTURE);
- gGL.loadMatrix((GLfloat*) draw->mTextureMatrix->mMatrix);
- gPipeline.mTextureMatrixOps++;
- }
- }
- else
- {
- gGL.getTexUnit(0)->unbindFast(LLTexUnit::TT_TEXTURE);
- }
- }
+ if (draw->mSpecularMap)
+ {
+ current_shader->bindTexture(LLShaderMgr::SPECULAR_MAP, draw->mSpecularMap);
+ }
+ }
+ else if (current_shader == simple_shader || current_shader == simple_shader->mRiggedVariant)
+ {
+ current_shader->bindTexture(LLShaderMgr::BUMP_MAP, LLViewerFetchedTexture::sFlatNormalImagep);
+ current_shader->bindTexture(LLShaderMgr::SPECULAR_MAP, LLViewerFetchedTexture::sWhiteImagep);
+ }
+ if (draw->mTextureList.size() > 1)
+ {
+ for (U32 i = 0; i < draw->mTextureList.size(); ++i)
+ {
+ if (draw->mTextureList[i].notNull())
+ {
+ gGL.getTexUnit(i)->bindFast(draw->mTextureList[i]);
+ }
+ }
+ }
+ else
+ { //not batching textures or batch has only 1 texture -- might need a texture matrix
+ if (draw->mTexture.notNull())
+ {
+ if (use_material)
+ {
+ current_shader->bindTexture(LLShaderMgr::DIFFUSE_MAP, draw->mTexture);
+ }
+ else
+ {
+ gGL.getTexUnit(0)->bindFast(draw->mTexture);
+ }
+
+ if (draw->mTextureMatrix)
+ {
+ tex_setup = true;
+ gGL.getTexUnit(0)->activate();
+ gGL.matrixMode(LLRender::MM_TEXTURE);
+ gGL.loadMatrix((GLfloat*)draw->mTextureMatrix->mMatrix);
+ gPipeline.mTextureMatrixOps++;
+ }
+ }
+ else
+ {
+ gGL.getTexUnit(0)->unbindFast(LLTexUnit::TT_TEXTURE);
+ }
+ }
+ }
return tex_setup;
}
@@ -481,8 +520,8 @@ void LLDrawPoolAlpha::RestoreTexSetup(bool tex_setup)
void LLDrawPoolAlpha::drawEmissive(U32 mask, LLDrawInfo* draw)
{
LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, 1.f);
- draw->mVertexBuffer->setBufferFast((mask & ~LLVertexBuffer::MAP_COLOR) | LLVertexBuffer::MAP_EMISSIVE);
- draw->mVertexBuffer->drawRangeFast(draw->mDrawMode, draw->mStart, draw->mEnd, draw->mCount, draw->mOffset);
+ draw->mVertexBuffer->setBuffer();
+ draw->mVertexBuffer->drawRange(LLRender::TRIANGLES, draw->mStart, draw->mEnd, draw->mCount, draw->mOffset);
}
@@ -551,6 +590,16 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only, bool rigged)
begin = gPipeline.beginAlphaGroups();
end = gPipeline.endAlphaGroups();
}
+
+ LLEnvironment& env = LLEnvironment::instance();
+ F32 water_height = env.getWaterHeight();
+
+ bool above_water = getType() == LLDrawPool::POOL_ALPHA_POST_WATER;
+ if (LLPipeline::sUnderWaterRender)
+ {
+ above_water = !above_water;
+ }
+
for (LLCullResult::sg_iterator i = begin; i != end; ++i)
{
@@ -562,6 +611,28 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only, bool rigged)
if (group->getSpatialPartition()->mRenderByGroup &&
!group->isDead())
{
+
+ LLSpatialBridge* bridge = group->getSpatialPartition()->asBridge();
+ const LLVector4a* ext = bridge ? bridge->getSpatialExtents() : group->getExtents();
+
+ if (!LLPipeline::sRenderingHUDs) // ignore above/below water for HUD render
+ {
+ if (above_water)
+ { // reject any spatial groups that have no part above water
+ if (ext[1].getF32ptr()[2] < water_height)
+ {
+ continue;
+ }
+ }
+ else
+ { // reject any spatial groups that he no part below water
+ if (ext[0].getF32ptr()[2] > water_height)
+ {
+ continue;
+ }
+ }
+ }
+
static std::vector<LLDrawInfo*> emissives;
static std::vector<LLDrawInfo*> rigged_emissives;
emissives.resize(0);
@@ -585,126 +656,120 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only, bool rigged)
continue;
}
- LL_PROFILE_ZONE_NAMED_CATEGORY_DRAWPOOL("ra - push batch")
+ LL_PROFILE_ZONE_NAMED_CATEGORY_DRAWPOOL("ra - push batch");
- U32 have_mask = params.mVertexBuffer->getTypeMask() & mask;
- if (have_mask != mask)
- { //FIXME!
- LL_WARNS_ONCE() << "Missing required components, expected mask: " << mask
- << " present: " << have_mask
- << ". Skipping render batch." << LL_ENDL;
- continue;
- }
+ LLRenderPass::applyModelMatrix(params);
- if(depth_only)
- {
- // when updating depth buffer, discard faces that are more than 90% transparent
- LLFace* face = params.mFace;
- if(face)
- {
- const LLTextureEntry* tep = face->getTextureEntry();
- if(tep)
- { // don't render faces that are more than 90% transparent
- if(tep->getColor().mV[3] < MINIMUM_IMPOSTOR_ALPHA)
- continue;
- }
- }
- }
+ LLMaterial* mat = NULL;
+ LLGLTFMaterial *gltf_mat = params.mGLTFMaterial;
+
+ LLGLDisable cull_face(gltf_mat && gltf_mat->mDoubleSided ? GL_CULL_FACE : 0);
+
+ if (gltf_mat && gltf_mat->mAlphaMode == LLGLTFMaterial::ALPHA_MODE_BLEND)
+ {
+ target_shader = &gDeferredPBRAlphaProgram;
+ if (params.mAvatar != nullptr)
+ {
+ target_shader = target_shader->mRiggedVariant;
+ }
- LLRenderPass::applyModelMatrix(params);
+ // shader must be bound before LLGLTFMaterial::bind
+ if (current_shader != target_shader)
+ {
+ gPipeline.bindDeferredShaderFast(*target_shader);
+ }
- LLMaterial* mat = NULL;
+ params.mGLTFMaterial->bind();
+ }
+ else
+ {
+ if (deferred_render)
+ {
+ mat = params.mMaterial;
+ }
- if (deferred_render)
- {
- mat = params.mMaterial;
- }
-
- if (params.mFullbright)
- {
- // Turn off lighting if it hasn't already been so.
- if (light_enabled || !initialized_lighting)
- {
- initialized_lighting = TRUE;
- target_shader = fullbright_shader;
-
- light_enabled = FALSE;
- }
- }
- // Turn on lighting if it isn't already.
- else if (!light_enabled || !initialized_lighting)
- {
- initialized_lighting = TRUE;
- target_shader = simple_shader;
- light_enabled = TRUE;
- }
+ if (params.mFullbright)
+ {
+ // Turn off lighting if it hasn't already been so.
+ if (light_enabled || !initialized_lighting)
+ {
+ initialized_lighting = TRUE;
+ target_shader = fullbright_shader;
- if (deferred_render && mat)
- {
- U32 mask = params.mShaderMask;
+ light_enabled = FALSE;
+ }
+ }
+ // Turn on lighting if it isn't already.
+ else if (!light_enabled || !initialized_lighting)
+ {
+ initialized_lighting = TRUE;
+ target_shader = simple_shader;
+ light_enabled = TRUE;
+ }
+
+ if (deferred_render && mat)
+ {
+ U32 mask = params.mShaderMask;
- llassert(mask < LLMaterial::SHADER_COUNT);
- target_shader = &(gDeferredMaterialProgram[mask]);
+ llassert(mask < LLMaterial::SHADER_COUNT);
+ target_shader = &(gDeferredMaterialProgram[mask]);
+
+ if (LLPipeline::sUnderWaterRender)
+ {
+ target_shader = &(gDeferredMaterialWaterProgram[mask]);
+ }
+
+ if (params.mAvatar != nullptr)
+ {
+ llassert(target_shader->mRiggedVariant != nullptr);
+ target_shader = target_shader->mRiggedVariant;
+ }
+ }
+ else if (!params.mFullbright)
+ {
+ target_shader = simple_shader;
+ }
+ else
+ {
+ target_shader = fullbright_shader;
+ }
- if (LLPipeline::sUnderWaterRender)
- {
- target_shader = &(gDeferredMaterialWaterProgram[mask]);
- }
if (params.mAvatar != nullptr)
{
- llassert(target_shader->mRiggedVariant != nullptr);
target_shader = target_shader->mRiggedVariant;
}
- if (current_shader != target_shader)
- {
- gPipeline.bindDeferredShader(*target_shader);
- }
- }
- else if (!params.mFullbright)
- {
- target_shader = simple_shader;
- }
- else
- {
- target_shader = fullbright_shader;
- }
-
- if (params.mAvatar != nullptr)
- {
- target_shader = target_shader->mRiggedVariant;
- }
-
- if (current_shader != target_shader)
- {// If we need shaders, and we're not ALREADY using the proper shader, then bind it
- // (this way we won't rebind shaders unnecessarily).
- target_shader->bind();
- }
+ if (current_shader != target_shader)
+ {// If we need shaders, and we're not ALREADY using the proper shader, then bind it
+ // (this way we won't rebind shaders unnecessarily).
+ gPipeline.bindDeferredShaderFast(*target_shader);
+ }
- LLVector4 spec_color(1, 1, 1, 1);
- F32 env_intensity = 0.0f;
- F32 brightness = 1.0f;
+ LLVector4 spec_color(1, 1, 1, 1);
+ F32 env_intensity = 0.0f;
+ F32 brightness = 1.0f;
- // We have a material. Supply the appropriate data here.
- if (mat && deferred_render)
- {
- spec_color = params.mSpecColor;
- env_intensity = params.mEnvIntensity;
- brightness = params.mFullbright ? 1.f : 0.f;
- }
+ // We have a material. Supply the appropriate data here.
+ if (mat && deferred_render)
+ {
+ spec_color = params.mSpecColor;
+ env_intensity = params.mEnvIntensity;
+ brightness = params.mFullbright ? 1.f : 0.f;
+ }
- if (current_shader)
- {
- current_shader->uniform4f(LLShaderMgr::SPECULAR_COLOR, spec_color.mV[0], spec_color.mV[1], spec_color.mV[2], spec_color.mV[3]);
- current_shader->uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, env_intensity);
- current_shader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, brightness);
+ if (current_shader)
+ {
+ current_shader->uniform4f(LLShaderMgr::SPECULAR_COLOR, spec_color.mV[0], spec_color.mV[1], spec_color.mV[2], spec_color.mV[3]);
+ current_shader->uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, env_intensity);
+ current_shader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, brightness);
+ }
}
- if (params.mGroup)
- {
- params.mGroup->rebuildMesh();
- }
+ //if (params.mGroup) // TOO LATE
+ //{
+ // params.mGroup->rebuildMesh();
+ //}
if (params.mAvatar != nullptr)
{
@@ -725,7 +790,7 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only, bool rigged)
bool tex_setup = TexSetup(&params, (mat != nullptr));
{
- LLGLEnableFunc stencil_test(GL_STENCIL_TEST, params.mSelected, &LLGLCommonFunc::selected_stencil_test);
+ //LLGLEnableFunc stencil_test(GL_STENCIL_TEST, params.mSelected, &LLGLCommonFunc::selected_stencil_test);
gGL.blendFunc((LLRender::eBlendFactor) params.mBlendFuncSrc, (LLRender::eBlendFactor) params.mBlendFuncDst, mAlphaSFactor, mAlphaDFactor);
@@ -738,18 +803,8 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only, bool rigged)
reset_minimum_alpha = true;
}
- U32 drawMask = mask;
- if (params.mFullbright)
- {
- drawMask &= ~(LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2);
- }
- if (params.mAvatar != nullptr)
- {
- drawMask |= LLVertexBuffer::MAP_WEIGHT4;
- }
-
- params.mVertexBuffer->setBufferFast(drawMask);
- params.mVertexBuffer->drawRangeFast(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
+ params.mVertexBuffer->setBuffer();
+ params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset);
if (reset_minimum_alpha)
{
diff --git a/indra/newview/lldrawpoolalpha.h b/indra/newview/lldrawpoolalpha.h
index fa8ef0f227..2c1ec30958 100644
--- a/indra/newview/lldrawpoolalpha.h
+++ b/indra/newview/lldrawpoolalpha.h
@@ -35,9 +35,13 @@ class LLFace;
class LLColor4;
class LLGLSLShader;
-class LLDrawPoolAlpha: public LLRenderPass
+class LLDrawPoolAlpha final: public LLRenderPass
{
public:
+
+ // set by llsettingsvo so lldrawpoolalpha has quick access to the water plane in eye space
+ static LLVector4 sWaterPlane;
+
enum
{
VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX |
@@ -47,7 +51,7 @@ public:
};
virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; }
- LLDrawPoolAlpha(U32 type = LLDrawPool::POOL_ALPHA);
+ LLDrawPoolAlpha(U32 type);
/*virtual*/ ~LLDrawPoolAlpha();
/*virtual*/ S32 getNumPostDeferredPasses();
@@ -91,11 +95,4 @@ private:
bool mRigged = false;
};
-class LLDrawPoolAlphaPostWater : public LLDrawPoolAlpha
-{
-public:
- LLDrawPoolAlphaPostWater();
- virtual void render(S32 pass = 0);
-};
-
#endif // LL_LLDRAWPOOLALPHA_H
diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp
index 4a9a3caaec..8a3ab20ab4 100644
--- a/indra/newview/lldrawpoolavatar.cpp
+++ b/indra/newview/lldrawpoolavatar.cpp
@@ -53,8 +53,6 @@
#include "llviewercontrol.h" // for gSavedSettings
#include "llviewertexturelist.h"
-static U32 sDataMask = LLDrawPoolAvatar::VERTEX_DATA_MASK;
-static U32 sBufferUsage = GL_STREAM_DRAW_ARB;
static U32 sShaderLevel = 0;
LLGLSLShader* LLDrawPoolAvatar::sVertexProgram = NULL;
@@ -143,15 +141,6 @@ void LLDrawPoolAvatar::prerender()
mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_AVATAR);
sShaderLevel = mShaderLevel;
-
- if (sShaderLevel > 0)
- {
- sBufferUsage = GL_DYNAMIC_DRAW_ARB;
- }
- else
- {
- sBufferUsage = GL_STREAM_DRAW_ARB;
- }
}
LLMatrix4& LLDrawPoolAvatar::getModelView()
@@ -932,11 +921,3 @@ LLColor3 LLDrawPoolAvatar::getDebugColor() const
}
-LLVertexBufferAvatar::LLVertexBufferAvatar()
-: LLVertexBuffer(sDataMask,
- GL_STREAM_DRAW_ARB) //avatars are always stream draw due to morph targets
-{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR
-}
-
-
diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h
index 21add39b21..ff78c6c60a 100644
--- a/indra/newview/lldrawpoolavatar.h
+++ b/indra/newview/lldrawpoolavatar.h
@@ -129,12 +129,6 @@ typedef enum
static LLGLSLShader* sVertexProgram;
};
-class LLVertexBufferAvatar : public LLVertexBuffer
-{
-public:
- LLVertexBufferAvatar();
-};
-
extern S32 AVATAR_OFFSET_POS;
extern S32 AVATAR_OFFSET_NORMAL;
extern S32 AVATAR_OFFSET_TEX0;
diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp
index c4c88d304c..f5d0412993 100644
--- a/indra/newview/lldrawpoolbump.cpp
+++ b/indra/newview/lldrawpoolbump.cpp
@@ -299,7 +299,7 @@ void LLDrawPoolBump::beginShiny()
void LLDrawPoolBump::bindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& diffuse_channel, S32& cube_channel)
{
LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL;
- if( cube_map )
+ if( cube_map && !LLPipeline::sReflectionProbesEnabled )
{
if (shader )
{
@@ -346,29 +346,29 @@ void LLDrawPoolBump::renderShiny()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; //LL_RECORD_BLOCK_TIME(FTM_RENDER_SHINY);
- if( gSky.mVOSkyp->getCubeMap() )
+ if( gSky.mVOSkyp->getCubeMap() && !LLPipeline::sReflectionProbesEnabled )
{
LLGLEnable blend_enable(GL_BLEND);
if (mShaderLevel > 1)
{
if (mRigged)
{
- LLRenderPass::pushRiggedBatches(LLRenderPass::PASS_SHINY_RIGGED, sVertexMask | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
+ LLRenderPass::pushRiggedBatches(LLRenderPass::PASS_SHINY_RIGGED, true, true);
}
else
{
- LLRenderPass::pushBatches(LLRenderPass::PASS_SHINY, sVertexMask | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
+ LLRenderPass::pushBatches(LLRenderPass::PASS_SHINY, true, true);
}
}
else
{
if (mRigged)
{
- gPipeline.renderRiggedGroups(this, LLRenderPass::PASS_SHINY_RIGGED, sVertexMask, TRUE);
+ gPipeline.renderRiggedGroups(this, LLRenderPass::PASS_SHINY_RIGGED, true);
}
else
{
- gPipeline.renderGroups(this, LLRenderPass::PASS_SHINY, sVertexMask, TRUE);
+ gPipeline.renderGroups(this, LLRenderPass::PASS_SHINY, true);
}
}
}
@@ -378,7 +378,7 @@ void LLDrawPoolBump::renderShiny()
void LLDrawPoolBump::unbindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& diffuse_channel, S32& cube_channel)
{
LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL;
- if( cube_map )
+ if( cube_map && !LLPipeline::sReflectionProbesEnabled)
{
if (shader_level > 1)
{
@@ -445,7 +445,20 @@ void LLDrawPoolBump::beginFullbrightShiny()
}
LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL;
- if( cube_map )
+
+ if (cube_map && !LLPipeline::sReflectionProbesEnabled)
+ {
+ // Make sure that texture coord generation happens for tex unit 1, as that's the one we use for
+ // the cube map in the one pass shiny shaders
+ gGL.getTexUnit(1)->disable();
+ cube_channel = shader->enableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
+ cube_map->enableTexture(cube_channel);
+ diffuse_channel = shader->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
+
+ gGL.getTexUnit(cube_channel)->bind(cube_map);
+ gGL.getTexUnit(0)->activate();
+ }
+
{
LLMatrix4 mat;
mat.initRows(LLVector4(gGLModelView+0),
@@ -466,16 +479,14 @@ void LLDrawPoolBump::beginFullbrightShiny()
LLVector4 vec4(vec, gShinyOrigin.mV[3]);
shader->uniform4fv(LLViewerShaderMgr::SHINY_ORIGIN, 1, vec4.mV);
- cube_map->setMatrix(1);
- // Make sure that texture coord generation happens for tex unit 1, as that's the one we use for
- // the cube map in the one pass shiny shaders
- gGL.getTexUnit(1)->disable();
- cube_channel = shader->enableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
- cube_map->enableTexture(cube_channel);
- diffuse_channel = shader->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
-
- gGL.getTexUnit(cube_channel)->bind(cube_map);
- gGL.getTexUnit(0)->activate();
+ if (LLPipeline::sReflectionProbesEnabled)
+ {
+ gPipeline.bindReflectionProbes(*shader);
+ }
+ else
+ {
+ gPipeline.setEnvMat(*shader);
+ }
}
if (mShaderLevel > 1)
@@ -490,7 +501,6 @@ void LLDrawPoolBump::renderFullbrightShiny()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; //LL_RECORD_BLOCK_TIME(FTM_RENDER_SHINY);
- if( gSky.mVOSkyp->getCubeMap() )
{
LLGLEnable blend_enable(GL_BLEND);
@@ -498,22 +508,22 @@ void LLDrawPoolBump::renderFullbrightShiny()
{
if (mRigged)
{
- LLRenderPass::pushRiggedBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY_RIGGED, sVertexMask | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
+ LLRenderPass::pushRiggedBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY_RIGGED, true, true);
}
else
{
- LLRenderPass::pushBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY, sVertexMask | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
+ LLRenderPass::pushBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY, true, true);
}
}
else
{
if (mRigged)
{
- LLRenderPass::pushRiggedBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY_RIGGED, sVertexMask);
+ LLRenderPass::pushRiggedBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY_RIGGED);
}
else
{
- LLRenderPass::pushBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY, sVertexMask);
+ LLRenderPass::pushBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY);
}
}
}
@@ -524,10 +534,13 @@ void LLDrawPoolBump::endFullbrightShiny()
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; //LL_RECORD_BLOCK_TIME(FTM_RENDER_SHINY);
LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL;
- if( cube_map )
+ if( cube_map && !LLPipeline::sReflectionProbesEnabled )
{
cube_map->disable();
- cube_map->restoreMatrix();
+ if (shader->mFeatures.hasReflectionProbes)
+ {
+ gPipeline.unbindReflectionProbes(*shader);
+ }
shader->unbind();
}
@@ -536,7 +549,7 @@ void LLDrawPoolBump::endFullbrightShiny()
mShiny = FALSE;
}
-void LLDrawPoolBump::renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture = TRUE)
+void LLDrawPoolBump::renderGroup(LLSpatialGroup* group, U32 type, bool texture = true)
{
LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[type];
@@ -546,13 +559,8 @@ void LLDrawPoolBump::renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL
applyModelMatrix(params);
- if (params.mGroup)
- {
- params.mGroup->rebuildMesh();
- }
- params.mVertexBuffer->setBuffer(mask);
- params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
- gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode);
+ params.mVertexBuffer->setBuffer();
+ params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset);
}
}
@@ -562,7 +570,7 @@ BOOL LLDrawPoolBump::bindBumpMap(LLDrawInfo& params, S32 channel)
{
U8 bump_code = params.mBump;
- return bindBumpMap(bump_code, params.mTexture, params.mVSize, channel);
+ return bindBumpMap(bump_code, params.mTexture, channel);
}
//static
@@ -572,14 +580,14 @@ BOOL LLDrawPoolBump::bindBumpMap(LLFace* face, S32 channel)
if (te)
{
U8 bump_code = te->getBumpmap();
- return bindBumpMap(bump_code, face->getTexture(), face->getVirtualSize(), channel);
+ return bindBumpMap(bump_code, face->getTexture(), channel);
}
return FALSE;
}
//static
-BOOL LLDrawPoolBump::bindBumpMap(U8 bump_code, LLViewerTexture* texture, F32 vsize, S32 channel)
+BOOL LLDrawPoolBump::bindBumpMap(U8 bump_code, LLViewerTexture* texture, S32 channel)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
//Note: texture atlas does not support bump texture now.
@@ -605,7 +613,7 @@ BOOL LLDrawPoolBump::bindBumpMap(U8 bump_code, LLViewerTexture* texture, F32 vsi
if( bump_code < LLStandardBumpmap::sStandardBumpmapCount )
{
bump = gStandardBumpmapList[bump_code].mImage;
- gBumpImageList.addTextureStats(bump_code, tex->getID(), vsize);
+ gBumpImageList.addTextureStats(bump_code, tex->getID(), tex->getMaxVirtualSize());
}
break;
}
@@ -655,26 +663,26 @@ void LLDrawPoolBump::beginBump()
void LLDrawPoolBump::renderBump(U32 pass)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; //LL_RECORD_BLOCK_TIME(FTM_RENDER_BUMP);
- LLGLDisable fog(GL_FOG);
LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_LEQUAL);
LLGLEnable blend(GL_BLEND);
gGL.diffuseColor4f(1,1,1,1);
/// Get rid of z-fighting with non-bump pass.
LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(-1.0f, -1.0f);
- renderBump(pass, sVertexMask);
+ pushBumpBatches(pass);
}
//static
void LLDrawPoolBump::endBump(U32 pass)
{
- gObjectBumpProgram.unbind();
+ LLGLSLShader::unbind();
gGL.setSceneBlendType(LLRender::BT_ALPHA);
}
S32 LLDrawPoolBump::getNumDeferredPasses()
{
+#if 0 //DEPRECATED -- RenderObjectBump should always be TRUE
if (gSavedSettings.getBOOL("RenderObjectBump"))
{
return 1;
@@ -683,6 +691,9 @@ S32 LLDrawPoolBump::getNumDeferredPasses()
{
return 0;
}
+#else
+ return 1;
+#endif
}
void LLDrawPoolBump::renderDeferred(S32 pass)
@@ -703,15 +714,15 @@ void LLDrawPoolBump::renderDeferred(S32 pass)
LLCullResult::drawinfo_iterator begin = gPipeline.beginRenderMap(type);
LLCullResult::drawinfo_iterator end = gPipeline.endRenderMap(type);
- U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_COLOR;
-
LLVOAvatar* avatar = nullptr;
U64 skin = 0;
- for (LLCullResult::drawinfo_iterator i = begin; i != end; ++i)
+ for (LLCullResult::drawinfo_iterator i = begin; i != end; )
{
LLDrawInfo& params = **i;
+ LLCullResult::increment_iterator(i, end);
+
LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(params.mAlphaMaskCutoff);
LLDrawPoolBump::bindBumpMap(params, bump_channel);
@@ -723,11 +734,11 @@ void LLDrawPoolBump::renderDeferred(S32 pass)
avatar = params.mAvatar;
skin = params.mSkinInfo->mHash;
}
- pushBatch(params, mask | LLVertexBuffer::MAP_WEIGHT4, TRUE, FALSE);
+ pushBatch(params, true, false);
}
else
{
- pushBatch(params, mask, TRUE, FALSE);
+ pushBatch(params, true, false);
}
}
@@ -743,6 +754,7 @@ void LLDrawPoolBump::renderDeferred(S32 pass)
void LLDrawPoolBump::renderPostDeferred(S32 pass)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL
for (int i = 0; i < 2; ++i)
{ // two passes -- static and rigged
mRigged = (i == 1);
@@ -1323,7 +1335,7 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI
}
}
-void LLDrawPoolBump::renderBump(U32 type, U32 mask)
+void LLDrawPoolBump::pushBumpBatches(U32 type)
{
LLVOAvatar* avatar = nullptr;
U64 skin = 0;
@@ -1331,7 +1343,6 @@ void LLDrawPoolBump::renderBump(U32 type, U32 mask)
if (mRigged)
{ // nudge type enum and include skinweights for rigged pass
type += 1;
- mask |= LLVertexBuffer::MAP_WEIGHT4;
}
LLCullResult::drawinfo_iterator begin = gPipeline.beginRenderMap(type);
@@ -1358,12 +1369,12 @@ void LLDrawPoolBump::renderBump(U32 type, U32 mask)
}
}
}
- pushBatch(params, mask, FALSE);
+ pushBatch(params, false);
}
}
}
-void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures)
+void LLDrawPoolBump::pushBatch(LLDrawInfo& params, bool texture, bool batch_textures)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
applyModelMatrix(params);
@@ -1416,12 +1427,8 @@ void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL
}
}
- if (params.mGroup)
- {
- params.mGroup->rebuildMesh();
- }
- params.mVertexBuffer->setBufferFast(mask);
- params.mVertexBuffer->drawRangeFast(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
+ params.mVertexBuffer->setBuffer();
+ params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset);
if (tex_setup)
{
@@ -1449,11 +1456,11 @@ void LLDrawPoolInvisible::render(S32 pass)
}
U32 invisi_mask = LLVertexBuffer::MAP_VERTEX;
- glStencilMask(0);
+ //glStencilMask(0); //deprecated
gGL.setColorMask(false, false);
pushBatches(LLRenderPass::PASS_INVISIBLE, invisi_mask, FALSE);
gGL.setColorMask(true, false);
- glStencilMask(0xFFFFFFFF);
+ //glStencilMask(0xFFFFFFFF); //deprecated
if (gPipeline.shadersLoaded())
{
diff --git a/indra/newview/lldrawpoolbump.h b/indra/newview/lldrawpoolbump.h
index cf463f4458..4400308451 100644
--- a/indra/newview/lldrawpoolbump.h
+++ b/indra/newview/lldrawpoolbump.h
@@ -55,10 +55,10 @@ public:
virtual void render(S32 pass = 0) override;
virtual S32 getNumPasses() override;
/*virtual*/ void prerender() override;
- void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures = FALSE) override;
+ void pushBatch(LLDrawInfo& params, bool texture, bool batch_textures = false) override;
- void renderBump(U32 type, U32 mask);
- void renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture) override;
+ void pushBumpBatches(U32 type);
+ void renderGroup(LLSpatialGroup* group, U32 type, bool texture) override;
S32 numBumpPasses();
@@ -87,7 +87,7 @@ public:
static BOOL bindBumpMap(LLFace* face, S32 channel = -2);
private:
- static BOOL bindBumpMap(U8 bump_code, LLViewerTexture* tex, F32 vsize, S32 channel);
+ static BOOL bindBumpMap(U8 bump_code, LLViewerTexture* tex, S32 channel);
bool mRigged = false; // if true, doing a rigged pass
};
diff --git a/indra/newview/lldrawpoolmaterials.cpp b/indra/newview/lldrawpoolmaterials.cpp
index 2b05f4c453..735f32ddbb 100644
--- a/indra/newview/lldrawpoolmaterials.cpp
+++ b/indra/newview/lldrawpoolmaterials.cpp
@@ -33,8 +33,6 @@
#include "llglcommonfunc.h"
#include "llvoavatar.h"
-S32 diffuse_channel = -1;
-
LLDrawPoolMaterials::LLDrawPoolMaterials()
: LLRenderPass(LLDrawPool::POOL_MATERIALS)
{
@@ -98,7 +96,8 @@ void LLDrawPoolMaterials::beginDeferredPass(S32 pass)
llassert(mShader->mRiggedVariant != nullptr);
mShader = mShader->mRiggedVariant;
}
- mShader->bind();
+
+ gPipeline.bindDeferredShader(*mShader);
if (LLPipeline::sRenderingHUDs)
{
@@ -108,8 +107,6 @@ void LLDrawPoolMaterials::beginDeferredPass(S32 pass)
{
mShader->uniform1i(LLShaderMgr::NO_ATMO, 0);
}
-
- diffuse_channel = mShader->enableTexture(LLShaderMgr::DIFFUSE_MAP);
}
void LLDrawPoolMaterials::endDeferredPass(S32 pass)
@@ -159,117 +156,160 @@ void LLDrawPoolMaterials::renderDeferred(S32 pass)
type += 1;
}
- U32 mask = mShader->mAttributeMask;
-
LLCullResult::drawinfo_iterator begin = gPipeline.beginRenderMap(type);
LLCullResult::drawinfo_iterator end = gPipeline.endRenderMap(type);
- for (LLCullResult::drawinfo_iterator i = begin; i != end; ++i)
+ F32 lastIntensity = 0.f;
+ F32 lastFullbright = 0.f;
+ F32 lastMinimumAlpha = 0.f;
+ LLVector4 lastSpecular = LLVector4(0, 0, 0, 0);
+
+ GLint intensity = mShader->getUniformLocation(LLShaderMgr::ENVIRONMENT_INTENSITY);
+ GLint brightness = mShader->getUniformLocation(LLShaderMgr::EMISSIVE_BRIGHTNESS);
+ GLint minAlpha = mShader->getUniformLocation(LLShaderMgr::MINIMUM_ALPHA);
+ GLint specular = mShader->getUniformLocation(LLShaderMgr::SPECULAR_COLOR);
+
+ GLint diffuseChannel = mShader->enableTexture(LLShaderMgr::DIFFUSE_MAP);
+ GLint specChannel = mShader->enableTexture(LLShaderMgr::SPECULAR_MAP);
+ GLint normChannel = mShader->enableTexture(LLShaderMgr::BUMP_MAP);
+
+ LLTexture* lastNormalMap = nullptr;
+ LLTexture* lastSpecMap = nullptr;
+ LLTexture* lastDiffuse = nullptr;
+
+ gGL.getTexUnit(diffuseChannel)->unbindFast(LLTexUnit::TT_TEXTURE);
+
+ if (intensity > -1)
+ {
+ glUniform1f(intensity, lastIntensity);
+ }
+
+ if (brightness > -1)
+ {
+ glUniform1f(brightness, lastFullbright);
+ }
+
+ if (minAlpha > -1)
+ {
+ glUniform1f(minAlpha, lastMinimumAlpha);
+ }
+
+ if (specular > -1)
+ {
+ glUniform4fv(specular, 1, lastSpecular.mV);
+ }
+
+ LLVOAvatar* lastAvatar = nullptr;
+
+ for (LLCullResult::drawinfo_iterator i = begin; i != end; )
{
+ LL_PROFILE_ZONE_NAMED_CATEGORY_MATERIAL("materials draw loop");
LLDrawInfo& params = **i;
- mShader->uniform4f(LLShaderMgr::SPECULAR_COLOR, params.mSpecColor.mV[0], params.mSpecColor.mV[1], params.mSpecColor.mV[2], params.mSpecColor.mV[3]);
- mShader->uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, params.mEnvIntensity);
-
- if (params.mNormalMap)
- {
- params.mNormalMap->addTextureStats(params.mVSize);
- bindNormalMap(params.mNormalMap);
- }
-
- if (params.mSpecularMap)
- {
- params.mSpecularMap->addTextureStats(params.mVSize);
- bindSpecularMap(params.mSpecularMap);
- }
-
- mShader->setMinimumAlpha(params.mAlphaMaskCutoff);
- mShader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, params.mFullbright ? 1.f : 0.f);
+ LLCullResult::increment_iterator(i, end);
+ if (specular > -1 && params.mSpecColor != lastSpecular)
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_MATERIAL;
- pushMaterialsBatch(params, mask, rigged);
+ lastSpecular = params.mSpecColor;
+ glUniform4fv(specular, 1, lastSpecular.mV);
}
- }
-}
-void LLDrawPoolMaterials::bindSpecularMap(LLViewerTexture* tex)
-{
- mShader->bindTexture(LLShaderMgr::SPECULAR_MAP, tex);
-}
+ if (intensity != -1 && lastIntensity != params.mEnvIntensity)
+ {
+ lastIntensity = params.mEnvIntensity;
+ glUniform1f(intensity, lastIntensity);
+ }
+
+ if (minAlpha > -1 && lastMinimumAlpha != params.mAlphaMaskCutoff)
+ {
+ lastMinimumAlpha = params.mAlphaMaskCutoff;
+ glUniform1f(minAlpha, lastMinimumAlpha);
+ }
-void LLDrawPoolMaterials::bindNormalMap(LLViewerTexture* tex)
-{
- mShader->bindTexture(LLShaderMgr::BUMP_MAP, tex);
-}
+ F32 fullbright = params.mFullbright ? 1.f : 0.f;
+ if (brightness > -1 && lastFullbright != fullbright)
+ {
+ lastFullbright = fullbright;
+ glUniform1f(brightness, lastFullbright);
+ }
-void LLDrawPoolMaterials::pushMaterialsBatch(LLDrawInfo& params, U32 mask, bool rigged)
-{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_MATERIAL;
- applyModelMatrix(params);
-
- bool tex_setup = false;
-
- //not batching textures or batch has only 1 texture -- might need a texture matrix
- if (params.mTextureMatrix)
- {
- //if (mShiny)
- {
- gGL.getTexUnit(0)->activate();
- gGL.matrixMode(LLRender::MM_TEXTURE);
- }
-
- gGL.loadMatrix((GLfloat*) params.mTextureMatrix->mMatrix);
- gPipeline.mTextureMatrixOps++;
-
- tex_setup = true;
- }
-
- if (mShaderLevel > 1)
- {
- if (params.mTexture.notNull())
- {
- gGL.getTexUnit(diffuse_channel)->bindFast(params.mTexture);
- }
- else
- {
- gGL.getTexUnit(diffuse_channel)->unbindFast(LLTexUnit::TT_TEXTURE);
- }
- }
-
- if (params.mGroup)
- {
- params.mGroup->rebuildMesh();
- }
+ if (normChannel > -1 && params.mNormalMap != lastNormalMap)
+ {
+ lastNormalMap = params.mNormalMap;
+ llassert(lastNormalMap);
+ gGL.getTexUnit(normChannel)->bindFast(lastNormalMap);
+ }
- // upload matrix palette to shader
- if (rigged && params.mAvatar.notNull())
- {
- const LLVOAvatar::MatrixPaletteCache& mpc = params.mAvatar->updateSkinInfoMatrixPalette(params.mSkinInfo);
- U32 count = mpc.mMatrixPalette.size();
+ if (specChannel > -1 && params.mSpecularMap != lastSpecMap)
+ {
+ lastSpecMap = params.mSpecularMap;
+ llassert(lastSpecMap);
+ gGL.getTexUnit(specChannel)->bindFast(lastSpecMap);
+ }
- if (count == 0)
+ if (params.mTexture != lastDiffuse)
{
- //skin info not loaded yet, don't render
- return;
+ lastDiffuse = params.mTexture;
+ if (lastDiffuse)
+ {
+ gGL.getTexUnit(diffuseChannel)->bindFast(lastDiffuse);
+ }
+ else
+ {
+ gGL.getTexUnit(diffuseChannel)->unbindFast(LLTexUnit::TT_TEXTURE);
+ }
}
- mShader->uniformMatrix3x4fv(LLViewerShaderMgr::AVATAR_MATRIX,
- count,
- FALSE,
- (GLfloat*)&(mpc.mGLMp[0]));
- }
+ // upload matrix palette to shader
+ if (rigged && params.mAvatar.notNull())
+ {
+ if (params.mAvatar != lastAvatar)
+ {
+ const LLVOAvatar::MatrixPaletteCache& mpc = params.mAvatar->updateSkinInfoMatrixPalette(params.mSkinInfo);
+ U32 count = mpc.mMatrixPalette.size();
- LLGLEnableFunc stencil_test(GL_STENCIL_TEST, params.mSelected, &LLGLCommonFunc::selected_stencil_test);
+ if (count == 0)
+ {
+ //skin info not loaded yet, don't render
+ return;
+ }
- params.mVertexBuffer->setBufferFast(mask);
- params.mVertexBuffer->drawRangeFast(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
+ mShader->uniformMatrix3x4fv(LLViewerShaderMgr::AVATAR_MATRIX,
+ count,
+ FALSE,
+ (GLfloat*)&(mpc.mGLMp[0]));
+ }
+ }
- if (tex_setup)
- {
- gGL.getTexUnit(0)->activate();
- gGL.loadIdentity();
- gGL.matrixMode(LLRender::MM_MODELVIEW);
+ applyModelMatrix(params);
+
+ bool tex_setup = false;
+
+ //not batching textures or batch has only 1 texture -- might need a texture matrix
+ if (params.mTextureMatrix)
+ {
+ gGL.getTexUnit(0)->activate();
+ gGL.matrixMode(LLRender::MM_TEXTURE);
+
+ gGL.loadMatrix((GLfloat*)params.mTextureMatrix->mMatrix);
+ gPipeline.mTextureMatrixOps++;
+
+ tex_setup = true;
+ }
+
+ /*if (params.mGroup) // TOO LATE
+ {
+ params.mGroup->rebuildMesh();
+ }*/
+
+ params.mVertexBuffer->setBuffer();
+ params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset);
+
+ if (tex_setup)
+ {
+ gGL.getTexUnit(0)->activate();
+ gGL.loadIdentity();
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
+ }
}
}
-
diff --git a/indra/newview/lldrawpoolmaterials.h b/indra/newview/lldrawpoolmaterials.h
index 8a3ad923df..c46c053bd0 100644
--- a/indra/newview/lldrawpoolmaterials.h
+++ b/indra/newview/lldrawpoolmaterials.h
@@ -65,11 +65,6 @@ public:
void beginDeferredPass(S32 pass) override;
void endDeferredPass(S32 pass) override;
void renderDeferred(S32 pass) override;
-
- void bindSpecularMap(LLViewerTexture* tex);
- void bindNormalMap(LLViewerTexture* tex);
-
- void pushMaterialsBatch(LLDrawInfo& params, U32 mask, bool rigged);
};
#endif //LL_LLDRAWPOOLMATERIALS_H
diff --git a/indra/newview/app_settings/shaders/class3/windlight/atmosphericsF.glsl b/indra/newview/lldrawpoolpbropaque.cpp
index 2b70ba76dc..9dd1bc0ba2 100644
--- a/indra/newview/app_settings/shaders/class3/windlight/atmosphericsF.glsl
+++ b/indra/newview/lldrawpoolpbropaque.cpp
@@ -1,9 +1,10 @@
/**
- * @file class3\wl\atmosphericsF.glsl
+ * @file lldrawpoolpbropaque.cpp
+ * @brief LLDrawPoolGLTFPBR class implementation
*
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2007, Linden Research, Inc.
+ * 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
@@ -23,24 +24,30 @@
* $/LicenseInfo$
*/
-vec3 getAdditiveColor();
-vec3 getAtmosAttenuation();
-vec3 scaleSoftClipFrag(vec3 light);
+#include "llviewerprecompiledheaders.h"
-uniform int no_atmo;
+#include "lldrawpool.h"
+#include "lldrawpoolpbropaque.h"
+#include "llviewershadermgr.h"
+#include "pipeline.h"
-vec3 atmosFragLighting(vec3 light, vec3 additive, vec3 atten)
+LLDrawPoolGLTFPBR::LLDrawPoolGLTFPBR() :
+ LLRenderPass(POOL_GLTF_PBR)
{
- if (no_atmo == 1)
- {
- return light;
- }
- light *= atten.r;
- light += additive;
- return light * 2.0;
}
-vec3 atmosLighting(vec3 light)
+void LLDrawPoolGLTFPBR::renderDeferred(S32 pass)
{
- return atmosFragLighting(light, getAdditiveColor(), getAtmosAttenuation());
+ const U32 types[] = { LLPipeline::RENDER_TYPE_PASS_GLTF_PBR, LLPipeline::RENDER_TYPE_PASS_GLTF_PBR_ALPHA_MASK };
+
+ for (U32 type : types)
+ {
+ gDeferredPBROpaqueProgram.bind();
+ pushGLTFBatches(type);
+
+ gDeferredPBROpaqueProgram.bind(true);
+ pushRiggedGLTFBatches(type+1);
+ }
}
+
+
diff --git a/indra/newview/lldrawpoolpbropaque.h b/indra/newview/lldrawpoolpbropaque.h
new file mode 100644
index 0000000000..2fe0695c69
--- /dev/null
+++ b/indra/newview/lldrawpoolpbropaque.h
@@ -0,0 +1,55 @@
+/**
+ * @file lldrawpoolpbropaque.h
+ * @brief LLDrawPoolPBrOpaque class definition
+ *
+ * $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$
+ */
+
+#ifndef LL_LLDRAWPOOLPBROPAQUE_H
+#define LL_LLDRAWPOOLPBROPAQUE_H
+
+#include "lldrawpool.h"
+
+class LLDrawPoolGLTFPBR final : public LLRenderPass
+{
+public:
+ enum
+ {
+ // See: DEFERRED_VB_MASK
+ VERTEX_DATA_MASK = 0
+ | LLVertexBuffer::MAP_VERTEX
+ | LLVertexBuffer::MAP_NORMAL
+ | LLVertexBuffer::MAP_TEXCOORD0 // Diffuse
+ | LLVertexBuffer::MAP_TEXCOORD1 // Normal
+ | LLVertexBuffer::MAP_TEXCOORD2 // Spec <-- ORM Occlusion Roughness Metal
+ | LLVertexBuffer::MAP_TANGENT
+ | LLVertexBuffer::MAP_COLOR
+ };
+ U32 getVertexDataMask() override { return VERTEX_DATA_MASK; }
+
+ LLDrawPoolGLTFPBR();
+
+ S32 getNumDeferredPasses() override { return 1; }
+ void renderDeferred(S32 pass) override;
+};
+
+#endif // LL_LLDRAWPOOLPBROPAQUE_H
diff --git a/indra/newview/lldrawpoolsimple.cpp b/indra/newview/lldrawpoolsimple.cpp
index e324a663f4..7a8b2b4b35 100644
--- a/indra/newview/lldrawpoolsimple.cpp
+++ b/indra/newview/lldrawpoolsimple.cpp
@@ -99,12 +99,12 @@ void LLDrawPoolGlow::render(LLGLSLShader* shader)
//first pass -- static objects
setup_glow_shader(shader);
- pushBatches(LLRenderPass::PASS_GLOW, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
+ pushBatches(LLRenderPass::PASS_GLOW, true, true);
// second pass -- rigged objects
shader = shader->mRiggedVariant;
setup_glow_shader(shader);
- pushRiggedBatches(LLRenderPass::PASS_GLOW_RIGGED, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
+ pushRiggedBatches(LLRenderPass::PASS_GLOW_RIGGED, true, true);
gGL.setColorMask(true, false);
gGL.setSceneBlendType(LLRender::BT_ALPHA);
@@ -161,21 +161,19 @@ void LLDrawPoolSimple::render(S32 pass)
gPipeline.enableLightsDynamic();
- U32 mask = getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX;
-
// first pass -- static objects
{
setup_simple_shader(shader);
- pushBatches(LLRenderPass::PASS_SIMPLE, mask, TRUE, TRUE);
+ pushBatches(LLRenderPass::PASS_SIMPLE, true, true);
if (LLPipeline::sRenderDeferred)
{ //if deferred rendering is enabled, bump faces aren't registered as simple
//render bump faces here as simple so bump faces will appear under water
- pushBatches(LLRenderPass::PASS_BUMP, mask, TRUE, TRUE);
- pushBatches(LLRenderPass::PASS_MATERIAL, mask, TRUE, TRUE);
- pushBatches(LLRenderPass::PASS_SPECMAP, mask, TRUE, TRUE);
- pushBatches(LLRenderPass::PASS_NORMMAP, mask, TRUE, TRUE);
- pushBatches(LLRenderPass::PASS_NORMSPEC, mask, TRUE, TRUE);
+ pushBatches(LLRenderPass::PASS_BUMP, true, true);
+ pushBatches(LLRenderPass::PASS_MATERIAL, true, true);
+ pushBatches(LLRenderPass::PASS_SPECMAP, true, true);
+ pushBatches(LLRenderPass::PASS_NORMMAP, true, true);
+ pushBatches(LLRenderPass::PASS_NORMSPEC, true, true);
}
}
@@ -183,16 +181,16 @@ void LLDrawPoolSimple::render(S32 pass)
{
shader = shader->mRiggedVariant;
setup_simple_shader(shader);
- pushRiggedBatches(LLRenderPass::PASS_SIMPLE_RIGGED, mask, TRUE, TRUE);
+ pushRiggedBatches(LLRenderPass::PASS_SIMPLE_RIGGED, true, true);
if (LLPipeline::sRenderDeferred)
{ //if deferred rendering is enabled, bump faces aren't registered as simple
//render bump faces here as simple so bump faces will appear under water
- pushRiggedBatches(LLRenderPass::PASS_BUMP_RIGGED, mask, TRUE, TRUE);
- pushRiggedBatches(LLRenderPass::PASS_MATERIAL_RIGGED, mask, TRUE, TRUE);
- pushRiggedBatches(LLRenderPass::PASS_SPECMAP_RIGGED, mask, TRUE, TRUE);
- pushRiggedBatches(LLRenderPass::PASS_NORMMAP_RIGGED, mask, TRUE, TRUE);
- pushRiggedBatches(LLRenderPass::PASS_NORMSPEC_RIGGED, mask, TRUE, TRUE);
+ pushRiggedBatches(LLRenderPass::PASS_BUMP_RIGGED, true, true);
+ pushRiggedBatches(LLRenderPass::PASS_MATERIAL_RIGGED, true, true);
+ pushRiggedBatches(LLRenderPass::PASS_SPECMAP_RIGGED, true, true);
+ pushRiggedBatches(LLRenderPass::PASS_NORMMAP_RIGGED, true, true);
+ pushRiggedBatches(LLRenderPass::PASS_NORMSPEC_RIGGED, true, true);
}
}
}
@@ -228,19 +226,19 @@ void LLDrawPoolAlphaMask::render(S32 pass)
// render static
setup_simple_shader(shader);
- pushMaskBatches(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
- pushMaskBatches(LLRenderPass::PASS_MATERIAL_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
- pushMaskBatches(LLRenderPass::PASS_SPECMAP_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
- pushMaskBatches(LLRenderPass::PASS_NORMMAP_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
- pushMaskBatches(LLRenderPass::PASS_NORMSPEC_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
+ pushMaskBatches(LLRenderPass::PASS_ALPHA_MASK, true, true);
+ pushMaskBatches(LLRenderPass::PASS_MATERIAL_ALPHA_MASK, true, true);
+ pushMaskBatches(LLRenderPass::PASS_SPECMAP_MASK, true, true);
+ pushMaskBatches(LLRenderPass::PASS_NORMMAP_MASK, true, true);
+ pushMaskBatches(LLRenderPass::PASS_NORMSPEC_MASK, true, true);
// render rigged
setup_simple_shader(shader->mRiggedVariant);
- pushRiggedMaskBatches(LLRenderPass::PASS_ALPHA_MASK_RIGGED, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
- pushRiggedMaskBatches(LLRenderPass::PASS_MATERIAL_ALPHA_MASK_RIGGED, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
- pushRiggedMaskBatches(LLRenderPass::PASS_SPECMAP_MASK_RIGGED, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
- pushRiggedMaskBatches(LLRenderPass::PASS_NORMMAP_MASK_RIGGED, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
- pushRiggedMaskBatches(LLRenderPass::PASS_NORMSPEC_MASK_RIGGED, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
+ pushRiggedMaskBatches(LLRenderPass::PASS_ALPHA_MASK_RIGGED, true, true);
+ pushRiggedMaskBatches(LLRenderPass::PASS_MATERIAL_ALPHA_MASK_RIGGED, true, true);
+ pushRiggedMaskBatches(LLRenderPass::PASS_SPECMAP_MASK_RIGGED, true, true);
+ pushRiggedMaskBatches(LLRenderPass::PASS_NORMMAP_MASK_RIGGED, true, true);
+ pushRiggedMaskBatches(LLRenderPass::PASS_NORMSPEC_MASK_RIGGED, true, true);
}
LLDrawPoolFullbrightAlphaMask::LLDrawPoolFullbrightAlphaMask() :
@@ -269,11 +267,11 @@ void LLDrawPoolFullbrightAlphaMask::render(S32 pass)
// render static
setup_fullbright_shader(shader);
- pushMaskBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
+ pushMaskBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, true, true);
// render rigged
setup_fullbright_shader(shader->mRiggedVariant);
- pushRiggedMaskBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK_RIGGED, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
+ pushRiggedMaskBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK_RIGGED, true, true);
}
//===============================
@@ -293,11 +291,11 @@ void LLDrawPoolSimple::renderDeferred(S32 pass)
//render static
setup_simple_shader(&gDeferredDiffuseProgram);
- pushBatches(LLRenderPass::PASS_SIMPLE, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
+ pushBatches(LLRenderPass::PASS_SIMPLE, true, true);
//render rigged
setup_simple_shader(gDeferredDiffuseProgram.mRiggedVariant);
- pushRiggedBatches(LLRenderPass::PASS_SIMPLE_RIGGED, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
+ pushRiggedBatches(LLRenderPass::PASS_SIMPLE_RIGGED, true, true);
}
static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_MASK_DEFERRED("Deferred Alpha Mask");
@@ -310,11 +308,11 @@ void LLDrawPoolAlphaMask::renderDeferred(S32 pass)
//render static
setup_simple_shader(shader);
- pushMaskBatches(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
+ pushMaskBatches(LLRenderPass::PASS_ALPHA_MASK, true, true);
//render rigged
setup_simple_shader(shader->mRiggedVariant);
- pushRiggedMaskBatches(LLRenderPass::PASS_ALPHA_MASK_RIGGED, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
+ pushRiggedMaskBatches(LLRenderPass::PASS_ALPHA_MASK_RIGGED, true, true);
}
// grass drawpool
@@ -360,7 +358,7 @@ void LLDrawPoolGrass::beginRenderPass(S32 pass)
else
{
gGL.flush();
- LLGLSLShader::bindNoShader();
+ LLGLSLShader::unbind();
}
}
@@ -453,15 +451,14 @@ void LLDrawPoolFullbright::renderPostDeferred(S32 pass)
}
gGL.setSceneBlendType(LLRender::BT_ALPHA);
- U32 fullbright_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXTURE_INDEX;
// render static
setup_fullbright_shader(shader);
- pushBatches(LLRenderPass::PASS_FULLBRIGHT, fullbright_mask, TRUE, TRUE);
+ pushBatches(LLRenderPass::PASS_FULLBRIGHT, true, true);
// render rigged
setup_fullbright_shader(shader->mRiggedVariant);
- pushRiggedBatches(LLRenderPass::PASS_FULLBRIGHT_RIGGED, fullbright_mask, TRUE, TRUE);
+ pushRiggedBatches(LLRenderPass::PASS_FULLBRIGHT_RIGGED, true, true);
}
void LLDrawPoolFullbright::render(S32 pass)
@@ -480,24 +477,21 @@ void LLDrawPoolFullbright::render(S32 pass)
shader = &gObjectFullbrightProgram;
}
-
- U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXTURE_INDEX;
-
// render static
setup_fullbright_shader(shader);
- pushBatches(LLRenderPass::PASS_FULLBRIGHT, mask, TRUE, TRUE);
- pushBatches(LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE, mask, TRUE, TRUE);
- pushBatches(LLRenderPass::PASS_SPECMAP_EMISSIVE, mask, TRUE, TRUE);
- pushBatches(LLRenderPass::PASS_NORMMAP_EMISSIVE, mask, TRUE, TRUE);
- pushBatches(LLRenderPass::PASS_NORMSPEC_EMISSIVE, mask, TRUE, TRUE);
+ pushBatches(LLRenderPass::PASS_FULLBRIGHT, true, true);
+ pushBatches(LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE, true, true);
+ pushBatches(LLRenderPass::PASS_SPECMAP_EMISSIVE, true, true);
+ pushBatches(LLRenderPass::PASS_NORMMAP_EMISSIVE, true, true);
+ pushBatches(LLRenderPass::PASS_NORMSPEC_EMISSIVE, true, true);
// render rigged
setup_fullbright_shader(shader->mRiggedVariant);
- pushRiggedBatches(LLRenderPass::PASS_FULLBRIGHT_RIGGED, mask, TRUE, TRUE);
- pushRiggedBatches(LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE_RIGGED, mask, TRUE, TRUE);
- pushRiggedBatches(LLRenderPass::PASS_SPECMAP_EMISSIVE_RIGGED, mask, TRUE, TRUE);
- pushRiggedBatches(LLRenderPass::PASS_NORMMAP_EMISSIVE_RIGGED, mask, TRUE, TRUE);
- pushRiggedBatches(LLRenderPass::PASS_NORMSPEC_EMISSIVE_RIGGED, mask, TRUE, TRUE);
+ pushRiggedBatches(LLRenderPass::PASS_FULLBRIGHT_RIGGED, true, true);
+ pushRiggedBatches(LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE_RIGGED, true, true);
+ pushRiggedBatches(LLRenderPass::PASS_SPECMAP_EMISSIVE_RIGGED, true, true);
+ pushRiggedBatches(LLRenderPass::PASS_NORMMAP_EMISSIVE_RIGGED, true, true);
+ pushRiggedBatches(LLRenderPass::PASS_NORMSPEC_EMISSIVE_RIGGED, true, true);
}
S32 LLDrawPoolFullbright::getNumPasses()
@@ -512,7 +506,7 @@ void LLDrawPoolFullbrightAlphaMask::renderPostDeferred(S32 pass)
LLGLSLShader* shader = nullptr;
if (LLPipeline::sRenderingHUDs)
{
- shader = &gObjectFullbrightAlphaMaskProgram;
+ shader = &gDeferredFullbrightAlphaMaskProgram;
}
else if (LLPipeline::sRenderDeferred)
{
@@ -531,14 +525,13 @@ void LLDrawPoolFullbrightAlphaMask::renderPostDeferred(S32 pass)
}
LLGLDisable blend(GL_BLEND);
- U32 fullbright_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXTURE_INDEX;
-
+
// render static
setup_fullbright_shader(shader);
- pushMaskBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, fullbright_mask, TRUE, TRUE);
+ pushMaskBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, true, true);
// render rigged
setup_fullbright_shader(shader->mRiggedVariant);
- pushRiggedMaskBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK_RIGGED, fullbright_mask, TRUE, TRUE);
+ pushRiggedMaskBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK_RIGGED, true, true);
}
diff --git a/indra/newview/lldrawpoolsky.cpp b/indra/newview/lldrawpoolsky.cpp
index 3a1efec91b..c39d728c95 100644
--- a/indra/newview/lldrawpoolsky.cpp
+++ b/indra/newview/lldrawpoolsky.cpp
@@ -51,7 +51,10 @@ LLDrawPoolSky::LLDrawPoolSky()
void LLDrawPoolSky::prerender()
{
mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT);
- gSky.mVOSkyp->updateGeometry(gSky.mVOSkyp->mDrawable);
+ if (gSky.mVOSkyp && gSky.mVOSkyp->mDrawable)
+ {
+ gSky.mVOSkyp->updateGeometry(gSky.mVOSkyp->mDrawable);
+ }
}
void LLDrawPoolSky::render(S32 pass)
@@ -81,8 +84,6 @@ void LLDrawPoolSky::render(S32 pass)
LLGLSPipelineDepthTestSkyBox gls_skybox(true, false);
- LLGLEnable fog_enable( (mShaderLevel < 1 && LLViewerCamera::getInstance()->cameraUnderWater()) ? GL_FOG : 0);
-
gGL.pushMatrix();
LLVector3 origin = LLViewerCamera::getInstance()->getOrigin();
gGL.translatef(origin.mV[0], origin.mV[1], origin.mV[2]);
@@ -109,20 +110,39 @@ void LLDrawPoolSky::renderSkyFace(U8 index)
return;
}
- if (index < 6) // sky tex...interp
+ if (index < LLVOSky::FACE_SUN) // sky tex...interp
{
llassert(mSkyTex);
mSkyTex[index].bindTexture(true); // bind the current tex
face->renderIndexed();
}
+ else // Moon
+ if (index == LLVOSky::FACE_MOON)
+ {
+ LLGLSPipelineDepthTestSkyBox gls_skybox(true, true); // SL-14113 Write depth for moon so stars can test if behind it
+
+ LLGLEnable blend(GL_BLEND);
+
+ // if (LLGLSLShader::sNoFixedFunction) // TODO: Necessary? is this always true? We already bailed on gPipeline.canUseWindLightShaders ... above
+ LLViewerTexture* tex = face->getTexture(LLRender::DIFFUSE_MAP);
+ if (tex)
+ {
+ gMoonProgram.bind(); // SL-14113 was gOneTextureNoColorProgram
+ gGL.getTexUnit(0)->bind(tex, true);
+ face->renderIndexed();
+ }
+ }
else // heavenly body faces, no interp...
{
+ LLGLSPipelineDepthTestSkyBox gls_skybox(true, false); // reset to previous
+
LLGLEnable blend(GL_BLEND);
LLViewerTexture* tex = face->getTexture(LLRender::DIFFUSE_MAP);
if (tex)
{
+ gOneTextureNoColorProgram.bind();
gGL.getTexUnit(0)->bind(tex, true);
face->renderIndexed();
}
diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp
index cc5cb667f0..64178f0a59 100644
--- a/indra/newview/lldrawpoolterrain.cpp
+++ b/indra/newview/lldrawpoolterrain.cpp
@@ -148,7 +148,7 @@ void LLDrawPoolTerrain::boostTerrainDetailTextures()
for (S32 i = 0; i < 4; i++)
{
compp->mDetailTextures[i]->setBoostLevel(LLGLTexture::BOOST_TERRAIN);
- compp->mDetailTextures[i]->addTextureStats(1024.f*1024.f); // assume large pixel area
+ compp->mDetailTextures[i]->addTextureStats(1024.f * 1024.f);
}
}
@@ -165,19 +165,6 @@ void LLDrawPoolTerrain::render(S32 pass)
LLOverrideFaceColor override(this, 1.f, 1.f, 1.f, 1.f);
- if (!gGLManager.mHasMultitexture)
- {
- // No multitexture, render simple land.
- renderSimple(); // Render without multitexture
- return;
- }
- // Render simplified land if video card can't do sufficient multitexturing
- if (!gGLManager.mHasARBEnvCombine || (gGLManager.mNumTextureUnits < 2))
- {
- renderSimple(); // Render without multitexture
- return;
- }
-
LLGLSPipeline gls;
if (mShaderLevel > 1 && sShader->mShaderLevel > 0)
@@ -194,10 +181,6 @@ void LLDrawPoolTerrain::render(S32 pass)
{
renderSimple();
}
- else if (gGLManager.mNumTextureUnits < 4)
- {
- renderFull2TU();
- }
else
{
renderFull4TU();
@@ -838,8 +821,7 @@ void LLDrawPoolTerrain::renderOwnership()
iter != mDrawFace.end(); iter++)
{
LLFace *facep = *iter;
- facep->renderIndexed(LLVertexBuffer::MAP_VERTEX |
- LLVertexBuffer::MAP_TEXCOORD0);
+ facep->renderIndexed();
}
gGL.matrixMode(LLRender::MM_TEXTURE);
diff --git a/indra/newview/lldrawpoolterrain.h b/indra/newview/lldrawpoolterrain.h
index 5b4558020d..e00e0c4720 100644
--- a/indra/newview/lldrawpoolterrain.h
+++ b/indra/newview/lldrawpoolterrain.h
@@ -33,14 +33,12 @@ class LLDrawPoolTerrain : public LLFacePool
{
LLPointer<LLViewerTexture> mTexturep;
public:
- enum
- {
- VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX |
- LLVertexBuffer::MAP_NORMAL |
- LLVertexBuffer::MAP_TEXCOORD0 |
- LLVertexBuffer::MAP_TEXCOORD1 |
- LLVertexBuffer::MAP_TEXCOORD2 |
- LLVertexBuffer::MAP_TEXCOORD3
+ enum
+ {
+ VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX |
+ LLVertexBuffer::MAP_NORMAL |
+ LLVertexBuffer::MAP_TEXCOORD0 |
+ LLVertexBuffer::MAP_TEXCOORD1
};
virtual U32 getVertexDataMask();
diff --git a/indra/newview/lldrawpooltree.cpp b/indra/newview/lldrawpooltree.cpp
index facfb235c9..61a8e20b54 100644
--- a/indra/newview/lldrawpooltree.cpp
+++ b/indra/newview/lldrawpooltree.cpp
@@ -93,7 +93,7 @@ void LLDrawPoolTree::render(S32 pass)
LLGLState test(GL_ALPHA_TEST, 0);
gGL.getTexUnit(sDiffTex)->bindFast(mTexturep);
- gPipeline.touchTexture(mTexturep, 1024.f * 1024.f); // <=== keep Linden tree textures at full res
+ mTexturep->addTextureStats(1024.f * 1024.f); // <=== keep Linden tree textures at full res
for (std::vector<LLFace*>::iterator iter = mDrawFace.begin();
iter != mDrawFace.end(); iter++)
@@ -117,8 +117,8 @@ void LLDrawPoolTree::render(S32 pass)
gPipeline.mMatrixOpCount++;
}
- buff->setBufferFast(LLDrawPoolTree::VERTEX_DATA_MASK);
- buff->drawRangeFast(LLRender::TRIANGLES, 0, buff->getNumVerts()-1, buff->getNumIndices(), 0);
+ buff->setBuffer();
+ buff->drawRange(LLRender::TRIANGLES, 0, buff->getNumVerts()-1, buff->getNumIndices(), 0);
}
}
}
diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp
index a84f62036e..cb3ef55edd 100644
--- a/indra/newview/lldrawpoolwater.cpp
+++ b/indra/newview/lldrawpoolwater.cpp
@@ -50,13 +50,13 @@
#include "llsettingssky.h"
#include "llsettingswater.h"
-BOOL deferred_render = FALSE;
-
BOOL LLDrawPoolWater::sSkipScreenCopy = FALSE;
BOOL LLDrawPoolWater::sNeedsReflectionUpdate = TRUE;
BOOL LLDrawPoolWater::sNeedsDistortionUpdate = TRUE;
F32 LLDrawPoolWater::sWaterFogEnd = 0.f;
+extern BOOL gCubeSnapshot;
+
LLDrawPoolWater::LLDrawPoolWater() : LLFacePool(POOL_WATER)
{
}
@@ -90,407 +90,72 @@ void LLDrawPoolWater::setNormalMaps(const LLUUID& normalMapId, const LLUUID& nex
mWaterNormp[1]->addTextureStats(1024.f*1024.f);
}
-//static
-void LLDrawPoolWater::restoreGL()
-{
- /*LLSettingsWater::ptr_t pwater = LLEnvironment::instance().getCurrentWater();
- if (pwater)
- {
- setTransparentTextures(pwater->getTransparentTextureID(), pwater->getNextTransparentTextureID());
- setOpaqueTexture(pwater->GetDefaultOpaqueTextureAssetId());
- setNormalMaps(pwater->getNormalMapID(), pwater->getNextNormalMapID());
- }*/
-}
-
void LLDrawPoolWater::prerender()
{
- mShaderLevel = (gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps) ? LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_WATER) : 0;
-}
-
-S32 LLDrawPoolWater::getNumPasses()
-{
- if (LLViewerCamera::getInstance()->getOrigin().mV[2] < 1024.f)
- {
- return 1;
- }
-
- return 0;
-}
-
-void LLDrawPoolWater::beginPostDeferredPass(S32 pass)
-{
- beginRenderPass(pass);
- deferred_render = TRUE;
-}
-
-void LLDrawPoolWater::endPostDeferredPass(S32 pass)
-{
- endRenderPass(pass);
- deferred_render = FALSE;
+ mShaderLevel = LLCubeMap::sUseCubeMaps ? LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_WATER) : 0;
}
-//===============================
-//DEFERRED IMPLEMENTATION
-//===============================
-void LLDrawPoolWater::renderDeferred(S32 pass)
+S32 LLDrawPoolWater::getNumPostDeferredPasses()
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; //LL_RECORD_BLOCK_TIME(FTM_RENDER_WATER);
-
- if (!LLPipeline::sRenderTransparentWater)
+ if (LLViewerCamera::getInstance()->getOrigin().mV[2] < 1024.f)
{
- // Will render opaque water without use of ALM
- render(pass);
- return;
+ return 1;
}
- deferred_render = TRUE;
- renderWater();
- deferred_render = FALSE;
+ return 0;
}
-//=========================================
-
-void LLDrawPoolWater::render(S32 pass)
-{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; //LL_RECORD_BLOCK_TIME(FTM_RENDER_WATER);
- if (mDrawFace.empty() || LLDrawable::getCurrentFrame() <= 1)
- {
- return;
- }
-
- //do a quick 'n dirty depth sort
- for (std::vector<LLFace*>::iterator iter = mDrawFace.begin();
- iter != mDrawFace.end(); iter++)
- {
- LLFace* facep = *iter;
- facep->mDistance = -facep->mCenterLocal.mV[2];
- }
-
- std::sort(mDrawFace.begin(), mDrawFace.end(), LLFace::CompareDistanceGreater());
-
- // See if we are rendering water as opaque or not
- if (!LLPipeline::sRenderTransparentWater)
- {
- // render water for low end hardware
- renderOpaqueLegacyWater();
- return;
- }
-
- LLGLEnable blend(GL_BLEND);
-
- if ((mShaderLevel > 0) && !sSkipScreenCopy)
- {
- renderWater();
- return;
- }
-
- LLVOSky *voskyp = gSky.mVOSkyp;
-
- stop_glerror();
-
- if (!gGLManager.mHasMultitexture)
- {
- // Ack! No multitexture! Bail!
- return;
- }
-
- LLFace* refl_face = voskyp->getReflFace();
-
- gPipeline.disableLights();
-
- LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
-
- LLGLDisable cullFace(GL_CULL_FACE);
-
- // Set up second pass first
- gGL.getTexUnit(1)->activate();
- gGL.getTexUnit(1)->enable(LLTexUnit::TT_TEXTURE);
- gGL.getTexUnit(1)->bind(mWaterImagep[0]) ;
-
- gGL.getTexUnit(2)->activate();
- gGL.getTexUnit(2)->enable(LLTexUnit::TT_TEXTURE);
- gGL.getTexUnit(2)->bind(mWaterImagep[1]) ;
-
- LLVector3 camera_up = LLViewerCamera::getInstance()->getUpAxis();
- F32 up_dot = camera_up * LLVector3::z_axis;
-
- LLColor4 water_color;
- if (LLViewerCamera::getInstance()->cameraUnderWater())
- {
- water_color.setVec(1.f, 1.f, 1.f, 0.4f);
- }
- else
- {
- water_color.setVec(1.f, 1.f, 1.f, 0.5f*(1.f + up_dot));
- }
-
- gGL.diffuseColor4fv(water_color.mV);
-
- // Automatically generate texture coords for detail map
- glEnable(GL_TEXTURE_GEN_S); //texture unit 1
- glEnable(GL_TEXTURE_GEN_T); //texture unit 1
- glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
- glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
-
- // Slowly move over time.
- F32 offset = fmod(gFrameTimeSeconds*2.f, 100.f);
- F32 tp0[4] = {16.f/256.f, 0.0f, 0.0f, offset*0.01f};
- F32 tp1[4] = {0.0f, 16.f/256.f, 0.0f, offset*0.01f};
- glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0);
- glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1);
-
- gGL.getTexUnit(0)->activate();
-
- glClearStencil(1);
- glClear(GL_STENCIL_BUFFER_BIT);
- LLGLEnable gls_stencil(GL_STENCIL_TEST);
- glStencilOp(GL_KEEP, GL_REPLACE, GL_KEEP);
- glStencilFunc(GL_ALWAYS, 0, 0xFFFFFFFF);
-
- for (std::vector<LLFace*>::iterator iter = mDrawFace.begin();
- iter != mDrawFace.end(); iter++)
- {
- LLFace *face = *iter;
- if (voskyp->isReflFace(face))
- {
- continue;
- }
- gGL.getTexUnit(0)->bind(face->getTexture());
- face->renderIndexed();
- }
-
- // Now, disable texture coord generation on texture state 1
- gGL.getTexUnit(1)->activate();
- gGL.getTexUnit(1)->unbind(LLTexUnit::TT_TEXTURE);
- gGL.getTexUnit(1)->disable();
-
- glDisable(GL_TEXTURE_GEN_S); //texture unit 1
- glDisable(GL_TEXTURE_GEN_T); //texture unit 1
-
- gGL.getTexUnit(2)->activate();
- gGL.getTexUnit(2)->unbind(LLTexUnit::TT_TEXTURE);
- gGL.getTexUnit(2)->disable();
-
- glDisable(GL_TEXTURE_GEN_S); //texture unit 1
- glDisable(GL_TEXTURE_GEN_T); //texture unit 1
-
- // Disable texture coordinate and color arrays
- gGL.getTexUnit(0)->activate();
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-
- stop_glerror();
-
- if (gSky.mVOSkyp->getCubeMap())
- {
- gSky.mVOSkyp->getCubeMap()->enable(0);
- gSky.mVOSkyp->getCubeMap()->bind();
-
- gGL.matrixMode(LLRender::MM_TEXTURE);
- gGL.loadIdentity();
- LLMatrix4 camera_mat = LLViewerCamera::getInstance()->getModelview();
- LLMatrix4 camera_rot(camera_mat.getMat3());
- camera_rot.invert();
-
- gGL.loadMatrix((F32 *)camera_rot.mMatrix);
-
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- LLOverrideFaceColor overrid(this, 1.f, 1.f, 1.f, 0.5f*up_dot);
-
- for (std::vector<LLFace*>::iterator iter = mDrawFace.begin();
- iter != mDrawFace.end(); iter++)
- {
- LLFace *face = *iter;
- if (voskyp->isReflFace(face))
- {
- //refl_face = face;
- continue;
- }
-
- if (face->getGeomCount() > 0)
- {
- face->renderIndexed();
- }
- }
-
- gSky.mVOSkyp->getCubeMap()->disable();
-
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
- gGL.matrixMode(LLRender::MM_TEXTURE);
- gGL.loadIdentity();
- gGL.matrixMode(LLRender::MM_MODELVIEW);
-
- }
-
- glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
-
- if (refl_face)
- {
- glStencilFunc(GL_NOTEQUAL, 0, 0xFFFFFFFF);
- renderReflection(refl_face);
- }
-}
-
-// for low end hardware
-void LLDrawPoolWater::renderOpaqueLegacyWater()
+void LLDrawPoolWater::beginPostDeferredPass(S32 pass)
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
- LLVOSky *voskyp = gSky.mVOSkyp;
+ LL_PROFILE_GPU_ZONE("water beginPostDeferredPass")
+ gGL.setColorMask(true, true);
- if (voskyp == NULL)
+ if (LLPipeline::sRenderTransparentWater)
{
- return;
- }
+ // copy framebuffer contents so far to a texture to be used for
+ // reflections and refractions
+ LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS);
- LLGLSLShader* shader = NULL;
- if (LLPipeline::sUnderWaterRender)
- {
- shader = &gObjectSimpleNonIndexedTexGenWaterProgram;
- }
- else
- {
- shader = &gObjectSimpleNonIndexedTexGenProgram;
- }
+ LLRenderTarget& src = gPipeline.mRT->screen;
+ LLRenderTarget& depth_src = gPipeline.mRT->deferredScreen;
+ LLRenderTarget& dst = gPipeline.mWaterDis;
- shader->bind();
+ dst.bindTarget();
+ gCopyDepthProgram.bind();
- stop_glerror();
+ S32 diff_map = gCopyDepthProgram.getTextureChannel(LLShaderMgr::DIFFUSE_MAP);
+ S32 depth_map = gCopyDepthProgram.getTextureChannel(LLShaderMgr::DEFERRED_DEPTH);
- // Depth sorting and write to depth buffer
- // since this is opaque, we should see nothing
- // behind the water. No blending because
- // of no transparency. And no face culling so
- // that the underside of the water is also opaque.
- LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE);
- LLGLDisable no_cull(GL_CULL_FACE);
- LLGLDisable no_blend(GL_BLEND);
+ gGL.getTexUnit(diff_map)->bind(&src);
+ gGL.getTexUnit(depth_map)->bind(&depth_src, true);
- gPipeline.disableLights();
+ gPipeline.mScreenTriangleVB->setBuffer();
+ gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
- // Activate the texture binding and bind one
- // texture since all images will have the same texture
- gGL.getTexUnit(0)->activate();
- gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
- gGL.getTexUnit(0)->bind(mOpaqueWaterImagep);
-
- // Automatically generate texture coords for water texture
- if (!shader)
- {
- glEnable(GL_TEXTURE_GEN_S); //texture unit 0
- glEnable(GL_TEXTURE_GEN_T); //texture unit 0
- glTexGenf(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
- glTexGenf(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
- }
-
- // Use the fact that we know all water faces are the same size
- // to save some computation
-
- // Slowly move texture coordinates over time so the watter appears
- // to be moving.
- F32 movement_period_secs = 50.f;
-
- F32 offset = fmod(gFrameTimeSeconds, movement_period_secs);
-
- if (movement_period_secs != 0)
- {
- offset /= movement_period_secs;
- }
- else
- {
- offset = 0;
- }
-
- F32 tp0[4] = { 16.f / 256.f, 0.0f, 0.0f, offset };
- F32 tp1[4] = { 0.0f, 16.f / 256.f, 0.0f, offset };
-
- if (!shader)
- {
- glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0);
- glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1);
- }
- else
- {
- shader->uniform4fv(LLShaderMgr::OBJECT_PLANE_S, 1, tp0);
- shader->uniform4fv(LLShaderMgr::OBJECT_PLANE_T, 1, tp1);
- }
-
- gGL.diffuseColor3f(1.f, 1.f, 1.f);
-
- for (std::vector<LLFace*>::iterator iter = mDrawFace.begin();
- iter != mDrawFace.end(); iter++)
- {
- LLFace *face = *iter;
- if (voskyp->isReflFace(face))
- {
- continue;
- }
-
- face->renderIndexed();
- }
-
- stop_glerror();
-
- if (!shader)
- {
- // Reset the settings back to expected values
- glDisable(GL_TEXTURE_GEN_S); //texture unit 0
- glDisable(GL_TEXTURE_GEN_T); //texture unit 0
- }
-
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-}
-
-
-void LLDrawPoolWater::renderReflection(LLFace* face)
-{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
- LLVOSky *voskyp = gSky.mVOSkyp;
-
- if (!voskyp)
- {
- return;
- }
-
- if (!face->getGeomCount())
- {
- return;
- }
-
- S8 dr = voskyp->getDrawRefl();
- if (dr < 0)
- {
- return;
- }
-
- LLGLSNoFog noFog;
-
- gGL.getTexUnit(0)->bind((dr == 0) ? voskyp->getSunTex() : voskyp->getMoonTex());
-
- LLOverrideFaceColor override(this, LLColor4(face->getFaceColor().mV));
- face->renderIndexed();
+ dst.flush();
+ }
}
-void LLDrawPoolWater::renderWater()
+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;
- LLEnvironment & environment = LLEnvironment::instance();
- LLSettingsWater::ptr_t pwater = environment.getCurrentWater();
- LLSettingsSky::ptr_t psky = environment.getCurrentSky();
+ LLEnvironment& environment = LLEnvironment::instance();
+ LLSettingsWater::ptr_t pwater = environment.getCurrentWater();
+ LLSettingsSky::ptr_t psky = environment.getCurrentSky();
LLVector3 light_dir = environment.getLightDirection();
bool sun_up = environment.getIsSunUp();
bool moon_up = environment.getIsMoonUp();
bool has_normal_mips = gSavedSettings.getBOOL("RenderWaterMipNormal");
bool underwater = LLViewerCamera::getInstance()->cameraUnderWater();
+ LLColor4 fog_color = LLColor4(pwater->getWaterFogColor(), 0.f);
+ LLColor3 fog_color_linear = linearColor3(fog_color);
if (sun_up)
{
@@ -508,56 +173,48 @@ void LLDrawPoolWater::renderWater()
F32 ground_proj_sq = light_dir.mV[0] * light_dir.mV[0] + light_dir.mV[1] * light_dir.mV[1];
light_exp = llmax(32.f, 256.f * powf(ground_proj_sq, 16.0f));
if (0.f < light_diffuse.normalize()) // Normalizing a color? Puzzling...
- {
+ {
light_diffuse *= (1.5f + (6.f * ground_proj_sq));
}
// set up normal maps filtering
for (auto norm_map : mWaterNormp)
- {
+ {
if (norm_map) norm_map->setFilteringOption(has_normal_mips ? LLTexUnit::TFO_ANISOTROPIC : LLTexUnit::TFO_POINT);
- }
+ }
LLColor4 specular(sun_up ? psky->getSunlightColor() : psky->getMoonlightColor());
F32 phase_time = (F32) LLFrameTimer::getElapsedSeconds() * 0.5f;
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 && LLPipeline::sWaterReflections)
+ 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;
}
}
- shader->bind();
- // 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();
- }
+ gPipeline.bindDeferredShader(*shader);
- // bind normal map
- S32 bumpTex = shader->enableTexture(LLViewerShaderMgr::BUMP_MAP);
+ //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();
@@ -567,12 +224,12 @@ void LLDrawPoolWater::renderWater()
if (tex_a && (!tex_b || (tex_a == tex_b)))
{
gGL.getTexUnit(bumpTex)->bind(tex_a);
- blend_factor = 0; // only one tex provided, no blending
+ 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
+ blend_factor = 0; // only one tex provided, no blending
}
else if (tex_b != tex_a)
{
@@ -581,25 +238,16 @@ void LLDrawPoolWater::renderWater()
}
// bind reflection texture from RenderTarget
- S32 screentex = shader->enableTexture(LLShaderMgr::WATER_SCREENTEX);
- F32 screenRes[] = {1.f / gGLViewport[2], 1.f / gGLViewport[3]};
+ S32 screentex = shader->enableTexture(LLShaderMgr::WATER_SCREENTEX);
+ S32 screenDepth = shader->enableTexture(LLShaderMgr::WATER_SCREENDEPTH);
- S32 diffTex = shader->enableTexture(LLShaderMgr::DIFFUSE_MAP);
+ F32 screenRes[] = { 1.f / gGLViewport[2], 1.f / gGLViewport[3] };
- // set uniforms for shader
- if (deferred_render)
- {
- 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);
- }
- }
+ S32 diffTex = shader->enableTexture(LLShaderMgr::DIFFUSE_MAP);
shader->uniform2fv(LLShaderMgr::DEFERRED_SCREEN_RES, 1, screenRes);
shader->uniform1f(LLShaderMgr::BLEND_FACTOR, blend_factor);
- LLColor4 fog_color(pwater->getWaterFogColor(), 0.0f);
F32 fog_density = pwater->getModifiedWaterFogDensity(underwater);
if (screentex > -1)
@@ -608,12 +256,17 @@ void LLDrawPoolWater::renderWater()
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);
}
- 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);
@@ -621,6 +274,7 @@ void LLDrawPoolWater::renderWater()
shader->uniform4fv(LLShaderMgr::SPECULAR_COLOR, 1, specular.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);
@@ -635,7 +289,7 @@ void LLDrawPoolWater::renderWater()
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 sunAngle = llmax(0.f, light_dir.mV[1]);
F32 scaledAngle = 1.f - sunAngle;
shader->uniform1i(LLShaderMgr::SUN_UP_FACTOR, sun_up ? 1 : 0);
@@ -644,8 +298,11 @@ void LLDrawPoolWater::renderWater()
shader->uniform1f(LLShaderMgr::WATER_SUN_ANGLE2, 0.1f + 0.2f * sunAngle);
shader->uniform1i(LLShaderMgr::WATER_EDGE_FACTOR, edge ? 1 : 0);
- LLVector4 rotated_light_direction = LLEnvironment::instance().getRotatedLightNorm();
- shader->uniform4fv(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);
if (LLViewerCamera::getInstance()->cameraUnderWater())
@@ -659,16 +316,16 @@ void LLDrawPoolWater::renderWater()
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<LLVOWater *>(face->getViewerObject());
+ water = static_cast<LLVOWater*>(face->getViewerObject());
if (!water) continue;
gGL.getTexUnit(diffTex)->bind(face->getTexture());
- if ((bool)edge == (bool) water->getIsEdgePatch())
+ if ((bool)edge == (bool)water->getIsEdgePatch())
{
face->renderIndexed();
@@ -689,22 +346,21 @@ void LLDrawPoolWater::renderWater()
shader->disableTexture(LLShaderMgr::WATER_SCREENDEPTH);
// clean up
- shader->unbind();
+ 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.getTexUnit(0)->activate();
+ gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
+
+ gGL.setColorMask(true, false);
}
LLViewerTexture *LLDrawPoolWater::getDebugTexture()
{
- return LLViewerFetchedTexture::sSmokeImagep;
+ return LLViewerTextureManager::getFetchedTexture(IMG_SMOKE);
}
LLColor3 LLDrawPoolWater::getDebugColor() const
diff --git a/indra/newview/lldrawpoolwater.h b/indra/newview/lldrawpoolwater.h
index 6f2fc3271d..3158b0a59b 100644
--- a/indra/newview/lldrawpoolwater.h
+++ b/indra/newview/lldrawpoolwater.h
@@ -35,7 +35,7 @@ class LLHeavenBody;
class LLWaterSurface;
class LLGLSLShader;
-class LLDrawPoolWater: public LLFacePool
+class LLDrawPoolWater final: public LLFacePool
{
protected:
LLPointer<LLViewerTexture> mWaterImagep[2];
@@ -56,29 +56,19 @@ public:
LLVertexBuffer::MAP_TEXCOORD0
};
- virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; }
+ virtual U32 getVertexDataMask() override { return VERTEX_DATA_MASK; }
LLDrawPoolWater();
/*virtual*/ ~LLDrawPoolWater();
- static void restoreGL();
-
- /*virtual*/ S32 getNumPostDeferredPasses() { return 0; } //getNumPasses(); }
- /*virtual*/ void beginPostDeferredPass(S32 pass);
- /*virtual*/ void endPostDeferredPass(S32 pass);
- /*virtual*/ void renderPostDeferred(S32 pass) { render(pass); }
- /*virtual*/ S32 getNumDeferredPasses() { return 1; }
- /*virtual*/ void renderDeferred(S32 pass = 0);
+ S32 getNumPostDeferredPasses() override;
+ void beginPostDeferredPass(S32 pass) override;
+ void renderPostDeferred(S32 pass) override;
- /*virtual*/ S32 getNumPasses();
- /*virtual*/ void render(S32 pass = 0);
- /*virtual*/ void prerender();
+ void prerender() override;
- /*virtual*/ LLViewerTexture *getDebugTexture();
- /*virtual*/ LLColor3 getDebugColor() const; // For AGP debug display
-
- void renderReflection(LLFace* face);
- void renderWater();
+ LLViewerTexture *getDebugTexture() override;
+ LLColor3 getDebugColor() const; // For AGP debug display
void setTransparentTextures(const LLUUID& transparentTextureId, const LLUUID& nextTransparentTextureId);
void setOpaqueTexture(const LLUUID& opaqueTextureId);
diff --git a/indra/newview/lldrawpoolwlsky.cpp b/indra/newview/lldrawpoolwlsky.cpp
index 9873846669..9fe1b64d3d 100644
--- a/indra/newview/lldrawpoolwlsky.cpp
+++ b/indra/newview/lldrawpoolwlsky.cpp
@@ -166,6 +166,11 @@ void LLDrawPoolWLSky::renderDome(const LLVector3& camPosLocal, F32 camHeightLoca
void LLDrawPoolWLSky::renderSkyHazeDeferred(const LLVector3& camPosLocal, F32 camHeightLocal) const
{
+ if (!gSky.mVOSkyp)
+ {
+ return;
+ }
+
LLVector3 const & origin = LLViewerCamera::getInstance()->getOrigin();
if (gPipeline.canUseWindLightShaders() && gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SKY))
@@ -266,18 +271,23 @@ void LLDrawPoolWLSky::renderStars(const LLVector3& camPosLocal) const
gGL.pushMatrix();
gGL.translatef(camPosLocal.mV[0], camPosLocal.mV[1], camPosLocal.mV[2]);
gGL.rotatef(gFrameTimeSeconds*0.01f, 0.f, 0.f, 1.f);
- gCustomAlphaProgram.bind();
- gCustomAlphaProgram.uniform1f(sCustomAlpha, star_alpha.mV[3]);
+ gStarsProgram.bind();
+ gStarsProgram.uniform1f(sCustomAlpha, star_alpha.mV[3]);
gSky.mVOWLSkyp->drawStars();
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
gGL.popMatrix();
- gCustomAlphaProgram.unbind();
-}
+ gStarsProgram.unbind(); // SL-14113 was gCustomAlphaProgram
+ }
void LLDrawPoolWLSky::renderStarsDeferred(const LLVector3& camPosLocal) const
{
+ if (!gSky.mVOSkyp)
+ {
+ return;
+ }
+
LLGLSPipelineBlendSkyBox gls_sky(true, false);
gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA);
@@ -319,6 +329,7 @@ void LLDrawPoolWLSky::renderStarsDeferred(const LLVector3& camPosLocal) const
gGL.pushMatrix();
gGL.translatef(camPosLocal.mV[0], camPosLocal.mV[1], camPosLocal.mV[2]);
+ gGL.rotatef(gFrameTimeSeconds*0.01f, 0.f, 0.f, 1.f);
gDeferredStarProgram.uniform1f(LLShaderMgr::BLEND_FACTOR, blend_factor);
if (LLPipeline::sReflectionRender)
@@ -343,7 +354,7 @@ void LLDrawPoolWLSky::renderStarsDeferred(const LLVector3& camPosLocal) const
void LLDrawPoolWLSky::renderSkyCloudsDeferred(const LLVector3& camPosLocal, F32 camHeightLocal, LLGLSLShader* cloudshader) const
{
- if (gPipeline.canUseWindLightShaders() && gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_CLOUDS) && gSky.mVOSkyp->getCloudNoiseTex())
+ if (gPipeline.canUseWindLightShaders() && gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_CLOUDS) && gSky.mVOSkyp && gSky.mVOSkyp->getCloudNoiseTex())
{
LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky();
@@ -397,7 +408,7 @@ void LLDrawPoolWLSky::renderSkyCloudsDeferred(const LLVector3& camPosLocal, F32
void LLDrawPoolWLSky::renderSkyClouds(const LLVector3& camPosLocal, F32 camHeightLocal, LLGLSLShader* cloudshader) const
{
- if (gPipeline.canUseWindLightShaders() && gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_CLOUDS) && gSky.mVOSkyp->getCloudNoiseTex())
+ if (gPipeline.canUseWindLightShaders() && gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_CLOUDS) && gSky.mVOSkyp && gSky.mVOSkyp->getCloudNoiseTex())
{
LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky();
@@ -451,11 +462,14 @@ void LLDrawPoolWLSky::renderSkyClouds(const LLVector3& camPosLocal, F32 camHeigh
void LLDrawPoolWLSky::renderHeavenlyBodies()
{
- LLGLSPipelineBlendSkyBox gls_skybox(true, false);
+ if (!gSky.mVOSkyp) return;
+
+ //LLGLSPipelineBlendSkyBox gls_skybox(true, false);
+ LLGLSPipelineBlendSkyBox gls_skybox(true, true); // SL-14113 we need moon to write to depth to clip stars behind
LLVector3 const & origin = LLViewerCamera::getInstance()->getOrigin();
gGL.pushMatrix();
- gGL.translatef(origin.mV[0], origin.mV[1], origin.mV[2]);
+ gGL.translatef(origin.mV[0], origin.mV[1], origin.mV[2]);
LLFace * face = gSky.mVOSkyp->mFace[LLVOSky::FACE_SUN];
@@ -547,7 +561,7 @@ void LLDrawPoolWLSky::renderHeavenlyBodies()
F32 moon_brightness = (float)psky->getMoonBrightness();
moon_shader->uniform1f(LLShaderMgr::MOON_BRIGHTNESS, moon_brightness);
- moon_shader->uniform4fv(LLShaderMgr::MOONLIGHT_COLOR, 1, gSky.mVOSkyp->getMoon().getColor().mV);
+ moon_shader->uniform3fv(LLShaderMgr::MOONLIGHT_COLOR, 1, gSky.mVOSkyp->getMoon().getColor().mV);
moon_shader->uniform4fv(LLShaderMgr::DIFFUSE_COLOR, 1, color.mV);
//moon_shader->uniform1f(LLShaderMgr::BLEND_FACTOR, blend_factor);
moon_shader->uniform3fv(LLShaderMgr::DEFERRED_MOON_DIR, 1, psky->getMoonDirection().mV); // shader: moon_dir
@@ -581,8 +595,8 @@ void LLDrawPoolWLSky::renderDeferred(S32 pass)
if (gPipeline.canUseWindLightShaders())
{
renderSkyHazeDeferred(origin, camHeightLocal);
- renderStarsDeferred(origin);
renderHeavenlyBodies();
+ renderStarsDeferred(origin);
renderSkyCloudsDeferred(origin, camHeightLocal, cloud_shader);
}
gGL.setColorMask(true, true);
@@ -600,8 +614,8 @@ void LLDrawPoolWLSky::render(S32 pass)
LLVector3 const & origin = LLViewerCamera::getInstance()->getOrigin();
renderSkyHaze(origin, camHeightLocal);
+ renderHeavenlyBodies();
renderStars(origin);
- renderHeavenlyBodies();
renderSkyClouds(origin, camHeightLocal, cloud_shader);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
diff --git a/indra/newview/lldynamictexture.cpp b/indra/newview/lldynamictexture.cpp
index 361a7666fa..7fdb3fbdaf 100644
--- a/indra/newview/lldynamictexture.cpp
+++ b/indra/newview/lldynamictexture.cpp
@@ -118,35 +118,10 @@ BOOL LLViewerDynamicTexture::render()
//-----------------------------------------------------------------------------
void LLViewerDynamicTexture::preRender(BOOL clear_depth)
{
- gPipeline.allocatePhysicsBuffer();
- if (!gNonInteractive)
- {
- llassert(mFullWidth <= static_cast<S32>(gPipeline.mPhysicsDisplay.getWidth()));
- llassert(mFullHeight <= static_cast<S32>(gPipeline.mPhysicsDisplay.getHeight()));
- }
-
- if (gPipeline.mPhysicsDisplay.isComplete() && !gGLManager.mIsAMD)
- { //using offscreen render target, just use the bottom left corner
- mOrigin.set(0, 0);
- }
- else
- { // force rendering to on-screen portion of frame buffer
- LLCoordScreen window_pos;
- gViewerWindow->getWindow()->getPosition( &window_pos );
- mOrigin.set(0, gViewerWindow->getWindowHeightRaw() - mFullHeight); // top left corner
-
- if (window_pos.mX < 0)
- {
- mOrigin.mX = -window_pos.mX;
- }
- if (window_pos.mY < 0)
- {
- mOrigin.mY += window_pos.mY;
- mOrigin.mY = llmax(mOrigin.mY, 0) ;
- }
- }
+ //use the bottom left corner
+ mOrigin.set(0, 0);
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
// Set up camera
LLViewerCamera* camera = LLViewerCamera::getInstance();
mCamera.setOrigin(*camera);
@@ -220,7 +195,7 @@ BOOL LLViewerDynamicTexture::updateAllInstances()
gPipeline.mBake.clear();
}
- LLGLSLShader::bindNoShader();
+ LLGLSLShader::unbind();
LLVertexBuffer::unbind();
BOOL result = FALSE;
diff --git a/indra/newview/llenvironment.cpp b/indra/newview/llenvironment.cpp
index 05c7decfbd..d88f0f9847 100644
--- a/indra/newview/llenvironment.cpp
+++ b/indra/newview/llenvironment.cpp
@@ -1629,28 +1629,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;
- }
- // update clouds, sun, and general
- updateCloudScroll();
+ 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);
- // 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();
- stop_glerror();
+ // cache this for use in rotating the rotated light vec for shader param updates later...
+ mLastCamYaw = cam->getYaw() + SUN_DELTA_YAW;
+ }
updateSettingsUniforms();
@@ -1727,8 +1730,19 @@ void LLEnvironment::updateGLVariablesForSettings(LLShaderUniforms* uniforms, con
//_WARNS("RIDER") << "pushing '" << (*it).first << "' as " << value << LL_ENDL;
break;
case LLSD::TypeReal:
- shader->uniform1f(it.second.getShaderKey(), value.asReal());
+ {
+ F32 v = value.asReal();
+ switch (it.second.getShaderKey())
+ { // convert to linear color space if this is a color parameter
+ case LLShaderMgr::HAZE_HORIZON:
+ case LLShaderMgr::HAZE_DENSITY:
+ case LLShaderMgr::CLOUD_SHADOW:
+ //v = sRGBtoLinear(v);
+ break;
+ }
+ shader->uniform1f(it.second.getShaderKey(), v);
//_WARNS("RIDER") << "pushing '" << (*it).first << "' as " << value << LL_ENDL;
+ }
break;
case LLSD::TypeBoolean:
@@ -1739,8 +1753,26 @@ void LLEnvironment::updateGLVariablesForSettings(LLShaderUniforms* uniforms, con
case LLSD::TypeArray:
{
LLVector4 vect4(value);
+
+ 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->uniform4fv(it.second.getShaderKey(), vect4 );
+ shader->uniform3fv(it.second.getShaderKey(), LLVector3(vect4.mV) );
break;
}
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index c3b3ccabb4..811f475705 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -192,7 +192,6 @@ void LLFace::destroy()
if (isState(LLFace::PARTICLE))
{
- LLVOPartGroup::freeVBSlot(getGeomIndex()/4);
clearState(LLFace::PARTICLE);
}
@@ -342,34 +341,6 @@ void LLFace::dirtyTexture()
gPipeline.markTextured(drawablep);
}
-void LLFace::notifyAboutCreatingTexture(LLViewerTexture *texture)
-{
- LLDrawable* drawablep = getDrawable();
- if(mVObjp.notNull() && mVObjp->getVolume())
- {
- LLVOVolume *vobj = drawablep->getVOVolume();
- if(vobj && vobj->notifyAboutCreatingTexture(texture))
- {
- gPipeline.markTextured(drawablep);
- gPipeline.markRebuild(drawablep, LLDrawable::REBUILD_VOLUME);
- }
- }
-}
-
-void LLFace::notifyAboutMissingAsset(LLViewerTexture *texture)
-{
- LLDrawable* drawablep = getDrawable();
- if(mVObjp.notNull() && mVObjp->getVolume())
- {
- LLVOVolume *vobj = drawablep->getVOVolume();
- if(vobj && vobj->notifyAboutMissingAsset(texture))
- {
- gPipeline.markTextured(drawablep);
- gPipeline.markRebuild(drawablep, LLDrawable::REBUILD_VOLUME);
- }
- }
-}
-
void LLFace::switchTexture(U32 ch, LLViewerTexture* new_texture)
{
llassert(ch < LLRender::NUM_TEXTURE_CHANNELS);
@@ -567,6 +538,7 @@ void LLFace::renderSelected(LLViewerTexture *imagep, const LLColor4& color)
if (mDrawablep->isState(LLDrawable::RIGGED))
{
+#if 0 // TODO -- there is no way this won't destroy our GL machine as implemented, rewrite it to not rely on software skinning
LLVOVolume* volume = mDrawablep->getVOVolume();
if (volume)
{
@@ -586,17 +558,17 @@ void LLFace::renderSelected(LLViewerTexture *imagep, const LLColor4& color)
glTexCoordPointer(2, GL_FLOAT, 8, vol_face.mTexCoords);
}
gGL.syncMatrices();
- LL_PROFILER_GPU_ZONEC( "gl.DrawElements", 0x00FF00 );
glDrawElements(GL_TRIANGLES, vol_face.mNumIndices, GL_UNSIGNED_SHORT, vol_face.mIndices);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
}
+#endif
}
else
{
// cheaters sometimes prosper...
//
- mVertexBuffer->setBuffer(mVertexBuffer->getTypeMask());
+ mVertexBuffer->setBuffer();
mVertexBuffer->draw(LLRender::TRIANGLES, mIndicesCount, mIndicesIndex);
}
@@ -644,14 +616,6 @@ void LLFace::renderOneWireframe(const LLColor4 &color, F32 fogCfx, bool wirefram
}
else
{
- LLGLEnable fog(GL_FOG);
- glFogi(GL_FOG_MODE, GL_LINEAR);
- float d = (LLViewerCamera::getInstance()->getPointOfInterest() - LLViewerCamera::getInstance()->getOrigin()).magVec();
- LLColor4 fogCol = color * fogCfx;
- glFogf(GL_FOG_START, d);
- glFogf(GL_FOG_END, d*(1 + (LLViewerCamera::getInstance()->getView() / LLViewerCamera::getInstance()->getDefaultFOV())));
- glFogfv(GL_FOG_COLOR, fogCol.mV);
-
gGL.flush();
{
gGL.diffuseColor4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], 0.4f);
@@ -667,7 +631,7 @@ void LLFace::renderOneWireframe(const LLColor4 &color, F32 fogCfx, bool wirefram
{
LLGLDisable depth(wireframe_selection ? 0 : GL_BLEND);
- LLGLEnable stencil(wireframe_selection ? 0 : GL_STENCIL_TEST);
+ //LLGLEnable stencil(wireframe_selection ? 0 : GL_STENCIL_TEST);
if (!wireframe_selection)
{ //modify wireframe into outline selection mode
@@ -683,54 +647,8 @@ void LLFace::renderOneWireframe(const LLColor4 &color, F32 fogCfx, bool wirefram
}
}
-/* removed in lieu of raycast uv detection
-void LLFace::renderSelectedUV()
-{
- LLViewerTexture* red_blue_imagep = LLViewerTextureManager::getFetchedTextureFromFile("uv_test1.j2c", TRUE, LLGLTexture::BOOST_UI);
- LLViewerTexture* green_imagep = LLViewerTextureManager::getFetchedTextureFromFile("uv_test2.tga", TRUE, LLGLTexture::BOOST_UI);
-
- LLGLSUVSelect object_select;
-
- // use red/blue gradient to get coarse UV coordinates
- renderSelected(red_blue_imagep, LLColor4::white);
-
- static F32 bias = 0.f;
- static F32 factor = -10.f;
- glPolygonOffset(factor, bias);
-
- // add green dither pattern on top of red/blue gradient
- gGL.blendFunc(LLRender::BF_ONE, LLRender::BF_ONE);
- gGL.matrixMode(LLRender::MM_TEXTURE);
- gGL.pushMatrix();
- // make green pattern repeat once per texel in red/blue texture
- gGL.scalef(256.f, 256.f, 1.f);
- gGL.matrixMode(LLRender::MM_MODELVIEW);
-
- renderSelected(green_imagep, LLColor4::white);
-
- gGL.matrixMode(LLRender::MM_TEXTURE);
- gGL.popMatrix();
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, LLRender::BF_ONE_MINUS_SOURCE_ALPHA);
-}
-*/
-
void LLFace::setDrawInfo(LLDrawInfo* draw_info)
{
- if (draw_info)
- {
- if (draw_info->mFace)
- {
- draw_info->mFace->setDrawInfo(NULL);
- }
- draw_info->mFace = this;
- }
-
- if (mDrawInfo)
- {
- mDrawInfo->mFace = NULL;
- }
-
mDrawInfo = draw_info;
}
@@ -1212,55 +1130,6 @@ bool LLFace::canRenderAsMask()
return false;
}
-
-//static
-void LLFace::cacheFaceInVRAM(const LLVolumeFace& vf)
-{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_FACE;
- U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 |
- LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_NORMAL;
-
- if (vf.mWeights)
- {
- mask |= LLVertexBuffer::MAP_WEIGHT4;
- }
-
- LLVertexBuffer* buff = new LLVertexBuffer(mask, GL_STATIC_DRAW_ARB);
- vf.mVertexBuffer = buff;
-
- buff->allocateBuffer(vf.mNumVertices, 0, true);
-
- LLStrider<LLVector4a> f_vert;
- LLStrider<LLVector4a> f_tangent;
- LLStrider<LLVector3> f_norm;
- LLStrider<LLVector2> f_tc;
-
- buff->getTangentStrider(f_tangent);
- buff->getVertexStrider(f_vert);
- buff->getNormalStrider(f_norm);
- buff->getTexCoord0Strider(f_tc);
-
- for (U32 i = 0; i < vf.mNumVertices; ++i)
- {
- *f_vert++ = vf.mPositions[i];
- *f_tangent++ = vf.mTangents[i];
- *f_tc++ = vf.mTexCoords[i];
- (*f_norm++).set(vf.mNormals[i].getF32ptr());
- }
-
- if (vf.mWeights)
- {
- LLStrider<LLVector4> f_wght;
- buff->getWeight4Strider(f_wght);
- for (U32 i = 0; i < vf.mNumVertices; ++i)
- {
- (*f_wght++).set(vf.mWeights[i].getF32ptr());
- }
- }
-
- buff->flush();
-}
-
//helper function for pushing primitives for transform shaders and cleaning up
//uninitialized data on the tail, plus tracking number of expected primitives
void push_for_transform(LLVertexBuffer* buff, U32 source_count, U32 dest_count)
@@ -1303,10 +1172,6 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
updateRebuildFlags();
}
-
- //don't use map range (generates many redundant unmap calls)
- bool map_range = false; //gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange;
-
if (mVertexBuffer.notNull())
{
if (num_indices + (S32) mIndicesIndex > mVertexBuffer->getNumIndices())
@@ -1384,10 +1249,15 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
LLColor4U color = tep->getColor();
+ if (tep->getGLTFRenderMaterial())
+ {
+ color = tep->getGLTFRenderMaterial()->mBaseColor;
+ }
+
if (rebuild_color)
{ //decide if shiny goes in alpha channel of color
if (tep &&
- getPoolType() != LLDrawPool::POOL_ALPHA) // <--- alpha channel MUST contain transparency, not shiny
+ !isInAlphaPool()) // <--- alpha channel MUST contain transparency, not shiny
{
LLMaterial* mat = tep->getMaterialParams().get();
@@ -1428,7 +1298,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
if (full_rebuild)
{
LL_PROFILE_ZONE_NAMED_CATEGORY_FACE("getGeometryVolume - indices");
- mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex, mIndicesCount, map_range);
+ mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex, mIndicesCount);
volatile __m128i* dst = (__m128i*) indicesp.get();
__m128i* src = (__m128i*) vf.mIndices;
@@ -1451,11 +1321,6 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
*idx++ = vf.mIndices[i]+index_offset;
}
}
-
- if (map_range)
- {
- mVertexBuffer->flush();
- }
}
F32 r = 0, os = 0, ot = 0, ms = 0, mt = 0, cos_ang = 0, sin_ang = 0;
@@ -1531,155 +1396,6 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
}
}
- static LLCachedControl<bool> use_transform_feedback(gSavedSettings, "RenderUseTransformFeedback", false);
-
-#ifdef GL_TRANSFORM_FEEDBACK_BUFFER
- if (use_transform_feedback &&
- mVertexBuffer->getUsage() == GL_DYNAMIC_COPY_ARB &&
- gTransformPositionProgram.mProgramObject && //transform shaders are loaded
- mVertexBuffer->useVBOs() && //target buffer is in VRAM
- !rebuild_weights && //TODO: add support for weights
- !volume.isUnique()) //source volume is NOT flexi
- { //use transform feedback to pack vertex buffer
-
- LL_PROFILE_ZONE_NAMED_CATEGORY_FACE("getGeometryVolume - transform feedback");
- LLGLEnable discard(GL_RASTERIZER_DISCARD);
- LLVertexBuffer* buff = (LLVertexBuffer*) vf.mVertexBuffer.get();
-
- if (vf.mVertexBuffer.isNull() || buff->getNumVerts() != vf.mNumVertices)
- {
- mVObjp->getVolume()->genTangents(f);
- LLFace::cacheFaceInVRAM(vf);
- buff = (LLVertexBuffer*) vf.mVertexBuffer.get();
- }
-
- LLGLSLShader* cur_shader = LLGLSLShader::sCurBoundShaderPtr;
-
- gGL.pushMatrix();
- gGL.loadMatrix((GLfloat*) mat_vert_in.mMatrix);
-
- if (rebuild_pos)
- {
- LL_PROFILE_ZONE_NAMED_CATEGORY_FACE("getGeometryVolume - tf position");
- gTransformPositionProgram.bind();
-
- mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_VERTEX, mGeomIndex, mGeomCount);
-
- U8 index = mTextureIndex < FACE_DO_NOT_BATCH_TEXTURES ? mTextureIndex : 0;
-
- S32 val = 0;
- U8* vp = (U8*) &val;
- vp[0] = index;
- vp[1] = 0;
- vp[2] = 0;
- vp[3] = 0;
-
- gTransformPositionProgram.uniform1i(sTextureIndexIn, val);
- glBeginTransformFeedback(GL_POINTS);
- buff->setBuffer(LLVertexBuffer::MAP_VERTEX);
-
- push_for_transform(buff, vf.mNumVertices, mGeomCount);
-
- glEndTransformFeedback();
- }
-
- if (rebuild_color)
- {
- LL_PROFILE_ZONE_NAMED_CATEGORY_FACE("getGeometryVolume - tf color");
- gTransformColorProgram.bind();
-
- mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_COLOR, mGeomIndex, mGeomCount);
-
- S32 val = *((S32*) color.mV);
-
- gTransformColorProgram.uniform1i(sColorIn, val);
- glBeginTransformFeedback(GL_POINTS);
- buff->setBuffer(LLVertexBuffer::MAP_VERTEX);
- push_for_transform(buff, vf.mNumVertices, mGeomCount);
- glEndTransformFeedback();
- }
-
- if (rebuild_emissive)
- {
- LL_PROFILE_ZONE_NAMED_CATEGORY_FACE("getGeometryVolume - tf emissive");
- gTransformColorProgram.bind();
-
- mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_EMISSIVE, mGeomIndex, mGeomCount);
-
- U8 glow = (U8) llclamp((S32) (getTextureEntry()->getGlow()*255), 0, 255);
-
- S32 glow32 = glow |
- (glow << 8) |
- (glow << 16) |
- (glow << 24);
-
- gTransformColorProgram.uniform1i(sColorIn, glow32);
- glBeginTransformFeedback(GL_POINTS);
- buff->setBuffer(LLVertexBuffer::MAP_VERTEX);
- push_for_transform(buff, vf.mNumVertices, mGeomCount);
- glEndTransformFeedback();
- }
-
- if (rebuild_normal)
- {
- LL_PROFILE_ZONE_NAMED_CATEGORY_FACE("getGeometryVolume - tf normal");
- gTransformNormalProgram.bind();
-
- mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_NORMAL, mGeomIndex, mGeomCount);
-
- glBeginTransformFeedback(GL_POINTS);
- buff->setBuffer(LLVertexBuffer::MAP_NORMAL);
- push_for_transform(buff, vf.mNumVertices, mGeomCount);
- glEndTransformFeedback();
- }
-
- if (rebuild_tangent)
- {
- LL_PROFILE_ZONE_NAMED_CATEGORY_FACE("getGeometryVolume - tf tangent");
- gTransformTangentProgram.bind();
-
- mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_TANGENT, mGeomIndex, mGeomCount);
-
- glBeginTransformFeedback(GL_POINTS);
- buff->setBuffer(LLVertexBuffer::MAP_TANGENT);
- push_for_transform(buff, vf.mNumVertices, mGeomCount);
- glEndTransformFeedback();
- }
-
- if (rebuild_tcoord)
- {
- LL_PROFILE_ZONE_NAMED_CATEGORY_FACE("getGeometryVolume - tf tcoord");
- gTransformTexCoordProgram.bind();
-
- mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_TEXCOORD0, mGeomIndex, mGeomCount);
-
- glBeginTransformFeedback(GL_POINTS);
- buff->setBuffer(LLVertexBuffer::MAP_TEXCOORD0);
- push_for_transform(buff, vf.mNumVertices, mGeomCount);
- glEndTransformFeedback();
-
- bool do_bump = bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1);
-
- if (do_bump)
- {
- mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_TEXCOORD1, mGeomIndex, mGeomCount);
- glBeginTransformFeedback(GL_POINTS);
- buff->setBuffer(LLVertexBuffer::MAP_TEXCOORD0);
- push_for_transform(buff, vf.mNumVertices, mGeomCount);
- glEndTransformFeedback();
- }
- }
-
- glBindBufferARB(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
- gGL.popMatrix();
-
- if (cur_shader)
- {
- cur_shader->bind();
- }
- }
- else
-#endif
{
//if it's not fullbright and has no normals, bake sunlight based on face normal
//bool bake_sunlight = !getTextureEntry()->getFullbright() &&
@@ -1793,10 +1509,17 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
scalea.load3(scale.mV);
LLMaterial* mat = tep->getMaterialParams().get();
+ LLGLTFMaterial* gltf_mat = tep->getGLTFRenderMaterial();
+
+ if (gltf_mat)
+ {
+ // Transforms will be applied later
+ do_xform = false;
+ }
bool do_bump = bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1);
- if (mat && !do_bump)
+ if ((mat || gltf_mat) && !do_bump)
{
do_bump = mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1)
|| mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD2);
@@ -1909,11 +1632,6 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
}
}
}
-
- if (map_range)
- {
- mVertexBuffer->flush();
- }
}
else
{ //bump mapped or has material, just do the whole expensive loop
@@ -1933,12 +1651,12 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
switch (ch)
{
case 0:
- mVertexBuffer->getTexCoord0Strider(dst, mGeomIndex, mGeomCount, map_range);
+ mVertexBuffer->getTexCoord0Strider(dst, mGeomIndex, mGeomCount);
break;
case 1:
if (mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1))
{
- mVertexBuffer->getTexCoord1Strider(dst, mGeomIndex, mGeomCount, map_range);
+ mVertexBuffer->getTexCoord1Strider(dst, mGeomIndex, mGeomCount);
if (mat && !tex_anim)
{
r = mat->getNormalRotation();
@@ -1958,7 +1676,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
case 2:
if (mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD2))
{
- mVertexBuffer->getTexCoord2Strider(dst, mGeomIndex, mGeomCount, map_range);
+ mVertexBuffer->getTexCoord2Strider(dst, mGeomIndex, mGeomCount);
if (mat && !tex_anim)
{
r = mat->getSpecularRotation();
@@ -2017,15 +1735,12 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
}
}
- if (map_range)
- {
- mVertexBuffer->flush();
- }
-
- if (!mat && do_bump)
+ if ((!mat && !gltf_mat) && do_bump)
{
- mVertexBuffer->getTexCoord1Strider(tex_coords1, mGeomIndex, mGeomCount, map_range);
+ mVertexBuffer->getTexCoord1Strider(tex_coords1, mGeomIndex, mGeomCount);
+ mVObjp->getVolume()->genTangents(f);
+
for (S32 i = 0; i < num_vertices; i++)
{
LLVector4a tangent = vf.mTangents[i];
@@ -2057,11 +1772,6 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
*tex_coords1++ = tc;
}
-
- if (map_range)
- {
- mVertexBuffer->flush();
- }
}
}
}
@@ -2077,7 +1787,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
llassert(num_vertices > 0);
- mVertexBuffer->getVertexStrider(vert, mGeomIndex, mGeomCount, map_range);
+ mVertexBuffer->getVertexStrider(vert, mGeomIndex, mGeomCount);
F32* dst = (F32*) vert.get();
@@ -2123,18 +1833,13 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
res0.store4a((F32*) dst);
dst += 4;
}
-
- if (map_range)
- {
- mVertexBuffer->flush();
- }
}
if (rebuild_normal)
{
LL_PROFILE_ZONE_NAMED_CATEGORY_FACE("getGeometryVolume - normal");
- mVertexBuffer->getNormalStrider(norm, mGeomIndex, mGeomCount, map_range);
+ mVertexBuffer->getNormalStrider(norm, mGeomIndex, mGeomCount);
F32* normals = (F32*) norm.get();
LLVector4a* src = vf.mNormals;
LLVector4a* end = src+num_vertices;
@@ -2146,62 +1851,47 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
normal.store4a(normals);
normals += 4;
}
-
- if (map_range)
- {
- mVertexBuffer->flush();
- }
}
if (rebuild_tangent)
{
LL_PROFILE_ZONE_NAMED_CATEGORY_FACE("getGeometryVolume - tangent");
- mVertexBuffer->getTangentStrider(tangent, mGeomIndex, mGeomCount, map_range);
+ mVertexBuffer->getTangentStrider(tangent, mGeomIndex, mGeomCount);
F32* tangents = (F32*) tangent.get();
- mVObjp->getVolume()->genTangents(f);
+ mVObjp->getVolume()->genTangents(f);
LLVector4Logical mask;
mask.clear();
mask.setElement<3>();
LLVector4a* src = vf.mTangents;
- LLVector4a* end = vf.mTangents+num_vertices;
+ LLVector4a* end = vf.mTangents +num_vertices;
while (src < end)
{
LLVector4a tangent_out;
mat_normal.rotate(*src, tangent_out);
- tangent_out.normalize3fast();
tangent_out.setSelectWithMask(mask, *src, tangent_out);
tangent_out.store4a(tangents);
src++;
tangents += 4;
}
-
- if (map_range)
- {
- mVertexBuffer->flush();
- }
}
if (rebuild_weights && vf.mWeights)
{
LL_PROFILE_ZONE_NAMED_CATEGORY_FACE("getGeometryVolume - weight");
- mVertexBuffer->getWeight4Strider(wght, mGeomIndex, mGeomCount, map_range);
+ mVertexBuffer->getWeight4Strider(wght, mGeomIndex, mGeomCount);
F32* weights = (F32*) wght.get();
LLVector4a::memcpyNonAliased16(weights, (F32*) vf.mWeights, num_vertices*4*sizeof(F32));
- if (map_range)
- {
- mVertexBuffer->flush();
- }
}
if (rebuild_color && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_COLOR) )
{
LL_PROFILE_ZONE_NAMED_CATEGORY_FACE("getGeometryVolume - color");
- mVertexBuffer->getColorStrider(colors, mGeomIndex, mGeomCount, map_range);
+ mVertexBuffer->getColorStrider(colors, mGeomIndex, mGeomCount);
LLVector4a src;
@@ -2222,18 +1912,13 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
src.store4a(dst);
dst += 4;
}
-
- if (map_range)
- {
- mVertexBuffer->flush();
- }
}
if (rebuild_emissive)
{
LL_PROFILE_ZONE_NAMED_CATEGORY_FACE("getGeometryVolume - emissive");
LLStrider<LLColor4U> emissive;
- mVertexBuffer->getEmissiveStrider(emissive, mGeomIndex, mGeomCount, map_range);
+ mVertexBuffer->getEmissiveStrider(emissive, mGeomIndex, mGeomCount);
U8 glow = (U8) llclamp((S32) (getTextureEntry()->getGlow()*255), 0, 255);
@@ -2261,11 +1946,6 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
src.store4a(dst);
dst += 4;
}
-
- if (map_range)
- {
- mVertexBuffer->flush();
- }
}
}
@@ -2288,6 +1968,15 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
return TRUE;
}
+void LLFace::renderIndexed()
+{
+ if (mVertexBuffer.notNull())
+ {
+ mVertexBuffer->setBuffer();
+ mVertexBuffer->drawRange(LLRender::TRIANGLES, getGeomIndex(), getGeomIndex() + getGeomCount()-1, getIndicesCount(), getIndicesStart());
+ }
+}
+
//check if the face has a media
BOOL LLFace::hasMedia() const
{
@@ -2314,6 +2003,7 @@ void LLFace::resetVirtualSize()
F32 LLFace::getTextureVirtualSize()
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
F32 radius;
F32 cos_angle_to_view_dir;
BOOL in_frustum = calcPixelArea(cos_angle_to_view_dir, radius);
@@ -2618,97 +2308,12 @@ void LLFace::setViewerObject(LLViewerObject* objp)
mVObjp = objp;
}
-const LLColor4& LLFace::getRenderColor() const
-{
- if (isState(USE_FACE_COLOR))
- {
- return mFaceColor; // Face Color
- }
- else
- {
- const LLTextureEntry* tep = getTextureEntry();
- return (tep ? tep->getColor() : LLColor4::white);
- }
-}
-
-void LLFace::renderSetColor() const
-{
- if (!LLFacePool::LLOverrideFaceColor::sOverrideFaceColor)
- {
- const LLColor4* color = &(getRenderColor());
-
- gGL.diffuseColor4fv(color->mV);
- }
-}
-
-S32 LLFace::pushVertices(const U16* index_array) const
-{
- if (mIndicesCount)
- {
- U32 render_type = LLRender::TRIANGLES;
- if (mDrawInfo)
- {
- render_type = mDrawInfo->mDrawMode;
- }
- mVertexBuffer->drawRange(render_type, mGeomIndex, mGeomIndex+mGeomCount-1, mIndicesCount, mIndicesIndex);
- gPipeline.addTrianglesDrawn(mIndicesCount, render_type);
- }
-
- return mIndicesCount;
-}
const LLMatrix4& LLFace::getRenderMatrix() const
{
return mDrawablep->getRenderMatrix();
}
-S32 LLFace::renderElements(const U16 *index_array) const
-{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_FACE
-
- S32 ret = 0;
-
- if (isState(GLOBAL))
- {
- ret = pushVertices(index_array);
- }
- else
- {
- gGL.pushMatrix();
- gGL.multMatrix((float*)getRenderMatrix().mMatrix);
- ret = pushVertices(index_array);
- gGL.popMatrix();
- }
-
- return ret;
-}
-
-S32 LLFace::renderIndexed()
-{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_FACE
-
- if(mDrawablep == NULL || mDrawPoolp == NULL)
- {
- return 0;
- }
-
- return renderIndexed(mDrawPoolp->getVertexDataMask());
-}
-
-S32 LLFace::renderIndexed(U32 mask)
-{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_FACE
-
- if (mVertexBuffer.isNull())
- {
- return 0;
- }
-
- mVertexBuffer->setBuffer(mask);
- U16* index_array = (U16*) mVertexBuffer->getIndicesPointer();
- return renderElements(index_array);
-}
-
//============================================================================
// From llface.inl
@@ -2792,3 +2397,10 @@ U64 LLFace::getSkinHash()
{
return mSkinInfo ? mSkinInfo->mHash : 0;
}
+
+bool LLFace::isInAlphaPool() const
+{
+ return getPoolType() == LLDrawPool::POOL_ALPHA ||
+ getPoolType() == LLDrawPool::POOL_ALPHA_PRE_WATER ||
+ getPoolType() == LLDrawPool::POOL_ALPHA_POST_WATER;
+}
diff --git a/indra/newview/llface.h b/indra/newview/llface.h
index aa00c9d052..ee8316018b 100644
--- a/indra/newview/llface.h
+++ b/indra/newview/llface.h
@@ -81,8 +81,6 @@ public:
PARTICLE = 0x0080,
};
- static void cacheFaceInVRAM(const LLVolumeFace& vf);
-
public:
LLFace(LLDrawable* drawablep, LLViewerObject* objp)
{
@@ -127,12 +125,6 @@ public:
S32 getIndexInTex(U32 ch) const {llassert(ch < LLRender::NUM_TEXTURE_CHANNELS); return mIndexInTex[ch];}
void setIndexInTex(U32 ch, S32 index) { llassert(ch < LLRender::NUM_TEXTURE_CHANNELS); mIndexInTex[ch] = index ;}
-
- void renderSetColor() const;
- S32 renderElements(const U16 *index_array) const;
- S32 renderIndexed ();
- S32 renderIndexed (U32 mask);
- S32 pushVertices(const U16* index_array) const;
void setWorldMatrix(const LLMatrix4& mat);
const LLTextureEntry* getTextureEntry() const { return mVObjp->getTE(mTEOffset); }
@@ -153,11 +145,12 @@ public:
void setDrawable(LLDrawable *drawable);
void setTEOffset(const S32 te_offset);
+ void renderIndexed();
void setFaceColor(const LLColor4& color); // override material color
void unsetFaceColor(); // switch back to material color
const LLColor4& getFaceColor() const { return mFaceColor; }
- const LLColor4& getRenderColor() const;
+
//for volumes
void updateRebuildFlags();
@@ -230,15 +223,14 @@ public:
LLVertexBuffer* getVertexBuffer() const { return mVertexBuffer; }
S32 getRiggedIndex(U32 type) const;
- void notifyAboutCreatingTexture(LLViewerTexture *texture);
- void notifyAboutMissingAsset(LLViewerTexture *texture);
-
// used to preserve draw order of faces that are batched together.
// Allows content creators to manipulate linked sets and face ordering
// for consistent alpha sorting results, particularly for rigged attachments
void setDrawOrderIndex(U32 index) { mDrawOrderIndex = index; }
U32 getDrawOrderIndex() const { return mDrawOrderIndex; }
+ // return true if this face is in an alpha draw pool
+ bool isInAlphaPool() const;
public: //aligned members
LLVector4a mExtents[2];
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/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp
index e934041e2e..3b1bee05af 100644
--- a/indra/newview/llfeaturemanager.cpp
+++ b/indra/newview/llfeaturemanager.cpp
@@ -431,41 +431,9 @@ bool LLFeatureManager::loadGPUClass()
LL_WARNS("RenderInit") << "Unable to get an accurate benchmark; defaulting to class 3" << LL_ENDL;
mGPUClass = GPU_CLASS_3;
#else
- if (gGLManager.mGLVersion <= 2.f)
- {
- mGPUClass = GPU_CLASS_0;
- }
- else if (gGLManager.mGLVersion <= 3.f)
- {
- mGPUClass = GPU_CLASS_1;
- }
- else if (gGLManager.mGLVersion < 3.3f)
- {
- mGPUClass = GPU_CLASS_2;
- }
- else if (gGLManager.mGLVersion < 4.f)
- {
- mGPUClass = GPU_CLASS_3;
- }
- else
- {
- mGPUClass = GPU_CLASS_4;
- }
- if (gGLManager.mIsIntel && mGPUClass > GPU_CLASS_1)
- {
- // Intels are generally weaker then other GPUs despite having advanced features
- mGPUClass = (EGPUClass)(mGPUClass - 1);
- }
+ mGPUClass = GPU_CLASS_2;
#endif
}
- else if (gGLManager.mGLVersion <= 2.f)
- {
- mGPUClass = GPU_CLASS_0;
- }
- else if (gGLManager.mGLVersion <= 3.f)
- {
- mGPUClass = GPU_CLASS_1;
- }
else if (gbps <= 5.f)
{
mGPUClass = GPU_CLASS_0;
@@ -607,7 +575,7 @@ void LLFeatureManager::applyFeatures(bool skipFeatures)
void LLFeatureManager::setGraphicsLevel(U32 level, bool skipFeatures)
{
LLViewerShaderMgr::sSkipReload = true;
-
+ flush_glerror(); // Whatever may have already happened (e.g., to cause us to change), don't let confuse it with new initializations.
applyBaseMasks();
// if we're passed an invalid level, default to "Low"
@@ -679,22 +647,18 @@ void LLFeatureManager::applyBaseMasks()
{
maskFeatures("TexUnit8orLess");
}
- if (gGLManager.mHasMapBufferRange)
- {
- maskFeatures("MapBufferRange");
- }
if (gGLManager.mVRAM > 512)
{
maskFeatures("VRAMGT512");
}
-
-#if LL_DARWIN
- const LLOSInfo& osInfo = LLOSInfo::instance();
- if (osInfo.mMajorVer == 10 && osInfo.mMinorVer < 7)
- {
- maskFeatures("OSX_10_6_8");
- }
-#endif
+ if (gGLManager.mVRAM < 2048)
+ {
+ maskFeatures("VRAMLT2GB");
+ }
+ if (gGLManager.mGLVersion < 3.99f)
+ {
+ maskFeatures("GL3");
+ }
// now mask by gpu string
// Replaces ' ' with '_' in mGPUString to deal with inability for parser to handle spaces
diff --git a/indra/newview/llfetchedgltfmaterial.cpp b/indra/newview/llfetchedgltfmaterial.cpp
new file mode 100644
index 0000000000..047f1a4965
--- /dev/null
+++ b/indra/newview/llfetchedgltfmaterial.cpp
@@ -0,0 +1,149 @@
+/**
+ * @file llfetchedgltfmaterial.cpp
+ *
+ * $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$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llfetchedgltfmaterial.h"
+
+#include "llviewertexturelist.h"
+#include "llavatarappearancedefines.h"
+#include "llshadermgr.h"
+#include "pipeline.h"
+
+LLFetchedGLTFMaterial::LLFetchedGLTFMaterial()
+ : LLGLTFMaterial()
+ , mExpectedFlusTime(0.f)
+ , mActive(true)
+ , mFetching(false)
+{
+
+}
+
+LLFetchedGLTFMaterial::~LLFetchedGLTFMaterial()
+{
+
+}
+
+void LLFetchedGLTFMaterial::bind()
+{
+ // glTF 2.0 Specification 3.9.4. Alpha Coverage
+ // mAlphaCutoff is only valid for LLGLTFMaterial::ALPHA_MODE_MASK
+ F32 min_alpha = -1.0;
+
+ LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
+
+ if (mAlphaMode == LLGLTFMaterial::ALPHA_MODE_MASK)
+ {
+ min_alpha = mAlphaCutoff;
+ }
+ shader->uniform1f(LLShaderMgr::MINIMUM_ALPHA, min_alpha);
+
+ if (mBaseColorTexture.notNull())
+ {
+ gGL.getTexUnit(0)->bindFast(mBaseColorTexture);
+ }
+ else
+ {
+ gGL.getTexUnit(0)->bindFast(LLViewerFetchedTexture::sWhiteImagep);
+ }
+
+ if (!LLPipeline::sShadowRender)
+ {
+ if (mNormalTexture.notNull())
+ {
+ shader->bindTexture(LLShaderMgr::BUMP_MAP, mNormalTexture);
+ }
+ else
+ {
+ shader->bindTexture(LLShaderMgr::BUMP_MAP, LLViewerFetchedTexture::sFlatNormalImagep);
+ }
+
+ if (mMetallicRoughnessTexture.notNull())
+ {
+ shader->bindTexture(LLShaderMgr::SPECULAR_MAP, mMetallicRoughnessTexture); // PBR linear packed Occlusion, Roughness, Metal.
+ }
+ else
+ {
+ shader->bindTexture(LLShaderMgr::SPECULAR_MAP, LLViewerFetchedTexture::sWhiteImagep);
+ }
+
+ if (mEmissiveTexture.notNull())
+ {
+ shader->bindTexture(LLShaderMgr::EMISSIVE_MAP, mEmissiveTexture); // PBR sRGB Emissive
+ }
+ else
+ {
+ shader->bindTexture(LLShaderMgr::EMISSIVE_MAP, LLViewerFetchedTexture::sWhiteImagep);
+ }
+
+ // NOTE: base color factor is baked into vertex stream
+
+ shader->uniform1f(LLShaderMgr::ROUGHNESS_FACTOR, mRoughnessFactor);
+ shader->uniform1f(LLShaderMgr::METALLIC_FACTOR, mMetallicFactor);
+ shader->uniform3fv(LLShaderMgr::EMISSIVE_COLOR, 1, mEmissiveColor.mV);
+
+ const LLMatrix3 base_color_matrix = mTextureTransform[GLTF_TEXTURE_INFO_BASE_COLOR].asMatrix();
+ shader->uniformMatrix3fv(LLShaderMgr::TEXTURE_BASECOLOR_MATRIX, 1, false, (F32*)base_color_matrix.mMatrix);
+ const LLMatrix3 normal_matrix = mTextureTransform[GLTF_TEXTURE_INFO_NORMAL].asMatrix();
+ shader->uniformMatrix3fv(LLShaderMgr::TEXTURE_NORMAL_MATRIX, 1, false, (F32*)normal_matrix.mMatrix);
+ const LLMatrix3 metallic_roughness_matrix = mTextureTransform[GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS].asMatrix();
+ shader->uniformMatrix3fv(LLShaderMgr::TEXTURE_METALLIC_ROUGHNESS_MATRIX, 1, false, (F32*)metallic_roughness_matrix.mMatrix);
+ const LLMatrix3 emissive_matrix = mTextureTransform[GLTF_TEXTURE_INFO_EMISSIVE].asMatrix();
+ shader->uniformMatrix3fv(LLShaderMgr::TEXTURE_EMISSIVE_MATRIX, 1, false, (F32*)emissive_matrix.mMatrix);
+ }
+
+}
+
+void LLFetchedGLTFMaterial::materialBegin()
+{
+ llassert(!mFetching);
+ mFetching = true;
+}
+
+void LLFetchedGLTFMaterial::onMaterialComplete(std::function<void()> 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<void()> material_complete : materialCompleteCallbacks)
+ {
+ material_complete();
+ }
+ materialCompleteCallbacks.clear();
+ materialCompleteCallbacks.shrink_to_fit();
+}
diff --git a/indra/newview/llfetchedgltfmaterial.h b/indra/newview/llfetchedgltfmaterial.h
new file mode 100644
index 0000000000..f784f19c4f
--- /dev/null
+++ b/indra/newview/llfetchedgltfmaterial.h
@@ -0,0 +1,65 @@
+/**
+ * @file llfetchedgltfmaterial.h
+ *
+ * $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$
+ */
+
+
+#pragma once
+
+#include "llgltfmaterial.h"
+#include "llpointer.h"
+#include "llviewertexture.h"
+
+class LLGLSLShader;
+
+class LLFetchedGLTFMaterial: public LLGLTFMaterial
+{
+ friend class LLGLTFMaterialList; // for lifetime management
+public:
+ LLFetchedGLTFMaterial();
+ virtual ~LLFetchedGLTFMaterial();
+
+ // If this material is loaded, fire the given function
+ void onMaterialComplete(std::function<void()> material_complete);
+
+ // bind this material for rendering
+ void bind();
+
+ // Textures used for fetching/rendering
+ LLPointer<LLViewerFetchedTexture> mBaseColorTexture;
+ LLPointer<LLViewerFetchedTexture> mNormalTexture;
+ LLPointer<LLViewerFetchedTexture> mMetallicRoughnessTexture;
+ LLPointer<LLViewerFetchedTexture> mEmissiveTexture;
+
+protected:
+ // Lifetime management
+
+ void materialBegin();
+ void materialComplete();
+
+ F64 mExpectedFlusTime; // since epoch in seconds
+ bool mActive;
+ bool mFetching;
+ std::vector<std::function<void()>> materialCompleteCallbacks;
+};
+
diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp
index e3a695fc79..29e8210d8e 100644
--- a/indra/newview/llfilepicker.cpp
+++ b/indra/newview/llfilepicker.cpp
@@ -55,13 +55,13 @@ LLFilePicker LLFilePicker::sInstance;
#define IMAGE_FILTER L"Images (*.tga; *.bmp; *.jpg; *.jpeg; *.png)\0*.tga;*.bmp;*.jpg;*.jpeg;*.png\0"
#define ANIM_FILTER L"Animations (*.bvh; *.anim)\0*.bvh;*.anim\0"
#define COLLADA_FILTER L"Scene (*.dae)\0*.dae\0"
-#ifdef _CORY_TESTING
-#define GEOMETRY_FILTER L"SL Geometry (*.slg)\0*.slg\0"
-#endif
+#define GLTF_FILTER L"glTF (*.gltf; *.glb)\0*.gltf;*.glb\0"
#define XML_FILTER L"XML files (*.xml)\0*.xml\0"
#define SLOBJECT_FILTER L"Objects (*.slobject)\0*.slobject\0"
#define RAW_FILTER L"RAW files (*.raw)\0*.raw\0"
#define MODEL_FILTER L"Model files (*.dae)\0*.dae\0"
+#define MATERIAL_FILTER L"GLTF Files (*.gltf; *.glb)\0*.gltf;*.glb\0"
+#define MATERIAL_TEXTURES_FILTER L"GLTF Import (*.gltf; *.glb; *.tga; *.bmp; *.jpg; *.jpeg; *.png)\0*.gltf;*.glb;*.tga;*.bmp;*.jpg;*.jpeg;*.png\0"
#define SCRIPT_FILTER L"Script files (*.lsl)\0*.lsl\0"
#define DICTIONARY_FILTER L"Dictionary files (*.dic; *.xcu)\0*.dic;*.xcu\0"
#endif
@@ -179,6 +179,7 @@ BOOL LLFilePicker::setupFilter(ELoadFilter filter)
SOUND_FILTER \
IMAGE_FILTER \
ANIM_FILTER \
+ MATERIAL_FILTER \
L"\0";
break;
case FFLOAD_WAV:
@@ -193,16 +194,14 @@ BOOL LLFilePicker::setupFilter(ELoadFilter filter)
mOFN.lpstrFilter = ANIM_FILTER \
L"\0";
break;
- case FFLOAD_COLLADA:
+ case FFLOAD_GLTF:
+ mOFN.lpstrFilter = GLTF_FILTER \
+ L"\0";
+ break;
+ case FFLOAD_COLLADA:
mOFN.lpstrFilter = COLLADA_FILTER \
L"\0";
break;
-#ifdef _CORY_TESTING
- case FFLOAD_GEOMETRY:
- mOFN.lpstrFilter = GEOMETRY_FILTER \
- L"\0";
- break;
-#endif
case FFLOAD_XML:
mOFN.lpstrFilter = XML_FILTER \
L"\0";
@@ -219,6 +218,16 @@ BOOL LLFilePicker::setupFilter(ELoadFilter filter)
mOFN.lpstrFilter = MODEL_FILTER \
L"\0";
break;
+ case FFLOAD_MATERIAL:
+ mOFN.lpstrFilter = MATERIAL_FILTER \
+ L"\0";
+ break;
+ case FFLOAD_MATERIAL_TEXTURE:
+ mOFN.lpstrFilter = MATERIAL_TEXTURES_FILTER \
+ MATERIAL_FILTER \
+ IMAGE_FILTER \
+ L"\0";
+ break;
case FFLOAD_SCRIPT:
mOFN.lpstrFilter = SCRIPT_FILTER \
L"\0";
@@ -480,18 +489,16 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename,
L"XAF Anim File (*.xaf)\0*.xaf\0" \
L"\0";
break;
-#ifdef _CORY_TESTING
- case FFSAVE_GEOMETRY:
+ case FFSAVE_GLTF:
if (filename.empty())
{
- wcsncpy( mFilesW,L"untitled.slg", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
+ wcsncpy( mFilesW,L"untitled.glb", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
}
- mOFN.lpstrDefExt = L"slg";
+ mOFN.lpstrDefExt = L"glb";
mOFN.lpstrFilter =
- L"SLG SL Geometry File (*.slg)\0*.slg\0" \
+ L"glTF Asset File (*.gltf *.glb)\0*.gltf;*.glb\0" \
L"\0";
break;
-#endif
case FFSAVE_XML:
if (filename.empty())
{
@@ -601,6 +608,8 @@ std::unique_ptr<std::vector<std::string>> LLFilePicker::navOpenFilterProc(ELoadF
allowedv->push_back("dic");
allowedv->push_back("xcu");
allowedv->push_back("gif");
+ allowedv->push_back("gltf");
+ allowedv->push_back("glb");
case FFLOAD_IMAGE:
allowedv->push_back("jpg");
allowedv->push_back("jpeg");
@@ -621,14 +630,13 @@ std::unique_ptr<std::vector<std::string>> LLFilePicker::navOpenFilterProc(ELoadF
allowedv->push_back("bvh");
allowedv->push_back("anim");
break;
+ case FFLOAD_GLTF:
+ allowedv->push_back("gltf");
+ allowedv->push_back("glb");
+ break;
case FFLOAD_COLLADA:
allowedv->push_back("dae");
break;
-#ifdef _CORY_TESTING
- case FFLOAD_GEOMETRY:
- allowedv->push_back("slg");
- break;
-#endif
case FFLOAD_XML:
allowedv->push_back("xml");
break;
@@ -728,13 +736,11 @@ bool LLFilePicker::doNavSaveDialog(ESaveFilter filter, const std::string& filena
extension = "xaf";
break;
-#ifdef _CORY_TESTING
- case FFSAVE_GEOMETRY:
+ case FFSAVE_GLTF:
type = "\?\?\?\?";
creator = "\?\?\?\?";
- extension = "slg";
+ extension = "glb";
break;
-#endif
case FFSAVE_XML:
type = "\?\?\?\?";
@@ -1354,10 +1360,13 @@ BOOL LLFilePicker::getOpenFile( ELoadFilter filter, bool blocking )
case FFLOAD_XML:
filtername = add_xml_filter_to_gtkchooser(picker);
break;
- case FFLOAD_COLLADA:
- filtername = add_collada_filter_to_gtkchooser(picker);
- break;
- case FFLOAD_IMAGE:
+ case FFLOAD_GLTF:
+ filtername = dead_code_should_blow_up_here(picker);
+ break;
+ case FFLOAD_COLLADA:
+ filtername = add_collada_filter_to_gtkchooser(picker);
+ break;
+ case FFLOAD_IMAGE:
filtername = add_imageload_filter_to_gtkchooser(picker);
break;
case FFLOAD_SCRIPT:
diff --git a/indra/newview/llfilepicker.h b/indra/newview/llfilepicker.h
index 73baeca1c0..f510d93dff 100644
--- a/indra/newview/llfilepicker.h
+++ b/indra/newview/llfilepicker.h
@@ -77,9 +77,7 @@ public:
FFLOAD_WAV = 2,
FFLOAD_IMAGE = 3,
FFLOAD_ANIM = 4,
-#ifdef _CORY_TESTING
- FFLOAD_GEOMETRY = 5,
-#endif
+ FFLOAD_GLTF = 5,
FFLOAD_XML = 6,
FFLOAD_SLOBJECT = 7,
FFLOAD_RAW = 8,
@@ -88,7 +86,9 @@ public:
FFLOAD_SCRIPT = 11,
FFLOAD_DICTIONARY = 12,
FFLOAD_DIRECTORY = 13, // To call from lldirpicker.
- FFLOAD_EXE = 14 // Note: EXE will be treated as ALL on Windows and Linux but not on Darwin
+ FFLOAD_EXE = 14, // Note: EXE will be treated as ALL on Windows and Linux but not on Darwin
+ FFLOAD_MATERIAL = 15,
+ FFLOAD_MATERIAL_TEXTURE = 16,
};
enum ESaveFilter
@@ -99,9 +99,7 @@ public:
FFSAVE_BMP = 5,
FFSAVE_AVI = 6,
FFSAVE_ANIM = 7,
-#ifdef _CORY_TESTING
- FFSAVE_GEOMETRY = 8,
-#endif
+ FFSAVE_GLTF = 8,
FFSAVE_XML = 9,
FFSAVE_COLLADA = 10,
FFSAVE_RAW = 11,
diff --git a/indra/newview/llflexibleobject.cpp b/indra/newview/llflexibleobject.cpp
index d5115df35f..500e3cc41b 100644
--- a/indra/newview/llflexibleobject.cpp
+++ b/indra/newview/llflexibleobject.cpp
@@ -399,6 +399,7 @@ void LLVolumeImplFlexible::doIdleUpdate()
updateRenderRes();
+ mVO->shrinkWrap();
gPipeline.markRebuild(drawablep, LLDrawable::REBUILD_POSITION, FALSE);
}
}
diff --git a/indra/newview/llfloaterautoreplacesettings.cpp b/indra/newview/llfloaterautoreplacesettings.cpp
index ec05ba924c..0964daa4d5 100644
--- a/indra/newview/llfloaterautoreplacesettings.cpp
+++ b/indra/newview/llfloaterautoreplacesettings.cpp
@@ -350,7 +350,7 @@ void LLFloaterAutoReplaceSettings::onDeleteEntry()
// called when the Import List button is pressed
void LLFloaterAutoReplaceSettings::onImportList()
{
- (new LLFilePickerReplyThread(boost::bind(&LLFloaterAutoReplaceSettings::loadListFromFile, this, _1), LLFilePicker::FFLOAD_XML, false))->getFile();
+ LLFilePickerReplyThread::startPicker(boost::bind(&LLFloaterAutoReplaceSettings::loadListFromFile, this, _1), LLFilePicker::FFLOAD_XML, false);
}
void LLFloaterAutoReplaceSettings::loadListFromFile(const std::vector<std::string>& filenames)
@@ -537,7 +537,7 @@ void LLFloaterAutoReplaceSettings::onExportList()
{
std::string listName=mListNames->getFirstSelected()->getColumn(0)->getValue().asString();
std::string listFileName = listName + ".xml";
- (new LLFilePickerReplyThread(boost::bind(&LLFloaterAutoReplaceSettings::saveListToFile, this, _1, listName), LLFilePicker::FFSAVE_XML, listFileName))->getFile();
+ LLFilePickerReplyThread::startPicker(boost::bind(&LLFloaterAutoReplaceSettings::saveListToFile, this, _1, listName), LLFilePicker::FFSAVE_XML, listFileName);
}
void LLFloaterAutoReplaceSettings::saveListToFile(const std::vector<std::string>& filenames, std::string listName)
diff --git a/indra/newview/llfloaterbulkpermission.cpp b/indra/newview/llfloaterbulkpermission.cpp
index a1a06706bc..a3cc939f85 100644
--- a/indra/newview/llfloaterbulkpermission.cpp
+++ b/indra/newview/llfloaterbulkpermission.cpp
@@ -306,6 +306,7 @@ void LLFloaterBulkPermission::handleInventory(LLViewerObject* viewer_obj, LLInve
( asstype == LLAssetType::AT_LSL_TEXT && gSavedSettings.getBOOL("BulkChangeIncludeScripts" )) ||
( asstype == LLAssetType::AT_SOUND && gSavedSettings.getBOOL("BulkChangeIncludeSounds" )) ||
( asstype == LLAssetType::AT_SETTINGS && gSavedSettings.getBOOL("BulkChangeIncludeSettings" )) ||
+ ( asstype == LLAssetType::AT_MATERIAL && gSavedSettings.getBOOL("BulkChangeIncludeMaterials")) ||
( asstype == LLAssetType::AT_TEXTURE && gSavedSettings.getBOOL("BulkChangeIncludeTextures" )))
{
LLViewerObject* object = gObjectList.findObject(viewer_obj->getID());
diff --git a/indra/newview/llfloatereditextdaycycle.cpp b/indra/newview/llfloatereditextdaycycle.cpp
index 297ad24359..6e8143384a 100644
--- a/indra/newview/llfloatereditextdaycycle.cpp
+++ b/indra/newview/llfloatereditextdaycycle.cpp
@@ -1524,7 +1524,7 @@ bool LLFloaterEditExtDayCycle::isAddingFrameAllowed()
void LLFloaterEditExtDayCycle::doImportFromDisk()
{ // Load a a legacy Windlight XML from disk.
- (new LLFilePickerReplyThread(boost::bind(&LLFloaterEditExtDayCycle::loadSettingFromFile, this, _1), LLFilePicker::FFLOAD_XML, false))->getFile();
+ LLFilePickerReplyThread::startPicker(boost::bind(&LLFloaterEditExtDayCycle::loadSettingFromFile, this, _1), LLFilePicker::FFLOAD_XML, false);
}
void LLFloaterEditExtDayCycle::loadSettingFromFile(const std::vector<std::string>& filenames)
diff --git a/indra/newview/llfloaterenvironmentadjust.cpp b/indra/newview/llfloaterenvironmentadjust.cpp
index 95d6a2d652..4d11399867 100644
--- a/indra/newview/llfloaterenvironmentadjust.cpp
+++ b/indra/newview/llfloaterenvironmentadjust.cpp
@@ -62,6 +62,7 @@ namespace
const std::string FIELD_SKY_MOON_ROTATION("moon_rotation");
const std::string FIELD_SKY_MOON_AZIMUTH("moon_azimuth");
const std::string FIELD_SKY_MOON_ELEVATION("moon_elevation");
+ const std::string FIELD_REFLECTION_PROBE_AMBIANCE("probe_ambiance");
const std::string BTN_RESET("btn_reset");
const F32 SLIDER_SCALE_SUN_AMBIENT(3.0f);
@@ -117,6 +118,8 @@ BOOL LLFloaterEnvironmentAdjust::postBuild()
getChild<LLTextureCtrl>(FIELD_WATER_NORMAL_MAP)->setBlankImageAssetID(LLUUID(gSavedSettings.getString("DefaultBlankNormalTexture")));
getChild<LLTextureCtrl>(FIELD_WATER_NORMAL_MAP)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onWaterMapChanged(); });
+ getChild<LLUICtrl>(FIELD_REFLECTION_PROBE_AMBIANCE)->setCommitCallback([this](LLUICtrl*, const LLSD&) { onReflectionProbeAmbianceChanged(); });
+
refresh();
return TRUE;
}
@@ -171,6 +174,8 @@ void LLFloaterEnvironmentAdjust::refresh()
getChild<LLTextureCtrl>(FIELD_SKY_CLOUD_MAP)->setValue(mLiveSky->getCloudNoiseTextureId());
getChild<LLTextureCtrl>(FIELD_WATER_NORMAL_MAP)->setValue(mLiveWater->getNormalMapID());
+ getChild<LLUICtrl>(FIELD_REFLECTION_PROBE_AMBIANCE)->setValue(mLiveSky->getReflectionProbeAmbiance());
+
LLColor3 glow(mLiveSky->getGlow());
// takes 40 - 0.2 range -> 0 - 1.99 UI range
@@ -468,6 +473,13 @@ void LLFloaterEnvironmentAdjust::onSunColorChanged()
mLiveSky->update();
}
+void LLFloaterEnvironmentAdjust::onReflectionProbeAmbianceChanged()
+{
+ if (!mLiveSky) return;
+ F32 ambiance = getChild<LLUICtrl>(FIELD_REFLECTION_PROBE_AMBIANCE)->getValue().asReal();
+ mLiveSky->setReflectionProbeAmbiance(ambiance);
+ mLiveSky->update();
+}
void LLFloaterEnvironmentAdjust::onEnvironmentUpdated(LLEnvironment::EnvSelection_t env, S32 version)
{
diff --git a/indra/newview/llfloaterenvironmentadjust.h b/indra/newview/llfloaterenvironmentadjust.h
index 05ff011be5..43c0ba0495 100644
--- a/indra/newview/llfloaterenvironmentadjust.h
+++ b/indra/newview/llfloaterenvironmentadjust.h
@@ -82,6 +82,8 @@ private:
void onCloudMapChanged();
void onWaterMapChanged();
+ void onReflectionProbeAmbianceChanged();
+
void onButtonReset();
void onEnvironmentUpdated(LLEnvironment::EnvSelection_t env, S32 version);
diff --git a/indra/newview/llfloaterfixedenvironment.cpp b/indra/newview/llfloaterfixedenvironment.cpp
index aa9a2c164a..b9dc14ac1a 100644
--- a/indra/newview/llfloaterfixedenvironment.cpp
+++ b/indra/newview/llfloaterfixedenvironment.cpp
@@ -440,7 +440,7 @@ void LLFloaterFixedEnvironmentWater::onOpen(const LLSD& key)
void LLFloaterFixedEnvironmentWater::doImportFromDisk()
{ // Load a a legacy Windlight XML from disk.
- (new LLFilePickerReplyThread(boost::bind(&LLFloaterFixedEnvironmentWater::loadWaterSettingFromFile, this, _1), LLFilePicker::FFLOAD_XML, false))->getFile();
+ LLFilePickerReplyThread::startPicker(boost::bind(&LLFloaterFixedEnvironmentWater::loadWaterSettingFromFile, this, _1), LLFilePicker::FFLOAD_XML, false);
}
void LLFloaterFixedEnvironmentWater::loadWaterSettingFromFile(const std::vector<std::string>& filenames)
@@ -526,7 +526,7 @@ void LLFloaterFixedEnvironmentSky::onClose(bool app_quitting)
void LLFloaterFixedEnvironmentSky::doImportFromDisk()
{ // Load a a legacy Windlight XML from disk.
- (new LLFilePickerReplyThread(boost::bind(&LLFloaterFixedEnvironmentSky::loadSkySettingFromFile, this, _1), LLFilePicker::FFLOAD_XML, false))->getFile();
+ LLFilePickerReplyThread::startPicker(boost::bind(&LLFloaterFixedEnvironmentSky::loadSkySettingFromFile, this, _1), LLFilePicker::FFLOAD_XML, false);
}
void LLFloaterFixedEnvironmentSky::loadSkySettingFromFile(const std::vector<std::string>& filenames)
diff --git a/indra/newview/llfloaterimagepreview.cpp b/indra/newview/llfloaterimagepreview.cpp
index 89ba687d25..6b0ba44624 100644
--- a/indra/newview/llfloaterimagepreview.cpp
+++ b/indra/newview/llfloaterimagepreview.cpp
@@ -797,8 +797,8 @@ void LLImagePreviewSculpted::setPreviewTarget(LLImageRaw* imagep, F32 distance)
U32 num_indices = vf.mNumIndices;
U32 num_vertices = vf.mNumVertices;
- mVertexBuffer = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0, 0);
- if (!mVertexBuffer->allocateBuffer(num_vertices, num_indices, TRUE))
+ mVertexBuffer = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0);
+ if (!mVertexBuffer->allocateBuffer(num_vertices, num_indices))
{
LL_WARNS() << "Failed to allocate Vertex Buffer for image preview to"
<< num_vertices << " vertices and "
@@ -838,6 +838,8 @@ void LLImagePreviewSculpted::setPreviewTarget(LLImageRaw* imagep, F32 distance)
{
*(index_strider++) = vf.mIndices[i];
}
+
+ mVertexBuffer->unmapBuffer();
}
@@ -906,7 +908,7 @@ BOOL LLImagePreviewSculpted::render()
const F32 BRIGHTNESS = 0.9f;
gGL.diffuseColor3f(BRIGHTNESS, BRIGHTNESS, BRIGHTNESS);
- mVertexBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0);
+ mVertexBuffer->setBuffer();
mVertexBuffer->draw(LLRender::TRIANGLES, num_indices, 0);
gGL.popMatrix();
diff --git a/indra/newview/llfloaterlagmeter.cpp b/indra/newview/llfloaterlagmeter.cpp
index f72f2631a1..db00f69f03 100644
--- a/indra/newview/llfloaterlagmeter.cpp
+++ b/indra/newview/llfloaterlagmeter.cpp
@@ -179,7 +179,7 @@ void LLFloaterLagMeter::determineClient()
{
mClientCause->setText( getString("client_texture_loading_cause_msg", mStringArgs) );
}
- else if(LLViewerTexture::sBoundTextureMemory > LLViewerTexture::sMaxBoundTextureMemory)
+ else if(LLViewerTexture::isMemoryForTextureLow())
{
mClientCause->setText( getString("client_texture_memory_cause_msg", mStringArgs) );
}
diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp
index 1a98ab9d76..9c4c9b3e59 100644
--- a/indra/newview/llfloaterland.cpp
+++ b/indra/newview/llfloaterland.cpp
@@ -2004,7 +2004,6 @@ BOOL LLPanelLandOptions::postBuild()
mSnapshotCtrl->setAllowNoTexture ( TRUE );
mSnapshotCtrl->setImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER);
mSnapshotCtrl->setDnDFilterPermMask(PERM_COPY | PERM_TRANSFER);
- mSnapshotCtrl->setNonImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER);
}
else
{
diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp
index 6f8f73bca0..c37d8fae53 100644
--- a/indra/newview/llfloatermodelpreview.cpp
+++ b/indra/newview/llfloatermodelpreview.cpp
@@ -97,7 +97,7 @@ private:
};
LLMeshFilePicker::LLMeshFilePicker(LLModelPreview* mp, S32 lod)
-: LLFilePickerThread(LLFilePicker::FFLOAD_COLLADA)
+: LLFilePickerThread(LLFilePicker::FFLOAD_MODEL)
{
mMP = mp;
mLOD = lod;
@@ -330,8 +330,8 @@ void LLFloaterModelPreview::initModelPreview()
S32 tex_width = 512;
S32 tex_height = 512;
- S32 max_width = llmin(PREVIEW_RENDER_SIZE, (S32)gPipeline.mScreenWidth);
- S32 max_height = llmin(PREVIEW_RENDER_SIZE, (S32)gPipeline.mScreenHeight);
+ S32 max_width = llmin(PREVIEW_RENDER_SIZE, (S32)gPipeline.mRT->width);
+ S32 max_height = llmin(PREVIEW_RENDER_SIZE, (S32)gPipeline.mRT->height);
while ((tex_width << 1) < max_width)
{
diff --git a/indra/newview/llfloaterperms.cpp b/indra/newview/llfloaterperms.cpp
index 649a107d74..fb55c6c6c4 100644
--- a/indra/newview/llfloaterperms.cpp
+++ b/indra/newview/llfloaterperms.cpp
@@ -123,6 +123,7 @@ const std::string LLFloaterPermsDefault::sCategoryNames[CAT_LAST] =
"Gestures",
"Wearables",
"Settings"
+ "Materials"
};
BOOL LLFloaterPermsDefault::postBuild()
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index 6909ad513d..0aa2462ddd 100644
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -399,6 +399,7 @@ BOOL LLFloaterPreference::postBuild()
gSavedSettings.getControl("PreferredMaturity")->getSignal()->connect(boost::bind(&LLFloaterPreference::onChangeMaturity, this));
gSavedPerAccountSettings.getControl("ModelUploadFolder")->getSignal()->connect(boost::bind(&LLFloaterPreference::onChangeModelFolder, this));
+ gSavedPerAccountSettings.getControl("PBRUploadFolder")->getSignal()->connect(boost::bind(&LLFloaterPreference::onChangePBRFolder, this));
gSavedPerAccountSettings.getControl("TextureUploadFolder")->getSignal()->connect(boost::bind(&LLFloaterPreference::onChangeTextureFolder, this));
gSavedPerAccountSettings.getControl("SoundUploadFolder")->getSignal()->connect(boost::bind(&LLFloaterPreference::onChangeSoundFolder, this));
gSavedPerAccountSettings.getControl("AnimationUploadFolder")->getSignal()->connect(boost::bind(&LLFloaterPreference::onChangeAnimationFolder, this));
@@ -691,6 +692,7 @@ void LLFloaterPreference::onOpen(const LLSD& key)
onChangeMaturity();
onChangeModelFolder();
+ onChangePBRFolder();
onChangeTextureFolder();
onChangeSoundFolder();
onChangeAnimationFolder();
@@ -1182,29 +1184,10 @@ void LLFloaterPreference::buildPopupLists()
void LLFloaterPreference::refreshEnabledState()
{
- LLCheckBoxCtrl* ctrl_wind_light = getChild<LLCheckBoxCtrl>("WindLightUseAtmosShaders");
- LLCheckBoxCtrl* ctrl_deferred = getChild<LLCheckBoxCtrl>("UseLightShaders");
+ LLCheckBoxCtrl* ctrl_pbr = getChild<LLCheckBoxCtrl>("UsePBRShaders");
- // if vertex shaders off, disable all shader related products
- if (!LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders"))
- {
- ctrl_wind_light->setEnabled(FALSE);
- ctrl_wind_light->setValue(FALSE);
- }
- else
- {
- ctrl_wind_light->setEnabled(TRUE);
- }
-
- //Deferred/SSAO/Shadows
- BOOL bumpshiny = gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps && LLFeatureManager::getInstance()->isFeatureAvailable("RenderObjectBump") && gSavedSettings.getBOOL("RenderObjectBump");
- BOOL shaders = gSavedSettings.getBOOL("WindLightUseAtmosShaders");
- BOOL enabled = LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") &&
- bumpshiny &&
- shaders &&
- (ctrl_wind_light->get()) ? TRUE : FALSE;
-
- ctrl_deferred->setEnabled(enabled);
+ //PBR
+ ctrl_pbr->setEnabled(TRUE);
// Cannot have floater active until caps have been received
getChild<LLButton>("default_creation_permissions")->setEnabled(LLStartUp::getStartupState() < STATE_STARTED ? false : true);
@@ -1214,58 +1197,19 @@ void LLFloaterPreference::refreshEnabledState()
void LLFloaterPreferenceGraphicsAdvanced::refreshEnabledState()
{
- LLComboBox* ctrl_reflections = getChild<LLComboBox>("Reflections");
- LLTextBox* reflections_text = getChild<LLTextBox>("ReflectionsText");
-
- // Reflections
- BOOL reflections = gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps;
- ctrl_reflections->setEnabled(reflections);
- reflections_text->setEnabled(reflections);
-
- // Bump & Shiny
- LLCheckBoxCtrl* bumpshiny_ctrl = getChild<LLCheckBoxCtrl>("BumpShiny");
- bool bumpshiny = gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps && LLFeatureManager::getInstance()->isFeatureAvailable("RenderObjectBump");
- bumpshiny_ctrl->setEnabled(bumpshiny ? TRUE : FALSE);
-
- // Avatar Mode
- // Avatar Render Mode
- getChild<LLCheckBoxCtrl>("AvatarCloth")->setEnabled(TRUE);
-
- // Vertex Shaders, Global Shader Enable
- // SL-12594 Basic shaders are always enabled. DJH TODO clean up now-orphaned state handling code
- LLSliderCtrl* terrain_detail = getChild<LLSliderCtrl>("TerrainDetail"); // can be linked with control var
- LLTextBox* terrain_text = getChild<LLTextBox>("TerrainDetailText");
-
- terrain_detail->setEnabled(FALSE);
- terrain_text->setEnabled(FALSE);
-
// WindLight
- LLCheckBoxCtrl* ctrl_wind_light = getChild<LLCheckBoxCtrl>("WindLightUseAtmosShaders");
LLSliderCtrl* sky = getChild<LLSliderCtrl>("SkyMeshDetail");
LLTextBox* sky_text = getChild<LLTextBox>("SkyMeshDetailText");
- ctrl_wind_light->setEnabled(TRUE);
sky->setEnabled(TRUE);
sky_text->setEnabled(TRUE);
- //Deferred/SSAO/Shadows
- LLCheckBoxCtrl* ctrl_deferred = getChild<LLCheckBoxCtrl>("UseLightShaders");
-
- BOOL enabled = LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") &&
- ((bumpshiny_ctrl && bumpshiny_ctrl->get()) ? TRUE : FALSE) &&
- (ctrl_wind_light->get()) ? TRUE : FALSE;
-
- ctrl_deferred->setEnabled(enabled);
-
LLCheckBoxCtrl* ctrl_ssao = getChild<LLCheckBoxCtrl>("UseSSAO");
LLCheckBoxCtrl* ctrl_dof = getChild<LLCheckBoxCtrl>("UseDoF");
LLComboBox* ctrl_shadow = getChild<LLComboBox>("ShadowDetail");
LLTextBox* shadow_text = getChild<LLTextBox>("RenderShadowDetailText");
- // note, okay here to get from ctrl_deferred as it's twin, ctrl_deferred2 will alway match it
- enabled = enabled && LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferredSSAO") && (ctrl_deferred->get() ? TRUE : FALSE);
+ BOOL enabled = LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferredSSAO");
- ctrl_deferred->set(gSavedSettings.getBOOL("RenderDeferred"));
-
ctrl_ssao->setEnabled(enabled);
ctrl_dof->setEnabled(enabled);
@@ -1274,30 +1218,32 @@ void LLFloaterPreferenceGraphicsAdvanced::refreshEnabledState()
ctrl_shadow->setEnabled(enabled);
shadow_text->setEnabled(enabled);
- // Hardware settings
- F32 mem_multiplier = gSavedSettings.getF32("RenderTextureMemoryMultiple");
- S32Megabytes min_tex_mem = LLViewerTextureList::getMinVideoRamSetting();
- S32Megabytes max_tex_mem = LLViewerTextureList::getMaxVideoRamSetting(false, mem_multiplier);
- getChild<LLSliderCtrl>("GraphicsCardTextureMemory")->setMinValue(min_tex_mem.value());
- getChild<LLSliderCtrl>("GraphicsCardTextureMemory")->setMaxValue(max_tex_mem.value());
+ if (!LLFeatureManager::instance().isFeatureAvailable("RenderFSAASamples"))
+ {
+ getChildView("fsaa")->setEnabled(FALSE);
+ }
- if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderVBOEnable") ||
- !gGLManager.mHasVertexBufferObject)
- {
- getChildView("vbo")->setEnabled(FALSE);
- }
+ enabled = false;
+ if (!LLFeatureManager::instance().isFeatureAvailable("RenderReflectionsEnabled"))
+ {
+ getChildView("ReflectionsEnabled")->setEnabled(FALSE);
+ }
+ else
+ {
+ enabled = gSavedSettings.getBOOL("RenderReflectionsEnabled");
+ }
- if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderCompressTextures") ||
- !gGLManager.mHasVertexBufferObject)
+ getChildView("ReflectionDetail")->setEnabled(enabled);
+ getChildView("ReflectionDetailText")->setEnabled(enabled);
+ getChildView("ScreenSpaceReflections")->setEnabled(enabled);
+
+ // Hardware settings
+
+ if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderCompressTextures"))
{
getChildView("texture compression")->setEnabled(FALSE);
}
- // if no windlight shaders, turn off nighttime brightness, gamma, and fog distance
- LLUICtrl* gamma_ctrl = getChild<LLUICtrl>("gamma");
- gamma_ctrl->setEnabled(!gPipeline.canUseWindLightShaders());
- getChildView("(brightness, lower is brighter)")->setEnabled(!gPipeline.canUseWindLightShaders());
- getChildView("fog")->setEnabled(!gPipeline.canUseWindLightShaders());
getChildView("antialiasing restart")->setVisible(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred"));
// now turn off any features that are unavailable
@@ -1348,11 +1294,6 @@ void LLAvatarComplexityControls::setIndirectMaxArc()
void LLFloaterPreferenceGraphicsAdvanced::disableUnavailableSettings()
{
- LLComboBox* ctrl_reflections = getChild<LLComboBox>("Reflections");
- LLTextBox* reflections_text = getChild<LLTextBox>("ReflectionsText");
- LLCheckBoxCtrl* ctrl_avatar_cloth = getChild<LLCheckBoxCtrl>("AvatarCloth");
- LLCheckBoxCtrl* ctrl_wind_light = getChild<LLCheckBoxCtrl>("WindLightUseAtmosShaders");
- LLCheckBoxCtrl* ctrl_deferred = getChild<LLCheckBoxCtrl>("UseLightShaders");
LLComboBox* ctrl_shadows = getChild<LLComboBox>("ShadowDetail");
LLTextBox* shadows_text = getChild<LLTextBox>("RenderShadowDetailText");
LLCheckBoxCtrl* ctrl_ssao = getChild<LLCheckBoxCtrl>("UseSSAO");
@@ -1363,9 +1304,6 @@ void LLFloaterPreferenceGraphicsAdvanced::disableUnavailableSettings()
// disabled windlight
if (!LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders"))
{
- ctrl_wind_light->setEnabled(FALSE);
- ctrl_wind_light->setValue(FALSE);
-
sky->setEnabled(FALSE);
sky_text->setEnabled(FALSE);
@@ -1379,9 +1317,6 @@ void LLFloaterPreferenceGraphicsAdvanced::disableUnavailableSettings()
ctrl_dof->setEnabled(FALSE);
ctrl_dof->setValue(FALSE);
-
- ctrl_deferred->setEnabled(FALSE);
- ctrl_deferred->setValue(FALSE);
}
// disabled deferred
@@ -1396,40 +1331,22 @@ void LLFloaterPreferenceGraphicsAdvanced::disableUnavailableSettings()
ctrl_dof->setEnabled(FALSE);
ctrl_dof->setValue(FALSE);
-
- ctrl_deferred->setEnabled(FALSE);
- ctrl_deferred->setValue(FALSE);
}
- // disabled deferred SSAO
+ // disabled deferred SSAO
if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferredSSAO"))
{
- ctrl_ssao->setEnabled(FALSE);
+ ctrl_ssao->setEnabled(FALSE);
ctrl_ssao->setValue(FALSE);
}
// disabled deferred shadows
- if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderShadowDetail"))
- {
- ctrl_shadows->setEnabled(FALSE);
- ctrl_shadows->setValue(0);
- shadows_text->setEnabled(FALSE);
- }
-
- // disabled reflections
- if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderReflectionDetail"))
- {
- ctrl_reflections->setEnabled(FALSE);
- ctrl_reflections->setValue(FALSE);
- reflections_text->setEnabled(FALSE);
- }
-
- // disabled cloth
- if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderAvatarCloth"))
- {
- ctrl_avatar_cloth->setEnabled(FALSE);
- ctrl_avatar_cloth->setValue(FALSE);
- }
+ if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderShadowDetail"))
+ {
+ ctrl_shadows->setEnabled(FALSE);
+ ctrl_shadows->setValue(0);
+ shadows_text->setEnabled(FALSE);
+ }
}
void LLFloaterPreference::refresh()
@@ -1896,6 +1813,14 @@ void LLFloaterPreference::onChangeModelFolder()
}
}
+void LLFloaterPreference::onChangePBRFolder()
+{
+ if (gInventory.isInventoryUsable())
+ {
+ getChild<LLTextBox>("upload_pbr")->setText(get_category_path(LLFolderType::FT_MATERIAL));
+ }
+}
+
void LLFloaterPreference::onChangeTextureFolder()
{
if (gInventory.isInventoryUsable())
diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h
index e312c35135..bab1ffdd56 100644
--- a/indra/newview/llfloaterpreference.h
+++ b/indra/newview/llfloaterpreference.h
@@ -176,6 +176,7 @@ public:
void applyResolution();
void onChangeMaturity();
void onChangeModelFolder();
+ void onChangePBRFolder();
void onChangeTextureFolder();
void onChangeSoundFolder();
void onChangeAnimationFolder();
diff --git a/indra/newview/llfloaterspellchecksettings.cpp b/indra/newview/llfloaterspellchecksettings.cpp
index de5d59f484..32eb70cd39 100644
--- a/indra/newview/llfloaterspellchecksettings.cpp
+++ b/indra/newview/llfloaterspellchecksettings.cpp
@@ -259,7 +259,7 @@ BOOL LLFloaterSpellCheckerImport::postBuild(void)
void LLFloaterSpellCheckerImport::onBtnBrowse()
{
- (new LLFilePickerReplyThread(boost::bind(&LLFloaterSpellCheckerImport::importSelectedDictionary, this, _1), LLFilePicker::FFLOAD_DICTIONARY, false))->getFile();
+ LLFilePickerReplyThread::startPicker(boost::bind(&LLFloaterSpellCheckerImport::importSelectedDictionary, this, _1), LLFilePicker::FFLOAD_DICTIONARY, false);
}
void LLFloaterSpellCheckerImport::importSelectedDictionary(const std::vector<std::string>& filenames)
diff --git a/indra/newview/llfloatertexturefetchdebugger.cpp b/indra/newview/llfloatertexturefetchdebugger.cpp
deleted file mode 100644
index cda4dc8bcc..0000000000
--- a/indra/newview/llfloatertexturefetchdebugger.cpp
+++ /dev/null
@@ -1,480 +0,0 @@
-/**
- * @file llfloatertexturefetchdebugger.cpp
- * @brief LLFloaterTextureFetchDebugger class definition
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2012, 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$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "llfloatertexturefetchdebugger.h"
-
-#include "lluictrlfactory.h"
-#include "llbutton.h"
-#include "llspinctrl.h"
-#include "llresmgr.h"
-
-#include "llmath.h"
-#include "llviewerwindow.h"
-#include "llappviewer.h"
-#include "lltexturefetch.h"
-#include "llviewercontrol.h"
-#include "llviewerassetstats.h" //gTextureTimer
-
-LLFloaterTextureFetchDebugger::LLFloaterTextureFetchDebugger(const LLSD& key)
- : LLFloater(key),
- mDebugger(NULL)
-{
- setTitle("Texture Fetching Debugger Floater");
-
- mCommitCallbackRegistrar.add("TexFetchDebugger.ChangeTexelPixelRatio", boost::bind(&LLFloaterTextureFetchDebugger::onChangeTexelPixelRatio, this));
-
- mCommitCallbackRegistrar.add("TexFetchDebugger.Start", boost::bind(&LLFloaterTextureFetchDebugger::onClickStart, this));
- mCommitCallbackRegistrar.add("TexFetchDebugger.Clear", boost::bind(&LLFloaterTextureFetchDebugger::onClickClear, this));
- mCommitCallbackRegistrar.add("TexFetchDebugger.Close", boost::bind(&LLFloaterTextureFetchDebugger::onClickClose, this));
- mCommitCallbackRegistrar.add("TexFetchDebugger.ResetFetchTime", boost::bind(&LLFloaterTextureFetchDebugger::onClickResetFetchTime, this));
-
- mCommitCallbackRegistrar.add("TexFetchDebugger.CacheRead", boost::bind(&LLFloaterTextureFetchDebugger::onClickCacheRead, this));
- mCommitCallbackRegistrar.add("TexFetchDebugger.CacheWrite", boost::bind(&LLFloaterTextureFetchDebugger::onClickCacheWrite, this));
- mCommitCallbackRegistrar.add("TexFetchDebugger.HTTPLoad", boost::bind(&LLFloaterTextureFetchDebugger::onClickHTTPLoad, this));
- mCommitCallbackRegistrar.add("TexFetchDebugger.Decode", boost::bind(&LLFloaterTextureFetchDebugger::onClickDecode, this));
- mCommitCallbackRegistrar.add("TexFetchDebugger.GLTexture", boost::bind(&LLFloaterTextureFetchDebugger::onClickGLTexture, this));
-
- mCommitCallbackRegistrar.add("TexFetchDebugger.RefetchVisCache", boost::bind(&LLFloaterTextureFetchDebugger::onClickRefetchVisCache, this));
- mCommitCallbackRegistrar.add("TexFetchDebugger.RefetchVisHTTP", boost::bind(&LLFloaterTextureFetchDebugger::onClickRefetchVisHTTP, this));
- mCommitCallbackRegistrar.add("TexFetchDebugger.RefetchAllCache", boost::bind(&LLFloaterTextureFetchDebugger::onClickRefetchAllCache, this));
- mCommitCallbackRegistrar.add("TexFetchDebugger.RefetchAllHTTP", boost::bind(&LLFloaterTextureFetchDebugger::onClickRefetchAllHTTP, this));
-}
-//----------------------------------------------
-
-BOOL LLFloaterTextureFetchDebugger::postBuild(void)
-{
- mDebugger = LLAppViewer::getTextureFetch()->getFetchDebugger();
- mStartStatus = (S32)LLTextureFetchDebugger::IDLE;
-
- //set states for buttons
- mButtonStateMap["start_btn"] = true;
- mButtonStateMap["close_btn"] = true;
- mButtonStateMap["clear_btn"] = true;
- mButtonStateMap["cacheread_btn"] = false;
- mButtonStateMap["cachewrite_btn"] = false;
- mButtonStateMap["http_btn"] = false;
- mButtonStateMap["decode_btn"] = false;
- mButtonStateMap["gl_btn"] = false;
-
- mButtonStateMap["refetchviscache_btn"] = false;
- mButtonStateMap["refetchvishttp_btn"] = false;
- mButtonStateMap["refetchallcache_btn"] = false;
- mButtonStateMap["refetchallhttp_btn"] = false;
-
- updateButtons();
-
- getChild<LLUICtrl>("texel_pixel_ratio")->setValue(gSavedSettings.getF32("TexelPixelRatio"));
-
- return TRUE ;
-}
-
-LLFloaterTextureFetchDebugger::~LLFloaterTextureFetchDebugger()
-{
- //stop everything
- mDebugger->setStopDebug();
-}
-
-void LLFloaterTextureFetchDebugger::updateButtons()
-{
- for(std::map<std::string, bool>::iterator iter = mButtonStateMap.begin(); iter != mButtonStateMap.end(); ++iter)
- {
- if(iter->second)
- {
- childEnable(iter->first.c_str());
- }
- else
- {
- childDisable(iter->first.c_str());
- }
- }
-}
-
-void LLFloaterTextureFetchDebugger::disableButtons()
-{
- childDisable("start_btn");
- childDisable("clear_btn");
- childDisable("cacheread_btn");
- childDisable("cachewrite_btn");
- childDisable("http_btn");
- childDisable("decode_btn");
- childDisable("gl_btn");
- childDisable("refetchviscache_btn");
- childDisable("refetchvishttp_btn");
- childDisable("refetchallcache_btn");
- childDisable("refetchallhttp_btn");
-}
-void LLFloaterTextureFetchDebugger::setStartStatus(S32 status)
-{
- llassert_always(LLTextureFetchDebugger::IDLE == (LLTextureFetchDebugger::e_debug_state)mStartStatus) ;
- mStartStatus = status;
-}
-
-bool LLFloaterTextureFetchDebugger::idleStart()
-{
- if(mStartStatus != (S32)LLTextureFetchDebugger::IDLE)
- {
- mDebugger->startWork((LLTextureFetchDebugger::e_debug_state)mStartStatus);
- mStartStatus = (S32)LLTextureFetchDebugger::IDLE;
- return true;
- }
-
- return false;
-}
-
-void LLFloaterTextureFetchDebugger::idle()
-{
- if(idleStart())
- {
- return;
- }
-
- const F32 max_time = 0.005f; //5ms
- LLTextureFetchDebugger::e_debug_state state = mDebugger->getState();
- if(mDebugger->update(max_time))
- {
- switch(state)
- {
- case LLTextureFetchDebugger::IDLE:
- break;
- case LLTextureFetchDebugger::START_DEBUG:
- mButtonStateMap["cacheread_btn"] = true;
- mButtonStateMap["http_btn"] = true;
- mButtonStateMap["refetchviscache_btn"] = true;
- mButtonStateMap["refetchvishttp_btn"] = true;
- mButtonStateMap["refetchallcache_btn"] = true;
- mButtonStateMap["refetchallhttp_btn"] = true;
- break;
- case LLTextureFetchDebugger::READ_CACHE:
- mButtonStateMap["decode_btn"] = true;
- break;
- case LLTextureFetchDebugger::WRITE_CACHE:
- break;
- case LLTextureFetchDebugger::DECODING:
- mButtonStateMap["gl_btn"] = true;
- break;
- case LLTextureFetchDebugger::HTTP_FETCHING:
- mButtonStateMap["cacheread_btn"] = true;
- mButtonStateMap["cachewrite_btn"] = true;
- mButtonStateMap["decode_btn"] = true;
- break;
- case LLTextureFetchDebugger::GL_TEX:
- break;
- case LLTextureFetchDebugger::REFETCH_VIS_CACHE:
- break;
- case LLTextureFetchDebugger::REFETCH_VIS_HTTP:
- break;
- case LLTextureFetchDebugger::REFETCH_ALL_CACHE:
- break;
- case LLTextureFetchDebugger::REFETCH_ALL_HTTP:
- break;
- default:
- break;
- }
-
- if(state != LLTextureFetchDebugger::IDLE)
- {
- updateButtons();
- }
- }
-}
-
-//----------------------
-void LLFloaterTextureFetchDebugger::onChangeTexelPixelRatio()
-{
- gSavedSettings.setF32("TexelPixelRatio", getChild<LLUICtrl>("texel_pixel_ratio")->getValue().asReal());
-}
-
-void LLFloaterTextureFetchDebugger::onClickStart()
-{
- disableButtons();
-
- setStartStatus((S32)LLTextureFetchDebugger::START_DEBUG);
-
- mButtonStateMap["start_btn"] = false;
-
- updateButtons();
-}
-
-void LLFloaterTextureFetchDebugger::onClickClose()
-{
- setVisible(FALSE);
-
- //stop everything
- mDebugger->setStopDebug();
-
- delete this;
-}
-
-void LLFloaterTextureFetchDebugger::onClickResetFetchTime()
-{
- gTextureTimer.start();
- gTextureTimer.pause();
-}
-
-void LLFloaterTextureFetchDebugger::onClickClear()
-{
- mButtonStateMap["start_btn"] = true;
- mButtonStateMap["close_btn"] = true;
- mButtonStateMap["clear_btn"] = true;
- mButtonStateMap["cacheread_btn"] = false;
- mButtonStateMap["cachewrite_btn"] = false;
- mButtonStateMap["http_btn"] = false;
- mButtonStateMap["decode_btn"] = false;
- mButtonStateMap["gl_btn"] = false;
- mButtonStateMap["refetchviscache_btn"] = true;
- mButtonStateMap["refetchvishttp_btn"] = true;
- updateButtons();
-
- //stop everything
- mDebugger->setStopDebug();
- mDebugger->clearHistory();
-}
-
-void LLFloaterTextureFetchDebugger::onClickCacheRead()
-{
- disableButtons();
-
- setStartStatus((S32)LLTextureFetchDebugger::READ_CACHE);
-}
-
-void LLFloaterTextureFetchDebugger::onClickCacheWrite()
-{
- disableButtons();
-
- setStartStatus((S32)LLTextureFetchDebugger::WRITE_CACHE);
-}
-
-void LLFloaterTextureFetchDebugger::onClickHTTPLoad()
-{
- disableButtons();
-
- setStartStatus((S32)LLTextureFetchDebugger::HTTP_FETCHING);
-}
-
-void LLFloaterTextureFetchDebugger::onClickDecode()
-{
- disableButtons();
-
- setStartStatus((S32)LLTextureFetchDebugger::DECODING);
-}
-
-void LLFloaterTextureFetchDebugger::onClickGLTexture()
-{
- disableButtons();
-
- setStartStatus((S32)LLTextureFetchDebugger::GL_TEX);
-}
-
-void LLFloaterTextureFetchDebugger::onClickRefetchVisCache()
-{
- disableButtons();
-
- setStartStatus((S32)LLTextureFetchDebugger::REFETCH_VIS_CACHE);
-}
-
-void LLFloaterTextureFetchDebugger::onClickRefetchVisHTTP()
-{
- disableButtons();
-
- setStartStatus((S32)LLTextureFetchDebugger::REFETCH_VIS_HTTP);
-}
-
-void LLFloaterTextureFetchDebugger::onClickRefetchAllCache()
-{
- disableButtons();
-
- setStartStatus((S32)LLTextureFetchDebugger::REFETCH_ALL_CACHE);
-}
-
-void LLFloaterTextureFetchDebugger::onClickRefetchAllHTTP()
-{
- disableButtons();
-
- setStartStatus((S32)LLTextureFetchDebugger::REFETCH_ALL_HTTP);
-}
-
-void LLFloaterTextureFetchDebugger::draw()
-{
- //total number of fetched textures
- {
- getChild<LLUICtrl>("total_num_fetched_label")->setTextArg("[NUM]", llformat("%d", mDebugger->getNumFetchedTextures()));
- }
-
- //total number of fetching requests
- {
- getChild<LLUICtrl>("total_num_fetching_requests_label")->setTextArg("[NUM]", llformat("%d", mDebugger->getNumFetchingRequests()));
- }
-
- //total number of cache hits
- {
- getChild<LLUICtrl>("total_num_cache_hits_label")->setTextArg("[NUM]", llformat("%d", mDebugger->getNumCacheHits()));
- }
-
- //total number of visible textures
- {
- getChild<LLUICtrl>("total_num_visible_tex_label")->setTextArg("[NUM]", llformat("%d", mDebugger->getNumVisibleFetchedTextures()));
- }
-
- //total number of visible texture fetching requests
- {
- getChild<LLUICtrl>("total_num_visible_tex_fetch_req_label")->setTextArg("[NUM]", llformat("%d", mDebugger->getNumVisibleFetchingRequests()));
- }
-
- //total number of fetched data
- {
- getChild<LLUICtrl>("total_fetched_data_label")->setTextArg("[SIZE1]", llformat("%d", mDebugger->getFetchedData() >> 10));
- getChild<LLUICtrl>("total_fetched_data_label")->setTextArg("[SIZE2]", llformat("%d", mDebugger->getDecodedData() >> 10));
- getChild<LLUICtrl>("total_fetched_data_label")->setTextArg("[PIXEL]", llformat("%.3f", mDebugger->getFetchedPixels() / 1000000.f));
- }
-
- //total number of visible fetched data
- {
- getChild<LLUICtrl>("total_fetched_vis_data_label")->setTextArg("[SIZE1]", llformat("%d", mDebugger->getVisibleFetchedData() >> 10));
- getChild<LLUICtrl>("total_fetched_vis_data_label")->setTextArg("[SIZE2]", llformat("%d", mDebugger->getVisibleDecodedData() >> 10));
- }
-
- //total number of rendered fetched data
- {
- getChild<LLUICtrl>("total_fetched_rendered_data_label")->setTextArg("[SIZE1]", llformat("%d", mDebugger->getRenderedData() >> 10));
- getChild<LLUICtrl>("total_fetched_rendered_data_label")->setTextArg("[SIZE2]", llformat("%d", mDebugger->getRenderedDecodedData() >> 10));
- getChild<LLUICtrl>("total_fetched_rendered_data_label")->setTextArg("[PIXEL]", llformat("%.3f", mDebugger->getRenderedPixels() / 1000000.f));
- }
-
- //total time on cache readings
- if(mDebugger->getCacheReadTime() < 0.f)
- {
- getChild<LLUICtrl>("total_time_cache_read_label")->setTextArg("[TIME]", std::string("----"));
- }
- else
- {
- getChild<LLUICtrl>("total_time_cache_read_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getCacheReadTime()));
- }
-
- //total time on cache writings
- if(mDebugger->getCacheWriteTime() < 0.f)
- {
- getChild<LLUICtrl>("total_time_cache_write_label")->setTextArg("[TIME]", std::string("----"));
- }
- else
- {
- getChild<LLUICtrl>("total_time_cache_write_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getCacheWriteTime()));
- }
-
- //total time on decoding
- if(mDebugger->getDecodeTime() < 0.f)
- {
- getChild<LLUICtrl>("total_time_decode_label")->setTextArg("[TIME]", std::string("----"));
- }
- else
- {
- getChild<LLUICtrl>("total_time_decode_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getDecodeTime()));
- }
-
- //total time on gl texture creation
- if(mDebugger->getGLCreationTime() < 0.f)
- {
- getChild<LLUICtrl>("total_time_gl_label")->setTextArg("[TIME]", std::string("----"));
- }
- else
- {
- getChild<LLUICtrl>("total_time_gl_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getGLCreationTime()));
- }
-
- //total time on HTTP fetching
- if(mDebugger->getHTTPTime() < 0.f)
- {
- getChild<LLUICtrl>("total_time_http_label")->setTextArg("[TIME]", std::string("----"));
- }
- else
- {
- getChild<LLUICtrl>("total_time_http_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getHTTPTime()));
- }
-
- //total time on entire fetching
- {
- getChild<LLUICtrl>("total_time_fetch_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getTotalFetchingTime()));
- }
-
- //total time on refetching visible textures from cache
- if(mDebugger->getRefetchVisCacheTime() < 0.f)
- {
- getChild<LLUICtrl>("total_time_refetch_vis_cache_label")->setTextArg("[TIME]", std::string("----"));
- getChild<LLUICtrl>("total_time_refetch_vis_cache_label")->setTextArg("[SIZE]", std::string("----"));
- getChild<LLUICtrl>("total_time_refetch_vis_cache_label")->setTextArg("[PIXEL]", std::string("----"));
- }
- else
- {
- getChild<LLUICtrl>("total_time_refetch_vis_cache_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getRefetchVisCacheTime()));
- getChild<LLUICtrl>("total_time_refetch_vis_cache_label")->setTextArg("[SIZE]", llformat("%d", mDebugger->getRefetchedVisData() >> 10));
- getChild<LLUICtrl>("total_time_refetch_vis_cache_label")->setTextArg("[PIXEL]", llformat("%.3f", mDebugger->getRefetchedVisPixels() / 1000000.f));
- }
-
- //total time on refetching all textures from cache
- if(mDebugger->getRefetchAllCacheTime() < 0.f)
- {
- getChild<LLUICtrl>("total_time_refetch_all_cache_label")->setTextArg("[TIME]", std::string("----"));
- getChild<LLUICtrl>("total_time_refetch_all_cache_label")->setTextArg("[SIZE]", std::string("----"));
- getChild<LLUICtrl>("total_time_refetch_all_cache_label")->setTextArg("[PIXEL]", std::string("----"));
- }
- else
- {
- getChild<LLUICtrl>("total_time_refetch_all_cache_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getRefetchAllCacheTime()));
- getChild<LLUICtrl>("total_time_refetch_all_cache_label")->setTextArg("[SIZE]", llformat("%d", mDebugger->getRefetchedAllData() >> 10));
- getChild<LLUICtrl>("total_time_refetch_all_cache_label")->setTextArg("[PIXEL]", llformat("%.3f", mDebugger->getRefetchedAllPixels() / 1000000.f));
- }
-
- //total time on refetching visible textures from http
- if(mDebugger->getRefetchVisHTTPTime() < 0.f)
- {
- getChild<LLUICtrl>("total_time_refetch_vis_http_label")->setTextArg("[TIME]", std::string("----"));
- getChild<LLUICtrl>("total_time_refetch_vis_http_label")->setTextArg("[SIZE]", std::string("----"));
- getChild<LLUICtrl>("total_time_refetch_vis_http_label")->setTextArg("[PIXEL]", std::string("----"));
- }
- else
- {
- getChild<LLUICtrl>("total_time_refetch_vis_http_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getRefetchVisHTTPTime()));
- getChild<LLUICtrl>("total_time_refetch_vis_http_label")->setTextArg("[SIZE]", llformat("%d", mDebugger->getRefetchedVisData() >> 10));
- getChild<LLUICtrl>("total_time_refetch_vis_http_label")->setTextArg("[PIXEL]", llformat("%.3f", mDebugger->getRefetchedVisPixels() / 1000000.f));
- }
-
- //total time on refetching all textures from http
- if(mDebugger->getRefetchAllHTTPTime() < 0.f)
- {
- getChild<LLUICtrl>("total_time_refetch_all_http_label")->setTextArg("[TIME]", std::string("----"));
- getChild<LLUICtrl>("total_time_refetch_all_http_label")->setTextArg("[SIZE]", std::string("----"));
- getChild<LLUICtrl>("total_time_refetch_all_http_label")->setTextArg("[PIXEL]", std::string("----"));
- }
- else
- {
- getChild<LLUICtrl>("total_time_refetch_all_http_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getRefetchAllHTTPTime()));
- getChild<LLUICtrl>("total_time_refetch_all_http_label")->setTextArg("[SIZE]", llformat("%d", mDebugger->getRefetchedAllData() >> 10));
- getChild<LLUICtrl>("total_time_refetch_all_http_label")->setTextArg("[PIXEL]", llformat("%.3f", mDebugger->getRefetchedAllPixels() / 1000000.f));
- }
-
- LLFloater::draw();
-}
diff --git a/indra/newview/llfloatertexturefetchdebugger.h b/indra/newview/llfloatertexturefetchdebugger.h
deleted file mode 100644
index 637f3b03e5..0000000000
--- a/indra/newview/llfloatertexturefetchdebugger.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/**
- * @file llfloatertexturefetchdebugger.h
- * @brief texture fetching debugger window, debug use only
- *
- * $LicenseInfo:firstyear=2004&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, 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$
- */
-
-#ifndef LL_FLOATER_TEXTURE_FETCH_DEBUGGER__H
-#define LL_FLOATER_TEXTURE_FETCH_DEBUGGER__H
-
-#include "llfloater.h"
-class LLTextureFetchDebugger;
-
-class LLFloaterTextureFetchDebugger : public LLFloater
-{
- friend class LLFloaterReg;
-public:
- /// initialize all the callbacks for the menu
-
- virtual BOOL postBuild() ;
- virtual void draw() ;
-
- void onChangeTexelPixelRatio();
-
- void onClickStart();
- void onClickClear();
- void onClickClose();
- void onClickResetFetchTime();
-
- void onClickCacheRead();
- void onClickCacheWrite();
- void onClickHTTPLoad();
- void onClickDecode();
- void onClickGLTexture();
-
- void onClickRefetchVisCache();
- void onClickRefetchVisHTTP();
- void onClickRefetchAllCache();
- void onClickRefetchAllHTTP();
-public:
- void idle() ;
-
-private:
- LLFloaterTextureFetchDebugger(const LLSD& key);
- virtual ~LLFloaterTextureFetchDebugger();
-
- void updateButtons();
- void disableButtons();
-
- void setStartStatus(S32 status);
- bool idleStart();
-private:
- LLTextureFetchDebugger* mDebugger;
- std::map<std::string, bool> mButtonStateMap;
- S32 mStartStatus;
-};
-
-#endif // LL_FLOATER_TEXTURE_FETCH_DEBUGGER__H
diff --git a/indra/newview/llfloateruipreview.cpp b/indra/newview/llfloateruipreview.cpp
index e67c79a3a0..67a205417e 100644
--- a/indra/newview/llfloateruipreview.cpp
+++ b/indra/newview/llfloateruipreview.cpp
@@ -1023,7 +1023,7 @@ void LLFloaterUIPreview::onClickEditFloater()
void LLFloaterUIPreview::onClickBrowseForEditor()
{
// Let the user choose an executable through the file picker dialog box
- (new LLFilePickerReplyThread(boost::bind(&LLFloaterUIPreview::getExecutablePath, this, _1), LLFilePicker::FFLOAD_EXE, false))->getFile();
+ LLFilePickerReplyThread::startPicker(boost::bind(&LLFloaterUIPreview::getExecutablePath, this, _1), LLFilePicker::FFLOAD_EXE, false);
}
void LLFloaterUIPreview::getExecutablePath(const std::vector<std::string>& filenames)
@@ -1077,7 +1077,7 @@ void LLFloaterUIPreview::getExecutablePath(const std::vector<std::string>& filen
void LLFloaterUIPreview::onClickBrowseForDiffs()
{
// create load dialog box
- (new LLFilePickerReplyThread(boost::bind(&LLFloaterUIPreview::getDiffsFilePath, this, _1), LLFilePicker::FFLOAD_XML, false))->getFile();
+ LLFilePickerReplyThread::startPicker(boost::bind(&LLFloaterUIPreview::getDiffsFilePath, this, _1), LLFilePicker::FFLOAD_XML, false);
}
void LLFloaterUIPreview::getDiffsFilePath(const std::vector<std::string>& filenames)
diff --git a/indra/newview/llglsandbox.cpp b/indra/newview/llglsandbox.cpp
index 175f1849cf..2e4d0f85b9 100644
--- a/indra/newview/llglsandbox.cpp
+++ b/indra/newview/llglsandbox.cpp
@@ -815,7 +815,7 @@ void LLViewerObjectList::renderObjectBeacons()
const LLVector3 &thisline = debug_beacon.mPositionAgent;
gGL.begin(LLRender::LINES);
- gGL.color4fv(color.mV);
+ gGL.color4fv(linearColor4(color).mV);
draw_cross_lines(thisline, 2.0f, 2.0f, 50.f);
draw_line_cube(0.10f, thisline);
@@ -844,7 +844,7 @@ void LLViewerObjectList::renderObjectBeacons()
const LLVector3 &thisline = debug_beacon.mPositionAgent;
gGL.begin(LLRender::LINES);
- gGL.color4fv(debug_beacon.mColor.mV);
+ gGL.color4fv(linearColor4(debug_beacon.mColor).mV);
draw_cross_lines(thisline, 0.5f, 0.5f, 0.5f);
draw_line_cube(0.10f, thisline);
@@ -987,9 +987,8 @@ private:
//-----------------------------------------------------------------------------
F32 gpu_benchmark()
{
- if (!gGLManager.mHasTimerQuery)
+ if (gGLManager.mGLVersion < 3.3f)
{ // don't bother benchmarking venerable drivers which don't support accurate timing anyway
- // and are likely to be correctly identified by the GPU table already.
return -1.f;
}
@@ -1000,8 +999,8 @@ F32 gpu_benchmark()
gBenchmarkProgram.mName = "Benchmark Shader";
gBenchmarkProgram.mFeatures.attachNothing = true;
gBenchmarkProgram.mShaderFiles.clear();
- gBenchmarkProgram.mShaderFiles.push_back(std::make_pair("interface/benchmarkV.glsl", GL_VERTEX_SHADER_ARB));
- gBenchmarkProgram.mShaderFiles.push_back(std::make_pair("interface/benchmarkF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gBenchmarkProgram.mShaderFiles.push_back(std::make_pair("interface/benchmarkV.glsl", GL_VERTEX_SHADER));
+ gBenchmarkProgram.mShaderFiles.push_back(std::make_pair("interface/benchmarkF.glsl", GL_FRAGMENT_SHADER));
gBenchmarkProgram.mShaderLevel = 1;
if (!gBenchmarkProgram.createShader(NULL, NULL))
{
@@ -1051,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
@@ -1084,9 +1083,9 @@ F32 gpu_benchmark()
delete [] pixels;
//make a dummy triangle to draw with
- LLPointer<LLVertexBuffer> buff = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX, GL_STREAM_DRAW_ARB);
+ LLPointer<LLVertexBuffer> buff = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX);
- if (!buff->allocateBuffer(3, 0, true))
+ if (!buff->allocateBuffer(3, 0))
{
LL_WARNS("Benchmark") << "Failed to allocate buffer during benchmark." << LL_ENDL;
// abandon the benchmark test
@@ -1110,22 +1109,12 @@ F32 gpu_benchmark()
v[1].set(-1, -3, 0);
v[2].set(3, 1, 0);
- buff->flush();
+ buff->unmapBuffer();
// ensure matched pair of bind() and unbind() calls
ShaderBinder binder(gBenchmarkProgram);
-#ifdef GL_ARB_vertex_array_object
- U32 glarray = 0;
-
- if (LLRender::sGLCoreProfile)
- {
- glGenVertexArrays(1, &glarray);
- glBindVertexArray(glarray);
- }
-#endif
-
- buff->setBuffer(LLVertexBuffer::MAP_VERTEX);
+ buff->setBuffer();
glFinish();
F32 time_passed = 0; // seconds
@@ -1157,15 +1146,6 @@ F32 gpu_benchmark()
}
}
-#ifdef GL_ARB_vertex_array_object
- if (LLRender::sGLCoreProfile)
- {
- glBindVertexArray(0);
- glDeleteVertexArrays(1, &glarray);
- }
-#endif
-
-
std::sort(results.begin(), results.end());
F32 gbps = results[results.size()/2];
diff --git a/indra/newview/llgltfmateriallist.cpp b/indra/newview/llgltfmateriallist.cpp
new file mode 100644
index 0000000000..bc094ac838
--- /dev/null
+++ b/indra/newview/llgltfmateriallist.cpp
@@ -0,0 +1,769 @@
+/**
+ * @file llgltfmateriallist.cpp
+ *
+ * $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$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llgltfmateriallist.h"
+
+#include "llagent.h"
+#include "llassetstorage.h"
+#include "lldispatcher.h"
+#include "llfetchedgltfmaterial.h"
+#include "llfilesystem.h"
+#include "llsdserialize.h"
+#include "lltinygltfhelper.h"
+#include "llviewercontrol.h"
+#include "llviewergenericmessage.h"
+#include "llviewerobjectlist.h"
+#include "llviewerregion.h"
+#include "llviewerstats.h"
+#include "llcorehttputil.h"
+#include "llagent.h"
+#include "llvocache.h"
+#include "llworld.h"
+
+#include "tinygltf/tiny_gltf.h"
+#include <strstream>
+
+#include "json/reader.h"
+#include "json/value.h"
+
+#include <unordered_set>
+
+LLGLTFMaterialList gGLTFMaterialList;
+
+LLGLTFMaterialList::modify_queue_t LLGLTFMaterialList::sModifyQueue;
+LLGLTFMaterialList::apply_queue_t LLGLTFMaterialList::sApplyQueue;
+LLSD LLGLTFMaterialList::sUpdates;
+
+const LLUUID LLGLTFMaterialList::BLANK_MATERIAL_ASSET_ID("968cbad0-4dad-d64e-71b5-72bf13ad051a");
+
+#ifdef SHOW_ASSERT
+// return true if given data is (probably) valid update message for ModifyMaterialParams capability
+static bool is_valid_update(const LLSD& data)
+{
+ llassert(data.isMap());
+
+ U32 count = 0;
+
+ if (data.has("object_id"))
+ {
+ if (!data["object_id"].isUUID())
+ {
+ LL_WARNS() << "object_id is not a UUID" << LL_ENDL;
+ return false;
+ }
+ ++count;
+ }
+ else
+ {
+ LL_WARNS() << "Missing required parameter: object_id" << LL_ENDL;
+ return false;
+ }
+
+ if (data.has("side"))
+ {
+ if (!data["side"].isInteger())
+ {
+ LL_WARNS() << "side is not an integer" << LL_ENDL;
+ return false;
+ }
+
+ if (data["side"].asInteger() < -1)
+ {
+ LL_WARNS() << "side is invalid" << LL_ENDL;
+ }
+ ++count;
+ }
+ else
+ {
+ LL_WARNS() << "Missing required parameter: side" << LL_ENDL;
+ return false;
+ }
+
+ if (data.has("gltf_json"))
+ {
+ if (!data["gltf_json"].isString())
+ {
+ LL_WARNS() << "gltf_json is not a string" << LL_ENDL;
+ return false;
+ }
+ ++count;
+ }
+
+ if (data.has("asset_id"))
+ {
+ if (!data["asset_id"].isUUID())
+ {
+ LL_WARNS() << "asset_id is not a UUID" << LL_ENDL;
+ return false;
+ }
+ ++count;
+ }
+
+ if (count < 3)
+ {
+ LL_WARNS() << "Only specified object_id and side, update won't actually change anything and is just noise" << LL_ENDL;
+ return false;
+ }
+
+ if (data.size() != count)
+ {
+ LL_WARNS() << "update data contains unrecognized parameters" << LL_ENDL;
+ return false;
+ }
+
+ return true;
+}
+#endif
+
+class LLGLTFMaterialOverrideDispatchHandler : public LLDispatchHandler
+{
+ LOG_CLASS(LLGLTFMaterialOverrideDispatchHandler);
+public:
+ LLGLTFMaterialOverrideDispatchHandler() = default;
+ ~LLGLTFMaterialOverrideDispatchHandler() override = default;
+
+ void addCallback(void(*callback)(const LLUUID& object_id, S32 side))
+ {
+ mSelectionCallbacks.push_back(callback);
+ }
+
+ bool operator()(const LLDispatcher* dispatcher, const std::string& key, const LLUUID& invoice, const sparam_t& strings) override
+ {
+ LL_PROFILE_ZONE_SCOPED;
+ // receive override data from simulator via LargeGenericMessage
+ // message should have:
+ // object_id - UUID of LLViewerObject
+ // side - S32 index of texture entry
+ // gltf_json - String of GLTF json for override data
+
+
+ LLSD message;
+
+ sparam_t::const_iterator it = strings.begin();
+ if (it != strings.end())
+ {
+ const std::string& llsdRaw = *it++;
+ std::istringstream llsdData(llsdRaw);
+ if (!LLSDSerialize::deserialize(message, llsdData, llsdRaw.length()))
+ {
+ LL_WARNS() << "LLGLTFMaterialOverrideDispatchHandler: Attempted to read parameter data into LLSD but failed:" << llsdRaw << LL_ENDL;
+ }
+ }
+ else
+ {
+ // malformed message, nothing we can do to handle it
+ LL_DEBUGS("GLTF") << "Empty message" << LL_ENDL;
+ return false;
+ }
+
+ LLGLTFOverrideCacheEntry object_override;
+ if (!object_override.fromLLSD(message))
+ {
+ // malformed message, nothing we can do to handle it
+ LL_DEBUGS("GLTF") << "Message without id:" << message << LL_ENDL;
+ return false;
+ }
+
+ // Cache the data
+ {
+ LL_DEBUGS("GLTF") << "material overrides cache" << LL_ENDL;
+
+ // default to main region if message doesn't specify
+ LLViewerRegion * region = gAgent.getRegion();;
+
+ if (object_override.mHasRegionHandle)
+ {
+ // TODO start requiring this once server sends this for all messages
+ region = LLWorld::instance().getRegionFromHandle(object_override.mRegionHandle);
+ }
+
+ if (region)
+ {
+ region->cacheFullUpdateGLTFOverride(object_override);
+ }
+ else
+ {
+ LL_WARNS("GLTF") << "could not access region for material overrides message cache, region_handle: " << LL_ENDL;
+ }
+ }
+ applyData(object_override);
+ return true;
+ }
+
+ void doSelectionCallbacks(const LLUUID& object_id, S32 side)
+ {
+ for (auto& callback : mSelectionCallbacks)
+ {
+ callback(object_id, side);
+ }
+ }
+
+ void applyData(const LLGLTFOverrideCacheEntry &object_override)
+ {
+ // Parse the data
+
+ LL::WorkQueue::ptr_t main_queue = LL::WorkQueue::getInstance("mainloop");
+ LL::WorkQueue::ptr_t general_queue = LL::WorkQueue::getInstance("General");
+
+ struct ReturnData
+ {
+ public:
+ LLPointer<LLGLTFMaterial> mMaterial;
+ S32 mSide;
+ bool mSuccess;
+ };
+
+ // fromJson() is performance heavy offload to a thread.
+ main_queue->postTo(
+ general_queue,
+ [object_override]() // Work done on general queue
+ {
+ std::vector<ReturnData> results;
+
+ if (!object_override.mSides.empty())
+ {
+ results.reserve(object_override.mSides.size());
+ // parse json
+ std::map<S32, std::string>::const_iterator iter = object_override.mSides.begin();
+ std::map<S32, std::string>::const_iterator end = object_override.mSides.end();
+ while (iter != end)
+ {
+ LLPointer<LLGLTFMaterial> override_data = new LLGLTFMaterial();
+ std::string warn_msg, error_msg;
+
+ bool success = override_data->fromJSON(iter->second, warn_msg, error_msg);
+
+ ReturnData result;
+ result.mSuccess = success;
+ result.mSide = iter->first;
+
+ if (success)
+ {
+ result.mMaterial = override_data;
+ }
+ else
+ {
+ LL_WARNS("GLTF") << "failed to parse GLTF override data. errors: " << error_msg << " | warnings: " << warn_msg << LL_ENDL;
+ }
+
+ results.push_back(result);
+ iter++;
+ }
+ }
+ return results;
+ },
+ [object_override, this](std::vector<ReturnData> results) // Callback to main thread
+ {
+
+ LLViewerObject * obj = gObjectList.findObject(object_override.mObjectId);
+
+ if (results.size() > 0 )
+ {
+ std::unordered_set<S32> side_set;
+
+ for (int i = 0; i < results.size(); ++i)
+ {
+ if (results[i].mSuccess)
+ {
+ // flag this side to not be nulled out later
+ side_set.insert(results[i].mSide);
+
+ if (!obj || !obj->setTEGLTFMaterialOverride(results[i].mSide, results[i].mMaterial))
+ {
+ // object not ready to receive override data, queue for later
+ gGLTFMaterialList.queueOverrideUpdate(object_override.mObjectId, results[i].mSide, results[i].mMaterial);
+ }
+ else if (obj && obj->getTE(results[i].mSide) && obj->getTE(results[i].mSide)->isSelected())
+ {
+ doSelectionCallbacks(object_override.mObjectId, results[i].mSide);
+ }
+ }
+ else
+ {
+ // unblock material editor
+ if (obj && obj->getTE(results[i].mSide) && obj->getTE(results[i].mSide)->isSelected())
+ {
+ doSelectionCallbacks(object_override.mObjectId, results[i].mSide);
+ }
+ }
+ }
+
+ if (obj && side_set.size() != obj->getNumTEs())
+ { // object exists and at least one texture entry needs to have its override data nulled out
+ for (int i = 0; i < obj->getNumTEs(); ++i)
+ {
+ if (side_set.find(i) == side_set.end())
+ {
+ obj->setTEGLTFMaterialOverride(i, nullptr);
+ if (obj->getTE(i) && obj->getTE(i)->isSelected())
+ {
+ doSelectionCallbacks(object_override.mObjectId, i);
+ }
+ }
+ }
+ }
+ }
+ else if (obj)
+ { // override list was empty or an error occurred, null out all overrides for this object
+ for (int i = 0; i < obj->getNumTEs(); ++i)
+ {
+ obj->setTEGLTFMaterialOverride(i, nullptr);
+ if (obj->getTE(i) && obj->getTE(i)->isSelected())
+ {
+ doSelectionCallbacks(obj->getID(), i);
+ }
+ }
+ }
+ });
+ }
+
+private:
+
+ std::vector<void(*)(const LLUUID& object_id, S32 side)> mSelectionCallbacks;
+};
+
+namespace
+{
+ LLGLTFMaterialOverrideDispatchHandler handle_gltf_override_message;
+}
+
+void LLGLTFMaterialList::queueOverrideUpdate(const LLUUID& id, S32 side, LLGLTFMaterial* override_data)
+{
+ override_list_t& overrides = mQueuedOverrides[id];
+
+ if (overrides.size() < side + 1)
+ {
+ overrides.resize(side + 1);
+ }
+
+ overrides[side] = override_data;
+}
+
+void LLGLTFMaterialList::applyQueuedOverrides(LLViewerObject* obj)
+{
+ LL_PROFILE_ZONE_SCOPED;
+ const LLUUID& id = obj->getID();
+ auto iter = mQueuedOverrides.find(id);
+
+ if (iter != mQueuedOverrides.end())
+ {
+ override_list_t& overrides = iter->second;
+ for (int i = 0; i < overrides.size(); ++i)
+ {
+ if (overrides[i].notNull())
+ {
+ if (!obj->getTE(i) || !obj->getTE(i)->getGLTFMaterial())
+ { // object doesn't have its base GLTF material yet, don't apply override (yet)
+ return;
+ }
+ obj->setTEGLTFMaterialOverride(i, overrides[i]);
+ if (obj->getTE(i)->isSelected())
+ {
+ handle_gltf_override_message.doSelectionCallbacks(id, i);
+ }
+ }
+ }
+
+ mQueuedOverrides.erase(iter);
+ }
+}
+
+void LLGLTFMaterialList::queueModify(const LLViewerObject* obj, S32 side, const LLGLTFMaterial* mat)
+{
+ if (obj && obj->getRenderMaterialID(side).notNull())
+ {
+ if (mat == nullptr)
+ {
+ sModifyQueue.push_back({ obj->getID(), side, LLGLTFMaterial(), false });
+ }
+ else
+ {
+ sModifyQueue.push_back({ obj->getID(), side, *mat, true });
+ }
+ }
+}
+
+void LLGLTFMaterialList::queueApply(const LLViewerObject* obj, S32 side, const LLUUID& asset_id)
+{
+ const LLGLTFMaterial* material_override = obj->getTE(side)->getGLTFMaterialOverride();
+ if (material_override)
+ {
+ LLGLTFMaterial* cleared_override = new LLGLTFMaterial(*material_override);
+ cleared_override->setBaseMaterial();
+ sApplyQueue.push_back({ obj->getID(), side, asset_id, cleared_override });
+ }
+ else
+ {
+ sApplyQueue.push_back({ obj->getID(), side, asset_id, nullptr });
+ }
+}
+
+void LLGLTFMaterialList::queueUpdate(const LLSD& data)
+{
+ llassert(is_valid_update(data));
+
+ if (!sUpdates.isArray())
+ {
+ sUpdates = LLSD::emptyArray();
+ }
+
+ sUpdates[sUpdates.size()] = data;
+}
+
+void LLGLTFMaterialList::flushUpdates(void(*done_callback)(bool))
+{
+ LLSD& data = sUpdates;
+
+ S32 i = data.size();
+
+ 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;
+
+ if (e.has_override)
+ {
+ data[i]["gltf_json"] = e.override_data.asJSON();
+ }
+ else
+ {
+ // Clear all overrides
+ data[i]["gltf_json"] = "";
+ }
+
+ llassert(is_valid_update(data[i]));
+ ++i;
+ }
+ sModifyQueue.clear();
+
+ for (auto& e : sApplyQueue)
+ {
+ data[i]["object_id"] = e.object_id;
+ data[i]["side"] = e.side;
+ data[i]["asset_id"] = e.asset_id;
+ if (e.override_data)
+ {
+ data[i]["gltf_json"] = e.override_data->asJSON();
+ }
+ else
+ {
+ // Clear all overrides
+ data[i]["gltf_json"] = "";
+ }
+
+ llassert(is_valid_update(data[i]));
+ ++i;
+ }
+ sApplyQueue.clear();
+
+#if 0 // debug output of data being sent to capability
+ std::stringstream str;
+ LLSDSerialize::serialize(data, str, LLSDSerialize::LLSD_NOTATION, LLSDFormatter::OPTIONS_PRETTY);
+ LL_INFOS() << "\n" << str.str() << LL_ENDL;
+#endif
+
+ if (sUpdates.size() > 0)
+ {
+ LLCoros::instance().launch("modifyMaterialCoro",
+ std::bind(&LLGLTFMaterialList::modifyMaterialCoro,
+ gAgent.getRegionCapability("ModifyMaterialParams"),
+ sUpdates,
+ done_callback));
+
+ sUpdates = LLSD::emptyArray();
+ }
+}
+
+void LLGLTFMaterialList::addSelectionUpdateCallback(void(*update_callback)(const LLUUID& object_id, S32 side))
+{
+ handle_gltf_override_message.addCallback(update_callback);
+}
+
+class AssetLoadUserData
+{
+public:
+ AssetLoadUserData() {}
+ tinygltf::Model mModelIn;
+ LLPointer<LLFetchedGLTFMaterial> mMaterial;
+};
+
+void LLGLTFMaterialList::onAssetLoadComplete(const LLUUID& id, LLAssetType::EType asset_type, void* user_data, S32 status, LLExtStat ext_status)
+{
+ LL_PROFILE_ZONE_NAMED("gltf asset callback");
+ AssetLoadUserData* asset_data = (AssetLoadUserData*)user_data;
+
+ if (status != LL_ERR_NOERR)
+ {
+ LL_WARNS("GLTF") << "Error getting material asset data: " << LLAssetStorage::getErrorString(status) << " (" << status << ")" << LL_ENDL;
+ asset_data->mMaterial->materialComplete();
+ delete asset_data;
+ }
+ else
+ {
+
+ LL::WorkQueue::ptr_t main_queue = LL::WorkQueue::getInstance("mainloop");
+ LL::WorkQueue::ptr_t general_queue = LL::WorkQueue::getInstance("General");
+
+ typedef std::pair<U32, tinygltf::Model> return_data_t;
+
+ main_queue->postTo(
+ general_queue,
+ [id, asset_type, asset_data]() // Work done on general queue
+ {
+ std::vector<char> buffer;
+ {
+ LL_PROFILE_ZONE_NAMED("gltf read asset");
+ LLFileSystem file(id, asset_type, LLFileSystem::READ);
+ auto size = file.getSize();
+ if (!size)
+ {
+ return false;
+ }
+
+ buffer.resize(size);
+ file.read((U8*)&buffer[0], buffer.size());
+ }
+
+ {
+ LL_PROFILE_ZONE_NAMED("gltf deserialize asset");
+
+ LLSD asset;
+
+ // read file into buffer
+ std::istrstream str(&buffer[0], buffer.size());
+
+ if (LLSDSerialize::deserialize(asset, str, buffer.size()))
+ {
+ if (asset.has("version") && asset["version"] == "1.0")
+ {
+ if (asset.has("type") && asset["type"].asString() == "GLTF 2.0")
+ {
+ if (asset.has("data") && asset["data"].isString())
+ {
+ std::string data = asset["data"];
+
+ std::string warn_msg, error_msg;
+
+ LL_PROFILE_ZONE_SCOPED;
+ tinygltf::TinyGLTF gltf;
+
+ if (!gltf.LoadASCIIFromString(&asset_data->mModelIn, &error_msg, &warn_msg, data.c_str(), data.length(), ""))
+ {
+ LL_WARNS("GLTF") << "Failed to decode material asset: "
+ << LL_NEWLINE
+ << warn_msg
+ << LL_NEWLINE
+ << error_msg
+ << LL_ENDL;
+ return false;
+ }
+ return true;
+ }
+ }
+ }
+ }
+ else
+ {
+ LL_WARNS("GLTF") << "Failed to deserialize material LLSD" << LL_ENDL;
+ }
+ }
+
+ return false;
+ },
+ [id, asset_data](bool result) // Callback to main thread
+ {
+
+ if (result)
+ {
+ asset_data->mMaterial->setFromModel(asset_data->mModelIn, 0/*only one index*/);
+ }
+ else
+ {
+ LL_DEBUGS("GLTF") << "Failed to get material " << id << LL_ENDL;
+ }
+
+ asset_data->mMaterial->materialComplete();
+
+ delete asset_data;
+ });
+ }
+}
+
+LLFetchedGLTFMaterial* LLGLTFMaterialList::getMaterial(const LLUUID& id)
+{
+ LL_PROFILE_ZONE_SCOPED;
+ uuid_mat_map_t::iterator iter = mList.find(id);
+ if (iter == mList.end())
+ {
+ LL_PROFILE_ZONE_NAMED("gltf fetch")
+ LLFetchedGLTFMaterial* mat = new LLFetchedGLTFMaterial();
+ mList[id] = mat;
+
+ if (!mat->mFetching)
+ {
+ mat->materialBegin();
+
+ AssetLoadUserData *user_data = new AssetLoadUserData();
+ user_data->mMaterial = mat;
+
+ gAssetStorage->getAssetData(id, LLAssetType::AT_MATERIAL, onAssetLoadComplete, (void*)user_data);
+ }
+
+ return mat;
+ }
+
+ return iter->second;
+}
+
+void LLGLTFMaterialList::addMaterial(const LLUUID& id, LLFetchedGLTFMaterial* material)
+{
+ mList[id] = material;
+}
+
+void LLGLTFMaterialList::removeMaterial(const LLUUID& id)
+{
+ mList.erase(id);
+}
+
+void LLGLTFMaterialList::flushMaterials()
+{
+ // Similar variant to what textures use
+ static const S32 MIN_UPDATE_COUNT = gSavedSettings.getS32("TextureFetchUpdateMinCount"); // default: 32
+ //update MIN_UPDATE_COUNT or 5% of materials, whichever is greater
+ U32 update_count = llmax((U32)MIN_UPDATE_COUNT, (U32)mList.size() / 20);
+ update_count = llmin(update_count, (U32)mList.size());
+
+ const F64 MAX_INACTIVE_TIME = 30.f;
+ F64 cur_time = LLTimer::getTotalSeconds();
+
+ // advance iter one past the last key we updated
+ uuid_mat_map_t::iterator iter = mList.find(mLastUpdateKey);
+ if (iter != mList.end()) {
+ ++iter;
+ }
+
+ while (update_count-- > 0)
+ {
+ if (iter == mList.end())
+ {
+ iter = mList.begin();
+ }
+
+ LLPointer<LLFetchedGLTFMaterial> material = iter->second;
+ if (material->getNumRefs() == 2) // this one plus one from the list
+ {
+
+ if (!material->mActive
+ && cur_time > material->mExpectedFlusTime)
+ {
+ iter = mList.erase(iter);
+ }
+ else
+ {
+ if (material->mActive)
+ {
+ material->mExpectedFlusTime = cur_time + MAX_INACTIVE_TIME;
+ material->mActive = false;
+ }
+ ++iter;
+ }
+ }
+ else
+ {
+ material->mActive = true;
+ ++iter;
+ }
+ }
+
+ if (iter != mList.end())
+ {
+ mLastUpdateKey = iter->first;
+ }
+ else
+ {
+ mLastUpdateKey.setNull();
+ }
+
+ {
+ using namespace LLStatViewer;
+ sample(NUM_MATERIALS, mList.size());
+ }
+}
+
+// static
+void LLGLTFMaterialList::registerCallbacks()
+{
+ gGenericDispatcher.addHandler("GLTFMaterialOverride", &handle_gltf_override_message);
+}
+
+// static
+void LLGLTFMaterialList::modifyMaterialCoro(std::string cap_url, LLSD overrides, void(*done_callback)(bool) )
+{
+ LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+ LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+ httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("modifyMaterialCoro", httpPolicy));
+ LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+ LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
+ LLCore::HttpHeaders::ptr_t httpHeaders;
+
+ httpOpts->setFollowRedirects(true);
+
+ LL_DEBUGS("GLTF") << "Applying override via ModifyMaterialParams cap: " << overrides << LL_ENDL;
+
+ LLSD result = httpAdapter->postAndSuspend(httpRequest, cap_url, overrides, httpOpts, httpHeaders);
+
+ LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+ LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+ bool success = true;
+ if (!status)
+ {
+ LL_WARNS("GLTF") << "Failed to modify material." << LL_ENDL;
+ success = false;
+ }
+ else if (!result["success"].asBoolean())
+ {
+ LL_WARNS("GLTF") << "Failed to modify material: " << result["message"] << LL_ENDL;
+ success = false;
+ }
+
+ if (done_callback)
+ {
+ done_callback(success);
+ }
+}
+
+void LLGLTFMaterialList::loadCacheOverrides(const LLGLTFOverrideCacheEntry& override)
+{
+ handle_gltf_override_message.applyData(override);
+}
diff --git a/indra/newview/llgltfmateriallist.h b/indra/newview/llgltfmateriallist.h
new file mode 100644
index 0000000000..85e60aa17f
--- /dev/null
+++ b/indra/newview/llgltfmateriallist.h
@@ -0,0 +1,151 @@
+/**
+ * @file llgltfmateriallist.h
+ *
+ * $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$
+ */
+
+
+#pragma once
+
+#include "llassettype.h"
+#include "llextendedstatus.h"
+#include "llfetchedgltfmaterial.h"
+#include "llgltfmaterial.h"
+#include "llpointer.h"
+
+#include <unordered_map>
+
+class LLFetchedGLTFMaterial;
+class LLGLTFOverrideCacheEntry;
+
+class LLGLTFMaterialList
+{
+public:
+ static const LLUUID BLANK_MATERIAL_ASSET_ID;
+
+ LLGLTFMaterialList() {}
+
+
+ LLFetchedGLTFMaterial* getMaterial(const LLUUID& id);
+
+ void addMaterial(const LLUUID& id, LLFetchedGLTFMaterial* material);
+ void removeMaterial(const LLUUID& id);
+
+ void flushMaterials();
+
+ static void registerCallbacks();
+
+ // Queue an modification of a material that we want to send to the simulator. Call "flushUpdates" to flush pending updates.
+ // id - ID of object to modify
+ // side - TexureEntry index to modify, or -1 for all sides
+ // 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 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
+ // side - TextureEntry index to apply material to, or -1 for all sides
+ // asset_id - ID of material asset to apply, or LLUUID::null to disassociate current material asset
+ //
+ // NOTE: Implicitly clears most override data if present
+ static void queueApply(const LLViewerObject* obj, S32 side, const LLUUID& asset_id);
+
+ // flush pending material updates to the simulator
+ // Automatically called once per frame, but may be called explicitly
+ // for cases that care about the done_callback forwarded to LLCoros::instance().launch
+ static void flushUpdates(void(*done_callback)(bool) = nullptr);
+
+ static void addSelectionUpdateCallback(void(*update_callback)(const LLUUID& object_id, S32 side));
+
+ // Queue an explicit LLSD ModifyMaterialParams update apply given override data
+ // overrides -- LLSD map (or array of maps) in the format:
+ // object_id UUID(required) id of object
+ // side integer(required) TE index of face to set, or -1 for all faces
+ // gltf_json string(optional) override data to set, empty string nulls out override data, omissions of this parameter keeps existing data
+ // asset_id UUID(optional) id of material asset to set, omission of this parameter keeps existing material asset id
+ //
+ // NOTE: Unless you already have a gltf_json string you want to send, strongly prefer using queueModify
+ // If the queue/flush API is insufficient, extend it.
+ static void queueUpdate(const LLSD& data);
+
+ // Called by batch builder to give LLGLTMaterialList an opportunity to apply
+ // any override data that arrived before the object was ready to receive it
+ void applyQueuedOverrides(LLViewerObject* obj);
+
+ static void loadCacheOverrides(const LLGLTFOverrideCacheEntry& override);
+
+private:
+ friend class LLGLTFMaterialOverrideDispatchHandler;
+ // save an override update that we got from the simulator for later (for example, if an override arrived for an unknown object)
+ // NOTE: this is NOT for applying overrides from the UI, see queueModifyMaterial above
+ void queueOverrideUpdate(const LLUUID& id, S32 side, LLGLTFMaterial* override_data);
+
+ static void modifyMaterialCoro(std::string cap_url, LLSD overrides, void(*done_callback)(bool));
+
+protected:
+ static void onAssetLoadComplete(
+ const LLUUID& asset_uuid,
+ LLAssetType::EType type,
+ void* user_data,
+ S32 status,
+ LLExtStat ext_status);
+
+ typedef std::unordered_map<LLUUID, LLPointer<LLFetchedGLTFMaterial > > uuid_mat_map_t;
+ uuid_mat_map_t mList;
+
+ typedef std::vector<LLPointer<LLGLTFMaterial> > override_list_t;
+ typedef std::unordered_map<LLUUID, override_list_t > queued_override_map_t;
+ queued_override_map_t mQueuedOverrides;
+
+ LLUUID mLastUpdateKey;
+
+ struct ModifyMaterialData
+ {
+ LLUUID object_id;
+ S32 side = -1;
+ LLGLTFMaterial override_data;
+
+ bool has_override = false;
+ };
+
+ typedef std::list<ModifyMaterialData> modify_queue_t;
+ static modify_queue_t sModifyQueue;
+
+ struct ApplyMaterialAssetData
+ {
+ LLUUID object_id;
+ S32 side = -1;
+ LLUUID asset_id;
+ LLPointer<LLGLTFMaterial> override_data;
+ };
+
+ typedef std::list<ApplyMaterialAssetData> apply_queue_t;
+ static apply_queue_t sApplyQueue;
+
+ // data to be flushed to ModifyMaterialParams capability
+ static LLSD sUpdates;
+};
+
+extern LLGLTFMaterialList gGLTFMaterialList;
+
+
diff --git a/indra/newview/llhudeffectlookat.cpp b/indra/newview/llhudeffectlookat.cpp
index 6898dce7b1..0f230067bc 100644
--- a/indra/newview/llhudeffectlookat.cpp
+++ b/indra/newview/llhudeffectlookat.cpp
@@ -495,7 +495,7 @@ void LLHUDEffectLookAt::render()
{
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- LLGLDisable gls_stencil(GL_STENCIL_TEST);
+ //LLGLDisable gls_stencil(GL_STENCIL_TEST);
LLVector3 target = mTargetPos + ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->mHeadp->getWorldPosition();
gGL.matrixMode(LLRender::MM_MODELVIEW);
diff --git a/indra/newview/llhudeffectpointat.cpp b/indra/newview/llhudeffectpointat.cpp
index ecf6d42d69..dfa299528a 100644
--- a/indra/newview/llhudeffectpointat.cpp
+++ b/indra/newview/llhudeffectpointat.cpp
@@ -322,7 +322,7 @@ void LLHUDEffectPointAt::render()
update();
if (sDebugPointAt && mTargetType != POINTAT_TARGET_NONE)
{
- LLGLDisable gls_stencil(GL_STENCIL_TEST);
+ //LLGLDisable gls_stencil(GL_STENCIL_TEST);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
LLVector3 target = mTargetPos + mSourceObject->getRenderPosition();
diff --git a/indra/newview/llhudicon.cpp b/indra/newview/llhudicon.cpp
index 85a878c4a2..38be2b69fd 100644
--- a/indra/newview/llhudicon.cpp
+++ b/indra/newview/llhudicon.cpp
@@ -64,7 +64,6 @@ LLHUDIcon::icon_instance_t LLHUDIcon::sIconInstances;
LLHUDIcon::LLHUDIcon(const U8 type) :
LLHUDObject(type),
mImagep(NULL),
- mPickID(0),
mScale(0.1f),
mHidden(FALSE)
{
@@ -76,15 +75,11 @@ LLHUDIcon::~LLHUDIcon()
mImagep = NULL;
}
-void LLHUDIcon::renderIcon(BOOL for_select)
+void LLHUDIcon::render()
{
LLGLSUIDefault texture_state;
LLGLDepthTest gls_depth(GL_TRUE);
- LLGLDisable gls_stencil(GL_STENCIL_TEST);
- if (for_select)
- {
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- }
+ //LLGLDisable gls_stencil(GL_STENCIL_TEST);
if (mHidden)
return;
@@ -116,7 +111,7 @@ void LLHUDIcon::renderIcon(BOOL for_select)
mDistance = dist_vec(icon_position, camera->getOrigin());
- F32 alpha_factor = for_select ? 1.f : clamp_rescale(mDistance, DIST_START_FADE, DIST_END_FADE, 1.f, 0.f);
+ F32 alpha_factor = clamp_rescale(mDistance, DIST_START_FADE, DIST_END_FADE, 1.f, 0.f);
LLVector3 x_pixel_vec;
LLVector3 y_pixel_vec;
@@ -150,13 +145,6 @@ void LLHUDIcon::renderIcon(BOOL for_select)
LLVector3 upper_left = icon_position - (x_scale * 0.5f) + y_scale;
LLVector3 upper_right = icon_position + (x_scale * 0.5f) + y_scale;
- if (for_select)
- {
- // set color to unique color id for picking
- LLColor4U coloru((U8)(mPickID >> 16), (U8)(mPickID >> 8), (U8)mPickID);
- gGL.color4ubv(coloru.mV);
- }
- else
{
LLColor4 icon_color = LLColor4::white;
icon_color.mV[VALPHA] = alpha_factor;
@@ -198,11 +186,6 @@ void LLHUDIcon::markDead()
LLHUDObject::markDead();
}
-void LLHUDIcon::render()
-{
- renderIcon(FALSE);
-}
-
BOOL LLHUDIcon::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, LLVector4a* intersection)
{
if (mHidden)
@@ -296,37 +279,6 @@ BOOL LLHUDIcon::lineSegmentIntersect(const LLVector4a& start, const LLVector4a&
}
//static
-S32 LLHUDIcon::generatePickIDs(S32 start_id, S32 step_size)
-{
- S32 cur_id = start_id;
- icon_instance_t::iterator icon_it;
-
- for(icon_it = sIconInstances.begin(); icon_it != sIconInstances.end(); ++icon_it)
- {
- (*icon_it)->mPickID = cur_id;
- cur_id += step_size;
- }
-
- return cur_id;
-}
-
-//static
-LLHUDIcon* LLHUDIcon::handlePick(S32 pick_id)
-{
- icon_instance_t::iterator icon_it;
-
- for(icon_it = sIconInstances.begin(); icon_it != sIconInstances.end(); ++icon_it)
- {
- if (pick_id == (*icon_it)->mPickID)
- {
- return *icon_it;
- }
- }
-
- return NULL;
-}
-
-//static
LLHUDIcon* LLHUDIcon::lineSegmentIntersectAll(const LLVector4a& start, const LLVector4a& end, LLVector4a* intersection)
{
icon_instance_t::iterator icon_it;
diff --git a/indra/newview/llhudicon.h b/indra/newview/llhudicon.h
index e00a985ddc..7f452b5c36 100644
--- a/indra/newview/llhudicon.h
+++ b/indra/newview/llhudicon.h
@@ -56,8 +56,6 @@ public:
void restartLifeTimer() { mLifeTimer.reset(); }
- static S32 generatePickIDs(S32 start_id, S32 step_size);
- static LLHUDIcon* handlePick(S32 pick_id);
static LLHUDIcon* lineSegmentIntersectAll(const LLVector4a& start, const LLVector4a& end, LLVector4a* intersection);
static void updateAll();
@@ -75,14 +73,11 @@ protected:
LLHUDIcon(const U8 type);
~LLHUDIcon();
- void renderIcon(BOOL for_select); // common render code
-
private:
LLPointer<LLViewerTexture> mImagep;
LLFrameTimer mAnimTimer;
LLFrameTimer mLifeTimer;
F32 mDistance;
- S32 mPickID;
F32 mScale;
BOOL mHidden;
diff --git a/indra/newview/llhudnametag.cpp b/indra/newview/llhudnametag.cpp
index 952fbf8e4b..e2d63ecc0a 100644
--- a/indra/newview/llhudnametag.cpp
+++ b/indra/newview/llhudnametag.cpp
@@ -228,7 +228,7 @@ void LLHUDNameTag::render()
if (sDisplayText)
{
LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
- LLGLDisable gls_stencil(GL_STENCIL_TEST);
+ //LLGLDisable gls_stencil(GL_STENCIL_TEST);
renderText(FALSE);
}
}
diff --git a/indra/newview/llhudobject.cpp b/indra/newview/llhudobject.cpp
index 45fa09e1a1..292045f25d 100644
--- a/indra/newview/llhudobject.cpp
+++ b/indra/newview/llhudobject.cpp
@@ -267,6 +267,13 @@ void LLHUDObject::updateAll()
// static
void LLHUDObject::renderAll()
{
+ LLGLSUIDefault gls_ui;
+
+ gUIProgram.bind();
+ gGL.color4f(1, 1, 1, 1);
+
+ LLGLDepthTest depth(GL_FALSE, GL_FALSE);
+
LLHUDObject *hud_objp;
hud_object_list_t::iterator object_it;
@@ -285,6 +292,7 @@ void LLHUDObject::renderAll()
}
LLVertexBuffer::unbind();
+ gUIProgram.unbind();
}
// static
diff --git a/indra/newview/llhudtext.cpp b/indra/newview/llhudtext.cpp
index 5952edfc44..22dca07096 100644
--- a/indra/newview/llhudtext.cpp
+++ b/indra/newview/llhudtext.cpp
@@ -102,7 +102,7 @@ void LLHUDText::render()
if (!mOnHUDAttachment && sDisplayText)
{
LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
- LLGLDisable gls_stencil(GL_STENCIL_TEST);
+ //LLGLDisable gls_stencil(GL_STENCIL_TEST);
renderText();
}
}
@@ -224,6 +224,10 @@ void LLHUDText::renderText()
}
text_color = segment_iter->mColor;
+ if (mOnHUDAttachment)
+ {
+ text_color = linearColor4(text_color);
+ }
text_color.mV[VALPHA] *= alpha_factor;
hud_render_text(segment_iter->getText(), render_position, *fontp, style, shadow, x_offset, y_offset, text_color, mOnHUDAttachment);
@@ -569,7 +573,6 @@ void LLHUDText::markDead()
void LLHUDText::renderAllHUD()
{
LLGLState::checkStates();
- LLGLState::checkTextureChannels();
{
LLGLEnable color_mat(GL_COLOR_MATERIAL);
@@ -586,7 +589,6 @@ void LLHUDText::renderAllHUD()
LLVertexBuffer::unbind();
LLGLState::checkStates();
- LLGLState::checkTextureChannels();
}
void LLHUDText::shiftAll(const LLVector3& offset)
diff --git a/indra/newview/llinspectobject.cpp b/indra/newview/llinspectobject.cpp
index 5329f10612..3d13985f08 100644
--- a/indra/newview/llinspectobject.cpp
+++ b/indra/newview/llinspectobject.cpp
@@ -116,6 +116,7 @@ private:
viewer_media_t mMediaImpl;
LLMediaEntry* mMediaEntry;
LLSafeHandle<LLObjectSelection> mObjectSelection;
+ boost::signals2::connection mSelectionUpdateSlot;
};
LLInspectObject::LLInspectObject(const LLSD& sd)
@@ -141,6 +142,10 @@ LLInspectObject::LLInspectObject(const LLSD& sd)
LLInspectObject::~LLInspectObject()
{
+ if (mSelectionUpdateSlot.connected())
+ {
+ mSelectionUpdateSlot.disconnect();
+ }
}
/*virtual*/
@@ -175,9 +180,12 @@ BOOL LLInspectObject::postBuild(void)
getChild<LLUICtrl>("more_info_btn")->setCommitCallback(
boost::bind(&LLInspectObject::onClickMoreInfo, this));
- // Watch for updates to selection properties off the network
- LLSelectMgr::getInstance()->mUpdateSignal.connect(
- boost::bind(&LLInspectObject::update, this) );
+ if (!mSelectionUpdateSlot.connected())
+ {
+ // Watch for updates to selection properties off the network
+ mSelectionUpdateSlot = LLSelectMgr::getInstance()->mUpdateSignal.connect(
+ boost::bind(&LLInspectObject::update, this));
+ }
return TRUE;
}
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index db347f7096..2665cb1b92 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -804,7 +804,10 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
if (obj)
{
- items.push_back(std::string("Copy Separator"));
+ if (obj->getType() != LLAssetType::AT_CATEGORY)
+ {
+ items.push_back(std::string("Copy Separator"));
+ }
items.push_back(std::string("Copy"));
if (!isItemCopyable())
{
@@ -917,7 +920,10 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
}
}
- items.push_back(std::string("Paste Separator"));
+ if (obj->getType() != LLAssetType::AT_CATEGORY)
+ {
+ items.push_back(std::string("Paste Separator"));
+ }
addDeleteContextMenuOptions(items, disabled_items);
@@ -1462,6 +1468,14 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,
new_listener = new LLSettingsBridge(inventory, root, uuid, LLSettingsType::fromInventoryFlags(flags));
break;
+ case LLAssetType::AT_MATERIAL:
+ if (inv_type != LLInventoryType::IT_MATERIAL)
+ {
+ LL_WARNS() << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(inv_type) << " on uuid " << uuid << LL_ENDL;
+ }
+ new_listener = new LLMaterialBridge(inventory, root, uuid);
+ break;
+
default:
LL_INFOS_ONCE() << "Unhandled asset type (llassetstorage.h): "
<< (S32)asset_type << " (" << LLAssetType::lookup(asset_type) << ")" << LL_ENDL;
@@ -4081,6 +4095,7 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
disabled_items.push_back(std::string("New Note"));
disabled_items.push_back(std::string("New Settings"));
disabled_items.push_back(std::string("New Gesture"));
+ disabled_items.push_back(std::string("New Material"));
disabled_items.push_back(std::string("New Clothes"));
disabled_items.push_back(std::string("New Body Parts"));
disabled_items.push_back(std::string("upload_def"));
@@ -4108,6 +4123,7 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
disabled_items.push_back(std::string("New Script"));
disabled_items.push_back(std::string("New Note"));
disabled_items.push_back(std::string("New Gesture"));
+ disabled_items.push_back(std::string("New Material"));
disabled_items.push_back(std::string("New Clothes"));
disabled_items.push_back(std::string("New Body Parts"));
disabled_items.push_back(std::string("upload_def"));
@@ -4162,20 +4178,25 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
if (!isInboxFolder() // don't allow creation in inbox
&& outfits_id != mUUID)
{
+ bool menu_items_added = false;
// Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694.
if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat))
{
items.push_back(std::string("New Folder"));
+ menu_items_added = true;
}
if (!isMarketplaceListingsFolder())
{
items.push_back(std::string("New Script"));
items.push_back(std::string("New Note"));
items.push_back(std::string("New Gesture"));
+ items.push_back(std::string("New Material"));
items.push_back(std::string("New Clothes"));
items.push_back(std::string("New Body Parts"));
items.push_back(std::string("New Settings"));
items.push_back(std::string("upload_def"));
+
+ menu_items_added = true;
if (!LLEnvironment::instance().isInventoryEnabled())
{
@@ -4183,6 +4204,10 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
}
}
+ if (menu_items_added)
+ {
+ items.push_back(std::string("Create Separator"));
+ }
}
getClipboardEntries(false, items, disabled_items, flags);
}
@@ -4457,6 +4482,7 @@ BOOL LLFolderBridge::dragOrDrop(MASK mask, BOOL drop,
case DAD_GESTURE:
case DAD_MESH:
case DAD_SETTINGS:
+ case DAD_MATERIAL:
accept = dragItemIntoFolder(inv_item, drop, tooltip_msg);
break;
case DAD_LINK:
@@ -6086,6 +6112,7 @@ BOOL LLCallingCardBridge::dragOrDrop(MASK mask, BOOL drop,
case DAD_GESTURE:
case DAD_MESH:
case DAD_SETTINGS:
+ case DAD_MATERIAL:
{
LLInventoryItem* inv_item = (LLInventoryItem*)cargo_data;
const LLPermissions& perm = inv_item->getPermissions();
@@ -7277,6 +7304,39 @@ bool LLSettingsBridge::canUpdateRegion() const
// +=================================================+
+// | LLMaterialBridge |
+// +=================================================+
+
+void LLMaterialBridge::openItem()
+{
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
+ }
+}
+
+void LLMaterialBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ LL_DEBUGS() << "LLMaterialBridge::buildContextMenu()" << LL_ENDL;
+
+ if (isMarketplaceListingsFolder())
+ {
+ menuentry_vec_t items;
+ menuentry_vec_t disabled_items;
+ addMarketplaceContextMenuOptions(flags, items, disabled_items);
+ items.push_back(std::string("Properties"));
+ getClipboardEntries(false, items, disabled_items, flags);
+ hide_context_entries(menu, items, disabled_items);
+ }
+ else
+ {
+ LLItemBridge::buildContextMenu(menu, flags);
+ }
+}
+
+
+// +=================================================+
// | LLLinkBridge |
// +=================================================+
// For broken folder links.
@@ -7663,6 +7723,24 @@ protected:
LLSettingsBridgeAction(const LLUUID& id, LLInventoryModel* model) : LLInvFVBridgeAction(id, model) {}
};
+class LLMaterialBridgeAction : public LLInvFVBridgeAction
+{
+ friend class LLInvFVBridgeAction;
+public:
+ void doIt() override
+ {
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ LLFloaterReg::showInstance("material_editor", LLSD(item->getUUID()), TAKE_FOCUS_YES);
+ }
+ LLInvFVBridgeAction::doIt();
+ }
+ ~LLMaterialBridgeAction() = default;
+private:
+ LLMaterialBridgeAction(const LLUUID& id,LLInventoryModel* model) : LLInvFVBridgeAction(id,model) {}
+};
+
LLInvFVBridgeAction* LLInvFVBridgeAction::createAction(LLAssetType::EType asset_type,
const LLUUID& uuid,
@@ -7705,6 +7783,9 @@ LLInvFVBridgeAction* LLInvFVBridgeAction::createAction(LLAssetType::EType asset_
case LLAssetType::AT_SETTINGS:
action = new LLSettingsBridgeAction(uuid, model);
break;
+ case LLAssetType::AT_MATERIAL:
+ action = new LLMaterialBridgeAction(uuid, model);
+ break;
default:
break;
}
diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h
index bdffecf1c6..d3cd180174 100644
--- a/indra/newview/llinventorybridge.h
+++ b/indra/newview/llinventorybridge.h
@@ -637,6 +637,17 @@ protected:
};
+class LLMaterialBridge : public LLItemBridge
+{
+public:
+ LLMaterialBridge(LLInventoryPanel* inventory,
+ LLFolderView* root,
+ const LLUUID& uuid) :
+ LLItemBridge(inventory, root, uuid) {}
+ virtual void openItem();
+ virtual void buildContextMenu(LLMenuGL& menu, U32 flags);
+};
+
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLInvFVBridgeAction
//
diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp
index e3a6b2dc85..374790b917 100644
--- a/indra/newview/llinventoryfilter.cpp
+++ b/indra/newview/llinventoryfilter.cpp
@@ -1305,6 +1305,18 @@ const std::string& LLInventoryFilter::getFilterText()
filtered_by_all_types = FALSE;
}
+ if (isFilterObjectTypesWith(LLInventoryType::IT_MATERIAL))
+ {
+ filtered_types += LLTrans::getString("Materials");
+ filtered_by_type = TRUE;
+ num_filter_types++;
+ }
+ else
+ {
+ not_filtered_types += LLTrans::getString("Materials");
+ filtered_by_all_types = FALSE;
+ }
+
if (isFilterObjectTypesWith(LLInventoryType::IT_NOTECARD))
{
filtered_types += LLTrans::getString("Notecards");
diff --git a/indra/newview/llinventoryicon.cpp b/indra/newview/llinventoryicon.cpp
index 44e493fdf4..e9b0e8404a 100644
--- a/indra/newview/llinventoryicon.cpp
+++ b/indra/newview/llinventoryicon.cpp
@@ -99,6 +99,8 @@ LLIconDictionary::LLIconDictionary()
addEntry(LLInventoryType::ICONNAME_SETTINGS_DAY, new IconEntry("Inv_SettingsDay"));
addEntry(LLInventoryType::ICONNAME_SETTINGS, new IconEntry("Inv_Settings"));
+ addEntry(LLInventoryType::ICONNAME_MATERIAL, new IconEntry("Inv_Material"));
+
addEntry(LLInventoryType::ICONNAME_INVALID, new IconEntry("Inv_Invalid"));
addEntry(LLInventoryType::ICONNAME_UNKNOWN, new IconEntry("Inv_Unknown"));
@@ -177,6 +179,9 @@ const std::string& LLInventoryIcon::getIconName(LLAssetType::EType asset_type,
case LLAssetType::AT_SETTINGS:
idx = assignSettingsIcon(misc_flag);
break;
+ case LLAssetType::AT_MATERIAL:
+ idx = LLInventoryType::ICONNAME_MATERIAL;
+ break;
case LLAssetType::AT_UNKNOWN:
idx = LLInventoryType::ICONNAME_UNKNOWN;
default:
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index b0d6f9d9c3..75dda5557d 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -227,8 +227,6 @@ LLInventoryModel::LLInventoryModel()
mHttpOptions(),
mHttpHeaders(),
mHttpPolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID),
- mHttpPriorityFG(0),
- mHttpPriorityBG(0),
mCategoryLock(),
mItemLock(),
mValidationInfo(new LLInventoryValidationInfo)
@@ -644,6 +642,11 @@ const LLUUID LLInventoryModel::findUserDefinedCategoryUUIDForType(LLFolderType::
cat_id = LLUUID(gSavedPerAccountSettings.getString("AnimationUploadFolder"));
break;
}
+ case LLFolderType::FT_MATERIAL:
+ {
+ cat_id = LLUUID(gSavedPerAccountSettings.getString("PBRUploadFolder"));
+ break;
+ }
default:
break;
}
@@ -2816,7 +2819,6 @@ LLCore::HttpHandle LLInventoryModel::requestPost(bool foreground,
handle = LLCoreHttpUtil::requestPostWithLLSD(request,
mHttpPolicyClass,
- (foreground ? mHttpPriorityFG : mHttpPriorityBG),
url,
body,
mHttpOptions,
@@ -2842,6 +2844,7 @@ void LLInventoryModel::createCommonSystemCategories()
gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, true);
gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK, true); // folder should exist before user tries to 'landmark this'
gInventory.findCategoryUUIDForType(LLFolderType::FT_SETTINGS, true);
+ gInventory.findCategoryUUIDForType(LLFolderType::FT_MATERIAL, true); // probably should be server created
gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, true);
}
@@ -4334,7 +4337,11 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
{
LL_WARNS("Inventory") << "Fatal inventory corruption: system folder type has excess copies under root, type " << ft << " count " << count_under_root << LL_ENDL;
validation_info->mDuplicateRequiredSystemFolders.insert(folder_type);
- if (!is_automatic && folder_type != LLFolderType::FT_SETTINGS)
+ if (!is_automatic
+ && folder_type != LLFolderType::FT_SETTINGS
+ // FT_MATERIAL might need to be automatic like the rest of upload folders
+ && folder_type != LLFolderType::FT_MATERIAL
+ )
{
// It is a fatal problem or can lead to fatal problems for COF,
// outfits, trash and other non-automatic folders.
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index c4133ff9bb..cb960d8185 100644
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -621,8 +621,6 @@ private:
LLCore::HttpOptions::ptr_t mHttpOptions;
LLCore::HttpHeaders::ptr_t mHttpHeaders;
LLCore::HttpRequest::policy_t mHttpPolicyClass;
- LLCore::HttpRequest::priority_t mHttpPriorityFG;
- LLCore::HttpRequest::priority_t mHttpPriorityBG;
/** HTTP Transport
** **
diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp
index c065c76dca..7e5a2b3950 100644
--- a/indra/newview/llinventorypanel.cpp
+++ b/indra/newview/llinventorypanel.cpp
@@ -1617,6 +1617,10 @@ void LLInventoryPanel::fileUploadLocation(const LLSD& userdata)
{
gSavedPerAccountSettings.setString("AnimationUploadFolder", LLFolderBridge::sSelf.get()->getUUID().asString());
}
+ else if (param == "pbr_material")
+ {
+ gSavedPerAccountSettings.setString("PBRUploadFolder", LLFolderBridge::sSelf.get()->getUUID().asString());
+ }
}
void LLInventoryPanel::purgeSelectedItems()
@@ -2015,7 +2019,43 @@ LLInventoryRecentItemsPanel::LLInventoryRecentItemsPanel( const Params& params)
void LLAssetFilteredInventoryPanel::initFromParams(const Params& p)
{
- mAssetType = LLAssetType::lookup(p.filter_asset_type.getValue());
+ // Init asset types
+ std::string types = p.filter_asset_types.getValue();
+
+ typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
+ boost::char_separator<char> sep("|");
+ tokenizer tokens(types, sep);
+ tokenizer::iterator token_iter = tokens.begin();
+
+ memset(mAssetTypes, 0, LLAssetType::AT_COUNT * sizeof(bool));
+ while (token_iter != tokens.end())
+ {
+ const std::string& token_str = *token_iter;
+ LLAssetType::EType asset_type = LLAssetType::lookup(token_str);
+ if (asset_type > LLAssetType::AT_NONE && asset_type < LLAssetType::AT_COUNT)
+ {
+ mAssetTypes[asset_type] = true;
+ }
+ ++token_iter;
+ }
+
+ // Init drag types
+ memset(mDragTypes, 0, EDragAndDropType::DAD_COUNT * sizeof(bool));
+ for (S32 i = 0; i < LLAssetType::AT_COUNT; i++)
+ {
+ if (mAssetTypes[i])
+ {
+ EDragAndDropType drag_type = LLViewerAssetType::lookupDragAndDropType((LLAssetType::EType)i);
+ if (drag_type != DAD_NONE)
+ {
+ mDragTypes[drag_type] = true;
+ }
+ }
+ }
+ // Always show AT_CATEGORY, but it shouldn't get into mDragTypes
+ mAssetTypes[LLAssetType::AT_CATEGORY] = true;
+
+ // Init the panel
LLInventoryPanel::initFromParams(p);
U64 filter_cats = getFilter().getFilterCategoryTypes();
filter_cats &= ~(1ULL << LLFolderType::FT_MARKETPLACE_LISTINGS);
@@ -2033,10 +2073,9 @@ BOOL LLAssetFilteredInventoryPanel::handleDragAndDrop(S32 x, S32 y, MASK mask, B
if (mAcceptsDragAndDrop)
{
- EDragAndDropType allow_type = LLViewerAssetType::lookupDragAndDropType(mAssetType);
// Don't allow DAD_CATEGORY here since it can contain other items besides required assets
// We should see everything we drop!
- if (allow_type == cargo_type)
+ if (mDragTypes[cargo_type])
{
result = LLInventoryPanel::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
}
@@ -2052,8 +2091,14 @@ bool LLAssetFilteredInventoryPanel::typedViewsFilter(const LLUUID& id, LLInvento
{
return false;
}
+ LLAssetType::EType asset_type = objectp->getType();
+
+ if (asset_type < 0 || asset_type >= LLAssetType::AT_COUNT)
+ {
+ return false;
+ }
- if (objectp->getType() != mAssetType && objectp->getType() != LLAssetType::AT_CATEGORY)
+ if (!mAssetTypes[asset_type])
{
return false;
}
@@ -2069,11 +2114,16 @@ void LLAssetFilteredInventoryPanel::itemChanged(const LLUUID& id, U32 mask, cons
return;
}
- if (model_item
- && model_item->getType() != mAssetType
- && model_item->getType() != LLAssetType::AT_CATEGORY)
+ if (model_item)
{
- return;
+ LLAssetType::EType asset_type = model_item->getType();
+
+ if (asset_type < 0
+ || asset_type >= LLAssetType::AT_COUNT
+ || !mAssetTypes[asset_type])
+ {
+ return;
+ }
}
LLInventoryPanel::itemChanged(id, mask, model_item);
@@ -2109,6 +2159,7 @@ namespace LLInitParam
declare(LLFolderType::lookup(LLFolderType::FT_OUTBOX) , LLFolderType::FT_OUTBOX);
declare(LLFolderType::lookup(LLFolderType::FT_BASIC_ROOT) , LLFolderType::FT_BASIC_ROOT);
declare(LLFolderType::lookup(LLFolderType::FT_SETTINGS) , LLFolderType::FT_SETTINGS);
+ declare(LLFolderType::lookup(LLFolderType::FT_MATERIAL) , LLFolderType::FT_MATERIAL);
declare(LLFolderType::lookup(LLFolderType::FT_MARKETPLACE_LISTINGS) , LLFolderType::FT_MARKETPLACE_LISTINGS);
declare(LLFolderType::lookup(LLFolderType::FT_MARKETPLACE_STOCK), LLFolderType::FT_MARKETPLACE_STOCK);
declare(LLFolderType::lookup(LLFolderType::FT_MARKETPLACE_VERSION), LLFolderType::FT_MARKETPLACE_VERSION);
diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h
index 552c61b915..d5219a22e7 100644
--- a/indra/newview/llinventorypanel.h
+++ b/indra/newview/llinventorypanel.h
@@ -393,9 +393,9 @@ public:
struct Params
: public LLInitParam::Block<Params, LLInventoryPanel::Params>
{
- Mandatory<std::string> filter_asset_type;
+ Mandatory<std::string> filter_asset_types;
- Params() : filter_asset_type("filter_asset_type") {}
+ Params() : filter_asset_types("filter_asset_types") {}
};
void initFromParams(const Params& p);
@@ -416,7 +416,8 @@ protected:
/*virtual*/ void itemChanged(const LLUUID& item_id, U32 mask, const LLInventoryObject* model_item) override;
private:
- LLAssetType::EType mAssetType;
+ bool mAssetTypes[LLAssetType::AT_COUNT];
+ bool mDragTypes[EDragAndDropType::DAD_COUNT];
};
#endif // LL_LLINVENTORYPANEL_H
diff --git a/indra/newview/lllocalbitmaps.cpp b/indra/newview/lllocalbitmaps.cpp
index de8db69e19..257208470e 100644
--- a/indra/newview/lllocalbitmaps.cpp
+++ b/indra/newview/lllocalbitmaps.cpp
@@ -47,7 +47,6 @@
/* misc headers */
#include "llscrolllistctrl.h"
-#include "llfilepicker.h"
#include "lllocaltextureobject.h"
#include "llviewertexturelist.h"
#include "llviewerobjectlist.h"
@@ -62,6 +61,7 @@
#include "pipeline.h"
#include "llmaterialmgr.h"
#include "llimagedimensionsinfo.h"
+#include "llinventoryicon.h"
#include "llviewercontrol.h"
#include "lltrans.h"
#include "llviewerdisplay.h"
@@ -919,7 +919,22 @@ LLLocalBitmapMgr::~LLLocalBitmapMgr()
mBitmapList.clear();
}
-LLUUID LLLocalBitmapMgr::addUnit(const std::string &filename)
+bool LLLocalBitmapMgr::addUnit(const std::vector<std::string>& filenames)
+{
+ bool add_successful = false;
+ std::vector<std::string>::const_iterator iter = filenames.begin();
+ while (iter != filenames.end())
+ {
+ if (!iter->empty() && addUnit(*iter).notNull())
+ {
+ add_successful = true;
+ }
+ iter++;
+ }
+ return add_successful;
+}
+
+LLUUID LLLocalBitmapMgr::addUnit(const std::string& filename)
{
if (!checkTextureDimensions(filename))
{
@@ -949,31 +964,6 @@ LLUUID LLLocalBitmapMgr::addUnit(const std::string &filename)
return LLUUID::null;
}
-bool LLLocalBitmapMgr::addUnit()
-{
- bool add_successful = false;
-
- LLFilePicker& picker = LLFilePicker::instance();
- if (picker.getMultipleOpenFiles(LLFilePicker::FFLOAD_IMAGE))
- {
- mTimer.stopTimer();
-
- std::string filename = picker.getFirstFile();
- while(!filename.empty())
- {
- if (addUnit(filename).notNull())
- {
- add_successful = true;
- }
- filename = picker.getNextFile();
- }
-
- mTimer.startTimer();
- }
-
- return add_successful;
-}
-
bool LLLocalBitmapMgr::checkTextureDimensions(std::string filename)
{
std::string exten = gDirUtilp->getExtension(filename);
@@ -1079,7 +1069,9 @@ void LLLocalBitmapMgr::feedScrollList(LLScrollListCtrl* ctrl)
{
if (ctrl)
{
- ctrl->clearRows();
+ std::string icon_name = LLInventoryIcon::getIconName(
+ LLAssetType::AT_TEXTURE,
+ LLInventoryType::IT_NONE);
if (!mBitmapList.empty())
{
@@ -1087,13 +1079,19 @@ void LLLocalBitmapMgr::feedScrollList(LLScrollListCtrl* ctrl)
iter != mBitmapList.end(); iter++)
{
LLSD element;
- element["columns"][0]["column"] = "unit_name";
- element["columns"][0]["type"] = "text";
- element["columns"][0]["value"] = (*iter)->getShortName();
- element["columns"][1]["column"] = "unit_id_HIDDEN";
- element["columns"][1]["type"] = "text";
- element["columns"][1]["value"] = (*iter)->getTrackingID();
+ element["columns"][0]["column"] = "icon";
+ element["columns"][0]["type"] = "icon";
+ element["columns"][0]["value"] = icon_name;
+
+ element["columns"][1]["column"] = "unit_name";
+ element["columns"][1]["type"] = "text";
+ element["columns"][1]["value"] = (*iter)->getShortName();
+
+ LLSD data;
+ data["id"] = (*iter)->getTrackingID();
+ data["type"] = (S32)LLAssetType::AT_TEXTURE;
+ element["value"] = data;
ctrl->addElement(element);
}
diff --git a/indra/newview/lllocalbitmaps.h b/indra/newview/lllocalbitmaps.h
index 02b8834c16..bb026ed3aa 100644
--- a/indra/newview/lllocalbitmaps.h
+++ b/indra/newview/lllocalbitmaps.h
@@ -115,8 +115,8 @@ class LLLocalBitmapMgr : public LLSingleton<LLLocalBitmapMgr>
LLSINGLETON(LLLocalBitmapMgr);
~LLLocalBitmapMgr();
public:
- bool addUnit();
- LLUUID addUnit(const std::string &filename);
+ bool addUnit(const std::vector<std::string>& filenames);
+ LLUUID addUnit(const std::string& filename);
void delUnit(LLUUID tracking_id);
bool checkTextureDimensions(std::string filename);
diff --git a/indra/newview/lllocalgltfmaterials.cpp b/indra/newview/lllocalgltfmaterials.cpp
new file mode 100644
index 0000000000..a9099b1ce9
--- /dev/null
+++ b/indra/newview/lllocalgltfmaterials.cpp
@@ -0,0 +1,465 @@
+/**
+ * @file lllocalrendermaterials.cpp
+ * @brief Local GLTF materials source
+ *
+ * $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$
+ */
+
+/* precompiled headers */
+#include "llviewerprecompiledheaders.h"
+
+/* own header */
+#include "lllocalgltfmaterials.h"
+
+/* boost: will not compile unless equivalent is undef'd, beware. */
+#include "fix_macros.h"
+#include <boost/filesystem.hpp>
+
+/* time headers */
+#include <time.h>
+#include <ctime>
+
+/* misc headers */
+#include "llgltfmateriallist.h"
+#include "llimage.h"
+#include "llinventoryicon.h"
+#include "llmaterialmgr.h"
+#include "llnotificationsutil.h"
+#include "llscrolllistctrl.h"
+#include "lltinygltfhelper.h"
+#include "llviewertexture.h"
+
+/*=======================================*/
+/* Formal declarations, constants, etc. */
+/*=======================================*/
+
+static const F32 LL_LOCAL_TIMER_HEARTBEAT = 3.0;
+static const S32 LL_LOCAL_UPDATE_RETRIES = 5;
+
+/*=======================================*/
+/* LLLocalGLTFMaterial: unit class */
+/*=======================================*/
+LLLocalGLTFMaterial::LLLocalGLTFMaterial(std::string filename, S32 index)
+ : mFilename(filename)
+ , mShortName(gDirUtilp->getBaseFileName(filename, true))
+ , mLastModified()
+ , mLinkStatus(LS_ON)
+ , mUpdateRetries(LL_LOCAL_UPDATE_RETRIES)
+ , mMaterialIndex(index)
+{
+ mTrackingID.generate();
+
+ /* extension */
+ std::string temp_exten = gDirUtilp->getExtension(mFilename);
+
+ if (temp_exten == "gltf")
+ {
+ mExtension = ET_MATERIAL_GLTF;
+ }
+ else if (temp_exten == "glb")
+ {
+ mExtension = ET_MATERIAL_GLB;
+ }
+ else
+ {
+ LL_WARNS("GLTF") << "File of no valid extension given, local material creation aborted." << "\n"
+ << "Filename: " << mFilename << LL_ENDL;
+ return; // no valid extension.
+ }
+}
+
+LLLocalGLTFMaterial::~LLLocalGLTFMaterial()
+{
+ // gGLTFMaterialList will clean itself
+}
+
+/* accessors */
+std::string LLLocalGLTFMaterial::getFilename() const
+{
+ return mFilename;
+}
+
+std::string LLLocalGLTFMaterial::getShortName() const
+{
+ return mShortName;
+}
+
+LLUUID LLLocalGLTFMaterial::getTrackingID() const
+{
+ return mTrackingID;
+}
+
+LLUUID LLLocalGLTFMaterial::getWorldID() const
+{
+ return mWorldID;
+}
+
+S32 LLLocalGLTFMaterial::getIndexInFile() const
+{
+ return mMaterialIndex;
+}
+
+/* update functions */
+bool LLLocalGLTFMaterial::updateSelf()
+{
+ bool updated = false;
+
+ if (mLinkStatus == LS_ON)
+ {
+ // verifying that the file exists
+ if (gDirUtilp->fileExists(mFilename))
+ {
+ // verifying that the file has indeed been modified
+
+#ifndef LL_WINDOWS
+ const std::time_t temp_time = boost::filesystem::last_write_time(boost::filesystem::path(mFilename));
+#else
+ const std::time_t temp_time = boost::filesystem::last_write_time(boost::filesystem::path(utf8str_to_utf16str(mFilename)));
+#endif
+ LLSD new_last_modified = asctime(localtime(&temp_time));
+
+ if (mLastModified.asString() != new_last_modified.asString())
+ {
+ if (loadMaterial())
+ {
+ // decode is successful, we can safely proceed.
+ if (mWorldID.isNull())
+ {
+ mWorldID.generate();
+ }
+ mLastModified = new_last_modified;
+
+ // addMaterial will replace material witha a new
+ // pointer if value already exists but we are
+ // reusing existing pointer, so it should add only.
+ gGLTFMaterialList.addMaterial(mWorldID, this);
+
+ mUpdateRetries = LL_LOCAL_UPDATE_RETRIES;
+ updated = true;
+ }
+
+ // if decoding failed, we get here and it will attempt to decode it in the next cycles
+ // until mUpdateRetries runs out. this is done because some software lock the material while writing to it
+ else
+ {
+ if (mUpdateRetries)
+ {
+ mUpdateRetries--;
+ }
+ else
+ {
+ LL_WARNS("GLTF") << "During the update process the following file was found" << "\n"
+ << "but could not be opened or decoded for " << LL_LOCAL_UPDATE_RETRIES << " attempts." << "\n"
+ << "Filename: " << mFilename << "\n"
+ << "Disabling further update attempts for this file." << LL_ENDL;
+
+ LLSD notif_args;
+ notif_args["FNAME"] = mFilename;
+ notif_args["NRETRIES"] = LL_LOCAL_UPDATE_RETRIES;
+ LLNotificationsUtil::add("LocalBitmapsUpdateFailedFinal", notif_args);
+
+ mLinkStatus = LS_BROKEN;
+ }
+ }
+ }
+
+ } // end if file exists
+
+ else
+ {
+ LL_WARNS("GLTF") << "During the update process, the following file was not found." << "\n"
+ << "Filename: " << mFilename << "\n"
+ << "Disabling further update attempts for this file." << LL_ENDL;
+
+ LLSD notif_args;
+ notif_args["FNAME"] = mFilename;
+ LLNotificationsUtil::add("LocalBitmapsUpdateFileNotFound", notif_args);
+
+ mLinkStatus = LS_BROKEN;
+ }
+ }
+
+ return updated;
+}
+
+bool LLLocalGLTFMaterial::loadMaterial()
+{
+ bool decode_successful = false;
+
+ switch (mExtension)
+ {
+ case ET_MATERIAL_GLTF:
+ case ET_MATERIAL_GLB:
+ {
+ std::string filename_lc = mFilename;
+ LLStringUtil::toLower(filename_lc);
+ std::string material_name;
+
+ // Might be a good idea to make these textures into local textures
+ decode_successful = LLTinyGLTFHelper::getMaterialFromFile(
+ mFilename,
+ mMaterialIndex,
+ this,
+ material_name);
+
+ if (!material_name.empty())
+ {
+ mShortName = gDirUtilp->getBaseFileName(filename_lc, true) + " (" + material_name + ")";
+ }
+
+ break;
+ }
+
+ default:
+ {
+ // separating this into -several- LL_WARNS() calls because in the extremely unlikely case that this happens
+ // accessing mFilename and any other object properties might very well crash the viewer.
+ // getting here should be impossible, or there's been a pretty serious bug.
+
+ LL_WARNS("GLTF") << "During a decode attempt, the following local material had no properly assigned extension." << LL_ENDL;
+ LL_WARNS("GLTF") << "Filename: " << mFilename << LL_ENDL;
+ LL_WARNS("GLTF") << "Disabling further update attempts for this file." << LL_ENDL;
+ mLinkStatus = LS_BROKEN;
+ }
+ }
+
+ return decode_successful;
+}
+
+
+/*=======================================*/
+/* LLLocalGLTFMaterialTimer: timer class */
+/*=======================================*/
+LLLocalGLTFMaterialTimer::LLLocalGLTFMaterialTimer() : LLEventTimer(LL_LOCAL_TIMER_HEARTBEAT)
+{
+}
+
+LLLocalGLTFMaterialTimer::~LLLocalGLTFMaterialTimer()
+{
+}
+
+void LLLocalGLTFMaterialTimer::startTimer()
+{
+ mEventTimer.start();
+}
+
+void LLLocalGLTFMaterialTimer::stopTimer()
+{
+ mEventTimer.stop();
+}
+
+bool LLLocalGLTFMaterialTimer::isRunning()
+{
+ return mEventTimer.getStarted();
+}
+
+BOOL LLLocalGLTFMaterialTimer::tick()
+{
+ // todo: do on idle? No point in timer
+ LLLocalGLTFMaterialMgr::getInstance()->doUpdates();
+ return FALSE;
+}
+
+/*=======================================*/
+/* LLLocalGLTFMaterialMgr: manager class */
+/*=======================================*/
+LLLocalGLTFMaterialMgr::LLLocalGLTFMaterialMgr()
+{
+}
+
+LLLocalGLTFMaterialMgr::~LLLocalGLTFMaterialMgr()
+{
+ mMaterialList.clear();
+}
+
+S32 LLLocalGLTFMaterialMgr::addUnit(const std::vector<std::string>& filenames)
+{
+ S32 add_count = 0;
+ std::vector<std::string>::const_iterator iter = filenames.begin();
+ while (iter != filenames.end())
+ {
+ if (!iter->empty())
+ {
+ add_count += addUnit(*iter);
+ }
+ iter++;
+ }
+ return add_count;
+}
+
+S32 LLLocalGLTFMaterialMgr::addUnit(const std::string& filename)
+{
+ S32 materials_in_file = LLTinyGLTFHelper::getMaterialCountFromFile(filename);
+ if (materials_in_file <= 0)
+ {
+ return 0;
+ }
+
+ S32 loaded_materials = 0;
+ for (S32 i = 0; i < materials_in_file; i++)
+ {
+ // Todo: this is rather inefficient, files will be spammed with
+ // separate loads and date checks, find a way to improve this.
+ // May be doUpdates() should be checking individual files.
+ LLPointer<LLLocalGLTFMaterial> unit = new LLLocalGLTFMaterial(filename, i);
+
+ // load material from file
+ if (unit->updateSelf())
+ {
+ mMaterialList.emplace_back(unit);
+ loaded_materials++;
+ }
+ else
+ {
+ LL_WARNS("GLTF") << "Attempted to add invalid or unreadable image file, attempt cancelled.\n"
+ << "Filename: " << filename << LL_ENDL;
+
+ LLSD notif_args;
+ notif_args["FNAME"] = filename;
+ LLNotificationsUtil::add("LocalGLTFVerifyFail", notif_args);
+
+ unit = NULL;
+ }
+ }
+
+ return loaded_materials;
+}
+
+void LLLocalGLTFMaterialMgr::delUnit(LLUUID tracking_id)
+{
+ if (!mMaterialList.empty())
+ {
+ std::vector<LLLocalGLTFMaterial*> to_delete;
+ for (local_list_iter iter = mMaterialList.begin(); iter != mMaterialList.end(); iter++)
+ { /* finding which ones we want deleted and making a separate list */
+ LLLocalGLTFMaterial* unit = *iter;
+ if (unit->getTrackingID() == tracking_id)
+ {
+ to_delete.push_back(unit);
+ }
+ }
+
+ for (std::vector<LLLocalGLTFMaterial*>::iterator del_iter = to_delete.begin();
+ del_iter != to_delete.end(); del_iter++)
+ { /* iterating over a temporary list, hence preserving the iterator validity while deleting. */
+ LLLocalGLTFMaterial* unit = *del_iter;
+ mMaterialList.remove(unit);
+
+ unit = NULL;
+ }
+ }
+}
+
+LLUUID LLLocalGLTFMaterialMgr::getWorldID(LLUUID tracking_id)
+{
+ LLUUID world_id = LLUUID::null;
+
+ for (local_list_iter iter = mMaterialList.begin(); iter != mMaterialList.end(); iter++)
+ {
+ LLLocalGLTFMaterial* unit = *iter;
+ if (unit->getTrackingID() == tracking_id)
+ {
+ world_id = unit->getWorldID();
+ }
+ }
+
+ return world_id;
+}
+
+bool LLLocalGLTFMaterialMgr::isLocal(const LLUUID world_id)
+{
+ for (local_list_iter iter = mMaterialList.begin(); iter != mMaterialList.end(); iter++)
+ {
+ LLLocalGLTFMaterial* unit = *iter;
+ if (unit->getWorldID() == world_id)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+void LLLocalGLTFMaterialMgr::getFilenameAndIndex(LLUUID tracking_id, std::string &filename, S32 &index)
+{
+ filename = "";
+ index = 0;
+
+ for (local_list_iter iter = mMaterialList.begin(); iter != mMaterialList.end(); iter++)
+ {
+ LLLocalGLTFMaterial* unit = *iter;
+ if (unit->getTrackingID() == tracking_id)
+ {
+ filename = unit->getFilename();
+ index = unit->getIndexInFile();
+ }
+ }
+}
+
+// probably shouldn't be here, but at the moment this mirrors lllocalbitmaps
+void LLLocalGLTFMaterialMgr::feedScrollList(LLScrollListCtrl* ctrl)
+{
+ if (ctrl)
+ {
+ if (!mMaterialList.empty())
+ {
+ std::string icon_name = LLInventoryIcon::getIconName(
+ LLAssetType::AT_MATERIAL,
+ LLInventoryType::IT_NONE);
+
+ for (local_list_iter iter = mMaterialList.begin();
+ iter != mMaterialList.end(); iter++)
+ {
+ LLSD element;
+
+ element["columns"][0]["column"] = "icon";
+ element["columns"][0]["type"] = "icon";
+ element["columns"][0]["value"] = icon_name;
+
+ element["columns"][1]["column"] = "unit_name";
+ element["columns"][1]["type"] = "text";
+ element["columns"][1]["value"] = (*iter)->getShortName();
+
+ LLSD data;
+ data["id"] = (*iter)->getTrackingID();
+ data["type"] = (S32)LLAssetType::AT_MATERIAL;
+ element["value"] = data;
+
+ ctrl->addElement(element);
+ }
+ }
+ }
+
+}
+
+void LLLocalGLTFMaterialMgr::doUpdates()
+{
+ // preventing theoretical overlap in cases with huge number of loaded images.
+ mTimer.stopTimer();
+
+ for (local_list_iter iter = mMaterialList.begin(); iter != mMaterialList.end(); iter++)
+ {
+ (*iter)->updateSelf();
+ }
+
+ mTimer.startTimer();
+}
+
diff --git a/indra/newview/lllocalgltfmaterials.h b/indra/newview/lllocalgltfmaterials.h
new file mode 100644
index 0000000000..6919b9b4b2
--- /dev/null
+++ b/indra/newview/lllocalgltfmaterials.h
@@ -0,0 +1,118 @@
+/**
+ * @file lllocalrendermaterials.h
+ * @brief Local GLTF materials header
+ *
+ * $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$
+ */
+
+#ifndef LL_LOCALGLTFMATERIALS_H
+#define LL_LOCALGLTFMATERIALS_H
+
+#include "lleventtimer.h"
+#include "llpointer.h"
+#include "llgltfmateriallist.h"
+
+class LLScrollListCtrl;
+class LLGLTFMaterial;
+class LLViewerObject;
+
+class LLLocalGLTFMaterial : public LLFetchedGLTFMaterial
+{
+public: /* main */
+ LLLocalGLTFMaterial(std::string filename, S32 index);
+ virtual ~LLLocalGLTFMaterial();
+
+public: /* accessors */
+ std::string getFilename() const;
+ std::string getShortName() const;
+ LLUUID getTrackingID() const;
+ LLUUID getWorldID() const;
+ S32 getIndexInFile() const;
+
+public:
+ bool updateSelf();
+
+private:
+ bool loadMaterial();
+
+private: /* private enums */
+ enum ELinkStatus
+ {
+ LS_ON,
+ LS_BROKEN,
+ };
+
+ enum EExtension
+ {
+ ET_MATERIAL_GLTF,
+ ET_MATERIAL_GLB,
+ };
+
+private: /* members */
+ std::string mFilename;
+ std::string mShortName;
+ LLUUID mTrackingID;
+ LLUUID mWorldID;
+ LLSD mLastModified;
+ EExtension mExtension;
+ ELinkStatus mLinkStatus;
+ S32 mUpdateRetries;
+ S32 mMaterialIndex; // Single file can have more than one
+};
+
+class LLLocalGLTFMaterialTimer : public LLEventTimer
+{
+public:
+ LLLocalGLTFMaterialTimer();
+ ~LLLocalGLTFMaterialTimer();
+
+public:
+ void startTimer();
+ void stopTimer();
+ bool isRunning();
+ BOOL tick();
+};
+
+class LLLocalGLTFMaterialMgr : public LLSingleton<LLLocalGLTFMaterialMgr>
+{
+ LLSINGLETON(LLLocalGLTFMaterialMgr);
+ ~LLLocalGLTFMaterialMgr();
+public:
+ S32 addUnit(const std::vector<std::string>& filenames);
+ S32 addUnit(const std::string& filename); // file can hold multiple materials
+ void delUnit(LLUUID tracking_id);
+
+ LLUUID getWorldID(LLUUID tracking_id);
+ bool isLocal(LLUUID world_id);
+ void getFilenameAndIndex(LLUUID tracking_id, std::string &filename, S32 &index);
+
+ void feedScrollList(LLScrollListCtrl* ctrl);
+ void doUpdates();
+
+private:
+ std::list<LLPointer<LLLocalGLTFMaterial> > mMaterialList;
+ LLLocalGLTFMaterialTimer mTimer;
+ typedef std::list<LLPointer<LLLocalGLTFMaterial> >::iterator local_list_iter;
+};
+
+#endif // LL_LOCALGLTFMATERIALS_H
+
diff --git a/indra/newview/llmaniprotate.cpp b/indra/newview/llmaniprotate.cpp
index d85a846f4d..6b9543d433 100644
--- a/indra/newview/llmaniprotate.cpp
+++ b/indra/newview/llmaniprotate.cpp
@@ -277,7 +277,7 @@ void LLManipRotate::render()
LLGLEnable cull_face(GL_CULL_FACE);
LLGLEnable clip_plane0(GL_CLIP_PLANE0);
LLGLDepthTest gls_depth(GL_FALSE);
- LLGLDisable gls_stencil(GL_STENCIL_TEST);
+ //LLGLDisable gls_stencil(GL_STENCIL_TEST);
// First pass: centers. Second pass: sides.
for( S32 i=0; i<2; i++ )
diff --git a/indra/newview/llmanipscale.cpp b/indra/newview/llmanipscale.cpp
index e74fd1241b..c15f1da26b 100644
--- a/indra/newview/llmanipscale.cpp
+++ b/indra/newview/llmanipscale.cpp
@@ -757,7 +757,7 @@ void LLManipScale::renderBoxHandle( F32 x, F32 y, F32 z )
{
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
LLGLDepthTest gls_depth(GL_FALSE);
- LLGLDisable gls_stencil(GL_STENCIL_TEST);
+ //LLGLDisable gls_stencil(GL_STENCIL_TEST);
gGL.pushMatrix();
{
diff --git a/indra/newview/llmaniptranslate.cpp b/indra/newview/llmaniptranslate.cpp
index 0b2a1ef389..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++;
}
@@ -1063,7 +1059,7 @@ void LLManipTranslate::render()
renderGuidelines();
}
{
- LLGLDisable gls_stencil(GL_STENCIL_TEST);
+ //LLGLDisable gls_stencil(GL_STENCIL_TEST);
renderTranslationHandles();
renderSnapGuides();
}
@@ -1529,7 +1525,7 @@ void LLManipTranslate::renderSnapGuides()
LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
{
- LLGLDisable stencil(GL_STENCIL_TEST);
+ //LLGLDisable stencil(GL_STENCIL_TEST);
{
LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_GREATER);
gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, getGridTexName());
@@ -1628,6 +1624,7 @@ void LLManipTranslate::highlightIntersection(LLVector3 normal,
LLQuaternion grid_rotation,
LLColor4 inner_color)
{
+#if 0 // DEPRECATED
if (!gSavedSettings.getBOOL("GridCrossSections"))
{
return;
@@ -1651,13 +1648,13 @@ void LLManipTranslate::highlightIntersection(LLVector3 normal,
}
{
- glStencilMask(stencil_mask);
- glClearStencil(1);
- glClear(GL_STENCIL_BUFFER_BIT);
+ //glStencilMask(stencil_mask); //deprecated
+ //glClearStencil(1);
+ //glClear(GL_STENCIL_BUFFER_BIT);
LLGLEnable cull_face(GL_CULL_FACE);
- LLGLEnable stencil(GL_STENCIL_TEST);
+ //LLGLEnable stencil(GL_STENCIL_TEST);
LLGLDepthTest depth (GL_TRUE, GL_FALSE, GL_ALWAYS);
- glStencilFunc(GL_ALWAYS, 0, stencil_mask);
+ //glStencilFunc(GL_ALWAYS, 0, stencil_mask);
gGL.setColorMask(false, false);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
@@ -1690,14 +1687,14 @@ void LLManipTranslate::highlightIntersection(LLVector3 normal,
}
//stencil in volumes
- glStencilOp(GL_INCR, GL_INCR, GL_INCR);
+ //glStencilOp(GL_INCR, GL_INCR, GL_INCR);
glCullFace(GL_FRONT);
for (U32 i = 0; i < num_types; i++)
{
gPipeline.renderObjects(types[i], LLVertexBuffer::MAP_VERTEX, FALSE);
}
- glStencilOp(GL_DECR, GL_DECR, GL_DECR);
+ //glStencilOp(GL_DECR, GL_DECR, GL_DECR);
glCullFace(GL_BACK);
for (U32 i = 0; i < num_types; i++)
{
@@ -1741,7 +1738,7 @@ void LLManipTranslate::highlightIntersection(LLVector3 normal,
{
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
LLGLDepthTest depth(GL_FALSE);
- LLGLEnable stencil(GL_STENCIL_TEST);
+ //LLGLEnable stencil(GL_STENCIL_TEST);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glStencilFunc(GL_EQUAL, 0, stencil_mask);
renderGrid(0,0,tiles,inner_color.mV[0], inner_color.mV[1], inner_color.mV[2], 0.25f);
@@ -1752,6 +1749,7 @@ void LLManipTranslate::highlightIntersection(LLVector3 normal,
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
gGL.popMatrix();
+#endif
}
void LLManipTranslate::renderText()
diff --git a/indra/newview/llmaterialeditor.cpp b/indra/newview/llmaterialeditor.cpp
new file mode 100644
index 0000000000..5628327ebe
--- /dev/null
+++ b/indra/newview/llmaterialeditor.cpp
@@ -0,0 +1,3289 @@
+/**
+ * @file llmaterialeditor.cpp
+ * @brief Implementation of the gltf material editor
+ *
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, 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$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llmaterialeditor.h"
+
+#include "llagent.h"
+#include "llagentbenefits.h"
+#include "llappviewer.h"
+#include "llcolorswatch.h"
+#include "llcombobox.h"
+#include "llfloaterreg.h"
+#include "llfilesystem.h"
+#include "llgltfmateriallist.h"
+#include "llinventorymodel.h"
+#include "lllocalgltfmaterials.h"
+#include "llnotificationsutil.h"
+#include "lltexturectrl.h"
+#include "lltrans.h"
+#include "llviewermenufile.h"
+#include "llviewertexture.h"
+#include "llsdutil.h"
+#include "llselectmgr.h"
+#include "llstatusbar.h" // can_afford_transaction()
+#include "lltoolpie.h"
+#include "llviewerinventory.h"
+#include "llinventory.h"
+#include "llviewerregion.h"
+#include "llvovolume.h"
+#include "roles_constants.h"
+#include "llviewerobjectlist.h"
+#include "llsdserialize.h"
+#include "llimagej2c.h"
+#include "llviewertexturelist.h"
+#include "llfloaterperms.h"
+
+#include "tinygltf/tiny_gltf.h"
+#include "lltinygltfhelper.h"
+#include <strstream>
+
+
+const std::string MATERIAL_BASE_COLOR_DEFAULT_NAME = "Base Color";
+const std::string MATERIAL_NORMAL_DEFAULT_NAME = "Normal";
+const std::string MATERIAL_METALLIC_DEFAULT_NAME = "Metallic Roughness";
+const std::string MATERIAL_EMISSIVE_DEFAULT_NAME = "Emissive";
+
+// Dirty flags
+static const U32 MATERIAL_BASE_COLOR_DIRTY = 0x1 << 0;
+static const U32 MATERIAL_BASE_COLOR_TEX_DIRTY = 0x1 << 1;
+
+static const U32 MATERIAL_NORMAL_TEX_DIRTY = 0x1 << 2;
+
+static const U32 MATERIAL_METALLIC_ROUGHTNESS_TEX_DIRTY = 0x1 << 3;
+static const U32 MATERIAL_METALLIC_ROUGHTNESS_METALNESS_DIRTY = 0x1 << 4;
+static const U32 MATERIAL_METALLIC_ROUGHTNESS_ROUGHNESS_DIRTY = 0x1 << 5;
+
+static const U32 MATERIAL_EMISIVE_COLOR_DIRTY = 0x1 << 6;
+static const U32 MATERIAL_EMISIVE_TEX_DIRTY = 0x1 << 7;
+
+static const U32 MATERIAL_DOUBLE_SIDED_DIRTY = 0x1 << 8;
+static const U32 MATERIAL_ALPHA_MODE_DIRTY = 0x1 << 9;
+static const U32 MATERIAL_ALPHA_CUTOFF_DIRTY = 0x1 << 10;
+
+LLUUID LLMaterialEditor::mOverrideObjectId;
+S32 LLMaterialEditor::mOverrideObjectTE = -1;
+bool LLMaterialEditor::mOverrideInProgress = false;
+bool LLMaterialEditor::mSelectionNeedsUpdate = true;
+
+LLFloaterComboOptions::LLFloaterComboOptions()
+ : LLFloater(LLSD())
+{
+ buildFromFile("floater_combobox_ok_cancel.xml");
+}
+
+LLFloaterComboOptions::~LLFloaterComboOptions()
+{
+
+}
+
+BOOL LLFloaterComboOptions::postBuild()
+{
+ mConfirmButton = getChild<LLButton>("combo_ok", TRUE);
+ mCancelButton = getChild<LLButton>("combo_cancel", TRUE);
+ mComboOptions = getChild<LLComboBox>("combo_options", TRUE);
+ mComboText = getChild<LLTextBox>("combo_text", TRUE);
+
+ mConfirmButton->setCommitCallback([this](LLUICtrl* ctrl, const LLSD& param) {onConfirm(); });
+ mCancelButton->setCommitCallback([this](LLUICtrl* ctrl, const LLSD& param) {onCancel(); });
+
+ return TRUE;
+}
+
+LLFloaterComboOptions* LLFloaterComboOptions::showUI(
+ combo_callback callback,
+ const std::string &title,
+ const std::string &description,
+ const std::list<std::string> &options)
+{
+ LLFloaterComboOptions* combo_picker = new LLFloaterComboOptions();
+ if (combo_picker)
+ {
+ combo_picker->mCallback = callback;
+ combo_picker->setTitle(title);
+
+ combo_picker->mComboText->setText(description);
+
+ std::list<std::string>::const_iterator iter = options.begin();
+ std::list<std::string>::const_iterator end = options.end();
+ for (; iter != end; iter++)
+ {
+ combo_picker->mComboOptions->addSimpleElement(*iter);
+ }
+ combo_picker->mComboOptions->selectFirstItem();
+
+ combo_picker->openFloater(LLSD(title));
+ combo_picker->setFocus(TRUE);
+ combo_picker->center();
+ }
+ return combo_picker;
+}
+
+LLFloaterComboOptions* LLFloaterComboOptions::showUI(
+ combo_callback callback,
+ const std::string &title,
+ const std::string &description,
+ const std::string &ok_text,
+ const std::string &cancel_text,
+ const std::list<std::string> &options)
+{
+ LLFloaterComboOptions* combo_picker = showUI(callback, title, description, options);
+ if (combo_picker)
+ {
+ combo_picker->mConfirmButton->setLabel(ok_text);
+ combo_picker->mCancelButton->setLabel(cancel_text);
+ }
+ return combo_picker;
+}
+
+void LLFloaterComboOptions::onConfirm()
+{
+ mCallback(mComboOptions->getSimple(), mComboOptions->getCurrentIndex());
+ closeFloater();
+}
+
+void LLFloaterComboOptions::onCancel()
+{
+ mCallback(std::string(), -1);
+ closeFloater();
+}
+
+class LLMaterialEditorCopiedCallback : public LLInventoryCallback
+{
+public:
+ LLMaterialEditorCopiedCallback(
+ const std::string &buffer,
+ const LLSD &old_key,
+ bool has_unsaved_changes)
+ : mBuffer(buffer),
+ mOldKey(old_key),
+ mHasUnsavedChanges(has_unsaved_changes)
+ {}
+
+ LLMaterialEditorCopiedCallback(
+ const LLSD &old_key,
+ const std::string &new_name)
+ : mOldKey(old_key),
+ mNewName(new_name),
+ mHasUnsavedChanges(false)
+ {}
+
+ virtual void fire(const LLUUID& inv_item_id)
+ {
+ if (!mNewName.empty())
+ {
+ // making a copy from a notecard doesn't change name, do it now
+ LLViewerInventoryItem* item = gInventory.getItem(inv_item_id);
+ if (item->getName() != mNewName)
+ {
+ LLSD updates;
+ updates["name"] = mNewName;
+ update_inventory_item(inv_item_id, updates, NULL);
+ }
+ }
+ LLMaterialEditor::finishSaveAs(mOldKey, inv_item_id, mBuffer, mHasUnsavedChanges);
+ }
+
+private:
+ std::string mBuffer;
+ LLSD mOldKey;
+ std::string mNewName;
+ bool mHasUnsavedChanges;
+};
+
+///----------------------------------------------------------------------------
+/// Class LLSelectedTEGetMatData
+/// For finding selected applicable inworld material
+///----------------------------------------------------------------------------
+
+struct LLSelectedTEGetMatData : public LLSelectedTEFunctor
+{
+ LLSelectedTEGetMatData(bool for_override);
+
+ bool apply(LLViewerObject* objectp, S32 te_index);
+
+ bool mIsOverride;
+ bool mIdenticalTexColor;
+ bool mIdenticalTexMetal;
+ bool mIdenticalTexEmissive;
+ bool mIdenticalTexNormal;
+ bool mFirst;
+ LLUUID mTexColorId;
+ LLUUID mTexMetalId;
+ LLUUID mTexEmissiveId;
+ LLUUID mTexNormalId;
+ LLUUID mObjectId;
+ S32 mObjectTE;
+ LLPointer<LLGLTFMaterial> mMaterial;
+ LLPointer<LLLocalGLTFMaterial> mLocalMaterial;
+};
+
+LLSelectedTEGetMatData::LLSelectedTEGetMatData(bool for_override)
+ : mIsOverride(for_override)
+ , mIdenticalTexColor(true)
+ , mIdenticalTexMetal(true)
+ , mIdenticalTexEmissive(true)
+ , mIdenticalTexNormal(true)
+ , mObjectTE(-1)
+ , mFirst(true)
+{}
+
+bool LLSelectedTEGetMatData::apply(LLViewerObject* objectp, S32 te_index)
+{
+ if (!objectp)
+ {
+ return false;
+ }
+ LLUUID mat_id = objectp->getRenderMaterialID(te_index);
+ bool can_use = mIsOverride ? objectp->permModify() : objectp->permCopy();
+ LLTextureEntry *tep = objectp->getTE(te_index);
+ // We might want to disable this entirely if at least
+ // something in selection is no-copy or no modify
+ // or has no base material
+ if (can_use && tep && mat_id.notNull())
+ {
+ if (mIsOverride)
+ {
+ LLPointer<LLGLTFMaterial> mat = tep->getGLTFRenderMaterial();
+
+ LLUUID tex_color_id;
+ LLUUID tex_metal_id;
+ LLUUID tex_emissive_id;
+ LLUUID tex_normal_id;
+ llassert(mat.notNull()); // by this point shouldn't be null
+ if (mat.notNull())
+ {
+ tex_color_id = mat->mBaseColorId;
+ tex_metal_id = mat->mMetallicRoughnessId;
+ tex_emissive_id = mat->mEmissiveId;
+ tex_normal_id = mat->mNormalId;
+ }
+ if (mFirst)
+ {
+ mMaterial = mat;
+ mTexColorId = tex_color_id;
+ mTexMetalId = tex_metal_id;
+ mTexEmissiveId = tex_emissive_id;
+ mTexNormalId = tex_normal_id;
+ mObjectTE = te_index;
+ mObjectId = objectp->getID();
+ mFirst = false;
+ }
+ else
+ {
+ if (mTexColorId != tex_color_id)
+ {
+ mIdenticalTexColor = false;
+ }
+ if (mTexMetalId != tex_metal_id)
+ {
+ mIdenticalTexMetal = false;
+ }
+ if (mTexEmissiveId != tex_emissive_id)
+ {
+ mIdenticalTexEmissive = false;
+ }
+ if (mTexNormalId != tex_normal_id)
+ {
+ mIdenticalTexNormal = false;
+ }
+ }
+ }
+ else
+ {
+ LLGLTFMaterial *mat = tep->getGLTFMaterial();
+ LLLocalGLTFMaterial *local_mat = dynamic_cast<LLLocalGLTFMaterial*>(mat);
+
+ if (local_mat)
+ {
+ mLocalMaterial = local_mat;
+ }
+ mMaterial = tep->getGLTFRenderMaterial();
+
+ if (mMaterial.isNull())
+ {
+ // Shouldn't be possible?
+ LL_WARNS("MaterialEditor") << "Object has material id, but no material" << LL_ENDL;
+ mMaterial = gGLTFMaterialList.getMaterial(mat_id);
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+///----------------------------------------------------------------------------
+/// Class LLMaterialEditor
+///----------------------------------------------------------------------------
+
+// Default constructor
+LLMaterialEditor::LLMaterialEditor(const LLSD& key)
+ : LLPreview(key)
+ , mUnsavedChanges(0)
+ , mRevertedChanges(0)
+ , mExpectedUploadCost(0)
+ , mUploadingTexturesCount(0)
+ , mUploadingTexturesFailure(false)
+{
+ const LLInventoryItem* item = getItem();
+ if (item)
+ {
+ mAssetID = item->getAssetUUID();
+ }
+}
+
+void LLMaterialEditor::setObjectID(const LLUUID& object_id)
+{
+ LLPreview::setObjectID(object_id);
+ const LLInventoryItem* item = getItem();
+ if (item)
+ {
+ mAssetID = item->getAssetUUID();
+ }
+}
+
+void LLMaterialEditor::setAuxItem(const LLInventoryItem* item)
+{
+ LLPreview::setAuxItem(item);
+ if (item)
+ {
+ mAssetID = item->getAssetUUID();
+ }
+}
+
+BOOL LLMaterialEditor::postBuild()
+{
+ // if this is a 'live editor' instance, it is also
+ // single instance and uses live overrides
+ mIsOverride = getIsSingleInstance();
+
+ mBaseColorTextureCtrl = getChild<LLTextureCtrl>("base_color_texture");
+ mMetallicTextureCtrl = getChild<LLTextureCtrl>("metallic_roughness_texture");
+ mEmissiveTextureCtrl = getChild<LLTextureCtrl>("emissive_texture");
+ mNormalTextureCtrl = getChild<LLTextureCtrl>("normal_texture");
+ mBaseColorCtrl = getChild<LLColorSwatchCtrl>("base color");
+ mEmissiveColorCtrl = getChild<LLColorSwatchCtrl>("emissive color");
+
+ if (!gAgent.isGodlike())
+ {
+ // Only allow fully permissive textures
+ mBaseColorTextureCtrl->setImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER);
+ mMetallicTextureCtrl->setImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER);
+ mEmissiveTextureCtrl->setImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER);
+ mNormalTextureCtrl->setImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER);
+ }
+
+ // Texture callback
+ mBaseColorTextureCtrl->setCommitCallback(boost::bind(&LLMaterialEditor::onCommitTexture, this, _1, _2, MATERIAL_BASE_COLOR_TEX_DIRTY));
+ mMetallicTextureCtrl->setCommitCallback(boost::bind(&LLMaterialEditor::onCommitTexture, this, _1, _2, MATERIAL_METALLIC_ROUGHTNESS_TEX_DIRTY));
+ mEmissiveTextureCtrl->setCommitCallback(boost::bind(&LLMaterialEditor::onCommitTexture, this, _1, _2, MATERIAL_EMISIVE_TEX_DIRTY));
+ mNormalTextureCtrl->setCommitCallback(boost::bind(&LLMaterialEditor::onCommitTexture, this, _1, _2, MATERIAL_NORMAL_TEX_DIRTY));
+
+ if (mIsOverride)
+ {
+ // Material override change success callback
+ LLGLTFMaterialList::addSelectionUpdateCallback(&LLMaterialEditor::updateLive);
+
+ // Live editing needs a recovery mechanism on cancel
+ mBaseColorTextureCtrl->setOnCancelCallback(boost::bind(&LLMaterialEditor::onCancelCtrl, this, _1, _2, MATERIAL_BASE_COLOR_TEX_DIRTY));
+ mMetallicTextureCtrl->setOnCancelCallback(boost::bind(&LLMaterialEditor::onCancelCtrl, this, _1, _2, MATERIAL_METALLIC_ROUGHTNESS_TEX_DIRTY));
+ mEmissiveTextureCtrl->setOnCancelCallback(boost::bind(&LLMaterialEditor::onCancelCtrl, this, _1, _2, MATERIAL_EMISIVE_TEX_DIRTY));
+ mNormalTextureCtrl->setOnCancelCallback(boost::bind(&LLMaterialEditor::onCancelCtrl, this, _1, _2, MATERIAL_NORMAL_TEX_DIRTY));
+
+ // Save applied changes on 'OK' to our recovery mechanism.
+ mBaseColorTextureCtrl->setOnSelectCallback(boost::bind(&LLMaterialEditor::onSelectCtrl, this, _1, _2, MATERIAL_BASE_COLOR_TEX_DIRTY));
+ mMetallicTextureCtrl->setOnSelectCallback(boost::bind(&LLMaterialEditor::onSelectCtrl, this, _1, _2, MATERIAL_METALLIC_ROUGHTNESS_TEX_DIRTY));
+ mEmissiveTextureCtrl->setOnSelectCallback(boost::bind(&LLMaterialEditor::onSelectCtrl, this, _1, _2, MATERIAL_EMISIVE_TEX_DIRTY));
+ mNormalTextureCtrl->setOnSelectCallback(boost::bind(&LLMaterialEditor::onSelectCtrl, this, _1, _2, MATERIAL_NORMAL_TEX_DIRTY));
+ }
+
+ if (!mIsOverride)
+ {
+ childSetAction("save", boost::bind(&LLMaterialEditor::onClickSave, this));
+ childSetAction("save_as", boost::bind(&LLMaterialEditor::onClickSaveAs, this));
+ childSetAction("cancel", boost::bind(&LLMaterialEditor::onClickCancel, this));
+ }
+
+ if (mIsOverride)
+ {
+ childSetVisible("base_color_upload_fee", FALSE);
+ childSetVisible("metallic_upload_fee", FALSE);
+ childSetVisible("emissive_upload_fee", FALSE);
+ childSetVisible("normal_upload_fee", FALSE);
+ }
+ else
+ {
+ S32 upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost();
+ getChild<LLUICtrl>("base_color_upload_fee")->setTextArg("[FEE]", llformat("%d", upload_cost));
+ getChild<LLUICtrl>("metallic_upload_fee")->setTextArg("[FEE]", llformat("%d", upload_cost));
+ getChild<LLUICtrl>("emissive_upload_fee")->setTextArg("[FEE]", llformat("%d", upload_cost));
+ getChild<LLUICtrl>("normal_upload_fee")->setTextArg("[FEE]", llformat("%d", upload_cost));
+ }
+
+ boost::function<void(LLUICtrl*, void*)> changes_callback = [this](LLUICtrl * ctrl, void* userData)
+ {
+ const U32 *flag = (const U32*)userData;
+ markChangesUnsaved(*flag);
+ // Apply changes to object live
+ applyToSelection();
+ };
+
+ childSetCommitCallback("double sided", changes_callback, (void*)&MATERIAL_DOUBLE_SIDED_DIRTY);
+
+ // BaseColor
+ mBaseColorCtrl->setCommitCallback(changes_callback, (void*)&MATERIAL_BASE_COLOR_DIRTY);
+ if (mIsOverride)
+ {
+ mBaseColorCtrl->setOnCancelCallback(boost::bind(&LLMaterialEditor::onCancelCtrl, this, _1, _2, MATERIAL_BASE_COLOR_DIRTY));
+ mBaseColorCtrl->setOnSelectCallback(boost::bind(&LLMaterialEditor::onSelectCtrl, this, _1, _2, MATERIAL_BASE_COLOR_DIRTY));
+ }
+ // transparency is a part of base color
+ childSetCommitCallback("transparency", changes_callback, (void*)&MATERIAL_BASE_COLOR_DIRTY);
+ childSetCommitCallback("alpha mode", changes_callback, (void*)&MATERIAL_ALPHA_MODE_DIRTY);
+ childSetCommitCallback("alpha cutoff", changes_callback, (void*)&MATERIAL_ALPHA_CUTOFF_DIRTY);
+
+ // Metallic-Roughness
+ childSetCommitCallback("metalness factor", changes_callback, (void*)&MATERIAL_METALLIC_ROUGHTNESS_METALNESS_DIRTY);
+ childSetCommitCallback("roughness factor", changes_callback, (void*)&MATERIAL_METALLIC_ROUGHTNESS_ROUGHNESS_DIRTY);
+
+ // Emissive
+ mEmissiveColorCtrl->setCommitCallback(changes_callback, (void*)&MATERIAL_EMISIVE_COLOR_DIRTY);
+ if (mIsOverride)
+ {
+ mEmissiveColorCtrl->setOnCancelCallback(boost::bind(&LLMaterialEditor::onCancelCtrl, this, _1, _2, MATERIAL_EMISIVE_COLOR_DIRTY));
+ mEmissiveColorCtrl->setOnSelectCallback(boost::bind(&LLMaterialEditor::onSelectCtrl, this, _1, _2, MATERIAL_EMISIVE_COLOR_DIRTY));
+ }
+
+ if (!mIsOverride)
+ {
+ // "unsaved_changes" doesn't exist in live editor
+ childSetVisible("unsaved_changes", mUnsavedChanges);
+
+ // Doesn't exist in live editor
+ getChild<LLUICtrl>("total_upload_fee")->setTextArg("[FEE]", llformat("%d", 0));
+ }
+
+ // Todo:
+ // Disable/enable setCanApplyImmediately() based on
+ // working from inventory, upload or editing inworld
+
+ return LLPreview::postBuild();
+}
+
+void LLMaterialEditor::onClickCloseBtn(bool app_quitting)
+{
+ if (app_quitting || mIsOverride)
+ {
+ closeFloater(app_quitting);
+ }
+ else
+ {
+ onClickCancel();
+ }
+}
+
+void LLMaterialEditor::onClose(bool app_quitting)
+{
+ if (mSelectionUpdateSlot.connected())
+ {
+ mSelectionUpdateSlot.disconnect();
+ }
+
+ LLPreview::onClose(app_quitting);
+}
+
+void LLMaterialEditor::draw()
+{
+ if (mIsOverride)
+ {
+ bool selection_empty = LLSelectMgr::getInstance()->getSelection()->isEmpty();
+ if (selection_empty && mHasSelection)
+ {
+ mSelectionNeedsUpdate = true;
+ }
+
+ if (mSelectionNeedsUpdate)
+ {
+ mSelectionNeedsUpdate = false;
+ clearTextures();
+ setFromSelection();
+ }
+ }
+ LLPreview::draw();
+}
+
+void LLMaterialEditor::handleReshape(const LLRect& new_rect, bool by_user)
+{
+ if (by_user)
+ {
+ const LLRect old_rect = getRect();
+ LLRect clamp_rect(new_rect);
+ clamp_rect.mRight = clamp_rect.mLeft + old_rect.getWidth();
+ LLPreview::handleReshape(clamp_rect, by_user);
+ }
+ else
+ {
+ LLPreview::handleReshape(new_rect, by_user);
+ }
+}
+
+LLUUID LLMaterialEditor::getBaseColorId()
+{
+ return mBaseColorTextureCtrl->getValue().asUUID();
+}
+
+void LLMaterialEditor::setBaseColorId(const LLUUID& id)
+{
+ mBaseColorTextureCtrl->setValue(id);
+ mBaseColorTextureCtrl->setDefaultImageAssetID(id);
+ mBaseColorTextureCtrl->setTentative(FALSE);
+}
+
+void LLMaterialEditor::setBaseColorUploadId(const LLUUID& id)
+{
+ // Might be better to use local textures and
+ // assign a fee in case of a local texture
+ if (id.notNull())
+ {
+ // todo: this does not account for posibility of texture
+ // being from inventory, need to check that
+ childSetValue("base_color_upload_fee", getString("upload_fee_string"));
+ // Only set if we will need to upload this texture
+ mBaseColorTextureUploadId = id;
+ }
+ markChangesUnsaved(MATERIAL_BASE_COLOR_TEX_DIRTY);
+}
+
+LLColor4 LLMaterialEditor::getBaseColor()
+{
+ LLColor4 ret = linearColor4(LLColor4(mBaseColorCtrl->getValue()));
+ ret.mV[3] = getTransparency();
+ return ret;
+}
+
+void LLMaterialEditor::setBaseColor(const LLColor4& color)
+{
+ mBaseColorCtrl->setValue(srgbColor4(color).getValue());
+ setTransparency(color.mV[3]);
+}
+
+F32 LLMaterialEditor::getTransparency()
+{
+ return childGetValue("transparency").asReal();
+}
+
+void LLMaterialEditor::setTransparency(F32 transparency)
+{
+ childSetValue("transparency", transparency);
+}
+
+std::string LLMaterialEditor::getAlphaMode()
+{
+ return childGetValue("alpha mode").asString();
+}
+
+void LLMaterialEditor::setAlphaMode(const std::string& alpha_mode)
+{
+ childSetValue("alpha mode", alpha_mode);
+}
+
+F32 LLMaterialEditor::getAlphaCutoff()
+{
+ return childGetValue("alpha cutoff").asReal();
+}
+
+void LLMaterialEditor::setAlphaCutoff(F32 alpha_cutoff)
+{
+ childSetValue("alpha cutoff", alpha_cutoff);
+}
+
+void LLMaterialEditor::setMaterialName(const std::string &name)
+{
+ setTitle(name);
+ mMaterialName = name;
+}
+
+LLUUID LLMaterialEditor::getMetallicRoughnessId()
+{
+ return mMetallicTextureCtrl->getValue().asUUID();
+}
+
+void LLMaterialEditor::setMetallicRoughnessId(const LLUUID& id)
+{
+ mMetallicTextureCtrl->setValue(id);
+ mMetallicTextureCtrl->setDefaultImageAssetID(id);
+ mMetallicTextureCtrl->setTentative(FALSE);
+}
+
+void LLMaterialEditor::setMetallicRoughnessUploadId(const LLUUID& id)
+{
+ if (id.notNull())
+ {
+ // todo: this does not account for posibility of texture
+ // being from inventory, need to check that
+ childSetValue("metallic_upload_fee", getString("upload_fee_string"));
+ mMetallicTextureUploadId = id;
+ }
+ markChangesUnsaved(MATERIAL_METALLIC_ROUGHTNESS_TEX_DIRTY);
+}
+
+F32 LLMaterialEditor::getMetalnessFactor()
+{
+ return childGetValue("metalness factor").asReal();
+}
+
+void LLMaterialEditor::setMetalnessFactor(F32 factor)
+{
+ childSetValue("metalness factor", factor);
+}
+
+F32 LLMaterialEditor::getRoughnessFactor()
+{
+ return childGetValue("roughness factor").asReal();
+}
+
+void LLMaterialEditor::setRoughnessFactor(F32 factor)
+{
+ childSetValue("roughness factor", factor);
+}
+
+LLUUID LLMaterialEditor::getEmissiveId()
+{
+ return mEmissiveTextureCtrl->getValue().asUUID();
+}
+
+void LLMaterialEditor::setEmissiveId(const LLUUID& id)
+{
+ mEmissiveTextureCtrl->setValue(id);
+ mEmissiveTextureCtrl->setDefaultImageAssetID(id);
+ mEmissiveTextureCtrl->setTentative(FALSE);
+}
+
+void LLMaterialEditor::setEmissiveUploadId(const LLUUID& id)
+{
+ if (id.notNull())
+ {
+ // todo: this does not account for posibility of texture
+ // being from inventory, need to check that
+ childSetValue("emissive_upload_fee", getString("upload_fee_string"));
+ mEmissiveTextureUploadId = id;
+ }
+ markChangesUnsaved(MATERIAL_EMISIVE_TEX_DIRTY);
+}
+
+LLColor4 LLMaterialEditor::getEmissiveColor()
+{
+ return linearColor4(LLColor4(mEmissiveColorCtrl->getValue()));
+}
+
+void LLMaterialEditor::setEmissiveColor(const LLColor4& color)
+{
+ mEmissiveColorCtrl->setValue(srgbColor4(color).getValue());
+}
+
+LLUUID LLMaterialEditor::getNormalId()
+{
+ return mNormalTextureCtrl->getValue().asUUID();
+}
+
+void LLMaterialEditor::setNormalId(const LLUUID& id)
+{
+ mNormalTextureCtrl->setValue(id);
+ mNormalTextureCtrl->setDefaultImageAssetID(id);
+ mNormalTextureCtrl->setTentative(FALSE);
+}
+
+void LLMaterialEditor::setNormalUploadId(const LLUUID& id)
+{
+ if (id.notNull())
+ {
+ // todo: this does not account for posibility of texture
+ // being from inventory, need to check that
+ childSetValue("normal_upload_fee", getString("upload_fee_string"));
+ mNormalTextureUploadId = id;
+ }
+ markChangesUnsaved(MATERIAL_NORMAL_TEX_DIRTY);
+}
+
+bool LLMaterialEditor::getDoubleSided()
+{
+ return childGetValue("double sided").asBoolean();
+}
+
+void LLMaterialEditor::setDoubleSided(bool double_sided)
+{
+ childSetValue("double sided", double_sided);
+}
+
+void LLMaterialEditor::resetUnsavedChanges()
+{
+ mUnsavedChanges = 0;
+ mRevertedChanges = 0;
+ if (!mIsOverride)
+ {
+ childSetVisible("unsaved_changes", false);
+ setCanSave(false);
+
+ mExpectedUploadCost = 0;
+ getChild<LLUICtrl>("total_upload_fee")->setTextArg("[FEE]", llformat("%d", mExpectedUploadCost));
+ }
+}
+
+void LLMaterialEditor::markChangesUnsaved(U32 dirty_flag)
+{
+ mUnsavedChanges |= dirty_flag;
+ if (mIsOverride)
+ {
+ // at the moment live editing (mIsOverride) applies everything 'live'
+ // and "unsaved_changes", save/cancel buttons don't exist there
+ return;
+ }
+
+ childSetVisible("unsaved_changes", mUnsavedChanges);
+
+ if (mUnsavedChanges)
+ {
+ const LLInventoryItem* item = getItem();
+ if (item)
+ {
+ LLPermissions perm(item->getPermissions());
+ bool allow_modify = canModify(mObjectUUID, item);
+ bool source_library = mObjectUUID.isNull() && gInventory.isObjectDescendentOf(mItemUUID, gInventory.getLibraryRootFolderID());
+ bool source_notecard = mNotecardInventoryID.notNull();
+
+ setCanSave(allow_modify && !source_library && !source_notecard);
+ }
+ }
+ else
+ {
+ setCanSave(false);
+ }
+
+ S32 upload_texture_count = 0;
+ if (mBaseColorTextureUploadId.notNull() && mBaseColorTextureUploadId == getBaseColorId())
+ {
+ upload_texture_count++;
+ }
+ if (mMetallicTextureUploadId.notNull() && mMetallicTextureUploadId == getMetallicRoughnessId())
+ {
+ upload_texture_count++;
+ }
+ if (mEmissiveTextureUploadId.notNull() && mEmissiveTextureUploadId == getEmissiveId())
+ {
+ upload_texture_count++;
+ }
+ if (mNormalTextureUploadId.notNull() && mNormalTextureUploadId == getNormalId())
+ {
+ upload_texture_count++;
+ }
+
+ mExpectedUploadCost = upload_texture_count * LLAgentBenefitsMgr::current().getTextureUploadCost();
+ getChild<LLUICtrl>("total_upload_fee")->setTextArg("[FEE]", llformat("%d", mExpectedUploadCost));
+}
+
+void LLMaterialEditor::setCanSaveAs(bool value)
+{
+ if (!mIsOverride)
+ {
+ childSetEnabled("save_as", value);
+ }
+}
+
+void LLMaterialEditor::setCanSave(bool value)
+{
+ if (!mIsOverride)
+ {
+ childSetEnabled("save", value);
+ }
+}
+
+void LLMaterialEditor::setEnableEditing(bool can_modify)
+{
+ childSetEnabled("double sided", can_modify);
+
+ // BaseColor
+ childSetEnabled("base color", can_modify);
+ childSetEnabled("transparency", can_modify);
+ childSetEnabled("alpha mode", can_modify);
+ childSetEnabled("alpha cutoff", can_modify);
+
+ // Metallic-Roughness
+ childSetEnabled("metalness factor", can_modify);
+ childSetEnabled("roughness factor", can_modify);
+
+ // Metallic-Roughness
+ childSetEnabled("metalness factor", can_modify);
+ childSetEnabled("roughness factor", can_modify);
+
+ // Emissive
+ childSetEnabled("emissive color", can_modify);
+
+ mBaseColorTextureCtrl->setEnabled(can_modify);
+ mMetallicTextureCtrl->setEnabled(can_modify);
+ mEmissiveTextureCtrl->setEnabled(can_modify);
+ mNormalTextureCtrl->setEnabled(can_modify);
+}
+
+void LLMaterialEditor::onCommitTexture(LLUICtrl* ctrl, const LLSD& data, S32 dirty_flag)
+{
+ if (!mIsOverride)
+ {
+ std::string upload_fee_ctrl_name;
+ LLUUID old_uuid;
+
+ switch (dirty_flag)
+ {
+ case MATERIAL_BASE_COLOR_TEX_DIRTY:
+ {
+ upload_fee_ctrl_name = "base_color_upload_fee";
+ old_uuid = mBaseColorTextureUploadId;
+ break;
+ }
+ case MATERIAL_METALLIC_ROUGHTNESS_TEX_DIRTY:
+ {
+ upload_fee_ctrl_name = "metallic_upload_fee";
+ old_uuid = mMetallicTextureUploadId;
+ break;
+ }
+ case MATERIAL_EMISIVE_TEX_DIRTY:
+ {
+ upload_fee_ctrl_name = "emissive_upload_fee";
+ old_uuid = mEmissiveTextureUploadId;
+ break;
+ }
+ case MATERIAL_NORMAL_TEX_DIRTY:
+ {
+ upload_fee_ctrl_name = "normal_upload_fee";
+ old_uuid = mNormalTextureUploadId;
+ break;
+ }
+ default:
+ break;
+ }
+ LLUUID new_val = ctrl->getValue().asUUID();
+ if (new_val == old_uuid && old_uuid.notNull())
+ {
+ childSetValue(upload_fee_ctrl_name, getString("upload_fee_string"));
+ }
+ else
+ {
+ // Texture picker has 'apply now' with 'cancel' support.
+ // Don't clean mBaseColorJ2C and mBaseColorFetched, it's our
+ // storage in case user decides to cancel changes.
+ // Without mBaseColorFetched, viewer will eventually cleanup
+ // the texture that is not in use
+ childSetValue(upload_fee_ctrl_name, getString("no_upload_fee_string"));
+ }
+ }
+
+ markChangesUnsaved(dirty_flag);
+ applyToSelection();
+}
+
+void LLMaterialEditor::onCancelCtrl(LLUICtrl* ctrl, const LLSD& data, S32 dirty_flag)
+{
+ mRevertedChanges |= dirty_flag;
+ applyToSelection();
+}
+
+void LLMaterialEditor::onSelectCtrl(LLUICtrl* ctrl, const LLSD& data, S32 dirty_flag)
+{
+ mUnsavedChanges |= dirty_flag;
+ applyToSelection();
+
+ struct f : public LLSelectedNodeFunctor
+ {
+ f(LLUICtrl* ctrl, S32 dirty_flag) : mCtrl(ctrl), mDirtyFlag(dirty_flag)
+ {
+ }
+
+ virtual bool apply(LLSelectNode* nodep)
+ {
+ LLViewerObject* objectp = nodep->getObject();
+ if (!objectp)
+ {
+ return false;
+ }
+ S32 num_tes = llmin((S32)objectp->getNumTEs(), (S32)objectp->getNumFaces()); // avatars have TEs but no faces
+ for (S32 te = 0; te < num_tes; ++te)
+ {
+ if (nodep->isTESelected(te) && nodep->mSavedGLTFOverrideMaterials.size() > te)
+ {
+ if (nodep->mSavedGLTFOverrideMaterials[te].isNull())
+ {
+ // populate with default values, default values basically mean 'not in use'
+ nodep->mSavedGLTFOverrideMaterials[te] = new LLGLTFMaterial();
+ }
+
+ switch (mDirtyFlag)
+ {
+ //Textures
+ case MATERIAL_BASE_COLOR_TEX_DIRTY:
+ {
+ nodep->mSavedGLTFOverrideMaterials[te]->setBaseColorId(mCtrl->getValue().asUUID(), true);
+ break;
+ }
+ case MATERIAL_METALLIC_ROUGHTNESS_TEX_DIRTY:
+ {
+ nodep->mSavedGLTFOverrideMaterials[te]->setMetallicRoughnessId(mCtrl->getValue().asUUID(), true);
+ break;
+ }
+ case MATERIAL_EMISIVE_TEX_DIRTY:
+ {
+ nodep->mSavedGLTFOverrideMaterials[te]->setEmissiveId(mCtrl->getValue().asUUID(), true);
+ break;
+ }
+ case MATERIAL_NORMAL_TEX_DIRTY:
+ {
+ nodep->mSavedGLTFOverrideMaterials[te]->setNormalId(mCtrl->getValue().asUUID(), true);
+ break;
+ }
+ // Colors
+ case MATERIAL_BASE_COLOR_DIRTY:
+ {
+ LLColor4 ret = linearColor4(LLColor4(mCtrl->getValue()));
+ // except transparency
+ ret.mV[3] = nodep->mSavedGLTFOverrideMaterials[te]->mBaseColor.mV[3];
+ nodep->mSavedGLTFOverrideMaterials[te]->setBaseColorFactor(ret, true);
+ break;
+ }
+ case MATERIAL_EMISIVE_COLOR_DIRTY:
+ {
+ nodep->mSavedGLTFOverrideMaterials[te]->setEmissiveColorFactor(LLColor3(mCtrl->getValue()), true);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ }
+ return true;
+ }
+
+ LLUICtrl* mCtrl;
+ S32 mDirtyFlag;
+ } func(ctrl, dirty_flag);
+
+ LLSelectMgr::getInstance()->getSelection()->applyToNodes(&func);
+}
+
+static void write_color(const LLColor4& color, std::vector<double>& c)
+{
+ for (int i = 0; i < c.size(); ++i) // NOTE -- use c.size because some gltf colors are 3-component
+ {
+ c[i] = color.mV[i];
+ }
+}
+
+static U32 write_texture(const LLUUID& id, tinygltf::Model& model)
+{
+ tinygltf::Image image;
+ image.uri = id.asString();
+ model.images.push_back(image);
+ U32 image_idx = model.images.size() - 1;
+
+ tinygltf::Texture texture;
+ texture.source = image_idx;
+ model.textures.push_back(texture);
+ U32 texture_idx = model.textures.size() - 1;
+
+ return texture_idx;
+}
+
+
+void LLMaterialEditor::onClickSave()
+{
+ if (!capabilitiesAvailable())
+ {
+ LLNotificationsUtil::add("MissingMaterialCaps");
+ return;
+ }
+ if (!can_afford_transaction(mExpectedUploadCost))
+ {
+ LLSD args;
+ args["COST"] = llformat("%d", mExpectedUploadCost);
+ LLNotificationsUtil::add("ErrorCannotAffordUpload", args);
+ return;
+ }
+
+ applyToSelection();
+ saveIfNeeded();
+}
+
+
+std::string LLMaterialEditor::getGLTFJson(bool prettyprint)
+{
+ tinygltf::Model model;
+ getGLTFModel(model);
+
+ std::ostringstream str;
+
+ tinygltf::TinyGLTF gltf;
+
+ gltf.WriteGltfSceneToStream(&model, str, prettyprint, false);
+
+ std::string dump = str.str();
+
+ return dump;
+}
+
+void LLMaterialEditor::getGLBData(std::vector<U8>& data)
+{
+ tinygltf::Model model;
+ getGLTFModel(model);
+
+ std::ostringstream str;
+
+ tinygltf::TinyGLTF gltf;
+
+ gltf.WriteGltfSceneToStream(&model, str, false, true);
+
+ std::string dump = str.str();
+
+ data.resize(dump.length());
+
+ memcpy(&data[0], dump.c_str(), dump.length());
+}
+
+void LLMaterialEditor::getGLTFModel(tinygltf::Model& model)
+{
+ model.materials.resize(1);
+ tinygltf::PbrMetallicRoughness& pbrMaterial = model.materials[0].pbrMetallicRoughness;
+
+ // write base color
+ LLColor4 base_color = getBaseColor();
+ base_color.mV[3] = getTransparency();
+ write_color(base_color, pbrMaterial.baseColorFactor);
+
+ model.materials[0].alphaCutoff = getAlphaCutoff();
+ model.materials[0].alphaMode = getAlphaMode();
+
+ LLUUID base_color_id = getBaseColorId();
+
+ if (base_color_id.notNull())
+ {
+ U32 texture_idx = write_texture(base_color_id, model);
+
+ pbrMaterial.baseColorTexture.index = texture_idx;
+ }
+
+ // write metallic/roughness
+ F32 metalness = getMetalnessFactor();
+ F32 roughness = getRoughnessFactor();
+
+ pbrMaterial.metallicFactor = metalness;
+ pbrMaterial.roughnessFactor = roughness;
+
+ LLUUID mr_id = getMetallicRoughnessId();
+ if (mr_id.notNull())
+ {
+ U32 texture_idx = write_texture(mr_id, model);
+ pbrMaterial.metallicRoughnessTexture.index = texture_idx;
+ }
+
+ //write emissive
+ LLColor4 emissive_color = getEmissiveColor();
+ model.materials[0].emissiveFactor.resize(3);
+ write_color(emissive_color, model.materials[0].emissiveFactor);
+
+ LLUUID emissive_id = getEmissiveId();
+ if (emissive_id.notNull())
+ {
+ U32 idx = write_texture(emissive_id, model);
+ model.materials[0].emissiveTexture.index = idx;
+ }
+
+ //write normal
+ LLUUID normal_id = getNormalId();
+ if (normal_id.notNull())
+ {
+ U32 idx = write_texture(normal_id, model);
+ model.materials[0].normalTexture.index = idx;
+ }
+
+ //write doublesided
+ model.materials[0].doubleSided = getDoubleSided();
+
+ model.asset.version = "2.0";
+}
+
+std::string LLMaterialEditor::getEncodedAsset()
+{
+ LLSD asset;
+ asset["version"] = "1.0";
+ asset["type"] = "GLTF 2.0";
+ asset["data"] = getGLTFJson(false);
+
+ std::ostringstream str;
+ LLSDSerialize::serialize(asset, str, LLSDSerialize::LLSD_BINARY);
+
+ return str.str();
+}
+
+bool LLMaterialEditor::decodeAsset(const std::vector<char>& buffer)
+{
+ LLSD asset;
+
+ std::istrstream str(&buffer[0], buffer.size());
+ if (LLSDSerialize::deserialize(asset, str, buffer.size()))
+ {
+ if (asset.has("version") && asset["version"] == "1.0")
+ {
+ if (asset.has("type") && asset["type"] == "GLTF 2.0")
+ {
+ if (asset.has("data") && asset["data"].isString())
+ {
+ std::string data = asset["data"];
+
+ tinygltf::TinyGLTF gltf;
+ tinygltf::TinyGLTF loader;
+ std::string error_msg;
+ std::string warn_msg;
+
+ tinygltf::Model model_in;
+
+ if (loader.LoadASCIIFromString(&model_in, &error_msg, &warn_msg, data.c_str(), data.length(), ""))
+ {
+ // assets are only supposed to have one item
+ return setFromGltfModel(model_in, 0, true);
+ }
+ else
+ {
+ LL_WARNS("MaterialEditor") << "Floater " << getKey() << " Failed to decode material asset: " << LL_NEWLINE
+ << warn_msg << LL_NEWLINE
+ << error_msg << LL_ENDL;
+ }
+ }
+ }
+ }
+ else
+ {
+ LL_WARNS("MaterialEditor") << "Invalid LLSD content "<< asset << " for flaoter " << getKey() << LL_ENDL;
+ }
+ }
+ else
+ {
+ LL_WARNS("MaterialEditor") << "Failed to deserialize material LLSD for flaoter " << getKey() << LL_ENDL;
+ }
+
+ return false;
+}
+
+/**
+ * Build a description of the material we just imported.
+ * Currently this means a list of the textures present but we
+ * may eventually want to make it more complete - will be guided
+ * by what the content creators say they need.
+ */
+const std::string LLMaterialEditor::buildMaterialDescription()
+{
+ std::ostringstream desc;
+ desc << LLTrans::getString("Material Texture Name Header");
+
+ // add the texture names for each just so long as the material
+ // we loaded has an entry for it (i think testing the texture
+ // control UUI for NULL is a valid metric for if it was loaded
+ // or not but I suspect this code will change a lot so may need
+ // to revisit
+ if (!mBaseColorTextureCtrl->getValue().asUUID().isNull())
+ {
+ desc << mBaseColorName;
+ desc << ", ";
+ }
+ if (!mMetallicTextureCtrl->getValue().asUUID().isNull())
+ {
+ desc << mMetallicRoughnessName;
+ desc << ", ";
+ }
+ if (!mEmissiveTextureCtrl->getValue().asUUID().isNull())
+ {
+ desc << mEmissiveName;
+ desc << ", ";
+ }
+ if (!mNormalTextureCtrl->getValue().asUUID().isNull())
+ {
+ desc << mNormalName;
+ }
+
+ // trim last char if it's a ',' in case there is no normal texture
+ // present and the code above inserts one
+ // (no need to check for string length - always has initial string)
+ std::string::iterator iter = desc.str().end() - 1;
+ if (*iter == ',')
+ {
+ desc.str().erase(iter);
+ }
+
+ // sanitize the material description so that it's compatible with the inventory
+ // note: split this up because clang doesn't like operating directly on the
+ // str() - error: lvalue reference to type 'basic_string<...>' cannot bind to a
+ // temporary of type 'basic_string<...>'
+ std::string inv_desc = desc.str();
+ LLInventoryObject::correctInventoryName(inv_desc);
+
+ return inv_desc;
+}
+
+bool LLMaterialEditor::saveIfNeeded()
+{
+ if (mUploadingTexturesCount > 0)
+ {
+ // Upload already in progress, wait until
+ // textures upload will retry saving on callback.
+ // Also should prevent some failure-callbacks
+ return true;
+ }
+
+ if (saveTextures() > 0)
+ {
+ // started texture upload
+ setEnabled(false);
+ return true;
+ }
+
+ std::string buffer = getEncodedAsset();
+
+ const LLInventoryItem* item = getItem();
+ // save it out to database
+ if (item)
+ {
+ if (!updateInventoryItem(buffer, mItemUUID, mObjectUUID))
+ {
+ return false;
+ }
+
+ if (mCloseAfterSave)
+ {
+ closeFloater();
+ }
+ else
+ {
+ mAssetStatus = PREVIEW_ASSET_LOADING;
+ setEnabled(false);
+ }
+ }
+ else
+ {
+ //make a new inventory item
+ std::string res_desc = buildMaterialDescription();
+ createInventoryItem(buffer, mMaterialName, res_desc);
+
+ // We do not update floater with uploaded asset yet, so just close it.
+ closeFloater();
+ }
+
+ return true;
+}
+
+// static
+bool LLMaterialEditor::updateInventoryItem(const std::string &buffer, const LLUUID &item_id, const LLUUID &task_id)
+{
+ const LLViewerRegion* region = gAgent.getRegion();
+ if (!region)
+ {
+ LL_WARNS("MaterialEditor") << "Not connected to a region, cannot save material." << LL_ENDL;
+ return false;
+ }
+ std::string agent_url = region->getCapability("UpdateMaterialAgentInventory");
+ std::string task_url = region->getCapability("UpdateMaterialTaskInventory");
+
+ if (!agent_url.empty() && !task_url.empty())
+ {
+ std::string url;
+ LLResourceUploadInfo::ptr_t uploadInfo;
+
+ if (task_id.isNull() && !agent_url.empty())
+ {
+ uploadInfo = std::make_shared<LLBufferedAssetUploadInfo>(item_id, LLAssetType::AT_MATERIAL, buffer,
+ [](LLUUID itemId, LLUUID newAssetId, LLUUID newItemId, LLSD)
+ {
+ // done callback
+ LLMaterialEditor::finishInventoryUpload(itemId, newAssetId, newItemId);
+ },
+ [](LLUUID itemId, LLUUID taskId, LLSD response, std::string reason)
+ {
+ // failure callback
+ LLMaterialEditor* me = LLFloaterReg::findTypedInstance<LLMaterialEditor>("material_editor", LLSD(itemId));
+ if (me)
+ {
+ me->setEnabled(true);
+ }
+ return true;
+ }
+ );
+ url = agent_url;
+ }
+ else if (!task_id.isNull() && !task_url.empty())
+ {
+ LLUUID object_uuid(task_id);
+ uploadInfo = std::make_shared<LLBufferedAssetUploadInfo>(task_id, item_id, LLAssetType::AT_MATERIAL, buffer,
+ [](LLUUID itemId, LLUUID task_id, LLUUID newAssetId, LLSD)
+ {
+ // done callback
+ LLMaterialEditor::finishTaskUpload(itemId, newAssetId, task_id);
+ },
+ [](LLUUID itemId, LLUUID task_id, LLSD response, std::string reason)
+ {
+ // failure callback
+ LLSD floater_key;
+ floater_key["taskid"] = task_id;
+ floater_key["itemid"] = itemId;
+ LLMaterialEditor* me = LLFloaterReg::findTypedInstance<LLMaterialEditor>("material_editor", floater_key);
+ if (me)
+ {
+ me->setEnabled(true);
+ }
+ return true;
+ }
+ );
+ url = task_url;
+ }
+
+ if (!url.empty() && uploadInfo)
+ {
+ LLViewerAssetUpload::EnqueueInventoryUpload(url, uploadInfo);
+ }
+ else
+ {
+ return false;
+ }
+
+ }
+ else // !gAssetStorage
+ {
+ LL_WARNS("MaterialEditor") << "Not connected to an materials capable region." << LL_ENDL;
+ return false;
+ }
+
+ // todo: apply permissions from textures here if server doesn't
+ // if any texture is 'no transfer', material should be 'no transfer' as well
+
+ return true;
+}
+
+void LLMaterialEditor::createInventoryItem(const std::string &buffer, const std::string &name, const std::string &desc)
+{
+ // gen a new uuid for this asset
+ LLTransactionID tid;
+ tid.generate(); // timestamp-based randomization + uniquification
+ LLAssetID new_asset_id = tid.makeAssetID(gAgent.getSecureSessionID());
+ U32 next_owner_perm = LLFloaterPerms::getNextOwnerPerms("Materials");
+ LLUUID parent = gInventory.findUserDefinedCategoryUUIDForType(LLFolderType::FT_MATERIAL);
+ const U8 subtype = NO_INV_SUBTYPE; // TODO maybe use AT_SETTINGS and LLSettingsType::ST_MATERIAL ?
+
+ create_inventory_item(gAgent.getID(), gAgent.getSessionID(), parent, tid, name, desc,
+ LLAssetType::AT_MATERIAL, LLInventoryType::IT_MATERIAL, subtype, next_owner_perm,
+ new LLBoostFuncInventoryCallback([output = buffer](LLUUID const& inv_item_id)
+ {
+ LLViewerInventoryItem* item = gInventory.getItem(inv_item_id);
+ if (item)
+ {
+ // create_inventory_item doesn't allow presetting some permissions, fix it now
+ LLPermissions perm = item->getPermissions();
+ if (perm.getMaskEveryone() != LLFloaterPerms::getEveryonePerms("Materials")
+ || perm.getMaskGroup() != LLFloaterPerms::getGroupPerms("Materials"))
+ {
+ perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms("Materials"));
+ perm.setMaskGroup(LLFloaterPerms::getGroupPerms("Materials"));
+
+ item->setPermissions(perm);
+
+ item->updateServer(FALSE);
+ gInventory.updateItem(item);
+ gInventory.notifyObservers();
+ }
+ }
+
+ // from reference in LLSettingsVOBase::createInventoryItem()/updateInventoryItem()
+ LLResourceUploadInfo::ptr_t uploadInfo =
+ std::make_shared<LLBufferedAssetUploadInfo>(
+ inv_item_id,
+ LLAssetType::AT_MATERIAL,
+ output,
+ [](LLUUID item_id, LLUUID new_asset_id, LLUUID new_item_id, LLSD response)
+ {
+ // done callback
+ LL_INFOS("Material") << "inventory item uploaded. item: " << item_id << " asset: " << new_asset_id << " new_item_id: " << new_item_id << " response: " << response << LL_ENDL;
+ LLSD params = llsd::map("ASSET_ID", new_asset_id);
+ LLNotificationsUtil::add("MaterialCreated", params);
+ },
+ nullptr // failure callback, floater already closed
+ );
+
+ const LLViewerRegion* region = gAgent.getRegion();
+ if (region)
+ {
+ std::string agent_url(region->getCapability("UpdateMaterialAgentInventory"));
+ if (agent_url.empty())
+ {
+ LL_ERRS("MaterialEditor") << "missing required agent inventory cap url" << LL_ENDL;
+ }
+ LLViewerAssetUpload::EnqueueInventoryUpload(agent_url, uploadInfo);
+ }
+ })
+ );
+}
+
+void LLMaterialEditor::finishInventoryUpload(LLUUID itemId, LLUUID newAssetId, LLUUID newItemId)
+{
+ // Update the UI with the new asset.
+ LLMaterialEditor* me = LLFloaterReg::findTypedInstance<LLMaterialEditor>("material_editor", LLSD(itemId));
+ if (me)
+ {
+ if (newItemId.isNull())
+ {
+ me->setAssetId(newAssetId);
+ me->refreshFromInventory();
+ }
+ else if (newItemId.notNull())
+ {
+ // Not supposed to happen?
+ me->refreshFromInventory(newItemId);
+ }
+ else
+ {
+ me->refreshFromInventory(itemId);
+ }
+ }
+}
+
+void LLMaterialEditor::finishTaskUpload(LLUUID itemId, LLUUID newAssetId, LLUUID taskId)
+{
+ LLSD floater_key;
+ floater_key["taskid"] = taskId;
+ floater_key["itemid"] = itemId;
+ LLMaterialEditor* me = LLFloaterReg::findTypedInstance<LLMaterialEditor>("material_editor", floater_key);
+ if (me)
+ {
+ me->setAssetId(newAssetId);
+ me->refreshFromInventory();
+ me->setEnabled(true);
+ }
+}
+
+void LLMaterialEditor::finishSaveAs(
+ const LLSD &oldKey,
+ const LLUUID &newItemId,
+ const std::string &buffer,
+ bool has_unsaved_changes)
+{
+ LLMaterialEditor* me = LLFloaterReg::findTypedInstance<LLMaterialEditor>("material_editor", oldKey);
+ LLViewerInventoryItem* item = gInventory.getItem(newItemId);
+ if (item)
+ {
+ if (me)
+ {
+ me->mItemUUID = newItemId;
+ me->mObjectUUID = LLUUID::null;
+ me->mNotecardInventoryID = LLUUID::null;
+ me->mNotecardObjectID = LLUUID::null;
+ me->mAuxItem = nullptr;
+ me->setKey(LLSD(newItemId)); // for findTypedInstance
+ me->setMaterialName(item->getName());
+ if (has_unsaved_changes)
+ {
+ if (!updateInventoryItem(buffer, newItemId, LLUUID::null))
+ {
+ me->setEnabled(true);
+ }
+ }
+ else
+ {
+ me->loadAsset();
+ me->setEnabled(true);
+ }
+ }
+ else if(has_unsaved_changes)
+ {
+ updateInventoryItem(buffer, newItemId, LLUUID::null);
+ }
+ }
+ else if (me)
+ {
+ me->setEnabled(true);
+ LL_WARNS("MaterialEditor") << "Item does not exist, floater " << me->getKey() << LL_ENDL;
+ }
+}
+
+void LLMaterialEditor::refreshFromInventory(const LLUUID& new_item_id)
+{
+ if (mIsOverride)
+ {
+ // refreshFromInventory shouldn't be called for overrides,
+ // but just in case.
+ LL_WARNS("MaterialEditor") << "Tried to refresh from inventory for live editor" << LL_ENDL;
+ return;
+ }
+ LLSD old_key = getKey();
+ if (new_item_id.notNull())
+ {
+ mItemUUID = new_item_id;
+ if (mNotecardInventoryID.notNull())
+ {
+ LLSD floater_key;
+ floater_key["objectid"] = mNotecardObjectID;
+ floater_key["notecardid"] = mNotecardInventoryID;
+ setKey(floater_key);
+ }
+ else if (mObjectUUID.notNull())
+ {
+ LLSD floater_key;
+ floater_key["taskid"] = new_item_id;
+ floater_key["itemid"] = mObjectUUID;
+ setKey(floater_key);
+ }
+ else
+ {
+ setKey(LLSD(new_item_id));
+ }
+ }
+ LL_DEBUGS("MaterialEditor") << "New floater key: " << getKey() << " Old key: " << old_key << LL_ENDL;
+ loadAsset();
+}
+
+
+void LLMaterialEditor::onClickSaveAs()
+{
+ if (!LLMaterialEditor::capabilitiesAvailable())
+ {
+ LLNotificationsUtil::add("MissingMaterialCaps");
+ return;
+ }
+
+ if (!can_afford_transaction(mExpectedUploadCost))
+ {
+ LLSD args;
+ args["COST"] = llformat("%d", mExpectedUploadCost);
+ LLNotificationsUtil::add("ErrorCannotAffordUpload", args);
+ return;
+ }
+
+ LLSD args;
+ args["DESC"] = mMaterialName;
+
+ LLNotificationsUtil::add("SaveMaterialAs", args, LLSD(), boost::bind(&LLMaterialEditor::onSaveAsMsgCallback, this, _1, _2));
+}
+
+void LLMaterialEditor::onSaveAsMsgCallback(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if (0 == option)
+ {
+ std::string new_name = response["message"].asString();
+ LLInventoryObject::correctInventoryName(new_name);
+ if (!new_name.empty())
+ {
+ const LLInventoryItem* item;
+ if (mNotecardInventoryID.notNull())
+ {
+ item = mAuxItem.get();
+ }
+ else
+ {
+ item = getItem();
+ }
+ if (item)
+ {
+ const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
+ LLUUID parent_id = item->getParentUUID();
+ if (mObjectUUID.notNull() || marketplacelistings_id == parent_id || gInventory.isObjectDescendentOf(item->getUUID(), gInventory.getLibraryRootFolderID()))
+ {
+ parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MATERIAL);
+ }
+
+ // A two step process, first copy an existing item, then create new asset
+ if (mNotecardInventoryID.notNull())
+ {
+ LLPointer<LLInventoryCallback> cb = new LLMaterialEditorCopiedCallback(getKey(), new_name);
+ copy_inventory_from_notecard(parent_id,
+ mNotecardObjectID,
+ mNotecardInventoryID,
+ mAuxItem.get(),
+ gInventoryCallbacks.registerCB(cb));
+ }
+ else
+ {
+ std::string buffer = getEncodedAsset();
+ LLPointer<LLInventoryCallback> cb = new LLMaterialEditorCopiedCallback(buffer, getKey(), mUnsavedChanges);
+ copy_inventory_item(
+ gAgent.getID(),
+ item->getPermissions().getOwner(),
+ item->getUUID(),
+ parent_id,
+ new_name,
+ cb);
+ }
+
+ mAssetStatus = PREVIEW_ASSET_LOADING;
+ setEnabled(false);
+ }
+ else
+ {
+ setMaterialName(new_name);
+ onClickSave();
+ }
+ }
+ else
+ {
+ LLNotificationsUtil::add("InvalidMaterialName");
+ }
+ }
+}
+
+void LLMaterialEditor::onClickCancel()
+{
+ if (mUnsavedChanges)
+ {
+ LLNotificationsUtil::add("UsavedMaterialChanges", LLSD(), LLSD(), boost::bind(&LLMaterialEditor::onCancelMsgCallback, this, _1, _2));
+ }
+ else
+ {
+ closeFloater();
+ }
+}
+
+void LLMaterialEditor::onCancelMsgCallback(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if (0 == option)
+ {
+ closeFloater();
+ }
+}
+
+static void pack_textures(
+ LLPointer<LLImageRaw>& base_color_img,
+ LLPointer<LLImageRaw>& normal_img,
+ LLPointer<LLImageRaw>& mr_img,
+ LLPointer<LLImageRaw>& emissive_img,
+ LLPointer<LLImageRaw>& occlusion_img,
+ LLPointer<LLImageJ2C>& base_color_j2c,
+ LLPointer<LLImageJ2C>& normal_j2c,
+ LLPointer<LLImageJ2C>& mr_j2c,
+ LLPointer<LLImageJ2C>& emissive_j2c)
+{
+ // NOTE : remove log spam and lossless vs lossy comparisons when the logs are no longer useful
+
+ if (base_color_img)
+ {
+ base_color_j2c = LLViewerTextureList::convertToUploadFile(base_color_img);
+ LL_DEBUGS("MaterialEditor") << "BaseColor: " << base_color_j2c->getDataSize() << LL_ENDL;
+ }
+
+ if (normal_img)
+ {
+ normal_j2c = LLViewerTextureList::convertToUploadFile(normal_img);
+
+ LLPointer<LLImageJ2C> test;
+ test = LLViewerTextureList::convertToUploadFile(normal_img, 1024, true);
+
+ S32 lossy_bytes = normal_j2c->getDataSize();
+ S32 lossless_bytes = test->getDataSize();
+
+ LL_DEBUGS("MaterialEditor") << llformat("Lossless vs Lossy: (%d/%d) = %.2f", lossless_bytes, lossy_bytes, (F32)lossless_bytes / lossy_bytes) << LL_ENDL;
+
+ normal_j2c = test;
+ }
+
+ if (mr_img)
+ {
+ mr_j2c = LLViewerTextureList::convertToUploadFile(mr_img);
+ LL_DEBUGS("MaterialEditor") << "Metallic/Roughness: " << mr_j2c->getDataSize() << LL_ENDL;
+ }
+
+ if (emissive_img)
+ {
+ emissive_j2c = LLViewerTextureList::convertToUploadFile(emissive_img);
+ LL_DEBUGS("MaterialEditor") << "Emissive: " << emissive_j2c->getDataSize() << LL_ENDL;
+ }
+}
+
+void LLMaterialEditor::uploadMaterialFromFile(const std::string& filename, S32 index)
+{
+ if (index < 0 || !LLMaterialEditor::capabilitiesAvailable())
+ {
+ return;
+ }
+
+ tinygltf::TinyGLTF loader;
+ std::string error_msg;
+ std::string warn_msg;
+
+ bool loaded = false;
+ tinygltf::Model model_in;
+
+ std::string filename_lc = filename;
+ LLStringUtil::toLower(filename_lc);
+
+ // Load a tinygltf model fom a file. Assumes that the input filename has already been
+ // been sanitized to one of (.gltf , .glb) extensions, so does a simple find to distinguish.
+ if (std::string::npos == filename_lc.rfind(".gltf"))
+ { // file is binary
+ loaded = loader.LoadBinaryFromFile(&model_in, &error_msg, &warn_msg, filename);
+ }
+ else
+ { // file is ascii
+ loaded = loader.LoadASCIIFromFile(&model_in, &error_msg, &warn_msg, filename);
+ }
+
+ if (!loaded)
+ {
+ LLNotificationsUtil::add("CannotUploadMaterial");
+ return;
+ }
+
+ if (model_in.materials.empty())
+ {
+ // materials are missing
+ return;
+ }
+
+ if (index >= 0 && model_in.materials.size() <= index)
+ {
+ // material is missing
+ return;
+ }
+
+ // Todo: no point in loading whole editor
+ // This uses 'filename' to make sure multiple bulk uploads work
+ // instead of fighting for a single instance.
+ LLMaterialEditor* me = (LLMaterialEditor*)LLFloaterReg::getInstance("material_editor", LLSD().with("filename", filename).with("index", LLSD::Integer(index)));
+ me->loadMaterial(model_in, filename_lc, index, false);
+ me->saveIfNeeded();
+}
+
+
+void LLMaterialEditor::loadMaterialFromFile(const std::string& filename, S32 index)
+{
+ tinygltf::TinyGLTF loader;
+ std::string error_msg;
+ std::string warn_msg;
+
+ bool loaded = false;
+ tinygltf::Model model_in;
+
+ std::string filename_lc = filename;
+ LLStringUtil::toLower(filename_lc);
+
+ // Load a tinygltf model fom a file. Assumes that the input filename has already been
+ // been sanitized to one of (.gltf , .glb) extensions, so does a simple find to distinguish.
+ if (std::string::npos == filename_lc.rfind(".gltf"))
+ { // file is binary
+ loaded = loader.LoadBinaryFromFile(&model_in, &error_msg, &warn_msg, filename);
+ }
+ else
+ { // file is ascii
+ loaded = loader.LoadASCIIFromFile(&model_in, &error_msg, &warn_msg, filename);
+ }
+
+ if (!loaded)
+ {
+ LLNotificationsUtil::add("CannotUploadMaterial");
+ return;
+ }
+
+ if (model_in.materials.empty())
+ {
+ // materials are missing
+ LLNotificationsUtil::add("CannotUploadMaterial");
+ return;
+ }
+
+ if (index >= 0 && model_in.materials.size() <= index)
+ {
+ // material is missing
+ LLNotificationsUtil::add("CannotUploadMaterial");
+ return;
+ }
+
+ LLMaterialEditor* me = (LLMaterialEditor*)LLFloaterReg::getInstance("material_editor");
+
+ if (index >= 0)
+ {
+ // Prespecified material
+ me->loadMaterial(model_in, filename_lc, index);
+ }
+ else if (model_in.materials.size() == 1)
+ {
+ // Only one, just load it
+ me->loadMaterial(model_in, filename_lc, 0);
+ }
+ else
+ {
+ // Promt user to select material
+ std::list<std::string> material_list;
+ std::vector<tinygltf::Material>::const_iterator mat_iter = model_in.materials.begin();
+ std::vector<tinygltf::Material>::const_iterator mat_end = model_in.materials.end();
+ for (; mat_iter != mat_end; mat_iter++)
+ {
+ std::string mat_name = mat_iter->name;
+ if (mat_name.empty())
+ {
+ material_list.push_back("Material " + std::to_string(material_list.size()));
+ }
+ else
+ {
+ material_list.push_back(mat_name);
+ }
+ }
+ LLFloaterComboOptions::showUI(
+ [me, model_in, filename_lc](const std::string& option, S32 index)
+ {
+ me->loadMaterial(model_in, filename_lc, index);
+ },
+ me->getString("material_selection_title"),
+ me->getString("material_selection_text"),
+ material_list
+ );
+ }
+}
+
+void LLMaterialEditor::onSelectionChanged()
+{
+ // Drop selection updates if we are waiting for
+ // overrides to finish applying to not reset values
+ // (might need a timeout)
+ if (!mOverrideInProgress)
+ {
+ // mUpdateSignal triggers a lot per frame, breakwater
+ mSelectionNeedsUpdate = true;
+ }
+}
+
+void LLMaterialEditor::updateLive()
+{
+ mSelectionNeedsUpdate = true;
+ mOverrideInProgress = false;
+}
+
+void LLMaterialEditor::updateLive(const LLUUID &object_id, S32 te)
+{
+ if (mOverrideObjectId != object_id
+ || mOverrideObjectTE != te)
+ {
+ // Ignore if waiting for override,
+ // if not waiting, mark selection dirty
+ mSelectionNeedsUpdate |= !mOverrideInProgress;
+ return;
+ }
+
+ // update for currently displayed object and face
+ mSelectionNeedsUpdate = true;
+ mOverrideInProgress = false;
+}
+
+void LLMaterialEditor::loadLive()
+{
+ LLMaterialEditor* me = (LLMaterialEditor*)LLFloaterReg::getInstance("live_material_editor");
+ if (me)
+ {
+ me->mOverrideInProgress = false;
+ me->setFromSelection();
+
+ // Set up for selection changes updates
+ if (!me->mSelectionUpdateSlot.connected())
+ {
+ me->mSelectionUpdateSlot = LLSelectMgr::instance().mUpdateSignal.connect(boost::bind(&LLMaterialEditor::onSelectionChanged, me));
+ }
+
+ me->openFloater();
+ me->setFocus(TRUE);
+ }
+}
+
+void LLMaterialEditor::saveObjectsMaterialAs()
+{
+ LLSelectedTEGetMatData func(false);
+ LLSelectMgr::getInstance()->getSelection()->applyToTEs(&func, true /*first applicable*/);
+ saveMaterialAs(func.mMaterial, func.mLocalMaterial);
+}
+void LLMaterialEditor::savePickedMaterialAs()
+{
+ LLPickInfo pick = LLToolPie::getInstance()->getPick();
+ if (pick.mPickType != LLPickInfo::PICK_OBJECT || !pick.getObject())
+ {
+ return;
+ }
+
+ LLPointer<LLGLTFMaterial> render_material;
+ LLPointer<LLLocalGLTFMaterial> local_material;
+
+ LLViewerObject *objectp = pick.getObject();
+ LLUUID mat_id = objectp->getRenderMaterialID(pick.mObjectFace);
+ if (mat_id.notNull() && objectp->permCopy())
+ {
+ // Try a face user picked first
+ // (likely the only method we need, but in such case
+ // enable_object_save_gltf_material will need to check this)
+ LLTextureEntry *tep = objectp->getTE(pick.mObjectFace);
+ LLGLTFMaterial *mat = tep->getGLTFMaterial();
+ LLLocalGLTFMaterial *local_mat = dynamic_cast<LLLocalGLTFMaterial*>(mat);
+
+ if (local_mat)
+ {
+ local_material = local_mat;
+ }
+ render_material = tep->getGLTFRenderMaterial();
+ }
+ else
+ {
+ // Find an applicable material.
+ // Do this before showing message, because
+ // message is going to drop selection.
+ LLSelectedTEGetMatData func(false);
+ LLSelectMgr::getInstance()->getSelection()->applyToTEs(&func, true /*first applicable*/);
+ local_material = func.mLocalMaterial;
+ render_material = func.mMaterial;
+ }
+
+ saveMaterialAs(render_material, local_material);
+}
+
+void LLMaterialEditor::saveMaterialAs(const LLGLTFMaterial* render_material, const LLLocalGLTFMaterial *local_material)
+{
+ if (local_material)
+ {
+ // This is a local material, reload it from file
+ // so that user won't end up with grey textures
+ // on next login.
+ LLMaterialEditor::loadMaterialFromFile(local_material->getFilename(), local_material->getIndexInFile());
+
+ LLMaterialEditor* me = (LLMaterialEditor*)LLFloaterReg::getInstance("material_editor");
+ if (me)
+ {
+ // don't use override material here, it has 'hacked ids'
+ // and values, use end result, apply it on top of local.
+ me->setBaseColor(render_material->mBaseColor);
+ me->setMetalnessFactor(render_material->mMetallicFactor);
+ me->setRoughnessFactor(render_material->mRoughnessFactor);
+ me->setEmissiveColor(render_material->mEmissiveColor);
+ me->setDoubleSided(render_material->mDoubleSided);
+ me->setAlphaMode(render_material->getAlphaMode());
+ me->setAlphaCutoff(render_material->mAlphaCutoff);
+
+ // most things like colors we can apply without verifying
+ // but texture ids are going to be different from both, base and override
+ // so only apply override id if there is actually a difference
+ if (local_material->mBaseColorId != render_material->mBaseColorId)
+ {
+ me->setBaseColorId(render_material->mBaseColorId);
+ me->childSetValue("base_color_upload_fee", me->getString("no_upload_fee_string"));
+ }
+ if (local_material->mNormalId != render_material->mNormalId)
+ {
+ me->setNormalId(render_material->mNormalId);
+ me->childSetValue("normal_upload_fee", me->getString("no_upload_fee_string"));
+ }
+ if (local_material->mMetallicRoughnessId != render_material->mMetallicRoughnessId)
+ {
+ me->setMetallicRoughnessId(render_material->mMetallicRoughnessId);
+ me->childSetValue("metallic_upload_fee", me->getString("no_upload_fee_string"));
+ }
+ if (local_material->mEmissiveId != render_material->mEmissiveId)
+ {
+ me->setEmissiveId(render_material->mEmissiveId);
+ me->childSetValue("emissive_upload_fee", me->getString("no_upload_fee_string"));
+ }
+
+ // recalculate upload prices
+ me->markChangesUnsaved(0);
+ }
+
+ return;
+ }
+
+ LLSD payload;
+ if (render_material)
+ {
+ payload["data"] = render_material->asJSON();
+ }
+ else
+ {
+ // Menu shouldn't allow this, but as a fallback
+ // pick defaults from a blank material
+ LLGLTFMaterial blank_mat;
+ payload["data"] = blank_mat.asJSON();
+ LL_WARNS() << "Got no material when trying to save material" << LL_ENDL;
+ }
+
+ LLSD args;
+ args["DESC"] = LLTrans::getString("New Material");
+
+ LLNotificationsUtil::add("SaveMaterialAs", args, payload, boost::bind(&LLMaterialEditor::onSaveObjectsMaterialAsMsgCallback, _1, _2));
+}
+
+void LLMaterialEditor::onSaveObjectsMaterialAsMsgCallback(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if (0 == option)
+ {
+ LLSD asset;
+ asset["version"] = "1.0";
+ asset["type"] = "GLTF 2.0";
+ asset["data"] = notification["payload"]["data"];
+
+ std::ostringstream str;
+ LLSDSerialize::serialize(asset, str, LLSDSerialize::LLSD_BINARY);
+
+ std::string new_name = response["message"].asString();
+ createInventoryItem(str.str(), new_name, std::string());
+ }
+}
+
+void LLMaterialEditor::loadMaterial(const tinygltf::Model &model_in, const std::string &filename_lc, S32 index, bool open_floater)
+{
+ if (model_in.materials.size() <= index)
+ {
+ return;
+ }
+ std::string folder = gDirUtilp->getDirName(filename_lc);
+
+ tinygltf::Material material_in = model_in.materials[index];
+
+ tinygltf::Model model_out;
+ model_out.asset.version = "2.0";
+ model_out.materials.resize(1);
+
+ // get base color texture
+ LLPointer<LLImageRaw> base_color_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.pbrMetallicRoughness.baseColorTexture.index, mBaseColorName);
+ // get normal map
+ LLPointer<LLImageRaw> normal_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.normalTexture.index, mNormalName);
+ // get metallic-roughness texture
+ LLPointer<LLImageRaw> mr_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.pbrMetallicRoughness.metallicRoughnessTexture.index, mMetallicRoughnessName);
+ // get emissive texture
+ LLPointer<LLImageRaw> emissive_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.emissiveTexture.index, mEmissiveName);
+ // get occlusion map if needed
+ LLPointer<LLImageRaw> occlusion_img;
+ if (material_in.occlusionTexture.index != material_in.pbrMetallicRoughness.metallicRoughnessTexture.index)
+ {
+ std::string tmp;
+ occlusion_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.occlusionTexture.index, tmp);
+ }
+
+ LLTinyGLTFHelper::initFetchedTextures(material_in, base_color_img, normal_img, mr_img, emissive_img, occlusion_img,
+ mBaseColorFetched, mNormalFetched, mMetallicRoughnessFetched, mEmissiveFetched);
+ pack_textures(base_color_img, normal_img, mr_img, emissive_img, occlusion_img,
+ mBaseColorJ2C, mNormalJ2C, mMetallicRoughnessJ2C, mEmissiveJ2C);
+
+ LLUUID base_color_id;
+ if (mBaseColorFetched.notNull())
+ {
+ mBaseColorFetched->forceToSaveRawImage(0, F32_MAX);
+ base_color_id = mBaseColorFetched->getID();
+
+ if (mBaseColorName.empty())
+ {
+ mBaseColorName = MATERIAL_BASE_COLOR_DEFAULT_NAME;
+ }
+ }
+
+ LLUUID normal_id;
+ if (mNormalFetched.notNull())
+ {
+ mNormalFetched->forceToSaveRawImage(0, F32_MAX);
+ normal_id = mNormalFetched->getID();
+
+ if (mNormalName.empty())
+ {
+ mNormalName = MATERIAL_NORMAL_DEFAULT_NAME;
+ }
+ }
+
+ LLUUID mr_id;
+ if (mMetallicRoughnessFetched.notNull())
+ {
+ mMetallicRoughnessFetched->forceToSaveRawImage(0, F32_MAX);
+ mr_id = mMetallicRoughnessFetched->getID();
+
+ if (mMetallicRoughnessName.empty())
+ {
+ mMetallicRoughnessName = MATERIAL_METALLIC_DEFAULT_NAME;
+ }
+ }
+
+ LLUUID emissive_id;
+ if (mEmissiveFetched.notNull())
+ {
+ mEmissiveFetched->forceToSaveRawImage(0, F32_MAX);
+ emissive_id = mEmissiveFetched->getID();
+
+ if (mEmissiveName.empty())
+ {
+ mEmissiveName = MATERIAL_EMISSIVE_DEFAULT_NAME;
+ }
+ }
+
+ setBaseColorId(base_color_id);
+ setBaseColorUploadId(base_color_id);
+ setMetallicRoughnessId(mr_id);
+ setMetallicRoughnessUploadId(mr_id);
+ setEmissiveId(emissive_id);
+ setEmissiveUploadId(emissive_id);
+ setNormalId(normal_id);
+ setNormalUploadId(normal_id);
+
+ setFromGltfModel(model_in, index);
+
+ setFromGltfMetaData(filename_lc, model_in, index);
+
+ markChangesUnsaved(U32_MAX);
+
+ if (open_floater)
+ {
+ openFloater(getKey());
+ setFocus(TRUE);
+ setCanSave(true);
+ setCanSaveAs(true);
+
+ applyToSelection();
+ }
+}
+
+bool LLMaterialEditor::setFromGltfModel(const tinygltf::Model& model, S32 index, bool set_textures)
+{
+ if (model.materials.size() > index)
+ {
+ const tinygltf::Material& material_in = model.materials[index];
+
+ if (set_textures)
+ {
+ S32 index;
+ LLUUID id;
+
+ // get base color texture
+ index = material_in.pbrMetallicRoughness.baseColorTexture.index;
+ if (index >= 0)
+ {
+ id.set(model.images[index].uri);
+ setBaseColorId(id);
+ }
+ else
+ {
+ setBaseColorId(LLUUID::null);
+ }
+
+ // get normal map
+ index = material_in.normalTexture.index;
+ if (index >= 0)
+ {
+ id.set(model.images[index].uri);
+ setNormalId(id);
+ }
+ else
+ {
+ setNormalId(LLUUID::null);
+ }
+
+ // get metallic-roughness texture
+ index = material_in.pbrMetallicRoughness.metallicRoughnessTexture.index;
+ if (index >= 0)
+ {
+ id.set(model.images[index].uri);
+ setMetallicRoughnessId(id);
+ }
+ else
+ {
+ setMetallicRoughnessId(LLUUID::null);
+ }
+
+ // get emissive texture
+ index = material_in.emissiveTexture.index;
+ if (index >= 0)
+ {
+ id.set(model.images[index].uri);
+ setEmissiveId(id);
+ }
+ else
+ {
+ setEmissiveId(LLUUID::null);
+ }
+ }
+
+ setAlphaMode(material_in.alphaMode);
+ setAlphaCutoff(material_in.alphaCutoff);
+
+ setBaseColor(LLTinyGLTFHelper::getColor(material_in.pbrMetallicRoughness.baseColorFactor));
+ setEmissiveColor(LLTinyGLTFHelper::getColor(material_in.emissiveFactor));
+
+ setMetalnessFactor(material_in.pbrMetallicRoughness.metallicFactor);
+ setRoughnessFactor(material_in.pbrMetallicRoughness.roughnessFactor);
+
+ setDoubleSided(material_in.doubleSided);
+ }
+
+ return true;
+}
+
+/**
+ * Build a texture name from the contents of the (in tinyGLFT parlance)
+ * Image URI. This often is filepath to the original image on the users'
+ * local file system.
+ */
+const std::string LLMaterialEditor::getImageNameFromUri(std::string image_uri, const std::string texture_type)
+{
+ // getBaseFileName() works differently on each platform and file patchs
+ // can contain both types of delimiter so unify them then extract the
+ // base name (no path or extension)
+ std::replace(image_uri.begin(), image_uri.end(), '\\', gDirUtilp->getDirDelimiter()[0]);
+ std::replace(image_uri.begin(), image_uri.end(), '/', gDirUtilp->getDirDelimiter()[0]);
+ const bool strip_extension = true;
+ std::string stripped_uri = gDirUtilp->getBaseFileName(image_uri, strip_extension);
+
+ // sometimes they can be really long and unwieldy - 64 chars is enough for anyone :)
+ const int max_texture_name_length = 64;
+ if (stripped_uri.length() > max_texture_name_length)
+ {
+ stripped_uri = stripped_uri.substr(0, max_texture_name_length - 1);
+ }
+
+ // We intend to append the type of texture (base color, emissive etc.) to the
+ // name of the texture but sometimes the creator already did that. To try
+ // to avoid repeats (not perfect), we look for the texture type in the name
+ // and if we find it, do not append the type, later on. One way this fails
+ // (and it's fine for now) is I see some texture/image uris have a name like
+ // "metallic roughness" and of course, that doesn't match our predefined
+ // name "metallicroughness" - consider fix later..
+ bool name_includes_type = false;
+ std::string stripped_uri_lower = stripped_uri;
+ LLStringUtil::toLower(stripped_uri_lower);
+ stripped_uri_lower.erase(std::remove_if(stripped_uri_lower.begin(), stripped_uri_lower.end(), isspace), stripped_uri_lower.end());
+ std::string texture_type_lower = texture_type;
+ LLStringUtil::toLower(texture_type_lower);
+ texture_type_lower.erase(std::remove_if(texture_type_lower.begin(), texture_type_lower.end(), isspace), texture_type_lower.end());
+ if (stripped_uri_lower.find(texture_type_lower) != std::string::npos)
+ {
+ name_includes_type = true;
+ }
+
+ // uri doesn't include the type at all
+ if (name_includes_type == false)
+ {
+ // uri doesn't include the type and the uri is not empty
+ // so we can include everything
+ if (stripped_uri.length() > 0)
+ {
+ // example "DamagedHelmet: base layer"
+ return STRINGIZE(
+ mMaterialNameShort <<
+ ": " <<
+ stripped_uri <<
+ " (" <<
+ texture_type <<
+ ")"
+ );
+ }
+ else
+ // uri doesn't include the type (because the uri is empty)
+ // so we must reorganize the string a bit to include the name
+ // and an explicit name type
+ {
+ // example "DamagedHelmet: (Emissive)"
+ return STRINGIZE(
+ mMaterialNameShort <<
+ " (" <<
+ texture_type <<
+ ")"
+ );
+ }
+ }
+ else
+ // uri includes the type so just use it directly with the
+ // name of the material
+ {
+ return STRINGIZE(
+ // example: AlienBust: normal_layer
+ mMaterialNameShort <<
+ ": " <<
+ stripped_uri
+ );
+ }
+}
+
+/**
+ * Update the metadata for the material based on what we find in the loaded
+ * file (along with some assumptions and interpretations...). Fields include
+ * the name of the material, a material description and the names of the
+ * composite textures.
+ */
+void LLMaterialEditor::setFromGltfMetaData(const std::string& filename, const tinygltf::Model& model, S32 index)
+{
+ // Use the name (without any path/extension) of the file that was
+ // uploaded as the base of the material name. Then if the name of the
+ // scene is present and not blank, append that and use the result as
+ // the name of the material. This is a first pass at creating a
+ // naming scheme that is useful to real content creators and hopefully
+ // avoid 500 materials in your inventory called "scene" or "Default"
+ const bool strip_extension = true;
+ std::string base_filename = gDirUtilp->getBaseFileName(filename, strip_extension);
+
+ // Extract the name of the scene. Note it is often blank or some very
+ // generic name like "Scene" or "Default" so using this in the name
+ // is less useful than you might imagine.
+ std::string material_name;
+ if (model.materials.size() > index && !model.materials[index].name.empty())
+ {
+ material_name = model.materials[index].name;
+ }
+ else if (model.scenes.size() > 0)
+ {
+ const tinygltf::Scene& scene_in = model.scenes[0];
+ if (scene_in.name.length())
+ {
+ material_name = scene_in.name;
+ }
+ else
+ {
+ // scene name is empty so no point using it
+ }
+ }
+ else
+ {
+ // scene name isn't present so no point using it
+ }
+
+ // If we have a valid material or scene name, use it to build the short and
+ // long versions of the material name. The long version is used
+ // as you might expect, for the material name. The short version is
+ // used as part of the image/texture name - the theory is that will
+ // allow content creators to track the material and the corresponding
+ // textures
+ if (material_name.length())
+ {
+ mMaterialNameShort = base_filename;
+
+ mMaterialName = STRINGIZE(
+ base_filename <<
+ " " <<
+ "(" <<
+ material_name <<
+ ")"
+ );
+ }
+ else
+ // otherwise, just use the trimmed filename as is
+ {
+ mMaterialNameShort = base_filename;
+ mMaterialName = base_filename;
+ }
+
+ // sanitize the material name so that it's compatible with the inventory
+ LLInventoryObject::correctInventoryName(mMaterialName);
+ LLInventoryObject::correctInventoryName(mMaterialNameShort);
+
+ // We also set the title of the floater to match the
+ // name of the material
+ setTitle(mMaterialName);
+
+ /**
+ * Extract / derive the names of each composite texture. For each, the
+ * index is used to to determine which of the "Images" is used. If the index
+ * is -1 then that texture type is not present in the material (Seems to be
+ * quite common that a material is missing 1 or more types of texture)
+ */
+ if (model.materials.size() > index)
+ {
+ const tinygltf::Material& first_material = model.materials[index];
+
+ mBaseColorName = MATERIAL_BASE_COLOR_DEFAULT_NAME;
+ // note: unlike the other textures, base color doesn't have its own entry
+ // in the tinyGLTF Material struct. Rather, it is taken from a
+ // sub-texture in the pbrMetallicRoughness member
+ int index = first_material.pbrMetallicRoughness.baseColorTexture.index;
+ if (index > -1 && index < model.images.size())
+ {
+ // sanitize the name we decide to use for each texture
+ std::string texture_name = getImageNameFromUri(model.images[index].uri, MATERIAL_BASE_COLOR_DEFAULT_NAME);
+ LLInventoryObject::correctInventoryName(texture_name);
+ mBaseColorName = texture_name;
+ }
+
+ mEmissiveName = MATERIAL_EMISSIVE_DEFAULT_NAME;
+ index = first_material.emissiveTexture.index;
+ if (index > -1 && index < model.images.size())
+ {
+ std::string texture_name = getImageNameFromUri(model.images[index].uri, MATERIAL_EMISSIVE_DEFAULT_NAME);
+ LLInventoryObject::correctInventoryName(texture_name);
+ mEmissiveName = texture_name;
+ }
+
+ mMetallicRoughnessName = MATERIAL_METALLIC_DEFAULT_NAME;
+ index = first_material.pbrMetallicRoughness.metallicRoughnessTexture.index;
+ if (index > -1 && index < model.images.size())
+ {
+ std::string texture_name = getImageNameFromUri(model.images[index].uri, MATERIAL_METALLIC_DEFAULT_NAME);
+ LLInventoryObject::correctInventoryName(texture_name);
+ mMetallicRoughnessName = texture_name;
+ }
+
+ mNormalName = MATERIAL_NORMAL_DEFAULT_NAME;
+ index = first_material.normalTexture.index;
+ if (index > -1 && index < model.images.size())
+ {
+ std::string texture_name = getImageNameFromUri(model.images[index].uri, MATERIAL_NORMAL_DEFAULT_NAME);
+ LLInventoryObject::correctInventoryName(texture_name);
+ mNormalName = texture_name;
+ }
+ }
+}
+
+void LLMaterialEditor::importMaterial()
+{
+ LLFilePickerReplyThread::startPicker(
+ [](const std::vector<std::string>& filenames, LLFilePicker::ELoadFilter load_filter, LLFilePicker::ESaveFilter save_filter)
+ {
+ if (LLAppViewer::instance()->quitRequested())
+ {
+ return;
+ }
+ if (filenames.size() > 0)
+ {
+ LLMaterialEditor::loadMaterialFromFile(filenames[0], -1);
+ }
+ },
+ LLFilePicker::FFLOAD_MATERIAL,
+ true);
+}
+
+class LLRenderMaterialFunctor : public LLSelectedTEFunctor
+{
+public:
+ LLRenderMaterialFunctor(const LLUUID &id)
+ : mMatId(id)
+ {
+ }
+
+ bool apply(LLViewerObject* objectp, S32 te) override
+ {
+ if (objectp && objectp->permModify() && objectp->getVolume())
+ {
+ LLVOVolume* vobjp = (LLVOVolume*)objectp;
+ vobjp->setRenderMaterialID(te, mMatId, false /*preview only*/);
+ vobjp->updateTEMaterialTextures(te);
+ }
+ return true;
+ }
+private:
+ LLUUID mMatId;
+};
+
+class LLRenderMaterialOverrideFunctor : public LLSelectedNodeFunctor
+{
+public:
+ LLRenderMaterialOverrideFunctor(
+ LLMaterialEditor * me,
+ const LLUUID &report_on_object_id,
+ S32 report_on_te)
+ : mEditor(me)
+ , mSuccess(false)
+ , mObjectId(report_on_object_id)
+ , mObjectTE(report_on_te)
+ {
+ }
+
+ virtual bool apply(LLSelectNode* nodep) override
+ {
+ LLViewerObject* objectp = nodep->getObject();
+ if (!objectp || !objectp->permModify() || !objectp->getVolume())
+ {
+ return false;
+ }
+ S32 num_tes = llmin((S32)objectp->getNumTEs(), (S32)objectp->getNumFaces()); // avatars have TEs but no faces
+
+ // post override from given object and te to the simulator
+ // requestData should have:
+ // object_id - UUID of LLViewerObject
+ // side - S32 index of texture entry
+ // gltf_json - String of GLTF json for override data
+
+ for (S32 te = 0; te < num_tes; ++te)
+ {
+ if (!nodep->isTESelected(te))
+ {
+ continue;
+ }
+
+ // Get material from object
+ // Selection can cover multiple objects, and live editor is
+ // supposed to overwrite changed values only
+ LLTextureEntry* tep = objectp->getTE(te);
+
+ if (tep->getGLTFMaterial() == nullptr)
+ {
+ // overrides are not supposed to work or apply if
+ // there is no base material to work from
+ continue;
+ }
+
+ LLPointer<LLGLTFMaterial> material = tep->getGLTFMaterialOverride();
+ // make a copy to not invalidate existing
+ // material for multiple objects
+ if (material.isNull())
+ {
+ // Start with a material override which does not make any changes
+ material = new LLGLTFMaterial();
+ }
+ else
+ {
+ material = new LLGLTFMaterial(*material);
+ }
+
+ U32 changed_flags = mEditor->getUnsavedChangesFlags();
+ U32 reverted_flags = mEditor->getRevertedChangesFlags();
+
+ LLPointer<LLGLTFMaterial> revert_mat;
+ if (nodep->mSavedGLTFOverrideMaterials.size() > te)
+ {
+ if (nodep->mSavedGLTFOverrideMaterials[te].notNull())
+ {
+ revert_mat = nodep->mSavedGLTFOverrideMaterials[te];
+ }
+ else
+ {
+ // mSavedGLTFOverrideMaterials[te] being present but null
+ // means we need to use a default value
+ revert_mat = new LLGLTFMaterial();
+ }
+ }
+ // else can not revert at all
+
+ // Override object's values with values from editor where appropriate
+ if (changed_flags & MATERIAL_BASE_COLOR_DIRTY)
+ {
+ material->setBaseColorFactor(mEditor->getBaseColor(), true);
+ }
+ else if ((reverted_flags & MATERIAL_BASE_COLOR_DIRTY) && revert_mat.notNull())
+ {
+ material->setBaseColorFactor(revert_mat->mBaseColor, false);
+ }
+
+ if (changed_flags & MATERIAL_BASE_COLOR_TEX_DIRTY)
+ {
+ material->setBaseColorId(mEditor->getBaseColorId(), true);
+ }
+ else if ((reverted_flags & MATERIAL_BASE_COLOR_TEX_DIRTY) && revert_mat.notNull())
+ {
+ material->setBaseColorId(revert_mat->mBaseColorId, false);
+ }
+
+ if (changed_flags & MATERIAL_NORMAL_TEX_DIRTY)
+ {
+ material->setNormalId(mEditor->getNormalId(), true);
+ }
+ else if ((reverted_flags & MATERIAL_NORMAL_TEX_DIRTY) && revert_mat.notNull())
+ {
+ material->setNormalId(revert_mat->mNormalId, false);
+ }
+
+ if (changed_flags & MATERIAL_METALLIC_ROUGHTNESS_TEX_DIRTY)
+ {
+ material->setMetallicRoughnessId(mEditor->getMetallicRoughnessId(), true);
+ }
+ else if ((reverted_flags & MATERIAL_METALLIC_ROUGHTNESS_TEX_DIRTY) && revert_mat.notNull())
+ {
+ material->setMetallicRoughnessId(revert_mat->mMetallicRoughnessId, false);
+ }
+
+ if (changed_flags & MATERIAL_METALLIC_ROUGHTNESS_METALNESS_DIRTY)
+ {
+ material->setMetallicFactor(mEditor->getMetalnessFactor(), true);
+ }
+ else if ((reverted_flags & MATERIAL_METALLIC_ROUGHTNESS_METALNESS_DIRTY) && revert_mat.notNull())
+ {
+ material->setMetallicFactor(revert_mat->mMetallicFactor, false);
+ }
+
+ if (changed_flags & MATERIAL_METALLIC_ROUGHTNESS_ROUGHNESS_DIRTY)
+ {
+ material->setRoughnessFactor(mEditor->getRoughnessFactor(), true);
+ }
+ else if ((reverted_flags & MATERIAL_METALLIC_ROUGHTNESS_ROUGHNESS_DIRTY) && revert_mat.notNull())
+ {
+ material->setRoughnessFactor(revert_mat->mRoughnessFactor, false);
+ }
+
+ if (changed_flags & MATERIAL_EMISIVE_COLOR_DIRTY)
+ {
+ material->setEmissiveColorFactor(LLColor3(mEditor->getEmissiveColor()), true);
+ }
+ else if ((reverted_flags & MATERIAL_EMISIVE_COLOR_DIRTY) && revert_mat.notNull())
+ {
+ material->setEmissiveColorFactor(revert_mat->mEmissiveColor, false);
+ }
+
+ if (changed_flags & MATERIAL_EMISIVE_TEX_DIRTY)
+ {
+ material->setEmissiveId(mEditor->getEmissiveId(), true);
+ }
+ else if ((reverted_flags & MATERIAL_EMISIVE_TEX_DIRTY) && revert_mat.notNull())
+ {
+ material->setEmissiveId(revert_mat->mEmissiveId, false);
+ }
+
+ if (changed_flags & MATERIAL_DOUBLE_SIDED_DIRTY)
+ {
+ material->setDoubleSided(mEditor->getDoubleSided(), true);
+ }
+ else if ((reverted_flags & MATERIAL_DOUBLE_SIDED_DIRTY) && revert_mat.notNull())
+ {
+ material->setDoubleSided(revert_mat->mDoubleSided, false);
+ }
+
+ if (changed_flags & MATERIAL_ALPHA_MODE_DIRTY)
+ {
+ material->setAlphaMode(mEditor->getAlphaMode(), true);
+ }
+ else if ((reverted_flags & MATERIAL_ALPHA_MODE_DIRTY) && revert_mat.notNull())
+ {
+ material->setAlphaMode(revert_mat->mAlphaMode, false);
+ }
+
+ if (changed_flags & MATERIAL_ALPHA_CUTOFF_DIRTY)
+ {
+ material->setAlphaCutoff(mEditor->getAlphaCutoff(), true);
+ }
+ else if ((reverted_flags & MATERIAL_ALPHA_CUTOFF_DIRTY) && revert_mat.notNull())
+ {
+ material->setAlphaCutoff(revert_mat->mAlphaCutoff, false);
+ }
+
+ if (mObjectTE == te
+ && mObjectId == objectp->getID())
+ {
+ mSuccess = true;
+ }
+ LLGLTFMaterialList::queueModify(objectp, te, material);
+ }
+ return true;
+ }
+
+ static void modifyCallback(bool success)
+ {
+ if (!success)
+ {
+ // something went wrong update selection
+ LLMaterialEditor::updateLive();
+ }
+ // else we will get updateLive(obj, id) from applied overrides
+ }
+
+ bool getResult() { return mSuccess; }
+
+private:
+ LLMaterialEditor * mEditor;
+ LLUUID mObjectId;
+ S32 mObjectTE;
+ bool mSuccess;
+};
+
+void LLMaterialEditor::applyToSelection()
+{
+ if (!mIsOverride)
+ {
+ // Only apply if working with 'live' materials
+ // Might need a better way to distinguish 'live' mode.
+ // But only one live edit is supposed to work at a time
+ // as a pair to tools floater.
+ return;
+ }
+
+ std::string url = gAgent.getRegionCapability("ModifyMaterialParams");
+ if (!url.empty())
+ {
+ // Don't send data if there is nothing to send.
+ // Some UI elements will cause multiple commits,
+ // like spin ctrls on click and on down
+ if (mUnsavedChanges != 0 || mRevertedChanges != 0)
+ {
+ mOverrideInProgress = true;
+ LLObjectSelectionHandle selected_objects = LLSelectMgr::getInstance()->getSelection();
+ LLRenderMaterialOverrideFunctor override_func(this, mOverrideObjectId, mOverrideObjectTE);
+ selected_objects->applyToNodes(&override_func);
+
+ void(*done_callback)(bool) = LLRenderMaterialOverrideFunctor::modifyCallback;
+
+ LLGLTFMaterialList::flushUpdates(done_callback);
+
+ if (!override_func.getResult())
+ {
+ // OverrideFunctor didn't find expected object or face
+ mOverrideInProgress = false;
+ }
+
+ // we posted all changes
+ mUnsavedChanges = 0;
+ mRevertedChanges = 0;
+ }
+ }
+ else
+ {
+ LL_WARNS("MaterialEditor") << "Not connected to materials capable region, missing ModifyMaterialParams cap" << LL_ENDL;
+
+ // Fallback local preview. Will be removed once override systems is finished and new cap is deployed everywhere.
+ LLPointer<LLFetchedGLTFMaterial> mat = new LLFetchedGLTFMaterial();
+ getGLTFMaterial(mat);
+ static const LLUUID placeholder("984e183e-7811-4b05-a502-d79c6f978a98");
+ gGLTFMaterialList.addMaterial(placeholder, mat);
+ LLRenderMaterialFunctor mat_func(placeholder);
+ LLObjectSelectionHandle selected_objects = LLSelectMgr::getInstance()->getSelection();
+ selected_objects->applyToTEs(&mat_func);
+ }
+}
+
+void LLMaterialEditor::getGLTFMaterial(LLGLTFMaterial* mat)
+{
+ mat->mBaseColor = getBaseColor();
+ mat->mBaseColor.mV[3] = getTransparency();
+ mat->mBaseColorId = getBaseColorId();
+
+ mat->mNormalId = getNormalId();
+
+ mat->mMetallicRoughnessId = getMetallicRoughnessId();
+ mat->mMetallicFactor = getMetalnessFactor();
+ mat->mRoughnessFactor = getRoughnessFactor();
+
+ mat->mEmissiveColor = getEmissiveColor();
+ mat->mEmissiveId = getEmissiveId();
+
+ mat->mDoubleSided = getDoubleSided();
+ mat->setAlphaMode(getAlphaMode());
+ mat->mAlphaCutoff = getAlphaCutoff();
+}
+
+void LLMaterialEditor::setFromGLTFMaterial(LLGLTFMaterial* mat)
+{
+ setBaseColor(mat->mBaseColor);
+ setBaseColorId(mat->mBaseColorId);
+ setNormalId(mat->mNormalId);
+
+ setMetallicRoughnessId(mat->mMetallicRoughnessId);
+ setMetalnessFactor(mat->mMetallicFactor);
+ setRoughnessFactor(mat->mRoughnessFactor);
+
+ setEmissiveColor(mat->mEmissiveColor);
+ setEmissiveId(mat->mEmissiveId);
+
+ setDoubleSided(mat->mDoubleSided);
+ setAlphaMode(mat->getAlphaMode());
+ setAlphaCutoff(mat->mAlphaCutoff);
+}
+
+bool LLMaterialEditor::setFromSelection()
+{
+ LLObjectSelectionHandle selected_objects = LLSelectMgr::getInstance()->getSelection();
+ LLSelectedTEGetMatData func(mIsOverride);
+
+ selected_objects->applyToTEs(&func);
+ mHasSelection = !selected_objects->isEmpty();
+ mSelectionNeedsUpdate = false;
+
+ if (func.mMaterial.notNull())
+ {
+ setFromGLTFMaterial(func.mMaterial);
+ setEnableEditing(true);
+ }
+ else
+ {
+ // pick defaults from a blank material;
+ LLGLTFMaterial blank_mat;
+ setFromGLTFMaterial(&blank_mat);
+ if (mIsOverride)
+ {
+ setEnableEditing(false);
+ }
+ }
+
+ if (mIsOverride)
+ {
+ mBaseColorTextureCtrl->setTentative(!func.mIdenticalTexColor);
+ mMetallicTextureCtrl->setTentative(!func.mIdenticalTexMetal);
+ mEmissiveTextureCtrl->setTentative(!func.mIdenticalTexEmissive);
+ mNormalTextureCtrl->setTentative(!func.mIdenticalTexNormal);
+
+ // Memorize selection data for filtering further updates
+ mOverrideObjectId = func.mObjectId;
+ mOverrideObjectTE = func.mObjectTE;
+ }
+
+ return func.mMaterial.notNull();
+}
+
+
+void LLMaterialEditor::loadAsset()
+{
+ const LLInventoryItem* item;
+ if (mNotecardInventoryID.notNull())
+ {
+ item = mAuxItem.get();
+ }
+ else
+ {
+ item = getItem();
+ }
+
+ bool fail = false;
+
+ if (item)
+ {
+ LLPermissions perm(item->getPermissions());
+ bool allow_copy = gAgent.allowOperation(PERM_COPY, perm, GP_OBJECT_MANIPULATE);
+ bool allow_modify = canModify(mObjectUUID, item);
+ bool source_library = mObjectUUID.isNull() && gInventory.isObjectDescendentOf(mItemUUID, gInventory.getLibraryRootFolderID());
+
+ setCanSaveAs(allow_copy);
+ setMaterialName(item->getName());
+
+ {
+ mAssetID = item->getAssetUUID();
+
+ if (mAssetID.isNull())
+ {
+ mAssetStatus = PREVIEW_ASSET_LOADED;
+ loadDefaults();
+ resetUnsavedChanges();
+ setEnableEditing(allow_modify && !source_library);
+ }
+ else
+ {
+ LLHost source_sim = LLHost();
+ LLSD* user_data = new LLSD();
+
+ if (mNotecardInventoryID.notNull())
+ {
+ user_data->with("objectid", mNotecardObjectID).with("notecardid", mNotecardInventoryID);
+ }
+ else if (mObjectUUID.notNull())
+ {
+ LLViewerObject* objectp = gObjectList.findObject(mObjectUUID);
+ if (objectp && objectp->getRegion())
+ {
+ source_sim = objectp->getRegion()->getHost();
+ }
+ else
+ {
+ // The object that we're trying to look at disappeared, bail.
+ LL_WARNS("MaterialEditor") << "Can't find object " << mObjectUUID << " associated with material." << LL_ENDL;
+ mAssetID.setNull();
+ mAssetStatus = PREVIEW_ASSET_LOADED;
+ resetUnsavedChanges();
+ setEnableEditing(allow_modify && !source_library);
+ return;
+ }
+ user_data->with("taskid", mObjectUUID).with("itemid", mItemUUID);
+ }
+ else
+ {
+ user_data = new LLSD(mItemUUID);
+ }
+
+ setEnableEditing(false); // wait for it to load
+
+ mAssetStatus = PREVIEW_ASSET_LOADING;
+
+ // May callback immediately
+ gAssetStorage->getAssetData(item->getAssetUUID(),
+ LLAssetType::AT_MATERIAL,
+ &onLoadComplete,
+ (void*)user_data,
+ TRUE);
+ }
+ }
+ }
+ else if (mObjectUUID.notNull() && mItemUUID.notNull())
+ {
+ LLViewerObject* objectp = gObjectList.findObject(mObjectUUID);
+ if (objectp && (objectp->isInventoryPending() || objectp->isInventoryDirty()))
+ {
+ // It's a material in object's inventory and we failed to get it because inventory is not up to date.
+ // Subscribe for callback and retry at inventoryChanged()
+ registerVOInventoryListener(objectp, NULL); //removes previous listener
+
+ if (objectp->isInventoryDirty())
+ {
+ objectp->requestInventory();
+ }
+ }
+ else
+ {
+ fail = true;
+ }
+ }
+ else
+ {
+ fail = true;
+ }
+
+ if (fail)
+ {
+ /*editor->setText(LLStringUtil::null);
+ editor->makePristine();
+ editor->setEnabled(TRUE);*/
+ // Don't set asset status here; we may not have set the item id yet
+ // (e.g. when this gets called initially)
+ //mAssetStatus = PREVIEW_ASSET_LOADED;
+ }
+}
+
+// static
+void LLMaterialEditor::onLoadComplete(const LLUUID& asset_uuid,
+ LLAssetType::EType type,
+ void* user_data, S32 status, LLExtStat ext_status)
+{
+ LLSD* floater_key = (LLSD*)user_data;
+ LL_DEBUGS("MaterialEditor") << "loading " << asset_uuid << " for " << *floater_key << LL_ENDL;
+ LLMaterialEditor* editor = LLFloaterReg::findTypedInstance<LLMaterialEditor>("material_editor", *floater_key);
+ if (editor)
+ {
+ if (asset_uuid != editor->mAssetID)
+ {
+ LL_WARNS("MaterialEditor") << "Asset id mismatch, expected: " << editor->mAssetID << " got: " << asset_uuid << LL_ENDL;
+ }
+ if (0 == status)
+ {
+ LLFileSystem file(asset_uuid, type, LLFileSystem::READ);
+
+ S32 file_length = file.getSize();
+
+ std::vector<char> buffer(file_length + 1);
+ file.read((U8*)&buffer[0], file_length);
+
+ editor->decodeAsset(buffer);
+
+ BOOL allow_modify = editor->canModify(editor->mObjectUUID, editor->getItem());
+ BOOL source_library = editor->mObjectUUID.isNull() && gInventory.isObjectDescendentOf(editor->mItemUUID, gInventory.getLibraryRootFolderID());
+ editor->setEnableEditing(allow_modify && !source_library);
+ editor->resetUnsavedChanges();
+ editor->mAssetStatus = PREVIEW_ASSET_LOADED;
+ editor->setEnabled(true); // ready for use
+ }
+ else
+ {
+ if (LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status ||
+ LL_ERR_FILE_EMPTY == status)
+ {
+ LLNotificationsUtil::add("MaterialMissing");
+ }
+ else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status)
+ {
+ // Not supposed to happen?
+ LL_WARNS("MaterialEditor") << "No permission to view material " << asset_uuid << LL_ENDL;
+ LLNotificationsUtil::add("MaterialNoPermissions");
+ }
+ else
+ {
+ LLNotificationsUtil::add("UnableToLoadMaterial");
+ }
+ editor->setEnableEditing(false);
+
+ LL_WARNS("MaterialEditor") << "Problem loading material: " << status << LL_ENDL;
+ editor->mAssetStatus = PREVIEW_ASSET_ERROR;
+ }
+ }
+ else
+ {
+ LL_DEBUGS("MaterialEditor") << "Floater " << *floater_key << " does not exist." << LL_ENDL;
+ }
+ delete floater_key;
+}
+
+void LLMaterialEditor::inventoryChanged(LLViewerObject* object,
+ LLInventoryObject::object_list_t* inventory,
+ S32 serial_num,
+ void* user_data)
+{
+ removeVOInventoryListener();
+ loadAsset();
+}
+
+
+void LLMaterialEditor::saveTexture(LLImageJ2C* img, const std::string& name, const LLUUID& asset_id, upload_callback_f cb)
+{
+ if (asset_id.isNull()
+ || img == nullptr
+ || img->getDataSize() == 0)
+ {
+ return;
+ }
+
+ // copy image bytes into string
+ std::string buffer;
+ buffer.assign((const char*) img->getData(), img->getDataSize());
+
+ U32 expected_upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost();
+
+ LLSD key = getKey();
+ std::function<bool(LLUUID itemId, LLSD response, std::string reason)> failed_upload([key](LLUUID assetId, LLSD response, std::string reason)
+ {
+ LLMaterialEditor* me = LLFloaterReg::findTypedInstance<LLMaterialEditor>("material_editor", key);
+ if (me)
+ {
+ me->setFailedToUploadTexture();
+ }
+ return true; // handled
+ });
+
+ LLResourceUploadInfo::ptr_t uploadInfo(std::make_shared<LLNewBufferedResourceUploadInfo>(
+ buffer,
+ asset_id,
+ name,
+ name,
+ 0,
+ LLFolderType::FT_TEXTURE,
+ LLInventoryType::IT_TEXTURE,
+ LLAssetType::AT_TEXTURE,
+ LLFloaterPerms::getNextOwnerPerms("Uploads"),
+ LLFloaterPerms::getGroupPerms("Uploads"),
+ LLFloaterPerms::getEveryonePerms("Uploads"),
+ expected_upload_cost,
+ false,
+ cb,
+ failed_upload));
+
+ upload_new_resource(uploadInfo);
+}
+
+void LLMaterialEditor::setFailedToUploadTexture()
+{
+ mUploadingTexturesFailure = true;
+ mUploadingTexturesCount--;
+ if (mUploadingTexturesCount == 0)
+ {
+ setEnabled(true);
+ }
+}
+
+S32 LLMaterialEditor::saveTextures()
+{
+ mUploadingTexturesFailure = false; // not supposed to get here if already uploading
+
+ S32 work_count = 0;
+ LLSD key = getKey(); // must be locally declared for lambda's capture to work
+ if (mBaseColorTextureUploadId == getBaseColorId() && mBaseColorTextureUploadId.notNull())
+ {
+ mUploadingTexturesCount++;
+ work_count++;
+ saveTexture(mBaseColorJ2C, mBaseColorName, mBaseColorTextureUploadId, [key](LLUUID newAssetId, LLSD response)
+ {
+ LLMaterialEditor* me = LLFloaterReg::findTypedInstance<LLMaterialEditor>("material_editor", key);
+ if (me)
+ {
+ if (response["success"].asBoolean())
+ {
+ me->setBaseColorId(newAssetId);
+
+ // discard upload buffers once texture have been saved
+ me->mBaseColorJ2C = nullptr;
+ me->mBaseColorFetched = nullptr;
+ me->mBaseColorTextureUploadId.setNull();
+
+ me->mUploadingTexturesCount--;
+
+ if (!me->mUploadingTexturesFailure)
+ {
+ // try saving
+ me->saveIfNeeded();
+ }
+ else if (me->mUploadingTexturesCount == 0)
+ {
+ me->setEnabled(true);
+ }
+ }
+ else
+ {
+ // stop upload if possible, unblock and let user decide
+ me->setFailedToUploadTexture();
+ }
+ }
+ });
+ }
+ if (mNormalTextureUploadId == getNormalId() && mNormalTextureUploadId.notNull())
+ {
+ mUploadingTexturesCount++;
+ work_count++;
+ saveTexture(mNormalJ2C, mNormalName, mNormalTextureUploadId, [key](LLUUID newAssetId, LLSD response)
+ {
+ LLMaterialEditor* me = LLFloaterReg::findTypedInstance<LLMaterialEditor>("material_editor", key);
+ if (me)
+ {
+ if (response["success"].asBoolean())
+ {
+ me->setNormalId(newAssetId);
+
+ // discard upload buffers once texture have been saved
+ me->mNormalJ2C = nullptr;
+ me->mNormalFetched = nullptr;
+ me->mNormalTextureUploadId.setNull();
+
+ me->mUploadingTexturesCount--;
+
+ if (!me->mUploadingTexturesFailure)
+ {
+ // try saving
+ me->saveIfNeeded();
+ }
+ else if (me->mUploadingTexturesCount == 0)
+ {
+ me->setEnabled(true);
+ }
+ }
+ else
+ {
+ // stop upload if possible, unblock and let user decide
+ me->setFailedToUploadTexture();
+ }
+ }
+ });
+ }
+ if (mMetallicTextureUploadId == getMetallicRoughnessId() && mMetallicTextureUploadId.notNull())
+ {
+ mUploadingTexturesCount++;
+ work_count++;
+ saveTexture(mMetallicRoughnessJ2C, mMetallicRoughnessName, mMetallicTextureUploadId, [key](LLUUID newAssetId, LLSD response)
+ {
+ LLMaterialEditor* me = LLFloaterReg::findTypedInstance<LLMaterialEditor>("material_editor", key);
+ if (me)
+ {
+ if (response["success"].asBoolean())
+ {
+ me->setMetallicRoughnessId(newAssetId);
+
+ // discard upload buffers once texture have been saved
+ me->mMetallicRoughnessJ2C = nullptr;
+ me->mMetallicRoughnessFetched = nullptr;
+ me->mMetallicTextureUploadId.setNull();
+
+ me->mUploadingTexturesCount--;
+
+ if (!me->mUploadingTexturesFailure)
+ {
+ // try saving
+ me->saveIfNeeded();
+ }
+ else if (me->mUploadingTexturesCount == 0)
+ {
+ me->setEnabled(true);
+ }
+ }
+ else
+ {
+ // stop upload if possible, unblock and let user decide
+ me->setFailedToUploadTexture();
+ }
+ }
+ });
+ }
+
+ if (mEmissiveTextureUploadId == getEmissiveId() && mEmissiveTextureUploadId.notNull())
+ {
+ mUploadingTexturesCount++;
+ work_count++;
+ saveTexture(mEmissiveJ2C, mEmissiveName, mEmissiveTextureUploadId, [key](LLUUID newAssetId, LLSD response)
+ {
+ LLMaterialEditor* me = LLFloaterReg::findTypedInstance<LLMaterialEditor>("material_editor", LLSD(key));
+ if (me)
+ {
+ if (response["success"].asBoolean())
+ {
+ me->setEmissiveId(newAssetId);
+
+ // discard upload buffers once texture have been saved
+ me->mEmissiveJ2C = nullptr;
+ me->mEmissiveFetched = nullptr;
+ me->mEmissiveTextureUploadId.setNull();
+
+ me->mUploadingTexturesCount--;
+
+ if (!me->mUploadingTexturesFailure)
+ {
+ // try saving
+ me->saveIfNeeded();
+ }
+ else if (me->mUploadingTexturesCount == 0)
+ {
+ me->setEnabled(true);
+ }
+ }
+ else
+ {
+ // stop upload if possible, unblock and let user decide
+ me->setFailedToUploadTexture();
+ }
+ }
+ });
+ }
+
+ if (!work_count)
+ {
+ // Discard upload buffers once textures have been confirmed as saved.
+ // Otherwise we keep buffers for potential upload failure recovery.
+ clearTextures();
+ }
+
+ // asset storage can callback immediately, causing a decrease
+ // of mUploadingTexturesCount, report amount of work scheduled
+ // not amount of work remaining
+ return work_count;
+}
+
+void LLMaterialEditor::clearTextures()
+{
+ mBaseColorJ2C = nullptr;
+ mNormalJ2C = nullptr;
+ mEmissiveJ2C = nullptr;
+ mMetallicRoughnessJ2C = nullptr;
+
+ mBaseColorFetched = nullptr;
+ mNormalFetched = nullptr;
+ mMetallicRoughnessFetched = nullptr;
+ mEmissiveFetched = nullptr;
+
+ mBaseColorTextureUploadId.setNull();
+ mNormalTextureUploadId.setNull();
+ mMetallicTextureUploadId.setNull();
+ mEmissiveTextureUploadId.setNull();
+}
+
+void LLMaterialEditor::loadDefaults()
+{
+ tinygltf::Model model_in;
+ model_in.materials.resize(1);
+ setFromGltfModel(model_in, 0, true);
+}
+
+bool LLMaterialEditor::capabilitiesAvailable()
+{
+ const LLViewerRegion* region = gAgent.getRegion();
+ if (!region)
+ {
+ LL_WARNS("MaterialEditor") << "Not connected to a region, cannot save material." << LL_ENDL;
+ return false;
+ }
+ std::string agent_url = region->getCapability("UpdateMaterialAgentInventory");
+ std::string task_url = region->getCapability("UpdateMaterialTaskInventory");
+
+ return (!agent_url.empty() && !task_url.empty());
+}
+
diff --git a/indra/newview/llmaterialeditor.h b/indra/newview/llmaterialeditor.h
new file mode 100644
index 0000000000..74c776031e
--- /dev/null
+++ b/indra/newview/llmaterialeditor.h
@@ -0,0 +1,312 @@
+/**
+ * @file llmaterialeditor.h
+ * @brief LLMaterialEditor class header file
+ *
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, 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$
+ */
+
+#pragma once
+
+#include "llpreview.h"
+#include "llvoinventorylistener.h"
+#include "llimagej2c.h"
+#include "llviewertexture.h"
+
+class LLButton;
+class LLColorSwatchCtrl;
+class LLComboBox;
+class LLGLTFMaterial;
+class LLLocalGLTFMaterial;
+class LLTextureCtrl;
+class LLTextBox;
+
+namespace tinygltf
+{
+ class Model;
+}
+
+// todo: Consider making into a notification or just merging with
+// presets. Layout is identical to camera/graphics presets so there
+// is no point in having multiple separate xmls and classes.
+class LLFloaterComboOptions : public LLFloater
+{
+public:
+ typedef std::function<void(const std::string&, S32)> combo_callback;
+ LLFloaterComboOptions();
+
+ virtual ~LLFloaterComboOptions();
+ /*virtual*/ BOOL postBuild();
+
+ static LLFloaterComboOptions* showUI(
+ combo_callback callback,
+ const std::string &title,
+ const std::string &description,
+ const std::list<std::string> &options);
+
+ static LLFloaterComboOptions* showUI(
+ combo_callback callback,
+ const std::string &title,
+ const std::string &description,
+ const std::string &ok_text,
+ const std::string &cancel_text,
+ const std::list<std::string> &options);
+
+private:
+ void onConfirm();
+ void onCancel();
+
+protected:
+ combo_callback mCallback;
+
+ LLButton *mConfirmButton;
+ LLButton *mCancelButton;
+ LLComboBox *mComboOptions;
+ LLTextBox *mComboText;
+};
+
+class LLMaterialEditor : public LLPreview, public LLVOInventoryListener
+{
+public:
+ LLMaterialEditor(const LLSD& key);
+
+ bool setFromGltfModel(const tinygltf::Model& model, S32 index, bool set_textures = false);
+
+ void setFromGltfMetaData(const std::string& filename, const tinygltf::Model& model, S32 index);
+
+ // open a file dialog and select a gltf/glb file for import
+ static void importMaterial();
+
+ // for live preview, apply current material to currently selected object
+ void applyToSelection();
+
+ void getGLTFMaterial(LLGLTFMaterial* mat);
+
+ void loadAsset() override;
+ // @index if -1 and file contains more than one material,
+ // will promt to select specific one
+ static void uploadMaterialFromFile(const std::string& filename, S32 index);
+ static void loadMaterialFromFile(const std::string& filename, S32 index = -1);
+
+ void onSelectionChanged(); // live overrides selection changes
+
+ static void updateLive();
+ static void updateLive(const LLUUID &object_id, S32 te);
+ static void loadLive();
+
+ static void saveObjectsMaterialAs();
+ static void savePickedMaterialAs();
+ static void onSaveObjectsMaterialAsMsgCallback(const LLSD& notification, const LLSD& response);
+
+ static void onLoadComplete(const LLUUID& asset_uuid, LLAssetType::EType type, void* user_data, S32 status, LLExtStat ext_status);
+
+ void inventoryChanged(LLViewerObject* object, LLInventoryObject::object_list_t* inventory, S32 serial_num, void* user_data) override;
+
+ typedef std::function<void(LLUUID newAssetId, LLSD response)> upload_callback_f;
+ void saveTexture(LLImageJ2C* img, const std::string& name, const LLUUID& asset_id, upload_callback_f cb);
+ void setFailedToUploadTexture();
+
+ // save textures to inventory if needed
+ // returns amount of scheduled uploads
+ S32 saveTextures();
+ void clearTextures();
+
+ void onClickSave();
+
+ // get a dump of the json representation of the current state of the editor UI in GLTF format
+ std::string getGLTFJson(bool prettyprint = true);
+
+ void getGLBData(std::vector<U8>& data);
+
+ void getGLTFModel(tinygltf::Model& model);
+
+ std::string getEncodedAsset();
+
+ bool decodeAsset(const std::vector<char>& buffer);
+
+ bool saveIfNeeded();
+
+ static void finishInventoryUpload(LLUUID itemId, LLUUID newAssetId, LLUUID newItemId);
+
+ static void finishTaskUpload(LLUUID itemId, LLUUID newAssetId, LLUUID taskId);
+
+ static void finishSaveAs(
+ const LLSD &oldKey,
+ const LLUUID &newItemId,
+ const std::string &buffer,
+ bool has_unsaved_changes);
+
+ void refreshFromInventory(const LLUUID& new_item_id = LLUUID::null);
+
+ void onClickSaveAs();
+ void onSaveAsMsgCallback(const LLSD& notification, const LLSD& response);
+ void onClickCancel();
+ void onCancelMsgCallback(const LLSD& notification, const LLSD& response);
+
+ // llpreview
+ void setObjectID(const LLUUID& object_id) override;
+ void setAuxItem(const LLInventoryItem* item) override;
+
+ // llpanel
+ BOOL postBuild() override;
+ void onClickCloseBtn(bool app_quitting = false) override;
+
+ void onClose(bool app_quitting) override;
+ void draw() override;
+ void handleReshape(const LLRect& new_rect, bool by_user = false) override;
+
+ LLUUID getBaseColorId();
+ void setBaseColorId(const LLUUID& id);
+ void setBaseColorUploadId(const LLUUID& id);
+
+ LLColor4 getBaseColor();
+
+ // sets both base color and transparency
+ void setBaseColor(const LLColor4& color);
+
+ F32 getTransparency();
+ void setTransparency(F32 transparency);
+
+ std::string getAlphaMode();
+ void setAlphaMode(const std::string& alpha_mode);
+
+ F32 getAlphaCutoff();
+ void setAlphaCutoff(F32 alpha_cutoff);
+
+ void setMaterialName(const std::string &name);
+
+ LLUUID getMetallicRoughnessId();
+ void setMetallicRoughnessId(const LLUUID& id);
+ void setMetallicRoughnessUploadId(const LLUUID& id);
+
+ F32 getMetalnessFactor();
+ void setMetalnessFactor(F32 factor);
+
+ F32 getRoughnessFactor();
+ void setRoughnessFactor(F32 factor);
+
+ LLUUID getEmissiveId();
+ void setEmissiveId(const LLUUID& id);
+ void setEmissiveUploadId(const LLUUID& id);
+
+ LLColor4 getEmissiveColor();
+ void setEmissiveColor(const LLColor4& color);
+
+ LLUUID getNormalId();
+ void setNormalId(const LLUUID& id);
+ void setNormalUploadId(const LLUUID& id);
+
+ bool getDoubleSided();
+ void setDoubleSided(bool double_sided);
+
+ void setCanSaveAs(bool value);
+ void setCanSave(bool value);
+ void setEnableEditing(bool can_modify);
+
+ void onCommitTexture(LLUICtrl* ctrl, const LLSD& data, S32 dirty_flag);
+ void onCancelCtrl(LLUICtrl* ctrl, const LLSD& data, S32 dirty_flag);
+ void onSelectCtrl(LLUICtrl* ctrl, const LLSD& data, S32 dirty_flag);
+
+ // initialize the UI from a default GLTF material
+ void loadDefaults();
+
+ U32 getUnsavedChangesFlags() { return mUnsavedChanges; }
+ U32 getRevertedChangesFlags() { return mRevertedChanges; }
+
+ static bool capabilitiesAvailable();
+
+private:
+ static void saveMaterialAs(const LLGLTFMaterial *render_material, const LLLocalGLTFMaterial *local_material);
+
+ static bool updateInventoryItem(const std::string &buffer, const LLUUID &item_id, const LLUUID &task_id);
+ static void createInventoryItem(const std::string &buffer, const std::string &name, const std::string &desc);
+
+ void setFromGLTFMaterial(LLGLTFMaterial* mat);
+ bool setFromSelection();
+
+ void loadMaterial(const tinygltf::Model &model, const std::string &filename_lc, S32 index, bool open_floater = true);
+
+ friend class LLMaterialFilePicker;
+
+ LLUUID mAssetID;
+
+ LLTextureCtrl* mBaseColorTextureCtrl;
+ LLTextureCtrl* mMetallicTextureCtrl;
+ LLTextureCtrl* mEmissiveTextureCtrl;
+ LLTextureCtrl* mNormalTextureCtrl;
+ LLColorSwatchCtrl* mBaseColorCtrl;
+ LLColorSwatchCtrl* mEmissiveColorCtrl;
+
+ // 'Default' texture, unless it's null or from inventory is the one with the fee
+ LLUUID mBaseColorTextureUploadId;
+ LLUUID mMetallicTextureUploadId;
+ LLUUID mEmissiveTextureUploadId;
+ LLUUID mNormalTextureUploadId;
+
+ // last known name of each texture
+ std::string mBaseColorName;
+ std::string mNormalName;
+ std::string mMetallicRoughnessName;
+ std::string mEmissiveName;
+
+ // keep pointers to fetched textures or viewer will remove them
+ // if user temporary selects something else with 'apply now'
+ LLPointer<LLViewerFetchedTexture> mBaseColorFetched;
+ LLPointer<LLViewerFetchedTexture> mNormalFetched;
+ LLPointer<LLViewerFetchedTexture> mMetallicRoughnessFetched;
+ LLPointer<LLViewerFetchedTexture> mEmissiveFetched;
+
+ // J2C versions of packed buffers for uploading
+ LLPointer<LLImageJ2C> mBaseColorJ2C;
+ LLPointer<LLImageJ2C> mNormalJ2C;
+ LLPointer<LLImageJ2C> mMetallicRoughnessJ2C;
+ LLPointer<LLImageJ2C> mEmissiveJ2C;
+
+ // utility function for converting image uri into a texture name
+ const std::string getImageNameFromUri(std::string image_uri, const std::string texture_type);
+
+ // utility function for building a description of the imported material
+ // based on what we know about it.
+ const std::string buildMaterialDescription();
+
+ void resetUnsavedChanges();
+ void markChangesUnsaved(U32 dirty_flag);
+
+ U32 mUnsavedChanges; // flags to indicate individual changed parameters
+ U32 mRevertedChanges; // flags to indicate individual reverted parameters
+ S32 mUploadingTexturesCount;
+ S32 mExpectedUploadCost;
+ bool mUploadingTexturesFailure;
+ std::string mMaterialNameShort;
+ std::string mMaterialName;
+
+ // if true, this instance is live instance editing overrides
+ bool mIsOverride = false;
+ bool mHasSelection = false;
+ // local id, texture ids per face for object overrides
+ // for "cancel" support
+ static LLUUID mOverrideObjectId; // static to avoid searching for the floater
+ static S32 mOverrideObjectTE;
+ static bool mOverrideInProgress;
+ static bool mSelectionNeedsUpdate;
+ boost::signals2::connection mSelectionUpdateSlot;
+};
+
diff --git a/indra/newview/llmaterialmgr.cpp b/indra/newview/llmaterialmgr.cpp
index a52f7244f3..3b59b2f05e 100644
--- a/indra/newview/llmaterialmgr.cpp
+++ b/indra/newview/llmaterialmgr.cpp
@@ -133,8 +133,7 @@ LLMaterialMgr::LLMaterialMgr():
mHttpRequest(),
mHttpHeaders(),
mHttpOptions(),
- mHttpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID),
- mHttpPriority(0)
+ mHttpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID)
{
LLAppCoreHttp & app_core_http(LLAppViewer::instance()->getAppCoreHttp());
@@ -693,7 +692,7 @@ void LLMaterialMgr::processGetQueue()
<< "\ndata: " << ll_pretty_print_sd(materialsData) << LL_ENDL;
LLCore::HttpHandle handle = LLCoreHttpUtil::requestPostWithLLSD(mHttpRequest,
- mHttpPolicy, mHttpPriority, capURL,
+ mHttpPolicy, capURL,
postData, mHttpOptions, mHttpHeaders, handler);
if (handle == LLCORE_HTTP_HANDLE_INVALID)
@@ -979,7 +978,7 @@ void LLMaterialMgr::processPutQueue()
));
LLCore::HttpHandle handle = LLCoreHttpUtil::requestPutWithLLSD(
- mHttpRequest, mHttpPolicy, mHttpPriority, capURL,
+ mHttpRequest, mHttpPolicy, capURL,
putData, mHttpOptions, mHttpHeaders, handler);
if (handle == LLCORE_HTTP_HANDLE_INVALID)
diff --git a/indra/newview/llmaterialmgr.h b/indra/newview/llmaterialmgr.h
index 843dc66fbc..f76cc27db1 100644
--- a/indra/newview/llmaterialmgr.h
+++ b/indra/newview/llmaterialmgr.h
@@ -141,7 +141,6 @@ private:
LLCore::HttpHeaders::ptr_t mHttpHeaders;
LLCore::HttpOptions::ptr_t mHttpOptions;
LLCore::HttpRequest::policy_t mHttpPolicy;
- LLCore::HttpRequest::priority_t mHttpPriority;
U32 getMaxEntries(const LLViewerRegion* regionp);
};
diff --git a/indra/newview/llmediadataclient.cpp b/indra/newview/llmediadataclient.cpp
index 9d0f62a30d..d3b981e205 100644
--- a/indra/newview/llmediadataclient.cpp
+++ b/indra/newview/llmediadataclient.cpp
@@ -354,7 +354,7 @@ void LLMediaDataClient::serviceQueue()
// and make the post
LLCore::HttpHandler::ptr_t handler = request->createHandler();
- LLCore::HttpHandle handle = LLCoreHttpUtil::requestPostWithLLSD(mHttpRequest, mHttpPolicy, 0,
+ LLCore::HttpHandle handle = LLCoreHttpUtil::requestPostWithLLSD(mHttpRequest, mHttpPolicy,
url, sd_payload, mHttpOpts, mHttpHeaders, handler);
if (handle == LLCORE_HTTP_HANDLE_INVALID)
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index f937754368..e8411dd573 100644
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -827,8 +827,7 @@ LLMeshRepoThread::LLMeshRepoThread()
mHttpLargeOptions(),
mHttpHeaders(),
mHttpPolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID),
- mHttpLargePolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID),
- mHttpPriority(0)
+ mHttpLargePolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID)
{
LLAppCoreHttp & app_core_http(LLAppViewer::instance()->getAppCoreHttp());
@@ -1286,7 +1285,6 @@ LLCore::HttpHandle LLMeshRepoThread::getByteRange(const std::string & url,
if (len < LARGE_MESH_FETCH_THRESHOLD)
{
handle = mHttpRequest->requestGetByteRange( mHttpPolicyClass,
- mHttpPriority,
url,
(disable_range_req ? size_t(0) : offset),
(disable_range_req ? size_t(0) : len),
@@ -1301,7 +1299,6 @@ LLCore::HttpHandle LLMeshRepoThread::getByteRange(const std::string & url,
else
{
handle = mHttpRequest->requestGetByteRange(mHttpLargePolicyClass,
- mHttpPriority,
url,
(disable_range_req ? size_t(0) : offset),
(disable_range_req ? size_t(0) : len),
@@ -2128,7 +2125,6 @@ LLMeshUploadThread::LLMeshUploadThread(LLMeshUploadThread::instance_list& data,
mHttpHeaders = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders);
mHttpHeaders->append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_LLSD_XML);
mHttpPolicyClass = LLAppViewer::instance()->getAppCoreHttp().getPolicy(LLAppCoreHttp::AP_UPLOADS);
- mHttpPriority = 0;
}
LLMeshUploadThread::~LLMeshUploadThread()
@@ -2647,7 +2643,6 @@ void LLMeshUploadThread::doWholeModelUpload()
LLCore::HttpHandle handle = LLCoreHttpUtil::requestPostWithLLSD(mHttpRequest,
mHttpPolicyClass,
- mHttpPriority,
mWholeModelUploadURL,
body,
mHttpOptions,
@@ -2698,7 +2693,6 @@ void LLMeshUploadThread::requestWholeModelFee()
dump_llsd_to_file(mModelData, make_dump_name("whole_model_fee_request_", dump_num));
LLCore::HttpHandle handle = LLCoreHttpUtil::requestPostWithLLSD(mHttpRequest,
mHttpPolicyClass,
- mHttpPriority,
mWholeModelFeeCapability,
mModelData,
mHttpOptions,
diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h
index e3688ff243..6922367ff7 100644
--- a/indra/newview/llmeshrepository.h
+++ b/indra/newview/llmeshrepository.h
@@ -322,7 +322,6 @@ public:
LLCore::HttpHeaders::ptr_t mHttpHeaders;
LLCore::HttpRequest::policy_t mHttpPolicyClass;
LLCore::HttpRequest::policy_t mHttpLargePolicyClass;
- LLCore::HttpRequest::priority_t mHttpPriority;
typedef std::set<LLCore::HttpHandler::ptr_t> http_request_set;
http_request_set mHttpRequestSet; // Outstanding HTTP requests
@@ -490,7 +489,6 @@ private:
LLCore::HttpOptions::ptr_t mHttpOptions;
LLCore::HttpHeaders::ptr_t mHttpHeaders;
LLCore::HttpRequest::policy_t mHttpPolicyClass;
- LLCore::HttpRequest::priority_t mHttpPriority;
};
// Params related to streaming cost, render cost, and scene complexity tracking.
diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp
index e1a5b22490..56a48cb74d 100644
--- a/indra/newview/llmodelpreview.cpp
+++ b/indra/newview/llmodelpreview.cpp
@@ -30,6 +30,7 @@
#include "llmodelloader.h"
#include "lldaeloader.h"
+#include "llgltfloader.h"
#include "llfloatermodelpreview.h"
#include "llagent.h"
@@ -747,20 +748,41 @@ void LLModelPreview::loadModel(std::string filename, S32 lod, bool force_disable
std::map<std::string, std::string> joint_alias_map;
getJointAliases(joint_alias_map);
- mModelLoader = new LLDAELoader(
- filename,
- lod,
- &LLModelPreview::loadedCallback,
- &LLModelPreview::lookupJointByName,
- &LLModelPreview::loadTextures,
- &LLModelPreview::stateChangedCallback,
- this,
- mJointTransformMap,
- mJointsFromNode,
- joint_alias_map,
- LLSkinningUtil::getMaxJointCount(),
- gSavedSettings.getU32("ImporterModelLimit"),
- gSavedSettings.getBOOL("ImporterPreprocessDAE"));
+ // three possible file extensions, .dae .gltf .glb
+ // check for .dae and if not then assume one of the .gl??
+ if (std::string::npos != filename.rfind(".dae"))
+ {
+ mModelLoader = new LLDAELoader(
+ filename,
+ lod,
+ &LLModelPreview::loadedCallback,
+ &LLModelPreview::lookupJointByName,
+ &LLModelPreview::loadTextures,
+ &LLModelPreview::stateChangedCallback,
+ this,
+ mJointTransformMap,
+ mJointsFromNode,
+ joint_alias_map,
+ LLSkinningUtil::getMaxJointCount(),
+ gSavedSettings.getU32("ImporterModelLimit"),
+ gSavedSettings.getBOOL("ImporterPreprocessDAE"));
+ }
+ else
+ {
+ mModelLoader = new LLGLTFLoader(
+ filename,
+ lod,
+ &LLModelPreview::loadedCallback,
+ &LLModelPreview::lookupJointByName,
+ &LLModelPreview::loadTextures,
+ &LLModelPreview::stateChangedCallback,
+ this,
+ mJointTransformMap,
+ mJointsFromNode,
+ joint_alias_map,
+ LLSkinningUtil::getMaxJointCount(),
+ gSavedSettings.getU32("ImporterModelLimit"));
+ }
if (force_disable_slm)
{
@@ -1307,7 +1329,7 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe
// extra space for normals and text coords
S32 tc_bytes_size = ((size_vertices * sizeof(LLVector2)) + 0xF) & ~0xF;
- LLVector4a* combined_positions = (LLVector4a*)ll_aligned_malloc<64>(sizeof(LLVector4a) * 2 * size_vertices + tc_bytes_size);
+ LLVector4a* combined_positions = (LLVector4a*)ll_aligned_malloc<64>(sizeof(LLVector4a) * 3 * size_vertices + tc_bytes_size);
LLVector4a* combined_normals = combined_positions + size_vertices;
LLVector2* combined_tex_coords = (LLVector2*)(combined_normals + size_vertices);
@@ -1427,7 +1449,7 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe
// IV. Repack back into individual faces
- LLVector4a* buffer_positions = (LLVector4a*)ll_aligned_malloc<64>(sizeof(LLVector4a) * 2 * size_vertices + tc_bytes_size);
+ LLVector4a* buffer_positions = (LLVector4a*)ll_aligned_malloc<64>(sizeof(LLVector4a) * 3 * size_vertices + tc_bytes_size);
LLVector4a* buffer_normals = buffer_positions + size_vertices;
LLVector2* buffer_tex_coords = (LLVector2*)(buffer_normals + size_vertices);
S32 buffer_idx_size = (size_indices * sizeof(U16) + 0xF) & ~0xF;
@@ -1548,7 +1570,7 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe
{
new_face.resizeIndices(buf_indices_copied);
new_face.resizeVertices(buf_positions_copied);
-
+ new_face.allocateTangents(buf_positions_copied);
S32 idx_size = (buf_indices_copied * sizeof(U16) + 0xF) & ~0xF;
LLVector4a::memcpyNonAliased16((F32*)new_face.mIndices, (F32*)buffer_indices, idx_size);
@@ -1832,6 +1854,14 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d
LLModel* target_model = mModel[lod][mdl_idx];
+ // carry over normalized transform into simplified model
+ for (int i = 0; i < base->getNumVolumeFaces(); ++i)
+ {
+ LLVolumeFace& src = base->getVolumeFace(i);
+ LLVolumeFace& dst = target_model->getVolumeFace(i);
+ dst.mNormalizedScale = src.mNormalizedScale;
+ }
+
S32 model_meshopt_mode = meshopt_mode;
// Ideally this should run not per model,
@@ -2742,9 +2772,9 @@ void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights)
mask |= LLVertexBuffer::MAP_WEIGHT4;
}
- vb = new LLVertexBuffer(mask, 0);
+ vb = new LLVertexBuffer(mask);
- if (!vb->allocateBuffer(num_vertices, num_indices, TRUE))
+ if (!vb->allocateBuffer(num_vertices, num_indices))
{
// We are likely to crash due this failure, if this happens, find a way to gracefully stop preview
std::ostringstream out;
@@ -2815,7 +2845,7 @@ void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights)
*(index_strider++) = vf.mIndices[i];
}
- vb->flush();
+ vb->unmapBuffer();
mVertexBuffer[lod][mdl].push_back(vb);
@@ -3009,11 +3039,11 @@ void LLModelPreview::addEmptyFace(LLModel* pTarget)
{
U32 type_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0;
- LLPointer<LLVertexBuffer> buff = new LLVertexBuffer(type_mask, 0);
+ LLPointer<LLVertexBuffer> buff = new LLVertexBuffer(type_mask);
- buff->allocateBuffer(1, 3, true);
+ buff->allocateBuffer(1, 3);
memset((U8*)buff->getMappedData(), 0, buff->getSize());
- memset((U8*)buff->getIndicesPointer(), 0, buff->getIndicesSize());
+ memset((U8*)buff->getMappedIndices(), 0, buff->getIndicesSize());
buff->validateRange(0, buff->getNumVerts() - 1, buff->getNumIndices(), 0);
@@ -3068,8 +3098,7 @@ BOOL LLModelPreview::render()
LLGLDisable no_blend(GL_BLEND);
LLGLEnable cull(GL_CULL_FACE);
LLGLDepthTest depth(GL_FALSE); // SL-12781 disable z-buffer to render background color
- LLGLDisable fog(GL_FOG);
-
+
{
gUIProgram.bind();
@@ -3270,8 +3299,6 @@ BOOL LLModelPreview::render()
gGL.pushMatrix();
gGL.color4fv(PREVIEW_EDGE_COL.mV);
- const U32 type_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0;
-
LLGLEnable normalize(GL_NORMALIZE);
if (!mBaseModel.empty() && mVertexBuffer[5].empty())
@@ -3334,7 +3361,7 @@ BOOL LLModelPreview::render()
{
LLVertexBuffer* buffer = mVertexBuffer[mPreviewLOD][model][i];
- buffer->setBuffer(type_mask & buffer->getTypeMask());
+ buffer->setBuffer();
if (textures)
{
@@ -3371,7 +3398,7 @@ BOOL LLModelPreview::render()
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glLineWidth(1.f);
}
- buffer->flush();
+ buffer->unmapBuffer();
}
gGL.popMatrix();
}
@@ -3485,7 +3512,7 @@ BOOL LLModelPreview::render()
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
gGL.diffuseColor4fv(PREVIEW_PSYH_FILL_COL.mV);
- buffer->setBuffer(type_mask & buffer->getTypeMask());
+ buffer->setBuffer();
buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts() - 1, buffer->getNumIndices(), 0);
gGL.diffuseColor4fv(PREVIEW_PSYH_EDGE_COL.mV);
@@ -3496,7 +3523,7 @@ BOOL LLModelPreview::render()
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glLineWidth(1.f);
- buffer->flush();
+ buffer->unmapBuffer();
}
}
}
@@ -3546,7 +3573,7 @@ BOOL LLModelPreview::render()
{
LLVertexBuffer* buffer = mVertexBuffer[LLModel::LOD_PHYSICS][model][v];
- buffer->setBuffer(type_mask & buffer->getTypeMask());
+ buffer->setBuffer();
LLStrider<LLVector3> pos_strider;
buffer->getVertexStrider(pos_strider, 0);
@@ -3568,7 +3595,7 @@ BOOL LLModelPreview::render()
}
}
- buffer->flush();
+ buffer->unmapBuffer();
}
}
}
@@ -3699,7 +3726,7 @@ BOOL LLModelPreview::render()
const std::string& binding = instance.mModel->mMaterialList[i];
const LLImportMaterial& material = instance.mMaterial[binding];
- buffer->setBuffer(type_mask & buffer->getTypeMask());
+ buffer->setBuffer();
gGL.diffuseColor4fv(material.mDiffuseColor.mV);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
diff --git a/indra/newview/lloutfitgallery.cpp b/indra/newview/lloutfitgallery.cpp
index 602b7412a4..92a742466e 100644
--- a/indra/newview/lloutfitgallery.cpp
+++ b/indra/newview/lloutfitgallery.cpp
@@ -1177,7 +1177,7 @@ void LLOutfitGallery::uploadPhoto(LLUUID outfit_id)
{
return;
}
- (new LLFilePickerReplyThread(boost::bind(&LLOutfitGallery::uploadOutfitImage, this, _1, outfit_id), LLFilePicker::FFLOAD_IMAGE, false))->getFile();
+ LLFilePickerReplyThread::startPicker(boost::bind(&LLOutfitGallery::uploadOutfitImage, this, _1, outfit_id), LLFilePicker::FFLOAD_IMAGE, false);
}
void LLOutfitGallery::uploadOutfitImage(const std::vector<std::string>& filenames, LLUUID outfit_id)
@@ -1360,7 +1360,6 @@ void LLOutfitGallery::onSelectPhoto(LLUUID selected_outfit_id)
"SELECT PHOTO",
PERM_NONE,
PERM_NONE,
- PERM_NONE,
FALSE,
NULL);
diff --git a/indra/newview/llpaneleditsky.cpp b/indra/newview/llpaneleditsky.cpp
index a169712bd8..d17845ebc5 100644
--- a/indra/newview/llpaneleditsky.cpp
+++ b/indra/newview/llpaneleditsky.cpp
@@ -108,6 +108,8 @@ namespace
const std::string FIELD_SKY_DENSITY_DROPLET_RADIUS("droplet_radius");
const std::string FIELD_SKY_DENSITY_ICE_LEVEL("ice_level");
+ const std::string FIELD_REFLECTION_PROBE_AMBIANCE("probe_ambiance");
+
const F32 SLIDER_SCALE_SUN_AMBIENT(3.0f);
const F32 SLIDER_SCALE_BLUE_HORIZON_DENSITY(2.0f);
const F32 SLIDER_SCALE_GLOW_R(20.0f);
@@ -150,6 +152,7 @@ BOOL LLPanelSettingsSkyAtmosTab::postBuild()
getChild<LLUICtrl>(FIELD_SKY_DENSITY_MOISTURE_LEVEL)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onMoistureLevelChanged(); });
getChild<LLUICtrl>(FIELD_SKY_DENSITY_DROPLET_RADIUS)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onDropletRadiusChanged(); });
getChild<LLUICtrl>(FIELD_SKY_DENSITY_ICE_LEVEL)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onIceLevelChanged(); });
+ getChild<LLUICtrl>(FIELD_REFLECTION_PROBE_AMBIANCE)->setCommitCallback([this](LLUICtrl*, const LLSD&) { onReflectionProbeAmbianceChanged(); });
refresh();
return TRUE;
@@ -172,6 +175,7 @@ void LLPanelSettingsSkyAtmosTab::setEnabled(BOOL enabled)
getChild<LLUICtrl>(FIELD_SKY_DENSITY_MOISTURE_LEVEL)->setEnabled(enabled);
getChild<LLUICtrl>(FIELD_SKY_DENSITY_DROPLET_RADIUS)->setEnabled(enabled);
getChild<LLUICtrl>(FIELD_SKY_DENSITY_ICE_LEVEL)->setEnabled(enabled);
+ getChild<LLUICtrl>(FIELD_REFLECTION_PROBE_AMBIANCE)->setEnabled(enabled);
}
}
@@ -203,10 +207,12 @@ void LLPanelSettingsSkyAtmosTab::refresh()
F32 moisture_level = mSkySettings->getSkyMoistureLevel();
F32 droplet_radius = mSkySettings->getSkyDropletRadius();
F32 ice_level = mSkySettings->getSkyIceLevel();
+ F32 rp_ambiance = mSkySettings->getReflectionProbeAmbiance();
getChild<LLUICtrl>(FIELD_SKY_DENSITY_MOISTURE_LEVEL)->setValue(moisture_level);
getChild<LLUICtrl>(FIELD_SKY_DENSITY_DROPLET_RADIUS)->setValue(droplet_radius);
getChild<LLUICtrl>(FIELD_SKY_DENSITY_ICE_LEVEL)->setValue(ice_level);
+ getChild<LLUICtrl>(FIELD_REFLECTION_PROBE_AMBIANCE)->setValue(rp_ambiance);
}
//-------------------------------------------------------------------------
@@ -311,6 +317,15 @@ void LLPanelSettingsSkyAtmosTab::onIceLevelChanged()
setIsDirty();
}
+void LLPanelSettingsSkyAtmosTab::onReflectionProbeAmbianceChanged()
+{
+ if (!mSkySettings) return;
+ F32 ambiance = getChild<LLUICtrl>(FIELD_REFLECTION_PROBE_AMBIANCE)->getValue().asReal();
+ mSkySettings->setReflectionProbeAmbiance(ambiance);
+ mSkySettings->update();
+ setIsDirty();
+}
+
//==========================================================================
LLPanelSettingsSkyCloudTab::LLPanelSettingsSkyCloudTab() :
LLPanelSettingsSky()
diff --git a/indra/newview/llpaneleditsky.h b/indra/newview/llpaneleditsky.h
index cb63d40b0c..cd89e02eea 100644
--- a/indra/newview/llpaneleditsky.h
+++ b/indra/newview/llpaneleditsky.h
@@ -79,6 +79,7 @@ private:
void onMoistureLevelChanged();
void onDropletRadiusChanged();
void onIceLevelChanged();
+ void onReflectionProbeAmbianceChanged();
};
diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp
index 0103bf628a..5c209bc4c6 100644
--- a/indra/newview/llpaneleditwearable.cpp
+++ b/indra/newview/llpaneleditwearable.cpp
@@ -574,7 +574,6 @@ static void init_texture_ctrl(LLPanelEditWearable* self, LLPanel* panel, const L
// Don't allow (no copy) or (notransfer) textures to be selected.
texture_ctrl->setImmediateFilterPermMask(PERM_NONE);
texture_ctrl->setDnDFilterPermMask(PERM_NONE);
- texture_ctrl->setNonImmediateFilterPermMask(PERM_NONE);
}
}
diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp
index 178aba11a3..cb09ec9fbf 100644
--- a/indra/newview/llpanelface.cpp
+++ b/indra/newview/llpanelface.cpp
@@ -32,7 +32,6 @@
// library includes
#include "llcalc.h"
#include "llerror.h"
-#include "llfocusmgr.h"
#include "llrect.h"
#include "llstring.h"
#include "llfontgl.h"
@@ -46,6 +45,7 @@
#include "llcombobox.h"
#include "lldrawpoolbump.h"
#include "llface.h"
+#include "llgltfmateriallist.h"
#include "llinventoryfunctions.h"
#include "llinventorymodel.h" // gInventory
#include "llinventorymodelbackgroundfetch.h"
@@ -53,6 +53,7 @@
#include "llfloaterreg.h"
#include "lllineeditor.h"
#include "llmaterialmgr.h"
+#include "llmaterialeditor.h"
#include "llmediactrl.h"
#include "llmediaentry.h"
#include "llmenubutton.h"
@@ -80,18 +81,107 @@
#include "llpluginclassmedia.h"
#include "llviewertexturelist.h"// Update sel manager as to which channel we're editing so it can reflect the correct overlay UI
+
+
+#include "llagent.h"
+#include "llfilesystem.h"
+#include "llviewerassetupload.h"
+#include "llviewermenufile.h"
+#include "llsd.h"
+#include "llsdutil.h"
+#include "llsdserialize.h"
+#include "llinventorymodel.h"
+
+using namespace std::literals;
+
+LLPanelFace::Selection LLPanelFace::sMaterialOverrideSelection;
+
//
// Constant definitions for comboboxes
// Must match the commbobox definitions in panel_tools_texture.xml
//
const S32 MATMEDIA_MATERIAL = 0; // Material
-const S32 MATMEDIA_MEDIA = 1; // Media
+const S32 MATMEDIA_PBR = 1; // PBR
+const S32 MATMEDIA_MEDIA = 2; // Media
const S32 MATTYPE_DIFFUSE = 0; // Diffuse material texture
const S32 MATTYPE_NORMAL = 1; // Normal map
const S32 MATTYPE_SPECULAR = 2; // Specular map
const S32 ALPHAMODE_MASK = 2; // Alpha masking mode
const S32 BUMPY_TEXTURE = 18; // use supplied normal map
const S32 SHINY_TEXTURE = 4; // use supplied specular map
+const S32 PBRTYPE_RENDER_MATERIAL_ID = 0; // Render Material ID
+const S32 PBRTYPE_BASE_COLOR = 1; // PBR Base Color
+const S32 PBRTYPE_NORMAL = 2; // PBR Normal
+const S32 PBRTYPE_METALLIC_ROUGHNESS = 3; // PBR Metallic
+const S32 PBRTYPE_EMISSIVE = 4; // PBR Emissive
+
+LLGLTFMaterial::TextureInfo texture_info_from_pbrtype(S32 pbr_type)
+{
+ switch (pbr_type)
+ {
+ case PBRTYPE_BASE_COLOR:
+ return LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR;
+ break;
+ case PBRTYPE_NORMAL:
+ return LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL;
+ break;
+ case PBRTYPE_METALLIC_ROUGHNESS:
+ return LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS;
+ break;
+ case PBRTYPE_EMISSIVE:
+ return LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE;
+ break;
+ default:
+ return LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT;
+ break;
+ }
+}
+
+void LLPanelFace::updateSelectedGLTFMaterials(std::function<void(LLGLTFMaterial*)> func)
+{
+ struct LLSelectedTEGLTFMaterialFunctor : public LLSelectedTEFunctor
+ {
+ LLSelectedTEGLTFMaterialFunctor(std::function<void(LLGLTFMaterial*)> func) : mFunc(func) {}
+ virtual ~LLSelectedTEGLTFMaterialFunctor() {};
+ bool apply(LLViewerObject* object, S32 face) override
+ {
+ LLGLTFMaterial new_override;
+ const LLTextureEntry* tep = object->getTE(face);
+ if (tep->getGLTFMaterialOverride())
+ {
+ new_override = *tep->getGLTFMaterialOverride();
+ }
+ mFunc(&new_override);
+ LLGLTFMaterialList::queueModify(object, face, &new_override);
+
+ return true;
+ }
+
+ std::function<void(LLGLTFMaterial*)> mFunc;
+ } select_func(func);
+
+ LLSelectMgr::getInstance()->getSelection()->applyToTEs(&select_func);
+}
+
+template<typename T>
+void readSelectedGLTFMaterial(std::function<T(const LLGLTFMaterial*)> func, T& value, bool& identical, bool has_tolerance, T tolerance)
+{
+ struct LLSelectedTEGetGLTFMaterialFunctor : public LLSelectedTEGetFunctor<T>
+ {
+ LLSelectedTEGetGLTFMaterialFunctor(std::function<T(const LLGLTFMaterial*)> func) : mFunc(func) {}
+ virtual ~LLSelectedTEGetGLTFMaterialFunctor() {};
+ T get(LLViewerObject* object, S32 face) override
+ {
+ const LLTextureEntry* tep = object->getTE(face);
+ const LLGLTFMaterial* render_material = tep->getGLTFRenderMaterial();
+
+ return mFunc(render_material);
+ }
+
+ std::function<T(const LLGLTFMaterial*)> mFunc;
+ } select_func(func);
+ identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue(&select_func, value, has_tolerance, tolerance);
+}
BOOST_STATIC_ASSERT(MATTYPE_DIFFUSE == LLRender::DIFFUSE_MAP && MATTYPE_NORMAL == LLRender::NORMAL_MAP && MATTYPE_SPECULAR == LLRender::SPECULAR_MAP);
@@ -103,16 +193,38 @@ std::string USE_TEXTURE;
LLRender::eTexIndex LLPanelFace::getTextureChannelToEdit()
{
- LLRadioGroup* radio_mat_type = getChild<LLRadioGroup>("radio_material_type");
-
- LLRender::eTexIndex channel_to_edit = (mComboMatMedia && mComboMatMedia->getCurrentIndex() == MATMEDIA_MATERIAL) ?
- (radio_mat_type ? (LLRender::eTexIndex)radio_mat_type->getSelectedIndex() : LLRender::DIFFUSE_MAP) : LLRender::DIFFUSE_MAP;
+ LLRender::eTexIndex channel_to_edit = LLRender::DIFFUSE_MAP;
+ if (mComboMatMedia)
+ {
+ U32 matmedia_selection = mComboMatMedia->getCurrentIndex();
+ if (matmedia_selection == MATMEDIA_MATERIAL)
+ {
+ LLRadioGroup* radio_mat_type = getChild<LLRadioGroup>("radio_material_type");
+ channel_to_edit = (LLRender::eTexIndex)radio_mat_type->getSelectedIndex();
+ }
+ if (matmedia_selection == MATMEDIA_PBR)
+ {
+ LLRadioGroup* radio_mat_type = getChild<LLRadioGroup>("radio_pbr_type");
+ channel_to_edit = (LLRender::eTexIndex)radio_mat_type->getSelectedIndex();
+ }
+ }
channel_to_edit = (channel_to_edit == LLRender::NORMAL_MAP) ? (getCurrentNormalMap().isNull() ? LLRender::DIFFUSE_MAP : channel_to_edit) : channel_to_edit;
channel_to_edit = (channel_to_edit == LLRender::SPECULAR_MAP) ? (getCurrentSpecularMap().isNull() ? LLRender::DIFFUSE_MAP : channel_to_edit) : channel_to_edit;
return channel_to_edit;
}
+LLRender::eTexIndex LLPanelFace::getTextureDropChannel()
+{
+ if (mComboMatMedia && mComboMatMedia->getCurrentIndex() == MATMEDIA_MATERIAL)
+ {
+ LLRadioGroup* radio_mat_type = getChild<LLRadioGroup>("radio_material_type");
+ return LLRender::eTexIndex(radio_mat_type->getSelectedIndex());
+ }
+
+ return LLRender::eTexIndex(MATTYPE_DIFFUSE);
+}
+
// Things the UI provides...
//
LLUUID LLPanelFace::getCurrentNormalMap() { return getChild<LLTextureCtrl>("bumpytexture control")->getImageAssetID(); }
@@ -167,8 +279,20 @@ BOOL LLPanelFace::postBuild()
childSetCommitCallback("add_media", &LLPanelFace::onClickBtnAddMedia, this);
childSetCommitCallback("delete_media", &LLPanelFace::onClickBtnDeleteMedia, this);
+ getChild<LLUICtrl>("gltfTextureScaleU")->setCommitCallback(boost::bind(&LLPanelFace::onCommitGLTFTextureScaleU, this, _1), nullptr);
+ getChild<LLUICtrl>("gltfTextureScaleV")->setCommitCallback(boost::bind(&LLPanelFace::onCommitGLTFTextureScaleV, this, _1), nullptr);
+ getChild<LLUICtrl>("gltfTextureRotation")->setCommitCallback(boost::bind(&LLPanelFace::onCommitGLTFRotation, this, _1), nullptr);
+ getChild<LLUICtrl>("gltfTextureOffsetU")->setCommitCallback(boost::bind(&LLPanelFace::onCommitGLTFTextureOffsetU, this, _1), nullptr);
+ getChild<LLUICtrl>("gltfTextureOffsetV")->setCommitCallback(boost::bind(&LLPanelFace::onCommitGLTFTextureOffsetV, this, _1), nullptr);
+
+ LLGLTFMaterialList::addSelectionUpdateCallback(&LLPanelFace::onMaterialOverrideReceived);
+ sMaterialOverrideSelection.connect();
+
childSetAction("button align",&LLPanelFace::onClickAutoFix,this);
childSetAction("button align textures", &LLPanelFace::onAlignTexture, this);
+ childSetAction("pbr_from_inventory", &LLPanelFace::onClickBtnLoadInvPBR, this);
+ childSetAction("edit_selected_pbr", &LLPanelFace::onClickBtnEditPBR, this);
+ childSetAction("save_selected_pbr", &LLPanelFace::onClickBtnSavePBR, this);
LLTextureCtrl* mTextureCtrl;
LLTextureCtrl* mShinyTextureCtrl;
@@ -187,6 +311,26 @@ BOOL LLPanelFace::postBuild()
setMouseOpaque(FALSE);
+ LLTextureCtrl* pbr_ctrl = findChild<LLTextureCtrl>("pbr_control");
+ if (pbr_ctrl)
+ {
+ pbr_ctrl->setDefaultImageAssetID(LLUUID::null);
+ pbr_ctrl->setBlankImageAssetID(LLGLTFMaterialList::BLANK_MATERIAL_ASSET_ID);
+ pbr_ctrl->setCommitCallback(boost::bind(&LLPanelFace::onCommitPbr, this, _2));
+ pbr_ctrl->setOnCancelCallback(boost::bind(&LLPanelFace::onCancelPbr, this, _2));
+ pbr_ctrl->setOnSelectCallback(boost::bind(&LLPanelFace::onSelectPbr, this, _2));
+ pbr_ctrl->setDragCallback(boost::bind(&LLPanelFace::onDragPbr, this, _2));
+ pbr_ctrl->setOnTextureSelectedCallback(boost::bind(&LLPanelFace::onPbrSelectionChanged, this, _1));
+ pbr_ctrl->setOnCloseCallback(boost::bind(&LLPanelFace::onCloseTexturePicker, this, _2));
+
+ pbr_ctrl->setFollowsTop();
+ pbr_ctrl->setFollowsLeft();
+ pbr_ctrl->setImmediateFilterPermMask(PERM_NONE);
+ pbr_ctrl->setDnDFilterPermMask(PERM_COPY | PERM_TRANSFER);
+ pbr_ctrl->setBakeTextureEnabled(false);
+ pbr_ctrl->setInventoryPickType(LLTextureCtrl::PICK_MATERIAL);
+ }
+
mTextureCtrl = getChild<LLTextureCtrl>("texture control");
if(mTextureCtrl)
{
@@ -290,20 +434,27 @@ BOOL LLPanelFace::postBuild()
mComboTexGen->setFollows(FOLLOWS_LEFT | FOLLOWS_TOP);
}
- mComboMatMedia = getChild<LLComboBox>("combobox matmedia");
+ mComboMatMedia = getChild<LLComboBox>("combobox matmedia");
if(mComboMatMedia)
{
- mComboMatMedia->setCommitCallback(LLPanelFace::onCommitMaterialsMedia,this);
- mComboMatMedia->selectNthItem(MATMEDIA_MATERIAL);
+ mComboMatMedia->setCommitCallback(LLPanelFace::onCommitMaterialsMedia,this);
+ mComboMatMedia->selectNthItem(MATMEDIA_MATERIAL);
}
- LLRadioGroup* radio_mat_type = getChild<LLRadioGroup>("radio_material_type");
+ LLRadioGroup* radio_mat_type = findChild<LLRadioGroup>("radio_material_type");
if(radio_mat_type)
{
radio_mat_type->setCommitCallback(LLPanelFace::onCommitMaterialType, this);
radio_mat_type->selectNthItem(MATTYPE_DIFFUSE);
}
+ LLRadioGroup* radio_pbr_type = findChild<LLRadioGroup>("radio_pbr_type");
+ if (radio_pbr_type)
+ {
+ radio_pbr_type->setCommitCallback(LLPanelFace::onCommitPbrType, this);
+ radio_pbr_type->selectNthItem(PBRTYPE_RENDER_MATERIAL_ID);
+ }
+
mCtrlGlow = getChild<LLSpinCtrl>("glow");
if(mCtrlGlow)
{
@@ -349,6 +500,11 @@ void LLPanelFace::draw()
updateMediaTitle();
LLPanel::draw();
+
+ if (sMaterialOverrideSelection.update())
+ {
+ setMaterialOverridesFromSelection();
+ }
}
void LLPanelFace::sendTexture()
@@ -474,9 +630,11 @@ struct LLPanelFaceSetTEFunctor : public LLSelectedTEFunctor
{
BOOL valid;
F32 value;
+ std::string prefix;
+ // Effectively the same as MATMEDIA_PBR sans using different radio,
+ // separate for the sake of clarity
LLRadioGroup * radio_mat_type = mPanel->getChild<LLRadioGroup>("radio_material_type");
- std::string prefix;
switch (radio_mat_type->getSelectedIndex())
{
case MATTYPE_DIFFUSE:
@@ -837,44 +995,58 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)
{
BOOL editable = objectp->permModify() && !objectp->isPermanentEnforced();
+ bool has_pbr_material;
+ updateUIGLTF(objectp, has_pbr_material, force_set_values);
+
+ const bool has_material = !has_pbr_material;
+
// only turn on auto-adjust button if there is a media renderer and the media is loaded
childSetEnabled("button align", editable);
- if (mComboMatMedia)
- {
- if (mComboMatMedia->getCurrentIndex() < MATMEDIA_MATERIAL)
- {
+ if (mComboMatMedia->getCurrentIndex() < MATMEDIA_MATERIAL)
+ {
+ // When selecting an object with a pbr and UI combo is not set,
+ // set to pbr option, otherwise to a texture (material)
+ if (has_pbr_material)
+ {
+ mComboMatMedia->selectNthItem(MATMEDIA_PBR);
+ }
+ else
+ {
mComboMatMedia->selectNthItem(MATMEDIA_MATERIAL);
- }
- mComboMatMedia->setEnabled(editable);
- }
- else
- {
- LL_WARNS() << "failed getChild for 'combobox matmedia'" << LL_ENDL;
- }
+ }
+ }
+
+ mComboMatMedia->setEnabled(editable);
LLRadioGroup* radio_mat_type = getChild<LLRadioGroup>("radio_material_type");
- if(radio_mat_type)
- {
- if (radio_mat_type->getSelectedIndex() < MATTYPE_DIFFUSE)
- {
- radio_mat_type->selectNthItem(MATTYPE_DIFFUSE);
- }
- }
- else
- {
- LL_WARNS("Materials") << "failed getChild for 'radio_material_type'" << LL_ENDL;
- }
+ if (radio_mat_type->getSelectedIndex() < MATTYPE_DIFFUSE)
+ {
+ radio_mat_type->selectNthItem(MATTYPE_DIFFUSE);
+ }
+ radio_mat_type->setEnabled(editable);
+
+ LLRadioGroup* radio_pbr_type = getChild<LLRadioGroup>("radio_pbr_type");
+ if (radio_pbr_type->getSelectedIndex() < PBRTYPE_RENDER_MATERIAL_ID)
+ {
+ radio_pbr_type->selectNthItem(PBRTYPE_RENDER_MATERIAL_ID);
+ }
+ radio_pbr_type->setEnabled(editable);
+ const bool pbr_selected = mComboMatMedia->getCurrentIndex() == MATMEDIA_PBR;
+ const bool texture_info_selected = pbr_selected && radio_pbr_type->getSelectedIndex() != PBRTYPE_RENDER_MATERIAL_ID;
- getChildView("radio_material_type")->setEnabled(editable);
getChildView("checkbox_sync_settings")->setEnabled(editable);
childSetValue("checkbox_sync_settings", gSavedSettings.getBOOL("SyncMaterialSettings"));
+
updateVisibility();
+ // *NOTE: The "identical" variable is currently only used to decide if
+ // the texgen control should be tentative - this is not used by GLTF
+ // materials. -Cosmic;2022-11-09
bool identical = true; // true because it is anded below
- bool identical_diffuse = false;
- bool identical_norm = false;
- bool identical_spec = false;
+ bool identical_diffuse = false;
+ bool identical_norm = false;
+ bool identical_spec = false;
LLTextureCtrl* texture_ctrl = getChild<LLTextureCtrl>("texture control");
LLTextureCtrl* shinytexture_ctrl = getChild<LLTextureCtrl>("shinytexture control");
@@ -901,9 +1073,9 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)
color_swatch->setOriginal(color);
color_swatch->set(color, force_set_values || (prev_color != color) || !editable);
- color_swatch->setValid(editable);
- color_swatch->setEnabled( editable );
- color_swatch->setCanApplyImmediately( editable );
+ color_swatch->setValid(editable && !has_pbr_material);
+ color_swatch->setEnabled( editable && !has_pbr_material);
+ color_swatch->setCanApplyImmediately( editable && !has_pbr_material);
}
// Color transparency
@@ -911,7 +1083,7 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)
F32 transparency = (1.f - color.mV[VALPHA]) * 100.f;
getChild<LLUICtrl>("ColorTrans")->setValue(editable ? transparency : 0);
- getChildView("ColorTrans")->setEnabled(editable);
+ getChildView("ColorTrans")->setEnabled(editable && has_material);
// Specular map
LLSelectedTEMaterial::getSpecularID(specmap_id, identical_spec);
@@ -956,7 +1128,7 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)
U8 bumpy = 0;
// Bumpy
- {
+ {
bool identical_bumpy = false;
LLSelectedTE::getBumpmap(bumpy,identical_bumpy);
@@ -977,7 +1149,7 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)
getChildView("combobox bumpiness")->setEnabled(editable);
getChild<LLUICtrl>("combobox bumpiness")->setTentative(!identical_bumpy);
getChildView("label bumpiness")->setEnabled(editable);
- }
+ }
// Texture
{
@@ -1046,21 +1218,21 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)
updateAlphaControls();
if (texture_ctrl)
- {
+ {
if (identical_diffuse)
{
texture_ctrl->setTentative(FALSE);
- texture_ctrl->setEnabled(editable);
+ texture_ctrl->setEnabled(editable && !has_pbr_material);
texture_ctrl->setImageAssetID(id);
- getChildView("combobox alphamode")->setEnabled(editable && mIsAlpha && transparency <= 0.f);
- getChildView("label alphamode")->setEnabled(editable && mIsAlpha);
- getChildView("maskcutoff")->setEnabled(editable && mIsAlpha);
- getChildView("label maskcutoff")->setEnabled(editable && mIsAlpha);
+ getChildView("combobox alphamode")->setEnabled(editable && mIsAlpha && transparency <= 0.f && !has_pbr_material);
+ getChildView("label alphamode")->setEnabled(editable && mIsAlpha && !has_pbr_material);
+ getChildView("maskcutoff")->setEnabled(editable && mIsAlpha && !has_pbr_material);
+ getChildView("label maskcutoff")->setEnabled(editable && mIsAlpha && !has_pbr_material);
texture_ctrl->setBakeTextureEnabled(TRUE);
}
else if (id.isNull())
- {
+ {
// None selected
texture_ctrl->setTentative(FALSE);
texture_ctrl->setEnabled(FALSE);
@@ -1071,17 +1243,17 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)
getChildView("label maskcutoff")->setEnabled(FALSE);
texture_ctrl->setBakeTextureEnabled(false);
- }
- else
- {
+ }
+ else
+ {
// Tentative: multiple selected with different textures
texture_ctrl->setTentative(TRUE);
- texture_ctrl->setEnabled(editable);
+ texture_ctrl->setEnabled(editable && !has_pbr_material);
texture_ctrl->setImageAssetID(id);
- getChildView("combobox alphamode")->setEnabled(editable && mIsAlpha && transparency <= 0.f);
- getChildView("label alphamode")->setEnabled(editable && mIsAlpha);
- getChildView("maskcutoff")->setEnabled(editable && mIsAlpha);
- getChildView("label maskcutoff")->setEnabled(editable && mIsAlpha);
+ getChildView("combobox alphamode")->setEnabled(editable && mIsAlpha && transparency <= 0.f && !has_pbr_material);
+ getChildView("label alphamode")->setEnabled(editable && mIsAlpha && !has_pbr_material);
+ getChildView("maskcutoff")->setEnabled(editable && mIsAlpha && !has_pbr_material);
+ getChildView("label maskcutoff")->setEnabled(editable && mIsAlpha && !has_pbr_material);
texture_ctrl->setBakeTextureEnabled(TRUE);
}
@@ -1091,14 +1263,14 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)
if (shinytexture_ctrl)
{
shinytexture_ctrl->setTentative( !identical_spec );
- shinytexture_ctrl->setEnabled( editable );
+ shinytexture_ctrl->setEnabled( editable && !has_pbr_material);
shinytexture_ctrl->setImageAssetID( specmap_id );
}
if (bumpytexture_ctrl)
{
bumpytexture_ctrl->setTentative( !identical_norm );
- bumpytexture_ctrl->setEnabled( editable );
+ bumpytexture_ctrl->setEnabled( editable && !has_pbr_material);
bumpytexture_ctrl->setImageAssetID( normmap_id );
}
}
@@ -1110,9 +1282,9 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)
LLCheckBoxCtrl* cb_planar_align = getChild<LLCheckBoxCtrl>("checkbox planar align");
align_planar = (cb_planar_align && cb_planar_align->get());
- bool enabled = (editable && isIdenticalPlanarTexgen());
+ bool enabled = (editable && isIdenticalPlanarTexgen() && (!pbr_selected || texture_info_selected));
childSetValue("checkbox planar align", align_planar && enabled);
- childSetVisible("checkbox planar align", enabled);
+ childSetVisible("checkbox planar align", enabled);
childSetEnabled("checkbox planar align", enabled);
childSetEnabled("button align textures", enabled && LLSelectMgr::getInstance()->getSelection()->getObjectCount() > 1);
@@ -1170,9 +1342,9 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)
getChild<LLUICtrl>("shinyScaleU")->setValue(spec_scale_s);
getChild<LLUICtrl>("bumpyScaleU")->setValue(norm_scale_s);
- getChildView("TexScaleU")->setEnabled(editable);
- getChildView("shinyScaleU")->setEnabled(editable && specmap_id.notNull());
- getChildView("bumpyScaleU")->setEnabled(editable && normmap_id.notNull());
+ getChildView("TexScaleU")->setEnabled(editable && has_material);
+ getChildView("shinyScaleU")->setEnabled(editable && has_material && specmap_id.notNull());
+ getChildView("bumpyScaleU")->setEnabled(editable && has_material && normmap_id.notNull());
BOOL diff_scale_tentative = !(identical && identical_diff_scale_s);
BOOL norm_scale_tentative = !(identical && identical_norm_scale_s);
@@ -1209,9 +1381,9 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)
BOOL norm_scale_tentative = !identical_norm_scale_t;
BOOL spec_scale_tentative = !identical_spec_scale_t;
- getChildView("TexScaleV")->setEnabled(editable);
- getChildView("shinyScaleV")->setEnabled(editable && specmap_id.notNull());
- getChildView("bumpyScaleV")->setEnabled(editable && normmap_id.notNull());
+ getChildView("TexScaleV")->setEnabled(editable && has_material);
+ getChildView("shinyScaleV")->setEnabled(editable && has_material && specmap_id.notNull());
+ getChildView("bumpyScaleV")->setEnabled(editable && has_material && normmap_id.notNull());
if (force_set_values)
{
@@ -1255,9 +1427,9 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)
getChild<LLUICtrl>("shinyOffsetU")->setTentative(LLSD(norm_offset_u_tentative));
getChild<LLUICtrl>("bumpyOffsetU")->setTentative(LLSD(spec_offset_u_tentative));
- getChildView("TexOffsetU")->setEnabled(editable);
- getChildView("shinyOffsetU")->setEnabled(editable && specmap_id.notNull());
- getChildView("bumpyOffsetU")->setEnabled(editable && normmap_id.notNull());
+ getChildView("TexOffsetU")->setEnabled(editable && has_material);
+ getChildView("shinyOffsetU")->setEnabled(editable && has_material && specmap_id.notNull());
+ getChildView("bumpyOffsetU")->setEnabled(editable && has_material && normmap_id.notNull());
}
{
@@ -1285,9 +1457,9 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)
getChild<LLUICtrl>("shinyOffsetV")->setTentative(LLSD(norm_offset_v_tentative));
getChild<LLUICtrl>("bumpyOffsetV")->setTentative(LLSD(spec_offset_v_tentative));
- getChildView("TexOffsetV")->setEnabled(editable);
- getChildView("shinyOffsetV")->setEnabled(editable && specmap_id.notNull());
- getChildView("bumpyOffsetV")->setEnabled(editable && normmap_id.notNull());
+ getChildView("TexOffsetV")->setEnabled(editable && has_material);
+ getChildView("shinyOffsetV")->setEnabled(editable && has_material && specmap_id.notNull());
+ getChildView("bumpyOffsetV")->setEnabled(editable && has_material && normmap_id.notNull());
}
// Texture rotation
@@ -1311,10 +1483,10 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)
F32 diff_rot_deg = diff_rotation * RAD_TO_DEG;
F32 norm_rot_deg = norm_rotation * RAD_TO_DEG;
F32 spec_rot_deg = spec_rotation * RAD_TO_DEG;
-
- getChildView("TexRot")->setEnabled(editable);
- getChildView("shinyRot")->setEnabled(editable && specmap_id.notNull());
- getChildView("bumpyRot")->setEnabled(editable && normmap_id.notNull());
+
+ getChildView("TexRot")->setEnabled(editable && has_material);
+ getChildView("shinyRot")->setEnabled(editable && has_material && specmap_id.notNull());
+ getChildView("bumpyRot")->setEnabled(editable && has_material && normmap_id.notNull());
getChild<LLUICtrl>("TexRot")->setTentative(diff_rot_tentative);
getChild<LLUICtrl>("shinyRot")->setTentative(LLSD(norm_rot_tentative));
@@ -1360,7 +1532,7 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)
LLSelectedTE::getFullbright(fullbright_flag,identical_fullbright);
getChild<LLUICtrl>("checkbox fullbright")->setValue((S32)(fullbright_flag != 0));
- getChildView("checkbox fullbright")->setEnabled(editable);
+ getChildView("checkbox fullbright")->setEnabled(editable && !has_pbr_material);
getChild<LLUICtrl>("checkbox fullbright")->setTentative(!identical_fullbright);
}
@@ -1380,46 +1552,63 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)
LLComboBox* mComboTexGen = getChild<LLComboBox>("combobox texgen");
if (mComboTexGen)
- {
+ {
S32 index = mComboTexGen ? mComboTexGen->getCurrentIndex() : 0;
- BOOL enabled = editable && (index != 1);
- BOOL identical_repeats = true;
+ bool enabled = editable && (index != 1);
+ bool identical_repeats = true;
+ S32 material_selection = mComboMatMedia->getCurrentIndex();
F32 repeats = 1.0f;
- U32 material_type = (mComboMatMedia->getCurrentIndex() == MATMEDIA_MATERIAL) ? radio_mat_type->getSelectedIndex() : MATTYPE_DIFFUSE;
- LLSelectMgr::getInstance()->setTextureChannel(LLRender::eTexIndex(material_type));
+ U32 material_type = MATTYPE_DIFFUSE;
+ if (material_selection == MATMEDIA_MATERIAL)
+ {
+ material_type = radio_mat_type->getSelectedIndex();
+ }
+ else if (material_selection == MATMEDIA_PBR)
+ {
+ enabled = editable && has_pbr_material;
+ material_type = radio_pbr_type->getSelectedIndex();
+ }
- switch (material_type)
- {
- default:
- case MATTYPE_DIFFUSE:
- {
- enabled = editable && !id.isNull();
- identical_repeats = identical_diff_repeats;
- repeats = repeats_diff;
- }
- break;
+ switch (material_type)
+ {
+ default:
+ case MATTYPE_DIFFUSE:
+ {
+ if (material_selection != MATMEDIA_PBR)
+ {
+ enabled = editable && !id.isNull();
+ }
+ identical_repeats = identical_diff_repeats;
+ repeats = repeats_diff;
+ }
+ break;
- case MATTYPE_SPECULAR:
- {
- enabled = (editable && ((shiny == SHINY_TEXTURE) && !specmap_id.isNull()));
- identical_repeats = identical_spec_repeats;
- repeats = repeats_spec;
- }
- break;
+ case MATTYPE_SPECULAR:
+ {
+ if (material_selection != MATMEDIA_PBR)
+ {
+ enabled = (editable && ((shiny == SHINY_TEXTURE) && !specmap_id.isNull()));
+ }
+ identical_repeats = identical_spec_repeats;
+ repeats = repeats_spec;
+ }
+ break;
- case MATTYPE_NORMAL:
- {
- enabled = (editable && ((bumpy == BUMPY_TEXTURE) && !normmap_id.isNull()));
- identical_repeats = identical_norm_repeats;
- repeats = repeats_norm;
- }
- break;
- }
+ case MATTYPE_NORMAL:
+ {
+ if (material_selection != MATMEDIA_PBR)
+ {
+ enabled = (editable && ((bumpy == BUMPY_TEXTURE) && !normmap_id.isNull()));
+ }
+ identical_repeats = identical_norm_repeats;
+ repeats = repeats_norm;
+ }
+ break;
+ }
BOOL repeats_tentative = !identical_repeats;
- getChildView("rptctrl")->setEnabled(identical_planar_texgen ? FALSE : enabled);
LLSpinCtrl* rpt_ctrl = getChild<LLSpinCtrl>("rptctrl");
if (force_set_values)
{
@@ -1431,6 +1620,7 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)
rpt_ctrl->setValue(editable ? repeats : 1.0f);
}
rpt_ctrl->setTentative(LLSD(repeats_tentative));
+ rpt_ctrl->setEnabled(has_material && !identical_planar_texgen && enabled);
}
}
@@ -1439,7 +1629,7 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)
LLMaterialPtr material;
LLSelectedTEMaterial::getCurrent(material, identical);
- if (material && editable)
+ if (material && editable)
{
LL_DEBUGS("Materials") << material->asLLSD() << LL_ENDL;
@@ -1558,6 +1748,12 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)
clearCtrls();
// Disable non-UICtrls
+ LLTextureCtrl* pbr_ctrl = findChild<LLTextureCtrl>("pbr_control");
+ if (pbr_ctrl)
+ {
+ pbr_ctrl->setImageAssetID(LLUUID::null);
+ pbr_ctrl->setEnabled(FALSE);
+ }
LLTextureCtrl* texture_ctrl = getChild<LLTextureCtrl>("texture control");
if(texture_ctrl)
{
@@ -1583,8 +1779,9 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)
getChildView("label shininess")->setEnabled(FALSE);
getChildView("label bumpiness")->setEnabled(FALSE);
getChildView("button align")->setEnabled(FALSE);
- //getChildView("has media")->setEnabled(FALSE);
- //getChildView("media info set")->setEnabled(FALSE);
+ getChildView("pbr_from_inventory")->setEnabled(FALSE);
+ getChildView("edit_selected_pbr")->setEnabled(FALSE);
+ getChildView("save_selected_pbr")->setEnabled(FALSE);
updateVisibility();
@@ -1600,6 +1797,82 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)
}
}
+void LLPanelFace::updateUIGLTF(LLViewerObject* objectp, bool& has_pbr_material, bool force_set_values)
+{
+ has_pbr_material = false;
+
+ const bool editable = objectp->permModify() && !objectp->isPermanentEnforced();
+ bool has_pbr_capabilities = LLMaterialEditor::capabilitiesAvailable();
+
+ // pbr material
+ LLTextureCtrl* pbr_ctrl = findChild<LLTextureCtrl>("pbr_control");
+ if (pbr_ctrl)
+ {
+ LLUUID pbr_id;
+ bool identical_pbr;
+ LLSelectedTE::getPbrMaterialId(pbr_id, identical_pbr);
+
+ has_pbr_material = pbr_id.notNull();
+
+ pbr_ctrl->setTentative(identical_pbr ? FALSE : TRUE);
+ pbr_ctrl->setEnabled(editable && has_pbr_capabilities);
+ pbr_ctrl->setImageAssetID(pbr_id);
+ }
+
+ getChildView("pbr_from_inventory")->setEnabled(editable && has_pbr_capabilities);
+ getChildView("edit_selected_pbr")->setEnabled(editable && has_pbr_material && has_pbr_capabilities);
+ getChildView("save_selected_pbr")->setEnabled(objectp->permCopy() && has_pbr_material && has_pbr_capabilities);
+
+ const bool show_pbr = mComboMatMedia->getCurrentIndex() == MATMEDIA_PBR && mComboMatMedia->getEnabled();
+ if (show_pbr)
+ {
+ const U32 pbr_type = findChild<LLRadioGroup>("radio_pbr_type")->getSelectedIndex();
+ const LLGLTFMaterial::TextureInfo texture_info = texture_info_from_pbrtype(pbr_type);
+ const bool show_texture_info = texture_info != LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT;
+
+ LLUICtrl* gltfCtrlTextureScaleU = getChild<LLUICtrl>("gltfTextureScaleU");
+ LLUICtrl* gltfCtrlTextureScaleV = getChild<LLUICtrl>("gltfTextureScaleV");
+ LLUICtrl* gltfCtrlTextureRotation = getChild<LLUICtrl>("gltfTextureRotation");
+ LLUICtrl* gltfCtrlTextureOffsetU = getChild<LLUICtrl>("gltfTextureOffsetU");
+ LLUICtrl* gltfCtrlTextureOffsetV = getChild<LLUICtrl>("gltfTextureOffsetV");
+
+ gltfCtrlTextureScaleU->setEnabled(show_texture_info && has_pbr_capabilities && has_pbr_material);
+ gltfCtrlTextureScaleV->setEnabled(show_texture_info && has_pbr_capabilities && has_pbr_material);
+ gltfCtrlTextureRotation->setEnabled(show_texture_info && has_pbr_capabilities && has_pbr_material);
+ gltfCtrlTextureOffsetU->setEnabled(show_texture_info && has_pbr_capabilities && has_pbr_material);
+ gltfCtrlTextureOffsetV->setEnabled(show_texture_info && has_pbr_capabilities && has_pbr_material);
+
+ // Control values are set in setMaterialOverridesFromSelection
+ }
+}
+
+void LLPanelFace::updateVisibilityGLTF()
+{
+ const bool show_pbr = mComboMatMedia->getCurrentIndex() == MATMEDIA_PBR && mComboMatMedia->getEnabled();
+
+ LLRadioGroup* radio_pbr_type = findChild<LLRadioGroup>("radio_pbr_type");
+ radio_pbr_type->setVisible(show_pbr);
+
+ const U32 pbr_type = radio_pbr_type->getSelectedIndex();
+ const bool show_pbr_render_material_id = show_pbr && (pbr_type == PBRTYPE_RENDER_MATERIAL_ID);
+ const bool show_pbr_base_color = show_pbr && (pbr_type == PBRTYPE_BASE_COLOR);
+ const bool show_pbr_normal = show_pbr && (pbr_type == PBRTYPE_NORMAL);
+ const bool show_pbr_metallic_roughness = show_pbr && (pbr_type == PBRTYPE_METALLIC_ROUGHNESS);
+ const bool show_pbr_emissive = show_pbr && (pbr_type == PBRTYPE_EMISSIVE);
+ const bool show_pbr_transform = show_pbr_base_color || show_pbr_normal || show_pbr_metallic_roughness || show_pbr_emissive;
+
+ getChildView("pbr_control")->setVisible(show_pbr_render_material_id);
+
+ getChildView("pbr_from_inventory")->setVisible(show_pbr_render_material_id);
+ getChildView("edit_selected_pbr")->setVisible(show_pbr_render_material_id);
+ getChildView("save_selected_pbr")->setVisible(show_pbr_render_material_id);
+
+ getChildView("gltfTextureScaleU")->setVisible(show_pbr_transform);
+ getChildView("gltfTextureScaleV")->setVisible(show_pbr_transform);
+ getChildView("gltfTextureRotation")->setVisible(show_pbr_transform);
+ getChildView("gltfTextureOffsetU")->setVisible(show_pbr_transform);
+ getChildView("gltfTextureOffsetV")->setVisible(show_pbr_transform);
+}
void LLPanelFace::updateCopyTexButton()
{
@@ -1798,6 +2071,12 @@ void LLPanelFace::unloadMedia()
mTitleMedia->unloadMediaSource();
}
+// static
+void LLPanelFace::onMaterialOverrideReceived(const LLUUID& object_id, S32 side)
+{
+ sMaterialOverrideSelection.onSelectedObjectUpdated(object_id, side);
+}
+
//////////////////////////////////////////////////////////////////////////////
//
void LLPanelFace::navigateToTitleMedia( const std::string url )
@@ -2429,11 +2708,12 @@ void LLPanelFace::onCommitMaterialsMedia(LLUICtrl* ctrl, void* userdata)
}
void LLPanelFace::updateVisibility()
-{
- LLRadioGroup* radio_mat_type = getChild<LLRadioGroup>("radio_material_type");
- LLComboBox* combo_shininess = getChild<LLComboBox>("combobox shininess");
- LLComboBox* combo_bumpiness = getChild<LLComboBox>("combobox bumpiness");
- if (!radio_mat_type || !mComboMatMedia || !combo_shininess || !combo_bumpiness)
+{
+ LLRadioGroup* radio_mat_type = findChild<LLRadioGroup>("radio_material_type");
+ LLRadioGroup* radio_pbr_type = findChild<LLRadioGroup>("radio_pbr_type");
+ LLComboBox* combo_shininess = findChild<LLComboBox>("combobox shininess");
+ LLComboBox* combo_bumpiness = findChild<LLComboBox>("combobox bumpiness");
+ if (!radio_mat_type || !radio_pbr_type || !mComboMatMedia || !combo_shininess || !combo_bumpiness)
{
LL_WARNS("Materials") << "Combo box not found...exiting." << LL_ENDL;
return;
@@ -2441,10 +2721,22 @@ void LLPanelFace::updateVisibility()
U32 materials_media = mComboMatMedia->getCurrentIndex();
U32 material_type = radio_mat_type->getSelectedIndex();
bool show_media = (materials_media == MATMEDIA_MEDIA) && mComboMatMedia->getEnabled();
- bool show_texture = (show_media || ((material_type == MATTYPE_DIFFUSE) && mComboMatMedia->getEnabled()));
- bool show_bumpiness = (!show_media) && (material_type == MATTYPE_NORMAL) && mComboMatMedia->getEnabled();
- bool show_shininess = (!show_media) && (material_type == MATTYPE_SPECULAR) && mComboMatMedia->getEnabled();
- getChildView("radio_material_type")->setVisible(!show_media);
+ bool show_material = materials_media == MATMEDIA_MATERIAL;
+ bool show_texture = (show_media || (show_material && (material_type == MATTYPE_DIFFUSE) && mComboMatMedia->getEnabled()));
+ bool show_bumpiness = show_material && (material_type == MATTYPE_NORMAL) && mComboMatMedia->getEnabled();
+ bool show_shininess = show_material && (material_type == MATTYPE_SPECULAR) && mComboMatMedia->getEnabled();
+ const bool show_pbr = mComboMatMedia->getCurrentIndex() == MATMEDIA_PBR && mComboMatMedia->getEnabled();
+ const U32 pbr_type = findChild<LLRadioGroup>("radio_pbr_type")->getSelectedIndex();
+ const LLGLTFMaterial::TextureInfo texture_info = texture_info_from_pbrtype(pbr_type);
+ const bool show_texture_info = show_pbr && texture_info != LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT;
+
+ radio_mat_type->setVisible(show_material);
+
+ // Shared material controls
+ getChildView("checkbox_sync_settings")->setVisible(show_material || show_media || show_texture_info);
+ getChildView("tex gen")->setVisible(show_material || show_media || show_texture_info);
+ getChildView("combobox texgen")->setVisible(show_material || show_media || show_texture_info);
+ getChildView("button align textures")->setVisible(show_material || show_media);
// Media controls
mTitleMediaText->setVisible(show_media);
@@ -2453,15 +2745,16 @@ void LLPanelFace::updateVisibility()
getChildView("button align")->setVisible(show_media);
// Diffuse texture controls
- getChildView("texture control")->setVisible(show_texture && !show_media);
- getChildView("label alphamode")->setVisible(show_texture && !show_media);
- getChildView("combobox alphamode")->setVisible(show_texture && !show_media);
+ getChildView("texture control")->setVisible(show_texture && show_material);
+ getChildView("label alphamode")->setVisible(show_texture && show_material);
+ getChildView("combobox alphamode")->setVisible(show_texture && show_material);
getChildView("label maskcutoff")->setVisible(false);
getChildView("maskcutoff")->setVisible(false);
- if (show_texture && !show_media)
+ if (show_texture && show_material)
{
updateAlphaControls();
}
+ // texture scale and position controls
getChildView("TexScaleU")->setVisible(show_texture);
getChildView("TexScaleV")->setVisible(show_texture);
getChildView("TexRot")->setVisible(show_texture);
@@ -2502,7 +2795,10 @@ void LLPanelFace::updateVisibility()
getChildView("bumpyOffsetU")->setVisible(show_bumpiness);
getChildView("bumpyOffsetV")->setVisible(show_bumpiness);
+ getChild<LLSpinCtrl>("rptctrl")->setVisible(show_material || show_media);
+ // PBR controls
+ updateVisibilityGLTF();
}
// static
@@ -2518,6 +2814,17 @@ void LLPanelFace::onCommitMaterialType(LLUICtrl* ctrl, void* userdata)
}
// static
+void LLPanelFace::onCommitPbrType(LLUICtrl* ctrl, void* userdata)
+{
+ LLPanelFace* self = (LLPanelFace*)userdata;
+ // Force to default states to side-step problems with menu contents
+ // and generally reflecting old state when switching tabs or objects
+ //
+ self->updateUI();
+ self->setMaterialOverridesFromSelection();
+}
+
+// static
void LLPanelFace::onCommitBump(LLUICtrl* ctrl, void* userdata)
{
LLPanelFace* self = (LLPanelFace*) userdata;
@@ -2582,8 +2889,8 @@ void LLPanelFace::updateShinyControls(bool is_setting_texture, bool mess_with_sh
LLRadioGroup* radio_mat_type = getChild<LLRadioGroup>("radio_material_type");
U32 materials_media = mComboMatMedia->getCurrentIndex();
U32 material_type = radio_mat_type->getSelectedIndex();
- bool show_media = (materials_media == MATMEDIA_MEDIA) && mComboMatMedia->getEnabled();
- bool show_shininess = (!show_media) && (material_type == MATTYPE_SPECULAR) && mComboMatMedia->getEnabled();
+ bool show_material = (materials_media == MATMEDIA_MATERIAL);
+ bool show_shininess = show_material && (material_type == MATTYPE_SPECULAR) && mComboMatMedia->getEnabled();
U32 shiny_value = comboShiny->getCurrentIndex();
bool show_shinyctrls = (shiny_value == SHINY_TEXTURE) && show_shininess; // Use texture
getChildView("label glossiness")->setVisible(show_shinyctrls);
@@ -2700,21 +3007,81 @@ void LLPanelFace::onCommitGlow(LLUICtrl* ctrl, void* userdata)
}
// static
+BOOL LLPanelFace::onDragPbr(LLUICtrl*, LLInventoryItem* item)
+{
+ BOOL accept = TRUE;
+ for (LLObjectSelection::root_iterator iter = LLSelectMgr::getInstance()->getSelection()->root_begin();
+ iter != LLSelectMgr::getInstance()->getSelection()->root_end(); iter++)
+ {
+ LLSelectNode* node = *iter;
+ LLViewerObject* obj = node->getObject();
+ if (!LLToolDragAndDrop::isInventoryDropAcceptable(obj, item))
+ {
+ accept = FALSE;
+ break;
+ }
+ }
+ return accept;
+}
+
+void LLPanelFace::onCommitPbr(const LLSD& data)
+{
+ LLTextureCtrl* pbr_ctrl = findChild<LLTextureCtrl>("pbr_control");
+ if (!pbr_ctrl) return;
+ if (!pbr_ctrl->getTentative())
+ {
+ // we grab the item id first, because we want to do a
+ // permissions check in the selection manager. ARGH!
+ LLUUID id = pbr_ctrl->getImageItemID();
+ if (id.isNull())
+ {
+ id = pbr_ctrl->getImageAssetID();
+ }
+ LLSelectMgr::getInstance()->selectionSetGLTFMaterial(id);
+ }
+}
+
+void LLPanelFace::onCancelPbr(const LLSD& data)
+{
+ LLSelectMgr::getInstance()->selectionRevertGLTFMaterials();
+}
+
+void LLPanelFace::onSelectPbr(const LLSD& data)
+{
+ LLSelectMgr::getInstance()->saveSelectedObjectTextures();
+
+ LLTextureCtrl* pbr_ctrl = findChild<LLTextureCtrl>("pbr_control");
+ if (!pbr_ctrl) return;
+ if (!pbr_ctrl->getTentative())
+ {
+ // we grab the item id first, because we want to do a
+ // permissions check in the selection manager. ARGH!
+ LLUUID id = pbr_ctrl->getImageItemID();
+ if (id.isNull())
+ {
+ id = pbr_ctrl->getImageAssetID();
+ }
+ LLSelectMgr::getInstance()->selectionSetGLTFMaterial(id);
+ LLSelectedTEMaterial::setMaterialID(this, id);
+ }
+}
+
+// static
BOOL LLPanelFace::onDragTexture(LLUICtrl*, LLInventoryItem* item)
{
- BOOL accept = TRUE;
- for (LLObjectSelection::root_iterator iter = LLSelectMgr::getInstance()->getSelection()->root_begin();
- iter != LLSelectMgr::getInstance()->getSelection()->root_end(); iter++)
- {
- LLSelectNode* node = *iter;
- LLViewerObject* obj = node->getObject();
- if(!LLToolDragAndDrop::isInventoryDropAcceptable(obj, item))
- {
- accept = FALSE;
- break;
- }
- }
- return accept;
+ BOOL accept = TRUE;
+ for (LLObjectSelection::root_iterator iter = LLSelectMgr::getInstance()->getSelection()->root_begin();
+ iter != LLSelectMgr::getInstance()->getSelection()->root_end(); iter++)
+ {
+ LLSelectNode* node = *iter;
+ LLViewerObject* obj = node->getObject();
+ if (!LLToolDragAndDrop::isInventoryDropAcceptable(obj, item))
+ {
+ accept = FALSE;
+ break;
+ }
+ }
+ return accept;
}
void LLPanelFace::onCommitTexture( const LLSD& data )
@@ -3265,11 +3632,20 @@ void LLPanelFace::onCommitRepeatsPerMeter(LLUICtrl* ctrl, void* userdata)
LLPanelFace* self = (LLPanelFace*) userdata;
LLUICtrl* repeats_ctrl = self->getChild<LLUICtrl>("rptctrl");
- LLRadioGroup* radio_mat_type = self->getChild<LLRadioGroup>("radio_material_type");
U32 materials_media = self->mComboMatMedia->getCurrentIndex();
+ U32 material_type = 0;
+ if (materials_media == MATMEDIA_PBR)
+ {
+ LLRadioGroup* radio_mat_type = self->getChild<LLRadioGroup>("radio_pbr_type");
+ material_type = radio_mat_type->getSelectedIndex();
+ }
+ if (materials_media == MATMEDIA_MATERIAL)
+ {
+ LLRadioGroup* radio_mat_type = self->getChild<LLRadioGroup>("radio_material_type");
+ material_type = radio_mat_type->getSelectedIndex();
+ }
- U32 material_type = (materials_media == MATMEDIA_MATERIAL) ? radio_mat_type->getSelectedIndex() : 0;
F32 repeats_per_meter = repeats_ctrl->getValue().asReal();
F32 obj_scale_s = 1.0f;
@@ -3398,6 +3774,24 @@ void LLPanelFace::onAlignTexture(void* userdata)
self->alignTestureLayer();
}
+void LLPanelFace::onClickBtnLoadInvPBR(void* userdata)
+{
+ // Shouldn't this be "save to inventory?"
+ LLPanelFace* self = (LLPanelFace*)userdata;
+ LLTextureCtrl* pbr_ctrl = self->findChild<LLTextureCtrl>("pbr_control");
+ pbr_ctrl->showPicker(true);
+}
+
+void LLPanelFace::onClickBtnEditPBR(void* userdata)
+{
+ LLMaterialEditor::loadLive();
+}
+
+void LLPanelFace::onClickBtnSavePBR(void* userdata)
+{
+ LLMaterialEditor::saveObjectsMaterialAs();
+}
+
enum EPasteMode
{
PASTE_COLOR,
@@ -3429,10 +3823,36 @@ private:
struct LLPanelFaceUpdateFunctor : public LLSelectedObjectFunctor
{
- LLPanelFaceUpdateFunctor(bool update_media) : mUpdateMedia(update_media) {}
+ LLPanelFaceUpdateFunctor(bool update_media, bool update_pbr)
+ : mUpdateMedia(update_media)
+ , mUpdatePbr(update_pbr)
+ {}
+
virtual bool apply(LLViewerObject* object)
{
+ if (mUpdatePbr)
+ {
+ // setRenderMaterialId is supposed to create it
+ LLRenderMaterialParams* param_block = (LLRenderMaterialParams*)object->getParameterEntry(LLNetworkData::PARAMS_RENDER_MATERIAL);
+ if (param_block)
+ {
+ if (param_block->isEmpty())
+ {
+ object->setHasRenderMaterialParams(false);
+ }
+ else if (object->hasRenderMaterialParams())
+ {
+ object->parameterChanged(LLNetworkData::PARAMS_RENDER_MATERIAL, true);
+ }
+ else
+ {
+ object->setHasRenderMaterialParams(true);
+ }
+ }
+ }
+
object->sendTEUpdate();
+
if (mUpdateMedia)
{
LLVOVolume *vo = dynamic_cast<LLVOVolume*>(object);
@@ -3445,6 +3865,7 @@ struct LLPanelFaceUpdateFunctor : public LLSelectedObjectFunctor
}
private:
bool mUpdateMedia;
+ bool mUpdatePbr;
};
struct LLPanelFaceNavigateHomeFunctor : public LLSelectedTEFunctor
@@ -3580,7 +4001,7 @@ void LLPanelFace::onPasteColor()
LLPanelFacePasteTexFunctor paste_func(this, PASTE_COLOR);
selected_objects->applyToTEs(&paste_func);
- LLPanelFaceUpdateFunctor sendfunc(false);
+ LLPanelFaceUpdateFunctor sendfunc(false, false);
selected_objects->applyToObjects(&sendfunc);
}
@@ -3683,6 +4104,11 @@ void LLPanelFace::onCopyTexture()
te_data["te"]["bumpmap"] = tep->getBumpmap();
te_data["te"]["bumpshiny"] = tep->getBumpShiny();
te_data["te"]["bumpfullbright"] = tep->getBumpShinyFullbright();
+ te_data["te"]["pbr"] = objectp->getRenderMaterialID(te);
+ if (tep->getGLTFMaterialOverride() != nullptr)
+ {
+ te_data["te"]["pbr_override"] = tep->getGLTFMaterialOverride()->asJSON();
+ }
if (te_data["te"].has("imageid"))
{
@@ -3936,9 +4362,11 @@ void LLPanelFace::onPasteTexture()
LLPanelFacePasteTexFunctor paste_func(this, PASTE_TEXTURE);
selected_objects->applyToTEs(&paste_func);
- LLPanelFaceUpdateFunctor sendfunc(true);
+ LLPanelFaceUpdateFunctor sendfunc(true, true);
selected_objects->applyToObjects(&sendfunc);
+ LLGLTFMaterialList::flushUpdates();
+
LLPanelFaceNavigateHomeFunctor navigate_home_func;
selected_objects->applyToTEs(&navigate_home_func);
}
@@ -4070,6 +4498,38 @@ void LLPanelFace::onPasteTexture(LLViewerObject* objectp, S32 te)
{
objectp->setTEBumpShinyFullbright(te, (U8)te_data["te"]["bumpfullbright"].asInteger());
}
+ // PBR/GLTF
+ if (te_data["te"].has("pbr"))
+ {
+ objectp->setRenderMaterialID(te, te_data["te"]["pbr"].asUUID(), false /*managing our own update*/);
+ tep->setGLTFRenderMaterial(nullptr);
+ tep->setGLTFMaterialOverride(nullptr);
+
+ LLSD override_data;
+ override_data["object_id"] = objectp->getID();
+ override_data["side"] = te;
+ if (te_data["te"].has("pbr_override"))
+ {
+ override_data["gltf_json"] = te_data["te"]["pbr_override"];
+ }
+ else
+ {
+ override_data["gltf_json"] = "";
+ }
+
+ override_data["asset_id"] = te_data["te"]["pbr"].asUUID();
+
+ LLGLTFMaterialList::queueUpdate(override_data);
+ }
+ else
+ {
+ objectp->setRenderMaterialID(te, LLUUID::null, false /*send in bulk later*/ );
+ tep->setGLTFRenderMaterial(nullptr);
+ tep->setGLTFMaterialOverride(nullptr);
+
+ // blank out most override data on the server
+ LLGLTFMaterialList::queueApply(objectp, te, LLUUID::null);
+ }
// Texture map
if (te_data["te"].has("scales") && te_data["te"].has("scalet"))
@@ -4211,6 +4671,222 @@ void LLPanelFace::onCommitPlanarAlign(LLUICtrl* ctrl, void* userdata)
self->sendTextureInfo();
}
+void LLPanelFace::updateGLTFTextureTransform(float value, U32 pbr_type, std::function<void(LLGLTFMaterial::TextureTransform*)> edit)
+{
+ U32 texture_info_start;
+ U32 texture_info_end;
+ if (gSavedSettings.getBOOL("SyncMaterialSettings"))
+ {
+ texture_info_start = 0;
+ texture_info_end = LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT;
+ }
+ else
+ {
+ texture_info_start = texture_info_from_pbrtype(pbr_type);
+ texture_info_end = texture_info_start + 1;
+ }
+ updateSelectedGLTFMaterials([&](LLGLTFMaterial* new_override)
+ {
+ for (U32 ti = texture_info_start; ti < texture_info_end; ++ti)
+ {
+ LLGLTFMaterial::TextureTransform& new_transform = new_override->mTextureTransform[(LLGLTFMaterial::TextureInfo)ti];
+ edit(&new_transform);
+ }
+ });
+
+ LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstNode();
+ if (node)
+ {
+ LLViewerObject* object = node->getObject();
+ sMaterialOverrideSelection.setObjectUpdatePending(object->getID(), node->getLastSelectedTE());
+ }
+}
+
+void LLPanelFace::setMaterialOverridesFromSelection()
+{
+ const U32 pbr_type = findChild<LLRadioGroup>("radio_pbr_type")->getSelectedIndex();
+ const LLGLTFMaterial::TextureInfo texture_info = texture_info_from_pbrtype(pbr_type);
+ if (texture_info == LLGLTFMaterial::TextureInfo::GLTF_TEXTURE_INFO_COUNT)
+ {
+ return;
+ }
+
+ LLGLTFMaterial::TextureTransform transform;
+ bool scale_u_same = true;
+ bool scale_v_same = true;
+ bool rotation_same = true;
+ bool offset_u_same = true;
+ bool offset_v_same = true;
+
+ readSelectedGLTFMaterial<float>([&](const LLGLTFMaterial* mat)
+ {
+ return mat ? mat->mTextureTransform[texture_info].mScale[VX] : 0.f;
+ }, transform.mScale[VX], scale_u_same, true, 1e-3f);
+ readSelectedGLTFMaterial<float>([&](const LLGLTFMaterial* mat)
+ {
+ return mat ? mat->mTextureTransform[texture_info].mScale[VY] : 0.f;
+ }, transform.mScale[VY], scale_v_same, true, 1e-3f);
+ readSelectedGLTFMaterial<float>([&](const LLGLTFMaterial* mat)
+ {
+ return mat ? mat->mTextureTransform[texture_info].mRotation : 0.f;
+ }, transform.mRotation, rotation_same, true, 1e-3f);
+ readSelectedGLTFMaterial<float>([&](const LLGLTFMaterial* mat)
+ {
+ return mat ? mat->mTextureTransform[texture_info].mOffset[VX] : 0.f;
+ }, transform.mOffset[VX], offset_u_same, true, 1e-3f);
+ readSelectedGLTFMaterial<float>([&](const LLGLTFMaterial* mat)
+ {
+ return mat ? mat->mTextureTransform[texture_info].mOffset[VY] : 0.f;
+ }, transform.mOffset[VY], offset_v_same, true, 1e-3f);
+
+ LLUICtrl* gltfCtrlTextureScaleU = getChild<LLUICtrl>("gltfTextureScaleU");
+ LLUICtrl* gltfCtrlTextureScaleV = getChild<LLUICtrl>("gltfTextureScaleV");
+ LLUICtrl* gltfCtrlTextureRotation = getChild<LLUICtrl>("gltfTextureRotation");
+ LLUICtrl* gltfCtrlTextureOffsetU = getChild<LLUICtrl>("gltfTextureOffsetU");
+ LLUICtrl* gltfCtrlTextureOffsetV = getChild<LLUICtrl>("gltfTextureOffsetV");
+
+ gltfCtrlTextureScaleU->setValue(transform.mScale[VX]);
+ gltfCtrlTextureScaleV->setValue(transform.mScale[VY]);
+ gltfCtrlTextureRotation->setValue(transform.mRotation * RAD_TO_DEG);
+ gltfCtrlTextureOffsetU->setValue(transform.mOffset[VX]);
+ gltfCtrlTextureOffsetV->setValue(transform.mOffset[VY]);
+
+ gltfCtrlTextureScaleU->setTentative(!scale_u_same);
+ gltfCtrlTextureScaleV->setTentative(!scale_v_same);
+ gltfCtrlTextureRotation->setTentative(!rotation_same);
+ gltfCtrlTextureOffsetU->setTentative(!offset_u_same);
+ gltfCtrlTextureOffsetV->setTentative(!offset_v_same);
+}
+
+void LLPanelFace::Selection::connect()
+{
+ if (!mSelectConnection.connected())
+ {
+ mSelectConnection = LLSelectMgr::instance().mUpdateSignal.connect(boost::bind(&LLPanelFace::Selection::onSelectionChanged, this));
+ }
+}
+
+bool LLPanelFace::Selection::update()
+{
+ const bool selection_changed = compareSelection();
+ if (selection_changed)
+ {
+ clearObjectUpdatePending();
+ }
+ else if (isObjectUpdatePending())
+ {
+ return false;
+ }
+
+ const bool changed = mChanged;
+ mChanged = false;
+ return changed;
+}
+
+void LLPanelFace::Selection::setObjectUpdatePending(const LLUUID &object_id, S32 side)
+{
+ mPendingObjectID = object_id;
+ mPendingSide = side;
+}
+
+void LLPanelFace::Selection::onSelectedObjectUpdated(const LLUUID& object_id, S32 side)
+{
+ if (object_id == mSelectedObjectID && side == mSelectedSide)
+ {
+ mChanged = true;
+ clearObjectUpdatePending();
+ }
+}
+
+void LLPanelFace::Selection::clearObjectUpdatePending()
+{
+ mPendingObjectID = LLUUID::null;
+ mPendingSide = -1;
+}
+
+bool LLPanelFace::Selection::compareSelection()
+{
+ if (!mNeedsSelectionCheck)
+ {
+ return false;
+ }
+ mNeedsSelectionCheck = false;
+
+ const S32 old_object_count = mSelectedObjectCount;
+ const LLUUID old_object_id = mSelectedObjectID;
+ const S32 old_side = mSelectedSide;
+
+ LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
+ LLSelectNode* node = selection->getFirstNode();
+ if (node)
+ {
+ LLViewerObject* object = node->getObject();
+ mSelectedObjectCount = selection->getObjectCount();
+ mSelectedObjectID = object->getID();
+ mSelectedSide = node->getLastSelectedTE();
+ }
+ else
+ {
+ mSelectedObjectCount = 0;
+ mSelectedObjectID = LLUUID::null;
+ mSelectedSide = -1;
+ }
+
+ const bool selection_changed = old_object_count != mSelectedObjectCount || old_object_id != mSelectedObjectID || old_side != mSelectedSide;
+ mChanged = mChanged || selection_changed;
+ return selection_changed;
+}
+
+void LLPanelFace::onCommitGLTFTextureScaleU(LLUICtrl* ctrl)
+{
+ const float value = ctrl->getValue().asReal();
+ const U32 pbr_type = findChild<LLRadioGroup>("radio_pbr_type")->getSelectedIndex();
+ updateGLTFTextureTransform(value, pbr_type, [&](LLGLTFMaterial::TextureTransform* new_transform)
+ {
+ new_transform->mScale.mV[VX] = value;
+ });
+}
+
+void LLPanelFace::onCommitGLTFTextureScaleV(LLUICtrl* ctrl)
+{
+ const float value = ctrl->getValue().asReal();
+ const U32 pbr_type = findChild<LLRadioGroup>("radio_pbr_type")->getSelectedIndex();
+ updateGLTFTextureTransform(value, pbr_type, [&](LLGLTFMaterial::TextureTransform* new_transform)
+ {
+ new_transform->mScale.mV[VY] = value;
+ });
+}
+
+void LLPanelFace::onCommitGLTFRotation(LLUICtrl* ctrl)
+{
+ const float value = ctrl->getValue().asReal() * DEG_TO_RAD;
+ const U32 pbr_type = findChild<LLRadioGroup>("radio_pbr_type")->getSelectedIndex();
+ updateGLTFTextureTransform(value, pbr_type, [&](LLGLTFMaterial::TextureTransform* new_transform)
+ {
+ new_transform->mRotation = value;
+ });
+}
+
+void LLPanelFace::onCommitGLTFTextureOffsetU(LLUICtrl* ctrl)
+{
+ const float value = ctrl->getValue().asReal();
+ const U32 pbr_type = findChild<LLRadioGroup>("radio_pbr_type")->getSelectedIndex();
+ updateGLTFTextureTransform(value, pbr_type, [&](LLGLTFMaterial::TextureTransform* new_transform)
+ {
+ new_transform->mOffset.mV[VX] = value;
+ });
+}
+
+void LLPanelFace::onCommitGLTFTextureOffsetV(LLUICtrl* ctrl)
+{
+ const float value = ctrl->getValue().asReal();
+ const U32 pbr_type = findChild<LLRadioGroup>("radio_pbr_type")->getSelectedIndex();
+ updateGLTFTextureTransform(value, pbr_type, [&](LLGLTFMaterial::TextureTransform* new_transform)
+ {
+ new_transform->mOffset.mV[VY] = value;
+ });
+}
+
void LLPanelFace::onTextureSelectionChanged(LLInventoryItem* itemp)
{
LL_DEBUGS("Materials") << "item asset " << itemp->getAssetUUID() << LL_ENDL;
@@ -4263,6 +4939,39 @@ void LLPanelFace::onTextureSelectionChanged(LLInventoryItem* itemp)
}
}
+void LLPanelFace::onPbrSelectionChanged(LLInventoryItem* itemp)
+{
+ LLTextureCtrl* pbr_ctrl = findChild<LLTextureCtrl>("pbr_control");
+ if (pbr_ctrl)
+ {
+ LLUUID obj_owner_id;
+ std::string obj_owner_name;
+ LLSelectMgr::instance().selectGetOwner(obj_owner_id, obj_owner_name);
+
+ LLSaleInfo sale_info;
+ LLSelectMgr::instance().selectGetSaleInfo(sale_info);
+
+ bool can_copy = itemp->getPermissions().allowCopyBy(gAgentID); // do we have perm to copy this texture?
+ bool can_transfer = itemp->getPermissions().allowOperationBy(PERM_TRANSFER, gAgentID); // do we have perm to transfer this texture?
+ bool is_object_owner = gAgentID == obj_owner_id; // does object for which we are going to apply texture belong to the agent?
+ bool not_for_sale = !sale_info.isForSale(); // is object for which we are going to apply texture not for sale?
+
+ if (can_copy && can_transfer)
+ {
+ pbr_ctrl->setCanApply(true, true);
+ return;
+ }
+
+ // if texture has (no-transfer) attribute it can be applied only for object which we own and is not for sale
+ pbr_ctrl->setCanApply(false, can_transfer ? true : is_object_owner && not_for_sale);
+
+ if (gSavedSettings.getBOOL("TextureLivePreview"))
+ {
+ LLNotificationsUtil::add("LivePreviewUnavailable");
+ }
+ }
+}
+
bool LLPanelFace::isIdenticalPlanarTexgen()
{
LLTextureEntry::e_texgen selected_texgen = LLTextureEntry::TEX_GEN_DEFAULT;
@@ -4342,6 +5051,18 @@ void LLPanelFace::LLSelectedTE::getTexId(LLUUID& id, bool& identical)
identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, id );
}
+void LLPanelFace::LLSelectedTE::getPbrMaterialId(LLUUID& id, bool& identical)
+{
+ struct LLSelectedTEGetmatId : public LLSelectedTEGetFunctor<LLUUID>
+ {
+ LLUUID get(LLViewerObject* object, S32 te_index)
+ {
+ return object->getRenderMaterialID(te_index);
+ }
+ } func;
+ identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue(&func, id);
+}
+
void LLPanelFace::LLSelectedTEMaterial::getCurrent(LLMaterialPtr& material_ptr, bool& identical_material)
{
struct MaterialFunctor : public LLSelectedTEGetFunctor<LLMaterialPtr>
@@ -4480,3 +5201,4 @@ void LLPanelFace::LLSelectedTE::getMaxDiffuseRepeats(F32& repeats, bool& identic
} max_diff_repeats_func;
identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &max_diff_repeats_func, repeats );
}
+
diff --git a/indra/newview/llpanelface.h b/indra/newview/llpanelface.h
index 44bc442bbb..707d693672 100644
--- a/indra/newview/llpanelface.h
+++ b/indra/newview/llpanelface.h
@@ -29,6 +29,7 @@
#include "v4color.h"
#include "llpanel.h"
+#include "llgltfmaterial.h"
#include "llmaterial.h"
#include "llmaterialmgr.h"
#include "lltextureentry.h"
@@ -102,6 +103,8 @@ public:
void refreshMedia();
void unloadMedia();
+ static void onMaterialOverrideReceived(const LLUUID& object_id, S32 side);
+
/*virtual*/ void draw();
LLMaterialPtr createDefaultMaterial(LLMaterialPtr current_material)
@@ -116,6 +119,7 @@ public:
}
LLRender::eTexIndex getTextureChannelToEdit();
+ LLRender::eTexIndex getTextureDropChannel();
protected:
void navigateToTitleMedia(const std::string url);
@@ -135,11 +139,15 @@ protected:
void sendShiny(U32 shininess); // applies and sends shininess
void sendFullbright(); // applies and sends full bright
void sendGlow();
- void sendMedia();
void alignTestureLayer();
void updateCopyTexButton();
+ void onCommitPbr(const LLSD& data);
+ void onCancelPbr(const LLSD& data);
+ void onSelectPbr(const LLSD& data);
+ static BOOL onDragPbr(LLUICtrl* ctrl, LLInventoryItem* item);
+
// this function is to return TRUE if the drag should succeed.
static BOOL onDragTexture(LLUICtrl* ctrl, LLInventoryItem* item);
@@ -206,9 +214,11 @@ protected:
static void onCommitMaterialGloss( LLUICtrl* ctrl, void* userdata);
static void onCommitMaterialEnv( LLUICtrl* ctrl, void* userdata);
static void onCommitMaterialMaskCutoff( LLUICtrl* ctrl, void* userdata);
+ static void onCommitMaterialID( LLUICtrl* ctrl, void* userdata);
static void onCommitMaterialsMedia( LLUICtrl* ctrl, void* userdata);
static void onCommitMaterialType( LLUICtrl* ctrl, void* userdata);
+ static void onCommitPbrType(LLUICtrl* ctrl, void* userdata);
static void onClickBtnEditMedia(LLUICtrl* ctrl, void* userdata);
static void onClickBtnDeleteMedia(LLUICtrl* ctrl, void* userdata);
static void onClickBtnAddMedia(LLUICtrl* ctrl, void* userdata);
@@ -220,8 +230,18 @@ protected:
static void onCommitGlow( LLUICtrl* ctrl, void *userdata);
static void onCommitPlanarAlign( LLUICtrl* ctrl, void* userdata);
static void onCommitRepeatsPerMeter( LLUICtrl* ctrl, void* userinfo);
+
+ void onCommitGLTFTextureScaleU(LLUICtrl* ctrl);
+ void onCommitGLTFTextureScaleV(LLUICtrl* ctrl);
+ void onCommitGLTFRotation(LLUICtrl* ctrl);
+ void onCommitGLTFTextureOffsetU(LLUICtrl* ctrl);
+ void onCommitGLTFTextureOffsetV(LLUICtrl* ctrl);
+
static void onClickAutoFix(void*);
static void onAlignTexture(void*);
+ static void onClickBtnLoadInvPBR(void* userdata);
+ static void onClickBtnEditPBR(void* userdata);
+ static void onClickBtnSavePBR(void* userdata);
public: // needs to be accessible to selection manager
void onCopyColor(); // records all selected faces
@@ -431,30 +451,64 @@ private:
* all controls of the floater texture picker which allow to apply the texture will be disabled.
*/
void onTextureSelectionChanged(LLInventoryItem* itemp);
+ void onPbrSelectionChanged(LLInventoryItem* itemp);
+
+ void updateUIGLTF(LLViewerObject* objectp, bool& has_pbr_material, bool force_set_values);
+ void updateVisibilityGLTF();
+
+ void updateSelectedGLTFMaterials(std::function<void(LLGLTFMaterial*)> func);
+ void updateGLTFTextureTransform(float value, U32 pbr_type, std::function<void(LLGLTFMaterial::TextureTransform*)> edit);
+
+ void setMaterialOverridesFromSelection();
LLMenuButton* mMenuClipboardColor;
LLMenuButton* mMenuClipboardTexture;
bool mIsAlpha;
- /* These variables interlock processing of materials updates sent to
- * the sim. mUpdateInFlight is set to flag that an update has been
- * sent to the sim and not acknowledged yet, and cleared when an
- * update is received from the sim. mUpdatePending is set when
- * there's an update in flight and another UI change has been made
- * that needs to be sent as a materials update, and cleared when the
- * update is sent. This prevents the sim from getting spammed with
- * update messages when, for example, the user holds down the
- * up-arrow on a spinner, and avoids running afoul of its throttle.
- */
- bool mUpdateInFlight;
- bool mUpdatePending;
-
LLSD mClipboardParams;
LLSD mMediaSettings;
bool mNeedMediaTitle;
+ class Selection
+ {
+ public:
+ void connect();
+
+ // Returns true if the selected objects or sides have changed since
+ // this was last called, and no object update is pending
+ bool update();
+
+ // Prevents update() returning true until the provided object is
+ // updated. Necessary to prevent controls updating when the mouse is
+ // held down.
+ void setObjectUpdatePending(const LLUUID &object_id, S32 side);
+
+ // Callbacks
+ void onSelectionChanged() { mNeedsSelectionCheck = true; }
+ void onSelectedObjectUpdated(const LLUUID &object_id, S32 side);
+
+ protected:
+ void clearObjectUpdatePending();
+ bool isObjectUpdatePending() { return mPendingSide != -1; }
+
+ bool compareSelection();
+
+ bool mChanged = false;
+
+ boost::signals2::scoped_connection mSelectConnection;
+ bool mNeedsSelectionCheck = true;
+ S32 mSelectedObjectCount = 0;
+ LLUUID mSelectedObjectID;
+ S32 mSelectedSide = -1;
+
+ LLUUID mPendingObjectID;
+ S32 mPendingSide = -1;
+ };
+
+ static Selection sMaterialOverrideSelection;
+
public:
#if defined(DEF_GET_MAT_STATE)
#undef DEF_GET_MAT_STATE
@@ -535,6 +589,7 @@ public:
DEF_EDIT_MAT_STATE(LLUUID,const LLUUID&,setNormalID);
DEF_EDIT_MAT_STATE(LLUUID,const LLUUID&,setSpecularID);
DEF_EDIT_MAT_STATE(LLColor4U, const LLColor4U&,setSpecularLightColor);
+ DEF_EDIT_MAT_STATE(LLUUID, const LLUUID&, setMaterialID);
};
class LLSelectedTE
@@ -544,6 +599,7 @@ public:
static void getFace(class LLFace*& face_to_return, bool& identical_face);
static void getImageFormat(LLGLenum& image_format_to_return, bool& identical_face);
static void getTexId(LLUUID& id, bool& identical);
+ static void getPbrMaterialId(LLUUID& id, bool& identical);
static void getObjectScaleS(F32& scale_s, bool& identical);
static void getObjectScaleT(F32& scale_t, bool& identical);
static void getMaxDiffuseRepeats(F32& repeats, bool& identical);
diff --git a/indra/newview/llpanelgroupnotices.cpp b/indra/newview/llpanelgroupnotices.cpp
index ab32ea3956..82f880c9ee 100644
--- a/indra/newview/llpanelgroupnotices.cpp
+++ b/indra/newview/llpanelgroupnotices.cpp
@@ -156,6 +156,7 @@ BOOL LLGroupDropTarget::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
case DAD_CALLINGCARD:
case DAD_MESH:
case DAD_SETTINGS:
+ case DAD_MATERIAL:
{
LLViewerInventoryItem* inv_item = (LLViewerInventoryItem*)cargo_data;
if(gInventory.getItem(inv_item->getUUID())
diff --git a/indra/newview/llpanellandmedia.cpp b/indra/newview/llpanellandmedia.cpp
index e379d67e37..ca252d1455 100644
--- a/indra/newview/llpanellandmedia.cpp
+++ b/indra/newview/llpanellandmedia.cpp
@@ -86,7 +86,6 @@ BOOL LLPanelLandMedia::postBuild()
mMediaTextureCtrl->setAllowNoTexture ( TRUE );
mMediaTextureCtrl->setImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER);
mMediaTextureCtrl->setDnDFilterPermMask(PERM_COPY | PERM_TRANSFER);
- mMediaTextureCtrl->setNonImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER);
mMediaAutoScaleCheck = getChild<LLCheckBoxCtrl>("media_auto_scale");
childSetCommitCallback("media_auto_scale", onCommitAny, this);
diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp
index 81acb1c8b4..f38357c5da 100644
--- a/indra/newview/llpanelmaininventory.cpp
+++ b/indra/newview/llpanelmaininventory.cpp
@@ -127,6 +127,7 @@ LLPanelMainInventory::LLPanelMainInventory(const LLPanel::Params& p)
mCommitCallbackRegistrar.add("Inventory.Share", boost::bind(&LLAvatarActions::shareWithAvatars, this));
mEnableCallbackRegistrar.add("Inventory.EnvironmentEnabled", [](LLUICtrl *, const LLSD &) { return LLPanelMainInventory::hasSettingsInventory(); });
+ mEnableCallbackRegistrar.add("Inventory.MaterialsEnabled", [](LLUICtrl *, const LLSD &) { return LLPanelMainInventory::hasMaterialsInventory(); });
mSavedFolderState = new LLSaveFolderState();
@@ -926,6 +927,7 @@ void LLFloaterInventoryFinder::updateElementsFromFilter()
getChild<LLUICtrl>("check_clothing")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_WEARABLE));
getChild<LLUICtrl>("check_gesture")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_GESTURE));
getChild<LLUICtrl>("check_landmark")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_LANDMARK));
+ getChild<LLUICtrl>("check_material")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_MATERIAL));
getChild<LLUICtrl>("check_notecard")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_NOTECARD));
getChild<LLUICtrl>("check_object")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_OBJECT));
getChild<LLUICtrl>("check_script")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_LSL));
@@ -982,6 +984,12 @@ void LLFloaterInventoryFinder::draw()
filtered_by_all_types = FALSE;
}
+ if (!getChild<LLUICtrl>("check_material")->getValue())
+ {
+ filter &= ~(0x1 << LLInventoryType::IT_MATERIAL);
+ filtered_by_all_types = FALSE;
+ }
+
if (!getChild<LLUICtrl>("check_notecard")->getValue())
{
filter &= ~(0x1 << LLInventoryType::IT_NOTECARD);
@@ -1136,6 +1144,7 @@ void LLFloaterInventoryFinder::selectAllTypes(void* user_data)
self->getChild<LLUICtrl>("check_clothing")->setValue(TRUE);
self->getChild<LLUICtrl>("check_gesture")->setValue(TRUE);
self->getChild<LLUICtrl>("check_landmark")->setValue(TRUE);
+ self->getChild<LLUICtrl>("check_material")->setValue(TRUE);
self->getChild<LLUICtrl>("check_notecard")->setValue(TRUE);
self->getChild<LLUICtrl>("check_object")->setValue(TRUE);
self->getChild<LLUICtrl>("check_script")->setValue(TRUE);
@@ -1156,6 +1165,7 @@ void LLFloaterInventoryFinder::selectNoTypes(void* user_data)
self->getChild<LLUICtrl>("check_clothing")->setValue(FALSE);
self->getChild<LLUICtrl>("check_gesture")->setValue(FALSE);
self->getChild<LLUICtrl>("check_landmark")->setValue(FALSE);
+ self->getChild<LLUICtrl>("check_material")->setValue(FALSE);
self->getChild<LLUICtrl>("check_notecard")->setValue(FALSE);
self->getChild<LLUICtrl>("check_object")->setValue(FALSE);
self->getChild<LLUICtrl>("check_script")->setValue(FALSE);
@@ -1592,5 +1602,13 @@ bool LLPanelMainInventory::hasSettingsInventory()
return LLEnvironment::instance().isInventoryEnabled();
}
+bool LLPanelMainInventory::hasMaterialsInventory()
+{
+ std::string agent_url = gAgent.getRegionCapability("UpdateMaterialAgentInventory");
+ std::string task_url = gAgent.getRegionCapability("UpdateMaterialTaskInventory");
+
+ return (!agent_url.empty() && !task_url.empty());
+}
+
// List Commands //
////////////////////////////////////////////////////////////////////////////////
diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h
index 257bce930c..9a36470273 100644
--- a/indra/newview/llpanelmaininventory.h
+++ b/indra/newview/llpanelmaininventory.h
@@ -165,6 +165,7 @@ protected:
void onCustomAction(const LLSD& command_name);
bool handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, EAcceptance* accept);
static bool hasSettingsInventory();
+ static bool hasMaterialsInventory();
/**
* Set upload cost in "Upload" sub menu.
*/
diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp
index 2da431955f..0704fc881d 100644
--- a/indra/newview/llpanelobject.cpp
+++ b/indra/newview/llpanelobject.cpp
@@ -252,8 +252,6 @@ BOOL LLPanelObject::postBuild()
// Don't allow (no copy) or (no transfer) textures to be selected during immediate mode
mCtrlSculptTexture->setImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER);
mCtrlSculptTexture->setDnDFilterPermMask(PERM_COPY | PERM_TRANSFER);
- // Allow any texture to be used during non-immediate mode.
- mCtrlSculptTexture->setNonImmediateFilterPermMask(PERM_NONE);
LLAggregatePermissions texture_perms;
if (LLSelectMgr::getInstance()->selectGetAggregateTexturePermissions(texture_perms))
{
diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp
index bd40c9dd2b..2db8620d2d 100644
--- a/indra/newview/llpanelobjectinventory.cpp
+++ b/indra/newview/llpanelobjectinventory.cpp
@@ -50,6 +50,7 @@
#include "llinventoryicon.h"
#include "llinventoryfilter.h"
#include "llinventoryfunctions.h"
+#include "llmaterialeditor.h"
#include "llpreviewanim.h"
#include "llpreviewgesture.h"
#include "llpreviewnotecard.h"
@@ -715,6 +716,7 @@ BOOL LLTaskCategoryBridge::dragOrDrop(MASK mask, BOOL drop,
case DAD_CALLINGCARD:
case DAD_MESH:
case DAD_SETTINGS:
+ case DAD_MATERIAL:
accept = LLToolDragAndDrop::isInventoryDropAcceptable(object, (LLViewerInventoryItem*)cargo_data);
if(accept && drop)
{
@@ -1162,6 +1164,58 @@ LLSettingsType::type_e LLTaskSettingsBridge::getSettingsType() const
}
///----------------------------------------------------------------------------
+/// Class LLTaskMaterialBridge
+///----------------------------------------------------------------------------
+
+class LLTaskMaterialBridge : public LLTaskInvFVBridge
+{
+public:
+ LLTaskMaterialBridge(LLPanelObjectInventory* panel,
+ const LLUUID& uuid,
+ const std::string& name) :
+ LLTaskInvFVBridge(panel, uuid, name) {}
+
+ BOOL canOpenItem() const override { return TRUE; }
+ void openItem() override;
+ BOOL removeItem() override;
+};
+
+void LLTaskMaterialBridge::openItem()
+{
+ LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
+ if(!object || object->isInventoryPending())
+ {
+ return;
+ }
+
+ // Note: even if we are not allowed to modify copyable notecard, we should be able to view it
+ LLInventoryItem *item = dynamic_cast<LLInventoryItem*>(object->getInventoryObject(mUUID));
+ BOOL item_copy = item && gAgent.allowOperation(PERM_COPY, item->getPermissions(), GP_OBJECT_MANIPULATE);
+ if( item_copy
+ || object->permModify()
+ || gAgent.isGodlike())
+ {
+ LLSD floater_key;
+ floater_key["taskid"] = mPanel->getTaskUUID();
+ floater_key["itemid"] = mUUID;
+ LLMaterialEditor* mat = LLFloaterReg::getTypedInstance<LLMaterialEditor>("material_editor", floater_key);
+ if (mat)
+ {
+ mat->setObjectID(mPanel->getTaskUUID());
+ mat->openFloater(floater_key);
+ mat->setFocus(TRUE);
+ }
+ }
+}
+
+BOOL LLTaskMaterialBridge::removeItem()
+{
+ LLFloaterReg::hideInstance("material_editor", LLSD(mUUID));
+ return LLTaskInvFVBridge::removeItem();
+}
+
+
+///----------------------------------------------------------------------------
/// LLTaskInvFVBridge impl
//----------------------------------------------------------------------------
@@ -1248,6 +1302,11 @@ LLTaskInvFVBridge* LLTaskInvFVBridge::createObjectBridge(LLPanelObjectInventory*
object_name,
itemflags);
break;
+ case LLAssetType::AT_MATERIAL:
+ new_bridge = new LLTaskMaterialBridge(panel,
+ object_id,
+ object_name);
+ break;
default:
LL_INFOS() << "Unhandled inventory type (llassetstorage.h): "
<< (S32)type << LL_ENDL;
diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp
index 708ff26ced..816633b545 100644
--- a/indra/newview/llpanelprofile.cpp
+++ b/indra/newview/llpanelprofile.cpp
@@ -1889,7 +1889,6 @@ void LLPanelProfileSecondLife::onShowTexturePicker()
"SELECT PHOTO",
PERM_NONE,
PERM_NONE,
- PERM_NONE,
FALSE,
NULL);
@@ -2230,7 +2229,6 @@ void LLPanelProfileFirstLife::onChangePhoto()
"SELECT PHOTO",
PERM_NONE,
PERM_NONE,
- PERM_NONE,
FALSE,
NULL);
diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp
index 39f4c7485b..0cbc2b0bad 100644
--- a/indra/newview/llpanelvolume.cpp
+++ b/indra/newview/llpanelvolume.cpp
@@ -48,6 +48,7 @@
#include "lltexturectrl.h"
#include "llcombobox.h"
//#include "llfirstuse.h"
+#include "llfloaterreg.h"
#include "llfocusmgr.h"
#include "llmanipscale.h"
#include "llinventorymodel.h"
@@ -146,6 +147,15 @@ BOOL LLPanelVolume::postBuild()
getChild<LLUICtrl>("Light Ambiance")->setValidateBeforeCommit( precommitValidate);
}
+ // REFLECTION PROBE Parameters
+ {
+ childSetCommitCallback("Reflection Probe", onCommitIsReflectionProbe, this);
+ childSetCommitCallback("Probe Dynamic", onCommitProbe, this);
+ childSetCommitCallback("Probe Volume Type", onCommitProbe, this);
+ childSetCommitCallback("Probe Ambiance", onCommitProbe, this);
+ childSetCommitCallback("Probe Near Clip", onCommitProbe, this);
+ }
+
// PHYSICS Parameters
{
// PhysicsShapeType combobox
@@ -366,6 +376,43 @@ void LLPanelVolume::getState( )
getChildView("Light Ambiance")->setEnabled(false);
}
+ // Reflection Probe
+ BOOL is_probe = volobjp && volobjp->isReflectionProbe();
+ getChild<LLUICtrl>("Reflection Probe")->setValue(is_probe);
+ getChildView("Reflection Probe")->setEnabled(editable && single_volume && volobjp && !volobjp->isMesh());
+
+ bool probe_enabled = is_probe && editable && single_volume;
+
+ getChildView("Probe Dynamic")->setEnabled(probe_enabled);
+ getChildView("Probe Volume Type")->setEnabled(probe_enabled);
+ getChildView("Probe Ambiance")->setEnabled(probe_enabled);
+ getChildView("Probe Near Clip")->setEnabled(probe_enabled);
+
+ if (!probe_enabled)
+ {
+ getChild<LLComboBox>("Probe Volume Type", true)->clear();
+ getChild<LLSpinCtrl>("Probe Ambiance", true)->clear();
+ getChild<LLSpinCtrl>("Probe Near Clip", true)->clear();
+ getChild<LLCheckBoxCtrl>("Probe Dynamic", true)->clear();
+ }
+ else
+ {
+ std::string volume_type;
+ if (volobjp->getReflectionProbeIsBox())
+ {
+ volume_type = "Box";
+ }
+ else
+ {
+ volume_type = "Sphere";
+ }
+
+ getChild<LLComboBox>("Probe Volume Type", true)->setValue(volume_type);
+ getChild<LLSpinCtrl>("Probe Ambiance", true)->setValue(volobjp->getReflectionProbeAmbiance());
+ getChild<LLSpinCtrl>("Probe Near Clip", true)->setValue(volobjp->getReflectionProbeNearClip());
+ getChild<LLCheckBoxCtrl>("Probe Dynamic", true)->setValue(volobjp->getReflectionProbeIsDynamic());
+ }
+
// Animated Mesh
BOOL is_animated_mesh = single_root_volume && root_volobjp && root_volobjp->isAnimatedObject();
getChild<LLUICtrl>("Animated Mesh Checkbox Ctrl")->setValue(is_animated_mesh);
@@ -648,6 +695,11 @@ void LLPanelVolume::clearCtrls()
getChildView("Light Radius")->setEnabled(false);
getChildView("Light Falloff")->setEnabled(false);
+ getChildView("Reflection Probe")->setEnabled(false);;
+ getChildView("Probe Volume Type")->setEnabled(false);
+ getChildView("Probe Dynamic")->setEnabled(false);
+ getChildView("Probe Ambiance")->setEnabled(false);
+ getChildView("Probe Near Clip")->setEnabled(false);
getChildView("Animated Mesh Checkbox Ctrl")->setEnabled(false);
getChildView("Flexible1D Checkbox Ctrl")->setEnabled(false);
getChildView("FlexNumSections")->setEnabled(false);
@@ -685,6 +737,42 @@ void LLPanelVolume::sendIsLight()
LL_INFOS() << "update light sent" << LL_ENDL;
}
+void LLPanelVolume::sendIsReflectionProbe()
+{
+ LLViewerObject* objectp = mObject;
+ if (!objectp || (objectp->getPCode() != LL_PCODE_VOLUME))
+ {
+ return;
+ }
+ LLVOVolume* volobjp = (LLVOVolume*)objectp;
+
+ BOOL value = getChild<LLUICtrl>("Reflection Probe")->getValue();
+ BOOL old_value = volobjp->isReflectionProbe();
+
+ volobjp->setIsReflectionProbe(value);
+ LL_INFOS() << "update reflection probe sent" << LL_ENDL;
+
+ if (value && !old_value)
+ { // has become a reflection probe, slam to a 10m sphere and pop up a message
+ // warning people about the pitfalls of reflection probes
+ auto* select_mgr = LLSelectMgr::getInstance();
+
+ mObject->setScale(LLVector3(10.f, 10.f, 10.f));
+ select_mgr->sendMultipleUpdate(UPD_ROTATION | UPD_POSITION | UPD_SCALE);
+
+ select_mgr->selectionUpdatePhantom(true);
+ select_mgr->selectionSetGLTFMaterial(LLUUID::null);
+ select_mgr->selectionSetAlphaOnly(0.f);
+
+ LLVolumeParams params;
+ params.getPathParams().setCurveType(LL_PCODE_PATH_CIRCLE);
+ params.getProfileParams().setCurveType(LL_PCODE_PROFILE_CIRCLE_HALF);
+ mObject->updateVolume(params);
+
+ LLNotificationsUtil::add("ReflectionProbeApplied");
+ }
+}
+
void LLPanelVolume::sendIsFlexible()
{
LLViewerObject* objectp = mObject;
@@ -1026,6 +1114,14 @@ void LLPanelVolume::onCopyLight()
}
}
+ if (volobjp && volobjp->isReflectionProbe())
+ {
+ clipboard["reflection_probe"]["is_box"] = volobjp->getReflectionProbeIsBox();
+ clipboard["reflection_probe"]["ambiance"] = volobjp->getReflectionProbeAmbiance();
+ clipboard["reflection_probe"]["near_clip"] = volobjp->getReflectionProbeNearClip();
+ clipboard["reflection_probe"]["dynamic"] = volobjp->getReflectionProbeIsDynamic();
+ }
+
mClipboardParams["light"] = clipboard;
}
@@ -1073,6 +1169,19 @@ void LLPanelVolume::onPasteLight()
spot_params.mV[2] = (F32)clipboard["spot"]["ambiance"].asReal();
volobjp->setSpotLightParams(spot_params);
}
+
+ if (clipboard.has("reflection_probe"))
+ {
+ volobjp->setIsReflectionProbe(TRUE);
+ volobjp->setReflectionProbeIsBox(clipboard["reflection_probe"]["is_box"].asBoolean());
+ volobjp->setReflectionProbeAmbiance((F32)clipboard["reflection_probe"]["ambiance"].asReal());
+ volobjp->setReflectionProbeNearClip((F32)clipboard["reflection_probe"]["near_clip"].asReal());
+ volobjp->setReflectionProbeIsDynamic(clipboard["reflection_probe"]["dynamic"].asBoolean());
+ }
+ else
+ {
+ volobjp->setIsReflectionProbe(false);
+ }
}
}
@@ -1212,6 +1321,53 @@ void LLPanelVolume::onCommitLight( LLUICtrl* ctrl, void* userdata )
}
+//static
+void LLPanelVolume::onCommitProbe(LLUICtrl* ctrl, void* userdata)
+{
+ LLPanelVolume* self = (LLPanelVolume*)userdata;
+ LLViewerObject* objectp = self->mObject;
+ if (!objectp || (objectp->getPCode() != LL_PCODE_VOLUME))
+ {
+ return;
+ }
+ LLVOVolume* volobjp = (LLVOVolume*)objectp;
+
+ volobjp->setReflectionProbeAmbiance((F32)self->getChild<LLUICtrl>("Probe Ambiance")->getValue().asReal());
+ volobjp->setReflectionProbeNearClip((F32)self->getChild<LLUICtrl>("Probe Near Clip")->getValue().asReal());
+ volobjp->setReflectionProbeIsDynamic(self->getChild<LLUICtrl>("Probe Dynamic")->getValue().asBoolean());
+
+ std::string shape_type = self->getChild<LLUICtrl>("Probe Volume Type")->getValue().asString();
+
+ bool is_box = shape_type == "Box";
+
+ if (volobjp->setReflectionProbeIsBox(is_box))
+ {
+ // make the volume match the probe
+ U8 profile, path;
+
+ if (!is_box)
+ {
+ profile = LL_PCODE_PROFILE_CIRCLE_HALF;
+ path = LL_PCODE_PATH_CIRCLE;
+
+ F32 scale = volobjp->getScale().mV[0];
+ volobjp->setScale(LLVector3(scale, scale, scale), FALSE);
+ LLSelectMgr::getInstance()->sendMultipleUpdate(UPD_ROTATION | UPD_POSITION | UPD_SCALE);
+ }
+ else
+ {
+ profile = LL_PCODE_PROFILE_SQUARE;
+ path = LL_PCODE_PATH_LINE;
+ }
+
+ LLVolumeParams params;
+ params.getProfileParams().setCurveType(profile);
+ params.getPathParams().setCurveType(path);
+ objectp->updateVolume(params);
+ }
+
+}
+
// static
void LLPanelVolume::onCommitIsLight( LLUICtrl* ctrl, void* userdata )
{
@@ -1227,7 +1383,7 @@ void LLPanelVolume::setLightTextureID(const LLUUID &asset_id, const LLUUID &item
LLViewerInventoryItem* item = gInventory.getItem(item_id);
if (item && !item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID()))
{
- LLToolDragAndDrop::handleDropTextureProtections(volobjp, item, LLToolDragAndDrop::SOURCE_AGENT, LLUUID::null);
+ LLToolDragAndDrop::handleDropMaterialProtections(volobjp, item, LLToolDragAndDrop::SOURCE_AGENT, LLUUID::null);
}
volobjp->setLightTextureID(asset_id);
}
@@ -1235,6 +1391,15 @@ void LLPanelVolume::setLightTextureID(const LLUUID &asset_id, const LLUUID &item
//----------------------------------------------------------------------------
// static
+void LLPanelVolume::onCommitIsReflectionProbe(LLUICtrl* ctrl, void* userdata)
+{
+ LLPanelVolume* self = (LLPanelVolume*)userdata;
+ self->sendIsReflectionProbe();
+}
+
+//----------------------------------------------------------------------------
+
+// static
void LLPanelVolume::onCommitFlexible( LLUICtrl* ctrl, void* userdata )
{
LLPanelVolume* self = (LLPanelVolume*) userdata;
diff --git a/indra/newview/llpanelvolume.h b/indra/newview/llpanelvolume.h
index d9198f3693..62a6d01b21 100644
--- a/indra/newview/llpanelvolume.h
+++ b/indra/newview/llpanelvolume.h
@@ -57,12 +57,15 @@ public:
void refresh();
void sendIsLight();
+ void sendIsReflectionProbe();
void sendIsFlexible();
static bool precommitValidate(const LLSD& data);
static void onCommitIsLight( LLUICtrl* ctrl, void* userdata);
static void onCommitLight( LLUICtrl* ctrl, void* userdata);
+ static void onCommitIsReflectionProbe(LLUICtrl* ctrl, void* userdata);
+ static void onCommitProbe(LLUICtrl* ctrl, void* userdata);
void onCommitIsFlexible( LLUICtrl* ctrl, void* userdata);
static void onCommitFlexible( LLUICtrl* ctrl, void* userdata);
void onCommitAnimatedMeshCheckbox(LLUICtrl* ctrl, void* userdata);
diff --git a/indra/newview/llplacesinventorypanel.h b/indra/newview/llplacesinventorypanel.h
index 5629438415..3c27964ec5 100644
--- a/indra/newview/llplacesinventorypanel.h
+++ b/indra/newview/llplacesinventorypanel.h
@@ -40,7 +40,7 @@ public:
{
Params()
{
- filter_asset_type = "landmark";
+ filter_asset_types = "landmark";
}
};
diff --git a/indra/newview/llpreview.cpp b/indra/newview/llpreview.cpp
index fc2de4844e..b9b2279e77 100644
--- a/indra/newview/llpreview.cpp
+++ b/indra/newview/llpreview.cpp
@@ -115,8 +115,11 @@ const LLInventoryItem *LLPreview::getItem() const
}
else if (mObjectUUID.isNull())
{
- // it's an inventory item, so get the item.
- item = gInventory.getItem(mItemUUID);
+ if (mItemUUID.notNull())
+ {
+ // it's an inventory item, so get the item.
+ item = gInventory.getItem(mItemUUID);
+ }
}
else
{
diff --git a/indra/newview/llpreview.h b/indra/newview/llpreview.h
index 9ac15d1639..ab60f4c008 100644
--- a/indra/newview/llpreview.h
+++ b/indra/newview/llpreview.h
@@ -83,7 +83,7 @@ public:
virtual BOOL handleHover(S32 x, S32 y, MASK mask);
virtual void onOpen(const LLSD& key);
- void setAuxItem( const LLInventoryItem* item );
+ virtual void setAuxItem( const LLInventoryItem* item );
static void onBtnCopyToInv(void* userdata);
diff --git a/indra/newview/llpreviewgesture.cpp b/indra/newview/llpreviewgesture.cpp
index 759e7859f2..544ff8b5dc 100644
--- a/indra/newview/llpreviewgesture.cpp
+++ b/indra/newview/llpreviewgesture.cpp
@@ -1108,14 +1108,16 @@ void LLPreviewGesture::saveIfNeeded()
item->setComplete(true);
uploadInfo = std::make_shared<LLBufferedAssetUploadInfo>(mItemUUID, LLAssetType::AT_GESTURE, buffer,
- [](LLUUID itemId, LLUUID newAssetId, LLUUID, LLSD) {
+ [](LLUUID itemId, LLUUID newAssetId, LLUUID, LLSD)
+ {
LLPreviewGesture::finishInventoryUpload(itemId, newAssetId);
- });
+ },
+ nullptr);
url = agent_url;
}
else if (!mObjectUUID.isNull() && !task_url.empty())
{
- uploadInfo = std::make_shared<LLBufferedAssetUploadInfo>(mObjectUUID, mItemUUID, LLAssetType::AT_GESTURE, buffer, nullptr);
+ uploadInfo = std::make_shared<LLBufferedAssetUploadInfo>(mObjectUUID, mItemUUID, LLAssetType::AT_GESTURE, buffer, nullptr, nullptr);
url = task_url;
}
diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp
index 33656566d1..20b821f895 100644
--- a/indra/newview/llpreviewnotecard.cpp
+++ b/indra/newview/llpreviewnotecard.cpp
@@ -553,7 +553,8 @@ bool LLPreviewNotecard::saveIfNeeded(LLInventoryItem* copyitem, bool sync)
uploadInfo = std::make_shared<LLBufferedAssetUploadInfo>(mItemUUID, LLAssetType::AT_NOTECARD, buffer,
[](LLUUID itemId, LLUUID newAssetId, LLUUID newItemId, LLSD) {
LLPreviewNotecard::finishInventoryUpload(itemId, newAssetId, newItemId);
- });
+ },
+ nullptr);
url = agent_url;
}
else if (!mObjectUUID.isNull() && !task_url.empty())
@@ -562,7 +563,8 @@ bool LLPreviewNotecard::saveIfNeeded(LLInventoryItem* copyitem, bool sync)
uploadInfo = std::make_shared<LLBufferedAssetUploadInfo>(mObjectUUID, mItemUUID, LLAssetType::AT_NOTECARD, buffer,
[object_uuid](LLUUID itemId, LLUUID, LLUUID newAssetId, LLSD) {
LLPreviewNotecard::finishTaskUpload(itemId, newAssetId, object_uuid);
- });
+ },
+ nullptr);
url = task_url;
}
diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp
index d677a996c1..8b93dd103d 100644
--- a/indra/newview/llpreviewscript.cpp
+++ b/indra/newview/llpreviewscript.cpp
@@ -1202,7 +1202,7 @@ BOOL LLScriptEdCore::handleKeyHere(KEY key, MASK mask)
void LLScriptEdCore::onBtnLoadFromFile( void* data )
{
- (new LLFilePickerReplyThread(boost::bind(&LLScriptEdCore::loadScriptFromFile, _1, data), LLFilePicker::FFLOAD_SCRIPT, false))->getFile();
+ LLFilePickerReplyThread::startPicker(boost::bind(&LLScriptEdCore::loadScriptFromFile, _1, data), LLFilePicker::FFLOAD_SCRIPT, false);
}
void LLScriptEdCore::loadScriptFromFile(const std::vector<std::string>& filenames, void* data)
@@ -1243,7 +1243,7 @@ void LLScriptEdCore::onBtnSaveToFile( void* userdata )
if( self->mSaveCallback )
{
- (new LLFilePickerReplyThread(boost::bind(&LLScriptEdCore::saveScriptToFile, _1, userdata), LLFilePicker::FFSAVE_SCRIPT, self->mScriptName))->getFile();
+ LLFilePickerReplyThread::startPicker(boost::bind(&LLScriptEdCore::saveScriptToFile, _1, userdata), LLFilePicker::FFSAVE_SCRIPT, self->mScriptName);
}
}
@@ -1686,6 +1686,32 @@ void LLPreviewLSL::finishedLSLUpload(LLUUID itemId, LLSD response)
}
}
+bool LLPreviewLSL::failedLSLUpload(LLUUID itemId, LLUUID taskId, LLSD response, std::string reason)
+{
+ LLSD floater_key;
+ if (taskId.notNull())
+ {
+ floater_key["taskid"] = taskId;
+ floater_key["itemid"] = itemId;
+ }
+ else
+ {
+ floater_key = LLSD(itemId);
+ }
+
+ LLPreviewLSL* preview = LLFloaterReg::findTypedInstance<LLPreviewLSL>("preview_script", floater_key);
+ if (preview)
+ {
+ // unfreeze floater
+ LLSD errors;
+ errors.append(LLTrans::getString("UploadFailed") + reason);
+ preview->callbackLSLCompileFailed(errors);
+ return true;
+ }
+
+ return false;
+}
+
// Save needs to compile the text in the buffer. If the compile
// succeeds, then save both assets out to the database. If the compile
// fails, go ahead and save the text anyway.
@@ -1723,7 +1749,8 @@ void LLPreviewLSL::saveIfNeeded(bool sync /*= true*/)
[old_asset_id](LLUUID itemId, LLUUID, LLUUID, LLSD response) {
LLFileSystem::removeFile(old_asset_id, LLAssetType::AT_LSL_TEXT);
LLPreviewLSL::finishedLSLUpload(itemId, response);
- }));
+ },
+ LLPreviewLSL::failedLSLUpload));
LLViewerAssetUpload::EnqueueInventoryUpload(url, uploadInfo);
}
@@ -2282,7 +2309,8 @@ void LLLiveLSLEditor::saveIfNeeded(bool sync /*= true*/)
[isRunning, old_asset_id](LLUUID itemId, LLUUID taskId, LLUUID newAssetId, LLSD response) {
LLFileSystem::removeFile(old_asset_id, LLAssetType::AT_LSL_TEXT);
LLLiveLSLEditor::finishLSLUpload(itemId, taskId, newAssetId, response, isRunning);
- }));
+ },
+ nullptr)); // needs failure handling?
LLViewerAssetUpload::EnqueueInventoryUpload(url, uploadInfo);
}
diff --git a/indra/newview/llpreviewscript.h b/indra/newview/llpreviewscript.h
index f851ff6f3f..b01c7fd4ad 100644
--- a/indra/newview/llpreviewscript.h
+++ b/indra/newview/llpreviewscript.h
@@ -245,6 +245,7 @@ protected:
static void* createScriptEdPanel(void* userdata);
static void finishedLSLUpload(LLUUID itemId, LLSD response);
+ static bool failedLSLUpload(LLUUID itemId, LLUUID taskId, LLSD response, std::string reason);
protected:
// Can safely close only after both text and bytecode are uploaded
diff --git a/indra/newview/llpreviewtexture.cpp b/indra/newview/llpreviewtexture.cpp
index 10177c8023..975e2bb910 100644
--- a/indra/newview/llpreviewtexture.cpp
+++ b/indra/newview/llpreviewtexture.cpp
@@ -296,7 +296,7 @@ void LLPreviewTexture::saveAs()
return;
std::string filename = getItem() ? LLDir::getScrubbedFileName(getItem()->getName()) : LLStringUtil::null;
- (new LLFilePickerReplyThread(boost::bind(&LLPreviewTexture::saveTextureToFile, this, _1), LLFilePicker::FFSAVE_TGAPNG, filename))->getFile();
+ LLFilePickerReplyThread::startPicker(boost::bind(&LLPreviewTexture::saveTextureToFile, this, _1), LLFilePicker::FFSAVE_TGAPNG, filename);
}
void LLPreviewTexture::saveTextureToFile(const std::vector<std::string>& filenames)
diff --git a/indra/newview/llreflectionmap.cpp b/indra/newview/llreflectionmap.cpp
new file mode 100644
index 0000000000..f346531bfd
--- /dev/null
+++ b/indra/newview/llreflectionmap.cpp
@@ -0,0 +1,240 @@
+/**
+ * @file llreflectionmap.cpp
+ * @brief LLReflectionMap class implementation
+ *
+ * $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$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llreflectionmap.h"
+#include "pipeline.h"
+#include "llviewerwindow.h"
+#include "llviewerregion.h"
+
+extern F32SecondsImplicit gFrameTimeSeconds;
+
+LLReflectionMap::LLReflectionMap()
+{
+}
+
+void LLReflectionMap::update(U32 resolution, U32 face)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+ mLastUpdateTime = gFrameTimeSeconds;
+ llassert(mCubeArray.notNull());
+ llassert(mCubeIndex != -1);
+ //llassert(LLPipeline::sRenderDeferred);
+
+ // make sure we don't walk off the edge of the render target
+ while (resolution > gPipeline.mRT->deferredScreen.getWidth() ||
+ resolution > gPipeline.mRT->deferredScreen.getHeight())
+ {
+ resolution /= 2;
+ }
+ gViewerWindow->cubeSnapshot(LLVector3(mOrigin), mCubeArray, mCubeIndex, face, getNearClip(), getIsDynamic());
+}
+
+void LLReflectionMap::autoAdjustOrigin()
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+
+ if (mGroup)
+ {
+ const LLVector4a* bounds = mGroup->getBounds();
+ auto* node = mGroup->getOctreeNode();
+
+ if (mGroup->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_VOLUME)
+ {
+ mPriority = 1;
+ // cast a ray towards 8 corners of bounding box
+ // nudge origin towards center of empty space
+
+ if (!node)
+ {
+ return;
+ }
+
+ mOrigin = bounds[0];
+
+ LLVector4a size = bounds[1];
+
+ LLVector4a corners[] =
+ {
+ { 1, 1, 1 },
+ { -1, 1, 1 },
+ { 1, -1, 1 },
+ { -1, -1, 1 },
+ { 1, 1, -1 },
+ { -1, 1, -1 },
+ { 1, -1, -1 },
+ { -1, -1, -1 }
+ };
+
+ for (int i = 0; i < 8; ++i)
+ {
+ corners[i].mul(size);
+ corners[i].add(bounds[0]);
+ }
+
+ LLVector4a extents[2];
+ extents[0].setAdd(bounds[0], bounds[1]);
+ extents[1].setSub(bounds[0], bounds[1]);
+
+ bool hit = false;
+ for (int i = 0; i < 8; ++i)
+ {
+ int face = -1;
+ LLVector4a intersection;
+ LLDrawable* drawable = mGroup->lineSegmentIntersect(bounds[0], corners[i], true, false, true, &face, &intersection);
+ if (drawable != nullptr)
+ {
+ hit = true;
+ update_min_max(extents[0], extents[1], intersection);
+ }
+ else
+ {
+ update_min_max(extents[0], extents[1], corners[i]);
+ }
+ }
+
+ if (hit)
+ {
+ mOrigin.setAdd(extents[0], extents[1]);
+ mOrigin.mul(0.5f);
+ }
+
+ // make sure radius encompasses all objects
+ LLSimdScalar r2 = 0.0;
+ for (int i = 0; i < 8; ++i)
+ {
+ LLVector4a v;
+ v.setSub(corners[i], mOrigin);
+
+ LLSimdScalar d = v.dot3(v);
+
+ if (d > r2)
+ {
+ r2 = d;
+ }
+ }
+
+ mRadius = llmax(sqrtf(r2.getF32()), 8.f);
+ }
+ }
+ else if (mViewerObject)
+ {
+ mPriority = 64;
+ mOrigin.load3(mViewerObject->getPositionAgent().mV);
+ mRadius = mViewerObject->getScale().mV[0]*0.5f;
+ }
+}
+
+bool LLReflectionMap::intersects(LLReflectionMap* other)
+{
+ // TODO: incorporate getBox
+ LLVector4a delta;
+ delta.setSub(other->mOrigin, mOrigin);
+
+ F32 dist = delta.dot3(delta).getF32();
+
+ F32 r2 = mRadius + other->mRadius;
+
+ r2 *= r2;
+
+ return dist < r2;
+}
+
+extern LLControlGroup gSavedSettings;
+
+F32 LLReflectionMap::getAmbiance()
+{
+ F32 ret = 0.f;
+ if (mViewerObject && mViewerObject->getVolume())
+ {
+ ret = ((LLVOVolume*)mViewerObject)->getReflectionProbeAmbiance();
+ }
+
+ return ret;
+}
+
+F32 LLReflectionMap::getNearClip()
+{
+ const F32 MINIMUM_NEAR_CLIP = 0.1f;
+
+ F32 ret = 0.f;
+
+ if (mViewerObject && mViewerObject->getVolume())
+ {
+ ret = ((LLVOVolume*)mViewerObject)->getReflectionProbeNearClip();
+ }
+
+ return llmax(ret, MINIMUM_NEAR_CLIP);
+}
+
+bool LLReflectionMap::getIsDynamic()
+{
+ if (gSavedSettings.getS32("RenderReflectionProbeDetail") > (S32) LLReflectionMapManager::DetailLevel::STATIC_ONLY &&
+ mViewerObject &&
+ mViewerObject->getVolume())
+ {
+ return ((LLVOVolume*)mViewerObject)->getReflectionProbeIsDynamic();
+ }
+
+ return false;
+}
+
+bool LLReflectionMap::getBox(LLMatrix4& box)
+{
+ if (mViewerObject)
+ {
+ LLVolume* volume = mViewerObject->getVolume();
+ if (volume)
+ {
+ LLVOVolume* vobjp = (LLVOVolume*)mViewerObject;
+
+ if (vobjp->getReflectionProbeIsBox())
+ {
+ glh::matrix4f mv(gGLModelView);
+ glh::matrix4f scale;
+ LLVector3 s = vobjp->getScale().scaledVec(LLVector3(0.5f, 0.5f, 0.5f));
+ mRadius = s.magVec();
+ scale.set_scale(glh::vec3f(s.mV));
+ if (vobjp->mDrawable != nullptr)
+ {
+ glh::matrix4f rm((F32*)vobjp->mDrawable->getWorldMatrix().mMatrix);
+
+ glh::matrix4f rt((F32*)vobjp->getRelativeXform().mMatrix);
+
+ mv = mv * rm * scale; // *rt;
+ mv = mv.inverse();
+
+ box = LLMatrix4(mv.m);
+
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
diff --git a/indra/newview/llreflectionmap.h b/indra/newview/llreflectionmap.h
new file mode 100644
index 0000000000..cf0bc2ff27
--- /dev/null
+++ b/indra/newview/llreflectionmap.h
@@ -0,0 +1,102 @@
+/**
+ * @file llreflectionmap.h
+ * @brief LLReflectionMap class declaration
+ *
+ * $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$
+ */
+
+#pragma once
+
+#include "llcubemaparray.h"
+#include "llmemory.h"
+
+class LLSpatialGroup;
+class LLViewerObject;
+
+class alignas(16) LLReflectionMap : public LLRefCount
+{
+ LL_ALIGN_NEW
+public:
+ // allocate an environment map of the given resolution
+ LLReflectionMap();
+
+ // update this environment map
+ // resolution - size of cube map to generate
+ void update(U32 resolution, U32 face);
+
+ // for volume partition probes, try to place this probe in the best spot
+ void autoAdjustOrigin();
+
+ // return true if given Reflection Map's influence volume intersect's with this one's
+ bool intersects(LLReflectionMap* other);
+
+ // Get the ambiance value to use for this probe
+ F32 getAmbiance();
+
+ // Get the near clip plane distance to use for this probe
+ F32 getNearClip();
+
+ // Return true if this probe should include avatars in its reflection map
+ bool getIsDynamic();
+
+ // get the encoded bounding box of this probe's influence volume
+ // will only return a box if this probe is associated with a VOVolume
+ // with its reflection probe influence volume to to VOLUME_TYPE_BOX
+ // return false if no bounding box (treat as sphere influence volume)
+ bool getBox(LLMatrix4& box);
+
+ // point at which environment map was last generated from (in agent space)
+ LLVector4a mOrigin;
+
+ // distance from viewer camera
+ F32 mDistance;
+
+ // radius of this probe's affected area
+ F32 mRadius = 16.f;
+
+ // last time this probe was updated (or when its update timer got reset)
+ F32 mLastUpdateTime = 0.f;
+
+ // last time this probe was bound for rendering
+ F32 mLastBindTime = 0.f;
+
+ // cube map used to sample this environment map
+ LLPointer<LLCubeMapArray> mCubeArray;
+ S32 mCubeIndex = -1; // index into cube map array or -1 if not currently stored in cube map array
+
+ // index into array packed by LLReflectionMapManager::getReflectionMaps
+ // WARNING -- only valid immediately after call to getReflectionMaps
+ S32 mProbeIndex = -1;
+
+ // set of any LLReflectionMaps that intersect this map (maintained by LLReflectionMapManager
+ std::vector<LLReflectionMap*> mNeighbors;
+
+ // spatial group this probe is tracking (if any)
+ LLSpatialGroup* mGroup = nullptr;
+
+ // viewer object this probe is tracking (if any)
+ LLViewerObject* mViewerObject = nullptr;
+
+ // what priority should this probe have (higher is higher priority)
+ U32 mPriority = 1;
+};
+
diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp
new file mode 100644
index 0000000000..e622f54756
--- /dev/null
+++ b/indra/newview/llreflectionmapmanager.cpp
@@ -0,0 +1,1024 @@
+/**
+ * @file llreflectionmapmanager.cpp
+ * @brief LLReflectionMapManager class implementation
+ *
+ * $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$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llreflectionmapmanager.h"
+#include "llviewercamera.h"
+#include "llspatialpartition.h"
+#include "llviewerregion.h"
+#include "pipeline.h"
+#include "llviewershadermgr.h"
+#include "llviewercontrol.h"
+#include "llenvironment.h"
+#include "llstartup.h"
+
+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();
+ origin.mV[2] += 64.f;
+
+ probe->mOrigin.load3(origin.mV);
+}
+
+LLReflectionMapManager::LLReflectionMapManager()
+{
+ initCubeFree();
+}
+
+void LLReflectionMapManager::initCubeFree()
+{
+ for (int i = 1; i < LL_MAX_REFLECTION_PROBE_COUNT; ++i)
+ {
+ mCubeFree[i] = true;
+ }
+
+ // cube index 0 is reserved for the fallback probe
+ mCubeFree[0] = false;
+}
+
+struct CompareProbeDistance
+{
+ bool operator()(const LLPointer<LLReflectionMap>& lhs, const LLPointer<LLReflectionMap>& rhs)
+ {
+ return lhs->mDistance < rhs->mDistance;
+ }
+};
+
+// helper class to seed octree with probes
+void LLReflectionMapManager::update()
+{
+ if (!LLPipeline::sReflectionProbesEnabled || gTeleportDisplay || LLStartUp::getStartupState() < STATE_PRECACHE)
+ {
+ return;
+ }
+
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+ llassert(!gCubeSnapshot); // assert a snapshot is not in progress
+ if (LLAppViewer::instance()->logoutRequestSent())
+ {
+ return;
+ }
+
+ initReflectionMaps();
+
+ if (!mRenderTarget.isComplete())
+ {
+ U32 color_fmt = GL_RGB16F;
+ U32 targetRes = mProbeResolution * 2; // super sample
+ mRenderTarget.allocate(targetRes, targetRes, color_fmt, true);
+ }
+
+ if (mMipChain.empty())
+ {
+ U32 res = mProbeResolution;
+ U32 count = log2((F32)res) + 0.5f;
+
+ mMipChain.resize(count);
+ for (int i = 0; i < count; ++i)
+ {
+ mMipChain[i].allocate(res, res, GL_RGBA16F);
+ res /= 2;
+ }
+ }
+
+
+ if (mDefaultProbe.isNull())
+ {
+ 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);
+ }
+
+ LLVector4a camera_pos;
+ camera_pos.load3(LLViewerCamera::instance().getOrigin().mV);
+
+ // process kill list
+ for (auto& probe : mKillList)
+ {
+ auto const & iter = std::find(mProbes.begin(), mProbes.end(), probe);
+ if (iter != mProbes.end())
+ {
+ deleteProbe(iter - mProbes.begin());
+ }
+ }
+
+ mKillList.clear();
+
+ // process create list
+ for (auto& probe : mCreateList)
+ {
+ mProbes.push_back(probe);
+ }
+
+ mCreateList.clear();
+
+ if (mProbes.empty())
+ {
+ return;
+ }
+
+ bool did_update = false;
+
+ static LLCachedControl<S32> sDetail(gSavedSettings, "RenderReflectionProbeDetail", -1);
+ bool realtime = sDetail >= (S32)LLReflectionMapManager::DetailLevel::REALTIME;
+
+ LLReflectionMap* closestDynamic = nullptr;
+
+ LLReflectionMap* oldestProbe = nullptr;
+
+ if (mUpdatingProbe != nullptr)
+ {
+ did_update = true;
+ doProbeUpdate();
+ }
+
+ //LL_INFOS() << mProbes.size() << LL_ENDL;
+
+ for (int i = 0; i < mProbes.size(); ++i)
+ {
+ LLReflectionMap* probe = mProbes[i];
+ if (probe->getNumRefs() == 1)
+ { // no references held outside manager, delete this probe
+ deleteProbe(i);
+ --i;
+ continue;
+ }
+
+ probe->mProbeIndex = i;
+
+ LLVector4a d;
+
+ if (!did_update &&
+ i < mReflectionProbeCount &&
+ (oldestProbe == nullptr || probe->mLastUpdateTime < oldestProbe->mLastUpdateTime))
+ {
+ oldestProbe = probe;
+ }
+
+ if (realtime &&
+ closestDynamic == nullptr &&
+ probe->mCubeIndex != -1 &&
+ probe->getIsDynamic())
+ {
+ closestDynamic = probe;
+ }
+
+ if (probe != mDefaultProbe)
+ {
+ d.setSub(camera_pos, probe->mOrigin);
+ probe->mDistance = d.getLength3().getF32() - probe->mRadius;
+ }
+ }
+
+ if (realtime && closestDynamic != nullptr)
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmu - realtime");
+ // update the closest dynamic probe realtime
+ closestDynamic->autoAdjustOrigin();
+ for (U32 i = 0; i < 6; ++i)
+ {
+ updateProbeFace(closestDynamic, i);
+ }
+ }
+
+ // switch to updating the next oldest probe
+ if (!did_update && oldestProbe != nullptr)
+ {
+ LLReflectionMap* probe = oldestProbe;
+ if (probe->mCubeIndex == -1)
+ {
+ probe->mCubeArray = mTexture;
+
+ probe->mCubeIndex = probe == mDefaultProbe ? 0 : allocateCubeIndex();
+ }
+
+ probe->autoAdjustOrigin();
+
+ mUpdatingProbe = probe;
+ doProbeUpdate();
+ }
+
+ // update distance to camera for all probes
+ std::sort(mProbes.begin(), mProbes.end(), CompareProbeDistance());
+}
+
+LLReflectionMap* LLReflectionMapManager::addProbe(LLSpatialGroup* group)
+{
+ LLReflectionMap* probe = new LLReflectionMap();
+ probe->mGroup = group;
+
+ if (group)
+ {
+ probe->mOrigin = group->getOctreeNode()->getCenter();
+ }
+
+ if (gCubeSnapshot)
+ { //snapshot is in progress, mProbes is being iterated over, defer insertion until next update
+ mCreateList.push_back(probe);
+ }
+ else
+ {
+ mProbes.push_back(probe);
+ }
+
+ return probe;
+}
+
+void LLReflectionMapManager::getReflectionMaps(std::vector<LLReflectionMap*>& maps)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+
+ U32 count = 0;
+ U32 lastIdx = 0;
+ for (U32 i = 0; count < maps.size() && i < mProbes.size(); ++i)
+ {
+ mProbes[i]->mLastBindTime = gFrameTimeSeconds; // something wants to use this probe, indicate it's been requested
+ if (mProbes[i]->mCubeIndex != -1)
+ {
+ mProbes[i]->mProbeIndex = count;
+ maps[count++] = mProbes[i];
+ }
+ else
+ {
+ mProbes[i]->mProbeIndex = -1;
+ }
+ lastIdx = i;
+ }
+
+ // set remaining probe indices to -1
+ for (U32 i = lastIdx+1; i < mProbes.size(); ++i)
+ {
+ mProbes[i]->mProbeIndex = -1;
+ }
+
+ // null terminate list
+ if (count < maps.size())
+ {
+ maps[count] = nullptr;
+ }
+}
+
+LLReflectionMap* LLReflectionMapManager::registerSpatialGroup(LLSpatialGroup* group)
+{
+#if 1
+ if (group->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_VOLUME)
+ {
+ OctreeNode* node = group->getOctreeNode();
+ F32 size = node->getSize().getF32ptr()[0];
+ if (size >= 15.f && size <= 17.f)
+ {
+ return addProbe(group);
+ }
+ }
+#endif
+
+#if 0
+ if (group->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_TERRAIN)
+ {
+ OctreeNode* node = group->getOctreeNode();
+ F32 size = node->getSize().getF32ptr()[0];
+ if (size >= 15.f && size <= 17.f)
+ {
+ return addProbe(group);
+ }
+ }
+#endif
+ return nullptr;
+}
+
+LLReflectionMap* LLReflectionMapManager::registerViewerObject(LLViewerObject* vobj)
+{
+ llassert(vobj != nullptr);
+
+ LLReflectionMap* probe = new LLReflectionMap();
+ probe->mViewerObject = vobj;
+ probe->mOrigin.load3(vobj->getPositionAgent().mV);
+
+ if (gCubeSnapshot)
+ { //snapshot is in progress, mProbes is being iterated over, defer insertion until next update
+ mCreateList.push_back(probe);
+ }
+ else
+ {
+ mProbes.push_back(probe);
+ }
+
+ return probe;
+}
+
+
+S32 LLReflectionMapManager::allocateCubeIndex()
+{
+ for (int i = 0; i < mReflectionProbeCount; ++i)
+ {
+ if (mCubeFree[i])
+ {
+ mCubeFree[i] = false;
+ return i;
+ }
+ }
+
+ // no cubemaps free, steal one from the back of the probe list
+ for (int i = mProbes.size() - 1; i >= mReflectionProbeCount; --i)
+ {
+ if (mProbes[i]->mCubeIndex != -1)
+ {
+ S32 ret = mProbes[i]->mCubeIndex;
+ mProbes[i]->mCubeIndex = -1;
+ mProbes[i]->mCubeArray = nullptr;
+ return ret;
+ }
+ }
+
+ llassert(false); // should never fail to allocate, something is probably wrong with mCubeFree
+ return -1;
+}
+
+void LLReflectionMapManager::deleteProbe(U32 i)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+ LLReflectionMap* probe = mProbes[i];
+
+ llassert(probe != mDefaultProbe);
+
+ if (probe->mCubeIndex != -1)
+ { // mark the cube index used by this probe as being free
+ mCubeFree[probe->mCubeIndex] = true;
+ }
+ if (mUpdatingProbe == probe)
+ {
+ mUpdatingProbe = nullptr;
+ mUpdatingFace = 0;
+ }
+
+ // remove from any Neighbors lists
+ for (auto& other : probe->mNeighbors)
+ {
+ auto const & iter = std::find(other->mNeighbors.begin(), other->mNeighbors.end(), probe);
+ llassert(iter != other->mNeighbors.end());
+ other->mNeighbors.erase(iter);
+ }
+
+ mProbes.erase(mProbes.begin() + i);
+}
+
+
+void LLReflectionMapManager::doProbeUpdate()
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+ llassert(mUpdatingProbe != nullptr);
+
+ updateProbeFace(mUpdatingProbe, mUpdatingFace);
+
+ if (++mUpdatingFace == 6)
+ {
+ updateNeighbors(mUpdatingProbe);
+ mUpdatingFace = 0;
+ if (isRadiancePass())
+ {
+ 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
+ gPipeline.mRT = &gPipeline.mAuxillaryRT;
+
+ 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 sourceIdx = mReflectionProbeCount;
+
+ if (probe != mUpdatingProbe)
+ { // this is the "realtime" probe that's updating every frame, use the secondary scratch space channel
+ sourceIdx += 1;
+ }
+
+ gGL.setColorMask(true, true);
+ LLGLDepthTest depth(GL_FALSE, GL_FALSE);
+ LLGLDisable cull(GL_CULL_FACE);
+ LLGLDisable blend(GL_BLEND);
+
+ // downsample to placeholder map
+ {
+ gReflectionMipProgram.bind();
+
+ gGL.matrixMode(gGL.MM_MODELVIEW);
+ gGL.pushMatrix();
+ gGL.loadIdentity();
+
+ gGL.matrixMode(gGL.MM_PROJECTION);
+ gGL.pushMatrix();
+ gGL.loadIdentity();
+
+ gGL.flush();
+ U32 res = mProbeResolution * 2;
+
+ 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);
+
+ LLRenderTarget* screen_rt = &gPipeline.mAuxillaryRT.screen;
+ LLRenderTarget* depth_rt = &gPipeline.mAuxillaryRT.deferredScreen;
+
+ for (int i = 0; i < mMipChain.size(); ++i)
+ {
+ LL_PROFILE_GPU_ZONE("probe mip");
+ mMipChain[i].bindTarget();
+ if (i == 0)
+ {
+
+ gGL.getTexUnit(diffuseChannel)->bind(screen_rt);
+ }
+ else
+ {
+ gGL.getTexUnit(diffuseChannel)->bind(&(mMipChain[i - 1]));
+ }
+
+ gGL.getTexUnit(depthChannel)->bind(depth_rt, true);
+
+ static LLStaticHashedString resScale("resScale");
+ static LLStaticHashedString znear("znear");
+ static LLStaticHashedString zfar("zfar");
+
+ gReflectionMipProgram.uniform1f(resScale, (F32) (1 << i));
+ gReflectionMipProgram.uniform1f(znear, probe->getNearClip());
+ gReflectionMipProgram.uniform1f(zfar, MAX_FAR_CLIP);
+
+ gGL.begin(gGL.QUADS);
+
+ gGL.texCoord2f(0, 0);
+ gGL.vertex2f(-1, -1);
+
+ gGL.texCoord2f(1.f, 0);
+ gGL.vertex2f(1, -1);
+
+ gGL.texCoord2f(1.f, 1.f);
+ gGL.vertex2f(1, 1);
+
+ gGL.texCoord2f(0, 1.f);
+ gGL.vertex2f(-1, 1);
+ gGL.end();
+ gGL.flush();
+
+ res /= 2;
+
+ S32 mip = i - (mMipChain.size() - mips);
+
+ if (mip >= 0)
+ {
+ 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, 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);
+ //}
+ mTexture->unbind();
+ }
+ mMipChain[i].flush();
+ }
+
+ gGL.popMatrix();
+ gGL.matrixMode(gGL.MM_MODELVIEW);
+ gGL.popMatrix();
+
+ gGL.getTexUnit(diffuseChannel)->unbind(LLTexUnit::TT_TEXTURE);
+ gGL.getTexUnit(depthChannel)->unbind(LLTexUnit::TT_TEXTURE);
+ gReflectionMipProgram.unbind();
+ }
+
+ if (face == 5)
+ {
+ mMipChain[0].bindTarget();
+ static LLStaticHashedString sSourceIdx("sourceIdx");
+
+ if (isRadiancePass())
+ {
+ //generate radiance map (even if this is not the irradiance map, we need the mip chain for the irradiance map)
+ gRadianceGenProgram.bind();
+ mVertexBuffer->setBuffer();
+
+ 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);
+
+ U32 res = mMipChain[0].getWidth();
+
+ for (int i = 0; i < mMipChain.size(); ++i)
+ {
+ 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();
+ }
+ else
+ {
+ //generate irradiance map
+ gIrradianceGenProgram.bind();
+ S32 channel = gIrradianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY);
+ mTexture->bind(channel);
+
+ static LLCachedControl<F32> 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
+ for (start_mip = 0; start_mip < mMipChain.size(); ++start_mip)
+ {
+ 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]);
+
+ F32 mat[16];
+ frame.getOpenGLRotation(mat);
+ gGL.loadMatrix(mat);
+
+ 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);
+ }
+ }
+ }
+
+ mMipChain[0].flush();
+
+ gIrradianceGenProgram.unbind();
+ }
+}
+
+void LLReflectionMapManager::rebuild()
+{
+ for (auto& probe : mProbes)
+ {
+ probe->mLastUpdateTime = 0.f;
+ }
+}
+
+void LLReflectionMapManager::shift(const LLVector4a& offset)
+{
+ for (auto& probe : mProbes)
+ {
+ probe->mOrigin.add(offset);
+ }
+}
+
+void LLReflectionMapManager::updateNeighbors(LLReflectionMap* probe)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+ if (mDefaultProbe == probe)
+ {
+ return;
+ }
+
+ //remove from existing neighbors
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmun - clear");
+
+ for (auto& other : probe->mNeighbors)
+ {
+ auto const & iter = std::find(other->mNeighbors.begin(), other->mNeighbors.end(), probe);
+ llassert(iter != other->mNeighbors.end()); // <--- bug davep if this ever happens, something broke badly
+ other->mNeighbors.erase(iter);
+ }
+
+ probe->mNeighbors.clear();
+ }
+
+ // search for new neighbors
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmun - search");
+ for (auto& other : mProbes)
+ {
+ if (other != mDefaultProbe && other != probe)
+ {
+ if (probe->intersects(other))
+ {
+ probe->mNeighbors.push_back(other);
+ other->mNeighbors.push_back(probe);
+ }
+ }
+ }
+ }
+}
+
+void LLReflectionMapManager::updateUniforms()
+{
+ if (!LLPipeline::sReflectionProbesEnabled)
+ {
+ return;
+ }
+
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+
+ // structure for packing uniform buffer object
+ // see class3/deferred/reflectionProbeF.glsl
+ struct ReflectionProbeData
+ {
+ // 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);
+ getReflectionMaps(mReflectionMaps);
+
+ ReflectionProbeData rpd;
+
+ // load modelview matrix into matrix 4a
+ LLMatrix4a modelview;
+ modelview.loadu(gGLModelView);
+ LLVector4a oa; // scratch space for transformed origin
+
+ S32 count = 0;
+ U32 nc = 0; // neighbor "cursor" - index into refNeighbor to start writing the next probe's list of neighbors
+
+ LLEnvironment& environment = LLEnvironment::instance();
+ LLSettingsSky::ptr_t psky = environment.getCurrentSky();
+
+ F32 minimum_ambiance = psky->getTotalReflectionProbeAmbiance();
+ F32 ambscale = gCubeSnapshot && !isRadiancePass() ? 0.f : 1.f;
+
+
+ for (auto* refmap : mReflectionMaps)
+ {
+ if (refmap == nullptr)
+ {
+ break;
+ }
+
+ llassert(refmap->mProbeIndex == count);
+ llassert(mReflectionMaps[refmap->mProbeIndex] == refmap);
+
+ llassert(refmap->mCubeIndex >= 0); // should always be true, if not, getReflectionMaps is bugged
+
+ {
+ //LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmsu - refSphere");
+
+ modelview.affineTransform(refmap->mOrigin, oa);
+ rpd.refSphere[count].set(oa.getF32ptr());
+ rpd.refSphere[count].mV[3] = refmap->mRadius;
+ }
+
+ rpd.refIndex[count][0] = refmap->mCubeIndex;
+ llassert(nc % 4 == 0);
+ rpd.refIndex[count][1] = nc / 4;
+ rpd.refIndex[count][3] = refmap->mPriority;
+
+ // for objects that are reflection probes, use the volume as the influence volume of the probe
+ // only possibile influence volumes are boxes and spheres, so detect boxes and treat everything else as spheres
+ if (refmap->getBox(rpd.refBox[count]))
+ { // negate priority to indicate this probe has a box influence volume
+ rpd.refIndex[count][3] = -rpd.refIndex[count][3];
+ }
+
+ rpd.refParams[count].set(llmax(minimum_ambiance, refmap->getAmbiance())*ambscale, 0.f, 0.f, 0.f);
+
+ S32 ni = nc; // neighbor ("index") - index into refNeighbor to write indices for current reflection probe's neighbors
+ {
+ //LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmsu - refNeighbors");
+ //pack neghbor list
+ for (auto& neighbor : refmap->mNeighbors)
+ {
+ if (ni >= 4096)
+ { // out of space
+ break;
+ }
+
+ GLint idx = neighbor->mProbeIndex;
+ if (idx == -1)
+ {
+ continue;
+ }
+
+ // this neighbor may be sampled
+ rpd.refNeighbor[ni++] = idx;
+ }
+ }
+
+ if (nc == ni)
+ {
+ //no neighbors, tag as empty
+ rpd.refIndex[count][1] = -1;
+ }
+ else
+ {
+ rpd.refIndex[count][2] = ni - nc;
+
+ // move the cursor forward
+ nc = ni;
+ if (nc % 4 != 0)
+ { // jump to next power of 4 for compatibility with ivec4
+ nc += 4 - (nc % 4);
+ }
+ }
+
+
+ count++;
+ }
+
+ rpd.refmapCount = count;
+
+ //copy rpd into uniform buffer object
+ if (mUBO == 0)
+ {
+ glGenBuffers(1, &mUBO);
+ }
+
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmsu - update buffer");
+ glBindBuffer(GL_UNIFORM_BUFFER, mUBO);
+ glBufferData(GL_UNIFORM_BUFFER, sizeof(ReflectionProbeData), &rpd, GL_STREAM_DRAW);
+ glBindBuffer(GL_UNIFORM_BUFFER, 0);
+ }
+}
+
+void LLReflectionMapManager::setUniforms()
+{
+ if (!LLPipeline::sReflectionProbesEnabled)
+ {
+ return;
+ }
+
+ if (mUBO == 0)
+ {
+ updateUniforms();
+ }
+ glBindBufferBase(GL_UNIFORM_BUFFER, 1, mUBO);
+}
+
+
+void renderReflectionProbe(LLReflectionMap* probe)
+{
+ F32* po = probe->mOrigin.getF32ptr();
+
+ //draw orange line from probe to neighbors
+ gGL.flush();
+ gGL.diffuseColor4f(1, 0.5f, 0, 1);
+ gGL.begin(gGL.LINES);
+ for (auto& neighbor : probe->mNeighbors)
+ {
+ gGL.vertex3fv(po);
+ gGL.vertex3fv(neighbor->mOrigin.getF32ptr());
+ }
+ gGL.end();
+ gGL.flush();
+
+#if 0
+ LLSpatialGroup* group = probe->mGroup;
+ if (group)
+ { // draw lines from corners of object aabb to reflection probe
+
+ const LLVector4a* bounds = group->getBounds();
+ LLVector4a o = bounds[0];
+
+ gGL.flush();
+ gGL.diffuseColor4f(0, 0, 1, 1);
+ F32* c = o.getF32ptr();
+
+ const F32* bc = bounds[0].getF32ptr();
+ const F32* bs = bounds[1].getF32ptr();
+
+ // daaw blue lines from corners to center of node
+ gGL.begin(gGL.LINES);
+ gGL.vertex3fv(c);
+ gGL.vertex3f(bc[0] + bs[0], bc[1] + bs[1], bc[2] + bs[2]);
+ gGL.vertex3fv(c);
+ gGL.vertex3f(bc[0] - bs[0], bc[1] + bs[1], bc[2] + bs[2]);
+ gGL.vertex3fv(c);
+ gGL.vertex3f(bc[0] + bs[0], bc[1] - bs[1], bc[2] + bs[2]);
+ gGL.vertex3fv(c);
+ gGL.vertex3f(bc[0] - bs[0], bc[1] - bs[1], bc[2] + bs[2]);
+
+ gGL.vertex3fv(c);
+ gGL.vertex3f(bc[0] + bs[0], bc[1] + bs[1], bc[2] - bs[2]);
+ gGL.vertex3fv(c);
+ gGL.vertex3f(bc[0] - bs[0], bc[1] + bs[1], bc[2] - bs[2]);
+ gGL.vertex3fv(c);
+ gGL.vertex3f(bc[0] + bs[0], bc[1] - bs[1], bc[2] - bs[2]);
+ gGL.vertex3fv(c);
+ gGL.vertex3f(bc[0] - bs[0], bc[1] - bs[1], bc[2] - bs[2]);
+ gGL.end();
+
+ //draw yellow line from center of node to reflection probe origin
+ gGL.flush();
+ gGL.diffuseColor4f(1, 1, 0, 1);
+ gGL.begin(gGL.LINES);
+ gGL.vertex3fv(c);
+ gGL.vertex3fv(po);
+ gGL.end();
+ gGL.flush();
+ }
+#endif
+}
+
+void LLReflectionMapManager::renderDebug()
+{
+ gDebugProgram.bind();
+
+ for (auto& probe : mProbes)
+ {
+ renderReflectionProbe(probe);
+ }
+
+ gDebugProgram.unbind();
+}
+
+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(mProbeResolution, 4, mReflectionProbeCount + 2);
+
+ mIrradianceMaps = new LLCubeMapArray();
+ mIrradianceMaps->allocate(LL_IRRADIANCE_MAP_RESOLUTION, 4, mReflectionProbeCount, FALSE);
+ }
+
+ if (mVertexBuffer.isNull())
+ {
+ U32 mask = LLVertexBuffer::MAP_VERTEX;
+ LLPointer<LLVertexBuffer> buff = new LLVertexBuffer(mask);
+ buff->allocateBuffer(4, 0);
+
+ LLStrider<LLVector3> v;
+
+ buff->getVertexStrider(v);
+
+ v[0] = LLVector3(-1, -1, -1);
+ v[1] = LLVector3(1, -1, -1);
+ v[2] = LLVector3(-1, 1, -1);
+ v[3] = LLVector3(1, 1, -1);
+
+ buff->unmapBuffer();
+
+ mVertexBuffer = buff;
+ }
+}
+
+void LLReflectionMapManager::cleanup()
+{
+ mVertexBuffer = nullptr;
+ mRenderTarget.release();
+
+ mMipChain.clear();
+
+ mTexture = nullptr;
+ mIrradianceMaps = nullptr;
+
+ mProbes.clear();
+ mKillList.clear();
+ mCreateList.clear();
+
+ mReflectionMaps.clear();
+ mUpdatingFace = 0;
+
+ mDefaultProbe = nullptr;
+ mUpdatingProbe = nullptr;
+
+ glDeleteBuffers(1, &mUBO);
+ mUBO = 0;
+
+ // note: also called on teleport (not just shutdown), so make sure we're in a good "starting" state
+ initCubeFree();
+}
diff --git a/indra/newview/llreflectionmapmanager.h b/indra/newview/llreflectionmapmanager.h
new file mode 100644
index 0000000000..5936b26b88
--- /dev/null
+++ b/indra/newview/llreflectionmapmanager.h
@@ -0,0 +1,183 @@
+/**
+ * @file llreflectionmapmanager.h
+ * @brief LLReflectionMapManager class declaration
+ *
+ * $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$
+ */
+
+#pragma once
+
+#include "llreflectionmap.h"
+#include "llrendertarget.h"
+#include "llcubemaparray.h"
+#include "llcubemap.h"
+
+class LLSpatialGroup;
+class LLViewerObject;
+
+// number of reflection probes to keep in vram
+#define LL_MAX_REFLECTION_PROBE_COUNT 256
+
+// reflection probe resolution
+#define LL_IRRADIANCE_MAP_RESOLUTION 64
+
+// reflection probe mininum scale
+#define LL_REFLECTION_PROBE_MINIMUM_SCALE 1.f;
+
+class alignas(16) LLReflectionMapManager
+{
+ LL_ALIGN_NEW
+public:
+ enum class DetailLevel
+ {
+ STATIC_ONLY = 0,
+ STATIC_AND_DYNAMIC,
+ REALTIME = 2
+ };
+
+ // allocate an environment map of the given resolution
+ LLReflectionMapManager();
+
+ // release any GL state
+ void cleanup();
+
+ // maintain reflection probes
+ void update();
+
+ // add a probe for the given spatial group
+ LLReflectionMap* addProbe(LLSpatialGroup* group = nullptr);
+
+ // Populate "maps" with the N most relevant Reflection Maps where N is no more than maps.size()
+ // If less than maps.size() ReflectionMaps are available, will assign trailing elements to nullptr.
+ // maps -- presized array of Reflection Map pointers
+ void getReflectionMaps(std::vector<LLReflectionMap*>& maps);
+
+ // called by LLSpatialGroup constructor
+ // If spatial group should receive a Reflection Probe, will create one for the specified spatial group
+ LLReflectionMap* registerSpatialGroup(LLSpatialGroup* group);
+
+ // presently hacked into LLViewerObject::setTE
+ // Used by LLViewerObjects that are Reflection Probes
+ // Guaranteed to not return null
+ LLReflectionMap* registerViewerObject(LLViewerObject* vobj);
+
+ // force an update of all probes
+ void rebuild();
+
+ // called on region crossing to "shift" probes into new coordinate frame
+ void shift(const LLVector4a& offset);
+
+ // debug display, called from llspatialpartition if reflection
+ // probe debug display is active
+ void renderDebug();
+
+ // 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;
+
+ // initialize mCubeFree array to default values
+ void initCubeFree();
+
+ // delete the probe with the given index in mProbes
+ void deleteProbe(U32 i);
+
+ // get a free cube index
+ // if no cube indices are free, free one starting from the back of the probe list
+ S32 allocateCubeIndex();
+
+ // update the neighbors of the given probe
+ void updateNeighbors(LLReflectionMap* probe);
+
+ // update UBO used for rendering (call only once per render pipe flush)
+ void updateUniforms();
+
+ // bind UBO used for rendering
+ void setUniforms();
+
+ // render target for cube snapshots
+ // used to generate mipmaps without doing a copy-to-texture
+ LLRenderTarget mRenderTarget;
+
+ std::vector<LLRenderTarget> mMipChain;
+
+ // storage for reflection probe radiance maps (plus two scratch space cubemaps)
+ LLPointer<LLCubeMapArray> mTexture;
+
+ // vertex buffer for pushing verts to filter shaders
+ LLPointer<LLVertexBuffer> mVertexBuffer;
+
+ // storage for reflection probe irradiance maps
+ LLPointer<LLCubeMapArray> mIrradianceMaps;
+
+ // array indicating if a particular cubemap is free
+ bool mCubeFree[LL_MAX_REFLECTION_PROBE_COUNT];
+
+ // start tracking the given spatial group
+ void trackGroup(LLSpatialGroup* group);
+
+ // perform an update on the currently updating Probe
+ void doProbeUpdate();
+
+ // update the specified face of the specified probe
+ void updateProbeFace(LLReflectionMap* probe, U32 face);
+
+ // list of active reflection maps
+ std::vector<LLPointer<LLReflectionMap> > mProbes;
+
+ // list of reflection maps to kill
+ std::vector<LLPointer<LLReflectionMap> > mKillList;
+
+ // list of reflection maps to create
+ std::vector<LLPointer<LLReflectionMap> > mCreateList;
+
+ // handle to UBO
+ U32 mUBO = 0;
+
+ // list of maps being used for rendering
+ std::vector<LLReflectionMap*> mReflectionMaps;
+
+ 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<LLReflectionMap> 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/llscenemonitor.cpp b/indra/newview/llscenemonitor.cpp
index 7089df677e..8d86e2de4c 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);
}
@@ -445,14 +445,14 @@ void LLSceneMonitor::calcDiffAggregate()
if(mDiffState == EXECUTE_DIFF)
{
- glBeginQueryARB(GL_SAMPLES_PASSED_ARB, mQueryObject);
+ glBeginQuery(GL_SAMPLES_PASSED, mQueryObject);
}
gl_draw_scaled_target(0, 0, S32(mDiff->getWidth() * mDiffPixelRatio), S32(mDiff->getHeight() * mDiffPixelRatio), mDiff);
if(mDiffState == EXECUTE_DIFF)
{
- glEndQueryARB(GL_SAMPLES_PASSED_ARB);
+ glEndQuery(GL_SAMPLES_PASSED);
mDiffState = WAIT_ON_RESULT;
}
@@ -483,11 +483,11 @@ void LLSceneMonitor::fetchQueryResult()
mDiffState = WAITING_FOR_NEXT_DIFF;
GLuint available = 0;
- glGetQueryObjectuivARB(mQueryObject, GL_QUERY_RESULT_AVAILABLE_ARB, &available);
+ glGetQueryObjectuiv(mQueryObject, GL_QUERY_RESULT_AVAILABLE, &available);
if(available)
{
GLuint count = 0;
- glGetQueryObjectuivARB(mQueryObject, GL_QUERY_RESULT_ARB, &count);
+ glGetQueryObjectuiv(mQueryObject, GL_QUERY_RESULT, &count);
mDiffResult = sqrtf(count * 0.5f / (mDiff->getWidth() * mDiff->getHeight() * mDiffPixelRatio * mDiffPixelRatio)); //0.5 -> (front face + back face)
diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
index 86f7d2bf25..02e85d7470 100644
--- a/indra/newview/llselectmgr.cpp
+++ b/indra/newview/llselectmgr.cpp
@@ -63,6 +63,7 @@
#include "llfloatertools.h"
#include "llframetimer.h"
#include "llfocusmgr.h"
+#include "llgltfmateriallist.h"
#include "llhudeffecttrail.h"
#include "llhudmanager.h"
#include "llinventorymodel.h"
@@ -1038,10 +1039,6 @@ void LLSelectMgr::addAsIndividual(LLViewerObject *objectp, S32 face, BOOL undoab
// check to see if object is already in list
LLSelectNode *nodep = mSelectedObjects->findNode(objectp);
- // Reset (in anticipation of being set to an appropriate value by panel refresh, if they're up)
- //
- setTextureChannel(LLRender::DIFFUSE_MAP);
-
// if not in list, add it
if (!nodep)
{
@@ -1168,8 +1165,8 @@ void LLSelectMgr::highlightObjectOnly(LLViewerObject* objectp)
return;
}
- if ((gSavedSettings.getBOOL("SelectOwnedOnly") && !objectp->permYouOwner())
- || (gSavedSettings.getBOOL("SelectMovableOnly") && (!objectp->permMove() || objectp->isPermanentEnforced())))
+ if ((gSavedSettings.getBOOL("SelectOwnedOnly") && !objectp->permYouOwner())
+ || (gSavedSettings.getBOOL("SelectMovableOnly") && (!objectp->permMove() || objectp->isPermanentEnforced())))
{
// only select my own objects
return;
@@ -1746,6 +1743,7 @@ void LLObjectSelection::applyNoCopyTextureToTEs(LLViewerInventoryItem* item)
S32 num_tes = llmin((S32)object->getNumTEs(), (S32)object->getNumFaces());
bool texture_copied = false;
+ bool updated = false;
for (S32 te = 0; te < num_tes; ++te)
{
if (node->isTESelected(te))
@@ -1754,22 +1752,71 @@ void LLObjectSelection::applyNoCopyTextureToTEs(LLViewerInventoryItem* item)
// without making any copies
if (!texture_copied)
{
- LLToolDragAndDrop::handleDropTextureProtections(object, item, LLToolDragAndDrop::SOURCE_AGENT, LLUUID::null);
+ LLToolDragAndDrop::handleDropMaterialProtections(object, item, LLToolDragAndDrop::SOURCE_AGENT, LLUUID::null);
texture_copied = true;
}
// apply texture for the selected faces
add(LLStatViewer::EDIT_TEXTURE, 1);
object->setTEImage(te, image);
- dialog_refresh_all();
-
- // send the update to the simulator
- object->sendTEUpdate();
+ updated = true;
}
}
+
+ if (updated) // not nessesary? sendTEUpdate update supposed to be done by sendfunc
+ {
+ dialog_refresh_all();
+
+ // send the update to the simulator
+ object->sendTEUpdate();
+ }
}
}
+void LLObjectSelection::applyNoCopyPbrMaterialToTEs(LLViewerInventoryItem* item)
+{
+ if (!item)
+ {
+ return;
+ }
+
+ LLUUID asset_id = item->getAssetUUID();
+
+ for (iterator iter = begin(); iter != end(); ++iter)
+ {
+ LLSelectNode* node = *iter;
+ LLViewerObject* object = (*iter)->getObject();
+ if (!object)
+ {
+ continue;
+ }
+
+ S32 num_tes = llmin((S32)object->getNumTEs(), (S32)object->getNumFaces());
+ bool material_copied = false;
+ for (S32 te = 0; te < num_tes; ++te)
+ {
+ if (node->isTESelected(te))
+ {
+ //(no-copy) materials must be moved to the object's inventory only once
+ // without making any copies
+ if (!material_copied && asset_id.notNull())
+ {
+ LLToolDragAndDrop::handleDropMaterialProtections(object, item, LLToolDragAndDrop::SOURCE_AGENT, LLUUID::null);
+ material_copied = true;
+ }
+
+ // apply texture for the selected faces
+ // blank out most override data on the server
+ //add(LLStatViewer::EDIT_TEXTURE, 1);
+ object->setRenderMaterialID(te, asset_id);
+ }
+ }
+ }
+
+ LLGLTFMaterialList::flushUpdates();
+}
+
+
//-----------------------------------------------------------------------------
// selectionSetImage()
//-----------------------------------------------------------------------------
@@ -1862,6 +1909,112 @@ void LLSelectMgr::selectionSetImage(const LLUUID& imageid)
}
//-----------------------------------------------------------------------------
+// selectionSetGLTFMaterial()
+//-----------------------------------------------------------------------------
+void LLSelectMgr::selectionSetGLTFMaterial(const LLUUID& mat_id)
+{
+ // First for (no copy) textures and multiple object selection
+ LLViewerInventoryItem* item = gInventory.getItem(mat_id);
+ if (item
+ && !item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID())
+ && (mSelectedObjects->getNumNodes() > 1))
+ {
+ LL_WARNS() << "Attempted to apply no-copy material to multiple objects"
+ << LL_ENDL;
+ return;
+ }
+
+ struct f : public LLSelectedTEFunctor
+ {
+ LLViewerInventoryItem* mItem;
+ LLUUID mMatId;
+ f(LLViewerInventoryItem* item, const LLUUID& id) : mItem(item), mMatId(id) {}
+ bool apply(LLViewerObject* objectp, S32 te)
+ {
+ if (objectp && !objectp->permModify())
+ {
+ return false;
+ }
+ LLUUID asset_id = mMatId;
+ if (mItem)
+ {
+ asset_id = mItem->getAssetUUID();
+ }
+
+ if (asset_id.notNull() && !objectp->hasRenderMaterialParams())
+ {
+ // make sure param section exists
+ objectp->setParameterEntryInUse(LLNetworkData::PARAMS_RENDER_MATERIAL, TRUE, false /*prevent an update*/);
+ }
+
+ // Blank out most override data on the object and send to server
+ objectp->setRenderMaterialID(te, asset_id);
+
+ return true;
+ }
+ };
+
+ if (item && !item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID()))
+ {
+ getSelection()->applyNoCopyPbrMaterialToTEs(item);
+ }
+ else
+ {
+ f setfunc(item, mat_id);
+ getSelection()->applyToTEs(&setfunc);
+ }
+
+ struct g : public LLSelectedObjectFunctor
+ {
+ LLViewerInventoryItem* mItem;
+ g(LLViewerInventoryItem* item) : mItem(item) {}
+ virtual bool apply(LLViewerObject* object)
+ {
+ if (object && !object->permModify())
+ {
+ return false;
+ }
+
+ LLRenderMaterialParams* param_block = (LLRenderMaterialParams*)object->getParameterEntry(LLNetworkData::PARAMS_RENDER_MATERIAL);
+ if (param_block)
+ {
+ // To not cause multiple competing request that modify
+ // same param field send update only once per object
+ if (param_block->isEmpty())
+ {
+ object->setHasRenderMaterialParams(false);
+ }
+ else if (object->hasRenderMaterialParams())
+ {
+ object->parameterChanged(LLNetworkData::PARAMS_RENDER_MATERIAL, true);
+ }
+ else
+ {
+ object->setHasRenderMaterialParams(true);
+ }
+ }
+
+ if (!mItem)
+ {
+ // 1 particle effect per object
+ LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE);
+ effectp->setSourceObject(gAgentAvatarp);
+ effectp->setTargetObject(object);
+ effectp->setDuration(LL_HUD_DUR_SHORT);
+ effectp->setColor(LLColor4U(gAgent.getEffectColor()));
+ }
+
+ dialog_refresh_all();
+ object->sendTEUpdate();
+ return true;
+ }
+ } sendfunc(item);
+ getSelection()->applyToObjects(&sendfunc);
+
+ LLGLTFMaterialList::flushUpdates();
+}
+
+//-----------------------------------------------------------------------------
// selectionSetColor()
//-----------------------------------------------------------------------------
void LLSelectMgr::selectionSetColor(const LLColor4 &color)
@@ -2038,6 +2191,81 @@ BOOL LLSelectMgr::selectionRevertTextures()
return revert_successful;
}
+void LLSelectMgr::selectionRevertGLTFMaterials()
+{
+ struct f : public LLSelectedTEFunctor
+ {
+ LLObjectSelectionHandle mSelectedObjects;
+ f(LLObjectSelectionHandle sel) : mSelectedObjects(sel) {}
+ bool apply(LLViewerObject* objectp, S32 te)
+ {
+ if (objectp && !objectp->permModify())
+ {
+ return false;
+ }
+
+ LLSelectNode* nodep = mSelectedObjects->findNode(objectp);
+ if (nodep && te < (S32)nodep->mSavedGLTFMaterialIds.size())
+ {
+ // Restore base material
+ LLUUID asset_id = nodep->mSavedGLTFMaterialIds[te];
+ objectp->setRenderMaterialID(te, asset_id, false /*wait for bulk update*/);
+
+
+ // todo: make sure this does not cause race condition with setRenderMaterialID
+ // when we are reverting from null id to non null plus override
+ if (te < (S32)nodep->mSavedGLTFOverrideMaterials.size()
+ && nodep->mSavedGLTFOverrideMaterials[te].notNull()
+ && asset_id.notNull())
+ {
+ // Restore overrides
+ LLGLTFMaterialList::queueModify(objectp, te, nodep->mSavedGLTFOverrideMaterials[te]);
+ }
+ else
+ {
+ //blank override out
+ LLGLTFMaterialList::queueApply(objectp, te, asset_id);
+ }
+
+ }
+ return true;
+ }
+ } setfunc(mSelectedObjects);
+ getSelection()->applyToTEs(&setfunc);
+
+ struct g : public LLSelectedObjectFunctor
+ {
+ virtual bool apply(LLViewerObject* object)
+ {
+ if (object && !object->permModify())
+ {
+ return false;
+ }
+
+ LLRenderMaterialParams* param_block = (LLRenderMaterialParams*)object->getParameterEntry(LLNetworkData::PARAMS_RENDER_MATERIAL);
+ if (param_block)
+ {
+ if (param_block->isEmpty())
+ {
+ object->setHasRenderMaterialParams(false);
+ }
+ else if (object->hasRenderMaterialParams())
+ {
+ object->parameterChanged(LLNetworkData::PARAMS_RENDER_MATERIAL, true);
+ }
+ else
+ {
+ object->setHasRenderMaterialParams(true);
+ }
+ }
+
+ object->sendTEUpdate();
+ return true;
+ }
+ } sendfunc;
+ getSelection()->applyToObjects(&sendfunc);
+}
+
void LLSelectMgr::selectionSetBumpmap(U8 bumpmap, const LLUUID &image_id)
{
struct f : public LLSelectedTEFunctor
@@ -2067,7 +2295,7 @@ void LLSelectMgr::selectionSetBumpmap(U8 bumpmap, const LLUUID &image_id)
{
LLViewerObject *object = mSelectedObjects->getFirstRootObject();
if (!object) return;
- LLToolDragAndDrop::handleDropTextureProtections(object, item, LLToolDragAndDrop::SOURCE_AGENT, LLUUID::null);
+ LLToolDragAndDrop::handleDropMaterialProtections(object, item, LLToolDragAndDrop::SOURCE_AGENT, LLUUID::null);
}
getSelection()->applyToTEs(&setfunc);
@@ -2127,7 +2355,7 @@ void LLSelectMgr::selectionSetShiny(U8 shiny, const LLUUID &image_id)
{
LLViewerObject *object = mSelectedObjects->getFirstRootObject();
if (!object) return;
- LLToolDragAndDrop::handleDropTextureProtections(object, item, LLToolDragAndDrop::SOURCE_AGENT, LLUUID::null);
+ LLToolDragAndDrop::handleDropMaterialProtections(object, item, LLToolDragAndDrop::SOURCE_AGENT, LLUUID::null);
}
getSelection()->applyToTEs(&setfunc);
@@ -5625,9 +5853,40 @@ void LLSelectMgr::processObjectProperties(LLMessageSystem* msg, void** user_data
if (can_copy && can_transfer)
{
- // this should be the only place that saved textures is called
node->saveTextures(texture_ids);
}
+
+ if (can_copy && can_transfer && node->getObject()->getVolume())
+ {
+ uuid_vec_t material_ids;
+ gltf_materials_vec_t materials;
+ LLVOVolume* vobjp = (LLVOVolume*)node->getObject();
+ for (int i = 0; i < vobjp->getNumTEs(); ++i)
+ {
+ material_ids.push_back(vobjp->getRenderMaterialID(i));
+
+ // Make a copy to ensure we won't affect live material
+ // with any potential changes nor live changes will be
+ // reflected in a saved copy.
+ // Like changes from local material (reuses pointer) or
+ // from live editor (revert mechanics might modify this)
+ LLGLTFMaterial* old_override = node->getObject()->getTE(i)->getGLTFMaterialOverride();
+ if (old_override)
+ {
+ LLPointer<LLGLTFMaterial> mat = new LLGLTFMaterial(*old_override);
+ materials.push_back(mat);
+ }
+ else
+ {
+ materials.push_back(nullptr);
+ }
+ }
+ node->saveGLTFMaterialIds(material_ids);
+
+ // processObjectProperties does not include overrides so this
+ // might need to be moved to LLGLTFMaterialOverrideDispatchHandler
+ node->saveGLTFOverrideMaterials(materials);
+ }
}
node->mValid = TRUE;
@@ -6094,7 +6353,7 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud)
auto renderMeshSelection_f = [fogCfx, wireframe_selection](LLSelectNode* node, LLViewerObject* objectp, LLColor4 hlColor)
{
//Need to because crash on ATI 3800 (and similar cards) MAINT-5018
- LLGLDisable multisample(LLPipeline::RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
+ LLGLDisable multisample(LLPipeline::RenderFSAASamples > 0 ? GL_MULTISAMPLE : 0);
LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
@@ -6379,6 +6638,8 @@ LLSelectNode::LLSelectNode(const LLSelectNode& nodep)
}
saveTextures(nodep.mSavedTextures);
+ saveGLTFMaterialIds(nodep.mSavedGLTFMaterialIds);
+ saveGLTFOverrideMaterials(nodep.mSavedGLTFOverrideMaterials);
}
LLSelectNode::~LLSelectNode()
@@ -6512,6 +6773,34 @@ void LLSelectNode::saveTextures(const uuid_vec_t& textures)
}
}
+void LLSelectNode::saveGLTFMaterialIds(const uuid_vec_t& materials)
+{
+ if (mObject.notNull())
+ {
+ mSavedGLTFMaterialIds.clear();
+
+ for (uuid_vec_t::const_iterator materials_it = materials.begin();
+ materials_it != materials.end(); ++materials_it)
+ {
+ mSavedGLTFMaterialIds.push_back(*materials_it);
+ }
+ }
+}
+
+void LLSelectNode::saveGLTFOverrideMaterials(const gltf_materials_vec_t& materials)
+{
+ if (mObject.notNull())
+ {
+ mSavedGLTFOverrideMaterials.clear();
+
+ for (gltf_materials_vec_t::const_iterator mat_it = materials.begin();
+ mat_it != materials.end(); ++mat_it)
+ {
+ mSavedGLTFOverrideMaterials.push_back(*mat_it);
+ }
+ }
+}
+
void LLSelectNode::saveTextureScaleRatios(LLRender::eTexIndex index_to_query)
{
mTextureScaleRatios.clear();
@@ -6731,15 +7020,8 @@ void LLSelectNode::renderOneSilhouette(const LLColor4 &color)
{
gGL.flush();
gGL.blendFunc(LLRender::BF_SOURCE_COLOR, LLRender::BF_ONE);
- LLGLEnable fog(GL_FOG);
- glFogi(GL_FOG_MODE, GL_LINEAR);
- float d = (LLViewerCamera::getInstance()->getPointOfInterest()-LLViewerCamera::getInstance()->getOrigin()).magVec();
- LLColor4 fogCol = color * (F32)llclamp((LLSelectMgr::getInstance()->getSelectionCenterGlobal()-gAgentCamera.getCameraPositionGlobal()).magVec()/(LLSelectMgr::getInstance()->getBBoxOfSelection().getExtentLocal().magVec()*4), 0.0, 1.0);
- glFogf(GL_FOG_START, d);
- glFogf(GL_FOG_END, d*(1 + (LLViewerCamera::getInstance()->getView() / LLViewerCamera::getInstance()->getDefaultFOV())));
- glFogfv(GL_FOG_COLOR, fogCol.mV);
-
- LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_GEQUAL);
+
+ LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_GEQUAL);
gGL.flush();
gGL.begin(LLRender::LINES);
{
@@ -8307,6 +8589,7 @@ DEF_DUMMY_CHECK_FUNCTOR(int)
DEF_DUMMY_CHECK_FUNCTOR(LLColor4)
DEF_DUMMY_CHECK_FUNCTOR(LLMediaEntry)
DEF_DUMMY_CHECK_FUNCTOR(LLPointer<LLMaterial>)
+DEF_DUMMY_CHECK_FUNCTOR(LLPointer<LLGLTFMaterial>)
DEF_DUMMY_CHECK_FUNCTOR(std::string)
DEF_DUMMY_CHECK_FUNCTOR(std::vector<std::string>)
diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h
index 199141fc32..3ee78f9a58 100644
--- a/indra/newview/llselectmgr.h
+++ b/indra/newview/llselectmgr.h
@@ -161,6 +161,8 @@ typedef enum e_selection_type
SELECT_TYPE_HUD
}ESelectType;
+typedef std::vector<LLPointer<LLGLTFMaterial> > gltf_materials_vec_t;
+
const S32 TE_SELECT_MASK_ALL = 0xFFFFFFFF;
// Contains information about a selected object, particularly which TEs are selected.
@@ -184,11 +186,20 @@ public:
LLViewerObject* getObject();
void setObject(LLViewerObject* object);
// *NOTE: invalidate stored textures and colors when # faces change
+ // Used by tools floater's color/texture pickers to restore changes
void saveColors();
void saveShinyColors();
void saveTextures(const uuid_vec_t& textures);
void saveTextureScaleRatios(LLRender::eTexIndex index_to_query);
+ // GLTF materials are applied to objects by ids,
+ // overrides get applied on top of materials resulting in
+ // final gltf material that users see.
+ // Ids get applied and restored by tools floater,
+ // overrides get applied in live material editor
+ void saveGLTFMaterialIds(const uuid_vec_t& materials);
+ void saveGLTFOverrideMaterials(const gltf_materials_vec_t& materials);
+
BOOL allowOperationOnNode(PermissionBit op, U64 group_proxy_power) const;
public:
@@ -224,6 +235,8 @@ public:
std::vector<LLColor4> mSavedColors;
std::vector<LLColor4> mSavedShinyColors;
uuid_vec_t mSavedTextures;
+ uuid_vec_t mSavedGLTFMaterialIds;
+ gltf_materials_vec_t mSavedGLTFOverrideMaterials;
std::vector<LLVector3> mTextureScaleRatios;
std::vector<LLVector3> mSilhouetteVertices; // array of vertices to render silhouette of object
std::vector<LLVector3> mSilhouetteNormals; // array of normals to render silhouette of object
@@ -366,6 +379,7 @@ public:
* Then this only texture is used for all selected faces.
*/
void applyNoCopyTextureToTEs(LLViewerInventoryItem* item);
+ void applyNoCopyPbrMaterialToTEs(LLViewerInventoryItem* item);
ESelectType getSelectType() const { return mSelectType; }
@@ -605,11 +619,6 @@ public:
void saveSelectedShinyColors();
void saveSelectedObjectTextures();
- // Sets which texture channel to query for scale and rot of display
- // and depends on UI state of LLPanelFace when editing
- void setTextureChannel(LLRender::eTexIndex texIndex) { mTextureChannel = texIndex; }
- LLRender::eTexIndex getTextureChannel() { return mTextureChannel; }
-
void selectionUpdatePhysics(BOOL use_physics);
void selectionUpdateTemporary(BOOL is_temporary);
void selectionUpdatePhantom(BOOL is_ghost);
@@ -627,12 +636,14 @@ public:
void selectionSetRestitution(F32 restitution);
void selectionSetMaterial(U8 material);
void selectionSetImage(const LLUUID& imageid); // could be item or asset id
+ void selectionSetGLTFMaterial(const LLUUID& mat_id); // could be item or asset id
void selectionSetColor(const LLColor4 &color);
void selectionSetColorOnly(const LLColor4 &color); // Set only the RGB channels
void selectionSetAlphaOnly(const F32 alpha); // Set only the alpha channel
void selectionRevertColors();
void selectionRevertShinyColors();
BOOL selectionRevertTextures();
+ void selectionRevertGLTFMaterials();
void selectionSetBumpmap( U8 bumpmap, const LLUUID &image_id );
void selectionSetTexGen( U8 texgen );
void selectionSetShiny( U8 shiny, const LLUUID &image_id );
diff --git a/indra/newview/llsettingsvo.cpp b/indra/newview/llsettingsvo.cpp
index 707b602fc6..fd27c83270 100644
--- a/indra/newview/llsettingsvo.cpp
+++ b/indra/newview/llsettingsvo.cpp
@@ -68,6 +68,8 @@
#undef VERIFY_LEGACY_CONVERSION
+extern BOOL gCubeSnapshot;
+
//=========================================================================
namespace
{
@@ -123,7 +125,7 @@ void LLSettingsVOBase::createNewInventoryItem(LLSettingsType::type_e stype, cons
void LLSettingsVOBase::createInventoryItem(const LLSettingsBase::ptr_t &settings, const LLUUID &parent_id, std::string settings_name, inventory_result_fn callback)
{
- U32 nextOwnerPerm = LLPermissions::DEFAULT.getMaskNextOwner();
+ U32 nextOwnerPerm = LLFloaterPerms::getNextOwnerPerms("Settings");
createInventoryItem(settings, nextOwnerPerm, parent_id, settings_name, callback);
}
@@ -234,9 +236,11 @@ void LLSettingsVOBase::updateInventoryItem(const LLSettingsBase::ptr_t &settings
LLSDSerialize::serialize(settingdata, buffer, LLSDSerialize::LLSD_NOTATION);
LLResourceUploadInfo::ptr_t uploadInfo = std::make_shared<LLBufferedAssetUploadInfo>(inv_item_id, LLAssetType::AT_SETTINGS, buffer.str(),
- [settings, callback](LLUUID itemId, LLUUID newAssetId, LLUUID newItemId, LLSD response) {
+ [settings, callback](LLUUID itemId, LLUUID newAssetId, LLUUID newItemId, LLSD response)
+ {
LLSettingsVOBase::onAgentAssetUploadComplete(itemId, newAssetId, newItemId, response, settings, callback);
- });
+ },
+ nullptr);
LLViewerAssetUpload::EnqueueInventoryUpload(agent_url, uploadInfo);
}
@@ -265,9 +269,11 @@ void LLSettingsVOBase::updateInventoryItem(const LLSettingsBase::ptr_t &settings
LLSDSerialize::serialize(settingdata, buffer, LLSDSerialize::LLSD_NOTATION);
LLResourceUploadInfo::ptr_t uploadInfo = std::make_shared<LLBufferedAssetUploadInfo>(object_id, inv_item_id, LLAssetType::AT_SETTINGS, buffer.str(),
- [settings, callback](LLUUID itemId, LLUUID taskId, LLUUID newAssetId, LLSD response) {
- LLSettingsVOBase::onTaskAssetUploadComplete(itemId, taskId, newAssetId, response, settings, callback);
- });
+ [settings, callback](LLUUID itemId, LLUUID taskId, LLUUID newAssetId, LLSD response)
+ {
+ LLSettingsVOBase::onTaskAssetUploadComplete(itemId, taskId, newAssetId, response, settings, callback);
+ },
+ nullptr);
LLViewerAssetUpload::EnqueueInventoryUpload(agent_url, uploadInfo);
}
@@ -667,54 +673,75 @@ void LLSettingsVOSky::updateSettings()
void LLSettingsVOSky::applySpecial(void *ptarget, bool force)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
- LLVector4 light_direction = LLEnvironment::instance().getClampedLightNorm();
+ LLVector3 light_direction = LLVector3(LLEnvironment::instance().getClampedLightNorm().mV);
+
+ bool radiance_pass = gCubeSnapshot && !gPipeline.mReflectionMapManager.isRadiancePass();
LLShaderUniforms* shader = &((LLShaderUniforms*)ptarget)[LLGLSLShader::SG_DEFAULT];
{
- shader->uniform4fv(LLViewerShaderMgr::LIGHTNORM, light_direction);
+ shader->uniform3fv(LLViewerShaderMgr::LIGHTNORM, light_direction);
shader->uniform3fv(LLShaderMgr::WL_CAMPOSLOCAL, LLViewerCamera::getInstance()->getOrigin());
}
shader = &((LLShaderUniforms*)ptarget)[LLGLSLShader::SG_SKY];
- {
- shader->uniform4fv(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->uniform4fv(LLShaderMgr::CLOUD_POS_DENSITY1, vect_c_p_d1);
+ // 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));
- LLVector4 sunDiffuse = LLVector4(LLVector3(psky->getSunlightColor().mV));
- LLVector4 moonDiffuse = LLVector4(LLVector3(psky->getMoonlightColor().mV));
+ LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky();
- shader->uniform4fv(LLShaderMgr::SUNLIGHT_COLOR, sunDiffuse);
- shader->uniform4fv(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));
- LLVector4 cloud_color(LLVector3(psky->getCloudColor().mV), 1.0);
- shader->uniform4fv(LLShaderMgr::CLOUD_COLOR, cloud_color);
- }
-
shader = &((LLShaderUniforms*)ptarget)[LLGLSLShader::SG_ANY];
shader->uniform1f(LLShaderMgr::SCENE_LIGHT_STRENGTH, mSceneLightStrength);
- LLColor4 ambient(getTotalAmbient());
- shader->uniform4fv(LLShaderMgr::AMBIENT, LLVector4(ambient.mV));
+ LLColor3 ambient(getTotalAmbient());
+
+ shader->uniform3fv(LLShaderMgr::AMBIENT, LLVector3(ambient.mV));
+
+ 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);
+ }
+ 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(sunDiffuse));
+ shader->uniform3fv(LLShaderMgr::MOONLIGHT_LINEAR,linearColor3v(moonDiffuse));
+
+ shader->uniform1f(LLShaderMgr::REFLECTION_PROBE_AMBIANCE, getTotalReflectionProbeAmbiance());
shader->uniform1i(LLShaderMgr::SUN_UP_FACTOR, getIsSunUp() ? 1 : 0);
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");
@@ -758,6 +785,7 @@ LLSettingsSky::parammapping_t LLSettingsVOSky::getParameterMap() const
param_map[SETTING_SKY_DROPLET_RADIUS] = DefaultParam(LLShaderMgr::DROPLET_RADIUS, sky_defaults[SETTING_SKY_DROPLET_RADIUS]);
param_map[SETTING_SKY_ICE_LEVEL] = DefaultParam(LLShaderMgr::ICE_LEVEL, sky_defaults[SETTING_SKY_ICE_LEVEL]);
+ param_map[SETTING_REFLECTION_PROBE_AMBIANCE] = DefaultParam(LLShaderMgr::REFLECTION_PROBE_AMBIANCE, sky_defaults[SETTING_REFLECTION_PROBE_AMBIANCE]);
// AdvancedAtmospherics TODO
// Provide mappings for new shader params here
}
@@ -939,6 +967,8 @@ void LLSettingsVOWater::applySpecial(void *ptarget, bool force)
LLVector4 waterPlane(enorm.v[0], enorm.v[1], enorm.v[2], -ep.dot(enorm));
+ LLDrawPoolAlpha::sWaterPlane = waterPlane;
+
shader->uniform4fv(LLShaderMgr::WATER_WATERPLANE, waterPlane.mV);
LLVector4 light_direction = env.getClampedLightNorm();
@@ -953,14 +983,16 @@ void LLSettingsVOWater::applySpecial(void *ptarget, bool force)
F32 waterFogDensity = env.getCurrentWater()->getModifiedWaterFogDensity(underwater);
shader->uniform1f(LLShaderMgr::WATER_FOGDENSITY, waterFogDensity);
- LLColor4 fog_color(env.getCurrentWater()->getWaterFogColor(), 0.0f);
+ LLColor4 fog_color(env.getCurrentWater()->getWaterFogColor());
shader->uniform4fv(LLShaderMgr::WATER_FOGCOLOR, fog_color.mV);
+ shader->uniform3fv(LLShaderMgr::WATER_FOGCOLOR_LINEAR, linearColor3(fog_color).mV);
+
F32 blend_factor = env.getCurrentWater()->getBlendFactor();
shader->uniform1f(LLShaderMgr::BLEND_FACTOR, blend_factor);
// update to normal lightnorm, water shader itself will use rotated lightnorm as necessary
- shader->uniform4fv(LLShaderMgr::LIGHTNORM, light_direction.mV);
+ shader->uniform3fv(LLShaderMgr::LIGHTNORM, light_direction.mV);
}
}
diff --git a/indra/newview/llsidepaneltaskinfo.cpp b/indra/newview/llsidepaneltaskinfo.cpp
index 7fa06f51e3..6216057c17 100644
--- a/indra/newview/llsidepaneltaskinfo.cpp
+++ b/indra/newview/llsidepaneltaskinfo.cpp
@@ -77,7 +77,7 @@ static LLPanelInjector<LLSidepanelTaskInfo> t_task_info("sidepanel_task_info");
LLSidepanelTaskInfo::LLSidepanelTaskInfo()
{
setMouseOpaque(FALSE);
- LLSelectMgr::instance().mUpdateSignal.connect(boost::bind(&LLSidepanelTaskInfo::refreshAll, this));
+ mSelectionUpdateSlot = LLSelectMgr::instance().mUpdateSignal.connect(boost::bind(&LLSidepanelTaskInfo::refreshAll, this));
}
@@ -85,6 +85,11 @@ LLSidepanelTaskInfo::~LLSidepanelTaskInfo()
{
if (sActivePanel == this)
sActivePanel = NULL;
+
+ if (mSelectionUpdateSlot.connected())
+ {
+ mSelectionUpdateSlot.disconnect();
+ }
}
// virtual
diff --git a/indra/newview/llsidepaneltaskinfo.h b/indra/newview/llsidepaneltaskinfo.h
index dc259cb22d..ac9c57f2e2 100644
--- a/indra/newview/llsidepaneltaskinfo.h
+++ b/indra/newview/llsidepaneltaskinfo.h
@@ -154,6 +154,8 @@ private:
LLView* mDAE;
LLView* mDAN;
LLView* mDAF;
+
+ boost::signals2::connection mSelectionUpdateSlot;
};
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index 42cd1133a2..32d76e690d 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -59,12 +59,12 @@ extern bool gShiftFrame;
static U32 sZombieGroups = 0;
U32 LLSpatialGroup::sNodeCount = 0;
-BOOL LLSpatialGroup::sNoDelete = FALSE;
+bool LLSpatialGroup::sNoDelete = false;
static F32 sLastMaxTexPriority = 1.f;
static F32 sCurMaxTexPriority = 1.f;
-BOOL LLSpatialPartition::sTeleportRequested = FALSE;
+bool LLSpatialPartition::sTeleportRequested = false;
//static counter for frame to switch LOD on
@@ -309,14 +309,13 @@ void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group)
if (vertex_count > 0 && index_count > 0)
{ //create vertex buffer containing volume geometry for this node
{
-
group->mBuilt = 1.f;
- if (group->mVertexBuffer.isNull() ||
- !group->mVertexBuffer->isWriteable() ||
- (group->mBufferUsage != group->mVertexBuffer->getUsage() && LLVertexBuffer::sEnableVBOs))
+ if (group->mVertexBuffer.isNull() ||
+ group->mVertexBuffer->getNumVerts() != vertex_count ||
+ group->mVertexBuffer->getNumVerts() != index_count)
{
- group->mVertexBuffer = createVertexBuffer(mVertexDataMask, group->mBufferUsage);
- if (!group->mVertexBuffer->allocateBuffer(vertex_count, index_count, true))
+ group->mVertexBuffer = new LLVertexBuffer(mVertexDataMask);
+ if (!group->mVertexBuffer->allocateBuffer(vertex_count, index_count))
{
LL_WARNS() << "Failed to allocate Vertex Buffer on rebuild to "
<< vertex_count << " vertices and "
@@ -325,18 +324,6 @@ void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group)
group->mBufferMap.clear();
}
}
- else
- {
- if (!group->mVertexBuffer->resizeBuffer(vertex_count, index_count))
- {
- // Is likely to cause a crash. If this gets triggered find a way to avoid it (don't forget to reset face)
- LL_WARNS() << "Failed to resize Vertex Buffer on rebuild to "
- << vertex_count << " vertices and "
- << index_count << " indices" << LL_ENDL;
- group->mVertexBuffer = NULL;
- group->mBufferMap.clear();
- }
- }
}
if (group->mVertexBuffer)
@@ -538,7 +525,6 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) : LLO
mSurfaceArea(0.f),
mBuilt(0.f),
mVertexBuffer(NULL),
- mBufferUsage(part->mBufferUsage),
mDistance(0.f),
mDepth(0.f),
mLastUpdateDistance(-1.f),
@@ -554,9 +540,12 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) : LLO
sg_assert(mOctreeNode->getListenerCount() == 0);
setState(SG_INITIAL_STATE_MASK);
gPipeline.markRebuild(this, TRUE);
+
+ // let the reflection map manager know about this spatial group
+ mReflectionProbe = gPipeline.mReflectionMapManager.registerSpatialGroup(this);
- mRadius = 1;
- mPixelArea = 1024.f;
+ mRadius = 1;
+ mPixelArea = 1024.f;
}
void LLSpatialGroup::updateDistance(LLCamera &camera)
@@ -564,6 +553,7 @@ void LLSpatialGroup::updateDistance(LLCamera &camera)
if (LLViewerCamera::sCurCameraID != LLViewerCamera::CAMERA_WORLD)
{
LL_WARNS() << "Attempted to update distance for camera other than world camera!" << LL_ENDL;
+ llassert(false);
return;
}
@@ -720,11 +710,6 @@ BOOL LLSpatialGroup::changeLOD()
return TRUE;
}
-
- if (mDistance > mRadius*2.f)
- {
- return FALSE;
- }
}
if (needsUpdate())
@@ -835,13 +820,12 @@ void LLSpatialGroup::destroyGL(bool keep_occlusion)
//==============================================
-LLSpatialPartition::LLSpatialPartition(U32 data_mask, BOOL render_by_group, U32 buffer_usage, LLViewerRegion* regionp)
+LLSpatialPartition::LLSpatialPartition(U32 data_mask, BOOL render_by_group, LLViewerRegion* regionp)
: mRenderByGroup(render_by_group), mBridge(NULL)
{
mRegionp = regionp;
mPartitionType = LLViewerRegion::PARTITION_NONE;
mVertexDataMask = data_mask;
- mBufferUsage = buffer_usage;
mDepthMask = FALSE;
mSlopRatio = 0.25f;
mInfiniteFarClip = FALSE;
@@ -1010,11 +994,11 @@ public:
virtual void processGroup(LLViewerOctreeGroup* base_group)
{
LLSpatialGroup* group = (LLSpatialGroup*)base_group;
- if (group->needsUpdate() ||
+ /*if (group->needsUpdate() ||
group->getVisible(LLViewerCamera::sCurCameraID) < LLDrawable::getCurrentFrame() - 1)
{
group->doOcclusion(mCamera);
- }
+ }*/
gPipeline.markNotCulled(group, *mCamera);
}
};
@@ -1399,7 +1383,9 @@ S32 LLSpatialPartition::cull(LLCamera &camera, std::vector<LLDrawable *>* result
return 0;
}
-
+
+extern BOOL gCubeSnapshot;
+
S32 LLSpatialPartition::cull(LLCamera &camera, bool do_occlusion)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_SPATIAL;
@@ -1418,7 +1404,7 @@ S32 LLSpatialPartition::cull(LLCamera &camera, bool do_occlusion)
LLOctreeCullShadow culler(&camera);
culler.traverse(mOctree);
}
- else if (mInfiniteFarClip || !LLPipeline::sUseFarClip)
+ else if (mInfiniteFarClip || (!LLPipeline::sUseFarClip && !gCubeSnapshot))
{
LLOctreeCullNoFarClip culler(&camera);
culler.traverse(mOctree);
@@ -1432,15 +1418,15 @@ S32 LLSpatialPartition::cull(LLCamera &camera, bool do_occlusion)
return 0;
}
-void pushVerts(LLDrawInfo* params, U32 mask)
+void pushVerts(LLDrawInfo* params)
{
LLRenderPass::applyModelMatrix(*params);
- params->mVertexBuffer->setBuffer(mask);
- params->mVertexBuffer->drawRange(params->mParticle ? LLRender::POINTS : LLRender::TRIANGLES,
+ params->mVertexBuffer->setBuffer();
+ params->mVertexBuffer->drawRange(LLRender::TRIANGLES,
params->mStart, params->mEnd, params->mCount, params->mOffset);
}
-void pushVerts(LLSpatialGroup* group, U32 mask)
+void pushVerts(LLSpatialGroup* group)
{
LLDrawInfo* params = NULL;
@@ -1449,36 +1435,25 @@ void pushVerts(LLSpatialGroup* group, U32 mask)
for (LLSpatialGroup::drawmap_elem_t::iterator j = i->second.begin(); j != i->second.end(); ++j)
{
params = *j;
- pushVerts(params, mask);
+ pushVerts(params);
}
}
}
-void pushVerts(LLFace* face, U32 mask)
+void pushVerts(LLFace* face)
{
if (face)
{
llassert(face->verify());
-
- LLVertexBuffer* buffer = face->getVertexBuffer();
-
- if (buffer && (face->getGeomCount() >= 3))
- {
- buffer->setBuffer(mask);
- U16 start = face->getGeomStart();
- U16 end = start + face->getGeomCount()-1;
- U32 count = face->getIndicesCount();
- U16 offset = face->getIndicesStart();
- buffer->drawRange(LLRender::TRIANGLES, start, end, count, offset);
- }
+ face->renderIndexed();
}
}
-void pushVerts(LLDrawable* drawable, U32 mask)
+void pushVerts(LLDrawable* drawable)
{
for (S32 i = 0; i < drawable->getNumFaces(); ++i)
{
- pushVerts(drawable->getFace(i), mask);
+ pushVerts(drawable->getFace(i));
}
}
@@ -1492,16 +1467,16 @@ void pushVerts(LLVolume* volume)
}
}
-void pushBufferVerts(LLVertexBuffer* buffer, U32 mask)
+void pushBufferVerts(LLVertexBuffer* buffer)
{
if (buffer)
{
- buffer->setBuffer(mask);
+ buffer->setBuffer();
buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0);
}
}
-void pushBufferVerts(LLSpatialGroup* group, U32 mask, bool push_alpha = true)
+void pushBufferVerts(LLSpatialGroup* group, bool push_alpha = true)
{
if (group->getSpatialPartition()->mRenderByGroup)
{
@@ -1512,7 +1487,7 @@ void pushBufferVerts(LLSpatialGroup* group, U32 mask, bool push_alpha = true)
if (push_alpha)
{
- pushBufferVerts(group->mVertexBuffer, mask);
+ pushBufferVerts(group->mVertexBuffer);
}
for (LLSpatialGroup::buffer_map_t::iterator i = group->mBufferMap.begin(); i != group->mBufferMap.end(); ++i)
@@ -1521,7 +1496,7 @@ void pushBufferVerts(LLSpatialGroup* group, U32 mask, bool push_alpha = true)
{
for (LLSpatialGroup::buffer_list_t::iterator k = j->second.begin(); k != j->second.end(); ++k)
{
- pushBufferVerts(*k, mask);
+ pushBufferVerts(*k);
}
}
}
@@ -1534,7 +1509,7 @@ void pushBufferVerts(LLSpatialGroup* group, U32 mask, bool push_alpha = true)
}*/
}
-void pushVertsColorCoded(LLSpatialGroup* group, U32 mask)
+void pushVertsColorCoded(LLSpatialGroup* group)
{
LLDrawInfo* params = NULL;
@@ -1559,8 +1534,8 @@ void pushVertsColorCoded(LLSpatialGroup* group, U32 mask)
params = *j;
LLRenderPass::applyModelMatrix(*params);
gGL.diffuseColor4f(colors[col].mV[0], colors[col].mV[1], colors[col].mV[2], 0.5f);
- params->mVertexBuffer->setBuffer(mask);
- params->mVertexBuffer->drawRange(params->mParticle ? LLRender::POINTS : LLRender::TRIANGLES,
+ params->mVertexBuffer->setBuffer();
+ params->mVertexBuffer->drawRange(LLRender::TRIANGLES,
params->mStart, params->mEnd, params->mCount, params->mOffset);
col = (col+1)%col_count;
}
@@ -1632,17 +1607,8 @@ void renderOctree(LLSpatialGroup* group)
if (group->mBuilt > 0.f)
{
group->mBuilt -= 2.f * gFrameIntervalSeconds.value();
- if (group->mBufferUsage == GL_STATIC_DRAW_ARB)
- {
- col.setVec(1.0f, 0, 0, group->mBuilt*0.5f);
- }
- else
- {
- col.setVec(0.1f,0.1f,1,0.1f);
- //col.setVec(1.0f, 1.0f, 0, sinf(group->mBuilt*3.14159f)*0.5f);
- }
-
- if (group->mBufferUsage != GL_STATIC_DRAW_ARB)
+ col.setVec(0.1f,0.1f,1,0.1f);
+
{
LLGLDepthTest gl_depth(FALSE, FALSE);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
@@ -1703,20 +1669,36 @@ void renderOctree(LLSpatialGroup* group)
LLFace* face = drawable->getFace(j);
if (face && face->getVertexBuffer())
{
- if (gFrameTimeSeconds - face->mLastUpdateTime < 0.5f)
- {
- gGL.diffuseColor4f(0, 1, 0, group->mBuilt);
- }
- else if (gFrameTimeSeconds - face->mLastMoveTime < 0.5f)
- {
- gGL.diffuseColor4f(1, 0, 0, group->mBuilt);
- }
- else
- {
- continue;
- }
+ LLVOVolume* vol = drawable->getVOVolume();
+
+ if (gFrameTimeSeconds - face->mLastUpdateTime < 0.5f)
+ {
+ if (vol && vol->isShrinkWrapped())
+ {
+ gGL.diffuseColor4f(0, 1, 1, group->mBuilt);
+ }
+ else
+ {
+ gGL.diffuseColor4f(0, 1, 0, group->mBuilt);
+ }
+ }
+ else if (gFrameTimeSeconds - face->mLastMoveTime < 0.5f)
+ {
+ if (vol && vol->isShrinkWrapped())
+ {
+ gGL.diffuseColor4f(1, 1, 0, group->mBuilt);
+ }
+ else
+ {
+ gGL.diffuseColor4f(1, 0, 0, group->mBuilt);
+ }
+ }
+ else
+ {
+ continue;
+ }
- face->getVertexBuffer()->setBuffer(LLVertexBuffer::MAP_VERTEX | (rigged ? LLVertexBuffer::MAP_WEIGHT4 : 0));
+ face->getVertexBuffer()->setBuffer();
//drawBox((face->mExtents[0] + face->mExtents[1])*0.5f,
// (face->mExtents[1]-face->mExtents[0])*0.5f);
face->getVertexBuffer()->draw(LLRender::TRIANGLES, face->getIndicesCount(), face->getIndicesStart());
@@ -1738,18 +1720,6 @@ void renderOctree(LLSpatialGroup* group)
gGL.diffuseColor4f(1,1,1,1);
}
}
- else
- {
- if (group->mBufferUsage == GL_STATIC_DRAW_ARB && !group->isEmpty()
- && group->getSpatialPartition()->mRenderByGroup)
- {
- col.setVec(0.8f, 0.4f, 0.1f, 0.1f);
- }
- else
- {
- col.setVec(0.1f, 0.1f, 1.f, 0.1f);
- }
- }
gGL.diffuseColor4fv(col.mV);
LLVector4a fudge;
@@ -1797,7 +1767,7 @@ void renderOctree(LLSpatialGroup* group)
}
}*/
}
-
+
// LLSpatialGroup::OctreeNode* node = group->mOctreeNode;
// gGL.diffuseColor4f(0,1,0,1);
// drawBoxOutline(LLVector3(node->getCenter()), LLVector3(node->getSize()));
@@ -1902,7 +1872,7 @@ void renderXRay(LLSpatialGroup* group, LLCamera* camera)
if (render_objects)
{
- pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX, false);
+ pushBufferVerts(group, false);
bool selected = false;
@@ -1984,7 +1954,7 @@ void renderUpdateType(LLDrawable* drawablep)
{
for (S32 i = 0; i < num_faces; ++i)
{
- pushVerts(drawablep->getFace(i), LLVertexBuffer::MAP_VERTEX);
+ pushVerts(drawablep->getFace(i));
}
}
}
@@ -2075,7 +2045,7 @@ void renderComplexityDisplay(LLDrawable* drawablep)
{
for (S32 i = 0; i < num_faces; ++i)
{
- pushVerts(drawablep->getFace(i), LLVertexBuffer::MAP_VERTEX);
+ pushVerts(drawablep->getFace(i));
}
}
LLViewerObject::const_child_list_t children = voVol->getChildren();
@@ -2089,7 +2059,7 @@ void renderComplexityDisplay(LLDrawable* drawablep)
{
for (S32 i = 0; i < num_faces; ++i)
{
- pushVerts(child->mDrawable->getFace(i), LLVertexBuffer::MAP_VERTEX);
+ pushVerts(child->mDrawable->getFace(i));
}
}
}
@@ -2323,7 +2293,7 @@ S32 get_physics_detail(const LLVolumeParams& volume_params, const LLVector3& sca
return detail;
}
-void renderMeshBaseHull(LLVOVolume* volume, U32 data_mask, LLColor4& color, LLColor4& line_color)
+void renderMeshBaseHull(LLVOVolume* volume, U32 data_mask, LLColor4& color)
{
LLUUID mesh_id = volume->getVolume()->getParams().getSculptID();
LLModel::Decomposition* decomp = gMeshRepo.getDecomposition(mesh_id);
@@ -2335,13 +2305,8 @@ void renderMeshBaseHull(LLVOVolume* volume, U32 data_mask, LLColor4& color, LLCo
{
if (!decomp->mBaseHullMesh.empty())
{
- gGL.diffuseColor4fv(color.mV);
+ gGL.diffuseColor4fv(color.mV);
LLVertexBuffer::drawArrays(LLRender::TRIANGLES, decomp->mBaseHullMesh.mPositions);
-
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- gGL.diffuseColor4fv(line_color.mV);
- LLVertexBuffer::drawArrays(LLRender::TRIANGLES, decomp->mBaseHullMesh.mPositions);
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
else
{
@@ -2358,19 +2323,13 @@ void renderMeshBaseHull(LLVOVolume* volume, U32 data_mask, LLColor4& color, LLCo
}
}
-void render_hull(LLModel::PhysicsMesh& mesh, const LLColor4& color, const LLColor4& line_color)
+void render_hull(LLModel::PhysicsMesh& mesh, const LLColor4& color)
{
- gGL.diffuseColor4fv(color.mV);
+ gGL.diffuseColor4fv(color.mV);
LLVertexBuffer::drawArrays(LLRender::TRIANGLES, mesh.mPositions);
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- glLineWidth(3.f);
- gGL.diffuseColor4fv(line_color.mV);
- LLVertexBuffer::drawArrays(LLRender::TRIANGLES, mesh.mPositions);
- glLineWidth(1.f);
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
-void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume)
+void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume, bool wireframe)
{
U8 physics_type = volume->getPhysicsShapeType();
@@ -2400,7 +2359,10 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume)
color = lerp( mid, high, 2.f * ( normalizedCost - 0.5f ) );
}
- LLColor4 line_color = color*0.5f;
+ if (wireframe)
+ {
+ color = color * 0.5f;
+ }
U32 data_mask = LLVertexBuffer::MAP_VERTEX;
@@ -2420,9 +2382,6 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume)
gGL.pushMatrix();
gGL.multMatrix((F32*) volume->getRelativeXform().mMatrix);
- LLGLEnable(GL_POLYGON_OFFSET_LINE);
- glPolygonOffset(3.f, 3.f);
-
if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::USER_MESH)
{
LLUUID mesh_id = volume->getVolume()->getParams().getSculptID();
@@ -2443,23 +2402,19 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume)
for (U32 i = 0; i < decomp->mMesh.size(); ++i)
{
- render_hull(decomp->mMesh[i], color, line_color);
+ render_hull(decomp->mMesh[i], color);
}
}
else if (!decomp->mPhysicsShapeMesh.empty())
{
//decomp has physics mesh, render that mesh
- gGL.diffuseColor4fv(color.mV);
- LLVertexBuffer::drawArrays(LLRender::TRIANGLES, decomp->mPhysicsShapeMesh.mPositions);
-
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- gGL.diffuseColor4fv(line_color.mV);
+ gGL.diffuseColor4fv(color.mV);
+
LLVertexBuffer::drawArrays(LLRender::TRIANGLES, decomp->mPhysicsShapeMesh.mPositions);
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
else
{ //no mesh or decomposition, render base hull
- renderMeshBaseHull(volume, data_mask, color, line_color);
+ renderMeshBaseHull(volume, data_mask, color);
if (decomp->mPhysicsShapeMesh.empty())
{
@@ -2479,7 +2434,7 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume)
{
if (volume->isMesh())
{
- renderMeshBaseHull(volume, data_mask, color, line_color);
+ renderMeshBaseHull(volume, data_mask, color);
}
else
{
@@ -2575,20 +2530,10 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume)
if (phys_volume->mHullPoints)
{
//render hull
-
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
-
- gGL.diffuseColor4fv(line_color.mV);
- LLVertexBuffer::unbind();
+ gGL.diffuseColor4fv(color.mV);
- llassert(LLGLSLShader::sCurBoundShader != 0);
-
- LLVertexBuffer::drawElements(LLRender::TRIANGLES, phys_volume->mHullPoints, NULL, phys_volume->mNumHullIndices, phys_volume->mHullIndices);
-
- gGL.diffuseColor4fv(color.mV);
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ LLVertexBuffer::unbind();
LLVertexBuffer::drawElements(LLRender::TRIANGLES, phys_volume->mHullPoints, NULL, phys_volume->mNumHullIndices, phys_volume->mHullIndices);
-
}
else
{
@@ -2601,41 +2546,50 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume)
}
else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::BOX)
{
- LLVector3 center = physics_spec.getCenter();
- LLVector3 scale = physics_spec.getScale();
- LLVector3 vscale = volume->getScale()*2.f;
- scale.set(scale[0]/vscale[0], scale[1]/vscale[1], scale[2]/vscale[2]);
-
- gGL.diffuseColor4fv(color.mV);
- drawBox(center, scale);
+ if (!wireframe)
+ {
+ LLVector3 center = physics_spec.getCenter();
+ LLVector3 scale = physics_spec.getScale();
+ LLVector3 vscale = volume->getScale() * 2.f;
+ scale.set(scale[0] / vscale[0], scale[1] / vscale[1], scale[2] / vscale[2]);
+
+ gGL.diffuseColor4fv(color.mV);
+ drawBox(center, scale);
+ }
}
else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::SPHERE)
{
- LLVolumeParams volume_params;
- volume_params.setType( LL_PCODE_PROFILE_CIRCLE_HALF, LL_PCODE_PATH_CIRCLE );
- volume_params.setBeginAndEndS( 0.f, 1.f );
- volume_params.setBeginAndEndT( 0.f, 1.f );
- volume_params.setRatio ( 1, 1 );
- volume_params.setShear ( 0, 0 );
- LLVolume* sphere = LLPrimitive::sVolumeManager->refVolume(volume_params, 3);
-
- gGL.diffuseColor4fv(color.mV);
- pushVerts(sphere);
- LLPrimitive::sVolumeManager->unrefVolume(sphere);
+ if (!wireframe)
+ {
+ LLVolumeParams volume_params;
+ volume_params.setType(LL_PCODE_PROFILE_CIRCLE_HALF, LL_PCODE_PATH_CIRCLE);
+ volume_params.setBeginAndEndS(0.f, 1.f);
+ volume_params.setBeginAndEndT(0.f, 1.f);
+ volume_params.setRatio(1, 1);
+ volume_params.setShear(0, 0);
+ LLVolume* sphere = LLPrimitive::sVolumeManager->refVolume(volume_params, 3);
+
+ gGL.diffuseColor4fv(color.mV);
+ pushVerts(sphere);
+ LLPrimitive::sVolumeManager->unrefVolume(sphere);
+ }
}
else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::CYLINDER)
{
- LLVolumeParams volume_params;
- volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_LINE );
- volume_params.setBeginAndEndS( 0.f, 1.f );
- volume_params.setBeginAndEndT( 0.f, 1.f );
- volume_params.setRatio ( 1, 1 );
- volume_params.setShear ( 0, 0 );
- LLVolume* cylinder = LLPrimitive::sVolumeManager->refVolume(volume_params, 3);
-
- gGL.diffuseColor4fv(color.mV);
- pushVerts(cylinder);
- LLPrimitive::sVolumeManager->unrefVolume(cylinder);
+ if (!wireframe)
+ {
+ LLVolumeParams volume_params;
+ volume_params.setType(LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_LINE);
+ volume_params.setBeginAndEndS(0.f, 1.f);
+ volume_params.setBeginAndEndT(0.f, 1.f);
+ volume_params.setRatio(1, 1);
+ volume_params.setShear(0, 0);
+ LLVolume* cylinder = LLPrimitive::sVolumeManager->refVolume(volume_params, 3);
+
+ gGL.diffuseColor4fv(color.mV);
+ pushVerts(cylinder);
+ LLPrimitive::sVolumeManager->unrefVolume(cylinder);
+ }
}
else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::PRIM_MESH)
{
@@ -2643,14 +2597,10 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume)
S32 detail = get_physics_detail(volume_params, volume->getScale());
LLVolume* phys_volume = LLPrimitive::sVolumeManager->refVolume(volume_params, detail);
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
-
- gGL.diffuseColor4fv(line_color.mV);
- pushVerts(phys_volume);
-
- gGL.diffuseColor4fv(color.mV);
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+
+ gGL.diffuseColor4fv(color.mV);
pushVerts(phys_volume);
+
LLPrimitive::sVolumeManager->unrefVolume(phys_volume);
}
else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::PRIM_CONVEX)
@@ -2662,23 +2612,15 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume)
if (phys_volume->mHullPoints && phys_volume->mHullIndices)
{
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+
llassert(LLGLSLShader::sCurBoundShader != 0);
LLVertexBuffer::unbind();
glVertexPointer(3, GL_FLOAT, 16, phys_volume->mHullPoints);
- gGL.diffuseColor4fv(line_color.mV);
- gGL.syncMatrices();
- {
- LL_PROFILER_GPU_ZONEC( "gl.DrawElements", 0x20FF20 )
- glDrawElements(GL_TRIANGLES, phys_volume->mNumHullIndices, GL_UNSIGNED_SHORT, phys_volume->mHullIndices);
- }
-
- gGL.diffuseColor4fv(color.mV);
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- {
- LL_PROFILER_GPU_ZONEC( "gl.DrawElements", 0x40FF40 )
- glDrawElements(GL_TRIANGLES, phys_volume->mNumHullIndices, GL_UNSIGNED_SHORT, phys_volume->mHullIndices);
- }
+
+ gGL.diffuseColor4fv(color.mV);
+
+ gGL.syncMatrices();
+ glDrawElements(GL_TRIANGLES, phys_volume->mNumHullIndices, GL_UNSIGNED_SHORT, phys_volume->mHullIndices);
}
else
{
@@ -2700,7 +2642,7 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume)
gGL.popMatrix();
}
-void renderPhysicsShapes(LLSpatialGroup* group)
+void renderPhysicsShapes(LLSpatialGroup* group, bool wireframe)
{
for (OctreeNode::const_element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i)
{
@@ -2718,7 +2660,7 @@ void renderPhysicsShapes(LLSpatialGroup* group)
{
gGL.pushMatrix();
gGL.multMatrix((F32*)bridge->mDrawable->getRenderMatrix().mMatrix);
- bridge->renderPhysicsShapes();
+ bridge->renderPhysicsShapes(wireframe);
gGL.popMatrix();
}
}
@@ -2732,16 +2674,17 @@ void renderPhysicsShapes(LLSpatialGroup* group)
gGL.pushMatrix();
LLVector3 trans = drawable->getRegion()->getOriginAgent();
gGL.translatef(trans.mV[0], trans.mV[1], trans.mV[2]);
- renderPhysicsShape(drawable, volume);
+ renderPhysicsShape(drawable, volume, wireframe);
gGL.popMatrix();
}
else
{
- renderPhysicsShape(drawable, volume);
+ renderPhysicsShape(drawable, volume, wireframe);
}
}
else
{
+#if 0
LLViewerObject* object = drawable->getVObj();
if (object && object->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH)
{
@@ -2758,11 +2701,11 @@ void renderPhysicsShapes(LLSpatialGroup* group)
{
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- buff->setBuffer(LLVertexBuffer::MAP_VERTEX);
- gGL.diffuseColor3f(0.2f, 0.5f, 0.3f);
+ buff->setBuffer();
+ gGL.diffuseColor4f(0.2f, 0.5f, 0.3f, 0.5f);
buff->draw(LLRender::TRIANGLES, buff->getNumIndices(), 0);
- gGL.diffuseColor3f(0.2f, 1.f, 0.3f);
+ gGL.diffuseColor4f(0.2f, 1.f, 0.3f, 0.75f);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
buff->draw(LLRender::TRIANGLES, buff->getNumIndices(), 0);
}
@@ -2770,6 +2713,7 @@ void renderPhysicsShapes(LLSpatialGroup* group)
}
gGL.popMatrix();
}
+#endif
}
}
}
@@ -2863,7 +2807,7 @@ void renderTextureAnim(LLDrawInfo* params)
LLGLEnable blend(GL_BLEND);
gGL.diffuseColor4f(1,1,0,0.5f);
- pushVerts(params, LLVertexBuffer::MAP_VERTEX);
+ pushVerts(params);
}
void renderBatchSize(LLDrawInfo* params)
@@ -2871,7 +2815,6 @@ void renderBatchSize(LLDrawInfo* params)
LLGLEnable offset(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(-1.f, 1.f);
LLGLSLShader* old_shader = LLGLSLShader::sCurBoundShaderPtr;
- U32 mask = LLVertexBuffer::MAP_VERTEX;
bool bind = false;
if (params->mAvatar)
{
@@ -2880,11 +2823,11 @@ void renderBatchSize(LLDrawInfo* params)
bind = true;
old_shader->mRiggedVariant->bind();
LLRenderPass::uploadMatrixPalette(*params);
- mask |= LLVertexBuffer::MAP_WEIGHT4;
}
- gGL.diffuseColor4ubv((GLubyte*)&(params->mDebugColor));
- pushVerts(params, mask);
+
+ gGL.diffuseColor4ubv(params->getDebugColor().mV);
+ pushVerts(params);
if (bind)
{
@@ -2893,42 +2836,6 @@ void renderBatchSize(LLDrawInfo* params)
}
}
-void renderShadowFrusta(LLDrawInfo* params)
-{
- LLGLEnable blend(GL_BLEND);
- gGL.setSceneBlendType(LLRender::BT_ADD);
-
- LLVector4a center;
- center.setAdd(params->mExtents[1], params->mExtents[0]);
- center.mul(0.5f);
- LLVector4a size;
- size.setSub(params->mExtents[1],params->mExtents[0]);
- size.mul(0.5f);
-
- if (gPipeline.mShadowCamera[4].AABBInFrustum(center, size))
- {
- gGL.diffuseColor3f(1,0,0);
- pushVerts(params, LLVertexBuffer::MAP_VERTEX);
- }
- if (gPipeline.mShadowCamera[5].AABBInFrustum(center, size))
- {
- gGL.diffuseColor3f(0,1,0);
- pushVerts(params, LLVertexBuffer::MAP_VERTEX);
- }
- if (gPipeline.mShadowCamera[6].AABBInFrustum(center, size))
- {
- gGL.diffuseColor3f(0,0,1);
- pushVerts(params, LLVertexBuffer::MAP_VERTEX);
- }
- if (gPipeline.mShadowCamera[7].AABBInFrustum(center, size))
- {
- gGL.diffuseColor3f(1,0,1);
- pushVerts(params, LLVertexBuffer::MAP_VERTEX);
- }
-
- gGL.setSceneBlendType(LLRender::BT_ALPHA);
-}
-
void renderTexelDensity(LLDrawable* drawable)
{
if (LLViewerTexture::sDebugTexelsMode == LLViewerTexture::DEBUG_TEXELS_OFF
@@ -2976,7 +2883,7 @@ void renderTexelDensity(LLDrawable* drawable)
if (buffer && (facep->getGeomCount() >= 3))
{
- buffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0);
+ buffer->setBuffer();
U16 start = facep->getGeomStart();
U16 end = start + facep->getGeomCount()-1;
U32 count = facep->getIndicesCount();
@@ -3051,7 +2958,7 @@ void renderLights(LLDrawable* drawablep)
LLFace * face = drawablep->getFace(i);
if (face)
{
- pushVerts(face, LLVertexBuffer::MAP_VERTEX);
+ pushVerts(face);
}
}
@@ -3215,7 +3122,6 @@ void renderRaycast(LLDrawable* drawablep)
gGL.diffuseColor4f(0,1,1,0.5f);
glVertexPointer(3, GL_FLOAT, sizeof(LLVector4a), face.mPositions);
gGL.syncMatrices();
- LL_PROFILER_GPU_ZONEC( "gl.DrawElements", 0x60FF60 );
glDrawElements(GL_TRIANGLES, face.mNumIndices, GL_UNSIGNED_SHORT, face.mIndices);
}
@@ -3424,10 +3330,10 @@ public:
}
}
- if (drawable->getVOVolume() && gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY))
+ /*if (drawable->getVOVolume() && gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY))
{
renderTexturePriority(drawable);
- }
+ }*/
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_POINTS))
{
@@ -3514,10 +3420,6 @@ public:
{
renderBatchSize(draw_info);
}
- if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
- {
- renderShadowFrusta(draw_info);
- }
}
}
}
@@ -3571,7 +3473,9 @@ class LLOctreeRenderPhysicsShapes : public OctreeTraveler
{
public:
LLCamera* mCamera;
- LLOctreeRenderPhysicsShapes(LLCamera* camera): mCamera(camera) {}
+ bool mWireframe;
+
+ LLOctreeRenderPhysicsShapes(LLCamera* camera, bool wireframe): mCamera(camera), mWireframe(wireframe) {}
virtual void traverse(const OctreeNode* node)
{
@@ -3592,7 +3496,7 @@ public:
group->rebuildGeom();
group->rebuildMesh();
- renderPhysicsShapes(group);
+ renderPhysicsShapes(group, mWireframe);
}
}
@@ -3725,7 +3629,7 @@ public:
};
-void LLSpatialPartition::renderPhysicsShapes()
+void LLSpatialPartition::renderPhysicsShapes(bool wireframe)
{
LLSpatialBridge* bridge = asBridge();
LLCamera* camera = LLViewerCamera::getInstance();
@@ -3737,11 +3641,9 @@ void LLSpatialPartition::renderPhysicsShapes()
gGL.flush();
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- glLineWidth(3.f);
- LLOctreeRenderPhysicsShapes render_physics(camera);
+ LLOctreeRenderPhysicsShapes render_physics(camera, wireframe);
render_physics.traverse(mOctree);
gGL.flush();
- glLineWidth(1.f);
}
void LLSpatialPartition::renderDebug()
@@ -3754,7 +3656,7 @@ void LLSpatialPartition::renderDebug()
LLPipeline::RENDER_DEBUG_BBOXES |
LLPipeline::RENDER_DEBUG_NORMALS |
LLPipeline::RENDER_DEBUG_POINTS |
- LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY |
+ //LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY |
LLPipeline::RENDER_DEBUG_TEXTURE_ANIM |
LLPipeline::RENDER_DEBUG_RAYCAST |
LLPipeline::RENDER_DEBUG_AVATAR_VOLUME |
@@ -3763,7 +3665,7 @@ void LLSpatialPartition::renderDebug()
//LLPipeline::RENDER_DEBUG_BUILD_QUEUE |
LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA |
LLPipeline::RENDER_DEBUG_RENDER_COMPLEXITY |
- LLPipeline::RENDER_DEBUG_TEXEL_DENSITY))
+ LLPipeline::RENDER_DEBUG_TEXEL_DENSITY))
{
return;
}
@@ -3797,7 +3699,6 @@ void LLSpatialPartition::renderDebug()
LLOctreeRenderNonOccluded render_debug(camera);
render_debug.traverse(mOctree);
-
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION))
{
{
@@ -3860,8 +3761,9 @@ public:
LLDrawable* mHit;
BOOL mPickTransparent;
BOOL mPickRigged;
+ BOOL mPickUnselectable;
- LLOctreeIntersect(const LLVector4a& start, const LLVector4a& end, BOOL pick_transparent, BOOL pick_rigged,
+ LLOctreeIntersect(const LLVector4a& start, const LLVector4a& end, BOOL pick_transparent, BOOL pick_rigged, BOOL pick_unselectable,
S32* face_hit, LLVector4a* intersection, LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent)
: mStart(start),
mEnd(end),
@@ -3872,7 +3774,8 @@ public:
mTangent(tangent),
mHit(NULL),
mPickTransparent(pick_transparent),
- mPickRigged(pick_rigged)
+ mPickRigged(pick_rigged),
+ mPickUnselectable(pick_unselectable)
{
}
@@ -3957,7 +3860,7 @@ public:
LLVOAvatar* avatar = (LLVOAvatar*) vobj;
if ((mPickRigged) || ((avatar->isSelf()) && (LLFloater::isVisible(gFloaterTools))))
{
- LLViewerObject* hit = avatar->lineSegmentIntersectRiggedAttachments(mStart, mEnd, -1, mPickTransparent, mPickRigged, mFaceHit, &intersection, mTexCoord, mNormal, mTangent);
+ LLViewerObject* hit = avatar->lineSegmentIntersectRiggedAttachments(mStart, mEnd, -1, mPickTransparent, mPickRigged, mPickUnselectable, mFaceHit, &intersection, mTexCoord, mNormal, mTangent);
if (hit)
{
mEnd = intersection;
@@ -3973,7 +3876,7 @@ public:
}
}
- if (!skip_check && vobj->lineSegmentIntersect(mStart, mEnd, -1, mPickTransparent, mPickRigged, mFaceHit, &intersection, mTexCoord, mNormal, mTangent))
+ if (!skip_check && vobj->lineSegmentIntersect(mStart, mEnd, -1, mPickTransparent, mPickRigged, mPickUnselectable, mFaceHit, &intersection, mTexCoord, mNormal, mTangent))
{
mEnd = intersection; // shorten ray so we only find CLOSER hits
if (mIntersection)
@@ -3993,6 +3896,7 @@ public:
LLDrawable* LLSpatialPartition::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end,
BOOL pick_transparent,
BOOL pick_rigged,
+ BOOL pick_unselectable,
S32* face_hit, // return the face hit
LLVector4a* intersection, // return the intersection point
LLVector2* tex_coord, // return the texture coordinates of the intersection point
@@ -4001,68 +3905,72 @@ LLDrawable* LLSpatialPartition::lineSegmentIntersect(const LLVector4a& start, co
)
{
- LLOctreeIntersect intersect(start, end, pick_transparent, pick_rigged, face_hit, intersection, tex_coord, normal, tangent);
+ LLOctreeIntersect intersect(start, end, pick_transparent, pick_rigged, pick_unselectable, face_hit, intersection, tex_coord, normal, tangent);
LLDrawable* drawable = intersect.check(mOctree);
return drawable;
}
+LLDrawable* LLSpatialGroup::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end,
+ BOOL pick_transparent,
+ BOOL pick_rigged,
+ BOOL pick_unselectable,
+ S32* face_hit, // return the face hit
+ LLVector4a* intersection, // return the intersection point
+ LLVector2* tex_coord, // return the texture coordinates of the intersection point
+ LLVector4a* normal, // return the surface normal at the intersection point
+ LLVector4a* tangent // return the surface tangent at the intersection point
+)
+
+{
+ LLOctreeIntersect intersect(start, end, pick_transparent, pick_rigged, pick_unselectable, face_hit, intersection, tex_coord, normal, tangent);
+ LLDrawable* drawable = intersect.check(getOctreeNode());
+
+ return drawable;
+}
+
LLDrawInfo::LLDrawInfo(U16 start, U16 end, U32 count, U32 offset,
LLViewerTexture* texture, LLVertexBuffer* buffer,
- bool selected,
- BOOL fullbright, U8 bump, BOOL particle, F32 part_size)
+ bool fullbright, U8 bump)
: mVertexBuffer(buffer),
mTexture(texture),
- mTextureMatrix(NULL),
- mModelMatrix(NULL),
mStart(start),
mEnd(end),
mCount(count),
mOffset(offset),
mFullbright(fullbright),
mBump(bump),
- mParticle(particle),
- mPartSize(part_size),
- mVSize(0.f),
- mGroup(NULL),
- mFace(NULL),
- mDistance(0.f),
- mDrawMode(LLRender::TRIANGLES),
- mMaterial(NULL),
- mShaderMask(0),
- mSpecColor(1.0f, 1.0f, 1.0f, 0.5f),
mBlendFuncSrc(LLRender::BF_SOURCE_ALPHA),
mBlendFuncDst(LLRender::BF_ONE_MINUS_SOURCE_ALPHA),
- mHasGlow(FALSE),
+ mHasGlow(false),
mEnvIntensity(0.0f),
- mAlphaMaskCutoff(0.5f),
- mDiffuseAlphaMode(0),
- mSelected(selected)
+ mAlphaMaskCutoff(0.5f)
{
mVertexBuffer->validateRange(mStart, mEnd, mCount, mOffset);
-
- mDebugColor = (rand() << 16) + rand();
- ((U8*)&mDebugColor)[3] = 200;
}
LLDrawInfo::~LLDrawInfo()
{
- /*if (LLSpatialGroup::sNoDelete)
- {
- LL_ERRS() << "LLDrawInfo deleted illegally!" << LL_ENDL;
- }*/
-
- if (mFace)
- {
- mFace->setDrawInfo(NULL);
- }
-
if (gDebugGL)
{
gPipeline.checkReferences(this);
}
}
+LLColor4U LLDrawInfo::getDebugColor() const
+{
+ LLColor4U color;
+
+ LLCRC hash;
+ hash.update((U8*)this + sizeof(S32), sizeof(LLDrawInfo) - sizeof(S32));
+
+ *((U32*) color.mV) = hash.getCRC();
+
+ color.mV[3] = 200;
+
+ return color;
+}
+
void LLDrawInfo::validate()
{
mVertexBuffer->validateRange(mStart, mEnd, mCount, mOffset);
@@ -4073,11 +3981,6 @@ U64 LLDrawInfo::getSkinHash()
return mSkinInfo ? mSkinInfo->mHash : 0;
}
-LLVertexBuffer* LLGeometryManager::createVertexBuffer(U32 type_mask, U32 usage)
-{
- return new LLVertexBuffer(type_mask, usage);
-}
-
LLCullResult::LLCullResult()
{
mVisibleGroupsAllocated = 0;
diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h
index 6d3ef33801..bc0eabfa0e 100644
--- a/indra/newview/llspatialpartition.h
+++ b/indra/newview/llspatialpartition.h
@@ -41,6 +41,7 @@
#include "llviewercamera.h"
#include "llvector4a.h"
#include "llvoavatar.h"
+#include "llfetchedgltfmaterial.h"
#include <queue>
#include <unordered_map>
@@ -53,10 +54,17 @@ class LLSpatialPartition;
class LLSpatialBridge;
class LLSpatialGroup;
class LLViewerRegion;
+class LLReflectionMap;
-void pushVerts(LLFace* face, U32 mask);
+void pushVerts(LLFace* face);
-class LLDrawInfo : public LLRefCount
+/*
+ Class that represents a single Draw Call
+
+ Make every effort to keep size minimal.
+ Member ordering is important for cache coherency
+*/
+class LLDrawInfo final : public LLRefCount
{
LL_ALIGN_NEW;
protected:
@@ -73,11 +81,13 @@ public:
LL_ERRS() << "Illegal operation!" << LL_ENDL;
return *this;
}
+
+ // return a hash of this LLDrawInfo as a debug color
+ LLColor4U getDebugColor() const;
LLDrawInfo(U16 start, U16 end, U32 count, U32 offset,
- LLViewerTexture* image, LLVertexBuffer* buffer,
- bool selected,
- BOOL fullbright = FALSE, U8 bump = 0, BOOL particle = FALSE, F32 part_size = 0);
+ LLViewerTexture* image, LLVertexBuffer* buffer,
+ bool fullbright = false, U8 bump = 0);
void validate();
@@ -85,51 +95,47 @@ public:
// return mSkinHash->mHash, or 0 if mSkinHash is null
U64 getSkinHash();
- LLVector4a mExtents[2];
-
LLPointer<LLVertexBuffer> mVertexBuffer;
+ U16 mStart = 0;
+ U16 mEnd = 0;
+ U32 mCount = 0;
+ U32 mOffset = 0;
+
LLPointer<LLViewerTexture> mTexture;
- std::vector<LLPointer<LLViewerTexture> > mTextureList;
+ LLPointer<LLViewerTexture> mSpecularMap;
+ LLPointer<LLViewerTexture> mNormalMap;
+
+ const LLMatrix4* mSpecularMapMatrix = nullptr;
+ const LLMatrix4* mNormalMapMatrix = nullptr;
+ const LLMatrix4* mTextureMatrix = nullptr;
+ const LLMatrix4* mModelMatrix = nullptr;
- // virtual size of mTexture and mTextureList textures
- // used to update the decode priority of textures in this DrawInfo
- std::vector<F32> mTextureListVSize;
-
- S32 mDebugColor;
- const LLMatrix4* mTextureMatrix;
- const LLMatrix4* mModelMatrix;
- U16 mStart;
- U16 mEnd;
- U32 mCount;
- U32 mOffset;
- BOOL mFullbright;
- U8 mBump;
- U8 mShiny;
- BOOL mParticle;
- F32 mPartSize;
- F32 mVSize;
- LLSpatialGroup* mGroup;
- LL_ALIGN_16(LLFace* mFace); //associated face
- F32 mDistance;
- U32 mDrawMode;
- LLMaterialPtr mMaterial; // If this is null, the following parameters are unused.
- LLMaterialID mMaterialID;
- U32 mShaderMask;
- U32 mBlendFuncSrc;
- U32 mBlendFuncDst;
- BOOL mHasGlow;
- LLPointer<LLViewerTexture> mSpecularMap;
- const LLMatrix4* mSpecularMapMatrix;
- LLPointer<LLViewerTexture> mNormalMap;
- const LLMatrix4* mNormalMapMatrix;
- LLVector4 mSpecColor; // XYZ = Specular RGB, W = Specular Exponent
- F32 mEnvIntensity;
- F32 mAlphaMaskCutoff;
- U8 mDiffuseAlphaMode;
- bool mSelected;
LLPointer<LLVOAvatar> mAvatar = nullptr;
LLMeshSkinInfo* mSkinInfo = nullptr;
+ // Material pointer here is likely for debugging only and are immaterial (zing!)
+ LLPointer<LLMaterial> mMaterial;
+
+ // PBR material parameters
+ LLPointer<LLFetchedGLTFMaterial> mGLTFMaterial;
+
+ LLVector4 mSpecColor = LLVector4(1.f, 1.f, 1.f, 0.5f); // XYZ = Specular RGB, W = Specular Exponent
+
+ std::vector<LLPointer<LLViewerTexture> > mTextureList;
+
+ LLUUID mMaterialID; // id of LLGLTFMaterial or LLMaterial applied to this draw info
+
+ U32 mShaderMask = 0;
+ F32 mEnvIntensity = 0.f;
+ F32 mAlphaMaskCutoff = 0.5f;
+
+ LLRender::eBlendFactor mBlendFuncSrc = LLRender::BF_SOURCE_ALPHA;
+ LLRender::eBlendFactor mBlendFuncDst = LLRender::BF_ONE_MINUS_SOURCE_ALPHA;
+ U8 mDiffuseAlphaMode = 0;
+ U8 mBump = 0;
+ U8 mShiny = 0;
+ bool mFullbright = false;
+ bool mHasGlow = false;
struct CompareTexture
{
@@ -190,19 +196,9 @@ public:
&& (lhs.isNull() || (rhs.notNull() && lhs->mBump > rhs->mBump));
}
};
-
- struct CompareDistanceGreater
- {
- bool operator()(const LLPointer<LLDrawInfo>& lhs, const LLPointer<LLDrawInfo>& rhs)
- {
- // sort by mBump value, sort NULL down to the end
- return lhs.get() != rhs.get()
- && (lhs.isNull() || (rhs.notNull() && lhs->mDistance > rhs->mDistance));
- }
- };
};
-LL_ALIGN_PREFIX(64)
+LL_ALIGN_PREFIX(16)
class LLSpatialGroup : public LLOcclusionCullingGroup
{
friend class LLSpatialPartition;
@@ -221,7 +217,7 @@ public:
}
static U32 sNodeCount;
- static BOOL sNoDelete; //deletion of spatial groups and draw info not allowed if TRUE
+ static bool sNoDelete; //deletion of spatial groups and draw info not allowed if TRUE
typedef std::vector<LLPointer<LLSpatialGroup> > sg_vector_t;
typedef std::vector<LLPointer<LLSpatialBridge> > bridge_list_t;
@@ -313,6 +309,18 @@ public:
void drawObjectBox(LLColor4 col);
+ LLDrawable* lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end,
+ BOOL pick_transparent,
+ BOOL pick_rigged,
+ BOOL pick_unselectable,
+ S32* face_hit, // return the face hit
+ LLVector4a* intersection = NULL, // return the intersection point
+ LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point
+ LLVector4a* normal = NULL, // return the surface normal at the intersection point
+ LLVector4a* tangent = NULL // return the surface tangent at the intersection point
+ );
+
+
LLSpatialPartition* getSpatialPartition() {return (LLSpatialPartition*)mSpatialPartition;}
//LISTENER FUNCTIONS
@@ -325,25 +333,21 @@ public:
LL_ALIGN_16(LLVector4a mViewAngle);
LL_ALIGN_16(LLVector4a mLastUpdateViewAngle);
- F32 mObjectBoxSize; //cached mObjectBounds[1].getLength3()
-
protected:
virtual ~LLSpatialGroup();
public:
+ LLPointer<LLVertexBuffer> mVertexBuffer;
+ draw_map_t mDrawMap;
+
bridge_list_t mBridgeList;
buffer_map_t mBufferMap; //used by volume buffers to attempt to reuse vertex buffers
+ F32 mObjectBoxSize; //cached mObjectBounds[1].getLength3()
U32 mGeometryBytes; //used by volumes to track how many bytes of geometry data are in this node
F32 mSurfaceArea; //used by volumes to track estimated surface area of geometry in this node
-
F32 mBuilt;
- LLPointer<LLVertexBuffer> mVertexBuffer;
-
- U32 mBufferUsage;
- draw_map_t mDrawMap;
-
F32 mDistance;
F32 mDepth;
F32 mLastUpdateDistance;
@@ -355,7 +359,9 @@ public:
//used by LLVOAVatar to set render order in alpha draw pool to preserve legacy render order behavior
LLVOAvatar* mAvatarp = nullptr;
U32 mRenderOrder = 0;
-} LL_ALIGN_POSTFIX(64);
+ // Reflection Probe associated with this node (if any)
+ LLPointer<LLReflectionMap> mReflectionProbe = nullptr;
+} LL_ALIGN_POSTFIX(16);
class LLGeometryManager
{
@@ -366,14 +372,12 @@ public:
virtual void rebuildMesh(LLSpatialGroup* group) = 0;
virtual void getGeometry(LLSpatialGroup* group) = 0;
virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32 &index_count);
-
- virtual LLVertexBuffer* createVertexBuffer(U32 type_mask, U32 usage);
};
class LLSpatialPartition: public LLViewerOctreePartition, public LLGeometryManager
{
public:
- LLSpatialPartition(U32 data_mask, BOOL render_by_group, U32 mBufferUsage, LLViewerRegion* regionp);
+ LLSpatialPartition(U32 data_mask, BOOL render_by_group, LLViewerRegion* regionp);
virtual ~LLSpatialPartition();
LLSpatialGroup *put(LLDrawable *drawablep, BOOL was_visible = FALSE);
@@ -382,6 +386,7 @@ public:
LLDrawable* lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end,
BOOL pick_transparent,
BOOL pick_rigged,
+ BOOL pick_unselectable,
S32* face_hit, // return the face hit
LLVector4a* intersection = NULL, // return the intersection point
LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point
@@ -410,7 +415,7 @@ public:
LLSpatialBridge* asBridge() { return mBridge; }
BOOL isBridge() { return asBridge() != NULL; }
- void renderPhysicsShapes();
+ void renderPhysicsShapes(bool depth_only);
void renderDebug();
void renderIntersectingBBoxes(LLCamera* camera);
void restoreGL();
@@ -423,14 +428,13 @@ public:
// use a pointer instead of making "isBridge" and "asBridge" virtual so it's safe
// to call asBridge() from the destructor
- BOOL mInfiniteFarClip; // if TRUE, frustum culling ignores far clip plane
- U32 mBufferUsage;
- const BOOL mRenderByGroup;
+ bool mInfiniteFarClip; // if TRUE, frustum culling ignores far clip plane
+ const bool mRenderByGroup;
U32 mVertexDataMask;
F32 mSlopRatio; //percentage distance must change before drawables receive LOD update (default is 0.25);
- BOOL mDepthMask; //if TRUE, objects in this partition will be written to depth during alpha rendering
+ bool mDepthMask; //if TRUE, objects in this partition will be written to depth during alpha rendering
- static BOOL sTeleportRequested; //started to issue a teleport request
+ static bool sTeleportRequested; //started to issue a teleport request
};
// class for creating bridges between spatial partitions
@@ -481,6 +485,23 @@ public:
typedef LLDrawInfo** drawinfo_iterator;
typedef LLDrawable** drawable_iterator;
+ // Helper function for taking advantage of _mm_prefetch when iterating over cull results
+ static inline void increment_iterator(LLCullResult::drawinfo_iterator& i, const LLCullResult::drawinfo_iterator& end)
+ {
+ ++i;
+
+ if (i != end)
+ {
+ _mm_prefetch((char*)(*i)->mVertexBuffer.get(), _MM_HINT_NTA);
+
+ auto* ni = i + 1;
+ if (ni != end)
+ {
+ _mm_prefetch((char*)*ni, _MM_HINT_NTA);
+ }
+ }
+ }
+
void clear();
sg_iterator beginVisibleGroups();
@@ -592,7 +613,6 @@ class LLTerrainPartition : public LLSpatialPartition
public:
LLTerrainPartition(LLViewerRegion* regionp);
virtual void getGeometry(LLSpatialGroup* group);
- virtual LLVertexBuffer* createVertexBuffer(U32 type_mask, U32 usage);
};
//spatial partition for trees
diff --git a/indra/newview/llsprite.cpp b/indra/newview/llsprite.cpp
index c3eb70f850..b641afc1ef 100644
--- a/indra/newview/llsprite.cpp
+++ b/indra/newview/llsprite.cpp
@@ -189,9 +189,8 @@ void LLSprite::updateFace(LLFace &face)
if (!face.getVertexBuffer())
{
LLVertexBuffer* buff = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX |
- LLVertexBuffer::MAP_TEXCOORD0,
- GL_STREAM_DRAW_ARB);
- buff->allocateBuffer(4, 12, TRUE);
+ LLVertexBuffer::MAP_TEXCOORD0 );
+ buff->allocateBuffer(4, 12);
face.setGeomIndex(0);
face.setIndicesIndex(0);
face.setVertexBuffer(buff);
@@ -243,7 +242,7 @@ void LLSprite::updateFace(LLFace &face)
*indicesp++ = 3 + index_offset;
}
- face.getVertexBuffer()->flush();
+ face.getVertexBuffer()->unmapBuffer();
face.mCenterAgent = mPosition;
}
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 6883ead5ee..0dc4746123 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -60,6 +60,7 @@
#include "llfloatergridstatus.h"
#include "llfloaterimsession.h"
#include "lllocationhistory.h"
+#include "llgltfmateriallist.h"
#include "llimageworker.h"
#include "llloginflags.h"
@@ -322,6 +323,8 @@ void set_flags_and_update_appearance()
{
LLAppearanceMgr::instance().setAttachmentInvLinkEnable(true);
LLAppearanceMgr::instance().updateAppearanceFromCOF(true, true, no_op);
+
+ LLInventoryModelBackgroundFetch::instance().start();
}
// Returns false to skip other idle processing. Should only return
@@ -1477,6 +1480,9 @@ bool idle_startup()
gXferManager->registerCallbacks(gMessageSystem);
display_startup();
+ LLGLTFMaterialList::registerCallbacks();
+ display_startup();
+
LLStartUp::initNameCache();
display_startup();
@@ -1551,12 +1557,10 @@ bool idle_startup()
LL_DEBUGS("AppInit") << "Initializing sky..." << LL_ENDL;
// Initialize all of the viewer object classes for the first time (doing things like texture fetches.
LLGLState::checkStates();
- LLGLState::checkTextureChannels();
gSky.init();
LLGLState::checkStates();
- LLGLState::checkTextureChannels();
display_startup();
diff --git a/indra/newview/llsurface.cpp b/indra/newview/llsurface.cpp
index ea36e1d7be..1418499f8b 100644
--- a/indra/newview/llsurface.cpp
+++ b/indra/newview/llsurface.cpp
@@ -681,6 +681,13 @@ BOOL LLSurface::idleUpdate(F32 max_update_time)
}
}
}
+
+ if (did_update)
+ {
+ // some patches changed, update region reflection probes
+ mRegionp->updateReflectionProbes();
+ }
+
return did_update;
}
diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp
index af89b4b53b..d873f5524f 100644
--- a/indra/newview/lltexturecache.cpp
+++ b/indra/newview/lltexturecache.cpp
@@ -95,14 +95,13 @@ private:
};
public:
- LLTextureCacheWorker(LLTextureCache* cache, U32 priority, const LLUUID& id,
+ LLTextureCacheWorker(LLTextureCache* cache, const LLUUID& id,
U8* data, S32 datasize, S32 offset,
S32 imagesize, // for writes
LLTextureCache::Responder* responder)
: LLWorkerClass(cache, "LLTextureCacheWorker"),
mID(id),
mCache(cache),
- mPriority(priority),
mReadData(NULL),
mWriteData(data),
mDataSize(datasize),
@@ -115,7 +114,6 @@ public:
mBytesToRead(0),
mBytesRead(0)
{
- mPriority &= LLWorkerThread::PRIORITY_LOWBITS;
}
~LLTextureCacheWorker()
{
@@ -129,13 +127,12 @@ public:
virtual bool doWork(S32 param); // Called from LLWorkerThread::processRequest()
- handle_t read() { addWork(0, LLWorkerThread::PRIORITY_HIGH | mPriority); return mRequestHandle; }
- handle_t write() { addWork(1, LLWorkerThread::PRIORITY_HIGH | mPriority); return mRequestHandle; }
+ handle_t read() { addWork(0); return mRequestHandle; }
+ handle_t write() { addWork(1); return mRequestHandle; }
bool complete() { return checkWork(); }
void ioComplete(S32 bytes)
{
mBytesRead = bytes;
- setPriority(LLWorkerThread::PRIORITY_HIGH | mPriority);
}
private:
@@ -145,7 +142,6 @@ private:
protected:
LLTextureCache* mCache;
- U32 mPriority;
LLUUID mID;
U8* mReadData;
@@ -164,11 +160,11 @@ protected:
class LLTextureCacheLocalFileWorker : public LLTextureCacheWorker
{
public:
- LLTextureCacheLocalFileWorker(LLTextureCache* cache, U32 priority, const std::string& filename, const LLUUID& id,
+ LLTextureCacheLocalFileWorker(LLTextureCache* cache, const std::string& filename, const LLUUID& id,
U8* data, S32 datasize, S32 offset,
S32 imagesize, // for writes
LLTextureCache::Responder* responder)
- : LLTextureCacheWorker(cache, priority, id, data, datasize, offset, imagesize, responder),
+ : LLTextureCacheWorker(cache, id, data, datasize, offset, imagesize, responder),
mFileName(filename)
{
@@ -183,6 +179,7 @@ private:
bool LLTextureCacheLocalFileWorker::doRead()
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
S32 local_size = LLAPRFile::size(mFileName, mCache->getLocalAPRFilePool());
if (local_size > 0 && mFileName.size() > 4)
@@ -207,50 +204,6 @@ bool LLTextureCacheLocalFileWorker::doRead()
return true;
}
-#if USE_LFS_READ
- if (mFileHandle == LLLFSThread::nullHandle())
- {
- mImageLocal = TRUE;
- mImageSize = local_size;
- if (!mDataSize || mDataSize + mOffset > local_size)
- {
- mDataSize = local_size - mOffset;
- }
- if (mDataSize <= 0)
- {
- // no more data to read
- mDataSize = 0;
- return true;
- }
- mReadData = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), mDataSize);
- mBytesRead = -1;
- mBytesToRead = mDataSize;
- setPriority(LLWorkerThread::PRIORITY_LOW | mPriority);
- mFileHandle = LLLFSThread::sLocal->read(local_filename, mReadData, mOffset, mDataSize,
- new ReadResponder(mCache, mRequestHandle));
- return false;
- }
- else
- {
- if (mBytesRead >= 0)
- {
- if (mBytesRead != mBytesToRead)
- {
-// LL_WARNS() << "Error reading file from local cache: " << local_filename
-// << " Bytes: " << mDataSize << " Offset: " << mOffset
-// << " / " << mDataSize << LL_ENDL;
- mDataSize = 0; // failed
- ll_aligned_free_16(mReadData);
- mReadData = NULL;
- }
- return true;
- }
- else
- {
- return false;
- }
- }
-#else
if (!mDataSize || mDataSize > local_size)
{
mDataSize = local_size;
@@ -274,7 +227,6 @@ bool LLTextureCacheLocalFileWorker::doRead()
mImageLocal = TRUE;
}
return true;
-#endif
}
bool LLTextureCacheLocalFileWorker::doWrite()
@@ -286,12 +238,12 @@ bool LLTextureCacheLocalFileWorker::doWrite()
class LLTextureCacheRemoteWorker : public LLTextureCacheWorker
{
public:
- LLTextureCacheRemoteWorker(LLTextureCache* cache, U32 priority, const LLUUID& id,
+ LLTextureCacheRemoteWorker(LLTextureCache* cache, const LLUUID& id,
U8* data, S32 datasize, S32 offset,
S32 imagesize, // for writes
LLPointer<LLImageRaw> raw, S32 discardlevel,
LLTextureCache::Responder* responder)
- : LLTextureCacheWorker(cache, priority, id, data, datasize, offset, imagesize, responder),
+ : LLTextureCacheWorker(cache, id, data, datasize, offset, imagesize, responder),
mState(INIT),
mRawImage(raw),
mRawDiscardLevel(discardlevel)
@@ -329,6 +281,7 @@ void LLTextureCacheWorker::startWork(S32 param)
// - the code supports offset reading but this is actually never exercised in the viewer
bool LLTextureCacheRemoteWorker::doRead()
{
+ LL_PROFILE_ZONE_SCOPED;
bool done = false;
S32 idx = -1;
@@ -580,6 +533,7 @@ bool LLTextureCacheRemoteWorker::doRead()
// - the code *does not* support offset writing so there are no difference between buffer addresses and start of data
bool LLTextureCacheRemoteWorker::doWrite()
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
bool done = false;
S32 idx = -1;
@@ -756,6 +710,7 @@ bool LLTextureCacheRemoteWorker::doWrite()
//virtual
bool LLTextureCacheWorker::doWork(S32 param)
{
+ LL_PROFILE_ZONE_SCOPED;
bool res = false;
if (param == 0) // read
{
@@ -775,11 +730,13 @@ bool LLTextureCacheWorker::doWork(S32 param)
//virtual (WORKER THREAD)
void LLTextureCacheWorker::finishWork(S32 param, bool completed)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
if (mResponder.notNull())
{
bool success = (completed && mDataSize > 0);
if (param == 0)
{
+ LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("tcwfw - read");
// read
if (success)
{
@@ -789,12 +746,14 @@ void LLTextureCacheWorker::finishWork(S32 param, bool completed)
}
else
{
+ LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("tcwfw - read fail");
ll_aligned_free_16(mReadData);
mReadData = NULL;
}
}
else
{
+ LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("tcwfw - write");
// write
mWriteData = NULL; // we never owned data
mDataSize = 0;
@@ -806,6 +765,7 @@ void LLTextureCacheWorker::finishWork(S32 param, bool completed)
//virtual (MAIN THREAD)
void LLTextureCacheWorker::endWork(S32 param, bool aborted)
{
+ LL_PROFILE_ZONE_SCOPED;
if (aborted)
{
// Let the destructor handle any cleanup
@@ -861,6 +821,7 @@ LLTextureCache::~LLTextureCache()
//virtual
S32 LLTextureCache::update(F32 max_time_ms)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
static LLFrameTimer timer ;
static const F32 MAX_TIME_INTERVAL = 300.f ; //seconds.
@@ -874,22 +835,6 @@ S32 LLTextureCache::update(F32 max_time_ms)
mCompletedList.clear();
mListMutex.unlock();
- lockWorkers();
-
- for (handle_list_t::iterator iter1 = priorty_list.begin();
- iter1 != priorty_list.end(); ++iter1)
- {
- handle_t handle = *iter1;
- handle_map_t::iterator iter2 = mWriters.find(handle);
- if(iter2 != mWriters.end())
- {
- LLTextureCacheWorker* worker = iter2->second;
- worker->setPriority(LLWorkerThread::PRIORITY_HIGH | worker->mPriority);
- }
- }
-
- unlockWorkers();
-
// call 'completed' with workers list unlocked (may call readComplete() or writeComplete()
for (responder_list_t::iterator iter1 = completed_list.begin();
iter1 != completed_list.end(); ++iter1)
@@ -1324,6 +1269,7 @@ void LLTextureCache::updateEntryTimeStamp(S32 idx, Entry& entry)
//update an existing entry, write to header file immediately.
bool LLTextureCache::updateEntry(S32& idx, Entry& entry, S32 new_image_size, S32 new_data_size)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
S32 new_body_size = llmax(0, new_data_size - TEXTURE_CACHE_ENTRY_SIZE) ;
if(new_image_size == entry.mImageSize && new_body_size == entry.mBodySize)
@@ -1879,6 +1825,7 @@ void LLTextureCache::purgeTextures(bool validate)
// call lockWorkers() first!
LLTextureCacheWorker* LLTextureCache::getReader(handle_t handle)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
LLTextureCacheWorker* res = NULL;
handle_map_t::iterator iter = mReaders.find(handle);
if (iter != mReaders.end())
@@ -1890,6 +1837,7 @@ LLTextureCacheWorker* LLTextureCache::getReader(handle_t handle)
LLTextureCacheWorker* LLTextureCache::getWriter(handle_t handle)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
LLTextureCacheWorker* res = NULL;
handle_map_t::iterator iter = mWriters.find(handle);
if (iter != mWriters.end())
@@ -1905,6 +1853,7 @@ LLTextureCacheWorker* LLTextureCache::getWriter(handle_t handle)
// Reads imagesize from the header, updates timestamp
S32 LLTextureCache::getHeaderCacheEntry(const LLUUID& id, Entry& entry)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
LLMutexLock lock(&mHeaderMutex);
S32 idx = openAndReadEntry(id, entry, false);
if (idx >= 0)
@@ -1917,6 +1866,7 @@ S32 LLTextureCache::getHeaderCacheEntry(const LLUUID& id, Entry& entry)
// Writes imagesize to the header, updates timestamp
S32 LLTextureCache::setHeaderCacheEntry(const LLUUID& id, Entry& entry, S32 imagesize, S32 datasize)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
mHeaderMutex.lock();
S32 idx = openAndReadEntry(id, entry, true); // read or create
mHeaderMutex.unlock();
@@ -1949,13 +1899,14 @@ S32 LLTextureCache::setHeaderCacheEntry(const LLUUID& id, Entry& entry, S32 imag
// Calls from texture pipeline thread (i.e. LLTextureFetch)
-LLTextureCache::handle_t LLTextureCache::readFromCache(const std::string& filename, const LLUUID& id, U32 priority,
+LLTextureCache::handle_t LLTextureCache::readFromCache(const std::string& filename, const LLUUID& id,
S32 offset, S32 size, ReadResponder* responder)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
// Note: checking to see if an entry exists can cause a stall,
// so let the thread handle it
LLMutexLock lock(&mWorkersMutex);
- LLTextureCacheWorker* worker = new LLTextureCacheLocalFileWorker(this, priority, filename, id,
+ LLTextureCacheWorker* worker = new LLTextureCacheLocalFileWorker(this, filename, id,
NULL, size, offset, 0,
responder);
handle_t handle = worker->read();
@@ -1963,13 +1914,14 @@ LLTextureCache::handle_t LLTextureCache::readFromCache(const std::string& filena
return handle;
}
-LLTextureCache::handle_t LLTextureCache::readFromCache(const LLUUID& id, U32 priority,
+LLTextureCache::handle_t LLTextureCache::readFromCache(const LLUUID& id,
S32 offset, S32 size, ReadResponder* responder)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
// Note: checking to see if an entry exists can cause a stall,
// so let the thread handle it
LLMutexLock lock(&mWorkersMutex);
- LLTextureCacheWorker* worker = new LLTextureCacheRemoteWorker(this, priority, id,
+ LLTextureCacheWorker* worker = new LLTextureCacheRemoteWorker(this, id,
NULL, size, offset,
0, NULL, 0, responder);
handle_t handle = worker->read();
@@ -1980,6 +1932,7 @@ LLTextureCache::handle_t LLTextureCache::readFromCache(const LLUUID& id, U32 pri
bool LLTextureCache::readComplete(handle_t handle, bool abort)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
lockWorkers();
handle_map_t::iterator iter = mReaders.find(handle);
LLTextureCacheWorker* worker = NULL;
@@ -2007,7 +1960,7 @@ bool LLTextureCache::readComplete(handle_t handle, bool abort)
return (complete || abort);
}
-LLTextureCache::handle_t LLTextureCache::writeToCache(const LLUUID& id, U32 priority,
+LLTextureCache::handle_t LLTextureCache::writeToCache(const LLUUID& id,
U8* data, S32 datasize, S32 imagesize,
LLPointer<LLImageRaw> rawimage, S32 discardlevel,
WriteResponder* responder)
@@ -2025,7 +1978,7 @@ LLTextureCache::handle_t LLTextureCache::writeToCache(const LLUUID& id, U32 prio
mDoPurge = !mPurgeEntryList.empty();
}
LLMutexLock lock(&mWorkersMutex);
- LLTextureCacheWorker* worker = new LLTextureCacheRemoteWorker(this, priority, id,
+ LLTextureCacheWorker* worker = new LLTextureCacheRemoteWorker(this, id,
data, datasize, 0,
imagesize, rawimage, discardlevel, responder);
handle_t handle = worker->write();
@@ -2093,6 +2046,7 @@ LLPointer<LLImageRaw> LLTextureCache::readFromFastCache(const LLUUID& id, S32& d
//return the fast cache location
bool LLTextureCache::writeToFastCache(LLUUID image_id, S32 id, LLPointer<LLImageRaw> raw, S32 discardlevel)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
//rescale image if needed
if (raw.isNull() || raw->isBufferInvalid() || !raw->getData())
{
diff --git a/indra/newview/lltexturecache.h b/indra/newview/lltexturecache.h
index e1c752b58e..f2a5978a7c 100644
--- a/indra/newview/lltexturecache.h
+++ b/indra/newview/lltexturecache.h
@@ -119,13 +119,13 @@ public:
void setReadOnly(BOOL read_only) ;
S64 initCache(ELLPath location, S64 maxsize, BOOL texture_cache_mismatch);
- handle_t readFromCache(const std::string& local_filename, const LLUUID& id, U32 priority, S32 offset, S32 size,
+ handle_t readFromCache(const std::string& local_filename, const LLUUID& id, S32 offset, S32 size,
ReadResponder* responder);
- handle_t readFromCache(const LLUUID& id, U32 priority, S32 offset, S32 size,
+ handle_t readFromCache(const LLUUID& id, S32 offset, S32 size,
ReadResponder* responder);
bool readComplete(handle_t handle, bool abort);
- handle_t writeToCache(const LLUUID& id, U32 priority, U8* data, S32 datasize, S32 imagesize, LLPointer<LLImageRaw> rawimage, S32 discardlevel,
+ handle_t writeToCache(const LLUUID& id, U8* data, S32 datasize, S32 imagesize, LLPointer<LLImageRaw> rawimage, S32 discardlevel,
WriteResponder* responder);
LLPointer<LLImageRaw> readFromFastCache(const LLUUID& id, S32& discardlevel);
bool writeComplete(handle_t handle, bool abort = false);
diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp
index 0ce82a1297..4849015e79 100644
--- a/indra/newview/lltexturectrl.cpp
+++ b/indra/newview/lltexturectrl.cpp
@@ -41,12 +41,15 @@
#include "llfolderviewmodel.h"
#include "llinventory.h"
#include "llinventoryfunctions.h"
+#include "llinventoryicon.h"
#include "llinventorymodelbackgroundfetch.h"
#include "llinventoryobserver.h"
#include "llinventorypanel.h"
#include "lllineeditor.h"
+#include "llmaterialeditor.h"
#include "llui.h"
#include "llviewerinventory.h"
+#include "llviewermenufile.h" // LLFilePickerReplyThread
#include "llpermissions.h"
#include "llpreviewtexture.h"
#include "llsaleinfo.h"
@@ -70,19 +73,12 @@
#include "llradiogroup.h"
#include "llfloaterreg.h"
#include "lllocalbitmaps.h"
+#include "lllocalgltfmaterials.h"
#include "llerror.h"
#include "llavatarappearancedefines.h"
-static const S32 LOCAL_TRACKING_ID_COLUMN = 1;
-
-//static const char CURRENT_IMAGE_NAME[] = "Current Texture";
-//static const char WHITE_IMAGE_NAME[] = "Blank Texture";
-//static const char NO_IMAGE_NAME[] = "None";
-
-
-
//static
bool get_is_predefined_texture(LLUUID asset_id)
{
@@ -152,7 +148,6 @@ LLFloaterTexturePicker::LLFloaterTexturePicker(
const std::string& label,
PermissionMask immediate_filter_perm_mask,
PermissionMask dnd_filter_perm_mask,
- PermissionMask non_immediate_filter_perm_mask,
BOOL can_apply_immediately,
LLUIImagePtr fallback_image)
: LLFloater(LLSD()),
@@ -171,7 +166,6 @@ LLFloaterTexturePicker::LLFloaterTexturePicker(
mFilterEdit(NULL),
mImmediateFilterPermMask(immediate_filter_perm_mask),
mDnDFilterPermMask(dnd_filter_perm_mask),
- mNonImmediateFilterPermMask(non_immediate_filter_perm_mask),
mContextConeOpacity(0.f),
mSelectedItemPinned( FALSE ),
mCanApply(true),
@@ -181,10 +175,11 @@ LLFloaterTexturePicker::LLFloaterTexturePicker(
mOnFloaterCloseCallback(NULL),
mSetImageAssetIDCallback(NULL),
mOnUpdateImageStatsCallback(NULL),
- mBakeTextureEnabled(FALSE)
+ mBakeTextureEnabled(FALSE),
+ mInventoryPickType(LLTextureCtrl::PICK_TEXTURE)
{
- buildFromFile("floater_texture_ctrl.xml");
mCanApplyImmediately = can_apply_immediately;
+ buildFromFile("floater_texture_ctrl.xml");
setCanMinimize(FALSE);
}
@@ -255,11 +250,8 @@ void LLFloaterTexturePicker::setActive( BOOL active )
void LLFloaterTexturePicker::setCanApplyImmediately(BOOL b)
{
mCanApplyImmediately = b;
- if (!mCanApplyImmediately)
- {
- getChild<LLUICtrl>("apply_immediate_check")->setValue(FALSE);
- }
- updateFilterPermMask();
+
+ getChild<LLUICtrl>("apply_immediate_check")->setValue(mCanApplyImmediately);
}
void LLFloaterTexturePicker::stopUsingPipette()
@@ -272,7 +264,59 @@ void LLFloaterTexturePicker::stopUsingPipette()
void LLFloaterTexturePicker::updateImageStats()
{
- if (mTexturep.notNull())
+ if (mGLTFMaterial.notNull())
+ {
+ S32 width = 0;
+ S32 height = 0;
+
+ bool has_texture = false;
+
+ if (mGLTFMaterial->mBaseColorTexture)
+ {
+ width = llmax(width, mGLTFMaterial->mBaseColorTexture->getFullWidth());
+ height = llmax(height, mGLTFMaterial->mBaseColorTexture->getFullHeight());
+ has_texture = true;
+ }
+ if (mGLTFMaterial->mNormalTexture)
+ {
+ width = llmax(width, mGLTFMaterial->mNormalTexture->getFullWidth());
+ height = llmax(height, mGLTFMaterial->mNormalTexture->getFullHeight());
+ has_texture = true;
+ }
+ if (mGLTFMaterial->mMetallicRoughnessTexture)
+ {
+ width = llmax(width, mGLTFMaterial->mMetallicRoughnessTexture->getFullWidth());
+ height = llmax(height, mGLTFMaterial->mMetallicRoughnessTexture->getFullHeight());
+ has_texture = true;
+ }
+ if (mGLTFMaterial->mEmissiveTexture)
+ {
+ width = llmax(width, mGLTFMaterial->mEmissiveTexture->getFullWidth());
+ height = llmax(height, mGLTFMaterial->mEmissiveTexture->getFullHeight());
+ has_texture = true;
+ }
+
+ if (width > 0 && height > 0)
+ {
+ std::string formatted_dims = llformat("%d x %d", width, height);
+ mResolutionLabel->setTextArg("[DIMENSIONS]", formatted_dims);
+ if (mOnUpdateImageStatsCallback)
+ {
+ mOnUpdateImageStatsCallback(mTexturep);
+ }
+ }
+ else if (has_texture)
+ {
+ // unknown resolution
+ mResolutionLabel->setTextArg("[DIMENSIONS]", std::string("[? x ?]"));
+ }
+ else
+ {
+ // No textures - no applicable resolution (may be show some max value instead?)
+ mResolutionLabel->setTextArg("[DIMENSIONS]", std::string(""));
+ }
+ }
+ else if (mTexturep.notNull())
{
//RN: have we received header data for this image?
if (mTexturep->getFullWidth() > 0 && mTexturep->getFullHeight() > 0)
@@ -306,8 +350,24 @@ BOOL LLFloaterTexturePicker::handleDragAndDrop(
BOOL handled = FALSE;
bool is_mesh = cargo_type == DAD_MESH;
+ bool is_texture = cargo_type == DAD_TEXTURE;
+ bool is_material = cargo_type == DAD_MATERIAL;
+
+ bool allow_dnd = false;
+ if (mInventoryPickType == LLTextureCtrl::PICK_MATERIAL)
+ {
+ allow_dnd = is_material;
+ }
+ else if (mInventoryPickType == LLTextureCtrl::PICK_TEXTURE)
+ {
+ allow_dnd = is_texture || is_mesh;
+ }
+ else
+ {
+ allow_dnd = is_texture || is_mesh || is_material;
+ }
- if ((cargo_type == DAD_TEXTURE) || is_mesh)
+ if (allow_dnd)
{
LLInventoryItem *item = (LLInventoryItem *)cargo_data;
@@ -321,7 +381,6 @@ BOOL LLFloaterTexturePicker::handleDragAndDrop(
if (mod) item_perm_mask |= PERM_MODIFY;
if (xfer) item_perm_mask |= PERM_TRANSFER;
- //PermissionMask filter_perm_mask = getFilterPermMask(); Commented out due to no-copy texture loss.
PermissionMask filter_perm_mask = mDnDFilterPermMask;
if ( (item_perm_mask & filter_perm_mask) == filter_perm_mask )
{
@@ -416,12 +475,8 @@ BOOL LLFloaterTexturePicker::postBuild()
childSetAction("None", LLFloaterTexturePicker::onBtnNone,this);
childSetAction("Blank", LLFloaterTexturePicker::onBtnBlank,this);
-
- childSetCommitCallback("show_folders_check", onShowFolders, this);
- getChildView("show_folders_check")->setVisible( FALSE);
-
- mFilterEdit = getChild<LLFilterEditor>("inventory search editor");
- mFilterEdit->setCommitCallback(boost::bind(&LLFloaterTexturePicker::onFilterEdit, this, _2));
+ mFilterEdit = getChild<LLFilterEditor>("inventory search editor");
+ mFilterEdit->setCommitCallback(boost::bind(&LLFloaterTexturePicker::onFilterEdit, this, _2));
mInventoryPanel = getChild<LLInventoryPanel>("inventory panel");
@@ -431,12 +486,12 @@ BOOL LLFloaterTexturePicker::postBuild()
if(mInventoryPanel)
{
- U32 filter_types = 0x0;
- filter_types |= 0x1 << LLInventoryType::IT_TEXTURE;
- filter_types |= 0x1 << LLInventoryType::IT_SNAPSHOT;
+ // to avoid having to make an assumption about which option is
+ // selected at startup, we call the same function that is triggered
+ // when a texture/materials/both choice is made and let it take care
+ // of setting the filters
+ refreshInventoryFilter();
- mInventoryPanel->setFilterTypes(filter_types);
- //mInventoryPanel->setFilterPermMask(getFilterPermMask()); //Commented out due to no-copy texture loss.
mInventoryPanel->setFilterPermMask(mImmediateFilterPermMask);
mInventoryPanel->setSelectCallback(boost::bind(&LLFloaterTexturePicker::onSelectionChange, this, _1, _2));
mInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
@@ -469,30 +524,23 @@ BOOL LLFloaterTexturePicker::postBuild()
mLocalScrollCtrl = getChild<LLScrollListCtrl>("l_name_list");
mLocalScrollCtrl->setCommitCallback(onLocalScrollCommit, this);
- LLLocalBitmapMgr::getInstance()->feedScrollList(mLocalScrollCtrl);
+ refreshLocalList();
mNoCopyTextureSelected = FALSE;
getChild<LLUICtrl>("apply_immediate_check")->setValue(gSavedSettings.getBOOL("TextureLivePreview"));
childSetCommitCallback("apply_immediate_check", onApplyImmediateCheck, this);
-
- if (!mCanApplyImmediately)
- {
- getChildView("show_folders_check")->setEnabled(FALSE);
- }
+ getChildView("apply_immediate_check")->setEnabled(mCanApplyImmediately);
getChild<LLUICtrl>("Pipette")->setCommitCallback( boost::bind(&LLFloaterTexturePicker::onBtnPipette, this));
childSetAction("Cancel", LLFloaterTexturePicker::onBtnCancel,this);
childSetAction("Select", LLFloaterTexturePicker::onBtnSelect,this);
- // update permission filter once UI is fully initialized
- updateFilterPermMask();
mSavedFolderState.setApply(FALSE);
LLToolPipette::getInstance()->setToolSelectCallback(boost::bind(&LLFloaterTexturePicker::onTextureSelect, this, _1));
getChild<LLComboBox>("l_bake_use_texture_combo_box")->setCommitCallback(onBakeTextureSelect, this);
- getChild<LLCheckBoxCtrl>("hide_base_mesh_region")->setCommitCallback(onHideBaseMeshRegionCheck, this);
setBakeTextureEnabled(TRUE);
return TRUE;
@@ -504,10 +552,11 @@ void LLFloaterTexturePicker::draw()
static LLCachedControl<F32> max_opacity(gSavedSettings, "PickerContextOpacity", 0.4f);
drawConeToOwner(mContextConeOpacity, max_opacity, mOwner);
+ // This is going to spam mOnUpdateImageStatsCallback,
+ // either move elsewhere or fix to cause update once per image
updateImageStats();
// if we're inactive, gray out "apply immediate" checkbox
- getChildView("show_folders_check")->setEnabled(mActive && mCanApplyImmediately && !mNoCopyTextureSelected);
getChildView("Select")->setEnabled(mActive && mCanApply);
getChildView("Pipette")->setEnabled(mActive);
getChild<LLUICtrl>("Pipette")->setValue(LLToolMgr::getInstance()->getCurrentTool() == LLToolPipette::getInstance());
@@ -516,28 +565,38 @@ void LLFloaterTexturePicker::draw()
if( mOwner )
{
mTexturep = NULL;
- if(mImageAssetID.notNull())
- {
- LLPointer<LLViewerFetchedTexture> texture = NULL;
+ mGLTFMaterial = NULL;
+ if (mImageAssetID.notNull())
+ {
+ if (mInventoryPickType == LLTextureCtrl::PICK_MATERIAL)
+ {
+ mGLTFMaterial = (LLFetchedGLTFMaterial*) gGLTFMaterialList.getMaterial(mImageAssetID);
+ }
+ else
+ {
+ LLPointer<LLViewerFetchedTexture> texture = NULL;
- if (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(mImageAssetID))
- {
- LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
- if (obj)
- {
- LLViewerTexture* viewerTexture = obj->getBakedTextureForMagicId(mImageAssetID);
- texture = viewerTexture ? dynamic_cast<LLViewerFetchedTexture*>(viewerTexture) : NULL;
- }
- }
+ if (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(mImageAssetID))
+ {
+ // TODO: Fix this! Picker is not warrantied to be connected to a selection
+ // LLSelectMgr shouldn't be used in texture picker
+ LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
+ if (obj)
+ {
+ LLViewerTexture* viewerTexture = obj->getBakedTextureForMagicId(mImageAssetID);
+ texture = viewerTexture ? dynamic_cast<LLViewerFetchedTexture*>(viewerTexture) : NULL;
+ }
+ }
- if (texture.isNull())
- {
- texture = LLViewerTextureManager::getFetchedTexture(mImageAssetID);
- }
+ if (texture.isNull())
+ {
+ texture = LLViewerTextureManager::getFetchedTexture(mImageAssetID);
+ }
- mTexturep = texture;
- mTexturep->setBoostLevel(LLGLTexture::BOOST_PREVIEW);
- }
+ mTexturep = texture;
+ mTexturep->setBoostLevel(LLGLTexture::BOOST_PREVIEW);
+ }
+ }
if (mTentativeLabel)
{
@@ -545,7 +604,7 @@ void LLFloaterTexturePicker::draw()
}
getChildView("Default")->setEnabled(mImageAssetID != mDefaultImageAssetID || mTentative);
- getChildView("Blank")->setEnabled(mImageAssetID != mBlankImageAssetID || mTentative);
+ getChildView("Blank")->setEnabled((mImageAssetID != mBlankImageAssetID && mBlankImageAssetID.notNull()) || mTentative);
getChildView("None")->setEnabled(mAllowNoTexture && (!mImageAssetID.isNull() || mTentative));
LLFloater::draw();
@@ -664,12 +723,6 @@ const LLUUID& LLFloaterTexturePicker::findItemID(const LLUUID& asset_id, BOOL co
return LLUUID::null;
}
-PermissionMask LLFloaterTexturePicker::getFilterPermMask()
-{
- bool apply_immediate = getChild<LLUICtrl>("apply_immediate_check")->getValue().asBoolean();
- return apply_immediate ? mImmediateFilterPermMask : mNonImmediateFilterPermMask;
-}
-
void LLFloaterTexturePicker::commitIfImmediateSet()
{
if (!mNoCopyTextureSelected && mOnFloaterCommitCallback && mCanApply)
@@ -712,8 +765,9 @@ void LLFloaterTexturePicker::onBtnBlank(void* userdata)
void LLFloaterTexturePicker::onBtnNone(void* userdata)
{
LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
+ self->setCanApply(true, true);
self->setImageID( LLUUID::null );
- self->commitCancel();
+ self->commitIfImmediateSet();
}
/*
@@ -750,8 +804,18 @@ void LLFloaterTexturePicker::onBtnSelect(void* userdata)
{
if (self->mLocalScrollCtrl->getVisible() && !self->mLocalScrollCtrl->getAllSelected().empty())
{
- LLUUID temp_id = self->mLocalScrollCtrl->getFirstSelected()->getColumn(LOCAL_TRACKING_ID_COLUMN)->getValue().asUUID();
- local_id = LLLocalBitmapMgr::getInstance()->getWorldID(temp_id);
+ LLSD data = self->mLocalScrollCtrl->getFirstSelected()->getValue();
+ LLUUID temp_id = data["id"];
+ S32 asset_type = data["type"].asInteger();
+
+ if (LLAssetType::AT_MATERIAL == asset_type)
+ {
+ local_id = LLLocalGLTFMaterialMgr::getInstance()->getWorldID(temp_id);
+ }
+ else
+ {
+ local_id = LLLocalBitmapMgr::getInstance()->getWorldID(temp_id);
+ }
}
}
@@ -823,20 +887,19 @@ void LLFloaterTexturePicker::onModeSelect(LLUICtrl* ctrl, void *userdata)
self->getChild<LLButton>("Default")->setVisible(index == 0 ? TRUE : FALSE);
self->getChild<LLButton>("Blank")->setVisible(index == 0 ? TRUE : FALSE);
self->getChild<LLButton>("None")->setVisible(index == 0 ? TRUE : FALSE);
- self->getChild<LLButton>("Pipette")->setVisible(index == 0 ? TRUE : FALSE);
self->getChild<LLFilterEditor>("inventory search editor")->setVisible(index == 0 ? TRUE : FALSE);
self->getChild<LLInventoryPanel>("inventory panel")->setVisible(index == 0 ? TRUE : FALSE);
- /*self->getChild<LLCheckBox>("show_folders_check")->setVisible(mode);
- no idea under which conditions the above is even shown, needs testing. */
-
self->getChild<LLButton>("l_add_btn")->setVisible(index == 1 ? TRUE : FALSE);
self->getChild<LLButton>("l_rem_btn")->setVisible(index == 1 ? TRUE : FALSE);
self->getChild<LLButton>("l_upl_btn")->setVisible(index == 1 ? TRUE : FALSE);
self->getChild<LLScrollListCtrl>("l_name_list")->setVisible(index == 1 ? TRUE : FALSE);
self->getChild<LLComboBox>("l_bake_use_texture_combo_box")->setVisible(index == 2 ? TRUE : FALSE);
- self->getChild<LLCheckBoxCtrl>("hide_base_mesh_region")->setVisible(FALSE);// index == 2 ? TRUE : FALSE);
+
+ bool pipette_visible = (index == 0)
+ && (self->mInventoryPickType != LLTextureCtrl::PICK_MATERIAL);
+ self->getChild<LLButton>("Pipette")->setVisible(pipette_visible);
if (index == 2)
{
@@ -898,11 +961,20 @@ void LLFloaterTexturePicker::onModeSelect(LLUICtrl* ctrl, void *userdata)
// static
void LLFloaterTexturePicker::onBtnAdd(void* userdata)
{
- if (LLLocalBitmapMgr::getInstance()->addUnit() == true)
- {
- LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
- LLLocalBitmapMgr::getInstance()->feedScrollList(self->mLocalScrollCtrl);
- }
+ LLFloaterTexturePicker* self = (LLFloaterTexturePicker*)userdata;
+
+ if (self->mInventoryPickType == LLTextureCtrl::PICK_TEXTURE_MATERIAL)
+ {
+ LLFilePickerReplyThread::startPicker(boost::bind(&onPickerCallback, _1, self->getHandle()), LLFilePicker::FFLOAD_MATERIAL_TEXTURE, true);
+ }
+ else if (self->mInventoryPickType == LLTextureCtrl::PICK_TEXTURE)
+ {
+ LLFilePickerReplyThread::startPicker(boost::bind(&onPickerCallback, _1, self->getHandle()), LLFilePicker::FFLOAD_IMAGE, true);
+ }
+ else if (self->mInventoryPickType == LLTextureCtrl::PICK_MATERIAL)
+ {
+ LLFilePickerReplyThread::startPicker(boost::bind(&onPickerCallback, _1, self->getHandle()), LLFilePicker::FFLOAD_MATERIAL, true);
+ }
}
// static
@@ -913,22 +985,32 @@ void LLFloaterTexturePicker::onBtnRemove(void* userdata)
if (!selected_items.empty())
{
+
for(std::vector<LLScrollListItem*>::iterator iter = selected_items.begin();
iter != selected_items.end(); iter++)
{
LLScrollListItem* list_item = *iter;
if (list_item)
{
- LLUUID tracking_id = list_item->getColumn(LOCAL_TRACKING_ID_COLUMN)->getValue().asUUID();
- LLLocalBitmapMgr::getInstance()->delUnit(tracking_id);
+ LLSD data = self->mLocalScrollCtrl->getFirstSelected()->getValue();
+ LLUUID tracking_id = data["id"];
+ S32 asset_type = data["type"].asInteger();
+
+ if (LLAssetType::AT_MATERIAL == asset_type)
+ {
+ LLLocalGLTFMaterialMgr::getInstance()->delUnit(tracking_id);
+ }
+ else
+ {
+ LLLocalBitmapMgr::getInstance()->delUnit(tracking_id);
+ }
}
}
self->getChild<LLButton>("l_rem_btn")->setEnabled(false);
self->getChild<LLButton>("l_upl_btn")->setEnabled(false);
- LLLocalBitmapMgr::getInstance()->feedScrollList(self->mLocalScrollCtrl);
+ self->refreshLocalList();
}
-
}
// static
@@ -944,15 +1026,29 @@ void LLFloaterTexturePicker::onBtnUpload(void* userdata)
/* currently only allows uploading one by one, picks the first item from the selection list. (not the vector!)
in the future, it might be a good idea to check the vector size and if more than one units is selected - opt for multi-image upload. */
-
- LLUUID tracking_id = (LLUUID)self->mLocalScrollCtrl->getSelectedItemLabel(LOCAL_TRACKING_ID_COLUMN);
- std::string filename = LLLocalBitmapMgr::getInstance()->getFilename(tracking_id);
- if (!filename.empty())
- {
- LLFloaterReg::showInstance("upload_image", LLSD(filename));
- }
+ LLSD data = self->mLocalScrollCtrl->getFirstSelected()->getValue();
+ LLUUID tracking_id = data["id"];
+ S32 asset_type = data["type"].asInteger();
+ if (LLAssetType::AT_MATERIAL == asset_type)
+ {
+ std::string filename;
+ S32 index;
+ LLLocalGLTFMaterialMgr::getInstance()->getFilenameAndIndex(tracking_id, filename, index);
+ if (!filename.empty())
+ {
+ LLMaterialEditor::loadMaterialFromFile(filename, index);
+ }
+ }
+ else
+ {
+ std::string filename = LLLocalBitmapMgr::getInstance()->getFilename(tracking_id);
+ if (!filename.empty())
+ {
+ LLFloaterReg::showInstance("upload_image", LLSD(filename));
+ }
+ }
}
//static
@@ -968,8 +1064,20 @@ void LLFloaterTexturePicker::onLocalScrollCommit(LLUICtrl* ctrl, void* userdata)
if (has_selection)
{
- LLUUID tracking_id = (LLUUID)self->mLocalScrollCtrl->getSelectedItemLabel(LOCAL_TRACKING_ID_COLUMN);
- LLUUID inworld_id = LLLocalBitmapMgr::getInstance()->getWorldID(tracking_id);
+ LLSD data = self->mLocalScrollCtrl->getFirstSelected()->getValue();
+ LLUUID tracking_id = data["id"];
+ S32 asset_type = data["type"].asInteger();
+ LLUUID inworld_id;
+
+ if (LLAssetType::AT_MATERIAL == asset_type)
+ {
+ inworld_id = LLLocalGLTFMaterialMgr::getInstance()->getWorldID(tracking_id);
+ }
+ else
+ {
+ inworld_id = LLLocalBitmapMgr::getInstance()->getWorldID(tracking_id);
+ }
+
if (self->mSetImageAssetIDCallback)
{
self->mSetImageAssetIDCallback(inworld_id);
@@ -986,22 +1094,6 @@ void LLFloaterTexturePicker::onLocalScrollCommit(LLUICtrl* ctrl, void* userdata)
}
// static
-void LLFloaterTexturePicker::onShowFolders(LLUICtrl* ctrl, void *user_data)
-{
- LLCheckBoxCtrl* check_box = (LLCheckBoxCtrl*)ctrl;
- LLFloaterTexturePicker* picker = (LLFloaterTexturePicker*)user_data;
-
- if (check_box->get())
- {
- picker->mInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
- }
- else
- {
- picker->mInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_NO_FOLDERS);
- }
-}
-
-// static
void LLFloaterTexturePicker::onApplyImmediateCheck(LLUICtrl* ctrl, void *user_data)
{
LLFloaterTexturePicker* picker = (LLFloaterTexturePicker*)user_data;
@@ -1009,7 +1101,6 @@ void LLFloaterTexturePicker::onApplyImmediateCheck(LLUICtrl* ctrl, void *user_da
LLCheckBoxCtrl* check_box = (LLCheckBoxCtrl*)ctrl;
gSavedSettings.setBOOL("TextureLivePreview", check_box->get());
- picker->updateFilterPermMask();
picker->commitIfImmediateSet();
}
@@ -1086,18 +1177,6 @@ void LLFloaterTexturePicker::onBakeTextureSelect(LLUICtrl* ctrl, void *user_data
}
}
-//static
-void LLFloaterTexturePicker::onHideBaseMeshRegionCheck(LLUICtrl* ctrl, void *user_data)
-{
- //LLFloaterTexturePicker* picker = (LLFloaterTexturePicker*)user_data;
- //LLCheckBoxCtrl* check_box = (LLCheckBoxCtrl*)ctrl;
-}
-
-void LLFloaterTexturePicker::updateFilterPermMask()
-{
- //mInventoryPanel->setFilterPermMask( getFilterPermMask() ); Commented out due to no-copy texture loss.
-}
-
void LLFloaterTexturePicker::setCanApply(bool can_preview, bool can_apply)
{
getChildRef<LLUICtrl>("Select").setEnabled(can_apply);
@@ -1143,6 +1222,48 @@ void LLFloaterTexturePicker::onFilterEdit(const std::string& search_string )
mInventoryPanel->setFilterSubString(search_string);
}
+void LLFloaterTexturePicker::refreshLocalList()
+{
+ mLocalScrollCtrl->clearRows();
+
+ if (mInventoryPickType == LLTextureCtrl::PICK_TEXTURE_MATERIAL)
+ {
+ LLLocalBitmapMgr::getInstance()->feedScrollList(mLocalScrollCtrl);
+ LLLocalGLTFMaterialMgr::getInstance()->feedScrollList(mLocalScrollCtrl);
+ }
+ else if (mInventoryPickType == LLTextureCtrl::PICK_TEXTURE)
+ {
+ LLLocalBitmapMgr::getInstance()->feedScrollList(mLocalScrollCtrl);
+ }
+ else if (mInventoryPickType == LLTextureCtrl::PICK_MATERIAL)
+ {
+ LLLocalGLTFMaterialMgr::getInstance()->feedScrollList(mLocalScrollCtrl);
+ }
+}
+
+void LLFloaterTexturePicker::refreshInventoryFilter()
+{
+ U32 filter_types = 0x0;
+
+ if (mInventoryPickType == LLTextureCtrl::PICK_TEXTURE_MATERIAL)
+ {
+ filter_types |= 0x1 << LLInventoryType::IT_TEXTURE;
+ filter_types |= 0x1 << LLInventoryType::IT_SNAPSHOT;
+ filter_types |= 0x1 << LLInventoryType::IT_MATERIAL;
+ }
+ else if (mInventoryPickType == LLTextureCtrl::PICK_TEXTURE)
+ {
+ filter_types |= 0x1 << LLInventoryType::IT_TEXTURE;
+ filter_types |= 0x1 << LLInventoryType::IT_SNAPSHOT;
+ }
+ else if (mInventoryPickType == LLTextureCtrl::PICK_MATERIAL)
+ {
+ filter_types |= 0x1 << LLInventoryType::IT_MATERIAL;
+ }
+
+ mInventoryPanel->setFilterTypes(filter_types);
+}
+
void LLFloaterTexturePicker::setLocalTextureEnabled(BOOL enabled)
{
mModeSelector->setEnabledByValue(1, enabled);
@@ -1170,13 +1291,97 @@ void LLFloaterTexturePicker::setBakeTextureEnabled(BOOL enabled)
onModeSelect(0, this);
}
+void LLFloaterTexturePicker::setInventoryPickType(LLTextureCtrl::EPickInventoryType type)
+{
+ mInventoryPickType = type;
+ refreshLocalList();
+ refreshInventoryFilter();
+
+ if (mInventoryPickType == LLTextureCtrl::PICK_MATERIAL)
+ {
+ getChild<LLButton>("Pipette")->setVisible(false);
+ }
+ else
+ {
+ S32 index = mModeSelector->getValue().asInteger();
+ getChild<LLButton>("Pipette")->setVisible(index == 0);
+ }
+
+ if (!mLabel.empty())
+ {
+ std::string pick = getString("pick title");
+
+ setTitle(pick + mLabel);
+ }
+ else if(mInventoryPickType == LLTextureCtrl::PICK_MATERIAL)
+ {
+ setTitle(getString("pick_material"));
+ }
+ else
+ {
+ setTitle(getString("pick_texture"));
+ }
+}
+
+void LLFloaterTexturePicker::onPickerCallback(const std::vector<std::string>& filenames, LLHandle<LLFloater> handle)
+{
+ std::vector<std::string>::const_iterator iter = filenames.begin();
+ while (iter != filenames.end())
+ {
+ if (!iter->empty())
+ {
+ std::string temp_exten = gDirUtilp->getExtension(*iter);
+ if (temp_exten == "gltf" || temp_exten == "glb")
+ {
+ LLLocalGLTFMaterialMgr::getInstance()->addUnit(*iter);
+ }
+ else
+ {
+ LLLocalBitmapMgr::getInstance()->addUnit(*iter);
+ }
+ }
+ iter++;
+ }
+
+ // Todo: this should referesh all pickers, not just a current one
+ if (!handle.isDead())
+ {
+ LLFloaterTexturePicker* self = (LLFloaterTexturePicker*)handle.get();
+ self->mLocalScrollCtrl->clearRows();
+
+ if (self->mInventoryPickType == LLTextureCtrl::PICK_TEXTURE_MATERIAL)
+ {
+ LLLocalBitmapMgr::getInstance()->feedScrollList(self->mLocalScrollCtrl);
+ LLLocalGLTFMaterialMgr::getInstance()->feedScrollList(self->mLocalScrollCtrl);
+ }
+ else if (self->mInventoryPickType == LLTextureCtrl::PICK_TEXTURE)
+ {
+ LLLocalBitmapMgr::getInstance()->feedScrollList(self->mLocalScrollCtrl);
+ }
+ else if (self->mInventoryPickType == LLTextureCtrl::PICK_MATERIAL)
+ {
+ LLLocalGLTFMaterialMgr::getInstance()->feedScrollList(self->mLocalScrollCtrl);
+ }
+ }
+}
+
void LLFloaterTexturePicker::onTextureSelect( const LLTextureEntry& te )
{
LLUUID inventory_item_id = findItemID(te.getID(), TRUE);
if (inventory_item_id.notNull())
{
LLToolPipette::getInstance()->setResult(TRUE, "");
- setImageID(te.getID());
+ if (mInventoryPickType == LLTextureCtrl::PICK_MATERIAL)
+ {
+ // tes have no data about material ids
+ // Plus gltf materials are layered with overrides,
+ // which mean that end result might have no id.
+ LL_WARNS() << "tes have no data about material ids" << LL_ENDL;
+ }
+ else
+ {
+ setImageID(te.getID());
+ }
mNoCopyTextureSelected = FALSE;
LLInventoryItem* itemp = gInventory.getItem(inventory_item_id);
@@ -1208,15 +1413,16 @@ LLTextureCtrl::LLTextureCtrl(const LLTextureCtrl::Params& p)
mOnCloseCallback(NULL),
mOnSelectCallback(NULL),
mBorderColor( p.border_color() ),
- mAllowNoTexture( FALSE ),
+ mAllowNoTexture( p.allow_no_texture ),
mAllowLocalTexture( TRUE ),
mImmediateFilterPermMask( PERM_NONE ),
- mNonImmediateFilterPermMask( PERM_NONE ),
mCanApplyImmediately( FALSE ),
mNeedsRawImageData( FALSE ),
mValid( TRUE ),
mShowLoadingPlaceholder( TRUE ),
mOpenTexPreview(false),
+ mBakeTextureEnabled(true),
+ mInventoryPickType(PICK_TEXTURE),
mImageAssetID(p.image_id),
mDefaultImageAssetID(p.default_image_id),
mDefaultImageName(p.default_image_name),
@@ -1389,7 +1595,6 @@ void LLTextureCtrl::showPicker(BOOL take_focus)
mLabel,
mImmediateFilterPermMask,
mDnDFilterPermMask,
- mNonImmediateFilterPermMask,
mCanApplyImmediately,
mFallbackImage);
mFloaterHandle = floaterp->getHandle();
@@ -1406,14 +1611,10 @@ void LLTextureCtrl::showPicker(BOOL take_focus)
if (texture_floaterp)
{
texture_floaterp->setOnFloaterCommitCallback(boost::bind(&LLTextureCtrl::onFloaterCommit, this, _1, _2));
- }
- if (texture_floaterp)
- {
texture_floaterp->setSetImageAssetIDCallback(boost::bind(&LLTextureCtrl::setImageAssetID, this, _1));
- }
- if (texture_floaterp)
- {
- texture_floaterp->setBakeTextureEnabled(TRUE);
+
+ texture_floaterp->setBakeTextureEnabled(mBakeTextureEnabled);
+ texture_floaterp->setInventoryPickType(mInventoryPickType);
}
LLFloater* root_floater = gFloaterView->getParentFloater(this);
@@ -1476,8 +1677,16 @@ BOOL LLTextureCtrl::handleMouseDown(S32 x, S32 y, MASK mask)
if (!mOpenTexPreview)
{
showPicker(FALSE);
- //grab textures first...
- LLInventoryModelBackgroundFetch::instance().start(gInventory.findCategoryUUIDForType(LLFolderType::FT_TEXTURE));
+ if (mInventoryPickType == LLTextureCtrl::PICK_MATERIAL)
+ {
+ //grab materials first...
+ LLInventoryModelBackgroundFetch::instance().start(gInventory.findCategoryUUIDForType(LLFolderType::FT_MATERIAL));
+ }
+ else
+ {
+ //grab textures first...
+ LLInventoryModelBackgroundFetch::instance().start(gInventory.findCategoryUUIDForType(LLFolderType::FT_TEXTURE));
+ }
//...then start full inventory fetch.
LLInventoryModelBackgroundFetch::instance().start();
handled = TRUE;
@@ -1521,9 +1730,9 @@ void LLTextureCtrl::onFloaterClose()
void LLTextureCtrl::onFloaterCommit(ETexturePickOp op, LLUUID id)
{
- LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get();
+ LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get();
- if( floaterp && getEnabled())
+ if( floaterp && getEnabled())
{
if (op == TEXTURE_CANCEL)
mViewModel->resetDirty();
@@ -1544,15 +1753,15 @@ void LLTextureCtrl::onFloaterCommit(ETexturePickOp op, LLUUID id)
}
else
{
- mImageItemID = floaterp->findItemID(floaterp->getAssetID(), FALSE);
- LL_DEBUGS() << "mImageItemID: " << mImageItemID << LL_ENDL;
- mImageAssetID = floaterp->getAssetID();
- LL_DEBUGS() << "mImageAssetID: " << mImageAssetID << LL_ENDL;
+ mImageItemID = floaterp->findItemID(floaterp->getAssetID(), FALSE);
+ LL_DEBUGS() << "mImageItemID: " << mImageItemID << LL_ENDL;
+ mImageAssetID = floaterp->getAssetID();
+ LL_DEBUGS() << "mImageAssetID: " << mImageAssetID << LL_ENDL;
}
if (op == TEXTURE_SELECT && mOnSelectCallback)
{
- mOnSelectCallback( this, LLSD() );
+ mOnSelectCallback(this, LLSD());
}
else if (op == TEXTURE_CANCEL && mOnCancelCallback)
{
@@ -1563,8 +1772,10 @@ void LLTextureCtrl::onFloaterCommit(ETexturePickOp op, LLUUID id)
// If the "no_commit_on_selection" parameter is set
// we commit only when user presses OK in the picker
// (i.e. op == TEXTURE_SELECT) or texture changes via DnD.
- if (mCommitOnSelection || op == TEXTURE_SELECT)
- onCommit();
+ if (mCommitOnSelection || op == TEXTURE_SELECT)
+ {
+ onCommit();
+ }
}
}
}
@@ -1609,8 +1820,9 @@ void LLTextureCtrl::setImageAssetID( const LLUUID& asset_id )
}
}
-void LLTextureCtrl::setBakeTextureEnabled(BOOL enabled)
+void LLTextureCtrl::setBakeTextureEnabled(bool enabled)
{
+ mBakeTextureEnabled = enabled;
LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get();
if (floaterp)
{
@@ -1618,6 +1830,16 @@ void LLTextureCtrl::setBakeTextureEnabled(BOOL enabled)
}
}
+void LLTextureCtrl::setInventoryPickType(EPickInventoryType type)
+{
+ mInventoryPickType = type;
+ LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get();
+ if (floaterp)
+ {
+ floaterp->setInventoryPickType(type);
+ }
+}
+
BOOL LLTextureCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask,
BOOL drop, EDragAndDropType cargo_type, void *cargo_data,
EAcceptance *accept,
@@ -1629,11 +1851,26 @@ BOOL LLTextureCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask,
// returns true, then the cast was valid, and we can perform
// the third test without problems.
LLInventoryItem* item = (LLInventoryItem*)cargo_data;
- bool is_mesh = cargo_type == DAD_MESH;
- if (getEnabled() &&
- ((cargo_type == DAD_TEXTURE) || is_mesh) &&
- allowDrop(item))
+ bool is_mesh = cargo_type == DAD_MESH;
+ bool is_texture = cargo_type == DAD_TEXTURE;
+ bool is_material = cargo_type == DAD_MATERIAL;
+
+ bool allow_dnd = false;
+ if (mInventoryPickType == LLTextureCtrl::PICK_MATERIAL)
+ {
+ allow_dnd = is_material;
+ }
+ else if (mInventoryPickType == LLTextureCtrl::PICK_TEXTURE)
+ {
+ allow_dnd = is_texture || is_mesh;
+ }
+ else
+ {
+ allow_dnd = is_texture || is_mesh || is_material;
+ }
+
+ if (getEnabled() && allow_dnd && allowDrop(item, cargo_type, tooltip_msg))
{
if (drop)
{
@@ -1697,7 +1934,7 @@ void LLTextureCtrl::draw()
}
else//mImageAssetID == LLUUID::null
{
- mTexturep = NULL;
+ mTexturep = NULL;
}
// Border
@@ -1785,7 +2022,7 @@ void LLTextureCtrl::draw()
LLUICtrl::draw();
}
-BOOL LLTextureCtrl::allowDrop(LLInventoryItem* item)
+BOOL LLTextureCtrl::allowDrop(LLInventoryItem* item, EDragAndDropType cargo_type, std::string& tooltip_msg)
{
BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID());
BOOL mod = item->getPermissions().allowModifyBy(gAgent.getID());
@@ -1797,8 +2034,6 @@ BOOL LLTextureCtrl::allowDrop(LLInventoryItem* item)
if (mod) item_perm_mask |= PERM_MODIFY;
if (xfer) item_perm_mask |= PERM_TRANSFER;
-// PermissionMask filter_perm_mask = mCanApplyImmediately ? commented out due to no-copy texture loss.
-// mImmediateFilterPermMask : mNonImmediateFilterPermMask;
PermissionMask filter_perm_mask = mImmediateFilterPermMask;
if ( (item_perm_mask & filter_perm_mask) == filter_perm_mask )
{
@@ -1813,6 +2048,12 @@ BOOL LLTextureCtrl::allowDrop(LLInventoryItem* item)
}
else
{
+ PermissionMask mask = PERM_COPY | PERM_TRANSFER;
+ if ((filter_perm_mask & mask) == mask
+ && cargo_type == DAD_TEXTURE)
+ {
+ tooltip_msg.assign(LLTrans::getString("TooltipTextureRestrictedDrop"));
+ }
return FALSE;
}
}
diff --git a/indra/newview/lltexturectrl.h b/indra/newview/lltexturectrl.h
index fbb38c4464..c66e618782 100644
--- a/indra/newview/lltexturectrl.h
+++ b/indra/newview/lltexturectrl.h
@@ -47,6 +47,7 @@ class LLComboBox;
class LLFloaterTexturePicker;
class LLInventoryItem;
class LLViewerFetchedTexture;
+class LLFetchedGLTFMaterial;
// used for setting drag & drop callbacks.
typedef boost::function<BOOL (LLUICtrl*, LLInventoryItem*)> drag_n_drop_callback;
@@ -78,6 +79,13 @@ public:
TEXTURE_CANCEL
} ETexturePickOp;
+ typedef enum e_pick_inventory_type
+ {
+ PICK_TEXTURE_MATERIAL = 0,
+ PICK_TEXTURE = 1,
+ PICK_MATERIAL = 2,
+ } EPickInventoryType;
+
public:
struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
{
@@ -101,7 +109,7 @@ public:
: image_id("image"),
default_image_id("default_image_id"),
default_image_name("default_image_name"),
- allow_no_texture("allow_no_texture"),
+ allow_no_texture("allow_no_texture", false),
can_apply_immediately("can_apply_immediately"),
no_commit_on_selection("no_commit_on_selection", false),
label_width("label_width", -1),
@@ -180,10 +188,7 @@ public:
{ mImmediateFilterPermMask = mask; }
void setDnDFilterPermMask(PermissionMask mask)
{ mDnDFilterPermMask = mask; }
- void setNonImmediateFilterPermMask(PermissionMask mask)
- { mNonImmediateFilterPermMask = mask; }
PermissionMask getImmediateFilterPermMask() { return mImmediateFilterPermMask; }
- PermissionMask getNonImmediateFilterPermMask() { return mNonImmediateFilterPermMask; }
void closeDependentFloater();
@@ -212,10 +217,14 @@ public:
LLViewerFetchedTexture* getTexture() { return mTexturep; }
- void setBakeTextureEnabled(BOOL enabled);
+ void setBakeTextureEnabled(bool enabled);
+ bool getBakeTextureEnabled() const { return mBakeTextureEnabled; }
+
+ void setInventoryPickType(EPickInventoryType type);
+ EPickInventoryType getInventoryPickType() { return mInventoryPickType; };
private:
- BOOL allowDrop(LLInventoryItem* item);
+ BOOL allowDrop(LLInventoryItem* item, EDragAndDropType cargo_type, std::string& tooltip_msg);
BOOL doDrop(LLInventoryItem* item);
private:
@@ -241,7 +250,6 @@ private:
BOOL mAllowLocalTexture;
PermissionMask mImmediateFilterPermMask;
PermissionMask mDnDFilterPermMask;
- PermissionMask mNonImmediateFilterPermMask;
BOOL mCanApplyImmediately;
BOOL mCommitOnSelection;
BOOL mNeedsRawImageData;
@@ -251,7 +259,8 @@ private:
std::string mLoadingPlaceholderString;
S32 mLabelWidth;
bool mOpenTexPreview;
- BOOL mBakeTextureEnabled;
+ bool mBakeTextureEnabled;
+ LLTextureCtrl::EPickInventoryType mInventoryPickType;
};
//////////////////////////////////////////////////////////////////////////////////////////
@@ -274,7 +283,6 @@ public:
const std::string& label,
PermissionMask immediate_filter_perm_mask,
PermissionMask dnd_filter_perm_mask,
- PermissionMask non_immediate_filter_perm_mask,
BOOL can_apply_immediately,
LLUIImagePtr fallback_image_name
);
@@ -305,9 +313,7 @@ public:
LLView* getOwner() const { return mOwner; }
void setOwner(LLView* owner) { mOwner = owner; }
void stopUsingPipette();
- PermissionMask getFilterPermMask();
- void updateFilterPermMask();
void commitIfImmediateSet();
void commitCancel();
@@ -329,9 +335,7 @@ public:
//static void onBtnRevert( void* userdata );
static void onBtnBlank(void* userdata);
static void onBtnNone(void* userdata);
- static void onBtnClear(void* userdata);
void onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action);
- static void onShowFolders(LLUICtrl* ctrl, void* userdata);
static void onApplyImmediateCheck(LLUICtrl* ctrl, void* userdata);
void onTextureSelect(const LLTextureEntry& te);
@@ -342,13 +346,20 @@ public:
static void onLocalScrollCommit(LLUICtrl* ctrl, void* userdata);
static void onBakeTextureSelect(LLUICtrl* ctrl, void *userdata);
- static void onHideBaseMeshRegionCheck(LLUICtrl* ctrl, void *userdata);
void setLocalTextureEnabled(BOOL enabled);
void setBakeTextureEnabled(BOOL enabled);
+ void setInventoryPickType(LLTextureCtrl::EPickInventoryType type);
+
+ static void onPickerCallback(const std::vector<std::string>& filenames, LLHandle<LLFloater> handle);
+
protected:
+ void refreshLocalList();
+ void refreshInventoryFilter();
+
LLPointer<LLViewerTexture> mTexturep;
+ LLPointer<LLFetchedGLTFMaterial> mGLTFMaterial;
LLView* mOwner;
LLUUID mImageAssetID; // Currently selected texture
@@ -372,7 +383,6 @@ protected:
LLInventoryPanel* mInventoryPanel;
PermissionMask mImmediateFilterPermMask;
PermissionMask mDnDFilterPermMask;
- PermissionMask mNonImmediateFilterPermMask;
BOOL mCanApplyImmediately;
BOOL mNoCopyTextureSelected;
F32 mContextConeOpacity;
@@ -386,6 +396,7 @@ private:
bool mCanApply;
bool mCanPreview;
bool mPreviewSettingChanged;
+ LLTextureCtrl::EPickInventoryType mInventoryPickType;
texture_selected_callback mTextureSelectedCallback;
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index a7dcb1a9bb..639e570ee7 100644
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -62,8 +62,6 @@
#include "llcorehttputil.h"
#include "llhttpretrypolicy.h"
-bool LLTextureFetchDebugger::sDebuggerEnabled = false ;
-
LLTrace::CountStatHandle<F64> LLTextureFetch::sCacheHit("texture_cache_hit");
LLTrace::CountStatHandle<F64> LLTextureFetch::sCacheAttempt("texture_cache_attempt");
LLTrace::EventStatHandle<LLUnit<F32, LLUnits::Percent> > LLTextureFetch::sCacheHitRate("texture_cache_hits");
@@ -213,35 +211,17 @@ const std::string sTesterName("TextureFetchTester");
//
// Worker State Machine
//
-// (ASCII art needed)
-//
-//
-// Priority Scheme
-//
-// [PRIORITY_LOW, PRIORITY_NORMAL) - for WAIT_HTTP_RESOURCE state
-// and other wait states
-// [PRIORITY_HIGH, PRIORITY_URGENT) - External event delivered,
-// rapidly transitioning through states,
-// no waiting allowed
-//
-// By itself, the above work queue model would fail the concurrency
-// and liveness requirements of the interface. A high priority
-// request could find itself on the head and stalled for external
-// reasons (see VWR-28996). So a few additional constraints are
-// required to keep things running:
-// * Anything that can make forward progress must be kept at a
-// higher priority than anything that can't.
-// * On completion of external events, the associated request
-// needs to be elevated beyond the normal range to handle
-// any data delivery and release any external resource.
-//
-// This effort is made to keep higher-priority entities moving
-// forward in their state machines at every possible step of
-// processing. It's not entirely proven that this produces the
-// experiencial benefits promised.
+// "doWork" will be executed for a given worker on its respective
+// LLQueuedThread. If doWork returns true, the worker is treated
+// as completed. If doWork returns false, the worker will be
+// put on the back of the work queue at the start of the next iteration
+// of the mainloop. If a worker is waiting on a resource, it should
+// return false as soon as possible and not block to avoid starving
+// other workers of cpu cycles.
//
+
//////////////////////////////////////////////////////////////////////////////
// Tuning/Parameterization Constants
@@ -262,8 +242,8 @@ static const S32 HTTP_REQUESTS_RANGE_END_MAX = 20000000;
//////////////////////////////////////////////////////////////////////////////
namespace
{
- // The NoOpDeletor is used when passing certain objects (the LLTextureFetchWorker and
- // the LLTextureFetchDebugger) in a smart pointer below for passage into
+ // The NoOpDeletor is used when passing certain objects (the LLTextureFetchWorker)
+ // in a smart pointer below for passage into
// the LLCore::Http libararies. When the smart pointer is destroyed, no
// action will be taken since we do not in these cases want the object to
// be destroyed at the end of the call.
@@ -300,7 +280,6 @@ class LLTextureFetchWorker : public LLWorkerClass, public LLCore::HttpHandler
{
friend class LLTextureFetch;
- friend class LLTextureFetchDebugger;
private:
class CacheReadResponder : public LLTextureCache::ReadResponder
@@ -385,14 +364,7 @@ private:
bool operator()(const LLTextureFetchWorker* lhs, const LLTextureFetchWorker* rhs) const
{
// greater priority is "less"
- const F32 lpriority = lhs->mImagePriority;
- const F32 rpriority = rhs->mImagePriority;
- if (lpriority > rpriority) // higher priority
- return true;
- else if (lpriority < rpriority)
- return false;
- else
- return lhs < rhs;
+ return lhs->mImagePriority > rhs->mImagePriority;
}
};
@@ -482,6 +454,9 @@ private:
// Locks: Mw
void resetFormattedData();
+ // get the relative priority of this worker (should map to max virtual size)
+ F32 getImagePriority() const;
+
// Locks: Mw
void setImagePriority(F32 priority);
@@ -496,9 +471,6 @@ private:
void clearPackets();
- // Locks: Mw (ctor invokes without lock)
- U32 calcWorkPriority();
-
// Locks: Mw
void removeFromCache();
@@ -565,16 +537,13 @@ private:
LLHost mHost;
std::string mUrl;
U8 mType;
- F32 mImagePriority;
- U32 mWorkPriority;
+ F32 mImagePriority; // should map to max virtual size
F32 mRequestedPriority;
S32 mDesiredDiscard;
S32 mSimRequestedDiscard;
S32 mRequestedDiscard;
S32 mLoadedDiscard;
S32 mDecodedDiscard;
- S32 mFullWidth;
- S32 mFullHeight;
LLFrameTimer mRequestedDeltaTimer;
LLFrameTimer mFetchDeltaTimer;
LLTimer mCacheReadTimer;
@@ -913,7 +882,6 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher,
mHost(host),
mUrl(url),
mImagePriority(priority),
- mWorkPriority(0),
mRequestedPriority(0.f),
mDesiredDiscard(-1),
mSimRequestedDiscard(-1),
@@ -960,15 +928,13 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher,
mCacheReadCount(0U),
mCacheWriteCount(0U),
mResourceWaitCount(0U),
- mFetchRetryPolicy(10.0,3600.0,2.0,10)
+ mFetchRetryPolicy(10.f,3600.f,2.f,10)
{
- calcWorkPriority();
mType = host.isOk() ? LLImageBase::TYPE_AVATAR_BAKE : LLImageBase::TYPE_NORMAL;
// LL_INFOS(LOG_TXT) << "Create: " << mID << " mHost:" << host << " Discard=" << discard << LL_ENDL;
if (!mFetcher->mDebugPause)
{
- U32 work_priority = mWorkPriority | LLWorkerThread::PRIORITY_HIGH;
- addWork(0, work_priority );
+ addWork(0);
}
setDesiredDiscard(discard, size);
}
@@ -1026,16 +992,6 @@ void LLTextureFetchWorker::clearPackets()
}
// Locks: Mw (ctor invokes without lock)
-U32 LLTextureFetchWorker::calcWorkPriority()
-{
- //llassert_always(mImagePriority >= 0 && mImagePriority <= LLViewerFetchedTexture::maxDecodePriority());
- static const F32 PRIORITY_SCALE = (F32)LLWorkerThread::PRIORITY_LOWBITS / LLViewerFetchedTexture::maxDecodePriority();
-
- mWorkPriority = llmin((U32)LLWorkerThread::PRIORITY_LOWBITS, (U32)(mImagePriority * PRIORITY_SCALE));
- return mWorkPriority;
-}
-
-// Locks: Mw (ctor invokes without lock)
void LLTextureFetchWorker::setDesiredDiscard(S32 discard, S32 size)
{
bool prioritize = false;
@@ -1043,11 +999,9 @@ void LLTextureFetchWorker::setDesiredDiscard(S32 discard, S32 size)
{
if (!haveWork())
{
- calcWorkPriority();
if (!mFetcher->mDebugPause)
{
- U32 work_priority = mWorkPriority | LLWorkerThread::PRIORITY_HIGH;
- addWork(0, work_priority);
+ addWork(0);
}
}
else if (mDesiredDiscard < discard)
@@ -1066,23 +1020,13 @@ void LLTextureFetchWorker::setDesiredDiscard(S32 discard, S32 size)
if ((prioritize && mState == INIT) || mState == DONE)
{
setState(INIT);
- U32 work_priority = mWorkPriority | LLWorkerThread::PRIORITY_HIGH;
- setPriority(work_priority);
}
}
// Locks: Mw
void LLTextureFetchWorker::setImagePriority(F32 priority)
{
-// llassert_always(priority >= 0 && priority <= LLViewerTexture::maxDecodePriority());
- F32 delta = fabs(priority - mImagePriority);
- if (delta > (mImagePriority * .05f) || mState == DONE)
- {
- mImagePriority = priority;
- calcWorkPriority();
- U32 work_priority = mWorkPriority | (getPriority() & LLWorkerThread::PRIORITY_HIGHBITS);
- setPriority(work_priority);
- }
+ mImagePriority = priority; //should map to max virtual size, abort if zero
}
// Locks: Mw
@@ -1102,6 +1046,11 @@ void LLTextureFetchWorker::resetFormattedData()
mHaveAllData = FALSE;
}
+F32 LLTextureFetchWorker::getImagePriority() const
+{
+ return mImagePriority;
+}
+
// Threads: Tmain
void LLTextureFetchWorker::startWork(S32 param)
{
@@ -1111,7 +1060,7 @@ void LLTextureFetchWorker::startWork(S32 param)
// Threads: Ttf
bool LLTextureFetchWorker::doWork(S32 param)
{
- LL_PROFILE_ZONE_SCOPED;
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD;
if (gNonInteractive)
{
return true;
@@ -1126,20 +1075,23 @@ bool LLTextureFetchWorker::doWork(S32 param)
{
if (mState < DECODE_IMAGE)
{
+ LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - state < decode");
return true; // abort
}
}
- if(mImagePriority < F_ALMOST_ZERO)
+ if (mImagePriority < F_ALMOST_ZERO)
{
if (mState == INIT || mState == LOAD_FROM_NETWORK)
{
+ LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - priority < 0");
LL_DEBUGS(LOG_TXT) << mID << " abort: mImagePriority < F_ALMOST_ZERO" << LL_ENDL;
return true; // abort
}
}
if(mState > CACHE_POST && !mCanUseHTTP)
{
+ LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - state > cache_post");
//nowhere to get data, abort.
LL_WARNS(LOG_TXT) << mID << " abort, nowhere to get data" << LL_ENDL;
return true ;
@@ -1161,6 +1113,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
if (mState == INIT)
{
+ LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - INIT");
mStateTimer.reset();
mFetchTimer.reset();
for(auto i : LOGGED_STATES)
@@ -1202,15 +1155,16 @@ bool LLTextureFetchWorker::doWork(S32 param)
if (mState == LOAD_FROM_TEXTURE_CACHE)
{
+ LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - LOAD_FROM_TEXTURE_CACHE");
if (mCacheReadHandle == LLTextureCache::nullHandle())
{
- U32 cache_priority = mWorkPriority;
S32 offset = mFormattedImage.notNull() ? mFormattedImage->getDataSize() : 0;
S32 size = mDesiredSize - offset;
if (size <= 0)
{
setState(CACHE_POST);
- return false;
+ return doWork(param);
+ // return false;
}
mFileSize = 0;
mLoaded = FALSE;
@@ -1219,35 +1173,28 @@ bool LLTextureFetchWorker::doWork(S32 param)
if (mUrl.compare(0, 7, "file://") == 0)
{
- setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it
-
// read file from local disk
++mCacheReadCount;
std::string filename = mUrl.substr(7, std::string::npos);
CacheReadResponder* responder = new CacheReadResponder(mFetcher, mID, mFormattedImage);
mCacheReadTimer.reset();
- mCacheReadHandle = mFetcher->mTextureCache->readFromCache(filename, mID, cache_priority,
- offset, size, responder);
+ mCacheReadHandle = mFetcher->mTextureCache->readFromCache(filename, mID, offset, size, responder);
}
else if ((mUrl.empty() || mFTType==FTT_SERVER_BAKE) && mFetcher->canLoadFromCache())
{
- setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it
-
++mCacheReadCount;
CacheReadResponder* responder = new CacheReadResponder(mFetcher, mID, mFormattedImage);
mCacheReadTimer.reset();
- mCacheReadHandle = mFetcher->mTextureCache->readFromCache(mID, cache_priority,
+ mCacheReadHandle = mFetcher->mTextureCache->readFromCache(mID,
offset, size, responder);;
}
else if(!mUrl.empty() && mCanUseHTTP)
{
- setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
setState(WAIT_HTTP_RESOURCE);
}
else
{
- setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
setState(LOAD_FROM_NETWORK);
}
}
@@ -1280,6 +1227,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
if (mState == CACHE_POST)
{
+ LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - CACHE_POST");
mCachedSize = mFormattedImage.notNull() ? mFormattedImage->getDataSize() : 0;
// Successfully loaded
if ((mCachedSize >= mDesiredSize) || mHaveAllData)
@@ -1321,6 +1269,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
if (mState == LOAD_FROM_NETWORK)
{
+ LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - LOAD_FROM_NETWORK");
// Check for retries to previous server failures.
F32 wait_seconds;
if (mFetchRetryPolicy.shouldRetry(wait_seconds))
@@ -1358,7 +1307,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
{
if (mFTType != FTT_DEFAULT)
{
- LL_WARNS(LOG_TXT) << "trying to seek a non-default texture on the sim. Bad!" << LL_ENDL;
+ LL_WARNS(LOG_TXT) << "Trying to fetch a texture of non-default type by UUID. This probably won't work!" << LL_ENDL;
}
setUrl(http_url + "/?texture_id=" + mID.asString().c_str());
LL_DEBUGS(LOG_TXT) << "Texture URL: " << mUrl << LL_ENDL;
@@ -1386,7 +1335,6 @@ bool LLTextureFetchWorker::doWork(S32 param)
if (mCanUseHTTP && !mUrl.empty())
{
setState(WAIT_HTTP_RESOURCE);
- setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
if(mWriteToCacheState != NOT_WRITE)
{
mWriteToCacheState = CAN_WRITE ;
@@ -1401,6 +1349,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
if (mState == WAIT_HTTP_RESOURCE)
{
+ LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - WAIT_HTTP_RESOURCE");
// NOTE:
// control the number of the http requests issued for:
// 1, not openning too many file descriptors at the same time;
@@ -1411,7 +1360,6 @@ bool LLTextureFetchWorker::doWork(S32 param)
if (mFetcher->getHttpWaitersCount() || ! acquireHttpSemaphore())
{
setState(WAIT_HTTP_RESOURCE2);
- setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);
mFetcher->addHttpWaiter(this->mID);
++mResourceWaitCount;
return false;
@@ -1425,12 +1373,14 @@ bool LLTextureFetchWorker::doWork(S32 param)
if (mState == WAIT_HTTP_RESOURCE2)
{
+ LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - WAIT_HTTP_RESOURCE2");
// Just idle it if we make it to the head...
return false;
}
if (mState == SEND_HTTP_REQ)
{
+ LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - SEND_HTTP_REQ");
// Also used in llmeshrepository
static LLCachedControl<bool> disable_range_req(gSavedSettings, "HttpRangeRequestsDisable", false);
@@ -1451,7 +1401,6 @@ bool LLTextureFetchWorker::doWork(S32 param)
{
// We already have all the data, just decode it
mLoadedDiscard = mFormattedImage->getDiscardLevel();
- setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
if (mLoadedDiscard < 0)
{
LL_WARNS(LOG_TXT) << mID << " mLoadedDiscard is " << mLoadedDiscard
@@ -1459,7 +1408,8 @@ bool LLTextureFetchWorker::doWork(S32 param)
}
setState(DECODE_IMAGE);
releaseHttpSemaphore();
- return false;
+ //return false;
+ return doWork(param);
}
else
{
@@ -1520,7 +1470,6 @@ bool LLTextureFetchWorker::doWork(S32 param)
// by people with questionable ISPs or networking gear that
// doesn't handle these well.
mHttpHandle = mFetcher->mHttpRequest->requestGet(mHttpPolicyClass,
- mWorkPriority,
mUrl,
options,
mFetcher->mHttpHeaders,
@@ -1529,7 +1478,6 @@ bool LLTextureFetchWorker::doWork(S32 param)
else
{
mHttpHandle = mFetcher->mHttpRequest->requestGetByteRange(mHttpPolicyClass,
- mWorkPriority,
mUrl,
mRequestedOffset,
(mRequestedOffset + mRequestedSize) > HTTP_REQUESTS_RANGE_END_MAX
@@ -1554,7 +1502,6 @@ bool LLTextureFetchWorker::doWork(S32 param)
mHttpActive = true;
mFetcher->addToHTTPQueue(mID);
recordTextureStart(true);
- setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);
setState(WAIT_HTTP_REQ);
// fall through
@@ -1562,6 +1509,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
if (mState == WAIT_HTTP_REQ)
{
+ LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - WAIT_HTTP_REQ");
// *NOTE: As stated above, all transitions out of this state should
// call releaseHttpSemaphore().
if (mLoaded)
@@ -1604,7 +1552,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
<< LL_ENDL;
}
- if (mFTType != FTT_SERVER_BAKE)
+ if (mFTType != FTT_SERVER_BAKE && mFTType != FTT_MAP_TILE)
{
mUrl.clear();
}
@@ -1612,7 +1560,6 @@ bool LLTextureFetchWorker::doWork(S32 param)
{
// Use available data
mLoadedDiscard = mFormattedImage->getDiscardLevel();
- setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
if (mLoadedDiscard < 0)
{
LL_WARNS(LOG_TXT) << mID << " mLoadedDiscard is " << mLoadedDiscard
@@ -1620,7 +1567,8 @@ bool LLTextureFetchWorker::doWork(S32 param)
}
setState(DECODE_IMAGE);
releaseHttpSemaphore();
- return false;
+ //return false;
+ return doWork(param);
}
// Fail harder
@@ -1737,9 +1685,9 @@ bool LLTextureFetchWorker::doWork(S32 param)
{
mWriteToCacheState = SHOULD_WRITE ;
}
- setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
releaseHttpSemaphore();
- return false;
+ //return false;
+ return doWork(param);
}
else
{
@@ -1749,17 +1697,16 @@ bool LLTextureFetchWorker::doWork(S32 param)
// an enormous amount of time to load textures. We'll revisit the
// various possible timeout components (total request time, connection
// time, I/O time, with and without retries, etc.) in the future.
-
- setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);
+
return false;
}
}
if (mState == DECODE_IMAGE)
{
+ LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - DECODE_IMAGE");
static LLCachedControl<bool> textures_decode_disabled(gSavedSettings, "TextureDecodeDisabled", false);
- setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it
if (textures_decode_disabled)
{
// for debug use, don't decode
@@ -1798,25 +1745,20 @@ bool LLTextureFetchWorker::doWork(S32 param)
mAuxImage = NULL;
llassert_always(mFormattedImage.notNull());
S32 discard = mHaveAllData ? 0 : mLoadedDiscard;
- U32 image_priority = LLWorkerThread::PRIORITY_NORMAL | mWorkPriority;
mDecoded = FALSE;
setState(DECODE_IMAGE_UPDATE);
LL_DEBUGS(LOG_TXT) << mID << ": Decoding. Bytes: " << mFormattedImage->getDataSize() << " Discard: " << discard
<< " All Data: " << mHaveAllData << LL_ENDL;
- mDecodeHandle = mFetcher->mImageDecodeThread->decodeImage(mFormattedImage, image_priority, discard, mNeedsAux,
+ mDecodeHandle = LLAppViewer::getImageDecodeThread()->decodeImage(mFormattedImage, discard, mNeedsAux,
new DecodeResponder(mFetcher, mID, this));
// fall though
}
if (mState == DECODE_IMAGE_UPDATE)
{
+ LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - DECODE_IMAGE_UPDATE");
if (mDecoded)
{
- if(mFetcher->getFetchDebugger() && !mInLocalCache)
- {
- mFetcher->getFetchDebugger()->addHistoryEntry(this);
- }
-
mDecodeTime = mDecodeTimer.getElapsedTimeF32();
if (mDecodedDiscard < 0)
@@ -1828,9 +1770,9 @@ bool LLTextureFetchWorker::doWork(S32 param)
llassert_always(mDecodeHandle == 0);
mFormattedImage = NULL;
++mRetryAttempt;
- setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
setState(INIT);
- return false;
+ //return false;
+ return doWork(param);
}
else
{
@@ -1843,7 +1785,6 @@ bool LLTextureFetchWorker::doWork(S32 param)
llassert_always(mRawImage.notNull());
LL_DEBUGS(LOG_TXT) << mID << ": Decoded. Discard: " << mDecodedDiscard
<< " Raw Image: " << llformat("%dx%d",mRawImage->getWidth(),mRawImage->getHeight()) << LL_ENDL;
- setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
setState(WRITE_TO_CACHE);
}
// fall through
@@ -1856,12 +1797,14 @@ bool LLTextureFetchWorker::doWork(S32 param)
if (mState == WRITE_TO_CACHE)
{
+ LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - WRITE_TO_CACHE");
if (mWriteToCacheState != SHOULD_WRITE || mFormattedImage.isNull())
{
// If we're in a local cache or we didn't actually receive any new data,
// or we failed to load anything, skip
setState(DONE);
- return false;
+ //return false;
+ return doWork(param);
}
S32 datasize = mFormattedImage->getDataSize();
if(mFileSize < datasize)//This could happen when http fetching and sim fetching mixed.
@@ -1876,8 +1819,6 @@ bool LLTextureFetchWorker::doWork(S32 param)
}
}
llassert_always(datasize);
- setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it
- U32 cache_priority = mWorkPriority;
mWritten = FALSE;
setState(WAIT_ON_WRITE);
++mCacheWriteCount;
@@ -1888,7 +1829,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
// So make sure users of getRequestFinished() does not attempt to modify image while
// fetcher is working
mCacheWriteTimer.reset();
- mCacheWriteHandle = mFetcher->mTextureCache->writeToCache(mID, cache_priority,
+ mCacheWriteHandle = mFetcher->mTextureCache->writeToCache(mID,
mFormattedImage->getData(), datasize,
mFileSize, mRawImage, mDecodedDiscard, responder);
// fall through
@@ -1896,6 +1837,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
if (mState == WAIT_ON_WRITE)
{
+ LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - WAIT_ON_WRITE");
if (writeToCacheComplete())
{
mCacheWriteTime = mCacheWriteTimer.getElapsedTimeF32();
@@ -1917,6 +1859,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
if (mState == DONE)
{
+ LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - DONE");
if (mDecodedDiscard >= 0 && mDesiredDiscard < mDecodedDiscard)
{
// More data was requested, return to INIT
@@ -1924,12 +1867,11 @@ bool LLTextureFetchWorker::doWork(S32 param)
LL_DEBUGS(LOG_TXT) << mID << " more data requested, returning to INIT: "
<< " mDecodedDiscard " << mDecodedDiscard << ">= 0 && mDesiredDiscard " << mDesiredDiscard
<< "<" << " mDecodedDiscard " << mDecodedDiscard << LL_ENDL;
- setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
- return false;
+ // return false;
+ return doWork(param);
}
else
{
- setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);
mFetchTime = mFetchTimer.getElapsedTimeF32();
return true;
}
@@ -1942,6 +1884,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
// virtual
void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response)
{
+ LL_PROFILE_ZONE_SCOPED;
static LLCachedControl<bool> log_to_viewer_log(gSavedSettings, "LogTextureDownloadsToViewerLog", false);
static LLCachedControl<bool> log_to_sim(gSavedSettings, "LogTextureDownloadsToSimulator", false);
static LLCachedControl<bool> log_texture_traffic(gSavedSettings, "LogTextureNetworkTraffic", false) ;
@@ -2051,9 +1994,10 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe
// Threads: Tmain
void LLTextureFetchWorker::endWork(S32 param, bool aborted)
{
+ LL_PROFILE_ZONE_SCOPED;
if (mDecodeHandle != 0)
{
- mFetcher->mImageDecodeThread->abortRequest(mDecodeHandle, false);
+ // LL::ThreadPool has no operation to cancel a particular work item
mDecodeHandle = 0;
}
mFormattedImage = NULL;
@@ -2066,6 +2010,7 @@ void LLTextureFetchWorker::endWork(S32 param, bool aborted)
// virtual
void LLTextureFetchWorker::finishWork(S32 param, bool completed)
{
+ LL_PROFILE_ZONE_SCOPED;
// The following are required in case the work was aborted
if (mCacheReadHandle != LLTextureCache::nullHandle())
{
@@ -2256,7 +2201,6 @@ S32 LLTextureFetchWorker::callbackHttpGet(LLCore::HttpResponse * response,
}
mLoaded = TRUE;
- setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
if (LLViewerStatsRecorder::instanceExists())
{
@@ -2272,6 +2216,7 @@ S32 LLTextureFetchWorker::callbackHttpGet(LLCore::HttpResponse * response,
void LLTextureFetchWorker::callbackCacheRead(bool success, LLImageFormatted* image,
S32 imagesize, BOOL islocal)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
LLMutexLock lock(&mWorkMutex); // +Mw
if (mState != LOAD_FROM_TEXTURE_CACHE)
{
@@ -2291,7 +2236,6 @@ void LLTextureFetchWorker::callbackCacheRead(bool success, LLImageFormatted* ima
}
}
mLoaded = TRUE;
- setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
} // -Mw
// Threads: Ttc
@@ -2304,7 +2248,6 @@ void LLTextureFetchWorker::callbackCacheWrite(bool success)
return;
}
mWritten = TRUE;
- setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
} // -Mw
//////////////////////////////////////////////////////////////////////////////
@@ -2343,7 +2286,6 @@ void LLTextureFetchWorker::callbackDecoded(bool success, LLImageRaw* raw, LLImag
}
mDecoded = TRUE;
// LL_INFOS(LOG_TXT) << mID << " : DECODE COMPLETE " << LL_ENDL;
- setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
} // -Mw
//////////////////////////////////////////////////////////////////////////////
@@ -2406,7 +2348,17 @@ void LLTextureFetchWorker::recordTextureDone(bool is_http, F64 byte_count)
//////////////////////////////////////////////////////////////////////////////
// public
-LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* imagedecodethread, bool threaded, bool qa_mode)
+std::string LLTextureFetch::getStateString(S32 state)
+{
+ if (state < 0 || state > sizeof(e_state_name) / sizeof(char*))
+ {
+ return llformat("%d", state);
+ }
+
+ return e_state_name[state];
+}
+
+LLTextureFetch::LLTextureFetch(LLTextureCache* cache, bool threaded, bool qa_mode)
: LLWorkerThread("TextureFetch", threaded, true),
mDebugCount(0),
mDebugPause(FALSE),
@@ -2415,7 +2367,6 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image
mQueueMutex(),
mNetworkQueueMutex(),
mTextureCache(cache),
- mImageDecodeThread(imagedecodethread),
mTextureBandwidth(0),
mHTTPTextureBits(0),
mTotalHTTPRequests(0),
@@ -2430,10 +2381,8 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image
mTotalCacheReadCount(0U),
mTotalCacheWriteCount(0U),
mTotalResourceWaitCount(0U),
- mFetchDebugger(NULL),
mFetchSource(LLTextureFetch::FROM_ALL),
mOriginFetchSource(LLTextureFetch::FROM_ALL),
- mFetcherLocked(FALSE),
mTextureInfoMainThread(false)
{
mMaxBandwidth = gSavedSettings.getF32("ThrottleBandwidthKBPS");
@@ -2454,21 +2403,6 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image
mHttpLowWater = HTTP_NONPIPE_REQUESTS_LOW_WATER;
mHttpSemaphore = 0;
- // Conditionally construct debugger object after 'this' is
- // fully initialized.
- LLTextureFetchDebugger::sDebuggerEnabled = gSavedSettings.getBOOL("TextureFetchDebuggerEnabled");
- if(LLTextureFetchDebugger::isEnabled())
- {
- mFetchDebugger = new LLTextureFetchDebugger(this, cache, imagedecodethread) ;
- mFetchSource = (e_tex_source)gSavedSettings.getS32("TextureFetchSource");
- if(mFetchSource < 0 && mFetchSource >= INVALID_SOURCE)
- {
- mFetchSource = LLTextureFetch::FROM_ALL;
- gSavedSettings.setS32("TextureFetchSource", 0);
- }
- mOriginFetchSource = mFetchSource;
- }
-
// If that test log has ben requested but not yet created, create it
if (LLMetricPerformanceTesterBasic::isMetricLogRequested(sTesterName) && !LLMetricPerformanceTesterBasic::getTester(sTesterName))
{
@@ -2497,22 +2431,16 @@ LLTextureFetch::~LLTextureFetch()
delete mHttpRequest;
mHttpRequest = NULL;
- delete mFetchDebugger;
- mFetchDebugger = NULL;
-
// ~LLQueuedThread() called here
}
-bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const LLUUID& id, const LLHost& host, F32 priority,
+S32 LLTextureFetch::createRequest(FTType f_type, const std::string& url, const LLUUID& id, const LLHost& host, F32 priority,
S32 w, S32 h, S32 c, S32 desired_discard, bool needs_aux, bool can_use_http)
{
- if(mFetcherLocked)
- {
- return false;
- }
+ LL_PROFILE_ZONE_SCOPED;
if (mDebugPause)
{
- return false;
+ return -1;
}
if (f_type == FTT_SERVER_BAKE)
@@ -2528,7 +2456,7 @@ bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const
<< host << " != " << worker->mHost << LL_ENDL;
removeRequest(worker, true);
worker = NULL;
- return false;
+ return -1;
}
}
@@ -2581,9 +2509,14 @@ bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const
{
if (worker->wasAborted())
{
- return false; // need to wait for previous aborted request to complete
+ return -1; // need to wait for previous aborted request to complete
}
worker->lockWorkMutex(); // +Mw
+ if (worker->mState == LLTextureFetchWorker::DONE && worker->mDesiredSize == llmax(desired_size, TEXTURE_CACHE_ENTRY_SIZE) && worker->mDesiredDiscard == desired_discard) {
+ worker->unlockWorkMutex(); // -Mw
+
+ return -1; // similar request has failed or is in a transitional state
+ }
worker->mActiveCount++;
worker->mNeedsAux = needs_aux;
worker->setImagePriority(priority);
@@ -2597,7 +2530,7 @@ bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const
worker->setState(LLTextureFetchWorker::INIT);
worker->unlockWorkMutex(); // -Mw
- worker->addWork(0, LLWorkerThread::PRIORITY_HIGH | worker->mWorkPriority);
+ worker->addWork(0);
}
else
{
@@ -2617,18 +2550,17 @@ bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const
worker->setCanUseHTTP(can_use_http) ;
worker->unlockWorkMutex(); // -Mw
}
-
+
LL_DEBUGS(LOG_TXT) << "REQUESTED: " << id << " f_type " << fttype_to_string(f_type)
<< " Discard: " << desired_discard << " size " << desired_size << LL_ENDL;
- return true;
+ return desired_discard;
}
-
-
// Threads: T*
//
// protected
void LLTextureFetch::addToHTTPQueue(const LLUUID& id)
{
+ LL_PROFILE_ZONE_SCOPED;
LLMutexLock lock(&mNetworkQueueMutex); // +Mfnq
mHTTPTextureQueue.insert(id);
mTotalHTTPRequests++;
@@ -2637,6 +2569,7 @@ void LLTextureFetch::addToHTTPQueue(const LLUUID& id)
// Threads: T*
void LLTextureFetch::removeFromHTTPQueue(const LLUUID& id, S32Bytes received_size)
{
+ LL_PROFILE_ZONE_SCOPED;
LLMutexLock lock(&mNetworkQueueMutex); // +Mfnq
mHTTPTextureQueue.erase(id);
mHTTPTextureBits += received_size; // Approximate - does not include header bits
@@ -2649,6 +2582,7 @@ void LLTextureFetch::removeFromHTTPQueue(const LLUUID& id, S32Bytes received_siz
// Threads: T*
void LLTextureFetch::deleteRequest(const LLUUID& id, bool cancel)
{
+ LL_PROFILE_ZONE_SCOPED;
lockQueue(); // +Mfq
LLTextureFetchWorker* worker = getWorkerAfterLock(id);
if (worker)
@@ -2674,6 +2608,7 @@ void LLTextureFetch::deleteRequest(const LLUUID& id, bool cancel)
// Threads: T*
void LLTextureFetch::removeRequest(LLTextureFetchWorker* worker, bool cancel)
{
+ LL_PROFILE_ZONE_SCOPED;
if(!worker)
{
return;
@@ -2742,6 +2677,7 @@ U32 LLTextureFetch::getTotalNumHTTPRequests()
// Locks: Mfq
LLTextureFetchWorker* LLTextureFetch::getWorkerAfterLock(const LLUUID& id)
{
+ LL_PROFILE_ZONE_SCOPED;
LLTextureFetchWorker* res = NULL;
map_t::iterator iter = mRequestMap.find(id);
if (iter != mRequestMap.end())
@@ -2765,6 +2701,7 @@ bool LLTextureFetch::getRequestFinished(const LLUUID& id, S32& discard_level,
LLPointer<LLImageRaw>& raw, LLPointer<LLImageRaw>& aux,
LLCore::HttpStatus& last_http_get_status)
{
+ LL_PROFILE_ZONE_SCOPED;
bool res = false;
LLTextureFetchWorker* worker = getWorker(id);
if (worker)
@@ -2779,7 +2716,7 @@ bool LLTextureFetch::getRequestFinished(const LLUUID& id, S32& discard_level,
if (!mDebugPause)
{
// LL_WARNS(LOG_TXT) << "Adding work for inactive worker: " << id << LL_ENDL;
- worker->addWork(0, LLWorkerThread::PRIORITY_HIGH | worker->mWorkPriority);
+ worker->addWork(0);
}
}
else if (worker->checkWork())
@@ -2855,16 +2792,19 @@ bool LLTextureFetch::getRequestFinished(const LLUUID& id, S32& discard_level,
// Threads: T*
bool LLTextureFetch::updateRequestPriority(const LLUUID& id, F32 priority)
{
- bool res = false;
- LLTextureFetchWorker* worker = getWorker(id);
- if (worker)
- {
- worker->lockWorkMutex(); // +Mw
- worker->setImagePriority(priority);
- worker->unlockWorkMutex(); // -Mw
- res = true;
- }
- return res;
+ LL_PROFILE_ZONE_SCOPED;
+ mRequestQueue.tryPost([=]()
+ {
+ LLTextureFetchWorker* worker = getWorker(id);
+ if (worker)
+ {
+ worker->lockWorkMutex(); // +Mw
+ worker->setImagePriority(priority);
+ worker->unlockWorkMutex(); // -Mw
+ }
+ });
+
+ return true;
}
// Replicates and expands upon the base class's
@@ -2881,6 +2821,7 @@ bool LLTextureFetch::updateRequestPriority(const LLUUID& id, F32 priority)
//virtual
S32 LLTextureFetch::getPending()
{
+ LL_PROFILE_ZONE_SCOPED;
S32 res;
lockData(); // +Ct
{
@@ -2914,7 +2855,7 @@ bool LLTextureFetch::runCondition()
} // -Mfq
return ! (have_no_commands
- && (mRequestQueue.empty() && mIdleThread)); // From base class
+ && (mRequestQueue.size() == 0 && mIdleThread)); // From base class
}
//////////////////////////////////////////////////////////////////////////////
@@ -2922,6 +2863,7 @@ bool LLTextureFetch::runCondition()
// Threads: Ttf
void LLTextureFetch::commonUpdate()
{
+ LL_PROFILE_ZONE_SCOPED;
// Update low/high water levels based on pipelining. We pick
// up setting eventually, so the semaphore/request level can
// fall outside the [0..HIGH_WATER] range. Expect that.
@@ -2958,6 +2900,7 @@ void LLTextureFetch::commonUpdate()
//virtual
S32 LLTextureFetch::update(F32 max_time_ms)
{
+ LL_PROFILE_ZONE_SCOPED;
static LLCachedControl<F32> band_width(gSavedSettings,"ThrottleBandwidthKBPS", 3000.0);
{
@@ -2977,11 +2920,6 @@ S32 LLTextureFetch::update(F32 max_time_ms)
commonUpdate();
}
- if (mFetchDebugger)
- {
- mFetchDebugger->tryToStopDebug(); //check if need to stop debugger.
- }
-
return res;
}
@@ -2997,18 +2935,6 @@ void LLTextureFetch::shutDownTextureCacheThread()
}
}
-// called in the MAIN thread after the ImageDecodeThread shuts down.
-//
-// Threads: Tmain
-void LLTextureFetch::shutDownImageDecodeThread()
-{
- if(mImageDecodeThread)
- {
- llassert_always(mImageDecodeThread->isQuitting() || mImageDecodeThread->isStopped()) ;
- mImageDecodeThread = NULL ;
- }
-}
-
// Threads: Ttf
void LLTextureFetch::startThread()
{
@@ -3030,6 +2956,7 @@ void LLTextureFetch::endThread()
// Threads: Ttf
void LLTextureFetch::threadedUpdate()
{
+ LL_PROFILE_ZONE_SCOPED;
llassert_always(mHttpRequest);
#if 0
@@ -3066,6 +2993,7 @@ void LLTextureFetch::threadedUpdate()
// Locks: Mw
bool LLTextureFetchWorker::insertPacket(S32 index, U8* data, S32 size)
{
+ LL_PROFILE_ZONE_SCOPED;
mRequestedDeltaTimer.reset();
if (index >= mTotalPackets)
{
@@ -3098,6 +3026,7 @@ bool LLTextureFetchWorker::insertPacket(S32 index, U8* data, S32 size)
void LLTextureFetchWorker::setState(e_state new_state)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
if (mFTType == FTT_SERVER_BAKE)
{
// NOTE: turning on these log statements is a reliable way to get
@@ -3119,7 +3048,7 @@ void LLTextureFetchWorker::setState(e_state new_state)
mSkippedStatesTime += d_time;
}
}
-
+
mStateTimer.reset();
mState = new_state;
}
@@ -3142,10 +3071,23 @@ BOOL LLTextureFetch::isFromLocalCache(const LLUUID& id)
return from_cache ;
}
+S32 LLTextureFetch::getFetchState(const LLUUID& id)
+{
+ S32 state = LLTextureFetchWorker::INVALID;
+ LLTextureFetchWorker* worker = getWorker(id);
+ if (worker && worker->haveWork())
+ {
+ state = worker->mState;
+ }
+
+ return state;
+}
+
// Threads: T*
S32 LLTextureFetch::getFetchState(const LLUUID& id, F32& data_progress_p, F32& requested_priority_p,
U32& fetch_priority_p, F32& fetch_dtime_p, F32& request_dtime_p, bool& can_use_http)
{
+ LL_PROFILE_ZONE_SCOPED;
S32 state = LLTextureFetchWorker::INVALID;
F32 data_progress = 0.0f;
F32 requested_priority = 0.0f;
@@ -3175,7 +3117,7 @@ S32 LLTextureFetch::getFetchState(const LLUUID& id, F32& data_progress_p, F32& r
{
requested_priority = worker->mImagePriority;
}
- fetch_priority = worker->getPriority();
+ fetch_priority = worker->getImagePriority();
can_use_http = worker->getCanUseHTTP() ;
worker->unlockWorkMutex(); // -Mw
}
@@ -3189,19 +3131,6 @@ S32 LLTextureFetch::getFetchState(const LLUUID& id, F32& data_progress_p, F32& r
void LLTextureFetch::dump()
{
- LL_INFOS(LOG_TXT) << "LLTextureFetch REQUESTS:" << LL_ENDL;
- for (request_queue_t::iterator iter = mRequestQueue.begin();
- iter != mRequestQueue.end(); ++iter)
- {
- LLQueuedThread::QueuedRequest* qreq = *iter;
- LLWorkerThread::WorkRequest* wreq = (LLWorkerThread::WorkRequest*)qreq;
- LLTextureFetchWorker* worker = (LLTextureFetchWorker*)wreq->getWorkerClass();
- LL_INFOS(LOG_TXT) << " ID: " << worker->mID
- << " PRI: " << llformat("0x%08x",wreq->getPriority())
- << " STATE: " << sStateDescs[worker->mState]
- << LL_ENDL;
- }
-
LL_INFOS(LOG_TXT) << "LLTextureFetch ACTIVE_HTTP:" << LL_ENDL;
for (queue_t::const_iterator iter(mHTTPTextureQueue.begin());
mHTTPTextureQueue.end() != iter;
@@ -3268,6 +3197,7 @@ bool LLTextureFetch::isHttpWaiter(const LLUUID & tid)
// Locks: -Mw (must not hold any worker when called)
void LLTextureFetch::releaseHttpWaiters()
{
+ LL_PROFILE_ZONE_SCOPED;
// Use mHttpSemaphore rather than mHTTPTextureQueue.size()
// to avoid a lock.
if (mHttpSemaphore >= mHttpLowWater)
@@ -3364,7 +3294,6 @@ void LLTextureFetch::releaseHttpWaiters()
}
worker->setState(LLTextureFetchWorker::SEND_HTTP_REQ);
- worker->setPriority(LLWorkerThread::PRIORITY_HIGH | worker->mWorkPriority);
worker->unlockWorkMutex(); // -Mw
removeHttpWaiter(worker->mID);
@@ -3454,6 +3383,7 @@ void LLTextureFetch::commandDataBreak()
// Threads: T*
void LLTextureFetch::cmdEnqueue(TFRequest * req)
{
+ LL_PROFILE_ZONE_SCOPED;
lockQueue(); // +Mfq
mCommands.push_back(req);
unlockQueue(); // -Mfq
@@ -3464,6 +3394,7 @@ void LLTextureFetch::cmdEnqueue(TFRequest * req)
// Threads: T*
LLTextureFetch::TFRequest * LLTextureFetch::cmdDequeue()
{
+ LL_PROFILE_ZONE_SCOPED;
TFRequest * ret = 0;
lockQueue(); // +Mfq
@@ -3480,6 +3411,7 @@ LLTextureFetch::TFRequest * LLTextureFetch::cmdDequeue()
// Threads: Ttf
void LLTextureFetch::cmdDoWork()
{
+ LL_PROFILE_ZONE_SCOPED;
if (mDebugPause)
{
return; // debug: don't do any work
@@ -3570,7 +3502,7 @@ TFReqSendMetrics::~TFReqSendMetrics()
bool
TFReqSendMetrics::doWork(LLTextureFetch * fetcher)
{
- static const U32 report_priority(1);
+ LL_PROFILE_ZONE_SCOPED;
//if (! gViewerAssetStatsThread1)
// return true;
@@ -3613,7 +3545,6 @@ TFReqSendMetrics::doWork(LLTextureFetch * fetcher)
// Don't care about handle, this is a fire-and-forget operation.
LLCoreHttpUtil::requestPostWithLLSD(&fetcher->getHttpRequest(),
fetcher->getMetricsPolicyClass(),
- report_priority,
mCapsURL,
mStatsSD,
LLCore::HttpOptions::ptr_t(),
@@ -3675,971 +3606,6 @@ truncate_viewer_metrics(int max_regions, LLSD & metrics)
} // end of anonymous namespace
-
-///////////////////////////////////////////////////////////////////////////////////////////
-//Start LLTextureFetchDebugger
-///////////////////////////////////////////////////////////////////////////////////////////
-//---------------------
-class LLDebuggerCacheReadResponder : public LLTextureCache::ReadResponder
-{
-public:
- LLDebuggerCacheReadResponder(LLTextureFetchDebugger* debugger, S32 id, LLImageFormatted* image)
- : mDebugger(debugger), mID(id)
- {
- setImage(image);
- }
- virtual void completed(bool success)
- {
- mDebugger->callbackCacheRead(mID, success, mFormattedImage, mImageSize, mImageLocal);
- }
-private:
- LLTextureFetchDebugger* mDebugger;
- S32 mID;
-};
-
-class LLDebuggerCacheWriteResponder : public LLTextureCache::WriteResponder
-{
-public:
- LLDebuggerCacheWriteResponder(LLTextureFetchDebugger* debugger, S32 id)
- : mDebugger(debugger), mID(id)
- {
- }
- virtual void completed(bool success)
- {
- mDebugger->callbackCacheWrite(mID, success);
- }
-private:
- LLTextureFetchDebugger* mDebugger;
- S32 mID;
-};
-
-class LLDebuggerDecodeResponder : public LLImageDecodeThread::Responder
-{
-public:
- LLDebuggerDecodeResponder(LLTextureFetchDebugger* debugger, S32 id)
- : mDebugger(debugger), mID(id)
- {
- }
- virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux)
- {
- mDebugger->callbackDecoded(mID, success, raw, aux);
- }
-private:
- LLTextureFetchDebugger* mDebugger;
- S32 mID;
-};
-
-
-LLTextureFetchDebugger::LLTextureFetchDebugger(LLTextureFetch* fetcher, LLTextureCache* cache, LLImageDecodeThread* imagedecodethread) :
- LLCore::HttpHandler(),
- mFetcher(fetcher),
- mTextureCache(cache),
- mImageDecodeThread(imagedecodethread),
- mHttpHeaders(),
- mHttpPolicyClass(fetcher->getPolicyClass()),
- mNbCurlCompleted(0),
- mTempIndex(0),
- mHistoryListIndex(0)
-{
- init();
-}
-
-LLTextureFetchDebugger::~LLTextureFetchDebugger()
-{
- mFetchingHistory.clear();
- mStopDebug = TRUE;
- tryToStopDebug();
-}
-
-void LLTextureFetchDebugger::init()
-{
- setDebuggerState(IDLE);
-
- mCacheReadTime = -1.f;
- mCacheWriteTime = -1.f;
- mDecodingTime = -1.f;
- mHTTPTime = -1.f;
- mGLCreationTime = -1.f;
-
- mTotalFetchingTime = 0.f;
- mRefetchVisCacheTime = -1.f;
- mRefetchVisHTTPTime = -1.f;
- mRefetchAllCacheTime = -1.f;
- mRefetchAllHTTPTime = -1.f;
-
- mNumFetchedTextures = 0;
- mNumCacheHits = 0;
- mNumVisibleFetchedTextures = 0;
- mNumVisibleFetchingRequests = 0;
- mFetchedData = 0;
- mDecodedData = 0;
- mVisibleFetchedData = 0;
- mVisibleDecodedData = 0;
- mRenderedData = 0;
- mRenderedDecodedData = 0;
- mFetchedPixels = 0;
- mRenderedPixels = 0;
- mRefetchedVisData = 0;
- mRefetchedVisPixels = 0;
- mRefetchedAllData = 0;
- mRefetchedAllPixels = 0;
-
- mFreezeHistory = FALSE;
- mStopDebug = FALSE;
- mClearHistory = FALSE;
- mRefetchNonVis = FALSE;
-
- mNbCurlRequests = 0;
-
- if (! mHttpHeaders)
- {
- mHttpHeaders = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders);
- mHttpHeaders->append(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_IMAGE_X_J2C);
- }
-}
-
-void LLTextureFetchDebugger::startWork(e_debug_state state)
-{
- switch(state)
- {
- case IDLE:
- break;
- case START_DEBUG:
- startDebug();
- break;
- case READ_CACHE:
- debugCacheRead();
- break;
- case WRITE_CACHE:
- debugCacheWrite();
- break;
- case DECODING:
- debugDecoder();
- break;
- case HTTP_FETCHING:
- debugHTTP();
- break;
- case GL_TEX:
- debugGLTextureCreation();
- break;
- case REFETCH_VIS_CACHE:
- debugRefetchVisibleFromCache();
- break;
- case REFETCH_VIS_HTTP:
- debugRefetchVisibleFromHTTP();
- break;
- case REFETCH_ALL_CACHE:
- debugRefetchAllFromCache();
- break;
- case REFETCH_ALL_HTTP:
- debugRefetchAllFromHTTP();
- break;
- default:
- break;
- }
- return;
-}
-
-void LLTextureFetchDebugger::startDebug()
-{
- //lock the fetcher
- mFetcher->lockFetcher(true);
- mFreezeHistory = TRUE;
- mFetcher->resetLoadSource();
-
- //clear the current fetching queue
- gTextureList.clearFetchingRequests();
-
- setDebuggerState(START_DEBUG);
-}
-
-bool LLTextureFetchDebugger::processStartDebug(F32 max_time)
-{
- mTimer.reset();
-
- //wait for all works to be done
- while(1)
- {
- S32 pending = 0;
- pending += LLAppViewer::getTextureCache()->update(1);
- pending += LLAppViewer::getImageDecodeThread()->update(1);
- // pending += LLAppViewer::getTextureFetch()->update(1); // This causes infinite recursion in some cases
- pending += mNbCurlRequests;
- if(!pending)
- {
- break;
- }
-
- if(mTimer.getElapsedTimeF32() > max_time)
- {
- return false;
- }
- }
-
- //collect statistics
- mTotalFetchingTime = gTextureTimer.getElapsedTimeF32() - mTotalFetchingTime;
-
- std::set<LLUUID> fetched_textures;
- S32 size = mFetchingHistory.size();
- for(S32 i = 0 ; i < size; i++)
- {
- bool in_list = true;
- if(fetched_textures.find(mFetchingHistory[i].mID) == fetched_textures.end())
- {
- fetched_textures.insert(mFetchingHistory[i].mID);
- in_list = false;
- }
-
- std::vector<LLViewerFetchedTexture*> textures;
- LLViewerTextureManager::findFetchedTextures(mFetchingHistory[i].mID, textures);
- std::vector<LLViewerFetchedTexture*>::iterator iter = textures.begin();
- while (iter != textures.end())
- {
- LLViewerFetchedTexture* tex = *iter++;
- // fetched data will be counted for both ui and regular elements
- if (tex && tex->isJustBound()) //visible
- {
- if (!in_list)
- {
- mNumVisibleFetchedTextures++;
- }
- mNumVisibleFetchingRequests++;
-
- mVisibleFetchedData += mFetchingHistory[i].mFetchedSize;
- mVisibleDecodedData += mFetchingHistory[i].mDecodedSize;
-
- if (tex->getDiscardLevel() >= mFetchingHistory[i].mDecodedLevel)
- {
- mRenderedData += mFetchingHistory[i].mFetchedSize;
- mRenderedDecodedData += mFetchingHistory[i].mDecodedSize;
- mRenderedPixels += tex->getWidth() * tex->getHeight();
- }
- }
- }
- }
-
- mNumFetchedTextures = fetched_textures.size();
-
- return true;
-}
-
-void LLTextureFetchDebugger::tryToStopDebug()
-{
- if(!mStopDebug)
- {
- return;
- }
-
- //clear the current debug work
- S32 size = mFetchingHistory.size();
- switch(mDebuggerState)
- {
- case READ_CACHE:
- for(S32 i = 0 ; i < size; i++)
- {
- if (mFetchingHistory[i]. mCacheHandle != LLTextureCache::nullHandle())
- {
- mTextureCache->readComplete(mFetchingHistory[i].mCacheHandle, true);
- }
- }
- break;
- case WRITE_CACHE:
- for(S32 i = 0 ; i < size; i++)
- {
- if (mFetchingHistory[i].mCacheHandle != LLTextureCache::nullHandle())
- {
- mTextureCache->writeComplete(mFetchingHistory[i].mCacheHandle, true);
- }
- }
- break;
- case DECODING:
- break;
- case HTTP_FETCHING:
- break;
- case GL_TEX:
- break;
- case REFETCH_VIS_CACHE:
- break;
- case REFETCH_VIS_HTTP:
- break;
- case REFETCH_ALL_CACHE:
- mRefetchList.clear();
- break;
- case REFETCH_ALL_HTTP:
- mRefetchList.clear();
- break;
- default:
- break;
- }
-
- if(update(0.005f))
- {
- //unlock the fetcher
- mFetcher->lockFetcher(false);
- mFetcher->resetLoadSource();
- mFreezeHistory = FALSE;
- mStopDebug = FALSE;
-
- if(mClearHistory)
- {
- mFetchingHistory.clear();
- mHandleToFetchIndex.clear();
- init();
- mTotalFetchingTime = gTextureTimer.getElapsedTimeF32(); //reset
- }
- }
-}
-
-//called in the main thread and when the fetching queue is empty
-void LLTextureFetchDebugger::clearHistory()
-{
- mClearHistory = TRUE;
-}
-
-void LLTextureFetchDebugger::addHistoryEntry(LLTextureFetchWorker* worker)
-{
- if(worker->mRawImage.isNull() || worker->mFormattedImage.isNull())
- {
- return;
- }
-
- if(mFreezeHistory)
- {
- if(mDebuggerState == REFETCH_VIS_CACHE || mDebuggerState == REFETCH_VIS_HTTP)
- {
- mRefetchedVisPixels += worker->mRawImage->getWidth() * worker->mRawImage->getHeight();
- mRefetchedVisData += worker->mFormattedImage->getDataSize();
- }
- else
- {
- mRefetchedAllPixels += worker->mRawImage->getWidth() * worker->mRawImage->getHeight();
- mRefetchedAllData += worker->mFormattedImage->getDataSize();
-
- // refetch list only requests/creates normal images, so requesting ui='false'
- LLViewerFetchedTexture* tex = LLViewerTextureManager::findFetchedTexture(worker->mID, TEX_LIST_STANDARD);
- if(tex && mRefetchList[tex].begin() != mRefetchList[tex].end())
- {
- if(worker->mDecodedDiscard == mFetchingHistory[mRefetchList[tex][0]].mDecodedLevel)
- {
- mRefetchList[tex].erase(mRefetchList[tex].begin());
- }
- }
- }
- return;
- }
-
- if(worker->mInCache)
- {
- mNumCacheHits++;
- }
- mFetchedData += worker->mFormattedImage->getDataSize();
- mDecodedData += worker->mRawImage->getDataSize();
- mFetchedPixels += worker->mRawImage->getWidth() * worker->mRawImage->getHeight();
-
- mFetchingHistory.push_back(FetchEntry(worker->mID, worker->mDesiredSize, worker->mDecodedDiscard,
- worker->mFormattedImage->getDataSize(), worker->mRawImage->getDataSize()));
-}
-
-void LLTextureFetchDebugger::lockCache()
-{
-}
-
-void LLTextureFetchDebugger::unlockCache()
-{
-}
-
-void LLTextureFetchDebugger::debugCacheRead()
-{
- lockCache();
- llassert_always(mDebuggerState == IDLE);
- mTimer.reset();
- setDebuggerState(READ_CACHE);
- mCacheReadTime = -1.f;
-
- S32 size = mFetchingHistory.size();
- for(S32 i = 0 ; i < size ; i++)
- {
- mFetchingHistory[i].mFormattedImage = NULL;
- mFetchingHistory[i].mCacheHandle = mTextureCache->readFromCache(mFetchingHistory[i].mID, LLWorkerThread::PRIORITY_NORMAL, 0, mFetchingHistory[i].mFetchedSize,
- new LLDebuggerCacheReadResponder(this, i, mFetchingHistory[i].mFormattedImage));
- }
-}
-
-void LLTextureFetchDebugger::clearCache()
-{
- S32 size = mFetchingHistory.size();
- {
- std::set<LLUUID> deleted_list;
- for(S32 i = 0 ; i < size ; i++)
- {
- if(deleted_list.find(mFetchingHistory[i].mID) == deleted_list.end())
- {
- deleted_list.insert(mFetchingHistory[i].mID);
- mTextureCache->removeFromCache(mFetchingHistory[i].mID);
- }
- }
- }
-}
-
-void LLTextureFetchDebugger::debugCacheWrite()
-{
- //remove from cache
- clearCache();
-
- lockCache();
- llassert_always(mDebuggerState == IDLE);
- mTimer.reset();
- setDebuggerState(WRITE_CACHE);
- mCacheWriteTime = -1.f;
-
- S32 size = mFetchingHistory.size();
- for(S32 i = 0 ; i < size ; i++)
- {
- if(mFetchingHistory[i].mFormattedImage.notNull())
- {
- mFetchingHistory[i].mCacheHandle = mTextureCache->writeToCache(mFetchingHistory[i].mID, LLWorkerThread::PRIORITY_NORMAL,
- mFetchingHistory[i].mFormattedImage->getData(), mFetchingHistory[i].mFetchedSize,
- mFetchingHistory[i].mDecodedLevel == 0 ? mFetchingHistory[i].mFetchedSize : mFetchingHistory[i].mFetchedSize + 1,
- NULL, 0, new LLDebuggerCacheWriteResponder(this, i));
- }
- }
-}
-
-void LLTextureFetchDebugger::lockDecoder()
-{
-}
-
-void LLTextureFetchDebugger::unlockDecoder()
-{
-}
-
-void LLTextureFetchDebugger::debugDecoder()
-{
- lockDecoder();
- llassert_always(mDebuggerState == IDLE);
- mTimer.reset();
- setDebuggerState(DECODING);
- mDecodingTime = -1.f;
-
- S32 size = mFetchingHistory.size();
- for(S32 i = 0 ; i < size ; i++)
- {
- if(mFetchingHistory[i].mFormattedImage.isNull())
- {
- continue;
- }
-
- mImageDecodeThread->decodeImage(mFetchingHistory[i].mFormattedImage, LLWorkerThread::PRIORITY_NORMAL,
- mFetchingHistory[i].mDecodedLevel, mFetchingHistory[i].mNeedsAux,
- new LLDebuggerDecodeResponder(this, i));
- }
-}
-
-void LLTextureFetchDebugger::debugHTTP()
-{
- llassert_always(mDebuggerState == IDLE);
-
- LLViewerRegion* region = gAgent.getRegion();
- if (!region)
- {
- LL_INFOS(LOG_TXT) << "Fetch Debugger : Current region undefined. Cannot fetch textures through HTTP." << LL_ENDL;
- return;
- }
-
- mHTTPUrl = region->getViewerAssetUrl();
- if (mHTTPUrl.empty())
- {
- LL_INFOS(LOG_TXT) << "Fetch Debugger : Current region URL undefined. Cannot fetch textures through HTTP." << LL_ENDL;
- return;
- }
-
- mTimer.reset();
- setDebuggerState(HTTP_FETCHING);
- mHTTPTime = -1.f;
-
- S32 size = mFetchingHistory.size();
- for (S32 i = 0 ; i < size ; i++)
- {
- mFetchingHistory[i].mCurlState = FetchEntry::CURL_NOT_DONE;
- mFetchingHistory[i].mCurlReceivedSize = 0;
- mFetchingHistory[i].mFormattedImage = NULL;
- }
- mNbCurlRequests = 0;
- mNbCurlCompleted = 0;
-
- fillCurlQueue();
-}
-
-S32 LLTextureFetchDebugger::fillCurlQueue()
-{
- if(mStopDebug) //stop
- {
- mNbCurlCompleted = mFetchingHistory.size();
- return 0;
- }
- if (mNbCurlRequests > HTTP_NONPIPE_REQUESTS_LOW_WATER)
- {
- return mNbCurlRequests;
- }
-
- S32 size = mFetchingHistory.size();
- for (S32 i = 0 ; i < size ; i++)
- {
- if (mFetchingHistory[i].mCurlState != FetchEntry::CURL_NOT_DONE)
- {
- continue;
- }
- std::string texture_url = mHTTPUrl + "/?texture_id=" + mFetchingHistory[i].mID.asString().c_str();
- S32 requestedSize = mFetchingHistory[i].mRequestedSize;
- // We request the whole file if the size was not set.
- requestedSize = llmax(0,requestedSize);
- // We request the whole file if the size was set to an absurdly high value (meaning all file)
- requestedSize = (requestedSize == 33554432 ? 0 : requestedSize);
-
- LLCore::HttpHandle handle = mFetcher->getHttpRequest().requestGetByteRange(mHttpPolicyClass,
- LLWorkerThread::PRIORITY_LOWBITS,
- texture_url,
- 0,
- requestedSize,
- LLCore::HttpOptions::ptr_t(),
- mHttpHeaders,
- LLCore::HttpHandler::ptr_t(this, &NoOpDeletor));
- if (LLCORE_HTTP_HANDLE_INVALID != handle)
- {
- mHandleToFetchIndex[handle] = i;
- mFetchingHistory[i].mHttpHandle = handle;
- mFetchingHistory[i].mCurlState = FetchEntry::CURL_IN_PROGRESS;
- mNbCurlRequests++;
- if (mNbCurlRequests >= HTTP_NONPIPE_REQUESTS_HIGH_WATER) // emulate normal pipeline
- {
- break;
- }
- }
- else
- {
- // Failed to queue request, log it and mark it done.
- LLCore::HttpStatus status(mFetcher->getHttpRequest().getStatus());
-
- LL_WARNS(LOG_TXT) << "Couldn't issue HTTP request in debugger for texture "
- << mFetchingHistory[i].mID
- << ", status: " << status.toTerseString()
- << " reason: " << status.toString()
- << LL_ENDL;
- mFetchingHistory[i].mCurlState = FetchEntry::CURL_DONE;
- }
- }
- //LL_INFOS(LOG_TXT) << "Fetch Debugger : Having " << mNbCurlRequests << " requests through the curl thread." << LL_ENDL;
- return mNbCurlRequests;
-}
-
-void LLTextureFetchDebugger::debugGLTextureCreation()
-{
- llassert_always(mDebuggerState == IDLE);
- setDebuggerState(GL_TEX);
- mTempTexList.clear();
-
- S32 size = mFetchingHistory.size();
- for(S32 i = 0 ; i < size ; i++)
- {
- if(mFetchingHistory[i].mRawImage.notNull())
- {
- std::vector<LLViewerFetchedTexture*> textures;
- gTextureList.findTexturesByID(mFetchingHistory[i].mID, textures);
- std::vector<LLViewerFetchedTexture*>::iterator iter = textures.begin();
- while (iter != textures.end())
- {
- LLViewerFetchedTexture* tex = *iter++;
- if (tex && !tex->isForSculptOnly())
- {
- tex->destroyGLTexture();
- mTempTexList.push_back(tex);
- }
- }
- }
- }
-
- mGLCreationTime = -1.f;
- mTempIndex = 0;
- mHistoryListIndex = 0;
-
- return;
-}
-
-bool LLTextureFetchDebugger::processGLCreation(F32 max_time)
-{
- mTimer.reset();
-
- bool done = true;
- S32 size = mFetchingHistory.size();
- S32 size1 = mTempTexList.size();
- for(; mHistoryListIndex < size && mTempIndex < size1; mHistoryListIndex++)
- {
- if(mFetchingHistory[mHistoryListIndex].mRawImage.notNull())
- {
- if(mFetchingHistory[mHistoryListIndex].mID == mTempTexList[mTempIndex]->getID())
- {
- mTempTexList[mTempIndex]->createGLTexture(mFetchingHistory[mHistoryListIndex].mDecodedLevel,
- mFetchingHistory[mHistoryListIndex].mRawImage, 0, TRUE, mTempTexList[mTempIndex]->getBoostLevel());
- mTempIndex++;
- }
- }
-
- if(mTimer.getElapsedTimeF32() > max_time)
- {
- done = false;
- break;
- }
- }
-
- if(mGLCreationTime < 0.f)
- {
- mGLCreationTime = mTimer.getElapsedTimeF32() ;
- }
- else
- {
- mGLCreationTime += mTimer.getElapsedTimeF32() ;
- }
-
- return done;
-}
-
-//clear fetching results of all textures.
-void LLTextureFetchDebugger::clearTextures()
-{
- S32 size = mFetchingHistory.size();
- for(S32 i = 0 ; i < size ; i++)
- {
- std::vector<LLViewerFetchedTexture*> textures;
- gTextureList.findTexturesByID(mFetchingHistory[i].mID, textures);
- std::vector<LLViewerFetchedTexture*>::iterator iter = textures.begin();
- while (iter != textures.end())
- {
- LLViewerFetchedTexture* tex = *iter++;
- if (tex)
- {
- tex->clearFetchedResults();
- }
- }
- }
-}
-
-void LLTextureFetchDebugger::makeRefetchList()
-{
- mRefetchList.clear();
- S32 size = mFetchingHistory.size();
- for(S32 i = 0 ; i < size; i++)
- {
- LLViewerFetchedTexture* tex = LLViewerTextureManager::getFetchedTexture(mFetchingHistory[i].mID);
- if(tex && tex->isJustBound()) //visible
- {
- continue; //the texture fetch pipeline will take care of visible textures.
- }
-
- // todo: Will attempt to refetch icons and ui elements as normal images (boost_none)
- // thus will create unnecessary LLViewerFetchedTexture, consider supporting separate UI textures
- mRefetchList[tex].push_back(i);
- }
-}
-
-void LLTextureFetchDebugger::scanRefetchList()
-{
- if(mStopDebug)
- {
- return;
- }
- if(!mRefetchNonVis)
- {
- return;
- }
-
- for(std::map< LLPointer<LLViewerFetchedTexture>, std::vector<S32> >::iterator iter = mRefetchList.begin();
- iter != mRefetchList.end(); )
- {
- if(iter->second.empty())
- {
- gTextureList.setDebugFetching(iter->first, -1);
- mRefetchList.erase(iter++); // This is the correct method to "erase and move on" in an std::map
- }
- else
- {
- gTextureList.setDebugFetching(iter->first, mFetchingHistory[iter->second[0]].mDecodedLevel);
- ++iter;
- }
- }
-}
-
-void LLTextureFetchDebugger::debugRefetchVisibleFromCache()
-{
- llassert_always(mDebuggerState == IDLE);
- setDebuggerState(REFETCH_VIS_CACHE);
-
- clearTextures();
- mFetcher->setLoadSource(LLTextureFetch::FROM_ALL);
-
- mTimer.reset();
- mFetcher->lockFetcher(false);
- mRefetchVisCacheTime = -1.f;
- mRefetchedVisData = 0;
- mRefetchedVisPixels = 0;
-}
-
-void LLTextureFetchDebugger::debugRefetchVisibleFromHTTP()
-{
- llassert_always(mDebuggerState == IDLE);
- setDebuggerState(REFETCH_VIS_HTTP);
-
- clearTextures();
- mFetcher->setLoadSource(LLTextureFetch::FROM_HTTP_ONLY);
-
- mTimer.reset();
- mFetcher->lockFetcher(false);
- mRefetchVisHTTPTime = -1.f;
- mRefetchedVisData = 0;
- mRefetchedVisPixels = 0;
-}
-
-void LLTextureFetchDebugger::debugRefetchAllFromCache()
-{
- llassert_always(mDebuggerState == IDLE);
- setDebuggerState(REFETCH_ALL_CACHE);
-
- clearTextures();
- makeRefetchList();
- mFetcher->setLoadSource(LLTextureFetch::FROM_ALL);
-
- mTimer.reset();
- mFetcher->lockFetcher(false);
- mRefetchAllCacheTime = -1.f;
- mRefetchedAllData = 0;
- mRefetchedAllPixels = 0;
- mRefetchNonVis = FALSE;
-}
-
-void LLTextureFetchDebugger::debugRefetchAllFromHTTP()
-{
- llassert_always(mDebuggerState == IDLE);
- setDebuggerState(REFETCH_ALL_HTTP);
-
- clearTextures();
- makeRefetchList();
- mFetcher->setLoadSource(LLTextureFetch::FROM_HTTP_ONLY);
-
- mTimer.reset();
- mFetcher->lockFetcher(false);
- mRefetchAllHTTPTime = -1.f;
- mRefetchedAllData = 0;
- mRefetchedAllPixels = 0;
- mRefetchNonVis = TRUE;
-}
-
-bool LLTextureFetchDebugger::update(F32 max_time)
-{
- switch(mDebuggerState)
- {
- case START_DEBUG:
- if(processStartDebug(max_time))
- {
- setDebuggerState(IDLE);
- }
- break;
- case READ_CACHE:
- if(!mTextureCache->update(1))
- {
- mCacheReadTime = mTimer.getElapsedTimeF32() ;
- setDebuggerState(IDLE);
- unlockCache();
- }
- break;
- case WRITE_CACHE:
- if(!mTextureCache->update(1))
- {
- mCacheWriteTime = mTimer.getElapsedTimeF32() ;
- setDebuggerState(IDLE);
- unlockCache();
- }
- break;
- case DECODING:
- if(!mImageDecodeThread->update(1))
- {
- mDecodingTime = mTimer.getElapsedTimeF32() ;
- setDebuggerState(IDLE);
- unlockDecoder();
- }
- break;
- case HTTP_FETCHING:
- // Do some notifications...
- mFetcher->getHttpRequest().update(10);
- if (!fillCurlQueue() && mNbCurlCompleted == mFetchingHistory.size())
- {
- mHTTPTime = mTimer.getElapsedTimeF32() ;
- setDebuggerState(IDLE);
- }
- break;
- case GL_TEX:
- if(processGLCreation(max_time))
- {
- setDebuggerState(IDLE);
- mTempTexList.clear();
- }
- break;
- case REFETCH_VIS_CACHE:
- if (LLAppViewer::getTextureFetch()->getNumRequests() == 0)
- {
- mRefetchVisCacheTime = mTimer.getElapsedTimeF32() ;
- setDebuggerState(IDLE);
- mFetcher->lockFetcher(true);
- mFetcher->resetLoadSource();
- }
- break;
- case REFETCH_VIS_HTTP:
- if (LLAppViewer::getTextureFetch()->getNumRequests() == 0)
- {
- mRefetchVisHTTPTime = mTimer.getElapsedTimeF32() ;
- setDebuggerState(IDLE);
- mFetcher->lockFetcher(true);
- mFetcher->resetLoadSource();
- }
- break;
- case REFETCH_ALL_CACHE:
- scanRefetchList();
- if (LLAppViewer::getTextureFetch()->getNumRequests() == 0)
- {
- if(!mRefetchNonVis)
- {
- mRefetchNonVis = TRUE; //start to fetch non-vis
- scanRefetchList();
- break;
- }
-
- mRefetchAllCacheTime = mTimer.getElapsedTimeF32() ;
- setDebuggerState(IDLE);
- mFetcher->lockFetcher(true);
- mFetcher->resetLoadSource();
- mRefetchList.clear();
- mRefetchNonVis = FALSE;
- }
- break;
- case REFETCH_ALL_HTTP:
- scanRefetchList();
- if (LLAppViewer::getTextureFetch()->getNumRequests() == 0)
- {
- mRefetchAllHTTPTime = mTimer.getElapsedTimeF32() ;
- setDebuggerState(IDLE);
- mFetcher->lockFetcher(true);
- mFetcher->resetLoadSource();
- mRefetchList.clear();
- mRefetchNonVis = FALSE;
- }
- break;
- default:
- setDebuggerState(IDLE);
- break;
- }
-
- return mDebuggerState == IDLE;
-}
-
-void LLTextureFetchDebugger::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response)
-{
- handle_fetch_map_t::iterator iter(mHandleToFetchIndex.find(handle));
- if (mHandleToFetchIndex.end() == iter)
- {
- LL_INFOS(LOG_TXT) << "Fetch Debugger : Couldn't find handle " << handle << " in fetch list." << LL_ENDL;
- return;
- }
-
- S32 fetch_ind(iter->second);
- mHandleToFetchIndex.erase(iter);
- if (fetch_ind >= mFetchingHistory.size() || mFetchingHistory[fetch_ind].mHttpHandle != handle)
- {
- LL_INFOS(LOG_TXT) << "Fetch Debugger : Handle and fetch object in disagreement. Punting." << LL_ENDL;
- }
- else
- {
- callbackHTTP(mFetchingHistory[fetch_ind], response);
- mFetchingHistory[fetch_ind].mHttpHandle = LLCORE_HTTP_HANDLE_INVALID; // Not valid after notification
- }
-}
-
-void LLTextureFetchDebugger::callbackCacheRead(S32 id, bool success, LLImageFormatted* image,
- S32 imagesize, BOOL islocal)
-{
- if (success)
- {
- mFetchingHistory[id].mFormattedImage = image;
- }
- mTextureCache->readComplete(mFetchingHistory[id].mCacheHandle, false);
- mFetchingHistory[id].mCacheHandle = LLTextureCache::nullHandle();
-}
-
-void LLTextureFetchDebugger::callbackCacheWrite(S32 id, bool success)
-{
- mTextureCache->writeComplete(mFetchingHistory[id].mCacheHandle);
- mFetchingHistory[id].mCacheHandle = LLTextureCache::nullHandle();
-}
-
-void LLTextureFetchDebugger::callbackDecoded(S32 id, bool success, LLImageRaw* raw, LLImageRaw* aux)
-{
- if (success)
- {
- llassert_always(raw);
- mFetchingHistory[id].mRawImage = raw;
- }
-}
-
-void LLTextureFetchDebugger::callbackHTTP(FetchEntry & fetch, LLCore::HttpResponse * response)
-{
- static const LLCore::HttpStatus par_status(HTTP_PARTIAL_CONTENT);
-
- LLCore::HttpStatus status(response->getStatus());
- mNbCurlRequests--;
- mNbCurlCompleted++;
- fetch.mCurlState = FetchEntry::CURL_DONE;
- if (status)
- {
- const bool partial(par_status == status);
- LLCore::BufferArray * ba(response->getBody()); // *Not* holding reference to body
-
- S32 data_size = ba ? ba->size() : 0;
- fetch.mCurlReceivedSize += data_size;
- //LL_INFOS(LOG_TXT) << "Fetch Debugger : got results for " << fetch.mID << ", data_size = " << data_size << ", received = " << fetch.mCurlReceivedSize << ", requested = " << fetch.mRequestedSize << ", partial = " << partial << LL_ENDL;
- if ((fetch.mCurlReceivedSize >= fetch.mRequestedSize) || !partial || (fetch.mRequestedSize == 600))
- {
- U8* d_buffer = (U8*)ll_aligned_malloc_16(data_size);
- if (ba)
- {
- ba->read(0, d_buffer, data_size);
- }
-
- llassert_always(fetch.mFormattedImage.isNull());
- {
- // For now, create formatted image based on extension
- std::string texture_url = mHTTPUrl + "/?texture_id=" + fetch.mID.asString().c_str();
- std::string extension = gDirUtilp->getExtension(texture_url);
- fetch.mFormattedImage = LLImageFormatted::createFromType(LLImageBase::getCodecFromExtension(extension));
- if (fetch.mFormattedImage.isNull())
- {
- fetch.mFormattedImage = new LLImageJ2C; // default
- }
- }
-
- fetch.mFormattedImage->setData(d_buffer, data_size);
- }
- }
- else //failed
- {
- LL_INFOS(LOG_TXT) << "Fetch Debugger : CURL GET FAILED, ID = " << fetch.mID
- << ", status: " << status.toTerseString()
- << " reason: " << status.toString() << LL_ENDL;
- }
-}
-
-
-//---------------------
-///////////////////////////////////////////////////////////////////////////////////////////
-//End LLTextureFetchDebugger
-///////////////////////////////////////////////////////////////////////////////////////////
-
LLTextureFetchTester::LLTextureFetchTester() : LLMetricPerformanceTesterBasic(sTesterName)
{
mTextureFetchTime = 0;
diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h
index d087db275b..4297117f75 100644
--- a/indra/newview/lltexturefetch.h
+++ b/indra/newview/lltexturefetch.h
@@ -48,7 +48,6 @@ class LLTextureFetchWorker;
class LLImageDecodeThread;
class LLHost;
class LLViewerAssetStats;
-class LLTextureFetchDebugger;
class LLTextureCache;
class LLTextureFetchTester;
@@ -59,7 +58,9 @@ class LLTextureFetch : public LLWorkerThread
friend class LLTextureFetchWorker;
public:
- LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* imagedecodethread, bool threaded, bool qa_mode);
+ static std::string getStateString(S32 state);
+
+ LLTextureFetch(LLTextureCache* cache, bool threaded, bool qa_mode);
~LLTextureFetch();
class TFRequest;
@@ -76,7 +77,7 @@ public:
void shutDownImageDecodeThread();
// Threads: T* (but Tmain mostly)
- bool createRequest(FTType f_type, const std::string& url, const LLUUID& id, const LLHost& host, F32 priority,
+ S32 createRequest(FTType f_type, const std::string& url, const LLUUID& id, const LLHost& host, F32 priority,
S32 w, S32 h, S32 c, S32 discard, bool needs_aux, bool can_use_http);
// Requests that a fetch operation be deleted from the queue.
@@ -110,10 +111,11 @@ public:
// Threads: T*
BOOL isFromLocalCache(const LLUUID& id);
- // @return Magic number giving the internal state of the
- // request. We should make these codes public if we're
- // going to return them as a status value.
- //
+ // get the current fetch state, if any, from the given UUID
+ S32 getFetchState(const LLUUID& id);
+
+ // @return Fetch state of given image and associates statistics
+ // See also getStateString
// Threads: T*
S32 getFetchState(const LLUUID& id, F32& decode_progress_p, F32& requested_priority_p,
U32& fetch_priority_p, F32& fetch_dtime_p, F32& request_dtime_p, bool& can_use_http);
@@ -307,7 +309,6 @@ private:
LLMutex mNetworkQueueMutex; //to protect mHTTPTextureQueue
LLTextureCache* mTextureCache;
- LLImageDecodeThread* mImageDecodeThread;
// Map of all requests by UUID
typedef std::map<LLUUID,LLTextureFetchWorker*> map_t;
@@ -392,10 +393,6 @@ public:
static LLTextureFetchTester* sTesterp;
private:
- //debug use
- LLTextureFetchDebugger* mFetchDebugger;
- bool mFetcherLocked;
-
e_tex_source mFetchSource;
e_tex_source mOriginFetchSource;
@@ -403,10 +400,6 @@ private:
//LLAdaptiveRetryPolicy mFetchRetryPolicy;
public:
- //debug use
- LLTextureFetchDebugger* getFetchDebugger() { return mFetchDebugger;}
- void lockFetcher(bool lock) { mFetcherLocked = lock;}
-
void setLoadSource(e_tex_source source) {mFetchSource = source;}
void resetLoadSource() {mFetchSource = mOriginFetchSource;}
bool canLoadFromCache() { return mFetchSource != FROM_HTTP_ONLY;}
@@ -414,216 +407,6 @@ public:
//debug use
class LLViewerFetchedTexture;
-class LLTextureFetchDebugger : public LLCore::HttpHandler
-{
- friend class LLTextureFetch;
-public:
- LLTextureFetchDebugger(LLTextureFetch* fetcher, LLTextureCache* cache, LLImageDecodeThread* imagedecodethread) ;
- ~LLTextureFetchDebugger();
-
-public:
- enum e_debug_state
- {
- IDLE = 0,
- START_DEBUG,
- READ_CACHE,
- WRITE_CACHE,
- DECODING,
- HTTP_FETCHING,
- GL_TEX,
- REFETCH_VIS_CACHE,
- REFETCH_VIS_HTTP,
- REFETCH_ALL_CACHE,
- REFETCH_ALL_HTTP,
- INVALID
- };
-
-private:
- struct FetchEntry
- {
- enum e_curl_state
- {
- CURL_NOT_DONE = 0,
- CURL_IN_PROGRESS,
- CURL_DONE
- };
- LLUUID mID;
- S32 mRequestedSize;
- S32 mDecodedLevel;
- S32 mFetchedSize;
- S32 mDecodedSize;
- BOOL mNeedsAux;
- U32 mCacheHandle;
- LLPointer<LLImageFormatted> mFormattedImage;
- LLPointer<LLImageRaw> mRawImage;
- e_curl_state mCurlState;
- S32 mCurlReceivedSize;
- LLCore::HttpHandle mHttpHandle;
-
- FetchEntry() :
- mDecodedLevel(-1),
- mFetchedSize(0),
- mDecodedSize(0),
- mHttpHandle(LLCORE_HTTP_HANDLE_INVALID)
- {}
- FetchEntry(LLUUID& id, S32 r_size, /*S32 f_discard, S32 c,*/ S32 level, S32 f_size, S32 d_size) :
- mID(id),
- mRequestedSize(r_size),
- mDecodedLevel(level),
- mFetchedSize(f_size),
- mDecodedSize(d_size),
- mNeedsAux(false),
- mHttpHandle(LLCORE_HTTP_HANDLE_INVALID)
- {}
- };
- typedef std::vector<FetchEntry> fetch_list_t;
- fetch_list_t mFetchingHistory;
-
- typedef std::map<LLCore::HttpHandle, S32> handle_fetch_map_t;
- handle_fetch_map_t mHandleToFetchIndex;
-
- void setDebuggerState(e_debug_state new_state) { mDebuggerState = new_state; }
- e_debug_state mDebuggerState;
-
- F32 mCacheReadTime;
- F32 mCacheWriteTime;
- F32 mDecodingTime;
- F32 mHTTPTime;
- F32 mGLCreationTime;
-
- F32 mTotalFetchingTime;
- F32 mRefetchVisCacheTime;
- F32 mRefetchVisHTTPTime;
- F32 mRefetchAllCacheTime;
- F32 mRefetchAllHTTPTime;
-
- LLTimer mTimer;
-
- LLTextureFetch* mFetcher;
- LLTextureCache* mTextureCache;
- LLImageDecodeThread* mImageDecodeThread;
- LLCore::HttpHeaders::ptr_t mHttpHeaders;
- LLCore::HttpRequest::policy_t mHttpPolicyClass;
-
- S32 mNumFetchedTextures;
- S32 mNumCacheHits;
- S32 mNumVisibleFetchedTextures;
- S32 mNumVisibleFetchingRequests;
- U32 mFetchedData;
- U32 mDecodedData;
- U32 mVisibleFetchedData;
- U32 mVisibleDecodedData;
- U32 mRenderedData;
- U32 mRenderedDecodedData;
- U32 mFetchedPixels;
- U32 mRenderedPixels;
- U32 mRefetchedVisData;
- U32 mRefetchedVisPixels;
- U32 mRefetchedAllData;
- U32 mRefetchedAllPixels;
-
- BOOL mFreezeHistory;
- BOOL mStopDebug;
- BOOL mClearHistory;
- BOOL mRefetchNonVis;
-
- std::string mHTTPUrl;
- S32 mNbCurlRequests;
- S32 mNbCurlCompleted;
-
- std::map< LLPointer<LLViewerFetchedTexture>, std::vector<S32> > mRefetchList; // treats UI textures as normal textures
- std::vector< LLPointer<LLViewerFetchedTexture> > mTempTexList;
- S32 mTempIndex;
- S32 mHistoryListIndex;
-
-public:
- bool update(F32 max_time); //called in the main thread once per frame
-
- //fetching history
- void clearHistory();
- void addHistoryEntry(LLTextureFetchWorker* worker);
-
- // Inherited from LLCore::HttpHandler
- // Threads: Ttf
- virtual void onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response);
-
- void startWork(e_debug_state state);
- void setStopDebug() {mStopDebug = TRUE;}
- void tryToStopDebug(); //stop everything
- void callbackCacheRead(S32 id, bool success, LLImageFormatted* image,
- S32 imagesize, BOOL islocal);
- void callbackCacheWrite(S32 id, bool success);
- void callbackDecoded(S32 id, bool success, LLImageRaw* raw, LLImageRaw* aux);
- void callbackHTTP(FetchEntry & fetch, LLCore::HttpResponse * response);
-
- e_debug_state getState() {return mDebuggerState;}
- S32 getNumFetchedTextures() {return mNumFetchedTextures;}
- S32 getNumFetchingRequests() {return mFetchingHistory.size();}
- S32 getNumCacheHits() {return mNumCacheHits;}
- S32 getNumVisibleFetchedTextures() {return mNumVisibleFetchedTextures;}
- S32 getNumVisibleFetchingRequests() {return mNumVisibleFetchingRequests;}
- U32 getFetchedData() {return mFetchedData;}
- U32 getDecodedData() {return mDecodedData;}
- U32 getVisibleFetchedData() {return mVisibleFetchedData;}
- U32 getVisibleDecodedData() {return mVisibleDecodedData;}
- U32 getRenderedData() {return mRenderedData;}
- U32 getRenderedDecodedData() {return mRenderedDecodedData;}
- U32 getFetchedPixels() {return mFetchedPixels;}
- U32 getRenderedPixels() {return mRenderedPixels;}
- U32 getRefetchedVisData() {return mRefetchedVisData;}
- U32 getRefetchedVisPixels() {return mRefetchedVisPixels;}
- U32 getRefetchedAllData() {return mRefetchedAllData;}
- U32 getRefetchedAllPixels() {return mRefetchedAllPixels;}
-
- F32 getCacheReadTime() {return mCacheReadTime;}
- F32 getCacheWriteTime() {return mCacheWriteTime;}
- F32 getDecodeTime() {return mDecodingTime;}
- F32 getGLCreationTime() {return mGLCreationTime;}
- F32 getHTTPTime() {return mHTTPTime;}
- F32 getTotalFetchingTime() {return mTotalFetchingTime;}
- F32 getRefetchVisCacheTime() {return mRefetchVisCacheTime;}
- F32 getRefetchVisHTTPTime() {return mRefetchVisHTTPTime;}
- F32 getRefetchAllCacheTime() {return mRefetchAllCacheTime;}
- F32 getRefetchAllHTTPTime() {return mRefetchAllHTTPTime;}
-
-private:
- void init();
- void clearTextures();//clear fetching results of all textures.
- void clearCache();
- void makeRefetchList();
- void scanRefetchList();
-
- void lockFetcher();
- void unlockFetcher();
-
- void lockCache();
- void unlockCache();
-
- void lockDecoder();
- void unlockDecoder();
-
- S32 fillCurlQueue();
-
- void startDebug();
- void debugCacheRead();
- void debugCacheWrite();
- void debugHTTP();
- void debugDecoder();
- void debugGLTextureCreation();
- void debugRefetchVisibleFromCache();
- void debugRefetchVisibleFromHTTP();
- void debugRefetchAllFromCache();
- void debugRefetchAllFromHTTP();
-
- bool processStartDebug(F32 max_time);
- bool processGLCreation(F32 max_time);
-
-private:
- static bool sDebuggerEnabled;
-public:
- static bool isEnabled() {return sDebuggerEnabled;}
-};
-
class LLTextureFetchTester : public LLMetricPerformanceTesterBasic
{
diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp
index cf9211767e..1f4f086352 100644
--- a/indra/newview/lltextureview.cpp
+++ b/indra/newview/lltextureview.cpp
@@ -49,6 +49,8 @@
#include "llviewerobjectlist.h"
#include "llviewertexture.h"
#include "llviewertexturelist.h"
+#include "llviewerwindow.h"
+#include "llwindow.h"
#include "llvovolume.h"
#include "llviewerstats.h"
#include "llworld.h"
@@ -117,8 +119,8 @@ public:
LLTextureBar* bar2p = (LLTextureBar*)i2;
LLViewerFetchedTexture *i1p = bar1p->mImagep;
LLViewerFetchedTexture *i2p = bar2p->mImagep;
- F32 pri1 = i1p->getDecodePriority(); // i1p->mRequestedDownloadPriority
- F32 pri2 = i2p->getDecodePriority(); // i2p->mRequestedDownloadPriority
+ F32 pri1 = i1p->getMaxVirtualSize();
+ F32 pri2 = i2p->getMaxVirtualSize();
if (pri1 > pri2)
return true;
else if (pri2 > pri1)
@@ -177,7 +179,7 @@ void LLTextureBar::draw()
{
color = LLColor4::magenta; // except none and alm
}
- else if (mImagep->getDecodePriority() <= 0.0f)
+ else if (mImagep->getMaxVirtualSize() <= 0.0f)
{
color = LLColor4::grey; color[VALPHA] = .7f;
}
@@ -202,26 +204,13 @@ void LLTextureBar::draw()
std::string uuid_str;
mImagep->mID.toString(uuid_str);
uuid_str = uuid_str.substr(0,7);
- if (mTextureView->mOrderFetch)
- {
- tex_str = llformat("%s %7.0f %d(%d) 0x%08x(%8.0f)",
- uuid_str.c_str(),
- mImagep->mMaxVirtualSize,
- mImagep->mDesiredDiscardLevel,
- mImagep->mRequestedDiscardLevel,
- mImagep->mFetchPriority,
- mImagep->getDecodePriority());
- }
- else
- {
- tex_str = llformat("%s %7.0f %d(%d) %8.0f(0x%08x)",
- uuid_str.c_str(),
- mImagep->mMaxVirtualSize,
- mImagep->mDesiredDiscardLevel,
- mImagep->mRequestedDiscardLevel,
- mImagep->getDecodePriority(),
- mImagep->mFetchPriority);
- }
+
+ tex_str = llformat("%s %7.0f %d(%d)",
+ uuid_str.c_str(),
+ mImagep->mMaxVirtualSize,
+ mImagep->mDesiredDiscardLevel,
+ mImagep->mRequestedDiscardLevel);
+
LLFontGL::getFontMonospace()->renderUTF8(tex_str, 0, title_x1, getRect().getHeight(),
color, LLFontGL::LEFT, LLFontGL::TOP);
@@ -499,10 +488,6 @@ private:
void LLGLTexMemBar::draw()
{
- S32Megabytes bound_mem = LLViewerTexture::sBoundTextureMemory;
- S32Megabytes max_bound_mem = LLViewerTexture::sMaxBoundTextureMemory;
- S32Megabytes total_mem = LLViewerTexture::sTotalTextureMemory;
- S32Megabytes max_total_mem = LLViewerTexture::sMaxTotalTextureMem;
F32 discard_bias = LLViewerTexture::sDesiredDiscardBias;
F32 cache_usage = LLAppViewer::getTextureCache()->getUsage().valueInUnits<LLUnits::Megabytes>();
F32 cache_max_usage = LLAppViewer::getTextureCache()->getMaxUsage().valueInUnits<LLUnits::Megabytes>();
@@ -548,15 +533,10 @@ void LLGLTexMemBar::draw()
U32 texFetchLatMed = U32(recording.getMean(LLTextureFetch::sTexFetchLatency).value() * 1000.0f);
U32 texFetchLatMax = U32(recording.getMax(LLTextureFetch::sTexFetchLatency).value() * 1000.0f);
- text = llformat("GL Tot: %d/%d MB GL Free: %d Sys Free: %d MB Bound: %4d/%4d MB FBO: %d MB Raw Tot: %d MB Bias: %.2f Cache: %.1f/%.1f MB",
- total_mem.value(),
- max_total_mem.value(),
- LLImageGLThread::getFreeVRAMMegabytes(),
+ text = llformat("GL Free: %d MB Sys Free: %d MB FBO: %d MB Bias: %.2f Cache: %.1f/%.1f MB",
+ gViewerWindow->getWindow()->getAvailableVRAMMegabytes(),
LLMemory::getAvailableMemKB()/1024,
- bound_mem.value(),
- max_bound_mem.value(),
LLRenderTarget::sBytesAllocated/(1024*1024),
- LLImageRaw::sGlobalRawMemory >> 20,
discard_bias,
cache_usage,
cache_max_usage);
@@ -836,7 +816,7 @@ void LLTextureView::draw()
LL_INFOS() << imagep->getID()
<< "\t" << tex_mem
<< "\t" << imagep->getBoostLevel()
- << "\t" << imagep->getDecodePriority()
+ << "\t" << imagep->getMaxVirtualSize()
<< "\t" << imagep->getWidth()
<< "\t" << imagep->getHeight()
<< "\t" << cur_discard
@@ -856,7 +836,7 @@ void LLTextureView::draw()
}
else
{
- pri = imagep->getDecodePriority();
+ pri = imagep->getMaxVirtualSize();
}
pri = llclamp(pri, 0.0f, HIGH_PRIORITY-1.f);
diff --git a/indra/newview/lltinygltfhelper.cpp b/indra/newview/lltinygltfhelper.cpp
new file mode 100644
index 0000000000..611911014a
--- /dev/null
+++ b/indra/newview/lltinygltfhelper.cpp
@@ -0,0 +1,358 @@
+/**
+ * @file lltinygltfhelper.cpp
+ *
+ * $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$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "lltinygltfhelper.h"
+
+#include "llimage.h"
+#include "llviewertexture.h"
+#include "llviewertexturelist.h"
+
+void strip_alpha_channel(LLPointer<LLImageRaw>& img)
+{
+ if (img->getComponents() == 4)
+ {
+ LLImageRaw* tmp = new LLImageRaw(img->getWidth(), img->getHeight(), 3);
+ tmp->copyUnscaled4onto3(img);
+ img = tmp;
+ }
+}
+
+// copy red channel from src_img to dst_img
+// PRECONDITIONS:
+// dst_img must be 3 component
+// src_img and dst_image must have the same dimensions
+void copy_red_channel(LLPointer<LLImageRaw>& src_img, LLPointer<LLImageRaw>& dst_img)
+{
+ llassert(src_img->getWidth() == dst_img->getWidth() && src_img->getHeight() == dst_img->getHeight());
+ llassert(dst_img->getComponents() == 3);
+
+ U32 pixel_count = dst_img->getWidth() * dst_img->getHeight();
+ U8* src = src_img->getData();
+ U8* dst = dst_img->getData();
+ S8 src_components = src_img->getComponents();
+
+ for (U32 i = 0; i < pixel_count; ++i)
+ {
+ dst[i * 3] = src[i * src_components];
+ }
+}
+
+void LLTinyGLTFHelper::initFetchedTextures(tinygltf::Material& material,
+ LLPointer<LLImageRaw>& base_color_img,
+ LLPointer<LLImageRaw>& normal_img,
+ LLPointer<LLImageRaw>& mr_img,
+ LLPointer<LLImageRaw>& emissive_img,
+ LLPointer<LLImageRaw>& occlusion_img,
+ LLPointer<LLViewerFetchedTexture>& base_color_tex,
+ LLPointer<LLViewerFetchedTexture>& normal_tex,
+ LLPointer<LLViewerFetchedTexture>& mr_tex,
+ LLPointer<LLViewerFetchedTexture>& emissive_tex)
+{
+ if (base_color_img)
+ {
+ base_color_tex = LLViewerTextureManager::getFetchedTexture(base_color_img, FTType::FTT_LOCAL_FILE, true);
+ }
+
+ if (normal_img)
+ {
+ strip_alpha_channel(normal_img);
+ normal_tex = LLViewerTextureManager::getFetchedTexture(normal_img, FTType::FTT_LOCAL_FILE, true);
+ }
+
+ if (mr_img)
+ {
+ strip_alpha_channel(mr_img);
+
+ if (occlusion_img && material.pbrMetallicRoughness.metallicRoughnessTexture.index != material.occlusionTexture.index)
+ {
+ // occlusion is a distinct texture from pbrMetallicRoughness
+ // pack into mr red channel
+ int occlusion_idx = material.occlusionTexture.index;
+ int mr_idx = material.pbrMetallicRoughness.metallicRoughnessTexture.index;
+ if (occlusion_idx != mr_idx)
+ {
+ //scale occlusion image to match resolution of mr image
+ occlusion_img->scale(mr_img->getWidth(), mr_img->getHeight());
+
+ copy_red_channel(occlusion_img, mr_img);
+ }
+ }
+ }
+ else if (occlusion_img)
+ {
+ //no mr but occlusion exists, make a white mr_img and copy occlusion red channel over
+ mr_img = new LLImageRaw(occlusion_img->getWidth(), occlusion_img->getHeight(), 3);
+ mr_img->clear(255, 255, 255);
+ copy_red_channel(occlusion_img, mr_img);
+ }
+
+ if (mr_img)
+ {
+ mr_tex = LLViewerTextureManager::getFetchedTexture(mr_img, FTType::FTT_LOCAL_FILE, true);
+ }
+
+ if (emissive_img)
+ {
+ strip_alpha_channel(emissive_img);
+ emissive_tex = LLViewerTextureManager::getFetchedTexture(emissive_img, FTType::FTT_LOCAL_FILE, true);
+ }
+}
+
+LLColor4 LLTinyGLTFHelper::getColor(const std::vector<double>& in)
+{
+ LLColor4 out;
+ for (S32 i = 0; i < llmin((S32)in.size(), 4); ++i)
+ {
+ out.mV[i] = in[i];
+ }
+
+ return out;
+}
+
+const tinygltf::Image * LLTinyGLTFHelper::getImageFromTextureIndex(const tinygltf::Model & model, S32 texture_index)
+{
+ if (texture_index >= 0)
+ {
+ S32 source_idx = model.textures[texture_index].source;
+ if (source_idx >= 0)
+ {
+ return &(model.images[source_idx]);
+ }
+ }
+
+ return nullptr;
+}
+
+LLImageRaw * LLTinyGLTFHelper::getTexture(const std::string & folder, const tinygltf::Model & model, S32 texture_index, std::string & name)
+{
+ const tinygltf::Image* image = getImageFromTextureIndex(model, texture_index);
+ LLImageRaw* rawImage = nullptr;
+
+ if (image != nullptr &&
+ image->bits == 8 &&
+ !image->image.empty() &&
+ image->component <= 4)
+ {
+ name = image->name;
+ rawImage = new LLImageRaw(&image->image[0], image->width, image->height, image->component);
+ rawImage->verticalFlip();
+ rawImage->optimizeAwayAlpha();
+ }
+
+ return rawImage;
+}
+
+LLImageRaw * LLTinyGLTFHelper::getTexture(const std::string & folder, const tinygltf::Model & model, S32 texture_index)
+{
+ const tinygltf::Image* image = getImageFromTextureIndex(model, texture_index);
+ LLImageRaw* rawImage = nullptr;
+
+ if (image != nullptr &&
+ image->bits == 8 &&
+ !image->image.empty() &&
+ image->component <= 4)
+ {
+ rawImage = new LLImageRaw(&image->image[0], image->width, image->height, image->component);
+ rawImage->verticalFlip();
+ }
+
+ return rawImage;
+}
+
+S32 LLTinyGLTFHelper::getMaterialCountFromFile(const std::string& filename)
+{
+ std::string exten = gDirUtilp->getExtension(filename);
+ S32 materials_in_file = 0;
+
+ if (exten == "gltf" || exten == "glb")
+ {
+ tinygltf::TinyGLTF loader;
+ std::string error_msg;
+ std::string warn_msg;
+
+ tinygltf::Model model_in;
+
+ std::string filename_lc = filename;
+ LLStringUtil::toLower(filename_lc);
+
+ // Load a tinygltf model fom a file. Assumes that the input filename has already been
+ // been sanitized to one of (.gltf , .glb) extensions, so does a simple find to distinguish.
+ bool decode_successful = false;
+ if (std::string::npos == filename_lc.rfind(".gltf"))
+ { // file is binary
+ decode_successful = loader.LoadBinaryFromFile(&model_in, &error_msg, &warn_msg, filename_lc);
+ }
+ else
+ { // file is ascii
+ decode_successful = loader.LoadASCIIFromFile(&model_in, &error_msg, &warn_msg, filename_lc);
+ }
+
+ if (!decode_successful)
+ {
+ LL_WARNS("GLTF") << "Cannot load, error: Failed to decode" << error_msg
+ << ", warning:" << warn_msg
+ << " file: " << filename
+ << LL_ENDL;
+ return 0;
+ }
+
+ if (model_in.materials.empty())
+ {
+ // materials are missing
+ LL_WARNS("GLTF") << "Cannot load. File has no materials " << filename << LL_ENDL;
+ return 0;
+ }
+ materials_in_file = model_in.materials.size();
+ }
+ return materials_in_file;
+}
+
+bool LLTinyGLTFHelper::getMaterialFromFile(
+ const std::string& filename,
+ S32 mat_index,
+ LLFetchedGLTFMaterial* material,
+ std::string& material_name)
+{
+ llassert(material);
+
+ tinygltf::TinyGLTF loader;
+ std::string error_msg;
+ std::string warn_msg;
+ tinygltf::Model model_in;
+ std::string filename_lc = filename;
+ bool decode_successful = true;
+
+ LLStringUtil::toLower(filename_lc);
+
+ // Load a tinygltf model fom a file. Assumes that the input filename has already been
+ // been sanitized to one of (.gltf , .glb) extensions, so does a simple find to distinguish.
+ if (std::string::npos == filename_lc.rfind(".gltf"))
+ { // file is binary
+ decode_successful = loader.LoadBinaryFromFile(&model_in, &error_msg, &warn_msg, filename_lc);
+ }
+ else
+ { // file is ascii
+ decode_successful = loader.LoadASCIIFromFile(&model_in, &error_msg, &warn_msg, filename_lc);
+ }
+
+ if (!decode_successful)
+ {
+ LL_WARNS("GLTF") << "Cannot load Material, error: " << error_msg
+ << ", warning:" << warn_msg
+ << " file: " << filename
+ << LL_ENDL;
+ return false;
+ }
+ else if (model_in.materials.size() <= mat_index)
+ {
+ // materials are missing
+ LL_WARNS("GLTF") << "Cannot load Material, Material " << mat_index << " is missing, " << filename << LL_ENDL;
+ return false;
+ }
+
+ material->setFromModel(model_in, mat_index);
+
+ std::string folder = gDirUtilp->getDirName(filename_lc);
+ tinygltf::Material material_in = model_in.materials[mat_index];
+
+ material_name = material_in.name;
+
+ // get base color texture
+ LLPointer<LLImageRaw> base_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.pbrMetallicRoughness.baseColorTexture.index);
+ // get normal map
+ LLPointer<LLImageRaw> normal_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.normalTexture.index);
+ // get metallic-roughness texture
+ LLPointer<LLImageRaw> mr_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.pbrMetallicRoughness.metallicRoughnessTexture.index);
+ // get emissive texture
+ LLPointer<LLImageRaw> emissive_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.emissiveTexture.index);
+ // get occlusion map if needed
+ LLPointer<LLImageRaw> occlusion_img;
+ if (material_in.occlusionTexture.index != material_in.pbrMetallicRoughness.metallicRoughnessTexture.index)
+ {
+ occlusion_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.occlusionTexture.index);
+ }
+
+ LLPointer<LLViewerFetchedTexture> base_color_tex;
+ LLPointer<LLViewerFetchedTexture> normal_tex;
+ LLPointer<LLViewerFetchedTexture> mr_tex;
+ LLPointer<LLViewerFetchedTexture> emissive_tex;
+
+ // todo: pass it into local bitmaps?
+ LLTinyGLTFHelper::initFetchedTextures(material_in,
+ base_img, normal_img, mr_img, emissive_img, occlusion_img,
+ base_color_tex, normal_tex, mr_tex, emissive_tex);
+
+ if (base_color_tex)
+ {
+ base_color_tex->addTextureStats(64.f * 64.f, TRUE);
+ material->mBaseColorId = base_color_tex->getID();
+ material->mBaseColorTexture = base_color_tex;
+ }
+ else
+ {
+ material->mBaseColorId = LLUUID::null;
+ material->mBaseColorTexture = nullptr;
+ }
+
+ if (normal_tex)
+ {
+ normal_tex->addTextureStats(64.f * 64.f, TRUE);
+ material->mNormalId = normal_tex->getID();
+ material->mNormalTexture = normal_tex;
+ }
+ else
+ {
+ material->mNormalId = LLUUID::null;
+ material->mNormalTexture = nullptr;
+ }
+
+ if (mr_tex)
+ {
+ mr_tex->addTextureStats(64.f * 64.f, TRUE);
+ material->mMetallicRoughnessId = mr_tex->getID();
+ material->mMetallicRoughnessTexture = mr_tex;
+ }
+ else
+ {
+ material->mMetallicRoughnessId = LLUUID::null;
+ material->mMetallicRoughnessTexture = nullptr;
+ }
+
+ if (emissive_tex)
+ {
+ emissive_tex->addTextureStats(64.f * 64.f, TRUE);
+ material->mEmissiveId = emissive_tex->getID();
+ material->mEmissiveTexture = emissive_tex;
+ }
+ else
+ {
+ material->mEmissiveId = LLUUID::null;
+ material->mEmissiveTexture = nullptr;
+ }
+
+ return true;
+}
diff --git a/indra/newview/lltinygltfhelper.h b/indra/newview/lltinygltfhelper.h
new file mode 100644
index 0000000000..92c9876aff
--- /dev/null
+++ b/indra/newview/lltinygltfhelper.h
@@ -0,0 +1,65 @@
+/**
+ * @file lltinygltfhelper.h
+ *
+ * $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$
+ */
+
+
+#pragma once
+
+#include "llgltfmaterial.h"
+#include "llgltfmateriallist.h"
+#include "llpointer.h"
+#include "tinygltf/tiny_gltf.h"
+
+class LLImageRaw;
+class LLViewerFetchedTexture;
+
+namespace LLTinyGLTFHelper
+{
+ LLColor4 getColor(const std::vector<double>& in);
+ const tinygltf::Image* getImageFromTextureIndex(const tinygltf::Model& model, S32 texture_index);
+ LLImageRaw* getTexture(const std::string& folder, const tinygltf::Model& model, S32 texture_index, std::string& name);
+ LLImageRaw* getTexture(const std::string& folder, const tinygltf::Model& model, S32 texture_index);
+
+ LLImageRaw* getTexture(const std::string& folder, const tinygltf::Model& model, S32 texture_index);
+
+ S32 getMaterialCountFromFile(const std::string& filename);
+
+ bool getMaterialFromFile(
+ const std::string& filename,
+ S32 mat_index,
+ LLFetchedGLTFMaterial* material,
+ std::string& material_name);
+
+ void initFetchedTextures(tinygltf::Material& material,
+ LLPointer<LLImageRaw>& base_color_img,
+ LLPointer<LLImageRaw>& normal_img,
+ LLPointer<LLImageRaw>& mr_img,
+ LLPointer<LLImageRaw>& emissive_img,
+ LLPointer<LLImageRaw>& occlusion_img,
+ LLPointer<LLViewerFetchedTexture>& base_color_tex,
+ LLPointer<LLViewerFetchedTexture>& normal_tex,
+ LLPointer<LLViewerFetchedTexture>& mr_tex,
+ LLPointer<LLViewerFetchedTexture>& emissive_tex);
+}
+
diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp
index b16b26b96e..53bc77daa9 100644
--- a/indra/newview/lltooldraganddrop.cpp
+++ b/indra/newview/lltooldraganddrop.cpp
@@ -257,7 +257,8 @@ LLToolDragAndDrop::LLDragAndDropDictionary::LLDragAndDropDictionary()
// |-------------------------------|----------------------------------------------|-----------------------------------------------|---------------------------------------------------|--------------------------------|
addEntry(DAD_NONE, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL));
addEntry(DAD_TEXTURE, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dTextureObject, &LLToolDragAndDrop::dad3dNULL));
- addEntry(DAD_SOUND, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL));
+ addEntry(DAD_MATERIAL, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dMaterialObject, &LLToolDragAndDrop::dad3dNULL));
+ addEntry(DAD_SOUND, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL));
addEntry(DAD_CALLINGCARD, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL));
addEntry(DAD_LANDMARK, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL));
addEntry(DAD_SCRIPT, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dRezScript, &LLToolDragAndDrop::dad3dNULL));
@@ -272,6 +273,7 @@ LLToolDragAndDrop::LLDragAndDropDictionary::LLDragAndDropDictionary()
addEntry(DAD_LINK, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL));
addEntry(DAD_MESH, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dMeshObject, &LLToolDragAndDrop::dad3dNULL));
addEntry(DAD_SETTINGS, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL));
+
// TODO: animation on self could play it? edit it?
// TODO: gesture on self could play it? edit it?
};
@@ -922,17 +924,17 @@ void LLToolDragAndDrop::pick(const LLPickInfo& pick_info)
}
// static
-BOOL LLToolDragAndDrop::handleDropTextureProtections(LLViewerObject* hit_obj,
+BOOL LLToolDragAndDrop::handleDropMaterialProtections(LLViewerObject* hit_obj,
LLInventoryItem* item,
LLToolDragAndDrop::ESource source,
const LLUUID& src_id)
{
// Always succeed if....
- // texture is from the library
+ // material is from the library
// or already in the contents of the object
if (SOURCE_LIBRARY == source)
{
- // dropping a texture from the library always just works.
+ // dropping a material from the library always just works.
return TRUE;
}
@@ -963,15 +965,15 @@ BOOL LLToolDragAndDrop::handleDropTextureProtections(LLViewerObject* hit_obj,
LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
if (!item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID()))
{
- // Check that we can add the texture as inventory to the object
+ // Check that we can add the material as inventory to the object
if (willObjectAcceptInventory(hit_obj,item) < ACCEPT_YES_COPY_SINGLE )
{
return FALSE;
}
- // make sure the object has the texture in it's inventory.
+ // make sure the object has the material in it's inventory.
if (SOURCE_AGENT == source)
{
- // Remove the texture from local inventory. The server
+ // Remove the material from local inventory. The server
// will actually remove the item from agent inventory.
gInventory.deleteObject(item->getUUID());
gInventory.notifyObservers();
@@ -993,10 +995,11 @@ BOOL LLToolDragAndDrop::handleDropTextureProtections(LLViewerObject* hit_obj,
}
}
// Add the texture item to the target object's inventory.
- if (LLAssetType::AT_TEXTURE == new_item->getType())
- {
- hit_obj->updateTextureInventory(new_item, TASK_INVENTORY_ITEM_KEY, true);
- }
+ if (LLAssetType::AT_TEXTURE == new_item->getType()
+ || LLAssetType::AT_MATERIAL == new_item->getType())
+ {
+ hit_obj->updateMaterialInventory(new_item, TASK_INVENTORY_ITEM_KEY, true);
+ }
else
{
hit_obj->updateInventory(new_item, TASK_INVENTORY_ITEM_KEY, true);
@@ -1015,9 +1018,10 @@ BOOL LLToolDragAndDrop::handleDropTextureProtections(LLViewerObject* hit_obj,
// *FIX: may want to make sure agent can paint hit_obj.
// Add the texture item to the target object's inventory.
- if (LLAssetType::AT_TEXTURE == new_item->getType())
+ if (LLAssetType::AT_TEXTURE == new_item->getType()
+ || LLAssetType::AT_MATERIAL == new_item->getType())
{
- hit_obj->updateTextureInventory(new_item, TASK_INVENTORY_ITEM_KEY, true);
+ hit_obj->updateMaterialInventory(new_item, TASK_INVENTORY_ITEM_KEY, true);
}
else
{
@@ -1043,26 +1047,94 @@ void LLToolDragAndDrop::dropTextureAllFaces(LLViewerObject* hit_obj,
LL_WARNS() << "LLToolDragAndDrop::dropTextureAllFaces no texture item." << LL_ENDL;
return;
}
+ S32 num_faces = hit_obj->getNumTEs();
+ bool has_non_pbr_faces = false;
+ for (S32 face = 0; face < num_faces; face++)
+ {
+ if (hit_obj->getRenderMaterialID(face).isNull())
+ {
+ has_non_pbr_faces = true;
+ break;
+ }
+ }
+ if (!has_non_pbr_faces)
+ {
+ return;
+ }
LLUUID asset_id = item->getAssetUUID();
- BOOL success = handleDropTextureProtections(hit_obj, item, source, src_id);
+ BOOL success = handleDropMaterialProtections(hit_obj, item, source, src_id);
if (!success)
{
return;
}
LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture(asset_id);
add(LLStatViewer::EDIT_TEXTURE, 1);
- S32 num_faces = hit_obj->getNumTEs();
for( S32 face = 0; face < num_faces; face++ )
{
-
- // update viewer side image in anticipation of update from simulator
- hit_obj->setTEImage(face, image);
- dialog_refresh_all();
+ if (hit_obj->getRenderMaterialID(face).isNull())
+ {
+ // update viewer side image in anticipation of update from simulator
+ hit_obj->setTEImage(face, image);
+ dialog_refresh_all();
+ }
}
// send the update to the simulator
hit_obj->sendTEUpdate();
}
+
+void LLToolDragAndDrop::dropMaterialOneFace(LLViewerObject* hit_obj,
+ S32 hit_face,
+ LLInventoryItem* item,
+ LLToolDragAndDrop::ESource source,
+ const LLUUID& src_id)
+{
+ if (hit_face == -1) return;
+ if (!item || item->getInventoryType() != LLInventoryType::IT_MATERIAL)
+ {
+ LL_WARNS() << "LLToolDragAndDrop::dropTextureOneFace no material item." << LL_ENDL;
+ return;
+ }
+ LLUUID asset_id = item->getAssetUUID();
+ BOOL success = handleDropMaterialProtections(hit_obj, item, source, src_id);
+ if (!success)
+ {
+ return;
+ }
+
+ hit_obj->setRenderMaterialID(hit_face, asset_id);
+
+ dialog_refresh_all();
+
+ // send the update to the simulator
+ hit_obj->sendTEUpdate();
+}
+
+
+void LLToolDragAndDrop::dropMaterialAllFaces(LLViewerObject* hit_obj,
+ LLInventoryItem* item,
+ LLToolDragAndDrop::ESource source,
+ const LLUUID& src_id)
+{
+ if (!item || item->getInventoryType() != LLInventoryType::IT_MATERIAL)
+ {
+ LL_WARNS() << "LLToolDragAndDrop::dropTextureAllFaces no material item." << LL_ENDL;
+ return;
+ }
+ LLUUID asset_id = item->getAssetUUID();
+ BOOL success = handleDropMaterialProtections(hit_obj, item, source, src_id);
+ if (!success)
+ {
+ return;
+ }
+
+ hit_obj->setRenderMaterialIDs(asset_id);
+ dialog_refresh_all();
+ // send the update to the simulator
+ hit_obj->sendTEUpdate();
+}
+
+
void LLToolDragAndDrop::dropMesh(LLViewerObject* hit_obj,
LLInventoryItem* item,
LLToolDragAndDrop::ESource source,
@@ -1074,7 +1146,7 @@ void LLToolDragAndDrop::dropMesh(LLViewerObject* hit_obj,
return;
}
LLUUID asset_id = item->getAssetUUID();
- BOOL success = handleDropTextureProtections(hit_obj, item, source, src_id);
+ BOOL success = handleDropMaterialProtections(hit_obj, item, source, src_id);
if(!success)
{
return;
@@ -1110,8 +1182,12 @@ void LLToolDragAndDrop::dropTextureOneFace(LLViewerObject* hit_obj,
LL_WARNS() << "LLToolDragAndDrop::dropTextureOneFace no texture item." << LL_ENDL;
return;
}
+ if (hit_obj->getRenderMaterialID(hit_face).notNull())
+ {
+ return;
+ }
LLUUID asset_id = item->getAssetUUID();
- BOOL success = handleDropTextureProtections(hit_obj, item, source, src_id);
+ BOOL success = handleDropMaterialProtections(hit_obj, item, source, src_id);
if (!success)
{
return;
@@ -1126,7 +1202,7 @@ void LLToolDragAndDrop::dropTextureOneFace(LLViewerObject* hit_obj,
if (gFloaterTools->getVisible() && panel_face)
{
- tex_channel = (tex_channel > -1) ? tex_channel : LLSelectMgr::getInstance()->getTextureChannel();
+ tex_channel = (tex_channel > -1) ? tex_channel : panel_face->getTextureDropChannel();
switch (tex_channel)
{
@@ -1633,6 +1709,7 @@ bool LLToolDragAndDrop::handleGiveDragAndDrop(LLUUID dest_agent, LLUUID session_
case DAD_MESH:
case DAD_CATEGORY:
case DAD_SETTINGS:
+ case DAD_MATERIAL:
{
LLInventoryObject* inv_obj = (LLInventoryObject*)cargo_data;
if(gInventory.getCategory(inv_obj->getUUID()) || (gInventory.getItem(inv_obj->getUUID())
@@ -1974,19 +2051,132 @@ EAcceptance LLToolDragAndDrop::dad3dApplyToObject(
return ACCEPT_NO;
}
+ if (cargo_type == DAD_TEXTURE)
+ {
+ if ((mask & MASK_SHIFT))
+ {
+ S32 num_faces = obj->getNumTEs();
+ bool has_non_pbr_faces = false;
+ for (S32 face = 0; face < num_faces; face++)
+ {
+ if (obj->getRenderMaterialID(face).isNull())
+ {
+ has_non_pbr_faces = true;
+ break;
+ }
+ }
+ if (!has_non_pbr_faces)
+ {
+ return ACCEPT_NO;
+ }
+ }
+ else if (obj->getRenderMaterialID(face).notNull())
+ {
+ return ACCEPT_NO;
+ }
+ }
+
if(drop && (ACCEPT_YES_SINGLE <= rv))
{
if (cargo_type == DAD_TEXTURE)
{
+ LLSelectNode *nodep = nullptr;
+ if (obj->isSelected())
+ {
+ // update object's saved textures
+ nodep = LLSelectMgr::getInstance()->getSelection()->findNode(obj);
+ }
+
if((mask & MASK_SHIFT))
{
dropTextureAllFaces(obj, item, mSource, mSourceID);
+
+ // If user dropped a texture onto face it implies
+ // applying texture now without cancel, save to selection
+ if (nodep)
+ {
+ uuid_vec_t texture_ids;
+ S32 num_faces = obj->getNumTEs();
+ for (S32 face = 0; face < num_faces; face++)
+ {
+ LLViewerTexture *tex = obj->getTEImage(face);
+ if (tex != nullptr)
+ {
+ texture_ids.push_back(tex->getID());
+ }
+ else
+ {
+ texture_ids.push_back(LLUUID::null);
+ }
+ }
+ nodep->saveTextures(texture_ids);
+ }
}
else
{
dropTextureOneFace(obj, face, item, mSource, mSourceID);
+
+ // If user dropped a texture onto face it implies
+ // applying texture now without cancel, save to selection
+ LLPanelFace* panel_face = gFloaterTools->getPanelFace();
+ if (nodep
+ && gFloaterTools->getVisible()
+ && panel_face
+ && panel_face->getTextureDropChannel() == 0 /*texture*/
+ && nodep->mSavedGLTFMaterialIds.size() > face)
+ {
+ LLViewerTexture *tex = obj->getTEImage(face);
+ if (tex != nullptr)
+ {
+ nodep->mSavedTextures[face] = tex->getID();
+ }
+ else
+ {
+ nodep->mSavedTextures[face] = LLUUID::null;
+ }
+ }
}
}
+ else if (cargo_type == DAD_MATERIAL)
+ {
+ LLSelectNode *nodep = nullptr;
+ if (obj->isSelected())
+ {
+ // update object's saved materials
+ nodep = LLSelectMgr::getInstance()->getSelection()->findNode(obj);
+ }
+
+ // If user dropped a material onto face it implies
+ // applying texture now without cancel, save to selection
+ if ((mask & MASK_SHIFT))
+ {
+ dropMaterialAllFaces(obj, item, mSource, mSourceID);
+
+ if (nodep)
+ {
+ uuid_vec_t material_ids;
+ S32 num_faces = obj->getNumTEs();
+ for (S32 face = 0; face < num_faces; face++)
+ {
+ material_ids.push_back(obj->getRenderMaterialID(face));
+ }
+ nodep->saveGLTFMaterialIds(material_ids);
+ }
+ }
+ else
+ {
+ dropMaterialOneFace(obj, face, item, mSource, mSourceID);
+
+ // If user dropped a material onto face it implies
+ // applying texture now without cancel, save to selection
+ if (nodep
+ && gFloaterTools->getVisible()
+ && nodep->mSavedGLTFMaterialIds.size() > face)
+ {
+ nodep->mSavedGLTFMaterialIds[face] = obj->getRenderMaterialID(face);
+ }
+ }
+ }
else if (cargo_type == DAD_MESH)
{
dropMesh(obj, item, mSource, mSourceID);
@@ -2015,6 +2205,12 @@ EAcceptance LLToolDragAndDrop::dad3dTextureObject(
return dad3dApplyToObject(obj, face, mask, drop, DAD_TEXTURE);
}
+EAcceptance LLToolDragAndDrop::dad3dMaterialObject(
+ LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
+{
+ return dad3dApplyToObject(obj, face, mask, drop, DAD_MATERIAL);
+}
+
EAcceptance LLToolDragAndDrop::dad3dMeshObject(
LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
{
diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h
index 4537d73332..bf35840964 100644
--- a/indra/newview/lltooldraganddrop.h
+++ b/indra/newview/lltooldraganddrop.h
@@ -94,7 +94,7 @@ public:
// deal with permissions of object, etc. returns TRUE if drop can
// proceed, otherwise FALSE.
- static BOOL handleDropTextureProtections(LLViewerObject* hit_obj,
+ static BOOL handleDropMaterialProtections(LLViewerObject* hit_obj,
LLInventoryItem* item,
LLToolDragAndDrop::ESource source,
const LLUUID& src_id);
@@ -168,6 +168,8 @@ protected:
MASK mask, BOOL drop);
EAcceptance dad3dTextureObject(LLViewerObject* obj, S32 face,
MASK mask, BOOL drop);
+ EAcceptance dad3dMaterialObject(LLViewerObject* obj, S32 face,
+ MASK mask, BOOL drop);
EAcceptance dad3dMeshObject(LLViewerObject* obj, S32 face,
MASK mask, BOOL drop);
// EAcceptance dad3dTextureSelf(LLViewerObject* obj, S32 face,
@@ -250,6 +252,14 @@ public:
LLInventoryItem* item,
ESource source,
const LLUUID& src_id);
+ static void dropMaterialOneFace(LLViewerObject* hit_obj, S32 hit_face,
+ LLInventoryItem* item,
+ ESource source,
+ const LLUUID& src_id);
+ static void dropMaterialAllFaces(LLViewerObject* hit_obj,
+ LLInventoryItem* item,
+ ESource source,
+ const LLUUID& src_id);
static void dropMesh(LLViewerObject* hit_obj,
LLInventoryItem* item,
ESource source,
diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp
index 5fb83bf08e..80ba54ab6c 100644
--- a/indra/newview/lltoolpie.cpp
+++ b/indra/newview/lltoolpie.cpp
@@ -823,15 +823,6 @@ BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask)
LLViewerMediaFocus::getInstance()->clearHover();
}
- static LLCachedControl<bool> enable_highlight(
- gSavedSettings, "RenderHoverGlowEnable", false);
- LLDrawable* drawable = NULL;
- if (enable_highlight && show_highlight && object)
- {
- drawable = object->mDrawable;
- }
- gPipeline.setHighlightObject(drawable);
-
return TRUE;
}
diff --git a/indra/newview/lltoolselect.cpp b/indra/newview/lltoolselect.cpp
index e52bc0b015..c6f3905ddc 100644
--- a/indra/newview/lltoolselect.cpp
+++ b/indra/newview/lltoolselect.cpp
@@ -65,7 +65,8 @@ BOOL LLToolSelect::handleMouseDown(S32 x, S32 y, MASK mask)
{
// do immediate pick query
BOOL pick_rigged = false; //gSavedSettings.getBOOL("AnimatedObjectsAllowLeftClick");
- mPick = gViewerWindow->pickImmediate(x, y, TRUE, pick_rigged);
+ BOOL pick_transparent = gSavedSettings.getBOOL("SelectInvisibleObjects");
+ mPick = gViewerWindow->pickImmediate(x, y, pick_transparent, pick_rigged);
// Pass mousedown to agent
LLTool::handleMouseDown(x, y, mask);
@@ -84,13 +85,13 @@ LLObjectSelectionHandle LLToolSelect::handleObjectSelection(const LLPickInfo& pi
}
BOOL select_owned = gSavedSettings.getBOOL("SelectOwnedOnly");
BOOL select_movable = gSavedSettings.getBOOL("SelectMovableOnly");
-
- // *NOTE: These settings must be cleaned up at bottom of function.
+
+ // *NOTE: These settings must be cleaned up at bottom of function.
if (temp_select || LLSelectMgr::getInstance()->mAllowSelectAvatar)
{
gSavedSettings.setBOOL("SelectOwnedOnly", FALSE);
gSavedSettings.setBOOL("SelectMovableOnly", FALSE);
- LLSelectMgr::getInstance()->setForceSelection(TRUE);
+ LLSelectMgr::getInstance()->setForceSelection(TRUE);
}
BOOL extend_select = (pick.mKeyMask == MASK_SHIFT) || (pick.mKeyMask == MASK_CONTROL);
diff --git a/indra/newview/llviewerassettype.cpp b/indra/newview/llviewerassettype.cpp
index 4804ef6ddc..481086f760 100644
--- a/indra/newview/llviewerassettype.cpp
+++ b/indra/newview/llviewerassettype.cpp
@@ -88,6 +88,7 @@ LLViewerAssetDictionary::LLViewerAssetDictionary()
addEntry(LLViewerAssetType::AT_NONE, new ViewerAssetEntry(DAD_NONE));
addEntry(LLViewerAssetType::AT_SETTINGS, new ViewerAssetEntry(DAD_SETTINGS));
+ addEntry(LLViewerAssetType::AT_MATERIAL, new ViewerAssetEntry(DAD_MATERIAL));
};
EDragAndDropType LLViewerAssetType::lookupDragAndDropType(EType asset_type)
diff --git a/indra/newview/llviewerassetupload.cpp b/indra/newview/llviewerassetupload.cpp
index 232b52a3f9..323190a04c 100644
--- a/indra/newview/llviewerassetupload.cpp
+++ b/indra/newview/llviewerassetupload.cpp
@@ -34,7 +34,6 @@
#include "lluuid.h"
#include "llvorbisencode.h"
#include "lluploaddialog.h"
-#include "llpreviewscript.h"
#include "llnotificationsutil.h"
#include "llagent.h"
#include "llfloaterreg.h"
@@ -554,7 +553,80 @@ LLSD LLNewFileResourceUploadInfo::exportTempFile()
}
//=========================================================================
-LLBufferedAssetUploadInfo::LLBufferedAssetUploadInfo(LLUUID itemId, LLAssetType::EType assetType, std::string buffer, invnUploadFinish_f finish) :
+LLNewBufferedResourceUploadInfo::LLNewBufferedResourceUploadInfo(
+ const std::string& buffer,
+ const LLAssetID& asset_id,
+ std::string name,
+ std::string description,
+ S32 compressionInfo,
+ LLFolderType::EType destinationType,
+ LLInventoryType::EType inventoryType,
+ LLAssetType::EType assetType,
+ U32 nextOWnerPerms,
+ U32 groupPerms,
+ U32 everyonePerms,
+ S32 expectedCost,
+ bool show_inventory,
+ uploadFinish_f finish,
+ uploadFailure_f failure)
+ : LLResourceUploadInfo(name, description, compressionInfo,
+ destinationType, inventoryType,
+ nextOWnerPerms, groupPerms, everyonePerms, expectedCost, show_inventory)
+ , mBuffer(buffer)
+ , mFinishFn(finish)
+ , mFailureFn(failure)
+{
+ setAssetType(assetType);
+ setAssetId(asset_id);
+}
+
+LLSD LLNewBufferedResourceUploadInfo::prepareUpload()
+{
+ if (getAssetId().isNull())
+ generateNewAssetId();
+
+ LLSD result = exportTempFile();
+ if (result.has("error"))
+ return result;
+
+ return LLResourceUploadInfo::prepareUpload();
+}
+
+LLSD LLNewBufferedResourceUploadInfo::exportTempFile()
+{
+ std::string filename = gDirUtilp->getTempFilename();
+
+ // copy buffer to the cache for upload
+ LLFileSystem file(getAssetId(), getAssetType(), LLFileSystem::APPEND);
+ file.write((U8*) mBuffer.c_str(), mBuffer.size());
+
+ return LLSD();
+}
+
+LLUUID LLNewBufferedResourceUploadInfo::finishUpload(LLSD &result)
+{
+ LLUUID newItemId = LLResourceUploadInfo::finishUpload(result);
+
+ if (mFinishFn)
+ {
+ mFinishFn(result["new_asset"].asUUID(), result);
+ }
+
+ return newItemId;
+}
+
+bool LLNewBufferedResourceUploadInfo::failedUpload(LLSD &result, std::string &reason)
+{
+ if (mFailureFn)
+ {
+ return mFailureFn(getAssetId(), result, reason);
+ }
+
+ return false; // Not handled
+}
+
+//=========================================================================
+LLBufferedAssetUploadInfo::LLBufferedAssetUploadInfo(LLUUID itemId, LLAssetType::EType assetType, std::string buffer, invnUploadFinish_f finish, uploadFailed_f failed) :
LLResourceUploadInfo(std::string(), std::string(), 0, LLFolderType::FT_NONE, LLInventoryType::IT_NONE,
0, 0, 0, 0),
mTaskUpload(false),
@@ -562,6 +634,7 @@ LLBufferedAssetUploadInfo::LLBufferedAssetUploadInfo(LLUUID itemId, LLAssetType:
mContents(buffer),
mInvnFinishFn(finish),
mTaskFinishFn(nullptr),
+ mFailureFn(failed),
mStoredToCache(false)
{
setItemId(itemId);
@@ -576,6 +649,7 @@ LLBufferedAssetUploadInfo::LLBufferedAssetUploadInfo(LLUUID itemId, LLPointer<LL
mContents(),
mInvnFinishFn(finish),
mTaskFinishFn(nullptr),
+ mFailureFn(nullptr),
mStoredToCache(false)
{
setItemId(itemId);
@@ -602,7 +676,7 @@ LLBufferedAssetUploadInfo::LLBufferedAssetUploadInfo(LLUUID itemId, LLPointer<LL
mContents.assign((char *)image->getData(), imageSize);
}
-LLBufferedAssetUploadInfo::LLBufferedAssetUploadInfo(LLUUID taskId, LLUUID itemId, LLAssetType::EType assetType, std::string buffer, taskUploadFinish_f finish) :
+LLBufferedAssetUploadInfo::LLBufferedAssetUploadInfo(LLUUID taskId, LLUUID itemId, LLAssetType::EType assetType, std::string buffer, taskUploadFinish_f finish, uploadFailed_f failed) :
LLResourceUploadInfo(std::string(), std::string(), 0, LLFolderType::FT_NONE, LLInventoryType::IT_NONE,
0, 0, 0, 0),
mTaskUpload(true),
@@ -610,6 +684,7 @@ LLBufferedAssetUploadInfo::LLBufferedAssetUploadInfo(LLUUID taskId, LLUUID itemI
mContents(buffer),
mInvnFinishFn(nullptr),
mTaskFinishFn(finish),
+ mFailureFn(failed),
mStoredToCache(false)
{
setItemId(itemId);
@@ -699,10 +774,19 @@ LLUUID LLBufferedAssetUploadInfo::finishUpload(LLSD &result)
return newAssetId;
}
+bool LLBufferedAssetUploadInfo::failedUpload(LLSD &result, std::string &reason)
+{
+ if (mFailureFn)
+ {
+ return mFailureFn(getItemId(), getTaskId(), result, reason);
+ }
+ return false;
+}
+
//=========================================================================
-LLScriptAssetUpload::LLScriptAssetUpload(LLUUID itemId, std::string buffer, invnUploadFinish_f finish):
- LLBufferedAssetUploadInfo(itemId, LLAssetType::AT_LSL_TEXT, buffer, finish),
+LLScriptAssetUpload::LLScriptAssetUpload(LLUUID itemId, std::string buffer, invnUploadFinish_f finish, uploadFailed_f failed):
+ LLBufferedAssetUploadInfo(itemId, LLAssetType::AT_LSL_TEXT, buffer, finish, failed),
mExerienceId(),
mTargetType(LSL2),
mIsRunning(false)
@@ -710,8 +794,8 @@ LLScriptAssetUpload::LLScriptAssetUpload(LLUUID itemId, std::string buffer, invn
}
LLScriptAssetUpload::LLScriptAssetUpload(LLUUID taskId, LLUUID itemId, TargetType_t targetType,
- bool isRunning, LLUUID exerienceId, std::string buffer, taskUploadFinish_f finish):
- LLBufferedAssetUploadInfo(taskId, itemId, LLAssetType::AT_LSL_TEXT, buffer, finish),
+ bool isRunning, LLUUID exerienceId, std::string buffer, taskUploadFinish_f finish, uploadFailed_f failed):
+ LLBufferedAssetUploadInfo(taskId, itemId, LLAssetType::AT_LSL_TEXT, buffer, finish, failed),
mExerienceId(exerienceId),
mTargetType(targetType),
mIsRunning(isRunning)
@@ -920,19 +1004,15 @@ void LLViewerAssetUpload::HandleUploadError(LLCore::HttpStatus status, LLSD &res
LLNotificationsUtil::add(label, args);
- // unfreeze script preview
- if (uploadInfo->getAssetType() == LLAssetType::AT_LSL_TEXT)
+ if (uploadInfo->failedUpload(result, reason))
{
- LLPreviewLSL* preview = LLFloaterReg::findTypedInstance<LLPreviewLSL>("preview_script",
- uploadInfo->getItemId());
- if (preview)
- {
- LLSD errors;
- errors.append(LLTrans::getString("UploadFailed") + reason);
- preview->callbackLSLCompileFailed(errors);
- }
+ // no further action required, already handled by a callback
+ // ex: do not trigger snapshot floater when failing material texture
+ return;
}
+ // Todo: move these floater specific actions into proper callbacks
+
// Let the Snapshot floater know we have failed uploading.
LLFloaterSnapshot* floater_snapshot = LLFloaterSnapshot::findInstance();
if (floater_snapshot && floater_snapshot->isWaitingState())
diff --git a/indra/newview/llviewerassetupload.h b/indra/newview/llviewerassetupload.h
index e56ba7d8f7..7f7707f5bb 100644
--- a/indra/newview/llviewerassetupload.h
+++ b/indra/newview/llviewerassetupload.h
@@ -64,6 +64,9 @@ public:
virtual void logPreparedUpload();
virtual LLUUID finishUpload(LLSD &result);
+ // return true if no further action is need
+ virtual bool failedUpload(LLSD &result, std::string &reason) { return false; }
+
LLTransactionID getTransactionId() const { return mTransactionId; }
LLAssetType::EType getAssetType() const { return mAssetType; }
std::string getAssetTypeString() const;
@@ -168,19 +171,60 @@ private:
};
//-------------------------------------------------------------------------
+// use when you have a resource in memory and you want to make a new inventory item
+class LLNewBufferedResourceUploadInfo : public LLResourceUploadInfo
+{
+public:
+ typedef std::function<void(LLUUID newAssetId, LLSD response)> uploadFinish_f;
+ typedef std::function<bool(LLUUID assetId, LLSD response, std::string reason)> uploadFailure_f;
+
+ LLNewBufferedResourceUploadInfo(
+ const std::string& buffer,
+ const LLAssetID& asset_id,
+ std::string name,
+ std::string description,
+ S32 compressionInfo,
+ LLFolderType::EType destinationType,
+ LLInventoryType::EType inventoryType,
+ LLAssetType::EType assetType,
+ U32 nextOWnerPerms,
+ U32 groupPerms,
+ U32 everyonePerms,
+ S32 expectedCost,
+ bool show_inventory,
+ uploadFinish_f finish,
+ uploadFailure_f failure);
+
+ virtual LLSD prepareUpload();
+
+protected:
+
+ virtual LLSD exportTempFile();
+ virtual LLUUID finishUpload(LLSD &result);
+ virtual bool failedUpload(LLSD &result, std::string &reason);
+
+private:
+ uploadFinish_f mFinishFn;
+ uploadFailure_f mFailureFn;
+ std::string mBuffer;
+};
+
+//-------------------------------------------------------------------------
class LLBufferedAssetUploadInfo : public LLResourceUploadInfo
{
public:
typedef std::function<void(LLUUID itemId, LLUUID newAssetId, LLUUID newItemId, LLSD response)> invnUploadFinish_f;
typedef std::function<void(LLUUID itemId, LLUUID taskId, LLUUID newAssetId, LLSD response)> taskUploadFinish_f;
+ typedef std::function<bool(LLUUID itemId, LLUUID taskId, LLSD response, std::string reason)> uploadFailed_f;
- LLBufferedAssetUploadInfo(LLUUID itemId, LLAssetType::EType assetType, std::string buffer, invnUploadFinish_f finish);
+ LLBufferedAssetUploadInfo(LLUUID itemId, LLAssetType::EType assetType, std::string buffer, invnUploadFinish_f finish, uploadFailed_f failed);
LLBufferedAssetUploadInfo(LLUUID itemId, LLPointer<LLImageFormatted> image, invnUploadFinish_f finish);
- LLBufferedAssetUploadInfo(LLUUID taskId, LLUUID itemId, LLAssetType::EType assetType, std::string buffer, taskUploadFinish_f finish);
+ LLBufferedAssetUploadInfo(LLUUID taskId, LLUUID itemId, LLAssetType::EType assetType, std::string buffer, taskUploadFinish_f finish, uploadFailed_f failed);
virtual LLSD prepareUpload();
virtual LLSD generatePostBody();
virtual LLUUID finishUpload(LLSD &result);
+ virtual bool failedUpload(LLSD &result, std::string &reason);
LLUUID getTaskId() const { return mTaskId; }
const std::string & getContents() const { return mContents; }
@@ -197,6 +241,7 @@ private:
std::string mContents;
invnUploadFinish_f mInvnFinishFn;
taskUploadFinish_f mTaskFinishFn;
+ uploadFailed_f mFailureFn;
bool mStoredToCache;
};
@@ -210,9 +255,9 @@ public:
MONO
};
- LLScriptAssetUpload(LLUUID itemId, std::string buffer, invnUploadFinish_f finish);
+ LLScriptAssetUpload(LLUUID itemId, std::string buffer, invnUploadFinish_f finish, uploadFailed_f failed);
LLScriptAssetUpload(LLUUID taskId, LLUUID itemId, TargetType_t targetType,
- bool isRunning, LLUUID exerienceId, std::string buffer, taskUploadFinish_f finish);
+ bool isRunning, LLUUID exerienceId, std::string buffer, taskUploadFinish_f finish, uploadFailed_f failed);
virtual LLSD generatePostBody();
diff --git a/indra/newview/llviewercamera.h b/indra/newview/llviewercamera.h
index 549778a841..b5841772ed 100644
--- a/indra/newview/llviewercamera.h
+++ b/indra/newview/llviewercamera.h
@@ -47,15 +47,14 @@ public:
typedef enum
{
CAMERA_WORLD = 0,
- CAMERA_SHADOW0,
- CAMERA_SHADOW1,
- CAMERA_SHADOW2,
- CAMERA_SHADOW3,
- CAMERA_SHADOW4,
- CAMERA_SHADOW5,
+ CAMERA_SUN_SHADOW0,
+ CAMERA_SUN_SHADOW1,
+ CAMERA_SUN_SHADOW2,
+ CAMERA_SUN_SHADOW3,
+ CAMERA_SPOT_SHADOW0,
+ CAMERA_SPOT_SHADOW1,
CAMERA_WATER0,
CAMERA_WATER1,
- CAMERA_GI_SOURCE,
NUM_CAMERAS
} eCameraID;
diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp
index 34c9dae4bb..5ddd8c78f7 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();
@@ -341,12 +339,6 @@ static bool handleMaxPartCountChanged(const LLSD& newvalue)
return true;
}
-static bool handleVideoMemoryChanged(const LLSD& newvalue)
-{
- gTextureList.updateMaxResidentTexMem(S32Megabytes(newvalue.asInteger()));
- return true;
-}
-
static bool handleChatFontSizeChanged(const LLSD& newvalue)
{
if(gConsole)
@@ -387,7 +379,7 @@ static bool handleJoystickChanged(const LLSD& newvalue)
static bool handleUseOcclusionChanged(const LLSD& newvalue)
{
- LLPipeline::sUseOcclusion = (newvalue.asBoolean() && gGLManager.mHasOcclusionQuery
+ LLPipeline::sUseOcclusion = (newvalue.asBoolean()
&& LLFeatureManager::getInstance()->isFeatureAvailable("UseOcclusion") && !gUseWireframe) ? 2 : 0;
return true;
}
@@ -440,41 +432,17 @@ static bool handleRenderLocalLightsChanged(const LLSD& newvalue)
return true;
}
-static bool handleRenderDeferredChanged(const LLSD& newvalue)
+static bool handleReflectionProbeDetailChanged(const LLSD& newvalue)
{
- LLRenderTarget::sUseFBO = newvalue.asBoolean();
- 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;
+ if (gPipeline.isInit())
+ {
+ LLPipeline::refreshCachedSettings();
+ gPipeline.releaseGLBuffers();
+ gPipeline.createGLBuffers();
+ gPipeline.resetVertexBuffers();
+ LLViewerShaderMgr::instance()->setShaders();
+ }
+ return true;
}
static bool handleRenderDebugPipelineChanged(const LLSD& newvalue)
@@ -678,7 +646,6 @@ void settings_setup_listeners()
setting_setup_signal_listener(gSavedSettings, "OctreeAlphaDistanceFactor", handleRepartition);
setting_setup_signal_listener(gSavedSettings, "OctreeAttachmentSizeFactor", handleRepartition);
setting_setup_signal_listener(gSavedSettings, "RenderMaxTextureIndex", handleSetShaderChanged);
- setting_setup_signal_listener(gSavedSettings, "RenderUseTriStrips", handleResetVertexBuffersChanged);
setting_setup_signal_listener(gSavedSettings, "RenderUIBuffer", handleWindowResized);
setting_setup_signal_listener(gSavedSettings, "RenderDepthOfField", handleReleaseGLBufferChanged);
setting_setup_signal_listener(gSavedSettings, "RenderFSAASamples", handleReleaseGLBufferChanged);
@@ -690,8 +657,7 @@ void settings_setup_listeners()
setting_setup_signal_listener(gSavedSettings, "RenderGlow", handleReleaseGLBufferChanged);
setting_setup_signal_listener(gSavedSettings, "RenderGlow", handleSetShaderChanged);
setting_setup_signal_listener(gSavedSettings, "RenderGlowResolutionPow", handleReleaseGLBufferChanged);
- setting_setup_signal_listener(gSavedSettings, "RenderAvatarCloth", handleSetShaderChanged);
- setting_setup_signal_listener(gSavedSettings, "WindLightUseAtmosShaders", handleSetShaderChanged);
+ // DEPRECATED -- setting_setup_signal_listener(gSavedSettings, "WindLightUseAtmosShaders", handleSetShaderChanged);
setting_setup_signal_listener(gSavedSettings, "RenderGammaFull", handleSetShaderChanged);
setting_setup_signal_listener(gSavedSettings, "RenderVolumeLODFactor", handleVolumeLODChanged);
setting_setup_signal_listener(gSavedSettings, "RenderAvatarLODFactor", handleAvatarLODChanged);
@@ -707,17 +673,19 @@ void settings_setup_listeners()
setting_setup_signal_listener(gSavedSettings, "RenderDebugTextureBind", handleResetVertexBuffersChanged);
setting_setup_signal_listener(gSavedSettings, "RenderAutoMaskAlphaDeferred", handleResetVertexBuffersChanged);
setting_setup_signal_listener(gSavedSettings, "RenderAutoMaskAlphaNonDeferred", handleResetVertexBuffersChanged);
- setting_setup_signal_listener(gSavedSettings, "RenderObjectBump", handleRenderBumpChanged);
+ // DEPRECATED - setting_setup_signal_listener(gSavedSettings, "RenderObjectBump", handleRenderBumpChanged);
setting_setup_signal_listener(gSavedSettings, "RenderMaxVBOSize", handleResetVertexBuffersChanged);
setting_setup_signal_listener(gSavedSettings, "RenderVSyncEnable", handleVSyncChanged);
setting_setup_signal_listener(gSavedSettings, "RenderDeferredNoise", handleReleaseGLBufferChanged);
setting_setup_signal_listener(gSavedSettings, "RenderDebugPipeline", handleRenderDebugPipelineChanged);
setting_setup_signal_listener(gSavedSettings, "RenderResolutionDivisor", handleRenderResolutionDivisorChanged);
- setting_setup_signal_listener(gSavedSettings, "RenderDeferred", handleRenderDeferredChanged);
+ // 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);
- setting_setup_signal_listener(gSavedSettings, "TextureMemory", handleVideoMemoryChanged);
setting_setup_signal_listener(gSavedSettings, "ChatFontSize", handleChatFontSizeChanged);
setting_setup_signal_listener(gSavedSettings, "ChatPersistTime", handleChatPersistTimeChanged);
setting_setup_signal_listener(gSavedSettings, "ConsoleMaxLines", handleConsoleMaxLinesChanged);
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index bc0fafb29f..2e20d61b15 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -31,6 +31,7 @@
#include "llgl.h"
#include "llrender.h"
#include "llglheaders.h"
+#include "llgltfmateriallist.h"
#include "llagent.h"
#include "llagentcamera.h"
#include "llviewercontrol.h"
@@ -97,6 +98,7 @@ BOOL gResizeScreenTexture = FALSE;
BOOL gResizeShadowTexture = FALSE;
BOOL gWindowResized = FALSE;
BOOL gSnapshot = FALSE;
+BOOL gCubeSnapshot = FALSE;
BOOL gShaderProfileFrame = FALSE;
// This is how long the sim will try to teleport you before giving up.
@@ -146,7 +148,6 @@ void display_startup()
static S32 frame_count = 0;
LLGLState::checkStates();
- LLGLState::checkTextureChannels();
if (frame_count++ > 1) // make sure we have rendered a frame first
{
@@ -158,15 +159,13 @@ void display_startup()
}
LLGLState::checkStates();
- LLGLState::checkTextureChannels();
- glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+ glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); // | GL_STENCIL_BUFFER_BIT);
LLGLSUIDefault gls_ui;
gPipeline.disableLights();
if (gViewerWindow)
gViewerWindow->setup2DRender();
- gGL.color4f(1,1,1,1);
if (gViewerWindow)
gViewerWindow->draw();
gGL.flush();
@@ -174,7 +173,6 @@ void display_startup()
LLVertexBuffer::unbind();
LLGLState::checkStates();
- LLGLState::checkTextureChannels();
if (gViewerWindow && gViewerWindow->getWindow())
gViewerWindow->getWindow()->swapBuffers();
@@ -182,26 +180,32 @@ void display_startup()
glClear(GL_DEPTH_BUFFER_BIT);
}
-static LLTrace::BlockTimerStatHandle FTM_UPDATE_CAMERA("Update Camera");
-
void display_update_camera()
{
- LL_RECORD_BLOCK_TIME(FTM_UPDATE_CAMERA);
+ LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Update Camera");
// TODO: cut draw distance down if customizing avatar?
// TODO: cut draw distance on per-parcel basis?
// Cut draw distance in half when customizing avatar,
// but on the viewer only.
F32 final_far = gAgentCamera.mDrawDistance;
- if (CAMERA_MODE_CUSTOMIZE_AVATAR == gAgentCamera.getCameraMode())
+ if (gCubeSnapshot)
+ {
+ final_far = gSavedSettings.getF32("RenderReflectionProbeDrawDistance");
+ }
+ else if (CAMERA_MODE_CUSTOMIZE_AVATAR == gAgentCamera.getCameraMode())
+
{
final_far *= 0.5f;
}
LLViewerCamera::getInstance()->setFar(final_far);
gViewerWindow->setup3DRender();
- // Update land visibility too
- LLWorld::getInstance()->setLandFarClip(final_far);
+ if (!gCubeSnapshot)
+ {
+ // Update land visibility too
+ LLWorld::getInstance()->setLandFarClip(final_far);
+ }
}
// Write some stats to LL_INFOS()
@@ -236,32 +240,15 @@ void display_stats()
}
}
-static LLTrace::BlockTimerStatHandle FTM_PICK("Picking");
-static LLTrace::BlockTimerStatHandle FTM_RENDER("Render");
-static LLTrace::BlockTimerStatHandle FTM_RENDER_HUD("Render HUD");
-static LLTrace::BlockTimerStatHandle FTM_UPDATE_SKY("Update Sky");
-static LLTrace::BlockTimerStatHandle FTM_UPDATE_DYNAMIC_TEXTURES("Update Dynamic Textures");
-static LLTrace::BlockTimerStatHandle FTM_IMAGE_UPDATE("Update Images");
-static LLTrace::BlockTimerStatHandle FTM_IMAGE_UPDATE_CLASS("Class");
-static LLTrace::BlockTimerStatHandle FTM_IMAGE_UPDATE_BUMP("Image Update Bump");
-static LLTrace::BlockTimerStatHandle FTM_IMAGE_UPDATE_LIST("List");
-static LLTrace::BlockTimerStatHandle FTM_IMAGE_UPDATE_DELETE("Delete");
-static LLTrace::BlockTimerStatHandle FTM_RESIZE_WINDOW("Resize Window");
-static LLTrace::BlockTimerStatHandle FTM_HUD_UPDATE("HUD Update");
-static LLTrace::BlockTimerStatHandle FTM_DISPLAY_UPDATE_GEOM("Update Geom");
-static LLTrace::BlockTimerStatHandle FTM_TEXTURE_UNBIND("Texture Unbind");
-static LLTrace::BlockTimerStatHandle FTM_TELEPORT_DISPLAY("Teleport Display");
-static LLTrace::BlockTimerStatHandle FTM_EEP_UPDATE("Env Update");
-
// Paint the display!
void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
{
- LL_RECORD_BLOCK_TIME(FTM_RENDER);
+ LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Render");
if (gWindowResized)
{ //skip render on frames where window has been resized
LL_DEBUGS("Window") << "Resizing window" << LL_ENDL;
- LL_RECORD_BLOCK_TIME(FTM_RESIZE_WINDOW);
+ LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Resize Window");
gGL.flush();
glClear(GL_COLOR_BUFFER_BIT);
gViewerWindow->getWindow()->swapBuffers();
@@ -283,11 +270,6 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
for_snapshot = FALSE;
}
- if (LLPipeline::sRenderFrameTest)
- {
- send_agent_pause();
- }
-
gSnapshot = for_snapshot;
LLGLSDefault gls_default;
@@ -296,7 +278,6 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
LLVertexBuffer::unbind();
LLGLState::checkStates();
- LLGLState::checkTextureChannels();
stop_glerror();
@@ -332,14 +313,12 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
gViewerWindow->checkSettings();
{
- LL_RECORD_BLOCK_TIME(FTM_PICK);
- LLAppViewer::instance()->pingMainloopTimeout("Display:Pick");
+ LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Picking");
gViewerWindow->performPick();
}
LLAppViewer::instance()->pingMainloopTimeout("Display:CheckStates");
LLGLState::checkStates();
- LLGLState::checkTextureChannels();
//////////////////////////////////////////////////////////
//
@@ -411,7 +390,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
if (gTeleportDisplay)
{
- LL_RECORD_BLOCK_TIME(FTM_TELEPORT_DISPLAY);
+ LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Teleport Display");
LLAppViewer::instance()->pingMainloopTimeout("Display:Teleport");
static LLCachedControl<F32> teleport_arrival_delay(gSavedSettings, "TeleportArrivalDelay");
static LLCachedControl<F32> teleport_local_delay(gSavedSettings, "TeleportLocalDelay");
@@ -623,7 +602,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_DYNAMIC_TEXTURES))
{
LLAppViewer::instance()->pingMainloopTimeout("Display:DynamicTextures");
- LL_RECORD_BLOCK_TIME(FTM_UPDATE_DYNAMIC_TEXTURES);
+ LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Update Dynamic Textures");
if (LLViewerDynamicTexture::updateAllInstances())
{
gGL.setColorMask(true, true);
@@ -654,21 +633,21 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
stop_glerror();
{
- LL_RECORD_BLOCK_TIME(FTM_EEP_UPDATE);
+ LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Env Update");
// update all the sky/atmospheric/water settings
LLEnvironment::instance().update(LLViewerCamera::getInstance());
}
// *TODO: merge these two methods
{
- LL_RECORD_BLOCK_TIME(FTM_HUD_UPDATE);
+ LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("HUD Update");
LLHUDManager::getInstance()->updateEffects();
LLHUDObject::updateAll();
stop_glerror();
}
{
- LL_RECORD_BLOCK_TIME(FTM_DISPLAY_UPDATE_GEOM);
+ LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Update Geom");
const F32 max_geom_update_time = 0.005f*10.f*gFrameIntervalSeconds.value(); // 50 ms/second update time
gPipeline.createObjects(max_geom_update_time);
gPipeline.processPartitionQ();
@@ -696,7 +675,6 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
gDepthDirty = FALSE;
LLGLState::checkStates();
- LLGLState::checkTextureChannels();
static LLCullResult result;
LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
@@ -705,7 +683,6 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
stop_glerror();
LLGLState::checkStates();
- LLGLState::checkTextureChannels();
LLAppViewer::instance()->pingMainloopTimeout("Display:Swap");
@@ -721,20 +698,18 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
glClearColor(0,0,0,0);
LLGLState::checkStates();
- LLGLState::checkTextureChannels();
if (!for_snapshot)
{
- if (gFrameCount > 1)
- { //for some reason, ATI 4800 series will error out if you
- //try to generate a shadow before the first frame is through
- gPipeline.generateSunShadow(*LLViewerCamera::getInstance());
- }
+ if (gFrameCount > 1 && !for_snapshot)
+ { //for some reason, ATI 4800 series will error out if you
+ //try to generate a shadow before the first frame is through
+ gPipeline.generateSunShadow(*LLViewerCamera::getInstance());
+ }
LLVertexBuffer::unbind();
LLGLState::checkStates();
- LLGLState::checkTextureChannels();
glh::matrix4f proj = get_current_projection();
glh::matrix4f mod = get_current_modelview();
@@ -751,25 +726,10 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
gViewerWindow->setup3DViewport();
LLGLState::checkStates();
- LLGLState::checkTextureChannels();
-
}
- glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
- }
-
- LLGLState::checkStates();
-
- //if (!for_snapshot)
- {
- LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("display - 3")
- LLAppViewer::instance()->pingMainloopTimeout("Display:Imagery");
- gPipeline.generateWaterReflection(*LLViewerCamera::getInstance());
- gPipeline.generateHighlight(*LLViewerCamera::getInstance());
- gPipeline.renderPhysicsDisplay();
+ glClear(GL_DEPTH_BUFFER_BIT);
}
- LLGLState::checkStates();
-
//////////////////////////////////////
//
// Update images, using the image stats generated during object update/culling
@@ -780,33 +740,30 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
LLAppViewer::instance()->pingMainloopTimeout("Display:UpdateImages");
{
- LL_RECORD_BLOCK_TIME(FTM_IMAGE_UPDATE);
+ LL_PROFILE_ZONE_NAMED("Update Images");
{
- LL_RECORD_BLOCK_TIME(FTM_IMAGE_UPDATE_CLASS);
+ LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Class");
LLViewerTexture::updateClass();
}
- LLImageGLThread::updateClass();
-
{
- LL_RECORD_BLOCK_TIME(FTM_IMAGE_UPDATE_BUMP);
+ LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Image Update Bump");
gBumpImageList.updateImages(); // must be called before gTextureList version so that it's textures are thrown out first.
}
{
- LL_RECORD_BLOCK_TIME(FTM_IMAGE_UPDATE_LIST);
+ LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("List");
F32 max_image_decode_time = 0.050f*gFrameIntervalSeconds.value(); // 50 ms/second decode time
max_image_decode_time = llclamp(max_image_decode_time, 0.002f, 0.005f ); // min 2ms/frame, max 5ms/frame)
gTextureList.updateImages(max_image_decode_time);
}
- /*{
- LL_RECORD_BLOCK_TIME(FTM_IMAGE_UPDATE_DELETE);
- //remove dead textures from GL
- LLImageGL::deleteDeadTextures();
- stop_glerror();
- }*/
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("GLTF Materials Cleanup");
+ //remove dead gltf materials
+ gGLTFMaterialList.flushMaterials();
+ }
}
LLGLState::checkStates();
@@ -854,7 +811,6 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
{
glClearColor(0.5f, 0.5f, 0.5f, 0.f);
glClear(GL_COLOR_BUFFER_BIT);
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
}
LLAppViewer::instance()->pingMainloopTimeout("Display:RenderStart");
@@ -906,19 +862,27 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
if (LLPipeline::sRenderDeferred)
{
- gPipeline.mDeferredScreen.bindTarget();
- glClearColor(1, 0, 1, 1);
- gPipeline.mDeferredScreen.clear();
+ gPipeline.mRT->deferredScreen.bindTarget();
+ if (gUseWireframe)
+ {
+ F32 g = 0.5f;
+ glClearColor(g, g, g, 1.f);
+ }
+ else
+ {
+ glClearColor(1, 0, 1, 1);
+ }
+ gPipeline.mRT->deferredScreen.clear();
}
else
{
- gPipeline.mScreen.bindTarget();
+ gPipeline.mRT->screen.bindTarget();
if (LLPipeline::sUnderWaterRender && !gPipeline.canUseWindLightShaders())
{
const LLColor4 &col = LLEnvironment::instance().getCurrentWater()->getWaterFogColor();
glClearColor(col.mV[0], col.mV[1], col.mV[2], 0.f);
}
- gPipeline.mScreen.clear();
+ gPipeline.mRT->screen.clear();
}
gGL.setColorMask(true, false);
@@ -949,33 +913,15 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
}
gOcclusionProgram.unbind();
- }
-
- gGL.setColorMask(true, false);
- if (LLPipeline::sRenderDeferred)
- {
- gPipeline.renderGeomDeferred(*LLViewerCamera::getInstance());
}
- else
- {
- gPipeline.renderGeom(*LLViewerCamera::getInstance(), TRUE);
- }
-
- gGL.setColorMask(true, 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();
+ gGL.setColorMask(true, true);
+ gPipeline.renderGeomDeferred(*LLViewerCamera::getInstance(), true);
}
{
- LL_RECORD_BLOCK_TIME(FTM_TEXTURE_UNBIND);
+ LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Texture Unbind");
for (U32 i = 0; i < gGLManager.mNumTextureImageUnits; i++)
{ //dummy cleanup of any currently bound textures
if (gGL.getTexUnit(i)->getCurrType() != LLTexUnit::TT_NONE)
@@ -988,19 +934,12 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
LLAppViewer::instance()->pingMainloopTimeout("Display:RenderFlush");
- LLRenderTarget &rt = (gPipeline.sRenderDeferred ? gPipeline.mDeferredScreen : gPipeline.mScreen);
+ LLRenderTarget &rt = (gPipeline.sRenderDeferred ? gPipeline.mRT->deferredScreen : gPipeline.mRT->screen);
rt.flush();
- if (rt.sUseFBO)
- {
- LLRenderTarget::copyContentsToFramebuffer(rt, 0, 0, rt.getWidth(), rt.getHeight(), 0, 0, rt.getWidth(),
- rt.getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
- GL_NEAREST);
- }
-
if (LLPipeline::sRenderDeferred)
{
- gPipeline.renderDeferredLighting(&gPipeline.mScreen);
+ gPipeline.renderDeferredLighting();
}
LLPipeline::sUnderWaterRender = FALSE;
@@ -1028,12 +967,6 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
stop_glerror();
- if (LLPipeline::sRenderFrameTest)
- {
- send_agent_resume();
- LLPipeline::sRenderFrameTest = FALSE;
- }
-
display_stats();
LLAppViewer::instance()->pingMainloopTimeout("Display:Done");
@@ -1047,6 +980,121 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
}
}
+// WIP simplified copy of display() that does minimal work
+void display_cube_face()
+{
+ LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Render Cube Face");
+ LL_PROFILE_GPU_ZONE("display cube face");
+
+ llassert(!gSnapshot);
+ llassert(!gTeleportDisplay);
+ llassert(LLStartUp::getStartupState() >= STATE_PRECACHE);
+ llassert(!LLAppViewer::instance()->logoutRequestSent());
+ llassert(!gRestoreGL);
+
+ bool rebuild = false;
+
+ LLGLSDefault gls_default;
+ LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE, GL_LEQUAL);
+
+ LLVertexBuffer::unbind();
+
+ gPipeline.disableLights();
+
+ gPipeline.mBackfaceCull = TRUE;
+
+ gViewerWindow->setup3DViewport();
+
+ if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
+ { //don't draw hud objects in this frame
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD);
+ }
+
+ if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES))
+ { //don't draw hud particles in this frame
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES);
+ }
+
+ 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;
+ LLPipeline::sUseOcclusion = 0; // occlusion data is from main camera point of view, don't read or write it during cube snapshots
+ //gDepthDirty = TRUE; //let "real" render pipe know it can't trust the depth buffer for occlusion data
+
+ static LLCullResult result;
+ LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
+ LLPipeline::sUnderWaterRender = LLViewerCamera::getInstance()->cameraUnderWater();
+ gPipeline.updateCull(*LLViewerCamera::getInstance(), result);
+
+ gGL.setColorMask(true, true);
+
+ glClearColor(0, 0, 0, 0);
+ gPipeline.generateSunShadow(*LLViewerCamera::getInstance());
+
+ glClear(GL_DEPTH_BUFFER_BIT); // | GL_STENCIL_BUFFER_BIT);
+
+ {
+ LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
+ gPipeline.stateSort(*LLViewerCamera::getInstance(), result);
+
+ if (rebuild)
+ {
+ //////////////////////////////////////
+ //
+ // rebuildPools
+ //
+ //
+ gPipeline.rebuildPools();
+ stop_glerror();
+ }
+ }
+
+ LLPipeline::sUseOcclusion = occlusion;
+
+ LLAppViewer::instance()->pingMainloopTimeout("Display:RenderStart");
+
+ LLPipeline::sUnderWaterRender = LLViewerCamera::getInstance()->cameraUnderWater() ? TRUE : FALSE;
+
+ gGL.setColorMask(true, true);
+
+ gPipeline.mRT->deferredScreen.bindTarget();
+ if (gUseWireframe)
+ {
+ glClearColor(0.5f, 0.5f, 0.5f, 1.f);
+ }
+ else
+ {
+ glClearColor(1, 0, 1, 1);
+ }
+ gPipeline.mRT->deferredScreen.clear();
+
+ LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
+
+ gPipeline.renderGeomDeferred(*LLViewerCamera::getInstance());
+
+ gPipeline.mRT->deferredScreen.flush();
+
+ gPipeline.renderDeferredLighting();
+
+ LLPipeline::sUnderWaterRender = FALSE;
+
+ // Finalize scene
+ //gPipeline.renderFinalize();
+
+ LLSpatialGroup::sNoDelete = FALSE;
+ gPipeline.clearReferences();
+
+ gPipeline.rebuildGroups();
+}
+
void render_hud_attachments()
{
gGL.matrixMode(LLRender::MM_PROJECTION);
@@ -1109,6 +1157,7 @@ void render_hud_attachments()
gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_SIMPLE);
gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_VOLUME);
gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_ALPHA);
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_ALPHA_PRE_WATER);
gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_ALPHA_MASK);
gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_FULLBRIGHT_ALPHA_MASK);
gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_FULLBRIGHT);
@@ -1125,7 +1174,7 @@ void render_hud_attachments()
gPipeline.stateSort(hud_cam, result);
- gPipeline.renderGeom(hud_cam);
+ gPipeline.renderGeomPostDeferred(hud_cam);
LLSpatialGroup::sNoDelete = FALSE;
//gPipeline.clearReferences();
@@ -1241,7 +1290,7 @@ bool setup_hud_matrices(const LLRect& screen_region)
void render_ui(F32 zoom_factor, int subfield)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; //LL_RECORD_BLOCK_TIME(FTM_RENDER_UI);
-
+ LL_PROFILE_GPU_ZONE("ui");
LLGLState::checkStates();
glh::matrix4f saved_view = get_current_modelview();
@@ -1262,69 +1311,68 @@ void render_ui(F32 zoom_factor, int subfield)
gGL.popMatrix();
}
- // Finalize scene
- gPipeline.renderFinalize();
+ // Render our post process prior to the HUD, UI, etc.
+ gPipeline.renderPostProcess();
+
+ // apply gamma correction and post effects
+ gPipeline.renderFinalize();
{
- // SL-15709
- // NOTE: Tracy only allows one ZoneScoped per function.
- // Solutions are:
- // 1. Use a new scope
- // 2. Use named zones
- // 3. Use transient zones
- LL_PROFILE_ZONE_NAMED_CATEGORY_UI("HUD"); //LL_RECORD_BLOCK_TIME(FTM_RENDER_HUD);
+ LLGLState::checkStates();
+
+
+ LL_PROFILE_ZONE_NAMED_CATEGORY_UI("HUD");
render_hud_elements();
+ LLGLState::checkStates();
render_hud_attachments();
+ LLGLState::checkStates();
+
LLGLSDefault gls_default;
LLGLSUIDefault gls_ui;
{
gPipeline.disableLights();
}
- {
- gGL.color4f(1,1,1,1);
- if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
- {
- if (!gDisconnected)
- {
- LL_PROFILE_ZONE_NAMED_CATEGORY_UI("UI 3D"); //LL_RECORD_BLOCK_TIME(FTM_RENDER_UI_3D);
- render_ui_3d();
- LLGLState::checkStates();
- }
- else
- {
- render_disconnected_background();
- }
-
- LL_PROFILE_ZONE_NAMED_CATEGORY_UI("UI 2D"); //LL_RECORD_BLOCK_TIME(FTM_RENDER_UI_2D);
- render_ui_2d();
- LLGLState::checkStates();
- }
- gGL.flush();
-
- gViewerWindow->setup2DRender();
- gViewerWindow->updateDebugText();
- gViewerWindow->drawDebugText();
+ bool render_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI);
+ if (render_ui)
+ {
+ if (!gDisconnected)
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_UI("UI 3D"); //LL_RECORD_BLOCK_TIME(FTM_RENDER_UI_3D);
+ LLGLState::checkStates();
+ render_ui_3d();
+ LLGLState::checkStates();
+ }
+ else
+ {
+ render_disconnected_background();
+ }
+ }
- LLVertexBuffer::unbind();
- }
+ if (render_ui)
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_UI("UI 2D"); //LL_RECORD_BLOCK_TIME(FTM_RENDER_UI_2D);
+ LLHUDObject::renderAll();
+ render_ui_2d();
+ }
- if (!gSnapshot)
- {
- set_current_modelview(saved_view);
- gGL.popMatrix();
- }
+ gViewerWindow->setup2DRender();
+ gViewerWindow->updateDebugText();
+ gViewerWindow->drawDebugText();
+ }
- } // Tracy integration
+ if (!gSnapshot)
+ {
+ set_current_modelview(saved_view);
+ gGL.popMatrix();
+ }
}
-static LLTrace::BlockTimerStatHandle FTM_SWAP("Swap");
-
void swap()
{
- LL_RECORD_BLOCK_TIME(FTM_SWAP);
-
+ LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Swap");
+ LL_PROFILE_GPU_ZONE("swap");
if (gDisplaySwapBuffers)
{
gViewerWindow->getWindow()->swapBuffers();
@@ -1422,6 +1470,7 @@ void render_ui_3d()
stop_glerror();
gUIProgram.bind();
+ gGL.color4f(1, 1, 1, 1);
// Coordinate axes
if (gSavedSettings.getBOOL("ShowAxes"))
@@ -1430,6 +1479,15 @@ void render_ui_3d()
}
gViewerWindow->renderSelections(FALSE, FALSE, TRUE); // Non HUD call in render_hud_elements
+
+ if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
+ {
+ // Render debugging beacons.
+ gObjectList.renderObjectBeacons();
+ gObjectList.resetObjectBeacons();
+ gSky.addSunMoonBeacons();
+ }
+
stop_glerror();
}
@@ -1465,6 +1523,7 @@ void render_ui_2d()
// render outline for HUD
if (isAgentAvatarValid() && gAgentCamera.mHUDCurZoom < 0.98f)
{
+ gUIProgram.bind();
gGL.pushMatrix();
S32 half_width = (gViewerWindow->getWorldViewWidthScaled() / 2);
S32 half_height = (gViewerWindow->getWorldViewHeightScaled() / 2);
@@ -1475,6 +1534,7 @@ void render_ui_2d()
gGL.color4fv(LLColor4::white.mV);
gl_rect_2d(-half_width, half_height, half_width, -half_height, FALSE);
gGL.popMatrix();
+ gUIProgram.unbind();
stop_glerror();
}
@@ -1486,7 +1546,7 @@ void render_ui_2d()
LLView::sIsRectDirty = false;
LLRect t_rect;
- gPipeline.mUIScreen.bindTarget();
+ gPipeline.mRT->uiScreen.bindTarget();
gGL.setColorMask(true, true);
{
static const S32 pad = 8;
@@ -1518,7 +1578,7 @@ void render_ui_2d()
gViewerWindow->draw();
}
- gPipeline.mUIScreen.flush();
+ gPipeline.mRT->uiScreen.flush();
gGL.setColorMask(true, false);
LLView::sDirtyRect = t_rect;
@@ -1528,7 +1588,7 @@ void render_ui_2d()
LLGLDisable blend(GL_BLEND);
S32 width = gViewerWindow->getWindowWidthScaled();
S32 height = gViewerWindow->getWindowHeightScaled();
- gGL.getTexUnit(0)->bind(&gPipeline.mUIScreen);
+ gGL.getTexUnit(0)->bind(&gPipeline.mRT->uiScreen);
gGL.begin(LLRender::TRIANGLE_STRIP);
gGL.color4f(1,1,1,1);
gGL.texCoord2f(0, 0); gGL.vertex2i(0, 0);
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index c0398372b4..14d5a7c276 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -135,7 +135,6 @@
#include "llfloatertelehub.h"
#include "llfloatertestinspectors.h"
#include "llfloatertestlistview.h"
-#include "llfloatertexturefetchdebugger.h"
#include "llfloatertools.h"
#include "llfloatertopobjects.h"
#include "llfloatertos.h"
@@ -154,6 +153,7 @@
#include "llinspectobject.h"
#include "llinspectremoteobject.h"
#include "llinspecttoast.h"
+#include "llmaterialeditor.h"
#include "llmoveview.h"
#include "llfloaterimnearbychat.h"
#include "llpanelblockedlist.h"
@@ -385,10 +385,6 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("mem_leaking", "floater_mem_leaking.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMemLeak>);
- if(gSavedSettings.getBOOL("TextureFetchDebuggerEnabled"))
- {
- LLFloaterReg::add("tex_fetch_debugger", "floater_texture_fetch_debugger.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTextureFetchDebugger>);
- }
LLFloaterReg::add("media_settings", "floater_media_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMediaSettings>);
LLFloaterReg::add("marketplace_listings", "floater_marketplace_listings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMarketplaceListings>);
LLFloaterReg::add("marketplace_validation", "floater_marketplace_validation.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMarketplaceValidation>);
@@ -438,6 +434,9 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("save_camera_preset", "floater_save_camera_preset.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSaveCameraPreset>);
LLFloaterReg::add("script_colors", "floater_script_ed_prefs.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterScriptEdPrefs>);
+ LLFloaterReg::add("material_editor", "floater_material_editor.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLMaterialEditor>);
+ LLFloaterReg::add("live_material_editor", "floater_live_material_editor.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLMaterialEditor>);
+
LLFloaterReg::add("telehubs", "floater_telehub.xml",&LLFloaterReg::build<LLFloaterTelehub>);
LLFloaterReg::add("test_inspectors", "floater_test_inspectors.xml", &LLFloaterReg::build<LLFloaterTestInspectors>);
//LLFloaterReg::add("test_list_view", "floater_test_list_view.xml",&LLFloaterReg::build<LLFloaterTestListView>);
diff --git a/indra/newview/llviewerfoldertype.cpp b/indra/newview/llviewerfoldertype.cpp
index f770db31dd..c8d4aae8fd 100644
--- a/indra/newview/llviewerfoldertype.cpp
+++ b/indra/newview/llviewerfoldertype.cpp
@@ -134,6 +134,7 @@ LLViewerFolderDictionary::LLViewerFolderDictionary()
addEntry(LLFolderType::FT_MY_OUTFITS, new ViewerFolderEntry("My Outfits", "Inv_SysOpen", "Inv_SysClosed", TRUE, true));
addEntry(LLFolderType::FT_MESH, new ViewerFolderEntry("Meshes", "Inv_SysOpen", "Inv_SysClosed", FALSE, true));
addEntry(LLFolderType::FT_SETTINGS, new ViewerFolderEntry("Settings", "Inv_SysOpen", "Inv_SysClosed", FALSE, true));
+ addEntry(LLFolderType::FT_MATERIAL, new ViewerFolderEntry("Materials", "Inv_SysOpen", "Inv_SysClosed", FALSE, true));
bool boxes_invisible = !gSavedSettings.getBOOL("InventoryOutboxMakeVisible");
addEntry(LLFolderType::FT_INBOX, new ViewerFolderEntry("Received Items", "Inv_SysOpen", "Inv_SysClosed", FALSE, boxes_invisible));
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 50252556de..518967709d 100644
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -147,6 +147,7 @@ LLLocalizedInventoryItemsDictionary::LLLocalizedInventoryItemsDictionary()
mInventoryItemsDict["Invalid Wearable"] = LLTrans::getString("Invalid Wearable");
mInventoryItemsDict["New Gesture"] = LLTrans::getString("New Gesture");
+ mInventoryItemsDict["New Material"] = LLTrans::getString("New Material");
mInventoryItemsDict["New Script"] = LLTrans::getString("New Script");
mInventoryItemsDict["New Folder"] = LLTrans::getString("New Folder");
mInventoryItemsDict["New Note"] = LLTrans::getString("New Note");
@@ -998,6 +999,21 @@ void create_notecard_cb(const LLUUID& inv_item)
}
}
+void create_gltf_material_cb(const LLUUID& inv_item)
+{
+ if (!inv_item.isNull())
+ {
+ LLViewerInventoryItem* item = gInventory.getItem(inv_item);
+ if (item)
+ {
+ set_default_permissions(item, "Materials");
+
+ gInventory.updateItem(item);
+ gInventory.notifyObservers();
+ }
+ }
+}
+
LLInventoryCallbackManager gInventoryCallbacks;
void create_inventory_item(const LLUUID& agent_id, const LLUUID& session_id,
@@ -1622,6 +1638,13 @@ void create_new_item(const std::string& name,
next_owner_perm = LLFloaterPerms::getNextOwnerPerms("Notecards");
break;
}
+
+ case LLInventoryType::IT_MATERIAL:
+ {
+ cb = new LLBoostFuncInventoryCallback(create_gltf_material_cb);
+ next_owner_perm = LLFloaterPerms::getNextOwnerPerms("Materials");
+ break;
+ }
default:
break;
}
@@ -1672,6 +1695,7 @@ void remove_folder_contents(const LLUUID& category, bool keep_outfit_links,
const std::string NEW_LSL_NAME = "New Script"; // *TODO:Translate? (probably not)
const std::string NEW_NOTECARD_NAME = "New Note"; // *TODO:Translate? (probably not)
const std::string NEW_GESTURE_NAME = "New Gesture"; // *TODO:Translate? (probably not)
+const std::string NEW_MATERIAL_NAME = "New Material"; // *TODO:Translate? (probably not)
// ! REFACTOR ! Really need to refactor this so that it's not a bunch of if-then statements...
void menu_create_inventory_item(LLInventoryPanel* panel, LLFolderBridge *bridge, const LLSD& userdata, const LLUUID& default_parent_uuid)
@@ -1727,6 +1751,15 @@ void menu_create_inventory_item(LLInventoryPanel* panel, LLFolderBridge *bridge,
LLInventoryType::IT_GESTURE,
PERM_ALL); // overridden in create_new_item
}
+ else if ("material" == type_name)
+ {
+ const LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLFolderType::FT_MATERIAL);
+ create_new_item(NEW_MATERIAL_NAME,
+ parent_id,
+ LLAssetType::AT_MATERIAL,
+ LLInventoryType::IT_MATERIAL,
+ PERM_ALL); // overridden in create_new_item
+ }
else if (("sky" == type_name) || ("water" == type_name) || ("daycycle" == type_name))
{
LLSettingsType::type_e stype(LLSettingsType::ST_NONE);
diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp
index f3b0e82b3a..be2a1da968 100644
--- a/indra/newview/llviewerjointmesh.cpp
+++ b/indra/newview/llviewerjointmesh.cpp
@@ -1,4 +1,4 @@
-/**
+ /**
* @file llviewerjointmesh.cpp
* @brief Implementation of LLViewerJointMesh class
*
@@ -62,10 +62,6 @@ extern PFNGLWEIGHTFVARBPROC glWeightfvARB;
extern PFNGLVERTEXBLENDARBPROC glVertexBlendARB;
#endif
-static const U32 sRenderMask = LLVertexBuffer::MAP_VERTEX |
- LLVertexBuffer::MAP_NORMAL |
- LLVertexBuffer::MAP_TEXCOORD0;
-
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// LLViewerJointMesh
@@ -287,8 +283,6 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy)
gGL.getTexUnit(diffuse_channel)->bind(LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT));
}
- U32 mask = sRenderMask;
-
U32 start = mMesh->mFaceVertexOffset;
U32 end = start + mMesh->mFaceVertexCount - 1;
U32 count = mMesh->mFaceIndexCount;
@@ -304,14 +298,9 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy)
{
uploadJointMatrices();
}
- mask = mask | LLVertexBuffer::MAP_WEIGHT;
- if (mFace->getPool()->getShaderLevel() > 1)
- {
- mask = mask | LLVertexBuffer::MAP_CLOTHWEIGHT;
- }
}
- buff->setBuffer(mask);
+ buff->setBuffer();
buff->drawRange(LLRender::TRIANGLES, start, end, count, offset);
}
else
@@ -319,7 +308,7 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy)
gGL.pushMatrix();
LLMatrix4 jointToWorld = getWorldMatrix();
gGL.multMatrix((GLfloat*)jointToWorld.mMatrix);
- buff->setBuffer(mask);
+ buff->setBuffer();
buff->drawRange(LLRender::TRIANGLES, start, end, count, offset);
gGL.popMatrix();
}
@@ -506,7 +495,7 @@ void LLViewerJointMesh::updateGeometry(LLFace *mFace, LLPolyMesh *mMesh)
}
}
- buffer->flush();
+ buffer->unmapBuffer();
}
void LLViewerJointMesh::updateJointGeometry()
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index a0223a5dbb..bc722f496f 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -93,6 +93,7 @@
#include "llpanelblockedlist.h"
#include "llpanelmaininventory.h"
#include "llmarketplacefunctions.h"
+#include "llmaterialeditor.h"
#include "llmenuoptionpathfindingrebakenavmesh.h"
#include "llmoveview.h"
#include "llnavigationbar.h"
@@ -270,16 +271,11 @@ void handle_reset_view();
void handle_duplicate_in_place(void*);
-
void handle_object_owner_self(void*);
void handle_object_owner_permissive(void*);
void handle_object_lock(void*);
void handle_object_asset_ids(void*);
void force_take_copy(void*);
-#ifdef _CORY_TESTING
-void force_export_copy(void*);
-void force_import_geometry(void*);
-#endif
void handle_force_parcel_owner_to_me(void*);
void handle_force_parcel_to_content(void*);
@@ -1096,6 +1092,10 @@ U64 info_display_from_string(std::string info_display)
{
return LLPipeline::RENDER_DEBUG_IMPOSTORS;
}
+ else if ("reflection probes" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_REFLECTION_PROBES;
+ }
else
{
LL_WARNS() << "unrecognized feature name '" << info_display << "'" << LL_ENDL;
@@ -1185,33 +1185,9 @@ class LLAdvancedCheckPeriodicSlowFrame : public view_listener_t
};
-
-////////////////
-// FRAME TEST //
-////////////////
-
-
-class LLAdvancedToggleFrameTest : public view_listener_t
-{
- bool handleEvent(const LLSD& userdata)
- {
- LLPipeline::sRenderFrameTest = !(LLPipeline::sRenderFrameTest);
- return true;
- }
-};
-
-class LLAdvancedCheckFrameTest : public view_listener_t
-{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = LLPipeline::sRenderFrameTest;
- return new_value;
- }
-};
-
-
///////////////////////////
// SELECTED TEXTURE INFO //
+//
///////////////////////////
@@ -1233,24 +1209,6 @@ class LLAdvancedToggleWireframe : public view_listener_t
bool handleEvent(const LLSD& userdata)
{
gUseWireframe = !(gUseWireframe);
- gWindowResized = TRUE;
-
- LLPipeline::updateRenderDeferred();
-
- if (gUseWireframe)
- {
- gInitialDeferredModeForWireframe = LLPipeline::sRenderDeferred;
- }
-
- gPipeline.resetVertexBuffers();
-
- if (!gUseWireframe && !gInitialDeferredModeForWireframe && LLPipeline::sRenderDeferred != bool(gInitialDeferredModeForWireframe) && gPipeline.isInit())
- {
- LLPipeline::refreshCachedSettings();
- gPipeline.releaseGLBuffers();
- gPipeline.createGLBuffers();
- LLViewerShaderMgr::instance()->setShaders();
- }
return true;
}
@@ -1260,8 +1218,7 @@ class LLAdvancedCheckWireframe : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
{
- bool new_value = gUseWireframe;
- return new_value;
+ return gUseWireframe;
}
};
@@ -2339,47 +2296,6 @@ class LLAdvancedCheckViewAdminOptions : public view_listener_t
}
};
-/////////////////////////////////////
-// Enable Object Object Occlusion ///
-/////////////////////////////////////
-class LLAdvancedEnableObjectObjectOcclusion: public view_listener_t
-{
- bool handleEvent(const LLSD& userdata)
- {
-
- bool new_value = gGLManager.mHasOcclusionQuery; // && LLFeatureManager::getInstance()->isFeatureAvailable(userdata.asString());
- return new_value;
-}
-};
-
-/////////////////////////////////////
-// Enable Deferred Rendering ///
-/////////////////////////////////////
-class LLAdvancedEnableRenderDeferred: public view_listener_t
-{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_WINDLIGHT) > 1 &&
- LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) > 0;
- return new_value;
- }
-};
-
-/////////////////////////////////////
-// Enable Deferred Rendering sub-options
-/////////////////////////////////////
-class LLAdvancedEnableRenderDeferredOptions: public view_listener_t
-{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_WINDLIGHT) > 1 &&
- LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) > 0 && gSavedSettings.getBOOL("RenderDeferred");
- return new_value;
- }
-};
-
-
-
//////////////////
// ADMIN STATUS //
//////////////////
@@ -2581,14 +2497,6 @@ class LLDevelopSetLoggingLevel : public view_listener_t
}
};
-class LLDevelopTextureFetchDebugger : public view_listener_t
-{
- bool handleEvent(const LLSD& userdata)
- {
- return gSavedSettings.getBOOL("TextureFetchDebuggerEnabled");
- }
-};
-
//////////////////
// ADMIN MENU //
//////////////////
@@ -2876,6 +2784,51 @@ void handle_object_open()
LLFloaterReg::showInstance("openobject");
}
+struct LLSelectedTEGetmatIdAndPermissions : public LLSelectedTEFunctor
+{
+ LLSelectedTEGetmatIdAndPermissions() : mCanCopy(true), mCanModify(true), mCanTransfer(true) {}
+ bool apply(LLViewerObject* objectp, S32 te_index)
+ {
+ mCanCopy &= (bool)objectp->permCopy();
+ mCanTransfer &= (bool)objectp->permTransfer();
+ mCanModify &= (bool)objectp->permModify();
+ LLUUID mat_id = objectp->getRenderMaterialID(te_index);
+ if (mat_id.notNull())
+ {
+ mMaterialId = mat_id;
+ }
+ return true;
+ }
+ bool mCanCopy;
+ bool mCanModify;
+ bool mCanTransfer;
+ LLUUID mMaterialId;
+};
+
+bool enable_object_edit_gltf_material()
+{
+ if (!LLMaterialEditor::capabilitiesAvailable())
+ {
+ return false;
+ }
+
+ LLSelectedTEGetmatIdAndPermissions func;
+ LLSelectMgr::getInstance()->getSelection()->applyToTEs(&func);
+ return func.mCanModify && func.mMaterialId.notNull();
+}
+
+bool enable_object_save_gltf_material()
+{
+ if (!LLMaterialEditor::capabilitiesAvailable())
+ {
+ return false;
+ }
+
+ LLSelectedTEGetmatIdAndPermissions func;
+ LLSelectMgr::getInstance()->getSelection()->applyToTEs(&func);
+ return func.mCanCopy && func.mMaterialId.notNull();
+}
+
bool enable_object_open()
{
// Look for contents in root object, which is all the LLFloaterOpenObject
@@ -2941,37 +2894,42 @@ class LLObjectBuild : public view_listener_t
}
};
-void handle_object_edit()
+void update_camera()
{
- LLViewerParcelMgr::getInstance()->deselectLand();
+ LLViewerParcelMgr::getInstance()->deselectLand();
- if (gAgentCamera.getFocusOnAvatar() && !LLToolMgr::getInstance()->inEdit())
- {
- LLFloaterTools::sPreviousFocusOnAvatar = true;
- LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
+ if (gAgentCamera.getFocusOnAvatar() && !LLToolMgr::getInstance()->inEdit())
+ {
+ LLFloaterTools::sPreviousFocusOnAvatar = true;
+ LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
+
+ if (selection->getSelectType() == SELECT_TYPE_HUD || !gSavedSettings.getBOOL("EditCameraMovement"))
+ {
+ // always freeze camera in space, even if camera doesn't move
+ // so, for example, follow cam scripts can't affect you when in build mode
+ gAgentCamera.setFocusGlobal(gAgentCamera.calcFocusPositionTargetGlobal(), LLUUID::null);
+ gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE);
+ }
+ else
+ {
+ gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE);
+ LLViewerObject* selected_objectp = selection->getFirstRootObject();
+ if (selected_objectp)
+ {
+ // zoom in on object center instead of where we clicked, as we need to see the manipulator handles
+ gAgentCamera.setFocusGlobal(selected_objectp->getPositionGlobal(), selected_objectp->getID());
+ gAgentCamera.cameraZoomIn(0.666f);
+ gAgentCamera.cameraOrbitOver(30.f * DEG_TO_RAD);
+ gViewerWindow->moveCursorToCenter();
+ }
+ }
+ }
+}
+
+void handle_object_edit()
+{
+ update_camera();
- if (selection->getSelectType() == SELECT_TYPE_HUD || !gSavedSettings.getBOOL("EditCameraMovement"))
- {
- // always freeze camera in space, even if camera doesn't move
- // so, for example, follow cam scripts can't affect you when in build mode
- gAgentCamera.setFocusGlobal(gAgentCamera.calcFocusPositionTargetGlobal(), LLUUID::null);
- gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE);
- }
- else
- {
- gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE);
- LLViewerObject* selected_objectp = selection->getFirstRootObject();
- if (selected_objectp)
- {
- // zoom in on object center instead of where we clicked, as we need to see the manipulator handles
- gAgentCamera.setFocusGlobal(selected_objectp->getPositionGlobal(), selected_objectp->getID());
- gAgentCamera.cameraZoomIn(0.666f);
- gAgentCamera.cameraOrbitOver( 30.f * DEG_TO_RAD );
- gViewerWindow->moveCursorToCenter();
- }
- }
- }
-
LLFloaterReg::showInstance("build");
LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset);
@@ -2985,6 +2943,28 @@ void handle_object_edit()
return;
}
+void handle_object_edit_gltf_material()
+{
+ if (!LLFloaterReg::instanceVisible("build"))
+ {
+ handle_object_edit(); // does update_camera();
+ }
+ else
+ {
+ update_camera();
+
+ LLViewerJoystick::getInstance()->moveObjects(true);
+ LLViewerJoystick::getInstance()->setNeedsReset(true);
+ }
+
+ LLMaterialEditor::loadLive();
+}
+
+void handle_object_save_gltf_material()
+{
+ LLMaterialEditor::savePickedMaterialAs();
+}
+
void handle_attachment_edit(const LLUUID& inv_item_id)
{
if (isAgentAvatarValid())
@@ -8131,6 +8111,18 @@ class LLToolsSelectOnlyMovableObjects : public view_listener_t
}
};
+class LLToolsSelectInvisibleObjects : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ BOOL cur_val = gSavedSettings.getBOOL("SelectInvisibleObjects");
+
+ gSavedSettings.setBOOL("SelectInvisibleObjects", !cur_val);
+
+ return true;
+ }
+};
+
class LLToolsSelectBySurrounding : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
@@ -8463,6 +8455,12 @@ void handle_cache_clear_immediately()
LLNotificationsUtil::add("ConfirmClearCache", LLSD(), LLSD(), callback_clear_cache_immediately);
}
+void handle_rebuild_reflection_probes()
+{
+ gPipeline.mReflectionMapManager.rebuild();
+}
+
+
void handle_web_content_test(const LLSD& param)
{
std::string url = param.asString();
@@ -9354,6 +9352,7 @@ void initialize_menus()
view_listener_t::addMenu(new LLToolsSelectTool(), "Tools.SelectTool");
view_listener_t::addMenu(new LLToolsSelectOnlyMyObjects(), "Tools.SelectOnlyMyObjects");
view_listener_t::addMenu(new LLToolsSelectOnlyMovableObjects(), "Tools.SelectOnlyMovableObjects");
+ view_listener_t::addMenu(new LLToolsSelectInvisibleObjects(), "Tools.SelectInvisibleObjects");
view_listener_t::addMenu(new LLToolsSelectBySurrounding(), "Tools.SelectBySurrounding");
view_listener_t::addMenu(new LLToolsShowHiddenSelection(), "Tools.ShowHiddenSelection");
view_listener_t::addMenu(new LLToolsShowSelectionLightRadius(), "Tools.ShowSelectionLightRadius");
@@ -9422,15 +9421,10 @@ void initialize_menus()
view_listener_t::addMenu(new LLAdvancedToggleWireframe(), "Advanced.ToggleWireframe");
view_listener_t::addMenu(new LLAdvancedCheckWireframe(), "Advanced.CheckWireframe");
// Develop > Render
- view_listener_t::addMenu(new LLAdvancedEnableObjectObjectOcclusion(), "Advanced.EnableObjectObjectOcclusion");
- view_listener_t::addMenu(new LLAdvancedEnableRenderDeferred(), "Advanced.EnableRenderDeferred");
- view_listener_t::addMenu(new LLAdvancedEnableRenderDeferredOptions(), "Advanced.EnableRenderDeferredOptions");
view_listener_t::addMenu(new LLAdvancedToggleRandomizeFramerate(), "Advanced.ToggleRandomizeFramerate");
view_listener_t::addMenu(new LLAdvancedCheckRandomizeFramerate(), "Advanced.CheckRandomizeFramerate");
view_listener_t::addMenu(new LLAdvancedTogglePeriodicSlowFrame(), "Advanced.TogglePeriodicSlowFrame");
view_listener_t::addMenu(new LLAdvancedCheckPeriodicSlowFrame(), "Advanced.CheckPeriodicSlowFrame");
- view_listener_t::addMenu(new LLAdvancedToggleFrameTest(), "Advanced.ToggleFrameTest");
- view_listener_t::addMenu(new LLAdvancedCheckFrameTest(), "Advanced.CheckFrameTest");
view_listener_t::addMenu(new LLAdvancedHandleAttachedLightParticles(), "Advanced.HandleAttachedLightParticles");
view_listener_t::addMenu(new LLAdvancedCheckRenderShadowOption(), "Advanced.CheckRenderShadowOption");
view_listener_t::addMenu(new LLAdvancedClickRenderShadowOption(), "Advanced.ClickRenderShadowOption");
@@ -9561,10 +9555,10 @@ void initialize_menus()
view_listener_t::addMenu(new LLDevelopCheckLoggingLevel(), "Develop.CheckLoggingLevel");
view_listener_t::addMenu(new LLDevelopSetLoggingLevel(), "Develop.SetLoggingLevel");
- //Develop (Texture Fetch Debug Console)
- view_listener_t::addMenu(new LLDevelopTextureFetchDebugger(), "Develop.SetTexFetchDebugger");
//Develop (clear cache immediately)
commit.add("Develop.ClearCache", boost::bind(&handle_cache_clear_immediately) );
+ //Develop (override environment map)
+ commit.add("Develop.RebuildReflectionProbes", boost::bind(&handle_rebuild_reflection_probes));
// Admin >Object
view_listener_t::addMenu(new LLAdminForceTakeCopy(), "Admin.ForceTakeCopy");
@@ -9644,10 +9638,15 @@ void initialize_menus()
commit.add("Object.Buy", boost::bind(&handle_buy));
commit.add("Object.Edit", boost::bind(&handle_object_edit));
+ commit.add("Object.Edit", boost::bind(&handle_object_edit));
+ commit.add("Object.EditGLTFMaterial", boost::bind(&handle_object_edit_gltf_material));
+ commit.add("Object.SaveGLTFMaterial", boost::bind(&handle_object_save_gltf_material));
commit.add("Object.Inspect", boost::bind(&handle_object_inspect));
commit.add("Object.Open", boost::bind(&handle_object_open));
commit.add("Object.Take", boost::bind(&handle_take));
commit.add("Object.ShowInspector", boost::bind(&handle_object_show_inspector));
+ enable.add("Object.EnableEditGLTFMaterial", boost::bind(&enable_object_edit_gltf_material));
+ enable.add("Object.EnableSaveGLTFMaterial", boost::bind(&enable_object_save_gltf_material));
enable.add("Object.EnableOpen", boost::bind(&enable_object_open));
enable.add("Object.EnableTouch", boost::bind(&enable_object_touch, _1));
enable.add("Object.EnableDelete", boost::bind(&enable_object_delete));
diff --git a/indra/newview/llviewermenu.h b/indra/newview/llviewermenu.h
index a90b32c984..7142763451 100644
--- a/indra/newview/llviewermenu.h
+++ b/indra/newview/llviewermenu.h
@@ -90,6 +90,8 @@ void handle_gestures(void*);
void handle_sit_down(void*);
void handle_object_build(void*);
void handle_object_touch();
+bool enable_object_edit_gltf_material();
+bool enable_object_save_gltf_material();
bool enable_object_open();
void handle_object_open();
@@ -108,6 +110,8 @@ void handle_zoom_to_object(LLUUID object_id);
void handle_object_return();
void handle_object_delete();
void handle_object_edit();
+void handle_object_edit_gltf_material();
+void handle_object_save_gltf_material();
void handle_attachment_edit(const LLUUID& inv_item_id);
void handle_attachment_touch(const LLUUID& inv_item_id);
@@ -131,7 +135,6 @@ bool anyone_copy_selection(LLSelectNode* nodep);
// *TODO: Move to separate file
bool for_sale_selection(LLSelectNode* nodep);
-void handle_save_snapshot(void *);
void handle_toggle_flycam();
void handle_object_sit_or_stand();
diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp
index fdf1d04c09..84b0010545 100644
--- a/indra/newview/llviewermenufile.cpp
+++ b/indra/newview/llviewermenufile.cpp
@@ -37,6 +37,8 @@
#include "llbuycurrencyhtml.h"
#include "llfloatermap.h"
#include "llfloatermodelpreview.h"
+#include "llmaterialeditor.h"
+#include "llfloaterperms.h"
#include "llfloatersnapshot.h"
#include "llfloatersimpleoutfitsnapshot.h"
#include "llimage.h"
@@ -48,9 +50,9 @@
#include "llinventorymodel.h" // gInventory
#include "llpluginclassmedia.h"
#include "llresourcedata.h"
-#include "lltoast.h"
-#include "llfloaterperms.h"
#include "llstatusbar.h"
+#include "lltinygltfhelper.h"
+#include "lltoast.h"
#include "llviewercontrol.h" // gSavedSettings
#include "llviewertexturelist.h"
#include "lluictrlfactory.h"
@@ -101,6 +103,19 @@ class LLFileEnableUploadModel : public view_listener_t
}
};
+class LLFileEnableUploadMaterial : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ if (gAgent.getRegionCapability("UpdateMaterialAgentInventory").empty())
+ {
+ return false;
+ }
+
+ return true;
+ }
+};
+
class LLMeshEnabled : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
@@ -234,6 +249,16 @@ LLFilePickerReplyThread::~LLFilePickerReplyThread()
delete mFailureSignal;
}
+void LLFilePickerReplyThread::startPicker(const file_picked_signal_t::slot_type & cb, LLFilePicker::ELoadFilter filter, bool get_multiple, const file_picked_signal_t::slot_type & failure_cb)
+{
+ (new LLFilePickerReplyThread(cb, filter, get_multiple, failure_cb))->getFile();
+}
+
+void LLFilePickerReplyThread::startPicker(const file_picked_signal_t::slot_type & cb, LLFilePicker::ESaveFilter filter, const std::string & proposed_name, const file_picked_signal_t::slot_type & failure_cb)
+{
+ (new LLFilePickerReplyThread(cb, filter, proposed_name, failure_cb))->getFile();
+}
+
void LLFilePickerReplyThread::notify(const std::vector<std::string>& filenames)
{
if (filenames.empty())
@@ -277,14 +302,12 @@ void LLMediaFilePicker::notify(const std::vector<std::string>& filenames)
static std::string SOUND_EXTENSIONS = "wav";
static std::string IMAGE_EXTENSIONS = "tga bmp jpg jpeg png";
static std::string ANIM_EXTENSIONS = "bvh anim";
-#ifdef _CORY_TESTING
-static std::string GEOMETRY_EXTENSIONS = "slg";
-#endif
static std::string XML_EXTENSIONS = "xml";
static std::string SLOBJECT_EXTENSIONS = "slobject";
#endif
static std::string ALL_FILE_EXTENSIONS = "*.*";
static std::string MODEL_EXTENSIONS = "dae";
+static std::string MATERIAL_EXTENSIONS = "gltf glb";
std::string build_extensions_string(LLFilePicker::ELoadFilter filter)
{
@@ -301,10 +324,8 @@ std::string build_extensions_string(LLFilePicker::ELoadFilter filter)
return SLOBJECT_EXTENSIONS;
case LLFilePicker::FFLOAD_MODEL:
return MODEL_EXTENSIONS;
-#ifdef _CORY_TESTING
- case LLFilePicker::FFLOAD_GEOMETRY:
- return GEOMETRY_EXTENSIONS;
-#endif
+ case LLFilePicker::FFLOAD_MATERIAL:
+ return MATERIAL_EXTENSIONS;
case LLFilePicker::FFLOAD_XML:
return XML_EXTENSIONS;
case LLFilePicker::FFLOAD_ALL:
@@ -451,19 +472,33 @@ void do_bulk_upload(std::vector<std::string> filenames, const LLSD& notification
if (LLResourceUploadInfo::findAssetTypeAndCodecOfExtension(ext, asset_type, codec) &&
LLAgentBenefitsMgr::current().findUploadCost(asset_type, expected_upload_cost))
{
- LLResourceUploadInfo::ptr_t uploadInfo(new LLNewFileResourceUploadInfo(
- filename,
- asset_name,
- asset_name, 0,
- LLFolderType::FT_NONE, LLInventoryType::IT_NONE,
- LLFloaterPerms::getNextOwnerPerms("Uploads"),
- LLFloaterPerms::getGroupPerms("Uploads"),
- LLFloaterPerms::getEveryonePerms("Uploads"),
- expected_upload_cost));
+ LLResourceUploadInfo::ptr_t uploadInfo(new LLNewFileResourceUploadInfo(
+ filename,
+ asset_name,
+ asset_name, 0,
+ LLFolderType::FT_NONE, LLInventoryType::IT_NONE,
+ LLFloaterPerms::getNextOwnerPerms("Uploads"),
+ LLFloaterPerms::getGroupPerms("Uploads"),
+ LLFloaterPerms::getEveryonePerms("Uploads"),
+ expected_upload_cost));
+
+ upload_new_resource(uploadInfo);
+ }
- upload_new_resource(uploadInfo);
- }
-}
+ // gltf does not use normal upload procedure
+ if (ext == "gltf" || ext == "glb")
+ {
+ S32 materials_in_file = LLTinyGLTFHelper::getMaterialCountFromFile(filename);
+
+ for (S32 i = 0; i < materials_in_file; i++)
+ {
+ // Todo:
+ // 1. Decouple bulk upload from material editor
+ // 2. Take into account possiblity of identical textures
+ LLMaterialEditor::uploadMaterialFromFile(filename, i);
+ }
+ }
+ }
}
bool get_bulk_upload_expected_cost(const std::vector<std::string>& filenames, S32& total_cost, S32& file_count, S32& bvh_count)
@@ -491,6 +526,44 @@ bool get_bulk_upload_expected_cost(const std::vector<std::string>& filenames, S3
total_cost += cost;
file_count++;
}
+
+ if (ext == "gltf" || ext == "glb")
+ {
+ S32 texture_upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost();
+ S32 materials_in_file = LLTinyGLTFHelper::getMaterialCountFromFile(filename);
+
+ for (S32 i = 0; i < materials_in_file; i++)
+ {
+ LLPointer<LLFetchedGLTFMaterial> material = new LLFetchedGLTFMaterial();
+ std::string material_name;
+ bool decode_successful = LLTinyGLTFHelper::getMaterialFromFile(filename, i, material.get(), material_name);
+
+ if (decode_successful)
+ {
+ // Todo: make it account for possibility of same texture in different
+ // materials and even in scope of same material
+ S32 texture_count = 0;
+ if (material->mBaseColorId.notNull())
+ {
+ texture_count++;
+ }
+ if (material->mMetallicRoughnessId.notNull())
+ {
+ texture_count++;
+ }
+ if (material->mNormalId.notNull())
+ {
+ texture_count++;
+ }
+ if (material->mEmissiveId.notNull())
+ {
+ texture_count++;
+ }
+ total_cost += texture_count * texture_upload_cost;
+ file_count++;
+ }
+ }
+ }
}
return file_count > 0;
@@ -560,7 +633,7 @@ class LLFileUploadImage : public view_listener_t
{
gAgentCamera.changeCameraToDefault();
}
- (new LLFilePickerReplyThread(boost::bind(&upload_single_file, _1, _2), LLFilePicker::FFLOAD_IMAGE, false))->getFile();
+ LLFilePickerReplyThread::startPicker(boost::bind(&upload_single_file, _1, _2), LLFilePicker::FFLOAD_IMAGE, false);
return true;
}
};
@@ -573,7 +646,16 @@ class LLFileUploadModel : public view_listener_t
return TRUE;
}
};
-
+
+class LLFileUploadMaterial : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLMaterialEditor::importMaterial();
+ return TRUE;
+ }
+};
+
class LLFileUploadSound : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
@@ -582,7 +664,7 @@ class LLFileUploadSound : public view_listener_t
{
gAgentCamera.changeCameraToDefault();
}
- (new LLFilePickerReplyThread(boost::bind(&upload_single_file, _1, _2), LLFilePicker::FFLOAD_WAV, false))->getFile();
+ LLFilePickerReplyThread::startPicker(boost::bind(&upload_single_file, _1, _2), LLFilePicker::FFLOAD_WAV, false);
return true;
}
};
@@ -595,7 +677,7 @@ class LLFileUploadAnim : public view_listener_t
{
gAgentCamera.changeCameraToDefault();
}
- (new LLFilePickerReplyThread(boost::bind(&upload_single_file, _1, _2), LLFilePicker::FFLOAD_ANIM, false))->getFile();
+ LLFilePickerReplyThread::startPicker(boost::bind(&upload_single_file, _1, _2), LLFilePicker::FFLOAD_ANIM, false);
return true;
}
};
@@ -608,7 +690,7 @@ class LLFileUploadBulk : public view_listener_t
{
gAgentCamera.changeCameraToDefault();
}
- (new LLFilePickerReplyThread(boost::bind(&upload_bulk, _1, _2), LLFilePicker::FFLOAD_ALL, true))->getFile();
+ LLFilePickerReplyThread::startPicker(boost::bind(&upload_bulk, _1, _2), LLFilePicker::FFLOAD_ALL, true);
return true;
}
};
@@ -1104,6 +1186,7 @@ void init_menu_file()
view_listener_t::addCommit(new LLFileUploadSound(), "File.UploadSound");
view_listener_t::addCommit(new LLFileUploadAnim(), "File.UploadAnim");
view_listener_t::addCommit(new LLFileUploadModel(), "File.UploadModel");
+ view_listener_t::addCommit(new LLFileUploadMaterial(), "File.UploadMaterial");
view_listener_t::addCommit(new LLFileUploadBulk(), "File.UploadBulk");
view_listener_t::addCommit(new LLFileCloseWindow(), "File.CloseWindow");
view_listener_t::addCommit(new LLFileCloseAllWindows(), "File.CloseAllWindows");
@@ -1114,6 +1197,7 @@ void init_menu_file()
view_listener_t::addEnable(new LLFileEnableUpload(), "File.EnableUpload");
view_listener_t::addEnable(new LLFileEnableUploadModel(), "File.EnableUploadModel");
+ view_listener_t::addEnable(new LLFileEnableUploadMaterial(), "File.EnableUploadMaterial");
view_listener_t::addMenu(new LLMeshEnabled(), "File.MeshEnabled");
view_listener_t::addMenu(new LLMeshUploadVisible(), "File.VisibleUploadModel");
diff --git a/indra/newview/llviewermenufile.h b/indra/newview/llviewermenufile.h
index beeac418d9..5c2caf9c51 100644
--- a/indra/newview/llviewermenufile.h
+++ b/indra/newview/llviewermenufile.h
@@ -115,14 +115,18 @@ class LLFilePickerReplyThread : public LLFilePickerThread
public:
typedef boost::signals2::signal<void(const std::vector<std::string>& filenames, LLFilePicker::ELoadFilter load_filter, LLFilePicker::ESaveFilter save_filter)> file_picked_signal_t;
-
- LLFilePickerReplyThread(const file_picked_signal_t::slot_type& cb, LLFilePicker::ELoadFilter filter, bool get_multiple, const file_picked_signal_t::slot_type& failure_cb = file_picked_signal_t());
- LLFilePickerReplyThread(const file_picked_signal_t::slot_type& cb, LLFilePicker::ESaveFilter filter, const std::string &proposed_name, const file_picked_signal_t::slot_type& failure_cb = file_picked_signal_t());
- ~LLFilePickerReplyThread();
+
+ static void startPicker(const file_picked_signal_t::slot_type& cb, LLFilePicker::ELoadFilter filter, bool get_multiple, const file_picked_signal_t::slot_type& failure_cb = file_picked_signal_t());
+ static void startPicker(const file_picked_signal_t::slot_type& cb, LLFilePicker::ESaveFilter filter, const std::string &proposed_name, const file_picked_signal_t::slot_type& failure_cb = file_picked_signal_t());
virtual void notify(const std::vector<std::string>& filenames);
private:
+ LLFilePickerReplyThread(const file_picked_signal_t::slot_type& cb, LLFilePicker::ELoadFilter filter, bool get_multiple, const file_picked_signal_t::slot_type& failure_cb = file_picked_signal_t());
+ LLFilePickerReplyThread(const file_picked_signal_t::slot_type& cb, LLFilePicker::ESaveFilter filter, const std::string &proposed_name, const file_picked_signal_t::slot_type& failure_cb = file_picked_signal_t());
+ ~LLFilePickerReplyThread();
+
+private:
LLFilePicker::ELoadFilter mLoadFilter;
LLFilePicker::ESaveFilter mSaveFilter;
file_picked_signal_t* mFilePickedSignal;
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index d97ed61e11..e96047df14 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -1423,7 +1423,8 @@ bool check_asset_previewable(const LLAssetType::EType asset_type)
(asset_type == LLAssetType::AT_TEXTURE) ||
(asset_type == LLAssetType::AT_ANIMATION) ||
(asset_type == LLAssetType::AT_SCRIPT) ||
- (asset_type == LLAssetType::AT_SOUND);
+ (asset_type == LLAssetType::AT_SOUND) ||
+ (asset_type == LLAssetType::AT_MATERIAL);
}
void open_inventory_offer(const uuid_vec_t& objects, const std::string& from_name)
@@ -1528,6 +1529,9 @@ void open_inventory_offer(const uuid_vec_t& objects, const std::string& from_nam
case LLAssetType::AT_SOUND:
LLFloaterReg::showInstance("preview_sound", LLSD(obj_id), take_focus);
break;
+ case LLAssetType::AT_MATERIAL:
+ LLFloaterReg::showInstance("material editor", LLSD(obj_id), take_focus);
+ break;
default:
LL_DEBUGS("Messaging") << "No preview method for previewable asset type : " << LLAssetType::lookupHumanReadable(asset_type) << LL_ENDL;
break;
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index f47f0b4572..9492604d7d 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -107,6 +107,7 @@
#include "llcleanup.h"
#include "llcallstack.h"
#include "llmeshrepository.h"
+#include "llgltfmateriallist.h"
#include "llgl.h"
//#define DEBUG_UPDATE_TYPE
@@ -246,6 +247,7 @@ LLViewerObject *LLViewerObject::createObject(const LLUUID &id, const LLPCode pco
LL_WARNS() << "Unknown object pcode " << (S32)pcode << LL_ENDL;
res = NULL; break;
}
+
return res;
}
@@ -259,7 +261,6 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe
mTEImages(NULL),
mTENormalMaps(NULL),
mTESpecularMaps(NULL),
- mGLName(0),
mbCanSelect(TRUE),
mFlags(0),
mPhysicsShapeType(0),
@@ -344,6 +345,13 @@ LLViewerObject::~LLViewerObject()
{
deleteTEImages();
+ // unhook from reflection probe manager
+ if (mReflectionProbe.notNull())
+ {
+ mReflectionProbe->mViewerObject = nullptr;
+ mReflectionProbe = nullptr;
+ }
+
if(mInventory)
{
mInventory->clear(); // will deref and delete entries
@@ -513,6 +521,12 @@ void LLViewerObject::markDead()
LLFollowCamMgr::getInstance()->removeFollowCamParams(mID);
}
+ if (mReflectionProbe.notNull())
+ {
+ mReflectionProbe->mViewerObject = nullptr;
+ mReflectionProbe = nullptr;
+ }
+
sNumZombieObjects++;
}
}
@@ -3490,11 +3504,11 @@ void LLViewerObject::removeInventory(const LLUUID& item_id)
++mExpectedInventorySerialNum;
}
-bool LLViewerObject::isTextureInInventory(LLViewerInventoryItem* item)
+bool LLViewerObject::isAssetInInventory(LLViewerInventoryItem* item)
{
bool result = false;
- if (item && LLAssetType::AT_TEXTURE == item->getType())
+ if (item)
{
std::list<LLUUID>::iterator begin = mPendingInventoryItemsIDs.begin();
std::list<LLUUID>::iterator end = mPendingInventoryItemsIDs.end();
@@ -3508,13 +3522,27 @@ bool LLViewerObject::isTextureInInventory(LLViewerInventoryItem* item)
return result;
}
-void LLViewerObject::updateTextureInventory(LLViewerInventoryItem* item, U8 key, bool is_new)
+void LLViewerObject::updateMaterialInventory(LLViewerInventoryItem* item, U8 key, bool is_new)
{
- if (item && !isTextureInInventory(item))
- {
- mPendingInventoryItemsIDs.push_back(item->getAssetUUID());
- updateInventory(item, key, is_new);
- }
+ if (!item)
+ {
+ return;
+ }
+ if (LLAssetType::AT_TEXTURE != item->getType()
+ && LLAssetType::AT_MATERIAL != item->getType())
+ {
+ // Not supported
+ return;
+ }
+
+ if (isAssetInInventory(item))
+ {
+ // already there
+ return;
+ }
+
+ mPendingInventoryItemsIDs.push_back(item->getAssetUUID());
+ updateInventory(item, key, is_new);
}
void LLViewerObject::updateInventory(
@@ -4044,7 +4072,7 @@ void LLViewerObject::updateTextures()
void LLViewerObject::boostTexturePriority(BOOL boost_children /* = TRUE */)
{
- if (isDead())
+ if (isDead() || !getVolume())
{
return;
}
@@ -4585,6 +4613,7 @@ BOOL LLViewerObject::lineSegmentIntersect(const LLVector4a& start, const LLVecto
S32 face,
BOOL pick_transparent,
BOOL pick_rigged,
+ BOOL pick_unselectable,
S32* face_hit,
LLVector4a* intersection,
LLVector2* tex_coord,
@@ -4748,9 +4777,38 @@ void LLViewerObject::setNumTEs(const U8 num_tes)
{
deleteTEImages();
}
+
+ S32 original_tes = getNumTEs();
+
LLPrimitive::setNumTEs(num_tes);
setChanged(TEXTURE);
+ // touch up GLTF materials
+ if (original_tes > 0)
+ {
+ for (int i = original_tes; i < getNumTEs(); ++i)
+ {
+ LLTextureEntry* src = getTE(original_tes - 1);
+ LLTextureEntry* tep = getTE(i);
+ setRenderMaterialID(i, getRenderMaterialID(original_tes - 1), false);
+
+ if (tep)
+ {
+ LLGLTFMaterial* base_material = src->getGLTFMaterial();
+ LLGLTFMaterial* override_material = src->getGLTFMaterialOverride();
+ if (base_material && override_material)
+ {
+ tep->setGLTFMaterialOverride(new LLGLTFMaterial(*override_material));
+
+ LLGLTFMaterial* render_material = new LLFetchedGLTFMaterial();
+ *render_material = *base_material;
+ render_material->applyOverride(*override_material);
+ tep->setGLTFRenderMaterial(render_material);
+ }
+ }
+ }
+ }
+
if (mDrawable.notNull())
{
gPipeline.markTextured(mDrawable);
@@ -4871,23 +4929,28 @@ void LLViewerObject::updateAvatarMeshVisibility(const LLUUID& id, const LLUUID&
}
}
-void LLViewerObject::setTE(const U8 te, const LLTextureEntry &texture_entry)
+
+void LLViewerObject::setTE(const U8 te, const LLTextureEntry& texture_entry)
{
- LLUUID old_image_id;
- if (getTE(te))
- {
- old_image_id = getTE(te)->getID();
- }
-
- LLPrimitive::setTE(te, texture_entry);
+ LLUUID old_image_id;
+ if (getTE(te))
+ {
+ old_image_id = getTE(te)->getID();
+ }
- const LLUUID& image_id = getTE(te)->getID();
- LLViewerTexture* bakedTexture = getBakedTextureForMagicId(image_id);
- mTEImages[te] = bakedTexture ? bakedTexture : LLViewerTextureManager::getFetchedTexture(image_id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
+ LLPrimitive::setTE(te, texture_entry);
-
- updateAvatarMeshVisibility(image_id,old_image_id);
+ const LLUUID& image_id = getTE(te)->getID();
+ LLViewerTexture* bakedTexture = getBakedTextureForMagicId(image_id);
+ mTEImages[te] = bakedTexture ? bakedTexture : LLViewerTextureManager::getFetchedTexture(image_id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
+
+ updateAvatarMeshVisibility(image_id, old_image_id);
+ updateTEMaterialTextures(te);
+}
+
+void LLViewerObject::updateTEMaterialTextures(U8 te)
+{
if (getTE(te)->getMaterialParams().notNull())
{
const LLUUID& norm_id = getTE(te)->getMaterialParams()->getNormalID();
@@ -4896,6 +4959,48 @@ void LLViewerObject::setTE(const U8 te, const LLTextureEntry &texture_entry)
const LLUUID& spec_id = getTE(te)->getMaterialParams()->getSpecularID();
mTESpecularMaps[te] = LLViewerTextureManager::getFetchedTexture(spec_id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_ALM, LLViewerTexture::LOD_TEXTURE);
}
+
+ LLFetchedGLTFMaterial* mat = (LLFetchedGLTFMaterial*) getTE(te)->getGLTFRenderMaterial();
+ LLUUID mat_id = getRenderMaterialID(te);
+ if (mat == nullptr && mat_id.notNull())
+ {
+ mat = (LLFetchedGLTFMaterial*) gGLTFMaterialList.getMaterial(mat_id);
+ getTE(te)->setGLTFMaterial(mat);
+ }
+ else if (mat_id.isNull() && mat != nullptr)
+ {
+ mat = nullptr;
+ getTE(te)->setGLTFMaterial(nullptr);
+ }
+
+ auto fetch_texture = [this](const LLUUID& id)
+ {
+ LLViewerFetchedTexture* img = nullptr;
+ if (id.notNull())
+ {
+ if (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(id))
+ {
+ // TODO -- fall back to LLTextureEntry::mGLTFRenderMaterial when overriding with baked texture
+ LLViewerTexture* viewerTexture = getBakedTextureForMagicId(id);
+ img = viewerTexture ? dynamic_cast<LLViewerFetchedTexture*>(viewerTexture) : nullptr;
+ }
+ else
+ {
+ img = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_ALM, LLViewerTexture::LOD_TEXTURE);
+ img->addTextureStats(64.f * 64.f, TRUE);
+ }
+ }
+
+ return img;
+ };
+
+ if (mat != nullptr)
+ {
+ mat->mBaseColorTexture = fetch_texture(mat->mBaseColorId);
+ mat->mNormalTexture = fetch_texture(mat->mNormalId);
+ mat->mMetallicRoughnessTexture = fetch_texture(mat->mMetallicRoughnessId);
+ mat->mEmissiveTexture= fetch_texture(mat->mEmissiveId);
+ }
}
void LLViewerObject::refreshBakeTexture()
@@ -5250,10 +5355,50 @@ S32 LLViewerObject::setTEMaterialParams(const U8 te, const LLMaterialPtr pMateri
setTENormalMap(te, (pMaterialParams) ? pMaterialParams->getNormalID() : LLUUID::null);
setTESpecularMap(te, (pMaterialParams) ? pMaterialParams->getSpecularID() : LLUUID::null);
- refreshMaterials();
return retval;
}
+S32 LLViewerObject::setTEGLTFMaterialOverride(U8 te, LLGLTFMaterial* override_mat)
+{
+ LL_PROFILE_ZONE_SCOPED;
+ S32 retval = TEM_CHANGE_NONE;
+
+ LLTextureEntry* tep = getTE(te);
+ if (!tep)
+ { // this could happen if the object is not fully formed yet
+ // returning TEM_CHANGE_NONE here signals to LLGLTFMaterialList to queue the override for later
+ return retval;
+ }
+
+ LLFetchedGLTFMaterial* src_mat = (LLFetchedGLTFMaterial*) tep->getGLTFMaterial();
+
+ if (!src_mat)
+ { // we can get into this state if an override has arrived before the viewer has
+ // received or handled an update, return TEM_CHANGE_NONE to signal to LLGLTFMaterialList that it
+ // should queue the update for later
+ return retval;
+ }
+
+ tep->setGLTFMaterialOverride(override_mat);
+
+ // if override mat exists, we must also have a source mat
+ llassert(override_mat ? bool(src_mat) : true);
+
+ if (override_mat && src_mat)
+ {
+ LLFetchedGLTFMaterial* render_mat = new LLFetchedGLTFMaterial(*src_mat);
+ render_mat->applyOverride(*override_mat);
+ tep->setGLTFRenderMaterial(render_mat);
+ retval = TEM_CHANGE_TEXTURE;
+ }
+ else if (tep->setGLTFRenderMaterial(nullptr))
+ {
+ retval = TEM_CHANGE_TEXTURE;
+ }
+
+ return retval;
+}
+
void LLViewerObject::refreshMaterials()
{
setChanged(TEXTURE);
@@ -5335,6 +5480,7 @@ S32 LLViewerObject::setTERotation(const U8 te, const F32 r)
if (mDrawable.notNull() && retval)
{
gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD);
+ shrinkWrap();
}
return retval;
}
@@ -5436,7 +5582,6 @@ void LLViewerObject::fitFaceTexture(const U8 face)
LL_INFOS() << "fitFaceTexture not implemented" << LL_ENDL;
}
-
LLBBox LLViewerObject::getBoundingBoxAgent() const
{
LLVector3 position_agent;
@@ -5521,18 +5666,6 @@ S32 LLViewerObject::countInventoryContents(LLAssetType::EType type)
return count;
}
-
-void LLViewerObject::setCanSelect(BOOL canSelect)
-{
- mbCanSelect = canSelect;
- for (child_list_t::iterator iter = mChildList.begin();
- iter != mChildList.end(); iter++)
- {
- LLViewerObject* child = *iter;
- child->mbCanSelect = canSelect;
- }
-}
-
void LLViewerObject::setDebugText(const std::string &utf8text)
{
if (utf8text.empty() && !mText)
@@ -6036,8 +6169,19 @@ LLViewerObject::ExtraParameter* LLViewerObject::createNewParameterEntry(U16 para
new_block = new LLExtendedMeshParams();
break;
}
+ case LLNetworkData::PARAMS_RENDER_MATERIAL:
+ {
+ new_block = new LLRenderMaterialParams();
+ break;
+ }
+ case LLNetworkData::PARAMS_REFLECTION_PROBE:
+ {
+ new_block = new LLReflectionProbeParams();
+ break;
+ }
default:
{
+ llassert(false); // invalid parameter type
LL_INFOS() << "Unknown param type." << LL_ENDL;
break;
}
@@ -6048,6 +6192,7 @@ LLViewerObject::ExtraParameter* LLViewerObject::createNewParameterEntry(U16 para
ExtraParameter* new_entry = new ExtraParameter;
new_entry->data = new_block;
new_entry->in_use = false; // not in use yet
+ llassert(mExtraParameterList[param_type] == nullptr); // leak -- redundantly allocated parameter entry
mExtraParameterList[param_type] = new_entry;
return new_entry;
}
@@ -6179,6 +6324,14 @@ void LLViewerObject::parameterChanged(U16 param_type, LLNetworkData* data, BOOL
LL_WARNS() << "Failed to send object extra parameters: " << param_type << LL_ENDL;
}
}
+ else
+ {
+ if (param_type == LLNetworkData::PARAMS_RENDER_MATERIAL)
+ {
+ const LLRenderMaterialParams* params = in_use ? (LLRenderMaterialParams*)getParameterEntry(LLNetworkData::PARAMS_RENDER_MATERIAL) : nullptr;
+ setRenderMaterialIDs(params, local_origin);
+ }
+ }
}
void LLViewerObject::setDrawableState(U32 state, BOOL recursive)
@@ -6716,7 +6869,7 @@ F32 LLAlphaObject::getPartSize(S32 idx)
return 0.f;
}
-void LLAlphaObject::getBlendFunc(S32 face, U32& src, U32& dst)
+void LLAlphaObject::getBlendFunc(S32 face, LLRender::eBlendFactor& src, LLRender::eBlendFactor& dst)
{
}
@@ -6977,6 +7130,187 @@ LLVOAvatar* LLViewerObject::getAvatar() const
return NULL;
}
+bool LLViewerObject::hasRenderMaterialParams() const
+{
+ return getParameterEntryInUse(LLNetworkData::PARAMS_RENDER_MATERIAL);
+}
+
+void LLViewerObject::setHasRenderMaterialParams(bool has_materials)
+{
+ bool had_materials = hasRenderMaterialParams();
+
+ if (had_materials != has_materials)
+ {
+ if (has_materials)
+ {
+ setParameterEntryInUse(LLNetworkData::PARAMS_RENDER_MATERIAL, TRUE, true);
+ }
+ else
+ {
+ setParameterEntryInUse(LLNetworkData::PARAMS_RENDER_MATERIAL, FALSE, true);
+ }
+ }
+}
+
+const LLUUID& LLViewerObject::getRenderMaterialID(U8 te) const
+{
+ LLRenderMaterialParams* param_block = (LLRenderMaterialParams*)getParameterEntry(LLNetworkData::PARAMS_RENDER_MATERIAL);
+ if (param_block)
+ {
+ return param_block->getMaterial(te);
+ }
+
+ 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
+
+ // if update is bound for server, should always null out GLTFRenderMaterial and clear GLTFMaterialOverride even if ids haven't changed
+ // (the case where ids haven't changed indicates the user has reapplied the original material, in which case overrides should be dropped)
+ // otherwise, should only null out the render material where ids or overrides have changed
+ // (the case where ids have changed but overrides are still present is from unsynchronized updates from the simulator)
+
+ S32 start_idx = 0;
+ S32 end_idx = getNumTEs();
+
+ if (te_in != -1)
+ {
+ start_idx = te_in;
+ end_idx = start_idx + 1;
+ }
+
+ start_idx = llmax(start_idx, 0);
+ end_idx = llmin(end_idx, (S32) getNumTEs());
+
+ LLRenderMaterialParams* param_block = (LLRenderMaterialParams*)getParameterEntry(LLNetworkData::PARAMS_RENDER_MATERIAL);
+ if (!param_block && id.notNull())
+ { // block doesn't exist, but it will need to
+ param_block = (LLRenderMaterialParams*)createNewParameterEntry(LLNetworkData::PARAMS_RENDER_MATERIAL)->data;
+ }
+
+
+ LLFetchedGLTFMaterial* new_material = nullptr;
+ if (id.notNull())
+ {
+ new_material = gGLTFMaterialList.getMaterial(id);
+ }
+
+ // update local state
+ for (S32 te = start_idx; te < end_idx; ++te)
+ {
+ LLTextureEntry* tep = getTE(te);
+
+ bool material_changed = !param_block || id != param_block->getMaterial(te);
+
+ if (update_server)
+ {
+ // Clear most overrides so the render material better matches the material
+ // ID (preserve transforms). If overrides become passthrough, set the overrides
+ // to nullptr.
+ if (tep->setBaseMaterial())
+ {
+ material_changed = true;
+ }
+ }
+
+ if (update_server || material_changed)
+ {
+ tep->setGLTFRenderMaterial(nullptr);
+ }
+
+ if (new_material != tep->getGLTFMaterial())
+ {
+ tep->setGLTFMaterial(new_material, !update_server);
+ }
+ }
+
+ // signal to render pipe that render batches must be rebuilt for this object
+ if (!new_material)
+ {
+ rebuildMaterial();
+ }
+ else
+ {
+ LLPointer<LLViewerObject> this_ptr = this;
+ new_material->onMaterialComplete([this_ptr]() mutable {
+ if (this_ptr->isDead()) { return; }
+
+ this_ptr->rebuildMaterial();
+ });
+ }
+
+ if (update_server)
+ {
+ // update via ModifyMaterialParams cap (server will echo back changes)
+ for (S32 te = start_idx; te < end_idx; ++te)
+ {
+ // This sends a cleared version of this object's current material
+ // override, but the override should already be cleared due to
+ // calling setBaseMaterial above.
+ LLGLTFMaterialList::queueApply(this, te, id);
+ }
+ }
+
+ // predictively update LLRenderMaterialParams (don't wait for server)
+ if (param_block)
+ { // update existing parameter block
+ for (S32 te = start_idx; te < end_idx; ++te)
+ {
+ param_block->setMaterial(te, id);
+ }
+
+ if (update_server)
+ {
+ // If 'in use' changes, it will send an update itself.
+ bool in_use_changed = setParameterEntryInUse(LLNetworkData::PARAMS_RENDER_MATERIAL, !param_block->isEmpty(), true);
+
+ if (!in_use_changed)
+ {
+ // In use didn't change, but the parameter did, send an update
+ parameterChanged(LLNetworkData::PARAMS_RENDER_MATERIAL, param_block, !param_block->isEmpty(), true);
+ }
+ }
+ }
+}
+
+void LLViewerObject::setRenderMaterialIDs(const LLUUID& id)
+{
+ setRenderMaterialID(-1, id);
+}
+
+void LLViewerObject::setRenderMaterialIDs(const LLRenderMaterialParams* material_params, bool local_origin)
+{
+ if (!local_origin)
+ {
+ for (S32 te = 0; te < getNumTEs(); ++te)
+ {
+ const LLUUID& id = material_params ? material_params->getMaterial(te) : LLUUID::null;
+ setRenderMaterialID(te, id, false);
+ }
+ }
+}
+
+void LLViewerObject::shrinkWrap()
+{
+ if (!mShouldShrinkWrap)
+ {
+ mShouldShrinkWrap = true;
+ if (mDrawable)
+ { // we weren't shrink wrapped before but we are now, update the spatial partition
+ gPipeline.markPartitionMove(mDrawable);
+ }
+ }
+}
class ObjectPhysicsProperties : public LLHTTPNode
{
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index 0005cdf14e..93b17361ab 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -43,6 +43,7 @@
#include "llvertexbuffer.h"
#include "llbbox.h"
#include "llrigginginfo.h"
+#include "llreflectionmap.h"
class LLAgent; // TODO: Get rid of this.
class LLAudioSource;
@@ -178,6 +179,19 @@ public:
const std::string& getAttachmentItemName() const;
virtual LLVOAvatar* getAvatar() const; //get the avatar this object is attached to, or NULL if object is not an attachment
+
+ bool hasRenderMaterialParams() const;
+ void setHasRenderMaterialParams(bool has_params);
+
+ const LLUUID& getRenderMaterialID(U8 te) const;
+
+ // set the RenderMaterialID for the given TextureEntry
+ // te - TextureEntry index to set, or -1 for all TEs
+ // id - asset id of material asset
+ // update_server - if true, will send updates to server and clear most overrides
+ void setRenderMaterialID(S32 te, const LLUUID& id, bool update_server = true);
+ void setRenderMaterialIDs(const LLUUID& id);
+
virtual BOOL isHUDAttachment() const { return FALSE; }
virtual BOOL isTempAttachment() const;
@@ -199,6 +213,7 @@ public:
// Graphical stuff for objects - maybe broken out into render class later?
virtual void updateTextures();
+ virtual void faceMappingChanged() {}
virtual void boostTexturePriority(BOOL boost_children = TRUE); // When you just want to boost priority of this object
virtual LLDrawable* createDrawable(LLPipeline *pipeline);
@@ -210,6 +225,8 @@ public:
F32 getRotTime() { return mRotTime; }
private:
void resetRotTime();
+ void setRenderMaterialIDs(const LLRenderMaterialParams* material_params, bool local_origin);
+ void rebuildMaterial();
public:
void resetRot();
void applyAngularVelocity(F32 dt);
@@ -238,6 +255,7 @@ public:
virtual BOOL isMesh() const { return FALSE; }
virtual BOOL isRiggedMesh() const { return FALSE; }
virtual BOOL hasLightTexture() const { return FALSE; }
+ virtual BOOL isReflectionProbe() const { return FALSE; }
// This method returns true if the object is over land owned by
// the agent, one of its groups, or it encroaches and
@@ -279,6 +297,7 @@ public:
S32 face = -1, // which face to check, -1 = ALL_SIDES
BOOL pick_transparent = FALSE,
BOOL pick_rigged = FALSE,
+ BOOL pick_unselectable = TRUE,
S32* face_hit = NULL, // which face was hit
LLVector4a* intersection = NULL, // return the intersection point
LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point
@@ -318,6 +337,7 @@ public:
/*virtual*/ void setNumTEs(const U8 num_tes);
/*virtual*/ void setTE(const U8 te, const LLTextureEntry &texture_entry);
+ void updateTEMaterialTextures(U8 te);
/*virtual*/ S32 setTETexture(const U8 te, const LLUUID &uuid);
/*virtual*/ S32 setTENormalMap(const U8 te, const LLUUID &uuid);
/*virtual*/ S32 setTESpecularMap(const U8 te, const LLUUID &uuid);
@@ -342,6 +362,7 @@ public:
/*virtual*/ S32 setTEGlow(const U8 te, const F32 glow);
/*virtual*/ S32 setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID);
/*virtual*/ S32 setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams);
+ virtual S32 setTEGLTFMaterialOverride(U8 te, LLGLTFMaterial* mat);
// Used by Materials update functions to properly kick off rebuilds
// of VBs etc when materials updates require changes.
@@ -356,7 +377,7 @@ public:
LLViewerTexture *getTEImage(const U8 te) const;
LLViewerTexture *getTENormalMap(const U8 te) const;
LLViewerTexture *getTESpecularMap(const U8 te) const;
-
+
bool isImageAlphaBlended(const U8 te) const;
void fitFaceTexture(const U8 face);
@@ -420,8 +441,6 @@ public:
void sendMaterialUpdate() const;
- void setCanSelect(BOOL canSelect);
-
void setDebugText(const std::string &utf8text);
void initHudText();
void restoreHudText();
@@ -472,7 +491,7 @@ public:
// manager until we have better iterators.
void updateInventory(LLViewerInventoryItem* item, U8 key, bool is_new);
void updateInventoryLocal(LLInventoryItem* item, U8 key); // Update without messaging.
- void updateTextureInventory(LLViewerInventoryItem* item, U8 key, bool is_new);
+ void updateMaterialInventory(LLViewerInventoryItem* item, U8 key, bool is_new);
LLInventoryObject* getInventoryObject(const LLUUID& item_id);
// Get content except for root category
@@ -481,8 +500,6 @@ public:
LLViewerInventoryItem* getInventoryItemByAsset(const LLUUID& asset_id);
S16 getInventorySerial() const { return mInventorySerialNum; }
- bool isTextureInInventory(LLViewerInventoryItem* item);
-
// These functions does viewer-side only object inventory modifications
void updateViewerInventoryAsset(
const LLViewerInventoryItem* item,
@@ -586,6 +603,14 @@ public:
virtual void parameterChanged(U16 param_type, bool local_origin);
virtual void parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_use, bool local_origin);
+ bool isShrinkWrapped() const { return mShouldShrinkWrap; }
+
+ // Used to improve performance. If an object is likely to rebuild its vertex buffer often
+ // as a side effect of some update (color update, scale, etc), setting this to true
+ // will cause it to be pushed deeper into the octree and isolate it from other nodes
+ // so that nearby objects won't attempt to share a vertex buffer with this object.
+ void shrinkWrap();
+
friend class LLViewerObjectList;
friend class LLViewerMediaList;
@@ -611,6 +636,8 @@ public:
std::vector<LLVector3> mUnselectedChildrenPositions ;
private:
+ bool isAssetInInventory(LLViewerInventoryItem* item);
+
ExtraParameter* createNewParameterEntry(U16 param_type);
ExtraParameter* getExtraParameterEntry(U16 param_type) const;
ExtraParameter* getExtraParameterEntryCreate(U16 param_type);
@@ -674,10 +701,10 @@ public:
LLPointer<LLViewerTexture> *mTEImages;
LLPointer<LLViewerTexture> *mTENormalMaps;
LLPointer<LLViewerTexture> *mTESpecularMaps;
-
- // Selection, picking and rendering variables
- U32 mGLName; // GL "name" used by selection code
- BOOL mbCanSelect; // true if user can select this object by clicking
+
+ // true if user can select this object by clicking under any circumstances (even if pick_unselectable is true)
+ // can likely be factored out
+ BOOL mbCanSelect;
private:
// Grabbed from UPDATE_FLAGS
@@ -847,6 +874,9 @@ protected:
F32 mLinksetCost;
F32 mPhysicsCost;
F32 mLinksetPhysicsCost;
+
+ // If true, "shrink wrap" this volume in its spatial partition. See "shrinkWrap"
+ bool mShouldShrinkWrap = false;
bool mCostStale;
mutable bool mPhysicsShapeUnknown;
@@ -906,6 +936,11 @@ private:
LLUUID mAttachmentItemID; // ItemID of the associated object is in user inventory.
EObjectUpdateType mLastUpdateType;
BOOL mLastUpdateCached;
+
+public:
+ // reflection probe state
+ bool mIsReflectionProbe = false; // if true, this object should register itself with LLReflectionProbeManager
+ LLPointer<LLReflectionMap> mReflectionProbe = nullptr; // reflection probe coupled to this viewer object. If not null, should be deregistered when this object is destroyed
};
///////////////////
@@ -955,7 +990,7 @@ public:
LLStrider<LLColor4U>& emissivep,
LLStrider<U16>& indicesp) = 0;
- virtual void getBlendFunc(S32 face, U32& src, U32& dst);
+ virtual void getBlendFunc(S32 face, LLRender::eBlendFactor& src, LLRender::eBlendFactor& dst);
F32 mDepth;
};
diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp
index e930b58111..816fa6607e 100644
--- a/indra/newview/llviewerobjectlist.cpp
+++ b/indra/newview/llviewerobjectlist.cpp
@@ -789,7 +789,33 @@ void LLViewerObjectList::updateApparentAngles(LLAgent &agent)
max_value = llmin((S32) mObjects.size(), mCurLazyUpdateIndex + num_updates);
}
+ // Iterate through some of the objects and lazy update their texture priorities
+ for (i = mCurLazyUpdateIndex; i < max_value; i++)
+ {
+ objectp = mObjects[i];
+ if (!objectp->isDead())
+ {
+ num_objects++;
+
+ // Update distance & gpw
+ objectp->setPixelAreaAndAngle(agent); // Also sets the approx. pixel area
+ objectp->updateTextures(); // Update the image levels of textures for this object.
+ }
+ }
+
+ mCurLazyUpdateIndex = max_value;
+ if (mCurLazyUpdateIndex == mObjects.size())
+ {
+ // restart
+ mCurLazyUpdateIndex = 0;
+ mCurBin = 0; // keep in sync with index (mObjects.size() could have changed)
+ }
+ else
+ {
+ mCurBin = (mCurBin + 1) % NUM_BINS;
+ }
+#if 1
// Slam priorities for textures that we care about (hovered, selected, and focused)
// Hovered
// Assumes only one level deep of parenting
@@ -820,32 +846,7 @@ void LLViewerObjectList::updateApparentAngles(LLAgent &agent)
}
} func;
LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func);
-
- // Iterate through some of the objects and lazy update their texture priorities
- for (i = mCurLazyUpdateIndex; i < max_value; i++)
- {
- objectp = mObjects[i];
- if (!objectp->isDead())
- {
- num_objects++;
-
- // Update distance & gpw
- objectp->setPixelAreaAndAngle(agent); // Also sets the approx. pixel area
- objectp->updateTextures(); // Update the image levels of textures for this object.
- }
- }
-
- mCurLazyUpdateIndex = max_value;
- if (mCurLazyUpdateIndex == mObjects.size())
- {
- // restart
- mCurLazyUpdateIndex = 0;
- mCurBin = 0; // keep in sync with index (mObjects.size() could have changed)
- }
- else
- {
- mCurBin = (mCurBin + 1) % NUM_BINS;
- }
+#endif
LLVOAvatar::cullAvatarsByPixelArea();
}
@@ -1340,38 +1341,13 @@ void LLViewerObjectList::cleanupReferences(LLViewerObject *objectp)
}
// Don't clean up mObject references, these will be cleaned up more efficiently later!
- // Also, not cleaned up
- removeDrawable(objectp->mDrawable);
-
+
if(new_dead_object)
{
mNumDeadObjects++;
}
}
-void LLViewerObjectList::removeDrawable(LLDrawable* drawablep)
-{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWABLE;
-
- if (!drawablep)
- {
- return;
- }
-
- for (S32 i = 0; i < drawablep->getNumFaces(); i++)
- {
- LLFace* facep = drawablep->getFace(i) ;
- if(facep)
- {
- LLViewerObject* objectp = facep->getViewerObject();
- if(objectp)
- {
- mSelectPickList.erase(objectp);
- }
- }
- }
-}
-
BOOL LLViewerObjectList::killObject(LLViewerObject *objectp)
{
// Don't ever kill gAgentAvatarp, just force it to the agent's region
@@ -1837,145 +1813,7 @@ void LLViewerObjectList::renderObjectBounds(const LLVector3 &center)
{
}
-void LLViewerObjectList::generatePickList(LLCamera &camera)
-{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
-
- LLViewerObject *objectp;
- S32 i;
- // Reset all of the GL names to zero.
- for (vobj_list_t::iterator iter = mObjects.begin(); iter != mObjects.end(); ++iter)
- {
- (*iter)->mGLName = 0;
- }
-
- mSelectPickList.clear();
-
- std::vector<LLDrawable*> pick_drawables;
-
- for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
- iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
- {
- LLViewerRegion* region = *iter;
- for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
- {
- LLSpatialPartition* part = region->getSpatialPartition(i);
- if (part)
- {
- part->cull(camera, &pick_drawables, TRUE);
- }
- }
- }
-
- for (std::vector<LLDrawable*>::iterator iter = pick_drawables.begin();
- iter != pick_drawables.end(); iter++)
- {
- LLDrawable* drawablep = *iter;
- if( !drawablep )
- continue;
-
- LLViewerObject* last_objectp = NULL;
- for (S32 face_num = 0; face_num < drawablep->getNumFaces(); face_num++)
- {
- LLFace * facep = drawablep->getFace(face_num);
- if (!facep) continue;
-
- LLViewerObject* objectp = facep->getViewerObject();
-
- if (objectp && objectp != last_objectp)
- {
- mSelectPickList.insert(objectp);
- last_objectp = objectp;
- }
- }
- }
-
- LLHUDNameTag::addPickable(mSelectPickList);
-
- for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
- iter != LLCharacter::sInstances.end(); ++iter)
- {
- objectp = (LLVOAvatar*) *iter;
- if (!objectp->isDead())
- {
- if (objectp->mDrawable.notNull() && objectp->mDrawable->isVisible())
- {
- mSelectPickList.insert(objectp);
- }
- }
- }
-
- // add all hud objects to pick list
- if (isAgentAvatarValid())
- {
- for (LLVOAvatar::attachment_map_t::iterator iter = gAgentAvatarp->mAttachmentPoints.begin();
- iter != gAgentAvatarp->mAttachmentPoints.end(); )
- {
- LLVOAvatar::attachment_map_t::iterator curiter = iter++;
- LLViewerJointAttachment* attachment = curiter->second;
- if (attachment->getIsHUDAttachment())
- {
- for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
- attachment_iter != attachment->mAttachedObjects.end();
- ++attachment_iter)
- {
- if (LLViewerObject* attached_object = attachment_iter->get())
- {
- mSelectPickList.insert(attached_object);
- LLViewerObject::const_child_list_t& child_list = attached_object->getChildren();
- for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
- iter != child_list.end(); iter++)
- {
- LLViewerObject* childp = *iter;
- if (childp)
- {
- mSelectPickList.insert(childp);
- }
- }
- }
- }
- }
- }
- }
-
- S32 num_pickables = (S32)mSelectPickList.size() + LLHUDIcon::getNumInstances();
-
- if (num_pickables != 0)
- {
- S32 step = (0x000fffff - GL_NAME_INDEX_OFFSET) / num_pickables;
-
- std::set<LLViewerObject*>::iterator pick_it;
- i = 0;
- for (pick_it = mSelectPickList.begin(); pick_it != mSelectPickList.end();)
- {
- LLViewerObject* objp = (*pick_it);
- if (!objp || objp->isDead() || !objp->mbCanSelect)
- {
- mSelectPickList.erase(pick_it++);
- continue;
- }
-
- objp->mGLName = (i * step) + GL_NAME_INDEX_OFFSET;
- i++;
- ++pick_it;
- }
-
- LLHUDIcon::generatePickIDs(i * step, step);
- }
-}
-
-LLViewerObject *LLViewerObjectList::getSelectedObject(const U32 object_id)
-{
- std::set<LLViewerObject*>::iterator pick_it;
- for (pick_it = mSelectPickList.begin(); pick_it != mSelectPickList.end(); ++pick_it)
- {
- if ((*pick_it)->mGLName == object_id)
- {
- return (*pick_it);
- }
- }
- return NULL;
-}
+extern BOOL gCubeSnapshot;
void LLViewerObjectList::addDebugBeacon(const LLVector3 &pos_agent,
const std::string &string,
@@ -1983,6 +1821,7 @@ void LLViewerObjectList::addDebugBeacon(const LLVector3 &pos_agent,
const LLColor4 &text_color,
S32 line_width)
{
+ llassert(!gCubeSnapshot);
LLDebugBeacon beacon;
beacon.mPositionAgent = pos_agent;
beacon.mString = string;
diff --git a/indra/newview/llviewerobjectlist.h b/indra/newview/llviewerobjectlist.h
index 72b2b99004..f2cba8c259 100644
--- a/indra/newview/llviewerobjectlist.h
+++ b/indra/newview/llviewerobjectlist.h
@@ -77,7 +77,6 @@ public:
BOOL killObject(LLViewerObject *objectp);
void killObjects(LLViewerRegion *regionp); // Kill all objects owned by a particular region.
void killAllObjects();
- void removeDrawable(LLDrawable* drawablep);
void cleanDeadObjects(const BOOL use_timer = TRUE); // Clean up the dead object list.
@@ -129,11 +128,6 @@ public:
void updateAvatarVisibility();
- // Selection related stuff
- void generatePickList(LLCamera &camera);
-
- LLViewerObject *getSelectedObject(const U32 object_id);
-
inline S32 getNumObjects() { return (S32) mObjects.size(); }
inline S32 getNumActiveObjects() { return (S32) mActiveObjects.size(); }
@@ -226,8 +220,6 @@ protected:
static std::map<U64, LLUUID> sIndexAndLocalIDToUUID;
- std::set<LLViewerObject *> mSelectPickList;
-
friend class LLViewerObject;
private:
diff --git a/indra/newview/llvieweroctree.cpp b/indra/newview/llvieweroctree.cpp
index 36b2bd4c32..7d6c18ae67 100644
--- a/indra/newview/llvieweroctree.cpp
+++ b/indra/newview/llvieweroctree.cpp
@@ -103,11 +103,11 @@ U8* get_box_fan_indices_ptr(LLCamera* camera, const LLVector4a& center)
}
//create a vertex buffer for efficiently rendering cubes
-LLVertexBuffer* ll_create_cube_vb(U32 type_mask, U32 usage)
+LLVertexBuffer* ll_create_cube_vb(U32 type_mask)
{
- LLVertexBuffer* ret = new LLVertexBuffer(type_mask, usage);
+ LLVertexBuffer* ret = new LLVertexBuffer(type_mask);
- ret->allocateBuffer(8, 64, true);
+ ret->allocateBuffer(8, 64);
LLStrider<LLVector3> pos;
LLStrider<U16> idx;
@@ -129,7 +129,7 @@ LLVertexBuffer* ll_create_cube_vb(U32 type_mask, U32 usage)
idx[i] = sOcclusionIndices[i];
}
- ret->flush();
+ ret->unmapBuffer();
return ret;
}
@@ -800,7 +800,7 @@ U32 LLOcclusionCullingGroup::getNewOcclusionQueryObjectName()
{
//seed 1024 query names into the free query pool
GLuint queries[1024];
- glGenQueriesARB(1024, queries);
+ glGenQueries(1024, queries);
for (int i = 0; i < 1024; ++i)
{
sFreeQueries.push(queries[i]);
@@ -917,15 +917,12 @@ void LLOcclusionCullingGroup::handleChildAddition(const OctreeNode* parent, Octr
void LLOcclusionCullingGroup::releaseOcclusionQueryObjectNames()
{
- if (gGLManager.mHasOcclusionQuery)
+ for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; ++i)
{
- for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; ++i)
+ if (mOcclusionQuery[i])
{
- if (mOcclusionQuery[i])
- {
- releaseOcclusionQueryObjectName(mOcclusionQuery[i]);
- mOcclusionQuery[i] = 0;
- }
+ releaseOcclusionQueryObjectName(mOcclusionQuery[i]);
+ mOcclusionQuery[i] = 0;
}
}
}
@@ -1129,7 +1126,7 @@ void LLOcclusionCullingGroup::checkOcclusion()
GLuint available;
{
LL_PROFILE_ZONE_NAMED_CATEGORY_OCTREE("co - query available");
- glGetQueryObjectuivARB(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_AVAILABLE_ARB, &available);
+ glGetQueryObjectuiv(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_AVAILABLE, &available);
}
if (available)
@@ -1137,7 +1134,7 @@ void LLOcclusionCullingGroup::checkOcclusion()
GLuint query_result; // Will be # samples drawn, or a boolean depending on mHasOcclusionQuery2 (both are type GLuint)
{
LL_PROFILE_ZONE_NAMED_CATEGORY_OCTREE("co - query result");
- glGetQueryObjectuivARB(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_ARB, &query_result);
+ glGetQueryObjectuiv(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT, &query_result);
}
#if LL_TRACK_PENDING_OCCLUSION_QUERIES
sPendingQueries.erase(mOcclusionQuery[LLViewerCamera::sCurCameraID]);
@@ -1172,7 +1169,7 @@ void LLOcclusionCullingGroup::checkOcclusion()
else if (mSpatialPartition->isOcclusionEnabled() && isOcclusionState(LLOcclusionCullingGroup::OCCLUDED))
{ //check occlusion has been issued for occluded node that has not had a query issued
assert_states_valid(this);
- clearOcclusionState(LLOcclusionCullingGroup::OCCLUDED, LLOcclusionCullingGroup::STATE_MODE_DIFF);
+ //clearOcclusionState(LLOcclusionCullingGroup::OCCLUDED, LLOcclusionCullingGroup::STATE_MODE_DIFF);
assert_states_valid(this);
}
}
@@ -1197,7 +1194,6 @@ void LLOcclusionCullingGroup::doOcclusion(LLCamera* camera, const LLVector4a* sh
OCCLUSION_FUDGE_Z = 1.;
}
- // Don't cull hole/edge water, unless we have the GL_ARB_depth_clamp extension
if (earlyFail(camera, bounds))
{
LL_PROFILE_ZONE_NAMED_CATEGORY_OCTREE("doOcclusion - early fail");
@@ -1221,17 +1217,12 @@ void LLOcclusionCullingGroup::doOcclusion(LLCamera* camera, const LLVector4a* sh
// Depth clamp all water to avoid it being culled as a result of being
// behind the far clip plane, and in the case of edge water to avoid
// it being culled while still visible.
- bool const use_depth_clamp = gGLManager.mHasDepthClamp &&
- (mSpatialPartition->mDrawableType == LLPipeline::RENDER_TYPE_WATER ||
+ bool const use_depth_clamp = (mSpatialPartition->mDrawableType == LLPipeline::RENDER_TYPE_WATER ||
mSpatialPartition->mDrawableType == LLPipeline::RENDER_TYPE_VOIDWATER);
- LLGLEnable clamp(use_depth_clamp ? GL_DEPTH_CLAMP : 0);
+ LLGLEnable clamp(use_depth_clamp ? GL_DEPTH_CLAMP : 0);
-#if !LL_DARWIN
- U32 mode = gGLManager.mHasOcclusionQuery2 ? GL_ANY_SAMPLES_PASSED : GL_SAMPLES_PASSED_ARB;
-#else
- U32 mode = GL_SAMPLES_PASSED_ARB;
-#endif
+ U32 mode = gGLManager.mGLVersion >= 3.3f ? GL_ANY_SAMPLES_PASSED : GL_SAMPLES_PASSED;
#if LL_TRACK_PENDING_OCCLUSION_QUERIES
sPendingQueries.insert(mOcclusionQuery[LLViewerCamera::sCurCameraID]);
@@ -1250,7 +1241,7 @@ void LLOcclusionCullingGroup::doOcclusion(LLCamera* camera, const LLVector4a* sh
//get an occlusion query that hasn't been used in awhile
releaseOcclusionQueryObjectName(mOcclusionQuery[LLViewerCamera::sCurCameraID]);
mOcclusionQuery[LLViewerCamera::sCurCameraID] = getNewOcclusionQueryObjectName();
- glBeginQueryARB(mode, mOcclusionQuery[LLViewerCamera::sCurCameraID]);
+ glBeginQuery(mode, mOcclusionQuery[LLViewerCamera::sCurCameraID]);
}
LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
@@ -1292,7 +1283,7 @@ void LLOcclusionCullingGroup::doOcclusion(LLCamera* camera, const LLVector4a* sh
{
LL_PROFILE_ZONE_NAMED("glEndQuery");
- glEndQueryARB(mode);
+ glEndQuery(mode);
}
}
}
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index ad7321ca4b..e3ac1767fb 100755
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -53,6 +53,7 @@
#include "llfloatergodtools.h"
#include "llfloaterreporter.h"
#include "llfloaterregioninfo.h"
+#include "llgltfmateriallist.h"
#include "llhttpnode.h"
#include "llregioninfomodel.h"
#include "llsdutil.h"
@@ -214,6 +215,7 @@ public:
LLVOCacheEntry::vocache_entry_set_t mVisibleEntries; //must-be-created visible entries wait for objects creation.
LLVOCacheEntry::vocache_entry_priority_list_t mWaitingList; //transient list storing sorted visible entries waiting for object creation.
std::set<U32> mNonCacheableCreatedList; //list of local ids of all non-cacheable objects
+ LLVOCacheEntry::vocache_gltf_overrides_map_t mGLTFOverridesJson; // for materials
// time?
// LRU info?
@@ -782,7 +784,10 @@ void LLViewerRegion::loadObjectCache()
if(LLVOCache::instanceExists())
{
- LLVOCache::getInstance()->readFromCache(mHandle, mImpl->mCacheID, mImpl->mCacheMap) ;
+ LLVOCache & vocache = LLVOCache::instance();
+ vocache.readFromCache(mHandle, mImpl->mCacheID, mImpl->mCacheMap) ;
+ vocache.readGenericExtrasFromCache(mHandle, mImpl->mCacheID, mImpl->mGLTFOverridesJson);
+
if (mImpl->mCacheMap.empty())
{
mCacheDirty = TRUE;
@@ -807,8 +812,10 @@ void LLViewerRegion::saveObjectCache()
{
const F32 start_time_threshold = 600.0f; //seconds
bool removal_enabled = sVOCacheCullingEnabled && (mRegionTimer.getElapsedTimeF32() > start_time_threshold); //allow to remove invalid objects from object cache file.
-
- LLVOCache::getInstance()->writeToCache(mHandle, mImpl->mCacheID, mImpl->mCacheMap, mCacheDirty, removal_enabled) ;
+
+ LLVOCache & instance = LLVOCache::instance();
+ instance.writeToCache(mHandle, mImpl->mCacheID, mImpl->mCacheMap, mCacheDirty, removal_enabled) ;
+ instance.writeGenericExtrasToCache(mHandle, mImpl->mCacheID, mImpl->mGLTFOverridesJson, mCacheDirty, removal_enabled);
mCacheDirty = FALSE;
}
@@ -1242,6 +1249,47 @@ U32 LLViewerRegion::getNumOfVisibleGroups() const
return mImpl ? mImpl->mVisibleGroups.size() : 0;
}
+void LLViewerRegion::updateReflectionProbes()
+{
+#if 1
+ const F32 probe_spacing = 32.f;
+ const F32 probe_radius = sqrtf((probe_spacing * 0.5f) * (probe_spacing * 0.5f) * 3.f);
+ const F32 hover_height = 2.f;
+
+ F32 start = probe_spacing * 0.5f;
+
+ U32 grid_width = REGION_WIDTH_METERS / probe_spacing;
+
+ mReflectionMaps.resize(grid_width * grid_width);
+
+ F32 water_height = getWaterHeight();
+ LLVector3 origin = getOriginAgent();
+
+ for (U32 i = 0; i < grid_width; ++i)
+ {
+ F32 x = i * probe_spacing + start;
+ for (U32 j = 0; j < grid_width; ++j)
+ {
+ F32 y = j * probe_spacing + start;
+
+ U32 idx = i * grid_width + j;
+
+ if (mReflectionMaps[idx].isNull())
+ {
+ mReflectionMaps[idx] = gPipeline.mReflectionMapManager.addProbe();
+ }
+
+ LLVector3 probe_origin = LLVector3(x,y, llmax(water_height, mImpl->mLandp->resolveHeightRegion(x,y)));
+ probe_origin.mV[2] += hover_height;
+ probe_origin += origin;
+
+ mReflectionMaps[idx]->mOrigin.load3(probe_origin.mV);
+ mReflectionMaps[idx]->mRadius = probe_radius;
+ }
+ }
+#endif
+}
+
void LLViewerRegion::addToVOCacheTree(LLVOCacheEntry* entry)
{
if(!sVOCacheCullingEnabled)
@@ -1782,7 +1830,7 @@ LLViewerObject* LLViewerRegion::addNewObject(LLVOCacheEntry* entry)
LLViewerObject* obj = NULL;
if(!entry->getEntry()->hasDrawable()) //not added to the rendering pipeline yet
- {
+ {
//add the object
obj = gObjectList.processObjectUpdateFromCache(entry, this);
if(obj)
@@ -2557,7 +2605,7 @@ LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLDataPackerB
LL_DEBUGS("AnimatedObjects") << " got update for local_id " << local_id << LL_ENDL;
dumpStack("AnimatedObjectsStack");
- // Update the cache entry
+ // Update the cache entry
entry->updateEntry(crc, dp);
decodeBoundingInfo(entry);
@@ -2574,7 +2622,7 @@ LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLDataPackerB
// Create new entry and add to map
result = CACHE_UPDATE_ADDED;
entry = new LLVOCacheEntry(local_id, crc, dp);
- record(LLStatViewer::OBJECT_CACHE_HIT_RATE, LLUnits::Ratio::fromValue(0));
+ record(LLStatViewer::OBJECT_CACHE_HIT_RATE, LLUnits::Ratio::fromValue(0));
mImpl->mCacheMap[local_id] = entry;
@@ -2592,6 +2640,22 @@ LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLViewerObjec
return result;
}
+void LLViewerRegion::cacheFullUpdateGLTFOverride(const LLGLTFOverrideCacheEntry &override_data)
+{
+ LLUUID object_id = override_data.mObjectId;
+ LLViewerObject * obj = gObjectList.findObject(object_id);
+ if (obj != nullptr)
+ {
+ U32 local_id = obj->getLocalID();
+
+ mImpl->mGLTFOverridesJson[local_id] = override_data;
+ }
+ else
+ {
+ LL_WARNS("GLTF") << "got material override for unknown object_id, cannot cache it" << LL_ENDL;
+ }
+}
+
LLVOCacheEntry* LLViewerRegion::getCacheEntryForOctree(U32 local_id)
{
if(!sVOCacheCullingEnabled)
@@ -2616,7 +2680,7 @@ LLVOCacheEntry* LLViewerRegion::getCacheEntry(U32 local_id, bool valid)
}
}
return NULL;
- }
+}
void LLViewerRegion::addCacheMiss(U32 id, LLViewerRegion::eCacheMissType miss_type)
{
@@ -2690,6 +2754,9 @@ bool LLViewerRegion::probeCache(U32 local_id, U32 crc, U32 flags, U8 &cache_miss
entry->setValid();
decodeBoundingInfo(entry);
+
+ loadCacheMiscExtras(local_id, entry, crc);
+
return true;
}
else
@@ -3050,6 +3117,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
capabilityNames.append("MapLayer");
capabilityNames.append("MapLayerGod");
capabilityNames.append("MeshUploadFlag");
+ capabilityNames.append("ModifyMaterialParams");
capabilityNames.append("NavMeshGenerationStatus");
capabilityNames.append("NewFileAgentInventory");
capabilityNames.append("ObjectAnimation");
@@ -3092,6 +3160,8 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
capabilityNames.append("UpdateSettingsAgentInventory");
capabilityNames.append("UpdateSettingsTaskInventory");
capabilityNames.append("UploadAgentProfileImage");
+ capabilityNames.append("UpdateMaterialAgentInventory");
+ capabilityNames.append("UpdateMaterialTaskInventory");
capabilityNames.append("UploadBakedTexture");
capabilityNames.append("UserInfo");
capabilityNames.append("ViewerAsset");
@@ -3470,3 +3540,11 @@ std::string LLViewerRegion::getSimHostName()
return std::string("...");
}
+void LLViewerRegion::loadCacheMiscExtras(U32 local_id, LLVOCacheEntry * entry, U32 crc)
+{
+ auto iter = mImpl->mGLTFOverridesJson.find(local_id);
+ if (iter != mImpl->mGLTFOverridesJson.end())
+ {
+ LLGLTFMaterialList::loadCacheOverrides(iter->second);
+ }
+}
diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h
index 6548e8d372..ec507fb982 100644
--- a/indra/newview/llviewerregion.h
+++ b/indra/newview/llviewerregion.h
@@ -41,6 +41,7 @@
#include "llcapabilityprovider.h"
#include "m4math.h" // LLMatrix4
#include "llframetimer.h"
+#include "llreflectionmap.h"
// Surface id's
#define LAND 1
@@ -67,6 +68,7 @@ class LLHost;
class LLBBox;
class LLSpatialGroup;
class LLDrawable;
+class LLGLTFOverrideCacheEntry;
class LLViewerRegionImpl;
class LLViewerOctreeGroup;
class LLVOCachePartition;
@@ -347,7 +349,10 @@ public:
// handle a full update message
eCacheUpdateResult cacheFullUpdate(LLDataPackerBinaryBuffer &dp, U32 flags);
- eCacheUpdateResult cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp, U32 flags);
+ eCacheUpdateResult cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp, U32 flags);
+
+ void cacheFullUpdateGLTFOverride(const LLGLTFOverrideCacheEntry &override_data);
+
LLVOCacheEntry* getCacheEntryForOctree(U32 local_id);
LLVOCacheEntry* getCacheEntry(U32 local_id, bool valid = true);
bool probeCache(U32 local_id, U32 crc, U32 flags, U8 &cache_miss_type);
@@ -401,6 +406,9 @@ public:
static BOOL isNewObjectCreationThrottleDisabled() {return sNewObjectCreationThrottle < 0;}
+ // rebuild reflection probe list
+ void updateReflectionProbes();
+
private:
void addToVOCacheTree(LLVOCacheEntry* entry);
LLViewerObject* addNewObject(LLVOCacheEntry* entry);
@@ -415,6 +423,8 @@ private:
void decodeBoundingInfo(LLVOCacheEntry* entry);
bool isNonCacheableObjectCreated(U32 local_id);
+ void loadCacheMiscExtras(U32 local_id, LLVOCacheEntry * entry, U32 crc);
+
public:
struct CompareDistance
{
@@ -574,6 +584,10 @@ private:
LLFrameTimer mMaterialsCapThrottleTimer;
LLFrameTimer mRenderInfoRequestTimer;
LLFrameTimer mRenderInfoReportTimer;
+
+ // list of reflection maps being managed by this llviewer region
+ std::vector<LLPointer<LLReflectionMap> > mReflectionMaps;
+
};
inline BOOL LLViewerRegion::getRegionProtocol(U64 protocol) const
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index 1c9360a843..90b06fa133 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -49,6 +49,8 @@
#include "lljoint.h"
#include "llskinningutil.h"
+//#pragma optimize("", off)
+
static LLStaticHashedString sTexture0("texture0");
static LLStaticHashedString sTexture1("texture1");
static LLStaticHashedString sTex0("tex0");
@@ -68,20 +70,16 @@ bool LLViewerShaderMgr::sSkipReload = false;
LLVector4 gShinyOrigin;
-//transform shaders
-LLGLSLShader gTransformPositionProgram;
-LLGLSLShader gTransformTexCoordProgram;
-LLGLSLShader gTransformNormalProgram;
-LLGLSLShader gTransformColorProgram;
-LLGLSLShader gTransformTangentProgram;
-
//utility shaders
LLGLSLShader gOcclusionProgram;
LLGLSLShader gSkinnedOcclusionProgram;
LLGLSLShader gOcclusionCubeProgram;
-LLGLSLShader gCustomAlphaProgram;
+LLGLSLShader gCustomAlphaProgram; // SL-14113 This used to be used for the stars with Atmospheric Shaders: OFF
LLGLSLShader gGlowCombineProgram;
LLGLSLShader gSplatTextureRectProgram;
+LLGLSLShader gReflectionMipProgram;
+LLGLSLShader gRadianceGenProgram;
+LLGLSLShader gIrradianceGenProgram;
LLGLSLShader gGlowCombineFXAAProgram;
LLGLSLShader gTwoTextureAddProgram;
LLGLSLShader gTwoTextureCompareProgram;
@@ -94,7 +92,9 @@ LLGLSLShader gDownsampleDepthProgram;
LLGLSLShader gDownsampleDepthRectProgram;
LLGLSLShader gAlphaMaskProgram;
LLGLSLShader gBenchmarkProgram;
-
+LLGLSLShader gReflectionProbeDisplayProgram;
+LLGLSLShader gCopyProgram;
+LLGLSLShader gCopyDepthProgram;
//object shaders
LLGLSLShader gObjectSimpleProgram;
@@ -144,6 +144,8 @@ LLGLSLShader gObjectAlphaMaskNoColorProgram;
LLGLSLShader gObjectAlphaMaskNoColorWaterProgram;
//environment shaders
+LLGLSLShader gMoonProgram;
+LLGLSLShader gStarsProgram;
LLGLSLShader gTerrainProgram;
LLGLSLShader gTerrainWaterProgram;
LLGLSLShader gWaterProgram;
@@ -180,7 +182,8 @@ LLGLSLShader gWLMoonProgram;
LLGLSLShader gGlowProgram;
LLGLSLShader gGlowExtractProgram;
LLGLSLShader gPostColorFilterProgram;
-LLGLSLShader gPostNightVisionProgram;
+LLGLSLShader gPostNightVisionProgram;
+LLGLSLShader gPostScreenSpaceReflectionProgram;
// Deferred rendering shaders
LLGLSLShader gDeferredImpostorProgram;
@@ -189,7 +192,6 @@ LLGLSLShader gDeferredUnderWaterProgram;
LLGLSLShader gDeferredDiffuseProgram;
LLGLSLShader gDeferredDiffuseAlphaMaskProgram;
LLGLSLShader gDeferredSkinnedDiffuseAlphaMaskProgram;
-LLGLSLShader gDeferredNonIndexedDiffuseProgram;
LLGLSLShader gDeferredNonIndexedDiffuseAlphaMaskProgram;
LLGLSLShader gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram;
LLGLSLShader gDeferredSkinnedDiffuseProgram;
@@ -214,15 +216,13 @@ LLGLSLShader gDeferredShadowProgram;
LLGLSLShader gDeferredSkinnedShadowProgram;
LLGLSLShader gDeferredShadowCubeProgram;
LLGLSLShader gDeferredShadowAlphaMaskProgram;
+LLGLSLShader gDeferredShadowGLTFAlphaMaskProgram;
LLGLSLShader gDeferredSkinnedShadowAlphaMaskProgram;
LLGLSLShader gDeferredShadowFullbrightAlphaMaskProgram;
LLGLSLShader gDeferredSkinnedShadowFullbrightAlphaMaskProgram;
LLGLSLShader gDeferredAvatarShadowProgram;
LLGLSLShader gDeferredAvatarAlphaShadowProgram;
LLGLSLShader gDeferredAvatarAlphaMaskShadowProgram;
-LLGLSLShader gDeferredAttachmentShadowProgram;
-LLGLSLShader gDeferredAttachmentAlphaShadowProgram;
-LLGLSLShader gDeferredAttachmentAlphaMaskShadowProgram;
LLGLSLShader gDeferredAlphaProgram;
LLGLSLShader gDeferredSkinnedAlphaProgram;
LLGLSLShader gDeferredAlphaImpostorProgram;
@@ -232,8 +232,11 @@ LLGLSLShader gDeferredSkinnedAlphaWaterProgram;
LLGLSLShader gDeferredAvatarEyesProgram;
LLGLSLShader gDeferredFullbrightProgram;
LLGLSLShader gDeferredFullbrightAlphaMaskProgram;
+LLGLSLShader gDeferredFullbrightAlphaMaskAlphaProgram;
LLGLSLShader gDeferredFullbrightWaterProgram;
LLGLSLShader gDeferredSkinnedFullbrightWaterProgram;
+LLGLSLShader gDeferredFullbrightWaterAlphaProgram;
+LLGLSLShader gDeferredSkinnedFullbrightWaterAlphaProgram;
LLGLSLShader gDeferredFullbrightAlphaMaskWaterProgram;
LLGLSLShader gDeferredSkinnedFullbrightAlphaMaskWaterProgram;
LLGLSLShader gDeferredEmissiveProgram;
@@ -253,11 +256,17 @@ LLGLSLShader gDeferredFullbrightShinyProgram;
LLGLSLShader gDeferredSkinnedFullbrightShinyProgram;
LLGLSLShader gDeferredSkinnedFullbrightProgram;
LLGLSLShader gDeferredSkinnedFullbrightAlphaMaskProgram;
+LLGLSLShader gDeferredSkinnedFullbrightAlphaMaskAlphaProgram;
LLGLSLShader gNormalMapGenProgram;
+LLGLSLShader gDeferredGenBrdfLutProgram;
// Deferred materials shaders
LLGLSLShader gDeferredMaterialProgram[LLMaterial::SHADER_COUNT*2];
LLGLSLShader gDeferredMaterialWaterProgram[LLMaterial::SHADER_COUNT*2];
+LLGLSLShader gDeferredPBROpaqueProgram;
+LLGLSLShader gDeferredSkinnedPBROpaqueProgram;
+LLGLSLShader gDeferredPBRAlphaProgram;
+LLGLSLShader gDeferredSkinnedPBRAlphaProgram;
//helper for making a rigged variant of a given shader
bool make_rigged_variant(LLGLSLShader& shader, LLGLSLShader& riggedShader)
@@ -348,14 +357,18 @@ LLViewerShaderMgr::LLViewerShaderMgr() :
mShaderList.push_back(&gDeferredSkinnedAlphaWaterProgram);
mShaderList.push_back(&gDeferredFullbrightProgram);
mShaderList.push_back(&gDeferredFullbrightAlphaMaskProgram);
+ mShaderList.push_back(&gDeferredFullbrightAlphaMaskAlphaProgram);
mShaderList.push_back(&gDeferredFullbrightWaterProgram);
mShaderList.push_back(&gDeferredSkinnedFullbrightWaterProgram);
+ mShaderList.push_back(&gDeferredFullbrightWaterAlphaProgram);
+ mShaderList.push_back(&gDeferredSkinnedFullbrightWaterAlphaProgram);
mShaderList.push_back(&gDeferredFullbrightAlphaMaskWaterProgram);
mShaderList.push_back(&gDeferredSkinnedFullbrightAlphaMaskWaterProgram);
mShaderList.push_back(&gDeferredFullbrightShinyProgram);
mShaderList.push_back(&gDeferredSkinnedFullbrightShinyProgram);
mShaderList.push_back(&gDeferredSkinnedFullbrightProgram);
mShaderList.push_back(&gDeferredSkinnedFullbrightAlphaMaskProgram);
+ mShaderList.push_back(&gDeferredSkinnedFullbrightAlphaMaskAlphaProgram);
mShaderList.push_back(&gDeferredEmissiveProgram);
mShaderList.push_back(&gDeferredSkinnedEmissiveProgram);
mShaderList.push_back(&gDeferredAvatarEyesProgram);
@@ -366,7 +379,10 @@ LLViewerShaderMgr::LLViewerShaderMgr() :
mShaderList.push_back(&gDeferredWLSkyProgram);
mShaderList.push_back(&gDeferredWLCloudProgram);
mShaderList.push_back(&gDeferredWLMoonProgram);
- mShaderList.push_back(&gDeferredWLSunProgram);
+ mShaderList.push_back(&gDeferredWLSunProgram);
+ mShaderList.push_back(&gDeferredPBRAlphaProgram);
+ mShaderList.push_back(&gDeferredSkinnedPBRAlphaProgram);
+
}
LLViewerShaderMgr::~LLViewerShaderMgr()
@@ -418,6 +434,7 @@ S32 LLViewerShaderMgr::getShaderLevel(S32 type)
void LLViewerShaderMgr::setShaders()
{
+ LL_PROFILE_ZONE_SCOPED;
//setShaders might be called redundantly by gSavedSettings, so return on reentrance
static bool reentrance = false;
@@ -434,16 +451,9 @@ void LLViewerShaderMgr::setShaders()
}
static LLCachedControl<U32> max_texture_index(gSavedSettings, "RenderMaxTextureIndex", 16);
- LLGLSLShader::sIndexedTextureChannels = llmax(llmin(gGLManager.mNumTextureImageUnits, (S32) max_texture_index), 1);
-
- //NEVER use more than 16 texture channels (work around for prevalent driver bug)
- LLGLSLShader::sIndexedTextureChannels = llmin(LLGLSLShader::sIndexedTextureChannels, 16);
-
- if (gGLManager.mGLSLVersionMajor < 1 ||
- (gGLManager.mGLSLVersionMajor == 1 && gGLManager.mGLSLVersionMinor <= 20))
- { //NEVER use indexed texture rendering when GLSL version is 1.20 or earlier
- LLGLSLShader::sIndexedTextureChannels = 1;
- }
+
+ // when using indexed texture rendering, leave 8 texture units available for shadow and reflection maps
+ LLGLSLShader::sIndexedTextureChannels = llmax(llmin(gGLManager.mNumTextureImageUnits-8, (S32) max_texture_index), 1);
reentrance = true;
@@ -457,9 +467,7 @@ void LLViewerShaderMgr::setShaders()
initAttribsAndUniforms();
gPipeline.releaseGLBuffers();
- LLPipeline::sWaterReflections = gGLManager.mHasCubeMap && LLPipeline::sRenderTransparentWater;
LLPipeline::sRenderGlow = gSavedSettings.getBOOL("RenderGlow");
- LLPipeline::updateRenderDeferred();
//hack to reset buffers that change behavior with shaders
gPipeline.resetVertexBuffers();
@@ -486,11 +494,9 @@ void LLViewerShaderMgr::setShaders()
llassert((gGLManager.mGLSLVersionMajor > 1 || gGLManager.mGLSLVersionMinor >= 10));
- bool canRenderDeferred = LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred");
- bool hasWindLightShaders = LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders");
- S32 shadow_detail = gSavedSettings.getS32("RenderShadowDetail");
- bool doingWindLight = hasWindLightShaders && gSavedSettings.getBOOL("WindLightUseAtmosShaders");
- bool useRenderDeferred = doingWindLight && canRenderDeferred && gSavedSettings.getBOOL("RenderDeferred");
+ //bool canRenderDeferred = true; // DEPRECATED -- LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred");
+ //bool hasWindLightShaders = true; // DEPRECATED -- LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders");
+ bool doingWindLight = true; //DEPRECATED -- hasWindLightShaders&& gSavedSettings.getBOOL("WindLightUseAtmosShaders");
S32 light_class = 3;
S32 interface_class = 2;
@@ -498,35 +504,8 @@ void LLViewerShaderMgr::setShaders()
S32 obj_class = 2;
S32 effect_class = 2;
S32 wl_class = 1;
- S32 water_class = 2;
- S32 deferred_class = 0;
- S32 transform_class = gGLManager.mHasTransformFeedback ? 1 : 0;
-
- static LLCachedControl<bool> use_transform_feedback(gSavedSettings, "RenderUseTransformFeedback", false);
- if (!use_transform_feedback)
- {
- transform_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;
- }
- }
+ S32 water_class = 3;
+ S32 deferred_class = 3;
if (doingWindLight)
{
@@ -554,7 +533,6 @@ void LLViewerShaderMgr::setShaders()
mShaderLevel[SHADER_EFFECT] = effect_class;
mShaderLevel[SHADER_WINDLIGHT] = wl_class;
mShaderLevel[SHADER_DEFERRED] = deferred_class;
- mShaderLevel[SHADER_TRANSFORM] = transform_class;
std::string shader_name = loadBasicShaders();
if (shader_name.empty())
@@ -640,89 +618,31 @@ void LLViewerShaderMgr::setShaders()
}
if (loaded)
-
- {
- loaded = loadTransformShaders();
- if (loaded)
- {
- LL_INFOS() << "Loaded transform shaders." << LL_ENDL;
- }
- else
- {
- LL_WARNS() << "Failed to load transform shaders." << LL_ENDL;
- llassert(loaded);
- }
- }
-
- if (loaded)
{
// Load max avatar shaders to set the max level
mShaderLevel[SHADER_AVATAR] = 3;
mMaxAvatarShaderLevel = 3;
-
- if (loadShadersObject())
- { //hardware skinning is enabled and rigged attachment shaders loaded correctly
- BOOL avatar_cloth = gSavedSettings.getBOOL("RenderAvatarCloth");
+ if (loadShadersObject())
+ { //hardware skinning is enabled and rigged attachment shaders loaded correctly
// cloth is a class3 shader
- S32 avatar_class = avatar_cloth ? 3 : 1;
+ S32 avatar_class = 1;
// Set the actual level
mShaderLevel[SHADER_AVATAR] = avatar_class;
loaded = loadShadersAvatar();
llassert(loaded);
-
- if (mShaderLevel[SHADER_AVATAR] != avatar_class)
- {
- if(llmax(mShaderLevel[SHADER_AVATAR]-1,0) >= 3)
- {
- avatar_cloth = true;
- }
- else
- {
- avatar_cloth = false;
- }
- gSavedSettings.setBOOL("RenderAvatarCloth", avatar_cloth);
- }
}
else
{ //hardware skinning not possible, neither is deferred rendering
- mShaderLevel[SHADER_AVATAR] = 0;
- mShaderLevel[SHADER_DEFERRED] = 0;
-
- gSavedSettings.setBOOL("RenderDeferred", FALSE);
- gSavedSettings.setBOOL("RenderAvatarCloth", FALSE);
-
- loadShadersAvatar(); // unloads
-
- loaded = loadShadersObject();
- llassert(loaded);
+ llassert(false); // SHOULD NOT BE POSSIBLE
}
}
- if (!loaded)
- { //some shader absolutely could not load, try to fall back to a simpler setting
- if (gSavedSettings.getBOOL("WindLightUseAtmosShaders"))
- { //disable windlight and try again
- gSavedSettings.setBOOL("WindLightUseAtmosShaders", FALSE);
- LL_WARNS() << "Falling back to no windlight shaders." << LL_ENDL;
- reentrance = false;
- setShaders();
- return;
- }
- }
-
llassert(loaded);
-
- if (loaded && !loadShadersDeferred())
- { //everything else succeeded but deferred failed, disable deferred and try again
- gSavedSettings.setBOOL("RenderDeferred", FALSE);
- LL_WARNS() << "Falling back to no deferred shaders." << LL_ENDL;
- reentrance = false;
- setShaders();
- return;
- }
+ loaded = loaded && loadShadersDeferred();
+ llassert(loaded);
if (gViewerWindow)
{
@@ -744,6 +664,7 @@ void LLViewerShaderMgr::unloadShaders()
gDownsampleDepthProgram.unload();
gDownsampleDepthRectProgram.unload();
gBenchmarkProgram.unload();
+ gReflectionProbeDisplayProgram.unload();
gAlphaMaskProgram.unload();
gUIProgram.unload();
gPathfindingProgram.unload();
@@ -751,6 +672,9 @@ void LLViewerShaderMgr::unloadShaders()
gCustomAlphaProgram.unload();
gGlowCombineProgram.unload();
gSplatTextureRectProgram.unload();
+ gReflectionMipProgram.unload();
+ gRadianceGenProgram.unload();
+ gIrradianceGenProgram.unload();
gGlowCombineFXAAProgram.unload();
gTwoTextureAddProgram.unload();
gTwoTextureCompareProgram.unload();
@@ -809,6 +733,9 @@ void LLViewerShaderMgr::unloadShaders()
gWaterProgram.unload();
gWaterEdgeProgram.unload();
gUnderWaterProgram.unload();
+
+ gMoonProgram.unload();
+ gStarsProgram.unload();
gTerrainProgram.unload();
gTerrainWaterProgram.unload();
gGlowProgram.unload();
@@ -829,22 +756,16 @@ void LLViewerShaderMgr::unloadShaders()
gPostColorFilterProgram.unload();
gPostNightVisionProgram.unload();
+ gPostScreenSpaceReflectionProgram.unload();
gDeferredDiffuseProgram.unload();
gDeferredDiffuseAlphaMaskProgram.unload();
gDeferredSkinnedDiffuseAlphaMaskProgram.unload();
gDeferredNonIndexedDiffuseAlphaMaskProgram.unload();
gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.unload();
- gDeferredNonIndexedDiffuseProgram.unload();
gDeferredSkinnedDiffuseProgram.unload();
gDeferredSkinnedBumpProgram.unload();
- gTransformPositionProgram.unload();
- gTransformTexCoordProgram.unload();
- gTransformNormalProgram.unload();
- gTransformColorProgram.unload();
- gTransformTangentProgram.unload();
-
mShaderLevel[SHADER_LIGHTING] = 0;
mShaderLevel[SHADER_OBJECT] = 0;
mShaderLevel[SHADER_AVATAR] = 0;
@@ -853,7 +774,6 @@ void LLViewerShaderMgr::unloadShaders()
mShaderLevel[SHADER_INTERFACE] = 0;
mShaderLevel[SHADER_EFFECT] = 0;
mShaderLevel[SHADER_WINDLIGHT] = 0;
- mShaderLevel[SHADER_TRANSFORM] = 0;
gPipeline.mShadersLoaded = false;
}
@@ -907,6 +827,7 @@ std::string LLViewerShaderMgr::loadBasicShaders()
shaders.push_back( make_pair( "lighting/lightSpecularV.glsl", mShaderLevel[SHADER_LIGHTING] ) );
shaders.push_back( make_pair( "windlight/atmosphericsFuncs.glsl", mShaderLevel[SHADER_WINDLIGHT] ) );
shaders.push_back( make_pair( "windlight/atmosphericsV.glsl", mShaderLevel[SHADER_WINDLIGHT] ) );
+ shaders.push_back( make_pair( "environment/srgbF.glsl", 1 ) );
shaders.push_back( make_pair( "avatar/avatarSkinV.glsl", 1 ) );
shaders.push_back( make_pair( "avatar/objectSkinV.glsl", 1 ) );
if (gGLManager.mGLSLVersionMajor >= 2 || gGLManager.mGLSLVersionMinor >= 30)
@@ -922,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)
{
@@ -938,11 +860,28 @@ 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";
+ }
+ }
+
+ 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++)
{
- // Note usage of GL_VERTEX_SHADER_ARB
- if (loadShaderFile(shaders[i].first, shaders[i].second, GL_VERTEX_SHADER_ARB, &attribs) == 0)
+ // Note usage of GL_VERTEX_SHADER
+ if (loadShaderFile(shaders[i].first, shaders[i].second, GL_VERTEX_SHADER, &attribs) == 0)
{
LL_WARNS("Shader") << "Failed to load vertex shader " << shaders[i].first << LL_ENDL;
return shaders[i].first;
@@ -957,9 +896,11 @@ std::string LLViewerShaderMgr::loadBasicShaders()
if (gGLManager.mGLSLVersionMajor > 1 || gGLManager.mGLSLVersionMinor >= 30)
{ //use indexed texture rendering for GLSL >= 1.30
- ch = llmax(LLGLSLShader::sIndexedTextureChannels-1, 1);
+ ch = llmax(LLGLSLShader::sIndexedTextureChannels, 1);
}
+ bool has_reflection_probes = gSavedSettings.getBOOL("RenderReflectionsEnabled") && gGLManager.mGLVersion > 3.99f;
+
std::vector<S32> index_channels;
index_channels.push_back(-1); shaders.push_back( make_pair( "windlight/atmosphericsVarsF.glsl", mShaderLevel[SHADER_WINDLIGHT] ) );
index_channels.push_back(-1); shaders.push_back( make_pair( "windlight/atmosphericsVarsWaterF.glsl", mShaderLevel[SHADER_WINDLIGHT] ) );
@@ -974,6 +915,8 @@ std::string LLViewerShaderMgr::loadBasicShaders()
index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/deferredUtil.glsl", 1) );
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", 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] ) );
@@ -1001,8 +944,8 @@ std::string LLViewerShaderMgr::loadBasicShaders()
for (U32 i = 0; i < shaders.size(); i++)
{
- // Note usage of GL_FRAGMENT_SHADER_ARB
- if (loadShaderFile(shaders[i].first, shaders[i].second, GL_FRAGMENT_SHADER_ARB, &attribs, index_channels[i]) == 0)
+ // Note usage of GL_FRAGMENT_SHADER
+ if (loadShaderFile(shaders[i].first, shaders[i].second, GL_FRAGMENT_SHADER, &attribs, index_channels[i]) == 0)
{
LL_WARNS("Shader") << "Failed to load fragment shader " << shaders[i].first << LL_ENDL;
return shaders[i].first;
@@ -1014,6 +957,8 @@ std::string LLViewerShaderMgr::loadBasicShaders()
BOOL LLViewerShaderMgr::loadShadersEnvironment()
{
+ LL_PROFILE_ZONE_SCOPED;
+#if 1 // DEPRECATED -- forward rendering is deprecated
BOOL success = TRUE;
if (mShaderLevel[SHADER_ENVIRONMENT] == 0)
@@ -1035,13 +980,41 @@ BOOL LLViewerShaderMgr::loadShadersEnvironment()
gTerrainProgram.mFeatures.disableTextureIndex = true;
gTerrainProgram.mFeatures.hasGamma = true;
gTerrainProgram.mShaderFiles.clear();
- gTerrainProgram.mShaderFiles.push_back(make_pair("environment/terrainV.glsl", GL_VERTEX_SHADER_ARB));
- gTerrainProgram.mShaderFiles.push_back(make_pair("environment/terrainF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gTerrainProgram.mShaderFiles.push_back(make_pair("environment/terrainV.glsl", GL_VERTEX_SHADER));
+ gTerrainProgram.mShaderFiles.push_back(make_pair("environment/terrainF.glsl", GL_FRAGMENT_SHADER));
gTerrainProgram.mShaderLevel = mShaderLevel[SHADER_ENVIRONMENT];
success = gTerrainProgram.createShader(NULL, NULL);
llassert(success);
}
+ if (success)
+ {
+ gStarsProgram.mName = "Environment Stars Shader";
+ gStarsProgram.mShaderFiles.clear();
+ gStarsProgram.mShaderFiles.push_back(make_pair("environment/starsV.glsl", GL_VERTEX_SHADER_ARB));
+ gStarsProgram.mShaderFiles.push_back(make_pair("environment/starsF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gStarsProgram.mShaderLevel = mShaderLevel[SHADER_ENVIRONMENT];
+ gStarsProgram.addConstant( LLGLSLShader::SHADER_CONST_STAR_DEPTH ); // SL-14113
+ success = gStarsProgram.createShader(NULL, NULL);
+ llassert(success);
+ }
+
+ if (success)
+ {
+ gMoonProgram.mName = "Environment Moon Shader";
+ gMoonProgram.mShaderFiles.clear();
+ gMoonProgram.mShaderFiles.push_back(make_pair("environment/moonV.glsl", GL_VERTEX_SHADER_ARB));
+ gMoonProgram.mShaderFiles.push_back(make_pair("environment/moonF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gMoonProgram.mShaderLevel = mShaderLevel[SHADER_ENVIRONMENT];
+ gMoonProgram.addConstant( LLGLSLShader::SHADER_CONST_CLOUD_MOON_DEPTH ); // SL-14113
+ success = gMoonProgram.createShader(NULL, NULL);
+ if (success)
+ {
+ gMoonProgram.bind();
+ gMoonProgram.uniform1i(sTex0, 0);
+ }
+ }
+
if (!success)
{
mShaderLevel[SHADER_ENVIRONMENT] = 0;
@@ -1049,12 +1022,14 @@ BOOL LLViewerShaderMgr::loadShadersEnvironment()
}
LLWorld::getInstance()->updateWaterObjects();
-
+#endif
return TRUE;
}
BOOL LLViewerShaderMgr::loadShadersWater()
{
+ LL_PROFILE_ZONE_SCOPED;
+#if 1 // DEPRECATED -- forward rendering is deprecated
BOOL success = TRUE;
BOOL terrainWaterSuccess = TRUE;
@@ -1072,12 +1047,20 @@ BOOL LLViewerShaderMgr::loadShadersWater()
// load water shader
gWaterProgram.mName = "Water Shader";
gWaterProgram.mFeatures.calculatesAtmospherics = true;
+ gWaterProgram.mFeatures.hasAtmospherics = true;
+ gWaterProgram.mFeatures.hasWaterFog = true;
gWaterProgram.mFeatures.hasGamma = true;
gWaterProgram.mFeatures.hasTransport = true;
gWaterProgram.mFeatures.hasSrgb = true;
+ gWaterProgram.mFeatures.hasReflectionProbes = true;
gWaterProgram.mShaderFiles.clear();
- gWaterProgram.mShaderFiles.push_back(make_pair("environment/waterV.glsl", GL_VERTEX_SHADER_ARB));
- gWaterProgram.mShaderFiles.push_back(make_pair("environment/waterF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gWaterProgram.mShaderFiles.push_back(make_pair("environment/waterV.glsl", GL_VERTEX_SHADER));
+ gWaterProgram.mShaderFiles.push_back(make_pair("environment/waterF.glsl", GL_FRAGMENT_SHADER));
+ gWaterProgram.clearPermutations();
+ if (LLPipeline::sRenderTransparentWater)
+ {
+ gWaterProgram.addPermutation("TRANSPARENT_WATER", "1");
+ }
gWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
gWaterProgram.mShaderLevel = mShaderLevel[SHADER_WATER];
success = gWaterProgram.createShader(NULL, NULL);
@@ -1089,13 +1072,21 @@ BOOL LLViewerShaderMgr::loadShadersWater()
// load water shader
gWaterEdgeProgram.mName = "Water Edge Shader";
gWaterEdgeProgram.mFeatures.calculatesAtmospherics = true;
+ gWaterEdgeProgram.mFeatures.hasAtmospherics = true;
+ gWaterEdgeProgram.mFeatures.hasWaterFog = true;
gWaterEdgeProgram.mFeatures.hasGamma = true;
gWaterEdgeProgram.mFeatures.hasTransport = true;
gWaterEdgeProgram.mFeatures.hasSrgb = true;
+ gWaterEdgeProgram.mFeatures.hasReflectionProbes = true;
gWaterEdgeProgram.mShaderFiles.clear();
- gWaterEdgeProgram.mShaderFiles.push_back(make_pair("environment/waterV.glsl", GL_VERTEX_SHADER_ARB));
- gWaterEdgeProgram.mShaderFiles.push_back(make_pair("environment/waterF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gWaterEdgeProgram.mShaderFiles.push_back(make_pair("environment/waterV.glsl", GL_VERTEX_SHADER));
+ gWaterEdgeProgram.mShaderFiles.push_back(make_pair("environment/waterF.glsl", GL_FRAGMENT_SHADER));
gWaterEdgeProgram.addPermutation("WATER_EDGE", "1");
+ gWaterEdgeProgram.clearPermutations();
+ if (LLPipeline::sRenderTransparentWater)
+ {
+ gWaterEdgeProgram.addPermutation("TRANSPARENT_WATER", "1");
+ }
gWaterEdgeProgram.mShaderGroup = LLGLSLShader::SG_WATER;
gWaterEdgeProgram.mShaderLevel = mShaderLevel[SHADER_WATER];
success = gWaterEdgeProgram.createShader(NULL, NULL);
@@ -1109,10 +1100,15 @@ BOOL LLViewerShaderMgr::loadShadersWater()
gUnderWaterProgram.mFeatures.calculatesAtmospherics = true;
gUnderWaterProgram.mFeatures.hasWaterFog = true;
gUnderWaterProgram.mShaderFiles.clear();
- gUnderWaterProgram.mShaderFiles.push_back(make_pair("environment/waterV.glsl", GL_VERTEX_SHADER_ARB));
- gUnderWaterProgram.mShaderFiles.push_back(make_pair("environment/underWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gUnderWaterProgram.mShaderFiles.push_back(make_pair("environment/waterV.glsl", GL_VERTEX_SHADER));
+ gUnderWaterProgram.mShaderFiles.push_back(make_pair("environment/underWaterF.glsl", GL_FRAGMENT_SHADER));
gUnderWaterProgram.mShaderLevel = mShaderLevel[SHADER_WATER];
gUnderWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
+ gUnderWaterProgram.clearPermutations();
+ if (LLPipeline::sRenderTransparentWater)
+ {
+ gUnderWaterProgram.addPermutation("TRANSPARENT_WATER", "1");
+ }
success = gUnderWaterProgram.createShader(NULL, NULL);
llassert(success);
}
@@ -1128,8 +1124,8 @@ BOOL LLViewerShaderMgr::loadShadersWater()
gTerrainWaterProgram.mFeatures.mIndexedTextureChannels = 0;
gTerrainWaterProgram.mFeatures.disableTextureIndex = true;
gTerrainWaterProgram.mShaderFiles.clear();
- gTerrainWaterProgram.mShaderFiles.push_back(make_pair("environment/terrainWaterV.glsl", GL_VERTEX_SHADER_ARB));
- gTerrainWaterProgram.mShaderFiles.push_back(make_pair("environment/terrainWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gTerrainWaterProgram.mShaderFiles.push_back(make_pair("environment/terrainWaterV.glsl", GL_VERTEX_SHADER));
+ gTerrainWaterProgram.mShaderFiles.push_back(make_pair("environment/terrainWaterF.glsl", GL_FRAGMENT_SHADER));
gTerrainWaterProgram.mShaderLevel = mShaderLevel[SHADER_ENVIRONMENT];
gTerrainWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
@@ -1167,11 +1163,13 @@ BOOL LLViewerShaderMgr::loadShadersWater()
LLWorld::getInstance()->updateWaterObjects();
+#endif
return TRUE;
}
BOOL LLViewerShaderMgr::loadShadersEffects()
{
+ LL_PROFILE_ZONE_SCOPED;
BOOL success = TRUE;
if (mShaderLevel[SHADER_EFFECT] == 0)
@@ -1187,8 +1185,8 @@ BOOL LLViewerShaderMgr::loadShadersEffects()
{
gGlowProgram.mName = "Glow Shader (Post)";
gGlowProgram.mShaderFiles.clear();
- gGlowProgram.mShaderFiles.push_back(make_pair("effects/glowV.glsl", GL_VERTEX_SHADER_ARB));
- gGlowProgram.mShaderFiles.push_back(make_pair("effects/glowF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gGlowProgram.mShaderFiles.push_back(make_pair("effects/glowV.glsl", GL_VERTEX_SHADER));
+ gGlowProgram.mShaderFiles.push_back(make_pair("effects/glowF.glsl", GL_FRAGMENT_SHADER));
gGlowProgram.mShaderLevel = mShaderLevel[SHADER_EFFECT];
success = gGlowProgram.createShader(NULL, NULL);
if (!success)
@@ -1201,8 +1199,8 @@ BOOL LLViewerShaderMgr::loadShadersEffects()
{
gGlowExtractProgram.mName = "Glow Extract Shader (Post)";
gGlowExtractProgram.mShaderFiles.clear();
- gGlowExtractProgram.mShaderFiles.push_back(make_pair("effects/glowExtractV.glsl", GL_VERTEX_SHADER_ARB));
- gGlowExtractProgram.mShaderFiles.push_back(make_pair("effects/glowExtractF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gGlowExtractProgram.mShaderFiles.push_back(make_pair("effects/glowExtractV.glsl", GL_VERTEX_SHADER));
+ gGlowExtractProgram.mShaderFiles.push_back(make_pair("effects/glowExtractF.glsl", GL_FRAGMENT_SHADER));
gGlowExtractProgram.mShaderLevel = mShaderLevel[SHADER_EFFECT];
success = gGlowExtractProgram.createShader(NULL, NULL);
if (!success)
@@ -1217,7 +1215,9 @@ BOOL LLViewerShaderMgr::loadShadersEffects()
BOOL LLViewerShaderMgr::loadShadersDeferred()
{
- bool use_sun_shadow = mShaderLevel[SHADER_DEFERRED] > 1;
+ LL_PROFILE_ZONE_SCOPED;
+ bool use_sun_shadow = mShaderLevel[SHADER_DEFERRED] > 1 &&
+ gSavedSettings.getS32("RenderShadowDetail") > 0;
BOOL ambient_kill = gSavedSettings.getBOOL("AmbientDisable");
BOOL sunlight_kill = gSavedSettings.getBOOL("SunlightDisable");
@@ -1229,14 +1229,13 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredTreeShadowProgram.unload();
gDeferredSkinnedTreeShadowProgram.unload();
gDeferredDiffuseProgram.unload();
+ gDeferredSkinnedDiffuseProgram.unload();
gDeferredDiffuseAlphaMaskProgram.unload();
gDeferredSkinnedDiffuseAlphaMaskProgram.unload();
gDeferredNonIndexedDiffuseAlphaMaskProgram.unload();
gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.unload();
- gDeferredNonIndexedDiffuseProgram.unload();
- gDeferredSkinnedDiffuseProgram.unload();
- gDeferredSkinnedBumpProgram.unload();
gDeferredBumpProgram.unload();
+ gDeferredSkinnedBumpProgram.unload();
gDeferredImpostorProgram.unload();
gDeferredTerrainProgram.unload();
gDeferredTerrainWaterProgram.unload();
@@ -1255,15 +1254,13 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredSkinnedShadowProgram.unload();
gDeferredShadowCubeProgram.unload();
gDeferredShadowAlphaMaskProgram.unload();
+ gDeferredShadowGLTFAlphaMaskProgram.unload();
gDeferredSkinnedShadowAlphaMaskProgram.unload();
gDeferredShadowFullbrightAlphaMaskProgram.unload();
gDeferredSkinnedShadowFullbrightAlphaMaskProgram.unload();
gDeferredAvatarShadowProgram.unload();
gDeferredAvatarAlphaShadowProgram.unload();
gDeferredAvatarAlphaMaskShadowProgram.unload();
- gDeferredAttachmentShadowProgram.unload();
- gDeferredAttachmentAlphaShadowProgram.unload();
- gDeferredAttachmentAlphaMaskShadowProgram.unload();
gDeferredAvatarProgram.unload();
gDeferredAvatarAlphaProgram.unload();
gDeferredAlphaProgram.unload();
@@ -1272,8 +1269,11 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredSkinnedAlphaWaterProgram.unload();
gDeferredFullbrightProgram.unload();
gDeferredFullbrightAlphaMaskProgram.unload();
+ gDeferredFullbrightAlphaMaskAlphaProgram.unload();
gDeferredFullbrightWaterProgram.unload();
gDeferredSkinnedFullbrightWaterProgram.unload();
+ gDeferredFullbrightWaterAlphaProgram.unload();
+ gDeferredSkinnedFullbrightWaterAlphaProgram.unload();
gDeferredFullbrightAlphaMaskWaterProgram.unload();
gDeferredSkinnedFullbrightAlphaMaskWaterProgram.unload();
gDeferredEmissiveProgram.unload();
@@ -1295,17 +1295,26 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredSkinnedFullbrightShinyProgram.unload();
gDeferredSkinnedFullbrightProgram.unload();
gDeferredSkinnedFullbrightAlphaMaskProgram.unload();
+ gDeferredSkinnedFullbrightAlphaMaskAlphaProgram.unload();
gDeferredHighlightProgram.unload();
gDeferredHighlightNormalProgram.unload();
gDeferredHighlightSpecularProgram.unload();
gNormalMapGenProgram.unload();
+ gDeferredGenBrdfLutProgram.unload();
+
for (U32 i = 0; i < LLMaterial::SHADER_COUNT*2; ++i)
{
gDeferredMaterialProgram[i].unload();
gDeferredMaterialWaterProgram[i].unload();
}
+
+ gDeferredPBROpaqueProgram.unload();
+ gDeferredSkinnedPBROpaqueProgram.unload();
+ gDeferredPBRAlphaProgram.unload();
+ gDeferredSkinnedPBRAlphaProgram.unload();
+
return TRUE;
}
@@ -1315,8 +1324,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
{
gDeferredHighlightProgram.mName = "Deferred Highlight Shader";
gDeferredHighlightProgram.mShaderFiles.clear();
- gDeferredHighlightProgram.mShaderFiles.push_back(make_pair("interface/highlightV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredHighlightProgram.mShaderFiles.push_back(make_pair("deferred/highlightF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredHighlightProgram.mShaderFiles.push_back(make_pair("interface/highlightV.glsl", GL_VERTEX_SHADER));
+ gDeferredHighlightProgram.mShaderFiles.push_back(make_pair("deferred/highlightF.glsl", GL_FRAGMENT_SHADER));
gDeferredHighlightProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
success = gDeferredHighlightProgram.createShader(NULL, NULL);
}
@@ -1325,8 +1334,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
{
gDeferredHighlightNormalProgram.mName = "Deferred Highlight Normals Shader";
gDeferredHighlightNormalProgram.mShaderFiles.clear();
- gDeferredHighlightNormalProgram.mShaderFiles.push_back(make_pair("interface/highlightNormV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredHighlightNormalProgram.mShaderFiles.push_back(make_pair("deferred/highlightF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredHighlightNormalProgram.mShaderFiles.push_back(make_pair("interface/highlightNormV.glsl", GL_VERTEX_SHADER));
+ gDeferredHighlightNormalProgram.mShaderFiles.push_back(make_pair("deferred/highlightF.glsl", GL_FRAGMENT_SHADER));
gDeferredHighlightNormalProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
success = gHighlightNormalProgram.createShader(NULL, NULL);
}
@@ -1335,8 +1344,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
{
gDeferredHighlightSpecularProgram.mName = "Deferred Highlight Spec Shader";
gDeferredHighlightSpecularProgram.mShaderFiles.clear();
- gDeferredHighlightSpecularProgram.mShaderFiles.push_back(make_pair("interface/highlightSpecV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredHighlightSpecularProgram.mShaderFiles.push_back(make_pair("deferred/highlightF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredHighlightSpecularProgram.mShaderFiles.push_back(make_pair("interface/highlightSpecV.glsl", GL_VERTEX_SHADER));
+ gDeferredHighlightSpecularProgram.mShaderFiles.push_back(make_pair("deferred/highlightF.glsl", GL_FRAGMENT_SHADER));
gDeferredHighlightSpecularProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
success = gDeferredHighlightSpecularProgram.createShader(NULL, NULL);
}
@@ -1347,8 +1356,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredDiffuseProgram.mFeatures.encodesNormal = true;
gDeferredDiffuseProgram.mFeatures.hasSrgb = true;
gDeferredDiffuseProgram.mShaderFiles.clear();
- gDeferredDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseIndexedF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER));
+ gDeferredDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseIndexedF.glsl", GL_FRAGMENT_SHADER));
gDeferredDiffuseProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
gDeferredDiffuseProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
success = make_rigged_variant(gDeferredDiffuseProgram, gDeferredSkinnedDiffuseProgram);
@@ -1360,8 +1369,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredDiffuseAlphaMaskProgram.mName = "Deferred Diffuse Alpha Mask Shader";
gDeferredDiffuseAlphaMaskProgram.mFeatures.encodesNormal = true;
gDeferredDiffuseAlphaMaskProgram.mShaderFiles.clear();
- gDeferredDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseAlphaMaskIndexedF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER));
+ gDeferredDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseAlphaMaskIndexedF.glsl", GL_FRAGMENT_SHADER));
gDeferredDiffuseAlphaMaskProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
gDeferredDiffuseAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
success = make_rigged_variant(gDeferredDiffuseAlphaMaskProgram, gDeferredSkinnedDiffuseAlphaMaskProgram);
@@ -1373,8 +1382,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredNonIndexedDiffuseAlphaMaskProgram.mName = "Deferred Diffuse Non-Indexed Alpha Mask Shader";
gDeferredNonIndexedDiffuseAlphaMaskProgram.mFeatures.encodesNormal = true;
gDeferredNonIndexedDiffuseAlphaMaskProgram.mShaderFiles.clear();
- gDeferredNonIndexedDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredNonIndexedDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseAlphaMaskF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredNonIndexedDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER));
+ gDeferredNonIndexedDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseAlphaMaskF.glsl", GL_FRAGMENT_SHADER));
gDeferredNonIndexedDiffuseAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
success = gDeferredNonIndexedDiffuseAlphaMaskProgram.createShader(NULL, NULL);
llassert(success);
@@ -1385,8 +1394,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mName = "Deferred Diffuse Non-Indexed Alpha Mask Shader";
gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mFeatures.encodesNormal = true;
gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mShaderFiles.clear();
- gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mShaderFiles.push_back(make_pair("deferred/diffuseNoColorV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mShaderFiles.push_back(make_pair("deferred/diffuseAlphaMaskNoColorF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mShaderFiles.push_back(make_pair("deferred/diffuseNoColorV.glsl", GL_VERTEX_SHADER));
+ gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mShaderFiles.push_back(make_pair("deferred/diffuseAlphaMaskNoColorF.glsl", GL_FRAGMENT_SHADER));
gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
success = gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.createShader(NULL, NULL);
llassert(success);
@@ -1394,24 +1403,11 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
if (success)
{
- gDeferredNonIndexedDiffuseProgram.mName = "Non Indexed Deferred Diffuse Shader";
- gDeferredNonIndexedDiffuseProgram.mShaderFiles.clear();
- gDeferredNonIndexedDiffuseProgram.mFeatures.encodesNormal = true;
- gDeferredNonIndexedDiffuseProgram.mFeatures.hasSrgb = true;
- gDeferredNonIndexedDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredNonIndexedDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseF.glsl", GL_FRAGMENT_SHADER_ARB));
- gDeferredNonIndexedDiffuseProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
- success = gDeferredNonIndexedDiffuseProgram.createShader(NULL, NULL);
- llassert(success);
- }
-
- if (success)
- {
gDeferredBumpProgram.mName = "Deferred Bump Shader";
gDeferredBumpProgram.mFeatures.encodesNormal = true;
gDeferredBumpProgram.mShaderFiles.clear();
- gDeferredBumpProgram.mShaderFiles.push_back(make_pair("deferred/bumpV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredBumpProgram.mShaderFiles.push_back(make_pair("deferred/bumpF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredBumpProgram.mShaderFiles.push_back(make_pair("deferred/bumpV.glsl", GL_VERTEX_SHADER));
+ gDeferredBumpProgram.mShaderFiles.push_back(make_pair("deferred/bumpF.glsl", GL_FRAGMENT_SHADER));
gDeferredBumpProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
success = make_rigged_variant(gDeferredBumpProgram, gDeferredSkinnedBumpProgram);
success = success && gDeferredBumpProgram.createShader(NULL, NULL);
@@ -1447,8 +1443,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
U32 alpha_mode = i & 0x3;
gDeferredMaterialProgram[i].mShaderFiles.clear();
- gDeferredMaterialProgram[i].mShaderFiles.push_back(make_pair("deferred/materialV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredMaterialProgram[i].mShaderFiles.push_back(make_pair("deferred/materialF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredMaterialProgram[i].mShaderFiles.push_back(make_pair("deferred/materialV.glsl", GL_VERTEX_SHADER));
+ gDeferredMaterialProgram[i].mShaderFiles.push_back(make_pair("deferred/materialF.glsl", GL_FRAGMENT_SHADER));
gDeferredMaterialProgram[i].mShaderLevel = mShaderLevel[SHADER_DEFERRED];
gDeferredMaterialProgram[i].clearPermutations();
@@ -1502,7 +1498,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredMaterialProgram[i].mFeatures.hasAtmospherics = true;
gDeferredMaterialProgram[i].mFeatures.hasGamma = true;
gDeferredMaterialProgram[i].mFeatures.hasShadows = use_sun_shadow;
-
+ gDeferredMaterialProgram[i].mFeatures.hasReflectionProbes = true;
+
if (has_skin)
{
gDeferredMaterialProgram[i].addPermutation("HAS_SKIN", "1");
@@ -1526,8 +1523,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
U32 alpha_mode = i & 0x3;
gDeferredMaterialWaterProgram[i].mShaderFiles.clear();
- gDeferredMaterialWaterProgram[i].mShaderFiles.push_back(make_pair("deferred/materialV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredMaterialWaterProgram[i].mShaderFiles.push_back(make_pair("deferred/materialF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredMaterialWaterProgram[i].mShaderFiles.push_back(make_pair("deferred/materialV.glsl", GL_VERTEX_SHADER));
+ gDeferredMaterialWaterProgram[i].mShaderFiles.push_back(make_pair("deferred/materialF.glsl", GL_FRAGMENT_SHADER));
gDeferredMaterialWaterProgram[i].mShaderLevel = mShaderLevel[SHADER_DEFERRED];
gDeferredMaterialWaterProgram[i].mShaderGroup = LLGLSLShader::SG_WATER;
@@ -1584,6 +1581,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredMaterialWaterProgram[i].addPermutation("LOCAL_LIGHT_KILL", "1");
}
+ gDeferredMaterialWaterProgram[i].mFeatures.hasReflectionProbes = true;
gDeferredMaterialWaterProgram[i].mFeatures.hasWaterFog = true;
gDeferredMaterialWaterProgram[i].mFeatures.hasSrgb = true;
gDeferredMaterialWaterProgram[i].mFeatures.encodesNormal = true;
@@ -1622,14 +1620,105 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredMaterialWaterProgram[9+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = true;
gDeferredMaterialWaterProgram[13+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = true;
+ if (success)
+ {
+ gDeferredPBROpaqueProgram.mName = "Deferred PBR Opaque Shader";
+ gDeferredPBROpaqueProgram.mFeatures.encodesNormal = true;
+ gDeferredPBROpaqueProgram.mFeatures.hasSrgb = true;
+
+ gDeferredPBROpaqueProgram.mShaderFiles.clear();
+ gDeferredPBROpaqueProgram.mShaderFiles.push_back(make_pair("deferred/pbropaqueV.glsl", GL_VERTEX_SHADER));
+ gDeferredPBROpaqueProgram.mShaderFiles.push_back(make_pair("deferred/pbropaqueF.glsl", GL_FRAGMENT_SHADER));
+ gDeferredPBROpaqueProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
+ gDeferredPBROpaqueProgram.addPermutation("HAS_NORMAL_MAP", "1");
+ gDeferredPBROpaqueProgram.addPermutation("HAS_SPECULAR_MAP", "1");
+ gDeferredPBROpaqueProgram.addPermutation("HAS_EMISSIVE_MAP", "1");
+ gDeferredPBROpaqueProgram.addPermutation("DIFFUSE_ALPHA_MODE", "0");
+
+ success = make_rigged_variant(gDeferredPBROpaqueProgram, gDeferredSkinnedPBROpaqueProgram);
+ if (success)
+ {
+ success = gDeferredPBROpaqueProgram.createShader(NULL, NULL);
+ }
+ llassert(success);
+ }
+
+ if (success)
+ {
+ LLGLSLShader* shader = &gDeferredPBRAlphaProgram;
+ shader->mName = "Deferred PBR Alpha Shader";
+
+ shader->mFeatures.calculatesLighting = false;
+ shader->mFeatures.hasLighting = false;
+ shader->mFeatures.isAlphaLighting = true;
+ shader->mFeatures.hasSrgb = true;
+ shader->mFeatures.encodesNormal = true;
+ shader->mFeatures.calculatesAtmospherics = true;
+ shader->mFeatures.hasAtmospherics = true;
+ shader->mFeatures.hasGamma = true;
+ shader->mFeatures.hasTransport = true;
+ shader->mFeatures.hasShadows = use_sun_shadow;
+ shader->mFeatures.isDeferred = true; // include deferredUtils
+ shader->mFeatures.hasReflectionProbes = mShaderLevel[SHADER_DEFERRED];
+
+ shader->mShaderFiles.clear();
+ shader->mShaderFiles.push_back(make_pair("deferred/pbralphaV.glsl", GL_VERTEX_SHADER));
+ shader->mShaderFiles.push_back(make_pair("deferred/pbralphaF.glsl", GL_FRAGMENT_SHADER));
+
+ shader->clearPermutations();
+
+ U32 alpha_mode = LLMaterial::DIFFUSE_ALPHA_MODE_BLEND;
+ shader->addPermutation("DIFFUSE_ALPHA_MODE", llformat("%d", alpha_mode));
+ shader->addPermutation("HAS_NORMAL_MAP", "1");
+ shader->addPermutation("HAS_SPECULAR_MAP", "1"); // PBR: Packed: Occlusion, Metal, Roughness
+ shader->addPermutation("HAS_EMISSIVE_MAP", "1");
+ shader->addPermutation("USE_VERTEX_COLOR", "1");
+
+ if (use_sun_shadow)
+ {
+ shader->addPermutation("HAS_SUN_SHADOW", "1");
+ }
+
+ if (ambient_kill)
+ {
+ shader->addPermutation("AMBIENT_KILL", "1");
+ }
+
+ if (sunlight_kill)
+ {
+ shader->addPermutation("SUNLIGHT_KILL", "1");
+ }
+
+ if (local_light_kill)
+ {
+ shader->addPermutation("LOCAL_LIGHT_KILL", "1");
+ }
+
+ shader->mShaderLevel = mShaderLevel[SHADER_DEFERRED];
+ success = make_rigged_variant(*shader, gDeferredSkinnedPBRAlphaProgram);
+ if (success)
+ {
+ success = shader->createShader(NULL, NULL);
+ }
+ llassert(success);
+
+ // Alpha Shader Hack
+ // See: LLRender::syncMatrices()
+ shader->mFeatures.calculatesLighting = true;
+ shader->mFeatures.hasLighting = true;
+
+ shader->mRiggedVariant->mFeatures.calculatesLighting = true;
+ shader->mRiggedVariant->mFeatures.hasLighting = true;
+ }
+
if (success)
{
gDeferredTreeProgram.mName = "Deferred Tree Shader";
gDeferredTreeProgram.mShaderFiles.clear();
gDeferredTreeProgram.mFeatures.encodesNormal = true;
- gDeferredTreeProgram.mShaderFiles.push_back(make_pair("deferred/treeV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredTreeProgram.mShaderFiles.push_back(make_pair("deferred/treeF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredTreeProgram.mShaderFiles.push_back(make_pair("deferred/treeV.glsl", GL_VERTEX_SHADER));
+ gDeferredTreeProgram.mShaderFiles.push_back(make_pair("deferred/treeF.glsl", GL_FRAGMENT_SHADER));
gDeferredTreeProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
success = gDeferredTreeProgram.createShader(NULL, NULL);
}
@@ -1638,10 +1727,8 @@ 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_ARB));
- gDeferredTreeShadowProgram.mShaderFiles.push_back(make_pair("deferred/treeShadowF.glsl", GL_FRAGMENT_SHADER_ARB));
+ 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];
gDeferredTreeShadowProgram.mRiggedVariant = &gDeferredSkinnedTreeShadowProgram;
success = gDeferredTreeShadowProgram.createShader(NULL, NULL);
@@ -1652,11 +1739,9 @@ 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_ARB));
- gDeferredSkinnedTreeShadowProgram.mShaderFiles.push_back(make_pair("deferred/treeShadowF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredSkinnedTreeShadowProgram.mShaderFiles.push_back(make_pair("deferred/treeShadowSkinnedV.glsl", GL_VERTEX_SHADER));
+ gDeferredSkinnedTreeShadowProgram.mShaderFiles.push_back(make_pair("deferred/treeShadowF.glsl", GL_FRAGMENT_SHADER));
gDeferredSkinnedTreeShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
success = gDeferredSkinnedTreeShadowProgram.createShader(NULL, NULL);
llassert(success);
@@ -1669,8 +1754,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredImpostorProgram.mFeatures.encodesNormal = true;
//gDeferredImpostorProgram.mFeatures.isDeferred = true;
gDeferredImpostorProgram.mShaderFiles.clear();
- gDeferredImpostorProgram.mShaderFiles.push_back(make_pair("deferred/impostorV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredImpostorProgram.mShaderFiles.push_back(make_pair("deferred/impostorF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredImpostorProgram.mShaderFiles.push_back(make_pair("deferred/impostorV.glsl", GL_VERTEX_SHADER));
+ gDeferredImpostorProgram.mShaderFiles.push_back(make_pair("deferred/impostorF.glsl", GL_FRAGMENT_SHADER));
gDeferredImpostorProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
success = gDeferredImpostorProgram.createShader(NULL, NULL);
llassert(success);
@@ -1684,8 +1769,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredLightProgram.mFeatures.hasSrgb = true;
gDeferredLightProgram.mShaderFiles.clear();
- gDeferredLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightV.glsl", GL_VERTEX_SHADER));
+ gDeferredLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightF.glsl", GL_FRAGMENT_SHADER));
gDeferredLightProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
gDeferredLightProgram.clearPermutations();
@@ -1720,8 +1805,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredMultiLightProgram[i].clearPermutations();
gDeferredMultiLightProgram[i].mShaderFiles.clear();
- gDeferredMultiLightProgram[i].mShaderFiles.push_back(make_pair("deferred/multiPointLightV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredMultiLightProgram[i].mShaderFiles.push_back(make_pair("deferred/multiPointLightF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredMultiLightProgram[i].mShaderFiles.push_back(make_pair("deferred/multiPointLightV.glsl", GL_VERTEX_SHADER));
+ gDeferredMultiLightProgram[i].mShaderFiles.push_back(make_pair("deferred/multiPointLightF.glsl", GL_FRAGMENT_SHADER));
gDeferredMultiLightProgram[i].mShaderLevel = mShaderLevel[SHADER_DEFERRED];
gDeferredMultiLightProgram[i].addPermutation("LIGHT_COUNT", llformat("%d", i+1));
@@ -1754,8 +1839,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredSpotLightProgram.mFeatures.hasShadows = true;
gDeferredSpotLightProgram.clearPermutations();
- gDeferredSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/spotLightF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightV.glsl", GL_VERTEX_SHADER));
+ gDeferredSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/spotLightF.glsl", GL_FRAGMENT_SHADER));
gDeferredSpotLightProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
if (ambient_kill)
@@ -1786,8 +1871,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredMultiSpotLightProgram.clearPermutations();
gDeferredMultiSpotLightProgram.mShaderFiles.clear();
- gDeferredMultiSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/multiPointLightV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredMultiSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/multiSpotLightF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredMultiSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/multiPointLightV.glsl", GL_VERTEX_SHADER));
+ gDeferredMultiSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/multiSpotLightF.glsl", GL_FRAGMENT_SHADER));
gDeferredMultiSpotLightProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
if (local_light_kill)
@@ -1826,8 +1911,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredSunProgram.mName = "Deferred Sun Shader";
gDeferredSunProgram.mShaderFiles.clear();
- gDeferredSunProgram.mShaderFiles.push_back(make_pair(vertex, GL_VERTEX_SHADER_ARB));
- gDeferredSunProgram.mShaderFiles.push_back(make_pair(fragment, GL_FRAGMENT_SHADER_ARB));
+ gDeferredSunProgram.mShaderFiles.push_back(make_pair(vertex, GL_VERTEX_SHADER));
+ gDeferredSunProgram.mShaderFiles.push_back(make_pair(fragment, GL_FRAGMENT_SHADER));
gDeferredSunProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
success = gDeferredSunProgram.createShader(NULL, NULL);
@@ -1840,8 +1925,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredBlurLightProgram.mFeatures.isDeferred = true;
gDeferredBlurLightProgram.mShaderFiles.clear();
- gDeferredBlurLightProgram.mShaderFiles.push_back(make_pair("deferred/blurLightV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredBlurLightProgram.mShaderFiles.push_back(make_pair("deferred/blurLightF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredBlurLightProgram.mShaderFiles.push_back(make_pair("deferred/blurLightV.glsl", GL_VERTEX_SHADER));
+ gDeferredBlurLightProgram.mShaderFiles.push_back(make_pair("deferred/blurLightF.glsl", GL_FRAGMENT_SHADER));
gDeferredBlurLightProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
success = gDeferredBlurLightProgram.createShader(NULL, NULL);
@@ -1878,19 +1963,13 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
shader->mFeatures.hasGamma = true;
shader->mFeatures.hasTransport = true;
shader->mFeatures.hasShadows = use_sun_shadow;
-
- if (mShaderLevel[SHADER_DEFERRED] < 1)
- {
- shader->mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
- }
- else
- { //shave off some texture units for shadow maps
- shader->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels - 6, 1);
- }
+ shader->mFeatures.hasReflectionProbes = true;
+ shader->mFeatures.hasWaterFog = true;
+ shader->mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
shader->mShaderFiles.clear();
- shader->mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB));
- shader->mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB));
+ shader->mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER));
+ shader->mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER));
shader->clearPermutations();
shader->addPermutation("USE_VERTEX_COLOR", "1");
@@ -1898,7 +1977,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
shader->addPermutation("USE_INDEXED_TEX", "1");
if (use_sun_shadow)
{
- shader->addPermutation("HAS_SHADOW", "1");
+ shader->addPermutation("HAS_SUN_SHADOW", "1");
}
if (ambient_kill)
@@ -1954,19 +2033,12 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
shader->mFeatures.isAlphaLighting = true;
shader->mFeatures.encodesNormal = true;
shader->mFeatures.hasShadows = use_sun_shadow;
-
- if (mShaderLevel[SHADER_DEFERRED] < 1)
- {
- shader->mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
- }
- else
- { //shave off some texture units for shadow maps
- shader->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels - 6, 1);
- }
+ shader->mFeatures.hasReflectionProbes = true;
+ shader->mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
shader->mShaderFiles.clear();
- shader->mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB));
- shader->mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB));
+ shader->mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER));
+ shader->mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER));
shader->clearPermutations();
shader->addPermutation("USE_INDEXED_TEX", "1");
@@ -1981,7 +2053,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
if (use_sun_shadow)
{
- shader->addPermutation("HAS_SHADOW", "1");
+ shader->addPermutation("HAS_SUN_SHADOW", "1");
}
shader->mRiggedVariant = &gDeferredSkinnedAlphaImpostorProgram;
@@ -2025,19 +2097,12 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
shader[i]->mFeatures.hasGamma = true;
shader[i]->mFeatures.hasTransport = true;
shader[i]->mFeatures.hasShadows = use_sun_shadow;
-
- if (mShaderLevel[SHADER_DEFERRED] < 1)
- {
- shader[i]->mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
- }
- else
- { //shave off some texture units for shadow maps
- shader[i]->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels - 6, 1);
- }
+ shader[i]->mFeatures.hasReflectionProbes = true;
+ shader[i]->mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
shader[i]->mShaderGroup = LLGLSLShader::SG_WATER;
shader[i]->mShaderFiles.clear();
- shader[i]->mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB));
- shader[i]->mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB));
+ shader[i]->mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER));
+ shader[i]->mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER));
shader[i]->clearPermutations();
shader[i]->addPermutation("USE_INDEXED_TEX", "1");
@@ -2046,7 +2111,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
shader[i]->addPermutation("HAS_ALPHA_MASK", "1");
if (use_sun_shadow)
{
- shader[i]->addPermutation("HAS_SHADOW", "1");
+ shader[i]->addPermutation("HAS_SUN_SHADOW", "1");
}
if (ambient_kill)
@@ -2096,8 +2161,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredAvatarEyesProgram.mFeatures.hasShadows = true;
gDeferredAvatarEyesProgram.mShaderFiles.clear();
- gDeferredAvatarEyesProgram.mShaderFiles.push_back(make_pair("deferred/avatarEyesV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredAvatarEyesProgram.mShaderFiles.push_back(make_pair("deferred/diffuseF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredAvatarEyesProgram.mShaderFiles.push_back(make_pair("deferred/avatarEyesV.glsl", GL_VERTEX_SHADER));
+ gDeferredAvatarEyesProgram.mShaderFiles.push_back(make_pair("deferred/diffuseF.glsl", GL_FRAGMENT_SHADER));
gDeferredAvatarEyesProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
success = gDeferredAvatarEyesProgram.createShader(NULL, NULL);
llassert(success);
@@ -2112,8 +2177,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredFullbrightProgram.mFeatures.hasSrgb = true;
gDeferredFullbrightProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
gDeferredFullbrightProgram.mShaderFiles.clear();
- gDeferredFullbrightProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredFullbrightProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredFullbrightProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightV.glsl", GL_VERTEX_SHADER));
+ gDeferredFullbrightProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightF.glsl", GL_FRAGMENT_SHADER));
gDeferredFullbrightProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
success = make_rigged_variant(gDeferredFullbrightProgram, gDeferredSkinnedFullbrightProgram);
success = gDeferredFullbrightProgram.createShader(NULL, NULL);
@@ -2129,8 +2194,9 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredFullbrightAlphaMaskProgram.mFeatures.hasSrgb = true;
gDeferredFullbrightAlphaMaskProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
gDeferredFullbrightAlphaMaskProgram.mShaderFiles.clear();
- gDeferredFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightV.glsl", GL_VERTEX_SHADER));
+ gDeferredFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightF.glsl", GL_FRAGMENT_SHADER));
+ gDeferredFullbrightAlphaMaskProgram.clearPermutations();
gDeferredFullbrightAlphaMaskProgram.addPermutation("HAS_ALPHA_MASK","1");
gDeferredFullbrightAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
success = make_rigged_variant(gDeferredFullbrightAlphaMaskProgram, gDeferredSkinnedFullbrightAlphaMaskProgram);
@@ -2138,6 +2204,27 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
llassert(success);
}
+ if (success)
+ {
+ gDeferredFullbrightAlphaMaskAlphaProgram.mName = "Deferred Fullbright Alpha Masking Alpha Shader";
+ gDeferredFullbrightAlphaMaskAlphaProgram.mFeatures.calculatesAtmospherics = true;
+ gDeferredFullbrightAlphaMaskAlphaProgram.mFeatures.hasGamma = true;
+ gDeferredFullbrightAlphaMaskAlphaProgram.mFeatures.hasTransport = true;
+ gDeferredFullbrightAlphaMaskAlphaProgram.mFeatures.hasSrgb = true;
+ gDeferredFullbrightAlphaMaskAlphaProgram.mFeatures.isDeferred = true;
+ gDeferredFullbrightAlphaMaskAlphaProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
+ gDeferredFullbrightAlphaMaskAlphaProgram.mShaderFiles.clear();
+ gDeferredFullbrightAlphaMaskAlphaProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightV.glsl", GL_VERTEX_SHADER));
+ gDeferredFullbrightAlphaMaskAlphaProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightF.glsl", GL_FRAGMENT_SHADER));
+ gDeferredFullbrightAlphaMaskAlphaProgram.clearPermutations();
+ gDeferredFullbrightAlphaMaskAlphaProgram.addPermutation("HAS_ALPHA_MASK", "1");
+ gDeferredFullbrightAlphaMaskAlphaProgram.addPermutation("IS_ALPHA", "1");
+ gDeferredFullbrightAlphaMaskAlphaProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
+ success = make_rigged_variant(gDeferredFullbrightAlphaMaskAlphaProgram, gDeferredSkinnedFullbrightAlphaMaskAlphaProgram);
+ success = success && gDeferredFullbrightAlphaMaskAlphaProgram.createShader(NULL, NULL);
+ llassert(success);
+ }
+
if (success)
{
gDeferredFullbrightWaterProgram.mName = "Deferred Fullbright Underwater Shader";
@@ -2148,8 +2235,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredFullbrightWaterProgram.mFeatures.hasSrgb = true;
gDeferredFullbrightWaterProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
gDeferredFullbrightWaterProgram.mShaderFiles.clear();
- gDeferredFullbrightWaterProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredFullbrightWaterProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredFullbrightWaterProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightV.glsl", GL_VERTEX_SHADER));
+ gDeferredFullbrightWaterProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightF.glsl", GL_FRAGMENT_SHADER));
gDeferredFullbrightWaterProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
gDeferredFullbrightWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
gDeferredFullbrightWaterProgram.addPermutation("WATER_FOG","1");
@@ -2158,6 +2245,29 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
llassert(success);
}
+ if (success)
+ {
+ gDeferredFullbrightWaterAlphaProgram.mName = "Deferred Fullbright Underwater Alpha Shader";
+ gDeferredFullbrightWaterAlphaProgram.mFeatures.calculatesAtmospherics = true;
+ gDeferredFullbrightWaterAlphaProgram.mFeatures.hasGamma = true;
+ gDeferredFullbrightWaterAlphaProgram.mFeatures.hasTransport = true;
+ gDeferredFullbrightWaterAlphaProgram.mFeatures.hasWaterFog = true;
+ gDeferredFullbrightWaterAlphaProgram.mFeatures.hasSrgb = true;
+ gDeferredFullbrightWaterAlphaProgram.mFeatures.isDeferred = true;
+ gDeferredFullbrightWaterAlphaProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
+ gDeferredFullbrightWaterAlphaProgram.mShaderFiles.clear();
+ gDeferredFullbrightWaterAlphaProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightV.glsl", GL_VERTEX_SHADER));
+ gDeferredFullbrightWaterAlphaProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightF.glsl", GL_FRAGMENT_SHADER));
+ gDeferredFullbrightWaterAlphaProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
+ gDeferredFullbrightWaterAlphaProgram.mShaderGroup = LLGLSLShader::SG_WATER;
+ gDeferredFullbrightWaterAlphaProgram.clearPermutations();
+ gDeferredFullbrightWaterAlphaProgram.addPermutation("WATER_FOG", "1");
+ gDeferredFullbrightWaterAlphaProgram.addPermutation("IS_ALPHA", "1");
+ success = make_rigged_variant(gDeferredFullbrightWaterAlphaProgram, gDeferredSkinnedFullbrightWaterAlphaProgram);
+ success = success && gDeferredFullbrightWaterAlphaProgram.createShader(NULL, NULL);
+ llassert(success);
+ }
+
if (success)
{
gDeferredFullbrightAlphaMaskWaterProgram.mName = "Deferred Fullbright Underwater Alpha Masking Shader";
@@ -2168,8 +2278,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredFullbrightAlphaMaskWaterProgram.mFeatures.hasSrgb = true;
gDeferredFullbrightAlphaMaskWaterProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
gDeferredFullbrightAlphaMaskWaterProgram.mShaderFiles.clear();
- gDeferredFullbrightAlphaMaskWaterProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredFullbrightAlphaMaskWaterProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredFullbrightAlphaMaskWaterProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightV.glsl", GL_VERTEX_SHADER));
+ gDeferredFullbrightAlphaMaskWaterProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightF.glsl", GL_FRAGMENT_SHADER));
gDeferredFullbrightAlphaMaskWaterProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
gDeferredFullbrightAlphaMaskWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
gDeferredFullbrightAlphaMaskWaterProgram.addPermutation("HAS_ALPHA_MASK","1");
@@ -2187,11 +2297,12 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredFullbrightShinyProgram.mFeatures.hasGamma = true;
gDeferredFullbrightShinyProgram.mFeatures.hasTransport = true;
gDeferredFullbrightShinyProgram.mFeatures.hasSrgb = true;
- gDeferredFullbrightShinyProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels-1;
+ gDeferredFullbrightShinyProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
gDeferredFullbrightShinyProgram.mShaderFiles.clear();
- gDeferredFullbrightShinyProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredFullbrightShinyProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredFullbrightShinyProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightShinyV.glsl", GL_VERTEX_SHADER));
+ gDeferredFullbrightShinyProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER));
gDeferredFullbrightShinyProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
+ gDeferredFullbrightShinyProgram.mFeatures.hasReflectionProbes = true;
success = make_rigged_variant(gDeferredFullbrightShinyProgram, gDeferredSkinnedFullbrightShinyProgram);
success = success && gDeferredFullbrightShinyProgram.createShader(NULL, NULL);
llassert(success);
@@ -2205,8 +2316,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredEmissiveProgram.mFeatures.hasTransport = true;
gDeferredEmissiveProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
gDeferredEmissiveProgram.mShaderFiles.clear();
- gDeferredEmissiveProgram.mShaderFiles.push_back(make_pair("deferred/emissiveV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredEmissiveProgram.mShaderFiles.push_back(make_pair("deferred/emissiveF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredEmissiveProgram.mShaderFiles.push_back(make_pair("deferred/emissiveV.glsl", GL_VERTEX_SHADER));
+ gDeferredEmissiveProgram.mShaderFiles.push_back(make_pair("deferred/emissiveF.glsl", GL_FRAGMENT_SHADER));
gDeferredEmissiveProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
success = make_rigged_variant(gDeferredEmissiveProgram, gDeferredSkinnedEmissiveProgram);
success = success && gDeferredEmissiveProgram.createShader(NULL, NULL);
@@ -2224,8 +2335,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredWaterProgram.mFeatures.hasSrgb = true;
gDeferredWaterProgram.mShaderFiles.clear();
- gDeferredWaterProgram.mShaderFiles.push_back(make_pair("deferred/waterV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredWaterProgram.mShaderFiles.push_back(make_pair("deferred/waterF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredWaterProgram.mShaderFiles.push_back(make_pair("deferred/waterV.glsl", GL_VERTEX_SHADER));
+ gDeferredWaterProgram.mShaderFiles.push_back(make_pair("deferred/waterF.glsl", GL_FRAGMENT_SHADER));
gDeferredWaterProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
gDeferredWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
success = gDeferredWaterProgram.createShader(NULL, NULL);
@@ -2245,8 +2356,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
//gDeferredUnderWaterProgram.mFeatures.hasShadows = true;
gDeferredUnderWaterProgram.mShaderFiles.clear();
- gDeferredUnderWaterProgram.mShaderFiles.push_back(make_pair("deferred/waterV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredUnderWaterProgram.mShaderFiles.push_back(make_pair("deferred/underWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredUnderWaterProgram.mShaderFiles.push_back(make_pair("deferred/waterV.glsl", GL_VERTEX_SHADER));
+ gDeferredUnderWaterProgram.mShaderFiles.push_back(make_pair("deferred/underWaterF.glsl", GL_FRAGMENT_SHADER));
gDeferredUnderWaterProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
gDeferredUnderWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
success = gDeferredUnderWaterProgram.createShader(NULL, NULL);
@@ -2264,13 +2375,19 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredSoftenProgram.mFeatures.hasGamma = true;
gDeferredSoftenProgram.mFeatures.isDeferred = true;
gDeferredSoftenProgram.mFeatures.hasShadows = use_sun_shadow;
+ gDeferredSoftenProgram.mFeatures.hasReflectionProbes = mShaderLevel[SHADER_DEFERRED] > 2;
gDeferredSoftenProgram.clearPermutations();
- gDeferredSoftenProgram.mShaderFiles.push_back(make_pair("deferred/softenLightV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredSoftenProgram.mShaderFiles.push_back(make_pair("deferred/softenLightF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredSoftenProgram.mShaderFiles.push_back(make_pair("deferred/softenLightV.glsl", GL_VERTEX_SHADER));
+ gDeferredSoftenProgram.mShaderFiles.push_back(make_pair("deferred/softenLightF.glsl", GL_FRAGMENT_SHADER));
gDeferredSoftenProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
+ if (use_sun_shadow)
+ {
+ gDeferredSoftenProgram.addPermutation("HAS_SUN_SHADOW", "1");
+ }
+
if (ambient_kill)
{
gDeferredSoftenProgram.addPermutation("AMBIENT_KILL", "1");
@@ -2289,6 +2406,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
if (gSavedSettings.getBOOL("RenderDeferredSSAO"))
{ //if using SSAO, take screen space light map into account as if shadows are enabled
gDeferredSoftenProgram.mShaderLevel = llmax(gDeferredSoftenProgram.mShaderLevel, 2);
+ gDeferredSoftenProgram.addPermutation("HAS_SSAO", "1");
}
success = gDeferredSoftenProgram.createShader(NULL, NULL);
@@ -2299,8 +2417,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
{
gDeferredSoftenWaterProgram.mName = "Deferred Soften Underwater Shader";
gDeferredSoftenWaterProgram.mShaderFiles.clear();
- gDeferredSoftenWaterProgram.mShaderFiles.push_back(make_pair("deferred/softenLightV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredSoftenWaterProgram.mShaderFiles.push_back(make_pair("deferred/softenLightF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredSoftenWaterProgram.mShaderFiles.push_back(make_pair("deferred/softenLightV.glsl", GL_VERTEX_SHADER));
+ gDeferredSoftenWaterProgram.mShaderFiles.push_back(make_pair("deferred/softenLightF.glsl", GL_FRAGMENT_SHADER));
gDeferredSoftenWaterProgram.clearPermutations();
gDeferredSoftenWaterProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
@@ -2314,6 +2432,12 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredSoftenWaterProgram.mFeatures.hasGamma = true;
gDeferredSoftenWaterProgram.mFeatures.isDeferred = true;
gDeferredSoftenWaterProgram.mFeatures.hasShadows = use_sun_shadow;
+ gDeferredSoftenWaterProgram.mFeatures.hasReflectionProbes = mShaderLevel[SHADER_DEFERRED] > 2;
+
+ if (use_sun_shadow)
+ {
+ gDeferredSoftenWaterProgram.addPermutation("HAS_SUN_SHADOW", "1");
+ }
if (ambient_kill)
{
@@ -2328,6 +2452,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
if (local_light_kill)
{
gDeferredSoftenWaterProgram.addPermutation("LOCAL_LIGHT_KILL", "1");
+ gDeferredSoftenWaterProgram.addPermutation("HAS_SSAO", "1");
}
if (gSavedSettings.getBOOL("RenderDeferredSSAO"))
@@ -2345,13 +2470,10 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredShadowProgram.mFeatures.isDeferred = true;
gDeferredShadowProgram.mFeatures.hasShadows = true;
gDeferredShadowProgram.mShaderFiles.clear();
- gDeferredShadowProgram.mShaderFiles.push_back(make_pair("deferred/shadowV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredShadowProgram.mShaderFiles.push_back(make_pair("deferred/shadowF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredShadowProgram.mShaderFiles.push_back(make_pair("deferred/shadowV.glsl", GL_VERTEX_SHADER));
+ gDeferredShadowProgram.mShaderFiles.push_back(make_pair("deferred/shadowF.glsl", GL_FRAGMENT_SHADER));
gDeferredShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
- if (gGLManager.mHasDepthClamp)
- {
- gDeferredShadowProgram.addPermutation("DEPTH_CLAMP", "1");
- }
+ // gDeferredShadowProgram.addPermutation("DEPTH_CLAMP", "1"); // disable depth clamp for now
gDeferredShadowProgram.mRiggedVariant = &gDeferredSkinnedShadowProgram;
success = gDeferredShadowProgram.createShader(NULL, NULL);
llassert(success);
@@ -2364,13 +2486,10 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredSkinnedShadowProgram.mFeatures.hasShadows = true;
gDeferredSkinnedShadowProgram.mFeatures.hasObjectSkinning = true;
gDeferredSkinnedShadowProgram.mShaderFiles.clear();
- gDeferredSkinnedShadowProgram.mShaderFiles.push_back(make_pair("deferred/shadowSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredSkinnedShadowProgram.mShaderFiles.push_back(make_pair("deferred/shadowF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredSkinnedShadowProgram.mShaderFiles.push_back(make_pair("deferred/shadowSkinnedV.glsl", GL_VERTEX_SHADER));
+ gDeferredSkinnedShadowProgram.mShaderFiles.push_back(make_pair("deferred/shadowF.glsl", GL_FRAGMENT_SHADER));
gDeferredSkinnedShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
- if (gGLManager.mHasDepthClamp)
- {
- gDeferredSkinnedShadowProgram.addPermutation("DEPTH_CLAMP", "1");
- }
+ // gDeferredSkinnedShadowProgram.addPermutation("DEPTH_CLAMP", "1"); // disable depth clamp for now
success = gDeferredSkinnedShadowProgram.createShader(NULL, NULL);
llassert(success);
}
@@ -2381,12 +2500,9 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredShadowCubeProgram.mFeatures.isDeferred = true;
gDeferredShadowCubeProgram.mFeatures.hasShadows = true;
gDeferredShadowCubeProgram.mShaderFiles.clear();
- gDeferredShadowCubeProgram.mShaderFiles.push_back(make_pair("deferred/shadowCubeV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredShadowCubeProgram.mShaderFiles.push_back(make_pair("deferred/shadowF.glsl", GL_FRAGMENT_SHADER_ARB));
- if (gGLManager.mHasDepthClamp)
- {
- gDeferredShadowCubeProgram.addPermutation("DEPTH_CLAMP", "1");
- }
+ gDeferredShadowCubeProgram.mShaderFiles.push_back(make_pair("deferred/shadowCubeV.glsl", GL_VERTEX_SHADER));
+ gDeferredShadowCubeProgram.mShaderFiles.push_back(make_pair("deferred/shadowF.glsl", GL_FRAGMENT_SHADER));
+ // gDeferredShadowCubeProgram.addPermutation("DEPTH_CLAMP", "1");
gDeferredShadowCubeProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
success = gDeferredShadowCubeProgram.createShader(NULL, NULL);
llassert(success);
@@ -2398,14 +2514,11 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredShadowFullbrightAlphaMaskProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
gDeferredShadowFullbrightAlphaMaskProgram.mShaderFiles.clear();
- gDeferredShadowFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredShadowFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredShadowFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskV.glsl", GL_VERTEX_SHADER));
+ gDeferredShadowFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskF.glsl", GL_FRAGMENT_SHADER));
gDeferredShadowFullbrightAlphaMaskProgram.clearPermutations();
- if (gGLManager.mHasDepthClamp)
- {
- gDeferredShadowFullbrightAlphaMaskProgram.addPermutation("DEPTH_CLAMP", "1");
- }
+ gDeferredShadowFullbrightAlphaMaskProgram.addPermutation("DEPTH_CLAMP", "1");
gDeferredShadowFullbrightAlphaMaskProgram.addPermutation("IS_FULLBRIGHT", "1");
gDeferredShadowFullbrightAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
gDeferredShadowFullbrightAlphaMaskProgram.mRiggedVariant = &gDeferredSkinnedShadowFullbrightAlphaMaskProgram;
@@ -2419,14 +2532,11 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredSkinnedShadowFullbrightAlphaMaskProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
gDeferredSkinnedShadowFullbrightAlphaMaskProgram.mFeatures.hasObjectSkinning = true;
gDeferredSkinnedShadowFullbrightAlphaMaskProgram.mShaderFiles.clear();
- gDeferredSkinnedShadowFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredSkinnedShadowFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredSkinnedShadowFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskSkinnedV.glsl", GL_VERTEX_SHADER));
+ gDeferredSkinnedShadowFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskF.glsl", GL_FRAGMENT_SHADER));
gDeferredSkinnedShadowFullbrightAlphaMaskProgram.clearPermutations();
- if (gGLManager.mHasDepthClamp)
- {
- gDeferredSkinnedShadowFullbrightAlphaMaskProgram.addPermutation("DEPTH_CLAMP", "1");
- }
+ gDeferredSkinnedShadowFullbrightAlphaMaskProgram.addPermutation("DEPTH_CLAMP", "1");
gDeferredSkinnedShadowFullbrightAlphaMaskProgram.addPermutation("IS_FULLBRIGHT", "1");
gDeferredSkinnedShadowFullbrightAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
success = gDeferredSkinnedShadowFullbrightAlphaMaskProgram.createShader(NULL, NULL);
@@ -2439,17 +2549,29 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredShadowAlphaMaskProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
gDeferredShadowAlphaMaskProgram.mShaderFiles.clear();
- gDeferredShadowAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredShadowAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskF.glsl", GL_FRAGMENT_SHADER_ARB));
- if (gGLManager.mHasDepthClamp)
- {
- gDeferredShadowAlphaMaskProgram.addPermutation("DEPTH_CLAMP", "1");
- }
+ gDeferredShadowAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskV.glsl", GL_VERTEX_SHADER));
+ gDeferredShadowAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskF.glsl", GL_FRAGMENT_SHADER));
gDeferredShadowAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
gDeferredShadowAlphaMaskProgram.mRiggedVariant = &gDeferredSkinnedShadowAlphaMaskProgram;
success = gDeferredShadowAlphaMaskProgram.createShader(NULL, NULL);
llassert(success);
}
+
+
+ if (success)
+ {
+ gDeferredShadowGLTFAlphaMaskProgram.mName = "Deferred Shadow Alpha Mask Shader";
+ gDeferredShadowGLTFAlphaMaskProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
+ gDeferredShadowGLTFAlphaMaskProgram.mShaderFiles.clear();
+ gDeferredShadowGLTFAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskV.glsl", GL_VERTEX_SHADER));
+ gDeferredShadowGLTFAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskF.glsl", GL_FRAGMENT_SHADER));
+ gDeferredShadowGLTFAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
+ gDeferredShadowGLTFAlphaMaskProgram.clearPermutations();
+ gDeferredShadowGLTFAlphaMaskProgram.addPermutation("GLTF", "1");
+ gDeferredShadowGLTFAlphaMaskProgram.mRiggedVariant = &gDeferredSkinnedShadowAlphaMaskProgram;
+ success = gDeferredShadowGLTFAlphaMaskProgram.createShader(NULL, NULL);
+ llassert(success);
+ }
if (success)
{
@@ -2457,12 +2579,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredSkinnedShadowAlphaMaskProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
gDeferredSkinnedShadowAlphaMaskProgram.mFeatures.hasObjectSkinning = true;
gDeferredSkinnedShadowAlphaMaskProgram.mShaderFiles.clear();
- gDeferredSkinnedShadowAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredSkinnedShadowAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskF.glsl", GL_FRAGMENT_SHADER_ARB));
- if (gGLManager.mHasDepthClamp)
- {
- gDeferredSkinnedShadowAlphaMaskProgram.addPermutation("DEPTH_CLAMP", "1");
- }
+ gDeferredSkinnedShadowAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskSkinnedV.glsl", GL_VERTEX_SHADER));
+ gDeferredSkinnedShadowAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskF.glsl", GL_FRAGMENT_SHADER));
gDeferredSkinnedShadowAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
success = gDeferredSkinnedShadowAlphaMaskProgram.createShader(NULL, NULL);
llassert(success);
@@ -2474,12 +2592,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredAvatarShadowProgram.mFeatures.hasSkinning = true;
gDeferredAvatarShadowProgram.mShaderFiles.clear();
- gDeferredAvatarShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarShadowV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredAvatarShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarShadowF.glsl", GL_FRAGMENT_SHADER_ARB));
- if (gGLManager.mHasDepthClamp)
- {
- gDeferredAvatarShadowProgram.addPermutation("DEPTH_CLAMP", "1");
- }
+ gDeferredAvatarShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarShadowV.glsl", GL_VERTEX_SHADER));
+ gDeferredAvatarShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarShadowF.glsl", GL_FRAGMENT_SHADER));
gDeferredAvatarShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
success = gDeferredAvatarShadowProgram.createShader(NULL, NULL);
llassert(success);
@@ -2490,22 +2604,19 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredAvatarAlphaShadowProgram.mName = "Deferred Avatar Alpha Shadow Shader";
gDeferredAvatarAlphaShadowProgram.mFeatures.hasSkinning = true;
gDeferredAvatarAlphaShadowProgram.mShaderFiles.clear();
- gDeferredAvatarAlphaShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaShadowV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredAvatarAlphaShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaShadowF.glsl", GL_FRAGMENT_SHADER_ARB));
- gDeferredAvatarAlphaShadowProgram.addPermutation("DEPTH_CLAMP", gGLManager.mHasDepthClamp ? "1" : "0");
+ gDeferredAvatarAlphaShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaShadowV.glsl", GL_VERTEX_SHADER));
+ gDeferredAvatarAlphaShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaShadowF.glsl", GL_FRAGMENT_SHADER));
gDeferredAvatarAlphaShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
success = gDeferredAvatarAlphaShadowProgram.createShader(NULL, NULL);
llassert(success);
}
-
if (success)
{
gDeferredAvatarAlphaMaskShadowProgram.mName = "Deferred Avatar Alpha Mask Shadow Shader";
gDeferredAvatarAlphaMaskShadowProgram.mFeatures.hasSkinning = true;
gDeferredAvatarAlphaMaskShadowProgram.mShaderFiles.clear();
- gDeferredAvatarAlphaMaskShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaShadowV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredAvatarAlphaMaskShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaMaskShadowF.glsl", GL_FRAGMENT_SHADER_ARB));
- gDeferredAvatarAlphaMaskShadowProgram.addPermutation("DEPTH_CLAMP", gGLManager.mHasDepthClamp ? "1" : "0");
+ gDeferredAvatarAlphaMaskShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaShadowV.glsl", GL_VERTEX_SHADER));
+ gDeferredAvatarAlphaMaskShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaMaskShadowF.glsl", GL_FRAGMENT_SHADER));
gDeferredAvatarAlphaMaskShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
success = gDeferredAvatarAlphaMaskShadowProgram.createShader(NULL, NULL);
llassert(success);
@@ -2513,49 +2624,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
if (success)
{
- gDeferredAttachmentShadowProgram.mName = "Deferred Attachment Shadow Shader";
- gDeferredAttachmentShadowProgram.mFeatures.hasObjectSkinning = true;
-
- gDeferredAttachmentShadowProgram.mShaderFiles.clear();
- gDeferredAttachmentShadowProgram.mShaderFiles.push_back(make_pair("deferred/attachmentShadowV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredAttachmentShadowProgram.mShaderFiles.push_back(make_pair("deferred/attachmentShadowF.glsl", GL_FRAGMENT_SHADER_ARB));
- if (gGLManager.mHasDepthClamp)
- {
- gDeferredAttachmentShadowProgram.addPermutation("DEPTH_CLAMP", "1");
- }
- gDeferredAttachmentShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
- success = gDeferredAttachmentShadowProgram.createShader(NULL, NULL);
- llassert(success);
- }
-
- if (success)
- {
- gDeferredAttachmentAlphaShadowProgram.mName = "Deferred Attachment Alpha Shadow Shader";
- gDeferredAttachmentAlphaShadowProgram.mFeatures.hasObjectSkinning = true;
- gDeferredAttachmentAlphaShadowProgram.mShaderFiles.clear();
- gDeferredAttachmentAlphaShadowProgram.mShaderFiles.push_back(make_pair("deferred/attachmentAlphaShadowV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredAttachmentAlphaShadowProgram.mShaderFiles.push_back(make_pair("deferred/attachmentAlphaShadowF.glsl", GL_FRAGMENT_SHADER_ARB));
- gDeferredAttachmentAlphaShadowProgram.addPermutation("DEPTH_CLAMP", gGLManager.mHasDepthClamp ? "1" : "0");
- gDeferredAttachmentAlphaShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
- success = gDeferredAttachmentAlphaShadowProgram.createShader(NULL, NULL);
- llassert(success);
- }
-
- if (success)
- {
- gDeferredAttachmentAlphaMaskShadowProgram.mName = "Deferred Attachment Alpha Mask Shadow Shader";
- gDeferredAttachmentAlphaMaskShadowProgram.mFeatures.hasObjectSkinning = true;
- gDeferredAttachmentAlphaMaskShadowProgram.mShaderFiles.clear();
- gDeferredAttachmentAlphaMaskShadowProgram.mShaderFiles.push_back(make_pair("deferred/attachmentAlphaShadowV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredAttachmentAlphaMaskShadowProgram.mShaderFiles.push_back(make_pair("deferred/attachmentAlphaMaskShadowF.glsl", GL_FRAGMENT_SHADER_ARB));
- gDeferredAttachmentAlphaMaskShadowProgram.addPermutation("DEPTH_CLAMP", gGLManager.mHasDepthClamp ? "1" : "0");
- gDeferredAttachmentAlphaMaskShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
- success = gDeferredAttachmentAlphaMaskShadowProgram.createShader(NULL, NULL);
- llassert(success);
- }
-
- if (success)
- {
gDeferredTerrainProgram.mName = "Deferred Terrain Shader";
gDeferredTerrainProgram.mFeatures.encodesNormal = true;
gDeferredTerrainProgram.mFeatures.hasSrgb = true;
@@ -2570,8 +2638,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredTerrainProgram.mFeatures.hasTransport = true;
gDeferredTerrainProgram.mShaderFiles.clear();
- gDeferredTerrainProgram.mShaderFiles.push_back(make_pair("deferred/terrainV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredTerrainProgram.mShaderFiles.push_back(make_pair("deferred/terrainF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredTerrainProgram.mShaderFiles.push_back(make_pair("deferred/terrainV.glsl", GL_VERTEX_SHADER));
+ gDeferredTerrainProgram.mShaderFiles.push_back(make_pair("deferred/terrainF.glsl", GL_FRAGMENT_SHADER));
gDeferredTerrainProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
success = gDeferredTerrainProgram.createShader(NULL, NULL);
llassert(success);
@@ -2593,8 +2661,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredTerrainWaterProgram.mFeatures.hasTransport = true;
gDeferredTerrainWaterProgram.mShaderFiles.clear();
- gDeferredTerrainWaterProgram.mShaderFiles.push_back(make_pair("deferred/terrainV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredTerrainWaterProgram.mShaderFiles.push_back(make_pair("deferred/terrainF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredTerrainWaterProgram.mShaderFiles.push_back(make_pair("deferred/terrainV.glsl", GL_VERTEX_SHADER));
+ gDeferredTerrainWaterProgram.mShaderFiles.push_back(make_pair("deferred/terrainF.glsl", GL_FRAGMENT_SHADER));
gDeferredTerrainWaterProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
gDeferredTerrainWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
gDeferredTerrainWaterProgram.addPermutation("WATER_FOG", "1");
@@ -2608,8 +2676,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredAvatarProgram.mFeatures.hasSkinning = true;
gDeferredAvatarProgram.mFeatures.encodesNormal = true;
gDeferredAvatarProgram.mShaderFiles.clear();
- gDeferredAvatarProgram.mShaderFiles.push_back(make_pair("deferred/avatarV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredAvatarProgram.mShaderFiles.push_back(make_pair("deferred/avatarF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredAvatarProgram.mShaderFiles.push_back(make_pair("deferred/avatarV.glsl", GL_VERTEX_SHADER));
+ gDeferredAvatarProgram.mShaderFiles.push_back(make_pair("deferred/avatarF.glsl", GL_FRAGMENT_SHADER));
gDeferredAvatarProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
success = gDeferredAvatarProgram.createShader(NULL, NULL);
llassert(success);
@@ -2631,17 +2699,18 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredAvatarAlphaProgram.mFeatures.hasGamma = true;
gDeferredAvatarAlphaProgram.mFeatures.isDeferred = true;
gDeferredAvatarAlphaProgram.mFeatures.hasShadows = true;
+ gDeferredAvatarAlphaProgram.mFeatures.hasReflectionProbes = true;
gDeferredAvatarAlphaProgram.mShaderFiles.clear();
- gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER));
+ gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER));
gDeferredAvatarAlphaProgram.clearPermutations();
gDeferredAvatarAlphaProgram.addPermutation("USE_DIFFUSE_TEX", "1");
gDeferredAvatarAlphaProgram.addPermutation("IS_AVATAR_SKIN", "1");
if (use_sun_shadow)
{
- gDeferredAvatarAlphaProgram.addPermutation("HAS_SHADOW", "1");
+ gDeferredAvatarAlphaProgram.addPermutation("HAS_SUN_SHADOW", "1");
}
if (ambient_kill)
@@ -2673,20 +2742,20 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredPostGammaCorrectProgram.mFeatures.hasSrgb = true;
gDeferredPostGammaCorrectProgram.mFeatures.isDeferred = true;
gDeferredPostGammaCorrectProgram.mShaderFiles.clear();
- gDeferredPostGammaCorrectProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredPostGammaCorrectProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredGammaCorrect.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredPostGammaCorrectProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER));
+ gDeferredPostGammaCorrectProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredGammaCorrect.glsl", GL_FRAGMENT_SHADER));
gDeferredPostGammaCorrectProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
success = gDeferredPostGammaCorrectProgram.createShader(NULL, NULL);
llassert(success);
}
- if (success)
+ if (success && gGLManager.mGLVersion > 3.9f)
{
gFXAAProgram.mName = "FXAA Shader";
gFXAAProgram.mFeatures.isDeferred = true;
gFXAAProgram.mShaderFiles.clear();
- gFXAAProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredV.glsl", GL_VERTEX_SHADER_ARB));
- gFXAAProgram.mShaderFiles.push_back(make_pair("deferred/fxaaF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gFXAAProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredV.glsl", GL_VERTEX_SHADER));
+ gFXAAProgram.mShaderFiles.push_back(make_pair("deferred/fxaaF.glsl", GL_FRAGMENT_SHADER));
gFXAAProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
success = gFXAAProgram.createShader(NULL, NULL);
llassert(success);
@@ -2697,8 +2766,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredPostProgram.mName = "Deferred Post Shader";
gFXAAProgram.mFeatures.isDeferred = true;
gDeferredPostProgram.mShaderFiles.clear();
- gDeferredPostProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredPostProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredPostProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER));
+ gDeferredPostProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredF.glsl", GL_FRAGMENT_SHADER));
gDeferredPostProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
success = gDeferredPostProgram.createShader(NULL, NULL);
llassert(success);
@@ -2709,8 +2778,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredCoFProgram.mName = "Deferred CoF Shader";
gDeferredCoFProgram.mShaderFiles.clear();
gDeferredCoFProgram.mFeatures.isDeferred = true;
- gDeferredCoFProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredCoFProgram.mShaderFiles.push_back(make_pair("deferred/cofF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredCoFProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER));
+ gDeferredCoFProgram.mShaderFiles.push_back(make_pair("deferred/cofF.glsl", GL_FRAGMENT_SHADER));
gDeferredCoFProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
success = gDeferredCoFProgram.createShader(NULL, NULL);
llassert(success);
@@ -2721,8 +2790,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredDoFCombineProgram.mName = "Deferred DoFCombine Shader";
gDeferredDoFCombineProgram.mFeatures.isDeferred = true;
gDeferredDoFCombineProgram.mShaderFiles.clear();
- gDeferredDoFCombineProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredDoFCombineProgram.mShaderFiles.push_back(make_pair("deferred/dofCombineF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredDoFCombineProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER));
+ gDeferredDoFCombineProgram.mShaderFiles.push_back(make_pair("deferred/dofCombineF.glsl", GL_FRAGMENT_SHADER));
gDeferredDoFCombineProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
success = gDeferredDoFCombineProgram.createShader(NULL, NULL);
llassert(success);
@@ -2733,8 +2802,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredPostNoDoFProgram.mName = "Deferred Post Shader";
gDeferredPostNoDoFProgram.mFeatures.isDeferred = true;
gDeferredPostNoDoFProgram.mShaderFiles.clear();
- gDeferredPostNoDoFProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredPostNoDoFProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoDoFF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredPostNoDoFProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER));
+ gDeferredPostNoDoFProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoDoFF.glsl", GL_FRAGMENT_SHADER));
gDeferredPostNoDoFProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
success = gDeferredPostNoDoFProgram.createShader(NULL, NULL);
llassert(success);
@@ -2749,8 +2818,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredWLSkyProgram.mFeatures.hasGamma = true;
gDeferredWLSkyProgram.mFeatures.hasSrgb = true;
- gDeferredWLSkyProgram.mShaderFiles.push_back(make_pair("deferred/skyV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredWLSkyProgram.mShaderFiles.push_back(make_pair("deferred/skyF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredWLSkyProgram.mShaderFiles.push_back(make_pair("deferred/skyV.glsl", GL_VERTEX_SHADER));
+ gDeferredWLSkyProgram.mShaderFiles.push_back(make_pair("deferred/skyF.glsl", GL_FRAGMENT_SHADER));
gDeferredWLSkyProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
gDeferredWLSkyProgram.mShaderGroup = LLGLSLShader::SG_SKY;
@@ -2767,10 +2836,11 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredWLCloudProgram.mFeatures.hasGamma = true;
gDeferredWLCloudProgram.mFeatures.hasSrgb = true;
- gDeferredWLCloudProgram.mShaderFiles.push_back(make_pair("deferred/cloudsV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredWLCloudProgram.mShaderFiles.push_back(make_pair("deferred/cloudsF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredWLCloudProgram.mShaderFiles.push_back(make_pair("deferred/cloudsV.glsl", GL_VERTEX_SHADER));
+ gDeferredWLCloudProgram.mShaderFiles.push_back(make_pair("deferred/cloudsF.glsl", GL_FRAGMENT_SHADER));
gDeferredWLCloudProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
gDeferredWLCloudProgram.mShaderGroup = LLGLSLShader::SG_SKY;
+ gDeferredWLCloudProgram.addConstant( LLGLSLShader::SHADER_CONST_CLOUD_MOON_DEPTH ); // SL-14113
success = gDeferredWLCloudProgram.createShader(NULL, NULL);
llassert(success);
}
@@ -2786,8 +2856,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredWLSunProgram.mFeatures.disableTextureIndex = true;
gDeferredWLSunProgram.mFeatures.hasSrgb = true;
gDeferredWLSunProgram.mShaderFiles.clear();
- gDeferredWLSunProgram.mShaderFiles.push_back(make_pair("deferred/sunDiscV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredWLSunProgram.mShaderFiles.push_back(make_pair("deferred/sunDiscF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredWLSunProgram.mShaderFiles.push_back(make_pair("deferred/sunDiscV.glsl", GL_VERTEX_SHADER));
+ gDeferredWLSunProgram.mShaderFiles.push_back(make_pair("deferred/sunDiscF.glsl", GL_FRAGMENT_SHADER));
gDeferredWLSunProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
gDeferredWLSunProgram.mShaderGroup = LLGLSLShader::SG_SKY;
success = gDeferredWLSunProgram.createShader(NULL, NULL);
@@ -2806,10 +2876,11 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredWLMoonProgram.mFeatures.disableTextureIndex = true;
gDeferredWLMoonProgram.mShaderFiles.clear();
- gDeferredWLMoonProgram.mShaderFiles.push_back(make_pair("deferred/moonV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredWLMoonProgram.mShaderFiles.push_back(make_pair("deferred/moonF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredWLMoonProgram.mShaderFiles.push_back(make_pair("deferred/moonV.glsl", GL_VERTEX_SHADER));
+ gDeferredWLMoonProgram.mShaderFiles.push_back(make_pair("deferred/moonF.glsl", GL_FRAGMENT_SHADER));
gDeferredWLMoonProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
gDeferredWLMoonProgram.mShaderGroup = LLGLSLShader::SG_SKY;
+ gDeferredWLMoonProgram.addConstant( LLGLSLShader::SHADER_CONST_CLOUD_MOON_DEPTH ); // SL-14113
success = gDeferredWLMoonProgram.createShader(NULL, NULL);
llassert(success);
}
@@ -2818,10 +2889,11 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
{
gDeferredStarProgram.mName = "Deferred Star Program";
gDeferredStarProgram.mShaderFiles.clear();
- gDeferredStarProgram.mShaderFiles.push_back(make_pair("deferred/starsV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredStarProgram.mShaderFiles.push_back(make_pair("deferred/starsF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredStarProgram.mShaderFiles.push_back(make_pair("deferred/starsV.glsl", GL_VERTEX_SHADER));
+ gDeferredStarProgram.mShaderFiles.push_back(make_pair("deferred/starsF.glsl", GL_FRAGMENT_SHADER));
gDeferredStarProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
gDeferredStarProgram.mShaderGroup = LLGLSLShader::SG_SKY;
+ gDeferredStarProgram.addConstant( LLGLSLShader::SHADER_CONST_STAR_DEPTH ); // SL-14113
success = gDeferredStarProgram.createShader(NULL, NULL);
llassert(success);
}
@@ -2830,21 +2902,119 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
{
gNormalMapGenProgram.mName = "Normal Map Generation Program";
gNormalMapGenProgram.mShaderFiles.clear();
- gNormalMapGenProgram.mShaderFiles.push_back(make_pair("deferred/normgenV.glsl", GL_VERTEX_SHADER_ARB));
- gNormalMapGenProgram.mShaderFiles.push_back(make_pair("deferred/normgenF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gNormalMapGenProgram.mShaderFiles.push_back(make_pair("deferred/normgenV.glsl", GL_VERTEX_SHADER));
+ gNormalMapGenProgram.mShaderFiles.push_back(make_pair("deferred/normgenF.glsl", GL_FRAGMENT_SHADER));
gNormalMapGenProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
gNormalMapGenProgram.mShaderGroup = LLGLSLShader::SG_SKY;
success = gNormalMapGenProgram.createShader(NULL, NULL);
}
+ if (success)
+ {
+ gDeferredGenBrdfLutProgram.mName = "Brdf Gen Shader";
+ gDeferredGenBrdfLutProgram.mShaderFiles.clear();
+ gDeferredGenBrdfLutProgram.mShaderFiles.push_back(make_pair("deferred/genbrdflutV.glsl", GL_VERTEX_SHADER));
+ gDeferredGenBrdfLutProgram.mShaderFiles.push_back(make_pair("deferred/genbrdflutF.glsl", GL_FRAGMENT_SHADER));
+ gDeferredGenBrdfLutProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
+ success = gDeferredGenBrdfLutProgram.createShader(NULL, NULL);
+ }
+
+ if (success) {
+ gPostScreenSpaceReflectionProgram.mName = "Screen Space Reflection Post";
+ gPostScreenSpaceReflectionProgram.mShaderFiles.clear();
+ gPostScreenSpaceReflectionProgram.mShaderFiles.push_back(make_pair("deferred/screenSpaceReflPostV.glsl", GL_VERTEX_SHADER));
+ gPostScreenSpaceReflectionProgram.mShaderFiles.push_back(make_pair("deferred/screenSpaceReflPostF.glsl", GL_FRAGMENT_SHADER));
+ gPostScreenSpaceReflectionProgram.mFeatures.hasScreenSpaceReflections = true;
+ gPostScreenSpaceReflectionProgram.mFeatures.isDeferred = true;
+ gPostScreenSpaceReflectionProgram.mShaderLevel = 3;
+ success = gPostScreenSpaceReflectionProgram.createShader(NULL, NULL);
+ }
+
return success;
}
BOOL LLViewerShaderMgr::loadShadersObject()
{
+ LL_PROFILE_ZONE_SCOPED;
BOOL success = TRUE;
- if (success)
+ if (success)
+ {
+ gObjectBumpProgram.mName = "Bump Shader";
+ gObjectBumpProgram.mFeatures.encodesNormal = true;
+ gObjectBumpProgram.mShaderFiles.clear();
+ gObjectBumpProgram.mShaderFiles.push_back(make_pair("objects/bumpV.glsl", GL_VERTEX_SHADER));
+ gObjectBumpProgram.mShaderFiles.push_back(make_pair("objects/bumpF.glsl", GL_FRAGMENT_SHADER));
+ gObjectBumpProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
+ success = make_rigged_variant(gObjectBumpProgram, gSkinnedObjectBumpProgram);
+ success = success && gObjectBumpProgram.createShader(NULL, NULL);
+ if (success)
+ { //lldrawpoolbump assumes "texture0" has channel 0 and "texture1" has channel 1
+ LLGLSLShader* shader[] = { &gObjectBumpProgram, &gSkinnedObjectBumpProgram };
+ for (int i = 0; i < 2; ++i)
+ {
+ shader[i]->bind();
+ shader[i]->uniform1i(sTexture0, 0);
+ shader[i]->uniform1i(sTexture1, 1);
+ shader[i]->unbind();
+ }
+ }
+ }
+
+ if (success)
+ {
+ gObjectSimpleProgram.mName = "Simple Shader";
+ gObjectSimpleProgram.mFeatures.calculatesLighting = true;
+ gObjectSimpleProgram.mFeatures.calculatesAtmospherics = true;
+ gObjectSimpleProgram.mFeatures.hasGamma = true;
+ gObjectSimpleProgram.mFeatures.hasAtmospherics = true;
+ gObjectSimpleProgram.mFeatures.hasLighting = true;
+ gObjectSimpleProgram.mFeatures.mIndexedTextureChannels = 0;
+ gObjectSimpleProgram.mShaderFiles.clear();
+ gObjectSimpleProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER));
+ gObjectSimpleProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER));
+ gObjectSimpleProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
+ success = make_rigged_variant(gObjectSimpleProgram, gSkinnedObjectSimpleProgram);
+ success = success && gObjectSimpleProgram.createShader(NULL, NULL);
+ }
+
+ if (success)
+ {
+ gObjectFullbrightProgram.mName = "Fullbright Shader";
+ gObjectFullbrightProgram.mFeatures.calculatesAtmospherics = true;
+ gObjectFullbrightProgram.mFeatures.hasGamma = true;
+ gObjectFullbrightProgram.mFeatures.hasTransport = true;
+ gObjectFullbrightProgram.mFeatures.isFullbright = true;
+ gObjectFullbrightProgram.mFeatures.hasSrgb = true;
+ gObjectFullbrightProgram.mFeatures.mIndexedTextureChannels = 0;
+ gObjectFullbrightProgram.mShaderFiles.clear();
+ gObjectFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER));
+ gObjectFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER));
+ gObjectFullbrightProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
+ success = make_rigged_variant(gObjectFullbrightProgram, gSkinnedObjectFullbrightProgram);
+ success = success && gObjectFullbrightProgram.createShader(NULL, NULL);
+ }
+
+ if (success)
+ {
+ gObjectFullbrightShinyWaterProgram.mName = "Fullbright Shiny Water Shader";
+ gObjectFullbrightShinyWaterProgram.mFeatures.calculatesAtmospherics = true;
+ gObjectFullbrightShinyWaterProgram.mFeatures.isFullbright = true;
+ gObjectFullbrightShinyWaterProgram.mFeatures.isShiny = true;
+ gObjectFullbrightShinyWaterProgram.mFeatures.hasGamma = true;
+ gObjectFullbrightShinyWaterProgram.mFeatures.hasTransport = true;
+ gObjectFullbrightShinyWaterProgram.mFeatures.hasWaterFog = true;
+ gObjectFullbrightShinyWaterProgram.mFeatures.mIndexedTextureChannels = 0;
+ gObjectFullbrightShinyWaterProgram.mShaderFiles.clear();
+ gObjectFullbrightShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyV.glsl", GL_VERTEX_SHADER));
+ gObjectFullbrightShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyWaterF.glsl", GL_FRAGMENT_SHADER));
+ gObjectFullbrightShinyWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
+ gObjectFullbrightShinyWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
+ success = make_rigged_variant(gObjectFullbrightShinyWaterProgram, gSkinnedObjectFullbrightShinyWaterProgram);
+ success = success && gObjectFullbrightShinyWaterProgram.createShader(NULL, NULL);
+ }
+
+ if (success)
{
gObjectSimpleNonIndexedTexGenProgram.mName = "Non indexed tex-gen Shader";
gObjectSimpleNonIndexedTexGenProgram.mFeatures.calculatesLighting = true;
@@ -2854,8 +3024,8 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gObjectSimpleNonIndexedTexGenProgram.mFeatures.hasLighting = true;
gObjectSimpleNonIndexedTexGenProgram.mFeatures.disableTextureIndex = true;
gObjectSimpleNonIndexedTexGenProgram.mShaderFiles.clear();
- gObjectSimpleNonIndexedTexGenProgram.mShaderFiles.push_back(make_pair("objects/simpleTexGenV.glsl", GL_VERTEX_SHADER_ARB));
- gObjectSimpleNonIndexedTexGenProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gObjectSimpleNonIndexedTexGenProgram.mShaderFiles.push_back(make_pair("objects/simpleTexGenV.glsl", GL_VERTEX_SHADER));
+ gObjectSimpleNonIndexedTexGenProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER));
gObjectSimpleNonIndexedTexGenProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
success = gObjectSimpleNonIndexedTexGenProgram.createShader(NULL, NULL);
}
@@ -2870,13 +3040,15 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gObjectSimpleNonIndexedTexGenWaterProgram.mFeatures.hasLighting = true;
gObjectSimpleNonIndexedTexGenWaterProgram.mFeatures.disableTextureIndex = true;
gObjectSimpleNonIndexedTexGenWaterProgram.mShaderFiles.clear();
- gObjectSimpleNonIndexedTexGenWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleTexGenV.glsl", GL_VERTEX_SHADER_ARB));
- gObjectSimpleNonIndexedTexGenWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gObjectSimpleNonIndexedTexGenWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleTexGenV.glsl", GL_VERTEX_SHADER));
+ gObjectSimpleNonIndexedTexGenWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER));
gObjectSimpleNonIndexedTexGenWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
gObjectSimpleNonIndexedTexGenWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
success = gObjectSimpleNonIndexedTexGenWaterProgram.createShader(NULL, NULL);
}
+#if 1 // DEPRECATED -- forward rendering is deprecated
+
if (success)
{
gObjectAlphaMaskNonIndexedProgram.mName = "Non indexed alpha mask Shader";
@@ -2888,8 +3060,8 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gObjectAlphaMaskNonIndexedProgram.mFeatures.disableTextureIndex = true;
gObjectAlphaMaskNonIndexedProgram.mFeatures.hasAlphaMask = true;
gObjectAlphaMaskNonIndexedProgram.mShaderFiles.clear();
- gObjectAlphaMaskNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/simpleNonIndexedV.glsl", GL_VERTEX_SHADER_ARB));
- gObjectAlphaMaskNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gObjectAlphaMaskNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/simpleNonIndexedV.glsl", GL_VERTEX_SHADER));
+ gObjectAlphaMaskNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER));
gObjectAlphaMaskNonIndexedProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
success = gObjectAlphaMaskNonIndexedProgram.createShader(NULL, NULL);
}
@@ -2905,8 +3077,8 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gObjectAlphaMaskNonIndexedWaterProgram.mFeatures.disableTextureIndex = true;
gObjectAlphaMaskNonIndexedWaterProgram.mFeatures.hasAlphaMask = true;
gObjectAlphaMaskNonIndexedWaterProgram.mShaderFiles.clear();
- gObjectAlphaMaskNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleNonIndexedV.glsl", GL_VERTEX_SHADER_ARB));
- gObjectAlphaMaskNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gObjectAlphaMaskNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleNonIndexedV.glsl", GL_VERTEX_SHADER));
+ gObjectAlphaMaskNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER));
gObjectAlphaMaskNonIndexedWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
gObjectAlphaMaskNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
success = gObjectAlphaMaskNonIndexedWaterProgram.createShader(NULL, NULL);
@@ -2923,8 +3095,8 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gObjectAlphaMaskNoColorProgram.mFeatures.disableTextureIndex = true;
gObjectAlphaMaskNoColorProgram.mFeatures.hasAlphaMask = true;
gObjectAlphaMaskNoColorProgram.mShaderFiles.clear();
- gObjectAlphaMaskNoColorProgram.mShaderFiles.push_back(make_pair("objects/simpleNoColorV.glsl", GL_VERTEX_SHADER_ARB));
- gObjectAlphaMaskNoColorProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gObjectAlphaMaskNoColorProgram.mShaderFiles.push_back(make_pair("objects/simpleNoColorV.glsl", GL_VERTEX_SHADER));
+ gObjectAlphaMaskNoColorProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER));
gObjectAlphaMaskNoColorProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
success = gObjectAlphaMaskNoColorProgram.createShader(NULL, NULL);
}
@@ -2940,8 +3112,8 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gObjectAlphaMaskNoColorWaterProgram.mFeatures.disableTextureIndex = true;
gObjectAlphaMaskNoColorWaterProgram.mFeatures.hasAlphaMask = true;
gObjectAlphaMaskNoColorWaterProgram.mShaderFiles.clear();
- gObjectAlphaMaskNoColorWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleNoColorV.glsl", GL_VERTEX_SHADER_ARB));
- gObjectAlphaMaskNoColorWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gObjectAlphaMaskNoColorWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleNoColorV.glsl", GL_VERTEX_SHADER));
+ gObjectAlphaMaskNoColorWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER));
gObjectAlphaMaskNoColorWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
gObjectAlphaMaskNoColorWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
success = gObjectAlphaMaskNoColorWaterProgram.createShader(NULL, NULL);
@@ -2958,8 +3130,8 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gTreeProgram.mFeatures.disableTextureIndex = true;
gTreeProgram.mFeatures.hasAlphaMask = true;
gTreeProgram.mShaderFiles.clear();
- gTreeProgram.mShaderFiles.push_back(make_pair("objects/treeV.glsl", GL_VERTEX_SHADER_ARB));
- gTreeProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gTreeProgram.mShaderFiles.push_back(make_pair("objects/treeV.glsl", GL_VERTEX_SHADER));
+ gTreeProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER));
gTreeProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
success = gTreeProgram.createShader(NULL, NULL);
}
@@ -2975,8 +3147,8 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gTreeWaterProgram.mFeatures.disableTextureIndex = true;
gTreeWaterProgram.mFeatures.hasAlphaMask = true;
gTreeWaterProgram.mShaderFiles.clear();
- gTreeWaterProgram.mShaderFiles.push_back(make_pair("objects/treeV.glsl", GL_VERTEX_SHADER_ARB));
- gTreeWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gTreeWaterProgram.mShaderFiles.push_back(make_pair("objects/treeV.glsl", GL_VERTEX_SHADER));
+ gTreeWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER));
gTreeWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
gTreeWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
success = gTreeWaterProgram.createShader(NULL, NULL);
@@ -2992,8 +3164,8 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gObjectFullbrightNoColorProgram.mFeatures.hasSrgb = true;
gObjectFullbrightNoColorProgram.mFeatures.disableTextureIndex = true;
gObjectFullbrightNoColorProgram.mShaderFiles.clear();
- gObjectFullbrightNoColorProgram.mShaderFiles.push_back(make_pair("objects/fullbrightNoColorV.glsl", GL_VERTEX_SHADER_ARB));
- gObjectFullbrightNoColorProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gObjectFullbrightNoColorProgram.mShaderFiles.push_back(make_pair("objects/fullbrightNoColorV.glsl", GL_VERTEX_SHADER));
+ gObjectFullbrightNoColorProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER));
gObjectFullbrightNoColorProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
success = gObjectFullbrightNoColorProgram.createShader(NULL, NULL);
}
@@ -3007,8 +3179,8 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gObjectFullbrightNoColorWaterProgram.mFeatures.hasTransport = true;
gObjectFullbrightNoColorWaterProgram.mFeatures.disableTextureIndex = true;
gObjectFullbrightNoColorWaterProgram.mShaderFiles.clear();
- gObjectFullbrightNoColorWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightNoColorV.glsl", GL_VERTEX_SHADER_ARB));
- gObjectFullbrightNoColorWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gObjectFullbrightNoColorWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightNoColorV.glsl", GL_VERTEX_SHADER));
+ gObjectFullbrightNoColorWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER));
gObjectFullbrightNoColorWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
gObjectFullbrightNoColorWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
success = gObjectFullbrightNoColorWaterProgram.createShader(NULL, NULL);
@@ -3020,8 +3192,8 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gImpostorProgram.mFeatures.disableTextureIndex = true;
gImpostorProgram.mFeatures.hasSrgb = true;
gImpostorProgram.mShaderFiles.clear();
- gImpostorProgram.mShaderFiles.push_back(make_pair("objects/impostorV.glsl", GL_VERTEX_SHADER_ARB));
- gImpostorProgram.mShaderFiles.push_back(make_pair("objects/impostorF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gImpostorProgram.mShaderFiles.push_back(make_pair("objects/impostorV.glsl", GL_VERTEX_SHADER));
+ gImpostorProgram.mShaderFiles.push_back(make_pair("objects/impostorF.glsl", GL_FRAGMENT_SHADER));
gImpostorProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
success = gImpostorProgram.createShader(NULL, NULL);
}
@@ -3037,8 +3209,8 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gObjectPreviewProgram.mFeatures.mIndexedTextureChannels = 0;
gObjectPreviewProgram.mFeatures.disableTextureIndex = true;
gObjectPreviewProgram.mShaderFiles.clear();
- gObjectPreviewProgram.mShaderFiles.push_back(make_pair("objects/previewV.glsl", GL_VERTEX_SHADER_ARB));
- gObjectPreviewProgram.mShaderFiles.push_back(make_pair("objects/previewF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gObjectPreviewProgram.mShaderFiles.push_back(make_pair("objects/previewV.glsl", GL_VERTEX_SHADER));
+ gObjectPreviewProgram.mShaderFiles.push_back(make_pair("objects/previewF.glsl", GL_FRAGMENT_SHADER));
gObjectPreviewProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
success = gObjectPreviewProgram.createShader(NULL, NULL);
gObjectPreviewProgram.mFeatures.hasLighting = true;
@@ -3055,8 +3227,8 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gPhysicsPreviewProgram.mFeatures.mIndexedTextureChannels = 0;
gPhysicsPreviewProgram.mFeatures.disableTextureIndex = true;
gPhysicsPreviewProgram.mShaderFiles.clear();
- gPhysicsPreviewProgram.mShaderFiles.push_back(make_pair("objects/previewPhysicsV.glsl", GL_VERTEX_SHADER_ARB));
- gPhysicsPreviewProgram.mShaderFiles.push_back(make_pair("objects/previewPhysicsF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gPhysicsPreviewProgram.mShaderFiles.push_back(make_pair("objects/previewPhysicsV.glsl", GL_VERTEX_SHADER));
+ gPhysicsPreviewProgram.mShaderFiles.push_back(make_pair("objects/previewPhysicsF.glsl", GL_FRAGMENT_SHADER));
gPhysicsPreviewProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
success = gPhysicsPreviewProgram.createShader(NULL, NULL);
gPhysicsPreviewProgram.mFeatures.hasLighting = false;
@@ -3064,23 +3236,6 @@ BOOL LLViewerShaderMgr::loadShadersObject()
if (success)
{
- gObjectSimpleProgram.mName = "Simple Shader";
- gObjectSimpleProgram.mFeatures.calculatesLighting = true;
- gObjectSimpleProgram.mFeatures.calculatesAtmospherics = true;
- gObjectSimpleProgram.mFeatures.hasGamma = true;
- gObjectSimpleProgram.mFeatures.hasAtmospherics = true;
- gObjectSimpleProgram.mFeatures.hasLighting = true;
- gObjectSimpleProgram.mFeatures.mIndexedTextureChannels = 0;
- gObjectSimpleProgram.mShaderFiles.clear();
- gObjectSimpleProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB));
- gObjectSimpleProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB));
- gObjectSimpleProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
- success = make_rigged_variant(gObjectSimpleProgram, gSkinnedObjectSimpleProgram);
- success = success && gObjectSimpleProgram.createShader(NULL, NULL);
- }
-
- if (success)
- {
gObjectSimpleImpostorProgram.mName = "Simple Impostor Shader";
gObjectSimpleImpostorProgram.mFeatures.calculatesLighting = true;
gObjectSimpleImpostorProgram.mFeatures.calculatesAtmospherics = true;
@@ -3093,8 +3248,8 @@ BOOL LLViewerShaderMgr::loadShadersObject()
//
gObjectSimpleImpostorProgram.mFeatures.hasAlphaMask = true;
gObjectSimpleImpostorProgram.mShaderFiles.clear();
- gObjectSimpleImpostorProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB));
- gObjectSimpleImpostorProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gObjectSimpleImpostorProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER));
+ gObjectSimpleImpostorProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER));
gObjectSimpleImpostorProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
success = make_rigged_variant(gObjectSimpleImpostorProgram, gSkinnedObjectSimpleImpostorProgram);
success = success && gObjectSimpleImpostorProgram.createShader(NULL, NULL);
@@ -3110,8 +3265,8 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gObjectSimpleWaterProgram.mFeatures.hasLighting = true;
gObjectSimpleWaterProgram.mFeatures.mIndexedTextureChannels = 0;
gObjectSimpleWaterProgram.mShaderFiles.clear();
- gObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB));
- gObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER));
+ gObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER));
gObjectSimpleWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
gObjectSimpleWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
make_rigged_variant(gObjectSimpleWaterProgram, gSkinnedObjectSimpleWaterProgram);
@@ -3120,30 +3275,6 @@ BOOL LLViewerShaderMgr::loadShadersObject()
if (success)
{
- gObjectBumpProgram.mName = "Bump Shader";
- gObjectBumpProgram.mFeatures.encodesNormal = true;
- gObjectBumpProgram.mShaderFiles.clear();
- gObjectBumpProgram.mShaderFiles.push_back(make_pair("objects/bumpV.glsl", GL_VERTEX_SHADER_ARB));
- gObjectBumpProgram.mShaderFiles.push_back(make_pair("objects/bumpF.glsl", GL_FRAGMENT_SHADER_ARB));
- gObjectBumpProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
- success = make_rigged_variant(gObjectBumpProgram, gSkinnedObjectBumpProgram);
- success = success && gObjectBumpProgram.createShader(NULL, NULL);
- if (success)
- { //lldrawpoolbump assumes "texture0" has channel 0 and "texture1" has channel 1
- LLGLSLShader* shader[] = { &gObjectBumpProgram, &gSkinnedObjectBumpProgram };
- for (int i = 0; i < 2; ++i)
- {
- shader[i]->bind();
- shader[i]->uniform1i(sTexture0, 0);
- shader[i]->uniform1i(sTexture1, 1);
- shader[i]->unbind();
- }
- }
- }
-
-
- if (success)
- {
gObjectSimpleAlphaMaskProgram.mName = "Simple Alpha Mask Shader";
gObjectSimpleAlphaMaskProgram.mFeatures.calculatesLighting = true;
gObjectSimpleAlphaMaskProgram.mFeatures.calculatesAtmospherics = true;
@@ -3153,8 +3284,8 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gObjectSimpleAlphaMaskProgram.mFeatures.hasAlphaMask = true;
gObjectSimpleAlphaMaskProgram.mFeatures.mIndexedTextureChannels = 0;
gObjectSimpleAlphaMaskProgram.mShaderFiles.clear();
- gObjectSimpleAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB));
- gObjectSimpleAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gObjectSimpleAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER));
+ gObjectSimpleAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER));
gObjectSimpleAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
success = make_rigged_variant(gObjectSimpleAlphaMaskProgram, gSkinnedObjectSimpleAlphaMaskProgram);
success = success && gObjectSimpleAlphaMaskProgram.createShader(NULL, NULL);
@@ -3171,8 +3302,8 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gObjectSimpleWaterAlphaMaskProgram.mFeatures.hasAlphaMask = true;
gObjectSimpleWaterAlphaMaskProgram.mFeatures.mIndexedTextureChannels = 0;
gObjectSimpleWaterAlphaMaskProgram.mShaderFiles.clear();
- gObjectSimpleWaterAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB));
- gObjectSimpleWaterAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gObjectSimpleWaterAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER));
+ gObjectSimpleWaterAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER));
gObjectSimpleWaterAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
gObjectSimpleWaterAlphaMaskProgram.mShaderGroup = LLGLSLShader::SG_WATER;
success = make_rigged_variant(gObjectSimpleWaterAlphaMaskProgram, gSkinnedObjectSimpleWaterAlphaMaskProgram);
@@ -3181,23 +3312,6 @@ BOOL LLViewerShaderMgr::loadShadersObject()
if (success)
{
- gObjectFullbrightProgram.mName = "Fullbright Shader";
- gObjectFullbrightProgram.mFeatures.calculatesAtmospherics = true;
- gObjectFullbrightProgram.mFeatures.hasGamma = true;
- gObjectFullbrightProgram.mFeatures.hasTransport = true;
- gObjectFullbrightProgram.mFeatures.isFullbright = true;
- gObjectFullbrightProgram.mFeatures.hasSrgb = true;
- gObjectFullbrightProgram.mFeatures.mIndexedTextureChannels = 0;
- gObjectFullbrightProgram.mShaderFiles.clear();
- gObjectFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB));
- gObjectFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB));
- gObjectFullbrightProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
- success = make_rigged_variant(gObjectFullbrightProgram, gSkinnedObjectFullbrightProgram);
- success = success && gObjectFullbrightProgram.createShader(NULL, NULL);
- }
-
- if (success)
- {
gObjectFullbrightWaterProgram.mName = "Fullbright Water Shader";
gObjectFullbrightWaterProgram.mFeatures.calculatesAtmospherics = true;
gObjectFullbrightWaterProgram.mFeatures.isFullbright = true;
@@ -3205,8 +3319,8 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gObjectFullbrightWaterProgram.mFeatures.hasTransport = true;
gObjectFullbrightWaterProgram.mFeatures.mIndexedTextureChannels = 0;
gObjectFullbrightWaterProgram.mShaderFiles.clear();
- gObjectFullbrightWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB));
- gObjectFullbrightWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gObjectFullbrightWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER));
+ gObjectFullbrightWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER));
gObjectFullbrightWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
gObjectFullbrightWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
success = make_rigged_variant(gObjectFullbrightWaterProgram, gSkinnedObjectFullbrightWaterProgram);
@@ -3223,8 +3337,8 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gObjectEmissiveProgram.mFeatures.hasSrgb = true;
gObjectEmissiveProgram.mFeatures.mIndexedTextureChannels = 0;
gObjectEmissiveProgram.mShaderFiles.clear();
- gObjectEmissiveProgram.mShaderFiles.push_back(make_pair("objects/emissiveV.glsl", GL_VERTEX_SHADER_ARB));
- gObjectEmissiveProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gObjectEmissiveProgram.mShaderFiles.push_back(make_pair("objects/emissiveV.glsl", GL_VERTEX_SHADER));
+ gObjectEmissiveProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER));
gObjectEmissiveProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
success = make_rigged_variant(gObjectEmissiveProgram, gSkinnedObjectEmissiveProgram);
success = success && gObjectEmissiveProgram.createShader(NULL, NULL);
@@ -3239,8 +3353,8 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gObjectEmissiveWaterProgram.mFeatures.hasTransport = true;
gObjectEmissiveWaterProgram.mFeatures.mIndexedTextureChannels = 0;
gObjectEmissiveWaterProgram.mShaderFiles.clear();
- gObjectEmissiveWaterProgram.mShaderFiles.push_back(make_pair("objects/emissiveV.glsl", GL_VERTEX_SHADER_ARB));
- gObjectEmissiveWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gObjectEmissiveWaterProgram.mShaderFiles.push_back(make_pair("objects/emissiveV.glsl", GL_VERTEX_SHADER));
+ gObjectEmissiveWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER));
gObjectEmissiveWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
gObjectEmissiveWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
success = make_rigged_variant(gObjectEmissiveWaterProgram, gSkinnedObjectEmissiveWaterProgram);
@@ -3258,8 +3372,8 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gObjectFullbrightAlphaMaskProgram.mFeatures.hasSrgb = true;
gObjectFullbrightAlphaMaskProgram.mFeatures.mIndexedTextureChannels = 0;
gObjectFullbrightAlphaMaskProgram.mShaderFiles.clear();
- gObjectFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB));
- gObjectFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gObjectFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER));
+ gObjectFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER));
gObjectFullbrightAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
success = make_rigged_variant(gObjectFullbrightAlphaMaskProgram, gSkinnedObjectFullbrightAlphaMaskProgram);
success = success && gObjectFullbrightAlphaMaskProgram.createShader(NULL, NULL);
@@ -3275,8 +3389,8 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gObjectFullbrightWaterAlphaMaskProgram.mFeatures.hasAlphaMask = true;
gObjectFullbrightWaterAlphaMaskProgram.mFeatures.mIndexedTextureChannels = 0;
gObjectFullbrightWaterAlphaMaskProgram.mShaderFiles.clear();
- gObjectFullbrightWaterAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB));
- gObjectFullbrightWaterAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gObjectFullbrightWaterAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER));
+ gObjectFullbrightWaterAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER));
gObjectFullbrightWaterAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
gObjectFullbrightWaterAlphaMaskProgram.mShaderGroup = LLGLSLShader::SG_WATER;
success = make_rigged_variant(gObjectFullbrightWaterAlphaMaskProgram, gSkinnedObjectFullbrightWaterAlphaMaskProgram);
@@ -3293,8 +3407,8 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gObjectShinyProgram.mFeatures.isShiny = true;
gObjectShinyProgram.mFeatures.mIndexedTextureChannels = 0;
gObjectShinyProgram.mShaderFiles.clear();
- gObjectShinyProgram.mShaderFiles.push_back(make_pair("objects/shinyV.glsl", GL_VERTEX_SHADER_ARB));
- gObjectShinyProgram.mShaderFiles.push_back(make_pair("objects/shinyF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gObjectShinyProgram.mShaderFiles.push_back(make_pair("objects/shinyV.glsl", GL_VERTEX_SHADER));
+ gObjectShinyProgram.mShaderFiles.push_back(make_pair("objects/shinyF.glsl", GL_FRAGMENT_SHADER));
gObjectShinyProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
success = make_rigged_variant(gObjectShinyProgram, gSkinnedObjectShinyProgram);
success = success && gObjectShinyProgram.createShader(NULL, NULL);
@@ -3310,8 +3424,8 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gObjectShinyWaterProgram.mFeatures.hasAtmospherics = true;
gObjectShinyWaterProgram.mFeatures.mIndexedTextureChannels = 0;
gObjectShinyWaterProgram.mShaderFiles.clear();
- gObjectShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
- gObjectShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyV.glsl", GL_VERTEX_SHADER_ARB));
+ gObjectShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyWaterF.glsl", GL_FRAGMENT_SHADER));
+ gObjectShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyV.glsl", GL_VERTEX_SHADER));
gObjectShinyWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
gObjectShinyWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
success = make_rigged_variant(gObjectShinyWaterProgram, gSkinnedObjectShinyWaterProgram);
@@ -3328,43 +3442,28 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gObjectFullbrightShinyProgram.mFeatures.hasTransport = true;
gObjectFullbrightShinyProgram.mFeatures.mIndexedTextureChannels = 0;
gObjectFullbrightShinyProgram.mShaderFiles.clear();
- gObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB));
- gObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyV.glsl", GL_VERTEX_SHADER));
+ gObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER));
gObjectFullbrightShinyProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
success = make_rigged_variant(gObjectFullbrightShinyProgram, gSkinnedObjectFullbrightShinyProgram);
success = success && gObjectFullbrightShinyProgram.createShader(NULL, NULL);
}
- if (success)
- {
- gObjectFullbrightShinyWaterProgram.mName = "Fullbright Shiny Water Shader";
- gObjectFullbrightShinyWaterProgram.mFeatures.calculatesAtmospherics = true;
- gObjectFullbrightShinyWaterProgram.mFeatures.isFullbright = true;
- gObjectFullbrightShinyWaterProgram.mFeatures.isShiny = true;
- gObjectFullbrightShinyWaterProgram.mFeatures.hasGamma = true;
- gObjectFullbrightShinyWaterProgram.mFeatures.hasTransport = true;
- gObjectFullbrightShinyWaterProgram.mFeatures.hasWaterFog = true;
- gObjectFullbrightShinyWaterProgram.mFeatures.mIndexedTextureChannels = 0;
- gObjectFullbrightShinyWaterProgram.mShaderFiles.clear();
- gObjectFullbrightShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB));
- gObjectFullbrightShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
- gObjectFullbrightShinyWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
- gObjectFullbrightShinyWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
- success = make_rigged_variant(gObjectFullbrightShinyWaterProgram, gSkinnedObjectFullbrightShinyWaterProgram);
- success = success && gObjectFullbrightShinyWaterProgram.createShader(NULL, NULL);
- }
+#endif
+
+ if (!success)
+ {
+ mShaderLevel[SHADER_OBJECT] = 0;
+ return FALSE;
+ }
- if( !success )
- {
- mShaderLevel[SHADER_OBJECT] = 0;
- return FALSE;
- }
-
return TRUE;
}
BOOL LLViewerShaderMgr::loadShadersAvatar()
{
+ LL_PROFILE_ZONE_SCOPED;
+#if 1 // DEPRECATED -- forward rendering is deprecated
BOOL success = TRUE;
if (mShaderLevel[SHADER_AVATAR] == 0)
@@ -3388,8 +3487,8 @@ BOOL LLViewerShaderMgr::loadShadersAvatar()
gAvatarProgram.mFeatures.hasAlphaMask = true;
gAvatarProgram.mFeatures.disableTextureIndex = true;
gAvatarProgram.mShaderFiles.clear();
- gAvatarProgram.mShaderFiles.push_back(make_pair("avatar/avatarV.glsl", GL_VERTEX_SHADER_ARB));
- gAvatarProgram.mShaderFiles.push_back(make_pair("avatar/avatarF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gAvatarProgram.mShaderFiles.push_back(make_pair("avatar/avatarV.glsl", GL_VERTEX_SHADER));
+ gAvatarProgram.mShaderFiles.push_back(make_pair("avatar/avatarF.glsl", GL_FRAGMENT_SHADER));
gAvatarProgram.mShaderLevel = mShaderLevel[SHADER_AVATAR];
success = gAvatarProgram.createShader(NULL, NULL);
@@ -3405,8 +3504,8 @@ BOOL LLViewerShaderMgr::loadShadersAvatar()
gAvatarWaterProgram.mFeatures.hasAlphaMask = true;
gAvatarWaterProgram.mFeatures.disableTextureIndex = true;
gAvatarWaterProgram.mShaderFiles.clear();
- gAvatarWaterProgram.mShaderFiles.push_back(make_pair("avatar/avatarV.glsl", GL_VERTEX_SHADER_ARB));
- gAvatarWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gAvatarWaterProgram.mShaderFiles.push_back(make_pair("avatar/avatarV.glsl", GL_VERTEX_SHADER));
+ gAvatarWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER));
// Note: no cloth under water:
gAvatarWaterProgram.mShaderLevel = llmin(mShaderLevel[SHADER_AVATAR], 1);
gAvatarWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
@@ -3426,8 +3525,8 @@ BOOL LLViewerShaderMgr::loadShadersAvatar()
gAvatarPickProgram.mFeatures.hasSkinning = true;
gAvatarPickProgram.mFeatures.disableTextureIndex = true;
gAvatarPickProgram.mShaderFiles.clear();
- gAvatarPickProgram.mShaderFiles.push_back(make_pair("avatar/pickAvatarV.glsl", GL_VERTEX_SHADER_ARB));
- gAvatarPickProgram.mShaderFiles.push_back(make_pair("avatar/pickAvatarF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gAvatarPickProgram.mShaderFiles.push_back(make_pair("avatar/pickAvatarV.glsl", GL_VERTEX_SHADER));
+ gAvatarPickProgram.mShaderFiles.push_back(make_pair("avatar/pickAvatarF.glsl", GL_FRAGMENT_SHADER));
gAvatarPickProgram.mShaderLevel = mShaderLevel[SHADER_AVATAR];
success = gAvatarPickProgram.createShader(NULL, NULL);
}
@@ -3444,8 +3543,8 @@ BOOL LLViewerShaderMgr::loadShadersAvatar()
gAvatarEyeballProgram.mFeatures.hasAlphaMask = true;
gAvatarEyeballProgram.mFeatures.disableTextureIndex = true;
gAvatarEyeballProgram.mShaderFiles.clear();
- gAvatarEyeballProgram.mShaderFiles.push_back(make_pair("avatar/eyeballV.glsl", GL_VERTEX_SHADER_ARB));
- gAvatarEyeballProgram.mShaderFiles.push_back(make_pair("avatar/eyeballF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gAvatarEyeballProgram.mShaderFiles.push_back(make_pair("avatar/eyeballV.glsl", GL_VERTEX_SHADER));
+ gAvatarEyeballProgram.mShaderFiles.push_back(make_pair("avatar/eyeballF.glsl", GL_FRAGMENT_SHADER));
gAvatarEyeballProgram.mShaderLevel = mShaderLevel[SHADER_AVATAR];
success = gAvatarEyeballProgram.createShader(NULL, NULL);
}
@@ -3456,20 +3555,21 @@ BOOL LLViewerShaderMgr::loadShadersAvatar()
mMaxAvatarShaderLevel = 0;
return FALSE;
}
-
+#endif
return TRUE;
}
BOOL LLViewerShaderMgr::loadShadersInterface()
{
+ LL_PROFILE_ZONE_SCOPED;
BOOL success = TRUE;
if (success)
{
gHighlightProgram.mName = "Highlight Shader";
gHighlightProgram.mShaderFiles.clear();
- gHighlightProgram.mShaderFiles.push_back(make_pair("interface/highlightV.glsl", GL_VERTEX_SHADER_ARB));
- gHighlightProgram.mShaderFiles.push_back(make_pair("interface/highlightF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gHighlightProgram.mShaderFiles.push_back(make_pair("interface/highlightV.glsl", GL_VERTEX_SHADER));
+ gHighlightProgram.mShaderFiles.push_back(make_pair("interface/highlightF.glsl", GL_FRAGMENT_SHADER));
gHighlightProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
success = make_rigged_variant(gHighlightProgram, gSkinnedHighlightProgram);
success = success && gHighlightProgram.createShader(NULL, NULL);
@@ -3479,8 +3579,8 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
{
gHighlightNormalProgram.mName = "Highlight Normals Shader";
gHighlightNormalProgram.mShaderFiles.clear();
- gHighlightNormalProgram.mShaderFiles.push_back(make_pair("interface/highlightNormV.glsl", GL_VERTEX_SHADER_ARB));
- gHighlightNormalProgram.mShaderFiles.push_back(make_pair("interface/highlightF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gHighlightNormalProgram.mShaderFiles.push_back(make_pair("interface/highlightNormV.glsl", GL_VERTEX_SHADER));
+ gHighlightNormalProgram.mShaderFiles.push_back(make_pair("interface/highlightF.glsl", GL_FRAGMENT_SHADER));
gHighlightNormalProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
success = gHighlightNormalProgram.createShader(NULL, NULL);
}
@@ -3489,8 +3589,8 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
{
gHighlightSpecularProgram.mName = "Highlight Spec Shader";
gHighlightSpecularProgram.mShaderFiles.clear();
- gHighlightSpecularProgram.mShaderFiles.push_back(make_pair("interface/highlightSpecV.glsl", GL_VERTEX_SHADER_ARB));
- gHighlightSpecularProgram.mShaderFiles.push_back(make_pair("interface/highlightF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gHighlightSpecularProgram.mShaderFiles.push_back(make_pair("interface/highlightSpecV.glsl", GL_VERTEX_SHADER));
+ gHighlightSpecularProgram.mShaderFiles.push_back(make_pair("interface/highlightF.glsl", GL_FRAGMENT_SHADER));
gHighlightSpecularProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
success = gHighlightSpecularProgram.createShader(NULL, NULL);
}
@@ -3499,8 +3599,8 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
{
gUIProgram.mName = "UI Shader";
gUIProgram.mShaderFiles.clear();
- gUIProgram.mShaderFiles.push_back(make_pair("interface/uiV.glsl", GL_VERTEX_SHADER_ARB));
- gUIProgram.mShaderFiles.push_back(make_pair("interface/uiF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gUIProgram.mShaderFiles.push_back(make_pair("interface/uiV.glsl", GL_VERTEX_SHADER));
+ gUIProgram.mShaderFiles.push_back(make_pair("interface/uiF.glsl", GL_FRAGMENT_SHADER));
gUIProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
success = gUIProgram.createShader(NULL, NULL);
}
@@ -3509,8 +3609,8 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
{
gPathfindingProgram.mName = "Pathfinding Shader";
gPathfindingProgram.mShaderFiles.clear();
- gPathfindingProgram.mShaderFiles.push_back(make_pair("interface/pathfindingV.glsl", GL_VERTEX_SHADER_ARB));
- gPathfindingProgram.mShaderFiles.push_back(make_pair("interface/pathfindingF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gPathfindingProgram.mShaderFiles.push_back(make_pair("interface/pathfindingV.glsl", GL_VERTEX_SHADER));
+ gPathfindingProgram.mShaderFiles.push_back(make_pair("interface/pathfindingF.glsl", GL_FRAGMENT_SHADER));
gPathfindingProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
success = gPathfindingProgram.createShader(NULL, NULL);
}
@@ -3519,8 +3619,8 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
{
gPathfindingNoNormalsProgram.mName = "PathfindingNoNormals Shader";
gPathfindingNoNormalsProgram.mShaderFiles.clear();
- gPathfindingNoNormalsProgram.mShaderFiles.push_back(make_pair("interface/pathfindingNoNormalV.glsl", GL_VERTEX_SHADER_ARB));
- gPathfindingNoNormalsProgram.mShaderFiles.push_back(make_pair("interface/pathfindingF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gPathfindingNoNormalsProgram.mShaderFiles.push_back(make_pair("interface/pathfindingNoNormalV.glsl", GL_VERTEX_SHADER));
+ gPathfindingNoNormalsProgram.mShaderFiles.push_back(make_pair("interface/pathfindingF.glsl", GL_FRAGMENT_SHADER));
gPathfindingNoNormalsProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
success = gPathfindingNoNormalsProgram.createShader(NULL, NULL);
}
@@ -3529,8 +3629,8 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
{
gCustomAlphaProgram.mName = "Custom Alpha Shader";
gCustomAlphaProgram.mShaderFiles.clear();
- gCustomAlphaProgram.mShaderFiles.push_back(make_pair("interface/customalphaV.glsl", GL_VERTEX_SHADER_ARB));
- gCustomAlphaProgram.mShaderFiles.push_back(make_pair("interface/customalphaF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gCustomAlphaProgram.mShaderFiles.push_back(make_pair("interface/customalphaV.glsl", GL_VERTEX_SHADER));
+ gCustomAlphaProgram.mShaderFiles.push_back(make_pair("interface/customalphaF.glsl", GL_FRAGMENT_SHADER));
gCustomAlphaProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
success = gCustomAlphaProgram.createShader(NULL, NULL);
}
@@ -3539,8 +3639,8 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
{
gSplatTextureRectProgram.mName = "Splat Texture Rect Shader";
gSplatTextureRectProgram.mShaderFiles.clear();
- gSplatTextureRectProgram.mShaderFiles.push_back(make_pair("interface/splattexturerectV.glsl", GL_VERTEX_SHADER_ARB));
- gSplatTextureRectProgram.mShaderFiles.push_back(make_pair("interface/splattexturerectF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gSplatTextureRectProgram.mShaderFiles.push_back(make_pair("interface/splattexturerectV.glsl", GL_VERTEX_SHADER));
+ gSplatTextureRectProgram.mShaderFiles.push_back(make_pair("interface/splattexturerectF.glsl", GL_FRAGMENT_SHADER));
gSplatTextureRectProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
success = gSplatTextureRectProgram.createShader(NULL, NULL);
if (success)
@@ -3555,8 +3655,8 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
{
gGlowCombineProgram.mName = "Glow Combine Shader";
gGlowCombineProgram.mShaderFiles.clear();
- gGlowCombineProgram.mShaderFiles.push_back(make_pair("interface/glowcombineV.glsl", GL_VERTEX_SHADER_ARB));
- gGlowCombineProgram.mShaderFiles.push_back(make_pair("interface/glowcombineF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gGlowCombineProgram.mShaderFiles.push_back(make_pair("interface/glowcombineV.glsl", GL_VERTEX_SHADER));
+ gGlowCombineProgram.mShaderFiles.push_back(make_pair("interface/glowcombineF.glsl", GL_FRAGMENT_SHADER));
gGlowCombineProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
success = gGlowCombineProgram.createShader(NULL, NULL);
if (success)
@@ -3572,8 +3672,8 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
{
gGlowCombineFXAAProgram.mName = "Glow CombineFXAA Shader";
gGlowCombineFXAAProgram.mShaderFiles.clear();
- gGlowCombineFXAAProgram.mShaderFiles.push_back(make_pair("interface/glowcombineFXAAV.glsl", GL_VERTEX_SHADER_ARB));
- gGlowCombineFXAAProgram.mShaderFiles.push_back(make_pair("interface/glowcombineFXAAF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gGlowCombineFXAAProgram.mShaderFiles.push_back(make_pair("interface/glowcombineFXAAV.glsl", GL_VERTEX_SHADER));
+ gGlowCombineFXAAProgram.mShaderFiles.push_back(make_pair("interface/glowcombineFXAAF.glsl", GL_FRAGMENT_SHADER));
gGlowCombineFXAAProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
success = gGlowCombineFXAAProgram.createShader(NULL, NULL);
if (success)
@@ -3585,13 +3685,12 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
}
}
-
if (success)
{
gTwoTextureAddProgram.mName = "Two Texture Add Shader";
gTwoTextureAddProgram.mShaderFiles.clear();
- gTwoTextureAddProgram.mShaderFiles.push_back(make_pair("interface/twotextureaddV.glsl", GL_VERTEX_SHADER_ARB));
- gTwoTextureAddProgram.mShaderFiles.push_back(make_pair("interface/twotextureaddF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gTwoTextureAddProgram.mShaderFiles.push_back(make_pair("interface/twotextureaddV.glsl", GL_VERTEX_SHADER));
+ gTwoTextureAddProgram.mShaderFiles.push_back(make_pair("interface/twotextureaddF.glsl", GL_FRAGMENT_SHADER));
gTwoTextureAddProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
success = gTwoTextureAddProgram.createShader(NULL, NULL);
if (success)
@@ -3607,8 +3706,8 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
{
gTwoTextureCompareProgram.mName = "Two Texture Compare Shader";
gTwoTextureCompareProgram.mShaderFiles.clear();
- gTwoTextureCompareProgram.mShaderFiles.push_back(make_pair("interface/twotexturecompareV.glsl", GL_VERTEX_SHADER_ARB));
- gTwoTextureCompareProgram.mShaderFiles.push_back(make_pair("interface/twotexturecompareF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gTwoTextureCompareProgram.mShaderFiles.push_back(make_pair("interface/twotexturecompareV.glsl", GL_VERTEX_SHADER));
+ gTwoTextureCompareProgram.mShaderFiles.push_back(make_pair("interface/twotexturecompareF.glsl", GL_FRAGMENT_SHADER));
gTwoTextureCompareProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
success = gTwoTextureCompareProgram.createShader(NULL, NULL);
if (success)
@@ -3624,8 +3723,8 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
{
gOneTextureFilterProgram.mName = "One Texture Filter Shader";
gOneTextureFilterProgram.mShaderFiles.clear();
- gOneTextureFilterProgram.mShaderFiles.push_back(make_pair("interface/onetexturefilterV.glsl", GL_VERTEX_SHADER_ARB));
- gOneTextureFilterProgram.mShaderFiles.push_back(make_pair("interface/onetexturefilterF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gOneTextureFilterProgram.mShaderFiles.push_back(make_pair("interface/onetexturefilterV.glsl", GL_VERTEX_SHADER));
+ gOneTextureFilterProgram.mShaderFiles.push_back(make_pair("interface/onetexturefilterF.glsl", GL_FRAGMENT_SHADER));
gOneTextureFilterProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
success = gOneTextureFilterProgram.createShader(NULL, NULL);
if (success)
@@ -3640,8 +3739,8 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
{
gOneTextureNoColorProgram.mName = "One Texture No Color Shader";
gOneTextureNoColorProgram.mShaderFiles.clear();
- gOneTextureNoColorProgram.mShaderFiles.push_back(make_pair("interface/onetexturenocolorV.glsl", GL_VERTEX_SHADER_ARB));
- gOneTextureNoColorProgram.mShaderFiles.push_back(make_pair("interface/onetexturenocolorF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gOneTextureNoColorProgram.mShaderFiles.push_back(make_pair("interface/onetexturenocolorV.glsl", GL_VERTEX_SHADER));
+ gOneTextureNoColorProgram.mShaderFiles.push_back(make_pair("interface/onetexturenocolorF.glsl", GL_FRAGMENT_SHADER));
gOneTextureNoColorProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
success = gOneTextureNoColorProgram.createShader(NULL, NULL);
if (success)
@@ -3655,8 +3754,8 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
{
gSolidColorProgram.mName = "Solid Color Shader";
gSolidColorProgram.mShaderFiles.clear();
- gSolidColorProgram.mShaderFiles.push_back(make_pair("interface/solidcolorV.glsl", GL_VERTEX_SHADER_ARB));
- gSolidColorProgram.mShaderFiles.push_back(make_pair("interface/solidcolorF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gSolidColorProgram.mShaderFiles.push_back(make_pair("interface/solidcolorV.glsl", GL_VERTEX_SHADER));
+ gSolidColorProgram.mShaderFiles.push_back(make_pair("interface/solidcolorF.glsl", GL_FRAGMENT_SHADER));
gSolidColorProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
success = gSolidColorProgram.createShader(NULL, NULL);
if (success)
@@ -3671,8 +3770,8 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
{
gOcclusionProgram.mName = "Occlusion Shader";
gOcclusionProgram.mShaderFiles.clear();
- gOcclusionProgram.mShaderFiles.push_back(make_pair("interface/occlusionV.glsl", GL_VERTEX_SHADER_ARB));
- gOcclusionProgram.mShaderFiles.push_back(make_pair("interface/occlusionF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gOcclusionProgram.mShaderFiles.push_back(make_pair("interface/occlusionV.glsl", GL_VERTEX_SHADER));
+ gOcclusionProgram.mShaderFiles.push_back(make_pair("interface/occlusionF.glsl", GL_FRAGMENT_SHADER));
gOcclusionProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
gOcclusionProgram.mRiggedVariant = &gSkinnedOcclusionProgram;
success = gOcclusionProgram.createShader(NULL, NULL);
@@ -3683,8 +3782,8 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
gSkinnedOcclusionProgram.mName = "Skinned Occlusion Shader";
gSkinnedOcclusionProgram.mFeatures.hasObjectSkinning = true;
gSkinnedOcclusionProgram.mShaderFiles.clear();
- gSkinnedOcclusionProgram.mShaderFiles.push_back(make_pair("interface/occlusionSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
- gSkinnedOcclusionProgram.mShaderFiles.push_back(make_pair("interface/occlusionF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gSkinnedOcclusionProgram.mShaderFiles.push_back(make_pair("interface/occlusionSkinnedV.glsl", GL_VERTEX_SHADER));
+ gSkinnedOcclusionProgram.mShaderFiles.push_back(make_pair("interface/occlusionF.glsl", GL_FRAGMENT_SHADER));
gSkinnedOcclusionProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
success = gSkinnedOcclusionProgram.createShader(NULL, NULL);
}
@@ -3693,8 +3792,8 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
{
gOcclusionCubeProgram.mName = "Occlusion Cube Shader";
gOcclusionCubeProgram.mShaderFiles.clear();
- gOcclusionCubeProgram.mShaderFiles.push_back(make_pair("interface/occlusionCubeV.glsl", GL_VERTEX_SHADER_ARB));
- gOcclusionCubeProgram.mShaderFiles.push_back(make_pair("interface/occlusionF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gOcclusionCubeProgram.mShaderFiles.push_back(make_pair("interface/occlusionCubeV.glsl", GL_VERTEX_SHADER));
+ gOcclusionCubeProgram.mShaderFiles.push_back(make_pair("interface/occlusionF.glsl", GL_FRAGMENT_SHADER));
gOcclusionCubeProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
success = gOcclusionCubeProgram.createShader(NULL, NULL);
}
@@ -3703,8 +3802,8 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
{
gDebugProgram.mName = "Debug Shader";
gDebugProgram.mShaderFiles.clear();
- gDebugProgram.mShaderFiles.push_back(make_pair("interface/debugV.glsl", GL_VERTEX_SHADER_ARB));
- gDebugProgram.mShaderFiles.push_back(make_pair("interface/debugF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDebugProgram.mShaderFiles.push_back(make_pair("interface/debugV.glsl", GL_VERTEX_SHADER));
+ gDebugProgram.mShaderFiles.push_back(make_pair("interface/debugF.glsl", GL_FRAGMENT_SHADER));
gDebugProgram.mRiggedVariant = &gSkinnedDebugProgram;
gDebugProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
success = make_rigged_variant(gDebugProgram, gSkinnedDebugProgram);
@@ -3715,8 +3814,8 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
{
gClipProgram.mName = "Clip Shader";
gClipProgram.mShaderFiles.clear();
- gClipProgram.mShaderFiles.push_back(make_pair("interface/clipV.glsl", GL_VERTEX_SHADER_ARB));
- gClipProgram.mShaderFiles.push_back(make_pair("interface/clipF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gClipProgram.mShaderFiles.push_back(make_pair("interface/clipV.glsl", GL_VERTEX_SHADER));
+ gClipProgram.mShaderFiles.push_back(make_pair("interface/clipF.glsl", GL_FRAGMENT_SHADER));
gClipProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
success = gClipProgram.createShader(NULL, NULL);
}
@@ -3725,8 +3824,8 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
{
gDownsampleDepthProgram.mName = "DownsampleDepth Shader";
gDownsampleDepthProgram.mShaderFiles.clear();
- gDownsampleDepthProgram.mShaderFiles.push_back(make_pair("interface/downsampleDepthV.glsl", GL_VERTEX_SHADER_ARB));
- gDownsampleDepthProgram.mShaderFiles.push_back(make_pair("interface/downsampleDepthF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDownsampleDepthProgram.mShaderFiles.push_back(make_pair("interface/downsampleDepthV.glsl", GL_VERTEX_SHADER));
+ gDownsampleDepthProgram.mShaderFiles.push_back(make_pair("interface/downsampleDepthF.glsl", GL_FRAGMENT_SHADER));
gDownsampleDepthProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
success = gDownsampleDepthProgram.createShader(NULL, NULL);
}
@@ -3735,18 +3834,57 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
{
gBenchmarkProgram.mName = "Benchmark Shader";
gBenchmarkProgram.mShaderFiles.clear();
- gBenchmarkProgram.mShaderFiles.push_back(make_pair("interface/benchmarkV.glsl", GL_VERTEX_SHADER_ARB));
- gBenchmarkProgram.mShaderFiles.push_back(make_pair("interface/benchmarkF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gBenchmarkProgram.mShaderFiles.push_back(make_pair("interface/benchmarkV.glsl", GL_VERTEX_SHADER));
+ gBenchmarkProgram.mShaderFiles.push_back(make_pair("interface/benchmarkF.glsl", GL_FRAGMENT_SHADER));
gBenchmarkProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
success = gBenchmarkProgram.createShader(NULL, NULL);
}
+ if (success)
+ {
+ 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));
+ gReflectionProbeDisplayProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
+ success = gReflectionProbeDisplayProgram.createShader(NULL, NULL);
+ }
+
+ if (success)
+ {
+ gCopyProgram.mName = "Copy Shader";
+ gCopyProgram.mShaderFiles.clear();
+ gCopyProgram.mShaderFiles.push_back(make_pair("interface/copyV.glsl", GL_VERTEX_SHADER));
+ gCopyProgram.mShaderFiles.push_back(make_pair("interface/copyF.glsl", GL_FRAGMENT_SHADER));
+ gCopyProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
+ success = gCopyProgram.createShader(NULL, NULL);
+ }
+
+ if (success)
+ {
+ gCopyDepthProgram.mName = "Copy Depth Shader";
+ gCopyDepthProgram.mShaderFiles.clear();
+ gCopyDepthProgram.mShaderFiles.push_back(make_pair("interface/copyV.glsl", GL_VERTEX_SHADER));
+ gCopyDepthProgram.mShaderFiles.push_back(make_pair("interface/copyF.glsl", GL_FRAGMENT_SHADER));
+ gCopyDepthProgram.clearPermutations();
+ gCopyDepthProgram.addPermutation("COPY_DEPTH", "1");
+ gCopyDepthProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
+ success = gCopyDepthProgram.createShader(NULL, NULL);
+ }
+
if (success)
{
gDownsampleDepthRectProgram.mName = "DownsampleDepthRect Shader";
gDownsampleDepthRectProgram.mShaderFiles.clear();
- gDownsampleDepthRectProgram.mShaderFiles.push_back(make_pair("interface/downsampleDepthV.glsl", GL_VERTEX_SHADER_ARB));
- gDownsampleDepthRectProgram.mShaderFiles.push_back(make_pair("interface/downsampleDepthRectF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDownsampleDepthRectProgram.mShaderFiles.push_back(make_pair("interface/downsampleDepthV.glsl", GL_VERTEX_SHADER));
+ gDownsampleDepthRectProgram.mShaderFiles.push_back(make_pair("interface/downsampleDepthRectF.glsl", GL_FRAGMENT_SHADER));
gDownsampleDepthRectProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
success = gDownsampleDepthRectProgram.createShader(NULL, NULL);
}
@@ -3755,12 +3893,52 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
{
gAlphaMaskProgram.mName = "Alpha Mask Shader";
gAlphaMaskProgram.mShaderFiles.clear();
- gAlphaMaskProgram.mShaderFiles.push_back(make_pair("interface/alphamaskV.glsl", GL_VERTEX_SHADER_ARB));
- gAlphaMaskProgram.mShaderFiles.push_back(make_pair("interface/alphamaskF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gAlphaMaskProgram.mShaderFiles.push_back(make_pair("interface/alphamaskV.glsl", GL_VERTEX_SHADER));
+ gAlphaMaskProgram.mShaderFiles.push_back(make_pair("interface/alphamaskF.glsl", GL_FRAGMENT_SHADER));
gAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
success = gAlphaMaskProgram.createShader(NULL, NULL);
}
+ if (success)
+ {
+ gReflectionMipProgram.mName = "Reflection Mip Shader";
+ 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));
+ gReflectionMipProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
+ success = gReflectionMipProgram.createShader(NULL, NULL);
+ if (success)
+ {
+ gReflectionMipProgram.bind();
+ gReflectionMipProgram.uniform1i(sScreenMap, 0);
+ gReflectionMipProgram.unbind();
+ }
+ }
+
+ if (success && gGLManager.mHasCubeMapArray)
+ {
+ gRadianceGenProgram.mName = "Radiance Gen Shader";
+ gRadianceGenProgram.mShaderFiles.clear();
+ gRadianceGenProgram.mShaderFiles.push_back(make_pair("interface/radianceGenV.glsl", GL_VERTEX_SHADER));
+ gRadianceGenProgram.mShaderFiles.push_back(make_pair("interface/radianceGenF.glsl", GL_FRAGMENT_SHADER));
+ gRadianceGenProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
+ success = gRadianceGenProgram.createShader(NULL, NULL);
+ }
+
+ if (success && gGLManager.mHasCubeMapArray)
+ {
+ gIrradianceGenProgram.mName = "Irradiance Gen Shader";
+ gIrradianceGenProgram.mShaderFiles.clear();
+ gIrradianceGenProgram.mShaderFiles.push_back(make_pair("interface/irradianceGenV.glsl", GL_VERTEX_SHADER));
+ gIrradianceGenProgram.mShaderFiles.push_back(make_pair("interface/irradianceGenF.glsl", GL_FRAGMENT_SHADER));
+ gIrradianceGenProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
+ success = gIrradianceGenProgram.createShader(NULL, NULL);
+ }
+
if( !success )
{
mShaderLevel[SHADER_INTERFACE] = 0;
@@ -3772,8 +3950,9 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
BOOL LLViewerShaderMgr::loadShadersWindLight()
{
+ LL_PROFILE_ZONE_SCOPED;
BOOL success = TRUE;
-
+#if 1 // DEPRECATED -- forward rendering is deprecated
if (mShaderLevel[SHADER_WINDLIGHT] < 2)
{
gWLSkyProgram.unload();
@@ -3791,8 +3970,8 @@ BOOL LLViewerShaderMgr::loadShadersWindLight()
gWLSkyProgram.mFeatures.hasTransport = true;
gWLSkyProgram.mFeatures.hasGamma = true;
gWLSkyProgram.mFeatures.hasSrgb = true;
- gWLSkyProgram.mShaderFiles.push_back(make_pair("windlight/skyV.glsl", GL_VERTEX_SHADER_ARB));
- gWLSkyProgram.mShaderFiles.push_back(make_pair("windlight/skyF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gWLSkyProgram.mShaderFiles.push_back(make_pair("windlight/skyV.glsl", GL_VERTEX_SHADER));
+ gWLSkyProgram.mShaderFiles.push_back(make_pair("windlight/skyF.glsl", GL_FRAGMENT_SHADER));
gWLSkyProgram.mShaderLevel = mShaderLevel[SHADER_WINDLIGHT];
gWLSkyProgram.mShaderGroup = LLGLSLShader::SG_SKY;
success = gWLSkyProgram.createShader(NULL, NULL);
@@ -3806,10 +3985,11 @@ BOOL LLViewerShaderMgr::loadShadersWindLight()
gWLCloudProgram.mFeatures.hasTransport = true;
gWLCloudProgram.mFeatures.hasGamma = true;
gWLCloudProgram.mFeatures.hasSrgb = true;
- gWLCloudProgram.mShaderFiles.push_back(make_pair("windlight/cloudsV.glsl", GL_VERTEX_SHADER_ARB));
- gWLCloudProgram.mShaderFiles.push_back(make_pair("windlight/cloudsF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gWLCloudProgram.mShaderFiles.push_back(make_pair("windlight/cloudsV.glsl", GL_VERTEX_SHADER));
+ gWLCloudProgram.mShaderFiles.push_back(make_pair("windlight/cloudsF.glsl", GL_FRAGMENT_SHADER));
gWLCloudProgram.mShaderLevel = mShaderLevel[SHADER_WINDLIGHT];
gWLCloudProgram.mShaderGroup = LLGLSLShader::SG_SKY;
+ gWLCloudProgram.addConstant( LLGLSLShader::SHADER_CONST_CLOUD_MOON_DEPTH ); // SL-14113
success = gWLCloudProgram.createShader(NULL, NULL);
}
@@ -3824,8 +4004,8 @@ BOOL LLViewerShaderMgr::loadShadersWindLight()
gWLSunProgram.mFeatures.isFullbright = true;
gWLSunProgram.mFeatures.disableTextureIndex = true;
gWLSunProgram.mShaderGroup = LLGLSLShader::SG_SKY;
- gWLSunProgram.mShaderFiles.push_back(make_pair("windlight/sunDiscV.glsl", GL_VERTEX_SHADER_ARB));
- gWLSunProgram.mShaderFiles.push_back(make_pair("windlight/sunDiscF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gWLSunProgram.mShaderFiles.push_back(make_pair("windlight/sunDiscV.glsl", GL_VERTEX_SHADER));
+ gWLSunProgram.mShaderFiles.push_back(make_pair("windlight/sunDiscF.glsl", GL_FRAGMENT_SHADER));
gWLSunProgram.mShaderLevel = mShaderLevel[SHADER_WINDLIGHT];
gWLSunProgram.mShaderGroup = LLGLSLShader::SG_SKY;
success = gWLSunProgram.createShader(NULL, NULL);
@@ -3842,102 +4022,14 @@ BOOL LLViewerShaderMgr::loadShadersWindLight()
gWLMoonProgram.mFeatures.isFullbright = true;
gWLMoonProgram.mFeatures.disableTextureIndex = true;
gWLMoonProgram.mShaderGroup = LLGLSLShader::SG_SKY;
- gWLMoonProgram.mShaderFiles.push_back(make_pair("windlight/moonV.glsl", GL_VERTEX_SHADER_ARB));
- gWLMoonProgram.mShaderFiles.push_back(make_pair("windlight/moonF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gWLMoonProgram.mShaderFiles.push_back(make_pair("windlight/moonV.glsl", GL_VERTEX_SHADER));
+ gWLMoonProgram.mShaderFiles.push_back(make_pair("windlight/moonF.glsl", GL_FRAGMENT_SHADER));
gWLMoonProgram.mShaderLevel = mShaderLevel[SHADER_WINDLIGHT];
gWLMoonProgram.mShaderGroup = LLGLSLShader::SG_SKY;
+ gWLMoonProgram.addConstant( LLGLSLShader::SHADER_CONST_CLOUD_MOON_DEPTH ); // SL-14113
success = gWLMoonProgram.createShader(NULL, NULL);
}
-
- return success;
-}
-
-BOOL LLViewerShaderMgr::loadTransformShaders()
-{
- BOOL success = TRUE;
-
- if (mShaderLevel[SHADER_TRANSFORM] < 1)
- {
- gTransformPositionProgram.unload();
- gTransformTexCoordProgram.unload();
- gTransformNormalProgram.unload();
- gTransformColorProgram.unload();
- gTransformTangentProgram.unload();
- return TRUE;
- }
-
- if (success)
- {
- gTransformPositionProgram.mName = "Position Transform Shader";
- gTransformPositionProgram.mShaderFiles.clear();
- gTransformPositionProgram.mShaderFiles.push_back(make_pair("transform/positionV.glsl", GL_VERTEX_SHADER_ARB));
- gTransformPositionProgram.mShaderLevel = mShaderLevel[SHADER_TRANSFORM];
-
- const char* varyings[] = {
- "position_out",
- "texture_index_out",
- };
-
- success = gTransformPositionProgram.createShader(NULL, NULL, 2, varyings);
- }
-
- if (success)
- {
- gTransformTexCoordProgram.mName = "TexCoord Transform Shader";
- gTransformTexCoordProgram.mShaderFiles.clear();
- gTransformTexCoordProgram.mShaderFiles.push_back(make_pair("transform/texcoordV.glsl", GL_VERTEX_SHADER_ARB));
- gTransformTexCoordProgram.mShaderLevel = mShaderLevel[SHADER_TRANSFORM];
-
- const char* varyings[] = {
- "texcoord_out",
- };
-
- success = gTransformTexCoordProgram.createShader(NULL, NULL, 1, varyings);
- }
-
- if (success)
- {
- gTransformNormalProgram.mName = "Normal Transform Shader";
- gTransformNormalProgram.mShaderFiles.clear();
- gTransformNormalProgram.mShaderFiles.push_back(make_pair("transform/normalV.glsl", GL_VERTEX_SHADER_ARB));
- gTransformNormalProgram.mShaderLevel = mShaderLevel[SHADER_TRANSFORM];
-
- const char* varyings[] = {
- "normal_out",
- };
-
- success = gTransformNormalProgram.createShader(NULL, NULL, 1, varyings);
- }
-
- if (success)
- {
- gTransformColorProgram.mName = "Color Transform Shader";
- gTransformColorProgram.mShaderFiles.clear();
- gTransformColorProgram.mShaderFiles.push_back(make_pair("transform/colorV.glsl", GL_VERTEX_SHADER_ARB));
- gTransformColorProgram.mShaderLevel = mShaderLevel[SHADER_TRANSFORM];
-
- const char* varyings[] = {
- "color_out",
- };
-
- success = gTransformColorProgram.createShader(NULL, NULL, 1, varyings);
- }
-
- if (success)
- {
- gTransformTangentProgram.mName = "Binormal Transform Shader";
- gTransformTangentProgram.mShaderFiles.clear();
- gTransformTangentProgram.mShaderFiles.push_back(make_pair("transform/binormalV.glsl", GL_VERTEX_SHADER_ARB));
- gTransformTangentProgram.mShaderLevel = mShaderLevel[SHADER_TRANSFORM];
-
- const char* varyings[] = {
- "tangent_out",
- };
-
- success = gTransformTangentProgram.createShader(NULL, NULL, 1, varyings);
- }
-
-
+#endif
return success;
}
diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h
index f8a261805b..593a8c14f3 100644
--- a/indra/newview/llviewershadermgr.h
+++ b/indra/newview/llviewershadermgr.h
@@ -62,7 +62,6 @@ public:
BOOL loadShadersWater();
BOOL loadShadersInterface();
BOOL loadShadersWindLight();
- BOOL loadTransformShaders();
std::vector<S32> mShaderLevel;
S32 mMaxAvatarShaderLevel;
@@ -78,7 +77,6 @@ public:
SHADER_WINDLIGHT,
SHADER_WATER,
SHADER_DEFERRED,
- SHADER_TRANSFORM,
SHADER_COUNT
};
@@ -150,27 +148,24 @@ inline bool operator != (LLViewerShaderMgr::shader_iter const & a, LLViewerShade
extern LLVector4 gShinyOrigin;
-//transform shaders
-extern LLGLSLShader gTransformPositionProgram;
-extern LLGLSLShader gTransformTexCoordProgram;
-extern LLGLSLShader gTransformNormalProgram;
-extern LLGLSLShader gTransformColorProgram;
-extern LLGLSLShader gTransformTangentProgram;
-
-
-
//utility shaders
extern LLGLSLShader gOcclusionProgram;
extern LLGLSLShader gOcclusionCubeProgram;
extern LLGLSLShader gCustomAlphaProgram;
extern LLGLSLShader gGlowCombineProgram;
extern LLGLSLShader gSplatTextureRectProgram;
+extern LLGLSLShader gReflectionMipProgram;
+extern LLGLSLShader gRadianceGenProgram;
+extern LLGLSLShader gIrradianceGenProgram;
extern LLGLSLShader gGlowCombineFXAAProgram;
extern LLGLSLShader gDebugProgram;
extern LLGLSLShader gClipProgram;
extern LLGLSLShader gDownsampleDepthProgram;
extern LLGLSLShader gDownsampleDepthRectProgram;
extern LLGLSLShader gBenchmarkProgram;
+extern LLGLSLShader gReflectionProbeDisplayProgram;
+extern LLGLSLShader gCopyProgram;
+extern LLGLSLShader gCopyDepthProgram;
//output tex0[tc0] + tex1[tc1]
extern LLGLSLShader gTwoTextureAddProgram;
@@ -219,6 +214,8 @@ extern LLGLSLShader gObjectShinyProgram;
extern LLGLSLShader gObjectShinyWaterProgram;
//environment shaders
+extern LLGLSLShader gMoonProgram;
+extern LLGLSLShader gStarsProgram;
extern LLGLSLShader gTerrainProgram;
extern LLGLSLShader gTerrainWaterProgram;
extern LLGLSLShader gWaterProgram;
@@ -255,7 +252,7 @@ extern LLGLSLShader gWLMoonProgram;
// Post Process Shaders
extern LLGLSLShader gPostColorFilterProgram;
extern LLGLSLShader gPostNightVisionProgram;
-
+extern LLGLSLShader gPostScreenSpaceReflectionProgram;
// Deferred rendering shaders
extern LLGLSLShader gDeferredImpostorProgram;
@@ -283,6 +280,7 @@ extern LLGLSLShader gDeferredSoftenWaterProgram;
extern LLGLSLShader gDeferredShadowProgram;
extern LLGLSLShader gDeferredShadowCubeProgram;
extern LLGLSLShader gDeferredShadowAlphaMaskProgram;
+extern LLGLSLShader gDeferredShadowGLTFAlphaMaskProgram;
extern LLGLSLShader gDeferredShadowFullbrightAlphaMaskProgram;
extern LLGLSLShader gDeferredPostProgram;
extern LLGLSLShader gDeferredCoFProgram;
@@ -291,17 +289,16 @@ extern LLGLSLShader gFXAAProgram;
extern LLGLSLShader gDeferredPostNoDoFProgram;
extern LLGLSLShader gDeferredPostGammaCorrectProgram;
extern LLGLSLShader gDeferredAvatarShadowProgram;
-extern LLGLSLShader gDeferredAttachmentShadowProgram;
-extern LLGLSLShader gDeferredAttachmentAlphaShadowProgram;
-extern LLGLSLShader gDeferredAttachmentAlphaMaskShadowProgram;
extern LLGLSLShader gDeferredAvatarAlphaShadowProgram;
extern LLGLSLShader gDeferredAvatarAlphaMaskShadowProgram;
extern LLGLSLShader gDeferredAlphaProgram;
extern LLGLSLShader gDeferredAlphaImpostorProgram;
extern LLGLSLShader gDeferredFullbrightProgram;
extern LLGLSLShader gDeferredFullbrightAlphaMaskProgram;
+extern LLGLSLShader gDeferredFullbrightAlphaMaskAlphaProgram;
extern LLGLSLShader gDeferredAlphaWaterProgram;
extern LLGLSLShader gDeferredFullbrightWaterProgram;
+extern LLGLSLShader gDeferredFullbrightWaterAlphaProgram;
extern LLGLSLShader gDeferredFullbrightAlphaMaskWaterProgram;
extern LLGLSLShader gDeferredEmissiveProgram;
extern LLGLSLShader gDeferredAvatarEyesProgram;
@@ -313,8 +310,12 @@ extern LLGLSLShader gDeferredWLMoonProgram;
extern LLGLSLShader gDeferredStarProgram;
extern LLGLSLShader gDeferredFullbrightShinyProgram;
extern LLGLSLShader gNormalMapGenProgram;
+extern LLGLSLShader gDeferredGenBrdfLutProgram;
// Deferred materials shaders
extern LLGLSLShader gDeferredMaterialProgram[LLMaterial::SHADER_COUNT*2];
extern LLGLSLShader gDeferredMaterialWaterProgram[LLMaterial::SHADER_COUNT*2];
+
+extern LLGLSLShader gDeferredPBROpaqueProgram;
+extern LLGLSLShader gDeferredPBRAlphaProgram;
#endif
diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp
index a4fbbb3e78..ee39b7d02f 100644
--- a/indra/newview/llviewerstats.cpp
+++ b/indra/newview/llviewerstats.cpp
@@ -65,6 +65,53 @@
#include "llinventorymodel.h"
#include "lluiusage.h"
+// "Minimal Vulkan" to get max API Version
+
+// Calls
+ #if defined(_WIN32)
+ #define VKAPI_ATTR
+ #define VKAPI_CALL __stdcall
+ #define VKAPI_PTR VKAPI_CALL
+ #else
+ #define VKAPI_ATTR
+ #define VKAPI_CALL
+ #define VKAPI_PTR
+ #endif // _WIN32
+
+// Macros
+ // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ // |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|
+ // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ // <variant> <-------major-------><-----------minor-----------> <--------------patch-------------->
+ // 0x7 0x7F 0x3FF 0xFFF
+ #define VK_API_VERSION_MAJOR( version) (((uint32_t)(version) >> 22) & 0x07FU) // 7 bits
+ #define VK_API_VERSION_MINOR( version) (((uint32_t)(version) >> 12) & 0x3FFU) // 10 bits
+ #define VK_API_VERSION_PATCH( version) (((uint32_t)(version) ) & 0xFFFU) // 12 bits
+ #define VK_API_VERSION_VARIANT(version) (((uint32_t)(version) >> 29) & 0x007U) // 3 bits
+
+ // NOTE: variant is first parameter! This is to match vulkan/vulkan_core.h
+ #define VK_MAKE_API_VERSION(variant, major, minor, patch) (0\
+ | (((uint32_t)(major & 0x07FU)) << 22) \
+ | (((uint32_t)(minor & 0x3FFU)) << 12) \
+ | (((uint32_t)(patch & 0xFFFU)) ) \
+ | (((uint32_t)(variant & 0x007U)) << 29) )
+
+ #define VK_DEFINE_HANDLE(object) typedef struct object##_T* object;
+
+// Types
+ VK_DEFINE_HANDLE(VkInstance);
+
+ typedef enum VkResult
+ {
+ VK_SUCCESS = 0,
+ VK_RESULT_MAX_ENUM = 0x7FFFFFFF
+ } VkResult;
+
+// Prototypes
+ typedef void (VKAPI_PTR *PFN_vkVoidFunction )(void);
+ typedef PFN_vkVoidFunction (VKAPI_PTR *PFN_vkGetInstanceProcAddr )(VkInstance instance, const char* pName);
+ typedef VkResult (VKAPI_PTR *PFN_vkEnumerateInstanceVersion)(uint32_t* pApiVersion);
+
namespace LLStatViewer
{
@@ -139,6 +186,7 @@ SimMeasurement<LLUnit<F64, LLUnits::Percent> >
LLTrace::SampleStatHandle<> FPS_SAMPLE("fpssample"),
NUM_IMAGES("numimagesstat"),
NUM_RAW_IMAGES("numrawimagesstat"),
+ NUM_MATERIALS("nummaterials"),
NUM_OBJECTS("numobjectsstat"),
NUM_ACTIVE_OBJECTS("numactiveobjectsstat"),
ENABLE_VBO("enablevbo", "Vertex Buffers Enabled"),
@@ -155,10 +203,7 @@ LLTrace::SampleStatHandle<LLUnit<F32, LLUnits::Percent> >
static LLTrace::SampleStatHandle<bool>
CHAT_BUBBLES("chatbubbles", "Chat Bubbles Enabled");
-LLTrace::SampleStatHandle<F64Megabytes > GL_TEX_MEM("gltexmemstat"),
- GL_BOUND_MEM("glboundmemstat"),
- RAW_MEM("rawmemstat"),
- FORMATTED_MEM("formattedmemstat");
+LLTrace::SampleStatHandle<F64Megabytes > FORMATTED_MEM("formattedmemstat");
LLTrace::SampleStatHandle<F64Kilobytes > DELTA_BANDWIDTH("deltabandwidth", "Increase/Decrease in bandwidth based on packet loss"),
MAX_BANDWIDTH("maxbandwidth", "Max bandwidth setting");
@@ -319,10 +364,10 @@ U32Bytes gTotalTextureBytesPerBoostLevel[LLViewerTexture::MAX_GL_IMAGE_CATEGOR
extern U32 gVisCompared;
extern U32 gVisTested;
-LLFrameTimer gTextureTimer;
-
void update_statistics()
{
+ LL_PROFILE_ZONE_SCOPED;
+
gTotalWorldData += gVLManager.getTotalBytes();
gTotalObjectData += gObjectData;
@@ -354,16 +399,8 @@ void update_statistics()
typedef LLTrace::StatType<LLTrace::TimeBlockAccumulator>::instance_tracker_t stat_type_t;
- F64Seconds idle_secs = last_frame_recording.getSum(*stat_type_t::getInstance("Idle"));
- F64Seconds network_secs = last_frame_recording.getSum(*stat_type_t::getInstance("Network"));
-
record(LLStatViewer::FRAME_STACKTIME, last_frame_recording.getSum(*stat_type_t::getInstance("Frame")));
- record(LLStatViewer::UPDATE_STACKTIME, idle_secs - network_secs);
- record(LLStatViewer::NETWORK_STACKTIME, network_secs);
- record(LLStatViewer::IMAGE_STACKTIME, last_frame_recording.getSum(*stat_type_t::getInstance("Update Images")));
- record(LLStatViewer::REBUILD_STACKTIME, last_frame_recording.getSum(*stat_type_t::getInstance("Sort Draw State")));
- record(LLStatViewer::RENDER_STACKTIME, last_frame_recording.getSum(*stat_type_t::getInstance("Render Geometry")));
-
+
if (gAgent.getRegion() && isAgentAvatarValid())
{
LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(gAgent.getRegion()->getHost());
@@ -416,19 +453,6 @@ void update_statistics()
}
}
-void update_texture_time()
-{
- if (gTextureList.isPrioRequestsFetched())
- {
- gTextureTimer.pause();
- }
- else
- {
- gTextureTimer.unpause();
- }
-
- record(LLStatViewer::TEXTURE_FETCH_TIME, gTextureTimer.getElapsedTimeF32());
-}
/*
* The sim-side LLSD is in newsim/llagentinfo.cpp:forwardViewerStats.
*
@@ -615,19 +639,76 @@ void send_viewer_stats(bool include_preferences)
// detailed information on versions and extensions can come later.
static bool vulkan_oneshot = false;
static bool vulkan_detected = false;
+ static std::string vulkan_max_api_version( "0.0" ); // Unknown/None
if (!vulkan_oneshot)
{
- HMODULE vulkan_loader = LoadLibraryExA("vulkan-1.dll", NULL, LOAD_LIBRARY_AS_DATAFILE);
+ // The 32-bit and 64-bit versions normally exist in:
+ // C:\Windows\System32
+ // C:\Windows\SysWOW64
+ HMODULE vulkan_loader = LoadLibraryA("vulkan-1.dll");
if (NULL != vulkan_loader)
{
vulkan_detected = true;
+ vulkan_max_api_version = "1.0"; // We have at least 1.0. See the note about vkEnumerateInstanceVersion() below.
+
+ // We use Run-Time Dynamic Linking (via GetProcAddress()) instead of Load-Time Dynamic Linking (via directly calling vkGetInstanceProcAddr()).
+ // This allows us to:
+ // a) not need the header: #include <vulkan/vulkan.h>
+ // (and not need to set the corresponding "Additional Include Directories" as long as we provide the equivalent Vulkan types/prototypes/etc.)
+ // b) not need to link to: vulkan-1.lib
+ // (and not need to set the corresponding "Additional Library Directories")
+ // The former will allow Second Life to start and run even if the vulkan.dll is missing.
+ // The latter will require us to:
+ // a) link with vulkan-1.lib
+ // b) cause a System Error at startup if the .dll is not found:
+ // "The code execution cannot proceed because vulkan-1.dll was not found."
+ //
+ // See:
+ // https://docs.microsoft.com/en-us/windows/win32/dlls/using-run-time-dynamic-linking
+ // https://docs.microsoft.com/en-us/windows/win32/dlls/run-time-dynamic-linking
+
+ // NOTE: Technically we can use GetProcAddress() as a replacement for vkGetInstanceProcAddr()
+ // but the canonical recommendation (mandate?) is to use vkGetInstanceProcAddr().
+ PFN_vkGetInstanceProcAddr pGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr) GetProcAddress(vulkan_loader, "vkGetInstanceProcAddr");
+ if(pGetInstanceProcAddr)
+ {
+ // Check for vkEnumerateInstanceVersion. If it exists then we have at least 1.1 and can query the max API version.
+ // NOTE: Each VkPhysicalDevice that supports Vulkan has its own VkPhysicalDeviceProperties.apiVersion which is separate from the max API version!
+ // See: https://www.lunarg.com/wp-content/uploads/2019/02/Vulkan-1.1-Compatibility-Statement_01_19.pdf
+ PFN_vkEnumerateInstanceVersion pEnumerateInstanceVersion = (PFN_vkEnumerateInstanceVersion) pGetInstanceProcAddr(NULL, "vkEnumerateInstanceVersion");
+ if(pEnumerateInstanceVersion)
+ {
+ uint32_t version = VK_MAKE_API_VERSION(0,1,1,0); // e.g. 4202631 = 1.2.135.0
+ VkResult status = pEnumerateInstanceVersion( &version );
+ if (status != VK_SUCCESS)
+ {
+ LL_INFOS("Vulkan") << "Failed to get Vulkan version. Assuming 1.0" << LL_ENDL;
+ }
+ else
+ {
+ // https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#extendingvulkan-coreversions-versionnumbers
+ int major = VK_API_VERSION_MAJOR ( version );
+ int minor = VK_API_VERSION_MINOR ( version );
+ int patch = VK_API_VERSION_PATCH ( version );
+ int variant = VK_API_VERSION_VARIANT( version );
+
+ vulkan_max_api_version = llformat( "%d.%d.%d.%d", major, minor, patch, variant );
+ LL_INFOS("Vulkan") << "Vulkan API version: " << vulkan_max_api_version << ", Raw version: " << version << LL_ENDL;
+ }
+ }
+ }
+ else
+ {
+ LL_WARNS("Vulkan") << "FAILED to get Vulkan vkGetInstanceProcAddr()!" << LL_ENDL;
+ }
FreeLibrary(vulkan_loader);
}
vulkan_oneshot = true;
}
misc["string_1"] = vulkan_detected ? llformat("Vulkan driver is detected") : llformat("No Vulkan driver detected");
+ misc["VulkanMaxApiVersion"] = vulkan_max_api_version;
#else
misc["string_1"] = llformat("Unused");
diff --git a/indra/newview/llviewerstats.h b/indra/newview/llviewerstats.h
index 017c79b2e3..4f0f4f8813 100644
--- a/indra/newview/llviewerstats.h
+++ b/indra/newview/llviewerstats.h
@@ -180,6 +180,7 @@ extern LLTrace::SampleStatHandle<> FPS_SAMPLE,
NUM_IMAGES,
NUM_RAW_IMAGES,
NUM_OBJECTS,
+ NUM_MATERIALS,
NUM_ACTIVE_OBJECTS,
ENABLE_VBO,
LIGHTING_DETAIL,
@@ -191,10 +192,8 @@ extern LLTrace::SampleStatHandle<> FPS_SAMPLE,
extern LLTrace::SampleStatHandle<LLUnit<F32, LLUnits::Percent> > PACKETS_LOST_PERCENT;
-extern LLTrace::SampleStatHandle<F64Megabytes > GL_TEX_MEM,
- GL_BOUND_MEM,
- RAW_MEM,
- FORMATTED_MEM;
+extern LLTrace::SampleStatHandle<F64Megabytes > FORMATTED_MEM;
+
extern LLTrace::SampleStatHandle<F64Kilobytes > DELTA_BANDWIDTH,
MAX_BANDWIDTH;
extern SimMeasurement<F64Milliseconds > SIM_FRAME_TIME,
@@ -296,7 +295,6 @@ void update_statistics();
void send_viewer_stats(bool include_preferences);
void update_texture_time();
-extern LLFrameTimer gTextureTimer;
extern U32Bytes gTotalTextureData;
extern U32Bytes gTotalObjectData;
extern U32Bytes gTotalTextureBytesPerBoostLevel[] ;
diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp
index 7abb42dd8a..1353eea2f2 100644
--- a/indra/newview/llviewertexteditor.cpp
+++ b/indra/newview/llviewertexteditor.cpp
@@ -42,6 +42,7 @@
#include "lllandmark.h"
#include "lllandmarkactions.h"
#include "lllandmarklist.h"
+#include "llmaterialeditor.h"
#include "llmemorystream.h"
#include "llmenugl.h"
#include "llnotecard.h"
@@ -542,6 +543,7 @@ LLUIImagePtr LLEmbeddedItems::getItemImage(llwchar ext_char) const
case LLAssetType::AT_GESTURE: img_name = "Inv_Gesture"; break;
case LLAssetType::AT_MESH: img_name = "Inv_Mesh"; break;
case LLAssetType::AT_SETTINGS: img_name = "Inv_Settings"; break;
+ case LLAssetType::AT_MATERIAL: img_name = "Inv_Material"; break;
default: img_name = "Inv_Invalid"; break; // use the Inv_Invalid icon for undefined object types (see MAINT-3981)
}
@@ -879,6 +881,7 @@ BOOL LLViewerTextEditor::handleDragAndDrop(S32 x, S32 y, MASK mask,
case DAD_ANIMATION:
case DAD_GESTURE:
case DAD_MESH:
+ case DAD_MATERIAL:
{
supported = true;
break;
@@ -1126,6 +1129,9 @@ BOOL LLViewerTextEditor::openEmbeddedItem(LLPointer<LLInventoryItem> item, llwch
case LLAssetType::AT_SETTINGS:
openEmbeddedSetting(item, wc);
return TRUE;
+ case LLAssetType::AT_MATERIAL:
+ openEmbeddedGLTFMaterial(item, wc);
+ return TRUE;
case LLAssetType::AT_NOTECARD:
case LLAssetType::AT_LSL_TEXT:
case LLAssetType::AT_CLOTHING:
@@ -1212,6 +1218,26 @@ void LLViewerTextEditor::openEmbeddedSetting(LLInventoryItem* item, llwchar wc)
}
}
+void LLViewerTextEditor::openEmbeddedGLTFMaterial(LLInventoryItem* item, llwchar wc)
+{
+ if (!item)
+ {
+ return;
+ }
+
+ LLSD floater_key;
+ floater_key["objectid"] = mObjectID;
+ floater_key["notecardid"] = mNotecardInventoryID;
+ LLMaterialEditor* preview = LLFloaterReg::getTypedInstance<LLMaterialEditor>("material_editor", floater_key);
+ if (preview)
+ {
+ preview->setAuxItem(item);
+ preview->setNotecardInfo(mNotecardInventoryID, mObjectID);
+ preview->openFloater(floater_key);
+ preview->setFocus(TRUE);
+ }
+}
+
void LLViewerTextEditor::showUnsavedAlertDialog( LLInventoryItem* item )
{
LLSD payload;
diff --git a/indra/newview/llviewertexteditor.h b/indra/newview/llviewertexteditor.h
index a6d7fef409..6170d476b8 100644
--- a/indra/newview/llviewertexteditor.h
+++ b/indra/newview/llviewertexteditor.h
@@ -108,6 +108,7 @@ private:
void openEmbeddedLandmark( LLPointer<LLInventoryItem> item_ptr, llwchar wc );
void openEmbeddedCallingcard( LLInventoryItem* item, llwchar wc);
void openEmbeddedSetting(LLInventoryItem* item, llwchar wc);
+ void openEmbeddedGLTFMaterial(LLInventoryItem* item, llwchar wc);
void showCopyToInvDialog( LLInventoryItem* item, llwchar wc );
void showUnsavedAlertDialog( LLInventoryItem* item );
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index e3ac56d0d3..721498572f 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -58,6 +58,8 @@
#include "llvovolume.h"
#include "llviewermedia.h"
#include "lltexturecache.h"
+#include "llviewerwindow.h"
+#include "llwindow.h"
///////////////////////////////////////////////////////////////////////////////
// extern
@@ -74,8 +76,11 @@ LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sWhiteImagep = NULL;
LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sDefaultImagep = NULL;
LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sSmokeImagep = NULL;
LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sFlatNormalImagep = NULL;
+LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sDefaultIrradiancePBRp;
LLViewerMediaTexture::media_map_t LLViewerMediaTexture::sMediaMap;
LLTexturePipelineTester* LLViewerTextureManager::sTesterp = NULL;
+F32 LLViewerFetchedTexture::sMaxVirtualSize = 8192.f*8192.f;
+
const std::string sTesterName("TextureTester");
S32 LLViewerTexture::sImageCount = 0;
@@ -84,11 +89,6 @@ S32 LLViewerTexture::sAuxCount = 0;
LLFrameTimer LLViewerTexture::sEvaluationTimer;
F32 LLViewerTexture::sDesiredDiscardBias = 0.f;
F32 LLViewerTexture::sDesiredDiscardScale = 1.1f;
-S32Bytes LLViewerTexture::sBoundTextureMemory;
-S32Bytes LLViewerTexture::sTotalTextureMemory;
-S32Megabytes LLViewerTexture::sMaxBoundTextureMemory;
-S32Megabytes LLViewerTexture::sMaxTotalTextureMem;
-S32Bytes LLViewerTexture::sMaxDesiredTextureMem;
S8 LLViewerTexture::sCameraMovingDiscardBias = 0;
F32 LLViewerTexture::sCameraMovingBias = 0.0f;
S32 LLViewerTexture::sMaxSculptRez = 128; //max sculpt image size
@@ -100,7 +100,6 @@ U32 LLViewerTexture::sMinLargeImageSize = 65536; //256 * 256.
U32 LLViewerTexture::sMaxSmallImageSize = MAX_CACHED_RAW_IMAGE_AREA;
bool LLViewerTexture::sFreezeImageUpdates = false;
F32 LLViewerTexture::sCurrentTime = 0.0f;
-F32 LLViewerTexture::sTexelPixelRatio = 1.0f;
LLViewerTexture::EDebugTexels LLViewerTexture::sDebugTexelsMode = LLViewerTexture::DEBUG_TEXELS_OFF;
@@ -287,6 +286,13 @@ LLPointer<LLViewerTexture> LLViewerTextureManager::getLocalTexture(const U32 wid
return tex;
}
+LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTexture(const LLImageRaw* raw, FTType type, bool usemipmaps)
+{
+ LLViewerFetchedTexture* ret = new LLViewerFetchedTexture(raw, type, usemipmaps);
+ gTextureList.addImage(ret, TEX_LIST_STANDARD);
+ return ret;
+}
+
LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTexture(
const LLUUID &image_id,
FTType f_type,
@@ -402,9 +408,6 @@ void LLViewerTextureManager::init()
LLViewerFetchedTexture::sDefaultImagep->dontDiscard();
LLViewerFetchedTexture::sDefaultImagep->setCategory(LLGLTexture::OTHER);
- LLViewerFetchedTexture::sSmokeImagep = LLViewerTextureManager::getFetchedTexture(IMG_SMOKE, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI);
- LLViewerFetchedTexture::sSmokeImagep->setNoDelete();
-
image_raw = new LLImageRaw(32,32,3);
data = image_raw->getData();
@@ -452,6 +455,7 @@ void LLViewerTextureManager::cleanup()
LLViewerFetchedTexture::sWhiteImagep = NULL;
LLViewerFetchedTexture::sFlatNormalImagep = NULL;
+ LLViewerFetchedTexture::sDefaultIrradiancePBRp = NULL;
LLViewerMediaTexture::cleanUpClass();
}
@@ -464,11 +468,6 @@ void LLViewerTextureManager::cleanup()
void LLViewerTexture::initClass()
{
LLImageGL::sDefaultGLTexture = LLViewerFetchedTexture::sDefaultImagep->getGLTexture();
-
- if(gSavedSettings.getBOOL("TextureFetchDebuggerEnabled"))
- {
- sTexelPixelRatio = gSavedSettings.getF32("TexelPixelRatio");
- }
}
// tuning params
@@ -493,7 +492,7 @@ bool LLViewerTexture::isMemoryForTextureLow()
S32Megabytes physical;
getGPUMemoryForTextures(gpu, physical);
- return (gpu < MIN_FREE_TEXTURE_MEMORY) || (physical < MIN_FREE_MAIN_MEMORY);
+ return (gpu < MIN_FREE_TEXTURE_MEMORY); // || (physical < MIN_FREE_MAIN_MEMORY);
}
//static
@@ -507,7 +506,7 @@ bool LLViewerTexture::isMemoryForTextureSuficientlyFree()
S32Megabytes physical;
getGPUMemoryForTextures(gpu, physical);
- return (gpu > DESIRED_FREE_TEXTURE_MEMORY) && (physical > DESIRED_FREE_MAIN_MEMORY);
+ return (gpu > DESIRED_FREE_TEXTURE_MEMORY); // && (physical > DESIRED_FREE_MAIN_MEMORY);
}
//static
@@ -528,9 +527,9 @@ void LLViewerTexture::getGPUMemoryForTextures(S32Megabytes &gpu, S32Megabytes &p
timer.reset();
{
- gpu_res = (S32Megabytes) LLImageGLThread::getFreeVRAMMegabytes();
+ gpu_res = (S32Megabytes)gViewerWindow->getWindow()->getAvailableVRAMMegabytes();
- //check main memory, only works for windows.
+ //check main memory, only works for windows and macos.
LLMemory::updateMemoryInfo();
physical_res = LLMemory::getAvailableMemKB();
@@ -553,27 +552,7 @@ void LLViewerTexture::updateClass()
LLViewerMediaTexture::updateClass();
- sBoundTextureMemory = LLImageGL::sBoundTextureMemory;
- sTotalTextureMemory = LLImageGL::sGlobalTextureMemory;
- sMaxBoundTextureMemory = gTextureList.getMaxResidentTexMem();
- sMaxTotalTextureMem = gTextureList.getMaxTotalTextureMem();
- sMaxDesiredTextureMem = sMaxTotalTextureMem; //in Bytes, by default and when total used texture memory is small.
-
- if (sBoundTextureMemory >= sMaxBoundTextureMemory ||
- sTotalTextureMemory >= sMaxTotalTextureMem)
- {
- //when texture memory overflows, lower down the threshold to release the textures more aggressively.
- sMaxDesiredTextureMem = llmin(sMaxDesiredTextureMem * 0.75f, F32Bytes(gMaxVideoRam));
-
- // If we are using more texture memory than we should,
- // scale up the desired discard level
- if (sEvaluationTimer.getElapsedTimeF32() > discard_delta_time)
- {
- sDesiredDiscardBias += discard_bias_delta;
- sEvaluationTimer.reset();
- }
- }
- else if(isMemoryForTextureLow())
+ if(isMemoryForTextureLow())
{
// Note: isMemoryForTextureLow() uses 1s delay, make sure we waited enough for it to recheck
if (sEvaluationTimer.getElapsedTimeF32() > GPU_MEMORY_CHECK_WAIT_TIME)
@@ -583,8 +562,6 @@ void LLViewerTexture::updateClass()
}
}
else if (sDesiredDiscardBias > 0.0f
- && sBoundTextureMemory < sMaxBoundTextureMemory * texmem_lower_bound_scale
- && sTotalTextureMemory < sMaxTotalTextureMem * texmem_lower_bound_scale
&& isMemoryForTextureSuficientlyFree())
{
// If we are using less texture memory than we should,
@@ -654,7 +631,6 @@ void LLViewerTexture::init(bool firstinit)
mMaxVirtualSize = 0.f;
mMaxVirtualSizeResetInterval = 1;
mMaxVirtualSizeResetCounter = mMaxVirtualSizeResetInterval;
- mAdditionalDecodePriority = 0.f;
mParcelMedia = NULL;
memset(&mNumVolumes, 0, sizeof(U32)* LLRender::NUM_VOLUME_TEXTURE_CHANNELS);
@@ -680,7 +656,10 @@ S8 LLViewerTexture::getType() const
void LLViewerTexture::cleanup()
{
- notifyAboutMissingAsset();
+ if (LLAppViewer::getTextureFetch())
+ {
+ LLAppViewer::getTextureFetch()->updateRequestPriority(mID, 0.f);
+ }
mFaceList[LLRender::DIFFUSE_MAP].clear();
mFaceList[LLRender::NORMAL_MAP].clear();
@@ -689,30 +668,6 @@ void LLViewerTexture::cleanup()
mVolumeList[LLRender::SCULPT_TEX].clear();
}
-void LLViewerTexture::notifyAboutCreatingTexture()
-{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
- for(U32 ch = 0; ch < LLRender::NUM_TEXTURE_CHANNELS; ++ch)
- {
- for(U32 f = 0; f < mNumFaces[ch]; f++)
- {
- mFaceList[ch][f]->notifyAboutCreatingTexture(this);
- }
- }
-}
-
-void LLViewerTexture::notifyAboutMissingAsset()
-{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
- for(U32 ch = 0; ch < LLRender::NUM_TEXTURE_CHANNELS; ++ch)
- {
- for(U32 f = 0; f < mNumFaces[ch]; f++)
- {
- mFaceList[ch][f]->notifyAboutMissingAsset(this);
- }
- }
-}
-
// virtual
void LLViewerTexture::dump()
{
@@ -738,6 +693,12 @@ void LLViewerTexture::setBoostLevel(S32 level)
}
}
+ // strongly encourage anything boosted to load at full res
+ if (mBoostLevel >= LLViewerTexture::BOOST_HIGH)
+ {
+ mMaxVirtualSize = 2048.f * 2048.f;
+ }
+
if (mBoostLevel == LLViewerTexture::BOOST_SELECTED)
{
mSelectedTime = gFrameTimeSeconds;
@@ -820,16 +781,9 @@ void LLViewerTexture::addTextureStats(F32 virtual_size, BOOL needs_gltexture) co
mNeedsGLTexture = TRUE;
}
- virtual_size *= sTexelPixelRatio;
- if(!mMaxVirtualSizeResetCounter)
- {
- //flag to reset the values because the old values are used.
- resetMaxVirtualSizeResetCounter();
- mMaxVirtualSize = virtual_size;
- mAdditionalDecodePriority = 0.f;
- mNeedsGLTexture = needs_gltexture;
- }
- else if (virtual_size > mMaxVirtualSize)
+ virtual_size = llmin(virtual_size, LLViewerFetchedTexture::sMaxVirtualSize);
+
+ if (virtual_size > mMaxVirtualSize)
{
mMaxVirtualSize = virtual_size;
}
@@ -838,7 +792,6 @@ void LLViewerTexture::addTextureStats(F32 virtual_size, BOOL needs_gltexture) co
void LLViewerTexture::resetTextureStats()
{
mMaxVirtualSize = 0.0f;
- mAdditionalDecodePriority = 0.f;
mMaxVirtualSizeResetCounter = 0;
}
@@ -1057,6 +1010,19 @@ const std::string& fttype_to_string(const FTType& fttype)
//start of LLViewerFetchedTexture
//----------------------------------------------------------------------------------------------
+//static
+LLViewerFetchedTexture* LLViewerFetchedTexture::getSmokeImage()
+{
+ if (sSmokeImagep.isNull())
+ {
+ sSmokeImagep = LLViewerTextureManager::getFetchedTexture(IMG_SMOKE);
+ }
+
+ sSmokeImagep->addTextureStats(1024.f * 1024.f);
+
+ return sSmokeImagep;
+}
+
LLViewerFetchedTexture::LLViewerFetchedTexture(const LLUUID& id, FTType f_type, const LLHost& host, BOOL usemipmaps)
: LLViewerTexture(id, usemipmaps),
mTargetHost(host)
@@ -1107,7 +1073,6 @@ void LLViewerFetchedTexture::init(bool firstinit)
if (firstinit)
{
- mDecodePriority = 0.f;
mInImageList = 0;
}
@@ -1156,6 +1121,7 @@ void LLViewerFetchedTexture::init(bool firstinit)
LLViewerFetchedTexture::~LLViewerFetchedTexture()
{
+ assert_main_thread();
//*NOTE getTextureFetch can return NULL when Viewer is shutting down.
// This is due to LLWearableList is singleton and is destroyed after
// LLAppViewer::cleanup() was called. (see ticket EXT-177)
@@ -1352,10 +1318,7 @@ void LLViewerFetchedTexture::dump()
void LLViewerFetchedTexture::destroyTexture()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
- if(LLImageGL::sGlobalTextureMemory < sMaxDesiredTextureMem * 0.95f)//not ready to release unused memory.
- {
- return ;
- }
+
if (mNeedsCreateTexture)//return if in the process of generating a new texture.
{
return;
@@ -1591,6 +1554,7 @@ BOOL LLViewerFetchedTexture::createTexture(S32 usename/*= 0*/)
void LLViewerFetchedTexture::postCreateTexture()
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
if (!mNeedsCreateTexture)
{
return;
@@ -1599,8 +1563,6 @@ void LLViewerFetchedTexture::postCreateTexture()
mGLTexturep->checkActiveThread();
#endif
- notifyAboutCreatingTexture();
-
setActive();
if (!needsToSaveRawImage())
@@ -1614,6 +1576,8 @@ void LLViewerFetchedTexture::postCreateTexture()
void LLViewerFetchedTexture::scheduleCreateTexture()
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
+
if (!mNeedsCreateTexture)
{
mNeedsCreateTexture = TRUE;
@@ -1690,6 +1654,7 @@ void LLViewerFetchedTexture::scheduleCreateTexture()
//virtual
void LLViewerFetchedTexture::setKnownDrawSize(S32 width, S32 height)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
if(mKnownDrawWidth < width || mKnownDrawHeight < height)
{
mKnownDrawWidth = llmax(mKnownDrawWidth, width);
@@ -1701,9 +1666,31 @@ void LLViewerFetchedTexture::setKnownDrawSize(S32 width, S32 height)
addTextureStats((F32)(mKnownDrawWidth * mKnownDrawHeight));
}
+void LLViewerFetchedTexture::setDebugText(const std::string& text)
+{
+ for (U32 ch = 0; ch < LLRender::NUM_TEXTURE_CHANNELS; ++ch)
+ {
+ llassert(mNumFaces[ch] <= mFaceList[ch].size());
+
+ for (U32 i = 0; i < mNumFaces[ch]; i++)
+ {
+ LLFace* facep = mFaceList[ch][i];
+ if (facep)
+ {
+ LLDrawable* drawable = facep->getDrawable();
+ if (drawable)
+ {
+ drawable->getVObj()->setDebugText(text);
+ }
+ }
+ }
+ }
+}
+
//virtual
void LLViewerFetchedTexture::processTextureStats()
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
if(mFullyLoaded)
{
if(mDesiredDiscardLevel > mMinDesiredDiscardLevel)//need to load more
@@ -1711,6 +1698,7 @@ void LLViewerFetchedTexture::processTextureStats()
mDesiredDiscardLevel = llmin(mDesiredDiscardLevel, mMinDesiredDiscardLevel);
mFullyLoaded = FALSE;
}
+ //setDebugText("fully loaded");
}
else
{
@@ -1723,7 +1711,7 @@ void LLViewerFetchedTexture::processTextureStats()
mDesiredDiscardLevel = 0;
}
else if (!LLPipeline::sRenderDeferred && mBoostLevel == LLGLTexture::BOOST_ALM)
- {
+ { // ??? don't load spec and normal maps when alm is disabled ???
mDesiredDiscardLevel = MAX_DISCARD_LEVEL + 1;
}
else if (mDontDiscard && mBoostLevel == LLGLTexture::BOOST_ICON)
@@ -1781,247 +1769,11 @@ void LLViewerFetchedTexture::processTextureStats()
}
}
-const F32 MAX_PRIORITY_PIXEL = 999.f; //pixel area
-const F32 PRIORITY_BOOST_LEVEL_FACTOR = 1000.f; //boost level
-const F32 PRIORITY_DELTA_DISCARD_LEVEL_FACTOR = 100000.f; //delta discard
-const S32 MAX_DELTA_DISCARD_LEVEL_FOR_PRIORITY = 4;
-const F32 PRIORITY_ADDITIONAL_FACTOR = 1000000.f; //additional
-const S32 MAX_ADDITIONAL_LEVEL_FOR_PRIORITY = 8;
-const F32 PRIORITY_BOOST_HIGH_FACTOR = 10000000.f;//boost high
-F32 LLViewerFetchedTexture::calcDecodePriority()
-{
-#ifndef LL_RELEASE_FOR_DOWNLOAD
- if (mID == LLAppViewer::getTextureFetch()->mDebugID)
- {
- LLAppViewer::getTextureFetch()->mDebugCount++; // for setting breakpoints
- }
-#endif
-
- if (mNeedsCreateTexture)
- {
- return mDecodePriority; // no change while waiting to create
- }
- if(mFullyLoaded && !mForceToSaveRawImage)//already loaded for static texture
- {
- return -1.0f; //alreay fetched
- }
-
- S32 cur_discard = getCurrentDiscardLevelForFetching();
- bool have_all_data = (cur_discard >= 0 && (cur_discard <= mDesiredDiscardLevel));
- F32 pixel_priority = (F32) sqrt(mMaxVirtualSize);
-
- F32 priority = 0.f;
-
- if (mIsMissingAsset)
- {
- priority = 0.0f;
- }
- else if(mDesiredDiscardLevel >= cur_discard && cur_discard > -1)
- {
- priority = -2.0f;
- }
- else if(mCachedRawDiscardLevel > -1 && mDesiredDiscardLevel >= mCachedRawDiscardLevel)
- {
- priority = -3.0f;
- }
- else if (mDesiredDiscardLevel > getMaxDiscardLevel())
- {
- // Don't decode anything we don't need
- priority = -4.0f;
- }
- else if ((mBoostLevel == LLGLTexture::BOOST_UI || mBoostLevel == LLGLTexture::BOOST_ICON) && !have_all_data)
- {
- priority = 1.f;
- }
- else if (pixel_priority < 0.001f && !have_all_data)
- {
- // Not on screen but we might want some data
- if (mBoostLevel > BOOST_SELECTED)
- {
- // Always want high boosted images
- priority = 1.f;
- }
- else
- {
- priority = -5.f; //stop fetching
- }
- }
- else if (cur_discard < 0)
- {
- //texture does not have any data, so we don't know the size of the image, treat it like 32 * 32.
- // priority range = 100,000 - 500,000
- static const F64 log_2 = log(2.0);
- F32 desired = (F32)(log(32.0/pixel_priority) / log_2);
- S32 ddiscard = MAX_DISCARD_LEVEL - (S32)desired;
- ddiscard = llclamp(ddiscard, 0, MAX_DELTA_DISCARD_LEVEL_FOR_PRIORITY);
- priority = (ddiscard + 1) * PRIORITY_DELTA_DISCARD_LEVEL_FACTOR;
- setAdditionalDecodePriority(0.1f);//boost the textures without any data so far.
- }
- else if ((mMinDiscardLevel > 0) && (cur_discard <= mMinDiscardLevel))
- {
- // larger mips are corrupted
- priority = -6.0f;
- }
- else
- {
- // priority range = 100,000 - 500,000
- S32 desired_discard = mDesiredDiscardLevel;
- if (!isJustBound() && mCachedRawImageReady)
- {
- if(mBoostLevel < BOOST_HIGH)
- {
- // We haven't rendered this in a while, de-prioritize it
- desired_discard += 2;
- }
- else
- {
- // We haven't rendered this in the last half second, and we have a cached raw image, leave the desired discard as-is
- desired_discard = cur_discard;
- }
- }
-
- S32 ddiscard = cur_discard - desired_discard;
- ddiscard = llclamp(ddiscard, -1, MAX_DELTA_DISCARD_LEVEL_FOR_PRIORITY);
- priority = (ddiscard + 1) * PRIORITY_DELTA_DISCARD_LEVEL_FACTOR;
- }
-
- // Priority Formula:
- // BOOST_HIGH + ADDITIONAL PRI + DELTA DISCARD + BOOST LEVEL + PIXELS
- // [10,000,000] + [1,000,000-9,000,000] + [100,000-500,000] + [1-20,000] + [0-999]
- if (priority > 0.0f)
- {
- bool large_enough = mCachedRawImageReady && ((S32)mTexelsPerImage > sMinLargeImageSize);
- if(large_enough)
- {
- //Note:
- //to give small, low-priority textures some chance to be fetched,
- //cut the priority in half if the texture size is larger than 256 * 256 and has a 64*64 ready.
- priority *= 0.5f;
- }
-
- pixel_priority = llclamp(pixel_priority, 0.0f, MAX_PRIORITY_PIXEL);
-
- priority += pixel_priority + PRIORITY_BOOST_LEVEL_FACTOR * mBoostLevel;
-
- if ( mBoostLevel > BOOST_HIGH)
- {
- if(mBoostLevel > BOOST_SUPER_HIGH)
- {
- //for very important textures, always grant the highest priority.
- priority += PRIORITY_BOOST_HIGH_FACTOR;
- }
- else if(mCachedRawImageReady)
- {
- //Note:
- //to give small, low-priority textures some chance to be fetched,
- //if high priority texture has a 64*64 ready, lower its fetching priority.
- setAdditionalDecodePriority(0.5f);
- }
- else
- {
- priority += PRIORITY_BOOST_HIGH_FACTOR;
- }
- }
-
- if(mAdditionalDecodePriority > 0.0f)
- {
- // priority range += 1,000,000.f-9,000,000.f
- F32 additional = PRIORITY_ADDITIONAL_FACTOR * (1.0 + mAdditionalDecodePriority * MAX_ADDITIONAL_LEVEL_FOR_PRIORITY);
- if(large_enough)
- {
- //Note:
- //to give small, low-priority textures some chance to be fetched,
- //cut the additional priority to a quarter if the texture size is larger than 256 * 256 and has a 64*64 ready.
- additional *= 0.25f;
- }
- priority += additional;
- }
- }
- return priority;
-}
-
-//static
-F32 LLViewerFetchedTexture::maxDecodePriority()
-{
- static const F32 max_priority = PRIORITY_BOOST_HIGH_FACTOR + //boost_high
- PRIORITY_ADDITIONAL_FACTOR * (MAX_ADDITIONAL_LEVEL_FOR_PRIORITY + 1) + //additional (view dependent factors)
- PRIORITY_DELTA_DISCARD_LEVEL_FACTOR * (MAX_DELTA_DISCARD_LEVEL_FOR_PRIORITY + 1) + //delta discard
- PRIORITY_BOOST_LEVEL_FACTOR * (BOOST_MAX_LEVEL - 1) + //boost level
- MAX_PRIORITY_PIXEL + 1.0f; //pixel area.
-
- return max_priority;
-}
-
//============================================================================
-void LLViewerFetchedTexture::setDecodePriority(F32 priority)
-{
- mDecodePriority = priority;
-
- if(mDecodePriority < F_ALMOST_ZERO)
- {
- mStopFetchingTimer.reset();
- }
-}
-
-void LLViewerFetchedTexture::setAdditionalDecodePriority(F32 priority)
-{
- priority = llclamp(priority, 0.f, 1.f);
- if(mAdditionalDecodePriority < priority)
- {
- mAdditionalDecodePriority = priority;
- }
-}
-
void LLViewerFetchedTexture::updateVirtualSize()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
- if(!mMaxVirtualSizeResetCounter)
- {
- addTextureStats(0.f, FALSE);//reset
- }
-
- for (U32 ch = 0; ch < LLRender::NUM_TEXTURE_CHANNELS; ++ch)
- {
- llassert(mNumFaces[ch] <= mFaceList[ch].size());
-
- for(U32 i = 0; i < mNumFaces[ch]; i++)
- {
- LLFace* facep = mFaceList[ch][i];
- if( facep )
- {
- LLDrawable* drawable = facep->getDrawable();
- if (drawable)
- {
- if(drawable->isRecentlyVisible())
- {
- if ((getBoostLevel() == LLViewerTexture::BOOST_NONE || getBoostLevel() == LLViewerTexture::BOOST_ALM)
- && drawable->getVObj()
- && drawable->getVObj()->isSelected())
- {
- setBoostLevel(LLViewerTexture::BOOST_SELECTED);
- }
- addTextureStats(facep->getVirtualSize());
- setAdditionalDecodePriority(facep->getImportanceToCamera());
- }
- }
- }
- }
- }
- //reset whether or not a face was selected after 10 seconds
- const F32 SELECTION_RESET_TIME = 10.f;
-
- if (getBoostLevel() == LLViewerTexture::BOOST_SELECTED &&
- gFrameTimeSeconds - mSelectedTime > SELECTION_RESET_TIME)
- {
- // Could have been BOOST_ALM, but if user was working with this texture, better keep it as NONE
- setBoostLevel(LLViewerTexture::BOOST_NONE);
- }
-
- if(mMaxVirtualSizeResetCounter > 0)
- {
- mMaxVirtualSizeResetCounter--;
- }
reorganizeFaceList();
reorganizeVolumeList();
}
@@ -2065,14 +1817,23 @@ bool LLViewerFetchedTexture::isActiveFetching()
return mFetchState > 7 && mFetchState < 10 && monitor_enabled; //in state of WAIT_HTTP_REQ or DECODE_IMAGE.
}
+void LLViewerFetchedTexture::setBoostLevel(S32 level)
+{
+ LLViewerTexture::setBoostLevel(level);
+
+ if (level >= LLViewerTexture::BOOST_HIGH)
+ {
+ mDesiredDiscardLevel = 0;
+ }
+}
+
bool LLViewerFetchedTexture::updateFetch()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
static LLCachedControl<bool> textures_decode_disabled(gSavedSettings,"TextureDecodeDisabled", false);
static LLCachedControl<F32> sCameraMotionThreshold(gSavedSettings,"TextureCameraMotionThreshold", 0.2);
static LLCachedControl<S32> sCameraMotionBoost(gSavedSettings,"TextureCameraMotionBoost", 3);
- if(textures_decode_disabled ||
- (gUseWireframe && mBoostLevel < LLGLTexture::BOOST_AVATAR_BAKED_SELF)) // don't fetch the surface textures in wireframe mode
+ if(textures_decode_disabled) // don't fetch the surface textures in wireframe mode
{
return false;
}
@@ -2091,31 +1852,40 @@ bool LLViewerFetchedTexture::updateFetch()
if (mNeedsCreateTexture)
{
+ LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - needs create");
// We may be fetching still (e.g. waiting on write)
// but don't check until we've processed the raw data we have
return false;
}
if (mIsMissingAsset)
{
+ LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - missing asset");
llassert_always(!mHasFetcher);
return false; // skip
}
if (!mLoadedCallbackList.empty() && mRawImage.notNull())
{
+ LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - callback pending");
return false; // process any raw image data in callbacks before replacing
}
if(mInFastCacheList)
{
+ LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - in fast cache");
return false;
}
+ if (mGLTexturep.isNull())
+ { // fix for crash inside getCurrentDiscardLevelForFetching (shouldn't happen but appears to be happening)
+ llassert(false);
+ return false;
+ }
S32 current_discard = getCurrentDiscardLevelForFetching();
S32 desired_discard = getDesiredDiscardLevel();
- F32 decode_priority = getDecodePriority();
- decode_priority = llclamp(decode_priority, 0.0f, maxDecodePriority());
+ F32 decode_priority = mMaxVirtualSize;
if (mIsFetching)
{
+ LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - is fetching");
// Sets mRawDiscardLevel, mRawImage, mAuxRawImage
S32 fetch_discard = current_discard;
@@ -2133,17 +1903,25 @@ bool LLViewerFetchedTexture::updateFetch()
if (finished)
{
mIsFetching = FALSE;
+ mLastFetchState = -1;
+ setDebugText("");
mLastPacketTimer.reset();
}
else
{
mFetchState = LLAppViewer::getTextureFetch()->getFetchState(mID, mDownloadProgress, mRequestedDownloadPriority,
mFetchPriority, mFetchDeltaTime, mRequestDeltaTime, mCanUseHTTP);
+ /*if (mFetchState != mLastFetchState)
+ {
+ setDebugText(LLTextureFetch::getStateString(mFetchState));
+ mLastFetchState = mFetchState;
+ }*/
}
// We may have data ready regardless of whether or not we are finished (e.g. waiting on write)
if (mRawImage.notNull())
{
+ LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - has raw image");
LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName);
if (tester)
{
@@ -2154,6 +1932,7 @@ bool LLViewerFetchedTexture::updateFetch()
if ((mRawImage->getDataSize() > 0 && mRawDiscardLevel >= 0) &&
(current_discard < 0 || mRawDiscardLevel < current_discard))
{
+ LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - data good");
mFullWidth = mRawImage->getWidth() << mRawDiscardLevel;
mFullHeight = mRawImage->getHeight() << mRawDiscardLevel;
setTexelsPerImage();
@@ -2190,6 +1969,7 @@ bool LLViewerFetchedTexture::updateFetch()
}
else
{
+ LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - data not needed");
// Data is ready but we don't need it
// (received it already while fetcher was writing to disk)
destroyRawImage();
@@ -2222,13 +2002,13 @@ bool LLViewerFetchedTexture::updateFetch()
if(current_discard >= 0)
{
mMinDiscardLevel = current_discard;
- desired_discard = current_discard;
+ //desired_discard = current_discard;
}
else
{
S32 dis_level = getDiscardLevel();
mMinDiscardLevel = dis_level;
- desired_discard = dis_level;
+ //desired_discard = dis_level;
}
}
destroyRawImage();
@@ -2242,12 +2022,6 @@ bool LLViewerFetchedTexture::updateFetch()
}
else
{
-// // Useful debugging code for undesired deprioritization of textures.
-// if (decode_priority <= 0.0f && desired_discard >= 0 && desired_discard < current_discard)
-// {
-// LL_INFOS() << "Calling updateRequestPriority() with decode_priority = 0.0f" << LL_ENDL;
-// calcDecodePriority();
-// }
static const F32 MAX_HOLD_TIME = 5.0f; //seconds to wait before canceling fecthing if decode_priority is 0.f.
if(decode_priority > 0.0f || mStopFetchingTimer.getElapsedTimeF32() > MAX_HOLD_TIME)
{
@@ -2257,21 +2031,27 @@ bool LLViewerFetchedTexture::updateFetch()
}
}
+ desired_discard = llmin(desired_discard, getMaxDiscardLevel());
+
bool make_request = true;
if (decode_priority <= 0)
{
+ LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - priority <= 0");
make_request = false;
}
else if(mDesiredDiscardLevel > getMaxDiscardLevel())
{
+ LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - desired > max");
make_request = false;
}
- else if (mNeedsCreateTexture || mIsMissingAsset)
+ else if (mNeedsCreateTexture || mIsMissingAsset)
{
+ LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - create or missing");
make_request = false;
}
else if (current_discard >= 0 && current_discard <= mMinDiscardLevel)
{
+ LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - current < min");
make_request = false;
}
else if(mCachedRawImage.notNull() // can be empty
@@ -2288,6 +2068,7 @@ bool LLViewerFetchedTexture::updateFetch()
if (make_request)
{
+#if 0
// Load the texture progressively: we try not to rush to the desired discard too fast.
// If the camera is not moving, we do not tweak the discard level notch by notch but go to the desired discard with larger boosted steps
// This mitigates the "textures stay blurry" problem when loading while not killing the texture memory while moving around
@@ -2304,18 +2085,23 @@ bool LLViewerFetchedTexture::updateFetch()
{
desired_discard = llmax(desired_discard, current_discard - delta_level);
}
+#endif
if (mIsFetching)
{
+ // already requested a higher resolution mip
if (mRequestedDiscardLevel <= desired_discard)
{
+ LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - requested < desired");
make_request = false;
}
}
else
{
+ // already at a higher resolution mip, don't discard
if (current_discard >= 0 && current_discard <= desired_discard)
{
+ LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - current <= desired");
make_request = false;
}
}
@@ -2323,6 +2109,7 @@ bool LLViewerFetchedTexture::updateFetch()
if (make_request)
{
+ LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - make request");
S32 w=0, h=0, c=0;
if (getDiscardLevel() >= 0)
{
@@ -2338,28 +2125,34 @@ bool LLViewerFetchedTexture::updateFetch()
}
// bypass texturefetch directly by pulling from LLTextureCache
- bool fetch_request_created = false;
- fetch_request_created = LLAppViewer::getTextureFetch()->createRequest(mFTType, mUrl, getID(), getTargetHost(), decode_priority,
+ S32 fetch_request_discard = -1;
+ fetch_request_discard = LLAppViewer::getTextureFetch()->createRequest(mFTType, mUrl, getID(), getTargetHost(), decode_priority,
w, h, c, desired_discard, needsAux(), mCanUseHTTP);
- if (fetch_request_created)
+ if (fetch_request_discard >= 0)
{
+ LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - request created");
mHasFetcher = TRUE;
mIsFetching = TRUE;
- mRequestedDiscardLevel = desired_discard;
+ // in some cases createRequest can modify discard, as an example
+ // bake textures are always at discard 0
+ mRequestedDiscardLevel = llmin(desired_discard, fetch_request_discard);
mFetchState = LLAppViewer::getTextureFetch()->getFetchState(mID, mDownloadProgress, mRequestedDownloadPriority,
mFetchPriority, mFetchDeltaTime, mRequestDeltaTime, mCanUseHTTP);
}
- // if createRequest() failed, we're finishing up a request for this UUID,
- // wait for it to complete
+ // If createRequest() failed, that means one of two things:
+ // 1. We're finishing up a request for this UUID, so we
+ // should wait for it to complete
+ // 2. We've failed a request for this UUID, so there is
+ // no need to create another request
}
else if (mHasFetcher && !mIsFetching)
{
// Only delete requests that haven't received any network data
// for a while. Note - this is the normal mechanism for
// deleting requests, not just a place to handle timeouts.
- const F32 FETCH_IDLE_TIME = 5.f;
+ const F32 FETCH_IDLE_TIME = 0.1f;
if (mLastPacketTimer.getElapsedTimeF32() > FETCH_IDLE_TIME)
{
LL_DEBUGS("Texture") << "exceeded idle time " << FETCH_IDLE_TIME << ", deleting request: " << getID() << LL_ENDL;
@@ -2410,8 +2203,6 @@ void LLViewerFetchedTexture::setIsMissingAsset(BOOL is_missing)
}
if (is_missing)
{
- notifyAboutMissingAsset();
-
if (mUrl.empty())
{
LL_WARNS() << mID << ": Marking image as missing" << LL_ENDL;
@@ -2669,7 +2460,7 @@ bool LLViewerFetchedTexture::doLoadedCallbacks()
LL_INFOS() << "baked texture: " << mID << "clears all call backs due to inactivity." << LL_ENDL;
LL_INFOS() << mUrl << LL_ENDL;
LL_INFOS() << "current discard: " << getDiscardLevel() << " current discard for fetch: " << getCurrentDiscardLevelForFetching() <<
- " Desired discard: " << getDesiredDiscardLevel() << "decode Pri: " << getDecodePriority() << LL_ENDL;
+ " Desired discard: " << getDesiredDiscardLevel() << "decode Pri: " << mMaxVirtualSize << LL_ENDL;
}
clearCallbackEntryList() ; //remove all callbacks.
@@ -2900,7 +2691,7 @@ void LLViewerFetchedTexture::forceImmediateUpdate()
return;
}
//if already called forceImmediateUpdate()
- if(mInImageList && mDecodePriority == LLViewerFetchedTexture::maxDecodePriority())
+ if(mInImageList && mMaxVirtualSize == LLViewerFetchedTexture::sMaxVirtualSize)
{
return;
}
@@ -2969,6 +2760,7 @@ bool LLViewerFetchedTexture::needsToSaveRawImage()
void LLViewerFetchedTexture::destroyRawImage()
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
if (mAuxRawImage.notNull() && !needsToSaveRawImage())
{
sAuxCount--;
@@ -3052,6 +2844,7 @@ void LLViewerFetchedTexture::setCachedRawImage(S32 discard_level, LLImageRaw* im
void LLViewerFetchedTexture::setCachedRawImage()
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
if(mRawImage == mCachedRawImage)
{
return;
@@ -3127,6 +2920,7 @@ void LLViewerFetchedTexture::checkCachedRawSculptImage()
void LLViewerFetchedTexture::saveRawImage()
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
if(mRawImage.isNull() || mRawImage == mSavedRawImage || (mSavedRawDiscardLevel >= 0 && mSavedRawDiscardLevel <= mRawDiscardLevel))
{
return;
@@ -3342,25 +3136,10 @@ void LLViewerLODTexture::processTextureStats()
}
else
{
- if(isLargeImage() && !isJustBound() && mAdditionalDecodePriority < 0.3f)
- {
- //if is a big image and not being used recently, nor close to the view point, do not load hi-res data.
- mMaxVirtualSize = llmin(mMaxVirtualSize, (F32)LLViewerTexture::sMinLargeImageSize);
- }
-
- if ((mCalculatedDiscardLevel >= 0.f) &&
- (llabs(mMaxVirtualSize - mDiscardVirtualSize) < mMaxVirtualSize*.20f))
- {
- // < 20% change in virtual size = no change in desired discard
- discard_level = mCalculatedDiscardLevel;
- }
- else
- {
- // Calculate the required scale factor of the image using pixels per texel
- discard_level = (F32)(log(mTexelsPerImage/mMaxVirtualSize) / log_4);
- mDiscardVirtualSize = mMaxVirtualSize;
- mCalculatedDiscardLevel = discard_level;
- }
+ // Calculate the required scale factor of the image using pixels per texel
+ discard_level = (F32)(log(mTexelsPerImage/mMaxVirtualSize) / log_4);
+ mDiscardVirtualSize = mMaxVirtualSize;
+ mCalculatedDiscardLevel = discard_level;
}
if (mBoostLevel < LLGLTexture::BOOST_SCULPTED)
{
@@ -3400,18 +3179,6 @@ void LLViewerLODTexture::processTextureStats()
//needs to release texture memory urgently
scaleDown();
}
- // Limit the amount of GL memory bound each frame
- else if ( sBoundTextureMemory > sMaxBoundTextureMemory * texmem_middle_bound_scale &&
- (!getBoundRecently() || mDesiredDiscardLevel >= mCachedRawDiscardLevel))
- {
- scaleDown();
- }
- // Only allow GL to have 2x the video card memory
- else if ( sTotalTextureMemory > sMaxTotalTextureMem * texmem_middle_bound_scale &&
- (!getBoundRecently() || mDesiredDiscardLevel >= mCachedRawDiscardLevel))
- {
- scaleDown();
- }
}
if (isUpdateFrozen() // we are out of memory and nearing max allowed bias
@@ -4192,7 +3959,6 @@ void LLTexturePipelineTester::compareTestSessions(llofstream* os)
*os << llformat("%s\n", getTesterName().c_str());
*os << llformat("AggregateResults\n");
- compareTestResults(os, "TotalFetchingTime", base_sessionp->mTotalFetchingTime, current_sessionp->mTotalFetchingTime);
compareTestResults(os, "TotalGrayTime", base_sessionp->mTotalGrayTime, current_sessionp->mTotalGrayTime);
compareTestResults(os, "TotalStablizingTime", base_sessionp->mTotalStablizingTime, current_sessionp->mTotalStablizingTime);
compareTestResults(os, "StartTimeLoadingSculpties", base_sessionp->mStartTimeLoadingSculpties, current_sessionp->mStartTimeLoadingSculpties);
@@ -4252,7 +4018,6 @@ LLMetricPerformanceTesterWithSession::LLTestSession* LLTexturePipelineTester::lo
return NULL;
}
- F32 total_fetching_time = 0.f;
F32 total_gray_time = 0.f;
F32 total_stablizing_time = 0.f;
F32 total_loading_sculpties_time = 0.f;
@@ -4287,7 +4052,6 @@ LLMetricPerformanceTesterWithSession::LLTestSession* LLTexturePipelineTester::lo
F32 cur_time = (*log)[label]["Time"].asReal();
if(start_time - start_fetching_time > F_ALMOST_ZERO) //fetching has paused for a while
{
- sessionp->mTotalFetchingTime += total_fetching_time;
sessionp->mTotalGrayTime += total_gray_time;
sessionp->mTotalStablizingTime += total_stablizing_time;
@@ -4295,14 +4059,12 @@ LLMetricPerformanceTesterWithSession::LLTestSession* LLTexturePipelineTester::lo
sessionp->mTotalTimeLoadingSculpties += total_loading_sculpties_time;
start_fetching_time = start_time;
- total_fetching_time = 0.0f;
total_gray_time = 0.f;
total_stablizing_time = 0.f;
total_loading_sculpties_time = 0.f;
}
else
{
- total_fetching_time = cur_time - start_time;
total_gray_time = (*log)[label]["TotalGrayTime"].asReal();
total_stablizing_time = (*log)[label]["TotalStablizingTime"].asReal();
@@ -4348,7 +4110,6 @@ LLMetricPerformanceTesterWithSession::LLTestSession* LLTexturePipelineTester::lo
in_log = (*log).has(currentLabel);
}
- sessionp->mTotalFetchingTime += total_fetching_time;
sessionp->mTotalGrayTime += total_gray_time;
sessionp->mTotalStablizingTime += total_stablizing_time;
@@ -4370,8 +4131,6 @@ LLTexturePipelineTester::LLTextureTestSession::~LLTextureTestSession()
}
void LLTexturePipelineTester::LLTextureTestSession::reset()
{
- mTotalFetchingTime = 0.0f;
-
mTotalGrayTime = 0.0f;
mTotalStablizingTime = 0.0f;
diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h
index b953d7006b..facf05e52f 100644
--- a/indra/newview/llviewertexture.h
+++ b/indra/newview/llviewertexture.h
@@ -134,7 +134,7 @@ public:
/*virtual*/ bool isActiveFetching();
/*virtual*/ const LLUUID& getID() const { return mID; }
- void setBoostLevel(S32 level);
+ virtual void setBoostLevel(S32 level);
S32 getBoostLevel() { return mBoostLevel; }
void setTextureListType(S32 tex_type) { mTextureListType = tex_type; }
S32 getTextureListType() { return mTextureListType; }
@@ -177,10 +177,7 @@ protected:
void cleanup() ;
void init(bool firstinit) ;
void reorganizeFaceList() ;
- void reorganizeVolumeList() ;
-
- void notifyAboutMissingAsset();
- void notifyAboutCreatingTexture();
+ void reorganizeVolumeList();
private:
friend class LLBumpImageList;
@@ -188,19 +185,20 @@ private:
virtual void switchToCachedImage();
- static bool isMemoryForTextureLow() ;
static bool isMemoryForTextureSuficientlyFree();
static void getGPUMemoryForTextures(S32Megabytes &gpu, S32Megabytes &physical);
+public:
+ static bool isMemoryForTextureLow();
protected:
+ friend class LLViewerTextureList;
LLUUID mID;
S32 mTextureListType; // along with mID identifies where to search for this texture in TextureList
F32 mSelectedTime; // time texture was last selected
- mutable F32 mMaxVirtualSize; // The largest virtual size of the image, in pixels - how much data to we need?
- mutable S32 mMaxVirtualSizeResetCounter ;
+ mutable F32 mMaxVirtualSize = 0.f; // The largest virtual size of the image, in pixels - how much data to we need?
+ mutable S32 mMaxVirtualSizeResetCounter;
mutable S32 mMaxVirtualSizeResetInterval;
- mutable F32 mAdditionalDecodePriority; // priority add to mDecodePriority.
LLFrameTimer mLastReferencedTimer;
ll_face_list_t mFaceList[LLRender::NUM_TEXTURE_CHANNELS]; //reverse pointer pointing to the faces using this image as texture
@@ -217,7 +215,6 @@ protected:
LL::WorkQueue::weak_t mMainQueue;
LL::WorkQueue::weak_t mImageQueue;
- static F32 sTexelPixelRatio;
public:
static const U32 sCurrentFileVersion;
static S32 sImageCount;
@@ -226,11 +223,6 @@ public:
static LLFrameTimer sEvaluationTimer;
static F32 sDesiredDiscardBias;
static F32 sDesiredDiscardScale;
- static S32Bytes sBoundTextureMemory;
- static S32Bytes sTotalTextureMemory;
- static S32Megabytes sMaxBoundTextureMemory;
- static S32Megabytes sMaxTotalTextureMem;
- static S32Bytes sMaxDesiredTextureMem ;
static S8 sCameraMovingDiscardBias;
static F32 sCameraMovingBias;
static S32 sMaxSculptRez ;
@@ -285,7 +277,6 @@ public:
LLViewerFetchedTexture(const std::string& url, FTType f_type, const LLUUID& id, BOOL usemipmaps = TRUE);
public:
- static F32 maxDecodePriority();
struct Compare
{
@@ -294,9 +285,10 @@ public:
{
const LLViewerFetchedTexture* lhsp = (const LLViewerFetchedTexture*)lhs;
const LLViewerFetchedTexture* rhsp = (const LLViewerFetchedTexture*)rhs;
+
// greater priority is "less"
- const F32 lpriority = lhsp->getDecodePriority();
- const F32 rpriority = rhsp->getDecodePriority();
+ const F32 lpriority = lhsp->mMaxVirtualSize;
+ const F32 rpriority = rhsp->mMaxVirtualSize;
if (lpriority > rpriority) // higher priority
return true;
if (lpriority < rpriority)
@@ -306,10 +298,10 @@ public:
};
public:
- /*virtual*/ S8 getType() const ;
+ /*virtual*/ S8 getType() const override;
FTType getFTType() const;
- /*virtual*/ void forceImmediateUpdate() ;
- /*virtual*/ void dump() ;
+ /*virtual*/ void forceImmediateUpdate() override;
+ /*virtual*/ void dump() override;
// Set callbacks to get called when the image gets updated with higher
// resolution versions.
@@ -335,7 +327,6 @@ public:
void destroyTexture() ;
virtual void processTextureStats() ;
- F32 calcDecodePriority() ;
BOOL needsAux() const { return mNeedsAux; }
@@ -343,20 +334,12 @@ public:
void setTargetHost(LLHost host) { mTargetHost = host; }
LLHost getTargetHost() const { return mTargetHost; }
- // Set the decode priority for this image...
- // DON'T CALL THIS UNLESS YOU KNOW WHAT YOU'RE DOING, it can mess up
- // the priority list, and cause horrible things to happen.
- void setDecodePriority(F32 priority = -1.0f);
- F32 getDecodePriority() const { return mDecodePriority; };
- F32 getAdditionalDecodePriority() const { return mAdditionalDecodePriority; };
-
- void setAdditionalDecodePriority(F32 priority) ;
-
void updateVirtualSize() ;
S32 getDesiredDiscardLevel() { return mDesiredDiscardLevel; }
void setMinDiscardLevel(S32 discard) { mMinDesiredDiscardLevel = llmin(mMinDesiredDiscardLevel,(S8)discard); }
+ void setBoostLevel(S32 level) override;
bool updateFetch();
bool setDebugFetching(S32 debug_level);
bool isInDebug() const { return mInDebug; }
@@ -369,10 +352,14 @@ public:
// Override the computation of discard levels if we know the exact output
// size of the image. Used for UI textures to not decode, even if we have
// more data.
- /*virtual*/ void setKnownDrawSize(S32 width, S32 height);
+ /*virtual*/ void setKnownDrawSize(S32 width, S32 height) override;
+
+ // Set the debug text of all Viewer Objects associated with this texture
+ // to the specified text
+ void setDebugText(const std::string& text);
void setIsMissingAsset(BOOL is_missing = true);
- /*virtual*/ BOOL isMissingAsset() const { return mIsMissingAsset; }
+ /*virtual*/ BOOL isMissingAsset() const override { return mIsMissingAsset; }
// returns dimensions of original image for local files (before power of two scaling)
// and returns 0 for all asset system images
@@ -415,7 +402,7 @@ public:
BOOL isRawImageValid()const { return mIsRawImageValid ; }
void forceToSaveRawImage(S32 desired_discard = 0, F32 kept_time = 0.f) ;
void forceToRefetchTexture(S32 desired_discard = 0, F32 kept_time = 60.f);
- /*virtual*/ void setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) ;
+ /*virtual*/ void setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) override;
void destroySavedRawImage() ;
LLImageRaw* getSavedRawImage() ;
BOOL hasSavedRawImage() const ;
@@ -431,10 +418,10 @@ public:
void setInFastCacheList(bool in_list) { mInFastCacheList = in_list; }
bool isInFastCacheList() { return mInFastCacheList; }
- /*virtual*/bool isActiveFetching(); //is actively in fetching by the fetching pipeline.
+ /*virtual*/bool isActiveFetching() override; //is actively in fetching by the fetching pipeline.
protected:
- /*virtual*/ void switchToCachedImage();
+ /*virtual*/ void switchToCachedImage() override;
S32 getCurrentDiscardLevelForFetching() ;
private:
@@ -472,11 +459,11 @@ protected:
S32 mRequestedDiscardLevel;
F32 mRequestedDownloadPriority;
S32 mFetchState;
+ S32 mLastFetchState = -1; // DEBUG
U32 mFetchPriority;
F32 mDownloadProgress;
F32 mFetchDeltaTime;
F32 mRequestDeltaTime;
- F32 mDecodePriority; // The priority for decoding this image.
S32 mMinDiscardLevel;
S8 mDesiredDiscardLevel; // The discard level we'd LIKE to have - if we have it and there's space
S8 mMinDesiredDiscardLevel; // The minimum discard level we'd like to have
@@ -500,7 +487,7 @@ protected:
F32 mLastCallBackActiveTime;
LLPointer<LLImageRaw> mRawImage;
- S32 mRawDiscardLevel;
+ S32 mRawDiscardLevel = -1;
// Used ONLY for cloth meshes right now. Make SURE you know what you're
// doing if you use it for anything else! - djs
@@ -534,11 +521,16 @@ protected:
BOOL mIsFetched ; //is loaded from remote or from cache, not generated locally.
public:
+ static F32 sMaxVirtualSize; //maximum possible value of mMaxVirtualSize
static LLPointer<LLViewerFetchedTexture> sMissingAssetImagep; // Texture to show for an image asset that is not in the database
static LLPointer<LLViewerFetchedTexture> sWhiteImagep; // Texture to show NOTHING (whiteness)
static LLPointer<LLViewerFetchedTexture> sDefaultImagep; // "Default" texture for error cases, the only case of fetched texture which is generated in local.
- static LLPointer<LLViewerFetchedTexture> sSmokeImagep; // Old "Default" translucent texture
static LLPointer<LLViewerFetchedTexture> sFlatNormalImagep; // Flat normal map denoting no bumpiness on a surface
+ static LLPointer<LLViewerFetchedTexture> sDefaultIrradiancePBRp; // PBR: irradiance
+
+ // not sure why, but something is iffy about the loading of this particular texture, use the accessor instead of accessing directly
+ static LLPointer<LLViewerFetchedTexture> sSmokeImagep; // Old "Default" translucent texture
+ static LLViewerFetchedTexture* getSmokeImage();
};
//
@@ -668,6 +660,8 @@ public:
static LLPointer<LLViewerTexture> getLocalTexture(const LLImageRaw* raw, BOOL usemipmaps) ;
static LLPointer<LLViewerTexture> getLocalTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps, BOOL generate_gl_tex = TRUE) ;
+ static LLViewerFetchedTexture* getFetchedTexture(const LLImageRaw* raw, FTType type, bool usemipmaps);
+
static LLViewerFetchedTexture* getFetchedTexture(const LLUUID &image_id,
FTType f_type = FTT_DEFAULT,
BOOL usemipmap = TRUE,
@@ -772,7 +766,6 @@ private:
void reset() ;
- F32 mTotalFetchingTime ;
F32 mTotalGrayTime ;
F32 mTotalStablizingTime ;
F32 mStartTimeLoadingSculpties ;
diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp
index 93ae1670c8..611aace4b4 100644
--- a/indra/newview/llviewertexturelist.cpp
+++ b/indra/newview/llviewertexturelist.cpp
@@ -91,8 +91,6 @@ LLTextureKey::LLTextureKey(LLUUID id, ETexListType tex_type)
LLViewerTextureList::LLViewerTextureList()
: mForceResetTextureStats(FALSE),
- mMaxResidentTexMemInMegaBytes(0),
- mMaxTotalTextureMemInMegaBytes(0),
mInitialized(FALSE)
{
}
@@ -101,12 +99,6 @@ void LLViewerTextureList::init()
{
mInitialized = TRUE ;
sNumImages = 0;
- mMaxResidentTexMemInMegaBytes = (U32Bytes)0;
- mMaxTotalTextureMemInMegaBytes = (U32Bytes)0;
-
- // Update how much texture RAM we're allowed to use.
- updateMaxResidentTexMem(S32Megabytes(0)); // 0 = use current
-
doPreloadImages();
}
@@ -130,7 +122,10 @@ void LLViewerTextureList::doPreloadImages()
// Set the default flat normal map
LLViewerFetchedTexture::sFlatNormalImagep = LLViewerTextureManager::getFetchedTextureFromFile("flatnormal.tga", FTT_LOCAL_FILE, MIPMAP_NO, LLViewerFetchedTexture::BOOST_BUMP);
-
+
+ // PBR: irradiance
+ LLViewerFetchedTexture::sDefaultIrradiancePBRp = LLViewerTextureManager::getFetchedTextureFromFile("default_irradiance.png", FTT_LOCAL_FILE, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI);
+
image_list->initFromFile();
// turn off clamping and bilinear filtering for uv picking images
@@ -208,8 +203,6 @@ static std::string get_texture_list_name()
void LLViewerTextureList::doPrefetchImages()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
- gTextureTimer.start();
- gTextureTimer.pause();
// todo: do not load without getViewerAssetUrl()
// either fail login without caps or provide this
@@ -366,7 +359,7 @@ void LLViewerTextureList::dump()
{
LLViewerFetchedTexture* image = *it;
- LL_INFOS() << "priority " << image->getDecodePriority()
+ LL_INFOS() << "priority " << image->getMaxVirtualSize()
<< " boost " << image->getBoostLevel()
<< " size " << image->getWidth() << "x" << image->getHeight()
<< " discard " << image->getDiscardLevel()
@@ -691,13 +684,14 @@ void LLViewerTextureList::removeImageFromList(LLViewerFetchedTexture *image)
assert_main_thread();
llassert_always(mInitialized) ;
llassert(image);
+ image->validateRefCount();
S32 count = 0;
if (image->isInImageList())
{
count = mImageList.erase(image) ;
if(count != 1)
- {
+ {
LL_INFOS() << "Image " << image->getID()
<< " had mInImageList set but mImageList.erase() returned " << count
<< LL_ENDL;
@@ -723,6 +717,7 @@ void LLViewerTextureList::removeImageFromList(LLViewerFetchedTexture *image)
LL_INFOS() << "Image " << image->getID() << " was in mUUIDMap with same pointer" << LL_ENDL ;
}
count = mImageList.erase(image) ;
+ llassert(count != 0);
if(count != 0)
{ // it was in the list already?
LL_WARNS() << "Image " << image->getID()
@@ -808,23 +803,23 @@ void LLViewerTextureList::updateImages(F32 max_time)
using namespace LLStatViewer;
sample(NUM_IMAGES, sNumImages);
sample(NUM_RAW_IMAGES, LLImageRaw::sRawImageCount);
- sample(GL_TEX_MEM, LLImageGL::sGlobalTextureMemory);
- sample(GL_BOUND_MEM, LLImageGL::sBoundTextureMemory);
- sample(RAW_MEM, F64Bytes(LLImageRaw::sGlobalRawMemory));
sample(FORMATTED_MEM, F64Bytes(LLImageFormatted::sGlobalFormattedMemory));
}
- //loading from fast cache
- max_time -= updateImagesLoadingFastCache(max_time);
-
- updateImagesDecodePriorities();
-
- F32 total_max_time = max_time;
+ // make sure each call below gets at least its "fair share" of time
+ F32 min_time = max_time * 0.33f;
+ F32 remaining_time = max_time;
- max_time -= updateImagesFetchTextures(max_time);
-
- max_time = llmax(max_time, total_max_time*.50f); // at least 50% of max_time
- max_time -= updateImagesCreateTextures(max_time);
+ //loading from fast cache
+ remaining_time -= updateImagesLoadingFastCache(remaining_time);
+ remaining_time = llmax(remaining_time, min_time);
+
+ //dispatch to texture fetch threads
+ remaining_time -= updateImagesFetchTextures(remaining_time);
+ remaining_time = llmax(remaining_time, min_time);
+
+ //handle results from decode threads
+ updateImagesCreateTextures(remaining_time);
if (!mDirtyTextureList.empty())
{
@@ -849,7 +844,6 @@ void LLViewerTextureList::updateImages(F32 max_time)
didone = image->doLoadedCallbacks();
}
}
-
updateImagesUpdateStats();
}
@@ -872,120 +866,119 @@ void LLViewerTextureList::clearFetchingRequests()
}
}
-void LLViewerTextureList::updateImagesDecodePriorities()
+static void touch_texture(LLViewerFetchedTexture* tex, F32 vsize)
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
- // Update the decode priority for N images each frame
- {
- F32 lazy_flush_timeout = 30.f; // stop decoding
- F32 max_inactive_time = 20.f; // actually delete
- S32 min_refs = 3; // 1 for mImageList, 1 for mUUIDMap, 1 for local reference
-
- //reset imagep->getLastReferencedTimer() when screen is showing the progress view to avoid removing pre-fetched textures too soon.
- bool reset_timer = gViewerWindow->getProgressView()->getVisible();
-
- static const S32 MAX_PRIO_UPDATES = gSavedSettings.getS32("TextureFetchUpdatePriorities"); // default: 32
- const size_t max_update_count = llmin((S32) (MAX_PRIO_UPDATES*MAX_PRIO_UPDATES*gFrameIntervalSeconds.value()) + 1, MAX_PRIO_UPDATES);
- S32 update_counter = llmin(max_update_count, mUUIDMap.size());
- uuid_map_t::iterator iter = mUUIDMap.upper_bound(mLastUpdateKey);
- while ((update_counter-- > 0) && !mUUIDMap.empty())
- {
- if (iter == mUUIDMap.end())
- {
- iter = mUUIDMap.begin();
+ if (tex)
+ {
+ tex->addTextureStats(vsize);
+ }
+}
+
+void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imagep)
+{
+ if (imagep->isInDebug() || imagep->isUnremovable())
+ {
+ //update_counter--;
+ return; //is in debug, ignore.
+ }
+
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE
+ {
+ for (U32 i = 0; i < LLRender::NUM_TEXTURE_CHANNELS; ++i)
+ {
+ for (U32 fi = 0; fi < imagep->getNumFaces(i); ++fi)
+ {
+ const LLFace* face = (*(imagep->getFaceList(i)))[fi];
+
+ if (face && face->getViewerObject() && face->getTextureEntry())
+ {
+ F32 vsize = face->getVirtualSize();
+
+ // if a GLTF material is present, ignore that face
+ // as far as this texture stats go, but update the GLTF material
+ // stats
+ const LLTextureEntry* te = face->getTextureEntry();
+ LLFetchedGLTFMaterial* mat = te ? (LLFetchedGLTFMaterial*)te->getGLTFRenderMaterial() : nullptr;
+ if (mat)
+ {
+ touch_texture(mat->mBaseColorTexture, vsize);
+ touch_texture(mat->mNormalTexture, vsize);
+ touch_texture(mat->mMetallicRoughnessTexture, vsize);
+ touch_texture(mat->mEmissiveTexture, vsize);
+ }
+ else
+ {
+ imagep->addTextureStats(vsize);
+ }
+ }
+ }
+ }
+ }
+
+ F32 lazy_flush_timeout = 30.f; // stop decoding
+ F32 max_inactive_time = 20.f; // actually delete
+ S32 min_refs = 3; // 1 for mImageList, 1 for mUUIDMap, 1 for local reference
+
+ //
+ // Flush formatted images using a lazy flush
+ //
+ S32 num_refs = imagep->getNumRefs();
+ if (num_refs == min_refs)
+ {
+ if (imagep->getLastReferencedTimer()->getElapsedTimeF32() > lazy_flush_timeout)
+ {
+ // Remove the unused image from the image list
+ deleteImage(imagep);
+ imagep = NULL; // should destroy the image
+ }
+ return;
+ }
+ else
+ {
+ if (imagep->hasSavedRawImage())
+ {
+ if (imagep->getElapsedLastReferencedSavedRawImageTime() > max_inactive_time)
+ {
+ imagep->destroySavedRawImage();
}
- mLastUpdateKey = iter->first;
- LLPointer<LLViewerFetchedTexture> imagep = iter->second;
- ++iter; // safe to increment now
+ }
- if(imagep->isInDebug() || imagep->isUnremovable())
- {
- update_counter--;
- continue; //is in debug, ignore.
- }
+ if (imagep->isDeleted())
+ {
+ return;
+ }
+ else if (imagep->isDeletionCandidate())
+ {
+ imagep->destroyTexture();
+ return;
+ }
+ else if (imagep->isInactive())
+ {
+ if (imagep->getLastReferencedTimer()->getElapsedTimeF32() > max_inactive_time)
+ {
+ imagep->setDeletionCandidate();
+ }
+ return;
+ }
+ else
+ {
+ imagep->getLastReferencedTimer()->reset();
- //
- // Flush formatted images using a lazy flush
- //
- S32 num_refs = imagep->getNumRefs();
- if (num_refs == min_refs)
- {
- if(reset_timer)
- {
- imagep->getLastReferencedTimer()->reset();
- }
- else if (imagep->getLastReferencedTimer()->getElapsedTimeF32() > lazy_flush_timeout)
- {
- // Remove the unused image from the image list
- deleteImage(imagep);
- imagep = NULL; // should destroy the image
- }
- continue;
- }
- else
- {
- if(imagep->hasSavedRawImage())
- {
- if(imagep->getElapsedLastReferencedSavedRawImageTime() > max_inactive_time)
- {
- imagep->destroySavedRawImage() ;
- }
- }
-
- if(imagep->isDeleted())
- {
- continue ;
- }
- else if(imagep->isDeletionCandidate())
- {
- imagep->destroyTexture() ;
- continue ;
- }
- else if(imagep->isInactive())
- {
- if(reset_timer)
- {
- imagep->getLastReferencedTimer()->reset();
- }
- else if (imagep->getLastReferencedTimer()->getElapsedTimeF32() > max_inactive_time)
- {
- imagep->setDeletionCandidate() ;
- }
- continue ;
- }
- else
- {
- imagep->getLastReferencedTimer()->reset();
-
- //reset texture state.
- imagep->setInactive() ;
- }
- }
+ //reset texture state.
+ imagep->setInactive();
+ }
+ }
- if (!imagep->isInImageList())
- {
- continue;
- }
- if(imagep->isInFastCacheList())
- {
- continue; //wait for loading from the fast cache.
- }
+ if (!imagep->isInImageList())
+ {
+ return;
+ }
+ if (imagep->isInFastCacheList())
+ {
+ return; //wait for loading from the fast cache.
+ }
- imagep->processTextureStats();
- F32 old_priority = imagep->getDecodePriority();
- F32 old_priority_test = llmax(old_priority, 0.0f);
- F32 decode_priority = imagep->calcDecodePriority();
- F32 decode_priority_test = llmax(decode_priority, 0.0f);
- // Ignore < 20% difference
- if ((decode_priority_test < old_priority_test * .8f) ||
- (decode_priority_test > old_priority_test * 1.25f))
- {
- mImageList.erase(imagep) ;
- imagep->setDecodePriority(decode_priority);
- mImageList.insert(imagep);
- }
- }
- }
+ imagep->processTextureStats();
}
void LLViewerTextureList::setDebugFetching(LLViewerFetchedTexture* tex, S32 debug_level)
@@ -997,17 +990,9 @@ void LLViewerTextureList::setDebugFetching(LLViewerFetchedTexture* tex, S32 debu
}
const F32 DEBUG_PRIORITY = 100000.f;
- F32 old_priority_test = llmax(tex->getDecodePriority(), 0.0f);
- F32 decode_priority_test = DEBUG_PRIORITY;
-
- // Ignore < 20% difference
- if ((decode_priority_test < old_priority_test * .8f) ||
- (decode_priority_test > old_priority_test * 1.25f))
- {
- removeImageFromList(tex);
- tex->setDecodePriority(decode_priority_test);
- addImageToList(tex);
- }
+ removeImageFromList(tex);
+ tex->mMaxVirtualSize = DEBUG_PRIORITY;
+ addImageToList(tex);
}
/*
@@ -1057,10 +1042,11 @@ F32 LLViewerTextureList::updateImagesCreateTextures(F32 max_time)
LLViewerFetchedTexture *imagep = *curiter;
imagep->createTexture();
imagep->postCreateTexture();
- if (create_timer.getElapsedTimeF32() > max_time)
- {
- break;
- }
+
+ if (create_timer.getElapsedTimeF32() > max_time)
+ {
+ break;
+ }
}
mCreateTextureList.erase(mCreateTextureList.begin(), enditer);
return create_timer.getElapsedTimeF32();
@@ -1088,10 +1074,6 @@ F32 LLViewerTextureList::updateImagesLoadingFastCache(F32 max_time)
enditer = iter;
LLViewerFetchedTexture *imagep = *curiter;
imagep->loadFromFastCache();
- if (timer.getElapsedTimeF32() > max_time)
- {
- break;
- }
}
mFastCacheList.erase(mFastCacheList.begin(), enditer);
return timer.getElapsedTimeF32();
@@ -1110,8 +1092,7 @@ void LLViewerTextureList::forceImmediateUpdate(LLViewerFetchedTexture* imagep)
}
imagep->processTextureStats();
- F32 decode_priority = LLViewerFetchedTexture::maxDecodePriority() ;
- imagep->setDecodePriority(decode_priority);
+ imagep->sMaxVirtualSize = LLViewerFetchedTexture::sMaxVirtualSize;
addImageToList(imagep);
return ;
@@ -1120,76 +1101,64 @@ void LLViewerTextureList::forceImmediateUpdate(LLViewerFetchedTexture* imagep)
F32 LLViewerTextureList::updateImagesFetchTextures(F32 max_time)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
- LLTimer image_op_timer;
-
- // Update fetch for N images each frame
- static const S32 MAX_HIGH_PRIO_COUNT = gSavedSettings.getS32("TextureFetchUpdateHighPriority"); // default: 32
- static const S32 MAX_UPDATE_COUNT = gSavedSettings.getS32("TextureFetchUpdateMaxMediumPriority"); // default: 256
- static const S32 MIN_UPDATE_COUNT = gSavedSettings.getS32("TextureFetchUpdateMinMediumPriority"); // default: 32
- static const F32 MIN_PRIORITY_THRESHOLD = gSavedSettings.getF32("TextureFetchUpdatePriorityThreshold"); // default: 0.0
- static const bool SKIP_LOW_PRIO = gSavedSettings.getBOOL("TextureFetchUpdateSkipLowPriority"); // default: false
-
- size_t max_priority_count = llmin((S32) (MAX_HIGH_PRIO_COUNT*MAX_HIGH_PRIO_COUNT*gFrameIntervalSeconds.value())+1, MAX_HIGH_PRIO_COUNT);
- max_priority_count = llmin(max_priority_count, mImageList.size());
-
- size_t total_update_count = mUUIDMap.size();
- size_t max_update_count = llmin((S32) (MAX_UPDATE_COUNT*MAX_UPDATE_COUNT*gFrameIntervalSeconds.value())+1, MAX_UPDATE_COUNT);
- max_update_count = llmin(max_update_count, total_update_count);
-
- // MAX_HIGH_PRIO_COUNT high priority entries
- typedef std::vector<LLViewerFetchedTexture*> entries_list_t;
- entries_list_t entries;
- size_t update_counter = max_priority_count;
- image_priority_list_t::iterator iter1 = mImageList.begin();
- while(update_counter > 0)
- {
- entries.push_back(*iter1);
-
- ++iter1;
- update_counter--;
- }
-
- // MAX_UPDATE_COUNT cycled entries
- update_counter = max_update_count;
- if(update_counter > 0)
- {
- uuid_map_t::iterator iter2 = mUUIDMap.upper_bound(mLastFetchKey);
- while ((update_counter > 0) && (total_update_count > 0))
- {
- if (iter2 == mUUIDMap.end())
- {
- iter2 = mUUIDMap.begin();
- }
- LLViewerFetchedTexture* imagep = iter2->second;
- // Skip the textures where there's really nothing to do so to give some times to others. Also skip the texture if it's already in the high prio set.
- if (!SKIP_LOW_PRIO || (SKIP_LOW_PRIO && ((imagep->getDecodePriority() > MIN_PRIORITY_THRESHOLD) || imagep->hasFetcher())))
+ typedef std::vector<LLPointer<LLViewerFetchedTexture> > entries_list_t;
+ entries_list_t entries;
+
+ // update N textures at beginning of mImageList
+ U32 update_count = 0;
+ static const S32 MIN_UPDATE_COUNT = gSavedSettings.getS32("TextureFetchUpdateMinCount"); // default: 32
+ // WIP -- dumb code here
+ //update MIN_UPDATE_COUNT or 5% of other textures, whichever is greater
+ update_count = llmax((U32) MIN_UPDATE_COUNT, (U32) mUUIDMap.size()/20);
+ update_count = llmin(update_count, (U32) mUUIDMap.size());
+
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vtluift - copy");
+
+ // copy entries out of UUID map for updating
+ entries.reserve(update_count);
+ uuid_map_t::iterator iter = mUUIDMap.upper_bound(mLastUpdateKey);
+ while (update_count-- > 0)
+ {
+ if (iter == mUUIDMap.end())
+ {
+ iter = mUUIDMap.begin();
+ }
+
+ if (iter->second->getGLTexture())
{
- entries.push_back(imagep);
- update_counter--;
+ entries.push_back(iter->second);
}
+ ++iter;
+ }
+ }
- iter2++;
- total_update_count--;
- }
- }
+ LLTimer timer;
- size_t min_update_count = llmin(MIN_UPDATE_COUNT,(S32)(entries.size()-max_priority_count));
- S32 min_count = max_priority_count + min_update_count;
- for (entries_list_t::iterator iter3 = entries.begin();
- iter3 != entries.end(); )
- {
- LLViewerFetchedTexture* imagep = *iter3++;
- imagep->updateFetch();
- if (min_count <= min_update_count)
- {
- mLastFetchKey = LLTextureKey(imagep->getID(), (ETexListType)imagep->getTextureListType());
- }
- if ((min_count-- <= 0) && (image_op_timer.getElapsedTimeF32() > max_time))
- {
- break;
- }
- }
- return image_op_timer.getElapsedTimeF32();
+ LLPointer<LLViewerTexture> last_imagep = nullptr;
+
+ for (auto& imagep : entries)
+ {
+ if (imagep->getNumRefs() > 1) // make sure this image hasn't been deleted before attempting to update (may happen as a side effect of some other image updating)
+ {
+ updateImageDecodePriority(imagep);
+ imagep->updateFetch();
+ }
+
+ last_imagep = imagep;
+
+ if (timer.getElapsedTimeF32() > max_time)
+ {
+ break;
+ }
+ }
+
+ if (last_imagep)
+ {
+ mLastUpdateKey = LLTextureKey(last_imagep->getID(), (ETexListType)last_imagep->getTextureListType());
+ }
+
+ return timer.getElapsedTimeF32();
}
void LLViewerTextureList::updateImagesUpdateStats()
@@ -1232,8 +1201,6 @@ void LLViewerTextureList::decodeAllImages(F32 max_time)
{
LLViewerFetchedTexture* imagep = *iter;
imagep->processTextureStats();
- F32 decode_priority = imagep->calcDecodePriority();
- imagep->setDecodePriority(decode_priority);
addImageToList(imagep);
}
image_list.clear();
@@ -1340,15 +1307,18 @@ BOOL LLViewerTextureList::createUploadFile(const std::string& filename,
}
// note: modifies the argument raw_image!!!!
-LLPointer<LLImageJ2C> LLViewerTextureList::convertToUploadFile(LLPointer<LLImageRaw> raw_image, const S32 max_image_dimentions)
+LLPointer<LLImageJ2C> LLViewerTextureList::convertToUploadFile(LLPointer<LLImageRaw> raw_image, const S32 max_image_dimentions, bool force_lossless)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
raw_image->biasedScaleToPowerOfTwo(max_image_dimentions);
LLPointer<LLImageJ2C> compressedImage = new LLImageJ2C();
- if (gSavedSettings.getBOOL("LosslessJ2CUpload") &&
- (raw_image->getWidth() * raw_image->getHeight() <= LL_IMAGE_REZ_LOSSLESS_CUTOFF * LL_IMAGE_REZ_LOSSLESS_CUTOFF))
- compressedImage->setReversible(TRUE);
+ if (force_lossless ||
+ (gSavedSettings.getBOOL("LosslessJ2CUpload") &&
+ (raw_image->getWidth() * raw_image->getHeight() <= LL_IMAGE_REZ_LOSSLESS_CUTOFF * LL_IMAGE_REZ_LOSSLESS_CUTOFF)))
+ {
+ compressedImage->setReversible(TRUE);
+ }
if (gSavedSettings.getBOOL("Jpeg2000AdvancedCompression"))
@@ -1373,156 +1343,6 @@ LLPointer<LLImageJ2C> LLViewerTextureList::convertToUploadFile(LLPointer<LLImage
return compressedImage;
}
-// Returns min setting for TextureMemory (in MB)
-S32Megabytes LLViewerTextureList::getMinVideoRamSetting()
-{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
- U32Megabytes system_ram = gSysMemory.getPhysicalMemoryKB();
- //min texture mem sets to 64M if total physical mem is more than 1.5GB
- return (system_ram > U32Megabytes(1500)) ? S32Megabytes(64) : gMinVideoRam ;
-}
-
-//static
-// Returns max setting for TextureMemory (in MB)
-S32Megabytes LLViewerTextureList::getMaxVideoRamSetting(bool get_recommended, float mem_multiplier)
-{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
- S32Megabytes max_texmem;
- if (gGLManager.mVRAM != 0)
- {
- // Treat any card with < 32 MB (shudder) as having 32 MB
- // - it's going to be swapping constantly regardless
- S32Megabytes max_vram(gGLManager.mVRAM);
-
- if(gGLManager.mIsAMD)
- {
- //shrink the availabe vram for ATI cards because some of them do not handel texture swapping well.
- max_vram = max_vram * 0.75f;
- }
-
- max_vram = llmax(max_vram, getMinVideoRamSetting());
- max_texmem = max_vram;
- if (!get_recommended)
- max_texmem *= 2;
- }
- else
- {
- if (!get_recommended)
- {
- max_texmem = (S32Megabytes)512;
- }
- else if (gSavedSettings.getBOOL("NoHardwareProbe")) //did not do hardware detection at startup
- {
- max_texmem = (S32Megabytes)512;
- }
- else
- {
- max_texmem = (S32Megabytes)128;
- }
- }
-
- S32Megabytes system_ram = gSysMemory.getPhysicalMemoryKB(); // In MB
- //LL_INFOS() << "*** DETECTED " << system_ram << " MB of system memory." << LL_ENDL;
- if (get_recommended)
- max_texmem = llmin(max_texmem, system_ram/2);
- else
- max_texmem = llmin(max_texmem, system_ram);
-
- // limit the texture memory to a multiple of the default if we've found some cards to behave poorly otherwise
- max_texmem = llmin(max_texmem, (S32Megabytes) (mem_multiplier * max_texmem));
-
- max_texmem = llclamp(max_texmem, getMinVideoRamSetting(), gMaxVideoRam);
-
- return max_texmem;
-}
-
-bool LLViewerTextureList::isPrioRequestsFetched()
-{
- static LLCachedControl<F32> prio_threshold(gSavedSettings, "TextureFetchUpdatePriorityThreshold", 0.0f);
- static LLCachedControl<F32> fetching_textures_threshold(gSavedSettings, "TextureListFetchingThreshold", 0.97f);
- S32 fetching_tex_count = 0;
- S32 tex_count_threshold = gTextureList.mImageList.size() * (1 - fetching_textures_threshold);
-
- for (LLViewerTextureList::image_priority_list_t::iterator iter = gTextureList.mImageList.begin();
- iter != gTextureList.mImageList.end(); )
- {
- LLPointer<LLViewerFetchedTexture> imagep = *iter++;
- if (imagep->getDecodePriority() > prio_threshold)
- {
- if (imagep->hasFetcher() || imagep->isFetching())
- {
- fetching_tex_count++;
- if (fetching_tex_count >= tex_count_threshold)
- {
- return false;
- }
- }
- }
- }
-
- return true;
-}
-
-const S32Megabytes VIDEO_CARD_FRAMEBUFFER_MEM(12);
-const S32Megabytes MIN_MEM_FOR_NON_TEXTURE(512);
-void LLViewerTextureList::updateMaxResidentTexMem(S32Megabytes mem)
-{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
- // Initialize the image pipeline VRAM settings
- S32Megabytes cur_mem(gSavedSettings.getS32("TextureMemory"));
- F32 mem_multiplier = gSavedSettings.getF32("RenderTextureMemoryMultiple");
- S32Megabytes default_mem = getMaxVideoRamSetting(true, mem_multiplier); // recommended default
- if (mem == (S32Bytes)0)
- {
- mem = cur_mem > (S32Bytes)0 ? cur_mem : default_mem;
- }
- else if (mem < (S32Bytes)0)
- {
- mem = default_mem;
- }
-
- mem = llclamp(mem, getMinVideoRamSetting(), getMaxVideoRamSetting(false, mem_multiplier));
- if (mem != cur_mem)
- {
- gSavedSettings.setS32("TextureMemory", mem.value());
- return; //listener will re-enter this function
- }
-
- if (gGLManager.mVRAM == 0)
- {
- LL_WARNS() << "VRAM amount not detected, defaulting to " << mem << " MB" << LL_ENDL;
- }
-
- // TODO: set available resident texture mem based on use by other subsystems
- // currently max(12MB, VRAM/4) assumed...
-
- S32Megabytes vb_mem = mem;
- S32Megabytes fb_mem = llmax(VIDEO_CARD_FRAMEBUFFER_MEM, vb_mem/4);
- mMaxResidentTexMemInMegaBytes = (vb_mem - fb_mem) ; //in MB
-
- mMaxTotalTextureMemInMegaBytes = mMaxResidentTexMemInMegaBytes * 2;
- if (mMaxResidentTexMemInMegaBytes > (S32Megabytes)640)
- {
- mMaxTotalTextureMemInMegaBytes -= (mMaxResidentTexMemInMegaBytes / 4);
- }
-
- //system mem
- S32Megabytes system_ram = gSysMemory.getPhysicalMemoryKB();
-
- //minimum memory reserved for non-texture use.
- //if system_raw >= 1GB, reserve at least 512MB for non-texture use;
- //otherwise reserve half of the system_ram for non-texture use.
- S32Megabytes min_non_texture_mem = llmin(system_ram / 2, MIN_MEM_FOR_NON_TEXTURE) ;
-
- if (mMaxTotalTextureMemInMegaBytes > system_ram - min_non_texture_mem)
- {
- mMaxTotalTextureMemInMegaBytes = system_ram - min_non_texture_mem ;
- }
-
- LL_INFOS() << "Total Video Memory set to: " << vb_mem << " MB" << LL_ENDL;
- LL_INFOS() << "Available Texture Memory set to: " << (vb_mem - fb_mem) << " MB" << LL_ENDL;
-}
-
///////////////////////////////////////////////////////////////////////////////
// We've been that the asset server does not contain the requested image id.
diff --git a/indra/newview/llviewertexturelist.h b/indra/newview/llviewertexturelist.h
index 0018e78d45..1b740d8c76 100644
--- a/indra/newview/llviewertexturelist.h
+++ b/indra/newview/llviewertexturelist.h
@@ -1,10 +1,10 @@
/**
- * @file llviewertexturelinumimagest.h
+ * @file llviewertexturelist.h
* @brief Object for managing the list of images within a region
*
- * $LicenseInfo:firstyear=2000&license=viewerlgpl$
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
+ * 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
@@ -96,7 +96,7 @@ public:
const std::string& out_filename,
const U8 codec,
const S32 max_image_dimentions = LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT);
- static LLPointer<LLImageJ2C> convertToUploadFile(LLPointer<LLImageRaw> raw_image, const S32 max_image_dimentions = LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT);
+ static LLPointer<LLImageJ2C> convertToUploadFile(LLPointer<LLImageRaw> raw_image, const S32 max_image_dimentions = LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT, bool force_lossless = false);
static void processImageNotInDatabase( LLMessageSystem *msg, void **user_data );
public:
@@ -125,12 +125,9 @@ public:
void handleIRCallback(void **data, const S32 number);
- S32Megabytes getMaxResidentTexMem() const { return mMaxResidentTexMemInMegaBytes; }
- S32Megabytes getMaxTotalTextureMem() const { return mMaxTotalTextureMemInMegaBytes;}
S32 getNumImages() { return mImageList.size(); }
- void updateMaxResidentTexMem(S32Megabytes mem);
-
+ // Local UI images
// Local UI images
void doPreloadImages();
// Network images. Needs caps and cache to work
@@ -139,13 +136,12 @@ public:
void clearFetchingRequests();
void setDebugFetching(LLViewerFetchedTexture* tex, S32 debug_level);
- static S32Megabytes getMinVideoRamSetting();
- static S32Megabytes getMaxVideoRamSetting(bool get_recommended, float mem_multiplier);
-
- static bool isPrioRequestsFetched();
-
private:
- void updateImagesDecodePriorities();
+ // do some book keeping on the specified texture
+ // - updates decode priority
+ // - updates desired discard level
+ // - cleans up textures that haven't been referenced in awhile
+ void updateImageDecodePriority(LLViewerFetchedTexture* imagep);
F32 updateImagesCreateTextures(F32 max_time);
F32 updateImagesFetchTextures(F32 max_time);
void updateImagesUpdateStats();
@@ -218,17 +214,14 @@ private:
typedef std::map< LLTextureKey, LLPointer<LLViewerFetchedTexture> > uuid_map_t;
uuid_map_t mUUIDMap;
LLTextureKey mLastUpdateKey;
- LLTextureKey mLastFetchKey;
- typedef std::set<LLPointer<LLViewerFetchedTexture>, LLViewerFetchedTexture::Compare> image_priority_list_t;
+ typedef std::set < LLPointer<LLViewerFetchedTexture> > image_priority_list_t;
image_priority_list_t mImageList;
// simply holds on to LLViewerFetchedTexture references to stop them from being purged too soon
std::set<LLPointer<LLViewerFetchedTexture> > mImagePreloads;
BOOL mInitialized ;
- S32Megabytes mMaxResidentTexMemInMegaBytes;
- S32Megabytes mMaxTotalTextureMemInMegaBytes;
LLFrameTimer mForceDecodeTimer;
private:
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index ddc11ac0bd..5c1467f28f 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -227,6 +227,7 @@ extern BOOL gDebugClicks;
extern BOOL gDisplaySwapBuffers;
extern BOOL gDepthDirty;
extern BOOL gResizeScreenTexture;
+extern BOOL gCubeSnapshot;
LLViewerWindow *gViewerWindow = NULL;
@@ -494,24 +495,12 @@ public:
if (gSavedSettings.getBOOL("DebugShowTime"))
{
- {
- const U32 y_inc2 = 15;
- LLFrameTimer& timer = gTextureTimer;
- F32 time = timer.getElapsedTimeF32();
- S32 hours = (S32)(time / (60*60));
- S32 mins = (S32)((time - hours*(60*60)) / 60);
- S32 secs = (S32)((time - hours*(60*60) - mins*60));
- addText(xpos, ypos, llformat("Texture: %d:%02d:%02d", hours,mins,secs)); ypos += y_inc2;
- }
-
- {
F32 time = gFrameTimeSeconds;
S32 hours = (S32)(time / (60*60));
S32 mins = (S32)((time - hours*(60*60)) / 60);
S32 secs = (S32)((time - hours*(60*60) - mins*60));
addText(xpos, ypos, llformat("Time: %d:%02d:%02d", hours,mins,secs)); ypos += y_inc;
}
- }
if (gSavedSettings.getBOOL("DebugShowMemory"))
{
@@ -610,29 +599,6 @@ public:
{
LLTrace::Recording& last_frame_recording = LLTrace::get_frame_recording().getLastRecording();
- if (gGLManager.mHasATIMemInfo)
- {
- S32 meminfo[4];
- glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, meminfo);
-
- addText(xpos, ypos, llformat("%.2f MB Texture Memory Free", meminfo[0]/1024.f));
- ypos += y_inc;
-
- if (gGLManager.mHasVertexBufferObject)
- {
- glGetIntegerv(GL_VBO_FREE_MEMORY_ATI, meminfo);
- addText(xpos, ypos, llformat("%.2f MB VBO Memory Free", meminfo[0]/1024.f));
- ypos += y_inc;
- }
- }
- else if (gGLManager.mHasNVXMemInfo)
- {
- S32 free_memory;
- glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &free_memory);
- addText(xpos, ypos, llformat("%.2f MB Video Memory Free", free_memory/1024.f));
- ypos += y_inc;
- }
-
//show streaming cost/triangle count of known prims in current region OR selection
{
F32 cost = 0.f;
@@ -692,24 +658,6 @@ public:
}
- addText(xpos, ypos, llformat("%d MB Index Data (%d MB Pooled, %d KIndices)", LLVertexBuffer::sAllocatedIndexBytes/(1024*1024), LLVBOPool::sIndexBytesPooled/(1024*1024), LLVertexBuffer::sIndexCount/1024));
- ypos += y_inc;
-
- addText(xpos, ypos, llformat("%d MB Vertex Data (%d MB Pooled, %d KVerts)", LLVertexBuffer::sAllocatedBytes/(1024*1024), LLVBOPool::sBytesPooled/(1024*1024), LLVertexBuffer::sVertexCount/1024));
- ypos += y_inc;
-
- addText(xpos, ypos, llformat("%d Vertex Buffers", LLVertexBuffer::sGLCount));
- ypos += y_inc;
-
- addText(xpos, ypos, llformat("%d Mapped Buffers", LLVertexBuffer::sMappedCount));
- ypos += y_inc;
-
- addText(xpos, ypos, llformat("%d Vertex Buffer Binds", LLVertexBuffer::sBindCount));
- ypos += y_inc;
-
- addText(xpos, ypos, llformat("%d Vertex Buffer Sets", LLVertexBuffer::sSetCount));
- ypos += y_inc;
-
addText(xpos, ypos, llformat("%d Texture Binds", LLImageGL::sBindCount));
ypos += y_inc;
@@ -784,9 +732,7 @@ public:
ypos += y_inc;
}
- LLVertexBuffer::sBindCount = LLImageGL::sBindCount =
- LLVertexBuffer::sSetCount = LLImageGL::sUniqueCount =
- gPipeline.mNumVisibleNodes = LLPipeline::sVisibleLightCount = 0;
+ gPipeline.mNumVisibleNodes = LLPipeline::sVisibleLightCount = 0;
}
if (gSavedSettings.getBOOL("DebugShowAvatarRenderInfo"))
{
@@ -1913,6 +1859,11 @@ LLViewerWindow::LLViewerWindow(const Params& p)
U32 fsaa_samples)
*/
// create window
+
+ U32 max_core_count = gSavedSettings.getU32("EmulateCoreCount");
+ U32 max_vram = gSavedSettings.getU32("RenderMaxVRAMBudget");
+ F32 max_gl_version = gSavedSettings.getF32("RenderMaxOpenGLVersion");
+
mWindow = LLWindowManager::createWindow(this,
p.title, p.name, p.x, p.y, p.width, p.height, 0,
p.fullscreen,
@@ -1920,7 +1871,10 @@ LLViewerWindow::LLViewerWindow(const Params& p)
gSavedSettings.getBOOL("RenderVSyncEnable"),
!gHeadlessClient,
p.ignore_pixel_depth,
- gSavedSettings.getBOOL("RenderDeferred") ? 0 : gSavedSettings.getU32("RenderFSAASamples")); //don't use window level anti-aliasing if FBOs are enabled
+ 0,
+ max_core_count,
+ max_vram,
+ max_gl_version); //don't use window level anti-aliasing
if (NULL == mWindow)
{
@@ -1999,12 +1953,7 @@ LLViewerWindow::LLViewerWindow(const Params& p)
LL_DEBUGS("Window") << "Loading feature tables." << LL_ENDL;
// Initialize OpenGL Renderer
- if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderVBOEnable") ||
- !gGLManager.mHasVertexBufferObject)
- {
- gSavedSettings.setBOOL("RenderVBOEnable", FALSE);
- }
- LLVertexBuffer::initClass(gSavedSettings.getBOOL("RenderVBOEnable"), gSavedSettings.getBOOL("RenderVBOMappingDisable"));
+ LLVertexBuffer::initClass(mWindow);
LL_INFOS("RenderInit") << "LLVertexBuffer initialization done." << LL_ENDL ;
gGL.init(true);
@@ -2017,11 +1966,6 @@ LLViewerWindow::LLViewerWindow(const Params& p)
gSavedSettings.setBOOL("ProbeHardwareOnStartup", FALSE);
}
- if (!gGLManager.mHasDepthClamp)
- {
- LL_INFOS("RenderInit") << "Missing feature GL_ARB_depth_clamp. Void water might disappear in rare cases." << LL_ENDL;
- }
-
// If we crashed while initializng GL stuff last time, disable certain features
if (gSavedSettings.getBOOL("RenderInitError"))
{
@@ -2682,10 +2626,10 @@ void LLViewerWindow::setMenuBackgroundColor(bool god_mode, bool dev_grid)
void LLViewerWindow::drawDebugText()
{
+ gUIProgram.bind();
gGL.color4f(1,1,1,1);
gGL.pushMatrix();
gGL.pushUIMatrix();
- gUIProgram.bind();
{
// scale view by UI global scale factor and aspect ratio correction factor
gGL.scaleUI(mDisplayScale.mV[VX], mDisplayScale.mV[VY], 1.f);
@@ -2742,6 +2686,7 @@ void LLViewerWindow::draw()
// No translation needed, this view is glued to 0,0
gUIProgram.bind();
+ gGL.color4f(1, 1, 1, 1);
gGL.pushMatrix();
LLUI::pushMatrix();
@@ -3397,7 +3342,7 @@ void LLViewerWindow::updateUI()
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST))
{
gDebugRaycastFaceHit = -1;
- gDebugRaycastObject = cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE,
+ gDebugRaycastObject = cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE, TRUE,
&gDebugRaycastFaceHit,
&gDebugRaycastIntersection,
&gDebugRaycastTexCoord,
@@ -4274,13 +4219,13 @@ void LLViewerWindow::pickAsync( S32 x,
BOOL pick_rigged,
BOOL pick_unselectable)
{
- BOOL in_build_mode = LLFloaterReg::instanceVisible("build");
- if (in_build_mode || LLDrawPoolAlpha::sShowDebugAlpha)
- {
- // build mode allows interaction with all transparent objects
- // "Show Debug Alpha" means no object actually transparent
- pick_transparent = TRUE;
- }
+ // "Show Debug Alpha" means no object actually transparent
+ BOOL in_build_mode = LLFloaterReg::instanceVisible("build");
+ if (LLDrawPoolAlpha::sShowDebugAlpha
+ || (in_build_mode && gSavedSettings.getBOOL("SelectInvisibleObjects")))
+ {
+ pick_transparent = TRUE;
+ }
LLPickInfo pick_info(LLCoordGL(x, y_from_bot), mask, pick_transparent, pick_rigged, FALSE, TRUE, pick_unselectable, callback);
schedulePick(pick_info);
@@ -4338,10 +4283,10 @@ void LLViewerWindow::returnEmptyPicks()
}
// Performs the GL object/land pick.
-LLPickInfo LLViewerWindow::pickImmediate(S32 x, S32 y_from_bot, BOOL pick_transparent, BOOL pick_rigged, BOOL pick_particle)
+LLPickInfo LLViewerWindow::pickImmediate(S32 x, S32 y_from_bot, BOOL pick_transparent, BOOL pick_rigged, BOOL pick_particle, BOOL pick_unselectable)
{
BOOL in_build_mode = LLFloaterReg::instanceVisible("build");
- if (in_build_mode || LLDrawPoolAlpha::sShowDebugAlpha)
+ if ((in_build_mode && gSavedSettings.getBOOL("SelectInvisibleObjects")) || LLDrawPoolAlpha::sShowDebugAlpha)
{
// build mode allows interaction with all transparent objects
// "Show Debug Alpha" means no object actually transparent
@@ -4387,6 +4332,7 @@ LLViewerObject* LLViewerWindow::cursorIntersect(S32 mouse_x, S32 mouse_y, F32 de
S32 this_face,
BOOL pick_transparent,
BOOL pick_rigged,
+ BOOL pick_unselectable,
S32* face_hit,
LLVector4a *intersection,
LLVector2 *uv,
@@ -4457,7 +4403,7 @@ LLViewerObject* LLViewerWindow::cursorIntersect(S32 mouse_x, S32 mouse_y, F32 de
{
if (this_object->isHUDAttachment()) // is a HUD object?
{
- if (this_object->lineSegmentIntersect(mh_start, mh_end, this_face, pick_transparent, pick_rigged,
+ if (this_object->lineSegmentIntersect(mh_start, mh_end, this_face, pick_transparent, pick_rigged, pick_unselectable,
face_hit, intersection, uv, normal, tangent))
{
found = this_object;
@@ -4465,7 +4411,7 @@ LLViewerObject* LLViewerWindow::cursorIntersect(S32 mouse_x, S32 mouse_y, F32 de
}
else // is a world object
{
- if (this_object->lineSegmentIntersect(mw_start, mw_end, this_face, pick_transparent, pick_rigged,
+ if (this_object->lineSegmentIntersect(mw_start, mw_end, this_face, pick_transparent, pick_rigged, pick_unselectable,
face_hit, intersection, uv, normal, tangent))
{
found = this_object;
@@ -4479,7 +4425,7 @@ LLViewerObject* LLViewerWindow::cursorIntersect(S32 mouse_x, S32 mouse_y, F32 de
if (!found) // if not found in HUD, look in world:
{
- found = gPipeline.lineSegmentIntersectInWorld(mw_start, mw_end, pick_transparent, pick_rigged,
+ found = gPipeline.lineSegmentIntersectInWorld(mw_start, mw_end, pick_transparent, pick_rigged, pick_unselectable,
face_hit, intersection, uv, normal, tangent);
if (found && !pick_transparent)
{
@@ -4737,8 +4683,8 @@ void LLViewerWindow::saveImageNumbered(LLImageFormatted *image, BOOL force_picke
else
pick_type = LLFilePicker::FFSAVE_ALL;
- (new LLFilePickerReplyThread(boost::bind(&LLViewerWindow::onDirectorySelected, this, _1, formatted_image, success_cb, failure_cb), pick_type, proposed_name,
- boost::bind(&LLViewerWindow::onSelectionFailure, this, failure_cb)))->getFile();
+ LLFilePickerReplyThread::startPicker(boost::bind(&LLViewerWindow::onDirectorySelected, this, _1, formatted_image, success_cb, failure_cb), pick_type, proposed_name,
+ boost::bind(&LLViewerWindow::onSelectionFailure, this, failure_cb));
}
else
{
@@ -4952,7 +4898,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
// PRE SNAPSHOT
gDisplaySwapBuffers = FALSE;
- glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+ glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); // stencil buffer is deprecated | GL_STENCIL_BUFFER_BIT);
setCursor(UI_CURSOR_WAIT);
// Hide all the UI widgets first and draw a frame
@@ -5004,10 +4950,10 @@ 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.mDeferredScreen.getWidth();
- original_height = gPipeline.mDeferredScreen.getHeight();
+ original_width = gPipeline.mRT->deferredScreen.getWidth();
+ original_height = gPipeline.mRT->deferredScreen.getHeight();
if (gPipeline.allocateScreenBuffer(image_width, image_height))
{
@@ -5086,8 +5032,6 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
F32 depth_conversion_factor_1 = (LLViewerCamera::getInstance()->getFar() + LLViewerCamera::getInstance()->getNear()) / (2.f * LLViewerCamera::getInstance()->getFar() * LLViewerCamera::getInstance()->getNear());
F32 depth_conversion_factor_2 = (LLViewerCamera::getInstance()->getFar() - LLViewerCamera::getInstance()->getNear()) / (2.f * LLViewerCamera::getInstance()->getFar() * LLViewerCamera::getInstance()->getNear());
- gObjectList.generatePickList(*LLViewerCamera::getInstance());
-
// Subimages are in fact partial rendering of the final view. This happens when the final view is bigger than the screen.
// In most common cases, scale_factor is 1 and there's no more than 1 iteration on x and y
for (int subimage_y = 0; subimage_y < scale_factor; ++subimage_y)
@@ -5250,9 +5194,10 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
BOOL LLViewerWindow::simpleSnapshot(LLImageRaw* raw, S32 image_width, S32 image_height, const int num_render_passes)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_APP;
gDisplaySwapBuffers = FALSE;
- glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+ glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); // stencil buffer is deprecated | GL_STENCIL_BUFFER_BIT);
setCursor(UI_CURSOR_WAIT);
BOOL prev_draw_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI) ? TRUE : FALSE;
@@ -5264,14 +5209,12 @@ BOOL LLViewerWindow::simpleSnapshot(LLImageRaw* raw, S32 image_width, S32 image_
LLPipeline::sShowHUDAttachments = FALSE;
LLRect window_rect = getWorldViewRectRaw();
- S32 original_width = LLPipeline::sRenderDeferred ? gPipeline.mDeferredScreen.getWidth() : gViewerWindow->getWorldViewWidthRaw();
- S32 original_height = LLPipeline::sRenderDeferred ? gPipeline.mDeferredScreen.getHeight() : gViewerWindow->getWorldViewHeightRaw();
+ S32 original_width = LLPipeline::sRenderDeferred ? gPipeline.mRT->deferredScreen.getWidth() : gViewerWindow->getWorldViewWidthRaw();
+ S32 original_height = LLPipeline::sRenderDeferred ? gPipeline.mRT->deferredScreen.getHeight() : gViewerWindow->getWorldViewHeightRaw();
LLRenderTarget scratch_space;
U32 color_fmt = GL_RGBA;
- const bool use_depth_buffer = true;
- const bool use_stencil_buffer = true;
- 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))
{
@@ -5346,6 +5289,149 @@ BOOL LLViewerWindow::simpleSnapshot(LLImageRaw* raw, S32 image_width, S32 image_
return true;
}
+void display_cube_face();
+
+BOOL LLViewerWindow::cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubearray, S32 cubeIndex, S32 face, F32 near_clip, bool dynamic_render)
+{
+ // NOTE: implementation derived from LLFloater360Capture::capture360Images() and simpleSnapshot
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_APP;
+ LL_PROFILE_GPU_ZONE("cubeSnapshot");
+ llassert(LLPipeline::sRenderDeferred);
+ llassert(!gCubeSnapshot); //assert a snapshot isn't already in progress
+
+ U32 res = gPipeline.mRT->deferredScreen.getWidth();
+
+ //llassert(res <= gPipeline.mRT->deferredScreen.getWidth());
+ //llassert(res <= gPipeline.mRT->deferredScreen.getHeight());
+
+ // save current view/camera settings so we can restore them afterwards
+ S32 old_occlusion = LLPipeline::sUseOcclusion;
+
+ // set new parameters specific to the 360 requirements
+ LLPipeline::sUseOcclusion = 0;
+ LLViewerCamera* camera = LLViewerCamera::getInstance();
+
+ LLViewerCamera saved_camera = LLViewerCamera::instance();
+ glh::matrix4f saved_proj = get_current_projection();
+ glh::matrix4f saved_mod = get_current_modelview();
+
+ // camera constants for the square, cube map capture image
+ camera->setAspect(1.0); // must set aspect ratio first to avoid undesirable clamping of vertical FoV
+ camera->setView(F_PI_BY_TWO);
+ camera->yaw(0.0);
+ camera->setOrigin(origin);
+ camera->setNear(near_clip);
+
+ glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); // stencil buffer is deprecated | GL_STENCIL_BUFFER_BIT);
+
+ U32 dynamic_render_types[] = {
+ LLPipeline::RENDER_TYPE_AVATAR,
+ LLPipeline::RENDER_TYPE_CONTROL_AV,
+ LLPipeline::RENDER_TYPE_PARTICLES
+ };
+ constexpr U32 dynamic_render_type_count = sizeof(dynamic_render_types) / sizeof(U32);
+ bool prev_dynamic_render_type[dynamic_render_type_count];
+
+
+ if (!dynamic_render)
+ {
+ for (int i = 0; i < dynamic_render_type_count; ++i)
+ {
+ prev_dynamic_render_type[i] = gPipeline.hasRenderType(dynamic_render_types[i]);
+ if (prev_dynamic_render_type[i])
+ {
+ gPipeline.toggleRenderType(dynamic_render_types[i]);
+ }
+ }
+ }
+
+ BOOL prev_draw_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI) ? TRUE : FALSE;
+ if (prev_draw_ui != false)
+ {
+ LLPipeline::toggleRenderDebugFeature(LLPipeline::RENDER_DEBUG_FEATURE_UI);
+ }
+
+ LLPipeline::sShowHUDAttachments = FALSE;
+ LLRect window_rect = getWorldViewRectRaw();
+
+ mWorldViewRectRaw.set(0, res, res, 0);
+
+ // these are the 6 directions we will point the camera, see LLCubeMapArray::sTargets
+ LLVector3 look_dirs[6] = {
+ LLVector3(1, 0, 0),
+ LLVector3(-1, 0, 0),
+ LLVector3(0, 1, 0),
+ LLVector3(0, -1, 0),
+ LLVector3(0, 0, 1),
+ LLVector3(0, 0, -1)
+ };
+
+ LLVector3 look_upvecs[6] = {
+ LLVector3(0, -1, 0),
+ LLVector3(0, -1, 0),
+ LLVector3(0, 0, 1),
+ LLVector3(0, 0, -1),
+ LLVector3(0, -1, 0),
+ LLVector3(0, -1, 0)
+ };
+
+ // for each of six sides of cubemap
+ //for (int i = 0; i < 6; ++i)
+ int i = face;
+ {
+ // set up camera to look in each direction
+ camera->lookDir(look_dirs[i], look_upvecs[i]);
+
+ // turning this flag off here prohibits the screen swap
+ // to present the new page to the viewer - this stops
+ // the black flash in between captures when the number
+ // of render passes is more than 1. We need to also
+ // set it here because code in LLViewerDisplay resets
+ // it to TRUE each time.
+ gDisplaySwapBuffers = FALSE;
+
+ // actually render the scene
+ gCubeSnapshot = TRUE;
+ display_cube_face();
+ gCubeSnapshot = FALSE;
+ }
+
+ gDisplaySwapBuffers = TRUE;
+
+ if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
+ {
+ if (prev_draw_ui != false)
+ {
+ LLPipeline::toggleRenderDebugFeature(LLPipeline::RENDER_DEBUG_FEATURE_UI);
+ }
+ }
+
+ if (!dynamic_render)
+ {
+ for (int i = 0; i < dynamic_render_type_count; ++i)
+ {
+ if (prev_dynamic_render_type[i])
+ {
+ gPipeline.toggleRenderType(dynamic_render_types[i]);
+ }
+ }
+ }
+
+ LLPipeline::sShowHUDAttachments = TRUE;
+
+ gPipeline.resetDrawOrders();
+ mWorldViewRectRaw = window_rect;
+
+ // restore original view/camera/avatar settings settings
+ *camera = saved_camera;
+ set_current_modelview(saved_mod);
+ set_current_projection(saved_proj);
+ LLPipeline::sUseOcclusion = old_occlusion;
+
+ // ====================================================
+ return true;
+}
+
void LLViewerWindow::destroyWindow()
{
if (mWindow)
@@ -5568,7 +5654,6 @@ void LLViewerWindow::stopGL(BOOL save_state)
// Pause texture decode threads (will get unpaused during main loop)
LLAppViewer::getTextureCache()->pause();
- LLAppViewer::getImageDecodeThread()->pause();
LLAppViewer::getTextureFetch()->pause();
gSky.destroyGL();
@@ -5615,8 +5700,6 @@ void LLViewerWindow::stopGL(BOOL save_state)
LLGLSLShader* shader = *(LLGLSLShader::sInstances.begin());
shader->unload();
}
-
- LL_INFOS() << "Remaining allocated texture memory: " << LLImageGL::sGlobalTextureMemory.value() << " bytes" << LL_ENDL;
}
}
@@ -5642,7 +5725,6 @@ void LLViewerWindow::restoreGL(const std::string& progress_message)
gSky.restoreGL();
gPipeline.restoreGL();
- LLDrawPoolWater::restoreGL();
LLManipTranslate::restoreGL();
gBumpImageList.restoreGL();
@@ -6039,7 +6121,7 @@ void LLPickInfo::fetchResults()
}
LLViewerObject* hit_object = gViewerWindow->cursorIntersect(mMousePt.mX, mMousePt.mY, 512.f,
- NULL, -1, mPickTransparent, mPickRigged, &face_hit,
+ NULL, -1, mPickTransparent, mPickRigged, mPickUnselectable, &face_hit,
&intersection, &uv, &normal, &tangent, &start, &end);
mPickPt = mMousePt;
@@ -6184,7 +6266,7 @@ void LLPickInfo::getSurfaceInfo()
if (objectp)
{
if (gViewerWindow->cursorIntersect(ll_round((F32)mMousePt.mX), ll_round((F32)mMousePt.mY), 1024.f,
- objectp, -1, mPickTransparent, mPickRigged,
+ objectp, -1, mPickTransparent, mPickRigged, mPickUnselectable,
&mObjectFace,
&intersection,
&mSTCoords,
diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h
index 1927e01ddb..586ea2bee7 100644
--- a/indra/newview/llviewerwindow.h
+++ b/indra/newview/llviewerwindow.h
@@ -68,6 +68,8 @@ class LLWindowListener;
class LLViewerWindowListener;
class LLVOPartGroup;
class LLPopupView;
+class LLCubeMap;
+class LLCubeMapArray;
#define PICK_HALF_WIDTH 5
#define PICK_DIAMETER (2 * PICK_HALF_WIDTH + 1)
@@ -362,6 +364,20 @@ public:
BOOL simpleSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height, const int num_render_passes);
+
+
+ // take a cubemap snapshot
+ // origin - vantage point to take the snapshot from
+ // cubearray - cubemap array for storing the results
+ // index - cube index in the array to use (cube index, not face-layer)
+ // face - which cube face to update
+ // near_clip - near clip setting to use
+ BOOL cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubearray, S32 index, S32 face, F32 near_clip, bool render_avatars);
+
+
+ // special implementation of simpleSnapshot for reflection maps
+ BOOL reflectionSnapshot(LLImageRaw* raw, S32 image_width, S32 image_height, const int num_render_passes);
+
BOOL thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL show_hud, BOOL do_rebuild, LLSnapshotModel::ESnapshotLayerType type);
BOOL isSnapshotLocSet() const;
void resetSnapshotLoc() const;
@@ -391,7 +407,7 @@ public:
BOOL pick_transparent = FALSE,
BOOL pick_rigged = FALSE,
BOOL pick_unselectable = FALSE);
- LLPickInfo pickImmediate(S32 x, S32 y, BOOL pick_transparent, BOOL pick_rigged = FALSE, BOOL pick_particle = FALSE);
+ LLPickInfo pickImmediate(S32 x, S32 y, BOOL pick_transparent, BOOL pick_rigged = FALSE, BOOL pick_particle = FALSE, BOOL pick_unselectable = TRUE);
LLHUDIcon* cursorIntersectIcon(S32 mouse_x, S32 mouse_y, F32 depth,
LLVector4a* intersection);
@@ -400,6 +416,7 @@ public:
S32 this_face = -1,
BOOL pick_transparent = FALSE,
BOOL pick_rigged = FALSE,
+ BOOL pick_unselectable = TRUE,
S32* face_hit = NULL,
LLVector4a *intersection = NULL,
LLVector2 *uv = NULL,
diff --git a/indra/newview/llvlcomposition.cpp b/indra/newview/llvlcomposition.cpp
index 0e6734f6e0..001fab7755 100644
--- a/indra/newview/llvlcomposition.cpp
+++ b/indra/newview/llvlcomposition.cpp
@@ -287,7 +287,7 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y,
BOOL delete_raw = (mDetailTextures[i]->reloadRawImage(ddiscard) != NULL) ;
if(mDetailTextures[i]->getRawImageLevel() != ddiscard)//raw iamge is not ready, will enter here again later.
{
- if (mDetailTextures[i]->getDecodePriority() <= 0.0f && !mDetailTextures[i]->hasSavedRawImage())
+ if (mDetailTextures[i]->getFetchPriority() <= 0.0f && !mDetailTextures[i]->hasSavedRawImage())
{
mDetailTextures[i]->setBoostLevel(LLGLTexture::BOOST_MAP);
mDetailTextures[i]->forceToRefetchTexture(ddiscard);
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 176528cb56..05fac036fb 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -1780,6 +1780,7 @@ BOOL LLVOAvatar::lineSegmentIntersect(const LLVector4a& start, const LLVector4a&
S32 face,
BOOL pick_transparent,
BOOL pick_rigged,
+ BOOL pick_unselectable,
S32* face_hit,
LLVector4a* intersection,
LLVector2* tex_coord,
@@ -1886,6 +1887,7 @@ LLViewerObject* LLVOAvatar::lineSegmentIntersectRiggedAttachments(const LLVector
S32 face,
BOOL pick_transparent,
BOOL pick_rigged,
+ BOOL pick_unselectable,
S32* face_hit,
LLVector4a* intersection,
LLVector2* tex_coord,
@@ -1916,7 +1918,7 @@ LLViewerObject* LLVOAvatar::lineSegmentIntersectRiggedAttachments(const LLVector
{
LLViewerObject* attached_object = attachment_iter->get();
- if (attached_object->lineSegmentIntersect(start, local_end, face, pick_transparent, pick_rigged, face_hit, &local_intersection, tex_coord, normal, tangent))
+ if (attached_object->lineSegmentIntersect(start, local_end, face, pick_transparent, pick_rigged, pick_unselectable, face_hit, &local_intersection, tex_coord, normal, tangent))
{
local_end = local_intersection;
if (intersection)
@@ -2346,15 +2348,15 @@ void LLVOAvatar::updateMeshData()
LLVertexBuffer* buff = facep->getVertexBuffer();
if(!facep->getVertexBuffer())
{
- buff = new LLVertexBufferAvatar();
- if (!buff->allocateBuffer(num_vertices, num_indices, TRUE))
+ buff = new LLVertexBuffer(LLDrawPoolAvatar::VERTEX_DATA_MASK);
+ if (!buff->allocateBuffer(num_vertices, num_indices))
{
LL_WARNS() << "Failed to allocate Vertex Buffer for Mesh to "
<< num_vertices << " vertices and "
<< num_indices << " indices" << LL_ENDL;
// Attempt to create a dummy triangle (one vertex, 3 indices, all 0)
facep->setSize(1, 3);
- buff->allocateBuffer(1, 3, true);
+ buff->allocateBuffer(1, 3);
memset((U8*) buff->getMappedData(), 0, buff->getSize());
memset((U8*) buff->getMappedIndices(), 0, buff->getIndicesSize());
}
@@ -2369,12 +2371,13 @@ void LLVOAvatar::updateMeshData()
}
else
{
- if (!buff->resizeBuffer(num_vertices, num_indices))
- {
+ buff = new LLVertexBuffer(buff->getTypeMask());
+ if (!buff->allocateBuffer(num_vertices, num_indices))
+ {
LL_WARNS() << "Failed to allocate vertex buffer for Mesh, Substituting" << LL_ENDL;
// Attempt to create a dummy triangle (one vertex, 3 indices, all 0)
facep->setSize(1, 3);
- buff->resizeBuffer(1, 3);
+ buff->allocateBuffer(1, 3);
memset((U8*) buff->getMappedData(), 0, buff->getSize());
memset((U8*) buff->getMappedIndices(), 0, buff->getIndicesSize());
}
@@ -2411,7 +2414,7 @@ void LLVOAvatar::updateMeshData()
}
stop_glerror();
- buff->flush();
+ buff->unmapBuffer();
if(!f_num)
{
@@ -5037,7 +5040,7 @@ U32 LLVOAvatar::renderSkinned()
LLVertexBuffer* vb = face->getVertexBuffer();
if (vb)
{
- vb->flush();
+ vb->unmapBuffer();
}
}
}
@@ -5672,7 +5675,6 @@ void LLVOAvatar::checkTextureLoading()
}
const F32 SELF_ADDITIONAL_PRI = 0.75f ;
-const F32 ADDITIONAL_PRI = 0.5f;
void LLVOAvatar::addBakedTextureStats( LLViewerFetchedTexture* imagep, F32 pixel_area, F32 texel_area_ratio, S32 boost_level)
{
//Note:
@@ -5687,15 +5689,6 @@ void LLVOAvatar::addBakedTextureStats( LLViewerFetchedTexture* imagep, F32 pixel
mMinPixelArea = llmin(pixel_area, mMinPixelArea);
imagep->addTextureStats(pixel_area / texel_area_ratio);
imagep->setBoostLevel(boost_level);
-
- if(boost_level != LLGLTexture::BOOST_AVATAR_BAKED_SELF)
- {
- imagep->setAdditionalDecodePriority(ADDITIONAL_PRI) ;
- }
- else
- {
- imagep->setAdditionalDecodePriority(SELF_ADDITIONAL_PRI) ;
- }
}
//virtual
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 56f2b73bef..7cc3337243 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -164,6 +164,7 @@ public:
S32 face = -1, // which face to check, -1 = ALL_SIDES
BOOL pick_transparent = FALSE,
BOOL pick_rigged = FALSE,
+ BOOL pick_unselectable = TRUE,
S32* face_hit = NULL, // which face was hit
LLVector4a* intersection = NULL, // return the intersection point
LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point
@@ -174,6 +175,7 @@ public:
S32 face = -1, // which face to check, -1 = ALL_SIDES
BOOL pick_transparent = FALSE,
BOOL pick_rigged = FALSE,
+ BOOL pick_unselectable = TRUE,
S32* face_hit = NULL, // which face was hit
LLVector4a* intersection = NULL, // return the intersection point
LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index 8fc1dcd81f..d8b82d3114 100644
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -1826,7 +1826,7 @@ void LLVOAvatarSelf::dumpLocalTextures() const
}
else
{
- const LLViewerFetchedTexture* image = dynamic_cast<LLViewerFetchedTexture*>( local_tex_obj->getImage() );
+ LLViewerFetchedTexture* image = dynamic_cast<LLViewerFetchedTexture*>( local_tex_obj->getImage() );
LL_INFOS() << "LocTex " << name << ": "
<< "Discard " << image->getDiscardLevel() << ", "
@@ -1836,7 +1836,7 @@ void LLVOAvatarSelf::dumpLocalTextures() const
// makes textures easier to steal
<< image->getID() << " "
#endif
- << "Priority: " << image->getDecodePriority()
+ << "Priority: " << image->getMaxVirtualSize()
<< LL_ENDL;
}
}
@@ -2075,8 +2075,7 @@ const std::string LLVOAvatarSelf::verboseDebugDumpLocalTextureDataInfo(const LLV
<< " glocdisc: " << getLocalDiscardLevel(tex_index, wearable_index)
<< " discard: " << image->getDiscardLevel()
<< " desired: " << image->getDesiredDiscardLevel()
- << " decode: " << image->getDecodePriority()
- << " addl: " << image->getAdditionalDecodePriority()
+ << " vsize: " << image->getMaxVirtualSize()
<< " ts: " << image->getTextureState()
<< " bl: " << image->getBoostLevel()
<< " fl: " << image->isFullyLoaded() // this is not an accessor for mFullyLoaded - see comment there.
@@ -2454,7 +2453,6 @@ void LLVOAvatarSelf::addLocalTextureStats( ETextureIndex type, LLViewerFetchedTe
desired_pixels = llmin(mPixelArea, (F32)getTexImageArea());
imagep->setBoostLevel(getAvatarBoostLevel());
- imagep->setAdditionalDecodePriority(SELF_ADDITIONAL_PRI) ;
imagep->resetTextureStats();
imagep->setMaxVirtualSizeResetInterval(MAX_TEXTURE_VIRTUAL_SIZE_RESET_INTERVAL);
imagep->addTextureStats( desired_pixels / texel_area_ratio );
@@ -2825,7 +2823,6 @@ void LLVOAvatarSelf::deleteScratchTextures()
LL_DEBUGS() << "Clearing Scratch Textures " << (S32Kilobytes)sScratchTexBytes << LL_ENDL;
delete_and_clear(sScratchTexNames);
- LLImageGL::sGlobalTextureMemory -= sScratchTexBytes;
sScratchTexBytes = S32Bytes(0);
}
}
diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp
index 55fc663496..cb75426cce 100644
--- a/indra/newview/llvocache.cpp
+++ b/indra/newview/llvocache.cpp
@@ -57,6 +57,75 @@ BOOL check_write(LLAPRFile* apr_file, void* src, S32 n_bytes)
return apr_file->write(src, n_bytes) == n_bytes ;
}
+bool LLGLTFOverrideCacheEntry::fromLLSD(const LLSD& data)
+{
+ if (!data.has("object_id"))
+ {
+ mObjectId.setNull();
+ return false;
+ }
+
+ if (data.has("region_handle_low") && data.has("region_handle_high"))
+ {
+ // TODO start requiring this once server sends this for all messages
+ U64 region_handle_low = data["region_handle_low"].asInteger();
+ U64 region_handle_high = data["region_handle_high"].asInteger();
+ mRegionHandle = (region_handle_low & 0x00000000ffffffffUL) || (region_handle_high << 32);
+ mHasRegionHandle = true;
+ }
+ else
+ {
+ mHasRegionHandle = false;
+ }
+
+ mObjectId = data["object_id"];
+
+ // message should be interpreted thusly:
+ /// sides is a list of face indices
+ // gltf_json is a list of corresponding json
+ // any side not represented in "sides" has no override
+ if (data.has("sides") && data.has("gltf_json"))
+ {
+ LLSD const& sides = data.get("sides");
+ LLSD const& gltf_json = data.get("gltf_json");
+
+ if (sides.isArray() && gltf_json.isArray() &&
+ sides.size() != 0 &&
+ sides.size() == gltf_json.size())
+ {
+ for (int i = 0; i < sides.size(); ++i)
+ {
+ S32 side_idx = sides[i].asInteger();
+ mSides[side_idx] = gltf_json[i].asString();
+ }
+ }
+ }
+ return true;
+}
+
+LLSD LLGLTFOverrideCacheEntry::toLLSD()
+{
+ llassert(false); // "Function not tested!!!
+
+ LLSD data;
+ if (mHasRegionHandle)
+ {
+ data["region_handle_low"] = LLSD::Integer(mRegionHandle & 0x00000000ffffffffUL);
+ data["region_handle_high"] = LLSD::Integer(mRegionHandle >> 32);
+ }
+
+ data["object_id"] = mObjectId;
+
+ std::map<S32, std::string>::const_iterator iter = mSides.begin();
+ std::map<S32, std::string>::const_iterator end = mSides.end();
+ while (iter != end)
+ {
+ data["sides"].append(LLSD::Integer(iter->first));
+ data["sides"].append(iter->second);
+ }
+
+ return data;
+}
//---------------------------------------------------------------------------
// LLVOCacheEntry
@@ -170,7 +239,7 @@ LLVOCacheEntry::~LLVOCacheEntry()
}
void LLVOCacheEntry::updateEntry(U32 crc, LLDataPackerBinaryBuffer &dp)
-{
+{
if(mCRC != crc)
{
mCRC = crc;
@@ -1435,7 +1504,12 @@ void LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::voca
return ;
}
-
+
+void LLVOCache::readGenericExtrasFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_gltf_overrides_map_t& cache_extras_entry_map)
+{
+ LL_DEBUGS() << "TODO" << LL_ENDL;
+}
+
void LLVOCache::purgeEntries(U32 size)
{
while(mHeaderEntryQueue.size() > size)
@@ -1572,3 +1646,7 @@ void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry:
return ;
}
+
+void LLVOCache::writeGenericExtrasToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_gltf_overrides_map_t& cache_extras_entry_map, BOOL dirty_cache, bool removal_enabled)
+{
+}
diff --git a/indra/newview/llvocache.h b/indra/newview/llvocache.h
index 55a13d934d..f41e9301ca 100644
--- a/indra/newview/llvocache.h
+++ b/indra/newview/llvocache.h
@@ -33,10 +33,24 @@
#include "llvieweroctree.h"
#include "llapr.h"
+#include <unordered_map>
+
//---------------------------------------------------------------------------
// Cache entries
class LLCamera;
+class LLGLTFOverrideCacheEntry
+{
+public:
+ bool fromLLSD(const LLSD& data);
+ LLSD toLLSD();
+
+ LLUUID mObjectId;
+ std::map<S32, std::string> mSides; //json per side
+ U64 mRegionHandle;
+ bool mHasRegionHandle;
+};
+
class LLVOCacheEntry
: public LLViewerOctreeEntryData
{
@@ -79,6 +93,13 @@ public:
}
}
};
+
+ struct ExtrasEntry
+ {
+ LLSD extras;
+ std::string extras_raw;
+ };
+
protected:
~LLVOCacheEntry();
public:
@@ -142,7 +163,9 @@ private:
public:
typedef std::map<U32, LLPointer<LLVOCacheEntry> > vocache_entry_map_t;
typedef std::set<LLVOCacheEntry*> vocache_entry_set_t;
- typedef std::set<LLVOCacheEntry*, CompareVOCacheEntry> vocache_entry_priority_list_t;
+ typedef std::set<LLVOCacheEntry*, CompareVOCacheEntry> vocache_entry_priority_list_t;
+
+ typedef std::unordered_map<U32, LLGLTFOverrideCacheEntry> vocache_gltf_overrides_map_t;
S32 mLastCameraUpdated;
protected:
@@ -265,7 +288,10 @@ public:
void removeCache(ELLPath location, bool started = false) ;
void readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_entry_map_t& cache_entry_map) ;
+ void readGenericExtrasFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_gltf_overrides_map_t& cache_extras_entry_map);
+
void writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_entry_map_t& cache_entry_map, BOOL dirty_cache, bool removal_enabled);
+ void writeGenericExtrasToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_gltf_overrides_map_t& cache_extras_entry_map, BOOL dirty_cache, bool removal_enabled);
void removeEntry(U64 handle) ;
U32 getCacheEntries() { return mNumEntries; }
diff --git a/indra/newview/llvograss.cpp b/indra/newview/llvograss.cpp
index 9a41eedb54..56faab92c5 100644
--- a/indra/newview/llvograss.cpp
+++ b/indra/newview/llvograss.cpp
@@ -594,7 +594,7 @@ U32 LLVOGrass::getPartitionType() const
}
LLGrassPartition::LLGrassPartition(LLViewerRegion* regionp)
-: LLSpatialPartition(LLDrawPoolAlpha::VERTEX_DATA_MASK | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, GL_STREAM_DRAW_ARB, regionp)
+: LLSpatialPartition(LLDrawPoolAlpha::VERTEX_DATA_MASK | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, regionp)
{
mDrawableType = LLPipeline::RENDER_TYPE_GRASS;
mPartitionType = LLViewerRegion::PARTITION_GRASS;
@@ -602,13 +602,10 @@ LLGrassPartition::LLGrassPartition(LLViewerRegion* regionp)
mDepthMask = TRUE;
mSlopRatio = 0.1f;
mRenderPass = LLRenderPass::PASS_GRASS;
- mBufferUsage = GL_DYNAMIC_DRAW_ARB;
}
void LLGrassPartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_count, U32& index_count)
{
- group->mBufferUsage = mBufferUsage;
-
mFaceList.clear();
LLViewerCamera* camera = LLViewerCamera::getInstance();
@@ -624,11 +621,6 @@ void LLGrassPartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_count
LLAlphaObject* obj = (LLAlphaObject*) drawablep->getVObj().get();
obj->mDepth = 0.f;
- if (drawablep->isAnimating())
- {
- group->mBufferUsage = GL_STREAM_DRAW_ARB;
- }
-
U32 count = 0;
for (S32 j = 0; j < drawablep->getNumFaces(); ++j)
{
@@ -707,8 +699,7 @@ void LLGrassPartition::getGeometry(LLSpatialGroup* group)
S32 idx = draw_vec.size()-1;
- BOOL fullbright = facep->isState(LLFace::FULLBRIGHT);
- F32 vsize = facep->getVirtualSize();
+ bool fullbright = facep->isState(LLFace::FULLBRIGHT);
if (idx >= 0 && draw_vec[idx]->mEnd == facep->getGeomIndex()-1 &&
draw_vec[idx]->mTexture == facep->getTexture() &&
@@ -719,7 +710,6 @@ void LLGrassPartition::getGeometry(LLSpatialGroup* group)
{
draw_vec[idx]->mCount += facep->getIndicesCount();
draw_vec[idx]->mEnd += facep->getGeomCount();
- draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, vsize);
}
else
{
@@ -731,17 +721,13 @@ void LLGrassPartition::getGeometry(LLSpatialGroup* group)
//facep->getTexture(),
buffer, object->isSelected(), fullbright);
- const LLVector4a* exts = group->getObjectExtents();
- info->mExtents[0] = exts[0];
- info->mExtents[1] = exts[1];
- info->mVSize = vsize;
draw_vec.push_back(info);
//for alpha sorting
facep->setDrawInfo(info);
}
}
- buffer->flush();
+ buffer->unmapBuffer();
mFaceList.clear();
}
@@ -758,7 +744,7 @@ void LLVOGrass::updateDrawable(BOOL force_damped)
}
// virtual
-BOOL LLVOGrass::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, BOOL pick_rigged, S32 *face_hitp,
+BOOL LLVOGrass::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, BOOL pick_rigged, BOOL pick_unselectable, S32 *face_hitp,
LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent)
{
diff --git a/indra/newview/llvograss.h b/indra/newview/llvograss.h
index 5634e048eb..63876dc099 100644
--- a/indra/newview/llvograss.h
+++ b/indra/newview/llvograss.h
@@ -79,6 +79,7 @@ public:
S32 face = -1, // which face to check, -1 = ALL_SIDES
BOOL pick_transparent = FALSE,
BOOL pick_rigged = FALSE,
+ BOOL pick_unselectable = TRUE,
S32* face_hit = NULL, // which face was hit
LLVector4a* intersection = NULL, // return the intersection point
LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point
diff --git a/indra/newview/llvoground.cpp b/indra/newview/llvoground.cpp
index 52a6395618..c2f7d4fef6 100644
--- a/indra/newview/llvoground.cpp
+++ b/indra/newview/llvoground.cpp
@@ -93,8 +93,8 @@ BOOL LLVOGround::updateGeometry(LLDrawable *drawable)
if (!face->getVertexBuffer())
{
face->setSize(5, 12);
- LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolGround::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB);
- if (!buff->allocateBuffer(face->getGeomCount(), face->getIndicesCount(), TRUE))
+ LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolGround::VERTEX_DATA_MASK);
+ if (!buff->allocateBuffer(face->getGeomCount(), face->getIndicesCount()))
{
LL_WARNS() << "Failed to allocate Vertex Buffer for VOGround to "
<< face->getGeomCount() << " vertices and "
@@ -160,7 +160,7 @@ BOOL LLVOGround::updateGeometry(LLDrawable *drawable)
*(texCoordsp++) = LLVector2(0.f, 1.f);
*(texCoordsp++) = LLVector2(0.5f, 0.5f);
- face->getVertexBuffer()->flush();
+ face->getVertexBuffer()->unmapBuffer();
LLPipeline::sCompiles++;
return TRUE;
}
diff --git a/indra/newview/llvoicevisualizer.cpp b/indra/newview/llvoicevisualizer.cpp
index 6e08a2ff12..34e561174c 100644
--- a/indra/newview/llvoicevisualizer.cpp
+++ b/indra/newview/llvoicevisualizer.cpp
@@ -356,7 +356,7 @@ void LLVoiceVisualizer::render()
//---------------------------------------------------------------
LLGLSPipelineAlpha alpha_blend;
LLGLDepthTest depth(GL_TRUE, GL_FALSE);
- LLGLDisable gls_stencil(GL_STENCIL_TEST);
+ //LLGLDisable gls_stencil(GL_STENCIL_TEST);
//-------------------------------------------------------------
// create coordinates of the geometry for the dot
diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp
index f3affbeb33..ac302ef421 100644
--- a/indra/newview/llvopartgroup.cpp
+++ b/indra/newview/llvopartgroup.cpp
@@ -46,18 +46,8 @@
extern U64MicrosecondsImplicit gFrameTime;
-LLPointer<LLVertexBuffer> LLVOPartGroup::sVB = NULL;
-S32 LLVOPartGroup::sVBSlotFree[];
-S32* LLVOPartGroup::sVBSlotCursor = NULL;
-
void LLVOPartGroup::initClass()
{
- for (S32 i = 0; i < LL_MAX_PARTICLE_COUNT; ++i)
- {
- sVBSlotFree[i] = i;
- }
-
- sVBSlotCursor = sVBSlotFree;
}
//static
@@ -65,9 +55,10 @@ void LLVOPartGroup::restoreGL()
{
//TODO: optimize out binormal mask here. Specular and normal coords as well.
- sVB = new LLVertexBuffer(VERTEX_DATA_MASK | LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2, GL_STREAM_DRAW_ARB);
+#if 0
+ sVB = new LLVertexBuffer(VERTEX_DATA_MASK | LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2);
U32 count = LL_MAX_PARTICLE_COUNT;
- if (!sVB->allocateBuffer(count*4, count*6, true))
+ if (!sVB->allocateBuffer(count*4, count*6))
{
LL_WARNS() << "Failed to allocate Vertex Buffer to "
<< count*4 << " vertices and "
@@ -117,27 +108,14 @@ void LLVOPartGroup::restoreGL()
*texcoordsp++ = LLVector2(1.f, 0.f);
}
- sVB->flush();
+ sVB->unmapBuffer();
+#endif
}
//static
void LLVOPartGroup::destroyGL()
{
- sVB = NULL;
-}
-
-//static
-S32 LLVOPartGroup::findAvailableVBSlot()
-{
- if (sVBSlotCursor >= sVBSlotFree + LL_MAX_PARTICLE_COUNT)
- { //no more available slots
- return -1;
- }
-
- S32 ret = *sVBSlotCursor;
- sVBSlotCursor++;
- return ret;
}
bool ll_is_part_idx_allocated(S32 idx, S32* start, S32* end)
@@ -155,20 +133,6 @@ bool ll_is_part_idx_allocated(S32 idx, S32* start, S32* end)
return false;
}
-//static
-void LLVOPartGroup::freeVBSlot(S32 idx)
-{
- llassert(idx < LL_MAX_PARTICLE_COUNT && idx >= 0);
- //llassert(sVBSlotCursor > sVBSlotFree);
- //llassert(ll_is_part_idx_allocated(idx, sVBSlotCursor, sVBSlotFree+LL_MAX_PARTICLE_COUNT));
-
- if (sVBSlotCursor > sVBSlotFree)
- {
- sVBSlotCursor--;
- *sVBSlotCursor = idx;
- }
-}
-
LLVOPartGroup::LLVOPartGroup(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
: LLAlphaObject(id, pcode, regionp),
mViewerPartGroupp(NULL)
@@ -291,13 +255,13 @@ F32 LLVOPartGroup::getPartSize(S32 idx)
return 0.f;
}
-void LLVOPartGroup::getBlendFunc(S32 idx, U32& src, U32& dst)
+void LLVOPartGroup::getBlendFunc(S32 idx, LLRender::eBlendFactor& src, LLRender::eBlendFactor& dst)
{
if (idx < (S32) mViewerPartGroupp->mParticles.size())
{
LLViewerPart* part = mViewerPartGroupp->mParticles[idx];
- src = part->mBlendFuncSource;
- dst = part->mBlendFuncDest;
+ src = (LLRender::eBlendFactor) part->mBlendFuncSource;
+ dst = (LLRender::eBlendFactor) part->mBlendFuncDest;
}
}
@@ -485,6 +449,7 @@ BOOL LLVOPartGroup::lineSegmentIntersect(const LLVector4a& start, const LLVector
S32 face,
BOOL pick_transparent,
BOOL pick_rigged,
+ BOOL pick_unselectable,
S32* face_hit,
LLVector4a* intersection,
LLVector2* tex_coord,
@@ -737,7 +702,7 @@ U32 LLVOPartGroup::getPartitionType() const
}
LLParticlePartition::LLParticlePartition(LLViewerRegion* regionp)
-: LLSpatialPartition(LLDrawPoolAlpha::VERTEX_DATA_MASK | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, GL_STREAM_DRAW_ARB, regionp)
+: LLSpatialPartition(LLDrawPoolAlpha::VERTEX_DATA_MASK | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, regionp)
{
mRenderPass = LLRenderPass::PASS_ALPHA;
mDrawableType = LLPipeline::RENDER_TYPE_PARTICLES;
@@ -756,32 +721,69 @@ LLHUDParticlePartition::LLHUDParticlePartition(LLViewerRegion* regionp) :
void LLParticlePartition::rebuildGeom(LLSpatialGroup* group)
{
LL_PROFILE_ZONE_SCOPED;
- if (group->isDead() || !group->hasState(LLSpatialGroup::GEOM_DIRTY))
- {
- return;
- }
+ LL_PROFILE_GPU_ZONE("particle vbo");
+ if (group->isDead() || !group->hasState(LLSpatialGroup::GEOM_DIRTY))
+ {
+ return;
+ }
- if (group->changeLOD())
- {
- group->mLastUpdateDistance = group->mDistance;
- group->mLastUpdateViewAngle = group->mViewAngle;
- }
-
- group->clearDrawMap();
-
- //get geometry count
- U32 index_count = 0;
- U32 vertex_count = 0;
+ if (group->changeLOD())
+ {
+ group->mLastUpdateDistance = group->mDistance;
+ group->mLastUpdateViewAngle = group->mViewAngle;
+ }
- addGeometryCount(group, vertex_count, index_count);
-
+ group->clearDrawMap();
+
+ //get geometry count
+ U32 index_count = 0;
+ U32 vertex_count = 0;
+
+ addGeometryCount(group, vertex_count, index_count);
- if (vertex_count > 0 && index_count > 0 && LLVOPartGroup::sVB)
- {
- group->mBuilt = 1.f;
- //use one vertex buffer for all groups
- group->mVertexBuffer = LLVOPartGroup::sVB;
- getGeometry(group);
+
+ if (vertex_count > 0 && index_count > 0)
+ {
+ group->mBuilt = 1.f;
+ if (group->mVertexBuffer.isNull() ||
+ group->mVertexBuffer->getNumVerts() < vertex_count || group->mVertexBuffer->getNumIndices() < index_count)
+ {
+ group->mVertexBuffer = new LLVertexBuffer(LLVOPartGroup::VERTEX_DATA_MASK);
+ group->mVertexBuffer->allocateBuffer(vertex_count, index_count);
+
+ // initialize index and texture coordinates only when buffer is reallocated
+ U16* indicesp = (U16*)group->mVertexBuffer->mapIndexBuffer(0, index_count);
+
+ U16 geom_idx = 0;
+ for (U32 i = 0; i < index_count; i += 6)
+ {
+ *indicesp++ = geom_idx + 0;
+ *indicesp++ = geom_idx + 1;
+ *indicesp++ = geom_idx + 2;
+
+ *indicesp++ = geom_idx + 1;
+ *indicesp++ = geom_idx + 3;
+ *indicesp++ = geom_idx + 2;
+
+ geom_idx += 4;
+ }
+
+ LLStrider<LLVector2> texcoordsp;
+
+ group->mVertexBuffer->getTexCoord0Strider(texcoordsp);
+
+ for (U32 i = 0; i < vertex_count; i += 4)
+ {
+ *texcoordsp++ = LLVector2(0.f, 1.f);
+ *texcoordsp++ = LLVector2(0.f, 0.f);
+ *texcoordsp++ = LLVector2(1.f, 1.f);
+ *texcoordsp++ = LLVector2(1.f, 0.f);
+ }
+
+ }
+
+
+ getGeometry(group);
}
else
{
@@ -795,8 +797,6 @@ void LLParticlePartition::rebuildGeom(LLSpatialGroup* group)
void LLParticlePartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_count, U32& index_count)
{
- group->mBufferUsage = mBufferUsage;
-
mFaceList.clear();
LLViewerCamera* camera = LLViewerCamera::getInstance();
@@ -849,10 +849,8 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group)
LLVertexBuffer* buffer = group->mVertexBuffer;
- LLStrider<U16> indicesp;
LLStrider<LLVector4a> verticesp;
LLStrider<LLVector3> normalsp;
- LLStrider<LLVector2> texcoordsp;
LLStrider<LLColor4U> colorsp;
LLStrider<LLColor4U> emissivep;
@@ -861,7 +859,9 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group)
buffer->getColorStrider(colorsp);
buffer->getEmissiveStrider(emissivep);
-
+ S32 geom_idx = 0;
+ S32 indices_idx = 0;
+
LLSpatialGroup::drawmap_elem_t& draw_vec = group->mDrawMap[mRenderPass];
for (std::vector<LLFace*>::iterator i = mFaceList.begin(); i != mFaceList.end(); ++i)
@@ -869,56 +869,44 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group)
LLFace* facep = *i;
LLAlphaObject* object = (LLAlphaObject*) facep->getViewerObject();
- if (!facep->isState(LLFace::PARTICLE))
- { //set the indices of this face
- S32 idx = LLVOPartGroup::findAvailableVBSlot();
- if (idx >= 0)
- {
- facep->setGeomIndex(idx*4);
- facep->setIndicesIndex(idx*6);
- facep->setVertexBuffer(LLVOPartGroup::sVB);
- facep->setPoolType(LLDrawPool::POOL_ALPHA);
- facep->setState(LLFace::PARTICLE);
- }
- else
- {
- continue; //out of space in particle buffer
- }
- }
-
- S32 geom_idx = (S32) facep->getGeomIndex();
+ facep->setGeomIndex(geom_idx);
+ facep->setIndicesIndex(indices_idx);
- LLStrider<U16> cur_idx = indicesp + facep->getIndicesStart();
LLStrider<LLVector4a> cur_vert = verticesp + geom_idx;
LLStrider<LLVector3> cur_norm = normalsp + geom_idx;
- LLStrider<LLVector2> cur_tc = texcoordsp + geom_idx;
LLStrider<LLColor4U> cur_col = colorsp + geom_idx;
LLStrider<LLColor4U> cur_glow = emissivep + geom_idx;
+ // not actually used
+ LLStrider<LLVector2> cur_tc;
+ LLStrider<U16> cur_idx;
+
+
+ geom_idx += 4;
+ indices_idx += 6;
+
LLColor4U* start_glow = cur_glow.get();
object->getGeometry(facep->getTEOffset(), cur_vert, cur_norm, cur_tc, cur_col, cur_glow, cur_idx);
- BOOL has_glow = FALSE;
+ bool has_glow = FALSE;
if (cur_glow.get() != start_glow)
{
- has_glow = TRUE;
+ has_glow = true;
}
llassert(facep->getGeomCount() == 4);
llassert(facep->getIndicesCount() == 6);
-
-
+
S32 idx = draw_vec.size()-1;
- BOOL fullbright = facep->isState(LLFace::FULLBRIGHT);
- F32 vsize = facep->getVirtualSize();
-
+ bool fullbright = facep->isState(LLFace::FULLBRIGHT);
+
bool batched = false;
- U32 bf_src = LLRender::BF_SOURCE_ALPHA;
- U32 bf_dst = LLRender::BF_ONE_MINUS_SOURCE_ALPHA;
+ LLRender::eBlendFactor bf_src = LLRender::BF_SOURCE_ALPHA;
+ LLRender::eBlendFactor bf_dst = LLRender::BF_ONE_MINUS_SOURCE_ALPHA;
object->getBlendFunc(facep->getTEOffset(), bf_src, bf_dst);
@@ -938,7 +926,6 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group)
batched = true;
info->mCount += facep->getIndicesCount();
info->mEnd += facep->getGeomCount();
- info->mVSize = llmax(draw_vec[idx]->mVSize, vsize);
}
else if (draw_vec[idx]->mStart == facep->getGeomIndex()+facep->getGeomCount()+1)
{
@@ -946,12 +933,10 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group)
info->mCount += facep->getIndicesCount();
info->mStart -= facep->getGeomCount();
info->mOffset = facep->getIndicesStart();
- info->mVSize = llmax(draw_vec[idx]->mVSize, vsize);
}
}
}
-
if (!batched)
{
U32 start = facep->getGeomIndex();
@@ -959,23 +944,18 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group)
U32 offset = facep->getIndicesStart();
U32 count = facep->getIndicesCount();
LLDrawInfo* info = new LLDrawInfo(start,end,count,offset,facep->getTexture(),
- //facep->getTexture(),
- buffer, object->isSelected(), fullbright);
+ buffer, fullbright);
- const LLVector4a* exts = group->getObjectExtents();
- info->mExtents[0] = exts[0];
- info->mExtents[1] = exts[1];
- info->mVSize = vsize;
info->mBlendFuncDst = bf_dst;
info->mBlendFuncSrc = bf_src;
info->mHasGlow = has_glow;
- info->mParticle = TRUE;
draw_vec.push_back(info);
//for alpha sorting
facep->setDrawInfo(info);
}
}
+ buffer->unmapBuffer();
mFaceList.clear();
}
diff --git a/indra/newview/llvopartgroup.h b/indra/newview/llvopartgroup.h
index 4e4d6e609d..4d471134d4 100644
--- a/indra/newview/llvopartgroup.h
+++ b/indra/newview/llvopartgroup.h
@@ -40,16 +40,9 @@ class LLVOPartGroup : public LLAlphaObject
{
public:
- //vertex buffer for holding all particles
- static LLPointer<LLVertexBuffer> sVB;
- static S32 sVBSlotFree[LL_MAX_PARTICLE_COUNT];
- static S32 *sVBSlotCursor;
-
static void initClass();
static void restoreGL();
static void destroyGL();
- static S32 findAvailableVBSlot();
- static void freeVBSlot(S32 idx);
enum
{
@@ -74,6 +67,7 @@ public:
S32 face,
BOOL pick_transparent,
BOOL pick_rigged,
+ BOOL pick_unselectable,
S32* face_hit,
LLVector4a* intersection,
LLVector2* tex_coord,
@@ -98,7 +92,7 @@ public:
void updateFaceSize(S32 idx) { }
F32 getPartSize(S32 idx);
- void getBlendFunc(S32 idx, U32& src, U32& dst);
+ void getBlendFunc(S32 idx, LLRender::eBlendFactor& src, LLRender::eBlendFactor& dst);
LLUUID getPartOwner(S32 idx);
LLUUID getPartSource(S32 idx);
diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp
index 909588367b..4b3b348d50 100644
--- a/indra/newview/llvosky.cpp
+++ b/indra/newview/llvosky.cpp
@@ -531,7 +531,7 @@ void LLVOSky::initCubeMap()
images.push_back(mShinyTex[side].getImageRaw());
}
- if (!mCubeMap && gSavedSettings.getBOOL("RenderWater") && gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps)
+ if (!mCubeMap && gSavedSettings.getBOOL("RenderWater") && LLCubeMap::sUseCubeMaps)
{
mCubeMap = new LLCubeMap(false);
}
@@ -576,7 +576,7 @@ void LLVOSky::restoreGL()
updateDirections(psky);
- if (gSavedSettings.getBOOL("RenderWater") && gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps)
+ if (gSavedSettings.getBOOL("RenderWater") && LLCubeMap::sUseCubeMaps)
{
initCubeMap();
}
@@ -692,7 +692,7 @@ bool LLVOSky::updateSky()
LLHeavenBody::setInterpVal( mInterpVal );
updateDirections(psky);
- if (!mCubeMap)
+ if (!mCubeMap || LLPipeline::sReflectionProbesEnabled)
{
mCubeMapUpdateStage = NUM_CUBEMAP_FACES;
mForceUpdate = FALSE;
@@ -715,7 +715,7 @@ bool LLVOSky::updateSky()
mForceUpdate = FALSE;
}
}
- else if (mCubeMapUpdateStage == NUM_CUBEMAP_FACES)
+ else if (mCubeMapUpdateStage == NUM_CUBEMAP_FACES && !LLPipeline::sReflectionProbesEnabled)
{
LL_PROFILE_ZONE_NAMED("updateSky - forced");
LLSkyTex::stepCurrent();
@@ -776,7 +776,7 @@ bool LLVOSky::updateSky()
mCubeMapUpdateStage = -1;
}
// run 0 to 5 faces, each face in own frame
- else if (mCubeMapUpdateStage >= 0 && mCubeMapUpdateStage < NUM_CUBEMAP_FACES)
+ else if (mCubeMapUpdateStage >= 0 && mCubeMapUpdateStage < NUM_CUBEMAP_FACES && !LLPipeline::sReflectionProbesEnabled)
{
LL_PROFILE_ZONE_NAMED("updateSky - create");
S32 side = mCubeMapUpdateStage;
@@ -1010,8 +1010,8 @@ BOOL LLVOSky::updateGeometry(LLDrawable *drawable)
face->setSize(4, 6);
face->setGeomIndex(0);
face->setIndicesIndex(0);
- LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolSky::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB);
- buff->allocateBuffer(4, 6, TRUE);
+ LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolSky::VERTEX_DATA_MASK);
+ buff->allocateBuffer(4, 6);
face->setVertexBuffer(buff);
index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp);
@@ -1046,7 +1046,7 @@ BOOL LLVOSky::updateGeometry(LLDrawable *drawable)
*indicesp++ = index_offset + 3;
*indicesp++ = index_offset + 2;
- buff->flush();
+ buff->unmapBuffer();
}
}
@@ -1139,8 +1139,8 @@ bool LLVOSky::updateHeavenlyBodyGeometry(LLDrawable *drawable, F32 scale, const
if (!facep->getVertexBuffer())
{
facep->setSize(4, 6);
- LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolSky::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB);
- if (!buff->allocateBuffer(facep->getGeomCount(), facep->getIndicesCount(), TRUE))
+ LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolSky::VERTEX_DATA_MASK);
+ if (!buff->allocateBuffer(facep->getGeomCount(), facep->getIndicesCount()))
{
LL_WARNS() << "Failed to allocate Vertex Buffer for vosky to "
<< facep->getGeomCount() << " vertices and "
@@ -1179,7 +1179,7 @@ bool LLVOSky::updateHeavenlyBodyGeometry(LLDrawable *drawable, F32 scale, const
*indicesp++ = index_offset + 2;
*indicesp++ = index_offset + 3;
- facep->getVertexBuffer()->flush();
+ facep->getVertexBuffer()->unmapBuffer();
return TRUE;
}
@@ -1379,8 +1379,8 @@ void LLVOSky::updateReflectionGeometry(LLDrawable *drawable, F32 H,
if (!face->getVertexBuffer() || quads*4 != face->getGeomCount())
{
face->setSize(quads * 4, quads * 6);
- LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolWater::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB);
- if (!buff->allocateBuffer(face->getGeomCount(), face->getIndicesCount(), TRUE))
+ LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolWater::VERTEX_DATA_MASK);
+ if (!buff->allocateBuffer(face->getGeomCount(), face->getIndicesCount()))
{
LL_WARNS() << "Failed to allocate Vertex Buffer for vosky to "
<< face->getGeomCount() << " vertices and "
@@ -1523,7 +1523,7 @@ void LLVOSky::updateReflectionGeometry(LLDrawable *drawable, F32 H,
}
}
- face->getVertexBuffer()->flush();
+ face->getVertexBuffer()->unmapBuffer();
}
}
diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp
index b0af565867..067272ec44 100644
--- a/indra/newview/llvosurfacepatch.cpp
+++ b/indra/newview/llvosurfacepatch.cpp
@@ -45,26 +45,6 @@
F32 LLVOSurfacePatch::sLODFactor = 1.f;
-//============================================================================
-
-class LLVertexBufferTerrain : public LLVertexBuffer
-{
-public:
- LLVertexBufferTerrain() :
- LLVertexBuffer(MAP_VERTEX | MAP_NORMAL | MAP_TEXCOORD0 | MAP_TEXCOORD1 | MAP_COLOR, GL_DYNAMIC_DRAW_ARB)
- {
- //texture coordinates 2 and 3 exist, but use the same data as texture coordinate 1
- };
-
- // virtual
- void setupVertexBuffer(U32 data_mask)
- {
- LLVertexBuffer::setupVertexBuffer(data_mask & ~(MAP_TEXCOORD2 | MAP_TEXCOORD3));
- }
-};
-
-//============================================================================
-
LLVOSurfacePatch::LLVOSurfacePatch(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
: LLStaticViewerObject(id, pcode, regionp),
mDirtiedPatch(FALSE),
@@ -880,7 +860,7 @@ void LLVOSurfacePatch::getGeomSizesEast(const S32 stride, const S32 east_stride,
}
}
-BOOL LLVOSurfacePatch::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, BOOL pick_rigged, S32 *face_hitp,
+BOOL LLVOSurfacePatch::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, BOOL pick_rigged, BOOL pick_unselectable, S32 *face_hitp,
LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent)
{
@@ -1001,7 +981,7 @@ U32 LLVOSurfacePatch::getPartitionType() const
}
LLTerrainPartition::LLTerrainPartition(LLViewerRegion* regionp)
-: LLSpatialPartition(LLDrawPoolTerrain::VERTEX_DATA_MASK, FALSE, GL_DYNAMIC_DRAW_ARB, regionp)
+: LLSpatialPartition(LLDrawPoolTerrain::VERTEX_DATA_MASK, FALSE, regionp)
{
mOcclusionEnabled = FALSE;
mInfiniteFarClip = TRUE;
@@ -1009,11 +989,6 @@ LLTerrainPartition::LLTerrainPartition(LLViewerRegion* regionp)
mPartitionType = LLViewerRegion::PARTITION_TERRAIN;
}
-LLVertexBuffer* LLTerrainPartition::createVertexBuffer(U32 type_mask, U32 usage)
-{
- return new LLVertexBufferTerrain();
-}
-
void LLTerrainPartition::getGeometry(LLSpatialGroup* group)
{
LL_PROFILE_ZONE_SCOPED;
@@ -1051,7 +1026,7 @@ void LLTerrainPartition::getGeometry(LLSpatialGroup* group)
index_offset += facep->getGeomCount();
}
- buffer->flush();
+ buffer->unmapBuffer();
mFaceList.clear();
}
diff --git a/indra/newview/llvosurfacepatch.h b/indra/newview/llvosurfacepatch.h
index 884dbb3be3..aed67162d1 100644
--- a/indra/newview/llvosurfacepatch.h
+++ b/indra/newview/llvosurfacepatch.h
@@ -85,6 +85,7 @@ public:
S32 face = -1, // which face to check, -1 = ALL_SIDES
BOOL pick_transparent = FALSE,
BOOL pick_rigged = FALSE,
+ BOOL pick_unselectable = TRUE,
S32* face_hit = NULL, // which face was hit
LLVector4a* intersection = NULL, // return the intersection point
LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point
diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp
index 493162b47b..0da77e4f8b 100644
--- a/indra/newview/llvotree.cpp
+++ b/indra/newview/llvotree.cpp
@@ -538,8 +538,8 @@ BOOL LLVOTree::updateGeometry(LLDrawable *drawable)
max_vertices += sLODVertexCount[lod];
}
- mReferenceBuffer = new LLVertexBuffer(LLDrawPoolTree::VERTEX_DATA_MASK, 0);
- if (!mReferenceBuffer->allocateBuffer(max_vertices, max_indices, TRUE))
+ mReferenceBuffer = new LLVertexBuffer(LLDrawPoolTree::VERTEX_DATA_MASK);
+ if (!mReferenceBuffer->allocateBuffer(max_vertices, max_indices))
{
LL_WARNS() << "Failed to allocate Vertex Buffer on update to "
<< max_vertices << " vertices and "
@@ -862,7 +862,7 @@ BOOL LLVOTree::updateGeometry(LLDrawable *drawable)
slices /= 2;
}
- mReferenceBuffer->flush();
+ mReferenceBuffer->unmapBuffer();
llassert(vertex_count == max_vertices);
llassert(index_count == max_indices);
}
@@ -921,19 +921,19 @@ void LLVOTree::updateMesh()
LLFace* facep = mDrawable->getFace(0);
if (!facep) return;
- LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolTree::VERTEX_DATA_MASK, GL_STATIC_DRAW_ARB);
- if (!buff->allocateBuffer(vert_count, index_count, TRUE))
+ LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolTree::VERTEX_DATA_MASK);
+ if (!buff->allocateBuffer(vert_count, index_count))
{
LL_WARNS() << "Failed to allocate Vertex Buffer on mesh update to "
<< vert_count << " vertices and "
<< index_count << " indices" << LL_ENDL;
- buff->allocateBuffer(1, 3, true);
+ buff->allocateBuffer(1, 3);
memset((U8*)buff->getMappedData(), 0, buff->getSize());
memset((U8*)buff->getMappedIndices(), 0, buff->getIndicesSize());
facep->setSize(1, 3);
facep->setVertexBuffer(buff);
- mReferenceBuffer->flush();
- buff->flush();
+ mReferenceBuffer->unmapBuffer();
+ buff->unmapBuffer();
return;
}
@@ -954,8 +954,8 @@ void LLVOTree::updateMesh()
genBranchPipeline(vertices, normals, tex_coords, colors, indices, idx_offset, scale_mat, mTrunkLOD, stop_depth, mDepth, mTrunkDepth, 1.0, mTwist, droop, mBranches, alpha);
- mReferenceBuffer->flush();
- buff->flush();
+ mReferenceBuffer->unmapBuffer();
+ buff->unmapBuffer();
}
void LLVOTree::appendMesh(LLStrider<LLVector3>& vertices,
@@ -1170,7 +1170,7 @@ void LLVOTree::updateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax)
mDrawable->setPositionGroup(pos);
}
-BOOL LLVOTree::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, BOOL pick_rigged, S32 *face_hitp,
+BOOL LLVOTree::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, BOOL pick_rigged, BOOL pick_unselectable, S32 *face_hitp,
LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent)
{
@@ -1226,7 +1226,7 @@ U32 LLVOTree::getPartitionType() const
}
LLTreePartition::LLTreePartition(LLViewerRegion* regionp)
-: LLSpatialPartition(0, FALSE, GL_DYNAMIC_DRAW_ARB, regionp)
+: LLSpatialPartition(0, FALSE, regionp)
{
mDrawableType = LLPipeline::RENDER_TYPE_TREE;
mPartitionType = LLViewerRegion::PARTITION_TREE;
diff --git a/indra/newview/llvotree.h b/indra/newview/llvotree.h
index 93c22d2da3..996e970cf8 100644
--- a/indra/newview/llvotree.h
+++ b/indra/newview/llvotree.h
@@ -111,6 +111,7 @@ public:
S32 face = -1, // which face to check, -1 = ALL_SIDES
BOOL pick_transparent = FALSE,
BOOL pick_rigged = FALSE,
+ BOOL pick_unselectable = TRUE,
S32* face_hit = NULL, // which face was hit
LLVector4a* intersection = NULL, // return the intersection point
LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 2e7ccc8334..fd1c137a56 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -88,13 +88,13 @@
#include "llcallstack.h"
#include "llsculptidsize.h"
#include "llavatarappearancedefines.h"
+#include "llgltfmateriallist.h"
const F32 FORCE_SIMPLE_RENDER_AREA = 512.f;
const F32 FORCE_CULL_AREA = 8.f;
U32 JOINT_COUNT_REQUIRED_FOR_FULLRIG = 1;
BOOL gAnimateTextures = TRUE;
-//extern BOOL gHideSelectedObjects;
F32 LLVOVolume::sLODFactor = 1.f;
F32 LLVOVolume::sLODSlopDistanceFactor = 0.5f; //Changing this to zero, effectively disables the LOD transition slop
@@ -105,6 +105,8 @@ S32 LLVOVolume::mRenderComplexity_current = 0;
LLPointer<LLObjectMediaDataClient> LLVOVolume::sObjectMediaClient = NULL;
LLPointer<LLObjectMediaNavigateClient> LLVOVolume::sObjectMediaNavigateClient = NULL;
+extern BOOL gCubeSnapshot;
+
// Implementation class of LLMediaDataClientObject. See llmediadataclient.h
class LLMediaDataClientObjectImpl : public LLMediaDataClientObject
{
@@ -528,6 +530,10 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys,
if (result & teDirtyBits)
{
updateTEData();
+ if (mDrawable)
+ { //on the fly TE updates break batches, isolate in octree
+ shrinkWrap();
+ }
}
if (result & TEM_CHANGE_MEDIA)
{
@@ -587,6 +593,7 @@ void LLVOVolume::animateTextures()
{
if (!mDead)
{
+ shrinkWrap();
F32 off_s = 0.f, off_t = 0.f, scale_s = 1.f, scale_t = 1.f, rot = 0.f;
S32 result = mTextureAnimp->animateTextures(off_s, off_t, scale_s, scale_t, rot);
@@ -699,12 +706,13 @@ void LLVOVolume::animateTextures()
void LLVOVolume::updateTextures()
{
- const F32 TEXTURE_AREA_REFRESH_TIME = 5.f; // seconds
- if (mTextureUpdateTimer.getElapsedTimeF32() > TEXTURE_AREA_REFRESH_TIME)
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
+ //const F32 TEXTURE_AREA_REFRESH_TIME = 1.f; // seconds
+ //if (mTextureUpdateTimer.getElapsedTimeF32() > TEXTURE_AREA_REFRESH_TIME)
{
updateTextureVirtualSize();
- if (mDrawable.notNull() && !isVisible() && !mDrawable->isActive())
+ /*if (mDrawable.notNull() && !isVisible() && !mDrawable->isActive())
{ //delete vertex buffer to free up some VRAM
LLSpatialGroup* group = mDrawable->getSpatialGroup();
if (group && (group->mVertexBuffer.notNull() || !group->mBufferMap.empty() || !group->mDrawMap.empty()))
@@ -715,9 +723,7 @@ void LLVOVolume::updateTextures()
//it becomes visible
group->setState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::MESH_DIRTY | LLSpatialGroup::NEW_DRAWINFO);
}
- }
-
-
+ }*/
}
}
@@ -747,7 +753,7 @@ void LLVOVolume::updateTextureVirtualSize(bool forced)
LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME;
// Update the pixel area of all faces
- if (mDrawable.isNull())
+ if (mDrawable.isNull() || gCubeSnapshot)
{
return;
}
@@ -791,6 +797,7 @@ void LLVOVolume::updateTextureVirtualSize(bool forced)
const S32 num_faces = mDrawable->getNumFaces();
F32 min_vsize=999999999.f, max_vsize=0.f;
LLViewerCamera* camera = LLViewerCamera::getInstance();
+ std::stringstream debug_text;
for (S32 i = 0; i < num_faces; i++)
{
LLFace* face = mDrawable->getFace(i);
@@ -802,7 +809,13 @@ void LLVOVolume::updateTextureVirtualSize(bool forced)
{
continue;
}
-
+
+ // clear out boost selected periodically
+ if (imagep->getBoostLevel() == LLGLTexture::BOOST_SELECTED)
+ {
+ imagep->setBoostLevel(LLGLTexture::BOOST_NONE);
+ }
+
F32 vsize;
F32 old_size = face->getVirtualSize();
@@ -817,10 +830,14 @@ void LLVOVolume::updateTextureVirtualSize(bool forced)
else
{
vsize = face->getTextureVirtualSize();
+ imagep->addTextureStats(vsize);
}
- mPixelArea = llmax(mPixelArea, face->getPixelArea());
+ mPixelArea = llmax(mPixelArea, face->getPixelArea());
+ // if the face has gotten small enough to turn off texture animation and texture
+ // animation is running, rebuild the render batch for this face to turn off
+ // texture animation
if (face->mTextureMatrix != NULL)
{
if ((vsize < MIN_TEX_ANIM_SIZE && old_size > MIN_TEX_ANIM_SIZE) ||
@@ -840,10 +857,11 @@ void LLVOVolume::updateTextureVirtualSize(bool forced)
LLViewerFetchedTexture* img = LLViewerTextureManager::staticCastToFetchedTexture(imagep) ;
if(img)
{
- F32 pri = img->getDecodePriority();
+ debug_text << img->getDiscardLevel() << ":" << img->getDesiredDiscardLevel() << ":" << img->getWidth() << ":" << (S32) sqrtf(vsize) << ":" << (S32) sqrtf(img->getMaxVirtualSize()) << "\n";
+ /*F32 pri = img->getDecodePriority();
pri = llmax(pri, 0.0f);
if (pri < min_vsize) min_vsize = pri;
- if (pri > max_vsize) max_vsize = pri;
+ if (pri > max_vsize) max_vsize = pri;*/
}
}
else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_AREA))
@@ -872,14 +890,6 @@ void LLVOVolume::updateTextureVirtualSize(bool forced)
F32 lodf = ((F32)(lod + 1.0f)/4.f);
F32 tex_size = lodf * LLViewerTexture::sMaxSculptRez ;
mSculptTexture->addTextureStats(2.f * tex_size * tex_size, FALSE);
-
- //if the sculpty very close to the view point, load first
- {
- LLVector3 lookAt = getPositionAgent() - camera->getOrigin();
- F32 dist = lookAt.normVec() ;
- F32 cos_angle_to_view_dir = lookAt * camera->getXAxis() ;
- mSculptTexture->setAdditionalDecodePriority(0.8f * LLFace::calcImportanceToCamera(cos_angle_to_view_dir, dist)) ;
- }
}
S32 texture_discard = mSculptTexture->getCachedRawImageLevel(); //try to match the texture
@@ -923,7 +933,8 @@ void LLVOVolume::updateTextureVirtualSize(bool forced)
}
else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY))
{
- setDebugText(llformat("%.0f:%.0f", (F32) sqrt(min_vsize),(F32) sqrt(max_vsize)));
+ //setDebugText(llformat("%.0f:%.0f", (F32) sqrt(min_vsize),(F32) sqrt(max_vsize)));
+ setDebugText(debug_text.str());
}
else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_AREA))
{
@@ -971,6 +982,11 @@ void LLVOVolume::setScale(const LLVector3 &scale, BOOL damped)
//since drawable transforms do not include scale, changing volume scale
//requires an immediate rebuild of volume verts.
gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_POSITION, TRUE);
+
+ if (mDrawable)
+ {
+ shrinkWrap();
+ }
}
}
@@ -1010,7 +1026,12 @@ LLDrawable *LLVOVolume::createDrawable(LLPipeline *pipeline)
// Add it to the pipeline mLightSet
gPipeline.setLight(mDrawable, TRUE);
}
-
+
+ if (isReflectionProbe())
+ {
+ updateReflectionProbePtr();
+ }
+
updateRadius();
bool force_update = true; // avoid non-alpha mDistance update being optimized away
mDrawable->updateDistance(*LLViewerCamera::getInstance(), force_update);
@@ -1131,27 +1152,7 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams &params_in, const S32 detail, bo
}
}
- static LLCachedControl<bool> use_transform_feedback(gSavedSettings, "RenderUseTransformFeedback", false);
-
- bool cache_in_vram = use_transform_feedback && gTransformPositionProgram.mProgramObject &&
- (!mVolumeImpl || !mVolumeImpl->isVolumeUnique());
-
- if (cache_in_vram)
- { //this volume might be used as source data for a transform object, put it in vram
- LLVolume* volume = getVolume();
- for (S32 i = 0; i < volume->getNumFaces(); ++i)
- {
- const LLVolumeFace& face = volume->getVolumeFace(i);
- if (face.mVertexBuffer.notNull())
- { //already cached
- break;
- }
- volume->genTangents(i);
- LLFace::cacheFaceInVRAM(face);
- }
- }
-
- return TRUE;
+ return TRUE;
}
else if (NO_LOD == lod)
{
@@ -2208,7 +2209,8 @@ void LLVOVolume::setNumTEs(const U8 num_tes)
return ;
}
-//virtual
+
+//virtual
void LLVOVolume::changeTEImage(S32 index, LLViewerTexture* imagep)
{
BOOL changed = (mTEImages[index] != imagep);
@@ -2236,7 +2238,12 @@ S32 LLVOVolume::setTETexture(const U8 te, const LLUUID &uuid)
S32 res = LLViewerObject::setTETexture(te, uuid);
if (res)
{
- gPipeline.markTextured(mDrawable);
+ if (mDrawable)
+ {
+ // dynamic texture changes break batches, isolate in octree
+ shrinkWrap();
+ gPipeline.markTextured(mDrawable);
+ }
mFaceMappingChanged = TRUE;
}
return res;
@@ -2271,6 +2278,7 @@ S32 LLVOVolume::setTEColor(const U8 te, const LLColor4& color)
// These should only happen on updates which are not the initial update.
mColorChanged = TRUE;
mDrawable->setState(LLDrawable::REBUILD_COLOR);
+ shrinkWrap();
dirtyMesh();
}
}
@@ -2360,7 +2368,11 @@ S32 LLVOVolume::setTEGlow(const U8 te, const F32 glow)
S32 res = LLViewerObject::setTEGlow(te, glow);
if (res)
{
- gPipeline.markTextured(mDrawable);
+ if (mDrawable)
+ {
+ gPipeline.markTextured(mDrawable);
+ shrinkWrap();
+ }
mFaceMappingChanged = TRUE;
}
return res;
@@ -2406,243 +2418,11 @@ S32 LLVOVolume::setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID)
return res;
}
-bool LLVOVolume::notifyAboutCreatingTexture(LLViewerTexture *texture)
-{ //Ok, here we have confirmation about texture creation, check our wait-list
- //and make changes, or return false
-
- std::pair<mmap_UUID_MAP_t::iterator, mmap_UUID_MAP_t::iterator> range = mWaitingTextureInfo.equal_range(texture->getID());
-
- typedef std::map<U8, LLMaterialPtr> map_te_material;
- map_te_material new_material;
-
- for(mmap_UUID_MAP_t::iterator range_it = range.first; range_it != range.second; ++range_it)
- {
- LLMaterialPtr cur_material = getTEMaterialParams(range_it->second.te);
-
- //here we just interesting in DIFFUSE_MAP only!
- if(NULL != cur_material.get() && LLRender::DIFFUSE_MAP == range_it->second.map && GL_RGBA != texture->getPrimaryFormat())
- { //ok let's check the diffuse mode
- switch(cur_material->getDiffuseAlphaMode())
- {
- case LLMaterial::DIFFUSE_ALPHA_MODE_BLEND:
- case LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE:
- case LLMaterial::DIFFUSE_ALPHA_MODE_MASK:
- { //uups... we have non 32 bit texture with LLMaterial::DIFFUSE_ALPHA_MODE_* => LLMaterial::DIFFUSE_ALPHA_MODE_NONE
-
- LLMaterialPtr mat = NULL;
- map_te_material::iterator it = new_material.find(range_it->second.te);
- if(new_material.end() == it) {
- mat = new LLMaterial(cur_material->asLLSD());
- new_material.insert(map_te_material::value_type(range_it->second.te, mat));
- } else {
- mat = it->second;
- }
-
- mat->setDiffuseAlphaMode(LLMaterial::DIFFUSE_ALPHA_MODE_NONE);
-
- } break;
- } //switch
- } //if
- } //for
-
- //setup new materials
- for(map_te_material::const_iterator it = new_material.begin(), end = new_material.end(); it != end; ++it)
- {
- LLMaterialMgr::getInstance()->put(getID(), it->first, *it->second);
- LLViewerObject::setTEMaterialParams(it->first, it->second);
- }
-
- //clear wait-list
- mWaitingTextureInfo.erase(range.first, range.second);
-
- return 0 != new_material.size();
-}
-
-bool LLVOVolume::notifyAboutMissingAsset(LLViewerTexture *texture)
-{ //Ok, here if we wait information about texture and it's missing
- //then depending from the texture map (diffuse, normal, or specular)
- //make changes in material and confirm it. If not return false.
- std::pair<mmap_UUID_MAP_t::iterator, mmap_UUID_MAP_t::iterator> range = mWaitingTextureInfo.equal_range(texture->getID());
- if(range.first == range.second) return false;
-
- typedef std::map<U8, LLMaterialPtr> map_te_material;
- map_te_material new_material;
-
- for(mmap_UUID_MAP_t::iterator range_it = range.first; range_it != range.second; ++range_it)
- {
- LLMaterialPtr cur_material = getTEMaterialParams(range_it->second.te);
- if (cur_material.isNull())
- continue;
-
- switch(range_it->second.map)
- {
- case LLRender::DIFFUSE_MAP:
- {
- if(LLMaterial::DIFFUSE_ALPHA_MODE_NONE != cur_material->getDiffuseAlphaMode())
- { //missing texture + !LLMaterial::DIFFUSE_ALPHA_MODE_NONE => LLMaterial::DIFFUSE_ALPHA_MODE_NONE
- LLMaterialPtr mat = NULL;
- map_te_material::iterator it = new_material.find(range_it->second.te);
- if(new_material.end() == it) {
- mat = new LLMaterial(cur_material->asLLSD());
- new_material.insert(map_te_material::value_type(range_it->second.te, mat));
- } else {
- mat = it->second;
- }
-
- mat->setDiffuseAlphaMode(LLMaterial::DIFFUSE_ALPHA_MODE_NONE);
- }
- } break;
- case LLRender::NORMAL_MAP:
- { //missing texture => reset material texture id
- LLMaterialPtr mat = NULL;
- map_te_material::iterator it = new_material.find(range_it->second.te);
- if(new_material.end() == it) {
- mat = new LLMaterial(cur_material->asLLSD());
- new_material.insert(map_te_material::value_type(range_it->second.te, mat));
- } else {
- mat = it->second;
- }
-
- mat->setNormalID(LLUUID::null);
- } break;
- case LLRender::SPECULAR_MAP:
- { //missing texture => reset material texture id
- LLMaterialPtr mat = NULL;
- map_te_material::iterator it = new_material.find(range_it->second.te);
- if(new_material.end() == it) {
- mat = new LLMaterial(cur_material->asLLSD());
- new_material.insert(map_te_material::value_type(range_it->second.te, mat));
- } else {
- mat = it->second;
- }
-
- mat->setSpecularID(LLUUID::null);
- } break;
- case LLRender::NUM_TEXTURE_CHANNELS:
- //nothing to do, make compiler happy
- break;
- } //switch
- } //for
-
- //setup new materials
- for(map_te_material::const_iterator it = new_material.begin(), end = new_material.end(); it != end; ++it)
- {
- LLMaterialMgr::getInstance()->setLocalMaterial(getRegion()->getRegionID(), it->second);
- LLViewerObject::setTEMaterialParams(it->first, it->second);
- }
-
- //clear wait-list
- mWaitingTextureInfo.erase(range.first, range.second);
-
- return 0 != new_material.size();
-}
-
S32 LLVOVolume::setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams)
{
- LLMaterialPtr pMaterial = const_cast<LLMaterialPtr&>(pMaterialParams);
-
- if(pMaterialParams)
- { //check all of them according to material settings
-
- LLViewerTexture *img_diffuse = getTEImage(te);
- LLViewerTexture *img_normal = getTENormalMap(te);
- LLViewerTexture *img_specular = getTESpecularMap(te);
-
- llassert(NULL != img_diffuse);
-
- LLMaterialPtr new_material = NULL;
-
- //diffuse
- if(NULL != img_diffuse)
- { //guard
- if(0 == img_diffuse->getPrimaryFormat() && !img_diffuse->isMissingAsset())
- { //ok here we don't have information about texture, let's belief and leave material settings
- //but we remember this case
- mWaitingTextureInfo.insert(mmap_UUID_MAP_t::value_type(img_diffuse->getID(), material_info(LLRender::DIFFUSE_MAP, te)));
- }
- else
- {
- bool bSetDiffuseNone = false;
- if(img_diffuse->isMissingAsset())
- {
- bSetDiffuseNone = true;
- }
- else
- {
- switch(pMaterialParams->getDiffuseAlphaMode())
- {
- case LLMaterial::DIFFUSE_ALPHA_MODE_BLEND:
- case LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE:
- case LLMaterial::DIFFUSE_ALPHA_MODE_MASK:
- { //all of them modes available only for 32 bit textures
- LLTextureEntry* tex_entry = getTE(te);
- bool bIsBakedImageId = false;
- if (tex_entry && LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(tex_entry->getID()))
- {
- bIsBakedImageId = true;
- }
- if (GL_RGBA != img_diffuse->getPrimaryFormat() && !bIsBakedImageId)
- {
- bSetDiffuseNone = true;
- }
- } break;
- }
- } //else
-
-
- if(bSetDiffuseNone)
- { //upps... we should substitute this material with LLMaterial::DIFFUSE_ALPHA_MODE_NONE
- new_material = new LLMaterial(pMaterialParams->asLLSD());
- new_material->setDiffuseAlphaMode(LLMaterial::DIFFUSE_ALPHA_MODE_NONE);
- }
- }
- }
-
- //normal
- if(LLUUID::null != pMaterialParams->getNormalID())
- {
- if(img_normal && img_normal->isMissingAsset() && img_normal->getID() == pMaterialParams->getNormalID())
- {
- if(!new_material) {
- new_material = new LLMaterial(pMaterialParams->asLLSD());
- }
- new_material->setNormalID(LLUUID::null);
- }
- else if(NULL == img_normal || 0 == img_normal->getPrimaryFormat())
- { //ok here we don't have information about texture, let's belief and leave material settings
- //but we remember this case
- mWaitingTextureInfo.insert(mmap_UUID_MAP_t::value_type(pMaterialParams->getNormalID(), material_info(LLRender::NORMAL_MAP,te)));
- }
-
- }
-
-
- //specular
- if(LLUUID::null != pMaterialParams->getSpecularID())
- {
- if(img_specular && img_specular->isMissingAsset() && img_specular->getID() == pMaterialParams->getSpecularID())
- {
- if(!new_material) {
- new_material = new LLMaterial(pMaterialParams->asLLSD());
- }
- new_material->setSpecularID(LLUUID::null);
- }
- else if(NULL == img_specular || 0 == img_specular->getPrimaryFormat())
- { //ok here we don't have information about texture, let's belief and leave material settings
- //but we remember this case
- mWaitingTextureInfo.insert(mmap_UUID_MAP_t::value_type(pMaterialParams->getSpecularID(), material_info(LLRender::SPECULAR_MAP, te)));
- }
- }
+ S32 res = LLViewerObject::setTEMaterialParams(te, pMaterialParams);
- if(new_material) {
- pMaterial = new_material;
- LLMaterialMgr::getInstance()->setLocalMaterial(getRegion()->getRegionID(), pMaterial);
- }
- }
-
- S32 res = LLViewerObject::setTEMaterialParams(te, pMaterial);
-
- LL_DEBUGS("MaterialTEs") << "te " << (S32)te << " material " << ((pMaterial) ? pMaterial->asLLSD() : LLSD("null")) << " res " << res
+ LL_DEBUGS("MaterialTEs") << "te " << (S32)te << " material " << ((pMaterialParams) ? pMaterialParams->asLLSD() : LLSD("null")) << " res " << res
<< ( LLSelectMgr::getInstance()->getSelection()->contains(const_cast<LLVOVolume*>(this), te) ? " selected" : " not selected" )
<< LL_ENDL;
setChanged(ALL_CHANGED);
@@ -2655,6 +2435,24 @@ S32 LLVOVolume::setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialPa
return TEM_CHANGE_TEXTURE;
}
+S32 LLVOVolume::setTEGLTFMaterialOverride(U8 te, LLGLTFMaterial* mat)
+{
+ S32 retval = LLViewerObject::setTEGLTFMaterialOverride(te, mat);
+
+ if (retval == TEM_CHANGE_TEXTURE)
+ {
+ if (!mDrawable.isNull())
+ {
+ gPipeline.markTextured(mDrawable);
+ gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL);
+ }
+ mFaceMappingChanged = TRUE;
+ }
+
+ return retval;
+}
+
+
S32 LLVOVolume::setTEScale(const U8 te, const F32 s, const F32 t)
{
S32 res = LLViewerObject::setTEScale(te, s, t);
@@ -2688,6 +2486,7 @@ S32 LLVOVolume::setTEScaleT(const U8 te, const F32 t)
return res;
}
+
void LLVOVolume::updateTEData()
{
/*if (mDrawable.notNull())
@@ -3440,6 +3239,11 @@ F32 LLVOVolume::getSpotLightPriority() const
void LLVOVolume::updateSpotLightPriority()
{
+ if (gCubeSnapshot)
+ {
+ return;
+ }
+
F32 r = getLightRadius();
LLVector3 pos = mDrawable->getPositionAgent();
@@ -3542,6 +3346,143 @@ F32 LLVOVolume::getLightCutoff() const
}
}
+BOOL LLVOVolume::isReflectionProbe() const
+{
+ return getParameterEntryInUse(LLNetworkData::PARAMS_REFLECTION_PROBE);
+}
+
+bool LLVOVolume::setIsReflectionProbe(BOOL is_probe)
+{
+ BOOL was_probe = isReflectionProbe();
+ if (is_probe != was_probe)
+ {
+ if (is_probe)
+ {
+ setParameterEntryInUse(LLNetworkData::PARAMS_REFLECTION_PROBE, TRUE, true);
+ }
+ else
+ {
+ setParameterEntryInUse(LLNetworkData::PARAMS_REFLECTION_PROBE, FALSE, true);
+ }
+ }
+
+ updateReflectionProbePtr();
+
+ return was_probe != is_probe;
+}
+
+bool LLVOVolume::setReflectionProbeAmbiance(F32 ambiance)
+{
+ LLReflectionProbeParams* param_block = (LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE);
+ if (param_block)
+ {
+ if (param_block->getAmbiance() != ambiance)
+ {
+ param_block->setAmbiance(ambiance);
+ parameterChanged(LLNetworkData::PARAMS_REFLECTION_PROBE, true);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool LLVOVolume::setReflectionProbeNearClip(F32 near_clip)
+{
+ LLReflectionProbeParams* param_block = (LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE);
+ if (param_block)
+ {
+ if (param_block->getClipDistance() != near_clip)
+ {
+ param_block->setClipDistance(near_clip);
+ parameterChanged(LLNetworkData::PARAMS_REFLECTION_PROBE, true);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool LLVOVolume::setReflectionProbeIsBox(bool is_box)
+{
+ LLReflectionProbeParams* param_block = (LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE);
+ if (param_block)
+ {
+ if (param_block->getIsBox() != is_box)
+ {
+ param_block->setIsBox(is_box);
+ parameterChanged(LLNetworkData::PARAMS_REFLECTION_PROBE, true);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool LLVOVolume::setReflectionProbeIsDynamic(bool is_dynamic)
+{
+ LLReflectionProbeParams* param_block = (LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE);
+ if (param_block)
+ {
+ if (param_block->getIsDynamic() != is_dynamic)
+ {
+ param_block->setIsDynamic(is_dynamic);
+ parameterChanged(LLNetworkData::PARAMS_REFLECTION_PROBE, true);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+F32 LLVOVolume::getReflectionProbeAmbiance() const
+{
+ const LLReflectionProbeParams* param_block = (const LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE);
+ if (param_block)
+ {
+ return param_block->getAmbiance();
+ }
+ else
+ {
+ return 0.f;
+ }
+}
+
+F32 LLVOVolume::getReflectionProbeNearClip() const
+{
+ const LLReflectionProbeParams* param_block = (const LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE);
+ if (param_block)
+ {
+ return param_block->getClipDistance();
+ }
+ else
+ {
+ return 0.f;
+ }
+}
+
+bool LLVOVolume::getReflectionProbeIsBox() const
+{
+ const LLReflectionProbeParams* param_block = (const LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE);
+ if (param_block)
+ {
+ return param_block->getIsBox();
+ }
+
+ return false;
+}
+
+bool LLVOVolume::getReflectionProbeIsDynamic() const
+{
+ const LLReflectionProbeParams* param_block = (const LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE);
+ if (param_block)
+ {
+ return param_block->getIsDynamic();
+ }
+
+ return false;
+}
+
U32 LLVOVolume::getVolumeInterfaceID() const
{
if (mVolumeImpl)
@@ -4130,7 +4071,7 @@ U32 LLVOVolume::getRenderCost(texture_cost_t &textures) const
}
}
- if (face->getPoolType() == LLDrawPool::POOL_ALPHA)
+ if (face->isInAlphaPool())
{
alpha = 1;
}
@@ -4427,6 +4368,23 @@ void LLVOVolume::parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_u
gPipeline.setLight(mDrawable, is_light);
}
}
+
+ updateReflectionProbePtr();
+}
+
+void LLVOVolume::updateReflectionProbePtr()
+{
+ if (isReflectionProbe())
+ {
+ if (mReflectionProbe.isNull())
+ {
+ mReflectionProbe = gPipeline.mReflectionMapManager.registerViewerObject(this);
+ }
+ }
+ else if (mReflectionProbe.notNull())
+ {
+ mReflectionProbe = nullptr;
+ }
}
void LLVOVolume::setSelected(BOOL sel)
@@ -4452,83 +4410,61 @@ void LLVOVolume::updateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax)
F32 LLVOVolume::getBinRadius()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME;
- F32 radius;
-
- F32 scale = 1.f;
-
- static LLCachedControl<S32> octree_size_factor(gSavedSettings, "OctreeStaticObjectSizeFactor", 3);
- static LLCachedControl<S32> octree_attachment_size_factor(gSavedSettings, "OctreeAttachmentSizeFactor", 4);
- static LLCachedControl<LLVector3> octree_distance_factor(gSavedSettings, "OctreeDistanceFactor", LLVector3(0.01f, 0.f, 0.f));
- static LLCachedControl<LLVector3> octree_alpha_distance_factor(gSavedSettings, "OctreeAlphaDistanceFactor", LLVector3(0.1f, 0.f, 0.f));
+ F32 radius;
- S32 size_factor = llmax((S32)octree_size_factor, 1);
- S32 attachment_size_factor = llmax((S32)octree_attachment_size_factor, 1);
- LLVector3 distance_factor = octree_distance_factor;
- LLVector3 alpha_distance_factor = octree_alpha_distance_factor;
+ static LLCachedControl<S32> octree_size_factor(gSavedSettings, "OctreeStaticObjectSizeFactor", 3);
+ static LLCachedControl<S32> octree_attachment_size_factor(gSavedSettings, "OctreeAttachmentSizeFactor", 4);
+ static LLCachedControl<LLVector3> octree_distance_factor(gSavedSettings, "OctreeDistanceFactor", LLVector3(0.01f, 0.f, 0.f));
+ static LLCachedControl<LLVector3> octree_alpha_distance_factor(gSavedSettings, "OctreeAlphaDistanceFactor", LLVector3(0.1f, 0.f, 0.f));
- const LLVector4a* ext = mDrawable->getSpatialExtents();
-
- BOOL shrink_wrap = mDrawable->isAnimating();
- BOOL alpha_wrap = FALSE;
+ S32 size_factor = llmax((S32)octree_size_factor, 1);
+ LLVector3 alpha_distance_factor = octree_alpha_distance_factor;
- if (!isHUDAttachment())
- {
- for (S32 i = 0; i < mDrawable->getNumFaces(); i++)
- {
- LLFace* face = mDrawable->getFace(i);
- if (!face) continue;
- if (face->getPoolType() == LLDrawPool::POOL_ALPHA &&
- !face->canRenderAsMask())
- {
- alpha_wrap = TRUE;
- break;
- }
- }
- }
- else
- {
- shrink_wrap = FALSE;
- }
+ //const LLVector4a* ext = mDrawable->getSpatialExtents();
- if (alpha_wrap)
- {
- LLVector3 bounds = getScale();
- radius = llmin(bounds.mV[1], bounds.mV[2]);
- radius = llmin(radius, bounds.mV[0]);
- radius *= 0.5f;
- radius *= 1.f+mDrawable->mDistanceWRTCamera*alpha_distance_factor[1];
- radius += mDrawable->mDistanceWRTCamera*alpha_distance_factor[0];
- }
- else if (shrink_wrap)
- {
- LLVector4a rad;
- rad.setSub(ext[1], ext[0]);
-
- radius = rad.getLength3().getF32()*0.5f;
- }
- else if (mDrawable->isStatic())
- {
- F32 szf = size_factor;
+ bool shrink_wrap = mShouldShrinkWrap || mDrawable->isAnimating();
+ bool alpha_wrap = FALSE;
- radius = llmax(mDrawable->getRadius(), szf);
-
- radius = powf(radius, 1.f+szf/radius);
+ if (!isHUDAttachment() && mDrawable->mDistanceWRTCamera < alpha_distance_factor[2])
+ {
+ for (S32 i = 0; i < mDrawable->getNumFaces(); i++)
+ {
+ LLFace* face = mDrawable->getFace(i);
+ if (!face) continue;
+ if (face->isInAlphaPool() &&
+ !face->canRenderAsMask())
+ {
+ alpha_wrap = TRUE;
+ break;
+ }
+ }
+ }
+ else
+ {
+ shrink_wrap = FALSE;
+ }
- radius *= 1.f + mDrawable->mDistanceWRTCamera * distance_factor[1];
- radius += mDrawable->mDistanceWRTCamera * distance_factor[0];
- }
- else if (mDrawable->getVObj()->isAttachment())
- {
- radius = llmax((S32) mDrawable->getRadius(),1)*attachment_size_factor;
- }
- else
- {
- radius = mDrawable->getRadius();
- radius *= 1.f + mDrawable->mDistanceWRTCamera * distance_factor[1];
- radius += mDrawable->mDistanceWRTCamera * distance_factor[0];
- }
+ if (alpha_wrap)
+ {
+ LLVector3 bounds = getScale();
+ radius = llmin(bounds.mV[1], bounds.mV[2]);
+ radius = llmin(radius, bounds.mV[0]);
+ radius *= 0.5f;
+ //radius *= 1.f+mDrawable->mDistanceWRTCamera*alpha_distance_factor[1];
+ //radius += mDrawable->mDistanceWRTCamera*alpha_distance_factor[0];
+ }
+ else if (shrink_wrap)
+ {
+ radius = mDrawable->getRadius() * 0.25f;
+ }
+ else
+ {
+ F32 szf = size_factor;
+ radius = llmax(mDrawable->getRadius(), szf);
+ //radius = llmax(radius, mDrawable->mDistanceWRTCamera * distance_factor[0]);
+ }
- return llclamp(radius*scale, 0.5f, 256.f);
+ return llclamp(radius, 0.5f, 256.f);
}
const LLVector3 LLVOVolume::getPivotPositionAgent() const
@@ -4571,6 +4507,11 @@ void LLVOVolume::markForUpdate(BOOL priority)
}
}
+ if (mDrawable)
+ {
+ shrinkWrap();
+ }
+
LLViewerObject::markForUpdate(priority);
mVolumeChanged = TRUE;
}
@@ -4626,7 +4567,7 @@ LLVector3 LLVOVolume::volumeDirectionToAgent(const LLVector3& dir) const
}
-BOOL LLVOVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, BOOL pick_rigged, S32 *face_hitp,
+BOOL LLVOVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, BOOL pick_rigged, BOOL pick_unselectable, S32 *face_hitp,
LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent)
{
@@ -4637,6 +4578,14 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a&
return FALSE;
}
+ if (!pick_unselectable)
+ {
+ if (!LLSelectMgr::instance().canSelectObject(this))
+ {
+ return FALSE;
+ }
+ }
+
BOOL ret = FALSE;
LLVolume* volume = getVolume();
@@ -4886,7 +4835,12 @@ void LLVOVolume::updateRiggedVolume(bool force_treat_as_rigged, LLRiggedVolume::
mRiggedVolume->update(skin, avatar, volume, face_index, rebuild_face_octrees);
}
-void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, const LLVolume* volume, FaceIndex face_index, bool rebuild_face_octrees)
+void LLRiggedVolume::update(
+ const LLMeshSkinInfo* skin,
+ LLVOAvatar* avatar,
+ const LLVolume* volume,
+ FaceIndex face_index,
+ bool rebuild_face_octrees)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME;
bool copy = false;
@@ -5070,7 +5024,7 @@ U32 LLVOVolume::getPartitionType() const
}
LLVolumePartition::LLVolumePartition(LLViewerRegion* regionp)
-: LLSpatialPartition(LLVOVolume::VERTEX_DATA_MASK, TRUE, GL_DYNAMIC_DRAW_ARB, regionp),
+: LLSpatialPartition(LLVOVolume::VERTEX_DATA_MASK, TRUE, regionp),
LLVolumeGeometryManager()
{
mLODPeriod = 32;
@@ -5078,7 +5032,6 @@ LLVolumeGeometryManager()
mDrawableType = LLPipeline::RENDER_TYPE_VOLUME;
mPartitionType = LLViewerRegion::PARTITION_VOLUME;
mSlopRatio = 0.25f;
- mBufferUsage = GL_DYNAMIC_DRAW_ARB;
}
LLVolumeBridge::LLVolumeBridge(LLDrawable* drawablep, LLViewerRegion* regionp)
@@ -5090,8 +5043,6 @@ LLVolumeGeometryManager()
mDrawableType = LLPipeline::RENDER_TYPE_VOLUME;
mPartitionType = LLViewerRegion::PARTITION_BRIDGE;
- mBufferUsage = GL_DYNAMIC_DRAW_ARB;
-
mSlopRatio = 0.25f;
}
@@ -5131,6 +5082,11 @@ bool can_batch_texture(LLFace* facep)
return false;
}
+ if (facep->getTextureEntry()->getGLTFRenderMaterial() != nullptr)
+ { // PBR materials break indexed texture batching
+ return false;
+ }
+
return true;
}
@@ -5222,6 +5178,8 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
return;
}
+ LL_LABEL_VERTEX_BUFFER(facep->getVertexBuffer(), LLRenderPass::lookupPassName(type));
+
U32 passType = type;
bool rigged = facep->isState(LLFace::RIGGED);
@@ -5237,7 +5195,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
S32 idx = draw_vec.size()-1;
- BOOL fullbright = (type == LLRenderPass::PASS_FULLBRIGHT) ||
+ bool fullbright = (type == LLRenderPass::PASS_FULLBRIGHT) ||
(type == LLRenderPass::PASS_INVISIBLE) ||
(type == LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK) ||
(type == LLRenderPass::PASS_ALPHA && facep->isState(LLFace::FULLBRIGHT)) ||
@@ -5286,8 +5244,24 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
U8 index = facep->getTextureIndex();
- LLMaterial* mat = facep->getTextureEntry()->getMaterialParams().get();
- LLMaterialID mat_id = facep->getTextureEntry()->getMaterialID();
+ LLMaterial* mat = nullptr;
+
+ LLUUID mat_id;
+
+ auto* gltf_mat = (LLFetchedGLTFMaterial*) facep->getTextureEntry()->getGLTFRenderMaterial();
+ if (gltf_mat != nullptr)
+ {
+ mat_id = gltf_mat->getHash(); // TODO: cache this hash
+ }
+ else
+ {
+ mat = facep->getTextureEntry()->getMaterialParams().get();
+ if (mat)
+ {
+ //mat_id = facep->getTextureEntry()->getMaterialID().asUUID();
+ mat_id = facep->getTextureEntry()->getMaterialParams()->getHash();
+ }
+ }
bool batchable = false;
@@ -5305,11 +5279,9 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
}
}
- F32 vsize = facep->getVirtualSize(); //TODO -- adjust by texture scale?
-
if (index < FACE_DO_NOT_BATCH_TEXTURES && idx >= 0)
{
- if (mat || draw_vec[idx]->mMaterial)
+ if (mat || gltf_mat || draw_vec[idx]->mMaterial)
{ //can't batch textures when materials are present (yet)
batchable = false;
}
@@ -5319,12 +5291,10 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
{
batchable = true;
draw_vec[idx]->mTextureList[index] = tex;
- draw_vec[idx]->mTextureListVSize[index] = vsize;
}
else if (draw_vec[idx]->mTextureList[index] == tex)
{ //this face's texture index can be used with this batch
batchable = true;
- draw_vec[idx]->mTextureListVSize[index] = llmax(vsize, draw_vec[idx]->mTextureListVSize[index]);
}
}
else
@@ -5341,7 +5311,6 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount() <= (U32) gGLManager.mGLMaxVertexRange &&
draw_vec[idx]->mCount + facep->getIndicesCount() <= (U32) gGLManager.mGLMaxIndexRange &&
#endif
- //draw_vec[idx]->mMaterial == mat &&
draw_vec[idx]->mMaterialID == mat_id &&
draw_vec[idx]->mFullbright == fullbright &&
draw_vec[idx]->mBump == bump &&
@@ -5349,24 +5318,18 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
draw_vec[idx]->mTextureMatrix == tex_mat &&
draw_vec[idx]->mModelMatrix == model_mat &&
draw_vec[idx]->mShaderMask == shader_mask &&
- draw_vec[idx]->mSelected == selected &&
draw_vec[idx]->mAvatar == facep->mAvatar &&
draw_vec[idx]->getSkinHash() == facep->getSkinHash())
{
draw_vec[idx]->mCount += facep->getIndicesCount();
draw_vec[idx]->mEnd += facep->getGeomCount();
- draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, vsize);
if (index < FACE_DO_NOT_BATCH_TEXTURES && index >= draw_vec[idx]->mTextureList.size())
{
draw_vec[idx]->mTextureList.resize(index+1);
draw_vec[idx]->mTextureList[index] = tex;
- draw_vec[idx]->mTextureListVSize.resize(index + 1);
- draw_vec[idx]->mTextureListVSize[index] = vsize;
}
draw_vec[idx]->validate();
- update_min_max(draw_vec[idx]->mExtents[0], draw_vec[idx]->mExtents[1], facep->mExtents[0]);
- update_min_max(draw_vec[idx]->mExtents[0], draw_vec[idx]->mExtents[1], facep->mExtents[1]);
}
else
{
@@ -5374,10 +5337,8 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
U32 end = start + facep->getGeomCount()-1;
U32 offset = facep->getIndicesStart();
U32 count = facep->getIndicesCount();
- LLPointer<LLDrawInfo> draw_info = new LLDrawInfo(start,end,count,offset, tex,
- facep->getVertexBuffer(), selected, fullbright, bump);
- draw_info->mGroup = group;
- draw_info->mVSize = vsize;
+ LLPointer<LLDrawInfo> draw_info = new LLDrawInfo(start,end,count,offset, tex,
+ facep->getVertexBuffer(), fullbright, bump);
draw_vec.push_back(draw_info);
draw_info->mTextureMatrix = tex_mat;
draw_info->mModelMatrix = model_mat;
@@ -5398,11 +5359,16 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
draw_info->mEnvIntensity = spec;
draw_info->mSpecularMap = NULL;
draw_info->mMaterial = mat;
+ draw_info->mGLTFMaterial = gltf_mat;
draw_info->mShaderMask = shader_mask;
draw_info->mAvatar = facep->mAvatar;
draw_info->mSkinInfo = facep->mSkinInfo;
- if (mat)
+ if (gltf_mat)
+ {
+ // nothing to do, render pools will reference the GLTF material
+ }
+ else if (mat)
{
draw_info->mMaterialID = mat_id;
@@ -5440,20 +5406,11 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
{ //for alpha sorting
facep->setDrawInfo(draw_info);
}
- draw_info->mExtents[0] = facep->mExtents[0];
- draw_info->mExtents[1] = facep->mExtents[1];
-
- if (LLPipeline::sUseTriStrips)
- {
- draw_info->mDrawMode = LLRender::TRIANGLE_STRIP;
- }
if (index < FACE_DO_NOT_BATCH_TEXTURES)
{ //initialize texture list for texture batching
draw_info->mTextureList.resize(index+1);
draw_info->mTextureList[index] = tex;
- draw_info->mTextureListVSize.resize(index + 1);
- draw_info->mTextureListVSize[index] = vsize;
}
draw_info->validate();
}
@@ -5564,6 +5521,7 @@ static inline void add_face(T*** list, U32* count, T* face)
void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME;
+ llassert(!gCubeSnapshot);
if (group->changeLOD())
{
@@ -5614,8 +5572,6 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
U32 spec_count[2] = { 0 };
U32 normspec_count[2] = { 0 };
- U32 useage = group->getSpatialPartition()->mBufferUsage;
-
static LLCachedControl<S32> max_vbo_size(gSavedSettings, "RenderMaxVBOSize", 512);
static LLCachedControl<S32> max_node_size(gSavedSettings, "RenderMaxNodeSize", 65536);
U32 max_vertices = (max_vbo_size * 1024)/LLVertexBuffer::calcVertexSize(group->getSpatialPartition()->mVertexDataMask);
@@ -5647,11 +5603,6 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
continue;
}
- if (drawablep->isAnimating())
- { //fall back to stream draw for animating verts
- useage = GL_STREAM_DRAW_ARB;
- }
-
LLVOVolume* vobj = drawablep->getVOVolume();
if (!vobj)
@@ -5659,6 +5610,9 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
continue;
}
+ // apply any pending material overrides
+ gGLTFMaterialList.applyQueuedOverrides(vobj);
+
std::string vobj_name = llformat("Vol%p", vobj);
bool is_mesh = vobj->isMesh();
@@ -5742,6 +5696,21 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
continue;
}
+ // HACK -- brute force this check every time a drawable gets rebuilt
+ vobj->updateTEMaterialTextures(i);
+#if 0
+#if LL_RELEASE_WITH_DEBUG_INFO
+ const LLUUID pbr_id( "49c88210-7238-2a6b-70ac-92d4f35963cf" );
+ const LLUUID obj_id( vobj->getID() );
+ bool is_pbr = (obj_id == pbr_id);
+#else
+ bool is_pbr = false;
+#endif
+#else
+ LLGLTFMaterial *gltf_mat = facep->getTextureEntry()->getGLTFRenderMaterial();
+ bool is_pbr = gltf_mat != nullptr;
+#endif
+
//ALWAYS null out vertex buffer on rebuild -- if the face lands in a render
// batch, it will recover its vertex buffer reference from the spatial group
facep->setVertexBuffer(NULL);
@@ -5807,6 +5776,11 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
BOOL force_simple = (facep->getPixelArea() < FORCE_SIMPLE_RENDER_AREA);
U32 type = gPipeline.getPoolTypeFromTE(te, tex);
+ if (is_pbr && gltf_mat && gltf_mat->mAlphaMode != LLGLTFMaterial::ALPHA_MODE_BLEND)
+ {
+ type = LLDrawPool::POOL_GLTF_PBR;
+ }
+ else
if (type != LLDrawPool::POOL_ALPHA && force_simple)
{
type = LLDrawPool::POOL_SIMPLE;
@@ -5871,28 +5845,39 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
if (gPipeline.canUseWindLightShadersOnObjects()
&& LLPipeline::sRenderBump)
{
- if (LLPipeline::sRenderDeferred && te->getMaterialParams().notNull() && !te->getMaterialID().isNull())
+ LLGLTFMaterial* gltf_mat = te->getGLTFRenderMaterial();
+
+ if (LLPipeline::sRenderDeferred &&
+ (gltf_mat != nullptr || (te->getMaterialParams().notNull() && !te->getMaterialID().isNull())))
{
- LLMaterial* mat = te->getMaterialParams().get();
- if (mat->getNormalID().notNull())
- {
- if (mat->getSpecularID().notNull())
- { //has normal and specular maps (needs texcoord1, texcoord2, and tangent)
- add_face(sNormSpecFaces, normspec_count, facep);
- }
- else
- { //has normal map (needs texcoord1 and tangent)
- add_face(sNormFaces, norm_count, facep);
- }
- }
- else if (mat->getSpecularID().notNull())
- { //has specular map but no normal map, needs texcoord2
- add_face(sSpecFaces, spec_count, facep);
- }
- else
- { //has neither specular map nor normal map, only needs texcoord0
- add_face(sSimpleFaces, simple_count, facep);
- }
+ if (gltf_mat != nullptr)
+ {
+ // all gltf materials have all vertex attributes for now
+ add_face(sNormSpecFaces, normspec_count, facep);
+ }
+ else
+ {
+ LLMaterial* mat = te->getMaterialParams().get();
+ if (mat->getNormalID().notNull())
+ {
+ if (mat->getSpecularID().notNull())
+ { //has normal and specular maps (needs texcoord1, texcoord2, and tangent)
+ add_face(sNormSpecFaces, normspec_count, facep);
+ }
+ else
+ { //has normal map (needs texcoord1 and tangent)
+ add_face(sNormFaces, norm_count, facep);
+ }
+ }
+ else if (mat->getSpecularID().notNull())
+ { //has specular map but no normal map, needs texcoord2
+ add_face(sSpecFaces, spec_count, facep);
+ }
+ else
+ { //has neither specular map nor normal map, only needs texcoord0
+ add_face(sSimpleFaces, simple_count, facep);
+ }
+ }
}
else if (te->getBumpmap())
{ //needs normal + tangent
@@ -5957,8 +5942,6 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
}
}
- group->mBufferUsage = useage;
-
//PROCESS NON-ALPHA FACES
U32 simple_mask = LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR;
U32 alpha_mask = simple_mask | 0x80000000; //hack to give alpha verts their own VBO
@@ -6051,8 +6034,6 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)
group->mBuilt = 1.f;
- S32 num_mapped_vertex_buffer = LLVertexBuffer::sMappedCount ;
-
const U32 MAX_BUFFER_COUNT = 4096;
LLVertexBuffer* locked_buffer[MAX_BUFFER_COUNT];
@@ -6103,11 +6084,7 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)
gPipeline.markRebuild(group, TRUE);
}
-
- if (buff->isLocked() && buffer_count < MAX_BUFFER_COUNT)
- {
- locked_buffer[buffer_count++] = buff;
- }
+ buff->unmapBuffer();
}
}
}
@@ -6125,44 +6102,17 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)
LL_PROFILE_ZONE_NAMED("rebuildMesh - flush");
for (LLVertexBuffer** iter = locked_buffer, ** end_iter = locked_buffer+buffer_count; iter != end_iter; ++iter)
{
- (*iter)->flush();
+ (*iter)->unmapBuffer();
}
// don't forget alpha
if(group != NULL &&
- !group->mVertexBuffer.isNull() &&
- group->mVertexBuffer->isLocked())
- {
- group->mVertexBuffer->flush();
- }
- }
-
- //if not all buffers are unmapped
- if(num_mapped_vertex_buffer != LLVertexBuffer::sMappedCount)
- {
- LL_WARNS() << "Not all mapped vertex buffers are unmapped!" << LL_ENDL ;
- for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter)
+ !group->mVertexBuffer.isNull())
{
- LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable();
- if(!drawablep)
- {
- continue;
- }
- for (S32 i = 0; i < drawablep->getNumFaces(); ++i)
- {
- LLFace* face = drawablep->getFace(i);
- if (face)
- {
- LLVertexBuffer* buff = face->getVertexBuffer();
- if (buff && buff->isLocked())
- {
- buff->flush();
- }
- }
- }
+ group->mVertexBuffer->unmapBuffer();
}
}
-
+
group->clearState(LLSpatialGroup::MESH_DIRTY | LLSpatialGroup::NEW_DRAWINFO);
}
}
@@ -6229,28 +6179,6 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace
LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME;
U32 geometryBytes = 0;
- U32 buffer_usage = group->mBufferUsage;
-
- static LLCachedControl<bool> use_transform_feedback(gSavedSettings, "RenderUseTransformFeedback", false);
-
- if (use_transform_feedback &&
- gTransformPositionProgram.mProgramObject && //transform shaders are loaded
- buffer_usage == GL_DYNAMIC_DRAW_ARB && //target buffer is in VRAM
- !(mask & LLVertexBuffer::MAP_WEIGHT4)) //TODO: add support for weights
- {
- buffer_usage = GL_DYNAMIC_COPY_ARB;
- }
-
-#if LL_DARWIN
- // HACK from Leslie:
- // Disable VBO usage for alpha on Mac OS X because it kills the framerate
- // due to implicit calls to glTexSubImage that are beyond our control.
- // (this works because the only calls here that sort by distance are alpha)
- if (distance_sort)
- {
- buffer_usage = 0x0;
- }
-#endif
//calculate maximum number of vertices to store in a single buffer
static LLCachedControl<S32> max_vbo_size(gSavedSettings, "RenderMaxVBOSize", 512);
@@ -6306,11 +6234,7 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace
buffer_index = -1;
}
- static LLCachedControl<U32> max_texture_index(gSavedSettings, "RenderMaxTextureIndex", 16);
- texture_index_channels = llmin(texture_index_channels, (S32) max_texture_index);
-
- //NEVER use more than 16 texture index channels (workaround for prevalent driver bug)
- texture_index_channels = llmin(texture_index_channels, 16);
+ texture_index_channels = LLGLSLShader::sIndexedTextureChannels;
bool flexi = false;
@@ -6471,19 +6395,13 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace
}
}
-
- if (flexi && buffer_usage && buffer_usage != GL_STREAM_DRAW_ARB)
- {
- buffer_usage = GL_STREAM_DRAW_ARB;
- }
-
//create vertex buffer
LLPointer<LLVertexBuffer> buffer;
{
LL_PROFILE_ZONE_NAMED("genDrawInfo - allocate");
- buffer = createVertexBuffer(mask, buffer_usage);
- if(!buffer->allocateBuffer(geom_count, index_count, TRUE))
+ buffer = new LLVertexBuffer(mask);
+ if(!buffer->allocateBuffer(geom_count, index_count))
{
LL_WARNS() << "Failed to allocate group Vertex Buffer to "
<< geom_count << " vertices and "
@@ -6576,15 +6494,24 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace
BOOL is_alpha = (facep->getPoolType() == LLDrawPool::POOL_ALPHA) ? TRUE : FALSE;
- LLMaterial* mat = te->getMaterialParams().get();
+ LLGLTFMaterial* gltf_mat = te->getGLTFRenderMaterial();
- bool can_be_shiny = true;
- if (mat)
- {
- U8 mode = mat->getDiffuseAlphaMode();
- can_be_shiny = mode == LLMaterial::DIFFUSE_ALPHA_MODE_NONE ||
- mode == LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE;
- }
+ LLMaterial* mat = nullptr;
+ bool can_be_shiny = false;
+
+ // ignore traditional material if GLTF material is present
+ if (gltf_mat == nullptr)
+ {
+ mat = te->getMaterialParams().get();
+
+ can_be_shiny = true;
+ if (mat)
+ {
+ U8 mode = mat->getDiffuseAlphaMode();
+ can_be_shiny = mode == LLMaterial::DIFFUSE_ALPHA_MODE_NONE ||
+ mode == LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE;
+ }
+ }
F32 te_alpha = te->getColor().mV[3];
bool use_legacy_bump = te->getBumpmap() && (te->getBumpmap() < 18) && (!mat || mat->getNormalID().isNull());
@@ -6593,10 +6520,26 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace
is_alpha = (is_alpha || transparent) ? TRUE : FALSE;
- if (mat && LLPipeline::sRenderDeferred && !hud_group)
+ if ((gltf_mat || mat) && LLPipeline::sRenderDeferred && !hud_group)
{
bool material_pass = false;
+ if (gltf_mat)
+ { // all other parameters ignored if gltf material is present
+ if (gltf_mat->mAlphaMode == LLGLTFMaterial::ALPHA_MODE_BLEND)
+ {
+ registerFace(group, facep, LLRenderPass::PASS_ALPHA);
+ }
+ else if (gltf_mat->mAlphaMode == LLGLTFMaterial::ALPHA_MODE_MASK)
+ {
+ registerFace(group, facep, LLRenderPass::PASS_GLTF_PBR_ALPHA_MASK);
+ }
+ else
+ {
+ registerFace(group, facep, LLRenderPass::PASS_GLTF_PBR);
+ }
+ }
+ else
// do NOT use 'fullbright' for this logic or you risk sending
// things without normals down the materials pipeline and will
// render poorly if not crash NORSPEC-240,314
@@ -6848,7 +6791,7 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace
if (buffer)
{
- buffer->flush();
+ buffer->unmapBuffer();
}
}
@@ -6863,9 +6806,6 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace
void LLVolumeGeometryManager::addGeometryCount(LLSpatialGroup* group, U32& vertex_count, U32& index_count)
{
- //initialize to default usage for this partition
- U32 usage = group->getSpatialPartition()->mBufferUsage;
-
//for each drawable
for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter)
{
@@ -6875,23 +6815,13 @@ void LLVolumeGeometryManager::addGeometryCount(LLSpatialGroup* group, U32& verte
{
continue;
}
-
- if (drawablep->isAnimating())
- { //fall back to stream draw for animating verts
- usage = GL_STREAM_DRAW_ARB;
- }
}
-
- group->mBufferUsage = usage;
}
void LLGeometryManager::addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32 &index_count)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME;
- //initialize to default usage for this partition
- U32 usage = group->getSpatialPartition()->mBufferUsage;
-
//clear off any old faces
mFaceList.clear();
@@ -6905,11 +6835,6 @@ void LLGeometryManager::addGeometryCount(LLSpatialGroup* group, U32 &vertex_coun
continue;
}
- if (drawablep->isAnimating())
- { //fall back to stream draw for animating verts
- usage = GL_STREAM_DRAW_ARB;
- }
-
//for each face
for (S32 i = 0; i < drawablep->getNumFaces(); i++)
{
@@ -6934,8 +6859,6 @@ void LLGeometryManager::addGeometryCount(LLSpatialGroup* group, U32 &vertex_coun
}
}
}
-
- group->mBufferUsage = usage;
}
LLHUDPartition::LLHUDPartition(LLViewerRegion* regionp) : LLBridgePartition(regionp)
diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h
index 59599ddc0c..9cfd90a940 100644
--- a/indra/newview/llvovolume.h
+++ b/indra/newview/llvovolume.h
@@ -68,7 +68,12 @@ public:
using FaceIndex = S32;
static const FaceIndex UPDATE_ALL_FACES = -1;
static const FaceIndex DO_NOT_UPDATE_FACES = -2;
- void update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, const LLVolume* src_volume, FaceIndex face_index = UPDATE_ALL_FACES, bool rebuild_face_octrees = true);
+ void update(
+ const LLMeshSkinInfo* skin,
+ LLVOAvatar* avatar,
+ const LLVolume* src_volume,
+ FaceIndex face_index = UPDATE_ALL_FACES,
+ bool rebuild_face_octrees = true);
std::string mExtraDebugText;
};
@@ -117,49 +122,50 @@ public:
};
public:
- LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp);
- /*virtual*/ void markDead(); // Override (and call through to parent) to clean up media references
+ LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp);
+ void markDead() override; // Override (and call through to parent) to clean up media references
- /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline);
+ LLDrawable* createDrawable(LLPipeline *pipeline) override;
void deleteFaces();
void animateTextures();
BOOL isVisible() const ;
- /*virtual*/ BOOL isActive() const;
- /*virtual*/ BOOL isAttachment() const;
- /*virtual*/ BOOL isRootEdit() const; // overridden for sake of attachments treating themselves as a root object
- /*virtual*/ BOOL isHUDAttachment() const;
+ BOOL isActive() const override;
+ BOOL isAttachment() const override;
+ BOOL isRootEdit() const override; // overridden for sake of attachments treating themselves as a root object
+ BOOL isHUDAttachment() const override;
void generateSilhouette(LLSelectNode* nodep, const LLVector3& view_point);
- /*virtual*/ BOOL setParent(LLViewerObject* parent);
- S32 getLOD() const { return mLOD; }
+ /*virtual*/ BOOL setParent(LLViewerObject* parent) override;
+ S32 getLOD() const override { return mLOD; }
void setNoLOD() { mLOD = NO_LOD; mLODChanged = TRUE; }
bool isNoLOD() const { return NO_LOD == mLOD; }
- const LLVector3 getPivotPositionAgent() const;
+ const LLVector3 getPivotPositionAgent() const override;
const LLMatrix4& getRelativeXform() const { return mRelativeXform; }
const LLMatrix3& getRelativeXformInvTrans() const { return mRelativeXformInvTrans; }
- /*virtual*/ const LLMatrix4 getRenderMatrix() const;
+ /*virtual*/ const LLMatrix4 getRenderMatrix() const override;
typedef std::map<LLUUID, S32> texture_cost_t;
U32 getRenderCost(texture_cost_t &textures) const;
- /*virtual*/ F32 getEstTrianglesMax() const;
- /*virtual*/ F32 getEstTrianglesStreamingCost() const;
- /* virtual*/ F32 getStreamingCost() const;
- /*virtual*/ bool getCostData(LLMeshCostData& costs) const;
+ /*virtual*/ F32 getEstTrianglesMax() const override;
+ /*virtual*/ F32 getEstTrianglesStreamingCost() const override;
+ /* virtual*/ F32 getStreamingCost() const override;
+ /*virtual*/ bool getCostData(LLMeshCostData& costs) const override;
- /*virtual*/ U32 getTriangleCount(S32* vcount = NULL) const;
- /*virtual*/ U32 getHighLODTriangleCount();
+ /*virtual*/ U32 getTriangleCount(S32* vcount = NULL) const override;
+ /*virtual*/ U32 getHighLODTriangleCount() override;
/*virtual*/ BOOL lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end,
S32 face = -1, // which face to check, -1 = ALL_SIDES
BOOL pick_transparent = FALSE,
BOOL pick_rigged = FALSE,
+ BOOL pick_unselectable = TRUE,
S32* face_hit = NULL, // which face was hit
LLVector4a* intersection = NULL, // return the intersection point
LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point
LLVector4a* normal = NULL, // return the surface normal at the intersection point
LLVector4a* tangent = NULL // return the surface tangent at the intersection point
- );
+ ) override;
LLVector3 agentPositionToVolume(const LLVector3& pos) const;
LLVector3 agentDirectionToVolume(const LLVector3& dir) const;
@@ -169,55 +175,59 @@ public:
BOOL getVolumeChanged() const { return mVolumeChanged; }
- /*virtual*/ F32 getRadius() const { return mVObjRadius; };
- const LLMatrix4& getWorldMatrix(LLXformMatrix* xform) const;
+ F32 getVObjRadius() const override { return mVObjRadius; };
+ const LLMatrix4& getWorldMatrix(LLXformMatrix* xform) const override;
- void markForUpdate(BOOL priority);
+ void markForUpdate(BOOL priority) override;
void markForUnload() { LLViewerObject::markForUnload(TRUE); mVolumeChanged = TRUE; }
- void faceMappingChanged() { mFaceMappingChanged=TRUE; };
+ void faceMappingChanged() override { mFaceMappingChanged=TRUE; }
- /*virtual*/ void onShift(const LLVector4a &shift_vector); // Called when the drawable shifts
+ /*virtual*/ void onShift(const LLVector4a &shift_vector) override; // Called when the drawable shifts
- /*virtual*/ void parameterChanged(U16 param_type, bool local_origin);
- /*virtual*/ void parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_use, bool local_origin);
+ /*virtual*/ void parameterChanged(U16 param_type, bool local_origin) override;
+ /*virtual*/ void parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_use, bool local_origin) override;
+
+ // update mReflectionProbe based on isReflectionProbe()
+ void updateReflectionProbePtr();
/*virtual*/ U32 processUpdateMessage(LLMessageSystem *mesgsys,
void **user_data,
U32 block_num, const EObjectUpdateType update_type,
- LLDataPacker *dp);
-
- /*virtual*/ void setSelected(BOOL sel);
- /*virtual*/ BOOL setDrawableParent(LLDrawable* parentp);
-
- /*virtual*/ void setScale(const LLVector3 &scale, BOOL damped);
-
- /*virtual*/ void changeTEImage(S32 index, LLViewerTexture* new_image) ;
- /*virtual*/ void setNumTEs(const U8 num_tes);
- /*virtual*/ void setTEImage(const U8 te, LLViewerTexture *imagep);
- /*virtual*/ S32 setTETexture(const U8 te, const LLUUID &uuid);
- /*virtual*/ S32 setTEColor(const U8 te, const LLColor3 &color);
- /*virtual*/ S32 setTEColor(const U8 te, const LLColor4 &color);
- /*virtual*/ S32 setTEBumpmap(const U8 te, const U8 bump);
- /*virtual*/ S32 setTEShiny(const U8 te, const U8 shiny);
- /*virtual*/ S32 setTEFullbright(const U8 te, const U8 fullbright);
- /*virtual*/ S32 setTEBumpShinyFullbright(const U8 te, const U8 bump);
- /*virtual*/ S32 setTEMediaFlags(const U8 te, const U8 media_flags);
- /*virtual*/ S32 setTEGlow(const U8 te, const F32 glow);
- /*virtual*/ S32 setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID);
+ LLDataPacker *dp) override;
+
+ /*virtual*/ void setSelected(BOOL sel) override;
+ /*virtual*/ BOOL setDrawableParent(LLDrawable* parentp) override;
+
+ /*virtual*/ void setScale(const LLVector3 &scale, BOOL damped) override;
+
+ /*virtual*/ void changeTEImage(S32 index, LLViewerTexture* new_image) override;
+ /*virtual*/ void setNumTEs(const U8 num_tes) override;
+ /*virtual*/ void setTEImage(const U8 te, LLViewerTexture *imagep) override;
+ /*virtual*/ S32 setTETexture(const U8 te, const LLUUID &uuid) override;
+ /*virtual*/ S32 setTEColor(const U8 te, const LLColor3 &color) override;
+ /*virtual*/ S32 setTEColor(const U8 te, const LLColor4 &color) override;
+ /*virtual*/ S32 setTEBumpmap(const U8 te, const U8 bump) override;
+ /*virtual*/ S32 setTEShiny(const U8 te, const U8 shiny) override;
+ /*virtual*/ S32 setTEFullbright(const U8 te, const U8 fullbright) override;
+ /*virtual*/ S32 setTEBumpShinyFullbright(const U8 te, const U8 bump) override;
+ /*virtual*/ S32 setTEMediaFlags(const U8 te, const U8 media_flags) override;
+ /*virtual*/ S32 setTEGlow(const U8 te, const F32 glow) override;
+ /*virtual*/ S32 setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID) override;
static void setTEMaterialParamsCallbackTE(const LLUUID& objectID, const LLMaterialID& pMaterialID, const LLMaterialPtr pMaterialParams, U32 te);
- /*virtual*/ S32 setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams);
- /*virtual*/ S32 setTEScale(const U8 te, const F32 s, const F32 t);
- /*virtual*/ S32 setTEScaleS(const U8 te, const F32 s);
- /*virtual*/ S32 setTEScaleT(const U8 te, const F32 t);
- /*virtual*/ S32 setTETexGen(const U8 te, const U8 texgen);
- /*virtual*/ S32 setTEMediaTexGen(const U8 te, const U8 media);
- /*virtual*/ BOOL setMaterial(const U8 material);
+ /*virtual*/ S32 setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams) override;
+ S32 setTEGLTFMaterialOverride(U8 te, LLGLTFMaterial* mat) override;
+ /*virtual*/ S32 setTEScale(const U8 te, const F32 s, const F32 t) override;
+ /*virtual*/ S32 setTEScaleS(const U8 te, const F32 s) override;
+ /*virtual*/ S32 setTEScaleT(const U8 te, const F32 t) override;
+ /*virtual*/ S32 setTETexGen(const U8 te, const U8 texgen) override;
+ /*virtual*/ S32 setTEMediaTexGen(const U8 te, const U8 media) override;
+ /*virtual*/ BOOL setMaterial(const U8 material) override;
void setTexture(const S32 face);
S32 getIndexInTex(U32 ch) const {return mIndexInTex[ch];}
- /*virtual*/ BOOL setVolume(const LLVolumeParams &volume_params, const S32 detail, bool unique_volume = false);
+ /*virtual*/ BOOL setVolume(const LLVolumeParams &volume_params, const S32 detail, bool unique_volume = false) override;
void updateSculptTexture();
void setIndexInTex(U32 ch, S32 index) { mIndexInTex[ch] = index ;}
void sculpt();
@@ -226,21 +236,21 @@ public:
void* user_data, S32 status, LLExtStat ext_status);
void updateRelativeXform(bool force_identity = false);
- /*virtual*/ BOOL updateGeometry(LLDrawable *drawable);
- /*virtual*/ void updateFaceSize(S32 idx);
- /*virtual*/ BOOL updateLOD();
- void updateRadius();
- /*virtual*/ void updateTextures();
+ /*virtual*/ BOOL updateGeometry(LLDrawable *drawable) override;
+ /*virtual*/ void updateFaceSize(S32 idx) override;
+ /*virtual*/ BOOL updateLOD() override;
+ void updateRadius() override;
+ /*virtual*/ void updateTextures() override;
void updateTextureVirtualSize(bool forced = false);
void updateFaceFlags();
void regenFaces();
BOOL genBBoxes(BOOL force_global, BOOL should_update_octree_bounds = TRUE);
void preRebuild();
- virtual void updateSpatialExtents(LLVector4a& min, LLVector4a& max);
- virtual F32 getBinRadius();
+ virtual void updateSpatialExtents(LLVector4a& min, LLVector4a& max) override;
+ virtual F32 getBinRadius() override;
- virtual U32 getPartitionType() const;
+ virtual U32 getPartitionType() const override;
// For Lights
void setIsLight(BOOL is_light);
@@ -283,14 +293,27 @@ public:
F32 getLightRadius() const;
F32 getLightFalloff(const F32 fudge_factor = 1.f) const;
F32 getLightCutoff() const;
-
+
+ // Reflection Probes
+ bool setIsReflectionProbe(BOOL is_probe);
+ bool setReflectionProbeAmbiance(F32 ambiance);
+ bool setReflectionProbeNearClip(F32 near_clip);
+ bool setReflectionProbeIsBox(bool is_box);
+ bool setReflectionProbeIsDynamic(bool is_dynamic);
+
+ BOOL isReflectionProbe() const override;
+ F32 getReflectionProbeAmbiance() const;
+ F32 getReflectionProbeNearClip() const;
+ bool getReflectionProbeIsBox() const;
+ bool getReflectionProbeIsDynamic() const;
+
// Flexible Objects
U32 getVolumeInterfaceID() const;
- virtual BOOL isFlexible() const;
- virtual BOOL isSculpted() const;
- virtual BOOL isMesh() const;
- virtual BOOL isRiggedMesh() const;
- virtual BOOL hasLightTexture() const;
+ virtual BOOL isFlexible() const override;
+ virtual BOOL isSculpted() const override;
+ virtual BOOL isMesh() const override;
+ virtual BOOL isRiggedMesh() const override;
+ virtual BOOL hasLightTexture() const override;
BOOL isVolumeGlobal() const;
@@ -307,12 +330,12 @@ public:
void onSetExtendedMeshFlags(U32 flags);
void setExtendedMeshFlags(U32 flags);
bool canBeAnimatedObject() const;
- bool isAnimatedObject() const;
- virtual void onReparent(LLViewerObject *old_parent, LLViewerObject *new_parent);
- virtual void afterReparent();
+ bool isAnimatedObject() const override;
+ virtual void onReparent(LLViewerObject *old_parent, LLViewerObject *new_parent) override;
+ virtual void afterReparent() override;
//virtual
- void updateRiggingInfo();
+ void updateRiggingInfo() override;
S32 mLastRiggingInfoLOD;
// Functions that deal with media, or media navigation
@@ -369,7 +392,10 @@ public:
// Rigged volume update (for raycasting)
// By default, this updates the bounding boxes of all the faces and builds an octree for precise per-triangle raycasting
- void updateRiggedVolume(bool force_treat_as_rigged, LLRiggedVolume::FaceIndex face_index = LLRiggedVolume::UPDATE_ALL_FACES, bool rebuild_face_octrees = true);
+ void updateRiggedVolume(
+ bool force_treat_as_rigged,
+ LLRiggedVolume::FaceIndex face_index = LLRiggedVolume::UPDATE_ALL_FACES,
+ bool rebuild_face_octrees = true);
LLRiggedVolume* getRiggedVolume();
//returns true if volume should be treated as a rigged volume
@@ -454,26 +480,6 @@ protected:
static S32 sNumLODChanges;
friend class LLVolumeImplFlexible;
-
-public:
- bool notifyAboutCreatingTexture(LLViewerTexture *texture);
- bool notifyAboutMissingAsset(LLViewerTexture *texture);
-
-private:
- struct material_info
- {
- LLRender::eTexIndex map;
- U8 te;
-
- material_info(LLRender::eTexIndex map_, U8 te_)
- : map(map_)
- , te(te_)
- {}
- };
-
- typedef std::multimap<LLUUID, material_info> mmap_UUID_MAP_t;
- mmap_UUID_MAP_t mWaitingTextureInfo;
-
};
#endif // LL_LLVOVOLUME_H
diff --git a/indra/newview/llvowater.cpp b/indra/newview/llvowater.cpp
index 089a7712c0..2356e72aab 100644
--- a/indra/newview/llvowater.cpp
+++ b/indra/newview/llvowater.cpp
@@ -150,10 +150,14 @@ BOOL LLVOWater::updateGeometry(LLDrawable *drawable)
indices_per_quad * num_quads);
LLVertexBuffer* buff = face->getVertexBuffer();
- if (!buff || !buff->isWriteable())
+ if (!buff ||
+ buff->getNumIndices() != face->getIndicesCount() ||
+ buff->getNumVerts() != face->getGeomCount() ||
+ face->getIndicesStart() != 0 ||
+ face->getGeomIndex() != 0)
{
- buff = new LLVertexBuffer(LLDrawPoolWater::VERTEX_DATA_MASK, GL_DYNAMIC_DRAW_ARB);
- if (!buff->allocateBuffer(face->getGeomCount(), face->getIndicesCount(), TRUE))
+ buff = new LLVertexBuffer(LLDrawPoolWater::VERTEX_DATA_MASK);
+ if (!buff->allocateBuffer(face->getGeomCount(), face->getIndicesCount()))
{
LL_WARNS() << "Failed to allocate Vertex Buffer on water update to "
<< face->getGeomCount() << " vertices and "
@@ -163,13 +167,6 @@ BOOL LLVOWater::updateGeometry(LLDrawable *drawable)
face->setGeomIndex(0);
face->setVertexBuffer(buff);
}
- else
- {
- if (!buff->resizeBuffer(face->getGeomCount(), face->getIndicesCount()))
- {
- LL_WARNS() << "Failed to resize Vertex Buffer" << LL_ENDL;
- }
- }
index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp);
@@ -230,7 +227,7 @@ BOOL LLVOWater::updateGeometry(LLDrawable *drawable)
}
}
- buff->flush();
+ buff->unmapBuffer();
mDrawable->movePartition();
LLPipeline::sCompiles++;
@@ -295,7 +292,7 @@ U32 LLVOVoidWater::getPartitionType() const
}
LLWaterPartition::LLWaterPartition(LLViewerRegion* regionp)
-: LLSpatialPartition(0, FALSE, GL_DYNAMIC_DRAW_ARB, regionp)
+: LLSpatialPartition(0, FALSE, regionp)
{
mInfiniteFarClip = TRUE;
mDrawableType = LLPipeline::RENDER_TYPE_WATER;
diff --git a/indra/newview/llvowlsky.cpp b/indra/newview/llvowlsky.cpp
index d1f584cbca..86e4853280 100644
--- a/indra/newview/llvowlsky.cpp
+++ b/indra/newview/llvowlsky.cpp
@@ -151,9 +151,9 @@ BOOL LLVOWLSky::updateGeometry(LLDrawable * drawable)
if (mFsSkyVerts.isNull())
{
- mFsSkyVerts = new LLVertexBuffer(LLDrawPoolWLSky::ADV_ATMO_SKY_VERTEX_DATA_MASK, GL_STATIC_DRAW_ARB);
+ mFsSkyVerts = new LLVertexBuffer(LLDrawPoolWLSky::ADV_ATMO_SKY_VERTEX_DATA_MASK);
- if (!mFsSkyVerts->allocateBuffer(4, 6, TRUE))
+ if (!mFsSkyVerts->allocateBuffer(4, 6))
{
LL_WARNS() << "Failed to allocate Vertex Buffer on full screen sky update" << LL_ENDL;
}
@@ -184,7 +184,7 @@ BOOL LLVOWLSky::updateGeometry(LLDrawable * drawable)
*indices++ = 3;
*indices++ = 2;
- mFsSkyVerts->flush();
+ mFsSkyVerts->unmapBuffer();
}
{
@@ -216,7 +216,7 @@ BOOL LLVOWLSky::updateGeometry(LLDrawable * drawable)
for (U32 i = 0; i < strips_segments ;++i)
{
- LLVertexBuffer * segment = new LLVertexBuffer(LLDrawPoolWLSky::SKY_VERTEX_DATA_MASK, GL_STATIC_DRAW_ARB);
+ LLVertexBuffer * segment = new LLVertexBuffer(LLDrawPoolWLSky::SKY_VERTEX_DATA_MASK);
mStripsVerts[i] = segment;
U32 num_stacks_this_seg = stacks_per_seg;
@@ -237,7 +237,7 @@ BOOL LLVOWLSky::updateGeometry(LLDrawable * drawable)
const U32 num_indices_this_seg = 1+num_stacks_this_seg*(2+2*verts_per_stack);
llassert(num_indices_this_seg * sizeof(U16) <= max_buffer_bytes);
- bool allocated = segment->allocateBuffer(num_verts_this_seg, num_indices_this_seg, TRUE);
+ bool allocated = segment->allocateBuffer(num_verts_this_seg, num_indices_this_seg);
#if RELEASE_SHOW_WARNS
if( !allocated )
{
@@ -267,7 +267,7 @@ BOOL LLVOWLSky::updateGeometry(LLDrawable * drawable)
buildStripsBuffer(begin_stack, end_stack, vertices, texCoords, indices, dome_radius, verts_per_stack, total_stacks);
// and unlock the buffer
- segment->flush();
+ segment->unmapBuffer();
}
#if RELEASE_SHOW_DEBUG
@@ -288,7 +288,7 @@ void LLVOWLSky::drawStars(void)
// render the stars as a sphere centered at viewer camera
if (mStarsVerts.notNull())
{
- mStarsVerts->setBuffer(LLDrawPoolWLSky::STAR_VERTEX_DATA_MASK);
+ mStarsVerts->setBuffer();
mStarsVerts->drawArrays(LLRender::TRIANGLES, 0, getStarsNumVerts()*4);
}
}
@@ -302,9 +302,9 @@ void LLVOWLSky::drawFsSky(void)
LLGLDisable disable_blend(GL_BLEND);
- mFsSkyVerts->setBuffer(LLDrawPoolWLSky::ADV_ATMO_SKY_VERTEX_DATA_MASK);
+ mFsSkyVerts->setBuffer();
mFsSkyVerts->drawRange(LLRender::TRIANGLES, 0, mFsSkyVerts->getNumVerts() - 1, mFsSkyVerts->getNumIndices(), 0);
- gPipeline.addTrianglesDrawn(mFsSkyVerts->getNumIndices(), LLRender::TRIANGLES);
+ gPipeline.addTrianglesDrawn(mFsSkyVerts->getNumIndices());
LLVertexBuffer::unbind();
}
@@ -317,21 +317,19 @@ void LLVOWLSky::drawDome(void)
LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
- const U32 data_mask = LLDrawPoolWLSky::SKY_VERTEX_DATA_MASK;
-
std::vector< LLPointer<LLVertexBuffer> >::const_iterator strips_vbo_iter, end_strips;
end_strips = mStripsVerts.end();
for(strips_vbo_iter = mStripsVerts.begin(); strips_vbo_iter != end_strips; ++strips_vbo_iter)
{
LLVertexBuffer * strips_segment = strips_vbo_iter->get();
- strips_segment->setBuffer(data_mask);
+ strips_segment->setBuffer();
strips_segment->drawRange(
LLRender::TRIANGLE_STRIP,
0, strips_segment->getNumVerts()-1, strips_segment->getNumIndices(),
0);
- gPipeline.addTrianglesDrawn(strips_segment->getNumIndices(), LLRender::TRIANGLE_STRIP);
+ gPipeline.addTrianglesDrawn(strips_segment->getNumIndices());
}
LLVertexBuffer::unbind();
@@ -518,10 +516,10 @@ BOOL LLVOWLSky::updateStarGeometry(LLDrawable *drawable)
LLStrider<LLColor4U> colorsp;
LLStrider<LLVector2> texcoordsp;
- if (mStarsVerts.isNull() || !mStarsVerts->isWriteable())
+ if (mStarsVerts.isNull())
{
- mStarsVerts = new LLVertexBuffer(LLDrawPoolWLSky::STAR_VERTEX_DATA_MASK, GL_DYNAMIC_DRAW);
- if (!mStarsVerts->allocateBuffer(getStarsNumVerts()*6, 0, TRUE))
+ mStarsVerts = new LLVertexBuffer(LLDrawPoolWLSky::STAR_VERTEX_DATA_MASK);
+ if (!mStarsVerts->allocateBuffer(getStarsNumVerts()*6, 0))
{
LL_WARNS() << "Failed to allocate Vertex Buffer for Sky to " << getStarsNumVerts() * 6 << " vertices" << LL_ENDL;
}
@@ -578,6 +576,6 @@ BOOL LLVOWLSky::updateStarGeometry(LLDrawable *drawable)
*(colorsp++) = LLColor4U(mStarColors[vtx]);
}
- mStarsVerts->flush();
+ mStarsVerts->unmapBuffer();
return TRUE;
}
diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp
index 871583e071..bba5f6dca6 100644
--- a/indra/newview/llworld.cpp
+++ b/indra/newview/llworld.cpp
@@ -38,6 +38,7 @@
#include "llglheaders.h"
#include "llhttpnode.h"
#include "llregionhandle.h"
+#include "llsky.h"
#include "llsurface.h"
#include "lltrans.h"
#include "llviewercamera.h"
@@ -117,6 +118,7 @@ void LLWorld::resetClass()
{
mHoleWaterObjects.clear();
gObjectList.destroy();
+ gSky.cleanup(); // references an object
for(region_list_t::iterator region_it = mRegionList.begin(); region_it != mRegionList.end(); )
{
LLViewerRegion* region_to_delete = *region_it++;
@@ -819,7 +821,7 @@ void LLWorld::updateNetStats()
void LLWorld::printPacketsLost()
{
- LL_INFOS() << "Simulators:" << LL_ENDL;
+ LL_INFOS() << "Simulators:" << LL_ENDL;
LL_INFOS() << "----------" << LL_ENDL;
LLCircuitData *cdp = NULL;
@@ -854,6 +856,7 @@ F32 LLWorld::getLandFarClip() const
void LLWorld::setLandFarClip(const F32 far_clip)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_ENVIRONMENT;
static S32 const rwidth = (S32)REGION_WIDTH_U32;
S32 const n1 = (llceil(mLandFarClip) - 1) / rwidth;
S32 const n2 = (llceil(far_clip) - 1) / rwidth;
diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp
index 5c56a1d34f..20084aa5d1 100644
--- a/indra/newview/llxmlrpctransaction.cpp
+++ b/indra/newview/llxmlrpctransaction.cpp
@@ -45,6 +45,12 @@
// Have to include these last to avoid queue redefinition!
#include <xmlrpc-epi/xmlrpc.h>
+// <xmlrpc-epi/queue.h> contains a harmful #define queue xmlrpc_queue. This
+// breaks any use of std::queue. Ditch that #define: if any of our code wants
+// to reference xmlrpc_queue, let it reference it directly.
+#if defined(queue)
+#undef queue
+#endif
#include "llappviewer.h"
#include "lltrans.h"
@@ -405,7 +411,7 @@ void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip, const
mHandler = LLXMLRPCTransaction::Handler::ptr_t(new Handler( mHttpRequest, this ));
- mPostH = mHttpRequest->requestPost(LLCore::HttpRequest::DEFAULT_POLICY_ID, 0,
+ mPostH = mHttpRequest->requestPost(LLCore::HttpRequest::DEFAULT_POLICY_ID,
mURI, body.get(), httpOpts, httpHeaders, mHandler);
}
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 13d6966723..325d01ff1b 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -132,12 +132,12 @@
// NOTE: Keep in sync with indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml
// NOTE: Unused consts are commented out since some compilers (on macOS) may complain about unused variables.
// const S32 WATER_REFLECT_NONE_WATER_OPAQUE = -2;
- const S32 WATER_REFLECT_NONE_WATER_TRANSPARENT = -1;
- const S32 WATER_REFLECT_MINIMAL = 0;
+ //const S32 WATER_REFLECT_NONE_WATER_TRANSPARENT = -1;
+ //const S32 WATER_REFLECT_MINIMAL = 0;
// const S32 WATER_REFLECT_TERRAIN = 1;
- const S32 WATER_REFLECT_STATIC_OBJECTS = 2;
- const S32 WATER_REFLECT_AVATARS = 3;
- const S32 WATER_REFLECT_EVERYTHING = 4;
+ //const S32 WATER_REFLECT_STATIC_OBJECTS = 2;
+ //const S32 WATER_REFLECT_AVATARS = 3;
+ //const S32 WATER_REFLECT_EVERYTHING = 4;
bool gShiftFrame = false;
@@ -203,7 +203,6 @@ F32 LLPipeline::RenderEdgeNormCutoff;
LLVector3 LLPipeline::RenderShadowGaussian;
F32 LLPipeline::RenderShadowBlurDistFactor;
bool LLPipeline::RenderDeferredAtmospheric;
-S32 LLPipeline::RenderReflectionDetail;
F32 LLPipeline::RenderHighlightFadeTime;
LLVector3 LLPipeline::RenderShadowClipPlanes;
LLVector3 LLPipeline::RenderShadowOrthoClipPlanes;
@@ -216,6 +215,7 @@ bool LLPipeline::CameraOffset;
F32 LLPipeline::CameraMaxCoF;
F32 LLPipeline::CameraDoFResScale;
F32 LLPipeline::RenderAutoHideSurfaceAreaLimit;
+bool LLPipeline::RenderScreenSpaceReflections;
LLTrace::EventStatHandle<S64> LLPipeline::sStatBatchSize("renderbatchsize");
const F32 BACKLIGHT_DAY_MAGNITUDE_OBJECT = 0.1f;
@@ -227,6 +227,7 @@ extern S32 gBoxFrame;
//extern BOOL gHideSelectedObjects;
extern BOOL gDisplaySwapBuffers;
extern BOOL gDebugGL;
+extern BOOL gCubeSnapshot;
bool gAvatarBacklight = false;
@@ -280,34 +281,11 @@ static LLStaticHashedString sKern("kern");
static LLStaticHashedString sKernScale("kern_scale");
//----------------------------------------
-std::string gPoolNames[] =
-{
- // Correspond to LLDrawpool enum render type
- "NONE",
- "POOL_SIMPLE",
- "POOL_GROUND",
- "POOL_FULLBRIGHT",
- "POOL_BUMP",
- "POOL_MATERIALS",
- "POOL_TERRAIN,"
- "POOL_SKY",
- "POOL_WL_SKY",
- "POOL_TREE",
- "POOL_ALPHA_MASK",
- "POOL_FULLBRIGHT_ALPHA_MASK",
- "POOL_GRASS",
- "POOL_INVISIBLE",
- "POOL_AVATAR",
- "POOL_VOIDWATER",
- "POOL_WATER",
- "POOL_GLOW",
- "POOL_ALPHA"
-};
void drawBox(const LLVector4a& c, const LLVector4a& r);
void drawBoxOutline(const LLVector3& pos, const LLVector3& size);
U32 nhpo2(U32 v);
-LLVertexBuffer* ll_create_cube_vb(U32 type_mask, U32 usage);
+LLVertexBuffer* ll_create_cube_vb(U32 type_mask);
void display_update_camera();
//----------------------------------------
@@ -335,10 +313,8 @@ bool LLPipeline::sRenderTransparentWater = true;
bool LLPipeline::sRenderBump = true;
bool LLPipeline::sBakeSunlight = false;
bool LLPipeline::sNoAlpha = false;
-bool LLPipeline::sUseTriStrips = true;
bool LLPipeline::sUseFarClip = true;
bool LLPipeline::sShadowRender = false;
-bool LLPipeline::sWaterReflections = false;
bool LLPipeline::sRenderGlow = false;
bool LLPipeline::sReflectionRender = false;
bool LLPipeline::sDistortionRender = false;
@@ -346,10 +322,10 @@ bool LLPipeline::sImpostorRender = false;
bool LLPipeline::sImpostorRenderAlphaDepthPass = false;
bool LLPipeline::sUnderWaterRender = false;
bool LLPipeline::sTextureBindTest = false;
-bool LLPipeline::sRenderFrameTest = false;
bool LLPipeline::sRenderAttachedLights = true;
bool LLPipeline::sRenderAttachedParticles = true;
bool LLPipeline::sRenderDeferred = false;
+bool LLPipeline::sReflectionProbesEnabled = false;
S32 LLPipeline::sVisibleLightCount = 0;
bool LLPipeline::sRenderingHUDs;
F32 LLPipeline::sDistortionWaterClipPlaneMargin = 1.0125f;
@@ -361,13 +337,27 @@ static LLCullResult* sCull = NULL;
void validate_framebuffer_object();
+// override the projection_matrix uniform on the given shader to that which would be set by the main camera
+void set_camera_projection_matrix(LLGLSLShader& shader)
+{
+ auto camProj = LLViewerCamera::getInstance()->getProjection();
+ glh::matrix4f projection = get_current_projection();
+ projection.set_row(0, glh::vec4f(camProj.mMatrix[0][0], camProj.mMatrix[0][1], camProj.mMatrix[0][2], camProj.mMatrix[0][3]));
+ projection.set_row(0, glh::vec4f(camProj.mMatrix[1][0], camProj.mMatrix[1][1], camProj.mMatrix[1][2], camProj.mMatrix[1][3]));
+ projection.set_row(0, glh::vec4f(camProj.mMatrix[2][0], camProj.mMatrix[2][1], camProj.mMatrix[2][2], camProj.mMatrix[2][3]));
+ projection.set_row(0, glh::vec4f(camProj.mMatrix[3][0], camProj.mMatrix[3][1], camProj.mMatrix[3][2], camProj.mMatrix[3][3]));
+ shader.uniformMatrix4fv(LLShaderMgr::PROJECTION_MATRIX, 1, FALSE, projection.m);
+}
+
// Add color attachments for deferred rendering
// target -- RenderTarget to add attachments to
-// for_impostor -- whether or not these render targets are for an impostor (if true, avoids implicit sRGB conversions)
bool addDeferredAttachments(LLRenderTarget& target, bool for_impostor = false)
{
- return target.addColorAttachment(for_impostor ? GL_RGBA : GL_SRGB8_ALPHA8) && //specular
- target.addColorAttachment(GL_RGB10_A2); //normal+z
+ bool valid = true
+ && target.addColorAttachment(GL_RGBA) // frag-data[1] specular OR PBR ORM
+ && target.addColorAttachment(GL_RGBA16F) // frag_data[2] normal+z+fogmask, See: class1\deferred\materialF.glsl & softenlight
+ && target.addColorAttachment(GL_RGBA); // frag_data[3] PBR emissive
+ return valid;
}
LLPipeline::LLPipeline() :
@@ -388,26 +378,9 @@ LLPipeline::LLPipeline() :
mGroupQ2Locked(false),
mResetVertexBuffers(false),
mLastRebuildPool(NULL),
- mAlphaPool(NULL),
- mSkyPool(NULL),
- mTerrainPool(NULL),
- mWaterPool(NULL),
- mGroundPool(NULL),
- mSimplePool(NULL),
- mGrassPool(NULL),
- mAlphaMaskPool(NULL),
- mFullbrightAlphaMaskPool(NULL),
- mFullbrightPool(NULL),
- mInvisiblePool(NULL),
- mGlowPool(NULL),
- mBumpPool(NULL),
- mMaterialsPool(NULL),
- mWLSkyPool(NULL),
mLightMask(0),
mLightMovingMask(0),
- mLightingDetail(0),
- mScreenWidth(0),
- mScreenHeight(0)
+ mLightingDetail(0)
{
mNoiseMap = 0;
mTrueNoiseMap = 0;
@@ -436,23 +409,22 @@ void LLPipeline::init()
{
refreshCachedSettings();
+ mRT = &mMainRT;
+
gOctreeMaxCapacity = gSavedSettings.getU32("OctreeMaxNodeCapacity");
gOctreeMinSize = gSavedSettings.getF32("OctreeMinimumNodeSize");
sDynamicLOD = gSavedSettings.getBOOL("RenderDynamicLOD");
- sRenderBump = gSavedSettings.getBOOL("RenderObjectBump");
- sUseTriStrips = gSavedSettings.getBOOL("RenderUseTriStrips");
- LLVertexBuffer::sUseStreamDraw = gSavedSettings.getBOOL("RenderUseStreamVBO");
- LLVertexBuffer::sUseVAO = gSavedSettings.getBOOL("RenderUseVAO");
- LLVertexBuffer::sPreferStreamDraw = gSavedSettings.getBOOL("RenderPreferStreamDraw");
+ sRenderBump = TRUE; // DEPRECATED -- gSavedSettings.getBOOL("RenderObjectBump");
sRenderAttachedLights = gSavedSettings.getBOOL("RenderAttachedLights");
sRenderAttachedParticles = gSavedSettings.getBOOL("RenderAttachedParticles");
- mInitialized = true;
+ mInitialized = true;
stop_glerror();
//create render pass pools
- getPool(LLDrawPool::POOL_ALPHA);
+ getPool(LLDrawPool::POOL_ALPHA_PRE_WATER);
+ getPool(LLDrawPool::POOL_ALPHA_POST_WATER);
getPool(LLDrawPool::POOL_SIMPLE);
getPool(LLDrawPool::POOL_ALPHA_MASK);
getPool(LLDrawPool::POOL_FULLBRIGHT_ALPHA_MASK);
@@ -462,6 +434,7 @@ void LLPipeline::init()
getPool(LLDrawPool::POOL_BUMP);
getPool(LLDrawPool::POOL_MATERIALS);
getPool(LLDrawPool::POOL_GLOW);
+ getPool(LLDrawPool::POOL_GLTF_PBR);
resetFrameStats();
@@ -506,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;
@@ -521,12 +489,26 @@ void LLPipeline::init()
if (mCubeVB.isNull())
{
- mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX, GL_STATIC_DRAW_ARB);
+ mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX);
}
- mDeferredVB = new LLVertexBuffer(DEFERRED_VB_MASK, 0);
- mDeferredVB->allocateBuffer(8, 0, true);
- setLightingDetail(-1);
+ mDeferredVB = new LLVertexBuffer(DEFERRED_VB_MASK);
+ mDeferredVB->allocateBuffer(8, 0);
+
+ {
+ mScreenTriangleVB = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX);
+ mScreenTriangleVB->allocateBuffer(3, 0);
+ LLStrider<LLVector3> vert;
+ mScreenTriangleVB->getVertexStrider(vert);
+
+ vert[0].set(-1, 1, 0);
+ vert[1].set(-1, -3, 0);
+ vert[2].set(3, 1, 0);
+
+ mScreenTriangleVB->unmapBuffer();
+ }
+
+ setLightingDetail(-1);
//
// Update all settings to trigger a cached settings refresh
@@ -537,8 +519,8 @@ void LLPipeline::init()
connectRefreshCachedSettingsSafe("RenderAvatarMaxNonImpostors");
connectRefreshCachedSettingsSafe("RenderDelayVBUpdate");
connectRefreshCachedSettingsSafe("UseOcclusion");
- connectRefreshCachedSettingsSafe("WindLightUseAtmosShaders");
- connectRefreshCachedSettingsSafe("RenderDeferred");
+ // DEPRECATED -- connectRefreshCachedSettingsSafe("WindLightUseAtmosShaders");
+ // DEPRECATED -- connectRefreshCachedSettingsSafe("RenderDeferred");
connectRefreshCachedSettingsSafe("RenderDeferredSunWash");
connectRefreshCachedSettingsSafe("RenderFSAASamples");
connectRefreshCachedSettingsSafe("RenderResolutionDivisor");
@@ -597,7 +579,6 @@ void LLPipeline::init()
connectRefreshCachedSettingsSafe("RenderShadowGaussian");
connectRefreshCachedSettingsSafe("RenderShadowBlurDistFactor");
connectRefreshCachedSettingsSafe("RenderDeferredAtmospheric");
- connectRefreshCachedSettingsSafe("RenderReflectionDetail");
connectRefreshCachedSettingsSafe("RenderHighlightFadeTime");
connectRefreshCachedSettingsSafe("RenderShadowClipPlanes");
connectRefreshCachedSettingsSafe("RenderShadowOrthoClipPlanes");
@@ -610,6 +591,7 @@ void LLPipeline::init()
connectRefreshCachedSettingsSafe("CameraMaxCoF");
connectRefreshCachedSettingsSafe("CameraDoFResScale");
connectRefreshCachedSettingsSafe("RenderAutoHideSurfaceAreaLimit");
+ connectRefreshCachedSettingsSafe("RenderScreenSpaceReflections");
gSavedSettings.getControl("RenderAutoHideSurfaceAreaLimit")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
}
@@ -657,8 +639,10 @@ void LLPipeline::cleanup()
LL_WARNS() << "Tree Pools not cleaned up" << LL_ENDL;
}
- delete mAlphaPool;
- mAlphaPool = NULL;
+ delete mAlphaPoolPreWater;
+ mAlphaPoolPreWater = nullptr;
+ delete mAlphaPoolPostWater;
+ mAlphaPoolPostWater = nullptr;
delete mSkyPool;
mSkyPool = NULL;
delete mTerrainPool;
@@ -692,8 +676,11 @@ void LLPipeline::cleanup()
mInitialized = false;
mDeferredVB = NULL;
+ mScreenTriangleVB = nullptr;
mCubeVB = NULL;
+
+ mReflectionMapManager.cleanup();
}
//============================================================================
@@ -710,14 +697,9 @@ void LLPipeline::destroyGL()
releaseGLBuffers();
- if (LLVertexBuffer::sEnableVBOs)
- {
- LLVertexBuffer::sEnableVBOs = FALSE;
- }
-
if (mMeshDirtyQueryObject)
{
- glDeleteQueriesARB(1, &mMeshDirtyQueryObject);
+ glDeleteQueries(1, &mMeshDirtyQueryObject);
mMeshDirtyQueryObject = 0;
}
}
@@ -734,8 +716,9 @@ void LLPipeline::requestResizeShadowTexture()
void LLPipeline::resizeShadowTexture()
{
- releaseShadowTargets();
- allocateShadowBuffer(mScreenWidth, mScreenHeight);
+ releaseSunShadowTargets();
+ releaseSpotShadowTargets();
+ allocateShadowBuffer(mRT->width, mRT->height);
gResizeShadowTexture = FALSE;
}
@@ -746,70 +729,37 @@ void LLPipeline::resizeScreenTexture()
GLuint resX = gViewerWindow->getWorldViewWidthRaw();
GLuint resY = gViewerWindow->getWorldViewHeightRaw();
- if (gResizeScreenTexture || (resX != mScreen.getWidth()) || (resY != mScreen.getHeight()))
+ if (gResizeScreenTexture || (resX != mRT->screen.getWidth()) || (resY != mRT->screen.getHeight()))
{
releaseScreenBuffers();
- releaseShadowTargets();
+ releaseSunShadowTargets();
+ releaseSpotShadowTargets();
allocateScreenBuffer(resX,resY);
gResizeScreenTexture = FALSE;
}
}
}
-void LLPipeline::allocatePhysicsBuffer()
-{
- GLuint resX = gViewerWindow->getWorldViewWidthRaw();
- GLuint resY = gViewerWindow->getWorldViewHeightRaw();
-
- if (mPhysicsDisplay.getWidth() != resX || mPhysicsDisplay.getHeight() != resY)
- {
- mPhysicsDisplay.allocate(resX, resY, GL_RGBA, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
- }
-}
-
bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
{
- refreshCachedSettings();
-
- bool save_settings = sRenderDeferred;
- if (save_settings)
- {
- // Set this flag in case we crash while resizing window or allocating space for deferred rendering targets
- gSavedSettings.setBOOL("RenderInitError", TRUE);
- gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE );
- }
-
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
eFBOStatus ret = doAllocateScreenBuffer(resX, resY);
- if (save_settings)
- {
- // don't disable shaders on next session
- gSavedSettings.setBOOL("RenderInitError", FALSE);
- gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE );
- }
-
- if (ret == FBO_FAILURE)
- { //FAILSAFE: screen buffer allocation failed, disable deferred rendering if it's enabled
- //NOTE: if the session closes successfully after this call, deferred rendering will be
- // disabled on future sessions
- if (LLPipeline::sRenderDeferred)
- {
- gSavedSettings.setBOOL("RenderDeferred", FALSE);
- LLPipeline::refreshCachedSettings();
- }
- }
-
return ret == FBO_SUCCESS_FULLRES;
}
LLPipeline::eFBOStatus LLPipeline::doAllocateScreenBuffer(U32 resX, U32 resY)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
// try to allocate screen buffers at requested resolution and samples
// - on failure, shrink number of samples and try again
// - if not multisampled, shrink resolution and try again (favor X resolution over Y)
// Make sure to call "releaseScreenBuffers" after each failure to cleanup the partially loaded state
+ // refresh cached settings here to protect against inconsistent event handling order
+ refreshCachedSettings();
+
U32 samples = RenderFSAASamples;
eFBOStatus ret = FBO_SUCCESS_FULLRES;
@@ -858,11 +808,21 @@ LLPipeline::eFBOStatus LLPipeline::doAllocateScreenBuffer(U32 resX, U32 resY)
bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
{
- refreshCachedSettings();
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+ if (mRT == &mMainRT && sReflectionProbesEnabled)
+ { // hacky -- allocate auxillary buffer
+ gCubeSnapshot = TRUE;
+ mReflectionMapManager.initReflectionMaps();
+ mRT = &mAuxillaryRT;
+ U32 res = mReflectionMapManager.mProbeResolution * 2; //multiply by 2 because probes will be super sampled
+ allocateScreenBuffer(res, res, samples);
+ mRT = &mMainRT;
+ gCubeSnapshot = FALSE;
+ }
// remember these dimensions
- mScreenWidth = resX;
- mScreenHeight = resY;
+ mRT->width = resX;
+ mRT->height = resY;
U32 res_mod = RenderResolutionDivisor;
@@ -874,84 +834,57 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
if (RenderUIBuffer)
{
- if (!mUIScreen.allocate(resX,resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE))
+ if (!mRT->uiScreen.allocate(resX,resY, GL_RGBA))
{
return false;
}
}
- if (LLPipeline::sRenderDeferred)
- {
- S32 shadow_detail = RenderShadowDetail;
- bool ssao = RenderDeferredSSAO;
+ S32 shadow_detail = RenderShadowDetail;
+ bool ssao = RenderDeferredSSAO;
- const U32 occlusion_divisor = 3;
-
- //allocate deferred rendering color buffers
- if (!mDeferredScreen.allocate(resX, resY, GL_SRGB8_ALPHA8, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
- if (!mDeferredDepth.allocate(resX, resY, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
- if (!mOcclusionDepth.allocate(resX/occlusion_divisor, resY/occlusion_divisor, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
- if (!addDeferredAttachments(mDeferredScreen)) return false;
+ //allocate deferred rendering color buffers
+ if (!mRT->deferredScreen.allocate(resX, resY, GL_RGBA, true)) return false;
+ if (!addDeferredAttachments(mRT->deferredScreen)) return false;
- GLuint screenFormat = GL_RGBA16;
- if (gGLManager.mIsAMD)
- {
- screenFormat = GL_RGBA12;
- }
-
- if (gGLManager.mGLVersion < 4.f && gGLManager.mIsNVIDIA)
- {
- screenFormat = GL_RGBA16F_ARB;
- }
+ GLuint screenFormat = GL_RGBA16;
- if (!mScreen.allocate(resX, resY, screenFormat, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
- if (samples > 0)
- {
- if (!mFXAABuffer.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_TEXTURE, FALSE, samples)) return false;
- }
- else
- {
- mFXAABuffer.release();
- }
+ 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)) return false;
+ }
+ else
+ {
+ mRT->fxaaBuffer.release();
+ }
- if (shadow_detail > 0 || ssao || RenderDepthOfField || samples > 0)
- { //only need mDeferredLight for shadows OR ssao OR dof OR fxaa
- if (!mDeferredLight.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false;
- }
- else
- {
- mDeferredLight.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)) return false;
+ }
+ else
+ {
+ mRT->deferredLight.release();
+ }
- allocateShadowBuffer(resX, resY);
+ allocateShadowBuffer(resX, resY);
- //HACK make screenbuffer allocations start failing after 30 seconds
- if (gSavedSettings.getBOOL("SimulateFBOFailure"))
- {
- return false;
- }
- }
- else
+ if (!gCubeSnapshot && RenderScreenSpaceReflections) // hack to not allocate mSceneMap for cube snapshots
{
- mDeferredLight.release();
-
- releaseShadowTargets();
+ mSceneMap.allocate(resX, resY, GL_RGB, true);
+ }
- mFXAABuffer.release();
- mScreen.release();
- mDeferredScreen.release(); //make sure to release any render targets that share a depth buffer with mDeferredScreen first
- mDeferredDepth.release();
- mOcclusionDepth.release();
-
- if (!mScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false;
- }
-
- if (LLPipeline::sRenderDeferred)
- { //share depth buffer between deferred targets
- mDeferredScreen.shareDepthBuffer(mScreen);
- }
+ //HACK make screenbuffer allocations start failing after 30 seconds
+ if (gSavedSettings.getBOOL("SimulateFBOFailure"))
+ {
+ return false;
+ }
- gGL.getTexUnit(0)->disable();
+ gGL.getTexUnit(0)->disable();
stop_glerror();
@@ -963,68 +896,89 @@ inline U32 BlurHappySize(U32 x, F32 scale) { return U32( x * scale + 16.0f) & ~0
bool LLPipeline::allocateShadowBuffer(U32 resX, U32 resY)
{
- refreshCachedSettings();
-
- if (LLPipeline::sRenderDeferred)
- {
- S32 shadow_detail = RenderShadowDetail;
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+ S32 shadow_detail = RenderShadowDetail;
- const U32 occlusion_divisor = 3;
+ F32 scale = llmax(0.f, RenderShadowResolutionScale);
+ U32 sun_shadow_map_width = BlurHappySize(resX, scale);
+ U32 sun_shadow_map_height = BlurHappySize(resY, scale);
- F32 scale = llmax(0.f,RenderShadowResolutionScale);
- U32 sun_shadow_map_width = BlurHappySize(resX, scale);
- U32 sun_shadow_map_height = BlurHappySize(resY, scale);
+ if (shadow_detail > 0)
+ { //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))
+ {
+ return false;
+ }
+ }
+ }
+ else
+ {
+ for (U32 i = 0; i < 4; i++)
+ {
+ releaseSunShadowTarget(i);
+ }
+ }
- if (shadow_detail > 0)
- { //allocate 4 sun shadow maps
- for (U32 i = 0; i < 4; i++)
- {
- if (!mShadow[i].allocate(sun_shadow_map_width, sun_shadow_map_height, 0, TRUE, FALSE, LLTexUnit::TT_TEXTURE))
- {
- return false;
- }
+ if (!gCubeSnapshot) // hack to not allocate spot shadow maps during ReflectionMapManager init
+ {
+ U32 width = (U32)(resX * scale);
+ U32 height = width;
- if (!mShadowOcclusion[i].allocate(sun_shadow_map_width/occlusion_divisor, sun_shadow_map_height/occlusion_divisor, 0, TRUE, FALSE, LLTexUnit::TT_TEXTURE))
+ if (shadow_detail > 1)
+ { //allocate two spot shadow maps
+ U32 spot_shadow_map_width = width;
+ 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))
{
return false;
}
- }
- }
- else
- {
- for (U32 i = 0; i < 4; i++)
- {
- releaseShadowTarget(i);
- }
- }
+ }
+ }
+ else
+ {
+ releaseSpotShadowTargets();
+ }
+ }
- U32 width = (U32) (resX*scale);
- U32 height = width;
- if (shadow_detail > 1)
- { //allocate two spot shadow maps
- U32 spot_shadow_map_width = width;
- U32 spot_shadow_map_height = height;
- for (U32 i = 4; i < 6; i++)
- {
- if (!mShadow[i].allocate(spot_shadow_map_width, spot_shadow_map_height, 0, TRUE, FALSE))
- {
- return false;
- }
- if (!mShadowOcclusion[i].allocate(spot_shadow_map_width/occlusion_divisor, height/occlusion_divisor, 0, TRUE, FALSE))
- {
- return false;
- }
- }
+ // set up shadow map filtering and compare modes
+ if (shadow_detail > 0)
+ {
+ for (U32 i = 0; i < 4; i++)
+ {
+ LLRenderTarget* shadow_target = getSunShadowTarget(i);
+ if (shadow_target)
+ {
+ gGL.getTexUnit(0)->bind(getSunShadowTarget(i), TRUE);
+ gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
+ gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
+ }
}
- else
- {
- for (U32 i = 4; i < 6; i++)
- {
- releaseShadowTarget(i);
- }
- }
- }
+ }
+
+ if (shadow_detail > 1 && !gCubeSnapshot)
+ {
+ for (U32 i = 0; i < 2; i++)
+ {
+ LLRenderTarget* shadow_target = getSpotShadowTarget(i);
+ if (shadow_target)
+ {
+ gGL.getTexUnit(0)->bind(shadow_target, TRUE);
+ gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
+ gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
+ }
+ }
+ }
return true;
}
@@ -1038,23 +992,13 @@ void LLPipeline::updateRenderTransparentWater()
//static
void LLPipeline::updateRenderBump()
{
- sRenderBump = gSavedSettings.getBOOL("RenderObjectBump");
-}
-
-// static
-void LLPipeline::updateRenderDeferred()
-{
- sRenderDeferred = !gUseWireframe &&
- RenderDeferred &&
- LLRenderTarget::sUseFBO &&
- LLPipeline::sRenderBump &&
- WindLightUseAtmosShaders &&
- (bool) LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred");
+ sRenderBump = TRUE; // DEPRECATED -- gSavedSettings.getBOOL("RenderObjectBump");
}
// static
void LLPipeline::refreshCachedSettings()
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
LLPipeline::sAutoMaskAlphaDeferred = gSavedSettings.getBOOL("RenderAutoMaskAlphaDeferred");
LLPipeline::sAutoMaskAlphaNonDeferred = gSavedSettings.getBOOL("RenderAutoMaskAlphaNonDeferred");
LLPipeline::sUseFarClip = gSavedSettings.getBOOL("RenderUseFarClip");
@@ -1065,11 +1009,10 @@ void LLPipeline::refreshCachedSettings()
LLPipeline::sUseOcclusion =
(!gUseWireframe
&& LLFeatureManager::getInstance()->isFeatureAvailable("UseOcclusion")
- && gSavedSettings.getBOOL("UseOcclusion")
- && gGLManager.mHasOcclusionQuery) ? 2 : 0;
+ && gSavedSettings.getBOOL("UseOcclusion")) ? 2 : 0;
- WindLightUseAtmosShaders = gSavedSettings.getBOOL("WindLightUseAtmosShaders");
- RenderDeferred = gSavedSettings.getBOOL("RenderDeferred");
+ WindLightUseAtmosShaders = TRUE; // DEPRECATED -- gSavedSettings.getBOOL("WindLightUseAtmosShaders");
+ RenderDeferred = TRUE; // DEPRECATED -- gSavedSettings.getBOOL("RenderDeferred");
RenderDeferredSunWash = gSavedSettings.getF32("RenderDeferredSunWash");
RenderFSAASamples = gSavedSettings.getU32("RenderFSAASamples");
RenderResolutionDivisor = gSavedSettings.getU32("RenderResolutionDivisor");
@@ -1128,7 +1071,6 @@ void LLPipeline::refreshCachedSettings()
RenderShadowGaussian = gSavedSettings.getVector3("RenderShadowGaussian");
RenderShadowBlurDistFactor = gSavedSettings.getF32("RenderShadowBlurDistFactor");
RenderDeferredAtmospheric = gSavedSettings.getBOOL("RenderDeferredAtmospheric");
- RenderReflectionDetail = gSavedSettings.getS32("RenderReflectionDetail");
RenderHighlightFadeTime = gSavedSettings.getF32("RenderHighlightFadeTime");
RenderShadowClipPlanes = gSavedSettings.getVector3("RenderShadowClipPlanes");
RenderShadowOrthoClipPlanes = gSavedSettings.getVector3("RenderShadowOrthoClipPlanes");
@@ -1141,8 +1083,9 @@ void LLPipeline::refreshCachedSettings()
CameraMaxCoF = gSavedSettings.getF32("CameraMaxCoF");
CameraDoFResScale = gSavedSettings.getF32("CameraDoFResScale");
RenderAutoHideSurfaceAreaLimit = gSavedSettings.getF32("RenderAutoHideSurfaceAreaLimit");
+ RenderScreenSpaceReflections = gSavedSettings.getBOOL("RenderScreenSpaceReflections");
+ sReflectionProbesEnabled = LLFeatureManager::getInstance()->isFeatureAvailable("RenderReflectionsEnabled") && gSavedSettings.getBOOL("RenderReflectionsEnabled");
RenderSpotLight = nullptr;
- updateRenderDeferred();
if (gNonInteractive)
{
@@ -1172,8 +1115,9 @@ void LLPipeline::releaseGLBuffers()
mWaterRef.release();
mWaterDis.release();
mBake.release();
- mHighlight.release();
+ mSceneMap.release();
+
for (U32 i = 0; i < 3; i++)
{
mGlow[i].release();
@@ -1192,58 +1136,64 @@ void LLPipeline::releaseLUTBuffers()
LLImageGL::deleteTextures(1, &mLightFunc);
mLightFunc = 0;
}
+
+ mPbrBrdfLut.release();
}
void LLPipeline::releaseShadowBuffers()
{
- releaseShadowTargets();
+ releaseSunShadowTargets();
+ releaseSpotShadowTargets();
}
void LLPipeline::releaseScreenBuffers()
{
- mUIScreen.release();
- mScreen.release();
- mFXAABuffer.release();
- mPhysicsDisplay.release();
- mDeferredScreen.release();
- mDeferredDepth.release();
- mDeferredLight.release();
- mOcclusionDepth.release();
+ mRT->uiScreen.release();
+ mRT->screen.release();
+ mRT->fxaaBuffer.release();
+ mRT->deferredScreen.release();
+ mRT->deferredLight.release();
}
-
-
-void LLPipeline::releaseShadowTarget(U32 index)
+
+void LLPipeline::releaseSunShadowTarget(U32 index)
{
- mShadow[index].release();
- mShadowOcclusion[index].release();
+ llassert(index < 4);
+ mRT->shadow[index].release();
}
-void LLPipeline::releaseShadowTargets()
+void LLPipeline::releaseSunShadowTargets()
{
- for (U32 i = 0; i < 6; i++)
+ for (U32 i = 0; i < 4; i++)
{
- releaseShadowTarget(i);
+ releaseSunShadowTarget(i);
}
}
+void LLPipeline::releaseSpotShadowTargets()
+{
+ if (!gCubeSnapshot) // hack to avoid freeing spot shadows during ReflectionMapManager init
+ {
+ for (U32 i = 0; i < 2; i++)
+ {
+ mSpotShadow[i].release();
+ }
+ }
+}
+
void LLPipeline::createGLBuffers()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
stop_glerror();
assertInitialized();
- updateRenderDeferred();
- if (LLPipeline::sWaterReflections)
+ if (LLPipeline::sRenderTransparentWater)
{ //water reflection texture
U32 res = (U32) llmax(gSavedSettings.getS32("RenderWaterRefResolution"), 512);
- mWaterRef.allocate(res,res,GL_RGBA,TRUE,FALSE);
- mWaterDis.allocate(res,res,GL_RGBA,TRUE,FALSE,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
-
- mHighlight.allocate(256,256,GL_RGBA, FALSE, FALSE);
+ mBake.allocate(512, 512, GL_RGBA, true); // SL-12781 Build > Upload > Model; 3D Preview
stop_glerror();
@@ -1254,12 +1204,12 @@ 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);
- mScreenWidth = 0;
- mScreenHeight = 0;
+ mRT->width = 0;
+ mRT->height = 0;
if (sRenderDeferred)
{
@@ -1279,7 +1229,7 @@ void LLPipeline::createGLBuffers()
LLImageGL::generateTextures(1, &mNoiseMap);
gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseMap);
- LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB, GL_FLOAT, noise, false);
+ LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F, noiseRes, noiseRes, GL_RGB, GL_FLOAT, noise, false);
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
}
@@ -1294,7 +1244,7 @@ void LLPipeline::createGLBuffers()
LLImageGL::generateTextures(1, &mTrueNoiseMap);
gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mTrueNoiseMap);
- LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB,GL_FLOAT, noise, false);
+ LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F, noiseRes, noiseRes, GL_RGB,GL_FLOAT, noise, false);
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
}
@@ -1359,6 +1309,21 @@ void LLPipeline::createLUTBuffers()
delete [] ls;
}
+
+ mPbrBrdfLut.allocate(512, 512, GL_RG16F);
+ mPbrBrdfLut.bindTarget();
+ gDeferredGenBrdfLutProgram.bind();
+
+ gGL.begin(LLRender::TRIANGLE_STRIP);
+ gGL.vertex2f(-1, -1);
+ gGL.vertex2f(-1, 1);
+ gGL.vertex2f(1, -1);
+ gGL.vertex2f(1, 1);
+ gGL.end();
+ gGL.flush();
+
+ gDeferredGenBrdfLutProgram.unbind();
+ mPbrBrdfLut.flush();
}
}
@@ -1575,9 +1540,12 @@ LLDrawPool *LLPipeline::findPool(const U32 type, LLViewerTexture *tex0)
case LLDrawPool::POOL_MATERIALS:
poolp = mMaterialsPool;
break;
- case LLDrawPool::POOL_ALPHA:
- poolp = mAlphaPool;
+ case LLDrawPool::POOL_ALPHA_PRE_WATER:
+ poolp = mAlphaPoolPreWater;
break;
+ case LLDrawPool::POOL_ALPHA_POST_WATER:
+ poolp = mAlphaPoolPostWater;
+ break;
case LLDrawPool::POOL_AVATAR:
case LLDrawPool::POOL_CONTROL_AV:
@@ -1599,6 +1567,10 @@ LLDrawPool *LLPipeline::findPool(const U32 type, LLViewerTexture *tex0)
poolp = mWLSkyPool;
break;
+ case LLDrawPool::POOL_GLTF_PBR:
+ poolp = mPBROpaquePool;
+ break;
+
default:
llassert(0);
LL_ERRS() << "Invalid Pool Type in LLPipeline::findPool() type=" << type << LL_ENDL;
@@ -1640,6 +1612,7 @@ U32 LLPipeline::getPoolTypeFromTE(const LLTextureEntry* te, LLViewerTexture* ima
}
LLMaterial* mat = te->getMaterialParams().get();
+ LLGLTFMaterial* gltf_mat = te->getGLTFRenderMaterial();
bool color_alpha = te->getColor().mV[3] < 0.999f;
bool alpha = color_alpha;
@@ -1665,7 +1638,7 @@ U32 LLPipeline::getPoolTypeFromTE(const LLTextureEntry* te, LLViewerTexture* ima
}
}
- if (alpha)
+ if (alpha || (gltf_mat && gltf_mat->mAlphaMode == LLGLTFMaterial::ALPHA_MODE_BLEND))
{
return LLDrawPool::POOL_ALPHA;
}
@@ -1673,6 +1646,10 @@ U32 LLPipeline::getPoolTypeFromTE(const LLTextureEntry* te, LLViewerTexture* ima
{
return LLDrawPool::POOL_BUMP;
}
+ else if (gltf_mat)
+ {
+ return LLDrawPool::POOL_GLTF_PBR;
+ }
else if (mat && !alpha)
{
return LLDrawPool::POOL_MATERIALS;
@@ -1749,14 +1726,6 @@ void LLPipeline::unlinkDrawable(LLDrawable *drawable)
}
}
- HighlightItem item(drawablep);
- mHighlightSet.erase(item);
-
- if (mHighlightObject == drawablep)
- {
- mHighlightObject = NULL;
- }
-
for (U32 i = 0; i < 2; ++i)
{
if (mShadowSpotLight[i] == drawablep)
@@ -2035,6 +2004,7 @@ void LLPipeline::updateMove()
//static
F32 LLPipeline::calcPixelArea(LLVector3 center, LLVector3 size, LLCamera &camera)
{
+ llassert(!gCubeSnapshot); // shouldn't be doing ANY of this during cube snap shots
LLVector3 lookAt = center - camera.getOrigin();
F32 dist = lookAt.length();
@@ -2333,17 +2303,35 @@ bool LLPipeline::getVisibleExtents(LLCamera& camera, LLVector3& min, LLVector3&
static LLTrace::BlockTimerStatHandle FTM_CULL("Object Culling");
-void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, LLPlane* planep)
+void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result)
{
- static LLCachedControl<bool> use_occlusion(gSavedSettings,"UseOcclusion");
- static bool can_use_occlusion = LLFeatureManager::getInstance()->isFeatureAvailable("UseOcclusion")
- && gGLManager.mHasOcclusionQuery;
-
LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; //LL_RECORD_BLOCK_TIME(FTM_CULL);
+ LL_PROFILE_GPU_ZONE("updateCull"); // should always be zero GPU time, but drop a timer to flush stuff out
- if (planep != nullptr)
+ bool water_clip = !sRenderTransparentWater;
+
+ if (water_clip)
{
- camera.setUserClipPlane(*planep);
+
+ LLVector3 pnorm;
+
+ F32 water_height = LLEnvironment::instance().getWaterHeight();
+
+ if (sUnderWaterRender)
+ {
+ //camera is below water, cull above water
+ pnorm.setVec(0, 0, 1);
+ }
+ else
+ {
+ //camera is above water, cull below water
+ pnorm = LLVector3(0, 0, -1);
+ }
+
+ LLPlane plane;
+ plane.setVec(LLVector3(0, 0, water_height), pnorm);
+
+ camera.setUserClipPlane(plane);
}
else
{
@@ -2354,56 +2342,6 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, LLPlane* pla
sCull->clear();
- bool to_texture = LLPipeline::sUseOcclusion > 1 && gPipeline.shadersLoaded();
-
- if (to_texture)
- {
- if (LLPipeline::sRenderDeferred && can_use_occlusion)
- {
- mOcclusionDepth.bindTarget();
- }
- else
- {
- mScreen.bindTarget();
- }
- }
-
- if (sUseOcclusion > 1)
- {
- gGL.setColorMask(false, false);
- }
-
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.pushMatrix();
- gGL.loadMatrix(gGLLastProjection);
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.pushMatrix();
- gGLLastMatrix = NULL;
- gGL.loadMatrix(gGLLastModelView);
-
- LLGLDisable blend(GL_BLEND);
- LLGLDisable test(GL_ALPHA_TEST);
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-
- LLGLDepthTest depth(GL_TRUE, GL_FALSE);
-
- bool bound_shader = false;
- if (gPipeline.shadersLoaded() && LLGLSLShader::sCurBoundShader == 0)
- { //if no shader is currently bound, use the occlusion shader instead of fixed function if we can
- // (shadow render uses a special shader that clamps to clip planes)
- bound_shader = true;
- gOcclusionCubeProgram.bind();
- }
-
- if (sUseOcclusion > 1)
- {
- if (mCubeVB.isNull())
- { //cube VB will be used for issuing occlusion queries
- mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX, GL_STATIC_DRAW_ARB);
- }
- mCubeVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
- }
-
for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
{
@@ -2425,16 +2363,10 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, LLPlane* pla
LLVOCachePartition* vo_part = region->getVOCachePartition();
if(vo_part)
{
- bool do_occlusion_cull = can_use_occlusion && use_occlusion && !gUseWireframe;
- vo_part->cull(camera, do_occlusion_cull);
+ vo_part->cull(camera, sUseOcclusion > 0);
}
}
- if (bound_shader)
- {
- gOcclusionCubeProgram.unbind();
- }
-
if (hasRenderType(LLPipeline::RENDER_TYPE_SKY) &&
gSky.mVOSkyp.notNull() &&
gSky.mVOSkyp->mDrawable.notNull())
@@ -2445,17 +2377,6 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, LLPlane* pla
stop_glerror();
}
- if (hasRenderType(LLPipeline::RENDER_TYPE_GROUND) &&
- !gPipeline.canUseWindLightShaders() &&
- gSky.mVOGroundp.notNull() &&
- gSky.mVOGroundp->mDrawable.notNull() &&
- !LLPipeline::sWaterReflections)
- {
- gSky.mVOGroundp->mDrawable->setVisible(camera);
- sCull->pushDrawable(gSky.mVOGroundp->mDrawable);
- }
-
-
if (hasRenderType(LLPipeline::RENDER_TYPE_WL_SKY) &&
gPipeline.canUseWindLightShaders() &&
gSky.mVOWLSkyp.notNull() &&
@@ -2471,28 +2392,6 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, LLPlane* pla
{
LLWorld::getInstance()->precullWaterObjects(camera, sCull, render_water);
}
-
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.popMatrix();
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.popMatrix();
-
- if (sUseOcclusion > 1)
- {
- gGL.setColorMask(true, false);
- }
-
- if (to_texture)
- {
- if (LLPipeline::sRenderDeferred && can_use_occlusion)
- {
- mOcclusionDepth.flush();
- }
- else
- {
- mScreen.flush();
- }
- }
}
void LLPipeline::markNotCulled(LLSpatialGroup* group, LLCamera& camera)
@@ -2504,7 +2403,7 @@ void LLPipeline::markNotCulled(LLSpatialGroup* group, LLCamera& camera)
group->setVisible();
- if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
+ if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD && !gCubeSnapshot)
{
group->updateDistance(camera);
}
@@ -2520,6 +2419,13 @@ void LLPipeline::markNotCulled(LLSpatialGroup* group, LLCamera& camera)
sCull->pushVisibleGroup(group);
}
+ if (group->needsUpdate() ||
+ group->getVisible(LLViewerCamera::sCurCameraID) < LLDrawable::getCurrentFrame() - 1)
+ {
+ // include this group in occlusion groups, not because it is an occluder, but because we want to run
+ // an occlusion query to find out if it's an occluder
+ markOccluder(group);
+ }
mNumVisibleNodes++;
}
@@ -2548,32 +2454,28 @@ void LLPipeline::markOccluder(LLSpatialGroup* group)
void LLPipeline::downsampleDepthBuffer(LLRenderTarget& source, LLRenderTarget& dest, LLRenderTarget* scratch_space)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
+ LL_PROFILE_GPU_ZONE("downsampleDepthBuffer");
+
LLGLSLShader* last_shader = LLGLSLShader::sCurBoundShaderPtr;
LLGLSLShader* shader = NULL;
if (scratch_space)
{
+#if 0 // TODO -- restore occlusion culling functionality
GLint bits = 0;
- bits |= (source.hasStencil() && dest.hasStencil()) ? GL_STENCIL_BUFFER_BIT : 0;
- bits |= GL_DEPTH_BUFFER_BIT;
- scratch_space->copyContents(source,
+ bits = GL_DEPTH_BUFFER_BIT;
+ scratch_space->copyContents(source,
0, 0, source.getWidth(), source.getHeight(),
0, 0, scratch_space->getWidth(), scratch_space->getHeight(), bits, GL_NEAREST);
+#endif
}
dest.bindTarget();
dest.clear(GL_DEPTH_BUFFER_BIT);
- LLStrider<LLVector3> vert;
- mDeferredVB->getVertexStrider(vert);
- LLStrider<LLVector2> tc0;
-
- vert[0].set(-1,1,0);
- vert[1].set(-1,-3,0);
- vert[2].set(3,1,0);
-
- if (source.getUsage() == LLTexUnit::TT_RECT_TEXTURE)
+ if (source.getUsage() == LLTexUnit::TT_TEXTURE)
{
shader = &gDownsampleDepthRectProgram;
shader->bind();
@@ -2592,8 +2494,8 @@ void LLPipeline::downsampleDepthBuffer(LLRenderTarget& source, LLRenderTarget& d
{
LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS);
- mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
- mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+ mScreenTriangleVB->setBuffer();
+ mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
}
dest.flush();
@@ -2608,17 +2510,12 @@ void LLPipeline::downsampleDepthBuffer(LLRenderTarget& source, LLRenderTarget& d
}
}
-void LLPipeline::doOcclusion(LLCamera& camera, LLRenderTarget& source, LLRenderTarget& dest, LLRenderTarget* scratch_space)
-{
- downsampleDepthBuffer(source, dest, scratch_space);
- dest.bindTarget();
- doOcclusion(camera);
- dest.flush();
-}
-
void LLPipeline::doOcclusion(LLCamera& camera)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
+ LL_PROFILE_GPU_ZONE("doOcclusion");
+ llassert(!gCubeSnapshot);
+
if (LLPipeline::sUseOcclusion > 1 && !LLSpatialPartition::sTeleportRequested &&
(sCull->hasOcclusionGroups() || LLVOCachePartition::sNeedsOcclusionCheck))
{
@@ -2639,25 +2536,13 @@ void LLPipeline::doOcclusion(LLCamera& camera)
LLGLDisable cull(GL_CULL_FACE);
-
- bool bind_shader = (LLGLSLShader::sCurBoundShader == 0);
- if (bind_shader)
- {
- if (LLPipeline::sShadowRender)
- {
- gDeferredShadowCubeProgram.bind();
- }
- else
- {
- gOcclusionCubeProgram.bind();
- }
- }
+ gOcclusionCubeProgram.bind();
if (mCubeVB.isNull())
{ //cube VB will be used for issuing occlusion queries
- mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX, GL_STATIC_DRAW_ARB);
+ mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX);
}
- mCubeVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+ mCubeVB->setBuffer();
for (LLCullResult::sg_iterator iter = sCull->beginOcclusionGroups(); iter != sCull->endOcclusionGroups(); ++iter)
{
@@ -2677,19 +2562,7 @@ void LLPipeline::doOcclusion(LLCamera& camera)
}
}
- if (bind_shader)
- {
- if (LLPipeline::sShadowRender)
- {
- gDeferredShadowCubeProgram.unbind();
- }
- else
- {
- gOcclusionCubeProgram.unbind();
- }
- }
-
- gGL.setColorMask(true, false);
+ gGL.setColorMask(true, true);
}
}
@@ -2715,10 +2588,6 @@ void LLPipeline::updateGL()
LLGLUpdate::sGLQ.pop_front();
}
}
-
- { //seed VBO Pools
- LLVertexBuffer::seedPools();
- }
}
void LLPipeline::clearRebuildGroups()
@@ -2837,6 +2706,8 @@ void LLPipeline::clearRebuildDrawables()
void LLPipeline::rebuildPriorityGroups()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
+ LL_PROFILE_GPU_ZONE("rebuildPriorityGroups");
+
LLTimer update_timer;
assertInitialized();
@@ -2860,7 +2731,7 @@ void LLPipeline::rebuildPriorityGroups()
void LLPipeline::rebuildGroups()
{
- if (mGroupQ2.empty())
+ if (mGroupQ2.empty() || gCubeSnapshot)
{
return;
}
@@ -2910,6 +2781,10 @@ void LLPipeline::updateGeom(F32 max_dtime)
LLPointer<LLDrawable> drawablep;
LL_RECORD_BLOCK_TIME(FTM_GEO_UPDATE);
+ if (gCubeSnapshot)
+ {
+ return;
+ }
assertInitialized();
@@ -3149,6 +3024,8 @@ void LLPipeline::shiftObjects(const LLVector3 &offset)
}
}
+ mReflectionMapManager.shift(offseta);
+
LLHUDText::shiftAll(offset);
LLHUDNameTag::shiftAll(offset);
@@ -3287,6 +3164,7 @@ void LLPipeline::markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags f
void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
+ LL_PROFILE_GPU_ZONE("stateSort");
if (hasAnyRenderType(LLPipeline::RENDER_TYPE_AVATAR,
LLPipeline::RENDER_TYPE_CONTROL_AV,
@@ -3329,7 +3207,7 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result)
}
}
- if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
+ if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD && !gCubeSnapshot)
{
LLSpatialGroup* last_group = NULL;
BOOL fov_changed = LLViewerCamera::getInstance()->isDefaultFOVChanged();
@@ -3411,7 +3289,7 @@ void LLPipeline::stateSort(LLSpatialGroup* group, LLCamera& camera)
stateSort(drawablep, camera);
}
- if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
+ if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD && !gCubeSnapshot)
{ //avoid redundant stateSort calls
group->mLastUpdateDistance = group->mDistance;
}
@@ -3480,7 +3358,7 @@ void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera)
}
}
- if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
+ if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD && !gCubeSnapshot)
{
//if (drawablep->isVisible()) isVisible() check here is redundant, if it wasn't visible, it wouldn't be here
{
@@ -3574,424 +3452,390 @@ void renderScriptedBeacons(LLDrawable* drawablep)
}
}
-void renderScriptedTouchBeacons(LLDrawable* drawablep)
+void renderScriptedTouchBeacons(LLDrawable *drawablep)
{
- LLViewerObject *vobj = drawablep->getVObj();
- if (vobj
- && !vobj->isAvatar()
- && !vobj->getParent()
- && vobj->flagScripted()
- && vobj->flagHandleTouch())
- {
- if (gPipeline.sRenderBeacons)
- {
- gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(1.f, 0.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), LLPipeline::DebugBeaconLineWidth);
- }
+ LLViewerObject *vobj = drawablep->getVObj();
+ if (vobj && !vobj->isAvatar() && !vobj->getParent() && vobj->flagScripted() && vobj->flagHandleTouch())
+ {
+ if (gPipeline.sRenderBeacons)
+ {
+ gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(1.f, 0.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f),
+ LLPipeline::DebugBeaconLineWidth);
+ }
- if (gPipeline.sRenderHighlight)
- {
- S32 face_id;
- S32 count = drawablep->getNumFaces();
- for (face_id = 0; face_id < count; face_id++)
- {
- LLFace * facep = drawablep->getFace(face_id);
- if (facep)
- {
- gPipeline.mHighlightFaces.push_back(facep);
- }
- }
- }
-}
+ if (gPipeline.sRenderHighlight)
+ {
+ S32 face_id;
+ S32 count = drawablep->getNumFaces();
+ for (face_id = 0; face_id < count; face_id++)
+ {
+ LLFace *facep = drawablep->getFace(face_id);
+ if (facep)
+ {
+ gPipeline.mHighlightFaces.push_back(facep);
+ }
+ }
+ }
+ }
}
-void renderPhysicalBeacons(LLDrawable* drawablep)
+void renderPhysicalBeacons(LLDrawable *drawablep)
{
- LLViewerObject *vobj = drawablep->getVObj();
- if (vobj
- && !vobj->isAvatar()
- //&& !vobj->getParent()
- && vobj->flagUsePhysics())
- {
- if (gPipeline.sRenderBeacons)
- {
- gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(0.f, 1.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), LLPipeline::DebugBeaconLineWidth);
- }
+ LLViewerObject *vobj = drawablep->getVObj();
+ if (vobj &&
+ !vobj->isAvatar()
+ //&& !vobj->getParent()
+ && vobj->flagUsePhysics())
+ {
+ if (gPipeline.sRenderBeacons)
+ {
+ gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(0.f, 1.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f),
+ LLPipeline::DebugBeaconLineWidth);
+ }
- if (gPipeline.sRenderHighlight)
- {
- S32 face_id;
- S32 count = drawablep->getNumFaces();
- for (face_id = 0; face_id < count; face_id++)
- {
- LLFace * facep = drawablep->getFace(face_id);
- if (facep)
- {
- gPipeline.mHighlightFaces.push_back(facep);
- }
- }
- }
-}
+ if (gPipeline.sRenderHighlight)
+ {
+ S32 face_id;
+ S32 count = drawablep->getNumFaces();
+ for (face_id = 0; face_id < count; face_id++)
+ {
+ LLFace *facep = drawablep->getFace(face_id);
+ if (facep)
+ {
+ gPipeline.mHighlightFaces.push_back(facep);
+ }
+ }
+ }
+ }
}
-void renderMOAPBeacons(LLDrawable* drawablep)
+void renderMOAPBeacons(LLDrawable *drawablep)
{
- LLViewerObject *vobj = drawablep->getVObj();
+ LLViewerObject *vobj = drawablep->getVObj();
- if(!vobj || vobj->isAvatar())
- return;
+ if (!vobj || vobj->isAvatar())
+ return;
- bool beacon=false;
- U8 tecount=vobj->getNumTEs();
- for(int x=0;x<tecount;x++)
- {
- if(vobj->getTE(x)->hasMedia())
- {
- beacon=true;
- break;
- }
- }
- if(beacon)
- {
- if (gPipeline.sRenderBeacons)
- {
- gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(1.f, 1.f, 1.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), LLPipeline::DebugBeaconLineWidth);
- }
+ bool beacon = false;
+ U8 tecount = vobj->getNumTEs();
+ for (int x = 0; x < tecount; x++)
+ {
+ if (vobj->getTE(x)->hasMedia())
+ {
+ beacon = true;
+ break;
+ }
+ }
+ if (beacon)
+ {
+ if (gPipeline.sRenderBeacons)
+ {
+ gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(1.f, 1.f, 1.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f),
+ LLPipeline::DebugBeaconLineWidth);
+ }
- if (gPipeline.sRenderHighlight)
- {
- S32 face_id;
- S32 count = drawablep->getNumFaces();
- for (face_id = 0; face_id < count; face_id++)
- {
- LLFace * facep = drawablep->getFace(face_id);
- if (facep)
- {
- gPipeline.mHighlightFaces.push_back(facep);
- }
- }
- }
-}
+ if (gPipeline.sRenderHighlight)
+ {
+ S32 face_id;
+ S32 count = drawablep->getNumFaces();
+ for (face_id = 0; face_id < count; face_id++)
+ {
+ LLFace *facep = drawablep->getFace(face_id);
+ if (facep)
+ {
+ gPipeline.mHighlightFaces.push_back(facep);
+ }
+ }
+ }
+ }
}
-void renderParticleBeacons(LLDrawable* drawablep)
+void renderParticleBeacons(LLDrawable *drawablep)
{
- // Look for attachments, objects, etc.
- LLViewerObject *vobj = drawablep->getVObj();
- if (vobj
- && vobj->isParticleSource())
- {
- if (gPipeline.sRenderBeacons)
- {
- LLColor4 light_blue(0.5f, 0.5f, 1.f, 0.5f);
- gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", light_blue, LLColor4(1.f, 1.f, 1.f, 0.5f), LLPipeline::DebugBeaconLineWidth);
- }
-
- if (gPipeline.sRenderHighlight)
- {
- S32 face_id;
- S32 count = drawablep->getNumFaces();
- for (face_id = 0; face_id < count; face_id++)
- {
- LLFace * facep = drawablep->getFace(face_id);
- if (facep)
- {
- gPipeline.mHighlightFaces.push_back(facep);
- }
- }
- }
-}
-}
+ // Look for attachments, objects, etc.
+ LLViewerObject *vobj = drawablep->getVObj();
+ if (vobj && vobj->isParticleSource())
+ {
+ if (gPipeline.sRenderBeacons)
+ {
+ LLColor4 light_blue(0.5f, 0.5f, 1.f, 0.5f);
+ gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", light_blue, LLColor4(1.f, 1.f, 1.f, 0.5f),
+ LLPipeline::DebugBeaconLineWidth);
+ }
-void renderSoundHighlights(LLDrawable* drawablep)
-{
- // Look for attachments, objects, etc.
- LLViewerObject *vobj = drawablep->getVObj();
- if (vobj && vobj->isAudioSource())
- {
- if (gPipeline.sRenderHighlight)
- {
- S32 face_id;
- S32 count = drawablep->getNumFaces();
- for (face_id = 0; face_id < count; face_id++)
- {
- LLFace * facep = drawablep->getFace(face_id);
- if (facep)
- {
- gPipeline.mHighlightFaces.push_back(facep);
- }
- }
- }
-}
+ if (gPipeline.sRenderHighlight)
+ {
+ S32 face_id;
+ S32 count = drawablep->getNumFaces();
+ for (face_id = 0; face_id < count; face_id++)
+ {
+ LLFace *facep = drawablep->getFace(face_id);
+ if (facep)
+ {
+ gPipeline.mHighlightFaces.push_back(facep);
+ }
+ }
+ }
+ }
}
-void LLPipeline::touchTexture(LLViewerTexture* tex, F32 vsize)
+void renderSoundHighlights(LLDrawable *drawablep)
{
- if (tex)
+ // Look for attachments, objects, etc.
+ LLViewerObject *vobj = drawablep->getVObj();
+ if (vobj && vobj->isAudioSource())
{
- LLImageGL* gl_tex = tex->getGLTexture();
- if (gl_tex && gl_tex->updateBindStats(gl_tex->mTextureMemory))
+ if (gPipeline.sRenderHighlight)
{
- tex->setActive();
- tex->addTextureStats(vsize);
+ S32 face_id;
+ S32 count = drawablep->getNumFaces();
+ for (face_id = 0; face_id < count; face_id++)
+ {
+ LLFace *facep = drawablep->getFace(face_id);
+ if (facep)
+ {
+ gPipeline.mHighlightFaces.push_back(facep);
+ }
+ }
}
}
-
-
}
-void LLPipeline::touchTextures(LLDrawInfo* info)
+
+void LLPipeline::postSort(LLCamera &camera)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
- for (int i = 0; i < info->mTextureList.size(); ++i)
+
+ assertInitialized();
+
+ LL_PUSH_CALLSTACKS();
+
+ if (!gCubeSnapshot)
{
- touchTexture(info->mTextureList[i], info->mTextureListVSize[i]);
+ // rebuild drawable geometry
+ for (LLCullResult::sg_iterator i = sCull->beginDrawableGroups(); i != sCull->endDrawableGroups(); ++i)
+ {
+ LLSpatialGroup *group = *i;
+ if (!sUseOcclusion || !group->isOcclusionState(LLSpatialGroup::OCCLUDED))
+ {
+ group->rebuildGeom();
+ }
+ }
+ LL_PUSH_CALLSTACKS();
+ // rebuild groups
+ sCull->assertDrawMapsEmpty();
+
+ rebuildPriorityGroups();
}
- touchTexture(info->mTexture, info->mVSize);
- touchTexture(info->mSpecularMap, info->mVSize);
- touchTexture(info->mNormalMap, info->mVSize);
-}
+ LL_PUSH_CALLSTACKS();
-void LLPipeline::postSort(LLCamera& camera)
-{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
+ // build render map
+ for (LLCullResult::sg_iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i)
+ {
+ LLSpatialGroup *group = *i;
+ if ((sUseOcclusion && group->isOcclusionState(LLSpatialGroup::OCCLUDED)) ||
+ (RenderAutoHideSurfaceAreaLimit > 0.f &&
+ group->mSurfaceArea > RenderAutoHideSurfaceAreaLimit * llmax(group->mObjectBoxSize, 10.f)))
+ {
+ continue;
+ }
- assertInitialized();
+ if (group->hasState(LLSpatialGroup::NEW_DRAWINFO) && group->hasState(LLSpatialGroup::GEOM_DIRTY) && !gCubeSnapshot)
+ { // no way this group is going to be drawable without a rebuild
+ group->rebuildGeom();
+ }
- LL_PUSH_CALLSTACKS();
- //rebuild drawable geometry
- for (LLCullResult::sg_iterator i = sCull->beginDrawableGroups(); i != sCull->endDrawableGroups(); ++i)
- {
- LLSpatialGroup* group = *i;
- if (!sUseOcclusion ||
- !group->isOcclusionState(LLSpatialGroup::OCCLUDED))
- {
- group->rebuildGeom();
- }
- }
- LL_PUSH_CALLSTACKS();
- //rebuild groups
- sCull->assertDrawMapsEmpty();
+ for (LLSpatialGroup::draw_map_t::iterator j = group->mDrawMap.begin(); j != group->mDrawMap.end(); ++j)
+ {
+ LLSpatialGroup::drawmap_elem_t &src_vec = j->second;
+ if (!hasRenderType(j->first))
+ {
+ continue;
+ }
- rebuildPriorityGroups();
- LL_PUSH_CALLSTACKS();
+ for (LLSpatialGroup::drawmap_elem_t::iterator k = src_vec.begin(); k != src_vec.end(); ++k)
+ {
+ LLDrawInfo *info = *k;
-
- //build render map
- for (LLCullResult::sg_iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i)
- {
- LLSpatialGroup* group = *i;
- if ((sUseOcclusion &&
- group->isOcclusionState(LLSpatialGroup::OCCLUDED)) ||
- (RenderAutoHideSurfaceAreaLimit > 0.f &&
- group->mSurfaceArea > RenderAutoHideSurfaceAreaLimit*llmax(group->mObjectBoxSize, 10.f)))
- {
- continue;
- }
+ sCull->pushDrawInfo(j->first, info);
+ if (!sShadowRender && !sReflectionRender && !gCubeSnapshot)
+ {
+ addTrianglesDrawn(info->mCount);
+ }
+ }
+ }
- if (group->hasState(LLSpatialGroup::NEW_DRAWINFO) && group->hasState(LLSpatialGroup::GEOM_DIRTY))
- { //no way this group is going to be drawable without a rebuild
- group->rebuildGeom();
- }
+ if (hasRenderType(LLPipeline::RENDER_TYPE_PASS_ALPHA))
+ {
+ LLSpatialGroup::draw_map_t::iterator alpha = group->mDrawMap.find(LLRenderPass::PASS_ALPHA);
- for (LLSpatialGroup::draw_map_t::iterator j = group->mDrawMap.begin(); j != group->mDrawMap.end(); ++j)
- {
- LLSpatialGroup::drawmap_elem_t& src_vec = j->second;
- if (!hasRenderType(j->first))
- {
- continue;
- }
-
- for (LLSpatialGroup::drawmap_elem_t::iterator k = src_vec.begin(); k != src_vec.end(); ++k)
- {
- LLDrawInfo* info = *k;
-
- sCull->pushDrawInfo(j->first, info);
- if (!sShadowRender && !sReflectionRender)
+ if (alpha != group->mDrawMap.end())
+ { // store alpha groups for sorting
+ LLSpatialBridge *bridge = group->getSpatialPartition()->asBridge();
+ if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD && !gCubeSnapshot)
{
- touchTextures(info);
- addTrianglesDrawn(info->mCount, info->mDrawMode);
+ if (bridge)
+ {
+ LLCamera trans_camera = bridge->transformCamera(camera);
+ group->updateDistance(trans_camera);
+ }
+ else
+ {
+ group->updateDistance(camera);
+ }
}
- }
- }
- if (hasRenderType(LLPipeline::RENDER_TYPE_PASS_ALPHA))
- {
- LLSpatialGroup::draw_map_t::iterator alpha = group->mDrawMap.find(LLRenderPass::PASS_ALPHA);
-
- if (alpha != group->mDrawMap.end())
- { //store alpha groups for sorting
- LLSpatialBridge* bridge = group->getSpatialPartition()->asBridge();
- if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
- {
- if (bridge)
- {
- LLCamera trans_camera = bridge->transformCamera(camera);
- group->updateDistance(trans_camera);
- }
- else
- {
- group->updateDistance(camera);
- }
- }
-
- if (hasRenderType(LLDrawPool::POOL_ALPHA))
- {
- sCull->pushAlphaGroup(group);
- }
- }
+ if (hasRenderType(LLDrawPool::POOL_ALPHA))
+ {
+ sCull->pushAlphaGroup(group);
+ }
+ }
LLSpatialGroup::draw_map_t::iterator rigged_alpha = group->mDrawMap.find(LLRenderPass::PASS_ALPHA_RIGGED);
if (rigged_alpha != group->mDrawMap.end())
- { //store rigged alpha groups for LLDrawPoolAlpha prepass (skip distance update, rigged attachments use depth buffer)
+ { // store rigged alpha groups for LLDrawPoolAlpha prepass (skip distance update, rigged attachments use depth buffer)
if (hasRenderType(LLDrawPool::POOL_ALPHA))
{
sCull->pushRiggedAlphaGroup(group);
}
}
- }
- }
-
- //flush particle VB
- if (LLVOPartGroup::sVB)
- {
- LLVOPartGroup::sVB->flush();
- }
- else
- {
- LL_WARNS_ONCE() << "Missing particle buffer" << LL_ENDL;
- }
+ }
+ }
- /*bool use_transform_feedback = gTransformPositionProgram.mProgramObject && !mMeshDirtyGroup.empty();
+ /*bool use_transform_feedback = gTransformPositionProgram.mProgramObject && !mMeshDirtyGroup.empty();
- if (use_transform_feedback)
- { //place a query around potential transform feedback code for synchronization
- mTransformFeedbackPrimitives = 0;
+ if (use_transform_feedback)
+ { //place a query around potential transform feedback code for synchronization
+ mTransformFeedbackPrimitives = 0;
- if (!mMeshDirtyQueryObject)
- {
- glGenQueriesARB(1, &mMeshDirtyQueryObject);
- }
+ if (!mMeshDirtyQueryObject)
+ {
+ glGenQueries(1, &mMeshDirtyQueryObject);
+ }
-
- glBeginQueryARB(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, mMeshDirtyQueryObject);
- }*/
- //pack vertex buffers for groups that chose to delay their updates
- for (LLSpatialGroup::sg_vector_t::iterator iter = mMeshDirtyGroup.begin(); iter != mMeshDirtyGroup.end(); ++iter)
- {
- (*iter)->rebuildMesh();
- }
+ glBeginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, mMeshDirtyQueryObject);
+ }*/
- /*if (use_transform_feedback)
- {
- glEndQueryARB(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
- }*/
-
- mMeshDirtyGroup.clear();
+ // pack vertex buffers for groups that chose to delay their updates
+ {
+ LL_PROFILE_GPU_ZONE("rebuildMesh");
+ for (LLSpatialGroup::sg_vector_t::iterator iter = mMeshDirtyGroup.begin(); iter != mMeshDirtyGroup.end(); ++iter)
+ {
+ (*iter)->rebuildMesh();
+ }
+ }
- if (!sShadowRender)
- {
+ /*if (use_transform_feedback)
+ {
+ glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
+ }*/
+
+ mMeshDirtyGroup.clear();
+
+ if (!sShadowRender)
+ {
// order alpha groups by distance
- std::sort(sCull->beginAlphaGroups(), sCull->endAlphaGroups(), LLSpatialGroup::CompareDepthGreater());
+ std::sort(sCull->beginAlphaGroups(), sCull->endAlphaGroups(), LLSpatialGroup::CompareDepthGreater());
// order rigged alpha groups by avatar attachment order
std::sort(sCull->beginRiggedAlphaGroups(), sCull->endRiggedAlphaGroups(), LLSpatialGroup::CompareRenderOrder());
- }
+ }
- LL_PUSH_CALLSTACKS();
- // only render if the flag is set. The flag is only set if we are in edit mode or the toggle is set in the menus
- if (LLFloaterReg::instanceVisible("beacons") && !sShadowRender)
- {
- if (sRenderScriptedTouchBeacons)
- {
- // Only show the beacon on the root object.
- forAllVisibleDrawables(renderScriptedTouchBeacons);
- }
- else
- if (sRenderScriptedBeacons)
- {
- // Only show the beacon on the root object.
- forAllVisibleDrawables(renderScriptedBeacons);
- }
+ LL_PUSH_CALLSTACKS();
+ // only render if the flag is set. The flag is only set if we are in edit mode or the toggle is set in the menus
+ if (LLFloaterReg::instanceVisible("beacons") && !sShadowRender && !gCubeSnapshot)
+ {
+ if (sRenderScriptedTouchBeacons)
+ {
+ // Only show the beacon on the root object.
+ forAllVisibleDrawables(renderScriptedTouchBeacons);
+ }
+ else if (sRenderScriptedBeacons)
+ {
+ // Only show the beacon on the root object.
+ forAllVisibleDrawables(renderScriptedBeacons);
+ }
- if (sRenderPhysicalBeacons)
- {
- // Only show the beacon on the root object.
- forAllVisibleDrawables(renderPhysicalBeacons);
- }
+ if (sRenderPhysicalBeacons)
+ {
+ // Only show the beacon on the root object.
+ forAllVisibleDrawables(renderPhysicalBeacons);
+ }
- if(sRenderMOAPBeacons)
- {
- forAllVisibleDrawables(renderMOAPBeacons);
- }
+ if (sRenderMOAPBeacons)
+ {
+ forAllVisibleDrawables(renderMOAPBeacons);
+ }
- if (sRenderParticleBeacons)
- {
- forAllVisibleDrawables(renderParticleBeacons);
- }
+ if (sRenderParticleBeacons)
+ {
+ forAllVisibleDrawables(renderParticleBeacons);
+ }
- // If god mode, also show audio cues
- if (sRenderSoundBeacons && gAudiop)
- {
- // Walk all sound sources and render out beacons for them. Note, this isn't done in the ForAllVisibleDrawables function, because some are not visible.
- LLAudioEngine::source_map::iterator iter;
- for (iter = gAudiop->mAllSources.begin(); iter != gAudiop->mAllSources.end(); ++iter)
- {
- LLAudioSource *sourcep = iter->second;
+ // If god mode, also show audio cues
+ if (sRenderSoundBeacons && gAudiop)
+ {
+ // Walk all sound sources and render out beacons for them. Note, this isn't done in the ForAllVisibleDrawables function, because
+ // some are not visible.
+ LLAudioEngine::source_map::iterator iter;
+ for (iter = gAudiop->mAllSources.begin(); iter != gAudiop->mAllSources.end(); ++iter)
+ {
+ LLAudioSource *sourcep = iter->second;
- LLVector3d pos_global = sourcep->getPositionGlobal();
- LLVector3 pos = gAgent.getPosAgentFromGlobal(pos_global);
- if (gPipeline.sRenderBeacons)
- {
- //pos += LLVector3(0.f, 0.f, 0.2f);
- gObjectList.addDebugBeacon(pos, "", LLColor4(1.f, 1.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), DebugBeaconLineWidth);
- }
- }
- // now deal with highlights for all those seeable sound sources
- forAllVisibleDrawables(renderSoundHighlights);
- }
- }
- LL_PUSH_CALLSTACKS();
- // If managing your telehub, draw beacons at telehub and currently selected spawnpoint.
- if (LLFloaterTelehub::renderBeacons() && !sShadowRender)
- {
- LLFloaterTelehub::addBeacons();
- }
+ LLVector3d pos_global = sourcep->getPositionGlobal();
+ LLVector3 pos = gAgent.getPosAgentFromGlobal(pos_global);
+ if (gPipeline.sRenderBeacons)
+ {
+ // pos += LLVector3(0.f, 0.f, 0.2f);
+ gObjectList.addDebugBeacon(pos, "", LLColor4(1.f, 1.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), DebugBeaconLineWidth);
+ }
+ }
+ // now deal with highlights for all those seeable sound sources
+ forAllVisibleDrawables(renderSoundHighlights);
+ }
+ }
+ LL_PUSH_CALLSTACKS();
+ // If managing your telehub, draw beacons at telehub and currently selected spawnpoint.
+ if (LLFloaterTelehub::renderBeacons() && !sShadowRender && !gCubeSnapshot)
+ {
+ LLFloaterTelehub::addBeacons();
+ }
- if (!sShadowRender)
- {
- mSelectedFaces.clear();
+ if (!sShadowRender && !gCubeSnapshot)
+ {
+ mSelectedFaces.clear();
- if (!gNonInteractive)
- {
- LLPipeline::setRenderHighlightTextureChannel(gFloaterTools->getPanelFace()->getTextureChannelToEdit());
- }
+ if (!gNonInteractive)
+ {
+ LLPipeline::setRenderHighlightTextureChannel(gFloaterTools->getPanelFace()->getTextureChannelToEdit());
+ }
- // Draw face highlights for selected faces.
- if (LLSelectMgr::getInstance()->getTEMode())
- {
- struct f : public LLSelectedTEFunctor
- {
- virtual bool apply(LLViewerObject* object, S32 te)
- {
- if (object->mDrawable)
- {
- LLFace * facep = object->mDrawable->getFace(te);
- if (facep)
- {
- gPipeline.mSelectedFaces.push_back(facep);
- }
- }
- return true;
- }
- } func;
- LLSelectMgr::getInstance()->getSelection()->applyToTEs(&func);
- }
- }
+ // Draw face highlights for selected faces.
+ if (LLSelectMgr::getInstance()->getTEMode())
+ {
+ struct f : public LLSelectedTEFunctor
+ {
+ virtual bool apply(LLViewerObject *object, S32 te)
+ {
+ if (object->mDrawable)
+ {
+ LLFace *facep = object->mDrawable->getFace(te);
+ if (facep)
+ {
+ gPipeline.mSelectedFaces.push_back(facep);
+ }
+ }
+ return true;
+ }
+ } func;
+ LLSelectMgr::getInstance()->getSelection()->applyToTEs(&func);
+ }
+ }
- //LLSpatialGroup::sNoDelete = FALSE;
- LL_PUSH_CALLSTACKS();
+ // LLSpatialGroup::sNoDelete = FALSE;
+ LL_PUSH_CALLSTACKS();
}
@@ -4000,22 +3844,20 @@ void render_hud_elements()
LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; //LL_RECORD_BLOCK_TIME(FTM_RENDER_UI);
gPipeline.disableLights();
- LLGLDisable fog(GL_FOG);
LLGLSUIDefault gls_ui;
- LLGLEnable stencil(GL_STENCIL_TEST);
- glStencilFunc(GL_ALWAYS, 255, 0xFFFFFFFF);
- glStencilMask(0xFFFFFFFF);
- glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
-
- gGL.color4f(1,1,1,1);
+ //LLGLEnable stencil(GL_STENCIL_TEST);
+ //glStencilFunc(GL_ALWAYS, 255, 0xFFFFFFFF);
+ //glStencilMask(0xFFFFFFFF);
+ //glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
gUIProgram.bind();
+ gGL.color4f(1, 1, 1, 1);
LLGLDepthTest depth(GL_TRUE, GL_FALSE);
if (!LLPipeline::sReflectionRender && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
{
- LLGLEnable multisample(LLPipeline::RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
+ LLGLEnable multisample(LLPipeline::RenderFSAASamples > 0 ? GL_MULTISAMPLE : 0);
gViewerWindow->renderSelections(FALSE, FALSE, FALSE); // For HUD version in render_ui_3d()
// Draw the tracking overlays
@@ -4028,9 +3870,6 @@ void render_hud_elements()
}
LLViewerParcelMgr::getInstance()->render();
LLViewerParcelMgr::getInstance()->renderParcelCollision();
-
- // Render name tags.
- LLHUDObject::renderAll();
}
else if (gForceRenderLandFence)
{
@@ -4043,7 +3882,6 @@ void render_hud_elements()
}
gUIProgram.unbind();
- gGL.flush();
}
void LLPipeline::renderHighlights()
@@ -4057,106 +3895,6 @@ void LLPipeline::renderHighlights()
LLGLEnable color_mat(GL_COLOR_MATERIAL);
disableLights();
- if (!hasRenderType(LLPipeline::RENDER_TYPE_HUD) && !mHighlightSet.empty())
- { //draw blurry highlight image over screen
- LLGLEnable blend(GL_BLEND);
- LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
- LLGLDisable test(GL_ALPHA_TEST);
-
- LLGLEnable stencil(GL_STENCIL_TEST);
- gGL.flush();
- glStencilMask(0xFFFFFFFF);
- glClearStencil(1);
- glClear(GL_STENCIL_BUFFER_BIT);
-
- glStencilFunc(GL_ALWAYS, 0, 0xFFFFFFFF);
- glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
-
- gGL.setColorMask(false, false);
-
- gHighlightProgram.bind();
-
- for (std::set<HighlightItem>::iterator iter = mHighlightSet.begin(); iter != mHighlightSet.end(); ++iter)
- {
- renderHighlight(iter->mItem->getVObj(), 1.f);
- }
- gGL.setColorMask(true, false);
-
- glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
- glStencilFunc(GL_NOTEQUAL, 0, 0xFFFFFFFF);
-
- //gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA);
-
- gGL.pushMatrix();
- gGL.loadIdentity();
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.pushMatrix();
- gGL.loadIdentity();
-
- gGL.getTexUnit(0)->bind(&mHighlight);
-
- LLVector2 tc1;
- LLVector2 tc2;
-
- tc1.setVec(0,0);
- tc2.setVec(2,2);
-
- gGL.begin(LLRender::TRIANGLES);
-
- F32 scale = RenderHighlightBrightness;
- LLColor4 color = RenderHighlightColor;
- F32 thickness = RenderHighlightThickness;
-
- for (S32 pass = 0; pass < 2; ++pass)
- {
- if (pass == 0)
- {
- gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA);
- }
- else
- {
- gGL.setSceneBlendType(LLRender::BT_ALPHA);
- }
-
- for (S32 i = 0; i < 8; ++i)
- {
- for (S32 j = 0; j < 8; ++j)
- {
- LLVector2 tc(i-4+0.5f, j-4+0.5f);
-
- F32 dist = 1.f-(tc.length()/sqrtf(32.f));
- dist *= scale/64.f;
-
- tc *= thickness;
- tc.mV[0] = (tc.mV[0])/mHighlight.getWidth();
- tc.mV[1] = (tc.mV[1])/mHighlight.getHeight();
-
- gGL.color4f(color.mV[0],
- color.mV[1],
- color.mV[2],
- color.mV[3]*dist);
-
- gGL.texCoord2f(tc.mV[0]+tc1.mV[0], tc.mV[1]+tc2.mV[1]);
- gGL.vertex2f(-1,3);
-
- gGL.texCoord2f(tc.mV[0]+tc1.mV[0], tc.mV[1]+tc1.mV[1]);
- gGL.vertex2f(-1,-1);
-
- gGL.texCoord2f(tc.mV[0]+tc2.mV[0], tc.mV[1]+tc1.mV[1]);
- gGL.vertex2f(3,-1);
- }
- }
- }
-
- gGL.end();
-
- gGL.popMatrix();
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.popMatrix();
-
- //gGL.setSceneBlendType(LLRender::BT_ALPHA);
- }
-
if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0))
{
gHighlightProgram.bind();
@@ -4274,268 +4012,42 @@ void LLPipeline::renderHighlights()
//debug use
U32 LLPipeline::sCurRenderPoolType = 0 ;
-void LLPipeline::renderGeom(LLCamera& camera, bool forceVBOUpdate)
+void LLPipeline::renderGeomDeferred(LLCamera& camera, bool do_occlusion)
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; //LL_RECORD_BLOCK_TIME(FTM_RENDER_GEOMETRY);
-
- assertInitialized();
-
- F32 saved_modelview[16];
- F32 saved_projection[16];
-
- //HACK: preserve/restore matrices around HUD render
- if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
- {
- for (U32 i = 0; i < 16; i++)
- {
- saved_modelview[i] = gGLModelView[i];
- saved_projection[i] = gGLProjection[i];
- }
- }
-
- ///////////////////////////////////////////
- //
- // Sync and verify GL state
- //
- //
-
- stop_glerror();
-
- LLVertexBuffer::unbind();
-
- // Do verification of GL state
- LLGLState::checkStates();
- LLGLState::checkTextureChannels();
- if (mRenderDebugMask & RENDER_DEBUG_VERIFY)
- {
- if (!verify())
- {
- LL_ERRS() << "Pipeline verification failed!" << LL_ENDL;
- }
- }
-
- LLAppViewer::instance()->pingMainloopTimeout("Pipeline:ForceVBO");
-
- // Initialize lots of GL state to "safe" values
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- gGL.matrixMode(LLRender::MM_TEXTURE);
- gGL.loadIdentity();
- gGL.matrixMode(LLRender::MM_MODELVIEW);
-
- LLGLSPipeline gls_pipeline;
- LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
-
- LLGLState gls_color_material(GL_COLOR_MATERIAL, mLightingDetail < 2);
-
- // Toggle backface culling for debugging
- LLGLEnable cull_face(mBackfaceCull ? GL_CULL_FACE : 0);
- // Set fog
- bool use_fog = hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FOG);
- LLGLEnable fog_enable(use_fog &&
- !gPipeline.canUseWindLightShadersOnObjects() ? GL_FOG : 0);
- gSky.updateFog(camera.getFar());
- if (!use_fog)
- {
- sUnderWaterRender = false;
- }
-
- gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sDefaultImagep);
- LLViewerFetchedTexture::sDefaultImagep->setAddressMode(LLTexUnit::TAM_WRAP);
-
-
- //////////////////////////////////////////////
- //
- // Actually render all of the geometry
- //
- //
- stop_glerror();
-
- LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDrawPools");
-
- for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
- {
- LLDrawPool *poolp = *iter;
- if (hasRenderType(poolp->getType()))
- {
- poolp->prerender();
- }
- }
-
- {
- LL_PROFILE_ZONE_NAMED_CATEGORY_DRAWPOOL("pools"); //LL_RECORD_BLOCK_TIME(FTM_POOLS);
-
- // HACK: don't calculate local lights if we're rendering the HUD!
- // Removing this check will cause bad flickering when there are
- // HUD elements being rendered AND the user is in flycam mode -nyx
- if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
- {
- calcNearbyLights(camera);
- setupHWLights(NULL);
- }
-
- bool occlude = sUseOcclusion > 1;
- U32 cur_type = 0;
-
- pool_set_t::iterator iter1 = mPools.begin();
- while ( iter1 != mPools.end() )
- {
- LLDrawPool *poolp = *iter1;
-
- cur_type = poolp->getType();
-
- //debug use
- sCurRenderPoolType = cur_type ;
-
- if (occlude && cur_type >= LLDrawPool::POOL_GRASS)
- {
- occlude = false;
- gGLLastMatrix = NULL;
- gGL.loadMatrix(gGLModelView);
- LLGLSLShader::bindNoShader();
- doOcclusion(camera);
- }
-
- pool_set_t::iterator iter2 = iter1;
- if (hasRenderType(poolp->getType()) && poolp->getNumPasses() > 0)
- {
- LL_PROFILE_ZONE_NAMED_CATEGORY_DRAWPOOL("pool render"); //LL_RECORD_BLOCK_TIME(FTM_POOLRENDER);
-
- gGLLastMatrix = NULL;
- gGL.loadMatrix(gGLModelView);
-
- for( S32 i = 0; i < poolp->getNumPasses(); i++ )
- {
- LLVertexBuffer::unbind();
- poolp->beginRenderPass(i);
- for (iter2 = iter1; iter2 != mPools.end(); iter2++)
- {
- LLDrawPool *p = *iter2;
- if (p->getType() != cur_type)
- {
- break;
- }
-
- if ( !p->getSkipRenderFlag() ) { p->render(i); }
- }
- poolp->endRenderPass(i);
- LLVertexBuffer::unbind();
- if (gDebugGL)
- {
- std::string msg = llformat("pass %d", i);
- LLGLState::checkStates(msg);
- //LLGLState::checkTextureChannels(msg);
- //LLGLState::checkClientArrays(msg);
- }
- }
- }
- else
- {
- // Skip all pools of this type
- for (iter2 = iter1; iter2 != mPools.end(); iter2++)
- {
- LLDrawPool *p = *iter2;
- if (p->getType() != cur_type)
- {
- break;
- }
- }
- }
- iter1 = iter2;
- stop_glerror();
- }
-
- LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDrawPoolsEnd");
-
- LLVertexBuffer::unbind();
-
- gGLLastMatrix = NULL;
- gGL.loadMatrix(gGLModelView);
-
- if (occlude)
- {
- occlude = false;
- gGLLastMatrix = NULL;
- gGL.loadMatrix(gGLModelView);
- LLGLSLShader::bindNoShader();
- doOcclusion(camera);
- }
- }
-
- LLVertexBuffer::unbind();
- LLGLState::checkStates();
-
- if (!LLPipeline::sImpostorRender)
- {
- LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderHighlights");
-
- if (!sReflectionRender)
- {
- renderHighlights();
- }
+ LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderGeomDeferred");
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; //LL_RECORD_BLOCK_TIME(FTM_RENDER_GEOMETRY);
+ LL_PROFILE_GPU_ZONE("renderGeomDeferred");
- // Contains a list of the faces of objects that are physical or
- // have touch-handlers.
- mHighlightFaces.clear();
+ if (gUseWireframe)
+ {
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ }
- LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDebug");
-
- renderDebug();
+ 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);
- LLVertexBuffer::unbind();
-
- if (!LLPipeline::sReflectionRender && !LLPipeline::sRenderDeferred)
- {
- if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
- {
- // Render debugging beacons.
- gObjectList.renderObjectBeacons();
- gObjectList.resetObjectBeacons();
- gSky.addSunMoonBeacons();
- }
- else
- {
- // Make sure particle effects disappear
- LLHUDObject::renderAllForTimer();
- }
- }
- else
- {
- // Make sure particle effects disappear
- LLHUDObject::renderAllForTimer();
- }
-
- LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderGeomEnd");
+ // 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
- //HACK: preserve/restore matrices around HUD render
- if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
- {
- for (U32 i = 0; i < 16; i++)
- {
- gGLModelView[i] = saved_modelview[i];
- gGLProjection[i] = saved_projection[i];
- }
- }
- }
+ glh::matrix4f n = m.inverse();
- LLVertexBuffer::unbind();
+ for (U32 i = 0; i < 16; ++i)
+ {
+ gGLDeltaModelView[i] = m.m[i];
+ gGLInverseDeltaModelView[i] = n.m[i];
+ }
+ }
- LLGLState::checkStates();
-// LLGLState::checkTextureChannels();
-// LLGLState::checkClientArrays();
-}
+ bool occlude = LLPipeline::sUseOcclusion > 1 && do_occlusion;
-void LLPipeline::renderGeomDeferred(LLCamera& camera)
-{
- LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderGeomDeferred");
+ setupHWLights(nullptr);
- LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; //LL_RECORD_BLOCK_TIME(FTM_RENDER_GEOMETRY);
{
- // SL-15709 -- NOTE: Tracy only allows one ZoneScoped per function.
- // Solutions are:
- // 1. Use a new scope
- // 2. Use named zones
- // 3. Use transient zones
- 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);
@@ -4548,12 +4060,17 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera)
}
}
- LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
+ LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE : 0);
LLVertexBuffer::unbind();
LLGLState::checkStates();
- LLGLState::checkTextureChannels();
+
+ if (LLViewerShaderMgr::instance()->mShaderLevel[LLViewerShaderMgr::SHADER_DEFERRED] > 1)
+ {
+ //update reflection probe uniform
+ mReflectionMapManager.updateUniforms();
+ }
U32 cur_type = 0;
@@ -4567,10 +4084,19 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera)
cur_type = poolp->getType();
+ if (occlude && cur_type >= LLDrawPool::POOL_GRASS)
+ {
+ llassert(!gCubeSnapshot); // never do occlusion culling on cube snapshots
+ occlude = false;
+ gGLLastMatrix = NULL;
+ gGL.loadMatrix(gGLModelView);
+ doOcclusion(camera);
+ }
+
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);
@@ -4621,24 +4147,41 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera)
gGL.setColorMask(true, false);
} // Tracy ZoneScoped
+
+ if (gUseWireframe)
+ {
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ }
}
-void LLPipeline::renderGeomPostDeferred(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)
+ {
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ }
+
U32 cur_type = 0;
LLGLEnable cull(GL_CULL_FACE);
- LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
+ LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE : 0);
calcNearbyLights(camera);
setupHWLights(NULL);
+ gGL.setSceneBlendType(LLRender::BT_ALPHA);
gGL.setColorMask(true, false);
pool_set_t::iterator iter1 = mPools.begin();
- bool occlude = LLPipeline::sUseOcclusion > 1 && do_occlusion;
+
+ if (gDebugGL || gDebugPipeline)
+ {
+ LLGLState::checkStates(GL_FALSE);
+ }
while ( iter1 != mPools.end() )
{
@@ -4646,20 +4189,10 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera, bool do_occlusion)
cur_type = poolp->getType();
- if (occlude && cur_type >= LLDrawPool::POOL_GRASS)
- {
- occlude = false;
- gGLLastMatrix = NULL;
- gGL.loadMatrix(gGLModelView);
- LLGLSLShader::bindNoShader();
- doOcclusion(camera, mScreen, mOcclusionDepth, &mDeferredDepth);
- gGL.setColorMask(true, false);
- }
-
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);
@@ -4683,7 +4216,7 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera, bool do_occlusion)
if (gDebugGL || gDebugPipeline)
{
- LLGLState::checkStates();
+ LLGLState::checkStates(GL_FALSE);
}
}
}
@@ -4707,20 +4240,25 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera, bool do_occlusion)
gGL.matrixMode(LLRender::MM_MODELVIEW);
gGL.loadMatrix(gGLModelView);
- if (occlude)
- {
- occlude = false;
- LLGLSLShader::bindNoShader();
- doOcclusion(camera);
- gGLLastMatrix = NULL;
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.loadMatrix(gGLModelView);
- }
+ if (!gCubeSnapshot)
+ {
+ // debug displays
+ renderHighlights();
+ mHighlightFaces.clear();
+
+ renderDebug();
+ }
+
+ if (gUseWireframe)
+ {
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ }
}
void LLPipeline::renderGeomShadow(LLCamera& camera)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
+ LL_PROFILE_GPU_ZONE("renderGeomShadow");
U32 cur_type = 0;
LLGLEnable cull(GL_CULL_FACE);
@@ -4759,8 +4297,6 @@ void LLPipeline::renderGeomShadow(LLCamera& camera)
}
poolp->endShadowPass(i);
LLVertexBuffer::unbind();
-
- LLGLState::checkStates();
}
}
else
@@ -4784,28 +4320,19 @@ void LLPipeline::renderGeomShadow(LLCamera& camera)
}
-void LLPipeline::addTrianglesDrawn(S32 index_count, U32 render_type)
-{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
- assertInitialized();
- S32 count = 0;
- if (render_type == LLRender::TRIANGLE_STRIP)
- {
- count = index_count-2;
- }
- else
- {
- count = index_count/3;
- }
+static U32 sIndicesDrawnCount = 0;
- record(sStatBatchSize, count);
- add(LLStatViewer::TRIANGLES_DRAWN, LLUnits::Triangles::fromValue(count));
+void LLPipeline::addTrianglesDrawn(S32 index_count)
+{
+ sIndicesDrawnCount += index_count;
+}
- if (LLPipeline::sRenderFrameTest)
- {
- gViewerWindow->getWindow()->swapBuffers();
- ms_sleep(16);
- }
+void LLPipeline::recordTrianglesDrawn()
+{
+ assertInitialized();
+ U32 count = sIndicesDrawnCount / 3;
+ sIndicesDrawnCount = 0;
+ add(LLStatViewer::TRIANGLES_DRAWN, LLUnits::Triangles::fromValue(count));
}
void LLPipeline::renderPhysicsDisplay()
@@ -4815,40 +4342,56 @@ void LLPipeline::renderPhysicsDisplay()
return;
}
- allocatePhysicsBuffer();
+ gGL.flush();
+ gDebugProgram.bind();
- gGL.flush();
- mPhysicsDisplay.bindTarget();
- glClearColor(0,0,0,1);
- gGL.setColorMask(true, true);
- mPhysicsDisplay.clear();
- glClearColor(0,0,0,0);
+ LLGLEnable(GL_POLYGON_OFFSET_LINE);
+ glPolygonOffset(3.f, 3.f);
+ glLineWidth(3.f);
+ LLGLEnable blend(GL_BLEND);
+ gGL.setSceneBlendType(LLRender::BT_ALPHA);
- gGL.setColorMask(true, false);
+ for (int pass = 0; pass < 3; ++pass)
+ {
+ // pass 0 - depth write enabled, color write disabled, fill
+ // pass 1 - depth write disabled, color write enabled, fill
+ // pass 2 - depth write disabled, color write enabled, wireframe
+ gGL.setColorMask(pass >= 1, false);
+ LLGLDepthTest depth(GL_TRUE, pass == 0);
- gDebugProgram.bind();
+ bool wireframe = (pass == 2);
- for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
- iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
- {
- LLViewerRegion* region = *iter;
- for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
- {
- LLSpatialPartition* part = region->getSpatialPartition(i);
- if (part)
- {
- if (hasRenderType(part->mDrawableType))
- {
- part->renderPhysicsShapes();
- }
- }
- }
- }
+ if (wireframe)
+ {
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ }
- gGL.flush();
+ for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
+ iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+ {
+ LLViewerRegion* region = *iter;
+ for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
+ {
+ LLSpatialPartition* part = region->getSpatialPartition(i);
+ if (part)
+ {
+ if (hasRenderType(part->mDrawableType))
+ {
+ part->renderPhysicsShapes(wireframe);
+ }
+ }
+ }
+ }
+ gGL.flush();
+ if (wireframe)
+ {
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ }
+ }
+ glLineWidth(1.f);
gDebugProgram.unbind();
- mPhysicsDisplay.flush();
+
}
extern std::set<LLSpatialGroup*> visible_selected_groups;
@@ -4920,7 +4463,7 @@ void LLPipeline::renderDebug()
const LLColor4 clearColor = gSavedSettings.getColor4("PathfindingNavMeshClear");
gGL.setColorMask(true, true);
glClearColor(clearColor.mV[0],clearColor.mV[1],clearColor.mV[2],0);
- glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+ glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); // no stencil -- deprecated | GL_STENCIL_BUFFER_BIT);
gGL.setColorMask(true, false);
glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
}
@@ -5134,8 +4677,6 @@ void LLPipeline::renderDebug()
}
}
- gGL.color4f(1,1,1,1);
-
gGLLastMatrix = NULL;
gGL.loadMatrix(gGLModelView);
gGL.setColorMask(true, false);
@@ -5144,6 +4685,7 @@ void LLPipeline::renderDebug()
if (!hud_only && !mDebugBlips.empty())
{ //render debug blips
gUIProgram.bind();
+ gGL.color4f(1, 1, 1, 1);
gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep, true);
@@ -5175,7 +4717,6 @@ void LLPipeline::renderDebug()
glPointSize(1.f);
}
-
// Debug stuff.
for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
@@ -5229,6 +4770,30 @@ void LLPipeline::renderDebug()
visible_selected_groups.clear();
+ //draw reflection probes and links between them
+ if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_REFLECTION_PROBES) && !hud_only)
+ {
+ mReflectionMapManager.renderDebug();
+ }
+
+ if (gSavedSettings.getBOOL("RenderReflectionProbeVolumes"))
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("probe debug display");
+
+ bindDeferredShader(gReflectionProbeDisplayProgram, NULL);
+ mScreenTriangleVB->setBuffer();
+
+ // Provide our projection matrix.
+ set_camera_projection_matrix(gReflectionProbeDisplayProgram);
+
+ LLGLEnable blend(GL_BLEND);
+ LLGLDepthTest depth(GL_FALSE);
+
+ mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+
+ unbindDeferredShader(gReflectionProbeDisplayProgram);
+ }
+
gUIProgram.bind();
if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST) && !hud_only)
@@ -5653,17 +5218,28 @@ void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp )
mMaterialsPool = new_poolp;
}
break;
- case LLDrawPool::POOL_ALPHA:
- if( mAlphaPool )
+ case LLDrawPool::POOL_ALPHA_PRE_WATER:
+ if( mAlphaPoolPreWater )
{
llassert(0);
- LL_WARNS() << "LLPipeline::addPool(): Ignoring duplicate Alpha pool" << LL_ENDL;
+ LL_WARNS() << "LLPipeline::addPool(): Ignoring duplicate Alpha pre-water pool" << LL_ENDL;
}
else
{
- mAlphaPool = (LLDrawPoolAlpha*) new_poolp;
+ mAlphaPoolPreWater = (LLDrawPoolAlpha*) new_poolp;
}
break;
+ case LLDrawPool::POOL_ALPHA_POST_WATER:
+ if (mAlphaPoolPostWater)
+ {
+ llassert(0);
+ LL_WARNS() << "LLPipeline::addPool(): Ignoring duplicate Alpha post-water pool" << LL_ENDL;
+ }
+ else
+ {
+ mAlphaPoolPostWater = (LLDrawPoolAlpha*)new_poolp;
+ }
+ break;
case LLDrawPool::POOL_AVATAR:
case LLDrawPool::POOL_CONTROL_AV:
@@ -5717,6 +5293,18 @@ void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp )
}
break;
+ case LLDrawPool::POOL_GLTF_PBR:
+ if( mPBROpaquePool )
+ {
+ llassert(0);
+ LL_WARNS() << "LLPipeline::addPool(): Ignoring duplicate PBR Opaque Pool" << LL_ENDL;
+ }
+ else
+ {
+ mPBROpaquePool = new_poolp;
+ }
+ break;
+
default:
llassert(0);
LL_WARNS() << "Invalid Pool Type in LLPipeline::addPool()" << LL_ENDL;
@@ -5809,10 +5397,15 @@ void LLPipeline::removeFromQuickLookup( LLDrawPool* poolp )
mMaterialsPool = NULL;
break;
- case LLDrawPool::POOL_ALPHA:
- llassert( poolp == mAlphaPool );
- mAlphaPool = NULL;
+ case LLDrawPool::POOL_ALPHA_PRE_WATER:
+ llassert( poolp == mAlphaPoolPreWater );
+ mAlphaPoolPreWater = nullptr;
break;
+
+ case LLDrawPool::POOL_ALPHA_POST_WATER:
+ llassert(poolp == mAlphaPoolPostWater);
+ mAlphaPoolPostWater = nullptr;
+ break;
case LLDrawPool::POOL_AVATAR:
case LLDrawPool::POOL_CONTROL_AV:
@@ -5833,6 +5426,11 @@ void LLPipeline::removeFromQuickLookup( LLDrawPool* poolp )
mGroundPool = NULL;
break;
+ case LLDrawPool::POOL_GLTF_PBR:
+ llassert( poolp == mPBROpaquePool );
+ mPBROpaquePool = NULL;
+ break;
+
default:
llassert(0);
LL_WARNS() << "Invalid Pool Type in LLPipeline::removeFromQuickLookup() type=" << poolp->getType() << LL_ENDL;
@@ -5949,6 +5547,7 @@ void LLPipeline::setupAvatarLights(bool for_edit)
static F32 calc_light_dist(LLVOVolume* light, const LLVector3& cam_pos, F32 max_dist)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
F32 inten = light->getLightIntensity();
if (inten < .001f)
{
@@ -5972,9 +5571,10 @@ static F32 calc_light_dist(LLVOVolume* light, const LLVector3& cam_pos, F32 max_
void LLPipeline::calcNearbyLights(LLCamera& camera)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
assertInitialized();
- if (LLPipeline::sReflectionRender)
+ if (LLPipeline::sReflectionRender || gCubeSnapshot)
{
return;
}
@@ -6066,7 +5666,7 @@ void LLPipeline::calcNearbyLights(LLCamera& camera)
// FIND NEW LIGHTS THAT ARE IN RANGE
light_set_t new_nearby_lights;
- for (LLDrawable::drawable_set_t::iterator iter = mLights.begin();
+ for (LLDrawable::ordered_drawable_set_t::iterator iter = mLights.begin();
iter != mLights.end(); ++iter)
{
LLDrawable* drawable = *iter;
@@ -6157,6 +5757,7 @@ void LLPipeline::calcNearbyLights(LLCamera& camera)
void LLPipeline::setupHWLights(LLDrawPool* pool)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
assertInitialized();
LLEnvironment& environment = LLEnvironment::instance();
@@ -6164,7 +5765,17 @@ void LLPipeline::setupHWLights(LLDrawPool* pool)
// Ambient
LLColor4 ambient = psky->getTotalAmbient();
- gGL.setAmbientLightColor(ambient);
+
+ static LLCachedControl<F32> 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();
bool moon_up = environment.getIsMoonUp();
@@ -6257,7 +5868,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;
@@ -6302,6 +5913,9 @@ void LLPipeline::setupHWLights(LLDrawPool* pool)
light_state->setDiffuse(light_color);
light_state->setAmbient(LLColor4::black);
light_state->setConstantAttenuation(0.f);
+ light_state->setSize(light->getLightRadius() * 1.5f);
+ light_state->setFalloff(light->getLightFalloff(DEFERRED_LIGHT_FALLOFF));
+
if (sRenderDeferred)
{
light_state->setLinearAttenuation(linatten);
@@ -6718,15 +6332,6 @@ void LLPipeline::toggleRenderType(U32 type)
//static
void LLPipeline::toggleRenderTypeControl(U32 type)
{
- U32 bit = (1<<type);
- if (gPipeline.hasRenderType(type))
- {
- LL_INFOS() << "Toggling render type mask " << std::hex << bit << " off" << std::dec << LL_ENDL;
- }
- else
- {
- LL_INFOS() << "Toggling render type mask " << std::hex << bit << " on" << std::dec << LL_ENDL;
- }
gPipeline.toggleRenderType(type);
}
@@ -6972,7 +6577,7 @@ LLVOPartGroup* LLPipeline::lineSegmentIntersectParticle(const LLVector4a& start,
LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_PARTICLE);
if (part && hasRenderType(part->mDrawableType))
{
- LLDrawable* hit = part->lineSegmentIntersect(start, local_end, TRUE, FALSE, face_hit, &position, NULL, NULL, NULL);
+ LLDrawable* hit = part->lineSegmentIntersect(start, local_end, TRUE, FALSE, TRUE, face_hit, &position, NULL, NULL, NULL);
if (hit)
{
drawable = hit;
@@ -7000,6 +6605,7 @@ LLVOPartGroup* LLPipeline::lineSegmentIntersectParticle(const LLVector4a& start,
LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector4a& start, const LLVector4a& end,
bool pick_transparent,
bool pick_rigged,
+ bool pick_unselectable,
S32* face_hit,
LLVector4a* intersection, // return the intersection point
LLVector2* tex_coord, // return the texture coordinates of the intersection point
@@ -7033,7 +6639,7 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector4a& start,
LLSpatialPartition* part = region->getSpatialPartition(j);
if (part && hasRenderType(part->mDrawableType))
{
- LLDrawable* hit = part->lineSegmentIntersect(start, local_end, pick_transparent, pick_rigged, face_hit, &position, tex_coord, normal, tangent);
+ LLDrawable* hit = part->lineSegmentIntersect(start, local_end, pick_transparent, pick_rigged, pick_unselectable, face_hit, &position, tex_coord, normal, tangent);
if (hit)
{
drawable = hit;
@@ -7090,7 +6696,7 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector4a& start,
LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_AVATAR);
if (part && hasRenderType(part->mDrawableType))
{
- LLDrawable* hit = part->lineSegmentIntersect(start, local_end, pick_transparent, pick_rigged, face_hit, &position, tex_coord, normal, tangent);
+ LLDrawable* hit = part->lineSegmentIntersect(start, local_end, pick_transparent, pick_rigged, pick_unselectable, face_hit, &position, tex_coord, normal, tangent);
if (hit)
{
LLVector4a delta;
@@ -7178,7 +6784,7 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInHUD(const LLVector4a& start, c
LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_HUD);
if (part)
{
- LLDrawable* hit = part->lineSegmentIntersect(start, end, pick_transparent, FALSE, face_hit, intersection, tex_coord, normal, tangent);
+ LLDrawable* hit = part->lineSegmentIntersect(start, end, pick_transparent, FALSE, TRUE, face_hit, intersection, tex_coord, normal, tangent);
if (hit)
{
drawable = hit;
@@ -7289,55 +6895,72 @@ void LLPipeline::doResetVertexBuffers(bool forced)
LLVOPartGroup::destroyGL();
gGL.resetVertexBuffer();
- SUBSYSTEM_CLEANUP(LLVertexBuffer);
-
- if (LLVertexBuffer::sGLCount != 0)
- {
- LL_WARNS() << "VBO wipe failed -- " << LLVertexBuffer::sGLCount << " buffers remaining." << LL_ENDL;
- }
-
- LLVertexBuffer::unbind();
+ LLVertexBuffer::unbind();
updateRenderBump();
- updateRenderDeferred();
-
- sUseTriStrips = gSavedSettings.getBOOL("RenderUseTriStrips");
- LLVertexBuffer::sUseStreamDraw = gSavedSettings.getBOOL("RenderUseStreamVBO");
- LLVertexBuffer::sUseVAO = gSavedSettings.getBOOL("RenderUseVAO");
- LLVertexBuffer::sPreferStreamDraw = gSavedSettings.getBOOL("RenderPreferStreamDraw");
- LLVertexBuffer::sEnableVBOs = gSavedSettings.getBOOL("RenderVBOEnable");
- LLVertexBuffer::sDisableVBOMapping = LLVertexBuffer::sEnableVBOs && gSavedSettings.getBOOL("RenderVBOMappingDisable") ;
+
sBakeSunlight = gSavedSettings.getBOOL("RenderBakeSunlight");
sNoAlpha = gSavedSettings.getBOOL("RenderNoAlpha");
LLPipeline::sTextureBindTest = gSavedSettings.getBOOL("RenderDebugTextureBind");
- LLVertexBuffer::initClass(LLVertexBuffer::sEnableVBOs, LLVertexBuffer::sDisableVBOMapping);
gGL.initVertexBuffer();
- mDeferredVB = new LLVertexBuffer(DEFERRED_VB_MASK, 0);
- mDeferredVB->allocateBuffer(8, 0, true);
+ mDeferredVB = new LLVertexBuffer(DEFERRED_VB_MASK);
+ mDeferredVB->allocateBuffer(8, 0);
LLVOPartGroup::restoreGL();
}
-void LLPipeline::renderObjects(U32 type, U32 mask, bool texture, bool batch_texture, bool rigged)
+void LLPipeline::renderObjects(U32 type, bool texture, bool batch_texture, bool rigged)
{
assertInitialized();
gGL.loadMatrix(gGLModelView);
gGLLastMatrix = NULL;
if (rigged)
{
- mSimplePool->pushRiggedBatches(type + 1, mask, texture, batch_texture);
+ mSimplePool->pushRiggedBatches(type + 1, texture, batch_texture);
}
else
{
- mSimplePool->pushBatches(type, mask, texture, batch_texture);
+ mSimplePool->pushBatches(type, texture, batch_texture);
}
gGL.loadMatrix(gGLModelView);
gGLLastMatrix = NULL;
}
-void LLPipeline::renderAlphaObjects(U32 mask, bool texture, bool batch_texture, bool rigged)
+void LLPipeline::renderShadowSimple(U32 type)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
+ assertInitialized();
+ gGL.loadMatrix(gGLModelView);
+ gGLLastMatrix = NULL;
+
+ LLVertexBuffer* last_vb = nullptr;
+
+ LLCullResult::drawinfo_iterator begin = gPipeline.beginRenderMap(type);
+ LLCullResult::drawinfo_iterator end = gPipeline.endRenderMap(type);
+
+ for (LLCullResult::drawinfo_iterator i = begin; i != end; )
+ {
+ LLDrawInfo& params = **i;
+
+ LLCullResult::increment_iterator(i, end);
+
+ LLVertexBuffer* vb = params.mVertexBuffer;
+ if (vb != last_vb)
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("push shadow simple");
+ mSimplePool->applyModelMatrix(params);
+ vb->setBuffer();
+ vb->drawRange(LLRender::TRIANGLES, 0, vb->getNumVerts()-1, vb->getNumIndices(), 0);
+ last_vb = vb;
+ }
+ }
+ gGL.loadMatrix(gGLModelView);
+ gGLLastMatrix = NULL;
+}
+
+void LLPipeline::renderAlphaObjects(bool texture, bool batch_texture, bool rigged)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
assertInitialized();
@@ -7346,64 +6969,67 @@ void LLPipeline::renderAlphaObjects(U32 mask, bool texture, bool batch_texture,
U32 type = LLRenderPass::PASS_ALPHA;
LLVOAvatar* lastAvatar = nullptr;
U64 lastMeshId = 0;
- for (LLCullResult::drawinfo_iterator i = gPipeline.beginRenderMap(type); i != gPipeline.endRenderMap(type); ++i)
+ auto* begin = gPipeline.beginRenderMap(type);
+ auto* end = gPipeline.endRenderMap(type);
+
+ for (LLCullResult::drawinfo_iterator i = begin; i != end; )
{
LLDrawInfo* pparams = *i;
- if (pparams)
+ LLCullResult::increment_iterator(i, end);
+
+ if (rigged)
{
- if (rigged)
+ if (pparams->mAvatar != nullptr)
{
- if (pparams->mAvatar != nullptr)
+ if (lastAvatar != pparams->mAvatar || lastMeshId != pparams->mSkinInfo->mHash)
{
- if (lastAvatar != pparams->mAvatar || lastMeshId != pparams->mSkinInfo->mHash)
- {
- mSimplePool->uploadMatrixPalette(*pparams);
- lastAvatar = pparams->mAvatar;
- lastMeshId = pparams->mSkinInfo->mHash;
- }
-
- mSimplePool->pushBatch(*pparams, mask | LLVertexBuffer::MAP_WEIGHT4, texture, batch_texture);
+ mSimplePool->uploadMatrixPalette(*pparams);
+ lastAvatar = pparams->mAvatar;
+ lastMeshId = pparams->mSkinInfo->mHash;
}
- }
- else if (pparams->mAvatar == nullptr)
- {
- mSimplePool->pushBatch(*pparams, mask, texture, batch_texture);
+
+ mSimplePool->pushBatch(*pparams, texture, batch_texture);
}
}
+ else if (pparams->mAvatar == nullptr)
+ {
+ mSimplePool->pushBatch(*pparams, texture, batch_texture);
+ }
}
+
gGL.loadMatrix(gGLModelView);
gGLLastMatrix = NULL;
}
-void LLPipeline::renderMaskedObjects(U32 type, U32 mask, bool texture, bool batch_texture, bool rigged)
+void LLPipeline::renderMaskedObjects(U32 type, bool texture, bool batch_texture, bool rigged)
{
assertInitialized();
gGL.loadMatrix(gGLModelView);
gGLLastMatrix = NULL;
if (rigged)
{
- mAlphaMaskPool->pushRiggedMaskBatches(type+1, mask, texture, batch_texture);
+ mAlphaMaskPool->pushRiggedMaskBatches(type+1, texture, batch_texture);
}
else
{
- mAlphaMaskPool->pushMaskBatches(type, mask, texture, batch_texture);
+ mAlphaMaskPool->pushMaskBatches(type, texture, batch_texture);
}
gGL.loadMatrix(gGLModelView);
gGLLastMatrix = NULL;
}
-void LLPipeline::renderFullbrightMaskedObjects(U32 type, U32 mask, bool texture, bool batch_texture, bool rigged)
+void LLPipeline::renderFullbrightMaskedObjects(U32 type, bool texture, bool batch_texture, bool rigged)
{
assertInitialized();
gGL.loadMatrix(gGLModelView);
gGLLastMatrix = NULL;
if (rigged)
{
- mFullbrightAlphaMaskPool->pushRiggedMaskBatches(type+1, mask, texture, batch_texture);
+ mFullbrightAlphaMaskPool->pushRiggedMaskBatches(type+1, texture, batch_texture);
}
else
{
- mFullbrightAlphaMaskPool->pushMaskBatches(type, mask, texture, batch_texture);
+ mFullbrightAlphaMaskPool->pushMaskBatches(type, texture, batch_texture);
}
gGL.loadMatrix(gGLModelView);
gGLLastMatrix = NULL;
@@ -7471,642 +7097,816 @@ void LLPipeline::bindScreenToTexture()
static LLTrace::BlockTimerStatHandle FTM_RENDER_BLOOM("Bloom");
-void LLPipeline::renderFinalize()
+void LLPipeline::renderPostProcess()
{
- LLVertexBuffer::unbind();
- LLGLState::checkStates();
- LLGLState::checkTextureChannels();
+ LLVertexBuffer::unbind();
+ LLGLState::checkStates();
- assertInitialized();
+ assertInitialized();
- if (gUseWireframe)
- {
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- }
+ LLVector2 tc1(0, 0);
+ LLVector2 tc2((F32)mRT->screen.getWidth() * 2, (F32)mRT->screen.getHeight() * 2);
- LLVector2 tc1(0, 0);
- LLVector2 tc2((F32) mScreen.getWidth() * 2, (F32) mScreen.getHeight() * 2);
+ LL_RECORD_BLOCK_TIME(FTM_RENDER_BLOOM);
+ LL_PROFILE_GPU_ZONE("renderPostProcess");
- LL_RECORD_BLOCK_TIME(FTM_RENDER_BLOOM);
- gGL.color4f(1, 1, 1, 1);
- LLGLDepthTest depth(GL_FALSE);
- LLGLDisable blend(GL_BLEND);
- LLGLDisable cull(GL_CULL_FACE);
+ LLGLDepthTest depth(GL_FALSE);
+ LLGLDisable blend(GL_BLEND);
+ LLGLDisable cull(GL_CULL_FACE);
- enableLightsFullbright();
+ enableLightsFullbright();
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.pushMatrix();
- gGL.loadIdentity();
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.pushMatrix();
- gGL.loadIdentity();
+ LLGLDisable test(GL_ALPHA_TEST);
- LLGLDisable test(GL_ALPHA_TEST);
+ gGL.setColorMask(true, true);
+ glClearColor(0, 0, 0, 0);
- gGL.setColorMask(true, true);
- glClearColor(0, 0, 0, 0);
+ if (sRenderGlow)
+ {
+ LL_PROFILE_GPU_ZONE("glow");
+ mGlow[2].bindTarget();
+ mGlow[2].clear();
- if (sRenderGlow)
- {
- mGlow[2].bindTarget();
- mGlow[2].clear();
-
- gGlowExtractProgram.bind();
- F32 minLum = llmax((F32) RenderGlowMinLuminance, 0.0f);
- F32 maxAlpha = RenderGlowMaxExtractAlpha;
- F32 warmthAmount = RenderGlowWarmthAmount;
- LLVector3 lumWeights = RenderGlowLumWeights;
- LLVector3 warmthWeights = RenderGlowWarmthWeights;
-
- gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_MIN_LUMINANCE, minLum);
- gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_MAX_EXTRACT_ALPHA, maxAlpha);
- gGlowExtractProgram.uniform3f(LLShaderMgr::GLOW_LUM_WEIGHTS, lumWeights.mV[0], lumWeights.mV[1],
- lumWeights.mV[2]);
- gGlowExtractProgram.uniform3f(LLShaderMgr::GLOW_WARMTH_WEIGHTS, warmthWeights.mV[0], warmthWeights.mV[1],
- warmthWeights.mV[2]);
- gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_WARMTH_AMOUNT, warmthAmount);
-
- {
- LLGLEnable blend_on(GL_BLEND);
- LLGLEnable test(GL_ALPHA_TEST);
+ gGlowExtractProgram.bind();
+ F32 minLum = llmax((F32)RenderGlowMinLuminance, 0.0f);
+ F32 maxAlpha = RenderGlowMaxExtractAlpha;
+ F32 warmthAmount = RenderGlowWarmthAmount;
+ LLVector3 lumWeights = RenderGlowLumWeights;
+ LLVector3 warmthWeights = RenderGlowWarmthWeights;
- gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA);
+ gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_MIN_LUMINANCE, minLum);
+ gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_MAX_EXTRACT_ALPHA, maxAlpha);
+ gGlowExtractProgram.uniform3f(LLShaderMgr::GLOW_LUM_WEIGHTS, lumWeights.mV[0], lumWeights.mV[1],
+ lumWeights.mV[2]);
+ gGlowExtractProgram.uniform3f(LLShaderMgr::GLOW_WARMTH_WEIGHTS, warmthWeights.mV[0], warmthWeights.mV[1],
+ warmthWeights.mV[2]);
+ gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_WARMTH_AMOUNT, warmthAmount);
- mScreen.bindTexture(0, 0, LLTexUnit::TFO_POINT);
+ {
+ LLGLEnable blend_on(GL_BLEND);
+ LLGLEnable test(GL_ALPHA_TEST);
- gGL.color4f(1, 1, 1, 1);
- gPipeline.enableLightsFullbright();
- gGL.begin(LLRender::TRIANGLE_STRIP);
- gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
- gGL.vertex2f(-1, -1);
+ gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA);
- gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
- gGL.vertex2f(-1, 3);
+ mRT->screen.bindTexture(0, 0, LLTexUnit::TFO_POINT);
- gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
- gGL.vertex2f(3, -1);
+ gGL.color4f(1, 1, 1, 1);
+ gPipeline.enableLightsFullbright();
+ gGL.begin(LLRender::TRIANGLE_STRIP);
+ gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
+ gGL.vertex2f(-1, -1);
- gGL.end();
+ gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
+ gGL.vertex2f(-1, 3);
- gGL.getTexUnit(0)->unbind(mScreen.getUsage());
+ gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
+ gGL.vertex2f(3, -1);
- mGlow[2].flush();
+ gGL.end();
- tc1.setVec(0, 0);
- tc2.setVec(2, 2);
- }
+ gGL.getTexUnit(0)->unbind(mRT->screen.getUsage());
- // power of two between 1 and 1024
- U32 glowResPow = RenderGlowResolutionPow;
- const U32 glow_res = llmax(1, llmin(1024, 1 << glowResPow));
+ mGlow[2].flush();
- S32 kernel = RenderGlowIterations * 2;
- F32 delta = RenderGlowWidth / glow_res;
- // Use half the glow width if we have the res set to less than 9 so that it looks
- // almost the same in either case.
- if (glowResPow < 9)
- {
- delta *= 0.5f;
- }
- F32 strength = RenderGlowStrength;
+ tc1.setVec(0, 0);
+ tc2.setVec(2, 2);
+ }
- gGlowProgram.bind();
- gGlowProgram.uniform1f(LLShaderMgr::GLOW_STRENGTH, strength);
+ // power of two between 1 and 1024
+ U32 glowResPow = RenderGlowResolutionPow;
+ const U32 glow_res = llmax(1, llmin(1024, 1 << glowResPow));
- for (S32 i = 0; i < kernel; i++)
- {
- mGlow[i % 2].bindTarget();
- mGlow[i % 2].clear();
+ S32 kernel = RenderGlowIterations * 2;
+ F32 delta = RenderGlowWidth / glow_res;
+ // Use half the glow width if we have the res set to less than 9 so that it looks
+ // almost the same in either case.
+ if (glowResPow < 9)
+ {
+ delta *= 0.5f;
+ }
+ F32 strength = RenderGlowStrength;
- if (i == 0)
- {
- gGL.getTexUnit(0)->bind(&mGlow[2]);
- }
- else
- {
- gGL.getTexUnit(0)->bind(&mGlow[(i - 1) % 2]);
- }
+ gGlowProgram.bind();
+ gGlowProgram.uniform1f(LLShaderMgr::GLOW_STRENGTH, strength);
- if (i % 2 == 0)
- {
- gGlowProgram.uniform2f(LLShaderMgr::GLOW_DELTA, delta, 0);
- }
- else
- {
- gGlowProgram.uniform2f(LLShaderMgr::GLOW_DELTA, 0, delta);
- }
+ for (S32 i = 0; i < kernel; i++)
+ {
+ mGlow[i % 2].bindTarget();
+ mGlow[i % 2].clear();
- gGL.begin(LLRender::TRIANGLE_STRIP);
- gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
- gGL.vertex2f(-1, -1);
+ if (i == 0)
+ {
+ gGL.getTexUnit(0)->bind(&mGlow[2]);
+ }
+ else
+ {
+ gGL.getTexUnit(0)->bind(&mGlow[(i - 1) % 2]);
+ }
- gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
- gGL.vertex2f(-1, 3);
+ if (i % 2 == 0)
+ {
+ gGlowProgram.uniform2f(LLShaderMgr::GLOW_DELTA, delta, 0);
+ }
+ else
+ {
+ gGlowProgram.uniform2f(LLShaderMgr::GLOW_DELTA, 0, delta);
+ }
- gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
- gGL.vertex2f(3, -1);
+ gGL.begin(LLRender::TRIANGLE_STRIP);
+ gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
+ gGL.vertex2f(-1, -1);
- gGL.end();
+ gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
+ gGL.vertex2f(-1, 3);
- mGlow[i % 2].flush();
- }
+ gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
+ gGL.vertex2f(3, -1);
- gGlowProgram.unbind();
- }
- else // !sRenderGlow, skip the glow ping-pong and just clear the result target
- {
- mGlow[1].bindTarget();
- mGlow[1].clear();
- mGlow[1].flush();
- }
+ gGL.end();
- gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft;
- gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom;
- gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth();
- gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight();
- glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
+ mGlow[i % 2].flush();
+ }
- tc2.setVec((F32) mScreen.getWidth(), (F32) mScreen.getHeight());
+ gGlowProgram.unbind();
+ gGL.setSceneBlendType(LLRender::BT_ALPHA);
+ }
+ else // !sRenderGlow, skip the glow ping-pong and just clear the result target
+ {
+ mGlow[1].bindTarget();
+ mGlow[1].clear();
+ mGlow[1].flush();
+ }
- gGL.flush();
+ gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft;
+ gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom;
+ gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth();
+ gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight();
+ glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
- LLVertexBuffer::unbind();
+ tc2.setVec((F32)mRT->screen.getWidth(), (F32)mRT->screen.getHeight());
+
+ gGL.flush();
+
+ LLVertexBuffer::unbind();
- if (LLPipeline::sRenderDeferred)
{
+ bool dof_enabled =
+ (RenderDepthOfFieldInEditMode || !LLToolMgr::getInstance()->inBuildMode()) &&
+ RenderDepthOfField &&
+ !gCubeSnapshot;
+
+ bool multisample = RenderFSAASamples > 1 && mRT->fxaaBuffer.isComplete() && !gCubeSnapshot;
+
+ gViewerWindow->setup3DViewport();
- bool dof_enabled = !LLViewerCamera::getInstance()->cameraUnderWater() &&
- (RenderDepthOfFieldInEditMode || !LLToolMgr::getInstance()->inBuildMode()) &&
- RenderDepthOfField;
+ if (dof_enabled)
+ {
+ LL_PROFILE_GPU_ZONE("dof");
+ LLGLSLShader* shader = &gDeferredPostProgram;
+ LLGLDisable blend(GL_BLEND);
- bool multisample = RenderFSAASamples > 1 && mFXAABuffer.isComplete();
+ // depth of field focal plane calculations
+ static F32 current_distance = 16.f;
+ static F32 start_distance = 16.f;
+ static F32 transition_time = 1.f;
- gViewerWindow->setup3DViewport();
+ LLVector3 focus_point;
- if (dof_enabled)
- {
- LLGLSLShader *shader = &gDeferredPostProgram;
- LLGLDisable blend(GL_BLEND);
+ LLViewerObject* obj = LLViewerMediaFocus::getInstance()->getFocusedObject();
+ if (obj && obj->mDrawable && obj->isSelected())
+ { // focus on selected media object
+ S32 face_idx = LLViewerMediaFocus::getInstance()->getFocusedFace();
+ if (obj && obj->mDrawable)
+ {
+ LLFace* face = obj->mDrawable->getFace(face_idx);
+ if (face)
+ {
+ focus_point = face->getPositionAgent();
+ }
+ }
+ }
- // depth of field focal plane calculations
- static F32 current_distance = 16.f;
- static F32 start_distance = 16.f;
- static F32 transition_time = 1.f;
+ if (focus_point.isExactlyZero())
+ {
+ if (LLViewerJoystick::getInstance()->getOverrideCamera())
+ { // focus on point under cursor
+ focus_point.set(gDebugRaycastIntersection.getF32ptr());
+ }
+ else if (gAgentCamera.cameraMouselook())
+ { // focus on point under mouselook crosshairs
+ LLVector4a result;
+ result.clear();
- LLVector3 focus_point;
+ gViewerWindow->cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE, TRUE, NULL, &result);
- LLViewerObject *obj = LLViewerMediaFocus::getInstance()->getFocusedObject();
- if (obj && obj->mDrawable && obj->isSelected())
- { // focus on selected media object
- S32 face_idx = LLViewerMediaFocus::getInstance()->getFocusedFace();
- if (obj && obj->mDrawable)
- {
- LLFace *face = obj->mDrawable->getFace(face_idx);
- if (face)
- {
- focus_point = face->getPositionAgent();
- }
- }
- }
+ focus_point.set(result.getF32ptr());
+ }
+ else
+ {
+ // focus on alt-zoom target
+ LLViewerRegion* region = gAgent.getRegion();
+ if (region)
+ {
+ focus_point = LLVector3(gAgentCamera.getFocusGlobal() - region->getOriginGlobal());
+ }
+ }
+ }
- if (focus_point.isExactlyZero())
- {
- if (LLViewerJoystick::getInstance()->getOverrideCamera())
- { // focus on point under cursor
- focus_point.set(gDebugRaycastIntersection.getF32ptr());
- }
- else if (gAgentCamera.cameraMouselook())
- { // focus on point under mouselook crosshairs
- LLVector4a result;
- result.clear();
+ LLVector3 eye = LLViewerCamera::getInstance()->getOrigin();
+ F32 target_distance = 16.f;
+ if (!focus_point.isExactlyZero())
+ {
+ target_distance = LLViewerCamera::getInstance()->getAtAxis() * (focus_point - eye);
+ }
- gViewerWindow->cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE, NULL, &result);
+ if (transition_time >= 1.f && fabsf(current_distance - target_distance) / current_distance > 0.01f)
+ { // large shift happened, interpolate smoothly to new target distance
+ transition_time = 0.f;
+ start_distance = current_distance;
+ }
+ else if (transition_time < 1.f)
+ { // currently in a transition, continue interpolating
+ transition_time += 1.f / CameraFocusTransitionTime * gFrameIntervalSeconds.value();
+ transition_time = llmin(transition_time, 1.f);
- focus_point.set(result.getF32ptr());
- }
- else
- {
- // focus on alt-zoom target
- LLViewerRegion *region = gAgent.getRegion();
- if (region)
- {
- focus_point = LLVector3(gAgentCamera.getFocusGlobal() - region->getOriginGlobal());
- }
- }
- }
+ F32 t = cosf(transition_time * F_PI + F_PI) * 0.5f + 0.5f;
+ current_distance = start_distance + (target_distance - start_distance) * t;
+ }
+ else
+ { // small or no change, just snap to target distance
+ current_distance = target_distance;
+ }
- LLVector3 eye = LLViewerCamera::getInstance()->getOrigin();
- F32 target_distance = 16.f;
- if (!focus_point.isExactlyZero())
- {
- target_distance = LLViewerCamera::getInstance()->getAtAxis() * (focus_point - eye);
- }
+ // convert to mm
+ F32 subject_distance = current_distance * 1000.f;
+ F32 fnumber = CameraFNumber;
+ F32 default_focal_length = CameraFocalLength;
- if (transition_time >= 1.f && fabsf(current_distance - target_distance) / current_distance > 0.01f)
- { // large shift happened, interpolate smoothly to new target distance
- transition_time = 0.f;
- start_distance = current_distance;
- }
- else if (transition_time < 1.f)
- { // currently in a transition, continue interpolating
- transition_time += 1.f / CameraFocusTransitionTime * gFrameIntervalSeconds.value();
- transition_time = llmin(transition_time, 1.f);
+ F32 fov = LLViewerCamera::getInstance()->getView();
- F32 t = cosf(transition_time * F_PI + F_PI) * 0.5f + 0.5f;
- current_distance = start_distance + (target_distance - start_distance) * t;
- }
- else
- { // small or no change, just snap to target distance
- current_distance = target_distance;
- }
+ const F32 default_fov = CameraFieldOfView * F_PI / 180.f;
- // convert to mm
- F32 subject_distance = current_distance * 1000.f;
- F32 fnumber = CameraFNumber;
- F32 default_focal_length = CameraFocalLength;
+ // F32 aspect_ratio = (F32) mRT->screen.getWidth()/(F32)mRT->screen.getHeight();
- F32 fov = LLViewerCamera::getInstance()->getView();
+ F32 dv = 2.f * default_focal_length * tanf(default_fov / 2.f);
- const F32 default_fov = CameraFieldOfView * F_PI / 180.f;
+ F32 focal_length = dv / (2 * tanf(fov / 2.f));
- // F32 aspect_ratio = (F32) mScreen.getWidth()/(F32)mScreen.getHeight();
+ // F32 tan_pixel_angle = tanf(LLDrawable::sCurPixelAngle);
- F32 dv = 2.f * default_focal_length * tanf(default_fov / 2.f);
+ // from wikipedia -- c = |s2-s1|/s2 * f^2/(N(S1-f))
+ // where N = fnumber
+ // s2 = dot distance
+ // s1 = subject distance
+ // f = focal length
+ //
- F32 focal_length = dv / (2 * tanf(fov / 2.f));
+ F32 blur_constant = focal_length * focal_length / (fnumber * (subject_distance - focal_length));
+ blur_constant /= 1000.f; // convert to meters for shader
+ F32 magnification = focal_length / (subject_distance - focal_length);
- // F32 tan_pixel_angle = tanf(LLDrawable::sCurPixelAngle);
+ { // build diffuse+bloom+CoF
+ mRT->deferredLight.bindTarget();
+ shader = &gDeferredCoFProgram;
- // from wikipedia -- c = |s2-s1|/s2 * f^2/(N(S1-f))
- // where N = fnumber
- // s2 = dot distance
- // s1 = subject distance
- // f = focal length
- //
+ bindDeferredShader(*shader);
- F32 blur_constant = focal_length * focal_length / (fnumber * (subject_distance - focal_length));
- blur_constant /= 1000.f; // convert to meters for shader
- F32 magnification = focal_length / (subject_distance - focal_length);
+ S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mRT->screen.getUsage());
+ if (channel > -1)
+ {
+ mRT->screen.bindTexture(0, channel);
+ }
- { // build diffuse+bloom+CoF
- mDeferredLight.bindTarget();
- shader = &gDeferredCoFProgram;
+ shader->uniform1f(LLShaderMgr::DOF_FOCAL_DISTANCE, -subject_distance / 1000.f);
+ shader->uniform1f(LLShaderMgr::DOF_BLUR_CONSTANT, blur_constant);
+ shader->uniform1f(LLShaderMgr::DOF_TAN_PIXEL_ANGLE, tanf(1.f / LLDrawable::sCurPixelAngle));
+ shader->uniform1f(LLShaderMgr::DOF_MAGNIFICATION, magnification);
+ shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF);
+ shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale);
- bindDeferredShader(*shader);
+ gGL.begin(LLRender::TRIANGLE_STRIP);
+ gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
+ gGL.vertex2f(-1, -1);
- S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage());
- if (channel > -1)
- {
- mScreen.bindTexture(0, channel);
- }
+ gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
+ gGL.vertex2f(-1, 3);
- shader->uniform1f(LLShaderMgr::DOF_FOCAL_DISTANCE, -subject_distance / 1000.f);
- shader->uniform1f(LLShaderMgr::DOF_BLUR_CONSTANT, blur_constant);
- shader->uniform1f(LLShaderMgr::DOF_TAN_PIXEL_ANGLE, tanf(1.f / LLDrawable::sCurPixelAngle));
- shader->uniform1f(LLShaderMgr::DOF_MAGNIFICATION, magnification);
- shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF);
- shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale);
+ gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
+ gGL.vertex2f(3, -1);
- gGL.begin(LLRender::TRIANGLE_STRIP);
- gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
- gGL.vertex2f(-1, -1);
+ gGL.end();
- gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
- gGL.vertex2f(-1, 3);
+ unbindDeferredShader(*shader);
+ mRT->deferredLight.flush();
+ }
- gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
- gGL.vertex2f(3, -1);
+ U32 dof_width = (U32)(mRT->screen.getWidth() * CameraDoFResScale);
+ U32 dof_height = (U32)(mRT->screen.getHeight() * CameraDoFResScale);
- gGL.end();
+ { // perform DoF sampling at half-res (preserve alpha channel)
+ mRT->screen.bindTarget();
+ glViewport(0, 0, dof_width, dof_height);
+ gGL.setColorMask(true, false);
- unbindDeferredShader(*shader);
- mDeferredLight.flush();
- }
+ shader = &gDeferredPostProgram;
+ bindDeferredShader(*shader);
+ S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mRT->deferredLight.getUsage());
+ if (channel > -1)
+ {
+ mRT->deferredLight.bindTexture(0, channel);
+ }
- U32 dof_width = (U32)(mScreen.getWidth() * CameraDoFResScale);
- U32 dof_height = (U32)(mScreen.getHeight() * CameraDoFResScale);
+ shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF);
+ shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale);
- { // perform DoF sampling at half-res (preserve alpha channel)
- mScreen.bindTarget();
- glViewport(0, 0, dof_width, dof_height);
- gGL.setColorMask(true, false);
+ gGL.begin(LLRender::TRIANGLE_STRIP);
+ gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
+ gGL.vertex2f(-1, -1);
- shader = &gDeferredPostProgram;
- bindDeferredShader(*shader);
- S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredLight.getUsage());
- if (channel > -1)
- {
- mDeferredLight.bindTexture(0, channel);
- }
+ gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
+ gGL.vertex2f(-1, 3);
- shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF);
- shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale);
+ gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
+ gGL.vertex2f(3, -1);
- gGL.begin(LLRender::TRIANGLE_STRIP);
- gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
- gGL.vertex2f(-1, -1);
+ gGL.end();
- gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
- gGL.vertex2f(-1, 3);
+ unbindDeferredShader(*shader);
+ mRT->screen.flush();
+ gGL.setColorMask(true, true);
+ }
- gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
- gGL.vertex2f(3, -1);
+ { // combine result based on alpha
+ if (multisample)
+ {
+ mRT->deferredLight.bindTarget();
+ glViewport(0, 0, mRT->deferredScreen.getWidth(), mRT->deferredScreen.getHeight());
+ }
+ else
+ {
+ gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft;
+ gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom;
+ gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth();
+ gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight();
+ glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
+ }
- gGL.end();
+ shader = &gDeferredDoFCombineProgram;
+ bindDeferredShader(*shader);
- unbindDeferredShader(*shader);
- mScreen.flush();
- gGL.setColorMask(true, true);
- }
+ S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mRT->screen.getUsage());
+ if (channel > -1)
+ {
+ mRT->screen.bindTexture(0, channel);
+ }
- { // combine result based on alpha
- if (multisample)
- {
- mDeferredLight.bindTarget();
- glViewport(0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight());
- }
- else
- {
- gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft;
- gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom;
- gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth();
- gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight();
- glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
- }
+ shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF);
+ shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale);
+ shader->uniform1f(LLShaderMgr::DOF_WIDTH, (dof_width - 1) / (F32)mRT->screen.getWidth());
+ shader->uniform1f(LLShaderMgr::DOF_HEIGHT, (dof_height - 1) / (F32)mRT->screen.getHeight());
- shader = &gDeferredDoFCombineProgram;
- bindDeferredShader(*shader);
+ gGL.begin(LLRender::TRIANGLE_STRIP);
+ gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
+ gGL.vertex2f(-1, -1);
- S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage());
- if (channel > -1)
- {
- mScreen.bindTexture(0, channel);
- }
+ gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
+ gGL.vertex2f(-1, 3);
- shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF);
- shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale);
- shader->uniform1f(LLShaderMgr::DOF_WIDTH, dof_width - 1);
- shader->uniform1f(LLShaderMgr::DOF_HEIGHT, dof_height - 1);
+ gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
+ gGL.vertex2f(3, -1);
- gGL.begin(LLRender::TRIANGLE_STRIP);
- gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
- gGL.vertex2f(-1, -1);
+ gGL.end();
- gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
- gGL.vertex2f(-1, 3);
+ unbindDeferredShader(*shader);
- gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
- gGL.vertex2f(3, -1);
+ if (multisample)
+ {
+ mRT->deferredLight.flush();
+ }
+ }
+ }
+ else
+ {
+ LL_PROFILE_GPU_ZONE("no dof");
+ if (multisample)
+ {
+ mRT->deferredLight.bindTarget();
+ }
+ LLGLSLShader* shader = &gDeferredPostNoDoFProgram;
- gGL.end();
+ bindDeferredShader(*shader);
- unbindDeferredShader(*shader);
+ S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mRT->screen.getUsage());
+ if (channel > -1)
+ {
+ mRT->screen.bindTexture(0, channel);
+ }
- if (multisample)
- {
- mDeferredLight.flush();
- }
- }
- }
- else
- {
- if (multisample)
- {
- mDeferredLight.bindTarget();
- }
- LLGLSLShader *shader = &gDeferredPostNoDoFProgram;
+ gGL.begin(LLRender::TRIANGLE_STRIP);
+ gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
+ gGL.vertex2f(-1, -1);
- bindDeferredShader(*shader);
+ gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
+ gGL.vertex2f(-1, 3);
- S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage());
- if (channel > -1)
- {
- mScreen.bindTexture(0, channel);
- }
+ gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
+ gGL.vertex2f(3, -1);
+
+ gGL.end();
+
+ unbindDeferredShader(*shader);
- gGL.begin(LLRender::TRIANGLE_STRIP);
- gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
- gGL.vertex2f(-1, -1);
+ if (multisample)
+ {
+ mRT->deferredLight.flush();
+ }
+ }
+ }
+}
- gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
- gGL.vertex2f(-1, 3);
+LLRenderTarget* LLPipeline::screenTarget() {
- gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
- gGL.vertex2f(3, -1);
+ bool dof_enabled = !LLViewerCamera::getInstance()->cameraUnderWater() &&
+ (RenderDepthOfFieldInEditMode || !LLToolMgr::getInstance()->inBuildMode()) &&
+ RenderDepthOfField &&
+ !gCubeSnapshot;
- gGL.end();
+ bool multisample = RenderFSAASamples > 1 && mRT->fxaaBuffer.isComplete() && !gCubeSnapshot;
- unbindDeferredShader(*shader);
+ if (multisample || dof_enabled)
+ return &mRT->deferredLight;
+
+ return &mRT->screen;
+}
- if (multisample)
- {
- mDeferredLight.flush();
- }
- }
+void LLPipeline::renderFinalize()
+{
+ LLVertexBuffer::unbind();
+ LLGLState::checkStates();
- if (multisample)
+ assertInitialized();
+
+ LLVector2 tc1(0, 0);
+ LLVector2 tc2((F32) mRT->screen.getWidth() * 2, (F32) mRT->screen.getHeight() * 2);
+
+ LL_RECORD_BLOCK_TIME(FTM_RENDER_BLOOM);
+ LL_PROFILE_GPU_ZONE("renderFinalize");
+
+ gGL.color4f(1, 1, 1, 1);
+ LLGLDepthTest depth(GL_FALSE);
+ LLGLDisable blend(GL_BLEND);
+ LLGLDisable cull(GL_CULL_FACE);
+
+ enableLightsFullbright();
+
+ LLGLDisable test(GL_ALPHA_TEST);
+
+ gGL.setColorMask(true, true);
+ glClearColor(0, 0, 0, 0);
+
+ if (!gCubeSnapshot)
+ {
+ LLRenderTarget* screen_target = screenTarget();
+
+ if (RenderScreenSpaceReflections && !gCubeSnapshot)
{
- // bake out texture2D with RGBL for FXAA shader
- mFXAABuffer.bindTarget();
+#if 0
+ LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("renderDeferredLighting - screen space reflections");
+ LL_PROFILE_GPU_ZONE("screen space reflections");
- S32 width = mScreen.getWidth();
- S32 height = mScreen.getHeight();
- glViewport(0, 0, width, height);
+ bindDeferredShader(gPostScreenSpaceReflectionProgram, NULL);
+ mScreenTriangleVB->setBuffer();
- LLGLSLShader *shader = &gGlowCombineFXAAProgram;
+ set_camera_projection_matrix(gPostScreenSpaceReflectionProgram);
- shader->bind();
- shader->uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, width, height);
+ // We need linear depth.
+ static LLStaticHashedString zfar("zFar");
+ static LLStaticHashedString znear("zNear");
+ float nearClip = LLViewerCamera::getInstance()->getNear();
+ float farClip = LLViewerCamera::getInstance()->getFar();
+ gPostScreenSpaceReflectionProgram.uniform1f(zfar, farClip);
+ gPostScreenSpaceReflectionProgram.uniform1f(znear, nearClip);
- S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredLight.getUsage());
+ S32 channel = gPostScreenSpaceReflectionProgram.enableTexture(LLShaderMgr::DIFFUSE_MAP, screenTarget()->getUsage());
if (channel > -1)
{
- mDeferredLight.bindTexture(0, channel);
+ screenTarget()->bindTexture(0, channel, LLTexUnit::TFO_POINT);
+ }
+
+ {
+ LLGLDisable blend(GL_BLEND);
+ LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
+
+ stop_glerror();
+ mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+ stop_glerror();
}
- gGL.begin(LLRender::TRIANGLE_STRIP);
- gGL.vertex2f(-1, -1);
- gGL.vertex2f(-1, 3);
- gGL.vertex2f(3, -1);
- gGL.end();
+ unbindDeferredShader(gPostScreenSpaceReflectionProgram);
+#else
+ LL_PROFILE_GPU_ZONE("ssr copy");
+ LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS);
- gGL.flush();
+ LLRenderTarget& src = *screen_target;
+ LLRenderTarget& depth_src = mRT->deferredScreen;
+ LLRenderTarget& dst = mSceneMap;
- shader->disableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredLight.getUsage());
- shader->unbind();
+ dst.bindTarget();
+ dst.clear();
+ gCopyDepthProgram.bind();
- mFXAABuffer.flush();
+ S32 diff_map = gCopyDepthProgram.getTextureChannel(LLShaderMgr::DIFFUSE_MAP);
+ S32 depth_map = gCopyDepthProgram.getTextureChannel(LLShaderMgr::DEFERRED_DEPTH);
- shader = &gFXAAProgram;
- shader->bind();
+ gGL.getTexUnit(diff_map)->bind(&src);
+ gGL.getTexUnit(depth_map)->bind(&depth_src, true);
- channel = shader->enableTexture(LLShaderMgr::DIFFUSE_MAP, mFXAABuffer.getUsage());
+ mScreenTriangleVB->setBuffer();
+ mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+
+ dst.flush();
+#endif
+ }
+
+ screenTarget()->bindTarget();
+
+ // gamma correct lighting
+ {
+ LL_PROFILE_GPU_ZONE("gamma correct");
+
+ LLGLDepthTest depth(GL_FALSE, GL_FALSE);
+
+ LLVector2 tc1(0, 0);
+ LLVector2 tc2((F32)screenTarget()->getWidth() * 2, (F32)screenTarget()->getHeight() * 2);
+
+ // Apply gamma correction to the frame here.
+ gDeferredPostGammaCorrectProgram.bind();
+
+ S32 channel = 0;
+ channel = gDeferredPostGammaCorrectProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, screenTarget()->getUsage());
if (channel > -1)
{
- mFXAABuffer.bindTexture(0, channel, LLTexUnit::TFO_BILINEAR);
+ screenTarget()->bindTexture(0, channel, LLTexUnit::TFO_POINT);
}
- gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft;
- gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom;
- gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth();
- gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight();
- glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
-
- F32 scale_x = (F32) width / mFXAABuffer.getWidth();
- F32 scale_y = (F32) height / mFXAABuffer.getHeight();
- shader->uniform2f(LLShaderMgr::FXAA_TC_SCALE, scale_x, scale_y);
- shader->uniform2f(LLShaderMgr::FXAA_RCP_SCREEN_RES, 1.f / width * scale_x, 1.f / height * scale_y);
- shader->uniform4f(LLShaderMgr::FXAA_RCP_FRAME_OPT, -0.5f / width * scale_x, -0.5f / height * scale_y,
- 0.5f / width * scale_x, 0.5f / height * scale_y);
- shader->uniform4f(LLShaderMgr::FXAA_RCP_FRAME_OPT2, -2.f / width * scale_x, -2.f / height * scale_y,
- 2.f / width * scale_x, 2.f / height * scale_y);
-
- gGL.begin(LLRender::TRIANGLE_STRIP);
- gGL.vertex2f(-1, -1);
- gGL.vertex2f(-1, 3);
- gGL.vertex2f(3, -1);
- gGL.end();
-
- gGL.flush();
- shader->unbind();
+ gDeferredPostGammaCorrectProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, screenTarget()->getWidth(), screenTarget()->getHeight());
+
+ F32 gamma = gSavedSettings.getF32("RenderDeferredDisplayGamma");
+
+ gDeferredPostGammaCorrectProgram.uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f / 2.2f));
+
+ mScreenTriangleVB->setBuffer();
+ mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+
+ gGL.getTexUnit(channel)->unbind(screenTarget()->getUsage());
+ gDeferredPostGammaCorrectProgram.unbind();
}
+
+ screenTarget()->flush();
+
+ LLVertexBuffer::unbind();
}
- else // not deferred
- {
- U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1;
- LLPointer<LLVertexBuffer> buff = new LLVertexBuffer(mask, 0);
- buff->allocateBuffer(3, 0, TRUE);
- LLStrider<LLVector3> v;
- LLStrider<LLVector2> uv1;
- LLStrider<LLVector2> uv2;
+ {
+ llassert(!gCubeSnapshot);
+ bool multisample = RenderFSAASamples > 1 && mRT->fxaaBuffer.isComplete();
+ LLGLSLShader* shader = &gGlowCombineProgram;
- buff->getVertexStrider(v);
- buff->getTexCoord0Strider(uv1);
- buff->getTexCoord1Strider(uv2);
+ S32 width = mRT->screen.getWidth();
+ S32 height = mRT->screen.getHeight();
- uv1[0] = LLVector2(0, 0);
- uv1[1] = LLVector2(0, 2);
- uv1[2] = LLVector2(2, 0);
+ S32 channel = -1;
- uv2[0] = LLVector2(0, 0);
- uv2[1] = LLVector2(0, tc2.mV[1] * 2.f);
- uv2[2] = LLVector2(tc2.mV[0] * 2.f, 0);
+ // Present everything.
+ if (multisample)
+ {
+ LL_PROFILE_GPU_ZONE("aa");
+ // bake out texture2D with RGBL for FXAA shader
+ mRT->fxaaBuffer.bindTarget();
- v[0] = LLVector3(-1, -1, 0);
- v[1] = LLVector3(-1, 3, 0);
- v[2] = LLVector3(3, -1, 0);
+ glViewport(0, 0, width, height);
- buff->flush();
+ shader = &gGlowCombineFXAAProgram;
- LLGLDisable blend(GL_BLEND);
+ shader->bind();
+ shader->uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, width, height);
- gGlowCombineProgram.bind();
+ channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mRT->deferredLight.getUsage());
+ if (channel > -1)
+ {
+ mRT->deferredLight.bindTexture(0, channel);
+ }
- gGL.getTexUnit(0)->bind(&mGlow[1]);
- gGL.getTexUnit(1)->bind(&mScreen);
+ {
+ LLGLDepthTest depth_test(GL_FALSE, GL_FALSE, GL_ALWAYS);
+ mScreenTriangleVB->setBuffer();
+ mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+ }
- LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
+ gGL.flush();
- buff->setBuffer(mask);
- buff->drawArrays(LLRender::TRIANGLE_STRIP, 0, 3);
+ shader->disableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mRT->deferredLight.getUsage());
+ shader->unbind();
- gGlowCombineProgram.unbind();
- }
+ mRT->fxaaBuffer.flush();
- gGL.setSceneBlendType(LLRender::BT_ALPHA);
+ shader = &gFXAAProgram;
+ shader->bind();
- if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PHYSICS_SHAPES))
- {
- gSplatTextureRectProgram.bind();
+ channel = shader->enableTexture(LLShaderMgr::DIFFUSE_MAP, mRT->fxaaBuffer.getUsage());
+ if (channel > -1)
+ {
+ mRT->fxaaBuffer.bindTexture(0, channel, LLTexUnit::TFO_BILINEAR);
+ }
- gGL.setColorMask(true, false);
+ gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft;
+ gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom;
+ gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth();
+ gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight();
+ glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
- LLVector2 tc1(0, 0);
- LLVector2 tc2((F32) gViewerWindow->getWorldViewWidthRaw() * 2,
- (F32) gViewerWindow->getWorldViewHeightRaw() * 2);
+ F32 scale_x = (F32)width / mRT->fxaaBuffer.getWidth();
+ F32 scale_y = (F32)height / mRT->fxaaBuffer.getHeight();
+ shader->uniform2f(LLShaderMgr::FXAA_TC_SCALE, scale_x, scale_y);
+ shader->uniform2f(LLShaderMgr::FXAA_RCP_SCREEN_RES, 1.f / width * scale_x, 1.f / height * scale_y);
+ shader->uniform4f(LLShaderMgr::FXAA_RCP_FRAME_OPT, -0.5f / width * scale_x, -0.5f / height * scale_y,
+ 0.5f / width * scale_x, 0.5f / height * scale_y);
+ shader->uniform4f(LLShaderMgr::FXAA_RCP_FRAME_OPT2, -2.f / width * scale_x, -2.f / height * scale_y,
+ 2.f / width * scale_x, 2.f / height * scale_y);
- LLGLEnable blend(GL_BLEND);
- gGL.color4f(1, 1, 1, 0.75f);
+ {
+ // at this point we should pointed at the backbuffer
+ llassert(LLRenderTarget::sCurFBO == 0);
- gGL.getTexUnit(0)->bind(&mPhysicsDisplay);
+ LLGLDepthTest depth_test(GL_TRUE, GL_TRUE, GL_ALWAYS);
+ S32 depth_channel = shader->getTextureChannel(LLShaderMgr::DEFERRED_DEPTH);
+ gGL.getTexUnit(depth_channel)->bind(&mRT->deferredScreen, true);
- gGL.begin(LLRender::TRIANGLES);
- gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
- gGL.vertex2f(-1, -1);
+ mScreenTriangleVB->setBuffer();
+ mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+ }
+
+ shader->unbind();
+ }
+ else
+ {
+ // at this point we should pointed at the backbuffer
+ llassert(LLRenderTarget::sCurFBO == 0);
- gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
- gGL.vertex2f(-1, 3);
+ LLGLDepthTest depth_test(GL_TRUE, GL_TRUE, GL_ALWAYS);
- gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
- gGL.vertex2f(3, -1);
+ shader->bind();
- gGL.end();
- gGL.flush();
+ S32 glow_channel = shader->getTextureChannel(LLShaderMgr::DEFERRED_EMISSIVE);
+ S32 screen_channel = shader->getTextureChannel(LLShaderMgr::DEFERRED_DIFFUSE);
+ S32 depth_channel = shader->getTextureChannel(LLShaderMgr::DEFERRED_DEPTH);
- gSplatTextureRectProgram.unbind();
- }
+ gGL.getTexUnit(glow_channel)->bind(&mGlow[1]);
+ gGL.getTexUnit(screen_channel)->bind(screenTarget());
+ gGL.getTexUnit(depth_channel)->bind(&mRT->deferredScreen, true);
- if (LLRenderTarget::sUseFBO)
- { // copy depth buffer from mScreen to framebuffer
- LLRenderTarget::copyContentsToFramebuffer(mScreen, 0, 0, mScreen.getWidth(), mScreen.getHeight(), 0, 0,
- mScreen.getWidth(), mScreen.getHeight(),
- GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
+ gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft;
+ gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom;
+ gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth();
+ gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight();
+ glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
+
+ mScreenTriangleVB->setBuffer();
+ mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+
+ gGL.flush();
+ shader->unbind();
+ }
+ }
+
+
+ gGL.setSceneBlendType(LLRender::BT_ALPHA);
+
+ if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PHYSICS_SHAPES))
+ {
+ renderPhysicsDisplay();
}
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.popMatrix();
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.popMatrix();
+ /*if (LLRenderTarget::sUseFBO && !gCubeSnapshot)
+ { // copy depth buffer from mRT->screen to framebuffer
+ LLRenderTarget::copyContentsToFramebuffer(mRT->screen, 0, 0, mRT->screen.getWidth(), mRT->screen.getHeight(), 0, 0,
+ mRT->screen.getWidth(), mRT->screen.getHeight(),
+ GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
+ }*/
LLVertexBuffer::unbind();
LLGLState::checkStates();
- LLGLState::checkTextureChannels();
+
+ // flush calls made to "addTrianglesDrawn" so far to stats machinery
+ recordTrianglesDrawn();
+}
+
+void LLPipeline::bindLightFunc(LLGLSLShader& shader)
+{
+ S32 channel = shader.enableTexture(LLShaderMgr::DEFERRED_LIGHTFUNC);
+ if (channel > -1)
+ {
+ gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, mLightFunc);
+ }
+
+ channel = shader.enableTexture(LLShaderMgr::DEFERRED_BRDF_LUT, LLTexUnit::TT_TEXTURE);
+ if (channel > -1)
+ {
+ mPbrBrdfLut.bindTexture(0, channel);
+ }
+}
+
+void LLPipeline::bindShadowMaps(LLGLSLShader& shader)
+{
+ for (U32 i = 0; i < 4; i++)
+ {
+ LLRenderTarget* shadow_target = getSunShadowTarget(i);
+ if (shadow_target)
+ {
+ S32 channel = shader.enableTexture(LLShaderMgr::DEFERRED_SHADOW0 + i, LLTexUnit::TT_TEXTURE);
+ if (channel > -1)
+ {
+ gGL.getTexUnit(channel)->bind(getSunShadowTarget(i), TRUE);
+ }
+ }
+ }
+
+ for (U32 i = 4; i < 6; i++)
+ {
+ S32 channel = shader.enableTexture(LLShaderMgr::DEFERRED_SHADOW0 + i);
+ if (channel > -1)
+ {
+ LLRenderTarget* shadow_target = getSpotShadowTarget(i - 4);
+ if (shadow_target)
+ {
+ gGL.getTexUnit(channel)->bind(shadow_target, TRUE);
+ }
+ }
+ }
+}
+
+void LLPipeline::bindDeferredShaderFast(LLGLSLShader& shader)
+{
+ shader.bind();
+ bindLightFunc(shader);
+ bindShadowMaps(shader);
+ bindReflectionProbes(shader);
}
void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_target)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
-
- LLRenderTarget* deferred_target = &mDeferredScreen;
- LLRenderTarget* deferred_depth_target = &mDeferredDepth;
- LLRenderTarget* deferred_light_target = &mDeferredLight;
+ LLRenderTarget* deferred_target = &mRT->deferredScreen;
+ LLRenderTarget* deferred_light_target = &mRT->deferredLight;
shader.bind();
S32 channel = 0;
channel = shader.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, deferred_target->getUsage());
if (channel > -1)
{
- deferred_target->bindTexture(0,channel, LLTexUnit::TFO_POINT);
+ deferred_target->bindTexture(0,channel, LLTexUnit::TFO_POINT); // frag_data[0]
+ gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
}
channel = shader.enableTexture(LLShaderMgr::DEFERRED_SPECULAR, deferred_target->getUsage());
if (channel > -1)
{
- deferred_target->bindTexture(1, channel, LLTexUnit::TFO_POINT);
+ deferred_target->bindTexture(1, channel, LLTexUnit::TFO_POINT); // frag_data[1]
+ gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
}
channel = shader.enableTexture(LLShaderMgr::DEFERRED_NORMAL, deferred_target->getUsage());
if (channel > -1)
{
- deferred_target->bindTexture(2, channel, LLTexUnit::TFO_POINT);
+ deferred_target->bindTexture(2, channel, LLTexUnit::TFO_POINT); // frag_data[2]
+ gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
}
- channel = shader.enableTexture(LLShaderMgr::DEFERRED_DEPTH, deferred_depth_target->getUsage());
- if (channel > -1)
- {
- gGL.getTexUnit(channel)->bind(deferred_depth_target, TRUE);
- stop_glerror();
+ channel = shader.enableTexture(LLShaderMgr::DEFERRED_EMISSIVE, deferred_target->getUsage());
+ if (channel > -1)
+ {
+ deferred_target->bindTexture(3, channel, LLTexUnit::TFO_POINT); // frag_data[3]
+ gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
}
-
- glh::matrix4f projection = get_current_projection();
- glh::matrix4f inv_proj = projection.inverse();
-
- if (shader.getUniformLocation(LLShaderMgr::INVERSE_PROJECTION_MATRIX) != -1)
+
+ channel = shader.enableTexture(LLShaderMgr::DEFERRED_DEPTH, deferred_target->getUsage());
+ if (channel > -1)
{
- shader.uniformMatrix4fv(LLShaderMgr::INVERSE_PROJECTION_MATRIX, 1, FALSE, inv_proj.m);
+ gGL.getTexUnit(channel)->bind(deferred_target, TRUE);
+ stop_glerror();
+ }
+
+ 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)
@@ -8129,11 +7929,7 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_
gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
}
- channel = shader.enableTexture(LLShaderMgr::DEFERRED_LIGHTFUNC);
- if (channel > -1)
- {
- gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, mLightFunc);
- }
+ bindLightFunc(shader);
stop_glerror();
@@ -8141,7 +7937,14 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_
channel = shader.enableTexture(LLShaderMgr::DEFERRED_LIGHT, light_target->getUsage());
if (channel > -1)
{
- light_target->bindTexture(0, channel, LLTexUnit::TFO_POINT);
+ if (light_target->isComplete())
+ {
+ light_target->bindTexture(0, channel, LLTexUnit::TFO_POINT);
+ }
+ else
+ {
+ gGL.getTexUnit(channel)->bindFast(LLViewerFetchedTexture::sWhiteImagep);
+ }
}
channel = shader.enableTexture(LLShaderMgr::DEFERRED_BLOOM);
@@ -8152,49 +7955,7 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_
stop_glerror();
- for (U32 i = 0; i < 4; i++)
- {
- LLRenderTarget* shadow_target = getShadowTarget(i);
- if (shadow_target)
- {
- channel = shader.enableTexture(LLShaderMgr::DEFERRED_SHADOW0+i, LLTexUnit::TT_TEXTURE);
- stop_glerror();
- if (channel > -1)
- {
- stop_glerror();
- gGL.getTexUnit(channel)->bind(getShadowTarget(i), TRUE);
- gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
- gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
- stop_glerror();
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
- stop_glerror();
- }
- }
- }
-
- for (U32 i = 4; i < 6; i++)
- {
- channel = shader.enableTexture(LLShaderMgr::DEFERRED_SHADOW0+i);
- stop_glerror();
- if (channel > -1)
- {
- stop_glerror();
- LLRenderTarget* shadow_target = getShadowTarget(i);
- if (shadow_target)
- {
- gGL.getTexUnit(channel)->bind(shadow_target, TRUE);
- gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
- gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
- stop_glerror();
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
- stop_glerror();
- }
- }
- }
+ bindShadowMaps(shader);
stop_glerror();
@@ -8213,23 +7974,29 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_
stop_glerror();
- channel = shader.enableTexture(LLShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
- if (channel > -1)
- {
- LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL;
- if (cube_map)
- {
- cube_map->enable(channel);
- cube_map->bind();
- F32* m = gGLModelView;
-
- F32 mat[] = { m[0], m[1], m[2],
- m[4], m[5], m[6],
- m[8], m[9], m[10] };
-
- shader.uniformMatrix3fv(LLShaderMgr::DEFERRED_ENV_MAT, 1, TRUE, mat);
- }
- }
+ if (!LLPipeline::sReflectionProbesEnabled)
+ {
+ channel = shader.enableTexture(LLShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
+ if (channel > -1)
+ {
+ LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL;
+ if (cube_map)
+ {
+ cube_map->enable(channel);
+ cube_map->bind();
+ }
+
+ F32* m = gGLModelView;
+
+ F32 mat[] = { m[0], m[1], m[2],
+ m[4], m[5], m[6],
+ m[8], m[9], m[10] };
+
+ shader.uniformMatrix3fv(LLShaderMgr::DEFERRED_ENV_MAT, 1, TRUE, mat);
+ }
+ }
+
+ bindReflectionProbes(shader);
if (gAtmosphere)
{
@@ -8259,7 +8026,14 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_
}
}
- shader.uniform4fv(LLShaderMgr::DEFERRED_SHADOW_CLIP, 1, mSunClipPlanes.mV);
+ /*if (gCubeSnapshot)
+ { // we only really care about the first two values, but the shader needs increasing separation between clip planes
+ shader.uniform4f(LLShaderMgr::DEFERRED_SHADOW_CLIP, 1.f, 64.f, 128.f, 256.f);
+ }
+ else*/
+ {
+ shader.uniform4fv(LLShaderMgr::DEFERRED_SHADOW_CLIP, 1, mSunClipPlanes.mV);
+ }
shader.uniform1f(LLShaderMgr::DEFERRED_SUN_WASH, RenderDeferredSunWash);
shader.uniform1f(LLShaderMgr::DEFERRED_SHADOW_NOISE, RenderShadowNoise);
shader.uniform1f(LLShaderMgr::DEFERRED_BLUR_SIZE, RenderShadowBlurSize);
@@ -8294,24 +8068,29 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_
shader.uniform3fv(LLShaderMgr::DEFERRED_SUN_DIR, 1, mTransformedSunDir.mV);
shader.uniform3fv(LLShaderMgr::DEFERRED_MOON_DIR, 1, mTransformedMoonDir.mV);
- shader.uniform2f(LLShaderMgr::DEFERRED_SHADOW_RES, mShadow[0].getWidth(), mShadow[0].getHeight());
- shader.uniform2f(LLShaderMgr::DEFERRED_PROJ_SHADOW_RES, mShadow[4].getWidth(), mShadow[4].getHeight());
+ 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);
+ 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();
shader.uniformMatrix4fv(LLShaderMgr::DEFERRED_NORM_MATRIX, 1, FALSE, norm_mat.m);
}
- shader.uniform4fv(LLShaderMgr::SUNLIGHT_COLOR, 1, mSunDiffuse.mV);
- shader.uniform4fv(LLShaderMgr::MOONLIGHT_COLOR, 1, mMoonDiffuse.mV);
+ shader.uniform3fv(LLShaderMgr::SUNLIGHT_COLOR, 1, mSunDiffuse.mV);
+ shader.uniform3fv(LLShaderMgr::MOONLIGHT_COLOR, 1, mMoonDiffuse.mV);
- LLEnvironment& environment = LLEnvironment::instance();
- LLSettingsSky::ptr_t sky = environment.getCurrentSky();
+ shader.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mReflectionMapManager.mMaxProbeLOD);
}
+
LLColor3 pow3f(LLColor3 v, F32 f)
{
v.mV[0] = powf(v.mV[0], f);
@@ -8328,48 +8107,38 @@ LLVector4 pow4fsrgb(LLVector4 v, F32 f)
return v;
}
-void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
+void LLPipeline::renderDeferredLighting()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
+ LL_PROFILE_GPU_ZONE("renderDeferredLighting");
if (!sCull)
{
return;
}
- LLRenderTarget *deferred_target = &mDeferredScreen;
- LLRenderTarget *deferred_depth_target = &mDeferredDepth;
- LLRenderTarget *deferred_light_target = &mDeferredLight;
+ static LLCachedControl<F32> 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;
{
- 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();
- {
- 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);
- }
-
- LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
+
+ LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE : 0);
if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
{
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
@@ -8380,13 +8149,6 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
glh::matrix4f mat = copy_matrix(gGLModelView);
- LLStrider<LLVector3> vert;
- mDeferredVB->getVertexStrider(vert);
-
- vert[0].set(-1, 1, 0);
- vert[1].set(-1, -3, 0);
- vert[2].set(3, 1, 0);
-
setupHWLights(NULL); // to set mSun/MoonDir;
glh::vec4f tc(mSunDir.mV);
@@ -8397,19 +8159,14 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
mat.mult_matrix_vec(tc_moon);
mTransformedMoonDir.set(tc_moon.v);
- gGL.pushMatrix();
- gGL.loadIdentity();
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.pushMatrix();
- gGL.loadIdentity();
-
if (RenderDeferredSSAO || RenderShadowDetail > 0)
{
+ LL_PROFILE_GPU_ZONE("sun program");
deferred_light_target->bindTarget();
{ // paint shadow/SSAO light map (direct lighting lightmap)
LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("renderDeferredLighting - sun shadow");
bindDeferredShader(gDeferredSunProgram, deferred_light_target);
- mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+ mScreenTriangleVB->setBuffer();
glClearColor(1, 1, 1, 1);
deferred_light_target->clear(GL_COLOR_BUFFER_BIT);
glClearColor(0, 0, 0, 0);
@@ -8441,9 +8198,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
{
LLGLDisable blend(GL_BLEND);
LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
- stop_glerror();
- mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
- stop_glerror();
+ mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
}
unbindDeferredShader(gDeferredSunProgram);
@@ -8452,8 +8207,10 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
}
if (RenderDeferredSSAO)
- { // soften direct lighting lightmap
+ {
+ // 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);
@@ -8461,10 +8218,10 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
glClearColor(0, 0, 0, 0);
bindDeferredShader(gDeferredBlurLightProgram);
- mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
- LLVector3 go = RenderShadowGaussian;
+
+ LLVector3 go = RenderShadowGaussian;
const U32 kern_length = 4;
- F32 blur_size = RenderShadowBlurSize;
+ F32 blur_size = RenderShadowBlurSize;
F32 dist_factor = RenderShadowBlurDistFactor;
// sample symmetrically with the middle sample falling exactly on 0.0
@@ -8488,9 +8245,8 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
{
LLGLDisable blend(GL_BLEND);
LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
- stop_glerror();
- mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
- stop_glerror();
+ mScreenTriangleVB->setBuffer();
+ mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
}
screen_target->flush();
@@ -8498,7 +8254,6 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
bindDeferredShader(gDeferredBlurLightProgram, screen_target);
- mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
deferred_light_target->bindTarget();
gDeferredBlurLightProgram.uniform2f(sDelta, 0.f, 1.f);
@@ -8506,22 +8261,13 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
{
LLGLDisable blend(GL_BLEND);
LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
- stop_glerror();
- mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
- stop_glerror();
+ mScreenTriangleVB->setBuffer();
+ mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
}
deferred_light_target->flush();
unbindDeferredShader(gDeferredBlurLightProgram);
}
- stop_glerror();
- gGL.popMatrix();
- stop_glerror();
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- stop_glerror();
- gGL.popMatrix();
- stop_glerror();
-
screen_target->bindTarget();
// clear color buffer here - zeroing alpha (glow) is important or it will accumulate against sky
glClearColor(0, 0, 0, 0);
@@ -8532,11 +8278,12 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
LLGLSLShader &soften_shader = LLPipeline::sUnderWaterRender ? gDeferredSoftenWaterProgram : gDeferredSoftenProgram;
LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("renderDeferredLighting - atmospherics");
+ LL_PROFILE_GPU_ZONE("atmospherics");
bindDeferredShader(soften_shader);
LLEnvironment &environment = LLEnvironment::instance();
soften_shader.uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0);
- soften_shader.uniform4fv(LLShaderMgr::LIGHTNORM, 1, environment.getClampedLightNorm().mV);
+ soften_shader.uniform3fv(LLShaderMgr::LIGHTNORM, 1, environment.getClampedLightNorm().mV);
{
LLGLDepthTest depth(GL_FALSE);
@@ -8544,41 +8291,14 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
LLGLDisable test(GL_ALPHA_TEST);
// full screen blit
- gGL.pushMatrix();
- gGL.loadIdentity();
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.pushMatrix();
- gGL.loadIdentity();
-
- mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
-
- mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
-
- gGL.popMatrix();
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.popMatrix();
+ mScreenTriangleVB->setBuffer();
+ mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
}
unbindDeferredShader(LLPipeline::sUnderWaterRender ? gDeferredSoftenWaterProgram : gDeferredSoftenProgram);
}
- { // 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();
- }
-
- bool render_local = RenderLocalLights;
+ bool render_local = RenderLocalLights; // && !gCubeSnapshot;
if (render_local)
{
@@ -8587,9 +8307,12 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
LLDrawable::drawable_list_t spot_lights;
LLDrawable::drawable_list_t fullscreen_spot_lights;
- for (U32 i = 0; i < 2; i++)
+ if (!gCubeSnapshot)
{
- mTargetShadowSpotLight[i] = NULL;
+ for (U32 i = 0; i < 2; i++)
+ {
+ mTargetShadowSpotLight[i] = NULL;
+ }
}
std::list<LLVector4> light_colors;
@@ -8598,14 +8321,15 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
{
LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("renderDeferredLighting - local lights");
+ LL_PROFILE_GPU_ZONE("local lights");
bindDeferredShader(gDeferredLightProgram);
if (mCubeVB.isNull())
{
- mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX, GL_STATIC_DRAW_ARB);
+ mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX);
}
- mCubeVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+ mCubeVB->setBuffer();
LLGLDepthTest depth(GL_TRUE, GL_FALSE);
// mNearbyLights already includes distance calculation and excludes muted avatars.
@@ -8634,7 +8358,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
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)
{
@@ -8704,10 +8428,11 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
if (!spot_lights.empty())
{
LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("renderDeferredLighting - projectors");
+ LL_PROFILE_GPU_ZONE("projectors");
LLGLDepthTest depth(GL_TRUE, GL_FALSE);
bindDeferredShader(gDeferredSpotLightProgram);
- mCubeVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+ mCubeVB->setBuffer();
gDeferredSpotLightProgram.enableTexture(LLShaderMgr::DEFERRED_PROJECTION);
@@ -8727,7 +8452,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
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);
@@ -8741,22 +8466,10 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
unbindDeferredShader(gDeferredSpotLightProgram);
}
- // reset mDeferredVB to fullscreen triangle
- mDeferredVB->getVertexStrider(vert);
- vert[0].set(-1, 1, 0);
- vert[1].set(-1, -3, 0);
- vert[2].set(3, 1, 0);
-
{
LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("renderDeferredLighting - fullscreen lights");
LLGLDepthTest depth(GL_FALSE);
-
- // full screen blit
- gGL.pushMatrix();
- gGL.loadIdentity();
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.pushMatrix();
- gGL.loadIdentity();
+ LL_PROFILE_GPU_ZONE("fullscreen lights");
U32 count = 0;
@@ -8785,8 +8498,8 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
gDeferredMultiLightProgram[idx].uniform1f(LLShaderMgr::MULTI_LIGHT_FAR_Z, far_z);
far_z = 0.f;
count = 0;
- mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
- mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+ mScreenTriangleVB->setBuffer();
+ mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
unbindDeferredShader(gDeferredMultiLightProgram[idx]);
}
}
@@ -8795,7 +8508,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
gDeferredMultiSpotLightProgram.enableTexture(LLShaderMgr::DEFERRED_PROJECTION);
- mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+ mScreenTriangleVB->setBuffer();
for (LLDrawable::drawable_list_t::iterator iter = fullscreen_spot_lights.begin(); iter != fullscreen_spot_lights.end(); ++iter)
{
@@ -8814,90 +8527,32 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
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);
gDeferredMultiSpotLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV);
gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, light_falloff_final);
- mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+ mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
}
gDeferredMultiSpotLightProgram.disableTexture(LLShaderMgr::DEFERRED_PROJECTION);
unbindDeferredShader(gDeferredMultiSpotLightProgram);
-
- gGL.popMatrix();
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.popMatrix();
}
}
- gGL.setColorMask(true, true);
- }
-
- screen_target->flush();
- // gamma correct lighting
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.pushMatrix();
- gGL.loadIdentity();
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.pushMatrix();
- gGL.loadIdentity();
-
- {
- LLGLDepthTest depth(GL_FALSE, GL_FALSE);
-
- LLVector2 tc1(0, 0);
- LLVector2 tc2((F32) screen_target->getWidth() * 2, (F32) screen_target->getHeight() * 2);
-
- screen_target->bindTarget();
- // Apply gamma correction to the frame here.
- gDeferredPostGammaCorrectProgram.bind();
- // mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
- S32 channel = 0;
- channel = gDeferredPostGammaCorrectProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, screen_target->getUsage());
- if (channel > -1)
- {
- screen_target->bindTexture(0, channel, LLTexUnit::TFO_POINT);
- }
-
- gDeferredPostGammaCorrectProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, screen_target->getWidth(), screen_target->getHeight());
-
- F32 gamma = gSavedSettings.getF32("RenderDeferredDisplayGamma");
-
- 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();
-
- gGL.getTexUnit(channel)->unbind(screen_target->getUsage());
- gDeferredPostGammaCorrectProgram.unbind();
- screen_target->flush();
+ gGL.setColorMask(true, true);
}
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.popMatrix();
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.popMatrix();
-
- screen_target->bindTarget();
-
{ // render non-deferred geometry (alpha, fullbright, glow)
LLGLDisable blend(GL_BLEND);
- LLGLDisable stencil(GL_STENCIL_TEST);
+ //LLGLDisable stencil(GL_STENCIL_TEST);
pushRenderTypeMask();
andRenderTypeMask(LLPipeline::RENDER_TYPE_ALPHA,
+ LLPipeline::RENDER_TYPE_ALPHA_PRE_WATER,
+ LLPipeline::RENDER_TYPE_ALPHA_POST_WATER,
LLPipeline::RENDER_TYPE_FULLBRIGHT,
LLPipeline::RENDER_TYPE_VOLUME,
LLPipeline::RENDER_TYPE_GLOW,
@@ -8919,31 +8574,26 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
LLPipeline::RENDER_TYPE_CONTROL_AV,
LLPipeline::RENDER_TYPE_ALPHA_MASK,
LLPipeline::RENDER_TYPE_FULLBRIGHT_ALPHA_MASK,
+ LLPipeline::RENDER_TYPE_WATER,
END_RENDER_TYPES);
renderGeomPostDeferred(*LLViewerCamera::getInstance());
popRenderTypeMask();
}
- {
- // render highlights, etc.
- renderHighlights();
- mHighlightFaces.clear();
-
- renderDebug();
-
- LLVertexBuffer::unbind();
+ screen_target->flush();
- if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
+ 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++)
{
- // Render debugging beacons.
- gObjectList.renderObjectBeacons();
- gObjectList.resetObjectBeacons();
- gSky.addSunMoonBeacons();
+ gGLLastModelView[i] = gGLModelView[i];
+ gGLLastProjection[i] = gGLProjection[i];
}
}
-
- screen_target->flush();
+ gGL.setColorMask(true, true);
}
void LLPipeline::setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep)
@@ -9036,6 +8686,7 @@ void LLPipeline::setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep)
shader.uniform1f(LLShaderMgr::PROJECTOR_SHADOW_FADE, 1.f);
}
+ //if (!gCubeSnapshot)
{
LLDrawable* potential = drawablep;
//determine if this is a good light for casting shadows
@@ -9087,15 +8738,17 @@ void LLPipeline::setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep)
void LLPipeline::unbindDeferredShader(LLGLSLShader &shader)
{
- LLRenderTarget* deferred_target = &mDeferredScreen;
- LLRenderTarget* deferred_depth_target = &mDeferredDepth;
- LLRenderTarget* deferred_light_target = &mDeferredLight;
+ LLRenderTarget* deferred_target = &mRT->deferredScreen;
+ LLRenderTarget* deferred_light_target = &mRT->deferredLight;
stop_glerror();
shader.disableTexture(LLShaderMgr::DEFERRED_NORMAL, deferred_target->getUsage());
shader.disableTexture(LLShaderMgr::DEFERRED_DIFFUSE, deferred_target->getUsage());
shader.disableTexture(LLShaderMgr::DEFERRED_SPECULAR, deferred_target->getUsage());
- shader.disableTexture(LLShaderMgr::DEFERRED_DEPTH, deferred_depth_target->getUsage());
+ shader.disableTexture(LLShaderMgr::DEFERRED_EMISSIVE, deferred_target->getUsage());
+ shader.disableTexture(LLShaderMgr::DEFERRED_BRDF_LUT);
+ //shader.disableTexture(LLShaderMgr::DEFERRED_DEPTH, deferred_depth_target->getUsage());
+ shader.disableTexture(LLShaderMgr::DEFERRED_DEPTH, deferred_target->getUsage());
shader.disableTexture(LLShaderMgr::DEFERRED_LIGHT, deferred_light_target->getUsage());
shader.disableTexture(LLShaderMgr::DIFFUSE_MAP);
shader.disableTexture(LLShaderMgr::DEFERRED_BLOOM);
@@ -9104,7 +8757,7 @@ void LLPipeline::unbindDeferredShader(LLGLSLShader &shader)
{
if (shader.disableTexture(LLShaderMgr::DEFERRED_SHADOW0+i) > -1)
{
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
}
}
@@ -9112,366 +8765,93 @@ void LLPipeline::unbindDeferredShader(LLGLSLShader &shader)
{
if (shader.disableTexture(LLShaderMgr::DEFERRED_SHADOW0+i) > -1)
{
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
}
}
shader.disableTexture(LLShaderMgr::DEFERRED_NOISE);
shader.disableTexture(LLShaderMgr::DEFERRED_LIGHTFUNC);
- S32 channel = shader.disableTexture(LLShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
- if (channel > -1)
- {
- LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL;
- if (cube_map)
- {
- cube_map->disable();
- }
- }
+ if (!LLPipeline::sReflectionProbesEnabled)
+ {
+ S32 channel = shader.disableTexture(LLShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
+ if (channel > -1)
+ {
+ LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL;
+ if (cube_map)
+ {
+ cube_map->disable();
+ }
+ }
+ }
+
+ unbindReflectionProbes(shader);
+
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
gGL.getTexUnit(0)->activate();
shader.unbind();
}
-inline float sgn(float a)
+void LLPipeline::setEnvMat(LLGLSLShader& shader)
{
- if (a > 0.0F) return (1.0F);
- if (a < 0.0F) return (-1.0F);
- return (0.0F);
+ F32* m = gGLModelView;
+
+ F32 mat[] = { m[0], m[1], m[2],
+ m[4], m[5], m[6],
+ m[8], m[9], m[10] };
+
+ shader.uniformMatrix3fv(LLShaderMgr::DEFERRED_ENV_MAT, 1, TRUE, mat);
}
-void LLPipeline::generateWaterReflection(LLCamera& camera_in)
+void LLPipeline::bindReflectionProbes(LLGLSLShader& shader)
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
-
- if (!assertInitialized())
+ if (!sReflectionProbesEnabled)
{
return;
}
- if (LLPipeline::sWaterReflections && LLDrawPoolWater::sNeedsReflectionUpdate)
+ S32 channel = shader.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY);
+ bool bound = false;
+ if (channel > -1 && mReflectionMapManager.mTexture.notNull())
{
- //disable occlusion culling for reflection/refraction passes (save setting to restore later)
- S32 occlude = LLPipeline::sUseOcclusion;
- LLPipeline::sUseOcclusion = 0;
-
- bool skip_avatar_update = false;
- if (!isAgentAvatarValid() || gAgentCamera.getCameraAnimating() || gAgentCamera.getCameraMode() != CAMERA_MODE_MOUSELOOK || !LLVOAvatar::sVisibleInFirstPerson)
- {
- skip_avatar_update = true;
- }
-
- LLCamera camera = camera_in;
- camera.setFar(camera_in.getFar() * 0.75f);
-
- bool camera_is_underwater = LLViewerCamera::getInstance()->cameraUnderWater();
-
- LLPipeline::sReflectionRender = true;
-
- gPipeline.pushRenderTypeMask();
-
- glh::matrix4f saved_modelview = get_current_modelview();
- glh::matrix4f saved_projection = get_current_projection();
- glh::matrix4f mat;
-
- S32 reflection_detail = RenderReflectionDetail;
-
- F32 water_height = gAgent.getRegion()->getWaterHeight();
- F32 camera_height = camera_in.getOrigin().mV[VZ];
- F32 distance_to_water = (water_height < camera_height) ? (camera_height - water_height) : (water_height - camera_height);
-
- LLVector3 reflection_offset = LLVector3(0, 0, distance_to_water * 2.0f);
- LLVector3 camera_look_at = camera_in.getAtAxis();
- LLVector3 reflection_look_at = LLVector3(camera_look_at.mV[VX], camera_look_at.mV[VY], -camera_look_at.mV[VZ]);
- LLVector3 reflect_origin = camera_in.getOrigin() - reflection_offset;
- LLVector3 reflect_interest_point = reflect_origin + (reflection_look_at * 5.0f);
-
- camera.setOriginAndLookAt(reflect_origin, LLVector3::z_axis, reflect_interest_point);
-
- //plane params
- LLPlane plane;
- LLVector3 pnorm;
-
- if (camera_is_underwater)
- {
- //camera is below water, cull above water
- pnorm.setVec(0, 0, 1);
- }
- else
- {
- //camera is above water, cull below water
- pnorm = LLVector3(0, 0, -1);
- }
-
- plane.setVec(LLVector3(0, 0, water_height), pnorm);
-
- if (!camera_is_underwater)
- {
- //generate planar reflection map
- LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WATER0;
-
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.pushMatrix();
-
- mat.set_scale(glh::vec3f(1, 1, -1));
- mat.set_translate(glh::vec3f(0,0,water_height*2.f));
- mat = saved_modelview * mat;
-
-
- mReflectionModelView = mat;
-
- set_current_modelview(mat);
- gGL.loadMatrix(mat.m);
-
- LLViewerCamera::updateFrustumPlanes(camera, FALSE, TRUE);
-
- glh::vec3f origin(0, 0, 0);
- glh::matrix4f inv_mat = mat.inverse();
- inv_mat.mult_matrix_vec(origin);
-
- camera.setOrigin(origin.v);
-
- glCullFace(GL_FRONT);
-
- if (LLDrawPoolWater::sNeedsReflectionUpdate)
- {
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- glClearColor(0,0,0,0);
- mWaterRef.bindTarget();
-
- gGL.setColorMask(true, true);
- mWaterRef.clear();
- gGL.setColorMask(true, false);
- mWaterRef.getViewport(gGLViewport);
-
- //initial sky pass (no user clip plane)
- //mask out everything but the sky
- gPipeline.pushRenderTypeMask();
- {
- if (reflection_detail >= WATER_REFLECT_MINIMAL)
- {
- gPipeline.andRenderTypeMask(
- LLPipeline::RENDER_TYPE_SKY,
- LLPipeline::RENDER_TYPE_WL_SKY,
- LLPipeline::RENDER_TYPE_CLOUDS,
- LLPipeline::END_RENDER_TYPES);
- }
- else
- {
- gPipeline.andRenderTypeMask(
- LLPipeline::RENDER_TYPE_SKY,
- LLPipeline::RENDER_TYPE_WL_SKY,
- LLPipeline::END_RENDER_TYPES);
- }
-
- updateCull(camera, mSky);
- stateSort(camera, mSky);
- renderGeom(camera, TRUE);
- }
- gPipeline.popRenderTypeMask();
-
- if (reflection_detail >= WATER_REFLECT_NONE_WATER_TRANSPARENT)
- {
- gPipeline.pushRenderTypeMask();
- {
- clearRenderTypeMask(
- LLPipeline::RENDER_TYPE_WATER,
- LLPipeline::RENDER_TYPE_VOIDWATER,
- LLPipeline::RENDER_TYPE_GROUND,
- LLPipeline::RENDER_TYPE_SKY,
- LLPipeline::RENDER_TYPE_CLOUDS,
- LLPipeline::END_RENDER_TYPES);
-
- if (reflection_detail > WATER_REFLECT_MINIMAL)
- { //mask out selected geometry based on reflection detail
- if (reflection_detail < WATER_REFLECT_EVERYTHING)
- {
- clearRenderTypeMask(LLPipeline::RENDER_TYPE_PARTICLES, END_RENDER_TYPES);
- if (reflection_detail < WATER_REFLECT_AVATARS)
- {
- clearRenderTypeMask(
- LLPipeline::RENDER_TYPE_AVATAR,
- LLPipeline::RENDER_TYPE_CONTROL_AV,
- END_RENDER_TYPES);
- if (reflection_detail < WATER_REFLECT_STATIC_OBJECTS)
- {
- clearRenderTypeMask(LLPipeline::RENDER_TYPE_VOLUME, END_RENDER_TYPES);
- }
- }
- }
-
- LLGLUserClipPlane clip_plane(plane, mReflectionModelView, saved_projection);
- LLGLDisable cull(GL_CULL_FACE);
- updateCull(camera, mReflectedObjects, &plane);
- stateSort(camera, mReflectedObjects);
- renderGeom(camera);
- }
- }
- gPipeline.popRenderTypeMask();
- }
-
- mWaterRef.flush();
- }
-
- glCullFace(GL_BACK);
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.popMatrix();
-
- set_current_modelview(saved_modelview);
- }
-
- camera.setOrigin(camera_in.getOrigin());
- //render distortion map
- static bool last_update = true;
- if (last_update)
- {
- gPipeline.pushRenderTypeMask();
-
- camera.setFar(camera_in.getFar());
- clearRenderTypeMask(
- LLPipeline::RENDER_TYPE_WATER,
- LLPipeline::RENDER_TYPE_VOIDWATER,
- LLPipeline::RENDER_TYPE_GROUND,
- END_RENDER_TYPES);
-
- // intentionally inverted so that distortion map contents (objects under the water when we're above it)
- // will properly include water fog effects
- LLPipeline::sUnderWaterRender = !camera_is_underwater;
-
- if (LLPipeline::sUnderWaterRender)
- {
- clearRenderTypeMask(
- LLPipeline::RENDER_TYPE_GROUND,
- LLPipeline::RENDER_TYPE_SKY,
- LLPipeline::RENDER_TYPE_CLOUDS,
- LLPipeline::RENDER_TYPE_WL_SKY,
- END_RENDER_TYPES);
- }
- LLViewerCamera::updateFrustumPlanes(camera);
-
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-
- if (LLPipeline::sUnderWaterRender || LLDrawPoolWater::sNeedsDistortionUpdate)
- {
- LLPipeline::sDistortionRender = true;
-
- LLColor3 col = LLEnvironment::instance().getCurrentWater()->getWaterFogColor();
- glClearColor(col.mV[0], col.mV[1], col.mV[2], 0.f);
-
- // HACK FIX -- pretend underwater camera is the world camera to fix weird visibility artifacts
- // during distortion render (doesn't break main render because the camera is the same perspective
- // as world camera and occlusion culling is disabled for this pass)
- //LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WATER1;
- LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
-
- mWaterDis.bindTarget();
- mWaterDis.getViewport(gGLViewport);
-
- gGL.setColorMask(true, true);
- mWaterDis.clear();
- gGL.setColorMask(true, false);
-
- F32 water_dist = water_height;
-
- //clip out geometry on the same side of water as the camera w/ enough margin to not include the water geo itself,
- // but not so much as to clip out parts of avatars that should be seen under the water in the distortion map
- LLPlane plane;
-
- if (camera_is_underwater)
- {
- //nudge clip plane below water to avoid visible holes in objects intersecting water surface
- water_dist /= LLPipeline::sDistortionWaterClipPlaneMargin;
- //camera is below water, clip plane points up
- pnorm.setVec(0, 0, -1);
- }
- else
- {
- //nudge clip plane above water to avoid visible holes in objects intersecting water surface
- water_dist *= LLPipeline::sDistortionWaterClipPlaneMargin;
- //camera is above water, clip plane points down
- pnorm = LLVector3(0, 0, 1);
- }
-
- plane.setVec(LLVector3(0, 0, water_dist), pnorm);
-
- LLGLUserClipPlane clip_plane(plane, saved_modelview, saved_projection);
-
- gGL.setColorMask(true, true);
- mWaterDis.clear();
- gGL.setColorMask(true, false);
-
- if (reflection_detail >= WATER_REFLECT_NONE_WATER_TRANSPARENT)
- {
- updateCull(camera, mRefractedObjects, &plane);
- stateSort(camera, mRefractedObjects);
- renderGeom(camera);
- }
-
- gUIProgram.bind();
-
- LLWorld::getInstance()->renderPropertyLines();
-
- gUIProgram.unbind();
-
- mWaterDis.flush();
- }
-
- LLPipeline::sDistortionRender = false;
-
- gPipeline.popRenderTypeMask();
- }
- last_update = LLDrawPoolWater::sNeedsReflectionUpdate && LLDrawPoolWater::sNeedsDistortionUpdate;
-
- gPipeline.popRenderTypeMask();
-
- LLPipeline::sUnderWaterRender = false;
- LLPipeline::sReflectionRender = false;
+ mReflectionMapManager.mTexture->bind(channel);
+ bound = true;
+ }
- LLDrawPoolWater::sNeedsReflectionUpdate = FALSE;
- LLDrawPoolWater::sNeedsDistortionUpdate = FALSE;
+ channel = shader.enableTexture(LLShaderMgr::IRRADIANCE_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY);
+ if (channel > -1 && mReflectionMapManager.mIrradianceMaps.notNull())
+ {
+ mReflectionMapManager.mIrradianceMaps->bind(channel);
+ bound = true;
+ }
- if (!LLRenderTarget::sUseFBO)
- {
- glClear(GL_DEPTH_BUFFER_BIT);
- }
- glClearColor(0.f, 0.f, 0.f, 0.f);
- gViewerWindow->setup3DViewport();
+ if (bound)
+ {
+ mReflectionMapManager.setUniforms();
- LLGLState::checkStates();
+ setEnvMat(shader);
+ }
+}
- if (!skip_avatar_update)
+void LLPipeline::unbindReflectionProbes(LLGLSLShader& shader)
+{
+ S32 channel = shader.disableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP);
+ if (channel > -1 && mReflectionMapManager.mTexture.notNull())
+ {
+ mReflectionMapManager.mTexture->unbind();
+ if (channel == 0)
{
- gAgentAvatarp->updateAttachmentVisibility(gAgentCamera.getCameraMode());
+ gGL.getTexUnit(channel)->enable(LLTexUnit::TT_TEXTURE);
}
-
- LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
-
- // restore occlusion culling
- LLPipeline::sUseOcclusion = occlude;
}
- else
- {
- // Initial sky pass is still needed even if water reflection is not rendering
- bool camera_is_underwater = LLViewerCamera::getInstance()->cameraUnderWater();
- if (!camera_is_underwater)
- {
- gPipeline.pushRenderTypeMask();
- {
- gPipeline.andRenderTypeMask(
- LLPipeline::RENDER_TYPE_SKY,
- LLPipeline::RENDER_TYPE_WL_SKY,
- LLPipeline::END_RENDER_TYPES);
+}
- LLCamera camera = camera_in;
- camera.setFar(camera_in.getFar() * 0.75f);
- updateCull(camera, mSky);
- stateSort(camera, mSky);
- renderGeom(camera, TRUE);
- }
- gPipeline.popRenderTypeMask();
- }
- }
+inline float sgn(float a)
+{
+ if (a > 0.0F) return (1.0F);
+ if (a < 0.0F) return (-1.0F);
+ return (0.0F);
}
glh::matrix4f look(const LLVector3 pos, const LLVector3 dir, const LLVector3 up)
@@ -9551,24 +8931,23 @@ 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);
-
- //disable occlusion culling for shadow passes (save setting to restore later)
- S32 occlude = LLPipeline::sUseOcclusion;
- if (!use_occlusion)
- {
- LLPipeline::sUseOcclusion = 0;
- }
+ LL_PROFILE_GPU_ZONE("renderShadow");
+
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,
@@ -9577,27 +8956,20 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera
LLRenderPass::PASS_NORMMAP_EMISSIVE,
LLRenderPass::PASS_NORMSPEC,
LLRenderPass::PASS_NORMSPEC_EMISSIVE,
+ LLRenderPass::PASS_GLTF_PBR
};
LLGLEnable cull(GL_CULL_FACE);
//enable depth clamping if available
- LLGLEnable depth_clamp(gGLManager.mHasDepthClamp ? GL_DEPTH_CLAMP : 0);
-
- if (use_shader)
- {
- gDeferredShadowCubeProgram.bind();
- }
+ LLGLEnable clamp_depth(depth_clamp ? GL_DEPTH_CLAMP : 0);
- LLRenderTarget& occlusion_target = mShadowOcclusion[LLViewerCamera::sCurCameraID - 1];
+ LLGLDepthTest depth_test(GL_TRUE, GL_TRUE, GL_LESS);
- occlusion_target.bindTarget();
updateCull(shadow_cam, result);
- occlusion_target.flush();
stateSort(shadow_cam, result);
-
//generate shadow map
gGL.matrixMode(LLRender::MM_PROJECTION);
gGL.pushMatrix();
@@ -9615,20 +8987,21 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera
LLEnvironment& environment = LLEnvironment::instance();
- LLVertexBuffer::unbind();
+ struct CompareVertexBuffer
+ {
+ bool operator()(const LLDrawInfo* const& lhs, const LLDrawInfo* const& rhs)
+ {
+ return lhs->mVertexBuffer > rhs->mVertexBuffer;
+ }
+ };
+
+ LLVertexBuffer::unbind();
for (int j = 0; j < 2; ++j) // 0 -- static, 1 -- rigged
{
bool rigged = j == 1;
- if (!use_shader)
- { //occlusion program is general purpose depth-only no-textures
- gOcclusionProgram.bind(rigged);
- }
- else
- {
- gDeferredShadowProgram.bind(rigged);
- LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0);
- }
+ gDeferredShadowProgram.bind(rigged);
+ LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0);
gGL.diffuseColor4f(1, 1, 1, 1);
@@ -9641,39 +9014,40 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera
}
LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("shadow simple"); //LL_RECORD_BLOCK_TIME(FTM_SHADOW_SIMPLE);
-
+ LL_PROFILE_GPU_ZONE("shadow simple");
gGL.getTexUnit(0)->disable();
- for (U32 i = 0; i < sizeof(types) / sizeof(U32); ++i)
- {
- renderObjects(types[i], LLVertexBuffer::MAP_VERTEX, FALSE, FALSE, rigged);
- }
- gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
- if (!use_shader)
+
+ for (U32 type : types)
{
- gOcclusionProgram.unbind();
+ if (rigged)
+ {
+ renderObjects(type, false, false, rigged);
+ }
+ else
+ {
+ renderShadowSimple(type);
+ }
}
+ gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
+ }
+ 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"); //LL_RECORD_BLOCK_TIME(FTM_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"); //LL_RECORD_BLOCK_TIME(FTM_SHADOW_GEOM);
-
+ LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("shadow geom");
renderGeomShadow(shadow_cam);
}
{
- LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("shadow alpha"); //LL_RECORD_BLOCK_TIME(FTM_SHADOW_ALPHA);
+ 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)
{
@@ -9683,65 +9057,79 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera
LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH, (float)target_width);
LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0);
- U32 mask = LLVertexBuffer::MAP_VERTEX |
- LLVertexBuffer::MAP_TEXCOORD0 |
- LLVertexBuffer::MAP_COLOR |
- LLVertexBuffer::MAP_TEXTURE_INDEX;
-
{
- LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("shadow alpha masked"); //LL_RECORD_BLOCK_TIME(FTM_SHADOW_ALPHA_MASKED);
- renderMaskedObjects(LLRenderPass::PASS_ALPHA_MASK, mask, TRUE, TRUE, rigged);
+ LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("shadow alpha masked");
+ LL_PROFILE_GPU_ZONE("shadow alpha masked");
+ renderMaskedObjects(LLRenderPass::PASS_ALPHA_MASK, true, true, rigged);
}
{
- LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("shadow alpha blend"); //LL_RECORD_BLOCK_TIME(FTM_SHADOW_ALPHA_BLEND);
+ LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("shadow alpha blend");
+ LL_PROFILE_GPU_ZONE("shadow alpha blend");
LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(0.598f);
- renderAlphaObjects(mask, TRUE, TRUE, rigged);
+ renderAlphaObjects(true, true, rigged);
}
-
{
- LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("shadow fullbright alpha masked"); //LL_RECORD_BLOCK_TIME(FTM_SHADOW_FULLBRIGHT_ALPHA_MASKED);
+ LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("shadow fullbright alpha masked");
+ LL_PROFILE_GPU_ZONE("shadow alpha masked");
gDeferredShadowFullbrightAlphaMaskProgram.bind(rigged);
LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH, (float)target_width);
LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0);
- renderFullbrightMaskedObjects(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, mask, TRUE, TRUE, rigged);
+ renderFullbrightMaskedObjects(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, true, true, rigged);
}
-
{
- LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("shadow alpha grass"); //LL_RECORD_BLOCK_TIME(FTM_SHADOW_ALPHA_GRASS);
+ LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("shadow alpha grass");
+ LL_PROFILE_GPU_ZONE("shadow alpha grass");
gDeferredTreeShadowProgram.bind(rigged);
if (i == 0)
{
LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(0.598f);
- renderObjects(LLRenderPass::PASS_GRASS, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, TRUE);
+ renderObjects(LLRenderPass::PASS_GRASS, true);
}
- U32 no_idx_mask = mask & ~LLVertexBuffer::MAP_TEXTURE_INDEX;
- renderMaskedObjects(LLRenderPass::PASS_NORMSPEC_MASK, no_idx_mask, true, false, rigged);
- renderMaskedObjects(LLRenderPass::PASS_MATERIAL_ALPHA_MASK, no_idx_mask, true, false, rigged);
- renderMaskedObjects(LLRenderPass::PASS_SPECMAP_MASK, no_idx_mask, true, false, rigged);
- renderMaskedObjects(LLRenderPass::PASS_NORMMAP_MASK, no_idx_mask, true, false, rigged);
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("shadow alpha material");
+ LL_PROFILE_GPU_ZONE("shadow alpha material");
+ renderMaskedObjects(LLRenderPass::PASS_NORMSPEC_MASK, true, false, rigged);
+ renderMaskedObjects(LLRenderPass::PASS_MATERIAL_ALPHA_MASK, true, false, rigged);
+ renderMaskedObjects(LLRenderPass::PASS_SPECMAP_MASK, true, false, rigged);
+ renderMaskedObjects(LLRenderPass::PASS_NORMMAP_MASK, true, false, rigged);
+ }
}
}
- }
-
- //glCullFace(GL_BACK);
- gDeferredShadowCubeProgram.bind();
- gGLLastMatrix = NULL;
- gGL.loadMatrix(gGLModelView);
+ for (int i = 0; i < 2; ++i)
+ {
+ bool rigged = i == 1;
+ gDeferredShadowGLTFAlphaMaskProgram.bind(rigged);
+ LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH, (float)target_width);
+ LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0);
+
+ gGL.loadMatrix(gGLModelView);
+ gGLLastMatrix = NULL;
- LLRenderTarget& occlusion_source = mShadow[LLViewerCamera::sCurCameraID - 1];
+ U32 type = LLRenderPass::PASS_GLTF_PBR_ALPHA_MASK;
- doOcclusion(shadow_cam, occlusion_source, occlusion_target);
+ if (rigged)
+ {
+ mAlphaMaskPool->pushRiggedGLTFBatches(type + 1);
+ }
+ else
+ {
+ mAlphaMaskPool->pushGLTFBatches(type);
+ }
- if (use_shader)
- {
- gDeferredShadowProgram.unbind();
+ gGL.loadMatrix(gGLModelView);
+ gGLLastMatrix = NULL;
+ }
}
+ gDeferredShadowCubeProgram.bind();
+ gGLLastMatrix = NULL;
+ gGL.loadMatrix(gGLModelView);
+
gGL.setColorMask(true, true);
gGL.matrixMode(LLRender::MM_PROJECTION);
@@ -9750,7 +9138,8 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera
gGL.popMatrix();
gGLLastMatrix = NULL;
- LLPipeline::sUseOcclusion = occlude;
+ // reset occlusion culling flag
+ sUseOcclusion = saved_occlusion;
LLPipeline::sShadowRender = false;
}
@@ -9949,64 +9338,17 @@ void LLPipeline::renderHighlight(const LLViewerObject* obj, F32 fade)
}
}
-void LLPipeline::generateHighlight(LLCamera& camera)
-{
- //render highlighted object as white into offscreen render target
- if (mHighlightObject.notNull())
- {
- mHighlightSet.insert(HighlightItem(mHighlightObject));
- }
-
- if (!mHighlightSet.empty())
- {
- F32 transition = gFrameIntervalSeconds.value()/RenderHighlightFadeTime;
-
- LLGLDisable test(GL_ALPHA_TEST);
- LLGLDepthTest depth(GL_FALSE);
- mHighlight.bindTarget();
- disableLights();
- gGL.setColorMask(true, true);
- mHighlight.clear();
-
- gHighlightProgram.bind();
-
- gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep);
- for (std::set<HighlightItem>::iterator iter = mHighlightSet.begin(); iter != mHighlightSet.end(); )
- {
- std::set<HighlightItem>::iterator cur_iter = iter++;
- if (cur_iter->mItem.isNull())
- {
- mHighlightSet.erase(cur_iter);
- continue;
- }
-
- if (cur_iter->mItem == mHighlightObject)
- {
- cur_iter->incrFade(transition);
- }
- else
- {
- cur_iter->incrFade(-transition);
- if (cur_iter->mFade <= 0.f)
- {
- mHighlightSet.erase(cur_iter);
- continue;
- }
- }
-
- renderHighlight(cur_iter->mItem->getVObj(), cur_iter->mFade);
- }
-
- mHighlight.flush();
- gGL.setColorMask(true, false);
- gViewerWindow->setup3DViewport();
- }
+LLRenderTarget* LLPipeline::getSunShadowTarget(U32 i)
+{
+ llassert(i < 4);
+ return &mRT->shadow[i];
}
-LLRenderTarget* LLPipeline::getShadowTarget(U32 i)
+LLRenderTarget* LLPipeline::getSpotShadowTarget(U32 i)
{
- return &mShadow[i];
+ llassert(i < 2);
+ return &mSpotShadow[i];
}
static LLTrace::BlockTimerStatHandle FTM_GEN_SUN_SHADOW("Gen Sun Shadow");
@@ -10020,11 +9362,11 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
}
LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; //LL_RECORD_BLOCK_TIME(FTM_GEN_SUN_SHADOW);
+ LL_PROFILE_GPU_ZONE("generateSunShadow");
bool skip_avatar_update = false;
if (!isAgentAvatarValid() || gAgentCamera.getCameraAnimating() || gAgentCamera.getCameraMode() != CAMERA_MODE_MOUSELOOK || !LLVOAvatar::sVisibleInFirstPerson)
{
-
skip_avatar_update = true;
}
@@ -10044,7 +9386,10 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
pushRenderTypeMask();
andRenderTypeMask(LLPipeline::RENDER_TYPE_SIMPLE,
LLPipeline::RENDER_TYPE_ALPHA,
+ LLPipeline::RENDER_TYPE_ALPHA_PRE_WATER,
+ LLPipeline::RENDER_TYPE_ALPHA_POST_WATER,
LLPipeline::RENDER_TYPE_GRASS,
+ LLPipeline::RENDER_TYPE_GLTF_PBR,
LLPipeline::RENDER_TYPE_FULLBRIGHT,
LLPipeline::RENDER_TYPE_BUMP,
LLPipeline::RENDER_TYPE_VOLUME,
@@ -10102,6 +9447,10 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
LLPipeline::RENDER_TYPE_PASS_NORMSPEC_BLEND_RIGGED,
LLPipeline::RENDER_TYPE_PASS_NORMSPEC_MASK_RIGGED,
LLPipeline::RENDER_TYPE_PASS_NORMSPEC_EMISSIVE_RIGGED,
+ LLPipeline::RENDER_TYPE_PASS_GLTF_PBR,
+ LLPipeline::RENDER_TYPE_PASS_GLTF_PBR_RIGGED,
+ LLPipeline::RENDER_TYPE_PASS_GLTF_PBR_ALPHA_MASK,
+ LLPipeline::RENDER_TYPE_PASS_GLTF_PBR_ALPHA_MASK_RIGGED,
END_RENDER_TYPES);
gGL.setColorMask(false, false);
@@ -10247,28 +9596,41 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
// convenience array of 4 near clip plane distances
F32 dist[] = { near_clip, mSunClipPlanes.mV[0], mSunClipPlanes.mV[1], mSunClipPlanes.mV[2], mSunClipPlanes.mV[3] };
-
if (mSunDiffuse == LLColor4::black)
- { //sun diffuse is totally black, shadows don't matter
+ { //sun diffuse is totally shadows don't matter
LLGLDepthTest depth(GL_TRUE);
for (S32 j = 0; j < 4; j++)
{
- mShadow[j].bindTarget();
- mShadow[j].clear();
- mShadow[j].flush();
+ mRT->shadow[j].bindTarget();
+ mRT->shadow[j].clear();
+ mRT->shadow[j].flush();
}
}
else
{
- for (S32 j = 0; j < 4; j++)
+ /*if (gCubeSnapshot)
+ {
+ // do one shadow split for cube snapshots, clear the rest
+ mSunClipPlanes.set(64.f, 64.f, 64.f);
+ dist[1] = dist[2] = dist[3] = dist[4] = 64.f;
+ for (S32 j = 1; j < 4; j++)
+ {
+ mRT->shadow[j].bindTarget();
+ mRT->shadow[j].clear();
+ mRT->shadow[j].flush();
+ }
+ }*/
+
+ //for (S32 j = 0; j < (gCubeSnapshot ? 1 : 4); j++)
+ for (S32 j = 0; j < 4; j++)
{
if (!hasRenderDebugMask(RENDER_DEBUG_SHADOW_FRUSTA))
{
mShadowFrustPoints[j].clear();
}
- LLViewerCamera::sCurCameraID = (LLViewerCamera::eCameraID)(LLViewerCamera::CAMERA_SHADOW0+j);
+ LLViewerCamera::sCurCameraID = (LLViewerCamera::eCameraID)(LLViewerCamera::CAMERA_SUN_SHADOW0+j);
//restore render matrices
set_current_modelview(saved_view);
@@ -10322,12 +9684,12 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
mShadowCamera[j+4] = shadow_cam;
}
- mShadow[j].bindTarget();
+ mRT->shadow[j].bindTarget();
{
LLGLDepthTest depth(GL_TRUE);
- mShadow[j].clear();
+ mRT->shadow[j].clear();
}
- mShadow[j].flush();
+ mRT->shadow[j].flush();
mShadowError.mV[j] = 0.f;
mShadowFOV.mV[j] = 0.f;
@@ -10614,18 +9976,16 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
stop_glerror();
- mShadow[j].bindTarget();
- mShadow[j].getViewport(gGLViewport);
- mShadow[j].clear();
+ mRT->shadow[j].bindTarget();
+ mRT->shadow[j].getViewport(gGLViewport);
+ mRT->shadow[j].clear();
- U32 target_width = mShadow[j].getWidth();
-
{
static LLCullResult result[4];
- renderShadow(view[j], proj[j], shadow_cam, result[j], TRUE, FALSE, target_width);
+ renderShadow(view[j], proj[j], shadow_cam, result[j], true);
}
- mShadow[j].flush();
+ mRT->shadow[j].flush();
if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
{
@@ -10640,142 +10000,148 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
if (gen_shadow)
{
- LLTrace::CountStatHandle<>* velocity_stat = LLViewerCamera::getVelocityStat();
- F32 fade_amt = gFrameIntervalSeconds.value()
- * llmax(LLTrace::get_frame_recording().getLastRecording().getSum(*velocity_stat) / LLTrace::get_frame_recording().getLastRecording().getDuration().value(), 1.0);
+ if (!gCubeSnapshot) //skip updating spot shadow maps during cubemap updates
+ {
+ LLTrace::CountStatHandle<>* velocity_stat = LLViewerCamera::getVelocityStat();
+ F32 fade_amt = gFrameIntervalSeconds.value()
+ * llmax(LLTrace::get_frame_recording().getLastRecording().getSum(*velocity_stat) / LLTrace::get_frame_recording().getLastRecording().getDuration().value(), 1.0);
- //update shadow targets
- for (U32 i = 0; i < 2; i++)
- { //for each current shadow
- LLViewerCamera::sCurCameraID = (LLViewerCamera::eCameraID)(LLViewerCamera::CAMERA_SHADOW4+i);
+ //update shadow targets
+ for (U32 i = 0; i < 2; i++)
+ { //for each current shadow
+ LLViewerCamera::sCurCameraID = (LLViewerCamera::eCameraID)(LLViewerCamera::CAMERA_SPOT_SHADOW0 + i);
+
+ if (mShadowSpotLight[i].notNull() &&
+ (mShadowSpotLight[i] == mTargetShadowSpotLight[0] ||
+ mShadowSpotLight[i] == mTargetShadowSpotLight[1]))
+ { //keep this spotlight
+ mSpotLightFade[i] = llmin(mSpotLightFade[i] + fade_amt, 1.f);
+ }
+ else
+ { //fade out this light
+ mSpotLightFade[i] = llmax(mSpotLightFade[i] - fade_amt, 0.f);
- if (mShadowSpotLight[i].notNull() &&
- (mShadowSpotLight[i] == mTargetShadowSpotLight[0] ||
- mShadowSpotLight[i] == mTargetShadowSpotLight[1]))
- { //keep this spotlight
- mSpotLightFade[i] = llmin(mSpotLightFade[i]+fade_amt, 1.f);
- }
- else
- { //fade out this light
- mSpotLightFade[i] = llmax(mSpotLightFade[i]-fade_amt, 0.f);
-
- if (mSpotLightFade[i] == 0.f || mShadowSpotLight[i].isNull())
- { //faded out, grab one of the pending spots (whichever one isn't already taken)
- if (mTargetShadowSpotLight[0] != mShadowSpotLight[(i+1)%2])
- {
- mShadowSpotLight[i] = mTargetShadowSpotLight[0];
- }
- else
- {
- mShadowSpotLight[i] = mTargetShadowSpotLight[1];
- }
- }
- }
- }
+ if (mSpotLightFade[i] == 0.f || mShadowSpotLight[i].isNull())
+ { //faded out, grab one of the pending spots (whichever one isn't already taken)
+ if (mTargetShadowSpotLight[0] != mShadowSpotLight[(i + 1) % 2])
+ {
+ mShadowSpotLight[i] = mTargetShadowSpotLight[0];
+ }
+ else
+ {
+ mShadowSpotLight[i] = mTargetShadowSpotLight[1];
+ }
+ }
+ }
+ }
+ }
- for (S32 i = 0; i < 2; i++)
- {
- set_current_modelview(saved_view);
- set_current_projection(saved_proj);
+ for (S32 i = 0; i < 2; i++)
+ {
+ set_current_modelview(saved_view);
+ set_current_projection(saved_proj);
- if (mShadowSpotLight[i].isNull())
- {
- continue;
- }
+ if (mShadowSpotLight[i].isNull())
+ {
+ continue;
+ }
- LLVOVolume* volume = mShadowSpotLight[i]->getVOVolume();
+ LLVOVolume* volume = mShadowSpotLight[i]->getVOVolume();
- if (!volume)
- {
- mShadowSpotLight[i] = NULL;
- continue;
- }
+ if (!volume)
+ {
+ mShadowSpotLight[i] = NULL;
+ continue;
+ }
- LLDrawable* drawable = mShadowSpotLight[i];
+ LLDrawable* drawable = mShadowSpotLight[i];
- LLVector3 params = volume->getSpotLightParams();
- F32 fov = params.mV[0];
+ LLVector3 params = volume->getSpotLightParams();
+ F32 fov = params.mV[0];
- //get agent->light space matrix (modelview)
- LLVector3 center = drawable->getPositionAgent();
- LLQuaternion quat = volume->getRenderRotation();
+ //get agent->light space matrix (modelview)
+ LLVector3 center = drawable->getPositionAgent();
+ LLQuaternion quat = volume->getRenderRotation();
- //get near clip plane
- LLVector3 scale = volume->getScale();
- LLVector3 at_axis(0,0,-scale.mV[2]*0.5f);
- at_axis *= quat;
+ //get near clip plane
+ LLVector3 scale = volume->getScale();
+ LLVector3 at_axis(0, 0, -scale.mV[2] * 0.5f);
+ at_axis *= quat;
- LLVector3 np = center+at_axis;
- at_axis.normVec();
+ LLVector3 np = center + at_axis;
+ at_axis.normVec();
- //get origin that has given fov for plane np, at_axis, and given scale
- F32 dist = (scale.mV[1]*0.5f)/tanf(fov*0.5f);
+ //get origin that has given fov for plane np, at_axis, and given scale
+ F32 dist = (scale.mV[1] * 0.5f) / tanf(fov * 0.5f);
- LLVector3 origin = np - at_axis*dist;
+ LLVector3 origin = np - at_axis * dist;
- LLMatrix4 mat(quat, LLVector4(origin, 1.f));
+ LLMatrix4 mat(quat, LLVector4(origin, 1.f));
- view[i+4] = glh::matrix4f((F32*) mat.mMatrix);
+ view[i + 4] = glh::matrix4f((F32*)mat.mMatrix);
- view[i+4] = view[i+4].inverse();
+ view[i + 4] = view[i + 4].inverse();
- //get perspective matrix
- F32 near_clip = dist+0.01f;
- F32 width = scale.mV[VX];
- F32 height = scale.mV[VY];
- F32 far_clip = dist+volume->getLightRadius()*1.5f;
+ //get perspective matrix
+ F32 near_clip = dist + 0.01f;
+ F32 width = scale.mV[VX];
+ F32 height = scale.mV[VY];
+ F32 far_clip = dist + volume->getLightRadius() * 1.5f;
- F32 fovy = fov * RAD_TO_DEG;
- F32 aspect = width/height;
-
- proj[i+4] = gl_perspective(fovy, aspect, near_clip, far_clip);
+ F32 fovy = fov * RAD_TO_DEG;
+ F32 aspect = width / height;
- //translate and scale to from [-1, 1] to [0, 1]
- glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f,
- 0.f, 0.5f, 0.f, 0.5f,
- 0.f, 0.f, 0.5f, 0.5f,
- 0.f, 0.f, 0.f, 1.f);
+ proj[i + 4] = gl_perspective(fovy, aspect, near_clip, far_clip);
- set_current_modelview(view[i+4]);
- set_current_projection(proj[i+4]);
+ //translate and scale to from [-1, 1] to [0, 1]
+ glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f,
+ 0.f, 0.5f, 0.f, 0.5f,
+ 0.f, 0.f, 0.5f, 0.5f,
+ 0.f, 0.f, 0.f, 1.f);
- mSunShadowMatrix[i+4] = trans*proj[i+4]*view[i+4]*inv_view;
-
- for (U32 j = 0; j < 16; j++)
- {
- gGLLastModelView[j] = mShadowModelview[i+4].m[j];
- gGLLastProjection[j] = mShadowProjection[i+4].m[j];
- }
+ set_current_modelview(view[i + 4]);
+ set_current_projection(proj[i + 4]);
- mShadowModelview[i+4] = view[i+4];
- mShadowProjection[i+4] = proj[i+4];
+ mSunShadowMatrix[i + 4] = trans * proj[i + 4] * view[i + 4] * inv_view;
- LLCamera shadow_cam = camera;
- shadow_cam.setFar(far_clip);
- shadow_cam.setOrigin(origin);
+ for (U32 j = 0; j < 16; j++)
+ {
+ gGLLastModelView[j] = mShadowModelview[i + 4].m[j];
+ gGLLastProjection[j] = mShadowProjection[i + 4].m[j];
+ }
- LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE);
+ mShadowModelview[i + 4] = view[i + 4];
+ mShadowProjection[i + 4] = proj[i + 4];
- stop_glerror();
+ if (!gCubeSnapshot) //skip updating spot shadow maps during cubemap updates
+ {
+ LLCamera shadow_cam = camera;
+ shadow_cam.setFar(far_clip);
+ shadow_cam.setOrigin(origin);
+
+ LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE);
- mShadow[i+4].bindTarget();
- mShadow[i+4].getViewport(gGLViewport);
- mShadow[i+4].clear();
+ stop_glerror();
- U32 target_width = mShadow[i+4].getWidth();
+ //
+
+ mSpotShadow[i].bindTarget();
+ mSpotShadow[i].getViewport(gGLViewport);
+ mSpotShadow[i].clear();
- static LLCullResult result[2];
+ static LLCullResult result[2];
- LLViewerCamera::sCurCameraID = (LLViewerCamera::eCameraID)(LLViewerCamera::CAMERA_SHADOW0 + i + 4);
+ LLViewerCamera::sCurCameraID = (LLViewerCamera::eCameraID)(LLViewerCamera::CAMERA_SPOT_SHADOW0 + i);
- RenderSpotLight = drawable;
+ RenderSpotLight = drawable;
- renderShadow(view[i+4], proj[i+4], shadow_cam, result[i], FALSE, FALSE, target_width);
+ renderShadow(view[i + 4], proj[i + 4], shadow_cam, result[i], false);
- RenderSpotLight = nullptr;
+ RenderSpotLight = nullptr;
- mShadow[i+4].flush();
- }
+ mSpotShadow[i].flush();
+ }
+ }
}
else
{ //no spotlight shadows
@@ -10797,7 +10163,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
gGL.loadMatrix(proj[1].m);
gGL.matrixMode(LLRender::MM_MODELVIEW);
}
- gGL.setColorMask(true, false);
+ gGL.setColorMask(true, true);
for (U32 i = 0; i < 16; i++)
{
@@ -10813,7 +10179,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
}
}
-void LLPipeline::renderGroups(LLRenderPass* pass, U32 type, U32 mask, bool texture)
+void LLPipeline::renderGroups(LLRenderPass* pass, U32 type, bool texture)
{
for (LLCullResult::sg_iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i)
{
@@ -10823,12 +10189,12 @@ void LLPipeline::renderGroups(LLRenderPass* pass, U32 type, U32 mask, bool textu
gPipeline.hasRenderType(group->getSpatialPartition()->mDrawableType) &&
group->mDrawMap.find(type) != group->mDrawMap.end())
{
- pass->renderGroup(group,type,mask,texture);
+ pass->renderGroup(group,type,texture);
}
}
}
-void LLPipeline::renderRiggedGroups(LLRenderPass* pass, U32 type, U32 mask, bool texture)
+void LLPipeline::renderRiggedGroups(LLRenderPass* pass, U32 type, bool texture)
{
for (LLCullResult::sg_iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i)
{
@@ -10838,7 +10204,7 @@ void LLPipeline::renderRiggedGroups(LLRenderPass* pass, U32 type, U32 mask, bool
gPipeline.hasRenderType(group->getSpatialPartition()->mDrawableType) &&
group->mDrawMap.find(type) != group->mDrawMap.end())
{
- pass->renderRiggedGroup(group, type, mask, texture);
+ pass->renderRiggedGroup(group, type, texture);
}
}
}
@@ -10848,8 +10214,8 @@ static LLTrace::BlockTimerStatHandle FTM_GENERATE_IMPOSTOR("Generate Impostor");
void LLPipeline::generateImpostor(LLVOAvatar* avatar, bool preview_avatar)
{
LL_RECORD_BLOCK_TIME(FTM_GENERATE_IMPOSTOR);
+ LL_PROFILE_GPU_ZONE("generateImpostor");
LLGLState::checkStates();
- LLGLState::checkTextureChannels();
static LLCullResult result;
result.clear();
@@ -11046,7 +10412,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)
{
@@ -11075,17 +10441,10 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar, bool preview_avatar)
if (preview_avatar)
{
// previews don't care about imposters
- if (LLPipeline::sRenderDeferred)
- {
- renderGeomDeferred(camera);
- renderGeomPostDeferred(camera);
- }
- else
- {
- renderGeom(camera);
- }
+ renderGeomDeferred(camera);
+ renderGeomPostDeferred(camera);
}
- else if (LLPipeline::sRenderDeferred)
+ else
{
avatar->mImpostor.clear();
renderGeomDeferred(camera);
@@ -11107,28 +10466,6 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar, bool preview_avatar)
sImpostorRenderAlphaDepthPass = false;
}
- else
- {
- LLGLEnable scissor(GL_SCISSOR_TEST);
- glScissor(0, 0, resX, resY);
- avatar->mImpostor.clear();
- renderGeom(camera);
-
- // Shameless hack time: render it all again,
- // this time writing the depth
- // values we need to generate the alpha mask below
- // while preserving the alpha-sorted color rendering
- // from the previous pass
- //
- sImpostorRenderAlphaDepthPass = true;
-
- // depth-only here...
- //
- gGL.setColorMask(false,false);
- renderGeom(camera);
-
- sImpostorRenderAlphaDepthPass = false;
- }
LLDrawPoolAvatar::sMinimumAlpha = old_alpha;
@@ -11136,8 +10473,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar, bool preview_avatar)
if (LLPipeline::sRenderDeferred)
{
GLuint buff = GL_COLOR_ATTACHMENT0;
- LL_PROFILER_GPU_ZONEC( "gl.DrawBuffersARB", 0x8000FF );
- glDrawBuffersARB(1, &buff);
+ glDrawBuffers(1, &buff);
}
LLGLDisable blend(GL_BLEND);
@@ -11220,7 +10556,6 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar, bool preview_avatar)
LLVertexBuffer::unbind();
LLGLState::checkStates();
- LLGLState::checkTextureChannels();
}
bool LLPipeline::hasRenderBatches(const U32 type) const
@@ -11537,3 +10872,9 @@ void LLPipeline::restoreHiddenObject( const LLUUID& id )
}
}
+void LLPipeline::overrideEnvironmentMap()
+{
+ //mReflectionMapManager.mProbes.clear();
+ //mReflectionMapManager.addProbe(LLViewerCamera::instance().getOrigin());
+}
+
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index 0830d4a2ea..5b80ae5696 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -38,6 +38,7 @@
#include "llgl.h"
#include "lldrawable.h"
#include "llrendertarget.h"
+#include "llreflectionmapmanager.h"
#include <stack>
@@ -50,6 +51,7 @@ class LLVOAvatar;
class LLVOPartGroup;
class LLGLSLShader;
class LLDrawPoolAlpha;
+class LLSettingsSky;
typedef enum e_avatar_skinning_method
{
@@ -131,12 +133,12 @@ public:
bool allocateScreenBuffer(U32 resX, U32 resY, U32 samples);
bool allocateShadowBuffer(U32 resX, U32 resY);
- void allocatePhysicsBuffer();
-
void resetVertexBuffers(LLDrawable* drawable);
void generateImpostor(LLVOAvatar* avatar, bool preview_avatar = false);
void bindScreenToTexture();
void renderFinalize();
+ void renderPostProcess();
+ LLRenderTarget* screenTarget();
void init();
void cleanup();
@@ -171,7 +173,6 @@ public:
// if source's depth buffer cannot be bound for reading, a scratch space depth buffer must be provided
void downsampleDepthBuffer(LLRenderTarget& source, LLRenderTarget& dest, LLRenderTarget* scratch_space = NULL);
- void doOcclusion(LLCamera& camera, LLRenderTarget& source, LLRenderTarget& dest, LLRenderTarget* scratch_space = NULL);
void doOcclusion(LLCamera& camera);
void markNotCulled(LLSpatialGroup* group, LLCamera &camera);
void markMoved(LLDrawable *drawablep, bool damped_motion = false);
@@ -187,6 +188,7 @@ public:
LLViewerObject* lineSegmentIntersectInWorld(const LLVector4a& start, const LLVector4a& end,
bool pick_transparent,
bool pick_rigged,
+ bool pick_unselectable,
S32* face_hit, // return the face hit
LLVector4a* intersection = NULL, // return the intersection point
LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point
@@ -216,8 +218,9 @@ public:
U32 addObject(LLViewerObject *obj);
void enableShadows(const bool enable_shadows);
- void releaseShadowTargets();
- void releaseShadowTarget(U32 index);
+ void releaseSpotShadowTargets();
+ void releaseSunShadowTargets();
+ void releaseSunShadowTarget(U32 index);
// void setLocalLighting(const bool local_lighting);
// bool isLocalLightingEnabled() const;
@@ -240,7 +243,9 @@ public:
bool visibleObjectsInFrustum(LLCamera& camera);
bool getVisibleExtents(LLCamera& camera, LLVector3 &min, LLVector3& max);
bool getVisiblePointCloud(LLCamera& camera, LLVector3 &min, LLVector3& max, std::vector<LLVector3>& fp, LLVector3 light_dir = LLVector3(0,0,0));
- void updateCull(LLCamera& camera, LLCullResult& result, LLPlane* plane = NULL); //if water_clip is 0, ignore water plane, 1, cull to above plane, -1, cull to below plane
+
+ // Populate given LLCullResult with results of a frustum cull of the entire scene against the given LLCamera
+ void updateCull(LLCamera& camera, LLCullResult& result);
void createObjects(F32 max_dtime);
void createObject(LLViewerObject* vobj);
void processPartitionQ();
@@ -261,19 +266,17 @@ public:
void stateSort(LLDrawable* drawablep, LLCamera& camera);
void postSort(LLCamera& camera);
- //update stats for textures in given DrawInfo
- void touchTextures(LLDrawInfo* info);
- void touchTexture(LLViewerTexture* tex, F32 vsize);
-
void forAllVisibleDrawables(void (*func)(LLDrawable*));
- void renderObjects(U32 type, U32 mask, bool texture = true, bool batch_texture = false, bool rigged = false);
- void renderAlphaObjects(U32 mask, bool texture = true, bool batch_texture = false, bool rigged = false);
- void renderMaskedObjects(U32 type, U32 mask, bool texture = true, bool batch_texture = false, bool rigged = false);
- void renderFullbrightMaskedObjects(U32 type, U32 mask, bool texture = true, bool batch_texture = false, bool rigged = false);
+ void renderObjects(U32 type, bool texture = true, bool batch_texture = false, bool rigged = false);
+ void renderShadowSimple(U32 type);
+
+ void renderAlphaObjects(bool texture = true, bool batch_texture = false, bool rigged = false);
+ void renderMaskedObjects(U32 type, bool texture = true, bool batch_texture = false, bool rigged = false);
+ void renderFullbrightMaskedObjects(U32 type, bool texture = true, bool batch_texture = false, bool rigged = false);
- void renderGroups(LLRenderPass* pass, U32 type, U32 mask, bool texture);
- void renderRiggedGroups(LLRenderPass* pass, U32 type, U32 mask, bool texture);
+ void renderGroups(LLRenderPass* pass, U32 type, bool texture);
+ void renderRiggedGroups(LLRenderPass* pass, U32 type, bool texture);
void grabReferences(LLCullResult& result);
void clearReferences();
@@ -283,29 +286,39 @@ public:
void checkReferences(LLDrawable* drawable);
void checkReferences(LLDrawInfo* draw_info);
void checkReferences(LLSpatialGroup* group);
-
-
- void renderGeom(LLCamera& camera, bool forceVBOUpdate = false);
- void renderGeomDeferred(LLCamera& camera);
- void renderGeomPostDeferred(LLCamera& camera, bool do_occlusion=true);
+
+ void renderGeomDeferred(LLCamera& camera, bool do_occlusion = false);
+ void renderGeomPostDeferred(LLCamera& camera);
void renderGeomShadow(LLCamera& camera);
+ void bindLightFunc(LLGLSLShader& shader);
+
+ // bind shadow maps
+ // if setup is true, wil lset texture compare mode function and filtering options
+ void bindShadowMaps(LLGLSLShader& shader);
+ void bindDeferredShaderFast(LLGLSLShader& shader);
void bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_target = nullptr);
void setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep);
void unbindDeferredShader(LLGLSLShader& shader);
- void renderDeferredLighting(LLRenderTarget* light_target);
+
+ // set env_mat parameter in given shader
+ void setEnvMat(LLGLSLShader& shader);
+
+ void bindReflectionProbes(LLGLSLShader& shader);
+ void unbindReflectionProbes(LLGLSLShader& shader);
+
+
+
+ void renderDeferredLighting();
void postDeferredGammaCorrect(LLRenderTarget* screen_target);
- void generateWaterReflection(LLCamera& camera);
void generateSunShadow(LLCamera& camera);
- LLRenderTarget* getShadowTarget(U32 i);
+ LLRenderTarget* getSunShadowTarget(U32 i);
+ LLRenderTarget* getSpotShadowTarget(U32 i);
- void generateHighlight(LLCamera& camera);
void renderHighlight(const LLViewerObject* obj, F32 fade);
- void setHighlightObject(LLDrawable* obj) { mHighlightObject = obj; }
-
-
- 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();
@@ -341,8 +354,8 @@ public:
LLCullResult::sg_iterator beginRiggedAlphaGroups();
LLCullResult::sg_iterator endRiggedAlphaGroups();
-
- void addTrianglesDrawn(S32 index_count, U32 render_type = LLRender::TRIANGLES);
+ void addTrianglesDrawn(S32 index_count);
+ void recordTrianglesDrawn();
bool hasRenderDebugFeatureMask(const U32 mask) const { return bool(mRenderDebugFeatureMask & mask); }
bool hasRenderDebugMask(const U64 mask) const { return bool(mRenderDebugMask & mask); }
@@ -415,7 +428,6 @@ public:
static void updateRenderTransparentWater();
static void updateRenderBump();
- static void updateRenderDeferred();
static void refreshCachedSettings();
void addDebugBlip(const LLVector3& position, const LLColor4& color);
@@ -426,6 +438,9 @@ public:
void hideObject( const LLUUID& id );
void restoreHiddenObject( const LLUUID& id );
+ LLReflectionMapManager mReflectionMapManager;
+ void overrideEnvironmentMap();
+
private:
void unloadShaders();
void addToQuickLookup( LLDrawPool* new_poolp );
@@ -459,7 +474,10 @@ public:
RENDER_TYPE_INVISIBLE = LLDrawPool::POOL_INVISIBLE,
RENDER_TYPE_VOIDWATER = LLDrawPool::POOL_VOIDWATER,
RENDER_TYPE_WATER = LLDrawPool::POOL_WATER,
+ RENDER_TYPE_GLTF_PBR = LLDrawPool::POOL_GLTF_PBR,
RENDER_TYPE_ALPHA = LLDrawPool::POOL_ALPHA,
+ RENDER_TYPE_ALPHA_PRE_WATER = LLDrawPool::POOL_ALPHA_PRE_WATER,
+ RENDER_TYPE_ALPHA_POST_WATER = LLDrawPool::POOL_ALPHA_POST_WATER,
RENDER_TYPE_GLOW = LLDrawPool::POOL_GLOW,
RENDER_TYPE_PASS_SIMPLE = LLRenderPass::PASS_SIMPLE,
RENDER_TYPE_PASS_SIMPLE_RIGGED = LLRenderPass::PASS_SIMPLE_RIGGED,
@@ -517,6 +535,10 @@ public:
RENDER_TYPE_PASS_NORMSPEC_MASK_RIGGED = LLRenderPass::PASS_NORMSPEC_MASK_RIGGED,
RENDER_TYPE_PASS_NORMSPEC_EMISSIVE = LLRenderPass::PASS_NORMSPEC_EMISSIVE,
RENDER_TYPE_PASS_NORMSPEC_EMISSIVE_RIGGED = LLRenderPass::PASS_NORMSPEC_EMISSIVE_RIGGED,
+ RENDER_TYPE_PASS_GLTF_PBR = LLRenderPass::PASS_GLTF_PBR,
+ RENDER_TYPE_PASS_GLTF_PBR_RIGGED = LLRenderPass::PASS_GLTF_PBR_RIGGED,
+ RENDER_TYPE_PASS_GLTF_PBR_ALPHA_MASK = LLRenderPass::PASS_GLTF_PBR_ALPHA_MASK,
+ RENDER_TYPE_PASS_GLTF_PBR_ALPHA_MASK_RIGGED = LLRenderPass::PASS_GLTF_PBR_ALPHA_MASK_RIGGED,
// Following are object types (only used in drawable mRenderType)
RENDER_TYPE_HUD = LLRenderPass::NUM_RENDER_TYPES,
RENDER_TYPE_VOLUME,
@@ -574,7 +596,8 @@ public:
RENDER_DEBUG_ATTACHMENT_BYTES = 0x20000000, // not used
RENDER_DEBUG_TEXEL_DENSITY = 0x40000000,
RENDER_DEBUG_TRIANGLE_COUNT = 0x80000000,
- RENDER_DEBUG_IMPOSTORS = 0x100000000
+ RENDER_DEBUG_IMPOSTORS = 0x100000000,
+ RENDER_DEBUG_REFLECTION_PROBES = 0x200000000
};
public:
@@ -609,10 +632,8 @@ public:
static bool sRenderBump;
static bool sBakeSunlight;
static bool sNoAlpha;
- static bool sUseTriStrips;
static bool sUseFarClip;
static bool sShadowRender;
- static bool sWaterReflections;
static bool sDynamicLOD;
static bool sPickAvatar;
static bool sReflectionRender;
@@ -622,50 +643,74 @@ public:
static bool sUnderWaterRender;
static bool sRenderGlow;
static bool sTextureBindTest;
- static bool sRenderFrameTest;
static bool sRenderAttachedLights;
static bool sRenderAttachedParticles;
static bool sRenderDeferred;
+ static bool sReflectionProbesEnabled;
static S32 sVisibleLightCount;
static bool sRenderingHUDs;
static F32 sDistortionWaterClipPlaneMargin;
static LLTrace::EventStatHandle<S64> sStatBatchSize;
- //screen texture
- U32 mScreenWidth;
- U32 mScreenHeight;
-
- LLRenderTarget mScreen;
- LLRenderTarget mUIScreen;
- LLRenderTarget mDeferredScreen;
- LLRenderTarget mFXAABuffer;
- LLRenderTarget mEdgeMap;
- LLRenderTarget mDeferredDepth;
- LLRenderTarget mOcclusionDepth;
- LLRenderTarget mDeferredLight;
- LLRenderTarget mHighlight;
- LLRenderTarget mPhysicsDisplay;
+ class RenderTargetPack
+ {
+ public:
+ U32 width = 0;
+ U32 height = 0;
+
+ //screen texture
+ LLRenderTarget screen;
+ LLRenderTarget uiScreen;
+ LLRenderTarget deferredScreen;
+ LLRenderTarget fxaaBuffer;
+ LLRenderTarget edgeMap;
+ LLRenderTarget deferredLight;
+
+ //sun shadow map
+ LLRenderTarget shadow[4];
+ };
+
+ // main full resoltuion render target
+ RenderTargetPack mMainRT;
+
+ // auxillary 512x512 render target pack
+ RenderTargetPack mAuxillaryRT;
+
+ // currently used render target pack
+ RenderTargetPack* mRT;
+
+ LLRenderTarget mSpotShadow[2];
+
+ LLRenderTarget mPbrBrdfLut;
+
+ // copy of the color/depth buffer just before gamma correction
+ // for use by SSR
+ LLRenderTarget mSceneMap;
LLCullResult mSky;
LLCullResult mReflectedObjects;
LLCullResult mRefractedObjects;
- //utility buffer for rendering post effects, gets abused by renderDeferredLighting
+ //utility buffers for rendering post effects
LLPointer<LLVertexBuffer> mDeferredVB;
+ // a single triangle that covers the whole screen
+ LLPointer<LLVertexBuffer> mScreenTriangleVB;
+
//utility buffer for rendering cubes, 8 vertices are corners of a cube [-1, 1]
LLPointer<LLVertexBuffer> mCubeVB;
- //sun shadow map
- LLRenderTarget mShadow[6];
- LLRenderTarget mShadowOcclusion[6];
+ //list of currently bound reflection maps
+ std::vector<LLReflectionMap*> mReflectionMaps;
+
std::vector<LLVector3> mShadowFrustPoints[4];
LLVector4 mShadowError;
LLVector4 mShadowFOV;
LLVector3 mShadowFrustOrigin[4];
LLCamera mShadowCamera[8];
LLVector3 mShadowExtents[4][2];
+ // TODO : separate Sun Shadow and Spot Shadow matrices
glh::matrix4f mSunShadowMatrix[6];
glh::matrix4f mShadowModelview[6];
glh::matrix4f mShadowProjection[6];
@@ -753,7 +798,7 @@ protected:
};
typedef std::set< Light, Light::compare > light_set_t;
- LLDrawable::drawable_set_t mLights;
+ LLDrawable::ordered_drawable_set_t mLights;
light_set_t mNearbyLights; // lights near camera
LLColor4 mHWLightColors[8];
@@ -809,9 +854,6 @@ protected:
}
};
- std::set<HighlightItem> mHighlightSet;
- LLPointer<LLDrawable> mHighlightObject;
-
//////////////////////////////////////////////////
//
// Draw pools are responsible for storing all rendered data,
@@ -845,21 +887,23 @@ protected:
// For quick-lookups into mPools (mapped by texture pointer)
std::map<uintptr_t, LLDrawPool*> mTerrainPools;
std::map<uintptr_t, LLDrawPool*> mTreePools;
- LLDrawPoolAlpha* mAlphaPool;
- LLDrawPool* mSkyPool;
- LLDrawPool* mTerrainPool;
- LLDrawPool* mWaterPool;
- LLDrawPool* mGroundPool;
- LLRenderPass* mSimplePool;
- LLRenderPass* mGrassPool;
- LLRenderPass* mAlphaMaskPool;
- LLRenderPass* mFullbrightAlphaMaskPool;
- LLRenderPass* mFullbrightPool;
- LLDrawPool* mInvisiblePool;
- LLDrawPool* mGlowPool;
- LLDrawPool* mBumpPool;
- LLDrawPool* mMaterialsPool;
- LLDrawPool* mWLSkyPool;
+ LLDrawPoolAlpha* mAlphaPoolPreWater = nullptr;
+ LLDrawPoolAlpha* mAlphaPoolPostWater = nullptr;
+ LLDrawPool* mSkyPool = nullptr;
+ LLDrawPool* mTerrainPool = nullptr;
+ LLDrawPool* mWaterPool = nullptr;
+ LLDrawPool* mGroundPool = nullptr;
+ LLRenderPass* mSimplePool = nullptr;
+ LLRenderPass* mGrassPool = nullptr;
+ LLRenderPass* mAlphaMaskPool = nullptr;
+ LLRenderPass* mFullbrightAlphaMaskPool = nullptr;
+ LLRenderPass* mFullbrightPool = nullptr;
+ LLDrawPool* mInvisiblePool = nullptr;
+ LLDrawPool* mGlowPool = nullptr;
+ LLDrawPool* mBumpPool = nullptr;
+ LLDrawPool* mMaterialsPool = nullptr;
+ LLDrawPool* mWLSkyPool = nullptr;
+ LLDrawPool* mPBROpaquePool = nullptr;
// Note: no need to keep an quick-lookup to avatar pools, since there's only one per avatar
public:
@@ -966,7 +1010,6 @@ public:
static LLVector3 RenderShadowGaussian;
static F32 RenderShadowBlurDistFactor;
static bool RenderDeferredAtmospheric;
- static S32 RenderReflectionDetail;
static F32 RenderHighlightFadeTime;
static LLVector3 RenderShadowClipPlanes;
static LLVector3 RenderShadowOrthoClipPlanes;
@@ -979,6 +1022,7 @@ public:
static F32 CameraMaxCoF;
static F32 CameraDoFResScale;
static F32 RenderAutoHideSurfaceAreaLimit;
+ static bool RenderScreenSpaceReflections;
};
void render_bbox(const LLVector3 &min, const LLVector3 &max);
diff --git a/indra/newview/skins/default/textures/default_irradiance.png b/indra/newview/skins/default/textures/default_irradiance.png
new file mode 100644
index 0000000000..899e0ddf2a
--- /dev/null
+++ b/indra/newview/skins/default/textures/default_irradiance.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Material.png b/indra/newview/skins/default/textures/icons/Inv_Material.png
new file mode 100644
index 0000000000..f5918ceaed
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Material.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index 1f2c0867c4..bdf12d73fc 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -302,6 +302,7 @@ with the same filename but different name
<texture name="Inv_LostClosed" file_name="icons/Inv_LostClosed.png" preload="false" />
<texture name="Inv_LostOpen" file_name="icons/Inv_LostOpen.png" preload="false" />
<texture name="Inv_Landmark" file_name="icons/Inv_Landmark.png" preload="false" />
+ <texture name="Inv_Material" file_name="icons/Inv_Material.png" preload="false" />
<texture name="Inv_Mesh" file_name="icons/Inv_Mesh.png" preload="false" />
<texture name="Inv_Notecard" file_name="icons/Inv_Notecard.png" preload="false" />
<texture name="Inv_Object" file_name="icons/Inv_Object.png" preload="false" />
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:</text>
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/en/floater_adjust_environment.xml b/indra/newview/skins/default/xui/en/floater_adjust_environment.xml
index f4a686bae1..39fe573c98 100644
--- a/indra/newview/skins/default/xui/en/floater_adjust_environment.xml
+++ b/indra/newview/skins/default/xui/en/floater_adjust_environment.xml
@@ -252,6 +252,25 @@
top_pad="5"
width="185"
can_edit_text="true"/>
+ <text follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="-5"
+ top_pad="15"
+ width="180">Reflection Probe Ambiance:</text>
+ <slider decimal_digits="3"
+ follows="left|top"
+ height="16"
+ increment="0.01"
+ initial_value="0"
+ layout="topleft"
+ left_delta="5"
+ min_val="0"
+ max_val="1"
+ name="probe_ambiance"
+ top_pad="5"
+ width="185"
+ can_edit_text="true"/>
</layout_panel>
<layout_panel border="false"
bevel_style="in"
diff --git a/indra/newview/skins/default/xui/en/floater_build_options.xml b/indra/newview/skins/default/xui/en/floater_build_options.xml
index 38428b36fc..7278e55d57 100644
--- a/indra/newview/skins/default/xui/en/floater_build_options.xml
+++ b/indra/newview/skins/default/xui/en/floater_build_options.xml
@@ -46,14 +46,14 @@
name="GridSubUnit"
top_pad="0"
width="200" />
- <check_box
+ <!-- <check_box
control_name="GridCrossSections"
height="16"
label="View cross-sections"
layout="topleft"
name="GridCrossSection"
top_pad="5"
- width="200" />
+ width="200" />-->
<text
type="string"
length="1"
diff --git a/indra/newview/skins/default/xui/en/floater_combobox_ok_cancel.xml b/indra/newview/skins/default/xui/en/floater_combobox_ok_cancel.xml
new file mode 100644
index 0000000000..63eaffde18
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_combobox_ok_cancel.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<floater
+ legacy_header_height="18"
+ height="130"
+ min_height="130"
+ width="270"
+ min_width="270"
+ layout="topleft"
+ name="floater_combo"
+ title="floater_combo"
+ help_topic="floater_combo"
+ can_resize="false"
+ can_minimize="false">
+ <text
+ follows="top|left|right"
+ height="10"
+ layout="topleft"
+ left="20"
+ name="combo_text"
+ top="30"
+ width="200">
+ Select an option:
+ </text>
+ <combo_box
+ follows="top|left"
+ layout="topleft"
+ left="20"
+ name="combo_options"
+ top_delta="20"
+ width="230"/>
+ <button
+ follows="top|left"
+ height="23"
+ label="OK"
+ layout="topleft"
+ top_delta="40"
+ left="20"
+ name="combo_ok"
+ width="90"/>
+ <button
+ follows="top|left"
+ height="23"
+ label="Cancel"
+ layout="topleft"
+ left_pad="50"
+ name="combo_cancel"
+ width="90"/>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml b/indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml
index d783d1e23c..e91efb89b2 100644
--- a/indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml
+++ b/indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml
@@ -2,7 +2,7 @@
<floater
legacy_header_height="18"
can_minimize="false"
- height="466"
+ height="486"
layout="topleft"
name="Inventory Finder"
help_topic="inventory_finder"
@@ -95,12 +95,29 @@
width="126" />
<icon
height="16"
+ image_name="Inv_Material"
+ layout="topleft"
+ left="8"
+ mouse_opaque="true"
+ name="icon_material"
+ top="122"
+ width="16" />
+ <check_box
+ height="16"
+ label="Materials"
+ layout="topleft"
+ left_pad="2"
+ name="check_material"
+ top_delta="0"
+ width="126" />
+ <icon
+ height="16"
image_name="Inv_Notecard"
layout="topleft"
left="8"
mouse_opaque="true"
name="icon_notecard"
- top="122"
+ top="142"
width="16" />
<check_box
height="16"
@@ -117,7 +134,7 @@
left="8"
mouse_opaque="true"
name="icon_object"
- top="142"
+ top="162"
width="16" />
<check_box
height="16"
@@ -134,7 +151,7 @@
left="8"
mouse_opaque="true"
name="icon_script"
- top="162"
+ top="182"
width="16" />
<check_box
height="16"
@@ -151,7 +168,7 @@
left="8"
mouse_opaque="true"
name="icon_sound"
- top="182"
+ top="202"
width="16" />
<check_box
height="16"
@@ -168,7 +185,7 @@
left="8"
mouse_opaque="true"
name="icon_texture"
- top="202"
+ top="222"
width="16" />
<check_box
height="16"
@@ -185,7 +202,7 @@
left="8"
mouse_opaque="true"
name="icon_snapshot"
- top="222"
+ top="242"
width="16" />
<check_box
height="16"
@@ -202,7 +219,7 @@
left="8"
mouse_opaque="true"
name="icon_settings"
- top="242"
+ top="262"
width="16" />
<check_box
height="16"
@@ -220,7 +237,7 @@
layout="topleft"
left="8"
name="All"
- top="262"
+ top="282"
width="100" />
<button
height="20"
@@ -274,7 +291,7 @@
width="260"/>
<check_box
height="16"
- top="352"
+ top="372"
label="Since Logoff"
layout="topleft"
left_delta="0"
@@ -290,7 +307,7 @@
layout="topleft"
left_delta="0"
name="- OR -"
- top="370"
+ top="390"
width="144">
- OR -
</text>
@@ -298,7 +315,7 @@
height="16"
layout="topleft"
name="date_search_direction"
- top="388"
+ top="408"
left="8"
width="270">
<radio_item
@@ -368,6 +385,6 @@
layout="topleft"
name="Close"
right="-6"
- top="434"
+ top="454"
width="76" />
</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_live_material_editor.xml b/indra/newview/skins/default/xui/en/floater_live_material_editor.xml
new file mode 100644
index 0000000000..5b7dab6a52
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_live_material_editor.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_resize="true"
+ default_tab_group="1"
+ height="790"
+ width="256"
+ min_height="500"
+ min_width="256"
+ layout="topleft"
+ name="material editor"
+ help_topic="material_editor"
+ single_instance="true"
+ title="Editing Material">
+ <scroll_container
+ name="materials_scroll"
+ top="18"
+ left="4"
+ height="768"
+ width="250"
+ follows="all"
+ layout="topleft"
+ color="DkGray2"
+ opaque="true"
+ tab_stop="true"
+ border="false"
+ reserve_scroll_corner="false">
+ <panel
+ name="panel_material"
+ filename="panel_gltf_material.xml"
+ layout="topleft"
+ follows="left|top|right"
+ border="false"
+ top="0"
+ left="0"
+ height="768"
+ width="236" />
+ </scroll_container>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_material_editor.xml b/indra/newview/skins/default/xui/en/floater_material_editor.xml
new file mode 100644
index 0000000000..6adfa40733
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_material_editor.xml
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_resize="true"
+ default_tab_group="1"
+ height="891"
+ width="256"
+ min_height="500"
+ min_width="256"
+ layout="topleft"
+ name="material editor"
+ help_topic="material_editor"
+ title="[MATERIAL_NAME]">
+ <string name="no_upload_fee_string">no upload fee</string>
+ <string name="upload_fee_string">L$[FEE] upload fee</string>
+ <string name="material_selection_title">Material selection</string>
+ <string name="material_selection_text">Select material:</string>
+ <string name="material_override_title">Editing Material</string>
+
+ <scroll_container
+ name="materials_scroll"
+ top="18"
+ left="4"
+ height="768"
+ width="250"
+ follows="all"
+ layout="topleft"
+ color="DkGray2"
+ opaque="true"
+ tab_stop="true"
+ border="false"
+ reserve_scroll_corner="false">
+ <panel
+ name="panel_material"
+ filename="panel_gltf_material.xml"
+ layout="topleft"
+ follows="left|top|right"
+ border="false"
+ top="0"
+ left="0"
+ height="768"
+ width="236" />
+ </scroll_container>
+
+ <panel
+ follows="right|bottom"
+ width="246"
+ height="97"
+ layout="bottomright"
+ top_pad="0"
+ left="5"
+ name="button_panel"
+ >
+ <text
+ type="string"
+ name="unsaved_changes"
+ font.style="BOLD"
+ text_color="DrYellow"
+ length="1"
+ follows="left|top"
+ height="10"
+ width="200"
+ layout="topleft"
+ left="10"
+ top="0"
+ >
+ Unsaved changes
+ </text>
+ <button
+ follows="left|top"
+ height="25"
+ label="Save"
+ enabled="false"
+ layout="topleft"
+ name="save"
+ top_pad="7"
+ left="0"
+ width="120" />
+ <button
+ follows="left|top"
+ height="25"
+ label="Save As..."
+ enabled="false"
+ layout="topleft"
+ name="save_as"
+ top_delta="0"
+ left_pad="6"
+ width="120" />
+ <text
+ type="string"
+ font.style="BOLD"
+ length="1"
+ follows="left|top"
+ height="10"
+ width="220"
+ layout="topleft"
+ left="10"
+ top_pad="5"
+ name="total_upload_fee"
+ >
+ Total upload fee: L$ [FEE]
+ </text>
+
+ <view_border
+ bevel_style="none"
+ height="0"
+ layout="topleft"
+ left="0"
+ name="button_border"
+ top_pad="7"
+ width="246"/>
+
+ <button
+ follows="left|top"
+ height="25"
+ label="Cancel"
+ layout="topleft"
+ name="cancel"
+ top_pad="7"
+ left="61"
+ width="121" />
+ </panel>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_my_environments.xml b/indra/newview/skins/default/xui/en/floater_my_environments.xml
index 6aff387dcb..db81c8bba2 100644
--- a/indra/newview/skins/default/xui/en/floater_my_environments.xml
+++ b/indra/newview/skins/default/xui/en/floater_my_environments.xml
@@ -119,7 +119,7 @@
follows="all"
layout="topleft"
name="pnl_settings"
- filter_asset_type="settings"/>
+ filter_asset_types="settings"/>
</panel>
</layout_panel>
<layout_panel
diff --git a/indra/newview/skins/default/xui/en/floater_perms_default.xml b/indra/newview/skins/default/xui/en/floater_perms_default.xml
index 49dc719a24..9ca61671e1 100644
--- a/indra/newview/skins/default/xui/en/floater_perms_default.xml
+++ b/indra/newview/skins/default/xui/en/floater_perms_default.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
legacy_header_height="18"
- height="250"
+ height="266"
layout="topleft"
name="perms default"
help_topic="perms_default"
@@ -10,7 +10,7 @@
width="700">
<panel
follows="left|top|right|bottom"
- height="200"
+ height="216"
label="Default Permissions"
layout="topleft"
left="10"
@@ -549,6 +549,70 @@
left_pad="0"
top_delta="0"
width="100" />
+ <text
+ name="label_14"
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="0"
+ tool_tip="Set default permissions for when GLTF Materials are created"
+ width="100">
+ Materials
+ </text>
+ <icon
+ follows="left|top"
+ height="16"
+ image_name="Inv_Material"
+ layout="topleft"
+ left_pad="2"
+ width="18"/>
+ <check_box
+ control_name="MaterialsNextOwnerCopy"
+ height="16"
+ layout="topleft"
+ name="env_material_c"
+ left_pad="45"
+ top_delta="0"
+ width="100">
+ <check_box.commit_callback
+ function="PermsDefault.Copy"
+ parameter="Materials" />
+ </check_box>
+ <check_box
+ control_name="MaterialsNextOwnerModify"
+ height="16"
+ layout="topleft"
+ name="env_materials_m"
+ left_pad="0"
+ top_delta="0"
+ width="100" />
+ <check_box
+ enabled_control="MaterialsNextOwnerCopy"
+ control_name="MaterialsNextOwnerTransfer"
+ height="16"
+ layout="topleft"
+ name="env_materials_t"
+ left_pad="0"
+ top_delta="0"
+ width="100" />
+ <check_box
+ control_name="MaterialsShareWithGroup"
+ height="16"
+ layout="topleft"
+ name="env_materials_s"
+ left_pad="0"
+ top_delta="0"
+ width="120" />
+ <check_box
+ control_name="MaterialsEveryoneCopy"
+ height="16"
+ layout="topleft"
+ name="env_materials_e"
+ left_pad="0"
+ top_delta="0"
+ width="100" />
</panel>
<button
height="20"
diff --git a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml
index d1e167df64..7f03fbe7c3 100644
--- a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml
+++ b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml
@@ -272,68 +272,6 @@
Hardware
</text>
- <slider
- control_name="TextureMemory"
- decimal_digits="0"
- follows="left|top"
- height="16"
- increment="16"
- initial_value="32"
- label="Texture Memory (MB):"
- label_width="185"
- layout="topleft"
- left="30"
- max_val="4096"
- name="GraphicsCardTextureMemory"
- tool_tip="Amount of memory to allocate for textures. Defaults to video card memory. Reducing this may improve performance but may also make textures blurry."
- top_delta="16"
- width="335" />
-
- <slider
- control_name="RenderFogRatio"
- follows="left|top"
- height="16"
- initial_value="4"
- decimal_digits="1"
- label="Fog Distance Ratio:"
- label_width="185"
- layout="topleft"
- left="30"
- name="fog"
- min_val="0.5"
- max_val="10"
- increment="0.1"
- top_delta="16"
- width="332" />
-
- <slider
- control_name="RenderGamma"
- follows="left|top"
- height="16"
- initial_value="1"
- decimal_digits="2"
- label="Gamma:"
- label_width="185"
- layout="topleft"
- left="30"
- name="gamma"
- min_val="0"
- max_val="2"
- increment="0.01"
- top_delta="16"
- width="332" />
- <text
- type="string"
- length="1"
- follows="left|top"
- height="16"
- layout="topleft"
- left="30"
- name="(brightness, lower is brighter)"
- top_delta="16"
- width="260">
- (0 = default brightness, lower = brighter)
- </text>
<check_box
control_name="RenderAnisotropic"
@@ -602,20 +540,6 @@
</check_box>
<check_box
- control_name="RenderObjectBump"
- height="16"
- initial_value="true"
- label="Bump mapping and shiny"
- layout="topleft"
- left="420"
- name="BumpShiny"
- top_delta="16"
- width="300">
- <check_box.commit_callback
- function="Pref.RenderOptionUpdate" />
- </check_box>
-
- <check_box
control_name="RenderLocalLights"
height="16"
initial_value="true"
@@ -627,116 +551,6 @@
width="300" />
<slider
- control_name="RenderTerrainDetail"
- follows="left|top"
- height="16"
- label="Terrain Detail:"
- label_width="165"
- layout="topleft"
- left="440"
- show_text="false"
- initial_value="0"
- increment="1"
- min_val="0"
- max_val="1"
- name="TerrainDetail"
- top_delta="16"
- width="280" >
- <slider.commit_callback
- function="Pref.UpdateSliderText"
- parameter="TerrainDetail" />
- </slider>
- <text
- type="string"
- length="1"
- follows="left|top"
- height="16"
- layout="topleft"
- top_delta="0"
- left_delta="284"
- name="TerrainDetailText"
- text_readonly_color="LabelDisabledColor"
- width="65">
- Low
- </text>
-
- <check_box
- control_name="RenderAvatarCloth"
- height="16"
- initial_value="true"
- label="Avatar cloth"
- layout="topleft"
- left="440"
- name="AvatarCloth"
- top_delta="16"
- width="280" />
-
- <text
- type="string"
- length="1"
- follows="left|top"
- height="16"
- layout="topleft"
- name="ReflectionsText"
- text_readonly_color="LabelDisabledColor"
- top_delta="16"
- left="440"
- width="128">
- Water Reflections:
- </text>
- <combo_box
- control_name="RenderReflectionDetail"
- height="18"
- layout="topleft"
- left_delta="170"
- top_delta="0"
- name="Reflections"
- width="150">
- <combo_box.item
- label="None; opaque"
- name="0"
- value="-2"/>
- <combo_box.item
- label="None; transparent"
- name="0"
- value="-1"/>
- <combo_box.item
- label="Minimal"
- name="0"
- value="0"/>
- <combo_box.item
- label="Terrain and trees"
- name="1"
- value="1"/>
- <combo_box.item
- label="All static objects"
- name="2"
- value="2"/>
- <combo_box.item
- label="All avatars and objects"
- name="3"
- value="3"/>
- <combo_box.item
- label="Everything"
- name="4"
- value="4"/>
- </combo_box>
-
- <check_box
- control_name="WindLightUseAtmosShaders"
- height="16"
- initial_value="true"
- label="Atmospheric shaders"
- layout="topleft"
- left="440"
- name="WindLightUseAtmosShaders"
- top_delta="16"
- width="280">
- <check_box.commit_callback
- function="Pref.RenderOptionUpdate" />
- </check_box>
-
- <slider
control_name="WLSkyDetail"
decimal_digits="0"
follows="left|top"
@@ -746,7 +560,7 @@
label="Sky:"
label_width="145"
layout="topleft"
- left="460"
+ left="420"
min_val="16"
max_val="128"
name="SkyMeshDetail"
@@ -772,26 +586,12 @@
</text>
<check_box
- control_name="RenderDeferred"
- height="16"
- initial_value="true"
- label="Advanced Lighting Model"
- layout="topleft"
- left="460"
- name="UseLightShaders"
- top_delta="16"
- width="260">
- <check_box.commit_callback
- function="Pref.RenderOptionUpdate" />
- </check_box>
-
- <check_box
control_name="RenderDeferredSSAO"
height="16"
initial_value="true"
label="Ambient Occlusion"
layout="topleft"
- left="480"
+ left="420"
name="UseSSAO"
top_delta="16"
width="240">
@@ -805,7 +605,7 @@
initial_value="true"
label="Depth of Field"
layout="topleft"
- left="480"
+ left="420"
name="UseDoF"
top_delta="16"
width="240">
@@ -813,29 +613,13 @@
function="Pref.RenderOptionUpdate" />
</check_box>
- <!--
- <check_box
- control_name="RenderUseAdvancedAtmospherics"
- height="16"
- initial_value="true"
- label="Advanced Atmospherics"
- layout="topleft"
- left="480"
- name="UseAdvancedAtmo"
- top_delta="16"
- width="240">
- <check_box.commit_callback
- function="Pref.AdvancedAtmosphericsEnable" />
- </check_box>
- -->
-
<text
type="string"
length="1"
follows="left|top"
height="16"
layout="topleft"
- left="480"
+ left="420"
name="RenderShadowDetailText"
text_readonly_color="LabelDisabledColor"
top_delta="16"
@@ -863,15 +647,79 @@
name="2"
value="2"/>
</combo_box>
+
+ <check_box
+ control_name="RenderReflectionsEnabled"
+ height="16"
+ initial_value="true"
+ label="Reflections"
+ layout="topleft"
+ left="420"
+ name="ReflectionsEnabled"
+ top_delta="16"
+ width="240">
+ <check_box.commit_callback
+ function="Pref.RenderOptionUpdate" />
+ </check_box>
+
+ <check_box
+ control_name="RenderScreenSpaceReflections"
+ height="16"
+ initial_value="true"
+ label="Screen Space Reflections"
+ layout="topleft"
+ left="440"
+ name="ScreenSpaceReflections"
+ top_delta="16"
+ width="240">
+ <check_box.commit_callback
+ function="Pref.RenderOptionUpdate" />
+ </check_box>
-<!-- End of Advanced Settings block -->
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="440"
+ name="ReflectionDetailText"
+ text_readonly_color="LabelDisabledColor"
+ top_delta="16"
+ width="128">
+ Reflection Detail:
+ </text>
+
+ <combo_box
+ control_name="RenderReflectionProbeDetail"
+ height="18"
+ layout="topleft"
+ left_delta="110"
+ top_delta="0"
+ name="ReflectionDetail"
+ width="150">
+ <combo_box.item
+ label="Static Only"
+ name="0"
+ value="0"/>
+ <combo_box.item
+ label="Static+Dynamic"
+ name="1"
+ value="1"/>
+ <combo_box.item
+ label="Realtime"
+ name="2"
+ value="2"/>
+ </combo_box>
+
+ <!-- End of Advanced Settings block -->
<view_border
bevel_style="in"
height="0"
layout="topleft"
left="13"
name="horiz_border"
- top_pad="21"
+ top="338"
top_delta="5"
width="774"/>
<button
@@ -881,7 +729,7 @@
layout="topleft"
left="20"
name="Defaults"
- top_delta="10"
+ top_delta="20"
width="210">
<button.commit_callback
function="Pref.HardwareDefaults" />
diff --git a/indra/newview/skins/default/xui/en/floater_settings_picker.xml b/indra/newview/skins/default/xui/en/floater_settings_picker.xml
index 3a26c3b547..8931269fe7 100644
--- a/indra/newview/skins/default/xui/en/floater_settings_picker.xml
+++ b/indra/newview/skins/default/xui/en/floater_settings_picker.xml
@@ -89,7 +89,7 @@
top="1"
right="-4"
bottom="-1"
- filter_asset_type="settings" />
+ filter_asset_types="settings" />
</panel>
</layout_panel>
<layout_panel name="pnl_combo"
diff --git a/indra/newview/skins/default/xui/en/floater_stats.xml b/indra/newview/skins/default/xui/en/floater_stats.xml
index b9ca0108b6..9ee161e611 100644
--- a/indra/newview/skins/default/xui/en/floater_stats.xml
+++ b/indra/newview/skins/default/xui/en/floater_stats.xml
@@ -133,6 +133,12 @@
label="Bound Mem"
stat="glboundmemstat"/>
</stat_view>
+ <stat_view name="material"
+ label="Material">
+ <stat_bar name="nummaterials"
+ label="Count"
+ stat="nummaterials"/>
+ </stat_view>
<stat_view name="memory"
label="Memory Usage">
<stat_bar name="LLTrace"
diff --git a/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml
index 3a66911389..47de3b7576 100644
--- a/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml
+++ b/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml
@@ -19,7 +19,15 @@
</floater.string>
<floater.string
name="pick title">
- Pick:
+Pick:
+ </floater.string>
+ <floater.string
+ name="pick_material">
+PICK: MATERIAL
+ </floater.string>
+ <floater.string
+ name="pick_texture">
+PICK: TEXTURE
</floater.string>
<view
@@ -138,6 +146,7 @@
word_wrap="true"
visible="false"
width="87" />
+
<filter_editor
follows="left|top|right"
height="23"
@@ -153,22 +162,13 @@
bg_alpha_color="DkGray2"
border="false"
follows="all"
- height="233"
+ height="242"
layout="topleft"
left_delta="0"
name="inventory panel"
top_pad="4"
width="231"
- filter_asset_type="texture"/>
- <check_box
- height="14"
- initial_value="false"
- label="Show folders"
- layout="topleft"
- name="show_folders_check"
- top_pad="0"
- left_delta="-3"
- width="200" />
+ filter_asset_types="texture|material"/>
<!-- middle: local mode -->
<button
@@ -218,8 +218,8 @@
multi_select="true"
search_column="1"
visible="false">
+ <column name="icon" label="" width="20" />
<column name="unit_name" label="Name" dynamicwidth="true" />
- <column name="unit_id_HIDDEN" label="ID" width="0" />
</scroll_list>
<!-- middle: bake mode -->
@@ -283,19 +283,6 @@
name="BAKED_AUX3"
value="10" />
</combo_box>
- <check_box
- follows="left|top"
- height="20"
- initial_value="false"
- label="Hide Base Mesh Region"
-
-layout="topleft"
- name="hide_base_mesh_region"
- left_delta="0"
- top_pad="10"
- top_delta="0"
- width="120"
- visible="false"/>
<!-- bottom static -->
<button
follows="bottom"
diff --git a/indra/newview/skins/default/xui/en/floater_texture_fetch_debugger.xml b/indra/newview/skins/default/xui/en/floater_texture_fetch_debugger.xml
deleted file mode 100644
index 9278a1a598..0000000000
--- a/indra/newview/skins/default/xui/en/floater_texture_fetch_debugger.xml
+++ /dev/null
@@ -1,440 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater
- legacy_header_height="18"
- can_minimize="false"
- height="600"
- layout="topleft"
- name="TexFetchDebugger"
- help_topic="texfetchdebugger"
- title="Texture Fetching Debugger"
- width="540">
- <text
- type="string"
- length="1"
- follows="left|top"
- height="25"
- layout="topleft"
- left="10"
- name="total_num_fetched_label"
- top="30"
- width="400">
- 1, Total number of fetched textures: [NUM]
- </text>
- <text
- type="string"
- length="1"
- follows="left|top"
- height="25"
- layout="topleft"
- left_delta="0"
- name="total_num_fetching_requests_label"
- top_delta="25"
- width="400">
- 2, Total number of fetching requests: [NUM]
- </text>
- <text
- type="string"
- length="1"
- follows="left|top"
- height="25"
- layout="topleft"
- left_delta="0"
- name="total_num_cache_hits_label"
- top_delta="25"
- width="400">
- 3, Total number of cache hits: [NUM]
- </text>
- <text
- type="string"
- length="1"
- follows="left|top"
- height="25"
- layout="topleft"
- left_delta="0"
- name="total_num_visible_tex_label"
- top_delta="25"
- width="400">
- 4, Total number of visible textures: [NUM]
- </text>
- <text
- type="string"
- length="1"
- follows="left|top"
- height="25"
- layout="topleft"
- left_delta="0"
- name="total_num_visible_tex_fetch_req_label"
- top_delta="25"
- width="450">
- 5, Total number of visible texture fetching requests: [NUM]
- </text>
- <text
- type="string"
- length="1"
- follows="left|top"
- height="25"
- layout="topleft"
- left_delta="0"
- name="total_fetched_data_label"
- top_delta="25"
- width="530">
- 6, Total number of fetched data: [SIZE1]KB, Decoded Data: [SIZE2]KB, [PIXEL]MPixels
- </text>
- <text
- type="string"
- length="1"
- follows="left|top"
- height="25"
- layout="topleft"
- left_delta="0"
- name="total_fetched_vis_data_label"
- top_delta="25"
- width="480">
- 7, Total number of visible data: [SIZE1]KB, Decoded Data: [SIZE2]KB
- </text>
- <text
- type="string"
- length="1"
- follows="left|top"
- height="25"
- layout="topleft"
- left_delta="0"
- name="total_fetched_rendered_data_label"
- top_delta="25"
- width="530">
- 8, Total number of rendered data: [SIZE1]KB, Decoded Data: [SIZE2]KB, [PIXEL]MPixels
- </text>
- <text
- type="string"
- length="1"
- follows="left|top"
- height="25"
- layout="topleft"
- left_delta="0"
- name="total_time_cache_read_label"
- top_delta="25"
- width="400">
- 9, Total time on cache readings: [TIME] seconds
- </text>
- <text
- type="string"
- length="1"
- follows="left|top"
- height="25"
- layout="topleft"
- left_delta="0"
- name="total_time_cache_write_label"
- top_delta="25"
- width="400">
- 10, Total time on cache writings: [TIME] seconds
- </text>
- <text
- type="string"
- length="1"
- follows="left|top"
- height="25"
- layout="topleft"
- left_delta="0"
- name="total_time_decode_label"
- top_delta="25"
- width="400">
- 11, Total time on decodings: [TIME] seconds
- </text>
- <text
- type="string"
- length="1"
- follows="left|top"
- height="25"
- layout="topleft"
- left_delta="0"
- name="total_time_gl_label"
- top_delta="25"
- width="400">
- 12, Total time on gl texture creation: [TIME] seconds
- </text>
- <text
- type="string"
- length="1"
- follows="left|top"
- height="25"
- layout="topleft"
- left_delta="0"
- name="total_time_http_label"
- top_delta="25"
- width="400">
- 13, Total time on HTTP fetching: [TIME] seconds
- </text>
- <text
- type="string"
- length="1"
- follows="left|top"
- height="25"
- layout="topleft"
- left_delta="0"
- name="total_time_fetch_label"
- top_delta="25"
- width="400">
- 14, Total time on entire fetching: [TIME] seconds
- </text>
- <text
- type="string"
- length="1"
- follows="left|top"
- height="25"
- layout="topleft"
- left_delta="0"
- name="total_time_refetch_vis_cache_label"
- top_delta="25"
- width="540">
- 15, Refetching visibles from cache, Time: [TIME] seconds, Fetched: [SIZE]KB, [PIXEL]MPixels
- </text>
- <text
- type="string"
- length="1"
- follows="left|top"
- height="25"
- layout="topleft"
- left_delta="0"
- name="total_time_refetch_all_cache_label"
- top_delta="25"
- width="540">
- 16, Refetching all textures from cache, Time: [TIME] seconds, Fetched: [SIZE]KB, [PIXEL]MPixels
- </text>
- <text
- type="string"
- length="1"
- follows="left|top"
- height="25"
- layout="topleft"
- left_delta="0"
- name="total_time_refetch_vis_http_label"
- top_delta="25"
- width="540">
- 17, Refetching visibles from HTTP, Time: [TIME] seconds, Fetched: [SIZE]KB, [PIXEL]MPixels
- </text>
- <text
- type="string"
- length="1"
- follows="left|top"
- height="25"
- layout="topleft"
- left_delta="0"
- name="total_time_refetch_all_http_label"
- top_delta="25"
- width="540">
- 18, Refetching all textures from HTTP, Time: [TIME] seconds, Fetched: [SIZE]KB, [PIXEL]MPixels
- </text>
- <spinner
- decimal_digits="2"
- follows="left|top"
- height="20"
- increment="0.01"
- initial_value="1.0"
- label="19, Ratio of Texel/Pixel:"
- label_width="130"
- layout="topleft"
- left_delta="0"
- max_val="10.0"
- min_val="0.01"
- name="texel_pixel_ratio"
- top_delta="30"
- width="200">
- <spinner.commit_callback
- function="TexFetchDebugger.ChangeTexelPixelRatio" />
- </spinner>
- <text
- type="string"
- length="1"
- follows="left|top"
- height="25"
- layout="topleft"
- left_delta="0"
- name="texture_source_label"
- top_delta="30"
- width="110">
- 20, Texture Source:
- </text>
- <radio_group
- control_name="TextureFetchSource"
- follows="top|left"
- draw_border="false"
- height="25"
- layout="topleft"
- left_pad="0"
- name="texture_source"
- top_delta="0"
- width="264">
- <radio_item
- height="16"
- label="Cache + HTTP"
- layout="topleft"
- left="3"
- name="0"
- top="0"
- width="100" />
- <radio_item
- height="16"
- label="HTTP Only"
- layout="topleft"
- left_delta="100"
- name="1"
- top_delta="0"
- width="200" />
- </radio_group>
- <button
- follows="left|top"
- height="20"
- label="Start"
- layout="topleft"
- left="10"
- name="start_btn"
- top_delta="20"
- width="70">
- <button.commit_callback
- function="TexFetchDebugger.Start" />
- </button>
- <button
- follows="left|top"
- height="20"
- label="Reset"
- layout="topleft"
- left_pad="7"
- name="clear_btn"
- top_delta="0"
- width="70">
- <button.commit_callback
- function="TexFetchDebugger.Clear" />
- </button>
- <button
- follows="left|top"
- height="20"
- label="Close"
- layout="topleft"
- left_pad="7"
- name="close_btn"
- top_delta="0"
- width="70">
- <button.commit_callback
- function="TexFetchDebugger.Close" />
- </button>
- <button
- follows="left|top"
- height="22"
- label="Reset Fetching Time"
- layout="topleft"
- left_pad="175"
- name="reset_time_btn"
- top_delta="0"
- width="120">
- <button.commit_callback
- function="TexFetchDebugger.ResetFetchTime" />
- </button>
- <button
- follows="left|top"
- height="20"
- label="Cache Read"
- layout="topleft"
- left="10"
- name="cacheread_btn"
- top_delta="20"
- width="80">
- <button.commit_callback
- function="TexFetchDebugger.CacheRead" />
- </button>
- <button
- follows="left|top"
- height="20"
- label="Cache Write"
- layout="topleft"
- left_pad="7"
- name="cachewrite_btn"
- top_delta="0"
- width="80">
- <button.commit_callback
- function="TexFetchDebugger.CacheWrite" />
- </button>
- <button
- follows="left|top"
- height="20"
- label="HTTP"
- layout="topleft"
- left_pad="7"
- name="http_btn"
- top_delta="0"
- width="70">
- <button.commit_callback
- function="TexFetchDebugger.HTTPLoad" />
- </button>
- <button
- follows="left|top"
- height="20"
- label="Decode"
- layout="topleft"
- left_pad="7"
- name="decode_btn"
- top_delta="0"
- width="70">
- <button.commit_callback
- function="TexFetchDebugger.Decode" />
- </button>
- <button
- follows="left|top"
- height="20"
- label="GL Texture"
- layout="topleft"
- left_pad="7"
- name="gl_btn"
- top_delta="0"
- width="70">
- <button.commit_callback
- function="TexFetchDebugger.GLTexture" />
- </button>
- <button
- follows="left|top"
- height="20"
- label="Refetch Vis Cache"
- layout="topleft"
- left="10"
- name="refetchviscache_btn"
- top_delta="20"
- width="120">
- <button.commit_callback
- function="TexFetchDebugger.RefetchVisCache" />
- </button>
- <button
- follows="left|top"
- height="20"
- label="Refetch All Cache"
- layout="topleft"
- left_pad="7"
- name="refetchallcache_btn"
- top_delta="0"
- width="120">
- <button.commit_callback
- function="TexFetchDebugger.RefetchAllCache" />
- </button>
- <button
- follows="left|top"
- height="20"
- label="Refetch Vis HTTP"
- layout="topleft"
- left_pad="7"
- name="refetchvishttp_btn"
- top_delta="0"
- width="120">
- <button.commit_callback
- function="TexFetchDebugger.RefetchVisHTTP" />
- </button>
- <button
- follows="left|top"
- height="20"
- label="Refetch All HTTP"
- layout="topleft"
- left_pad="7"
- name="refetchallhttp_btn"
- top_delta="0"
- width="120">
- <button.commit_callback
- function="TexFetchDebugger.RefetchAllHTTP" />
- </button>
-</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml
index ade79b8884..4700488197 100644
--- a/indra/newview/skins/default/xui/en/floater_tools.xml
+++ b/indra/newview/skins/default/xui/en/floater_tools.xml
@@ -2,7 +2,7 @@
<floater
positioning="cascading"
legacy_header_height="18"
- height="609"
+ height="651"
layout="topleft"
bg_opaque_image="Window_NoTitle_Foreground"
bg_alpha_image="Window_NoTitle_Background"
@@ -820,7 +820,7 @@
width="282"/>
<tab_container
follows="left|top"
- height="426"
+ height="476"
halign="center"
left="0"
name="Object Info Tabs"
@@ -2531,7 +2531,70 @@ even though the user gets a free copy.
mouse_opaque="true"
name="Light Ambiance"
width="120" />
- <text
+ <check_box
+ height="16"
+ label="Reflection Probe"
+ layout="topleft"
+ left="10"
+ name="Reflection Probe"
+ tool_tip="Adjusts how objects within this volume receive reflections when PBR is enabled"
+ top_pad="10"
+ width="60" />
+ <combo_box
+ height="19"
+ top_delta="0"
+ left="144"
+ follows="left|top"
+ name="Probe Volume Type"
+ tool_tip="Choose the probe influence volume"
+ width="108">
+ <combo_box.item
+ label="Sphere"
+ name="Sphere"
+ value="Sphere" />
+ <combo_box.item
+ label="Box"
+ name="Box"
+ value="Box"/>
+ </combo_box>
+ <check_box
+ height="16"
+ label="Dynamic"
+ layout="topleft"
+ left="10"
+ name="Probe Dynamic"
+ tool_tip="When enabled, Avatars will appear in reflections within this probe's influence volume."
+ bottom_delta="19"
+ width="60" />
+ <spinner bottom_delta="19"
+ decimal_digits="3"
+ follows="left|top"
+ height="16"
+ increment="0.05"
+ initial_value="0"
+ label="Ambiance"
+ label_width="55"
+ left="10"
+ max_val="1"
+ min_val="0"
+ mouse_opaque="true"
+ name="Probe Ambiance"
+ width="120" />
+ <spinner bottom_delta="0"
+ decimal_digits="3"
+ follows="left|top"
+ height="16"
+ increment="0.05"
+ initial_value="0"
+ label="Near Clip"
+ label_width="55"
+ left="144"
+ max_val="1024"
+ min_val="0"
+ mouse_opaque="true"
+ name="Probe Near Clip"
+ width="120" />
+ <text
type="string"
length="1"
follows="left|top"
@@ -2686,7 +2749,7 @@ even though the user gets a free copy.
border_visible="true"
bevel_style="in"
follows="left|top|right"
- height="335"
+ height="387"
layout="topleft"
left="10"
name="contents_inventory"
diff --git a/indra/newview/skins/default/xui/en/menu_attachment_self.xml b/indra/newview/skins/default/xui/en/menu_attachment_self.xml
index 3b91b9df7a..630a1981df 100644
--- a/indra/newview/skins/default/xui/en/menu_attachment_self.xml
+++ b/indra/newview/skins/default/xui/en/menu_attachment_self.xml
@@ -13,6 +13,22 @@
function="EnableEdit" />
</menu_item_call>
<menu_item_call
+ label="Edit PBR Material"
+ name="EditGLTFMaterial">
+ <menu_item_call.on_click
+ function="Object.EditGLTFMaterial" />
+ <menu_item_call.on_enable
+ function="Object.EnableEditGLTFMaterial"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Save material to inventory"
+ name="SaveGLTFMaterial">
+ <menu_item_call.on_click
+ function="Object.SaveGLTFMaterial" />
+ <menu_item_call.on_enable
+ function="Object.EnableSaveGLTFMaterial"/>
+ </menu_item_call>
+ <menu_item_call
enabled="false"
label="Detach item"
layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml
index aa3d0ae071..5e2fd31301 100644
--- a/indra/newview/skins/default/xui/en/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/en/menu_inventory.xml
@@ -143,264 +143,6 @@
function="Inventory.EmptyLostAndFound"
parameter="rename" />
</menu_item_call>
- <menu_item_call
- label="New Folder"
- layout="topleft"
- name="New Folder">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="category" />
- </menu_item_call>
- <menu_item_call
- label="New Outfit"
- layout="topleft"
- name="New Outfit">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="outfit" />
- </menu_item_call>
- <menu_item_call
- label="New Script"
- layout="topleft"
- name="New Script">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="lsl" />
- </menu_item_call>
- <menu_item_call
- label="New Notecard"
- layout="topleft"
- name="New Note">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="notecard" />
- </menu_item_call>
- <menu_item_call
- label="New Gesture"
- layout="topleft"
- name="New Gesture">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="gesture" />
- </menu_item_call>
- <menu
- label="New Clothes"
- layout="topleft"
- name="New Clothes">
- <menu_item_call
- label="New Shirt"
- layout="topleft"
- name="New Shirt">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="shirt" />
- </menu_item_call>
- <menu_item_call
- label="New Pants"
- layout="topleft"
- name="New Pants">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="pants" />
- </menu_item_call>
- <menu_item_call
- label="New Shoes"
- layout="topleft"
- name="New Shoes">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="shoes" />
- </menu_item_call>
- <menu_item_call
- label="New Socks"
- layout="topleft"
- name="New Socks">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="socks" />
- </menu_item_call>
- <menu_item_call
- label="New Jacket"
- layout="topleft"
- name="New Jacket">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="jacket" />
- </menu_item_call>
- <menu_item_call
- label="New Skirt"
- layout="topleft"
- name="New Skirt">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="skirt" />
- </menu_item_call>
- <menu_item_call
- label="New Gloves"
- layout="topleft"
- name="New Gloves">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="gloves" />
- </menu_item_call>
- <menu_item_call
- label="New Undershirt"
- layout="topleft"
- name="New Undershirt">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="undershirt" />
- </menu_item_call>
- <menu_item_call
- label="New Underpants"
- layout="topleft"
- name="New Underpants">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="underpants" />
- </menu_item_call>
- <menu_item_call
- label="New Alpha Mask"
- layout="topleft"
- name="New Alpha Mask">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="alpha" />
- </menu_item_call>
- <menu_item_call
- label="New Tattoo"
- layout="topleft"
- name="New Tattoo">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="tattoo" />
- </menu_item_call>
- <menu_item_call
- label="New Universal"
- layout="topleft"
- name="New Universal">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="universal" />
- </menu_item_call>
- <menu_item_call
- label="New Physics"
- layout="topleft"
- name="New Physics">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="physics" />
- </menu_item_call>
- </menu>
- <menu
- label="New Body Parts"
- layout="topleft"
- name="New Body Parts">
- <menu_item_call
- label="New Shape"
- layout="topleft"
- name="New Shape">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="shape" />
- </menu_item_call>
- <menu_item_call
- label="New Skin"
- layout="topleft"
- name="New Skin">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="skin" />
- </menu_item_call>
- <menu_item_call
- label="New Hair"
- layout="topleft"
- name="New Hair">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="hair" />
- </menu_item_call>
- <menu_item_call
- label="New Eyes"
- layout="topleft"
- name="New Eyes">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="eyes" />
- </menu_item_call>
- </menu>
- <menu
- label="New Settings"
- layout="topleft"
- name="New Settings">
- <menu_item_call
- label="New Sky"
- layout="topleft"
- name="New Sky">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="sky"/>
- <menu_item_call.on_enable
- function="Inventory.EnvironmentEnabled" />
- </menu_item_call>
- <menu_item_call
- label="New Water"
- layout="topleft"
- name="New Water">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="water"/>
- <menu_item_call.on_enable
- function="Inventory.EnvironmentEnabled" />
- </menu_item_call>
- <menu_item_call
- label="New Day Cycle"
- layout="topleft"
- name="New Day Cycle">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="daycycle"/>
- <menu_item_call.on_enable
- function="Inventory.EnvironmentEnabled" />
- </menu_item_call>
- </menu>
- <menu
- label="Use as default for"
- layout="topleft"
- name="upload_def">
- <menu_item_call
- label="Image uploads"
- layout="topleft"
- name="Image uploads">
- <menu_item_call.on_click
- function="Inventory.FileUploadLocation"
- parameter="texture" />
- </menu_item_call>
- <menu_item_call
- label="Sound uploads"
- layout="topleft"
- name="Sound uploads">
- <menu_item_call.on_click
- function="Inventory.FileUploadLocation"
- parameter="sound" />
- </menu_item_call>
- <menu_item_call
- label="Animation uploads"
- layout="topleft"
- name="Animation uploads">
- <menu_item_call.on_click
- function="Inventory.FileUploadLocation"
- parameter="animation" />
- </menu_item_call>
- <menu_item_call
- label="Model uploads"
- layout="topleft"
- name="Model uploads">
- <menu_item_call.on_click
- function="Inventory.FileUploadLocation"
- parameter="model" />
- </menu_item_call>
- </menu>
<menu
label="Change Type"
layout="topleft"
@@ -683,6 +425,285 @@
parameter="delete_system_folder" />
</menu_item_call>
<menu_item_separator
+ layout="topleft"
+ name="Create Separator" />
+ <menu_item_call
+ label="New Folder"
+ layout="topleft"
+ name="New Folder">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="category" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Outfit"
+ layout="topleft"
+ name="New Outfit">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="outfit" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Script"
+ layout="topleft"
+ name="New Script">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="lsl" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Notecard"
+ layout="topleft"
+ name="New Note">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="notecard" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Gesture"
+ layout="topleft"
+ name="New Gesture">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="gesture" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Material"
+ layout="topleft"
+ name="New Material">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="material" />
+ <menu_item_call.on_enable
+ function="Inventory.MaterialsEnabled" />
+ </menu_item_call>
+ <menu
+ label="New Clothes"
+ layout="topleft"
+ name="New Clothes">
+ <menu_item_call
+ label="New Shirt"
+ layout="topleft"
+ name="New Shirt">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="shirt" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Pants"
+ layout="topleft"
+ name="New Pants">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="pants" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Shoes"
+ layout="topleft"
+ name="New Shoes">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="shoes" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Socks"
+ layout="topleft"
+ name="New Socks">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="socks" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Jacket"
+ layout="topleft"
+ name="New Jacket">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="jacket" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Skirt"
+ layout="topleft"
+ name="New Skirt">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="skirt" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Gloves"
+ layout="topleft"
+ name="New Gloves">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="gloves" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Undershirt"
+ layout="topleft"
+ name="New Undershirt">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="undershirt" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Underpants"
+ layout="topleft"
+ name="New Underpants">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="underpants" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Alpha Mask"
+ layout="topleft"
+ name="New Alpha Mask">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="alpha" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Tattoo"
+ layout="topleft"
+ name="New Tattoo">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="tattoo" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Universal"
+ layout="topleft"
+ name="New Universal">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="universal" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Physics"
+ layout="topleft"
+ name="New Physics">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="physics" />
+ </menu_item_call>
+ </menu>
+ <menu
+ label="New Body Parts"
+ layout="topleft"
+ name="New Body Parts">
+ <menu_item_call
+ label="New Shape"
+ layout="topleft"
+ name="New Shape">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="shape" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Skin"
+ layout="topleft"
+ name="New Skin">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="skin" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Hair"
+ layout="topleft"
+ name="New Hair">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="hair" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Eyes"
+ layout="topleft"
+ name="New Eyes">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="eyes" />
+ </menu_item_call>
+ </menu>
+ <menu
+ label="New Settings"
+ layout="topleft"
+ name="New Settings">
+ <menu_item_call
+ label="New Sky"
+ layout="topleft"
+ name="New Sky">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="sky"/>
+ <menu_item_call.on_enable
+ function="Inventory.EnvironmentEnabled" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Water"
+ layout="topleft"
+ name="New Water">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="water"/>
+ <menu_item_call.on_enable
+ function="Inventory.EnvironmentEnabled" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Day Cycle"
+ layout="topleft"
+ name="New Day Cycle">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="daycycle"/>
+ <menu_item_call.on_enable
+ function="Inventory.EnvironmentEnabled" />
+ </menu_item_call>
+ </menu>
+ <menu
+ label="Use as default for"
+ layout="topleft"
+ name="upload_def">
+ <menu_item_call
+ label="Image uploads"
+ layout="topleft"
+ name="Image uploads">
+ <menu_item_call.on_click
+ function="Inventory.FileUploadLocation"
+ parameter="texture" />
+ </menu_item_call>
+ <menu_item_call
+ label="Sound uploads"
+ layout="topleft"
+ name="Sound uploads">
+ <menu_item_call.on_click
+ function="Inventory.FileUploadLocation"
+ parameter="sound" />
+ </menu_item_call>
+ <menu_item_call
+ label="Animation uploads"
+ layout="topleft"
+ name="Animation uploads">
+ <menu_item_call.on_click
+ function="Inventory.FileUploadLocation"
+ parameter="animation" />
+ </menu_item_call>
+ <menu_item_call
+ label="Model uploads"
+ layout="topleft"
+ name="Model uploads">
+ <menu_item_call.on_click
+ function="Inventory.FileUploadLocation"
+ parameter="model" />
+ </menu_item_call>
+ <menu_item_call
+ label="PBR material uploads"
+ layout="topleft"
+ name="PBR uploads">
+ <menu_item_call.on_click
+ function="Inventory.FileUploadLocation"
+ parameter="pbr_material" />
+ </menu_item_call>
+ </menu>
+ <menu_item_separator
layout="topleft" />
<menu_item_separator
layout="topleft" />
diff --git a/indra/newview/skins/default/xui/en/menu_inventory_add.xml b/indra/newview/skins/default/xui/en/menu_inventory_add.xml
index 3385a29a6c..b04215872c 100644
--- a/indra/newview/skins/default/xui/en/menu_inventory_add.xml
+++ b/indra/newview/skins/default/xui/en/menu_inventory_add.xml
@@ -47,13 +47,23 @@
label="Model..."
layout="topleft"
name="Upload Model">
- <menu_item_call.on_click
- function="File.UploadModel"
- parameter="" />
- <menu_item_call.on_enable
- function="File.EnableUploadModel" />
- <menu_item_call.on_visible
- function="File.VisibleUploadModel"/>
+ <menu_item_call.on_click
+ function="File.UploadModel"
+ parameter="" />
+ <menu_item_call.on_enable
+ function="File.EnableUploadModel" />
+ <menu_item_call.on_visible
+ function="File.VisibleUploadModel"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Material..."
+ layout="topleft"
+ name="Upload Material">
+ <menu_item_call.on_click
+ function="File.UploadMaterial"
+ parameter="" />
+ <menu_item_call.on_enable
+ function="File.EnableUploadMaterial" />
</menu_item_call>
<menu_item_call
label="Bulk..."
@@ -97,6 +107,16 @@
function="Inventory.DoCreate"
parameter="gesture" />
</menu_item_call>
+ <menu_item_call
+ label="New Material"
+ layout="topleft"
+ name="New Material">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="material" />
+ <menu_item_call.on_enable
+ function="Inventory.MaterialsEnabled" />
+ </menu_item_call>
<menu
height="175"
label="New Clothes"
diff --git a/indra/newview/skins/default/xui/en/menu_object.xml b/indra/newview/skins/default/xui/en/menu_object.xml
index ce34508303..6d37c15815 100644
--- a/indra/newview/skins/default/xui/en/menu_object.xml
+++ b/indra/newview/skins/default/xui/en/menu_object.xml
@@ -22,6 +22,22 @@
function="EnableEdit"/>
</menu_item_call>
<menu_item_call
+ label="Edit PBR Material"
+ name="EditGLTFMaterial">
+ <menu_item_call.on_click
+ function="Object.EditGLTFMaterial" />
+ <menu_item_call.on_enable
+ function="Object.EnableEditGLTFMaterial"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Save material to inventory"
+ name="SaveGLTFMaterial">
+ <menu_item_call.on_click
+ function="Object.SaveGLTFMaterial" />
+ <menu_item_call.on_enable
+ function="Object.EnableSaveGLTFMaterial"/>
+ </menu_item_call>
+ <menu_item_call
label="Build"
name="Build">
<menu_item_call.on_click
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 58584345a9..2512fadec7 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -1418,6 +1418,15 @@ function="World.EnvPreset"
function="Tools.SelectOnlyMovableObjects"
parameter="movable" />
</menu_item_check>
+ <menu_item_check
+ label="Select Invisible Objects"
+ name="Select Invisible Objects">
+ <menu_item_check.on_check
+ control="SelectInvisibleObjects" />
+ <menu_item_check.on_click
+ function="Tools.SelectInvisibleObjects"
+ parameter="invisible" />
+ </menu_item_check>
<menu_item_check
label="Select By Surrounding"
name="Select By Surrounding">
@@ -1456,6 +1465,15 @@ function="World.EnvPreset"
function="Tools.ShowSelectionLightRadius" />
</menu_item_check>
<menu_item_check
+ label="Show Reflection Probe Volumes"
+ name="Show Reflection Probe Volumes">
+ <menu_item_check.on_check
+ control="RenderReflectionProbeVolumes" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="RenderReflectionProbeVolumes" />
+ </menu_item_check>
+ <menu_item_check
label="Show Selection Beam"
name="Show Selection Beam">
<menu_item_check.on_check
@@ -1575,6 +1593,16 @@ function="World.EnvPreset"
<menu_item_call.on_visible
function="File.VisibleUploadModel"/>
</menu_item_call>
+ <menu_item_call
+ label="Material..."
+ layout="topleft"
+ name="Upload Material">
+ <menu_item_call.on_click
+ function="File.UploadMaterial"
+ parameter="" />
+ <menu_item_call.on_enable
+ function="File.EnableUploadMaterial" />
+ </menu_item_call>
<menu_item_call
label="Bulk..."
layout="topleft"
@@ -1587,7 +1615,8 @@ function="World.EnvPreset"
parameter="" />
</menu_item_call>
</menu>
- <menu_item_separator/>
+
+ <menu_item_separator/>
<menu_item_call
enabled="false"
label="Undo"
@@ -2439,20 +2468,6 @@ function="World.EnvPreset"
function="Advanced.ToggleConsole"
parameter="scene monitor" />
</menu_item_check>
- <menu_item_call
- enabled="false"
- visible="false"
- label="Texture Fetch Debug Console"
- name="Texture Fetch Debug Console">
- <menu_item_call.on_click
- function="Floater.Show"
- parameter="tex_fetch_debugger" />
- <on_enable
- function="Develop.SetTexFetchDebugger" />
- <on_visible
- function="Develop.SetTexFetchDebugger" />
- </menu_item_call>
-
<menu_item_separator/>
<menu_item_call
@@ -2731,15 +2746,6 @@ function="World.EnvPreset"
function="Advanced.TogglePeriodicSlowFrame"
parameter="points" />
</menu_item_check>
- <menu_item_check
- label="Frame Test"
- name="Frame Test">
- <menu_item_check.on_check
- function="Advanced.CheckFrameTest"
- parameter="Frame Test" />
- <menu_item_check.on_click
- function="Advanced.ToggleFrameTest" />
- </menu_item_check>
<menu_item_call
label="Frame Profile"
name="Frame Profile">
@@ -2919,6 +2925,16 @@ function="World.EnvPreset"
parameter="lights" />
</menu_item_check>
<menu_item_check
+ label="Reflection Probes"
+ name="Reflection Probes">
+ <menu_item_check.on_check
+ function="Advanced.CheckInfoDisplay"
+ parameter="reflection probes" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleInfoDisplay"
+ parameter="reflection probes" />
+ </menu_item_check>
+ <menu_item_check
label="Particles"
name="Particles">
<menu_item_check.on_check
@@ -3084,24 +3100,10 @@ function="World.EnvPreset"
<menu_item_check.on_click
function="ToggleControl"
parameter="UseOcclusion" />
- <menu_item_check.on_enable
- function="Advanced.EnableObjectObjectOcclusion" />
</menu_item_check>
<menu_item_separator />
<menu_item_check
- label="Advanced Lighting Model"
- name="Advanced Lighting Model">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="RenderDeferred" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="RenderDeferred" />
- <menu_item_check.on_enable
- function="Advanced.EnableRenderDeferred" />
- </menu_item_check>
- <menu_item_check
label=" Shadows from Sun/Moon/Projectors"
name="Shadows from Sun/Moon/Projectors">
<menu_item_check.on_check
@@ -3247,16 +3249,13 @@ function="World.EnvPreset"
function="Advanced.HandleAttachedLightParticles"
parameter="RenderAttachedParticles" />
</menu_item_check>
- <menu_item_check
- label="Hover Glow Objects"
- name="Hover Glow Objects">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="RenderHoverGlowEnable" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="RenderHoverGlowEnable" />
- </menu_item_check>
+ <menu_item_call
+ enabled="true"
+ label="Rebuild Reflection Probes"
+ name="Rebuild Reflection Probes">
+ <menu_item_call.on_click
+ function="Develop.RebuildReflectionProbes" />
+ </menu_item_call>
<menu_item_separator />
<menu_item_call
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index d1a99133f0..7cdf4af5c2 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -6802,6 +6802,22 @@ You don&apos;t have permission to view this notecard.
<notification
icon="notifytip.tga"
+ name="MaterialMissing"
+ type="notifytip">
+ Material is missing from database.
+ <tag>fail</tag>
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="MaterialNoPermissions"
+ type="notifytip">
+ You don&apos;t have permission to view this material.
+ <tag>fail</tag>
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
name="RezItemNoPermissions"
type="notifytip">
Insufficient permissions to rez object.
@@ -6833,6 +6849,23 @@ Please try again.
<notification
icon="notifytip.tga"
+ name="UnableToLoadMaterial"
+ type="notifytip">
+ Unable to load material.
+ Please try again.
+ <tag>fail</tag>
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="MissingMaterialCaps"
+ type="notifytip">
+ <tag>fail</tag>
+ Not connected to a materials capable region.
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
name="ScriptMissing"
type="notifytip">
Script is missing from database.
@@ -9063,7 +9096,64 @@ Unable to upload texture.
[REASON]
<tag>fail</tag>
</notification>
-
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotUploadMaterial"
+ type="alertmodal">
+There was a problem uploading the file
+ <tag>fail</tag>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ label="Save Material"
+ name="SaveMaterialAs"
+ type="alertmodal">
+ <unique/>
+ Name this material:
+ <tag>confirm</tag>
+ <form name="form">
+ <input name="message" type="text">
+ [DESC]
+ </input>
+ <button
+ default="true"
+ index="0"
+ name="OK"
+ text="OK"/>
+ <button
+ index="1"
+ name="Cancel"
+ text="Cancel"/>
+ </form>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="InvalidMaterialName"
+ type="alertmodal">
+Please enter a non-empty name
+ <tag>fail</tag>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="UsavedMaterialChanges"
+ type="alertmodal">
+ You have unsaved changes.
+ <form name="form">
+ <button
+ index="0"
+ name="discard"
+ text="Discard changes"/>
+ <button
+ index="1"
+ name="keep"
+ text="Keep editing"/>
+ </form>
+ </notification>
+
<notification
icon="alertmodal.tga"
name="LivePreviewUnavailable"
@@ -9760,6 +9850,15 @@ Attempt cancelled.
<notification
icon="alertmodal.tga"
+ name="LocalGLTFVerifyFail"
+ persist="true"
+ type="notify">
+Attempted to add an invalid or unreadable GLTF material [FNAME] which could not be opened or decoded.
+Attempt cancelled.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
name="PathfindingReturnMultipleItems"
type="alertmodal">
You are returning [NUM_ITEMS] items. Are you sure you want to continue?
@@ -11930,4 +12029,22 @@ If you want others to see this object, remove it and re-attach it to an avatar a
yestext="OK"/>
</notification>
+<notification
+ icon="notifytip.tga"
+ name="MaterialCreated"
+ type="notifytip">
+Material successfully created. Asset ID: [ASSET_ID]
+</notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="ReflectionProbeApplied"
+ persist="true"
+ type="alertmodal">
+ Your object has been set to the default Reflection Probe state, which is an invisible, phantom, 5m sphere. To learn more about Reflection Probes and how to use them, see the Knowledge Base.
+ <usetemplate ignoretext="Reflection Probe tips"
+ name="okignore"
+ yestext="OK"/>
+ </notification>
+
</notifications>
diff --git a/indra/newview/skins/default/xui/en/panel_gltf_material.xml b/indra/newview/skins/default/xui/en/panel_gltf_material.xml
new file mode 100644
index 0000000000..6975525b3d
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_gltf_material.xml
@@ -0,0 +1,392 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ layout="topleft"
+ follows="left|top|right"
+ border="false"
+ name="panel_gltf_material"
+ top="0"
+ left="0"
+ height="768"
+ width="247">
+ <check_box
+ follows="left|top"
+ layout="topleft"
+ label="Double Sided"
+ left="10"
+ top="0"
+ name="double sided"
+ height="25"
+ width="120" />
+ <panel
+ border="true"
+ follows="left|top"
+ width="246"
+ height="196"
+ layout="topleft"
+ left="1"
+ mouse_opaque="false"
+ name="base_color_texture_pnl"
+ top_pad="5"
+ >
+ <text
+ type="string"
+ font.style="BOLD"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="10"
+ top="5"
+ width="128"
+ name="base_color_lbl">
+ Base Color:
+ </text>
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ fallback_image="materials_ui_x_24.png"
+ allow_no_texture="true"
+ follows="left|top"
+ top_pad="8"
+ height="151"
+ layout="topleft"
+ left="10"
+ name="base_color_texture"
+ tool_tip="Base Color map. Alpha channel is optional and used for transparency."
+ width="128" />
+ <text
+ type="string"
+ font.style="BOLD"
+ length="1"
+ follows="left|top"
+ height="10"
+ width="128"
+ layout="topleft"
+ left="10"
+ top_pad="-17"
+ name="base_color_upload_fee">
+ No upload fee
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_pad="5"
+ top="8"
+ name="base_color_tint_lbl">
+ Tint
+ </text>
+ <color_swatch
+ can_apply_immediately="true"
+ follows="left|top"
+ height="40"
+ label_height="0"
+ layout="topleft"
+ left_delta="0"
+ top_pad="5"
+ name="base color"
+ width="40" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="0"
+ top_pad="5"
+ width="96"
+ name="base_color_transparency_lbl">
+ Transparency
+ </text>
+ <spinner
+ decimal_digits="3"
+ follows="left|top"
+ height="19"
+ increment="0.01"
+ initial_value="1"
+ layout="topleft"
+ left_delta="0"
+ top_pad="5"
+ min_val="0"
+ max_val="1"
+ name="transparency"
+ width="64"/>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="0"
+ text_readonly_color="LabelDisabledColor"
+ top_pad="5"
+ width="90"
+ name="alpha_mode_lbl">
+ Alpha mode
+ </text>
+ <combo_box
+ height="23"
+ layout="topleft"
+ left_delta="0"
+ name="alpha mode"
+ top_pad="4"
+ width="89">
+ <combo_box.item
+ label="Opaque"
+ name="None"
+ value="OPAQUE" />
+ <combo_box.item
+ label="Blend"
+ name="Alpha blending"
+ value="BLEND" />
+ <combo_box.item
+ label="Mask"
+ name="Alpha masking"
+ value="MASK" />
+ </combo_box>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="0"
+ top_pad="5"
+ width="96"
+ name="alpha_cutoff_lbl">
+ Alpha Cutoff
+ </text>
+ <spinner
+ decimal_digits="3"
+ follows="left|top"
+ height="19"
+ increment="0.01"
+ initial_value="1"
+ layout="topleft"
+ left_delta="0"
+ top_pad="5"
+ min_val="0"
+ max_val="1"
+ name="alpha cutoff"
+ width="64"/>
+ </panel>
+ <panel
+ border="true"
+ follows="left|top"
+ width="246"
+ height="175"
+ layout="topleft"
+ left="1"
+ mouse_opaque="false"
+ name="metallic_texture_pnl"
+ top_pad="5">
+ <text
+ type="string"
+ font.style="BOLD"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="10"
+ top="5"
+ name="metallic_roughness_lbl">
+ Metallic-Roughness:
+ </text>
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ fallback_image="materials_ui_x_24.png"
+ allow_no_texture="true"
+ follows="left|top"
+ width="128"
+ height="151"
+ layout="topleft"
+ left="10"
+ name="metallic_roughness_texture"
+ tool_tip="GLTF metallic-roughness map with optional occlusion. Red channel is occlusion, green channel is roughness, blue channel is metalness."
+ top_pad="8"/>
+ <text
+ type="string"
+ font.style="BOLD"
+ length="1"
+ follows="left|top"
+ height="10"
+ width="128"
+ layout="topleft"
+ left="10"
+ top_pad="-17"
+ name="metallic_upload_fee">
+ No upload fee
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_pad="5"
+ top="8"
+ name="metallic_factor_lbl">
+ Metallic Factor
+ </text>
+ <spinner
+ decimal_digits="3"
+ follows="left|top"
+ height="19"
+ increment="0.01"
+ initial_value="0"
+ layout="topleft"
+ left_delta="0"
+ top_pad="5"
+ min_val="0"
+ max_val="1"
+ name="metalness factor"
+ width="64"/>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="0"
+ top_pad="5"
+ width="96"
+ name="roughness_factor_lbl">
+ Roughness Factor
+ </text>
+ <spinner
+ decimal_digits="3"
+ follows="left|top"
+ height="19"
+ increment="0.01"
+ initial_value="0"
+ layout="topleft"
+ left_delta="0"
+ top_pad="5"
+ min_val="0"
+ max_val="1"
+ name="roughness factor"
+ width="64"/>
+ </panel>
+ <panel
+ border="true"
+ follows="left|top"
+ width="246"
+ height="175"
+ layout="topleft"
+ left="1"
+ mouse_opaque="false"
+ name="emissive_texture_pnl"
+ top_pad="5">
+ <text
+ type="string"
+ font.style="BOLD"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="10"
+ top="5"
+ width="64"
+ name="emissive_lbl">
+ Emissive:
+ </text>
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ fallback_image="materials_ui_x_24.png"
+ allow_no_texture="true"
+ follows="left|top"
+ top_pad="8"
+ height="151"
+ layout="topleft"
+ left="10"
+ name="emissive_texture"
+ width="128" />
+ <text
+ type="string"
+ font.style="BOLD"
+ length="1"
+ follows="left|top"
+ height="10"
+ width="128"
+ layout="topleft"
+ left="10"
+ top_pad="-17"
+ name="emissive_upload_fee">
+ No upload fee
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_pad="5"
+ top="8"
+ name="emissive_tint_lbl">
+ Tint
+ </text>
+ <color_swatch
+ can_apply_immediately="true"
+ follows="left|top"
+ height="40"
+ label_height="0"
+ layout="topleft"
+ left_delta="0"
+ top_pad="5"
+ name="emissive color"
+ width="40" />
+ </panel>
+ <panel
+ border="true"
+ follows="left|top"
+ width="246"
+ height="175"
+ layout="topleft"
+ left="1"
+ mouse_opaque="false"
+ top_pad="5"
+ name="normal_texture_pnl">
+ <text
+ type="string"
+ font.style="BOLD"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="10"
+ top="5"
+ width="64"
+ name="normal_lbl">
+ Normal:
+ </text>
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ fallback_image="materials_ui_x_24.png"
+ allow_no_texture="true"
+ follows="left|top"
+ top_pad="8"
+ height="151"
+ layout="topleft"
+ left="10"
+ name="normal_texture"
+ width="128" />
+ <text
+ type="string"
+ font.style="BOLD"
+ length="1"
+ follows="left|top"
+ height="10"
+ width="128"
+ layout="topleft"
+ left="10"
+ top_pad="-17"
+ name="normal_upload_fee">
+ No upload fee
+ </text>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml
index 5aff7a5127..38d364cf9a 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml
@@ -231,34 +231,6 @@
m
</text>
- <check_box
- control_name="WindLightUseAtmosShaders"
- height="16"
- initial_value="true"
- label="Atmospheric shaders"
- layout="topleft"
- left="30"
- name="WindLightUseAtmosShaders"
- top_delta="24"
- width="280">
- <check_box.commit_callback
- function="Pref.RenderOptionUpdate" />
- </check_box>
-
- <check_box
- control_name="RenderDeferred"
- height="16"
- initial_value="true"
- label="Advanced Lighting Model"
- layout="topleft"
- left="30"
- name="UseLightShaders"
- top_delta="24"
- width="256">
- <check_box.commit_callback
- function="Pref.RenderOptionUpdate" />
- </check_box>
-
<slider
control_name="IndirectMaxComplexity"
tool_tip="Controls at what point a visually complex avatar is drawn as a JellyDoll"
@@ -274,7 +246,7 @@
max_val="101"
name="IndirectMaxComplexity"
show_text="false"
- top_delta="60"
+ top_delta="36"
width="300">
<slider.commit_callback
function="Pref.UpdateIndirectMaxComplexity"
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_uploads.xml b/indra/newview/skins/default/xui/en/panel_preferences_uploads.xml
index 67eff2b762..08ff3d4d53 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_uploads.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_uploads.xml
@@ -126,6 +126,31 @@
type="string"
length="1"
follows="left|top"
+ height="12"
+ layout="topleft"
+ left="37"
+ name="title_pbr"
+ top_pad="7"
+ width="100">
+ PBR Materials
+ </text>
+ <text
+ type="string"
+ use_ellipses="true"
+ follows="left|top"
+ height="27"
+ layout="topleft"
+ font.style="BOLD"
+ left="37"
+ name="upload_pbr"
+ top_pad="5"
+ width="370"
+ word_wrap="true"/>
+
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
height="30"
layout="topleft"
font.style="ITALIC"
diff --git a/indra/newview/skins/default/xui/en/panel_settings_sky_atmos.xml b/indra/newview/skins/default/xui/en/panel_settings_sky_atmos.xml
index 6f82a0efa1..094be36b01 100644
--- a/indra/newview/skins/default/xui/en/panel_settings_sky_atmos.xml
+++ b/indra/newview/skins/default/xui/en/panel_settings_sky_atmos.xml
@@ -315,6 +315,29 @@
top_delta="20"
width="219"
can_edit_text="true"/>
+ <text
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="-5"
+ top_delta="25"
+ width="200">
+ Reflection Probe Ambiance:
+ </text>
+ <slider
+ decimal_digits="3"
+ follows="left|top"
+ height="16"
+ increment="0.01"
+ initial_value="0"
+ layout="topleft"
+ left_delta="5"
+ min_val="0"
+ max_val="1"
+ name="probe_ambiance"
+ top_delta="20"
+ width="219"
+ can_edit_text="true"/>
</layout_panel>
</layout_stack>
</layout_panel>
diff --git a/indra/newview/skins/default/xui/en/panel_tools_texture.xml b/indra/newview/skins/default/xui/en/panel_tools_texture.xml
index c7052bb737..3bcbe0ca3a 100644
--- a/indra/newview/skins/default/xui/en/panel_tools_texture.xml
+++ b/indra/newview/skins/default/xui/en/panel_tools_texture.xml
@@ -2,7 +2,7 @@
<panel
border="false"
follows="all"
- height="420"
+ height="500"
label="Texture"
layout="topleft"
left="0"
@@ -144,13 +144,16 @@
name="Materials"
value="Materials" />
<combo_box.item
+ label="PBR"
+ name="PBR"
+ value="PBR" />
+ <combo_box.item
label="Media"
name="Media"
value="Media" />
</combo_box>
<radio_group
- control_name="ComboMaterialType"
- height="50"
+ height="84"
layout="topleft"
left_pad="5"
top_delta="-10"
@@ -179,6 +182,50 @@
top_pad="1"
value="2"/>
</radio_group>
+ <radio_group
+ height="84"
+ layout="topleft"
+ left_delta="0"
+ top_delta="0"
+ width="150"
+ visible = "false"
+ name="radio_pbr_type">
+ <radio_item
+ label="Complete material"
+ name="Complete material"
+ top="0"
+ layout="topleft"
+ height="16"
+ value="0"/>
+ <radio_item
+ label="Base color"
+ name="Base color"
+ layout="topleft"
+ top_pad="1"
+ height="16"
+ value="1"/>
+ <radio_item
+ label="Normal"
+ layout="topleft"
+ top_pad="1"
+ height="16"
+ name="Normal"
+ value="2"/>
+ <radio_item
+ label="Metallic/roughness"
+ name="Metallic/roughness"
+ height="16"
+ layout="topleft"
+ top_pad="1"
+ value="3"/>
+ <radio_item
+ label="Emissive"
+ name="Emissive"
+ layout="topleft"
+ top_pad="1"
+ height="16"
+ value="4"/>
+ </radio_group>
<menu_button
menu_filename="menu_copy_paste_texture.xml"
follows="top|left"
@@ -195,7 +242,7 @@
<check_box
control_name="SyncMaterialSettings"
follows="top|left"
- height="20"
+ height="47"
initial_value="false"
label="Lock repeat"
layout="topleft"
@@ -206,6 +253,45 @@
width="160" />
<texture_picker
can_apply_immediately="true"
+ allow_no_texture="true"
+ follows="left|top"
+ height="80"
+ label="PBR "
+ layout="topleft"
+ left="10"
+ name="pbr_control"
+ tool_tip="Click to choose a pbr material"
+ top_pad="5"
+ width="64" />
+ <button
+ follows="left|top"
+ height="23"
+ layout="topleft"
+ left_pad="10"
+ top_delta="0"
+ name="pbr_from_inventory"
+ label="Choose from inventory"
+ width="140"/>
+ <button
+ follows="left|top"
+ height="23"
+ layout="topleft"
+ left_delta="0"
+ top_pad="4"
+ name="edit_selected_pbr"
+ label="Edit Selected"
+ width="140"/>
+ <button
+ follows="left|top"
+ height="23"
+ layout="topleft"
+ left_delta="0"
+ top_pad="4"
+ name="save_selected_pbr"
+ label="Save to inventory"
+ width="140"/>
+ <texture_picker
+ can_apply_immediately="true"
default_image_name="Default"
fallback_image="materials_ui_x_24.png"
follows="left|top"
@@ -215,7 +301,7 @@
left="10"
name="texture control"
tool_tip="Click to choose a picture"
- top_pad="5"
+ top_delta="-54"
width="64" />
<text
type="string"
@@ -814,13 +900,13 @@
left="7"
name="checkbox planar align"
tool_tip="Align textures on all selected faces with the last selected face. Requires Planar texture mapping."
- top_delta="16"
+ top_delta="20"
width="260" />
<button
- follows="left|top"
- layout="topleft"
+ follows="left|top"
+ layout="topleft"
left="9"
- top="204"
+ top="231"
height="20"
label="Align"
label_selected="Align current texture layers"
@@ -839,4 +925,67 @@
height="4"
start_url="about:blank"
decouple_texture_size="true" />
- </panel>
+ <!-- BEGIN PBR Material texture transform parameters -->
+ <spinner
+ follows="left|top"
+ height="19"
+ initial_value="1"
+ label="Scale u"
+ label_width="205"
+ layout="topleft"
+ left="10"
+ min_val="-100"
+ max_val="100"
+ name="gltfTextureScaleU"
+ top_delta="34"
+ width="265" />
+ <spinner
+ follows="left|top"
+ height="19"
+ initial_value="1"
+ label="Scale v"
+ label_width="205"
+ layout="topleft"
+ left="10"
+ min_val="-100"
+ max_val="100"
+ name="gltfTextureScaleV"
+ width="265" />
+ <spinner
+ follows="left|top"
+ height="19"
+ initial_value="0"
+ label="Rotation"
+ label_width="205"
+ layout="topleft"
+ left="10"
+ min_val="-360"
+ max_val="360"
+ name="gltfTextureRotation"
+ width="265" />
+ <spinner
+ follows="left|top"
+ height="19"
+ initial_value="0"
+ label="Offset u"
+ label_width="205"
+ layout="topleft"
+ left="10"
+ min_val="-999"
+ max_val="999"
+ name="gltfTextureOffsetU"
+ width="265" />
+ <spinner
+ follows="left|top"
+ height="19"
+ initial_value="0"
+ label="Offset v"
+ label_width="205"
+ layout="topleft"
+ left="10"
+ min_val="-999"
+ max_val="999"
+ name="gltfTextureOffsetV"
+ width="265" />
+ <!-- END PBR Material texture transform parameters -->
+</panel>
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 42a10e8c56..7177cb1273 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -319,6 +319,11 @@ Only items with unrestricted
'next owner' permissions
can be attached to notecards.
</string>
+ <string name="TooltipTextureRestrictedDrop">
+Only textures with unrestricted
+copy and transfer permissions
+are allowed.
+ </string>
<!-- searching - generic -->
<string name="Searching">Searching...</string>
@@ -403,6 +408,7 @@ http://secondlife.com/support for help fixing this problem.
<string name="symbolic link">link</string>
<string name="symbolic folder link">folder link</string>
<string name="settings blob">settings</string>
+ <string name="render material">material</string>
<string name="mesh">mesh</string>
<!-- llvoavatar. Displayed in the avatar chat bubble -->
@@ -2426,6 +2432,7 @@ If you continue to receive this message, please contact Second Life support for
<string name="Clothing" value=" Clothing," />
<string name="Gestures" value=" Gestures," />
<string name="Landmarks" value=" Landmarks," />
+ <string name="Materials" value=" Materials," />
<string name="Notecards" value=" Notecards," />
<string name="Objects" value=" Objects," />
<string name="Scripts" value=" Scripts," />
@@ -2471,6 +2478,9 @@ If you continue to receive this message, please contact Second Life support for
<string name="InvFolder Meshes">Meshes</string>
<string name="InvFolder Received Items">Received Items</string>
<string name="InvFolder Merchant Outbox">Merchant Outbox</string>
+ <string name="InvFolder Settings">Settings</string>
+ <string name="InvFolder Material">Materials</string>
+ <string name="InvFolder Materials">Materials</string>
<!-- are used for Friends and Friends/All folders in Inventory "Calling cards" folder. See EXT-694-->
<string name="InvFolder Friends">Friends</string>
@@ -3851,6 +3861,7 @@ Abuse Report</string>
<string name="New Physics">New Physics</string>
<string name="Invalid Wearable">Invalid Wearable</string>
<string name="New Gesture">New Gesture</string>
+ <string name="New Material">New Material</string>
<string name="New Script">New Script</string>
<string name="New Note">New Note</string>
<string name="New Folder">New Folder</string>
@@ -4271,6 +4282,9 @@ name="Command_360_Capture_Tooltip">Capture a 360 equirectangular image</string>
<string name="ExperiencePermissionShort16">Sit</string>
<string name="ExperiencePermissionShort17">Environment</string>
+ <!-- PBR Materials -->
+ <string name="Material Texture Name Header">Textures present this material: </string>
+
<!-- Conversation log messages -->
<string name="logging_calls_disabled_log_empty">
Conversations are not being logged. To begin keeping a log, choose "Save: Log only" or "Save: Log and transcripts" under Preferences > Chat.
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:</text>
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 :</text>
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:</text>
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:</text>
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:</text>
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。
diff --git a/indra/newview/tests/llviewercontrollistener_test.cpp b/indra/newview/tests/llviewercontrollistener_test.cpp
new file mode 100644
index 0000000000..6d100ef984
--- /dev/null
+++ b/indra/newview/tests/llviewercontrollistener_test.cpp
@@ -0,0 +1,174 @@
+/**
+ * @file llviewercontrollistener_test.cpp
+ * @author Nat Goodspeed
+ * @date 2022-06-09
+ * @brief Test for llviewercontrollistener.
+ *
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
+ * Copyright (c) 2022, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "llviewerprecompiledheaders.h"
+// associated header
+#include "llviewercontrollistener.h"
+// STL headers
+// std headers
+// external library headers
+// other Linden headers
+#include "../test/lltut.h"
+#include "../test/catch_and_store_what_in.h" // catch_what()
+#include "commoncontrol.h"
+#include "llcontrol.h" // LLControlGroup
+#include "llviewercontrollistener.h"
+
+/*****************************************************************************
+* TUT
+*****************************************************************************/
+namespace tut
+{
+ void ensure_contains(const std::string& msg, const std::string& substr)
+ {
+ ensure_contains("Exception does not contain " + substr, msg, substr);
+ }
+
+ struct llviewercontrollistener_data
+ {
+ LLControlGroup Global{"FakeGlobal"};
+
+ llviewercontrollistener_data()
+ {
+ Global.declareString("strvar", "woof", "string variable");
+ // together we will stroll the boolvar, ma cherie
+ Global.declareBOOL("boolvar", TRUE, "bool variable");
+ }
+ };
+ typedef test_group<llviewercontrollistener_data> llviewercontrollistener_group;
+ typedef llviewercontrollistener_group::object object;
+ llviewercontrollistener_group llviewercontrollistenergrp("llviewercontrollistener");
+
+ template<> template<>
+ void object::test<1>()
+ {
+ set_test_name("CommonControl no listener");
+ // Not implemented: the linker drags in LLViewerControlListener when
+ // we bring in LLViewerControl.
+ }
+
+ template<> template<>
+ void object::test<2>()
+ {
+ set_test_name("CommonControl bad group");
+ std::string threw{ catch_what<LL::CommonControl::ParamError>(
+ [](){ LL::CommonControl::get("Nonexistent", "Variable"); }) };
+ ensure_contains(threw, "group");
+ ensure_contains(threw, "Nonexistent");
+ }
+
+ template<> template<>
+ void object::test<3>()
+ {
+ set_test_name("CommonControl bad variable");
+ std::string threw{ catch_what<LL::CommonControl::ParamError>(
+ [](){ LL::CommonControl::get("FakeGlobal", "Nonexistent"); }) };
+ ensure_contains(threw, "key");
+ ensure_contains(threw, "Nonexistent");
+ }
+
+ template<> template<>
+ void object::test<4>()
+ {
+ set_test_name("CommonControl toggle string");
+ std::string threw{ catch_what<LL::CommonControl::ParamError>(
+ [](){ LL::CommonControl::toggle("FakeGlobal", "strvar"); }) };
+ ensure_contains(threw, "non-boolean");
+ ensure_contains(threw, "strvar");
+ }
+
+ template<> template<>
+ void object::test<5>()
+ {
+ set_test_name("CommonControl list bad group");
+ std::string threw{ catch_what<LL::CommonControl::ParamError>(
+ [](){ LL::CommonControl::get_vars("Nonexistent"); }) };
+ ensure_contains(threw, "group");
+ ensure_contains(threw, "Nonexistent");
+ }
+
+ template<> template<>
+ void object::test<6>()
+ {
+ set_test_name("CommonControl get");
+ auto strvar{ LL::CommonControl::get("FakeGlobal", "strvar") };
+ ensure_equals(strvar, "woof");
+ auto boolvar{ LL::CommonControl::get("FakeGlobal", "boolvar") };
+ ensure(boolvar);
+ }
+
+ template<> template<>
+ void object::test<7>()
+ {
+ set_test_name("CommonControl set, set_default, toggle");
+
+ std::string newstr{ LL::CommonControl::set("FakeGlobal", "strvar", "mouse").asString() };
+ ensure_equals(newstr, "mouse");
+ ensure_equals(LL::CommonControl::get("FakeGlobal", "strvar").asString(), "mouse");
+ ensure_equals(LL::CommonControl::set_default("FakeGlobal", "strvar").asString(), "woof");
+
+ bool newbool{ LL::CommonControl::set("FakeGlobal", "boolvar", false) };
+ ensure(! newbool);
+ ensure(! LL::CommonControl::get("FakeGlobal", "boolvar").asBoolean());
+ ensure(LL::CommonControl::set_default("FakeGlobal", "boolvar").asBoolean());
+ ensure(! LL::CommonControl::toggle("FakeGlobal", "boolvar").asBoolean());
+ }
+
+ template<> template<>
+ void object::test<8>()
+ {
+ set_test_name("CommonControl get_def");
+ LLSD def{ LL::CommonControl::get_def("FakeGlobal", "strvar") };
+ ensure_equals(
+ def,
+ llsd::map("name", "strvar",
+ "type", "String",
+ "value", "woof",
+ "comment", "string variable"));
+ }
+
+ template<> template<>
+ void object::test<9>()
+ {
+ set_test_name("CommonControl get_groups");
+ std::vector<std::string> groups{ LL::CommonControl::get_groups() };
+ ensure_equals(groups.size(), 1);
+ ensure_equals(groups[0], "FakeGlobal");
+ }
+
+ template<> template<>
+ void object::test<10>()
+ {
+ set_test_name("CommonControl get_vars");
+ LLSD vars{ LL::CommonControl::get_vars("FakeGlobal") };
+ // convert from array (unpredictable order) to map
+ LLSD varsmap{ LLSD::emptyMap() };
+ for (auto& var : llsd::inArray(vars))
+ {
+ varsmap[var["name"].asString()] = var;
+ }
+ // comparing maps is order-insensitive
+ ensure_equals(
+ varsmap,
+ llsd::map(
+ "strvar",
+ llsd::map("name", "strvar",
+ "type", "String",
+ "value", "woof",
+ "comment", "string variable"),
+ "boolvar",
+ llsd::map("name", "boolvar",
+ "type", "Boolean",
+ "value", TRUE,
+ "comment", "bool variable")));
+ }
+} // namespace tut
diff --git a/indra/test/test.cpp b/indra/test/test.cpp
index bb48216b2b..28f25087ac 100644
--- a/indra/test/test.cpp
+++ b/indra/test/test.cpp
@@ -401,7 +401,7 @@ public:
{
// Per http://confluence.jetbrains.net/display/TCD65/Build+Script+Interaction+with+TeamCity#BuildScriptInteractionwithTeamCity-ServiceMessages
std::string result;
- BOOST_FOREACH(char c, str)
+ for (char c : str)
{
switch (c)
{