render: call Vulkan diagnostics and capability checks directly

This commit is contained in:
nmzik
2026-09-06 04:11:46 +04:00
parent dda628ca81
commit 1eb13dfa5e
12 changed files with 29 additions and 48 deletions
+4 -1
View File
@@ -31,7 +31,6 @@ struct GraphicContext {
bool memory_budget_ext_enabled = false; bool memory_budget_ext_enabled = false;
bool rt_extensions_enabled = false; bool rt_extensions_enabled = false;
bool compute_subgroup_size_control_enabled = false; bool compute_subgroup_size_control_enabled = false;
bool compute_wave64_supported = false;
bool sample_rate_shading_enabled = false; bool sample_rate_shading_enabled = false;
bool mesh_shader_enabled = false; bool mesh_shader_enabled = false;
vk::PhysicalDeviceMeshShaderPropertiesEXT mesh_shader_properties = {}; vk::PhysicalDeviceMeshShaderPropertiesEXT mesh_shader_properties = {};
@@ -82,6 +81,10 @@ struct GraphicContext {
return it->second.first; return it->second.first;
} }
[[nodiscard]] bool SupportsComputeWave64() const noexcept {
return subgroup_size == 64u || compute_subgroup_size_control_enabled;
}
[[nodiscard]] vk::DeviceSize StorageMinAlignment() const { [[nodiscard]] vk::DeviceSize StorageMinAlignment() const {
const auto alignment = physical_device_properties.limits.minStorageBufferOffsetAlignment; const auto alignment = physical_device_properties.limits.minStorageBufferOffsetAlignment;
return alignment != 0 ? alignment : 1; return alignment != 0 ? alignment : 1;
@@ -19,11 +19,11 @@ void ReportVulkanFatal(const char* what, vk::Result result, uint64_t tick, uint3
uint32_t arg3, uint64_t arg4) { uint32_t arg3, uint64_t arg4) {
LOGF("%s failed: %s (%d), tick=%" PRIu64 " debug_op=%u debug_submit=%" PRIu64 LOGF("%s failed: %s (%d), tick=%" PRIu64 " debug_op=%u debug_submit=%" PRIu64
" args=%u,%u,%u,%u,0x%016" PRIx64 "\n", " args=%u,%u,%u,%u,0x%016" PRIx64 "\n",
what, VulkanToString(result).c_str(), static_cast<int>(result), tick, debug_op, what, vk::to_string(result).c_str(), static_cast<int>(result), tick, debug_op,
debug_submit, arg0, arg1, arg2, arg3, arg4); debug_submit, arg0, arg1, arg2, arg3, arg4);
std::printf("%s failed: %s (%d), tick=%" PRIu64 " debug_op=%u debug_submit=%" PRIu64 std::printf("%s failed: %s (%d), tick=%" PRIu64 " debug_op=%u debug_submit=%" PRIu64
" args=%u,%u,%u,%u,0x%016" PRIx64 "\n", " args=%u,%u,%u,%u,0x%016" PRIx64 "\n",
what, VulkanToString(result).c_str(), static_cast<int>(result), tick, debug_op, what, vk::to_string(result).c_str(), static_cast<int>(result), tick, debug_op,
debug_submit, arg0, arg1, arg2, arg3, arg4); debug_submit, arg0, arg1, arg2, arg3, arg4);
std::fflush(stdout); std::fflush(stdout);
} }
@@ -206,7 +206,7 @@ void RenderExecutor::ResolveRenderDepthTarget(uint64_t submit_id, CommandBuffer&
const auto format = ResolveHostDepthAttachmentFormat(buffer, *policy, has_stencil, samples); const auto format = ResolveHostDepthAttachmentFormat(buffer, *policy, has_stencil, samples);
if (format == vk::Format::eUndefined) { if (format == vk::Format::eUndefined) {
DepthFatal("no host depth/stencil format supports required usage for %s", DepthFatal("no host depth/stencil format supports required usage for %s",
VulkanToString(ideal_format).c_str()); vk::to_string(ideal_format).c_str());
} }
const auto guest_format = policy->guest_format; const auto guest_format = policy->guest_format;
const uint32_t bytes = policy->bytes_per_element; const uint32_t bytes = policy->bytes_per_element;
@@ -455,14 +455,14 @@ void PipelineCache::InitializeDriverCache() {
auto result = m_graphics.device.createPipelineCache(&create, nullptr, &m_driver_cache); auto result = m_graphics.device.createPipelineCache(&create, nullptr, &m_driver_cache);
if (result != vk::Result::eSuccess && !initial_data.empty()) { if (result != vk::Result::eSuccess && !initial_data.empty()) {
PipelineCacheLog("Vulkan pipeline cache: driver rejected {} ({}); starting empty", path, PipelineCacheLog("Vulkan pipeline cache: driver rejected {} ({}); starting empty", path,
VulkanToString(result)); vk::to_string(result));
initial_data.clear(); initial_data.clear();
create.initialDataSize = 0; create.initialDataSize = 0;
create.pInitialData = nullptr; create.pInitialData = nullptr;
result = m_graphics.device.createPipelineCache(&create, nullptr, &m_driver_cache); result = m_graphics.device.createPipelineCache(&create, nullptr, &m_driver_cache);
} }
if (result != vk::Result::eSuccess) { if (result != vk::Result::eSuccess) {
PipelineCacheLog("Vulkan pipeline cache: disabled ({})", VulkanToString(result)); PipelineCacheLog("Vulkan pipeline cache: disabled ({})", vk::to_string(result));
m_driver_cache = nullptr; m_driver_cache = nullptr;
return; return;
} }
@@ -499,7 +499,7 @@ void PipelineCache::Save() {
if (result != vk::Result::eSuccess || size == 0 || if (result != vk::Result::eSuccess || size == 0 ||
size > std::numeric_limits<uint32_t>::max()) { size > std::numeric_limits<uint32_t>::max()) {
PipelineCacheLog("Vulkan pipeline cache: save failed ({}, {} bytes)", PipelineCacheLog("Vulkan pipeline cache: save failed ({}, {} bytes)",
VulkanToString(result), size); vk::to_string(result), size);
return; return;
} }
payload.resize(size); payload.resize(size);
@@ -590,7 +590,7 @@ PipelineCache::GraphicsPrograms PipelineCache::GetGraphicsPrograms(
ShaderProgram PipelineCache::GetComputeProgram(const HW::ComputeShaderInfo& regs, ShaderProgram PipelineCache::GetComputeProgram(const HW::ComputeShaderInfo& regs,
const HW::ShaderRegisters& sh, const HW::ShaderRegisters& sh,
ShaderComputeInputInfo& input_info) { ShaderComputeInputInfo& input_info) {
input_info.host_subgroup_size = m_graphics.compute_wave64_supported ? 64u : 32u; input_info.host_subgroup_size = m_graphics.SupportsComputeWave64() ? 64u : 32u;
const auto params = PrepareProgram(regs, sh, input_info); const auto params = PrepareProgram(regs, sh, input_info);
Common::LockGuard lock(m_mutex); Common::LockGuard lock(m_mutex);
uint32_t push_data_cursor = 0; uint32_t push_data_cursor = 0;
@@ -103,7 +103,7 @@ static void GetInputFormat(const ShaderBufferResource& res, vk::Format& format,
size = 4; size = 4;
if (NarrowInputFormat(format, size, used_components)) { if (NarrowInputFormat(format, size, used_components)) {
LOGF("InputFormat: narrowing fmt=%u to %s for used_components=%u\n", raw_format, LOGF("InputFormat: narrowing fmt=%u to %s for used_components=%u\n", raw_format,
VulkanToString(format).c_str(), used_components); vk::to_string(format).c_str(), used_components);
} }
return; return;
} }
@@ -117,7 +117,7 @@ static void GetInputFormat(const ShaderBufferResource& res, vk::Format& format,
size = 2; size = 2;
if (NarrowInputFormat(format, size, used_components)) { if (NarrowInputFormat(format, size, used_components)) {
LOGF("InputFormat: narrowing fmt=%u to %s for used_components=%u\n", raw_format, LOGF("InputFormat: narrowing fmt=%u to %s for used_components=%u\n", raw_format,
VulkanToString(format).c_str(), used_components); vk::to_string(format).c_str(), used_components);
} }
return; return;
} }
@@ -450,7 +450,7 @@ void CreatePipelineInternal(
graphics.device.createShaderModule(&create_info, nullptr, &tess_control_shader_module); graphics.device.createShaderModule(&create_info, nullptr, &tess_control_shader_module);
if (graphics_debug_dump_enabled()) { if (graphics_debug_dump_enabled()) {
LOGF("PipelineTrace: vkCreateShaderModule RectList TCS done result=%s module=%p\n", LOGF("PipelineTrace: vkCreateShaderModule RectList TCS done result=%s module=%p\n",
VulkanToString(result).c_str(), static_cast<void*>(tess_control_shader_module)); vk::to_string(result).c_str(), static_cast<void*>(tess_control_shader_module));
} }
EXIT_NOT_IMPLEMENTED(result != vk::Result::eSuccess); EXIT_NOT_IMPLEMENTED(result != vk::Result::eSuccess);
@@ -460,7 +460,7 @@ void CreatePipelineInternal(
graphics.device.createShaderModule(&create_info, nullptr, &tess_eval_shader_module); graphics.device.createShaderModule(&create_info, nullptr, &tess_eval_shader_module);
if (graphics_debug_dump_enabled()) { if (graphics_debug_dump_enabled()) {
LOGF("PipelineTrace: vkCreateShaderModule RectList TES done result=%s module=%p\n", LOGF("PipelineTrace: vkCreateShaderModule RectList TES done result=%s module=%p\n",
VulkanToString(result).c_str(), static_cast<void*>(tess_eval_shader_module)); vk::to_string(result).c_str(), static_cast<void*>(tess_eval_shader_module));
} }
EXIT_NOT_IMPLEMENTED(result != vk::Result::eSuccess); EXIT_NOT_IMPLEMENTED(result != vk::Result::eSuccess);
} }
@@ -678,7 +678,7 @@ void CreatePipelineInternal(
&pipeline.pipeline_layout); &pipeline.pipeline_layout);
if (graphics_debug_dump_enabled()) { if (graphics_debug_dump_enabled()) {
LOGF("PipelineTrace: vkCreatePipelineLayout done result=%s layout=%p\n", LOGF("PipelineTrace: vkCreatePipelineLayout done result=%s layout=%p\n",
VulkanToString(result).c_str(), static_cast<void*>(pipeline.pipeline_layout)); vk::to_string(result).c_str(), static_cast<void*>(pipeline.pipeline_layout));
} }
EXIT_NOT_IMPLEMENTED(result != vk::Result::eSuccess); EXIT_NOT_IMPLEMENTED(result != vk::Result::eSuccess);
@@ -771,7 +771,7 @@ void CreatePipelineInternal(
&pipeline.pipeline); &pipeline.pipeline);
if (graphics_debug_dump_enabled()) { if (graphics_debug_dump_enabled()) {
LOGF("PipelineTrace: vkCreateGraphicsPipelines done result=%s pipeline=%p\n", LOGF("PipelineTrace: vkCreateGraphicsPipelines done result=%s pipeline=%p\n",
VulkanToString(result).c_str(), static_cast<void*>(pipeline.pipeline)); vk::to_string(result).c_str(), static_cast<void*>(pipeline.pipeline));
} }
EXIT_NOT_IMPLEMENTED(result != vk::Result::eSuccess); EXIT_NOT_IMPLEMENTED(result != vk::Result::eSuccess);
@@ -824,7 +824,7 @@ void CreatePipelineInternal(GraphicContext& graphics, PipelineCache::Pipeline& p
auto result = graphics.device.createPipelineLayout(&pipeline_layout_info, nullptr, auto result = graphics.device.createPipelineLayout(&pipeline_layout_info, nullptr,
&pipeline.pipeline_layout); &pipeline.pipeline_layout);
LOGF("PipelineTrace: vkCreatePipelineLayout CS done result=%s layout=%p\n", LOGF("PipelineTrace: vkCreatePipelineLayout CS done result=%s layout=%p\n",
VulkanToString(result).c_str(), static_cast<void*>(pipeline.pipeline_layout)); vk::to_string(result).c_str(), static_cast<void*>(pipeline.pipeline_layout));
EXIT_NOT_IMPLEMENTED(result != vk::Result::eSuccess); EXIT_NOT_IMPLEMENTED(result != vk::Result::eSuccess);
EXIT_NOT_IMPLEMENTED(pipeline.pipeline_layout == nullptr); EXIT_NOT_IMPLEMENTED(pipeline.pipeline_layout == nullptr);
@@ -841,7 +841,7 @@ void CreatePipelineInternal(GraphicContext& graphics, PipelineCache::Pipeline& p
result = graphics.device.createComputePipelines(driver_cache, 1, &info, nullptr, result = graphics.device.createComputePipelines(driver_cache, 1, &info, nullptr,
&pipeline.pipeline); &pipeline.pipeline);
LOGF("PipelineTrace: vkCreateComputePipelines done result=%s pipeline=%p\n", LOGF("PipelineTrace: vkCreateComputePipelines done result=%s pipeline=%p\n",
VulkanToString(result).c_str(), static_cast<void*>(pipeline.pipeline)); vk::to_string(result).c_str(), static_cast<void*>(pipeline.pipeline));
EXIT_NOT_IMPLEMENTED(result != vk::Result::eSuccess); EXIT_NOT_IMPLEMENTED(result != vk::Result::eSuccess);
EXIT_NOT_IMPLEMENTED(pipeline.pipeline == nullptr); EXIT_NOT_IMPLEMENTED(pipeline.pipeline == nullptr);
@@ -133,7 +133,7 @@ static void LogFramebufferSkip(const char* draw_name, const RenderColorInfo& col
" prim=%u index_count=%u flags=0x%08" PRIx32 "\n", " prim=%u index_count=%u flags=0x%08" PRIx32 "\n",
log_id, draw_name, RenderColorTypeName(color), color.desc.info.data.address, log_id, draw_name, RenderColorTypeName(color), color.desc.info.data.address,
color.desc.info.data.size, color.image_id ? "yes" : "no", color.desc.info.data.size, color.image_id ? "yes" : "no",
VulkanToString(depth.desc.view_info.format).c_str(), depth.image_id ? "yes" : "no", vk::to_string(depth.desc.view_info.format).c_str(), depth.image_id ? "yes" : "no",
static_cast<int>(!depth.desc.info.data.Empty()) + static_cast<int>(!depth.desc.info.data.Empty()) +
static_cast<int>(depth.desc.info.HasStencil()), static_cast<int>(depth.desc.info.HasStencil()),
ctx.GetRenderTargetMask(), static_cast<uint32_t>(ucfg.GetPrimType()), index_count, flags); ctx.GetRenderTargetMask(), static_cast<uint32_t>(ucfg.GetPrimType()), index_count, flags);
+1 -1
View File
@@ -71,7 +71,7 @@ bool GraphicContext::CreateAllocator() {
const auto result = static_cast<vk::Result>(vmaCreateAllocator(&info, &allocator)); const auto result = static_cast<vk::Result>(vmaCreateAllocator(&info, &allocator));
if (result != vk::Result::eSuccess) { if (result != vk::Result::eSuccess) {
LOGF("vmaCreateAllocator failed: %s\n", VulkanToString(result).c_str()); LOGF("vmaCreateAllocator failed: %s\n", vk::to_string(result).c_str());
return false; return false;
} }
return true; return true;
+1 -17
View File
@@ -96,22 +96,6 @@ constexpr auto kFormatLookup = MakeFormatLookup();
} // namespace } // namespace
std::string VulkanToString(vk::Result value) {
return vk::to_string(value);
}
std::string VulkanToString(vk::Format value) {
return vk::to_string(value);
}
std::string VulkanToString(vk::ImageLayout value) {
return vk::to_string(value);
}
std::string VulkanToString(vk::QueueFlags value) {
return vk::to_string(value);
}
vk::Format VulkanFormat(Prospero::BufferFormat guest_format) { vk::Format VulkanFormat(Prospero::BufferFormat guest_format) {
const auto index = static_cast<size_t>(guest_format); const auto index = static_cast<size_t>(guest_format);
return index < kFormatLookup.size() ? kFormatLookup[index] : vk::Format::eUndefined; return index < kFormatLookup.size() ? kFormatLookup[index] : vk::Format::eUndefined;
@@ -119,7 +103,7 @@ vk::Format VulkanFormat(Prospero::BufferFormat guest_format) {
void RequireVulkanSuccess(vk::Result result, const char* operation) { void RequireVulkanSuccess(vk::Result result, const char* operation) {
if (result != vk::Result::eSuccess) { if (result != vk::Result::eSuccess) {
EXIT("%s failed: %s (%d)\n", operation, VulkanToString(result).c_str(), EXIT("%s failed: %s (%d)\n", operation, vk::to_string(result).c_str(),
static_cast<int>(result)); static_cast<int>(result));
} }
} }
-4
View File
@@ -25,10 +25,6 @@ namespace Libs::Graphics {
using VulkanMemoryBarrier = vk::MemoryBarrier; using VulkanMemoryBarrier = vk::MemoryBarrier;
std::string VulkanToString(vk::Result value);
std::string VulkanToString(vk::Format value);
std::string VulkanToString(vk::ImageLayout value);
std::string VulkanToString(vk::QueueFlags value);
vk::Format VulkanFormat(Prospero::BufferFormat guest_format); vk::Format VulkanFormat(Prospero::BufferFormat guest_format);
void RequireVulkanSuccess(vk::Result result, const char* operation); void RequireVulkanSuccess(vk::Result result, const char* operation);
@@ -573,7 +573,7 @@ Swapchain::Status Swapchain::AcquireNextImage() {
case vk::Result::eErrorSurfaceLostKHR: case vk::Result::eErrorSurfaceLostKHR:
LOGF("vkAcquireNextImageKHR returned vk::Result::eErrorSurfaceLostKHR\n"); LOGF("vkAcquireNextImageKHR returned vk::Result::eErrorSurfaceLostKHR\n");
return Status::SurfaceLost; return Status::SurfaceLost;
default: EXIT("vkAcquireNextImageKHR failed: %s\n", VulkanToString(result).c_str()); default: EXIT("vkAcquireNextImageKHR failed: %s\n", vk::to_string(result).c_str());
} }
EXIT_IF(m_image_index >= m_images.size()); EXIT_IF(m_image_index >= m_images.size());
return Status::Success; return Status::Success;
@@ -702,7 +702,7 @@ Swapchain::Status Swapchain::Present() {
case vk::Result::eErrorSurfaceLostKHR: case vk::Result::eErrorSurfaceLostKHR:
LOGF("vkQueuePresentKHR returned vk::Result::eErrorSurfaceLostKHR\n"); LOGF("vkQueuePresentKHR returned vk::Result::eErrorSurfaceLostKHR\n");
return Status::SurfaceLost; return Status::SurfaceLost;
default: EXIT("vkQueuePresentKHR failed: %s\n", VulkanToString(result).c_str()); default: EXIT("vkQueuePresentKHR failed: %s\n", vk::to_string(result).c_str());
} }
m_frame_index = (m_frame_index + 1u) % static_cast<uint32_t>(m_images.size()); m_frame_index = (m_frame_index + 1u) % static_cast<uint32_t>(m_images.size());
return Status::Success; return Status::Success;
@@ -143,7 +143,7 @@ static uint32_t VulkanFindQueueFamily(vk::PhysicalDevice device, vk::SurfaceKHR
"vkGetPhysicalDeviceSurfaceSupportKHR"); "vkGetPhysicalDeviceSurfaceSupportKHR");
LOGF("\tqueue family: %s [count = %u], [present = %s]\n", LOGF("\tqueue family: %s [count = %u], [present = %s]\n",
VulkanToString(properties.queueFlags).c_str(), properties.queueCount, vk::to_string(properties.queueFlags).c_str(), properties.queueCount,
(presentation_supported == VK_TRUE ? "true" : "false")); (presentation_supported == VK_TRUE ? "true" : "false"));
if (properties.queueCount != 0 && (properties.queueFlags & required) == required && if (properties.queueCount != 0 && (properties.queueFlags & required) == required &&
presentation_supported == VK_TRUE) { presentation_supported == VK_TRUE) {
@@ -525,14 +525,12 @@ static void VulkanInitSubgroupSizeControl(vk::PhysicalDevice physical_device,
(graphics.required_subgroup_size_stages & vk::ShaderStageFlagBits::eCompute) && (graphics.required_subgroup_size_stages & vk::ShaderStageFlagBits::eCompute) &&
subgroup_size_control.minSubgroupSize <= 64 && subgroup_size_control.minSubgroupSize <= 64 &&
subgroup_size_control.maxSubgroupSize >= 64; subgroup_size_control.maxSubgroupSize >= 64;
graphics.compute_wave64_supported =
graphics.subgroup_size == 64u || graphics.compute_subgroup_size_control_enabled;
LOGF("Vulkan subgroup: default=%u min=%u max=%u stages=0x%08x size_control=%s wave64=%s\n", LOGF("Vulkan subgroup: default=%u min=%u max=%u stages=0x%08x size_control=%s wave64=%s\n",
graphics.subgroup_size, graphics.min_subgroup_size, graphics.max_subgroup_size, graphics.subgroup_size, graphics.min_subgroup_size, graphics.max_subgroup_size,
static_cast<vk::ShaderStageFlags::MaskType>(graphics.required_subgroup_size_stages), static_cast<vk::ShaderStageFlags::MaskType>(graphics.required_subgroup_size_stages),
graphics.compute_subgroup_size_control_enabled ? "true" : "false", graphics.compute_subgroup_size_control_enabled ? "true" : "false",
graphics.compute_wave64_supported ? "true" : "false"); graphics.SupportsComputeWave64() ? "true" : "false");
} }
static vk::Device VulkanCreateDevice(vk::PhysicalDevice physical_device, const VulkanExtensions& r, static vk::Device VulkanCreateDevice(vk::PhysicalDevice physical_device, const VulkanExtensions& r,
@@ -724,7 +722,7 @@ static vk::Device VulkanCreateDevice(vk::PhysicalDevice physical_device, const V
auto result = physical_device.createDevice(&create_info, nullptr, &device); auto result = physical_device.createDevice(&create_info, nullptr, &device);
if (result != vk::Result::eSuccess) { if (result != vk::Result::eSuccess) {
LOGF("vkCreateDevice failed: %s\n", VulkanToString(result).c_str()); LOGF("vkCreateDevice failed: %s\n", vk::to_string(result).c_str());
return nullptr; return nullptr;
} }
@@ -903,7 +901,7 @@ static void VulkanCheckInstanceVersion() {
if (VULKAN_HPP_DEFAULT_DISPATCHER.vkEnumerateInstanceVersion != nullptr) { if (VULKAN_HPP_DEFAULT_DISPATCHER.vkEnumerateInstanceVersion != nullptr) {
auto result = vk::enumerateInstanceVersion(&version); auto result = vk::enumerateInstanceVersion(&version);
if (result != vk::Result::eSuccess) { if (result != vk::Result::eSuccess) {
EXIT("Could not query Vulkan loader version: %s\n", VulkanToString(result).c_str()); EXIT("Could not query Vulkan loader version: %s\n", vk::to_string(result).c_str());
} }
} }
+1 -1
View File
@@ -892,7 +892,7 @@ std::string Hex(u32 value) {
} }
std::string VulkanResultName(vk::Result result) { std::string VulkanResultName(vk::Result result) {
return VulkanToString(result); return vk::to_string(result);
} }
[[noreturn]] void Fail(const char *shader_name, const char *stage, [[noreturn]] void Fail(const char *shader_name, const char *stage,