Skip to content

Commit

Permalink
[vulkan] handled swapchain VK_NOT_READY error
Browse files Browse the repository at this point in the history
  • Loading branch information
PanosK92 committed Feb 3, 2025
1 parent 8b80f6b commit 041a13a
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 29 deletions.
4 changes: 2 additions & 2 deletions runtime/Core/Debugging.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ namespace spartan
static bool IsBreadcrumbsEnabled() { return m_breadcrumbs_enabled; }

private:
inline static bool m_validation_layer_enabled = true; // enables Vulkan diagnostic layers, incurs significant per-draw CPU performance overhead
inline static bool m_gpu_assisted_validation_enabled = true; // performs GPU-based validation with substantial CPU and GPU performance impact
inline static bool m_validation_layer_enabled = false; // enables Vulkan diagnostic layers, incurs significant per-draw CPU performance overhead
inline static bool m_gpu_assisted_validation_enabled = false; // performs GPU-based validation with substantial CPU and GPU performance impact
inline static bool m_logging_to_file_enabled = false; // writes diagnostic logs to disk, causes high CPU overhead due to file I/O operations
inline static bool m_breadcrumbs_enabled = false; // tracks GPU crash information in breadcrumbs.txt, minimal overhead (AMD GPUs only)
inline static bool m_renderdoc_enabled = false; // integrates RenderDoc graphics debugging, introduces high CPU overhead from API wrapping
Expand Down
24 changes: 12 additions & 12 deletions runtime/RHI/RHI_DirectXShaderCompiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -227,12 +227,12 @@ Warning Options:

static bool error_check(IDxcResult* dxc_result)
{
// Get error buffer
// get error buffer
IDxcBlobEncoding* error_buffer = nullptr;
HRESULT result = dxc_result->GetErrorBuffer(&error_buffer);
if (SUCCEEDED(result))
{
// Log info, warnings and errors
// log info, warnings and errors
std::stringstream ss(std::string(static_cast<char*>(error_buffer->GetBufferPointer()), error_buffer->GetBufferSize()));
std::string line;
while (getline(ss, line, '\n'))
Expand Down Expand Up @@ -281,7 +281,7 @@ Warning Options:
DxcCreateInstance(CLSID_DxcCompiler, IID_PPV_ARGS(&m_compiler));
DxcCreateInstance(CLSID_DxcUtils, IID_PPV_ARGS(&m_utils));

// Try to get the version information
// try to get the version information
IDxcVersionInfo* version_info = nullptr;
HRESULT hr = m_compiler->QueryInterface(&version_info);
if (SUCCEEDED(hr) && version_info)
Expand All @@ -302,7 +302,7 @@ Warning Options:
}
}

// Get shader source
// get shader source
DxcBuffer dxc_buffer = {};
IDxcBlobEncoding* blob_encoding = nullptr;
{
Expand All @@ -314,37 +314,37 @@ Warning Options:

dxc_buffer.Ptr = blob_encoding->GetBufferPointer();
dxc_buffer.Size = blob_encoding->GetBufferSize();
dxc_buffer.Encoding = DXC_CP_ACP; // Assume BOM says UTF8 or UTF16 or this is ANSI text.
dxc_buffer.Encoding = DXC_CP_ACP; // assume BOM says UTF8 or UTF16 or this is ANSI text
}

// Convert arguments to wstring
// convert arguments to wstring
std::vector<std::wstring> arguments_wstring;
arguments_wstring.reserve(arguments.size());
for (const std::string& str : arguments)
{
arguments_wstring.emplace_back(FileSystem::StringToWstring(str));
}

// Convert arguments to LPCWSTR
// convert arguments to LPCWSTR
std::vector<LPCWSTR> arguments_lpcwstr;
arguments_lpcwstr.reserve(arguments.size());
for (const std::wstring& wstr : arguments_wstring)
{
arguments_lpcwstr.emplace_back(wstr.c_str());
}

// Compile
// compile
IDxcResult* dxc_result = nullptr;
m_compiler->Compile
(
&dxc_buffer, // Source text to compile
arguments_lpcwstr.data(), // Array of pointers to arguments
static_cast<uint32_t>(arguments_lpcwstr.size()), // Number of arguments
&dxc_buffer, // source text to compile
arguments_lpcwstr.data(), // array of pointers to arguments
static_cast<uint32_t>(arguments_lpcwstr.size()), // number of arguments
nullptr, // don't use an include handler
IID_PPV_ARGS(&dxc_result) // IDxcResult: status, buffer, and errors
);

// Check for errors
// check for errors
if (!error_check(dxc_result))
{
if (dxc_result)
Expand Down
5 changes: 2 additions & 3 deletions runtime/RHI/Vulkan/Vulkan_DescriptorSet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "../RHI_Device.h"
#include "../RHI_DescriptorSet.h"
#include "../RHI_Implementation.h"
#include "../RHI_Sampler.h"
#include "../RHI_Buffer.h"
#include "../Rendering/Renderer.h"
//================================
Expand Down Expand Up @@ -59,11 +58,11 @@ namespace spartan
for (const RHI_Descriptor& descriptor : descriptors)
{
// in case of a null texture (which is legal), don't skip it
// set a checkeboard texture instead, this way if it's sampled (which is wrong), we'll see it
// set a checkerboard texture instead, this way if it's sampled (which is wrong), we'll see it
if (!descriptor.data && descriptor.type != RHI_Descriptor_Type::Texture)
continue;

// the binldess texture array has it's own descriptor
// the bindldess texture array has it's own descriptor
bool binldess_array = descriptor.as_array && descriptor.array_length == rhi_max_array_size;
if (binldess_array)
continue;
Expand Down
2 changes: 1 addition & 1 deletion runtime/RHI/Vulkan/Vulkan_Device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1107,7 +1107,7 @@ namespace spartan
}
else
{
features_robustness.pNext = nullptr; /// remove VRS from the chain
features_robustness.pNext = nullptr; // remove VRS from the chain
}
}

Expand Down
45 changes: 34 additions & 11 deletions runtime/RHI/Vulkan/Vulkan_SwapChain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -410,26 +410,49 @@ namespace spartan

void RHI_SwapChain::AcquireNextImage()
{
// when we run out of buffers, wait
// Reset any previous state if needed
if (m_buffer_index != numeric_limits<uint32_t>::max())
{
m_image_acquired_fence[m_buffer_index]->Wait();
m_image_acquired_fence[m_buffer_index]->Reset();
}

// get sync objects
// Prepare for the acquisition
m_buffer_index = (m_buffer_index + 1) % m_buffer_count;
RHI_SyncPrimitive* signal_semaphore = m_image_acquired_semaphore[m_buffer_index].get();
RHI_SyncPrimitive* signal_fence = m_image_acquired_fence[m_buffer_index].get();

SP_ASSERT_VK(vkAcquireNextImageKHR(
RHI_Context::device, // device
static_cast<VkSwapchainKHR>(m_rhi_swapchain), // swapchain
numeric_limits<uint64_t>::max(), // timeout - wait/block
static_cast<VkSemaphore>(signal_semaphore->GetRhiResource()), // signal semaphore
static_cast<VkFence>(signal_fence->GetRhiResource()), // signal fence
&m_image_index // pImageIndex
));
// i've had a case with a 1080 Ti where vkAcquireNextImageKHR would
// return VK_NOT_READY so we handle that by retrying a few times
uint32_t retry_count = 0;
const uint32_t retry_max = 5;
while (retry_count < retry_max)
{
VkResult result = vkAcquireNextImageKHR(
RHI_Context::device,
static_cast<VkSwapchainKHR>(m_rhi_swapchain),
numeric_limits<uint64_t>::max(),
static_cast<VkSemaphore>(signal_semaphore->GetRhiResource()),
static_cast<VkFence>(signal_fence->GetRhiResource()),
&m_image_index
);

if (result == VK_SUCCESS)
{
return;
}
else if (result == VK_NOT_READY)
{
this_thread::sleep_for(std::chrono::milliseconds(1));
retry_count++;
}
else
{
SP_ASSERT_VK(result);
}
}

SP_ASSERT_MSG(false, "Failed to acquire next image after multiple retries");
}

void RHI_SwapChain::Present()
Expand Down

0 comments on commit 041a13a

Please sign in to comment.