mirror of
https://github.com/cemu-project/Cemu.git
synced 2025-01-07 15:48:15 +01:00
implement occlusion queries
This commit is contained in:
parent
4cce3699f3
commit
eb7c10e89f
@ -1,9 +1,9 @@
|
||||
#include "Cafe/HW/Latte/Renderer/Metal/CachedFBOMtl.h"
|
||||
#include "Cafe/HW/Latte/Renderer/Metal/LatteTextureViewMtl.h"
|
||||
#include "HW/Latte/Renderer/Metal/LatteToMtl.h"
|
||||
#include "Metal/MTLRenderPass.hpp"
|
||||
#include "Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h"
|
||||
#include "Cafe/HW/Latte/Renderer/Metal/LatteToMtl.h"
|
||||
|
||||
void CachedFBOMtl::CreateRenderPass()
|
||||
CachedFBOMtl::CachedFBOMtl(class MetalRenderer* metalRenderer, uint64 key) : LatteCachedFBO(key)
|
||||
{
|
||||
m_renderPassDescriptor = MTL::RenderPassDescriptor::alloc()->init();
|
||||
|
||||
@ -39,6 +39,9 @@ void CachedFBOMtl::CreateRenderPass()
|
||||
stencilAttachment->setStoreAction(MTL::StoreActionStore);
|
||||
}
|
||||
}
|
||||
|
||||
// Visibility buffer
|
||||
m_renderPassDescriptor->setVisibilityResultBuffer(metalRenderer->GetOcclusionQueryResultBuffer());
|
||||
}
|
||||
|
||||
CachedFBOMtl::~CachedFBOMtl()
|
||||
|
@ -8,10 +8,7 @@
|
||||
class CachedFBOMtl : public LatteCachedFBO
|
||||
{
|
||||
public:
|
||||
CachedFBOMtl(uint64 key) : LatteCachedFBO(key)
|
||||
{
|
||||
CreateRenderPass();
|
||||
}
|
||||
CachedFBOMtl(class MetalRenderer* metalRenderer, uint64 key);
|
||||
|
||||
~CachedFBOMtl();
|
||||
|
||||
@ -22,6 +19,4 @@ public:
|
||||
|
||||
private:
|
||||
MTL::RenderPassDescriptor* m_renderPassDescriptor = nullptr;
|
||||
|
||||
void CreateRenderPass();
|
||||
};
|
||||
|
@ -1,17 +1,25 @@
|
||||
#include "Cafe/HW/Latte/Renderer/Metal/MetalQuery.h"
|
||||
#include "Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h"
|
||||
#include "HW/Latte/Renderer/Metal/MetalCommon.h"
|
||||
|
||||
bool LatteQueryObjectMtl::getResult(uint64& numSamplesPassed)
|
||||
{
|
||||
cemuLog_log(LogType::MetalLogging, "LatteQueryObjectMtl::getResult: occlusion queries are not yet supported on Metal");
|
||||
if (!m_mtlr->CommandBufferCompleted(m_commandBuffer))
|
||||
return false;
|
||||
|
||||
numSamplesPassed = m_mtlr->GetOcclusionQueryResultsPtr()[m_queryIndex];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void LatteQueryObjectMtl::begin()
|
||||
{
|
||||
cemuLog_log(LogType::MetalLogging, "LatteQueryObjectMtl::begin: occlusion queries are not yet supported on Metal");
|
||||
m_queryIndex = m_mtlr->GetAvailableOcclusionQueryIndex();
|
||||
m_mtlr->SetActiveOcclusionQueryIndex(m_queryIndex);
|
||||
}
|
||||
|
||||
void LatteQueryObjectMtl::end()
|
||||
{
|
||||
cemuLog_log(LogType::MetalLogging, "LatteQueryObjectMtl::end: occlusion queries are not yet supported on Metal");
|
||||
m_mtlr->SetActiveOcclusionQueryIndex(INVALID_UINT32);
|
||||
// TODO: request soon submit of the command buffer
|
||||
}
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
#include "Cafe/HW/Latte/Renderer/Metal/MetalCommon.h"
|
||||
|
||||
// HACK: Dummy occlusion query object
|
||||
class LatteQueryObjectMtl : public LatteQueryObject
|
||||
{
|
||||
public:
|
||||
@ -16,4 +15,8 @@ public:
|
||||
|
||||
private:
|
||||
class MetalRenderer* m_mtlr;
|
||||
|
||||
uint32 m_queryIndex;
|
||||
MTL::CommandBuffer* m_commandBuffer;
|
||||
uint64 m_acccumulatedSum;
|
||||
};
|
||||
|
@ -21,12 +21,14 @@
|
||||
#include "HW/Latte/Renderer/Metal/MetalCommon.h"
|
||||
#include "HW/Latte/Renderer/Metal/MetalLayerHandle.h"
|
||||
#include "HW/Latte/Renderer/Renderer.h"
|
||||
#include "Metal/MTLRenderCommandEncoder.hpp"
|
||||
|
||||
#define IMGUI_IMPL_METAL_CPP
|
||||
#include "imgui/imgui_extension.h"
|
||||
#include "imgui/imgui_impl_metal.h"
|
||||
|
||||
#define COMMIT_TRESHOLD 256
|
||||
#define OCCLUSION_QUERY_POOL_SIZE 1024
|
||||
|
||||
extern bool hasValidFramebufferAttached;
|
||||
|
||||
@ -94,6 +96,17 @@ MetalRenderer::MetalRenderer()
|
||||
m_xfbRingBuffer->setLabel(GetLabel("Transform feedback buffer", m_xfbRingBuffer));
|
||||
#endif
|
||||
|
||||
// Occlusion queries
|
||||
m_occlusionQuery.m_resultBuffer = m_device->newBuffer(OCCLUSION_QUERY_POOL_SIZE * sizeof(uint64), MTL::ResourceStorageModeShared);
|
||||
#ifdef CEMU_DEBUG_ASSERT
|
||||
m_occlusionQuery.m_resultBuffer->setLabel(GetLabel("Occlusion query result buffer", m_occlusionQuery.m_resultBuffer));
|
||||
#endif
|
||||
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
|
||||
for (uint32 i = 0; i < METAL_SHADER_TYPE_TOTAL; i++)
|
||||
{
|
||||
@ -467,7 +480,7 @@ void MetalRenderer::renderTarget_setScissor(sint32 scissorX, sint32 scissorY, si
|
||||
|
||||
LatteCachedFBO* MetalRenderer::rendertarget_createCachedFBO(uint64 key)
|
||||
{
|
||||
return new CachedFBOMtl(key);
|
||||
return new CachedFBOMtl(this, key);
|
||||
}
|
||||
|
||||
void MetalRenderer::rendertarget_deleteCachedFBO(LatteCachedFBO* cfbo)
|
||||
@ -1042,6 +1055,14 @@ void MetalRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32
|
||||
encoderState.m_depthClipEnable = zClipEnable;
|
||||
}
|
||||
|
||||
// Visibility result mode
|
||||
if (m_occlusionQuery.m_activeIndex != encoderState.m_visibilityResultOffset)
|
||||
{
|
||||
auto mode = (m_occlusionQuery.m_activeIndex == INVALID_UINT32 ? MTL::VisibilityResultModeDisabled : MTL::VisibilityResultModeCounting);
|
||||
renderCommandEncoder->setVisibilityResultMode(mode, m_occlusionQuery.m_activeIndex);
|
||||
encoderState.m_visibilityResultOffset = m_occlusionQuery.m_activeIndex;
|
||||
}
|
||||
|
||||
// todo - how does culling behave with rects?
|
||||
// right now we just assume that their winding is always CW
|
||||
if (isPrimitiveRect)
|
||||
@ -1284,21 +1305,20 @@ void MetalRenderer::indexData_uploadIndexMemory(uint32 bufferIndex, uint32 offse
|
||||
}
|
||||
|
||||
LatteQueryObject* MetalRenderer::occlusionQuery_create() {
|
||||
cemuLog_log(LogType::MetalLogging, "MetalRenderer::occlusionQuery_create: Occlusion queries are not yet supported on Metal");
|
||||
|
||||
return new LatteQueryObjectMtl(this);
|
||||
}
|
||||
|
||||
void MetalRenderer::occlusionQuery_destroy(LatteQueryObject* queryObj) {
|
||||
cemuLog_log(LogType::MetalLogging, "MetalRenderer::occlusionQuery_destroy: occlusion queries are not yet supported on Metal");
|
||||
// TODO: do something?
|
||||
}
|
||||
|
||||
void MetalRenderer::occlusionQuery_flush() {
|
||||
cemuLog_log(LogType::MetalLogging, "MetalRenderer::occlusionQuery_flush: occlusion queries are not yet supported on Metal");
|
||||
// TODO: implement
|
||||
debug_printf("Occlusion query flush is not implemented\n");
|
||||
}
|
||||
|
||||
void MetalRenderer::occlusionQuery_updateState() {
|
||||
cemuLog_log(LogType::MetalLogging, "MetalRenderer::occlusionQuery_updateState: occlusion queries are not yet supported on Metal");
|
||||
// TODO
|
||||
}
|
||||
|
||||
void MetalRenderer::SetBuffer(MTL::RenderCommandEncoder* renderCommandEncoder, MetalShaderType shaderType, MTL::Buffer* buffer, size_t offset, uint32 index)
|
||||
@ -1574,6 +1594,8 @@ void MetalRenderer::CommitCommandBuffer()
|
||||
|
||||
m_memoryManager->GetTemporaryBufferAllocator().SetActiveCommandBuffer(nullptr);
|
||||
|
||||
m_occlusionQuery.m_availableIndices.insert(m_occlusionQuery.m_availableIndices.end(), m_occlusionQuery.m_crntCmdBuffIndices.begin(), m_occlusionQuery.m_crntCmdBuffIndices.end());
|
||||
|
||||
// Debug
|
||||
//m_commandQueue->insertDebugCaptureBoundary();
|
||||
}
|
||||
|
@ -99,6 +99,7 @@ struct MetalEncoderState
|
||||
uint32 m_depthSlope = 0;
|
||||
uint32 m_depthClamp = 0;
|
||||
bool m_depthClipEnable = true;
|
||||
uint32 m_visibilityResultOffset = INVALID_UINT32;
|
||||
struct {
|
||||
MTL::Buffer* m_buffer;
|
||||
size_t m_offset;
|
||||
@ -376,6 +377,36 @@ public:
|
||||
return m_readbackBuffer;
|
||||
}
|
||||
|
||||
MTL::Buffer* GetOcclusionQueryResultBuffer() const
|
||||
{
|
||||
return m_occlusionQuery.m_resultBuffer;
|
||||
}
|
||||
|
||||
uint64* GetOcclusionQueryResultsPtr()
|
||||
{
|
||||
return m_occlusionQuery.m_resultsPtr;
|
||||
}
|
||||
|
||||
uint32 GetAvailableOcclusionQueryIndex()
|
||||
{
|
||||
if (m_occlusionQuery.m_availableIndices.empty())
|
||||
{
|
||||
cemuLog_log(LogType::Force, "No occlusion query index available");
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 queryIndex = m_occlusionQuery.m_availableIndices.back();
|
||||
m_occlusionQuery.m_availableIndices.pop_back();
|
||||
m_occlusionQuery.m_crntCmdBuffIndices.push_back(queryIndex);
|
||||
|
||||
return queryIndex;
|
||||
}
|
||||
|
||||
void SetActiveOcclusionQueryIndex(uint32 queryIndex)
|
||||
{
|
||||
m_occlusionQuery.m_activeIndex = queryIndex;
|
||||
}
|
||||
|
||||
private:
|
||||
MetalLayerHandle m_mainLayer;
|
||||
MetalLayerHandle m_padLayer;
|
||||
@ -423,6 +454,16 @@ private:
|
||||
// Transform feedback
|
||||
MTL::Buffer* m_xfbRingBuffer;
|
||||
|
||||
// Occlusion queries
|
||||
struct
|
||||
{
|
||||
MTL::Buffer* m_resultBuffer;
|
||||
uint64* m_resultsPtr;
|
||||
std::vector<uint32> m_availableIndices;
|
||||
std::vector<uint32> m_crntCmdBuffIndices;
|
||||
uint32 m_activeIndex = INVALID_UINT32;
|
||||
} m_occlusionQuery;
|
||||
|
||||
// Active objects
|
||||
std::vector<MetalCommandBuffer> m_commandBuffers;
|
||||
MetalEncoderType m_encoderType = MetalEncoderType::None;
|
||||
|
Loading…
Reference in New Issue
Block a user