mirror of
https://github.com/godotengine/godot.git
synced 2024-11-21 19:42:43 +00:00
Merge pull request #97554 from clayjohn/batching-uniform-sets
Combine texture and instance data into one uniform set in the 2D renderer
This commit is contained in:
commit
e7a9104f37
@ -1974,6 +1974,12 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() {
|
||||
default_canvas_texture = texture_storage->canvas_texture_allocate();
|
||||
texture_storage->canvas_texture_initialize(default_canvas_texture);
|
||||
|
||||
RendererRD::TextureStorage::CanvasTextureInfo info = RendererRD::TextureStorage::get_singleton()->canvas_texture_get_info(default_canvas_texture, default_filter, default_repeat, false, false);
|
||||
default_texture_info.diffuse = info.diffuse;
|
||||
default_texture_info.normal = info.normal;
|
||||
default_texture_info.specular = info.specular;
|
||||
default_texture_info.sampler = info.sampler;
|
||||
|
||||
state.shadow_texture_size = GLOBAL_GET("rendering/2d/shadow_atlas/size");
|
||||
|
||||
//create functions for shader and material
|
||||
@ -2219,7 +2225,7 @@ void RendererCanvasRenderRD::_render_batch_items(RenderTarget p_to_render_target
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, state.default_transforms_uniform_set, TRANSFORMS_UNIFORM_SET);
|
||||
|
||||
Item *current_clip = nullptr;
|
||||
state.current_tex_uniform_set = RID();
|
||||
state.current_batch_uniform_set = RID();
|
||||
|
||||
for (uint32_t i = 0; i <= state.current_batch_index; i++) {
|
||||
Batch *current_batch = &state.canvas_instance_batches[i];
|
||||
@ -2337,11 +2343,11 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
|
||||
instance_data->world[i] = world[i];
|
||||
}
|
||||
|
||||
instance_data->flags = base_flags | r_current_batch->tex_flags; // Reset on each command for safety, keep canvas texture binding config.
|
||||
instance_data->flags = base_flags | r_current_batch->tex_info.flags; // Reset on each command for safety, keep canvas texture binding config.
|
||||
|
||||
instance_data->color_texture_pixel_size[0] = r_current_batch->tex_texpixel_size.width;
|
||||
instance_data->color_texture_pixel_size[1] = r_current_batch->tex_texpixel_size.height;
|
||||
instance_data->specular_shininess = r_current_batch->tex_specular_shininess;
|
||||
instance_data->color_texture_pixel_size[0] = r_current_batch->tex_info.texpixel_size.width;
|
||||
instance_data->color_texture_pixel_size[1] = r_current_batch->tex_info.texpixel_size.height;
|
||||
instance_data->specular_shininess = r_current_batch->tex_info.specular_shininess;
|
||||
|
||||
return instance_data;
|
||||
};
|
||||
@ -2373,10 +2379,10 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
|
||||
bool has_msdf = bool(rect->flags & CANVAS_RECT_MSDF);
|
||||
TextureState tex_state(rect->texture, texture_filter, texture_repeat, has_msdf, use_linear_colors);
|
||||
|
||||
if (tex_state != r_current_batch->tex_state) {
|
||||
if (tex_state != r_current_batch->tex_info.state) {
|
||||
r_current_batch = _new_batch(r_batch_broken);
|
||||
r_current_batch->set_tex_state(tex_state);
|
||||
_prepare_batch_texture(r_current_batch, rect->texture);
|
||||
r_current_batch->tex_info.state = tex_state;
|
||||
_prepare_batch_texture_info(r_current_batch, rect->texture);
|
||||
}
|
||||
|
||||
Color modulated = rect->modulate * base_color;
|
||||
@ -2399,7 +2405,7 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
|
||||
Rect2 dst_rect;
|
||||
|
||||
if (rect->texture.is_valid()) {
|
||||
src_rect = (rect->flags & CANVAS_RECT_REGION) ? Rect2(rect->source.position * r_current_batch->tex_texpixel_size, rect->source.size * r_current_batch->tex_texpixel_size) : Rect2(0, 0, 1, 1);
|
||||
src_rect = (rect->flags & CANVAS_RECT_REGION) ? Rect2(rect->source.position * r_current_batch->tex_info.texpixel_size, rect->source.size * r_current_batch->tex_info.texpixel_size) : Rect2(0, 0, 1, 1);
|
||||
dst_rect = Rect2(rect->rect.position, rect->rect.size);
|
||||
|
||||
if (dst_rect.size.width < 0) {
|
||||
@ -2484,10 +2490,10 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
|
||||
}
|
||||
|
||||
TextureState tex_state(np->texture, texture_filter, texture_repeat, false, use_linear_colors);
|
||||
if (tex_state != r_current_batch->tex_state) {
|
||||
if (tex_state != r_current_batch->tex_info.state) {
|
||||
r_current_batch = _new_batch(r_batch_broken);
|
||||
r_current_batch->set_tex_state(tex_state);
|
||||
_prepare_batch_texture(r_current_batch, np->texture);
|
||||
r_current_batch->tex_info.state = tex_state;
|
||||
_prepare_batch_texture_info(r_current_batch, np->texture);
|
||||
}
|
||||
|
||||
InstanceData *instance_data = new_instance_data();
|
||||
@ -2499,7 +2505,7 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
|
||||
src_rect = Rect2(0, 0, 1, 1);
|
||||
} else {
|
||||
if (np->source != Rect2()) {
|
||||
src_rect = Rect2(np->source.position.x * r_current_batch->tex_texpixel_size.width, np->source.position.y * r_current_batch->tex_texpixel_size.height, np->source.size.x * r_current_batch->tex_texpixel_size.width, np->source.size.y * r_current_batch->tex_texpixel_size.height);
|
||||
src_rect = Rect2(np->source.position.x * r_current_batch->tex_info.texpixel_size.width, np->source.position.y * r_current_batch->tex_info.texpixel_size.height, np->source.size.x * r_current_batch->tex_info.texpixel_size.width, np->source.size.y * r_current_batch->tex_info.texpixel_size.height);
|
||||
instance_data->color_texture_pixel_size[0] = 1.0 / np->source.size.width;
|
||||
instance_data->color_texture_pixel_size[1] = 1.0 / np->source.size.height;
|
||||
} else {
|
||||
@ -2553,10 +2559,10 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
|
||||
r_current_batch->command = c;
|
||||
|
||||
TextureState tex_state(polygon->texture, texture_filter, texture_repeat, false, use_linear_colors);
|
||||
if (tex_state != r_current_batch->tex_state) {
|
||||
if (tex_state != r_current_batch->tex_info.state) {
|
||||
r_current_batch = _new_batch(r_batch_broken);
|
||||
r_current_batch->set_tex_state(tex_state);
|
||||
_prepare_batch_texture(r_current_batch, polygon->texture);
|
||||
r_current_batch->tex_info.state = tex_state;
|
||||
_prepare_batch_texture_info(r_current_batch, polygon->texture);
|
||||
}
|
||||
|
||||
// pipeline variant
|
||||
@ -2596,10 +2602,10 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
|
||||
r_current_batch->pipeline_variant = variant[primitive->point_count - 1];
|
||||
|
||||
TextureState tex_state(primitive->texture, texture_filter, texture_repeat, false, use_linear_colors);
|
||||
if (tex_state != r_current_batch->tex_state) {
|
||||
if (tex_state != r_current_batch->tex_info.state) {
|
||||
r_current_batch = _new_batch(r_batch_broken);
|
||||
r_current_batch->set_tex_state(tex_state);
|
||||
_prepare_batch_texture(r_current_batch, primitive->texture);
|
||||
r_current_batch->tex_info.state = tex_state;
|
||||
_prepare_batch_texture_info(r_current_batch, primitive->texture);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2657,8 +2663,8 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
|
||||
if (c->type == Item::Command::TYPE_MESH) {
|
||||
const Item::CommandMesh *m = static_cast<const Item::CommandMesh *>(c);
|
||||
TextureState tex_state(m->texture, texture_filter, texture_repeat, false, use_linear_colors);
|
||||
r_current_batch->set_tex_state(tex_state);
|
||||
_prepare_batch_texture(r_current_batch, m->texture);
|
||||
r_current_batch->tex_info.state = tex_state;
|
||||
_prepare_batch_texture_info(r_current_batch, m->texture);
|
||||
instance_data = new_instance_data();
|
||||
|
||||
r_current_batch->mesh_instance_count = 1;
|
||||
@ -2680,8 +2686,8 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
|
||||
}
|
||||
|
||||
TextureState tex_state(mm->texture, texture_filter, texture_repeat, false, use_linear_colors);
|
||||
r_current_batch->set_tex_state(tex_state);
|
||||
_prepare_batch_texture(r_current_batch, mm->texture);
|
||||
r_current_batch->tex_info.state = tex_state;
|
||||
_prepare_batch_texture_info(r_current_batch, mm->texture);
|
||||
instance_data = new_instance_data();
|
||||
|
||||
instance_data->flags |= 1; // multimesh, trails disabled
|
||||
@ -2698,8 +2704,8 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
|
||||
|
||||
const Item::CommandParticles *pt = static_cast<const Item::CommandParticles *>(c);
|
||||
TextureState tex_state(pt->texture, texture_filter, texture_repeat, false, use_linear_colors);
|
||||
r_current_batch->set_tex_state(tex_state);
|
||||
_prepare_batch_texture(r_current_batch, pt->texture);
|
||||
r_current_batch->tex_info.state = tex_state;
|
||||
_prepare_batch_texture_info(r_current_batch, pt->texture);
|
||||
|
||||
instance_data = new_instance_data();
|
||||
|
||||
@ -2795,7 +2801,20 @@ void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, PipelineV
|
||||
|
||||
ERR_FAIL_NULL(p_batch->command);
|
||||
|
||||
_bind_canvas_texture(p_draw_list, p_batch->tex_uniform_set);
|
||||
{
|
||||
RD::Uniform u_diffuse(RD::UNIFORM_TYPE_TEXTURE, 0, p_batch->tex_info.diffuse);
|
||||
RD::Uniform u_normal(RD::UNIFORM_TYPE_TEXTURE, 1, p_batch->tex_info.normal);
|
||||
RD::Uniform u_specular(RD::UNIFORM_TYPE_TEXTURE, 2, p_batch->tex_info.specular);
|
||||
RD::Uniform u_sampler(RD::UNIFORM_TYPE_SAMPLER, 3, p_batch->tex_info.sampler);
|
||||
RD::Uniform u_instance_data(RD::UNIFORM_TYPE_STORAGE_BUFFER, 4, state.canvas_instance_data_buffers[state.current_data_buffer_index].instance_buffers[p_batch->instance_buffer_index]);
|
||||
|
||||
RID uniform_set = uniform_set_cache->get_cache(shader.default_version_rd_shader, BATCH_UNIFORM_SET, u_diffuse, u_normal, u_specular, u_sampler, u_instance_data);
|
||||
|
||||
if (state.current_batch_uniform_set != uniform_set) {
|
||||
state.current_batch_uniform_set = uniform_set;
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, uniform_set, BATCH_UNIFORM_SET);
|
||||
}
|
||||
}
|
||||
|
||||
switch (p_batch->command_type) {
|
||||
case Item::Command::TYPE_RECT:
|
||||
@ -2810,13 +2829,6 @@ void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, PipelineV
|
||||
PushConstant push_constant;
|
||||
push_constant.base_instance_index = p_batch->start;
|
||||
RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(PushConstant));
|
||||
|
||||
RD::Uniform u_instance_data(RD::UNIFORM_TYPE_STORAGE_BUFFER, 0, state.canvas_instance_data_buffers[state.current_data_buffer_index].instance_buffers[p_batch->instance_buffer_index]);
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(
|
||||
p_draw_list,
|
||||
uniform_set_cache->get_cache(shader.default_version_rd_shader, INSTANCE_DATA_UNIFORM_SET, u_instance_data),
|
||||
INSTANCE_DATA_UNIFORM_SET);
|
||||
|
||||
RD::get_singleton()->draw_list_bind_index_array(p_draw_list, shader.quad_index_array);
|
||||
RD::get_singleton()->draw_list_draw(p_draw_list, true, p_batch->instance_count);
|
||||
|
||||
@ -2839,13 +2851,6 @@ void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, PipelineV
|
||||
PushConstant push_constant;
|
||||
push_constant.base_instance_index = p_batch->start;
|
||||
RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(PushConstant));
|
||||
|
||||
RD::Uniform u_instance_data(RD::UNIFORM_TYPE_STORAGE_BUFFER, 0, state.canvas_instance_data_buffers[state.current_data_buffer_index].instance_buffers[p_batch->instance_buffer_index]);
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(
|
||||
p_draw_list,
|
||||
uniform_set_cache->get_cache(shader.default_version_rd_shader, INSTANCE_DATA_UNIFORM_SET, u_instance_data),
|
||||
INSTANCE_DATA_UNIFORM_SET);
|
||||
|
||||
RD::get_singleton()->draw_list_bind_vertex_array(p_draw_list, pb->vertex_array);
|
||||
if (pb->indices.is_valid()) {
|
||||
RD::get_singleton()->draw_list_bind_index_array(p_draw_list, pb->indices);
|
||||
@ -2868,13 +2873,6 @@ void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, PipelineV
|
||||
PushConstant push_constant;
|
||||
push_constant.base_instance_index = p_batch->start;
|
||||
RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(PushConstant));
|
||||
|
||||
RD::Uniform u_instance_data(RD::UNIFORM_TYPE_STORAGE_BUFFER, 0, state.canvas_instance_data_buffers[state.current_data_buffer_index].instance_buffers[p_batch->instance_buffer_index]);
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(
|
||||
p_draw_list,
|
||||
uniform_set_cache->get_cache(shader.default_version_rd_shader, INSTANCE_DATA_UNIFORM_SET, u_instance_data),
|
||||
INSTANCE_DATA_UNIFORM_SET);
|
||||
|
||||
RD::get_singleton()->draw_list_bind_index_array(p_draw_list, primitive_arrays.index_array[MIN(3u, primitive->point_count) - 1]);
|
||||
uint32_t instance_count = p_batch->instance_count;
|
||||
RD::get_singleton()->draw_list_draw(p_draw_list, true, instance_count);
|
||||
@ -2934,12 +2932,6 @@ void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, PipelineV
|
||||
break;
|
||||
}
|
||||
|
||||
RD::Uniform u_instance_data(RD::UNIFORM_TYPE_STORAGE_BUFFER, 0, state.canvas_instance_data_buffers[state.current_data_buffer_index].instance_buffers[p_batch->instance_buffer_index]);
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(
|
||||
p_draw_list,
|
||||
uniform_set_cache->get_cache(shader.default_version_rd_shader, INSTANCE_DATA_UNIFORM_SET, u_instance_data),
|
||||
INSTANCE_DATA_UNIFORM_SET);
|
||||
|
||||
uint32_t surf_count = mesh_storage->mesh_get_surface_count(mesh);
|
||||
static const PipelineVariant variant[RS::PRIMITIVE_MAX] = { PIPELINE_VARIANT_ATTRIBUTE_POINTS, PIPELINE_VARIANT_ATTRIBUTE_LINES, PIPELINE_VARIANT_ATTRIBUTE_LINES_STRIP, PIPELINE_VARIANT_ATTRIBUTE_TRIANGLES, PIPELINE_VARIANT_ATTRIBUTE_TRIANGLE_STRIP };
|
||||
|
||||
@ -3046,60 +3038,46 @@ void RendererCanvasRenderRD::_allocate_instance_buffer() {
|
||||
state.canvas_instance_data_buffers[state.current_data_buffer_index].instance_buffers.push_back(buf);
|
||||
}
|
||||
|
||||
void RendererCanvasRenderRD::_prepare_batch_texture(Batch *p_current_batch, RID p_texture) const {
|
||||
void RendererCanvasRenderRD::_prepare_batch_texture_info(Batch *p_current_batch, RID p_texture) const {
|
||||
if (p_texture.is_null()) {
|
||||
p_texture = default_canvas_texture;
|
||||
}
|
||||
|
||||
Color specular_shininess;
|
||||
bool use_normal;
|
||||
bool use_specular;
|
||||
Size2i size;
|
||||
bool success = RendererRD::TextureStorage::get_singleton()->canvas_texture_get_uniform_set(
|
||||
p_texture,
|
||||
p_current_batch->tex_state.texture_filter(),
|
||||
p_current_batch->tex_state.texture_repeat(),
|
||||
shader.default_version_rd_shader,
|
||||
CANVAS_TEXTURE_UNIFORM_SET,
|
||||
p_current_batch->tex_state.linear_colors(),
|
||||
p_current_batch->tex_uniform_set,
|
||||
size,
|
||||
specular_shininess,
|
||||
use_normal,
|
||||
use_specular,
|
||||
p_current_batch->tex_state.texture_is_data());
|
||||
RendererRD::TextureStorage::CanvasTextureInfo info =
|
||||
RendererRD::TextureStorage::get_singleton()->canvas_texture_get_info(
|
||||
p_texture,
|
||||
p_current_batch->tex_info.state.texture_filter(),
|
||||
p_current_batch->tex_info.state.texture_repeat(),
|
||||
p_current_batch->tex_info.state.linear_colors(),
|
||||
p_current_batch->tex_info.state.texture_is_data());
|
||||
|
||||
// something odd happened
|
||||
if (!success) {
|
||||
_prepare_batch_texture(p_current_batch, default_canvas_texture);
|
||||
if (info.is_null()) {
|
||||
_prepare_batch_texture_info(p_current_batch, default_canvas_texture);
|
||||
return;
|
||||
}
|
||||
|
||||
p_current_batch->tex_info.diffuse = info.diffuse;
|
||||
p_current_batch->tex_info.normal = info.normal;
|
||||
p_current_batch->tex_info.specular = info.specular;
|
||||
p_current_batch->tex_info.sampler = info.sampler;
|
||||
|
||||
// cache values to be copied to instance data
|
||||
if (specular_shininess.a < 0.999) {
|
||||
p_current_batch->tex_flags |= FLAGS_DEFAULT_SPECULAR_MAP_USED;
|
||||
if (info.specular_color.a < 0.999) {
|
||||
p_current_batch->tex_info.flags |= FLAGS_DEFAULT_SPECULAR_MAP_USED;
|
||||
}
|
||||
|
||||
if (use_normal) {
|
||||
p_current_batch->tex_flags |= FLAGS_DEFAULT_NORMAL_MAP_USED;
|
||||
if (info.use_normal) {
|
||||
p_current_batch->tex_info.flags |= FLAGS_DEFAULT_NORMAL_MAP_USED;
|
||||
}
|
||||
|
||||
uint8_t a = uint8_t(CLAMP(specular_shininess.a * 255.0, 0.0, 255.0));
|
||||
uint8_t b = uint8_t(CLAMP(specular_shininess.b * 255.0, 0.0, 255.0));
|
||||
uint8_t g = uint8_t(CLAMP(specular_shininess.g * 255.0, 0.0, 255.0));
|
||||
uint8_t r = uint8_t(CLAMP(specular_shininess.r * 255.0, 0.0, 255.0));
|
||||
p_current_batch->tex_specular_shininess = uint32_t(a) << 24 | uint32_t(b) << 16 | uint32_t(g) << 8 | uint32_t(r);
|
||||
uint8_t a = uint8_t(CLAMP(info.specular_color.a * 255.0, 0.0, 255.0));
|
||||
uint8_t b = uint8_t(CLAMP(info.specular_color.b * 255.0, 0.0, 255.0));
|
||||
uint8_t g = uint8_t(CLAMP(info.specular_color.g * 255.0, 0.0, 255.0));
|
||||
uint8_t r = uint8_t(CLAMP(info.specular_color.r * 255.0, 0.0, 255.0));
|
||||
p_current_batch->tex_info.specular_shininess = uint32_t(a) << 24 | uint32_t(b) << 16 | uint32_t(g) << 8 | uint32_t(r);
|
||||
|
||||
p_current_batch->tex_texpixel_size = Vector2(1.0 / float(size.width), 1.0 / float(size.height));
|
||||
}
|
||||
|
||||
void RendererCanvasRenderRD::_bind_canvas_texture(RD::DrawListID p_draw_list, RID p_uniform_set) {
|
||||
if (state.current_tex_uniform_set == p_uniform_set) {
|
||||
return;
|
||||
}
|
||||
|
||||
state.current_tex_uniform_set = p_uniform_set;
|
||||
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, p_uniform_set, CANVAS_TEXTURE_UNIFORM_SET);
|
||||
p_current_batch->tex_info.texpixel_size = Vector2(1.0 / float(info.size.width), 1.0 / float(info.size.height));
|
||||
}
|
||||
|
||||
RendererCanvasRenderRD::~RendererCanvasRenderRD() {
|
||||
|
@ -45,8 +45,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
|
||||
BASE_UNIFORM_SET = 0,
|
||||
MATERIAL_UNIFORM_SET = 1,
|
||||
TRANSFORMS_UNIFORM_SET = 2,
|
||||
CANVAS_TEXTURE_UNIFORM_SET = 3,
|
||||
INSTANCE_DATA_UNIFORM_SET = 4,
|
||||
BATCH_UNIFORM_SET = 3,
|
||||
};
|
||||
|
||||
const int SAMPLERS_BINDING_FIRST_INDEX = 10;
|
||||
@ -423,24 +422,25 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
|
||||
}
|
||||
};
|
||||
|
||||
struct TextureInfo {
|
||||
TextureState state;
|
||||
uint32_t specular_shininess = 0;
|
||||
uint32_t flags = 0;
|
||||
Vector2 texpixel_size;
|
||||
|
||||
RID diffuse;
|
||||
RID normal;
|
||||
RID specular;
|
||||
RID sampler;
|
||||
};
|
||||
|
||||
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;
|
||||
TextureInfo tex_info;
|
||||
|
||||
Color modulate = Color(1.0, 1.0, 1.0, 1.0);
|
||||
|
||||
@ -462,14 +462,6 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
|
||||
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 {
|
||||
@ -509,7 +501,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
|
||||
uint32_t max_instances_per_buffer = 16384;
|
||||
uint32_t max_instance_buffer_size = 16384 * sizeof(InstanceData);
|
||||
|
||||
RID current_tex_uniform_set;
|
||||
RID current_batch_uniform_set;
|
||||
|
||||
LightUniform *light_uniforms = nullptr;
|
||||
|
||||
@ -532,6 +524,8 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
|
||||
|
||||
Item *items[MAX_RENDER_ITEMS];
|
||||
|
||||
TextureInfo default_texture_info;
|
||||
|
||||
bool using_directional_lights = false;
|
||||
RID default_canvas_texture;
|
||||
|
||||
@ -561,8 +555,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
|
||||
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, Batch *&r_current_batch);
|
||||
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);
|
||||
void _prepare_batch_texture_info(Batch *p_current_batch, RID p_texture) const;
|
||||
[[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();
|
||||
|
@ -54,11 +54,6 @@ struct InstanceData {
|
||||
uint lights[4];
|
||||
};
|
||||
|
||||
layout(set = 4, binding = 0, std430) restrict readonly buffer DrawData {
|
||||
InstanceData data[];
|
||||
}
|
||||
instances;
|
||||
|
||||
layout(push_constant, std430) uniform Params {
|
||||
uint base_instance_index; // base index to instance data
|
||||
uint pad1;
|
||||
@ -163,3 +158,8 @@ layout(set = 3, binding = 0) uniform texture2D color_texture;
|
||||
layout(set = 3, binding = 1) uniform texture2D normal_texture;
|
||||
layout(set = 3, binding = 2) uniform texture2D specular_texture;
|
||||
layout(set = 3, binding = 3) uniform sampler texture_sampler;
|
||||
|
||||
layout(set = 3, binding = 4, std430) restrict readonly buffer DrawData {
|
||||
InstanceData data[];
|
||||
}
|
||||
instances;
|
||||
|
@ -40,25 +40,12 @@ using namespace RendererRD;
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// TextureStorage::CanvasTexture
|
||||
|
||||
void TextureStorage::CanvasTexture::clear_sets() {
|
||||
if (cleared_cache) {
|
||||
return;
|
||||
}
|
||||
for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
|
||||
for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) {
|
||||
for (int k = 0; k < 2; k++) {
|
||||
if (RD::get_singleton()->uniform_set_is_valid(uniform_sets[i][j][k])) {
|
||||
RD::get_singleton()->free(uniform_sets[i][j][k]);
|
||||
uniform_sets[i][j][k] = RID();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
cleared_cache = true;
|
||||
void TextureStorage::CanvasTexture::clear_cache() {
|
||||
info_cache[0] = CanvasTextureCache();
|
||||
info_cache[1] = CanvasTextureCache();
|
||||
}
|
||||
|
||||
TextureStorage::CanvasTexture::~CanvasTexture() {
|
||||
clear_sets();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
@ -612,8 +599,7 @@ void TextureStorage::canvas_texture_set_channel(RID p_canvas_texture, RS::Canvas
|
||||
ct->specular = p_texture;
|
||||
} break;
|
||||
}
|
||||
|
||||
ct->clear_sets();
|
||||
ct->clear_cache();
|
||||
}
|
||||
|
||||
void TextureStorage::canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_specular_color, float p_shininess) {
|
||||
@ -624,7 +610,6 @@ void TextureStorage::canvas_texture_set_shading_parameters(RID p_canvas_texture,
|
||||
ct->specular_color.g = p_specular_color.g;
|
||||
ct->specular_color.b = p_specular_color.b;
|
||||
ct->specular_color.a = p_shininess;
|
||||
ct->clear_sets();
|
||||
}
|
||||
|
||||
void TextureStorage::canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter) {
|
||||
@ -632,7 +617,6 @@ void TextureStorage::canvas_texture_set_texture_filter(RID p_canvas_texture, RS:
|
||||
ERR_FAIL_NULL(ct);
|
||||
|
||||
ct->texture_filter = p_filter;
|
||||
ct->clear_sets();
|
||||
}
|
||||
|
||||
void TextureStorage::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat) {
|
||||
@ -640,17 +624,14 @@ void TextureStorage::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS:
|
||||
ERR_FAIL_NULL(ct);
|
||||
|
||||
ct->texture_repeat = p_repeat;
|
||||
ct->clear_sets();
|
||||
}
|
||||
|
||||
bool TextureStorage::canvas_texture_get_uniform_set(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID p_base_shader, int p_base_set, bool p_use_srgb, RID &r_uniform_set, Size2i &r_size, Color &r_specular_shininess, bool &r_use_normal, bool &r_use_specular, bool p_texture_is_data) {
|
||||
TextureStorage::CanvasTextureInfo TextureStorage::canvas_texture_get_info(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, bool p_use_srgb, bool p_texture_is_data) {
|
||||
MaterialStorage *material_storage = MaterialStorage::get_singleton();
|
||||
|
||||
CanvasTexture *ct = nullptr;
|
||||
Texture *t = get_texture(p_texture);
|
||||
|
||||
// TODO once we have our texture storage split off we'll look into moving this code into canvas_texture
|
||||
|
||||
if (t) {
|
||||
//regular texture
|
||||
if (!t->canvas_texture) {
|
||||
@ -667,93 +648,71 @@ bool TextureStorage::canvas_texture_get_uniform_set(RID p_texture, RS::CanvasIte
|
||||
}
|
||||
|
||||
if (!ct) {
|
||||
return false; //invalid texture RID
|
||||
return CanvasTextureInfo(); //invalid texture RID
|
||||
}
|
||||
|
||||
RS::CanvasItemTextureFilter filter = ct->texture_filter != RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT ? ct->texture_filter : p_base_filter;
|
||||
ERR_FAIL_COND_V(filter == RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, false);
|
||||
ERR_FAIL_COND_V(filter == RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, CanvasTextureInfo());
|
||||
|
||||
RS::CanvasItemTextureRepeat repeat = ct->texture_repeat != RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT ? ct->texture_repeat : p_base_repeat;
|
||||
ERR_FAIL_COND_V(repeat == RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, false);
|
||||
ERR_FAIL_COND_V(repeat == RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, CanvasTextureInfo());
|
||||
|
||||
RID uniform_set = ct->uniform_sets[filter][repeat][int(p_use_srgb)];
|
||||
if (!RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
|
||||
//create and update
|
||||
Vector<RD::Uniform> uniforms;
|
||||
CanvasTextureCache &ctc = ct->info_cache[int(p_use_srgb)];
|
||||
if (!RD::get_singleton()->texture_is_valid(ctc.diffuse) ||
|
||||
!RD::get_singleton()->texture_is_valid(ctc.normal) ||
|
||||
!RD::get_singleton()->texture_is_valid(ctc.specular)) {
|
||||
{ //diffuse
|
||||
RD::Uniform u;
|
||||
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
|
||||
u.binding = 0;
|
||||
|
||||
t = get_texture(ct->diffuse);
|
||||
if (!t) {
|
||||
u.append_id(texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE));
|
||||
ctc.diffuse = texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE);
|
||||
ct->size_cache = Size2i(1, 1);
|
||||
} else {
|
||||
u.append_id(t->rd_texture_srgb.is_valid() && p_use_srgb && !p_texture_is_data ? t->rd_texture_srgb : t->rd_texture);
|
||||
ctc.diffuse = t->rd_texture_srgb.is_valid() && p_use_srgb && !p_texture_is_data ? t->rd_texture_srgb : t->rd_texture;
|
||||
ct->size_cache = Size2i(t->width_2d, t->height_2d);
|
||||
if (t->render_target) {
|
||||
t->render_target->was_used = true;
|
||||
}
|
||||
}
|
||||
uniforms.push_back(u);
|
||||
}
|
||||
{ //normal
|
||||
RD::Uniform u;
|
||||
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
|
||||
u.binding = 1;
|
||||
|
||||
t = get_texture(ct->normal_map);
|
||||
if (!t) {
|
||||
u.append_id(texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL));
|
||||
ctc.normal = texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL);
|
||||
ct->use_normal_cache = false;
|
||||
} else {
|
||||
u.append_id(t->rd_texture);
|
||||
ctc.normal = t->rd_texture;
|
||||
ct->use_normal_cache = true;
|
||||
if (t->render_target) {
|
||||
t->render_target->was_used = true;
|
||||
}
|
||||
}
|
||||
uniforms.push_back(u);
|
||||
}
|
||||
{ //specular
|
||||
RD::Uniform u;
|
||||
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
|
||||
u.binding = 2;
|
||||
|
||||
t = get_texture(ct->specular);
|
||||
if (!t) {
|
||||
u.append_id(texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE));
|
||||
ctc.specular = texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE);
|
||||
ct->use_specular_cache = false;
|
||||
} else {
|
||||
u.append_id(t->rd_texture);
|
||||
ctc.specular = t->rd_texture;
|
||||
ct->use_specular_cache = true;
|
||||
if (t->render_target) {
|
||||
t->render_target->was_used = true;
|
||||
}
|
||||
}
|
||||
uniforms.push_back(u);
|
||||
}
|
||||
{ //sampler
|
||||
RD::Uniform u;
|
||||
u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
|
||||
u.binding = 3;
|
||||
u.append_id(material_storage->sampler_rd_get_default(filter, repeat));
|
||||
uniforms.push_back(u);
|
||||
}
|
||||
|
||||
uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_base_shader, p_base_set);
|
||||
ct->uniform_sets[filter][repeat][int(p_use_srgb)] = uniform_set;
|
||||
ct->cleared_cache = false;
|
||||
}
|
||||
|
||||
r_uniform_set = uniform_set;
|
||||
r_size = ct->size_cache;
|
||||
r_specular_shininess = ct->specular_color;
|
||||
r_use_normal = ct->use_normal_cache;
|
||||
r_use_specular = ct->use_specular_cache;
|
||||
CanvasTextureInfo res;
|
||||
res.diffuse = ctc.diffuse;
|
||||
res.normal = ctc.normal;
|
||||
res.specular = ctc.specular;
|
||||
res.sampler = material_storage->sampler_rd_get_default(filter, repeat);
|
||||
res.size = ct->size_cache;
|
||||
res.specular_color = ct->specular_color;
|
||||
res.use_normal = ct->use_normal_cache;
|
||||
res.use_specular = ct->use_specular_cache;
|
||||
|
||||
return true;
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Texture API */
|
||||
|
@ -76,6 +76,21 @@ public:
|
||||
TYPE_3D
|
||||
};
|
||||
|
||||
struct CanvasTextureInfo {
|
||||
RID diffuse;
|
||||
RID normal;
|
||||
RID specular;
|
||||
RID sampler;
|
||||
Size2i size;
|
||||
Color specular_color;
|
||||
|
||||
bool use_normal = false;
|
||||
bool use_specular = false;
|
||||
|
||||
_FORCE_INLINE_ bool is_valid() const { return diffuse.is_valid(); }
|
||||
_FORCE_INLINE_ bool is_null() const { return diffuse.is_null(); }
|
||||
};
|
||||
|
||||
private:
|
||||
friend class LightStorage;
|
||||
friend class MaterialStorage;
|
||||
@ -86,6 +101,12 @@ private:
|
||||
|
||||
/* Canvas Texture API */
|
||||
|
||||
struct CanvasTextureCache {
|
||||
RID diffuse = RID();
|
||||
RID normal = RID();
|
||||
RID specular = RID();
|
||||
};
|
||||
|
||||
class CanvasTexture {
|
||||
public:
|
||||
RID diffuse;
|
||||
@ -96,14 +117,14 @@ private:
|
||||
|
||||
RS::CanvasItemTextureFilter texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT;
|
||||
RS::CanvasItemTextureRepeat texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT;
|
||||
RID uniform_sets[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX][2];
|
||||
CanvasTextureCache info_cache[2];
|
||||
|
||||
Size2i size_cache = Size2i(1, 1);
|
||||
bool use_normal_cache = false;
|
||||
bool use_specular_cache = false;
|
||||
bool cleared_cache = true;
|
||||
|
||||
void clear_sets();
|
||||
void clear_cache();
|
||||
~CanvasTexture();
|
||||
};
|
||||
|
||||
@ -477,7 +498,7 @@ public:
|
||||
virtual void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) override;
|
||||
virtual void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) override;
|
||||
|
||||
bool canvas_texture_get_uniform_set(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID p_base_shader, int p_base_set, bool p_use_srgb, RID &r_uniform_set, Size2i &r_size, Color &r_specular_shininess, bool &r_use_normal, bool &r_use_specular, bool p_texture_is_data);
|
||||
CanvasTextureInfo canvas_texture_get_info(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, bool p_use_srgb, bool p_texture_is_data);
|
||||
|
||||
/* Texture API */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user