mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-23 21:39:52 +00:00
Add a hidden debug option [Graphics]GfxDebugSplitSubmit to try to narrow down some Vulkan issues, see #10163. Also improve some asserts.
This commit is contained in:
parent
acdb89c898
commit
b6911d2764
@ -18,6 +18,7 @@
|
|||||||
// Additionally, Common/Vulkan/* , including this file, are also licensed
|
// Additionally, Common/Vulkan/* , including this file, are also licensed
|
||||||
// under the public domain.
|
// under the public domain.
|
||||||
|
|
||||||
|
#include "Common/Log.h"
|
||||||
#include "Common/Vulkan/VulkanMemory.h"
|
#include "Common/Vulkan/VulkanMemory.h"
|
||||||
|
|
||||||
VulkanPushBuffer::VulkanPushBuffer(VulkanContext *vulkan, size_t size) : device_(vulkan->GetDevice()), buf_(0), offset_(0), size_(size), writePtr_(nullptr) {
|
VulkanPushBuffer::VulkanPushBuffer(VulkanContext *vulkan, size_t size) : device_(vulkan->GetDevice()), buf_(0), offset_(0), size_(size), writePtr_(nullptr) {
|
||||||
@ -44,7 +45,7 @@ bool VulkanPushBuffer::AddBuffer() {
|
|||||||
|
|
||||||
VkResult res = vkCreateBuffer(device_, &b, nullptr, &info.buffer);
|
VkResult res = vkCreateBuffer(device_, &b, nullptr, &info.buffer);
|
||||||
if (VK_SUCCESS != res) {
|
if (VK_SUCCESS != res) {
|
||||||
ELOG("vkCreateBuffer failed! result=%d", (int)res);
|
_assert_msg_(G3D, false, "vkCreateBuffer failed! result=%d", (int)res);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,7 +62,7 @@ bool VulkanPushBuffer::AddBuffer() {
|
|||||||
|
|
||||||
res = vkAllocateMemory(device_, &alloc, nullptr, &info.deviceMemory);
|
res = vkAllocateMemory(device_, &alloc, nullptr, &info.deviceMemory);
|
||||||
if (VK_SUCCESS != res) {
|
if (VK_SUCCESS != res) {
|
||||||
ELOG("vkAllocateMemory failed! result=%d", (int)res);
|
_assert_msg_(G3D, false, "vkAllocateMemory failed! size=%d result=%d", (int)reqs.size, (int)res);
|
||||||
vkDestroyBuffer(device_, info.buffer, nullptr);
|
vkDestroyBuffer(device_, info.buffer, nullptr);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -545,6 +545,7 @@ static ConfigSetting graphicsSettings[] = {
|
|||||||
ReportedConfigSetting("FragmentTestCache", &g_Config.bFragmentTestCache, true, true, true),
|
ReportedConfigSetting("FragmentTestCache", &g_Config.bFragmentTestCache, true, true, true),
|
||||||
|
|
||||||
ConfigSetting("GfxDebugOutput", &g_Config.bGfxDebugOutput, false, false, false),
|
ConfigSetting("GfxDebugOutput", &g_Config.bGfxDebugOutput, false, false, false),
|
||||||
|
ConfigSetting("GfxDebugSplitSubmit", &g_Config.bGfxDebugSplitSubmit, false, false, false),
|
||||||
ConfigSetting("LogFrameDrops", &g_Config.bLogFrameDrops, false, true, false),
|
ConfigSetting("LogFrameDrops", &g_Config.bLogFrameDrops, false, true, false),
|
||||||
|
|
||||||
ConfigSetting(false),
|
ConfigSetting(false),
|
||||||
|
@ -218,6 +218,7 @@ public:
|
|||||||
bool bHardwareTessellation;
|
bool bHardwareTessellation;
|
||||||
std::string sPostShaderName; // Off for off.
|
std::string sPostShaderName; // Off for off.
|
||||||
bool bGfxDebugOutput;
|
bool bGfxDebugOutput;
|
||||||
|
bool bGfxDebugSplitSubmit;
|
||||||
|
|
||||||
// Sound
|
// Sound
|
||||||
bool bEnableSound;
|
bool bEnableSound;
|
||||||
|
@ -473,7 +473,7 @@ VkDescriptorSet DrawEngineVulkan::GetOrCreateDescriptorSet(VkImageView imageView
|
|||||||
descAlloc.descriptorSetCount = 1;
|
descAlloc.descriptorSetCount = 1;
|
||||||
VkResult result = vkAllocateDescriptorSets(vulkan_->GetDevice(), &descAlloc, &desc);
|
VkResult result = vkAllocateDescriptorSets(vulkan_->GetDevice(), &descAlloc, &desc);
|
||||||
// Even in release mode, this is bad.
|
// Even in release mode, this is bad.
|
||||||
_assert_msg_(G3D, result == VK_SUCCESS, "Ran out of descriptor space in pool. sz=%d", (int)frame->descSets.size());
|
_assert_msg_(G3D, result == VK_SUCCESS, "Ran out of descriptor space in pool. sz=%d res=%d", (int)frame->descSets.size(), (int)result);
|
||||||
|
|
||||||
// We just don't write to the slots we don't care about.
|
// We just don't write to the slots we don't care about.
|
||||||
// We need 8 now that we support secondary texture bindings.
|
// We need 8 now that we support secondary texture bindings.
|
||||||
@ -1041,8 +1041,6 @@ DrawEngineVulkan::TessellationDataTransferVulkan::~TessellationDataTransferVulka
|
|||||||
void DrawEngineVulkan::TessellationDataTransferVulkan::PrepareBuffers(float *&pos, float *&tex, float *&col, int &posStride, int &texStride, int &colStride, int size, bool hasColor, bool hasTexCoords) {
|
void DrawEngineVulkan::TessellationDataTransferVulkan::PrepareBuffers(float *&pos, float *&tex, float *&col, int &posStride, int &texStride, int &colStride, int size, bool hasColor, bool hasTexCoords) {
|
||||||
colStride = 4;
|
colStride = 4;
|
||||||
|
|
||||||
assert(size > 0);
|
|
||||||
|
|
||||||
// TODO: This SHOULD work without padding but I can't get it to work on nvidia, so had
|
// TODO: This SHOULD work without padding but I can't get it to work on nvidia, so had
|
||||||
// to expand to vec4. Driver bug?
|
// to expand to vec4. Driver bug?
|
||||||
struct TessData {
|
struct TessData {
|
||||||
@ -1064,6 +1062,5 @@ void DrawEngineVulkan::TessellationDataTransferVulkan::PrepareBuffers(float *&po
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DrawEngineVulkan::TessellationDataTransferVulkan::SendDataToShader(const float *pos, const float *tex, const float *col, int size, bool hasColor, bool hasTexCoords) {
|
void DrawEngineVulkan::TessellationDataTransferVulkan::SendDataToShader(const float *pos, const float *tex, const float *col, int size, bool hasColor, bool hasTexCoords) {
|
||||||
assert(pos);
|
|
||||||
// Nothing to do here!
|
// Nothing to do here!
|
||||||
}
|
}
|
||||||
|
@ -278,6 +278,7 @@ static VulkanPipeline *CreateVulkanPipeline(VkDevice device, VkPipelineCache pip
|
|||||||
VkPipeline pipeline;
|
VkPipeline pipeline;
|
||||||
VkResult result = vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipe, nullptr, &pipeline);
|
VkResult result = vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipe, nullptr, &pipeline);
|
||||||
if (result != VK_SUCCESS) {
|
if (result != VK_SUCCESS) {
|
||||||
|
_assert_msg_(G3D, "Failed creating graphics pipeline! result='%s'", VulkanResultToString(result));
|
||||||
ERROR_LOG(G3D, "Failed creating graphics pipeline! result='%s'", VulkanResultToString(result));
|
ERROR_LOG(G3D, "Failed creating graphics pipeline! result='%s'", VulkanResultToString(result));
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -212,7 +212,9 @@ bool WindowsVulkanContext::Init(HINSTANCE hInst, HWND hWnd, std::string *error_m
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
draw_ = Draw::T3DCreateVulkanContext(g_Vulkan);
|
bool splitSubmit = g_Config.bGfxDebugSplitSubmit;
|
||||||
|
|
||||||
|
draw_ = Draw::T3DCreateVulkanContext(g_Vulkan, splitSubmit);
|
||||||
bool success = draw_->CreatePresets();
|
bool success = draw_->CreatePresets();
|
||||||
assert(success); // Doesn't fail, we include the compiler.
|
assert(success); // Doesn't fail, we include the compiler.
|
||||||
draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());
|
draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());
|
||||||
|
@ -762,8 +762,7 @@ void VulkanRenderManager::Submit(int frame, bool triggerFence) {
|
|||||||
if (frameData.hasInitCommands) {
|
if (frameData.hasInitCommands) {
|
||||||
cmdBufs[numCmdBufs++] = frameData.initCmd;
|
cmdBufs[numCmdBufs++] = frameData.initCmd;
|
||||||
frameData.hasInitCommands = false;
|
frameData.hasInitCommands = false;
|
||||||
}
|
if (splitSubmit_) {
|
||||||
if (false) {
|
|
||||||
// Send the init commands off separately. Used this once to confirm that the cause of a device loss was in the init cmdbuf.
|
// Send the init commands off separately. Used this once to confirm that the cause of a device loss was in the init cmdbuf.
|
||||||
VkSubmitInfo submit_info{ VK_STRUCTURE_TYPE_SUBMIT_INFO };
|
VkSubmitInfo submit_info{ VK_STRUCTURE_TYPE_SUBMIT_INFO };
|
||||||
submit_info.commandBufferCount = (uint32_t)numCmdBufs;
|
submit_info.commandBufferCount = (uint32_t)numCmdBufs;
|
||||||
@ -772,10 +771,11 @@ void VulkanRenderManager::Submit(int frame, bool triggerFence) {
|
|||||||
if (res == VK_ERROR_DEVICE_LOST) {
|
if (res == VK_ERROR_DEVICE_LOST) {
|
||||||
_assert_msg_(G3D, false, "Lost the Vulkan device!");
|
_assert_msg_(G3D, false, "Lost the Vulkan device!");
|
||||||
} else {
|
} else {
|
||||||
_assert_msg_(G3D, res == VK_SUCCESS, "vkQueueSubmit failed! result=%d", (int)res);
|
_assert_msg_(G3D, res == VK_SUCCESS, "vkQueueSubmit failed (init)! result=%d", (int)res);
|
||||||
}
|
}
|
||||||
numCmdBufs = 0;
|
numCmdBufs = 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
cmdBufs[numCmdBufs++] = frameData.mainCmd;
|
cmdBufs[numCmdBufs++] = frameData.mainCmd;
|
||||||
|
|
||||||
VkSubmitInfo submit_info{ VK_STRUCTURE_TYPE_SUBMIT_INFO };
|
VkSubmitInfo submit_info{ VK_STRUCTURE_TYPE_SUBMIT_INFO };
|
||||||
@ -795,7 +795,7 @@ void VulkanRenderManager::Submit(int frame, bool triggerFence) {
|
|||||||
if (res == VK_ERROR_DEVICE_LOST) {
|
if (res == VK_ERROR_DEVICE_LOST) {
|
||||||
_assert_msg_(G3D, false, "Lost the Vulkan device!");
|
_assert_msg_(G3D, false, "Lost the Vulkan device!");
|
||||||
} else {
|
} else {
|
||||||
_assert_msg_(G3D, res == VK_SUCCESS, "vkQueueSubmit failed! result=%d", (int)res);
|
_assert_msg_(G3D, res == VK_SUCCESS, "vkQueueSubmit failed (main, split=%d)! result=%d", (int)splitSubmit_, (int)res);
|
||||||
}
|
}
|
||||||
|
|
||||||
// When !triggerFence, we notify after syncing with Vulkan.
|
// When !triggerFence, we notify after syncing with Vulkan.
|
||||||
@ -823,8 +823,8 @@ void VulkanRenderManager::EndSubmitFrame(int frame) {
|
|||||||
present.waitSemaphoreCount = 1;
|
present.waitSemaphoreCount = 1;
|
||||||
|
|
||||||
VkResult res = vkQueuePresentKHR(vulkan_->GetGraphicsQueue(), &present);
|
VkResult res = vkQueuePresentKHR(vulkan_->GetGraphicsQueue(), &present);
|
||||||
// TODO: Deal with VK_SUBOPTIMAL_WSI ?
|
// TODO: Deal with VK_SUBOPTIMAL_KHR ?
|
||||||
if (res == VK_ERROR_OUT_OF_DATE_KHR) {
|
if (res == VK_ERROR_OUT_OF_DATE_KHR || res == VK_SUBOPTIMAL_KHR) {
|
||||||
// ignore, it'll be fine. this happens sometimes during resizes, and we do make sure to recreate the swap chain.
|
// ignore, it'll be fine. this happens sometimes during resizes, and we do make sure to recreate the swap chain.
|
||||||
} else {
|
} else {
|
||||||
_assert_msg_(G3D, res == VK_SUCCESS, "vkQueuePresentKHR failed! result=%d", (int)res);
|
_assert_msg_(G3D, res == VK_SUCCESS, "vkQueuePresentKHR failed! result=%d", (int)res);
|
||||||
|
@ -208,6 +208,10 @@ public:
|
|||||||
return !framebuffers_.empty();
|
return !framebuffers_.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetSplitSubmit(bool split) {
|
||||||
|
splitSubmit_ = split;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool InitBackbufferFramebuffers(int width, int height);
|
bool InitBackbufferFramebuffers(int width, int height);
|
||||||
bool InitDepthStencilBuffer(VkCommandBuffer cmd); // Used for non-buffered rendering.
|
bool InitDepthStencilBuffer(VkCommandBuffer cmd); // Used for non-buffered rendering.
|
||||||
@ -259,6 +263,7 @@ private:
|
|||||||
bool insideFrame_ = false;
|
bool insideFrame_ = false;
|
||||||
VKRStep *curRenderStep_ = nullptr;
|
VKRStep *curRenderStep_ = nullptr;
|
||||||
std::vector<VKRStep *> steps_;
|
std::vector<VKRStep *> steps_;
|
||||||
|
bool splitSubmit_ = false;
|
||||||
|
|
||||||
// Execution time state
|
// Execution time state
|
||||||
bool run_ = true;
|
bool run_ = true;
|
||||||
|
@ -665,7 +665,7 @@ DrawContext *T3DCreateDX9Context(IDirect3D9 *d3d, IDirect3D9Ex *d3dEx, int adapt
|
|||||||
DrawContext *T3DCreateD3D11Context(ID3D11Device *device, ID3D11DeviceContext *context, ID3D11Device1 *device1, ID3D11DeviceContext1 *context1, D3D_FEATURE_LEVEL featureLevel, HWND hWnd);
|
DrawContext *T3DCreateD3D11Context(ID3D11Device *device, ID3D11DeviceContext *context, ID3D11Device1 *device1, ID3D11DeviceContext1 *context1, D3D_FEATURE_LEVEL featureLevel, HWND hWnd);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DrawContext *T3DCreateVulkanContext(VulkanContext *context);
|
DrawContext *T3DCreateVulkanContext(VulkanContext *context, bool split);
|
||||||
|
|
||||||
// UBs for the preset shaders
|
// UBs for the preset shaders
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#include "Common/Vulkan/SPIRVDisasm.h"
|
#include "Common/Vulkan/SPIRVDisasm.h"
|
||||||
|
#include "Core/Config.h"
|
||||||
|
|
||||||
#include "base/logging.h"
|
#include "base/logging.h"
|
||||||
#include "base/display.h"
|
#include "base/display.h"
|
||||||
@ -348,7 +349,7 @@ class VKFramebuffer;
|
|||||||
|
|
||||||
class VKContext : public DrawContext {
|
class VKContext : public DrawContext {
|
||||||
public:
|
public:
|
||||||
VKContext(VulkanContext *vulkan);
|
VKContext(VulkanContext *vulkan, bool splitSubmit);
|
||||||
virtual ~VKContext();
|
virtual ~VKContext();
|
||||||
|
|
||||||
const DeviceCaps &GetDeviceCaps() const override {
|
const DeviceCaps &GetDeviceCaps() const override {
|
||||||
@ -674,7 +675,7 @@ bool VKTexture::Create(VkCommandBuffer cmd, const TextureDesc &desc) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
VKContext::VKContext(VulkanContext *vulkan)
|
VKContext::VKContext(VulkanContext *vulkan, bool splitSubmit)
|
||||||
: vulkan_(vulkan), caps_{}, renderManager_(vulkan) {
|
: vulkan_(vulkan), caps_{}, renderManager_(vulkan) {
|
||||||
caps_.anisoSupported = vulkan->GetFeaturesAvailable().samplerAnisotropy != 0;
|
caps_.anisoSupported = vulkan->GetFeaturesAvailable().samplerAnisotropy != 0;
|
||||||
caps_.geometryShaderSupported = vulkan->GetFeaturesAvailable().geometryShader != 0;
|
caps_.geometryShaderSupported = vulkan->GetFeaturesAvailable().geometryShader != 0;
|
||||||
@ -755,6 +756,8 @@ VKContext::VKContext(VulkanContext *vulkan)
|
|||||||
assert(VK_SUCCESS == res);
|
assert(VK_SUCCESS == res);
|
||||||
|
|
||||||
pipelineCache_ = vulkan_->CreatePipelineCache();
|
pipelineCache_ = vulkan_->CreatePipelineCache();
|
||||||
|
|
||||||
|
renderManager_.SetSplitSubmit(splitSubmit);
|
||||||
}
|
}
|
||||||
|
|
||||||
VKContext::~VKContext() {
|
VKContext::~VKContext() {
|
||||||
@ -1188,8 +1191,8 @@ void VKContext::Clear(int clearMask, uint32_t colorval, float depthVal, int sten
|
|||||||
renderManager_.Clear(colorval, depthVal, stencilVal, mask);
|
renderManager_.Clear(colorval, depthVal, stencilVal, mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawContext *T3DCreateVulkanContext(VulkanContext *vulkan) {
|
DrawContext *T3DCreateVulkanContext(VulkanContext *vulkan, bool split) {
|
||||||
return new VKContext(vulkan);
|
return new VKContext(vulkan, split);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddFeature(std::vector<std::string> &features, const char *name, VkBool32 available, VkBool32 enabled) {
|
void AddFeature(std::vector<std::string> &features, const char *name, VkBool32 available, VkBool32 enabled) {
|
||||||
|
Loading…
Reference in New Issue
Block a user