Debug visualization for the Vulkan memory allocator. Shows some interesting behaviour.

This commit is contained in:
Henrik Rydgård committed 2018-01-29 19:38:10 +01:00
1 parent 2ae2dd7d40
commit c60c8ed68a
18 files changed
+168 -15

No files matched your search

+2
View File
@@ -1188,6 +1188,8 @@ set(GPU_GLES
set(GPU_VULKAN
GPU/Vulkan/DepalettizeShaderVulkan.cpp
GPU/Vulkan/DepalettizeShaderVulkan.h
GPU/Vulkan/DebugVisVulkan.cpp
GPU/Vulkan/DebugVisVulkan.h
GPU/Vulkan/DrawEngineVulkan.cpp
GPU/Vulkan/DrawEngineVulkan.h
GPU/Vulkan/FragmentShaderGeneratorVulkan.cpp
+7
View File
@@ -293,6 +293,13 @@ int VulkanDeviceAllocator::ComputeUsagePercent() const {
return blockSum == 0 ? 0 : 100 * blocksUsed / blockSum;
}
std::vector<uint8_t> VulkanDeviceAllocator::GetSlabUsage(int slabIndex) const {
if (slabIndex < 0 || slabIndex >= (int)slabs_.size())
return std::vector<uint8_t>();
const Slab &slab = slabs_[slabIndex];
return slab.usage;
}
void VulkanDeviceAllocator::Free(VkDeviceMemory deviceMemory, size_t offset) {
assert(!destroyed_);
+2 -1
View File
@@ -146,11 +146,12 @@ public:
static const size_t ALLOCATE_FAILED = -1;
int GetBlockCount() const { return (int)slabs_.size(); }
int GetSlabCount() const { return (int)slabs_.size(); }
int GetMinSlabSize() const { return (int)minSlabSize_; }
int GetMaxSlabSize() const { return (int)maxSlabSize_; }
int ComputeUsagePercent() const;
std::vector<uint8_t> GetSlabUsage(int slab) const;
private:
static const size_t SLAB_GRAIN_SIZE = 1024;
+1
View File
@@ -789,6 +789,7 @@ static ConfigSetting debuggerSettings[] = {
ConfigSetting("DisplayStatusBar", &g_Config.bDisplayStatusBar, true),
ConfigSetting("ShowBottomTabTitles",&g_Config.bShowBottomTabTitles,true),
ConfigSetting("ShowDeveloperMenu", &g_Config.bShowDeveloperMenu, false),
ConfigSetting("ShowAllocatorDebug", &g_Config.bShowAllocatorDebug, false, false),
ConfigSetting("SkipDeadbeefFilling", &g_Config.bSkipDeadbeefFilling, false),
ConfigSetting("FuncHashMap", &g_Config.bFuncHashMap, false),
+1
View File
@@ -447,6 +447,7 @@ public:
bool bDisplayStatusBar;
bool bShowBottomTabTitles;
bool bShowDeveloperMenu;
bool bShowAllocatorDebug;
// Double edged sword: much easier debugging, but not accurate.
bool bSkipDeadbeefFilling;
bool bFuncHashMap;
+3 -1
View File
@@ -256,6 +256,7 @@
<ClInclude Include="Software\SoftGpu.h" />
<ClInclude Include="Software\TransformUnit.h" />
<ClInclude Include="Common\TextureDecoder.h" />
<ClInclude Include="Vulkan\DebugVisVulkan.h" />
<ClInclude Include="Vulkan\DepalettizeShaderVulkan.h" />
<ClInclude Include="Vulkan\DrawEngineVulkan.h" />
<ClInclude Include="Vulkan\FragmentShaderGeneratorVulkan.h" />
@@ -360,6 +361,7 @@
<ClCompile Include="Software\SoftGpu.cpp" />
<ClCompile Include="Software\TransformUnit.cpp" />
<ClCompile Include="Common\TextureDecoder.cpp" />
<ClCompile Include="Vulkan\DebugVisVulkan.cpp" />
<ClCompile Include="Vulkan\DepalettizeShaderVulkan.cpp" />
<ClCompile Include="Vulkan\DrawEngineVulkan.cpp" />
<ClCompile Include="Vulkan\FragmentShaderGeneratorVulkan.cpp" />
@@ -385,4 +387,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>
+3 -1
View File
@@ -270,6 +270,7 @@
<ClInclude Include="D3D11\StateMappingD3D11.h">
<Filter>D3D11</Filter>
</ClInclude>
<ClInclude Include="Vulkan\DebugVisVulkan.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="Math3D.cpp">
@@ -536,5 +537,6 @@
<ClCompile Include="Common\StencilCommon.cpp">
<Filter>Common</Filter>
</ClCompile>
<ClCompile Include="Vulkan\DebugVisVulkan.cpp" />
</ItemGroup>
</Project>
</Project>
+93
View File
@@ -0,0 +1,93 @@
// Copyright (c) 2016- PPSSPP Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0 or later versions.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include "DebugVisVulkan.h"
#include "Common/Vulkan/VulkanMemory.h"
#include "Common/Vulkan/VulkanImage.h"
#include "GPU/Vulkan/GPU_Vulkan.h"
#include "GPU/Vulkan/VulkanUtil.h"
#include "gfx_es2/draw_buffer.h"
#include "thin3d/thin3d.h"
#include "ui/ui_context.h"
#include "ui/view.h"
void DrawAllocatorVis(UIContext *ui, GPUInterface *gpu) {
if (!gpu) {
return;
}
using namespace Draw;
const int padding = 10;
const int columnWidth = 256;
const int starty = padding * 8;
int x = padding;
int y = starty;
int w = columnWidth; // We will double this when actually drawing to make the pixels visible.
ui->End();
ui->Begin();
GPU_Vulkan *gpuVulkan = static_cast<GPU_Vulkan *>(gpu);
VulkanDeviceAllocator *alloc = gpuVulkan->GetTextureCache()->GetAllocator();
std::vector<Draw::Texture *> texturesToDelete;
for (int i = 0; i < alloc->GetSlabCount(); i++) {
std::vector<uint8_t> usage = alloc->GetSlabUsage(i);
int h = ((int)usage.size() + w - 1) / w;
if (y + h + padding > ui->GetBounds().h) {
y = starty;
x += columnWidth + padding;
}
std::vector<uint8_t> initData(w * h * 4);
uint32_t *wideData = (uint32_t *)initData.data();
// Convert to nice colors. If we really wanted to save on memory, we could use a 16-bit texture...
for (int j = 0; j < usage.size(); j++) {
switch (usage[j]) {
case 0: wideData[j] = 0xFF333333; break;
case 1: wideData[j] = 0xFF33FF33; break;
case 2: wideData[j] = 0xFF3333FF; break;
default: wideData[j] = 0xFFFF00FF; break; // Magenta - if you see this, need to add more cases.
}
}
Draw::TextureDesc desc{};
desc.width = w;
desc.height = h;
desc.depth = 1;
desc.format = Draw::DataFormat::R8G8B8A8_UNORM;
desc.mipLevels = 1;
desc.type = Draw::TextureType::LINEAR2D;
desc.initData.push_back(initData.data());
Draw::DrawContext *draw = ui->GetDrawContext();
Draw::Texture *tex = draw->CreateTexture(desc);
UI::Drawable white(0xFFFFFFFF);
draw->BindTexture(0, tex);
ui->Draw()->Rect(x, y, w, h, 0xFFFFFFFF);
ui->Flush();
texturesToDelete.push_back(tex);
y += h + padding;
}
ui->Flush();
for (auto iter : texturesToDelete)
iter->Release();
}
+26
View File
@@ -0,0 +1,26 @@
// Copyright (c) 2016- PPSSPP Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0 or later versions.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#pragma once
#include "thin3d/thin3d.h"
class GPUInterface;
class UIContext;
// gpu MUST be an instance of GPU_Vulkan. If not, will definitely crash.
void DrawAllocatorVis(UIContext *ui, GPUInterface *gpu);
+4
View File
@@ -78,6 +78,10 @@ public:
std::vector<std::string> DebugGetShaderIDs(DebugShaderType shader) override;
std::string DebugGetShaderString(std::string id, DebugShaderType shader, DebugShaderStringType stringType) override;
TextureCacheVulkan *GetTextureCache() {
return textureCacheVulkan_;
}
protected:
void FastRunLoop(DisplayList &list) override;
void FinishDeferred() override;
+1 -1
View File
@@ -845,7 +845,7 @@ bool TextureCacheVulkan::GetCurrentTextureDebug(GPUDebugBuffer &buffer, int leve
void TextureCacheVulkan::GetStats(char *ptr, size_t size) {
snprintf(ptr, size, "Alloc: %d slabs\nSlab min/max: %d/%d\nAlloc usage: %d%%",
allocator_->GetBlockCount(), allocator_->GetMinSlabSize(), allocator_->GetMaxSlabSize(), allocator_->ComputeUsagePercent());
allocator_->GetSlabCount(), allocator_->GetMinSlabSize(), allocator_->GetMaxSlabSize(), allocator_->ComputeUsagePercent());
}
std::vector<std::string> TextureCacheVulkan::DebugGetSamplerIDs() const {
+2
View File
@@ -54,6 +54,8 @@ public:
Vulkan2D(VulkanContext *vulkan);
~Vulkan2D();
VulkanContext *GetVulkanContext() const { return vulkan_; }
void DeviceLost();
void DeviceRestore(VulkanContext *vulkan);
void Shutdown();
+1
View File
@@ -70,6 +70,7 @@ void DevMenu::CreatePopupContents(UI::ViewGroup *parent) {
items->Add(new Choice(sy->T("Developer Tools")))->OnClick.Handle(this, &DevMenu::OnDeveloperTools);
items->Add(new Choice(dev->T("Jit Compare")))->OnClick.Handle(this, &DevMenu::OnJitCompare);
items->Add(new Choice(dev->T("Shader Viewer")))->OnClick.Handle(this, &DevMenu::OnShaderView);
items->Add(new CheckBox(&g_Config.bShowAllocatorDebug, dev->T("Allocator Viewer")));
items->Add(new Choice(dev->T("Toggle Freeze")))->OnClick.Handle(this, &DevMenu::OnFreezeFrame);
items->Add(new Choice(dev->T("Dump Frame GPU Commands")))->OnClick.Handle(this, &DevMenu::OnDumpFrame);
items->Add(new Choice(dev->T("Toggle Audio Debug")))->OnClick.Handle(this, &DevMenu::OnToggleAudioDebug);
+13 -8
View File
@@ -50,6 +50,7 @@
#include "GPU/GPUState.h"
#include "GPU/GPUInterface.h"
#include "GPU/GLES/FramebufferManagerGLES.h"
#include "GPU/Vulkan/DebugVisVulkan.h"
#include "Core/HLE/sceCtrl.h"
#include "Core/HLE/sceDisplay.h"
#include "Core/HLE/sceSas.h"
@@ -1179,9 +1180,10 @@ void EmuScreen::renderUI() {
using namespace Draw;
DrawContext *thin3d = screenManager()->getDrawContext();
UIContext *ctx = screenManager()->getUIContext();
// This sets up some important states but not the viewport.
screenManager()->getUIContext()->Begin();
ctx->Begin();
Viewport viewport;
viewport.TopLeftX = 0;
@@ -1192,11 +1194,10 @@ void EmuScreen::renderUI() {
viewport.MinDepth = 0.0;
thin3d->SetViewports(1, &viewport);
DrawBuffer *draw2d = screenManager()->getUIContext()->Draw();
DrawBuffer *draw2d = ctx->Draw();
if (root_) {
UI::LayoutViewHierarchy(*screenManager()->getUIContext(), root_);
root_->Draw(*screenManager()->getUIContext());
UI::LayoutViewHierarchy(*ctx, root_);
root_->Draw(*ctx);
}
if (g_Config.bShowDebugStats && !invalid_) {
@@ -1208,16 +1209,20 @@ void EmuScreen::renderUI() {
}
if (g_Config.iShowFPSCounter && !invalid_) {
DrawFPS(draw2d, screenManager()->getUIContext()->GetBounds());
DrawFPS(draw2d, ctx->GetBounds());
}
if (g_Config.iGPUBackend == (int)GPUBackend::VULKAN && g_Config.bShowAllocatorDebug) {
DrawAllocatorVis(ctx, gpu);
}
#ifdef USE_PROFILER
if (g_Config.bShowFrameProfiler && !invalid_) {
DrawProfile(*screenManager()->getUIContext());
DrawProfile(*ctx);
}
#endif
screenManager()->getUIContext()->End();
ctx->End();
}
void EmuScreen::autoLoad() {
+2 -1
View File
@@ -142,7 +142,8 @@ VULKAN_FILES := \
$(SRC)/GPU/Vulkan/TextureScalerVulkan.cpp \
$(SRC)/GPU/Vulkan/DepalettizeShaderVulkan.cpp \
$(SRC)/GPU/Vulkan/VertexShaderGeneratorVulkan.cpp \
$(SRC)/GPU/Vulkan/VulkanUtil.cpp
$(SRC)/GPU/Vulkan/VulkanUtil.cpp \
$(SRC)/GPU/Vulkan/DebugVisVulkan.cpp
#endif
SPIRV_CROSS_FILES := \
+4
View File
@@ -219,6 +219,10 @@ public:
splitSubmit_ = split;
}
VulkanContext *GetVulkanContext() {
return vulkan_;
}
private:
bool InitBackbufferFramebuffers(int width, int height);
bool InitDepthStencilBuffer(VkCommandBuffer cmd); // Used for non-buffered rendering.
+2
View File
@@ -520,6 +520,7 @@ struct TextureDesc {
int depth;
int mipLevels;
bool generateMips;
// Does not take ownership over pointed-to data.
std::vector<uint8_t *> initData;
};
@@ -564,6 +565,7 @@ public:
// Resources
virtual Buffer *CreateBuffer(size_t size, uint32_t usageFlags) = 0;
// Does not take ownership over pointed-to initData. After this returns, can dispose of it.
virtual Texture *CreateTexture(const TextureDesc &desc) = 0;
// On some hardware, you might get a 24-bit depth buffer even though you only wanted a 16-bit one.
virtual Framebuffer *CreateFramebuffer(const FramebufferDesc &desc) = 0;
+1 -2
View File
@@ -652,8 +652,7 @@ enum class TextureState {
bool VKTexture::Create(VkCommandBuffer cmd, const TextureDesc &desc, VulkanDeviceAllocator *alloc) {
// Zero-sized textures not allowed.
if (desc.width * desc.height * desc.depth == 0)
return false;
assert(desc.width * desc.height * desc.depth > 0);
format_ = desc.format;
mipLevels_ = desc.mipLevels;
width_ = desc.width;