implemented occlusion query pool with conservative culling
This commit is contained in:
@@ -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);
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user