feat: modules moved and engine moved to submodule

This commit is contained in:
Jan van der Weide 2025-04-12 18:40:44 +02:00
parent dfb5e645cd
commit c33d2130cc
5136 changed files with 225275 additions and 64485 deletions

View file

@ -26,12 +26,19 @@ if env["xaudio2"]:
print_error("Target platform '{}' does not support the XAudio2 audio driver".format(env["platform"]))
Exit(255)
SConscript("xaudio2/SCsub")
# Shared Apple platform drivers
if env["platform"] in ["macos", "ios"]:
SConscript("apple/SCsub")
# Accessibility
if env["accesskit"] and env["platform"] in ["macos", "windows", "linuxbsd"]:
SConscript("accesskit/SCsub")
# Midi drivers
SConscript("alsamidi/SCsub")
SConscript("coremidi/SCsub")
if env["platform"] in ["macos", "ios"]:
SConscript("coremidi/SCsub")
SConscript("winmidi/SCsub")
# Graphics drivers

View file

@ -0,0 +1,16 @@
#!/usr/bin/env python
from misc.utility.scons_hints import *
Import("env")
# Driver source files
env.add_source_files(env.drivers_sources, "accessibility_driver_accesskit.cpp")
if env["accesskit_sdk_path"] == "":
if env["platform"] == "windows":
env.add_source_files(env.drivers_sources, "dynwrappers/accesskit-dll_wrap.c")
if env["platform"] == "macos":
env.add_source_files(env.drivers_sources, "dynwrappers/accesskit-dylib_wrap.c")
if env["platform"] == "linuxbsd":
env.add_source_files(env.drivers_sources, "dynwrappers/accesskit-so_wrap.c")
env.Prepend(CPPPATH=["#thirdparty/accesskit/include"])

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,197 @@
/**************************************************************************/
/* accessibility_driver_accesskit.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifdef ACCESSKIT_ENABLED
#include "core/templates/rid_owner.h"
#include "servers/display_server.h"
#ifdef ACCESSKIT_DYNAMIC
#ifdef LINUXBSD_ENABLED
#include "drivers/accesskit/dynwrappers/accesskit-so_wrap.h"
#endif
#ifdef MACOS_ENABLED
#include "drivers/accesskit/dynwrappers/accesskit-dylib_wrap.h"
#endif
#ifdef WINDOWS_ENABLED
#include "drivers/accesskit/dynwrappers/accesskit-dll_wrap.h"
#endif
#else
#include <accesskit.h>
#endif
class AccessibilityDriverAccessKit : public AccessibilityDriver {
static AccessibilityDriverAccessKit *singleton;
struct AccessibilityElement {
HashMap<accesskit_action, Callable> actions;
DisplayServer::WindowID window_id = DisplayServer::INVALID_WINDOW_ID;
RID parent;
LocalVector<RID> children;
Vector3i run;
Variant meta;
String name;
String name_extra_info;
accesskit_role role = ACCESSKIT_ROLE_UNKNOWN;
accesskit_node *node = nullptr;
};
mutable RID_PtrOwner<AccessibilityElement> rid_owner;
struct WindowData {
// Adapter.
#ifdef WINDOWS_ENABLED
accesskit_windows_subclassing_adapter *adapter = nullptr;
#endif
#ifdef MACOS_ENABLED
accesskit_macos_subclassing_adapter *adapter = nullptr;
#endif
#ifdef LINUXBSD_ENABLED
accesskit_unix_adapter *adapter = nullptr;
#endif
RID root_id;
HashSet<RID> update;
};
RID focus;
HashMap<DisplayServer::WindowID, WindowData> windows;
HashMap<DisplayServer::AccessibilityRole, accesskit_role> role_map;
HashMap<DisplayServer::AccessibilityAction, accesskit_action> action_map;
_FORCE_INLINE_ accesskit_role _accessibility_role(DisplayServer::AccessibilityRole p_role) const;
_FORCE_INLINE_ accesskit_action _accessibility_action(DisplayServer::AccessibilityAction p_action) const;
void _free_recursive(WindowData *p_wd, const RID &p_id);
_FORCE_INLINE_ void _ensure_node(const RID &p_id, AccessibilityElement *p_ae);
static void _accessibility_action_callback(struct accesskit_action_request *p_request, void *p_user_data);
static accesskit_tree_update *_accessibility_initial_tree_update_callback(void *p_user_data);
static void _accessibility_deactivation_callback(void *p_user_data);
static accesskit_tree_update *_accessibility_build_tree_update(void *p_user_data);
bool in_accessibility_update = false;
Callable update_cb;
public:
Error init() override;
bool window_create(DisplayServer::WindowID p_window_id, void *p_handle) override;
void window_destroy(DisplayServer::WindowID p_window_id) override;
RID accessibility_create_element(DisplayServer::WindowID p_window_id, DisplayServer::AccessibilityRole p_role) override;
RID accessibility_create_sub_element(const RID &p_parent_rid, DisplayServer::AccessibilityRole p_role, int p_insert_pos = -1) override;
virtual RID accessibility_create_sub_text_edit_elements(const RID &p_parent_rid, const RID &p_shaped_text, float p_min_height, int p_insert_pos = -1) override;
bool accessibility_has_element(const RID &p_id) const override;
void accessibility_free_element(const RID &p_id) override;
void accessibility_element_set_meta(const RID &p_id, const Variant &p_meta) override;
Variant accessibility_element_get_meta(const RID &p_id) const override;
void accessibility_update_if_active(const Callable &p_callable) override;
void accessibility_update_set_focus(const RID &p_id) override;
RID accessibility_get_window_root(DisplayServer::WindowID p_window_id) const override;
void accessibility_set_window_rect(DisplayServer::WindowID p_window_id, const Rect2 &p_rect_out, const Rect2 &p_rect_in) override;
void accessibility_set_window_focused(DisplayServer::WindowID p_window_id, bool p_focused) override;
void accessibility_update_set_role(const RID &p_id, DisplayServer::AccessibilityRole p_role) override;
void accessibility_update_set_name(const RID &p_id, const String &p_name) override;
void accessibility_update_set_extra_info(const RID &p_id, const String &p_name_extra_info) override;
void accessibility_update_set_description(const RID &p_id, const String &p_description) override;
void accessibility_update_set_value(const RID &p_id, const String &p_value) override;
void accessibility_update_set_tooltip(const RID &p_id, const String &p_tooltip) override;
void accessibility_update_set_bounds(const RID &p_id, const Rect2 &p_rect) override;
void accessibility_update_set_transform(const RID &p_id, const Transform2D &p_transform) override;
void accessibility_update_add_child(const RID &p_id, const RID &p_child_id) override;
void accessibility_update_add_related_controls(const RID &p_id, const RID &p_related_id) override;
void accessibility_update_add_related_details(const RID &p_id, const RID &p_related_id) override;
void accessibility_update_add_related_described_by(const RID &p_id, const RID &p_related_id) override;
void accessibility_update_add_related_flow_to(const RID &p_id, const RID &p_related_id) override;
void accessibility_update_add_related_labeled_by(const RID &p_id, const RID &p_related_id) override;
void accessibility_update_add_related_radio_group(const RID &p_id, const RID &p_related_id) override;
void accessibility_update_set_active_descendant(const RID &p_id, const RID &p_other_id) override;
void accessibility_update_set_next_on_line(const RID &p_id, const RID &p_other_id) override;
void accessibility_update_set_previous_on_line(const RID &p_id, const RID &p_other_id) override;
void accessibility_update_set_member_of(const RID &p_id, const RID &p_group_id) override;
void accessibility_update_set_in_page_link_target(const RID &p_id, const RID &p_other_id) override;
void accessibility_update_set_error_message(const RID &p_id, const RID &p_other_id) override;
void accessibility_update_set_live(const RID &p_id, DisplayServer::AccessibilityLiveMode p_live) override;
void accessibility_update_add_action(const RID &p_id, DisplayServer::AccessibilityAction p_action, const Callable &p_callable) override;
void accessibility_update_add_custom_action(const RID &p_id, int p_action_id, const String &p_action_description) override;
void accessibility_update_set_table_row_count(const RID &p_id, int p_count) override;
void accessibility_update_set_table_column_count(const RID &p_id, int p_count) override;
void accessibility_update_set_table_row_index(const RID &p_id, int p_index) override;
void accessibility_update_set_table_column_index(const RID &p_id, int p_index) override;
void accessibility_update_set_table_cell_position(const RID &p_id, int p_row_index, int p_column_index) override;
void accessibility_update_set_table_cell_span(const RID &p_id, int p_row_span, int p_column_span) override;
void accessibility_update_set_list_item_count(const RID &p_id, int p_size) override;
void accessibility_update_set_list_item_index(const RID &p_id, int p_index) override;
void accessibility_update_set_list_item_level(const RID &p_id, int p_level) override;
void accessibility_update_set_list_item_selected(const RID &p_id, bool p_selected) override;
void accessibility_update_set_list_item_expanded(const RID &p_id, bool p_expanded) override;
void accessibility_update_set_popup_type(const RID &p_id, DisplayServer::AccessibilityPopupType p_popup) override;
void accessibility_update_set_checked(const RID &p_id, bool p_checekd) override;
void accessibility_update_set_num_value(const RID &p_id, double p_position) override;
void accessibility_update_set_num_range(const RID &p_id, double p_min, double p_max) override;
void accessibility_update_set_num_step(const RID &p_id, double p_step) override;
void accessibility_update_set_num_jump(const RID &p_id, double p_jump) override;
void accessibility_update_set_scroll_x(const RID &p_id, double p_position) override;
void accessibility_update_set_scroll_x_range(const RID &p_id, double p_min, double p_max) override;
void accessibility_update_set_scroll_y(const RID &p_id, double p_position) override;
void accessibility_update_set_scroll_y_range(const RID &p_id, double p_min, double p_max) override;
void accessibility_update_set_text_decorations(const RID &p_id, bool p_underline, bool p_strikethrough, bool p_overline) override;
void accessibility_update_set_text_align(const RID &p_id, HorizontalAlignment p_align) override;
void accessibility_update_set_text_selection(const RID &p_id, const RID &p_text_start_id, int p_start_char, const RID &p_text_end_id, int p_end_char) override;
void accessibility_update_set_flag(const RID &p_id, DisplayServer::AccessibilityFlags p_flag, bool p_value) override;
void accessibility_update_set_classname(const RID &p_id, const String &p_classname) override;
void accessibility_update_set_placeholder(const RID &p_id, const String &p_placeholder) override;
void accessibility_update_set_language(const RID &p_id, const String &p_language) override;
void accessibility_update_set_text_orientation(const RID &p_id, bool p_vertical) override;
void accessibility_update_set_list_orientation(const RID &p_id, bool p_vertical) override;
void accessibility_update_set_shortcut(const RID &p_id, const String &p_shortcut) override;
void accessibility_update_set_url(const RID &p_id, const String &p_url) override;
void accessibility_update_set_role_description(const RID &p_id, const String &p_description) override;
void accessibility_update_set_state_description(const RID &p_id, const String &p_description) override;
void accessibility_update_set_color_value(const RID &p_id, const Color &p_color) override;
void accessibility_update_set_background_color(const RID &p_id, const Color &p_color) override;
void accessibility_update_set_foreground_color(const RID &p_id, const Color &p_color) override;
AccessibilityDriverAccessKit();
~AccessibilityDriverAccessKit();
};
#endif // ACCESSKIT_ENABLED

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef AUDIO_DRIVER_ALSA_H
#define AUDIO_DRIVER_ALSA_H
#pragma once
#ifdef ALSA_ENABLED
@ -95,5 +94,3 @@ public:
};
#endif // ALSA_ENABLED
#endif // AUDIO_DRIVER_ALSA_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef MIDI_DRIVER_ALSAMIDI_H
#define MIDI_DRIVER_ALSAMIDI_H
#pragma once
#ifdef ALSAMIDI_ENABLED
@ -78,5 +77,3 @@ public:
};
#endif // ALSAMIDI_ENABLED
#endif // MIDI_DRIVER_ALSAMIDI_H

View file

@ -5,3 +5,4 @@ Import("env")
# Driver source files
env.add_source_files(env.drivers_sources, "*.mm")
env.add_source_files(env.drivers_sources, "*.cpp")

View file

@ -28,7 +28,10 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#include "core/input/input.h"
#include "core/input/input_enums.h"
#define Key _QKey
#import <GameController/GameController.h>
@ -43,6 +46,11 @@ struct GameController {
RumbleContext *rumble_context API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0)) = nil;
NSInteger ff_effect_timestamp = 0;
bool force_feedback = false;
bool double_nintendo_joycon_layout = false;
bool single_nintendo_joycon_layout = false;
bool axis_changed[(int)JoyAxis::MAX];
double axis_value[(int)JoyAxis::MAX];
GameController(int p_joy_id, GCController *p_controller);
~GameController();

View file

@ -30,7 +30,7 @@
#import "joypad_apple.h"
#include <CoreHaptics/CoreHaptics.h>
#import <CoreHaptics/CoreHaptics.h>
#import <os/log.h>
#include "core/config/project_settings.h"
@ -134,6 +134,11 @@ public:
GameController::GameController(int p_joy_id, GCController *p_controller) :
joy_id(p_joy_id), controller(p_controller) {
force_feedback = NO;
for (int i = 0; i < (int)JoyAxis::MAX; i++) {
axis_changed[i] = false;
axis_value[i] = 0.0;
}
if (@available(macOS 11.0, iOS 14.0, tvOS 14.0, *)) {
if (controller.haptics != nil) {
// Create a rumble context for the controller.
@ -144,6 +149,16 @@ GameController::GameController(int p_joy_id, GCController *p_controller) :
}
}
if (@available(macOS 10.15, iOS 13.0, tvOS 13.0, *)) {
if ([controller.productCategory isEqualToString:@"Switch Pro Controller"] || [controller.productCategory isEqualToString:@"Nintendo Switch Joy-Con (L/R)"]) {
double_nintendo_joycon_layout = true;
}
if ([controller.productCategory isEqualToString:@"Nintendo Switch Joy-Con (L)"] || [controller.productCategory isEqualToString:@"Nintendo Switch Joy-Con (R)"]) {
single_nintendo_joycon_layout = true;
}
}
int l_joy_id = joy_id;
auto BUTTON = [l_joy_id](JoyButton p_button) {
@ -152,13 +167,199 @@ GameController::GameController(int p_joy_id, GCController *p_controller) :
};
};
if (controller.extendedGamepad != nil) {
auto JOYSTICK_LEFT = ^(GCControllerDirectionPad *dpad, float xValue, float yValue) {
if (axis_value[(int)JoyAxis::LEFT_X] != xValue) {
axis_changed[(int)JoyAxis::LEFT_X] = true;
axis_value[(int)JoyAxis::LEFT_X] = xValue;
}
if (axis_value[(int)JoyAxis::LEFT_Y] != -yValue) {
axis_changed[(int)JoyAxis::LEFT_Y] = true;
axis_value[(int)JoyAxis::LEFT_Y] = -yValue;
}
};
auto JOYSTICK_RIGHT = ^(GCControllerDirectionPad *dpad, float xValue, float yValue) {
if (axis_value[(int)JoyAxis::RIGHT_X] != xValue) {
axis_changed[(int)JoyAxis::RIGHT_X] = true;
axis_value[(int)JoyAxis::RIGHT_X] = xValue;
}
if (axis_value[(int)JoyAxis::RIGHT_Y] != -yValue) {
axis_changed[(int)JoyAxis::RIGHT_Y] = true;
axis_value[(int)JoyAxis::RIGHT_Y] = -yValue;
}
};
auto TRIGGER_LEFT = ^(GCControllerButtonInput *button, float value, BOOL pressed) {
if (axis_value[(int)JoyAxis::TRIGGER_LEFT] != value) {
axis_changed[(int)JoyAxis::TRIGGER_LEFT] = true;
axis_value[(int)JoyAxis::TRIGGER_LEFT] = value;
}
};
auto TRIGGER_RIGHT = ^(GCControllerButtonInput *button, float value, BOOL pressed) {
if (axis_value[(int)JoyAxis::TRIGGER_RIGHT] != value) {
axis_changed[(int)JoyAxis::TRIGGER_RIGHT] = true;
axis_value[(int)JoyAxis::TRIGGER_RIGHT] = value;
}
};
if (@available(macOS 11.0, iOS 14.0, tvOS 14.0, *)) {
if (controller.physicalInputProfile != nil) {
GCPhysicalInputProfile *profile = controller.physicalInputProfile;
GCControllerButtonInput *buttonA = profile.buttons[GCInputButtonA];
GCControllerButtonInput *buttonB = profile.buttons[GCInputButtonB];
GCControllerButtonInput *buttonX = profile.buttons[GCInputButtonX];
GCControllerButtonInput *buttonY = profile.buttons[GCInputButtonY];
if (double_nintendo_joycon_layout) {
if (buttonA) {
buttonA.pressedChangedHandler = BUTTON(JoyButton::B);
}
if (buttonB) {
buttonB.pressedChangedHandler = BUTTON(JoyButton::A);
}
if (buttonX) {
buttonX.pressedChangedHandler = BUTTON(JoyButton::Y);
}
if (buttonY) {
buttonY.pressedChangedHandler = BUTTON(JoyButton::X);
}
} else if (single_nintendo_joycon_layout) {
if (buttonA) {
buttonA.pressedChangedHandler = BUTTON(JoyButton::A);
}
if (buttonB) {
buttonB.pressedChangedHandler = BUTTON(JoyButton::X);
}
if (buttonX) {
buttonX.pressedChangedHandler = BUTTON(JoyButton::B);
}
if (buttonY) {
buttonY.pressedChangedHandler = BUTTON(JoyButton::Y);
}
} else {
if (buttonA) {
buttonA.pressedChangedHandler = BUTTON(JoyButton::A);
}
if (buttonB) {
buttonB.pressedChangedHandler = BUTTON(JoyButton::B);
}
if (buttonX) {
buttonX.pressedChangedHandler = BUTTON(JoyButton::X);
}
if (buttonY) {
buttonY.pressedChangedHandler = BUTTON(JoyButton::Y);
}
}
GCControllerButtonInput *leftThumbstickButton = profile.buttons[GCInputLeftThumbstickButton];
GCControllerButtonInput *rightThumbstickButton = profile.buttons[GCInputRightThumbstickButton];
if (leftThumbstickButton) {
leftThumbstickButton.pressedChangedHandler = BUTTON(JoyButton::LEFT_STICK);
}
if (rightThumbstickButton) {
rightThumbstickButton.pressedChangedHandler = BUTTON(JoyButton::RIGHT_STICK);
}
GCControllerButtonInput *leftShoulder = profile.buttons[GCInputLeftShoulder];
GCControllerButtonInput *rightShoulder = profile.buttons[GCInputRightShoulder];
if (leftShoulder) {
leftShoulder.pressedChangedHandler = BUTTON(JoyButton::LEFT_SHOULDER);
}
if (rightShoulder) {
rightShoulder.pressedChangedHandler = BUTTON(JoyButton::RIGHT_SHOULDER);
}
GCControllerButtonInput *leftTrigger = profile.buttons[GCInputLeftTrigger];
GCControllerButtonInput *rightTrigger = profile.buttons[GCInputRightTrigger];
if (leftTrigger) {
leftTrigger.valueChangedHandler = TRIGGER_LEFT;
}
if (rightTrigger) {
rightTrigger.valueChangedHandler = TRIGGER_RIGHT;
}
GCControllerButtonInput *buttonMenu = profile.buttons[GCInputButtonMenu];
GCControllerButtonInput *buttonHome = profile.buttons[GCInputButtonHome];
GCControllerButtonInput *buttonOptions = profile.buttons[GCInputButtonOptions];
if (buttonMenu) {
buttonMenu.pressedChangedHandler = BUTTON(JoyButton::START);
}
if (buttonHome) {
buttonHome.pressedChangedHandler = BUTTON(JoyButton::GUIDE);
}
if (buttonOptions) {
buttonOptions.pressedChangedHandler = BUTTON(JoyButton::BACK);
}
// Xbox controller buttons.
if (@available(macOS 12.0, iOS 15.0, tvOS 15.0, *)) {
GCControllerButtonInput *buttonShare = profile.buttons[GCInputButtonShare];
if (buttonShare) {
buttonShare.pressedChangedHandler = BUTTON(JoyButton::MISC1);
}
}
GCControllerButtonInput *paddleButton1 = profile.buttons[GCInputXboxPaddleOne];
GCControllerButtonInput *paddleButton2 = profile.buttons[GCInputXboxPaddleTwo];
GCControllerButtonInput *paddleButton3 = profile.buttons[GCInputXboxPaddleThree];
GCControllerButtonInput *paddleButton4 = profile.buttons[GCInputXboxPaddleFour];
if (paddleButton1) {
paddleButton1.pressedChangedHandler = BUTTON(JoyButton::PADDLE1);
}
if (paddleButton2) {
paddleButton2.pressedChangedHandler = BUTTON(JoyButton::PADDLE2);
}
if (paddleButton3) {
paddleButton3.pressedChangedHandler = BUTTON(JoyButton::PADDLE3);
}
if (paddleButton4) {
paddleButton4.pressedChangedHandler = BUTTON(JoyButton::PADDLE4);
}
GCControllerDirectionPad *leftThumbstick = profile.dpads[GCInputLeftThumbstick];
if (leftThumbstick) {
leftThumbstick.valueChangedHandler = JOYSTICK_LEFT;
}
GCControllerDirectionPad *rightThumbstick = profile.dpads[GCInputRightThumbstick];
if (rightThumbstick) {
rightThumbstick.valueChangedHandler = JOYSTICK_RIGHT;
}
GCControllerDirectionPad *dpad = nil;
if (controller.extendedGamepad != nil) {
dpad = controller.extendedGamepad.dpad;
} else if (controller.microGamepad != nil) {
dpad = controller.microGamepad.dpad;
}
if (dpad) {
dpad.up.pressedChangedHandler = BUTTON(JoyButton::DPAD_UP);
dpad.down.pressedChangedHandler = BUTTON(JoyButton::DPAD_DOWN);
dpad.left.pressedChangedHandler = BUTTON(JoyButton::DPAD_LEFT);
dpad.right.pressedChangedHandler = BUTTON(JoyButton::DPAD_RIGHT);
}
}
} else if (controller.extendedGamepad != nil) {
GCExtendedGamepad *gamepad = controller.extendedGamepad;
gamepad.buttonA.pressedChangedHandler = BUTTON(JoyButton::A);
gamepad.buttonB.pressedChangedHandler = BUTTON(JoyButton::B);
gamepad.buttonX.pressedChangedHandler = BUTTON(JoyButton::X);
gamepad.buttonY.pressedChangedHandler = BUTTON(JoyButton::Y);
if (double_nintendo_joycon_layout) {
gamepad.buttonA.pressedChangedHandler = BUTTON(JoyButton::B);
gamepad.buttonB.pressedChangedHandler = BUTTON(JoyButton::A);
gamepad.buttonX.pressedChangedHandler = BUTTON(JoyButton::Y);
gamepad.buttonY.pressedChangedHandler = BUTTON(JoyButton::X);
} else if (single_nintendo_joycon_layout) {
gamepad.buttonA.pressedChangedHandler = BUTTON(JoyButton::A);
gamepad.buttonB.pressedChangedHandler = BUTTON(JoyButton::X);
gamepad.buttonX.pressedChangedHandler = BUTTON(JoyButton::B);
gamepad.buttonY.pressedChangedHandler = BUTTON(JoyButton::Y);
} else {
gamepad.buttonA.pressedChangedHandler = BUTTON(JoyButton::A);
gamepad.buttonB.pressedChangedHandler = BUTTON(JoyButton::B);
gamepad.buttonX.pressedChangedHandler = BUTTON(JoyButton::X);
gamepad.buttonY.pressedChangedHandler = BUTTON(JoyButton::Y);
}
gamepad.leftShoulder.pressedChangedHandler = BUTTON(JoyButton::LEFT_SHOULDER);
gamepad.rightShoulder.pressedChangedHandler = BUTTON(JoyButton::RIGHT_SHOULDER);
gamepad.dpad.up.pressedChangedHandler = BUTTON(JoyButton::DPAD_UP);
@ -166,21 +367,10 @@ GameController::GameController(int p_joy_id, GCController *p_controller) :
gamepad.dpad.left.pressedChangedHandler = BUTTON(JoyButton::DPAD_LEFT);
gamepad.dpad.right.pressedChangedHandler = BUTTON(JoyButton::DPAD_RIGHT);
gamepad.leftThumbstick.valueChangedHandler = ^(GCControllerDirectionPad *dpad, float xValue, float yValue) {
Input::get_singleton()->joy_axis(l_joy_id, JoyAxis::LEFT_X, xValue);
Input::get_singleton()->joy_axis(l_joy_id, JoyAxis::LEFT_Y, -yValue);
};
gamepad.rightThumbstick.valueChangedHandler = ^(GCControllerDirectionPad *dpad, float xValue, float yValue) {
Input::get_singleton()->joy_axis(l_joy_id, JoyAxis::RIGHT_X, xValue);
Input::get_singleton()->joy_axis(l_joy_id, JoyAxis::RIGHT_Y, -yValue);
};
gamepad.leftTrigger.valueChangedHandler = ^(GCControllerButtonInput *button, float value, BOOL pressed) {
Input::get_singleton()->joy_axis(l_joy_id, JoyAxis::TRIGGER_LEFT, value);
};
gamepad.rightTrigger.valueChangedHandler = ^(GCControllerButtonInput *button, float value, BOOL pressed) {
Input::get_singleton()->joy_axis(l_joy_id, JoyAxis::TRIGGER_RIGHT, value);
};
gamepad.leftThumbstick.valueChangedHandler = JOYSTICK_LEFT;
gamepad.rightThumbstick.valueChangedHandler = JOYSTICK_RIGHT;
gamepad.leftTrigger.valueChangedHandler = TRIGGER_LEFT;
gamepad.rightTrigger.valueChangedHandler = TRIGGER_RIGHT;
if (@available(macOS 10.14.1, iOS 12.1, tvOS 12.1, *)) {
gamepad.leftThumbstickButton.pressedChangedHandler = BUTTON(JoyButton::LEFT_STICK);
@ -313,7 +503,13 @@ void JoypadApple::add_joypad(GCController *p_controller) {
}
// Tell Godot about our new controller.
Input::get_singleton()->joy_connection_changed(joy_id, true, String::utf8(p_controller.vendorName.UTF8String));
char const *device_name;
if (@available(macOS 10.15, iOS 13.0, tvOS 13.0, *)) {
device_name = p_controller.productCategory.UTF8String;
} else {
device_name = p_controller.vendorName.UTF8String;
}
Input::get_singleton()->joy_connection_changed(joy_id, true, String::utf8(device_name));
// Assign our player index.
joypads.insert(joy_id, memnew(GameController(joy_id, p_controller)));
@ -404,6 +600,13 @@ void JoypadApple::process_joypads() {
int id = E.key;
GameController &joypad = *E.value;
for (int i = 0; i < (int)JoyAxis::MAX; i++) {
if (joypad.axis_changed[i]) {
joypad.axis_changed[i] = false;
Input::get_singleton()->joy_axis(id, (JoyAxis)i, joypad.axis_value[i]);
}
}
if (joypad.force_feedback) {
Input *input = Input::get_singleton();
uint64_t timestamp = input->get_joy_vibration_timestamp(id);

View file

@ -0,0 +1,129 @@
/**************************************************************************/
/* thread_apple.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#include "thread_apple.h"
#include "core/error/error_macros.h"
#include "core/object/script_language.h"
#include "core/string/ustring.h"
SafeNumeric<uint64_t> Thread::id_counter(1); // The first value after .increment() is 2, hence by default the main thread ID should be 1.
thread_local Thread::ID Thread::caller_id = Thread::id_counter.increment();
struct ThreadData {
Thread::Callback callback;
void *userdata;
Thread::ID caller_id;
};
void *Thread::thread_callback(void *p_data) {
ThreadData *thread_data = static_cast<ThreadData *>(p_data);
// Set the caller ID for this thread
caller_id = thread_data->caller_id;
ScriptServer::thread_enter(); // Scripts may need to attach a stack.
// Call the actual callback
thread_data->callback(thread_data->userdata);
ScriptServer::thread_exit();
// Clean up
memdelete(thread_data);
return nullptr;
}
Error Thread::set_name(const String &p_name) {
int err = pthread_setname_np(p_name.utf8().get_data());
return err == 0 ? OK : ERR_INVALID_PARAMETER;
}
Thread::ID Thread::start(Thread::Callback p_callback, void *p_user, const Settings &p_settings) {
ERR_FAIL_COND_V_MSG(id != UNASSIGNED_ID, UNASSIGNED_ID, "A Thread object has been re-started without wait_to_finish() having been called on it.");
id = id_counter.increment();
ThreadData *thread_data = memnew(ThreadData);
thread_data->callback = p_callback;
thread_data->userdata = p_user;
thread_data->caller_id = id;
// Create the thread
pthread_attr_t attr;
pthread_attr_init(&attr);
switch (p_settings.priority) {
case PRIORITY_LOW:
pthread_attr_set_qos_class_np(&attr, QOS_CLASS_UTILITY, 0);
break;
case PRIORITY_NORMAL:
pthread_attr_set_qos_class_np(&attr, QOS_CLASS_USER_INITIATED, 0);
break;
case PRIORITY_HIGH:
pthread_attr_set_qos_class_np(&attr, QOS_CLASS_USER_INTERACTIVE, 0);
break;
}
if (p_settings.stack_size > 0) {
pthread_attr_setstacksize(&attr, p_settings.stack_size);
}
// Create the thread
pthread_create(&pthread, &attr, thread_callback, thread_data);
// Clean up attributes
pthread_attr_destroy(&attr);
return id;
}
void Thread::wait_to_finish() {
ERR_FAIL_COND_MSG(id == UNASSIGNED_ID, "Attempt of waiting to finish on a thread that was never started.");
ERR_FAIL_COND_MSG(id == get_caller_id(), "Threads can't wait to finish on themselves, another thread must wait.");
int err = pthread_join(pthread, nullptr);
if (err != 0) {
ERR_FAIL_MSG("Thread::wait_to_finish() failed to join thread.");
}
pthread = pthread_t();
id = UNASSIGNED_ID;
}
Thread::~Thread() {
if (id != UNASSIGNED_ID) {
#ifdef DEBUG_ENABLED
WARN_PRINT(
"A Thread object is being destroyed without its completion having been realized.\n"
"Please call wait_to_finish() on it to ensure correct cleanup.");
#endif
pthread_detach(pthread);
}
}

View file

@ -0,0 +1,110 @@
/**************************************************************************/
/* thread_apple.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#include "core/templates/safe_refcount.h"
#include "core/typedefs.h"
#include <pthread.h>
#include <new> // For hardware interference size
class String;
class Thread {
public:
typedef void (*Callback)(void *p_userdata);
typedef uint64_t ID;
enum : ID {
UNASSIGNED_ID = 0,
MAIN_ID = 1
};
enum Priority {
PRIORITY_LOW,
PRIORITY_NORMAL,
PRIORITY_HIGH
};
struct Settings {
Priority priority;
/// Override the default stack size (0 means default)
uint64_t stack_size = 0;
Settings() { priority = PRIORITY_NORMAL; }
};
#if defined(__cpp_lib_hardware_interference_size)
GODOT_GCC_WARNING_PUSH_AND_IGNORE("-Winterference-size")
static constexpr size_t CACHE_LINE_BYTES = std::hardware_destructive_interference_size;
GODOT_GCC_WARNING_POP
#else
// At a negligible memory cost, we use a conservatively high value.
static constexpr size_t CACHE_LINE_BYTES = 128;
#endif
private:
friend class Main;
ID id = UNASSIGNED_ID;
pthread_t pthread;
static SafeNumeric<uint64_t> id_counter;
static thread_local ID caller_id;
static void *thread_callback(void *p_data);
static void make_main_thread() { caller_id = MAIN_ID; }
static void release_main_thread() { caller_id = id_counter.increment(); }
public:
_FORCE_INLINE_ static void yield() { pthread_yield_np(); }
_FORCE_INLINE_ ID get_id() const { return id; }
// get the ID of the caller thread
_FORCE_INLINE_ static ID get_caller_id() {
return caller_id;
}
// get the ID of the main thread
_FORCE_INLINE_ static ID get_main_id() { return MAIN_ID; }
_FORCE_INLINE_ static bool is_main_thread() { return caller_id == MAIN_ID; }
static Error set_name(const String &p_name);
ID start(Thread::Callback p_callback, void *p_user, const Settings &p_settings = Settings());
bool is_started() const { return id != UNASSIGNED_ID; }
/// Waits until thread is finished, and deallocates it.
void wait_to_finish();
Thread() = default;
~Thread();
};

View file

@ -26,7 +26,7 @@ thirdparty_sources = [
]
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
env_backtrace.Prepend(CPPPATH=[thirdparty_dir])
env_backtrace.Prepend(CPPEXTPATH=[thirdparty_dir])
env_thirdparty = env_backtrace.Clone()
env_thirdparty.disable_warnings()

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef AUDIO_DRIVER_COREAUDIO_H
#define AUDIO_DRIVER_COREAUDIO_H
#pragma once
#ifdef COREAUDIO_ENABLED
@ -126,5 +125,3 @@ public:
};
#endif // COREAUDIO_ENABLED
#endif // AUDIO_DRIVER_COREAUDIO_H

View file

@ -28,7 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#include "audio_driver_coreaudio.h"
#import "audio_driver_coreaudio.h"
#ifdef COREAUDIO_ENABLED

View file

@ -4,4 +4,4 @@ from misc.utility.scons_hints import *
Import("env")
# Driver source files
env.add_source_files(env.drivers_sources, "*.cpp")
env.add_source_files(env.drivers_sources, "*.mm")

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef MIDI_DRIVER_COREMIDI_H
#define MIDI_DRIVER_COREMIDI_H
#pragma once
#ifdef COREMIDI_ENABLED
@ -67,5 +66,3 @@ public:
};
#endif // COREMIDI_ENABLED
#endif // MIDI_DRIVER_COREMIDI_H

View file

@ -1,5 +1,5 @@
/**************************************************************************/
/* midi_driver_coremidi.cpp */
/* midi_driver_coremidi.mm */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@ -28,7 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#include "midi_driver_coremidi.h"
#import "midi_driver_coremidi.h"
#ifdef COREMIDI_ENABLED

View file

@ -15,15 +15,15 @@ thirdparty_obj = []
# DirectX Headers (must take precedence over Windows SDK's).
env.Prepend(CPPPATH=["#thirdparty/directx_headers/include/directx"])
env_d3d12_rdd.Prepend(CPPPATH=["#thirdparty/directx_headers/include/directx"])
env_d3d12_rdd.Prepend(CPPPATH=["#thirdparty/directx_headers/include/dxguids"])
env.Prepend(CPPEXTPATH=["#thirdparty/directx_headers/include/directx"])
env_d3d12_rdd.Prepend(CPPEXTPATH=["#thirdparty/directx_headers/include/directx"])
env_d3d12_rdd.Prepend(CPPEXTPATH=["#thirdparty/directx_headers/include/dxguids"])
# Direct3D 12 Memory Allocator.
env.Append(CPPPATH=["#thirdparty/d3d12ma"])
env_d3d12_rdd.Append(CPPPATH=["#thirdparty/d3d12ma"])
env.Append(CPPEXTPATH=["#thirdparty/d3d12ma"])
env_d3d12_rdd.Append(CPPEXTPATH=["#thirdparty/d3d12ma"])
# Agility SDK.
@ -38,7 +38,7 @@ if env["agility_sdk_path"] != "" and os.path.exists(env["agility_sdk_path"]):
if env["use_pix"]:
env_d3d12_rdd.Append(CPPDEFINES=["PIX_ENABLED"])
env_d3d12_rdd.Append(CPPPATH=[env["pix_path"] + "/Include"])
env_d3d12_rdd.Append(CPPEXTPATH=[env["pix_path"] + "/Include"])
# Mesa (SPIR-V to DXIL functionality).
@ -147,7 +147,7 @@ else:
env.Append(CCFLAGS=["-Wno-unknown-pragmas"])
# This is needed since rendering_device_d3d12.cpp needs to include some Mesa internals.
env_d3d12_rdd.Prepend(CPPPATH=mesa_private_inc_paths)
env_d3d12_rdd.Prepend(CPPEXTPATH=mesa_private_inc_paths)
# For the same reason as above, the defines must be the same as in the 3rd-party code itself.
env_d3d12_rdd.Append(CPPDEFINES=extra_defines)

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef D3D12_GODOT_NIR_BRIDGE_H
#define D3D12_GODOT_NIR_BRIDGE_H
#pragma once
#include <stdint.h>
@ -56,5 +55,3 @@ typedef struct GodotNirCallbacks {
#ifdef __cplusplus
}
#endif
#endif // D3D12_GODOT_NIR_BRIDGE_H

View file

@ -30,35 +30,4 @@
#include "rendering_context_driver_d3d12.h"
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
#pragma GCC diagnostic ignored "-Wshadow"
#pragma GCC diagnostic ignored "-Wswitch"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#pragma GCC diagnostic ignored "-Wduplicated-branches"
#pragma GCC diagnostic ignored "-Wunused-variable"
#pragma GCC diagnostic ignored "-Wsign-compare"
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#pragma GCC diagnostic ignored "-Wunused-function"
#pragma GCC diagnostic ignored "-Wnonnull-compare"
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#elif defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
#pragma clang diagnostic ignored "-Wstring-plus-int"
#pragma clang diagnostic ignored "-Wswitch"
#pragma clang diagnostic ignored "-Wmissing-field-initializers"
#pragma clang diagnostic ignored "-Wtautological-undefined-compare"
#pragma clang diagnostic ignored "-Wunused-variable"
#pragma clang diagnostic ignored "-Wunused-but-set-variable"
#pragma clang diagnostic ignored "-Wunused-function"
#pragma clang diagnostic ignored "-Wunused-private-field"
#pragma clang diagnostic ignored "-Wimplicit-fallthrough"
#endif
#if defined(_MSC_VER)
#pragma warning(disable : 4189 4505)
#endif
#include "thirdparty/d3d12ma/D3D12MemAlloc.cpp"
#include <D3D12MemAlloc.cpp>

View file

@ -28,12 +28,9 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef DXIL_HASH_H
#define DXIL_HASH_H
#pragma once
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
void compute_dxil_hash(const BYTE *pData, UINT byteCount, BYTE *pOutHash);
#endif // DXIL_HASH_H

View file

@ -37,27 +37,7 @@
#include "core/version.h"
#include "servers/rendering/rendering_device.h"
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
#pragma GCC diagnostic ignored "-Wshadow"
#pragma GCC diagnostic ignored "-Wswitch"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#elif defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
#pragma clang diagnostic ignored "-Wstring-plus-int"
#pragma clang diagnostic ignored "-Wswitch"
#pragma clang diagnostic ignored "-Wmissing-field-initializers"
#endif
#include "dxcapi.h"
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic pop
#elif defined(__clang__)
#pragma clang diagnostic pop
#endif
#include <dxcapi.h>
#if !defined(_MSC_VER)
#include <guiddef.h>

View file

@ -28,10 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef RENDERING_CONTEXT_DRIVER_D3D12_H
#define RENDERING_CONTEXT_DRIVER_D3D12_H
#pragma once
#include "core/error/error_list.h"
#include "core/os/mutex.h"
#include "core/string/ustring.h"
#include "core/templates/rid_owner.h"
@ -39,22 +37,6 @@
#include "servers/display_server.h"
#include "servers/rendering/rendering_context_driver.h"
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
#pragma GCC diagnostic ignored "-Wshadow"
#pragma GCC diagnostic ignored "-Wswitch"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#elif defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
#pragma clang diagnostic ignored "-Wstring-plus-int"
#pragma clang diagnostic ignored "-Wswitch"
#pragma clang diagnostic ignored "-Wmissing-field-initializers"
#pragma clang diagnostic ignored "-Wimplicit-fallthrough"
#endif
#if defined(AS)
#undef AS
#endif
@ -73,20 +55,14 @@
#include <dcomp.h>
#endif
#include "d3dx12.h"
#include <d3dx12.h>
#include <dxgi1_6.h>
#include <wrl/client.h>
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic pop
#elif defined(__clang__)
#pragma clang diagnostic pop
#endif
using Microsoft::WRL::ComPtr;
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
#define ARRAY_SIZE(a) std::size(a)
class RenderingContextDriverD3D12 : public RenderingContextDriver {
ComPtr<ID3D12DeviceFactory> device_factory;
@ -146,5 +122,3 @@ public:
RenderingContextDriverD3D12();
virtual ~RenderingContextDriverD3D12() override;
};
#endif // RENDERING_CONTEXT_DRIVER_D3D12_H

View file

@ -39,44 +39,13 @@
#include "dxil_hash.h"
#include "rendering_context_driver_d3d12.h"
// No point in fighting warnings in Mesa.
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable : 4200) // "nonstandard extension used: zero-sized array in struct/union".
#pragma warning(disable : 4806) // "'&': unsafe operation: no value of type 'bool' promoted to type 'uint32_t' can equal the given constant".
#endif
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
#pragma GCC diagnostic ignored "-Wshadow"
#pragma GCC diagnostic ignored "-Wswitch"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#elif defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
#pragma clang diagnostic ignored "-Wstring-plus-int"
#pragma clang diagnostic ignored "-Wswitch"
#pragma clang diagnostic ignored "-Wmissing-field-initializers"
#endif
#include "nir_spirv.h"
#include "nir_to_dxil.h"
#include "spirv_to_dxil.h"
#include <nir_spirv.h>
#include <nir_to_dxil.h>
#include <spirv_to_dxil.h>
extern "C" {
#include "dxil_spirv_nir.h"
#include <dxil_spirv_nir.h>
}
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic pop
#elif defined(__clang__)
#pragma clang diagnostic pop
#endif
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
#if !defined(_MSC_VER)
#include <guiddef.h>
@ -332,6 +301,20 @@ const RenderingDeviceDriverD3D12::D3D12Format RenderingDeviceDriverD3D12::RD_TO_
/* DATA_FORMAT_G16_B16_R16_3PLANE_422_UNORM */ {},
/* DATA_FORMAT_G16_B16R16_2PLANE_422_UNORM */ {},
/* DATA_FORMAT_G16_B16_R16_3PLANE_444_UNORM */ {},
/* DATA_FORMAT_ASTC_4x4_SFLOAT_BLOCK */ {},
/* DATA_FORMAT_ASTC_5x4_SFLOAT_BLOCK */ {},
/* DATA_FORMAT_ASTC_5x5_SFLOAT_BLOCK */ {},
/* DATA_FORMAT_ASTC_6x5_SFLOAT_BLOCK */ {},
/* DATA_FORMAT_ASTC_6x6_SFLOAT_BLOCK */ {},
/* DATA_FORMAT_ASTC_8x5_SFLOAT_BLOCK */ {},
/* DATA_FORMAT_ASTC_8x6_SFLOAT_BLOCK */ {},
/* DATA_FORMAT_ASTC_8x8_SFLOAT_BLOCK */ {},
/* DATA_FORMAT_ASTC_10x5_SFLOAT_BLOCK*/ {},
/* DATA_FORMAT_ASTC_10x6_SFLOAT_BLOCK */ {},
/* DATA_FORMAT_ASTC_10x8_SFLOAT_BLOCK */ {},
/* DATA_FORMAT_ASTC_10x10_SFLOAT_BLOCK */ {},
/* DATA_FORMAT_ASTC_12x10_SFLOAT_BLOCK */ {},
/* DATA_FORMAT_ASTC_12x12_SFLOAT_BLOCK */ {},
};
Error RenderingDeviceDriverD3D12::DescriptorsHeap::allocate(ID3D12Device *p_device, D3D12_DESCRIPTOR_HEAP_TYPE p_type, uint32_t p_descriptor_count, bool p_for_gpu) {
@ -1208,7 +1191,7 @@ RDD::TextureID RenderingDeviceDriverD3D12::texture_create(const TextureFormat &p
if ((p_format.usage_bits & TEXTURE_USAGE_STORAGE_BIT)) {
resource_desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
}
if ((p_format.usage_bits & TEXTURE_USAGE_VRS_ATTACHMENT_BIT)) {
if ((p_format.usage_bits & TEXTURE_USAGE_VRS_ATTACHMENT_BIT) && (p_format.usage_bits & TEXTURE_USAGE_VRS_FRAGMENT_SHADING_RATE_BIT)) {
// For VRS images we can't use the typeless format.
resource_desc.Format = DXGI_FORMAT_R8_UINT;
}
@ -1353,14 +1336,9 @@ RDD::TextureID RenderingDeviceDriverD3D12::texture_create(const TextureFormat &p
}
tex_info->states_ptr = &tex_info->owner_info.states;
tex_info->format = p_format.format;
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
#endif
GODOT_GCC_WARNING_PUSH_AND_IGNORE("-Wstrict-aliasing")
tex_info->desc = *(CD3DX12_RESOURCE_DESC *)&resource_desc;
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic pop
#endif
GODOT_GCC_WARNING_POP
tex_info->base_layer = 0;
tex_info->layers = resource_desc.ArraySize();
tex_info->base_mip = 0;
@ -1813,8 +1791,11 @@ static D3D12_BARRIER_ACCESS _rd_texture_layout_access_mask(RDD::TextureLayout p_
return D3D12_BARRIER_ACCESS_RESOLVE_SOURCE;
case RDD::TEXTURE_LAYOUT_RESOLVE_DST_OPTIMAL:
return D3D12_BARRIER_ACCESS_RESOLVE_DEST;
case RDD::TEXTURE_LAYOUT_VRS_ATTACHMENT_OPTIMAL:
case RDD::TEXTURE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL:
return D3D12_BARRIER_ACCESS_SHADING_RATE_SOURCE;
case RDD::TEXTURE_LAYOUT_FRAGMENT_DENSITY_MAP_ATTACHMENT_OPTIMAL:
DEV_ASSERT(false && "Fragment density maps are not supported in D3D12.");
return D3D12_BARRIER_ACCESS_NO_ACCESS;
default:
return D3D12_BARRIER_ACCESS_NO_ACCESS;
}
@ -1933,7 +1914,7 @@ static void _rd_stages_to_d3d12(BitField<RDD::PipelineStageBits> p_stages, D3D12
r_sync |= D3D12_BARRIER_SYNC_VERTEX_SHADING;
}
if (p_stages.has_flag(RDD::PIPELINE_STAGE_FRAGMENT_SHADER_BIT)) {
if (p_stages.has_flag(RDD::PIPELINE_STAGE_FRAGMENT_SHADER_BIT) || p_stages.has_flag(RDD::PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT)) {
r_sync |= D3D12_BARRIER_SYNC_PIXEL_SHADING;
}
@ -2028,8 +2009,11 @@ static D3D12_BARRIER_LAYOUT _rd_texture_layout_to_d3d12_barrier_layout(RDD::Text
return D3D12_BARRIER_LAYOUT_RESOLVE_SOURCE;
case RDD::TEXTURE_LAYOUT_RESOLVE_DST_OPTIMAL:
return D3D12_BARRIER_LAYOUT_RESOLVE_DEST;
case RDD::TEXTURE_LAYOUT_VRS_ATTACHMENT_OPTIMAL:
case RDD::TEXTURE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL:
return D3D12_BARRIER_LAYOUT_SHADING_RATE_SOURCE;
case RDD::TEXTURE_LAYOUT_FRAGMENT_DENSITY_MAP_ATTACHMENT_OPTIMAL:
DEV_ASSERT(false && "Fragment density maps are not supported in D3D12.");
return D3D12_BARRIER_LAYOUT_UNDEFINED;
default:
DEV_ASSERT(false && "Unknown texture layout.");
return D3D12_BARRIER_LAYOUT_UNDEFINED;
@ -2437,7 +2421,7 @@ RDD::SwapChainID RenderingDeviceDriverD3D12::swap_chain_create(RenderingContextD
color_ref.aspect.set_flag(RDD::TEXTURE_ASPECT_COLOR_BIT);
subpass.color_references.push_back(color_ref);
RenderPassID render_pass = render_pass_create(attachment, subpass, {}, 1);
RenderPassID render_pass = render_pass_create(attachment, subpass, {}, 1, AttachmentReference());
ERR_FAIL_COND_V(!render_pass, SwapChainID());
// Create the empty swap chain until it is resized.
@ -2797,8 +2781,8 @@ RDD::FramebufferID RenderingDeviceDriverD3D12::_framebuffer_create(RenderPassID
uint32_t vrs_index = UINT32_MAX;
for (const Subpass &E : pass_info->subpasses) {
if (E.vrs_reference.attachment != AttachmentReference::UNUSED) {
vrs_index = E.vrs_reference.attachment;
if (E.fragment_shading_rate_reference.attachment != AttachmentReference::UNUSED) {
vrs_index = E.fragment_shading_rate_reference.attachment;
}
}
@ -3074,7 +3058,7 @@ Vector<uint8_t> RenderingDeviceDriverD3D12::shader_compile_binary_from_spirv(Vec
// Translate SPIR-V shaders to DXIL, and collect shader info from the new representation.
HashMap<ShaderStage, Vector<uint8_t>> dxil_blobs;
BitField<ShaderStage> stages_processed;
BitField<ShaderStage> stages_processed = {};
{
HashMap<int, nir_shader *> stages_nir_shaders;
@ -3529,7 +3513,7 @@ Vector<uint8_t> RenderingDeviceDriverD3D12::shader_compile_binary_from_spirv(Vec
ComPtr<ID3DBlob> error_blob;
HRESULT res = D3DX12SerializeVersionedRootSignature(context_driver->lib_d3d12, &root_sig_desc, D3D_ROOT_SIGNATURE_VERSION_1_1, root_sig_blob.GetAddressOf(), error_blob.GetAddressOf());
ERR_FAIL_COND_V_MSG(!SUCCEEDED(res), Vector<uint8_t>(),
"Serialization of root signature failed with error " + vformat("0x%08ux", (uint64_t)res) + " and the following message:\n" + String((char *)error_blob->GetBufferPointer(), error_blob->GetBufferSize()));
"Serialization of root signature failed with error " + vformat("0x%08ux", (uint64_t)res) + " and the following message:\n" + String::ascii(Span((char *)error_blob->GetBufferPointer(), error_blob->GetBufferSize())));
binary_data.root_signature_crc = crc32(0, nullptr, 0);
binary_data.root_signature_crc = crc32(binary_data.root_signature_crc, (const Bytef *)root_sig_blob->GetBufferPointer(), root_sig_blob->GetBufferSize());
@ -3677,7 +3661,8 @@ RDD::ShaderID RenderingDeviceDriverD3D12::shader_create_from_bytecode(const Vect
read_offset += sizeof(uint32_t) * 3 + bin_data_size;
if (binary_data.shader_name_len) {
r_name.parse_utf8((const char *)(binptr + read_offset), binary_data.shader_name_len);
r_name.clear();
r_name.append_utf8((const char *)(binptr + read_offset), binary_data.shader_name_len);
read_offset += STEPIFY(binary_data.shader_name_len, 4);
}
@ -4949,7 +4934,9 @@ Vector<uint8_t> RenderingDeviceDriverD3D12::pipeline_cache_serialize() {
// ----- SUBPASS -----
RDD::RenderPassID RenderingDeviceDriverD3D12::render_pass_create(VectorView<Attachment> p_attachments, VectorView<Subpass> p_subpasses, VectorView<SubpassDependency> p_subpass_dependencies, uint32_t p_view_count) {
RDD::RenderPassID RenderingDeviceDriverD3D12::render_pass_create(VectorView<Attachment> p_attachments, VectorView<Subpass> p_subpasses, VectorView<SubpassDependency> p_subpass_dependencies, uint32_t p_view_count, AttachmentReference p_fragment_density_map_attachment) {
ERR_FAIL_COND_V_MSG(p_fragment_density_map_attachment.attachment != AttachmentReference::UNUSED, RenderPassID(), "Fragment density maps are not supported in D3D12.");
// Pre-bookkeep.
RenderPassInfo *pass_info = VersatileResource::allocate<RenderPassInfo>(resources_allocator);
@ -5050,7 +5037,7 @@ void RenderingDeviceDriverD3D12::command_begin_render_pass(CommandBufferID p_cmd
}
}
if (fb_info->vrs_attachment && vrs_capabilities.ss_image_supported) {
if (fb_info->vrs_attachment && fsr_capabilities.attachment_supported) {
ComPtr<ID3D12GraphicsCommandList5> cmd_list_5;
cmd_buf_info->cmd_list->QueryInterface(cmd_list_5.GetAddressOf());
if (cmd_list_5) {
@ -5170,7 +5157,7 @@ void RenderingDeviceDriverD3D12::command_end_render_pass(CommandBufferID p_cmd_b
const FramebufferInfo *fb_info = cmd_buf_info->render_pass_state.fb_info;
const RenderPassInfo *pass_info = cmd_buf_info->render_pass_state.pass_info;
if (vrs_capabilities.ss_image_supported) {
if (fsr_capabilities.attachment_supported) {
ComPtr<ID3D12GraphicsCommandList5> cmd_list_5;
cmd_buf_info->cmd_list->QueryInterface(cmd_list_5.GetAddressOf());
if (cmd_list_5) {
@ -6218,6 +6205,8 @@ uint64_t RenderingDeviceDriverD3D12::limit_get(Limit p_limit) {
return D3D12_CS_THREAD_GROUP_MAX_Y;
case LIMIT_MAX_COMPUTE_WORKGROUP_SIZE_Z:
return D3D12_CS_THREAD_GROUP_MAX_Z;
case LIMIT_MAX_COMPUTE_SHARED_MEMORY_SIZE:
return D3D12_CS_TGSM_REGISTER_COUNT * sizeof(float);
case LIMIT_SUBGROUP_SIZE:
// Note in min/max. Shader model 6.6 supports it (see https://microsoft.github.io/DirectX-Specs/d3d/HLSL_SM_6_6_WaveSize.html),
// but at this time I don't know the implications on the transpilation to DXIL, etc.
@ -6228,12 +6217,6 @@ uint64_t RenderingDeviceDriverD3D12::limit_get(Limit p_limit) {
return subgroup_capabilities.supported_stages_flags_rd();
case LIMIT_SUBGROUP_OPERATIONS:
return subgroup_capabilities.supported_operations_flags_rd();
case LIMIT_VRS_TEXEL_WIDTH:
case LIMIT_VRS_TEXEL_HEIGHT:
return vrs_capabilities.ss_image_tile_size;
case LIMIT_VRS_MAX_FRAGMENT_WIDTH:
case LIMIT_VRS_MAX_FRAGMENT_HEIGHT:
return vrs_capabilities.ss_max_fragment_size;
case LIMIT_MAX_SHADER_VARYINGS:
return MIN(D3D12_VS_OUTPUT_REGISTER_COUNT, D3D12_PS_INPUT_REGISTER_COUNT);
default: {
@ -6270,12 +6253,8 @@ uint64_t RenderingDeviceDriverD3D12::api_trait_get(ApiTrait p_trait) {
bool RenderingDeviceDriverD3D12::has_feature(Features p_feature) {
switch (p_feature) {
case SUPPORTS_MULTIVIEW:
return multiview_capabilities.is_supported && multiview_capabilities.max_view_count > 1;
case SUPPORTS_FSR_HALF_FLOAT:
return shader_capabilities.native_16bit_ops && storage_buffer_capabilities.storage_buffer_16_bit_access_is_supported;
case SUPPORTS_ATTACHMENT_VRS:
return vrs_capabilities.ss_image_supported;
case SUPPORTS_FRAGMENT_SHADER_WITH_ONLY_SIDE_EFFECTS:
return true;
case SUPPORTS_BUFFER_DEVICE_ADDRESS:
@ -6289,6 +6268,14 @@ const RDD::MultiviewCapabilities &RenderingDeviceDriverD3D12::get_multiview_capa
return multiview_capabilities;
}
const RDD::FragmentShadingRateCapabilities &RenderingDeviceDriverD3D12::get_fragment_shading_rate_capabilities() {
return fsr_capabilities;
}
const RDD::FragmentDensityMapCapabilities &RenderingDeviceDriverD3D12::get_fragment_density_map_capabilities() {
return fdm_capabilities;
}
String RenderingDeviceDriverD3D12::get_api_name() const {
return "D3D12";
}
@ -6450,12 +6437,6 @@ Error RenderingDeviceDriverD3D12::_check_capabilities() {
device_capabilities.version_minor = feature_level % 10;
// Assume not supported until proven otherwise.
vrs_capabilities.draw_call_supported = false;
vrs_capabilities.primitive_supported = false;
vrs_capabilities.primitive_in_multiviewport = false;
vrs_capabilities.ss_image_supported = false;
vrs_capabilities.ss_image_tile_size = 1;
vrs_capabilities.additional_rates_supported = false;
multiview_capabilities.is_supported = false;
multiview_capabilities.geometry_shader_is_supported = false;
multiview_capabilities.tessellation_shader_is_supported = false;
@ -6546,14 +6527,12 @@ Error RenderingDeviceDriverD3D12::_check_capabilities() {
res = device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS6, &options6, sizeof(options6));
if (SUCCEEDED(res)) {
if (options6.VariableShadingRateTier >= D3D12_VARIABLE_SHADING_RATE_TIER_1) {
vrs_capabilities.draw_call_supported = true;
fsr_capabilities.pipeline_supported = true;
if (options6.VariableShadingRateTier >= D3D12_VARIABLE_SHADING_RATE_TIER_2) {
vrs_capabilities.primitive_supported = true;
vrs_capabilities.primitive_in_multiviewport = options6.PerPrimitiveShadingRateSupportedWithViewportIndexing;
vrs_capabilities.ss_image_supported = true;
vrs_capabilities.ss_image_tile_size = options6.ShadingRateImageTileSize;
vrs_capabilities.ss_max_fragment_size = 8; // TODO figure out if this is supplied and/or needed
vrs_capabilities.additional_rates_supported = options6.AdditionalShadingRatesSupported;
fsr_capabilities.primitive_supported = true;
fsr_capabilities.attachment_supported = true;
fsr_capabilities.min_texel_size = Size2i(options6.ShadingRateImageTileSize, options6.ShadingRateImageTileSize);
fsr_capabilities.max_texel_size = Size2i(8, 8);
}
}
}
@ -6565,19 +6544,16 @@ Error RenderingDeviceDriverD3D12::_check_capabilities() {
barrier_capabilities.enhanced_barriers_supported = options12.EnhancedBarriersSupported;
}
if (vrs_capabilities.draw_call_supported || vrs_capabilities.primitive_supported || vrs_capabilities.ss_image_supported) {
if (fsr_capabilities.pipeline_supported || fsr_capabilities.primitive_supported || fsr_capabilities.attachment_supported) {
print_verbose("- D3D12 Variable Rate Shading supported:");
if (vrs_capabilities.draw_call_supported) {
if (fsr_capabilities.pipeline_supported) {
print_verbose(" Draw call");
}
if (vrs_capabilities.primitive_supported) {
print_verbose(String(" Per-primitive (multi-viewport: ") + (vrs_capabilities.primitive_in_multiviewport ? "yes" : "no") + ")");
if (fsr_capabilities.primitive_supported) {
print_verbose(" Primitive");
}
if (vrs_capabilities.ss_image_supported) {
print_verbose(String(" Screen-space image (tile size: ") + itos(vrs_capabilities.ss_image_tile_size) + ")");
}
if (vrs_capabilities.additional_rates_supported) {
print_verbose(String(" Additional rates: ") + (vrs_capabilities.additional_rates_supported ? "yes" : "no"));
if (fsr_capabilities.attachment_supported) {
print_verbose(String(" Screen-space image (tile size: ") + itos(fsr_capabilities.min_texel_size.x) + ")");
}
} else {
print_verbose("- D3D12 Variable Rate Shading not supported");

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef RENDERING_DEVICE_DRIVER_D3D12_H
#define RENDERING_DEVICE_DRIVER_D3D12_H
#pragma once
#include "core/templates/hash_map.h"
#include "core/templates/paged_allocator.h"
@ -41,26 +40,10 @@
#define __REQUIRED_RPCNDR_H_VERSION__ 475
#endif
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
#pragma GCC diagnostic ignored "-Wshadow"
#pragma GCC diagnostic ignored "-Wswitch"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#elif defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
#pragma clang diagnostic ignored "-Wstring-plus-int"
#pragma clang diagnostic ignored "-Wswitch"
#pragma clang diagnostic ignored "-Wmissing-field-initializers"
#pragma clang diagnostic ignored "-Wimplicit-fallthrough"
#endif
#include "d3dx12.h"
#include <d3dx12.h>
#include <dxgi1_6.h>
#define D3D12MA_D3D12_HEADERS_ALREADY_INCLUDED
#include "D3D12MemAlloc.h"
#include <D3D12MemAlloc.h>
#include <wrl/client.h>
@ -69,12 +52,6 @@
#undef MemoryBarrier
#endif
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic pop
#elif defined(__clang__)
#pragma clang diagnostic pop
#endif
using Microsoft::WRL::ComPtr;
#define D3D12_BITCODE_OFFSETS_NUM_STAGES 3
@ -116,16 +93,6 @@ class RenderingDeviceDriverD3D12 : public RenderingDeviceDriver {
uint32_t supported_operations_flags_rd() const;
};
struct VRSCapabilities {
bool draw_call_supported = false; // We can specify our fragment rate on a draw call level.
bool primitive_supported = false; // We can specify our fragment rate on each drawcall.
bool primitive_in_multiviewport = false;
bool ss_image_supported = false; // We can provide a density map attachment on our framebuffer.
uint32_t ss_image_tile_size = 0;
uint32_t ss_max_fragment_size = 0;
bool additional_rates_supported = false;
};
struct ShaderCapabilities {
D3D_SHADER_MODEL shader_model = (D3D_SHADER_MODEL)0;
bool native_16bit_ops = false;
@ -157,7 +124,8 @@ class RenderingDeviceDriverD3D12 : public RenderingDeviceDriver {
uint32_t feature_level = 0; // Major * 10 + minor.
SubgroupCapabilities subgroup_capabilities;
RDD::MultiviewCapabilities multiview_capabilities;
VRSCapabilities vrs_capabilities;
FragmentShadingRateCapabilities fsr_capabilities;
FragmentDensityMapCapabilities fdm_capabilities;
ShaderCapabilities shader_capabilities;
StorageBufferCapabilities storage_buffer_capabilities;
FormatCapabilities format_capabilities;
@ -834,7 +802,7 @@ private:
};
public:
virtual RenderPassID render_pass_create(VectorView<Attachment> p_attachments, VectorView<Subpass> p_subpasses, VectorView<SubpassDependency> p_subpass_dependencies, uint32_t p_view_count) override final;
virtual RenderPassID render_pass_create(VectorView<Attachment> p_attachments, VectorView<Subpass> p_subpasses, VectorView<SubpassDependency> p_subpass_dependencies, uint32_t p_view_count, AttachmentReference p_fragment_density_map_attachment) override final;
virtual void render_pass_free(RenderPassID p_render_pass) override final;
// ----- COMMANDS -----
@ -1002,6 +970,8 @@ public:
virtual uint64_t api_trait_get(ApiTrait p_trait) override final;
virtual bool has_feature(Features p_feature) override final;
virtual const MultiviewCapabilities &get_multiview_capabilities() override final;
virtual const FragmentShadingRateCapabilities &get_fragment_shading_rate_capabilities() override final;
virtual const FragmentDensityMapCapabilities &get_fragment_density_map_capabilities() override final;
virtual String get_api_name() const override final;
virtual String get_api_version() const override final;
virtual String get_pipeline_cache_uuid() const override final;
@ -1036,5 +1006,3 @@ public:
RenderingDeviceDriverD3D12(RenderingContextDriverD3D12 *p_context_driver);
virtual ~RenderingDeviceDriverD3D12();
};
#endif // RENDERING_DEVICE_DRIVER_D3D12_H

View file

@ -151,7 +151,7 @@ int EGLManager::_get_gldisplay_id(void *p_display) {
String EGLManager::shader_cache_dir;
void EGLManager::_set_cache(const void *p_key, EGLsizeiANDROID p_key_size, const void *p_value, EGLsizeiANDROID p_value_size) {
String name = CryptoCore::b64_encode_str((const uint8_t *)p_key, p_key_size).replace("/", "_");
String name = CryptoCore::b64_encode_str((const uint8_t *)p_key, p_key_size).replace_char('/', '_');
String path = shader_cache_dir.path_join(name) + ".cache";
Error err = OK;
@ -163,7 +163,7 @@ void EGLManager::_set_cache(const void *p_key, EGLsizeiANDROID p_key_size, const
}
EGLsizeiANDROID EGLManager::_get_cache(const void *p_key, EGLsizeiANDROID p_key_size, void *p_value, EGLsizeiANDROID p_value_size) {
String name = CryptoCore::b64_encode_str((const uint8_t *)p_key, p_key_size).replace("/", "_");
String name = CryptoCore::b64_encode_str((const uint8_t *)p_key, p_key_size).replace_char('/', '_');
String path = shader_cache_dir.path_join(name) + ".cache";
Error err = OK;

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef EGL_MANAGER_H
#define EGL_MANAGER_H
#pragma once
#ifdef EGL_ENABLED
@ -119,5 +118,3 @@ public:
};
#endif // EGL_ENABLED
#endif // EGL_MANAGER_H

View file

@ -13,12 +13,7 @@ if env["platform"] in ["macos", "windows", "linuxbsd"]:
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
# Treat glad headers as system headers to avoid raising warnings. Not supported on MSVC.
if not env.msvc:
env.Append(CPPFLAGS=["-isystem", Dir(thirdparty_dir).path])
else:
env.Prepend(CPPPATH=[thirdparty_dir])
env.Prepend(CPPEXTPATH=[thirdparty_dir])
env.Append(CPPDEFINES=["GLAD_ENABLED"])
env.Append(CPPDEFINES=["EGL_ENABLED"])

View file

@ -243,7 +243,7 @@ void CopyEffects::gaussian_blur(GLuint p_source_texture, int p_mipmap_count, con
glBindTexture(GL_TEXTURE_2D, p_source_texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, i - 1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, i - 1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, i);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, p_source_texture, i);
#ifdef DEV_ENABLED
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef COPY_EFFECTS_GLES3_H
#define COPY_EFFECTS_GLES3_H
#pragma once
#ifdef GLES3_ENABLED
@ -77,5 +76,3 @@ public:
} //namespace GLES3
#endif // GLES3_ENABLED
#endif // COPY_EFFECTS_GLES3_H

View file

@ -91,7 +91,7 @@ CubemapFilter::~CubemapFilter() {
Vector3 importance_sample_GGX(Vector2 xi, float roughness4) {
// Compute distribution direction
float phi = 2.0 * Math_PI * xi.x;
float phi = 2.0 * Math::PI * xi.x;
float cos_theta = sqrt((1.0 - xi.y) / (1.0 + (roughness4 - 1.0) * xi.y));
float sin_theta = sqrt(1.0 - cos_theta * cos_theta);
@ -107,7 +107,7 @@ Vector3 importance_sample_GGX(Vector2 xi, float roughness4) {
float distribution_GGX(float NdotH, float roughness4) {
float NdotH2 = NdotH * NdotH;
float denom = (NdotH2 * (roughness4 - 1.0) + 1.0);
denom = Math_PI * denom * denom;
denom = Math::PI * denom * denom;
return roughness4 / denom;
}
@ -157,7 +157,7 @@ void CubemapFilter::filter_radiance(GLuint p_source_cubemap, GLuint p_dest_cubem
float roughness4 = roughness * roughness;
roughness4 *= roughness4;
float solid_angle_texel = 4.0 * Math_PI / float(6 * size * size);
float solid_angle_texel = 4.0 * Math::PI / float(6 * size * size);
LocalVector<float> sample_directions;
sample_directions.resize(4 * sample_count);

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef CUBEMAP_FILTER_GLES3_H
#define CUBEMAP_FILTER_GLES3_H
#pragma once
#ifdef GLES3_ENABLED
@ -66,5 +65,3 @@ public:
} //namespace GLES3
#endif // GLES3_ENABLED
#endif // CUBEMAP_FILTER_GLES3_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef FEED_EFFECTS_GLES3_H
#define FEED_EFFECTS_GLES3_H
#pragma once
#ifdef GLES3_ENABLED
@ -65,5 +64,3 @@ private:
} // namespace GLES3
#endif // GLES3_ENABLED
#endif // FEED_EFFECTS_GLES3_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GLOW_GLES3_H
#define GLOW_GLES3_H
#pragma once
#ifdef GLES3_ENABLED
@ -85,5 +84,3 @@ public:
} //namespace GLES3
#endif // GLES3_ENABLED
#endif // GLOW_GLES3_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef POST_EFFECTS_GLES3_H
#define POST_EFFECTS_GLES3_H
#pragma once
#ifdef GLES3_ENABLED
@ -65,5 +64,3 @@ public:
} //namespace GLES3
#endif // GLES3_ENABLED
#endif // POST_EFFECTS_GLES3_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef FOG_GLES3_H
#define FOG_GLES3_H
#pragma once
#ifdef GLES3_ENABLED
@ -55,5 +54,3 @@ public:
} // namespace GLES3
#endif // GLES3_ENABLED
#endif // FOG_GLES3_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GI_GLES3_H
#define GI_GLES3_H
#pragma once
#ifdef GLES3_ENABLED
@ -87,5 +86,3 @@ public:
}; // namespace GLES3
#endif // GLES3_ENABLED
#endif // GI_GLES3_H

View file

@ -1152,6 +1152,12 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend
// Reset base data.
_update_transform_2d_to_mat2x3(base_transform * draw_transform, state.instance_data_array[r_index].world);
_prepare_canvas_texture(state.canvas_instance_batches[state.current_batch_index].tex, state.canvas_instance_batches[state.current_batch_index].filter, state.canvas_instance_batches[state.current_batch_index].repeat, r_index, texpixel_size);
state.instance_data_array[r_index].lights[0] = lights[0];
state.instance_data_array[r_index].lights[1] = lights[1];
state.instance_data_array[r_index].lights[2] = lights[2];
state.instance_data_array[r_index].lights[3] = lights[3];
state.instance_data_array[r_index].flags = base_flags;
state.instance_data_array[r_index].instance_uniforms_ofs = p_item->instance_allocated_shader_uniforms_offset;
for (uint32_t j = 0; j < 3; j++) {
int offset = j == 0 ? 0 : 1;
@ -1289,7 +1295,7 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend
_FORCE_INLINE_ static uint32_t _indices_to_primitives(RS::PrimitiveType p_primitive, uint32_t p_indices) {
static const uint32_t divisor[RS::PRIMITIVE_MAX] = { 1, 2, 1, 3, 1 };
static const uint32_t subtractor[RS::PRIMITIVE_MAX] = { 0, 0, 1, 0, 1 };
static const uint32_t subtractor[RS::PRIMITIVE_MAX] = { 0, 0, 1, 0, 2 };
return (p_indices - subtractor[p_primitive]) / divisor[p_primitive];
}
@ -1566,7 +1572,7 @@ void RasterizerCanvasGLES3::_add_to_batch(uint32_t &r_index, bool &r_batch_broke
}
void RasterizerCanvasGLES3::_new_batch(bool &r_batch_broken) {
if (state.canvas_instance_batches.size() == 0) {
if (state.canvas_instance_batches.is_empty()) {
Batch new_batch;
new_batch.instance_buffer_index = state.current_instance_buffer_index;
state.canvas_instance_batches.push_back(new_batch);
@ -1686,7 +1692,7 @@ void RasterizerCanvasGLES3::light_update_shadow(RID p_rid, int p_shadow_index, c
}
// Precomputed:
// Vector3 cam_target = Basis::from_euler(Vector3(0, 0, Math_TAU * ((i + 3) / 4.0))).xform(Vector3(0, 1, 0));
// Vector3 cam_target = Basis::from_euler(Vector3(0, 0, Math::TAU * ((i + 3) / 4.0))).xform(Vector3(0, 1, 0));
// projection = projection * Projection(Transform3D().looking_at(cam_targets[i], Vector3(0, 0, -1)).affine_inverse());
const Projection projections[4] = {
projection * Projection(Vector4(0, 0, -1, 0), Vector4(1, 0, 0, 0), Vector4(0, -1, 0, 0), Vector4(0, 0, 0, 1)),
@ -1761,7 +1767,7 @@ void RasterizerCanvasGLES3::light_update_directional_shadow(RID p_rid, int p_sha
Vector2 center = p_clip_rect.get_center();
float to_edge_distance = ABS(light_dir.dot(p_clip_rect.get_support(-light_dir)) - light_dir.dot(center));
float to_edge_distance = Math::abs(light_dir.dot(p_clip_rect.get_support(-light_dir)) - light_dir.dot(center));
Vector2 from_pos = center - light_dir * (to_edge_distance + p_cull_distance);
float distance = to_edge_distance * 2.0 + p_cull_distance;

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef RASTERIZER_CANVAS_GLES3_H
#define RASTERIZER_CANVAS_GLES3_H
#pragma once
#ifdef GLES3_ENABLED
@ -388,5 +387,3 @@ public:
};
#endif // GLES3_ENABLED
#endif // RASTERIZER_CANVAS_GLES3_H

View file

@ -55,6 +55,7 @@
#define _EXT_DEBUG_TYPE_PORTABILITY_ARB 0x824F
#define _EXT_DEBUG_TYPE_PERFORMANCE_ARB 0x8250
#define _EXT_DEBUG_TYPE_OTHER_ARB 0x8251
#define _EXT_DEBUG_TYPE_MARKER_ARB 0x8268
#define _EXT_MAX_DEBUG_MESSAGE_LENGTH_ARB 0x9143
#define _EXT_MAX_DEBUG_LOGGED_MESSAGES_ARB 0x9144
#define _EXT_DEBUG_LOGGED_MESSAGES_ARB 0x9145
@ -140,7 +141,7 @@ void RasterizerGLES3::clear_depth(float p_depth) {
#ifdef CAN_DEBUG
static void GLAPIENTRY _gl_debug_print(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const GLvoid *userParam) {
// These are ultimately annoying, so removing for now.
if (type == _EXT_DEBUG_TYPE_OTHER_ARB || type == _EXT_DEBUG_TYPE_PERFORMANCE_ARB) {
if (type == _EXT_DEBUG_TYPE_OTHER_ARB || type == _EXT_DEBUG_TYPE_PERFORMANCE_ARB || type == _EXT_DEBUG_TYPE_MARKER_ARB) {
return;
}

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef RASTERIZER_GLES3_H
#define RASTERIZER_GLES3_H
#pragma once
#ifdef GLES3_ENABLED
@ -105,6 +104,7 @@ public:
void blit_render_targets_to_screen(DisplayServer::WindowID p_screen, const BlitToScreen *p_render_targets, int p_amount);
bool is_opengl() { return true; }
void gl_end_frame(bool p_swap_buffers);
void end_frame(bool p_swap_buffers);
@ -141,5 +141,3 @@ public:
};
#endif // GLES3_ENABLED
#endif // RASTERIZER_GLES3_H

View file

@ -708,12 +708,7 @@ void RasterizerSceneGLES3::_setup_sky(const RenderDataGLES3 *p_render_data, cons
sky_light_data.enabled = true;
float angular_diameter = light_storage->light_get_param(base, RS::LIGHT_PARAM_SIZE);
if (angular_diameter > 0.0) {
angular_diameter = Math::tan(Math::deg_to_rad(angular_diameter));
} else {
angular_diameter = 0.0;
}
sky_light_data.size = angular_diameter;
sky_light_data.size = Math::deg_to_rad(angular_diameter);
sky_globals.directional_light_count++;
if (sky_globals.directional_light_count >= sky_globals.max_directional_lights) {
break;
@ -1224,7 +1219,7 @@ void RasterizerSceneGLES3::voxel_gi_set_quality(RS::VoxelGIQuality) {
_FORCE_INLINE_ static uint32_t _indices_to_primitives(RS::PrimitiveType p_primitive, uint32_t p_indices) {
static const uint32_t divisor[RS::PRIMITIVE_MAX] = { 1, 2, 1, 3, 1 };
static const uint32_t subtractor[RS::PRIMITIVE_MAX] = { 0, 0, 1, 0, 1 };
static const uint32_t subtractor[RS::PRIMITIVE_MAX] = { 0, 0, 1, 0, 2 };
return (p_indices - subtractor[p_primitive]) / divisor[p_primitive];
}
void RasterizerSceneGLES3::_fill_render_list(RenderListType p_render_list, const RenderDataGLES3 *p_render_data, PassMode p_pass_mode, bool p_append) {
@ -1677,7 +1672,7 @@ void RasterizerSceneGLES3::_setup_lights(const RenderDataGLES3 *p_render_data, b
if (is_using_physical_light_units()) {
light_data.energy *= light_storage->light_get_param(base, RS::LIGHT_PARAM_INTENSITY);
} else {
light_data.energy *= Math_PI;
light_data.energy *= Math::PI;
}
if (p_render_data->camera_attributes.is_valid()) {
@ -1867,14 +1862,14 @@ void RasterizerSceneGLES3::_setup_lights(const RenderDataGLES3 *p_render_data, b
// Convert from Luminous Power to Luminous Intensity
if (type == RS::LIGHT_OMNI) {
energy *= 1.0 / (Math_PI * 4.0);
energy *= 1.0 / (Math::PI * 4.0);
} else {
// Spot Lights are not physically accurate, Luminous Intensity should change in relation to the cone angle.
// We make this assumption to keep them easy to control.
energy *= 1.0 / Math_PI;
energy *= 1.0 / Math::PI;
}
} else {
energy *= Math_PI;
energy *= Math::PI;
}
if (p_render_data->camera_attributes.is_valid()) {
@ -3223,11 +3218,11 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
spec_constants |= SceneShaderGLES3::DISABLE_LIGHT_DIRECTIONAL;
spec_constants |= SceneShaderGLES3::DISABLE_LIGHTMAP;
} else {
if (inst->omni_light_gl_cache.size() == 0) {
if (inst->omni_light_gl_cache.is_empty()) {
spec_constants |= SceneShaderGLES3::DISABLE_LIGHT_OMNI;
}
if (inst->spot_light_gl_cache.size() == 0) {
if (inst->spot_light_gl_cache.is_empty()) {
spec_constants |= SceneShaderGLES3::DISABLE_LIGHT_SPOT;
}
@ -3235,7 +3230,7 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
spec_constants |= SceneShaderGLES3::DISABLE_LIGHT_DIRECTIONAL;
}
if (inst->reflection_probe_rid_cache.size() == 0) {
if (inst->reflection_probe_rid_cache.is_empty()) {
// We don't have any probes.
spec_constants |= SceneShaderGLES3::DISABLE_REFLECTION_PROBE;
} else if (inst->reflection_probe_rid_cache.size() > 1) {

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef RASTERIZER_SCENE_GLES3_H
#define RASTERIZER_SCENE_GLES3_H
#pragma once
#ifdef GLES3_ENABLED
@ -740,7 +739,7 @@ protected:
float baked_exposure = 1.0;
//State to track when radiance cubemap needs updating
GLES3::SkyMaterialData *prev_material;
GLES3::SkyMaterialData *prev_material = nullptr;
Vector3 prev_position = Vector3(0.0, 0.0, 0.0);
float prev_time = 0.0f;
};
@ -879,5 +878,3 @@ public:
};
#endif // GLES3_ENABLED
#endif // RASTERIZER_SCENE_GLES3_H

View file

@ -73,7 +73,7 @@ void ShaderGLES3::_add_stage(const char *p_code, StageType p_stage_type) {
} else if (l.begins_with("#CODE")) {
chunk.type = StageTemplate::Chunk::TYPE_CODE;
push_chunk = true;
chunk.code = l.replace_first("#CODE", String()).replace(":", "").strip_edges().to_upper();
chunk.code = l.replace_first("#CODE", String()).remove_char(':').strip_edges().to_upper();
} else {
text += l + "\n";
}
@ -690,7 +690,7 @@ void ShaderGLES3::_save_to_cache(Version *p_version) {
void ShaderGLES3::_clear_version(Version *p_version) {
// Variants not compiled yet, just return
if (p_version->variants.size() == 0) {
if (p_version->variants.is_empty()) {
return;
}

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef SHADER_GLES3_H
#define SHADER_GLES3_H
#pragma once
#include "core/math/projection.h"
#include "core/os/mutex.h"
@ -189,7 +188,7 @@ protected:
Version *version = version_owner.get_or_null(p_version);
ERR_FAIL_NULL_V(version, false);
if (version->variants.size() == 0) {
if (version->variants.is_empty()) {
_initialize_version(version); //may lack initialization
}
@ -258,5 +257,3 @@ public:
};
#endif // GLES3_ENABLED
#endif // SHADER_GLES3_H

View file

@ -78,8 +78,8 @@ Config::Config() {
#endif
bptc_supported = extensions.has("GL_ARB_texture_compression_bptc") || extensions.has("EXT_texture_compression_bptc");
astc_supported = extensions.has("GL_KHR_texture_compression_astc") || extensions.has("GL_OES_texture_compression_astc") || extensions.has("GL_KHR_texture_compression_astc_ldr") || extensions.has("GL_KHR_texture_compression_astc_hdr");
astc_hdr_supported = extensions.has("GL_KHR_texture_compression_astc_hdr");
astc_supported = astc_hdr_supported || extensions.has("GL_KHR_texture_compression_astc") || extensions.has("GL_OES_texture_compression_astc") || extensions.has("GL_KHR_texture_compression_astc_ldr") || extensions.has("WEBGL_compressed_texture_astc");
astc_layered_supported = extensions.has("GL_KHR_texture_compression_astc_sliced_3d");
if (RasterizerGLES3::is_gles_over_gl()) {
@ -226,7 +226,7 @@ Config::Config() {
// OpenGL ES 3.0 V@331.0 (GIT@35e467f, Ice9844a736) (Date:04/15/19)
// OpenGL ES 3.0 V@415.0 (GIT@d39f783, I79de86aa2c, 1591296226) (Date:06/04/20)
// OpenGL ES 3.0 V@0502.0 (GIT@09fef447e8, I1fe547a144, 1661493934) (Date:08/25/22)
String driver_version = gl_version.get_slice("V@", 1).get_slice(" ", 0);
String driver_version = gl_version.get_slice("V@", 1).get_slicec(' ', 0);
if (driver_version.is_valid_float() && driver_version.to_float() >= 331.0) {
flip_xy_workaround = false;

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef CONFIG_GLES3_H
#define CONFIG_GLES3_H
#pragma once
#ifdef GLES3_ENABLED
@ -123,5 +122,3 @@ public:
} // namespace GLES3
#endif // GLES3_ENABLED
#endif // CONFIG_GLES3_H

View file

@ -1181,7 +1181,7 @@ void LightStorage::lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point,
return; // Nothing could be done.
}
node = ABS(node) - 1;
node = Math::abs(node) - 1;
uint32_t *tetrahedron = (uint32_t *)&lm->tetrahedra[node * 4];
Vector3 points[4] = { lm->points[tetrahedron[0]], lm->points[tetrahedron[1]], lm->points[tetrahedron[2]], lm->points[tetrahedron[3]] };

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef LIGHT_STORAGE_GLES3_H
#define LIGHT_STORAGE_GLES3_H
#pragma once
#ifdef GLES3_ENABLED
@ -909,5 +908,3 @@ public:
} // namespace GLES3
#endif // GLES3_ENABLED
#endif // LIGHT_STORAGE_GLES3_H

View file

@ -1143,9 +1143,9 @@ MaterialStorage::MaterialStorage() {
actions.renames["CANVAS_MATRIX"] = "canvas_transform";
actions.renames["SCREEN_MATRIX"] = "screen_transform";
actions.renames["TIME"] = "time";
actions.renames["PI"] = _MKSTR(Math_PI);
actions.renames["TAU"] = _MKSTR(Math_TAU);
actions.renames["E"] = _MKSTR(Math_E);
actions.renames["PI"] = String::num(Math::PI);
actions.renames["TAU"] = String::num(Math::TAU);
actions.renames["E"] = String::num(Math::E);
actions.renames["AT_LIGHT_PASS"] = "false";
actions.renames["INSTANCE_CUSTOM"] = "instance_custom";
@ -1238,9 +1238,9 @@ MaterialStorage::MaterialStorage() {
actions.renames["TIME"] = "scene_data.time";
actions.renames["EXPOSURE"] = "(1.0 / scene_data.emissive_exposure_normalization)";
actions.renames["PI"] = _MKSTR(Math_PI);
actions.renames["TAU"] = _MKSTR(Math_TAU);
actions.renames["E"] = _MKSTR(Math_E);
actions.renames["PI"] = String::num(Math::PI);
actions.renames["TAU"] = String::num(Math::TAU);
actions.renames["E"] = String::num(Math::E);
actions.renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB";
actions.renames["CLIP_SPACE_FAR"] = "SHADER_SPACE_FAR";
actions.renames["VIEWPORT_SIZE"] = "scene_data.viewport_size";
@ -1406,9 +1406,9 @@ MaterialStorage::MaterialStorage() {
}
actions.renames["TRANSFORM"] = "xform";
actions.renames["TIME"] = "time";
actions.renames["PI"] = _MKSTR(Math_PI);
actions.renames["TAU"] = _MKSTR(Math_TAU);
actions.renames["E"] = _MKSTR(Math_E);
actions.renames["PI"] = String::num(Math::PI);
actions.renames["TAU"] = String::num(Math::TAU);
actions.renames["E"] = String::num(Math::E);
actions.renames["LIFETIME"] = "lifetime";
actions.renames["DELTA"] = "local_delta";
actions.renames["NUMBER"] = "particle_number";
@ -1463,9 +1463,9 @@ MaterialStorage::MaterialStorage() {
actions.renames["SCREEN_UV"] = "uv";
actions.renames["TIME"] = "time";
actions.renames["FRAGCOORD"] = "gl_FragCoord";
actions.renames["PI"] = _MKSTR(Math_PI);
actions.renames["TAU"] = _MKSTR(Math_TAU);
actions.renames["E"] = _MKSTR(Math_E);
actions.renames["PI"] = String::num(Math::PI);
actions.renames["TAU"] = String::num(Math::TAU);
actions.renames["E"] = String::num(Math::E);
actions.renames["HALF_RES_COLOR"] = "half_res_color";
actions.renames["QUARTER_RES_COLOR"] = "quarter_res_color";
actions.renames["RADIANCE"] = "radiance";
@ -1925,7 +1925,7 @@ void MaterialStorage::global_shader_parameters_load_settings(bool p_load_texture
for (const PropertyInfo &E : settings) {
if (E.name.begins_with("shader_globals/")) {
StringName name = E.name.get_slice("/", 1);
StringName name = E.name.get_slicec('/', 1);
Dictionary d = GLOBAL_GET(E.name);
ERR_CONTINUE(!d.has("type"));

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef MATERIAL_STORAGE_GLES3_H
#define MATERIAL_STORAGE_GLES3_H
#pragma once
#ifdef GLES3_ENABLED
@ -634,5 +633,3 @@ public:
} // namespace GLES3
#endif // GLES3_ENABLED
#endif // MATERIAL_STORAGE_GLES3_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef MESH_STORAGE_GLES3_H
#define MESH_STORAGE_GLES3_H
#pragma once
#ifdef GLES3_ENABLED
@ -604,5 +603,3 @@ public:
} // namespace GLES3
#endif // GLES3_ENABLED
#endif // MESH_STORAGE_GLES3_H

View file

@ -513,7 +513,7 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
double new_phase = Math::fmod(p_particles->phase + (p_delta / p_particles->lifetime) * p_particles->speed_scale, 1.0);
double new_phase = Math::fmod(p_particles->phase + (p_delta / p_particles->lifetime), 1.0);
//update current frame
ParticlesFrameParams frame_params;
@ -534,7 +534,7 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta
p_particles->phase = new_phase;
frame_params.time = RSG::rasterizer->get_total_time();
frame_params.delta = p_delta * p_particles->speed_scale;
frame_params.delta = p_delta;
frame_params.random_seed = p_particles->random_seed;
frame_params.explosiveness = p_particles->explosiveness;
frame_params.randomness = p_particles->randomness;
@ -1097,8 +1097,6 @@ void ParticlesStorage::update_particles() {
fixed_fps = particles->fixed_fps;
}
bool zero_time_scale = Engine::get_singleton()->get_time_scale() <= 0.0;
if (particles->clear && particles->pre_process_time > 0.0) {
double frame_time;
if (fixed_fps > 0) {
@ -1115,37 +1113,27 @@ void ParticlesStorage::update_particles() {
}
}
double time_scale = MAX(particles->speed_scale, 0.0);
if (fixed_fps > 0) {
double frame_time;
double decr;
if (zero_time_scale) {
frame_time = 0.0;
decr = 1.0 / fixed_fps;
} else {
frame_time = 1.0 / fixed_fps;
decr = frame_time;
}
double frame_time = 1.0 / fixed_fps;
double delta = RSG::rasterizer->get_frame_delta_time();
if (delta > 0.1) { //avoid recursive stalls if fps goes below 10
delta = 0.1;
} else if (delta <= 0.0) { //unlikely but..
delta = 0.001;
}
double todo = particles->frame_remainder + delta;
double todo = particles->frame_remainder + delta * time_scale;
while (todo >= frame_time) {
_particles_process(particles, frame_time);
todo -= decr;
todo -= frame_time;
}
particles->frame_remainder = todo;
} else {
if (zero_time_scale) {
_particles_process(particles, 0.0);
} else {
_particles_process(particles, RSG::rasterizer->get_frame_delta_time());
}
_particles_process(particles, RSG::rasterizer->get_frame_delta_time() * time_scale);
}
if (particles->request_process_time > 0.0) {

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef PARTICLES_STORAGE_GLES3_H
#define PARTICLES_STORAGE_GLES3_H
#pragma once
#ifdef GLES3_ENABLED
@ -460,5 +459,3 @@ public:
} // namespace GLES3
#endif // GLES3_ENABLED
#endif // PARTICLES_STORAGE_GLES3_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef RENDER_SCENE_BUFFERS_GLES3_H
#define RENDER_SCENE_BUFFERS_GLES3_H
#pragma once
#ifdef GLES3_ENABLED
@ -164,5 +163,3 @@ public:
};
#endif // GLES3_ENABLED
#endif // RENDER_SCENE_BUFFERS_GLES3_H

View file

@ -1468,8 +1468,8 @@ void TextureStorage::texture_debug_usage(List<RS::TextureInfo> *r_info) {
List<RID> textures;
texture_owner.get_owned_list(&textures);
for (List<RID>::Element *E = textures.front(); E; E = E->next()) {
Texture *t = texture_owner.get_or_null(E->get());
for (const RID &rid : textures) {
Texture *t = texture_owner.get_or_null(rid);
if (!t) {
continue;
}

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEXTURE_STORAGE_GLES3_H
#define TEXTURE_STORAGE_GLES3_H
#pragma once
#ifdef GLES3_ENABLED
@ -730,5 +729,3 @@ inline String TextureStorage::get_framebuffer_error(GLenum p_status) {
} // namespace GLES3
#endif // GLES3_ENABLED
#endif // TEXTURE_STORAGE_GLES3_H

View file

@ -421,6 +421,9 @@ bool Utilities::has_os_feature(const String &p_feature) const {
if (p_feature == "etc2") {
return config->etc2_supported;
}
if (p_feature == "astc_hdr") {
return config->astc_hdr_supported;
}
return false;
}

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef UTILITIES_GLES3_H
#define UTILITIES_GLES3_H
#pragma once
#ifdef GLES3_ENABLED
@ -233,5 +232,3 @@ public:
} // namespace GLES3
#endif // GLES3_ENABLED
#endif // UTILITIES_GLES3_H

View file

@ -22,7 +22,7 @@ thirdparty_sources = [
]
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
env_metal.Prepend(CPPPATH=[thirdparty_dir, thirdparty_dir + "/include"])
env_metal.Prepend(CPPEXTPATH=[thirdparty_dir, thirdparty_dir + "/include"])
# Must enable exceptions for SPIRV-Cross; otherwise, it will abort the process on errors.
if "-fno-exceptions" in env_metal["CXXFLAGS"]:

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef INFLECTION_MAP_H
#define INFLECTION_MAP_H
#pragma once
#include "core/templates/hash_map.h"
#include "core/templates/local_vector.h"
@ -121,5 +120,3 @@ protected:
HashMap<KeyType, IndexValue> _inflection_indexes;
IndexValue _linear_indexes[LinearCount];
};
#endif // INFLECTION_MAP_H

View file

@ -28,6 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
/**************************************************************************/
/* */
/* Portions of this code were derived from MoltenVK. */
@ -48,9 +50,6 @@
/* permissions and limitations under the License. */
/**************************************************************************/
#ifndef METAL_DEVICE_PROPERTIES_H
#define METAL_DEVICE_PROPERTIES_H
#import "servers/rendering/rendering_device.h"
#import <Foundation/Foundation.h>
@ -125,6 +124,7 @@ struct MetalLimits {
uint32_t maxVertexInputBindingStride;
uint32_t maxDrawIndexedIndexValue;
uint32_t maxShaderVaryings;
uint32_t maxThreadGroupMemoryAllocation;
double temporalScalerInputContentMinScale;
double temporalScalerInputContentMaxScale;
@ -152,5 +152,3 @@ public:
private:
static const SampleCount sample_count[RenderingDevice::TextureSamples::TEXTURE_SAMPLES_MAX];
};
#endif // METAL_DEVICE_PROPERTIES_H

View file

@ -305,6 +305,14 @@ void MetalDeviceProperties::init_limits(id<MTLDevice> p_device) {
limits.maxVertexInputBindingStride = (2 * KIBI);
limits.maxShaderVaryings = 31; // Accurate on Apple4 and above. See: https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf
if ([p_device supportsFamily:MTLGPUFamilyApple4]) {
limits.maxThreadGroupMemoryAllocation = 32768;
} else if ([p_device supportsFamily:MTLGPUFamilyApple3]) {
limits.maxThreadGroupMemoryAllocation = 16384;
} else {
limits.maxThreadGroupMemoryAllocation = 16352;
}
#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST
limits.minUniformBufferOffsetAlignment = 64;
#endif

View file

@ -28,6 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
/**************************************************************************/
/* */
/* Portions of this code were derived from MoltenVK. */
@ -48,14 +50,11 @@
/* permissions and limitations under the License. */
/**************************************************************************/
#ifndef METAL_OBJECTS_H
#define METAL_OBJECTS_H
#import "metal_device_properties.h"
#import "metal_utils.h"
#import "pixel_formats.h"
#import "servers/rendering/rendering_device_driver.h"
#include "servers/rendering/rendering_device_driver.h"
#import <CommonCrypto/CommonDigest.h>
#import <Foundation/Foundation.h>
@ -787,20 +786,20 @@ struct BoundUniformSet {
class API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0)) MDUniformSet {
private:
void bind_uniforms_argument_buffers(MDShader *p_shader, MDCommandBuffer::RenderState &p_state);
void bind_uniforms_direct(MDShader *p_shader, MDCommandBuffer::RenderState &p_state);
void bind_uniforms_argument_buffers(MDShader *p_shader, MDCommandBuffer::ComputeState &p_state);
void bind_uniforms_direct(MDShader *p_shader, MDCommandBuffer::ComputeState &p_state);
void bind_uniforms_argument_buffers(MDShader *p_shader, MDCommandBuffer::RenderState &p_state, uint32_t p_set_index);
void bind_uniforms_direct(MDShader *p_shader, MDCommandBuffer::RenderState &p_state, uint32_t p_set_index);
void bind_uniforms_argument_buffers(MDShader *p_shader, MDCommandBuffer::ComputeState &p_state, uint32_t p_set_index);
void bind_uniforms_direct(MDShader *p_shader, MDCommandBuffer::ComputeState &p_state, uint32_t p_set_index);
public:
uint32_t index;
LocalVector<RDD::BoundUniform> uniforms;
HashMap<MDShader *, BoundUniformSet> bound_uniforms;
void bind_uniforms(MDShader *p_shader, MDCommandBuffer::RenderState &p_state);
void bind_uniforms(MDShader *p_shader, MDCommandBuffer::ComputeState &p_state);
void bind_uniforms(MDShader *p_shader, MDCommandBuffer::RenderState &p_state, uint32_t p_set_index);
void bind_uniforms(MDShader *p_shader, MDCommandBuffer::ComputeState &p_state, uint32_t p_set_index);
BoundUniformSet &bound_uniform_set(MDShader *p_shader, id<MTLDevice> p_device, ResourceUsageMap &p_resource_usage);
BoundUniformSet &bound_uniform_set(MDShader *p_shader, id<MTLDevice> p_device, ResourceUsageMap &p_resource_usage, uint32_t p_set_index);
};
class API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0)) MDPipeline {
@ -975,5 +974,3 @@ auto release(RDD::ID p_id) {
}
} // namespace rid
#endif // METAL_OBJECTS_H

View file

@ -213,36 +213,38 @@ void MDCommandBuffer::render_bind_uniform_set(RDD::UniformSetID p_uniform_set, R
DEV_ASSERT(type == MDCommandBufferStateType::Render);
MDUniformSet *set = (MDUniformSet *)(p_uniform_set.id);
if (render.uniform_sets.size() <= set->index) {
if (render.uniform_sets.size() <= p_set_index) {
uint32_t s = render.uniform_sets.size();
render.uniform_sets.resize(set->index + 1);
render.uniform_sets.resize(p_set_index + 1);
// Set intermediate values to null.
std::fill(&render.uniform_sets[s], &render.uniform_sets[set->index] + 1, nullptr);
std::fill(&render.uniform_sets[s], &render.uniform_sets[p_set_index] + 1, nullptr);
}
if (render.uniform_sets[set->index] != set) {
if (render.uniform_sets[p_set_index] != set) {
render.dirty.set_flag(RenderState::DIRTY_UNIFORMS);
render.uniform_set_mask |= 1ULL << set->index;
render.uniform_sets[set->index] = set;
render.uniform_set_mask |= 1ULL << p_set_index;
render.uniform_sets[p_set_index] = set;
}
}
void MDCommandBuffer::render_bind_uniform_sets(VectorView<RDD::UniformSetID> p_uniform_sets, RDD::ShaderID p_shader, uint32_t p_first_set_index, uint32_t p_set_count) {
DEV_ASSERT(type == MDCommandBufferStateType::Render);
for (size_t i = 0u; i < p_set_count; ++i) {
for (size_t i = 0; i < p_set_count; ++i) {
MDUniformSet *set = (MDUniformSet *)(p_uniform_sets[i].id);
if (render.uniform_sets.size() <= set->index) {
uint32_t index = p_first_set_index + i;
if (render.uniform_sets.size() <= index) {
uint32_t s = render.uniform_sets.size();
render.uniform_sets.resize(set->index + 1);
render.uniform_sets.resize(index + 1);
// Set intermediate values to null.
std::fill(&render.uniform_sets[s], &render.uniform_sets[set->index] + 1, nullptr);
std::fill(&render.uniform_sets[s], &render.uniform_sets[index] + 1, nullptr);
}
if (render.uniform_sets[set->index] != set) {
if (render.uniform_sets[index] != set) {
render.dirty.set_flag(RenderState::DIRTY_UNIFORMS);
render.uniform_set_mask |= 1ULL << set->index;
render.uniform_sets[set->index] = set;
render.uniform_set_mask |= 1ULL << index;
render.uniform_sets[index] = set;
}
}
}
@ -474,14 +476,14 @@ void MDCommandBuffer::_render_bind_uniform_sets() {
while (set_uniforms != 0) {
// Find the index of the next set bit.
int index = __builtin_ctzll(set_uniforms);
uint32_t index = (uint32_t)__builtin_ctzll(set_uniforms);
// Clear the set bit.
set_uniforms &= (set_uniforms - 1);
MDUniformSet *set = render.uniform_sets[index];
if (set == nullptr || set->index >= (uint32_t)shader->sets.size()) {
if (set == nullptr || index >= (uint32_t)shader->sets.size()) {
continue;
}
set->bind_uniforms(shader, render);
set->bind_uniforms(shader, render, index);
}
}
@ -610,7 +612,7 @@ void MDCommandBuffer::_render_clear_render_area() {
bool shouldClearStencil = (ds_index != RDD::AttachmentReference::UNUSED && pass.attachments[ds_index].shouldClear(subpass, true));
if (shouldClearDepth || shouldClearStencil) {
MDAttachment const &attachment = pass.attachments[ds_index];
BitField<RDD::TextureAspectBits> bits;
BitField<RDD::TextureAspectBits> bits = {};
if (shouldClearDepth && attachment.type & MDAttachmentType::Depth) {
bits.set_flag(RDD::TEXTURE_ASPECT_DEPTH_BIT);
}
@ -955,7 +957,7 @@ void MDCommandBuffer::compute_bind_uniform_set(RDD::UniformSetID p_uniform_set,
MDShader *shader = (MDShader *)(p_shader.id);
MDUniformSet *set = (MDUniformSet *)(p_uniform_set.id);
set->bind_uniforms(shader, compute);
set->bind_uniforms(shader, compute, p_set_index);
}
void MDCommandBuffer::compute_bind_uniform_sets(VectorView<RDD::UniformSetID> p_uniform_sets, RDD::ShaderID p_shader, uint32_t p_first_set_index, uint32_t p_set_count) {
@ -966,7 +968,7 @@ void MDCommandBuffer::compute_bind_uniform_sets(VectorView<RDD::UniformSetID> p_
// TODO(sgc): Bind multiple buffers using [encoder setBuffers:offsets:withRange:]
for (size_t i = 0u; i < p_set_count; ++i) {
MDUniformSet *set = (MDUniformSet *)(p_uniform_sets[i].id);
set->bind_uniforms(shader, compute);
set->bind_uniforms(shader, compute, p_first_set_index + i);
}
}
@ -1052,50 +1054,50 @@ void MDRenderShader::encode_push_constant_data(VectorView<uint32_t> p_data, MDCo
}
}
void MDUniformSet::bind_uniforms_argument_buffers(MDShader *p_shader, MDCommandBuffer::RenderState &p_state) {
void MDUniformSet::bind_uniforms_argument_buffers(MDShader *p_shader, MDCommandBuffer::RenderState &p_state, uint32_t p_set_index) {
DEV_ASSERT(p_shader->uses_argument_buffers);
DEV_ASSERT(p_state.encoder != nil);
UniformSet const &set_info = p_shader->sets[index];
UniformSet const &set_info = p_shader->sets[p_set_index];
id<MTLRenderCommandEncoder> __unsafe_unretained enc = p_state.encoder;
id<MTLDevice> __unsafe_unretained device = enc.device;
BoundUniformSet &bus = bound_uniform_set(p_shader, device, p_state.resource_usage);
BoundUniformSet &bus = bound_uniform_set(p_shader, device, p_state.resource_usage, p_set_index);
// Set the buffer for the vertex stage.
{
uint32_t const *offset = set_info.offsets.getptr(RDD::SHADER_STAGE_VERTEX);
if (offset) {
[enc setVertexBuffer:bus.buffer offset:*offset atIndex:index];
[enc setVertexBuffer:bus.buffer offset:*offset atIndex:p_set_index];
}
}
// Set the buffer for the fragment stage.
{
uint32_t const *offset = set_info.offsets.getptr(RDD::SHADER_STAGE_FRAGMENT);
if (offset) {
[enc setFragmentBuffer:bus.buffer offset:*offset atIndex:index];
[enc setFragmentBuffer:bus.buffer offset:*offset atIndex:p_set_index];
}
}
}
void MDUniformSet::bind_uniforms_direct(MDShader *p_shader, MDCommandBuffer::RenderState &p_state) {
void MDUniformSet::bind_uniforms_direct(MDShader *p_shader, MDCommandBuffer::RenderState &p_state, uint32_t p_set_index) {
DEV_ASSERT(!p_shader->uses_argument_buffers);
DEV_ASSERT(p_state.encoder != nil);
id<MTLRenderCommandEncoder> __unsafe_unretained enc = p_state.encoder;
UniformSet const &set = p_shader->sets[index];
UniformSet const &set = p_shader->sets[p_set_index];
for (uint32_t i = 0; i < MIN(uniforms.size(), set.uniforms.size()); i++) {
RDD::BoundUniform const &uniform = uniforms[i];
UniformInfo ui = set.uniforms[i];
const UniformInfo &ui = set.uniforms[i];
static const RDC::ShaderStage stage_usages[2] = { RDC::ShaderStage::SHADER_STAGE_VERTEX, RDC::ShaderStage::SHADER_STAGE_FRAGMENT };
for (const RDC::ShaderStage stage : stage_usages) {
ShaderStageUsage const stage_usage = ShaderStageUsage(1 << stage);
BindingInfo *bi = ui.bindings.getptr(stage);
const BindingInfo *bi = ui.bindings.getptr(stage);
if (bi == nullptr) {
// No binding for this stage.
continue;
@ -1129,7 +1131,7 @@ void MDUniformSet::bind_uniforms_direct(MDShader *p_shader, MDCommandBuffer::Ren
samplers[j] = sampler;
textures[j] = texture;
}
BindingInfo *sbi = ui.bindings_secondary.getptr(stage);
const BindingInfo *sbi = ui.bindings_secondary.getptr(stage);
if (sbi) {
if (stage == RDD::SHADER_STAGE_VERTEX) {
[enc setVertexSamplerStates:samplers withRange:NSMakeRange(sbi->index, count)];
@ -1175,7 +1177,7 @@ void MDUniformSet::bind_uniforms_direct(MDShader *p_shader, MDCommandBuffer::Ren
[enc setFragmentTexture:obj atIndex:bi->index];
}
BindingInfo *sbi = ui.bindings_secondary.getptr(stage);
const BindingInfo *sbi = ui.bindings_secondary.getptr(stage);
if (sbi) {
id<MTLTexture> tex = obj.parentTexture ? obj.parentTexture : obj;
id<MTLBuffer> buf = tex.buffer;
@ -1256,47 +1258,47 @@ void MDUniformSet::bind_uniforms_direct(MDShader *p_shader, MDCommandBuffer::Ren
}
}
void MDUniformSet::bind_uniforms(MDShader *p_shader, MDCommandBuffer::RenderState &p_state) {
void MDUniformSet::bind_uniforms(MDShader *p_shader, MDCommandBuffer::RenderState &p_state, uint32_t p_set_index) {
if (p_shader->uses_argument_buffers) {
bind_uniforms_argument_buffers(p_shader, p_state);
bind_uniforms_argument_buffers(p_shader, p_state, p_set_index);
} else {
bind_uniforms_direct(p_shader, p_state);
bind_uniforms_direct(p_shader, p_state, p_set_index);
}
}
void MDUniformSet::bind_uniforms_argument_buffers(MDShader *p_shader, MDCommandBuffer::ComputeState &p_state) {
void MDUniformSet::bind_uniforms_argument_buffers(MDShader *p_shader, MDCommandBuffer::ComputeState &p_state, uint32_t p_set_index) {
DEV_ASSERT(p_shader->uses_argument_buffers);
DEV_ASSERT(p_state.encoder != nil);
UniformSet const &set_info = p_shader->sets[index];
UniformSet const &set_info = p_shader->sets[p_set_index];
id<MTLComputeCommandEncoder> enc = p_state.encoder;
id<MTLDevice> device = enc.device;
BoundUniformSet &bus = bound_uniform_set(p_shader, device, p_state.resource_usage);
BoundUniformSet &bus = bound_uniform_set(p_shader, device, p_state.resource_usage, p_set_index);
uint32_t const *offset = set_info.offsets.getptr(RDD::SHADER_STAGE_COMPUTE);
if (offset) {
[enc setBuffer:bus.buffer offset:*offset atIndex:index];
[enc setBuffer:bus.buffer offset:*offset atIndex:p_set_index];
}
}
void MDUniformSet::bind_uniforms_direct(MDShader *p_shader, MDCommandBuffer::ComputeState &p_state) {
void MDUniformSet::bind_uniforms_direct(MDShader *p_shader, MDCommandBuffer::ComputeState &p_state, uint32_t p_set_index) {
DEV_ASSERT(!p_shader->uses_argument_buffers);
DEV_ASSERT(p_state.encoder != nil);
id<MTLComputeCommandEncoder> __unsafe_unretained enc = p_state.encoder;
UniformSet const &set = p_shader->sets[index];
UniformSet const &set = p_shader->sets[p_set_index];
for (uint32_t i = 0; i < uniforms.size(); i++) {
RDD::BoundUniform const &uniform = uniforms[i];
UniformInfo ui = set.uniforms[i];
const UniformInfo &ui = set.uniforms[i];
const RDC::ShaderStage stage = RDC::ShaderStage::SHADER_STAGE_COMPUTE;
const ShaderStageUsage stage_usage = ShaderStageUsage(1 << stage);
BindingInfo *bi = ui.bindings.getptr(stage);
const BindingInfo *bi = ui.bindings.getptr(stage);
if (bi == nullptr) {
// No binding for this stage.
continue;
@ -1326,7 +1328,7 @@ void MDUniformSet::bind_uniforms_direct(MDShader *p_shader, MDCommandBuffer::Com
samplers[j] = sampler;
textures[j] = texture;
}
BindingInfo *sbi = ui.bindings_secondary.getptr(stage);
const BindingInfo *sbi = ui.bindings_secondary.getptr(stage);
if (sbi) {
[enc setSamplerStates:samplers withRange:NSMakeRange(sbi->index, count)];
}
@ -1352,7 +1354,7 @@ void MDUniformSet::bind_uniforms_direct(MDShader *p_shader, MDCommandBuffer::Com
id<MTLTexture> obj = rid::get(uniform.ids[0]);
[enc setTexture:obj atIndex:bi->index];
BindingInfo *sbi = ui.bindings_secondary.getptr(stage);
const BindingInfo *sbi = ui.bindings_secondary.getptr(stage);
if (sbi) {
id<MTLTexture> tex = obj.parentTexture ? obj.parentTexture : obj;
id<MTLBuffer> buf = tex.buffer;
@ -1407,22 +1409,22 @@ void MDUniformSet::bind_uniforms_direct(MDShader *p_shader, MDCommandBuffer::Com
}
}
void MDUniformSet::bind_uniforms(MDShader *p_shader, MDCommandBuffer::ComputeState &p_state) {
void MDUniformSet::bind_uniforms(MDShader *p_shader, MDCommandBuffer::ComputeState &p_state, uint32_t p_set_index) {
if (p_shader->uses_argument_buffers) {
bind_uniforms_argument_buffers(p_shader, p_state);
bind_uniforms_argument_buffers(p_shader, p_state, p_set_index);
} else {
bind_uniforms_direct(p_shader, p_state);
bind_uniforms_direct(p_shader, p_state, p_set_index);
}
}
BoundUniformSet &MDUniformSet::bound_uniform_set(MDShader *p_shader, id<MTLDevice> p_device, ResourceUsageMap &p_resource_usage) {
BoundUniformSet &MDUniformSet::bound_uniform_set(MDShader *p_shader, id<MTLDevice> p_device, ResourceUsageMap &p_resource_usage, uint32_t p_set_index) {
BoundUniformSet *sus = bound_uniforms.getptr(p_shader);
if (sus != nullptr) {
sus->merge_into(p_resource_usage);
return *sus;
}
UniformSet const &set = p_shader->sets[index];
UniformSet const &set = p_shader->sets[p_set_index];
HashMap<id<MTLResource>, StageResourceUsage> bound_resources;
auto add_usage = [&bound_resources](id<MTLResource> __unsafe_unretained res, RDD::ShaderStage stage, MTLResourceUsage usage) {

View file

@ -28,11 +28,12 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef METAL_UTILS_H
#define METAL_UTILS_H
#pragma once
#import <os/log.h>
#import <functional>
#pragma mark - Boolean flags
namespace flags {
@ -101,5 +102,3 @@ private:
extern os_log_t LOG_DRIVER;
// Used for dynamic tracing.
extern os_log_t LOG_INTERVALS;
#endif // METAL_UTILS_H

View file

@ -28,6 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
/**************************************************************************/
/* */
/* Portions of this code were derived from MoltenVK. */
@ -48,16 +50,14 @@
/* permissions and limitations under the License. */
/**************************************************************************/
#ifndef PIXEL_FORMATS_H
#define PIXEL_FORMATS_H
#include "core/typedefs.h"
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
GODOT_CLANG_WARNING_PUSH_AND_IGNORE("-Wdeprecated-declarations")
#import "inflection_map.h"
#import "metal_device_properties.h"
#import "servers/rendering/rendering_device.h"
#include "servers/rendering/rendering_device.h"
#import <Metal/Metal.h>
@ -408,6 +408,4 @@ protected:
TightLocalVector<MTLFormatDesc> _mtl_vertex_format_descs;
};
#pragma clang diagnostic pop
#endif // PIXEL_FORMATS_H
GODOT_CLANG_WARNING_POP

View file

@ -450,8 +450,7 @@ void PixelFormats::initDataFormatCapabilities() {
addDataFormatDesc(X8_D24_UNORM_PACK32, Invalid, Depth24Unorm_Stencil8, Invalid, Invalid, 1, 1, 4, DepthStencil);
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunguarded-availability"
GODOT_CLANG_WARNING_PUSH_AND_IGNORE("-Wunguarded-availability")
addDataFormatDesc(BC1_RGB_UNORM_BLOCK, BC1_RGBA, Invalid, Invalid, Invalid, 4, 4, 8, Compressed);
addDataFormatDesc(BC1_RGB_SRGB_BLOCK, BC1_RGBA_sRGB, Invalid, Invalid, Invalid, 4, 4, 8, Compressed);
@ -476,7 +475,7 @@ void PixelFormats::initDataFormatCapabilities() {
addDataFormatDesc(BC7_UNORM_BLOCK, BC7_RGBAUnorm, Invalid, Invalid, Invalid, 4, 4, 16, Compressed);
addDataFormatDesc(BC7_SRGB_BLOCK, BC7_RGBAUnorm_sRGB, Invalid, Invalid, Invalid, 4, 4, 16, Compressed);
#pragma clang diagnostic pop
GODOT_CLANG_WARNING_POP
addDataFormatDesc(ETC2_R8G8B8_UNORM_BLOCK, ETC2_RGB8, Invalid, Invalid, Invalid, 4, 4, 8, Compressed);
addDataFormatDesc(ETC2_R8G8B8_SRGB_BLOCK, ETC2_RGB8_sRGB, Invalid, Invalid, Invalid, 4, 4, 8, Compressed);
@ -493,32 +492,46 @@ void PixelFormats::initDataFormatCapabilities() {
addDataFormatDesc(EAC_R11G11_SNORM_BLOCK, EAC_RG11Snorm, Invalid, Invalid, Invalid, 4, 4, 16, Compressed);
addDataFormatDesc(ASTC_4x4_UNORM_BLOCK, ASTC_4x4_LDR, Invalid, Invalid, Invalid, 4, 4, 16, Compressed);
addDataFormatDesc(ASTC_4x4_SFLOAT_BLOCK, ASTC_4x4_HDR, Invalid, Invalid, Invalid, 4, 4, 16, Compressed);
addDataFormatDesc(ASTC_4x4_SRGB_BLOCK, ASTC_4x4_sRGB, Invalid, Invalid, Invalid, 4, 4, 16, Compressed);
addDataFormatDesc(ASTC_5x4_UNORM_BLOCK, ASTC_5x4_LDR, Invalid, Invalid, Invalid, 5, 4, 16, Compressed);
addDataFormatDesc(ASTC_5x4_SFLOAT_BLOCK, ASTC_5x4_HDR, Invalid, Invalid, Invalid, 5, 4, 16, Compressed);
addDataFormatDesc(ASTC_5x4_SRGB_BLOCK, ASTC_5x4_sRGB, Invalid, Invalid, Invalid, 5, 4, 16, Compressed);
addDataFormatDesc(ASTC_5x5_UNORM_BLOCK, ASTC_5x5_LDR, Invalid, Invalid, Invalid, 5, 5, 16, Compressed);
addDataFormatDesc(ASTC_5x5_SFLOAT_BLOCK, ASTC_5x5_HDR, Invalid, Invalid, Invalid, 5, 5, 16, Compressed);
addDataFormatDesc(ASTC_5x5_SRGB_BLOCK, ASTC_5x5_sRGB, Invalid, Invalid, Invalid, 5, 5, 16, Compressed);
addDataFormatDesc(ASTC_6x5_UNORM_BLOCK, ASTC_6x5_LDR, Invalid, Invalid, Invalid, 6, 5, 16, Compressed);
addDataFormatDesc(ASTC_6x5_SFLOAT_BLOCK, ASTC_6x5_HDR, Invalid, Invalid, Invalid, 6, 5, 16, Compressed);
addDataFormatDesc(ASTC_6x5_SRGB_BLOCK, ASTC_6x5_sRGB, Invalid, Invalid, Invalid, 6, 5, 16, Compressed);
addDataFormatDesc(ASTC_6x6_UNORM_BLOCK, ASTC_6x6_LDR, Invalid, Invalid, Invalid, 6, 6, 16, Compressed);
addDataFormatDesc(ASTC_6x6_SFLOAT_BLOCK, ASTC_6x6_HDR, Invalid, Invalid, Invalid, 6, 6, 16, Compressed);
addDataFormatDesc(ASTC_6x6_SRGB_BLOCK, ASTC_6x6_sRGB, Invalid, Invalid, Invalid, 6, 6, 16, Compressed);
addDataFormatDesc(ASTC_8x5_UNORM_BLOCK, ASTC_8x5_LDR, Invalid, Invalid, Invalid, 8, 5, 16, Compressed);
addDataFormatDesc(ASTC_8x5_SFLOAT_BLOCK, ASTC_8x5_HDR, Invalid, Invalid, Invalid, 8, 5, 16, Compressed);
addDataFormatDesc(ASTC_8x5_SRGB_BLOCK, ASTC_8x5_sRGB, Invalid, Invalid, Invalid, 8, 5, 16, Compressed);
addDataFormatDesc(ASTC_8x6_UNORM_BLOCK, ASTC_8x6_LDR, Invalid, Invalid, Invalid, 8, 6, 16, Compressed);
addDataFormatDesc(ASTC_8x6_SFLOAT_BLOCK, ASTC_8x6_HDR, Invalid, Invalid, Invalid, 8, 6, 16, Compressed);
addDataFormatDesc(ASTC_8x6_SRGB_BLOCK, ASTC_8x6_sRGB, Invalid, Invalid, Invalid, 8, 6, 16, Compressed);
addDataFormatDesc(ASTC_8x8_UNORM_BLOCK, ASTC_8x8_LDR, Invalid, Invalid, Invalid, 8, 8, 16, Compressed);
addDataFormatDesc(ASTC_8x8_SFLOAT_BLOCK, ASTC_8x8_HDR, Invalid, Invalid, Invalid, 8, 8, 16, Compressed);
addDataFormatDesc(ASTC_8x8_SRGB_BLOCK, ASTC_8x8_sRGB, Invalid, Invalid, Invalid, 8, 8, 16, Compressed);
addDataFormatDesc(ASTC_10x5_UNORM_BLOCK, ASTC_10x5_LDR, Invalid, Invalid, Invalid, 10, 5, 16, Compressed);
addDataFormatDesc(ASTC_10x5_SFLOAT_BLOCK, ASTC_10x5_HDR, Invalid, Invalid, Invalid, 10, 5, 16, Compressed);
addDataFormatDesc(ASTC_10x5_SRGB_BLOCK, ASTC_10x5_sRGB, Invalid, Invalid, Invalid, 10, 5, 16, Compressed);
addDataFormatDesc(ASTC_10x6_UNORM_BLOCK, ASTC_10x6_LDR, Invalid, Invalid, Invalid, 10, 6, 16, Compressed);
addDataFormatDesc(ASTC_10x6_SFLOAT_BLOCK, ASTC_10x6_HDR, Invalid, Invalid, Invalid, 10, 6, 16, Compressed);
addDataFormatDesc(ASTC_10x6_SRGB_BLOCK, ASTC_10x6_sRGB, Invalid, Invalid, Invalid, 10, 6, 16, Compressed);
addDataFormatDesc(ASTC_10x8_UNORM_BLOCK, ASTC_10x8_LDR, Invalid, Invalid, Invalid, 10, 8, 16, Compressed);
addDataFormatDesc(ASTC_10x8_SFLOAT_BLOCK, ASTC_10x8_HDR, Invalid, Invalid, Invalid, 10, 8, 16, Compressed);
addDataFormatDesc(ASTC_10x8_SRGB_BLOCK, ASTC_10x8_sRGB, Invalid, Invalid, Invalid, 10, 8, 16, Compressed);
addDataFormatDesc(ASTC_10x10_UNORM_BLOCK, ASTC_10x10_LDR, Invalid, Invalid, Invalid, 10, 10, 16, Compressed);
addDataFormatDesc(ASTC_10x10_SFLOAT_BLOCK, ASTC_10x10_HDR, Invalid, Invalid, Invalid, 10, 10, 16, Compressed);
addDataFormatDesc(ASTC_10x10_SRGB_BLOCK, ASTC_10x10_sRGB, Invalid, Invalid, Invalid, 10, 10, 16, Compressed);
addDataFormatDesc(ASTC_12x10_UNORM_BLOCK, ASTC_12x10_LDR, Invalid, Invalid, Invalid, 12, 10, 16, Compressed);
addDataFormatDesc(ASTC_12x10_SFLOAT_BLOCK, ASTC_12x10_HDR, Invalid, Invalid, Invalid, 12, 10, 16, Compressed);
addDataFormatDesc(ASTC_12x10_SRGB_BLOCK, ASTC_12x10_sRGB, Invalid, Invalid, Invalid, 12, 10, 16, Compressed);
addDataFormatDesc(ASTC_12x12_UNORM_BLOCK, ASTC_12x12_LDR, Invalid, Invalid, Invalid, 12, 12, 16, Compressed);
addDataFormatDesc(ASTC_12x12_SFLOAT_BLOCK, ASTC_12x12_HDR, Invalid, Invalid, Invalid, 12, 12, 16, Compressed);
addDataFormatDesc(ASTC_12x12_SRGB_BLOCK, ASTC_12x12_sRGB, Invalid, Invalid, Invalid, 12, 12, 16, Compressed);
addDfFormatDescChromaSubsampling(G8B8G8R8_422_UNORM, GBGR422, 1, 8, 2, 1, 4);
@ -715,8 +728,7 @@ void PixelFormats::initMTLPixelFormatCapabilities() {
addMTLPixelFormatDescSRGB(ASTC_12x12_sRGB, ASTC_12x12, RF, ASTC_12x12_LDR);
addMTLPixelFormatDesc(ASTC_12x12_HDR, ASTC_12x12, RF);
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunguarded-availability"
GODOT_CLANG_WARNING_PUSH_AND_IGNORE("-Wunguarded-availability")
addMTLPixelFormatDesc(BC1_RGBA, BC1_RGBA, RF);
addMTLPixelFormatDescSRGB(BC1_RGBA_sRGB, BC1_RGBA, RF, BC1_RGBA);
@ -733,7 +745,7 @@ void PixelFormats::initMTLPixelFormatCapabilities() {
addMTLPixelFormatDesc(BC7_RGBAUnorm, BC7_RGBA, RF);
addMTLPixelFormatDescSRGB(BC7_RGBAUnorm_sRGB, BC7_RGBA, RF, BC7_RGBAUnorm);
#pragma clang diagnostic pop
GODOT_CLANG_WARNING_POP
// YUV pixel formats
addMTLPixelFormatDesc(GBGR422, None, RF);
@ -954,8 +966,7 @@ void PixelFormats::modifyMTLFormatCapabilities(const MetalFeatures &p_feat) {
setMTLPixFmtCapsIf(noHDR_ASTC, ASTC_12x10_HDR, None);
setMTLPixFmtCapsIf(noHDR_ASTC, ASTC_12x12_HDR, None);
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunguarded-availability"
GODOT_CLANG_WARNING_PUSH_AND_IGNORE("-Wunguarded-availability")
bool noBC = !p_feat.supportsBCTextureCompression;
setMTLPixFmtCapsIf(noBC, BC1_RGBA, None);
@ -973,7 +984,7 @@ void PixelFormats::modifyMTLFormatCapabilities(const MetalFeatures &p_feat) {
setMTLPixFmtCapsIf(noBC, BC7_RGBAUnorm, None);
setMTLPixFmtCapsIf(noBC, BC7_RGBAUnorm_sRGB, None);
#pragma clang diagnostic pop
GODOT_CLANG_WARNING_POP
setMTLPixFmtCapsIf(iosOnly2, BGRA10_XR, None);
setMTLPixFmtCapsIf(iosOnly2, BGRA10_XR_sRGB, None);

View file

@ -28,13 +28,12 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef RENDERING_CONTEXT_DRIVER_METAL_H
#define RENDERING_CONTEXT_DRIVER_METAL_H
#pragma once
#ifdef METAL_ENABLED
#import "servers/rendering/rendering_context_driver.h"
#import "servers/rendering/rendering_device_driver.h"
#include "servers/rendering/rendering_context_driver.h"
#include "servers/rendering/rendering_device_driver.h"
#import <CoreGraphics/CGGeometry.h>
@ -143,5 +142,3 @@ public:
};
#endif // METAL_ENABLED
#endif // RENDERING_CONTEXT_DRIVER_METAL_H

View file

@ -28,12 +28,11 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef RENDERING_DEVICE_DRIVER_METAL_H
#define RENDERING_DEVICE_DRIVER_METAL_H
#pragma once
#import "metal_objects.h"
#import "servers/rendering/rendering_device_driver.h"
#include "servers/rendering/rendering_device_driver.h"
#import <Metal/Metal.h>
#import <variant>
@ -66,6 +65,8 @@ class API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0)) RenderingDeviceDriverMet
RDD::Capabilities capabilities;
RDD::MultiviewCapabilities multiview_capabilities;
RDD::FragmentShadingRateCapabilities fsr_capabilities;
RDD::FragmentDensityMapCapabilities fdm_capabilities;
id<MTLBinaryArchive> archive = nil;
uint32_t archive_count = 0;
@ -316,7 +317,7 @@ public:
// ----- SUBPASS -----
virtual RenderPassID render_pass_create(VectorView<Attachment> p_attachments, VectorView<Subpass> p_subpasses, VectorView<SubpassDependency> p_subpass_dependencies, uint32_t p_view_count) override final;
virtual RenderPassID render_pass_create(VectorView<Attachment> p_attachments, VectorView<Subpass> p_subpasses, VectorView<SubpassDependency> p_subpass_dependencies, uint32_t p_view_count, AttachmentReference p_fragment_density_map_attachment) override final;
virtual void render_pass_free(RenderPassID p_render_pass) override final;
// ----- COMMANDS -----
@ -421,6 +422,8 @@ public:
virtual uint64_t api_trait_get(ApiTrait p_trait) override final;
virtual bool has_feature(Features p_feature) override final;
virtual const MultiviewCapabilities &get_multiview_capabilities() override final;
virtual const FragmentShadingRateCapabilities &get_fragment_shading_rate_capabilities() override final;
virtual const FragmentDensityMapCapabilities &get_fragment_density_map_capabilities() override final;
virtual String get_api_name() const override final { return "Metal"; }
virtual String get_api_version() const override final;
virtual String get_pipeline_cache_uuid() const override final;
@ -444,5 +447,3 @@ public:
RenderingDeviceDriverMetal(RenderingContextDriverMetal *p_context_driver);
~RenderingDeviceDriverMetal();
};
#endif // RENDERING_DEVICE_DRIVER_METAL_H

View file

@ -53,10 +53,10 @@
#import "pixel_formats.h"
#import "rendering_context_driver_metal.h"
#import "core/io/compression.h"
#import "core/io/marshalls.h"
#import "core/string/ustring.h"
#import "core/templates/hash_map.h"
#include "core/io/compression.h"
#include "core/io/marshalls.h"
#include "core/string/ustring.h"
#include "core/templates/hash_map.h"
#import <Metal/MTLTexture.h>
#import <Metal/Metal.h>
@ -405,6 +405,15 @@ RDD::TextureID RenderingDeviceDriverMetal::texture_create_from_extension(uint64_
RDD::TextureID RenderingDeviceDriverMetal::texture_create_shared(TextureID p_original_texture, const TextureView &p_view) {
id<MTLTexture> src_texture = rid::get(p_original_texture);
NSUInteger slices = src_texture.arrayLength;
if (src_texture.textureType == MTLTextureTypeCube) {
// Metal expects Cube textures to have a slice count of 6.
slices = 6;
} else if (src_texture.textureType == MTLTextureTypeCubeArray) {
// Metal expects Cube Array textures to have 6 slices per layer.
slices *= 6;
}
#if DEV_ENABLED
if (src_texture.sampleCount > 1) {
// TODO(sgc): is it ok to create a shared texture from a multi-sample texture?
@ -434,7 +443,7 @@ RDD::TextureID RenderingDeviceDriverMetal::texture_create_shared(TextureID p_ori
id<MTLTexture> obj = [src_texture newTextureViewWithPixelFormat:format
textureType:src_texture.textureType
levels:NSMakeRange(0, src_texture.mipmapLevelCount)
slices:NSMakeRange(0, src_texture.arrayLength)
slices:NSMakeRange(0, slices)
swizzle:swizzle];
ERR_FAIL_NULL_V_MSG(obj, TextureID(), "Unable to create shared texture");
return rid::make(obj);
@ -566,7 +575,14 @@ void RenderingDeviceDriverMetal::texture_get_copyable_layout(TextureID p_texture
r_layout->size = get_image_format_required_size(format, sz.width, sz.height, sz.depth, 1, &sbw, &sbh);
r_layout->row_pitch = r_layout->size / ((sbh / bh) * sz.depth);
r_layout->depth_pitch = r_layout->size / sz.depth;
r_layout->layer_pitch = r_layout->size / obj.arrayLength;
uint32_t array_length = obj.arrayLength;
if (obj.textureType == MTLTextureTypeCube) {
array_length = 6;
} else if (obj.textureType == MTLTextureTypeCubeArray) {
array_length *= 6;
}
r_layout->layer_pitch = r_layout->size / array_length;
} else {
CRASH_NOW_MSG("need to calculate layout for shared texture");
}
@ -974,7 +990,7 @@ RDD::SwapChainID RenderingDeviceDriverMetal::swap_chain_create(RenderingContextD
color_ref.aspect.set_flag(RDD::TEXTURE_ASPECT_COLOR_BIT);
subpass.color_references.push_back(color_ref);
RenderPassID render_pass = render_pass_create(attachment, subpass, {}, 1);
RenderPassID render_pass = render_pass_create(attachment, subpass, {}, 1, RDD::AttachmentReference());
ERR_FAIL_COND_V(!render_pass, SwapChainID());
// Create the empty swap chain until it is resized.
@ -2460,6 +2476,8 @@ RDD::ShaderID RenderingDeviceDriverMetal::shader_create_from_bytecode(const Vect
HashMap<ShaderStage, MDLibrary *> libraries;
for (ShaderStageData &shader_data : binary_data.stages) {
r_shader_desc.stages.push_back(shader_data.stage);
SHA256Digest key = SHA256Digest(shader_data.source.ptr(), shader_data.source.length());
if (ShaderCacheEntry **p = _shader_cache.getptr(key); p != nullptr) {
@ -2506,7 +2524,7 @@ RDD::ShaderID RenderingDeviceDriverMetal::shader_create_from_bytecode(const Vect
su.writable = uniform.writable;
su.length = uniform.length;
su.binding = uniform.binding;
su.stages = uniform.stages;
su.stages = (ShaderStage)(uint8_t)uniform.stages;
uset.write[i] = su;
UniformInfo ui;
@ -2572,7 +2590,7 @@ RDD::ShaderID RenderingDeviceDriverMetal::shader_create_from_bytecode(const Vect
sc.type = c.type;
sc.constant_id = c.constant_id;
sc.int_value = c.int_value;
sc.stages = c.stages;
sc.stages = (ShaderStage)(uint8_t)c.stages;
r_shader_desc.specialization_constants.write[i] = sc;
}
@ -3044,7 +3062,7 @@ void RenderingDeviceDriverMetal::command_bind_push_constants(CommandBufferID p_c
String RenderingDeviceDriverMetal::_pipeline_get_cache_path() const {
String path = OS::get_singleton()->get_user_data_dir() + "/metal/pipelines";
path += "." + context_device.name.validate_filename().replace(" ", "_").to_lower();
path += "." + context_device.name.validate_filename().replace_char(' ', '_').to_lower();
if (Engine::get_singleton()->is_editor_hint()) {
path += ".editor";
}
@ -3102,7 +3120,7 @@ Vector<uint8_t> RenderingDeviceDriverMetal::pipeline_cache_serialize() {
// ----- SUBPASS -----
RDD::RenderPassID RenderingDeviceDriverMetal::render_pass_create(VectorView<Attachment> p_attachments, VectorView<Subpass> p_subpasses, VectorView<SubpassDependency> p_subpass_dependencies, uint32_t p_view_count) {
RDD::RenderPassID RenderingDeviceDriverMetal::render_pass_create(VectorView<Attachment> p_attachments, VectorView<Subpass> p_subpasses, VectorView<SubpassDependency> p_subpass_dependencies, uint32_t p_view_count, AttachmentReference p_fragment_density_map_attachment) {
PixelFormats &pf = *pixel_formats;
size_t subpass_count = p_subpasses.size();
@ -3899,16 +3917,16 @@ uint64_t RenderingDeviceDriverMetal::get_lazily_memory_used() {
uint64_t RenderingDeviceDriverMetal::limit_get(Limit p_limit) {
MetalDeviceProperties const &props = (*device_properties);
MetalLimits const &limits = props.limits;
uint64_t safe_unbounded = ((uint64_t)1 << 30);
#if defined(DEV_ENABLED)
#define UNKNOWN(NAME) \
case NAME: \
WARN_PRINT_ONCE("Returning maximum value for unknown limit " #NAME "."); \
return (uint64_t)1 << 30;
return safe_unbounded;
#else
#define UNKNOWN(NAME) \
case NAME: \
return (uint64_t)1 << 30
return safe_unbounded
#endif
// clang-format off
@ -3981,6 +3999,8 @@ uint64_t RenderingDeviceDriverMetal::limit_get(Limit p_limit) {
return limits.maxThreadsPerThreadGroup.height;
case LIMIT_MAX_COMPUTE_WORKGROUP_SIZE_Z:
return limits.maxThreadsPerThreadGroup.depth;
case LIMIT_MAX_COMPUTE_SHARED_MEMORY_SIZE:
return limits.maxThreadGroupMemoryAllocation;
case LIMIT_MAX_VIEWPORT_DIMENSIONS_X:
return limits.maxViewportDimensionX;
case LIMIT_MAX_VIEWPORT_DIMENSIONS_Y:
@ -4002,12 +4022,12 @@ uint64_t RenderingDeviceDriverMetal::limit_get(Limit p_limit) {
return (uint64_t)((1.0 / limits.temporalScalerInputContentMinScale) * 1000'000);
case LIMIT_MAX_SHADER_VARYINGS:
return limits.maxShaderVaryings;
UNKNOWN(LIMIT_VRS_TEXEL_WIDTH);
UNKNOWN(LIMIT_VRS_TEXEL_HEIGHT);
UNKNOWN(LIMIT_VRS_MAX_FRAGMENT_WIDTH);
UNKNOWN(LIMIT_VRS_MAX_FRAGMENT_HEIGHT);
default:
ERR_FAIL_V(0);
default: {
#ifdef DEV_ENABLED
WARN_PRINT("Returning maximum value for unknown limit " + itos(p_limit) + ".");
#endif
return safe_unbounded;
}
}
// clang-format on
return 0;
@ -4024,17 +4044,8 @@ uint64_t RenderingDeviceDriverMetal::api_trait_get(ApiTrait p_trait) {
bool RenderingDeviceDriverMetal::has_feature(Features p_feature) {
switch (p_feature) {
case SUPPORTS_MULTIVIEW:
return multiview_capabilities.is_supported;
case SUPPORTS_FSR_HALF_FLOAT:
return true;
case SUPPORTS_ATTACHMENT_VRS:
// TODO(sgc): Maybe supported via https://developer.apple.com/documentation/metal/render_passes/rendering_at_different_rasterization_rates?language=objc
// See also:
//
// * https://forum.beyond3d.com/threads/variable-rate-shading-vs-variable-rate-rasterization.62243/post-2191363
//
return false;
case SUPPORTS_FRAGMENT_SHADER_WITH_ONLY_SIDE_EFFECTS:
return true;
case SUPPORTS_BUFFER_DEVICE_ADDRESS:
@ -4052,6 +4063,14 @@ const RDD::MultiviewCapabilities &RenderingDeviceDriverMetal::get_multiview_capa
return multiview_capabilities;
}
const RDD::FragmentShadingRateCapabilities &RenderingDeviceDriverMetal::get_fragment_shading_rate_capabilities() {
return fsr_capabilities;
}
const RDD::FragmentDensityMapCapabilities &RenderingDeviceDriverMetal::get_fragment_density_map_capabilities() {
return fdm_capabilities;
}
String RenderingDeviceDriverMetal::get_api_version() const {
return vformat("%d.%d", version_major, version_minor);
}

View file

@ -30,9 +30,9 @@ if env["builtin_libpng"]:
]
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
env_png.Prepend(CPPPATH=[thirdparty_dir])
env_png.Prepend(CPPEXTPATH=[thirdparty_dir])
# Needed for drivers includes and in platform/web.
env.Prepend(CPPPATH=[thirdparty_dir])
env.Prepend(CPPEXTPATH=[thirdparty_dir])
env_thirdparty = env_png.Clone()
env_thirdparty.disable_warnings()

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef IMAGE_LOADER_PNG_H
#define IMAGE_LOADER_PNG_H
#pragma once
#include "core/io/image_loader.h"
@ -45,5 +44,3 @@ public:
virtual void get_recognized_extensions(List<String> *p_extensions) const;
ImageLoaderPNG();
};
#endif // IMAGE_LOADER_PNG_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef PNG_DRIVER_COMMON_H
#define PNG_DRIVER_COMMON_H
#pragma once
#include "core/io/image.h"
@ -42,5 +41,3 @@ Error png_to_image(const uint8_t *p_source, size_t p_size, bool p_force_linear,
// Contents of p_buffer is unspecified if error returned.
Error image_to_png(const Ref<Image> &p_image, Vector<uint8_t> &p_buffer);
} // namespace PNGDriverCommon
#endif // PNG_DRIVER_COMMON_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef RESOURCE_SAVER_PNG_H
#define RESOURCE_SAVER_PNG_H
#pragma once
#include "core/io/image.h"
#include "core/io/resource_saver.h"
@ -45,5 +44,3 @@ public:
ResourceSaverPNG();
};
#endif // RESOURCE_SAVER_PNG_H

View file

@ -312,11 +312,11 @@ Error AudioDriverPulseAudio::init() {
String context_name;
if (Engine::get_singleton()->is_editor_hint()) {
context_name = VERSION_NAME " Editor";
context_name = GODOT_VERSION_NAME " Editor";
} else {
context_name = GLOBAL_GET("application/config/name");
if (context_name.is_empty()) {
context_name = VERSION_NAME " Project";
context_name = GODOT_VERSION_NAME " Project";
}
}

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef AUDIO_DRIVER_PULSEAUDIO_H
#define AUDIO_DRIVER_PULSEAUDIO_H
#pragma once
#ifdef PULSEAUDIO_ENABLED
@ -128,5 +127,3 @@ public:
};
#endif // PULSEAUDIO_ENABLED
#endif // AUDIO_DRIVER_PULSEAUDIO_H

View file

@ -28,13 +28,10 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef REGISTER_DRIVER_TYPES_H
#define REGISTER_DRIVER_TYPES_H
#pragma once
void register_core_driver_types();
void unregister_core_driver_types();
void register_driver_types();
void unregister_driver_types();
#endif // REGISTER_DRIVER_TYPES_H

View file

@ -43,6 +43,7 @@
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#ifdef HAVE_MNTENT
@ -256,7 +257,7 @@ static void _get_drives(List<String> *list) {
// Parse only file:// links
if (strncmp(string, "file://", 7) == 0) {
// Strip any unwanted edges on the strings and push_back if it's not a duplicate.
String fpath = String::utf8(string + 7).strip_edges().split_spaces()[0].uri_decode();
String fpath = String::utf8(string + 7).strip_edges().split_spaces()[0].uri_file_decode();
if (!list->find(fpath)) {
list->push_back(fpath);
}
@ -342,7 +343,7 @@ Error DirAccessUnix::change_dir(String p_dir) {
String prev_dir;
char real_current_dir_name[2048];
ERR_FAIL_NULL_V(getcwd(real_current_dir_name, 2048), ERR_BUG);
if (prev_dir.parse_utf8(real_current_dir_name) != OK) {
if (prev_dir.append_utf8(real_current_dir_name) != OK) {
prev_dir = real_current_dir_name; //no utf8, maybe latin?
}
@ -365,7 +366,7 @@ Error DirAccessUnix::change_dir(String p_dir) {
if (!base.is_empty() && !try_dir.begins_with(base)) {
ERR_FAIL_NULL_V(getcwd(real_current_dir_name, 2048), ERR_BUG);
String new_dir;
new_dir.parse_utf8(real_current_dir_name);
new_dir.append_utf8(real_current_dir_name);
if (!new_dir.begins_with(base)) {
try_dir = current_dir; //revert
@ -383,7 +384,7 @@ String DirAccessUnix::get_current_dir(bool p_include_drive) const {
if (!base.is_empty()) {
String bd = current_dir.replace_first(base, "");
if (bd.begins_with("/")) {
return _get_root_string() + bd.substr(1, bd.length());
return _get_root_string() + bd.substr(1);
} else {
return _get_root_string() + bd;
}
@ -486,7 +487,7 @@ String DirAccessUnix::read_link(String p_file) {
ssize_t len = readlink(p_file.utf8().get_data(), buf, sizeof(buf));
String link;
if (len > 0) {
link.parse_utf8(buf, len);
link.append_utf8(buf, len);
}
return link;
}
@ -544,6 +545,24 @@ bool DirAccessUnix::is_case_sensitive(const String &p_path) const {
return true;
}
bool DirAccessUnix::is_equivalent(const String &p_path_a, const String &p_path_b) const {
String f1 = fix_path(p_path_a);
struct stat st1 = {};
int err = stat(f1.utf8().get_data(), &st1);
if (err) {
return DirAccess::is_equivalent(p_path_a, p_path_b);
}
String f2 = fix_path(p_path_b);
struct stat st2 = {};
err = stat(f2.utf8().get_data(), &st2);
if (err) {
return DirAccess::is_equivalent(p_path_a, p_path_b);
}
return (st1.st_dev == st2.st_dev) && (st1.st_ino == st2.st_ino);
}
DirAccessUnix::DirAccessUnix() {
dir_stream = nullptr;
_cisdir = false;
@ -553,7 +572,8 @@ DirAccessUnix::DirAccessUnix() {
// set current directory to an absolute path of the current directory
char real_current_dir_name[2048];
ERR_FAIL_NULL(getcwd(real_current_dir_name, 2048));
if (current_dir.parse_utf8(real_current_dir_name) != OK) {
current_dir.clear();
if (current_dir.append_utf8(real_current_dir_name) != OK) {
current_dir = real_current_dir_name;
}

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef DIR_ACCESS_UNIX_H
#define DIR_ACCESS_UNIX_H
#pragma once
#if defined(UNIX_ENABLED)
@ -41,6 +40,7 @@
#include <unistd.h>
class DirAccessUnix : public DirAccess {
GDSOFTCLASS(DirAccessUnix, DirAccess);
DIR *dir_stream = nullptr;
bool _cisdir = false;
@ -86,6 +86,7 @@ public:
virtual Error create_link(String p_source, String p_target) override;
virtual bool is_case_sensitive(const String &p_path) const override;
virtual bool is_equivalent(const String &p_path_a, const String &p_path_b) const override;
virtual uint64_t get_space_left() override;
@ -96,5 +97,3 @@ public:
};
#endif // UNIX_ENABLED
#endif // DIR_ACCESS_UNIX_H

View file

@ -211,7 +211,7 @@ String FileAccessUnix::get_real_path() const {
}
String result;
Error parse_ok = result.parse_utf8(resolved_path);
Error parse_ok = result.append_utf8(resolved_path);
::free(resolved_path);
if (parse_ok != OK) {
@ -336,16 +336,19 @@ bool FileAccessUnix::file_exists(const String &p_path) {
uint64_t FileAccessUnix::_get_modified_time(const String &p_file) {
String file = fix_path(p_file);
struct stat status = {};
int err = stat(file.utf8().get_data(), &status);
struct stat st = {};
int err = stat(file.utf8().get_data(), &st);
if (!err) {
uint64_t modified_time = status.st_mtime;
uint64_t modified_time = 0;
if ((st.st_mode & S_IFMT) == S_IFLNK || (st.st_mode & S_IFMT) == S_IFREG || (st.st_mode & S_IFDIR) == S_IFDIR) {
modified_time = st.st_mtime;
}
#ifdef ANDROID_ENABLED
// Workaround for GH-101007
//FIXME: After saving, all timestamps (st_mtime, st_ctime, st_atime) are set to the same value.
// After exporting or after some time, only 'modified_time' resets to a past timestamp.
uint64_t created_time = status.st_ctime;
uint64_t created_time = st.st_ctime;
if (modified_time < created_time) {
modified_time = created_time;
}
@ -356,6 +359,32 @@ uint64_t FileAccessUnix::_get_modified_time(const String &p_file) {
}
}
uint64_t FileAccessUnix::_get_access_time(const String &p_file) {
String file = fix_path(p_file);
struct stat st = {};
int err = stat(file.utf8().get_data(), &st);
if (!err) {
if ((st.st_mode & S_IFMT) == S_IFLNK || (st.st_mode & S_IFMT) == S_IFREG || (st.st_mode & S_IFDIR) == S_IFDIR) {
return st.st_atime;
}
}
ERR_FAIL_V_MSG(0, "Failed to get access time for: " + p_file + "");
}
int64_t FileAccessUnix::_get_size(const String &p_file) {
String file = fix_path(p_file);
struct stat st = {};
int err = stat(file.utf8().get_data(), &st);
if (!err) {
if ((st.st_mode & S_IFMT) == S_IFLNK || (st.st_mode & S_IFMT) == S_IFREG) {
return st.st_size;
}
}
ERR_FAIL_V_MSG(-1, "Failed to get size for: " + p_file + "");
}
BitField<FileAccess::UnixPermissionFlags> FileAccessUnix::_get_unix_permissions(const String &p_file) {
String file = fix_path(p_file);
struct stat status = {};

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef FILE_ACCESS_UNIX_H
#define FILE_ACCESS_UNIX_H
#pragma once
#include "core/io/file_access.h"
#include "core/os/memory.h"
@ -39,6 +38,7 @@
#if defined(UNIX_ENABLED)
class FileAccessUnix : public FileAccess {
GDSOFTCLASS(FileAccessUnix, FileAccess);
FILE *f = nullptr;
int flags = 0;
void check_errors(bool p_write = false) const;
@ -81,6 +81,8 @@ public:
virtual bool file_exists(const String &p_path) override; ///< return true if a file exists
virtual uint64_t _get_modified_time(const String &p_file) override;
virtual uint64_t _get_access_time(const String &p_file) override;
virtual int64_t _get_size(const String &p_file) override;
virtual BitField<FileAccess::UnixPermissionFlags> _get_unix_permissions(const String &p_file) override;
virtual Error _set_unix_permissions(const String &p_file, BitField<FileAccess::UnixPermissionFlags> p_permissions) override;
@ -96,5 +98,3 @@ public:
};
#endif // UNIX_ENABLED
#endif // FILE_ACCESS_UNIX_H

View file

@ -67,7 +67,7 @@ Error FileAccessUnixPipe::open_internal(const String &p_path, int p_mode_flags)
path_src = p_path;
ERR_FAIL_COND_V_MSG(fd[0] >= 0 || fd[1] >= 0, ERR_ALREADY_IN_USE, "Pipe is already in use.");
path = String("/tmp/") + p_path.replace("pipe://", "").replace("/", "_");
path = String("/tmp/") + p_path.replace("pipe://", "").replace_char('/', '_');
const CharString path_utf8 = path.utf8();
struct stat st = {};

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef FILE_ACCESS_UNIX_PIPE_H
#define FILE_ACCESS_UNIX_PIPE_H
#pragma once
#include "core/io/file_access.h"
#include "core/os/memory.h"
@ -39,6 +38,7 @@
#if defined(UNIX_ENABLED)
class FileAccessUnixPipe : public FileAccess {
GDSOFTCLASS(FileAccessUnixPipe, FileAccess);
bool unlink_on_close = false;
int fd[2] = { -1, -1 };
@ -76,6 +76,8 @@ public:
virtual bool file_exists(const String &p_path) override { return false; }
virtual uint64_t _get_modified_time(const String &p_file) override { return 0; }
virtual uint64_t _get_access_time(const String &p_file) override { return 0; }
virtual int64_t _get_size(const String &p_file) override { return -1; }
virtual BitField<FileAccess::UnixPermissionFlags> _get_unix_permissions(const String &p_file) override { return 0; }
virtual Error _set_unix_permissions(const String &p_file, BitField<FileAccess::UnixPermissionFlags> p_permissions) override { return ERR_UNAVAILABLE; }
@ -91,5 +93,3 @@ public:
};
#endif // UNIX_ENABLED
#endif // FILE_ACCESS_UNIX_PIPE_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef IP_UNIX_H
#define IP_UNIX_H
#pragma once
#if defined(UNIX_ENABLED) && !defined(UNIX_SOCKET_UNAVAILABLE)
@ -50,5 +49,3 @@ public:
};
#endif // UNIX_ENABLED
#endif // IP_UNIX_H

View file

@ -135,10 +135,7 @@ NetSocketUnix::~NetSocketUnix() {
// Silence a warning reported in GH-27594.
// EAGAIN and EWOULDBLOCK have the same value on most platforms, but it's not guaranteed.
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wlogical-op"
#endif
GODOT_GCC_WARNING_PUSH_AND_IGNORE("-Wlogical-op")
NetSocketUnix::NetError NetSocketUnix::_get_socket_error() const {
if (errno == EISCONN) {
@ -163,9 +160,7 @@ NetSocketUnix::NetError NetSocketUnix::_get_socket_error() const {
return ERR_NET_OTHER;
}
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic pop
#endif
GODOT_GCC_WARNING_POP
bool NetSocketUnix::_can_use_ip(const IPAddress &p_ip, const bool p_for_bind) const {
if (p_for_bind && !(p_ip.is_valid() || p_ip.is_wildcard())) {

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef NET_SOCKET_UNIX_H
#define NET_SOCKET_UNIX_H
#pragma once
#if defined(UNIX_ENABLED) && !defined(UNIX_SOCKET_UNAVAILABLE)
@ -98,5 +97,3 @@ public:
};
#endif // UNIX_ENABLED && !UNIX_SOCKET_UNAVAILABLE
#endif // NET_SOCKET_UNIX_H

View file

@ -580,6 +580,126 @@ Dictionary OS_Unix::get_memory_info() const {
return meminfo;
}
#ifndef __GLIBC__
void OS_Unix::_load_iconv() {
#if defined(MACOS_ENABLED) || defined(IOS_ENABLED)
String iconv_lib_aliases[] = { "/usr/lib/libiconv.2.dylib" };
String iconv_func_aliases[] = { "iconv" };
String charset_lib_aliases[] = { "/usr/lib/libcharset.1.dylib" };
#else
String iconv_lib_aliases[] = { "", "libiconv.2.so", "libiconv.so" };
String iconv_func_aliases[] = { "libiconv", "iconv", "bsd_iconv", "rpl_iconv" };
String charset_lib_aliases[] = { "", "libcharset.1.so", "libcharset.so" };
#endif
for (size_t i = 0; i < sizeof(iconv_lib_aliases) / sizeof(iconv_lib_aliases[0]); i++) {
void *iconv_lib = iconv_lib_aliases[i].is_empty() ? RTLD_NEXT : dlopen(iconv_lib_aliases[i].utf8().get_data(), RTLD_NOW);
if (iconv_lib) {
for (size_t j = 0; j < sizeof(iconv_func_aliases) / sizeof(iconv_func_aliases[0]); j++) {
gd_iconv_open = (PIConvOpen)dlsym(iconv_lib, (iconv_func_aliases[j] + "_open").utf8().get_data());
gd_iconv = (PIConv)dlsym(iconv_lib, (iconv_func_aliases[j]).utf8().get_data());
gd_iconv_close = (PIConvClose)dlsym(iconv_lib, (iconv_func_aliases[j] + "_close").utf8().get_data());
if (gd_iconv_open && gd_iconv && gd_iconv_close) {
break;
}
}
if (gd_iconv_open && gd_iconv && gd_iconv_close) {
break;
}
if (!iconv_lib_aliases[i].is_empty()) {
dlclose(iconv_lib);
}
}
}
for (size_t i = 0; i < sizeof(charset_lib_aliases) / sizeof(charset_lib_aliases[0]); i++) {
void *cs_lib = charset_lib_aliases[i].is_empty() ? RTLD_NEXT : dlopen(charset_lib_aliases[i].utf8().get_data(), RTLD_NOW);
if (cs_lib) {
gd_locale_charset = (PIConvLocaleCharset)dlsym(cs_lib, "locale_charset");
if (gd_locale_charset) {
break;
}
if (!charset_lib_aliases[i].is_empty()) {
dlclose(cs_lib);
}
}
}
_iconv_ok = gd_iconv_open && gd_iconv && gd_iconv_close && gd_locale_charset;
}
#endif
String OS_Unix::multibyte_to_string(const String &p_encoding, const PackedByteArray &p_array) const {
ERR_FAIL_COND_V_MSG(!_iconv_ok, String(), "Conversion failed: Unable to load libiconv");
LocalVector<char> chars;
#ifdef __GLIBC__
gd_iconv_t ctx = gd_iconv_open("UTF-8", p_encoding.is_empty() ? nl_langinfo(CODESET) : p_encoding.utf8().get_data());
#else
gd_iconv_t ctx = gd_iconv_open("UTF-8", p_encoding.is_empty() ? gd_locale_charset() : p_encoding.utf8().get_data());
#endif
ERR_FAIL_COND_V_MSG(ctx == (gd_iconv_t)(-1), String(), "Conversion failed: Unknown encoding");
char *in_ptr = (char *)p_array.ptr();
size_t in_size = p_array.size();
chars.resize(in_size);
char *out_ptr = (char *)chars.ptr();
size_t out_size = chars.size();
while (gd_iconv(ctx, &in_ptr, &in_size, &out_ptr, &out_size) == (size_t)-1) {
if (errno != E2BIG) {
gd_iconv_close(ctx);
ERR_FAIL_V_MSG(String(), vformat("Conversion failed: %d - %s", errno, strerror(errno)));
}
int64_t rate = (chars.size()) / (p_array.size() - in_size);
size_t oldpos = chars.size() - out_size;
chars.resize(chars.size() + in_size * rate);
out_ptr = (char *)chars.ptr() + oldpos;
out_size = chars.size() - oldpos;
}
chars.resize(chars.size() - out_size);
gd_iconv_close(ctx);
return String::utf8((const char *)chars.ptr(), chars.size());
}
PackedByteArray OS_Unix::string_to_multibyte(const String &p_encoding, const String &p_string) const {
ERR_FAIL_COND_V_MSG(!_iconv_ok, PackedByteArray(), "Conversion failed: Unable to load libiconv");
CharString charstr = p_string.utf8();
PackedByteArray ret;
#ifdef __GLIBC__
gd_iconv_t ctx = gd_iconv_open(p_encoding.is_empty() ? nl_langinfo(CODESET) : p_encoding.utf8().get_data(), "UTF-8");
#else
gd_iconv_t ctx = gd_iconv_open(p_encoding.is_empty() ? gd_locale_charset() : p_encoding.utf8().get_data(), "UTF-8");
#endif
ERR_FAIL_COND_V_MSG(ctx == (gd_iconv_t)(-1), PackedByteArray(), "Conversion failed: Unknown encoding");
char *in_ptr = (char *)charstr.ptr();
size_t in_size = charstr.size();
ret.resize(in_size);
char *out_ptr = (char *)ret.ptrw();
size_t out_size = ret.size();
while (gd_iconv(ctx, &in_ptr, &in_size, &out_ptr, &out_size) == (size_t)-1) {
if (errno != E2BIG) {
gd_iconv_close(ctx);
ERR_FAIL_V_MSG(PackedByteArray(), vformat("Conversion failed: %d - %s", errno, strerror(errno)));
}
int64_t rate = (ret.size()) / (charstr.size() - in_size);
size_t oldpos = ret.size() - out_size;
ret.resize(ret.size() + in_size * rate);
out_ptr = (char *)ret.ptrw() + oldpos;
out_size = ret.size() - oldpos;
}
ret.resize(ret.size() - out_size);
gd_iconv_close(ctx);
return ret;
}
Dictionary OS_Unix::execute_with_pipe(const String &p_path, const List<String> &p_arguments, bool p_blocking) {
#define CLEAN_PIPES \
if (pipe_in[0] >= 0) { \
@ -685,6 +805,57 @@ Dictionary OS_Unix::execute_with_pipe(const String &p_path, const List<String> &
#endif
}
int OS_Unix::_wait_for_pid_completion(const pid_t p_pid, int *r_status, int p_options) {
while (true) {
if (waitpid(p_pid, r_status, p_options) != -1) {
// Thread exited normally.
return 0;
}
const int error = errno;
if (error == EINTR) {
// We're in a debugger, should call waitpid again.
// See https://stackoverflow.com/a/45472920/730797.
continue;
}
return error;
}
}
bool OS_Unix::_check_pid_is_running(const pid_t p_pid, int *r_status) const {
const ProcessInfo *pi = process_map->getptr(p_pid);
if (pi && !pi->is_running) {
// Can return cached value.
if (r_status) {
*r_status = pi->exit_code;
}
return false;
}
int status = 0;
const int result = _wait_for_pid_completion(p_pid, &status, WNOHANG);
if (result == 0) {
// Thread is still running.
return true;
}
ERR_FAIL_COND_V_MSG(result == -1, false, vformat("Thread %d exited with errno: %d", (int)p_pid, errno));
// Thread exited normally.
status = WIFEXITED(status) ? WEXITSTATUS(status) : status;
if (pi) {
pi->is_running = false;
pi->exit_code = status;
}
if (r_status) {
*r_status = status;
}
return false;
}
Error OS_Unix::execute(const String &p_path, const List<String> &p_arguments, String *r_pipe, int *r_exitcode, bool read_stderr, Mutex *p_pipe_mutex, bool p_open_console) {
#ifdef __EMSCRIPTEN__
// Don't compile this code at all to avoid undefined references.
@ -710,7 +881,7 @@ Error OS_Unix::execute(const String &p_path, const List<String> &p_arguments, St
p_pipe_mutex->lock();
}
String pipe_out;
if (pipe_out.parse_utf8(buf) == OK) {
if (pipe_out.append_utf8(buf) == OK) {
(*r_pipe) += pipe_out;
} else {
(*r_pipe) += String(buf); // If not valid UTF-8 try decode as Latin-1
@ -750,12 +921,12 @@ Error OS_Unix::execute(const String &p_path, const List<String> &p_arguments, St
raise(SIGKILL);
}
int status;
waitpid(pid, &status, 0);
int status = 0;
const int result = _wait_for_pid_completion(pid, &status, 0);
if (r_exitcode) {
*r_exitcode = WIFEXITED(status) ? WEXITSTATUS(status) : status;
}
return OK;
return result ? FAILED : OK;
#endif
}
@ -809,7 +980,7 @@ Error OS_Unix::kill(const ProcessID &p_pid) {
if (!ret) {
//avoid zombie process
int st;
::waitpid(p_pid, &st, 0);
_wait_for_pid_completion(p_pid, &st, 0);
}
return ret ? ERR_INVALID_PARAMETER : OK;
}
@ -820,42 +991,19 @@ int OS_Unix::get_process_id() const {
bool OS_Unix::is_process_running(const ProcessID &p_pid) const {
MutexLock lock(process_map_mutex);
const ProcessInfo *pi = process_map->getptr(p_pid);
if (pi && !pi->is_running) {
return false;
}
int status = 0;
if (waitpid(p_pid, &status, WNOHANG) != 0) {
if (pi) {
pi->is_running = false;
pi->exit_code = status;
}
return false;
}
return true;
return _check_pid_is_running(p_pid, nullptr);
}
int OS_Unix::get_process_exit_code(const ProcessID &p_pid) const {
MutexLock lock(process_map_mutex);
const ProcessInfo *pi = process_map->getptr(p_pid);
if (pi && !pi->is_running) {
return pi->exit_code;
int exit_code = 0;
if (_check_pid_is_running(p_pid, &exit_code)) {
// Thread is still running
return -1;
}
int status = 0;
if (waitpid(p_pid, &status, WNOHANG) != 0) {
status = WIFEXITED(status) ? WEXITSTATUS(status) : status;
if (pi) {
pi->is_running = false;
pi->exit_code = status;
}
return status;
}
return -1;
return exit_code;
}
String OS_Unix::get_locale() const {
@ -942,7 +1090,7 @@ String OS_Unix::get_environment(const String &p_var) const {
return "";
}
String s;
if (s.parse_utf8(val) == OK) {
if (s.append_utf8(val) == OK) {
return s;
}
return String(val); // Not valid UTF-8, so return as-is
@ -971,7 +1119,7 @@ String OS_Unix::get_executable_path() const {
ssize_t len = readlink("/proc/self/exe", buf, sizeof(buf));
String b;
if (len > 0) {
b.parse_utf8(buf, len);
b.append_utf8(buf, len);
}
if (b.is_empty()) {
WARN_PRINT("Couldn't get executable path from /proc/self/exe, using argv[0]");
@ -1007,9 +1155,8 @@ String OS_Unix::get_executable_path() const {
WARN_PRINT("Couldn't get executable path from sysctl");
return OS::get_executable_path();
}
String b;
b.parse_utf8(buf);
return b;
return String::utf8(buf);
#elif defined(__APPLE__)
char temp_path[1];
uint32_t buff_size = 1;
@ -1082,6 +1229,10 @@ void UnixTerminalLogger::log_error(const char *p_function, const char *p_file, i
UnixTerminalLogger::~UnixTerminalLogger() {}
OS_Unix::OS_Unix() {
#ifndef __GLIBC__
_load_iconv();
#endif
Vector<Logger *> loggers;
loggers.push_back(memnew(UnixTerminalLogger));
_set_logger(memnew(CompositeLogger(loggers)));

View file

@ -28,14 +28,28 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef OS_UNIX_H
#define OS_UNIX_H
#pragma once
#ifdef UNIX_ENABLED
#include "core/os/os.h"
#include "drivers/unix/ip_unix.h"
#ifdef __GLIBC__
#include <iconv.h>
#include <langinfo.h>
#define gd_iconv_t iconv_t
#define gd_iconv_open iconv_open
#define gd_iconv iconv
#define gd_iconv_close iconv_close
#else
typedef void *gd_iconv_t;
typedef gd_iconv_t (*PIConvOpen)(const char *, const char *);
typedef size_t (*PIConv)(gd_iconv_t, char **, size_t *, char **, size_t *);
typedef int (*PIConvClose)(gd_iconv_t);
typedef const char *(*PIConvLocaleCharset)(void);
#endif
class OS_Unix : public OS {
struct ProcessInfo {
mutable bool is_running = true;
@ -44,6 +58,22 @@ class OS_Unix : public OS {
HashMap<ProcessID, ProcessInfo> *process_map = nullptr;
Mutex process_map_mutex;
#ifdef __GLIBC__
bool _iconv_ok = true;
#else
bool _iconv_ok = false;
PIConvOpen gd_iconv_open = nullptr;
PIConv gd_iconv = nullptr;
PIConvClose gd_iconv_close = nullptr;
PIConvLocaleCharset gd_locale_charset = nullptr;
void _load_iconv();
#endif
static int _wait_for_pid_completion(const pid_t p_pid, int *r_status, int p_options);
bool _check_pid_is_running(const pid_t p_pid, int *r_status) const;
protected:
// UNIX only handles the core functions.
// inheriting platforms under unix (eg. X11) should handle the rest
@ -88,6 +118,9 @@ public:
virtual Dictionary get_memory_info() const override;
virtual String multibyte_to_string(const String &p_encoding, const PackedByteArray &p_array) const override;
virtual PackedByteArray string_to_multibyte(const String &p_encoding, const String &p_string) const override;
virtual Error execute(const String &p_path, const List<String> &p_arguments, String *r_pipe = nullptr, int *r_exitcode = nullptr, bool read_stderr = false, Mutex *p_pipe_mutex = nullptr, bool p_open_console = false) override;
virtual Dictionary execute_with_pipe(const String &p_path, const List<String> &p_arguments, bool p_blocking = true) override;
virtual Error create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id = nullptr, bool p_open_console = false) override;
@ -116,5 +149,3 @@ public:
};
#endif // UNIX_ENABLED
#endif // OS_UNIX_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef SYSLOG_LOGGER_H
#define SYSLOG_LOGGER_H
#pragma once
#ifdef UNIX_ENABLED
@ -44,5 +43,3 @@ public:
};
#endif // UNIX_ENABLED
#endif // SYSLOG_LOGGER_H

View file

@ -35,6 +35,11 @@
#include "core/os/thread.h"
#include "core/string/ustring.h"
#if defined(PLATFORM_THREAD_OVERRIDE) && defined(__APPLE__)
void init_thread_posix() {
}
#else
#ifdef PTHREAD_BSD_SET_NAME
#include <pthread_np.h>
#endif
@ -73,4 +78,6 @@ void init_thread_posix() {
Thread::_set_platform_functions({ .set_name = set_name });
}
#endif // PLATFORM_THREAD_OVERRIDE && __APPLE__
#endif // UNIX_ENABLED

View file

@ -28,9 +28,6 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef THREAD_POSIX_H
#define THREAD_POSIX_H
#pragma once
void init_thread_posix();
#endif // THREAD_POSIX_H

View file

@ -8,11 +8,11 @@ thirdparty_dir = "#thirdparty/vulkan"
thirdparty_volk_dir = "#thirdparty/volk"
# Use bundled Vulkan headers
env.Prepend(CPPPATH=[thirdparty_dir, thirdparty_dir + "/include"])
env.Prepend(CPPEXTPATH=[thirdparty_dir, thirdparty_dir + "/include"])
if env["use_volk"]:
env.AppendUnique(CPPDEFINES=["USE_VOLK"])
env.Prepend(CPPPATH=[thirdparty_volk_dir])
env.Prepend(CPPEXTPATH=[thirdparty_volk_dir])
if env["platform"] == "android":
env.AppendUnique(CPPDEFINES=["VK_USE_PLATFORM_ANDROID_KHR"])

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GODOT_VULKAN_H
#define GODOT_VULKAN_H
#pragma once
#ifdef USE_VOLK
#include <volk.h>
@ -38,5 +37,3 @@
#define VK_NO_STDINT_H
#include <vulkan/vulkan.h>
#endif
#endif // GODOT_VULKAN_H

Some files were not shown because too many files have changed in this diff Show more