#include "pipelines.h"
#include "gpu.h"
#include "types.h"
#include <iostream>


void RayPipeline::create(SDL_GPUDevice* dev, SDL_Window* win) {
  vert = load_shader(dev, "shaders/ray.vert.spv", SDL_GPU_SHADERSTAGE_VERTEX,   0, 0);
  frag = load_shader(dev, "shaders/ray.frag.spv", SDL_GPU_SHADERSTAGE_FRAGMENT, 1, 1);

  SDL_GPUColorTargetDescription color_tgt {
    .format = SDL_GetGPUSwapchainTextureFormat(dev, win),
  };

  SDL_GPUGraphicsPipelineCreateInfo info {
    .vertex_shader   = vert,
    .fragment_shader = frag,
    .vertex_input_state = {
      .vertex_buffer_descriptions = nullptr,
      .num_vertex_buffers         = 0,
      .vertex_attributes          = nullptr,
      .num_vertex_attributes      = 0,
    },
    .primitive_type = SDL_GPU_PRIMITIVETYPE_TRIANGLELIST,
    .rasterizer_state = {
      .fill_mode  = SDL_GPU_FILLMODE_FILL,
      .cull_mode  = SDL_GPU_CULLMODE_NONE,
      .front_face = SDL_GPU_FRONTFACE_COUNTER_CLOCKWISE,
    },
    .target_info = {
      .color_target_descriptions = &color_tgt,
      .num_color_targets         = 1,
    },
  };

  pipeline = SDL_CreateGPUGraphicsPipeline(dev, &info);
  if (!pipeline)
    std::cerr << "Ray pipeline failed: " << SDL_GetError() << std::endl;
}

void RayPipeline::destroy(SDL_GPUDevice* dev) {
  if (pipeline) SDL_ReleaseGPUGraphicsPipeline(dev, pipeline);
  if (vert)     SDL_ReleaseGPUShader(dev, vert);
  if (frag)     SDL_ReleaseGPUShader(dev, frag);
}

void PostPipeline::create(SDL_GPUDevice* dev, SDL_Window* win) {
  vert = load_shader(dev, "shaders/ray.vert.spv",  SDL_GPU_SHADERSTAGE_VERTEX,   0, 0);
  frag = load_shader(dev, "shaders/post.frag.spv",  SDL_GPU_SHADERSTAGE_FRAGMENT, 1, 1);

  SDL_GPUColorTargetDescription color_tgt {
    .format = SDL_GetGPUSwapchainTextureFormat(dev, win),
  };

  SDL_GPUGraphicsPipelineCreateInfo info {
    .vertex_shader   = vert,
    .fragment_shader = frag,
    .vertex_input_state = {
      .vertex_buffer_descriptions = nullptr,
      .num_vertex_buffers         = 0,
      .vertex_attributes          = nullptr,
      .num_vertex_attributes      = 0,
    },
    .primitive_type = SDL_GPU_PRIMITIVETYPE_TRIANGLELIST,
    .rasterizer_state = {
      .fill_mode  = SDL_GPU_FILLMODE_FILL,
      .cull_mode  = SDL_GPU_CULLMODE_NONE,
      .front_face = SDL_GPU_FRONTFACE_COUNTER_CLOCKWISE,
    },
    .target_info = {
      .color_target_descriptions = &color_tgt,
      .num_color_targets         = 1,
    },
  };

  pipeline = SDL_CreateGPUGraphicsPipeline(dev, &info);
  if (!pipeline)
    std::cerr << "Post pipeline failed: " << SDL_GetError() << std::endl;
}

void PostPipeline::destroy(SDL_GPUDevice* dev) {
  if (pipeline) SDL_ReleaseGPUGraphicsPipeline(dev, pipeline);
  if (vert)     SDL_ReleaseGPUShader(dev, vert);
  if (frag)     SDL_ReleaseGPUShader(dev, frag);
}