From a0c29c666fe51aba6b6fee0b9b9fd3683829a880 Mon Sep 17 00:00:00 2001 From: mushgunAX Date: Fri, 23 Sep 2022 13:14:46 +0800 Subject: [PATCH 01/13] progress on input manager, near ready for PR --- .../src/Input/SHInputManagerSystem.cpp | 147 +++++ SHADE_Engine/src/Input/SHInputManagerSystem.h | 559 ++++++++++++++++++ 2 files changed, 706 insertions(+) create mode 100644 SHADE_Engine/src/Input/SHInputManagerSystem.cpp create mode 100644 SHADE_Engine/src/Input/SHInputManagerSystem.h diff --git a/SHADE_Engine/src/Input/SHInputManagerSystem.cpp b/SHADE_Engine/src/Input/SHInputManagerSystem.cpp new file mode 100644 index 00000000..d5e9bb3f --- /dev/null +++ b/SHADE_Engine/src/Input/SHInputManagerSystem.cpp @@ -0,0 +1,147 @@ +/********************************************************************* + * \file SHInputManagerSystem.cpp + * \author Ryan Wang Nian Jing + * \brief Definition of input manager. + * Handles input from keyboard and mouse. Soon to include controller. + * + * \copyright Copyright (c) 2022 DigiPen Institute of Technology. Reproduction + or disclosure of this file or its contents without the prior written + consent of DigiPen Institute of Technology is prohibited. + *********************************************************************/ + +#pragma once +#include "SHInputManagerSystem.h" + +namespace SHADE +{ + /*------------------------------------------------------------------------*/ + /* Static defines */ + /*------------------------------------------------------------------------*/ + + unsigned SHInputManagerSystem::keyCount = 0; + bool SHInputManagerSystem::keys[MAX_KEYS]; + bool SHInputManagerSystem::keysLast[MAX_KEYS]; + double SHInputManagerSystem::keysHeldTime[MAX_KEYS]; + double SHInputManagerSystem::keysReleasedTime[MAX_KEYS]; + + unsigned SHInputManagerSystem::keyToggleCount = 0; + bool SHInputManagerSystem::keysToggle[MAX_KEYS]; + bool SHInputManagerSystem::keysToggleLast[MAX_KEYS]; + double SHInputManagerSystem::keysToggleOnTime[MAX_KEYS]; + double SHInputManagerSystem::keysToggleOffTime[MAX_KEYS]; + + int SHInputManagerSystem::mouseScreenX = 0; + int SHInputManagerSystem::mouseScreenY = 0; + int SHInputManagerSystem::mouseScreenXLast = 0; + int SHInputManagerSystem::mouseScreenYLast = 0; + int SHInputManagerSystem::mouseWheelVerticalDelta = 0; + int SHInputManagerSystem::mouseWheelVerticalDeltaPoll = 0; + + void SHInputManagerSystem::InputManagerRoutine:: + FixedExecute(double dt) noexcept + { + //Keyboard and Mouse Buttons//////////////////////////////////////////////// + //Poll + unsigned char keyboardState[MAX_KEYS]; + GetKeyboardState(keyboardState); + keyCount = 0; + keyToggleCount = 0; + for (size_t i = 0; i < MAX_KEYS; ++i) + { + //Ignore shift, ctrl and alt since they are split to left and right + if (static_cast(i) == SH_KEYCODE::SHIFT || + static_cast(i) == SH_KEYCODE::CTRL || + static_cast(i) == SH_KEYCODE::ALT) + continue; + + //Pressed state + if (keyboardState[i] & 0b10000000) + { + ++keyCount; + keys[i] = true; + } + else keys[i] = false; + + //Toggle state + if (keyboardState[i] & 0b00000001) + { + ++keyToggleCount; + keysToggle[i] = true; + } + else keysToggle[i] = false; + } + + //Timers + for (size_t i = 0; i < MAX_KEYS; ++i) + { + if (keys[i]) //Key is down + { + if (!keysLast[i]) //Key was just pressed + { + keysHeldTime[i] = 0.0; //Reset timer + } + keysHeldTime[i] += dt; //Tick up + } + else //Key is up + { + if (keysLast[i]) //Key was just released + { + keysReleasedTime[i] = 0.0; //Reset timer + } + keysReleasedTime[i] += dt; //Tick up + } + } + + //Write to lastKeys + memcpy(keysLast, keys, sizeof(keys)); + + //Mouse Positioning///////////////////////////////////// + //https://stackoverflow.com/a/6423739 + + //Get cursor position, even when it is outside window + POINT p; + GetCursorPos(&p); + mouseScreenX = p.x; + mouseScreenY = p.y; + + //Mouse wheel vertical delta updating + mouseWheelVerticalDelta = 0; + mouseWheelVerticalDelta = mouseWheelVerticalDeltaPoll; + mouseWheelVerticalDeltaPoll = 0; + } + + bool SHInputManagerSystem::AnyKeyDown(SH_KEYCODE* firstDetected) noexcept + { + for (size_t i = 0; i < MAX_KEYS; ++i) + { + if (keys[i] && !keysLast[i]) + { + if (firstDetected) *firstDetected = static_cast(i); + return true; + } + } + return false; + } + + bool SHInputManagerSystem::AnyKey(SH_KEYCODE* firstDetected) noexcept + { + for (size_t i = 0; i < MAX_KEYS; ++i) + { + if (keys[i]) + { + if (firstDetected) *firstDetected = static_cast(i); + return true; + } + } + return false; + } + + bool SHInputManagerSystem::AnyKeyUp(SH_KEYCODE* firstDetected) noexcept + { + for (size_t i = 0; i < MAX_KEYS; ++i) + { + + } + } + +} //namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Input/SHInputManagerSystem.h b/SHADE_Engine/src/Input/SHInputManagerSystem.h new file mode 100644 index 00000000..39c97d6f --- /dev/null +++ b/SHADE_Engine/src/Input/SHInputManagerSystem.h @@ -0,0 +1,559 @@ +/********************************************************************* + * \file SHInputManagerSystem.h + * \author Ryan Wang Nian Jing + * \brief Declaration of input manager. + * Handles input from keyboard and mouse. Soon to include controller. + * + * \copyright Copyright (c) 2022 DigiPen Institute of Technology. Reproduction + or disclosure of this file or its contents without the prior written + consent of DigiPen Institute of Technology is prohibited. + *********************************************************************/ + +#pragma once +//#include +#include "../../SHADE_Managed/src/SHpch.h" +#include "ECS_Base/System/SHSystem.h" +#include "ECS_Base/System/SHFixedSystemRoutine.h" + +namespace SHADE +{ + class SH_API SHInputManagerSystem : public SHSystem + { + public: + class SH_API InputManagerRoutine : public SHFixedSystemRoutine + { + public: + virtual void FixedExecute(double dt) noexcept override final; + }; + + public: + /*------------------------------------------------------------------------*/ + /* Enumerations */ + /*------------------------------------------------------------------------*/ + enum class SH_KEYCODE + { + LMB = 0X01, + RMB = 0X02, + CANCEL = 0X03, + MMB = 0X04, + XMB1 = 0X05, + XMB2 = 0X06, + + BACKSPACE = 0X08, + TAB = 0X09, + + CLEAR = 0X0C, + ENTER = 0X0D, + + SHIFT = 0X10, //USE LEFT OR RIGHT SHIFT INSTEAD + CTRL = 0X11, //USE LEFT OR RIGHT CTRL INSTEAD + ALT = 0X12, //USE LEFT OR RIGHT ALT INSTEAD + PAUSE = 0X13, + CAPS_LOCK = 0X14, + IME_KANA = 0X15, + IME_HANGUL = 0X15, + IME_ON = 0X16, + IME_JUNJA = 0X17, + IME_FINAL = 0X18, + IME_HANJA = 0X19, + IME_KANJI = 0X19, + IME_OFF = 0X1A, + ESCAPE = 0X1B, + IME_CONVERT = 0X1C, + IME_NONCONVERT = 0X1D, + IME_ACCEPT = 0X1E, + IME_MODECHANGE = 0X1F, + SPACE = 0X20, + PAGE_UP = 0X21, + PAGE_DOWN = 0X22, + END = 0X23, + HOME = 0X24, + LEFT_ARROW = 0X25, + UP_ARROW = 0X26, + RIGHT_ARROW = 0X27, + DOWN_ARROW = 0X28, + SELECT = 0X29, + PRINT = 0X2A, + EXECUTE = 0X2B, + PRINT_SCREEN = 0X2C, + INSERT = 0X2D, + DEL = 0X2E, + HELP = 0X2F, + + NUMBER_0 = 0X30, + NUMBER_1, + NUMBER_2, + NUMBER_3, + NUMBER_4, + NUMBER_5, + NUMBER_6, + NUMBER_7, + NUMBER_8, + NUMBER_9, + + A = 0X41, + B, + C, + D, + E, + F, + G, + H, + I, + J, + K, + L, + M, + N, + O, + P, + Q, + R, + S, + T, + U, + V, + W, + X, + Y, + Z, + + LEFT_WINDOWS = 0X5B, + RIGHT_WINDOWS, + APPS, + + SLEEP = 0X5F, + + NUMPAD_0 = 0X60, + NUMPAD_1, + NUMPAD_2, + NUMPAD_3, + NUMPAD_4, + NUMPAD_5, + NUMPAD_6, + NUMPAD_7, + NUMPAD_8, + NUMPAD_9, + + MULTIPLY = 0X6A, + ADD, + SEPARATOR, + SUBTRACT, + DECIMAL, + DIVIDE, + + F1 = 0X70, + F2, + F3, + F4, + F5, + F6, + F7, + F8, + F9, + F10, + F11, + F12, + F13, + F14, + F15, + F16, + F17, + F18, + F19, + F20, + F21, + F22, + F23, + F24, + + NUM_LOCK = 0X90, + SCROLL_LOCK = 0X91, + + OEM_PC98_NUMPAD_EQUAL = 0X92, + OEM_FUJITSU_DICTIONARY = 0X92, + OEM_FUJITSU_UNREGISTER, + OEM_FUJITSU_REGISTER, + OEM_FUJITSU_LEFT_THUMB, + OEM_FUJITSU_RIGHT_THUMB, + + LEFT_SHIFT = 0XA0, + RIGHT_SHIFT, + LEFT_CTRL, + RIGHT_CTRL, + LEFT_ALT, + RIGHT_ALT, + BROWSER_BACK, + BROWSER_FORWARD, + BROWSER_REFRESH, + BROWSER_STOP, + BROWSER_SEARCH, + BROWSER_FAVOURITES, + BROWSER_HOME, + VOLUME_MUTE, + VOLUME_DOWN, + VOLUME_UP, + MEDIA_NEXT_TRACK, + MEDIA_PREVIOUS_TRACK, + MEDIA_STOP, + MEDIA_PLAY_PAUSE, + LAUNCH_MAIL, + LAUNCH_MEDIA_SELECT, + LAUNCH_APP_1, + LAUNCH_APP_2, + + OEM_1 = 0XBA, + OEM_PLUS, + OEM_COMMA, + OEM_MINUS, + OEM_PERIOD, + OEM_2, + OEM_3, + + GAMEPAD_A = 0XC3, + GAMEPAD_B, + GAMEPAD_X, + GAMEPAD_Y, + GAMEPAD_RIGHTSHOULDER, + GAMEPAD_LEFTSHOULDER, + GAMEPAD_LEFTTRIGGER, + GAMEPAD_RIGHTTRIGGER, + GAMEPAD_DPAD_UP, + GAMEPAD_DPAD_DOWN, + GAMEPAD_DPAD_LEFT, + GAMEPAD_DPAD_RIGHT, + GAMEPAD_MENU, + GAMEPAD_VIEW, + GAMEPAD_LEFT_THUMBSTICK_BUTTON, + GAMEPAD_RIGHT_THUMBSTICK_BUTTON, + GAMEPAD_LEFT_THUMBSTICK_UP, + GAMEPAD_LEFT_THUMBSTICK_DOWN, + GAMEPAD_LEFT_THUMBSTICK_RIGHT, + GAMEPAD_LEFT_THUMBSTICK_LEFT, + GAMEPAD_RIGHT_THUMBSTICK_UP, + GAMEPAD_RIGHT_THUMBSTICK_DOWN, + GAMEPAD_RIGHT_THUMBSTICK_RIGHT, + GAMEPAD_RIGHT_THUMBSTICK_LEFT, + + OEM_4, + OEM_5, + OEM_6, + OEM_7, + OEM_8, + + OEM_AX = 0XE1, + OEM_102, + OEM_ICO_HELP, + OEM_ICO_00, + IME_PROCESS, + OEM_ICO_CLEAR, + PACKET, + + OEM_RESET = 0XE9, + OEM_JUMP, + OEM_PA1, + OEM_PA2, + OEM_PA3, + OEM_WSCTRL, + OEM_CUSEL, + OEM_ATTN, + OEM_FINISH, + OEM_COPY, + OEM_AUTO, + OEM_ENLW, + OEM_BACKTAB, + + ATTN, + CRSEL, + EXSEL, + EREOF, + PLAY, + ZOOM, + NONAME, + PA_1, + OEM_CLEAR + }; + + public: + /*------------------------------------------------------------------------*/ + /* Constructors & Destructor */ + /*------------------------------------------------------------------------*/ + SHInputManagerSystem() noexcept = default; + ~SHInputManagerSystem() noexcept = default; + + SHInputManagerSystem(const SHInputManagerSystem&) = delete; + SHInputManagerSystem(SHInputManagerSystem&&) = delete; + + SHInputManagerSystem& operator= (const SHInputManagerSystem&) = delete; + SHInputManagerSystem& operator= (SHInputManagerSystem&&) = delete; + + /*------------------------------------------------------------------------*/ + /* SHSystem Overrides */ + /*------------------------------------------------------------------------*/ + virtual void Init() override final; + virtual void Exit() override final; + + /*------------------------------------------------------------------------*/ + /* Member Functions */ + /*------------------------------------------------------------------------*/ + + //Needs to be linked to WM_MOUSEWHEEL in wndProc + static inline void PollWheelVerticalDelta(WPARAM wParam) noexcept + { + mouseWheelVerticalDeltaPoll += GET_WHEEL_DELTA_WPARAM(wParam); + } + + //For testing purposes + //static void PrintCurrentState() noexcept; + + /*------------------------------------------------------------------------*/ + /* Input state accessors (KB & M) */ + /*------------------------------------------------------------------------*/ + //Get how many keys are presently down + static inline unsigned GetKeyCount() noexcept + { + return keyCount; + } + + //How many keys are presently toggled + static inline unsigned GetKeyToggleCount() noexcept + { + return keyToggleCount; + } + + //Any key pressed in THIS FRAME ONLY + //Keys being held beforehand don't count + //Output parameter is which key was first to be detected + static bool AnyKeyDown(SH_KEYCODE* firstKey = nullptr) noexcept; + + //Any key is being held down + //Return false if no key being held + //Output parameter is which key was first to be detected + static bool AnyKey(SH_KEYCODE* firstKey = nullptr) noexcept; + + //Any key released in THIS FRAME ONLY + //Keys that are released beforehand don't count + //Output parameter is which key was first to be detected + static bool AnyKeyUp(SH_KEYCODE* firstKey = nullptr) noexcept; + + //Check if a particular key was pressed down in THIS FRAME ONLY + //Keys being held beforehand don't count + //Output parameter is how long the key has been released for prior + static inline bool GetKeyDown (SH_KEYCODE key, + double* releasedTime = nullptr) noexcept + { + if (releasedTime) *releasedTime = keysReleasedTime[static_cast(key)]; + return (keys[static_cast(key)] && !keysLast[static_cast(key)]); + } + + //Check if a particular key was toggled on in THIS FRAME ONLY + //Keys that stay toggled on afterwards don't count + //Output parameter is how long the key has been toggled off for prior + static inline bool GetKeyToggleOn (SH_KEYCODE key, + double* toggleOffTime = nullptr) noexcept + { + if (toggleOffTime) + *toggleOffTime = keysToggleOffTime[static_cast(key)]; + return (keysToggle[static_cast(key)] && + !keysToggleLast[static_cast(key)]); + } + + //Check if a particular key is presently being held down on + //Output parameter is how long the key has been held and released + static inline bool GetKey(SH_KEYCODE key, + double* heldTime = nullptr, double* releasedTime = nullptr) noexcept + { + if (heldTime) *heldTime = keysHeldTime[static_cast(key)]; + if (releasedTime) *releasedTime = keysReleasedTime[static_cast(key)]; + return keys[static_cast(key)]; + } + + //Check if a particular key is presently toggled on + //Output parameter is how long the key has been toggled on and off + static inline bool GetKeyToggle(SH_KEYCODE key, + double* onTime = nullptr, double* offTime = nullptr) noexcept + { + if (onTime) *onTime = keysToggleOnTime[static_cast(key)]; + if (offTime) *offTime = keysToggleOffTime[static_cast(key)]; + return keysToggle[static_cast(key)]; + } + + //Check if a particular key was released in THIS FRAME ONLY + //Keys already released beforehand don't count + //Output parameter is how long the key has been held for prior + static inline bool GetKeyUp(SH_KEYCODE key, + double* heldTime = nullptr) noexcept + { + if (heldTime) *heldTime = keysHeldTime[static_cast(key)]; + return (!keys[static_cast(key)] && keysLast[static_cast(key)]); + } + + //Check if a particular key was toggled off in THIS FRAME ONLY + //Keys that stay toggled off afterwards don't count + //Output parameter is how long the key has been toggled on for prior + static inline bool GetKeyToggleOff(SH_KEYCODE key, + double* toggleOnTime = nullptr) noexcept + { + if (toggleOnTime) + *toggleOnTime = keysToggleOnTime[static_cast(key)]; + return (!keysToggle[static_cast(key)] && + keysToggleLast[static_cast(key)]); + } + + //Mouse///////////// + + //Get the mouse location with respect to the screen + static inline void GetMouseScreenPosition (int* x = nullptr, + int* y = nullptr) noexcept + { + if (x) *x = mouseScreenX; + if (y) *y = mouseScreenY; + } + + //Get the mouse location with respect to current window + static inline void GetMouseWindowPosition (int* x = nullptr, + int* y = nullptr) noexcept + { + POINT p{ mouseScreenX, mouseScreenY }; + ScreenToClient(GetActiveWindow(), &p); + if (x) *x = mouseScreenX; + if (y) *y = mouseScreenY; + } + + //Get the mouse wheel vertical delta + static inline int GetMouseWheelVerticalDelta() noexcept + { + return mouseWheelVerticalDelta; + } + + //GET INPUT TIMINGS/////////////////////////////////////////////////////////// + + //Keyboard///////////// + + //How long has this key been held down for + static inline double GetKeyHeldTime(SH_KEYCODE key) noexcept + { + return keysHeldTime[static_cast(key)]; + } + + //How long has this key been released for + static inline double GetKeyReleasedTime(SH_KEYCODE key) noexcept + { + return keysReleasedTime[static_cast(key)]; + } + + //How long has this key been toggled on for + static inline double GetKeyToggleOnTime(SH_KEYCODE key) noexcept + { + return keysToggleOnTime[static_cast(key)]; + } + + //How long has this keen been toggled off for + static inline double GetKeyToggleOffTime(SH_KEYCODE key) noexcept + { + return keysToggleOffTime[static_cast(key)]; + } + + /*------------------------------------------------------------------------*/ + /* Other Functions */ + /*------------------------------------------------------------------------*/ + + //Mouse//////////////////////// + + //Move mouse cursor to a position on the screen + static inline void SetMouseScreenPosition(int x = 0, int y = 0) noexcept + { + SetCursorPos(x, y); + } + + //Move mouse cursor to a position on the active window + static inline void SetMouseWindowPosition(int x = 0, int y = 0) noexcept + { + POINT p{ x, y }; + ClientToScreen(GetActiveWindow(), &p); + SetCursorPos(p.x, p.y); + } + + private: + /*------------------------------------------------------------------------*/ + /* Constants */ + /*------------------------------------------------------------------------*/ + static constexpr size_t MAX_KEYS = UCHAR_MAX + 1; + + /*------------------------------------------------------------------------*/ + /* Data Members */ + /*------------------------------------------------------------------------*/ + + //KEYBOARD AND MOUSE BUTTONS//////////////////////////////////////////////// + + //How many keys are presently being pressed + static unsigned keyCount; + + //Key states of all keys presently + //true for being pressed, false for released + static bool keys[MAX_KEYS]; + + //Key states of all keys in the last frame + //true for being pressed, false for released + static bool keysLast[MAX_KEYS]; + + //Key held durations + //Stops ticking up when released + //Will be reset when held again + static double keysHeldTime[MAX_KEYS]; + + //Key released durations + //Stops ticking up when held + //Will be reset when off again + static double keysReleasedTime[MAX_KEYS]; + + //How many keys are presently being toggled + static unsigned keyToggleCount; + + //Toggle key states of keys (not neccessarily just caps/num/scroll locks) + static bool keysToggle[MAX_KEYS]; + + //Toggle key states of keys in the last frame + static bool keysToggleLast[MAX_KEYS]; + + //Key toggle durations + //Stops ticking up when untoggled + //Will be reset when toggled again + static double keysToggleOnTime[MAX_KEYS]; + + //Key untoggle durations + //Stops ticking up when toggled + //Will be reset when untoggled again + static double keysToggleOffTime[MAX_KEYS]; + + //MOUSE VARIABLES/////////////////////////////////////////////////////////// + + //Present horizontal positioning of the mouse WRT the screen + static int mouseScreenX; + //Present vertical positioning of the mouse WRT the screen + static int mouseScreenY; + + //Horizontal positioning of the mouse WRT screen in last frame + static int mouseScreenXLast; + //Vertical positioning of the mouse WRT screen in the last frame + static int mouseScreenYLast; + + //For polling mouse wheel events, not to be read + static int mouseWheelVerticalDeltaPoll; + //Mouse wheel vertical rotation speed. Positive is rotation AWAY from user + static int mouseWheelVerticalDelta; + + //CONTROLLER VARIABLES////////////////////////////////////////////////////// + + //OTHER VARIABLES/////////////////////////////////////////////////////////// + + //Axis bindings + //X + + //Y + + //Other mappings + + //Buffer + }; +} \ No newline at end of file From 800732706ef7a18dea432d4cbbcff96b971f7a4f Mon Sep 17 00:00:00 2001 From: mushgunAX Date: Fri, 23 Sep 2022 17:42:31 +0800 Subject: [PATCH 02/13] input pch move, init, exit, etc definitions --- .../src/Input/SHInputManagerSystem.cpp | 35 ++++++++++++++++++- SHADE_Engine/src/Input/SHInputManagerSystem.h | 2 +- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/SHADE_Engine/src/Input/SHInputManagerSystem.cpp b/SHADE_Engine/src/Input/SHInputManagerSystem.cpp index d5e9bb3f..cbc49d7d 100644 --- a/SHADE_Engine/src/Input/SHInputManagerSystem.cpp +++ b/SHADE_Engine/src/Input/SHInputManagerSystem.cpp @@ -10,6 +10,7 @@ *********************************************************************/ #pragma once +#include #include "SHInputManagerSystem.h" namespace SHADE @@ -37,6 +38,33 @@ namespace SHADE int SHInputManagerSystem::mouseWheelVerticalDelta = 0; int SHInputManagerSystem::mouseWheelVerticalDeltaPoll = 0; + void SHInputManagerSystem::Init() + { + keyCount = 0; + SecureZeroMemory(keys, sizeof(keys)); + SecureZeroMemory(keysLast, sizeof(keysLast)); + SecureZeroMemory(keysHeldTime, sizeof(keysHeldTime)); + SecureZeroMemory(keysReleasedTime, sizeof(keysReleasedTime)); + + keyToggleCount = 0; + SecureZeroMemory(keysToggle, sizeof(keysToggle)); + SecureZeroMemory(keysToggleLast, sizeof(keysToggleLast)); + SecureZeroMemory(keysToggleOnTime, sizeof(keysToggleOnTime)); + SecureZeroMemory(keysToggleOffTime, sizeof(keysToggleOffTime)); + + mouseScreenX = 0; + mouseScreenY = 0; + mouseScreenXLast = 0; + mouseScreenYLast = 0; + mouseWheelVerticalDelta = 0; + mouseWheelVerticalDeltaPoll = 0; + } + + void SHInputManagerSystem::Exit() + { + //No dynamically allocated memory. Nothing to do here. + } + void SHInputManagerSystem::InputManagerRoutine:: FixedExecute(double dt) noexcept { @@ -140,8 +168,13 @@ namespace SHADE { for (size_t i = 0; i < MAX_KEYS; ++i) { - + if (!keys[i] && keysLast[i]) + { + if (firstDetected) *firstDetected = static_cast(i); + return true; + } } + return false; } } //namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Input/SHInputManagerSystem.h b/SHADE_Engine/src/Input/SHInputManagerSystem.h index 39c97d6f..6ee73ae9 100644 --- a/SHADE_Engine/src/Input/SHInputManagerSystem.h +++ b/SHADE_Engine/src/Input/SHInputManagerSystem.h @@ -11,7 +11,7 @@ #pragma once //#include -#include "../../SHADE_Managed/src/SHpch.h" +//#include "../../SHADE_Managed/src/SHpch.h" #include "ECS_Base/System/SHSystem.h" #include "ECS_Base/System/SHFixedSystemRoutine.h" From 759c87e2a19655246630ca8f3773d51d7abf8669 Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Sat, 24 Sep 2022 02:07:47 +0800 Subject: [PATCH 03/13] Material data on the GPU is now updated when material data changes --- .../Graphics/MiddleEnd/Batching/SHBatch.cpp | 85 ++++++++++++++++++- .../src/Graphics/MiddleEnd/Batching/SHBatch.h | 7 ++ .../Graphics/MiddleEnd/Batching/SHBatcher.cpp | 6 +- .../Graphics/MiddleEnd/Batching/SHBatcher.h | 2 +- .../MiddleEnd/Batching/SHSuperBatch.cpp | 3 +- .../MiddleEnd/Batching/SHSuperBatch.h | 4 +- .../Interface/SHMaterialInstance.cpp | 5 +- .../MiddleEnd/Interface/SHMaterialInstance.h | 6 +- .../Interface/SHMaterialInstance.hpp | 3 + .../Graphics/RenderGraph/SHRenderGraph.cpp | 4 +- 10 files changed, 109 insertions(+), 16 deletions(-) diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp index a68ee7fa..4667d5db 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp @@ -58,6 +58,9 @@ namespace SHADE // Add renderable in subBatch->Renderables.insert(renderable); + // Also add material instance in + referencedMatInstances.insert(renderable->GetMaterial()); + // Mark all as dirty setAllDirtyFlags(); } @@ -67,8 +70,8 @@ namespace SHADE // Check if we have a SubBatch with the same mesh yet auto subBatch = std::find_if(subBatches.begin(), subBatches.end(), [&](const SHSubBatch& batch) { - return batch.Mesh == renderable->Mesh; - }); + return batch.Mesh == renderable->Mesh; + }); // Attempt to remove if it exists if (subBatch == subBatches.end()) @@ -76,6 +79,22 @@ namespace SHADE subBatch->Renderables.erase(renderable); + // Check if other renderables in subBatches contain the same material instance + bool matUnused = true; + for (const auto& subBatch : subBatches) + for (const auto& rend : subBatch.Renderables) + { + if (rend->GetMaterial() == renderable->GetMaterial()) + { + matUnused = false; + break; + } + } + + // Material is no longer in this library, so we remove it + if (matUnused) + referencedMatInstances.erase(renderable->GetMaterial()); + // Mark all as dirty for (bool& dirt : isDirty) dirt = true; @@ -101,7 +120,63 @@ namespace SHADE } } - void SHBatch::UpdateTransformBuffer(uint32_t frameIndex) + void SHBatch::UpdateMaterialBuffer(uint32_t frameIndex) + { + if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS) + { + SHLOG_WARNING("[SHBatch] Attempted to update transform buffers with an invalid frame index."); + return; + } + + // Check if there are even material properties to update + if (!matPropsData) + return; + + // Check if any materials have changed + bool hasChanged = false; + for (auto material : referencedMatInstances) + { + if (material->HasChanged()) + { + hasChanged = true; + break; + } + } + + // We need to update all the material buffers if the materials have changed + if (hasChanged) + { + for (auto& dirt : matBufferDirty) + dirt = true; + } + + // Check if this frame's buffer is dirty + if (!matBufferDirty[frameIndex]) + return; + + // Build CPI Buffer + uint32_t nextInstanceIndex = 0; + char* propsCurrPtr = matPropsData.get(); + for (auto& subBatch : subBatches) + for (const SHRenderable* renderable : subBatch.Renderables) + { + + renderable->GetMaterial()->ExportProperties(propsCurrPtr); + propsCurrPtr += singleMatPropSize; + } + + // Transfer to GPU + SHVkUtil::EnsureBufferAndCopyHostVisibleData + ( + device, matPropsBuffer[frameIndex], matPropsData.get(), static_cast(matPropsDataSize), + vk::BufferUsageFlagBits::eStorageBuffer + ); + + // This frame is updated + matBufferDirty[frameIndex] = false; + } + + void SHBatch::UpdateTransformBuffer(uint32_t frameIndex) { if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS) { @@ -169,7 +244,6 @@ namespace SHADE vk::ShaderStageFlagBits::eFragment ); const bool EMPTY_MAT_PROPS = !SHADER_INFO; - Byte singleMatPropSize = 0; Byte matPropTotalBytes = 0; if (!EMPTY_MAT_PROPS) { @@ -252,6 +326,9 @@ namespace SHADE } isDirty[frameIndex] = false; + + // Save logical device + this->device = device; } /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.h b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.h index a572adca..d40a66ea 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.h @@ -34,6 +34,7 @@ namespace SHADE class SHMesh; class SHRenderable; class SHVkLogicalDevice; + class SHMaterialInstance; /*---------------------------------------------------------------------------------*/ /* Type Definitions */ @@ -73,6 +74,7 @@ namespace SHADE void Add(const SHRenderable* renderable); void Remove(const SHRenderable* renderable); void Clear(); + void UpdateMaterialBuffer(uint32_t frameIndex); void UpdateTransformBuffer(uint32_t frameIndex); void Build(Handle device, uint32_t frameIndex); void Draw(Handle cmdBuffer, uint32_t frameIndex); @@ -86,8 +88,12 @@ namespace SHADE /*-----------------------------------------------------------------------------*/ /* Data Members */ /*-----------------------------------------------------------------------------*/ + // Resources + Handle device; // Batch Properties Handle pipeline; + std::unordered_set> referencedMatInstances; + std::array matBufferDirty; // Batch Tree std::vector subBatches; std::array isDirty; @@ -96,6 +102,7 @@ namespace SHADE std::vector transformData; std::unique_ptr matPropsData; Byte matPropsDataSize = 0; + Byte singleMatPropSize = 0; bool isCPUBuffersDirty = true; // GPU Buffers std::array, SHGraphicsConstants::NUM_FRAME_BUFFERS> drawDataBuffer; diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatcher.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatcher.cpp index ecd99a20..c4320aac 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatcher.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatcher.cpp @@ -109,11 +109,11 @@ namespace SHADE superBatches.clear(); } - void SHBatcher::UpdateTransformBuffer(uint32_t frameIndex) -{ + void SHBatcher::UpdateBuffers(uint32_t frameIndex) + { for (auto& batch : superBatches) { - batch->UpdateTransformBuffer(frameIndex); + batch->UpdateBuffers(frameIndex); } } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatcher.h b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatcher.h index b4fff203..985e8e16 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatcher.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatcher.h @@ -53,7 +53,7 @@ namespace SHADE void RemoveFromBatch(SHRenderable const* renderable); void FinaliseBatches(Handle device, uint32_t frameIndex); void ClearBatches(); - void UpdateTransformBuffer(uint32_t frameIndex); + void UpdateBuffers(uint32_t frameIndex); void RegisterSuperBatch(Handle superBatch); void DeregisterSuperBatch(Handle superBatch); diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHSuperBatch.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHSuperBatch.cpp index 633d40a9..b0173399 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHSuperBatch.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHSuperBatch.cpp @@ -78,10 +78,11 @@ namespace SHADE batches.clear(); } - void SHSuperBatch::UpdateTransformBuffer(uint32_t frameIndex) + void SHSuperBatch::UpdateBuffers(uint32_t frameIndex) { for (auto& batch : batches) { + batch.UpdateMaterialBuffer(frameIndex); batch.UpdateTransformBuffer(frameIndex); } } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHSuperBatch.h b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHSuperBatch.h index 5379ee61..a09fc64e 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHSuperBatch.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHSuperBatch.h @@ -54,8 +54,8 @@ namespace SHADE /*-----------------------------------------------------------------------------*/ void Add(const SHRenderable* renderable) noexcept; void Remove(const SHRenderable* renderable) noexcept; - void Clear() noexcept; - void UpdateTransformBuffer(uint32_t frameIndex); + void Clear() noexcept; + void UpdateBuffers(uint32_t frameIndex); void Build(Handle device, uint32_t frameIndex) noexcept; void Draw(Handle cmdBuffer, uint32_t frameIndex) noexcept; diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.cpp index 57a91941..0e5a61dd 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.cpp @@ -38,7 +38,7 @@ namespace SHADE dataStore.reset(); } - void SHMaterialInstance::ExportProperties(void* dest) const + void SHMaterialInstance::ExportProperties(void* dest) { assert(dataStore != nullptr); @@ -62,6 +62,9 @@ namespace SHADE const auto DATA_OFFSET = variable->offset; memcpy(static_cast(dest) + DATA_OFFSET, dataStore.get() + data.StoredDataOffset, data.DataSize); } + + // Data was exported so unflag + dataWasChanged = false; } /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.h index db0201b7..5d6c4925 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.h @@ -62,12 +62,13 @@ namespace SHADE template const T& GetProperty(const std::string& key) const; void ResetProperties() noexcept; - void ExportProperties(void* dest) const; + void ExportProperties(void* dest); /*-----------------------------------------------------------------------------*/ /* Getter Functions */ /*-----------------------------------------------------------------------------*/ - Handle GetBaseMaterial() const { return baseMaterial; } + Handle GetBaseMaterial() const noexcept { return baseMaterial; } + bool HasChanged() const noexcept { return dataWasChanged; } private: /*-----------------------------------------------------------------------------*/ @@ -77,6 +78,7 @@ namespace SHADE std::vector overrideData; std::unique_ptr dataStore; size_t dataStoreSize = 0; + bool dataWasChanged = false; /*-----------------------------------------------------------------------------*/ /* Helper Functions */ diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.hpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.hpp index 0aead306..b3dc6c3a 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.hpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.hpp @@ -53,6 +53,9 @@ namespace SHADE // Save the override data information overrideData.emplace_back(std::move(od)); + + // Flag + dataWasChanged = true; } template T& SHMaterialInstance::GetProperty(const std::string& key) diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp index ecf9059c..6070361f 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp @@ -348,8 +348,8 @@ namespace SHADE void SHSubpass::Execute(Handle& commandBuffer, uint32_t frameIndex) noexcept { - // Ensure correct transforms are provided - superBatch->UpdateTransformBuffer(frameIndex); + // Ensure updated transforms and materials are provided + superBatch->UpdateBuffers(frameIndex); // Draw all the batches superBatch->Draw(commandBuffer, frameIndex); From 15f12a2608fc2fa398fe855e803bfc8f9e11d4cc Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Sat, 24 Sep 2022 02:13:09 +0800 Subject: [PATCH 04/13] Fixed warnings in SHBatch.cpp --- .../Graphics/MiddleEnd/Batching/SHBatch.cpp | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp index 4667d5db..7b2ebd49 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp @@ -81,8 +81,8 @@ namespace SHADE // Check if other renderables in subBatches contain the same material instance bool matUnused = true; - for (const auto& subBatch : subBatches) - for (const auto& rend : subBatch.Renderables) + for (const auto& sb : subBatches) + for (const auto& rend : sb.Renderables) { if (rend->GetMaterial() == renderable->GetMaterial()) { @@ -134,7 +134,7 @@ namespace SHADE // Check if any materials have changed bool hasChanged = false; - for (auto material : referencedMatInstances) + for (const auto& material : referencedMatInstances) { if (material->HasChanged()) { @@ -155,12 +155,10 @@ namespace SHADE return; // Build CPI Buffer - uint32_t nextInstanceIndex = 0; char* propsCurrPtr = matPropsData.get(); for (auto& subBatch : subBatches) for (const SHRenderable* renderable : subBatch.Renderables) { - renderable->GetMaterial()->ExportProperties(propsCurrPtr); propsCurrPtr += singleMatPropSize; } @@ -205,10 +203,10 @@ namespace SHADE } // Transfer to GPU - transformDataBuffer[frameIndex]->WriteToMemory(transformData.data(), transformData.size() * sizeof(SHMatrix), 0, 0); + transformDataBuffer[frameIndex]->WriteToMemory(transformData.data(), static_cast(transformData.size() * sizeof(SHMatrix)), 0, 0); } - void SHBatch::Build(Handle device, uint32_t frameIndex) + void SHBatch::Build(Handle _device, uint32_t frameIndex) { if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS) { @@ -305,14 +303,14 @@ namespace SHADE const uint32_t DRAW_DATA_BYTES = static_cast(drawData.size() * sizeof(vk::DrawIndexedIndirectCommand)); SHVkUtil::EnsureBufferAndCopyHostVisibleData ( - device, drawDataBuffer[frameIndex], drawData.data(), DRAW_DATA_BYTES, + _device, drawDataBuffer[frameIndex], drawData.data(), DRAW_DATA_BYTES, BuffUsage::eIndirectBuffer ); // - Transform Buffer const uint32_t TF_DATA_BYTES = static_cast(transformData.size() * sizeof(SHMatrix)); SHVkUtil::EnsureBufferAndCopyHostVisibleData ( - device, transformDataBuffer[frameIndex], transformData.data(), TF_DATA_BYTES, + _device, transformDataBuffer[frameIndex], transformData.data(), TF_DATA_BYTES, BuffUsage::eVertexBuffer ); // - Material Properties Buffer @@ -320,7 +318,7 @@ namespace SHADE { SHVkUtil::EnsureBufferAndCopyHostVisibleData ( - device, matPropsBuffer[frameIndex], matPropsData.get(), static_cast(matPropsDataSize), + _device, matPropsBuffer[frameIndex], matPropsData.get(), static_cast(matPropsDataSize), BuffUsage::eStorageBuffer ); } @@ -328,7 +326,7 @@ namespace SHADE isDirty[frameIndex] = false; // Save logical device - this->device = device; + this->device = _device; } /*---------------------------------------------------------------------------------*/ From 8ab5afd3c4761274d0423657bdfdd801b345fe23 Mon Sep 17 00:00:00 2001 From: mushgunAX Date: Sun, 25 Sep 2022 16:39:01 +0800 Subject: [PATCH 05/13] first version of IM ready for PR --- .../src/Application/SBApplication.cpp | 4 ++++ .../src/Input/SHInputManagerSystem.cpp | 6 ++++++ SHADE_Engine/src/Input/SHInputManagerSystem.h | 21 +++++++++++++++++++ 3 files changed, 31 insertions(+) diff --git a/SHADE_Application/src/Application/SBApplication.cpp b/SHADE_Application/src/Application/SBApplication.cpp index bb4ccc35..7ef8adfe 100644 --- a/SHADE_Application/src/Application/SBApplication.cpp +++ b/SHADE_Application/src/Application/SBApplication.cpp @@ -23,6 +23,7 @@ #include "Graphics/MiddleEnd/Interface/SHRenderable.h" #include "Scene/SHSceneManager.h" #include "Math/Transform/SHTransformSystem.h" +#include "Input/SHInputManagerSystem.h" #include "Scenes/SBTestScene.h" #include "Math/Transform/SHTransformComponent.h" @@ -52,6 +53,7 @@ namespace Sandbox SHADE::SHSystemManager::CreateSystem(); SHADE::SHSystemManager::CreateSystem(); SHADE::SHGraphicsSystem* graphicsSystem = static_cast(SHADE::SHSystemManager::GetSystem()); + SHADE::SHSystemManager::CreateSystem(); // Create Routines SHADE::SHSystemManager::RegisterRoutine(); @@ -71,6 +73,8 @@ namespace Sandbox SHADE::SHComponentManager::CreateComponentSparseSet(); SHADE::SHComponentManager::CreateComponentSparseSet(); + + SHADE::SHSystemManager::RegisterRoutine(); // Set up graphics system and windows graphicsSystem->SetWindow(&window); diff --git a/SHADE_Engine/src/Input/SHInputManagerSystem.cpp b/SHADE_Engine/src/Input/SHInputManagerSystem.cpp index cbc49d7d..1beabe3f 100644 --- a/SHADE_Engine/src/Input/SHInputManagerSystem.cpp +++ b/SHADE_Engine/src/Input/SHInputManagerSystem.cpp @@ -35,6 +35,8 @@ namespace SHADE int SHInputManagerSystem::mouseScreenY = 0; int SHInputManagerSystem::mouseScreenXLast = 0; int SHInputManagerSystem::mouseScreenYLast = 0; + double SHInputManagerSystem::mouseVelocityX = 0; + double SHInputManagerSystem::mouseVelocityY = 0; int SHInputManagerSystem::mouseWheelVerticalDelta = 0; int SHInputManagerSystem::mouseWheelVerticalDeltaPoll = 0; @@ -126,6 +128,10 @@ namespace SHADE //Mouse Positioning///////////////////////////////////// //https://stackoverflow.com/a/6423739 + //Set last positioning + mouseScreenXLast = mouseScreenX; + mouseScreenYLast = mouseScreenY; + //Get cursor position, even when it is outside window POINT p; GetCursorPos(&p); diff --git a/SHADE_Engine/src/Input/SHInputManagerSystem.h b/SHADE_Engine/src/Input/SHInputManagerSystem.h index 6ee73ae9..77d8f8fd 100644 --- a/SHADE_Engine/src/Input/SHInputManagerSystem.h +++ b/SHADE_Engine/src/Input/SHInputManagerSystem.h @@ -420,6 +420,16 @@ namespace SHADE if (y) *y = mouseScreenY; } + //Get the mouse velocity + //Two output parameters for x and y velocitites + //In pixels per second for both + static inline void GetMouseVelocity(double* x = nullptr, + double* y = nullptr) noexcept + { + if (x) *x = mouseVelocityX; + if (y) *y = mouseVelocityY; + } + //Get the mouse wheel vertical delta static inline int GetMouseWheelVerticalDelta() noexcept { @@ -529,15 +539,26 @@ namespace SHADE //MOUSE VARIABLES/////////////////////////////////////////////////////////// //Present horizontal positioning of the mouse WRT the screen + //Increasing rightwards static int mouseScreenX; //Present vertical positioning of the mouse WRT the screen + //Increasing downwards static int mouseScreenY; //Horizontal positioning of the mouse WRT screen in last frame + //Increasing rightwards static int mouseScreenXLast; //Vertical positioning of the mouse WRT screen in the last frame + //Increasing downwards static int mouseScreenYLast; + //The velocity at which the mouse is being moved horizontally (px/s) + //Rightwards is positive + static double mouseVelocityX; + //The velocity at which the mouse is being moved vertically (px/s) + //Downwards is positive + static double mouseVelocityY; + //For polling mouse wheel events, not to be read static int mouseWheelVerticalDeltaPoll; //Mouse wheel vertical rotation speed. Positive is rotation AWAY from user From 4e60b3495acb2e2cdc86df3e98a706b5c517fa9c Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Sun, 25 Sep 2022 20:28:01 +0800 Subject: [PATCH 06/13] Handles will now properly show up automatically dereferenced or NULL in Visual Studio's debug views --- SHADE_Engine/NatvisFile.natvis | 10 ++++++++++ SHADE_Engine/premake5.lua | 3 ++- 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 SHADE_Engine/NatvisFile.natvis diff --git a/SHADE_Engine/NatvisFile.natvis b/SHADE_Engine/NatvisFile.natvis new file mode 100644 index 00000000..6747262b --- /dev/null +++ b/SHADE_Engine/NatvisFile.natvis @@ -0,0 +1,10 @@ + + + + NULL + ID = {id.Data.Index} Version = {id.Data.Version} Type = {"$T1"} + + (*library).objects.denseArray[(*library).objects.sparseArray[id.Data.Index]] + + + \ No newline at end of file diff --git a/SHADE_Engine/premake5.lua b/SHADE_Engine/premake5.lua index 84acd8fa..2e6c39f9 100644 --- a/SHADE_Engine/premake5.lua +++ b/SHADE_Engine/premake5.lua @@ -15,7 +15,8 @@ project "SHADE_Engine" "%{prj.location}/src/**.hpp", "%{prj.location}/src/**.c", "%{prj.location}/src/**.cpp", - "%{prj.location}/src/**.glsl" + "%{prj.location}/src/**.glsl", + "%{prj.location}/**.natvis" } includedirs From a197ae842ccb379f962445579388c5c5a1517894 Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Sun, 25 Sep 2022 21:46:57 +0800 Subject: [PATCH 07/13] Fixed crash on AMD GPUs resulting from Nvidia treating UniformBuffers and UniformBuffersDynamic as the same --- SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorPool.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorPool.h b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorPool.h index b862ec09..91112496 100644 --- a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorPool.h +++ b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorPool.h @@ -39,7 +39,8 @@ namespace SHADE std::vector Limits = { { vk::DescriptorType::eCombinedImageSampler, 100 }, - { vk::DescriptorType::eUniformBuffer, 100 } + { vk::DescriptorType::eUniformBuffer, 100 }, + { vk::DescriptorType::eUniformBufferDynamic, 100 } }; /// /// Maximum number of descriptor sets allowed From fc5ff763f3d64b84d05a3b1da30ad7372ad74207 Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Sun, 25 Sep 2022 22:55:14 +0800 Subject: [PATCH 08/13] Added SHMaterialInstanceCache --- SHADE_Application/src/Scenes/SBTestScene.cpp | 2 +- .../MiddleEnd/Interface/SHGraphicsSystem.cpp | 13 ++- .../MiddleEnd/Interface/SHGraphicsSystem.h | 11 ++- .../MiddleEnd/Interface/SHRenderable.cpp | 2 +- .../Materials/SHMaterialInstanceCache.cpp | 47 ++++++++++ .../Materials/SHMaterialInstanceCache.h | 93 +++++++++++++++++++ 6 files changed, 158 insertions(+), 10 deletions(-) create mode 100644 SHADE_Engine/src/Graphics/MiddleEnd/Materials/SHMaterialInstanceCache.cpp create mode 100644 SHADE_Engine/src/Graphics/MiddleEnd/Materials/SHMaterialInstanceCache.h diff --git a/SHADE_Application/src/Scenes/SBTestScene.cpp b/SHADE_Application/src/Scenes/SBTestScene.cpp index 0caf3c7e..c91fee9c 100644 --- a/SHADE_Application/src/Scenes/SBTestScene.cpp +++ b/SHADE_Application/src/Scenes/SBTestScene.cpp @@ -36,7 +36,7 @@ namespace Sandbox graphicsSystem->BuildMeshBuffers(); // Create Materials - auto matInst = graphicsSystem->AddMaterialInstance(); + auto matInst = graphicsSystem->AddOrGetBaseMaterialInstance(); // Create Stress Test Objects static const SHVec3 TEST_OBJ_SCALE = { 0.2f, 0.2f, 0.2f }; diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp index 48f16713..b909aeff 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp @@ -415,14 +415,19 @@ namespace SHADE resourceManager.Free(material); } - Handle SHGraphicsSystem::AddMaterialInstance(Handle material) + Handle SHGraphicsSystem::AddOrGetBaseMaterialInstance(Handle material) { - return resourceManager.Create(material); + return materialInstanceCache.CreateOrGet(resourceManager, material); } - SHADE::Handle SHGraphicsSystem::AddMaterialInstance() + SHADE::Handle SHGraphicsSystem::AddOrGetBaseMaterialInstance() { - return AddMaterialInstance(defaultMaterial); + return AddOrGetBaseMaterialInstance(defaultMaterial); + } + + SHADE::Handle SHGraphicsSystem::AddMaterialInstanceCopy(Handle materialInst) + { + return resourceManager.Create(materialInst->GetBaseMaterial()); } void SHGraphicsSystem::RemoveMaterialInstance(Handle materialInstance) diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h index 3dc452be..bee7a0f1 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h @@ -28,6 +28,7 @@ of DigiPen Institute of Technology is prohibited. #include "Graphics/MiddleEnd/Shaders/SHShaderSourceLibrary.h" #include "Graphics/MiddleEnd/Shaders/SHShaderModuleLibrary.h" #include "SHMeshLibrary.h" +#include "Graphics/MiddleEnd/Materials/SHMaterialInstanceCache.h" namespace SHADE { @@ -119,9 +120,10 @@ namespace SHADE /* Material Creation Functions */ /*-----------------------------------------------------------------------------*/ Handle AddMaterial(Handle vertShader, Handle fragShader, Handle subpass); - void RemoveMaterial(Handle material);; - Handle AddMaterialInstance(); - Handle AddMaterialInstance(Handle material); + void RemoveMaterial(Handle material); + Handle AddOrGetBaseMaterialInstance(); + Handle AddOrGetBaseMaterialInstance(Handle material); + Handle AddMaterialInstanceCopy(Handle materialInst); void RemoveMaterialInstance(Handle materialInstance); /*-----------------------------------------------------------------------------*/ @@ -228,8 +230,9 @@ namespace SHADE Handle globalData; // Middle End Resources - ResourceManager resourceManager; + ResourceManager resourceManager; SHMeshLibrary meshLibrary; + SHMaterialInstanceCache materialInstanceCache; // Viewports Handle defaultViewport; // Whole screen std::vector> viewports; // Additional viewports diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.cpp index 5199565c..a4cda42d 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.cpp @@ -81,7 +81,7 @@ namespace SHADE if (!material) { SHGraphicsSystem* gfxSystem = SHSystemManager::GetSystem(); - material = gfxSystem->AddMaterialInstance(sharedMaterial->GetBaseMaterial()); + material = gfxSystem->AddOrGetBaseMaterialInstance(sharedMaterial->GetBaseMaterial()); } return material; diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Materials/SHMaterialInstanceCache.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Materials/SHMaterialInstanceCache.cpp new file mode 100644 index 00000000..ed3d27c3 --- /dev/null +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Materials/SHMaterialInstanceCache.cpp @@ -0,0 +1,47 @@ +/************************************************************************************//*! +\file SHMaterialInstanceCache.cpp +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Sep 25, 2022 +\brief Contains the definition of SHMaterialInstanceCache's functions. + + +Copyright (C) 2022 DigiPen Institute of Technology. +Reproduction or disclosure of this file or its contents without the prior written consent +of DigiPen Institute of Technology is prohibited. +*//*************************************************************************************/ +#include "SHpch.h" +#include "SHMaterialInstanceCache.h" + +#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h" +#include "Resource/ResourceLibrary.h" + + +namespace SHADE +{ + /*---------------------------------------------------------------------------------*/ + /* Usage Functions */ + /*---------------------------------------------------------------------------------*/ + SHADE::Handle SHMaterialInstanceCache::CreateOrGet(ResourceManager& manager, Handle material) + { + // Check if there is already an existing instance + auto matInst = cache.find(material); + if (matInst == cache.end()) + { + // Create and return + return cache.emplace(material, manager.Create(material)).first->second; + } + + return matInst->second; + } + + void SHMaterialInstanceCache::Remove(Handle material) + { + cache.erase(material); + } + + void SHMaterialInstanceCache::Clear() + { + cache.clear(); + } +} diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Materials/SHMaterialInstanceCache.h b/SHADE_Engine/src/Graphics/MiddleEnd/Materials/SHMaterialInstanceCache.h new file mode 100644 index 00000000..d85cb553 --- /dev/null +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Materials/SHMaterialInstanceCache.h @@ -0,0 +1,93 @@ +/************************************************************************************//*! +\file SHMaterialInstanceCache.h +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Sep 25, 2022 +\brief Contains the definition of SHMaterialInstanceCache. + + +Copyright (C) 2022 DigiPen Institute of Technology. +Reproduction or disclosure of this file or its contents without the prior written consent +of DigiPen Institute of Technology is prohibited. +*//*************************************************************************************/ +#pragma once + +// STL Includes +#include +// Project Includes +#include "Resource/Handle.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Forward Declarations */ + /*-----------------------------------------------------------------------------------*/ + class SHMaterial; + class SHMaterialInstance; + class ResourceManager; + + /*-----------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*-----------------------------------------------------------------------------------*/ + /*************************************************************************************/ + /*! + \brief + Creates and caches base SHMaterialInstances. Note that base SHMaterialInstances + refer to SHMaterialInstances with no overrides. + */ + /*************************************************************************************/ + class SHMaterialInstanceCache + { + public: + /*---------------------------------------------------------------------------------*/ + /* Usage Functions */ + /*---------------------------------------------------------------------------------*/ + /***********************************************************************************/ + /*! + + \brief + + + \param material + Material to get the SHMaterialInstance for. + + \return + Handle to the base SHMaterialInstance that is mapped to SHMaterial. + + */ + /***********************************************************************************/ + Handle CreateOrGet(ResourceManager& manager, Handle material); + /***********************************************************************************/ + /*! + + \brief + Removes a SHMaterialInstance from the cache with a matching material. + + \param material + Handle to a SHMaterial that is used to check for removal. + + */ + /***********************************************************************************/ + void Remove(Handle material); + /***********************************************************************************/ + /*! + + \brief + Removes all SHMaterialInstances in the cache. + + */ + /***********************************************************************************/ + void Clear(); + + private: + /*---------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*---------------------------------------------------------------------------------*/ + using MaterialMap = std::unordered_map, Handle>; + + /*---------------------------------------------------------------------------------*/ + /* Data Members */ + /*---------------------------------------------------------------------------------*/ + MaterialMap cache; + }; +} From dc6289e8cf8c6a2b6e815d49bc8f69d6bd9e40b4 Mon Sep 17 00:00:00 2001 From: Brandon Mak Date: Sun, 25 Sep 2022 23:25:51 +0800 Subject: [PATCH 09/13] WIP --- SHADE_Application/src/Scenes/SBTestScene.cpp | 4 +- .../Graphics/Commands/SHVkCommandBuffer.cpp | 234 +++++++++--------- .../Graphics/MiddleEnd/Batching/SHBatch.cpp | 3 +- .../MiddleEnd/Interface/SHGraphicsSystem.cpp | 6 +- .../Graphics/RenderGraph/SHRenderGraph.cpp | 36 ++- .../src/Graphics/RenderGraph/SHRenderGraph.h | 2 + 6 files changed, 161 insertions(+), 124 deletions(-) diff --git a/SHADE_Application/src/Scenes/SBTestScene.cpp b/SHADE_Application/src/Scenes/SBTestScene.cpp index c91fee9c..fc2f9731 100644 --- a/SHADE_Application/src/Scenes/SBTestScene.cpp +++ b/SHADE_Application/src/Scenes/SBTestScene.cpp @@ -40,8 +40,8 @@ namespace Sandbox // Create Stress Test Objects static const SHVec3 TEST_OBJ_SCALE = { 0.2f, 0.2f, 0.2f }; - constexpr int NUM_ROWS = 200; - constexpr int NUM_COLS = 100; + constexpr int NUM_ROWS = 1; + constexpr int NUM_COLS = 1; static const SHVec3 TEST_OBJ_SPACING = { 1.0f, 1.0f, 1.0f }; static const SHVec3 TEST_OBJ_START_POS = { - (NUM_COLS / 2 * TEST_OBJ_SPACING.x ), 0.0f, 0.0f }; for (int z = 0; z < NUM_ROWS; ++z) diff --git a/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.cpp b/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.cpp index 83095371..eb65598c 100644 --- a/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.cpp +++ b/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.cpp @@ -16,7 +16,7 @@ namespace SHADE { /***************************************************************************/ /*! - + \brief Frees the command buffer. @@ -30,13 +30,13 @@ namespace SHADE /***************************************************************************/ /*! - + \brief - Only the command buffer is allocated using - VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT bit, is resetting + Only the command buffer is allocated using + VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT bit, is resetting individually permitted. Otherwise, throw exception. IMPORTANT NOTE: the command buffer cannot be in the pending state!!! - + */ /***************************************************************************/ void SHVkCommandBuffer::Reset(void) @@ -67,10 +67,10 @@ namespace SHADE /***************************************************************************/ /*! - + \brief Begins the command buffer. - + */ /***************************************************************************/ void SHVkCommandBuffer::BeginRecording(void) noexcept @@ -108,10 +108,10 @@ namespace SHADE /***************************************************************************/ /*! - + \brief End the recording of a command buffer. - + */ /***************************************************************************/ void SHVkCommandBuffer::EndRecording(void) noexcept @@ -121,21 +121,21 @@ namespace SHADE SHLOG_ERROR("Command Buffer not in recording state, cannot end recording. "); return; } - + vkCommandBuffer.end(); cmdBufferState = SH_CMD_BUFFER_STATE::EXECUTABLE; } /***************************************************************************/ /*! - + \brief - Begins a renderpass in the command buffer. 2 important things to note - here, the command buffer used MUST be a primary command buffer and + Begins a renderpass in the command buffer. 2 important things to note + here, the command buffer used MUST be a primary command buffer and command buffer MUST be in a recording state. - + \param renderpassHdl - Renderpass for obvious reasons. + Renderpass for obvious reasons. \param framebufferHdl Framebuffer required in the begin info. @@ -145,7 +145,7 @@ namespace SHADE \param extent Extent of the render area in the framebuffer. - + */ /***************************************************************************/ void SHVkCommandBuffer::BeginRenderpass(Handle const& renderpassHdl, Handle const& framebufferHdl, vk::Offset2D offset, vk::Extent2D extent) noexcept @@ -170,7 +170,7 @@ namespace SHADE vk::RenderPassBeginInfo renderPassInfo{}; renderPassInfo.renderPass = renderpassHdl->GetVkRenderpass(); renderPassInfo.framebuffer = framebufferHdl->GetVkFramebuffer(); - + // If the extent passed in is 0, use the framebuffer dimensions instead. if (extent.width == 0 && extent.height == 0) renderPassInfo.renderArea.extent = framebufferExtent; @@ -192,16 +192,16 @@ namespace SHADE } // Begin the render pass - vkCommandBuffer.beginRenderPass (&renderPassInfo, vk::SubpassContents::eInline); + vkCommandBuffer.beginRenderPass(&renderPassInfo, vk::SubpassContents::eInline); } /***************************************************************************/ /*! - + \brief Ends a renderpass. - + */ /***************************************************************************/ void SHVkCommandBuffer::EndRenderpass(void) noexcept @@ -216,14 +216,14 @@ namespace SHADE /***************************************************************************/ /*! - + \brief Sets the viewport dynamically for the command buffer. #NoteToSelf: Dynamic state will not affect pipelines that don't use dynamic state so there isn't a need to do any checks. Also, setting dynamic state like this only needs to happen ONCE per command buffer UNLESS a different viewport is to be used for different drawing commands. - + \param vpWidth viewport width @@ -254,7 +254,7 @@ namespace SHADE \param vpMaxDepth viewport maximum depth value - + */ /***************************************************************************/ void SHVkCommandBuffer::SetViewportScissor(float vpWidth, float vpHeight, uint32_t sWidth, uint32_t sHeight, float vpX /*= 0.0f*/, float vpY /*= 0.0f*/, int32_t sX /*= 0.0f*/, int32_t sY /*= 0.0f*/, float vpMinDepth /*= 0.0f*/, float vpMaxDepth /*= 1.0f*/) noexcept @@ -283,13 +283,13 @@ namespace SHADE /***************************************************************************/ /*! - + \brief Binds a pipeline object to the command buffer. - + \param pipelineHdl The pipeline to bind. - + */ /***************************************************************************/ void SHVkCommandBuffer::BindPipeline(Handle const& pipelineHdl) noexcept @@ -307,7 +307,7 @@ namespace SHADE /*! \brief - Binds a buffer to the vertex buffer binding point specified in + Binds a buffer to the vertex buffer binding point specified in bindingPoint. \param bindingPoint @@ -321,29 +321,32 @@ namespace SHADE */ /***************************************************************************/ - void SHVkCommandBuffer::BindVertexBuffer (uint32_t bindingPoint, Handle const& buffer, vk::DeviceSize offset) noexcept + void SHVkCommandBuffer::BindVertexBuffer(uint32_t bindingPoint, Handle const& buffer, vk::DeviceSize offset) noexcept { if (cmdBufferState == SH_CMD_BUFFER_STATE::RECORDING) { - auto bufferHandle = buffer->GetVkBuffer(); - vkCommandBuffer.bindVertexBuffers (bindingPoint, 1, &bufferHandle, &offset); + if (buffer) + { + auto bufferHandle = buffer->GetVkBuffer(); + vkCommandBuffer.bindVertexBuffers(bindingPoint, 1, &bufferHandle, &offset); + } } } /***************************************************************************/ /*! - + \brief Binds an index buffer to the pipeline. - + \param buffer The buffer to bind. \param startingIndex - The starting index in the index buffer. For example, 0 would mean - starting at the beginning. 5 would mean starting at byte offset + The starting index in the index buffer. For example, 0 would mean + starting at the beginning. 5 would mean starting at byte offset size(uint32_t) * 5. - + */ /***************************************************************************/ void SHVkCommandBuffer::BindIndexBuffer(Handle const& buffer, uint32_t startingIndex) const noexcept @@ -351,33 +354,33 @@ namespace SHADE if (cmdBufferState == SH_CMD_BUFFER_STATE::RECORDING) { auto bufferHandle = buffer->GetVkBuffer(); - vkCommandBuffer.bindIndexBuffer (bufferHandle, sizeof (uint32_t) * startingIndex, vk::IndexType::eUint32); + vkCommandBuffer.bindIndexBuffer(bufferHandle, sizeof(uint32_t) * startingIndex, vk::IndexType::eUint32); } } void SHVkCommandBuffer::BindDescriptorSet(Handle descSetGroup, vk::PipelineBindPoint bindPoint, uint32_t firstSet, std::span dynamicOffsets) { - vkCommandBuffer.bindDescriptorSets (bindPoint, boundPipelineLayoutHdl->GetVkPipelineLayout(), firstSet, descSetGroup->GetVkHandle(), dynamicOffsets); + vkCommandBuffer.bindDescriptorSets(bindPoint, boundPipelineLayoutHdl->GetVkPipelineLayout(), firstSet, descSetGroup->GetVkHandle(), dynamicOffsets); } /***************************************************************************/ /*! - + \brief Calls vkCmdDraw. - + \param vertexCount How many vertices to draw \param instanceCount Number of instances to draw - + \param firstVertex First vertex in the buffer of vertices to start from \param firstInstance First instance to start from. - + */ /***************************************************************************/ void SHVkCommandBuffer::DrawArrays(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance) const noexcept @@ -387,30 +390,30 @@ namespace SHADE SHLOG_ERROR("Command buffer must have started recording before a pipeline can be bound. "); return; } - vkCommandBuffer.draw (vertexCount, instanceCount, firstVertex, firstInstance); + vkCommandBuffer.draw(vertexCount, instanceCount, firstVertex, firstInstance); } /***************************************************************************/ /*! - + \brief Issues a non-instanced indexed draw call. - + \param indexCount Number of indices to draw. \param firstIndex Starting index. if the array was 0, 2, 5, 4, and we indicated this to be - 1. The draw call would start from index 2. + 1. The draw call would start from index 2. \param vertexOffset - Starting vertex offset. This would indicate that vertex pulling should + Starting vertex offset. This would indicate that vertex pulling should start from a certain vertex. So a vertex offset of 3 (for example) would mean an index of 0 would mean the 3rd vertex. - + */ /***************************************************************************/ - void SHVkCommandBuffer::DrawIndexed (uint32_t indexCount, uint32_t firstIndex, uint32_t vertexOffset) const noexcept + void SHVkCommandBuffer::DrawIndexed(uint32_t indexCount, uint32_t firstIndex, uint32_t vertexOffset) const noexcept { if (cmdBufferState != SH_CMD_BUFFER_STATE::RECORDING) { @@ -422,7 +425,7 @@ namespace SHADE vkCommandBuffer.drawIndexed(indexCount, 1, firstIndex, vertexOffset, 0); } - + /***************************************************************************/ /*! @@ -445,35 +448,36 @@ namespace SHADE return; } - vkCommandBuffer.drawIndexedIndirect(indirectDrawData->GetVkBuffer(), 0, drawCount, sizeof(vk::DrawIndexedIndirectCommand)); + if (indirectDrawData) + vkCommandBuffer.drawIndexedIndirect(indirectDrawData->GetVkBuffer(), 0, drawCount, sizeof(vk::DrawIndexedIndirectCommand)); } void SHVkCommandBuffer::CopyBufferToImage(const vk::Buffer& src, const vk::Image& dst, const std::vector& copyInfo) { - vkCommandBuffer.copyBufferToImage - ( - src, dst, vk::ImageLayout::eTransferDstOptimal, - static_cast(copyInfo.size()), copyInfo.data() - ); + vkCommandBuffer.copyBufferToImage + ( + src, dst, vk::ImageLayout::eTransferDstOptimal, + static_cast(copyInfo.size()), copyInfo.data() + ); } void SHVkCommandBuffer::PipelineBarrier( - vk::PipelineStageFlags srcStage, - vk::PipelineStageFlags dstStage, - vk::DependencyFlags deps, - std::vector const& memoryBarriers, - std::vector const& bufferMemoryBarriers, - std::vector const& imageMemoryBarriers - ) const noexcept + vk::PipelineStageFlags srcStage, + vk::PipelineStageFlags dstStage, + vk::DependencyFlags deps, + std::vector const& memoryBarriers, + std::vector const& bufferMemoryBarriers, + std::vector const& imageMemoryBarriers + ) const noexcept { - vkCommandBuffer.pipelineBarrier ( - srcStage, - dstStage, - deps, - memoryBarriers, - bufferMemoryBarriers, - imageMemoryBarriers - ); + vkCommandBuffer.pipelineBarrier( + srcStage, + dstStage, + deps, + memoryBarriers, + bufferMemoryBarriers, + imageMemoryBarriers + ); } bool SHVkCommandBuffer::IsReadyToSubmit(void) const noexcept @@ -498,10 +502,10 @@ namespace SHADE /***************************************************************************/ /*! - + \brief Calls vkCmdPushConstants and submits data stored in command buffer. - + */ /***************************************************************************/ void SHVkCommandBuffer::SubmitPushConstants(void) const noexcept @@ -514,13 +518,13 @@ namespace SHADE /***************************************************************************/ /*! - + \brief Simply returns the command buffer handle. - - \return + + \return The command buffer handle. - + */ /***************************************************************************/ vk::CommandBuffer const& SHVkCommandBuffer::GetVkCommandBuffer(void) const noexcept @@ -530,11 +534,11 @@ namespace SHADE /***************************************************************************/ /*! - + \brief - See https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/vkGetRenderAreaGranularity.html + See https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/vkGetRenderAreaGranularity.html or look up vkGetRenderAreaGranularity. - + \param renderpassHdl Renderpass to get info from. @@ -544,9 +548,9 @@ namespace SHADE \param renderArea For the comparison. Again, look it up on the webpage. - \return + \return If optimal, true. otherwise false. - + */ /***************************************************************************/ bool SHVkCommandBuffer::IsRenderAreaOptimal(Handle const& renderpassHdl, vk::Extent2D const& framebufferExtent, vk::Rect2D const& renderArea) const noexcept @@ -558,14 +562,14 @@ namespace SHADE /***************************************************************************/ /*! - + \brief Setter for the state of the command buffer. - + \param state - - \return - + + \return + */ /***************************************************************************/ void SHVkCommandBuffer::SetState(SH_CMD_BUFFER_STATE state) noexcept @@ -575,12 +579,12 @@ namespace SHADE /***************************************************************************/ /*! - + \brief Returns the state of the command buffer. - - \return - + + \return + */ /***************************************************************************/ SH_CMD_BUFFER_STATE SHVkCommandBuffer::GetState(void) const noexcept @@ -590,14 +594,14 @@ namespace SHADE /***************************************************************************/ /*! - + \brief Creates a command buffer. Cmd buffer can be primary or secondary. If secondary, flags will automatically have renderpass continue bit. Command pool used to create this command buffer will determine whether or not - this buffer will be allocated with + this buffer will be allocated with VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT using the reset mode. - + \param logicalDevice Need a logical device to create a buffer. @@ -606,7 +610,7 @@ namespace SHADE \param type Type of the command buffer; primary or secondary. - + */ /***************************************************************************/ SHVkCommandBuffer::SHVkCommandBuffer(Handle const& commandPool, SH_CMD_BUFFER_TYPE type) noexcept @@ -616,7 +620,7 @@ namespace SHADE , parentPoolResetMode{ SH_CMD_POOL_RESET::POOL_BASED } , usageFlags{} , commandBufferCount{ 0 } - , parentPool{commandPool} + , parentPool{ commandPool } , pushConstantData{} { @@ -657,54 +661,54 @@ namespace SHADE commandBufferType = type; commandBufferCount = allocateInfo.commandBufferCount; - if (parentPool->GetIsTransient ()) + if (parentPool->GetIsTransient()) usageFlags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit; if (commandBufferType == SH_CMD_BUFFER_TYPE::SECONDARY) usageFlags |= vk::CommandBufferUsageFlagBits::eRenderPassContinue; - + // Reset all the push constant data to 0 - memset (pushConstantData, 0, PUSH_CONSTANT_SIZE); + memset(pushConstantData, 0, PUSH_CONSTANT_SIZE); } /***************************************************************************/ /*! - + \brief Move ctor. Invalidates Vulkan handles. - + \param rhs the other command buffer. - + */ /***************************************************************************/ SHVkCommandBuffer::SHVkCommandBuffer(SHVkCommandBuffer&& rhs) noexcept - : vkCommandBuffer {std::move (rhs.vkCommandBuffer)} - , cmdBufferState {rhs.cmdBufferState} - , commandBufferType {rhs.commandBufferType} - , parentPoolResetMode {rhs.parentPoolResetMode} - , usageFlags {rhs.usageFlags} - , commandBufferCount {rhs.commandBufferCount} - , parentPool {rhs.parentPool} - , boundPipelineLayoutHdl{rhs.boundPipelineLayoutHdl } + : vkCommandBuffer{ std::move(rhs.vkCommandBuffer) } + , cmdBufferState{ rhs.cmdBufferState } + , commandBufferType{ rhs.commandBufferType } + , parentPoolResetMode{ rhs.parentPoolResetMode } + , usageFlags{ rhs.usageFlags } + , commandBufferCount{ rhs.commandBufferCount } + , parentPool{ rhs.parentPool } + , boundPipelineLayoutHdl{ rhs.boundPipelineLayoutHdl } { - memcpy (pushConstantData, rhs.pushConstantData, PUSH_CONSTANT_SIZE); + memcpy(pushConstantData, rhs.pushConstantData, PUSH_CONSTANT_SIZE); rhs.vkCommandBuffer = VK_NULL_HANDLE; } /***************************************************************************/ /*! - + \brief Move assignment operator. Invalidates Vulkan handles. - + \param rhs The other Vulkan Handle. - - \return + + \return a reference itself. - + */ /***************************************************************************/ SHVkCommandBuffer& SHVkCommandBuffer::operator=(SHVkCommandBuffer&& rhs) noexcept diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp index 7b2ebd49..f73c5306 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp @@ -203,7 +203,8 @@ namespace SHADE } // Transfer to GPU - transformDataBuffer[frameIndex]->WriteToMemory(transformData.data(), static_cast(transformData.size() * sizeof(SHMatrix)), 0, 0); + if (transformDataBuffer[frameIndex]) + transformDataBuffer[frameIndex]->WriteToMemory(transformData.data(), static_cast(transformData.size() * sizeof(SHMatrix)), 0, 0); } void SHBatch::Build(Handle _device, uint32_t frameIndex) diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp index b909aeff..bb2391e3 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp @@ -150,9 +150,9 @@ namespace SHADE //compositeSubpass->AddInput("Position"); // TODO: Use macro to add this node when SH_EDITOR is enabled - //auto imguiNode = worldRenderGraph->AddNode("ImGui Node", { "Present" }, {}); - //auto imguiSubpass = imguiNode->AddSubpass("ImGui Draw"); - //imguiSubpass->AddColorOutput("Present"); + auto imguiNode = worldRenderGraph->AddNode("ImGui Node", { "Present" }, {}); + auto imguiSubpass = imguiNode->AddSubpass("ImGui Draw"); + imguiSubpass->AddColorOutput("Present"); worldRenderGraph->Generate(); diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp index 6070361f..7ef5c0b9 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp @@ -348,7 +348,7 @@ namespace SHADE void SHSubpass::Execute(Handle& commandBuffer, uint32_t frameIndex) noexcept { - // Ensure updated transforms and materials are provided + // Ensure correct transforms are provided superBatch->UpdateBuffers(frameIndex); // Draw all the batches @@ -524,6 +524,7 @@ namespace SHADE , configured{ rhs.configured } , executed{ rhs.executed } , ptrToResources{ rhs.ptrToResources } + , pipelineLibrary{ std::move(rhs.pipelineLibrary) } { rhs.renderpass = {}; } @@ -544,6 +545,7 @@ namespace SHADE resourceAttachmentMapping = std::move(rhs.resourceAttachmentMapping); subpassIndexing = std::move(rhs.subpassIndexing); ptrToResources = std::move(rhs.ptrToResources); + pipelineLibrary = std::move(rhs.pipelineLibrary); rhs.renderpass = {}; @@ -625,7 +627,7 @@ namespace SHADE } void SHRenderGraphNode::FinaliseBatch(uint32_t frameIndex) -{ + { batcher.FinaliseBatches(logicalDeviceHdl, frameIndex); } @@ -993,6 +995,34 @@ namespace SHADE } + SHRenderGraph::SHRenderGraph(SHRenderGraph&& rhs) noexcept + : logicalDeviceHdl{ rhs.logicalDeviceHdl } + , swapchainHdl{ rhs.swapchainHdl } + , nodeIndexing{ std::move(rhs.nodeIndexing) } + , nodes{ std::move(rhs.nodes) } + , graphResources{ std::move(rhs.graphResources) } + , resourceManager{ std::move(rhs.resourceManager) } + , globalData{ rhs.globalData } + { + + } + + SHRenderGraph& SHRenderGraph::operator=(SHRenderGraph&& rhs) noexcept + { + if (&rhs == this) + return *this; + + logicalDeviceHdl = rhs.logicalDeviceHdl; + swapchainHdl = rhs.swapchainHdl; + nodeIndexing = std::move(rhs.nodeIndexing); + nodes = std::move(rhs.nodes); + graphResources = std::move(rhs.graphResources); + resourceManager = std::move(rhs.resourceManager); + globalData = rhs.globalData; + + return *this; + } + /***************************************************************************/ /*! @@ -1084,7 +1114,7 @@ namespace SHADE } void SHRenderGraph::FinaliseBatch(uint32_t frameIndex) -{ + { for (auto& node : nodes) { node->FinaliseBatch(frameIndex); diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h index b8c00417..d5421bdc 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h @@ -279,6 +279,8 @@ namespace SHADE /* CTORS AND DTORS */ /*-----------------------------------------------------------------------*/ SHRenderGraph (void) noexcept; + SHRenderGraph(SHRenderGraph&& rhs) noexcept; + SHRenderGraph& operator=(SHRenderGraph&& rhs) noexcept; /*-----------------------------------------------------------------------*/ /* PUBLIC MEMBER FUNCTIONS */ From 864983360425cba5505f4d306cabe8e99c07aca9 Mon Sep 17 00:00:00 2001 From: Brandon Mak Date: Sun, 25 Sep 2022 23:45:05 +0800 Subject: [PATCH 10/13] subpass not null anymore --- SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp | 8 +++++++- SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h | 2 ++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp index 7ef5c0b9..85d822b5 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp @@ -220,7 +220,6 @@ namespace SHADE , depthReferences{} , inputReferences{} { - superBatch = rm.Create(GetHandle()); } /***************************************************************************/ @@ -366,6 +365,12 @@ namespace SHADE exteriorDrawCalls.push_back(newDrawCall); } + void SHSubpass::Init(ResourceManager& resourceManager) noexcept + { + superBatch = resourceManager.Create(GetHandle()); + + } + /***************************************************************************/ /*! @@ -579,6 +584,7 @@ namespace SHADE subpasses.emplace_back(resourceManager.Create(resourceManager, GetHandle(), subpasses.size(), &resourceAttachmentMapping, ptrToResources)); subpassIndexing.try_emplace(subpassName, static_cast(subpasses.size()) - 1u); Handle subpass = subpasses.back(); + subpass->Init(resourceManager); // Register the SuperBatch batcher.RegisterSuperBatch(subpass->GetSuperBatch()); diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h index d5421bdc..45624436 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h @@ -140,6 +140,8 @@ namespace SHADE void Execute(Handle& commandBuffer, uint32_t frameIndex) noexcept; void AddExteriorDrawCalls(std::function&)> const& newDrawCall) noexcept; + void Init (ResourceManager& resourceManager) noexcept; + /*-----------------------------------------------------------------------*/ /* GETTERS AND SETTERS */ /*-----------------------------------------------------------------------*/ From a5c804ca8bba5f62921ca6b5e92fe651da2f916b Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Mon, 26 Sep 2022 00:08:32 +0800 Subject: [PATCH 11/13] Fixed SHRenderGraph not moving the batcher --- SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp index 85d822b5..92276f95 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp @@ -530,6 +530,8 @@ namespace SHADE , executed{ rhs.executed } , ptrToResources{ rhs.ptrToResources } , pipelineLibrary{ std::move(rhs.pipelineLibrary) } + , batcher { std::move(rhs.batcher) } + { rhs.renderpass = {}; } @@ -551,6 +553,7 @@ namespace SHADE subpassIndexing = std::move(rhs.subpassIndexing); ptrToResources = std::move(rhs.ptrToResources); pipelineLibrary = std::move(rhs.pipelineLibrary); + batcher = std::move(rhs.batcher); rhs.renderpass = {}; From 31dff230ef62e09237293e0a4d822c3db1d4f315 Mon Sep 17 00:00:00 2001 From: Brandon Mak Date: Mon, 26 Sep 2022 00:37:58 +0800 Subject: [PATCH 12/13] FIXED MY SHIT WHEE --- .../src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp | 2 +- SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp index bb2391e3..2637cb75 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp @@ -150,7 +150,7 @@ namespace SHADE //compositeSubpass->AddInput("Position"); // TODO: Use macro to add this node when SH_EDITOR is enabled - auto imguiNode = worldRenderGraph->AddNode("ImGui Node", { "Present" }, {}); + auto imguiNode = worldRenderGraph->AddNode("ImGui Node", { "Present" }, {"G-Buffer"}); auto imguiSubpass = imguiNode->AddSubpass("ImGui Draw"); imguiSubpass->AddColorOutput("Present"); diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp index 92276f95..3f5641c0 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp @@ -716,7 +716,7 @@ namespace SHADE // First we want to take all the attachment descriptions and initialize the // finalLayout to whatever layout is specified in the last subpass that references the attachment. - for (auto& node : nodes) + for (uint32_t i = 0; auto& node : nodes) { // key is handle ID, value is pair (first is initial layout, second is final layout). std::unordered_map resourceAttLayouts; @@ -730,7 +730,7 @@ namespace SHADE { for (auto& color : subpass->colorReferences) { - if (node->attResources[color.attachment]->resourceType == SH_ATT_DESC_TYPE::COLOR_PRESENT) + if (i == nodes.size() - 1 && node->attResources[color.attachment]->resourceType == SH_ATT_DESC_TYPE::COLOR_PRESENT) resourceAttLayouts[color.attachment] = vk::ImageLayout::ePresentSrcKHR; else resourceAttLayouts[color.attachment] = color.layout; @@ -749,6 +749,7 @@ namespace SHADE att.initialLayout = vk::ImageLayout::eUndefined; att.finalLayout = resourceAttLayouts[i]; } + ++i; } // at this point all attachment descs will have their final layouts initialized as if they were standalone and did @@ -857,7 +858,7 @@ namespace SHADE for (auto& inputAtt : subpass->inputReferences) { auto resource = node->attResources[inputAtt.attachment]; - if (resource->resourceType == SH_ATT_DESC_TYPE::COLOR) + if (resource->resourceType == SH_ATT_DESC_TYPE::COLOR || resource->resourceType == SH_ATT_DESC_TYPE::COLOR_PRESENT) colorRead |= (1 << i); else if (resource->resourceType == SH_ATT_DESC_TYPE::DEPTH_STENCIL) depthRead |= (1 << i); From 6d68e6cb5e2df8fade43c6aa779644bd0e05993a Mon Sep 17 00:00:00 2001 From: Brandon Mak Date: Mon, 26 Sep 2022 00:37:58 +0800 Subject: [PATCH 13/13] FIXED MY SHIT WHEE (render graph color present attachment now have correct layout) --- .../src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp | 2 +- SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp index bb2391e3..2637cb75 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp @@ -150,7 +150,7 @@ namespace SHADE //compositeSubpass->AddInput("Position"); // TODO: Use macro to add this node when SH_EDITOR is enabled - auto imguiNode = worldRenderGraph->AddNode("ImGui Node", { "Present" }, {}); + auto imguiNode = worldRenderGraph->AddNode("ImGui Node", { "Present" }, {"G-Buffer"}); auto imguiSubpass = imguiNode->AddSubpass("ImGui Draw"); imguiSubpass->AddColorOutput("Present"); diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp index 92276f95..3f5641c0 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp @@ -716,7 +716,7 @@ namespace SHADE // First we want to take all the attachment descriptions and initialize the // finalLayout to whatever layout is specified in the last subpass that references the attachment. - for (auto& node : nodes) + for (uint32_t i = 0; auto& node : nodes) { // key is handle ID, value is pair (first is initial layout, second is final layout). std::unordered_map resourceAttLayouts; @@ -730,7 +730,7 @@ namespace SHADE { for (auto& color : subpass->colorReferences) { - if (node->attResources[color.attachment]->resourceType == SH_ATT_DESC_TYPE::COLOR_PRESENT) + if (i == nodes.size() - 1 && node->attResources[color.attachment]->resourceType == SH_ATT_DESC_TYPE::COLOR_PRESENT) resourceAttLayouts[color.attachment] = vk::ImageLayout::ePresentSrcKHR; else resourceAttLayouts[color.attachment] = color.layout; @@ -749,6 +749,7 @@ namespace SHADE att.initialLayout = vk::ImageLayout::eUndefined; att.finalLayout = resourceAttLayouts[i]; } + ++i; } // at this point all attachment descs will have their final layouts initialized as if they were standalone and did @@ -857,7 +858,7 @@ namespace SHADE for (auto& inputAtt : subpass->inputReferences) { auto resource = node->attResources[inputAtt.attachment]; - if (resource->resourceType == SH_ATT_DESC_TYPE::COLOR) + if (resource->resourceType == SH_ATT_DESC_TYPE::COLOR || resource->resourceType == SH_ATT_DESC_TYPE::COLOR_PRESENT) colorRead |= (1 << i); else if (resource->resourceType == SH_ATT_DESC_TYPE::DEPTH_STENCIL) depthRead |= (1 << i);