Implemented async gpu query with frame shifting

This commit is contained in:
turanszkij
2016-11-12 18:44:15 +01:00
parent 0056007964
commit 597adf1589
13 changed files with 109 additions and 64 deletions
Binary file not shown.
+4
View File
@@ -44,6 +44,10 @@ runProcess(function()
if(input.Press(VK_F6)) then
main.GetActiveComponent().SetPreferredThreadingCount(4);
end
if(input.Press(VK_F7)) then
LoadModel("C:\\PROJECTS\\WickedEngine\\WickedEngine\\Scene\\Sample\\","scene");
end
update()
end
+2 -1
View File
@@ -42,7 +42,8 @@ namespace wiGraphicsTypes
virtual HRESULT CreateDepthStencilState(const DepthStencilStateDesc *pDepthStencilStateDesc, DepthStencilState *pDepthStencilState) = 0;
virtual HRESULT CreateRasterizerState(const RasterizerStateDesc *pRasterizerStateDesc, RasterizerState *pRasterizerState) = 0;
virtual HRESULT CreateSamplerState(const SamplerDesc *pSamplerDesc, Sampler *pSamplerState) = 0;
virtual HRESULT CreateQuery(const GPUQueryDesc *pDesc, GPUQuery *pQuery) = 0;
// async: don't flush GPU pipeline when performing query, but introduce latency of two frames
virtual HRESULT CreateQuery(const GPUQueryDesc *pDesc, GPUQuery *pQuery, bool async = true) = 0;
virtual void PresentBegin() = 0;
virtual void PresentEnd() = 0;
+47 -15
View File
@@ -1308,6 +1308,11 @@ inline Texture2DDesc _ConvertTexture2DDesc_Inv(const D3D11_TEXTURE2D_DESC* pDesc
}
// Local Helpers:
const void* const __nullBlob[1024] = { 0 }; // this is initialized to nullptrs!
#define REQUESTQUERYID ((GetFrameCount() + GPUQuery::ASYNC_LATENCY - 1) % GPUQuery::ASYNC_LATENCY)
#define READQUERYID ((GetFrameCount()) % GPUQuery::ASYNC_LATENCY)
// Engine functions
@@ -1335,11 +1340,7 @@ GraphicsDevice_DX11::GraphicsDevice_DX11(wiWindowRegistration::window_type windo
}
UINT createDeviceFlags = 0;
#ifdef _DEBUG
#ifndef WINSTORE_SUPPORT
createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
#endif
D3D_DRIVER_TYPE driverTypes[] =
{
@@ -1532,7 +1533,7 @@ HRESULT GraphicsDevice_DX11::CreateBuffer(const GPUBufferDesc *pDesc, const Subr
ppBuffer->desc = *pDesc;
HRESULT hr = device->CreateBuffer(&desc, data, &ppBuffer->resource_DX11);
assert(SUCCEEDED(hr) && "GPUBuffer Creation failed!");
assert(SUCCEEDED(hr) && "GPUBuffer creation failed!");
if (SUCCEEDED(hr))
{
@@ -1627,7 +1628,7 @@ HRESULT GraphicsDevice_DX11::CreateTexture2D(const Texture2DDesc* pDesc, const S
HRESULT hr = S_OK;
hr = device->CreateTexture2D(&desc, data, &((*ppTexture2D)->texture2D_DX11));
assert(SUCCEEDED(hr) && "Texture2D creating failed!");
assert(SUCCEEDED(hr) && "Texture2D creation failed!");
if (FAILED(hr))
return hr;
@@ -2168,9 +2169,10 @@ HRESULT GraphicsDevice_DX11::CreateSamplerState(const SamplerDesc *pSamplerDesc,
pSamplerState->desc = *pSamplerDesc;
return device->CreateSamplerState(&desc, &pSamplerState->resource_DX11);
}
HRESULT GraphicsDevice_DX11::CreateQuery(const GPUQueryDesc *pDesc, GPUQuery *pQuery)
HRESULT GraphicsDevice_DX11::CreateQuery(const GPUQueryDesc *pDesc, GPUQuery *pQuery, bool async)
{
pQuery->desc = *pDesc;
pQuery->async = async;
D3D11_QUERY_DESC desc;
desc.MiscFlags = 0;
@@ -2179,7 +2181,23 @@ HRESULT GraphicsDevice_DX11::CreateQuery(const GPUQueryDesc *pDesc, GPUQuery *pQ
{
desc.Query = D3D11_QUERY_OCCLUSION;
}
return device->CreateQuery(&desc, &pQuery->resource_DX11);
HRESULT hr = E_FAIL;
if (async)
{
for (int i = 0; i < GPUQuery::ASYNC_LATENCY; ++i)
{
hr = device->CreateQuery(&desc, &pQuery->resource_DX11[i]);
assert(SUCCEEDED(hr) && "GPUQuery creation failed!");
}
}
else
{
hr = device->CreateQuery(&desc, &pQuery->resource_DX11[0]);
assert(SUCCEEDED(hr) && "GPUQuery creation failed!");
}
return hr;
}
@@ -2308,7 +2326,6 @@ void GraphicsDevice_DX11::BindUnorderedAccessResourceCS(const GPUUnorderedResour
if (resource != nullptr)
deviceContexts[threadID]->CSSetUnorderedAccessViews(slot, 1, &resource->unorderedAccessView_DX11, nullptr);
}
const void* const __nullBlob[1024] = { 0 }; // this is initialized to nullptrs!
void GraphicsDevice_DX11::UnBindResources(int slot, int num, GRAPHICSTHREAD threadID)
{
assert(num <= ARRAYSIZE(__nullBlob) && "Extend nullBlob to support more resource unbinding!");
@@ -2599,31 +2616,46 @@ void GraphicsDevice_DX11::SetScissorRects(UINT numRects, const Rect* rects, GRAP
deviceContexts[threadID]->RSSetScissorRects(numRects, nullptr);
}
}
void GraphicsDevice_DX11::QueryBegin(GPUQuery *query, GRAPHICSTHREAD threadID)
{
//query->result_passed = FALSE;
//query->result_passed_sample_count = 0;
deviceContexts[threadID]->Begin(query->resource_DX11);
const int _requestQueryID = (query->async ? REQUESTQUERYID : 0);
deviceContexts[threadID]->Begin(query->resource_DX11[_requestQueryID]);
query->active[_requestQueryID] = true;
}
void GraphicsDevice_DX11::QueryEnd(GPUQuery *query, GRAPHICSTHREAD threadID)
{
deviceContexts[threadID]->End(query->resource_DX11);
const int _requestQueryID = (query->async ? REQUESTQUERYID : 0);
deviceContexts[threadID]->End(query->resource_DX11[_requestQueryID]);
query->active[_requestQueryID] = true;
}
bool GraphicsDevice_DX11::QueryRead(GPUQuery *query, GRAPHICSTHREAD threadID)
{
const int _readQueryID = (query->async ? READQUERYID : 0);
const UINT _flags = (query->async ? D3D11_ASYNC_GETDATA_DONOTFLUSH : 0);
if (!query->active[_readQueryID])
{
return true;
}
assert(threadID == GRAPHICSTHREAD_IMMEDIATE && "A query can only be read on the immediate graphics thread!");
HRESULT hr = S_OK;
switch (query->desc.Type)
{
case GPU_QUERY_TYPE_OCCLUSION:
hr = deviceContexts[threadID]->GetData(query->resource_DX11, &query->result_passed_sample_count, sizeof(query->result_passed_sample_count), 0/*D3D11_ASYNC_GETDATA_DONOTFLUSH*/);
hr = deviceContexts[threadID]->GetData(query->resource_DX11[_readQueryID], &query->result_passed_sample_count, sizeof(query->result_passed_sample_count), _flags);
query->result_passed = query->result_passed_sample_count != 0;
break;
case GPU_QUERY_TYPE_OCCLUSION_PREDICATE:
default:
hr = deviceContexts[threadID]->GetData(query->resource_DX11, &query->result_passed, sizeof(query->result_passed), 0/*D3D11_ASYNC_GETDATA_DONOTFLUSH*/);
hr = deviceContexts[threadID]->GetData(query->resource_DX11[_readQueryID], &query->result_passed, sizeof(query->result_passed), _flags);
break;
}
query->active[_readQueryID] = false;
return SUCCEEDED(hr);
}
+1 -1
View File
@@ -58,7 +58,7 @@ namespace wiGraphicsTypes
virtual HRESULT CreateDepthStencilState(const DepthStencilStateDesc *pDepthStencilStateDesc, DepthStencilState *pDepthStencilState) override;
virtual HRESULT CreateRasterizerState(const RasterizerStateDesc *pRasterizerStateDesc, RasterizerState *pRasterizerState) override;
virtual HRESULT CreateSamplerState(const SamplerDesc *pSamplerDesc, Sampler *pSamplerState) override;
virtual HRESULT CreateQuery(const GPUQueryDesc *pDesc, GPUQuery *pQuery) override;
virtual HRESULT CreateQuery(const GPUQueryDesc *pDesc, GPUQuery *pQuery, bool async = true) override;
virtual void PresentBegin() override;
virtual void PresentEnd() override;
+10 -2
View File
@@ -193,10 +193,18 @@ namespace wiGraphicsTypes
GPUQuery::GPUQuery()
{
SAFE_INIT(resource_DX11);
for (int i = 0; i < ASYNC_LATENCY; ++i)
{
SAFE_INIT(resource_DX11[i]);
active[i] = false;
}
async = false;
}
GPUQuery::~GPUQuery()
{
SAFE_RELEASE(resource_DX11);
for (int i = 0; i < ASYNC_LATENCY; ++i)
{
SAFE_RELEASE(resource_DX11[i]);
}
}
}
+10 -5
View File
@@ -264,17 +264,22 @@ namespace wiGraphicsTypes
class GPUQuery
{
friend class GraphicsDevice_DX11;
public:
static const int ASYNC_LATENCY = 4;
private:
ID3D11Query* resource_DX11;
ID3D11Query* resource_DX11[ASYNC_LATENCY];
GPUQueryDesc desc;
bool active;
bool active[ASYNC_LATENCY];
// async: shift query frames to avoid pipeline stalls from waiting for the GPU:
// we always request queries for some frames forward in time (QueryBegin, QueryEnd)
// so we always read the query which occured some frames behind because of that (QueryRead)
bool async;
public:
GPUQuery();
virtual ~GPUQuery();
bool IsValid() { return resource_DX11 != nullptr; }
bool IsActive() { return active; }
void SetActive(bool value) { active = value; }
bool IsValid() { return resource_DX11[0] != nullptr; }
GPUQueryDesc GetDesc() { return desc; }
BOOL result_passed;
+2 -5
View File
@@ -3677,11 +3677,8 @@ Object::Object(const string& name) :Transform()
GPUQueryDesc desc;
desc.Type = GPU_QUERY_TYPE_OCCLUSION_PREDICATE;
desc.MiscFlags = 0;
for (int i = 0; i < ARRAYSIZE(occlusionQueries); ++i)
{
wiRenderer::GetDevice()->CreateQuery(&desc, &occlusionQueries[i]);
occlusionQueries[i].result_passed = TRUE;
}
wiRenderer::GetDevice()->CreateQuery(&desc, &occlusionQuery, true);
occlusionQuery.result_passed = TRUE;
}
Object::~Object() {
}
+4 -2
View File
@@ -443,8 +443,9 @@ struct Object : public Streamable, public Transform
int physicsObjectI;
// occlusion results for the previous 3 frames
wiGraphicsTypes::GPUQuery occlusionQueries[3];
// occlusion result
wiGraphicsTypes::GPUQuery occlusionQuery;
bool skipOcclusionQuery;
// Is it deformed with an armature?
bool isArmatureDeformed() const
@@ -477,6 +478,7 @@ struct Object : public Streamable, public Transform
color = XMFLOAT3(1, 1, 1);
trailDistortTex = nullptr;
trailTex = nullptr;
skipOcclusionQuery;
}
void EmitTrail(const XMFLOAT3& color, float fadeSpeed = 0.06f);
void FadeTrail();
+23 -25
View File
@@ -87,6 +87,7 @@ wiWaterPlane wiRenderer::waterPlane;
#pragma endregion
wiRenderer::wiRenderer()
{
}
@@ -110,11 +111,11 @@ void wiRenderer::Present(function<void()> drawToScreen1,function<void()> drawToS
if(drawToScreen3!=nullptr)
drawToScreen3();
wiFrameRate::Frame();
GetDevice()->PresentEnd();
*prevFrameCam = *cam;
wiFrameRate::Frame();
}
@@ -1389,6 +1390,7 @@ void wiRenderer::UpdatePerFrameData()
FrameCulling& culling = x.second;
culling.culledRenderer.clear();
culling.culledRenderer_opaque.clear();
culling.culledRenderer_transparent.clear();
culling.culledHairParticleSystems.clear();
culling.culledLights.clear();
@@ -1404,6 +1406,7 @@ void wiRenderer::UpdatePerFrameData()
for (Cullable* x : culledObjects)
{
Object* object = (Object*)x;
culling.culledRenderer[object->mesh].push_front(object);
for (wiHairParticle* hair : object->hParticleSystems)
{
culling.culledHairParticleSystems.push_back(hair);
@@ -1411,7 +1414,7 @@ void wiRenderer::UpdatePerFrameData()
}
if (object->GetRenderTypes() & RENDERTYPE_OPAQUE)
{
culling.culledRenderer[object->mesh].push_front(object);
culling.culledRenderer_opaque[object->mesh].push_front(object);
}
if (!foundClosestReflector && camera == getCamera() && object->IsReflector())
{
@@ -1733,15 +1736,15 @@ void wiRenderer::OcclusionCulling_Render(GRAPHICSTHREAD threadID)
MiscCB cb;
for (Object* instance : visibleInstances)
{
GPUQuery& query = instance->occlusionQueries[0];
GPUQuery& query = instance->occlusionQuery;
if (instance->bounds.intersects(getCamera()->translation))
{
// if the camera is inside the bounding box, then the object is most likely visible, so skip occlusion query
query.result_passed = true;
query.SetActive(false);
instance->skipOcclusionQuery = true;
}
else
else if(!instance->skipOcclusionQuery)
{
// render bounding box to later read the occlusion status
GetDevice()->QueryBegin(&query, threadID);
@@ -1749,7 +1752,7 @@ void wiRenderer::OcclusionCulling_Render(GRAPHICSTHREAD threadID)
GetDevice()->UpdateBuffer(constantBuffers[CBTYPE_MISC], &cb, threadID);
GetDevice()->Draw(36, threadID);
GetDevice()->QueryEnd(&query, threadID);
query.SetActive(true);
instance->skipOcclusionQuery = false;
}
}
}
@@ -1778,18 +1781,8 @@ void wiRenderer::OcclusionCulling_Read()
for (Object* instance : visibleInstances)
{
GPUQuery& query = instance->occlusionQueries[0];
if (!query.IsActive())
{
continue;
}
int queryFailCount = 0;
while (!GetDevice()->QueryRead(&query, GRAPHICSTHREAD_IMMEDIATE))
{
queryFailCount++;
}
query.SetActive(false);
GPUQuery& query = instance->occlusionQuery;
while (!GetDevice()->QueryRead(&query, GRAPHICSTHREAD_IMMEDIATE)) {}
}
}
@@ -3115,7 +3108,7 @@ void wiRenderer::RenderMeshes(const XMFLOAT3& eye, const CulledCollection& culle
if (dither > 1.0f - FLT_EPSILON)
continue;
if (disableOcclusionCulling || instance->occlusionQueries[0].result_passed == TRUE)
if (disableOcclusionCulling || instance->occlusionQuery.result_passed == TRUE)
{
mesh->AddRenderableInstance(Instance(XMMatrixTranspose(mesh->aabb.getAsBoxMatrix()*XMLoadFloat4x4(&instance->world)), dither, instance->color), k, threadID);
++k;
@@ -3228,7 +3221,7 @@ void wiRenderer::RenderMeshes(const XMFLOAT3& eye, const CulledCollection& culle
if (dither > 1.0f - FLT_EPSILON)
continue;
if (disableOcclusionCulling || instance->occlusionQueries[0].result_passed == TRUE)
if (disableOcclusionCulling || instance->occlusionQuery.result_passed == TRUE)
{
if (mesh->softBody || instance->isArmatureDeformed())
mesh->AddRenderableInstance(Instance(XMMatrixIdentity(), dither, instance->color), k, threadID);
@@ -3342,7 +3335,7 @@ void wiRenderer::DrawWorld(Camera* camera, bool tessellation, GRAPHICSTHREAD thr
{
const FrameCulling& culling = frameCullings[camera];
const CulledCollection& culledRenderer = culling.culledRenderer;
const CulledCollection& culledRenderer = culling.culledRenderer_opaque;
GetDevice()->EventBegin(L"DrawWorld");
@@ -3999,7 +3992,7 @@ wiRenderer::Picked wiRenderer::Pick(RAY& ray, int pickType, const string& layer,
vector<Picked> pickPoints;
RayIntersectMeshes(ray, culledObjects, pickPoints, pickType, true, layer, layerDisable);
RayIntersectMeshes(ray, culledObjects, pickPoints, pickType, true, layer, layerDisable, true);
for (auto& model : GetScene().models)
{
@@ -4104,7 +4097,7 @@ RAY wiRenderer::getPickRay(long cursorX, long cursorY){
}
void wiRenderer::RayIntersectMeshes(const RAY& ray, const CulledList& culledObjects, vector<Picked>& points,
int pickType, bool dynamicObjects, const string& layer, const string& layerDisable)
int pickType, bool dynamicObjects, const string& layer, const string& layerDisable, bool onlyVisible)
{
if (culledObjects.empty())
{
@@ -4125,7 +4118,8 @@ void wiRenderer::RayIntersectMeshes(const RAY& ray, const CulledList& culledObje
XMVECTOR& rayOrigin = XMLoadFloat3(&ray.origin);
XMVECTOR& rayDirection = XMVector3Normalize(XMLoadFloat3(&ray.direction));
for (Cullable* culled : culledObjects){
for (Cullable* culled : culledObjects)
{
Object* object = (Object*)culled;
if (!(pickType & object->GetRenderTypes()))
@@ -4136,6 +4130,10 @@ void wiRenderer::RayIntersectMeshes(const RAY& ray, const CulledList& culledObje
{
continue;
}
if (onlyVisible && object->occlusionQuery.result_passed != TRUE)
{
continue;
}
// layer support
if (checkLayers || dontcheckLayers)
+2 -5
View File
@@ -76,13 +76,9 @@ public:
static wiGraphicsTypes::Texture *textures[TEXTYPE_LAST];
//static int SHADOWMAPRES,SOFTSHADOW,POINTLIGHTSHADOW,POINTLIGHTSHADOWRES,SPOTLIGHTSHADOW,SPOTLIGHTSHADOWRES;
static int SHADOWRES_2D, SHADOWRES_CUBE, SHADOWCOUNT_2D, SHADOWCOUNT_CUBE, SOFTSHADOWQUALITY_2D;
static bool HAIRPARTICLEENABLED, EMITTERSENABLED;
//static void SetDirectionalLightShadowProps(int resolution, int softShadowQuality);
//static void SetPointLightShadowProps(int shadowMapCount, int resolution);
//static void SetSpotLightShadowProps(int count, int resolution);
static void SetShadowProps2D(int resolution, int count, int softShadowQuality);
static void SetShadowPropsCube(int resolution, int count);
@@ -361,6 +357,7 @@ public:
struct FrameCulling
{
CulledCollection culledRenderer;
CulledCollection culledRenderer_opaque;
CulledCollection culledRenderer_transparent;
vector<wiHairParticle*> culledHairParticleSystems;
CulledList culledLights;
@@ -491,7 +488,7 @@ public:
static Picked Pick(RAY& ray, int pickType = PICK_OPAQUE, const string& layer = "", const string& layerDisable = "");
static RAY getPickRay(long cursorX, long cursorY);
static void RayIntersectMeshes(const RAY& ray, const CulledList& culledObjects, vector<Picked>& points,
int pickType = PICK_OPAQUE, bool dynamicObjects = true, const string& layer = "", const string& layerDisable = "");
int pickType = PICK_OPAQUE, bool dynamicObjects = true, const string& layer = "", const string& layerDisable = "", bool onlyVisible = false);
static void CalculateVertexAO(Object* object);
static PHYSICS* physicsEngine;
+1 -1
View File
@@ -7,7 +7,7 @@ namespace wiVersion
// minor features, major updates
const int minor = 9;
// minor bug fixes, alterations, refactors, updates
const int revision = 37;
const int revision = 38;
long GetVersion()
+3 -2
View File
@@ -37,7 +37,7 @@ Spotlights + shadow maps
Point lights + shadow cubemaps
Diffuse, specular lighting for all lights
Soft shadows
Rigid body physics simulation (HAVOK) [NOT PUBLIC]
Rigid body physics simulation (HAVOK) [PRIVATE]
Rigid body physics simulation (BULLET)
Soft body physics simulation (BULLET)
Sound (Xaudio2)
@@ -56,4 +56,5 @@ Color Grading
Lua Scripting
Dynamic environment mapping
Impostor system
Tiled forward rendering
Tiled forward (Forward+) rendering
Occlusion culling with gpu queries