cache DirectWrite render targets
This commit is contained in:
parent
c140b6271b
commit
9fc666d49d
@ -51,41 +51,45 @@ GC_Run GC_RunFromString(Arena *arena, String str, GC_FontKey font, f32 font_size
|
|||||||
u32 *uncached_codepoints = PushStructsNoZero(scratch.arena, u32, codepoints_count);
|
u32 *uncached_codepoints = PushStructsNoZero(scratch.arena, u32, codepoints_count);
|
||||||
u64 uncached_codepoints_count = 0;
|
u64 uncached_codepoints_count = 0;
|
||||||
|
|
||||||
|
/* TODO: Include advances for glyphs in run that have rasterized but not finished uploading to atlas */
|
||||||
u64 pending_glyphs_count = 0;
|
u64 pending_glyphs_count = 0;
|
||||||
{
|
{
|
||||||
if (codepoints_count > 0)
|
if (codepoints_count > 0)
|
||||||
{
|
{
|
||||||
Lock lock = LockS(&GC.glyphs_mutex);
|
Lock lock = LockS(&GC.glyphs_mutex);
|
||||||
for (u64 codepoint_idx = 0; codepoint_idx < codepoints_count; ++codepoint_idx)
|
|
||||||
{
|
{
|
||||||
u32 codepoint = codepoints[codepoint_idx];
|
i64 completion = G_CompletionValueFromQueue(G_QueueKind_AsyncCopy);
|
||||||
|
for (u64 codepoint_idx = 0; codepoint_idx < codepoints_count; ++codepoint_idx)
|
||||||
|
{
|
||||||
|
u32 codepoint = codepoints[codepoint_idx];
|
||||||
|
|
||||||
GC_GlyphDesc desc = ZI;
|
GC_GlyphDesc desc = ZI;
|
||||||
desc.font = font;
|
desc.font = font;
|
||||||
desc.font_size = font_size;
|
desc.font_size = font_size;
|
||||||
desc.codepoint = codepoint;
|
desc.codepoint = codepoint;
|
||||||
|
|
||||||
u64 hash = GC_HashFromGlyphDesc(desc);
|
u64 hash = GC_HashFromGlyphDesc(desc);
|
||||||
GC_GlyphBin *bin = &GC.glyph_bins[hash % countof(GC.glyph_bins)];
|
GC_GlyphBin *bin = &GC.glyph_bins[hash % countof(GC.glyph_bins)];
|
||||||
GC_Glyph *glyph = bin->first;
|
GC_Glyph *glyph = bin->first;
|
||||||
for (; glyph; glyph = glyph->next)
|
for (; glyph; glyph = glyph->next)
|
||||||
{
|
{
|
||||||
if (glyph->hash == hash) break;
|
if (glyph->hash == hash) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (glyph == 0)
|
if (glyph == 0)
|
||||||
{
|
{
|
||||||
uncached_codepoints[uncached_codepoints_count] = codepoint;
|
uncached_codepoints[uncached_codepoints_count] = codepoint;
|
||||||
uncached_codepoints_count += 1;
|
uncached_codepoints_count += 1;
|
||||||
}
|
}
|
||||||
else if (Atomic32Fetch(&glyph->ready) == 0)
|
else if (completion < Atomic64Fetch(&glyph->async_copy_completion_target))
|
||||||
{
|
{
|
||||||
pending_glyphs_count += 1;
|
pending_glyphs_count += 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ready_glyphs[ready_glyphs_count] = glyph;
|
ready_glyphs[ready_glyphs_count] = glyph;
|
||||||
ready_glyphs_count += 1;
|
ready_glyphs_count += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Unlock(&lock);
|
Unlock(&lock);
|
||||||
@ -121,6 +125,7 @@ GC_Run GC_RunFromString(Arena *arena, String str, GC_FontKey font, f32 font_size
|
|||||||
glyph = PushStruct(perm, GC_Glyph);
|
glyph = PushStruct(perm, GC_Glyph);
|
||||||
glyph->desc = desc;
|
glyph->desc = desc;
|
||||||
glyph->hash = hash;
|
glyph->hash = hash;
|
||||||
|
Atomic64FetchSet(&glyph->async_copy_completion_target, I64Max);
|
||||||
SllStackPush(bin->first, glyph);
|
SllStackPush(bin->first, glyph);
|
||||||
/* Create cmd */
|
/* Create cmd */
|
||||||
{
|
{
|
||||||
@ -217,12 +222,14 @@ void GC_TickAsync(WaveLaneCtx *lane, AsyncTickCtx *tick)
|
|||||||
GC_AsyncCtx *async = &GC.async_ctx;
|
GC_AsyncCtx *async = &GC.async_ctx;
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Collect cmds
|
//- Begin tick
|
||||||
|
|
||||||
/* TODO: Limit cmds processed per-tick */
|
/* TODO: Limit cmds processed per-tick */
|
||||||
|
|
||||||
if (lane->idx == 0)
|
if (lane->idx == 0)
|
||||||
{
|
{
|
||||||
|
ZeroStruct(&async->cmds);
|
||||||
|
|
||||||
Lock lock = LockE(&GC.submit.mutex);
|
Lock lock = LockE(&GC.submit.mutex);
|
||||||
{
|
{
|
||||||
/* Pop cmds from submission queue */
|
/* Pop cmds from submission queue */
|
||||||
@ -245,12 +252,43 @@ void GC_TickAsync(WaveLaneCtx *lane, AsyncTickCtx *tick)
|
|||||||
|
|
||||||
WaveSync(lane);
|
WaveSync(lane);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Allocate atlas rects
|
//- Rasterize glyphs
|
||||||
|
|
||||||
|
/* TODO: Process cmds unevenly to account for varying work size */
|
||||||
|
|
||||||
|
{
|
||||||
|
RngU64 cmd_idxs = WaveIdxRangeFromCount(lane, async->cmds.count);
|
||||||
|
for (u64 cmd_idx = cmd_idxs.min; cmd_idx < cmd_idxs.max; ++cmd_idx)
|
||||||
|
{
|
||||||
|
GC_Cmd *cmd = &async->cmds.v[cmd_idx];
|
||||||
|
GC_Glyph *glyph = cmd->glyph;
|
||||||
|
ResourceKey resource = glyph->desc.font.r;
|
||||||
|
GC_GlyphDesc desc = glyph->desc;
|
||||||
|
TTF_GlyphResult ttf_result = TTF_RasterizeGlyphFromCodepoint(tick->arena, desc.codepoint, resource, desc.font_size);;
|
||||||
|
glyph->font_size = desc.font_size;
|
||||||
|
glyph->font_ascent = ttf_result.font_ascent;
|
||||||
|
glyph->font_descent = ttf_result.font_descent;
|
||||||
|
glyph->font_cap = ttf_result.font_cap;
|
||||||
|
glyph->advance = ttf_result.advance;
|
||||||
|
glyph->bounds = ttf_result.bounds;
|
||||||
|
cmd->rasterized = ttf_result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: Only sync first lane? */
|
||||||
|
|
||||||
|
WaveSync(lane);
|
||||||
|
|
||||||
|
////////////////////////////
|
||||||
|
//- Allocate atlas slices
|
||||||
|
|
||||||
if (lane->idx == 0)
|
if (lane->idx == 0)
|
||||||
{
|
{
|
||||||
/* TODO: Remove this */
|
/* FIXME: Dynamic atlases */
|
||||||
/* Create atlas */
|
/* Create atlas */
|
||||||
Vec2I32 atlas_dims = VEC2I32(8192, 8192);
|
Vec2I32 atlas_dims = VEC2I32(8192, 8192);
|
||||||
if (G_IsResourceNil(GC.atlas))
|
if (G_IsResourceNil(GC.atlas))
|
||||||
@ -270,27 +308,10 @@ void GC_TickAsync(WaveLaneCtx *lane, AsyncTickCtx *tick)
|
|||||||
{
|
{
|
||||||
GC_Cmd *cmd = &async->cmds.v[cmd_idx];
|
GC_Cmd *cmd = &async->cmds.v[cmd_idx];
|
||||||
GC_Glyph *glyph = cmd->glyph;
|
GC_Glyph *glyph = cmd->glyph;
|
||||||
|
|
||||||
ResourceKey resource = glyph->desc.font.r;
|
|
||||||
String resource_data = DataFromResource(resource);
|
|
||||||
String resource_name = NameFromResource(resource);
|
|
||||||
|
|
||||||
GC_GlyphDesc desc = glyph->desc;
|
GC_GlyphDesc desc = glyph->desc;
|
||||||
|
TTF_GlyphResult ttf_result = cmd->rasterized;
|
||||||
|
|
||||||
TTF_GlyphResult ttf_info = TTF_RasterizeGlyphFromCodepoint(tick->arena, desc.codepoint, resource, desc.font_size);
|
Vec2I32 image_dims = ttf_result.image_dims;
|
||||||
glyph->font_size = desc.font_size;
|
|
||||||
glyph->font_ascent = ttf_info.font_ascent;
|
|
||||||
glyph->font_descent = ttf_info.font_descent;
|
|
||||||
glyph->font_cap = ttf_info.font_cap;
|
|
||||||
glyph->advance = ttf_info.advance;
|
|
||||||
glyph->bounds = ttf_info.bounds;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
u32 *image_pixels = ttf_info.image_pixels;
|
|
||||||
Vec2I32 image_dims = ttf_info.image_dims;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Vec2I32 atlas_offset = GC.atlas_pos;
|
Vec2I32 atlas_offset = GC.atlas_pos;
|
||||||
GC.atlas_row_height = MaxI32(GC.atlas_row_height, image_dims.y);
|
GC.atlas_row_height = MaxI32(GC.atlas_row_height, image_dims.y);
|
||||||
@ -309,14 +330,36 @@ void GC_TickAsync(WaveLaneCtx *lane, AsyncTickCtx *tick)
|
|||||||
glyph->tex_slice_uv.p0.y = (f32)glyph->tex_slice.p0.y / (f32)atlas_dims.x;
|
glyph->tex_slice_uv.p0.y = (f32)glyph->tex_slice.p0.y / (f32)atlas_dims.x;
|
||||||
glyph->tex_slice_uv.p1.x = (f32)glyph->tex_slice.p1.x / (f32)atlas_dims.x;
|
glyph->tex_slice_uv.p1.x = (f32)glyph->tex_slice.p1.x / (f32)atlas_dims.x;
|
||||||
glyph->tex_slice_uv.p1.y = (f32)glyph->tex_slice.p1.y / (f32)atlas_dims.x;
|
glyph->tex_slice_uv.p1.y = (f32)glyph->tex_slice.p1.y / (f32)atlas_dims.x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WaveSync(lane);
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
//- Upload glyphs to atlas
|
||||||
|
|
||||||
|
{
|
||||||
|
RngU64 cmd_idxs = WaveIdxRangeFromCount(lane, async->cmds.count);
|
||||||
|
for (u64 cmd_idx = cmd_idxs.min; cmd_idx < cmd_idxs.max; ++cmd_idx)
|
||||||
|
{
|
||||||
|
GC_Cmd *cmd = &async->cmds.v[cmd_idx];
|
||||||
|
GC_Glyph *glyph = cmd->glyph;
|
||||||
|
ResourceKey resource = glyph->desc.font.r;
|
||||||
|
GC_GlyphDesc desc = glyph->desc;
|
||||||
|
TTF_GlyphResult ttf_result = TTF_RasterizeGlyphFromCodepoint(tick->arena, desc.codepoint, resource, desc.font_size);;
|
||||||
|
|
||||||
|
u32 *image_pixels = ttf_result.image_pixels;
|
||||||
|
Vec2I32 image_dims = ttf_result.image_dims;
|
||||||
|
|
||||||
|
i64 completion_target = 0;
|
||||||
if (image_dims.x > 0 && image_dims.y > 0)
|
if (image_dims.x > 0 && image_dims.y > 0)
|
||||||
{
|
{
|
||||||
G_CommandListHandle cl = G_PrepareCommandList(G_QueueKind_AsyncCopy);
|
G_CommandListHandle cl = G_PrepareCommandList(G_QueueKind_AsyncCopy);
|
||||||
{
|
{
|
||||||
|
|
||||||
G_CopyCpuToTexture(
|
G_CopyCpuToTexture(
|
||||||
cl,
|
cl,
|
||||||
GC.atlas, VEC3I32(atlas_offset.x, atlas_offset.y, 0),
|
GC.atlas, VEC3I32(glyph->tex_slice.p0.x, glyph->tex_slice.p0.y, 0),
|
||||||
image_pixels, VEC3I32(image_dims.x, image_dims.y, 1),
|
image_pixels, VEC3I32(image_dims.x, image_dims.y, 1),
|
||||||
RNG3I32(
|
RNG3I32(
|
||||||
VEC3I32(0, 0, 0),
|
VEC3I32(0, 0, 0),
|
||||||
@ -324,133 +367,13 @@ void GC_TickAsync(WaveLaneCtx *lane, AsyncTickCtx *tick)
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
G_CommitCommandList(cl);
|
completion_target = G_CommitCommandList(cl);
|
||||||
|
|
||||||
G_SyncCpu(G_QueueMask_All);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Atomic32Set(&glyph->ready, 1);
|
Atomic64Set(&glyph->async_copy_completion_target, completion_target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WaveSync(lane);
|
|
||||||
|
|
||||||
// //////////////////////////////
|
|
||||||
// //- Allocate atlas rects
|
|
||||||
|
|
||||||
// if (lane->idx == 0)
|
|
||||||
// {
|
|
||||||
// /* TODO: Remove this */
|
|
||||||
// /* Create atlas */
|
|
||||||
// Vec2I32 atlas_dims = VEC2I32(8192, 8192);
|
|
||||||
// if (G_IsResourceNil(GC.atlas))
|
|
||||||
// {
|
|
||||||
// G_ArenaHandle gpu_perm = G_PermArena();
|
|
||||||
// GC.atlas = G_PushTexture2D(
|
|
||||||
// gpu_perm,
|
|
||||||
// G_Format_R8G8B8A8_Unorm_Srgb,
|
|
||||||
// atlas_dims,
|
|
||||||
// /* FIXME: We may need simultaneous access? */
|
|
||||||
// G_Layout_AnyQueue_ShaderRead_CopyRead_CopyWrite_Present,
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
// for (u64 cmd_idx = 0; cmd_idx < async->cmds.count; ++cmd_idx)
|
|
||||||
// {
|
|
||||||
// GC_Cmd *cmd = &async->cmds.v[cmd_idx];
|
|
||||||
// GC_Glyph *glyph = cmd->glyph;
|
|
||||||
|
|
||||||
// ResourceKey resource = glyph->desc.font.r;
|
|
||||||
// String resource_data = DataFromResource(resource);
|
|
||||||
// String resource_name = NameFromResource(resource);
|
|
||||||
|
|
||||||
// GC_GlyphDesc desc = glyph->desc;
|
|
||||||
|
|
||||||
// TTF_GlyphDesc ttf_desc = TTF_GlyphDescFromCodepoint(desc.codepoint, resource, desc.font_size);
|
|
||||||
// glyph->font_size = ttf_desc.font_size;
|
|
||||||
// glyph->font_ascent = ttf_desc.font_ascent;
|
|
||||||
// glyph->font_descent = ttf_desc.font_descent;
|
|
||||||
// glyph->font_cap = ttf_desc.font_cap;
|
|
||||||
|
|
||||||
// glyph->advance = ttf_desc.advance;
|
|
||||||
// glyph->bounds = ttf_desc.bounds;
|
|
||||||
// Vec2 dims = DimsFromRng2(glyph->bounds);
|
|
||||||
|
|
||||||
// Vec2I32 atlas_offset = GC.atlas_pos;
|
|
||||||
// GC.atlas_row_height = MaxI32(GC.atlas_row_height, dims.y);
|
|
||||||
// if (atlas_offset.x + dims.x > atlas_dims.x);
|
|
||||||
// {
|
|
||||||
// GC.atlas_pos.x = 0;
|
|
||||||
// GC.atlas_pos.y += GC.atlas_row_height;
|
|
||||||
// GC.atlas_row_height = dims.y;
|
|
||||||
// }
|
|
||||||
// GC.atlas_pos.x += dims.x;
|
|
||||||
|
|
||||||
// Rng2I32 src_slice = ZI;
|
|
||||||
// src_slice.p0.x = 0;
|
|
||||||
// src_slice.p0.y = 0;
|
|
||||||
// src_slice.p1.x = RoundF32ToI32(dims.x);
|
|
||||||
// src_slice.p1.y = RoundF32ToI32(dims.y);
|
|
||||||
|
|
||||||
// Vec2I32 src_dims = DimsFromRng2I32(src_slice);
|
|
||||||
// if (src_dims.x > 0 && src_dims.y > 0)
|
|
||||||
// {
|
|
||||||
// u64 src_pixels_count = src_dims.x * src_dims.y;
|
|
||||||
// u32 *src_pixels = PushStructsNoZero(tick->arena, u32, src_pixels_count);
|
|
||||||
// TTF_RasterizeGlyph(src_pixels, src_dims, src_slice, ttf_desc);
|
|
||||||
|
|
||||||
// DEBUGBREAKABLE;
|
|
||||||
|
|
||||||
|
|
||||||
// // G_CommandListHandle cl = G_PrepareCommandList(G_QueueKind_AsyncCopy);
|
|
||||||
// G_CommandListHandle cl = G_PrepareCommandList(G_QueueKind_Direct);
|
|
||||||
// {
|
|
||||||
// G_CopyCpuToTexture(
|
|
||||||
// cl,
|
|
||||||
// GC.atlas, VEC3I32(atlas_offset.x, atlas_offset.y, 0),
|
|
||||||
// src_pixels, VEC3I32(src_dims.x, src_dims.y, 0),
|
|
||||||
// RNG3I32(
|
|
||||||
// VEC3I32(src_slice.p0.x, src_slice.p0.y, 0),
|
|
||||||
// VEC3I32(src_slice.p1.x, src_slice.p1.y, 1)
|
|
||||||
// )
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
// G_CommitCommandList(cl);
|
|
||||||
|
|
||||||
// G_SyncCpu(G_QueueMask_All);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Atomic32Set(&glyph->ready, 1);
|
|
||||||
|
|
||||||
// // ResourceKey resource = desc.font.r;
|
|
||||||
// // String resource_data = DataFromResource(resource);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// WaveSync(lane);
|
|
||||||
|
|
||||||
//////////////////////////////
|
|
||||||
//- Process cmds
|
|
||||||
|
|
||||||
/* TODO: Process cmds unevenly to account for varying work size */
|
|
||||||
|
|
||||||
// if (async->cmds.count > 0)
|
|
||||||
// {
|
|
||||||
// RngU64 cmd_idxs = WaveIdxRangeFromCount(lane, async->cmds.count);
|
|
||||||
// for (u64 cmd_idx = cmd_idxs.min; cmd_idx < cmd_idxs.max; ++cmd_idx)
|
|
||||||
// {
|
|
||||||
// GC_Cmd *cmd = &async->cmds.v[cmd_idx];
|
|
||||||
// GC_Glyph *glyph = cmd->glyph;
|
|
||||||
|
|
||||||
// GC_GlyphDesc desc = glyph->desc;
|
|
||||||
|
|
||||||
// ResourceKey resource = desc.font.r;
|
|
||||||
// String resource_data = DataFromResource(resource);
|
|
||||||
|
|
||||||
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- End tick
|
//- End tick
|
||||||
|
|
||||||
|
|||||||
@ -22,8 +22,7 @@ Struct(GC_Glyph)
|
|||||||
|
|
||||||
GC_GlyphDesc desc;
|
GC_GlyphDesc desc;
|
||||||
u64 hash;
|
u64 hash;
|
||||||
|
Atomic64 async_copy_completion_target;
|
||||||
Atomic32 ready;
|
|
||||||
|
|
||||||
/* Font info */
|
/* Font info */
|
||||||
f32 font_size;
|
f32 font_size;
|
||||||
@ -96,6 +95,9 @@ Struct(GC_Run)
|
|||||||
Struct(GC_Cmd)
|
Struct(GC_Cmd)
|
||||||
{
|
{
|
||||||
GC_Glyph *glyph;
|
GC_Glyph *glyph;
|
||||||
|
|
||||||
|
/* Async temporary data */
|
||||||
|
TTF_GlyphResult rasterized;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(GC_CmdNode)
|
Struct(GC_CmdNode)
|
||||||
|
|||||||
@ -729,7 +729,6 @@ i64 G_D12_CommitRawCommandList(G_D12_RawCommandList *cl)
|
|||||||
{
|
{
|
||||||
/* Execute */
|
/* Execute */
|
||||||
ID3D12CommandQueue_ExecuteCommandLists(queue->d3d_queue, 1, (ID3D12CommandList **)&cl->d3d_cl);
|
ID3D12CommandQueue_ExecuteCommandLists(queue->d3d_queue, 1, (ID3D12CommandList **)&cl->d3d_cl);
|
||||||
|
|
||||||
Lock lock = LockE(&queue->commit_mutex);
|
Lock lock = LockE(&queue->commit_mutex);
|
||||||
{
|
{
|
||||||
completion_target = ++queue->commit_fence_target;
|
completion_target = ++queue->commit_fence_target;
|
||||||
@ -1462,6 +1461,7 @@ G_D12_Cmd *G_D12_PushCmd(G_D12_CmdList *cl)
|
|||||||
|
|
||||||
/* Push cmd to chunk */
|
/* Push cmd to chunk */
|
||||||
G_D12_Cmd *cmd = &chunk->cmds[chunk->cmds_count++];
|
G_D12_Cmd *cmd = &chunk->cmds[chunk->cmds_count++];
|
||||||
|
ZeroStruct(cmd);
|
||||||
++cl->cmds_count;
|
++cl->cmds_count;
|
||||||
return cmd;
|
return cmd;
|
||||||
}
|
}
|
||||||
@ -1488,7 +1488,7 @@ G_D12_StagingRegionNode *G_D12_PushStagingRegion(G_D12_CmdList *cl, u64 size)
|
|||||||
{
|
{
|
||||||
G_D12_StagingRing *old_ring = 0;
|
G_D12_StagingRing *old_ring = 0;
|
||||||
G_D12_StagingRing *ring = queue->staging_ring;
|
G_D12_StagingRing *ring = queue->staging_ring;
|
||||||
i64 completed = ID3D12Fence_GetCompletedValue(queue->commit_fence);
|
i64 completion = ID3D12Fence_GetCompletedValue(queue->commit_fence);
|
||||||
|
|
||||||
/* Find first completed region with matching size.
|
/* Find first completed region with matching size.
|
||||||
* For each region in ring:
|
* For each region in ring:
|
||||||
@ -1504,9 +1504,6 @@ G_D12_StagingRegionNode *G_D12_PushStagingRegion(G_D12_CmdList *cl, u64 size)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* FIXME: Region completion target should be atomic, and initialized to
|
|
||||||
* u64/i64 max until cl submission actually sets value */
|
|
||||||
|
|
||||||
/* Find region with large enough size */
|
/* Find region with large enough size */
|
||||||
G_D12_StagingRegionNode *match = 0;
|
G_D12_StagingRegionNode *match = 0;
|
||||||
if (ring && ring->size >= size)
|
if (ring && ring->size >= size)
|
||||||
@ -1515,7 +1512,7 @@ G_D12_StagingRegionNode *G_D12_PushStagingRegion(G_D12_CmdList *cl, u64 size)
|
|||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
G_D12_StagingRegionNode *next = r->next;
|
G_D12_StagingRegionNode *next = r->next;
|
||||||
b32 is_completed = completed >= Atomic64Fetch(&r->completion_target);
|
b32 is_completed = completion >= Atomic64Fetch(&r->completion_target);
|
||||||
if (is_completed)
|
if (is_completed)
|
||||||
{
|
{
|
||||||
u64 region_size = 0;
|
u64 region_size = 0;
|
||||||
@ -1530,7 +1527,7 @@ G_D12_StagingRegionNode *G_D12_PushStagingRegion(G_D12_CmdList *cl, u64 size)
|
|||||||
|
|
||||||
if (region_size < size)
|
if (region_size < size)
|
||||||
{
|
{
|
||||||
b32 next_is_completed = completed >= Atomic64Fetch(&next->completion_target);
|
b32 next_is_completed = completion >= Atomic64Fetch(&next->completion_target);
|
||||||
if (next_is_completed)
|
if (next_is_completed)
|
||||||
{
|
{
|
||||||
if (next->pos > r->pos)
|
if (next->pos > r->pos)
|
||||||
@ -1587,8 +1584,7 @@ G_D12_StagingRegionNode *G_D12_PushStagingRegion(G_D12_CmdList *cl, u64 size)
|
|||||||
/* Queue old ring for deletion */
|
/* Queue old ring for deletion */
|
||||||
old_ring = ring;
|
old_ring = ring;
|
||||||
ring = 0;
|
ring = 0;
|
||||||
u64 new_ring_size = MaxU64(AlignU64ToNextPow2(size), Kibi(64));
|
u64 new_ring_size = MaxU64(AlignU64ToNextPow2(size), Mebi(8));
|
||||||
// u64 new_ring_size = MaxU64(AlignU64ToNextPow2(size), Kibi(128));
|
|
||||||
if (old_ring)
|
if (old_ring)
|
||||||
{
|
{
|
||||||
new_ring_size = MaxU64(new_ring_size, old_ring->size * 2);
|
new_ring_size = MaxU64(new_ring_size, old_ring->size * 2);
|
||||||
@ -1667,6 +1663,7 @@ G_D12_StagingRegionNode *G_D12_PushStagingRegion(G_D12_CmdList *cl, u64 size)
|
|||||||
if (old_ring)
|
if (old_ring)
|
||||||
{
|
{
|
||||||
/* FIXME: Queue old ring for deletion with command list */
|
/* FIXME: Queue old ring for deletion with command list */
|
||||||
|
DEBUGBREAKABLE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Unlock(&lock);
|
Unlock(&lock);
|
||||||
@ -2425,14 +2422,16 @@ void G_CopyCpuToTexture(G_CommandListHandle cl_handle, G_ResourceHandle dst_hand
|
|||||||
ID3D12Device_GetCopyableFootprints(g->device, &src_desc, 0, 1, 0, &footprint, (u32 *)&footprint_rows_count, &footprint_row_size, &footprint_size);
|
ID3D12Device_GetCopyableFootprints(g->device, &src_desc, 0, 1, 0, &footprint, (u32 *)&footprint_rows_count, &footprint_row_size, &footprint_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
G_D12_StagingRegionNode *region = G_D12_PushStagingRegion(cl, footprint_size);
|
G_D12_StagingRegionNode *staging_region = G_D12_PushStagingRegion(cl, footprint_size);
|
||||||
footprint.Offset = region->pos;
|
G_D12_Resource *staging_resource = staging_region->ring->resource;
|
||||||
|
G_ResourceHandle staging_resource_handle = G_D12_MakeHandle(G_ResourceHandle, staging_resource);
|
||||||
|
footprint.Offset = staging_region->pos;
|
||||||
|
|
||||||
/* Fill staging buffer */
|
/* Fill staging buffer */
|
||||||
{
|
{
|
||||||
D3D12_RANGE read_range = ZI;
|
D3D12_RANGE read_range = ZI;
|
||||||
u8 *src_base = src;
|
u8 *src_base = src;
|
||||||
u8 *dst_base = (u8 *)region->ring->base + footprint.Offset;
|
u8 *dst_base = (u8 *)staging_region->ring->base + footprint.Offset;
|
||||||
u32 z_size = footprint_row_size * footprint_rows_count;
|
u32 z_size = footprint_row_size * footprint_rows_count;
|
||||||
for (i32 z = 0; z < src_dims.z; ++z)
|
for (i32 z = 0; z < src_dims.z; ++z)
|
||||||
{
|
{
|
||||||
@ -2454,7 +2453,7 @@ void G_CopyCpuToTexture(G_CommandListHandle cl_handle, G_ResourceHandle dst_hand
|
|||||||
G_CopyBufferToTexture(
|
G_CopyBufferToTexture(
|
||||||
cl_handle,
|
cl_handle,
|
||||||
dst_handle, dst_copy_range,
|
dst_handle, dst_copy_range,
|
||||||
G_D12_MakeHandle(G_ResourceHandle, region->ring->resource), footprint.Offset
|
staging_resource_handle, footprint.Offset
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,8 +8,11 @@ V_WidgetTheme V_GetWidgetTheme(void)
|
|||||||
// theme.font = GC_FontKeyFromResource(ResourceKeyFromStore(&V_Resources, Lit("font/fixedsys.ttf")));
|
// theme.font = GC_FontKeyFromResource(ResourceKeyFromStore(&V_Resources, Lit("font/fixedsys.ttf")));
|
||||||
// theme.font_size = 16;
|
// theme.font_size = 16;
|
||||||
|
|
||||||
theme.font = GC_FontKeyFromResource(ResourceKeyFromStore(&V_Resources, Lit("font/roboto-med.ttf")));
|
theme.font = GC_FontKeyFromResource(ResourceKeyFromStore(&V_Resources, Lit("font/fixedsys.ttf")));
|
||||||
theme.font_size = 100;
|
theme.font_size = 64;
|
||||||
|
|
||||||
|
// theme.font = GC_FontKeyFromResource(ResourceKeyFromStore(&V_Resources, Lit("font/roboto-med.ttf")));
|
||||||
|
// theme.font_size = 100;
|
||||||
|
|
||||||
theme.window_background_color = Rgb32(0xff1a1d1e);
|
theme.window_background_color = Rgb32(0xff1a1d1e);
|
||||||
theme.window_border_color = Rgb32(0xff343a3b);
|
theme.window_border_color = Rgb32(0xff343a3b);
|
||||||
|
|||||||
@ -79,12 +79,13 @@ TTF_GlyphResult TTF_RasterizeGlyphFromCodepoint(Arena *arena, u32 codepoint, Res
|
|||||||
f32 em_size = font_size * (3.0 / 4.0);
|
f32 em_size = font_size * (3.0 / 4.0);
|
||||||
f32 pixels_per_em = em_size * (TTF_DW_Dpi / 72.0f);
|
f32 pixels_per_em = em_size * (TTF_DW_Dpi / 72.0f);
|
||||||
|
|
||||||
/* Load font */
|
//////////////////////////////
|
||||||
|
//- Load font
|
||||||
|
|
||||||
HRESULT hr = 0;
|
HRESULT hr = 0;
|
||||||
TTF_DW_Font *font = 0;
|
TTF_DW_Font *font = 0;
|
||||||
{
|
{
|
||||||
u64 hash = RandU64FromSeeds(ttf.v, (u64)(*(u32 *)&font_size));
|
u64 hash = RandU64FromSeeds(ttf.v, (u64)(*(u32 *)&font_size));
|
||||||
/* Grab font from cache */
|
|
||||||
{
|
{
|
||||||
Lock lock = LockS(&TTF_DW.font_bins_mutex);
|
Lock lock = LockS(&TTF_DW.font_bins_mutex);
|
||||||
{
|
{
|
||||||
@ -99,7 +100,6 @@ TTF_GlyphResult TTF_RasterizeGlyphFromCodepoint(Arena *arena, u32 codepoint, Res
|
|||||||
}
|
}
|
||||||
Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
/* Create font new font */
|
|
||||||
if (!font)
|
if (!font)
|
||||||
{
|
{
|
||||||
Lock lock = LockE(&TTF_DW.font_bins_mutex);
|
Lock lock = LockE(&TTF_DW.font_bins_mutex);
|
||||||
@ -172,11 +172,60 @@ TTF_GlyphResult TTF_RasterizeGlyphFromCodepoint(Arena *arena, u32 codepoint, Res
|
|||||||
f32 font_descent = font->design_metrics.descent * pixels_per_design_unit;
|
f32 font_descent = font->design_metrics.descent * pixels_per_design_unit;
|
||||||
f32 font_cap = font->design_metrics.capHeight * pixels_per_design_unit;
|
f32 font_cap = font->design_metrics.capHeight * pixels_per_design_unit;
|
||||||
|
|
||||||
/* Render glyph */
|
|
||||||
TTF_GlyphResult result = ZI;
|
TTF_GlyphResult result = ZI;
|
||||||
{
|
{
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
|
/* TODO: Dynamic render target dimensions? */
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
//- Fetch render target
|
||||||
|
|
||||||
|
Vec2I32 rt_dims = VEC2I32(256, 256);
|
||||||
|
TTF_DW_RenderTarget *rt = 0;
|
||||||
|
{
|
||||||
|
Lock lock = LockE(&TTF_DW.free_render_targets_mutex);
|
||||||
|
{
|
||||||
|
rt = TTF_DW.first_free_render_target;
|
||||||
|
if (rt)
|
||||||
|
{
|
||||||
|
SllStackPop(TTF_DW.first_free_render_target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Unlock(&lock);
|
||||||
|
if (!rt)
|
||||||
|
{
|
||||||
|
Arena *perm = PermArena();
|
||||||
|
rt = PushStruct(perm, TTF_DW_RenderTarget);
|
||||||
|
IDWriteBitmapRenderTarget *dw_rt = 0;
|
||||||
|
HDC dc = 0;
|
||||||
|
DIBSECTION dib = ZI;
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = IDWriteGdiInterop_CreateBitmapRenderTarget(TTF_DW.gdi_interop, 0, (UINT32)rt_dims.x, (UINT32)rt_dims.y, &dw_rt);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = IDWriteBitmapRenderTarget_SetPixelsPerDip(dw_rt, TTF_DW_Dpi / 96.0);
|
||||||
|
dc = IDWriteBitmapRenderTarget_GetMemoryDC(dw_rt);
|
||||||
|
HBITMAP bitmap = (HBITMAP)GetCurrentObject(dc, OBJ_BITMAP);
|
||||||
|
GetObject(bitmap, sizeof(dib), &dib);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rt->dims = rt_dims;
|
||||||
|
rt->dw_rt = dw_rt;
|
||||||
|
rt->dc = dc;
|
||||||
|
rt->dib = dib;
|
||||||
|
rt->hr = hr;
|
||||||
|
}
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = font->hr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
//- Render
|
||||||
|
|
||||||
/* Glyph idx */
|
/* Glyph idx */
|
||||||
u16 glyph_idx = 0;
|
u16 glyph_idx = 0;
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
@ -192,44 +241,25 @@ TTF_GlyphResult TTF_RasterizeGlyphFromCodepoint(Arena *arena, u32 codepoint, Res
|
|||||||
}
|
}
|
||||||
f32 advance = (f32)m.advanceWidth * pixels_per_design_unit;
|
f32 advance = (f32)m.advanceWidth * pixels_per_design_unit;
|
||||||
|
|
||||||
/* FIXME: Dynamic render target */
|
|
||||||
Vec2I32 rt_dims = VEC2I32(256, 256);
|
|
||||||
|
|
||||||
/* Best-guess a position in the middle of the render target based on metrics */
|
/* Best-guess a position in the middle of the render target based on metrics */
|
||||||
Vec2I32 rt_baseline = ZI;
|
Vec2I32 rt_baseline = ZI;
|
||||||
rt_baseline.x = (rt_dims.x / 2) - (advance / 2);
|
rt_baseline.x = (rt_dims.x / 2) - (advance / 2);
|
||||||
rt_baseline.y = (rt_dims.y / 2) + (font_cap / 2);
|
rt_baseline.y = (rt_dims.y / 2) + (font_cap / 2);
|
||||||
|
|
||||||
/* Create render target */
|
|
||||||
IDWriteBitmapRenderTarget *render_target = 0;
|
|
||||||
HDC dc = 0;
|
|
||||||
DIBSECTION dib = ZI;
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
hr = IDWriteGdiInterop_CreateBitmapRenderTarget(TTF_DW.gdi_interop, 0, (UINT32)rt_dims.x, (UINT32)rt_dims.y, &render_target);
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
hr = IDWriteBitmapRenderTarget_SetPixelsPerDip(render_target, TTF_DW_Dpi / 96.0);
|
|
||||||
dc = IDWriteBitmapRenderTarget_GetMemoryDC(render_target);
|
|
||||||
HBITMAP bitmap = (HBITMAP)GetCurrentObject(dc, OBJ_BITMAP);
|
|
||||||
GetObject(bitmap, sizeof(dib), &dib);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Render */
|
/* Render */
|
||||||
Rng2I32 rt_slice = ZI;
|
Rng2I32 rt_slice = ZI;
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
/* Clear target */
|
/* Clear target */
|
||||||
{
|
{
|
||||||
HGDIOBJ original = SelectObject(dc, GetStockObject(DC_PEN));
|
HGDIOBJ original = SelectObject(rt->dc, GetStockObject(DC_PEN));
|
||||||
{
|
{
|
||||||
SetDCPenColor(dc, bg_color);
|
SetDCPenColor(rt->dc, bg_color);
|
||||||
SelectObject(dc, GetStockObject(DC_BRUSH));
|
SelectObject(rt->dc, GetStockObject(DC_BRUSH));
|
||||||
SetDCBrushColor(dc, bg_color);
|
SetDCBrushColor(rt->dc, bg_color);
|
||||||
Rectangle(dc, 0, 0, rt_dims.x, rt_dims.y);
|
Rectangle(rt->dc, 0, 0, rt_dims.x, rt_dims.y);
|
||||||
}
|
}
|
||||||
SelectObject(dc, original);
|
SelectObject(rt->dc, original);
|
||||||
}
|
}
|
||||||
/* Draw glyph */
|
/* Draw glyph */
|
||||||
{
|
{
|
||||||
@ -242,7 +272,7 @@ TTF_GlyphResult TTF_RasterizeGlyphFromCodepoint(Arena *arena, u32 codepoint, Res
|
|||||||
}
|
}
|
||||||
RECT bounding_box = ZI;
|
RECT bounding_box = ZI;
|
||||||
hr = IDWriteBitmapRenderTarget_DrawGlyphRun(
|
hr = IDWriteBitmapRenderTarget_DrawGlyphRun(
|
||||||
render_target,
|
rt->dw_rt,
|
||||||
rt_baseline.x,
|
rt_baseline.x,
|
||||||
rt_baseline.y,
|
rt_baseline.y,
|
||||||
DWRITE_MEASURING_MODE_NATURAL,
|
DWRITE_MEASURING_MODE_NATURAL,
|
||||||
@ -262,6 +292,9 @@ TTF_GlyphResult TTF_RasterizeGlyphFromCodepoint(Arena *arena, u32 codepoint, Res
|
|||||||
rt_slice.p1.y = MinI32(rt_slice.p1.y, rt_dims.y);
|
rt_slice.p1.y = MinI32(rt_slice.p1.y, rt_dims.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
//- Copy result
|
||||||
|
|
||||||
/* Copy from target to result */
|
/* Copy from target to result */
|
||||||
Vec2I32 dst_dims = ZI;
|
Vec2I32 dst_dims = ZI;
|
||||||
u32 *dst_pixels = 0;
|
u32 *dst_pixels = 0;
|
||||||
@ -269,8 +302,8 @@ TTF_GlyphResult TTF_RasterizeGlyphFromCodepoint(Arena *arena, u32 codepoint, Res
|
|||||||
{
|
{
|
||||||
dst_dims = DimsFromRng2I32(rt_slice);
|
dst_dims = DimsFromRng2I32(rt_slice);
|
||||||
dst_pixels = PushStructsNoZero(arena, u32, dst_dims.x * dst_dims.y);
|
dst_pixels = PushStructsNoZero(arena, u32, dst_dims.x * dst_dims.y);
|
||||||
u64 src_pitch = (u64)dib.dsBm.bmWidthBytes / 4;
|
u64 src_pitch = (u64)rt->dib.dsBm.bmWidthBytes / 4;
|
||||||
u32 *src_pixels = (u32 *)dib.dsBm.bmBits;
|
u32 *src_pixels = (u32 *)rt->dib.dsBm.bmBits;
|
||||||
for (i32 y = 0; y < dst_dims.y; ++y)
|
for (i32 y = 0; y < dst_dims.y; ++y)
|
||||||
{
|
{
|
||||||
u64 src_y = rt_slice.p0.y + y;
|
u64 src_y = rt_slice.p0.y + y;
|
||||||
@ -292,7 +325,12 @@ TTF_GlyphResult TTF_RasterizeGlyphFromCodepoint(Arena *arena, u32 codepoint, Res
|
|||||||
result.image_dims = dst_dims;
|
result.image_dims = dst_dims;
|
||||||
result.image_pixels = dst_pixels;
|
result.image_pixels = dst_pixels;
|
||||||
|
|
||||||
IDWriteBitmapRenderTarget_Release(render_target);
|
/* Free render target */
|
||||||
|
{
|
||||||
|
Lock lock = LockE(&TTF_DW.free_render_targets_mutex);
|
||||||
|
SllStackPush(TTF_DW.first_free_render_target, rt);
|
||||||
|
Unlock(&lock);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
result.ttf = ttf;
|
result.ttf = ttf;
|
||||||
result.codepoint = codepoint;
|
result.codepoint = codepoint;
|
||||||
|
|||||||
@ -158,6 +158,16 @@ Struct(TTF_DW_Font)
|
|||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Struct(TTF_DW_RenderTarget)
|
||||||
|
{
|
||||||
|
TTF_DW_RenderTarget *next;
|
||||||
|
Vec2I32 dims;
|
||||||
|
IDWriteBitmapRenderTarget *dw_rt;
|
||||||
|
HDC dc;
|
||||||
|
DIBSECTION dib;
|
||||||
|
HRESULT hr;
|
||||||
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Context types
|
//~ Context types
|
||||||
|
|
||||||
@ -174,6 +184,9 @@ Struct(TTF_DW_Ctx)
|
|||||||
|
|
||||||
Mutex font_bins_mutex;
|
Mutex font_bins_mutex;
|
||||||
TTF_DW_Font *font_bins[1024];
|
TTF_DW_Font *font_bins[1024];
|
||||||
|
|
||||||
|
Mutex free_render_targets_mutex;
|
||||||
|
TTF_DW_RenderTarget *first_free_render_target;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern TTF_DW_Ctx TTF_DW;
|
extern TTF_DW_Ctx TTF_DW;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user