Skip to content

Draft: vkd3d-shader/hlsl: Only use the temp copy for uniform components that are written.

Patch 1/4 is just !1364 (merged), which I need so that tests don't segfault on my machine.


Because it is possible to store values in uniforms in HLSL what we are currently doing is turning the uniform variable into a temp, creating a uniform copy of the variable, and storing that uniform into the temp at the beginning of the program in prepend_uniform_copy().

This however has a couple of problems:

  • The uniform load is at the beginning of the program, so it must live in a temp register for a long time, even if the loads to the temp are copy-propagated into it.
  • If we access the uniform variable with a dynamic index load, copy-prop can't lower dynamic indexes, so dynamic loads always are done from the temp and cannot be traced back to the uniform load. This is a problem because SM1 vertex shaders can do relative addressing (yet to be implemented) but only directly from the uniform ('c' registers), not from a temp ('r' registers). It is worth noting that dynamic stores are not allowed on uniforms on any shader model.

Patch 3/4 takes care of actually using the uniform variable whenever possible and only defer stores (and subsequent derefs) to the temp when needed, and only to the affected components. For this, some of the copy-prop machinery is required.

This lowers the number of required temp registers for the following shader from 12 (+1 big indexable) to 2 (+1 big indexable) on ps_4_0, and from 24 to 17 on ps_2_0:

int i;
float3x3 mats[4];

float4 main() : sv_target
{
    return mul(mats[i], float3(1, 2, 3)).xyzz;
}

Patch 4/4 contains a simple optimization for SM1 that further lowers this number of temp registers from 17 to 14 on ps_2_0.


The next step I see for SM1 vertex shader relative addressing (and with the benefit of temp optimization) is make it so that loads to uniforms don't allocate a temp register both in SM1 and SM4 and when lowering srcs to vsir we can detect when the src is to a uniform load and directly refer to the pertaining register of the uniform variable.

I also tried the idea of, every time an instruction has a deref to a load from a uniform variable, creating a copy of the load right before the instruction and refer to it, so uniform loads have to stay as little time as possible using a temp. This approach is tested in my tmp_optimization branch and it lowers the number of temp registers required in the shader above to 4 in ps_2_0 like the native compiler, but probably will be redundant considering the previous one or future vsir optimization passes.

Edited by Francisco Casas

Merge request reports

Loading