// File: /workspace/github_cpp_makefile_star2_O1/rossy[P]crossc/SPIRV-Cross/spirv_glsl.cpp
// Function: spirv_cross::CompilerGLSL::buffer_is_packing_standard(spirv_cross::SPIRType const&, spirv_cross::BufferPackingStandard, unsigned int, unsigned int)
bool CompilerGLSL::buffer_is_packing_standard(const SPIRType &type, BufferPackingStandard packing,
                                              uint32_t start_offset, uint32_t end_offset)
{
	// This is very tricky and error prone, but try to be exhaustive and correct here.
	// SPIR-V doesn't directly say if we're using std430 or std140.
	// SPIR-V communicates this using Offset and ArrayStride decorations (which is what really matters),
	// so we have to try to infer whether or not the original GLSL source was std140 or std430 based on this information.
	// We do not have to consider shared or packed since these layouts are not allowed in Vulkan SPIR-V (they are useless anyways, and custom offsets would do the same thing).
	//
	// It is almost certain that we're using std430, but it gets tricky with arrays in particular.
	// We will assume std430, but infer std140 if we can prove the struct is not compliant with std430.
	//
	// The only two differences between std140 and std430 are related to padding alignment/array stride
	// in arrays and structs. In std140 they take minimum vec4 alignment.
	// std430 only removes the vec4 requirement.

	uint32_t offset = 0;
	uint32_t pad_alignment = 1;

	for (uint32_t i = 0; i < type.member_types.size(); i++)
	{
		auto &memb_type = get<SPIRType>(type.member_types[i]);
		auto member_flags = ir.meta[type.self].members.at(i).decoration_flags;

		// Verify alignment rules.
		uint32_t packed_alignment = type_to_packed_alignment(memb_type, member_flags, packing);
		uint32_t packed_size = type_to_packed_size(memb_type, member_flags, packing);

		if (packing_is_hlsl(packing))
		{
			// If a member straddles across a vec4 boundary, alignment is actually vec4.
			uint32_t begin_word = offset / 16;
			uint32_t end_word = (offset + packed_size - 1) / 16;
			if (begin_word != end_word)
				packed_alignment = max(packed_alignment, 16u);
		}

		uint32_t alignment = max(packed_alignment, pad_alignment);
		offset = (offset + alignment - 1) & ~(alignment - 1);

		// Field is not in the specified range anymore and we can ignore any further fields.
		if (offset >= end_offset)
			break;

		// The next member following a struct member is aligned to the base alignment of the struct that came before.
		// GL 4.5 spec, 7.6.2.2.
		if (memb_type.basetype == SPIRType::Struct)
			pad_alignment = packed_alignment;
		else
			pad_alignment = 1;

		// Only care about packing if we are in the given range
		if (offset >= start_offset)
		{
			// We only care about offsets in std140, std430, etc ...
			// For EnhancedLayout variants, we have the flexibility to choose our own offsets.
			if (!packing_has_flexible_offset(packing))
			{
				uint32_t actual_offset = type_struct_member_offset(type, i);
				if (actual_offset != offset) // This cannot be the packing we're looking for.
					return false;
			}

			// Verify array stride rules.
			if (!memb_type.array.empty() && type_to_packed_array_stride(memb_type, member_flags, packing) !=
			                                    type_struct_member_array_stride(type, i))
				return false;

			// Verify that sub-structs also follow packing rules.
			// We cannot use enhanced layouts on substructs, so they better be up to spec.
			auto substruct_packing = packing_to_substruct_packing(packing);

			if (!memb_type.member_types.empty() && !buffer_is_packing_standard(memb_type, substruct_packing))
				return false;
		}

		// Bump size.
		offset += packed_size;
	}

	return true;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x78, %rsp
movl %r8d, 0x2c(%rsp)
movl %ecx, 0x24(%rsp)
movq 0x68(%rsi), %rax
cmpq %rax, 0x70(%rsi)
je 0x29bd0
movq %rsi, %r13
movq %rdi, %rbx
movl %edx, 0x8(%rsp)
andl $-0x2, %edx
movl %edx, 0x28(%rsp)
movl $0x1, %r15d
xorl %r14d, %r14d
xorl %r12d, %r12d
movl $0x1, 0xc(%rsp)
movq %rdi, 0x18(%rsp)
movq %rsi, 0x10(%rsp)
movl (%rax,%r14,4), %esi
movq %rbx, %rdi
callq 0xa426
movq %rax, %rbp
movl 0x8(%r13), %eax
movq 0x38(%rbx), %rcx
imulq $0x148, %rax, %rdx      # imm = 0x148
movq 0xd0(%rcx,%rdx), %rax
movq 0xd8(%rcx,%rdx), %rdx
subq %rax, %rdx
sarq $0x4, %rdx
movabsq $0x4ec4ec4ec4ec4ec5, %rcx # imm = 0x4EC4EC4EC4EC4EC5
imulq %rcx, %rdx
cmpq %r14, %rdx
jbe 0x29be1
imulq $0xd0, %r14, %rcx
leaq (%rax,%rcx), %rsi
addq $0x68, %rsi
movq -0x8(%rsi), %rax
movq %rax, 0x38(%rsp)
xorl %ecx, %ecx
movq %rcx, 0x40(%rsp)
movq 0x8(%rsi), %rax
movq %rax, 0x48(%rsp)
movq %rcx, 0x50(%rsp)
movq 0x18(%rsi), %rax
movq %rax, 0x58(%rsp)
movups 0x20(%rsi), %xmm0
leaq 0x40(%rsp), %rdi
movups %xmm0, 0x20(%rdi)
movq %rcx, 0x70(%rsp)
movq %rdi, 0x30(%rsp)
leaq 0x30(%rsp), %rdx
callq 0xd402
movq %rbx, %rdi
movq %rbp, %rsi
leaq 0x38(%rsp), %r13
movq %r13, %rdx
movl 0x8(%rsp), %r14d
movl %r14d, %ecx
callq 0x29242
movq %rbx, %rdi
movl %eax, %ebx
movq %rbp, %rsi
movq %r13, %rdx
movl %r14d, %ecx
callq 0x2960e
movl %eax, %r14d
cmpl $0x4, 0x28(%rsp)
jne 0x29a80
leal (%r12,%r14), %eax
decl %eax
xorl %r12d, %eax
cmpl $0x10, %eax
jb 0x29a80
cmpl $0x11, %ebx
movl $0x10, %eax
cmovbl %eax, %ebx
movl 0xc(%rsp), %eax
cmpl %eax, %ebx
cmoval %ebx, %eax
leal (%r12,%rax), %ecx
decl %ecx
negl %eax
movl %eax, %r12d
andl %ecx, %r12d
cmpl 0x2c(%rsp), %r12d
jae 0x29ac2
cmpl $0xc, 0xc(%rbp)
movl $0x1, %eax
cmovnel %eax, %ebx
movl %ebx, 0xc(%rsp)
cmpl 0x24(%rsp), %r12d
jae 0x29acc
addl %r14d, %r12d
xorl %ebx, %ebx
movb $0x1, %bpl
jmp 0x29b8c
movl $0x2, %ebx
jmp 0x29b8a
leal -0x1(%r15), %r13d
cmpl $0x4, 0x8(%rsp)
movq 0x18(%rsp), %rbx
ja 0x29b03
movl 0x8(%rsp), %eax
movl $0x13, %ecx
btl %eax, %ecx
jae 0x29b03
movq %rbx, %rdi
movq 0x10(%rsp), %rsi
movl %r13d, %edx
callq 0x155fe
cmpl %r12d, %eax
jne 0x29b85
movq 0x20(%rbp), %rax
cmpq 0x28(%rbp), %rax
je 0x29b37
movq %rbx, %rdi
movq %rbp, %rsi
leaq 0x38(%rsp), %rdx
movl 0x8(%rsp), %ecx
callq 0x2957a
movq %rbx, %rdi
movl %eax, %ebx
movq 0x10(%rsp), %rsi
movl %r13d, %edx
callq 0x1570e
cmpl %eax, %ebx
jne 0x29b85
movl 0x8(%rsp), %edx
cmpl $0x2, %edx
je 0x29b58
cmpl $0x5, %edx
je 0x29b51
cmpl $0x3, %edx
jne 0x29b5a
movl $0x1, %edx
jmp 0x29b5a
movl $0x4, %edx
jmp 0x29b5a
xorl %edx, %edx
movq 0x68(%rbp), %rax
cmpq 0x70(%rbp), %rax
je 0x29ab5
movq 0x18(%rsp), %rdi
movq %rbp, %rsi
xorl %ecx, %ecx
movl $0xffffffff, %r8d       # imm = 0xFFFFFFFF
callq 0x29938
testb %al, %al
jne 0x29ab5
movl $0x1, %ebx
xorl %ebp, %ebp
leaq 0x40(%rsp), %rdi
callq 0xd5b0
testb %bpl, %bpl
je 0x29bc8
movl %r15d, %r14d
movq 0x10(%rsp), %r13
movq 0x68(%r13), %rax
movq 0x70(%r13), %rcx
subq %rax, %rcx
sarq $0x2, %rcx
incl %r15d
cmpq %r14, %rcx
movq 0x18(%rsp), %rbx
ja 0x2998c
movl $0x2, %ebx
cmpl $0x2, %ebx
sete %al
jmp 0x29bd2
movb $0x1, %al
addq $0x78, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x8b531(%rip), %rdi     # 0xb5119
movq %r14, %rsi
xorl %eax, %eax
callq 0x63d0
jmp 0x29bfa
jmp 0x29bfa
jmp 0x29bfa
jmp 0x29bfa
movq %rax, %rbx
leaq 0x40(%rsp), %rdi
callq 0xd5b0
movq %rbx, %rdi
callq 0x64a0
nop