mirror of
https://github.com/cemu-project/Cemu.git
synced 2024-11-29 20:44:18 +01:00
make occlusion queries accumulate with draws
This commit is contained in:
parent
00256e5589
commit
e7ac19979d
@ -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)
|
||||||
|
@ -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();
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user