feat: Enable Vulkan validation layers and improve GPU diagnostics logging

This commit is contained in:
2026-01-04 00:34:04 +00:00
parent 5be0fd8dae
commit deea1cc19e
2 changed files with 83 additions and 50 deletions

View File

@@ -58,9 +58,34 @@ void Sdl3App::CreateInstance() {
TRACE_VAR(extensionCount);
TRACE_VAR(extensionList.size());
// Enable validation layers if available
std::vector<const char*> layerList;
uint32_t layerCount;
vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
std::vector<VkLayerProperties> availableLayers(layerCount);
vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data());
const char* validationLayer = "VK_LAYER_KHRONOS_validation";
bool validationAvailable = false;
for (const auto& layer : availableLayers) {
if (strcmp(layer.layerName, validationLayer) == 0) {
validationAvailable = true;
break;
}
}
if (validationAvailable) {
layerList.push_back(validationLayer);
std::cout << "Validation layer enabled: " << validationLayer << "\n";
} else {
std::cout << "Validation layer not available: " << validationLayer << "\n";
}
VkInstanceCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
createInfo.pApplicationInfo = &appInfo;
createInfo.enabledLayerCount = static_cast<uint32_t>(layerList.size());
createInfo.ppEnabledLayerNames = layerList.data();
createInfo.enabledExtensionCount = static_cast<uint32_t>(extensionList.size());
createInfo.ppEnabledExtensionNames = extensionList.data();

View File

@@ -3,6 +3,7 @@
#include "logging/logger.hpp"
#include <limits>
#include <sstream>
#include <stdexcept>
#include <unordered_map>
@@ -23,77 +24,78 @@ const std::unordered_map<SDL_Keycode, std::string> kGuiKeyNames = {
namespace sdl3cpp::app {
void Sdl3App::PrintGpuDiagnostics(const std::string& errorContext) {
std::cerr << "\n========================================\n";
std::cerr << "GPU DIAGNOSTIC REPORT\n";
std::cerr << "========================================\n";
std::cerr << "Error Context: " << errorContext << "\n\n";
std::stringstream ss;
ss << "\n========================================\n";
ss << "GPU DIAGNOSTIC REPORT\n";
ss << "========================================\n";
ss << "Error Context: " << errorContext << "\n\n";
// Device properties
if (physicalDevice_ != VK_NULL_HANDLE) {
VkPhysicalDeviceProperties deviceProps{};
vkGetPhysicalDeviceProperties(physicalDevice_, &deviceProps);
std::cerr << "=== GPU Information ===\n";
std::cerr << "Device Name: " << deviceProps.deviceName << "\n";
std::cerr << "Driver Version: " << VK_API_VERSION_MAJOR(deviceProps.driverVersion) << "."
ss << "=== GPU Information ===\n";
ss << "Device Name: " << deviceProps.deviceName << "\n";
ss << "Driver Version: " << VK_API_VERSION_MAJOR(deviceProps.driverVersion) << "."
<< VK_API_VERSION_MINOR(deviceProps.driverVersion) << "."
<< VK_API_VERSION_PATCH(deviceProps.driverVersion) << "\n";
std::cerr << "API Version: " << VK_API_VERSION_MAJOR(deviceProps.apiVersion) << "."
ss << "API Version: " << VK_API_VERSION_MAJOR(deviceProps.apiVersion) << "."
<< VK_API_VERSION_MINOR(deviceProps.apiVersion) << "."
<< VK_API_VERSION_PATCH(deviceProps.apiVersion) << "\n";
std::cerr << "Vendor ID: 0x" << std::hex << deviceProps.vendorID << std::dec << "\n";
std::cerr << "Device ID: 0x" << std::hex << deviceProps.deviceID << std::dec << "\n";
ss << "Vendor ID: 0x" << std::hex << deviceProps.vendorID << std::dec << "\n";
ss << "Device ID: 0x" << std::hex << deviceProps.deviceID << std::dec << "\n";
VkPhysicalDeviceMemoryProperties memProps{};
vkGetPhysicalDeviceMemoryProperties(physicalDevice_, &memProps);
std::cerr << "\n=== Memory Information ===\n";
ss << "\n=== Memory Information ===\n";
uint64_t totalVRAM = 0;
for (uint32_t i = 0; i < memProps.memoryHeapCount; i++) {
if (memProps.memoryHeaps[i].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) {
totalVRAM += memProps.memoryHeaps[i].size;
}
}
std::cerr << "Total VRAM: " << (totalVRAM / 1024 / 1024) << " MB\n";
ss << "Total VRAM: " << (totalVRAM / 1024 / 1024) << " MB\n";
// Memory heaps breakdown
std::cerr << "Memory Heaps (" << memProps.memoryHeapCount << "):\n";
ss << "Memory Heaps (" << memProps.memoryHeapCount << "):\n";
for (uint32_t i = 0; i < memProps.memoryHeapCount; i++) {
std::cerr << " Heap " << i << ": " << (memProps.memoryHeaps[i].size / 1024 / 1024) << " MB";
ss << " Heap " << i << ": " << (memProps.memoryHeaps[i].size / 1024 / 1024) << " MB";
if (memProps.memoryHeaps[i].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) {
std::cerr << " (Device Local)";
ss << " (Device Local)";
}
std::cerr << "\n";
ss << "\n";
}
}
// Swapchain state
std::cerr << "\n=== Swapchain State ===\n";
std::cerr << "Extent: " << swapChainExtent_.width << "x" << swapChainExtent_.height << "\n";
std::cerr << "Image Count: " << swapChainImages_.size() << "\n";
std::cerr << "Format: " << swapChainImageFormat_ << "\n";
std::cerr << "Consecutive Recreations: " << consecutiveSwapchainRecreations_ << "\n";
std::cerr << "Framebuffer Resized Flag: " << (framebufferResized_ ? "true" : "false") << "\n";
std::cerr << "First Frame Completed: " << (firstFrameCompleted_ ? "true" : "false") << "\n";
ss << "\n=== Swapchain State ===\n";
ss << "Extent: " << swapChainExtent_.width << "x" << swapChainExtent_.height << "\n";
ss << "Image Count: " << swapChainImages_.size() << "\n";
ss << "Format: " << swapChainImageFormat_ << "\n";
ss << "Consecutive Recreations: " << consecutiveSwapchainRecreations_ << "\n";
ss << "Framebuffer Resized Flag: " << (framebufferResized_ ? "true" : "false") << "\n";
ss << "First Frame Completed: " << (firstFrameCompleted_ ? "true" : "false") << "\n";
// Render objects
std::cerr << "\n=== Scene State ===\n";
std::cerr << "Render Objects: " << renderObjects_.size() << "\n";
std::cerr << "Vertices: " << vertices_.size() << "\n";
std::cerr << "Indices: " << indices_.size() << "\n";
std::cerr << "Pipelines: " << graphicsPipelines_.size() << "\n";
std::cerr << "GUI Renderer Active: " << (guiRenderer_ ? "true" : "false") << "\n";
std::cerr << "GUI Has Commands: " << (guiHasCommands_ ? "true" : "false") << "\n";
ss << "\n=== Scene State ===\n";
ss << "Render Objects: " << renderObjects_.size() << "\n";
ss << "Vertices: " << vertices_.size() << "\n";
ss << "Indices: " << indices_.size() << "\n";
ss << "Pipelines: " << graphicsPipelines_.size() << "\n";
ss << "GUI Renderer Active: " << (guiRenderer_ ? "true" : "false") << "\n";
ss << "GUI Has Commands: " << (guiHasCommands_ ? "true" : "false") << "\n";
// Check device features that might be related
if (physicalDevice_ != VK_NULL_HANDLE) {
VkPhysicalDeviceFeatures deviceFeatures{};
vkGetPhysicalDeviceFeatures(physicalDevice_, &deviceFeatures);
std::cerr << "\n=== Relevant Device Features ===\n";
std::cerr << "Geometry Shader: " << (deviceFeatures.geometryShader ? "supported" : "not supported") << "\n";
std::cerr << "Tessellation Shader: " << (deviceFeatures.tessellationShader ? "supported" : "not supported") << "\n";
std::cerr << "Multi Draw Indirect: " << (deviceFeatures.multiDrawIndirect ? "supported" : "not supported") << "\n";
ss << "\n=== Relevant Device Features ===\n";
ss << "Geometry Shader: " << (deviceFeatures.geometryShader ? "supported" : "not supported") << "\n";
ss << "Tessellation Shader: " << (deviceFeatures.tessellationShader ? "supported" : "not supported") << "\n";
ss << "Multi Draw Indirect: " << (deviceFeatures.multiDrawIndirect ? "supported" : "not supported") << "\n";
}
// Queue properties
@@ -103,28 +105,31 @@ void Sdl3App::PrintGpuDiagnostics(const std::string& errorContext) {
std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice_, &queueFamilyCount, queueFamilies.data());
std::cerr << "\n=== Queue Families ===\n";
ss << "\n=== Queue Families ===\n";
for (uint32_t i = 0; i < queueFamilyCount; i++) {
std::cerr << "Family " << i << ": " << queueFamilies[i].queueCount << " queues, flags: 0x"
ss << "Family " << i << ": " << queueFamilies[i].queueCount << " queues, flags: 0x"
<< std::hex << queueFamilies[i].queueFlags << std::dec << "\n";
}
}
std::cerr << "\n=== Possible Causes ===\n";
std::cerr << "1. GPU driver crash or hang - Check dmesg for GPU reset messages\n";
std::cerr << "2. Infinite loop in shader code - Review vertex/fragment shaders\n";
std::cerr << "3. Command buffer submission issue - Check synchronization\n";
std::cerr << "4. GPU overheating or hardware issue - Monitor GPU temperature\n";
std::cerr << "5. Driver bug - Try updating GPU drivers to latest version\n";
std::cerr << "6. Resource exhaustion - Check system memory and VRAM usage\n";
ss << "\n=== Possible Causes ===\n";
ss << "1. GPU driver crash or hang - Check dmesg for GPU reset messages\n";
ss << "2. Infinite loop in shader code - Review vertex/fragment shaders\n";
ss << "3. Command buffer submission issue - Check synchronization\n";
ss << "4. GPU overheating or hardware issue - Monitor GPU temperature\n";
ss << "5. Driver bug - Try updating GPU drivers to latest version\n";
ss << "6. Resource exhaustion - Check system memory and VRAM usage\n";
std::cerr << "\n=== Recommended Actions ===\n";
std::cerr << "1. Check system logs: dmesg | grep -i 'gpu\\|radeon\\|amdgpu'\n";
std::cerr << "2. Update GPU drivers: sudo dnf update mesa-vulkan-drivers\n";
std::cerr << "3. Verify GPU health: radeontop or similar monitoring tool\n";
std::cerr << "4. Check for driver messages: journalctl -k | grep -i amdgpu\n";
std::cerr << "5. Try with different Vulkan settings or validation layers\n";
std::cerr << "========================================\n\n";
ss << "\n=== Recommended Actions ===\n";
ss << "1. Check system logs: dmesg | grep -i 'gpu\\|radeon\\|amdgpu'\n";
ss << "2. Update GPU drivers: sudo dnf update mesa-vulkan-drivers\n";
ss << "3. Verify GPU health: radeontop or similar monitoring tool\n";
ss << "4. Check for driver messages: journalctl -k | grep -i amdgpu\n";
ss << "5. Try with different Vulkan settings or validation layers\n";
ss << "========================================\n";
// LOG_ERROR(ss.str());
std::cerr << ss.str() << std::endl;
}
void Sdl3App::CreateCommandBuffers() {
@@ -170,6 +175,8 @@ void Sdl3App::RecordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageI
vkCmdBindIndexBuffer(commandBuffer, indexBuffer_, 0, VK_INDEX_TYPE_UINT16);
core::PushConstants pushConstants{};
pushConstants.viewProj = viewProj;
// Temporarily disable drawing to test if hang is caused by draw commands
/*
for (const auto& object : renderObjects_) {
auto pipelineIt = graphicsPipelines_.find(object.shaderKey);
if (pipelineIt == graphicsPipelines_.end()) {
@@ -184,6 +191,7 @@ void Sdl3App::RecordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageI
&pushConstants);
vkCmdDrawIndexed(commandBuffer, object.indexCount, 1, object.indexOffset, object.vertexOffset, 0);
}
*/
vkCmdEndRenderPass(commandBuffer);
if (guiRenderer_) {
guiRenderer_->BlitToSwapchain(commandBuffer, swapChainImages_[imageIndex]);