#include "video.hpp" #include extern "C" { #include "memory.h" #include "plat.h" #include "str.h" } Pipeline_Builder::Pipeline_Builder(Arena* arena): arena(arena) {} void Pipeline_Builder::begin_rp() { pass = (Render_Pass*)arena_alloc(arena, sizeof *pass); pass->target = 0; pass->clear = { 0, 0, 0, 0 }; } void Pipeline_Builder::rp_target(Texture_Id id, Colour clear) { pass->target = id; pass->clear = clear; pass->mode = Clear_Mode::clear; } void Pipeline_Builder::rp_target(Texture_Id id, Clear_Mode clear) { pass->target = id; assert(clear != Clear_Mode::clear); pass->mode = clear; } void Pipeline_Builder::validate_rp() { assert(pass->target); } Render_Pass& Pipeline_Builder::build_rp() { validate_rp(); return *pass; } void Pipeline_Builder::begin(Device* dev) { pip = (Pipeline*)arena_alloc(arena, sizeof *pip); memset(pip, 0, sizeof *pip); if (dev) { Texture_Id backbuffer_id = dev->get_backbuffer(); Texture& backbuffer = dev->get_texture(backbuffer_id); pip->scissor[0] = 0; pip->scissor[1] = 0; pip->scissor[2] = backbuffer.w; pip->scissor[3] = backbuffer.h; pip->viewport[0] = 0; pip->viewport[1] = 0; pip->viewport[2] = backbuffer.w; pip->viewport[3] = backbuffer.h; } } void Pipeline_Builder::viewport( float x, float y, float w, float h ) { pip->viewport[0] = x; pip->viewport[1] = y; pip->viewport[2] = w; pip->viewport[3] = h; } void Pipeline_Builder::scissor( float x, float y, float w, float h ) { pip->scissor[0] = x; pip->scissor[1] = y; pip->scissor[2] = w; pip->scissor[3] = h; } void Pipeline_Builder::shader(Shader_Id s) { pip->shader = s; } void Pipeline_Builder::texture( int binding, Texture_Id t, Sampler_Id s ) { Descriptor* d; Texture_Descriptor* td; assert(pip->descriptor_count < pipeline_max_descriptors); d = &pip->descriptors[pip->descriptor_count++]; td = (Texture_Descriptor*)d->payload; d->slot = binding; d->type = Descriptor::Type::texture; td->sampler = s; td->texture = t; } void Pipeline_Builder::cbuffer(int binding, Buffer_Id id) { Descriptor* d; Constant_Buffer_Descriptor* cd; assert(pip->descriptor_count < pipeline_max_descriptors); d = &pip->descriptors[pip->descriptor_count++]; cd = (Constant_Buffer_Descriptor*)d->payload; d->slot = binding; d->type = Descriptor::Type::constant_buffer; cd->buffer = id; } void Pipeline_Builder::vertex_format(Vertex_Format_Id vf) { pip->vertex_format = vf; } Pipeline& Pipeline_Builder::build() { #define h(n, v) \ n = fnv1a64_2(n, (uint8_t*)&v, sizeof v) validate(); pip->pipeline_hash = fnv1a64(0, 0); h(pip->pipeline_hash, pip->vertex_format); h(pip->pipeline_hash, pip->shader); h(pip->pipeline_hash, pip->descriptor_count); { int i, e = pip->descriptor_count; pip->descriptor_resource_hash = fnv1a64(0, 0); for (i = 0; i < e; i++) { Descriptor* d = &pip->descriptors[i]; h(pip->pipeline_hash, d->type); h(pip->pipeline_hash, d->slot); h(pip->descriptor_resource_hash, d->type); h(pip->descriptor_resource_hash, d->slot); switch (d->type) { case Descriptor::Type::texture: { auto td = (Texture_Descriptor*)d->payload; h(pip->descriptor_resource_hash, td->sampler); h(pip->descriptor_resource_hash, td->texture); } break; case Descriptor::Type::constant_buffer: { auto cd = (Constant_Buffer_Descriptor*)d->payload; h(pip->descriptor_resource_hash, cd->buffer); } break; } } } return *pip; #undef h } void Pipeline_Builder::validate() { assert(pip->vertex_format); assert(pip->shader); }