
struct VertexIn {
	[[vk::layout(0)]] float2 pos;
}
struct VertexOut {
	[[vk::layout(0)]] float4 color;
	float4 position : SV_Position;
}

struct PushConstant {
    float2 screen_size;
    float2 position;
    float size;
}

[[vk::push_constant]]
ConstantBuffer<PushConstant> push_constant;

[shader("vertex")]
VertexOut vertex(VertexIn vertex) {
	VertexOut output;

	output.position = float4(
        2.0 * (push_constant.position.x + vertex.pos.x * push_constant.size) /
        push_constant.screen_size.x - 1.0,
        2.0 * (push_constant.position.y + vertex.pos.y * push_constant.size) /
        push_constant.screen_size.y - 1.0,
        0.0,
        1.0,
    );
	output.color = float4(1.0, 1.0, 0.0, 1.0);

	return output;
}

struct FragmentOut {
    float4 color : SV_Target;
}

[shader("fragment")]
FragmentOut fragment(VertexOut input, float3 bary: SV_BARYCENTRICS) {
    FragmentOut output;

    output.color = input.color;
	return output;
}



struct GlyphDesc {
	uint vertex_offset;
	uint index_offset;
	uint vertex_count;
	uint index_count;
}

static const uint SOLID = 0;
static const uint CONVEX = 0;
static const uint CONCAVE = 0;

struct MeshOut {
	float4 pos : SV_Position;
}

struct MeshInvocation {
	uint glyph_id;
	uint vertex_triangle_offsets;
}

struct MeshIn {
	MeshInvocation glyph_id[32];
}
struct PrimOut {
	uint kind : BLENDINDICES0;
}

[[vk::binding(0)]]
StructuredBuffer<GlyphDesc> glyphs;

[[vk::binding(1)]]
StructuredBuffer<uint> glyphs_ids;

[shader("mesh")]
[numthreads(32, 1, 1)]
[outputtopology("triangle")]
void mesh(uint3 gid: SV_GroupID, // dispatched group id
          uint3 tid: SV_GroupThreadID, // global thread id
          uint ti: SV_GroupIndex, // local group thread index
          out indices uint3 triangles[126],
          out vertices MeshOut vertices[64],
          out primitives PrimOut attr[126],
          in MeshIn mesh,
) {

	SetMeshOutputCounts(0, 0);
// we have a limited number of verts/triangles we can output
// if a glyph exceeds the 126 triangles/64 verts limit, then we need more than
// one thread building geometry.
// all threads sharing one glyph should be in the same subgroup/wave.
}

struct FragmentIn2 {
	float4 pos : SV_Position;
	sample float3 bary : SV_BARYCENTRICS;
	uint kind : BLENDINDICES0;
}

float2 computeUV(const float3 bary)
{
    const float u = bary.x * 0 + bary.y * 0.5f + bary.z * 1;
    const float v = bary.x * 0 + bary.y * 0.0f + bary.z * 1;
    return float2(u, v);
}

float computeQuadraticBezierFunction(const float2 uv)
{
    return uv.x * uv.x - uv.y;
}

[shader("fragment")]
FragmentOut fragment_barycentric(FragmentIn2 input) {
    const uint kind = input.kind;
    const float2 uv = computeUV(input.bary);
    const float sign = computeQuadraticBezierFunction(uv);

    if ((kind == CONVEX) && sign > 0.0f || (kind == CONCAVE) && sign < 0.0f) {
        discard;
    }

    FragmentOut output;
    output.color = float4(1.0, 0.0, 0.0, 1.0);

	return output;
}
