WIP: lunasvg implementation, things stopped working
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
#include "renderer/renderer.h"
|
||||
#include "ui/ui_core.h"
|
||||
#include "ui/ui_icons.h"
|
||||
|
||||
#include <d3d12.h>
|
||||
#include <dxgi1_5.h>
|
||||
@@ -201,6 +202,10 @@ struct Renderer {
|
||||
F32 font_atlas_size; // font size the atlas was built at
|
||||
F32 font_line_height;
|
||||
|
||||
// Icon atlas
|
||||
ID3D12Resource *icon_texture;
|
||||
ID3D12DescriptorHeap *icon_srv_heap;
|
||||
|
||||
// GDI text measurement
|
||||
HDC measure_dc;
|
||||
HFONT measure_font;
|
||||
@@ -976,7 +981,7 @@ static void emit_text_glyphs(DrawBatch *batch, Renderer *r,
|
||||
////////////////////////////////
|
||||
// Flush helper: issues a draw call for accumulated vertices, then resets batch
|
||||
|
||||
static void flush_batch(Renderer *r, DrawBatch *batch, UINT buf_idx) {
|
||||
static void flush_batch(Renderer *r, DrawBatch *batch, UINT buf_idx, ID3D12DescriptorHeap *tex_heap = nullptr) {
|
||||
if (batch->index_count == 0) return;
|
||||
|
||||
r->command_list->SetPipelineState(r->pipeline_state);
|
||||
@@ -985,10 +990,11 @@ static void flush_batch(Renderer *r, DrawBatch *batch, UINT buf_idx) {
|
||||
float constants[4] = { (float)r->width, (float)r->height, 0, 0 };
|
||||
r->command_list->SetGraphicsRoot32BitConstants(0, 4, constants, 0);
|
||||
|
||||
// Bind font texture
|
||||
r->command_list->SetDescriptorHeaps(1, &r->srv_heap);
|
||||
// Bind texture (font or icon)
|
||||
ID3D12DescriptorHeap *heap = tex_heap ? tex_heap : r->srv_heap;
|
||||
r->command_list->SetDescriptorHeaps(1, &heap);
|
||||
r->command_list->SetGraphicsRootDescriptorTable(1,
|
||||
r->srv_heap->GetGPUDescriptorHandleForHeapStart());
|
||||
heap->GetGPUDescriptorHandleForHeapStart());
|
||||
|
||||
r->command_list->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
|
||||
@@ -1053,6 +1059,8 @@ void renderer_destroy(Renderer *r) {
|
||||
if (r->index_buffers[i]) r->index_buffers[i]->Release();
|
||||
}
|
||||
if (r->font_texture) r->font_texture->Release();
|
||||
if (r->icon_texture) r->icon_texture->Release();
|
||||
if (r->icon_srv_heap) r->icon_srv_heap->Release();
|
||||
if (r->pipeline_state) r->pipeline_state->Release();
|
||||
if (r->root_signature) r->root_signature->Release();
|
||||
|
||||
@@ -1133,6 +1141,23 @@ void renderer_end_frame(Renderer *r, Clay_RenderCommandArray render_commands) {
|
||||
batch.vertex_count = 0;
|
||||
batch.index_count = 0;
|
||||
|
||||
// Track which texture is currently bound (0 = font, 1 = icon)
|
||||
int bound_texture = 0;
|
||||
|
||||
auto bind_font = [&]() {
|
||||
if (bound_texture != 0) {
|
||||
flush_batch(r, &batch, buf_idx, r->srv_heap);
|
||||
bound_texture = 0;
|
||||
}
|
||||
};
|
||||
|
||||
auto bind_icon = [&]() {
|
||||
if (bound_texture != 1 && r->icon_srv_heap) {
|
||||
flush_batch(r, &batch, buf_idx);
|
||||
bound_texture = 1;
|
||||
}
|
||||
};
|
||||
|
||||
for (int32_t i = 0; i < render_commands.length; i++) {
|
||||
Clay_RenderCommand *cmd = Clay_RenderCommandArray_Get(&render_commands, i);
|
||||
Clay_BoundingBox bb = cmd->boundingBox;
|
||||
@@ -1177,6 +1202,7 @@ void renderer_end_frame(Renderer *r, Clay_RenderCommandArray render_commands) {
|
||||
} break;
|
||||
|
||||
case CLAY_RENDER_COMMAND_TYPE_TEXT: {
|
||||
bind_font();
|
||||
Clay_TextRenderData *text = &cmd->renderData.text;
|
||||
emit_text_glyphs(&batch, r, bb, text->textColor,
|
||||
text->stringContents.chars, text->stringContents.length,
|
||||
@@ -1185,7 +1211,8 @@ void renderer_end_frame(Renderer *r, Clay_RenderCommandArray render_commands) {
|
||||
|
||||
case CLAY_RENDER_COMMAND_TYPE_SCISSOR_START: {
|
||||
// Flush before changing scissor
|
||||
flush_batch(r, &batch, buf_idx);
|
||||
ID3D12DescriptorHeap *heap = bound_texture == 1 ? r->icon_srv_heap : r->srv_heap;
|
||||
flush_batch(r, &batch, buf_idx, heap);
|
||||
D3D12_RECT clip = {};
|
||||
clip.left = (LONG)Max(bb.x, 0.f);
|
||||
clip.top = (LONG)Max(bb.y, 0.f);
|
||||
@@ -1197,7 +1224,8 @@ void renderer_end_frame(Renderer *r, Clay_RenderCommandArray render_commands) {
|
||||
} break;
|
||||
|
||||
case CLAY_RENDER_COMMAND_TYPE_SCISSOR_END: {
|
||||
flush_batch(r, &batch, buf_idx);
|
||||
ID3D12DescriptorHeap *heap = bound_texture == 1 ? r->icon_srv_heap : r->srv_heap;
|
||||
flush_batch(r, &batch, buf_idx, heap);
|
||||
D3D12_RECT full_scissor = { 0, 0, (LONG)r->width, (LONG)r->height };
|
||||
r->command_list->RSSetScissorRects(1, &full_scissor);
|
||||
} break;
|
||||
@@ -1207,6 +1235,7 @@ void renderer_end_frame(Renderer *r, Clay_RenderCommandArray render_commands) {
|
||||
if (custom->customData) {
|
||||
CustomRenderType type = *(CustomRenderType *)custom->customData;
|
||||
if (type == CUSTOM_RENDER_VGRADIENT) {
|
||||
bind_font();
|
||||
CustomGradientData *grad = (CustomGradientData *)custom->customData;
|
||||
Clay_Color tc = grad->top_color;
|
||||
Clay_Color bc = grad->bottom_color;
|
||||
@@ -1217,6 +1246,20 @@ void renderer_end_frame(Renderer *r, Clay_RenderCommandArray render_commands) {
|
||||
custom->cornerRadius.topLeft, custom->cornerRadius.topRight,
|
||||
custom->cornerRadius.bottomRight, custom->cornerRadius.bottomLeft,
|
||||
1.0f);
|
||||
} else if (type == CUSTOM_RENDER_ICON) {
|
||||
bind_icon();
|
||||
CustomIconData *icon = (CustomIconData *)custom->customData;
|
||||
Clay_Color c = icon->color;
|
||||
float cr = c.r / 255.f, cg = c.g / 255.f;
|
||||
float cb = c.b / 255.f, ca = c.a / 255.f;
|
||||
UI_IconInfo *info = &g_icons[icon->icon_id];
|
||||
emit_quad(&batch,
|
||||
bb.x, bb.y, bb.x + bb.width, bb.y + bb.height,
|
||||
info->u0, info->v0, info->u1, info->v1,
|
||||
cr, cg, cb, ca,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 1.0f);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
@@ -1228,7 +1271,8 @@ void renderer_end_frame(Renderer *r, Clay_RenderCommandArray render_commands) {
|
||||
}
|
||||
|
||||
// Flush remaining
|
||||
flush_batch(r, &batch, buf_idx);
|
||||
ID3D12DescriptorHeap *heap = bound_texture == 1 ? r->icon_srv_heap : r->srv_heap;
|
||||
flush_batch(r, &batch, buf_idx, heap);
|
||||
}
|
||||
|
||||
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET;
|
||||
@@ -1245,6 +1289,101 @@ void renderer_end_frame(Renderer *r, Clay_RenderCommandArray render_commands) {
|
||||
r->frame_index++;
|
||||
}
|
||||
|
||||
void renderer_create_icon_atlas(Renderer *r, const uint8_t *data, int32_t w, int32_t h) {
|
||||
// Create texture resource
|
||||
D3D12_HEAP_PROPERTIES heap_props = {};
|
||||
heap_props.Type = D3D12_HEAP_TYPE_DEFAULT;
|
||||
|
||||
D3D12_RESOURCE_DESC tex_desc = {};
|
||||
tex_desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
|
||||
tex_desc.Width = w;
|
||||
tex_desc.Height = h;
|
||||
tex_desc.DepthOrArraySize = 1;
|
||||
tex_desc.MipLevels = 1;
|
||||
tex_desc.Format = DXGI_FORMAT_R8_UNORM;
|
||||
tex_desc.SampleDesc.Count = 1;
|
||||
tex_desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
|
||||
|
||||
r->device->CreateCommittedResource(&heap_props, D3D12_HEAP_FLAG_NONE,
|
||||
&tex_desc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr,
|
||||
IID_PPV_ARGS(&r->icon_texture));
|
||||
|
||||
// Upload via staging buffer
|
||||
D3D12_PLACED_SUBRESOURCE_FOOTPRINT footprint = {};
|
||||
UINT64 total_bytes = 0;
|
||||
r->device->GetCopyableFootprints(&tex_desc, 0, 1, 0, &footprint, nullptr, nullptr, &total_bytes);
|
||||
|
||||
D3D12_HEAP_PROPERTIES upload_heap = {};
|
||||
upload_heap.Type = D3D12_HEAP_TYPE_UPLOAD;
|
||||
|
||||
D3D12_RESOURCE_DESC upload_desc = {};
|
||||
upload_desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||
upload_desc.Width = total_bytes;
|
||||
upload_desc.Height = 1;
|
||||
upload_desc.DepthOrArraySize = 1;
|
||||
upload_desc.MipLevels = 1;
|
||||
upload_desc.SampleDesc.Count = 1;
|
||||
upload_desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||
|
||||
ID3D12Resource *upload_buf = nullptr;
|
||||
r->device->CreateCommittedResource(&upload_heap, D3D12_HEAP_FLAG_NONE,
|
||||
&upload_desc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr,
|
||||
IID_PPV_ARGS(&upload_buf));
|
||||
|
||||
void *mapped = nullptr;
|
||||
D3D12_RANGE read_range = {0, 0};
|
||||
upload_buf->Map(0, &read_range, &mapped);
|
||||
U8 *dst = (U8 *)mapped;
|
||||
for (int y = 0; y < h; y++) {
|
||||
memcpy(dst + y * footprint.Footprint.RowPitch, data + y * w, w);
|
||||
}
|
||||
upload_buf->Unmap(0, nullptr);
|
||||
|
||||
r->frames[0].command_allocator->Reset();
|
||||
r->command_list->Reset(r->frames[0].command_allocator, nullptr);
|
||||
|
||||
D3D12_TEXTURE_COPY_LOCATION src_loc = {};
|
||||
src_loc.pResource = upload_buf;
|
||||
src_loc.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
|
||||
src_loc.PlacedFootprint = footprint;
|
||||
|
||||
D3D12_TEXTURE_COPY_LOCATION dst_loc = {};
|
||||
dst_loc.pResource = r->icon_texture;
|
||||
dst_loc.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
||||
dst_loc.SubresourceIndex = 0;
|
||||
|
||||
r->command_list->CopyTextureRegion(&dst_loc, 0, 0, 0, &src_loc, nullptr);
|
||||
|
||||
D3D12_RESOURCE_BARRIER barrier = {};
|
||||
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
barrier.Transition.pResource = r->icon_texture;
|
||||
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST;
|
||||
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
|
||||
barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
||||
r->command_list->ResourceBarrier(1, &barrier);
|
||||
|
||||
r->command_list->Close();
|
||||
r->command_queue->ExecuteCommandLists(1, (ID3D12CommandList *const *)&r->command_list);
|
||||
wait_for_pending(r);
|
||||
upload_buf->Release();
|
||||
|
||||
// Create separate SRV heap for icon texture
|
||||
D3D12_DESCRIPTOR_HEAP_DESC srv_desc = {};
|
||||
srv_desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
|
||||
srv_desc.NumDescriptors = 1;
|
||||
srv_desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
|
||||
r->device->CreateDescriptorHeap(&srv_desc, IID_PPV_ARGS(&r->icon_srv_heap));
|
||||
|
||||
D3D12_SHADER_RESOURCE_VIEW_DESC srv_view = {};
|
||||
srv_view.Format = DXGI_FORMAT_R8_UNORM;
|
||||
srv_view.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
|
||||
srv_view.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
|
||||
srv_view.Texture2D.MipLevels = 1;
|
||||
|
||||
r->device->CreateShaderResourceView(r->icon_texture,
|
||||
&srv_view, r->icon_srv_heap->GetCPUDescriptorHandleForHeapStart());
|
||||
}
|
||||
|
||||
void renderer_resize(Renderer *r, int32_t width, int32_t height) {
|
||||
if (width <= 0 || height <= 0) return;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user