mirror of
https://github.com/izzy2lost/xenia-edge.git
synced 2026-07-06 00:20:26 -07:00
[Vulkan] wave64 optimization for AMD RDNA gpus (5000/6000/7000 series)
This commit is contained in:
@@ -480,12 +480,15 @@ bool VulkanRenderTargetCache::Initialize(uint32_t shared_memory_binding_count) {
|
||||
resolve_copy_shader_code.unscaled_size_bytes &&
|
||||
resolve_copy_shader_code.scaled &&
|
||||
resolve_copy_shader_code.scaled_size_bytes);
|
||||
// Resolve copy shaders use 8x8 = 64 threads per group. Request wave64 mode
|
||||
// on RDNA GPUs to ensure one full wave per group.
|
||||
VkPipeline resolve_copy_pipeline = ui::vulkan::util::CreateComputePipeline(
|
||||
vulkan_device, resolve_copy_pipeline_layout_,
|
||||
draw_resolution_scaled ? resolve_copy_shader_code.scaled
|
||||
: resolve_copy_shader_code.unscaled,
|
||||
draw_resolution_scaled ? resolve_copy_shader_code.scaled_size_bytes
|
||||
: resolve_copy_shader_code.unscaled_size_bytes);
|
||||
: resolve_copy_shader_code.unscaled_size_bytes,
|
||||
nullptr, "main", 64);
|
||||
if (resolve_copy_pipeline == VK_NULL_HANDLE) {
|
||||
XELOGE(
|
||||
"VulkanRenderTargetCache: Failed to create the resolve copy "
|
||||
@@ -551,10 +554,13 @@ bool VulkanRenderTargetCache::Initialize(uint32_t shared_memory_binding_count) {
|
||||
for (size_t i = 0; i < xe::countof(host_depth_store_shaders); ++i) {
|
||||
const std::pair<const uint32_t*, size_t> host_depth_store_shader =
|
||||
host_depth_store_shaders[i];
|
||||
// Host depth store shaders use 8x8 = 64 threads per group. Request wave64
|
||||
// mode on RDNA GPUs to ensure one full wave per group.
|
||||
VkPipeline host_depth_store_pipeline =
|
||||
ui::vulkan::util::CreateComputePipeline(
|
||||
vulkan_device, host_depth_store_pipeline_layout_,
|
||||
host_depth_store_shader.first, host_depth_store_shader.second);
|
||||
host_depth_store_shader.first, host_depth_store_shader.second,
|
||||
nullptr, "main", 64);
|
||||
if (host_depth_store_pipeline == VK_NULL_HANDLE) {
|
||||
XELOGE(
|
||||
"VulkanRenderTargetCache: Failed to create the {}-sample host "
|
||||
@@ -740,12 +746,15 @@ bool VulkanRenderTargetCache::Initialize(uint32_t shared_memory_binding_count) {
|
||||
Shutdown();
|
||||
return false;
|
||||
}
|
||||
// Resolve clear shaders use 8x8 = 64 threads per group. Request wave64
|
||||
// mode on RDNA GPUs to ensure one full wave per group.
|
||||
resolve_fsi_clear_32bpp_pipeline_ = ui::vulkan::util::CreateComputePipeline(
|
||||
vulkan_device, resolve_fsi_clear_pipeline_layout_,
|
||||
draw_resolution_scaled ? shaders::resolve_clear_32bpp_scaled_cs
|
||||
: shaders::resolve_clear_32bpp_cs,
|
||||
draw_resolution_scaled ? sizeof(shaders::resolve_clear_32bpp_scaled_cs)
|
||||
: sizeof(shaders::resolve_clear_32bpp_cs));
|
||||
: sizeof(shaders::resolve_clear_32bpp_cs),
|
||||
nullptr, "main", 64);
|
||||
if (resolve_fsi_clear_32bpp_pipeline_ == VK_NULL_HANDLE) {
|
||||
XELOGE(
|
||||
"VulkanRenderTargetCache: Failed to create the 32bpp resolve EDRAM "
|
||||
@@ -758,7 +767,8 @@ bool VulkanRenderTargetCache::Initialize(uint32_t shared_memory_binding_count) {
|
||||
draw_resolution_scaled ? shaders::resolve_clear_64bpp_scaled_cs
|
||||
: shaders::resolve_clear_64bpp_cs,
|
||||
draw_resolution_scaled ? sizeof(shaders::resolve_clear_64bpp_scaled_cs)
|
||||
: sizeof(shaders::resolve_clear_64bpp_cs));
|
||||
: sizeof(shaders::resolve_clear_64bpp_cs),
|
||||
nullptr, "main", 64);
|
||||
if (resolve_fsi_clear_64bpp_pipeline_ == VK_NULL_HANDLE) {
|
||||
XELOGE(
|
||||
"VulkanRenderTargetCache: Failed to create the 64bpp resolve EDRAM "
|
||||
|
||||
@@ -168,6 +168,7 @@ std::unique_ptr<VulkanDevice> VulkanDevice::CreateIfSupported(
|
||||
bool ext_1_3_EXT_shader_demote_to_helper_invocation = false;
|
||||
bool ext_1_3_KHR_dynamic_rendering = false;
|
||||
bool ext_EXT_non_seamless_cube_map = false;
|
||||
bool ext_1_3_EXT_subgroup_size_control = false;
|
||||
if (with_gpu_emulation) {
|
||||
// #15.
|
||||
XE_UI_VULKAN_LOCAL_PROMOTED_EXTENSION(KHR_sampler_mirror_clamp_to_edge, 1,
|
||||
@@ -192,6 +193,8 @@ std::unique_ptr<VulkanDevice> VulkanDevice::CreateIfSupported(
|
||||
EXT_shader_demote_to_helper_invocation, 1, 3)
|
||||
// #423.
|
||||
XE_UI_VULKAN_LOCAL_EXTENSION(EXT_non_seamless_cube_map)
|
||||
// #226.
|
||||
XE_UI_VULKAN_LOCAL_PROMOTED_EXTENSION(EXT_subgroup_size_control, 1, 3)
|
||||
}
|
||||
if (properties.apiVersion >= VK_MAKE_API_VERSION(0, 1, 1, 0)) {
|
||||
// #237.
|
||||
@@ -299,6 +302,17 @@ std::unique_ptr<VulkanDevice> VulkanDevice::CreateIfSupported(
|
||||
VulkanFeatures<VkPhysicalDeviceDynamicRenderingFeatures,
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES>
|
||||
features_1_3_KHR_dynamic_rendering;
|
||||
// Vulkan 1.1 core subgroup properties.
|
||||
VkPhysicalDeviceSubgroupProperties properties_subgroup = {
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES};
|
||||
// VK_EXT_subgroup_size_control (#226, promoted to 1.3).
|
||||
VkPhysicalDeviceSubgroupSizeControlProperties
|
||||
properties_1_3_EXT_subgroup_size_control = {
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES};
|
||||
VulkanFeatures<
|
||||
VkPhysicalDeviceSubgroupSizeControlFeatures,
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES>
|
||||
features_1_3_EXT_subgroup_size_control;
|
||||
|
||||
if (get_physical_device_properties2_supported) {
|
||||
if (properties.apiVersion >= VK_MAKE_API_VERSION(0, 1, 2, 0)) {
|
||||
@@ -336,6 +350,18 @@ std::unique_ptr<VulkanDevice> VulkanDevice::CreateIfSupported(
|
||||
features_EXT_non_seamless_cube_map.Link(supported_features_2,
|
||||
device_create_info);
|
||||
}
|
||||
// Subgroup properties are Vulkan 1.1 core.
|
||||
if (properties.apiVersion >= VK_MAKE_API_VERSION(0, 1, 1, 0)) {
|
||||
properties_subgroup.pNext = properties_2.pNext;
|
||||
properties_2.pNext = &properties_subgroup;
|
||||
}
|
||||
// VK_EXT_subgroup_size_control properties and features.
|
||||
if (ext_1_3_EXT_subgroup_size_control) {
|
||||
properties_1_3_EXT_subgroup_size_control.pNext = properties_2.pNext;
|
||||
properties_2.pNext = &properties_1_3_EXT_subgroup_size_control;
|
||||
features_1_3_EXT_subgroup_size_control.Link(supported_features_2,
|
||||
device_create_info);
|
||||
}
|
||||
ifn.vkGetPhysicalDeviceProperties2(physical_device, &properties_2);
|
||||
ifn.vkGetPhysicalDeviceFeatures2(physical_device, &supported_features_2);
|
||||
}
|
||||
@@ -713,6 +739,37 @@ std::unique_ptr<VulkanDevice> VulkanDevice::CreateIfSupported(
|
||||
}
|
||||
}
|
||||
|
||||
// Vulkan 1.1 core subgroup properties.
|
||||
if (properties.apiVersion >= VK_MAKE_API_VERSION(0, 1, 1, 0)) {
|
||||
XE_UI_VULKAN_PROPERTY_2(properties_subgroup, subgroupSize);
|
||||
device->properties_.subgroupSupportedStages =
|
||||
properties_subgroup.supportedStages;
|
||||
XELOGI("* subgroupSupportedStages: {}",
|
||||
vk::to_string(
|
||||
vk::ShaderStageFlags(properties_subgroup.supportedStages)));
|
||||
device->properties_.subgroupSupportedOperations =
|
||||
properties_subgroup.supportedOperations;
|
||||
XELOGI("* subgroupSupportedOperations: {}",
|
||||
vk::to_string(vk::SubgroupFeatureFlags(
|
||||
properties_subgroup.supportedOperations)));
|
||||
}
|
||||
|
||||
// VK_EXT_subgroup_size_control (#226, promoted to 1.3).
|
||||
if (ext_1_3_EXT_subgroup_size_control) {
|
||||
XE_UI_VULKAN_PROPERTY_2(properties_1_3_EXT_subgroup_size_control,
|
||||
minSubgroupSize);
|
||||
XE_UI_VULKAN_PROPERTY_2(properties_1_3_EXT_subgroup_size_control,
|
||||
maxSubgroupSize);
|
||||
if (with_gpu_emulation) {
|
||||
XE_UI_VULKAN_FEATURE_2(features_1_3_EXT_subgroup_size_control,
|
||||
subgroupSizeControl);
|
||||
XE_UI_VULKAN_FEATURE_2(features_1_3_EXT_subgroup_size_control,
|
||||
computeFullSubgroups);
|
||||
}
|
||||
}
|
||||
device->extensions_.ext_1_3_EXT_subgroup_size_control =
|
||||
ext_1_3_EXT_subgroup_size_control;
|
||||
|
||||
#undef XE_UI_VULKAN_LIMIT
|
||||
#undef XE_UI_VULKAN_ENUM_LIMIT
|
||||
#undef XE_UI_VULKAN_FEATURE
|
||||
|
||||
@@ -161,6 +161,17 @@ class VulkanDevice {
|
||||
// VK_EXT_non_seamless_cube_map (#423)
|
||||
|
||||
bool nonSeamlessCubeMap = false;
|
||||
|
||||
// Vulkan 1.1 Subgroup Properties
|
||||
uint32_t subgroupSize = 32;
|
||||
VkShaderStageFlags subgroupSupportedStages = 0;
|
||||
VkSubgroupFeatureFlags subgroupSupportedOperations = 0;
|
||||
|
||||
// VK_EXT_subgroup_size_control (#226, promoted to 1.3)
|
||||
uint32_t minSubgroupSize = 0;
|
||||
uint32_t maxSubgroupSize = 0;
|
||||
bool subgroupSizeControl = false;
|
||||
bool computeFullSubgroups = false;
|
||||
};
|
||||
|
||||
// Properties of the core API and enabled extensions, and enabled features.
|
||||
@@ -188,6 +199,8 @@ class VulkanDevice {
|
||||
bool ext_1_3_KHR_maintenance4 = false; // #414
|
||||
// VK_KHR_dynamic_rendering (#55, promoted to 1.3)
|
||||
bool ext_1_3_KHR_dynamic_rendering = false;
|
||||
// VK_EXT_subgroup_size_control (#226, promoted to 1.3)
|
||||
bool ext_1_3_EXT_subgroup_size_control = false;
|
||||
};
|
||||
|
||||
const Extensions& extensions() const { return extensions_; }
|
||||
|
||||
@@ -200,7 +200,11 @@ VkPipeline CreateComputePipeline(
|
||||
const VulkanDevice* const vulkan_device, const VkPipelineLayout layout,
|
||||
const VkShaderModule shader,
|
||||
const VkSpecializationInfo* const specialization_info,
|
||||
const char* const entry_point) {
|
||||
const char* const entry_point, const uint32_t required_subgroup_size) {
|
||||
VkPipelineShaderStageRequiredSubgroupSizeCreateInfo subgroup_size_info = {};
|
||||
subgroup_size_info.sType =
|
||||
VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO;
|
||||
|
||||
VkComputePipelineCreateInfo pipeline_create_info;
|
||||
pipeline_create_info.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
|
||||
pipeline_create_info.pNext = nullptr;
|
||||
@@ -216,6 +220,16 @@ VkPipeline CreateComputePipeline(
|
||||
pipeline_create_info.layout = layout;
|
||||
pipeline_create_info.basePipelineHandle = VK_NULL_HANDLE;
|
||||
pipeline_create_info.basePipelineIndex = -1;
|
||||
|
||||
// Request specific subgroup size if supported and in range.
|
||||
if (required_subgroup_size != 0 &&
|
||||
vulkan_device->properties().subgroupSizeControl &&
|
||||
required_subgroup_size >= vulkan_device->properties().minSubgroupSize &&
|
||||
required_subgroup_size <= vulkan_device->properties().maxSubgroupSize) {
|
||||
subgroup_size_info.requiredSubgroupSize = required_subgroup_size;
|
||||
pipeline_create_info.stage.pNext = &subgroup_size_info;
|
||||
}
|
||||
|
||||
VkPipeline pipeline;
|
||||
if (vulkan_device->functions().vkCreateComputePipelines(
|
||||
vulkan_device->device(), VK_NULL_HANDLE, 1, &pipeline_create_info,
|
||||
@@ -228,14 +242,16 @@ VkPipeline CreateComputePipeline(
|
||||
VkPipeline CreateComputePipeline(
|
||||
const VulkanDevice* const vulkan_device, VkPipelineLayout layout,
|
||||
const uint32_t* shader_code, size_t shader_code_size_bytes,
|
||||
const VkSpecializationInfo* specialization_info, const char* entry_point) {
|
||||
const VkSpecializationInfo* specialization_info, const char* entry_point,
|
||||
const uint32_t required_subgroup_size) {
|
||||
const VkShaderModule shader =
|
||||
CreateShaderModule(vulkan_device, shader_code, shader_code_size_bytes);
|
||||
if (shader == VK_NULL_HANDLE) {
|
||||
return VK_NULL_HANDLE;
|
||||
}
|
||||
const VkPipeline pipeline = CreateComputePipeline(
|
||||
vulkan_device, layout, shader, specialization_info, entry_point);
|
||||
const VkPipeline pipeline =
|
||||
CreateComputePipeline(vulkan_device, layout, shader, specialization_info,
|
||||
entry_point, required_subgroup_size);
|
||||
vulkan_device->functions().vkDestroyShaderModule(vulkan_device->device(),
|
||||
shader, nullptr);
|
||||
return pipeline;
|
||||
|
||||
@@ -180,16 +180,20 @@ inline VkShaderModule CreateShaderModule(
|
||||
: VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
// If required_subgroup_size is non-zero and VK_EXT_subgroup_size_control is
|
||||
// supported with the requested size in range, the pipeline will be created
|
||||
// with that subgroup size requirement. This can be used to request wave64
|
||||
// mode on RDNA GPUs for 64-thread compute shaders.
|
||||
VkPipeline CreateComputePipeline(
|
||||
const VulkanDevice* vulkan_device, VkPipelineLayout layout,
|
||||
VkShaderModule shader,
|
||||
const VkSpecializationInfo* specialization_info = nullptr,
|
||||
const char* entry_point = "main");
|
||||
const char* entry_point = "main", uint32_t required_subgroup_size = 0);
|
||||
VkPipeline CreateComputePipeline(
|
||||
const VulkanDevice* vulkan_device, VkPipelineLayout layout,
|
||||
const uint32_t* shader_code, size_t shader_code_size_bytes,
|
||||
const VkSpecializationInfo* specialization_info = nullptr,
|
||||
const char* entry_point = "main");
|
||||
const char* entry_point = "main", uint32_t required_subgroup_size = 0);
|
||||
|
||||
} // namespace util
|
||||
} // namespace vulkan
|
||||
|
||||
Reference in New Issue
Block a user