GPU: Add host/hardware stats
This commit is contained in:
@ -513,6 +513,8 @@ void D3D11Device::CopyTextureRegion(GPUTexture* dst, u32 dst_x, u32 dst_y, u32 d
|
||||
|
||||
src11->CommitClear(m_context.Get());
|
||||
|
||||
s_stats.num_copies++;
|
||||
|
||||
const CD3D11_BOX src_box(static_cast<LONG>(src_x), static_cast<LONG>(src_y), 0, static_cast<LONG>(src_x + width),
|
||||
static_cast<LONG>(src_y + height), 1);
|
||||
m_context->CopySubresourceRegion(dst11->GetD3DTexture(), D3D11CalcSubresource(dst_level, dst_layer, dst->GetLevels()),
|
||||
@ -531,6 +533,8 @@ void D3D11Device::ResolveTextureRegion(GPUTexture* dst, u32 dst_x, u32 dst_y, u3
|
||||
DebugAssert((dst_y + height) <= dst->GetMipHeight(dst_level));
|
||||
DebugAssert(!dst->IsMultisampled() && src->IsMultisampled());
|
||||
|
||||
s_stats.num_copies++;
|
||||
|
||||
// DX11 can't resolve partial rects.
|
||||
Assert(src_x == 0 && src_y == 0 && width == src->GetWidth() && height == src->GetHeight() && dst_x == 0 &&
|
||||
dst_y == 0 && width == dst->GetMipWidth(dst_level) && height == dst->GetMipHeight(dst_level));
|
||||
@ -635,6 +639,7 @@ bool D3D11Device::BeginPresent(bool skip_present)
|
||||
static constexpr float clear_color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
|
||||
m_context->ClearRenderTargetView(m_swap_chain_rtv.Get(), clear_color);
|
||||
m_context->OMSetRenderTargets(1, m_swap_chain_rtv.GetAddressOf(), nullptr);
|
||||
s_stats.num_render_passes++;
|
||||
m_num_current_render_targets = 0;
|
||||
std::memset(m_current_render_targets.data(), 0, sizeof(m_current_render_targets));
|
||||
m_current_depth_target = nullptr;
|
||||
@ -852,7 +857,9 @@ void D3D11Device::MapVertexBuffer(u32 vertex_size, u32 vertex_count, void** map_
|
||||
|
||||
void D3D11Device::UnmapVertexBuffer(u32 vertex_size, u32 vertex_count)
|
||||
{
|
||||
m_vertex_buffer.Unmap(m_context.Get(), vertex_size * vertex_count);
|
||||
const u32 upload_size = vertex_size * vertex_count;
|
||||
s_stats.buffer_streamed += upload_size;
|
||||
m_vertex_buffer.Unmap(m_context.Get(), upload_size);
|
||||
}
|
||||
|
||||
void D3D11Device::MapIndexBuffer(u32 index_count, DrawIndex** map_ptr, u32* map_space, u32* map_base_index)
|
||||
@ -865,6 +872,7 @@ void D3D11Device::MapIndexBuffer(u32 index_count, DrawIndex** map_ptr, u32* map_
|
||||
|
||||
void D3D11Device::UnmapIndexBuffer(u32 used_index_count)
|
||||
{
|
||||
s_stats.buffer_streamed += sizeof(DrawIndex) * used_index_count;
|
||||
m_index_buffer.Unmap(m_context.Get(), sizeof(DrawIndex) * used_index_count);
|
||||
}
|
||||
|
||||
@ -874,6 +882,7 @@ void D3D11Device::PushUniformBuffer(const void* data, u32 data_size)
|
||||
const auto res = m_uniform_buffer.Map(m_context.Get(), UNIFORM_BUFFER_ALIGNMENT, used_space);
|
||||
std::memcpy(res.pointer, data, data_size);
|
||||
m_uniform_buffer.Unmap(m_context.Get(), data_size);
|
||||
s_stats.buffer_streamed += data_size;
|
||||
|
||||
const UINT first_constant = (res.index_aligned * UNIFORM_BUFFER_ALIGNMENT) / 16u;
|
||||
const UINT num_constants = (used_space * UNIFORM_BUFFER_ALIGNMENT) / 16u;
|
||||
@ -895,6 +904,8 @@ void D3D11Device::UnmapUniformBuffer(u32 size)
|
||||
const UINT num_constants = used_space / 16u;
|
||||
|
||||
m_uniform_buffer.Unmap(m_context.Get(), used_space);
|
||||
s_stats.buffer_streamed += size;
|
||||
|
||||
m_context->VSSetConstantBuffers1(0, 1, m_uniform_buffer.GetD3DBufferArray(), &first_constant, &num_constants);
|
||||
m_context->PSSetConstantBuffers1(0, 1, m_uniform_buffer.GetD3DBufferArray(), &first_constant, &num_constants);
|
||||
}
|
||||
@ -944,6 +955,7 @@ void D3D11Device::SetRenderTargets(GPUTexture* const* rts, u32 num_rts, GPUTextu
|
||||
if (!changed)
|
||||
return;
|
||||
|
||||
s_stats.num_render_passes++;
|
||||
m_context->OMSetRenderTargets(num_rts, rtvs, ds ? static_cast<D3D11Texture*>(ds)->GetD3DDSV() : nullptr);
|
||||
}
|
||||
|
||||
@ -1035,10 +1047,12 @@ void D3D11Device::SetScissor(s32 x, s32 y, s32 width, s32 height)
|
||||
|
||||
void D3D11Device::Draw(u32 vertex_count, u32 base_vertex)
|
||||
{
|
||||
s_stats.num_draws++;
|
||||
m_context->Draw(vertex_count, base_vertex);
|
||||
}
|
||||
|
||||
void D3D11Device::DrawIndexed(u32 index_count, u32 base_index, u32 base_vertex)
|
||||
{
|
||||
s_stats.num_draws++;
|
||||
m_context->DrawIndexed(index_count, base_index, base_vertex);
|
||||
}
|
||||
|
||||
@ -45,6 +45,8 @@ bool D3D11Device::DownloadTexture(GPUTexture* texture, u32 x, u32 y, u32 width,
|
||||
return false;
|
||||
}
|
||||
|
||||
s_stats.num_downloads++;
|
||||
|
||||
const u32 copy_size = tex->GetPixelSize() * width;
|
||||
StringUtil::StrideMemCpy(out_data, out_data_stride, sr.pData, sr.RowPitch, copy_size, height);
|
||||
m_context->Unmap(m_readback_staging_texture.Get(), 0);
|
||||
@ -218,6 +220,10 @@ bool D3D11Texture::Update(u32 x, u32 y, u32 width, u32 height, const void* data,
|
||||
|
||||
ID3D11DeviceContext1* context = D3D11Device::GetD3DContext();
|
||||
CommitClear(context);
|
||||
|
||||
GPUDevice::GetStatistics().buffer_streamed += height * pitch;
|
||||
GPUDevice::GetStatistics().num_uploads++;
|
||||
|
||||
context->UpdateSubresource(m_texture.Get(), srnum, &box, data, pitch, 0);
|
||||
m_state = GPUTexture::State::Dirty;
|
||||
return true;
|
||||
@ -246,6 +252,9 @@ bool D3D11Texture::Map(void** map, u32* map_stride, u32 x, u32 y, u32 width, u32
|
||||
return false;
|
||||
}
|
||||
|
||||
GPUDevice::GetStatistics().buffer_streamed += height * sr.RowPitch;
|
||||
GPUDevice::GetStatistics().num_uploads++;
|
||||
|
||||
*map = static_cast<u8*>(sr.pData) + (y * sr.RowPitch) + (x * GetPixelSize());
|
||||
*map_stride = sr.RowPitch;
|
||||
m_mapped_subresource = srnum;
|
||||
@ -323,6 +332,12 @@ std::unique_ptr<D3D11Texture> D3D11Texture::Create(ID3D11Device* device, u32 wid
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (initial_data)
|
||||
{
|
||||
GPUDevice::GetStatistics().buffer_streamed += height * initial_data_stride;
|
||||
GPUDevice::GetStatistics().num_uploads++;
|
||||
}
|
||||
|
||||
ComPtr<ID3D11ShaderResourceView> srv;
|
||||
if (bind_flags & D3D11_BIND_SHADER_RESOURCE)
|
||||
{
|
||||
@ -412,7 +427,10 @@ void* D3D11TextureBuffer::Map(u32 required_elements)
|
||||
|
||||
void D3D11TextureBuffer::Unmap(u32 used_elements)
|
||||
{
|
||||
m_buffer.Unmap(D3D11Device::GetD3DContext(), used_elements * GetElementSize(m_format));
|
||||
const u32 size = used_elements * GetElementSize(m_format);
|
||||
GPUDevice::GetStatistics().buffer_streamed += size;
|
||||
GPUDevice::GetStatistics().num_uploads++;
|
||||
m_buffer.Unmap(D3D11Device::GetD3DContext(), size);
|
||||
}
|
||||
|
||||
void D3D11TextureBuffer::SetDebugName(const std::string_view& name)
|
||||
|
||||
@ -118,7 +118,8 @@ D3D12Device::ComPtr<ID3D12RootSignature> D3D12Device::CreateRootSignature(const
|
||||
}
|
||||
|
||||
bool D3D12Device::CreateDevice(const std::string_view& adapter, bool threaded_presentation,
|
||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features, Error* error)
|
||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features,
|
||||
Error* error)
|
||||
{
|
||||
std::unique_lock lock(s_instance_mutex);
|
||||
|
||||
@ -1256,6 +1257,8 @@ void D3D12Device::CopyTextureRegion(GPUTexture* dst, u32 dst_x, u32 dst_y, u32 d
|
||||
D->CommitClear();
|
||||
}
|
||||
|
||||
s_stats.num_copies++;
|
||||
|
||||
// *now* we can do a normal image copy.
|
||||
if (InRenderPass())
|
||||
EndRenderPass();
|
||||
@ -1297,6 +1300,8 @@ void D3D12Device::ResolveTextureRegion(GPUTexture* dst, u32 dst_x, u32 dst_y, u3
|
||||
if (InRenderPass())
|
||||
EndRenderPass();
|
||||
|
||||
s_stats.num_copies++;
|
||||
|
||||
D3D12Texture* D = static_cast<D3D12Texture*>(dst);
|
||||
D3D12Texture* S = static_cast<D3D12Texture*>(src);
|
||||
ID3D12GraphicsCommandList4* cmdlist = GetCommandList();
|
||||
@ -1401,7 +1406,9 @@ void D3D12Device::MapVertexBuffer(u32 vertex_size, u32 vertex_count, void** map_
|
||||
|
||||
void D3D12Device::UnmapVertexBuffer(u32 vertex_size, u32 vertex_count)
|
||||
{
|
||||
m_vertex_buffer.CommitMemory(vertex_size * vertex_count);
|
||||
const u32 upload_size = vertex_size * vertex_count;
|
||||
s_stats.buffer_streamed += upload_size;
|
||||
m_vertex_buffer.CommitMemory(upload_size);
|
||||
}
|
||||
|
||||
void D3D12Device::MapIndexBuffer(u32 index_count, DrawIndex** map_ptr, u32* map_space, u32* map_base_index)
|
||||
@ -1421,7 +1428,9 @@ void D3D12Device::MapIndexBuffer(u32 index_count, DrawIndex** map_ptr, u32* map_
|
||||
|
||||
void D3D12Device::UnmapIndexBuffer(u32 used_index_count)
|
||||
{
|
||||
m_index_buffer.CommitMemory(sizeof(DrawIndex) * used_index_count);
|
||||
const u32 upload_size = sizeof(DrawIndex) * used_index_count;
|
||||
s_stats.buffer_streamed += upload_size;
|
||||
m_index_buffer.CommitMemory(upload_size);
|
||||
}
|
||||
|
||||
void D3D12Device::PushUniformBuffer(const void* data, u32 data_size)
|
||||
@ -1441,6 +1450,7 @@ void D3D12Device::PushUniformBuffer(const void* data, u32 data_size)
|
||||
UpdateRootSignature();
|
||||
}
|
||||
|
||||
s_stats.buffer_streamed += data_size;
|
||||
GetCommandList()->SetGraphicsRoot32BitConstants(push_parameter[static_cast<u8>(m_current_pipeline_layout)],
|
||||
data_size / 4u, data, 0);
|
||||
}
|
||||
@ -1462,6 +1472,7 @@ void* D3D12Device::MapUniformBuffer(u32 size)
|
||||
|
||||
void D3D12Device::UnmapUniformBuffer(u32 size)
|
||||
{
|
||||
s_stats.buffer_streamed += size;
|
||||
m_uniform_buffer_position = m_uniform_buffer.GetCurrentOffset();
|
||||
m_uniform_buffer.CommitMemory(size);
|
||||
m_dirty_flags |= DIRTY_FLAG_CONSTANT_BUFFER;
|
||||
@ -1681,6 +1692,7 @@ void D3D12Device::BeginRenderPass()
|
||||
|
||||
// TODO: Stats
|
||||
m_in_render_pass = true;
|
||||
s_stats.num_render_passes++;
|
||||
|
||||
// If this is a new command buffer, bind the pipeline and such.
|
||||
if (m_dirty_flags & DIRTY_FLAG_INITIAL)
|
||||
@ -1715,6 +1727,7 @@ void D3D12Device::BeginSwapChainRenderPass()
|
||||
m_num_current_render_targets = 0;
|
||||
m_current_depth_target = nullptr;
|
||||
m_in_render_pass = true;
|
||||
s_stats.num_render_passes++;
|
||||
|
||||
// Clear pipeline, it's likely incompatible.
|
||||
m_current_pipeline = nullptr;
|
||||
@ -2119,11 +2132,13 @@ bool D3D12Device::UpdateRootParameters(u32 dirty)
|
||||
void D3D12Device::Draw(u32 vertex_count, u32 base_vertex)
|
||||
{
|
||||
PreDrawCheck();
|
||||
s_stats.num_draws++;
|
||||
GetCommandList()->DrawInstanced(vertex_count, 1, base_vertex, 0);
|
||||
}
|
||||
|
||||
void D3D12Device::DrawIndexed(u32 index_count, u32 base_index, u32 base_vertex)
|
||||
{
|
||||
PreDrawCheck();
|
||||
s_stats.num_draws++;
|
||||
GetCommandList()->DrawIndexedInstanced(index_count, 1, base_index, base_vertex, 0);
|
||||
}
|
||||
|
||||
@ -443,6 +443,9 @@ bool D3D12Texture::Update(u32 x, u32 y, u32 width, u32 height, const void* data,
|
||||
m_state = State::Dirty;
|
||||
}
|
||||
|
||||
GPUDevice::GetStatistics().buffer_streamed += required_size;
|
||||
GPUDevice::GetStatistics().num_uploads++;
|
||||
|
||||
// first time the texture is used? don't leave it undefined
|
||||
if (m_resource_state == D3D12_RESOURCE_STATE_COMMON)
|
||||
TransitionToState(cmdlist, D3D12_RESOURCE_STATE_COPY_DEST);
|
||||
@ -511,6 +514,9 @@ void D3D12Texture::Unmap()
|
||||
const u32 offset = sb.GetCurrentOffset();
|
||||
sb.CommitMemory(req_size);
|
||||
|
||||
GPUDevice::GetStatistics().buffer_streamed += req_size;
|
||||
GPUDevice::GetStatistics().num_uploads++;
|
||||
|
||||
ID3D12GraphicsCommandList4* cmdlist = GetCommandBufferForUpdate();
|
||||
|
||||
// first time the texture is used? don't leave it undefined
|
||||
@ -907,7 +913,10 @@ void* D3D12TextureBuffer::Map(u32 required_elements)
|
||||
|
||||
void D3D12TextureBuffer::Unmap(u32 used_elements)
|
||||
{
|
||||
m_buffer.CommitMemory(GetElementSize(m_format) * used_elements);
|
||||
const u32 size = GetElementSize(m_format) * used_elements;
|
||||
GPUDevice::GetStatistics().buffer_streamed += size;
|
||||
GPUDevice::GetStatistics().num_uploads++;
|
||||
m_buffer.CommitMemory(size);
|
||||
}
|
||||
|
||||
void D3D12TextureBuffer::SetDebugName(const std::string_view& name)
|
||||
|
||||
@ -40,6 +40,7 @@ std::unique_ptr<GPUDevice> g_gpu_device;
|
||||
|
||||
static std::string s_pipeline_cache_path;
|
||||
size_t GPUDevice::s_total_vram_usage = 0;
|
||||
GPUDevice::Statistics GPUDevice::s_stats = {};
|
||||
|
||||
GPUSampler::GPUSampler() = default;
|
||||
|
||||
@ -206,6 +207,11 @@ size_t GPUFramebufferManagerBase::KeyHash::operator()(const Key& key) const
|
||||
return XXH32(&key, sizeof(key), 0x1337);
|
||||
}
|
||||
|
||||
GPUDevice::GPUDevice()
|
||||
{
|
||||
ResetStatistics();
|
||||
}
|
||||
|
||||
GPUDevice::~GPUDevice() = default;
|
||||
|
||||
RenderAPI GPUDevice::GetPreferredAPI()
|
||||
@ -993,6 +999,11 @@ float GPUDevice::GetAndResetAccumulatedGPUTime()
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
void GPUDevice::ResetStatistics()
|
||||
{
|
||||
s_stats = {};
|
||||
}
|
||||
|
||||
std::unique_ptr<GPUDevice> GPUDevice::CreateDeviceForAPI(RenderAPI api)
|
||||
{
|
||||
switch (api)
|
||||
|
||||
@ -458,6 +458,16 @@ public:
|
||||
bool prefer_unused_textures : 1;
|
||||
};
|
||||
|
||||
struct Statistics
|
||||
{
|
||||
size_t buffer_streamed;
|
||||
u32 num_draws;
|
||||
u32 num_render_passes;
|
||||
u32 num_copies;
|
||||
u32 num_downloads;
|
||||
u32 num_uploads;
|
||||
};
|
||||
|
||||
struct AdapterAndModeList
|
||||
{
|
||||
std::vector<std::string> adapter_names;
|
||||
@ -474,6 +484,7 @@ public:
|
||||
static constexpr u32 MAX_RENDER_TARGETS = 4;
|
||||
static_assert(sizeof(GPUPipeline::GraphicsConfig::color_formats) == sizeof(GPUTexture::Format) * MAX_RENDER_TARGETS);
|
||||
|
||||
GPUDevice();
|
||||
virtual ~GPUDevice();
|
||||
|
||||
/// Returns the default/preferred API for the system.
|
||||
@ -652,6 +663,9 @@ public:
|
||||
/// Returns the amount of GPU time utilized since the last time this method was called.
|
||||
virtual float GetAndResetAccumulatedGPUTime();
|
||||
|
||||
ALWAYS_INLINE static Statistics& GetStatistics() { return s_stats; }
|
||||
static void ResetStatistics();
|
||||
|
||||
protected:
|
||||
virtual bool CreateDevice(const std::string_view& adapter, bool threaded_presentation,
|
||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features,
|
||||
@ -738,6 +752,8 @@ private:
|
||||
float m_display_frame_interval = 0.0f;
|
||||
|
||||
protected:
|
||||
static Statistics s_stats;
|
||||
|
||||
bool m_gpu_timing_enabled = false;
|
||||
bool m_vsync_enabled = false;
|
||||
bool m_debug_device = false;
|
||||
|
||||
@ -890,6 +890,9 @@ bool MetalTexture::Update(u32 x, u32 y, u32 width, u32 height, const void* data,
|
||||
const u32 aligned_pitch = Common::AlignUpPow2(width * GetPixelSize(), TEXTURE_UPLOAD_PITCH_ALIGNMENT);
|
||||
const u32 req_size = height * aligned_pitch;
|
||||
|
||||
GPUDevice::GetStatistics().buffer_streamed += req_size;
|
||||
GPUDevice::GetStatistics().num_uploads++;
|
||||
|
||||
MetalDevice& dev = MetalDevice::GetInstance();
|
||||
MetalStreamBuffer& sb = dev.GetTextureStreamBuffer();
|
||||
id<MTLBuffer> actual_buffer;
|
||||
@ -989,6 +992,9 @@ void MetalTexture::Unmap()
|
||||
const u32 aligned_pitch = Common::AlignUpPow2(m_map_width * GetPixelSize(), TEXTURE_UPLOAD_PITCH_ALIGNMENT);
|
||||
const u32 req_size = m_map_height * aligned_pitch;
|
||||
|
||||
GPUDevice::GetStatistics().buffer_streamed += req_size;
|
||||
GPUDevice::GetStatistics().num_uploads++;
|
||||
|
||||
MetalDevice& dev = MetalDevice::GetInstance();
|
||||
MetalStreamBuffer& sb = dev.GetTextureStreamBuffer();
|
||||
const u32 offset = sb.GetCurrentOffset();
|
||||
@ -1206,6 +1212,8 @@ bool MetalDevice::DownloadTexture(GPUTexture* texture, u32 x, u32 y, u32 width,
|
||||
MetalTexture* T = static_cast<MetalTexture*>(texture);
|
||||
CommitClear(T);
|
||||
|
||||
s_stats.num_downloads++;
|
||||
|
||||
@autoreleasepool
|
||||
{
|
||||
id<MTLBlitCommandEncoder> encoder = GetBlitEncoder(true);
|
||||
@ -1303,6 +1311,8 @@ void MetalDevice::CopyTextureRegion(GPUTexture* dst, u32 dst_x, u32 dst_y, u32 d
|
||||
S->SetUseFenceCounter(m_current_fence_counter);
|
||||
D->SetUseFenceCounter(m_current_fence_counter);
|
||||
|
||||
s_stats.num_copies++;
|
||||
|
||||
@autoreleasepool
|
||||
{
|
||||
id<MTLBlitCommandEncoder> encoder = GetBlitEncoder(true);
|
||||
@ -1365,6 +1375,8 @@ void MetalDevice::ResolveTextureRegion(GPUTexture* dst, u32 dst_x, u32 dst_y, u3
|
||||
if (InRenderPass())
|
||||
EndRenderPass();
|
||||
|
||||
s_stats.num_copies++;
|
||||
|
||||
const u32 threadgroupHeight = resolve_pipeline.maxTotalThreadsPerThreadgroup / resolve_pipeline.threadExecutionWidth;
|
||||
const MTLSize intrinsicThreadgroupSize = MTLSizeMake(resolve_pipeline.threadExecutionWidth, threadgroupHeight, 1);
|
||||
const MTLSize threadgroupsInGrid =
|
||||
@ -1472,7 +1484,10 @@ void* MetalTextureBuffer::Map(u32 required_elements)
|
||||
|
||||
void MetalTextureBuffer::Unmap(u32 used_elements)
|
||||
{
|
||||
m_buffer.CommitMemory(GetElementSize(m_format) * used_elements);
|
||||
const u32 size = GetElementSize(m_format) * used_elements;
|
||||
GPUDevice::GetStatistics().buffer_streamed += size;
|
||||
GPUDevice::GetStatistics().num_uploads++;
|
||||
m_buffer.CommitMemory(size);
|
||||
}
|
||||
|
||||
void MetalTextureBuffer::SetDebugName(const std::string_view& name)
|
||||
@ -1523,7 +1538,9 @@ void MetalDevice::MapVertexBuffer(u32 vertex_size, u32 vertex_count, void** map_
|
||||
|
||||
void MetalDevice::UnmapVertexBuffer(u32 vertex_size, u32 vertex_count)
|
||||
{
|
||||
m_vertex_buffer.CommitMemory(vertex_size * vertex_count);
|
||||
const u32 size = vertex_size * vertex_count;
|
||||
s_stats.buffer_streamed += size;
|
||||
m_vertex_buffer.CommitMemory(size);
|
||||
}
|
||||
|
||||
void MetalDevice::MapIndexBuffer(u32 index_count, DrawIndex** map_ptr, u32* map_space, u32* map_base_index)
|
||||
@ -1543,11 +1560,14 @@ void MetalDevice::MapIndexBuffer(u32 index_count, DrawIndex** map_ptr, u32* map_
|
||||
|
||||
void MetalDevice::UnmapIndexBuffer(u32 used_index_count)
|
||||
{
|
||||
m_index_buffer.CommitMemory(sizeof(DrawIndex) * used_index_count);
|
||||
const u32 size = sizeof(DrawIndex) * used_index_count;
|
||||
s_stats.buffer_streamed += size;
|
||||
m_index_buffer.CommitMemory(size);
|
||||
}
|
||||
|
||||
void MetalDevice::PushUniformBuffer(const void* data, u32 data_size)
|
||||
{
|
||||
s_stats.buffer_streamed += data_size;
|
||||
void* map = MapUniformBuffer(data_size);
|
||||
std::memcpy(map, data, data_size);
|
||||
UnmapUniformBuffer(data_size);
|
||||
@ -1568,6 +1588,7 @@ void* MetalDevice::MapUniformBuffer(u32 size)
|
||||
|
||||
void MetalDevice::UnmapUniformBuffer(u32 size)
|
||||
{
|
||||
s_stats.buffer_streamed += size;
|
||||
m_current_uniform_buffer_position = m_uniform_buffer.GetCurrentOffset();
|
||||
m_uniform_buffer.CommitMemory(size);
|
||||
if (InRenderPass())
|
||||
@ -1758,6 +1779,8 @@ void MetalDevice::BeginRenderPass()
|
||||
m_inline_upload_encoder = nil;
|
||||
}
|
||||
|
||||
s_stats.num_render_passes++;
|
||||
|
||||
@autoreleasepool
|
||||
{
|
||||
MTLRenderPassDescriptor* desc = [MTLRenderPassDescriptor renderPassDescriptor];
|
||||
@ -1927,6 +1950,7 @@ void MetalDevice::PreDrawCheck()
|
||||
void MetalDevice::Draw(u32 vertex_count, u32 base_vertex)
|
||||
{
|
||||
PreDrawCheck();
|
||||
s_stats.num_draws++;
|
||||
[m_render_encoder drawPrimitives:m_current_pipeline->GetPrimitive() vertexStart:base_vertex vertexCount:vertex_count];
|
||||
}
|
||||
|
||||
@ -1934,6 +1958,8 @@ void MetalDevice::DrawIndexed(u32 index_count, u32 base_index, u32 base_vertex)
|
||||
{
|
||||
PreDrawCheck();
|
||||
|
||||
s_stats.num_draws++;
|
||||
|
||||
const u32 index_offset = base_index * sizeof(u16);
|
||||
[m_render_encoder drawIndexedPrimitives:m_current_pipeline->GetPrimitive()
|
||||
indexCount:index_count
|
||||
@ -2000,6 +2026,7 @@ bool MetalDevice::BeginPresent(bool skip_present)
|
||||
m_layer_pass_desc.colorAttachments[0].texture = layer_texture;
|
||||
m_layer_pass_desc.colorAttachments[0].loadAction = MTLLoadActionClear;
|
||||
m_render_encoder = [[m_render_cmdbuf renderCommandEncoderWithDescriptor:m_layer_pass_desc] retain];
|
||||
s_stats.num_render_passes++;
|
||||
std::memset(m_current_render_targets.data(), 0, sizeof(m_current_render_targets));
|
||||
m_num_current_render_targets = 0;
|
||||
m_current_depth_target = nullptr;
|
||||
|
||||
@ -76,6 +76,8 @@ bool OpenGLDevice::DownloadTexture(GPUTexture* texture, u32 x, u32 y, u32 width,
|
||||
const u32 layer = 0;
|
||||
const u32 level = 0;
|
||||
|
||||
s_stats.num_downloads++;
|
||||
|
||||
if (GLAD_GL_VERSION_4_5 || GLAD_GL_ARB_get_texture_sub_image)
|
||||
{
|
||||
glGetTextureSubImage(T->GetGLId(), level, x, y, layer, width, height, 1, gl_format, gl_type,
|
||||
@ -116,6 +118,8 @@ void OpenGLDevice::CopyTextureRegion(GPUTexture* dst, u32 dst_x, u32 dst_y, u32
|
||||
CommitClear(D);
|
||||
CommitClear(S);
|
||||
|
||||
s_stats.num_copies++;
|
||||
|
||||
const GLuint sid = S->GetGLId();
|
||||
const GLuint did = D->GetGLId();
|
||||
if (GLAD_GL_VERSION_4_3 || GLAD_GL_ARB_copy_image)
|
||||
@ -192,6 +196,8 @@ void OpenGLDevice::ResolveTextureRegion(GPUTexture* dst, u32 dst_x, u32 dst_y, u
|
||||
CommitClear(D);
|
||||
}
|
||||
|
||||
s_stats.num_copies++;
|
||||
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glBlitFramebuffer(src_x, src_y, src_x + width, src_y + height, dst_x, dst_y, dst_x + width, dst_y + height,
|
||||
GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
||||
@ -307,7 +313,8 @@ bool OpenGLDevice::HasSurface() const
|
||||
}
|
||||
|
||||
bool OpenGLDevice::CreateDevice(const std::string_view& adapter, bool threaded_presentation,
|
||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features, Error* error)
|
||||
std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features,
|
||||
Error* error)
|
||||
{
|
||||
m_gl_context = GL::Context::Create(m_window_info, error);
|
||||
if (!m_gl_context)
|
||||
@ -1030,6 +1037,8 @@ ALWAYS_INLINE_RELEASE void OpenGLDevice::SetVertexBufferOffsets(u32 base_vertex)
|
||||
|
||||
void OpenGLDevice::Draw(u32 vertex_count, u32 base_vertex)
|
||||
{
|
||||
s_stats.num_draws++;
|
||||
|
||||
if (glDrawElementsBaseVertex) [[likely]]
|
||||
{
|
||||
glDrawArrays(m_current_pipeline->GetTopology(), base_vertex, vertex_count);
|
||||
@ -1042,6 +1051,8 @@ void OpenGLDevice::Draw(u32 vertex_count, u32 base_vertex)
|
||||
|
||||
void OpenGLDevice::DrawIndexed(u32 index_count, u32 base_index, u32 base_vertex)
|
||||
{
|
||||
s_stats.num_draws++;
|
||||
|
||||
if (glDrawElementsBaseVertex) [[likely]]
|
||||
{
|
||||
const void* indices = reinterpret_cast<const void*>(static_cast<uintptr_t>(base_index) * sizeof(u16));
|
||||
@ -1066,7 +1077,9 @@ void OpenGLDevice::MapVertexBuffer(u32 vertex_size, u32 vertex_count, void** map
|
||||
|
||||
void OpenGLDevice::UnmapVertexBuffer(u32 vertex_size, u32 vertex_count)
|
||||
{
|
||||
m_vertex_buffer->Unmap(vertex_size * vertex_count);
|
||||
const u32 size = vertex_size * vertex_count;
|
||||
s_stats.buffer_streamed += size;
|
||||
m_vertex_buffer->Unmap(size);
|
||||
}
|
||||
|
||||
void OpenGLDevice::MapIndexBuffer(u32 index_count, DrawIndex** map_ptr, u32* map_space, u32* map_base_index)
|
||||
@ -1079,7 +1092,9 @@ void OpenGLDevice::MapIndexBuffer(u32 index_count, DrawIndex** map_ptr, u32* map
|
||||
|
||||
void OpenGLDevice::UnmapIndexBuffer(u32 used_index_count)
|
||||
{
|
||||
m_index_buffer->Unmap(sizeof(DrawIndex) * used_index_count);
|
||||
const u32 size = sizeof(DrawIndex) * used_index_count;
|
||||
s_stats.buffer_streamed += size;
|
||||
m_index_buffer->Unmap(size);
|
||||
}
|
||||
|
||||
void OpenGLDevice::PushUniformBuffer(const void* data, u32 data_size)
|
||||
@ -1087,6 +1102,7 @@ void OpenGLDevice::PushUniformBuffer(const void* data, u32 data_size)
|
||||
const auto res = m_uniform_buffer->Map(m_uniform_buffer_alignment, data_size);
|
||||
std::memcpy(res.pointer, data, data_size);
|
||||
m_uniform_buffer->Unmap(data_size);
|
||||
s_stats.buffer_streamed += data_size;
|
||||
glBindBufferRange(GL_UNIFORM_BUFFER, 1, m_uniform_buffer->GetGLBufferId(), res.buffer_offset, data_size);
|
||||
}
|
||||
|
||||
@ -1099,6 +1115,7 @@ void* OpenGLDevice::MapUniformBuffer(u32 size)
|
||||
void OpenGLDevice::UnmapUniformBuffer(u32 size)
|
||||
{
|
||||
const u32 pos = m_uniform_buffer->Unmap(size);
|
||||
s_stats.buffer_streamed += pos;
|
||||
glBindBufferRange(GL_UNIFORM_BUFFER, 1, m_uniform_buffer->GetGLBufferId(), pos, size);
|
||||
}
|
||||
|
||||
@ -1135,6 +1152,7 @@ void OpenGLDevice::SetRenderTargets(GPUTexture* const* rts, u32 num_rts, GPUText
|
||||
}
|
||||
}
|
||||
|
||||
s_stats.num_render_passes++;
|
||||
m_current_fbo = fbo;
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
|
||||
}
|
||||
|
||||
@ -166,6 +166,9 @@ std::unique_ptr<OpenGLTexture> OpenGLTexture::Create(u32 width, u32 height, u32
|
||||
const u32 alignment = ((data_pitch % 4) == 0) ? 4 : (((data_pitch % 2) == 0) ? 2 : 1);
|
||||
if (data)
|
||||
{
|
||||
GPUDevice::GetStatistics().buffer_streamed += data_pitch * height;
|
||||
GPUDevice::GetStatistics().num_uploads++;
|
||||
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, data_pitch / pixel_size);
|
||||
if (alignment != 4)
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);
|
||||
@ -248,6 +251,9 @@ bool OpenGLTexture::Update(u32 x, u32 y, u32 width, u32 height, const void* data
|
||||
|
||||
CommitClear();
|
||||
|
||||
GPUDevice::GetStatistics().buffer_streamed += map_size;
|
||||
GPUDevice::GetStatistics().num_uploads++;
|
||||
|
||||
OpenGLDevice::BindUpdateTextureUnit();
|
||||
glBindTexture(target, m_id);
|
||||
|
||||
@ -309,6 +315,10 @@ void OpenGLTexture::Unmap()
|
||||
|
||||
const u32 pitch = Common::AlignUpPow2(static_cast<u32>(m_map_width) * GetPixelSize(), TEXTURE_UPLOAD_PITCH_ALIGNMENT);
|
||||
const u32 upload_size = pitch * static_cast<u32>(m_map_height);
|
||||
|
||||
GPUDevice::GetStatistics().buffer_streamed += upload_size;
|
||||
GPUDevice::GetStatistics().num_uploads++;
|
||||
|
||||
OpenGLStreamBuffer* sb = OpenGLDevice::GetTextureStreamBuffer();
|
||||
sb->Unmap(upload_size);
|
||||
sb->Bind();
|
||||
@ -627,7 +637,10 @@ void* OpenGLTextureBuffer::Map(u32 required_elements)
|
||||
|
||||
void OpenGLTextureBuffer::Unmap(u32 used_elements)
|
||||
{
|
||||
m_buffer->Unmap(used_elements * GetElementSize(m_format));
|
||||
const u32 size = used_elements * GetElementSize(m_format);
|
||||
GPUDevice::GetStatistics().buffer_streamed += size;
|
||||
GPUDevice::GetStatistics().num_uploads++;
|
||||
m_buffer->Unmap(size);
|
||||
}
|
||||
|
||||
void OpenGLTextureBuffer::SetDebugName(const std::string_view& name)
|
||||
|
||||
@ -2568,6 +2568,8 @@ void VulkanDevice::CopyTextureRegion(GPUTexture* dst, u32 dst_x, u32 dst_y, u32
|
||||
if (InRenderPass())
|
||||
EndRenderPass();
|
||||
|
||||
s_stats.num_copies++;
|
||||
|
||||
S->SetUseFenceCounter(GetCurrentFenceCounter());
|
||||
D->SetUseFenceCounter(GetCurrentFenceCounter());
|
||||
S->TransitionToLayout((D == S) ? VulkanTexture::Layout::TransferSelf : VulkanTexture::Layout::TransferSrc);
|
||||
@ -2592,6 +2594,8 @@ void VulkanDevice::ResolveTextureRegion(GPUTexture* dst, u32 dst_x, u32 dst_y, u
|
||||
if (InRenderPass())
|
||||
EndRenderPass();
|
||||
|
||||
s_stats.num_copies++;
|
||||
|
||||
VulkanTexture* D = static_cast<VulkanTexture*>(dst);
|
||||
VulkanTexture* S = static_cast<VulkanTexture*>(src);
|
||||
const VkCommandBuffer cmdbuf = GetCurrentCommandBuffer();
|
||||
@ -2699,7 +2703,9 @@ void VulkanDevice::MapVertexBuffer(u32 vertex_size, u32 vertex_count, void** map
|
||||
|
||||
void VulkanDevice::UnmapVertexBuffer(u32 vertex_size, u32 vertex_count)
|
||||
{
|
||||
m_vertex_buffer.CommitMemory(vertex_size * vertex_count);
|
||||
const u32 size = vertex_size * vertex_count;
|
||||
s_stats.buffer_streamed += size;
|
||||
m_vertex_buffer.CommitMemory(size);
|
||||
}
|
||||
|
||||
void VulkanDevice::MapIndexBuffer(u32 index_count, DrawIndex** map_ptr, u32* map_space, u32* map_base_index)
|
||||
@ -2719,12 +2725,15 @@ void VulkanDevice::MapIndexBuffer(u32 index_count, DrawIndex** map_ptr, u32* map
|
||||
|
||||
void VulkanDevice::UnmapIndexBuffer(u32 used_index_count)
|
||||
{
|
||||
m_index_buffer.CommitMemory(sizeof(DrawIndex) * used_index_count);
|
||||
const u32 size = sizeof(DrawIndex) * used_index_count;
|
||||
s_stats.buffer_streamed += size;
|
||||
m_index_buffer.CommitMemory(size);
|
||||
}
|
||||
|
||||
void VulkanDevice::PushUniformBuffer(const void* data, u32 data_size)
|
||||
{
|
||||
DebugAssert(data_size < UNIFORM_PUSH_CONSTANTS_SIZE);
|
||||
s_stats.buffer_streamed += data_size;
|
||||
vkCmdPushConstants(GetCurrentCommandBuffer(), GetCurrentVkPipelineLayout(), UNIFORM_PUSH_CONSTANTS_STAGES, 0,
|
||||
data_size, data);
|
||||
}
|
||||
@ -2745,6 +2754,7 @@ void* VulkanDevice::MapUniformBuffer(u32 size)
|
||||
|
||||
void VulkanDevice::UnmapUniformBuffer(u32 size)
|
||||
{
|
||||
s_stats.buffer_streamed += size;
|
||||
m_uniform_buffer_position = m_uniform_buffer.GetCurrentOffset();
|
||||
m_uniform_buffer.CommitMemory(size);
|
||||
m_dirty_flags |= DIRTY_FLAG_DYNAMIC_OFFSETS;
|
||||
@ -3147,6 +3157,8 @@ void VulkanDevice::BeginRenderPass()
|
||||
vkCmdBeginRenderPass(GetCurrentCommandBuffer(), &bi, VK_SUBPASS_CONTENTS_INLINE);
|
||||
}
|
||||
|
||||
s_stats.num_render_passes++;
|
||||
|
||||
// If this is a new command buffer, bind the pipeline and such.
|
||||
if (m_dirty_flags & DIRTY_FLAG_INITIAL)
|
||||
SetInitialPipelineState();
|
||||
@ -3212,6 +3224,7 @@ void VulkanDevice::BeginSwapChainRenderPass()
|
||||
vkCmdBeginRenderPass(GetCurrentCommandBuffer(), &rp, VK_SUBPASS_CONTENTS_INLINE);
|
||||
}
|
||||
|
||||
s_stats.num_render_passes++;
|
||||
m_num_current_render_targets = 0;
|
||||
std::memset(m_current_render_targets.data(), 0, sizeof(m_current_render_targets));
|
||||
m_current_depth_target = nullptr;
|
||||
@ -3568,11 +3581,13 @@ bool VulkanDevice::UpdateDescriptorSets(u32 dirty)
|
||||
void VulkanDevice::Draw(u32 vertex_count, u32 base_vertex)
|
||||
{
|
||||
PreDrawCheck();
|
||||
s_stats.num_draws++;
|
||||
vkCmdDraw(GetCurrentCommandBuffer(), vertex_count, 1, base_vertex, 0);
|
||||
}
|
||||
|
||||
void VulkanDevice::DrawIndexed(u32 index_count, u32 base_index, u32 base_vertex)
|
||||
{
|
||||
PreDrawCheck();
|
||||
s_stats.num_draws++;
|
||||
vkCmdDrawIndexed(GetCurrentCommandBuffer(), index_count, 1, base_index, base_vertex, 0);
|
||||
}
|
||||
|
||||
@ -339,6 +339,9 @@ bool VulkanTexture::Update(u32 x, u32 y, u32 width, u32 height, const void* data
|
||||
sbuffer.CommitMemory(required_size);
|
||||
}
|
||||
|
||||
GPUDevice::GetStatistics().buffer_streamed += required_size;
|
||||
GPUDevice::GetStatistics().num_uploads++;
|
||||
|
||||
const VkCommandBuffer cmdbuf = GetCommandBufferForUpdate();
|
||||
|
||||
// if we're an rt and have been cleared, and the full rect isn't being uploaded, do the clear
|
||||
@ -407,6 +410,9 @@ void VulkanTexture::Unmap()
|
||||
const u32 offset = sb.GetCurrentOffset();
|
||||
sb.CommitMemory(req_size);
|
||||
|
||||
GPUDevice::GetStatistics().buffer_streamed += req_size;
|
||||
GPUDevice::GetStatistics().num_uploads++;
|
||||
|
||||
// first time the texture is used? don't leave it undefined
|
||||
const VkCommandBuffer cmdbuf = GetCommandBufferForUpdate();
|
||||
if (m_layout == Layout::Undefined)
|
||||
@ -745,6 +751,8 @@ bool VulkanDevice::DownloadTexture(GPUTexture* texture, u32 x, u32 y, u32 width,
|
||||
return false;
|
||||
}
|
||||
|
||||
s_stats.num_downloads++;
|
||||
|
||||
if (InRenderPass())
|
||||
EndRenderPass();
|
||||
|
||||
@ -1015,7 +1023,10 @@ void* VulkanTextureBuffer::Map(u32 required_elements)
|
||||
|
||||
void VulkanTextureBuffer::Unmap(u32 used_elements)
|
||||
{
|
||||
m_buffer.CommitMemory(GetElementSize(m_format) * used_elements);
|
||||
const u32 size = GetElementSize(m_format) * used_elements;
|
||||
GPUDevice::GetStatistics().buffer_streamed += size;
|
||||
GPUDevice::GetStatistics().num_uploads++;
|
||||
m_buffer.CommitMemory(size);
|
||||
}
|
||||
|
||||
void VulkanTextureBuffer::SetDebugName(const std::string_view& name)
|
||||
|
||||
Reference in New Issue
Block a user