HLSL编译使用shaderc,然后使用SPIRV-cross进行内省的大小错误?

huangapple go评论120阅读模式
英文:

HLSL compiled with shaderc and introspected with SPIRV-cross has wrong size?

问题

我正在编译这个着色器,使用shaderc将其转换为spirv,然后使用spirv-cross提取反射数据。我的程序认为ubo缓冲区的总大小为32字节,但一个4x4的浮点矩阵(每个元素4字节)应该有16字节,而不是32字节。

是否HLSL有严格的32字节对齐要求或类似的要求?

值得注意的是,以下的代码是有效的:

struct VSInput
{
    [[vk::location(0)]] float2 Pos : POSITION0;
    [[vk::location(1)]] float3 Color : COLOR0;
};

struct UBO
{
    vector<float, 4> transform;
};

ConstantBuffer<UBO> ubo : register(b0);

struct VSOutput
{
    float4 Pos : SV_POSITION;
    [[vk::location(0)]] float3 Color : COLOR0;
};

VSOutput main(VSInput input)
{
    float2x2 tmp = (float2x2) ubo.transform;
    VSOutput output = (VSOutput)0;
    output.Color = input.Color;

    output.Pos = float4(tmp * input.Pos.xy, 0, 1);
    return output;
}

这个HLSL着色器旨在直接翻译为GLSL的下面的代码:

#version 450
#extension GL_EXT_scalar_block_layout : enable

layout(location = 0) in vec2 inPosition;
layout(location = 1) in vec3 inColor;

layout(location = 0) out vec3 fragColor;

layout(binding = 0, scalar) uniform MatUBO
{
    mat2 transform;
};

void main() {
    gl_Position = vec4(transform * inPosition, 0.5, 1.0);
    fragColor = inColor;
}

希望这些信息对你有所帮助。

英文:

I am compiling this shader

struct VSInput
{
[[vk::location(0)]] float2 Pos : POSITION0;
[[vk::location(1)]] float3 Color : COLOR0;
};

struct UBO
{
	float2x2 transform;
};

cbuffer ubo : register(b0) { UBO ubo; }

struct VSOutput
{
	float4 Pos : SV_POSITION;
	[[vk::location(0)]] float3 Color : COLOR0;
};

VSOutput main(VSInput input)
{
	VSOutput output = (VSOutput)0;
	output.Color = input.Color;
	output.Pos = float4(ubo.transform * input.Pos.xy, 0, 1);
	return output;
}

To spirv using shaderc then extracting reflection data with spirv-cross. My program thinks the ubo buffer has a total size of 32 bytes, but a 2x2 = 4 matrix of floats (4 bytes) should have 16 bytes, not 32.

Does HLSL have strict 32 byte alignment requirements or something like that?

For the record this works:

struct VSInput
{
[[vk::location(0)]] float2 Pos : POSITION0;
[[vk::location(1)]] float3 Color : COLOR0;
};

struct UBO
{
	vector&lt;float, 4&gt; transform;
};

ConstantBuffer&lt;UBO&gt; ubo : register(b0);

struct VSOutput
{
	float4 Pos : SV_POSITION;
	[[vk::location(0)]] float3 Color : COLOR0;
};

VSOutput main(VSInput input)
{
	float2x2 tmp = (float2x2) ubo.transform;
	VSOutput output = (VSOutput)0;
	output.Color = input.Color;
	
	output.Pos = float4(tmp * input.Pos.xy, 0, 1);
	return output;
}

This hlsl shader is meant to be a direct translation of this GLSL one:

#version 450
#extension GL_EXT_scalar_block_layout : enable

layout(location = 0) in vec2 inPosition;
layout(location = 1) in vec3 inColor;

layout(location = 0) out vec3 fragColor;

layout(binding = 0, scalar) uniform MatUBO
{
    mat2 transform;
};

void main() {
    gl_Position = vec4(transform * inPosition, 0.5, 1.0);
    fragColor = inColor;
}

答案1

得分: 1

但是一个2x2的浮点矩阵(4字节)应该有16字节,而不是32字节。

这不是UBO数组对齐的工作方式。 Vulkan默认情况下使用std140布局来限制统一缓冲区的布局。因此,统一块的布局将遵循这个规定。

UBO中的矩阵实际上是向量数组。而std140布局中的数组始终具有16字节的数组步幅。因此,您的UBO为32字节。

英文:

> but a 2x2 = 4 matrix of floats (4 bytes) should have 16 bytes, not 32.

That's not how UBO alignment of arrays works. Vulkan, by default, operates under the limitations of std140 layout for uniform buffers. Therefore, the layout of uniform blocks will conform to that.

Matrices in a UBO are effectively arrays of vectors. And arrays in std140 layout always have an array stride of 16 bytes. Therefore, your UBO is 32 bytes.

huangapple
  • 本文由 发表于 2023年3月7日 04:35:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/75655581.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定