Browse Source

[vk] Proof of Concept: Enable/Use GPL

pull/2725/head
Ribbit 5 months ago
committed by crueter
parent
commit
4deaf21e3c
  1. 397
      src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
  2. 1
      src/video_core/renderer_vulkan/vk_graphics_pipeline.h
  3. 103
      src/video_core/vulkan_common/vulkan_device.cpp
  4. 22
      src/video_core/vulkan_common/vulkan_device.h

397
src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp

@ -6,7 +6,9 @@
#include <algorithm>
#include <iostream>
#include <optional>
#include <span>
#include <utility>
#include <boost/container/small_vector.hpp>
#include <boost/container/static_vector.hpp>
@ -805,98 +807,377 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
.pAttachments = cb_attachments.data(),
.blendConstants = {}
};
static_vector<VkDynamicState, 34> dynamic_states{
VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR,
VK_DYNAMIC_STATE_DEPTH_BIAS, VK_DYNAMIC_STATE_BLEND_CONSTANTS,
VK_DYNAMIC_STATE_DEPTH_BOUNDS, VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK,
VK_DYNAMIC_STATE_STENCIL_WRITE_MASK, VK_DYNAMIC_STATE_STENCIL_REFERENCE,
VK_DYNAMIC_STATE_LINE_WIDTH,
enum class DynamicStateSubset : u8 {
VertexInput,
PreRaster,
FragmentOutput,
};
static_vector<VkDynamicState, 34> dynamic_states;
static_vector<VkDynamicState, 8> vertex_input_dynamic_states;
static_vector<VkDynamicState, 24> pre_raster_dynamic_states;
static_vector<VkDynamicState, 24> fragment_output_dynamic_states;
const auto add_dynamic_state = [&](VkDynamicState state, DynamicStateSubset subset) {
dynamic_states.push_back(state);
switch (subset) {
case DynamicStateSubset::VertexInput:
vertex_input_dynamic_states.push_back(state);
break;
case DynamicStateSubset::PreRaster:
pre_raster_dynamic_states.push_back(state);
break;
case DynamicStateSubset::FragmentOutput:
fragment_output_dynamic_states.push_back(state);
break;
}
};
add_dynamic_state(VK_DYNAMIC_STATE_VIEWPORT, DynamicStateSubset::PreRaster);
add_dynamic_state(VK_DYNAMIC_STATE_SCISSOR, DynamicStateSubset::PreRaster);
add_dynamic_state(VK_DYNAMIC_STATE_DEPTH_BIAS, DynamicStateSubset::PreRaster);
add_dynamic_state(VK_DYNAMIC_STATE_BLEND_CONSTANTS, DynamicStateSubset::FragmentOutput);
add_dynamic_state(VK_DYNAMIC_STATE_DEPTH_BOUNDS, DynamicStateSubset::FragmentOutput);
add_dynamic_state(VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK, DynamicStateSubset::FragmentOutput);
add_dynamic_state(VK_DYNAMIC_STATE_STENCIL_WRITE_MASK, DynamicStateSubset::FragmentOutput);
add_dynamic_state(VK_DYNAMIC_STATE_STENCIL_REFERENCE, DynamicStateSubset::FragmentOutput);
add_dynamic_state(VK_DYNAMIC_STATE_LINE_WIDTH, DynamicStateSubset::PreRaster);
if (key.state.extended_dynamic_state) {
static constexpr std::array extended{
VK_DYNAMIC_STATE_CULL_MODE_EXT,
VK_DYNAMIC_STATE_FRONT_FACE_EXT,
//VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT, //Disabled for VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME
VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT,
VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT,
VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT,
VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE_EXT,
VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT,
VK_DYNAMIC_STATE_STENCIL_OP_EXT,
std::pair{VK_DYNAMIC_STATE_CULL_MODE_EXT, DynamicStateSubset::PreRaster},
std::pair{VK_DYNAMIC_STATE_FRONT_FACE_EXT, DynamicStateSubset::PreRaster},
std::pair{VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT, DynamicStateSubset::FragmentOutput},
std::pair{VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT, DynamicStateSubset::FragmentOutput},
std::pair{VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT, DynamicStateSubset::FragmentOutput},
std::pair{VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE_EXT,
DynamicStateSubset::FragmentOutput},
std::pair{VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT, DynamicStateSubset::FragmentOutput},
std::pair{VK_DYNAMIC_STATE_STENCIL_OP_EXT, DynamicStateSubset::FragmentOutput},
};
if (key.state.dynamic_vertex_input) {
dynamic_states.push_back(VK_DYNAMIC_STATE_VERTEX_INPUT_EXT);
add_dynamic_state(VK_DYNAMIC_STATE_VERTEX_INPUT_EXT, DynamicStateSubset::VertexInput);
}
for (const auto& [state, subset] : extended) {
add_dynamic_state(state, subset);
}
dynamic_states.insert(dynamic_states.end(), extended.begin(), extended.end());
if (key.state.extended_dynamic_state_2) {
static constexpr std::array extended2{
VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE_EXT,
VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE_EXT,
VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE_EXT,
std::pair{VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE_EXT, DynamicStateSubset::PreRaster},
std::pair{VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE_EXT,
DynamicStateSubset::VertexInput},
std::pair{VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE_EXT,
DynamicStateSubset::PreRaster},
};
dynamic_states.insert(dynamic_states.end(), extended2.begin(), extended2.end());
for (const auto& [state, subset] : extended2) {
add_dynamic_state(state, subset);
}
}
if (key.state.extended_dynamic_state_2_extra) {
dynamic_states.push_back(VK_DYNAMIC_STATE_LOGIC_OP_EXT);
add_dynamic_state(VK_DYNAMIC_STATE_LOGIC_OP_EXT, DynamicStateSubset::FragmentOutput);
}
if (key.state.extended_dynamic_state_3_blend) {
static constexpr std::array extended3{
VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT,
VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT,
VK_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT,
// VK_DYNAMIC_STATE_COLOR_BLEND_ADVANCED_EXT,
std::pair{VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT,
DynamicStateSubset::FragmentOutput},
std::pair{VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT,
DynamicStateSubset::FragmentOutput},
std::pair{VK_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT,
DynamicStateSubset::FragmentOutput},
};
dynamic_states.insert(dynamic_states.end(), extended3.begin(), extended3.end());
for (const auto& [state, subset] : extended3) {
add_dynamic_state(state, subset);
}
}
if (key.state.extended_dynamic_state_3_enables) {
static constexpr std::array extended3{
VK_DYNAMIC_STATE_DEPTH_CLAMP_ENABLE_EXT,
VK_DYNAMIC_STATE_LOGIC_OP_ENABLE_EXT,
// additional state3 extensions
VK_DYNAMIC_STATE_LINE_RASTERIZATION_MODE_EXT,
VK_DYNAMIC_STATE_CONSERVATIVE_RASTERIZATION_MODE_EXT,
VK_DYNAMIC_STATE_LINE_STIPPLE_ENABLE_EXT,
VK_DYNAMIC_STATE_ALPHA_TO_COVERAGE_ENABLE_EXT,
VK_DYNAMIC_STATE_ALPHA_TO_ONE_ENABLE_EXT,
VK_DYNAMIC_STATE_DEPTH_CLIP_ENABLE_EXT,
VK_DYNAMIC_STATE_PROVOKING_VERTEX_MODE_EXT,
std::pair{VK_DYNAMIC_STATE_DEPTH_CLAMP_ENABLE_EXT, DynamicStateSubset::PreRaster},
std::pair{VK_DYNAMIC_STATE_LOGIC_OP_ENABLE_EXT,
DynamicStateSubset::FragmentOutput},
std::pair{VK_DYNAMIC_STATE_LINE_RASTERIZATION_MODE_EXT,
DynamicStateSubset::PreRaster},
std::pair{VK_DYNAMIC_STATE_CONSERVATIVE_RASTERIZATION_MODE_EXT,
DynamicStateSubset::PreRaster},
std::pair{VK_DYNAMIC_STATE_LINE_STIPPLE_ENABLE_EXT,
DynamicStateSubset::PreRaster},
std::pair{VK_DYNAMIC_STATE_ALPHA_TO_COVERAGE_ENABLE_EXT,
DynamicStateSubset::FragmentOutput},
std::pair{VK_DYNAMIC_STATE_ALPHA_TO_ONE_ENABLE_EXT,
DynamicStateSubset::FragmentOutput},
std::pair{VK_DYNAMIC_STATE_DEPTH_CLIP_ENABLE_EXT, DynamicStateSubset::PreRaster},
std::pair{VK_DYNAMIC_STATE_PROVOKING_VERTEX_MODE_EXT,
DynamicStateSubset::PreRaster},
};
dynamic_states.insert(dynamic_states.end(), extended3.begin(), extended3.end());
for (const auto& [state, subset] : extended3) {
add_dynamic_state(state, subset);
}
}
}
const VkPipelineDynamicStateCreateInfo dynamic_state_ci{
.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.dynamicStateCount = static_cast<u32>(dynamic_states.size()),
.pDynamicStates = dynamic_states.data(),
const auto make_dynamic_ci = [](const auto& states) -> VkPipelineDynamicStateCreateInfo {
return VkPipelineDynamicStateCreateInfo{
.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.dynamicStateCount = static_cast<u32>(states.size()),
.pDynamicStates = states.empty() ? nullptr : states.data(),
};
};
const VkPipelineDynamicStateCreateInfo dynamic_state_ci = make_dynamic_ci(dynamic_states);
[[maybe_unused]] const VkPipelineDynamicStateCreateInfo vertex_input_dynamic_state_ci =
make_dynamic_ci(vertex_input_dynamic_states);
[[maybe_unused]] const VkPipelineDynamicStateCreateInfo pre_raster_dynamic_state_ci =
make_dynamic_ci(pre_raster_dynamic_states);
[[maybe_unused]] const VkPipelineDynamicStateCreateInfo fragment_output_dynamic_state_ci =
make_dynamic_ci(fragment_output_dynamic_states);
[[maybe_unused]] const VkPipelineDynamicStateCreateInfo* vertex_input_dynamic_state_ci_ptr =
vertex_input_dynamic_states.empty() ? nullptr : &vertex_input_dynamic_state_ci;
[[maybe_unused]] const VkPipelineDynamicStateCreateInfo* pre_raster_dynamic_state_ci_ptr =
pre_raster_dynamic_states.empty() ? nullptr : &pre_raster_dynamic_state_ci;
[[maybe_unused]] const VkPipelineDynamicStateCreateInfo* fragment_output_dynamic_state_ci_ptr =
fragment_output_dynamic_states.empty() ? nullptr : &fragment_output_dynamic_state_ci;
[[maybe_unused]] const VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT subgroup_size_ci{
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT,
.pNext = nullptr,
.requiredSubgroupSize = GuestWarpSize,
};
static_vector<VkPipelineShaderStageCreateInfo, 5> shader_stages;
[[maybe_unused]] static_vector<VkPipelineShaderStageCreateInfo, 4> preraster_shader_stages;
[[maybe_unused]] std::optional<VkPipelineShaderStageCreateInfo> fragment_shader_stage;
for (size_t stage = 0; stage < Maxwell::MaxShaderStage; ++stage) {
if (!spv_modules[stage]) {
continue;
}
[[maybe_unused]] auto& stage_ci =
shader_stages.emplace_back(VkPipelineShaderStageCreateInfo{
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.stage = MaxwellToVK::ShaderStage(Shader::StageFromIndex(stage)),
.module = *spv_modules[stage],
.pName = "main",
.pSpecializationInfo = nullptr,
});
VkPipelineShaderStageCreateInfo stage_ci{
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.stage = MaxwellToVK::ShaderStage(Shader::StageFromIndex(stage)),
.module = *spv_modules[stage],
.pName = "main",
.pSpecializationInfo = nullptr,
};
shader_stages.push_back(stage_ci);
if (stage_ci.stage == VK_SHADER_STAGE_FRAGMENT_BIT) {
fragment_shader_stage = stage_ci;
} else {
preraster_shader_stages.push_back(stage_ci);
}
}
#if defined(VK_EXT_GRAPHICS_PIPELINE_LIBRARY_EXTENSION_NAME) && defined(VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME)
if (device.UseGraphicsPipelineLibrary()) {
for (auto& library : pipeline_libraries) {
library.reset();
}
const bool capture_stats =
device.IsKhrPipelineExecutablePropertiesEnabled() &&
Settings::values.renderer_debug.GetValue();
const auto build_with_gpl = [&]() -> bool {
try {
VkPipelineCreateFlags library_flags = VK_PIPELINE_CREATE_LIBRARY_BIT_KHR;
if (capture_stats) {
library_flags |= VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR;
}
#if defined(VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT)
if (device.ShouldRetainLinkTimeOptimizationInfo()) {
library_flags |=
VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT;
}
#endif
const VkGraphicsPipelineLibraryCreateInfoEXT vertex_input_library_info{
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_LIBRARY_CREATE_INFO_EXT,
.pNext = nullptr,
.flags = VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT,
};
VkGraphicsPipelineCreateInfo vertex_input_library_ci{
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.pNext = &vertex_input_library_info,
.flags = library_flags,
.stageCount = 0,
.pStages = nullptr,
.pVertexInputState = &vertex_input_ci,
.pInputAssemblyState = &input_assembly_ci,
.pTessellationState = nullptr,
.pViewportState = nullptr,
.pRasterizationState = nullptr,
.pMultisampleState = nullptr,
.pDepthStencilState = nullptr,
.pColorBlendState = nullptr,
.pDynamicState = vertex_input_dynamic_state_ci_ptr,
.layout = VK_NULL_HANDLE,
.renderPass = VK_NULL_HANDLE,
.subpass = 0,
.basePipelineHandle = nullptr,
.basePipelineIndex = 0,
};
pipeline_libraries[0] = device.GetLogical().CreateGraphicsPipeline(
vertex_input_library_ci, *pipeline_cache);
const VkGraphicsPipelineLibraryCreateInfoEXT pre_raster_library_info{
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_LIBRARY_CREATE_INFO_EXT,
.pNext = nullptr,
.flags = VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT,
};
VkGraphicsPipelineCreateInfo pre_raster_library_ci{
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.pNext = &pre_raster_library_info,
.flags = library_flags,
.stageCount = static_cast<u32>(preraster_shader_stages.size()),
.pStages = preraster_shader_stages.empty() ? nullptr
: preraster_shader_stages.data(),
.pVertexInputState = nullptr,
.pInputAssemblyState = nullptr,
.pTessellationState = &tessellation_ci,
.pViewportState = &viewport_ci,
.pRasterizationState = &rasterization_ci,
.pMultisampleState = nullptr,
.pDepthStencilState = nullptr,
.pColorBlendState = nullptr,
.pDynamicState = pre_raster_dynamic_state_ci_ptr,
.layout = *pipeline_layout,
.renderPass = render_pass,
.subpass = 0,
.basePipelineHandle = nullptr,
.basePipelineIndex = 0,
};
pipeline_libraries[1] = device.GetLogical().CreateGraphicsPipeline(
pre_raster_library_ci, *pipeline_cache);
pipeline_libraries[2].reset();
if (fragment_shader_stage) {
const VkGraphicsPipelineLibraryCreateInfoEXT fragment_shader_library_info{
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_LIBRARY_CREATE_INFO_EXT,
.pNext = nullptr,
.flags = VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT,
};
VkPipelineShaderStageCreateInfo fragment_stage_ci = *fragment_shader_stage;
VkGraphicsPipelineCreateInfo fragment_shader_library_ci{
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.pNext = &fragment_shader_library_info,
.flags = library_flags,
.stageCount = 1,
.pStages = &fragment_stage_ci,
.pVertexInputState = nullptr,
.pInputAssemblyState = nullptr,
.pTessellationState = nullptr,
.pViewportState = nullptr,
.pRasterizationState = nullptr,
.pMultisampleState = nullptr,
.pDepthStencilState = nullptr,
.pColorBlendState = nullptr,
.pDynamicState = nullptr,
.layout = *pipeline_layout,
.renderPass = render_pass,
.subpass = 0,
.basePipelineHandle = nullptr,
.basePipelineIndex = 0,
};
pipeline_libraries[2] = device.GetLogical().CreateGraphicsPipeline(
fragment_shader_library_ci, *pipeline_cache);
}
const VkGraphicsPipelineLibraryCreateInfoEXT fragment_output_library_info{
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_LIBRARY_CREATE_INFO_EXT,
.pNext = nullptr,
.flags = VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT,
};
VkGraphicsPipelineCreateInfo fragment_output_library_ci{
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.pNext = &fragment_output_library_info,
.flags = library_flags,
.stageCount = 0,
.pStages = nullptr,
.pVertexInputState = nullptr,
.pInputAssemblyState = nullptr,
.pTessellationState = nullptr,
.pViewportState = nullptr,
.pRasterizationState = nullptr,
.pMultisampleState = &multisample_ci,
.pDepthStencilState = &depth_stencil_ci,
.pColorBlendState = &color_blend_ci,
.pDynamicState = fragment_output_dynamic_state_ci_ptr,
.layout = VK_NULL_HANDLE,
.renderPass = render_pass,
.subpass = 0,
.basePipelineHandle = nullptr,
.basePipelineIndex = 0,
};
pipeline_libraries[3] = device.GetLogical().CreateGraphicsPipeline(
fragment_output_library_ci, *pipeline_cache);
std::array<VkPipeline, 4> linked_libraries{};
u32 linked_count = 0;
for (const auto& library : pipeline_libraries) {
if (library) {
linked_libraries[linked_count++] = *library;
}
}
if (linked_count == 0) {
return false;
}
VkPipelineLibraryCreateInfoKHR link_info{
.sType = VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR,
.pNext = nullptr,
.libraryCount = linked_count,
.pLibraries = linked_libraries.data(),
};
VkGraphicsPipelineLibraryCreateInfoEXT executable_library_info{
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_LIBRARY_CREATE_INFO_EXT,
.pNext = &link_info,
.flags = 0,
};
VkPipelineCreateFlags executable_flags = capture_stats
? VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR
: 0;
#if defined(VK_PIPELINE_CREATE_LINK_TIME_OPTIMIZATION_BIT_EXT)
if (device.ShouldEnableLinkTimeOptimization()) {
executable_flags |= VK_PIPELINE_CREATE_LINK_TIME_OPTIMIZATION_BIT_EXT;
}
#endif
VkGraphicsPipelineCreateInfo executable_ci{
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.pNext = &executable_library_info,
.flags = executable_flags,
.stageCount = 0,
.pStages = nullptr,
.pVertexInputState = nullptr,
.pInputAssemblyState = nullptr,
.pTessellationState = nullptr,
.pViewportState = nullptr,
.pRasterizationState = nullptr,
.pMultisampleState = nullptr,
.pDepthStencilState = nullptr,
.pColorBlendState = nullptr,
.pDynamicState = nullptr,
.layout = *pipeline_layout,
.renderPass = render_pass,
.subpass = 0,
.basePipelineHandle = nullptr,
.basePipelineIndex = 0,
};
pipeline = device.GetLogical().CreateGraphicsPipeline(executable_ci, *pipeline_cache);
return true;
} catch (const vk::Exception& exception) {
LOG_WARNING(Render_Vulkan,
"VK_EXT_graphics_pipeline_library pipeline creation failed: {}",
exception.what());
for (auto& library : pipeline_libraries) {
library.reset();
}
device.DisableGraphicsPipelineLibrary(exception.what());
return false;
}
};
if (build_with_gpl()) {
return;
}
}
#endif
VkPipelineCreateFlags flags{};
if (device.IsKhrPipelineExecutablePropertiesEnabled() && Settings::values.renderer_debug.GetValue()) {
flags |= VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR;

1
src/video_core/renderer_vulkan/vk_graphics_pipeline.h

@ -154,6 +154,7 @@ private:
DescriptorAllocator descriptor_allocator;
vk::PipelineLayout pipeline_layout;
vk::DescriptorUpdateTemplate descriptor_update_template;
std::array<vk::Pipeline, 4> pipeline_libraries{};
vk::Pipeline pipeline;
std::condition_variable build_condvar;

103
src/video_core/vulkan_common/vulkan_device.cpp

@ -974,6 +974,8 @@ bool Device::HasTimelineSemaphore() const {
bool Device::GetSuitability(bool requires_swapchain) {
// Assume we will be suitable.
bool suitable = true;
use_graphics_pipeline_library = false;
graphics_pipeline_library_disable_reason.clear();
// Configure properties.
VkPhysicalDeviceVulkan12Features features_1_2{};
@ -1024,6 +1026,19 @@ bool Device::GetSuitability(bool requires_swapchain) {
#undef FEATURE_EXTENSION
#undef EXTENSION
#if defined(VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME)
if (supported_extensions.contains(VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME)) {
loaded_extensions.insert(VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME);
extensions.pipeline_library = true;
}
#endif
#if defined(VK_EXT_GRAPHICS_PIPELINE_LIBRARY_EXTENSION_NAME)
if (supported_extensions.contains(VK_EXT_GRAPHICS_PIPELINE_LIBRARY_EXTENSION_NAME)) {
loaded_extensions.insert(VK_EXT_GRAPHICS_PIPELINE_LIBRARY_EXTENSION_NAME);
extensions.graphics_pipeline_library = true;
}
#endif
// Some extensions are mandatory. Check those.
#define CHECK_EXTENSION(extension_name) \
if (!loaded_extensions.contains(extension_name)) { \
@ -1089,6 +1104,14 @@ bool Device::GetSuitability(bool requires_swapchain) {
FOR_EACH_VK_FEATURE_1_3(EXT_FEATURE);
}
#if (defined(VK_EXT_graphics_pipeline_library) || defined(VK_EXT_GRAPHICS_PIPELINE_LIBRARY_EXTENSION_NAME)) && defined(VK_EXT_GRAPHICS_PIPELINE_LIBRARY_EXTENSION_NAME)
if (extensions.graphics_pipeline_library) {
features.graphics_pipeline_library.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GRAPHICS_PIPELINE_LIBRARY_FEATURES_EXT;
SetNext(next, features.graphics_pipeline_library);
}
#endif
#undef EXT_FEATURE
#undef FEATURE
@ -1158,6 +1181,13 @@ bool Device::GetSuitability(bool requires_swapchain) {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT;
SetNext(next, properties.transform_feedback);
}
#if (defined(VK_EXT_graphics_pipeline_library) || defined(VK_EXT_GRAPHICS_PIPELINE_LIBRARY_EXTENSION_NAME)) && defined(VK_EXT_GRAPHICS_PIPELINE_LIBRARY_EXTENSION_NAME)
if (extensions.graphics_pipeline_library) {
properties.graphics_pipeline_library.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GRAPHICS_PIPELINE_LIBRARY_PROPERTIES_EXT;
SetNext(next, properties.graphics_pipeline_library);
}
#endif
// Perform the property fetch.
physical.GetProperties2(properties2);
@ -1168,6 +1198,31 @@ bool Device::GetSuitability(bool requires_swapchain) {
// Unload extensions if feature support is insufficient.
RemoveUnsuitableExtensions();
#if (defined(VK_EXT_graphics_pipeline_library) || defined(VK_EXT_GRAPHICS_PIPELINE_LIBRARY_EXTENSION_NAME)) && defined(VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME)
const bool gpl_extensions_supported =
extensions.pipeline_library && extensions.graphics_pipeline_library;
const bool gpl_feature_supported =
extensions.graphics_pipeline_library &&
features.graphics_pipeline_library.graphicsPipelineLibrary == VK_TRUE;
const bool gpl_supported = gpl_extensions_supported && gpl_feature_supported;
const bool gpl_enabled = gpl_supported;
if (!gpl_supported) {
graphics_pipeline_library_disable_reason = gpl_extensions_supported
? "VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT not reported"
: "Required pipeline library extensions missing";
} else {
graphics_pipeline_library_disable_reason.clear();
LOG_INFO(Render_Vulkan, "VK_EXT_graphics_pipeline_library enabled by default");
}
use_graphics_pipeline_library = gpl_enabled;
if (!use_graphics_pipeline_library && !graphics_pipeline_library_disable_reason.empty()) {
LOG_DEBUG(Render_Vulkan, "VK_EXT_graphics_pipeline_library disabled: {}",
graphics_pipeline_library_disable_reason);
}
#endif
// Check limits.
struct Limit {
u32 minimum;
@ -1194,6 +1249,46 @@ bool Device::GetSuitability(bool requires_swapchain) {
return suitable;
}
#if (defined(VK_EXT_graphics_pipeline_library) || defined(VK_EXT_GRAPHICS_PIPELINE_LIBRARY_EXTENSION_NAME)) && defined(VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME)
bool Device::UseGraphicsPipelineLibrary() const noexcept {
return use_graphics_pipeline_library;
}
bool Device::ShouldRetainLinkTimeOptimizationInfo() const noexcept {
return use_graphics_pipeline_library &&
properties.graphics_pipeline_library.graphicsPipelineLibraryFastLinking == VK_TRUE;
}
bool Device::ShouldEnableLinkTimeOptimization() const noexcept {
return use_graphics_pipeline_library &&
properties.graphics_pipeline_library.graphicsPipelineLibraryFastLinking == VK_TRUE;
}
void Device::DisableGraphicsPipelineLibrary(std::string_view reason) const noexcept {
if (!use_graphics_pipeline_library) {
return;
}
use_graphics_pipeline_library = false;
graphics_pipeline_library_disable_reason.assign(reason.begin(), reason.end());
LOG_WARNING(Render_Vulkan,
"Disabling VK_EXT_graphics_pipeline_library for this session: {}", reason);
}
#else
bool Device::UseGraphicsPipelineLibrary() const noexcept {
return false;
}
bool Device::ShouldRetainLinkTimeOptimizationInfo() const noexcept {
return false;
}
bool Device::ShouldEnableLinkTimeOptimization() const noexcept {
return false;
}
void Device::DisableGraphicsPipelineLibrary(std::string_view) const noexcept {}
#endif
void Device::RemoveUnsuitableExtensions() {
// VK_EXT_custom_border_color
extensions.custom_border_color = features.custom_border_color.customBorderColors &&
@ -1318,6 +1413,14 @@ void Device::RemoveUnsuitableExtensions() {
RemoveExtensionFeatureIfUnsuitable(extensions.workgroup_memory_explicit_layout,
features.workgroup_memory_explicit_layout,
VK_KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_EXTENSION_NAME);
#if (defined(VK_EXT_graphics_pipeline_library) || defined(VK_EXT_GRAPHICS_PIPELINE_LIBRARY_EXTENSION_NAME)) && defined(VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME)
if (!(extensions.pipeline_library && extensions.graphics_pipeline_library &&
features.graphics_pipeline_library.graphicsPipelineLibrary)) {
RemoveExtensionFeature(extensions.graphics_pipeline_library,
features.graphics_pipeline_library,
VK_EXT_GRAPHICS_PIPELINE_LIBRARY_EXTENSION_NAME);
}
#endif
}
void Device::SetupFamilies(VkSurfaceKHR surface) {

22
src/video_core/vulkan_common/vulkan_device.h

@ -9,6 +9,7 @@
#include <set>
#include <span>
#include <string>
#include <string_view>
#include <unordered_map>
#include <vector>
@ -435,6 +436,11 @@ public:
return extensions.pipeline_executable_properties;
}
bool UseGraphicsPipelineLibrary() const noexcept;
bool ShouldRetainLinkTimeOptimizationInfo() const noexcept;
bool ShouldEnableLinkTimeOptimization() const noexcept;
void DisableGraphicsPipelineLibrary(std::string_view reason) const noexcept;
/// Returns true if VK_KHR_swapchain_mutable_format is enabled.
bool IsKhrSwapchainMutableFormatEnabled() const {
return extensions.swapchain_mutable_format;
@ -789,6 +795,13 @@ private:
FOR_EACH_VK_FEATURE_EXT(FEATURE);
FOR_EACH_VK_EXTENSION(EXTENSION);
#if defined(VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME)
bool pipeline_library{};
#endif
#if defined(VK_EXT_GRAPHICS_PIPELINE_LIBRARY_EXTENSION_NAME)
bool graphics_pipeline_library{};
#endif
#undef EXTENSION
#undef FEATURE
};
@ -804,6 +817,10 @@ private:
FOR_EACH_VK_FEATURE_1_3(FEATURE_CORE);
FOR_EACH_VK_FEATURE_EXT(FEATURE_EXT);
#if defined(VK_EXT_graphics_pipeline_library) || defined(VK_EXT_GRAPHICS_PIPELINE_LIBRARY_EXTENSION_NAME)
VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT graphics_pipeline_library{};
#endif
#undef FEATURE_CORE
#undef FEATURE_EXT
@ -817,6 +834,9 @@ private:
VkPhysicalDevicePushDescriptorPropertiesKHR push_descriptor{};
VkPhysicalDeviceSubgroupSizeControlProperties subgroup_size_control{};
VkPhysicalDeviceTransformFeedbackPropertiesEXT transform_feedback{};
#if defined(VK_EXT_graphics_pipeline_library) || defined(VK_EXT_GRAPHICS_PIPELINE_LIBRARY_EXTENSION_NAME)
VkPhysicalDeviceGraphicsPipelineLibraryPropertiesEXT graphics_pipeline_library{};
#endif
VkPhysicalDeviceProperties properties{};
};
@ -849,6 +869,8 @@ private:
bool dynamic_state3_blending{}; ///< Has all blending features of dynamic_state3.
bool dynamic_state3_enables{}; ///< Has all enables features of dynamic_state3.
bool supports_conditional_barriers{}; ///< Allows barriers in conditional control flow.
mutable bool use_graphics_pipeline_library{}; ///< Runtime flag for VK_EXT_graphics_pipeline_library usage
mutable std::string graphics_pipeline_library_disable_reason;
u64 device_access_memory{}; ///< Total size of device local memory in bytes.
u32 sets_per_pool{}; ///< Sets per Description Pool
NvidiaArchitecture nvidia_arch{NvidiaArchitecture::Arch_AmpereOrNewer};

Loading…
Cancel
Save