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:
Henrik Rydgård 2017-11-22 10:46:23 +01:00
parent acdb89c898
commit b6911d2764
10 changed files with 38 additions and 27 deletions

View File

@ -18,6 +18,7 @@
// Additionally, Common/Vulkan/* , including this file, are also licensed
// under the public domain.
#include "Common/Log.h"
#include "Common/Vulkan/VulkanMemory.h"
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);
if (VK_SUCCESS != res) {
ELOG("vkCreateBuffer failed! result=%d", (int)res);
_assert_msg_(G3D, false, "vkCreateBuffer failed! result=%d", (int)res);
return false;
}
@ -61,7 +62,7 @@ bool VulkanPushBuffer::AddBuffer() {
res = vkAllocateMemory(device_, &alloc, nullptr, &info.deviceMemory);
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);
return false;
}

View File

@ -545,6 +545,7 @@ static ConfigSetting graphicsSettings[] = {
ReportedConfigSetting("FragmentTestCache", &g_Config.bFragmentTestCache, true, true, true),
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(false),

View File

@ -218,6 +218,7 @@ public:
bool bHardwareTessellation;
std::string sPostShaderName; // Off for off.
bool bGfxDebugOutput;
bool bGfxDebugSplitSubmit;
// Sound
bool bEnableSound;

View File

@ -473,7 +473,7 @@ VkDescriptorSet DrawEngineVulkan::GetOrCreateDescriptorSet(VkImageView imageView
descAlloc.descriptorSetCount = 1;
VkResult result = vkAllocateDescriptorSets(vulkan_->GetDevice(), &descAlloc, &desc);
// 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 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) {
colStride = 4;
assert(size > 0);
// TODO: This SHOULD work without padding but I can't get it to work on nvidia, so had
// to expand to vec4. Driver bug?
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) {
assert(pos);
// Nothing to do here!
}

View File

@ -278,6 +278,7 @@ static VulkanPipeline *CreateVulkanPipeline(VkDevice device, VkPipelineCache pip
VkPipeline pipeline;
VkResult result = vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipe, nullptr, &pipeline);
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));
return nullptr;
}

View File

@ -212,7 +212,9 @@ bool WindowsVulkanContext::Init(HINSTANCE hInst, HWND hWnd, std::string *error_m
return false;
}
draw_ = Draw::T3DCreateVulkanContext(g_Vulkan);
bool splitSubmit = g_Config.bGfxDebugSplitSubmit;
draw_ = Draw::T3DCreateVulkanContext(g_Vulkan, splitSubmit);
bool success = draw_->CreatePresets();
assert(success); // Doesn't fail, we include the compiler.
draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());

View File

@ -762,19 +762,19 @@ void VulkanRenderManager::Submit(int frame, bool triggerFence) {
if (frameData.hasInitCommands) {
cmdBufs[numCmdBufs++] = frameData.initCmd;
frameData.hasInitCommands = false;
}
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.
VkSubmitInfo submit_info{ VK_STRUCTURE_TYPE_SUBMIT_INFO };
submit_info.commandBufferCount = (uint32_t)numCmdBufs;
submit_info.pCommandBuffers = cmdBufs;
res = vkQueueSubmit(vulkan_->GetGraphicsQueue(), 1, &submit_info, VK_NULL_HANDLE);
if (res == VK_ERROR_DEVICE_LOST) {
_assert_msg_(G3D, false, "Lost the Vulkan device!");
} else {
_assert_msg_(G3D, res == VK_SUCCESS, "vkQueueSubmit failed! result=%d", (int)res);
if (splitSubmit_) {
// 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 };
submit_info.commandBufferCount = (uint32_t)numCmdBufs;
submit_info.pCommandBuffers = cmdBufs;
res = vkQueueSubmit(vulkan_->GetGraphicsQueue(), 1, &submit_info, VK_NULL_HANDLE);
if (res == VK_ERROR_DEVICE_LOST) {
_assert_msg_(G3D, false, "Lost the Vulkan device!");
} else {
_assert_msg_(G3D, res == VK_SUCCESS, "vkQueueSubmit failed (init)! result=%d", (int)res);
}
numCmdBufs = 0;
}
numCmdBufs = 0;
}
cmdBufs[numCmdBufs++] = frameData.mainCmd;
@ -795,7 +795,7 @@ void VulkanRenderManager::Submit(int frame, bool triggerFence) {
if (res == VK_ERROR_DEVICE_LOST) {
_assert_msg_(G3D, false, "Lost the Vulkan device!");
} 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.
@ -823,8 +823,8 @@ void VulkanRenderManager::EndSubmitFrame(int frame) {
present.waitSemaphoreCount = 1;
VkResult res = vkQueuePresentKHR(vulkan_->GetGraphicsQueue(), &present);
// TODO: Deal with VK_SUBOPTIMAL_WSI ?
if (res == VK_ERROR_OUT_OF_DATE_KHR) {
// TODO: Deal with VK_SUBOPTIMAL_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.
} else {
_assert_msg_(G3D, res == VK_SUCCESS, "vkQueuePresentKHR failed! result=%d", (int)res);

View File

@ -208,6 +208,10 @@ public:
return !framebuffers_.empty();
}
void SetSplitSubmit(bool split) {
splitSubmit_ = split;
}
private:
bool InitBackbufferFramebuffers(int width, int height);
bool InitDepthStencilBuffer(VkCommandBuffer cmd); // Used for non-buffered rendering.
@ -259,6 +263,7 @@ private:
bool insideFrame_ = false;
VKRStep *curRenderStep_ = nullptr;
std::vector<VKRStep *> steps_;
bool splitSubmit_ = false;
// Execution time state
bool run_ = true;

View File

@ -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);
#endif
DrawContext *T3DCreateVulkanContext(VulkanContext *context);
DrawContext *T3DCreateVulkanContext(VulkanContext *context, bool split);
// UBs for the preset shaders

View File

@ -22,6 +22,7 @@
#include <assert.h>
#include "Common/Vulkan/SPIRVDisasm.h"
#include "Core/Config.h"
#include "base/logging.h"
#include "base/display.h"
@ -348,7 +349,7 @@ class VKFramebuffer;
class VKContext : public DrawContext {
public:
VKContext(VulkanContext *vulkan);
VKContext(VulkanContext *vulkan, bool splitSubmit);
virtual ~VKContext();
const DeviceCaps &GetDeviceCaps() const override {
@ -674,7 +675,7 @@ bool VKTexture::Create(VkCommandBuffer cmd, const TextureDesc &desc) {
return true;
}
VKContext::VKContext(VulkanContext *vulkan)
VKContext::VKContext(VulkanContext *vulkan, bool splitSubmit)
: vulkan_(vulkan), caps_{}, renderManager_(vulkan) {
caps_.anisoSupported = vulkan->GetFeaturesAvailable().samplerAnisotropy != 0;
caps_.geometryShaderSupported = vulkan->GetFeaturesAvailable().geometryShader != 0;
@ -755,6 +756,8 @@ VKContext::VKContext(VulkanContext *vulkan)
assert(VK_SUCCESS == res);
pipelineCache_ = vulkan_->CreatePipelineCache();
renderManager_.SetSplitSubmit(splitSubmit);
}
VKContext::~VKContext() {
@ -1188,8 +1191,8 @@ void VKContext::Clear(int clearMask, uint32_t colorval, float depthVal, int sten
renderManager_.Clear(colorval, depthVal, stencilVal, mask);
}
DrawContext *T3DCreateVulkanContext(VulkanContext *vulkan) {
return new VKContext(vulkan);
DrawContext *T3DCreateVulkanContext(VulkanContext *vulkan, bool split) {
return new VKContext(vulkan, split);
}
void AddFeature(std::vector<std::string> &features, const char *name, VkBool32 available, VkBool32 enabled) {