Removed the base batch / non-base batch separation from BatchGroup. This is only needed for light queues, so rather have LightBatchQueue have separate queues for base & non-base.

Removed useScissor -flag from render path commands, as it can be automatically determined when it should be used.
This commit is contained in:
Lasse Öörni 2014-02-23 02:14:56 +02:00
Родитель da6c5e54ad
Коммит bfd968f9d7
11 изменённых файлов: 52 добавлений и 157 удалений

Просмотреть файл

@ -18,6 +18,6 @@
<command type="scenepass" pass="refract">
<texture unit="environment" name="viewport" />
</command>
<command type="scenepass" pass="alpha" usescissor="true" vertexlights="true" sort="backtofront" metadata="alpha" />
<command type="scenepass" pass="alpha" vertexlights="true" sort="backtofront" metadata="alpha" />
<command type="scenepass" pass="postalpha" sort="backtofront" />
</renderpath>

Просмотреть файл

@ -6,6 +6,6 @@
<command type="scenepass" pass="refract">
<texture unit="environment" name="viewport" />
</command>
<command type="scenepass" pass="alpha" usescissor="true" vertexlights="true" sort="backtofront" metadata="alpha" />
<command type="scenepass" pass="alpha" vertexlights="true" sort="backtofront" metadata="alpha" />
<command type="scenepass" pass="postalpha" sort="backtofront" />
</renderpath>

Просмотреть файл

@ -9,6 +9,6 @@
<command type="scenepass" pass="refract">
<texture unit="environment" name="viewport" />
</command>
<command type="scenepass" pass="alpha" usescissor="true" vertexlights="true" sort="backtofront" metadata="alpha" />
<command type="scenepass" pass="alpha" vertexlights="true" sort="backtofront" metadata="alpha" />
<command type="scenepass" pass="postalpha" sort="backtofront" />
</renderpath>

Просмотреть файл

@ -19,6 +19,6 @@
<command type="scenepass" pass="refract">
<texture unit="environment" name="viewport" />
</command>
<command type="scenepass" pass="alpha" usescissor="true" vertexlights="true" sort="backtofront" metadata="alpha" />
<command type="scenepass" pass="alpha" vertexlights="true" sort="backtofront" metadata="alpha" />
<command type="scenepass" pass="postalpha" sort="backtofront" />
</renderpath>

Просмотреть файл

@ -1076,7 +1076,7 @@ The render path XML definition looks like this:
<rendertarget name="RTName" tag="TagName" enabled="true|false" size="x y"|sizedivisor="x y"|rtsizedivisor="x y"
format="rgb|rgba|r32f|rgba16|rgba16f|rgba32f|rg16|rg16f|rg32f|lineardepth" filter="true|false" srgb="true|false" persistent="true|false" />
<command type="clear" tag="TagName" enabled="true|false" clearcolor="r g b a|fog" cleardepth="x" clearstencil="y" output="viewport|RTName" />
<command type="scenepass" pass="PassName" sort="fronttoback|backtofront" marktostencil="true|false" usescissor="true|false" vertexlights="true|false" metadata="base|alpha|gbuffer" >
<command type="scenepass" pass="PassName" sort="fronttoback|backtofront" marktostencil="true|false" vertexlights="true|false" metadata="base|alpha|gbuffer" >
<output index="0" name="RTName1" />
<output index="1" name="RTName2" />
<output index="2" name="RTName3" />

Просмотреть файл

@ -766,16 +766,13 @@ unsigned BatchGroupKey::ToHash() const
void BatchQueue::Clear(int maxSortedInstances)
{
batches_.Clear();
sortedBaseBatches_.Clear();
sortedBatches_.Clear();
baseBatchGroups_.Clear();
batchGroups_.Clear();
maxSortedInstances_ = maxSortedInstances;
}
void BatchQueue::SortBackToFront()
{
sortedBaseBatches_.Clear();
sortedBatches_.Resize(batches_.Size());
for (unsigned i = 0; i < batches_.Size(); ++i)
@ -784,52 +781,23 @@ void BatchQueue::SortBackToFront()
Sort(sortedBatches_.Begin(), sortedBatches_.End(), CompareBatchesBackToFront);
// Do not actually sort batch groups, just list them
sortedBaseBatchGroups_.Resize(baseBatchGroups_.Size());
sortedBatchGroups_.Resize(batchGroups_.Size());
unsigned index = 0;
for (HashMap<BatchGroupKey, BatchGroup>::Iterator i = baseBatchGroups_.Begin(); i != baseBatchGroups_.End(); ++i)
sortedBaseBatchGroups_[index++] = &i->second_;
index = 0;
for (HashMap<BatchGroupKey, BatchGroup>::Iterator i = batchGroups_.Begin(); i != batchGroups_.End(); ++i)
sortedBatchGroups_[index++] = &i->second_;
}
void BatchQueue::SortFrontToBack()
{
sortedBaseBatches_.Clear();
sortedBatches_.Clear();
// Need to divide into base and non-base batches here to ensure proper order in relation to grouped batches
for (unsigned i = 0; i < batches_.Size(); ++i)
{
if (batches_[i].isBase_)
sortedBaseBatches_.Push(&batches_[i]);
else
sortedBatches_.Push(&batches_[i]);
}
sortedBatches_.Push(&batches_[i]);
SortFrontToBack2Pass(sortedBaseBatches_);
SortFrontToBack2Pass(sortedBatches_);
// Sort each group front to back
for (HashMap<BatchGroupKey, BatchGroup>::Iterator i = baseBatchGroups_.Begin(); i != baseBatchGroups_.End(); ++i)
{
if (i->second_.instances_.Size() <= maxSortedInstances_)
{
Sort(i->second_.instances_.Begin(), i->second_.instances_.End(), CompareInstancesFrontToBack);
if (i->second_.instances_.Size())
i->second_.distance_ = i->second_.instances_[0].distance_;
}
else
{
float minDistance = M_INFINITY;
for (PODVector<InstanceData>::ConstIterator j = i->second_.instances_.Begin(); j != i->second_.instances_.End(); ++j)
minDistance = Min(minDistance, j->distance_);
i->second_.distance_ = minDistance;
}
}
for (HashMap<BatchGroupKey, BatchGroup>::Iterator i = batchGroups_.Begin(); i != batchGroups_.End(); ++i)
{
if (i->second_.instances_.Size() <= maxSortedInstances_)
@ -847,17 +815,12 @@ void BatchQueue::SortFrontToBack()
}
}
sortedBaseBatchGroups_.Resize(baseBatchGroups_.Size());
sortedBatchGroups_.Resize(batchGroups_.Size());
unsigned index = 0;
for (HashMap<BatchGroupKey, BatchGroup>::Iterator i = baseBatchGroups_.Begin(); i != baseBatchGroups_.End(); ++i)
sortedBaseBatchGroups_[index++] = &i->second_;
index = 0;
for (HashMap<BatchGroupKey, BatchGroup>::Iterator i = batchGroups_.Begin(); i != batchGroups_.End(); ++i)
sortedBatchGroups_[index++] = &i->second_;
SortFrontToBack2Pass(reinterpret_cast<PODVector<Batch*>& >(sortedBaseBatchGroups_));
SortFrontToBack2Pass(reinterpret_cast<PODVector<Batch*>& >(sortedBatchGroups_));
}
@ -923,25 +886,27 @@ void BatchQueue::SortFrontToBack2Pass(PODVector<Batch*>& batches)
void BatchQueue::SetTransforms(void* lockedData, unsigned& freeIndex)
{
for (HashMap<BatchGroupKey, BatchGroup>::Iterator i = baseBatchGroups_.Begin(); i != baseBatchGroups_.End(); ++i)
i->second_.SetTransforms(lockedData, freeIndex);
for (HashMap<BatchGroupKey, BatchGroup>::Iterator i = batchGroups_.Begin(); i != batchGroups_.End(); ++i)
i->second_.SetTransforms(lockedData, freeIndex);
}
void BatchQueue::Draw(View* view, bool useScissor, bool markToStencil) const
void BatchQueue::Draw(View* view, bool markToStencil, bool usingLightOptimization) const
{
Graphics* graphics = view->GetGraphics();
Renderer* renderer = view->GetRenderer();
graphics->SetScissorTest(false);
// If View has set up its own light optimizations, do not disturb the stencil/scissor test settings
if (!usingLightOptimization)
{
graphics->SetScissorTest(false);
// During G-buffer rendering, mark opaque pixels' lightmask to stencil buffer if requested
if (!markToStencil)
graphics->SetStencilTest(false);
}
// During G-buffer rendering, mark opaque pixels to stencil buffer
if (!markToStencil)
graphics->SetStencilTest(false);
// Base instanced
for (PODVector<BatchGroup*>::ConstIterator i = sortedBaseBatchGroups_.Begin(); i != sortedBaseBatchGroups_.End(); ++i)
// Instanced
for (PODVector<BatchGroup*>::ConstIterator i = sortedBatchGroups_.Begin(); i != sortedBatchGroups_.End(); ++i)
{
BatchGroup* group = *i;
if (markToStencil)
@ -949,104 +914,29 @@ void BatchQueue::Draw(View* view, bool useScissor, bool markToStencil) const
group->Draw(view);
}
// Base non-instanced
for (PODVector<Batch*>::ConstIterator i = sortedBaseBatches_.Begin(); i != sortedBaseBatches_.End(); ++i)
// Non-instanced
for (PODVector<Batch*>::ConstIterator i = sortedBatches_.Begin(); i != sortedBatches_.End(); ++i)
{
Batch* batch = *i;
if (markToStencil)
graphics->SetStencilTest(true, CMP_ALWAYS, OP_REF, OP_KEEP, OP_KEEP, batch->lightMask_);
batch->Draw(view);
}
// Non-base instanced
for (PODVector<BatchGroup*>::ConstIterator i = sortedBatchGroups_.Begin(); i != sortedBatchGroups_.End(); ++i)
{
BatchGroup* group = *i;
if (useScissor && group->lightQueue_)
renderer->OptimizeLightByScissor(group->lightQueue_->light_, group->camera_);
if (markToStencil)
graphics->SetStencilTest(true, CMP_ALWAYS, OP_REF, OP_KEEP, OP_KEEP, group->lightMask_);
group->Draw(view);
}
// Non-base non-instanced
for (PODVector<Batch*>::ConstIterator i = sortedBatches_.Begin(); i != sortedBatches_.End(); ++i)
{
Batch* batch = *i;
if (useScissor)
if (!usingLightOptimization)
{
// If drawing an alpha batch, we can optimize fillrate by scissor test
if (!batch->isBase_ && batch->lightQueue_)
renderer->OptimizeLightByScissor(batch->lightQueue_->light_, batch->camera_);
else
graphics->SetScissorTest(false);
}
if (markToStencil)
graphics->SetStencilTest(true, CMP_ALWAYS, OP_REF, OP_KEEP, OP_KEEP, batch->lightMask_);
batch->Draw(view);
}
}
void BatchQueue::Draw(Light* light, View* view) const
{
Graphics* graphics = view->GetGraphics();
Renderer* renderer = view->GetRenderer();
graphics->SetScissorTest(false);
graphics->SetStencilTest(false);
// Base instanced
for (PODVector<BatchGroup*>::ConstIterator i = sortedBaseBatchGroups_.Begin(); i != sortedBaseBatchGroups_.End(); ++i)
{
BatchGroup* group = *i;
group->Draw(view);
}
// Base non-instanced
for (PODVector<Batch*>::ConstIterator i = sortedBaseBatches_.Begin(); i != sortedBaseBatches_.End(); ++i)
{
Batch* batch = *i;
batch->Draw(view);
}
// All base passes have been drawn. Optimize at this point by both stencil volume and scissor
bool optimized = false;
// Non-base instanced
for (PODVector<BatchGroup*>::ConstIterator i = sortedBatchGroups_.Begin(); i != sortedBatchGroups_.End(); ++i)
{
BatchGroup* group = *i;
if (!optimized)
{
renderer->OptimizeLightByStencil(light, group->camera_);
renderer->OptimizeLightByScissor(light, group->camera_);
optimized = true;
}
group->Draw(view);
}
// Non-base non-instanced
for (PODVector<Batch*>::ConstIterator i = sortedBatches_.Begin(); i != sortedBatches_.End(); ++i)
{
Batch* batch = *i;
if (!optimized)
{
renderer->OptimizeLightByStencil(light, batch->camera_);
renderer->OptimizeLightByScissor(light, batch->camera_);
optimized = true;
}
batch->Draw(view);
}
}
unsigned BatchQueue::GetNumInstances() const
{
unsigned total = 0;
for (HashMap<BatchGroupKey, BatchGroup>::ConstIterator i = baseBatchGroups_.Begin(); i != baseBatchGroups_.End(); ++i)
{
if (i->second_.geometryType_ == GEOM_INSTANCED)
total += i->second_.instances_.Size();
}
for (HashMap<BatchGroupKey, BatchGroup>::ConstIterator i = batchGroups_.Begin(); i != batchGroups_.End(); ++i)
{
if (i->second_.geometryType_ == GEOM_INSTANCED)

Просмотреть файл

@ -229,16 +229,12 @@ public:
/// Pre-set instance transforms of all groups. The vertex buffer must be big enough to hold all transforms.
void SetTransforms(void* lockedData, unsigned& freeIndex);
/// Draw.
void Draw(View* view, bool useScissor = false, bool markToStencil = false) const;
/// Draw with forward light optimizations.
void Draw(Light* light, View* view) const;
void Draw(View* view, bool markToStencil = false, bool usingLightOptimization = false) const;
/// Return the combined amount of instances.
unsigned GetNumInstances() const;
/// Return whether the batch group is empty.
bool IsEmpty() const { return batches_.Empty() && baseBatchGroups_.Empty() && batchGroups_.Empty(); }
bool IsEmpty() const { return batches_.Empty() && batchGroups_.Empty(); }
/// Instanced draw calls with base flag.
HashMap<BatchGroupKey, BatchGroup> baseBatchGroups_;
/// Instanced draw calls.
HashMap<BatchGroupKey, BatchGroup> batchGroups_;
/// Shader remapping table for 2-pass state and distance sort.
@ -250,12 +246,8 @@ public:
/// Unsorted non-instanced draw calls.
PODVector<Batch> batches_;
/// Sorted non-instanced draw calls with base flag.
PODVector<Batch*> sortedBaseBatches_;
/// Sorted non-instanced draw calls.
PODVector<Batch*> sortedBatches_;
/// Sorted instanced draw calls with base flag.
PODVector<BatchGroup*> sortedBaseBatchGroups_;
/// Sorted instanced draw calls.
PODVector<BatchGroup*> sortedBatchGroups_;
/// Maximum sorted instances.
@ -284,7 +276,9 @@ struct LightBatchQueue
Light* light_;
/// Shadow map depth texture.
Texture2D* shadowMap_;
/// Lit geometry draw calls.
/// Lit geometry draw calls, base (replace blend mode)
BatchQueue litBaseBatches_;
/// Lit geometry draw calls, non-base (additive)
BatchQueue litBatches_;
/// Shadow map split queues.
Vector<ShadowBatchQueue> shadowSplits_;

Просмотреть файл

@ -129,8 +129,6 @@ void RenderPathCommand::Load(const XMLElement& element)
markToStencil_ = element.GetBool("marktostencil");
if (element.HasAttribute("vertexlights"))
vertexLights_ = element.GetBool("vertexlights");
if (element.HasAttribute("usescissor"))
useScissor_ = element.GetBool("usescissor");
break;
case CMD_FORWARDLIGHTS:

Просмотреть файл

@ -107,7 +107,6 @@ struct RenderPathCommand
useFogColor_(false),
markToStencil_(false),
useLitBase_(true),
useScissor_(false),
vertexLights_(false)
{
}
@ -174,8 +173,6 @@ struct RenderPathCommand
bool markToStencil_;
/// Use lit base pass optimization for forward per-pixel lights.
bool useLitBase_;
/// Scissor optimization flag.
bool useScissor_;
/// Vertex lights flag.
bool vertexLights_;
};

Просмотреть файл

@ -275,6 +275,7 @@ void SortBatchQueueBackToFrontWork(const WorkItem* item, unsigned threadIndex)
void SortLightQueueWork(const WorkItem* item, unsigned threadIndex)
{
LightBatchQueue* start = reinterpret_cast<LightBatchQueue*>(item->start_);
start->litBaseBatches_.SortFrontToBack();
start->litBatches_.SortFrontToBack();
}
@ -356,7 +357,6 @@ bool View::Define(RenderSurface* renderTarget, Viewport* viewport)
info.pass_ = command.pass_;
info.allowInstancing_ = command.sortMode_ != SORT_BACKTOFRONT;
info.markToStencil_ = command.markToStencil_;
info.useScissor_ = command.useScissor_;
info.vertexLights_ = command.vertexLights_;
// Check scenepass metadata for defining custom passes which interact with lighting
@ -818,6 +818,7 @@ void View::GetBatches()
light->SetLightQueue(&lightQueue);
lightQueue.light_ = light;
lightQueue.shadowMap_ = 0;
lightQueue.litBaseBatches_.Clear(maxSortedInstances);
lightQueue.litBatches_.Clear(maxSortedInstances);
lightQueue.volumeBatches_.Clear();
@ -1201,7 +1202,12 @@ void View::GetLitBatches(Drawable* drawable, LightBatchQueue& lightQueue, BatchQ
destBatch.zone_ = zone;
if (!isLitAlpha)
AddBatchToQueue(lightQueue.litBatches_, destBatch, tech);
{
if (destBatch.isBase_)
AddBatchToQueue(lightQueue.litBaseBatches_, destBatch, tech);
else
AddBatchToQueue(lightQueue.litBatches_, destBatch, tech);
}
else if (alphaQueue)
{
// Transparent batches can not be instanced
@ -1337,7 +1343,7 @@ void View::ExecuteRenderPathCommands()
SetTextures(command);
graphics_->SetFillMode(camera_->GetFillMode());
graphics_->SetClipPlane(camera_->GetUseClipping(), camera_->GetClipPlane(), camera_->GetView(), camera_->GetProjection());
batchQueues_[command.pass_].Draw(this, command.useScissor_, command.markToStencil_);
batchQueues_[command.pass_].Draw(this, command.markToStencil_, false);
}
break;
@ -1371,7 +1377,17 @@ void View::ExecuteRenderPathCommands()
SetTextures(command);
graphics_->SetFillMode(camera_->GetFillMode());
graphics_->SetClipPlane(camera_->GetUseClipping(), camera_->GetClipPlane(), camera_->GetView(), camera_->GetProjection());
i->litBatches_.Draw(i->light_, this);
// Draw base (replace blend) batches first
i->litBaseBatches_.Draw(this);
// Then, if there are additive passes, optimize the light and draw them
if (!i->litBatches_.IsEmpty())
{
renderer_->OptimizeLightByScissor(i->light_, camera_);
renderer_->OptimizeLightByStencil(i->light_, camera_);
i->litBatches_.Draw(this, false, true);
}
}
graphics_->SetScissorTest(false);
@ -2545,11 +2561,10 @@ void View::AddBatchToQueue(BatchQueue& batchQueue, Batch& batch, Technique* tech
if (batch.geometryType_ == GEOM_INSTANCED)
{
HashMap<BatchGroupKey, BatchGroup>* groups = batch.isBase_ ? &batchQueue.baseBatchGroups_ : &batchQueue.batchGroups_;
BatchGroupKey key(batch);
HashMap<BatchGroupKey, BatchGroup>::Iterator i = groups->Find(key);
if (i == groups->End())
HashMap<BatchGroupKey, BatchGroup>::Iterator i = batchQueue.batchGroups_.Find(key);
if (i == batchQueue.batchGroups_.End())
{
// Create a new group based on the batch
// In case the group remains below the instancing limit, do not enable instancing shaders yet
@ -2557,7 +2572,7 @@ void View::AddBatchToQueue(BatchQueue& batchQueue, Batch& batch, Technique* tech
newGroup.geometryType_ = GEOM_STATIC;
renderer_->SetBatchShaders(newGroup, tech, allowShadows);
newGroup.CalculateSortKey();
i = groups->Insert(MakePair(key, newGroup));
i = batchQueue.batchGroups_.Insert(MakePair(key, newGroup));
}
int oldSize = i->second_.instances_.Size();
@ -2591,6 +2606,7 @@ void View::PrepareInstancingBuffer()
{
for (unsigned j = 0; j < i->shadowSplits_.Size(); ++j)
totalInstances += i->shadowSplits_[j].shadowBatches_.GetNumInstances();
totalInstances += i->litBaseBatches_.GetNumInstances();
totalInstances += i->litBatches_.GetNumInstances();
}
@ -2610,6 +2626,7 @@ void View::PrepareInstancingBuffer()
{
for (unsigned j = 0; j < i->shadowSplits_.Size(); ++j)
i->shadowSplits_[j].shadowBatches_.SetTransforms(dest, freeIndex);
i->litBaseBatches_.SetTransforms(dest, freeIndex);
i->litBatches_.SetTransforms(dest, freeIndex);
}

Просмотреть файл

@ -339,7 +339,6 @@ static void RegisterRenderPath(asIScriptEngine* engine)
engine->RegisterObjectProperty("RenderPathCommand", "bool markToStencil", offsetof(RenderPathCommand, markToStencil_));
engine->RegisterObjectProperty("RenderPathCommand", "bool vertexLights", offsetof(RenderPathCommand, vertexLights_));
engine->RegisterObjectProperty("RenderPathCommand", "bool useLitBase", offsetof(RenderPathCommand, useLitBase_));
engine->RegisterObjectProperty("RenderPathCommand", "bool useScissor", offsetof(RenderPathCommand, useScissor_));
engine->RegisterObjectProperty("RenderPathCommand", "String vertexShaderName", offsetof(RenderPathCommand, vertexShaderName_));
engine->RegisterObjectProperty("RenderPathCommand", "String pixelShaderName", offsetof(RenderPathCommand, pixelShaderName_));
engine->RegisterObjectProperty("RenderPathCommand", "String vertexShaderDefines", offsetof(RenderPathCommand, vertexShaderDefines_));