diff options
Diffstat (limited to 'servers/rendering/renderer_rd/renderer_canvas_render_rd.h')
-rw-r--r-- | servers/rendering/renderer_rd/renderer_canvas_render_rd.h | 201 |
1 files changed, 171 insertions, 30 deletions
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h index 9deb4814c7..87de07464e 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h @@ -46,6 +46,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender { MATERIAL_UNIFORM_SET = 1, TRANSFORMS_UNIFORM_SET = 2, CANVAS_TEXTURE_UNIFORM_SET = 3, + INSTANCE_DATA_UNIFORM_SET = 4, }; const int SAMPLERS_BINDING_FIRST_INDEX = 10; @@ -335,6 +336,146 @@ class RendererCanvasRenderRD : public RendererCanvasRender { //state that does not vary across rendering all items + struct InstanceData { + float world[6]; + uint32_t flags; + uint32_t specular_shininess; + union { + //rect + struct { + float modulation[4]; + union { + float msdf[4]; + float ninepatch_margins[4]; + }; + float dst_rect[4]; + float src_rect[4]; + float pad[2]; + }; + //primitive + struct { + float points[6]; // vec2 points[3] + float uvs[6]; // vec2 points[3] + uint32_t colors[6]; // colors encoded as half + }; + }; + float color_texture_pixel_size[2]; + uint32_t lights[4]; + }; + + struct PushConstant { + uint32_t base_instance_index; + uint32_t pad1; + uint32_t pad2; + uint32_t pad3; + }; + + // TextureState is used to determine when a new batch is required due to a change of texture state. + struct TextureState { + static const uint32_t FILTER_SHIFT = 0; + static const uint32_t FILTER_BITS = 3; + static const uint32_t FILTER_MASK = (1 << FILTER_BITS) - 1; + static const uint32_t REPEAT_SHIFT = FILTER_BITS; + static const uint32_t REPEAT_BITS = 2; + static const uint32_t REPEAT_MASK = (1 << REPEAT_BITS) - 1; + static const uint32_t TEXTURE_IS_DATA_SHIFT = REPEAT_SHIFT + REPEAT_BITS; + static const uint32_t TEXTURE_IS_DATA_BITS = 1; + static const uint32_t TEXTURE_IS_DATA_MASK = (1 << TEXTURE_IS_DATA_BITS) - 1; + static const uint32_t LINEAR_COLORS_SHIFT = TEXTURE_IS_DATA_SHIFT + TEXTURE_IS_DATA_BITS; + static const uint32_t LINEAR_COLORS_BITS = 1; + static const uint32_t LINEAR_COLORS_MASK = (1 << LINEAR_COLORS_BITS) - 1; + + RID texture; + uint32_t other = 0; + + TextureState() {} + + TextureState(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, bool p_texture_is_data, bool p_use_linear_colors) { + texture = p_texture; + other = (((uint32_t)p_base_filter & FILTER_MASK) << FILTER_SHIFT) | + (((uint32_t)p_base_repeat & REPEAT_MASK) << REPEAT_SHIFT) | + (((uint32_t)p_texture_is_data & TEXTURE_IS_DATA_MASK) << TEXTURE_IS_DATA_SHIFT) | + (((uint32_t)p_use_linear_colors & LINEAR_COLORS_MASK) << LINEAR_COLORS_SHIFT); + } + + _FORCE_INLINE_ RS::CanvasItemTextureFilter texture_filter() const { + return (RS::CanvasItemTextureFilter)((other >> FILTER_SHIFT) & FILTER_MASK); + } + + _FORCE_INLINE_ RS::CanvasItemTextureRepeat texture_repeat() const { + return (RS::CanvasItemTextureRepeat)((other >> REPEAT_SHIFT) & REPEAT_MASK); + } + + _FORCE_INLINE_ bool linear_colors() const { + return (other >> LINEAR_COLORS_SHIFT) & LINEAR_COLORS_MASK; + } + + _FORCE_INLINE_ bool texture_is_data() const { + return (other >> TEXTURE_IS_DATA_SHIFT) & TEXTURE_IS_DATA_MASK; + } + + bool operator==(const TextureState &p_val) const { + return (texture == p_val.texture) && (other == p_val.other); + } + + bool operator!=(const TextureState &p_val) const { + return (texture != p_val.texture) || (other != p_val.other); + } + }; + + struct Batch { + // Position in the UBO measured in bytes + uint32_t start = 0; + uint32_t instance_count = 0; + uint32_t instance_buffer_index = 0; + + TextureState tex_state; + RID tex_uniform_set; + + // The following tex_ prefixed fields are used to cache the texture data for the current batch. + // These values are applied to new InstanceData for the batch + + // The cached specular shininess derived from the current texture. + uint32_t tex_specular_shininess = 0; + // The cached texture flags, such as FLAGS_DEFAULT_SPECULAR_MAP_USED and FLAGS_DEFAULT_NORMAL_MAP_USED + uint32_t tex_flags = 0; + // The cached texture pixel size. + Vector2 tex_texpixel_size; + + Color modulate = Color(1.0, 1.0, 1.0, 1.0); + + Item *clip = nullptr; + + RID material; + CanvasMaterialData *material_data = nullptr; + PipelineLightMode light_mode = PipelineLightMode::PIPELINE_LIGHT_MODE_DISABLED; + PipelineVariant pipeline_variant = PipelineVariant::PIPELINE_VARIANT_QUAD; + + const Item::Command *command = nullptr; + Item::Command::Type command_type = Item::Command::TYPE_ANIMATION_SLICE; // Can default to any type that doesn't form a batch. + + // batch-specific data + union { + // TYPE_PRIMITIVE + uint32_t primitive_points = 0; + // TYPE_PARTICLES + uint32_t mesh_instance_count; + }; + bool has_blend = false; + + void set_tex_state(TextureState &p_tex_state) { + tex_state = p_tex_state; + tex_uniform_set = RID(); + tex_texpixel_size = Size2(); + tex_specular_shininess = 0; + tex_flags = 0; + } + }; + + struct DataBuffer { + LocalVector<RID> instance_buffers; + }; + struct State { //state buffer struct Buffer { @@ -357,6 +498,19 @@ class RendererCanvasRenderRD : public RendererCanvasRender { uint32_t pad2; }; + LocalVector<DataBuffer> canvas_instance_data_buffers; + LocalVector<Batch> canvas_instance_batches; + uint32_t current_data_buffer_index = 0; + uint32_t current_instance_buffer_index = 0; + uint32_t current_batch_index = 0; + uint32_t last_instance_index = 0; + InstanceData *instance_data_array = nullptr; + + uint32_t max_instances_per_buffer = 16384; + uint32_t max_instance_buffer_size = 16384 * sizeof(InstanceData); + + RID current_tex_uniform_set; + LightUniform *light_uniforms = nullptr; RID lights_uniform_buffer; @@ -376,33 +530,6 @@ class RendererCanvasRenderRD : public RendererCanvasRender { } state; - struct PushConstant { - float world[6]; - uint32_t flags; - uint32_t specular_shininess; - union { - //rect - struct { - float modulation[4]; - union { - float msdf[4]; - float ninepatch_margins[4]; - }; - float dst_rect[4]; - float src_rect[4]; - float pad[2]; - }; - //primitive - struct { - float points[6]; // vec2 points[3] - float uvs[6]; // vec2 points[3] - uint32_t colors[6]; // colors encoded as half - }; - }; - float color_texture_pixel_size[2]; - uint32_t lights[4]; - }; - Item *items[MAX_RENDER_ITEMS]; bool using_directional_lights = false; @@ -422,9 +549,23 @@ class RendererCanvasRenderRD : public RendererCanvasRender { Color debug_redraw_color; double debug_redraw_time = 1.0; - inline void _bind_canvas_texture(RD::DrawListID p_draw_list, RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID &r_last_texture, PushConstant &push_constant, Size2 &r_texpixel_size, bool p_texture_is_data = false); //recursive, so regular inline used instead. - void _render_item(RenderingDevice::DrawListID p_draw_list, RID p_render_target, const Item *p_item, RenderingDevice::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, Light *p_lights, PipelineVariants *p_pipeline_variants, bool &r_sdf_used, const Point2 &p_repeat_offset, RenderingMethod::RenderInfo *r_render_info = nullptr); - void _render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool &r_sdf_used, bool p_to_backbuffer = false, RenderingMethod::RenderInfo *r_render_info = nullptr); + // A structure to store cached render target information + struct RenderTarget { + // Current render target for the canvas. + RID render_target; + // The base flags for each InstanceData, derived from the render target. + // Either FLAGS_CONVERT_ATTRIBUTES_TO_LINEAR or 0 + uint32_t base_flags = 0; + }; + + void _render_batch_items(RenderTarget p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool &r_sdf_used, bool p_to_backbuffer = false, RenderingMethod::RenderInfo *r_render_info = nullptr); + void _record_item_commands(const Item *p_item, RenderTarget p_render_target, const Transform2D &p_base_transform, Item *&r_current_clip, Light *p_lights, uint32_t &r_index, bool &r_batch_broken, bool &r_sdf_used); + void _render_batch(RD::DrawListID p_draw_list, PipelineVariants *p_pipeline_variants, RenderingDevice::FramebufferFormatID p_framebuffer_format, Light *p_lights, Batch const *p_batch, RenderingMethod::RenderInfo *r_render_info = nullptr); + void _prepare_batch_texture(Batch *p_current_batch, RID p_texture) const; + void _bind_canvas_texture(RD::DrawListID p_draw_list, RID p_uniform_set); + [[nodiscard]] Batch *_new_batch(bool &r_batch_broken); + void _add_to_batch(uint32_t &r_index, bool &r_batch_broken, Batch *&r_current_batch); + void _allocate_instance_buffer(); _FORCE_INLINE_ void _update_transform_2d_to_mat2x4(const Transform2D &p_transform, float *p_mat2x4); _FORCE_INLINE_ void _update_transform_2d_to_mat2x3(const Transform2D &p_transform, float *p_mat2x3); |