diff --git a/interface/src/Util.cpp b/interface/src/Util.cpp index 4983983c02..43c52916fe 100644 --- a/interface/src/Util.cpp +++ b/interface/src/Util.cpp @@ -96,26 +96,31 @@ void renderWorldBox(gpu::Batch& batch) { glm::vec3(HALF_TREE_SCALE, 0.0f, HALF_TREE_SCALE), GREY); - geometryCache->renderWireCubeInstance(batch, Transform(), GREY4); + geometryCache->renderWireCubeInstance(batch, GREY4); // Draw meter markers along the 3 axis to help with measuring things const float MARKER_DISTANCE = 1.0f; const float MARKER_RADIUS = 0.05f; transform = Transform().setScale(MARKER_RADIUS); - geometryCache->renderSolidSphereInstance(batch, transform, RED); + batch.setModelTransform(transform); + geometryCache->renderSolidSphereInstance(batch, RED); transform = Transform().setTranslation(glm::vec3(MARKER_DISTANCE, 0.0f, 0.0f)).setScale(MARKER_RADIUS); - geometryCache->renderSolidSphereInstance(batch, transform, RED); + batch.setModelTransform(transform); + geometryCache->renderSolidSphereInstance(batch, RED); transform = Transform().setTranslation(glm::vec3(0.0f, MARKER_DISTANCE, 0.0f)).setScale(MARKER_RADIUS); - geometryCache->renderSolidSphereInstance(batch, transform, GREEN); + batch.setModelTransform(transform); + geometryCache->renderSolidSphereInstance(batch, GREEN); transform = Transform().setTranslation(glm::vec3(0.0f, 0.0f, MARKER_DISTANCE)).setScale(MARKER_RADIUS); - geometryCache->renderSolidSphereInstance(batch, transform, BLUE); + batch.setModelTransform(transform); + geometryCache->renderSolidSphereInstance(batch, BLUE); transform = Transform().setTranslation(glm::vec3(MARKER_DISTANCE, 0.0f, MARKER_DISTANCE)).setScale(MARKER_RADIUS); - geometryCache->renderSolidSphereInstance(batch, transform, GREY); + batch.setModelTransform(transform); + geometryCache->renderSolidSphereInstance(batch, GREY); } // Return a random vector of average length 1 diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 2739a9483b..a552b77f1f 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -456,7 +456,8 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) { Transform transform; transform.setTranslation(position); transform.postScale(INDICATOR_RADIUS); - DependencyManager::get()->renderSolidSphereInstance(batch, transform, LOOK_AT_INDICATOR_COLOR); + batch.setModelTransform(transform); + DependencyManager::get()->renderSolidSphereInstance(batch, LOOK_AT_INDICATOR_COLOR); } // If the avatar is looking at me, indicate that they are @@ -484,9 +485,9 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) { eyeDiameter = DEFAULT_EYE_DIAMETER; } + batch.setModelTransform(Transform(transform).postScale(eyeDiameter * getUniformScale() / 2.0f + RADIUS_INCREMENT)); DependencyManager::get()->renderSolidSphereInstance(batch, - Transform(transform).postScale(eyeDiameter * getUniformScale() / 2.0f + RADIUS_INCREMENT), - glm::vec4(LOOKING_AT_ME_COLOR, alpha)); + glm::vec4(LOOKING_AT_ME_COLOR, alpha)); position = getHead()->getRightEyePosition(); transform.setTranslation(position); @@ -494,9 +495,9 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) { if (eyeDiameter == 0.0f) { eyeDiameter = DEFAULT_EYE_DIAMETER; } + batch.setModelTransform(Transform(transform).postScale(eyeDiameter * getUniformScale() / 2.0f + RADIUS_INCREMENT)); DependencyManager::get()->renderSolidSphereInstance(batch, - Transform(transform).postScale(eyeDiameter * getUniformScale() / 2.0f + RADIUS_INCREMENT), - glm::vec4(LOOKING_AT_ME_COLOR, alpha)); + glm::vec4(LOOKING_AT_ME_COLOR, alpha)); } } diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index fba5e1ab13..5371fe5736 100644 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -60,7 +60,8 @@ void Hand::renderHandTargets(RenderArgs* renderArgs, bool isMine) { transform.setTranslation(position); transform.setRotation(palm.getRotation()); transform.postScale(SPHERE_RADIUS); - DependencyManager::get()->renderSolidSphereInstance(batch, transform, grayColor); + batch.setModelTransform(transform); + DependencyManager::get()->renderSolidSphereInstance(batch, grayColor); // draw a green sphere at the old "finger tip" transform = Transform(); @@ -68,7 +69,8 @@ void Hand::renderHandTargets(RenderArgs* renderArgs, bool isMine) { transform.setTranslation(position); transform.setRotation(palm.getRotation()); transform.postScale(SPHERE_RADIUS); - DependencyManager::get()->renderSolidSphereInstance(batch, transform, greenColor); + batch.setModelTransform(transform); + DependencyManager::get()->renderSolidSphereInstance(batch, greenColor); } } diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index 61bc5c861e..b97fd2b0ea 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -467,5 +467,6 @@ void Head::renderLookatTarget(RenderArgs* renderArgs, glm::vec3 lookatPosition) const float LOOK_AT_TARGET_RADIUS = 0.075f; transform.postScale(LOOK_AT_TARGET_RADIUS); const glm::vec4 LOOK_AT_TARGET_COLOR = { 0.8f, 0.0f, 0.0f, 0.75f }; - geometryCache->renderSolidSphereInstance(batch, transform, LOOK_AT_TARGET_COLOR); + batch.setModelTransform(transform); + geometryCache->renderSolidSphereInstance(batch, LOOK_AT_TARGET_COLOR); } diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 969773c3d3..6198a1b0a0 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -349,17 +349,15 @@ void SkeletonModel::renderBoundingCollisionShapes(gpu::Batch& batch, float scale // draw a blue sphere at the capsule top point glm::vec3 topPoint = _translation + getRotation() * (scale * (_boundingCapsuleLocalOffset + (0.5f * _boundingCapsuleHeight) * Vectors::UNIT_Y)); - geometryCache->renderSolidSphereInstance(batch, - Transform().setTranslation(topPoint).postScale(scale * _boundingCapsuleRadius), - glm::vec4(0.6f, 0.6f, 0.8f, alpha)); + batch.setModelTransform(Transform().setTranslation(topPoint).postScale(scale * _boundingCapsuleRadius)); + geometryCache->renderSolidSphereInstance(batch, glm::vec4(0.6f, 0.6f, 0.8f, alpha)); // draw a yellow sphere at the capsule bottom point glm::vec3 bottomPoint = topPoint - glm::vec3(0.0f, scale * _boundingCapsuleHeight, 0.0f); glm::vec3 axis = topPoint - bottomPoint; - geometryCache->renderSolidSphereInstance(batch, - Transform().setTranslation(bottomPoint).postScale(scale * _boundingCapsuleRadius), - glm::vec4(0.8f, 0.8f, 0.6f, alpha)); + batch.setModelTransform(Transform().setTranslation(bottomPoint).postScale(scale * _boundingCapsuleRadius)); + geometryCache->renderSolidSphereInstance(batch, glm::vec4(0.8f, 0.8f, 0.6f, alpha)); // draw a green cylinder between the two points glm::vec3 origin(0.0f); diff --git a/interface/src/ui/overlays/Cube3DOverlay.cpp b/interface/src/ui/overlays/Cube3DOverlay.cpp index 7688bce985..e291882161 100644 --- a/interface/src/ui/overlays/Cube3DOverlay.cpp +++ b/interface/src/ui/overlays/Cube3DOverlay.cpp @@ -60,7 +60,8 @@ void Cube3DOverlay::render(RenderArgs* args) { // } transform.setScale(dimensions); - DependencyManager::get()->renderSolidCubeInstance(*batch, transform, cubeColor); + batch->setModelTransform(transform); + DependencyManager::get()->renderSolidCubeInstance(*batch, cubeColor); } else { if (getIsDashedLine()) { @@ -96,9 +97,9 @@ void Cube3DOverlay::render(RenderArgs* args) { geometryCache->renderDashedLine(*batch, bottomRightFar, topRightFar, cubeColor); } else { - batch->setModelTransform(Transform()); transform.setScale(dimensions); - DependencyManager::get()->renderWireCubeInstance(*batch, transform, cubeColor); + batch->setModelTransform(transform); + DependencyManager::get()->renderWireCubeInstance(*batch, cubeColor); } } } diff --git a/interface/src/ui/overlays/Sphere3DOverlay.cpp b/interface/src/ui/overlays/Sphere3DOverlay.cpp index 63ed7fe31d..dcd1460ff4 100644 --- a/interface/src/ui/overlays/Sphere3DOverlay.cpp +++ b/interface/src/ui/overlays/Sphere3DOverlay.cpp @@ -39,14 +39,13 @@ void Sphere3DOverlay::render(RenderArgs* args) { auto batch = args->_batch; if (batch) { - batch->setModelTransform(Transform()); - Transform transform = _transform; transform.postScale(getDimensions() * SPHERE_OVERLAY_SCALE); + batch->setModelTransform(transform); if (_isSolid) { - DependencyManager::get()->renderSolidSphereInstance(*batch, transform, sphereColor); + DependencyManager::get()->renderSolidSphereInstance(*batch, sphereColor); } else { - DependencyManager::get()->renderWireSphereInstance(*batch, transform, sphereColor); + DependencyManager::get()->renderWireSphereInstance(*batch, sphereColor); } } } diff --git a/libraries/entities-renderer/src/RenderableBoxEntityItem.cpp b/libraries/entities-renderer/src/RenderableBoxEntityItem.cpp index 1b1437a7d9..2d054ec31b 100644 --- a/libraries/entities-renderer/src/RenderableBoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableBoxEntityItem.cpp @@ -61,14 +61,14 @@ void RenderableBoxEntityItem::render(RenderArgs* args) { return; } + batch.setModelTransform(transToCenter); // we want to include the scale as well if (_procedural->ready()) { - batch.setModelTransform(transToCenter); // we want to include the scale as well _procedural->prepare(batch, getPosition(), getDimensions()); auto color = _procedural->getColor(cubeColor); batch._glColor4f(color.r, color.g, color.b, color.a); DependencyManager::get()->renderCube(batch); } else { - DependencyManager::get()->renderSolidCubeInstance(batch, transToCenter, cubeColor); + DependencyManager::get()->renderSolidCubeInstance(batch, cubeColor); } static const auto triCount = DependencyManager::get()->getCubeTriangleCount(); args->_details._trianglesRendered += (int)triCount; diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index a788a76905..84c53e05da 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -440,8 +440,8 @@ void RenderableModelEntityItem::render(RenderArgs* args) { bool success; auto shapeTransform = getTransformToCenter(success); if (success) { - batch.setModelTransform(Transform()); // we want to include the scale as well - DependencyManager::get()->renderWireCubeInstance(batch, shapeTransform, greenColor); + batch.setModelTransform(shapeTransform); // we want to include the scale as well + DependencyManager::get()->renderWireCubeInstance(batch, greenColor); } } } diff --git a/libraries/entities-renderer/src/RenderableSphereEntityItem.cpp b/libraries/entities-renderer/src/RenderableSphereEntityItem.cpp index 9f16de0db1..b5867fb1ee 100644 --- a/libraries/entities-renderer/src/RenderableSphereEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableSphereEntityItem.cpp @@ -64,15 +64,14 @@ void RenderableSphereEntityItem::render(RenderArgs* args) { return; } modelTransform.postScale(SPHERE_ENTITY_SCALE); + batch.setModelTransform(modelTransform); // use a transform with scale, rotation, registration point and translation if (_procedural->ready()) { - batch.setModelTransform(modelTransform); // use a transform with scale, rotation, registration point and translation _procedural->prepare(batch, getPosition(), getDimensions()); auto color = _procedural->getColor(sphereColor); batch._glColor4f(color.r, color.g, color.b, color.a); DependencyManager::get()->renderSphere(batch); } else { - batch.setModelTransform(Transform()); - DependencyManager::get()->renderSolidSphereInstance(batch, modelTransform, sphereColor); + DependencyManager::get()->renderSolidSphereInstance(batch, sphereColor); } static const auto triCount = DependencyManager::get()->getSphereTriangleCount(); args->_details._trianglesRendered += (int)triCount; diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp index 9396933fc6..530c4f5063 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp @@ -132,7 +132,6 @@ void RenderableZoneEntityItem::render(RenderArgs* args) { Q_ASSERT(args->_batch); gpu::Batch& batch = *args->_batch; - batch.setModelTransform(Transform()); bool success; auto shapeTransform = getTransformToCenter(success); @@ -142,9 +141,11 @@ void RenderableZoneEntityItem::render(RenderArgs* args) { auto geometryCache = DependencyManager::get(); if (getShapeType() == SHAPE_TYPE_SPHERE) { shapeTransform.postScale(SPHERE_ENTITY_SCALE); - geometryCache->renderWireSphereInstance(batch, shapeTransform, DEFAULT_COLOR); + batch.setModelTransform(shapeTransform); + geometryCache->renderWireSphereInstance(batch, DEFAULT_COLOR); } else { - geometryCache->renderWireCubeInstance(batch, shapeTransform, DEFAULT_COLOR); + batch.setModelTransform(shapeTransform); + geometryCache->renderWireCubeInstance(batch, DEFAULT_COLOR); } break; } diff --git a/libraries/gl/src/gl/Config.h b/libraries/gl/src/gl/Config.h index 2e42e85122..8f7582c271 100644 --- a/libraries/gl/src/gl/Config.h +++ b/libraries/gl/src/gl/Config.h @@ -9,8 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#ifndef gpu__GPUConfig__ -#define gpu__GPUConfig__ +#ifndef hifi_gpu_GPUConfig_h +#define hifi_gpu_GPUConfig_h #define GL_GLEXT_PROTOTYPES 1 @@ -38,8 +38,6 @@ #define GPU_FEATURE_PROFILE GPU_CORE #define GPU_INPUT_PROFILE GPU_CORE_43 -#elif defined(ANDROID) - #else #include @@ -50,4 +48,11 @@ #endif +#if (GPU_INPUT_PROFILE == GPU_CORE_43) +// Deactivate SSBO for now, we've run into some issues +// on GL 4.3 capable GPUs not behaving as expected +//#define GPU_SSBO_DRAW_CALL_INFO #endif + + +#endif // hifi_gpu_GPUConfig_h diff --git a/libraries/gpu/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp index 999e528a94..18e923831f 100644 --- a/libraries/gpu/src/gpu/Batch.cpp +++ b/libraries/gpu/src/gpu/Batch.cpp @@ -29,20 +29,6 @@ ProfileRangeBatch::~ProfileRangeBatch() { using namespace gpu; -Batch::Batch() : - _commands(), - _commandOffsets(), - _params(), - _data(), - _buffers(), - _textures(), - _streamFormats(), - _transforms(), - _pipelines(), - _framebuffers() -{ -} - Batch::Batch(const CacheState& cacheState) : Batch() { _commands.reserve(cacheState.commandsSize); _commandOffsets.reserve(cacheState.offsetsSize); @@ -88,6 +74,8 @@ void Batch::draw(Primitive primitiveType, uint32 numVertices, uint32 startVertex _params.push_back(startVertex); _params.push_back(numVertices); _params.push_back(primitiveType); + + captureDrawCallInfo(); } void Batch::drawIndexed(Primitive primitiveType, uint32 numIndices, uint32 startIndex) { @@ -96,6 +84,8 @@ void Batch::drawIndexed(Primitive primitiveType, uint32 numIndices, uint32 start _params.push_back(startIndex); _params.push_back(numIndices); _params.push_back(primitiveType); + + captureDrawCallInfo(); } void Batch::drawInstanced(uint32 numInstances, Primitive primitiveType, uint32 numVertices, uint32 startVertex, uint32 startInstance) { @@ -106,6 +96,8 @@ void Batch::drawInstanced(uint32 numInstances, Primitive primitiveType, uint32 n _params.push_back(numVertices); _params.push_back(primitiveType); _params.push_back(numInstances); + + captureDrawCallInfo(); } void Batch::drawIndexedInstanced(uint32 numInstances, Primitive primitiveType, uint32 numIndices, uint32 startIndex, uint32 startInstance) { @@ -116,6 +108,8 @@ void Batch::drawIndexedInstanced(uint32 numInstances, Primitive primitiveType, u _params.push_back(numIndices); _params.push_back(primitiveType); _params.push_back(numInstances); + + captureDrawCallInfo(); } @@ -123,12 +117,16 @@ void Batch::multiDrawIndirect(uint32 numCommands, Primitive primitiveType) { ADD_COMMAND(multiDrawIndirect); _params.push_back(numCommands); _params.push_back(primitiveType); + + captureDrawCallInfo(); } void Batch::multiDrawIndexedIndirect(uint32 nbCommands, Primitive primitiveType) { ADD_COMMAND(multiDrawIndexedIndirect); _params.push_back(nbCommands); _params.push_back(primitiveType); + + captureDrawCallInfo(); } void Batch::setInputFormat(const Stream::FormatPointer& format) { @@ -185,7 +183,8 @@ void Batch::setIndirectBuffer(const BufferPointer& buffer, Offset offset, Offset void Batch::setModelTransform(const Transform& model) { ADD_COMMAND(setModelTransform); - _params.push_back(_transforms.cache(model)); + _currentModel = model; + _invalidModel = true; } void Batch::setViewTransform(const Transform& view) { @@ -344,6 +343,19 @@ void Batch::runLambda(std::function f) { _params.push_back(_lambdas.cache(f)); } +void Batch::startNamedCall(const std::string& name) { + ADD_COMMAND(startNamedCall); + _params.push_back(_names.cache(name)); + + _currentNamedCall = name; +} + +void Batch::stopNamedCall() { + ADD_COMMAND(stopNamedCall); + + _currentNamedCall.clear(); +} + void Batch::enableStereo(bool enable) { _enableStereo = enable; } @@ -360,14 +372,13 @@ bool Batch::isSkyboxEnabled() const { return _enableSkybox; } -void Batch::setupNamedCalls(const std::string& instanceName, size_t count, NamedBatchData::Function function) { - NamedBatchData& instance = _namedData[instanceName]; - instance.count += count; - instance.function = function; -} - void Batch::setupNamedCalls(const std::string& instanceName, NamedBatchData::Function function) { - setupNamedCalls(instanceName, 1, function); + NamedBatchData& instance = _namedData[instanceName]; + if (!instance.function) { + instance.function = function; + } + + captureNamedDrawCallInfo(instanceName); } BufferPointer Batch::getNamedBuffer(const std::string& instanceName, uint8_t index) { @@ -376,16 +387,74 @@ BufferPointer Batch::getNamedBuffer(const std::string& instanceName, uint8_t ind instance.buffers.resize(index + 1); } if (!instance.buffers[index]) { - instance.buffers[index].reset(new Buffer()); + instance.buffers[index] = std::make_shared(); } return instance.buffers[index]; } +Batch::DrawCallInfoBuffer& Batch::getDrawCallInfoBuffer() { + if (_currentNamedCall.empty()) { + return _drawCallInfos; + } else { + return _namedData[_currentNamedCall].drawCallInfos; + } +} + +const Batch::DrawCallInfoBuffer& Batch::getDrawCallInfoBuffer() const { + if (_currentNamedCall.empty()) { + return _drawCallInfos; + } else { + auto it = _namedData.find(_currentNamedCall); + Q_ASSERT_X(it != _namedData.end(), Q_FUNC_INFO, (_currentNamedCall + " not in _namedData.").data()); + return it->second.drawCallInfos; + } +} + +void Batch::captureDrawCallInfoImpl() { + if (_invalidModel) { + TransformObject object; + _currentModel.getMatrix(object._model); + + // FIXME - we don't want to be using glm::inverse() here but it fixes the flickering issue we are + // seeing with planky blocks in toybox. Our implementation of getInverseMatrix() is buggy in cases + // of non-uniform scale. We need to fix that. In the mean time, glm::inverse() works. + //_model.getInverseMatrix(_object._modelInverse); + object._modelInverse = glm::inverse(object._model); + + _objects.push_back(object); + + // Flag is clean + _invalidModel = false; + } + + auto& drawCallInfos = getDrawCallInfoBuffer(); + drawCallInfos.push_back((uint16)_objects.size() - 1); +} + +void Batch::captureDrawCallInfo() { + if (!_currentNamedCall.empty()) { + // If we are processing a named call, we don't want to register the raw draw calls + return; + } + + captureDrawCallInfoImpl(); +} + +void Batch::captureNamedDrawCallInfo(std::string name) { + std::swap(_currentNamedCall, name); // Set and save _currentNamedCall + captureDrawCallInfoImpl(); + std::swap(_currentNamedCall, name); // Restore _currentNamedCall +} + void Batch::preExecute() { for (auto& mapItem : _namedData) { - mapItem.second.process(*this); + auto& name = mapItem.first; + auto& instance = mapItem.second; + + startNamedCall(name); + instance.process(*this); + stopNamedCall(); } - _namedData.clear(); } QDebug& operator<<(QDebug& debug, const Batch::CacheState& cacheState) { diff --git a/libraries/gpu/src/gpu/Batch.h b/libraries/gpu/src/gpu/Batch.h index aa2fc1622c..a2ee57759f 100644 --- a/libraries/gpu/src/gpu/Batch.h +++ b/libraries/gpu/src/gpu/Batch.h @@ -29,7 +29,12 @@ class QDebug; namespace gpu { enum ReservedSlot { + +#ifdef GPU_SSBO_DRAW_CALL_INFO TRANSFORM_OBJECT_SLOT = 6, +#else + TRANSFORM_OBJECT_SLOT = 31, +#endif TRANSFORM_CAMERA_SLOT = 7, }; @@ -45,13 +50,31 @@ class Batch { public: typedef Stream::Slot Slot; + + class DrawCallInfo { + public: + using Index = uint16_t; + + DrawCallInfo(Index idx) : index(idx) {} + + Index index { 0 }; + uint16_t unused { 0 }; // Reserved space for later + + }; + // Make sure DrawCallInfo has no extra padding + static_assert(sizeof(DrawCallInfo) == 4, "DrawCallInfo size is incorrect."); + + using DrawCallInfoBuffer = std::vector; + struct NamedBatchData { using BufferPointers = std::vector; using Function = std::function; BufferPointers buffers; - size_t count { 0 }; Function function; + DrawCallInfoBuffer drawCallInfos; + + size_t count() const { return drawCallInfos.size(); } void process(Batch& batch) { if (function) { @@ -62,6 +85,16 @@ public: using NamedBatchDataMap = std::map; + DrawCallInfoBuffer _drawCallInfos; + + std::string _currentNamedCall; + + const DrawCallInfoBuffer& getDrawCallInfoBuffer() const; + DrawCallInfoBuffer& getDrawCallInfoBuffer(); + + void captureDrawCallInfo(); + void captureNamedDrawCallInfo(std::string name); + class CacheState { public: size_t commandsSize; @@ -88,7 +121,7 @@ public: transformsSize(transformsSize), pipelinesSize(pipelinesSize), framebuffersSize(framebuffersSize), queriesSize(queriesSize) { } }; - Batch(); + Batch() {} Batch(const CacheState& cacheState); explicit Batch(const Batch& batch); ~Batch(); @@ -121,13 +154,8 @@ public: void multiDrawIndirect(uint32 numCommands, Primitive primitiveType); void multiDrawIndexedIndirect(uint32 numCommands, Primitive primitiveType); - - void setupNamedCalls(const std::string& instanceName, size_t count, NamedBatchData::Function function); void setupNamedCalls(const std::string& instanceName, NamedBatchData::Function function); BufferPointer getNamedBuffer(const std::string& instanceName, uint8_t index = 0); - void setNamedBuffer(const std::string& instanceName, BufferPointer& buffer, uint8_t index = 0); - - // Input Stage // InputFormat @@ -304,6 +332,9 @@ public: COMMAND_runLambda, + COMMAND_startNamedCall, + COMMAND_stopNamedCall, + // TODO: As long as we have gl calls explicitely issued from interface // code, we need to be able to record and batch these calls. THe long // term strategy is to get rid of any GL calls in favor of the HIFI GPU API @@ -395,7 +426,7 @@ public: typedef Cache::Vector PipelineCaches; typedef Cache::Vector FramebufferCaches; typedef Cache::Vector QueryCaches; - typedef Cache::Vector ProfileRangeCaches; + typedef Cache::Vector StringCaches; typedef Cache>::Vector LambdaCache; // Cache Data in a byte array if too big to fit in Param @@ -415,6 +446,18 @@ public: Params _params; Bytes _data; + // SSBO class... layout MUST match the layout in TransformCamera.slh + class TransformObject { + public: + Mat4 _model; + Mat4 _modelInverse; + }; + + using TransformObjects = std::vector; + bool _invalidModel { true }; + Transform _currentModel; + TransformObjects _objects; + BufferCaches _buffers; TextureCaches _textures; StreamFormatCaches _streamFormats; @@ -423,7 +466,8 @@ public: FramebufferCaches _framebuffers; QueryCaches _queries; LambdaCache _lambdas; - ProfileRangeCaches _profileRanges; + StringCaches _profileRanges; + StringCaches _names; NamedBatchDataMap _namedData; @@ -431,8 +475,13 @@ public: bool _enableSkybox{ false }; protected: + void startNamedCall(const std::string& name); + void stopNamedCall(); + // Maybe useful but shoudln't be public. Please convince me otherwise void runLambda(std::function f); + + void captureDrawCallInfoImpl(); }; } diff --git a/libraries/gpu/src/gpu/Context.h b/libraries/gpu/src/gpu/Context.h index ed2afe91eb..dceb606f20 100644 --- a/libraries/gpu/src/gpu/Context.h +++ b/libraries/gpu/src/gpu/Context.h @@ -76,13 +76,6 @@ public: virtual void syncCache() = 0; virtual void downloadFramebuffer(const FramebufferPointer& srcFramebuffer, const Vec4i& region, QImage& destImage) = 0; - // UBO class... layout MUST match the layout in TransformCamera.slh - class TransformObject { - public: - Mat4 _model; - Mat4 _modelInverse; - }; - // UBO class... layout MUST match the layout in TransformCamera.slh class TransformCamera { public: diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index a730c06bd9..14e4397b83 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -62,6 +62,9 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = (&::gpu::GLBackend::do_runLambda), + (&::gpu::GLBackend::do_startNamedCall), + (&::gpu::GLBackend::do_stopNamedCall), + (&::gpu::GLBackend::do_glActiveBindTexture), (&::gpu::GLBackend::do_glUniform1i), @@ -121,11 +124,7 @@ Backend* GLBackend::createBackend() { return new GLBackend(); } -GLBackend::GLBackend() : - _input(), - _pipeline(), - _output() -{ +GLBackend::GLBackend() { glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &_uboAlignment); initInput(); initTransform(); @@ -155,31 +154,30 @@ void GLBackend::renderPassTransfer(Batch& batch) { { // Sync all the buffers PROFILE_RANGE("syncCPUTransform"); - _transform._cameras.resize(0); + _transform._cameras.clear(); _transform._cameraOffsets.clear(); - _transform._objects.resize(0); - _transform._objectOffsets.clear(); for (_commandIndex = 0; _commandIndex < numCommands; ++_commandIndex) { switch (*command) { - case Batch::COMMAND_draw: - case Batch::COMMAND_drawIndexed: - case Batch::COMMAND_drawInstanced: - case Batch::COMMAND_drawIndexedInstanced: - _transform.preUpdate(_commandIndex, _stereo); - break; + case Batch::COMMAND_draw: + case Batch::COMMAND_drawIndexed: + case Batch::COMMAND_drawInstanced: + case Batch::COMMAND_drawIndexedInstanced: + case Batch::COMMAND_multiDrawIndirect: + case Batch::COMMAND_multiDrawIndexedIndirect: + _transform.preUpdate(_commandIndex, _stereo); + break; - case Batch::COMMAND_setModelTransform: - case Batch::COMMAND_setViewportTransform: - case Batch::COMMAND_setViewTransform: - case Batch::COMMAND_setProjectionTransform: { - CommandCall call = _commandCalls[(*command)]; - (this->*(call))(batch, *offset); - break; - } + case Batch::COMMAND_setViewportTransform: + case Batch::COMMAND_setViewTransform: + case Batch::COMMAND_setProjectionTransform: { + CommandCall call = _commandCalls[(*command)]; + (this->*(call))(batch, *offset); + break; + } - default: - break; + default: + break; } command++; offset++; @@ -188,12 +186,14 @@ void GLBackend::renderPassTransfer(Batch& batch) { { // Sync the transform buffers PROFILE_RANGE("syncGPUTransform"); - _transform.transfer(); + _transform.transfer(batch); } + + } void GLBackend::renderPassDraw(Batch& batch) { - _transform._objectsItr = _transform._objectOffsets.begin(); + _currentDraw = -1; _transform._camerasItr = _transform._cameraOffsets.begin(); const size_t numCommands = batch.getCommands().size(); const Batch::Commands::value_type* command = batch.getCommands().data(); @@ -209,6 +209,22 @@ void GLBackend::renderPassDraw(Batch& batch) { case Batch::COMMAND_setProjectionTransform: break; + case Batch::COMMAND_draw: + case Batch::COMMAND_drawIndexed: + case Batch::COMMAND_drawInstanced: + case Batch::COMMAND_drawIndexedInstanced: + case Batch::COMMAND_multiDrawIndirect: + case Batch::COMMAND_multiDrawIndexedIndirect: { + // updates for draw calls + ++_currentDraw; + updateInput(); + updateTransform(batch); + updatePipeline(); + + CommandCall call = _commandCalls[(*command)]; + (this->*(call))(batch, *offset); + break; + } default: { CommandCall call = _commandCalls[(*command)]; (this->*(call))(batch, *offset); @@ -306,10 +322,6 @@ void GLBackend::syncCache() { } void GLBackend::do_draw(Batch& batch, size_t paramOffset) { - updateInput(); - updateTransform(); - updatePipeline(); - Primitive primitiveType = (Primitive)batch._params[paramOffset + 2]._uint; GLenum mode = _primitiveToGLmode[primitiveType]; uint32 numVertices = batch._params[paramOffset + 1]._uint; @@ -319,10 +331,6 @@ void GLBackend::do_draw(Batch& batch, size_t paramOffset) { } void GLBackend::do_drawIndexed(Batch& batch, size_t paramOffset) { - updateInput(); - updateTransform(); - updatePipeline(); - Primitive primitiveType = (Primitive)batch._params[paramOffset + 2]._uint; GLenum mode = _primitiveToGLmode[primitiveType]; uint32 numIndices = batch._params[paramOffset + 1]._uint; @@ -338,10 +346,6 @@ void GLBackend::do_drawIndexed(Batch& batch, size_t paramOffset) { } void GLBackend::do_drawInstanced(Batch& batch, size_t paramOffset) { - updateInput(); - updateTransform(); - updatePipeline(); - GLint numInstances = batch._params[paramOffset + 4]._uint; Primitive primitiveType = (Primitive)batch._params[paramOffset + 3]._uint; GLenum mode = _primitiveToGLmode[primitiveType]; @@ -353,10 +357,6 @@ void GLBackend::do_drawInstanced(Batch& batch, size_t paramOffset) { } void GLBackend::do_drawIndexedInstanced(Batch& batch, size_t paramOffset) { - updateInput(); - updateTransform(); - updatePipeline(); - GLint numInstances = batch._params[paramOffset + 4]._uint; GLenum mode = _primitiveToGLmode[(Primitive)batch._params[paramOffset + 3]._uint]; uint32 numIndices = batch._params[paramOffset + 2]._uint; @@ -381,10 +381,6 @@ void GLBackend::do_drawIndexedInstanced(Batch& batch, size_t paramOffset) { void GLBackend::do_multiDrawIndirect(Batch& batch, size_t paramOffset) { #if (GPU_INPUT_PROFILE == GPU_CORE_43) - updateInput(); - updateTransform(); - updatePipeline(); - uint commandCount = batch._params[paramOffset + 0]._uint; GLenum mode = _primitiveToGLmode[(Primitive)batch._params[paramOffset + 1]._uint]; @@ -398,10 +394,6 @@ void GLBackend::do_multiDrawIndirect(Batch& batch, size_t paramOffset) { void GLBackend::do_multiDrawIndexedIndirect(Batch& batch, size_t paramOffset) { #if (GPU_INPUT_PROFILE == GPU_CORE_43) - updateInput(); - updateTransform(); - updatePipeline(); - uint commandCount = batch._params[paramOffset + 0]._uint; GLenum mode = _primitiveToGLmode[(Primitive)batch._params[paramOffset + 1]._uint]; GLenum indexType = _elementTypeToGLType[_input._indexBufferType]; @@ -423,6 +415,15 @@ void GLBackend::do_runLambda(Batch& batch, size_t paramOffset) { f(); } +void GLBackend::do_startNamedCall(Batch& batch, size_t paramOffset) { + batch._currentNamedCall = batch._names.get(batch._params[paramOffset]._uint); + _currentDraw = -1; +} + +void GLBackend::do_stopNamedCall(Batch& batch, size_t paramOffset) { + batch._currentNamedCall.clear(); +} + void GLBackend::resetStages() { resetInputStage(); resetPipelineStage(); diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index 400c9f08f8..7f37a73c57 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -320,42 +320,38 @@ protected: void killTransform(); // Synchronize the state cache of this Backend with the actual real state of the GL Context void syncTransformStateCache(); - void updateTransform() const; + void updateTransform(const Batch& batch); void resetTransformStage(); struct TransformStageState { - using TransformObjects = std::vector; using TransformCameras = std::vector; - TransformObject _object; TransformCamera _camera; - TransformObjects _objects; TransformCameras _cameras; - size_t _cameraUboSize{ 0 }; - size_t _objectUboSize{ 0 }; - GLuint _objectBuffer{ 0 }; - GLuint _cameraBuffer{ 0 }; - Transform _model; + mutable std::map _drawCallInfoOffsets; + + GLuint _objectBuffer { 0 }; + GLuint _cameraBuffer { 0 }; + GLuint _drawCallInfoBuffer { 0 }; + GLuint _objectBufferTexture { 0 }; + size_t _cameraUboSize { 0 }; Transform _view; Mat4 _projection; - Vec4i _viewport{ 0, 0, 1, 1 }; - Vec2 _depthRange{ 0.0f, 1.0f }; - bool _invalidModel{true}; - bool _invalidView{false}; - bool _invalidProj{false}; - bool _invalidViewport{ false }; + Vec4i _viewport { 0, 0, 1, 1 }; + Vec2 _depthRange { 0.0f, 1.0f }; + bool _invalidView { false }; + bool _invalidProj { false }; + bool _invalidViewport { false }; using Pair = std::pair; using List = std::list; List _cameraOffsets; - List _objectOffsets; - mutable List::const_iterator _objectsItr; mutable List::const_iterator _camerasItr; void preUpdate(size_t commandIndex, const StereoState& stereo); void update(size_t commandIndex, const StereoState& stereo) const; - void transfer() const; + void transfer(const Batch& batch) const; } _transform; int32_t _uboAlignment{ 0 }; @@ -465,6 +461,9 @@ protected: void do_runLambda(Batch& batch, size_t paramOffset); + void do_startNamedCall(Batch& batch, size_t paramOffset); + void do_stopNamedCall(Batch& batch, size_t paramOffset); + void resetStages(); // TODO: As long as we have gl calls explicitely issued from interface @@ -486,6 +485,8 @@ protected: void do_pushProfileRange(Batch& batch, size_t paramOffset); void do_popProfileRange(Batch& batch, size_t paramOffset); + + int _currentDraw { -1 }; typedef void (GLBackend::*CommandCall)(Batch&, size_t); static CommandCall _commandCalls[Batch::NUM_COMMANDS]; diff --git a/libraries/gpu/src/gpu/GLBackendShader.cpp b/libraries/gpu/src/gpu/GLBackendShader.cpp index 19fa94524e..ca9c014c00 100755 --- a/libraries/gpu/src/gpu/GLBackendShader.cpp +++ b/libraries/gpu/src/gpu/GLBackendShader.cpp @@ -75,9 +75,9 @@ void makeBindings(GLBackend::GLShader* shader) { glBindAttribLocation(glprogram, gpu::Stream::SKIN_CLUSTER_WEIGHT, "inSkinClusterWeight"); } - loc = glGetAttribLocation(glprogram, "inInstanceTransform"); - if (loc >= 0 && loc != gpu::Stream::INSTANCE_XFM) { - glBindAttribLocation(glprogram, gpu::Stream::INSTANCE_XFM, "inInstanceTransform"); + loc = glGetAttribLocation(glprogram, "_drawCallInfo"); + if (loc >= 0 && loc != gpu::Stream::DRAW_CALL_INFO) { + glBindAttribLocation(glprogram, gpu::Stream::DRAW_CALL_INFO, "_drawCallInfo"); } // Link again to take into account the assigned attrib location @@ -92,17 +92,27 @@ void makeBindings(GLBackend::GLShader* shader) { // now assign the ubo binding, then DON't relink! //Check for gpu specific uniform slotBindings - loc = glGetUniformBlockIndex(glprogram, "transformObjectBuffer"); +#ifdef GPU_SSBO_DRAW_CALL_INFO + loc = glGetProgramResourceIndex(glprogram, GL_SHADER_STORAGE_BLOCK, "transformObjectBuffer"); if (loc >= 0) { - glUniformBlockBinding(glprogram, loc, gpu::TRANSFORM_OBJECT_SLOT); + glShaderStorageBlockBinding(glprogram, loc, gpu::TRANSFORM_OBJECT_SLOT); shader->_transformObjectSlot = gpu::TRANSFORM_OBJECT_SLOT; } +#else + loc = glGetUniformLocation(glprogram, "transformObjectBuffer"); + if (loc >= 0) { + glProgramUniform1i(glprogram, loc, gpu::TRANSFORM_OBJECT_SLOT); + shader->_transformObjectSlot = gpu::TRANSFORM_OBJECT_SLOT; + } +#endif loc = glGetUniformBlockIndex(glprogram, "transformCameraBuffer"); if (loc >= 0) { glUniformBlockBinding(glprogram, loc, gpu::TRANSFORM_CAMERA_SLOT); shader->_transformCameraSlot = gpu::TRANSFORM_CAMERA_SLOT; } + + (void)CHECK_GL_ERROR(); } GLBackend::GLShader* compileShader(const Shader& shader) { diff --git a/libraries/gpu/src/gpu/GLBackendTransform.cpp b/libraries/gpu/src/gpu/GLBackendTransform.cpp index 9bfd258833..d5bcfa3321 100755 --- a/libraries/gpu/src/gpu/GLBackendTransform.cpp +++ b/libraries/gpu/src/gpu/GLBackendTransform.cpp @@ -16,8 +16,6 @@ using namespace gpu; // Transform Stage void GLBackend::do_setModelTransform(Batch& batch, size_t paramOffset) { - _transform._model = batch._transforms.get(batch._params[paramOffset]._uint); - _transform._invalidModel = true; } void GLBackend::do_setViewTransform(Batch& batch, size_t paramOffset) { @@ -63,26 +61,29 @@ void GLBackend::do_setDepthRangeTransform(Batch& batch, size_t paramOffset) { void GLBackend::initTransform() { glGenBuffers(1, &_transform._objectBuffer); glGenBuffers(1, &_transform._cameraBuffer); + glGenBuffers(1, &_transform._drawCallInfoBuffer); +#ifndef GPU_SSBO_DRAW_CALL_INFO + glGenTextures(1, &_transform._objectBufferTexture); +#endif size_t cameraSize = sizeof(TransformCamera); while (_transform._cameraUboSize < cameraSize) { _transform._cameraUboSize += _uboAlignment; } - size_t objectSize = sizeof(TransformObject); - while (_transform._objectUboSize < objectSize) { - _transform._objectUboSize += _uboAlignment; - } } void GLBackend::killTransform() { glDeleteBuffers(1, &_transform._objectBuffer); glDeleteBuffers(1, &_transform._cameraBuffer); + glDeleteBuffers(1, &_transform._drawCallInfoBuffer); +#ifndef GPU_SSBO_DRAW_CALL_INFO + glDeleteTextures(1, &_transform._objectBufferTexture); +#endif } void GLBackend::syncTransformStateCache() { _transform._invalidViewport = true; _transform._invalidProj = true; _transform._invalidView = true; - _transform._invalidModel = true; glGetIntegerv(GL_VIEWPORT, (GLint*) &_transform._viewport); @@ -91,7 +92,6 @@ void GLBackend::syncTransformStateCache() { Mat4 modelView; auto modelViewInv = glm::inverse(modelView); _transform._view.evalFromRawMatrix(modelViewInv); - _transform._model.setIdentity(); } void GLBackend::TransformStageState::preUpdate(size_t commandIndex, const StereoState& stereo) { @@ -108,16 +108,6 @@ void GLBackend::TransformStageState::preUpdate(size_t commandIndex, const Stereo _view.getInverseMatrix(_camera._view); } - if (_invalidModel) { - _model.getMatrix(_object._model); - - // FIXME - we don't want to be using glm::inverse() here but it fixes the flickering issue we are - // seeing with planky blocks in toybox. Our implementation of getInverseMatrix() is buggy in cases - // of non-uniform scale. We need to fix that. In the mean time, glm::inverse() works. - //_model.getInverseMatrix(_object._modelInverse); - _object._modelInverse = glm::inverse(_object._model); - } - if (_invalidView || _invalidProj || _invalidViewport) { size_t offset = _cameraUboSize * _cameras.size(); if (stereo._enable) { @@ -131,56 +121,68 @@ void GLBackend::TransformStageState::preUpdate(size_t commandIndex, const Stereo } } - if (_invalidModel) { - size_t offset = _objectUboSize * _objects.size(); - _objectOffsets.push_back(TransformStageState::Pair(commandIndex, offset)); - _objects.push_back(_object); - } - // Flags are clean - _invalidView = _invalidProj = _invalidModel = _invalidViewport = false; + _invalidView = _invalidProj = _invalidViewport = false; } -void GLBackend::TransformStageState::transfer() const { +void GLBackend::TransformStageState::transfer(const Batch& batch) const { // FIXME not thread safe static std::vector bufferData; if (!_cameras.empty()) { - glBindBuffer(GL_UNIFORM_BUFFER, _cameraBuffer); bufferData.resize(_cameraUboSize * _cameras.size()); for (size_t i = 0; i < _cameras.size(); ++i) { memcpy(bufferData.data() + (_cameraUboSize * i), &_cameras[i], sizeof(TransformCamera)); } + glBindBuffer(GL_UNIFORM_BUFFER, _cameraBuffer); glBufferData(GL_UNIFORM_BUFFER, bufferData.size(), bufferData.data(), GL_DYNAMIC_DRAW); - } - - if (!_objects.empty()) { - glBindBuffer(GL_UNIFORM_BUFFER, _objectBuffer); - bufferData.resize(_objectUboSize * _objects.size()); - for (size_t i = 0; i < _objects.size(); ++i) { - memcpy(bufferData.data() + (_objectUboSize * i), &_objects[i], sizeof(TransformObject)); - } - glBufferData(GL_UNIFORM_BUFFER, bufferData.size(), bufferData.data(), GL_DYNAMIC_DRAW); - } - - if (!_cameras.empty() || !_objects.empty()) { glBindBuffer(GL_UNIFORM_BUFFER, 0); } + + if (!batch._objects.empty()) { + auto byteSize = batch._objects.size() * sizeof(Batch::TransformObject); + bufferData.resize(byteSize); + memcpy(bufferData.data(), batch._objects.data(), byteSize); + +#ifdef GPU_SSBO_DRAW_CALL_INFO + glBindBuffer(GL_SHADER_STORAGE_BUFFER, _objectBuffer); + glBufferData(GL_SHADER_STORAGE_BUFFER, bufferData.size(), bufferData.data(), GL_DYNAMIC_DRAW); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); +#else + glBindBuffer(GL_TEXTURE_BUFFER, _objectBuffer); + glBufferData(GL_TEXTURE_BUFFER, bufferData.size(), bufferData.data(), GL_DYNAMIC_DRAW); + glBindBuffer(GL_TEXTURE_BUFFER, 0); +#endif + } + + if (!batch._namedData.empty()) { + bufferData.clear(); + for (auto& data : batch._namedData) { + auto currentSize = bufferData.size(); + auto bytesToCopy = data.second.drawCallInfos.size() * sizeof(Batch::DrawCallInfo); + bufferData.resize(currentSize + bytesToCopy); + memcpy(bufferData.data() + currentSize, data.second.drawCallInfos.data(), bytesToCopy); + _drawCallInfoOffsets[data.first] = (GLvoid*)currentSize; + } + + glBindBuffer(GL_ARRAY_BUFFER, _drawCallInfoBuffer); + glBufferData(GL_ARRAY_BUFFER, bufferData.size(), bufferData.data(), GL_DYNAMIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + +#ifdef GPU_SSBO_DRAW_CALL_INFO + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, TRANSFORM_OBJECT_SLOT, _objectBuffer); +#else + glActiveTexture(GL_TEXTURE0 + TRANSFORM_OBJECT_SLOT); + glBindTexture(GL_TEXTURE_BUFFER, _objectBufferTexture); + glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, _objectBuffer); +#endif + CHECK_GL_ERROR(); } void GLBackend::TransformStageState::update(size_t commandIndex, const StereoState& stereo) const { static const size_t INVALID_OFFSET = (size_t)-1; size_t offset = INVALID_OFFSET; - while ((_objectsItr != _objectOffsets.end()) && (commandIndex >= (*_objectsItr).first)) { - offset = (*_objectsItr).second; - ++_objectsItr; - } - if (offset != INVALID_OFFSET) { - glBindBufferRange(GL_UNIFORM_BUFFER, TRANSFORM_OBJECT_SLOT, - _objectBuffer, offset, sizeof(Backend::TransformObject)); - } - - offset = INVALID_OFFSET; while ((_camerasItr != _cameraOffsets.end()) && (commandIndex >= (*_camerasItr).first)) { offset = (*_camerasItr).second; ++_camerasItr; @@ -191,14 +193,29 @@ void GLBackend::TransformStageState::update(size_t commandIndex, const StereoSta offset += _cameraUboSize; } glBindBufferRange(GL_UNIFORM_BUFFER, TRANSFORM_CAMERA_SLOT, - _cameraBuffer, offset, sizeof(Backend::TransformCamera)); + _cameraBuffer, offset, sizeof(Backend::TransformCamera)); } (void)CHECK_GL_ERROR(); } -void GLBackend::updateTransform() const { +void GLBackend::updateTransform(const Batch& batch) { _transform.update(_commandIndex, _stereo); + + auto& drawCallInfoBuffer = batch.getDrawCallInfoBuffer(); + if (batch._currentNamedCall.empty()) { + auto& drawCallInfo = drawCallInfoBuffer[_currentDraw]; + glDisableVertexAttribArray(gpu::Stream::DRAW_CALL_INFO); // Make sure attrib array is disabled + glVertexAttribI2i(gpu::Stream::DRAW_CALL_INFO, drawCallInfo.index, drawCallInfo.unused); + } else { + glEnableVertexAttribArray(gpu::Stream::DRAW_CALL_INFO); // Make sure attrib array is enabled + glBindBuffer(GL_ARRAY_BUFFER, _transform._drawCallInfoBuffer); + glVertexAttribIPointer(gpu::Stream::DRAW_CALL_INFO, 2, GL_UNSIGNED_SHORT, 0, + _transform._drawCallInfoOffsets[batch._currentNamedCall]); + glVertexAttribDivisor(gpu::Stream::DRAW_CALL_INFO, 1); + } + + (void)CHECK_GL_ERROR(); } void GLBackend::resetTransformStage() { diff --git a/libraries/gpu/src/gpu/Inputs.slh b/libraries/gpu/src/gpu/Inputs.slh index 99e1e1d6d5..ce5e4227eb 100644 --- a/libraries/gpu/src/gpu/Inputs.slh +++ b/libraries/gpu/src/gpu/Inputs.slh @@ -10,13 +10,12 @@ !> <@if not GPU_INPUTS_SLH@> <@def GPU_INPUTS_SLH@> -in vec4 inPosition; -in vec4 inNormal; -in vec4 inColor; -in vec4 inTexCoord0; -in vec4 inTangent; -in vec4 inSkinClusterIndex; -in vec4 inSkinClusterWeight; -in vec4 inTexCoord1; -in mat4 inInstanceTransform; +layout(location = 0) in vec4 inPosition; +layout(location = 1) in vec4 inNormal; +layout(location = 2) in vec4 inColor; +layout(location = 3) in vec4 inTexCoord0; +layout(location = 4) in vec4 inTangent; +layout(location = 5) in vec4 inSkinClusterIndex; +layout(location = 6) in vec4 inSkinClusterWeight; +layout(location = 7) in vec4 inTexCoord1; <@endif@> diff --git a/libraries/gpu/src/gpu/Stream.cpp b/libraries/gpu/src/gpu/Stream.cpp index ff765f3250..90f2327fc8 100644 --- a/libraries/gpu/src/gpu/Stream.cpp +++ b/libraries/gpu/src/gpu/Stream.cpp @@ -34,14 +34,7 @@ const ElementArray& getDefaultElements() { //SKIN_CLUSTER_WEIGHT = 6, Element::VEC4F_XYZW, //TEXCOORD1 = 7, - Element::VEC2F_UV, - //INSTANCE_SCALE = 8, - Element::VEC3F_XYZ, - //INSTANCE_TRANSLATE = 9, - Element::VEC3F_XYZ, - //INSTANCE_XFM = 10, - // FIXME make a matrix element - Element::VEC4F_XYZW + Element::VEC2F_UV }}; return defaultElements; } diff --git a/libraries/gpu/src/gpu/Stream.h b/libraries/gpu/src/gpu/Stream.h index 8c0833dd42..c8d9335bf7 100644 --- a/libraries/gpu/src/gpu/Stream.h +++ b/libraries/gpu/src/gpu/Stream.h @@ -37,12 +37,10 @@ public: SKIN_CLUSTER_INDEX = 5, SKIN_CLUSTER_WEIGHT = 6, TEXCOORD1 = 7, - INSTANCE_SCALE = 8, - INSTANCE_TRANSLATE = 9, - INSTANCE_XFM = 10, + NUM_INPUT_SLOTS = TEXCOORD1 + 1, - // Instance XFM is a mat4, and as such takes up 4 slots - NUM_INPUT_SLOTS = INSTANCE_XFM + 4, + + DRAW_CALL_INFO = 15, // Reserve last input slot for draw call infos }; typedef uint8 Slot; diff --git a/libraries/gpu/src/gpu/Transform.slh b/libraries/gpu/src/gpu/Transform.slh index 26ea9784be..ea5ee06a7b 100644 --- a/libraries/gpu/src/gpu/Transform.slh +++ b/libraries/gpu/src/gpu/Transform.slh @@ -10,13 +10,8 @@ <@if not GPU_TRANSFORM_STATE_SLH@> <@def GPU_TRANSFORM_STATE_SLH@> -<@func declareStandardTransform()@> -struct TransformObject { - mat4 _model; - mat4 _modelInverse; -}; - -struct TransformCamera { +<@func declareStandardCameraTransform()@> +struct TransformCamera { mat4 _view; mat4 _viewInverse; mat4 _projectionViewUntranslated; @@ -25,13 +20,6 @@ struct TransformCamera { vec4 _viewport; }; -layout(std140) uniform transformObjectBuffer { - TransformObject _object; -}; -TransformObject getTransformObject() { - return _object; -} - layout(std140) uniform transformCameraBuffer { TransformCamera _camera; }; @@ -40,6 +28,50 @@ TransformCamera getTransformCamera() { } <@endfunc@> + +<@func declareStandardObjectTransform()@> +struct TransformObject { + mat4 _model; + mat4 _modelInverse; +}; + +layout(location=15) in ivec2 _drawCallInfo; + +<@if FALSE @> +// Disable SSBOs for now +layout(std140) buffer transformObjectBuffer { + TransformObject _object[]; +}; +TransformObject getTransformObject() { + return _object[_drawCallInfo.x]; +} +<@else@> +uniform samplerBuffer transformObjectBuffer; + +TransformObject getTransformObject() { + int offset = 8 * _drawCallInfo.x; + TransformObject object; + object._model[0] = texelFetch(transformObjectBuffer, offset); + object._model[1] = texelFetch(transformObjectBuffer, offset + 1); + object._model[2] = texelFetch(transformObjectBuffer, offset + 2); + object._model[3] = texelFetch(transformObjectBuffer, offset + 3); + + object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4); + object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5); + object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6); + object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7); + + return object; +} +<@endif@> +<@endfunc@> + + +<@func declareStandardTransform()@> +<$declareStandardObjectTransform()$> +<$declareStandardCameraTransform()$> +<@endfunc@> + <@func transformCameraViewport(cameraTransform, viewport)@> <$viewport$> = <$cameraTransform$>._viewport; <@endfunc@> @@ -53,15 +85,6 @@ TransformCamera getTransformCamera() { } <@endfunc@> -<@func transformInstancedModelToClipPos(cameraTransform, objectTransform, modelPos, clipPos)@> - - { // transformModelToClipPos - vec4 _eyepos = (inInstanceTransform * <$modelPos$>) + vec4(-<$modelPos$>.w * <$cameraTransform$>._viewInverse[3].xyz, 0.0); - <$clipPos$> = <$cameraTransform$>._projectionViewUntranslated * _eyepos; - } -<@endfunc@> - <@func $transformModelToEyeAndClipPos(cameraTransform, objectTransform, modelPos, eyePos, clipPos)@> @@ -74,30 +97,12 @@ TransformCamera getTransformCamera() { } <@endfunc@> -<@func $transformInstancedModelToEyeAndClipPos(cameraTransform, objectTransform, modelPos, eyePos, clipPos)@> - - { // transformModelToClipPos - vec4 _worldpos = (inInstanceTransform * <$modelPos$>); - <$eyePos$> = (<$cameraTransform$>._view * _worldpos); - vec4 _eyepos =(inInstanceTransform * <$modelPos$>) + vec4(-<$modelPos$>.w * <$cameraTransform$>._viewInverse[3].xyz, 0.0); - <$clipPos$> = <$cameraTransform$>._projectionViewUntranslated * _eyepos; - // <$eyePos$> = (<$cameraTransform$>._projectionInverse * <$clipPos$>); - } -<@endfunc@> - <@func transformModelToWorldPos(objectTransform, modelPos, worldPos)@> { // transformModelToWorldPos <$worldPos$> = (<$objectTransform$>._model * <$modelPos$>); } <@endfunc@> -<@func transformInstancedModelToWorldPos(objectTransform, modelPos, worldPos)@> - { // transformModelToWorldPos - <$worldPos$> = (inInstanceTransform * <$modelPos$>); - } -<@endfunc@> - <@func transformModelToEyeDir(cameraTransform, objectTransform, modelDir, eyeDir)@> { // transformModelToEyeDir vec3 mr0 = vec3(<$objectTransform$>._modelInverse[0].x, <$objectTransform$>._modelInverse[1].x, <$objectTransform$>._modelInverse[2].x); @@ -112,21 +117,6 @@ TransformCamera getTransformCamera() { } <@endfunc@> -<@func transformInstancedModelToEyeDir(cameraTransform, objectTransform, modelDir, eyeDir)@> - { // transformModelToEyeDir - mat4 modelInverse = inverse(inInstanceTransform); - vec3 mr0 = vec3(modelInverse[0].x, modelInverse[1].x, modelInverse[2].x); - vec3 mr1 = vec3(modelInverse[0].y, modelInverse[1].y, modelInverse[2].y); - vec3 mr2 = vec3(modelInverse[0].z, modelInverse[1].z, modelInverse[2].z); - - vec3 mvc0 = vec3(dot(<$cameraTransform$>._viewInverse[0].xyz, mr0), dot(<$cameraTransform$>._viewInverse[0].xyz, mr1), dot(<$cameraTransform$>._viewInverse[0].xyz, mr2)); - vec3 mvc1 = vec3(dot(<$cameraTransform$>._viewInverse[1].xyz, mr0), dot(<$cameraTransform$>._viewInverse[1].xyz, mr1), dot(<$cameraTransform$>._viewInverse[1].xyz, mr2)); - vec3 mvc2 = vec3(dot(<$cameraTransform$>._viewInverse[2].xyz, mr0), dot(<$cameraTransform$>._viewInverse[2].xyz, mr1), dot(<$cameraTransform$>._viewInverse[2].xyz, mr2)); - - <$eyeDir$> = vec3(dot(mvc0, <$modelDir$>), dot(mvc1, <$modelDir$>), dot(mvc2, <$modelDir$>)); - } -<@endfunc@> - <@func transformEyeToWorldDir(cameraTransform, eyeDir, worldDir)@> { // transformEyeToWorldDir <$worldDir$> = vec3(<$cameraTransform$>._viewInverse * vec4(<$eyeDir$>.xyz, 0.0)); diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 35773e8748..aa82232524 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -43,7 +43,6 @@ static const int VERTICES_PER_TRIANGLE = 3; static const gpu::Element POSITION_ELEMENT{ gpu::VEC3, gpu::FLOAT, gpu::XYZ }; static const gpu::Element NORMAL_ELEMENT{ gpu::VEC3, gpu::FLOAT, gpu::XYZ }; static const gpu::Element COLOR_ELEMENT{ gpu::VEC4, gpu::NUINT8, gpu::RGBA }; -static const gpu::Element TRANSFORM_ELEMENT{ gpu::MAT4, gpu::FLOAT, gpu::XYZW }; static gpu::Stream::FormatPointer SOLID_STREAM_FORMAT; static gpu::Stream::FormatPointer INSTANCED_SOLID_STREAM_FORMAT; @@ -491,7 +490,6 @@ gpu::Stream::FormatPointer& getInstancedSolidStreamFormat() { INSTANCED_SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, POSITION_ELEMENT); INSTANCED_SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, NORMAL_ELEMENT); INSTANCED_SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::COLOR, gpu::Stream::COLOR, COLOR_ELEMENT, 0, gpu::Stream::PER_INSTANCE); - INSTANCED_SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::INSTANCE_XFM, gpu::Stream::INSTANCE_XFM, TRANSFORM_ELEMENT, 0, gpu::Stream::PER_INSTANCE); } return INSTANCED_SOLID_STREAM_FORMAT; } @@ -511,11 +509,9 @@ GeometryCache::~GeometryCache() { #endif //def WANT_DEBUG } -void setupBatchInstance(gpu::Batch& batch, gpu::BufferPointer transformBuffer, gpu::BufferPointer colorBuffer) { +void setupBatchInstance(gpu::Batch& batch, gpu::BufferPointer colorBuffer) { gpu::BufferView colorView(colorBuffer, COLOR_ELEMENT); batch.setInputBuffer(gpu::Stream::COLOR, colorView); - gpu::BufferView instanceXfmView(transformBuffer, 0, transformBuffer->getSize(), TRANSFORM_ELEMENT); - batch.setInputBuffer(gpu::Stream::INSTANCE_XFM, instanceXfmView); } void GeometryCache::renderShape(gpu::Batch& batch, Shape shape) { @@ -528,24 +524,24 @@ void GeometryCache::renderWireShape(gpu::Batch& batch, Shape shape) { _shapes[shape].drawWire(batch); } -void GeometryCache::renderShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& transformBuffer, gpu::BufferPointer& colorBuffer) { +void GeometryCache::renderShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer) { batch.setInputFormat(getInstancedSolidStreamFormat()); - setupBatchInstance(batch, transformBuffer, colorBuffer); + setupBatchInstance(batch, colorBuffer); _shapes[shape].drawInstances(batch, count); } -void GeometryCache::renderWireShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& transformBuffer, gpu::BufferPointer& colorBuffer) { +void GeometryCache::renderWireShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer) { batch.setInputFormat(getInstancedSolidStreamFormat()); - setupBatchInstance(batch, transformBuffer, colorBuffer); + setupBatchInstance(batch, colorBuffer); _shapes[shape].drawWireInstances(batch, count); } -void GeometryCache::renderCubeInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer transformBuffer, gpu::BufferPointer colorBuffer) { - renderShapeInstances(batch, Cube, count, transformBuffer, colorBuffer); +void GeometryCache::renderCubeInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer colorBuffer) { + renderShapeInstances(batch, Cube, count, colorBuffer); } -void GeometryCache::renderWireCubeInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer transformBuffer, gpu::BufferPointer colorBuffer) { - renderWireShapeInstances(batch, Cube, count, transformBuffer, colorBuffer); +void GeometryCache::renderWireCubeInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer colorBuffer) { + renderWireShapeInstances(batch, Cube, count, colorBuffer); } void GeometryCache::renderCube(gpu::Batch& batch) { @@ -556,8 +552,8 @@ void GeometryCache::renderWireCube(gpu::Batch& batch) { renderWireShape(batch, Cube); } -void GeometryCache::renderSphereInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer transformBuffer, gpu::BufferPointer colorBuffer) { - renderShapeInstances(batch, Sphere, count, transformBuffer, colorBuffer); +void GeometryCache::renderSphereInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer colorBuffer) { + renderShapeInstances(batch, Sphere, count, colorBuffer); } void GeometryCache::renderSphere(gpu::Batch& batch) { @@ -1854,45 +1850,34 @@ uint32_t toCompactColor(const glm::vec4& color) { return compactColor; } -static const size_t INSTANCE_TRANSFORM_BUFFER = 0; -static const size_t INSTANCE_COLOR_BUFFER = 1; +static const size_t INSTANCE_COLOR_BUFFER = 0; template -void renderInstances(const std::string& name, gpu::Batch& batch, const Transform& transform, const glm::vec4& color, F f) { +void renderInstances(const std::string& name, gpu::Batch& batch, const glm::vec4& color, F f) { { - gpu::BufferPointer instanceTransformBuffer = batch.getNamedBuffer(name, INSTANCE_TRANSFORM_BUFFER); - glm::mat4 glmTransform; - instanceTransformBuffer->append(transform.getMatrix(glmTransform)); - gpu::BufferPointer instanceColorBuffer = batch.getNamedBuffer(name, INSTANCE_COLOR_BUFFER); auto compactColor = toCompactColor(color); instanceColorBuffer->append(compactColor); } batch.setupNamedCalls(name, [f](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) { - auto pipeline = DependencyManager::get()->bindSimpleProgram(batch); - auto location = pipeline->getProgram()->getUniforms().findLocation("Instanced"); - - batch._glUniform1i(location, 1); + DependencyManager::get()->bindSimpleProgram(batch); f(batch, data); - batch._glUniform1i(location, 0); }); } -void GeometryCache::renderSolidSphereInstance(gpu::Batch& batch, const Transform& transform, const glm::vec4& color) { +void GeometryCache::renderSolidSphereInstance(gpu::Batch& batch, const glm::vec4& color) { static const std::string INSTANCE_NAME = __FUNCTION__; - renderInstances(INSTANCE_NAME, batch, transform, color, [](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) { - DependencyManager::get()->renderShapeInstances(batch, GeometryCache::Sphere, data.count, - data.buffers[INSTANCE_TRANSFORM_BUFFER], + renderInstances(INSTANCE_NAME, batch, color, [](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) { + DependencyManager::get()->renderShapeInstances(batch, GeometryCache::Sphere, data.count(), data.buffers[INSTANCE_COLOR_BUFFER]); }); } -void GeometryCache::renderWireSphereInstance(gpu::Batch& batch, const Transform& transform, const glm::vec4& color) { +void GeometryCache::renderWireSphereInstance(gpu::Batch& batch, const glm::vec4& color) { static const std::string INSTANCE_NAME = __FUNCTION__; - renderInstances(INSTANCE_NAME, batch, transform, color, [](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) { - DependencyManager::get()->renderWireShapeInstances(batch, GeometryCache::Sphere, data.count, - data.buffers[INSTANCE_TRANSFORM_BUFFER], + renderInstances(INSTANCE_NAME, batch, color, [](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) { + DependencyManager::get()->renderWireShapeInstances(batch, GeometryCache::Sphere, data.count(), data.buffers[INSTANCE_COLOR_BUFFER]); }); } @@ -1901,12 +1886,12 @@ void GeometryCache::renderWireSphereInstance(gpu::Batch& batch, const Transform& // available shape types, both solid and wireframes //#define DEBUG_SHAPES -void GeometryCache::renderSolidCubeInstance(gpu::Batch& batch, const Transform& transform, const glm::vec4& color) { +void GeometryCache::renderSolidCubeInstance(gpu::Batch& batch, const glm::vec4& color) { static const std::string INSTANCE_NAME = __FUNCTION__; #ifdef DEBUG_SHAPES static auto startTime = usecTimestampNow(); - renderInstances(INSTANCE_NAME, batch, transform, color, [](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) { + renderInstances(INSTANCE_NAME, batch, color, [](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) { auto usecs = usecTimestampNow(); usecs -= startTime; @@ -1931,29 +1916,25 @@ void GeometryCache::renderSolidCubeInstance(gpu::Batch& batch, const Transform& // For the first half second for a given shape, show the wireframe, for the second half, show the solid. if (fractionalSeconds > 0.5f) { - DependencyManager::get()->renderShapeInstances(batch, shape, data.count, - data.buffers[INSTANCE_TRANSFORM_BUFFER], + DependencyManager::get()->renderShapeInstances(batch, shape, data.count(), data.buffers[INSTANCE_COLOR_BUFFER]); } else { - DependencyManager::get()->renderWireShapeInstances(batch, shape, data.count, - data.buffers[INSTANCE_TRANSFORM_BUFFER], + DependencyManager::get()->renderWireShapeInstances(batch, shape, data.count(), data.buffers[INSTANCE_COLOR_BUFFER]); } }); #else - renderInstances(INSTANCE_NAME, batch, transform, color, [](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) { - DependencyManager::get()->renderCubeInstances(batch, data.count, - data.buffers[INSTANCE_TRANSFORM_BUFFER], + renderInstances(INSTANCE_NAME, batch, color, [](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) { + DependencyManager::get()->renderCubeInstances(batch, data.count(), data.buffers[INSTANCE_COLOR_BUFFER]); }); #endif } -void GeometryCache::renderWireCubeInstance(gpu::Batch& batch, const Transform& transform, const glm::vec4& color) { +void GeometryCache::renderWireCubeInstance(gpu::Batch& batch, const glm::vec4& color) { static const std::string INSTANCE_NAME = __FUNCTION__; - renderInstances(INSTANCE_NAME, batch, transform, color, [](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) { - DependencyManager::get()->renderWireCubeInstances(batch, data.count, - data.buffers[INSTANCE_TRANSFORM_BUFFER], + renderInstances(INSTANCE_NAME, batch, color, [](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) { + DependencyManager::get()->renderWireCubeInstances(batch, data.count(), data.buffers[INSTANCE_COLOR_BUFFER]); }); } diff --git a/libraries/render-utils/src/GeometryCache.h b/libraries/render-utils/src/GeometryCache.h index 90ba3be978..81b8dfb325 100644 --- a/libraries/render-utils/src/GeometryCache.h +++ b/libraries/render-utils/src/GeometryCache.h @@ -154,41 +154,41 @@ public: gpu::PipelinePointer bindSimpleProgram(gpu::Batch& batch, bool textured = false, bool culled = true, bool emissive = false, bool depthBias = false); - void renderSolidSphereInstance(gpu::Batch& batch, const Transform& xfm, const glm::vec4& color); - void renderSolidSphereInstance(gpu::Batch& batch, const Transform& xfm, const glm::vec3& color) { - renderSolidSphereInstance(batch, xfm, glm::vec4(color, 1.0)); + void renderSolidSphereInstance(gpu::Batch& batch, const glm::vec4& color); + void renderSolidSphereInstance(gpu::Batch& batch, const glm::vec3& color) { + renderSolidSphereInstance(batch, glm::vec4(color, 1.0)); } - void renderWireSphereInstance(gpu::Batch& batch, const Transform& xfm, const glm::vec4& color); - void renderWireSphereInstance(gpu::Batch& batch, const Transform& xfm, const glm::vec3& color) { - renderWireSphereInstance(batch, xfm, glm::vec4(color, 1.0)); + void renderWireSphereInstance(gpu::Batch& batch, const glm::vec4& color); + void renderWireSphereInstance(gpu::Batch& batch, const glm::vec3& color) { + renderWireSphereInstance(batch, glm::vec4(color, 1.0)); } - void renderSolidCubeInstance(gpu::Batch& batch, const Transform& xfm, const glm::vec4& color); - void renderSolidCubeInstance(gpu::Batch& batch, const Transform& xfm, const glm::vec3& color) { - renderSolidCubeInstance(batch, xfm, glm::vec4(color, 1.0)); + void renderSolidCubeInstance(gpu::Batch& batch, const glm::vec4& color); + void renderSolidCubeInstance(gpu::Batch& batch, const glm::vec3& color) { + renderSolidCubeInstance(batch, glm::vec4(color, 1.0)); } - void renderWireCubeInstance(gpu::Batch& batch, const Transform& xfm, const glm::vec4& color); - void renderWireCubeInstance(gpu::Batch& batch, const Transform& xfm, const glm::vec3& color) { - renderWireCubeInstance(batch, xfm, glm::vec4(color, 1.0)); + void renderWireCubeInstance(gpu::Batch& batch, const glm::vec4& color); + void renderWireCubeInstance(gpu::Batch& batch, const glm::vec3& color) { + renderWireCubeInstance(batch, glm::vec4(color, 1.0)); } - void renderShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& transformBuffer, gpu::BufferPointer& colorBuffer); - void renderWireShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& transformBuffer, gpu::BufferPointer& colorBuffer); + void renderShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer); + void renderWireShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer); void renderShape(gpu::Batch& batch, Shape shape); void renderWireShape(gpu::Batch& batch, Shape shape); size_t getShapeTriangleCount(Shape shape); - void renderCubeInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer transformBuffer, gpu::BufferPointer colorBuffer); - void renderWireCubeInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer transformBuffer, gpu::BufferPointer colorBuffer); + void renderCubeInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer colorBuffer); + void renderWireCubeInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer colorBuffer); void renderCube(gpu::Batch& batch); void renderWireCube(gpu::Batch& batch); size_t getCubeTriangleCount(); - void renderSphereInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer transformBuffer, gpu::BufferPointer colorBuffer); - void renderWireSphereInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer transformBuffer, gpu::BufferPointer colorBuffer); + void renderSphereInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer colorBuffer); + void renderWireSphereInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer colorBuffer); void renderSphere(gpu::Batch& batch); void renderWireSphere(gpu::Batch& batch); size_t getSphereTriangleCount(); diff --git a/libraries/render-utils/src/model_translucent.slf b/libraries/render-utils/src/model_translucent.slf index 12e841399b..1a17258408 100755 --- a/libraries/render-utils/src/model_translucent.slf +++ b/libraries/render-utils/src/model_translucent.slf @@ -17,7 +17,7 @@ <@include DeferredLighting.slh@> <@include gpu/Transform.slh@> -<$declareStandardTransform()$> +<$declareStandardCameraTransform()$> // Everything about light diff --git a/libraries/render-utils/src/simple.slv b/libraries/render-utils/src/simple.slv index 59b16cf0e5..46127d6752 100644 --- a/libraries/render-utils/src/simple.slv +++ b/libraries/render-utils/src/simple.slv @@ -17,9 +17,7 @@ <@include gpu/Transform.slh@> <$declareStandardTransform()$> -uniform bool Instanced = false; // the interpolated normal - out vec3 _normal; out vec3 _modelNormal; out vec3 _color; @@ -35,11 +33,6 @@ void main(void) { // standard transform TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); - if (Instanced) { - <$transformInstancedModelToClipPos(cam, obj, inPosition, gl_Position)$> - <$transformInstancedModelToEyeDir(cam, obj, inNormal.xyz, _normal)$> - } else { - <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$> - <$transformModelToEyeDir(cam, obj, inNormal.xyz, _normal)$> - } + <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$> + <$transformModelToEyeDir(cam, obj, inNormal.xyz, _normal)$> } \ No newline at end of file diff --git a/tests/gpu-test/src/main.cpp b/tests/gpu-test/src/main.cpp index de5aa877eb..b1ca3d0448 100644 --- a/tests/gpu-test/src/main.cpp +++ b/tests/gpu-test/src/main.cpp @@ -124,7 +124,6 @@ class QTestWindow : public QWindow { glm::mat4 _projectionMatrix; RateCounter fps; QTime _time; - int _instanceLocation{ -1 }; protected: void renderText(); @@ -164,7 +163,6 @@ public: state->setMultisampleEnable(true); state->setDepthTest(gpu::State::DepthTest { true }); _pipeline = gpu::Pipeline::create(shader, state); - _instanceLocation = _pipeline->getProgram()->getUniforms().findLocation("Instanced"); // Clear screen gpu::Batch batch; @@ -218,16 +216,16 @@ public: static const std::string GRID_INSTANCE = "Grid"; static auto compactColor1 = toCompactColor(vec4{ 0.35f, 0.25f, 0.15f, 1.0f }); static auto compactColor2 = toCompactColor(vec4{ 0.15f, 0.25f, 0.35f, 1.0f }); - static gpu::BufferPointer transformBuffer; + static std::vector transforms; static gpu::BufferPointer colorBuffer; - if (!transformBuffer) { - transformBuffer = std::make_shared(); + if (!transforms.empty()) { + transforms.reserve(200); colorBuffer = std::make_shared(); for (int i = 0; i < 100; ++i) { { glm::mat4 transform = glm::translate(mat4(), vec3(0, -1, -50 + i)); transform = glm::scale(transform, vec3(100, 1, 1)); - transformBuffer->append(transform); + transforms.push_back(transform); colorBuffer->append(compactColor1); } @@ -235,20 +233,20 @@ public: glm::mat4 transform = glm::mat4_cast(quat(vec3(0, PI / 2.0f, 0))); transform = glm::translate(transform, vec3(0, -1, -50 + i)); transform = glm::scale(transform, vec3(100, 1, 1)); - transformBuffer->append(transform); + transforms.push_back(transform); colorBuffer->append(compactColor2); } } } - - batch.setupNamedCalls(GRID_INSTANCE, 200, [=](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) { - batch.setViewTransform(camera); - batch.setModelTransform(Transform()); - batch.setPipeline(_pipeline); - batch._glUniform1i(_instanceLocation, 1); - geometryCache->renderWireShapeInstances(batch, GeometryCache::Line, data.count, transformBuffer, colorBuffer); - batch._glUniform1i(_instanceLocation, 0); - }); + + for (auto& transform : transforms) { + batch.setModelTransform(transform); + batch.setupNamedCalls(GRID_INSTANCE, [=](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) { + batch.setViewTransform(camera); + batch.setPipeline(_pipeline); + geometryCache->renderWireShapeInstances(batch, GeometryCache::Line, data.count(), colorBuffer); + }); + } } { @@ -316,14 +314,11 @@ public: batch.setViewTransform(camera); batch.setModelTransform(Transform()); batch.setPipeline(_pipeline); - batch._glUniform1i(_instanceLocation, 1); batch.setInputFormat(getInstancedSolidStreamFormat()); batch.setInputBuffer(gpu::Stream::COLOR, colorView); - batch.setInputBuffer(gpu::Stream::INSTANCE_XFM, instanceXfmView); batch.setIndirectBuffer(indirectBuffer); shapeData.setupBatch(batch); batch.multiDrawIndexedIndirect(TYPE_COUNT, gpu::TRIANGLES); - batch._glUniform1i(_instanceLocation, 0); } #else batch.setViewTransform(camera); diff --git a/tests/gpu-test/src/unlit.slv b/tests/gpu-test/src/unlit.slv index 3271d0ee90..d51d817429 100644 --- a/tests/gpu-test/src/unlit.slv +++ b/tests/gpu-test/src/unlit.slv @@ -19,8 +19,6 @@ <$declareStandardTransform()$> // the interpolated normal -uniform bool Instanced = false; - out vec3 _normal; out vec3 _color; out vec2 _texCoord0; @@ -32,12 +30,7 @@ void main(void) { // standard transform TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); - if (Instanced) { - <$transformInstancedModelToClipPos(cam, obj, inPosition, gl_Position)$> - <$transformInstancedModelToEyeDir(cam, obj, inNormal.xyz, _normal)$> - } else { - <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$> - <$transformModelToEyeDir(cam, obj, inNormal.xyz, _normal)$> - } + <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$> + <$transformModelToEyeDir(cam, obj, inNormal.xyz, _normal)$> _normal = vec3(0.0, 0.0, 1.0); } \ No newline at end of file