Skip to content

Commit 436843e

Browse files
committed
Use only one encoder in RendererD3D9::Draw()
1 parent a0b200b commit 436843e

File tree

10 files changed

+210
-82
lines changed

10 files changed

+210
-82
lines changed

demo/common/blit.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ void Blit::set_texture(const std::shared_ptr<Texture> &new_texture) {
8484
void Blit::draw(const std::shared_ptr<CommandEncoder> &encoder) {
8585
encoder->bind_render_pipeline(pipeline_);
8686

87-
encoder->bind_vertex_buffers({vertex_buffer_});
87+
encoder->bind_vertex_buffers({{vertex_buffer_, 0}});
8888

8989
encoder->bind_descriptor_set(descriptor_set_);
9090

pathfinder/core/d3d11/gpu_data.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ struct SegmentsD3D11 {
201201
std::vector<Vec2F> points;
202202
std::vector<SegmentIndicesD3D11> indices;
203203

204-
/// Add a outline as segments.
204+
/// Add an outline as segments.
205205
Range add_path(const Outline &outline);
206206
};
207207

pathfinder/core/d3d9/renderer.cpp

Lines changed: 118 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ constexpr size_t CLIP_TILE_INSTANCE_SIZE = 16;
4343
// 65536
4444
constexpr size_t MAX_FILLS_PER_BATCH = 0x10000;
4545

46+
constexpr uint32_t DEFAULT_TILE_BATCH_COUNT = 10;
47+
4648
RendererD3D9::RendererD3D9(const std::shared_ptr<Device> &_device, const std::shared_ptr<Queue> &_queue)
4749
: Renderer(_device, _queue) {
4850
mask_render_pass_clear =
@@ -80,6 +82,44 @@ std::shared_ptr<Texture> RendererD3D9::get_dest_texture() {
8082
return dest_texture;
8183
}
8284

85+
void RendererD3D9::update_tile_batch_storage(uint32_t new_tile_batch_count) {
86+
if (tile_batch_storage_count > 0) {
87+
allocator->free_buffer(tile_ub_id);
88+
}
89+
90+
// Create a new uniform buffer.
91+
tile_ub_id = allocator->allocate_buffer(new_tile_batch_count * sizeof(TileUniformD3d9),
92+
BufferType::Uniform,
93+
"tile uniform buffer");
94+
95+
for (int i = tile_batch_storage_count; i < new_tile_batch_count; i++) {
96+
// Set descriptor set.
97+
auto tile_descriptor_set = device->create_descriptor_set();
98+
tile_descriptor_set->add_or_update({
99+
Descriptor::sampled(0, ShaderStage::Vertex, "uTextureMetadata"),
100+
Descriptor::sampled(1, ShaderStage::Vertex, "uZBuffer"),
101+
Descriptor::uniform(2, ShaderStage::VertexAndFragment, "bUniform", allocator->get_buffer(tile_ub_id)),
102+
Descriptor::sampled(3, ShaderStage::Fragment, "uColorTexture0"),
103+
Descriptor::sampled(4, ShaderStage::Fragment, "uMaskTexture0"),
104+
// Unused binding.
105+
Descriptor::sampled(5,
106+
ShaderStage::Fragment,
107+
"uDestTexture",
108+
allocator->get_texture(dummy_texture_id),
109+
get_default_sampler()),
110+
// Unused binding.
111+
Descriptor::sampled(6,
112+
ShaderStage::Fragment,
113+
"uGammaLUT",
114+
allocator->get_texture(dummy_texture_id),
115+
get_default_sampler()),
116+
});
117+
tile_descriptor_sets.push_back(tile_descriptor_set);
118+
}
119+
120+
tile_batch_storage_count = new_tile_batch_count;
121+
}
122+
83123
void RendererD3D9::set_up_pipelines() {
84124
// Fill pipeline.
85125
{
@@ -170,30 +210,7 @@ void RendererD3D9::set_up_pipelines() {
170210
{1, 1, DataType::u32, stride, offsetof(TileObjectPrimitive, metadata_id), VertexInputRate::Instance});
171211
}
172212

173-
// Create uniform buffer.
174-
tile_ub_id = allocator->allocate_buffer(sizeof(TileUniformD3d9), BufferType::Uniform, "tile uniform buffer");
175-
176-
// Set descriptor set.
177-
tile_descriptor_set = device->create_descriptor_set();
178-
tile_descriptor_set->add_or_update({
179-
Descriptor::sampled(0, ShaderStage::Vertex, "uTextureMetadata"),
180-
Descriptor::sampled(1, ShaderStage::Vertex, "uZBuffer"),
181-
Descriptor::uniform(2, ShaderStage::VertexAndFragment, "bUniform", allocator->get_buffer(tile_ub_id)),
182-
Descriptor::sampled(3, ShaderStage::Fragment, "uColorTexture0"),
183-
Descriptor::sampled(4, ShaderStage::Fragment, "uMaskTexture0"),
184-
// Unused binding.
185-
Descriptor::sampled(5,
186-
ShaderStage::Fragment,
187-
"uDestTexture",
188-
allocator->get_texture(dummy_texture_id),
189-
get_default_sampler()),
190-
// Unused binding.
191-
Descriptor::sampled(6,
192-
ShaderStage::Fragment,
193-
"uGammaLUT",
194-
allocator->get_texture(dummy_texture_id),
195-
get_default_sampler()),
196-
});
213+
update_tile_batch_storage(DEFAULT_TILE_BATCH_COUNT);
197214

198215
auto tile_vert_shader = device->create_shader_module(tile_vert_source, ShaderStage::Vertex, "tile vert");
199216
auto tile_frag_shader = device->create_shader_module(tile_frag_source, ShaderStage::Fragment, "tile frag");
@@ -202,7 +219,7 @@ void RendererD3D9::set_up_pipelines() {
202219
tile_frag_shader,
203220
attribute_descriptions,
204221
BlendState::from_over(),
205-
tile_descriptor_set,
222+
tile_descriptor_sets.front(),
206223
TextureFormat::Rgba8Unorm,
207224
"tile pipeline");
208225
}
@@ -218,7 +235,7 @@ TextureFormat RendererD3D9::mask_texture_format() const {
218235

219236
void RendererD3D9::reallocate_alpha_tile_pages_if_necessary() {
220237
// Make sure at least one page is allocated even when thers's no alpha tile.
221-
// Bacause we use `*mask_storage.framebuffer_id` in several places.
238+
// Because we use `*mask_storage.framebuffer_id` in several places.
222239
uint32_t alpha_tile_pages_needed = std::max((alpha_tile_count + 0xffff) >> 16, 1u);
223240

224241
if (alpha_tile_pages_needed <= mask_storage.allocated_page_count) {
@@ -353,23 +370,48 @@ void RendererD3D9::draw(const std::shared_ptr<SceneBuilder> &_scene_builder, boo
353370

354371
reallocate_alpha_tile_pages_if_necessary();
355372

373+
auto encoder = device->create_command_encoder("upload & draw fills, tiles");
374+
375+
uint64_t *fill_vertex_buffer_id = nullptr;
376+
356377
// No fills to draw.
357378
if (!scene_builder->pending_fills.empty()) {
358-
auto encoder = device->create_command_encoder("upload & draw fills");
359-
360379
// Upload fills to buffer.
361-
auto fill_vertex_buffer_id = upload_fills(scene_builder->pending_fills, encoder);
380+
fill_vertex_buffer_id = new uint64_t;
381+
*fill_vertex_buffer_id = upload_fills(scene_builder->pending_fills, encoder);
362382

363383
// We can do fill drawing as soon as the fill vertex buffer is ready.
364-
draw_fills(fill_vertex_buffer_id, scene_builder->pending_fills.size(), encoder);
384+
draw_fills(*fill_vertex_buffer_id, scene_builder->pending_fills.size(), encoder);
385+
}
386+
387+
upload_and_draw_tiles(scene_builder->tile_batches, encoder);
365388

366-
queue->submit(encoder, fence);
389+
queue->submit(encoder, fence);
367390

368-
allocator->free_buffer(fill_vertex_buffer_id);
391+
// Clean up.
392+
if (fill_vertex_buffer_id) {
393+
allocator->free_buffer(*fill_vertex_buffer_id);
369394
}
370395

371-
// Tiles need to be drawn after fill drawing and after tile batches are prepared.
372-
upload_and_draw_tiles(scene_builder->tile_batches);
396+
for (auto tile_vertex_buffer_id : tile_vertex_buffer_ids) {
397+
allocator->free_buffer(tile_vertex_buffer_id);
398+
}
399+
tile_vertex_buffer_ids.clear();
400+
401+
for (auto z_buffer_texture_id : z_buffer_texture_ids) {
402+
allocator->free_texture(z_buffer_texture_id);
403+
}
404+
z_buffer_texture_ids.clear();
405+
406+
for (auto clip_buffer_info : clip_buffer_infos) {
407+
allocator->free_buffer(clip_buffer_info.clip_buffer_id);
408+
}
409+
clip_buffer_infos.clear();
410+
411+
if (temp_mask_texture_id) {
412+
allocator->free_texture(*temp_mask_texture_id);
413+
temp_mask_texture_id = nullptr;
414+
}
373415
}
374416

375417
uint64_t RendererD3D9::upload_fills(const std::vector<Fill> &fills,
@@ -408,8 +450,15 @@ uint64_t RendererD3D9::upload_tiles(const std::vector<TileObjectPrimitive> &tile
408450
return tile_vertex_buffer_id;
409451
}
410452

411-
void RendererD3D9::upload_and_draw_tiles(const std::vector<DrawTileBatchD3D9> &tile_batches) {
412-
// One draw call for one batch.
453+
void RendererD3D9::upload_and_draw_tiles(const std::vector<DrawTileBatchD3D9> &tile_batches,
454+
const std::shared_ptr<CommandEncoder> &encoder) {
455+
int tile_batch_idx = 0;
456+
457+
if (tile_batches.size() > tile_batch_storage_count) {
458+
update_tile_batch_storage(tile_batches.size());
459+
}
460+
461+
// One draw call for each batch.
413462
for (const auto &batch : tile_batches) {
414463
uint32_t tile_count = batch.tiles.size();
415464

@@ -418,34 +467,30 @@ void RendererD3D9::upload_and_draw_tiles(const std::vector<DrawTileBatchD3D9> &t
418467
continue;
419468
}
420469

421-
// Different batches will use the same tile vertex buffer, so we need to make sure
422-
// that a batch is done drawing before processing the next batch.
423-
auto encoder = device->create_command_encoder("upload & draw tiles");
424-
425470
// Apply clip paths.
426471
if (!batch.clips.empty()) {
427472
auto clip_buffer_info = upload_clip_tiles(batch.clips, encoder);
428473
clip_tiles(clip_buffer_info, encoder);
429-
// Although the command buffer is not submitted yet,
430-
// it's safe to free it here since the GPU resources are not actually freed.
431-
allocator->free_buffer(clip_buffer_info.clip_buffer_id);
474+
475+
clip_buffer_infos.push_back(clip_buffer_info);
432476
}
433477

434478
auto tile_vertex_buffer_id = upload_tiles(batch.tiles, encoder);
479+
tile_vertex_buffer_ids.push_back(tile_vertex_buffer_id);
435480

436481
auto z_buffer_texture_id = upload_z_buffer(batch.z_buffer_data, encoder);
482+
z_buffer_texture_ids.push_back(z_buffer_texture_id);
437483

438484
draw_tiles(tile_vertex_buffer_id,
439485
tile_count,
440486
batch.render_target_id,
441487
batch.color_texture_info,
442488
z_buffer_texture_id,
443-
encoder);
444-
445-
queue->submit(encoder, fence);
489+
encoder,
490+
tile_descriptor_sets[tile_batch_idx],
491+
tile_batch_idx * sizeof(TileUniformD3d9));
446492

447-
allocator->free_texture(z_buffer_texture_id);
448-
allocator->free_buffer(tile_vertex_buffer_id);
493+
tile_batch_idx++;
449494
}
450495
}
451496

@@ -466,7 +511,7 @@ void RendererD3D9::draw_fills(uint64_t fill_vertex_buffer_id,
466511
encoder->bind_render_pipeline(fill_pipeline);
467512

468513
encoder->bind_vertex_buffers(
469-
{allocator->get_buffer(quad_vertex_buffer_id), allocator->get_buffer(fill_vertex_buffer_id)});
514+
{{allocator->get_buffer(quad_vertex_buffer_id), 0}, {allocator->get_buffer(fill_vertex_buffer_id), 0}});
470515

471516
encoder->bind_descriptor_set(fill_descriptor_set);
472517

@@ -491,12 +536,15 @@ ClipBufferInfo RendererD3D9::upload_clip_tiles(const std::vector<Clip> &clips,
491536

492537
void RendererD3D9::clip_tiles(const ClipBufferInfo &clip_buffer_info, const std::shared_ptr<CommandEncoder> &encoder) {
493538
// A temporary mask framebuffer for clipping.
494-
auto temp_mask_texture_id = allocator->allocate_texture(
495-
Vec2I(MASK_FRAMEBUFFER_WIDTH, MASK_FRAMEBUFFER_HEIGHT * mask_storage.allocated_page_count),
496-
TextureFormat::Rgba16Float,
497-
"temp mask texture");
539+
if (!temp_mask_texture_id) {
540+
temp_mask_texture_id = new uint64_t;
541+
*temp_mask_texture_id = allocator->allocate_texture(
542+
Vec2I(MASK_FRAMEBUFFER_WIDTH, MASK_FRAMEBUFFER_HEIGHT * mask_storage.allocated_page_count),
543+
TextureFormat::Rgba16Float,
544+
"temp mask texture");
545+
}
498546

499-
auto temp_mask_texture = allocator->get_texture(temp_mask_texture_id);
547+
auto temp_mask_texture = allocator->get_texture(*temp_mask_texture_id);
500548

501549
auto clip_vertex_buffer = allocator->get_buffer(clip_buffer_info.clip_buffer_id);
502550

@@ -517,7 +565,7 @@ void RendererD3D9::clip_tiles(const ClipBufferInfo &clip_buffer_info, const std:
517565

518566
encoder->bind_render_pipeline(tile_clip_copy_pipeline);
519567

520-
encoder->bind_vertex_buffers({allocator->get_buffer(quad_vertex_buffer_id), clip_vertex_buffer});
568+
encoder->bind_vertex_buffers({{allocator->get_buffer(quad_vertex_buffer_id), 0}, {clip_vertex_buffer, 0}});
521569

522570
encoder->bind_descriptor_set(tile_clip_copy_descriptor_set);
523571

@@ -539,24 +587,24 @@ void RendererD3D9::clip_tiles(const ClipBufferInfo &clip_buffer_info, const std:
539587

540588
encoder->bind_render_pipeline(tile_clip_combine_pipeline);
541589

542-
encoder->bind_vertex_buffers({allocator->get_buffer(quad_vertex_buffer_id), clip_vertex_buffer});
590+
encoder->bind_vertex_buffers({{allocator->get_buffer(quad_vertex_buffer_id), 0}, {clip_vertex_buffer, 0}});
543591

544592
encoder->bind_descriptor_set(tile_clip_combine_descriptor_set);
545593

546594
encoder->draw_instanced(6, clip_buffer_info.clip_count);
547595

548596
encoder->end_render_pass();
549597
}
550-
551-
allocator->free_texture(temp_mask_texture_id);
552598
}
553599

554600
void RendererD3D9::draw_tiles(uint64_t tile_vertex_buffer_id,
555601
uint32_t tiles_count,
556602
const std::shared_ptr<const RenderTargetId> &render_target_id,
557603
const std::shared_ptr<const TileBatchTextureInfo> &color_texture_info,
558604
uint64_t z_buffer_texture_id,
559-
const std::shared_ptr<CommandEncoder> &encoder) {
605+
const std::shared_ptr<CommandEncoder> &encoder,
606+
const std::shared_ptr<DescriptorSet> &tile_descriptor_set,
607+
uint64_t tile_uniform_offset) {
560608
std::shared_ptr<Texture> target_texture;
561609

562610
// If no specific RenderTarget is given, we render to the dst framebuffer.
@@ -632,7 +680,10 @@ void RendererD3D9::draw_tiles(uint64_t tile_vertex_buffer_id,
632680

633681
// We don't need to preserve the data until the upload commands are implemented because
634682
// these uniform buffers are host-visible/coherent.
635-
encoder->write_buffer(allocator->get_buffer(tile_ub_id), 0, sizeof(TileUniformD3d9), &tile_uniform);
683+
encoder->write_buffer(allocator->get_buffer(tile_ub_id),
684+
tile_uniform_offset,
685+
sizeof(TileUniformD3d9),
686+
&tile_uniform);
636687
}
637688

638689
// Update descriptor set.
@@ -643,6 +694,12 @@ void RendererD3D9::draw_tiles(uint64_t tile_vertex_buffer_id,
643694
allocator->get_texture(metadata_texture_id),
644695
default_sampler),
645696
Descriptor::sampled(1, ShaderStage::Vertex, "uZBuffer", z_buffer_texture, default_sampler),
697+
Descriptor::uniform(2,
698+
ShaderStage::VertexAndFragment,
699+
"bUniform",
700+
allocator->get_buffer(tile_ub_id),
701+
tile_uniform_offset,
702+
sizeof(TileUniformD3d9)),
646703
Descriptor::sampled(3, ShaderStage::Fragment, "uColorTexture0", color_texture, color_texture_sampler),
647704
Descriptor::sampled(4,
648705
ShaderStage::Fragment,
@@ -654,7 +711,7 @@ void RendererD3D9::draw_tiles(uint64_t tile_vertex_buffer_id,
654711
encoder->bind_render_pipeline(tile_pipeline);
655712

656713
encoder->bind_vertex_buffers(
657-
{allocator->get_buffer(quad_vertex_buffer_id), allocator->get_buffer(tile_vertex_buffer_id)});
714+
{{allocator->get_buffer(quad_vertex_buffer_id), 0}, {allocator->get_buffer(tile_vertex_buffer_id), 0}});
658715

659716
encoder->bind_descriptor_set(tile_descriptor_set);
660717

pathfinder/core/d3d9/renderer.h

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,22 @@ class RendererD3D9 : public Renderer {
5454
std::shared_ptr<RenderPipeline> tile_clip_copy_pipeline, tile_clip_combine_pipeline; // For clip paths.
5555

5656
/// Descriptor sets.
57-
std::shared_ptr<DescriptorSet> fill_descriptor_set, tile_descriptor_set;
57+
std::shared_ptr<DescriptorSet> fill_descriptor_set;
5858
std::shared_ptr<DescriptorSet> tile_clip_copy_descriptor_set, tile_clip_combine_descriptor_set; // For clip paths.
5959

60+
std::vector<std::shared_ptr<DescriptorSet>> tile_descriptor_sets;
61+
6062
/// Uniform buffers.
6163
uint64_t fill_ub_id, tile_ub_id;
6264

65+
uint32_t tile_batch_storage_count = 0;
66+
67+
// Temp
68+
std::vector<uint64_t> tile_vertex_buffer_ids;
69+
std::vector<uint64_t> z_buffer_texture_ids;
70+
std::vector<ClipBufferInfo> clip_buffer_infos;
71+
uint64_t *temp_mask_texture_id = nullptr;
72+
6373
/// Where the final rendering output goes.
6474
/// This is not managed by the memory allocator.
6575
std::shared_ptr<Texture> dest_texture;
@@ -88,7 +98,8 @@ class RendererD3D9 : public Renderer {
8898

8999
void create_tile_clip_combine_pipeline();
90100

91-
void upload_and_draw_tiles(const std::vector<DrawTileBatchD3D9> &tile_batches);
101+
void upload_and_draw_tiles(const std::vector<DrawTileBatchD3D9> &tile_batches,
102+
const std::shared_ptr<CommandEncoder> &encoder);
92103

93104
/// Upload fills data to GPU.
94105
uint64_t upload_fills(const std::vector<Fill> &fills, const std::shared_ptr<CommandEncoder> &encoder) const;
@@ -112,12 +123,16 @@ class RendererD3D9 : public Renderer {
112123
const std::shared_ptr<const RenderTargetId> &render_target_id,
113124
const std::shared_ptr<const TileBatchTextureInfo> &color_texture_info,
114125
uint64_t z_buffer_texture_id,
115-
const std::shared_ptr<CommandEncoder> &encoder);
126+
const std::shared_ptr<CommandEncoder> &encoder,
127+
const std::shared_ptr<DescriptorSet> &tile_descriptor_set,
128+
uint64_t tile_uniform_offset);
116129

117130
/// Draw the mask texture. Use Renderer::buffered_fills.
118131
void draw_fills(uint64_t fill_vertex_buffer_id,
119132
uint32_t fills_count,
120133
const std::shared_ptr<CommandEncoder> &encoder) const;
134+
135+
void update_tile_batch_storage(uint32_t new_tile_batch_count);
121136
};
122137

123138
} // namespace Pathfinder

0 commit comments

Comments
 (0)