Float control setting

using vkGetPhysicalDeviceFeatures2KHR, I can get the float control flag of the physical device. For NVIDIA GeForce RTX 3050 Laptop GPU , shaderDenormFlushToZeroFloat32 is false.

How can i change this flag? I want to set shaderDenormFlushToZeroFloat32 = true.
the pseudo code is as follows:

....
VkPhysicalDeviceFloatControlsProperties float_control;
float_control.shaderDenormFlushToZeroFloat32 = true;
....

VkDeviceCreateInfo createInfo;
createInfo.pNext = &float_control
....

But no matter float_control.shaderDenormFlushToZeroFloat32 is true or false for pseudo code , the shader behave is the same.

As the “get” part of the function suggests, it’s a function that queries something in the implementation, not one that allows you to tell it what to do.

It should similarly be obvious by Vulkan’s (rather strict) naming conversions that the VkDeviceQueueCreateInfo structure should not take a structure named VkPhysicalDeviceFloatControlsProperties as one of its extension structures.

If shaderDenormFlushToZeroFloat32 is true, then this means that denormalized floats can be flushed to zero. It doesn’t say they will be.

If you want to ensure that denormalized floats are not flushed, then you must first see if the implementation even allows that. This requires the shaderDenormPreserveFloat32 feature. If the implementation provides this functionality, then you can decorate your shader entrypoint with DenormPreserve to ensure preserving denormalized floats.

I don’t know what the Vulkan-GLSL equivalent to this is, so I don’t know how to turn it on from GLSL.

It’s my mistake for pseudo code. VkDeviceCreateInfo structure takes a structure named VkPhysicalDeviceFloatControlsProperties as one of its extension structures. I have fixed it.

I have two question:

I don’t know the meaning of It doesn’t say they will be.

I have a vkDeviceMemory. I use vkMapMemory to write as int type to set value to 0x8040’0000 which is a denormalized float. And I read this buffer in compute shader as float type.

layout(set = 0, binding = 0) buffer input_buffer{
    float input_arr[];
};
layout(set = 0, binding = 1) buffer output_buffer{
    float output_arr[];
};


void main() {

    output_arr[gl_GlobalInvocationID.x] = input_arr[gl_GlobalInvocationID.x] + input_arr[gl_GlobalInvocationID.x];
}

In my opinion, since shaderDenormFlushToZeroFloat32 is false, so the output value should be a denormalized float, not zero. But I print out output value which is zero, that conflicts with shaderDenormFlushToZeroFloat32 is false

No, it doesn’t. Vulkan’s naming convensions are very strict and very simple. If it’s a Vk<NameOfObject><OtherStuff> struct, its extension structs will be named Vk<NameOfObject><DifferentOtherStuff> too. VkPhysicalDeviceFloatControlsProperties is taken by exactly one function: vkGetPhysicalDeviceProperties2.

You cannot pass VkPhysicalDeviceFloatControlsProperties to VkDeviceCreateInfo. Well, you can, but it won’t actually do anything and if you’re using validation layers, you’ll get an error.

… I don’t know how to explain it any better than that. If something doesn’t say that X happens, then you don’t know if X will happen. That something can happen does not mean that it will.

The word “can” means “is able to”, not “will definitely happen”. I can eat a whole pizza. That does not mean I will do so whenever I am presented with a whole pizza.

If the standard says that a thing will definitely happen, then it will use the word “must”. Note that in the standard, “can” and “must” are in bold-face to make it clear that they are intentionally making such a distinction between what implementations “can” and “must” do.

Vulkan defines a set of rules for how floating-point operations work with regard to precision. But these are largely very flexible, and by default they allow implements to round denormalized floats to zero.

If the implementation specifies shaderDenormFlushToZeroFloat32 , this still means the default behavior is used (which is whatever the implementation wants). However, you have the ability to require denormalized to be flushed to zero for all operations within a shader.

Similarly, shaderDenormPreserveFloat32 being set means that the implementation may preserve denormalized values, but you can also force it to do so within a shader.

These are not queries about what the implementation will do to denormalized values; it’s a statement about your ability to force a shader to handle denormalized values. Some implementations cannot handle denormalized floats at all, so they do not support denormalization preservation. Some implementations (in theory) always handle denormalized values and do not flush them at all, so they do not support flushing behavior. And some implementations may sometimes preserve and sometimes flush, but don’t let you pick which happens.