<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://abolishcrlf.org//feed.xml" rel="self" type="application/atom+xml" /><link href="https://abolishcrlf.org//" rel="alternate" type="text/html" /><updated>2026-07-23T16:54:35+00:00</updated><id>https://abolishcrlf.org//feed.xml</id><title type="html">Abolish \r\n</title><subtitle>Removing Vestigial Technology</subtitle><entry><title type="html">State of HLSL: February 2026</title><link href="https://abolishcrlf.org//2026/02/10/HLSLState.html" rel="alternate" type="text/html" title="State of HLSL: February 2026" /><published>2026-02-10T15:00:00+00:00</published><updated>2026-02-10T15:00:00+00:00</updated><id>https://abolishcrlf.org//2026/02/10/HLSLState</id><content type="html" xml:base="https://abolishcrlf.org//2026/02/10/HLSLState.html"><![CDATA[<h1 id="state-of-hlsl-february-2026">State of HLSL: February 2026</h1>

<p>I’ll probably always remember 2025 as the year that I stopped being able to have
conversations about future directions for GPU programming without someone
slipping the word “neural” into the conversation. While I’m personally skeptical
about many applications of neural networks, 2025 is also the year that some
really interesting use cases, specifically around realtime graphics, gained
attention.</p>

<p>The rise of “neural rendering” (a term I loathe) defined 2025 and dominated the
conversation around HLSL this year, but it isn’t the only thing happening in
HLSL-land. So let’s talk about the other things first then come back around.</p>

<h2 id="status-of-hlsl-in-clang">Status of HLSL in Clang</h2>

<p>The HLSL teams at Microsoft and Google have continued to make steady progress on
the Clang implementation of HLSL. Clang now supports <code class="language-plaintext highlighter-rouge">[RW]Buffer</code> and
<code class="language-plaintext highlighter-rouge">[RW]StructuredBuffer</code> resource types and will soon support
<code class="language-plaintext highlighter-rouge">[RW]ByteAddressBuffer</code>. The team has continued expanding support for the HLSL
intrinsic functions, and we’re just starting work on graphics shaders which will
include support for shader inputs and outputs, matrix data types, texture
resources and more!</p>

<p>Most of the work that we’re driving is just to bring feature parity with DXC,
but I do want to highlight a few areas where we’re investing in significant
improvements over DXC.</p>

<h3 id="better-root-signature-diagnostics">Better Root Signature Diagnostics</h3>

<p>One of the really cool things that got built this year in Clang is the new root
signature parser (shout out to <a href="https://github.com/inbelic">Finn Plummer</a> who
did this). We get a lot of complaints about root signatures for a lot of
reasons, and the weird grammar parsing is just one of the reasons people tend to
dislike them. While a longer-term solution to root signatures isn’t currently on
our roadmap, the new parser in Clang is pretty awesome and it really shows the
kind of quality focus our team is driving.</p>

<p>A key goal of this work was to prioritize great diagnostics coming from the root
signature parser with accurate source locations so that if you make a mistake in
a root signature the parser will give you as much help as we can to find the
error. To enable this, the new root signature parser uses Clang’s utilities for parsing, source
locations and diagnostics. This makes it possible for Clang to give diagnostics
with accurate source locations in cases where DXC could not.</p>

<p>For example, given the root signatures specified as:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#define BasicValidation \
  "StaticSampler(s0, maxAnisotropy = 13)," \
  "StaticSampler(s1, maxAnisotropy = 17)," \
  "StaticSampler(s2, maxAnisotropy = 13)," \
  "StaticSampler(s3, maxAnisotropy = 13)," \
  "StaticSampler(s4, maxAnisotropy = 23)," \
  "StaticSampler(s5, maxAnisotropy = 13)"
</span></code></pre></div></div>

<p>DXC provides the following diagnostic, where the source location points to the
line that the preprocessor directive begins on, not necessarily where the error
is.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&lt;source&gt;:40:9: error: root signature error - Static sampler: MaxAnisotropy must be in the range [0 to 16].  17 specified.
</code></pre></div></div>

<p>The new parser in Clang provides much more context, with specific locations
inside the macro definition itself:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&lt;source&gt;:42:4: error: value must be in the range [0, 16]
   42 |   "StaticSampler(s1, maxAnisotropy = 17)," \
      |    ^
&lt;source&gt;:45:4: error: value must be in the range [0, 16]
   45 |   "StaticSampler(s4, maxAnisotropy = 23)," \
      |    ^
2 errors generated.
</code></pre></div></div>

<p>You may notice that Clang produced two errors rather than just one. This is
another key difference between DXC and Clang’s parsers. The DXC parser aborts on
the first error it encounters. This means that if your root signature has
multiple errors you need to iterate resolving one then recompiling the shader to
see the next error. The new parser in Clang recovers from parsing errors where
it can and attempts to continue parsing to provide a more comprehensive set of
diagnostics in a single pass.</p>

<p>To demonstrate some of the resilience in Clang’s parser and it’s ability to
recover consider the following root signature that has multiple errors,
sometimes in the same clauses:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#define Recovery \
  "CBV(b0, reported_diag, flags = skipped_diag)," \
  "DescriptorTable( " \
  "  UAV(u0, reported_diag), " \
  "  SRV(t0, skipped_diag), " \
  ")," \
  "StaticSampler(s0, reported_diag, SRV(t0, reported_diag)"
</span></code></pre></div></div>

<p>For this root signature DXC’s parser provides the diagnostic:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&lt;source&gt;:63:9: error: root signature error - Unexpected token 'reported_diag'
#define Recovery \
        ^
</code></pre></div></div>

<p>Meanwhile Clang’s new parser identifies multiple errors in a single pass:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&lt;source&gt;:64:12: error: invalid parameter of CBV
   64 |   "CBV(b0, reported_diag, flags = skipped_diag)," \
      |            ^
&lt;source&gt;:66:14: error: invalid parameter of UAV
   66 |   "  UAV(u0, reported_diag), " \
      |              ^
&lt;source&gt;:69:22: error: invalid parameter of StaticSampler
   69 |   "StaticSampler(s0, reported_diag, SRV(t0, reported_diag)"
      |                      ^
&lt;source&gt;:69:45: error: invalid parameter of SRV
   69 |   "StaticSampler(s0, reported_diag, SRV(t0, reported_diag)"
      |                                             ^
4 errors generated.
</code></pre></div></div>

<p>Clang’s parser can’t always detect all the errors as the parsing context may be
incomplete, but it does a much better job than DXC’s parser.</p>

<p>We really think this kind of quality-of-life improvement will make Clang a much
better tool for our users and we’re really excited to see some of this quality
focus coming to life. Both of the examples above I pulled from a <a href="https://godbolt.org/z/escEaK6vT">Compiler
Explorer</a> demo Finn created that shows off the
differences in diagnostics between Clang and DXC really well. Take a look at
that for more examples and keep playing with it.</p>

<h3 id="offload-test-suite">Offload Test Suite</h3>

<p>Another big area that we’ve been investing in is our testing infrastructure.
DXC’s infrastructure for testing shader execution only supports DirectX on
Windows, which turns out to be a pretty big limitation as we’re increasingly
viewing HLSL as a cross-platform language. Further, the infrastructure is very
tightly connected to DXC in a way that doesn’t make it easy to use with Clang.</p>

<p><img src="https://abolishcrlf.org/assets/images/TrainSmashAPIs.jpg" /></p>

<p>To address these limitations we’ve built a new testing infrastructure in LLVM
called the <a href="https://github.com/llvm/offload-test-suite/">Offload Test Suite</a>.
The new infrastructure is dependent on LLVM for some utilities, but the test
execution is decoupled from the compiler and source language allowing us to run
the same tests with DXC and Clang. Additionally, the new infrastructure supports
DirectX, Vulkan and Metal giving us wide testing coverage.</p>

<p>We’re using this new infrastructure to not only expand our testing of the Clang
compiler implementation, but also to ensure that shaders compiled with Clang
behave the same as when they are compiled with DXC. We hope this will make it a
smoother migration path for our users.</p>

<p>If you’re interested to learn more about this infrastructure, I gave a <a href="https://www.youtube.com/watch?v=umTaqZYYBlU">talk
last fall at the LLVM Developer
Meeting</a> about it and how the HLSL
team has integrated it to our workflows.</p>

<h2 id="standardizing-hlsl">Standardizing HLSL!</h2>

<blockquote>
  <p>Note: I wrote about standardizing HLSL on the <a href="https://devblogs.microsoft.com/directx/standardizing-hlsl">DirectX
blog</a>. If you
prefer to read a more “official” (read humorless and devoid of personality or
memes) version of this go there. Otherwise strap in!</p>
</blockquote>

<p>The development in HLSL that I’m most excited about coming into 2026 is that
we’ve started the process of forming a committee to standardize HLSL. I’ve built
my career around open source software, and deeply believe that some types of
software just should not be proprietary, moving to standardize HLSL is the only
path I see forward for HLSL to evolve and thrive. I’ve said this a few times,
but I’ll reiterate it here: <strong>the future of HLSL is cross-platform and open</strong>.</p>

<p>This has been a huge effort for me personally as I’ve been working to win hearts
and minds across Microsoft as well as strengthening partnerships across the
industry. Microsoft has some reputations that we’re working to overcome and I’ve
put a lot of my personal reputation out to signal that we’re serious
about this.</p>

<h3 id="why-are-we-doing-this">Why are we doing this?</h3>

<p>In my experience, compilers and programming languages are just too complicated
and don’t bring enough differentiating value for businesses to justify
adequately staffing compiler teams to build proprietary compilers at quality and
scale that compete against open source alternatives. This is especially true for
languages as complex as C++ (which HLSL is trending toward).</p>

<p><img src="https://abolishcrlf.org/assets/images/LucileCompilerCost.jpg" /></p>

<p>Inadequate staffing for HLSL has been a huge problem for our team. We have a
massive pressure to constantly expose new shader model features, and we have
never had a large enough team to both expose new hardware features and evolve
HLSL itself to make users more productive. This has led to a lot of short
sighted decisions along the way. We’ve taken shortcuts and accrued massive
technical debt, the most obvious bit of which is DXC being locked to LLVM 3.7
which is now over a decade old.</p>

<p><img src="https://abolishcrlf.org/assets/images/HurdleLLVM37.jpg" /></p>

<p>The bare truth is that a good programming language and compiler is price of
admission for a platform, but it isn’t going to sell more hardware or software
licenses. That said, a <em>bad</em> programming language or compiler can burden
software developers so much that it impairs their ability to ship quality
software, which will adversely impact sales.</p>

<p>While I don’t think the HLSL compiler is (yet) out of date and “bad” enough to
be a real liability, it is trending that direction so we <em>really</em> need to fix
it, and in fixing it we need to shift our development model for HLSL to be more
sustainable with reasonable investment of resources.</p>

<p>This is all business speak for: embrace open source, build broad partnerships,
and build a healthy community.</p>

<h3 id="what-benefit-will-a-standard-provide-for-users">What benefit will a standard provide for users?</h3>

<p>Being unable to invest sufficiently in evolving HLSL itself and in quality
toolchain features has contributed to some long-lasting industry problems that
have at times seemed intractable. One clear example is the complexity of shader
build pipelines.</p>

<p>When you build a cross-platform application’s CPU code you can generally use the
same language (and often compiler) for the bulk of your application logic.
Concretely, if you’re building a game for Windows, Linux, macOS, Xbox,
Playstation and Nintendo; you can write your CPU code in C and C++ and you can
use Clang as the compiler. You may have some platform-specific bits in your
C/C++ code, but most of the code is easily shared. The same is not strictly
true for GPU programming.</p>

<p>The Khronos Group, through its members and community, has done amazing work
building a cross-platform pipeline for GPU programs, but it is immensely
complex. Consider my modified version of the SPIRV ecosystem diagram from
<a href="https://www.khronos.org/spirv/#spir-ecosystem">Khronos</a>, where I’ve added
DirectX into the picture:</p>

<p><img src="https://abolishcrlf.org/assets/images/SPIREcosystem2025.png" /></p>

<p>It’s impressive how many source languages you can choose from (on the left), and
how many target runtimes you can execute on top of (on the right). The problem
is the number of (lossy) translation layers in the middle. SPIRV-Cross in
particular is load-bearing in a lot of shader build pipelines, and it destroys
debug information (mapping of final executable code to source lines), which
makes shader debugging and profiling extremely difficult.</p>

<p>The absence of unifying tooling which led to this ecosystem state has caused
cross-platform game engines to develop their own complex shader build pipelines.
I’ve been working in this space a <em>long</em> time and I still get horrified when I
hear about how developers actually build shaders for their titles.</p>

<p><img src="https://abolishcrlf.org/assets/images/CharlieRenderingEngineer.jpg" /></p>

<p>Shader build pipelines for AAA engines are complex Rube Goldberg machines that
we all put up with in the name of maintaining productivity. Microsoft will not
sell more XBoxes or Windows licenses if we fix this problem, so the problem gets
ignored… Until now.</p>

<p>Today we already have a native build pipeline for HLSL using DXC and Clang
to build shaders for DirectX and Vulkan. We also have a native-ish path for
Metal through the Metal Shader Converter, which is an IR-&gt;IR translator that
preserves accurate debug information and enables HLSL to be used with Apple’s
native shader debugging and profiling tools (which is crazy impressive!).</p>

<p>My sincere hope is that by standardizing HLSL in conjunction with our
integration of HLSL into Clang we’ll build a broad community around HLSL that
prioritizes cross-platform support, high quality tooling, and language
evolution. Our ultimate goal is to build broad industry partnerships to ensure
that all HLSL users get the best tooling possible.</p>

<p>Hey Apple, Sony and Nintendo: come join us!</p>

<p><img src="https://abolishcrlf.org/assets/images/DarkSideStandard.jpg" /></p>

<h3 id="dont-standard-committees-make-things-slow">Don’t standard committees make things slow?</h3>

<p>In conversations I tend to use the term “deliberate” to describe how I would
like to see HLSL evolve. Historically, I think we’ve allowed the language to
evolve haphazardly without a framing process that required us to think through
the short and long term implications of new features. We’ve at times moved too
slowly and at other times moved too fast. This both leaves us behind in terms of
useful feature sets and lacking in quality. As a notable example, HLSL 2021
introduced more bugs than features, and we’ve now spent years addressing them.</p>

<p><img src="https://abolishcrlf.org/assets/images/DXCBrokeShiba.jpg" /></p>

<p>I believe that adopting a standard process will force us to evolve HLSL within a
process designed to make us be thoughtful and deliberate about the features we
add (and remove) from HLSL. This process may at times be slower than we could be
without it, and it may be slower than other competing languages, but I believe
it will produce a higher quality result which is in the best interests of
everyone. I also believe that by doing this under an international
standardization body, we will have a framework to keep us honest and curtail our
base instincts that may lead us to make rapid and flawed decisions.</p>

<p>I bristle when I hear people talk about “rapid innovation” in programming
languages or compilers. There are certainly types of software where rapid
innovation may benefit users, but infrastructural software that people depend on
needs a level of stability and reliability that is at odds with the “move fast
and break things” model.</p>

<p>I can’t imagine anyone wants to integrate an experimental tool in a
load-bearing capacity to a production codebase, and following on from that I
believe that most of HLSL’s users want to be able to depend on HLSL being stable
so that the code they write in HLSL today will work as expected in the future.
The <em>worst</em> thing we could do is make fundamental changes to the semantics of
HLSL without considering our users and the impact on them, and a standard
process will provide a forum for our users to have a voice and a framework to
keep us honest as we evolve HLSL for the future.</p>

<h3 id="okay-how-does-this-really-work">Okay, how does this really work?</h3>

<p>The newly formed <a href="https://ecma-international.org/technical-committees/tc57/">Technical Committee
57</a> under Ecma
International will focus on specifying and standardizing the core HLSL language.
This effort will focus initially on core behaviors (grammar, basic data types,
conversion rules, overload resolution, etc) and a limited set of common features
that are across all API targets.</p>

<p>As the committee evolves we hope that it will provide energy around evolving
HLSL into a better language while also solidifying it as a cross-platform
standard that is not locked to Microsoft platforms.</p>

<p><img src="https://abolishcrlf.org/assets/images/BuzzHLSLEverywhere.jpg" /></p>

<p>The committee will operate almost entirely in public and on
<a href="https://github.com/hlsl-tc57">GitHub</a>, but meetings will only be open to Ecma
members and invited experts. We invite everyone to follow along with our public
work and contribute to the process!</p>

<h2 id="neural-rendering">Neural Rendering</h2>

<p>I guess I’ve delayed talking about “Neural Rendering” enough and I should just
get this over with. Personally I <em>hate</em> this term because I’m constantly
fighting with people to explain that from a compiler and language perspective
“neural rendering” isn’t any different from any other neural network
evaluation, and it’s all just linear algebra on big multi-dimensional
matrices… but alas I’m just an old man yelling.</p>

<p><img src="https://abolishcrlf.org/assets/images/ManYellsAtNN.jpg" /></p>

<p>We do have some big work from last year and ongoing around neural network
evaluation. Last year we released a preview of the <a href="https://devblogs.microsoft.com/directx/cooperative-vector/">D3D12 Cooperative
Vector</a> feature
which enabled evaluation of small neural networks in rendering and compute
workloads. After a great deal of soul searching in the fall we decided the
feature <a href="https://devblogs.microsoft.com/directx/shader-model-6-9-and-the-future-of-cooperative-vector/">wasn’t quite ready for
primetime</a>,
but we’ve been actively working on bringing the capabilities of Cooperative
Vector, as well as a more capable replacement for <a href="https://devblogs.microsoft.com/directx/agility-sdk-1-711/">Wave
Matrix</a> (which we
previewed back in 2023 but didn’t release in SM 6.8).</p>

<p>The new feature, boringly named <a href="https://github.com/microsoft/hlsl-specs/blob/main/proposals/0035-linalg-matrix.md">Linear Algebra (or LinAlg for
short)</a>
includes both the features of Cooperative Vector, and the features of Wave
Matrix. We’ve worked to align the feature more closely with other APIs (read
Vulkan) so that our new feature can someday be used with both Vulkan and DirectX
via HLSL (and maybe Metal too if Apple aligns). This will enable WebGPU to use
it to implement their proposed <a href="https://dawn.googlesource.com/dawn/+/refs/heads/main/docs/dawn/features/subgroup_matrix.md">Subgroup
Matrix</a>
feature for browsers on Windows.</p>

<p>Regardless of how you feel about GenAI or LLMs (I’m a skeptic), it is clear that
neural networks have more and more useful applications in graphics programming.
There’s a lot of excitement about neural networks for texture compression, radiance
caching, path tracing, denoising, and upscaling. For all these applications and
more it’s super important that HLSL be able to efficiently lower these
algorithms so that shader authors can take full advantage of modern GPU
hardware.</p>

<p>One thing I’m excited about is the capability of neural networks to approximate
complex functions. In a few years when matrix multiplication and accumulation
hardware trickles down to lower-end GPU parts and proliferates across install
bases, function approximation may be a valuable technique for enabling higher
fidelity rendering techniques on lower-end hardware at acceptable frame rates.</p>

<h2 id="parting-thoughts">Parting Thoughts</h2>

<p>If you made it this far: congratulations! I’ve droned on a lot and I won’t keep
you long here. There are a few key themes I’m pushing for HLSL in 2026 which
I’ll state clearly even though they are represented in all the text above.</p>

<h3 id="cross-platform-and-open">Cross-platform and Open</h3>

<p>The future of HLSL is cross-platform and open. That means open source, it means
an open specification with a royalty-free patent and IP policy. It means we will
welcome contributions from everyone everywhere.</p>

<p><img src="https://abolishcrlf.org/assets/images/GalaxyBrainHLSL.jpg" /></p>

<h3 id="quality-quality-quality">Quality, Quality, Quality</h3>

<p>We cannot sacrifice quality for expediency or flashiness. We’ve been burned time
and again by shortcuts and lax quality standards, and that pain spreads to our
users. We’ve worked really hard to bring a higher standard of quality to
everything we do in HLSL whether that is our compiler implementation, our
designs for new features, or our draft language specification. We will continue
making those investments in quality, <em>and</em> we will continue to have communities
to help keep us honest along the way.</p>

<p><img src="https://abolishcrlf.org/assets/images/BurnItDownCrash.jpg" /></p>

<h3 id="hlsl-exists-to-serve-users">HLSL Exists to Serve Users</h3>

<p>The thing that makes HLSL a valuable piece of technology is how widely used it
is. We will focus on engaging with our users, responding to their feedback, and
prioritizing their concerns. We won’t always give each individual user all the
things they want because we do have to take a more wholistic look across our
whole user base, but our central motivation must be to empower our users to
be productive and to leverage our tools to make their applications the best they
can be.</p>

<p><img src="https://abolishcrlf.org/assets/images/ThatWouldBeGreatGH.jpg" /></p>]]></content><author><name>Chris Bieneman</name></author><summary type="html"><![CDATA[Another year, another language]]></summary></entry><entry><title type="html">An Experimental Approach to `printf` in HLSL</title><link href="https://abolishcrlf.org//2025/12/31/Printf.html" rel="alternate" type="text/html" title="An Experimental Approach to `printf` in HLSL" /><published>2025-12-31T06:00:00+00:00</published><updated>2025-12-31T06:00:00+00:00</updated><id>https://abolishcrlf.org//2025/12/31/Printf</id><content type="html" xml:base="https://abolishcrlf.org//2025/12/31/Printf.html"><![CDATA[<p>There are a million reasons why having <code class="language-plaintext highlighter-rouge">printf</code> support in HLSL would be super
valuable. It even <a href="https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/printf">used to
exist</a> in
older shader models. Other shader languages like the Metal Shading language have
their own <a href="https://developer.apple.com/documentation/metal/logging-shader-debug-messages">logging
mechanisms</a>,
and shader programming gurus like <a href="https://therealmjp.github.io/posts/hlsl-printf/">MJP have rolled their
own</a>.</p>

<p><strong>Disclaimer:</strong> having an officially supported way to print strings would be
<em>super</em> useful for HLSL… Although <strong>this isn’t official</strong>, this is just me
playing around on my holiday break. It is likely we could make something like
this supported in Clang, however there are some challenges to supporting this in
DXC and when targeting SPIRV or Metal (more on that later).</p>

<p>Before I go any further, let me show you want it looks like to use this. Given
the HLSL code here:</p>

<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="cp">#include</span> <span class="cpf">"dx/printf.h"</span><span class="cp">
</span>
<span class="p">[</span><span class="n">numthreads</span><span class="p">(</span><span class="mi">16</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">)]</span>
<span class="kt">void</span> <span class="nf">main</span><span class="p">(</span><span class="n">uint3</span> <span class="n">TID</span> <span class="o">:</span> <span class="n">SV_GroupThreadID</span><span class="p">)</span> <span class="p">{</span>
  <span class="c1">// Required to initialize the debug output stream.</span>
  <span class="n">dx</span><span class="o">::</span><span class="n">InitializeDebugStream</span><span class="p">();</span>
  <span class="n">uint</span> <span class="n">idx</span> <span class="o">=</span> <span class="n">TID</span><span class="p">.</span><span class="n">x</span><span class="p">;</span>
  <span class="n">uint</span> <span class="n">value</span> <span class="o">=</span> <span class="n">idx</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">value</span> <span class="o">%</span> <span class="mi">3</span> <span class="o">==</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">value</span> <span class="o">%</span> <span class="mi">5</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span>
    <span class="n">dx</span><span class="o">::</span><span class="n">printf</span><span class="p">(</span><span class="s">"FizzBuzz(%u)</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">value</span><span class="p">);</span>
  <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">value</span> <span class="o">%</span> <span class="mi">3</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span>
    <span class="n">dx</span><span class="o">::</span><span class="n">printf</span><span class="p">(</span><span class="s">"Fizz(%u)</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">value</span><span class="p">);</span>
  <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">value</span> <span class="o">%</span> <span class="mi">5</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span>
    <span class="n">dx</span><span class="o">::</span><span class="n">printf</span><span class="p">(</span><span class="s">"Buzz(%u)</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">value</span><span class="p">);</span>
  <span class="k">else</span>
    <span class="n">dx</span><span class="o">::</span><span class="n">printf</span><span class="p">(</span><span class="s">"Baz(%u)</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">value</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>This results in producing a buffer, that when interpreted by the CPU prints
(note ordering of messages can be dependent on compiler optimizations and
hardware constraints, but more on that later):</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>FizzBuzz(15)
Fizz(3)
Fizz(6)
Fizz(9)
Fizz(12)
Buzz(5)
Buzz(10)
Baz(1)
Baz(2)
Baz(4)
Baz(7)
Baz(8)
Baz(11)
Baz(13)
Baz(14)
Baz(16)
</code></pre></div></div>

<h2 id="the-challenges-with-printf">The Challenges with <code class="language-plaintext highlighter-rouge">printf</code></h2>

<p>There are two different classes of challenges that <code class="language-plaintext highlighter-rouge">printf</code> pose. First is the
general problem space around <code class="language-plaintext highlighter-rouge">printf</code> on a GPU, and the second is more about how
to fit <code class="language-plaintext highlighter-rouge">printf</code> into HLSL. The design I’ve prototyped tries to address problems
in both of these spaces to provide a powerful solution for users.</p>

<h3 id="problem-space-printing-text-on-gpus">Problem Space: Printing Text on GPUs</h3>

<p>The main problem with printing text on GPUs comes down to two main issues
around string data: (1) string data can be big, and (2) string formatting is
<em>wildly</em> divergent.</p>

<p>Large amounts of string data coming on and off the GPU would pose a significant
performance problem at multiple levels of the software stack. Embedding strings
into GPU programs bloats the program sizes, increasing the data drivers need to
manage and (if not stripped) results in transferring more data than necessary to
the GPU (and potentially back). This would result in logging having a
potentially massive impact on the runtime of a given shader, which would in turn
limit its usefulness as a debugging tool.</p>

<p>Formatting strings on a GPU opens another massive can of worms because
thread-divergent values would likely cause significant divergence in processing,
and that’s before you even start to think about problems with memory
allocations. I don’t know of any implementation outside the “C++ on your GPU”
world that has actually tried to do string formatting on a GPU for good reason.</p>

<p>The solution I’ve prototyped aims to address both of these challenges by not
doing any string processing on the GPU, and removing the strings entirely from
the compiled shader binary that gets handed to the driver. This has an added
benefit that it requires <em>no changes</em> to GPU drivers, and can work on existing
production drivers.</p>

<p>Instead of processing the strings in the shader program, this solution depends
on a new compile-time feature I’ve prototyped in the DirectXShaderCompiler and
Clang, which collects all the strings in a shader into a packed de-duplicated
string table, and converts strings to offsets into the table via a compile-time
evaluated builtin function (<code class="language-plaintext highlighter-rouge">__builtin_hlsl_string_to_offset</code>).</p>

<p>With these features <code class="language-plaintext highlighter-rouge">printf</code> is entirely implemented in HLSL. The actual
implementation from my prototype is:</p>

<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span><span class="o">...</span> <span class="nc">T</span><span class="p">&gt;</span> <span class="kt">void</span> <span class="nf">printf</span><span class="p">(</span><span class="n">string</span> <span class="n">Str</span><span class="p">,</span> <span class="n">T</span><span class="p">...</span> <span class="n">Args</span><span class="p">)</span> <span class="p">{</span>
  <span class="n">uint</span> <span class="n">ThreadIndex</span> <span class="o">=</span> <span class="n">WavePrefixSum</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
  <span class="n">uint</span> <span class="n">ThreadCount</span> <span class="o">=</span> <span class="n">WaveActiveSum</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
  <span class="n">uint</span> <span class="n">StrOffset</span> <span class="o">=</span> <span class="n">__builtin_hlsl_string_to_offset</span><span class="p">(</span><span class="n">Str</span><span class="p">);</span>
  <span class="n">uint</span> <span class="n">ArgSize</span> <span class="o">=</span> <span class="n">NumDwords</span><span class="o">&lt;</span><span class="n">T</span><span class="p">...</span><span class="o">&gt;</span><span class="p">()</span> <span class="o">*</span> <span class="mi">4</span><span class="p">;</span>
  <span class="n">uint</span> <span class="n">MessageSize</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">MessagePrefix</span><span class="p">)</span> <span class="o">+</span> <span class="p">(</span><span class="n">ThreadCount</span> <span class="o">*</span> <span class="n">ArgSize</span><span class="p">);</span>
  <span class="n">uint</span> <span class="n">StartOffset</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">WaveIsFirstLane</span><span class="p">())</span> <span class="p">{</span>
    <span class="n">InterlockedAdd</span><span class="p">(</span><span class="n">OutputOffset</span><span class="p">,</span> <span class="n">MessageSize</span><span class="p">,</span> <span class="n">StartOffset</span><span class="p">);</span>
    <span class="n">MessagePrefix</span> <span class="n">Prefix</span> <span class="o">=</span> <span class="p">{</span><span class="n">ThreadCount</span><span class="p">,</span> <span class="n">StrOffset</span><span class="p">,</span> <span class="n">ArgSize</span><span class="p">};</span>
    <span class="n">DebugOutput</span><span class="p">.</span><span class="n">Store</span><span class="o">&lt;</span><span class="n">MessagePrefix</span><span class="o">&gt;</span><span class="p">(</span><span class="n">StartOffset</span><span class="p">,</span> <span class="n">Prefix</span><span class="p">);</span>
  <span class="p">}</span>
  <span class="n">StartOffset</span> <span class="o">=</span> <span class="n">WaveReadLaneFirst</span><span class="p">(</span><span class="n">StartOffset</span><span class="p">);</span>
  <span class="n">uint</span> <span class="n">ThreadOffset</span> <span class="o">=</span>
      <span class="n">StartOffset</span> <span class="o">+</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">MessagePrefix</span><span class="p">)</span> <span class="o">+</span> <span class="p">(</span><span class="n">ThreadIndex</span> <span class="o">*</span> <span class="n">ArgSize</span><span class="p">);</span>
  <span class="n">StoreArgs</span><span class="p">(</span><span class="n">DebugOutput</span><span class="p">,</span> <span class="n">ThreadOffset</span><span class="p">,</span> <span class="n">Args</span><span class="p">...);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>This function writes into a <code class="language-plaintext highlighter-rouge">RWByteAddressBuffer</code> the number of threads
participating in the print, the offset of the format string, and the size of the
per-thread argument lists. It then writes the per-thread argument list. Each
argument takes one or more 32-bit dwords, The current implementation does
mis-align 64-bit types, because I’m lazy, and there are a few other missing
features and improvements that I’d want to include if we pursued a solution like
this in the future.</p>

<h3 id="problem-space-hlsl-isnt-ready-yet">Problem Space: HLSL isn’t ready (yet)</h3>

<p>You may have noticed from the code above that this uses a feature of C++ that
doesn’t exist in HLSL (yet): variadic templates. Argument packing for <code class="language-plaintext highlighter-rouge">printf</code>
is an interesting problem. The way that variable argument lists work in C
<em>really</em> won’t work on a GPU. It involves packing arguments into effectively an
untyped stack-allocated array and walking the array with the format string to
determine the types.</p>

<p>For a GPU program we want as much of the packing/unpacking to happen at compile
time as possible. Templates are ideal for this since they’re fully resolved
early in the compiler at compile time.</p>

<p>Adding variadic template support to DXC turned out to be unexpectedly easy
because of how Clang implements new C++ language features. When a C++ language
feature does not add incompatibilities with pre-existing language rules and is
strictly additive, the Clang maintainers add the feature in all previous C++
language modes, and issue warnings for using the feature in older modes. This
means that all the functionality for resolving variadic templates in the AST was
already present in DXC. Re-enabling the support required enabling the parsing
logic for parameter packs (<code class="language-plaintext highlighter-rouge">...</code>), and everything else just mostly worked.</p>

<p>A second problem that I encountered bringing this to DXC was the implementation
of the <code class="language-plaintext highlighter-rouge">string</code> type. Many users would probably be surprised to know that HLSL
does have a <code class="language-plaintext highlighter-rouge">string</code> type, it’s just extremely limited in what you can do with
it. Today it is used almost exclusively for specifying root signatures in
raytracing shaders.</p>

<p>They are effectively <code class="language-plaintext highlighter-rouge">static const char *</code> variables in the raytracing
subobject, and they’re disallowed in almost every other semantic context. For
this I evolved <code class="language-plaintext highlighter-rouge">string</code> objects so they can be parameters to functions. They’re
still just <code class="language-plaintext highlighter-rouge">const char*</code> pointers (I even fixed a few bugs relating to their
const-ness), and they’re passed as pointers rather than copy-in/copy-out.</p>

<p>This slight generalization of string handling allows <code class="language-plaintext highlighter-rouge">printf</code> to become a fully
software implemented feature.</p>

<h2 id="bringing-it-together">Bringing it Together</h2>

<p>The full implementation of my <code class="language-plaintext highlighter-rouge">printf</code> prototype for HLSL can be found in my
<a href="https://github.com/microsoft/DirectXShaderCompiler/compare/main...llvm-beanz:DirectXShaderCompiler:cbieneman/strtab">fork of
DXC</a>.
The main bits of it are the compiler changes to implement
<code class="language-plaintext highlighter-rouge">__builtin_hlsl_string_to_offset</code>, and the new
<a href="https://github.com/microsoft/DirectXShaderCompiler/compare/main...llvm-beanz:DirectXShaderCompiler:cbieneman/strtab#diff-08dfb201ad90cb4f6d2c4de26c0a51c60505b20b9c4e739657d5393e5d7d14b4"><code class="language-plaintext highlighter-rouge">printf.h</code></a>.</p>

<p>In addition to the changes in my fork of DXC I’ve also implemented the string
format handling in my <a href="https://github.com/llvm/offload-test-suite/compare/main...llvm-beanz:offload-test-suite:cbieneman/printf">fork of our test
suite</a>.</p>

<p>In a future where this solution becomes generally supported, I would expect to
have the HLSL toolchain vend both the HLSL language functionality <em>and</em> a
permissively licensed string format implementation that could be used by any
application developer. There’s also nothing intrinsic about how the formatting
is interpreted to the system, so it is also possible that a developer could use
their own formatting logic with their own format specifiers. This could provide
a lot of flexibility to users.</p>

<p>One big caveat: as I mentioned at the beginning the ordering of messages is
pretty dependent on compiler optimizations and the hardware you run on. You
can’t depend on any given ordering since the atomic operations used to grab
space in the output buffer doesn’t have strict ordering guarantees and wave
scheduling is largely undefined.</p>

<p>Despite that, this proof-of-concept implementation does work today on any
retail DirectX 12 driver that supports Shader Model 6.0 or later.</p>

<h2 id="future-challenges">Future Challenges</h2>

<p>Bringing this into the core of the HLSL language and compiler has a few
roadblocks. The main missing language features are variadic templates, and
more general <code class="language-plaintext highlighter-rouge">string</code> types. We have had discussions about adding variadic
templates as part of the plan to adopt <a href="https://github.com/microsoft/hlsl-specs/blob/main/proposals/0023-cxx11-base.md">C++11 as the base of
HLSL</a>.</p>

<p>The issues around the <code class="language-plaintext highlighter-rouge">string</code> type are a bit harder to figure out. The way
strings are used in HLSL today is a bit magic and ill-defined. We’ll really need
to spend some time documenting and defining the <code class="language-plaintext highlighter-rouge">string</code> object and the syntax
and semantics of raytracing root signatures to figure out the best way to
support this going forward. I believe there is a relatively straight forward
path here, but we’ll need to spend some time working on it.</p>

<p>I fully expect that my prototype implementation will work with Clang in the
near-ish future as the missing HLSL features are all in progress, but DXC
support is a bit trickier. While I’ve demonstrated that it can work in my
proof-of-concept implementation, I’ve worked around a few gnarly bugs in DXC to
do so. DXC does some <a href="https://github.com/microsoft/DirectXShaderCompiler/compare/main...llvm-beanz:DirectXShaderCompiler:cbieneman/strtab">very strange things during
codegen</a>
for function parameters, that needed to be reverted back to the original Clang
code. This makes my prototype work, but causes some of our other tests to fail
and I haven’t had a chance to investigate.</p>

<p>There are also some limitations in the current DXC implementation around how
format strings can and can’t be used, which may be more restrictive than we
really want, and I’d like to at least consider alternatives. Specifically, the
current implementation requires that format strings be uniform across all
threads, and there might be value in allowing them to be thread-divergent. DXC
also doesn’t really support creating local variables of <code class="language-plaintext highlighter-rouge">string</code> types, which
means you can’t have more general logic to select format strings. Enabling some
of these cases will also require that the string lowering IR pass I wrote gain
some complexity as well.</p>

<p>I’ve also thought about a slight adjustments that we may want to consider. The
current <code class="language-plaintext highlighter-rouge">printf</code> implementation depends on a <code class="language-plaintext highlighter-rouge">groupshared uint</code> for the counter.
We could instead support the counter being the first four bytes of the
<code class="language-plaintext highlighter-rouge">RWByteAddressBuffer</code> this has a potential benefit that the resulting resources
would contain the total amount of data written to the buffer and it saves 4
bytes of <code class="language-plaintext highlighter-rouge">groupshared</code> memory, but would be slower during execution. My gut
feeling is that stealing 4 bytes of <code class="language-plaintext highlighter-rouge">groupshared</code> memory is better, but we could
make the implementation work both ways.</p>

<p>Another big area that I haven’t thought about much is how to bring this to
Vulkan and Metal shaders. One nice thing about the DirectX object file format is
that it has named sections, so the string table can be its own section that the
runtime and tools see but is never passed to drivers.</p>

<p>SPIRV has no such separation. To support this in SPIRV we’d likely need to
create an annotation instruction that contains the string table and parse the
string table out of the SPIRV. Not really a big deal, but unfortunate.</p>

<p>For Metal there are a couple different approaches we could take. One would be to
tie this into the <a href="https://developer.apple.com/documentation/metal/logging-shader-debug-messages">Metal logging
system</a>.
If we wanted to have a unified portable system we’d need some way to attach the
string table into the Metal library, or carry the data alongside the shader.
This is not the only case where we’re needing to carry side-metadata along with
shaders for Metal, so we may need to think more generally about this problem in
the future. If only the Metal Shader Converter were open source, then we could
make the string table a user-defined attribute on the shader, but alas…</p>]]></content><author><name>Chris Bieneman</name></author><summary type="html"><![CDATA[Bringing the best form of debugging to shaders!]]></summary></entry><entry><title type="html">State of HLSL: February 2025</title><link href="https://abolishcrlf.org//2025/02/17/HLSLState.html" rel="alternate" type="text/html" title="State of HLSL: February 2025" /><published>2025-02-17T20:00:00+00:00</published><updated>2025-02-17T20:00:00+00:00</updated><id>https://abolishcrlf.org//2025/02/17/HLSLState</id><content type="html" xml:base="https://abolishcrlf.org//2025/02/17/HLSLState.html"><![CDATA[<h1 id="state-of-hlsl-february-2025">State of HLSL: February 2025</h1>

<p>Looking back, 2024 was a big year for HLSL. <a href="https://devblogs.microsoft.com/directx/agility-sdk-1-613-0/">Shader Model 6.8 went
retail</a>, a <a href="https://devblogs.microsoft.com/directx/d3d12-mesh-nodes-in-work-graphs/">Work
Graphs Mesh Nodes Preview was
released</a>,
the <a href="https://devblogs.microsoft.com/directx/open-sourcing-dxil-validator-hash/">DXIL Validator was open
sourced</a>,
<a href="https://devblogs.microsoft.com/directx/directx-adopting-spir-v/">DirectX announced plans to adopt
SPIRV</a>, and in
news you probably missed: simple HLSL shaders compiled with Clang built from
<code class="language-plaintext highlighter-rouge">main</code>, successfully ran on GPUs for the first time!</p>

<p>That last milestone probably mostly escaped notice, but it was a really huge
achievement and I want to take some time to explore the state of HLSL in Clang
to show some of the great things that we’re working on right under your nose
that you might not be aware of.</p>

<h2 id="status-of-hlsl-in-clang">Status of HLSL in Clang</h2>

<p>Today we have a handful of <em>extremely</em> simple HLSL compute shaders that compile
successfully in Clang. Clang supports the basic syntax and semantics of HLSL, a
reasonable sampling of the HLSL intrinsic functions, and a couple basic resource
types. Clang is not nearly ready for use by developers, but we’re a few weeks
away from compiling compute shaders from an internal trove of production code.</p>

<p>Despite the early state of the compiler there are a few improvements over DXC
that we can already demonstrate.</p>

<h3 id="addressing-design-bugs">Addressing Design Bugs</h3>

<p>DXC has a significant number of bugs that exist because either the design of
HLSL or design decisions made during DXC’s implementation. In some cases, like
the HLSL 202x <a href="https://github.com/microsoft/hlsl-specs/blob/main/proposals/0017-conforming-literals.md">Conforming
Literals</a>
feature, we can fix the issue in DXC and implement the correct solution in
Clang. In other cases, the fixes in DXC are very complicated and would require
invasive changes to DXC.</p>

<p>For an example of the later case consider DXC issue
<a href="https://github.com/microsoft/DirectXShaderCompiler/issues/4871">#4871</a>. This
issue occurs because of problems in DXC’s design for implementing HLSL’s
by-value calling convention. In Clang, we’ve prioritized full and accurate AST
representations which enable us to handle these problems more robustly.</p>

<h3 id="improved-diagnostics">Improved diagnostics</h3>

<p>HLSL has a lot of implicit behavior which it has carried from its origins as a
domain-specific language. Users have found it useful to be aware of implicit
behavior, like implicit conversions, since they can have a runtime performance
impact. Unfortunately DXC doesn’t always have the ability to diagnose implicit
conversions because they are not captured in the AST.</p>

<p>In the example below, Clang will warn about the implicit conversion of <code class="language-plaintext highlighter-rouge">F</code> from
a <code class="language-plaintext highlighter-rouge">float4</code> to an <code class="language-plaintext highlighter-rouge">int4</code> <em>and</em> the implicit conversion on return of the <code class="language-plaintext highlighter-rouge">int4</code>
back to the <code class="language-plaintext highlighter-rouge">float4</code>. Meanwhile DXC will perform the conversions with no
diagnostics.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>void SillyTrunc(inout int4) {}

export float4 Trunc(float4 F) {
    SillyTrunc(F);
    return F;
}
</code></pre></div></div>
<p><a href="https://godbolt.org/z/xffPqd8ne">Compiler Explorer</a></p>

<h3 id="language-server">Language Server</h3>

<p>Clang comes with a production implementation of Language Server Protocol which
is used to power IDE tooling through a JSON-RPC interface that is widely adopted
by a large number of code editors.</p>

<p>In our efforts to add HLSL support to Clang we’ve also gained a working LSP
server with minimal investment. We plan to continue working on QoL improvements
to make <code class="language-plaintext highlighter-rouge">clangd</code>’s HLSL support production ready, but even with our minimal
investments we’re already seeing promising results!</p>

<p><img src="https://abolishcrlf.org/assets/images/clangd-vim.png" /></p>

<h3 id="experimental-language-features">Experimental Language Features</h3>

<p>As we’re working on Clang we’re also not ripping out all of C++’s features.
We’ve been leaving C++ features that we want to add to HLSL working in Clang.
This simple shader utilizes both C++’s <code class="language-plaintext highlighter-rouge">auto</code> keyword <em>and</em> C++ lambdas. Clang
can successfully compile this to valid DXIL!</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>RWBuffer&lt;int4&gt; In : register(u0);
RWBuffer&lt;int4&gt; Out : register(u1);

int reduceSum(int4 V) {
    auto R = [](int LHS, int RHS) -&gt; int {
        return LHS + RHS;
    };
    return R(V.x, R(V.y, R(V.z, V.w)));
}

[numthreads(8,1,1)]
void main(uint GI : SV_GroupIndex) {
    Out[GI] = reduceSum(In[GI]).xxxx;
}
</code></pre></div></div>
<p><a href="https://godbolt.org/z/9d9vxvhn8">Compiler Explorer</a></p>

<p>Another frequently requested feature in HLSL is C++’s <code class="language-plaintext highlighter-rouge">constexpr</code>. In Clang,
we’re using <code class="language-plaintext highlighter-rouge">constexpr</code> as a vital implementation tool to ensure constant
evaluation of complex math operations. We’re extending <code class="language-plaintext highlighter-rouge">constexpr</code> support in
Clang to include HLSL’s vector types and implicit conversions so that HLSL
expressions can fully leverage the feature. For example the HLSL
<code class="language-plaintext highlighter-rouge">D3DCOLORtoUBYTE4</code> function is implemented as a <code class="language-plaintext highlighter-rouge">constexpr</code>:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>constexpr vector&lt;uint, 4&gt; D3DCOLORtoUBYTE4(vector&lt;float, 4&gt; V) {
  return V.zyxw * 255.001953f;
}
</code></pre></div></div>

<p>This evaluation includes the implicit scalar to vector conversion and the
evaluation of the vector constant expression.</p>

<h2 id="language-evolution">Language Evolution</h2>

<p>Something else that happened in 2024 that may have escaped notice was the first
approved and implemented feature for the next version of HLSL.</p>

<h3 id="hlsl-202x">HLSL 202x</h3>

<p>The next version of HLSL is codenamed 202x, and it will serve as a bridge
between DXC and Clang. We’re realistic that the two compilers will never be
fully identical, but 202x will allow us to move DXC toward Clang and Clang
toward DXC. This gives us the ability to deprecate some problematic features of
HLSL during the compiler transition while providing a graceful path for users.
We expect that shaders which compile successfully with HLSL 202x in DXC will
compile successfully in Clang with little to no adjustment required.</p>

<p>The first feature added in HLSL 202x was <a href="https://github.com/microsoft/hlsl-specs/blob/main/proposals/0017-conforming-literals.md">0017 Conforming
Literals</a>,
which addressed a number of bugs in DXC that were caused by the complicated way
DXC assigned types to integer and floating point literals.</p>

<h3 id="hlsl-202y">HLSL 202y</h3>

<p>In addition to planning our bridging release, we’ve also been planning our next
feature release, codenamed 202y, which will be available only in Clang. We
expect HLSL 202y will be a combination of new features and refinements of
existing HLSL.</p>

<p>As an example, two likely HLSL 202y features are <a href="https://github.com/microsoft/hlsl-specs/blob/main/proposals/0007-const-instance-methods.md"><code class="language-plaintext highlighter-rouge">const</code> non-static member
functions</a>,
and <a href="https://github.com/microsoft/hlsl-specs/blob/main/proposals/0008-non-member-operator-overloading.md">non-member operator
overloading</a>.
Both of these features require significant changes to how and when overload
resolution occurs in HLSL. These features will necessitate adopting overload
resolution rules more like C++, which will break source compatibility for some
code.</p>

<p>Another feature that has been frequently requested is <a href="https://github.com/microsoft/hlsl-specs/pull/325">C++
constructors</a>, which will
require addressing our <a href="https://github.com/microsoft/hlsl-specs/blob/main/proposals/0005-strict-initializer-lists.md">initialization list
handling</a>.</p>

<p>While we expect that these features will cause some disruption to existing HLSL
codebases, we believe all of these features will deliver on highly demanded user
requests, while improving the familiarity of HLSL. The disruptive refinements to
the base language will also enable us to add other frequently requested features
like <a href="https://github.com/microsoft/hlsl-specs/blob/main/proposals/0004-unions.md"><code class="language-plaintext highlighter-rouge">union</code>
types</a>,
<a href="https://github.com/microsoft/DirectXShaderCompiler/issues/4096">conversion
operators</a>, and
<a href="https://github.com/microsoft/hlsl-specs/issues/394">access specifiers</a>.</p>

<h3 id="public-design-process">Public Design Process</h3>

<p>One last big change that we were working on at the end of 2024 and are just
getting rolling in 2025 is an expansion of our <a href="https://github.com/microsoft/hlsl-specs/blob/main/docs/Process.md">public language design
process</a>.</p>

<p>We’ve had difficulty ensuring that proposals move through the process smoothly.
We also have found that we need a wide variety of input in order to maintain
high quality for all our design specifications. To address both of these issues
we’ve started hosting regular <a href="https://github.com/microsoft/hlsl-specs/blob/main/docs/DesignMeeting.md">public design
meetings</a>.</p>

<p>This provides a tactical forum for us to coordinate shepherding proposals
through the language evolution process, and it allows us to have a space to
discuss changes with a wider audience of stakeholders. We’re optimistic that
these public meetings will help us drive a more open and public collaboration to
evolve HLSL.</p>]]></content><author><name>Chris Bieneman</name></author><summary type="html"><![CDATA[Where we are and where we're going]]></summary></entry></feed>