From 6c5d7b87891d909500325425a6a1ede7e35da63c Mon Sep 17 00:00:00 2001
From: Brad Davis <bdavis@saintandreas.org>
Date: Thu, 9 Jul 2015 17:53:26 -0700
Subject: [PATCH] Performance optimizations in transform buffers and geometry
 cache

---
 libraries/gpu/src/gpu/GLBackendTransform.cpp |  4 +-
 libraries/render-utils/src/GeometryCache.cpp | 60 +++++++++++++-------
 2 files changed, 42 insertions(+), 22 deletions(-)

diff --git a/libraries/gpu/src/gpu/GLBackendTransform.cpp b/libraries/gpu/src/gpu/GLBackendTransform.cpp
index 5f4d5f4af6..48a42fe5f1 100755
--- a/libraries/gpu/src/gpu/GLBackendTransform.cpp
+++ b/libraries/gpu/src/gpu/GLBackendTransform.cpp
@@ -117,7 +117,7 @@ void GLBackend::updateTransform() {
     if (_transform._invalidView || _transform._invalidProj || _transform._invalidViewport) {
         glBindBufferBase(GL_UNIFORM_BUFFER, TRANSFORM_CAMERA_SLOT, 0);
         glBindBuffer(GL_ARRAY_BUFFER, _transform._transformCameraBuffer);
-        glBufferData(GL_ARRAY_BUFFER, sizeof(_transform._transformCamera), (const void*) &_transform._transformCamera, GL_DYNAMIC_DRAW);
+        glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(_transform._transformCamera), (const void*)&_transform._transformCamera);
         glBindBuffer(GL_ARRAY_BUFFER, 0);
         CHECK_GL_ERROR();
     }
@@ -125,7 +125,7 @@ void GLBackend::updateTransform() {
     if (_transform._invalidModel) {
         glBindBufferBase(GL_UNIFORM_BUFFER, TRANSFORM_OBJECT_SLOT, 0);
         glBindBuffer(GL_ARRAY_BUFFER, _transform._transformObjectBuffer);
-        glBufferData(GL_ARRAY_BUFFER, sizeof(_transform._transformObject), (const void*) &_transform._transformObject, GL_DYNAMIC_DRAW);
+        glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(_transform._transformObject), (const void*) &_transform._transformObject);
         glBindBuffer(GL_ARRAY_BUFFER, 0);
         CHECK_GL_ERROR();
     }
diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp
index 35f946c55c..02e59bfa3a 100644
--- a/libraries/render-utils/src/GeometryCache.cpp
+++ b/libraries/render-utils/src/GeometryCache.cpp
@@ -279,14 +279,21 @@ void GeometryCache::renderSphere(gpu::Batch& batch, float radius, int slices, in
     const int VERTICES_SLOT = 0;
     const int NORMALS_SLOT = 1;
     const int COLOR_SLOT = 2;
-    gpu::Stream::FormatPointer streamFormat(new gpu::Stream::Format()); // 1 for everyone
-    streamFormat->setAttribute(gpu::Stream::POSITION, VERTICES_SLOT, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0);
-    streamFormat->setAttribute(gpu::Stream::NORMAL, NORMALS_SLOT, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ));
-    streamFormat->setAttribute(gpu::Stream::COLOR, COLOR_SLOT, gpu::Element(gpu::VEC4, gpu::UINT8, gpu::RGBA));
+    static gpu::Stream::FormatPointer streamFormat;
+    static gpu::Element positionElement, normalElement, colorElement;
+    if (!streamFormat) {
+        streamFormat.reset(new gpu::Stream::Format()); // 1 for everyone
+        streamFormat->setAttribute(gpu::Stream::POSITION, VERTICES_SLOT, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0);
+        streamFormat->setAttribute(gpu::Stream::NORMAL, NORMALS_SLOT, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ));
+        streamFormat->setAttribute(gpu::Stream::COLOR, COLOR_SLOT, gpu::Element(gpu::VEC4, gpu::UINT8, gpu::RGBA));
+        positionElement = streamFormat->getAttributes().at(gpu::Stream::POSITION)._element;
+        normalElement = streamFormat->getAttributes().at(gpu::Stream::NORMAL)._element;
+        colorElement = streamFormat->getAttributes().at(gpu::Stream::COLOR)._element;
+    }
 
-    gpu::BufferView verticesView(verticesBuffer, streamFormat->getAttributes().at(gpu::Stream::POSITION)._element);
-    gpu::BufferView normalsView(verticesBuffer, streamFormat->getAttributes().at(gpu::Stream::NORMAL)._element);
-    gpu::BufferView colorView(colorBuffer, streamFormat->getAttributes().at(gpu::Stream::COLOR)._element);
+    gpu::BufferView verticesView(verticesBuffer, positionElement);
+    gpu::BufferView normalsView(verticesBuffer, normalElement);
+    gpu::BufferView colorView(colorBuffer, colorElement);
     
     batch.setInputFormat(streamFormat);
     batch.setInputBuffer(VERTICES_SLOT, verticesView);
@@ -899,14 +906,21 @@ void GeometryCache::renderSolidCube(gpu::Batch& batch, float size, const glm::ve
     const int VERTICES_SLOT = 0;
     const int NORMALS_SLOT = 1;
     const int COLOR_SLOT = 2;
-    gpu::Stream::FormatPointer streamFormat(new gpu::Stream::Format()); // 1 for everyone
+    static gpu::Stream::FormatPointer streamFormat;
+    static gpu::Element positionElement, normalElement, colorElement;
+    if (!streamFormat) {
+        streamFormat.reset(new gpu::Stream::Format()); // 1 for everyone
+        streamFormat->setAttribute(gpu::Stream::POSITION, VERTICES_SLOT, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0);
+        streamFormat->setAttribute(gpu::Stream::NORMAL, NORMALS_SLOT, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ));
+        streamFormat->setAttribute(gpu::Stream::COLOR, COLOR_SLOT, gpu::Element(gpu::VEC4, gpu::UINT8, gpu::RGBA));
+        positionElement = streamFormat->getAttributes().at(gpu::Stream::POSITION)._element;
+        normalElement = streamFormat->getAttributes().at(gpu::Stream::NORMAL)._element;
+        colorElement = streamFormat->getAttributes().at(gpu::Stream::COLOR)._element;
+    }
     
-    streamFormat->setAttribute(gpu::Stream::POSITION, VERTICES_SLOT, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0);
-    streamFormat->setAttribute(gpu::Stream::NORMAL, NORMALS_SLOT, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ));
-    streamFormat->setAttribute(gpu::Stream::COLOR, COLOR_SLOT, gpu::Element(gpu::VEC4, gpu::UINT8, gpu::RGBA));
-
-    gpu::BufferView verticesView(verticesBuffer, 0, verticesBuffer->getSize(), VERTEX_STRIDE, streamFormat->getAttributes().at(gpu::Stream::POSITION)._element);
-    gpu::BufferView normalsView(verticesBuffer, NORMALS_OFFSET, verticesBuffer->getSize(), VERTEX_STRIDE, streamFormat->getAttributes().at(gpu::Stream::NORMAL)._element);
+    
+    gpu::BufferView verticesView(verticesBuffer, 0, verticesBuffer->getSize(), VERTEX_STRIDE, positionElement);
+    gpu::BufferView normalsView(verticesBuffer, NORMALS_OFFSET, verticesBuffer->getSize(), VERTEX_STRIDE, normalElement);
     gpu::BufferView colorView(colorBuffer, streamFormat->getAttributes().at(gpu::Stream::COLOR)._element);
     
     batch.setInputFormat(streamFormat);
@@ -986,12 +1000,18 @@ void GeometryCache::renderWireCube(gpu::Batch& batch, float size, const glm::vec
 
     const int VERTICES_SLOT = 0;
     const int COLOR_SLOT = 1;
-    gpu::Stream::FormatPointer streamFormat(new gpu::Stream::Format()); // 1 for everyone
-    streamFormat->setAttribute(gpu::Stream::POSITION, VERTICES_SLOT, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0);
-    streamFormat->setAttribute(gpu::Stream::COLOR, COLOR_SLOT, gpu::Element(gpu::VEC4, gpu::UINT8, gpu::RGBA));
-    
-    gpu::BufferView verticesView(verticesBuffer, streamFormat->getAttributes().at(gpu::Stream::POSITION)._element);
-    gpu::BufferView colorView(colorBuffer, streamFormat->getAttributes().at(gpu::Stream::COLOR)._element);
+    static gpu::Stream::FormatPointer streamFormat;
+    static gpu::Element positionElement, colorElement;
+    if (!streamFormat) {
+        streamFormat.reset(new gpu::Stream::Format()); // 1 for everyone
+        streamFormat->setAttribute(gpu::Stream::POSITION, VERTICES_SLOT, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0);
+        streamFormat->setAttribute(gpu::Stream::COLOR, COLOR_SLOT, gpu::Element(gpu::VEC4, gpu::UINT8, gpu::RGBA));
+        positionElement = streamFormat->getAttributes().at(gpu::Stream::POSITION)._element;
+        colorElement = streamFormat->getAttributes().at(gpu::Stream::COLOR)._element;
+    }
+   
+    gpu::BufferView verticesView(verticesBuffer, positionElement);
+    gpu::BufferView colorView(colorBuffer, colorElement);
     
     batch.setInputFormat(streamFormat);
     batch.setInputBuffer(VERTICES_SLOT, verticesView);