Merge branch 'development' of https://github.com/o3de/o3de into daimini/FocusMode/breadcrumbs
Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> # Conflicts: # Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.cpp
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
<svg width="24" height="33" viewBox="0 0 24 33" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="5" y="7" width="2" height="12" fill="#808080"/>
|
||||
<rect x="5" y="19" width="2" height="14" fill="#808080"/>
|
||||
<rect x="17" y="16" width="2" height="12" transform="rotate(90 17 16)" fill="#808080"/>
|
||||
<circle cx="6" cy="6" r="2" fill="#808080"/>
|
||||
<circle cx="18" cy="17" r="2" fill="#808080"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 398 B |
@@ -0,0 +1,5 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="5" width="2" height="12" fill="grey"/>
|
||||
<rect x="17" y="12" width="2" height="12" transform="rotate(90 17 12)" fill="grey"/>
|
||||
<circle cx="18" cy="13" r="2" fill="grey"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 280 B |
@@ -0,0 +1,6 @@
|
||||
<svg width="24" height="26" viewBox="0 0 24 26" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="5" width="2" height="12" fill="grey"/>
|
||||
<rect x="5" y="14" width="2" height="12" fill="grey"/>
|
||||
<rect x="17" y="12" width="2" height="12" transform="rotate(90 17 12)" fill="grey"/>
|
||||
<circle cx="18" cy="13" r="2" fill="grey"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 335 B |
@@ -0,0 +1,6 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="5" y="7" width="2" height="7" fill="#808080"/>
|
||||
<rect x="17" y="12" width="2" height="12" transform="rotate(90 17 12)" fill="#808080"/>
|
||||
<circle cx="6" cy="6" r="2" fill="#808080"/>
|
||||
<circle cx="18" cy="13" r="2" fill="#808080"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 339 B |
@@ -9,7 +9,7 @@
|
||||
#include "QtEditorApplication.h"
|
||||
|
||||
#ifdef PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
#include <AzFramework/API/ApplicationAPI_Linux.h>
|
||||
#include <AzFramework/XcbEventHandler.h>
|
||||
#endif
|
||||
|
||||
namespace Editor
|
||||
@@ -19,7 +19,7 @@ namespace Editor
|
||||
if (GetIEditor()->IsInGameMode())
|
||||
{
|
||||
#ifdef PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
AzFramework::LinuxXcbEventHandlerBus::Broadcast(&AzFramework::LinuxXcbEventHandler::HandleXcbEvent, static_cast<xcb_generic_event_t*>(message));
|
||||
AzFramework::XcbEventHandlerBus::Broadcast(&AzFramework::XcbEventHandler::HandleXcbEvent, static_cast<xcb_generic_event_t*>(message));
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -28,34 +28,10 @@ namespace AzFramework
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
InputChannelId::InputChannelId(const char* name)
|
||||
: m_crc32(name)
|
||||
{
|
||||
memset(m_name, 0, AZ_ARRAY_SIZE(m_name));
|
||||
azstrncpy(m_name, NAME_BUFFER_SIZE, name, MAX_NAME_LENGTH);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
InputChannelId::InputChannelId(const InputChannelId& other)
|
||||
: m_crc32(other.m_crc32)
|
||||
{
|
||||
memset(m_name, 0, AZ_ARRAY_SIZE(m_name));
|
||||
azstrcpy(m_name, NAME_BUFFER_SIZE, other.m_name);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
InputChannelId& InputChannelId::operator=(const InputChannelId& other)
|
||||
{
|
||||
azstrcpy(m_name, NAME_BUFFER_SIZE, other.m_name);
|
||||
m_crc32 = other.m_crc32;
|
||||
return *this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const char* InputChannelId::GetName() const
|
||||
{
|
||||
return m_name;
|
||||
return m_name.c_str();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <AzCore/Math/Crc.h>
|
||||
#include <AzCore/RTTI/ReflectContext.h>
|
||||
#include <AzCore/std/hash.h>
|
||||
#include <AzCore/std/string/fixed_string.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
namespace AzFramework
|
||||
@@ -22,8 +23,7 @@ namespace AzFramework
|
||||
public:
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constants
|
||||
static const int NAME_BUFFER_SIZE = 64;
|
||||
static const int MAX_NAME_LENGTH = NAME_BUFFER_SIZE - 1;
|
||||
static constexpr int MAX_NAME_LENGTH = 64;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Allocator
|
||||
@@ -39,21 +39,28 @@ namespace AzFramework
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//! Constructor
|
||||
//! \param[in] name Name of the input channel (will be truncated if exceeds MAX_NAME_LENGTH)
|
||||
explicit InputChannelId(const char* name = "");
|
||||
//! \param[in] name Name of the input channel (will be ignored if exceeds MAX_NAME_LENGTH)
|
||||
explicit constexpr InputChannelId(AZStd::string_view name = "")
|
||||
: m_name(name)
|
||||
, m_crc32(name)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//! Copy constructor
|
||||
//! \param[in] other Another instance of the class to copy from
|
||||
InputChannelId(const InputChannelId& other);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//! Copy assignment operator
|
||||
//! \param[in] other Another instance of the class to copy from
|
||||
InputChannelId& operator=(const InputChannelId& other);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//! Default destructor
|
||||
constexpr InputChannelId(const InputChannelId& other) = default;
|
||||
constexpr InputChannelId(InputChannelId&& other) = default;
|
||||
constexpr InputChannelId& operator=(const InputChannelId& other)
|
||||
{
|
||||
m_name = other.m_name;
|
||||
m_crc32 = other.m_crc32;
|
||||
return *this;
|
||||
}
|
||||
constexpr InputChannelId& operator=(InputChannelId&& other)
|
||||
{
|
||||
m_name = AZStd::move(other.m_name);
|
||||
m_crc32 = AZStd::move(other.m_crc32);
|
||||
other.m_crc32 = 0;
|
||||
return *this;
|
||||
}
|
||||
~InputChannelId() = default;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -77,7 +84,7 @@ namespace AzFramework
|
||||
private:
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Variables
|
||||
char m_name[NAME_BUFFER_SIZE]; //!< Name of the input channel
|
||||
AZStd::fixed_string<MAX_NAME_LENGTH> m_name; //!< Name of the input channel
|
||||
AZ::Crc32 m_crc32; //!< Crc32 of the input channel
|
||||
};
|
||||
} // namespace AzFramework
|
||||
|
||||
@@ -28,91 +28,6 @@ namespace AzFramework
|
||||
return (inputDeviceId.GetNameCrc32() == IdForIndex0.GetNameCrc32());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const InputChannelId InputDeviceGamepad::Button::A("gamepad_button_a");
|
||||
const InputChannelId InputDeviceGamepad::Button::B("gamepad_button_b");
|
||||
const InputChannelId InputDeviceGamepad::Button::X("gamepad_button_x");
|
||||
const InputChannelId InputDeviceGamepad::Button::Y("gamepad_button_y");
|
||||
const InputChannelId InputDeviceGamepad::Button::L1("gamepad_button_l1");
|
||||
const InputChannelId InputDeviceGamepad::Button::R1("gamepad_button_r1");
|
||||
const InputChannelId InputDeviceGamepad::Button::L3("gamepad_button_l3");
|
||||
const InputChannelId InputDeviceGamepad::Button::R3("gamepad_button_r3");
|
||||
const InputChannelId InputDeviceGamepad::Button::DU("gamepad_button_d_up");
|
||||
const InputChannelId InputDeviceGamepad::Button::DD("gamepad_button_d_down");
|
||||
const InputChannelId InputDeviceGamepad::Button::DL("gamepad_button_d_left");
|
||||
const InputChannelId InputDeviceGamepad::Button::DR("gamepad_button_d_right");
|
||||
const InputChannelId InputDeviceGamepad::Button::Start("gamepad_button_start");
|
||||
const InputChannelId InputDeviceGamepad::Button::Select("gamepad_button_select");
|
||||
const AZStd::array<InputChannelId, 14> InputDeviceGamepad::Button::All =
|
||||
{{
|
||||
A,
|
||||
B,
|
||||
X,
|
||||
Y,
|
||||
L1,
|
||||
R1,
|
||||
L3,
|
||||
R3,
|
||||
DU,
|
||||
DD,
|
||||
DL,
|
||||
DR,
|
||||
Start,
|
||||
Select
|
||||
}};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const InputChannelId InputDeviceGamepad::Trigger::L2("gamepad_trigger_l2");
|
||||
const InputChannelId InputDeviceGamepad::Trigger::R2("gamepad_trigger_r2");
|
||||
const AZStd::array<InputChannelId, 2> InputDeviceGamepad::Trigger::All =
|
||||
{{
|
||||
L2,
|
||||
R2
|
||||
}};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const InputChannelId InputDeviceGamepad::ThumbStickAxis2D::L("gamepad_thumbstick_l");
|
||||
const InputChannelId InputDeviceGamepad::ThumbStickAxis2D::R("gamepad_thumbstick_r");
|
||||
const AZStd::array<InputChannelId, 2> InputDeviceGamepad::ThumbStickAxis2D::All =
|
||||
{{
|
||||
L,
|
||||
R
|
||||
}};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const InputChannelId InputDeviceGamepad::ThumbStickAxis1D::LX("gamepad_thumbstick_l_x");
|
||||
const InputChannelId InputDeviceGamepad::ThumbStickAxis1D::LY("gamepad_thumbstick_l_y");
|
||||
const InputChannelId InputDeviceGamepad::ThumbStickAxis1D::RX("gamepad_thumbstick_r_x");
|
||||
const InputChannelId InputDeviceGamepad::ThumbStickAxis1D::RY("gamepad_thumbstick_r_y");
|
||||
const AZStd::array<InputChannelId, 4> InputDeviceGamepad::ThumbStickAxis1D::All =
|
||||
{{
|
||||
LX,
|
||||
LY,
|
||||
RX,
|
||||
RY
|
||||
}};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const InputChannelId InputDeviceGamepad::ThumbStickDirection::LU("gamepad_thumbstick_l_up");
|
||||
const InputChannelId InputDeviceGamepad::ThumbStickDirection::LD("gamepad_thumbstick_l_down");
|
||||
const InputChannelId InputDeviceGamepad::ThumbStickDirection::LL("gamepad_thumbstick_l_left");
|
||||
const InputChannelId InputDeviceGamepad::ThumbStickDirection::LR("gamepad_thumbstick_l_right");
|
||||
const InputChannelId InputDeviceGamepad::ThumbStickDirection::RU("gamepad_thumbstick_r_up");
|
||||
const InputChannelId InputDeviceGamepad::ThumbStickDirection::RD("gamepad_thumbstick_r_down");
|
||||
const InputChannelId InputDeviceGamepad::ThumbStickDirection::RL("gamepad_thumbstick_r_left");
|
||||
const InputChannelId InputDeviceGamepad::ThumbStickDirection::RR("gamepad_thumbstick_r_right");
|
||||
const AZStd::array<InputChannelId, 8> InputDeviceGamepad::ThumbStickDirection::All =
|
||||
{{
|
||||
LU,
|
||||
LD,
|
||||
LL,
|
||||
LR,
|
||||
RU,
|
||||
RD,
|
||||
RL,
|
||||
RR
|
||||
}};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void InputDeviceGamepad::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
|
||||
@@ -59,75 +59,115 @@ namespace AzFramework
|
||||
//! All the input channel ids that identify game-pad digital button input
|
||||
struct Button
|
||||
{
|
||||
static const InputChannelId A; //!< The bottom diamond face button
|
||||
static const InputChannelId B; //!< The right diamond face button
|
||||
static const InputChannelId X; //!< The left diamond face button
|
||||
static const InputChannelId Y; //!< The top diamond face button
|
||||
static const InputChannelId L1; //!< The top-left shoulder bumper button
|
||||
static const InputChannelId R1; //!< The top-right shoulder bumper button
|
||||
static const InputChannelId L3; //!< The left thumb-stick click button
|
||||
static const InputChannelId R3; //!< The right thumb-stick click button
|
||||
static const InputChannelId DU; //!< The up directional pad button
|
||||
static const InputChannelId DD; //!< The down directional pad button
|
||||
static const InputChannelId DL; //!< The left directional pad button
|
||||
static const InputChannelId DR; //!< The right directional pad button
|
||||
static const InputChannelId Start; //!< The start/pause/options button
|
||||
static const InputChannelId Select; //!< The select/back button
|
||||
static constexpr inline InputChannelId A{"gamepad_button_a"}; //!< The bottom diamond face button
|
||||
static constexpr inline InputChannelId B{"gamepad_button_b"}; //!< The right diamond face button
|
||||
static constexpr inline InputChannelId X{"gamepad_button_x"}; //!< The left diamond face button
|
||||
static constexpr inline InputChannelId Y{"gamepad_button_y"}; //!< The top diamond face button
|
||||
static constexpr inline InputChannelId L1{"gamepad_button_l1"}; //!< The top-left shoulder bumper button
|
||||
static constexpr inline InputChannelId R1{"gamepad_button_r1"}; //!< The top-right shoulder bumper button
|
||||
static constexpr inline InputChannelId L3{"gamepad_button_l3"}; //!< The left thumb-stick click button
|
||||
static constexpr inline InputChannelId R3{"gamepad_button_r3"}; //!< The right thumb-stick click button
|
||||
static constexpr inline InputChannelId DU{"gamepad_button_d_up"}; //!< The up directional pad button
|
||||
static constexpr inline InputChannelId DD{"gamepad_button_d_down"}; //!< The down directional pad button
|
||||
static constexpr inline InputChannelId DL{"gamepad_button_d_left"}; //!< The left directional pad button
|
||||
static constexpr inline InputChannelId DR{"gamepad_button_d_right"}; //!< The right directional pad button
|
||||
static constexpr inline InputChannelId Start{"gamepad_button_start"}; //!< The start/pause/options button
|
||||
static constexpr inline InputChannelId Select{"gamepad_button_select"}; //!< The select/back button
|
||||
|
||||
//!< All digital game-pad button ids
|
||||
static const AZStd::array<InputChannelId, 14> All;
|
||||
static constexpr inline AZStd::array All
|
||||
{
|
||||
A,
|
||||
B,
|
||||
X,
|
||||
Y,
|
||||
L1,
|
||||
R1,
|
||||
L3,
|
||||
R3,
|
||||
DU,
|
||||
DD,
|
||||
DL,
|
||||
DR,
|
||||
Start,
|
||||
Select
|
||||
};
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//! All the input channel ids that identify game-pad analog trigger input
|
||||
struct Trigger
|
||||
{
|
||||
static const InputChannelId L2; //!< The bottom-left shoulder trigger
|
||||
static const InputChannelId R2; //!< The bottom-right shoulder trigger
|
||||
static constexpr inline InputChannelId L2{"gamepad_trigger_l2"}; //!< The bottom-left shoulder trigger
|
||||
static constexpr inline InputChannelId R2{"gamepad_trigger_r2"}; //!< The bottom-right shoulder trigger
|
||||
|
||||
//!< All analog game-pad trigger ids
|
||||
static const AZStd::array<InputChannelId, 2> All;
|
||||
static constexpr inline AZStd::array All
|
||||
{
|
||||
L2,
|
||||
R2
|
||||
};
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//! All the input channel ids that identify game-pad thumb-stick 2D axis input
|
||||
struct ThumbStickAxis2D
|
||||
{
|
||||
static const InputChannelId L; //!< The left-hand thumb-stick
|
||||
static const InputChannelId R; //!< The right-hand thumb-stick
|
||||
static constexpr inline InputChannelId L{"gamepad_thumbstick_l"}; //!< The left-hand thumb-stick
|
||||
static constexpr inline InputChannelId R{"gamepad_thumbstick_r"}; //!< The right-hand thumb-stick
|
||||
|
||||
//!< All game-pad thumb-stick 2D axis input channel ids
|
||||
static const AZStd::array<InputChannelId, 2> All;
|
||||
static constexpr inline AZStd::array All
|
||||
{
|
||||
L,
|
||||
R
|
||||
};
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//! All the input channel ids that identify game-pad thumb-stick 1D axis input
|
||||
struct ThumbStickAxis1D
|
||||
{
|
||||
static const InputChannelId LX; //!< X-axis of the left-hand thumb-stick
|
||||
static const InputChannelId LY; //!< Y-axis of the left-hand thumb-stick
|
||||
static const InputChannelId RX; //!< X-axis of the right-hand thumb-stick
|
||||
static const InputChannelId RY; //!< Y-axis of the right-hand thumb-stick
|
||||
static constexpr inline InputChannelId LX{"gamepad_thumbstick_l_x"}; //!< X-axis of the left-hand thumb-stick
|
||||
static constexpr inline InputChannelId LY{"gamepad_thumbstick_l_y"}; //!< Y-axis of the left-hand thumb-stick
|
||||
static constexpr inline InputChannelId RX{"gamepad_thumbstick_r_x"}; //!< X-axis of the right-hand thumb-stick
|
||||
static constexpr inline InputChannelId RY{"gamepad_thumbstick_r_y"}; //!< Y-axis of the right-hand thumb-stick
|
||||
|
||||
//!< All game-pad thumb-stick 1D axis input channel ids
|
||||
static const AZStd::array<InputChannelId, 4> All;
|
||||
static constexpr inline AZStd::array All
|
||||
{
|
||||
LX,
|
||||
LY,
|
||||
RX,
|
||||
RY
|
||||
};
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//! All the input channel ids that identify game-pad thumb-stick directional input
|
||||
struct ThumbStickDirection
|
||||
{
|
||||
static const InputChannelId LU; //!< Up on the left-hand thumb-stick
|
||||
static const InputChannelId LD; //!< Down on the left-hand thumb-stick
|
||||
static const InputChannelId LL; //!< Left on the left-hand thumb-stick
|
||||
static const InputChannelId LR; //!< Right on the left-hand thumb-stick
|
||||
static const InputChannelId RU; //!< Up on the left-hand thumb-stick
|
||||
static const InputChannelId RD; //!< Down on the left-hand thumb-stick
|
||||
static const InputChannelId RL; //!< Left on the left-hand thumb-stick
|
||||
static const InputChannelId RR; //!< Right on the left-hand thumb-stick
|
||||
static constexpr inline InputChannelId LU{"gamepad_thumbstick_l_up"}; //!< Up on the left-hand thumb-stick
|
||||
static constexpr inline InputChannelId LD{"gamepad_thumbstick_l_down"}; //!< Down on the left-hand thumb-stick
|
||||
static constexpr inline InputChannelId LL{"gamepad_thumbstick_l_left"}; //!< Left on the left-hand thumb-stick
|
||||
static constexpr inline InputChannelId LR{"gamepad_thumbstick_l_right"}; //!< Right on the left-hand thumb-stick
|
||||
static constexpr inline InputChannelId RU{"gamepad_thumbstick_r_up"}; //!< Up on the left-hand thumb-stick
|
||||
static constexpr inline InputChannelId RD{"gamepad_thumbstick_r_down"}; //!< Down on the left-hand thumb-stick
|
||||
static constexpr inline InputChannelId RL{"gamepad_thumbstick_r_left"}; //!< Left on the left-hand thumb-stick
|
||||
static constexpr inline InputChannelId RR{"gamepad_thumbstick_r_right"}; //!< Right on the left-hand thumb-stick
|
||||
|
||||
//!< All game-pad thumb-stick directional input channel ids
|
||||
static const AZStd::array<InputChannelId, 8> All;
|
||||
static constexpr inline AZStd::array All
|
||||
{
|
||||
LU,
|
||||
LD,
|
||||
LL,
|
||||
LR,
|
||||
RU,
|
||||
RD,
|
||||
RL,
|
||||
RR
|
||||
};
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
-273
@@ -24,279 +24,6 @@ namespace AzFramework
|
||||
return (inputDeviceId.GetNameCrc32() == Id.GetNameCrc32());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Alphanumeric Keys
|
||||
const InputChannelId InputDeviceKeyboard::Key::Alphanumeric0("keyboard_key_alphanumeric_0");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Alphanumeric1("keyboard_key_alphanumeric_1");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Alphanumeric2("keyboard_key_alphanumeric_2");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Alphanumeric3("keyboard_key_alphanumeric_3");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Alphanumeric4("keyboard_key_alphanumeric_4");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Alphanumeric5("keyboard_key_alphanumeric_5");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Alphanumeric6("keyboard_key_alphanumeric_6");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Alphanumeric7("keyboard_key_alphanumeric_7");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Alphanumeric8("keyboard_key_alphanumeric_8");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Alphanumeric9("keyboard_key_alphanumeric_9");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericA("keyboard_key_alphanumeric_A");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericB("keyboard_key_alphanumeric_B");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericC("keyboard_key_alphanumeric_C");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericD("keyboard_key_alphanumeric_D");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericE("keyboard_key_alphanumeric_E");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericF("keyboard_key_alphanumeric_F");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericG("keyboard_key_alphanumeric_G");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericH("keyboard_key_alphanumeric_H");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericI("keyboard_key_alphanumeric_I");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericJ("keyboard_key_alphanumeric_J");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericK("keyboard_key_alphanumeric_K");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericL("keyboard_key_alphanumeric_L");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericM("keyboard_key_alphanumeric_M");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericN("keyboard_key_alphanumeric_N");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericO("keyboard_key_alphanumeric_O");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericP("keyboard_key_alphanumeric_P");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericQ("keyboard_key_alphanumeric_Q");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericR("keyboard_key_alphanumeric_R");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericS("keyboard_key_alphanumeric_S");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericT("keyboard_key_alphanumeric_T");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericU("keyboard_key_alphanumeric_U");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericV("keyboard_key_alphanumeric_V");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericW("keyboard_key_alphanumeric_W");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericX("keyboard_key_alphanumeric_X");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericY("keyboard_key_alphanumeric_Y");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericZ("keyboard_key_alphanumeric_Z");
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Edit (and escape) Keys
|
||||
const InputChannelId InputDeviceKeyboard::Key::EditBackspace("keyboard_key_edit_backspace");
|
||||
const InputChannelId InputDeviceKeyboard::Key::EditCapsLock("keyboard_key_edit_capslock");
|
||||
const InputChannelId InputDeviceKeyboard::Key::EditEnter("keyboard_key_edit_enter");
|
||||
const InputChannelId InputDeviceKeyboard::Key::EditSpace("keyboard_key_edit_space");
|
||||
const InputChannelId InputDeviceKeyboard::Key::EditTab("keyboard_key_edit_tab");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Escape("keyboard_key_escape");
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Function Keys
|
||||
const InputChannelId InputDeviceKeyboard::Key::Function01("keyboard_key_function_F01");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Function02("keyboard_key_function_F02");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Function03("keyboard_key_function_F03");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Function04("keyboard_key_function_F04");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Function05("keyboard_key_function_F05");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Function06("keyboard_key_function_F06");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Function07("keyboard_key_function_F07");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Function08("keyboard_key_function_F08");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Function09("keyboard_key_function_F09");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Function10("keyboard_key_function_F10");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Function11("keyboard_key_function_F11");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Function12("keyboard_key_function_F12");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Function13("keyboard_key_function_F13");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Function14("keyboard_key_function_F14");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Function15("keyboard_key_function_F15");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Function16("keyboard_key_function_F16");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Function17("keyboard_key_function_F17");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Function18("keyboard_key_function_F18");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Function19("keyboard_key_function_F19");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Function20("keyboard_key_function_F20");
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Modifier Keys
|
||||
const InputChannelId InputDeviceKeyboard::Key::ModifierAltL("keyboard_key_modifier_alt_l");
|
||||
const InputChannelId InputDeviceKeyboard::Key::ModifierAltR("keyboard_key_modifier_alt_r");
|
||||
const InputChannelId InputDeviceKeyboard::Key::ModifierCtrlL("keyboard_key_modifier_ctrl_l");
|
||||
const InputChannelId InputDeviceKeyboard::Key::ModifierCtrlR("keyboard_key_modifier_ctrl_r");
|
||||
const InputChannelId InputDeviceKeyboard::Key::ModifierShiftL("keyboard_key_modifier_shift_l");
|
||||
const InputChannelId InputDeviceKeyboard::Key::ModifierShiftR("keyboard_key_modifier_shift_r");
|
||||
const InputChannelId InputDeviceKeyboard::Key::ModifierSuperL("keyboard_key_modifier_super_l");
|
||||
const InputChannelId InputDeviceKeyboard::Key::ModifierSuperR("keyboard_key_modifier_super_r");
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Navigation Keys
|
||||
const InputChannelId InputDeviceKeyboard::Key::NavigationArrowDown("keyboard_key_navigation_arrow_down");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NavigationArrowLeft("keyboard_key_navigation_arrow_left");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NavigationArrowRight("keyboard_key_navigation_arrow_right");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NavigationArrowUp("keyboard_key_navigation_arrow_up");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NavigationDelete("keyboard_key_navigation_delete");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NavigationEnd("keyboard_key_navigation_end");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NavigationHome("keyboard_key_navigation_home");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NavigationInsert("keyboard_key_navigation_insert");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NavigationPageDown("keyboard_key_navigation_page_down");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NavigationPageUp("keyboard_key_navigation_page_up");
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Numpad Keys
|
||||
const InputChannelId InputDeviceKeyboard::Key::NumLock("keyboard_key_num_lock");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NumPad0("keyboard_key_numpad_0");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NumPad1("keyboard_key_numpad_1");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NumPad2("keyboard_key_numpad_2");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NumPad3("keyboard_key_numpad_3");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NumPad4("keyboard_key_numpad_4");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NumPad5("keyboard_key_numpad_5");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NumPad6("keyboard_key_numpad_6");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NumPad7("keyboard_key_numpad_7");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NumPad8("keyboard_key_numpad_8");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NumPad9("keyboard_key_numpad_9");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NumPadAdd("keyboard_key_numpad_add");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NumPadDecimal("keyboard_key_numpad_decimal");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NumPadDivide("keyboard_key_numpad_divide");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NumPadEnter("keyboard_key_numpad_enter");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NumPadMultiply("keyboard_key_numpad_multiply");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NumPadSubtract("keyboard_key_numpad_subtract");
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Punctuation Keys
|
||||
const InputChannelId InputDeviceKeyboard::Key::PunctuationApostrophe("keyboard_key_punctuation_apostrophe");
|
||||
const InputChannelId InputDeviceKeyboard::Key::PunctuationBackslash("keyboard_key_punctuation_backslash");
|
||||
const InputChannelId InputDeviceKeyboard::Key::PunctuationBracketL("keyboard_key_punctuation_bracket_l");
|
||||
const InputChannelId InputDeviceKeyboard::Key::PunctuationBracketR("keyboard_key_punctuation_bracket_r");
|
||||
const InputChannelId InputDeviceKeyboard::Key::PunctuationComma("keyboard_key_punctuation_comma");
|
||||
const InputChannelId InputDeviceKeyboard::Key::PunctuationEquals("keyboard_key_punctuation_equals");
|
||||
const InputChannelId InputDeviceKeyboard::Key::PunctuationHyphen("keyboard_key_punctuation_hyphen");
|
||||
const InputChannelId InputDeviceKeyboard::Key::PunctuationPeriod("keyboard_key_punctuation_period");
|
||||
const InputChannelId InputDeviceKeyboard::Key::PunctuationSemicolon("keyboard_key_punctuation_semicolon");
|
||||
const InputChannelId InputDeviceKeyboard::Key::PunctuationSlash("keyboard_key_punctuation_slash");
|
||||
const InputChannelId InputDeviceKeyboard::Key::PunctuationTilde("keyboard_key_punctuation_tilde");
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Supplementary ISO Key
|
||||
const InputChannelId InputDeviceKeyboard::Key::SupplementaryISO("keyboard_key_supplementary_iso");
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Windows System Keys
|
||||
const InputChannelId InputDeviceKeyboard::Key::WindowsSystemPause("keyboard_key_windows_system_pause");
|
||||
const InputChannelId InputDeviceKeyboard::Key::WindowsSystemPrint("keyboard_key_windows_system_print");
|
||||
const InputChannelId InputDeviceKeyboard::Key::WindowsSystemScrollLock("keyboard_key_windows_system_scroll_lock");
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const AZStd::array<InputChannelId, 112> InputDeviceKeyboard::Key::All =
|
||||
{{
|
||||
// Alphanumeric Keys
|
||||
Alphanumeric0,
|
||||
Alphanumeric1,
|
||||
Alphanumeric2,
|
||||
Alphanumeric3,
|
||||
Alphanumeric4,
|
||||
Alphanumeric5,
|
||||
Alphanumeric6,
|
||||
Alphanumeric7,
|
||||
Alphanumeric8,
|
||||
Alphanumeric9,
|
||||
AlphanumericA,
|
||||
AlphanumericB,
|
||||
AlphanumericC,
|
||||
AlphanumericD,
|
||||
AlphanumericE,
|
||||
AlphanumericF,
|
||||
AlphanumericG,
|
||||
AlphanumericH,
|
||||
AlphanumericI,
|
||||
AlphanumericJ,
|
||||
AlphanumericK,
|
||||
AlphanumericL,
|
||||
AlphanumericM,
|
||||
AlphanumericN,
|
||||
AlphanumericO,
|
||||
AlphanumericP,
|
||||
AlphanumericQ,
|
||||
AlphanumericR,
|
||||
AlphanumericS,
|
||||
AlphanumericT,
|
||||
AlphanumericU,
|
||||
AlphanumericV,
|
||||
AlphanumericW,
|
||||
AlphanumericX,
|
||||
AlphanumericY,
|
||||
AlphanumericZ,
|
||||
|
||||
// Edit (and escape) Keys
|
||||
EditBackspace,
|
||||
EditCapsLock,
|
||||
EditEnter,
|
||||
EditSpace,
|
||||
EditTab,
|
||||
Escape,
|
||||
|
||||
// Function Keys
|
||||
Function01,
|
||||
Function02,
|
||||
Function03,
|
||||
Function04,
|
||||
Function05,
|
||||
Function06,
|
||||
Function07,
|
||||
Function08,
|
||||
Function09,
|
||||
Function10,
|
||||
Function11,
|
||||
Function12,
|
||||
Function13,
|
||||
Function14,
|
||||
Function15,
|
||||
Function16,
|
||||
Function17,
|
||||
Function18,
|
||||
Function19,
|
||||
Function20,
|
||||
|
||||
// Modifier Keys
|
||||
ModifierAltL,
|
||||
ModifierAltR,
|
||||
ModifierCtrlL,
|
||||
ModifierCtrlR,
|
||||
ModifierShiftL,
|
||||
ModifierShiftR,
|
||||
ModifierSuperL,
|
||||
ModifierSuperR,
|
||||
|
||||
// Navigation Keys
|
||||
NavigationArrowDown,
|
||||
NavigationArrowLeft,
|
||||
NavigationArrowRight,
|
||||
NavigationArrowUp,
|
||||
NavigationDelete,
|
||||
NavigationEnd,
|
||||
NavigationHome,
|
||||
NavigationInsert,
|
||||
NavigationPageDown,
|
||||
NavigationPageUp,
|
||||
|
||||
// Numpad Keys
|
||||
NumLock,
|
||||
NumPad0,
|
||||
NumPad1,
|
||||
NumPad2,
|
||||
NumPad3,
|
||||
NumPad4,
|
||||
NumPad5,
|
||||
NumPad6,
|
||||
NumPad7,
|
||||
NumPad8,
|
||||
NumPad9,
|
||||
NumPadAdd,
|
||||
NumPadDecimal,
|
||||
NumPadDivide,
|
||||
NumPadEnter,
|
||||
NumPadMultiply,
|
||||
NumPadSubtract,
|
||||
|
||||
// Punctuation Keys
|
||||
PunctuationApostrophe,
|
||||
PunctuationBackslash,
|
||||
PunctuationBracketL,
|
||||
PunctuationBracketR,
|
||||
PunctuationComma,
|
||||
PunctuationEquals,
|
||||
PunctuationHyphen,
|
||||
PunctuationPeriod,
|
||||
PunctuationSemicolon,
|
||||
PunctuationSlash,
|
||||
PunctuationTilde,
|
||||
|
||||
// Supplementary ISO Key
|
||||
SupplementaryISO,
|
||||
|
||||
// Windows System Keys
|
||||
WindowsSystemPause,
|
||||
WindowsSystemPrint,
|
||||
WindowsSystemScrollLock
|
||||
}};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
ModifierKeyMask GetCorrespondingModifierKeyMask(const InputChannelId& channelId)
|
||||
{
|
||||
|
||||
+245
-114
@@ -94,137 +94,268 @@ namespace AzFramework
|
||||
struct Key
|
||||
{
|
||||
// Alphanumeric Keys
|
||||
static const InputChannelId Alphanumeric0; //!< The 0 key
|
||||
static const InputChannelId Alphanumeric1; //!< The 1 key
|
||||
static const InputChannelId Alphanumeric2; //!< The 2 key
|
||||
static const InputChannelId Alphanumeric3; //!< The 3 key
|
||||
static const InputChannelId Alphanumeric4; //!< The 4 key
|
||||
static const InputChannelId Alphanumeric5; //!< The 5 key
|
||||
static const InputChannelId Alphanumeric6; //!< The 6 key
|
||||
static const InputChannelId Alphanumeric7; //!< The 7 key
|
||||
static const InputChannelId Alphanumeric8; //!< The 8 key
|
||||
static const InputChannelId Alphanumeric9; //!< The 9 key
|
||||
static const InputChannelId AlphanumericA; //!< The A key
|
||||
static const InputChannelId AlphanumericB; //!< The B key
|
||||
static const InputChannelId AlphanumericC; //!< The C key
|
||||
static const InputChannelId AlphanumericD; //!< The D key
|
||||
static const InputChannelId AlphanumericE; //!< The E key
|
||||
static const InputChannelId AlphanumericF; //!< The F key
|
||||
static const InputChannelId AlphanumericG; //!< The G key
|
||||
static const InputChannelId AlphanumericH; //!< The H key
|
||||
static const InputChannelId AlphanumericI; //!< The I key
|
||||
static const InputChannelId AlphanumericJ; //!< The J key
|
||||
static const InputChannelId AlphanumericK; //!< The K key
|
||||
static const InputChannelId AlphanumericL; //!< The L key
|
||||
static const InputChannelId AlphanumericM; //!< The M key
|
||||
static const InputChannelId AlphanumericN; //!< The N key
|
||||
static const InputChannelId AlphanumericO; //!< The O key
|
||||
static const InputChannelId AlphanumericP; //!< The P key
|
||||
static const InputChannelId AlphanumericQ; //!< The Q key
|
||||
static const InputChannelId AlphanumericR; //!< The R key
|
||||
static const InputChannelId AlphanumericS; //!< The S key
|
||||
static const InputChannelId AlphanumericT; //!< The T key
|
||||
static const InputChannelId AlphanumericU; //!< The U key
|
||||
static const InputChannelId AlphanumericV; //!< The V key
|
||||
static const InputChannelId AlphanumericW; //!< The W key
|
||||
static const InputChannelId AlphanumericX; //!< The X key
|
||||
static const InputChannelId AlphanumericY; //!< The Y key
|
||||
static const InputChannelId AlphanumericZ; //!< The Z key
|
||||
static constexpr inline InputChannelId Alphanumeric0{"keyboard_key_alphanumeric_0"}; //!< The 0 key
|
||||
static constexpr inline InputChannelId Alphanumeric1{"keyboard_key_alphanumeric_1"}; //!< The 1 key
|
||||
static constexpr inline InputChannelId Alphanumeric2{"keyboard_key_alphanumeric_2"}; //!< The 2 key
|
||||
static constexpr inline InputChannelId Alphanumeric3{"keyboard_key_alphanumeric_3"}; //!< The 3 key
|
||||
static constexpr inline InputChannelId Alphanumeric4{"keyboard_key_alphanumeric_4"}; //!< The 4 key
|
||||
static constexpr inline InputChannelId Alphanumeric5{"keyboard_key_alphanumeric_5"}; //!< The 5 key
|
||||
static constexpr inline InputChannelId Alphanumeric6{"keyboard_key_alphanumeric_6"}; //!< The 6 key
|
||||
static constexpr inline InputChannelId Alphanumeric7{"keyboard_key_alphanumeric_7"}; //!< The 7 key
|
||||
static constexpr inline InputChannelId Alphanumeric8{"keyboard_key_alphanumeric_8"}; //!< The 8 key
|
||||
static constexpr inline InputChannelId Alphanumeric9{"keyboard_key_alphanumeric_9"}; //!< The 9 key
|
||||
static constexpr inline InputChannelId AlphanumericA{"keyboard_key_alphanumeric_A"}; //!< The A key
|
||||
static constexpr inline InputChannelId AlphanumericB{"keyboard_key_alphanumeric_B"}; //!< The B key
|
||||
static constexpr inline InputChannelId AlphanumericC{"keyboard_key_alphanumeric_C"}; //!< The C key
|
||||
static constexpr inline InputChannelId AlphanumericD{"keyboard_key_alphanumeric_D"}; //!< The D key
|
||||
static constexpr inline InputChannelId AlphanumericE{"keyboard_key_alphanumeric_E"}; //!< The E key
|
||||
static constexpr inline InputChannelId AlphanumericF{"keyboard_key_alphanumeric_F"}; //!< The F key
|
||||
static constexpr inline InputChannelId AlphanumericG{"keyboard_key_alphanumeric_G"}; //!< The G key
|
||||
static constexpr inline InputChannelId AlphanumericH{"keyboard_key_alphanumeric_H"}; //!< The H key
|
||||
static constexpr inline InputChannelId AlphanumericI{"keyboard_key_alphanumeric_I"}; //!< The I key
|
||||
static constexpr inline InputChannelId AlphanumericJ{"keyboard_key_alphanumeric_J"}; //!< The J key
|
||||
static constexpr inline InputChannelId AlphanumericK{"keyboard_key_alphanumeric_K"}; //!< The K key
|
||||
static constexpr inline InputChannelId AlphanumericL{"keyboard_key_alphanumeric_L"}; //!< The L key
|
||||
static constexpr inline InputChannelId AlphanumericM{"keyboard_key_alphanumeric_M"}; //!< The M key
|
||||
static constexpr inline InputChannelId AlphanumericN{"keyboard_key_alphanumeric_N"}; //!< The N key
|
||||
static constexpr inline InputChannelId AlphanumericO{"keyboard_key_alphanumeric_O"}; //!< The O key
|
||||
static constexpr inline InputChannelId AlphanumericP{"keyboard_key_alphanumeric_P"}; //!< The P key
|
||||
static constexpr inline InputChannelId AlphanumericQ{"keyboard_key_alphanumeric_Q"}; //!< The Q key
|
||||
static constexpr inline InputChannelId AlphanumericR{"keyboard_key_alphanumeric_R"}; //!< The R key
|
||||
static constexpr inline InputChannelId AlphanumericS{"keyboard_key_alphanumeric_S"}; //!< The S key
|
||||
static constexpr inline InputChannelId AlphanumericT{"keyboard_key_alphanumeric_T"}; //!< The T key
|
||||
static constexpr inline InputChannelId AlphanumericU{"keyboard_key_alphanumeric_U"}; //!< The U key
|
||||
static constexpr inline InputChannelId AlphanumericV{"keyboard_key_alphanumeric_V"}; //!< The V key
|
||||
static constexpr inline InputChannelId AlphanumericW{"keyboard_key_alphanumeric_W"}; //!< The W key
|
||||
static constexpr inline InputChannelId AlphanumericX{"keyboard_key_alphanumeric_X"}; //!< The X key
|
||||
static constexpr inline InputChannelId AlphanumericY{"keyboard_key_alphanumeric_Y"}; //!< The Y key
|
||||
static constexpr inline InputChannelId AlphanumericZ{"keyboard_key_alphanumeric_Z"}; //!< The Z key
|
||||
|
||||
// Edit (and escape) Keys
|
||||
static const InputChannelId EditBackspace; //!< The backspace key
|
||||
static const InputChannelId EditCapsLock; //!< The caps lock key
|
||||
static const InputChannelId EditEnter; //!< The enter/return key
|
||||
static const InputChannelId EditSpace; //!< The spacebar key
|
||||
static const InputChannelId EditTab; //!< The tab key
|
||||
static const InputChannelId Escape; //!< The escape key
|
||||
// Edit {and escape} Keys
|
||||
static constexpr inline InputChannelId EditBackspace{"keyboard_key_edit_backspace"}; //!< The backspace key
|
||||
static constexpr inline InputChannelId EditCapsLock{"keyboard_key_edit_capslock"}; //!< The caps lock key
|
||||
static constexpr inline InputChannelId EditEnter{"keyboard_key_edit_enter"}; //!< The enter/return key
|
||||
static constexpr inline InputChannelId EditSpace{"keyboard_key_edit_space"}; //!< The spacebar key
|
||||
static constexpr inline InputChannelId EditTab{"keyboard_key_edit_tab"}; //!< The tab key
|
||||
static constexpr inline InputChannelId Escape{"keyboard_key_escape"}; //!< The escape key
|
||||
|
||||
// Function Keys
|
||||
static const InputChannelId Function01; //!< The F1 key
|
||||
static const InputChannelId Function02; //!< The F2 key
|
||||
static const InputChannelId Function03; //!< The F3 key
|
||||
static const InputChannelId Function04; //!< The F4 key
|
||||
static const InputChannelId Function05; //!< The F5 key
|
||||
static const InputChannelId Function06; //!< The F6 key
|
||||
static const InputChannelId Function07; //!< The F7 key
|
||||
static const InputChannelId Function08; //!< The F8 key
|
||||
static const InputChannelId Function09; //!< The F9 key
|
||||
static const InputChannelId Function10; //!< The F10 key
|
||||
static const InputChannelId Function11; //!< The F11 key
|
||||
static const InputChannelId Function12; //!< The F12 key
|
||||
static const InputChannelId Function13; //!< The F13 key
|
||||
static const InputChannelId Function14; //!< The F14 key
|
||||
static const InputChannelId Function15; //!< The F15 key
|
||||
static const InputChannelId Function16; //!< The F16 key
|
||||
static const InputChannelId Function17; //!< The F17 key
|
||||
static const InputChannelId Function18; //!< The F18 key
|
||||
static const InputChannelId Function19; //!< The F19 key
|
||||
static const InputChannelId Function20; //!< The F20 key
|
||||
static constexpr inline InputChannelId Function01{"keyboard_key_function_F01"}; //!< The F1 key
|
||||
static constexpr inline InputChannelId Function02{"keyboard_key_function_F02"}; //!< The F2 key
|
||||
static constexpr inline InputChannelId Function03{"keyboard_key_function_F03"}; //!< The F3 key
|
||||
static constexpr inline InputChannelId Function04{"keyboard_key_function_F04"}; //!< The F4 key
|
||||
static constexpr inline InputChannelId Function05{"keyboard_key_function_F05"}; //!< The F5 key
|
||||
static constexpr inline InputChannelId Function06{"keyboard_key_function_F06"}; //!< The F6 key
|
||||
static constexpr inline InputChannelId Function07{"keyboard_key_function_F07"}; //!< The F7 key
|
||||
static constexpr inline InputChannelId Function08{"keyboard_key_function_F08"}; //!< The F8 key
|
||||
static constexpr inline InputChannelId Function09{"keyboard_key_function_F09"}; //!< The F9 key
|
||||
static constexpr inline InputChannelId Function10{"keyboard_key_function_F10"}; //!< The F10 key
|
||||
static constexpr inline InputChannelId Function11{"keyboard_key_function_F11"}; //!< The F11 key
|
||||
static constexpr inline InputChannelId Function12{"keyboard_key_function_F12"}; //!< The F12 key
|
||||
static constexpr inline InputChannelId Function13{"keyboard_key_function_F13"}; //!< The F13 key
|
||||
static constexpr inline InputChannelId Function14{"keyboard_key_function_F14"}; //!< The F14 key
|
||||
static constexpr inline InputChannelId Function15{"keyboard_key_function_F15"}; //!< The F15 key
|
||||
static constexpr inline InputChannelId Function16{"keyboard_key_function_F16"}; //!< The F16 key
|
||||
static constexpr inline InputChannelId Function17{"keyboard_key_function_F17"}; //!< The F17 key
|
||||
static constexpr inline InputChannelId Function18{"keyboard_key_function_F18"}; //!< The F18 key
|
||||
static constexpr inline InputChannelId Function19{"keyboard_key_function_F19"}; //!< The F19 key
|
||||
static constexpr inline InputChannelId Function20{"keyboard_key_function_F20"}; //!< The F20 key
|
||||
|
||||
// Modifier Keys
|
||||
static const InputChannelId ModifierAltL; //!< The left alt/option key
|
||||
static const InputChannelId ModifierAltR; //!< The right alt/option key
|
||||
static const InputChannelId ModifierCtrlL; //!< The left control key
|
||||
static const InputChannelId ModifierCtrlR; //!< The right control key
|
||||
static const InputChannelId ModifierShiftL; //!< The left shift key
|
||||
static const InputChannelId ModifierShiftR; //!< The right shift key
|
||||
static const InputChannelId ModifierSuperL; //!< The left super (windows or apple) key
|
||||
static const InputChannelId ModifierSuperR; //!< The right super (windows or apple) key
|
||||
static constexpr inline InputChannelId ModifierAltL{"keyboard_key_modifier_alt_l"}; //!< The left alt/option key
|
||||
static constexpr inline InputChannelId ModifierAltR{"keyboard_key_modifier_alt_r"}; //!< The right alt/option key
|
||||
static constexpr inline InputChannelId ModifierCtrlL{"keyboard_key_modifier_ctrl_l"}; //!< The left control key
|
||||
static constexpr inline InputChannelId ModifierCtrlR{"keyboard_key_modifier_ctrl_r"}; //!< The right control key
|
||||
static constexpr inline InputChannelId ModifierShiftL{"keyboard_key_modifier_shift_l"}; //!< The left shift key
|
||||
static constexpr inline InputChannelId ModifierShiftR{"keyboard_key_modifier_shift_r"}; //!< The right shift key
|
||||
static constexpr inline InputChannelId ModifierSuperL{"keyboard_key_modifier_super_l"}; //!< The left super {windows or apple} key
|
||||
static constexpr inline InputChannelId ModifierSuperR{"keyboard_key_modifier_super_r"}; //!< The right super {windows or apple} key
|
||||
|
||||
// Navigation Keys
|
||||
static const InputChannelId NavigationArrowDown; //!< The down arrow key
|
||||
static const InputChannelId NavigationArrowLeft; //!< The left arrow key
|
||||
static const InputChannelId NavigationArrowRight; //!< The right arrow key
|
||||
static const InputChannelId NavigationArrowUp; //!< The up arrow key
|
||||
static const InputChannelId NavigationDelete; //!< The delete key
|
||||
static const InputChannelId NavigationEnd; //!< The end key
|
||||
static const InputChannelId NavigationHome; //!< The home key
|
||||
static const InputChannelId NavigationInsert; //!< The insert key
|
||||
static const InputChannelId NavigationPageDown; //!< The page down key
|
||||
static const InputChannelId NavigationPageUp; //!< The page up key
|
||||
static constexpr inline InputChannelId NavigationArrowDown{"keyboard_key_navigation_arrow_down"}; //!< The down arrow key
|
||||
static constexpr inline InputChannelId NavigationArrowLeft{"keyboard_key_navigation_arrow_left"}; //!< The left arrow key
|
||||
static constexpr inline InputChannelId NavigationArrowRight{"keyboard_key_navigation_arrow_right"}; //!< The right arrow key
|
||||
static constexpr inline InputChannelId NavigationArrowUp{"keyboard_key_navigation_arrow_up"}; //!< The up arrow key
|
||||
static constexpr inline InputChannelId NavigationDelete{"keyboard_key_navigation_delete"}; //!< The delete key
|
||||
static constexpr inline InputChannelId NavigationEnd{"keyboard_key_navigation_end"}; //!< The end key
|
||||
static constexpr inline InputChannelId NavigationHome{"keyboard_key_navigation_home"}; //!< The home key
|
||||
static constexpr inline InputChannelId NavigationInsert{"keyboard_key_navigation_insert"}; //!< The insert key
|
||||
static constexpr inline InputChannelId NavigationPageDown{"keyboard_key_navigation_page_down"}; //!< The page down key
|
||||
static constexpr inline InputChannelId NavigationPageUp{"keyboard_key_navigation_page_up"}; //!< The page up key
|
||||
|
||||
// Numpad Keys
|
||||
static const InputChannelId NumLock; //!< The num lock key (the clear key on apple keyboards)
|
||||
static const InputChannelId NumPad0; //!< The numpad 0 key
|
||||
static const InputChannelId NumPad1; //!< The numpad 1 key
|
||||
static const InputChannelId NumPad2; //!< The numpad 2 key
|
||||
static const InputChannelId NumPad3; //!< The numpad 3 key
|
||||
static const InputChannelId NumPad4; //!< The numpad 4 key
|
||||
static const InputChannelId NumPad5; //!< The numpad 5 key
|
||||
static const InputChannelId NumPad6; //!< The numpad 6 key
|
||||
static const InputChannelId NumPad7; //!< The numpad 7 key
|
||||
static const InputChannelId NumPad8; //!< The numpad 8 key
|
||||
static const InputChannelId NumPad9; //!< The numpad 9 key
|
||||
static const InputChannelId NumPadAdd; //!< The numpad add key
|
||||
static const InputChannelId NumPadDecimal; //!< The numpad decimal key
|
||||
static const InputChannelId NumPadDivide; //!< The numpad divide key
|
||||
static const InputChannelId NumPadEnter; //!< The numpad enter key
|
||||
static const InputChannelId NumPadMultiply; //!< The numpad multiply key
|
||||
static const InputChannelId NumPadSubtract; //!< The numpad subtract key
|
||||
static constexpr inline InputChannelId NumLock{"keyboard_key_num_lock"}; //!< The num lock key {the clear key on apple keyboards}
|
||||
static constexpr inline InputChannelId NumPad0{"keyboard_key_numpad_0"}; //!< The numpad 0 key
|
||||
static constexpr inline InputChannelId NumPad1{"keyboard_key_numpad_1"}; //!< The numpad 1 key
|
||||
static constexpr inline InputChannelId NumPad2{"keyboard_key_numpad_2"}; //!< The numpad 2 key
|
||||
static constexpr inline InputChannelId NumPad3{"keyboard_key_numpad_3"}; //!< The numpad 3 key
|
||||
static constexpr inline InputChannelId NumPad4{"keyboard_key_numpad_4"}; //!< The numpad 4 key
|
||||
static constexpr inline InputChannelId NumPad5{"keyboard_key_numpad_5"}; //!< The numpad 5 key
|
||||
static constexpr inline InputChannelId NumPad6{"keyboard_key_numpad_6"}; //!< The numpad 6 key
|
||||
static constexpr inline InputChannelId NumPad7{"keyboard_key_numpad_7"}; //!< The numpad 7 key
|
||||
static constexpr inline InputChannelId NumPad8{"keyboard_key_numpad_8"}; //!< The numpad 8 key
|
||||
static constexpr inline InputChannelId NumPad9{"keyboard_key_numpad_9"}; //!< The numpad 9 key
|
||||
static constexpr inline InputChannelId NumPadAdd{"keyboard_key_numpad_add"}; //!< The numpad add key
|
||||
static constexpr inline InputChannelId NumPadDecimal{"keyboard_key_numpad_decimal"}; //!< The numpad decimal key
|
||||
static constexpr inline InputChannelId NumPadDivide{"keyboard_key_numpad_divide"}; //!< The numpad divide key
|
||||
static constexpr inline InputChannelId NumPadEnter{"keyboard_key_numpad_enter"}; //!< The numpad enter key
|
||||
static constexpr inline InputChannelId NumPadMultiply{"keyboard_key_numpad_multiply"}; //!< The numpad multiply key
|
||||
static constexpr inline InputChannelId NumPadSubtract{"keyboard_key_numpad_subtract"}; //!< The numpad subtract key
|
||||
|
||||
// Punctuation Keys
|
||||
static const InputChannelId PunctuationApostrophe; //!< The apostrophe key
|
||||
static const InputChannelId PunctuationBackslash; //!< The backslash key
|
||||
static const InputChannelId PunctuationBracketL; //!< The left bracket key
|
||||
static const InputChannelId PunctuationBracketR; //!< The right bracket key
|
||||
static const InputChannelId PunctuationComma; //!< The comma key
|
||||
static const InputChannelId PunctuationEquals; //!< The equals key
|
||||
static const InputChannelId PunctuationHyphen; //!< The hyphen/underscore key
|
||||
static const InputChannelId PunctuationPeriod; //!< The period key
|
||||
static const InputChannelId PunctuationSemicolon; //!< The semicolon key
|
||||
static const InputChannelId PunctuationSlash; //!< The (forward) slash key
|
||||
static const InputChannelId PunctuationTilde; //!< The tilde/grave key
|
||||
static constexpr inline InputChannelId PunctuationApostrophe{"keyboard_key_punctuation_apostrophe"}; //!< The apostrophe key
|
||||
static constexpr inline InputChannelId PunctuationBackslash{"keyboard_key_punctuation_backslash"}; //!< The backslash key
|
||||
static constexpr inline InputChannelId PunctuationBracketL{"keyboard_key_punctuation_bracket_l"}; //!< The left bracket key
|
||||
static constexpr inline InputChannelId PunctuationBracketR{"keyboard_key_punctuation_bracket_r"}; //!< The right bracket key
|
||||
static constexpr inline InputChannelId PunctuationComma{"keyboard_key_punctuation_comma"}; //!< The comma key
|
||||
static constexpr inline InputChannelId PunctuationEquals{"keyboard_key_punctuation_equals"}; //!< The equals key
|
||||
static constexpr inline InputChannelId PunctuationHyphen{"keyboard_key_punctuation_hyphen"}; //!< The hyphen/underscore key
|
||||
static constexpr inline InputChannelId PunctuationPeriod{"keyboard_key_punctuation_period"}; //!< The period key
|
||||
static constexpr inline InputChannelId PunctuationSemicolon{"keyboard_key_punctuation_semicolon"}; //!< The semicolon key
|
||||
static constexpr inline InputChannelId PunctuationSlash{"keyboard_key_punctuation_slash"}; //!< The {forward} slash key
|
||||
static constexpr inline InputChannelId PunctuationTilde{"keyboard_key_punctuation_tilde"}; //!< The tilde/grave key
|
||||
|
||||
// Supplementary ISO Key
|
||||
static const InputChannelId SupplementaryISO; //!< The supplementary ISO layout key
|
||||
static constexpr inline InputChannelId SupplementaryISO{"keyboard_key_supplementary_iso"}; //!< The supplementary ISO layout key
|
||||
|
||||
// Windows System Keys
|
||||
static const InputChannelId WindowsSystemPause; //!< The windows pause key
|
||||
static const InputChannelId WindowsSystemPrint; //!< The windows print key
|
||||
static const InputChannelId WindowsSystemScrollLock; //!< The windows scroll lock key
|
||||
static constexpr inline InputChannelId WindowsSystemPause{"keyboard_key_windows_system_pause"}; //!< The windows pause key
|
||||
static constexpr inline InputChannelId WindowsSystemPrint{"keyboard_key_windows_system_print"}; //!< The windows print key
|
||||
static constexpr inline InputChannelId WindowsSystemScrollLock{"keyboard_key_windows_system_scroll_lock"}; //!< The windows scroll lock key
|
||||
|
||||
//!< All keyboard key ids
|
||||
static const AZStd::array<InputChannelId, 112> All;
|
||||
static constexpr inline AZStd::array All
|
||||
{
|
||||
// Alphanumeric Keys
|
||||
Alphanumeric0,
|
||||
Alphanumeric1,
|
||||
Alphanumeric2,
|
||||
Alphanumeric3,
|
||||
Alphanumeric4,
|
||||
Alphanumeric5,
|
||||
Alphanumeric6,
|
||||
Alphanumeric7,
|
||||
Alphanumeric8,
|
||||
Alphanumeric9,
|
||||
AlphanumericA,
|
||||
AlphanumericB,
|
||||
AlphanumericC,
|
||||
AlphanumericD,
|
||||
AlphanumericE,
|
||||
AlphanumericF,
|
||||
AlphanumericG,
|
||||
AlphanumericH,
|
||||
AlphanumericI,
|
||||
AlphanumericJ,
|
||||
AlphanumericK,
|
||||
AlphanumericL,
|
||||
AlphanumericM,
|
||||
AlphanumericN,
|
||||
AlphanumericO,
|
||||
AlphanumericP,
|
||||
AlphanumericQ,
|
||||
AlphanumericR,
|
||||
AlphanumericS,
|
||||
AlphanumericT,
|
||||
AlphanumericU,
|
||||
AlphanumericV,
|
||||
AlphanumericW,
|
||||
AlphanumericX,
|
||||
AlphanumericY,
|
||||
AlphanumericZ,
|
||||
|
||||
// Edit (and escape) Keys
|
||||
EditBackspace,
|
||||
EditCapsLock,
|
||||
EditEnter,
|
||||
EditSpace,
|
||||
EditTab,
|
||||
Escape,
|
||||
|
||||
// Function Keys
|
||||
Function01,
|
||||
Function02,
|
||||
Function03,
|
||||
Function04,
|
||||
Function05,
|
||||
Function06,
|
||||
Function07,
|
||||
Function08,
|
||||
Function09,
|
||||
Function10,
|
||||
Function11,
|
||||
Function12,
|
||||
Function13,
|
||||
Function14,
|
||||
Function15,
|
||||
Function16,
|
||||
Function17,
|
||||
Function18,
|
||||
Function19,
|
||||
Function20,
|
||||
|
||||
// Modifier Keys
|
||||
ModifierAltL,
|
||||
ModifierAltR,
|
||||
ModifierCtrlL,
|
||||
ModifierCtrlR,
|
||||
ModifierShiftL,
|
||||
ModifierShiftR,
|
||||
ModifierSuperL,
|
||||
ModifierSuperR,
|
||||
|
||||
// Navigation Keys
|
||||
NavigationArrowDown,
|
||||
NavigationArrowLeft,
|
||||
NavigationArrowRight,
|
||||
NavigationArrowUp,
|
||||
NavigationDelete,
|
||||
NavigationEnd,
|
||||
NavigationHome,
|
||||
NavigationInsert,
|
||||
NavigationPageDown,
|
||||
NavigationPageUp,
|
||||
|
||||
// Numpad Keys
|
||||
NumLock,
|
||||
NumPad0,
|
||||
NumPad1,
|
||||
NumPad2,
|
||||
NumPad3,
|
||||
NumPad4,
|
||||
NumPad5,
|
||||
NumPad6,
|
||||
NumPad7,
|
||||
NumPad8,
|
||||
NumPad9,
|
||||
NumPadAdd,
|
||||
NumPadDecimal,
|
||||
NumPadDivide,
|
||||
NumPadEnter,
|
||||
NumPadMultiply,
|
||||
NumPadSubtract,
|
||||
|
||||
// Punctuation Keys
|
||||
PunctuationApostrophe,
|
||||
PunctuationBackslash,
|
||||
PunctuationBracketL,
|
||||
PunctuationBracketR,
|
||||
PunctuationComma,
|
||||
PunctuationEquals,
|
||||
PunctuationHyphen,
|
||||
PunctuationPeriod,
|
||||
PunctuationSemicolon,
|
||||
PunctuationSlash,
|
||||
PunctuationTilde,
|
||||
|
||||
// Supplementary ISO Key
|
||||
SupplementaryISO,
|
||||
|
||||
// Windows System Keys
|
||||
WindowsSystemPause,
|
||||
WindowsSystemPrint,
|
||||
WindowsSystemScrollLock
|
||||
};
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -23,44 +23,6 @@ namespace AzFramework
|
||||
return (inputDeviceId.GetNameCrc32() == Id.GetNameCrc32());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const InputChannelId InputDeviceMotion::Acceleration::Gravity("motion_acceleration_gravity");
|
||||
const InputChannelId InputDeviceMotion::Acceleration::Raw("motion_acceleration_raw");
|
||||
const InputChannelId InputDeviceMotion::Acceleration::User("motion_acceleration_user");
|
||||
const AZStd::array<InputChannelId, 3> InputDeviceMotion::Acceleration::All =
|
||||
{{
|
||||
Gravity,
|
||||
Raw,
|
||||
User
|
||||
}};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const InputChannelId InputDeviceMotion::RotationRate::Raw("motion_rotation_rate_raw");
|
||||
const InputChannelId InputDeviceMotion::RotationRate::Unbiased("motion_rotation_rate_unbiased");
|
||||
const AZStd::array<InputChannelId, 2> InputDeviceMotion::RotationRate::All =
|
||||
{{
|
||||
Raw,
|
||||
Unbiased
|
||||
}};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const InputChannelId InputDeviceMotion::MagneticField::North("motion_magnetic_field_north");
|
||||
const InputChannelId InputDeviceMotion::MagneticField::Raw("motion_magnetic_field_raw");
|
||||
const InputChannelId InputDeviceMotion::MagneticField::Unbiased("motion_magnetic_field_unbiased");
|
||||
const AZStd::array<InputChannelId, 3> InputDeviceMotion::MagneticField::All =
|
||||
{{
|
||||
North,
|
||||
Raw,
|
||||
Unbiased
|
||||
}};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const InputChannelId InputDeviceMotion::Orientation::Current("motion_orientation_current");
|
||||
const AZStd::array<InputChannelId, 1> InputDeviceMotion::Orientation::All =
|
||||
{{
|
||||
Current
|
||||
}};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void InputDeviceMotion::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
|
||||
@@ -44,12 +44,17 @@ namespace AzFramework
|
||||
//! - InputMotionSensorRequests::SetInputChannelEnabled
|
||||
struct Acceleration
|
||||
{
|
||||
static const InputChannelId Gravity;
|
||||
static const InputChannelId Raw;
|
||||
static const InputChannelId User;
|
||||
static constexpr inline InputChannelId Gravity{"motion_acceleration_gravity"};
|
||||
static constexpr inline InputChannelId Raw{"motion_acceleration_raw"};
|
||||
static constexpr inline InputChannelId User{"motion_acceleration_user"};
|
||||
|
||||
//!< All acceleration input channel ids
|
||||
static const AZStd::array<InputChannelId, 3> All;
|
||||
static constexpr inline AZStd::array All
|
||||
{
|
||||
Gravity,
|
||||
Raw,
|
||||
User
|
||||
};
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -60,11 +65,15 @@ namespace AzFramework
|
||||
//! - InputMotionSensorRequests::SetInputChannelEnabled
|
||||
struct RotationRate
|
||||
{
|
||||
static const InputChannelId Raw;
|
||||
static const InputChannelId Unbiased;
|
||||
static constexpr inline InputChannelId Raw{"motion_rotation_rate_raw"};
|
||||
static constexpr inline InputChannelId Unbiased{"motion_rotation_rate_unbiased"};
|
||||
|
||||
//!< All rotation rate input channel ids
|
||||
static const AZStd::array<InputChannelId, 2> All;
|
||||
static constexpr inline AZStd::array All
|
||||
{
|
||||
Raw,
|
||||
Unbiased
|
||||
};
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -75,12 +84,17 @@ namespace AzFramework
|
||||
//! - InputMotionSensorRequests::SetInputChannelEnabled
|
||||
struct MagneticField
|
||||
{
|
||||
static const InputChannelId North;
|
||||
static const InputChannelId Raw;
|
||||
static const InputChannelId Unbiased;
|
||||
static constexpr inline InputChannelId North{"motion_magnetic_field_north"};
|
||||
static constexpr inline InputChannelId Raw{"motion_magnetic_field_raw"};
|
||||
static constexpr inline InputChannelId Unbiased{"motion_magnetic_field_unbiased"};
|
||||
|
||||
//!< All magnetic field input channel ids
|
||||
static const AZStd::array<InputChannelId, 3> All;
|
||||
static constexpr inline AZStd::array All
|
||||
{
|
||||
North,
|
||||
Raw,
|
||||
Unbiased
|
||||
};
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -91,10 +105,13 @@ namespace AzFramework
|
||||
//! - InputMotionSensorRequests::SetInputChannelEnabled
|
||||
struct Orientation
|
||||
{
|
||||
static const InputChannelId Current;
|
||||
static constexpr inline InputChannelId Current{"motion_orientation_current"};
|
||||
|
||||
//!< All orientation input channel ids
|
||||
static const AZStd::array<InputChannelId, 1> All;
|
||||
static constexpr inline AZStd::array All
|
||||
{
|
||||
Current
|
||||
};
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -33,35 +33,6 @@ namespace AzFramework
|
||||
return (inputDeviceId.GetNameCrc32() == Id.GetNameCrc32());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const InputChannelId InputDeviceMouse::Button::Left("mouse_button_left");
|
||||
const InputChannelId InputDeviceMouse::Button::Right("mouse_button_right");
|
||||
const InputChannelId InputDeviceMouse::Button::Middle("mouse_button_middle");
|
||||
const InputChannelId InputDeviceMouse::Button::Other1("mouse_button_other1");
|
||||
const InputChannelId InputDeviceMouse::Button::Other2("mouse_button_other2");
|
||||
const AZStd::array<InputChannelId, 5> InputDeviceMouse::Button::All =
|
||||
{{
|
||||
Left,
|
||||
Right,
|
||||
Middle,
|
||||
Other1,
|
||||
Other2
|
||||
}};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const InputChannelId InputDeviceMouse::Movement::X("mouse_delta_x");
|
||||
const InputChannelId InputDeviceMouse::Movement::Y("mouse_delta_y");
|
||||
const InputChannelId InputDeviceMouse::Movement::Z("mouse_delta_z");
|
||||
const AZStd::array<InputChannelId, 3> InputDeviceMouse::Movement::All =
|
||||
{{
|
||||
X,
|
||||
Y,
|
||||
Z
|
||||
}};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const InputChannelId InputDeviceMouse::SystemCursorPosition("mouse_system_cursor_position");
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void InputDeviceMouse::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
|
||||
@@ -66,14 +66,21 @@ namespace AzFramework
|
||||
//! been implemented for windows simply to provide for backwards compatibility with CryInput.
|
||||
struct Button
|
||||
{
|
||||
static const InputChannelId Left; //!< The left mouse button
|
||||
static const InputChannelId Right; //!< The right mouse button
|
||||
static const InputChannelId Middle; //!< The middle mouse button
|
||||
static const InputChannelId Other1; //!< DEPRECATED: the x1 mouse button
|
||||
static const InputChannelId Other2; //!< DEPRECATED: the x2 mouse button
|
||||
static constexpr inline InputChannelId Left{"mouse_button_left"}; //!< The left mouse button
|
||||
static constexpr inline InputChannelId Right{"mouse_button_right"}; //!< The right mouse button
|
||||
static constexpr inline InputChannelId Middle{"mouse_button_middle"}; //!< The middle mouse button
|
||||
static constexpr inline InputChannelId Other1{"mouse_button_other1"}; //!< DEPRECATED: the x1 mouse button
|
||||
static constexpr inline InputChannelId Other2{"mouse_button_other2"}; //!< DEPRECATED: the x2 mouse button
|
||||
|
||||
//!< All mouse button ids
|
||||
static const AZStd::array<InputChannelId, 5> All;
|
||||
static constexpr inline AZStd::array All
|
||||
{
|
||||
Left,
|
||||
Right,
|
||||
Middle,
|
||||
Other1,
|
||||
Other2
|
||||
};
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -82,12 +89,17 @@ namespace AzFramework
|
||||
//! directly correlate to the mouse position (which is queried directly from the system).
|
||||
struct Movement
|
||||
{
|
||||
static const InputChannelId X; //!< Raw horizontal mouse movement over the last frame
|
||||
static const InputChannelId Y; //!< Raw vertical mouse movement over the last frame
|
||||
static const InputChannelId Z; //!< Raw mouse wheel movement over the last frame
|
||||
static constexpr inline InputChannelId X{"mouse_delta_x"}; //!< Raw horizontal mouse movement over the last frame
|
||||
static constexpr inline InputChannelId Y{"mouse_delta_y"}; //!< Raw vertical mouse movement over the last frame
|
||||
static constexpr inline InputChannelId Z{"mouse_delta_z"}; //!< Raw mouse wheel movement over the last frame
|
||||
|
||||
//!< All mouse movement ids
|
||||
static const AZStd::array<InputChannelId, 3> All;
|
||||
static constexpr inline AZStd::array All
|
||||
{
|
||||
X,
|
||||
Y,
|
||||
Z
|
||||
};
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -96,7 +108,7 @@ namespace AzFramework
|
||||
//! the system cursor is hidden or visible. When the system cursor has been constrained to
|
||||
//! the active window values will be in the [0.0, 1.0] range, but not when unconstrained.
|
||||
//! See also InputSystemCursorRequests::SetSystemCursorState and GetSystemCursorState.
|
||||
static const InputChannelId SystemCursorPosition;
|
||||
static constexpr inline InputChannelId SystemCursorPosition{"mouse_system_cursor_position"};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Allocator
|
||||
|
||||
@@ -24,31 +24,6 @@ namespace AzFramework
|
||||
return (inputDeviceId.GetNameCrc32() == Id.GetNameCrc32());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const InputChannelId InputDeviceTouch::Touch::Index0("touch_index_0");
|
||||
const InputChannelId InputDeviceTouch::Touch::Index1("touch_index_1");
|
||||
const InputChannelId InputDeviceTouch::Touch::Index2("touch_index_2");
|
||||
const InputChannelId InputDeviceTouch::Touch::Index3("touch_index_3");
|
||||
const InputChannelId InputDeviceTouch::Touch::Index4("touch_index_4");
|
||||
const InputChannelId InputDeviceTouch::Touch::Index5("touch_index_5");
|
||||
const InputChannelId InputDeviceTouch::Touch::Index6("touch_index_6");
|
||||
const InputChannelId InputDeviceTouch::Touch::Index7("touch_index_7");
|
||||
const InputChannelId InputDeviceTouch::Touch::Index8("touch_index_8");
|
||||
const InputChannelId InputDeviceTouch::Touch::Index9("touch_index_9");
|
||||
const AZStd::array<InputChannelId, 10> InputDeviceTouch::Touch::All =
|
||||
{{
|
||||
Index0,
|
||||
Index1,
|
||||
Index2,
|
||||
Index3,
|
||||
Index4,
|
||||
Index5,
|
||||
Index6,
|
||||
Index7,
|
||||
Index8,
|
||||
Index9
|
||||
}};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void InputDeviceTouch::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
|
||||
@@ -38,19 +38,31 @@ namespace AzFramework
|
||||
//! track is arbitrary, but ten seems to be more than sufficient for most game applications.
|
||||
struct Touch
|
||||
{
|
||||
static const InputChannelId Index0; //!< Touch index 0
|
||||
static const InputChannelId Index1; //!< Touch index 1
|
||||
static const InputChannelId Index2; //!< Touch index 2
|
||||
static const InputChannelId Index3; //!< Touch index 3
|
||||
static const InputChannelId Index4; //!< Touch index 4
|
||||
static const InputChannelId Index5; //!< Touch index 5
|
||||
static const InputChannelId Index6; //!< Touch index 6
|
||||
static const InputChannelId Index7; //!< Touch index 7
|
||||
static const InputChannelId Index8; //!< Touch index 8
|
||||
static const InputChannelId Index9; //!< Touch index 9
|
||||
static constexpr inline InputChannelId Index0{"touch_index_0"}; //!< Touch index 0
|
||||
static constexpr inline InputChannelId Index1{"touch_index_1"}; //!< Touch index 1
|
||||
static constexpr inline InputChannelId Index2{"touch_index_2"}; //!< Touch index 2
|
||||
static constexpr inline InputChannelId Index3{"touch_index_3"}; //!< Touch index 3
|
||||
static constexpr inline InputChannelId Index4{"touch_index_4"}; //!< Touch index 4
|
||||
static constexpr inline InputChannelId Index5{"touch_index_5"}; //!< Touch index 5
|
||||
static constexpr inline InputChannelId Index6{"touch_index_6"}; //!< Touch index 6
|
||||
static constexpr inline InputChannelId Index7{"touch_index_7"}; //!< Touch index 7
|
||||
static constexpr inline InputChannelId Index8{"touch_index_8"}; //!< Touch index 8
|
||||
static constexpr inline InputChannelId Index9{"touch_index_9"}; //!< Touch index 9
|
||||
|
||||
//!< All touch input channel ids
|
||||
static const AZStd::array<InputChannelId, 10> All;
|
||||
static constexpr inline AZStd::array All
|
||||
{
|
||||
Index0,
|
||||
Index1,
|
||||
Index2,
|
||||
Index3,
|
||||
Index4,
|
||||
Index5,
|
||||
Index6,
|
||||
Index7,
|
||||
Index8,
|
||||
Index9
|
||||
};
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
-11
@@ -23,17 +23,6 @@ namespace AzFramework
|
||||
return (inputDeviceId.GetNameCrc32() == Id.GetNameCrc32());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const InputChannelId InputDeviceVirtualKeyboard::Command::EditEnter("virtual_keyboard_edit_enter");
|
||||
const InputChannelId InputDeviceVirtualKeyboard::Command::EditClear("virtual_keyboard_edit_clear");
|
||||
const InputChannelId InputDeviceVirtualKeyboard::Command::NavigationBack("virtual_keyboard_navigation_back");
|
||||
const AZStd::array<InputChannelId, 3> InputDeviceVirtualKeyboard::Command::All =
|
||||
{{
|
||||
EditClear,
|
||||
EditEnter,
|
||||
NavigationBack
|
||||
}};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void InputDeviceVirtualKeyboard::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
|
||||
+9
-4
@@ -39,17 +39,22 @@ namespace AzFramework
|
||||
struct Command
|
||||
{
|
||||
//!< The clear command used to indicate the user wants to clear the active text field
|
||||
static const InputChannelId EditClear;
|
||||
static constexpr inline InputChannelId EditClear{"virtual_keyboard_edit_enter"};
|
||||
|
||||
//!< The enter/return/close command used to indicate the user has finished text editing
|
||||
static const InputChannelId EditEnter;
|
||||
static constexpr inline InputChannelId EditEnter{"virtual_keyboard_edit_clear"};
|
||||
|
||||
//!< The back command used to indicate the user wants to navigate 'backwards'.
|
||||
//!< This is specific to android devices, and does not have an ios equivalent.
|
||||
static const InputChannelId NavigationBack;
|
||||
static constexpr inline InputChannelId NavigationBack{"virtual_keyboard_navigation_back"};
|
||||
|
||||
//!< All virtual keyboard command ids
|
||||
static const AZStd::array<InputChannelId, 3> All;
|
||||
static constexpr inline AZStd::array All
|
||||
{
|
||||
EditClear,
|
||||
EditEnter,
|
||||
NavigationBack
|
||||
};
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -95,4 +95,4 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
|
||||
|
||||
endif()
|
||||
|
||||
endif()
|
||||
endif()
|
||||
|
||||
+20
-25
@@ -6,29 +6,26 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzFramework/API/ApplicationAPI_Platform.h>
|
||||
#include <AzFramework/Application/Application.h>
|
||||
#include "Application_Linux_xcb.h"
|
||||
#include <AzFramework/XcbApplication.h>
|
||||
#include <AzFramework/XcbEventHandler.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
namespace AzFramework
|
||||
{
|
||||
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
class LinuxXcbConnectionManagerImpl
|
||||
: public LinuxXcbConnectionManagerBus::Handler
|
||||
class XcbConnectionManagerImpl
|
||||
: public XcbConnectionManagerBus::Handler
|
||||
{
|
||||
public:
|
||||
LinuxXcbConnectionManagerImpl()
|
||||
XcbConnectionManagerImpl()
|
||||
{
|
||||
m_xcbConnection = xcb_connect(nullptr, nullptr);
|
||||
AZ_Error("ApplicationLinux", m_xcbConnection != nullptr, "Unable to connect to X11 Server.");
|
||||
LinuxXcbConnectionManagerBus::Handler::BusConnect();
|
||||
AZ_Error("Application", m_xcbConnection != nullptr, "Unable to connect to X11 Server.");
|
||||
XcbConnectionManagerBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
~LinuxXcbConnectionManagerImpl()
|
||||
~XcbConnectionManagerImpl() override
|
||||
{
|
||||
LinuxXcbConnectionManagerBus::Handler::BusDisconnect();
|
||||
XcbConnectionManagerBus::Handler::BusDisconnect();
|
||||
xcb_disconnect(m_xcbConnection);
|
||||
}
|
||||
|
||||
@@ -42,53 +39,51 @@ namespace AzFramework
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
ApplicationLinux_xcb::ApplicationLinux_xcb()
|
||||
XcbApplication::XcbApplication()
|
||||
{
|
||||
LinuxLifecycleEvents::Bus::Handler::BusConnect();
|
||||
m_xcbConnectionManager = AZStd::make_unique<LinuxXcbConnectionManagerImpl>();
|
||||
if (LinuxXcbConnectionManagerInterface::Get() == nullptr)
|
||||
m_xcbConnectionManager = AZStd::make_unique<XcbConnectionManagerImpl>();
|
||||
if (XcbConnectionManagerInterface::Get() == nullptr)
|
||||
{
|
||||
LinuxXcbConnectionManagerInterface::Register(m_xcbConnectionManager.get());
|
||||
XcbConnectionManagerInterface::Register(m_xcbConnectionManager.get());
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
ApplicationLinux_xcb::~ApplicationLinux_xcb()
|
||||
XcbApplication::~XcbApplication()
|
||||
{
|
||||
if (LinuxXcbConnectionManagerInterface::Get() == m_xcbConnectionManager.get())
|
||||
if (XcbConnectionManagerInterface::Get() == m_xcbConnectionManager.get())
|
||||
{
|
||||
LinuxXcbConnectionManagerInterface::Unregister(m_xcbConnectionManager.get());
|
||||
XcbConnectionManagerInterface::Unregister(m_xcbConnectionManager.get());
|
||||
}
|
||||
m_xcbConnectionManager.reset();
|
||||
LinuxLifecycleEvents::Bus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void ApplicationLinux_xcb::PumpSystemEventLoopOnce()
|
||||
void XcbApplication::PumpSystemEventLoopOnce()
|
||||
{
|
||||
if (xcb_connection_t* xcbConnection = m_xcbConnectionManager->GetXcbConnection())
|
||||
{
|
||||
if (xcb_generic_event_t* event = xcb_poll_for_event(xcbConnection))
|
||||
{
|
||||
LinuxXcbEventHandlerBus::Broadcast(&LinuxXcbEventHandlerBus::Events::HandleXcbEvent, event);
|
||||
XcbEventHandlerBus::Broadcast(&XcbEventHandlerBus::Events::HandleXcbEvent, event);
|
||||
free(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void ApplicationLinux_xcb::PumpSystemEventLoopUntilEmpty()
|
||||
void XcbApplication::PumpSystemEventLoopUntilEmpty()
|
||||
{
|
||||
if (xcb_connection_t* xcbConnection = m_xcbConnectionManager->GetXcbConnection())
|
||||
{
|
||||
while (xcb_generic_event_t* event = xcb_poll_for_event(xcbConnection))
|
||||
{
|
||||
LinuxXcbEventHandlerBus::Broadcast(&LinuxXcbEventHandlerBus::Events::HandleXcbEvent, event);
|
||||
XcbEventHandlerBus::Broadcast(&XcbEventHandlerBus::Events::HandleXcbEvent, event);
|
||||
free(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
|
||||
} // namespace AzFramework
|
||||
+7
-13
@@ -5,27 +5,24 @@
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzFramework/API/ApplicationAPI_Platform.h>
|
||||
#include <AzFramework/Application/Application.h>
|
||||
#include <AzFramework/XcbConnectionManager.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
namespace AzFramework
|
||||
{
|
||||
|
||||
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
class ApplicationLinux_xcb
|
||||
class XcbApplication
|
||||
: public Application::Implementation
|
||||
, public LinuxLifecycleEvents::Bus::Handler
|
||||
{
|
||||
public:
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
AZ_CLASS_ALLOCATOR(ApplicationLinux_xcb, AZ::SystemAllocator, 0);
|
||||
ApplicationLinux_xcb();
|
||||
~ApplicationLinux_xcb() override;
|
||||
AZ_CLASS_ALLOCATOR(XcbApplication, AZ::SystemAllocator, 0);
|
||||
XcbApplication();
|
||||
~XcbApplication() override;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Application::Implementation
|
||||
@@ -33,9 +30,6 @@ namespace AzFramework
|
||||
void PumpSystemEventLoopUntilEmpty() override;
|
||||
|
||||
private:
|
||||
AZStd::unique_ptr<LinuxXcbConnectionManager> m_xcbConnectionManager;
|
||||
AZStd::unique_ptr<XcbConnectionManager> m_xcbConnectionManager;
|
||||
};
|
||||
|
||||
#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
|
||||
} // namespace AzFramework
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
#include <AzCore/RTTI/RTTI.h>
|
||||
|
||||
#include <xcb/xcb.h>
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
class XcbConnectionManager
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(XcbConnectionManager, "{1F756E14-8D74-42FD-843C-4863307710DB}");
|
||||
|
||||
virtual ~XcbConnectionManager() = default;
|
||||
|
||||
virtual xcb_connection_t* GetXcbConnection() const = 0;
|
||||
};
|
||||
|
||||
class XcbConnectionManagerBusTraits
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// EBusTraits overrides
|
||||
static constexpr AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
|
||||
static constexpr AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
};
|
||||
|
||||
using XcbConnectionManagerBus = AZ::EBus<XcbConnectionManager, XcbConnectionManagerBusTraits>;
|
||||
using XcbConnectionManagerInterface = AZ::Interface<XcbConnectionManager>;
|
||||
} // namespace AzFramework
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
#include <AzCore/RTTI/RTTI.h>
|
||||
|
||||
#include <xcb/xcb.h>
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
class XcbEventHandler
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(XcbEventHandler, "{3F756E14-8D74-42FD-843C-4863307710DB}");
|
||||
|
||||
virtual ~XcbEventHandler() = default;
|
||||
|
||||
virtual void HandleXcbEvent(xcb_generic_event_t* event) = 0;
|
||||
};
|
||||
|
||||
class XcbEventHandlerBusTraits
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// EBusTraits overrides
|
||||
static constexpr AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
|
||||
static constexpr AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
};
|
||||
|
||||
using XcbEventHandlerBus = AZ::EBus<XcbEventHandler, XcbEventHandlerBusTraits>;
|
||||
} // namespace AzFramework
|
||||
+271
@@ -0,0 +1,271 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard.h>
|
||||
#include <AzFramework/XcbEventHandler.h>
|
||||
#include <AzFramework/XcbConnectionManager.h>
|
||||
#include <AzFramework/XcbInputDeviceKeyboard.h>
|
||||
|
||||
#define explicit ExplicitIsACXXKeyword
|
||||
#include <xcb/xkb.h>
|
||||
#undef explicit
|
||||
#include <xkbcommon/xkbcommon-keysyms.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
#include <xkbcommon/xkbcommon-x11.h>
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
XcbInputDeviceKeyboard::XcbInputDeviceKeyboard(InputDeviceKeyboard& inputDevice)
|
||||
: InputDeviceKeyboard::Implementation(inputDevice)
|
||||
{
|
||||
XcbEventHandlerBus::Handler::BusConnect();
|
||||
|
||||
auto* interface = AzFramework::XcbConnectionManagerInterface::Get();
|
||||
if (!interface)
|
||||
{
|
||||
AZ_Warning("ApplicationLinux", false, "XCB interface not available");
|
||||
return;
|
||||
}
|
||||
|
||||
auto* connection = interface->GetXcbConnection();
|
||||
if (!connection)
|
||||
{
|
||||
AZ_Warning("ApplicationLinux", false, "XCB connection not available");
|
||||
return;
|
||||
}
|
||||
|
||||
XcbStdFreePtr<xcb_xkb_use_extension_reply_t> xkbUseExtensionReply{
|
||||
xcb_xkb_use_extension_reply(connection, xcb_xkb_use_extension(connection, 1, 0), nullptr)
|
||||
};
|
||||
if (!xkbUseExtensionReply)
|
||||
{
|
||||
AZ_Warning("ApplicationLinux", false, "Failed to initialize the xkb extension");
|
||||
return;
|
||||
}
|
||||
if (!xkbUseExtensionReply->supported)
|
||||
{
|
||||
AZ_Warning("ApplicationLinux", false, "The X server does not support the xkb extension");
|
||||
return;
|
||||
}
|
||||
|
||||
m_coreDeviceId = xkb_x11_get_core_keyboard_device_id(connection);
|
||||
|
||||
m_xkbContext.reset(xkb_context_new(XKB_CONTEXT_NO_FLAGS));
|
||||
m_xkbKeymap.reset(xkb_x11_keymap_new_from_device(m_xkbContext.get(), connection, m_coreDeviceId, XKB_KEYMAP_COMPILE_NO_FLAGS));
|
||||
m_xkbState.reset(xkb_x11_state_new_from_device(m_xkbKeymap.get(), connection, m_coreDeviceId));
|
||||
|
||||
m_initialized = true;
|
||||
}
|
||||
|
||||
bool XcbInputDeviceKeyboard::IsConnected() const
|
||||
{
|
||||
auto* connection = AzFramework::XcbConnectionManagerInterface::Get()->GetXcbConnection();
|
||||
return connection && !xcb_connection_has_error(connection);
|
||||
}
|
||||
|
||||
bool XcbInputDeviceKeyboard::HasTextEntryStarted() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void XcbInputDeviceKeyboard::TextEntryStart(const InputDeviceKeyboard::VirtualKeyboardOptions& options)
|
||||
{
|
||||
}
|
||||
|
||||
void XcbInputDeviceKeyboard::TextEntryStop()
|
||||
{
|
||||
}
|
||||
|
||||
void XcbInputDeviceKeyboard::TickInputDevice()
|
||||
{
|
||||
ProcessRawEventQueues();
|
||||
}
|
||||
|
||||
void XcbInputDeviceKeyboard::HandleXcbEvent(xcb_generic_event_t* event)
|
||||
{
|
||||
if (!m_initialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event->response_type & ~0x80)
|
||||
{
|
||||
case XCB_KEY_PRESS:
|
||||
{
|
||||
auto* keyPress = reinterpret_cast<xcb_key_press_event_t*>(event);
|
||||
|
||||
const InputChannelId* key = InputChannelFromKeyEvent(keyPress->detail);
|
||||
if (key)
|
||||
{
|
||||
QueueRawKeyEvent(*key, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case XCB_KEY_RELEASE:
|
||||
{
|
||||
auto* keyRelease = reinterpret_cast<xcb_key_release_event_t*>(event);
|
||||
|
||||
const InputChannelId* key = InputChannelFromKeyEvent(keyRelease->detail);
|
||||
if (key)
|
||||
{
|
||||
QueueRawKeyEvent(*key, false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] const InputChannelId* XcbInputDeviceKeyboard::InputChannelFromKeyEvent(xcb_keycode_t code) const
|
||||
{
|
||||
const xcb_keysym_t keysym = xkb_state_key_get_one_sym(m_xkbState.get(), code);
|
||||
|
||||
switch(keysym)
|
||||
{
|
||||
case XKB_KEY_0: return &InputDeviceKeyboard::Key::Alphanumeric0;
|
||||
case XKB_KEY_1: return &InputDeviceKeyboard::Key::Alphanumeric1;
|
||||
case XKB_KEY_2: return &InputDeviceKeyboard::Key::Alphanumeric2;
|
||||
case XKB_KEY_3: return &InputDeviceKeyboard::Key::Alphanumeric3;
|
||||
case XKB_KEY_4: return &InputDeviceKeyboard::Key::Alphanumeric4;
|
||||
case XKB_KEY_5: return &InputDeviceKeyboard::Key::Alphanumeric5;
|
||||
case XKB_KEY_6: return &InputDeviceKeyboard::Key::Alphanumeric6;
|
||||
case XKB_KEY_7: return &InputDeviceKeyboard::Key::Alphanumeric7;
|
||||
case XKB_KEY_8: return &InputDeviceKeyboard::Key::Alphanumeric8;
|
||||
case XKB_KEY_9: return &InputDeviceKeyboard::Key::Alphanumeric9;
|
||||
case XKB_KEY_A:
|
||||
case XKB_KEY_a: return &InputDeviceKeyboard::Key::AlphanumericA;
|
||||
case XKB_KEY_B:
|
||||
case XKB_KEY_b: return &InputDeviceKeyboard::Key::AlphanumericB;
|
||||
case XKB_KEY_C:
|
||||
case XKB_KEY_c: return &InputDeviceKeyboard::Key::AlphanumericC;
|
||||
case XKB_KEY_D:
|
||||
case XKB_KEY_d: return &InputDeviceKeyboard::Key::AlphanumericD;
|
||||
case XKB_KEY_E:
|
||||
case XKB_KEY_e: return &InputDeviceKeyboard::Key::AlphanumericE;
|
||||
case XKB_KEY_F:
|
||||
case XKB_KEY_f: return &InputDeviceKeyboard::Key::AlphanumericF;
|
||||
case XKB_KEY_G:
|
||||
case XKB_KEY_g: return &InputDeviceKeyboard::Key::AlphanumericG;
|
||||
case XKB_KEY_H:
|
||||
case XKB_KEY_h: return &InputDeviceKeyboard::Key::AlphanumericH;
|
||||
case XKB_KEY_I:
|
||||
case XKB_KEY_i: return &InputDeviceKeyboard::Key::AlphanumericI;
|
||||
case XKB_KEY_J:
|
||||
case XKB_KEY_j: return &InputDeviceKeyboard::Key::AlphanumericJ;
|
||||
case XKB_KEY_K:
|
||||
case XKB_KEY_k: return &InputDeviceKeyboard::Key::AlphanumericK;
|
||||
case XKB_KEY_L:
|
||||
case XKB_KEY_l: return &InputDeviceKeyboard::Key::AlphanumericL;
|
||||
case XKB_KEY_M:
|
||||
case XKB_KEY_m: return &InputDeviceKeyboard::Key::AlphanumericM;
|
||||
case XKB_KEY_N:
|
||||
case XKB_KEY_n: return &InputDeviceKeyboard::Key::AlphanumericN;
|
||||
case XKB_KEY_O:
|
||||
case XKB_KEY_o: return &InputDeviceKeyboard::Key::AlphanumericO;
|
||||
case XKB_KEY_P:
|
||||
case XKB_KEY_p: return &InputDeviceKeyboard::Key::AlphanumericP;
|
||||
case XKB_KEY_Q:
|
||||
case XKB_KEY_q: return &InputDeviceKeyboard::Key::AlphanumericQ;
|
||||
case XKB_KEY_R:
|
||||
case XKB_KEY_r: return &InputDeviceKeyboard::Key::AlphanumericR;
|
||||
case XKB_KEY_S:
|
||||
case XKB_KEY_s: return &InputDeviceKeyboard::Key::AlphanumericS;
|
||||
case XKB_KEY_T:
|
||||
case XKB_KEY_t: return &InputDeviceKeyboard::Key::AlphanumericT;
|
||||
case XKB_KEY_U:
|
||||
case XKB_KEY_u: return &InputDeviceKeyboard::Key::AlphanumericU;
|
||||
case XKB_KEY_V:
|
||||
case XKB_KEY_v: return &InputDeviceKeyboard::Key::AlphanumericV;
|
||||
case XKB_KEY_W:
|
||||
case XKB_KEY_w: return &InputDeviceKeyboard::Key::AlphanumericW;
|
||||
case XKB_KEY_X:
|
||||
case XKB_KEY_x: return &InputDeviceKeyboard::Key::AlphanumericX;
|
||||
case XKB_KEY_Y:
|
||||
case XKB_KEY_y: return &InputDeviceKeyboard::Key::AlphanumericY;
|
||||
case XKB_KEY_Z:
|
||||
case XKB_KEY_z: return &InputDeviceKeyboard::Key::AlphanumericZ;
|
||||
case XKB_KEY_BackSpace: return &InputDeviceKeyboard::Key::EditBackspace;
|
||||
case XKB_KEY_Caps_Lock: return &InputDeviceKeyboard::Key::EditCapsLock;
|
||||
case XKB_KEY_Return: return &InputDeviceKeyboard::Key::EditEnter;
|
||||
case XKB_KEY_space: return &InputDeviceKeyboard::Key::EditSpace;
|
||||
case XKB_KEY_Tab: return &InputDeviceKeyboard::Key::EditTab;
|
||||
case XKB_KEY_Escape: return &InputDeviceKeyboard::Key::Escape;
|
||||
case XKB_KEY_F1: return &InputDeviceKeyboard::Key::Function01;
|
||||
case XKB_KEY_F2: return &InputDeviceKeyboard::Key::Function02;
|
||||
case XKB_KEY_F3: return &InputDeviceKeyboard::Key::Function03;
|
||||
case XKB_KEY_F4: return &InputDeviceKeyboard::Key::Function04;
|
||||
case XKB_KEY_F5: return &InputDeviceKeyboard::Key::Function05;
|
||||
case XKB_KEY_F6: return &InputDeviceKeyboard::Key::Function06;
|
||||
case XKB_KEY_F7: return &InputDeviceKeyboard::Key::Function07;
|
||||
case XKB_KEY_F8: return &InputDeviceKeyboard::Key::Function08;
|
||||
case XKB_KEY_F9: return &InputDeviceKeyboard::Key::Function09;
|
||||
case XKB_KEY_F10: return &InputDeviceKeyboard::Key::Function10;
|
||||
case XKB_KEY_F11: return &InputDeviceKeyboard::Key::Function11;
|
||||
case XKB_KEY_F12: return &InputDeviceKeyboard::Key::Function12;
|
||||
case XKB_KEY_F13: return &InputDeviceKeyboard::Key::Function13;
|
||||
case XKB_KEY_F14: return &InputDeviceKeyboard::Key::Function14;
|
||||
case XKB_KEY_F15: return &InputDeviceKeyboard::Key::Function15;
|
||||
case XKB_KEY_F16: return &InputDeviceKeyboard::Key::Function16;
|
||||
case XKB_KEY_F17: return &InputDeviceKeyboard::Key::Function17;
|
||||
case XKB_KEY_F18: return &InputDeviceKeyboard::Key::Function18;
|
||||
case XKB_KEY_F19: return &InputDeviceKeyboard::Key::Function19;
|
||||
case XKB_KEY_F20: return &InputDeviceKeyboard::Key::Function20;
|
||||
case XKB_KEY_Alt_L: return &InputDeviceKeyboard::Key::ModifierAltL;
|
||||
case XKB_KEY_Alt_R: return &InputDeviceKeyboard::Key::ModifierAltR;
|
||||
case XKB_KEY_Control_L: return &InputDeviceKeyboard::Key::ModifierCtrlL;
|
||||
case XKB_KEY_Control_R: return &InputDeviceKeyboard::Key::ModifierCtrlR;
|
||||
case XKB_KEY_Shift_L: return &InputDeviceKeyboard::Key::ModifierShiftL;
|
||||
case XKB_KEY_Shift_R: return &InputDeviceKeyboard::Key::ModifierShiftR;
|
||||
case XKB_KEY_Super_L: return &InputDeviceKeyboard::Key::ModifierSuperL;
|
||||
case XKB_KEY_Super_R: return &InputDeviceKeyboard::Key::ModifierSuperR;
|
||||
case XKB_KEY_Down: return &InputDeviceKeyboard::Key::NavigationArrowDown;
|
||||
case XKB_KEY_Left: return &InputDeviceKeyboard::Key::NavigationArrowLeft;
|
||||
case XKB_KEY_Right: return &InputDeviceKeyboard::Key::NavigationArrowRight;
|
||||
case XKB_KEY_Up: return &InputDeviceKeyboard::Key::NavigationArrowUp;
|
||||
case XKB_KEY_Delete: return &InputDeviceKeyboard::Key::NavigationDelete;
|
||||
case XKB_KEY_End: return &InputDeviceKeyboard::Key::NavigationEnd;
|
||||
case XKB_KEY_Home: return &InputDeviceKeyboard::Key::NavigationHome;
|
||||
case XKB_KEY_Insert: return &InputDeviceKeyboard::Key::NavigationInsert;
|
||||
case XKB_KEY_Page_Down: return &InputDeviceKeyboard::Key::NavigationPageDown;
|
||||
case XKB_KEY_Page_Up: return &InputDeviceKeyboard::Key::NavigationPageUp;
|
||||
case XKB_KEY_Num_Lock: return &InputDeviceKeyboard::Key::NumLock;
|
||||
case XKB_KEY_KP_0: return &InputDeviceKeyboard::Key::NumPad0;
|
||||
case XKB_KEY_KP_1: return &InputDeviceKeyboard::Key::NumPad1;
|
||||
case XKB_KEY_KP_2: return &InputDeviceKeyboard::Key::NumPad2;
|
||||
case XKB_KEY_KP_3: return &InputDeviceKeyboard::Key::NumPad3;
|
||||
case XKB_KEY_KP_4: return &InputDeviceKeyboard::Key::NumPad4;
|
||||
case XKB_KEY_KP_5: return &InputDeviceKeyboard::Key::NumPad5;
|
||||
case XKB_KEY_KP_6: return &InputDeviceKeyboard::Key::NumPad6;
|
||||
case XKB_KEY_KP_7: return &InputDeviceKeyboard::Key::NumPad7;
|
||||
case XKB_KEY_KP_8: return &InputDeviceKeyboard::Key::NumPad8;
|
||||
case XKB_KEY_KP_9: return &InputDeviceKeyboard::Key::NumPad9;
|
||||
case XKB_KEY_KP_Add: return &InputDeviceKeyboard::Key::NumPadAdd;
|
||||
case XKB_KEY_KP_Decimal: return &InputDeviceKeyboard::Key::NumPadDecimal;
|
||||
case XKB_KEY_KP_Divide: return &InputDeviceKeyboard::Key::NumPadDivide;
|
||||
case XKB_KEY_KP_Enter: return &InputDeviceKeyboard::Key::NumPadEnter;
|
||||
case XKB_KEY_KP_Multiply: return &InputDeviceKeyboard::Key::NumPadMultiply;
|
||||
case XKB_KEY_KP_Subtract: return &InputDeviceKeyboard::Key::NumPadSubtract;
|
||||
case XKB_KEY_apostrophe: return &InputDeviceKeyboard::Key::PunctuationApostrophe;
|
||||
case XKB_KEY_backslash: return &InputDeviceKeyboard::Key::PunctuationBackslash;
|
||||
case XKB_KEY_bracketleft: return &InputDeviceKeyboard::Key::PunctuationBracketL;
|
||||
case XKB_KEY_bracketright: return &InputDeviceKeyboard::Key::PunctuationBracketR;
|
||||
case XKB_KEY_comma: return &InputDeviceKeyboard::Key::PunctuationComma;
|
||||
case XKB_KEY_equal: return &InputDeviceKeyboard::Key::PunctuationEquals;
|
||||
case XKB_KEY_hyphen: return &InputDeviceKeyboard::Key::PunctuationHyphen;
|
||||
case XKB_KEY_period: return &InputDeviceKeyboard::Key::PunctuationPeriod;
|
||||
case XKB_KEY_semicolon: return &InputDeviceKeyboard::Key::PunctuationSemicolon;
|
||||
case XKB_KEY_slash: return &InputDeviceKeyboard::Key::PunctuationSlash;
|
||||
case XKB_KEY_grave:
|
||||
case XKB_KEY_asciitilde: return &InputDeviceKeyboard::Key::PunctuationTilde;
|
||||
case XKB_KEY_ISO_Group_Shift: return &InputDeviceKeyboard::Key::SupplementaryISO;
|
||||
case XKB_KEY_Pause: return &InputDeviceKeyboard::Key::WindowsSystemPause;
|
||||
case XKB_KEY_Print: return &InputDeviceKeyboard::Key::WindowsSystemPrint;
|
||||
case XKB_KEY_Scroll_Lock: return &InputDeviceKeyboard::Key::WindowsSystemScrollLock;
|
||||
default: return nullptr;
|
||||
}
|
||||
}
|
||||
} // namespace AzFramework
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard.h>
|
||||
#include <AzFramework/XcbEventHandler.h>
|
||||
#include <AzFramework/XcbInterface.h>
|
||||
|
||||
#include <xcb/xcb.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
class XcbInputDeviceKeyboard
|
||||
: public InputDeviceKeyboard::Implementation
|
||||
, public XcbEventHandlerBus::Handler
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(XcbInputDeviceKeyboard, AZ::SystemAllocator, 0);
|
||||
|
||||
using InputDeviceKeyboard::Implementation::Implementation;
|
||||
XcbInputDeviceKeyboard(InputDeviceKeyboard& inputDevice);
|
||||
|
||||
bool IsConnected() const override;
|
||||
|
||||
bool HasTextEntryStarted() const override;
|
||||
void TextEntryStart(const InputDeviceKeyboard::VirtualKeyboardOptions& options) override;
|
||||
void TextEntryStop() override;
|
||||
void TickInputDevice() override;
|
||||
|
||||
void HandleXcbEvent(xcb_generic_event_t* event) override;
|
||||
|
||||
private:
|
||||
[[nodiscard]] const InputChannelId* InputChannelFromKeyEvent(xcb_keycode_t code) const;
|
||||
|
||||
XcbUniquePtr<xkb_context, xkb_context_unref> m_xkbContext;
|
||||
XcbUniquePtr<xkb_keymap, xkb_keymap_unref> m_xkbKeymap;
|
||||
XcbUniquePtr<xkb_state, xkb_state_unref> m_xkbState;
|
||||
int m_coreDeviceId{-1};
|
||||
bool m_initialized{false};
|
||||
};
|
||||
} // namespace AzFramework
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <xcb/xcb.h>
|
||||
|
||||
#include <AzCore/std/smart_ptr/unique_ptr.h>
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
// @brief Wrap a function pointer in a type
|
||||
// This serves as a convenient way to wrap a function pointer in a given
|
||||
// type. That type can then be used in a `unique_ptr` or `shared_ptr`.
|
||||
// Using a type instead of a function pointer by value prevents the need to
|
||||
// copy the pointer when copying the smart poiner.
|
||||
template<auto Callable>
|
||||
struct XcbDeleterFreeFunctionWrapper
|
||||
{
|
||||
using value_type = decltype(Callable);
|
||||
static constexpr value_type s_value = Callable;
|
||||
constexpr operator value_type() const noexcept
|
||||
{
|
||||
return s_value;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, auto fn>
|
||||
using XcbUniquePtr = AZStd::unique_ptr<T, XcbDeleterFreeFunctionWrapper<fn>>;
|
||||
|
||||
template<typename T>
|
||||
using XcbStdFreePtr = XcbUniquePtr<T, ::free>;
|
||||
} // namespace AzFramework
|
||||
+22
-29
@@ -6,41 +6,37 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzFramework/API/ApplicationAPI_Platform.h>
|
||||
#include <AzFramework/Application/Application.h>
|
||||
#include <AzFramework/Windowing/NativeWindow.h>
|
||||
#include <xcb/xcb.h>
|
||||
#include <AzFramework/XcbNativeWindow.h>
|
||||
#include <AzFramework/XcbConnectionManager.h>
|
||||
|
||||
#include "NativeWindow_Linux_xcb.h"
|
||||
#include <xcb/xcb.h>
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
|
||||
[[maybe_unused]] const char LinuxXcbErrorWindow[] = "NativeWindow_Linux_xcb";
|
||||
[[maybe_unused]] const char XcbErrorWindow[] = "XcbNativeWindow";
|
||||
static constexpr uint8_t s_XcbFormatDataSize = 32; // Format indicator for xcb for client messages
|
||||
static constexpr uint16_t s_DefaultXcbWindowBorderWidth = 4; // The default border with in pixels if a border was specified
|
||||
static constexpr uint8_t s_XcbResponseTypeMask = 0x7f; // Mask to extract the specific event type from an xcb event
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
NativeWindowImpl_Linux_xcb::NativeWindowImpl_Linux_xcb()
|
||||
XcbNativeWindow::XcbNativeWindow()
|
||||
: NativeWindow::Implementation()
|
||||
{
|
||||
if (auto xcbConnectionManager = AzFramework::LinuxXcbConnectionManagerInterface::Get();
|
||||
if (auto xcbConnectionManager = AzFramework::XcbConnectionManagerInterface::Get();
|
||||
xcbConnectionManager != nullptr)
|
||||
{
|
||||
m_xcbConnection = xcbConnectionManager->GetXcbConnection();
|
||||
}
|
||||
AZ_Error(LinuxXcbErrorWindow, m_xcbConnection != nullptr, "Unable to get XCB Connection");
|
||||
AZ_Error(XcbErrorWindow, m_xcbConnection != nullptr, "Unable to get XCB Connection");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
NativeWindowImpl_Linux_xcb::~NativeWindowImpl_Linux_xcb()
|
||||
{
|
||||
}
|
||||
XcbNativeWindow::~XcbNativeWindow() = default;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void NativeWindowImpl_Linux_xcb::InitWindow(const AZStd::string& title,
|
||||
void XcbNativeWindow::InitWindow(const AZStd::string& title,
|
||||
const WindowGeometry& geometry,
|
||||
const WindowStyleMasks& styleMasks)
|
||||
{
|
||||
@@ -98,13 +94,13 @@ namespace AzFramework
|
||||
|
||||
xcb_intern_atom_cookie_t cookieProtocol = xcb_intern_atom(m_xcbConnection, 1, strlen(wmProtocolString), wmProtocolString);
|
||||
xcb_intern_atom_reply_t* replyProtocol = xcb_intern_atom_reply(m_xcbConnection, cookieProtocol, nullptr);
|
||||
AZ_Error(LinuxXcbErrorWindow, replyProtocol != nullptr, "Unable to query xcb '%s' atom", wmProtocolString);
|
||||
AZ_Error(XcbErrorWindow, replyProtocol != nullptr, "Unable to query xcb '%s' atom", wmProtocolString);
|
||||
m_xcbAtomProtocols = replyProtocol->atom;
|
||||
|
||||
const static char* wmDeleteWindowString = "WM_DELETE_WINDOW";
|
||||
xcb_intern_atom_cookie_t cookieDeleteWindow = xcb_intern_atom(m_xcbConnection, 0, strlen(wmDeleteWindowString), wmDeleteWindowString);
|
||||
xcb_intern_atom_reply_t* replyDeleteWindow = xcb_intern_atom_reply(m_xcbConnection, cookieDeleteWindow, nullptr);
|
||||
AZ_Error(LinuxXcbErrorWindow, replyDeleteWindow != nullptr, "Unable to query xcb '%s' atom", wmDeleteWindowString);
|
||||
AZ_Error(XcbErrorWindow, replyDeleteWindow != nullptr, "Unable to query xcb '%s' atom", wmDeleteWindowString);
|
||||
m_xcbAtomDeleteWindow = replyDeleteWindow->atom;
|
||||
|
||||
xcbCheckResult = xcb_change_property_checked(m_xcbConnection,
|
||||
@@ -123,9 +119,9 @@ namespace AzFramework
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void NativeWindowImpl_Linux_xcb::Activate()
|
||||
void XcbNativeWindow::Activate()
|
||||
{
|
||||
LinuxXcbEventHandlerBus::Handler::BusConnect();
|
||||
XcbEventHandlerBus::Handler::BusConnect();
|
||||
|
||||
if (!m_activated) // nothing to do if window was already activated
|
||||
{
|
||||
@@ -137,7 +133,7 @@ namespace AzFramework
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void NativeWindowImpl_Linux_xcb::Deactivate()
|
||||
void XcbNativeWindow::Deactivate()
|
||||
{
|
||||
if (m_activated) // nothing to do if window was already deactivated
|
||||
{
|
||||
@@ -148,17 +144,17 @@ namespace AzFramework
|
||||
xcb_unmap_window(m_xcbConnection, m_xcbWindow);
|
||||
xcb_flush(m_xcbConnection);
|
||||
}
|
||||
LinuxXcbEventHandlerBus::Handler::BusDisconnect();
|
||||
XcbEventHandlerBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
NativeWindowHandle NativeWindowImpl_Linux_xcb::GetWindowHandle() const
|
||||
NativeWindowHandle XcbNativeWindow::GetWindowHandle() const
|
||||
{
|
||||
return reinterpret_cast<NativeWindowHandle>(m_xcbWindow);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void NativeWindowImpl_Linux_xcb::SetWindowTitle(const AZStd::string& title)
|
||||
void XcbNativeWindow::SetWindowTitle(const AZStd::string& title)
|
||||
{
|
||||
xcb_void_cookie_t xcbCheckResult;
|
||||
xcbCheckResult = xcb_change_property(m_xcbConnection,
|
||||
@@ -173,7 +169,7 @@ namespace AzFramework
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void NativeWindowImpl_Linux_xcb::ResizeClientArea(WindowSize clientAreaSize)
|
||||
void XcbNativeWindow::ResizeClientArea(WindowSize clientAreaSize)
|
||||
{
|
||||
const uint32_t values[] = { clientAreaSize.m_width, clientAreaSize.m_height };
|
||||
|
||||
@@ -184,7 +180,7 @@ namespace AzFramework
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
uint32_t NativeWindowImpl_Linux_xcb::GetDisplayRefreshRate() const
|
||||
uint32_t XcbNativeWindow::GetDisplayRefreshRate() const
|
||||
{
|
||||
// [GFX TODO][GHI - 2678]
|
||||
// Using 60 for now until proper support is added
|
||||
@@ -192,7 +188,7 @@ namespace AzFramework
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
bool NativeWindowImpl_Linux_xcb::ValidateXcbResult(xcb_void_cookie_t cookie)
|
||||
bool XcbNativeWindow::ValidateXcbResult(xcb_void_cookie_t cookie)
|
||||
{
|
||||
bool result = true;
|
||||
if (xcb_generic_error_t* error = xcb_request_check(m_xcbConnection, cookie))
|
||||
@@ -204,7 +200,7 @@ namespace AzFramework
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void NativeWindowImpl_Linux_xcb::HandleXcbEvent(xcb_generic_event_t* event)
|
||||
void XcbNativeWindow::HandleXcbEvent(xcb_generic_event_t* event)
|
||||
{
|
||||
switch (event->response_type & s_XcbResponseTypeMask)
|
||||
{
|
||||
@@ -233,7 +229,7 @@ namespace AzFramework
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void NativeWindowImpl_Linux_xcb::WindowSizeChanged(const uint32_t width, const uint32_t height)
|
||||
void XcbNativeWindow::WindowSizeChanged(const uint32_t width, const uint32_t height)
|
||||
{
|
||||
if (m_width != width || m_height != height)
|
||||
{
|
||||
@@ -246,7 +242,4 @@ namespace AzFramework
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
|
||||
} // namespace AzFramework
|
||||
+9
-10
@@ -5,24 +5,25 @@
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzFramework/API/ApplicationAPI_Platform.h>
|
||||
#include <AzFramework/Application/Application.h>
|
||||
#include <AzFramework/Windowing/NativeWindow.h>
|
||||
#include <AzFramework/XcbEventHandler.h>
|
||||
|
||||
#include <xcb/xcb.h>
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
class NativeWindowImpl_Linux_xcb final
|
||||
class XcbNativeWindow final
|
||||
: public NativeWindow::Implementation
|
||||
, public LinuxXcbEventHandlerBus::Handler
|
||||
, public XcbEventHandlerBus::Handler
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(NativeWindowImpl_Linux_xcb, AZ::SystemAllocator, 0);
|
||||
NativeWindowImpl_Linux_xcb();
|
||||
~NativeWindowImpl_Linux_xcb() override;
|
||||
AZ_CLASS_ALLOCATOR(XcbNativeWindow, AZ::SystemAllocator, 0);
|
||||
XcbNativeWindow();
|
||||
~XcbNativeWindow() override;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// NativeWindow::Implementation
|
||||
@@ -37,7 +38,7 @@ namespace AzFramework
|
||||
uint32_t GetDisplayRefreshRate() const override;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// LinuxXcbEventHandlerBus::Handler
|
||||
// XcbEventHandlerBus::Handler
|
||||
void HandleXcbEvent(xcb_generic_event_t* event) override;
|
||||
|
||||
private:
|
||||
@@ -49,6 +50,4 @@ namespace AzFramework
|
||||
xcb_atom_t m_xcbAtomProtocols;
|
||||
xcb_atom_t m_xcbAtomDeleteWindow;
|
||||
};
|
||||
#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
|
||||
} // namespace AzFramework
|
||||
@@ -0,0 +1,18 @@
|
||||
#
|
||||
# Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
# For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
#
|
||||
#
|
||||
|
||||
set(FILES
|
||||
AzFramework/XcbApplication.cpp
|
||||
AzFramework/XcbApplication.h
|
||||
AzFramework/XcbConnectionManager.h
|
||||
AzFramework/XcbInputDeviceKeyboard.cpp
|
||||
AzFramework/XcbInputDeviceKeyboard.h
|
||||
AzFramework/XcbInterface.h
|
||||
AzFramework/XcbNativeWindow.cpp
|
||||
AzFramework/XcbNativeWindow.h
|
||||
)
|
||||
@@ -12,10 +12,6 @@
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
|
||||
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
#include <xcb/xcb.h>
|
||||
#endif // LY_COMPILE_DEFINITIONS
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
class LinuxLifecycleEvents
|
||||
@@ -30,54 +26,4 @@ namespace AzFramework
|
||||
|
||||
using Bus = AZ::EBus<LinuxLifecycleEvents>;
|
||||
};
|
||||
|
||||
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
class LinuxXcbConnectionManager
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(LinuxXcbConnectionManager, "{1F756E14-8D74-42FD-843C-4863307710DB}");
|
||||
|
||||
virtual ~LinuxXcbConnectionManager() = default;
|
||||
|
||||
virtual xcb_connection_t* GetXcbConnection() const = 0;
|
||||
};
|
||||
|
||||
class LinuxXcbConnectionManagerBusTraits
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// EBusTraits overrides
|
||||
static constexpr AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
|
||||
static constexpr AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
};
|
||||
|
||||
using LinuxXcbConnectionManagerBus = AZ::EBus<LinuxXcbConnectionManager, LinuxXcbConnectionManagerBusTraits>;
|
||||
using LinuxXcbConnectionManagerInterface = AZ::Interface<LinuxXcbConnectionManager>;
|
||||
|
||||
class LinuxXcbEventHandler
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(LinuxXcbEventHandler, "{3F756E14-8D74-42FD-843C-4863307710DB}");
|
||||
|
||||
virtual ~LinuxXcbEventHandler() = default;
|
||||
|
||||
virtual void HandleXcbEvent(xcb_generic_event_t* event) = 0;
|
||||
};
|
||||
|
||||
class LinuxXcbEventHandlerBusTraits
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// EBusTraits overrides
|
||||
static constexpr AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
|
||||
static constexpr AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
};
|
||||
|
||||
using LinuxXcbEventHandlerBus = AZ::EBus<LinuxXcbEventHandler, LinuxXcbEventHandlerBusTraits>;
|
||||
|
||||
#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
} // namespace AzFramework
|
||||
|
||||
+4
-2
@@ -8,7 +8,9 @@
|
||||
|
||||
#include <AzFramework/Application/Application.h>
|
||||
|
||||
#include "Application_Linux_xcb.h"
|
||||
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
#include <AzFramework/XcbApplication.h>
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
namespace AzFramework
|
||||
@@ -17,7 +19,7 @@ namespace AzFramework
|
||||
Application::Implementation* Application::Implementation::Create()
|
||||
{
|
||||
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
return aznew ApplicationLinux_xcb();
|
||||
return aznew XcbApplication();
|
||||
#elif PAL_TRAIT_LINUX_WINDOW_MANAGER_WAYLAND
|
||||
#error "Linux Window Manager Wayland not supported."
|
||||
return nullptr;
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
#include <AzFramework/XcbInputDeviceKeyboard.h>
|
||||
#endif
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
InputDeviceKeyboard::Implementation* InputDeviceKeyboard::Implementation::Create(InputDeviceKeyboard& inputDevice)
|
||||
{
|
||||
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
return aznew XcbInputDeviceKeyboard(inputDevice);
|
||||
#elif PAL_TRAIT_LINUX_WINDOW_MANAGER_WAYLAND
|
||||
#error "Linux Window Manager Wayland not supported."
|
||||
return nullptr;
|
||||
#else
|
||||
#error "Linux Window Manager not recognized."
|
||||
return nullptr;
|
||||
#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
}
|
||||
} // namespace AzFramework
|
||||
-293
@@ -1,293 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/std/typetraits/integral_constant.h>
|
||||
#include <AzFramework/API/ApplicationAPI_Linux.h>
|
||||
#include <AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard.h>
|
||||
|
||||
#define explicit ExplicitIsACXXKeyword
|
||||
#include <xcb/xkb.h>
|
||||
#undef explicit
|
||||
#include <xkbcommon/xkbcommon-keysyms.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
#include <xkbcommon/xkbcommon-x11.h>
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
class InputDeviceKeyboardXcb
|
||||
: public InputDeviceKeyboard::Implementation
|
||||
, public LinuxXcbEventHandlerBus::Handler
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(InputDeviceKeyboardXcb, AZ::SystemAllocator, 0);
|
||||
|
||||
using InputDeviceKeyboard::Implementation::Implementation;
|
||||
InputDeviceKeyboardXcb(InputDeviceKeyboard& inputDevice)
|
||||
: InputDeviceKeyboard::Implementation(inputDevice)
|
||||
{
|
||||
LinuxXcbEventHandlerBus::Handler::BusConnect();
|
||||
|
||||
auto* interface = AzFramework::LinuxXcbConnectionManagerInterface::Get();
|
||||
if (!interface)
|
||||
{
|
||||
AZ_Warning("ApplicationLinux", false, "XCB interface not available");
|
||||
return;
|
||||
}
|
||||
|
||||
auto* connection = AzFramework::LinuxXcbConnectionManagerInterface::Get()->GetXcbConnection();
|
||||
if (!connection)
|
||||
{
|
||||
AZ_Warning("ApplicationLinux", false, "XCB connection not available");
|
||||
return;
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<xcb_xkb_use_extension_reply_t, DeleterForFreeFn<::std::free>> xkbUseExtensionReply{
|
||||
xcb_xkb_use_extension_reply(connection, xcb_xkb_use_extension(connection, 1, 0), nullptr)
|
||||
};
|
||||
if (!xkbUseExtensionReply)
|
||||
{
|
||||
AZ_Warning("ApplicationLinux", false, "Failed to initialize the xkb extension");
|
||||
return;
|
||||
}
|
||||
if (!xkbUseExtensionReply->supported)
|
||||
{
|
||||
AZ_Warning("ApplicationLinux", false, "The X server does not support the xkb extension");
|
||||
return;
|
||||
}
|
||||
|
||||
m_coreDeviceId = xkb_x11_get_core_keyboard_device_id(connection);
|
||||
|
||||
m_xkbContext.reset(xkb_context_new(XKB_CONTEXT_NO_FLAGS));
|
||||
m_xkbKeymap.reset(xkb_x11_keymap_new_from_device(m_xkbContext.get(), connection, m_coreDeviceId, XKB_KEYMAP_COMPILE_NO_FLAGS));
|
||||
m_xkbState.reset(xkb_x11_state_new_from_device(m_xkbKeymap.get(), connection, m_coreDeviceId));
|
||||
|
||||
m_initialized = true;
|
||||
}
|
||||
|
||||
bool IsConnected() const override
|
||||
{
|
||||
return m_initialized;
|
||||
}
|
||||
|
||||
bool HasTextEntryStarted() const override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void TextEntryStart(const InputDeviceKeyboard::VirtualKeyboardOptions& options) override
|
||||
{
|
||||
}
|
||||
|
||||
void TextEntryStop() override
|
||||
{
|
||||
}
|
||||
|
||||
void TickInputDevice() override
|
||||
{
|
||||
ProcessRawEventQueues();
|
||||
}
|
||||
|
||||
void HandleXcbEvent(xcb_generic_event_t* event) override
|
||||
{
|
||||
if (!IsConnected())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event->response_type & ~0x80)
|
||||
{
|
||||
case XCB_KEY_PRESS:
|
||||
{
|
||||
auto* keyPress = reinterpret_cast<xcb_key_press_event_t*>(event);
|
||||
|
||||
const InputChannelId* key = InputChannelFromKeyEvent(keyPress->detail);
|
||||
if (key)
|
||||
{
|
||||
QueueRawKeyEvent(*key, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case XCB_KEY_RELEASE:
|
||||
{
|
||||
auto* keyRelease = reinterpret_cast<xcb_key_release_event_t*>(event);
|
||||
|
||||
const InputChannelId* key = InputChannelFromKeyEvent(keyRelease->detail);
|
||||
if (key)
|
||||
{
|
||||
QueueRawKeyEvent(*key, false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
[[nodiscard]] const InputChannelId* InputChannelFromKeyEvent(xcb_keycode_t code) const
|
||||
{
|
||||
const xcb_keysym_t keysym = xkb_state_key_get_one_sym(m_xkbState.get(), code);
|
||||
|
||||
switch(keysym)
|
||||
{
|
||||
case XKB_KEY_0: return &InputDeviceKeyboard::Key::Alphanumeric0;
|
||||
case XKB_KEY_1: return &InputDeviceKeyboard::Key::Alphanumeric1;
|
||||
case XKB_KEY_2: return &InputDeviceKeyboard::Key::Alphanumeric2;
|
||||
case XKB_KEY_3: return &InputDeviceKeyboard::Key::Alphanumeric3;
|
||||
case XKB_KEY_4: return &InputDeviceKeyboard::Key::Alphanumeric4;
|
||||
case XKB_KEY_5: return &InputDeviceKeyboard::Key::Alphanumeric5;
|
||||
case XKB_KEY_6: return &InputDeviceKeyboard::Key::Alphanumeric6;
|
||||
case XKB_KEY_7: return &InputDeviceKeyboard::Key::Alphanumeric7;
|
||||
case XKB_KEY_8: return &InputDeviceKeyboard::Key::Alphanumeric8;
|
||||
case XKB_KEY_9: return &InputDeviceKeyboard::Key::Alphanumeric9;
|
||||
case XKB_KEY_A:
|
||||
case XKB_KEY_a: return &InputDeviceKeyboard::Key::AlphanumericA;
|
||||
case XKB_KEY_B:
|
||||
case XKB_KEY_b: return &InputDeviceKeyboard::Key::AlphanumericB;
|
||||
case XKB_KEY_C:
|
||||
case XKB_KEY_c: return &InputDeviceKeyboard::Key::AlphanumericC;
|
||||
case XKB_KEY_D:
|
||||
case XKB_KEY_d: return &InputDeviceKeyboard::Key::AlphanumericD;
|
||||
case XKB_KEY_E:
|
||||
case XKB_KEY_e: return &InputDeviceKeyboard::Key::AlphanumericE;
|
||||
case XKB_KEY_F:
|
||||
case XKB_KEY_f: return &InputDeviceKeyboard::Key::AlphanumericF;
|
||||
case XKB_KEY_G:
|
||||
case XKB_KEY_g: return &InputDeviceKeyboard::Key::AlphanumericG;
|
||||
case XKB_KEY_H:
|
||||
case XKB_KEY_h: return &InputDeviceKeyboard::Key::AlphanumericH;
|
||||
case XKB_KEY_I:
|
||||
case XKB_KEY_i: return &InputDeviceKeyboard::Key::AlphanumericI;
|
||||
case XKB_KEY_J:
|
||||
case XKB_KEY_j: return &InputDeviceKeyboard::Key::AlphanumericJ;
|
||||
case XKB_KEY_K:
|
||||
case XKB_KEY_k: return &InputDeviceKeyboard::Key::AlphanumericK;
|
||||
case XKB_KEY_L:
|
||||
case XKB_KEY_l: return &InputDeviceKeyboard::Key::AlphanumericL;
|
||||
case XKB_KEY_M:
|
||||
case XKB_KEY_m: return &InputDeviceKeyboard::Key::AlphanumericM;
|
||||
case XKB_KEY_N:
|
||||
case XKB_KEY_n: return &InputDeviceKeyboard::Key::AlphanumericN;
|
||||
case XKB_KEY_O:
|
||||
case XKB_KEY_o: return &InputDeviceKeyboard::Key::AlphanumericO;
|
||||
case XKB_KEY_P:
|
||||
case XKB_KEY_p: return &InputDeviceKeyboard::Key::AlphanumericP;
|
||||
case XKB_KEY_Q:
|
||||
case XKB_KEY_q: return &InputDeviceKeyboard::Key::AlphanumericQ;
|
||||
case XKB_KEY_R:
|
||||
case XKB_KEY_r: return &InputDeviceKeyboard::Key::AlphanumericR;
|
||||
case XKB_KEY_S:
|
||||
case XKB_KEY_s: return &InputDeviceKeyboard::Key::AlphanumericS;
|
||||
case XKB_KEY_T:
|
||||
case XKB_KEY_t: return &InputDeviceKeyboard::Key::AlphanumericT;
|
||||
case XKB_KEY_U:
|
||||
case XKB_KEY_u: return &InputDeviceKeyboard::Key::AlphanumericU;
|
||||
case XKB_KEY_V:
|
||||
case XKB_KEY_v: return &InputDeviceKeyboard::Key::AlphanumericV;
|
||||
case XKB_KEY_W:
|
||||
case XKB_KEY_w: return &InputDeviceKeyboard::Key::AlphanumericW;
|
||||
case XKB_KEY_X:
|
||||
case XKB_KEY_x: return &InputDeviceKeyboard::Key::AlphanumericX;
|
||||
case XKB_KEY_Y:
|
||||
case XKB_KEY_y: return &InputDeviceKeyboard::Key::AlphanumericY;
|
||||
case XKB_KEY_Z:
|
||||
case XKB_KEY_z: return &InputDeviceKeyboard::Key::AlphanumericZ;
|
||||
case XKB_KEY_BackSpace: return &InputDeviceKeyboard::Key::EditBackspace;
|
||||
case XKB_KEY_Caps_Lock: return &InputDeviceKeyboard::Key::EditCapsLock;
|
||||
case XKB_KEY_Return: return &InputDeviceKeyboard::Key::EditEnter;
|
||||
case XKB_KEY_space: return &InputDeviceKeyboard::Key::EditSpace;
|
||||
case XKB_KEY_Tab: return &InputDeviceKeyboard::Key::EditTab;
|
||||
case XKB_KEY_Escape: return &InputDeviceKeyboard::Key::Escape;
|
||||
case XKB_KEY_F1: return &InputDeviceKeyboard::Key::Function01;
|
||||
case XKB_KEY_F2: return &InputDeviceKeyboard::Key::Function02;
|
||||
case XKB_KEY_F3: return &InputDeviceKeyboard::Key::Function03;
|
||||
case XKB_KEY_F4: return &InputDeviceKeyboard::Key::Function04;
|
||||
case XKB_KEY_F5: return &InputDeviceKeyboard::Key::Function05;
|
||||
case XKB_KEY_F6: return &InputDeviceKeyboard::Key::Function06;
|
||||
case XKB_KEY_F7: return &InputDeviceKeyboard::Key::Function07;
|
||||
case XKB_KEY_F8: return &InputDeviceKeyboard::Key::Function08;
|
||||
case XKB_KEY_F9: return &InputDeviceKeyboard::Key::Function09;
|
||||
case XKB_KEY_F10: return &InputDeviceKeyboard::Key::Function10;
|
||||
case XKB_KEY_F11: return &InputDeviceKeyboard::Key::Function11;
|
||||
case XKB_KEY_F12: return &InputDeviceKeyboard::Key::Function12;
|
||||
case XKB_KEY_F13: return &InputDeviceKeyboard::Key::Function13;
|
||||
case XKB_KEY_F14: return &InputDeviceKeyboard::Key::Function14;
|
||||
case XKB_KEY_F15: return &InputDeviceKeyboard::Key::Function15;
|
||||
case XKB_KEY_F16: return &InputDeviceKeyboard::Key::Function16;
|
||||
case XKB_KEY_F17: return &InputDeviceKeyboard::Key::Function17;
|
||||
case XKB_KEY_F18: return &InputDeviceKeyboard::Key::Function18;
|
||||
case XKB_KEY_F19: return &InputDeviceKeyboard::Key::Function19;
|
||||
case XKB_KEY_F20: return &InputDeviceKeyboard::Key::Function20;
|
||||
case XKB_KEY_Alt_L: return &InputDeviceKeyboard::Key::ModifierAltL;
|
||||
case XKB_KEY_Alt_R: return &InputDeviceKeyboard::Key::ModifierAltR;
|
||||
case XKB_KEY_Control_L: return &InputDeviceKeyboard::Key::ModifierCtrlL;
|
||||
case XKB_KEY_Control_R: return &InputDeviceKeyboard::Key::ModifierCtrlR;
|
||||
case XKB_KEY_Shift_L: return &InputDeviceKeyboard::Key::ModifierShiftL;
|
||||
case XKB_KEY_Shift_R: return &InputDeviceKeyboard::Key::ModifierShiftR;
|
||||
case XKB_KEY_Super_L: return &InputDeviceKeyboard::Key::ModifierSuperL;
|
||||
case XKB_KEY_Super_R: return &InputDeviceKeyboard::Key::ModifierSuperR;
|
||||
case XKB_KEY_Down: return &InputDeviceKeyboard::Key::NavigationArrowDown;
|
||||
case XKB_KEY_Left: return &InputDeviceKeyboard::Key::NavigationArrowLeft;
|
||||
case XKB_KEY_Right: return &InputDeviceKeyboard::Key::NavigationArrowRight;
|
||||
case XKB_KEY_Up: return &InputDeviceKeyboard::Key::NavigationArrowUp;
|
||||
case XKB_KEY_Delete: return &InputDeviceKeyboard::Key::NavigationDelete;
|
||||
case XKB_KEY_End: return &InputDeviceKeyboard::Key::NavigationEnd;
|
||||
case XKB_KEY_Home: return &InputDeviceKeyboard::Key::NavigationHome;
|
||||
case XKB_KEY_Insert: return &InputDeviceKeyboard::Key::NavigationInsert;
|
||||
case XKB_KEY_Page_Down: return &InputDeviceKeyboard::Key::NavigationPageDown;
|
||||
case XKB_KEY_Page_Up: return &InputDeviceKeyboard::Key::NavigationPageUp;
|
||||
case XKB_KEY_Num_Lock: return &InputDeviceKeyboard::Key::NumLock;
|
||||
case XKB_KEY_KP_0: return &InputDeviceKeyboard::Key::NumPad0;
|
||||
case XKB_KEY_KP_1: return &InputDeviceKeyboard::Key::NumPad1;
|
||||
case XKB_KEY_KP_2: return &InputDeviceKeyboard::Key::NumPad2;
|
||||
case XKB_KEY_KP_3: return &InputDeviceKeyboard::Key::NumPad3;
|
||||
case XKB_KEY_KP_4: return &InputDeviceKeyboard::Key::NumPad4;
|
||||
case XKB_KEY_KP_5: return &InputDeviceKeyboard::Key::NumPad5;
|
||||
case XKB_KEY_KP_6: return &InputDeviceKeyboard::Key::NumPad6;
|
||||
case XKB_KEY_KP_7: return &InputDeviceKeyboard::Key::NumPad7;
|
||||
case XKB_KEY_KP_8: return &InputDeviceKeyboard::Key::NumPad8;
|
||||
case XKB_KEY_KP_9: return &InputDeviceKeyboard::Key::NumPad9;
|
||||
case XKB_KEY_KP_Add: return &InputDeviceKeyboard::Key::NumPadAdd;
|
||||
case XKB_KEY_KP_Decimal: return &InputDeviceKeyboard::Key::NumPadDecimal;
|
||||
case XKB_KEY_KP_Divide: return &InputDeviceKeyboard::Key::NumPadDivide;
|
||||
case XKB_KEY_KP_Enter: return &InputDeviceKeyboard::Key::NumPadEnter;
|
||||
case XKB_KEY_KP_Multiply: return &InputDeviceKeyboard::Key::NumPadMultiply;
|
||||
case XKB_KEY_KP_Subtract: return &InputDeviceKeyboard::Key::NumPadSubtract;
|
||||
case XKB_KEY_apostrophe: return &InputDeviceKeyboard::Key::PunctuationApostrophe;
|
||||
case XKB_KEY_backslash: return &InputDeviceKeyboard::Key::PunctuationBackslash;
|
||||
case XKB_KEY_bracketleft: return &InputDeviceKeyboard::Key::PunctuationBracketL;
|
||||
case XKB_KEY_bracketright: return &InputDeviceKeyboard::Key::PunctuationBracketR;
|
||||
case XKB_KEY_comma: return &InputDeviceKeyboard::Key::PunctuationComma;
|
||||
case XKB_KEY_equal: return &InputDeviceKeyboard::Key::PunctuationEquals;
|
||||
case XKB_KEY_hyphen: return &InputDeviceKeyboard::Key::PunctuationHyphen;
|
||||
case XKB_KEY_period: return &InputDeviceKeyboard::Key::PunctuationPeriod;
|
||||
case XKB_KEY_semicolon: return &InputDeviceKeyboard::Key::PunctuationSemicolon;
|
||||
case XKB_KEY_slash: return &InputDeviceKeyboard::Key::PunctuationSlash;
|
||||
case XKB_KEY_grave:
|
||||
case XKB_KEY_asciitilde: return &InputDeviceKeyboard::Key::PunctuationTilde;
|
||||
case XKB_KEY_ISO_Group_Shift: return &InputDeviceKeyboard::Key::SupplementaryISO;
|
||||
case XKB_KEY_Pause: return &InputDeviceKeyboard::Key::WindowsSystemPause;
|
||||
case XKB_KEY_Print: return &InputDeviceKeyboard::Key::WindowsSystemPrint;
|
||||
case XKB_KEY_Scroll_Lock: return &InputDeviceKeyboard::Key::WindowsSystemScrollLock;
|
||||
default: return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
template<auto freeFn>
|
||||
using DeleterForFreeFn = AZStd::integral_constant<decltype(freeFn), freeFn>;
|
||||
|
||||
AZStd::unique_ptr<xkb_context, DeleterForFreeFn<xkb_context_unref>> m_xkbContext;
|
||||
AZStd::unique_ptr<xkb_keymap, DeleterForFreeFn<xkb_keymap_unref>> m_xkbKeymap;
|
||||
AZStd::unique_ptr<xkb_state, DeleterForFreeFn<xkb_state_unref>> m_xkbState;
|
||||
int m_coreDeviceId{-1};
|
||||
bool m_initialized{false};
|
||||
};
|
||||
|
||||
InputDeviceKeyboard::Implementation* InputDeviceKeyboard::Implementation::Create(InputDeviceKeyboard& inputDevice)
|
||||
{
|
||||
return aznew InputDeviceKeyboardXcb(inputDevice);
|
||||
}
|
||||
} // namespace AzFramework
|
||||
+4
-3
@@ -6,14 +6,16 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "NativeWindow_Linux_xcb.h"
|
||||
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
#include <AzFramework/XcbNativeWindow.h>
|
||||
#endif
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
NativeWindow::Implementation* NativeWindow::Implementation::Create()
|
||||
{
|
||||
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
return aznew NativeWindowImpl_Linux_xcb();
|
||||
return aznew XcbNativeWindow();
|
||||
#elif PAL_TRAIT_LINUX_WINDOW_MANAGER_WAYLAND
|
||||
#error "Linux Window Manager Wayland not supported."
|
||||
return nullptr;
|
||||
@@ -22,5 +24,4 @@ namespace AzFramework
|
||||
return nullptr;
|
||||
#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
}
|
||||
|
||||
} // namespace AzFramework
|
||||
|
||||
@@ -10,6 +10,14 @@
|
||||
# Only 'xcb' and 'wayland' are recognized
|
||||
if (${PAL_TRAIT_LINUX_WINDOW_MANAGER} STREQUAL "xcb")
|
||||
|
||||
set(LY_COMPILE_DEFINITIONS PUBLIC PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB)
|
||||
set(LY_INCLUDE_DIRECTORIES
|
||||
PUBLIC
|
||||
Platform/Common/Xcb
|
||||
)
|
||||
set(LY_FILES_CMAKE
|
||||
Platform/Common/Xcb/azframework_xcb_files.cmake
|
||||
)
|
||||
set(LY_BUILD_DEPENDENCIES
|
||||
PRIVATE
|
||||
3rdParty::X11::xcb
|
||||
@@ -18,8 +26,6 @@ if (${PAL_TRAIT_LINUX_WINDOW_MANAGER} STREQUAL "xcb")
|
||||
3rdParty::X11::xkbcommon_X11
|
||||
)
|
||||
|
||||
set(LY_COMPILE_DEFINITIONS PUBLIC PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB)
|
||||
|
||||
elseif(PAL_TRAIT_LINUX_WINDOW_MANAGER STREQUAL "wayland")
|
||||
|
||||
set(LY_COMPILE_DEFINITIONS PUBLIC PAL_TRAIT_LINUX_WINDOW_MANAGER_WAYLAND)
|
||||
|
||||
@@ -12,8 +12,6 @@ set(FILES
|
||||
AzFramework/API/ApplicationAPI_Platform.h
|
||||
AzFramework/API/ApplicationAPI_Linux.h
|
||||
AzFramework/Application/Application_Linux.cpp
|
||||
AzFramework/Application/Application_Linux_xcb.h
|
||||
AzFramework/Application/Application_Linux_xcb.cpp
|
||||
AzFramework/Asset/AssetSystemComponentHelper_Linux.cpp
|
||||
AzFramework/Process/ProcessWatcher_Linux.cpp
|
||||
AzFramework/Process/ProcessCommon.h
|
||||
@@ -22,10 +20,8 @@ set(FILES
|
||||
../Common/Unimplemented/AzFramework/StreamingInstall/StreamingInstall_Unimplemented.cpp
|
||||
../Common/Default/AzFramework/TargetManagement/TargetManagementComponent_Default.cpp
|
||||
AzFramework/Windowing/NativeWindow_Linux.cpp
|
||||
AzFramework/Windowing/NativeWindow_Linux_xcb.h
|
||||
AzFramework/Windowing/NativeWindow_Linux_xcb.cpp
|
||||
../Common/Unimplemented/AzFramework/Input/Devices/Gamepad/InputDeviceGamepad_Unimplemented.cpp
|
||||
AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard_xcb.cpp
|
||||
AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard_Linux.cpp
|
||||
../Common/Unimplemented/AzFramework/Input/Devices/Motion/InputDeviceMotion_Unimplemented.cpp
|
||||
../Common/Unimplemented/AzFramework/Input/Devices/Mouse/InputDeviceMouse_Unimplemented.cpp
|
||||
../Common/Unimplemented/AzFramework/Input/Devices/Touch/InputDeviceTouch_Unimplemented.cpp
|
||||
|
||||
+7
-1
@@ -138,7 +138,13 @@ namespace AzToolsFramework
|
||||
m_indexMap[row] = index;
|
||||
m_rowMap[index] = row;
|
||||
++row;
|
||||
++m_displayedItemsCounter;
|
||||
|
||||
// We only want to increase the displayed counter if it is a parent (Source)
|
||||
// so we don't cut children entries.
|
||||
if (entry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Source)
|
||||
{
|
||||
++m_displayedItemsCounter;
|
||||
}
|
||||
}
|
||||
|
||||
if (model->hasChildren(index))
|
||||
|
||||
+6
-4
@@ -29,20 +29,20 @@ namespace AzToolsFramework
|
||||
{
|
||||
AssetBrowserTableView::AssetBrowserTableView(QWidget* parent)
|
||||
: AzQtComponents::TableView(parent)
|
||||
, m_delegate(new EntryDelegate(this))
|
||||
, m_delegate(new SearchEntryDelegate(this))
|
||||
{
|
||||
setSortingEnabled(true);
|
||||
setSortingEnabled(false);
|
||||
setItemDelegate(m_delegate);
|
||||
setRootIsDecorated(false);
|
||||
|
||||
//Styling the header aligning text to the left and using a bold font.
|
||||
header()->setDefaultAlignment(Qt::AlignLeft);
|
||||
header()->setStyleSheet("QHeaderView { font-weight: bold; }");
|
||||
header()->setStyleSheet("QHeaderView { font-weight: bold; };");
|
||||
|
||||
|
||||
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
|
||||
setMouseTracking(true);
|
||||
setSortingEnabled(false);
|
||||
setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
|
||||
connect(this, &AzQtComponents::TableView::customContextMenuRequested, this, &AssetBrowserTableView::OnContextMenu);
|
||||
@@ -67,6 +67,8 @@ namespace AzToolsFramework
|
||||
|
||||
header()->setSectionResizeMode(0, QHeaderView::ResizeMode::Stretch);
|
||||
header()->setSectionResizeMode(1, QHeaderView::ResizeMode::Stretch);
|
||||
header()->setSortIndicatorShown(false);
|
||||
header()->setSectionsClickable(false);
|
||||
}
|
||||
|
||||
void AssetBrowserTableView::SetName(const QString& name)
|
||||
|
||||
+4
-4
@@ -26,7 +26,7 @@ namespace AzToolsFramework
|
||||
class AssetBrowserEntry;
|
||||
class AssetBrowserTableModel;
|
||||
class AssetBrowserFilterModel;
|
||||
class EntryDelegate;
|
||||
class SearchEntryDelegate;
|
||||
|
||||
class AssetBrowserTableView //! Table view that displays the asset browser entries in a list.
|
||||
: public AzQtComponents::TableView
|
||||
@@ -67,9 +67,9 @@ namespace AzToolsFramework
|
||||
|
||||
private:
|
||||
QString m_name;
|
||||
QPointer<AssetBrowserTableModel> m_tableModel = nullptr;
|
||||
QPointer<AssetBrowserFilterModel> m_sourceFilterModel = nullptr;
|
||||
EntryDelegate* m_delegate = nullptr;
|
||||
QPointer<AssetBrowserTableModel> m_tableModel;
|
||||
QPointer<AssetBrowserFilterModel> m_sourceFilterModel;
|
||||
SearchEntryDelegate* m_delegate = nullptr;
|
||||
|
||||
private Q_SLOTS:
|
||||
void OnContextMenu(const QPoint& point);
|
||||
|
||||
+167
-6
@@ -11,12 +11,13 @@
|
||||
#include <AzToolsFramework/AssetBrowser/AssetBrowserModel.h>
|
||||
#include <AzToolsFramework/Thumbnails/ThumbnailerBus.h>
|
||||
#include <AzToolsFramework/AssetBrowser/Views/EntryDelegate.h>
|
||||
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
#include <AzQtComponents/Components/StyledBusyLabel.h>
|
||||
|
||||
#include <QApplication>
|
||||
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // 4251: class 'QScopedPointer<QBrushData,QBrushDataPointerDeleter>' needs to have dll-interface to be used by clients of class 'QBrush'
|
||||
// 4800: 'uint': forcing value to bool 'true' or 'false' (performance warning)
|
||||
#include <QAbstractItemView>
|
||||
#include <QPainter>
|
||||
AZ_POP_DISABLE_WARNING
|
||||
|
||||
@@ -24,8 +25,13 @@ namespace AzToolsFramework
|
||||
{
|
||||
namespace AssetBrowser
|
||||
{
|
||||
const int ENTRY_SPACING_LEFT_PIXELS = 8;
|
||||
const int ENTRY_ICON_MARGIN_LEFT_PIXELS = 2;
|
||||
static constexpr const char* TreeIconPathFirst = "Assets/Editor/Icons/AssetBrowser/TreeBranch_First.svg";
|
||||
static constexpr const char* TreeIconPathMiddle = "Assets/Editor/Icons/AssetBrowser/TreeBranch_Middle.svg";
|
||||
static constexpr const char* TreeIconPathLast = "Assets/Editor/Icons/AssetBrowser/TreeBranch_Last.svg";
|
||||
static constexpr const char* TreeIconPathOneChild = "Assets/Editor/Icons/AssetBrowser/TreeBranch_OneChild.svg";
|
||||
|
||||
const int EntrySpacingLeftPixels = 8;
|
||||
const int EntryIconMarginLeftPixels = 2;
|
||||
|
||||
EntryDelegate::EntryDelegate(QWidget* parent)
|
||||
: QStyledItemDelegate(parent)
|
||||
@@ -62,7 +68,7 @@ namespace AzToolsFramework
|
||||
|
||||
// Draw main entry thumbnail.
|
||||
QRect remainingRect(option.rect);
|
||||
remainingRect.adjust(ENTRY_ICON_MARGIN_LEFT_PIXELS, 0, 0, 0); // bump it rightwards to give some margin to the icon.
|
||||
remainingRect.adjust(EntryIconMarginLeftPixels, 0, 0, 0); // bump it rightwards to give some margin to the icon.
|
||||
|
||||
QSize iconSize(m_iconSize, m_iconSize);
|
||||
// Note that the thumbnail might actually be smaller than the row if theres a lot of padding or font size
|
||||
@@ -89,7 +95,7 @@ namespace AzToolsFramework
|
||||
}
|
||||
|
||||
remainingRect.adjust(thumbX, 0, 0, 0); // bump it to the right by the size of the thumbnail
|
||||
remainingRect.adjust(ENTRY_SPACING_LEFT_PIXELS, 0, 0, 0); // bump it to the right by the spacing.
|
||||
remainingRect.adjust(EntrySpacingLeftPixels, 0, 0, 0); // bump it to the right by the spacing.
|
||||
}
|
||||
QString displayString = index.column() == aznumeric_cast<int>(AssetBrowserEntry::Column::Name)
|
||||
? qvariant_cast<QString>(entry->data(aznumeric_cast<int>(AssetBrowserEntry::Column::Name)))
|
||||
@@ -148,7 +154,162 @@ namespace AzToolsFramework
|
||||
return m_iconSize;
|
||||
}
|
||||
|
||||
} // namespace Thumbnailer
|
||||
SearchEntryDelegate::SearchEntryDelegate(QWidget* parent)
|
||||
: EntryDelegate(parent)
|
||||
{
|
||||
LoadBranchPixMaps();
|
||||
}
|
||||
|
||||
void SearchEntryDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
{
|
||||
auto data = index.data(AssetBrowserModel::Roles::EntryRole);
|
||||
if (data.canConvert<const AssetBrowserEntry*>())
|
||||
{
|
||||
bool isEnabled = (option.state & QStyle::State_Enabled) != 0;
|
||||
bool isSelected = (option.state & QStyle::State_Selected) != 0;
|
||||
|
||||
QStyle* style = option.widget ? option.widget->style() : QApplication::style();
|
||||
|
||||
// draw the background
|
||||
style->drawPrimitive(QStyle::PE_PanelItemViewItem, &option, painter, option.widget);
|
||||
|
||||
// Draw main entry thumbnail.
|
||||
QRect remainingRect(option.rect);
|
||||
|
||||
QSize iconSize(m_iconSize, m_iconSize);
|
||||
// Note that the thumbnail might actually be smaller than the row if theres a lot of padding or font size
|
||||
// so it needs to center vertically with padding in that case:
|
||||
QPoint iconTopLeft;
|
||||
QPoint branchIconTopLeft = QPoint();
|
||||
|
||||
auto entry = qvariant_cast<const AssetBrowserEntry*>(data);
|
||||
auto sourceEntry = azrtti_cast<const SourceAssetBrowserEntry*>(entry);
|
||||
|
||||
//If it is a SourceEntry or it is not the column name we don't want to add space for the branch Icon
|
||||
if (sourceEntry || index.column() != aznumeric_cast<int>(AssetBrowserEntry::Column::Name))
|
||||
{
|
||||
remainingRect.adjust(EntryIconMarginLeftPixels, 0, 0, 0); // bump it rightwards to give some margin to the icon.
|
||||
iconTopLeft = QPoint(remainingRect.x(), remainingRect.y() + (remainingRect.height() / 2) - (m_iconSize / 2));
|
||||
}
|
||||
else
|
||||
{
|
||||
remainingRect.adjust(EntryIconMarginLeftPixels + m_iconSize, 0, 0, 0); // bump it rightwards to give some margin to the icon.
|
||||
iconTopLeft = QPoint(remainingRect.x() / 2 + m_iconSize, remainingRect.y() + (remainingRect.height() / 2) - (m_iconSize / 2));
|
||||
branchIconTopLeft = QPoint((remainingRect.x() / 2) - 2, remainingRect.y() + (remainingRect.height() / 2) - (m_iconSize / 2));
|
||||
}
|
||||
|
||||
QPalette actualPalette(option.palette);
|
||||
|
||||
if (index.column() == aznumeric_cast<int>(AssetBrowserEntry::Column::Name))
|
||||
{
|
||||
int thumbX = DrawThumbnail(painter, iconTopLeft, iconSize, entry->GetThumbnailKey());
|
||||
if (sourceEntry)
|
||||
{
|
||||
if (m_showSourceControl)
|
||||
{
|
||||
DrawThumbnail(painter, iconTopLeft, iconSize, sourceEntry->GetSourceControlThumbnailKey());
|
||||
}
|
||||
// sources with no children should be greyed out.
|
||||
if (sourceEntry->GetChildCount() == 0)
|
||||
{
|
||||
isEnabled = false; // draw in disabled style.
|
||||
actualPalette.setCurrentColorGroup(QPalette::Disabled);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//Get the indexes above and below our entry to see what type are they.
|
||||
QAbstractItemView* view = qobject_cast<QAbstractItemView*>(option.styleObject);
|
||||
const QAbstractItemModel* viewModel = view->model();
|
||||
|
||||
const QModelIndex indexBelow = viewModel->index(index.row() + 1, index.column());
|
||||
const QModelIndex indexAbove = viewModel->index(index.row() - 1, index.column());
|
||||
|
||||
auto aboveEntry = qvariant_cast<const AssetBrowserEntry*>(indexBelow.data(AssetBrowserModel::Roles::EntryRole));
|
||||
auto belowEntry = qvariant_cast<const AssetBrowserEntry*>(indexAbove.data(AssetBrowserModel::Roles::EntryRole));
|
||||
|
||||
auto aboveSourceEntry = azrtti_cast<const SourceAssetBrowserEntry*>(aboveEntry);
|
||||
auto belowSourceEntry = azrtti_cast<const SourceAssetBrowserEntry*>(belowEntry);
|
||||
|
||||
// if current index is the last entry in the view
|
||||
// or the index above it is a Source Entry and
|
||||
// the index below is invalid or is valid but it is also a source entry
|
||||
// then the current index is the only child.
|
||||
if (index.row() == viewModel->rowCount() - 1 ||
|
||||
(indexBelow.isValid() && aboveSourceEntry &&
|
||||
(!indexAbove.isValid() || (indexAbove.isValid() && belowSourceEntry))))
|
||||
{
|
||||
DrawBranchPixMap(EntryBranchType::OneChild, painter, branchIconTopLeft, iconSize); // Draw One Child Icon
|
||||
}
|
||||
else if (indexBelow.isValid() && aboveSourceEntry) // The index above is a source entry
|
||||
{
|
||||
DrawBranchPixMap(EntryBranchType::Last, painter, branchIconTopLeft, iconSize); // Draw First child Icon
|
||||
}
|
||||
else if (indexAbove.isValid() && belowSourceEntry) // The index below is a source entry
|
||||
{
|
||||
DrawBranchPixMap(EntryBranchType::First, painter, branchIconTopLeft, iconSize); // Draw Last Child Icon
|
||||
}
|
||||
else //the index above and below are also child entries
|
||||
{
|
||||
DrawBranchPixMap(EntryBranchType::Middle, painter, branchIconTopLeft, iconSize); // Draw Default child Icon.
|
||||
}
|
||||
}
|
||||
|
||||
remainingRect.adjust(thumbX, 0, 0, 0); // bump it to the right by the size of the thumbnail
|
||||
remainingRect.adjust(EntrySpacingLeftPixels, 0, 0, 0); // bump it to the right by the spacing.
|
||||
}
|
||||
QString displayString = index.column() == aznumeric_cast<int>(AssetBrowserEntry::Column::Name)
|
||||
? qvariant_cast<QString>(entry->data(aznumeric_cast<int>(AssetBrowserEntry::Column::Name)))
|
||||
: qvariant_cast<QString>(entry->data(aznumeric_cast<int>(AssetBrowserEntry::Column::Path)));
|
||||
|
||||
style->drawItemText(
|
||||
painter, remainingRect, option.displayAlignment, actualPalette, isEnabled, displayString,
|
||||
isSelected ? QPalette::HighlightedText : QPalette::Text);
|
||||
}
|
||||
}
|
||||
|
||||
void SearchEntryDelegate::LoadBranchPixMaps()
|
||||
{
|
||||
AZ::IO::BasicPath<AZ::IO::FixedMaxPathString> absoluteIconPath;
|
||||
for (int branchType = EntryBranchType::First; branchType != EntryBranchType::Count; ++branchType)
|
||||
{
|
||||
QPixmap pixmap;
|
||||
switch (branchType)
|
||||
{
|
||||
case AzToolsFramework::AssetBrowser::EntryBranchType::First:
|
||||
absoluteIconPath = AZ::IO::FixedMaxPath(AZ::Utils::GetEnginePath()) / TreeIconPathFirst;
|
||||
break;
|
||||
case AzToolsFramework::AssetBrowser::EntryBranchType::Middle:
|
||||
absoluteIconPath = AZ::IO::FixedMaxPath(AZ::Utils::GetEnginePath()) / TreeIconPathMiddle;
|
||||
break;
|
||||
case AzToolsFramework::AssetBrowser::EntryBranchType::Last:
|
||||
absoluteIconPath = AZ::IO::FixedMaxPath(AZ::Utils::GetEnginePath()) / TreeIconPathLast;
|
||||
break;
|
||||
case AzToolsFramework::AssetBrowser::EntryBranchType::OneChild:
|
||||
default:
|
||||
absoluteIconPath = AZ::IO::FixedMaxPath(AZ::Utils::GetEnginePath()) / TreeIconPathOneChild;
|
||||
break;
|
||||
}
|
||||
bool pixmapLoadedSuccess = pixmap.load(absoluteIconPath.c_str());
|
||||
AZ_Assert(pixmapLoadedSuccess, "Error loading Branch Icons in SearchEntryDelegate");
|
||||
|
||||
m_branchIcons[static_cast<EntryBranchType>(branchType)] = pixmap;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void SearchEntryDelegate::DrawBranchPixMap(
|
||||
EntryBranchType branchType, QPainter* painter, const QPoint& point, const QSize& size) const
|
||||
{
|
||||
const QPixmap& pixmap = m_branchIcons[branchType];
|
||||
|
||||
pixmap.scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
const QSize sizeDelta = size - pixmap.size();
|
||||
const QPoint pointDelta = QPoint(sizeDelta.width() / 2, sizeDelta.height() / 2);
|
||||
painter->drawPixmap(point + pointDelta, pixmap);
|
||||
}
|
||||
|
||||
} // namespace AssetBrowser
|
||||
} // namespace AzToolsFramework
|
||||
|
||||
#include "AssetBrowser/Views/moc_EntryDelegate.cpp"
|
||||
|
||||
+29
-1
@@ -27,9 +27,19 @@ namespace AzToolsFramework
|
||||
{
|
||||
namespace AssetBrowser
|
||||
{
|
||||
//! Type of branch icon the delegate should paint.
|
||||
enum EntryBranchType
|
||||
{
|
||||
First,
|
||||
Middle,
|
||||
Last,
|
||||
OneChild,
|
||||
Count
|
||||
};
|
||||
|
||||
class AssetBrowserFilterModel;
|
||||
|
||||
//! EntryDelegate draws a single item in AssetBrowser
|
||||
//! EntryDelegate draws a single item in AssetBrowser.
|
||||
class EntryDelegate
|
||||
: public QStyledItemDelegate
|
||||
{
|
||||
@@ -52,5 +62,23 @@ namespace AzToolsFramework
|
||||
//! Draw a thumbnail and return its width
|
||||
int DrawThumbnail(QPainter* painter, const QPoint& point, const QSize& size, Thumbnailer::SharedThumbnailKey thumbnailKey) const;
|
||||
};
|
||||
|
||||
//! SearchEntryDelegate draws a single item in AssetBrowserTableView.
|
||||
class SearchEntryDelegate
|
||||
: public EntryDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit SearchEntryDelegate(QWidget* parent = nullptr);
|
||||
|
||||
void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
|
||||
|
||||
private:
|
||||
void LoadBranchPixMaps();
|
||||
void DrawBranchPixMap(EntryBranchType branchType, QPainter* painter, const QPoint& point, const QSize& size) const;
|
||||
|
||||
private:
|
||||
QMap<EntryBranchType, QPixmap> m_branchIcons;
|
||||
};
|
||||
} // namespace AssetBrowser
|
||||
} // namespace AzToolsFramework
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace AzToolsFramework
|
||||
virtual AZ::EntityId GetFocusRoot() = 0;
|
||||
|
||||
//! Returns whether the entity id provided is part of the focused sub-tree.
|
||||
virtual bool IsInFocusSubTree(AZ::EntityId entityId) = 0;
|
||||
virtual bool IsInFocusSubTree(AZ::EntityId entityId) const = 0;
|
||||
};
|
||||
|
||||
} // namespace AzToolsFramework
|
||||
|
||||
+1
-1
@@ -86,7 +86,7 @@ namespace AzToolsFramework
|
||||
return m_focusRoot;
|
||||
}
|
||||
|
||||
bool FocusModeSystemComponent::IsInFocusSubTree(AZ::EntityId entityId)
|
||||
bool FocusModeSystemComponent::IsInFocusSubTree(AZ::EntityId entityId) const
|
||||
{
|
||||
if (m_focusRoot == AZ::EntityId())
|
||||
{
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ namespace AzToolsFramework
|
||||
void SetFocusRoot(AZ::EntityId entityId) override;
|
||||
void ClearFocusRoot() override;
|
||||
AZ::EntityId GetFocusRoot() override;
|
||||
bool IsInFocusSubTree(AZ::EntityId entityId) override;
|
||||
bool IsInFocusSubTree(AZ::EntityId entityId) const override;
|
||||
|
||||
private:
|
||||
AZ::EntityId m_focusRoot;
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace AzToolsFramework::Prefab
|
||||
{
|
||||
InstanceOptionalReference focusedInstance;
|
||||
|
||||
if (entityId == AZ::EntityId())
|
||||
if (!entityId.IsValid())
|
||||
{
|
||||
PrefabEditorEntityOwnershipInterface* prefabEditorEntityOwnershipInterface =
|
||||
AZ::Interface<PrefabEditorEntityOwnershipInterface>::Get();
|
||||
@@ -121,7 +121,7 @@ namespace AzToolsFramework::Prefab
|
||||
return false;
|
||||
}
|
||||
|
||||
if (entityId == AZ::EntityId())
|
||||
if (!entityId.IsValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -18,18 +18,19 @@ AzToolsFramework--EntityOutlinerWidget QTreeView
|
||||
selection-background-color: transparent;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Entity Outliner handles hover and selected state of items via code,
|
||||
* so we need to override the AzQtComponents::Treeview style.
|
||||
*/
|
||||
AzToolsFramework--EntityOutlinerWidget QTreeView::branch:hover
|
||||
, AzToolsFramework--EntityOutlinerWidget QTreeView::item:hover
|
||||
{
|
||||
background: rgba(255, 255, 255, 30);
|
||||
}
|
||||
|
||||
AzToolsFramework--EntityOutlinerWidget QTreeView::branch:selected
|
||||
, AzToolsFramework--EntityOutlinerWidget QTreeView::branch:selected
|
||||
, AzToolsFramework--EntityOutlinerWidget QTreeView::item:selected
|
||||
, AzToolsFramework--EntityOutlinerWidget QTreeView::branch:selected:active
|
||||
, AzToolsFramework--EntityOutlinerWidget QTreeView::item:selected:active
|
||||
{
|
||||
background: rgba(255, 255, 255, 45);
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+18
-8
@@ -44,6 +44,7 @@
|
||||
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityHelpers.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityInfoBus.h>
|
||||
#include <AzToolsFramework/FocusMode/FocusModeInterface.h>
|
||||
#include <AzToolsFramework/ToolsComponents/ComponentAssetMimeDataContainer.h>
|
||||
#include <AzToolsFramework/ToolsComponents/ComponentMimeData.h>
|
||||
#include <AzToolsFramework/ToolsComponents/EditorEntityIdContainer.h>
|
||||
@@ -102,10 +103,14 @@ namespace AzToolsFramework
|
||||
EntityCompositionNotificationBus::Handler::BusConnect();
|
||||
AZ::EntitySystemBus::Handler::BusConnect();
|
||||
|
||||
m_editorEntityFrameworkInterface = AZ::Interface<AzToolsFramework::EditorEntityUiInterface>::Get();
|
||||
m_editorEntityUiInterface = AZ::Interface<AzToolsFramework::EditorEntityUiInterface>::Get();
|
||||
AZ_Assert(m_editorEntityUiInterface != nullptr,
|
||||
"EntityOutlinerListModel requires a EditorEntityUiInterface instance on Initialize.");
|
||||
|
||||
AZ_Assert(m_editorEntityFrameworkInterface != nullptr,
|
||||
"EntityOutlinerListModel requires a EditorEntityFrameworkInterface instance on Initialize.");
|
||||
m_focusModeInterface = AZ::Interface<FocusModeInterface>::Get();
|
||||
AZ_Assert(
|
||||
m_focusModeInterface != nullptr,
|
||||
"EntityOutlinerListModel requires a FocusModeInterface instance on Initialize.");
|
||||
}
|
||||
|
||||
int EntityOutlinerListModel::rowCount(const QModelIndex& parent) const
|
||||
@@ -279,7 +284,7 @@ namespace AzToolsFramework
|
||||
|
||||
QVariant EntityOutlinerListModel::GetEntityIcon(const AZ::EntityId& id) const
|
||||
{
|
||||
auto entityUiHandler = m_editorEntityFrameworkInterface->GetHandler(id);
|
||||
auto entityUiHandler = m_editorEntityUiInterface->GetHandler(id);
|
||||
QIcon icon;
|
||||
|
||||
// Retrieve the icon from the handler
|
||||
@@ -316,7 +321,7 @@ namespace AzToolsFramework
|
||||
|
||||
QVariant EntityOutlinerListModel::GetEntityTooltip(const AZ::EntityId& id) const
|
||||
{
|
||||
auto entityUiHandler = m_editorEntityFrameworkInterface->GetHandler(id);
|
||||
auto entityUiHandler = m_editorEntityUiInterface->GetHandler(id);
|
||||
QString tooltip;
|
||||
|
||||
// Retrieve the tooltip from the handler
|
||||
@@ -349,7 +354,7 @@ namespace AzToolsFramework
|
||||
QVariant EntityOutlinerListModel::dataForVisibility(const QModelIndex& index, int role) const
|
||||
{
|
||||
auto entityId = GetEntityFromIndex(index);
|
||||
auto entityUiHandler = m_editorEntityFrameworkInterface->GetHandler(entityId);
|
||||
auto entityUiHandler = m_editorEntityUiInterface->GetHandler(entityId);
|
||||
|
||||
if (!entityUiHandler || entityUiHandler->CanToggleLockVisibility(entityId))
|
||||
{
|
||||
@@ -377,7 +382,7 @@ namespace AzToolsFramework
|
||||
QVariant EntityOutlinerListModel::dataForLock(const QModelIndex& index, int role) const
|
||||
{
|
||||
auto entityId = GetEntityFromIndex(index);
|
||||
auto entityUiHandler = m_editorEntityFrameworkInterface->GetHandler(entityId);
|
||||
auto entityUiHandler = m_editorEntityUiInterface->GetHandler(entityId);
|
||||
|
||||
if (!entityUiHandler || entityUiHandler->CanToggleLockVisibility(entityId))
|
||||
{
|
||||
@@ -436,7 +441,7 @@ namespace AzToolsFramework
|
||||
if (value.canConvert<Qt::CheckState>())
|
||||
{
|
||||
const auto entityId = GetEntityFromIndex(index);
|
||||
auto entityUiHandler = m_editorEntityFrameworkInterface->GetHandler(entityId);
|
||||
auto entityUiHandler = m_editorEntityUiInterface->GetHandler(entityId);
|
||||
|
||||
if (!entityUiHandler || entityUiHandler->CanToggleLockVisibility(entityId))
|
||||
{
|
||||
@@ -532,6 +537,11 @@ namespace AzToolsFramework
|
||||
break;
|
||||
}
|
||||
|
||||
if (AZ::EntityId entityId = GetEntityFromIndex(index); !m_focusModeInterface->IsInFocusSubTree(entityId))
|
||||
{
|
||||
itemFlags &= !Qt::ItemIsEnabled;
|
||||
}
|
||||
|
||||
return itemFlags;
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -36,6 +36,7 @@
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
class EditorEntityUiInterface;
|
||||
class FocusModeInterface;
|
||||
|
||||
namespace EntityOutliner
|
||||
{
|
||||
@@ -273,7 +274,8 @@ namespace AzToolsFramework
|
||||
QVariant GetEntityIcon(const AZ::EntityId& id) const;
|
||||
QVariant GetEntityTooltip(const AZ::EntityId& id) const;
|
||||
|
||||
EditorEntityUiInterface* m_editorEntityFrameworkInterface = nullptr;
|
||||
EditorEntityUiInterface* m_editorEntityUiInterface = nullptr;
|
||||
FocusModeInterface* m_focusModeInterface = nullptr;
|
||||
};
|
||||
|
||||
class EntityOutlinerCheckBox
|
||||
|
||||
+42
@@ -40,6 +40,8 @@ namespace AzToolsFramework
|
||||
"EntityOutlinerTreeView requires a EditorEntityFrameworkInterface instance on Construction.");
|
||||
|
||||
FocusModeNotificationBus::Handler::BusConnect();
|
||||
|
||||
viewport()->setMouseTracking(true);
|
||||
}
|
||||
|
||||
EntityOutlinerTreeView::~EntityOutlinerTreeView()
|
||||
@@ -63,6 +65,11 @@ namespace AzToolsFramework
|
||||
}
|
||||
}
|
||||
|
||||
void EntityOutlinerTreeView::leaveEvent([[maybe_unused]] QEvent* event)
|
||||
{
|
||||
m_mousePosition = QPoint();
|
||||
}
|
||||
|
||||
void EntityOutlinerTreeView::mousePressEvent(QMouseEvent* event)
|
||||
{
|
||||
//postponing normal mouse pressed logic until mouse is released or dragged
|
||||
@@ -116,6 +123,8 @@ namespace AzToolsFramework
|
||||
setSelectionMode(selectionModeBefore);
|
||||
}
|
||||
|
||||
m_mousePosition = event->pos();
|
||||
|
||||
//process mouse movement as normal, potentially triggering drag and drop
|
||||
QTreeView::mouseMoveEvent(event);
|
||||
}
|
||||
@@ -176,12 +185,45 @@ namespace AzToolsFramework
|
||||
|
||||
void EntityOutlinerTreeView::drawBranches(QPainter* painter, const QRect& rect, const QModelIndex& index) const
|
||||
{
|
||||
const bool isEnabled = (this->model()->flags(index) & Qt::ItemIsEnabled);
|
||||
|
||||
const bool isSelected = selectionModel()->isSelected(index);
|
||||
const bool isHovered = (index == indexAt(m_mousePosition)) && isEnabled;
|
||||
|
||||
// Paint the branch Selection/Hover Rect
|
||||
PaintBranchSelectionHoverRect(painter, rect, isSelected, isHovered);
|
||||
|
||||
// Paint the branch background as defined by the entity's handler, or its closes ancestor's.
|
||||
PaintBranchBackground(painter, rect, index);
|
||||
|
||||
QTreeView::drawBranches(painter, rect, index);
|
||||
}
|
||||
|
||||
void EntityOutlinerTreeView::PaintBranchSelectionHoverRect(
|
||||
QPainter* painter, const QRect& rect, bool isSelected, bool isHovered) const
|
||||
{
|
||||
painter->save();
|
||||
painter->setRenderHint(QPainter::Antialiasing, false);
|
||||
|
||||
if (isSelected || isHovered)
|
||||
{
|
||||
QPainterPath backgroundPath;
|
||||
QRect backgroundRect(rect);
|
||||
|
||||
backgroundPath.addRect(backgroundRect);
|
||||
|
||||
QColor backgroundColor = m_hoverColor;
|
||||
if (isSelected)
|
||||
{
|
||||
backgroundColor = m_selectedColor;
|
||||
}
|
||||
|
||||
painter->fillPath(backgroundPath, backgroundColor);
|
||||
}
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
void EntityOutlinerTreeView::PaintBranchBackground(QPainter* painter, const QRect& rect, const QModelIndex& index) const
|
||||
{
|
||||
// Go through ancestors and add them to the stack
|
||||
|
||||
+3
@@ -61,6 +61,7 @@ namespace AzToolsFramework
|
||||
void startDrag(Qt::DropActions supportedActions) override;
|
||||
void dragMoveEvent(QDragMoveEvent* event) override;
|
||||
void dropEvent(QDropEvent* event) override;
|
||||
void leaveEvent(QEvent* event) override;
|
||||
|
||||
// FocusModeNotificationBus overrides ...
|
||||
void OnEditorFocusChanged(AZ::EntityId entityId) override;
|
||||
@@ -77,8 +78,10 @@ namespace AzToolsFramework
|
||||
void StartCustomDrag(const QModelIndexList& indexList, Qt::DropActions supportedActions) override;
|
||||
|
||||
void PaintBranchBackground(QPainter* painter, const QRect& rect, const QModelIndex& index) const;
|
||||
void PaintBranchSelectionHoverRect(QPainter* painter, const QRect& rect, bool isSelected, bool isHovered) const;
|
||||
|
||||
QMouseEvent* m_queuedMouseEvent;
|
||||
QPoint m_mousePosition;
|
||||
bool m_draggingUnselectedItem; // This is set when an item is dragged outside its bounding box.
|
||||
|
||||
int m_expandOnlyDelay = -1;
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <AzFramework/Viewport/CameraState.h>
|
||||
#include <AzFramework/Viewport/ViewportScreen.h>
|
||||
#include <AzFramework/Visibility/BoundsBus.h>
|
||||
#include <AzToolsFramework/FocusMode/FocusModeInterface.h>
|
||||
#include <AzToolsFramework/API/EditorViewportIconDisplayInterface.h>
|
||||
#include <AzToolsFramework/ToolsComponents/EditorEntityIconComponentBus.h>
|
||||
#include <AzToolsFramework/Viewport/ViewportMessages.h>
|
||||
@@ -112,6 +113,17 @@ namespace AzToolsFramework
|
||||
}
|
||||
}
|
||||
|
||||
EditorHelpers::EditorHelpers(const EditorVisibleEntityDataCache* entityDataCache)
|
||||
: m_entityDataCache(entityDataCache)
|
||||
{
|
||||
m_focusModeInterface = AZ::Interface<FocusModeInterface>::Get();
|
||||
AZ_Assert(
|
||||
m_focusModeInterface,
|
||||
"EditorHelpers - "
|
||||
"Focus Mode Interface could not be found. "
|
||||
"Check that it is being correctly initialized.");
|
||||
}
|
||||
|
||||
AZ::EntityId EditorHelpers::HandleMouseInteraction(
|
||||
const AzFramework::CameraState& cameraState, const ViewportInteraction::MouseInteractionEvent& mouseInteraction)
|
||||
{
|
||||
@@ -173,6 +185,12 @@ namespace AzToolsFramework
|
||||
}
|
||||
}
|
||||
|
||||
// Verify if the entity Id corresponds to an entity that is focused; if not, halt selection.
|
||||
if (!m_focusModeInterface->IsInFocusSubTree(entityIdUnderCursor))
|
||||
{
|
||||
return AZ::EntityId();
|
||||
}
|
||||
|
||||
return entityIdUnderCursor;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ namespace AzFramework
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
class EditorVisibleEntityDataCache;
|
||||
class FocusModeInterface;
|
||||
|
||||
namespace ViewportInteraction
|
||||
{
|
||||
@@ -38,10 +39,7 @@ namespace AzToolsFramework
|
||||
|
||||
//! An EditorVisibleEntityDataCache must be passed to EditorHelpers to allow it to
|
||||
//! efficiently read entity data without resorting to EBus calls.
|
||||
explicit EditorHelpers(const EditorVisibleEntityDataCache* entityDataCache)
|
||||
: m_entityDataCache(entityDataCache)
|
||||
{
|
||||
}
|
||||
explicit EditorHelpers(const EditorVisibleEntityDataCache* entityDataCache);
|
||||
EditorHelpers(const EditorHelpers&) = delete;
|
||||
EditorHelpers& operator=(const EditorHelpers&) = delete;
|
||||
~EditorHelpers() = default;
|
||||
@@ -62,5 +60,6 @@ namespace AzToolsFramework
|
||||
|
||||
private:
|
||||
const EditorVisibleEntityDataCache* m_entityDataCache = nullptr; //!< Entity Data queried by the EditorHelpers.
|
||||
const FocusModeInterface* m_focusModeInterface = nullptr;
|
||||
};
|
||||
} // namespace AzToolsFramework
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzTest/AzTest.h>
|
||||
#include <AzCore/UserSettings/UserSettingsComponent.h>
|
||||
#include <AzCore/Component/TransformBus.h>
|
||||
#include <AzToolsFramework/FocusMode/FocusModeInterface.h>
|
||||
#include <AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h>
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
class EditorFocusModeTests
|
||||
: public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
void SetUp() override
|
||||
{
|
||||
m_app.Start(m_descriptor);
|
||||
|
||||
// Without this, the user settings component would attempt to save on finalize/shutdown. Since the file is
|
||||
// shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash
|
||||
// in the unit tests.
|
||||
AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize);
|
||||
|
||||
GenerateTestHierarchy();
|
||||
}
|
||||
|
||||
void GenerateTestHierarchy()
|
||||
{
|
||||
/*
|
||||
* City
|
||||
* |_ Street
|
||||
* |_ Car
|
||||
* | |_ Passenger
|
||||
* |_ SportsCar
|
||||
* |_ Passenger
|
||||
*/
|
||||
|
||||
m_entityMap["cityId"] = CreateEditorEntity("City", AZ::EntityId());
|
||||
m_entityMap["streetId"] = CreateEditorEntity("Street", m_entityMap["cityId"]);
|
||||
m_entityMap["carId"] = CreateEditorEntity("Car", m_entityMap["streetId"]);
|
||||
m_entityMap["passengerId1"] = CreateEditorEntity("Passenger", m_entityMap["carId"]);
|
||||
m_entityMap["sportsCarId"] = CreateEditorEntity("SportsCar", m_entityMap["streetId"]);
|
||||
m_entityMap["passengerId2"] = CreateEditorEntity("Passenger", m_entityMap["sportsCarId"]);
|
||||
}
|
||||
|
||||
AZ::EntityId CreateEditorEntity(const char* name, AZ::EntityId parentId)
|
||||
{
|
||||
AZ::Entity* entity = nullptr;
|
||||
UnitTest::CreateDefaultEditorEntity(name, &entity);
|
||||
|
||||
// Parent
|
||||
AZ::TransformBus::Event(entity->GetId(), &AZ::TransformInterface::SetParent, parentId);
|
||||
|
||||
return entity->GetId();
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
m_app.Stop();
|
||||
}
|
||||
|
||||
UnitTest::ToolsTestApplication m_app{ "EditorFocusModeTests" };
|
||||
AZ::ComponentApplication::Descriptor m_descriptor;
|
||||
AZStd::unordered_map<AZStd::string, AZ::EntityId> m_entityMap;
|
||||
};
|
||||
|
||||
TEST_F(EditorFocusModeTests, EditorFocusModeTests_SetFocus)
|
||||
{
|
||||
FocusModeInterface* focusModeInterface = AZ::Interface<FocusModeInterface>::Get();
|
||||
EXPECT_TRUE(focusModeInterface != nullptr);
|
||||
|
||||
focusModeInterface->SetFocusRoot(m_entityMap["carId"]);
|
||||
EXPECT_EQ(focusModeInterface->GetFocusRoot(), m_entityMap["carId"]);
|
||||
|
||||
focusModeInterface->ClearFocusRoot();
|
||||
EXPECT_EQ(focusModeInterface->GetFocusRoot(), AZ::EntityId());
|
||||
}
|
||||
|
||||
TEST_F(EditorFocusModeTests, EditorFocusModeTests_IsInFocusSubTree)
|
||||
{
|
||||
FocusModeInterface* focusModeInterface = AZ::Interface<FocusModeInterface>::Get();
|
||||
EXPECT_TRUE(focusModeInterface != nullptr);
|
||||
|
||||
focusModeInterface->ClearFocusRoot();
|
||||
|
||||
EXPECT_EQ(focusModeInterface->IsInFocusSubTree(m_entityMap["cityId"]), true);
|
||||
EXPECT_EQ(focusModeInterface->IsInFocusSubTree(m_entityMap["streetId"]), true);
|
||||
EXPECT_EQ(focusModeInterface->IsInFocusSubTree(m_entityMap["carId"]), true);
|
||||
EXPECT_EQ(focusModeInterface->IsInFocusSubTree(m_entityMap["passengerId1"]), true);
|
||||
EXPECT_EQ(focusModeInterface->IsInFocusSubTree(m_entityMap["sportsCarId"]), true);
|
||||
EXPECT_EQ(focusModeInterface->IsInFocusSubTree(m_entityMap["passengerId2"]), true);
|
||||
|
||||
focusModeInterface->SetFocusRoot(m_entityMap["streetId"]);
|
||||
|
||||
EXPECT_EQ(focusModeInterface->IsInFocusSubTree(m_entityMap["cityId"]), false);
|
||||
EXPECT_EQ(focusModeInterface->IsInFocusSubTree(m_entityMap["streetId"]), true);
|
||||
EXPECT_EQ(focusModeInterface->IsInFocusSubTree(m_entityMap["carId"]), true);
|
||||
EXPECT_EQ(focusModeInterface->IsInFocusSubTree(m_entityMap["passengerId1"]), true);
|
||||
EXPECT_EQ(focusModeInterface->IsInFocusSubTree(m_entityMap["sportsCarId"]), true);
|
||||
EXPECT_EQ(focusModeInterface->IsInFocusSubTree(m_entityMap["passengerId2"]), true);
|
||||
|
||||
focusModeInterface->SetFocusRoot(m_entityMap["carId"]);
|
||||
|
||||
EXPECT_EQ(focusModeInterface->IsInFocusSubTree(m_entityMap["cityId"]), false);
|
||||
EXPECT_EQ(focusModeInterface->IsInFocusSubTree(m_entityMap["streetId"]), false);
|
||||
EXPECT_EQ(focusModeInterface->IsInFocusSubTree(m_entityMap["carId"]), true);
|
||||
EXPECT_EQ(focusModeInterface->IsInFocusSubTree(m_entityMap["passengerId1"]), true);
|
||||
EXPECT_EQ(focusModeInterface->IsInFocusSubTree(m_entityMap["sportsCarId"]), false);
|
||||
EXPECT_EQ(focusModeInterface->IsInFocusSubTree(m_entityMap["passengerId2"]), false);
|
||||
|
||||
focusModeInterface->SetFocusRoot(m_entityMap["passengerId2"]);
|
||||
|
||||
EXPECT_EQ(focusModeInterface->IsInFocusSubTree(m_entityMap["cityId"]), false);
|
||||
EXPECT_EQ(focusModeInterface->IsInFocusSubTree(m_entityMap["streetId"]), false);
|
||||
EXPECT_EQ(focusModeInterface->IsInFocusSubTree(m_entityMap["carId"]), false);
|
||||
EXPECT_EQ(focusModeInterface->IsInFocusSubTree(m_entityMap["passengerId1"]), false);
|
||||
EXPECT_EQ(focusModeInterface->IsInFocusSubTree(m_entityMap["sportsCarId"]), false);
|
||||
EXPECT_EQ(focusModeInterface->IsInFocusSubTree(m_entityMap["passengerId2"]), true);
|
||||
|
||||
focusModeInterface->ClearFocusRoot();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/Component/EntityId.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityHelpers.h>
|
||||
#include <AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabFocusInterface.h>
|
||||
#include <Prefab/PrefabTestFixture.h>
|
||||
|
||||
namespace UnitTest
|
||||
{
|
||||
class PrefabFocusTests
|
||||
: public PrefabTestFixture
|
||||
{
|
||||
protected:
|
||||
void GenerateTestHierarchy()
|
||||
{
|
||||
/*
|
||||
* City (Prefab Container)
|
||||
* |_ City
|
||||
* |_ Street (Prefab Container)
|
||||
* |_ Car (Prefab Container)
|
||||
* | |_ Passenger
|
||||
* |_ SportsCar (Prefab Container)
|
||||
* |_ Passenger
|
||||
*/
|
||||
|
||||
m_entityMap["passenger1"] = CreateEntity("Passenger1");
|
||||
m_entityMap["passenger2"] = CreateEntity("Passenger2");
|
||||
m_entityMap["city"] = CreateEntity("City");
|
||||
|
||||
AzToolsFramework::EditorEntityContextRequestBus::Broadcast(
|
||||
&AzToolsFramework::EditorEntityContextRequests::HandleEntitiesAdded,
|
||||
AzToolsFramework::EntityList{ m_entityMap["passenger1"], m_entityMap["passenger2"], m_entityMap["city"] });
|
||||
|
||||
AZStd::unique_ptr<AzToolsFramework::Prefab::Instance> carInstance =
|
||||
m_prefabSystemComponent->CreatePrefab({ m_entityMap["passenger1"] }, {}, "test/car");
|
||||
ASSERT_TRUE(carInstance);
|
||||
m_instanceMap["car"] = carInstance.get();
|
||||
|
||||
AZStd::unique_ptr<AzToolsFramework::Prefab::Instance> sportsCarInstance =
|
||||
m_prefabSystemComponent->CreatePrefab({ m_entityMap["passenger2"] }, {}, "test/sportsCar");
|
||||
ASSERT_TRUE(sportsCarInstance);
|
||||
m_instanceMap["sportsCar"] = sportsCarInstance.get();
|
||||
|
||||
AZStd::unique_ptr<AzToolsFramework::Prefab::Instance> streetInstance =
|
||||
m_prefabSystemComponent->CreatePrefab({}, MakeInstanceList( AZStd::move(carInstance), AZStd::move(sportsCarInstance) ), "test/street");
|
||||
ASSERT_TRUE(streetInstance);
|
||||
m_instanceMap["street"] = streetInstance.get();
|
||||
|
||||
m_rootInstance =
|
||||
m_prefabSystemComponent->CreatePrefab({ m_entityMap["city"] }, MakeInstanceList(AZStd::move(streetInstance)), "test/city");
|
||||
ASSERT_TRUE(m_rootInstance);
|
||||
m_instanceMap["city"] = m_rootInstance.get();
|
||||
}
|
||||
|
||||
AZStd::unordered_map<AZStd::string, AZ::Entity*> m_entityMap;
|
||||
AZStd::unordered_map<AZStd::string, Instance*> m_instanceMap;
|
||||
|
||||
AZStd::unique_ptr<AzToolsFramework::Prefab::Instance> m_rootInstance;
|
||||
};
|
||||
|
||||
TEST_F(PrefabFocusTests, PrefabFocus_FocusOnOwningPrefab)
|
||||
{
|
||||
GenerateTestHierarchy();
|
||||
|
||||
PrefabFocusInterface* prefabFocusInterface = AZ::Interface<PrefabFocusInterface>::Get();
|
||||
EXPECT_TRUE(prefabFocusInterface != nullptr);
|
||||
|
||||
// Verify FocusOnOwningPrefab works when passing the container entity of the root prefab.
|
||||
{
|
||||
prefabFocusInterface->FocusOnOwningPrefab(m_instanceMap["city"]->GetContainerEntityId());
|
||||
EXPECT_EQ(prefabFocusInterface->GetFocusedPrefabTemplateId(), m_instanceMap["city"]->GetTemplateId());
|
||||
|
||||
auto instance = prefabFocusInterface->GetFocusedPrefabInstance();
|
||||
EXPECT_TRUE(instance.has_value());
|
||||
EXPECT_EQ(&instance->get(), m_instanceMap["city"]);
|
||||
}
|
||||
|
||||
// Verify FocusOnOwningPrefab works when passing a nested entity of the root prefab.
|
||||
{
|
||||
prefabFocusInterface->FocusOnOwningPrefab(m_entityMap["city"]->GetId());
|
||||
EXPECT_EQ(prefabFocusInterface->GetFocusedPrefabTemplateId(), m_instanceMap["city"]->GetTemplateId());
|
||||
|
||||
auto instance = prefabFocusInterface->GetFocusedPrefabInstance();
|
||||
EXPECT_TRUE(instance.has_value());
|
||||
EXPECT_EQ(&instance->get(), m_instanceMap["city"]);
|
||||
}
|
||||
|
||||
// Verify FocusOnOwningPrefab works when passing the container entity of a nested prefab.
|
||||
{
|
||||
prefabFocusInterface->FocusOnOwningPrefab(m_instanceMap["car"]->GetContainerEntityId());
|
||||
EXPECT_EQ(prefabFocusInterface->GetFocusedPrefabTemplateId(), m_instanceMap["car"]->GetTemplateId());
|
||||
|
||||
auto instance = prefabFocusInterface->GetFocusedPrefabInstance();
|
||||
EXPECT_TRUE(instance.has_value());
|
||||
EXPECT_EQ(&instance->get(), m_instanceMap["car"]);
|
||||
}
|
||||
|
||||
// Verify FocusOnOwningPrefab works when passing a nested entity of the a nested prefab.
|
||||
{
|
||||
prefabFocusInterface->FocusOnOwningPrefab(m_entityMap["passenger1"]->GetId());
|
||||
EXPECT_EQ(prefabFocusInterface->GetFocusedPrefabTemplateId(), m_instanceMap["car"]->GetTemplateId());
|
||||
|
||||
auto instance = prefabFocusInterface->GetFocusedPrefabInstance();
|
||||
EXPECT_TRUE(instance.has_value());
|
||||
EXPECT_EQ(&instance->get(), m_instanceMap["car"]);
|
||||
}
|
||||
|
||||
// Verify FocusOnOwningPrefab points to the root prefab when the focus is cleared.
|
||||
{
|
||||
AzToolsFramework::PrefabEditorEntityOwnershipInterface* prefabEditorEntityOwnershipInterface =
|
||||
AZ::Interface<AzToolsFramework::PrefabEditorEntityOwnershipInterface>::Get();
|
||||
AzToolsFramework::Prefab::InstanceOptionalReference rootPrefabInstance =
|
||||
prefabEditorEntityOwnershipInterface->GetRootPrefabInstance();
|
||||
EXPECT_TRUE(rootPrefabInstance.has_value());
|
||||
|
||||
prefabFocusInterface->FocusOnOwningPrefab(AZ::EntityId());
|
||||
EXPECT_EQ(prefabFocusInterface->GetFocusedPrefabTemplateId(), rootPrefabInstance->get().GetTemplateId());
|
||||
|
||||
auto instance = prefabFocusInterface->GetFocusedPrefabInstance();
|
||||
EXPECT_TRUE(instance.has_value());
|
||||
EXPECT_EQ(&instance->get(), &rootPrefabInstance->get());
|
||||
}
|
||||
|
||||
m_rootInstance.release();
|
||||
}
|
||||
|
||||
TEST_F(PrefabFocusTests, PrefabFocus_IsOwningPrefabBeingFocused)
|
||||
{
|
||||
GenerateTestHierarchy();
|
||||
|
||||
PrefabFocusInterface* prefabFocusInterface = AZ::Interface<PrefabFocusInterface>::Get();
|
||||
EXPECT_TRUE(prefabFocusInterface != nullptr);
|
||||
|
||||
// Verify IsOwningPrefabBeingFocused returns true for all entities in a focused prefab (container/nested)
|
||||
{
|
||||
prefabFocusInterface->FocusOnOwningPrefab(m_instanceMap["city"]->GetContainerEntityId());
|
||||
|
||||
EXPECT_TRUE(prefabFocusInterface->IsOwningPrefabBeingFocused(m_instanceMap["city"]->GetContainerEntityId()));
|
||||
EXPECT_TRUE(prefabFocusInterface->IsOwningPrefabBeingFocused(m_entityMap["city"]->GetId()));
|
||||
}
|
||||
|
||||
// Verify IsOwningPrefabBeingFocused returns false for all entities not in a focused prefab (ancestors/descendants)
|
||||
{
|
||||
prefabFocusInterface->FocusOnOwningPrefab(m_instanceMap["street"]->GetContainerEntityId());
|
||||
|
||||
EXPECT_TRUE(prefabFocusInterface->IsOwningPrefabBeingFocused(m_instanceMap["street"]->GetContainerEntityId()));
|
||||
EXPECT_FALSE(prefabFocusInterface->IsOwningPrefabBeingFocused(m_instanceMap["city"]->GetContainerEntityId()));
|
||||
EXPECT_FALSE(prefabFocusInterface->IsOwningPrefabBeingFocused(m_entityMap["city"]->GetId()));
|
||||
EXPECT_FALSE(prefabFocusInterface->IsOwningPrefabBeingFocused(m_instanceMap["car"]->GetContainerEntityId()));
|
||||
EXPECT_FALSE(prefabFocusInterface->IsOwningPrefabBeingFocused(m_entityMap["passenger1"]->GetId()));
|
||||
}
|
||||
|
||||
// Verify IsOwningPrefabBeingFocused returns false for all entities not in a focused prefab (siblings)
|
||||
{
|
||||
prefabFocusInterface->FocusOnOwningPrefab(m_instanceMap["sportsCar"]->GetContainerEntityId());
|
||||
|
||||
EXPECT_TRUE(prefabFocusInterface->IsOwningPrefabBeingFocused(m_instanceMap["sportsCar"]->GetContainerEntityId()));
|
||||
EXPECT_TRUE(prefabFocusInterface->IsOwningPrefabBeingFocused(m_entityMap["passenger2"]->GetId()));
|
||||
EXPECT_FALSE(prefabFocusInterface->IsOwningPrefabBeingFocused(m_instanceMap["car"]->GetContainerEntityId()));
|
||||
EXPECT_FALSE(prefabFocusInterface->IsOwningPrefabBeingFocused(m_entityMap["passenger1"]->GetId()));
|
||||
}
|
||||
|
||||
m_rootInstance.release();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -34,6 +34,7 @@ set(FILES
|
||||
EntityTestbed.h
|
||||
FileFunc.cpp
|
||||
FingerprintingTests.cpp
|
||||
FocusMode/EditorFocusModeTests.cpp
|
||||
GenericComponentWrapperTest.cpp
|
||||
InstanceDataHierarchy.cpp
|
||||
IntegerPrimtitiveTestConfig.h
|
||||
@@ -50,6 +51,7 @@ set(FILES
|
||||
Prefab/Benchmark/PrefabLoadBenchmarks.cpp
|
||||
Prefab/Benchmark/PrefabUpdateInstancesBenchmarks.cpp
|
||||
Prefab/Benchmark/SpawnableCreateBenchmarks.cpp
|
||||
Prefab/PrefabFocus/PrefabFocusTests.cpp
|
||||
Prefab/MockPrefabFileIOActionValidator.cpp
|
||||
Prefab/MockPrefabFileIOActionValidator.h
|
||||
Prefab/PrefabDuplicateTests.cpp
|
||||
|
||||
@@ -122,6 +122,9 @@ class BatchAnalytics:
|
||||
)
|
||||
]
|
||||
|
||||
for named_query in self._named_queries:
|
||||
named_query.node.add_dependency(self._athena_work_group)
|
||||
|
||||
@property
|
||||
def athena_work_group_name(self) -> athena.CfnWorkGroup.name:
|
||||
return self._athena_work_group.name
|
||||
|
||||
@@ -85,7 +85,6 @@ namespace AZ
|
||||
{
|
||||
const auto jobLambda = [&]() -> void
|
||||
{
|
||||
AZ_PROFILE_SCOPE(AzRender, "MeshFP::Simulate() Lambda");
|
||||
for (auto meshDataIter = iteratorRange.first; meshDataIter != iteratorRange.second; ++meshDataIter)
|
||||
{
|
||||
if (!meshDataIter->m_model)
|
||||
|
||||
@@ -28,25 +28,19 @@ namespace AZ
|
||||
size_t m_accumulatedInBytes = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Tracks memory usage for a specific heap in the system. The data is expected to adhere to the following constraints:
|
||||
*
|
||||
* 1) Reserved <= Budget (unless the budget is 0).
|
||||
* 2) Resident <= Reserved.
|
||||
*/
|
||||
//! Tracks memory usage for a specific heap in the system. The data is expected to adhere to the following constraints:
|
||||
//! 1) Reserved <= Budget (unless the budget is 0).
|
||||
//! 2) Resident <= Reserved.
|
||||
struct HeapMemoryUsage
|
||||
{
|
||||
HeapMemoryUsage() = default;
|
||||
HeapMemoryUsage(const HeapMemoryUsage&);
|
||||
HeapMemoryUsage& operator=(const HeapMemoryUsage&);
|
||||
|
||||
/**
|
||||
* This helper reserves memory in a thread-safe fashion. If the result exceeds the budget, the reservation is safely
|
||||
* reverted and false is returned. otherwise, true is returned. Only m_reservedInBytes is affected.
|
||||
*
|
||||
* @param sizeInBytes The amount of bytes to reserve.
|
||||
* @return Whether the reservation was successful.
|
||||
*/
|
||||
//! This helper reserves memory in a thread-safe fashion. If the result exceeds the budget, the reservation is safely
|
||||
//! reverted and false is returned. otherwise, true is returned. Only m_reservedInBytes is affected.
|
||||
//! @param sizeInBytes The amount of bytes to reserve.
|
||||
//! @return Whether the reservation was successful.
|
||||
bool TryReserveMemory(size_t sizeInBytes)
|
||||
{
|
||||
const size_t reservationInBytes = (m_reservedInBytes += sizeInBytes);
|
||||
@@ -60,45 +54,41 @@ namespace AZ
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to validate sizes
|
||||
*/
|
||||
//! Helper function to validate sizes
|
||||
void Validate()
|
||||
{
|
||||
if (Validation::IsEnabled())
|
||||
{
|
||||
AZ_Assert(m_budgetInBytes >= m_reservedInBytes, "Reserved memory is larger than memory budget");
|
||||
AZ_Assert(m_reservedInBytes >= m_residentInBytes, "Resident memory is larger than reserved memory");
|
||||
AZ_Assert(
|
||||
m_budgetInBytes >= m_reservedInBytes,
|
||||
"Reserved memory is larger than memory budget. Memory budget %zu Reserved %zu", m_budgetInBytes, m_reservedInBytes.load());
|
||||
AZ_Assert(
|
||||
m_reservedInBytes >= m_residentInBytes,
|
||||
"Resident memory is larger than reserved memory. Reserved Memory %zu Resident memory %zu", m_reservedInBytes.load(),
|
||||
m_residentInBytes.load());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The budget for the heap in bytes. A non-zero budget means the pool will reject reservation requests
|
||||
* once the budget is exceeded. A zero budget effectively disables this check. On certain platforms,
|
||||
* it may be unnecessary to budget certain heaps. Other platforms may require a non-zero budget for certain
|
||||
* heaps.
|
||||
*/
|
||||
// The budget for the heap in bytes. A non-zero budget means the pool will reject reservation requests
|
||||
// once the budget is exceeded. A zero budget effectively disables this check. On certain platforms,
|
||||
// it may be unnecessary to budget certain heaps. Other platforms may require a non-zero budget for certain
|
||||
// heaps.
|
||||
size_t m_budgetInBytes = 0;
|
||||
|
||||
/**
|
||||
* Number of bytes reserved on the heap for allocations. This value represents the allocation capacity for
|
||||
* the platform. It is validated against the budget and may not exceed it.
|
||||
*/
|
||||
// Number of bytes reserved on the heap for allocations. This value represents the allocation capacity for
|
||||
// the platform. It is validated against the budget and may not exceed it.
|
||||
AZStd::atomic_size_t m_reservedInBytes{ 0 };
|
||||
|
||||
/**
|
||||
* Number of bytes physically allocated on the heap. This may not exceed the reservation. Certain platforms
|
||||
* may choose to transfer memory down the heap level hierarchy in response to memory trim events from the driver.
|
||||
*/
|
||||
// Number of bytes physically allocated on the heap. This may not exceed the reservation. Certain platforms
|
||||
// may choose to transfer memory down the heap level hierarchy in response to memory trim events from the driver.
|
||||
AZStd::atomic_size_t m_residentInBytes{ 0 };
|
||||
};
|
||||
|
||||
/**
|
||||
* Describes memory usage metrics of a resource pool. Resource pools *can* associate with a single
|
||||
* device memory heap (i.e. a single GPU) and the host memory heap. Certain pools on specific platforms
|
||||
* may not require one or the other. In this case, the memory usage / budget will report empty values for
|
||||
* that heap type.
|
||||
*/
|
||||
//!
|
||||
//! Describes memory usage metrics of a resource pool. Resource pools *can* associate with a single
|
||||
//! device memory heap (i.e. a single GPU) and the host memory heap. Certain pools on specific platforms
|
||||
//! may not require one or the other. In this case, the memory usage / budget will report empty values for
|
||||
//! that heap type.
|
||||
struct PoolMemoryUsage
|
||||
{
|
||||
PoolMemoryUsage() = default;
|
||||
|
||||
@@ -13,13 +13,12 @@ namespace AZ
|
||||
{
|
||||
namespace RHI
|
||||
{
|
||||
/**
|
||||
* A virtual address which may be relative to a base resource. This means
|
||||
* 0 might be a valid address (dependent on the Allocator::Descriptor::m_addressBase value).
|
||||
* To account for this, VirtualAddress::Null is used instead. Check validity of the address
|
||||
* using IsValid or IsNull instead of checking for 0. VirtualAddress is initialized
|
||||
* to Null, so returning the default constructor is sufficient to represent an invalid address.
|
||||
*/
|
||||
|
||||
//! A virtual address which may be relative to a base resource. This means
|
||||
//! 0 might be a valid address (dependent on the Allocator::Descriptor::m_addressBase value).
|
||||
//! To account for this, VirtualAddress::Null is used instead. Check validity of the address
|
||||
//! using IsValid or IsNull instead of checking for 0. VirtualAddress is initialized
|
||||
//! to Null, so returning the default constructor is sufficient to represent an invalid address.
|
||||
class VirtualAddress
|
||||
{
|
||||
static const VirtualAddress Null;
|
||||
@@ -29,13 +28,13 @@ namespace AZ
|
||||
|
||||
static VirtualAddress CreateNull();
|
||||
|
||||
/// Creates a valid address with a zero offset.
|
||||
//! Creates a valid address with a zero offset.
|
||||
static VirtualAddress CreateZero();
|
||||
|
||||
/// Creates an address from a pointer.
|
||||
//! Creates an address from a pointer.
|
||||
static VirtualAddress CreateFromPointer(void* ptr);
|
||||
|
||||
/// Creates an address from an offset from a base pointer.
|
||||
//! Creates an address from an offset from a base pointer.
|
||||
static VirtualAddress CreateFromOffset(uint64_t offset);
|
||||
|
||||
inline bool IsValid() const
|
||||
@@ -51,15 +50,13 @@ namespace AZ
|
||||
uintptr_t m_ptr;
|
||||
};
|
||||
|
||||
/**
|
||||
* An allocator interface used for external GPU allocations. The allocator
|
||||
* does not manage the host memory. Instead, the user specifies a base address
|
||||
* (which may be 0, in order to allocate offsets from a base resource). The allocator
|
||||
* interface also provides an API for garbage collection. If used to manage GPU resources,
|
||||
* these are often deferred-released after N frames. The user may provide a garbage collection
|
||||
* latency, which controls the number of GarbageCollect calls that must occur before an allocation
|
||||
* is actually reclaimed. The intended use case is to garbage collect at the end of each frame.
|
||||
*/
|
||||
//! An allocator interface used for external GPU allocations. The allocator
|
||||
//! does not manage the host memory. Instead, the user specifies a base address
|
||||
//! (which may be 0, in order to allocate offsets from a base resource). The allocator
|
||||
//! interface also provides an API for garbage collection. If used to manage GPU resources,
|
||||
//! these are often deferred-released after N frames. The user may provide a garbage collection
|
||||
//! latency, which controls the number of GarbageCollect calls that must occur before an allocation
|
||||
//! is actually reclaimed. The intended use case is to garbage collect at the end of each frame.
|
||||
class Allocator
|
||||
{
|
||||
public:
|
||||
@@ -86,44 +83,42 @@ namespace AZ
|
||||
|
||||
virtual void Shutdown() = 0;
|
||||
|
||||
/**
|
||||
* Allocates a virtual address relative to the base address provided at initialization time.
|
||||
* @param byteCount The number of bytes to allocate.
|
||||
* @param byteAlignement The alignment used to align the allocation.
|
||||
*/
|
||||
//! Allocates a virtual address relative to the base address provided at initialization time.
|
||||
//! @param byteCount The number of bytes to allocate.
|
||||
//! @param byteAlignement The alignment used to align the allocation.
|
||||
virtual VirtualAddress Allocate(size_t byteCount, size_t byteAlignment) = 0;
|
||||
|
||||
/**
|
||||
* Deallocates an allocation. The memory is not reclaimed until garbage collect is called.
|
||||
* Depending on the garbage collection latency, it may take several garbage collection cycles
|
||||
* before the memory is reclaimed.
|
||||
*/
|
||||
//! Deallocates an allocation. The memory is not reclaimed until garbage collect is called.
|
||||
//! Depending on the garbage collection latency, it may take several garbage collection cycles
|
||||
//! before the memory is reclaimed.
|
||||
virtual void DeAllocate(VirtualAddress offset) = 0;
|
||||
|
||||
/// Allocations are deferred-released until a specific number of GC cycles have occurred. This
|
||||
/// is useful for allocations actively being consumed by the GPU.
|
||||
//! Allocations are deferred-released until a specific number of GC cycles have occurred. This
|
||||
//! is useful for allocations actively being consumed by the GPU.
|
||||
virtual void GarbageCollect() = 0;
|
||||
|
||||
/// Forces garbage collection of all allocations, regardless of the GC latency.
|
||||
//! Forces garbage collection of all allocations, regardless of the GC latency.
|
||||
virtual void GarbageCollectForce() = 0;
|
||||
|
||||
/**
|
||||
* Returns the number of allocations active for this allocator. This includes
|
||||
* allocations that are pending garbage collection.
|
||||
*/
|
||||
//! Returns the number of allocations active for this allocator. This includes
|
||||
//! allocations that are pending garbage collection.
|
||||
virtual size_t GetAllocationCount() const { return 0; }
|
||||
|
||||
/**
|
||||
* Returns the number of bytes used by the allocator. This includes
|
||||
* allocations that are pending garbage collection.
|
||||
*/
|
||||
//! Returns the number of bytes used by the allocator. This includes
|
||||
//! allocations that are pending garbage collection.
|
||||
virtual size_t GetAllocatedByteCount() const { return 0; }
|
||||
|
||||
/// Returns the descriptor used to initialize the allocator.
|
||||
//! Returns the descriptor used to initialize the allocator.
|
||||
virtual const Descriptor& GetDescriptor() const = 0;
|
||||
|
||||
/// Helper for converting agnostic VirtualAddress type to pointer type. Will convert
|
||||
/// VirtualAddress::Null to nullptr.
|
||||
//! Clone the current allocator to the new allocator passed in
|
||||
virtual void Clone([[maybe_unused]] RHI::Allocator* newAllocator)
|
||||
{
|
||||
AZ_Assert(false, "Not Implemented");
|
||||
};
|
||||
|
||||
//! Helper for converting agnostic VirtualAddress type to pointer type. Will convert
|
||||
//! VirtualAddress::Null to nullptr.
|
||||
template <typename T>
|
||||
T* AllocateAs(size_t byteCount, size_t byteAlignment)
|
||||
{
|
||||
|
||||
@@ -139,6 +139,12 @@ namespace AZ
|
||||
//! Notifies after all objects currently in the platform release queue are released
|
||||
virtual void ObjectCollectionNotify(RHI::ObjectCollectorNotifyFunction notifyFunction) = 0;
|
||||
|
||||
//! Allows the back-ends to compact SRG related memory if applicable
|
||||
virtual RHI::ResultCode CompactSRGMemory()
|
||||
{
|
||||
return RHI::ResultCode::Success;
|
||||
};
|
||||
|
||||
protected:
|
||||
DeviceFeatures m_features;
|
||||
DeviceLimits m_limits;
|
||||
|
||||
@@ -112,6 +112,9 @@ namespace AZ
|
||||
//! Returns true if Pix dll is loaded
|
||||
static bool IsPixModuleLoaded();
|
||||
|
||||
//! Returns true if Warp is enabled
|
||||
static bool UsingWarpDevice();
|
||||
|
||||
//! Returns the name of the Factory.
|
||||
virtual Name GetName() = 0;
|
||||
|
||||
|
||||
@@ -55,6 +55,7 @@ namespace AZ
|
||||
size_t GetAllocationCount() const override;
|
||||
size_t GetAllocatedByteCount() const override;
|
||||
const Descriptor& GetDescriptor() const override;
|
||||
void Clone(RHI::Allocator* newAllocator) override;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private:
|
||||
|
||||
@@ -155,11 +155,6 @@ namespace AZ
|
||||
{
|
||||
arguments += " -Zpr";
|
||||
}
|
||||
if (m_dxcGenerateDebugInfo)
|
||||
{
|
||||
arguments += " -Zi"; // Generate debug information
|
||||
arguments += " -Zss"; // Compute Shader Hash considering source information
|
||||
}
|
||||
// strip spaces at both sides
|
||||
AZStd::string dxcAdditionalFreeArguments = m_dxcAdditionalFreeArguments;
|
||||
AzFramework::StringFunc::TrimWhiteSpace(dxcAdditionalFreeArguments, true, true);
|
||||
|
||||
@@ -8,12 +8,12 @@
|
||||
|
||||
#include <Atom/RHI/Factory.h>
|
||||
#include <Atom/RHI/ResourceInvalidateBus.h>
|
||||
#include <Atom/RHI/RHIUtils.h>
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
#include <AzCore/Component/TickBus.h>
|
||||
|
||||
#if defined(USE_RENDERDOC) || defined(USE_PIX)
|
||||
#include <AzCore/Module/DynamicModuleHandle.h>
|
||||
#include <Atom/RHI/RHIUtils.h>
|
||||
#include <Atom_RHI_Traits_Platform.h>
|
||||
#endif
|
||||
|
||||
@@ -28,6 +28,8 @@ static AZStd::unique_ptr<AZ::DynamicModuleHandle> s_pixModule;
|
||||
static bool s_isPixGpuCaptureDllLoaded = false;
|
||||
#endif
|
||||
|
||||
static bool s_usingWarpDevice = false;
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace RHI
|
||||
@@ -55,6 +57,8 @@ namespace AZ
|
||||
|
||||
Factory::Factory()
|
||||
{
|
||||
AZStd::string preferredUserAdapterName = RHI::GetCommandLineValue("forceAdapter");
|
||||
s_usingWarpDevice = preferredUserAdapterName == "Microsoft Basic Render Driver";
|
||||
#if defined(USE_RENDERDOC)
|
||||
// If RenderDoc is requested, we need to load the library as early as possible (before device queries/factories are made)
|
||||
bool enableRenderDoc = RHI::QueryCommandLineOption("enableRenderDoc");
|
||||
@@ -197,5 +201,10 @@ namespace AZ
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Factory::UsingWarpDevice()
|
||||
{
|
||||
return s_usingWarpDevice;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -314,6 +314,11 @@ namespace AZ
|
||||
|
||||
resourcePoolDatabase.ForEachShaderResourceGroupPool<decltype(compileAllLambda)>(compileAllLambda);
|
||||
}
|
||||
|
||||
//It is possible for certain back ends to run out of SRG memory (due to fragmentation) in which case
|
||||
//we try to compact and re-compile SRGs.
|
||||
RHI::ResultCode resultCode = m_device->CompactSRGMemory();
|
||||
AZ_Assert(resultCode == RHI::ResultCode::Success, "SRG compaction failed and this can lead to a gpu crash.");
|
||||
}
|
||||
|
||||
void FrameScheduler::BuildRayTracingShaderTables()
|
||||
|
||||
@@ -344,5 +344,17 @@ namespace AZ
|
||||
handle = node.m_nextFree;
|
||||
}
|
||||
}
|
||||
|
||||
void FreeListAllocator::Clone(RHI::Allocator* newAllocator)
|
||||
{
|
||||
FreeListAllocator* newFreeListAllocator = static_cast<FreeListAllocator*>(newAllocator);
|
||||
newFreeListAllocator->m_headHandle = m_headHandle;
|
||||
newFreeListAllocator->m_nodeFreeList = m_nodeFreeList;
|
||||
newFreeListAllocator->m_nodes = m_nodes;
|
||||
newFreeListAllocator->m_allocations = m_allocations;
|
||||
newFreeListAllocator->m_garbage = m_garbage;
|
||||
newFreeListAllocator->m_garbageCollectCycle = m_garbageCollectCycle;
|
||||
newFreeListAllocator->m_byteCountTotal = m_byteCountTotal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,6 +64,12 @@ namespace AZ
|
||||
//! int array: Max count for descriptors
|
||||
AZStd::unordered_map<AZStd::string, AZStd::array<uint32_t, NumHeapFlags>> m_descriptorHeapLimits;
|
||||
|
||||
// Number of max static handles for shader visible srv/uav/cbv views
|
||||
uint32_t m_numShaderVisibleCbvSrvUavStaticHandles = 2000;
|
||||
|
||||
//Bool to indicate allowing compaction of shader visible srv/uav/cbv heap in case of fragmentation
|
||||
bool m_allowDescriptorHeapCompaction = false;
|
||||
|
||||
FrameGraphExecuterData m_frameGraphExecuterData;
|
||||
|
||||
void LoadPlatformLimitsDescriptor(const char* rhiName) override;
|
||||
|
||||
@@ -255,6 +255,11 @@ namespace AZ
|
||||
|
||||
// Compilation parameters
|
||||
AZStd::string params = shaderCompilerArguments.MakeAdditionalDxcCommandLineString();
|
||||
if (BuildHasDebugInfo(shaderCompilerArguments))
|
||||
{
|
||||
params += " -Zi"; // Generate debug information
|
||||
params += " -Zss"; // Compute Shader Hash considering source information
|
||||
}
|
||||
|
||||
// Enable half precision types when shader model >= 6.2
|
||||
int shaderModelMajor = 0;
|
||||
@@ -281,12 +286,11 @@ namespace AZ
|
||||
AZStd::string symbolDatabaseFileCliArgument{" "}; // when not debug: still insert a space between 5.dxil and 7.hlsl-in
|
||||
if (BuildHasDebugInfo(shaderCompilerArguments))
|
||||
{
|
||||
// prepare .ldd filename:
|
||||
// prepare .pdb filename:
|
||||
AZStd::string md5hex = RHI::ByteToHexString(md5);
|
||||
AZStd::string symbolDatabaseFilePath = dxcInputFile.c_str(); // mutate from source
|
||||
AZStd::string lldFileName = md5hex // lld is like pdb but it's the default symbol database extension in dxc
|
||||
+ "-" + profileIt->second; // concatenate the shader profile to disambiguate vs/ps...
|
||||
AzFramework::StringFunc::Path::ReplaceFullName(symbolDatabaseFilePath, lldFileName.c_str(), "lld");
|
||||
AZStd::string pdbFileName = md5hex + "-" + profileIt->second; // concatenate the shader profile to disambiguate vs/ps...
|
||||
AzFramework::StringFunc::Path::ReplaceFullName(symbolDatabaseFilePath, pdbFileName.c_str(), "pdb");
|
||||
// it is possible that another activated platform/profile, already exported that file. (since it's hashed on the source file)
|
||||
// dxc returns an error in such case. we get less surprising effets by just not mentionning an -Fd argument
|
||||
if (AZ::IO::SystemFile::Exists(symbolDatabaseFilePath.c_str()))
|
||||
|
||||
@@ -19,8 +19,10 @@ namespace AZ
|
||||
if (SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<PlatformLimitsDescriptor, Base>()
|
||||
->Version(0)
|
||||
->Version(1)
|
||||
->Field("DescriptorHeapLimits", &PlatformLimitsDescriptor::m_descriptorHeapLimits)
|
||||
->Field("NumShaderVisibleCbvSrvUavStaticHandles", &PlatformLimitsDescriptor::m_numShaderVisibleCbvSrvUavStaticHandles)
|
||||
->Field("AllowDescriptorHeapCompaction", &PlatformLimitsDescriptor::m_allowDescriptorHeapCompaction)
|
||||
->Field("FrameGraphExecuterData", &PlatformLimitsDescriptor::m_frameGraphExecuterData)
|
||||
;
|
||||
}
|
||||
@@ -54,7 +56,7 @@ namespace AZ
|
||||
// Map default value must be initialized after attempting to serialize (and result in failure).
|
||||
// Otherwise, serialization won't overwrite the default values.
|
||||
m_descriptorHeapLimits = AZStd::unordered_map<AZStd::string, AZStd::array<uint32_t, NumHeapFlags>>({
|
||||
{ AZStd::string("DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV"), { 1000000, 1000000 } },
|
||||
{ AZStd::string("DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV"), { 100000, 1000000 } },
|
||||
{ AZStd::string("DESCRIPTOR_HEAP_TYPE_SAMPLER"), { 2048, 2048 } },
|
||||
{ AZStd::string("DESCRIPTOR_HEAP_TYPE_RTV"), { 2048, 0 } },
|
||||
{ AZStd::string("DESCRIPTOR_HEAP_TYPE_DSV"), { 2048, 0 } }
|
||||
|
||||
@@ -438,7 +438,7 @@ namespace AZ
|
||||
switch (pipelineType)
|
||||
{
|
||||
case RHI::PipelineStateType::Draw:
|
||||
if (binding.m_resourceTable.IsValid())
|
||||
if (binding.m_resourceTable.IsValid() && compiledData.m_gpuViewsDescriptorHandle.ptr)
|
||||
{
|
||||
GetCommandList()->SetGraphicsRootDescriptorTable(binding.m_resourceTable.GetIndex(), compiledData.m_gpuViewsDescriptorHandle);
|
||||
}
|
||||
@@ -448,14 +448,15 @@ namespace AZ
|
||||
GetCommandList()->SetGraphicsRootConstantBufferView(binding.m_constantBuffer.GetIndex(), compiledData.m_gpuConstantAddress);
|
||||
}
|
||||
|
||||
if (binding.m_samplerTable.IsValid())
|
||||
if (binding.m_samplerTable.IsValid() && compiledData.m_gpuSamplersDescriptorHandle.ptr)
|
||||
{
|
||||
GetCommandList()->SetGraphicsRootDescriptorTable(binding.m_samplerTable.GetIndex(), compiledData.m_gpuSamplersDescriptorHandle);
|
||||
}
|
||||
|
||||
for (uint32_t unboundedArrayIndex = 0; unboundedArrayIndex < ShaderResourceGroupCompiledData::MaxUnboundedArrays; ++unboundedArrayIndex)
|
||||
{
|
||||
if (binding.m_unboundedArrayResourceTables[unboundedArrayIndex].IsValid())
|
||||
if (binding.m_unboundedArrayResourceTables[unboundedArrayIndex].IsValid() &&
|
||||
compiledData.m_gpuUnboundedArraysDescriptorHandles[unboundedArrayIndex].ptr)
|
||||
{
|
||||
GetCommandList()->SetGraphicsRootDescriptorTable(
|
||||
binding.m_unboundedArrayResourceTables[unboundedArrayIndex].GetIndex(),
|
||||
@@ -465,7 +466,7 @@ namespace AZ
|
||||
break;
|
||||
|
||||
case RHI::PipelineStateType::Dispatch:
|
||||
if (binding.m_resourceTable.IsValid())
|
||||
if (binding.m_resourceTable.IsValid() && compiledData.m_gpuViewsDescriptorHandle.ptr)
|
||||
{
|
||||
GetCommandList()->SetComputeRootDescriptorTable(binding.m_resourceTable.GetIndex(), compiledData.m_gpuViewsDescriptorHandle);
|
||||
}
|
||||
@@ -475,14 +476,15 @@ namespace AZ
|
||||
GetCommandList()->SetComputeRootConstantBufferView(binding.m_constantBuffer.GetIndex(), compiledData.m_gpuConstantAddress);
|
||||
}
|
||||
|
||||
if (binding.m_samplerTable.IsValid())
|
||||
if (binding.m_samplerTable.IsValid() && compiledData.m_gpuSamplersDescriptorHandle.ptr)
|
||||
{
|
||||
GetCommandList()->SetComputeRootDescriptorTable(binding.m_samplerTable.GetIndex(), compiledData.m_gpuSamplersDescriptorHandle);
|
||||
}
|
||||
|
||||
for (uint32_t unboundedArrayIndex = 0; unboundedArrayIndex < ShaderResourceGroupCompiledData::MaxUnboundedArrays; ++unboundedArrayIndex)
|
||||
{
|
||||
if (binding.m_unboundedArrayResourceTables[unboundedArrayIndex].IsValid())
|
||||
if (binding.m_unboundedArrayResourceTables[unboundedArrayIndex].IsValid() &&
|
||||
compiledData.m_gpuUnboundedArraysDescriptorHandles[unboundedArrayIndex].ptr)
|
||||
{
|
||||
GetCommandList()->SetComputeRootDescriptorTable(
|
||||
binding.m_unboundedArrayResourceTables[unboundedArrayIndex].GetIndex(),
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace AZ
|
||||
|
||||
void CommandListBase::SetNameInternal(const AZStd::string_view& name)
|
||||
{
|
||||
AZStd::wstring wname;
|
||||
AZStd::fixed_wstring<256> wname;
|
||||
AZStd::to_wstring(wname, name.data());
|
||||
GetCommandList()->SetName(wname.data());
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace AZ
|
||||
{
|
||||
Device& device = static_cast<Device&>(deviceBase);
|
||||
m_currentFrameIndex = 0;
|
||||
m_frameFences.resize(RHI::Limits::Device::FrameCountMax - 1);
|
||||
m_frameFences.resize(RHI::Limits::Device::FrameCountMax);
|
||||
for (FenceSet& fences : m_frameFences)
|
||||
{
|
||||
fences.Init(device.GetDevice(), RHI::FenceState::Signaled);
|
||||
|
||||
@@ -10,7 +10,9 @@
|
||||
#include <RHI/Conversions.h>
|
||||
#include <RHI/Device.h>
|
||||
#include <RHI/Image.h>
|
||||
#include <RHI/ShaderResourceGroupPool.h>
|
||||
#include <Atom/RHI.Reflect/DX12/PlatformLimitsDescriptor.h>
|
||||
#include <Atom/RHI/ShaderResourceGroupPool.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -40,7 +42,7 @@ namespace AZ
|
||||
|
||||
for (D3D12_SRV_DIMENSION dimension : validSRVDimensions)
|
||||
{
|
||||
DescriptorHandle srvDescriptorHandle = Allocate(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE, 1).GetOffset();
|
||||
DescriptorHandle srvDescriptorHandle = AllocateHandle(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE, 1);
|
||||
|
||||
D3D12_SHADER_RESOURCE_VIEW_DESC desc = {};
|
||||
desc.Format = DXGI_FORMAT_R32_UINT;
|
||||
@@ -62,7 +64,7 @@ namespace AZ
|
||||
|
||||
for (D3D12_UAV_DIMENSION dimension : UAVDimensions)
|
||||
{
|
||||
DescriptorHandle uavDescriptorHandle = Allocate(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE, 1).GetOffset();
|
||||
DescriptorHandle uavDescriptorHandle = AllocateHandle(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE, 1);
|
||||
|
||||
D3D12_UNORDERED_ACCESS_VIEW_DESC desc = {};
|
||||
desc.Format = DXGI_FORMAT_R32_UINT;
|
||||
@@ -75,14 +77,14 @@ namespace AZ
|
||||
void DescriptorContext::CreateNullDescriptorsCBV()
|
||||
{
|
||||
D3D12_CONSTANT_BUFFER_VIEW_DESC constantBufferDesc = {};
|
||||
DescriptorHandle cbvDescriptorHandle = Allocate(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE, 1).GetOffset();
|
||||
DescriptorHandle cbvDescriptorHandle = AllocateHandle(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE, 1);
|
||||
m_device->CreateConstantBufferView(&constantBufferDesc, GetCpuPlatformHandle(cbvDescriptorHandle));
|
||||
m_nullDescriptorCBV = cbvDescriptorHandle;
|
||||
}
|
||||
|
||||
void DescriptorContext::CreateNullDescriptorsSampler()
|
||||
{
|
||||
m_nullSamplerDescriptor = Allocate(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, D3D12_DESCRIPTOR_HEAP_FLAG_NONE, 1).GetOffset();
|
||||
m_nullSamplerDescriptor = AllocateHandle(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, D3D12_DESCRIPTOR_HEAP_FLAG_NONE, 1);
|
||||
D3D12_SAMPLER_DESC samplerDesc = {};
|
||||
samplerDesc.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR;
|
||||
samplerDesc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
||||
@@ -102,7 +104,7 @@ namespace AZ
|
||||
|
||||
AZ_Assert(platformLimitsDescriptor.get(), "Platform limits information is missing");
|
||||
m_platformLimitsDescriptor = platformLimitsDescriptor;
|
||||
|
||||
m_allowDescriptorHeapCompaction = m_platformLimitsDescriptor->m_allowDescriptorHeapCompaction;
|
||||
for (const auto& itr : platformLimitsDescriptor->m_descriptorHeapLimits)
|
||||
{
|
||||
for (uint32_t shaderVisibleIdx = 0; shaderVisibleIdx < PlatformLimitsDescriptor::NumHeapFlags; ++shaderVisibleIdx)
|
||||
@@ -114,11 +116,33 @@ namespace AZ
|
||||
|
||||
if (descriptorCountMax)
|
||||
{
|
||||
GetPool(static_cast<uint32_t>(heapTypeIdx.value()), shaderVisibleIdx).Init(m_device.get(), type, flags, descriptorCountMax);
|
||||
if (m_allowDescriptorHeapCompaction && IsShaderVisibleCbvSrvUavHeap(type, flags))
|
||||
{
|
||||
//Init the two heaps to help support compaction after fragmentation
|
||||
m_shaderVisibleCbvSrvUavPools[0].Init(
|
||||
m_device.get(), D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE,
|
||||
descriptorCountMax, platformLimitsDescriptor->m_numShaderVisibleCbvSrvUavStaticHandles);
|
||||
|
||||
m_shaderVisibleCbvSrvUavPools[1].Init(
|
||||
m_device.get(), D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE,
|
||||
descriptorCountMax, platformLimitsDescriptor->m_numShaderVisibleCbvSrvUavStaticHandles);
|
||||
}
|
||||
else
|
||||
{
|
||||
GetPool(static_cast<uint32_t>(heapTypeIdx.value()), shaderVisibleIdx).Init(m_device.get(), type, flags, descriptorCountMax, descriptorCountMax);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (m_allowDescriptorHeapCompaction)
|
||||
{
|
||||
m_backupStaticHandles.Init(
|
||||
m_device.get(), D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE,
|
||||
platformLimitsDescriptor->m_numShaderVisibleCbvSrvUavStaticHandles,
|
||||
platformLimitsDescriptor->m_numShaderVisibleCbvSrvUavStaticHandles);
|
||||
}
|
||||
|
||||
CreateNullDescriptors();
|
||||
}
|
||||
|
||||
@@ -129,7 +153,7 @@ namespace AZ
|
||||
{
|
||||
if (constantBufferView.IsNull())
|
||||
{
|
||||
constantBufferView = Allocate(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE, 1).GetOffset();
|
||||
constantBufferView = AllocateHandle(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE, 1);
|
||||
}
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE descriptorHandle = GetCpuPlatformHandle(constantBufferView);
|
||||
|
||||
@@ -145,7 +169,7 @@ namespace AZ
|
||||
{
|
||||
if (shaderResourceView.IsNull())
|
||||
{
|
||||
shaderResourceView = Allocate(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE, 1).GetOffset();
|
||||
shaderResourceView = AllocateHandle(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE, 1);
|
||||
}
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE descriptorHandle = GetCpuPlatformHandle(shaderResourceView);
|
||||
|
||||
@@ -165,7 +189,7 @@ namespace AZ
|
||||
{
|
||||
if (unorderedAccessView.IsNull())
|
||||
{
|
||||
unorderedAccessView = Allocate(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE, 1).GetOffset();
|
||||
unorderedAccessView = AllocateHandle(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE, 1);
|
||||
}
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE unorderedAccessDescriptor = GetCpuPlatformHandle(unorderedAccessView);
|
||||
|
||||
@@ -176,7 +200,24 @@ namespace AZ
|
||||
// Copy the UAV descriptor into the GPU-visible version for clearing.
|
||||
if (unorderedAccessViewClear.IsNull())
|
||||
{
|
||||
unorderedAccessViewClear = Allocate(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, 1).GetOffset();
|
||||
unorderedAccessViewClear = AllocateHandle(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, 1);
|
||||
|
||||
if (unorderedAccessViewClear.IsNull())
|
||||
{
|
||||
AZ_Assert(
|
||||
false,
|
||||
"Descriptor heap ran out of memory for static handles. Please consider increasing the value of NumShaderVisibleCbvSrvUavStaticHandles"
|
||||
"within platformlimits.azasset file for dx12.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_allowDescriptorHeapCompaction)
|
||||
{
|
||||
//We make a copy of static handles in case we need to compact and recreate the shader visible heap
|
||||
m_device->CopyDescriptorsSimple(
|
||||
1, m_backupStaticHandles.GetCpuPlatformHandle(unorderedAccessViewClear), unorderedAccessDescriptor,
|
||||
unorderedAccessViewClear.m_type);
|
||||
}
|
||||
}
|
||||
CopyDescriptor(unorderedAccessViewClear, unorderedAccessView);
|
||||
}
|
||||
@@ -188,7 +229,7 @@ namespace AZ
|
||||
{
|
||||
if (shaderResourceView.IsNull())
|
||||
{
|
||||
shaderResourceView = Allocate(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE, 1).GetOffset();
|
||||
shaderResourceView = AllocateHandle(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE, 1);
|
||||
}
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE descriptorHandle = GetCpuPlatformHandle(shaderResourceView);
|
||||
|
||||
@@ -205,7 +246,7 @@ namespace AZ
|
||||
{
|
||||
if (unorderedAccessView.IsNull())
|
||||
{
|
||||
unorderedAccessView = Allocate(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE, 1).GetOffset();
|
||||
unorderedAccessView = AllocateHandle(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE, 1);
|
||||
}
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE unorderedAccessDescriptor = GetCpuPlatformHandle(unorderedAccessView);
|
||||
|
||||
@@ -216,7 +257,24 @@ namespace AZ
|
||||
// Copy the UAV descriptor into the GPU-visible version for clearing.
|
||||
if (unorderedAccessViewClear.IsNull())
|
||||
{
|
||||
unorderedAccessViewClear = Allocate(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, 1).GetOffset();
|
||||
unorderedAccessViewClear = AllocateHandle(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, 1);
|
||||
|
||||
if (unorderedAccessViewClear.IsNull())
|
||||
{
|
||||
AZ_Assert(
|
||||
false,
|
||||
"Descriptor heap ran out of memory for static handles. Please consider increasing the value of "
|
||||
"NumShaderVisibleCbvSrvUavStaticHandles within platformlimits.azasset file for dx12.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_allowDescriptorHeapCompaction)
|
||||
{
|
||||
// We make a copy of static handles in case we need to compact and recreate the shader visible heap
|
||||
m_device->CopyDescriptorsSimple(
|
||||
1, m_backupStaticHandles.GetCpuPlatformHandle(unorderedAccessViewClear), unorderedAccessDescriptor,
|
||||
unorderedAccessViewClear.m_type);
|
||||
}
|
||||
}
|
||||
CopyDescriptor(unorderedAccessViewClear, unorderedAccessView);
|
||||
}
|
||||
@@ -228,7 +286,7 @@ namespace AZ
|
||||
{
|
||||
if (renderTargetView.IsNull())
|
||||
{
|
||||
renderTargetView = Allocate(D3D12_DESCRIPTOR_HEAP_TYPE_RTV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE, 1).GetOffset();
|
||||
renderTargetView = AllocateHandle(D3D12_DESCRIPTOR_HEAP_TYPE_RTV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE, 1);
|
||||
}
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE renderTargetDescriptor = GetCpuPlatformHandle(renderTargetView);
|
||||
|
||||
@@ -245,13 +303,13 @@ namespace AZ
|
||||
{
|
||||
if (depthStencilView.IsNull())
|
||||
{
|
||||
depthStencilView = Allocate(D3D12_DESCRIPTOR_HEAP_TYPE_DSV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE, 1).GetOffset();
|
||||
depthStencilView = AllocateHandle(D3D12_DESCRIPTOR_HEAP_TYPE_DSV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE, 1);
|
||||
}
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE depthStencilDescriptor = GetCpuPlatformHandle(depthStencilView);
|
||||
|
||||
if (depthStencilReadView.IsNull())
|
||||
{
|
||||
depthStencilReadView = Allocate(D3D12_DESCRIPTOR_HEAP_TYPE_DSV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE, 1).GetOffset();
|
||||
depthStencilReadView = AllocateHandle(D3D12_DESCRIPTOR_HEAP_TYPE_DSV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE, 1);
|
||||
}
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE depthStencilReadDescriptor = GetCpuPlatformHandle(depthStencilReadView);
|
||||
|
||||
@@ -274,7 +332,7 @@ namespace AZ
|
||||
{
|
||||
if (samplerHandle.IsNull())
|
||||
{
|
||||
samplerHandle = Allocate(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, D3D12_DESCRIPTOR_HEAP_FLAG_NONE, 1).GetOffset();
|
||||
samplerHandle = AllocateHandle(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, D3D12_DESCRIPTOR_HEAP_FLAG_NONE, 1);
|
||||
}
|
||||
|
||||
D3D12_SAMPLER_DESC samplerDesc;
|
||||
@@ -286,17 +344,49 @@ namespace AZ
|
||||
{
|
||||
if (!descriptorHandle.IsNull())
|
||||
{
|
||||
ReleaseDescriptorTable(DescriptorTable(descriptorHandle, 1));
|
||||
GetPool(descriptorHandle.m_type, descriptorHandle.m_flags).ReleaseHandle(descriptorHandle);
|
||||
}
|
||||
}
|
||||
|
||||
DescriptorTable DescriptorContext::CreateDescriptorTable(
|
||||
D3D12_DESCRIPTOR_HEAP_TYPE descriptorHeapType,
|
||||
uint32_t descriptorCount)
|
||||
D3D12_DESCRIPTOR_HEAP_TYPE descriptorHeapType, uint32_t descriptorCount, ShaderResourceGroup* srg)
|
||||
{
|
||||
return Allocate(descriptorHeapType, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, descriptorCount);
|
||||
if (m_allowDescriptorHeapCompaction && !m_compactionInProgress)
|
||||
{
|
||||
// Track active SRGs in case we need to compact the shader visible cbv_srv_uav heap
|
||||
AZStd::scoped_lock lock{ m_srgMapMutex };
|
||||
auto iter = m_srgAllocations.find(srg);
|
||||
if (iter == m_srgAllocations.end())
|
||||
{
|
||||
m_srgAllocations.emplace(srg, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_srgAllocations[srg]++;
|
||||
}
|
||||
}
|
||||
|
||||
return GetPool(descriptorHeapType, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE).AllocateTable(descriptorCount);
|
||||
}
|
||||
|
||||
void DescriptorContext::ReleaseDescriptorTable(DescriptorTable table, ShaderResourceGroup* srg)
|
||||
{
|
||||
if (m_allowDescriptorHeapCompaction && !m_compactionInProgress)
|
||||
{
|
||||
//Track active SRGs in case we need to compact the shader visible cbv_srv_uav heap
|
||||
AZStd::scoped_lock lock{ m_srgMapMutex };
|
||||
auto iter = m_srgAllocations.find(srg);
|
||||
AZ_Assert(iter != m_srgAllocations.end(), "Srg entry not found");
|
||||
m_srgAllocations[srg]--;
|
||||
if (m_srgAllocations[srg] == 0)
|
||||
{
|
||||
m_srgAllocations.erase(srg);
|
||||
}
|
||||
}
|
||||
|
||||
GetPool(table.GetType(), table.GetFlags()).ReleaseTable(table);
|
||||
}
|
||||
|
||||
void DescriptorContext::UpdateDescriptorTableRange(
|
||||
DescriptorTable gpuDestinationTable,
|
||||
const DescriptorHandle* cpuSourceDescriptors,
|
||||
@@ -313,14 +403,12 @@ namespace AZ
|
||||
}
|
||||
|
||||
// Resolve destination descriptor to platform handle.
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE gpuDestinationHandle = GetCpuPlatformHandle(gpuDestinationTable.GetOffset());
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE gpuDestinationHandle = GetCpuPlatformHandleForTable(gpuDestinationTable);
|
||||
|
||||
// An array of descriptor sizes for each range. We just want N ranges with 1 descriptor each.
|
||||
AZStd::vector<uint32_t> rangeCounts(DescriptorCount, 1);
|
||||
|
||||
/**
|
||||
* We are gathering N source descriptors into a contiguous destination table.
|
||||
*/
|
||||
//We are gathering N source descriptors into a contiguous destination table.
|
||||
m_device->CopyDescriptors(
|
||||
1, // Number of destination ranges.
|
||||
&gpuDestinationHandle, // Destination range array.
|
||||
@@ -353,19 +441,24 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_allowDescriptorHeapCompaction)
|
||||
{
|
||||
m_backupStaticHandles.GarbageCollect();
|
||||
}
|
||||
}
|
||||
|
||||
DescriptorTable DescriptorContext::Allocate(
|
||||
DescriptorTable DescriptorContext::AllocateTable(
|
||||
D3D12_DESCRIPTOR_HEAP_TYPE type,
|
||||
D3D12_DESCRIPTOR_HEAP_FLAGS flags,
|
||||
uint32_t count)
|
||||
{
|
||||
return GetPool(type, flags).Allocate(count);
|
||||
return GetPool(type, flags).AllocateTable(count);
|
||||
}
|
||||
|
||||
void DescriptorContext::ReleaseDescriptorTable(DescriptorTable table)
|
||||
DescriptorHandle DescriptorContext::AllocateHandle(D3D12_DESCRIPTOR_HEAP_TYPE type, D3D12_DESCRIPTOR_HEAP_FLAGS flags, uint32_t count)
|
||||
{
|
||||
GetPool(table.GetType(), table.GetFlags()).Release(table);
|
||||
return GetPool(type, flags).AllocateHandle(count);
|
||||
}
|
||||
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE DescriptorContext::GetCpuPlatformHandle(DescriptorHandle handle) const
|
||||
@@ -378,6 +471,16 @@ namespace AZ
|
||||
return GetPool(handle.m_type, handle.m_flags).GetGpuPlatformHandle(handle);
|
||||
}
|
||||
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE DescriptorContext::GetCpuPlatformHandleForTable(DescriptorTable descTable) const
|
||||
{
|
||||
return GetPool(descTable.GetOffset().m_type, descTable.GetOffset().m_flags).GetCpuPlatformHandleForTable(descTable);
|
||||
}
|
||||
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE DescriptorContext::GetGpuPlatformHandleForTable(DescriptorTable descTable) const
|
||||
{
|
||||
return GetPool(descTable.GetOffset().m_type, descTable.GetOffset().m_flags).GetGpuPlatformHandleForTable(descTable);
|
||||
}
|
||||
|
||||
DescriptorHandle DescriptorContext::GetNullHandleSRV(D3D12_SRV_DIMENSION dimension) const
|
||||
{
|
||||
auto iter = m_nullDescriptorsSRV.find(dimension);
|
||||
@@ -431,14 +534,88 @@ namespace AZ
|
||||
{
|
||||
AZ_Assert(type < D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES, "Trying to get pool with invalid type: [%d]", type);
|
||||
AZ_Assert(flag < NumHeapFlags, "Trying to get pool with invalid flag: [%d]", flag);
|
||||
return m_pools[type][flag];
|
||||
|
||||
if (m_allowDescriptorHeapCompaction && IsShaderVisibleCbvSrvUavHeap(type, flag))
|
||||
{
|
||||
return m_shaderVisibleCbvSrvUavPools[m_currentHeapIndex];
|
||||
}
|
||||
else
|
||||
{
|
||||
return m_pools[type][flag];
|
||||
}
|
||||
}
|
||||
|
||||
const DescriptorPool& DescriptorContext::GetPool(uint32_t type, uint32_t flag) const
|
||||
{
|
||||
AZ_Assert(type < D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES, "Trying to get pool with invalid type: [%d]", type);
|
||||
AZ_Assert(flag < NumHeapFlags, "Trying to get pool with invalid flag: [%d]", flag);
|
||||
return m_pools[type][flag];
|
||||
if (m_allowDescriptorHeapCompaction && IsShaderVisibleCbvSrvUavHeap(type, flag))
|
||||
{
|
||||
return m_shaderVisibleCbvSrvUavPools[m_currentHeapIndex];
|
||||
}
|
||||
else
|
||||
{
|
||||
return m_pools[type][flag];
|
||||
}
|
||||
}
|
||||
|
||||
RHI::ResultCode DescriptorContext::CompactDescriptorHeap()
|
||||
{
|
||||
//Check if heap compaction is enabled by the user. Since there is an overhead associated with heap compaction it is not enabled by default
|
||||
if(!m_allowDescriptorHeapCompaction)
|
||||
{
|
||||
AZ_Assert(
|
||||
false,
|
||||
"Descriptor heap Compaction not allowed. Please consider increasing number of handles allowed for the second value"
|
||||
"of DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV or enabling AllowDescriptorHeapCompaction within platformlimits.azasset file for dx12.");
|
||||
return RHI::ResultCode::OutOfMemory;
|
||||
}
|
||||
|
||||
//We need to ping-pong between two heaps as we cannot compact the active heap without updating it and that is not allowed as
|
||||
//we need to keep that gpu memory untouched until GPU is finished consuming which can take up to 3 frames.
|
||||
m_compactionInProgress = true;
|
||||
DescriptorPool& srcPool = GetPool(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE);
|
||||
|
||||
//Update the currently active heap index
|
||||
m_currentHeapIndex = !m_currentHeapIndex;
|
||||
DescriptorPool& destPool = GetPool(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE);
|
||||
|
||||
//Copy over all the static handles first
|
||||
for (size_t i = 0; i < m_platformLimitsDescriptor->m_numShaderVisibleCbvSrvUavStaticHandles; i++)
|
||||
{
|
||||
DescriptorHandle srcHandle(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE, static_cast<uint32_t>(i));
|
||||
DescriptorHandle destHandle(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, static_cast<uint32_t>(i));
|
||||
m_device->CopyDescriptorsSimple(1, destPool.GetCpuPlatformHandle(destHandle), m_backupStaticHandles.GetCpuPlatformHandle(srcHandle), destHandle.m_type);
|
||||
}
|
||||
|
||||
//Clone the allocator of the source pool into the destination pool
|
||||
srcPool.CloneAllocator(destPool.GetAllocator());
|
||||
|
||||
{
|
||||
//The mutex is here 'just in case' Compaction is called from more than one thread.
|
||||
AZStd::scoped_lock lock{ m_srgMapMutex };
|
||||
//Re-update all the descriptor tables associated with active SRGs
|
||||
for (const auto& [srg, numAllocations] : m_srgAllocations)
|
||||
{
|
||||
RHI::ResultCode resultCode = static_cast<ShaderResourceGroupPool*>(srg->GetPool())->UpdateDescriptorTableAfterCompaction(*srg, srg->GetData());
|
||||
if (resultCode != RHI::ResultCode::Success)
|
||||
{
|
||||
return resultCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Clear the allocator of the source pool
|
||||
srcPool.ClearAllocator();
|
||||
|
||||
m_compactionInProgress = false;
|
||||
|
||||
return RHI::ResultCode::Success;
|
||||
}
|
||||
|
||||
bool DescriptorContext::IsShaderVisibleCbvSrvUavHeap(uint32_t type, uint32_t flag) const
|
||||
{
|
||||
return type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV && flag == D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
#include <Atom/RHI.Reflect/SamplerState.h>
|
||||
#include <Atom/RHI/Buffer.h>
|
||||
#include <Atom/RHI/Image.h>
|
||||
#include <AzCore/std/containers/unordered_map.h>
|
||||
#include <RHI/ShaderResourceGroup.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -82,12 +84,14 @@ namespace AZ
|
||||
//! Creates a GPU-visible descriptor table.
|
||||
//! @param descriptorHeapType The descriptor heap to allocate from.
|
||||
//! @param descriptorCount The number of descriptors to allocate.
|
||||
//! @param srg Shader resource group with which the descriptor table is associated with
|
||||
DescriptorTable CreateDescriptorTable(
|
||||
D3D12_DESCRIPTOR_HEAP_TYPE descriptorHeapType,
|
||||
uint32_t descriptorCount);
|
||||
|
||||
void ReleaseDescriptorTable(DescriptorTable descriptorTable);
|
||||
D3D12_DESCRIPTOR_HEAP_TYPE descriptorHeapType, uint32_t descriptorCount, ShaderResourceGroup* srg);
|
||||
|
||||
//! Releases a GPU-visible descriptor table.
|
||||
//! @param descriptorHeapType The descriptor heap to allocate from.
|
||||
//! @param srg Shader resource group with which the descriptor table is associated with
|
||||
void ReleaseDescriptorTable(DescriptorTable descriptorTable, ShaderResourceGroup* srg);
|
||||
|
||||
//! Performs a gather of disjoint CPU-side descriptors and copies to a contiguous GPU-side descriptor table.
|
||||
//! @param gpuDestinationTable The destination descriptor table that the descriptors will be uploaded to.
|
||||
@@ -110,6 +114,8 @@ namespace AZ
|
||||
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE GetCpuPlatformHandle(DescriptorHandle handle) const;
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE GetGpuPlatformHandle(DescriptorHandle handle) const;
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE GetCpuPlatformHandleForTable(DescriptorTable descTable) const;
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE GetGpuPlatformHandleForTable(DescriptorTable descTable) const;
|
||||
|
||||
void SetDescriptorHeaps(ID3D12GraphicsCommandList* commandList) const;
|
||||
|
||||
@@ -117,6 +123,12 @@ namespace AZ
|
||||
|
||||
ID3D12DeviceX* GetDevice();
|
||||
|
||||
//! Since we are only allowed one shader visible CbvSrvUav heap of a limited size in certain hardware, it is possible that
|
||||
//! it can get fragmented by constant alloc/de-alloc of descriptor tables related to direct views or unbounded resource views within a SRG. We use two
|
||||
//! heaps to ping pong during compaction as fragmentation can occur many times. It copies static handles directly and for all the
|
||||
//! dynamic handles we re-update the new heap by copying over the handles from the 'non-shader visible' heap.
|
||||
RHI::ResultCode CompactDescriptorHeap();
|
||||
|
||||
private:
|
||||
void CopyDescriptor(DescriptorHandle dst, DescriptorHandle src);
|
||||
|
||||
@@ -129,10 +141,13 @@ namespace AZ
|
||||
DescriptorPool& GetPool(uint32_t type, uint32_t flag);
|
||||
const DescriptorPool& GetPool(uint32_t type, uint32_t flag) const;
|
||||
|
||||
DescriptorTable Allocate(
|
||||
D3D12_DESCRIPTOR_HEAP_TYPE type,
|
||||
D3D12_DESCRIPTOR_HEAP_FLAGS flags,
|
||||
uint32_t count);
|
||||
//! Allocates a Descriptor table which describes a contiguous range of descriptor handles
|
||||
DescriptorTable AllocateTable(D3D12_DESCRIPTOR_HEAP_TYPE type, D3D12_DESCRIPTOR_HEAP_FLAGS flags, uint32_t count);
|
||||
|
||||
//! Allocates a single descriptor handle
|
||||
DescriptorHandle AllocateHandle(D3D12_DESCRIPTOR_HEAP_TYPE type, D3D12_DESCRIPTOR_HEAP_FLAGS flags, uint32_t count);
|
||||
|
||||
bool IsShaderVisibleCbvSrvUavHeap(uint32_t type, uint32_t flag) const;
|
||||
|
||||
static const uint32_t NumHeapFlags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE + 1;
|
||||
static const uint32_t s_descriptorCountMax[D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES][NumHeapFlags];
|
||||
@@ -147,6 +162,25 @@ namespace AZ
|
||||
DescriptorHandle m_nullSamplerDescriptor;
|
||||
|
||||
RHI::ConstPtr<PlatformLimitsDescriptor> m_platformLimitsDescriptor;
|
||||
|
||||
// Use 2 heaps below in order to ping-pong between shader visible CbvSrvUav heap when one of them fragments and run out of memory.
|
||||
static const uint32_t MaxShaderVisibleCbvSrvUavHeaps = 2;
|
||||
DescriptorPoolShaderVisibleCbvSrvUav m_shaderVisibleCbvSrvUavPools[MaxShaderVisibleCbvSrvUavHeaps];
|
||||
//This pool stores a copy of static handles that can later be used to recreate the compacted shader visible CbvSrvUav heap.
|
||||
DescriptorPool m_backupStaticHandles;
|
||||
|
||||
//Boolean to dictate when compaction was in progress
|
||||
bool m_compactionInProgress = false;
|
||||
|
||||
//Boolean to dictate if we should support compaction for shader visible CbvSrvUav heap
|
||||
bool m_allowDescriptorHeapCompaction = false;
|
||||
|
||||
//Map to store active SRGs and the number of associated descriptor tables. This is used to recreate the new compacted heap when we switch heaps
|
||||
AZStd::unordered_map<ShaderResourceGroup*, uint32_t> m_srgAllocations;
|
||||
AZStd::mutex m_srgMapMutex;
|
||||
|
||||
//Index that holds the currently active shader visible CbvSrvUav heap
|
||||
uint32_t m_currentHeapIndex = 0;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,34 +18,38 @@ namespace AZ
|
||||
ID3D12DeviceX* device,
|
||||
D3D12_DESCRIPTOR_HEAP_TYPE type,
|
||||
D3D12_DESCRIPTOR_HEAP_FLAGS flags,
|
||||
uint32_t descriptorCount)
|
||||
uint32_t descriptorCountForHeap,
|
||||
uint32_t descriptorCountForAllocator)
|
||||
{
|
||||
m_Desc.Type = type;
|
||||
m_Desc.Flags = flags;
|
||||
m_Desc.NumDescriptors = descriptorCount;
|
||||
m_Desc.NodeMask = 1;
|
||||
m_desc.Type = type;
|
||||
m_desc.Flags = flags;
|
||||
m_desc.NumDescriptors = descriptorCountForHeap;
|
||||
m_desc.NodeMask = 1;
|
||||
|
||||
ID3D12DescriptorHeap* heap;
|
||||
DX12::AssertSuccess(device->CreateDescriptorHeap(&m_Desc, IID_GRAPHICS_PPV_ARGS(&heap)));
|
||||
DX12::AssertSuccess(device->CreateDescriptorHeap(&m_desc, IID_GRAPHICS_PPV_ARGS(&heap)));
|
||||
heap->SetName(L"DescriptorHeap");
|
||||
|
||||
m_DescriptorHeap.Attach(heap);
|
||||
m_Stride = device->GetDescriptorHandleIncrementSize(m_Desc.Type);
|
||||
m_descriptorHeap.Attach(heap);
|
||||
m_stride = device->GetDescriptorHandleIncrementSize(m_desc.Type);
|
||||
|
||||
m_CpuStart = heap->GetCPUDescriptorHandleForHeapStart();
|
||||
m_GpuStart = {};
|
||||
|
||||
if (RHI::CheckBitsAny(flags, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE))
|
||||
{
|
||||
m_GpuStart = heap->GetGPUDescriptorHandleForHeapStart();
|
||||
}
|
||||
m_cpuStart = heap->GetCPUDescriptorHandleForHeapStart();
|
||||
m_gpuStart = {};
|
||||
|
||||
const bool isGpuVisible = RHI::CheckBitsAll(flags, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE);
|
||||
if (isGpuVisible)
|
||||
{
|
||||
m_gpuStart = heap->GetGPUDescriptorHandleForHeapStart();
|
||||
}
|
||||
|
||||
if (isGpuVisible)
|
||||
{
|
||||
RHI::FreeListAllocator::Descriptor descriptor;
|
||||
descriptor.m_alignmentInBytes = 1;
|
||||
descriptor.m_capacityInBytes = descriptorCount;
|
||||
|
||||
//It is possible for descriptorCountForAllocator to not match descriptorCountForHeap for DescriptorPoolShaderVisibleCbvSrvUav
|
||||
//heaps in which case descriptorCountForAllocator defines the number of static handles
|
||||
descriptor.m_capacityInBytes = aznumeric_cast<uint32_t>(descriptorCountForAllocator);
|
||||
descriptor.m_garbageCollectLatency = RHI::Limits::Device::FrameCountMax;
|
||||
|
||||
RHI::FreeListAllocator* allocator = aznew RHI::FreeListAllocator();
|
||||
@@ -56,10 +60,11 @@ namespace AZ
|
||||
{
|
||||
// Non-shader-visible heaps don't require contiguous descriptors. Therefore, we can allocate
|
||||
// them using a block allocator.
|
||||
|
||||
RHI::PoolAllocator::Descriptor descriptor;
|
||||
descriptor.m_alignmentInBytes = 1;
|
||||
descriptor.m_elementSize = 1;
|
||||
descriptor.m_capacityInBytes = descriptorCount;
|
||||
descriptor.m_capacityInBytes = aznumeric_cast<uint32_t>(descriptorCountForAllocator);
|
||||
descriptor.m_garbageCollectLatency = 0;
|
||||
|
||||
RHI::PoolAllocator* allocator = aznew RHI::PoolAllocator();
|
||||
@@ -68,7 +73,7 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
DescriptorTable DescriptorPool::Allocate(uint32_t count)
|
||||
DescriptorHandle DescriptorPool::AllocateHandle(uint32_t count)
|
||||
{
|
||||
RHI::VirtualAddress address;
|
||||
{
|
||||
@@ -78,24 +83,34 @@ namespace AZ
|
||||
|
||||
if (address.IsValid())
|
||||
{
|
||||
DescriptorHandle handle(m_Desc.Type, m_Desc.Flags, static_cast<uint32_t>(address.m_ptr));
|
||||
return DescriptorTable(handle, static_cast<uint16_t>(count));
|
||||
DescriptorHandle handle(m_desc.Type, m_desc.Flags, static_cast<uint32_t>(address.m_ptr));
|
||||
return handle;
|
||||
}
|
||||
else
|
||||
{
|
||||
return DescriptorTable{};
|
||||
return DescriptorHandle{};
|
||||
}
|
||||
}
|
||||
|
||||
void DescriptorPool::Release(DescriptorTable table)
|
||||
void DescriptorPool::ReleaseHandle(DescriptorHandle handle)
|
||||
{
|
||||
if (table.IsNull())
|
||||
if (handle.IsNull())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AZStd::lock_guard<AZStd::mutex> lock(m_mutex);
|
||||
m_allocator->DeAllocate(RHI::VirtualAddress::CreateFromOffset(table.GetOffset().m_index));
|
||||
m_allocator->DeAllocate(RHI::VirtualAddress::CreateFromOffset(handle.m_index));
|
||||
}
|
||||
|
||||
DescriptorTable DescriptorPool::AllocateTable(uint32_t count)
|
||||
{
|
||||
return DescriptorTable(AllocateHandle(count), static_cast<uint16_t>(count));
|
||||
}
|
||||
|
||||
void DescriptorPool::ReleaseTable(DescriptorTable table)
|
||||
{
|
||||
ReleaseHandle(table.GetOffset());
|
||||
}
|
||||
|
||||
void DescriptorPool::GarbageCollect()
|
||||
@@ -106,20 +121,134 @@ namespace AZ
|
||||
|
||||
ID3D12DescriptorHeap* DescriptorPool::GetPlatformHeap() const
|
||||
{
|
||||
return m_DescriptorHeap.Get();
|
||||
return m_descriptorHeap.Get();
|
||||
}
|
||||
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE DescriptorPool::GetCpuPlatformHandle(DescriptorHandle handle) const
|
||||
{
|
||||
AZ_Assert(handle.m_index != DescriptorHandle::NullIndex, "Index is invalid");
|
||||
return D3D12_CPU_DESCRIPTOR_HANDLE{ m_CpuStart.ptr + handle.m_index * m_Stride };
|
||||
return D3D12_CPU_DESCRIPTOR_HANDLE{ m_cpuStart.ptr + handle.m_index * m_stride };
|
||||
}
|
||||
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE DescriptorPool::GetGpuPlatformHandle(DescriptorHandle handle) const
|
||||
{
|
||||
AZ_Assert(handle.IsShaderVisible(), "Handle is not shader visible");
|
||||
AZ_Assert(handle.m_index != DescriptorHandle::NullIndex, "Index is invalid");
|
||||
return D3D12_GPU_DESCRIPTOR_HANDLE{ m_GpuStart.ptr + handle.m_index * m_Stride };
|
||||
return D3D12_GPU_DESCRIPTOR_HANDLE{ m_gpuStart.ptr + (handle.m_index * m_stride) };
|
||||
}
|
||||
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE DescriptorPool::GetCpuPlatformHandleForTable(DescriptorTable descTable) const
|
||||
{
|
||||
DescriptorHandle handle = descTable.GetOffset();
|
||||
AZ_Assert(handle.m_index != DescriptorHandle::NullIndex, "Index is invalid");
|
||||
return D3D12_CPU_DESCRIPTOR_HANDLE{ m_cpuStart.ptr + handle.m_index * m_stride };
|
||||
}
|
||||
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE DescriptorPool::GetGpuPlatformHandleForTable(DescriptorTable descTable) const
|
||||
{
|
||||
DescriptorHandle handle = descTable.GetOffset();
|
||||
AZ_Assert(handle.IsShaderVisible(), "Handle is not shader visible");
|
||||
AZ_Assert(handle.m_index != DescriptorHandle::NullIndex, "Index is invalid");
|
||||
return D3D12_GPU_DESCRIPTOR_HANDLE{ m_gpuStart.ptr + (handle.m_index * m_stride) };
|
||||
}
|
||||
|
||||
void DescriptorPool::CloneAllocator(RHI::Allocator* newAllocator)
|
||||
{
|
||||
m_allocator->Clone(newAllocator);
|
||||
}
|
||||
|
||||
void DescriptorPool::ClearAllocator()
|
||||
{
|
||||
AZ_Assert(m_gpuStart.ptr, "Clearing the allocator is only supported for the gpu visible heap as only this heap can be compacted");
|
||||
static_cast<RHI::FreeListAllocator*>(m_allocator.get())
|
||||
->Init(static_cast<RHI::FreeListAllocator*>(m_allocator.get())->GetDescriptor());
|
||||
}
|
||||
|
||||
RHI::Allocator* DescriptorPool::GetAllocator() const
|
||||
{
|
||||
return m_allocator.get();
|
||||
}
|
||||
|
||||
void DescriptorPoolShaderVisibleCbvSrvUav::Init(
|
||||
ID3D12DeviceX* device,
|
||||
D3D12_DESCRIPTOR_HEAP_TYPE type,
|
||||
D3D12_DESCRIPTOR_HEAP_FLAGS flags,
|
||||
uint32_t descriptorCount,
|
||||
uint32_t staticHandlesCount)
|
||||
{
|
||||
//This pool manages two allocators. The allocator in the base class manages static handles
|
||||
Base::Init(device, type, flags, descriptorCount, staticHandlesCount);
|
||||
|
||||
//This allocator manages dynamic handles associated with descriptor tables. This allows us to
|
||||
//reconstruct the full heap in a compact manner if it ever fragments.
|
||||
RHI::FreeListAllocator::Descriptor descriptor;
|
||||
descriptor.m_alignmentInBytes = 1;
|
||||
descriptor.m_capacityInBytes = aznumeric_cast<uint32_t>(descriptorCount - staticHandlesCount);
|
||||
descriptor.m_garbageCollectLatency = RHI::Limits::Device::FrameCountMax;
|
||||
|
||||
RHI::FreeListAllocator* allocator = aznew RHI::FreeListAllocator();
|
||||
allocator->Init(descriptor);
|
||||
m_unboundedArrayAllocator.reset(allocator);
|
||||
|
||||
//Cache the starting point of the dynamic section of the heap
|
||||
m_startingHandleIndex = staticHandlesCount;
|
||||
}
|
||||
|
||||
DescriptorTable DescriptorPoolShaderVisibleCbvSrvUav::AllocateTable(uint32_t count)
|
||||
{
|
||||
RHI::VirtualAddress address;
|
||||
{
|
||||
AZStd::lock_guard<AZStd::mutex> lock(m_mutex);
|
||||
address = m_unboundedArrayAllocator->Allocate(count, 1);
|
||||
}
|
||||
|
||||
if (address.IsValid())
|
||||
{
|
||||
DescriptorHandle handle(m_desc.Type, m_desc.Flags, static_cast<uint32_t>(address.m_ptr));
|
||||
return DescriptorTable(handle, static_cast<uint16_t>(count));
|
||||
}
|
||||
else
|
||||
{
|
||||
return DescriptorTable{};
|
||||
}
|
||||
}
|
||||
|
||||
void DescriptorPoolShaderVisibleCbvSrvUav::ReleaseTable(DescriptorTable table)
|
||||
{
|
||||
if (table.IsNull())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AZStd::lock_guard<AZStd::mutex> lock(m_mutex);
|
||||
m_unboundedArrayAllocator->DeAllocate(RHI::VirtualAddress::CreateFromOffset(table.GetOffset().m_index));
|
||||
}
|
||||
|
||||
void DescriptorPoolShaderVisibleCbvSrvUav::GarbageCollect()
|
||||
{
|
||||
Base::GarbageCollect();
|
||||
m_unboundedArrayAllocator->GarbageCollect();
|
||||
}
|
||||
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE DescriptorPoolShaderVisibleCbvSrvUav::GetCpuPlatformHandleForTable(DescriptorTable descTable) const
|
||||
{
|
||||
DescriptorHandle handle = descTable.GetOffset();
|
||||
AZ_Assert(handle.m_index != DescriptorHandle::NullIndex, "Index is invalid");
|
||||
return D3D12_CPU_DESCRIPTOR_HANDLE{ m_cpuStart.ptr + (m_startingHandleIndex * m_stride) + (handle.m_index * m_stride) };
|
||||
}
|
||||
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE DescriptorPoolShaderVisibleCbvSrvUav::GetGpuPlatformHandleForTable(DescriptorTable descTable) const
|
||||
{
|
||||
DescriptorHandle handle = descTable.GetOffset();
|
||||
AZ_Assert(handle.IsShaderVisible(), "Handle is not shader visible");
|
||||
AZ_Assert(handle.m_index != DescriptorHandle::NullIndex, "Index is invalid");
|
||||
return D3D12_GPU_DESCRIPTOR_HANDLE{ m_gpuStart.ptr + (m_startingHandleIndex * m_stride) + (handle.m_index * m_stride) };
|
||||
}
|
||||
|
||||
void DescriptorPoolShaderVisibleCbvSrvUav::ClearAllocator()
|
||||
{
|
||||
Base::ClearAllocator();
|
||||
static_cast<RHI::FreeListAllocator*>(m_unboundedArrayAllocator.get())->Init(static_cast<RHI::FreeListAllocator*>(m_unboundedArrayAllocator.get())->GetDescriptor());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,37 +18,91 @@ namespace AZ
|
||||
{
|
||||
namespace DX12
|
||||
{
|
||||
//! This class defines a Descriptor pool which manages all the descriptors used for binding resources
|
||||
class DescriptorPool
|
||||
{
|
||||
public:
|
||||
DescriptorPool() = default;
|
||||
virtual ~DescriptorPool() = default;
|
||||
|
||||
void Init(
|
||||
//! Initialize the native heap as well as init the allocators tracking the memory for descriptor handles
|
||||
virtual void Init(
|
||||
ID3D12DeviceX* device,
|
||||
D3D12_DESCRIPTOR_HEAP_TYPE type,
|
||||
D3D12_DESCRIPTOR_HEAP_FLAGS flags,
|
||||
uint32_t descriptorCount);
|
||||
uint32_t descriptorCountForHeap,
|
||||
uint32_t descriptorCountForAllocator);
|
||||
|
||||
ID3D12DescriptorHeap* GetPlatformHeap() const;
|
||||
|
||||
DescriptorTable Allocate(uint32_t count = 1);
|
||||
//! Allocate a Descriptor handles
|
||||
DescriptorHandle AllocateHandle(uint32_t count = 1);
|
||||
//! Release a descriptor handle
|
||||
void ReleaseHandle(DescriptorHandle table);
|
||||
//! Allocate a range contiguous handles (i.e Descriptor table)
|
||||
virtual DescriptorTable AllocateTable(uint32_t count = 1);
|
||||
//! Release a range contiguous handles (i.e Descriptor table)
|
||||
virtual void ReleaseTable(DescriptorTable table);
|
||||
//! Garbage collection for freed handles or tables
|
||||
virtual void GarbageCollect();
|
||||
//Get native pointers from the heap
|
||||
virtual D3D12_CPU_DESCRIPTOR_HANDLE GetCpuPlatformHandleForTable(DescriptorTable handle) const;
|
||||
virtual D3D12_GPU_DESCRIPTOR_HANDLE GetGpuPlatformHandleForTable(DescriptorTable handle) const;
|
||||
//Clear the tracking allocator
|
||||
virtual void ClearAllocator();
|
||||
|
||||
void Release(DescriptorTable table);
|
||||
|
||||
void GarbageCollect();
|
||||
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE GetCpuPlatformHandle(DescriptorHandle handle) const;
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE GetGpuPlatformHandle(DescriptorHandle handle) const;
|
||||
|
||||
private:
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE m_CpuStart = {};
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE m_GpuStart = {};
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE m_NullDescriptor = {};
|
||||
uint32_t m_Stride = 0;
|
||||
D3D12_DESCRIPTOR_HEAP_DESC m_Desc;
|
||||
Microsoft::WRL::ComPtr<ID3D12DescriptorHeap> m_DescriptorHeap;
|
||||
//Clone the tracking allocator
|
||||
void CloneAllocator(RHI::Allocator* newAllocator);
|
||||
RHI::Allocator* GetAllocator() const;
|
||||
|
||||
protected:
|
||||
D3D12_DESCRIPTOR_HEAP_DESC m_desc;
|
||||
AZStd::mutex m_mutex;
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE m_cpuStart = {};
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE m_gpuStart = {};
|
||||
uint32_t m_stride = 0;
|
||||
private:
|
||||
|
||||
// Native heap
|
||||
Microsoft::WRL::ComPtr<ID3D12DescriptorHeap> m_descriptorHeap;
|
||||
|
||||
// Allocator used to manage the whole native heap. In the case of DescriptorPoolShaderVisibleCbvSrvUav this allocator
|
||||
// is used to manage the part of the heap that only manages static handles.
|
||||
AZStd::unique_ptr<RHI::Allocator> m_allocator;
|
||||
};
|
||||
|
||||
//! A specialized pool that specifically handles Descriptor tables for Cbv/Srv/Uav views and allows for Compaction
|
||||
//! Specifically this pool handles the dynamic part of the heap
|
||||
class DescriptorPoolShaderVisibleCbvSrvUav : public DescriptorPool
|
||||
{
|
||||
using Base = DescriptorPool;
|
||||
|
||||
public:
|
||||
void Init(
|
||||
ID3D12DeviceX* device,
|
||||
D3D12_DESCRIPTOR_HEAP_TYPE type,
|
||||
D3D12_DESCRIPTOR_HEAP_FLAGS flags,
|
||||
uint32_t descriptorCount,
|
||||
uint32_t staticHandlesCount);
|
||||
|
||||
DescriptorTable AllocateTable(uint32_t count = 1) override;
|
||||
void ReleaseTable(DescriptorTable table) override;
|
||||
void GarbageCollect() override;
|
||||
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE GetCpuPlatformHandleForTable(DescriptorTable handle) const override;
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE GetGpuPlatformHandleForTable(DescriptorTable handle) const override;
|
||||
void ClearAllocator() override;
|
||||
|
||||
private:
|
||||
|
||||
// A separate allocator that handles descriptor tables which are dynamic in nature and may fragment and require compaction
|
||||
AZStd::unique_ptr<RHI::Allocator> m_unboundedArrayAllocator;
|
||||
//Starting index of the dynamic part of the heap
|
||||
uint32_t m_startingHandleIndex = 0;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -625,5 +625,20 @@ namespace AZ
|
||||
{
|
||||
return m_isAftermathInitialized;
|
||||
}
|
||||
|
||||
RHI::ResultCode Device::CompactSRGMemory()
|
||||
{
|
||||
if (m_isDescriptorHeapCompactionNeeded)
|
||||
{
|
||||
m_isDescriptorHeapCompactionNeeded = false;
|
||||
return m_descriptorContext->CompactDescriptorHeap();
|
||||
}
|
||||
return RHI::ResultCode::Success;
|
||||
}
|
||||
|
||||
void Device::DescriptorHeapCompactionNeeded()
|
||||
{
|
||||
m_isDescriptorHeapCompactionNeeded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,39 +98,27 @@ namespace AZ
|
||||
D3D12_RESOURCE_STATES initialState,
|
||||
ImageTileLayout& imageTilingInfo);
|
||||
|
||||
/**
|
||||
* Queues a DX12 COM object for release (by taking a reference) after the current frame has flushed
|
||||
* through the GPU.
|
||||
*/
|
||||
//! Queues a DX12 COM object for release (by taking a reference) after the current frame has flushed
|
||||
//! through the GPU.
|
||||
void QueueForRelease(RHI::Ptr<ID3D12Object> dx12Object);
|
||||
|
||||
/**
|
||||
* Queues the backing Memory instance of a MemoryView for release (by taking a reference) after the
|
||||
* current frame has flushed through the GPU. The reference on the MemoryView itself is not released.
|
||||
*/
|
||||
//! Queues the backing Memory instance of a MemoryView for release (by taking a reference) after the
|
||||
//! current frame has flushed through the GPU. The reference on the MemoryView itself is not released.
|
||||
void QueueForRelease(const MemoryView& memoryView);
|
||||
|
||||
/**
|
||||
* Allocates host memory from the internal frame allocator that is suitable for staging
|
||||
* uploads to the GPU for the current frame. The memory is valid for the lifetime of
|
||||
* the frame and is automatically reclaimed after the frame has completed on the GPU.
|
||||
*/
|
||||
//! Allocates host memory from the internal frame allocator that is suitable for staging
|
||||
//! uploads to the GPU for the current frame. The memory is valid for the lifetime of
|
||||
//! the frame and is automatically reclaimed after the frame has completed on the GPU.
|
||||
MemoryView AcquireStagingMemory(size_t size, size_t alignment);
|
||||
|
||||
/**
|
||||
* Acquires a pipeline layout from the internal cache.
|
||||
*/
|
||||
//! Acquires a pipeline layout from the internal cache.
|
||||
RHI::ConstPtr<PipelineLayout> AcquirePipelineLayout(const RHI::PipelineLayoutDescriptor& descriptor);
|
||||
|
||||
/**
|
||||
* Acquires a new command list for the frame given the hardware queue class. The command list is
|
||||
* automatically reclaimed after the current frame has flushed through the GPU.
|
||||
*/
|
||||
//! Acquires a new command list for the frame given the hardware queue class. The command list is
|
||||
//! automatically reclaimed after the current frame has flushed through the GPU.
|
||||
CommandList* AcquireCommandList(RHI::HardwareQueueClass hardwareQueueClass);
|
||||
|
||||
/**
|
||||
* Acquires a sampler from the internal cache.
|
||||
*/
|
||||
//! Acquires a sampler from the internal cache.
|
||||
RHI::ConstPtr<Sampler> AcquireSampler(const RHI::SamplerState& state);
|
||||
|
||||
const PhysicalDevice& GetPhysicalDevice() const;
|
||||
@@ -146,6 +134,10 @@ namespace AZ
|
||||
AsyncUploadQueue& GetAsyncUploadQueue();
|
||||
|
||||
bool IsAftermathInitialized() const;
|
||||
|
||||
//! Indicate that we need to compact the shader visible srv/uav/cbv shader visible heap.
|
||||
void DescriptorHeapCompactionNeeded();
|
||||
|
||||
private:
|
||||
Device();
|
||||
|
||||
@@ -167,6 +159,7 @@ namespace AZ
|
||||
RHI::ResourceMemoryRequirements GetResourceMemoryRequirements(const RHI::ImageDescriptor & descriptor) override;
|
||||
RHI::ResourceMemoryRequirements GetResourceMemoryRequirements(const RHI::BufferDescriptor & descriptor) override;
|
||||
void ObjectCollectionNotify(RHI::ObjectCollectorNotifyFunction notifyFunction) override;
|
||||
RHI::ResultCode CompactSRGMemory() override;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
RHI::ResultCode InitSubPlatform(RHI::PhysicalDevice& physicalDevice);
|
||||
@@ -198,6 +191,9 @@ namespace AZ
|
||||
AZStd::mutex m_samplerCacheMutex;
|
||||
|
||||
bool m_isAftermathInitialized = false;
|
||||
|
||||
// Boolean used to compact the view specific shader visible heap
|
||||
bool m_isDescriptorHeapCompactionNeeded = false;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,9 +49,11 @@ namespace AZ
|
||||
AZStd::array_view<uint8_t> bytes;
|
||||
|
||||
bool shouldCreateLibFromSerializedData = true;
|
||||
if (RHI::Factory::Get().IsRenderDocModuleLoaded() || RHI::Factory::Get().IsPixModuleLoaded())
|
||||
if (RHI::Factory::Get().IsRenderDocModuleLoaded() ||
|
||||
RHI::Factory::Get().IsPixModuleLoaded() ||
|
||||
RHI::Factory::Get().UsingWarpDevice())
|
||||
{
|
||||
// CreatePipelineLibrary api does not function properly if Renderdoc or Pix is enabled
|
||||
// CreatePipelineLibrary api does not function properly if Renderdoc, Pix or Warp is enabled
|
||||
shouldCreateLibFromSerializedData = false;
|
||||
}
|
||||
|
||||
@@ -215,9 +217,11 @@ namespace AZ
|
||||
|
||||
RHI::ResultCode PipelineLibrary::MergeIntoInternal([[maybe_unused]] AZStd::array_view<const RHI::PipelineLibrary*> pipelineLibraries)
|
||||
{
|
||||
if (RHI::Factory::Get().IsRenderDocModuleLoaded() || RHI::Factory::Get().IsPixModuleLoaded())
|
||||
if (RHI::Factory::Get().IsRenderDocModuleLoaded() ||
|
||||
RHI::Factory::Get().IsPixModuleLoaded() ||
|
||||
RHI::Factory::Get().UsingWarpDevice())
|
||||
{
|
||||
// StorePipeline api does not function properly if RenderDoc or Pix is enabled
|
||||
// StorePipeline api does not function properly if RenderDoc, Pix or Warp is enabled
|
||||
return RHI::ResultCode::Fail;
|
||||
}
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@ namespace AZ
|
||||
ShaderResourceGroup() = default;
|
||||
|
||||
friend class ShaderResourceGroupPool;
|
||||
friend class DescriptorContext;
|
||||
|
||||
/// The current index into the compiled data array.
|
||||
uint32_t m_compiledDataIndex = 0;
|
||||
|
||||
@@ -132,33 +132,17 @@ namespace AZ
|
||||
compiledData.m_cpuConstantAddress = cpuAddress + m_constantBufferSize * i;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_viewsDescriptorTableSize)
|
||||
{
|
||||
group.m_viewsDescriptorTable = m_descriptorContext->CreateDescriptorTable(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, m_viewsDescriptorTableRingSize);
|
||||
|
||||
if (!group.m_viewsDescriptorTable.IsValid())
|
||||
{
|
||||
AZ_Error("ShaderResourceGroupPool", false, "Descriptor context failed to allocate view descriptor table. Try increasing the limits specified in platformlimits.azasset file for dx12");
|
||||
return RHI::ResultCode::OutOfMemory;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < copyCount; ++i)
|
||||
{
|
||||
const DescriptorHandle descriptorHandle = group.m_viewsDescriptorTable.GetOffset() + m_viewsDescriptorTableSize * i;
|
||||
|
||||
ShaderResourceGroupCompiledData& compiledData = group.m_compiledData[i];
|
||||
compiledData.m_gpuViewsDescriptorHandle = m_descriptorContext->GetGpuPlatformHandle(descriptorHandle);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (m_samplersDescriptorTableSize)
|
||||
{
|
||||
group.m_samplersDescriptorTable = m_descriptorContext->CreateDescriptorTable(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, m_samplersDescriptorTableRingSize);
|
||||
group.m_samplersDescriptorTable = m_descriptorContext->CreateDescriptorTable(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, m_samplersDescriptorTableRingSize, &group);
|
||||
|
||||
if (!group.m_samplersDescriptorTable.IsValid())
|
||||
{
|
||||
AZ_Error("ShaderResourceGroupPool", false, "Descriptor context failed to allocate sampler descriptor table. Try increasing the limits specified in platformlimits.azasset file for dx12.");
|
||||
AZ_Error(
|
||||
"ShaderResourceGroupPool", false,
|
||||
"Descriptor context failed to allocate sampler descriptor table. Please consider increasing number of handles "
|
||||
"allowed for the second value of DESCRIPTOR_HEAP_TYPE_SAMPLER within platformlimits.azasset file for dx12.");
|
||||
return RHI::ResultCode::OutOfMemory;
|
||||
}
|
||||
|
||||
@@ -167,7 +151,7 @@ namespace AZ
|
||||
const DescriptorHandle descriptorHandle = group.m_samplersDescriptorTable.GetOffset() + m_samplersDescriptorTableSize * i;
|
||||
|
||||
ShaderResourceGroupCompiledData& compiledData = group.m_compiledData[i];
|
||||
compiledData.m_gpuSamplersDescriptorHandle = m_descriptorContext->GetGpuPlatformHandle(descriptorHandle);
|
||||
compiledData.m_gpuSamplersDescriptorHandle = m_descriptorContext->GetGpuPlatformHandleForTable(DescriptorTable(descriptorHandle, static_cast<uint16_t>(m_samplersDescriptorTableSize)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,19 +170,25 @@ namespace AZ
|
||||
|
||||
if (m_viewsDescriptorTableSize)
|
||||
{
|
||||
m_descriptorContext->ReleaseDescriptorTable(group.m_viewsDescriptorTable);
|
||||
if (group.m_viewsDescriptorTable.IsValid())
|
||||
{
|
||||
m_descriptorContext->ReleaseDescriptorTable(group.m_viewsDescriptorTable, &group);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_samplersDescriptorTableSize)
|
||||
{
|
||||
m_descriptorContext->ReleaseDescriptorTable(group.m_samplersDescriptorTable);
|
||||
if (group.m_viewsDescriptorTable.IsValid())
|
||||
{
|
||||
m_descriptorContext->ReleaseDescriptorTable(group.m_samplersDescriptorTable, &group);
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t unboundedArrayindex = 0; unboundedArrayindex < (ShaderResourceGroupCompiledData::MaxUnboundedArrays * RHI::Limits::Device::FrameCountMax); ++unboundedArrayindex)
|
||||
{
|
||||
if (group.m_unboundedDescriptorTables[unboundedArrayindex].IsValid())
|
||||
{
|
||||
m_descriptorContext->ReleaseDescriptorTable(group.m_unboundedDescriptorTables[unboundedArrayindex]);
|
||||
m_descriptorContext->ReleaseDescriptorTable(group.m_unboundedDescriptorTables[unboundedArrayindex], &group);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,6 +203,7 @@ namespace AZ
|
||||
const RHI::ShaderResourceGroupData& groupData)
|
||||
{
|
||||
ShaderResourceGroup& group = static_cast<ShaderResourceGroup&>(groupBase);
|
||||
auto& device = static_cast<Device&>(GetDevice());
|
||||
group.m_compiledDataIndex = (group.m_compiledDataIndex + 1) % RHI::Limits::Device::FrameCountMax;
|
||||
|
||||
if (m_constantBufferSize)
|
||||
@@ -222,6 +213,22 @@ namespace AZ
|
||||
|
||||
if (m_viewsDescriptorTableSize)
|
||||
{
|
||||
//Lazy initialization for cbv/srv/uav Descriptor Tables
|
||||
if (!group.m_viewsDescriptorTable.IsValid())
|
||||
{
|
||||
group.m_viewsDescriptorTable = m_descriptorContext->CreateDescriptorTable(
|
||||
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, m_viewsDescriptorTableRingSize, &group);
|
||||
|
||||
if (!group.m_viewsDescriptorTable.IsValid())
|
||||
{
|
||||
//We have support for compacting D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV (if applicable) so try that.
|
||||
device.DescriptorHeapCompactionNeeded();
|
||||
return RHI::ResultCode::Success;
|
||||
}
|
||||
|
||||
CacheGpuHandlesForViews(group);
|
||||
}
|
||||
|
||||
const DescriptorTable descriptorTable(
|
||||
group.m_viewsDescriptorTable.GetOffset() + group.m_compiledDataIndex * m_viewsDescriptorTableSize,
|
||||
static_cast<uint16_t>(m_viewsDescriptorTableSize));
|
||||
@@ -246,6 +253,18 @@ namespace AZ
|
||||
return RHI::ResultCode::Success;
|
||||
}
|
||||
|
||||
void ShaderResourceGroupPool::CacheGpuHandlesForViews(ShaderResourceGroup& group)
|
||||
{
|
||||
for (uint32_t i = 0; i < RHI::Limits::Device::FrameCountMax; ++i)
|
||||
{
|
||||
const DescriptorHandle descriptorHandle = group.m_viewsDescriptorTable.GetOffset() + m_viewsDescriptorTableSize * i;
|
||||
|
||||
ShaderResourceGroupCompiledData& compiledData = group.m_compiledData[i];
|
||||
compiledData.m_gpuViewsDescriptorHandle = m_descriptorContext->GetGpuPlatformHandleForTable(
|
||||
DescriptorTable(descriptorHandle, static_cast<uint16_t>(m_viewsDescriptorTableSize)));
|
||||
}
|
||||
}
|
||||
|
||||
void ShaderResourceGroupPool::UpdateViewsDescriptorTable(DescriptorTable descriptorTable, const RHI::ShaderResourceGroupData& groupData)
|
||||
{
|
||||
const RHI::ShaderResourceGroupLayout& groupLayout = *groupData.GetLayout();
|
||||
@@ -261,27 +280,27 @@ namespace AZ
|
||||
AZStd::vector<DescriptorHandle> descriptorHandles;
|
||||
switch (descriptorRangeType)
|
||||
{
|
||||
case D3D12_DESCRIPTOR_RANGE_TYPE_SRV:
|
||||
{
|
||||
descriptorHandles = GetSRVsFromImageViews< RHI::BufferView, BufferView> (bufferViews, D3D12_SRV_DIMENSION_BUFFER);
|
||||
break;
|
||||
case D3D12_DESCRIPTOR_RANGE_TYPE_SRV:
|
||||
{
|
||||
descriptorHandles = GetSRVsFromImageViews< RHI::BufferView, BufferView> (bufferViews, D3D12_SRV_DIMENSION_BUFFER);
|
||||
break;
|
||||
}
|
||||
case D3D12_DESCRIPTOR_RANGE_TYPE_UAV:
|
||||
{
|
||||
descriptorHandles = GetUAVsFromImageViews<RHI::BufferView, BufferView>(bufferViews, D3D12_UAV_DIMENSION_BUFFER);
|
||||
break;
|
||||
}
|
||||
case D3D12_DESCRIPTOR_RANGE_TYPE_CBV:
|
||||
{
|
||||
descriptorHandles = GetCBVsFromBufferViews(bufferViews);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
AZ_Assert(false, "Unhandled D3D12_DESCRIPTOR_RANGE_TYPE enumeration");
|
||||
break;
|
||||
}
|
||||
case D3D12_DESCRIPTOR_RANGE_TYPE_UAV:
|
||||
{
|
||||
descriptorHandles = GetUAVsFromImageViews<RHI::BufferView, BufferView>(bufferViews, D3D12_UAV_DIMENSION_BUFFER);
|
||||
break;
|
||||
}
|
||||
case D3D12_DESCRIPTOR_RANGE_TYPE_CBV:
|
||||
{
|
||||
descriptorHandles = GetCBVsFromBufferViews(bufferViews);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
AZ_Assert(false, "Unhandled D3D12_DESCRIPTOR_RANGE_TYPE enumeration");
|
||||
break;
|
||||
}
|
||||
UpdateDescriptorTableRange(descriptorTable, descriptorHandles, bufferInputIndex);
|
||||
|
||||
UpdateDescriptorTableRange(descriptorTable, descriptorHandles, bufferInputIndex);
|
||||
++shaderInputIndex;
|
||||
}
|
||||
|
||||
@@ -297,23 +316,24 @@ namespace AZ
|
||||
AZStd::vector<DescriptorHandle> descriptorHandles;
|
||||
switch (descriptorRangeType)
|
||||
{
|
||||
case D3D12_DESCRIPTOR_RANGE_TYPE_SRV:
|
||||
{
|
||||
descriptorHandles = GetSRVsFromImageViews<RHI::ImageView, ImageView>(imageViews, ConvertSRVDimension(shaderInputImage.m_type));
|
||||
break;
|
||||
}
|
||||
case D3D12_DESCRIPTOR_RANGE_TYPE_UAV:
|
||||
{
|
||||
descriptorHandles = GetUAVsFromImageViews<RHI::ImageView, ImageView>(imageViews, ConvertUAVDimension(shaderInputImage.m_type));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
case D3D12_DESCRIPTOR_RANGE_TYPE_SRV:
|
||||
{
|
||||
descriptorHandles =
|
||||
GetSRVsFromImageViews<RHI::ImageView, ImageView>(imageViews, ConvertSRVDimension(shaderInputImage.m_type));
|
||||
break;
|
||||
}
|
||||
case D3D12_DESCRIPTOR_RANGE_TYPE_UAV:
|
||||
{
|
||||
descriptorHandles =
|
||||
GetUAVsFromImageViews<RHI::ImageView, ImageView>(imageViews, ConvertUAVDimension(shaderInputImage.m_type));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
AZ_Assert(false, "Unhandled D3D12_DESCRIPTOR_RANGE_TYPE enumeration");
|
||||
break;
|
||||
}
|
||||
|
||||
UpdateDescriptorTableRange(descriptorTable, descriptorHandles, imageInputIndex);
|
||||
|
||||
++shaderInputIndex;
|
||||
}
|
||||
}
|
||||
@@ -334,7 +354,7 @@ namespace AZ
|
||||
void ShaderResourceGroupPool::UpdateUnboundedArrayDescriptorTables(ShaderResourceGroup& group, const RHI::ShaderResourceGroupData& groupData)
|
||||
{
|
||||
const RHI::ShaderResourceGroupLayout& groupLayout = *groupData.GetLayout();
|
||||
|
||||
auto& device = static_cast<Device&>(GetDevice());
|
||||
uint32_t shaderInputIndex = 0;
|
||||
|
||||
// process buffer unbounded arrays
|
||||
@@ -350,50 +370,30 @@ namespace AZ
|
||||
{
|
||||
if (group.m_unboundedDescriptorTables[tableIndex].IsValid())
|
||||
{
|
||||
m_descriptorContext->ReleaseDescriptorTable(group.m_unboundedDescriptorTables[tableIndex]);
|
||||
m_descriptorContext->ReleaseDescriptorTable(group.m_unboundedDescriptorTables[tableIndex], &group);
|
||||
group.m_unboundedDescriptorTables[tableIndex] = DescriptorTable{};
|
||||
}
|
||||
|
||||
if (!bufferViews.empty())
|
||||
{
|
||||
group.m_unboundedDescriptorTables[tableIndex] = m_descriptorContext->CreateDescriptorTable(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, static_cast<uint32_t>(bufferViews.size()));
|
||||
AZ_Assert(group.m_unboundedDescriptorTables[tableIndex].IsValid(), "Descriptor context failed to allocate unbounded array descriptor table, most likely out of memory.");
|
||||
group.m_unboundedDescriptorTables[tableIndex] = m_descriptorContext->CreateDescriptorTable(
|
||||
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, static_cast<uint32_t>(bufferViews.size()), &group);
|
||||
|
||||
if (!group.m_unboundedDescriptorTables[tableIndex].IsValid())
|
||||
{
|
||||
// We have support for compacting D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV (if applicable) so try that.
|
||||
device.DescriptorHeapCompactionNeeded();
|
||||
return;
|
||||
}
|
||||
|
||||
ShaderResourceGroupCompiledData& compiledData = group.m_compiledData[group.m_compiledDataIndex];
|
||||
compiledData.m_gpuUnboundedArraysDescriptorHandles[shaderInputIndex] = m_descriptorContext->GetGpuPlatformHandle(group.m_unboundedDescriptorTables[tableIndex].GetOffset());
|
||||
compiledData.m_gpuUnboundedArraysDescriptorHandles[shaderInputIndex] = m_descriptorContext->GetGpuPlatformHandleForTable(group.m_unboundedDescriptorTables[tableIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
++shaderInputIndex;
|
||||
|
||||
if (bufferViews.empty())
|
||||
{
|
||||
// we don't need to update descriptors since the buffer list is empty
|
||||
continue;
|
||||
}
|
||||
|
||||
D3D12_DESCRIPTOR_RANGE_TYPE descriptorRangeType = ConvertShaderInputBufferAccess(shaderInputBufferUnboundedArray.m_access);
|
||||
|
||||
AZStd::vector<DescriptorHandle> descriptorHandles;
|
||||
switch (descriptorRangeType)
|
||||
{
|
||||
case D3D12_DESCRIPTOR_RANGE_TYPE_SRV:
|
||||
{
|
||||
descriptorHandles = GetSRVsFromImageViews<RHI::BufferView, BufferView>(bufferViews, D3D12_SRV_DIMENSION_BUFFER);
|
||||
break;
|
||||
}
|
||||
case D3D12_DESCRIPTOR_RANGE_TYPE_UAV:
|
||||
{
|
||||
descriptorHandles = GetUAVsFromImageViews<RHI::BufferView, BufferView>(bufferViews, D3D12_UAV_DIMENSION_BUFFER);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
AZ_Assert(false, "Unhandled D3D12_DESCRIPTOR_RANGE_TYPE enumeration");
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
const DescriptorTable descriptorTable(group.m_unboundedDescriptorTables[tableIndex].GetOffset(), static_cast<uint16_t>(bufferViews.size()));
|
||||
m_descriptorContext->UpdateDescriptorTableRange(descriptorTable, descriptorHandles.data(), D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
|
||||
UpdateUnboundedBuffersDescTable(descriptorTable, groupData, shaderInputIndex, shaderInputBufferUnboundedArray.m_access);
|
||||
++shaderInputIndex;
|
||||
}
|
||||
|
||||
// process image unbounded arrays
|
||||
@@ -407,55 +407,223 @@ namespace AZ
|
||||
// resize the descriptor table allocation if necessary
|
||||
if (group.m_unboundedDescriptorTables[tableIndex].GetSize() != imageViews.size())
|
||||
{
|
||||
|
||||
if (group.m_unboundedDescriptorTables[tableIndex].IsValid())
|
||||
{
|
||||
m_descriptorContext->ReleaseDescriptorTable(group.m_unboundedDescriptorTables[tableIndex]);
|
||||
m_descriptorContext->ReleaseDescriptorTable(group.m_unboundedDescriptorTables[tableIndex], &group);
|
||||
group.m_unboundedDescriptorTables[tableIndex] = DescriptorTable{};
|
||||
}
|
||||
|
||||
if (!imageViews.empty())
|
||||
{
|
||||
group.m_unboundedDescriptorTables[tableIndex] = m_descriptorContext->CreateDescriptorTable(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, static_cast<uint32_t>(imageViews.size()));
|
||||
AZ_Assert(group.m_unboundedDescriptorTables[tableIndex].IsValid(), "Descriptor context failed to allocate unbounded array descriptor table, most likely out of memory.");
|
||||
group.m_unboundedDescriptorTables[tableIndex] = m_descriptorContext->CreateDescriptorTable(
|
||||
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, static_cast<uint32_t>(imageViews.size()), &group);
|
||||
|
||||
if (!group.m_unboundedDescriptorTables[tableIndex].IsValid())
|
||||
{
|
||||
// We have support for compacting D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV (if applicable) so try that
|
||||
device.DescriptorHeapCompactionNeeded();
|
||||
return;
|
||||
}
|
||||
|
||||
ShaderResourceGroupCompiledData& compiledData = group.m_compiledData[group.m_compiledDataIndex];
|
||||
compiledData.m_gpuUnboundedArraysDescriptorHandles[shaderInputIndex] = m_descriptorContext->GetGpuPlatformHandle(group.m_unboundedDescriptorTables[tableIndex].GetOffset());
|
||||
compiledData.m_gpuUnboundedArraysDescriptorHandles[shaderInputIndex] = m_descriptorContext->GetGpuPlatformHandleForTable(group.m_unboundedDescriptorTables[tableIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
++shaderInputIndex;
|
||||
|
||||
if (imageViews.empty())
|
||||
{
|
||||
// we don't need to update descriptors since the image list is empty
|
||||
continue;
|
||||
}
|
||||
|
||||
D3D12_DESCRIPTOR_RANGE_TYPE descriptorRangeType = ConvertShaderInputImageAccess(shaderInputImageUnboundedArray.m_access);
|
||||
|
||||
AZStd::vector<DescriptorHandle> descriptorHandles;
|
||||
switch (descriptorRangeType)
|
||||
{
|
||||
case D3D12_DESCRIPTOR_RANGE_TYPE_SRV:
|
||||
{
|
||||
descriptorHandles = GetSRVsFromImageViews<RHI::ImageView, ImageView>(imageViews, ConvertSRVDimension(shaderInputImageUnboundedArray.m_type));
|
||||
break;
|
||||
}
|
||||
case D3D12_DESCRIPTOR_RANGE_TYPE_UAV:
|
||||
{
|
||||
descriptorHandles = GetUAVsFromImageViews<RHI::ImageView, ImageView>(imageViews, ConvertUAVDimension(shaderInputImageUnboundedArray.m_type));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
AZ_Assert(false, "Unhandled D3D12_DESCRIPTOR_RANGE_TYPE enumeration");
|
||||
break;
|
||||
}
|
||||
|
||||
const DescriptorTable descriptorTable(group.m_unboundedDescriptorTables[tableIndex].GetOffset(), static_cast<uint16_t>(imageViews.size()));
|
||||
m_descriptorContext->UpdateDescriptorTableRange(descriptorTable, descriptorHandles.data(), D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
|
||||
UpdateUnboundedImagesDescTable(descriptorTable, groupData, shaderInputIndex, shaderInputImageUnboundedArray.m_access, shaderInputImageUnboundedArray.m_type);
|
||||
++shaderInputIndex;
|
||||
}
|
||||
}
|
||||
|
||||
void ShaderResourceGroupPool::UpdateUnboundedBuffersDescTable(
|
||||
DescriptorTable descriptorTable,
|
||||
const RHI::ShaderResourceGroupData& groupData,
|
||||
uint32_t shaderInputIndex,
|
||||
RHI::ShaderInputBufferAccess bufferAccess)
|
||||
{
|
||||
const RHI::ShaderInputBufferUnboundedArrayIndex bufferUnboundedArrayInputIndex(shaderInputIndex);
|
||||
AZStd::array_view<RHI::ConstPtr<RHI::BufferView>> bufferViews =
|
||||
groupData.GetBufferViewUnboundedArray(bufferUnboundedArrayInputIndex);
|
||||
|
||||
if (bufferViews.empty())
|
||||
{
|
||||
// we don't need to update descriptors since the buffer list is empty
|
||||
return;
|
||||
}
|
||||
|
||||
D3D12_DESCRIPTOR_RANGE_TYPE descriptorRangeType = ConvertShaderInputBufferAccess(bufferAccess);
|
||||
|
||||
AZStd::vector<DescriptorHandle> descriptorHandles;
|
||||
switch (descriptorRangeType)
|
||||
{
|
||||
case D3D12_DESCRIPTOR_RANGE_TYPE_SRV:
|
||||
{
|
||||
descriptorHandles = GetSRVsFromImageViews<RHI::BufferView, BufferView>(bufferViews, D3D12_SRV_DIMENSION_BUFFER);
|
||||
break;
|
||||
}
|
||||
case D3D12_DESCRIPTOR_RANGE_TYPE_UAV:
|
||||
{
|
||||
descriptorHandles = GetUAVsFromImageViews<RHI::BufferView, BufferView>(bufferViews, D3D12_UAV_DIMENSION_BUFFER);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
AZ_Assert(false, "Unhandled D3D12_DESCRIPTOR_RANGE_TYPE enumeration");
|
||||
break;
|
||||
}
|
||||
|
||||
m_descriptorContext->UpdateDescriptorTableRange(
|
||||
descriptorTable, descriptorHandles.data(), D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
|
||||
}
|
||||
|
||||
void ShaderResourceGroupPool::UpdateUnboundedImagesDescTable(
|
||||
DescriptorTable descriptorTable,
|
||||
const RHI::ShaderResourceGroupData& groupData,
|
||||
uint32_t shaderInputIndex,
|
||||
RHI::ShaderInputImageAccess imageAccess,
|
||||
RHI::ShaderInputImageType imageType)
|
||||
{
|
||||
const RHI::ShaderInputImageUnboundedArrayIndex imageUnboundedArrayInputIndex(shaderInputIndex);
|
||||
AZStd::array_view<RHI::ConstPtr<RHI::ImageView>> imageViews =
|
||||
groupData.GetImageViewUnboundedArray(imageUnboundedArrayInputIndex);
|
||||
|
||||
if (imageViews.empty())
|
||||
{
|
||||
// we don't need to update descriptors since the image list is empty
|
||||
return;
|
||||
}
|
||||
|
||||
D3D12_DESCRIPTOR_RANGE_TYPE descriptorRangeType = ConvertShaderInputImageAccess(imageAccess);
|
||||
|
||||
AZStd::vector<DescriptorHandle> descriptorHandles;
|
||||
switch (descriptorRangeType)
|
||||
{
|
||||
case D3D12_DESCRIPTOR_RANGE_TYPE_SRV:
|
||||
{
|
||||
descriptorHandles = GetSRVsFromImageViews<RHI::ImageView, ImageView>(imageViews, ConvertSRVDimension(imageType));
|
||||
break;
|
||||
}
|
||||
case D3D12_DESCRIPTOR_RANGE_TYPE_UAV:
|
||||
{
|
||||
descriptorHandles = GetUAVsFromImageViews<RHI::ImageView, ImageView>(imageViews, ConvertUAVDimension(imageType));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
AZ_Assert(false, "Unhandled D3D12_DESCRIPTOR_RANGE_TYPE enumeration");
|
||||
break;
|
||||
}
|
||||
|
||||
m_descriptorContext->UpdateDescriptorTableRange(
|
||||
descriptorTable, descriptorHandles.data(), D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
|
||||
}
|
||||
|
||||
RHI::ResultCode ShaderResourceGroupPool::UpdateDescriptorTableAfterCompaction(
|
||||
RHI::ShaderResourceGroup& groupBase, const RHI::ShaderResourceGroupData& groupData)
|
||||
{
|
||||
// Since we are trying to compact we will re-create all the descriptor tables and re-update them all
|
||||
ShaderResourceGroup& group = static_cast<ShaderResourceGroup&>(groupBase);
|
||||
|
||||
if (m_viewsDescriptorTableSize)
|
||||
{
|
||||
group.m_viewsDescriptorTable = m_descriptorContext->CreateDescriptorTable(
|
||||
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, m_viewsDescriptorTableRingSize, &group);
|
||||
|
||||
if (!group.m_viewsDescriptorTable.IsValid())
|
||||
{
|
||||
AZ_Assert(
|
||||
false,
|
||||
"Descriptor heap ran out of memory. Please consider increasing number of handles allowed for the second value"
|
||||
"of DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV within platformlimits.azasset file for dx12.");
|
||||
return RHI::ResultCode::OutOfMemory;
|
||||
}
|
||||
|
||||
CacheGpuHandlesForViews(group);
|
||||
|
||||
const DescriptorTable descriptorTable(
|
||||
group.m_viewsDescriptorTable.GetOffset() + group.m_compiledDataIndex * m_viewsDescriptorTableSize,
|
||||
static_cast<uint16_t>(m_viewsDescriptorTableSize));
|
||||
|
||||
UpdateViewsDescriptorTable(descriptorTable, groupData);
|
||||
}
|
||||
|
||||
if (m_unboundedArrayCount)
|
||||
{
|
||||
//Reset all the old descriptor tables as the previous heap is gone.
|
||||
for (uint32_t unboundedArrayindex = 0; unboundedArrayindex < (ShaderResourceGroupCompiledData::MaxUnboundedArrays * RHI::Limits::Device::FrameCountMax); ++unboundedArrayindex)
|
||||
{
|
||||
group.m_unboundedDescriptorTables[unboundedArrayindex] = DescriptorTable{};
|
||||
}
|
||||
|
||||
const RHI::ShaderResourceGroupLayout& groupLayout = *groupData.GetLayout();
|
||||
uint32_t shaderInputIndex = 0;
|
||||
|
||||
// process buffer unbounded arrays
|
||||
for (const RHI::ShaderInputBufferUnboundedArrayDescriptor& shaderInputBufferUnboundedArray : groupLayout.GetShaderInputListForBufferUnboundedArrays())
|
||||
{
|
||||
const RHI::ShaderInputBufferUnboundedArrayIndex bufferUnboundedArrayInputIndex(shaderInputIndex);
|
||||
AZStd::array_view<RHI::ConstPtr<RHI::BufferView>> bufferViews = groupData.GetBufferViewUnboundedArray(bufferUnboundedArrayInputIndex);
|
||||
|
||||
uint32_t tableIndex = shaderInputIndex * RHI::Limits::Device::FrameCountMax + group.m_compiledDataIndex;
|
||||
if (!bufferViews.empty())
|
||||
{
|
||||
group.m_unboundedDescriptorTables[tableIndex] = m_descriptorContext->CreateDescriptorTable(
|
||||
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, static_cast<uint32_t>(bufferViews.size()), &group);
|
||||
|
||||
if (!group.m_unboundedDescriptorTables[tableIndex].IsValid())
|
||||
{
|
||||
AZ_Assert(
|
||||
false,
|
||||
"Descriptor heap ran out of memory. Please consider increasing number of handles allowed for the second value"
|
||||
"of DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV within platformlimits.azasset file for dx12.");
|
||||
return RHI::ResultCode::OutOfMemory;
|
||||
}
|
||||
|
||||
ShaderResourceGroupCompiledData& compiledData = group.m_compiledData[group.m_compiledDataIndex];
|
||||
compiledData.m_gpuUnboundedArraysDescriptorHandles[shaderInputIndex] = m_descriptorContext->GetGpuPlatformHandleForTable(group.m_unboundedDescriptorTables[tableIndex]);
|
||||
|
||||
const DescriptorTable descriptorTable(
|
||||
group.m_unboundedDescriptorTables[tableIndex].GetOffset(), static_cast<uint16_t>(bufferViews.size()));
|
||||
UpdateUnboundedBuffersDescTable(descriptorTable, groupData, shaderInputIndex, shaderInputBufferUnboundedArray.m_access);
|
||||
}
|
||||
shaderInputIndex++;
|
||||
}
|
||||
|
||||
// process image unbounded arrays
|
||||
for (const RHI::ShaderInputImageUnboundedArrayDescriptor& shaderInputImageUnboundedArray :
|
||||
groupLayout.GetShaderInputListForImageUnboundedArrays())
|
||||
{
|
||||
const RHI::ShaderInputImageUnboundedArrayIndex imageUnboundedArrayInputIndex(shaderInputIndex);
|
||||
AZStd::array_view<RHI::ConstPtr<RHI::ImageView>> imageViews =
|
||||
groupData.GetImageViewUnboundedArray(imageUnboundedArrayInputIndex);
|
||||
|
||||
uint32_t tableIndex = shaderInputIndex * RHI::Limits::Device::FrameCountMax + group.m_compiledDataIndex;
|
||||
if (!imageViews.empty())
|
||||
{
|
||||
group.m_unboundedDescriptorTables[tableIndex] = m_descriptorContext->CreateDescriptorTable(
|
||||
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, static_cast<uint32_t>(imageViews.size()), &group);
|
||||
|
||||
if (!group.m_unboundedDescriptorTables[tableIndex].IsValid())
|
||||
{
|
||||
AZ_Assert(
|
||||
false,
|
||||
"Descriptor heap ran out of memory. Please consider increasing number of handles allowed for the second value"
|
||||
"of DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV within platformlimits.azasset file for dx12.");
|
||||
return RHI::ResultCode::OutOfMemory;
|
||||
}
|
||||
|
||||
ShaderResourceGroupCompiledData& compiledData = group.m_compiledData[group.m_compiledDataIndex];
|
||||
compiledData.m_gpuUnboundedArraysDescriptorHandles[shaderInputIndex] = m_descriptorContext->GetGpuPlatformHandleForTable(group.m_unboundedDescriptorTables[tableIndex]);
|
||||
|
||||
const DescriptorTable descriptorTable(group.m_unboundedDescriptorTables[tableIndex].GetOffset(), static_cast<uint16_t>(imageViews.size()));
|
||||
UpdateUnboundedImagesDescTable(descriptorTable, groupData, shaderInputIndex, shaderInputImageUnboundedArray.m_access, shaderInputImageUnboundedArray.m_type);
|
||||
}
|
||||
shaderInputIndex++;
|
||||
}
|
||||
}
|
||||
return RHI::ResultCode::Success;
|
||||
}
|
||||
|
||||
void ShaderResourceGroupPool::OnFrameEnd()
|
||||
{
|
||||
m_constantAllocator.GarbageCollect();
|
||||
|
||||
@@ -30,6 +30,9 @@ namespace AZ
|
||||
|
||||
static RHI::Ptr<ShaderResourceGroupPool> Create();
|
||||
|
||||
//! Re-Update the descriptor tables for all the cbv/srv/uav views (direct and via unbounded array)
|
||||
RHI::ResultCode UpdateDescriptorTableAfterCompaction(RHI::ShaderResourceGroup& groupBase, const RHI::ShaderResourceGroupData& groupData);
|
||||
|
||||
private:
|
||||
ShaderResourceGroupPool() = default;
|
||||
|
||||
@@ -51,6 +54,21 @@ namespace AZ
|
||||
void UpdateSamplersDescriptorTable(DescriptorTable descriptorTable, const RHI::ShaderResourceGroupData& groupData);
|
||||
void UpdateUnboundedArrayDescriptorTables(ShaderResourceGroup& group, const RHI::ShaderResourceGroupData& groupData);
|
||||
|
||||
//! Update all the buffer views for the unbounded array
|
||||
void UpdateUnboundedBuffersDescTable(
|
||||
DescriptorTable descriptorTable,
|
||||
const RHI::ShaderResourceGroupData& groupData,
|
||||
uint32_t shaderInputIndex,
|
||||
RHI::ShaderInputBufferAccess bufferAccess);
|
||||
|
||||
//! Update all the image views for the unbounded array
|
||||
void UpdateUnboundedImagesDescTable(
|
||||
DescriptorTable descriptorTable,
|
||||
const RHI::ShaderResourceGroupData& groupData,
|
||||
uint32_t shaderInputIndex,
|
||||
RHI::ShaderInputImageAccess imageAccess,
|
||||
RHI::ShaderInputImageType imageType);
|
||||
|
||||
void UpdateDescriptorTableRange(
|
||||
DescriptorTable descriptorTable,
|
||||
const AZStd::vector<DescriptorHandle>& descriptors,
|
||||
@@ -66,6 +84,9 @@ namespace AZ
|
||||
RHI::ShaderInputSamplerIndex samplerIndex,
|
||||
AZStd::array_view<RHI::SamplerState> samplerStates);
|
||||
|
||||
//Cache all the gpu handles for the Descriptor tables related to all the views
|
||||
void CacheGpuHandlesForViews(ShaderResourceGroup& group);
|
||||
|
||||
DescriptorTable GetBufferTable(DescriptorTable descriptorTable, RHI::ShaderInputBufferIndex bufferIndex) const;
|
||||
DescriptorTable GetBufferTableUnbounded(DescriptorTable descriptorTable, RHI::ShaderInputBufferIndex bufferIndex) const;
|
||||
DescriptorTable GetImageTable(DescriptorTable descriptorTable, RHI::ShaderInputImageIndex imageIndex) const;
|
||||
@@ -79,7 +100,6 @@ namespace AZ
|
||||
|
||||
AZStd::vector<DescriptorHandle> GetCBVsFromBufferViews(const AZStd::array_view<RHI::ConstPtr<RHI::BufferView>>& bufferViews);
|
||||
|
||||
AZStd::mutex m_constantAllocatorMutex;
|
||||
MemoryPoolSubAllocator m_constantAllocator;
|
||||
DescriptorContext* m_descriptorContext = nullptr;
|
||||
uint32_t m_constantBufferSize = 0;
|
||||
|
||||
@@ -21,11 +21,13 @@
|
||||
"$type": "AZ::DX12::PlatformLimitsDescriptor",
|
||||
"DescriptorHeapLimits":
|
||||
{
|
||||
"DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV": [1000000, 1000000],
|
||||
"DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV": [100000, 1000000],
|
||||
"DESCRIPTOR_HEAP_TYPE_SAMPLER": [2048, 2048],
|
||||
"DESCRIPTOR_HEAP_TYPE_RTV": [2048, 0],
|
||||
"DESCRIPTOR_HEAP_TYPE_DSV": [2048, 0]
|
||||
}
|
||||
},
|
||||
"NumShaderVisibleCbvSrvUavStaticHandles": 2000,
|
||||
"AllowDescriptorHeapCompaction": false
|
||||
},
|
||||
"vulkan":
|
||||
{
|
||||
|
||||
@@ -10,6 +10,10 @@
|
||||
#include <RHI/Instance.h>
|
||||
#include <RHI/WSISurface.h>
|
||||
|
||||
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
#include <AzFramework/XcbConnectionManager.h>
|
||||
#endif
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace Vulkan
|
||||
@@ -21,7 +25,7 @@ namespace AZ
|
||||
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
|
||||
xcb_connection_t* xcb_connection = nullptr;
|
||||
if (auto xcbConnectionManager = AzFramework::LinuxXcbConnectionManagerInterface::Get();
|
||||
if (auto xcbConnectionManager = AzFramework::XcbConnectionManagerInterface::Get();
|
||||
xcbConnectionManager != nullptr)
|
||||
{
|
||||
xcb_connection = xcbConnectionManager->GetXcbConnection();
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace AZ
|
||||
//! by ShaderVariantAssetBuilder this is 1+.
|
||||
static uint32_t MakeAssetProductSubId(
|
||||
uint32_t rhiApiUniqueIndex, uint32_t supervariantIndex, ShaderVariantStableId variantStableId,
|
||||
uint32_t subProductType = ShaderVariantAssetSubProductType);
|
||||
uint32_t subProductType = 0);
|
||||
|
||||
ShaderVariantAsset() = default;
|
||||
~ShaderVariantAsset() = default;
|
||||
|
||||
@@ -51,11 +51,11 @@ set(FILES
|
||||
Include/Multiplayer/NetworkTime/RewindableObject.inl
|
||||
Include/Multiplayer/Physics/PhysicsUtils.h
|
||||
Include/Multiplayer/ReplicationWindows/IReplicationWindow.h
|
||||
Source/AutoGen/AutoComponentTypes_Header.jinja
|
||||
Source/AutoGen/AutoComponentTypes_Source.jinja
|
||||
Source/AutoGen/AutoComponent_Common.jinja
|
||||
Source/AutoGen/AutoComponent_Header.jinja
|
||||
Source/AutoGen/AutoComponent_Source.jinja
|
||||
Include/Multiplayer/AutoGen/AutoComponentTypes_Header.jinja
|
||||
Include/Multiplayer/AutoGen/AutoComponentTypes_Source.jinja
|
||||
Include/Multiplayer/AutoGen/AutoComponent_Common.jinja
|
||||
Include/Multiplayer/AutoGen/AutoComponent_Header.jinja
|
||||
Include/Multiplayer/AutoGen/AutoComponent_Source.jinja
|
||||
Source/AutoGen/LocalPredictionPlayerInputComponent.AutoComponent.xml
|
||||
Source/AutoGen/Multiplayer.AutoPackets.xml
|
||||
Source/AutoGen/MultiplayerEditor.AutoPackets.xml
|
||||
|
||||
@@ -652,8 +652,13 @@ namespace ScriptCanvas
|
||||
return {};
|
||||
}
|
||||
|
||||
bool Method::GetBehaviorContextClassMethod(const AZStd::string&, const AZ::BehaviorClass*& outClass, const AZ::BehaviorMethod*& outMethod, EventType& outType) const
|
||||
bool Method::GetBehaviorContextClassMethod(const AZ::BehaviorClass*& outClass, const AZ::BehaviorMethod*& outMethod, EventType& outType) const
|
||||
{
|
||||
if (m_lookupName.empty() && m_className.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
AZStd::string prettyClassName;
|
||||
AZStd::string methodName = m_lookupName;
|
||||
|
||||
@@ -749,15 +754,14 @@ namespace ScriptCanvas
|
||||
AZStd::tuple<const AZ::BehaviorMethod*, MethodType, EventType, const AZ::BehaviorClass*> Method::LookupMethod() const
|
||||
{
|
||||
using TupleType = AZStd::tuple<const AZ::BehaviorMethod*, MethodType, EventType, const AZ::BehaviorClass*>;
|
||||
AZStd::string methodName = m_lookupName;
|
||||
|
||||
|
||||
AZStd::string prettyClassName;
|
||||
|
||||
const AZ::BehaviorClass* bcClass{};
|
||||
const AZ::BehaviorMethod* method{};
|
||||
EventType eventType;
|
||||
|
||||
if (GetBehaviorContextClassMethod(m_lookupName, bcClass, method, eventType))
|
||||
if (GetBehaviorContextClassMethod(bcClass, method, eventType))
|
||||
{
|
||||
return TupleType{ method, m_methodType, eventType, bcClass };
|
||||
}
|
||||
@@ -776,7 +780,7 @@ namespace ScriptCanvas
|
||||
const AZ::BehaviorMethod* method{};
|
||||
EventType eventType;
|
||||
|
||||
if (GetBehaviorContextClassMethod(m_lookupName, bcClass, method, eventType))
|
||||
if (GetBehaviorContextClassMethod(bcClass, method, eventType))
|
||||
{
|
||||
m_eventType = eventType;
|
||||
ConfigureMethod(*method, bcClass);
|
||||
|
||||
@@ -168,7 +168,7 @@ namespace ScriptCanvas
|
||||
|
||||
AZ_INLINE void SetWarnOnMissingFunction(bool enabled) { m_warnOnMissingFunction = enabled; }
|
||||
|
||||
bool GetBehaviorContextClassMethod(const AZStd::string& name, const AZ::BehaviorClass*& outClass, const AZ::BehaviorMethod*& outMethod, EventType& outType) const;
|
||||
bool GetBehaviorContextClassMethod(const AZ::BehaviorClass*& outClass, const AZ::BehaviorMethod*& outMethod, EventType& outType) const;
|
||||
|
||||
private:
|
||||
friend struct ScriptCanvas::BehaviorContextMethodHelper;
|
||||
|
||||
@@ -13,8 +13,6 @@
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/Serialization/EditContextConstants.inl>
|
||||
|
||||
#include <Atom/RPI.Public/FeatureProcessorFactory.h>
|
||||
#include <TerrainRenderer/TerrainFeatureProcessor.h>
|
||||
#include <TerrainSystem/TerrainSystem.h>
|
||||
|
||||
namespace Terrain
|
||||
@@ -34,8 +32,6 @@ namespace Terrain
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
;
|
||||
}
|
||||
|
||||
Terrain::TerrainFeatureProcessor::Reflect(context);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,9 +45,8 @@ namespace Terrain
|
||||
incompatible.push_back(AZ_CRC_CE("TerrainService"));
|
||||
}
|
||||
|
||||
void TerrainSystemComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
|
||||
void TerrainSystemComponent::GetRequiredServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& required)
|
||||
{
|
||||
required.push_back(AZ_CRC_CE("RPISystem"));
|
||||
}
|
||||
|
||||
void TerrainSystemComponent::GetDependentServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& dependent)
|
||||
@@ -68,14 +63,11 @@ namespace Terrain
|
||||
// every time an entity is added or removed to a level. If this ever changes, the Terrain System ownership could move into
|
||||
// the level component.
|
||||
m_terrainSystem = new TerrainSystem();
|
||||
AZ::RPI::FeatureProcessorFactory::Get()->RegisterFeatureProcessor<Terrain::TerrainFeatureProcessor>();
|
||||
}
|
||||
|
||||
void TerrainSystemComponent::Deactivate()
|
||||
{
|
||||
delete m_terrainSystem;
|
||||
m_terrainSystem = nullptr;
|
||||
|
||||
AZ::RPI::FeatureProcessorFactory::Get()->UnregisterFeatureProcessor<Terrain::TerrainFeatureProcessor>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,6 +95,8 @@ namespace Terrain
|
||||
AzFramework::EntityDebugDisplayEventBus::Handler::BusConnect(GetEntityId());
|
||||
AzFramework::BoundsRequestBus::Handler::BusConnect(GetEntityId());
|
||||
AzFramework::Terrain::TerrainDataNotificationBus::Handler::BusConnect();
|
||||
|
||||
RefreshCachedWireframeGrid(AZ::Aabb::CreateNull());
|
||||
}
|
||||
|
||||
void TerrainWorldDebuggerComponent::Deactivate()
|
||||
|
||||
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Components/TerrainWorldRendererComponent.h>
|
||||
#include <AzCore/Component/Entity.h>
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzFramework/Entity/GameEntityContextBus.h>
|
||||
|
||||
#include <SurfaceData/SurfaceDataSystemRequestBus.h>
|
||||
|
||||
#include <Atom/RPI.Public/Scene.h>
|
||||
#include <Atom/RPI.Public/FeatureProcessorFactory.h>
|
||||
#include <TerrainRenderer/TerrainFeatureProcessor.h>
|
||||
|
||||
namespace Terrain
|
||||
{
|
||||
void TerrainWorldRendererConfig::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
Terrain::TerrainFeatureProcessor::Reflect(context);
|
||||
|
||||
AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context);
|
||||
if (serialize)
|
||||
{
|
||||
serialize->Class<TerrainWorldRendererConfig, AZ::ComponentConfig>()->Version(1);
|
||||
|
||||
AZ::EditContext* edit = serialize->GetEditContext();
|
||||
if (edit)
|
||||
{
|
||||
edit->Class<TerrainWorldRendererConfig>("Terrain World Renderer Component", "Enables terrain rendering")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZStd::vector<AZ::Crc32>({ AZ_CRC_CE("Level") }))
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TerrainWorldRendererComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& services)
|
||||
{
|
||||
services.push_back(AZ_CRC_CE("TerrainRendererService"));
|
||||
}
|
||||
|
||||
void TerrainWorldRendererComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& services)
|
||||
{
|
||||
services.push_back(AZ_CRC_CE("TerrainRendererService"));
|
||||
}
|
||||
|
||||
void TerrainWorldRendererComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& services)
|
||||
{
|
||||
services.push_back(AZ_CRC_CE("TerrainService"));
|
||||
}
|
||||
|
||||
void TerrainWorldRendererComponent::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
TerrainWorldRendererConfig::Reflect(context);
|
||||
|
||||
AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context);
|
||||
if (serialize)
|
||||
{
|
||||
serialize->Class<TerrainWorldRendererComponent, AZ::Component>()->Version(0)->Field(
|
||||
"Configuration", &TerrainWorldRendererComponent::m_configuration);
|
||||
}
|
||||
}
|
||||
|
||||
TerrainWorldRendererComponent::TerrainWorldRendererComponent(const TerrainWorldRendererConfig& configuration)
|
||||
: m_configuration(configuration)
|
||||
{
|
||||
}
|
||||
|
||||
TerrainWorldRendererComponent::~TerrainWorldRendererComponent()
|
||||
{
|
||||
if (m_terrainRendererActive)
|
||||
{
|
||||
Deactivate();
|
||||
}
|
||||
}
|
||||
|
||||
AZ::RPI::Scene* TerrainWorldRendererComponent::GetScene() const
|
||||
{
|
||||
// Find the entity context for the entity ID.
|
||||
AzFramework::EntityContextId entityContextId = AzFramework::EntityContextId::CreateNull();
|
||||
AzFramework::EntityIdContextQueryBus::EventResult(
|
||||
entityContextId, GetEntityId(), &AzFramework::EntityIdContextQueryBus::Events::GetOwningContextId);
|
||||
|
||||
return AZ::RPI::Scene::GetSceneForEntityContextId(entityContextId);
|
||||
}
|
||||
|
||||
void TerrainWorldRendererComponent::Activate()
|
||||
{
|
||||
// On component activation, register the terrain feature processor with Atom and the scene related to this entity context.
|
||||
|
||||
AZ::RPI::FeatureProcessorFactory::Get()->RegisterFeatureProcessor<Terrain::TerrainFeatureProcessor>();
|
||||
|
||||
if (AZ::RPI::Scene* scene = GetScene(); scene)
|
||||
{
|
||||
m_terrainFeatureProcessor = scene->EnableFeatureProcessor<Terrain::TerrainFeatureProcessor>();
|
||||
}
|
||||
|
||||
AzFramework::Terrain::TerrainDataNotificationBus::Handler::BusConnect();
|
||||
m_terrainRendererActive = true;
|
||||
}
|
||||
|
||||
void TerrainWorldRendererComponent::Deactivate()
|
||||
{
|
||||
// On component deactivation, unregister the feature processor and remove it from the default scene.
|
||||
|
||||
m_terrainRendererActive = false;
|
||||
AzFramework::Terrain::TerrainDataNotificationBus::Handler::BusDisconnect();
|
||||
|
||||
if (AZ::RPI::Scene* scene = GetScene(); scene)
|
||||
{
|
||||
if (scene->GetFeatureProcessor<Terrain::TerrainFeatureProcessor>())
|
||||
{
|
||||
scene->DisableFeatureProcessor<Terrain::TerrainFeatureProcessor>();
|
||||
}
|
||||
}
|
||||
m_terrainFeatureProcessor = nullptr;
|
||||
|
||||
AZ::RPI::FeatureProcessorFactory::Get()->UnregisterFeatureProcessor<Terrain::TerrainFeatureProcessor>();
|
||||
}
|
||||
|
||||
bool TerrainWorldRendererComponent::ReadInConfig(const AZ::ComponentConfig* baseConfig)
|
||||
{
|
||||
if (auto config = azrtti_cast<const TerrainWorldRendererConfig*>(baseConfig))
|
||||
{
|
||||
m_configuration = *config;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TerrainWorldRendererComponent::WriteOutConfig(AZ::ComponentConfig* outBaseConfig) const
|
||||
{
|
||||
if (auto config = azrtti_cast<TerrainWorldRendererConfig*>(outBaseConfig))
|
||||
{
|
||||
*config = m_configuration;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void TerrainWorldRendererComponent::OnTerrainDataDestroyBegin()
|
||||
{
|
||||
// If the terrain is being destroyed, remove all existing terrain data from the feature processor.
|
||||
|
||||
if (m_terrainFeatureProcessor)
|
||||
{
|
||||
m_terrainFeatureProcessor->RemoveTerrainData();
|
||||
}
|
||||
}
|
||||
|
||||
void TerrainWorldRendererComponent::OnTerrainDataChanged([[maybe_unused]] const AZ::Aabb& dirtyRegion, [[maybe_unused]] TerrainDataChangedMask dataChangedMask)
|
||||
{
|
||||
// Block other threads from accessing the surface data bus while we are in GetValue (which may call into the SurfaceData bus).
|
||||
// We lock our surface data mutex *before* checking / setting "isRequestInProgress" so that we prevent race conditions
|
||||
// that create false detection of cyclic dependencies when multiple requests occur on different threads simultaneously.
|
||||
// (One case where this was previously able to occur was in rapid updating of the Preview widget on the
|
||||
// GradientSurfaceDataComponent in the Editor when moving the threshold sliders back and forth rapidly)
|
||||
auto& surfaceDataContext = SurfaceData::SurfaceDataSystemRequestBus::GetOrCreateContext(false);
|
||||
typename SurfaceData::SurfaceDataSystemRequestBus::Context::DispatchLockGuard scopeLock(surfaceDataContext.m_contextMutex);
|
||||
|
||||
AZ::Vector2 queryResolution = AZ::Vector2(1.0f);
|
||||
AzFramework::Terrain::TerrainDataRequestBus::BroadcastResult(
|
||||
queryResolution, &AzFramework::Terrain::TerrainDataRequests::GetTerrainHeightQueryResolution);
|
||||
|
||||
AZ::Aabb worldBounds = AZ::Aabb::CreateNull();
|
||||
AzFramework::Terrain::TerrainDataRequestBus::BroadcastResult(
|
||||
worldBounds, &AzFramework::Terrain::TerrainDataRequests::GetTerrainAabb);
|
||||
|
||||
|
||||
AZ::Transform transform = AZ::Transform::CreateTranslation(worldBounds.GetCenter());
|
||||
|
||||
uint32_t width = aznumeric_cast<uint32_t>(
|
||||
(float)worldBounds.GetXExtent() / queryResolution.GetX());
|
||||
uint32_t height = aznumeric_cast<uint32_t>(
|
||||
(float)worldBounds.GetYExtent() / queryResolution.GetY());
|
||||
AZStd::vector<float> pixels;
|
||||
pixels.resize_no_construct(width * height);
|
||||
const uint32_t pixelDataSize = width * height * sizeof(float);
|
||||
memset(pixels.data(), 0, pixelDataSize);
|
||||
|
||||
for (uint32_t y = 0; y < height; y++)
|
||||
{
|
||||
for (uint32_t x = 0; x < width; x++)
|
||||
{
|
||||
bool terrainExists = true;
|
||||
float terrainHeight = 0.0f;
|
||||
AzFramework::Terrain::TerrainDataRequestBus::BroadcastResult(
|
||||
terrainHeight, &AzFramework::Terrain::TerrainDataRequests::GetHeightFromFloats,
|
||||
(x * queryResolution.GetX()) + worldBounds.GetMin().GetX(),
|
||||
(y * queryResolution.GetY()) + worldBounds.GetMin().GetY(),
|
||||
AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT,
|
||||
&terrainExists);
|
||||
|
||||
pixels[(y * width) + x] =
|
||||
(terrainHeight - worldBounds.GetMin().GetZ()) / worldBounds.GetExtents().GetZ();
|
||||
}
|
||||
}
|
||||
|
||||
if (m_terrainFeatureProcessor)
|
||||
{
|
||||
m_terrainFeatureProcessor->UpdateTerrainData(transform, worldBounds, queryResolution.GetX(), width, height, pixels);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Component/Component.h>
|
||||
#include <AzCore/Math/Vector3.h>
|
||||
#include <TerrainSystem/TerrainSystem.h>
|
||||
|
||||
namespace LmbrCentral
|
||||
{
|
||||
template<typename, typename>
|
||||
class EditorWrappedComponentBase;
|
||||
}
|
||||
|
||||
namespace AZ::RPI
|
||||
{
|
||||
class Scene;
|
||||
}
|
||||
|
||||
namespace Terrain
|
||||
{
|
||||
class TerrainFeatureProcessor;
|
||||
|
||||
class TerrainWorldRendererConfig
|
||||
: public AZ::ComponentConfig
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(TerrainWorldRendererConfig, AZ::SystemAllocator, 0);
|
||||
AZ_RTTI(TerrainWorldRendererConfig, "{08C5863C-092D-4A69-8226-4978E4F6E343}", AZ::ComponentConfig);
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
};
|
||||
|
||||
|
||||
class TerrainWorldRendererComponent
|
||||
: public AZ::Component
|
||||
, public AzFramework::Terrain::TerrainDataNotificationBus::Handler
|
||||
{
|
||||
public:
|
||||
template<typename, typename>
|
||||
friend class LmbrCentral::EditorWrappedComponentBase;
|
||||
AZ_COMPONENT(TerrainWorldRendererComponent, "{3B0DB71E-5944-437C-8C88-70F8B405BFC7}");
|
||||
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& services);
|
||||
static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& services);
|
||||
static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& services);
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
TerrainWorldRendererComponent(const TerrainWorldRendererConfig& configuration);
|
||||
TerrainWorldRendererComponent() = default;
|
||||
~TerrainWorldRendererComponent() override;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// AZ::Component interface implementation
|
||||
void Activate() override;
|
||||
void Deactivate() override;
|
||||
bool ReadInConfig(const AZ::ComponentConfig* baseConfig) override;
|
||||
bool WriteOutConfig(AZ::ComponentConfig* outBaseConfig) const override;
|
||||
|
||||
protected:
|
||||
void OnTerrainDataDestroyBegin() override;
|
||||
void OnTerrainDataChanged(const AZ::Aabb& dirtyRegion, TerrainDataChangedMask dataChangedMask) override;
|
||||
|
||||
AZ::RPI::Scene* GetScene() const;
|
||||
|
||||
private:
|
||||
TerrainWorldRendererConfig m_configuration;
|
||||
bool m_terrainRendererActive{ false };
|
||||
TerrainFeatureProcessor* m_terrainFeatureProcessor{ nullptr };
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <EditorComponents/EditorTerrainWorldRendererComponent.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
|
||||
namespace Terrain
|
||||
{
|
||||
void EditorTerrainWorldRendererComponent::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
BaseClassType::Reflect(context);
|
||||
|
||||
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
|
||||
|
||||
if (serializeContext)
|
||||
{
|
||||
serializeContext->Class<EditorTerrainWorldRendererComponent, BaseClassType>()
|
||||
->Version(0)
|
||||
;
|
||||
|
||||
if (auto editContext = serializeContext->GetEditContext())
|
||||
{
|
||||
editContext->Class<EditorTerrainWorldRendererComponent>(
|
||||
"Terrain World Renderer", "")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::Category, "Terrain")
|
||||
->Attribute(AZ::Edit::Attributes::Icon, "Editor/Icons/Components/TerrainWorldRenderer.svg")
|
||||
->Attribute(AZ::Edit::Attributes::ViewportIcon, "Editor/Icons/Components/Viewport/TerrainWorldRenderer.svg")
|
||||
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZStd::vector<AZ::Crc32>({ AZ_CRC_CE("Level") }))
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void EditorTerrainWorldRendererComponent::Init()
|
||||
{
|
||||
BaseClassType::Init();
|
||||
}
|
||||
|
||||
void EditorTerrainWorldRendererComponent::Activate()
|
||||
{
|
||||
BaseClassType::Activate();
|
||||
}
|
||||
|
||||
AZ::u32 EditorTerrainWorldRendererComponent::ConfigurationChanged()
|
||||
{
|
||||
return BaseClassType::ConfigurationChanged();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Components/TerrainWorldRendererComponent.h>
|
||||
#include <AzToolsFramework/ToolsComponents/EditorComponentBase.h>
|
||||
#include <LmbrCentral/Component/EditorWrappedComponentBase.h>
|
||||
|
||||
namespace Terrain
|
||||
{
|
||||
class EditorTerrainWorldRendererComponent
|
||||
: public LmbrCentral::EditorWrappedComponentBase<TerrainWorldRendererComponent, TerrainWorldRendererConfig>
|
||||
{
|
||||
public:
|
||||
using BaseClassType = LmbrCentral::EditorWrappedComponentBase<TerrainWorldRendererComponent, TerrainWorldRendererConfig>;
|
||||
AZ_EDITOR_COMPONENT(EditorTerrainWorldRendererComponent, "{7BEFF763-89A6-4EDA-B199-B049A8E757AF}", BaseClassType);
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// AZ::Component interface implementation
|
||||
void Init() override;
|
||||
void Activate() override;
|
||||
AZ::u32 ConfigurationChanged() override;
|
||||
|
||||
protected:
|
||||
using BaseClassType::m_configuration;
|
||||
using BaseClassType::m_component;
|
||||
using BaseClassType::m_visible;
|
||||
|
||||
private:
|
||||
};
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user