radv: implement VK_KHR_shader_float_controls
authorSamuel Pitoiset <samuel.pitoiset@gmail.com>
Mon, 14 Oct 2019 09:27:32 +0000 (11:27 +0200)
committerSamuel Pitoiset <samuel.pitoiset@gmail.com>
Fri, 18 Oct 2019 14:55:58 +0000 (16:55 +0200)
This exposes what's required for DX and this is what we already
configure. The driver flushes denorms for FP32 and preserves them
for FP16/FP64. Note that we can't allow both preserving and
flushing denorms because this won't work for merged shaders. This
will require LLVM to update the float mode register to make it work.

Only enabled on GFX8+ with the LLVM path because it's untested on
previous chips and ACO doesn't support it.

This extension is required for SPIRV 1.4.

Signed-off-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Reviewed-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
docs/relnotes/new_features.txt
src/amd/vulkan/radv_device.c
src/amd/vulkan/radv_extensions.py
src/amd/vulkan/radv_nir_to_llvm.c
src/amd/vulkan/radv_shader.c
src/amd/vulkan/radv_shader.h
src/amd/vulkan/radv_shader_info.c

index 2f7944e929c8a1b8648a0aed0ae6987b3c23a36a..1e146b4b06a92567cca9f098a4570168cb049032 100644 (file)
@@ -4,7 +4,7 @@ GL_EXT_demote_to_helper_invocation on iris, i965.
 OpenGL 4.6 on i965, iris.
 VK_ANDROID_external_memory_android_hardware_buffer on RADV.
 VK_KHR_shader_clock on Intel, RADV.
-VK_KHR_shader_float_controls on Intel.
+VK_KHR_shader_float_controls on Intel, RADV.
 VK_KHR_spirv_1_4 on Intel.
 VK_EXT_shader_subgroup_ballot on Intel.
 VK_EXT_shader_subgroup_vote on Intel.
index 37df820d9caa141c31fafe56fa0cb511d0768a69..5fdb1903c09435a782217f029b410092c2b550fc 100644 (file)
@@ -1488,6 +1488,44 @@ void radv_GetPhysicalDeviceProperties2(
                        properties->uniformTexelBufferOffsetSingleTexelAlignment = true;
                        break;
                }
+               case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES_KHR : {
+                       VkPhysicalDeviceFloatControlsPropertiesKHR *properties =
+                               (VkPhysicalDeviceFloatControlsPropertiesKHR *)ext;
+
+                       /* On AMD hardware, denormals and rounding modes for
+                        * fp16/fp64 are controlled by the same config
+                        * register.
+                        */
+                       properties->denormBehaviorIndependence = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_32_BIT_ONLY_KHR;
+                       properties->roundingModeIndependence = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_32_BIT_ONLY_KHR;
+
+                       /* Do not allow both preserving and flushing denorms
+                        * because different shaders in the same pipeline can
+                        * have different settings and this won't work for
+                        * merged shaders. To make it work, this requires LLVM
+                        * support for changing the register. The same logic
+                        * applies for the rounding modes because they are
+                        * configured with the same config register.
+                        */
+                       properties->shaderDenormFlushToZeroFloat32 = true;
+                       properties->shaderDenormPreserveFloat32 = false;
+                       properties->shaderRoundingModeRTEFloat32 = true;
+                       properties->shaderRoundingModeRTZFloat32 = false;
+                       properties->shaderSignedZeroInfNanPreserveFloat32 = true;
+
+                       properties->shaderDenormFlushToZeroFloat16 = false;
+                       properties->shaderDenormPreserveFloat16 = true;
+                       properties->shaderRoundingModeRTEFloat16 = true;
+                       properties->shaderRoundingModeRTZFloat16 = false;
+                       properties->shaderSignedZeroInfNanPreserveFloat16 = true;
+
+                       properties->shaderDenormFlushToZeroFloat64 = false;
+                       properties->shaderDenormPreserveFloat64 = true;
+                       properties->shaderRoundingModeRTEFloat64 = true;
+                       properties->shaderRoundingModeRTZFloat64 = false;
+                       properties->shaderSignedZeroInfNanPreserveFloat64 = true;
+                       break;
+               }
                default:
                        break;
                }
index 91bbe70217ec199a673f8358f808f55764188d91..11d907ed3418983ff2fd73a2b50a867d9fd3a1c9 100644 (file)
@@ -89,6 +89,7 @@ EXTENSIONS = [
     Extension('VK_KHR_shader_atomic_int64',               1, 'LLVM_VERSION_MAJOR >= 9'),
     Extension('VK_KHR_shader_clock',                      1, True),
     Extension('VK_KHR_shader_draw_parameters',            1, True),
+    Extension('VK_KHR_shader_float_controls',             1, 'device->rad_info.chip_class >= GFX8 && !device->use_aco'),
     Extension('VK_KHR_shader_float16_int8',               1, '!device->use_aco'),
     Extension('VK_KHR_storage_buffer_storage_class',      1, True),
     Extension('VK_KHR_surface',                          25, 'RADV_HAS_SURFACE'),
index 126251193b19a6e5298158e3ccca5eed8779229e..85b452719f0966a68d47f037b8795d3a0eaa7319 100644 (file)
@@ -4769,9 +4769,13 @@ LLVMModuleRef ac_translate_nir_to_llvm(struct ac_llvm_compiler *ac_llvm,
        ctx.options = options;
        ctx.shader_info = shader_info;
 
-       enum ac_float_mode float_mode =
-               options->unsafe_math ? AC_FLOAT_MODE_UNSAFE_FP_MATH :
-                                      AC_FLOAT_MODE_DEFAULT;
+       enum ac_float_mode float_mode = AC_FLOAT_MODE_DEFAULT;
+
+       if (shader_info->float_controls_mode & FLOAT_CONTROLS_DENORM_FLUSH_TO_ZERO_FP32) {
+               float_mode = AC_FLOAT_MODE_DENORM_FLUSH_TO_ZERO;
+       } else if (options->unsafe_math) {
+               float_mode = AC_FLOAT_MODE_UNSAFE_FP_MATH;
+       }
 
        ac_llvm_context_init(&ctx.ac, ac_llvm, options->chip_class,
                             options->family, float_mode, options->wave_size, 64);
index 91e22c9d68f810f88b860851d581fc35869e51a3..5f962ed160ba064a0e49d685c565ead223f5f7f8 100644 (file)
@@ -344,6 +344,7 @@ radv_shader_compile_to_nir(struct radv_device *device,
                                .descriptor_indexing = true,
                                .device_group = true,
                                .draw_parameters = true,
+                               .float_controls = true,
                                .float16 = !device->physical_device->use_aco,
                                .float64 = true,
                                .geometry_streams = true,
index aa8a340d2e1b510f727b0e47eeb3fe06ca57541e..fe23728cb6631a9bd99a9cd885ee998029d8fd47 100644 (file)
@@ -314,6 +314,8 @@ struct radv_shader_info {
 
        struct gfx9_gs_info gs_ring_info;
        struct gfx10_ngg_info ngg_info;
+
+       unsigned float_controls_mode;
 };
 
 enum radv_shader_binary_type {
index 950b5bd599d1e4a299cd4d97277ecefb06ce27f5..60e0cd22fb0c24cc685219545b16d58edc3b4807 100644 (file)
@@ -780,4 +780,5 @@ radv_nir_shader_info_pass(const struct nir_shader *nir,
                es_info->esgs_itemsize = (max_output_written + 1) * 16;
        }
 
+       info->float_controls_mode = nir->info.float_controls_execution_mode;
 }