Merge pull request #6871 from Atlante45/feat/draw-call-info

Unify normal and named draw paths
This commit is contained in:
samcake 2016-02-01 14:19:15 -08:00
commit 1b52d700a0
29 changed files with 482 additions and 388 deletions

View file

@ -96,26 +96,31 @@ void renderWorldBox(gpu::Batch& batch) {
glm::vec3(HALF_TREE_SCALE, 0.0f, HALF_TREE_SCALE), GREY); 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 // Draw meter markers along the 3 axis to help with measuring things
const float MARKER_DISTANCE = 1.0f; const float MARKER_DISTANCE = 1.0f;
const float MARKER_RADIUS = 0.05f; const float MARKER_RADIUS = 0.05f;
transform = Transform().setScale(MARKER_RADIUS); 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); 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); 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); 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); 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 // Return a random vector of average length 1

View file

@ -456,7 +456,8 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
Transform transform; Transform transform;
transform.setTranslation(position); transform.setTranslation(position);
transform.postScale(INDICATOR_RADIUS); transform.postScale(INDICATOR_RADIUS);
DependencyManager::get<GeometryCache>()->renderSolidSphereInstance(batch, transform, LOOK_AT_INDICATOR_COLOR); batch.setModelTransform(transform);
DependencyManager::get<GeometryCache>()->renderSolidSphereInstance(batch, LOOK_AT_INDICATOR_COLOR);
} }
// If the avatar is looking at me, indicate that they are // If the avatar is looking at me, indicate that they are
@ -484,8 +485,8 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
eyeDiameter = DEFAULT_EYE_DIAMETER; eyeDiameter = DEFAULT_EYE_DIAMETER;
} }
batch.setModelTransform(Transform(transform).postScale(eyeDiameter * getUniformScale() / 2.0f + RADIUS_INCREMENT));
DependencyManager::get<GeometryCache>()->renderSolidSphereInstance(batch, DependencyManager::get<GeometryCache>()->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(); position = getHead()->getRightEyePosition();
@ -494,8 +495,8 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
if (eyeDiameter == 0.0f) { if (eyeDiameter == 0.0f) {
eyeDiameter = DEFAULT_EYE_DIAMETER; eyeDiameter = DEFAULT_EYE_DIAMETER;
} }
batch.setModelTransform(Transform(transform).postScale(eyeDiameter * getUniformScale() / 2.0f + RADIUS_INCREMENT));
DependencyManager::get<GeometryCache>()->renderSolidSphereInstance(batch, DependencyManager::get<GeometryCache>()->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));
} }

View file

@ -60,7 +60,8 @@ void Hand::renderHandTargets(RenderArgs* renderArgs, bool isMine) {
transform.setTranslation(position); transform.setTranslation(position);
transform.setRotation(palm.getRotation()); transform.setRotation(palm.getRotation());
transform.postScale(SPHERE_RADIUS); transform.postScale(SPHERE_RADIUS);
DependencyManager::get<GeometryCache>()->renderSolidSphereInstance(batch, transform, grayColor); batch.setModelTransform(transform);
DependencyManager::get<GeometryCache>()->renderSolidSphereInstance(batch, grayColor);
// draw a green sphere at the old "finger tip" // draw a green sphere at the old "finger tip"
transform = Transform(); transform = Transform();
@ -68,7 +69,8 @@ void Hand::renderHandTargets(RenderArgs* renderArgs, bool isMine) {
transform.setTranslation(position); transform.setTranslation(position);
transform.setRotation(palm.getRotation()); transform.setRotation(palm.getRotation());
transform.postScale(SPHERE_RADIUS); transform.postScale(SPHERE_RADIUS);
DependencyManager::get<GeometryCache>()->renderSolidSphereInstance(batch, transform, greenColor); batch.setModelTransform(transform);
DependencyManager::get<GeometryCache>()->renderSolidSphereInstance(batch, greenColor);
} }
} }

View file

@ -467,5 +467,6 @@ void Head::renderLookatTarget(RenderArgs* renderArgs, glm::vec3 lookatPosition)
const float LOOK_AT_TARGET_RADIUS = 0.075f; const float LOOK_AT_TARGET_RADIUS = 0.075f;
transform.postScale(LOOK_AT_TARGET_RADIUS); transform.postScale(LOOK_AT_TARGET_RADIUS);
const glm::vec4 LOOK_AT_TARGET_COLOR = { 0.8f, 0.0f, 0.0f, 0.75f }; 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);
} }

View file

@ -349,17 +349,15 @@ void SkeletonModel::renderBoundingCollisionShapes(gpu::Batch& batch, float scale
// draw a blue sphere at the capsule top point // draw a blue sphere at the capsule top point
glm::vec3 topPoint = _translation + getRotation() * (scale * (_boundingCapsuleLocalOffset + (0.5f * _boundingCapsuleHeight) * Vectors::UNIT_Y)); glm::vec3 topPoint = _translation + getRotation() * (scale * (_boundingCapsuleLocalOffset + (0.5f * _boundingCapsuleHeight) * Vectors::UNIT_Y));
geometryCache->renderSolidSphereInstance(batch, batch.setModelTransform(Transform().setTranslation(topPoint).postScale(scale * _boundingCapsuleRadius));
Transform().setTranslation(topPoint).postScale(scale * _boundingCapsuleRadius), geometryCache->renderSolidSphereInstance(batch, glm::vec4(0.6f, 0.6f, 0.8f, alpha));
glm::vec4(0.6f, 0.6f, 0.8f, alpha));
// draw a yellow sphere at the capsule bottom point // draw a yellow sphere at the capsule bottom point
glm::vec3 bottomPoint = topPoint - glm::vec3(0.0f, scale * _boundingCapsuleHeight, 0.0f); glm::vec3 bottomPoint = topPoint - glm::vec3(0.0f, scale * _boundingCapsuleHeight, 0.0f);
glm::vec3 axis = topPoint - bottomPoint; glm::vec3 axis = topPoint - bottomPoint;
geometryCache->renderSolidSphereInstance(batch, batch.setModelTransform(Transform().setTranslation(bottomPoint).postScale(scale * _boundingCapsuleRadius));
Transform().setTranslation(bottomPoint).postScale(scale * _boundingCapsuleRadius), geometryCache->renderSolidSphereInstance(batch, glm::vec4(0.8f, 0.8f, 0.6f, alpha));
glm::vec4(0.8f, 0.8f, 0.6f, alpha));
// draw a green cylinder between the two points // draw a green cylinder between the two points
glm::vec3 origin(0.0f); glm::vec3 origin(0.0f);

View file

@ -60,7 +60,8 @@ void Cube3DOverlay::render(RenderArgs* args) {
// } // }
transform.setScale(dimensions); transform.setScale(dimensions);
DependencyManager::get<GeometryCache>()->renderSolidCubeInstance(*batch, transform, cubeColor); batch->setModelTransform(transform);
DependencyManager::get<GeometryCache>()->renderSolidCubeInstance(*batch, cubeColor);
} else { } else {
if (getIsDashedLine()) { if (getIsDashedLine()) {
@ -96,9 +97,9 @@ void Cube3DOverlay::render(RenderArgs* args) {
geometryCache->renderDashedLine(*batch, bottomRightFar, topRightFar, cubeColor); geometryCache->renderDashedLine(*batch, bottomRightFar, topRightFar, cubeColor);
} else { } else {
batch->setModelTransform(Transform());
transform.setScale(dimensions); transform.setScale(dimensions);
DependencyManager::get<GeometryCache>()->renderWireCubeInstance(*batch, transform, cubeColor); batch->setModelTransform(transform);
DependencyManager::get<GeometryCache>()->renderWireCubeInstance(*batch, cubeColor);
} }
} }
} }

View file

@ -39,14 +39,13 @@ void Sphere3DOverlay::render(RenderArgs* args) {
auto batch = args->_batch; auto batch = args->_batch;
if (batch) { if (batch) {
batch->setModelTransform(Transform());
Transform transform = _transform; Transform transform = _transform;
transform.postScale(getDimensions() * SPHERE_OVERLAY_SCALE); transform.postScale(getDimensions() * SPHERE_OVERLAY_SCALE);
batch->setModelTransform(transform);
if (_isSolid) { if (_isSolid) {
DependencyManager::get<GeometryCache>()->renderSolidSphereInstance(*batch, transform, sphereColor); DependencyManager::get<GeometryCache>()->renderSolidSphereInstance(*batch, sphereColor);
} else { } else {
DependencyManager::get<GeometryCache>()->renderWireSphereInstance(*batch, transform, sphereColor); DependencyManager::get<GeometryCache>()->renderWireSphereInstance(*batch, sphereColor);
} }
} }
} }

View file

@ -61,14 +61,14 @@ void RenderableBoxEntityItem::render(RenderArgs* args) {
return; return;
} }
if (_procedural->ready()) {
batch.setModelTransform(transToCenter); // we want to include the scale as well batch.setModelTransform(transToCenter); // we want to include the scale as well
if (_procedural->ready()) {
_procedural->prepare(batch, getPosition(), getDimensions()); _procedural->prepare(batch, getPosition(), getDimensions());
auto color = _procedural->getColor(cubeColor); auto color = _procedural->getColor(cubeColor);
batch._glColor4f(color.r, color.g, color.b, color.a); batch._glColor4f(color.r, color.g, color.b, color.a);
DependencyManager::get<GeometryCache>()->renderCube(batch); DependencyManager::get<GeometryCache>()->renderCube(batch);
} else { } else {
DependencyManager::get<GeometryCache>()->renderSolidCubeInstance(batch, transToCenter, cubeColor); DependencyManager::get<GeometryCache>()->renderSolidCubeInstance(batch, cubeColor);
} }
static const auto triCount = DependencyManager::get<GeometryCache>()->getCubeTriangleCount(); static const auto triCount = DependencyManager::get<GeometryCache>()->getCubeTriangleCount();
args->_details._trianglesRendered += (int)triCount; args->_details._trianglesRendered += (int)triCount;

View file

@ -440,8 +440,8 @@ void RenderableModelEntityItem::render(RenderArgs* args) {
bool success; bool success;
auto shapeTransform = getTransformToCenter(success); auto shapeTransform = getTransformToCenter(success);
if (success) { if (success) {
batch.setModelTransform(Transform()); // we want to include the scale as well batch.setModelTransform(shapeTransform); // we want to include the scale as well
DependencyManager::get<GeometryCache>()->renderWireCubeInstance(batch, shapeTransform, greenColor); DependencyManager::get<GeometryCache>()->renderWireCubeInstance(batch, greenColor);
} }
} }
} }

View file

@ -64,15 +64,14 @@ void RenderableSphereEntityItem::render(RenderArgs* args) {
return; return;
} }
modelTransform.postScale(SPHERE_ENTITY_SCALE); modelTransform.postScale(SPHERE_ENTITY_SCALE);
if (_procedural->ready()) {
batch.setModelTransform(modelTransform); // use a transform with scale, rotation, registration point and translation batch.setModelTransform(modelTransform); // use a transform with scale, rotation, registration point and translation
if (_procedural->ready()) {
_procedural->prepare(batch, getPosition(), getDimensions()); _procedural->prepare(batch, getPosition(), getDimensions());
auto color = _procedural->getColor(sphereColor); auto color = _procedural->getColor(sphereColor);
batch._glColor4f(color.r, color.g, color.b, color.a); batch._glColor4f(color.r, color.g, color.b, color.a);
DependencyManager::get<GeometryCache>()->renderSphere(batch); DependencyManager::get<GeometryCache>()->renderSphere(batch);
} else { } else {
batch.setModelTransform(Transform()); DependencyManager::get<GeometryCache>()->renderSolidSphereInstance(batch, sphereColor);
DependencyManager::get<GeometryCache>()->renderSolidSphereInstance(batch, modelTransform, sphereColor);
} }
static const auto triCount = DependencyManager::get<GeometryCache>()->getSphereTriangleCount(); static const auto triCount = DependencyManager::get<GeometryCache>()->getSphereTriangleCount();
args->_details._trianglesRendered += (int)triCount; args->_details._trianglesRendered += (int)triCount;

View file

@ -132,7 +132,6 @@ void RenderableZoneEntityItem::render(RenderArgs* args) {
Q_ASSERT(args->_batch); Q_ASSERT(args->_batch);
gpu::Batch& batch = *args->_batch; gpu::Batch& batch = *args->_batch;
batch.setModelTransform(Transform());
bool success; bool success;
auto shapeTransform = getTransformToCenter(success); auto shapeTransform = getTransformToCenter(success);
@ -142,9 +141,11 @@ void RenderableZoneEntityItem::render(RenderArgs* args) {
auto geometryCache = DependencyManager::get<GeometryCache>(); auto geometryCache = DependencyManager::get<GeometryCache>();
if (getShapeType() == SHAPE_TYPE_SPHERE) { if (getShapeType() == SHAPE_TYPE_SPHERE) {
shapeTransform.postScale(SPHERE_ENTITY_SCALE); shapeTransform.postScale(SPHERE_ENTITY_SCALE);
geometryCache->renderWireSphereInstance(batch, shapeTransform, DEFAULT_COLOR); batch.setModelTransform(shapeTransform);
geometryCache->renderWireSphereInstance(batch, DEFAULT_COLOR);
} else { } else {
geometryCache->renderWireCubeInstance(batch, shapeTransform, DEFAULT_COLOR); batch.setModelTransform(shapeTransform);
geometryCache->renderWireCubeInstance(batch, DEFAULT_COLOR);
} }
break; break;
} }

View file

@ -9,8 +9,8 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// //
#ifndef gpu__GPUConfig__ #ifndef hifi_gpu_GPUConfig_h
#define gpu__GPUConfig__ #define hifi_gpu_GPUConfig_h
#define GL_GLEXT_PROTOTYPES 1 #define GL_GLEXT_PROTOTYPES 1
@ -38,8 +38,6 @@
#define GPU_FEATURE_PROFILE GPU_CORE #define GPU_FEATURE_PROFILE GPU_CORE
#define GPU_INPUT_PROFILE GPU_CORE_43 #define GPU_INPUT_PROFILE GPU_CORE_43
#elif defined(ANDROID)
#else #else
#include <GL/glew.h> #include <GL/glew.h>
@ -50,4 +48,11 @@
#endif #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
#endif // hifi_gpu_GPUConfig_h

View file

@ -29,20 +29,6 @@ ProfileRangeBatch::~ProfileRangeBatch() {
using namespace gpu; using namespace gpu;
Batch::Batch() :
_commands(),
_commandOffsets(),
_params(),
_data(),
_buffers(),
_textures(),
_streamFormats(),
_transforms(),
_pipelines(),
_framebuffers()
{
}
Batch::Batch(const CacheState& cacheState) : Batch() { Batch::Batch(const CacheState& cacheState) : Batch() {
_commands.reserve(cacheState.commandsSize); _commands.reserve(cacheState.commandsSize);
_commandOffsets.reserve(cacheState.offsetsSize); _commandOffsets.reserve(cacheState.offsetsSize);
@ -88,6 +74,8 @@ void Batch::draw(Primitive primitiveType, uint32 numVertices, uint32 startVertex
_params.push_back(startVertex); _params.push_back(startVertex);
_params.push_back(numVertices); _params.push_back(numVertices);
_params.push_back(primitiveType); _params.push_back(primitiveType);
captureDrawCallInfo();
} }
void Batch::drawIndexed(Primitive primitiveType, uint32 numIndices, uint32 startIndex) { 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(startIndex);
_params.push_back(numIndices); _params.push_back(numIndices);
_params.push_back(primitiveType); _params.push_back(primitiveType);
captureDrawCallInfo();
} }
void Batch::drawInstanced(uint32 numInstances, Primitive primitiveType, uint32 numVertices, uint32 startVertex, uint32 startInstance) { 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(numVertices);
_params.push_back(primitiveType); _params.push_back(primitiveType);
_params.push_back(numInstances); _params.push_back(numInstances);
captureDrawCallInfo();
} }
void Batch::drawIndexedInstanced(uint32 numInstances, Primitive primitiveType, uint32 numIndices, uint32 startIndex, uint32 startInstance) { 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(numIndices);
_params.push_back(primitiveType); _params.push_back(primitiveType);
_params.push_back(numInstances); _params.push_back(numInstances);
captureDrawCallInfo();
} }
@ -123,12 +117,16 @@ void Batch::multiDrawIndirect(uint32 numCommands, Primitive primitiveType) {
ADD_COMMAND(multiDrawIndirect); ADD_COMMAND(multiDrawIndirect);
_params.push_back(numCommands); _params.push_back(numCommands);
_params.push_back(primitiveType); _params.push_back(primitiveType);
captureDrawCallInfo();
} }
void Batch::multiDrawIndexedIndirect(uint32 nbCommands, Primitive primitiveType) { void Batch::multiDrawIndexedIndirect(uint32 nbCommands, Primitive primitiveType) {
ADD_COMMAND(multiDrawIndexedIndirect); ADD_COMMAND(multiDrawIndexedIndirect);
_params.push_back(nbCommands); _params.push_back(nbCommands);
_params.push_back(primitiveType); _params.push_back(primitiveType);
captureDrawCallInfo();
} }
void Batch::setInputFormat(const Stream::FormatPointer& format) { 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) { void Batch::setModelTransform(const Transform& model) {
ADD_COMMAND(setModelTransform); ADD_COMMAND(setModelTransform);
_params.push_back(_transforms.cache(model)); _currentModel = model;
_invalidModel = true;
} }
void Batch::setViewTransform(const Transform& view) { void Batch::setViewTransform(const Transform& view) {
@ -344,6 +343,19 @@ void Batch::runLambda(std::function<void()> f) {
_params.push_back(_lambdas.cache(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) { void Batch::enableStereo(bool enable) {
_enableStereo = enable; _enableStereo = enable;
} }
@ -360,14 +372,13 @@ bool Batch::isSkyboxEnabled() const {
return _enableSkybox; return _enableSkybox;
} }
void Batch::setupNamedCalls(const std::string& instanceName, size_t count, NamedBatchData::Function function) { void Batch::setupNamedCalls(const std::string& instanceName, NamedBatchData::Function function) {
NamedBatchData& instance = _namedData[instanceName]; NamedBatchData& instance = _namedData[instanceName];
instance.count += count; if (!instance.function) {
instance.function = function; instance.function = function;
} }
void Batch::setupNamedCalls(const std::string& instanceName, NamedBatchData::Function function) { captureNamedDrawCallInfo(instanceName);
setupNamedCalls(instanceName, 1, function);
} }
BufferPointer Batch::getNamedBuffer(const std::string& instanceName, uint8_t index) { 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); instance.buffers.resize(index + 1);
} }
if (!instance.buffers[index]) { if (!instance.buffers[index]) {
instance.buffers[index].reset(new Buffer()); instance.buffers[index] = std::make_shared<Buffer>();
} }
return instance.buffers[index]; 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() { void Batch::preExecute() {
for (auto& mapItem : _namedData) { 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) { QDebug& operator<<(QDebug& debug, const Batch::CacheState& cacheState) {

View file

@ -29,7 +29,12 @@ class QDebug;
namespace gpu { namespace gpu {
enum ReservedSlot { enum ReservedSlot {
#ifdef GPU_SSBO_DRAW_CALL_INFO
TRANSFORM_OBJECT_SLOT = 6, TRANSFORM_OBJECT_SLOT = 6,
#else
TRANSFORM_OBJECT_SLOT = 31,
#endif
TRANSFORM_CAMERA_SLOT = 7, TRANSFORM_CAMERA_SLOT = 7,
}; };
@ -45,13 +50,31 @@ class Batch {
public: public:
typedef Stream::Slot Slot; 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<DrawCallInfo>;
struct NamedBatchData { struct NamedBatchData {
using BufferPointers = std::vector<BufferPointer>; using BufferPointers = std::vector<BufferPointer>;
using Function = std::function<void(gpu::Batch&, NamedBatchData&)>; using Function = std::function<void(gpu::Batch&, NamedBatchData&)>;
BufferPointers buffers; BufferPointers buffers;
size_t count { 0 };
Function function; Function function;
DrawCallInfoBuffer drawCallInfos;
size_t count() const { return drawCallInfos.size(); }
void process(Batch& batch) { void process(Batch& batch) {
if (function) { if (function) {
@ -62,6 +85,16 @@ public:
using NamedBatchDataMap = std::map<std::string, NamedBatchData>; using NamedBatchDataMap = std::map<std::string, NamedBatchData>;
DrawCallInfoBuffer _drawCallInfos;
std::string _currentNamedCall;
const DrawCallInfoBuffer& getDrawCallInfoBuffer() const;
DrawCallInfoBuffer& getDrawCallInfoBuffer();
void captureDrawCallInfo();
void captureNamedDrawCallInfo(std::string name);
class CacheState { class CacheState {
public: public:
size_t commandsSize; size_t commandsSize;
@ -88,7 +121,7 @@ public:
transformsSize(transformsSize), pipelinesSize(pipelinesSize), framebuffersSize(framebuffersSize), queriesSize(queriesSize) { } transformsSize(transformsSize), pipelinesSize(pipelinesSize), framebuffersSize(framebuffersSize), queriesSize(queriesSize) { }
}; };
Batch(); Batch() {}
Batch(const CacheState& cacheState); Batch(const CacheState& cacheState);
explicit Batch(const Batch& batch); explicit Batch(const Batch& batch);
~Batch(); ~Batch();
@ -121,13 +154,8 @@ public:
void multiDrawIndirect(uint32 numCommands, Primitive primitiveType); void multiDrawIndirect(uint32 numCommands, Primitive primitiveType);
void multiDrawIndexedIndirect(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); void setupNamedCalls(const std::string& instanceName, NamedBatchData::Function function);
BufferPointer getNamedBuffer(const std::string& instanceName, uint8_t index = 0); BufferPointer getNamedBuffer(const std::string& instanceName, uint8_t index = 0);
void setNamedBuffer(const std::string& instanceName, BufferPointer& buffer, uint8_t index = 0);
// Input Stage // Input Stage
// InputFormat // InputFormat
@ -304,6 +332,9 @@ public:
COMMAND_runLambda, COMMAND_runLambda,
COMMAND_startNamedCall,
COMMAND_stopNamedCall,
// TODO: As long as we have gl calls explicitely issued from interface // 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 // 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 // term strategy is to get rid of any GL calls in favor of the HIFI GPU API
@ -395,7 +426,7 @@ public:
typedef Cache<PipelinePointer>::Vector PipelineCaches; typedef Cache<PipelinePointer>::Vector PipelineCaches;
typedef Cache<FramebufferPointer>::Vector FramebufferCaches; typedef Cache<FramebufferPointer>::Vector FramebufferCaches;
typedef Cache<QueryPointer>::Vector QueryCaches; typedef Cache<QueryPointer>::Vector QueryCaches;
typedef Cache<std::string>::Vector ProfileRangeCaches; typedef Cache<std::string>::Vector StringCaches;
typedef Cache<std::function<void()>>::Vector LambdaCache; typedef Cache<std::function<void()>>::Vector LambdaCache;
// Cache Data in a byte array if too big to fit in Param // Cache Data in a byte array if too big to fit in Param
@ -415,6 +446,18 @@ public:
Params _params; Params _params;
Bytes _data; Bytes _data;
// SSBO class... layout MUST match the layout in TransformCamera.slh
class TransformObject {
public:
Mat4 _model;
Mat4 _modelInverse;
};
using TransformObjects = std::vector<TransformObject>;
bool _invalidModel { true };
Transform _currentModel;
TransformObjects _objects;
BufferCaches _buffers; BufferCaches _buffers;
TextureCaches _textures; TextureCaches _textures;
StreamFormatCaches _streamFormats; StreamFormatCaches _streamFormats;
@ -423,7 +466,8 @@ public:
FramebufferCaches _framebuffers; FramebufferCaches _framebuffers;
QueryCaches _queries; QueryCaches _queries;
LambdaCache _lambdas; LambdaCache _lambdas;
ProfileRangeCaches _profileRanges; StringCaches _profileRanges;
StringCaches _names;
NamedBatchDataMap _namedData; NamedBatchDataMap _namedData;
@ -431,8 +475,13 @@ public:
bool _enableSkybox{ false }; bool _enableSkybox{ false };
protected: protected:
void startNamedCall(const std::string& name);
void stopNamedCall();
// Maybe useful but shoudln't be public. Please convince me otherwise // Maybe useful but shoudln't be public. Please convince me otherwise
void runLambda(std::function<void()> f); void runLambda(std::function<void()> f);
void captureDrawCallInfoImpl();
}; };
} }

View file

@ -76,13 +76,6 @@ public:
virtual void syncCache() = 0; virtual void syncCache() = 0;
virtual void downloadFramebuffer(const FramebufferPointer& srcFramebuffer, const Vec4i& region, QImage& destImage) = 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 // UBO class... layout MUST match the layout in TransformCamera.slh
class TransformCamera { class TransformCamera {
public: public:

View file

@ -62,6 +62,9 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] =
(&::gpu::GLBackend::do_runLambda), (&::gpu::GLBackend::do_runLambda),
(&::gpu::GLBackend::do_startNamedCall),
(&::gpu::GLBackend::do_stopNamedCall),
(&::gpu::GLBackend::do_glActiveBindTexture), (&::gpu::GLBackend::do_glActiveBindTexture),
(&::gpu::GLBackend::do_glUniform1i), (&::gpu::GLBackend::do_glUniform1i),
@ -121,11 +124,7 @@ Backend* GLBackend::createBackend() {
return new GLBackend(); return new GLBackend();
} }
GLBackend::GLBackend() : GLBackend::GLBackend() {
_input(),
_pipeline(),
_output()
{
glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &_uboAlignment); glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &_uboAlignment);
initInput(); initInput();
initTransform(); initTransform();
@ -155,10 +154,8 @@ void GLBackend::renderPassTransfer(Batch& batch) {
{ // Sync all the buffers { // Sync all the buffers
PROFILE_RANGE("syncCPUTransform"); PROFILE_RANGE("syncCPUTransform");
_transform._cameras.resize(0); _transform._cameras.clear();
_transform._cameraOffsets.clear(); _transform._cameraOffsets.clear();
_transform._objects.resize(0);
_transform._objectOffsets.clear();
for (_commandIndex = 0; _commandIndex < numCommands; ++_commandIndex) { for (_commandIndex = 0; _commandIndex < numCommands; ++_commandIndex) {
switch (*command) { switch (*command) {
@ -166,10 +163,11 @@ void GLBackend::renderPassTransfer(Batch& batch) {
case Batch::COMMAND_drawIndexed: case Batch::COMMAND_drawIndexed:
case Batch::COMMAND_drawInstanced: case Batch::COMMAND_drawInstanced:
case Batch::COMMAND_drawIndexedInstanced: case Batch::COMMAND_drawIndexedInstanced:
case Batch::COMMAND_multiDrawIndirect:
case Batch::COMMAND_multiDrawIndexedIndirect:
_transform.preUpdate(_commandIndex, _stereo); _transform.preUpdate(_commandIndex, _stereo);
break; break;
case Batch::COMMAND_setModelTransform:
case Batch::COMMAND_setViewportTransform: case Batch::COMMAND_setViewportTransform:
case Batch::COMMAND_setViewTransform: case Batch::COMMAND_setViewTransform:
case Batch::COMMAND_setProjectionTransform: { case Batch::COMMAND_setProjectionTransform: {
@ -188,12 +186,14 @@ void GLBackend::renderPassTransfer(Batch& batch) {
{ // Sync the transform buffers { // Sync the transform buffers
PROFILE_RANGE("syncGPUTransform"); PROFILE_RANGE("syncGPUTransform");
_transform.transfer(); _transform.transfer(batch);
} }
} }
void GLBackend::renderPassDraw(Batch& batch) { void GLBackend::renderPassDraw(Batch& batch) {
_transform._objectsItr = _transform._objectOffsets.begin(); _currentDraw = -1;
_transform._camerasItr = _transform._cameraOffsets.begin(); _transform._camerasItr = _transform._cameraOffsets.begin();
const size_t numCommands = batch.getCommands().size(); const size_t numCommands = batch.getCommands().size();
const Batch::Commands::value_type* command = batch.getCommands().data(); const Batch::Commands::value_type* command = batch.getCommands().data();
@ -209,6 +209,22 @@ void GLBackend::renderPassDraw(Batch& batch) {
case Batch::COMMAND_setProjectionTransform: case Batch::COMMAND_setProjectionTransform:
break; 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: { default: {
CommandCall call = _commandCalls[(*command)]; CommandCall call = _commandCalls[(*command)];
(this->*(call))(batch, *offset); (this->*(call))(batch, *offset);
@ -306,10 +322,6 @@ void GLBackend::syncCache() {
} }
void GLBackend::do_draw(Batch& batch, size_t paramOffset) { void GLBackend::do_draw(Batch& batch, size_t paramOffset) {
updateInput();
updateTransform();
updatePipeline();
Primitive primitiveType = (Primitive)batch._params[paramOffset + 2]._uint; Primitive primitiveType = (Primitive)batch._params[paramOffset + 2]._uint;
GLenum mode = _primitiveToGLmode[primitiveType]; GLenum mode = _primitiveToGLmode[primitiveType];
uint32 numVertices = batch._params[paramOffset + 1]._uint; 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) { void GLBackend::do_drawIndexed(Batch& batch, size_t paramOffset) {
updateInput();
updateTransform();
updatePipeline();
Primitive primitiveType = (Primitive)batch._params[paramOffset + 2]._uint; Primitive primitiveType = (Primitive)batch._params[paramOffset + 2]._uint;
GLenum mode = _primitiveToGLmode[primitiveType]; GLenum mode = _primitiveToGLmode[primitiveType];
uint32 numIndices = batch._params[paramOffset + 1]._uint; 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) { void GLBackend::do_drawInstanced(Batch& batch, size_t paramOffset) {
updateInput();
updateTransform();
updatePipeline();
GLint numInstances = batch._params[paramOffset + 4]._uint; GLint numInstances = batch._params[paramOffset + 4]._uint;
Primitive primitiveType = (Primitive)batch._params[paramOffset + 3]._uint; Primitive primitiveType = (Primitive)batch._params[paramOffset + 3]._uint;
GLenum mode = _primitiveToGLmode[primitiveType]; 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) { void GLBackend::do_drawIndexedInstanced(Batch& batch, size_t paramOffset) {
updateInput();
updateTransform();
updatePipeline();
GLint numInstances = batch._params[paramOffset + 4]._uint; GLint numInstances = batch._params[paramOffset + 4]._uint;
GLenum mode = _primitiveToGLmode[(Primitive)batch._params[paramOffset + 3]._uint]; GLenum mode = _primitiveToGLmode[(Primitive)batch._params[paramOffset + 3]._uint];
uint32 numIndices = batch._params[paramOffset + 2]._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) { void GLBackend::do_multiDrawIndirect(Batch& batch, size_t paramOffset) {
#if (GPU_INPUT_PROFILE == GPU_CORE_43) #if (GPU_INPUT_PROFILE == GPU_CORE_43)
updateInput();
updateTransform();
updatePipeline();
uint commandCount = batch._params[paramOffset + 0]._uint; uint commandCount = batch._params[paramOffset + 0]._uint;
GLenum mode = _primitiveToGLmode[(Primitive)batch._params[paramOffset + 1]._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) { void GLBackend::do_multiDrawIndexedIndirect(Batch& batch, size_t paramOffset) {
#if (GPU_INPUT_PROFILE == GPU_CORE_43) #if (GPU_INPUT_PROFILE == GPU_CORE_43)
updateInput();
updateTransform();
updatePipeline();
uint commandCount = batch._params[paramOffset + 0]._uint; uint commandCount = batch._params[paramOffset + 0]._uint;
GLenum mode = _primitiveToGLmode[(Primitive)batch._params[paramOffset + 1]._uint]; GLenum mode = _primitiveToGLmode[(Primitive)batch._params[paramOffset + 1]._uint];
GLenum indexType = _elementTypeToGLType[_input._indexBufferType]; GLenum indexType = _elementTypeToGLType[_input._indexBufferType];
@ -423,6 +415,15 @@ void GLBackend::do_runLambda(Batch& batch, size_t paramOffset) {
f(); 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() { void GLBackend::resetStages() {
resetInputStage(); resetInputStage();
resetPipelineStage(); resetPipelineStage();

View file

@ -320,28 +320,26 @@ protected:
void killTransform(); void killTransform();
// Synchronize the state cache of this Backend with the actual real state of the GL Context // Synchronize the state cache of this Backend with the actual real state of the GL Context
void syncTransformStateCache(); void syncTransformStateCache();
void updateTransform() const; void updateTransform(const Batch& batch);
void resetTransformStage(); void resetTransformStage();
struct TransformStageState { struct TransformStageState {
using TransformObjects = std::vector<TransformObject>;
using TransformCameras = std::vector<TransformCamera>; using TransformCameras = std::vector<TransformCamera>;
TransformObject _object;
TransformCamera _camera; TransformCamera _camera;
TransformObjects _objects;
TransformCameras _cameras; TransformCameras _cameras;
size_t _cameraUboSize{ 0 }; mutable std::map<std::string, GLvoid*> _drawCallInfoOffsets;
size_t _objectUboSize{ 0 };
GLuint _objectBuffer { 0 }; GLuint _objectBuffer { 0 };
GLuint _cameraBuffer { 0 }; GLuint _cameraBuffer { 0 };
Transform _model; GLuint _drawCallInfoBuffer { 0 };
GLuint _objectBufferTexture { 0 };
size_t _cameraUboSize { 0 };
Transform _view; Transform _view;
Mat4 _projection; Mat4 _projection;
Vec4i _viewport { 0, 0, 1, 1 }; Vec4i _viewport { 0, 0, 1, 1 };
Vec2 _depthRange { 0.0f, 1.0f }; Vec2 _depthRange { 0.0f, 1.0f };
bool _invalidModel{true};
bool _invalidView { false }; bool _invalidView { false };
bool _invalidProj { false }; bool _invalidProj { false };
bool _invalidViewport { false }; bool _invalidViewport { false };
@ -349,13 +347,11 @@ protected:
using Pair = std::pair<size_t, size_t>; using Pair = std::pair<size_t, size_t>;
using List = std::list<Pair>; using List = std::list<Pair>;
List _cameraOffsets; List _cameraOffsets;
List _objectOffsets;
mutable List::const_iterator _objectsItr;
mutable List::const_iterator _camerasItr; mutable List::const_iterator _camerasItr;
void preUpdate(size_t commandIndex, const StereoState& stereo); void preUpdate(size_t commandIndex, const StereoState& stereo);
void update(size_t commandIndex, const StereoState& stereo) const; void update(size_t commandIndex, const StereoState& stereo) const;
void transfer() const; void transfer(const Batch& batch) const;
} _transform; } _transform;
int32_t _uboAlignment{ 0 }; int32_t _uboAlignment{ 0 };
@ -465,6 +461,9 @@ protected:
void do_runLambda(Batch& batch, size_t paramOffset); 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(); void resetStages();
// TODO: As long as we have gl calls explicitely issued from interface // TODO: As long as we have gl calls explicitely issued from interface
@ -487,6 +486,8 @@ protected:
void do_pushProfileRange(Batch& batch, size_t paramOffset); void do_pushProfileRange(Batch& batch, size_t paramOffset);
void do_popProfileRange(Batch& batch, size_t paramOffset); void do_popProfileRange(Batch& batch, size_t paramOffset);
int _currentDraw { -1 };
typedef void (GLBackend::*CommandCall)(Batch&, size_t); typedef void (GLBackend::*CommandCall)(Batch&, size_t);
static CommandCall _commandCalls[Batch::NUM_COMMANDS]; static CommandCall _commandCalls[Batch::NUM_COMMANDS];
}; };

View file

@ -75,9 +75,9 @@ void makeBindings(GLBackend::GLShader* shader) {
glBindAttribLocation(glprogram, gpu::Stream::SKIN_CLUSTER_WEIGHT, "inSkinClusterWeight"); glBindAttribLocation(glprogram, gpu::Stream::SKIN_CLUSTER_WEIGHT, "inSkinClusterWeight");
} }
loc = glGetAttribLocation(glprogram, "inInstanceTransform"); loc = glGetAttribLocation(glprogram, "_drawCallInfo");
if (loc >= 0 && loc != gpu::Stream::INSTANCE_XFM) { if (loc >= 0 && loc != gpu::Stream::DRAW_CALL_INFO) {
glBindAttribLocation(glprogram, gpu::Stream::INSTANCE_XFM, "inInstanceTransform"); glBindAttribLocation(glprogram, gpu::Stream::DRAW_CALL_INFO, "_drawCallInfo");
} }
// Link again to take into account the assigned attrib location // 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! // now assign the ubo binding, then DON't relink!
//Check for gpu specific uniform slotBindings //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) { if (loc >= 0) {
glUniformBlockBinding(glprogram, loc, gpu::TRANSFORM_OBJECT_SLOT); glShaderStorageBlockBinding(glprogram, loc, gpu::TRANSFORM_OBJECT_SLOT);
shader->_transformObjectSlot = 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"); loc = glGetUniformBlockIndex(glprogram, "transformCameraBuffer");
if (loc >= 0) { if (loc >= 0) {
glUniformBlockBinding(glprogram, loc, gpu::TRANSFORM_CAMERA_SLOT); glUniformBlockBinding(glprogram, loc, gpu::TRANSFORM_CAMERA_SLOT);
shader->_transformCameraSlot = gpu::TRANSFORM_CAMERA_SLOT; shader->_transformCameraSlot = gpu::TRANSFORM_CAMERA_SLOT;
} }
(void)CHECK_GL_ERROR();
} }
GLBackend::GLShader* compileShader(const Shader& shader) { GLBackend::GLShader* compileShader(const Shader& shader) {

View file

@ -16,8 +16,6 @@ using namespace gpu;
// Transform Stage // Transform Stage
void GLBackend::do_setModelTransform(Batch& batch, size_t paramOffset) { 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) { 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() { void GLBackend::initTransform() {
glGenBuffers(1, &_transform._objectBuffer); glGenBuffers(1, &_transform._objectBuffer);
glGenBuffers(1, &_transform._cameraBuffer); glGenBuffers(1, &_transform._cameraBuffer);
glGenBuffers(1, &_transform._drawCallInfoBuffer);
#ifndef GPU_SSBO_DRAW_CALL_INFO
glGenTextures(1, &_transform._objectBufferTexture);
#endif
size_t cameraSize = sizeof(TransformCamera); size_t cameraSize = sizeof(TransformCamera);
while (_transform._cameraUboSize < cameraSize) { while (_transform._cameraUboSize < cameraSize) {
_transform._cameraUboSize += _uboAlignment; _transform._cameraUboSize += _uboAlignment;
} }
size_t objectSize = sizeof(TransformObject);
while (_transform._objectUboSize < objectSize) {
_transform._objectUboSize += _uboAlignment;
}
} }
void GLBackend::killTransform() { void GLBackend::killTransform() {
glDeleteBuffers(1, &_transform._objectBuffer); glDeleteBuffers(1, &_transform._objectBuffer);
glDeleteBuffers(1, &_transform._cameraBuffer); glDeleteBuffers(1, &_transform._cameraBuffer);
glDeleteBuffers(1, &_transform._drawCallInfoBuffer);
#ifndef GPU_SSBO_DRAW_CALL_INFO
glDeleteTextures(1, &_transform._objectBufferTexture);
#endif
} }
void GLBackend::syncTransformStateCache() { void GLBackend::syncTransformStateCache() {
_transform._invalidViewport = true; _transform._invalidViewport = true;
_transform._invalidProj = true; _transform._invalidProj = true;
_transform._invalidView = true; _transform._invalidView = true;
_transform._invalidModel = true;
glGetIntegerv(GL_VIEWPORT, (GLint*) &_transform._viewport); glGetIntegerv(GL_VIEWPORT, (GLint*) &_transform._viewport);
@ -91,7 +92,6 @@ void GLBackend::syncTransformStateCache() {
Mat4 modelView; Mat4 modelView;
auto modelViewInv = glm::inverse(modelView); auto modelViewInv = glm::inverse(modelView);
_transform._view.evalFromRawMatrix(modelViewInv); _transform._view.evalFromRawMatrix(modelViewInv);
_transform._model.setIdentity();
} }
void GLBackend::TransformStageState::preUpdate(size_t commandIndex, const StereoState& stereo) { 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); _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) { if (_invalidView || _invalidProj || _invalidViewport) {
size_t offset = _cameraUboSize * _cameras.size(); size_t offset = _cameraUboSize * _cameras.size();
if (stereo._enable) { 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 // 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 // FIXME not thread safe
static std::vector<uint8_t> bufferData; static std::vector<uint8_t> bufferData;
if (!_cameras.empty()) { if (!_cameras.empty()) {
glBindBuffer(GL_UNIFORM_BUFFER, _cameraBuffer);
bufferData.resize(_cameraUboSize * _cameras.size()); bufferData.resize(_cameraUboSize * _cameras.size());
for (size_t i = 0; i < _cameras.size(); ++i) { for (size_t i = 0; i < _cameras.size(); ++i) {
memcpy(bufferData.data() + (_cameraUboSize * i), &_cameras[i], sizeof(TransformCamera)); 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); 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); 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(); CHECK_GL_ERROR();
} }
void GLBackend::TransformStageState::update(size_t commandIndex, const StereoState& stereo) const { void GLBackend::TransformStageState::update(size_t commandIndex, const StereoState& stereo) const {
static const size_t INVALID_OFFSET = (size_t)-1; static const size_t INVALID_OFFSET = (size_t)-1;
size_t offset = INVALID_OFFSET; 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)) { while ((_camerasItr != _cameraOffsets.end()) && (commandIndex >= (*_camerasItr).first)) {
offset = (*_camerasItr).second; offset = (*_camerasItr).second;
++_camerasItr; ++_camerasItr;
@ -197,8 +199,23 @@ void GLBackend::TransformStageState::update(size_t commandIndex, const StereoSta
(void)CHECK_GL_ERROR(); (void)CHECK_GL_ERROR();
} }
void GLBackend::updateTransform() const { void GLBackend::updateTransform(const Batch& batch) {
_transform.update(_commandIndex, _stereo); _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() { void GLBackend::resetTransformStage() {

View file

@ -10,13 +10,12 @@
!> !>
<@if not GPU_INPUTS_SLH@> <@if not GPU_INPUTS_SLH@>
<@def GPU_INPUTS_SLH@> <@def GPU_INPUTS_SLH@>
in vec4 inPosition; layout(location = 0) in vec4 inPosition;
in vec4 inNormal; layout(location = 1) in vec4 inNormal;
in vec4 inColor; layout(location = 2) in vec4 inColor;
in vec4 inTexCoord0; layout(location = 3) in vec4 inTexCoord0;
in vec4 inTangent; layout(location = 4) in vec4 inTangent;
in vec4 inSkinClusterIndex; layout(location = 5) in vec4 inSkinClusterIndex;
in vec4 inSkinClusterWeight; layout(location = 6) in vec4 inSkinClusterWeight;
in vec4 inTexCoord1; layout(location = 7) in vec4 inTexCoord1;
in mat4 inInstanceTransform;
<@endif@> <@endif@>

View file

@ -34,14 +34,7 @@ const ElementArray& getDefaultElements() {
//SKIN_CLUSTER_WEIGHT = 6, //SKIN_CLUSTER_WEIGHT = 6,
Element::VEC4F_XYZW, Element::VEC4F_XYZW,
//TEXCOORD1 = 7, //TEXCOORD1 = 7,
Element::VEC2F_UV, 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
}}; }};
return defaultElements; return defaultElements;
} }

View file

@ -37,12 +37,10 @@ public:
SKIN_CLUSTER_INDEX = 5, SKIN_CLUSTER_INDEX = 5,
SKIN_CLUSTER_WEIGHT = 6, SKIN_CLUSTER_WEIGHT = 6,
TEXCOORD1 = 7, TEXCOORD1 = 7,
INSTANCE_SCALE = 8, NUM_INPUT_SLOTS = TEXCOORD1 + 1,
INSTANCE_TRANSLATE = 9,
INSTANCE_XFM = 10,
// 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; typedef uint8 Slot;

View file

@ -10,12 +10,7 @@
<@if not GPU_TRANSFORM_STATE_SLH@> <@if not GPU_TRANSFORM_STATE_SLH@>
<@def GPU_TRANSFORM_STATE_SLH@> <@def GPU_TRANSFORM_STATE_SLH@>
<@func declareStandardTransform()@> <@func declareStandardCameraTransform()@>
struct TransformObject {
mat4 _model;
mat4 _modelInverse;
};
struct TransformCamera { struct TransformCamera {
mat4 _view; mat4 _view;
mat4 _viewInverse; mat4 _viewInverse;
@ -25,13 +20,6 @@ struct TransformCamera {
vec4 _viewport; vec4 _viewport;
}; };
layout(std140) uniform transformObjectBuffer {
TransformObject _object;
};
TransformObject getTransformObject() {
return _object;
}
layout(std140) uniform transformCameraBuffer { layout(std140) uniform transformCameraBuffer {
TransformCamera _camera; TransformCamera _camera;
}; };
@ -40,6 +28,50 @@ TransformCamera getTransformCamera() {
} }
<@endfunc@> <@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)@> <@func transformCameraViewport(cameraTransform, viewport)@>
<$viewport$> = <$cameraTransform$>._viewport; <$viewport$> = <$cameraTransform$>._viewport;
<@endfunc@> <@endfunc@>
@ -53,15 +85,6 @@ TransformCamera getTransformCamera() {
} }
<@endfunc@> <@endfunc@>
<@func transformInstancedModelToClipPos(cameraTransform, objectTransform, modelPos, clipPos)@>
<!// Equivalent to the following but hoppefully a tad more accurate
//return camera._projection * camera._view * object._model * pos; !>
{ // 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)@> <@func $transformModelToEyeAndClipPos(cameraTransform, objectTransform, modelPos, eyePos, clipPos)@>
<!// Equivalent to the following but hoppefully a tad more accurate <!// Equivalent to the following but hoppefully a tad more accurate
//return camera._projection * camera._view * object._model * pos; !> //return camera._projection * camera._view * object._model * pos; !>
@ -74,30 +97,12 @@ TransformCamera getTransformCamera() {
} }
<@endfunc@> <@endfunc@>
<@func $transformInstancedModelToEyeAndClipPos(cameraTransform, objectTransform, modelPos, eyePos, clipPos)@>
<!// Equivalent to the following but hoppefully a tad more accurate
//return camera._projection * camera._view * object._model * pos; !>
{ // 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)@> <@func transformModelToWorldPos(objectTransform, modelPos, worldPos)@>
{ // transformModelToWorldPos { // transformModelToWorldPos
<$worldPos$> = (<$objectTransform$>._model * <$modelPos$>); <$worldPos$> = (<$objectTransform$>._model * <$modelPos$>);
} }
<@endfunc@> <@endfunc@>
<@func transformInstancedModelToWorldPos(objectTransform, modelPos, worldPos)@>
{ // transformModelToWorldPos
<$worldPos$> = (inInstanceTransform * <$modelPos$>);
}
<@endfunc@>
<@func transformModelToEyeDir(cameraTransform, objectTransform, modelDir, eyeDir)@> <@func transformModelToEyeDir(cameraTransform, objectTransform, modelDir, eyeDir)@>
{ // transformModelToEyeDir { // transformModelToEyeDir
vec3 mr0 = vec3(<$objectTransform$>._modelInverse[0].x, <$objectTransform$>._modelInverse[1].x, <$objectTransform$>._modelInverse[2].x); vec3 mr0 = vec3(<$objectTransform$>._modelInverse[0].x, <$objectTransform$>._modelInverse[1].x, <$objectTransform$>._modelInverse[2].x);
@ -112,21 +117,6 @@ TransformCamera getTransformCamera() {
} }
<@endfunc@> <@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)@> <@func transformEyeToWorldDir(cameraTransform, eyeDir, worldDir)@>
{ // transformEyeToWorldDir { // transformEyeToWorldDir
<$worldDir$> = vec3(<$cameraTransform$>._viewInverse * vec4(<$eyeDir$>.xyz, 0.0)); <$worldDir$> = vec3(<$cameraTransform$>._viewInverse * vec4(<$eyeDir$>.xyz, 0.0));

View file

@ -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 POSITION_ELEMENT{ gpu::VEC3, gpu::FLOAT, gpu::XYZ };
static const gpu::Element NORMAL_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 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 SOLID_STREAM_FORMAT;
static gpu::Stream::FormatPointer INSTANCED_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::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::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::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; return INSTANCED_SOLID_STREAM_FORMAT;
} }
@ -511,11 +509,9 @@ GeometryCache::~GeometryCache() {
#endif //def WANT_DEBUG #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); gpu::BufferView colorView(colorBuffer, COLOR_ELEMENT);
batch.setInputBuffer(gpu::Stream::COLOR, colorView); 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) { void GeometryCache::renderShape(gpu::Batch& batch, Shape shape) {
@ -528,24 +524,24 @@ void GeometryCache::renderWireShape(gpu::Batch& batch, Shape shape) {
_shapes[shape].drawWire(batch); _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()); batch.setInputFormat(getInstancedSolidStreamFormat());
setupBatchInstance(batch, transformBuffer, colorBuffer); setupBatchInstance(batch, colorBuffer);
_shapes[shape].drawInstances(batch, count); _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()); batch.setInputFormat(getInstancedSolidStreamFormat());
setupBatchInstance(batch, transformBuffer, colorBuffer); setupBatchInstance(batch, colorBuffer);
_shapes[shape].drawWireInstances(batch, count); _shapes[shape].drawWireInstances(batch, count);
} }
void GeometryCache::renderCubeInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer transformBuffer, gpu::BufferPointer colorBuffer) { void GeometryCache::renderCubeInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer colorBuffer) {
renderShapeInstances(batch, Cube, count, transformBuffer, colorBuffer); renderShapeInstances(batch, Cube, count, colorBuffer);
} }
void GeometryCache::renderWireCubeInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer transformBuffer, gpu::BufferPointer colorBuffer) { void GeometryCache::renderWireCubeInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer colorBuffer) {
renderWireShapeInstances(batch, Cube, count, transformBuffer, colorBuffer); renderWireShapeInstances(batch, Cube, count, colorBuffer);
} }
void GeometryCache::renderCube(gpu::Batch& batch) { void GeometryCache::renderCube(gpu::Batch& batch) {
@ -556,8 +552,8 @@ void GeometryCache::renderWireCube(gpu::Batch& batch) {
renderWireShape(batch, Cube); renderWireShape(batch, Cube);
} }
void GeometryCache::renderSphereInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer transformBuffer, gpu::BufferPointer colorBuffer) { void GeometryCache::renderSphereInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer colorBuffer) {
renderShapeInstances(batch, Sphere, count, transformBuffer, colorBuffer); renderShapeInstances(batch, Sphere, count, colorBuffer);
} }
void GeometryCache::renderSphere(gpu::Batch& batch) { void GeometryCache::renderSphere(gpu::Batch& batch) {
@ -1854,45 +1850,34 @@ uint32_t toCompactColor(const glm::vec4& color) {
return compactColor; return compactColor;
} }
static const size_t INSTANCE_TRANSFORM_BUFFER = 0; static const size_t INSTANCE_COLOR_BUFFER = 0;
static const size_t INSTANCE_COLOR_BUFFER = 1;
template <typename F> template <typename F>
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); gpu::BufferPointer instanceColorBuffer = batch.getNamedBuffer(name, INSTANCE_COLOR_BUFFER);
auto compactColor = toCompactColor(color); auto compactColor = toCompactColor(color);
instanceColorBuffer->append(compactColor); instanceColorBuffer->append(compactColor);
} }
batch.setupNamedCalls(name, [f](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) { batch.setupNamedCalls(name, [f](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {
auto pipeline = DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch); DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch);
auto location = pipeline->getProgram()->getUniforms().findLocation("Instanced");
batch._glUniform1i(location, 1);
f(batch, data); 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__; static const std::string INSTANCE_NAME = __FUNCTION__;
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) {
DependencyManager::get<GeometryCache>()->renderShapeInstances(batch, GeometryCache::Sphere, data.count, DependencyManager::get<GeometryCache>()->renderShapeInstances(batch, GeometryCache::Sphere, data.count(),
data.buffers[INSTANCE_TRANSFORM_BUFFER],
data.buffers[INSTANCE_COLOR_BUFFER]); 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__; static const std::string INSTANCE_NAME = __FUNCTION__;
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) {
DependencyManager::get<GeometryCache>()->renderWireShapeInstances(batch, GeometryCache::Sphere, data.count, DependencyManager::get<GeometryCache>()->renderWireShapeInstances(batch, GeometryCache::Sphere, data.count(),
data.buffers[INSTANCE_TRANSFORM_BUFFER],
data.buffers[INSTANCE_COLOR_BUFFER]); data.buffers[INSTANCE_COLOR_BUFFER]);
}); });
} }
@ -1901,12 +1886,12 @@ void GeometryCache::renderWireSphereInstance(gpu::Batch& batch, const Transform&
// available shape types, both solid and wireframes // available shape types, both solid and wireframes
//#define DEBUG_SHAPES //#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__; static const std::string INSTANCE_NAME = __FUNCTION__;
#ifdef DEBUG_SHAPES #ifdef DEBUG_SHAPES
static auto startTime = usecTimestampNow(); 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(); auto usecs = usecTimestampNow();
usecs -= startTime; 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. // For the first half second for a given shape, show the wireframe, for the second half, show the solid.
if (fractionalSeconds > 0.5f) { if (fractionalSeconds > 0.5f) {
DependencyManager::get<GeometryCache>()->renderShapeInstances(batch, shape, data.count, DependencyManager::get<GeometryCache>()->renderShapeInstances(batch, shape, data.count(),
data.buffers[INSTANCE_TRANSFORM_BUFFER],
data.buffers[INSTANCE_COLOR_BUFFER]); data.buffers[INSTANCE_COLOR_BUFFER]);
} else { } else {
DependencyManager::get<GeometryCache>()->renderWireShapeInstances(batch, shape, data.count, DependencyManager::get<GeometryCache>()->renderWireShapeInstances(batch, shape, data.count(),
data.buffers[INSTANCE_TRANSFORM_BUFFER],
data.buffers[INSTANCE_COLOR_BUFFER]); data.buffers[INSTANCE_COLOR_BUFFER]);
} }
}); });
#else #else
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) {
DependencyManager::get<GeometryCache>()->renderCubeInstances(batch, data.count, DependencyManager::get<GeometryCache>()->renderCubeInstances(batch, data.count(),
data.buffers[INSTANCE_TRANSFORM_BUFFER],
data.buffers[INSTANCE_COLOR_BUFFER]); data.buffers[INSTANCE_COLOR_BUFFER]);
}); });
#endif #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__; static const std::string INSTANCE_NAME = __FUNCTION__;
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) {
DependencyManager::get<GeometryCache>()->renderWireCubeInstances(batch, data.count, DependencyManager::get<GeometryCache>()->renderWireCubeInstances(batch, data.count(),
data.buffers[INSTANCE_TRANSFORM_BUFFER],
data.buffers[INSTANCE_COLOR_BUFFER]); data.buffers[INSTANCE_COLOR_BUFFER]);
}); });
} }

View file

@ -154,41 +154,41 @@ public:
gpu::PipelinePointer bindSimpleProgram(gpu::Batch& batch, bool textured = false, bool culled = true, gpu::PipelinePointer bindSimpleProgram(gpu::Batch& batch, bool textured = false, bool culled = true,
bool emissive = false, bool depthBias = false); bool emissive = false, bool depthBias = false);
void renderSolidSphereInstance(gpu::Batch& batch, const Transform& xfm, const glm::vec4& color); void renderSolidSphereInstance(gpu::Batch& batch, const glm::vec4& color);
void renderSolidSphereInstance(gpu::Batch& batch, const Transform& xfm, const glm::vec3& color) { void renderSolidSphereInstance(gpu::Batch& batch, const glm::vec3& color) {
renderSolidSphereInstance(batch, xfm, glm::vec4(color, 1.0)); 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 glm::vec4& color);
void renderWireSphereInstance(gpu::Batch& batch, const Transform& xfm, const glm::vec3& color) { void renderWireSphereInstance(gpu::Batch& batch, const glm::vec3& color) {
renderWireSphereInstance(batch, xfm, glm::vec4(color, 1.0)); 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 glm::vec4& color);
void renderSolidCubeInstance(gpu::Batch& batch, const Transform& xfm, const glm::vec3& color) { void renderSolidCubeInstance(gpu::Batch& batch, const glm::vec3& color) {
renderSolidCubeInstance(batch, xfm, glm::vec4(color, 1.0)); 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 glm::vec4& color);
void renderWireCubeInstance(gpu::Batch& batch, const Transform& xfm, const glm::vec3& color) { void renderWireCubeInstance(gpu::Batch& batch, const glm::vec3& color) {
renderWireCubeInstance(batch, xfm, glm::vec4(color, 1.0)); renderWireCubeInstance(batch, glm::vec4(color, 1.0));
} }
void renderShapeInstances(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& transformBuffer, gpu::BufferPointer& colorBuffer); void renderWireShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer);
void renderShape(gpu::Batch& batch, Shape shape); void renderShape(gpu::Batch& batch, Shape shape);
void renderWireShape(gpu::Batch& batch, Shape shape); void renderWireShape(gpu::Batch& batch, Shape shape);
size_t getShapeTriangleCount(Shape shape); size_t getShapeTriangleCount(Shape shape);
void renderCubeInstances(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 transformBuffer, gpu::BufferPointer colorBuffer); void renderWireCubeInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer colorBuffer);
void renderCube(gpu::Batch& batch); void renderCube(gpu::Batch& batch);
void renderWireCube(gpu::Batch& batch); void renderWireCube(gpu::Batch& batch);
size_t getCubeTriangleCount(); size_t getCubeTriangleCount();
void renderSphereInstances(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 transformBuffer, gpu::BufferPointer colorBuffer); void renderWireSphereInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer colorBuffer);
void renderSphere(gpu::Batch& batch); void renderSphere(gpu::Batch& batch);
void renderWireSphere(gpu::Batch& batch); void renderWireSphere(gpu::Batch& batch);
size_t getSphereTriangleCount(); size_t getSphereTriangleCount();

View file

@ -17,7 +17,7 @@
<@include DeferredLighting.slh@> <@include DeferredLighting.slh@>
<@include gpu/Transform.slh@> <@include gpu/Transform.slh@>
<$declareStandardTransform()$> <$declareStandardCameraTransform()$>
// Everything about light // Everything about light

View file

@ -17,9 +17,7 @@
<@include gpu/Transform.slh@> <@include gpu/Transform.slh@>
<$declareStandardTransform()$> <$declareStandardTransform()$>
uniform bool Instanced = false;
// the interpolated normal // the interpolated normal
out vec3 _normal; out vec3 _normal;
out vec3 _modelNormal; out vec3 _modelNormal;
out vec3 _color; out vec3 _color;
@ -35,11 +33,6 @@ void main(void) {
// standard transform // standard transform
TransformCamera cam = getTransformCamera(); TransformCamera cam = getTransformCamera();
TransformObject obj = getTransformObject(); TransformObject obj = getTransformObject();
if (Instanced) {
<$transformInstancedModelToClipPos(cam, obj, inPosition, gl_Position)$>
<$transformInstancedModelToEyeDir(cam, obj, inNormal.xyz, _normal)$>
} else {
<$transformModelToClipPos(cam, obj, inPosition, gl_Position)$> <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$>
<$transformModelToEyeDir(cam, obj, inNormal.xyz, _normal)$> <$transformModelToEyeDir(cam, obj, inNormal.xyz, _normal)$>
} }
}

View file

@ -124,7 +124,6 @@ class QTestWindow : public QWindow {
glm::mat4 _projectionMatrix; glm::mat4 _projectionMatrix;
RateCounter fps; RateCounter fps;
QTime _time; QTime _time;
int _instanceLocation{ -1 };
protected: protected:
void renderText(); void renderText();
@ -164,7 +163,6 @@ public:
state->setMultisampleEnable(true); state->setMultisampleEnable(true);
state->setDepthTest(gpu::State::DepthTest { true }); state->setDepthTest(gpu::State::DepthTest { true });
_pipeline = gpu::Pipeline::create(shader, state); _pipeline = gpu::Pipeline::create(shader, state);
_instanceLocation = _pipeline->getProgram()->getUniforms().findLocation("Instanced");
// Clear screen // Clear screen
gpu::Batch batch; gpu::Batch batch;
@ -218,16 +216,16 @@ public:
static const std::string GRID_INSTANCE = "Grid"; static const std::string GRID_INSTANCE = "Grid";
static auto compactColor1 = toCompactColor(vec4{ 0.35f, 0.25f, 0.15f, 1.0f }); 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 auto compactColor2 = toCompactColor(vec4{ 0.15f, 0.25f, 0.35f, 1.0f });
static gpu::BufferPointer transformBuffer; static std::vector<glm::mat4> transforms;
static gpu::BufferPointer colorBuffer; static gpu::BufferPointer colorBuffer;
if (!transformBuffer) { if (!transforms.empty()) {
transformBuffer = std::make_shared<gpu::Buffer>(); transforms.reserve(200);
colorBuffer = std::make_shared<gpu::Buffer>(); colorBuffer = std::make_shared<gpu::Buffer>();
for (int i = 0; i < 100; ++i) { for (int i = 0; i < 100; ++i) {
{ {
glm::mat4 transform = glm::translate(mat4(), vec3(0, -1, -50 + i)); glm::mat4 transform = glm::translate(mat4(), vec3(0, -1, -50 + i));
transform = glm::scale(transform, vec3(100, 1, 1)); transform = glm::scale(transform, vec3(100, 1, 1));
transformBuffer->append(transform); transforms.push_back(transform);
colorBuffer->append(compactColor1); colorBuffer->append(compactColor1);
} }
@ -235,21 +233,21 @@ public:
glm::mat4 transform = glm::mat4_cast(quat(vec3(0, PI / 2.0f, 0))); glm::mat4 transform = glm::mat4_cast(quat(vec3(0, PI / 2.0f, 0)));
transform = glm::translate(transform, vec3(0, -1, -50 + i)); transform = glm::translate(transform, vec3(0, -1, -50 + i));
transform = glm::scale(transform, vec3(100, 1, 1)); transform = glm::scale(transform, vec3(100, 1, 1));
transformBuffer->append(transform); transforms.push_back(transform);
colorBuffer->append(compactColor2); colorBuffer->append(compactColor2);
} }
} }
} }
batch.setupNamedCalls(GRID_INSTANCE, 200, [=](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) { for (auto& transform : transforms) {
batch.setModelTransform(transform);
batch.setupNamedCalls(GRID_INSTANCE, [=](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {
batch.setViewTransform(camera); batch.setViewTransform(camera);
batch.setModelTransform(Transform());
batch.setPipeline(_pipeline); batch.setPipeline(_pipeline);
batch._glUniform1i(_instanceLocation, 1); geometryCache->renderWireShapeInstances(batch, GeometryCache::Line, data.count(), colorBuffer);
geometryCache->renderWireShapeInstances(batch, GeometryCache::Line, data.count, transformBuffer, colorBuffer);
batch._glUniform1i(_instanceLocation, 0);
}); });
} }
}
{ {
static const size_t ITEM_COUNT = 1000; static const size_t ITEM_COUNT = 1000;
@ -316,14 +314,11 @@ public:
batch.setViewTransform(camera); batch.setViewTransform(camera);
batch.setModelTransform(Transform()); batch.setModelTransform(Transform());
batch.setPipeline(_pipeline); batch.setPipeline(_pipeline);
batch._glUniform1i(_instanceLocation, 1);
batch.setInputFormat(getInstancedSolidStreamFormat()); batch.setInputFormat(getInstancedSolidStreamFormat());
batch.setInputBuffer(gpu::Stream::COLOR, colorView); batch.setInputBuffer(gpu::Stream::COLOR, colorView);
batch.setInputBuffer(gpu::Stream::INSTANCE_XFM, instanceXfmView);
batch.setIndirectBuffer(indirectBuffer); batch.setIndirectBuffer(indirectBuffer);
shapeData.setupBatch(batch); shapeData.setupBatch(batch);
batch.multiDrawIndexedIndirect(TYPE_COUNT, gpu::TRIANGLES); batch.multiDrawIndexedIndirect(TYPE_COUNT, gpu::TRIANGLES);
batch._glUniform1i(_instanceLocation, 0);
} }
#else #else
batch.setViewTransform(camera); batch.setViewTransform(camera);

View file

@ -19,8 +19,6 @@
<$declareStandardTransform()$> <$declareStandardTransform()$>
// the interpolated normal // the interpolated normal
uniform bool Instanced = false;
out vec3 _normal; out vec3 _normal;
out vec3 _color; out vec3 _color;
out vec2 _texCoord0; out vec2 _texCoord0;
@ -32,12 +30,7 @@ void main(void) {
// standard transform // standard transform
TransformCamera cam = getTransformCamera(); TransformCamera cam = getTransformCamera();
TransformObject obj = getTransformObject(); TransformObject obj = getTransformObject();
if (Instanced) {
<$transformInstancedModelToClipPos(cam, obj, inPosition, gl_Position)$>
<$transformInstancedModelToEyeDir(cam, obj, inNormal.xyz, _normal)$>
} else {
<$transformModelToClipPos(cam, obj, inPosition, gl_Position)$> <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$>
<$transformModelToEyeDir(cam, obj, inNormal.xyz, _normal)$> <$transformModelToEyeDir(cam, obj, inNormal.xyz, _normal)$>
}
_normal = vec3(0.0, 0.0, 1.0); _normal = vec3(0.0, 0.0, 1.0);
} }