diff --git a/drivers/d3d12/rendering_device_driver_d3d12.cpp b/drivers/d3d12/rendering_device_driver_d3d12.cpp index 3c32692e538f..a8360da7c227 100644 --- a/drivers/d3d12/rendering_device_driver_d3d12.cpp +++ b/drivers/d3d12/rendering_device_driver_d3d12.cpp @@ -6198,6 +6198,8 @@ bool RenderingDeviceDriverD3D12::has_feature(Features p_feature) { return true; case SUPPORTS_VULKAN_MEMORY_MODEL: return false; + case SUPPORTS_POINT_SIZE: + return false; default: return false; } diff --git a/drivers/metal/rendering_device_driver_metal.mm b/drivers/metal/rendering_device_driver_metal.mm index 657f78155860..7ed8a4c0791c 100644 --- a/drivers/metal/rendering_device_driver_metal.mm +++ b/drivers/metal/rendering_device_driver_metal.mm @@ -2567,6 +2567,8 @@ static void update_uniform_info(const RenderingShaderContainerMetal::UniformData return device_properties->features.supports_native_image_atomics; case SUPPORTS_VULKAN_MEMORY_MODEL: return true; + case SUPPORTS_POINT_SIZE: + return true; default: return false; } diff --git a/drivers/vulkan/rendering_device_driver_vulkan.cpp b/drivers/vulkan/rendering_device_driver_vulkan.cpp index a340fe566caa..874c9fdb5d74 100644 --- a/drivers/vulkan/rendering_device_driver_vulkan.cpp +++ b/drivers/vulkan/rendering_device_driver_vulkan.cpp @@ -6196,6 +6196,8 @@ bool RenderingDeviceDriverVulkan::has_feature(Features p_feature) { #endif case SUPPORTS_VULKAN_MEMORY_MODEL: return vulkan_memory_model_support && vulkan_memory_model_device_scope_support; + case SUPPORTS_POINT_SIZE: + return true; default: return false; } diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp index cb893150cf11..b1288813b17d 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -484,6 +484,7 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p pipeline_key.framebuffer_format_id = framebuffer_format; pipeline_key.wireframe = p_params->force_wireframe; pipeline_key.ubershader = 0; + pipeline_key.emulate_point_size = shader->uses_point_size && scene_shader.emulate_point_size; const RD::PolygonCullMode cull_mode = shader->get_cull_mode_from_cull_variant(cull_variant); RID vertex_array_rd; @@ -497,9 +498,9 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p bool pipeline_motion_vectors = pipeline_key.color_pass_flags & SceneShaderForwardClustered::PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS; uint64_t input_mask = shader->get_vertex_input_mask(pipeline_key.version, pipeline_key.color_pass_flags, pipeline_key.ubershader); if (surf->owner->mesh_instance.is_valid()) { - mesh_storage->mesh_instance_surface_get_vertex_arrays_and_format(surf->owner->mesh_instance, surf->surface_index, input_mask, pipeline_motion_vectors, vertex_array_rd, vertex_format); + mesh_storage->mesh_instance_surface_get_vertex_arrays_and_format(surf->owner->mesh_instance, surf->surface_index, input_mask, pipeline_motion_vectors, pipeline_key.emulate_point_size, vertex_array_rd, vertex_format); } else { - mesh_storage->mesh_surface_get_vertex_arrays_and_format(mesh_surface, input_mask, pipeline_motion_vectors, vertex_array_rd, vertex_format); + mesh_storage->mesh_surface_get_vertex_arrays_and_format(mesh_surface, input_mask, pipeline_motion_vectors, pipeline_key.emulate_point_size, vertex_array_rd, vertex_format); } pipeline_key.vertex_format_id = vertex_format; @@ -534,7 +535,11 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p } if (pipeline_valid) { - index_array_rd = mesh_storage->mesh_surface_get_index_array(mesh_surface, element_info.lod_index); + if (!pipeline_key.emulate_point_size) { + index_array_rd = mesh_storage->mesh_surface_get_index_array(mesh_surface, element_info.lod_index); + } else { + index_array_rd = RID(); + } if (prev_vertex_array_rd != vertex_array_rd) { RD::get_singleton()->draw_list_bind_vertex_array(draw_list, vertex_array_rd); @@ -592,7 +597,14 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p instance_count /= surf->owner->trail_steps; } - if (bool(surf->owner->base_flags & INSTANCE_DATA_FLAG_MULTIMESH_INDIRECT)) { + bool indirect = bool(surf->owner->base_flags & INSTANCE_DATA_FLAG_MULTIMESH_INDIRECT); + + if (pipeline_key.emulate_point_size) { + if (indirect) { + WARN_PRINT("Indirect draws are not supported when emulating point size."); + } + RD::get_singleton()->draw_list_draw(draw_list, false, mesh_storage->mesh_surface_get_vertex_count(mesh_surface), instance_count * 6); + } else if (indirect) { RD::get_singleton()->draw_list_draw_indirect(draw_list, index_array_rd.is_valid(), mesh_storage->_multimesh_get_command_buffer_rd_rid(surf->owner->data->base), surf->surface_index * sizeof(uint32_t) * mesh_storage->INDIRECT_MULTIMESH_COMMAND_STRIDE, 1, 0); } else { RD::get_singleton()->draw_list_draw(draw_list, index_array_rd.is_valid(), instance_count); @@ -4517,7 +4529,7 @@ void RenderForwardClustered::_mesh_compile_pipeline_for_surface(SceneShaderForwa RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton(); uint64_t input_mask = p_shader->get_vertex_input_mask(r_pipeline_key.version, r_pipeline_key.color_pass_flags, p_ubershader); bool pipeline_motion_vectors = r_pipeline_key.color_pass_flags & SceneShaderForwardClustered::PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS; - r_pipeline_key.vertex_format_id = mesh_storage->mesh_surface_get_vertex_format(p_mesh_surface, input_mask, p_instanced_surface, pipeline_motion_vectors); + r_pipeline_key.vertex_format_id = mesh_storage->mesh_surface_get_vertex_format(p_mesh_surface, input_mask, p_instanced_surface, pipeline_motion_vectors, r_pipeline_key.emulate_point_size); r_pipeline_key.ubershader = p_ubershader; p_shader->pipeline_hash_map.compile_pipeline(r_pipeline_key, r_pipeline_key.hash(), p_source, p_ubershader); @@ -4540,6 +4552,7 @@ void RenderForwardClustered::_mesh_compile_pipelines_for_surface(const SurfacePi pipeline_key.cull_mode = RD::POLYGON_CULL_DISABLED; pipeline_key.primitive_type = mesh_storage->mesh_surface_get_primitive(p_surface.mesh_surface); pipeline_key.wireframe = false; + pipeline_key.emulate_point_size = p_surface.shader->uses_point_size && scene_shader.emulate_point_size; // Grab the shader and surface used for most passes. const uint32_t multiview_iterations = multiview_enabled ? 2 : 1; @@ -4638,6 +4651,7 @@ void RenderForwardClustered::_mesh_compile_pipelines_for_surface(const SurfacePi pipeline_key.primitive_type = mesh_storage->mesh_surface_get_primitive(p_surface.mesh_surface_shadow); pipeline_key.version = SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS; pipeline_key.framebuffer_format_id = _get_depth_framebuffer_format_for_pipeline(buffers_can_be_storage, RD::TextureSamples(p_global.texture_samples), false, false); + pipeline_key.emulate_point_size = p_surface.shader_shadow->uses_point_size && scene_shader.emulate_point_size; _mesh_compile_pipeline_for_surface(p_surface.shader_shadow, p_surface.mesh_surface_shadow, true, p_surface.instanced, p_source, pipeline_key, r_pipeline_pairs); if (p_global.use_shadow_dual_paraboloid) { diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp index c79c6998272e..adefdfd7d20a 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp @@ -411,7 +411,12 @@ void SceneShaderForwardClustered::ShaderData::_create_pipeline(PipelineKey p_pip RD::RENDER_PRIMITIVE_TRIANGLE_STRIPS, }; - RD::RenderPrimitive primitive_rd = uses_point_size ? RD::RENDER_PRIMITIVE_POINTS : primitive_rd_table[p_pipeline_key.primitive_type]; + RD::RenderPrimitive primitive_rd; + if (uses_point_size) { + primitive_rd = p_pipeline_key.emulate_point_size ? RD::RENDER_PRIMITIVE_TRIANGLES : RD::RENDER_PRIMITIVE_POINTS; + } else { + primitive_rd = primitive_rd_table[p_pipeline_key.primitive_type]; + } RD::PipelineRasterizationState raster_state; raster_state.cull_mode = p_pipeline_key.cull_mode; @@ -479,6 +484,13 @@ void SceneShaderForwardClustered::ShaderData::_create_pipeline(PipelineKey p_pip sc.constant_id = 1; sc.int_value = p_pipeline_key.shader_specialization.packed_1; + sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_INT; + specialization_constants.push_back(sc); + + sc = {}; // Sanitize value bits. "bool_value" only assigns 8 bits and keeps the remaining bits intact. + sc.constant_id = 2; + sc.bool_value = p_pipeline_key.emulate_point_size; + sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL; specialization_constants.push_back(sc); RID shader_rid = get_shader_variant(p_pipeline_key.version, p_pipeline_key.color_pass_flags, p_pipeline_key.ubershader); @@ -621,6 +633,8 @@ SceneShaderForwardClustered::~SceneShaderForwardClustered() { void SceneShaderForwardClustered::init(const String p_defines) { RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); + emulate_point_size = !RD::get_singleton()->has_feature(RD::SUPPORTS_POINT_SIZE); + { Vector shader_versions; for (uint32_t ubershader = 0; ubershader < 2; ubershader++) { @@ -701,9 +715,9 @@ void SceneShaderForwardClustered::init(const String p_defines) { actions.renames["UV"] = "uv_interp"; actions.renames["UV2"] = "uv2_interp"; actions.renames["COLOR"] = "color_interp"; - actions.renames["POINT_SIZE"] = "gl_PointSize"; - actions.renames["INSTANCE_ID"] = "gl_InstanceIndex"; - actions.renames["VERTEX_ID"] = "gl_VertexIndex"; + actions.renames["POINT_SIZE"] = "point_size"; + actions.renames["INSTANCE_ID"] = "INSTANCE_INDEX"; + actions.renames["VERTEX_ID"] = "VERTEX_INDEX"; actions.renames["Z_CLIP_SCALE"] = "z_clip_scale"; actions.renames["ALPHA_SCISSOR_THRESHOLD"] = "alpha_scissor_threshold"; @@ -748,7 +762,7 @@ void SceneShaderForwardClustered::init(const String p_defines) { actions.renames["AO"] = "ao"; actions.renames["AO_LIGHT_AFFECT"] = "ao_light_affect"; actions.renames["EMISSION"] = "emission"; - actions.renames["POINT_COORD"] = "gl_PointCoord"; + actions.renames["POINT_COORD"] = "point_coord"; actions.renames["INSTANCE_CUSTOM"] = "instance_custom"; actions.renames["SCREEN_UV"] = "screen_uv"; actions.renames["DEPTH"] = "gl_FragDepth"; @@ -829,6 +843,9 @@ void SceneShaderForwardClustered::init(const String p_defines) { actions.usage_defines["MODEL_MATRIX"] = "#define MODEL_MATRIX_USED\n"; + actions.usage_defines["POINT_SIZE"] = "#define POINT_SIZE_USED\n"; + actions.usage_defines["POINT_COORD"] = "#define POINT_COORD_USED\n"; + actions.render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n"; actions.render_mode_defines["world_vertex_coords"] = "#define VERTEX_WORLD_COORDS_USED\n"; actions.render_mode_defines["ensure_correct_normals"] = "#define ENSURE_CORRECT_NORMALS\n"; diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h index f1752af9bc7f..5b8837997856 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h @@ -195,6 +195,7 @@ class SceneShaderForwardClustered { ShaderSpecialization shader_specialization = {}; uint32_t wireframe = false; uint32_t ubershader = false; + bool emulate_point_size = false; uint32_t hash() const { uint32_t h = hash_murmur3_one_64(vertex_format_id); @@ -208,6 +209,7 @@ class SceneShaderForwardClustered { h = hash_murmur3_one_32(shader_specialization.packed_2, h); h = hash_murmur3_one_32(wireframe, h); h = hash_murmur3_one_32(ubershader, h); + h = hash_murmur3_one_32(emulate_point_size, h); return hash_fmix32(h); } }; @@ -342,6 +344,7 @@ class SceneShaderForwardClustered { SceneForwardClusteredShaderRD shader; ShaderCompiler compiler; + bool emulate_point_size = false; RID default_shader; RID default_material; diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp index ee12788ac7c5..f459dd4a69be 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -2393,6 +2393,7 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr pipeline_key.wireframe = p_params->force_wireframe; pipeline_key.render_pass = p_params->subpass; pipeline_key.ubershader = 0; + pipeline_key.emulate_point_size = shader->uses_point_size && scene_shader.emulate_point_size; const RD::PolygonCullMode cull_mode = shader->get_cull_mode_from_cull_variant(cull_variant); RD::VertexFormatID vertex_format = -1; @@ -2405,9 +2406,9 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr // Skeleton and blend shape. uint64_t input_mask = shader->get_vertex_input_mask(pipeline_key.version, pipeline_key.ubershader); if (surf->owner->mesh_instance.is_valid()) { - mesh_storage->mesh_instance_surface_get_vertex_arrays_and_format(surf->owner->mesh_instance, surf->surface_index, input_mask, p_pass_mode == PASS_MODE_MOTION_VECTORS, vertex_array_rd, vertex_format); + mesh_storage->mesh_instance_surface_get_vertex_arrays_and_format(surf->owner->mesh_instance, surf->surface_index, input_mask, p_pass_mode == PASS_MODE_MOTION_VECTORS, pipeline_key.emulate_point_size, vertex_array_rd, vertex_format); } else { - mesh_storage->mesh_surface_get_vertex_arrays_and_format(mesh_surface, input_mask, p_pass_mode == PASS_MODE_MOTION_VECTORS, vertex_array_rd, vertex_format); + mesh_storage->mesh_surface_get_vertex_arrays_and_format(mesh_surface, input_mask, p_pass_mode == PASS_MODE_MOTION_VECTORS, pipeline_key.emulate_point_size, vertex_array_rd, vertex_format); } pipeline_key.vertex_format_id = vertex_format; @@ -2442,7 +2443,11 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr } if (pipeline_valid) { - index_array_rd = mesh_storage->mesh_surface_get_index_array(mesh_surface, element_info.lod_index); + if (!pipeline_key.emulate_point_size) { + index_array_rd = mesh_storage->mesh_surface_get_index_array(mesh_surface, element_info.lod_index); + } else { + index_array_rd = RID(); + } if (prev_vertex_array_rd != vertex_array_rd) { RD::get_singleton()->draw_list_bind_vertex_array(draw_list, vertex_array_rd); @@ -2500,7 +2505,14 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr instance_count /= surf->owner->trail_steps; } - if (bool(surf->owner->base_flags & INSTANCE_DATA_FLAG_MULTIMESH_INDIRECT)) { + bool indirect = bool(surf->owner->base_flags & INSTANCE_DATA_FLAG_MULTIMESH_INDIRECT); + + if (pipeline_key.emulate_point_size) { + if (indirect) { + WARN_PRINT("Indirect draws are not supported when emulating point size."); + } + RD::get_singleton()->draw_list_draw(draw_list, false, mesh_storage->mesh_surface_get_vertex_count(mesh_surface), instance_count * 6); + } else if (indirect) { RD::get_singleton()->draw_list_draw_indirect(draw_list, index_array_rd.is_valid(), mesh_storage->_multimesh_get_command_buffer_rd_rid(surf->owner->data->base), surf->surface_index * sizeof(uint32_t) * mesh_storage->INDIRECT_MULTIMESH_COMMAND_STRIDE, 1, 0); } else { RD::get_singleton()->draw_list_draw(draw_list, index_array_rd.is_valid(), instance_count); @@ -3132,7 +3144,7 @@ static RD::FramebufferFormatID _get_shadow_atlas_framebuffer_format_for_pipeline void RenderForwardMobile::_mesh_compile_pipeline_for_surface(SceneShaderForwardMobile::ShaderData *p_shader, void *p_mesh_surface, bool p_instanced_surface, RS::PipelineSource p_source, SceneShaderForwardMobile::ShaderData::PipelineKey &r_pipeline_key, Vector *r_pipeline_pairs) { RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton(); uint64_t input_mask = p_shader->get_vertex_input_mask(r_pipeline_key.version, true); - r_pipeline_key.vertex_format_id = mesh_storage->mesh_surface_get_vertex_format(p_mesh_surface, input_mask, p_instanced_surface, false); + r_pipeline_key.vertex_format_id = mesh_storage->mesh_surface_get_vertex_format(p_mesh_surface, input_mask, p_instanced_surface, false, r_pipeline_key.emulate_point_size); r_pipeline_key.ubershader = true; p_shader->pipeline_hash_map.compile_pipeline(r_pipeline_key, r_pipeline_key.hash(), p_source, r_pipeline_key.ubershader); @@ -3149,6 +3161,7 @@ void RenderForwardMobile::_mesh_compile_pipelines_for_surface(const SurfacePipel pipeline_key.cull_mode = RD::POLYGON_CULL_DISABLED; pipeline_key.primitive_type = mesh_storage->mesh_surface_get_primitive(p_surface.mesh_surface); pipeline_key.wireframe = false; + pipeline_key.emulate_point_size = p_surface.shader->uses_point_size && scene_shader.emulate_point_size; const bool multiview_enabled = p_global.use_multiview && scene_shader.is_multiview_shader_group_enabled(); const bool buffers_can_be_storage = _render_buffers_can_be_storage(); @@ -3200,6 +3213,8 @@ void RenderForwardMobile::_mesh_compile_pipelines_for_surface(const SurfacePipel return; } + pipeline_key.emulate_point_size = p_surface.shader_shadow->uses_point_size && scene_shader.emulate_point_size; + if (p_global.use_shadow_cubemaps) { pipeline_key.version = SceneShaderForwardMobile::SHADER_VERSION_SHADOW_PASS; pipeline_key.framebuffer_format_id = _get_shadow_cubemap_framebuffer_format_for_pipeline(); diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp index bb1faa199884..c5b3743961ef 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp @@ -366,7 +366,12 @@ void SceneShaderForwardMobile::ShaderData::_create_pipeline(PipelineKey p_pipeli depth_stencil_state.back_op = op; } - RD::RenderPrimitive primitive_rd = uses_point_size ? RD::RENDER_PRIMITIVE_POINTS : primitive_rd_table[p_pipeline_key.primitive_type]; + RD::RenderPrimitive primitive_rd; + if (uses_point_size) { + primitive_rd = p_pipeline_key.emulate_point_size ? RD::RENDER_PRIMITIVE_TRIANGLES : RD::RENDER_PRIMITIVE_POINTS; + } else { + primitive_rd = primitive_rd_table[p_pipeline_key.primitive_type]; + } RD::PipelineRasterizationState raster_state; raster_state.cull_mode = p_pipeline_key.cull_mode; @@ -430,6 +435,12 @@ void SceneShaderForwardMobile::ShaderData::_create_pipeline(PipelineKey p_pipeli sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_FLOAT; specialization_constants.push_back(sc); + sc = {}; // Sanitize value bits. "bool_value" only assigns 8 bits and keeps the remaining bits intact. + sc.constant_id = 3; + sc.bool_value = p_pipeline_key.emulate_point_size; + sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL; + specialization_constants.push_back(sc); + RID shader_rid = get_shader_variant(p_pipeline_key.version, p_pipeline_key.ubershader); ERR_FAIL_COND(shader_rid.is_null()); @@ -559,6 +570,8 @@ void SceneShaderForwardMobile::init(const String p_defines) { // Store whether the shader will prefer using the FP16 variant. use_fp16 = RD::get_singleton()->has_feature(RD::SUPPORTS_HALF_FLOAT); + emulate_point_size = !RD::get_singleton()->has_feature(RD::SUPPORTS_POINT_SIZE); + // Immutable samplers : create the shadow sampler to be passed when creating the pipeline. { RD::SamplerState sampler; @@ -636,9 +649,9 @@ void SceneShaderForwardMobile::init(const String p_defines) { actions.renames["UV"] = "uv_interp"; actions.renames["UV2"] = "uv2_interp"; actions.renames["COLOR"] = "color_highp"; - actions.renames["POINT_SIZE"] = "gl_PointSize"; - actions.renames["INSTANCE_ID"] = "gl_InstanceIndex"; - actions.renames["VERTEX_ID"] = "gl_VertexIndex"; + actions.renames["POINT_SIZE"] = "point_size"; + actions.renames["INSTANCE_ID"] = "INSTANCE_INDEX"; + actions.renames["VERTEX_ID"] = "VERTEX_INDEX"; actions.renames["Z_CLIP_SCALE"] = "z_clip_scale"; actions.renames["ALPHA_SCISSOR_THRESHOLD"] = "alpha_scissor_threshold_highp"; @@ -683,7 +696,7 @@ void SceneShaderForwardMobile::init(const String p_defines) { actions.renames["AO"] = "ao_highp"; actions.renames["AO_LIGHT_AFFECT"] = "ao_light_affect_highp"; actions.renames["EMISSION"] = "emission_highp"; - actions.renames["POINT_COORD"] = "gl_PointCoord"; + actions.renames["POINT_COORD"] = "point_coord"; actions.renames["INSTANCE_CUSTOM"] = "instance_custom"; actions.renames["SCREEN_UV"] = "screen_uv"; actions.renames["DEPTH"] = "gl_FragDepth"; @@ -764,6 +777,9 @@ void SceneShaderForwardMobile::init(const String p_defines) { actions.usage_defines["MODEL_MATRIX"] = "#define MODEL_MATRIX_USED\n"; + actions.usage_defines["POINT_SIZE"] = "#define POINT_SIZE_USED\n"; + actions.usage_defines["POINT_COORD"] = "#define POINT_COORD_USED\n"; + actions.render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n"; actions.render_mode_defines["world_vertex_coords"] = "#define VERTEX_WORLD_COORDS_USED\n"; actions.render_mode_defines["ensure_correct_normals"] = "#define ENSURE_CORRECT_NORMALS\n"; diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h index 6fc033d43370..4b67e68c5589 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h @@ -201,6 +201,7 @@ class SceneShaderForwardMobile { uint32_t render_pass = 0; uint32_t wireframe = false; uint32_t ubershader = false; + bool emulate_point_size = false; uint32_t hash() const { uint32_t h = hash_murmur3_one_32(vertex_format_id); @@ -214,6 +215,7 @@ class SceneShaderForwardMobile { h = hash_murmur3_one_32(render_pass, h); h = hash_murmur3_one_32(wireframe, h); h = hash_murmur3_one_32(ubershader, h); + h = hash_murmur3_one_32(emulate_point_size, h); return hash_fmix32(h); } }; @@ -345,6 +347,7 @@ class SceneShaderForwardMobile { SceneForwardMobileShaderRD shader; ShaderCompiler compiler; bool use_fp16 = false; + bool emulate_point_size = false; RID default_shader; RID default_material; diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index cecc4db07d3f..78cb7f90ba0e 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -477,9 +477,9 @@ RID RendererCanvasRenderRD::_get_pipeline_specialization_or_ubershader(CanvasSha RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton(); uint64_t input_mask = p_shader_data->get_vertex_input_mask(r_pipeline_key.variant, r_pipeline_key.ubershader); if (p_mesh_instance.is_valid()) { - mesh_storage->mesh_instance_surface_get_vertex_arrays_and_format(p_mesh_instance, p_surface_index, input_mask, false, *r_vertex_array, r_pipeline_key.vertex_format_id); + mesh_storage->mesh_instance_surface_get_vertex_arrays_and_format(p_mesh_instance, p_surface_index, input_mask, false, false, *r_vertex_array, r_pipeline_key.vertex_format_id); } else { - mesh_storage->mesh_surface_get_vertex_arrays_and_format(p_surface, input_mask, false, *r_vertex_array, r_pipeline_key.vertex_format_id); + mesh_storage->mesh_surface_get_vertex_arrays_and_format(p_surface, input_mask, false, false, *r_vertex_array, r_pipeline_key.vertex_format_id); } } diff --git a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl index b4a1f6347e91..7f456eeef7bc 100644 --- a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl @@ -178,6 +178,11 @@ uint cluster_get_range_clip_mask(uint i, uint z_min, uint z_max) { return bitfieldInsert(uint(0), uint(0xFFFFFFFF), local_min, mask_width); } #endif // !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) && defined(USE_VERTEX_LIGHTING) + +#if defined(POINT_SIZE_USED) && defined(POINT_COORD_USED) +layout(location = 14) out vec2 point_coord_interp; +#endif + invariant gl_Position; #GLOBALS @@ -265,7 +270,7 @@ void vertex_shader(vec3 vertex_input, uint trail_size = (instances.data[instance_index].flags >> INSTANCE_FLAGS_PARTICLE_TRAIL_SHIFT) & INSTANCE_FLAGS_PARTICLE_TRAIL_MASK; uint stride = 3 + 1 + 1; //particles always uses this format - uint offset = trail_size * stride * gl_InstanceIndex; + uint offset = trail_size * stride * INSTANCE_INDEX; #ifdef COLOR_USED vec4 pcolor; @@ -307,7 +312,7 @@ void vertex_shader(vec3 vertex_input, #else uint stride = multimesh_stride(); - uint offset = stride * (gl_InstanceIndex + multimesh_offset); + uint offset = stride * (INSTANCE_INDEX + multimesh_offset); if (sc_multimesh_format_2d()) { matrix = mat4(transforms.data[offset + 0], transforms.data[offset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0)); @@ -438,6 +443,10 @@ void vertex_shader(vec3 vertex_input, mat3 modelview_normal = mat3(read_view_matrix) * model_normal_matrix; vec2 read_viewport_size = scene_data.viewport_size; +#ifdef POINT_SIZE_USED + float point_size = 1.0; +#endif + { #CODE : VERTEX } @@ -695,6 +704,27 @@ void vertex_shader(vec3 vertex_input, gl_Position.z = mix(gl_Position.w, gl_Position.z, z_clip_scale); } #endif + +#ifdef POINT_SIZE_USED + if (sc_emulate_point_size) { + vec2 point_coords[6] = vec2[]( + vec2(0, 1), + vec2(0, 0), + vec2(1, 1), + vec2(0, 0), + vec2(1, 0), + vec2(1, 1)); + + vec2 point_coord = point_coords[gl_VertexIndex % 6]; + gl_Position.xy += (point_coord * 2.0 - 1.0) * point_size * scene_data.screen_pixel_size * gl_Position.w; + +#ifdef POINT_COORD_USED + point_coord_interp = point_coord; +#endif + } else { + gl_PointSize = point_size; + } +#endif } void _unpack_vertex_attributes(vec4 p_vertex_in, vec3 p_compressed_aabb_position, vec3 p_compressed_aabb_size, @@ -740,7 +770,7 @@ void _unpack_vertex_attributes(vec4 p_vertex_in, vec3 p_compressed_aabb_position void main() { uint instance_index = draw_call.instance_index; if (!sc_multimesh()) { - instance_index += gl_InstanceIndex; + instance_index += INSTANCE_INDEX; } instance_index_interp = instance_index; @@ -967,6 +997,11 @@ ivec2 multiview_uv(ivec2 uv) { layout(location = 12) in vec4 diffuse_light_interp; layout(location = 13) in vec4 specular_light_interp; #endif + +#if defined(POINT_SIZE_USED) && defined(POINT_COORD_USED) +layout(location = 14) in vec2 point_coord_interp; +#endif + //defines to keep compatibility with vertex #ifdef USE_MULTIVIEW @@ -1291,6 +1326,19 @@ void fragment_shader(in SceneData scene_data) { vec4(0.0, 0.0, 0.0, 1.0))); vec2 read_viewport_size = scene_data.viewport_size; +#ifdef POINT_COORD_USED +#ifdef POINT_SIZE_USED + vec2 point_coord; + if (sc_emulate_point_size) { + point_coord = point_coord_interp; + } else { + point_coord = gl_PointCoord; + } +#else // !POINT_SIZE_USED + vec2 point_coord = vec2(0.5); +#endif +#endif + { #CODE : FRAGMENT } diff --git a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl index dac841ba0b89..d1eddfac71ef 100644 --- a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl @@ -142,6 +142,20 @@ float sc_luminance_multiplier() { return 1.0; } +layout(constant_id = 2) const bool sc_emulate_point_size = false; + +#ifdef POINT_SIZE_USED + +#define VERTEX_INDEX (sc_emulate_point_size ? gl_InstanceIndex : gl_VertexIndex) +#define INSTANCE_INDEX (sc_emulate_point_size ? (gl_VertexIndex / 6) : gl_InstanceIndex) + +#else + +#define VERTEX_INDEX gl_VertexIndex +#define INSTANCE_INDEX gl_InstanceIndex + +#endif + #define REFLECTION_MULTIPLIER 1.0 #define SDFGI_MAX_CASCADES 8 diff --git a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl index b9f1018ccdb3..43277ba30413 100644 --- a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl @@ -163,6 +163,10 @@ ivec2 multiview_uv(ivec2 uv) { } #endif // !USE_MULTIVIEW +#if defined(POINT_SIZE_USED) && defined(POINT_COORD_USED) +layout(location = 14) out vec2 point_coord_interp; +#endif + invariant gl_Position; #GLOBALS @@ -305,7 +309,7 @@ void vertex_shader(in vec3 vertex, uint trail_size = (instances.data[instance_index].flags >> INSTANCE_FLAGS_PARTICLE_TRAIL_SHIFT) & INSTANCE_FLAGS_PARTICLE_TRAIL_MASK; uint stride = 3 + 1 + 1; //particles always uses this format - uint offset = trail_size * stride * gl_InstanceIndex; + uint offset = trail_size * stride * INSTANCE_INDEX; #ifdef COLOR_USED vec4 pcolor; @@ -347,7 +351,7 @@ void vertex_shader(in vec3 vertex, #else uint stride = multimesh_stride(); - uint offset = stride * (gl_InstanceIndex + multimesh_offset); + uint offset = stride * (INSTANCE_INDEX + multimesh_offset); if (sc_multimesh_format_2d()) { matrix = mat4(transforms.data[offset + 0], transforms.data[offset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0)); @@ -464,6 +468,10 @@ void vertex_shader(in vec3 vertex, mat3 modelview_normal = mat3(read_view_matrix) * model_normal_matrix; vec2 read_viewport_size = scene_data.viewport_size; +#ifdef POINT_SIZE_USED + float point_size = 1.0; +#endif + { #CODE : VERTEX } @@ -665,6 +673,27 @@ void vertex_shader(in vec3 vertex, #ifdef MODE_RENDER_MOTION_VECTORS screen_position_output = gl_Position; #endif // MODE_RENDER_MOTION_VECTORS + +#ifdef POINT_SIZE_USED + if (sc_emulate_point_size) { + vec2 point_coords[6] = vec2[]( + vec2(0, 1), + vec2(0, 0), + vec2(1, 1), + vec2(0, 0), + vec2(1, 0), + vec2(1, 1)); + + vec2 point_coord = point_coords[gl_VertexIndex % 6]; + gl_Position.xy += (point_coord * 2.0 - 1.0) * point_size * scene_data.screen_pixel_size * gl_Position.w; + +#ifdef POINT_COORD_USED + point_coord_interp = point_coord; +#endif + } else { + gl_PointSize = point_size; + } +#endif } void main() { @@ -934,6 +963,10 @@ ivec2 multiview_uv(ivec2 uv) { } #endif // !USE_MULTIVIEW +#if defined(POINT_SIZE_USED) && defined(POINT_COORD_USED) +layout(location = 14) in vec2 point_coord_interp; +#endif + //defines to keep compatibility with vertex #ifdef USE_MULTIVIEW @@ -1211,6 +1244,19 @@ void main() { vec4(0.0, 0.0, 0.0, 1.0))); vec2 read_viewport_size = scene_data.viewport_size; +#ifdef POINT_COORD_USED +#ifdef POINT_SIZE_USED + vec2 point_coord; + if (sc_emulate_point_size) { + point_coord = point_coord_interp; + } else { + point_coord = gl_PointCoord; + } +#else // !POINT_SIZE_USED + vec2 point_coord = vec2(0.5); +#endif +#endif + { #CODE : FRAGMENT } diff --git a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl index a96921e68c9a..a2eeb3392919 100644 --- a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl @@ -215,6 +215,20 @@ half sc_luminance_multiplier() { return half(sc_packed_2()); } +layout(constant_id = 3) const bool sc_emulate_point_size = false; + +#ifdef POINT_SIZE_USED + +#define VERTEX_INDEX (sc_emulate_point_size ? gl_InstanceIndex : gl_VertexIndex) +#define INSTANCE_INDEX (sc_emulate_point_size ? (gl_VertexIndex / 6) : gl_InstanceIndex) + +#else + +#define VERTEX_INDEX gl_VertexIndex +#define INSTANCE_INDEX gl_InstanceIndex + +#endif + // Like the luminance multiplier, but it is only for sky and reflection probes // since they are always LDR. #define REFLECTION_MULTIPLIER half(2.0) diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp index 5c479d8bed5f..189262f4e226 100644 --- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp @@ -1259,7 +1259,7 @@ void MeshStorage::update_mesh_instances() { RD::get_singleton()->compute_list_end(); } -RD::VertexFormatID MeshStorage::_mesh_surface_generate_vertex_format(uint64_t p_surface_format, uint64_t p_input_mask, bool p_instanced_surface, bool p_input_motion_vectors, uint32_t &r_position_stride) { +RD::VertexFormatID MeshStorage::_mesh_surface_generate_vertex_format(uint64_t p_surface_format, uint64_t p_input_mask, bool p_instanced_surface, bool p_input_motion_vectors, bool p_point_size_emulated, uint32_t &r_position_stride) { Vector attributes; uint32_t normal_tangent_stride = 0; uint32_t attribute_stride = 0; @@ -1396,6 +1396,10 @@ RD::VertexFormatID MeshStorage::_mesh_surface_generate_vertex_format(uint64_t p_ skin_stride += sizeof(int16_t) * 4; } break; } + + if (p_point_size_emulated) { + vd.frequency = RD::VERTEX_FREQUENCY_INSTANCE; + } } if (!(p_input_mask & (1ULL << i))) { @@ -1447,9 +1451,9 @@ RD::VertexFormatID MeshStorage::_mesh_surface_generate_vertex_format(uint64_t p_ return RD::get_singleton()->vertex_format_create(attributes); } -void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::Version &v, Mesh::Surface *s, uint64_t p_input_mask, bool p_input_motion_vectors, MeshInstance::Surface *mis, uint32_t p_current_buffer, uint32_t p_previous_buffer) { +void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::Version &v, Mesh::Surface *s, uint64_t p_input_mask, bool p_input_motion_vectors, bool p_point_size_emulated, MeshInstance::Surface *mis, uint32_t p_current_buffer, uint32_t p_previous_buffer) { uint32_t position_stride = 0; - v.vertex_format = _mesh_surface_generate_vertex_format(s->format, p_input_mask, mis != nullptr, p_input_motion_vectors, position_stride); + v.vertex_format = _mesh_surface_generate_vertex_format(s->format, p_input_mask, mis != nullptr, p_input_motion_vectors, p_point_size_emulated, position_stride); Vector buffers; Vector offsets; @@ -1513,7 +1517,8 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V v.current_buffer = p_current_buffer; v.previous_buffer = p_previous_buffer; v.input_motion_vectors = p_input_motion_vectors; - v.vertex_array = RD::get_singleton()->vertex_array_create(s->vertex_count, v.vertex_format, buffers, offsets); + v.point_size_emulated = p_point_size_emulated; + v.vertex_array = RD::get_singleton()->vertex_array_create(p_point_size_emulated ? 0 : s->vertex_count, v.vertex_format, buffers, offsets); } ////////////////// MULTIMESH diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h index 5640918b5f06..776c8603d662 100644 --- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h @@ -100,6 +100,7 @@ class MeshStorage : public RendererMeshStorage { uint32_t current_buffer = 0; uint32_t previous_buffer = 0; bool input_motion_vectors = false; + bool point_size_emulated = false; RD::VertexFormatID vertex_format = 0; RID vertex_array; }; @@ -208,8 +209,8 @@ class MeshStorage : public RendererMeshStorage { weight_update_list(this), array_update_list(this) {} }; - RD::VertexFormatID _mesh_surface_generate_vertex_format(uint64_t p_surface_format, uint64_t p_input_mask, bool p_instanced_surface, bool p_input_motion_vectors, uint32_t &r_position_stride); - void _mesh_surface_generate_version_for_input_mask(Mesh::Surface::Version &v, Mesh::Surface *s, uint64_t p_input_mask, bool p_input_motion_vectors, MeshInstance::Surface *mis = nullptr, uint32_t p_current_buffer = 0, uint32_t p_previous_buffer = 0); + RD::VertexFormatID _mesh_surface_generate_vertex_format(uint64_t p_surface_format, uint64_t p_input_mask, bool p_instanced_surface, bool p_input_motion_vectors, bool p_point_size_emulated, uint32_t &r_position_stride); + void _mesh_surface_generate_version_for_input_mask(Mesh::Surface::Version &v, Mesh::Surface *s, uint64_t p_input_mask, bool p_input_motion_vectors, bool p_point_size_emulated, MeshInstance::Surface *mis = nullptr, uint32_t p_current_buffer = 0, uint32_t p_previous_buffer = 0); void _mesh_surface_clear(Mesh *p_mesh, int p_surface); void _mesh_instance_clear(MeshInstance *mi); @@ -445,6 +446,11 @@ class MeshStorage : public RendererMeshStorage { return surface->primitive; } + _FORCE_INLINE_ uint32_t mesh_surface_get_vertex_count(void *p_surface) { + Mesh::Surface *surface = reinterpret_cast(p_surface); + return surface->vertex_count; + } + _FORCE_INLINE_ bool mesh_surface_has_lod(void *p_surface) const { Mesh::Surface *s = reinterpret_cast(p_surface); return s->lod_count > 0; @@ -500,7 +506,7 @@ class MeshStorage : public RendererMeshStorage { } } - _FORCE_INLINE_ void mesh_surface_get_vertex_arrays_and_format(void *p_surface, uint64_t p_input_mask, bool p_input_motion_vectors, RID &r_vertex_array_rd, RD::VertexFormatID &r_vertex_format) { + _FORCE_INLINE_ void mesh_surface_get_vertex_arrays_and_format(void *p_surface, uint64_t p_input_mask, bool p_input_motion_vectors, bool p_point_size_emulated, RID &r_vertex_array_rd, RD::VertexFormatID &r_vertex_format) { Mesh::Surface *s = reinterpret_cast(p_surface); s->version_lock.lock(); @@ -508,7 +514,7 @@ class MeshStorage : public RendererMeshStorage { //there will never be more than, at much, 3 or 4 versions, so iterating is the fastest way for (uint32_t i = 0; i < s->version_count; i++) { - if (s->versions[i].input_mask != p_input_mask || s->versions[i].input_motion_vectors != p_input_motion_vectors) { + if (s->versions[i].input_mask != p_input_mask || s->versions[i].input_motion_vectors != p_input_motion_vectors || s->versions[i].point_size_emulated != p_point_size_emulated) { // Find the version that matches the inputs required. continue; } @@ -524,7 +530,7 @@ class MeshStorage : public RendererMeshStorage { s->version_count++; s->versions = (Mesh::Surface::Version *)memrealloc(s->versions, sizeof(Mesh::Surface::Version) * s->version_count); - _mesh_surface_generate_version_for_input_mask(s->versions[version], s, p_input_mask, p_input_motion_vectors); + _mesh_surface_generate_version_for_input_mask(s->versions[version], s, p_input_mask, p_input_motion_vectors, p_point_size_emulated); r_vertex_format = s->versions[version].vertex_format; r_vertex_array_rd = s->versions[version].vertex_array; @@ -532,7 +538,7 @@ class MeshStorage : public RendererMeshStorage { s->version_lock.unlock(); } - _FORCE_INLINE_ void mesh_instance_surface_get_vertex_arrays_and_format(RID p_mesh_instance, uint64_t p_surface_index, uint64_t p_input_mask, bool p_input_motion_vectors, RID &r_vertex_array_rd, RD::VertexFormatID &r_vertex_format) { + _FORCE_INLINE_ void mesh_instance_surface_get_vertex_arrays_and_format(RID p_mesh_instance, uint64_t p_surface_index, uint64_t p_input_mask, bool p_input_motion_vectors, bool p_point_size_emulated, RID &r_vertex_array_rd, RD::VertexFormatID &r_vertex_format) { MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance); ERR_FAIL_NULL(mi); Mesh *mesh = mi->mesh; @@ -571,7 +577,7 @@ class MeshStorage : public RendererMeshStorage { mis->version_count++; mis->versions = (Mesh::Surface::Version *)memrealloc(mis->versions, sizeof(Mesh::Surface::Version) * mis->version_count); - _mesh_surface_generate_version_for_input_mask(mis->versions[version], s, p_input_mask, p_input_motion_vectors, mis, current_buffer, previous_buffer); + _mesh_surface_generate_version_for_input_mask(mis->versions[version], s, p_input_mask, p_input_motion_vectors, p_point_size_emulated, mis, current_buffer, previous_buffer); r_vertex_format = mis->versions[version].vertex_format; r_vertex_array_rd = mis->versions[version].vertex_array; @@ -623,10 +629,10 @@ class MeshStorage : public RendererMeshStorage { return s->particles_render_index; } - _FORCE_INLINE_ RD::VertexFormatID mesh_surface_get_vertex_format(void *p_surface, uint64_t p_input_mask, bool p_instanced_surface, bool p_input_motion_vectors) { + _FORCE_INLINE_ RD::VertexFormatID mesh_surface_get_vertex_format(void *p_surface, uint64_t p_input_mask, bool p_instanced_surface, bool p_input_motion_vectors, bool p_point_size_emulated) { Mesh::Surface *s = reinterpret_cast(p_surface); uint32_t position_stride = 0; - return _mesh_surface_generate_vertex_format(s->format, p_input_mask, p_instanced_surface, p_input_motion_vectors, position_stride); + return _mesh_surface_generate_vertex_format(s->format, p_input_mask, p_instanced_surface, p_input_motion_vectors, p_point_size_emulated, position_stride); } Dependency *mesh_get_dependency(RID p_mesh) const; diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp index 6a3646e4beda..8e4d0ec05743 100644 --- a/servers/rendering/rendering_device.cpp +++ b/servers/rendering/rendering_device.cpp @@ -4855,10 +4855,6 @@ void RenderingDevice::draw_list_draw(DrawListID p_list, bool p_use_indices, uint uint32_t to_draw; if (p_procedural_vertices > 0) { -#ifdef DEBUG_ENABLED - ERR_FAIL_COND_MSG(draw_list.validation.pipeline_vertex_format != INVALID_ID, - "Procedural vertices requested, but pipeline expects a vertex array."); -#endif to_draw = p_procedural_vertices; } else { #ifdef DEBUG_ENABLED diff --git a/servers/rendering/rendering_device_commons.h b/servers/rendering/rendering_device_commons.h index e51566453a40..0f775b0e81bc 100644 --- a/servers/rendering/rendering_device_commons.h +++ b/servers/rendering/rendering_device_commons.h @@ -957,6 +957,7 @@ class RenderingDeviceCommons : public Object { SUPPORTS_BUFFER_DEVICE_ADDRESS, SUPPORTS_IMAGE_ATOMIC_32_BIT, SUPPORTS_VULKAN_MEMORY_MODEL, + SUPPORTS_POINT_SIZE, }; enum SubgroupOperations {