Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SPIR-V -> HLSL : cross compiling bindings overlap #2064

Open
Try opened this issue Nov 22, 2022 · 2 comments
Open

SPIR-V -> HLSL : cross compiling bindings overlap #2064

Try opened this issue Nov 22, 2022 · 2 comments

Comments

@Try
Copy link
Contributor

Try commented Nov 22, 2022

Simple reproducer:

#version 460

layout (location = 0) out vec4 fragColor;

layout(binding = 0, std430) readonly buffer A { vec4 a[]; };
layout(binding = 0, std430) readonly buffer B { uint b[]; };

void main()
{
	fragColor = vec4(0.4, 0.4, 0.8, 1.0);
}

Been cross-compiled to HLSL as:

// error: resource _22 at register 0 overlaps with resource _17 at register 0, space 0
ByteAddressBuffer _17 : register(t0);
ByteAddressBuffer _22 : register(t0);
...

Seemingly there is 'simple' solution for SSBO - to use only a single binding. However, I don't know, if there is a solution for textures.
Any opinions on should this be implemented in any way or not? Thanks!

@HansKristian-Work
Copy link
Contributor

Would need similar hacks as MSL where multiple OpVariables alias the same binding. This breaks down if different qualifiers like globallycoherent are applied though.

Textures won't work here. Need to stamp out different space variables that application root signature must resolve. Descriptor aliasing really isn't feasible with HLSL.

@Try
Copy link
Contributor Author

Try commented Oct 16, 2023

Would need similar hacks as MSL where multiple OpVariables alias the same binding

I've checked MSL codegen and it doesn't look quite right:
https://shader-playground.timjones.io/b4739d6b673576df6b38fb0ad49bc48c

In generated shader there is an issue: buffer now consumes multiple bind-points, what is a problem for engine (and also defeat the purpose of feature).
In my end, engine exposes maxBuffers/maxTextures so consuming extra bind-point will break abstraction.

Proposed change (buffers only):

HLSL merge qualifiers:

readonly + writeonly = RWByteAddressBuffer
if any of overlapped buffers is coherent, then globallycoherent will be used on merged binding.

Overlap of multiple uniform buffers, can be compiled as:

cbuffer M : register(b0)
{
    uint _data_16_26[MAX_OF_SIZES/4];
};

static const A _16 = (A)_data_16_26; // need to be careful about structure declaration, assuming tight packing here
static const B _26 = (B)_data_16_26;

MSL use reinterpret_cast:

fragment main0_out main0(device A& _14 [[buffer (0)]])
{
    const    device B& _15 = reinterpret_cast<const device B&>(_14);
    volatile device C& _16 = reinterpret_cast<volatile device C&>(_14);
             device D& _17 = reinterpret_cast<device D&>(_14);

It' possible to use const_cast as well, if needed.
Uniform/Storage overlap is more tricky as shader is not allowed to cast from device to constant and vise-versa. Probably it's OK to promote constant to device on shader side, effectively turning uniform buffer into readonly storage buffer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants