diff options
Diffstat (limited to 'servers/visual/rasterizer/rasterizer_canvas_rd.cpp')
-rw-r--r-- | servers/visual/rasterizer/rasterizer_canvas_rd.cpp | 562 |
1 files changed, 333 insertions, 229 deletions
diff --git a/servers/visual/rasterizer/rasterizer_canvas_rd.cpp b/servers/visual/rasterizer/rasterizer_canvas_rd.cpp index d09b353007..93f905b72b 100644 --- a/servers/visual/rasterizer/rasterizer_canvas_rd.cpp +++ b/servers/visual/rasterizer/rasterizer_canvas_rd.cpp @@ -225,42 +225,34 @@ RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vector<int // that need to be created for these formats. uint32_t vertex_count = p_points.size(); - uint32_t base_offset = 0; uint32_t stride = 2; //vertices always repeat - if ((uint32_t)p_colors.size() == vertex_count) { + if ((uint32_t)p_colors.size() == vertex_count || p_colors.size() == 1) { stride += 4; - } else { - base_offset += 4; } if ((uint32_t)p_uvs.size() == vertex_count) { stride += 2; - } else { - base_offset += 2; } if ((uint32_t)p_bones.size() == vertex_count * 4) { stride += 4; - } else { - base_offset += 4; } if ((uint32_t)p_weights.size() == vertex_count * 4) { stride += 4; - } else { - base_offset += 4; } - uint32_t buffer_size = base_offset + stride * p_points.size(); + uint32_t buffer_size = stride * p_points.size(); PoolVector<uint8_t> polygon_buffer; polygon_buffer.resize(buffer_size * sizeof(float)); Vector<RD::VertexDescription> descriptions; descriptions.resize(5); + Vector<RID> buffers; + buffers.resize(5); { PoolVector<uint8_t>::Read r = polygon_buffer.read(); float *fptr = (float *)r.ptr(); uint32_t *uptr = (uint32_t *)r.ptr(); - uint32_t single_offset = 0; - + uint32_t base_offset = 0; { //vertices RD::VertexDescription vd; vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; @@ -281,7 +273,7 @@ RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vector<int } //colors - if ((uint32_t)p_colors.size() == vertex_count) { + if ((uint32_t)p_colors.size() == vertex_count || p_colors.size() == 1) { RD::VertexDescription vd; vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; vd.offset = base_offset * sizeof(float); @@ -290,31 +282,34 @@ RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vector<int descriptions.write[1] = vd; - const Color *color_ptr = p_colors.ptr(); + if (p_colors.size() == 1) { + Color color = p_colors[0]; + for (uint32_t i = 0; i < vertex_count; i++) { + fptr[base_offset + i * stride + 0] = color.r; + fptr[base_offset + i * stride + 1] = color.g; + fptr[base_offset + i * stride + 2] = color.b; + fptr[base_offset + i * stride + 3] = color.a; + } + } else { + const Color *color_ptr = p_colors.ptr(); - for (uint32_t i = 0; i < vertex_count; i++) { - fptr[base_offset + i * stride + 0] = color_ptr[i].r; - fptr[base_offset + i * stride + 1] = color_ptr[i].g; - fptr[base_offset + i * stride + 2] = color_ptr[i].b; - fptr[base_offset + i * stride + 3] = color_ptr[i].a; + for (uint32_t i = 0; i < vertex_count; i++) { + fptr[base_offset + i * stride + 0] = color_ptr[i].r; + fptr[base_offset + i * stride + 1] = color_ptr[i].g; + fptr[base_offset + i * stride + 2] = color_ptr[i].b; + fptr[base_offset + i * stride + 3] = color_ptr[i].a; + } } base_offset += 4; } else { RD::VertexDescription vd; vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; - vd.offset = single_offset * sizeof(float); + vd.offset = 0; vd.location = VS::ARRAY_COLOR; vd.stride = 0; descriptions.write[1] = vd; - - Color color = p_colors.size() ? p_colors[0] : Color(1, 1, 1, 1); - fptr[single_offset + 0] = color.r; - fptr[single_offset + 1] = color.g; - fptr[single_offset + 2] = color.b; - fptr[single_offset + 3] = color.a; - - single_offset += 4; + buffers.write[1] = polygon_buffers.default_color_buffer; } //uvs @@ -337,17 +332,12 @@ RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vector<int } else { RD::VertexDescription vd; vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; - vd.offset = single_offset * sizeof(float); + vd.offset = 0; vd.location = VS::ARRAY_TEX_UV; vd.stride = 0; descriptions.write[2] = vd; - - Vector2 uv; - fptr[single_offset + 0] = uv.x; - fptr[single_offset + 1] = uv.y; - - single_offset += 2; + buffers.write[2] = polygon_buffers.default_uv_buffer; } //bones @@ -373,17 +363,12 @@ RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vector<int } else { RD::VertexDescription vd; vd.format = RD::DATA_FORMAT_R32G32B32A32_UINT; - vd.offset = single_offset * sizeof(float); + vd.offset = 0; vd.location = VS::ARRAY_BONES; vd.stride = 0; descriptions.write[3] = vd; - - uptr[single_offset + 0] = 0; - uptr[single_offset + 1] = 0; - uptr[single_offset + 2] = 0; - uptr[single_offset + 3] = 0; - single_offset += 4; + buffers.write[3] = polygon_buffers.default_bone_buffer; } //bones @@ -409,22 +394,16 @@ RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vector<int } else { RD::VertexDescription vd; vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; - vd.offset = single_offset * sizeof(float); + vd.offset = 0; vd.location = VS::ARRAY_WEIGHTS; vd.stride = 0; descriptions.write[4] = vd; - - fptr[single_offset + 0] = 0.0; - fptr[single_offset + 1] = 0.0; - fptr[single_offset + 2] = 0.0; - fptr[single_offset + 3] = 0.0; - single_offset += 4; + buffers.write[4] = polygon_buffers.default_weight_buffer; } //check that everything is as it should be - ERR_FAIL_COND_V(single_offset != (base_offset - stride), 0); - ERR_FAIL_COND_V(((base_offset - stride) + stride * vertex_count) != buffer_size, 0); + ERR_FAIL_COND_V(base_offset != stride, 0); //bug } RD::VertexFormatID vertex_id = RD::get_singleton()->vertex_format_create(descriptions); @@ -432,11 +411,12 @@ RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vector<int PolygonBuffers pb; pb.vertex_buffer = RD::get_singleton()->vertex_buffer_create(polygon_buffer.size(), polygon_buffer); - Vector<RID> buffers; - buffers.resize(descriptions.size()); for (int i = 0; i < descriptions.size(); i++) { - buffers.write[i] = pb.vertex_buffer; + if (buffers[i] == RID()) { //if put in vertex, use as vertex + buffers.write[i] = pb.vertex_buffer; + } } + pb.vertex_array = RD::get_singleton()->vertex_array_create(p_points.size(), vertex_id, buffers); if (p_indices.size()) { @@ -508,9 +488,10 @@ Size2i RasterizerCanvasRD::_bind_texture_binding(TextureBindingID p_binding, RD: } //////////////////// -void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_item, RenderTargetFormat p_render_target_format, RD::TextureSamples p_samples, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, Light *p_lights) { +void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_item, RD::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, Light *p_lights) { //create an empty push constant + PushConstant push_constant; Transform2D base_transform = p_canvas_transform_inverse * p_item->final_transform; _update_transform_2d_to_mat2x3(base_transform, push_constant.world); @@ -538,30 +519,190 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_ uint32_t base_flags = 0; + bool light_uniform_set_dirty = false; + + if (!p_item->custom_data) { + p_item->custom_data = memnew(ItemStateData); + light_uniform_set_dirty = true; + } + + ItemStateData *state_data = (ItemStateData *)p_item->custom_data; + + Light *light_cache[DEFAULT_MAX_LIGHTS_PER_ITEM]; + uint16_t light_count = 0; + PipelineLightMode light_mode; + { + Light *light = p_lights; - uint16_t light_count = 0; while (light) { if (light->render_index_cache >= 0 && p_item->light_mask & light->item_mask && p_item->z_final >= light->z_min && p_item->z_final <= light->z_max && p_item->global_rect_cache.intersects_transformed(light->xform_cache, light->rect_cache)) { uint32_t light_index = light->render_index_cache; push_constant.lights[light_count >> 2] |= light_index << ((light_count & 3) * 8); + + if (!light_uniform_set_dirty && (state_data->light_cache[light_count].light != light || state_data->light_cache[light_count].light_version != light->version)) { + light_uniform_set_dirty = true; + } + + light_cache[light_count] = light; + light_count++; if (light->mode == VS::CANVAS_LIGHT_MODE_MASK) { base_flags |= FLAGS_USING_LIGHT_MASK; } - if (light_count == MAX_LIGHTS_PER_ITEM) { + if (light_count == state.max_lights_per_item) { break; } } light = light->next_ptr; } + if (light_count != state_data->light_cache_count) { + light_uniform_set_dirty = true; + } base_flags |= light_count << FLAGS_LIGHT_COUNT_SHIFT; } + if (light_count) { + + //validate and update lighs if they are being used + bool invalid_uniform = state_data->light_uniform_set.is_valid() && !RD::get_singleton()->uniform_set_is_valid(state_data->light_uniform_set); + + if (state_data->light_uniform_set.is_null() || invalid_uniform || light_uniform_set_dirty) { + //recreate uniform set + if (state_data->light_uniform_set.is_valid() && !invalid_uniform) { + RD::get_singleton()->free(state_data->light_uniform_set); + } + + state_data->light_uniform_set = RID(); + + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.binding = 0; + u.ids.push_back(state.lights_uniform_buffer); + uniforms.push_back(u); + } + + { + + RD::Uniform u_lights; + u_lights.type = RD::UNIFORM_TYPE_TEXTURE; + u_lights.binding = 1; + + RD::Uniform u_shadows; + u_shadows.type = RD::UNIFORM_TYPE_TEXTURE; + u_shadows.binding = 2; + + //lights + for (uint32_t i = 0; i < state.max_lights_per_item; i++) { + if (i < light_count) { + + CanvasLight *cl = canvas_light_owner.getornull(light_cache[i]->light_internal); + ERR_CONTINUE(!cl); + + RID rd_texture; + + if (cl->texture.is_valid()) { + rd_texture = storage->texture_get_rd_texture(cl->texture); + } + if (rd_texture.is_valid()) { + u_lights.ids.push_back(rd_texture); + } else { + u_lights.ids.push_back(default_textures.white_texture); + } + if (cl->shadow.texture.is_valid()) { + u_shadows.ids.push_back(cl->shadow.texture); + } else { + u_shadows.ids.push_back(default_textures.black_texture); + } + } else { + u_lights.ids.push_back(default_textures.white_texture); + u_shadows.ids.push_back(default_textures.black_texture); + } + } + + uniforms.push_back(u_lights); + uniforms.push_back(u_shadows); + } + + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_SAMPLER; + u.binding = 3; + u.ids.push_back(state.shadow_sampler); + uniforms.push_back(u); + } + + state_data->light_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, shader.default_version_rd_shader_light, 3); + } + + RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, state_data->light_uniform_set, 3); + light_mode = PIPELINE_LIGHT_MODE_ENABLED; + } else { + light_mode = PIPELINE_LIGHT_MODE_DISABLED; + } + + { + //state uniform + bool invalid_uniform = state_data->state_uniform_set.is_valid() && !RD::get_singleton()->uniform_set_is_valid(state_data->state_uniform_set); + + if (state_data->state_uniform_set.is_null() || invalid_uniform) { + if (state_data->state_uniform_set.is_valid() && !invalid_uniform) { + RD::get_singleton()->free(state_data->state_uniform_set); + } + state_data->state_uniform_set = RID(); + + Vector<RD::Uniform> uniforms; + + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.binding = 0; + u.ids.push_back(state.canvas_state_buffer); + uniforms.push_back(u); + } + + if (false && p_item->skeleton.is_valid()) { + //bind skeleton stuff + } else { + //bind default + + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.binding = 0; + u.ids.push_back(state.canvas_state_buffer); + uniforms.push_back(u); + } + + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE_BUFFER; + u.binding = 1; + u.ids.push_back(shader.default_skeleton_texture_buffer); + uniforms.push_back(u); + } + + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.binding = 2; + u.ids.push_back(shader.default_skeleton_uniform_buffer); + uniforms.push_back(u); + } + } + + state_data->state_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, shader.default_version_rd_shader, 2); + } + + RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, state_data->state_uniform_set, 2); + } + PipelineVariants *pipeline_variants = &shader.pipeline_variants; bool reclip = false; @@ -579,7 +720,7 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_ //bind pipeline { - RID pipeline = pipeline_variants->variants[p_render_target_format][PIPELINE_VARIANT_QUAD].get_render_pipeline(RD::INVALID_ID, p_samples); + RID pipeline = pipeline_variants->variants[light_mode][PIPELINE_VARIANT_QUAD].get_render_pipeline(RD::INVALID_ID, p_framebuffer_format); RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline); } @@ -679,7 +820,7 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_ //bind pipeline { - RID pipeline = pipeline_variants->variants[p_render_target_format][PIPELINE_VARIANT_NINEPATCH].get_render_pipeline(RD::INVALID_ID, p_samples); + RID pipeline = pipeline_variants->variants[light_mode][PIPELINE_VARIANT_NINEPATCH].get_render_pipeline(RD::INVALID_ID, p_framebuffer_format); RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline); } @@ -761,7 +902,7 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_ { static const PipelineVariant variant[VS::PRIMITIVE_MAX] = { PIPELINE_VARIANT_ATTRIBUTE_POINTS, PIPELINE_VARIANT_ATTRIBUTE_LINES, PIPELINE_VARIANT_ATTRIBUTE_TRIANGLES }; ERR_CONTINUE(polygon->primitive < 0 || polygon->primitive >= VS::PRIMITIVE_MAX); - RID pipeline = pipeline_variants->variants[p_render_target_format][variant[polygon->primitive]].get_render_pipeline(pb->vertex_format_id, p_samples); + RID pipeline = pipeline_variants->variants[light_mode][variant[polygon->primitive]].get_render_pipeline(pb->vertex_format_id, p_framebuffer_format); RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline); } @@ -815,7 +956,7 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_ { static const PipelineVariant variant[4] = { PIPELINE_VARIANT_PRIMITIVE_POINTS, PIPELINE_VARIANT_PRIMITIVE_LINES, PIPELINE_VARIANT_PRIMITIVE_TRIANGLES, PIPELINE_VARIANT_PRIMITIVE_TRIANGLES }; ERR_CONTINUE(primitive->point_count == 0 || primitive->point_count > 4); - RID pipeline = pipeline_variants->variants[p_render_target_format][variant[primitive->point_count - 1]].get_render_pipeline(RD::INVALID_ID, p_samples); + RID pipeline = pipeline_variants->variants[light_mode][variant[primitive->point_count - 1]].get_render_pipeline(RD::INVALID_ID, p_framebuffer_format); RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline); } @@ -1184,7 +1325,6 @@ void RasterizerCanvasRD::_render_items(RID p_to_render_target, int p_item_count, Item *current_clip = NULL; - RenderTargetFormat render_target_format = RENDER_TARGET_FORMAT_8_BIT_INT; Transform2D canvas_transform_inverse = p_canvas_transform_inverse; RID framebuffer = storage->render_target_get_rd_framebuffer(p_to_render_target); @@ -1197,10 +1337,9 @@ void RasterizerCanvasRD::_render_items(RID p_to_render_target, int p_item_count, storage->render_target_disable_clear_request(p_to_render_target); } #warning TODO obtain from framebuffer format eventually when this is implemented - RD::TextureSamples texture_samples = RD::TEXTURE_SAMPLES_1; - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, clear ? RD::INITIAL_ACTION_CLEAR : RD::INITIAL_ACTION_KEEP_COLOR, RD::FINAL_ACTION_READ_COLOR_DISCARD_DEPTH, clear_colors); + RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(framebuffer); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, state.canvas_state_uniform_set, 3); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, clear ? RD::INITIAL_ACTION_CLEAR : RD::INITIAL_ACTION_KEEP_COLOR, RD::FINAL_ACTION_READ_COLOR_DISCARD_DEPTH, clear_colors); for (int i = 0; i < p_item_count; i++) { @@ -1221,104 +1360,18 @@ void RasterizerCanvasRD::_render_items(RID p_to_render_target, int p_item_count, } } - if (false) { //not skeleton - - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, shader.default_skeleton_uniform_set, 1); - } - - _render_item(draw_list, ci, render_target_format, texture_samples, canvas_transform_inverse, current_clip, p_lights); + _render_item(draw_list, ci, fb_format, canvas_transform_inverse, current_clip, p_lights); } RD::get_singleton()->draw_list_end(); } -void RasterizerCanvasRD::_update_canvas_state_uniform_set() { - - if (state.canvas_state_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(state.canvas_state_uniform_set)) { - return; //nothing to update - } - - Vector<RD::Uniform> uniforms; - - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 0; - u.ids.push_back(state.canvas_state_buffer); - uniforms.push_back(u); - } - - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 1; - u.ids.push_back(state.lights_uniform_buffer); - uniforms.push_back(u); - } - - { - - RD::Uniform u_lights; - u_lights.type = RD::UNIFORM_TYPE_TEXTURE; - u_lights.binding = 2; - - RD::Uniform u_shadows; - u_shadows.type = RD::UNIFORM_TYPE_TEXTURE; - u_shadows.binding = 3; - - //lights - for (uint32_t i = 0; i < MAX_LIGHT_TEXTURES; i++) { - if (i < canvas_light_owner.get_rid_count()) { - CanvasLight *cl = canvas_light_owner.get_rid_by_index(i); - cl->texture_index = i; - RID rd_texture; - - if (cl->texture.is_valid()) { - rd_texture = storage->texture_get_rd_texture(cl->texture); - } - if (rd_texture.is_valid()) { - u_lights.ids.push_back(rd_texture); - } else { - u_lights.ids.push_back(default_textures.white_texture); - } - if (cl->shadow.texture.is_valid()) { - u_shadows.ids.push_back(cl->shadow.texture); - } else { - u_shadows.ids.push_back(default_textures.black_texture); - } - } else { - u_lights.ids.push_back(default_textures.white_texture); - u_shadows.ids.push_back(default_textures.black_texture); - } - } - - //in case there are more - for (uint32_t i = MAX_LIGHT_TEXTURES; i < canvas_light_owner.get_rid_count(); i++) { - CanvasLight *cl = canvas_light_owner.get_rid_by_index(i); - cl->texture_index = -1; //make invalid (no texture) - } - - uniforms.push_back(u_lights); - uniforms.push_back(u_shadows); - } - - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_SAMPLER; - u.binding = 4; - u.ids.push_back(state.shadow_sampler); - uniforms.push_back(u); - } - - state.canvas_state_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, shader.default_version_rd_shader, 3); // uses index 3 -} - void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, const Transform2D &p_canvas_transform) { int item_count = 0; //setup canvas state uniforms if needed - _update_canvas_state_uniform_set(); + Transform2D canvas_transform_inverse = p_canvas_transform.affine_inverse(); { @@ -1356,14 +1409,14 @@ void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_ite while (l) { - if (index == MAX_RENDER_LIGHTS) { + if (index == state.max_lights_per_render) { l->render_index_cache = -1; l = l->next_ptr; continue; } CanvasLight *clight = canvas_light_owner.getornull(l->light_internal); - if (!clight || clight->texture_index < 0) { //unused or invalid texture + if (!clight) { //unused or invalid texture l->render_index_cache = -1; l = l->next_ptr; ERR_CONTINUE(!clight); @@ -1390,7 +1443,7 @@ void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_ite } else { state.light_uniforms[index].shadow_pixel_size = 1.0; } - state.light_uniforms[index].flags = clight->texture_index; + state.light_uniforms[index].flags |= l->mode << LIGHT_FLAGS_BLEND_SHIFT; state.light_uniforms[index].flags |= l->shadow_filter << LIGHT_FLAGS_FILTER_SHIFT; if (clight->shadow.texture.is_valid()) { @@ -1439,7 +1492,6 @@ RID RasterizerCanvasRD::light_create() { CanvasLight canvas_light; canvas_light.shadow.size = 0; - canvas_light.texture_index = -1; return canvas_light_owner.make_rid(canvas_light); } @@ -1451,11 +1503,6 @@ void RasterizerCanvasRD::light_set_texture(RID p_rid, RID p_texture) { } cl->texture = p_texture; - - //canvas state uniform set needs updating - if (state.canvas_state_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(state.canvas_state_uniform_set)) { - RD::get_singleton()->free(state.canvas_state_uniform_set); - } } void RasterizerCanvasRD::light_set_use_shadow(RID p_rid, bool p_enable, int p_resolution) { CanvasLight *cl = canvas_light_owner.getornull(p_rid); @@ -1506,11 +1553,6 @@ void RasterizerCanvasRD::light_set_use_shadow(RID p_rid, bool p_enable, int p_re } cl->shadow.size = p_resolution; - - //canvas state uniform set needs updating - if (state.canvas_state_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(state.canvas_state_uniform_set)) { - RD::get_singleton()->free(state.canvas_state_uniform_set); - } } void RasterizerCanvasRD::light_update_shadow(RID p_rid, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders) { @@ -1831,35 +1873,58 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) { } { //shader variants + + uint32_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE); + + String global_defines; + if (textures_per_stage <= 16) { + //ARM pretty much, and very old Intel GPUs under Linux + state.max_lights_per_item = 4; //sad + global_defines += "#define MAX_LIGHT_TEXTURES 4\n"; + } else if (textures_per_stage <= 32) { + //Apple (Metal) + state.max_lights_per_item = 8; //sad + global_defines += "#define MAX_LIGHT_TEXTURES 8\n"; + } else { + //Anything else (16 lights per item) + state.max_lights_per_item = DEFAULT_MAX_LIGHTS_PER_ITEM; + global_defines += "#define MAX_LIGHT_TEXTURES " + itos(DEFAULT_MAX_LIGHTS_PER_ITEM) + "\n"; + } + + uint32_t uniform_max_size = RD::get_singleton()->limit_get(RD::LIMIT_MAX_UNIFORM_BUFFER_SIZE); + if (uniform_max_size < 65536) { + //Yes, you guessed right, ARM again + state.max_lights_per_render = 64; + global_defines += "#define MAX_LIGHTS 64\n"; + } else { + state.max_lights_per_render = DEFAULT_MAX_LIGHTS_PER_RENDER; + global_defines += "#define MAX_LIGHTS " + itos(DEFAULT_MAX_LIGHTS_PER_RENDER) + "\n"; + } + + state.light_uniforms = memnew_arr(LightUniform, state.max_lights_per_render); Vector<String> variants; + //non light variants variants.push_back(""); //none by default is first variant variants.push_back("#define USE_NINEPATCH\n"); //ninepatch is the second variant variants.push_back("#define USE_PRIMITIVE\n"); //primitve is the third variants.push_back("#define USE_PRIMITIVE\n#define USE_POINT_SIZE\n"); //points need point size variants.push_back("#define USE_ATTRIBUTES\n"); // attributes for vertex arrays variants.push_back("#define USE_ATTRIBUTES\n#define USE_POINT_SIZE\n"); //attributes with point size - shader.canvas_shader.initialize(variants); + //light variants + variants.push_back("#define USE_LIGHTING\n"); //none by default is first variant + variants.push_back("#define USE_LIGHTING\n#define USE_NINEPATCH\n"); //ninepatch is the second variant + variants.push_back("#define USE_LIGHTING\n#define USE_PRIMITIVE\n"); //primitve is the third + variants.push_back("#define USE_LIGHTING\n#define USE_PRIMITIVE\n#define USE_POINT_SIZE\n"); //points need point size + variants.push_back("#define USE_LIGHTING\n#define USE_ATTRIBUTES\n"); // attributes for vertex arrays + variants.push_back("#define USE_LIGHTING\n#define USE_ATTRIBUTES\n#define USE_POINT_SIZE\n"); //attributes with point size - shader.default_version = shader.canvas_shader.version_create(); + shader.canvas_shader.initialize(variants, global_defines); - { - //framebuffer formats - RD::AttachmentFormat af; - af.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - af.samples = RD::TEXTURE_SAMPLES_1; - af.usage_flags = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_RETRIEVE_BIT; - Vector<RD::AttachmentFormat> formats; - formats.push_back(af); - shader.framebuffer_formats[RENDER_TARGET_FORMAT_8_BIT_INT] = RD::get_singleton()->framebuffer_format_create(formats); - - formats.clear(); - af.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - formats.push_back(af); - shader.framebuffer_formats[RENDER_TARGET_FORMAT_16_BIT_FLOAT] = RD::get_singleton()->framebuffer_format_create(formats); - } + shader.default_version = shader.canvas_shader.version_create(); + shader.default_version_rd_shader = shader.canvas_shader.version_get_shader(shader.default_version, SHADER_VARIANT_QUAD); + shader.default_version_rd_shader_light = shader.canvas_shader.version_get_shader(shader.default_version, SHADER_VARIANT_QUAD_LIGHT); - for (int i = 0; i < RENDER_TARGET_FORMAT_MAX; i++) { - RD::FramebufferFormatID fb_format = shader.framebuffer_formats[i]; + for (int i = 0; i < PIPELINE_LIGHT_MODE_MAX; i++) { for (int j = 0; j < PIPELINE_VARIANT_MAX; j++) { RD::RenderPrimitive primitive[PIPELINE_VARIANT_MAX] = { RD::RENDER_PRIMITIVE_TRIANGLES, @@ -1871,23 +1936,31 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) { RD::RENDER_PRIMITIVE_LINES, RD::RENDER_PRIMITIVE_POINTS, }; - ShaderVariant shader_variants[PIPELINE_VARIANT_MAX] = { - SHADER_VARIANT_QUAD, - SHADER_VARIANT_NINEPATCH, - SHADER_VARIANT_PRIMITIVE, - SHADER_VARIANT_PRIMITIVE, - SHADER_VARIANT_PRIMITIVE_POINTS, - SHADER_VARIANT_ATTRIBUTES, - SHADER_VARIANT_ATTRIBUTES, - SHADER_VARIANT_ATTRIBUTES_POINTS + ShaderVariant shader_variants[PIPELINE_LIGHT_MODE_MAX][PIPELINE_VARIANT_MAX] = { + { //non lit + SHADER_VARIANT_QUAD, + SHADER_VARIANT_NINEPATCH, + SHADER_VARIANT_PRIMITIVE, + SHADER_VARIANT_PRIMITIVE, + SHADER_VARIANT_PRIMITIVE_POINTS, + SHADER_VARIANT_ATTRIBUTES, + SHADER_VARIANT_ATTRIBUTES, + SHADER_VARIANT_ATTRIBUTES_POINTS }, + { //lit + SHADER_VARIANT_QUAD_LIGHT, + SHADER_VARIANT_NINEPATCH_LIGHT, + SHADER_VARIANT_PRIMITIVE_LIGHT, + SHADER_VARIANT_PRIMITIVE_LIGHT, + SHADER_VARIANT_PRIMITIVE_POINTS_LIGHT, + SHADER_VARIANT_ATTRIBUTES_LIGHT, + SHADER_VARIANT_ATTRIBUTES_LIGHT, + SHADER_VARIANT_ATTRIBUTES_POINTS_LIGHT }, }; - RID shader_variant = shader.canvas_shader.version_get_shader(shader.default_version, shader_variants[j]); - shader.pipeline_variants.variants[i][j].setup(shader_variant, fb_format, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_blend(), 0); + RID shader_variant = shader.canvas_shader.version_get_shader(shader.default_version, shader_variants[i][j]); + shader.pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_blend(), 0); } } - - shader.default_version_rd_shader = shader.canvas_shader.version_get_shader(shader.default_version, 0); } { //shadow rendering @@ -1901,6 +1974,7 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) { RD::AttachmentFormat af_color; af_color.format = RD::DATA_FORMAT_R32_SFLOAT; af_color.usage_flags = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + af_color.samples = RenderingDevice::TEXTURE_SAMPLES_64; attachments.push_back(af_color); @@ -1908,6 +1982,7 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) { af_depth.format = RD::DATA_FORMAT_D24_UNORM_S8_UINT; af_depth.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_X8_D24_UNORM_PACK32, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_X8_D24_UNORM_PACK32 : RD::DATA_FORMAT_D32_SFLOAT; af_depth.usage_flags = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + af_depth.samples = RenderingDevice::TEXTURE_SAMPLES_64; attachments.push_back(af_depth); @@ -1944,7 +2019,7 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) { { //state allocate state.canvas_state_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(State::Buffer)); - state.lights_uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(LightUniform) * MAX_RENDER_LIGHTS); + state.lights_uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(LightUniform) * state.max_lights_per_render); RD::SamplerState shadow_sampler_state; shadow_sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR; @@ -1956,6 +2031,60 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) { } { + { + PoolVector<uint8_t> colors; + colors.resize(sizeof(float) * 4); + { + PoolVector<uint8_t>::Write w = colors.write(); + float *fptr = (float *)w.ptr(); + fptr[0] = 1.0; + fptr[1] = 1.0; + fptr[2] = 1.0; + fptr[3] = 1.0; + } + polygon_buffers.default_color_buffer = RD::get_singleton()->vertex_buffer_create(colors.size(), colors); + } + + { + PoolVector<uint8_t> uvs; + uvs.resize(sizeof(float) * 2); + { + PoolVector<uint8_t>::Write w = uvs.write(); + float *fptr = (float *)w.ptr(); + fptr[0] = 0.0; + fptr[1] = 0.0; + } + polygon_buffers.default_uv_buffer = RD::get_singleton()->vertex_buffer_create(uvs.size(), uvs); + } + + { + PoolVector<uint8_t> bones; + bones.resize(sizeof(uint32_t) * 4); + { + PoolVector<uint8_t>::Write w = bones.write(); + uint32_t *iptr = (uint32_t *)w.ptr(); + iptr[0] = 0; + iptr[1] = 0; + iptr[2] = 0; + iptr[3] = 0; + } + polygon_buffers.default_bone_buffer = RD::get_singleton()->vertex_buffer_create(bones.size(), bones); + } + + { + PoolVector<uint8_t> weights; + weights.resize(sizeof(float) * 4); + { + PoolVector<uint8_t>::Write w = weights.write(); + float *fptr = (float *)w.ptr(); + fptr[0] = 0.0; + fptr[1] = 0.0; + fptr[2] = 0.0; + fptr[3] = 0.0; + } + polygon_buffers.default_weight_buffer = RD::get_singleton()->vertex_buffer_create(weights.size(), weights); + } + //polygon buffers polygon_buffers.last_id = 1; } @@ -1987,28 +2116,13 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) { { //default skeleton buffer - shader.default_skeleton_uniform = RD::get_singleton()->uniform_buffer_create(sizeof(SkeletonUniform)); + shader.default_skeleton_uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SkeletonUniform)); SkeletonUniform su; _update_transform_2d_to_mat4(Transform2D(), su.skeleton_inverse); _update_transform_2d_to_mat4(Transform2D(), su.skeleton_transform); - RD::get_singleton()->buffer_update(shader.default_skeleton_uniform, 0, sizeof(SkeletonUniform), &su); - } + RD::get_singleton()->buffer_update(shader.default_skeleton_uniform_buffer, 0, sizeof(SkeletonUniform), &su); - { //default material uniform set - Vector<RD::Uniform> default_material_uniforms; - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 2; - u.ids.push_back(shader.default_skeleton_uniform); - default_material_uniforms.push_back(u); - - u.ids.clear(); - u.type = RD::UNIFORM_TYPE_TEXTURE_BUFFER; - u.binding = 1; - u.ids.push_back(default_textures.default_multimesh_tb); - default_material_uniforms.push_back(u); - - shader.default_skeleton_uniform_set = RD::get_singleton()->uniform_set_create(default_material_uniforms, shader.canvas_shader.version_get_shader(shader.default_version, SHADER_VARIANT_ATTRIBUTES), 2); + shader.default_skeleton_texture_buffer = RD::get_singleton()->texture_buffer_create(32, RD::DATA_FORMAT_R32G32B32A32_SFLOAT); } ERR_FAIL_COND(sizeof(PushConstant) != 128); @@ -2021,10 +2135,6 @@ bool RasterizerCanvasRD::free(RID p_rid) { ERR_FAIL_COND_V(!cl, false); light_set_use_shadow(p_rid, false, 64); canvas_light_owner.free(p_rid); - //canvas state uniform set needs updating - if (state.canvas_state_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(state.canvas_state_uniform_set)) { - RD::get_singleton()->free(state.canvas_state_uniform_set); - } } else if (occluder_polygon_owner.owns(p_rid)) { occluder_polygon_set_shape_as_lines(p_rid, PoolVector<Vector2>()); occluder_polygon_owner.free(p_rid); @@ -2043,10 +2153,6 @@ RasterizerCanvasRD::~RasterizerCanvasRD() { RD::get_singleton()->free(state.canvas_state_buffer); } - if (state.canvas_state_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(state.canvas_state_uniform_set)) { - RD::get_singleton()->free(state.canvas_state_uniform_set); - } - //bindings { @@ -2070,8 +2176,6 @@ RasterizerCanvasRD::~RasterizerCanvasRD() { //shaders - RD::get_singleton()->free(shader.default_skeleton_uniform_set); - RD::get_singleton()->free(shader.default_skeleton_uniform); shader.canvas_shader.version_free(shader.default_version); //buffers |