microsoft / hlsl-specs

HLSL Specifications
MIT License
125 stars 34 forks source link

[0023] C++11 as base, why not C++17 ? #348

Closed devshgraphicsprogramming closed 1 month ago

devshgraphicsprogramming commented 1 month ago

Which proposal does this relate to?

https://github.com/microsoft/hlsl-specs/blob/main/proposals/0023-cxx11-base.md

Describe the issue or outstanding question.

First of all, I'm a bit let down that C++20 isn't the default as we'd really appreciate the ability to use concepts. We do a lot of very horrible enable_if in our HLSL codebase to achieve the equivalent.

C++20 also introduces consteval and constinit which would be quite useful for the domain of GPU programming (I find myself needing to deal with consteval-like expressions a lot more in shaders than host code).

Also templated lambdas are what I'd deem "the final cleanup" of changes C++14 did to lambdas https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0428r2.pdf

That being said, one can view C++14 and C++17 as very minor increments over C++11

Why C++14 ?

IIRC Metal SL was based off C++14 so its rather weird that HLSL 202y starting many years after metal would choose to use a lower C++ version as the baseline.

First of all some C++14 features are already supported by DXC, such as variable templates. We already make use of them in our type_traits header.

Secondly, C++14 allows for far more useful constexpr functions which can do conditional branches and loops. This means we can actually hope for a constant evaluation of higher order mathematical functions such as erf that we write ourselves.

Lastly, Lambda expressions from C+11 aren't that useful by themselves. C++14 allows Generic Lambdas. These are awesome as they allow you to implement if constexpr from C++17 as a workaround (which we used before transitioning to C++17).

https://github.com/Garcia6l20/if_constexpr14

Mind you that with current C++98 with 11 extensions codebase we have to implement all of our would-be if constexpr as named structs which have partial specializations on the bool. But a C++11 lambda cannot be used as a if constexpr replacement because the arguments cannot be auto.

Generic Lambdas are not only useful to emulate if constexpr they solve a very important issue we have right now which is mainly that operator() can't be easily templated (in a way that its transparent to the functor calling code), either all functor's operator() must be templated or none.

It really makes writing lambdas for lower_bound and upper_bound a lot easier, you don't need to declare separate lambdas just because the type changed (as long as lets say the members being compared / logic inside stay the same).

Why C++17 ?

First, The above shows why C++17's if constexpr is pretty and useful, as its a pretty horrible hack and doesn't work the same as an if constexpr and has limitations where it won't work the same.

Second lambda improvement is the ability to capture this by value, I see this as a very important addition.

Third, typename in "template template parameter" makes code partial specializing on vector-like more "correct.

template<template<typename,int32_t> Vector, typename T, int32_t Dim>

A scalar type is a typename and not a class or struct. And yes we already do that, because we made an emulated_float64_t scalar type for Intel ARC GPUs which don't support shaderFloat64, so we also made emulated_vector and emulated_matrix plus partial specs of <function> https://github.com/Devsh-Graphics-Programming/Nabla/tree/23843c84e22f29af1ac7b0c321bdb0377748138d/include/nbl/builtin/hlsl/emulated

Fourth, fold expressions and initializers in if and switch are awesome.

Finally nested namespace definitions are a nice cosmetic feature.

llvm-beanz commented 1 month ago

The main reason is time and resources. Adopting a new base version of C++ isn't just flipping a switch in the compiler. It also involves updating and tweaking the design and implementation of HLSL features to adjust to the new base version. Iteratively raising the base version gives us the opportunity to review each new C++ feature, identify how they interact with HLSL and make adjustments as we go.

It is important to remember that C++ 11 was a massive feature version over C++98/03. In order to make C++11 our base we'll have dozens of new features that need to be adjusted and tweaked to work with HLSL. We'll have existing HLSL syntax that will need to be deprecated in 202x and removed in 202y (specifically HLSL's initializer lists which cannot be used under variadic template pack expansions).

Choosing to start at C++ 11 for the Clang implementation gives us a head start on resolving those issues, but also doesn't fully flood our team resolving 20 years of C++ evolution at the same time.

We are very interested in adding C++20, in particular concepts to HLSL, and we may even add concepts before we move the base version to C++ 20 because we're actually using them internally in the compiler implementation for Clang.

damyanp commented 1 month ago

Longer term we definitely want to bring in more features from later C++ standards, however for proposal 23 the plan is to target C++11, as described above.