implemented occlusion query pool with conservative culling

This commit is contained in:
turanszkij
2017-05-29 23:35:23 +02:00
parent bea995e53d
commit 84cd694a1c
7 changed files with 80 additions and 32 deletions
+1
View File
@@ -64,6 +64,7 @@ void Editor::Initialize()
//wiRenderer::SetPointLightShadowProps(3, 512);
//wiRenderer::SetSpotLightShadowProps(3, 512);
wiRenderer::physicsEngine = new wiBULLET();
wiRenderer::SetOcclusionCullingEnabled(true);
wiHairParticle::Settings(400, 1000, 2000);
-4
View File
@@ -2591,8 +2591,6 @@ HRESULT GraphicsDevice_DX11::CreateQuery(const GPUQueryDesc *pDesc, GPUQuery *pQ
{
HRESULT hr = E_FAIL;
#ifndef _ARM // phone actually crashes on createquery :(
pQuery->desc = *pDesc;
pQuery->async_frameshift = pQuery->desc.async_latency;
@@ -2630,8 +2628,6 @@ HRESULT GraphicsDevice_DX11::CreateQuery(const GPUQueryDesc *pDesc, GPUQuery *pQ
assert(SUCCEEDED(hr) && "GPUQuery creation failed!");
}
#endif // WINSTORE_SUPPORT
return hr;
}
+7 -9
View File
@@ -3832,14 +3832,8 @@ void Object::init()
color = XMFLOAT3(1, 1, 1);
trailDistortTex = nullptr;
trailTex = nullptr;
skipOcclusionQuery = true;
GPUQueryDesc desc;
desc.Type = GPU_QUERY_TYPE_OCCLUSION_PREDICATE;
desc.MiscFlags = 0;
desc.async_latency = 1;
wiRenderer::GetDevice()->CreateQuery(&desc, &occlusionQuery);
occlusionQuery.result_passed = TRUE;
occlusionHistory = 0xFFFFFFFF;
occlusionQueryID = -1;
}
void Object::EmitTrail(const XMFLOAT3& col, float fadeSpeed) {
if (mesh != nullptr)
@@ -3968,7 +3962,11 @@ int Object::GetRenderTypes() const
}
bool Object::IsOccluded() const
{
return !skipOcclusionQuery && occlusionQuery.result_passed == FALSE;
// Perform a conservative occlusion test:
// If it is visible in any frames in the history, it is determined visible in this frame
// But if all queries failed in the history, it is occluded.
// If it pops up for a frame after occluded, it is visible again for some frames
return ((occlusionQueryID >= 0) && (occlusionHistory & 0xFFFFFFFF) == 0);
}
XMMATRIX Object::GetOBB() const
{
+4 -3
View File
@@ -464,9 +464,10 @@ struct Object : public Streamable, public Transform
int physicsObjectID;
// occlusion result
wiGraphicsTypes::GPUQuery occlusionQuery;
bool skipOcclusionQuery;
// occlusion result history bitfield (32 bit->32 frame history)
uint32_t occlusionHistory;
// occlusion query pool index
int occlusionQueryID;
// Is it deformed with an armature?
bool isArmatureDeformed() const
+64 -14
View File
@@ -61,11 +61,12 @@ float wiRenderer::SPECULARAA = 0.0f;
float wiRenderer::renderTime = 0, wiRenderer::renderTime_Prev = 0, wiRenderer::deltaTime = 0;
XMFLOAT2 wiRenderer::temporalAAJitter = XMFLOAT2(0, 0), wiRenderer::temporalAAJitterPrev = XMFLOAT2(0, 0);
float wiRenderer::RESOLUTIONSCALE = 1.0f;
GPUQuery wiRenderer::occlusionQueries[];
Texture2D* wiRenderer::enviroMap,*wiRenderer::colorGrading;
float wiRenderer::GameSpeed=1,wiRenderer::overrideGameSpeed=1;
bool wiRenderer::debugLightCulling = false;
bool wiRenderer::occlusionCulling = true;
bool wiRenderer::occlusionCulling = false;
bool wiRenderer::temporalAA = false, wiRenderer::temporalAADEBUG = false;
wiRenderer::VoxelizedSceneData wiRenderer::voxelSceneData = VoxelizedSceneData();
int wiRenderer::visibleCount;
@@ -2082,6 +2083,8 @@ void wiRenderer::OcclusionCulling_Render(GRAPHICSTHREAD threadID)
wiProfiler::GetInstance().BeginRange("Occlusion Culling Render", wiProfiler::DOMAIN_GPU, threadID);
int queryID = 0;
if (!culledRenderer.empty())
{
GetDevice()->EventBegin("Occlusion Culling Render", threadID);
@@ -2094,10 +2097,12 @@ void wiRenderer::OcclusionCulling_Render(GRAPHICSTHREAD threadID)
GetDevice()->BindPS(nullptr, threadID);
GetDevice()->BindPrimitiveTopology(PRIMITIVETOPOLOGY::TRIANGLESTRIP, threadID);
int queryID = 0;
for (CulledCollection::const_iterator iter = culledRenderer.begin(); iter != culledRenderer.end(); ++iter)
{
Mesh* mesh = iter->first;
if (!mesh->renderable || mesh->softBody) // todo: correct softbody
if (!mesh->renderable)
{
continue;
}
@@ -2106,25 +2111,30 @@ void wiRenderer::OcclusionCulling_Render(GRAPHICSTHREAD threadID)
MiscCB cb;
for (Object* instance : visibleInstances)
{
GPUQuery& query = instance->occlusionQuery;
if(queryID >= ARRAYSIZE(occlusionQueries))
{
instance->occlusionQueryID = -1; // assign an invalid id from the pool
continue;
}
// If a query could be retrieved from the pool for the instance, the instance can be occluded, so render it
GPUQuery& query = occlusionQueries[queryID];
if (!query.IsValid())
{
continue;
}
if (instance->bounds.intersects(getCamera()->translation))
if (instance->bounds.intersects(getCamera()->translation) || mesh->softBody) // todo: correct softbody
{
// if the camera is inside the bounding box, then the object is most likely visible, so skip occlusion query and mark it as visible:
query.result_passed = true;
instance->skipOcclusionQuery = true;
// camera is inside the instance, mark it as visible in this frame:
instance->occlusionHistory |= 1;
}
else
{
if (instance->skipOcclusionQuery)
{
instance->skipOcclusionQuery = false;
continue;
}
// only query for occlusion if the camera is outside the instance
instance->occlusionQueryID = queryID; // just assign the id from the pool
queryID++;
// previous frame view*projection because these are drawn against the previous depth buffer:
cb.mTransform = XMMatrixTranspose(instance->GetOBB()*prevFrameCam->GetViewProjection());
GetDevice()->UpdateBuffer(constantBuffers[CBTYPE_MISC], &cb, threadID);
@@ -2170,13 +2180,29 @@ void wiRenderer::OcclusionCulling_Read()
for (Object* instance : visibleInstances)
{
GPUQuery& query = instance->occlusionQuery;
instance->occlusionHistory <<= 1; // advance history by 1 frame
if (instance->occlusionQueryID < 0)
{
instance->occlusionHistory |= 1; // mark this frame as visible
continue;
}
GPUQuery& query = occlusionQueries[instance->occlusionQueryID];
if (!query.IsValid())
{
instance->occlusionHistory |= 1; // mark this frame as visible
continue;
}
while (!GetDevice()->QueryRead(&query, GRAPHICSTHREAD_IMMEDIATE)) {}
if (query.result_passed == TRUE)
{
instance->occlusionHistory |= 1; // mark this frame as visible
}
else
{
// leave this frame as occluded
}
}
}
@@ -5636,7 +5662,7 @@ void wiRenderer::RayIntersectMeshes(const RAY& ray, const CulledList& culledObje
{
continue;
}
if (onlyVisible && object->occlusionQuery.result_passed != TRUE)
if (onlyVisible && object->IsOccluded())
{
continue;
}
@@ -6206,3 +6232,27 @@ void wiRenderer::Remove(EnvironmentProbe* value)
value->detach();
}
}
void wiRenderer::SetOcclusionCullingEnabled(bool value)
{
static bool initialized = false;
if (!initialized && value == true)
{
initialized = true;
GPUQueryDesc desc;
desc.Type = GPU_QUERY_TYPE_OCCLUSION_PREDICATE;
desc.MiscFlags = 0;
desc.async_latency = 1;
for (int i = 0; i < ARRAYSIZE(occlusionQueries); ++i)
{
wiRenderer::GetDevice()->CreateQuery(&desc, &occlusionQueries[i]);
occlusionQueries[i].result_passed = TRUE;
}
}
occlusionCulling = value;
}
+3 -1
View File
@@ -307,6 +307,8 @@ protected:
{}
} static voxelSceneData;
static wiGraphicsTypes::GPUQuery occlusionQueries[256];
public:
static std::string SHADERPATH;
@@ -356,7 +358,7 @@ public:
static bool GetDebugLightCulling() { return debugLightCulling; }
static void SetAdvancedLightCulling(bool enabled) { advancedLightCulling = enabled; }
static bool GetAdvancedLightCulling() { return advancedLightCulling; }
static void SetOcclusionCullingEnabled(bool enabled) { occlusionCulling = enabled; }
static void SetOcclusionCullingEnabled(bool enabled); // also inits query pool!
static bool GetOcclusionCullingEnabled() { return occlusionCulling; }
static void SetTemporalAAEnabled(bool enabled) { temporalAA = enabled; }
static bool GetTemporalAAEnabled() { return temporalAA; }
+1 -1
View File
@@ -9,7 +9,7 @@ namespace wiVersion
// minor features, major updates
const int minor = 11;
// minor bug fixes, alterations, refactors, updates
const int revision = 60;
const int revision = 61;
long GetVersion()