英文:
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<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;
}
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论