// File: /workspace/github_cpp_makefile_star2_O2/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, 0x30(%rsp)
movl %ecx, 0x28(%rsp)
movq %rsi, %r13
movq %rdi, 0x18(%rsp)
movl %edx, 0x4(%rsp)
andl $-0x2, %edx
movl %edx, 0x2c(%rsp)
xorl %esi, %esi
pushq $0x1
popq %rbp
leaq 0x38(%rsp), %rdx
xorl %ebx, %ebx
movq %r13, 0x10(%rsp)
movl %esi, %esi
movq 0x68(%r13), %rax
movq 0x70(%r13), %rcx
subq %rax, %rcx
sarq $0x2, %rcx
cmpq %rsi, %rcx
jbe 0x23d53
movl %ebp, 0x34(%rsp)
movq %rsi, %r15
movl (%rax,%rsi,4), %esi
movq %rdx, %rbp
movq 0x18(%rsp), %r14
movq %r14, %rdi
callq 0x90a4
movq %rax, %r12
movl 0x8(%r13), %eax
movq 0x38(%r14), %rcx
imulq $0x148, %rax, %rax      # imm = 0x148
leaq (%rcx,%rax), %rdi
addq $0xd0, %rdi
movq %r15, 0x20(%rsp)
movq %r15, %rsi
callq 0x41c9e
leaq 0x60(%rax), %rsi
movq %rbp, %rdi
callq 0x934a
movq %r14, %rdi
movq %r12, %rsi
movq %rbp, %rdx
movl 0x4(%rsp), %r15d
movl %r15d, %ecx
callq 0x23554
movl %eax, %r13d
movq %r14, %rdi
movq %r12, 0x8(%rsp)
movq %r12, %rsi
movq %rbp, %rdx
movl %r15d, %ecx
callq 0x23876
movl %eax, %r15d
movq %rbp, %r14
leal -0x1(%rbx), %eax
cmpl $0x4, 0x2c(%rsp)
jne 0x23c14
leal (%rax,%r15), %ecx
xorl %ebx, %ecx
cmpl $0x10, %ecx
jb 0x23c14
cmpl $0x11, %r13d
pushq $0x10
popq %rcx
cmovbl %ecx, %r13d
movl 0x34(%rsp), %edx
cmpl %edx, %r13d
movl %edx, %ecx
cmoval %r13d, %ecx
addl %ecx, %eax
negl %ecx
andl %eax, %ecx
cmpl 0x30(%rsp), %ecx
jae 0x23c54
movq 0x8(%rsp), %rax
cmpl $0xc, 0xc(%rax)
pushq $0x1
popq %rax
cmovnel %eax, %r13d
movq %rcx, %r12
cmpl 0x28(%rsp), %ecx
jae 0x23c64
addl %r15d, %r12d
xorl %r15d, %r15d
movb $0x1, %r14b
jmp 0x23d27
movq %rcx, %r12
xorl %r14d, %r14d
movl %edx, %r13d
pushq $0x2
jmp 0x23d25
cmpl $0x4, 0x4(%rsp)
movq 0x18(%rsp), %rbp
ja 0x23c97
movl 0x4(%rsp), %eax
pushq $0x13
popq %rcx
btl %eax, %ecx
jae 0x23c97
movq %rbp, %rdi
movq 0x10(%rsp), %rsi
movq 0x20(%rsp), %rdx
callq 0x1267e
cmpl %r12d, %eax
jne 0x23d20
movq 0x8(%rsp), %rcx
movq 0x20(%rcx), %rax
cmpq 0x28(%rcx), %rax
je 0x23cd2
movq %rbp, %rdi
movq 0x8(%rsp), %rsi
movq %r14, %rdx
movl 0x4(%rsp), %ecx
callq 0x237e2
movl %eax, %ebx
movq %rbp, %rdi
movq 0x10(%rsp), %rsi
movq 0x20(%rsp), %rdx
callq 0x1272c
cmpl %eax, %ebx
jne 0x23d20
movl 0x4(%rsp), %edx
cmpl $0x2, %edx
je 0x23cf3
cmpl $0x5, %edx
movq 0x8(%rsp), %rsi
je 0x23cee
cmpl $0x3, %edx
jne 0x23cfa
pushq $0x1
jmp 0x23cf0
pushq $0x4
popq %rdx
jmp 0x23cfa
xorl %edx, %edx
movq 0x8(%rsp), %rsi
movq 0x68(%rsi), %rax
cmpq 0x70(%rsi), %rax
je 0x23c46
movq 0x18(%rsp), %rdi
xorl %ecx, %ecx
pushq $-0x1
popq %r8
callq 0x23b1a
testb %al, %al
jne 0x23c46
xorl %r14d, %r14d
pushq $0x1
popq %r15
leaq 0x40(%rsp), %rdi
callq 0xb51c
movq 0x20(%rsp), %rsi
incl %esi
movl %r13d, %ebp
testb %r14b, %r14b
movq 0x10(%rsp), %r13
leaq 0x38(%rsp), %rdx
movq %r12, %rbx
jne 0x23b55
jmp 0x23d57
pushq $0x2
popq %r15
cmpl $0x2, %r15d
sete %al
addq $0x78, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x23d75
jmp 0x23d75
jmp 0x23d75
jmp 0x23d75
movq %rax, %rbx
leaq 0x40(%rsp), %rdi
callq 0xb51c
movq %rbx, %rdi
callq 0x64b0