diff --git a/src/d3d11/d3d11_blend.cpp b/src/d3d11/d3d11_blend.cpp index 6e56c385..90aeb478 100644 --- a/src/d3d11/d3d11_blend.cpp +++ b/src/d3d11/d3d11_blend.cpp @@ -21,7 +21,7 @@ namespace dxvk { m_msState.sampleMask = 0; // Set during bind m_msState.enableAlphaToCoverage = desc.AlphaToCoverageEnable; m_msState.enableAlphaToOne = VK_FALSE; - m_msState.enableSampleShading = VK_TRUE; + m_msState.enableSampleShading = VK_FALSE; m_msState.minSampleShading = 0.0f; // In 11_0, there is no logic op state. Later versions diff --git a/src/d3d11/d3d11_context_imm.cpp b/src/d3d11/d3d11_context_imm.cpp index d6e068bd..cccbafc3 100644 --- a/src/d3d11/d3d11_context_imm.cpp +++ b/src/d3d11/d3d11_context_imm.cpp @@ -41,21 +41,23 @@ namespace dxvk { void STDMETHODCALLTYPE D3D11ImmediateContext::Flush() { - 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); + if (m_csChunk->commandCount() != 0) { + m_parent->FlushInitContext(); + m_drawCount = 0; - ctx->beginRecording( - dev->createCommandList()); - }); - - FlushCsChunk(); + // 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( + dev->createCommandList()); + }); + + FlushCsChunk(); + } } diff --git a/src/d3d11/d3d11_query.cpp b/src/d3d11/d3d11_query.cpp index 90914a51..998311ec 100644 --- a/src/d3d11/d3d11_query.cpp +++ b/src/d3d11/d3d11_query.cpp @@ -13,19 +13,27 @@ namespace dxvk { break; case D3D11_QUERY_OCCLUSION: + m_query = new DxvkQuery( + VK_QUERY_TYPE_OCCLUSION, + VK_QUERY_CONTROL_PRECISE_BIT); + break; + case D3D11_QUERY_OCCLUSION_PREDICATE: - m_query = new DxvkQuery(VK_QUERY_TYPE_OCCLUSION); + m_query = new DxvkQuery( + VK_QUERY_TYPE_OCCLUSION, 0); break; case D3D11_QUERY_TIMESTAMP: - m_query = new DxvkQuery(VK_QUERY_TYPE_TIMESTAMP); + m_query = new DxvkQuery( + VK_QUERY_TYPE_TIMESTAMP, 0); break; case D3D11_QUERY_TIMESTAMP_DISJOINT: break; 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; default: diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index 8ff4bf39..4056f6e9 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -73,7 +73,7 @@ namespace dxvk { m_cmd->cmdBeginQuery( handle.queryPool, handle.queryId, - 0); + handle.flags); query.query->beginRecording(query.revision); this->insertActiveQuery(query); @@ -1636,7 +1636,7 @@ namespace dxvk { DxvkQueryHandle DxvkContext::allocQuery(const DxvkQueryRevision& query) { const VkQueryType queryType = query.query->type(); - DxvkQueryHandle queryHandle = { VK_NULL_HANDLE, 0 }; + DxvkQueryHandle queryHandle = DxvkQueryHandle(); Rc queryPool = m_queryPools[queryType]; if (queryPool != nullptr) @@ -1681,7 +1681,7 @@ namespace dxvk { m_cmd->cmdBeginQuery( handle.queryPool, handle.queryId, - 0); + handle.flags); } } diff --git a/src/dxvk/dxvk_event.cpp b/src/dxvk/dxvk_event.cpp index 31bce013..0f2aff70 100644 --- a/src/dxvk/dxvk_event.cpp +++ b/src/dxvk/dxvk_event.cpp @@ -17,10 +17,8 @@ namespace dxvk { void DxvkEvent::signal(uint32_t revision) { std::unique_lock lock(m_mutex); - if (m_revision == revision) { + if (m_revision == revision) m_status = DxvkEventStatus::Signaled; - m_signal.notify_one(); - } } diff --git a/src/dxvk/dxvk_event.h b/src/dxvk/dxvk_event.h index 33c1e1ea..325e1cea 100644 --- a/src/dxvk/dxvk_event.h +++ b/src/dxvk/dxvk_event.h @@ -1,6 +1,5 @@ #pragma once -#include #include #include "dxvk_include.h" @@ -49,8 +48,7 @@ namespace dxvk { private: - std::mutex m_mutex; - std::condition_variable m_signal; + std::mutex m_mutex; DxvkEventStatus m_status = DxvkEventStatus::Reset; uint32_t m_revision = 0; diff --git a/src/dxvk/dxvk_query.cpp b/src/dxvk/dxvk_query.cpp index b7f6a417..520b3928 100644 --- a/src/dxvk/dxvk_query.cpp +++ b/src/dxvk/dxvk_query.cpp @@ -2,8 +2,10 @@ namespace dxvk { - DxvkQuery::DxvkQuery(VkQueryType type) - : m_type(type) { + DxvkQuery::DxvkQuery( + VkQueryType type, + VkQueryControlFlags flags) + : m_type(type), m_flags(flags) { } @@ -57,7 +59,6 @@ namespace dxvk { m_status = DxvkQueryStatus::Pending; } else { m_status = DxvkQueryStatus::Available; - m_signal.notify_all(); } m_handle = DxvkQueryHandle(); @@ -110,10 +111,8 @@ namespace dxvk { 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_signal.notify_all(); - } } } diff --git a/src/dxvk/dxvk_query.h b/src/dxvk/dxvk_query.h index e71d3219..bf4fc410 100644 --- a/src/dxvk/dxvk_query.h +++ b/src/dxvk/dxvk_query.h @@ -1,6 +1,5 @@ #pragma once -#include #include #include "dxvk_limits.h" @@ -78,8 +77,9 @@ namespace dxvk { * index of a single Vulkan query. */ struct DxvkQueryHandle { - VkQueryPool queryPool = VK_NULL_HANDLE; - uint32_t queryId = 0; + VkQueryPool queryPool = VK_NULL_HANDLE; + uint32_t queryId = 0; + VkQueryControlFlags flags = 0; }; /** @@ -93,7 +93,9 @@ namespace dxvk { public: - DxvkQuery(VkQueryType type); + DxvkQuery( + VkQueryType type, + VkQueryControlFlags flags); ~DxvkQuery(); /** @@ -104,6 +106,17 @@ namespace dxvk { 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 * @@ -172,10 +185,10 @@ namespace dxvk { private: - const VkQueryType m_type; + const VkQueryType m_type; + const VkQueryControlFlags m_flags; - std::mutex m_mutex; - std::condition_variable m_signal; + std::mutex m_mutex; DxvkQueryStatus m_status = DxvkQueryStatus::Reset; DxvkQueryData m_data = {}; diff --git a/src/dxvk/dxvk_query_pool.cpp b/src/dxvk/dxvk_query_pool.cpp index 31826ee6..ac4f5e66 100644 --- a/src/dxvk/dxvk_query_pool.cpp +++ b/src/dxvk/dxvk_query_pool.cpp @@ -48,7 +48,10 @@ namespace dxvk { const uint32_t queryIndex = m_queryRangeOffset + m_queryRangeLength; 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); m_queries.at(queryIndex) = query; @@ -56,7 +59,7 @@ namespace dxvk { m_queryRangeLength += 1; return result; } else { - return DxvkQueryHandle { VK_NULL_HANDLE, 0 }; + return DxvkQueryHandle(); } } diff --git a/src/dxvk/dxvk_query_pool.h b/src/dxvk/dxvk_query_pool.h index 2c3110f7..cd6c4953 100644 --- a/src/dxvk/dxvk_query_pool.h +++ b/src/dxvk/dxvk_query_pool.h @@ -9,8 +9,6 @@ namespace dxvk { /** * \brief Query range - * - * */ struct DxvkQueryRange { Rc queryPool; diff --git a/tests/d3d11/test_d3d11_triangle.cpp b/tests/d3d11/test_d3d11_triangle.cpp index 797c3011..258d825d 100644 --- a/tests/d3d11/test_d3d11_triangle.cpp +++ b/tests/d3d11/test_d3d11_triangle.cpp @@ -4,6 +4,8 @@ #include #include +#include + #include "../test_utils.h" using namespace dxvk; @@ -242,6 +244,12 @@ public: &m_vertexFormat))) 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; // Test normal draws with base vertex + m_context->Begin(m_query.ptr()); m_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); m_context->IASetInputLayout(m_vertexFormat.ptr()); m_context->IASetVertexBuffers(0, 1, &m_vertexBuffer, &vsStride, &vsOffset); m_context->Draw(3, 0); m_context->Draw(3, 3); + m_context->End(m_query.ptr()); // Test instanced draws with base instance and base vertex vsOffset = 6 * sizeof(Vertex); @@ -302,6 +312,26 @@ public: m_context->OMSetRenderTargets(0, nullptr, nullptr); 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 m_vertexShader; Com m_pixelShader; + Com m_query; + D3D_FEATURE_LEVEL m_featureLevel; };