@@ -43,6 +43,8 @@ constexpr size_t CLIP_TILE_INSTANCE_SIZE = 16;
4343// 65536
4444constexpr size_t MAX_FILLS_PER_BATCH = 0x10000 ;
4545
46+ constexpr uint32_t DEFAULT_TILE_BATCH_COUNT = 10 ;
47+
4648RendererD3D9::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+
83123void 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
219236void 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
375417uint64_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
492537void 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
554600void 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
0 commit comments