// File: /workspace/github_cpp_makefile_star2_O3/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 $0x88, %rsp
movl %r8d, 0x2c(%rsp)
movl %ecx, 0x28(%rsp)
movq 0x68(%rsi), %rax
cmpq %rax, 0x70(%rsi)
je 0x295ab
movl %edx, %r15d
movq %rdi, 0x10(%rsp)
movl %edx, %ecx
andl $-0x2, %ecx
movl %ecx, 0x24(%rsp)
movl $0x1, %ebp
xorl %ebx, %ebx
xorl %r13d, %r13d
movl $0x1, 0x4(%rsp)
movq %rsi, 0x18(%rsp)
movq %r13, 0x8(%rsp)
movq %rbp, 0x38(%rsp)
movq %rsi, %r12
movl (%rax,%rbx,4), %esi
movq 0x10(%rsp), %rbp
movq %rbp, %rdi
callq 0xa3ea
movq %rax, %r13
movl 0x8(%r12), %eax
movq 0x38(%rbp), %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 %rbx, %rdx
jbe 0x295cf
imulq $0xd0, %rbx, %rcx
leaq (%rax,%rcx), %rsi
addq $0x68, %rsi
movq -0x8(%rsi), %rax
movq %rax, 0x48(%rsp)
xorl %ecx, %ecx
movq %rcx, 0x50(%rsp)
movq 0x8(%rsi), %rax
movq %rax, 0x58(%rsp)
movq %rcx, 0x60(%rsp)
movq 0x18(%rsi), %rax
movq %rax, 0x68(%rsp)
movups 0x20(%rsi), %xmm0
leaq 0x50(%rsp), %rdi
movups %xmm0, 0x20(%rdi)
movq %rcx, 0x80(%rsp)
movq %rdi, 0x40(%rsp)
leaq 0x40(%rsp), %rdx
callq 0xd3c2
movq %rbp, %rdi
movq %r13, %rsi
leaq 0x48(%rsp), %rbx
movq %rbx, %rdx
movl %r15d, %ecx
callq 0x28c1a
movl %eax, %r12d
movq %rbp, %rdi
movq %r13, %r14
movq %r13, %rsi
movq %rbx, %rdx
movl %r15d, %ecx
callq 0x28fdc
movq 0x38(%rsp), %rbp
movq 0x8(%rsp), %rdx
leal -0x1(%rdx), %esi
cmpl $0x4, 0x24(%rsp)
movq %rax, 0x30(%rsp)
jne 0x2947d
leal (%rsi,%rax), %ecx
xorl %edx, %ecx
cmpl $0x10, %ecx
jb 0x2947d
cmpl $0x11, %r12d
movl $0x10, %ecx
cmovbl %ecx, %r12d
movl 0x4(%rsp), %ecx
cmpl %ecx, %r12d
cmoval %r12d, %ecx
addl %ecx, %esi
negl %ecx
andl %esi, %ecx
cmpl 0x2c(%rsp), %ecx
setae 0x3(%rsp)
jae 0x295af
movq %rcx, %r13
cmpl $0xc, 0xc(%r14)
movl $0x1, %eax
cmovnel %eax, %r12d
movl %r12d, 0x4(%rsp)
cmpl 0x28(%rsp), %r13d
jb 0x2957b
leal -0x1(%rbp), %eax
movl %eax, 0x8(%rsp)
cmpl $0x4, %r15d
ja 0x294f2
movl $0x13, %eax
btl %r15d, %eax
jae 0x294f2
movq 0x10(%rsp), %rdi
movq 0x18(%rsp), %rsi
movl 0x8(%rsp), %edx
callq 0x15402
cmpl %r13d, %eax
jne 0x295af
movq 0x20(%r14), %rax
cmpq 0x28(%r14), %rax
je 0x29531
movq %rbx, %rdx
movq 0x10(%rsp), %rbx
movq %rbx, %rdi
movq %r14, %rsi
movl %r15d, %r12d
movl %r15d, %ecx
callq 0x28f48
movl %eax, %r15d
movq %rbx, %rdi
movq 0x18(%rsp), %rsi
movl 0x8(%rsp), %edx
callq 0x1550e
cmpl %eax, %r15d
movl %r12d, %r15d
jne 0x295af
cmpl $0x2, %r15d
je 0x29551
cmpl $0x5, %r15d
je 0x2954a
cmpl $0x3, %r15d
jne 0x29555
movl $0x1, %edx
jmp 0x29558
movl $0x4, %edx
jmp 0x29558
xorl %edx, %edx
jmp 0x29558
movl %r15d, %edx
movq 0x68(%r14), %rax
cmpq 0x70(%r14), %rax
je 0x2957b
movq 0x10(%rsp), %rdi
movq %r14, %rsi
xorl %ecx, %ecx
movl $0xffffffff, %r8d       # imm = 0xFFFFFFFF
callq 0x29318
testb %al, %al
je 0x295af
addl 0x30(%rsp), %r13d
leaq 0x50(%rsp), %rdi
callq 0xd570
movl %ebp, %ebx
movq 0x18(%rsp), %rsi
movq 0x68(%rsi), %rax
movq 0x70(%rsi), %rcx
subq %rax, %rcx
sarq $0x2, %rcx
incl %ebp
cmpq %rbx, %rcx
ja 0x29368
movb $0x1, %al
jmp 0x295bd
leaq 0x50(%rsp), %rdi
callq 0xd570
movb 0x3(%rsp), %al
addq $0x88, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x8ab43(%rip), %rdi     # 0xb4119
movq %rbx, %rsi
xorl %eax, %eax
callq 0x63d0
jmp 0x295e8
jmp 0x295e8
jmp 0x295e8
jmp 0x295e8
movq %rax, %rbx
leaq 0x50(%rsp), %rdi
callq 0xd570
movq %rbx, %rdi
callq 0x64a0
nop