Merge pull request #5168 from samcake/daft

Improving the rendering job architecture
This commit is contained in:
Clément Brisset 2015-06-19 18:00:39 +02:00
commit 5192796851
13 changed files with 451 additions and 507 deletions

View file

@ -10,25 +10,7 @@
Script.include("cookies.js"); Script.include("cookies.js");
var panel = new Panel(10, 400); var panel = new Panel(10, 800);
panel.newCheckbox("Enable Cull Opaque",
function(value) { Scene.setEngineCullOpaque((value != 0)); },
function() { return Scene.doEngineCullOpaque(); },
function(value) { return (value); }
);
panel.newCheckbox("Enable Sort Opaque",
function(value) { Scene.setEngineSortOpaque((value != 0)); },
function() { return Scene.doEngineSortOpaque(); },
function(value) { return (value); }
);
panel.newCheckbox("Enable Render Opaque",
function(value) { Scene.setEngineRenderOpaque((value != 0)); },
function() { return Scene.doEngineRenderOpaque(); },
function(value) { return (value); }
);
panel.newSlider("Num Feed Opaques", 0, 1000, panel.newSlider("Num Feed Opaques", 0, 1000,
function(value) { }, function(value) { },
@ -48,24 +30,6 @@ panel.newSlider("Max Drawn Opaques", -1, 1000,
function(value) { return (value); } function(value) { return (value); }
); );
panel.newCheckbox("Enable Cull Transparent",
function(value) { Scene.setEngineCullTransparent((value != 0)); },
function() { return Scene.doEngineCullTransparent(); },
function(value) { return (value); }
);
panel.newCheckbox("Enable Sort Transparent",
function(value) { Scene.setEngineSortTransparent((value != 0)); },
function() { return Scene.doEngineSortTransparent(); },
function(value) { return (value); }
);
panel.newCheckbox("Enable Render Transparent",
function(value) { Scene.setEngineRenderTransparent((value != 0)); },
function() { return Scene.doEngineRenderTransparent(); },
function(value) { return (value); }
);
panel.newSlider("Num Feed Transparents", 0, 100, panel.newSlider("Num Feed Transparents", 0, 100,
function(value) { }, function(value) { },
function() { return Scene.getEngineNumFeedTransparentItems(); }, function() { return Scene.getEngineNumFeedTransparentItems(); },
@ -84,6 +48,24 @@ panel.newSlider("Max Drawn Transparents", -1, 100,
function(value) { return (value); } function(value) { return (value); }
); );
panel.newSlider("Num Feed Overlay3Ds", 0, 100,
function(value) { },
function() { return Scene.getEngineNumFeedOverlay3DItems(); },
function(value) { return (value); }
);
panel.newSlider("Num Drawn Overlay3Ds", 0, 100,
function(value) { },
function() { return Scene.getEngineNumDrawnOverlay3DItems(); },
function(value) { return (value); }
);
panel.newSlider("Max Drawn Overlay3Ds", -1, 100,
function(value) { Scene.setEngineMaxDrawnOverlay3DItems(value); },
function() { return Scene.getEngineMaxDrawnOverlay3DItems(); },
function(value) { return (value); }
);
var tickTackPeriod = 500; var tickTackPeriod = 500;
function updateCounters() { function updateCounters() {
@ -91,6 +73,8 @@ function updateCounters() {
panel.set("Num Drawn Opaques", panel.get("Num Drawn Opaques")); panel.set("Num Drawn Opaques", panel.get("Num Drawn Opaques"));
panel.set("Num Feed Transparents", panel.get("Num Feed Transparents")); panel.set("Num Feed Transparents", panel.get("Num Feed Transparents"));
panel.set("Num Drawn Transparents", panel.get("Num Drawn Transparents")); panel.set("Num Drawn Transparents", panel.get("Num Drawn Transparents"));
panel.set("Num Feed Overlay3Ds", panel.get("Num Feed Overlay3Ds"));
panel.set("Num Drawn Overlay3Ds", panel.get("Num Drawn Overlay3Ds"));
} }
Script.setInterval(updateCounters, tickTackPeriod); Script.setInterval(updateCounters, tickTackPeriod);

View file

@ -3541,6 +3541,7 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se
renderContext._maxDrawnOpaqueItems = sceneInterface->getEngineMaxDrawnOpaqueItems(); renderContext._maxDrawnOpaqueItems = sceneInterface->getEngineMaxDrawnOpaqueItems();
renderContext._maxDrawnTransparentItems = sceneInterface->getEngineMaxDrawnTransparentItems(); renderContext._maxDrawnTransparentItems = sceneInterface->getEngineMaxDrawnTransparentItems();
renderContext._maxDrawnOverlay3DItems = sceneInterface->getEngineMaxDrawnOverlay3DItems();
renderArgs->_shouldRender = LODManager::shouldRender; renderArgs->_shouldRender = LODManager::shouldRender;
@ -3558,6 +3559,8 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se
sceneInterface->setEngineFeedTransparentItems(engineRC->_numFeedTransparentItems); sceneInterface->setEngineFeedTransparentItems(engineRC->_numFeedTransparentItems);
sceneInterface->setEngineDrawnTransparentItems(engineRC->_numDrawnTransparentItems); sceneInterface->setEngineDrawnTransparentItems(engineRC->_numDrawnTransparentItems);
sceneInterface->setEngineFeedOverlay3DItems(engineRC->_numFeedOverlay3DItems);
sceneInterface->setEngineDrawnOverlay3DItems(engineRC->_numDrawnOverlay3DItems);
} }
//Render the sixense lasers //Render the sixense lasers
if (Menu::getInstance()->isOptionChecked(MenuOption::SixenseLasers)) { if (Menu::getInstance()->isOptionChecked(MenuOption::SixenseLasers)) {

View file

@ -506,7 +506,7 @@ FBXNode parseFBX(QIODevice* device) {
QVector<glm::vec4> createVec4Vector(const QVector<double>& doubleVector) { QVector<glm::vec4> createVec4Vector(const QVector<double>& doubleVector) {
QVector<glm::vec4> values; QVector<glm::vec4> values;
for (const double* it = doubleVector.constData(), *end = it + (doubleVector.size() / 4 * 4); it != end; ) { for (const double* it = doubleVector.constData(), *end = it + ((doubleVector.size() / 4) * 4); it != end; ) {
float x = *it++; float x = *it++;
float y = *it++; float y = *it++;
float z = *it++; float z = *it++;
@ -516,9 +516,27 @@ QVector<glm::vec4> createVec4Vector(const QVector<double>& doubleVector) {
return values; return values;
} }
QVector<glm::vec4> createVec4VectorRGBA(const QVector<double>& doubleVector, glm::vec4& average) {
QVector<glm::vec4> values;
for (const double* it = doubleVector.constData(), *end = it + ((doubleVector.size() / 4) * 4); it != end; ) {
float x = *it++;
float y = *it++;
float z = *it++;
float w = *it++;
auto val = glm::vec4(x, y, z, w);
values.append(val);
average += val;
}
if (!values.isEmpty()) {
average *= (1.0f / float(values.size()));
}
return values;
}
QVector<glm::vec3> createVec3Vector(const QVector<double>& doubleVector) { QVector<glm::vec3> createVec3Vector(const QVector<double>& doubleVector) {
QVector<glm::vec3> values; QVector<glm::vec3> values;
for (const double* it = doubleVector.constData(), *end = it + (doubleVector.size() / 3 * 3); it != end; ) { for (const double* it = doubleVector.constData(), *end = it + ((doubleVector.size() / 3) * 3); it != end; ) {
float x = *it++; float x = *it++;
float y = *it++; float y = *it++;
float z = *it++; float z = *it++;
@ -529,7 +547,7 @@ QVector<glm::vec3> createVec3Vector(const QVector<double>& doubleVector) {
QVector<glm::vec2> createVec2Vector(const QVector<double>& doubleVector) { QVector<glm::vec2> createVec2Vector(const QVector<double>& doubleVector) {
QVector<glm::vec2> values; QVector<glm::vec2> values;
for (const double* it = doubleVector.constData(), *end = it + (doubleVector.size() / 2 * 2); it != end; ) { for (const double* it = doubleVector.constData(), *end = it + ((doubleVector.size() / 2) * 2); it != end; ) {
float s = *it++; float s = *it++;
float t = *it++; float t = *it++;
values.append(glm::vec2(s, -t)); values.append(glm::vec2(s, -t));
@ -799,6 +817,7 @@ public:
QVector<int> normalIndices; QVector<int> normalIndices;
bool colorsByVertex; bool colorsByVertex;
glm::vec4 averageColor{1.0f, 1.0f, 1.0f, 1.0f};
QVector<glm::vec4> colors; QVector<glm::vec4> colors;
QVector<int> colorIndices; QVector<int> colorIndices;
@ -940,8 +959,7 @@ ExtractedMesh extractMesh(const FBXNode& object, unsigned int& meshIndex) {
bool indexToDirect = false; bool indexToDirect = false;
foreach (const FBXNode& subdata, child.children) { foreach (const FBXNode& subdata, child.children) {
if (subdata.name == "Colors") { if (subdata.name == "Colors") {
data.colors = createVec4Vector(getDoubleVector(subdata)); data.colors = createVec4VectorRGBA(getDoubleVector(subdata), data.averageColor);
} else if (subdata.name == "ColorsIndex") { } else if (subdata.name == "ColorsIndex") {
data.colorIndices = getIntVector(subdata); data.colorIndices = getIntVector(subdata);
@ -957,6 +975,19 @@ ExtractedMesh extractMesh(const FBXNode& object, unsigned int& meshIndex) {
data.colorsByVertex = true; data.colorsByVertex = true;
} }
#if defined(FBXREADER_KILL_BLACK_COLOR_ATTRIBUTE)
// Potential feature where we decide to kill the color attribute is to dark?
// Tested with the model:
// https://hifi-public.s3.amazonaws.com/ryan/gardenLight2.fbx
// let's check if we did have true data ?
if (glm::all(glm::lessThanEqual(data.averageColor, glm::vec4(0.09f)))) {
data.colors.clear();
data.colorIndices.clear();
data.colorsByVertex = false;
qCDebug(modelformat) << "LayerElementColor has an average value of 0.0f... let's forget it.";
}
#endif
} else if (child.name == "LayerElementUV") { } else if (child.name == "LayerElementUV") {
if (child.properties.at(0).toInt() == 0) { if (child.properties.at(0).toInt() == 0) {
AttributeData attrib; AttributeData attrib;

View file

@ -210,7 +210,7 @@ void DeferredLightingEffect::addSpotLight(const glm::vec3& position, float radiu
} }
} }
void DeferredLightingEffect::prepare() { void DeferredLightingEffect::prepare(RenderArgs* args) {
// clear the normal and specular buffers // clear the normal and specular buffers
auto textureCache = DependencyManager::get<TextureCache>(); auto textureCache = DependencyManager::get<TextureCache>();
textureCache->setPrimaryDrawBuffers(false, true, false); textureCache->setPrimaryDrawBuffers(false, true, false);
@ -224,7 +224,7 @@ void DeferredLightingEffect::prepare() {
textureCache->setPrimaryDrawBuffers(true, false, false); textureCache->setPrimaryDrawBuffers(true, false, false);
} }
void DeferredLightingEffect::render() { void DeferredLightingEffect::render(RenderArgs* args) {
// perform deferred lighting, rendering to free fbo // perform deferred lighting, rendering to free fbo
glDisable(GL_BLEND); glDisable(GL_BLEND);
glDisable(GL_LIGHTING); glDisable(GL_LIGHTING);

View file

@ -66,8 +66,8 @@ public:
void addSpotLight(const glm::vec3& position, float radius, const glm::vec3& color = glm::vec3(1.0f, 1.0f, 1.0f), void addSpotLight(const glm::vec3& position, float radius, const glm::vec3& color = glm::vec3(1.0f, 1.0f, 1.0f),
float intensity = 0.5f, const glm::quat& orientation = glm::quat(), float exponent = 0.0f, float cutoff = PI); float intensity = 0.5f, const glm::quat& orientation = glm::quat(), float exponent = 0.0f, float cutoff = PI);
void prepare(); void prepare(RenderArgs* args);
void render(); void render(RenderArgs* args);
void copyBack(RenderArgs* args); void copyBack(RenderArgs* args);
void setupTransparent(RenderArgs* args, int lightBufferUnit); void setupTransparent(RenderArgs* args, int lightBufferUnit);

View file

@ -1804,6 +1804,7 @@ AABox Model::getPartBounds(int meshIndex, int partIndex) {
} }
void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool translucent) { void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool translucent) {
PerformanceTimer perfTimer("Model::renderPart");
if (!_readyWhenAdded) { if (!_readyWhenAdded) {
return; // bail asap return; // bail asap
} }

View file

@ -24,37 +24,49 @@
using namespace render; using namespace render;
template <> void render::jobRun(const PrepareDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { void PrepareDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
PerformanceTimer perfTimer("PrepareDeferred"); DependencyManager::get<DeferredLightingEffect>()->prepare(renderContext->args);
DependencyManager::get<DeferredLightingEffect>()->prepare();
} }
template <> void render::jobRun(const RenderDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { void RenderDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
PerformanceTimer perfTimer("RenderDeferred"); DependencyManager::get<DeferredLightingEffect>()->render(renderContext->args);
DependencyManager::get<DeferredLightingEffect>()->render();
// renderContext->args->_context->syncCache();
} }
template <> void render::jobRun(const ResolveDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { void ResolveDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
PerformanceTimer perfTimer("ResolveDeferred"); PerformanceTimer perfTimer("ResolveDeferred");
DependencyManager::get<DeferredLightingEffect>()->copyBack(renderContext->args); DependencyManager::get<DeferredLightingEffect>()->copyBack(renderContext->args);
renderContext->args->_context->syncCache();
} }
RenderDeferredTask::RenderDeferredTask() : Task() { RenderDeferredTask::RenderDeferredTask() : Task() {
_jobs.push_back(Job(PrepareDeferred())); _jobs.push_back(Job(new PrepareDeferred::JobModel("PrepareDeferred")));
_jobs.push_back(Job(DrawBackground())); _jobs.push_back(Job(new DrawBackground::JobModel("DrawBackground")));
_jobs.push_back(Job(DrawOpaqueDeferred())); _jobs.push_back(Job(new FetchItems::JobModel("FetchOpaque",
_jobs.push_back(Job(DrawLight())); FetchItems(
_jobs.push_back(Job(ResetGLState())); [] (const RenderContextPointer& context, int count) {
_jobs.push_back(Job(RenderDeferred())); context->_numFeedOpaqueItems = count;
_jobs.push_back(Job(ResolveDeferred())); }
_jobs.push_back(Job(DrawTransparentDeferred())); )
_jobs.push_back(Job(DrawOverlay3D())); )));
_jobs.push_back(Job(ResetGLState())); _jobs.push_back(Job(new CullItems::JobModel("CullOpaque", _jobs.back().getOutput())));
_jobs.push_back(Job(new DepthSortItems::JobModel("DepthSortOpaque", _jobs.back().getOutput())));
_jobs.push_back(Job(new DrawOpaqueDeferred::JobModel("DrawOpaqueDeferred", _jobs.back().getOutput())));
_jobs.push_back(Job(new DrawLight::JobModel("DrawLight")));
_jobs.push_back(Job(new ResetGLState::JobModel()));
_jobs.push_back(Job(new RenderDeferred::JobModel("RenderDeferred")));
_jobs.push_back(Job(new ResolveDeferred::JobModel("ResolveDeferred")));
_jobs.push_back(Job(new FetchItems::JobModel("FetchTransparent",
FetchItems(
ItemFilter::Builder::transparentShape().withoutLayered(),
[] (const RenderContextPointer& context, int count) {
context->_numFeedTransparentItems = count;
}
)
)));
_jobs.push_back(Job(new CullItems::JobModel("CullTransparent", _jobs.back().getOutput())));
_jobs.push_back(Job(new DepthSortItems::JobModel("DepthSortTransparent", _jobs.back().getOutput(), DepthSortItems(false))));
_jobs.push_back(Job(new DrawTransparentDeferred::JobModel("TransparentDeferred", _jobs.back().getOutput())));
_jobs.push_back(Job(new DrawOverlay3D::JobModel("DrawOverlay3D")));
_jobs.push_back(Job(new ResetGLState::JobModel()));
} }
RenderDeferredTask::~RenderDeferredTask() { RenderDeferredTask::~RenderDeferredTask() {
@ -80,61 +92,16 @@ void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const Rend
} }
}; };
void DrawOpaqueDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems) {
template <> void render::jobRun(const DrawOpaqueDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
PerformanceTimer perfTimer("DrawOpaqueDeferred");
assert(renderContext->args); assert(renderContext->args);
assert(renderContext->args->_viewFrustum); assert(renderContext->args->_viewFrustum);
// render opaques
auto& scene = sceneContext->_scene;
auto& items = scene->getMasterBucket().at(ItemFilter::Builder::opaqueShape().withoutLayered());
auto& renderDetails = renderContext->args->_details;
ItemIDsBounds inItems;
inItems.reserve(items.size());
for (auto id : items) {
inItems.emplace_back(ItemIDAndBounds(id));
}
ItemIDsBounds& renderedItems = inItems;
renderContext->_numFeedOpaqueItems = renderedItems.size();
ItemIDsBounds culledItems;
culledItems.reserve(inItems.size());
if (renderContext->_cullOpaque) {
renderDetails.pointTo(RenderDetails::OPAQUE_ITEM);
cullItems(sceneContext, renderContext, renderedItems, culledItems);
renderDetails.pointTo(RenderDetails::OTHER_ITEM);
renderedItems = culledItems;
}
renderContext->_numDrawnOpaqueItems = renderedItems.size();
ItemIDsBounds sortedItems;
sortedItems.reserve(culledItems.size());
if (renderContext->_sortOpaque) {
depthSortItems(sceneContext, renderContext, true, renderedItems, sortedItems); // Sort Front to back opaque items!
renderedItems = sortedItems;
}
// ItemIDsBounds sortedItems;
/* ItemMaterialBucketMap stateSortedItems;
stateSortedItems.allocateStandardMaterialBuckets();
if (true) {
for (auto& itemIDAndBound : renderedItems) {
stateSortedItems.insert(itemIDAndBound.id, scene->getItem(itemIDAndBound.id).getMaterialKey());
}
}
*/
if (renderContext->_renderOpaque) {
RenderArgs* args = renderContext->args; RenderArgs* args = renderContext->args;
gpu::Batch batch; gpu::Batch batch;
args->_batch = &batch; args->_batch = &batch;
renderContext->_numDrawnOpaqueItems = inItems.size();
glm::mat4 projMat; glm::mat4 projMat;
Transform viewMat; Transform viewMat;
args->_viewFrustum->evalProjectionMatrix(projMat); args->_viewFrustum->evalProjectionMatrix(projMat);
@ -154,56 +121,25 @@ template <> void render::jobRun(const DrawOpaqueDeferred& job, const SceneContex
batch._glDrawBuffers(bufferCount, buffers); batch._glDrawBuffers(bufferCount, buffers);
} }
renderItems(sceneContext, renderContext, renderedItems, renderContext->_maxDrawnOpaqueItems); renderItems(sceneContext, renderContext, inItems, renderContext->_maxDrawnOpaqueItems);
// Before rendering the batch make sure we re in sync with gl state
args->_context->syncCache();
renderContext->args->_context->syncCache();
args->_context->render((*args->_batch)); args->_context->render((*args->_batch));
args->_batch = nullptr; args->_batch = nullptr;
}
} }
void DrawTransparentDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems) {
template <> void render::jobRun(const DrawTransparentDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
PerformanceTimer perfTimer("DrawTransparentDeferred");
assert(renderContext->args); assert(renderContext->args);
assert(renderContext->args->_viewFrustum); assert(renderContext->args->_viewFrustum);
// render transparents
auto& scene = sceneContext->_scene;
auto& items = scene->getMasterBucket().at(ItemFilter::Builder::transparentShape().withoutLayered());
auto& renderDetails = renderContext->args->_details; auto& renderDetails = renderContext->args->_details;
ItemIDsBounds inItems;
inItems.reserve(items.size());
for (auto id : items) {
inItems.push_back(id);
}
ItemIDsBounds& renderedItems = inItems;
renderContext->_numFeedTransparentItems = renderedItems.size();
ItemIDsBounds culledItems;
if (renderContext->_cullTransparent) {
renderDetails.pointTo(RenderDetails::TRANSLUCENT_ITEM);
cullItems(sceneContext, renderContext, inItems, culledItems);
renderDetails.pointTo(RenderDetails::OTHER_ITEM);
renderedItems = culledItems;
}
renderContext->_numDrawnTransparentItems = renderedItems.size();
ItemIDsBounds sortedItems;
if (renderContext->_sortTransparent) {
depthSortItems(sceneContext, renderContext, false, renderedItems, sortedItems); // Sort Back to front transparent items!
renderedItems = sortedItems;
}
if (renderContext->_renderTransparent) {
RenderArgs* args = renderContext->args; RenderArgs* args = renderContext->args;
gpu::Batch batch; gpu::Batch batch;
args->_batch = &batch; args->_batch = &batch;
renderContext->_numDrawnTransparentItems = inItems.size();
glm::mat4 projMat; glm::mat4 projMat;
Transform viewMat; Transform viewMat;
@ -214,7 +150,6 @@ template <> void render::jobRun(const DrawTransparentDeferred& job, const SceneC
} }
batch.setProjectionTransform(projMat); batch.setProjectionTransform(projMat);
batch.setViewTransform(viewMat); batch.setViewTransform(viewMat);
const float TRANSPARENT_ALPHA_THRESHOLD = 0.0f; const float TRANSPARENT_ALPHA_THRESHOLD = 0.0f;
{ {
@ -226,7 +161,7 @@ template <> void render::jobRun(const DrawTransparentDeferred& job, const SceneC
} }
renderItems(sceneContext, renderContext, renderedItems, renderContext->_maxDrawnTransparentItems); renderItems(sceneContext, renderContext, inItems, renderContext->_maxDrawnTransparentItems);
// Before rendering the batch make sure we re in sync with gl state // Before rendering the batch make sure we re in sync with gl state
args->_context->syncCache(); args->_context->syncCache();
@ -234,8 +169,7 @@ template <> void render::jobRun(const DrawTransparentDeferred& job, const SceneC
args->_batch = nullptr; args->_batch = nullptr;
// reset blend function to standard... // reset blend function to standard...
// glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE);
}
} }
const gpu::PipelinePointer& DrawOverlay3D::getOpaquePipeline() const { const gpu::PipelinePointer& DrawOverlay3D::getOpaquePipeline() const {
@ -253,8 +187,7 @@ const gpu::PipelinePointer& DrawOverlay3D::getOpaquePipeline() const {
return _opaquePipeline; return _opaquePipeline;
} }
template <> void render::jobRun(const DrawOverlay3D& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
PerformanceTimer perfTimer("DrawOverlay3D");
assert(renderContext->args); assert(renderContext->args);
assert(renderContext->args->_viewFrustum); assert(renderContext->args->_viewFrustum);
@ -271,13 +204,14 @@ template <> void render::jobRun(const DrawOverlay3D& job, const SceneContextPoin
inItems.emplace_back(id); inItems.emplace_back(id);
} }
} }
renderContext->_numFeedOverlay3DItems = inItems.size();
renderContext->_numDrawnOverlay3DItems = inItems.size();
RenderArgs* args = renderContext->args; RenderArgs* args = renderContext->args;
gpu::Batch batch; gpu::Batch batch;
args->_batch = &batch; args->_batch = &batch;
args->_whiteTexture = DependencyManager::get<TextureCache>()->getWhiteTexture(); args->_whiteTexture = DependencyManager::get<TextureCache>()->getWhiteTexture();
glm::mat4 projMat; glm::mat4 projMat;
Transform viewMat; Transform viewMat;
args->_viewFrustum->evalProjectionMatrix(projMat); args->_viewFrustum->evalProjectionMatrix(projMat);
@ -287,12 +221,13 @@ template <> void render::jobRun(const DrawOverlay3D& job, const SceneContextPoin
} }
batch.setProjectionTransform(projMat); batch.setProjectionTransform(projMat);
batch.setViewTransform(viewMat); batch.setViewTransform(viewMat);
batch.setPipeline(job.getOpaquePipeline());
batch.setPipeline(getOpaquePipeline());
batch.setUniformTexture(0, args->_whiteTexture); batch.setUniformTexture(0, args->_whiteTexture);
if (!inItems.empty()) { if (!inItems.empty()) {
batch.clearFramebuffer(gpu::Framebuffer::BUFFER_DEPTH, glm::vec4(), 1.f, 0); batch.clearFramebuffer(gpu::Framebuffer::BUFFER_DEPTH, glm::vec4(), 1.f, 0);
renderItems(sceneContext, renderContext, inItems); renderItems(sceneContext, renderContext, inItems, renderContext->_maxDrawnOverlay3DItems);
} }
// Before rendering the batch make sure we re in sync with gl state // Before rendering the batch make sure we re in sync with gl state
@ -301,3 +236,4 @@ template <> void render::jobRun(const DrawOverlay3D& job, const SceneContextPoin
args->_batch = nullptr; args->_batch = nullptr;
args->_whiteTexture.reset(); args->_whiteTexture.reset();
} }

View file

@ -18,48 +18,49 @@
class PrepareDeferred { class PrepareDeferred {
public: public:
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
typedef render::Job::Model<PrepareDeferred> JobModel;
}; };
namespace render {
template <> void jobRun(const PrepareDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext);
}
class RenderDeferred { class RenderDeferred {
public: public:
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
typedef render::Job::Model<RenderDeferred> JobModel;
}; };
namespace render {
template <> void jobRun(const RenderDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext);
}
class ResolveDeferred { class ResolveDeferred {
public: public:
}; void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
namespace render {
template <> void jobRun(const ResolveDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext);
}
typedef render::Job::Model<ResolveDeferred> JobModel;
};
class DrawOpaqueDeferred { class DrawOpaqueDeferred {
public: public:
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const render::ItemIDsBounds& inItems);
typedef render::Job::ModelI<DrawOpaqueDeferred, render::ItemIDsBounds> JobModel;
}; };
namespace render {
template <> void jobRun(const DrawOpaqueDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext);
}
class DrawTransparentDeferred { class DrawTransparentDeferred {
public: public:
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const render::ItemIDsBounds& inItems);
typedef render::Job::ModelI<DrawTransparentDeferred, render::ItemIDsBounds> JobModel;
}; };
namespace render {
template <> void jobRun(const DrawTransparentDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext);
}
class DrawOverlay3D { class DrawOverlay3D {
mutable gpu::PipelinePointer _opaquePipeline; //lazy evaluation hence mutable mutable gpu::PipelinePointer _opaquePipeline; //lazy evaluation hence mutable
public: public:
const gpu::PipelinePointer& getOpaquePipeline() const; const gpu::PipelinePointer& getOpaquePipeline() const;
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
typedef render::Job::Model<DrawOverlay3D> JobModel;
}; };
namespace render {
template <> void jobRun(const DrawOverlay3D& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext);
}
class RenderDeferredTask : public render::Task { class RenderDeferredTask : public render::Task {
public: public:

View file

@ -25,11 +25,6 @@
using namespace render; using namespace render;
DrawSceneTask::DrawSceneTask() : Task() { DrawSceneTask::DrawSceneTask() : Task() {
_jobs.push_back(Job(DrawOpaque()));
_jobs.push_back(Job(DrawLight()));
_jobs.push_back(Job(DrawTransparent()));
_jobs.push_back(Job(ResetGLState()));
} }
DrawSceneTask::~DrawSceneTask() { DrawSceneTask::~DrawSceneTask() {
@ -56,8 +51,11 @@ void DrawSceneTask::run(const SceneContextPointer& sceneContext, const RenderCon
Job::~Job() { Job::~Job() {
} }
void render::cullItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outItems) { void render::cullItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outItems) {
PerformanceTimer perfTimer("cullItems");
assert(renderContext->args); assert(renderContext->args);
assert(renderContext->args->_viewFrustum); assert(renderContext->args->_viewFrustum);
@ -68,17 +66,9 @@ void render::cullItems(const SceneContextPointer& sceneContext, const RenderCont
renderDetails->_considered += inItems.size(); renderDetails->_considered += inItems.size();
// Culling / LOD // Culling / LOD
for (auto itemDetails : inItems) { for (auto item : inItems) {
auto item = scene->getItem(itemDetails.id); if (item.bounds.isNull()) {
AABox bound; outItems.emplace_back(item); // One more Item to render
{
PerformanceTimer perfTimer("getBound");
bound = item.getBound();
}
if (bound.isNull()) {
outItems.emplace_back(ItemIDAndBounds(itemDetails.id)); // One more Item to render
continue; continue;
} }
@ -87,16 +77,16 @@ void render::cullItems(const SceneContextPointer& sceneContext, const RenderCont
bool outOfView; bool outOfView;
{ {
PerformanceTimer perfTimer("boxInFrustum"); PerformanceTimer perfTimer("boxInFrustum");
outOfView = args->_viewFrustum->boxInFrustum(bound) == ViewFrustum::OUTSIDE; outOfView = args->_viewFrustum->boxInFrustum(item.bounds) == ViewFrustum::OUTSIDE;
} }
if (!outOfView) { if (!outOfView) {
bool bigEnoughToRender; bool bigEnoughToRender;
{ {
PerformanceTimer perfTimer("shouldRender"); PerformanceTimer perfTimer("shouldRender");
bigEnoughToRender = (args->_shouldRender) ? args->_shouldRender(args, bound) : true; bigEnoughToRender = (args->_shouldRender) ? args->_shouldRender(args, item.bounds) : true;
} }
if (bigEnoughToRender) { if (bigEnoughToRender) {
outItems.emplace_back(ItemIDAndBounds(itemDetails.id, bound)); // One more Item to render outItems.emplace_back(item); // One more Item to render
} else { } else {
renderDetails->_tooSmall++; renderDetails->_tooSmall++;
} }
@ -107,6 +97,32 @@ void render::cullItems(const SceneContextPointer& sceneContext, const RenderCont
renderDetails->_rendered += outItems.size(); renderDetails->_rendered += outItems.size();
} }
void FetchItems::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, ItemIDsBounds& outItems) {
auto& scene = sceneContext->_scene;
auto& items = scene->getMasterBucket().at(_filter);
auto& renderDetails = renderContext->args->_details;
outItems.clear();
outItems.reserve(items.size());
for (auto id : items) {
auto& item = scene->getItem(id);
outItems.emplace_back(ItemIDAndBounds(id, item.getBound()));
}
if (_probeNumItems) {
_probeNumItems(renderContext, outItems.size());
}
}
void CullItems::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outItems) {
outItems.clear();
outItems.reserve(inItems.size());
cullItems(sceneContext, renderContext, inItems, outItems);
}
struct ItemBound { struct ItemBound {
float _centerDepth = 0.0f; float _centerDepth = 0.0f;
float _nearDepth = 0.0f; float _nearDepth = 0.0f;
@ -130,7 +146,6 @@ struct BackToFrontSort {
}; };
void render::depthSortItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, bool frontToBack, const ItemIDsBounds& inItems, ItemIDsBounds& outItems) { void render::depthSortItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, bool frontToBack, const ItemIDsBounds& inItems, ItemIDsBounds& outItems) {
PerformanceTimer perfTimer("depthSortItems");
assert(renderContext->args); assert(renderContext->args);
assert(renderContext->args->_viewFrustum); assert(renderContext->args->_viewFrustum);
@ -139,6 +154,7 @@ void render::depthSortItems(const SceneContextPointer& sceneContext, const Rende
// Allocate and simply copy // Allocate and simply copy
outItems.clear();
outItems.reserve(inItems.size()); outItems.reserve(inItems.size());
@ -169,8 +185,14 @@ void render::depthSortItems(const SceneContextPointer& sceneContext, const Rende
} }
} }
void DepthSortItems::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outItems) {
outItems.clear();
outItems.reserve(inItems.size());
depthSortItems(sceneContext, renderContext, _frontToBack, inItems, outItems);
}
void render::renderItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, int maxDrawnItems) { void render::renderItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, int maxDrawnItems) {
PerformanceTimer perfTimer("renderItems");
auto& scene = sceneContext->_scene; auto& scene = sceneContext->_scene;
RenderArgs* args = renderContext->args; RenderArgs* args = renderContext->args;
// render // render
@ -183,6 +205,11 @@ void render::renderItems(const SceneContextPointer& sceneContext, const RenderCo
int numItems = 0; int numItems = 0;
for (auto itemDetails : inItems) { for (auto itemDetails : inItems) {
auto item = scene->getItem(itemDetails.id); auto item = scene->getItem(itemDetails.id);
if (numItems + 1 >= maxDrawnItems) {
item.render(args);
return;
}
item.render(args); item.render(args);
numItems++; numItems++;
if (numItems >= maxDrawnItems) { if (numItems >= maxDrawnItems) {
@ -224,8 +251,7 @@ void addClearStateCommands(gpu::Batch& batch) {
// Back to no program // Back to no program
batch._glUseProgram(0); batch._glUseProgram(0);
} }
void ResetGLState::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
template <> void render::jobRun(const ResetGLState& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
gpu::Batch theBatch; gpu::Batch theBatch;
addClearStateCommands(theBatch); addClearStateCommands(theBatch);
@ -233,160 +259,7 @@ template <> void render::jobRun(const ResetGLState& job, const SceneContextPoint
renderContext->args->_context->render(theBatch); renderContext->args->_context->render(theBatch);
} }
template <> void render::jobRun(const DrawOpaque& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { void DrawLight::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
PerformanceTimer perfTimer("DrawOpaque");
assert(renderContext->args);
assert(renderContext->args->_viewFrustum);
// render opaques
auto& scene = sceneContext->_scene;
auto& items = scene->getMasterBucket().at(ItemFilter::Builder::opaqueShape());
auto& renderDetails = renderContext->args->_details;
ItemIDsBounds inItems;
inItems.reserve(items.size());
for (auto id : items) {
inItems.emplace_back(ItemIDAndBounds(id));
}
ItemIDsBounds& renderedItems = inItems;
renderContext->_numFeedOpaqueItems = renderedItems.size();
ItemIDsBounds culledItems;
culledItems.reserve(inItems.size());
if (renderContext->_cullOpaque) {
renderDetails.pointTo(RenderDetails::OPAQUE_ITEM);
cullItems(sceneContext, renderContext, renderedItems, culledItems);
renderDetails.pointTo(RenderDetails::OTHER_ITEM);
renderedItems = culledItems;
}
renderContext->_numDrawnOpaqueItems = renderedItems.size();
ItemIDsBounds sortedItems;
sortedItems.reserve(culledItems.size());
if (renderContext->_sortOpaque) {
depthSortItems(sceneContext, renderContext, true, renderedItems, sortedItems); // Sort Front to back opaque items!
renderedItems = sortedItems;
}
if (renderContext->_renderOpaque) {
RenderArgs* args = renderContext->args;
gpu::Batch batch;
args->_batch = &batch;
glm::mat4 projMat;
Transform viewMat;
args->_viewFrustum->evalProjectionMatrix(projMat);
args->_viewFrustum->evalViewTransform(viewMat);
if (args->_renderMode == RenderArgs::MIRROR_RENDER_MODE) {
viewMat.postScale(glm::vec3(-1.0f, 1.0f, 1.0f));
}
batch.setProjectionTransform(projMat);
batch.setViewTransform(viewMat);
{
GLenum buffers[3];
int bufferCount = 0;
buffers[bufferCount++] = GL_COLOR_ATTACHMENT0;
buffers[bufferCount++] = GL_COLOR_ATTACHMENT1;
buffers[bufferCount++] = GL_COLOR_ATTACHMENT2;
batch._glDrawBuffers(bufferCount, buffers);
}
renderItems(sceneContext, renderContext, renderedItems, renderContext->_maxDrawnOpaqueItems);
args->_context->render((*args->_batch));
args->_batch = nullptr;
}
}
template <> void render::jobRun(const DrawTransparent& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
PerformanceTimer perfTimer("DrawTransparent");
assert(renderContext->args);
assert(renderContext->args->_viewFrustum);
// render transparents
auto& scene = sceneContext->_scene;
auto& items = scene->getMasterBucket().at(ItemFilter::Builder::transparentShape());
auto& renderDetails = renderContext->args->_details;
ItemIDsBounds inItems;
inItems.reserve(items.size());
for (auto id : items) {
inItems.emplace_back(id);
}
ItemIDsBounds& renderedItems = inItems;
renderContext->_numFeedTransparentItems = renderedItems.size();
ItemIDsBounds culledItems;
culledItems.reserve(inItems.size());
if (renderContext->_cullTransparent) {
renderDetails.pointTo(RenderDetails::TRANSLUCENT_ITEM);
cullItems(sceneContext, renderContext, inItems, culledItems);
renderDetails.pointTo(RenderDetails::OTHER_ITEM);
renderedItems = culledItems;
}
renderContext->_numDrawnTransparentItems = renderedItems.size();
ItemIDsBounds sortedItems;
sortedItems.reserve(culledItems.size());
if (renderContext->_sortTransparent) {
depthSortItems(sceneContext, renderContext, false, renderedItems, sortedItems); // Sort Back to front transparent items!
renderedItems = sortedItems;
}
if (renderContext->_renderTransparent) {
RenderArgs* args = renderContext->args;
gpu::Batch batch;
args->_batch = &batch;
glm::mat4 projMat;
Transform viewMat;
args->_viewFrustum->evalProjectionMatrix(projMat);
args->_viewFrustum->evalViewTransform(viewMat);
if (args->_renderMode == RenderArgs::MIRROR_RENDER_MODE) {
viewMat.postScale(glm::vec3(-1.0f, 1.0f, 1.0f));
}
batch.setProjectionTransform(projMat);
batch.setViewTransform(viewMat);
const float MOSTLY_OPAQUE_THRESHOLD = 0.75f;
const float TRANSPARENT_ALPHA_THRESHOLD = 0.0f;
// render translucent meshes afterwards
{
GLenum buffers[2];
int bufferCount = 0;
buffers[bufferCount++] = GL_COLOR_ATTACHMENT1;
buffers[bufferCount++] = GL_COLOR_ATTACHMENT2;
batch._glDrawBuffers(bufferCount, buffers);
args->_alphaThreshold = MOSTLY_OPAQUE_THRESHOLD;
}
renderItems(sceneContext, renderContext, renderedItems, renderContext->_maxDrawnTransparentItems);
{
GLenum buffers[3];
int bufferCount = 0;
buffers[bufferCount++] = GL_COLOR_ATTACHMENT0;
batch._glDrawBuffers(bufferCount, buffers);
args->_alphaThreshold = TRANSPARENT_ALPHA_THRESHOLD;
}
renderItems(sceneContext, renderContext, renderedItems, renderContext->_maxDrawnTransparentItems);
args->_context->render((*args->_batch));
args->_batch = nullptr;
}
}
template <> void render::jobRun(const DrawLight& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
PerformanceTimer perfTimer("DrawLight");
assert(renderContext->args); assert(renderContext->args);
assert(renderContext->args->_viewFrustum); assert(renderContext->args->_viewFrustum);
@ -398,7 +271,8 @@ template <> void render::jobRun(const DrawLight& job, const SceneContextPointer&
ItemIDsBounds inItems; ItemIDsBounds inItems;
inItems.reserve(items.size()); inItems.reserve(items.size());
for (auto id : items) { for (auto id : items) {
inItems.emplace_back(id); auto item = scene->getItem(id);
inItems.emplace_back(ItemIDAndBounds(id, item.getBound()));
} }
ItemIDsBounds culledItems; ItemIDsBounds culledItems;
@ -413,8 +287,7 @@ template <> void render::jobRun(const DrawLight& job, const SceneContextPointer&
args->_batch = nullptr; args->_batch = nullptr;
} }
template <> void render::jobRun(const DrawBackground& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { void DrawBackground::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
PerformanceTimer perfTimer("DrawBackground");
assert(renderContext->args); assert(renderContext->args);
assert(renderContext->args->_viewFrustum); assert(renderContext->args->_viewFrustum);
@ -450,53 +323,6 @@ template <> void render::jobRun(const DrawBackground& job, const SceneContextPoi
args->_context->syncCache(); args->_context->syncCache();
} }
template <> void render::jobRun(const DrawPostLayered& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
PerformanceTimer perfTimer("DrawPostLayered");
assert(renderContext->args);
assert(renderContext->args->_viewFrustum);
// render backgrounds
auto& scene = sceneContext->_scene;
auto& items = scene->getMasterBucket().at(ItemFilter::Builder::opaqueShape().withLayered());
ItemIDsBounds inItems;
inItems.reserve(items.size());
for (auto id : items) {
auto& item = scene->getItem(id);
if (item.getKey().isVisible() && (item.getLayer() > 0)) {
inItems.emplace_back(id);
}
}
if (inItems.empty()) {
return;
}
RenderArgs* args = renderContext->args;
gpu::Batch batch;
args->_batch = &batch;
glm::mat4 projMat;
Transform viewMat;
args->_viewFrustum->evalProjectionMatrix(projMat);
args->_viewFrustum->evalViewTransform(viewMat);
if (args->_renderMode == RenderArgs::MIRROR_RENDER_MODE) {
viewMat.postScale(glm::vec3(-1.0f, 1.0f, 1.0f));
}
batch.setProjectionTransform(projMat);
batch.setViewTransform(viewMat);
batch.clearFramebuffer(gpu::Framebuffer::BUFFER_DEPTH, glm::vec4(), 1.f, 0);
renderItems(sceneContext, renderContext, inItems);
args->_context->render((*args->_batch));
args->_batch = nullptr;
// Force the context sync
args->_context->syncCache();
}
void ItemMaterialBucketMap::insert(const ItemID& id, const model::MaterialKey& key) { void ItemMaterialBucketMap::insert(const ItemID& id, const model::MaterialKey& key) {
// Insert the itemID in every bucket where it filters true // Insert the itemID in every bucket where it filters true
for (auto& bucket : (*this)) { for (auto& bucket : (*this)) {

View file

@ -13,42 +13,173 @@
#define hifi_render_Task_h #define hifi_render_Task_h
#include "Engine.h" #include "Engine.h"
#include "gpu/Batch.h"
#include <PerfStat.h>
namespace render { namespace render {
template <class T> void jobRun(const T& jobModel, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { } template <class T> void jobRun(T& jobModel, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
jobModel.run(sceneContext, renderContext);
}
template <class T, class I> void jobRunI(T& jobModel, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const I& input) {
jobModel.run(sceneContext, renderContext, input);
}
template <class T, class O> void jobRunO(T& jobModel, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, O& output) {
jobModel.run(sceneContext, renderContext, output);
}
template <class T, class I, class O> void jobRunIO(T& jobModel, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const I& input, O& output) {
jobModel.run(sceneContext, renderContext, input, output);
}
class Job { class Job {
public: public:
// Varying represent a varying piece of data
class Varying {
public:
Varying(const Varying& var): _concept(var._concept) {}
Varying() {}
template <class T> template <class T>
Job(T data) : _concept(new Model<T>(data)) {} Varying(const T& data) : _concept(new Job::Varying::Model<T>(data)) {}
Job(const Job& other) : _concept(other._concept) {}
~Job();
virtual void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { // Access the _data contained win the concept explicitely
if (_concept) { template <class T> T& edit() { return (static_cast<Model<T>*> (_concept.get())->_data); }
_concept->run(sceneContext, renderContext); template <class T> const T& get() const { return (static_cast<const Model<T>*> (_concept.get())->_data); }
}
protected:
friend class Job;
std::vector<std::weak_ptr<Job>> _consumerJobs;
void addJobConsumer(const std::shared_ptr<Job>& job) {
_consumerJobs.push_back(job);
} }
protected:
class Concept { class Concept {
public: public:
virtual ~Concept() = default; virtual ~Concept() = default;
};
template <class T> class Model : public Concept {
public:
typedef T Data;
Data _data;
Model(const Model& source): _data(source.data) {}
Model(const Data& data): _data(data) {}
virtual ~Model() {}
};
std::shared_ptr<Concept> _concept;
};
Job(const Job& other) : _concept(other._concept) {}
~Job();
const std::string& getName() const { return _concept->getName(); }
const Varying getInput() const { return _concept->getInput(); }
const Varying getOutput() const { return _concept->getOutput(); }
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
PerformanceTimer perfTimer(getName().c_str());
PROFILE_RANGE(getName().c_str());
_concept->run(sceneContext, renderContext);
}
protected:
public:
class Concept {
std::string _name;
public:
Concept() : _name() {}
Concept(const std::string& name) : _name(name) {}
virtual ~Concept() = default;
void setName(const std::string& name) { _name = name; }
const std::string& getName() const { return _name; }
virtual const Varying getInput() const { return Varying(); }
virtual const Varying getOutput() const { return Varying(); }
virtual void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) = 0; virtual void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) = 0;
}; };
Job(Concept* concept) : _concept(concept) {}
public:
template <class T> class Model : public Concept { template <class T> class Model : public Concept {
public: public:
typedef T Data; typedef T Data;
Data _data; Data _data;
Model() {}
Model(const std::string& name): Concept(name) {}
Model(Data data): _data(data) {} Model(Data data): _data(data) {}
Model(Data data, const std::string& name): Concept(name), _data(data) {}
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { jobRun(_data, sceneContext, renderContext); } void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { jobRun(_data, sceneContext, renderContext); }
}; };
template <class T, class I> class ModelI : public Concept {
public:
typedef T Data;
typedef I Input;
Data _data;
Varying _input;
const Varying getInput() const { return _input; }
ModelI(const std::string& name, const Varying& input): Concept(name), _input(input) {}
ModelI(const std::string& name, Data data): Concept(name), _data(data) {}
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { jobRunI(_data, sceneContext, renderContext, _input.get<I>()); }
};
template <class T, class O> class ModelO : public Concept {
public:
typedef T Data;
typedef O Output;
Data _data;
Varying _output;
const Varying getOutput() const { return _output; }
ModelO(const std::string& name): Concept(name), _output(Output()) {
}
ModelO(const std::string& name, Data data): Concept(name), _data(data), _output(Output()) {}
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
jobRunO(_data, sceneContext, renderContext, _output.edit<O>());
}
};
template <class T, class I, class O> class ModelIO : public Concept {
public:
typedef T Data;
typedef I Input;
typedef O Output;
Data _data;
Varying _input;
Varying _output;
const Varying getInput() const { return _input; }
const Varying getOutput() const { return _output; }
ModelIO(const std::string& name, const Varying& input, Data data = Data()): Concept(name), _data(data), _input(input), _output(Output()) {}
ModelIO(const std::string& name, Data data, Output output): Concept(name), _data(data), _output(output) {}
void setInput(const Varying& input) { _input = input; }
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { jobRunIO(_data, sceneContext, renderContext, _input.get<I>(), _output.edit<O>()); }
};
std::shared_ptr<Concept> _concept; std::shared_ptr<Concept> _concept;
}; };
@ -62,43 +193,59 @@ void depthSortItems(const SceneContextPointer& sceneContext, const RenderContext
void renderItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, int maxDrawnItems = -1); void renderItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, int maxDrawnItems = -1);
class FetchItems {
void materialSortItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outItems);
class DrawOpaque {
public: public:
typedef std::function<void (const RenderContextPointer& context, int count)> ProbeNumItems;
FetchItems(const ProbeNumItems& probe): _probeNumItems(probe) {}
FetchItems(const ItemFilter& filter, const ProbeNumItems& probe): _filter(filter), _probeNumItems(probe) {}
ItemFilter _filter = ItemFilter::Builder::opaqueShape().withoutLayered();
ProbeNumItems _probeNumItems;
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, ItemIDsBounds& outItems);
typedef Job::ModelO<FetchItems, ItemIDsBounds> JobModel;
}; };
template <> void jobRun(const DrawOpaque& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext);
class CullItems {
class DrawTransparent {
public: public:
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outItems);
typedef Job::ModelIO<CullItems, ItemIDsBounds, ItemIDsBounds> JobModel;
};
class DepthSortItems {
public:
bool _frontToBack = true;
DepthSortItems(bool frontToBack = true) : _frontToBack(frontToBack) {}
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outITems);
typedef Job::ModelIO<DepthSortItems, ItemIDsBounds, ItemIDsBounds> JobModel;
}; };
template <> void jobRun(const DrawTransparent& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext);
class DrawLight { class DrawLight {
public: public:
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext);
typedef Job::Model<DrawLight> JobModel;
}; };
template <> void jobRun(const DrawLight& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext);
class DrawBackground { class DrawBackground {
public: public:
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext);
typedef Job::Model<DrawBackground> JobModel;
}; };
template <> void jobRun(const DrawBackground& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext);
class DrawPostLayered {
public:
};
template <> void jobRun(const DrawPostLayered& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext);
class ResetGLState { class ResetGLState {
public: public:
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext);
typedef Job::Model<ResetGLState> JobModel;
}; };
template <> void jobRun(const ResetGLState& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext);
class DrawSceneTask : public Task { class DrawSceneTask : public Task {
@ -126,6 +273,7 @@ public:
// standard builders allocating the main buckets // standard builders allocating the main buckets
void allocateStandardMaterialBuckets(); void allocateStandardMaterialBuckets();
}; };
void materialSortItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outItems);
} }

View file

@ -45,6 +45,10 @@ public:
int _numDrawnTransparentItems = 0; int _numDrawnTransparentItems = 0;
int _maxDrawnTransparentItems = -1; int _maxDrawnTransparentItems = -1;
int _numFeedOverlay3DItems = 0;
int _numDrawnOverlay3DItems = 0;
int _maxDrawnOverlay3DItems = -1;
RenderContext() {} RenderContext() {}
}; };
typedef std::shared_ptr<RenderContext> RenderContextPointer; typedef std::shared_ptr<RenderContext> RenderContextPointer;

View file

@ -159,4 +159,6 @@ void SceneScriptingInterface::clearEngineCounters() {
_numDrawnOpaqueItems = 0; _numDrawnOpaqueItems = 0;
_numFeedTransparentItems = 0; _numFeedTransparentItems = 0;
_numDrawnTransparentItems = 0; _numDrawnTransparentItems = 0;
_numFeedOverlay3DItems = 0;
_numDrawnOverlay3DItems = 0;
} }

View file

@ -90,17 +90,22 @@ public:
Q_INVOKABLE int getEngineNumDrawnOpaqueItems() { return _numDrawnOpaqueItems; } Q_INVOKABLE int getEngineNumDrawnOpaqueItems() { return _numDrawnOpaqueItems; }
void setEngineDrawnTransparentItems(int count) { _numDrawnTransparentItems = count; } void setEngineDrawnTransparentItems(int count) { _numDrawnTransparentItems = count; }
Q_INVOKABLE int getEngineNumDrawnTransparentItems() { return _numDrawnTransparentItems; } Q_INVOKABLE int getEngineNumDrawnTransparentItems() { return _numDrawnTransparentItems; }
void setEngineDrawnOverlay3DItems(int count) { _numDrawnOverlay3DItems = count; }
Q_INVOKABLE int getEngineNumDrawnOverlay3DItems() { return _numDrawnOverlay3DItems; }
void setEngineFeedOpaqueItems(int count) { _numFeedOpaqueItems = count; } void setEngineFeedOpaqueItems(int count) { _numFeedOpaqueItems = count; }
Q_INVOKABLE int getEngineNumFeedOpaqueItems() { return _numFeedOpaqueItems; } Q_INVOKABLE int getEngineNumFeedOpaqueItems() { return _numFeedOpaqueItems; }
void setEngineFeedTransparentItems(int count) { _numFeedTransparentItems = count; } void setEngineFeedTransparentItems(int count) { _numFeedTransparentItems = count; }
Q_INVOKABLE int getEngineNumFeedTransparentItems() { return _numFeedTransparentItems; } Q_INVOKABLE int getEngineNumFeedTransparentItems() { return _numFeedTransparentItems; }
void setEngineFeedOverlay3DItems(int count) { _numFeedOverlay3DItems = count; }
Q_INVOKABLE int getEngineNumFeedOverlay3DItems() { return _numFeedOverlay3DItems; }
Q_INVOKABLE void setEngineMaxDrawnOpaqueItems(int count) { _maxDrawnOpaqueItems = count; } Q_INVOKABLE void setEngineMaxDrawnOpaqueItems(int count) { _maxDrawnOpaqueItems = count; }
Q_INVOKABLE int getEngineMaxDrawnOpaqueItems() { return _maxDrawnOpaqueItems; } Q_INVOKABLE int getEngineMaxDrawnOpaqueItems() { return _maxDrawnOpaqueItems; }
Q_INVOKABLE void setEngineMaxDrawnTransparentItems(int count) { _maxDrawnTransparentItems = count; } Q_INVOKABLE void setEngineMaxDrawnTransparentItems(int count) { _maxDrawnTransparentItems = count; }
Q_INVOKABLE int getEngineMaxDrawnTransparentItems() { return _maxDrawnTransparentItems; } Q_INVOKABLE int getEngineMaxDrawnTransparentItems() { return _maxDrawnTransparentItems; }
Q_INVOKABLE void setEngineMaxDrawnOverlay3DItems(int count) { _maxDrawnOverlay3DItems = count; }
Q_INVOKABLE int getEngineMaxDrawnOverlay3DItems() { return _maxDrawnOverlay3DItems; }
signals: signals:
void shouldRenderAvatarsChanged(bool shouldRenderAvatars); void shouldRenderAvatarsChanged(bool shouldRenderAvatars);
void shouldRenderEntitiesChanged(bool shouldRenderEntities); void shouldRenderEntitiesChanged(bool shouldRenderEntities);
@ -124,9 +129,12 @@ protected:
int _numDrawnOpaqueItems = 0; int _numDrawnOpaqueItems = 0;
int _numFeedTransparentItems = 0; int _numFeedTransparentItems = 0;
int _numDrawnTransparentItems = 0; int _numDrawnTransparentItems = 0;
int _numFeedOverlay3DItems = 0;
int _numDrawnOverlay3DItems = 0;
int _maxDrawnOpaqueItems = -1; int _maxDrawnOpaqueItems = -1;
int _maxDrawnTransparentItems = -1; int _maxDrawnTransparentItems = -1;
int _maxDrawnOverlay3DItems = -1;
}; };