#ifndef RAYTRACE_BUFFERS_H
#define RAYTRACE_BUFFERS_H

#include "raytrace_setup.glsl"

// NOTE: We store last face index for an antry. This makes updates easier and allow for current last
// face tracking without additional buffer just for this (and less atomics to update it)
// To calculate faces per entry just subtract entry[idx] - entry[max(0, idx - 1)]

// NOTE: Also, we store each surface separately as a primitive, but they might be sharing the
// vertex range.

struct TransformedDataLocation
{
	uint surface_idx;		// each submitted surface for given geometry
	uint last_face_idx;		// these are unique for each surface
	uint last_vtx_idx;		// these can repease for multiple surfaces
	uint material_idx;		// global material index for the surface
	uint raytrace;			//
	uint voxelize;			//
	uint _pad0;
	uint _pad1;
	ivec4 bbox_min;			// bbox for the surface. integer because we need atomics to update it... should be enough
	ivec4 bbox_max;			// ...
};

layout (std430) buffer TransformedDataLocationBuffer {
	TransformedDataLocation transformed_data_location[];
};

struct TransformedDataFace
{
	uint material_idx;
};

layout (std430) buffer TransformedDataFacesBuffer {
	TransformedDataFace transformed_data_faces[];
};

layout (std430) buffer TransformedDataIndexBuffer {
	uint transformed_data_indices[];
};


layout (std430) BUFF_ATTR buffer BucketData {
	uint sizes_histogram[32];	// computing this with cpu takes way too much time, especially with debug
	ivec3 grid_shift;
	vec3 grid_size;             // this is actually cell size!
	uint total_intersections;
#ifndef USE_LINKED_LISTS
	uint voxelization_group_sizes[16 * 16 * 16];
	uint sizes[GRID_RES * GRID_RES * GRID_RES];
	uint offsets[GRID_RES * GRID_RES * GRID_RES];
	uint16_t sizes16[GRID_RES * GRID_RES * GRID_RES];
	uint16_t offsets16[GRID_RES * GRID_RES * GRID_RES];
	uint indices[];
#else
#endif

} in_buckets;

layout (std430) readonly buffer InVertexBuffer {
	float in_vtx_data[];
};

//layout (std430, binding = 1) buffer BBoxBuffer {
layout (std430) buffer BBoxBuffer {
	vec4 grid_size_raytrace;
	vec4 grid_size_raytrace_recip;
	vec4 grid_size_voxelize;
	vec4 grid_size_voxelize_recip;
	vec4 grid_size_combined;
	vec4 grid_shift_raytrace;
	vec4 grid_shift_voxelize;
	vec4 grid_shift_combined;
	vec4 bbox_raytrace_min;
	vec4 bbox_raytrace_max;
	vec4 bbox_voxelize_min;
	vec4 bbox_voxelize_max;
	vec4 bbox_combined_min;
	vec4 bbox_combined_max;
} in_bbox_data;

// encode color as uint. saves space. 64MB for 256^3 instead of 256MB
layout (std430) buffer VoxelLightBuffer {
	uint in_voxel_light_data[];
};

layout (std430) buffer VoxelOcclusionBuffer {
	uint in_voxel_occlusion_data[];
};

// TODO: This is currently unused
// encode normal as uint. saves space. 64MB for 256^3 instead of 256MB
//layout (std430, binding = 8) buffer VoxelNormalBuffer {
//	uint normal[];
//} in_voxel_normal_data;

#endif