[prev in list] [next in list] [prev in thread] [next in thread] 

List:       wine-devel
Subject:    Re: [vkd3d] Handling object components within the HLSL compiler.
From:       Francisco Casas <fcasas () codeweavers ! com>
Date:       2022-08-31 23:52:20
Message-ID: b26800a5-1422-75b9-7383-fa4240f81fa8 () codeweavers ! com
[Download RAW message or body]


On 31-08-22 14:12, Zebediah Figura wrote:
> I don't think I understand the point of splitting uniforms for sm4 but 
> not sm1. If we need to determine (and potentially store) the actual type 
> of a uniform per-component anyway, why would we need to do that 
> differently for structs and arrays?
> 

Well, first, I don't think we should split uniforms completely, only 
separate the object components as standalone variables.

So, if we have, say

struct {
   float4 foo;
   Texture2D tex[2];
   float4 bar;
} pou;

We would be effectively end up with 3 variables:

The original:

---
struct {
   float4 foo;
   Texture2D tex[2];
   float4 bar;
} pou;
---

and:

---
Texture2D "pou.tex[0]";
Texture2D "pou.tex[1]";
---

because we would be adding a store from the "pou.tex[0]" variable to 
pou.tex[0], and from the "pou.tex[1]" variable to pou.tex[1], copy-prop 
should replace all derefs to the Texture components to derefs to these 
new variables.

The pou variable no longer has to worry about the register allocation of 
its Texture fields, because the new variables do that.

Generalizing, variables should no longer care about their object 
components, unless they are objects themselves.

I think something similar happens under the hood in SM4, consider the 
output of the following shader in the native compiler:

---
struct {
   float4 foo;
   Texture2D tex[2];
   float4 bar;
} pou;

float4 main() : SV_TARGET
{
	return pou.bar + pou.tex[0].Load(int3(1, 2, 3)) + 
pou.tex[1].Load(int3(1, 2, 3));
}
---

---
// Buffer Definitions:
//
// cbuffer $Globals
// {
//
//   struct <unnamed>
//   {
//
//       float4 foo;                    // Offset:    0
//       float4 bar;                    // Offset:   16
//
//   } pou;                             // Offset:    0 Size:    32
                                         // Textures:  t0-t1
//
// }
//
//
// Resource Bindings:
//
// Name                   Type      Format  Dim       HLSL Bind Count
// --------------------- ---------- ------- --------  --------- ------
// pou.tex[0]            texture    float4        2d         t0      1
// pou.tex[1]            texture    float4        2d         t1      1
// $Globals              cbuffer        NA        NA        cb0      1
---

Object components are listed separately in the resource bindings, and 
they are efectively removed (or ignored?) in the definition of pou.


Now, regarding SM1, it is not possible to declare objects inside other 
components, it is only possible to create (possibly multi-dimensional) 
arrays of single object types:

---
sampler sam[3][2];

float4 main() : SV_TARGET
{
	return tex2D(sam[2][1], float2(1, 2));
}
---

but they don't appear as different variables in the CTAB section:

---
// Parameters:
//
//   sampler2D sam[6];
//
//
// Registers:
//
//   Name         Reg   Size
//   ------------ ----- ----
//   sam          s0       6
//
---

Unlike in SM4:
---
// Resource Bindings:
//
// Name                     Type     Format   Dim   Slot Elements
// ------------------------ -------- ------- ------ ---- --------
// sam[2][1]                 sampler     NA     NA     5        1
// sam[2][1]                 texture float4     2d     5        1
---
(to get this output I used fxc 9 with compatibility mode)


So, in summary, my idea is to:

- For SM4, separate object components as stand-alone variables that take 
care of the register allocation of these individual objects.
- For SM1, just support (possibly multi-dimensional) object arrays.


With this, for both SM1 and SM4, each variable should only care about 
the allocation of a single type of register, so we can use the register 
offsets as we do now.
In the future we would probably want to remove the "offset" field from 
the derefs, and make each hlsl_sm*.c compute the register offsets from 
the derefs in their index path form.



[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic