Skip to content

Commit

Permalink
D3D12: Fix rare case where command list was executed with open queries
Browse files Browse the repository at this point in the history
  • Loading branch information
stenzek committed Apr 1, 2019
1 parent 92f1f55 commit f2d8c8d
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 2 deletions.
6 changes: 6 additions & 0 deletions Source/Core/VideoBackends/D3D12/PerfQuery.cpp
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ void PerfQuery::EnableQuery(PerfQueryGroup type)
PartialFlush(do_resolve, blocking); PartialFlush(do_resolve, blocking);
} }


// Ensure all state is applied before beginning the query.
// This is because we can't leave a query open when submitting a command list, and the draw
// call itself may need to execute a command list if we run out of descriptors. Note that
// this assumes that the caller has bound all required state prior to enabling the query.
Renderer::GetInstance()->ApplyState();

if (type == PQG_ZCOMP_ZCOMPLOC || type == PQG_ZCOMP) if (type == PQG_ZCOMP_ZCOMPLOC || type == PQG_ZCOMP)
{ {
ActiveQuery& entry = m_query_buffer[m_query_next_pos]; ActiveQuery& entry = m_query_buffer[m_query_next_pos];
Expand Down
5 changes: 3 additions & 2 deletions Source/Core/VideoBackends/D3D12/Renderer.h
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ class Renderer final : public ::Renderer
void SetVertexBuffer(D3D12_GPU_VIRTUAL_ADDRESS address, u32 stride, u32 size); void SetVertexBuffer(D3D12_GPU_VIRTUAL_ADDRESS address, u32 stride, u32 size);
void SetIndexBuffer(D3D12_GPU_VIRTUAL_ADDRESS address, u32 size, DXGI_FORMAT format); void SetIndexBuffer(D3D12_GPU_VIRTUAL_ADDRESS address, u32 size, DXGI_FORMAT format);


// Binds all dirty state
bool ApplyState();

protected: protected:
void OnConfigChanged(u32 bits) override; void OnConfigChanged(u32 bits) override;


Expand Down Expand Up @@ -131,8 +134,6 @@ class Renderer final : public ::Renderer


void CheckForSwapChainChanges(); void CheckForSwapChainChanges();


// Binds all dirty state
bool ApplyState();
void BindFramebuffer(DXFramebuffer* fb); void BindFramebuffer(DXFramebuffer* fb);
void SetRootSignatures(); void SetRootSignatures();
void SetDescriptorHeaps(); void SetDescriptorHeaps();
Expand Down
9 changes: 9 additions & 0 deletions Source/Core/VideoCommon/PerfQueryBase.h
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -31,22 +31,31 @@ class PerfQueryBase
public: public:
PerfQueryBase() : m_query_count(0) {} PerfQueryBase() : m_query_count(0) {}
virtual ~PerfQueryBase() {} virtual ~PerfQueryBase() {}

// Checks if performance queries are enabled in the gameini configuration. // Checks if performance queries are enabled in the gameini configuration.
// NOTE: Called from CPU+GPU thread // NOTE: Called from CPU+GPU thread
static bool ShouldEmulate(); static bool ShouldEmulate();


// Begin querying the specified value for the following host GPU commands // Begin querying the specified value for the following host GPU commands
// The call to EnableQuery() should be placed immediately before the draw command, otherwise
// there is a risk of GPU resets if the query is left open and the buffer is submitted during
// resource binding (D3D12/Vulkan).
virtual void EnableQuery(PerfQueryGroup type) {} virtual void EnableQuery(PerfQueryGroup type) {}

// Stop querying the specified value for the following host GPU commands // Stop querying the specified value for the following host GPU commands
virtual void DisableQuery(PerfQueryGroup type) {} virtual void DisableQuery(PerfQueryGroup type) {}

// Reset query counters to zero and drop any pending queries // Reset query counters to zero and drop any pending queries
virtual void ResetQuery() {} virtual void ResetQuery() {}

// Return the measured value for the specified query type // Return the measured value for the specified query type
// NOTE: Called from CPU thread // NOTE: Called from CPU thread
virtual u32 GetQueryResult(PerfQueryType type) { return 0; } virtual u32 GetQueryResult(PerfQueryType type) { return 0; }

// Request the value of any pending queries - causes a pipeline flush and thus should be used // Request the value of any pending queries - causes a pipeline flush and thus should be used
// carefully! // carefully!
virtual void FlushResults() {} virtual void FlushResults() {}

// True if there are no further pending query results // True if there are no further pending query results
// NOTE: Called from CPU thread // NOTE: Called from CPU thread
virtual bool IsFlushed() const { return true; } virtual bool IsFlushed() const { return true; }
Expand Down

0 comments on commit f2d8c8d

Please sign in to comment.