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

Added support for offset glsl keyword. #86

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
/build*
/bin/*
/bin/*
/.vs
/.vscode
31 changes: 23 additions & 8 deletions spirv_reflect.c
Original file line number Diff line number Diff line change
Expand Up @@ -2055,9 +2055,19 @@ static SpvReflectResult ParseDescriptorBlockVariable(
return SPV_REFLECT_RESULT_SUCCESS;
}

static int SortCompareMembersOffset(const void* a, const void* b)
{
const SpvReflectBlockVariable* p_elem_a = (const SpvReflectBlockVariable*)a;
const SpvReflectBlockVariable* p_elem_b = (const SpvReflectBlockVariable*)b;
int value = (int)(p_elem_a->offset) - (int)(p_elem_b->offset);
assert(value != 0);
return value;
}

static SpvReflectResult ParseDescriptorBlockVariableSizes(
Parser* p_parser,
SpvReflectShaderModule* p_module,
uint32_t alignment,
bool is_parent_root,
bool is_parent_aos,
bool is_parent_rta,
Expand Down Expand Up @@ -2117,7 +2127,7 @@ static SpvReflectResult ParseDescriptorBlockVariableSizes(
// If array of structs, parse members first...
bool is_struct = (p_member_type->type_flags & SPV_REFLECT_TYPE_FLAG_STRUCT) == SPV_REFLECT_TYPE_FLAG_STRUCT;
if (is_struct) {
SpvReflectResult result = ParseDescriptorBlockVariableSizes(p_parser, p_module, false, true, is_parent_rta, p_member_var);
SpvReflectResult result = ParseDescriptorBlockVariableSizes(p_parser, p_module, alignment, false, true, is_parent_rta, p_member_var);
if (result != SPV_REFLECT_RESULT_SUCCESS) {
return result;
}
Expand All @@ -2134,7 +2144,7 @@ static SpvReflectResult ParseDescriptorBlockVariableSizes(
case SpvOpTypeRuntimeArray: {
bool is_struct = (p_member_type->type_flags & SPV_REFLECT_TYPE_FLAG_STRUCT) == SPV_REFLECT_TYPE_FLAG_STRUCT;
if (is_struct) {
SpvReflectResult result = ParseDescriptorBlockVariableSizes(p_parser, p_module, false, true, true, p_member_var);
SpvReflectResult result = ParseDescriptorBlockVariableSizes(p_parser, p_module, alignment, false, true, true, p_member_var);
if (result != SPV_REFLECT_RESULT_SUCCESS) {
return result;
}
Expand All @@ -2143,7 +2153,7 @@ static SpvReflectResult ParseDescriptorBlockVariableSizes(
break;

case SpvOpTypeStruct: {
SpvReflectResult result = ParseDescriptorBlockVariableSizes(p_parser, p_module, false, is_parent_aos, is_parent_rta, p_member_var);
SpvReflectResult result = ParseDescriptorBlockVariableSizes(p_parser, p_module, alignment, false, is_parent_aos, is_parent_rta, p_member_var);
if (result != SPV_REFLECT_RESULT_SUCCESS) {
return result;
}
Expand All @@ -2155,6 +2165,8 @@ static SpvReflectResult ParseDescriptorBlockVariableSizes(
}
}

qsort(p_var->members, p_var->member_count, sizeof(p_var->members[0]), SortCompareMembersOffset);

// Parse padded size using offset difference for all member except for the last entry...
for (uint32_t member_index = 0; member_index < (p_var->member_count - 1); ++member_index) {
SpvReflectBlockVariable* p_member_var = &p_var->members[member_index];
Expand All @@ -2167,11 +2179,10 @@ static SpvReflectResult ParseDescriptorBlockVariableSizes(
p_member_var->padded_size = p_member_var->size;
}
}
// ...last entry just gets rounded up to near multiple of SPIRV_DATA_ALIGNMENT, which is 16 and
// subtract the offset.
// ...last entry just gets rounded up to near multiple of alignment and subtract the offset.
if (p_var->member_count > 0) {
SpvReflectBlockVariable* p_member_var = &p_var->members[p_var->member_count - 1];
p_member_var->padded_size = RoundUp(p_member_var->offset + p_member_var->size, SPIRV_DATA_ALIGNMENT) - p_member_var->offset;
p_member_var->padded_size = RoundUp(p_member_var->offset + p_member_var->size, alignment) - p_member_var->offset;
if (p_member_var->size > p_member_var->padded_size) {
p_member_var->size = p_member_var->padded_size;
}
Expand Down Expand Up @@ -2322,7 +2333,7 @@ static SpvReflectResult ParseDescriptorBlocks(Parser* p_parser, SpvReflectShader
p_descriptor->block.name = p_descriptor->name;

bool is_parent_rta = (p_descriptor->descriptor_type == SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER);
result = ParseDescriptorBlockVariableSizes(p_parser, p_module, true, false, is_parent_rta, &p_descriptor->block);
result = ParseDescriptorBlockVariableSizes(p_parser, p_module, SPIRV_DATA_ALIGNMENT, true, false, is_parent_rta, &p_descriptor->block);
if (result != SPV_REFLECT_RESULT_SUCCESS) {
return result;
}
Expand Down Expand Up @@ -3021,11 +3032,15 @@ static SpvReflectResult ParsePushConstantBlocks(Parser* p_parser, SpvReflectShad
if (result != SPV_REFLECT_RESULT_SUCCESS) {
return result;
}
result = ParseDescriptorBlockVariableSizes(p_parser, p_module, true, false, false, p_push_constant);
result = ParseDescriptorBlockVariableSizes(p_parser, p_module, SPIRV_WORD_SIZE, true, false, false, p_push_constant);
if (result != SPV_REFLECT_RESULT_SUCCESS) {
return result;
}

p_push_constant->offset = p_push_constant->members[0].offset;
p_push_constant->size -= p_push_constant->offset;
p_push_constant->padded_size -= p_push_constant->offset;

++push_constant_index;
}

Expand Down
1 change: 1 addition & 0 deletions tests/build_all_shaders.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ def my_which(cmd):
{'source':"glsl/built_in_format.glsl", 'entry':"main", 'stage':'vert'},
{'source':"glsl/input_attachment.glsl", 'entry':"main", 'stage':'frag'},
{'source':"glsl/texel_buffer.glsl", 'entry':"main", 'stage':'vert'},
{'source':"glsl/struct_offset.glsl", 'entry':"main", 'stage':'vert'},

{'source':"hlsl/append_consume.hlsl", 'entry':"main", 'profile':'ps_6_0', 'stage':'frag'},
{'source':"hlsl/binding_array.hlsl", 'entry':"main", 'profile':'ps_6_0', 'stage':'frag'},
Expand Down
24 changes: 24 additions & 0 deletions tests/glsl/struct_offset.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#version 450

layout(location=0) in vec2 aPos;
layout(location=1) in vec2 aUV;

struct S
{
vec3 a;
vec2 b;
};

layout(push_constant) uniform uPushConstant { layout(offset = 8) vec2 uScale; float d2; layout(offset = 4) float d1;} vpc1;

layout(set=0, binding=0, std140) uniform uBuffer { layout(offset = 4) float d0; layout(offset = 16) vec2 uTranslate; layout(offset = 8) float d1;} vpc2;

out gl_PerVertex { vec4 gl_Position; };
layout(location = 0) out struct { vec2 Pos; vec2 UV; } Out;

void main(void)
{
Out.UV = aUV;
Out.Pos = aPos;
gl_Position = vec4(aPos * vpc1.uScale + vpc2.uTranslate, 0, 1);
}
Binary file added tests/glsl/struct_offset.spv
Binary file not shown.
Loading