#include "shaderPatcher.hpp"
#include "gpuMemory.hpp"

#include <cstdlib>
#include <cstring>

namespace render::kernel
{

static void *patcherAllocator(void *smth, unsigned int size);
static void patcherFree(void *smth, void *mem);

ShaderPatcher::ShaderPatcher()
{
    size_t memSize = 64 * 1024;

    this->buffer = new GpuBuffer(
        SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW,
        SCE_GXM_MEMORY_ATTRIB_RW,
        memSize);

    this->vBuffer = new GpuVertexUsseBuffer(memSize);
    this->fBuffer = new GpuFragmentUsseBuffer(memSize);

    SceGxmShaderPatcherParams params;
    memset(&params, 0, sizeof(SceGxmShaderPatcherParams));

    params.hostAllocCallback = patcherAllocator;
    params.hostFreeCallback = patcherFree;

    params.bufferMem = this->buffer->data;
    params.bufferMemSize = memSize;

    params.vertexUsseMem = this->vBuffer->data;
    params.vertexUsseOffset = this->vBuffer->offset;
    params.vertexUsseMemSize = memSize;

    params.fragmentUsseMem = this->fBuffer->data;
    params.fragmentUsseOffset = this->fBuffer->offset;
    params.fragmentUsseMemSize = memSize;

    sceGxmShaderPatcherCreate(&params, &this->patcher);
}

ShaderPatcher::~ShaderPatcher()
{
    sceGxmShaderPatcherDestroy(this->patcher);

    delete this->vBuffer;
    delete this->fBuffer;
    delete this->buffer;
}

SceGxmShaderPatcher *ShaderPatcher::GetPatcher() const
{
    return this->patcher;
}

static void *patcherAllocator(void *smth, unsigned int size)
{
    return malloc(size);
}

static void patcherFree(void *smth, void *mem)
{
    free(mem);
}

} // namespace render::kernel