diff --git a/Common/Vulkan/VulkanMemory.cpp b/Common/Vulkan/VulkanMemory.cpp index 2538865deb..67d300dc44 100644 --- a/Common/Vulkan/VulkanMemory.cpp +++ b/Common/Vulkan/VulkanMemory.cpp @@ -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; } diff --git a/Core/Config.cpp b/Core/Config.cpp index 9e0537ed24..48aee13246 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -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), diff --git a/Core/Config.h b/Core/Config.h index ee63af6f30..25882624e3 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -218,6 +218,7 @@ public: bool bHardwareTessellation; std::string sPostShaderName; // Off for off. bool bGfxDebugOutput; + bool bGfxDebugSplitSubmit; // Sound bool bEnableSound; diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index 88d0ed4b68..5e33cf017f 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -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! } diff --git a/GPU/Vulkan/PipelineManagerVulkan.cpp b/GPU/Vulkan/PipelineManagerVulkan.cpp index f63f0de9c1..4f3f8e0552 100644 --- a/GPU/Vulkan/PipelineManagerVulkan.cpp +++ b/GPU/Vulkan/PipelineManagerVulkan.cpp @@ -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; } diff --git a/Windows/GPU/WindowsVulkanContext.cpp b/Windows/GPU/WindowsVulkanContext.cpp index b7a3b44039..e0958b4f7f 100644 --- a/Windows/GPU/WindowsVulkanContext.cpp +++ b/Windows/GPU/WindowsVulkanContext.cpp @@ -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()); diff --git a/ext/native/thin3d/VulkanRenderManager.cpp b/ext/native/thin3d/VulkanRenderManager.cpp index 37f2555c09..23f48aba9d 100644 --- a/ext/native/thin3d/VulkanRenderManager.cpp +++ b/ext/native/thin3d/VulkanRenderManager.cpp @@ -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); diff --git a/ext/native/thin3d/VulkanRenderManager.h b/ext/native/thin3d/VulkanRenderManager.h index 86f282d43d..b8257cac86 100644 --- a/ext/native/thin3d/VulkanRenderManager.h +++ b/ext/native/thin3d/VulkanRenderManager.h @@ -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 steps_; + bool splitSubmit_ = false; // Execution time state bool run_ = true; diff --git a/ext/native/thin3d/thin3d.h b/ext/native/thin3d/thin3d.h index 9671bfa21b..0b77a21641 100644 --- a/ext/native/thin3d/thin3d.h +++ b/ext/native/thin3d/thin3d.h @@ -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 diff --git a/ext/native/thin3d/thin3d_vulkan.cpp b/ext/native/thin3d/thin3d_vulkan.cpp index 1e651b9e1b..a320a75061 100644 --- a/ext/native/thin3d/thin3d_vulkan.cpp +++ b/ext/native/thin3d/thin3d_vulkan.cpp @@ -22,6 +22,7 @@ #include #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 &features, const char *name, VkBool32 available, VkBool32 enabled) {