Browse Source

Re-added "flush GPU command buffer" -feature for controlling timestep variance and input lag. Direct3D only for now. Default off, as can decrease performance.

Lasse Öörni 12 years ago
parent
commit
5fb42a277c

+ 41 - 0
Source/Engine/Graphics/Direct3D9/D3D9Graphics.cpp

@@ -178,8 +178,10 @@ Graphics::Graphics(Context* context) :
     resizable_(false),
     vsync_(false),
     tripleBuffer_(false),
+    flushGPU_(false),
     sRGB_(false),
     deviceLost_(false),
+    queryIssued_(false),
     lightPrepassSupport_(false),
     deferredSupport_(false),
     hardwareShadowSupport_(false),
@@ -221,6 +223,11 @@ Graphics::~Graphics()
         impl_->defaultDepthStencilSurface_->Release();
         impl_->defaultDepthStencilSurface_ = 0;
     }
+    if (impl_->frameQuery_)
+    {
+        impl_->frameQuery_->Release();
+        impl_->frameQuery_ = 0;
+    }
     if (impl_->device_)
     {
         impl_->device_->Release();
@@ -446,6 +453,11 @@ void Graphics::SetSRGB(bool enable)
     sRGB_ = enable && sRGBWriteSupport_;
 }
 
+void Graphics::SetFlushGPU(bool enable)
+{
+    flushGPU_ = enable;
+}
+
 bool Graphics::ToggleFullscreen()
 {
     return SetMode(width_, height_, !fullscreen_, resizable_, vsync_, tripleBuffer_, multiSample_);
@@ -582,6 +594,18 @@ bool Graphics::BeginFrame()
         }
     }
     
+    // If a query was issued on the previous frame, wait for it to finish before beginning the next
+    if (impl_->frameQuery_ && queryIssued_)
+    {
+        PROFILE(FlushGPU);
+        
+        while (impl_->frameQuery_->GetData(0, 0, D3DGETDATA_FLUSH) == S_FALSE)
+        {
+        }
+        
+        queryIssued_ = false;
+    }
+    
     impl_->device_->BeginScene();
     
     // Set default rendertarget and depth buffer
@@ -614,6 +638,13 @@ void Graphics::EndFrame()
     impl_->device_->EndScene();
     impl_->device_->Present(0, 0, 0, 0);
     
+    // Optionally flush GPU buffer to avoid control lag or framerate fluctuations due to pre-render
+    if (impl_->frameQuery_ && flushGPU_)
+    {
+        impl_->frameQuery_->Issue(D3DISSUE_END);
+        queryIssued_ = true;
+    }
+    
     // Clean up too large scratch buffers
     CleanupScratchBuffers();
 }
@@ -2370,6 +2401,11 @@ void Graphics::OnDeviceLost()
         impl_->defaultDepthStencilSurface_->Release();
         impl_->defaultDepthStencilSurface_ = 0;
     }
+    if (impl_->frameQuery_)
+    {
+        impl_->frameQuery_->Release();
+        impl_->frameQuery_ = 0;
+    }
     
     for (unsigned i = 0; i < gpuObjects_.Size(); ++i)
         gpuObjects_[i]->OnDeviceLost();
@@ -2384,6 +2420,9 @@ void Graphics::OnDeviceReset()
     impl_->device_->GetRenderTarget(0, &impl_->defaultColorSurface_);
     impl_->device_->GetDepthStencilSurface(&impl_->defaultDepthStencilSurface_);
     
+    // Create frame query for flushing the GPU command buffer
+    impl_->device_->CreateQuery(D3DQUERYTYPE_EVENT, &impl_->frameQuery_);
+    
     ResetCachedState();
 }
 
@@ -2448,6 +2487,8 @@ void Graphics::ResetCachedState()
     impl_->blendEnable_ = FALSE;
     impl_->srcBlend_ = D3DBLEND_ONE;
     impl_->destBlend_ = D3DBLEND_ZERO;
+    
+    queryIssued_ = false;
 }
 
 void Graphics::SetTextureUnitMappings()

+ 8 - 0
Source/Engine/Graphics/Direct3D9/D3D9Graphics.h

@@ -93,6 +93,8 @@ public:
     bool SetMode(int width, int height);
     /// Set whether the main window uses sRGB conversion on write.
     void SetSRGB(bool enable);
+    /// Set whether to flush the GPU command buffer to prevent multiple frames being queued and uneven frame timesteps. Default off, may decrease performance if enabled.
+    void SetFlushGPU(bool enable);
     /// Toggle between full screen and windowed mode. Return true if successful.
     bool ToggleFullscreen();
     /// Close the window.
@@ -236,6 +238,8 @@ public:
     bool GetTripleBuffer() const { return tripleBuffer_; }
     /// Return whether the main window is using sRGB conversion on write.
     bool GetSRGB() const { return sRGB_; }
+    /// Return whether the GPU command buffer is flushed each frame.
+    bool GetFlushGPU() const { return flushGPU_; }
     /// Return whether Direct3D device is lost, and can not yet render. This happens during fullscreen resolution switching.
     bool IsDeviceLost() const { return deviceLost_; }
     /// Return number of primitives drawn this frame.
@@ -427,10 +431,14 @@ private:
     bool vsync_;
     /// Triple buffering flag.
     bool tripleBuffer_;
+    /// Flush GPU command buffer flag.
+    bool flushGPU_;
     /// sRGB conversion on write flag for the main window.
     bool sRGB_;
     /// Direct3D device lost flag.
     bool deviceLost_;
+    /// Flush query issued flag.
+    bool queryIssued_;
     /// Light pre-pass rendering support flag.
     bool lightPrepassSupport_;
     /// Deferred rendering support flag.

+ 1 - 0
Source/Engine/Graphics/Direct3D9/D3D9GraphicsImpl.cpp

@@ -36,6 +36,7 @@ GraphicsImpl::GraphicsImpl() :
     device_(0),
     defaultColorSurface_(0),
     defaultDepthStencilSurface_(0),
+    frameQuery_(0),
     adapter_(D3DADAPTER_DEFAULT),
     deviceType_(D3DDEVTYPE_HAL)
 {

+ 2 - 0
Source/Engine/Graphics/Direct3D9/D3D9GraphicsImpl.h

@@ -61,6 +61,8 @@ private:
     IDirect3DSurface9* defaultColorSurface_;
     /// Default depth-stencil surface.
     IDirect3DSurface9* defaultDepthStencilSurface_;
+    /// Frame query for flushing the GPU command queue.
+    IDirect3DQuery9* frameQuery_;
     /// Adapter number.
     DWORD adapter_;
     /// Device type.

+ 4 - 0
Source/Engine/Graphics/OpenGL/OGLGraphics.h

@@ -98,6 +98,8 @@ public:
     bool SetMode(int width, int height);
     /// Set whether the main window uses sRGB conversion on write.
     void SetSRGB(bool enable);
+    /// Set whether to flush the GPU command buffer to prevent multiple frames being queued and uneven frame timesteps. Not yet implemented on OpenGL.
+    void SetFlushGPU(bool enable) {}
     /// Toggle between full screen and windowed mode. Return true if successful.
     bool ToggleFullscreen();
     /// Close the window.
@@ -243,6 +245,8 @@ public:
     bool GetTripleBuffer() const { return tripleBuffer_; }
     /// Return whether the main window is using sRGB conversion on write.
     bool GetSRGB() const { return sRGB_; }
+    /// Return whether the GPU command buffer is flushed each frame. Not yet implemented on OpenGL.
+    bool GetFlushGPU() const { return false; }
     /// Return whether device is lost, and can not yet render.
     bool IsDeviceLost() const;
     /// Return number of primitives drawn this frame.

+ 2 - 0
Source/Engine/Script/GraphicsAPI.cpp

@@ -1187,6 +1187,8 @@ static void RegisterGraphics(asIScriptEngine* engine)
     engine->RegisterObjectMethod("Graphics", "IntVector2 get_windowPosition() const", asMETHOD(Graphics, GetWindowPosition), asCALL_THISCALL);
     engine->RegisterObjectMethod("Graphics", "void set_sRGB(bool)", asMETHOD(Graphics, SetSRGB), asCALL_THISCALL);
     engine->RegisterObjectMethod("Graphics", "bool get_sRGB() const", asMETHOD(Graphics, GetSRGB), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Graphics", "void set_flushGPU(bool)", asMETHOD(Graphics, SetFlushGPU), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Graphics", "bool get_flushGPU() const", asMETHOD(Graphics, GetFlushGPU), asCALL_THISCALL);
     engine->RegisterObjectMethod("Graphics", "int get_width() const", asMETHOD(Graphics, GetWidth), asCALL_THISCALL);
     engine->RegisterObjectMethod("Graphics", "int get_height() const", asMETHOD(Graphics, GetHeight), asCALL_THISCALL);
     engine->RegisterObjectMethod("Graphics", "int get_multiSample() const", asMETHOD(Graphics, GetMultiSample), asCALL_THISCALL);

+ 3 - 0
Source/Extras/LuaScript/pkgs/Graphics/Graphics.pkg

@@ -10,6 +10,7 @@ class Graphics : public Object
     bool SetMode(int width, int height);
     
     void SetSRGB(bool enable);
+    void SetFlushGPU(bool enable);
     bool ToggleFullscreen();
     void Close();
     bool TakeScreenShot(Image& destImage);
@@ -26,6 +27,7 @@ class Graphics : public Object
     bool GetVSync() const;
     bool GetTripleBuffer() const;
     bool GetSRGB() const;
+    bool GetFlushGPU() const;
     bool IsDeviceLost() const;
     unsigned GetNumPrimitives() const;
     unsigned GetNumBatches() const;
@@ -55,6 +57,7 @@ class Graphics : public Object
     tolua_readonly tolua_property__get_set bool vSync;
     tolua_readonly tolua_property__get_set bool tripleBuffer;
     tolua_property__get_set bool sRGB;
+    tolua_property__get_set bool flushGPU;
     tolua_readonly tolua_property__is_set bool deviceLost;
     tolua_readonly tolua_property__get_set unsigned numPrimitives;
     tolua_readonly tolua_property__get_set unsigned numBatches;