diff options
Diffstat (limited to 'indra')
29 files changed, 985 insertions, 485 deletions
| diff --git a/indra/llcommon/llprofilercategories.h b/indra/llcommon/llprofilercategories.h index 0de343d020..1c4f0f5624 100644 --- a/indra/llcommon/llprofilercategories.h +++ b/indra/llcommon/llprofilercategories.h @@ -67,6 +67,7 @@  #define LL_PROFILER_CATEGORY_ENABLE_VERTEX      1  #define LL_PROFILER_CATEGORY_ENABLE_VOLUME      1  #define LL_PROFILER_CATEGORY_ENABLE_WIN32       1 +#define LL_PROFILER_CATEGORY_ENABLE_GLTF        1  #define LL_PROFILER_CATEGORY_ENABLE_VOICE       1  #if LL_PROFILER_CATEGORY_ENABLE_APP @@ -277,12 +278,19 @@      #define LL_PROFILE_ZONE_SCOPED_CATEGORY_WIN32  #endif +#if LL_PROFILER_CATEGORY_ENABLE_GLTF +    #define LL_PROFILE_ZONE_NAMED_CATEGORY_GLTF  LL_PROFILE_ZONE_NAMED +    #define LL_PROFILE_ZONE_SCOPED_CATEGORY_GLTF LL_PROFILE_ZONE_SCOPED +#else +    #define LL_PROFILE_ZONE_NAMED_CATEGORY_GLTF(name) +    #define LL_PROFILE_ZONE_SCOPED_CATEGORY_GLTF +#endif  #if LL_PROFILER_CATEGORY_ENABLE_VOICE -#define LL_PROFILE_ZONE_NAMED_CATEGORY_VOICE  LL_PROFILE_ZONE_NAMED -#define LL_PROFILE_ZONE_SCOPED_CATEGORY_VOICE LL_PROFILE_ZONE_SCOPED +    #define LL_PROFILE_ZONE_NAMED_CATEGORY_VOICE  LL_PROFILE_ZONE_NAMED +    #define LL_PROFILE_ZONE_SCOPED_CATEGORY_VOICE LL_PROFILE_ZONE_SCOPED  #else -#define LL_PROFILE_ZONE_NAMED_CATEGORY_VOICE(name) -#define LL_PROFILE_ZONE_SCOPED_CATEGORY_VOICE +    #define LL_PROFILE_ZONE_NAMED_CATEGORY_VOICE(name) +    #define LL_PROFILE_ZONE_SCOPED_CATEGORY_VOICE  #endif  #endif // LL_PROFILER_CATEGORIES_H diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index e22df46b28..25e4a88f28 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -54,6 +54,8 @@ using std::string;  GLuint LLGLSLShader::sCurBoundShader = 0;  LLGLSLShader* LLGLSLShader::sCurBoundShaderPtr = NULL;  S32 LLGLSLShader::sIndexedTextureChannels = 0; +U32 LLGLSLShader::sMaxGLTFMaterials = 0; +U32 LLGLSLShader::sMaxGLTFNodes = 0;  bool LLGLSLShader::sProfileEnabled = false;  std::set<LLGLSLShader*> LLGLSLShader::sInstances;  LLGLSLShader::defines_map_t LLGLSLShader::sGlobalDefines; @@ -978,7 +980,9 @@ bool LLGLSLShader::mapUniforms()      const char* ubo_names[] =      {          "ReflectionProbes", // UB_REFLECTION_PROBES -        "GLTFJoints", // UB_GLTF_JOINTS +        "GLTFJoints",       // UB_GLTF_JOINTS +        "GLTFNodes",        // UB_GLTF_NODES +        "GLTFMaterials",    // UB_GLTF_MATERIALS      };      llassert(LL_ARRAY_SIZE(ubo_names) == NUM_UNIFORM_BLOCKS); diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index cc2ba0fcff..86e5625dca 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -147,8 +147,10 @@ public:      enum UniformBlock : GLuint      { -        UB_REFLECTION_PROBES, -        UB_GLTF_JOINTS, +        UB_REFLECTION_PROBES,   // "ReflectionProbes" +        UB_GLTF_JOINTS,         // "GLTFJoints" +        UB_GLTF_NODES,          // "GLTFNodes" +        UB_GLTF_MATERIALS,      // "GLTFMaterials"          NUM_UNIFORM_BLOCKS      }; @@ -163,6 +165,9 @@ public:      static LLGLSLShader* sCurBoundShaderPtr;      static S32 sIndexedTextureChannels; +    static U32 sMaxGLTFMaterials; +    static U32 sMaxGLTFNodes; +      static void initProfile();      static void finishProfile(bool emit_report = true); diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index cfefde3acc..a0209fab43 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -991,6 +991,8 @@ void LLRender::syncLightState()  void LLRender::syncMatrices()  {      STOP_GLERROR; +    LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; +      static const U32 name[] =      {          LLShaderMgr::MODELVIEW_MATRIX, diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 574cf55a0e..a8e9f20b40 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -1185,6 +1185,8 @@ void LLShaderMgr::initAttribsAndUniforms()      mReservedUniforms.push_back("normal_texcoord"); // (GLTF)      mReservedUniforms.push_back("metallic_roughness_texcoord"); // (GLTF)      mReservedUniforms.push_back("occlusion_texcoord"); // (GLTF) +    mReservedUniforms.push_back("gltf_node_id"); // (GLTF) +    mReservedUniforms.push_back("gltf_material_id"); // (GLTF)      mReservedUniforms.push_back("terrain_texture_transforms"); // (GLTF) diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index c00aff3a9a..fe6137c448 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -63,6 +63,8 @@ public:          NORMAL_TEXCOORD,                      //  "normal_texcoord" (GLTF)          METALLIC_ROUGHNESS_TEXCOORD,          //  "metallic_roughness_texcoord" (GLTF)          OCCLUSION_TEXCOORD,                   //  "occlusion_texcoord" (GLTF) +        GLTF_NODE_ID,                         //  "gltf_node_id" (GLTF) +        GLTF_MATERIAL_ID,                     //  "gltf_material_id" (GLTF)          TERRAIN_TEXTURE_TRANSFORMS,           //  "terrain_texture_transforms" (GLTF) diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index f82ec30242..2eb7c21f77 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -806,6 +806,13 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi      STOP_GLERROR;  } +void LLVertexBuffer::drawRangeFast(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const +{ +    glDrawRangeElements(sGLMode[mode], start, end, count, mIndicesType, +        (GLvoid*)(indices_offset * (size_t)mIndicesStride)); +} + +  void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const  {      drawRange(mode, 0, mNumVerts-1, count, indices_offset); @@ -1062,12 +1069,6 @@ bool LLVertexBuffer::updateNumVerts(U32 nverts)      bool success = true; -    if (nverts > 65536) -    { -        LL_WARNS() << "Vertex buffer overflow!" << LL_ENDL; -        nverts = 65536; -    } -      U32 needed_size = calcOffsets(mTypeMask, mOffsets, nverts);      if (needed_size != mSize) @@ -1210,7 +1211,7 @@ U8* LLVertexBuffer::mapIndexBuffer(U32 index, S32 count)  //  end -- last byte to copy (NOT last byte + 1)  //  data -- data to be flushed  //  dst -- mMappedData or mMappedIndexData -static void flush_vbo(GLenum target, U32 start, U32 end, void* data, U8* dst) +void LLVertexBuffer::flush_vbo(GLenum target, U32 start, U32 end, void* data, U8* dst)  {  #if LL_DARWIN      LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vb memcpy"); @@ -1218,6 +1219,8 @@ static void flush_vbo(GLenum target, U32 start, U32 end, void* data, U8* dst)      // copy into mapped buffer      memcpy(dst+start, data, end-start+1);  #else +    llassert(target == GL_ARRAY_BUFFER ? sGLRenderBuffer == mGLBuffer : sGLRenderIndices == mGLIndices); +      // skip mapped data and stream to GPU via glBufferSubData      if (end != 0)      { @@ -1627,81 +1630,51 @@ void LLVertexBuffer::setupVertexBuffer()  void LLVertexBuffer::setPositionData(const LLVector4a* data)  { -#if !LL_DARWIN -    llassert(sGLRenderBuffer == mGLBuffer); -#endif      flush_vbo(GL_ARRAY_BUFFER, 0, sizeof(LLVector4a) * getNumVerts()-1, (U8*) data, mMappedData);  }  void LLVertexBuffer::setTexCoord0Data(const LLVector2* data)  { -#if !LL_DARWIN -    llassert(sGLRenderBuffer == mGLBuffer); -#endif      flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_TEXCOORD0], mOffsets[TYPE_TEXCOORD0] + sTypeSize[TYPE_TEXCOORD0] * getNumVerts() - 1, (U8*)data, mMappedData);  }  void LLVertexBuffer::setTexCoord1Data(const LLVector2* data)  { -#if !LL_DARWIN -    llassert(sGLRenderBuffer == mGLBuffer); -#endif      flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_TEXCOORD1], mOffsets[TYPE_TEXCOORD1] + sTypeSize[TYPE_TEXCOORD1] * getNumVerts() - 1, (U8*)data, mMappedData);  }  void LLVertexBuffer::setColorData(const LLColor4U* data)  { -#if !LL_DARWIN -    llassert(sGLRenderBuffer == mGLBuffer); -#endif      flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_COLOR], mOffsets[TYPE_COLOR] + sTypeSize[TYPE_COLOR] * getNumVerts() - 1, (U8*) data, mMappedData);  }  void LLVertexBuffer::setNormalData(const LLVector4a* data)  { -#if !LL_DARWIN -    llassert(sGLRenderBuffer == mGLBuffer); -#endif      flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_NORMAL], mOffsets[TYPE_NORMAL] + sTypeSize[TYPE_NORMAL] * getNumVerts() - 1, (U8*) data, mMappedData);  }  void LLVertexBuffer::setTangentData(const LLVector4a* data)  { -#if !LL_DARWIN -    llassert(sGLRenderBuffer == mGLBuffer); -#endif      flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_TANGENT], mOffsets[TYPE_TANGENT] + sTypeSize[TYPE_TANGENT] * getNumVerts() - 1, (U8*) data, mMappedData);  }  void LLVertexBuffer::setWeight4Data(const LLVector4a* data)  { -#if !LL_DARWIN -    llassert(sGLRenderBuffer == mGLBuffer); -#endif      flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_WEIGHT4], mOffsets[TYPE_WEIGHT4] + sTypeSize[TYPE_WEIGHT4] * getNumVerts() - 1, (U8*) data, mMappedData);  }  void LLVertexBuffer::setJointData(const U64* data)  { -#if !LL_DARWIN -    llassert(sGLRenderBuffer == mGLBuffer); -#endif      flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_JOINT], mOffsets[TYPE_JOINT] + sTypeSize[TYPE_JOINT] * getNumVerts() - 1, (U8*) data, mMappedData);  }  void LLVertexBuffer::setIndexData(const U16* data)  { -#if !LL_DARWIN -    llassert(sGLRenderIndices == mGLIndices); -#endif      flush_vbo(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(U16) * getNumIndices() - 1, (U8*) data, mMappedIndexData);  }  void LLVertexBuffer::setIndexData(const U32* data)  { -#if !LL_DARWIN -    llassert(sGLRenderIndices == mGLIndices); -#endif      if (mIndicesType != GL_UNSIGNED_INT)      { // HACK -- vertex buffers are initialized as 16-bit indices, but can be switched to 32-bit indices          mIndicesType = GL_UNSIGNED_INT; @@ -1711,3 +1684,62 @@ void LLVertexBuffer::setIndexData(const U32* data)      flush_vbo(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(U32) * getNumIndices() - 1, (U8*)data, mMappedIndexData);  } +void LLVertexBuffer::setPositionData(const LLVector4a* data, U32 offset, U32 count) +{ +    flush_vbo(GL_ARRAY_BUFFER, offset * sizeof(LLVector4a), (offset + count) * sizeof(LLVector4a) - 1, (U8*)data, mMappedData); +} + +void LLVertexBuffer::setNormalData(const LLVector4a* data, U32 offset, U32 count) +{ +    flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_NORMAL] + offset * sTypeSize[TYPE_NORMAL], mOffsets[TYPE_NORMAL] + (offset + count) * sTypeSize[TYPE_NORMAL] - 1, (U8*)data, mMappedData); +} + +void LLVertexBuffer::setTexCoord0Data(const LLVector2* data, U32 offset, U32 count) +{ +    flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_TEXCOORD0] + offset * sTypeSize[TYPE_TEXCOORD0], mOffsets[TYPE_TEXCOORD0] + (offset + count) * sTypeSize[TYPE_TEXCOORD0] - 1, (U8*)data, mMappedData); +} + +void LLVertexBuffer::setTexCoord1Data(const LLVector2* data, U32 offset, U32 count) +{ +    flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_TEXCOORD1] + offset * sTypeSize[TYPE_TEXCOORD1], mOffsets[TYPE_TEXCOORD1] + (offset + count) * sTypeSize[TYPE_TEXCOORD1] - 1, (U8*)data, mMappedData); +} + +void LLVertexBuffer::setColorData(const LLColor4U* data, U32 offset, U32 count) +{ +    flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_COLOR] + offset * sTypeSize[TYPE_COLOR], mOffsets[TYPE_COLOR] + (offset + count) * sTypeSize[TYPE_COLOR] - 1, (U8*)data, mMappedData); +} + +void LLVertexBuffer::setTangentData(const LLVector4a* data, U32 offset, U32 count) +{ +    flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_TANGENT] + offset * sTypeSize[TYPE_TANGENT], mOffsets[TYPE_TANGENT] + (offset + count) * sTypeSize[TYPE_TANGENT] - 1, (U8*)data, mMappedData); +} + +void LLVertexBuffer::setWeight4Data(const LLVector4a* data, U32 offset, U32 count) +{ +    flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_WEIGHT4] + offset * sTypeSize[TYPE_WEIGHT4], mOffsets[TYPE_WEIGHT4] + (offset + count) * sTypeSize[TYPE_WEIGHT4] - 1, (U8*)data, mMappedData); +} + +void LLVertexBuffer::setJointData(const U64* data, U32 offset, U32 count) +{ +    flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_JOINT] + offset * sTypeSize[TYPE_JOINT], mOffsets[TYPE_JOINT] + (offset + count) * sTypeSize[TYPE_JOINT] - 1, (U8*)data, mMappedData); +} + +void LLVertexBuffer::setIndexData(const U16* data, U32 offset, U32 count) +{ +    flush_vbo(GL_ELEMENT_ARRAY_BUFFER, offset * sizeof(U16), (offset + count) * sizeof(U16) - 1, (U8*)data, mMappedIndexData); +} + +void LLVertexBuffer::setIndexData(const U32* data, U32 offset, U32 count) +{ +    if (mIndicesType != GL_UNSIGNED_INT) +    { // HACK -- vertex buffers are initialized as 16-bit indices, but can be switched to 32-bit indices +        mIndicesType = GL_UNSIGNED_INT; +        mIndicesStride = 4; +        mNumIndices /= 2; +    } +    flush_vbo(GL_ELEMENT_ARRAY_BUFFER, offset * sizeof(U32), (offset + count) * sizeof(U32) - 1, (U8*)data, mMappedIndexData); +} + + + + diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index 601096abf9..49500e28ce 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -202,6 +202,18 @@ public:      void setIndexData(const U16* data);      void setIndexData(const U32* data); +    void setPositionData(const LLVector4a* data, U32 offset, U32 count); +    void setNormalData(const LLVector4a* data, U32 offset, U32 count); +    void setTangentData(const LLVector4a* data, U32 offset, U32 count); +    void setWeight4Data(const LLVector4a* data, U32 offset, U32 count); +    void setJointData(const U64* data, U32 offset, U32 count); +    void setTexCoord0Data(const LLVector2* data, U32 offset, U32 count); +    void setTexCoord1Data(const LLVector2* data, U32 offset, U32 count); +    void setColorData(const LLColor4U* data, U32 offset, U32 count); +    void setIndexData(const U16* data, U32 offset, U32 count); +    void setIndexData(const U32* data, U32 offset, U32 count); + +      U32 getNumVerts() const                 { return mNumVerts; }      U32 getNumIndices() const               { return mNumIndices; } @@ -219,6 +231,10 @@ public:      void drawArrays(U32 mode, U32 offset, U32 count) const;      void drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const; +    // draw without syncing matrices.  If you're positive there have been no matrix +    // since the last call to syncMatrices, this is much faster than drawRange +    void drawRangeFast(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const; +      //for debugging, validate data in given range is valid      bool validateRange(U32 start, U32 end, U32 count, U32 offset) const; @@ -256,6 +272,8 @@ private:      friend class LLNavShapeVBOManager;      friend class LLNavMeshVBOManager; +    void flush_vbo(GLenum target, U32 start, U32 end, void* data, U8* dst); +      LLVertexBuffer(U32 typemask, U32 usage)          : LLVertexBuffer(typemask)      {} diff --git a/indra/newview/app_settings/shaders/class1/gltf/pbrmetallicroughnessF.glsl b/indra/newview/app_settings/shaders/class1/gltf/pbrmetallicroughnessF.glsl index 789c00259b..ac4ff50552 100644 --- a/indra/newview/app_settings/shaders/class1/gltf/pbrmetallicroughnessF.glsl +++ b/indra/newview/app_settings/shaders/class1/gltf/pbrmetallicroughnessF.glsl @@ -28,18 +28,40 @@  // GLTF pbrMetallicRoughness implementation +uniform int gltf_material_id; + +vec3 emissiveColor = vec3(0,0,0); +float metallicFactor = 1.0; +float roughnessFactor = 1.0; +float minimum_alpha = -1.0; + +layout (std140) uniform GLTFMaterials +{ +    // see pbrmetallicroughnessV.glsl for packing +    vec4 gltf_material_data[MAX_UBO_VEC4S]; +}; + +void unpackMaterial() +{ +    if (gltf_material_id > -1) +    { +        int idx = gltf_material_id*12; +        emissiveColor = gltf_material_data[idx+10].rgb; +        roughnessFactor = gltf_material_data[idx+11].g; +        metallicFactor = gltf_material_data[idx+11].b; +        minimum_alpha -= gltf_material_data[idx+11].a; +    } +}  // ==================================  // needed by all variants  // ==================================  uniform sampler2D diffuseMap;  //always in sRGB space  uniform sampler2D emissiveMap; -uniform vec3 emissiveColor;  in vec3 vary_position;  in vec4 vertex_color;  in vec2 base_color_uv;  in vec2 emissive_uv; -uniform float minimum_alpha;  void mirrorClip(vec3 pos);  vec3 linear_to_srgb(vec3 c); @@ -54,8 +76,6 @@ vec3 srgb_to_linear(vec3 c);  uniform sampler2D normalMap;  uniform sampler2D metallicRoughnessMap;  uniform sampler2D occlusionMap; -uniform float metallicFactor; -uniform float roughnessFactor;  in vec3 vary_normal;  in vec3 vary_tangent;  flat in float vary_sign; @@ -154,7 +174,7 @@ out vec4 frag_data[4];  void main()  { - +    unpackMaterial();  // ==================================  // all variants  //   mirror clip @@ -165,6 +185,10 @@ void main()      vec3 pos = vary_position;      mirrorClip(pos); +#ifdef ALPHA_BLEND +    //waterClip(pos); +#endif +      vec4 basecolor = texture(diffuseMap, base_color_uv.xy).rgba;      basecolor.rgb = srgb_to_linear(basecolor.rgb);      basecolor *= vertex_color; diff --git a/indra/newview/app_settings/shaders/class1/gltf/pbrmetallicroughnessV.glsl b/indra/newview/app_settings/shaders/class1/gltf/pbrmetallicroughnessV.glsl index aac3dc917f..6a628bc852 100644 --- a/indra/newview/app_settings/shaders/class1/gltf/pbrmetallicroughnessV.glsl +++ b/indra/newview/app_settings/shaders/class1/gltf/pbrmetallicroughnessV.glsl @@ -26,19 +26,95 @@  // GLTF pbrMetallicRoughness implementation  uniform mat4 modelview_matrix; - -#ifdef HAS_SKIN  uniform mat4 projection_matrix; -#else -uniform mat3 normal_matrix; -uniform mat4 modelview_projection_matrix; + +#ifdef MULTI_UV +in vec2 texcoord1; +int base_color_texcoord = 0; +int emissive_texcoord = 0; +#ifndef UNLIT +int normal_texcoord = 0; +int metallic_roughness_texcoord = 0; +int occlusion_texcoord = 0; +#endif +#endif + +uniform int gltf_material_id; + +layout (std140) uniform GLTFMaterials +{ +    // index by gltf_material_id*12 + +    // [gltf_material_id + [0-1]] -  base color transform +    // [gltf_material_id + [2-3]] -  normal transform +    // [gltf_material_id + [4-5]] -  metallic roughness transform +    // [gltf_material_id + [6-7]] -  emissive transform +    // [gltf_material_id + [8-9]] -  occlusion transform +    // [gltf_material_id + 10]    -  emissive factor +    // [gltf_material_id + 11]    -  .r unused, .g roughness, .b metalness, .a minimum alpha + +    // Transforms are packed as follows +    // packed[0] = vec4(scale.x, scale.y, rotation, offset.x) +    // packed[1] = vec4(mScale.y, texcoord, 0, 0) +    vec4 gltf_material_data[MAX_UBO_VEC4S]; +}; + +vec4[2] texture_base_color_transform; +vec4[2] texture_normal_transform; +vec4[2] texture_metallic_roughness_transform; +vec4[2] texture_emissive_transform; +vec4[2] texture_occlusion_transform; + +void unpackTextureTransforms() +{ +    if (gltf_material_id != -1) +    { +        int idx = gltf_material_id*12; + +        texture_base_color_transform[0] = gltf_material_data[idx+0]; +        texture_base_color_transform[1] = gltf_material_data[idx+1]; + +        texture_normal_transform[0] = gltf_material_data[idx+2]; +        texture_normal_transform[1] = gltf_material_data[idx+3]; + +        texture_metallic_roughness_transform[0] = gltf_material_data[idx+4]; +        texture_metallic_roughness_transform[1] = gltf_material_data[idx+5]; + +        texture_emissive_transform[0] = gltf_material_data[idx+6]; +        texture_emissive_transform[1] = gltf_material_data[idx+7]; + +        texture_occlusion_transform[0] = gltf_material_data[idx+8]; +        texture_occlusion_transform[1] = gltf_material_data[idx+9]; + +#ifdef MULTI_UV +        base_color_texcoord = int(gltf_material_data[idx+1].g); +        emissive_texcoord = int(gltf_material_data[idx+7].g); +#ifndef UNLIT +        normal_texcoord = int(gltf_material_data[idx+3].g); +        metallic_roughness_texcoord = int(gltf_material_data[idx+5].g); +        occlusion_texcoord = int(gltf_material_data[idx+9].g);  #endif +#endif +    } +    else +    { +        texture_base_color_transform[0] = vec4(1.0, 1.0, 0.0, 0.0); +        texture_base_color_transform[1] = vec4(0.0, 0.0, 0.0, 0.0); + +        texture_normal_transform[0] = vec4(1.0, 1.0, 0.0, 0.0); +        texture_normal_transform[1] = vec4(0.0, 0.0, 0.0, 0.0); + +        texture_metallic_roughness_transform[0] = vec4(1.0, 1.0, 0.0, 0.0); +        texture_metallic_roughness_transform[1] = vec4(0.0, 0.0, 0.0, 0.0); + +        texture_emissive_transform[0] = vec4(1.0, 1.0, 0.0, 0.0); +        texture_emissive_transform[1] = vec4(0.0, 0.0, 0.0, 0.0); + +        texture_occlusion_transform[0] = vec4(1.0, 1.0, 0.0, 0.0); +        texture_occlusion_transform[1] = vec4(0.0, 0.0, 0.0, 0.0); +    } +} -uniform vec4[2] texture_base_color_transform; -uniform vec4[2] texture_normal_transform; -uniform vec4[2] texture_metallic_roughness_transform; -uniform vec4[2] texture_emissive_transform; -uniform vec4[2] texture_occlusion_transform;  in vec3 position;  in vec4 diffuse_color; @@ -59,17 +135,6 @@ flat out float vary_sign;  out vec3 vary_normal;  #endif -#ifdef MULTI_UV -in vec2 texcoord1; -uniform int base_color_texcoord; -uniform int emissive_texcoord; -#ifndef UNLIT -uniform int normal_texcoord; -uniform int metallic_roughness_texcoord; -uniform int occlusion_texcoord; -#endif -#endif -  vec2 gltf_texture_transform(vec2 texcoord, vec4[2] p)  {      texcoord.y = 1.0 - texcoord.y; @@ -124,23 +189,22 @@ vec3 gltf_tangent_space_transform(vec4 vertex_tangent, vec3 vertex_normal, vec4[  }  #endif - -  #ifdef ALPHA_BLEND  out vec3 vary_fragcoord;  #endif  #ifdef HAS_SKIN -in uvec4 joint; -in vec4 weight4;  layout (std140) uniform GLTFJoints  { -    // list of OBBs for user override probes -    mat3x4 gltf_joints[MAX_JOINTS_PER_GLTF_OBJECT]; +    mat3x4 gltf_joints[MAX_NODES_PER_GLTF_OBJECT];  }; -mat4 getGLTFSkinTransform() + +in uvec4 joint; +in vec4 weight4; + +mat4 getGLTFTransform()  {      int i; @@ -169,21 +233,37 @@ mat4 getGLTFSkinTransform()      ret[3] = vec4(trans, 1.0);      return ret; +} -#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. -   mat3x4 dummy1 = gltf_joints[0]; -   mat3x4 dummy2 = gltf_joints[MAX_JOINTS_PER_GLTF_OBJECT-1]; -#endif +#else + +layout (std140) uniform GLTFNodes +{ +    mat3x4 gltf_nodes[MAX_NODES_PER_GLTF_OBJECT]; +}; + +uniform int gltf_node_id = 0; + +mat4 getGLTFTransform() +{ +    mat4 ret; +    mat3x4 src = gltf_nodes[gltf_node_id]; + +    ret[0] = vec4(src[0].xyz, 0); +    ret[1] = vec4(src[1].xyz, 0); +    ret[2] = vec4(src[2].xyz, 0); + +    ret[3] = vec4(src[0].w, src[1].w, src[2].w, 1); +    return ret;  }  #endif  void main()  { -#ifdef HAS_SKIN -    mat4 mat = getGLTFSkinTransform(); +    unpackTextureTransforms(); +    mat4 mat = getGLTFTransform();      mat = modelview_matrix * mat; @@ -193,13 +273,6 @@ void main()      vec4 vert = projection_matrix * vec4(pos, 1.0);      gl_Position = vert; -#else -    vary_position = (modelview_matrix*vec4(position.xyz, 1.0)).xyz; -    //transform vertex -    vec4 vert = modelview_projection_matrix * vec4(position.xyz, 1.0); -    gl_Position = vert; -#endif -      vec2 bcuv;      vec2 emuv; @@ -237,13 +310,8 @@ void main()  #endif  #ifndef UNLIT -#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      n = normalize(n);      vary_tangent = normalize(gltf_tangent_space_transform(vec4(t, tangent.w), n, texture_normal_transform)); diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt index 8950770172..03849a0326 100644 --- a/indra/newview/featuretable.txt +++ b/indra/newview/featuretable.txt @@ -111,7 +111,7 @@ RenderReflectionProbeLevel  1   0  RenderMirrors				1	0  RenderHeroProbeResolution	1	256  RenderHeroProbeDistance		1	4 -RenderHeroProbeUpdateRate	1	4 +RenderHeroProbeUpdateRate	1	6  RenderHeroProbeConservativeUpdateMultiplier 1 16  // diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt index 8c71235f37..7aa8504eaa 100644 --- a/indra/newview/featuretable_mac.txt +++ b/indra/newview/featuretable_mac.txt @@ -109,7 +109,7 @@ RenderReflectionProbeLevel  1   0  RenderMirrors				1	0  RenderHeroProbeResolution	1	256  RenderHeroProbeDistance		1	4 -RenderHeroProbeUpdateRate	1	4 +RenderHeroProbeUpdateRate	1   6  RenderHeroProbeConservativeUpdateMultiplier 1 16  // diff --git a/indra/newview/gltf/animation.cpp b/indra/newview/gltf/animation.cpp index 8b85eba3e5..3dff67d746 100644 --- a/indra/newview/gltf/animation.cpp +++ b/indra/newview/gltf/animation.cpp @@ -70,6 +70,14 @@ bool Animation::prep(Asset& asset)          }      } +    for (auto& channel : mScaleChannels) +    { +        if (!channel.prep(asset, mSamplers[channel.mSampler])) +        { +            return false; +        } +    } +      return true;  } @@ -82,18 +90,37 @@ void Animation::update(Asset& asset, F32 dt)  void Animation::apply(Asset& asset, float time)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_GLTF; +      // convert time to animation loop time      time = fmod(time, mMaxTime - mMinTime) + mMinTime;      // apply each channel -    for (auto& channel : mRotationChannels)      { -        channel.apply(asset, mSamplers[channel.mSampler], time); +        LL_PROFILE_ZONE_NAMED_CATEGORY_GLTF("gltfanim - rotation"); + +        for (auto& channel : mRotationChannels) +        { +            channel.apply(asset, mSamplers[channel.mSampler], time); +        } +    } + +    { +        LL_PROFILE_ZONE_NAMED_CATEGORY_GLTF("gltfanim - translation"); + +        for (auto& channel : mTranslationChannels) +        { +            channel.apply(asset, mSamplers[channel.mSampler], time); +        }      } -    for (auto& channel : mTranslationChannels)      { -        channel.apply(asset, mSamplers[channel.mSampler], time); +        LL_PROFILE_ZONE_NAMED_CATEGORY_GLTF("gltfanim - scale"); + +        for (auto& channel : mScaleChannels) +        { +            channel.apply(asset, mSamplers[channel.mSampler], time); +        }      }  }; @@ -178,7 +205,8 @@ const Animation::Channel& Animation::Channel::operator=(const Value& src)  void Animation::Sampler::getFrameInfo(Asset& asset, F32 time, U32& frameIndex, F32& t)  { -    LL_PROFILE_ZONE_SCOPED; +    LL_PROFILE_ZONE_SCOPED_CATEGORY_GLTF; +    llassert(mFrameTimes.size() > 1); // if there is only one frame, there is no need to interpolate      if (time < mMinTime)      { @@ -187,32 +215,33 @@ void Animation::Sampler::getFrameInfo(Asset& asset, F32 time, U32& frameIndex, F          return;      } -    if (mFrameTimes.size() > 1) +    frameIndex = U32(mFrameTimes.size()) - 2; +    t = 1.f; + +    if (time > mMaxTime)      { -        llassert(mFrameTimes.size() <= size_t(U32_MAX)); -        frameIndex = U32(mFrameTimes.size()) - 2; -        t = 1.f; +        return; +    } -        if (time > mMaxTime) -        { -            return; -        } +    if (time < mLastFrameTime) +    { +        mLastFrameIndex = 0; +    } -        for (U32 i = 0; i < (U32)mFrameTimes.size() - 1; i++) +    mLastFrameTime = time; + +    U32 idx = mLastFrameIndex; + +    for (U32 i = idx; i < (U32)mFrameTimes.size() - 1; i++) +    { +        if (time >= mFrameTimes[i] && time < mFrameTimes[i + 1])          { -            if (time >= mFrameTimes[i] && time < mFrameTimes[i + 1]) -            { -                frameIndex = i; -                t = (time - mFrameTimes[i]) / (mFrameTimes[i + 1] - mFrameTimes[i]); -                return; -            } +            frameIndex = i; +            t = (time - mFrameTimes[i]) / (mFrameTimes[i + 1] - mFrameTimes[i]); +            mLastFrameIndex = frameIndex; +            return;          }      } -    else -    { -        frameIndex = 0; -        t = 0.0f; -    }  }  bool Animation::RotationChannel::prep(Asset& asset, Animation::Sampler& sampler) @@ -231,14 +260,14 @@ void Animation::RotationChannel::apply(Asset& asset, Sampler& sampler, F32 time)      Node& node = asset.mNodes[mTarget.mNode]; -    sampler.getFrameInfo(asset, time, frameIndex, t); - -    if (sampler.mFrameTimes.size() == 1) +    if (sampler.mFrameTimes.size() < 2)      {          node.setRotation(mRotations[0]);      }      else      { +        sampler.getFrameInfo(asset, time, frameIndex, t); +          // interpolate          quat qf = glm::slerp(mRotations[frameIndex], mRotations[frameIndex + 1], t); @@ -264,14 +293,14 @@ void Animation::TranslationChannel::apply(Asset& asset, Sampler& sampler, F32 ti      Node& node = asset.mNodes[mTarget.mNode]; -    sampler.getFrameInfo(asset, time, frameIndex, t); - -    if (sampler.mFrameTimes.size() == 1) +    if (sampler.mFrameTimes.size() < 2)      {          node.setTranslation(mTranslations[0]);      }      else      { +        sampler.getFrameInfo(asset, time, frameIndex, t); +          // interpolate          const vec3& v0 = mTranslations[frameIndex];          const vec3& v1 = mTranslations[frameIndex + 1]; @@ -298,14 +327,14 @@ void Animation::ScaleChannel::apply(Asset& asset, Sampler& sampler, F32 time)      Node& node = asset.mNodes[mTarget.mNode]; -    sampler.getFrameInfo(asset, time, frameIndex, t); - -    if (sampler.mFrameTimes.size() == 1) +    if (sampler.mFrameTimes.size() < 2)      {          node.setScale(mScales[0]);      }      else      { +        sampler.getFrameInfo(asset, time, frameIndex, t); +          // interpolate          const vec3& v0 = mScales[frameIndex];          const vec3& v1 = mScales[frameIndex + 1]; @@ -373,6 +402,7 @@ Skin::~Skin()  void Skin::uploadMatrixPalette(Asset& asset)  {      // prepare matrix palette +    LL_PROFILE_ZONE_SCOPED_CATEGORY_GLTF;      U32 max_joints = LLSkinningUtil::getMaxGLTFJointCount(); diff --git a/indra/newview/gltf/animation.h b/indra/newview/gltf/animation.h index d5426fd4ce..ab8839470a 100644 --- a/indra/newview/gltf/animation.h +++ b/indra/newview/gltf/animation.h @@ -49,6 +49,9 @@ namespace LL                  S32 mOutput = INVALID_INDEX;                  std::string mInterpolation; +                F32 mLastFrameTime = 0.f; +                U32 mLastFrameIndex = 0; +                  bool prep(Asset& asset);                  void serialize(boost::json::object& dst) const; diff --git a/indra/newview/gltf/asset.cpp b/indra/newview/gltf/asset.cpp index 21be69aae2..a454e68a92 100644 --- a/indra/newview/gltf/asset.cpp +++ b/indra/newview/gltf/asset.cpp @@ -35,6 +35,7 @@  #include "buffer_util.h"  #include <boost/url.hpp>  #include "llimagejpeg.h" +#include "../llskinningutil.h"  using namespace LL::GLTF;  using namespace boost::json; @@ -86,7 +87,6 @@ namespace LL      }  } -  void Scene::updateTransforms(Asset& asset)  {      mat4 identity = glm::identity<mat4>(); @@ -98,26 +98,6 @@ void Scene::updateTransforms(Asset& asset)      }  } -void Scene::updateRenderTransforms(Asset& asset, const mat4& modelview) -{ -    for (auto& nodeIndex : mNodes) -    { -        Node& node = asset.mNodes[nodeIndex]; -        node.updateRenderTransforms(asset, modelview); -    } -} - -void Node::updateRenderTransforms(Asset& asset, const mat4& modelview) -{ -    mRenderMatrix = modelview * mMatrix; - -    for (auto& childIndex : mChildren) -    { -        Node& child = asset.mNodes[childIndex]; -        child.updateRenderTransforms(asset, mRenderMatrix); -    } -} -  void Node::updateTransforms(Asset& asset, const mat4& parentMatrix)  {      makeMatrixValid(); @@ -137,19 +117,119 @@ void Node::updateTransforms(Asset& asset, const mat4& parentMatrix)  void Asset::updateTransforms()  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_GLTF;      for (auto& scene : mScenes)      {          scene.updateTransforms(*this);      } + +    uploadTransforms();  } -void Asset::updateRenderTransforms(const mat4& modelview) +void Asset::uploadTransforms()  { -    // use mAssetMatrix to update render transforms from node list -    for (auto& node : mNodes) +    LL_PROFILE_ZONE_SCOPED_CATEGORY_GLTF; +    // prepare matrix palette +    U32 max_nodes = LLSkinningUtil::getMaxGLTFJointCount(); + +    size_t node_count = llmin<size_t>(max_nodes, mNodes.size()); + +    std::vector<mat4> t_mp; + +    t_mp.resize(node_count); + +    for (U32 i = 0; i < node_count; ++i)      { -        node.mRenderMatrix = modelview * node.mAssetMatrix; +        Node& node = mNodes[i]; +        // build matrix palette in asset space +        t_mp[i] = node.mAssetMatrix;      } + +    std::vector<F32> glmp; + +    glmp.resize(node_count * 12); + +    F32* mp = glmp.data(); + +    for (U32 i = 0; i < node_count; ++i) +    { +        F32* m = glm::value_ptr(t_mp[i]); + +        U32 idx = i * 12; + +        mp[idx + 0] = m[0]; +        mp[idx + 1] = m[1]; +        mp[idx + 2] = m[2]; +        mp[idx + 3] = m[12]; + +        mp[idx + 4] = m[4]; +        mp[idx + 5] = m[5]; +        mp[idx + 6] = m[6]; +        mp[idx + 7] = m[13]; + +        mp[idx + 8] = m[8]; +        mp[idx + 9] = m[9]; +        mp[idx + 10] = m[10]; +        mp[idx + 11] = m[14]; +    } + +    if (mNodesUBO == 0) +    { +        glGenBuffers(1, &mNodesUBO); +    } + +    glBindBuffer(GL_UNIFORM_BUFFER, mNodesUBO); +    glBufferData(GL_UNIFORM_BUFFER, glmp.size() * sizeof(F32), glmp.data(), GL_STREAM_DRAW); +    glBindBuffer(GL_UNIFORM_BUFFER, 0); +} + +void Asset::uploadMaterials() +{ +    LL_PROFILE_ZONE_SCOPED_CATEGORY_GLTF; +    // see pbrmetallicroughnessV.glsl for the layout of the material UBO +    std::vector<vec4> md; + +    U32 material_size = sizeof(vec4) * 12; +    U32 max_materials = gGLManager.mMaxUniformBlockSize / material_size; + +    U32 mat_count = (U32)mMaterials.size(); +    mat_count = llmin(mat_count, max_materials); + +    md.resize(mat_count * 12); + +    for (U32 i = 0; i < mat_count*12; i += 12) +    { +        Material& material = mMaterials[i/12]; + +        // add texture transforms and UV indices +        material.mPbrMetallicRoughness.mBaseColorTexture.mTextureTransform.getPacked(&md[i+0]); +        md[i + 1].g = (F32)material.mPbrMetallicRoughness.mBaseColorTexture.getTexCoord(); +        material.mNormalTexture.mTextureTransform.getPacked(&md[i + 2]); +        md[i + 3].g = (F32)material.mNormalTexture.getTexCoord(); +        material.mPbrMetallicRoughness.mMetallicRoughnessTexture.mTextureTransform.getPacked(&md[i+4]); +        md[i + 5].g = (F32)material.mPbrMetallicRoughness.mMetallicRoughnessTexture.getTexCoord(); +        material.mEmissiveTexture.mTextureTransform.getPacked(&md[i + 6]); +        md[i + 7].g = (F32)material.mEmissiveTexture.getTexCoord(); +        material.mOcclusionTexture.mTextureTransform.getPacked(&md[i + 8]); +        md[i + 9].g = (F32)material.mOcclusionTexture.getTexCoord(); + +        // add material properties +        F32 min_alpha = material.mAlphaMode == Material::AlphaMode::MASK ? material.mAlphaCutoff : -1.0f; +        md[i + 10] = vec4(material.mEmissiveFactor, 1.f); +        md[i + 11] = vec4(0.f, +            material.mPbrMetallicRoughness.mRoughnessFactor, +            material.mPbrMetallicRoughness.mMetallicFactor, +            min_alpha); +    } + +    if (mMaterialsUBO == 0) +    { +        glGenBuffers(1, &mMaterialsUBO); +    } + +    glBindBuffer(GL_UNIFORM_BUFFER, mMaterialsUBO); +    glBufferData(GL_UNIFORM_BUFFER, md.size() * sizeof(vec4), md.data(), GL_STREAM_DRAW); +    glBindBuffer(GL_UNIFORM_BUFFER, 0);  }  S32 Asset::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, @@ -363,6 +443,7 @@ const Image& Image::operator=(const Value& src)  void Asset::update()  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_GLTF;      F32 dt = gFrameTimeSeconds - mLastUpdateTime;      if (dt > 0.f) @@ -383,11 +464,27 @@ void Asset::update()          {              skin.uploadMatrixPalette(*this);          } + +        uploadMaterials(); + +        { +            LL_PROFILE_ZONE_NAMED_CATEGORY_GLTF("gltf - addTextureStats"); + +            for (auto& image : mImages) +            { +                if (image.mTexture.notNull()) +                { // HACK - force texture to be loaded full rez +                    // TODO: calculate actual vsize +                    image.mTexture->addTextureStats(2048.f * 2048.f); +                } +            } +        }      }  }  bool Asset::prep()  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_GLTF;      // check required extensions and fail if not supported      bool unsupported = false;      for (auto& extension : mExtensionsRequired) @@ -445,6 +542,127 @@ bool Asset::prep()          }      } +    // prepare vertex buffers + +    // material count is number of materials + 1 for default material +    U32 mat_count = (U32) mMaterials.size() + 1; + +    if (LLGLSLShader::sCurBoundShaderPtr == nullptr) +    { // make sure a shader is bound to satisfy mVertexBuffer->setBuffer +        gDebugProgram.bind(); +    } + +    for (S32 double_sided = 0; double_sided < 2; ++double_sided) +    { +        RenderData& rd = mRenderData[double_sided]; +        for (U32 i = 0; i < LLGLSLShader::NUM_GLTF_VARIANTS; ++i) +        { +            rd.mBatches[i].resize(mat_count); +        } + +        // for each material +        for (S32 mat_id = -1; mat_id < (S32)mMaterials.size(); ++mat_id) +        { +            // for each shader variant +            U32 vertex_count[LLGLSLShader::NUM_GLTF_VARIANTS] = { 0 }; +            U32 index_count[LLGLSLShader::NUM_GLTF_VARIANTS] = { 0 }; + +            S32 ds_mat = mat_id == -1 ? 0 : mMaterials[mat_id].mDoubleSided; +            if (ds_mat != double_sided) +            { +                continue; +            } + +            for (U32 variant = 0; variant < LLGLSLShader::NUM_GLTF_VARIANTS; ++variant) +            { +                U32 attribute_mask = 0; +                // for each mesh +                for (auto& mesh : mMeshes) +                { +                    // for each primitive +                    for (auto& primitive : mesh.mPrimitives) +                    { +                        if (primitive.mMaterial == mat_id && primitive.mShaderVariant == variant) +                        { +                            // accumulate vertex and index counts +                            primitive.mVertexOffset = vertex_count[variant]; +                            primitive.mIndexOffset = index_count[variant]; + +                            vertex_count[variant] += primitive.getVertexCount(); +                            index_count[variant] += primitive.getIndexCount(); + +                            // all primitives of a given variant and material should all have the same attribute mask +                            llassert(attribute_mask == 0 || primitive.mAttributeMask == attribute_mask); +                            attribute_mask |= primitive.mAttributeMask; +                        } +                    } +                } + +                // allocate vertex buffer and pack it +                if (vertex_count[variant] > 0) +                { +                    U32 mat_idx = mat_id + 1; +                    LLVertexBuffer* vb = new LLVertexBuffer(attribute_mask); + +                    rd.mBatches[variant][mat_idx].mVertexBuffer = vb; +                    vb->allocateBuffer(vertex_count[variant], +                        index_count[variant] * 2); // hack double index count... TODO: find a better way to indicate 32-bit indices will be used +                    vb->setBuffer(); + +                    for (auto& mesh : mMeshes) +                    { +                        for (auto& primitive : mesh.mPrimitives) +                        { +                            if (primitive.mMaterial == mat_id && primitive.mShaderVariant == variant) +                            { +                                primitive.upload(vb); +                            } +                        } +                    } + +                    vb->unmapBuffer(); + +                    vb->unbind(); +                } +            } +        } +    } + +    // sanity check that all primitives have a vertex buffer +    for (auto& mesh : mMeshes) +    { +        for (auto& primitive : mesh.mPrimitives) +        { +            llassert(primitive.mVertexBuffer.notNull()); +        } +    } + +    // build render batches +    for (S32 node_id = 0; node_id < mNodes.size(); ++node_id) +    { +        Node& node = mNodes[node_id]; + +        if (node.mMesh != INVALID_INDEX) +        { +            auto& mesh = mMeshes[node.mMesh]; + +            S32 mat_idx = mesh.mPrimitives[0].mMaterial + 1; + +            S32 double_sided = mat_idx == 0 ? 0 : mMaterials[mat_idx - 1].mDoubleSided; + +            for (S32 j = 0; j < mesh.mPrimitives.size(); ++j) +            { +                auto& primitive = mesh.mPrimitives[j]; + +                S32 variant = primitive.mShaderVariant; + +                RenderData& rd = mRenderData[double_sided]; +                RenderBatch& rb = rd.mBatches[variant][mat_idx]; + +                rb.mPrimitives.push_back({ j, node_id }); +            } +        } +    }      return true;  } @@ -455,6 +673,7 @@ Asset::Asset(const Value& src)  bool Asset::load(std::string_view filename)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_GLTF;      mFilename = filename;      std::string ext = gDirUtilp->getExtension(mFilename); @@ -903,14 +1122,14 @@ bool Image::save(Asset& asset, const std::string& folder)      return true;  } -void Material::TextureInfo::serialize(object& dst) const +void TextureInfo::serialize(object& dst) const  {      write(mIndex, "index", dst, INVALID_INDEX);      write(mTexCoord, "texCoord", dst, 0);      write_extensions(dst, &mTextureTransform, "KHR_texture_transform");  } -S32 Material::TextureInfo::getTexCoord() const +S32 TextureInfo::getTexCoord() const  {      if (mTextureTransform.mPresent && mTextureTransform.mTexCoord != INVALID_INDEX)      { @@ -928,7 +1147,7 @@ bool Material::isMultiUV() const          mEmissiveTexture.getTexCoord() != 0;  } -const Material::TextureInfo& Material::TextureInfo::operator=(const Value& src) +const TextureInfo& TextureInfo::operator=(const Value& src)  {      if (src.is_object())      { @@ -940,23 +1159,23 @@ const Material::TextureInfo& Material::TextureInfo::operator=(const Value& src)      return *this;  } -bool Material::TextureInfo::operator==(const Material::TextureInfo& rhs) const +bool TextureInfo::operator==(const TextureInfo& rhs) const  {      return mIndex == rhs.mIndex && mTexCoord == rhs.mTexCoord;  } -bool Material::TextureInfo::operator!=(const Material::TextureInfo& rhs) const +bool TextureInfo::operator!=(const TextureInfo& rhs) const  {      return !(*this == rhs);  } -void Material::OcclusionTextureInfo::serialize(object& dst) const +void OcclusionTextureInfo::serialize(object& dst) const  {      TextureInfo::serialize(dst);      write(mStrength, "strength", dst, 1.f);  } -const Material::OcclusionTextureInfo& Material::OcclusionTextureInfo::operator=(const Value& src) +const OcclusionTextureInfo& OcclusionTextureInfo::operator=(const Value& src)  {      TextureInfo::operator=(src); @@ -968,13 +1187,13 @@ const Material::OcclusionTextureInfo& Material::OcclusionTextureInfo::operator=(      return *this;  } -void Material::NormalTextureInfo::serialize(object& dst) const +void NormalTextureInfo::serialize(object& dst) const  {      TextureInfo::serialize(dst);      write(mScale, "scale", dst, 1.f);  } -const Material::NormalTextureInfo& Material::NormalTextureInfo::operator=(const Value& src) +const NormalTextureInfo& NormalTextureInfo::operator=(const Value& src)  {      TextureInfo::operator=(src);      if (src.is_object()) @@ -1035,18 +1254,12 @@ void Material::Unlit::serialize(object& dst) const      // no members and object has already been created, nothing to do  } -void TextureTransform::getPacked(F32* packed) const +void TextureTransform::getPacked(vec4* packed) const  { -    packed[0] = mScale.x; -    packed[1] = mScale.y; -    packed[2] = mRotation; -    packed[3] = mOffset.x; -    packed[4] = mOffset.y; - -    packed[5] = packed[6] = packed[7] = 0.f; +    packed[0] = vec4(mScale.x, mScale.y, mRotation, mOffset.x); +    packed[1] = vec4(mOffset.y, 0.f, 0.f, 0.f);  } -  const TextureTransform& TextureTransform::operator=(const Value& src)  {      mPresent = true; diff --git a/indra/newview/gltf/asset.h b/indra/newview/gltf/asset.h index ea3f7d480a..27821659db 100644 --- a/indra/newview/gltf/asset.h +++ b/indra/newview/gltf/asset.h @@ -34,6 +34,7 @@  #include "boost/json.hpp"  #include "common.h"  #include "../llviewertexture.h" +#include "llglslshader.h"  extern F32SecondsImplicit       gFrameTimeSeconds; @@ -65,14 +66,51 @@ namespace LL              vec2 mScale = vec2(1.f, 1.f);              S32 mTexCoord = INVALID_INDEX; -            // get the texture transform as a packed array of floats -            // dst MUST point to at least 8 floats -            void getPacked(F32* dst) const; +            // get the texture transform as a packed array of vec4's +            // dst MUST point to at least 2 vec4's +            void getPacked(vec4* dst) const;              const TextureTransform& operator=(const Value& src);              void serialize(boost::json::object& dst) const;          }; +        class TextureInfo +        { +        public: +            S32 mIndex = INVALID_INDEX; +            S32 mTexCoord = 0; + +            TextureTransform mTextureTransform; + +            bool operator==(const TextureInfo& rhs) const; +            bool operator!=(const TextureInfo& rhs) const; + +            // get the UV channel that should be used for sampling this texture +            // returns mTextureTransform.mTexCoord if present and valid, otherwise mTexCoord +            S32 getTexCoord() const; + +            const TextureInfo& operator=(const Value& src); +            void serialize(boost::json::object& dst) const; +        }; + +        class NormalTextureInfo : public TextureInfo +        { +        public: +            F32 mScale = 1.0f; + +            const NormalTextureInfo& operator=(const Value& src); +            void serialize(boost::json::object& dst) const; +        }; + +        class OcclusionTextureInfo : public TextureInfo +        { +        public: +            F32 mStrength = 1.0f; + +            const OcclusionTextureInfo& operator=(const Value& src); +            void serialize(boost::json::object& dst) const; +        }; +          class Material          {          public: @@ -91,42 +129,6 @@ namespace LL                  BLEND              }; -            class TextureInfo -            { -            public: -                S32 mIndex = INVALID_INDEX; -                S32 mTexCoord = 0; - -                TextureTransform mTextureTransform; - -                bool operator==(const TextureInfo& rhs) const; -                bool operator!=(const TextureInfo& rhs) const; - -                // get the UV channel that should be used for sampling this texture -                // returns mTextureTransform.mTexCoord if present and valid, otherwise mTexCoord -                S32 getTexCoord() const; - -                const TextureInfo& operator=(const Value& src); -                void serialize(boost::json::object& dst) const; -            }; - -            class NormalTextureInfo : public TextureInfo -            { -            public: -                F32 mScale = 1.0f; - -                const NormalTextureInfo& operator=(const Value& src); -                void serialize(boost::json::object& dst) const; -            }; - -            class OcclusionTextureInfo : public TextureInfo -            { -            public: -                F32 mStrength = 1.0f; - -                const OcclusionTextureInfo& operator=(const Value& src); -                void serialize(boost::json::object& dst) const; -            };              class PbrMetallicRoughness              { @@ -179,7 +181,6 @@ namespace LL          {          public:              mat4 mMatrix = glm::identity<mat4>(); //local transform -            mat4 mRenderMatrix; //transform for rendering              mat4 mAssetMatrix; //transform from local to asset space              mat4 mAssetMatrixInv; //transform from asset to local space @@ -206,10 +207,6 @@ namespace LL              const Node& operator=(const Value& src);              void serialize(boost::json::object& dst) const; -            // Set mRenderMatrix to a transform that can be used for the current render pass -            // modelview -- parent's render matrix -            void updateRenderTransforms(Asset& asset, const mat4& modelview); -              // update mAssetMatrix and mAssetMatrixInv              void updateTransforms(Asset& asset, const mat4& parentMatrix); @@ -322,6 +319,31 @@ namespace LL              bool prep(Asset& asset);          }; +        // Render Batch -- vertex buffer and list of primitives to render using +        // said vertex buffer +        class RenderBatch +        { +        public: +            struct PrimitiveData +            { +                S32 mPrimitiveIndex = INVALID_INDEX; +                S32 mNodeIndex = INVALID_INDEX; +            }; + +            LLPointer<LLVertexBuffer> mVertexBuffer; +            std::vector<PrimitiveData> mPrimitives; +        }; + +        class RenderData +        { +        public: +            // list of render batches +            // indexed by [material index + 1](0 is reserved for default material) +            // there should be exactly one render batch per material per variant +            std::vector<RenderBatch> mBatches[LLGLSLShader::NUM_GLTF_VARIANTS]; +        }; + +          // C++ representation of a GLTF Asset          class Asset          { @@ -359,6 +381,16 @@ namespace LL              // the last time update() was called according to gFrameTimeSeconds              F32 mLastUpdateTime = gFrameTimeSeconds; +            // data used for rendering +            // 0 - single sided +            // 1 - double sided +            RenderData mRenderData[2]; + +            // UBO for storing node transforms +            U32 mNodesUBO = 0; + +            // UBO for storing material data +            U32 mMaterialsUBO = 0;              // prepare for first time use              bool prep(); @@ -373,8 +405,11 @@ namespace LL              // update asset-to-node and node-to-asset transforms              void updateTransforms(); -            // update node render transforms -            void updateRenderTransforms(const mat4& modelview); +            // upload matrices to UBO +            void uploadTransforms(); + +            // upload materils to UBO +            void uploadMaterials();              // return the index of the node that the line segment intersects with, or -1 if no hit              // input and output values must be in this asset's local coordinate frame diff --git a/indra/newview/gltf/common.h b/indra/newview/gltf/common.h index 4f660d7cfc..b9698d4017 100644 --- a/indra/newview/gltf/common.h +++ b/indra/newview/gltf/common.h @@ -64,6 +64,9 @@ namespace LL          class Asset;          class Material; +        class TextureInfo; +        class NormalTextureInfo; +        class OcclusionTextureInfo;          class Mesh;          class Node;          class Scene; @@ -78,6 +81,17 @@ namespace LL          class Accessor;          class BufferView;          class Buffer; + +        enum class TextureType : U8 +        { +            BASE_COLOR = 0, +            NORMAL, +            METALLIC_ROUGHNESS, +            OCCLUSION, +            EMISSIVE +        }; + +        constexpr U32 TEXTURE_TYPE_COUNT = 5;      }  } diff --git a/indra/newview/gltf/primitive.cpp b/indra/newview/gltf/primitive.cpp index 2280c7004e..e1579374d4 100644 --- a/indra/newview/gltf/primitive.cpp +++ b/indra/newview/gltf/primitive.cpp @@ -380,11 +380,22 @@ bool Primitive::prep(Asset& asset)              }          }      } +    else +    { //everything must be indexed at runtime +        mIndexArray.resize(mPositions.size()); +        for (U32 i = 0; i < mPositions.size(); ++i) +        { +            mIndexArray[i] = i; +        } +    }      U32 mask = LLVertexBuffer::MAP_VERTEX; +    mShaderVariant = 0; +      if (!mWeights.empty())      { +        mShaderVariant |= LLGLSLShader::GLTFVariant::RIGGED;          mask |= LLVertexBuffer::MAP_WEIGHT4;          mask |= LLVertexBuffer::MAP_JOINT;      } @@ -406,9 +417,6 @@ bool Primitive::prep(Asset& asset)          mColors.resize(mPositions.size(), LLColor4U::white);      } -    mShaderVariant = 0; - -    // TODO: support colorless vertex buffers      mask |= LLVertexBuffer::MAP_COLOR;      bool unlit = false; @@ -506,69 +514,79 @@ bool Primitive::prep(Asset& asset)          mask |= LLVertexBuffer::MAP_TANGENT;      } -    if (LLGLSLShader::sCurBoundShaderPtr == nullptr) -    { // make sure a shader is bound to satisfy mVertexBuffer->setBuffer -        gDebugProgram.bind(); +    mAttributeMask = mask; + +    if (mMaterial != INVALID_INDEX) +    { +        Material& material = asset.mMaterials[mMaterial]; +        if (material.mAlphaMode == Material::AlphaMode::BLEND) +        { +            mShaderVariant |= LLGLSLShader::GLTFVariant::ALPHA_BLEND; +        }      } -    mVertexBuffer = new LLVertexBuffer(mask); +    createOctree(); + +    return true; +} + +void Primitive::upload(LLVertexBuffer* buffer) +{ +    mVertexBuffer = buffer;      // we store these buffer sizes as S32 elsewhere      llassert(mPositions.size() <= size_t(S32_MAX));      llassert(mIndexArray.size() <= size_t(S32_MAX / 2)); -    mVertexBuffer->allocateBuffer(U32(mPositions.size()), U32(mIndexArray.size() * 2)); // double the size of the index buffer for 32-bit indices -    mVertexBuffer->setBuffer(); -    mVertexBuffer->setPositionData(mPositions.data()); -    mVertexBuffer->setColorData(mColors.data()); +    llassert(mVertexBuffer != nullptr); + +    // assert that buffer can hold this primitive +    llassert(mVertexBuffer->getNumVerts() >= mPositions.size() + mVertexOffset); +    llassert(mVertexBuffer->getNumIndices() >= mIndexArray.size() + mIndexOffset); +    llassert(mVertexBuffer->getTypeMask() == mAttributeMask); + +    U32 offset = mVertexOffset; +    U32 count = getVertexCount(); + +    mVertexBuffer->setPositionData(mPositions.data(), offset, count); +    mVertexBuffer->setColorData(mColors.data(), offset, count);      if (!mNormals.empty())      { -        mVertexBuffer->setNormalData(mNormals.data()); +        mVertexBuffer->setNormalData(mNormals.data(), offset, count);      }      if (!mTangents.empty())      { -        mVertexBuffer->setTangentData(mTangents.data()); +        mVertexBuffer->setTangentData(mTangents.data(), offset, count);      }      if (!mWeights.empty())      { -        mShaderVariant |= LLGLSLShader::GLTFVariant::RIGGED; -        mVertexBuffer->setWeight4Data(mWeights.data()); -        mVertexBuffer->setJointData(mJoints.data()); +        mVertexBuffer->setWeight4Data(mWeights.data(), offset, count); +        mVertexBuffer->setJointData(mJoints.data(), offset, count);      }      // flip texcoord y, upload, then flip back (keep the off-spec data in vram only)      vertical_flip(mTexCoords0); -    mVertexBuffer->setTexCoord0Data(mTexCoords0.data()); +    mVertexBuffer->setTexCoord0Data(mTexCoords0.data(), offset, count);      vertical_flip(mTexCoords0);      if (!mTexCoords1.empty())      {          vertical_flip(mTexCoords1); -        mVertexBuffer->setTexCoord1Data(mTexCoords1.data()); +        mVertexBuffer->setTexCoord1Data(mTexCoords1.data(), offset, count);          vertical_flip(mTexCoords1);      } -      if (!mIndexArray.empty())      { -        mVertexBuffer->setIndexData(mIndexArray.data()); -    } - -    createOctree(); - -    mVertexBuffer->unbind(); - -    if (mMaterial != INVALID_INDEX) -    { -        Material& material = asset.mMaterials[mMaterial]; -        if (material.mAlphaMode == Material::AlphaMode::BLEND) +        std::vector<U32> index_array; +        index_array.resize(mIndexArray.size()); +        for (U32 i = 0; i < mIndexArray.size(); ++i)          { -            mShaderVariant |= LLGLSLShader::GLTFVariant::ALPHA_BLEND; +            index_array[i] = mIndexArray[i] + mVertexOffset;          } +        mVertexBuffer->setIndexData(index_array.data(), mIndexOffset, getIndexCount());      } - -    return true;  }  void initOctreeTriangle(LLVolumeTriangle* tri, F32 scaler, S32 i0, S32 i1, S32 i2, const LLVector4a& v0, const LLVector4a& v1, const LLVector4a& v2) @@ -616,7 +634,7 @@ void Primitive::createOctree()      if (mMode == Mode::TRIANGLES)      { -        const U32 num_triangles = mVertexBuffer->getNumIndices() / 3; +        const U32 num_triangles = getIndexCount() / 3;          // Initialize all the triangles we need          mOctreeTriangles.resize(num_triangles); @@ -640,7 +658,7 @@ void Primitive::createOctree()      }      else if (mMode == Mode::TRIANGLE_STRIP)      { -        const U32 num_triangles = mVertexBuffer->getNumIndices() - 2; +        const U32 num_triangles = getIndexCount() - 2;          // Initialize all the triangles we need          mOctreeTriangles.resize(num_triangles); @@ -664,7 +682,7 @@ void Primitive::createOctree()      }      else if (mMode == Mode::TRIANGLE_FAN)      { -        const U32 num_triangles = mVertexBuffer->getNumIndices() - 2; +        const U32 num_triangles = getIndexCount() - 2;          // Initialize all the triangles we need          mOctreeTriangles.resize(num_triangles); diff --git a/indra/newview/gltf/primitive.h b/indra/newview/gltf/primitive.h index 7cc05cf831..304eb26432 100644 --- a/indra/newview/gltf/primitive.h +++ b/indra/newview/gltf/primitive.h @@ -54,10 +54,7 @@ namespace LL              ~Primitive(); -            // GPU copy of mesh data -            LLPointer<LLVertexBuffer> mVertexBuffer; - -            // CPU copy of mesh data, keep these as LLVector types for compatibility with raycasting code +            // CPU copy of mesh data              std::vector<LLVector2> mTexCoords0;              std::vector<LLVector2> mTexCoords1;              std::vector<LLVector4a> mNormals; @@ -80,6 +77,17 @@ namespace LL              // shader variant according to LLGLSLShader::GLTFVariant flags              U8 mShaderVariant = 0; +            // vertex attribute mask +            U32 mAttributeMask = 0; + +            // backpointer to vertex buffer (owned by Asset) +            LLPointer<LLVertexBuffer> mVertexBuffer; +            U32 mVertexOffset = 0; +            U32 mIndexOffset = 0; + +            U32 getVertexCount() const { return (U32) mPositions.size(); } +            U32 getIndexCount() const { return (U32) mIndexArray.size(); } +              std::unordered_map<std::string, S32> mAttributes;              // create octree based on vertex buffer @@ -100,6 +108,11 @@ namespace LL              const Primitive& operator=(const Value& src);              bool prep(Asset& asset); + +            // upload geometry to given vertex buffer +            // asserts that buffer is bound +            // asserts that buffer is valid for this primitive +            void upload(LLVertexBuffer* buffer);          };      }  } diff --git a/indra/newview/gltfscenemanager.cpp b/indra/newview/gltfscenemanager.cpp index e01aec0497..7b2de4d6de 100644 --- a/indra/newview/gltfscenemanager.cpp +++ b/indra/newview/gltfscenemanager.cpp @@ -437,6 +437,8 @@ void GLTFSceneManager::onGLTFLoadComplete(const LLUUID& id, LLAssetType::EType a  void GLTFSceneManager::update()  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_GLTF; +      for (U32 i = 0; i < mObjects.size(); ++i)      {          if (mObjects[i]->isDead() || mObjects[i]->mGLTFAsset == nullptr) @@ -552,6 +554,7 @@ void GLTFSceneManager::render(bool opaque, bool rigged, bool unlit)  void GLTFSceneManager::render(U8 variant)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_GLTF;      // just render the whole scene by traversing the whole scenegraph      // Assumes camera transform is already set and appropriate shader is already bound.      // Eventually we'll want a smarter render pipe that has pre-sorted the scene graph @@ -563,8 +566,6 @@ void GLTFSceneManager::render(U8 variant)          render((U8) (variant | LLGLSLShader::GLTFVariant::MULTI_UV));      } -    gGL.matrixMode(LLRender::MM_MODELVIEW); -      bool rigged = variant & LLGLSLShader::GLTFVariant::RIGGED;      for (U32 i = 0; i < mObjects.size(); ++i) @@ -581,19 +582,11 @@ void GLTFSceneManager::render(U8 variant)          LLMatrix4a mat = mObjects[i]->getGLTFAssetToAgentTransform(); -        LLMatrix4a modelview; -        modelview.loadu(gGLModelView); - -        matMul(mat, modelview, modelview); - -        mat4 mdv = glm::make_mat4(modelview.getF32ptr()); -        asset->updateRenderTransforms(mdv); +        // provide a modelview matrix that goes from asset to camera space +        // (matrix palettes are in asset space) +        gGL.loadMatrix(gGLModelView); +        gGL.multMatrix(mat.getF32ptr()); -        if (rigged) -        { // provide a modelview matrix that goes from asset to camera space for rigged render passes -            // (matrix palettes are in asset space) -            gGL.loadMatrix(glm::value_ptr(mdv)); -        }          render(*asset, variant);          gGL.popMatrix(); @@ -602,176 +595,185 @@ void GLTFSceneManager::render(U8 variant)  void GLTFSceneManager::render(Asset& asset, U8 variant)  { -    bool opaque = !(variant & LLGLSLShader::GLTFVariant::ALPHA_BLEND); -    bool rigged = variant & LLGLSLShader::GLTFVariant::RIGGED; +    LL_PROFILE_ZONE_SCOPED_CATEGORY_GLTF; -    if (opaque) +    for (U32 ds = 0; ds < 2; ++ds)      { -        gGLTFPBRMetallicRoughnessProgram.bind(variant); -    } -    else -    { // alpha shaders need all the shadow map setup etc -        gPipeline.bindDeferredShader(gGLTFPBRMetallicRoughnessProgram.mGLTFVariants[variant]); -    } +        RenderData& rd = asset.mRenderData[ds]; +        auto& batches = rd.mBatches[variant]; -    for (auto& node : asset.mNodes) -    { -        if (node.mSkin != INVALID_INDEX) +        if (batches.empty())          { -            if (rigged) -            { -                Skin& skin = asset.mSkins[node.mSkin]; -                glBindBufferBase(GL_UNIFORM_BUFFER, LLGLSLShader::UB_GLTF_JOINTS, skin.mUBO); -            } +            return;          } -        if (node.mMesh != INVALID_INDEX) +        LLGLDisable cull_face(ds == 1 ? GL_CULL_FACE : 0); + +        bool opaque = !(variant & LLGLSLShader::GLTFVariant::ALPHA_BLEND); +        bool rigged = variant & LLGLSLShader::GLTFVariant::RIGGED; + +        bool shader_bound = false; + +        for (U32 i = 0; i < batches.size(); ++i)          { -            Mesh& mesh = asset.mMeshes[node.mMesh]; -            for (auto& primitive : mesh.mPrimitives) +            if (batches[i].mPrimitives.empty() || batches[i].mVertexBuffer.isNull())              { -                if (primitive.mShaderVariant != variant) +                continue; +            } + +            if (!shader_bound) +            { // don't bind the shader until we know we have somthing to render +                if (opaque)                  { -                    continue; +                    gGLTFPBRMetallicRoughnessProgram.bind(variant); +                } +                else +                { // alpha shaders need all the shadow map setup etc +                    gPipeline.bindDeferredShader(gGLTFPBRMetallicRoughnessProgram.mGLTFVariants[variant]);                  }                  if (!rigged)                  { -                    gGL.loadMatrix((F32*)glm::value_ptr(node.mRenderMatrix)); +                    glBindBufferBase(GL_UNIFORM_BUFFER, LLGLSLShader::UB_GLTF_NODES, asset.mNodesUBO);                  } -                bool cull = true; -                if (primitive.mMaterial != INVALID_INDEX) -                { -                    Material& material = asset.mMaterials[primitive.mMaterial]; -                    bind(asset, material); -                    cull = !material.mDoubleSided; -                } -                else +                glBindBufferBase(GL_UNIFORM_BUFFER, LLGLSLShader::UB_GLTF_MATERIALS, asset.mMaterialsUBO); + +                for (U32 i = 0; i < TEXTURE_TYPE_COUNT; ++i)                  { -                    LLFetchedGLTFMaterial::sDefault.bind(); +                    mLastTexture[i] = -2;                  } -                LLGLDisable cull_face(!cull ? GL_CULL_FACE : 0); +                gGL.syncMatrices(); +                shader_bound = true; +            } + +            { +                LL_PROFILE_ZONE_NAMED_CATEGORY_GLTF("gltfdc - set vb"); +                batches[i].mVertexBuffer->setBuffer(); +            } + +            S32 mat_idx = i - 1; +            if (mat_idx != INVALID_INDEX) +            { +                Material& material = asset.mMaterials[mat_idx]; +                bind(asset, material); +            } +            else +            { +                LLFetchedGLTFMaterial::sDefault.bind(); +                LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::GLTF_MATERIAL_ID, -1); +            } + +            for (auto& pdata : batches[i].mPrimitives) +            { +                LL_PROFILE_ZONE_NAMED_CATEGORY_GLTF("GLTF draw call"); +                Node& node = asset.mNodes[pdata.mNodeIndex]; +                Mesh& mesh = asset.mMeshes[node.mMesh]; +                Primitive& primitive = mesh.mPrimitives[pdata.mPrimitiveIndex]; -                primitive.mVertexBuffer->setBuffer(); -                if (primitive.mVertexBuffer->getNumIndices() > 0) +                if (rigged)                  { -                    primitive.mVertexBuffer->draw(primitive.mGLMode, primitive.mVertexBuffer->getNumIndices(), 0); +                    LL_PROFILE_ZONE_NAMED_CATEGORY_GLTF("gltfdc - bind skin"); +                    llassert(node.mSkin != INVALID_INDEX); +                    Skin& skin = asset.mSkins[node.mSkin]; +                    glBindBufferBase(GL_UNIFORM_BUFFER, LLGLSLShader::UB_GLTF_JOINTS, skin.mUBO);                  }                  else                  { -                    primitive.mVertexBuffer->drawArrays(primitive.mGLMode, 0, primitive.mVertexBuffer->getNumVerts()); +                    LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::GLTF_NODE_ID, pdata.mNodeIndex); +                } + +                { +                    LL_PROFILE_ZONE_NAMED_CATEGORY_GLTF("gltfdc - push vb"); + +                    primitive.mVertexBuffer->drawRangeFast(primitive.mGLMode, primitive.mVertexOffset, primitive.mVertexOffset + primitive.getVertexCount() - 1, primitive.getIndexCount(), primitive.mIndexOffset);                  }              }          }      }  } -static void bindTexture(Asset& asset, S32 uniform, Material::TextureInfo& info, LLViewerTexture* fallback) +void GLTFSceneManager::bindTexture(Asset& asset, TextureType texture_type, TextureInfo& info, LLViewerTexture* fallback)  { -    if (info.mIndex != INVALID_INDEX) +    U8 type_idx = (U8)texture_type; + +    if (info.mIndex == mLastTexture[type_idx]) +    { //already bound +        return; +    } + +    S32 uniform[] =      { -        Texture& texture = asset.mTextures[info.mIndex]; +        LLShaderMgr::DIFFUSE_MAP, +        LLShaderMgr::NORMAL_MAP, +        LLShaderMgr::METALLIC_ROUGHNESS_MAP, +        LLShaderMgr::OCCLUSION_MAP, +        LLShaderMgr::EMISSIVE_MAP +    }; -        LLViewerTexture* tex = asset.mImages[texture.mSource].mTexture; -        if (tex) +    S32 channel = LLGLSLShader::sCurBoundShaderPtr->getTextureChannel(uniform[(U8)type_idx]); + +    if (channel > -1) +    { +        glActiveTexture(GL_TEXTURE0 + channel); + +        if (info.mIndex != INVALID_INDEX)          { -            tex->addTextureStats(2048.f * 2048.f); -            S32 channel = LLGLSLShader::sCurBoundShaderPtr->bindTexture(uniform, tex); +            Texture& texture = asset.mTextures[info.mIndex]; + +            LLViewerTexture* tex = asset.mImages[texture.mSource].mTexture; +            if (tex) +            { +                LL_PROFILE_ZONE_NAMED_CATEGORY_GLTF("gl bind texture"); +                glBindTexture(GL_TEXTURE_2D, tex->getTexName()); -            if (channel != -1 && texture.mSampler != -1) -            { // set sampler state -                Sampler& sampler = asset.mSamplers[texture.mSampler]; -                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, sampler.mWrapS); -                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, sampler.mWrapT); -                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, sampler.mMagFilter); +                if (channel != -1 && texture.mSampler != -1) +                { // set sampler state +                    Sampler& sampler = asset.mSamplers[texture.mSampler]; +                    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, sampler.mWrapS); +                    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, sampler.mWrapT); +                    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, sampler.mMagFilter); -                // NOTE: do not set min filter.  Always respect client preference for min filter +                    // NOTE: do not set min filter.  Always respect client preference for min filter +                } +                else +                { +                    // set default sampler state +                    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); +                    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); +                    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); +                }              }              else              { -                // set default sampler state -                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); -                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); -                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); +                glBindTexture(GL_TEXTURE_2D, fallback->getTexName());              }          }          else          { -            LLGLSLShader::sCurBoundShaderPtr->bindTexture(uniform, fallback); +            glBindTexture(GL_TEXTURE_2D, fallback->getTexName());          }      } -    else -    { -        LLGLSLShader::sCurBoundShaderPtr->bindTexture(uniform, fallback); -    }  }  void GLTFSceneManager::bind(Asset& asset, Material& material)  { -    // bind for rendering (derived from 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; - +    LL_PROFILE_ZONE_SCOPED_CATEGORY_GLTF;      LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; -    if (!LLPipeline::sShadowRender || (material.mAlphaMode == Material::AlphaMode::BLEND)) -    { -        if (material.mAlphaMode == Material::AlphaMode::MASK) -        { -            // dividing the alpha cutoff by transparency here allows the shader to compare against -            // the alpha value of the texture without needing the transparency value -            if (material.mPbrMetallicRoughness.mBaseColorFactor.a > 0.f) -            { -                min_alpha = material.mAlphaCutoff / material.mPbrMetallicRoughness.mBaseColorFactor.a; -            } -            else -            { -                min_alpha = 1024.f; -            } -        } -        shader->uniform1f(LLShaderMgr::MINIMUM_ALPHA, min_alpha); -    } - -    bindTexture(asset, LLShaderMgr::DIFFUSE_MAP, material.mPbrMetallicRoughness.mBaseColorTexture, LLViewerFetchedTexture::sWhiteImagep); - -    F32 tf[8]; -    material.mPbrMetallicRoughness.mBaseColorTexture.mTextureTransform.getPacked(tf); -    shader->uniform4fv(LLShaderMgr::TEXTURE_BASE_COLOR_TRANSFORM, 2, tf); -    shader->uniform1i(LLShaderMgr::BASE_COLOR_TEXCOORD, material.mPbrMetallicRoughness.mBaseColorTexture.getTexCoord()); +    bindTexture(asset, TextureType::BASE_COLOR, material.mPbrMetallicRoughness.mBaseColorTexture, LLViewerFetchedTexture::sWhiteImagep);      if (!LLPipeline::sShadowRender)      { -        bindTexture(asset, LLShaderMgr::NORMAL_MAP, material.mNormalTexture, LLViewerFetchedTexture::sFlatNormalImagep); -        bindTexture(asset, LLShaderMgr::METALLIC_ROUGHNESS_MAP, material.mPbrMetallicRoughness.mMetallicRoughnessTexture, LLViewerFetchedTexture::sWhiteImagep); -        bindTexture(asset, LLShaderMgr::OCCLUSION_MAP, material.mOcclusionTexture, LLViewerFetchedTexture::sWhiteImagep); -        bindTexture(asset, LLShaderMgr::EMISSIVE_MAP, material.mEmissiveTexture, LLViewerFetchedTexture::sWhiteImagep); - -        // NOTE: base color factor is baked into vertex stream - -        shader->uniform1f(LLShaderMgr::ROUGHNESS_FACTOR, material.mPbrMetallicRoughness.mRoughnessFactor); -        shader->uniform1f(LLShaderMgr::METALLIC_FACTOR, material.mPbrMetallicRoughness.mMetallicFactor); -        shader->uniform3fv(LLShaderMgr::EMISSIVE_COLOR, 1, glm::value_ptr(material.mEmissiveFactor)); - -        material.mNormalTexture.mTextureTransform.getPacked(tf); -        shader->uniform4fv(LLShaderMgr::TEXTURE_NORMAL_TRANSFORM, 2, tf); -        shader->uniform1i(LLShaderMgr::NORMAL_TEXCOORD, material.mNormalTexture.getTexCoord()); - -        material.mPbrMetallicRoughness.mMetallicRoughnessTexture.mTextureTransform.getPacked(tf); -        shader->uniform4fv(LLShaderMgr::TEXTURE_METALLIC_ROUGHNESS_TRANSFORM, 2, tf); -        shader->uniform1i(LLShaderMgr::METALLIC_ROUGHNESS_TEXCOORD, material.mPbrMetallicRoughness.mMetallicRoughnessTexture.getTexCoord()); - -        material.mOcclusionTexture.mTextureTransform.getPacked(tf); -        shader->uniform4fv(LLShaderMgr::TEXTURE_OCCLUSION_TRANSFORM, 2, tf); -        shader->uniform1i(LLShaderMgr::OCCLUSION_TEXCOORD, material.mOcclusionTexture.getTexCoord()); - -        material.mEmissiveTexture.mTextureTransform.getPacked(tf); -        shader->uniform4fv(LLShaderMgr::TEXTURE_EMISSIVE_TRANSFORM, 2, tf); -        shader->uniform1i(LLShaderMgr::EMISSIVE_TEXCOORD, material.mEmissiveTexture.getTexCoord()); +        bindTexture(asset, TextureType::NORMAL, material.mNormalTexture, LLViewerFetchedTexture::sFlatNormalImagep); +        bindTexture(asset, TextureType::METALLIC_ROUGHNESS, material.mPbrMetallicRoughness.mMetallicRoughnessTexture, LLViewerFetchedTexture::sWhiteImagep); +        bindTexture(asset, TextureType::OCCLUSION, material.mOcclusionTexture, LLViewerFetchedTexture::sWhiteImagep); +        bindTexture(asset, TextureType::EMISSIVE, material.mEmissiveTexture, LLViewerFetchedTexture::sWhiteImagep);      } + +    shader->uniform1i(LLShaderMgr::GLTF_MATERIAL_ID, &material - &asset.mMaterials[0]);  }  LLMatrix4a inverse(const LLMatrix4a& mat) @@ -931,10 +933,11 @@ void renderAssetDebug(LLViewerObject* obj, Asset* asset)      // assumes modelview matrix is already set      gGL.pushMatrix(); -      // get raycast in asset space      LLMatrix4a agent_to_asset = obj->getAgentToGLTFAssetTransform(); +    gGL.multMatrix(agent_to_asset.getF32ptr()); +      vec4 start;      vec4 end; @@ -952,7 +955,8 @@ void renderAssetDebug(LLViewerObject* obj, Asset* asset)          if (node.mMesh != INVALID_INDEX)          { -            gGL.loadMatrix((F32*)glm::value_ptr(node.mRenderMatrix)); +            gGL.pushMatrix(); +            gGL.multMatrix((F32*)glm::value_ptr(node.mAssetMatrix));              // draw bounding box of mesh primitives              if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_BBOXES)) @@ -995,6 +999,7 @@ void renderAssetDebug(LLViewerObject* obj, Asset* asset)                  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);              }  #endif +            gGL.popMatrix();          }      } @@ -1013,35 +1018,15 @@ void GLTFSceneManager::renderDebug()      gDebugProgram.bind(); +    gGL.pushMatrix(); +    gGL.loadMatrix(gGLModelView); +      LLGLDisable cullface(GL_CULL_FACE);      LLGLEnable blend(GL_BLEND);      gGL.setSceneBlendType(LLRender::BT_ALPHA);      gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);      gPipeline.disableLights(); -    // force update all mRenderMatrix, not just nodes with meshes -    for (auto& obj : mObjects) -    { -        if (obj->isDead() || obj->mGLTFAsset == nullptr) -        { -            continue; -        } - -        mat4 mat = glm::make_mat4(obj->getGLTFAssetToAgentTransform().getF32ptr()); - -        mat4 modelview = glm::make_mat4(gGLModelView); - - -        modelview = modelview * mat; - -        Asset* asset = obj->mGLTFAsset.get(); - -        for (auto& node : asset->mNodes) -        { -            node.mRenderMatrix = modelview * node.mAssetMatrix; -        } -    } -      for (auto& obj : mObjects)      {          if (obj->isDead() || obj->mGLTFAsset == nullptr) @@ -1062,9 +1047,6 @@ void GLTFSceneManager::renderDebug()              LLGLDepthTest depth(GL_TRUE, i == 0 ? GL_FALSE : GL_TRUE, i == 0 ? GL_GREATER : GL_LEQUAL);              LLGLState blend(GL_BLEND, i == 0 ? GL_TRUE : GL_FALSE); - -            gGL.pushMatrix(); -              for (auto& obj : mObjects)              {                  if (obj->isDead() || obj->mGLTFAsset == nullptr) @@ -1072,20 +1054,16 @@ void GLTFSceneManager::renderDebug()                      continue;                  } -                mat4 mat = glm::make_mat4(obj->getGLTFAssetToAgentTransform().getF32ptr()); +                gGL.pushMatrix(); -                mat4 modelview = glm::make_mat4(gGLModelView); - -                modelview = modelview * mat; +                gGL.multMatrix(obj->getGLTFAssetToAgentTransform().getF32ptr());                  Asset* asset = obj->mGLTFAsset.get();                  for (auto& node : asset->mNodes)                  { -                    // force update all mRenderMatrix, not just nodes with meshes -                    node.mRenderMatrix = modelview * node.mAssetMatrix; - -                    gGL.loadMatrix(glm::value_ptr(node.mRenderMatrix)); +                    gGL.pushMatrix(); +                    gGL.multMatrix(glm::value_ptr(node.mAssetMatrix));                      // render x-axis red, y-axis green, z-axis blue                      gGL.color4f(1.f, 0.f, 0.f, 0.5f);                      gGL.begin(LLRender::LINES); @@ -1121,12 +1099,12 @@ void GLTFSceneManager::renderDebug()                      }                      gGL.end();                      gGL.flush(); +                    gGL.popMatrix();                  } -            } -            gGL.popMatrix(); +                gGL.popMatrix(); +            }          } -      } @@ -1140,28 +1118,36 @@ void GLTFSceneManager::renderDebug()          if (drawable)          { -            gGL.pushMatrix(); -            Asset* asset = drawable->getVObj()->mGLTFAsset.get(); -            Node* node = &asset->mNodes[node_hit]; -            Primitive* primitive = &asset->mMeshes[node->mMesh].mPrimitives[primitive_hit]; -            gGL.flush(); -            glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); -            gGL.color3f(1, 0, 1); -            drawBoxOutline(intersection, LLVector4a(0.1f, 0.1f, 0.1f, 0.f)); +            LLViewerObject* obj = drawable->getVObj(); +            if (obj) +            { +                gGL.pushMatrix(); +                gGL.multMatrix(obj->getGLTFAssetToAgentTransform().getF32ptr()); +                Asset* asset = obj->mGLTFAsset.get(); +                Node* node = &asset->mNodes[node_hit]; +                Primitive* primitive = &asset->mMeshes[node->mMesh].mPrimitives[primitive_hit]; -            gGL.loadMatrix(glm::value_ptr(node->mRenderMatrix)); +                gGL.flush(); +                glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); +                gGL.color3f(1, 0, 1); +                drawBoxOutline(intersection, LLVector4a(0.1f, 0.1f, 0.1f, 0.f)); +                gGL.multMatrix(glm::value_ptr(node->mAssetMatrix)); -            auto* listener = (LLVolumeOctreeListener*) primitive->mOctree->getListener(0); -            drawBoxOutline(listener->mBounds[0], listener->mBounds[1]); +                auto* listener = (LLVolumeOctreeListener*)primitive->mOctree->getListener(0); +                drawBoxOutline(listener->mBounds[0], listener->mBounds[1]); -            gGL.flush(); -            glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); -            gGL.popMatrix(); +                gGL.flush(); +                glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); +                gGL.popMatrix(); +            }          }      } + +    gGL.popMatrix();      gDebugProgram.unbind(); +  } diff --git a/indra/newview/gltfscenemanager.h b/indra/newview/gltfscenemanager.h index 7da413e8b2..853bca59d0 100644 --- a/indra/newview/gltfscenemanager.h +++ b/indra/newview/gltfscenemanager.h @@ -59,7 +59,7 @@ namespace LL          // bind the given material for rendering          void bind(LL::GLTF::Asset& asset, LL::GLTF::Material& material); - +        void bindTexture(LL::GLTF::Asset& asset, LL::GLTF::TextureType texture_type, LL::GLTF::TextureInfo& info, LLViewerTexture* fallback);          void renderOpaque();          void renderAlpha(); @@ -94,6 +94,11 @@ namespace LL          U32 mPendingGLTFUploads = 0;          U32 mJointUBO = 0; + + +        // render loop state +        S32 mLastTexture[GLTF::TEXTURE_TYPE_COUNT] = { -2, -2, -2, -2, -2 }; +      };  } diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index 93fea899f3..34da5b29d4 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -257,7 +257,7 @@ void LLDrawPoolAlpha::forwardRender(bool rigged)      mAlphaDFactor = LLRender::BF_ONE_MINUS_SOURCE_ALPHA;       // }      gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor); -    if (rigged) +    if (rigged && mType == LLDrawPool::POOL_ALPHA_POST_WATER)      { // draw GLTF scene to depth buffer before rigged alpha          LL::GLTFSceneManager::instance().render(false, false);          LL::GLTFSceneManager::instance().render(false, true); diff --git a/indra/newview/lldrawpoolpbropaque.cpp b/indra/newview/lldrawpoolpbropaque.cpp index 5eb10fe335..4ea23412e6 100644 --- a/indra/newview/lldrawpoolpbropaque.cpp +++ b/indra/newview/lldrawpoolpbropaque.cpp @@ -54,7 +54,10 @@ void LLDrawPoolGLTFPBR::renderDeferred(S32 pass)  {      llassert(!LLPipeline::sRenderingHUDs); -    LL::GLTFSceneManager::instance().renderOpaque(); +    if (mRenderType == LLPipeline::RENDER_TYPE_PASS_GLTF_PBR_ALPHA_MASK) +    { +        LL::GLTFSceneManager::instance().renderOpaque(); +    }      gDeferredPBROpaqueProgram.bind();      pushGLTFBatches(mRenderType); diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index f544b70329..66ccdd2b32 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -188,18 +188,8 @@ void LLHeroProbeManager::update()                  LLVector3(0, 0, -1)              }; -            // Iterate through each face of the cube -            for (int i = 0; i < 6; i++) -            { -                float cube_facing = fmax(-1, fmin(1.0f, cameraDirection * cubeFaces[i])); - -                cube_facing = 1 - cube_facing; - -                mFaceUpdateList[i] = ceilf(cube_facing * gPipeline.RenderHeroProbeConservativeUpdateMultiplier); -                } - -              mProbes[0]->mOrigin = probe_pos; +            mProbes[0]->mRadius = mNearestHero->getScale().magVec() * 0.5f;          }          else          { @@ -220,9 +210,10 @@ void LLHeroProbeManager::renderProbes()      static LLCachedControl<S32> sDetail(gSavedSettings, "RenderHeroReflectionProbeDetail", -1);      static LLCachedControl<S32> sLevel(gSavedSettings, "RenderHeroReflectionProbeLevel", 3); +    static LLCachedControl<S32> sUpdateRate(gSavedSettings, "RenderHeroProbeUpdateRate", 0);      F32 near_clip = 0.01f; -    if (mNearestHero != nullptr && (gPipeline.RenderHeroProbeUpdateRate == 0 || (gFrameCount % gPipeline.RenderHeroProbeUpdateRate) == 0) && +    if (mNearestHero != nullptr &&          !gTeleportDisplay && !gDisconnected && !LLAppViewer::instance()->logoutRequestSent())      {          LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("hpmu - realtime"); @@ -232,20 +223,36 @@ void LLHeroProbeManager::renderProbes()          gPipeline.mReflectionMapManager.mRadiancePass = true;          mRenderingMirror = true; -        doOcclusion(); +        S32 rate = sUpdateRate; -        for (U32 j = 0; j < mProbes.size(); j++) +        // rate must be divisor of 6 (1, 2, 3, or 6) +        if (rate < 1) +        { +            rate = 1; +        } +        else if (rate > 3)          { +            rate = 6; +        } + +        S32 face = gFrameCount % 6; + +        if (!mProbes.empty() && !mProbes[0].isNull() && !mProbes[0]->mOccluded) +        { +            LL_PROFILE_ZONE_NUM(gFrameCount % rate); +            LL_PROFILE_ZONE_NUM(rate); +              for (U32 i = 0; i < 6; ++i)              { -                if (mFaceUpdateList[i] > 0 && mCurrentProbeUpdateFrame % mFaceUpdateList[i] == 0) -                { -                    updateProbeFace(mProbes[j], i, mNearestHero->getReflectionProbeIsDynamic() && sDetail > 0, near_clip); -                    mCurrentProbeUpdateFrame = 0; +                if ((gFrameCount % rate) == (i % rate)) +                { // update 6/rate faces per frame +                    LL_PROFILE_ZONE_NUM(i); +                    updateProbeFace(mProbes[0], i, mNearestHero->getReflectionProbeIsDynamic() && sDetail > 0, near_clip);                  }              } -            generateRadiance(mProbes[j]); +            generateRadiance(mProbes[0]);          } +          mRenderingMirror = false;          gPipeline.mReflectionMapManager.mRadiancePass = radiance_pass; @@ -253,8 +260,6 @@ void LLHeroProbeManager::renderProbes()          mProbes[0]->mViewerObject = mNearestHero;          mProbes[0]->autoAdjustOrigin();      } - -    mCurrentProbeUpdateFrame++;  }  // Do the reflection map update render passes. @@ -388,6 +393,7 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, bool  // Useful when we may not always be rendering a full set of faces of the probe.  void LLHeroProbeManager::generateRadiance(LLReflectionMap* probe)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;      S32 sourceIdx = mReflectionProbeCount;      // Unlike the reflectionmap manager, all probes are considered "realtime" for hero probes. @@ -594,7 +600,7 @@ void LLHeroProbeManager::doOcclusion()      for (auto& probe : mProbes)      { -        if (probe != nullptr && probe != mDefaultProbe) +        if (probe != nullptr)          {              probe->doOcclusion(eye);          } diff --git a/indra/newview/llheroprobemanager.h b/indra/newview/llheroprobemanager.h index c8d505f4c3..28852770c3 100644 --- a/indra/newview/llheroprobemanager.h +++ b/indra/newview/llheroprobemanager.h @@ -147,9 +147,6 @@ private:      bool mReset = false;      bool mRenderingMirror = false; -    std::map<int, int> mFaceUpdateList; - -    U32 mCurrentProbeUpdateFrame = 0;      std::vector<LLPointer<LLVOVolume>>                       mHeroVOList;      LLPointer<LLVOVolume>                                 mNearestHero; diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 37fbfccbbb..12d0aa4f8e 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -259,7 +259,18 @@ static bool make_gltf_variant(LLGLSLShader& shader, LLGLSLShader& variant, bool      variant.mDefines = shader.mDefines;    // NOTE: Must come before addPermutation -    variant.addPermutation("MAX_JOINTS_PER_GLTF_OBJECT", std::to_string(LLSkinningUtil::getMaxGLTFJointCount())); +    U32 node_size = 16 * 3; +    U32 max_nodes = gGLManager.mMaxUniformBlockSize / node_size; +    variant.addPermutation("MAX_NODES_PER_GLTF_OBJECT", std::to_string(max_nodes)); + +    U32 material_size = 16 * 12; +    U32 max_materials = gGLManager.mMaxUniformBlockSize / material_size; +    LLGLSLShader::sMaxGLTFMaterials = max_materials; + +    variant.addPermutation("MAX_MATERIALS_PER_GLTF_OBJECT", std::to_string(max_materials)); + +    U32 max_vec4s = gGLManager.mMaxUniformBlockSize / 16; +    variant.addPermutation("MAX_UBO_VEC4S", std::to_string(max_vec4s));      if (rigged)      { diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index f9ff8217af..6c9c4751d7 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -2436,6 +2436,7 @@ void LLPipeline::doOcclusion(LLCamera& camera)          mCubeVB->setBuffer();          mReflectionMapManager.doOcclusion(); +        mHeroProbeManager.doOcclusion();          gOcclusionCubeProgram.unbind();          gGL.setColorMask(true, true); 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 a80b1e1c13..7bc81a1f79 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 @@ -864,21 +864,21 @@     name="HeroProbeUpdateRate"     width="150">      <combo_box.item -      label="Every Frame" -      name="0" -      value="1"/> +      label="Low" +      name="6" +      value="6"/> +    <combo_box.item +      label="Medium" +      name="3" +      value="3"/>      <combo_box.item -      label="Every 2nd Frame" +      label="High"        name="1"        value="2"/>      <combo_box.item -      label="Every 3rd Frame" -      name="2" -      value="3"/> -    <combo_box.item -      label="Every 4th Frame" -      name="3" -      value="4"/> +      label="Ultra" +      name="0" +      value="1"/>    </combo_box>    <!-- End of mirror settings --> diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 0e7c522f74..4a043bbbc9 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -2866,8 +2866,8 @@ function="World.EnvPreset"          <menu_item_call           label="Open..."           name="Open..."> -          <menu_item_call.on_enable -             function="EnableGLTF"/> +            <!--<menu_item_call.on_enable +             function="EnableGLTF"/>-->            <menu_item_call.on_click             function="Advanced.ClickGLTFOpen" />          </menu_item_call> | 
