#include "dx_pipeline_loader.h"

#include "backend/dx/dx_renderer.h"

bool dx_pipeline_loader::load(const char* vertex_shader_name, const char* pixel_shader_name) {
    auto renderer = aorii::get_renderer<dx_renderer>();
    const auto d3d_device = renderer->get_d3d_device();

    const auto& vertex_shader_code = renderer->load_shader(vertex_shader_name);
    const auto& pixel_shader_code = renderer->load_shader(pixel_shader_name);

    auto hr = d3d_device->CreateVertexShader(vertex_shader_code.data(), vertex_shader_code.size(), nullptr, &vertex_shader);
    if (FAILED(hr)) {
        spdlog::critical("rect_pipeline 无法创建顶点着色器: {0}", hr);
        return false;
    }
    hr = d3d_device->CreatePixelShader(pixel_shader_code.data(), pixel_shader_code.size(), nullptr, &pixel_shader);
    if (FAILED(hr)) {
        spdlog::critical("rect_pipeline 无法创建像素着色器: {0}", hr);
        return false;
    }
    uint32_t offset = 0;
    D3D11_INPUT_ELEMENT_DESC layout_desc[] = {
        { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
        {"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0},
        { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 16, D3D11_INPUT_PER_VERTEX_DATA, 0 },
        { "TEXCOORD", 1, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 32, D3D11_INPUT_PER_VERTEX_DATA, 0},
        { "TEXCOORD", 2, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 48, D3D11_INPUT_PER_VERTEX_DATA, 0},
        { "TEXCOORD", 3, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 64, D3D11_INPUT_PER_VERTEX_DATA, 0},
    };
    constexpr int32_t element_count = sizeof(layout_desc) / sizeof(D3D11_INPUT_ELEMENT_DESC);
    hr = d3d_device->CreateInputLayout(layout_desc, element_count, vertex_shader_code.data(), vertex_shader_code.size(), &input_layout);
    if (FAILED(hr)) {
        spdlog::critical("{0} 无法创建输入布局: {1}", vertex_shader_name, hr);
        return false;
    }
    return true;
}

void dx_pipeline_loader::use() const {
    const auto d3d_context = aorii::get_renderer<dx_renderer>()->get_d3d_context();
    d3d_context->VSSetShader(vertex_shader, nullptr, 0);
    d3d_context->PSSetShader(pixel_shader, nullptr, 0);
    d3d_context->IASetInputLayout(input_layout);
}
