Open PavielKraskouski opened 1 year ago
Tagging subscribers to this area: @dotnet/area-system-numerics See info in area-owners.md if you want to be subscribed.
Author: | PavielKraskouski |
---|---|
Assignees: | - |
Labels: | `api-suggestion`, `area-System.Numerics` |
Milestone: | - |
While this would be convenient, it is very counter-intuitive to the places that these vector types are typically used.
Vector2/3/4
are types that have SIMD acceleration and which are typically enregistered. That is, unlike a regular struct where the type would be considered to have 2, 3, or 4 distinct fields; SIMD types are typically considered and operated on as 1 individual unit. At runtime, they typically exist in a single register when being utilized and not in memory or promoted to a register per field.
Because of this, accessing the individual fields of these SIMD types can be quite a bit more expensive and thus deconstruction will lead to very poor performance and is effectively an anti-pattern for the type. You instead typically want to treat it like you would any other primitive type; replacing the whole vector at once.
We do not typically provide a way to construct a type from a tuple, particularly not implicitly and I expect that side is a non-starter.
This issue has been marked needs-author-action
and may be missing some important information.
Then what is better for performance if I still need to extract the values of the vector components, because they are used separately in different formulas: access the fields of the vector directly or write the fields to separate variables for later use?
Could you elaborate on the formula being used?
You typically want to try to restructure your data to allow taking advantage of the underlying vectorization where possible. One of the most typical ways to do this would be to utilize "structure of arrays" (SoA) rather than "arrays of structures" (AoS).
However, if you can't restructure your data, there are often some simple transformations you can make to the code to better take advantage of how SIMD works at the hardware level. The perf benefits tend to be well worth it, particularly in the domains these types get used.
I am working on a software renderer. All my textures are a one-dimensional Vector3
array. For each type of texture, Vector3
stores different information. For color textures, these are colors in linear space in the range [0, 1]
, for normal maps, these are normal vectors. I also use MRAO textures that store different coefficients in each Vector3
component (X
- metalness, Y
- roughness, Z
- ambient occlusion). Colors and normal vectors are used as expected using SIMD acceleration. But Vector3
components of MRAO textures cannot be used as a whole.
Here is an example of calculating Fresnel reflectance at 0 degrees using metalness (mrao.X
):
Vector3 F0 = Vector3.Lerp(new(0.04f), baseColor, mrao.X);
This calculates ambient light reflection, which uses ambient occlusion (mrao.Z
).
Vector3 ambient = AmbientLight * baseColor * mrao.Z;
Calculating values of the normal distribution function and the geometric masking-shadowing function using roughness (mrao.Y
):
float DTrowbridgeReitz()
{
float a2 = mrao.Y * mrao.Y * mrao.Y * mrao.Y;
float denom = NdotH * NdotH * (a2 - 1) + 1;
return a2 / Max(1e-4f, Pi * denom * denom);
}
float GSmith()
{
float GSchlickBeckmann(float NdotX)
{
float k = mrao.Y * mrao.Y * 0.5f;
return 1 / Max(1e-4f, NdotX * (1 - k) + k);
}
return GSchlickBeckmann(NdotL) * GSchlickBeckmann(NdotV);
}
Background and motivation
Convenient conversion from a vector to a tuple of its components and vice versa.
API Proposal
API Usage
Alternative Designs
No response
Risks
No response