[Vulkan] Float controls properties
This commit is contained in:
parent
8febf02a39
commit
715d614f5e
|
@ -28,7 +28,8 @@ SpirvShaderTranslator::Features::Features(bool all)
|
|||
max_storage_buffer_range(all ? UINT32_MAX : (128 * 1024 * 1024)),
|
||||
clip_distance(all),
|
||||
cull_distance(all),
|
||||
float_controls(all) {}
|
||||
signed_zero_inf_nan_preserve_float32(all),
|
||||
denorm_flush_to_zero_float32(all) {}
|
||||
|
||||
SpirvShaderTranslator::Features::Features(
|
||||
const ui::vulkan::VulkanProvider& provider)
|
||||
|
@ -48,8 +49,18 @@ SpirvShaderTranslator::Features::Features(
|
|||
} else {
|
||||
spirv_version = spv::Spv_1_0;
|
||||
}
|
||||
float_controls = spirv_version >= spv::Spv_1_4 ||
|
||||
device_extensions.khr_shader_float_controls;
|
||||
if (spirv_version >= spv::Spv_1_4 ||
|
||||
device_extensions.khr_shader_float_controls) {
|
||||
const VkPhysicalDeviceFloatControlsPropertiesKHR&
|
||||
float_controls_properties = provider.device_float_controls_properties();
|
||||
signed_zero_inf_nan_preserve_float32 =
|
||||
bool(float_controls_properties.shaderSignedZeroInfNanPreserveFloat32);
|
||||
denorm_flush_to_zero_float32 =
|
||||
bool(float_controls_properties.shaderDenormFlushToZeroFloat32);
|
||||
} else {
|
||||
signed_zero_inf_nan_preserve_float32 = false;
|
||||
denorm_flush_to_zero_float32 = false;
|
||||
}
|
||||
}
|
||||
|
||||
SpirvShaderTranslator::SpirvShaderTranslator(const Features& features)
|
||||
|
@ -82,7 +93,8 @@ void SpirvShaderTranslator::StartTranslation() {
|
|||
builder_->addCapability(IsSpirvTessEvalShader() ? spv::CapabilityTessellation
|
||||
: spv::CapabilityShader);
|
||||
if (features_.spirv_version < spv::Spv_1_4) {
|
||||
if (features_.float_controls) {
|
||||
if (features_.signed_zero_inf_nan_preserve_float32 ||
|
||||
features_.denorm_flush_to_zero_float32) {
|
||||
builder_->addExtension("SPV_KHR_float_controls");
|
||||
}
|
||||
}
|
||||
|
@ -511,21 +523,21 @@ std::vector<uint8_t> SpirvShaderTranslator::CompleteTranslation() {
|
|||
? spv::ExecutionModelTessellationEvaluation
|
||||
: spv::ExecutionModelVertex;
|
||||
}
|
||||
// TODO(Triang3l): Re-enable float controls when
|
||||
// VkPhysicalDeviceFloatControlsPropertiesKHR are handled.
|
||||
/* if (features_.float_controls) {
|
||||
if (features_.denorm_flush_to_zero_float32) {
|
||||
// Flush to zero, similar to the real hardware, also for things like Shader
|
||||
// Model 3 multiplication emulation.
|
||||
builder_->addCapability(spv::CapabilityDenormFlushToZero);
|
||||
builder_->addExecutionMode(function_main_,
|
||||
spv::ExecutionModeDenormFlushToZero, 32);
|
||||
}
|
||||
if (features_.signed_zero_inf_nan_preserve_float32) {
|
||||
// Signed zero used to get VFACE from ps_param_gen, also special behavior
|
||||
// for infinity in certain instructions (such as logarithm, reciprocal,
|
||||
// muls_prev2).
|
||||
builder_->addCapability(spv::CapabilitySignedZeroInfNanPreserve);
|
||||
builder_->addExecutionMode(function_main_,
|
||||
spv::ExecutionModeSignedZeroInfNanPreserve, 32);
|
||||
} */
|
||||
}
|
||||
spv::Instruction* entry_point =
|
||||
builder_->addEntryPoint(execution_model, function_main_, "main");
|
||||
for (spv::Id interface_id : main_interface_) {
|
||||
|
|
|
@ -92,7 +92,8 @@ class SpirvShaderTranslator : public ShaderTranslator {
|
|||
uint32_t max_storage_buffer_range;
|
||||
bool clip_distance;
|
||||
bool cull_distance;
|
||||
bool float_controls;
|
||||
bool signed_zero_inf_nan_preserve_float32;
|
||||
bool denorm_flush_to_zero_float32;
|
||||
};
|
||||
SpirvShaderTranslator(const Features& features);
|
||||
|
||||
|
|
|
@ -125,6 +125,12 @@ bool VulkanProvider::Initialize() {
|
|||
library_functions_loaded &=
|
||||
(lfn_.vkCreateInstance = PFN_vkCreateInstance(lfn_.vkGetInstanceProcAddr(
|
||||
VK_NULL_HANDLE, "vkCreateInstance"))) != nullptr;
|
||||
library_functions_loaded &=
|
||||
(lfn_.vkEnumerateInstanceExtensionProperties =
|
||||
PFN_vkEnumerateInstanceExtensionProperties(
|
||||
lfn_.vkGetInstanceProcAddr(
|
||||
VK_NULL_HANDLE,
|
||||
"vkEnumerateInstanceExtensionProperties"))) != nullptr;
|
||||
if (!library_functions_loaded) {
|
||||
XELOGE(
|
||||
"Failed to get Vulkan library function pointers via "
|
||||
|
@ -144,11 +150,58 @@ bool VulkanProvider::Initialize() {
|
|||
VK_SUCCESS) {
|
||||
instance_api_version = VK_API_VERSION_1_0;
|
||||
}
|
||||
XELOGVK("Vulkan instance version {}.{}.{}",
|
||||
XELOGVK("Vulkan instance version: {}.{}.{}",
|
||||
VK_VERSION_MAJOR(instance_api_version),
|
||||
VK_VERSION_MINOR(instance_api_version),
|
||||
VK_VERSION_PATCH(instance_api_version));
|
||||
|
||||
// Get the instance extensions.
|
||||
std::vector<VkExtensionProperties> instance_extension_properties;
|
||||
VkResult instance_extensions_enumerate_result;
|
||||
for (;;) {
|
||||
uint32_t instance_extension_count =
|
||||
uint32_t(instance_extension_properties.size());
|
||||
bool instance_extensions_was_empty = !instance_extension_count;
|
||||
instance_extensions_enumerate_result =
|
||||
lfn_.vkEnumerateInstanceExtensionProperties(
|
||||
nullptr, &instance_extension_count,
|
||||
instance_extensions_was_empty
|
||||
? nullptr
|
||||
: instance_extension_properties.data());
|
||||
// If the original extension count was 0 (first call), SUCCESS is
|
||||
// returned, not INCOMPLETE.
|
||||
if (instance_extensions_enumerate_result == VK_SUCCESS ||
|
||||
instance_extensions_enumerate_result == VK_INCOMPLETE) {
|
||||
instance_extension_properties.resize(instance_extension_count);
|
||||
if (instance_extensions_enumerate_result == VK_SUCCESS &&
|
||||
(!instance_extensions_was_empty || !instance_extension_count)) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (instance_extensions_enumerate_result != VK_SUCCESS) {
|
||||
instance_extension_properties.clear();
|
||||
}
|
||||
std::memset(&instance_extensions_, 0, sizeof(instance_extensions_));
|
||||
if (instance_api_version >= VK_MAKE_VERSION(1, 1, 0)) {
|
||||
instance_extensions_.khr_get_physical_device_properties2 = true;
|
||||
}
|
||||
for (const VkExtensionProperties& instance_extension :
|
||||
instance_extension_properties) {
|
||||
const char* instance_extension_name = instance_extension.extensionName;
|
||||
if (!instance_extensions_.khr_get_physical_device_properties2 &&
|
||||
!std::strcmp(instance_extension_name,
|
||||
"VK_KHR_get_physical_device_properties2")) {
|
||||
instance_extensions_.khr_get_physical_device_properties2 = true;
|
||||
}
|
||||
}
|
||||
XELOGVK("Vulkan instance extensions:");
|
||||
XELOGVK(
|
||||
"* VK_KHR_get_physical_device_properties2: {}",
|
||||
instance_extensions_.khr_get_physical_device_properties2 ? "yes" : "no");
|
||||
|
||||
// Create the instance.
|
||||
std::vector<const char*> instance_extensions_enabled;
|
||||
instance_extensions_enabled.push_back("VK_KHR_surface");
|
||||
|
@ -157,6 +210,12 @@ bool VulkanProvider::Initialize() {
|
|||
#elif XE_PLATFORM_WIN32
|
||||
instance_extensions_enabled.push_back("VK_KHR_win32_surface");
|
||||
#endif
|
||||
if (instance_api_version < VK_MAKE_VERSION(1, 1, 0)) {
|
||||
if (instance_extensions_.khr_get_physical_device_properties2) {
|
||||
instance_extensions_enabled.push_back(
|
||||
"VK_KHR_get_physical_device_properties2");
|
||||
}
|
||||
}
|
||||
VkApplicationInfo application_info;
|
||||
application_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
|
||||
application_info.pNext = nullptr;
|
||||
|
@ -205,11 +264,16 @@ bool VulkanProvider::Initialize() {
|
|||
}
|
||||
|
||||
// Get instance functions.
|
||||
std::memset(&ifn_, 0, sizeof(ifn_));
|
||||
bool instance_functions_loaded = true;
|
||||
#define XE_VULKAN_LOAD_IFN(name) \
|
||||
instance_functions_loaded &= \
|
||||
(ifn_.name = PFN_##name( \
|
||||
lfn_.vkGetInstanceProcAddr(instance_, #name))) != nullptr;
|
||||
#define XE_VULKAN_LOAD_IFN_SYMBOL(name, symbol) \
|
||||
instance_functions_loaded &= \
|
||||
(ifn_.name = PFN_##name( \
|
||||
lfn_.vkGetInstanceProcAddr(instance_, symbol))) != nullptr;
|
||||
XE_VULKAN_LOAD_IFN(vkCreateDevice);
|
||||
XE_VULKAN_LOAD_IFN(vkDestroyDevice);
|
||||
XE_VULKAN_LOAD_IFN(vkDestroySurfaceKHR);
|
||||
|
@ -229,6 +293,13 @@ bool VulkanProvider::Initialize() {
|
|||
#elif XE_PLATFORM_WIN32
|
||||
XE_VULKAN_LOAD_IFN(vkCreateWin32SurfaceKHR);
|
||||
#endif
|
||||
if (instance_extensions_.khr_get_physical_device_properties2) {
|
||||
XE_VULKAN_LOAD_IFN_SYMBOL(vkGetPhysicalDeviceProperties2KHR,
|
||||
(instance_api_version >= VK_MAKE_VERSION(1, 1, 0))
|
||||
? "vkGetPhysicalDeviceProperties2"
|
||||
: "vkGetPhysicalDeviceProperties2KHR");
|
||||
}
|
||||
#undef XE_VULKAN_LOAD_IFN_SYMBOL
|
||||
#undef XE_VULKAN_LOAD_IFN
|
||||
if (!instance_functions_loaded) {
|
||||
XELOGE("Failed to get Vulkan instance function pointers");
|
||||
|
@ -470,6 +541,32 @@ bool VulkanProvider::Initialize() {
|
|||
"support");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get additional device properties.
|
||||
std::memset(&device_float_controls_properties_, 0,
|
||||
sizeof(device_float_controls_properties_));
|
||||
if (instance_extensions_.khr_get_physical_device_properties2) {
|
||||
VkPhysicalDeviceProperties2KHR device_properties_2;
|
||||
device_properties_2.sType =
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR;
|
||||
device_properties_2.pNext = nullptr;
|
||||
VkPhysicalDeviceProperties2KHR* device_properties_2_last =
|
||||
&device_properties_2;
|
||||
if (device_extensions_.khr_shader_float_controls) {
|
||||
device_float_controls_properties_.sType =
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES_KHR;
|
||||
device_float_controls_properties_.pNext = nullptr;
|
||||
device_properties_2_last->pNext = &device_float_controls_properties_;
|
||||
device_properties_2_last =
|
||||
reinterpret_cast<VkPhysicalDeviceProperties2KHR*>(
|
||||
&device_float_controls_properties_);
|
||||
}
|
||||
if (device_properties_2_last != &device_properties_2) {
|
||||
ifn_.vkGetPhysicalDeviceProperties2KHR(physical_device_,
|
||||
&device_properties_2);
|
||||
}
|
||||
}
|
||||
|
||||
XELOGVK(
|
||||
"Vulkan device: {} (vendor {:04X}, device {:04X}, driver {:08X}, API "
|
||||
"{}.{}.{})",
|
||||
|
@ -487,6 +584,17 @@ bool VulkanProvider::Initialize() {
|
|||
device_extensions_.khr_shader_float_controls ? "yes" : "no");
|
||||
XELOGVK("* VK_KHR_spirv_1_4: {}",
|
||||
device_extensions_.khr_spirv_1_4 ? "yes" : "no");
|
||||
if (device_extensions_.khr_shader_float_controls) {
|
||||
XELOGVK(
|
||||
"* Signed zero, inf, nan preserve for float32: {}",
|
||||
device_float_controls_properties_.shaderSignedZeroInfNanPreserveFloat32
|
||||
? "yes"
|
||||
: "no");
|
||||
XELOGVK("* Denorm flush to zero for float32: {}",
|
||||
device_float_controls_properties_.shaderDenormFlushToZeroFloat32
|
||||
? "yes"
|
||||
: "no");
|
||||
}
|
||||
// TODO(Triang3l): Report properties, features.
|
||||
|
||||
// Create the device.
|
||||
|
|
|
@ -57,12 +57,21 @@ class VulkanProvider : public GraphicsProvider {
|
|||
PFN_vkDestroyInstance vkDestroyInstance;
|
||||
// From vkGetInstanceProcAddr.
|
||||
PFN_vkCreateInstance vkCreateInstance;
|
||||
PFN_vkEnumerateInstanceExtensionProperties
|
||||
vkEnumerateInstanceExtensionProperties;
|
||||
struct {
|
||||
PFN_vkEnumerateInstanceVersion vkEnumerateInstanceVersion;
|
||||
} v_1_1;
|
||||
};
|
||||
const LibraryFunctions& lfn() const { return lfn_; }
|
||||
|
||||
struct InstanceExtensions {
|
||||
// Core since 1.1.0.
|
||||
bool khr_get_physical_device_properties2;
|
||||
};
|
||||
const InstanceExtensions& instance_extensions() const {
|
||||
return instance_extensions_;
|
||||
}
|
||||
VkInstance instance() const { return instance_; }
|
||||
struct InstanceFunctions {
|
||||
PFN_vkCreateDevice vkCreateDevice;
|
||||
|
@ -75,6 +84,8 @@ class VulkanProvider : public GraphicsProvider {
|
|||
PFN_vkGetPhysicalDeviceFeatures vkGetPhysicalDeviceFeatures;
|
||||
PFN_vkGetPhysicalDeviceMemoryProperties vkGetPhysicalDeviceMemoryProperties;
|
||||
PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties;
|
||||
// VK_KHR_get_physical_device_properties2 or 1.1.0.
|
||||
PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR;
|
||||
PFN_vkGetPhysicalDeviceQueueFamilyProperties
|
||||
vkGetPhysicalDeviceQueueFamilyProperties;
|
||||
PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR
|
||||
|
@ -129,6 +140,10 @@ class VulkanProvider : public GraphicsProvider {
|
|||
uint32_t queue_family_graphics_compute() const {
|
||||
return queue_family_graphics_compute_;
|
||||
}
|
||||
const VkPhysicalDeviceFloatControlsPropertiesKHR&
|
||||
device_float_controls_properties() const {
|
||||
return device_float_controls_properties_;
|
||||
}
|
||||
|
||||
VkDevice device() const { return device_; }
|
||||
struct DeviceFunctions {
|
||||
|
@ -262,8 +277,9 @@ class VulkanProvider : public GraphicsProvider {
|
|||
|
||||
LibraryFunctions lfn_ = {};
|
||||
|
||||
InstanceExtensions instance_extensions_;
|
||||
VkInstance instance_ = VK_NULL_HANDLE;
|
||||
InstanceFunctions ifn_ = {};
|
||||
InstanceFunctions ifn_;
|
||||
|
||||
VkPhysicalDevice physical_device_ = VK_NULL_HANDLE;
|
||||
VkPhysicalDeviceProperties device_properties_;
|
||||
|
@ -274,6 +290,7 @@ class VulkanProvider : public GraphicsProvider {
|
|||
uint32_t memory_types_host_coherent_;
|
||||
uint32_t memory_types_host_cached_;
|
||||
uint32_t queue_family_graphics_compute_;
|
||||
VkPhysicalDeviceFloatControlsPropertiesKHR device_float_controls_properties_;
|
||||
|
||||
VkDevice device_ = VK_NULL_HANDLE;
|
||||
DeviceFunctions dfn_ = {};
|
||||
|
|
Loading…
Reference in New Issue