mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-03-02 04:29:14 +01:00
[d3d11] Added test case for occlusion queries and small improvements
This commit is contained in:
parent
675a629ae5
commit
e89c7e9276
@ -21,7 +21,7 @@ namespace dxvk {
|
|||||||
m_msState.sampleMask = 0; // Set during bind
|
m_msState.sampleMask = 0; // Set during bind
|
||||||
m_msState.enableAlphaToCoverage = desc.AlphaToCoverageEnable;
|
m_msState.enableAlphaToCoverage = desc.AlphaToCoverageEnable;
|
||||||
m_msState.enableAlphaToOne = VK_FALSE;
|
m_msState.enableAlphaToOne = VK_FALSE;
|
||||||
m_msState.enableSampleShading = VK_TRUE;
|
m_msState.enableSampleShading = VK_FALSE;
|
||||||
m_msState.minSampleShading = 0.0f;
|
m_msState.minSampleShading = 0.0f;
|
||||||
|
|
||||||
// In 11_0, there is no logic op state. Later versions
|
// In 11_0, there is no logic op state. Later versions
|
||||||
|
@ -41,21 +41,23 @@ namespace dxvk {
|
|||||||
|
|
||||||
|
|
||||||
void STDMETHODCALLTYPE D3D11ImmediateContext::Flush() {
|
void STDMETHODCALLTYPE D3D11ImmediateContext::Flush() {
|
||||||
m_parent->FlushInitContext();
|
if (m_csChunk->commandCount() != 0) {
|
||||||
m_drawCount = 0;
|
m_parent->FlushInitContext();
|
||||||
|
m_drawCount = 0;
|
||||||
// Add commands to flush the threaded
|
|
||||||
// context, then flush the command list
|
|
||||||
EmitCs([dev = m_device] (DxvkContext* ctx) {
|
|
||||||
dev->submitCommandList(
|
|
||||||
ctx->endRecording(),
|
|
||||||
nullptr, nullptr);
|
|
||||||
|
|
||||||
ctx->beginRecording(
|
// Add commands to flush the threaded
|
||||||
dev->createCommandList());
|
// context, then flush the command list
|
||||||
});
|
EmitCs([dev = m_device] (DxvkContext* ctx) {
|
||||||
|
dev->submitCommandList(
|
||||||
FlushCsChunk();
|
ctx->endRecording(),
|
||||||
|
nullptr, nullptr);
|
||||||
|
|
||||||
|
ctx->beginRecording(
|
||||||
|
dev->createCommandList());
|
||||||
|
});
|
||||||
|
|
||||||
|
FlushCsChunk();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -13,19 +13,27 @@ namespace dxvk {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case D3D11_QUERY_OCCLUSION:
|
case D3D11_QUERY_OCCLUSION:
|
||||||
|
m_query = new DxvkQuery(
|
||||||
|
VK_QUERY_TYPE_OCCLUSION,
|
||||||
|
VK_QUERY_CONTROL_PRECISE_BIT);
|
||||||
|
break;
|
||||||
|
|
||||||
case D3D11_QUERY_OCCLUSION_PREDICATE:
|
case D3D11_QUERY_OCCLUSION_PREDICATE:
|
||||||
m_query = new DxvkQuery(VK_QUERY_TYPE_OCCLUSION);
|
m_query = new DxvkQuery(
|
||||||
|
VK_QUERY_TYPE_OCCLUSION, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case D3D11_QUERY_TIMESTAMP:
|
case D3D11_QUERY_TIMESTAMP:
|
||||||
m_query = new DxvkQuery(VK_QUERY_TYPE_TIMESTAMP);
|
m_query = new DxvkQuery(
|
||||||
|
VK_QUERY_TYPE_TIMESTAMP, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case D3D11_QUERY_TIMESTAMP_DISJOINT:
|
case D3D11_QUERY_TIMESTAMP_DISJOINT:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case D3D11_QUERY_PIPELINE_STATISTICS:
|
case D3D11_QUERY_PIPELINE_STATISTICS:
|
||||||
m_query = new DxvkQuery(VK_QUERY_TYPE_PIPELINE_STATISTICS);
|
m_query = new DxvkQuery(
|
||||||
|
VK_QUERY_TYPE_PIPELINE_STATISTICS, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -73,7 +73,7 @@ namespace dxvk {
|
|||||||
m_cmd->cmdBeginQuery(
|
m_cmd->cmdBeginQuery(
|
||||||
handle.queryPool,
|
handle.queryPool,
|
||||||
handle.queryId,
|
handle.queryId,
|
||||||
0);
|
handle.flags);
|
||||||
|
|
||||||
query.query->beginRecording(query.revision);
|
query.query->beginRecording(query.revision);
|
||||||
this->insertActiveQuery(query);
|
this->insertActiveQuery(query);
|
||||||
@ -1636,7 +1636,7 @@ namespace dxvk {
|
|||||||
DxvkQueryHandle DxvkContext::allocQuery(const DxvkQueryRevision& query) {
|
DxvkQueryHandle DxvkContext::allocQuery(const DxvkQueryRevision& query) {
|
||||||
const VkQueryType queryType = query.query->type();
|
const VkQueryType queryType = query.query->type();
|
||||||
|
|
||||||
DxvkQueryHandle queryHandle = { VK_NULL_HANDLE, 0 };
|
DxvkQueryHandle queryHandle = DxvkQueryHandle();
|
||||||
Rc<DxvkQueryPool> queryPool = m_queryPools[queryType];
|
Rc<DxvkQueryPool> queryPool = m_queryPools[queryType];
|
||||||
|
|
||||||
if (queryPool != nullptr)
|
if (queryPool != nullptr)
|
||||||
@ -1681,7 +1681,7 @@ namespace dxvk {
|
|||||||
m_cmd->cmdBeginQuery(
|
m_cmd->cmdBeginQuery(
|
||||||
handle.queryPool,
|
handle.queryPool,
|
||||||
handle.queryId,
|
handle.queryId,
|
||||||
0);
|
handle.flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,10 +17,8 @@ namespace dxvk {
|
|||||||
void DxvkEvent::signal(uint32_t revision) {
|
void DxvkEvent::signal(uint32_t revision) {
|
||||||
std::unique_lock<std::mutex> lock(m_mutex);
|
std::unique_lock<std::mutex> lock(m_mutex);
|
||||||
|
|
||||||
if (m_revision == revision) {
|
if (m_revision == revision)
|
||||||
m_status = DxvkEventStatus::Signaled;
|
m_status = DxvkEventStatus::Signaled;
|
||||||
m_signal.notify_one();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <condition_variable>
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
#include "dxvk_include.h"
|
#include "dxvk_include.h"
|
||||||
@ -49,8 +48,7 @@ namespace dxvk {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
std::mutex m_mutex;
|
std::mutex m_mutex;
|
||||||
std::condition_variable m_signal;
|
|
||||||
|
|
||||||
DxvkEventStatus m_status = DxvkEventStatus::Reset;
|
DxvkEventStatus m_status = DxvkEventStatus::Reset;
|
||||||
uint32_t m_revision = 0;
|
uint32_t m_revision = 0;
|
||||||
|
@ -2,8 +2,10 @@
|
|||||||
|
|
||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
|
|
||||||
DxvkQuery::DxvkQuery(VkQueryType type)
|
DxvkQuery::DxvkQuery(
|
||||||
: m_type(type) {
|
VkQueryType type,
|
||||||
|
VkQueryControlFlags flags)
|
||||||
|
: m_type(type), m_flags(flags) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,7 +59,6 @@ namespace dxvk {
|
|||||||
m_status = DxvkQueryStatus::Pending;
|
m_status = DxvkQueryStatus::Pending;
|
||||||
} else {
|
} else {
|
||||||
m_status = DxvkQueryStatus::Available;
|
m_status = DxvkQueryStatus::Available;
|
||||||
m_signal.notify_all();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_handle = DxvkQueryHandle();
|
m_handle = DxvkQueryHandle();
|
||||||
@ -110,10 +111,8 @@ namespace dxvk {
|
|||||||
Logger::err(str::format("DxvkQuery: Unhandled query type: ", m_type));
|
Logger::err(str::format("DxvkQuery: Unhandled query type: ", m_type));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (++m_queryIndex == m_queryCount && m_status == DxvkQueryStatus::Pending) {
|
if (++m_queryIndex == m_queryCount && m_status == DxvkQueryStatus::Pending)
|
||||||
m_status = DxvkQueryStatus::Available;
|
m_status = DxvkQueryStatus::Available;
|
||||||
m_signal.notify_all();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <condition_variable>
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
#include "dxvk_limits.h"
|
#include "dxvk_limits.h"
|
||||||
@ -78,8 +77,9 @@ namespace dxvk {
|
|||||||
* index of a single Vulkan query.
|
* index of a single Vulkan query.
|
||||||
*/
|
*/
|
||||||
struct DxvkQueryHandle {
|
struct DxvkQueryHandle {
|
||||||
VkQueryPool queryPool = VK_NULL_HANDLE;
|
VkQueryPool queryPool = VK_NULL_HANDLE;
|
||||||
uint32_t queryId = 0;
|
uint32_t queryId = 0;
|
||||||
|
VkQueryControlFlags flags = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -93,7 +93,9 @@ namespace dxvk {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DxvkQuery(VkQueryType type);
|
DxvkQuery(
|
||||||
|
VkQueryType type,
|
||||||
|
VkQueryControlFlags flags);
|
||||||
~DxvkQuery();
|
~DxvkQuery();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -104,6 +106,17 @@ namespace dxvk {
|
|||||||
return m_type;
|
return m_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Query control flags
|
||||||
|
*
|
||||||
|
* Flags that will be applied when
|
||||||
|
* calling \c vkCmdBeginQuery.
|
||||||
|
* \returns Query control flags
|
||||||
|
*/
|
||||||
|
VkQueryControlFlags flags() const {
|
||||||
|
return m_flags;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Resets the query object
|
* \brief Resets the query object
|
||||||
*
|
*
|
||||||
@ -172,10 +185,10 @@ namespace dxvk {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
const VkQueryType m_type;
|
const VkQueryType m_type;
|
||||||
|
const VkQueryControlFlags m_flags;
|
||||||
|
|
||||||
std::mutex m_mutex;
|
std::mutex m_mutex;
|
||||||
std::condition_variable m_signal;
|
|
||||||
|
|
||||||
DxvkQueryStatus m_status = DxvkQueryStatus::Reset;
|
DxvkQueryStatus m_status = DxvkQueryStatus::Reset;
|
||||||
DxvkQueryData m_data = {};
|
DxvkQueryData m_data = {};
|
||||||
|
@ -48,7 +48,10 @@ namespace dxvk {
|
|||||||
const uint32_t queryIndex = m_queryRangeOffset + m_queryRangeLength;
|
const uint32_t queryIndex = m_queryRangeOffset + m_queryRangeLength;
|
||||||
|
|
||||||
if (queryIndex < m_queryCount) {
|
if (queryIndex < m_queryCount) {
|
||||||
const DxvkQueryHandle result = { m_queryPool, queryIndex };
|
DxvkQueryHandle result;
|
||||||
|
result.queryPool = m_queryPool;
|
||||||
|
result.queryId = queryIndex;
|
||||||
|
result.flags = query.query->flags();
|
||||||
|
|
||||||
query.query->associateQuery(query.revision, result);
|
query.query->associateQuery(query.revision, result);
|
||||||
m_queries.at(queryIndex) = query;
|
m_queries.at(queryIndex) = query;
|
||||||
@ -56,7 +59,7 @@ namespace dxvk {
|
|||||||
m_queryRangeLength += 1;
|
m_queryRangeLength += 1;
|
||||||
return result;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
return DxvkQueryHandle { VK_NULL_HANDLE, 0 };
|
return DxvkQueryHandle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,8 +9,6 @@ namespace dxvk {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Query range
|
* \brief Query range
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
struct DxvkQueryRange {
|
struct DxvkQueryRange {
|
||||||
Rc<DxvkQueryPool> queryPool;
|
Rc<DxvkQueryPool> queryPool;
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <windowsx.h>
|
#include <windowsx.h>
|
||||||
|
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
#include "../test_utils.h"
|
#include "../test_utils.h"
|
||||||
|
|
||||||
using namespace dxvk;
|
using namespace dxvk;
|
||||||
@ -242,6 +244,12 @@ public:
|
|||||||
&m_vertexFormat)))
|
&m_vertexFormat)))
|
||||||
throw DxvkError("Failed to create input layout");
|
throw DxvkError("Failed to create input layout");
|
||||||
|
|
||||||
|
D3D11_QUERY_DESC queryDesc;
|
||||||
|
queryDesc.Query = D3D11_QUERY_OCCLUSION;
|
||||||
|
queryDesc.MiscFlags = 0;
|
||||||
|
|
||||||
|
if (FAILED(m_device->CreateQuery(&queryDesc, &m_query)))
|
||||||
|
throw DxvkError("Failed to create occlusion query");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -275,11 +283,13 @@ public:
|
|||||||
UINT vsOffset = 0;
|
UINT vsOffset = 0;
|
||||||
|
|
||||||
// Test normal draws with base vertex
|
// Test normal draws with base vertex
|
||||||
|
m_context->Begin(m_query.ptr());
|
||||||
m_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
m_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||||
m_context->IASetInputLayout(m_vertexFormat.ptr());
|
m_context->IASetInputLayout(m_vertexFormat.ptr());
|
||||||
m_context->IASetVertexBuffers(0, 1, &m_vertexBuffer, &vsStride, &vsOffset);
|
m_context->IASetVertexBuffers(0, 1, &m_vertexBuffer, &vsStride, &vsOffset);
|
||||||
m_context->Draw(3, 0);
|
m_context->Draw(3, 0);
|
||||||
m_context->Draw(3, 3);
|
m_context->Draw(3, 3);
|
||||||
|
m_context->End(m_query.ptr());
|
||||||
|
|
||||||
// Test instanced draws with base instance and base vertex
|
// Test instanced draws with base instance and base vertex
|
||||||
vsOffset = 6 * sizeof(Vertex);
|
vsOffset = 6 * sizeof(Vertex);
|
||||||
@ -302,6 +312,26 @@ public:
|
|||||||
m_context->OMSetRenderTargets(0, nullptr, nullptr);
|
m_context->OMSetRenderTargets(0, nullptr, nullptr);
|
||||||
|
|
||||||
m_swapChain->Present(0, 0);
|
m_swapChain->Present(0, 0);
|
||||||
|
|
||||||
|
// Test query results
|
||||||
|
while (true) {
|
||||||
|
UINT64 samplesPassed = 0;
|
||||||
|
|
||||||
|
UINT queryStatus = m_context->GetData(
|
||||||
|
m_query.ptr(), &samplesPassed, sizeof(samplesPassed),
|
||||||
|
D3D11_ASYNC_GETDATA_DONOTFLUSH);
|
||||||
|
|
||||||
|
if (queryStatus == S_OK) {
|
||||||
|
if (samplesPassed == 0)
|
||||||
|
std::cerr << "Occlusion query returned 0 samples" << std::endl;
|
||||||
|
break;
|
||||||
|
} else if (queryStatus == S_FALSE) {
|
||||||
|
std::this_thread::yield();
|
||||||
|
} else {
|
||||||
|
std::cerr << "Occlusion query failed" << std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -354,6 +384,8 @@ private:
|
|||||||
Com<ID3D11VertexShader> m_vertexShader;
|
Com<ID3D11VertexShader> m_vertexShader;
|
||||||
Com<ID3D11PixelShader> m_pixelShader;
|
Com<ID3D11PixelShader> m_pixelShader;
|
||||||
|
|
||||||
|
Com<ID3D11Query> m_query;
|
||||||
|
|
||||||
D3D_FEATURE_LEVEL m_featureLevel;
|
D3D_FEATURE_LEVEL m_featureLevel;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user