make occlusion queries accumulate with draws

This commit is contained in:
Samuliak 2024-10-30 09:20:50 +01:00
parent 00256e5589
commit e7ac19979d
No known key found for this signature in database
5 changed files with 40 additions and 37 deletions

View File

@ -22,6 +22,13 @@ struct MetalPixelFormatSupport
} }
}; };
// TODO: don't define a new struct for this
struct MetalQueryRange
{
uint32 begin;
uint32 end;
};
#define MAX_MTL_BUFFERS 31 #define MAX_MTL_BUFFERS 31
// Buffer indices 28-30 are reserved for the helper shaders // Buffer indices 28-30 are reserved for the helper shaders
#define GET_MTL_VERTEX_BUFFER_INDEX(index) (MAX_MTL_BUFFERS - index - 4) #define GET_MTL_VERTEX_BUFFER_INDEX(index) (MAX_MTL_BUFFERS - index - 4)

View File

@ -1,6 +1,5 @@
#include "Cafe/HW/Latte/Renderer/Metal/MetalQuery.h" #include "Cafe/HW/Latte/Renderer/Metal/MetalQuery.h"
#include "Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h" #include "Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h"
#include "HW/Latte/Renderer/Metal/MetalCommon.h"
bool LatteQueryObjectMtl::getResult(uint64& numSamplesPassed) bool LatteQueryObjectMtl::getResult(uint64& numSamplesPassed)
{ {
@ -13,29 +12,31 @@ bool LatteQueryObjectMtl::getResult(uint64& numSamplesPassed)
if (!CommandBufferCompleted(m_commandBuffer)) if (!CommandBufferCompleted(m_commandBuffer))
return false; return false;
numSamplesPassed = m_mtlr->GetOcclusionQueryResultsPtr()[m_queryIndex]; uint64* resultPtr = m_mtlr->GetOcclusionQueryResultsPtr();
numSamplesPassed = 0;
for (uint32 i = m_range.begin; i != m_range.end; i = (i + 1) % MetalRenderer::OCCLUSION_QUERY_POOL_SIZE)
numSamplesPassed += resultPtr[i];
return true; return true;
} }
LatteQueryObjectMtl::~LatteQueryObjectMtl() LatteQueryObjectMtl::~LatteQueryObjectMtl()
{ {
if (m_queryIndex != INVALID_UINT32)
m_mtlr->ReleaseOcclusionQueryIndex(m_queryIndex);
if (m_commandBuffer) if (m_commandBuffer)
m_commandBuffer->release(); m_commandBuffer->release();
} }
void LatteQueryObjectMtl::begin() void LatteQueryObjectMtl::begin()
{ {
m_queryIndex = m_mtlr->GetAvailableOcclusionQueryIndex(); m_range.begin = m_mtlr->GetOcclusionQueryIndex();
m_mtlr->SetActiveOcclusionQueryIndex(m_queryIndex); m_mtlr->BeginOcclusionQuery();
} }
void LatteQueryObjectMtl::end() void LatteQueryObjectMtl::end()
{ {
m_mtlr->SetActiveOcclusionQueryIndex(INVALID_UINT32); m_range.end = m_mtlr->GetOcclusionQueryIndex();
m_mtlr->EndOcclusionQuery();
if (m_mtlr->IsCommandBufferActive()) if (m_mtlr->IsCommandBufferActive())
{ {
m_commandBuffer = m_mtlr->GetCurrentCommandBuffer()->retain(); m_commandBuffer = m_mtlr->GetCurrentCommandBuffer()->retain();

View File

@ -14,10 +14,15 @@ public:
void begin() override; void begin() override;
void end() override; void end() override;
void GrowRange()
{
m_range.end++;
}
private: private:
class MetalRenderer* m_mtlr; class MetalRenderer* m_mtlr;
uint32 m_queryIndex = INVALID_UINT32; MetalQueryRange m_range = {INVALID_UINT32, INVALID_UINT32};
// TODO: make this a list of command buffers // TODO: make this a list of command buffers
MTL::CommandBuffer* m_commandBuffer = nullptr; MTL::CommandBuffer* m_commandBuffer = nullptr;
}; };

View File

@ -31,7 +31,6 @@
#include "imgui/imgui_impl_metal.h" #include "imgui/imgui_impl_metal.h"
#define DEFAULT_COMMIT_TRESHOLD 196 #define DEFAULT_COMMIT_TRESHOLD 196
#define OCCLUSION_QUERY_POOL_SIZE 1024
extern bool hasValidFramebufferAttached; extern bool hasValidFramebufferAttached;
@ -98,10 +97,6 @@ MetalRenderer::MetalRenderer()
#endif #endif
m_occlusionQuery.m_resultsPtr = (uint64*)m_occlusionQuery.m_resultBuffer->contents(); m_occlusionQuery.m_resultsPtr = (uint64*)m_occlusionQuery.m_resultBuffer->contents();
m_occlusionQuery.m_availableIndices.reserve(OCCLUSION_QUERY_POOL_SIZE);
for (uint32 i = 0; i < OCCLUSION_QUERY_POOL_SIZE; i++)
m_occlusionQuery.m_availableIndices.push_back(i);
// Initialize state // Initialize state
for (uint32 i = 0; i < METAL_SHADER_TYPE_TOTAL; i++) for (uint32 i = 0; i < METAL_SHADER_TYPE_TOTAL; i++)
{ {
@ -1115,11 +1110,10 @@ void MetalRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32
} }
// Visibility result mode // Visibility result mode
if (m_occlusionQuery.m_activeIndex != encoderState.m_visibilityResultOffset) if (m_occlusionQuery.m_active)
{ {
auto mode = (m_occlusionQuery.m_activeIndex == INVALID_UINT32 ? MTL::VisibilityResultModeDisabled : MTL::VisibilityResultModeCounting); auto mode = (m_occlusionQuery.m_currentIndex == INVALID_UINT32 ? MTL::VisibilityResultModeDisabled : MTL::VisibilityResultModeCounting);
renderCommandEncoder->setVisibilityResultMode(mode, m_occlusionQuery.m_activeIndex * sizeof(uint64)); renderCommandEncoder->setVisibilityResultMode(mode, m_occlusionQuery.m_currentIndex * sizeof(uint64));
encoderState.m_visibilityResultOffset = m_occlusionQuery.m_activeIndex;
} }
// todo - how does culling behave with rects? // todo - how does culling behave with rects?
@ -1302,6 +1296,11 @@ void MetalRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32
m_state.m_isFirstDrawInRenderPass = false; m_state.m_isFirstDrawInRenderPass = false;
// Occlusion queries
if (m_occlusionQuery.m_active)
m_occlusionQuery.m_currentIndex = (m_occlusionQuery.m_currentIndex + 1) % OCCLUSION_QUERY_POOL_SIZE;
// Streamout
LatteStreamout_FinishDrawcall(false); LatteStreamout_FinishDrawcall(false);
// Debug // Debug

View File

@ -104,7 +104,6 @@ struct MetalEncoderState
uint32 m_depthSlope = 0; uint32 m_depthSlope = 0;
uint32 m_depthClamp = 0; uint32 m_depthClamp = 0;
bool m_depthClipEnable = true; bool m_depthClipEnable = true;
uint32 m_visibilityResultOffset = INVALID_UINT32;
struct { struct {
MTL::Buffer* m_buffer; MTL::Buffer* m_buffer;
size_t m_offset; size_t m_offset;
@ -170,7 +169,8 @@ enum class MetalEncoderType
class MetalRenderer : public Renderer class MetalRenderer : public Renderer
{ {
public: public:
static const inline int TEXTURE_READBACK_SIZE = 32 * 1024 * 1024; // 32 MB static constexpr uint32 OCCLUSION_QUERY_POOL_SIZE = 1024;
static constexpr uint32 TEXTURE_READBACK_SIZE = 32 * 1024 * 1024; // 32 MB
MetalRenderer(); MetalRenderer();
~MetalRenderer() override; ~MetalRenderer() override;
@ -428,28 +428,19 @@ public:
return m_occlusionQuery.m_resultsPtr; return m_occlusionQuery.m_resultsPtr;
} }
uint32 GetAvailableOcclusionQueryIndex() uint32 GetOcclusionQueryIndex()
{ {
if (m_occlusionQuery.m_availableIndices.empty()) return m_occlusionQuery.m_currentIndex;
{
cemuLog_log(LogType::Force, "No occlusion query index available");
return 0;
} }
uint32 queryIndex = m_occlusionQuery.m_availableIndices.back(); void BeginOcclusionQuery()
m_occlusionQuery.m_availableIndices.pop_back(); {
m_occlusionQuery.m_active = true;
return queryIndex;
} }
void ReleaseOcclusionQueryIndex(uint32 queryIndex) void EndOcclusionQuery()
{ {
m_occlusionQuery.m_availableIndices.push_back(queryIndex); m_occlusionQuery.m_active = false;
}
void SetActiveOcclusionQueryIndex(uint32 queryIndex)
{
m_occlusionQuery.m_activeIndex = queryIndex;
} }
private: private:
@ -505,8 +496,8 @@ private:
{ {
MTL::Buffer* m_resultBuffer; MTL::Buffer* m_resultBuffer;
uint64* m_resultsPtr; uint64* m_resultsPtr;
std::vector<uint32> m_availableIndices; uint32 m_currentIndex = 0;
uint32 m_activeIndex = INVALID_UINT32; bool m_active = false;
} m_occlusionQuery; } m_occlusionQuery;
// Active objects // Active objects