#include #include #include "gfx/renderer_api.h" #include "runtime/mem_arena.h" #include "device_objects.hpp" #include "gpu.hpp" extern "C" void RT_RENDERER_API_FN(CmdBeginPass)(rt_command_buffer_handle cmdhandle, const rt_cmd_begin_pass_info *info) { rt_command_buffer *cmd = rtGetCommandBuffer(cmdhandle); if (!RT_VERIFY(cmd)) return; if (cmd->annotation) { WCHAR wname[128]; if (rtUTF8ToWStr(info->name, wname, sizeof(wname)) == RT_SUCCESS) cmd->annotation->BeginEvent(wname); } // Setup rtvs ID3D11RenderTargetView *rtvs[4]; ID3D11DepthStencilView *dsv = nullptr; for (uint32_t i = 0; i < info->color_buffer_count; ++i) { rt_render_target *rt = rtGetRenderTarget(info->color_buffers[i]); if (!RT_VERIFY(rt)) return; RT_ASSERT(rt->IsColorRenderTarget(), "Needs to provide a valid color render target"); rtvs[i] = rt->rtv; if (info->color_buffer_loads[i] == RT_PASS_LOAD_MODE_CLEAR) { FLOAT color[4] = { info->color_buffer_clear_values[i].color.r, info->color_buffer_clear_values[i].color.g, info->color_buffer_clear_values[i].color.b, info->color_buffer_clear_values[i].color.a, }; cmd->context->ClearRenderTargetView(rt->rtv, color); } } rt_render_target *dsvrt = rtGetRenderTarget(info->depth_stencil_buffer); if (dsvrt) { RT_ASSERT(dsvrt->IsDepthStencilTarget(), "Need to provide a valid depth stencil render target"); dsv = dsvrt->dsv; if (info->depth_stencil_buffer_load == RT_PASS_LOAD_MODE_CLEAR) cmd->context->ClearDepthStencilView( dsv, (dsvrt->HasStencilComponent()) ? D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL : D3D11_CLEAR_DEPTH, info->depth_stencil_buffer_clear_value.depth_stencil.depth, static_cast(info->depth_stencil_buffer_clear_value.depth_stencil.stencil)); } cmd->context->OMSetRenderTargets(static_cast(info->color_buffer_count), rtvs, dsv); D3D11_VIEWPORT viewport; viewport.TopLeftX = static_cast(info->render_area.offset.x); viewport.TopLeftY = static_cast(info->render_area.offset.y); viewport.Width = static_cast(info->render_area.size.x); viewport.Height = static_cast(info->render_area.size.y); viewport.MinDepth = 0.f; viewport.MaxDepth = 1.f; cmd->context->RSSetViewports(1, &viewport); // We currently only support triangles, so here is a good place to set this cmd->context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); } extern "C" void RT_RENDERER_API_FN(CmdEndPass)(rt_command_buffer_handle cmdhandle) { rt_command_buffer *cmd = rtGetCommandBuffer(cmdhandle); if (!RT_VERIFY(cmd)) return; if (cmd->annotation) { cmd->annotation->EndEvent(); } } extern "C" void RT_RENDERER_API_FN(CmdTransitionRenderTarget)(rt_command_buffer_handle cmdhandle, rt_render_target_handle target, rt_render_target_state state) { rt_command_buffer *cmd = rtGetCommandBuffer(cmdhandle); if (!RT_VERIFY(cmd)) return; RT_UNUSED(target); RT_UNUSED(state); } extern "C" void RT_RENDERER_API_FN(CmdFlushRenderTargetWrite)(rt_command_buffer_handle cmdhandle, rt_render_target_handle render_target) { rt_command_buffer *cmd = rtGetCommandBuffer(cmdhandle); if (!RT_VERIFY(cmd)) return; RT_UNUSED(render_target); } extern "C" void RT_RENDERER_API_FN(CmdBindPipeline)(rt_command_buffer_handle cmdhandle, rt_pipeline_handle pipeline_handle) { rt_command_buffer *cmd = rtGetCommandBuffer(cmdhandle); if (!RT_VERIFY(cmd)) return; rt_pipeline *pipeline = rtGetPipeline(pipeline_handle); if (pipeline->IsComputePipeline()) { rtReportError("dx11", "Attempted to bind a compute pipeline via CmdBindPipeline. Use " "CmdBindComputePipeline instead."); return; } auto context = cmd->context; context->IASetInputLayout(pipeline->input_layout); context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); context->VSSetShader(pipeline->vertex_shader, nullptr, 0); context->PSSetShader(pipeline->pixel_shader, nullptr, 0); context->RSSetState(pipeline->rasterizer_state); } extern "C" void RT_RENDERER_API_FN(CmdBindVertexBuffers)(rt_command_buffer_handle cmdhandle, uint32_t first_binding, uint32_t count, const rt_buffer_handle *buffers, const uint32_t *_strides, const uint32_t *_offsets) { rt_command_buffer *cmd = rtGetCommandBuffer(cmdhandle); if (!RT_VERIFY(cmd)) return; rt_temp_arena temp = rtGetTemporaryArena(NULL, 0); if (!temp.arena) return; ID3D11Buffer **vbos = RT_ARENA_PUSH_ARRAY(temp.arena, ID3D11Buffer *, count); static_assert(sizeof(UINT) == sizeof(uint32_t)); const UINT *offsets = _offsets; const UINT *strides = _strides; if (!vbos || !strides) goto out; if (!offsets) { offsets = RT_ARENA_PUSH_ARRAY_ZERO(temp.arena, UINT, count); } for (uint32_t i = 0; i < count; ++i) { rt_buffer *buffer = rtGetBuffer(buffers[i]); RT_ASSERT(buffer->type == RT_BUFFER_TYPE_VERTEX, "Buffer must be a vertex buffer"); vbos[i] = buffer->buffer; } cmd->context->IASetVertexBuffers(first_binding, count, vbos, strides, offsets); out: rtReturnTemporaryArena(temp); } extern "C" void RT_RENDERER_API_FN(CmdDraw)(rt_command_buffer_handle cmdhandle, uint32_t first, uint32_t count) { rt_command_buffer *cmd = rtGetCommandBuffer(cmdhandle); if (!RT_VERIFY(cmd)) return; cmd->context->Draw(count, first); }