diff options
Diffstat (limited to 'servers')
24 files changed, 780 insertions, 328 deletions
diff --git a/servers/audio/audio_driver_dummy.cpp b/servers/audio/audio_driver_dummy.cpp index a28dcb1015..47799dce96 100644 --- a/servers/audio/audio_driver_dummy.cpp +++ b/servers/audio/audio_driver_dummy.cpp @@ -46,7 +46,7 @@ Error AudioDriverDummy::init() { int latency = GLOBAL_GET("audio/driver/output_latency"); buffer_frames = closest_power_of_2(latency * mix_rate / 1000); - samples_in = memnew_arr(int32_t, buffer_frames * channels); + samples_in = memnew_arr(int32_t, (size_t)buffer_frames * channels); thread.start(AudioDriverDummy::thread_func, this); diff --git a/servers/audio/audio_rb_resampler.cpp b/servers/audio/audio_rb_resampler.cpp index 3c8a1469cd..d9c442facf 100644 --- a/servers/audio/audio_rb_resampler.cpp +++ b/servers/audio/audio_rb_resampler.cpp @@ -176,8 +176,9 @@ Error AudioRBResampler::setup(int p_channels, int p_src_mix_rate, int p_target_m rb_bits = desired_rb_bits; rb_len = (1 << rb_bits); rb_mask = rb_len - 1; - rb = memnew_arr(float, rb_len *p_channels); - read_buf = memnew_arr(float, rb_len *p_channels); + const size_t array_size = rb_len * (size_t)p_channels; + rb = memnew_arr(float, array_size); + read_buf = memnew_arr(float, array_size); } src_mix_rate = p_src_mix_rate; diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp index ac1569c15d..a420134626 100644 --- a/servers/audio_server.cpp +++ b/servers/audio_server.cpp @@ -1112,16 +1112,16 @@ float AudioServer::get_playback_speed_scale() const { return playback_speed_scale; } -void AudioServer::start_playback_stream(Ref<AudioStreamPlayback> p_playback, StringName p_bus, Vector<AudioFrame> p_volume_db_vector, float p_start_time) { +void AudioServer::start_playback_stream(Ref<AudioStreamPlayback> p_playback, StringName p_bus, Vector<AudioFrame> p_volume_db_vector, float p_start_time, float p_pitch_scale) { ERR_FAIL_COND(p_playback.is_null()); Map<StringName, Vector<AudioFrame>> map; map[p_bus] = p_volume_db_vector; - start_playback_stream(p_playback, map, p_start_time); + start_playback_stream(p_playback, map, p_start_time, p_pitch_scale); } -void AudioServer::start_playback_stream(Ref<AudioStreamPlayback> p_playback, Map<StringName, Vector<AudioFrame>> p_bus_volumes, float p_start_time, float p_highshelf_gain, float p_attenuation_cutoff_hz, float p_pitch_scale) { +void AudioServer::start_playback_stream(Ref<AudioStreamPlayback> p_playback, Map<StringName, Vector<AudioFrame>> p_bus_volumes, float p_start_time, float p_pitch_scale, float p_highshelf_gain, float p_attenuation_cutoff_hz) { ERR_FAIL_COND(p_playback.is_null()); AudioStreamPlaybackListNode *playback_node = new AudioStreamPlaybackListNode(); diff --git a/servers/audio_server.h b/servers/audio_server.h index a60d4ae4c4..46873845dc 100644 --- a/servers/audio_server.h +++ b/servers/audio_server.h @@ -368,9 +368,9 @@ public: float get_playback_speed_scale() const; // Convenience method. - void start_playback_stream(Ref<AudioStreamPlayback> p_playback, StringName p_bus, Vector<AudioFrame> p_volume_db_vector, float p_start_time = 0); + void start_playback_stream(Ref<AudioStreamPlayback> p_playback, StringName p_bus, Vector<AudioFrame> p_volume_db_vector, float p_start_time = 0, float p_pitch_scale = 1); // Expose all parameters. - void start_playback_stream(Ref<AudioStreamPlayback> p_playback, Map<StringName, Vector<AudioFrame>> p_bus_volumes, float p_start_time = 0, float p_highshelf_gain = 0, float p_attenuation_cutoff_hz = 0, float p_pitch_scale = 1); + void start_playback_stream(Ref<AudioStreamPlayback> p_playback, Map<StringName, Vector<AudioFrame>> p_bus_volumes, float p_start_time = 0, float p_pitch_scale = 1, float p_highshelf_gain = 0, float p_attenuation_cutoff_hz = 0); void stop_playback_stream(Ref<AudioStreamPlayback> p_playback); void set_playback_bus_exclusive(Ref<AudioStreamPlayback> p_playback, StringName p_bus, Vector<AudioFrame> p_volumes); diff --git a/servers/physics_server_2d.cpp b/servers/physics_server_2d.cpp index fe2970912a..a6cb7dbdd9 100644 --- a/servers/physics_server_2d.cpp +++ b/servers/physics_server_2d.cpp @@ -452,22 +452,22 @@ void PhysicsTestMotionParameters2D::set_exclude_objects(const Array &p_exclude) void PhysicsTestMotionParameters2D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_from"), &PhysicsTestMotionParameters2D::get_from); - ClassDB::bind_method(D_METHOD("set_from"), &PhysicsTestMotionParameters2D::set_from); + ClassDB::bind_method(D_METHOD("set_from", "from"), &PhysicsTestMotionParameters2D::set_from); ClassDB::bind_method(D_METHOD("get_motion"), &PhysicsTestMotionParameters2D::get_motion); - ClassDB::bind_method(D_METHOD("set_motion"), &PhysicsTestMotionParameters2D::set_motion); + ClassDB::bind_method(D_METHOD("set_motion", "motion"), &PhysicsTestMotionParameters2D::set_motion); ClassDB::bind_method(D_METHOD("get_margin"), &PhysicsTestMotionParameters2D::get_margin); - ClassDB::bind_method(D_METHOD("set_margin"), &PhysicsTestMotionParameters2D::set_margin); + ClassDB::bind_method(D_METHOD("set_margin", "margin"), &PhysicsTestMotionParameters2D::set_margin); ClassDB::bind_method(D_METHOD("is_collide_separation_ray_enabled"), &PhysicsTestMotionParameters2D::is_collide_separation_ray_enabled); - ClassDB::bind_method(D_METHOD("set_collide_separation_ray_enabled"), &PhysicsTestMotionParameters2D::set_collide_separation_ray_enabled); + ClassDB::bind_method(D_METHOD("set_collide_separation_ray_enabled", "enabled"), &PhysicsTestMotionParameters2D::set_collide_separation_ray_enabled); ClassDB::bind_method(D_METHOD("get_exclude_bodies"), &PhysicsTestMotionParameters2D::get_exclude_bodies); - ClassDB::bind_method(D_METHOD("set_exclude_bodies"), &PhysicsTestMotionParameters2D::set_exclude_bodies); + ClassDB::bind_method(D_METHOD("set_exclude_bodies", "exclude_list"), &PhysicsTestMotionParameters2D::set_exclude_bodies); ClassDB::bind_method(D_METHOD("get_exclude_objects"), &PhysicsTestMotionParameters2D::get_exclude_objects); - ClassDB::bind_method(D_METHOD("set_exclude_objects"), &PhysicsTestMotionParameters2D::set_exclude_objects); + ClassDB::bind_method(D_METHOD("set_exclude_objects", "exclude_list"), &PhysicsTestMotionParameters2D::set_exclude_objects); ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "from"), "set_from", "get_from"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "motion"), "set_motion", "get_motion"); diff --git a/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp index d66a8bfe0d..90922cc250 100644 --- a/servers/physics_server_3d.cpp +++ b/servers/physics_server_3d.cpp @@ -402,25 +402,25 @@ void PhysicsTestMotionParameters3D::set_exclude_objects(const Array &p_exclude) void PhysicsTestMotionParameters3D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_from"), &PhysicsTestMotionParameters3D::get_from); - ClassDB::bind_method(D_METHOD("set_from"), &PhysicsTestMotionParameters3D::set_from); + ClassDB::bind_method(D_METHOD("set_from", "from"), &PhysicsTestMotionParameters3D::set_from); ClassDB::bind_method(D_METHOD("get_motion"), &PhysicsTestMotionParameters3D::get_motion); - ClassDB::bind_method(D_METHOD("set_motion"), &PhysicsTestMotionParameters3D::set_motion); + ClassDB::bind_method(D_METHOD("set_motion", "motion"), &PhysicsTestMotionParameters3D::set_motion); ClassDB::bind_method(D_METHOD("get_margin"), &PhysicsTestMotionParameters3D::get_margin); - ClassDB::bind_method(D_METHOD("set_margin"), &PhysicsTestMotionParameters3D::set_margin); + ClassDB::bind_method(D_METHOD("set_margin", "margin"), &PhysicsTestMotionParameters3D::set_margin); ClassDB::bind_method(D_METHOD("get_max_collisions"), &PhysicsTestMotionParameters3D::get_max_collisions); - ClassDB::bind_method(D_METHOD("set_max_collisions"), &PhysicsTestMotionParameters3D::set_max_collisions); + ClassDB::bind_method(D_METHOD("set_max_collisions", "max_collisions"), &PhysicsTestMotionParameters3D::set_max_collisions); ClassDB::bind_method(D_METHOD("is_collide_separation_ray_enabled"), &PhysicsTestMotionParameters3D::is_collide_separation_ray_enabled); - ClassDB::bind_method(D_METHOD("set_collide_separation_ray_enabled"), &PhysicsTestMotionParameters3D::set_collide_separation_ray_enabled); + ClassDB::bind_method(D_METHOD("set_collide_separation_ray_enabled", "enabled"), &PhysicsTestMotionParameters3D::set_collide_separation_ray_enabled); ClassDB::bind_method(D_METHOD("get_exclude_bodies"), &PhysicsTestMotionParameters3D::get_exclude_bodies); - ClassDB::bind_method(D_METHOD("set_exclude_bodies"), &PhysicsTestMotionParameters3D::set_exclude_bodies); + ClassDB::bind_method(D_METHOD("set_exclude_bodies", "exclude_list"), &PhysicsTestMotionParameters3D::set_exclude_bodies); ClassDB::bind_method(D_METHOD("get_exclude_objects"), &PhysicsTestMotionParameters3D::get_exclude_objects); - ClassDB::bind_method(D_METHOD("set_exclude_objects"), &PhysicsTestMotionParameters3D::set_exclude_objects); + ClassDB::bind_method(D_METHOD("set_exclude_objects", "exclude_list"), &PhysicsTestMotionParameters3D::set_exclude_objects); ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "from"), "set_from", "get_from"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "motion"), "set_motion", "get_motion"); 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 6a3b9726da..85ebf076cc 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -757,9 +757,6 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat scene_state.ubo.fog_density = environment_get_fog_density(p_render_data->environment); scene_state.ubo.fog_height = environment_get_fog_height(p_render_data->environment); scene_state.ubo.fog_height_density = environment_get_fog_height_density(p_render_data->environment); - if (scene_state.ubo.fog_height_density >= 0.0001) { - scene_state.ubo.fog_height_density = 1.0 / scene_state.ubo.fog_height_density; - } scene_state.ubo.fog_aerial_perspective = environment_get_fog_aerial_perspective(p_render_data->environment); Color fog_color = environment_get_fog_light_color(p_render_data->environment).to_linear(); 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 6937df85fb..5d80ae6212 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -1637,9 +1637,6 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data, scene_state.ubo.fog_density = environment_get_fog_density(p_render_data->environment); scene_state.ubo.fog_height = environment_get_fog_height(p_render_data->environment); scene_state.ubo.fog_height_density = environment_get_fog_height_density(p_render_data->environment); - if (scene_state.ubo.fog_height_density >= 0.0001) { - scene_state.ubo.fog_height_density = 1.0 / scene_state.ubo.fog_height_density; - } scene_state.ubo.fog_aerial_perspective = environment_get_fog_aerial_perspective(p_render_data->environment); Color fog_color = environment_get_fog_light_color(p_render_data->environment).to_linear(); diff --git a/servers/rendering/renderer_rd/pipeline_cache_rd.cpp b/servers/rendering/renderer_rd/pipeline_cache_rd.cpp index aefe926cb0..0d60052666 100644 --- a/servers/rendering/renderer_rd/pipeline_cache_rd.cpp +++ b/servers/rendering/renderer_rd/pipeline_cache_rd.cpp @@ -35,8 +35,10 @@ RID PipelineCacheRD::_generate_version(RD::VertexFormatID p_vertex_format_id, RD RD::PipelineMultisampleState multisample_state_version = multisample_state; multisample_state_version.sample_count = RD::get_singleton()->framebuffer_format_get_texture_samples(p_framebuffer_format_id, p_render_pass); + bool wireframe = p_wireframe || rasterization_state.wireframe; + RD::PipelineRasterizationState raster_state_version = rasterization_state; - raster_state_version.wireframe = p_wireframe; + raster_state_version.wireframe = wireframe; Vector<RD::PipelineSpecializationConstant> specialization_constants = base_specialization_constants; @@ -59,7 +61,7 @@ RID PipelineCacheRD::_generate_version(RD::VertexFormatID p_vertex_format_id, RD versions = (Version *)memrealloc(versions, sizeof(Version) * (version_count + 1)); versions[version_count].framebuffer_id = p_framebuffer_format_id; versions[version_count].vertex_id = p_vertex_format_id; - versions[version_count].wireframe = p_wireframe; + versions[version_count].wireframe = wireframe; versions[version_count].pipeline = pipeline; versions[version_count].render_pass = p_render_pass; versions[version_count].bool_specializations = p_bool_specializations; diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp index 45d3b3f09f..a7bfea455d 100644 --- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp @@ -3959,7 +3959,7 @@ void RendererStorageRD::_multimesh_make_local(MultiMesh *multimesh) const { memcpy(w, r, buffer.size()); } } else { - memset(w, 0, multimesh->instances * multimesh->stride_cache * sizeof(float)); + memset(w, 0, (size_t)multimesh->instances * multimesh->stride_cache * sizeof(float)); } } uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; @@ -4372,13 +4372,13 @@ void RendererStorageRD::_update_dirty_multimeshes() { if (multimesh->data_cache_used_dirty_regions > 32 || multimesh->data_cache_used_dirty_regions > visible_region_count / 2) { //if there too many dirty regions, or represent the majority of regions, just copy all, else transfer cost piles up too much - RD::get_singleton()->buffer_update(multimesh->buffer, 0, MIN(visible_region_count * region_size, multimesh->instances * multimesh->stride_cache * sizeof(float)), data); + RD::get_singleton()->buffer_update(multimesh->buffer, 0, MIN(visible_region_count * region_size, multimesh->instances * (uint32_t)multimesh->stride_cache * (uint32_t)sizeof(float)), data); } else { //not that many regions? update them all for (uint32_t i = 0; i < visible_region_count; i++) { if (multimesh->data_cache_dirty_regions[i]) { - uint64_t offset = i * region_size; - uint64_t size = multimesh->stride_cache * multimesh->instances * sizeof(float); + uint32_t offset = i * region_size; + uint32_t size = multimesh->stride_cache * (uint32_t)multimesh->instances * (uint32_t)sizeof(float); RD::get_singleton()->buffer_update(multimesh->buffer, offset, MIN(region_size, size - offset), &data[i * region_size]); } } @@ -9970,6 +9970,6 @@ RendererStorageRD::~RendererStorageRD() { if (effects) { memdelete(effects); - effects = NULL; + effects = nullptr; } } diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.h b/servers/rendering/renderer_rd/renderer_storage_rd.h index d56afcc448..d6129bb57b 100644 --- a/servers/rendering/renderer_rd/renderer_storage_rd.h +++ b/servers/rendering/renderer_rd/renderer_storage_rd.h @@ -1284,7 +1284,7 @@ private: void _update_global_variables(); /* EFFECTS */ - EffectsRD *effects = NULL; + EffectsRD *effects = nullptr; public: virtual bool can_create_resources_async() const; diff --git a/servers/rendering/renderer_rd/shader_compiler_rd.cpp b/servers/rendering/renderer_rd/shader_compiler_rd.cpp index 4c26941dae..42d11d8bc1 100644 --- a/servers/rendering/renderer_rd/shader_compiler_rd.cpp +++ b/servers/rendering/renderer_rd/shader_compiler_rd.cpp @@ -1463,6 +1463,7 @@ void ShaderCompilerRD::initialize(DefaultIdentifierActions p_actions) { texture_functions.insert("textureLod"); texture_functions.insert("textureProjLod"); texture_functions.insert("textureGrad"); + texture_functions.insert("textureGather"); texture_functions.insert("textureSize"); texture_functions.insert("texelFetch"); } diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl index f0fb31a457..5261868155 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl @@ -526,12 +526,12 @@ vec4 fog_process(vec3 vertex) { float fog_amount = 1.0 - exp(min(0.0, -length(vertex) * scene_data.fog_density)); - if (abs(scene_data.fog_height_density) > 0.001) { + if (abs(scene_data.fog_height_density) >= 0.0001) { float y = (scene_data.camera_matrix * vec4(vertex, 1.0)).y; - float y_dist = scene_data.fog_height - y; + float y_dist = y - scene_data.fog_height; - float vfog_amount = clamp(exp(y_dist * scene_data.fog_height_density), 0.0, 1.0); + float vfog_amount = 1.0 - exp(min(0.0, y_dist * scene_data.fog_height_density)); fog_amount = max(vfog_amount, fog_amount); } diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl index f3db4abe3b..4d466342f8 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl @@ -97,6 +97,11 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte #endif inout vec3 diffuse_light, inout vec3 specular_light) { + vec4 orms_unpacked = unpackUnorm4x8(orms); + + float roughness = orms_unpacked.y; + float metallic = orms_unpacked.z; + #if defined(LIGHT_CODE_USED) // light is written by the light shader @@ -125,9 +130,7 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte float cLdotH = clamp(A + dot(L, H), 0.0, 1.0); #endif - float metallic = unpackUnorm4x8(orms).z; if (metallic < 1.0) { - float roughness = unpackUnorm4x8(orms).y; float diffuse_brdf_NL; // BRDF times N.L for calculating diffuse radiance #if defined(DIFFUSE_LAMBERT_WRAP) @@ -199,7 +202,6 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte #endif //LIGHT_TRANSMITTANCE_USED } - float roughness = unpackUnorm4x8(orms).y; if (roughness > 0.0) { // FIXME: roughness == 0 should not disable specular light entirely // D @@ -211,7 +213,7 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte float blinn = pow(cNdotH, shininess); blinn *= (shininess + 2.0) * (1.0 / (8.0 * M_PI)); - specular_light += light_color * attenuation * specular_amount * blinn * f0 * unpackUnorm4x8(orms).w; + specular_light += light_color * attenuation * specular_amount * blinn * f0 * orms_unpacked.w; #elif defined(SPECULAR_PHONG) @@ -221,7 +223,7 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte float phong = pow(cRdotV, shininess); phong *= (shininess + 1.0) * (1.0 / (8.0 * M_PI)); - specular_light += light_color * attenuation * specular_amount * phong * f0 * unpackUnorm4x8(orms).w; + specular_light += light_color * attenuation * specular_amount * phong * f0 * orms_unpacked.w; #elif defined(SPECULAR_TOON) diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl index 750ec5f00a..0ee68d5e10 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl @@ -552,12 +552,12 @@ vec4 fog_process(vec3 vertex) { float fog_amount = 1.0 - exp(min(0.0, -length(vertex) * scene_data.fog_density)); - if (abs(scene_data.fog_height_density) > 0.001) { + if (abs(scene_data.fog_height_density) >= 0.0001) { float y = (scene_data.camera_matrix * vec4(vertex, 1.0)).y; - float y_dist = scene_data.fog_height - y; + float y_dist = y - scene_data.fog_height; - float vfog_amount = clamp(exp(y_dist * scene_data.fog_height_density), 0.0, 1.0); + float vfog_amount = 1.0 - exp(min(0.0, y_dist * scene_data.fog_height_density)); fog_amount = max(vfog_amount, fog_amount); } diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp index 74f18b1da5..b67b1cd806 100644 --- a/servers/rendering/renderer_viewport.cpp +++ b/servers/rendering/renderer_viewport.cpp @@ -77,33 +77,17 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) { RSG::scene->free(p_viewport->render_buffers); p_viewport->render_buffers = RID(); } else { - RS::ViewportScale3D scale_3d = p_viewport->scale_3d; - if (Engine::get_singleton()->is_editor_hint()) { // ignore this inside of the editor - scale_3d = RS::VIEWPORT_SCALE_3D_DISABLED; + float scale_3d = p_viewport->scale_3d; + if (Engine::get_singleton()->is_editor_hint()) { + // Ignore the 3D viewport render scaling inside of the editor. + // The Half Resolution 3D editor viewport option should be used instead. + scale_3d = 1.0; } - int width = p_viewport->size.width; - int height = p_viewport->size.height; - switch (scale_3d) { - case RS::VIEWPORT_SCALE_3D_75_PERCENT: { - width = (width * 3) / 4; - height = (height * 3) / 4; - }; break; - case RS::VIEWPORT_SCALE_3D_50_PERCENT: { - width = width >> 1; - height = height >> 1; - }; break; - case RS::VIEWPORT_SCALE_3D_33_PERCENT: { - width = width / 3; - height = height / 3; - }; break; - case RS::VIEWPORT_SCALE_3D_25_PERCENT: { - width = width >> 2; - height = height >> 2; - }; break; - default: - break; - } + // Clamp 3D rendering resolution to reasonable values supported on most hardware. + // This prevents freezing the engine or outright crashing on lower-end GPUs. + const int width = CLAMP(p_viewport->size.width * scale_3d, 1, 16384); + const int height = CLAMP(p_viewport->size.height * scale_3d, 1, 16384); RSG::scene->render_buffers_configure(p_viewport->render_buffers, p_viewport->render_target, width, height, p_viewport->msaa, p_viewport->screen_space_aa, p_viewport->use_debanding, p_viewport->get_view_count()); } } @@ -690,15 +674,18 @@ void RendererViewport::viewport_set_use_xr(RID p_viewport, bool p_use_xr) { _configure_3d_render_buffers(viewport); } -void RendererViewport::viewport_set_scale_3d(RID p_viewport, RenderingServer::ViewportScale3D p_scale_3d) { +void RendererViewport::viewport_set_scale_3d(RID p_viewport, float p_scale_3d) { Viewport *viewport = viewport_owner.get_or_null(p_viewport); ERR_FAIL_COND(!viewport); - if (viewport->scale_3d == p_scale_3d) { + // Clamp to reasonable values that are actually useful. + // Values above 2.0 don't serve a practical purpose since the viewport + // isn't displayed with mipmaps. + if (viewport->scale_3d == CLAMP(p_scale_3d, 0.1, 2.0)) { return; } - viewport->scale_3d = p_scale_3d; + viewport->scale_3d = CLAMP(p_scale_3d, 0.1, 2.0); _configure_3d_render_buffers(viewport); } diff --git a/servers/rendering/renderer_viewport.h b/servers/rendering/renderer_viewport.h index 41d818cf99..f6e6cc8e84 100644 --- a/servers/rendering/renderer_viewport.h +++ b/servers/rendering/renderer_viewport.h @@ -49,7 +49,7 @@ public: bool use_xr; /* use xr interface to override camera positioning and projection matrices and control output */ - RS::ViewportScale3D scale_3d = RenderingServer::VIEWPORT_SCALE_3D_DISABLED; + float scale_3d = 1.0; Size2i size; RID camera; @@ -207,7 +207,7 @@ public: void viewport_initialize(RID p_rid); void viewport_set_use_xr(RID p_viewport, bool p_use_xr); - void viewport_set_scale_3d(RID p_viewport, RenderingServer::ViewportScale3D p_scale_3d); + void viewport_set_scale_3d(RID p_viewport, float p_scale_3d); void viewport_set_size(RID p_viewport, int p_width, int p_height); diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp index 70f676e5ac..dcbc5f5c8e 100644 --- a/servers/rendering/rendering_device.cpp +++ b/servers/rendering/rendering_device.cpp @@ -476,7 +476,7 @@ void RenderingDevice::_bind_methods() { ClassDB::bind_method(D_METHOD("get_device_name"), &RenderingDevice::get_device_name); ClassDB::bind_method(D_METHOD("get_device_pipeline_cache_uuid"), &RenderingDevice::get_device_pipeline_cache_uuid); - ClassDB::bind_method(D_METHOD("get_memory_usage"), &RenderingDevice::get_memory_usage); + ClassDB::bind_method(D_METHOD("get_memory_usage", "type"), &RenderingDevice::get_memory_usage); ClassDB::bind_method(D_METHOD("get_driver_resource", "resource", "rid", "index"), &RenderingDevice::get_driver_resource); diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index 49ade3c6a1..911d4c463b 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -526,7 +526,7 @@ public: FUNCRIDSPLIT(viewport) FUNC2(viewport_set_use_xr, RID, bool) - FUNC2(viewport_set_scale_3d, RID, ViewportScale3D) + FUNC2(viewport_set_scale_3d, RID, float) FUNC3(viewport_set_size, RID, int, int) FUNC2(viewport_set_active, RID, bool) diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index 713d927c50..9c38bf7606 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -1599,7 +1599,8 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type } const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { - //constructors + // Constructors. + { "bool", TYPE_BOOL, { TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false }, { "bvec2", TYPE_BVEC2, { TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false }, { "bvec2", TYPE_BVEC2, { TYPE_BOOL, TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false }, @@ -1672,7 +1673,7 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "mat3", TYPE_MAT3, { TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false }, { "mat4", TYPE_MAT4, { TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false }, - //conversion scalars + // Conversion scalars. { "int", TYPE_INT, { TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false }, { "int", TYPE_INT, { TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, false }, @@ -1694,7 +1695,7 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "bool", TYPE_BOOL, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true }, { "bool", TYPE_BOOL, { TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false }, - //conversion vectors + // Conversion vectors. { "ivec2", TYPE_IVEC2, { TYPE_BVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false }, { "ivec2", TYPE_IVEC2, { TYPE_IVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false }, @@ -1756,7 +1757,7 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "bvec4", TYPE_BVEC4, { TYPE_UVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, true }, { "bvec4", TYPE_BVEC4, { TYPE_VEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false }, - //conversion between matrixes + // Conversion between matrixes. { "mat2", TYPE_MAT2, { TYPE_MAT3, TYPE_VOID }, { "" }, TAG_GLOBAL, false }, { "mat2", TYPE_MAT2, { TYPE_MAT4, TYPE_VOID }, { "" }, TAG_GLOBAL, false }, @@ -1765,43 +1766,58 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "mat4", TYPE_MAT4, { TYPE_MAT2, TYPE_VOID }, { "" }, TAG_GLOBAL, false }, { "mat4", TYPE_MAT4, { TYPE_MAT3, TYPE_VOID }, { "" }, TAG_GLOBAL, false }, - //builtins - trigonometry + // Built-ins - trigonometric functions. + // radians { "radians", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "degrees" }, TAG_GLOBAL, false }, { "radians", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "degrees" }, TAG_GLOBAL, false }, { "radians", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "degrees" }, TAG_GLOBAL, false }, { "radians", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "degrees" }, TAG_GLOBAL, false }, + // degrees + { "degrees", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "radians" }, TAG_GLOBAL, false }, { "degrees", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "radians" }, TAG_GLOBAL, false }, { "degrees", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "radians" }, TAG_GLOBAL, false }, { "degrees", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "radians" }, TAG_GLOBAL, false }, + // sin + { "sin", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false }, { "sin", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false }, { "sin", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false }, { "sin", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false }, + // cos + { "cos", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false }, { "cos", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false }, { "cos", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false }, { "cos", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false }, + // tan + { "tan", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false }, { "tan", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false }, { "tan", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false }, { "tan", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false }, + // asin + { "asin", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "asin", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "asin", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "asin", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + // acos + { "acos", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "acos", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "acos", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "acos", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + // atan + { "atan", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "y_over_x" }, TAG_GLOBAL, false }, { "atan", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "y_over_x" }, TAG_GLOBAL, false }, { "atan", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "y_over_x" }, TAG_GLOBAL, false }, @@ -1811,66 +1827,101 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "atan", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "y", "x" }, TAG_GLOBAL, false }, { "atan", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "y", "x" }, TAG_GLOBAL, false }, + // sinh + { "sinh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "sinh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "sinh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "sinh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + // cosh + { "cosh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "cosh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "cosh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "cosh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + // tanh + { "tanh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "tanh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "tanh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "tanh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + // asinh + { "asinh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "asinh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "asinh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "asinh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + // acosh + { "acosh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "acosh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "acosh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "acosh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + // atanh + { "atanh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "atanh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "atanh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "atanh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, - //builtins - exponential + // Builtins - exponential functions. + // pow + { "pow", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "x", "y" }, TAG_GLOBAL, false }, { "pow", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "x", "y" }, TAG_GLOBAL, false }, { "pow", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "x", "y" }, TAG_GLOBAL, false }, { "pow", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "x", "y" }, TAG_GLOBAL, false }, + + // exp + { "exp", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "exp", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "exp", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "exp", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + + // log + { "log", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "log", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "log", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "log", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + + // exp2 + { "exp2", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "exp2", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "exp2", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "exp2", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + + // log2 + { "log2", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "log2", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "log2", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "log2", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + + // sqrt + { "sqrt", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "sqrt", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "sqrt", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "sqrt", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + + // inversesqrt + { "inversesqrt", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "inversesqrt", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "inversesqrt", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "inversesqrt", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, - //builtins - common + + // Built-ins - common functions. + // abs + { "abs", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "abs", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "abs", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, @@ -1881,6 +1932,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "abs", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "abs", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + // sign + { "sign", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "sign", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "sign", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, @@ -1891,31 +1944,50 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "sign", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "sign", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + // floor + { "floor", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "floor", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "floor", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "floor", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + + // trunc + { "trunc", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "trunc", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "trunc", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "trunc", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + + // round + { "round", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "round", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "round", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "round", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + + // roundEven + { "roundEven", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "roundEven", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "roundEven", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "roundEven", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + + // ceil + { "ceil", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "ceil", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "ceil", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "ceil", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + + // fract + { "fract", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "fract", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "fract", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "fract", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + // mod + { "mod", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "x", "y" }, TAG_GLOBAL, false }, { "mod", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "x", "y" }, TAG_GLOBAL, false }, { "mod", TYPE_VEC2, { TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "x", "y" }, TAG_GLOBAL, false }, @@ -1924,11 +1996,15 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "mod", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "x", "y" }, TAG_GLOBAL, false }, { "mod", TYPE_VEC4, { TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "x", "y" }, TAG_GLOBAL, false }, + // modf + { "modf", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "x", "i" }, TAG_GLOBAL, true }, { "modf", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "x", "i" }, TAG_GLOBAL, true }, { "modf", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "x", "i" }, TAG_GLOBAL, true }, { "modf", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "x", "i" }, TAG_GLOBAL, true }, + // min + { "min", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "min", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "min", TYPE_VEC2, { TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, @@ -1953,6 +2029,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "min", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true }, { "min", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true }, + // max + { "max", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "max", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "max", TYPE_VEC2, { TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, @@ -1977,6 +2055,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "max", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true }, { "max", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true }, + // clamp + { "clamp", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false }, { "clamp", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false }, { "clamp", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false }, @@ -2001,6 +2081,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "clamp", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, true }, { "clamp", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, true }, + // mix + { "mix", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "a", "b", "value" }, TAG_GLOBAL, false }, { "mix", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "a", "b", "value" }, TAG_GLOBAL, false }, { "mix", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_BVEC2, TYPE_VOID }, { "a", "b", "value" }, TAG_GLOBAL, false }, @@ -2012,6 +2094,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "mix", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_BVEC4, TYPE_VOID }, { "a", "b", "value" }, TAG_GLOBAL, false }, { "mix", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b", "value" }, TAG_GLOBAL, false }, + // step + { "step", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "edge", "x" }, TAG_GLOBAL, false }, { "step", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "edge", "x" }, TAG_GLOBAL, false }, { "step", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "edge", "x" }, TAG_GLOBAL, false }, @@ -2019,6 +2103,9 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "step", TYPE_VEC2, { TYPE_FLOAT, TYPE_VEC2, TYPE_VOID }, { "edge", "x" }, TAG_GLOBAL, false }, { "step", TYPE_VEC3, { TYPE_FLOAT, TYPE_VEC3, TYPE_VOID }, { "edge", "x" }, TAG_GLOBAL, false }, { "step", TYPE_VEC4, { TYPE_FLOAT, TYPE_VEC4, TYPE_VOID }, { "edge", "x" }, TAG_GLOBAL, false }, + + // smoothstep + { "smoothstep", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "edge0", "edge1", "value" }, TAG_GLOBAL, false }, { "smoothstep", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "edge0", "edge1", "value" }, TAG_GLOBAL, false }, { "smoothstep", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "edge0", "edge1", "value" }, TAG_GLOBAL, false }, @@ -2027,77 +2114,127 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "smoothstep", TYPE_VEC3, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VEC3, TYPE_VOID }, { "edge0", "edge1", "value" }, TAG_GLOBAL, false }, { "smoothstep", TYPE_VEC4, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VEC4, TYPE_VOID }, { "edge0", "edge1", "value" }, TAG_GLOBAL, false }, + // isnan + { "isnan", TYPE_BOOL, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "isnan", TYPE_BVEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "isnan", TYPE_BVEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "isnan", TYPE_BVEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + // isinf + { "isinf", TYPE_BOOL, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "isinf", TYPE_BVEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "isinf", TYPE_BVEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "isinf", TYPE_BVEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + // floatBitsToInt + { "floatBitsToInt", TYPE_INT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, true }, { "floatBitsToInt", TYPE_IVEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, true }, { "floatBitsToInt", TYPE_IVEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, true }, { "floatBitsToInt", TYPE_IVEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, true }, + // floatBitsToUint + { "floatBitsToUint", TYPE_UINT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, true }, { "floatBitsToUint", TYPE_UVEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, true }, { "floatBitsToUint", TYPE_UVEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, true }, { "floatBitsToUint", TYPE_UVEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, true }, + // intBitsToFloat + { "intBitsToFloat", TYPE_FLOAT, { TYPE_INT, TYPE_VOID }, { "x" }, TAG_GLOBAL, true }, { "intBitsToFloat", TYPE_VEC2, { TYPE_IVEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, true }, { "intBitsToFloat", TYPE_VEC3, { TYPE_IVEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, true }, { "intBitsToFloat", TYPE_VEC4, { TYPE_IVEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, true }, + // uintBitsToFloat + { "uintBitsToFloat", TYPE_FLOAT, { TYPE_UINT, TYPE_VOID }, { "x" }, TAG_GLOBAL, true }, { "uintBitsToFloat", TYPE_VEC2, { TYPE_UVEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, true }, { "uintBitsToFloat", TYPE_VEC3, { TYPE_UVEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, true }, { "uintBitsToFloat", TYPE_VEC4, { TYPE_UVEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, true }, - //builtins - geometric + // Built-ins - geometric functions. + // length + + { "length", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "length", TYPE_FLOAT, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "length", TYPE_FLOAT, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "length", TYPE_FLOAT, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + + // distance + + { "distance", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "distance", TYPE_FLOAT, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "distance", TYPE_FLOAT, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "distance", TYPE_FLOAT, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, + + // dot + + { "dot", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "dot", TYPE_FLOAT, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "dot", TYPE_FLOAT, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "dot", TYPE_FLOAT, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, + + // cross + { "cross", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, + + // normalize + + { "normalize", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "v" }, TAG_GLOBAL, false }, { "normalize", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "v" }, TAG_GLOBAL, false }, { "normalize", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "v" }, TAG_GLOBAL, false }, { "normalize", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "v" }, TAG_GLOBAL, false }, + + // reflect + { "reflect", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "I", "N" }, TAG_GLOBAL, false }, + + // refract + { "refract", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "I", "N", "eta" }, TAG_GLOBAL, false }, + // faceforward + { "faceforward", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "N", "I", "Nref" }, TAG_GLOBAL, false }, { "faceforward", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "N", "I", "Nref" }, TAG_GLOBAL, false }, { "faceforward", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "N", "I", "Nref" }, TAG_GLOBAL, false }, + // matrixCompMult + { "matrixCompMult", TYPE_MAT2, { TYPE_MAT2, TYPE_MAT2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "matrixCompMult", TYPE_MAT3, { TYPE_MAT3, TYPE_MAT3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "matrixCompMult", TYPE_MAT4, { TYPE_MAT4, TYPE_MAT4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, + // outerProduct + { "outerProduct", TYPE_MAT2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "c", "r" }, TAG_GLOBAL, false }, { "outerProduct", TYPE_MAT3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "c", "r" }, TAG_GLOBAL, false }, { "outerProduct", TYPE_MAT4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "c", "r" }, TAG_GLOBAL, false }, + // transpose + { "transpose", TYPE_MAT2, { TYPE_MAT2, TYPE_VOID }, { "m" }, TAG_GLOBAL, false }, { "transpose", TYPE_MAT3, { TYPE_MAT3, TYPE_VOID }, { "m" }, TAG_GLOBAL, false }, { "transpose", TYPE_MAT4, { TYPE_MAT4, TYPE_VOID }, { "m" }, TAG_GLOBAL, false }, + // determinant + { "determinant", TYPE_FLOAT, { TYPE_MAT2, TYPE_VOID }, { "m" }, TAG_GLOBAL, false }, { "determinant", TYPE_FLOAT, { TYPE_MAT3, TYPE_VOID }, { "m" }, TAG_GLOBAL, false }, { "determinant", TYPE_FLOAT, { TYPE_MAT4, TYPE_VOID }, { "m" }, TAG_GLOBAL, false }, + // inverse + { "inverse", TYPE_MAT2, { TYPE_MAT2, TYPE_VOID }, { "m" }, TAG_GLOBAL, false }, { "inverse", TYPE_MAT3, { TYPE_MAT3, TYPE_VOID }, { "m" }, TAG_GLOBAL, false }, { "inverse", TYPE_MAT4, { TYPE_MAT4, TYPE_VOID }, { "m" }, TAG_GLOBAL, false }, + // lessThan + { "lessThan", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "lessThan", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "lessThan", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, @@ -2110,6 +2247,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "lessThan", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true }, { "lessThan", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true }, + // greaterThan + { "greaterThan", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "greaterThan", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "greaterThan", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, @@ -2122,6 +2261,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "greaterThan", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true }, { "greaterThan", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true }, + // lessThanEqual + { "lessThanEqual", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "lessThanEqual", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "lessThanEqual", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, @@ -2134,6 +2275,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "lessThanEqual", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true }, { "lessThanEqual", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true }, + // greaterThanEqual + { "greaterThanEqual", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "greaterThanEqual", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "greaterThanEqual", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, @@ -2146,6 +2289,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "greaterThanEqual", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true }, { "greaterThanEqual", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true }, + // equal + { "equal", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "equal", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "equal", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, @@ -2162,6 +2307,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "equal", TYPE_BVEC3, { TYPE_BVEC3, TYPE_BVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "equal", TYPE_BVEC4, { TYPE_BVEC4, TYPE_BVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, + // notEqual + { "notEqual", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "notEqual", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "notEqual", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, @@ -2178,19 +2325,27 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "notEqual", TYPE_BVEC3, { TYPE_BVEC3, TYPE_BVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, { "notEqual", TYPE_BVEC4, { TYPE_BVEC4, TYPE_BVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false }, + // any + { "any", TYPE_BOOL, { TYPE_BVEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "any", TYPE_BOOL, { TYPE_BVEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "any", TYPE_BOOL, { TYPE_BVEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + // all + { "all", TYPE_BOOL, { TYPE_BVEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "all", TYPE_BOOL, { TYPE_BVEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "all", TYPE_BOOL, { TYPE_BVEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, + // not + { "not", TYPE_BVEC2, { TYPE_BVEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "not", TYPE_BVEC3, { TYPE_BVEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, { "not", TYPE_BVEC4, { TYPE_BVEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false }, - //builtins - texture + // Built-ins: texture functions. + // textureSize + { "textureSize", TYPE_IVEC2, { TYPE_SAMPLER2D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true }, { "textureSize", TYPE_IVEC2, { TYPE_ISAMPLER2D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true }, { "textureSize", TYPE_IVEC2, { TYPE_USAMPLER2D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true }, @@ -2203,6 +2358,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "textureSize", TYPE_IVEC2, { TYPE_SAMPLERCUBE, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true }, { "textureSize", TYPE_IVEC2, { TYPE_SAMPLERCUBEARRAY, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true }, + // texture + { "texture", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false }, { "texture", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false }, { "texture", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true }, @@ -2226,6 +2383,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "texture", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false }, { "texture", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false }, + // textureProj + { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true }, { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true }, { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true }, @@ -2245,6 +2404,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true }, { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true }, + // textureLod + { "textureLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false }, { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true }, { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true }, @@ -2257,6 +2418,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "textureLod", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false }, { "textureLod", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false }, + // texelFetch + { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true }, { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true }, { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true }, @@ -2267,6 +2430,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true }, { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true }, + // textureProjLod + { "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true }, { "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true }, { "textureProjLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true }, @@ -2277,6 +2442,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "textureProjLod", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true }, { "textureProjLod", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true }, + // textureGrad + { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true }, { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true }, { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true }, @@ -2289,40 +2456,202 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "textureGrad", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true }, { "textureGrad", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true }, + // textureGather + + { "textureGather", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true }, + { "textureGather", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true }, + { "textureGather", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true }, + { "textureGather", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, true }, + { "textureGather", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, true }, + { "textureGather", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, true }, + { "textureGather", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true }, + { "textureGather", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true }, + { "textureGather", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true }, + { "textureGather", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, true }, + { "textureGather", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, true }, + { "textureGather", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, true }, + { "textureGather", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true }, + { "textureGather", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, true }, + + // dFdx + { "dFdx", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, { "dFdx", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, { "dFdx", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, { "dFdx", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + // dFdy + { "dFdy", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, { "dFdy", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, { "dFdy", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, { "dFdy", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + // fwidth + { "fwidth", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, { "fwidth", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, { "fwidth", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, { "fwidth", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, - //sub-functions + // Sub-functions. + // array - //array { "length", TYPE_INT, { TYPE_VOID }, { "" }, TAG_ARRAY, true }, - // modern functions + // Modern functions. + // fma { "fma", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "a", "b", "c" }, TAG_GLOBAL, false }, { "fma", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b", "c" }, TAG_GLOBAL, false }, { "fma", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b", "c" }, TAG_GLOBAL, false }, { "fma", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b", "c" }, TAG_GLOBAL, false }, + // Packing/Unpacking functions. + + { "packHalf2x16", TYPE_UINT, { TYPE_VEC2, TYPE_VOID }, { "v" }, TAG_GLOBAL, true }, + { "packUnorm2x16", TYPE_UINT, { TYPE_VEC2, TYPE_VOID }, { "v" }, TAG_GLOBAL, true }, + { "packSnorm2x16", TYPE_UINT, { TYPE_VEC2, TYPE_VOID }, { "v" }, TAG_GLOBAL, true }, + { "packUnorm4x8", TYPE_UINT, { TYPE_VEC4, TYPE_VOID }, { "v" }, TAG_GLOBAL, true }, + { "packSnorm4x8", TYPE_UINT, { TYPE_VEC4, TYPE_VOID }, { "v" }, TAG_GLOBAL, true }, + + { "unpackHalf2x16", TYPE_VEC2, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, true }, + { "unpackUnorm2x16", TYPE_VEC2, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, true }, + { "unpackSnorm2x16", TYPE_VEC2, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, true }, + { "unpackUnorm4x8", TYPE_VEC4, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, true }, + { "unpackSnorm4x8", TYPE_VEC4, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, true }, + + // bitfieldExtract + + { "bitfieldExtract", TYPE_INT, { TYPE_INT, TYPE_INT, TYPE_INT, TYPE_VOID }, { "value", "offset", "bits" }, TAG_GLOBAL, true }, + { "bitfieldExtract", TYPE_IVEC2, { TYPE_IVEC2, TYPE_INT, TYPE_INT, TYPE_VOID }, { "value", "offset", "bits" }, TAG_GLOBAL, true }, + { "bitfieldExtract", TYPE_IVEC3, { TYPE_IVEC3, TYPE_INT, TYPE_INT, TYPE_VOID }, { "value", "offset", "bits" }, TAG_GLOBAL, true }, + { "bitfieldExtract", TYPE_IVEC4, { TYPE_IVEC4, TYPE_INT, TYPE_INT, TYPE_VOID }, { "value", "offset", "bits" }, TAG_GLOBAL, true }, + + { "bitfieldExtract", TYPE_UINT, { TYPE_UINT, TYPE_INT, TYPE_INT, TYPE_VOID }, { "value", "offset", "bits" }, TAG_GLOBAL, true }, + { "bitfieldExtract", TYPE_UVEC2, { TYPE_UVEC2, TYPE_INT, TYPE_INT, TYPE_VOID }, { "value", "offset", "bits" }, TAG_GLOBAL, true }, + { "bitfieldExtract", TYPE_UVEC3, { TYPE_UVEC3, TYPE_INT, TYPE_INT, TYPE_VOID }, { "value", "offset", "bits" }, TAG_GLOBAL, true }, + { "bitfieldExtract", TYPE_UVEC4, { TYPE_UVEC4, TYPE_INT, TYPE_INT, TYPE_VOID }, { "value", "offset", "bits" }, TAG_GLOBAL, true }, + + // bitfieldInsert + + { "bitfieldInsert", TYPE_INT, { TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_VOID }, { "base", "insert", "offset", "bits" }, TAG_GLOBAL, true }, + { "bitfieldInsert", TYPE_IVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_INT, TYPE_INT, TYPE_VOID }, { "base", "insert", "offset", "bits" }, TAG_GLOBAL, true }, + { "bitfieldInsert", TYPE_IVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_INT, TYPE_INT, TYPE_VOID }, { "base", "insert", "offset", "bits" }, TAG_GLOBAL, true }, + { "bitfieldInsert", TYPE_IVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_INT, TYPE_INT, TYPE_VOID }, { "base", "insert", "offset", "bits" }, TAG_GLOBAL, true }, + + { "bitfieldInsert", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_INT, TYPE_INT, TYPE_VOID }, { "base", "insert", "offset", "bits" }, TAG_GLOBAL, true }, + { "bitfieldInsert", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_INT, TYPE_INT, TYPE_VOID }, { "base", "insert", "offset", "bits" }, TAG_GLOBAL, true }, + { "bitfieldInsert", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_INT, TYPE_INT, TYPE_VOID }, { "base", "insert", "offset", "bits" }, TAG_GLOBAL, true }, + { "bitfieldInsert", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_INT, TYPE_INT, TYPE_VOID }, { "base", "insert", "offset", "bits" }, TAG_GLOBAL, true }, + + // bitfieldReverse + + { "bitfieldReverse", TYPE_INT, { TYPE_INT, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + { "bitfieldReverse", TYPE_IVEC2, { TYPE_IVEC2, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + { "bitfieldReverse", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + { "bitfieldReverse", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + + { "bitfieldReverse", TYPE_UINT, { TYPE_UINT, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + { "bitfieldReverse", TYPE_UVEC2, { TYPE_UVEC2, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + { "bitfieldReverse", TYPE_UVEC3, { TYPE_UVEC3, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + { "bitfieldReverse", TYPE_UVEC4, { TYPE_UVEC4, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + + // bitCount + + { "bitCount", TYPE_INT, { TYPE_INT, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + { "bitCount", TYPE_IVEC2, { TYPE_IVEC2, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + { "bitCount", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + { "bitCount", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + + { "bitCount", TYPE_UINT, { TYPE_UINT, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + { "bitCount", TYPE_UVEC2, { TYPE_UVEC2, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + { "bitCount", TYPE_UVEC3, { TYPE_UVEC3, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + { "bitCount", TYPE_UVEC4, { TYPE_UVEC4, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + + // findLSB + + { "findLSB", TYPE_INT, { TYPE_INT, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + { "findLSB", TYPE_IVEC2, { TYPE_IVEC2, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + { "findLSB", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + { "findLSB", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + + { "findLSB", TYPE_UINT, { TYPE_UINT, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + { "findLSB", TYPE_UVEC2, { TYPE_UVEC2, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + { "findLSB", TYPE_UVEC3, { TYPE_UVEC3, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + { "findLSB", TYPE_UVEC4, { TYPE_UVEC4, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + + // findMSB + + { "findMSB", TYPE_INT, { TYPE_INT, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + { "findMSB", TYPE_IVEC2, { TYPE_IVEC2, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + { "findMSB", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + { "findMSB", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + + { "findMSB", TYPE_UINT, { TYPE_UINT, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + { "findMSB", TYPE_UVEC2, { TYPE_UVEC2, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + { "findMSB", TYPE_UVEC3, { TYPE_UVEC3, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + { "findMSB", TYPE_UVEC4, { TYPE_UVEC4, TYPE_VOID }, { "value" }, TAG_GLOBAL, true }, + + // umulExtended + + { "umulExtended", TYPE_VOID, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "y", "msb", "lsb" }, TAG_GLOBAL, true }, + { "umulExtended", TYPE_VOID, { TYPE_UVEC2, TYPE_UVEC2, TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "x", "y", "msb", "lsb" }, TAG_GLOBAL, true }, + { "umulExtended", TYPE_VOID, { TYPE_UVEC3, TYPE_UVEC3, TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "x", "y", "msb", "lsb" }, TAG_GLOBAL, true }, + { "umulExtended", TYPE_VOID, { TYPE_UVEC4, TYPE_UVEC4, TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "x", "y", "msb", "lsb" }, TAG_GLOBAL, true }, + + // imulExtended + + { "imulExtended", TYPE_VOID, { TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_VOID }, { "x", "y", "msb", "lsb" }, TAG_GLOBAL, true }, + { "imulExtended", TYPE_VOID, { TYPE_IVEC2, TYPE_IVEC2, TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, { "x", "y", "msb", "lsb" }, TAG_GLOBAL, true }, + { "imulExtended", TYPE_VOID, { TYPE_IVEC3, TYPE_IVEC3, TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, { "x", "y", "msb", "lsb" }, TAG_GLOBAL, true }, + { "imulExtended", TYPE_VOID, { TYPE_IVEC4, TYPE_IVEC4, TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, { "x", "y", "msb", "lsb" }, TAG_GLOBAL, true }, + + // uaddCarry + + { "uaddCarry", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "y", "carry" }, TAG_GLOBAL, true }, + { "uaddCarry", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "x", "y", "carry" }, TAG_GLOBAL, true }, + { "uaddCarry", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "x", "y", "carry" }, TAG_GLOBAL, true }, + { "uaddCarry", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "x", "y", "carry" }, TAG_GLOBAL, true }, + + // usubBorrow + + { "usubBorrow", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "y", "borrow" }, TAG_GLOBAL, true }, + { "usubBorrow", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "x", "y", "borrow" }, TAG_GLOBAL, true }, + { "usubBorrow", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "x", "y", "borrow" }, TAG_GLOBAL, true }, + { "usubBorrow", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "x", "y", "borrow" }, TAG_GLOBAL, true }, + + // ldexp + + { "ldexp", TYPE_FLOAT, { TYPE_FLOAT, TYPE_INT, TYPE_VOID }, { "x", "exp" }, TAG_GLOBAL, true }, + { "ldexp", TYPE_VEC2, { TYPE_VEC2, TYPE_IVEC2, TYPE_VOID }, { "x", "exp" }, TAG_GLOBAL, true }, + { "ldexp", TYPE_VEC3, { TYPE_VEC3, TYPE_IVEC3, TYPE_VOID }, { "x", "exp" }, TAG_GLOBAL, true }, + { "ldexp", TYPE_VEC4, { TYPE_VEC4, TYPE_IVEC4, TYPE_VOID }, { "x", "exp" }, TAG_GLOBAL, true }, + + // frexp + + { "frexp", TYPE_FLOAT, { TYPE_FLOAT, TYPE_INT, TYPE_VOID }, { "x", "exp" }, TAG_GLOBAL, true }, + { "frexp", TYPE_VEC2, { TYPE_VEC2, TYPE_IVEC2, TYPE_VOID }, { "x", "exp" }, TAG_GLOBAL, true }, + { "frexp", TYPE_VEC3, { TYPE_VEC3, TYPE_IVEC3, TYPE_VOID }, { "x", "exp" }, TAG_GLOBAL, true }, + { "frexp", TYPE_VEC4, { TYPE_VEC4, TYPE_IVEC4, TYPE_VOID }, { "x", "exp" }, TAG_GLOBAL, true }, + { nullptr, TYPE_VOID, { TYPE_VOID }, { "" }, TAG_GLOBAL, false } }; const ShaderLanguage::BuiltinFuncOutArgs ShaderLanguage::builtin_func_out_args[] = { - //constructors - { "modf", 1 }, - { nullptr, 0 } + { "modf", { 1, -1 } }, + { "umulExtended", { 2, 3 } }, + { "imulExtended", { 2, 3 } }, + { "uaddCarry", { 2, -1 } }, + { "usubBorrow", { 2, -1 } }, + { "ldexp", { 1, -1 } }, + { "frexp", { 1, -1 } }, + { nullptr, { 0, -1 } } +}; + +const ShaderLanguage::BuiltinFuncConstArgs ShaderLanguage::builtin_func_const_args[] = { + { "textureGather", 2, 0, 3 }, + { nullptr, 0, 0, 0 } }; bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionInfo &p_function_info, OperatorNode *p_func, DataType *r_ret_type, StringName *r_ret_type_str) { @@ -2416,100 +2745,152 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI } if (!fail) { - //make sure its not an out argument used in the wrong way - int outarg_idx = 0; - while (builtin_func_out_args[outarg_idx].name) { - if (String(name) == builtin_func_out_args[outarg_idx].name) { - int arg_idx = builtin_func_out_args[outarg_idx].argument; - - if (arg_idx < argcount) { - if (p_func->arguments[arg_idx + 1]->type != Node::TYPE_VARIABLE && p_func->arguments[arg_idx + 1]->type != Node::TYPE_MEMBER && p_func->arguments[arg_idx + 1]->type != Node::TYPE_ARRAY) { - _set_error("Argument " + itos(arg_idx + 1) + " of function '" + String(name) + "' is not a variable, array or member."); - return false; + { + int constarg_idx = 0; + while (builtin_func_const_args[constarg_idx].name) { + if (String(name) == builtin_func_const_args[constarg_idx].name) { + int arg = builtin_func_const_args[constarg_idx].arg + 1; + if (p_func->arguments.size() <= arg) { + break; } - if (p_func->arguments[arg_idx + 1]->type == Node::TYPE_ARRAY) { - ArrayNode *mn = static_cast<ArrayNode *>(p_func->arguments[arg_idx + 1]); - if (mn->is_const) { - fail = true; - } - } else if (p_func->arguments[arg_idx + 1]->type == Node::TYPE_MEMBER) { - MemberNode *mn = static_cast<MemberNode *>(p_func->arguments[arg_idx + 1]); - if (mn->basetype_const) { - fail = true; + int min = builtin_func_const_args[constarg_idx].min; + int max = builtin_func_const_args[constarg_idx].max; + + bool error = false; + if (p_func->arguments[arg]->type == Node::TYPE_VARIABLE) { + const VariableNode *vn = (VariableNode *)p_func->arguments[arg]; + + bool is_const = false; + ConstantNode::Value value; + + _find_identifier(p_block, false, p_function_info, vn->name, nullptr, nullptr, &is_const, nullptr, nullptr, &value); + if (!is_const || value.sint < min || value.sint > max) { + error = true; } - } else { // TYPE_VARIABLE - VariableNode *vn = static_cast<VariableNode *>(p_func->arguments[arg_idx + 1]); - if (vn->is_const) { - fail = true; - } else { - StringName varname = vn->name; - if (shader->uniforms.has(varname)) { - fail = true; - } else { - if (shader->varyings.has(varname)) { - _set_error(vformat("Varyings cannot be passed for '%s' parameter!", "out")); - return false; - } - if (p_function_info.built_ins.has(varname)) { - BuiltInInfo info = p_function_info.built_ins[varname]; - if (info.constant) { - fail = true; - } + } else { + if (p_func->arguments[arg]->type == Node::TYPE_CONSTANT) { + ConstantNode *cn = (ConstantNode *)p_func->arguments[arg]; + + if (cn->get_datatype() == TYPE_INT && cn->values.size() == 1) { + int value = cn->values[0].sint; + + if (value < min || value > max) { + error = true; } + } else { + error = true; } + } else { + error = true; } } - if (fail) { - _set_error(vformat("Constant value cannot be passed for '%s' parameter!", "out")); + if (error) { + _set_error(vformat("Expected integer constant within %s..%s range.", min, max)); return false; } + } + constarg_idx++; + } + } - StringName var_name; - if (p_func->arguments[arg_idx + 1]->type == Node::TYPE_ARRAY) { - var_name = static_cast<const ArrayNode *>(p_func->arguments[arg_idx + 1])->name; - } else if (p_func->arguments[arg_idx + 1]->type == Node::TYPE_MEMBER) { - Node *n = static_cast<const MemberNode *>(p_func->arguments[arg_idx + 1])->owner; - while (n->type == Node::TYPE_MEMBER) { - n = static_cast<const MemberNode *>(n)->owner; - } - if (n->type != Node::TYPE_VARIABLE && n->type != Node::TYPE_ARRAY) { + //make sure its not an out argument used in the wrong way + int outarg_idx = 0; + while (builtin_func_out_args[outarg_idx].name) { + if (String(name) == builtin_func_out_args[outarg_idx].name) { + for (int arg = 0; arg < BuiltinFuncOutArgs::MAX_ARGS; arg++) { + int arg_idx = builtin_func_out_args[outarg_idx].arguments[arg]; + if (arg_idx == -1) { + break; + } + if (arg_idx < argcount) { + if (p_func->arguments[arg_idx + 1]->type != Node::TYPE_VARIABLE && p_func->arguments[arg_idx + 1]->type != Node::TYPE_MEMBER && p_func->arguments[arg_idx + 1]->type != Node::TYPE_ARRAY) { _set_error("Argument " + itos(arg_idx + 1) + " of function '" + String(name) + "' is not a variable, array or member."); return false; } - if (n->type == Node::TYPE_VARIABLE) { - var_name = static_cast<const VariableNode *>(n)->name; - } else { // TYPE_ARRAY - var_name = static_cast<const ArrayNode *>(n)->name; + + if (p_func->arguments[arg_idx + 1]->type == Node::TYPE_ARRAY) { + ArrayNode *mn = static_cast<ArrayNode *>(p_func->arguments[arg_idx + 1]); + if (mn->is_const) { + fail = true; + } + } else if (p_func->arguments[arg_idx + 1]->type == Node::TYPE_MEMBER) { + MemberNode *mn = static_cast<MemberNode *>(p_func->arguments[arg_idx + 1]); + if (mn->basetype_const) { + fail = true; + } + } else { // TYPE_VARIABLE + VariableNode *vn = static_cast<VariableNode *>(p_func->arguments[arg_idx + 1]); + if (vn->is_const) { + fail = true; + } else { + StringName varname = vn->name; + if (shader->uniforms.has(varname)) { + fail = true; + } else { + if (shader->varyings.has(varname)) { + _set_error(vformat("Varyings cannot be passed for '%s' parameter!", "out")); + return false; + } + if (p_function_info.built_ins.has(varname)) { + BuiltInInfo info = p_function_info.built_ins[varname]; + if (info.constant) { + fail = true; + } + } + } + } } - } else { // TYPE_VARIABLE - var_name = static_cast<const VariableNode *>(p_func->arguments[arg_idx + 1])->name; - } - const BlockNode *b = p_block; - bool valid = false; - while (b) { - if (b->variables.has(var_name) || p_function_info.built_ins.has(var_name)) { - valid = true; - break; + if (fail) { + _set_error(vformat("Constant value cannot be passed for '%s' parameter!", "out")); + return false; } - if (b->parent_function) { - for (int i = 0; i < b->parent_function->arguments.size(); i++) { - if (b->parent_function->arguments[i].name == var_name) { - valid = true; - break; + + StringName var_name; + if (p_func->arguments[arg_idx + 1]->type == Node::TYPE_ARRAY) { + var_name = static_cast<const ArrayNode *>(p_func->arguments[arg_idx + 1])->name; + } else if (p_func->arguments[arg_idx + 1]->type == Node::TYPE_MEMBER) { + Node *n = static_cast<const MemberNode *>(p_func->arguments[arg_idx + 1])->owner; + while (n->type == Node::TYPE_MEMBER) { + n = static_cast<const MemberNode *>(n)->owner; + } + if (n->type != Node::TYPE_VARIABLE && n->type != Node::TYPE_ARRAY) { + _set_error("Argument " + itos(arg_idx + 1) + " of function '" + String(name) + "' is not a variable, array or member."); + return false; + } + if (n->type == Node::TYPE_VARIABLE) { + var_name = static_cast<const VariableNode *>(n)->name; + } else { // TYPE_ARRAY + var_name = static_cast<const ArrayNode *>(n)->name; + } + } else { // TYPE_VARIABLE + var_name = static_cast<const VariableNode *>(p_func->arguments[arg_idx + 1])->name; + } + const BlockNode *b = p_block; + bool valid = false; + while (b) { + if (b->variables.has(var_name) || p_function_info.built_ins.has(var_name)) { + valid = true; + break; + } + if (b->parent_function) { + for (int i = 0; i < b->parent_function->arguments.size(); i++) { + if (b->parent_function->arguments[i].name == var_name) { + valid = true; + break; + } } } + b = b->parent_block; } - b = b->parent_block; - } - if (!valid) { - _set_error("Argument " + itos(arg_idx + 1) + " of function '" + String(name) + "' can only take a local variable, array or member."); - return false; + if (!valid) { + _set_error("Argument " + itos(arg_idx + 1) + " of function '" + String(name) + "' can only take a local variable, array or member."); + return false; + } } } } - outarg_idx++; } //implicitly convert values if possible @@ -3873,6 +4254,116 @@ bool ShaderLanguage::_propagate_function_call_sampler_builtin_reference(StringNa ERR_FAIL_V(false); //bug? function not found } +ShaderLanguage::Node *ShaderLanguage::_parse_array_size(BlockNode *p_block, const FunctionInfo &p_function_info, int &r_array_size) { + int array_size = 0; + + Node *n = _parse_and_reduce_expression(p_block, p_function_info); + if (n) { + if (n->type == Node::TYPE_VARIABLE) { + VariableNode *vn = static_cast<VariableNode *>(n); + if (vn) { + ConstantNode::Value v; + DataType data_type; + bool is_const = false; + + _find_identifier(p_block, false, p_function_info, vn->name, &data_type, nullptr, &is_const, nullptr, nullptr, &v); + + if (is_const) { + if (data_type == TYPE_INT) { + int32_t value = v.sint; + if (value > 0) { + array_size = value; + } + } else if (data_type == TYPE_UINT) { + uint32_t value = v.uint; + if (value > 0U) { + array_size = value; + } + } + } + } + } else if (n->type == Node::TYPE_OPERATOR) { + _set_error("Array size expressions are not yet implemented."); + return nullptr; + } + } + + r_array_size = array_size; + return n; +} + +Error ShaderLanguage::_parse_global_array_size(int &r_array_size) { + if (r_array_size > 0) { + _set_error("Array size is already defined!"); + return ERR_PARSE_ERROR; + } + TkPos pos = _get_tkpos(); + Token tk = _get_token(); + + int array_size = 0; + + if (tk.type != TK_INT_CONSTANT || ((int)tk.constant) <= 0) { + _set_tkpos(pos); + Node *n = _parse_array_size(nullptr, FunctionInfo(), array_size); + if (!n) { + return ERR_PARSE_ERROR; + } + } else if (((int)tk.constant) > 0) { + array_size = (uint32_t)tk.constant; + } + + if (array_size <= 0) { + _set_error("Expected single integer constant > 0"); + return ERR_PARSE_ERROR; + } + + tk = _get_token(); + if (tk.type != TK_BRACKET_CLOSE) { + _set_error("Expected ']'"); + return ERR_PARSE_ERROR; + } + + r_array_size = array_size; + return OK; +} + +Error ShaderLanguage::_parse_local_array_size(BlockNode *p_block, const FunctionInfo &p_function_info, ArrayDeclarationNode *p_node, ArrayDeclarationNode::Declaration *p_decl, int &r_array_size, bool &r_is_unknown_size) { + TkPos pos = _get_tkpos(); + Token tk = _get_token(); + + if (tk.type == TK_BRACKET_CLOSE) { + r_is_unknown_size = true; + } else { + if (tk.type != TK_INT_CONSTANT || ((int)tk.constant) <= 0) { + _set_tkpos(pos); + int array_size = 0; + Node *n = _parse_array_size(p_block, p_function_info, array_size); + if (!n) { + return ERR_PARSE_ERROR; + } + p_decl->size = array_size; + p_node->size_expression = n; + } else if (((int)tk.constant) > 0) { + p_decl->size = (uint32_t)tk.constant; + } + + if (p_decl->size <= 0) { + _set_error("Expected single integer constant > 0"); + return ERR_PARSE_ERROR; + } + + tk = _get_token(); + if (tk.type != TK_BRACKET_CLOSE) { + _set_error("Expected ']'"); + return ERR_PARSE_ERROR; + } + + r_array_size = p_decl->size; + } + + return OK; +} + ShaderLanguage::Node *ShaderLanguage::_parse_array_constructor(BlockNode *p_block, const FunctionInfo &p_function_info) { DataType type = TYPE_VOID; String struct_name = ""; @@ -5885,11 +6376,46 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun Node *vardecl = nullptr; while (true) { - if (tk.type != TK_IDENTIFIER) { - _set_error("Expected identifier after type"); + bool unknown_size = false; + int array_size = 0; + + ArrayDeclarationNode *anode = nullptr; + ArrayDeclarationNode::Declaration adecl; + + if (tk.type != TK_IDENTIFIER && tk.type != TK_BRACKET_OPEN) { + _set_error("Expected identifier or '[' after type."); return ERR_PARSE_ERROR; } + if (tk.type == TK_BRACKET_OPEN) { + anode = alloc_node<ArrayDeclarationNode>(); + + if (is_struct) { + anode->struct_name = struct_name; + anode->datatype = TYPE_STRUCT; + } else { + anode->datatype = type; + } + + anode->precision = precision; + anode->is_const = is_const; + vardecl = (Node *)anode; + + adecl.size = 0U; + adecl.single_expression = false; + + Error error = _parse_local_array_size(p_block, p_function_info, anode, &adecl, array_size, unknown_size); + if (error != OK) { + return error; + } + tk = _get_token(); + + if (tk.type != TK_IDENTIFIER) { + _set_error("Expected identifier!"); + return ERR_PARSE_ERROR; + } + } + StringName name = tk.text; ShaderLanguage::IdentifierType itype; if (_find_identifier(p_block, true, p_function_info, name, (ShaderLanguage::DataType *)nullptr, &itype)) { @@ -5899,6 +6425,8 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun } } + adecl.name = name; + #ifdef DEBUG_ENABLED if (check_warnings && HAS_WARNING(ShaderWarning::UNUSED_LOCAL_VARIABLE_FLAG)) { if (p_block && p_block->parent_function) { @@ -5917,95 +6445,47 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun var.type = type; var.precision = precision; var.line = tk_line; - var.array_size = 0; + var.array_size = array_size; var.is_const = is_const; var.struct_name = struct_name; tk = _get_token(); if (tk.type == TK_BRACKET_OPEN) { - bool unknown_size = false; + if (var.array_size > 0 || unknown_size) { + _set_error("Array size is already defined!"); + return ERR_PARSE_ERROR; + } if (RenderingServer::get_singleton()->is_low_end() && is_const) { _set_error("Local const arrays are supported only on high-end platform!"); return ERR_PARSE_ERROR; } - ArrayDeclarationNode *node = alloc_node<ArrayDeclarationNode>(); + anode = alloc_node<ArrayDeclarationNode>(); if (is_struct) { - node->struct_name = struct_name; - node->datatype = TYPE_STRUCT; + anode->struct_name = struct_name; + anode->datatype = TYPE_STRUCT; } else { - node->datatype = type; + anode->datatype = type; } - node->precision = precision; - node->is_const = is_const; - vardecl = (Node *)node; - - ArrayDeclarationNode::Declaration decl; - decl.name = name; - decl.size = 0U; - decl.single_expression = false; - - pos = _get_tkpos(); - tk = _get_token(); - - if (tk.type == TK_BRACKET_CLOSE) { - unknown_size = true; - } else { - if (tk.type != TK_INT_CONSTANT || ((int)tk.constant) <= 0) { - _set_tkpos(pos); - Node *n = _parse_and_reduce_expression(p_block, p_function_info); - if (n) { - if (n->type == Node::TYPE_VARIABLE) { - VariableNode *vn = static_cast<VariableNode *>(n); - if (vn) { - ConstantNode::Value v; - DataType data_type; - - _find_identifier(p_block, false, p_function_info, vn->name, &data_type, nullptr, &is_const, nullptr, nullptr, &v); - - if (is_const) { - if (data_type == TYPE_INT) { - int32_t value = v.sint; - if (value > 0) { - node->size_expression = n; - decl.size = (uint32_t)value; - } - } else if (data_type == TYPE_UINT) { - uint32_t value = v.uint; - if (value > 0U) { - node->size_expression = n; - decl.size = value; - } - } - } - } - } else if (n->type == Node::TYPE_OPERATOR) { - _set_error("Array size expressions are not yet implemented."); - return ERR_PARSE_ERROR; - } - } - } else if (((int)tk.constant) > 0) { - decl.size = (uint32_t)tk.constant; - } + anode->precision = precision; + anode->is_const = is_const; + vardecl = (Node *)anode; - if (decl.size == 0U) { - _set_error("Expected integer constant > 0 or ']'"); - return ERR_PARSE_ERROR; - } - tk = _get_token(); + adecl.size = 0U; + adecl.single_expression = false; - if (tk.type != TK_BRACKET_CLOSE) { - _set_error("Expected ']'"); - return ERR_PARSE_ERROR; - } - var.array_size = decl.size; + Error error = _parse_local_array_size(p_block, p_function_info, anode, &adecl, var.array_size, unknown_size); + if (error != OK) { + return error; } + tk = _get_token(); + } + if (var.array_size > 0 || unknown_size) { bool full_def = false; - tk = _get_token(); if (tk.type == TK_OP_ASSIGN) { if (RenderingServer::get_singleton()->is_low_end()) { _set_error("Array initialization is supported only on high-end platform!"); @@ -6024,7 +6504,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun return ERR_PARSE_ERROR; } else { if (unknown_size) { - decl.size = n->get_array_size(); + adecl.size = n->get_array_size(); var.array_size = n->get_array_size(); } @@ -6032,8 +6512,8 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun return ERR_PARSE_ERROR; } - decl.single_expression = true; - decl.initializer.push_back(n); + adecl.single_expression = true; + adecl.initializer.push_back(n); } tk = _get_token(); @@ -6172,7 +6652,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun return ERR_PARSE_ERROR; } - if (node->is_const && n->type == Node::TYPE_OPERATOR && ((OperatorNode *)n)->op == OP_CALL) { + if (anode->is_const && n->type == Node::TYPE_OPERATOR && ((OperatorNode *)n)->op == OP_CALL) { _set_error("Expected constant expression"); return ERR_PARSE_ERROR; } @@ -6183,13 +6663,13 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun tk = _get_token(); if (tk.type == TK_COMMA) { - decl.initializer.push_back(n); + adecl.initializer.push_back(n); continue; } else if (!curly && tk.type == TK_PARENTHESIS_CLOSE) { - decl.initializer.push_back(n); + adecl.initializer.push_back(n); break; } else if (curly && tk.type == TK_CURLY_BRACKET_CLOSE) { - decl.initializer.push_back(n); + adecl.initializer.push_back(n); break; } else { if (curly) { @@ -6201,9 +6681,9 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun } } if (unknown_size) { - decl.size = decl.initializer.size(); - var.array_size = decl.initializer.size(); - } else if (decl.initializer.size() != var.array_size) { + adecl.size = adecl.initializer.size(); + var.array_size = adecl.initializer.size(); + } else if (adecl.initializer.size() != var.array_size) { _set_error("Array size mismatch"); return ERR_PARSE_ERROR; } @@ -6215,13 +6695,13 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun _set_error("Expected array initialization"); return ERR_PARSE_ERROR; } - if (node->is_const) { + if (anode->is_const) { _set_error("Expected initialization of constant"); return ERR_PARSE_ERROR; } } - node->declarations.push_back(decl); + anode->declarations.push_back(adecl); } else if (tk.type == TK_OP_ASSIGN) { VariableDeclarationNode *node = alloc_node<VariableDeclarationNode>(); if (is_struct) { @@ -7068,8 +7548,23 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct _set_error("void datatype not allowed here"); return ERR_PARSE_ERROR; } - tk = _get_token(); + + if (tk.type != TK_IDENTIFIER && tk.type != TK_BRACKET_OPEN) { + _set_error("Expected identifier or '['."); + return ERR_PARSE_ERROR; + } + + int array_size = 0; + + if (tk.type == TK_BRACKET_OPEN) { + Error error = _parse_global_array_size(array_size); + if (error != OK) { + return error; + } + tk = _get_token(); + } + if (tk.type != TK_IDENTIFIER) { _set_error("Expected identifier!"); return ERR_PARSE_ERROR; @@ -7080,41 +7575,29 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct member->datatype = type; member->struct_name = struct_name; member->name = tk.text; + member->array_size = array_size; if (member_names.has(member->name)) { _set_error("Redefinition of '" + String(member->name) + "'"); return ERR_PARSE_ERROR; } member_names.insert(member->name); - tk = _get_token(); - if (tk.type == TK_BRACKET_OPEN) { - tk = _get_token(); - if (tk.type == TK_INT_CONSTANT && tk.constant > 0) { - member->array_size = (int)tk.constant; - tk = _get_token(); - if (tk.type == TK_BRACKET_CLOSE) { - tk = _get_token(); - if (tk.type != TK_SEMICOLON) { - _set_error("Expected ';'"); - return ERR_PARSE_ERROR; - } - } else { - _set_error("Expected ']'"); - return ERR_PARSE_ERROR; - } - } else { - _set_error("Expected single integer constant > 0"); - return ERR_PARSE_ERROR; + if (tk.type == TK_BRACKET_OPEN) { + Error error = _parse_global_array_size(member->array_size); + if (error != OK) { + return error; } + tk = _get_token(); } - st_node->members.push_back(member); if (tk.type != TK_SEMICOLON) { - _set_error("Expected ']' or ';'"); + _set_error("Expected ';'"); return ERR_PARSE_ERROR; } + + st_node->members.push_back(member); member_count++; } } @@ -7223,23 +7706,17 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct tk = _get_token(); - if (tk.type == TK_BRACKET_OPEN) { - tk = _get_token(); - - if (tk.type == TK_INT_CONSTANT && tk.constant > 0) { - array_size = (int)tk.constant; + if (tk.type != TK_IDENTIFIER && tk.type != TK_BRACKET_OPEN) { + _set_error("Expected identifier or '['."); + return ERR_PARSE_ERROR; + } - tk = _get_token(); - if (tk.type == TK_BRACKET_CLOSE) { - tk = _get_token(); - } else { - _set_error("Expected ']'"); - return ERR_PARSE_ERROR; - } - } else { - _set_error("Expected integer constant > 0"); - return ERR_PARSE_ERROR; + if (tk.type == TK_BRACKET_OPEN) { + Error error = _parse_global_array_size(array_size); + if (error != OK) { + return error; } + tk = _get_token(); } if (tk.type != TK_IDENTIFIER) { @@ -7283,26 +7760,11 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct tk = _get_token(); if (tk.type == TK_BRACKET_OPEN) { - if (uniform2.array_size > 0) { - _set_error("Array size is already defined!"); - return ERR_PARSE_ERROR; + Error error = _parse_global_array_size(uniform2.array_size); + if (error != OK) { + return error; } tk = _get_token(); - - if (tk.type == TK_INT_CONSTANT && tk.constant > 0) { - uniform2.array_size = (int)tk.constant; - - tk = _get_token(); - if (tk.type == TK_BRACKET_CLOSE) { - tk = _get_token(); - } else { - _set_error("Expected ']'"); - return ERR_PARSE_ERROR; - } - } else { - _set_error("Expected integer constant > 0"); - return ERR_PARSE_ERROR; - } } if (is_sampler_type(type)) { @@ -8800,10 +9262,16 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct } int idx2 = 0; - int out_arg = -1; + Set<int> out_args; while (builtin_func_out_args[idx2].name != nullptr) { if (builtin_func_out_args[idx2].name == builtin_func_defs[idx].name) { - out_arg = builtin_func_out_args[idx2].argument; + for (int i = 0; i < BuiltinFuncOutArgs::MAX_ARGS; i++) { + int arg = builtin_func_out_args[idx2].arguments[i]; + if (arg == -1) { + break; + } + out_args.insert(arg); + } break; } idx2++; @@ -8840,7 +9308,7 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct calltip += char32_t(0xFFFF); } - if (out_arg >= 0 && i == out_arg) { + if (out_args.has(i)) { calltip += "out "; } diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h index 1444546f05..c82f71d10d 100644 --- a/servers/rendering/shader_language.h +++ b/servers/rendering/shader_language.h @@ -949,8 +949,16 @@ private: }; struct BuiltinFuncOutArgs { //arguments used as out in built in functions + enum { MAX_ARGS = 2 }; const char *name; - int argument; + const int arguments[MAX_ARGS]; + }; + + struct BuiltinFuncConstArgs { + const char *name; + int arg; + int min; + int max; }; CompletionType completion_type; @@ -966,6 +974,7 @@ private: bool _get_completable_identifier(BlockNode *p_block, CompletionType p_type, StringName &identifier); static const BuiltinFuncDef builtin_func_defs[]; static const BuiltinFuncOutArgs builtin_func_out_args[]; + static const BuiltinFuncConstArgs builtin_func_const_args[]; Error _validate_datatype(DataType p_type); bool _compare_datatypes(DataType p_datatype_a, String p_datatype_name_a, int p_array_size_a, DataType p_datatype_b, String p_datatype_name_b, int p_array_size_b); @@ -979,6 +988,10 @@ private: bool _validate_varying_using(ShaderNode::Varying &p_varying, String *r_message); bool _check_node_constness(const Node *p_node) const; + Node *_parse_array_size(BlockNode *p_block, const FunctionInfo &p_function_info, int &r_array_size); + Error _parse_global_array_size(int &r_array_size); + Error _parse_local_array_size(BlockNode *p_block, const FunctionInfo &p_function_info, ArrayDeclarationNode *p_node, ArrayDeclarationNode::Declaration *p_decl, int &r_array_size, bool &r_is_unknown_size); + Node *_parse_expression(BlockNode *p_block, const FunctionInfo &p_function_info); Node *_parse_array_constructor(BlockNode *p_block, const FunctionInfo &p_function_info); Node *_parse_array_constructor(BlockNode *p_block, const FunctionInfo &p_function_info, DataType p_type, const StringName &p_struct_name, int p_array_size); diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index 93919a5ec6..b3efe840b6 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -934,7 +934,7 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa } } - ERR_FAIL_COND_V_MSG((bsformat) != (format & (ARRAY_FORMAT_VERTEX | ARRAY_FORMAT_NORMAL | ARRAY_FORMAT_TANGENT)), ERR_INVALID_PARAMETER, "Blend shape format must match the main array format for Vertex, Normal and Tangent arrays."); + ERR_FAIL_COND_V_MSG((bsformat & RS::ARRAY_FORMAT_BLEND_SHAPE_MASK) != (format & RS::ARRAY_FORMAT_BLEND_SHAPE_MASK), ERR_INVALID_PARAMETER, "Blend shape format must match the main array format for Vertex, Normal and Tangent arrays."); } } @@ -2269,12 +2269,6 @@ void RenderingServer::_bind_methods() { BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_CLUSTER_REFLECTION_PROBES); BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_OCCLUDERS); - BIND_ENUM_CONSTANT(VIEWPORT_SCALE_3D_DISABLED); - BIND_ENUM_CONSTANT(VIEWPORT_SCALE_3D_75_PERCENT); - BIND_ENUM_CONSTANT(VIEWPORT_SCALE_3D_50_PERCENT); - BIND_ENUM_CONSTANT(VIEWPORT_SCALE_3D_33_PERCENT); - BIND_ENUM_CONSTANT(VIEWPORT_SCALE_3D_25_PERCENT); - /* SKY API */ ClassDB::bind_method(D_METHOD("sky_create"), &RenderingServer::sky_create); @@ -2817,11 +2811,11 @@ RenderingServer::RenderingServer() { "rendering/vulkan/rendering/back_end", PROPERTY_HINT_ENUM, "Forward Clustered (Supports Desktop Only),Forward Mobile (Supports Desktop and Mobile)")); - GLOBAL_DEF("rendering/3d/viewport/scale", 0); + GLOBAL_DEF("rendering/3d/viewport/scale", 1.0); ProjectSettings::get_singleton()->set_custom_property_info("rendering/3d/viewport/scale", - PropertyInfo(Variant::INT, + PropertyInfo(Variant::FLOAT, "rendering/3d/viewport/scale", - PROPERTY_HINT_ENUM, "Disabled,75%,50%,33%,25%")); + PROPERTY_HINT_RANGE, "0.25,2.0,0.01")); GLOBAL_DEF("rendering/shader_compiler/shader_cache/enabled", true); GLOBAL_DEF("rendering/shader_compiler/shader_cache/compress", true); diff --git a/servers/rendering_server.h b/servers/rendering_server.h index 2dffa6bc75..b50da66d03 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -752,19 +752,10 @@ public: CANVAS_ITEM_TEXTURE_REPEAT_MAX, }; - enum ViewportScale3D { - VIEWPORT_SCALE_3D_DISABLED, - VIEWPORT_SCALE_3D_75_PERCENT, - VIEWPORT_SCALE_3D_50_PERCENT, - VIEWPORT_SCALE_3D_33_PERCENT, - VIEWPORT_SCALE_3D_25_PERCENT, - VIEWPORT_SCALE_3D_MAX, - }; - virtual RID viewport_create() = 0; virtual void viewport_set_use_xr(RID p_viewport, bool p_use_xr) = 0; - virtual void viewport_set_scale_3d(RID p_viewport, ViewportScale3D p_scale_3d) = 0; + virtual void viewport_set_scale_3d(RID p_viewport, float p_scale_3d) = 0; virtual void viewport_set_size(RID p_viewport, int p_width, int p_height) = 0; virtual void viewport_set_active(RID p_viewport, bool p_active) = 0; virtual void viewport_set_parent_viewport(RID p_viewport, RID p_parent_viewport) = 0; @@ -1553,7 +1544,6 @@ VARIANT_ENUM_CAST(RenderingServer::ViewportDebugDraw); VARIANT_ENUM_CAST(RenderingServer::ViewportOcclusionCullingBuildQuality); VARIANT_ENUM_CAST(RenderingServer::ViewportSDFOversize); VARIANT_ENUM_CAST(RenderingServer::ViewportSDFScale); -VARIANT_ENUM_CAST(RenderingServer::ViewportScale3D); VARIANT_ENUM_CAST(RenderingServer::SkyMode); VARIANT_ENUM_CAST(RenderingServer::EnvironmentBG); VARIANT_ENUM_CAST(RenderingServer::EnvironmentAmbientSource); diff --git a/servers/xr_server.cpp b/servers/xr_server.cpp index f6e6e5953f..780bd10fc5 100644 --- a/servers/xr_server.cpp +++ b/servers/xr_server.cpp @@ -41,7 +41,7 @@ XRServer *XRServer::get_singleton() { void XRServer::_bind_methods() { ClassDB::bind_method(D_METHOD("get_world_scale"), &XRServer::get_world_scale); - ClassDB::bind_method(D_METHOD("set_world_scale"), &XRServer::set_world_scale); + ClassDB::bind_method(D_METHOD("set_world_scale", "scale"), &XRServer::set_world_scale); ClassDB::bind_method(D_METHOD("get_reference_frame"), &XRServer::get_reference_frame); ClassDB::bind_method(D_METHOD("center_on_hmd", "rotation_mode", "keep_height"), &XRServer::center_on_hmd); ClassDB::bind_method(D_METHOD("get_hmd_transform"), &XRServer::get_hmd_transform); |