Introduce the gpu::Batch for the full Model::render call

This commit is contained in:
Sam Gateau 2014-10-21 17:46:41 -07:00
parent f090a1868c
commit 821284edfd
4 changed files with 111 additions and 85 deletions

View file

@ -14,16 +14,15 @@
#define ADD_COMMAND(call) _commands.push_back(COMMAND_##call); _commandCalls.push_back(&gpu::Batch::do_##call); _commandOffsets.push_back(_params.size()); #define ADD_COMMAND(call) _commands.push_back(COMMAND_##call); _commandCalls.push_back(&gpu::Batch::do_##call); _commandOffsets.push_back(_params.size());
//#define DO_IT_NOW(call, offset) uint32 __param = _params.size() - (offset); do##call(__param);
//#define DO_IT_NOW(call, offset) uint32 __param = _commandOffsets.back(); CommandCall call = _commandCalls.back(); (this->*(call))(__param);
//#define DO_IT_NOW(call, offset) runLastCommand(); //#define DO_IT_NOW(call, offset) runLastCommand();
//#define DO_IT_NOW(call, offset) uint32 __param = _params.size() - (offset); runCommand(_commands.size() -1);// do##call(__param);
#define DO_IT_NOW(call, offset) #define DO_IT_NOW(call, offset)
using namespace gpu; using namespace gpu;
Batch::Batch() : Batch::Batch() :
_commands(), _commands(),
_commandCalls(),
_commandOffsets(),
_params(), _params(),
_resources(), _resources(),
_data(){ _data(){
@ -34,6 +33,8 @@ Batch::~Batch() {
void Batch::clear() { void Batch::clear() {
_commands.clear(); _commands.clear();
_commandCalls.clear();
_commandOffsets.clear();
_params.clear(); _params.clear();
_resources.clear(); _resources.clear();
_data.clear(); _data.clear();

View file

@ -31,11 +31,6 @@ typedef int Stamp;
typedef unsigned int uint32; typedef unsigned int uint32;
typedef int int32; typedef int int32;
// TODO: move the backend namespace into dedicated files, for now we keep it close to the gpu objects definition for convenience
namespace backend {
};
enum Primitive { enum Primitive {
PRIMITIVE_POINTS = 0, PRIMITIVE_POINTS = 0,
PRIMITIVE_LINES, PRIMITIVE_LINES,
@ -226,7 +221,6 @@ protected:
Resources _resources; Resources _resources;
Bytes _data; Bytes _data;
uint32 cacheResource(Resource* res); uint32 cacheResource(Resource* res);
uint32 cacheResource(const void* pointer); uint32 cacheResource(const void* pointer);
ResourceCache* editResource(uint32 offset) { ResourceCache* editResource(uint32 offset) {
@ -246,22 +240,11 @@ protected:
uint32 offset = _commandOffsets[index]; uint32 offset = _commandOffsets[index];
CommandCall call = _commandCalls[index]; CommandCall call = _commandCalls[index];
(this->*(call))(offset); (this->*(call))(offset);
uint32 nextOFfset = offset;
GLenum error = glGetError();
if (error) {
error++;
}
} }
void runLastCommand() { void runLastCommand() {
uint32 index = _commands.size() - 1; uint32 index = _commands.size() - 1;
uint32 offset = _commandOffsets[index]; runCommand(index);
/* CommandCall call = _commandCalls[index];
(this->*(call))(offset);
uint32 nextOFfset = offset;
*/
runCommand(_commands[index], offset);
} }
void runCommand(Command com, uint32 offset); void runCommand(Command com, uint32 offset);

View file

@ -28,6 +28,7 @@
#include "gpu/Batch.h" #include "gpu/Batch.h"
#define GLBATCH( call ) batch._##call #define GLBATCH( call ) batch._##call
//#define GLBATCH( call ) call
using namespace std; using namespace std;
@ -433,97 +434,135 @@ bool Model::render(float alpha, RenderMode mode, RenderArgs* args) {
segregateMeshGroups(); segregateMeshGroups();
} }
glEnableClientState(GL_VERTEX_ARRAY); // Let's introduce a gpu::Batch to capture all the calls to the graphics api
glEnableClientState(GL_NORMAL_ARRAY); gpu::Batch batch;
glDisable(GL_COLOR_MATERIAL); GLBATCH(glEnableClientState)(GL_VERTEX_ARRAY);
GLBATCH(glEnableClientState)(GL_NORMAL_ARRAY);
GLBATCH(glDisable)(GL_COLOR_MATERIAL);
if (mode == DIFFUSE_RENDER_MODE || mode == NORMAL_RENDER_MODE) { if (mode == DIFFUSE_RENDER_MODE || mode == NORMAL_RENDER_MODE) {
glDisable(GL_CULL_FACE); GLBATCH(glDisable)(GL_CULL_FACE);
} else { } else {
glEnable(GL_CULL_FACE); GLBATCH(glEnable)(GL_CULL_FACE);
if (mode == SHADOW_RENDER_MODE) { if (mode == SHADOW_RENDER_MODE) {
glCullFace(GL_FRONT); GLBATCH(glCullFace)(GL_FRONT);
} }
} }
// render opaque meshes with alpha testing // render opaque meshes with alpha testing
glDisable(GL_BLEND); GLBATCH(glDisable)(GL_BLEND);
glEnable(GL_ALPHA_TEST); GLBATCH(glEnable)(GL_ALPHA_TEST);
if (mode == SHADOW_RENDER_MODE) { if (mode == SHADOW_RENDER_MODE) {
glAlphaFunc(GL_EQUAL, 0.0f); GLBATCH(glAlphaFunc)(GL_EQUAL, 0.0f);
} }
Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(
/*Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(
mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE, mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE,
mode == DEFAULT_RENDER_MODE || mode == NORMAL_RENDER_MODE, mode == DEFAULT_RENDER_MODE || mode == NORMAL_RENDER_MODE,
mode == DEFAULT_RENDER_MODE); mode == DEFAULT_RENDER_MODE);
*/
{
GLenum buffers[3];
int bufferCount = 0;
if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE) {
buffers[bufferCount++] = GL_COLOR_ATTACHMENT0;
}
if (mode == DEFAULT_RENDER_MODE || mode == NORMAL_RENDER_MODE) {
buffers[bufferCount++] = GL_COLOR_ATTACHMENT1;
}
if (mode == DEFAULT_RENDER_MODE) {
buffers[bufferCount++] = GL_COLOR_ATTACHMENT2;
}
GLBATCH(glDrawBuffers)(bufferCount, buffers);
}
const float DEFAULT_ALPHA_THRESHOLD = 0.5f; const float DEFAULT_ALPHA_THRESHOLD = 0.5f;
//renderMeshes(RenderMode mode, bool translucent, float alphaThreshold, bool hasTangents, bool hasSpecular, book isSkinned, args); //renderMeshes(RenderMode mode, bool translucent, float alphaThreshold, bool hasTangents, bool hasSpecular, book isSkinned, args);
int opaqueMeshPartsRendered = 0; int opaqueMeshPartsRendered = 0;
opaqueMeshPartsRendered += renderMeshes(mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, args); opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, args);
opaqueMeshPartsRendered += renderMeshes(mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, args); opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, args);
opaqueMeshPartsRendered += renderMeshes(mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, args); opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, args);
opaqueMeshPartsRendered += renderMeshes(mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, args); opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, args);
opaqueMeshPartsRendered += renderMeshes(mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, args); opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, args);
opaqueMeshPartsRendered += renderMeshes(mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, args); opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, args);
opaqueMeshPartsRendered += renderMeshes(mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, args); opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, args);
opaqueMeshPartsRendered += renderMeshes(mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, args); opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, args);
// render translucent meshes afterwards // render translucent meshes afterwards
Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(false, true, true); //Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(false, true, true);
{
GLenum buffers[2];
int bufferCount = 0;
buffers[bufferCount++] = GL_COLOR_ATTACHMENT1;
buffers[bufferCount++] = GL_COLOR_ATTACHMENT2;
GLBATCH(glDrawBuffers)(bufferCount, buffers);
}
int translucentMeshPartsRendered = 0; int translucentMeshPartsRendered = 0;
const float MOSTLY_OPAQUE_THRESHOLD = 0.75f; const float MOSTLY_OPAQUE_THRESHOLD = 0.75f;
translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, args); translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, args);
translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, args); translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, args);
translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, args); translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, args);
translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, args); translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, args);
translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, false, args); translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, false, args);
translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, true, args); translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, true, args);
translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_OPAQUE_THRESHOLD, true, true, false, args); translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, true, false, args);
translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, true, args); translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, true, args);
glDisable(GL_ALPHA_TEST); GLBATCH(glDisable)(GL_ALPHA_TEST);
glEnable(GL_BLEND); GLBATCH(glEnable)(GL_BLEND);
glDepthMask(false); GLBATCH(glDepthMask)(false);
glDepthFunc(GL_LEQUAL); GLBATCH(glDepthFunc)(GL_LEQUAL);
Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true);
//Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true);
{
GLenum buffers[1];
int bufferCount = 0;
buffers[bufferCount++] = GL_COLOR_ATTACHMENT0;
GLBATCH(glDrawBuffers)(bufferCount, buffers);
}
if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE) { if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE) {
const float MOSTLY_TRANSPARENT_THRESHOLD = 0.0f; const float MOSTLY_TRANSPARENT_THRESHOLD = 0.0f;
translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, args); translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, args);
translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, args); translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, args);
translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, args); translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, args);
translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, args); translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, args);
translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, false, args); translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, false, args);
translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, true, args); translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, true, args);
translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, true, false, args); translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, true, false, args);
translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, true, args); translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, true, args);
} }
glDepthMask(true); GLBATCH(glDepthMask)(true);
glDepthFunc(GL_LESS); GLBATCH(glDepthFunc)(GL_LESS);
glDisable(GL_CULL_FACE); GLBATCH(glDisable)(GL_CULL_FACE);
if (mode == SHADOW_RENDER_MODE) { if (mode == SHADOW_RENDER_MODE) {
glCullFace(GL_BACK); GLBATCH(glCullFace)(GL_BACK);
} }
// deactivate vertex arrays after drawing // deactivate vertex arrays after drawing
glDisableClientState(GL_NORMAL_ARRAY); GLBATCH(glDisableClientState)(GL_NORMAL_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY); GLBATCH(glDisableClientState)(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY); GLBATCH(glDisableClientState)(GL_TEXTURE_COORD_ARRAY);
// bind with 0 to switch back to normal operation // bind with 0 to switch back to normal operation
glBindBuffer(GL_ARRAY_BUFFER, 0); GLBATCH(glBindBuffer)(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); GLBATCH(glBindBuffer)(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindTexture(GL_TEXTURE_2D, 0); GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0);
// Render!
::gpu::backend::renderBatch(batch);
batch.clear();
// restore all the default material settings // restore all the default material settings
Application::getInstance()->setupWorldLight(); Application::getInstance()->setupWorldLight();
@ -1509,7 +1548,7 @@ void Model::segregateMeshGroups() {
_meshGroupsKnown = true; _meshGroupsKnown = true;
} }
int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold, int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold,
bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args) { bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args) {
bool dontCullOutOfViewMeshParts = Menu::getInstance()->isOptionChecked(MenuOption::DontCullOutOfViewMeshParts); bool dontCullOutOfViewMeshParts = Menu::getInstance()->isOptionChecked(MenuOption::DontCullOutOfViewMeshParts);
@ -1611,7 +1650,7 @@ int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold,
Locations* activeLocations = locations; Locations* activeLocations = locations;
// Try to use the Batch // Try to use the Batch
gpu::Batch batch; //gpu::Batch batch;
/*if (isSkinned) { /*if (isSkinned) {
skinProgram->bind(); skinProgram->bind();
@ -1868,7 +1907,6 @@ int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold,
//activeProgram->release(); //activeProgram->release();
GLBATCH(glUseProgram)(0); GLBATCH(glUseProgram)(0);
::gpu::backend::renderBatch(batch);
return meshPartsRendered; return meshPartsRendered;
} }

View file

@ -36,6 +36,10 @@ class ViewFrustum;
typedef QSharedPointer<AnimationHandle> AnimationHandlePointer; typedef QSharedPointer<AnimationHandle> AnimationHandlePointer;
typedef QWeakPointer<AnimationHandle> WeakAnimationHandlePointer; typedef QWeakPointer<AnimationHandle> WeakAnimationHandlePointer;
namespace gpu {
class Batch;
}
/// A generic 3D model displaying geometry loaded from a URL. /// A generic 3D model displaying geometry loaded from a URL.
class Model : public QObject, public PhysicsEntity { class Model : public QObject, public PhysicsEntity {
Q_OBJECT Q_OBJECT
@ -252,7 +256,7 @@ private:
void applyNextGeometry(); void applyNextGeometry();
void deleteGeometry(); void deleteGeometry();
int renderMeshes(RenderMode mode, bool translucent, float alphaThreshold, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args = NULL); int renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args = NULL);
QVector<JointState> createJointStates(const FBXGeometry& geometry); QVector<JointState> createJointStates(const FBXGeometry& geometry);
void initJointTransforms(); void initJointTransforms();