From bc02c0560edecdff46aa430ff53edd37e0ea754c Mon Sep 17 00:00:00 2001 From: InoriRus Date: Wed, 27 Apr 2022 18:49:15 +1000 Subject: [PATCH] one step closer to run games --- appveyor.yml | 2 +- source/CMakeLists.txt | 2 +- source/emulator/include/Emulator/Audio.h | 13 + source/emulator/include/Emulator/Controller.h | 3 + source/emulator/include/Emulator/Dialog.h | 10 + .../include/Emulator/Graphics/Graphics.h | 1 + .../Emulator/Graphics/GraphicsRender.h | 39 +- .../Emulator/Graphics/HardwareContext.h | 102 +- .../Graphics/Objects/DepthStencilBuffer.h | 1 + .../Emulator/Graphics/Objects/GpuMemory.h | 8 +- .../include/Emulator/Graphics/Objects/Label.h | 8 +- .../emulator/include/Emulator/Graphics/Pm4.h | 22 + .../include/Emulator/Graphics/Shader.h | 20 +- .../emulator/include/Emulator/Graphics/Tile.h | 14 +- .../include/Emulator/Kernel/FileSystem.h | 2 + .../include/Emulator/Kernel/Pthread.h | 4 + source/emulator/include/Emulator/Libs/Errno.h | 14 + source/emulator/include/Emulator/Network.h | 32 + source/emulator/src/Audio.cpp | 191 +++- source/emulator/src/Controller.cpp | 131 ++- source/emulator/src/Dialog.cpp | 30 + source/emulator/src/Graphics/Graphics.cpp | 29 + .../emulator/src/Graphics/GraphicsRender.cpp | 743 +++++++++------ source/emulator/src/Graphics/GraphicsRun.cpp | 222 +++-- .../Graphics/Objects/DepthStencilBuffer.cpp | 6 + .../src/Graphics/Objects/GpuMemory.cpp | 877 ++++++++++-------- .../emulator/src/Graphics/Objects/Label.cpp | 99 +- source/emulator/src/Graphics/Shader.cpp | 51 +- source/emulator/src/Graphics/ShaderSpirv.cpp | 46 +- source/emulator/src/Graphics/Tile.cpp | 305 +++--- source/emulator/src/Graphics/Utils.cpp | 4 + source/emulator/src/Graphics/VideoOut.cpp | 28 +- source/emulator/src/Graphics/Window.cpp | 21 +- source/emulator/src/Kernel/FileSystem.cpp | 70 +- source/emulator/src/Kernel/Pthread.cpp | 24 + source/emulator/src/Libs/LibAudio.cpp | 29 + source/emulator/src/Libs/LibDialog.cpp | 16 + .../emulator/src/Libs/LibGraphicsDriver.cpp | 1 + source/emulator/src/Libs/LibKernel.cpp | 15 + source/emulator/src/Libs/LibNet.cpp | 24 + source/emulator/src/Libs/LibPad.cpp | 2 + source/emulator/src/Libs/LibSaveData.cpp | 103 +- source/emulator/src/Libs/LibSystemService.cpp | 21 + source/emulator/src/Libs/LibUserService.cpp | 13 + source/emulator/src/Network.cpp | 703 +++++++++++++- source/lib/Core/src/Threads.cpp | 22 +- source/unit_test/CMakeLists.txt | 5 - 47 files changed, 3020 insertions(+), 1108 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index d8ac4aa..f3fea8a 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 0.0.14.build-{build} +version: 0.0.15.build-{build} image: Visual Studio 2019 environment: matrix: diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index 28fd5d3..875e4e9 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -82,7 +82,7 @@ if (KYTY_LINKER STREQUAL LD) set(KYTY_LD_OPTIONS "-Wl,--image-base=0x100000000000") endif() -project(Kyty${KYTY_PROJECT_NAME}${CMAKE_BUILD_TYPE}${KYTY_COMPILER} VERSION 0.0.14) +project(Kyty${KYTY_PROJECT_NAME}${CMAKE_BUILD_TYPE}${KYTY_COMPILER} VERSION 0.0.15) include(src_script.cmake) diff --git a/source/emulator/include/Emulator/Audio.h b/source/emulator/include/Emulator/Audio.h index 11997e1..552408e 100644 --- a/source/emulator/include/Emulator/Audio.h +++ b/source/emulator/include/Emulator/Audio.h @@ -23,12 +23,25 @@ int KYTY_SYSV_ABI AudioOutOutputs(AudioOutOutputParam* param, uint32_t num); } // namespace AudioOut +namespace AudioIn { + +int KYTY_SYSV_ABI AudioInOpen(int user_id, uint32_t type, uint32_t index, uint32_t len, uint32_t freq, uint32_t param); +int KYTY_SYSV_ABI AudioInInput(int handle, void* dest); + +} // namespace AudioIn + namespace VoiceQoS { int KYTY_SYSV_ABI VoiceQoSInit(void* mem_block, uint32_t mem_size, int32_t app_type); } // namespace VoiceQoS +namespace Ajm { + +int KYTY_SYSV_ABI AjmInitialize(int64_t reserved, uint32_t* context); + +} // namespace Ajm + } // namespace Kyty::Libs::Audio #endif // KYTY_EMU_ENABLED diff --git a/source/emulator/include/Emulator/Controller.h b/source/emulator/include/Emulator/Controller.h index ad31afa..3ed01b6 100644 --- a/source/emulator/include/Emulator/Controller.h +++ b/source/emulator/include/Emulator/Controller.h @@ -43,6 +43,7 @@ enum class Axis struct PadControllerInformation; struct PadData; +struct PadVibrationParam; inline int controller_get_axis(int min, int max, int value) { @@ -60,6 +61,8 @@ int KYTY_SYSV_ABI PadOpen(int user_id, int type, int index, const void* param); int KYTY_SYSV_ABI PadSetMotionSensorState(int handle, bool enable); int KYTY_SYSV_ABI PadGetControllerInformation(int handle, PadControllerInformation* info); int KYTY_SYSV_ABI PadReadState(int handle, PadData* data); +int KYTY_SYSV_ABI PadRead(int handle, PadData* data, int num); +int KYTY_SYSV_ABI PadSetVibration(int handle, const PadVibrationParam* param); } // namespace Kyty::Libs::Controller diff --git a/source/emulator/include/Emulator/Dialog.h b/source/emulator/include/Emulator/Dialog.h index bf59386..36cbfa6 100644 --- a/source/emulator/include/Emulator/Dialog.h +++ b/source/emulator/include/Emulator/Dialog.h @@ -1,6 +1,8 @@ #ifndef EMULATOR_INCLUDE_EMULATOR_DIALOG_H_ #define EMULATOR_INCLUDE_EMULATOR_DIALOG_H_ +#include "Kyty/Core/Common.h" + #include "Emulator/Common.h" #ifdef KYTY_EMU_ENABLED @@ -13,6 +15,14 @@ int KYTY_SYSV_ABI CommonDialogInitialize(); } // namespace CommonDialog +namespace SaveDataDialog { + +int KYTY_SYSV_ABI SaveDataDialogUpdateStatus(); +int KYTY_SYSV_ABI SaveDataDialogTerminate(); +int KYTY_SYSV_ABI SaveDataDialogProgressBarSetValue(int target, uint32_t rate); + +} // namespace SaveDataDialog + } // namespace Kyty::Libs::Dialog #endif // KYTY_EMU_ENABLED diff --git a/source/emulator/include/Emulator/Graphics/Graphics.h b/source/emulator/include/Emulator/Graphics/Graphics.h index 47dbd15..30f5c59 100644 --- a/source/emulator/include/Emulator/Graphics/Graphics.h +++ b/source/emulator/include/Emulator/Graphics/Graphics.h @@ -24,6 +24,7 @@ int KYTY_SYSV_ABI GraphicsUpdateVsShader(uint32_t* cmd, uint64_t size, cons int KYTY_SYSV_ABI GraphicsSetPsShader(uint32_t* cmd, uint64_t size, const uint32_t* ps_regs); int KYTY_SYSV_ABI GraphicsSetPsShader350(uint32_t* cmd, uint64_t size, const uint32_t* ps_regs); int KYTY_SYSV_ABI GraphicsUpdatePsShader(uint32_t* cmd, uint64_t size, const uint32_t* ps_regs); +int KYTY_SYSV_ABI GraphicsUpdatePsShader350(uint32_t* cmd, uint64_t size, const uint32_t* ps_regs); int KYTY_SYSV_ABI GraphicsSetCsShaderWithModifier(uint32_t* cmd, uint64_t size, const uint32_t* cs_regs, uint32_t shader_modifier); int KYTY_SYSV_ABI GraphicsSetEmbeddedVsShader(uint32_t* cmd, uint64_t size, uint32_t id, uint32_t shader_modifier); int KYTY_SYSV_ABI GraphicsDrawIndex(uint32_t* cmd, uint64_t size, uint32_t index_count, const void* index_addr, uint32_t flags, diff --git a/source/emulator/include/Emulator/Graphics/GraphicsRender.h b/source/emulator/include/Emulator/Graphics/GraphicsRender.h index ee1392d..b07f2fb 100644 --- a/source/emulator/include/Emulator/Graphics/GraphicsRender.h +++ b/source/emulator/include/Emulator/Graphics/GraphicsRender.h @@ -69,24 +69,29 @@ private: void GraphicsRenderInit(); void GraphicsRenderCreateContext(); -void GraphicsRenderDrawIndex(CommandBuffer* buffer, HW::HardwareContext* ctx, HW::UserConfig* ucfg, uint32_t index_type_and_size, - uint32_t index_count, const void* index_addr, uint32_t flags, uint32_t type); -void GraphicsRenderDrawIndexAuto(CommandBuffer* buffer, HW::HardwareContext* ctx, HW::UserConfig* ucfg, uint32_t index_count, - uint32_t flags); -void GraphicsRenderWriteAtEndOfPipe(CommandBuffer* buffer, uint64_t* dst_gpu_addr, uint64_t value); -void GraphicsRenderWriteAtEndOfPipeClockCounter(CommandBuffer* buffer, uint64_t* dst_gpu_addr); -void GraphicsRenderWriteAtEndOfPipe(CommandBuffer* buffer, uint32_t* dst_gpu_addr, uint32_t value); -void GraphicsRenderWriteAtEndOfPipeGds(CommandBuffer* buffer, uint32_t* dst_gpu_addr, uint32_t dw_offset, uint32_t dw_num); -void GraphicsRenderWriteAtEndOfPipeWithInterruptWriteBackFlip(CommandBuffer* buffer, uint32_t* dst_gpu_addr, uint32_t value, int handle, - int index, int flip_mode, int64_t flip_arg); -void GraphicsRenderWriteAtEndOfPipeWithFlip(CommandBuffer* buffer, uint32_t* dst_gpu_addr, uint32_t value, int handle, int index, - int flip_mode, int64_t flip_arg); -void GraphicsRenderWriteAtEndOfPipeWithWriteBack(CommandBuffer* buffer, uint64_t* dst_gpu_addr, uint64_t value); -void GraphicsRenderWriteAtEndOfPipeWithInterruptWriteBack(CommandBuffer* buffer, uint64_t* dst_gpu_addr, uint64_t value); -void GraphicsRenderWriteAtEndOfPipeWithInterrupt(CommandBuffer* buffer, uint64_t* dst_gpu_addr, uint64_t value); +void GraphicsRenderDrawIndex(uint64_t submit_id, CommandBuffer* buffer, HW::HardwareContext* ctx, HW::UserConfig* ucfg, + uint32_t index_type_and_size, uint32_t index_count, const void* index_addr, uint32_t flags, uint32_t type); +void GraphicsRenderDrawIndexAuto(uint64_t submit_id, CommandBuffer* buffer, HW::HardwareContext* ctx, HW::UserConfig* ucfg, + uint32_t index_count, uint32_t flags); +void GraphicsRenderWriteAtEndOfPipe64(uint64_t submit_id, CommandBuffer* buffer, uint64_t* dst_gpu_addr, uint64_t value); +void GraphicsRenderWriteAtEndOfPipeClockCounter(uint64_t submit_id, CommandBuffer* buffer, uint64_t* dst_gpu_addr); +void GraphicsRenderWriteAtEndOfPipe32(uint64_t submit_id, CommandBuffer* buffer, uint32_t* dst_gpu_addr, uint32_t value); +void GraphicsRenderWriteAtEndOfPipeGds32(uint64_t submit_id, CommandBuffer* buffer, uint32_t* dst_gpu_addr, uint32_t dw_offset, + uint32_t dw_num); +void GraphicsRenderWriteAtEndOfPipeWithInterruptWriteBackFlip32(uint64_t submit_id, CommandBuffer* buffer, uint32_t* dst_gpu_addr, + uint32_t value, int handle, int index, int flip_mode, int64_t flip_arg); +void GraphicsRenderWriteAtEndOfPipeWithFlip32(uint64_t submit_id, CommandBuffer* buffer, uint32_t* dst_gpu_addr, uint32_t value, int handle, + int index, int flip_mode, int64_t flip_arg); +void GraphicsRenderWriteAtEndOfPipeOnlyFlip(uint64_t submit_id, CommandBuffer* buffer, int handle, int index, int flip_mode, + int64_t flip_arg); +void GraphicsRenderWriteAtEndOfPipeWithWriteBack64(uint64_t submit_id, CommandBuffer* buffer, uint64_t* dst_gpu_addr, uint64_t value); +void GraphicsRenderWriteAtEndOfPipeWithInterruptWriteBack64(uint64_t submit_id, CommandBuffer* buffer, uint64_t* dst_gpu_addr, + uint64_t value); +void GraphicsRenderWriteAtEndOfPipeWithInterrupt64(uint64_t submit_id, CommandBuffer* buffer, uint64_t* dst_gpu_addr, uint64_t value); +void GraphicsRenderWriteAtEndOfPipeWithInterrupt32(uint64_t submit_id, CommandBuffer* buffer, uint32_t* dst_gpu_addr, uint32_t value); void GraphicsRenderWriteBack(); -void GraphicsRenderDispatchDirect(CommandBuffer* buffer, HW::HardwareContext* ctx, uint32_t thread_group_x, uint32_t thread_group_y, - uint32_t thread_group_z, uint32_t mode); +void GraphicsRenderDispatchDirect(uint64_t submit_id, CommandBuffer* buffer, HW::HardwareContext* ctx, uint32_t thread_group_x, + uint32_t thread_group_y, uint32_t thread_group_z, uint32_t mode); void GraphicsRenderMemoryBarrier(CommandBuffer* buffer); void GraphicsRenderRenderTextureBarrier(CommandBuffer* buffer, uint64_t vaddr, uint64_t size); void GraphicsRenderDepthStencilBarrier(CommandBuffer* buffer, uint64_t vaddr, uint64_t size); diff --git a/source/emulator/include/Emulator/Graphics/HardwareContext.h b/source/emulator/include/Emulator/Graphics/HardwareContext.h index 30126dc..6ebc1b1 100644 --- a/source/emulator/include/Emulator/Graphics/HardwareContext.h +++ b/source/emulator/include/Emulator/Graphics/HardwareContext.h @@ -305,16 +305,42 @@ struct ColorControl uint8_t op = 0xCC; }; +struct ScanModeControl +{ + bool msaa_enable = false; + bool vport_scissor_enable = false; + bool line_stipple_enable = false; +}; + +struct AaSampleControl +{ + uint64_t centroid_priority = 0; + uint32_t locations[16] = {}; +}; + +struct AaConfig +{ + uint8_t msaa_num_samples = 0; + bool aa_mask_centroid_dtmn = false; + uint8_t max_sample_dist = 0; + uint8_t msaa_exposed_samples = 0; +}; + struct Viewport { - float zmin = 0.0f; - float zmax = 0.0f; - float xscale = 0.0f; - float xoffset = 0.0f; - float yscale = 0.0f; - float yoffset = 0.0f; - float zscale = 0.0f; - float zoffset = 0.0f; + float zmin = 0.0f; + float zmax = 0.0f; + float xscale = 0.0f; + float xoffset = 0.0f; + float yscale = 0.0f; + float yoffset = 0.0f; + float zscale = 0.0f; + float zoffset = 0.0f; + int viewport_scissor_left = 0; + int viewport_scissor_top = 0; + int viewport_scissor_right = 0; + int viewport_scissor_bottom = 0; + bool viewport_scissor_window_offset_enable = false; }; struct ScreenViewport @@ -578,24 +604,30 @@ public: m_cs.cs_shader_modifier = shader_modifier; } - [[nodiscard]] const BlendColor& GetBlendColor() const { return m_blend_color; } - void SetBlendColor(const BlendColor& color) { m_blend_color = color; } - [[nodiscard]] const ClipControl& GetClipControl() const { return m_clip_control; } - void SetClipControl(const ClipControl& control) { m_clip_control = control; } - [[nodiscard]] const RenderControl& GetRenderControl() const { return m_render_control; } - void SetRenderControl(const RenderControl& control) { m_render_control = control; } - [[nodiscard]] const DepthControl& GetDepthControl() const { return m_depth_control; } - void SetDepthControl(const DepthControl& control) { m_depth_control = control; } - [[nodiscard]] const ModeControl& GetModeControl() const { return m_mode_control; } - void SetModeControl(const ModeControl& control) { m_mode_control = control; } - [[nodiscard]] const EqaaControl& GetEqaaControl() const { return m_eqaa_control; } - void SetEqaaControl(const EqaaControl& control) { m_eqaa_control = control; } - [[nodiscard]] const StencilControl& GetStencilControl() const { return m_stencil_control; } - void SetStencilControl(const StencilControl& control) { m_stencil_control = control; } - [[nodiscard]] const StencilMask& GetStencilMask() const { return m_stencil_mask; } - void SetStencilMask(const StencilMask& mask) { m_stencil_mask = mask; } - [[nodiscard]] const ColorControl& GetColorControl() const { return m_color_control; } - void SetColorControl(const ColorControl& control) { m_color_control = control; } + [[nodiscard]] const BlendColor& GetBlendColor() const { return m_blend_color; } + void SetBlendColor(const BlendColor& color) { m_blend_color = color; } + [[nodiscard]] const ClipControl& GetClipControl() const { return m_clip_control; } + void SetClipControl(const ClipControl& control) { m_clip_control = control; } + [[nodiscard]] const RenderControl& GetRenderControl() const { return m_render_control; } + void SetRenderControl(const RenderControl& control) { m_render_control = control; } + [[nodiscard]] const DepthControl& GetDepthControl() const { return m_depth_control; } + void SetDepthControl(const DepthControl& control) { m_depth_control = control; } + [[nodiscard]] const ModeControl& GetModeControl() const { return m_mode_control; } + void SetModeControl(const ModeControl& control) { m_mode_control = control; } + [[nodiscard]] const EqaaControl& GetEqaaControl() const { return m_eqaa_control; } + void SetEqaaControl(const EqaaControl& control) { m_eqaa_control = control; } + [[nodiscard]] const StencilControl& GetStencilControl() const { return m_stencil_control; } + void SetStencilControl(const StencilControl& control) { m_stencil_control = control; } + [[nodiscard]] const StencilMask& GetStencilMask() const { return m_stencil_mask; } + void SetStencilMask(const StencilMask& mask) { m_stencil_mask = mask; } + [[nodiscard]] const ColorControl& GetColorControl() const { return m_color_control; } + void SetColorControl(const ColorControl& control) { m_color_control = control; } + [[nodiscard]] const ScanModeControl& GetScanModeControl() const { return m_scan_mode_control; } + void SetScanModeControl(const ScanModeControl& control) { m_scan_mode_control = control; } + [[nodiscard]] const AaSampleControl& GetAaSampleControl() const { return m_aa_sample_control; } + void SetAaSampleControl(const AaSampleControl& control) { m_aa_sample_control = control; } + [[nodiscard]] const AaConfig& GetAaConfig() const { return m_aa_config; } + void SetAaConfig(const AaConfig& config) { m_aa_config = config; } void SetVsUserSgpr(uint32_t id, uint32_t value, UserSgprType type) { @@ -636,13 +668,17 @@ public: private: float m_line_width = 1.0f; - BlendControl m_blend_control[8]; - BlendColor m_blend_color; - RenderTarget m_render_targets[8]; - uint32_t m_render_target_mask = 0; - ScreenViewport m_screen_viewport; - ClipControl m_clip_control; - ColorControl m_color_control; + BlendControl m_blend_control[8]; + BlendColor m_blend_color; + RenderTarget m_render_targets[8]; + uint32_t m_render_target_mask = 0; + ScreenViewport m_screen_viewport; + ClipControl m_clip_control; + ColorControl m_color_control; + ScanModeControl m_scan_mode_control; + + AaSampleControl m_aa_sample_control; + AaConfig m_aa_config; VertexShaderInfo m_vs; PixelShaderInfo m_ps; diff --git a/source/emulator/include/Emulator/Graphics/Objects/DepthStencilBuffer.h b/source/emulator/include/Emulator/Graphics/Objects/DepthStencilBuffer.h index 8f7f854..881e741 100644 --- a/source/emulator/include/Emulator/Graphics/Objects/DepthStencilBuffer.h +++ b/source/emulator/include/Emulator/Graphics/Objects/DepthStencilBuffer.h @@ -31,6 +31,7 @@ public: } bool Equal(const uint64_t* other) const override; + // bool Reuse(const uint64_t* other) const override; [[nodiscard]] create_func_t GetCreateFunc() const override; [[nodiscard]] create_from_objects_func_t GetCreateFromObjectsFunc() const override { return nullptr; }; diff --git a/source/emulator/include/Emulator/Graphics/Objects/GpuMemory.h b/source/emulator/include/Emulator/Graphics/Objects/GpuMemory.h index 28fe848..6645508 100644 --- a/source/emulator/include/Emulator/Graphics/Objects/GpuMemory.h +++ b/source/emulator/include/Emulator/Graphics/Objects/GpuMemory.h @@ -73,6 +73,7 @@ public: KYTY_CLASS_DEFAULT_COPY(GpuObject); virtual bool Equal(const uint64_t* other) const = 0; + // virtual bool Reuse(const uint64_t* /*other*/) const { return false; }; [[nodiscard]] virtual create_func_t GetCreateFunc() const = 0; [[nodiscard]] virtual create_from_objects_func_t GetCreateFromObjectsFunc() const = 0; @@ -90,9 +91,10 @@ void GpuMemoryInit(); void GpuMemorySetAllocatedRange(uint64_t vaddr, uint64_t size); void GpuMemoryFree(GraphicContext* ctx, uint64_t vaddr, uint64_t size, bool unmap); -void* GpuMemoryCreateObject(GraphicContext* ctx, CommandBuffer* buffer, uint64_t vaddr, uint64_t size, const GpuObject& info); -void* GpuMemoryCreateObject(GraphicContext* ctx, CommandBuffer* buffer, const uint64_t* vaddr, const uint64_t* size, int vaddr_num, +void* GpuMemoryCreateObject(uint64_t submit_id, GraphicContext* ctx, CommandBuffer* buffer, uint64_t vaddr, uint64_t size, const GpuObject& info); +void* GpuMemoryCreateObject(uint64_t submit_id, GraphicContext* ctx, CommandBuffer* buffer, const uint64_t* vaddr, const uint64_t* size, + int vaddr_num, const GpuObject& info); void GpuMemoryResetHash(GraphicContext* ctx, const uint64_t* vaddr, const uint64_t* size, int vaddr_num, GpuMemoryObjectType type); void GpuMemoryDbgDump(); void GpuMemoryFlush(GraphicContext* ctx); @@ -101,7 +103,7 @@ void GpuMemoryWriteBack(GraphicContext* ctx); bool GpuMemoryCheckAccessViolation(uint64_t vaddr, uint64_t size); bool GpuMemoryWatcherEnabled(); -Vector GpuMemoryFindObjects(uint64_t vaddr, uint64_t size, bool exact, bool only_first); +Vector GpuMemoryFindObjects(uint64_t vaddr, uint64_t size, GpuMemoryObjectType type, bool exact, bool only_first); bool VulkanAllocate(GraphicContext* ctx, VulkanMemory* mem); void VulkanFree(GraphicContext* ctx, VulkanMemory* mem); diff --git a/source/emulator/include/Emulator/Graphics/Objects/Label.h b/source/emulator/include/Emulator/Graphics/Objects/Label.h index a7b3038..d97913d 100644 --- a/source/emulator/include/Emulator/Graphics/Objects/Label.h +++ b/source/emulator/include/Emulator/Graphics/Objects/Label.h @@ -12,6 +12,7 @@ namespace Kyty::Libs::Graphics { struct Label; class CommandBuffer; +struct GraphicContext; void LabelInit(); @@ -53,7 +54,12 @@ public: [[nodiscard]] update_func_t GetUpdateFunc() const override; }; -void LabelSet(CommandBuffer* buffer, Label* label); +Label* LabelCreate64(GraphicContext* ctx, uint64_t* dst_gpu_addr, uint64_t value, LabelGpuObject::callback_t callback_1, + LabelGpuObject::callback_t callback_2, const uint64_t* args); +Label* LabelCreate32(GraphicContext* ctx, uint32_t* dst_gpu_addr, uint32_t value, LabelGpuObject::callback_t callback_1, + LabelGpuObject::callback_t callback_2, const uint64_t* args); +void LabelDelete(Label* label); +void LabelSet(CommandBuffer* buffer, Label* label); } // namespace Kyty::Libs::Graphics diff --git a/source/emulator/include/Emulator/Graphics/Pm4.h b/source/emulator/include/Emulator/Graphics/Pm4.h index 3eafb45..aaa626c 100644 --- a/source/emulator/include/Emulator/Graphics/Pm4.h +++ b/source/emulator/include/Emulator/Graphics/Pm4.h @@ -337,6 +337,14 @@ constexpr uint32_t PA_SU_LINE_CNTL = 0x282; constexpr uint32_t PA_SU_LINE_CNTL_WIDTH_SHIFT = 0; constexpr uint32_t PA_SU_LINE_CNTL_WIDTH_MASK = 0xFFFF; +constexpr uint32_t PA_SC_MODE_CNTL_0 = 0x292; +constexpr uint32_t PA_SC_MODE_CNTL_0_MSAA_ENABLE_SHIFT = 0; +constexpr uint32_t PA_SC_MODE_CNTL_0_MSAA_ENABLE_MASK = 0x1; +constexpr uint32_t PA_SC_MODE_CNTL_0_VPORT_SCISSOR_ENABLE_SHIFT = 1; +constexpr uint32_t PA_SC_MODE_CNTL_0_VPORT_SCISSOR_ENABLE_MASK = 0x1; +constexpr uint32_t PA_SC_MODE_CNTL_0_LINE_STIPPLE_ENABLE_SHIFT = 2; +constexpr uint32_t PA_SC_MODE_CNTL_0_LINE_STIPPLE_ENABLE_MASK = 0x1; + constexpr uint32_t DB_HTILE_SURFACE = 0x2AF; constexpr uint32_t DB_HTILE_SURFACE_LINEAR_SHIFT = 0; constexpr uint32_t DB_HTILE_SURFACE_LINEAR_MASK = 0x1; @@ -355,6 +363,20 @@ constexpr uint32_t DB_HTILE_SURFACE_DST_OUTSIDE_ZERO_TO_ONE_MASK = 0x1; constexpr uint32_t VGT_SHADER_STAGES_EN = 0x2D5; +constexpr uint32_t PA_SC_CENTROID_PRIORITY_0 = 0x2F5; + +constexpr uint32_t PA_SC_AA_CONFIG = 0x2F8; +constexpr uint32_t PA_SC_AA_CONFIG_MSAA_NUM_SAMPLES_SHIFT = 0; +constexpr uint32_t PA_SC_AA_CONFIG_MSAA_NUM_SAMPLES_MASK = 0x7; +constexpr uint32_t PA_SC_AA_CONFIG_AA_MASK_CENTROID_DTMN_SHIFT = 4; +constexpr uint32_t PA_SC_AA_CONFIG_AA_MASK_CENTROID_DTMN_MASK = 0x1; +constexpr uint32_t PA_SC_AA_CONFIG_MAX_SAMPLE_DIST_SHIFT = 13; +constexpr uint32_t PA_SC_AA_CONFIG_MAX_SAMPLE_DIST_MASK = 0xF; +constexpr uint32_t PA_SC_AA_CONFIG_MSAA_EXPOSED_SAMPLES_SHIFT = 20; +constexpr uint32_t PA_SC_AA_CONFIG_MSAA_EXPOSED_SAMPLES_MASK = 0x7; + +constexpr uint32_t PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0 = 0x2FE; + constexpr uint32_t CB_COLOR0_BASE = 0x318; constexpr uint32_t CB_COLOR0_INFO = 0x31C; diff --git a/source/emulator/include/Emulator/Graphics/Shader.h b/source/emulator/include/Emulator/Graphics/Shader.h index 71a58da..c6947a6 100644 --- a/source/emulator/include/Emulator/Graphics/Shader.h +++ b/source/emulator/include/Emulator/Graphics/Shader.h @@ -352,10 +352,21 @@ struct ShaderInstruction ShaderOperand dst2; }; -struct ShaderLabel +class ShaderLabel { - uint32_t dst; - uint32_t src; +public: + explicit ShaderLabel(const ShaderInstruction& inst): m_dst(inst.pc + 4 + inst.src[0].constant.i), m_src(inst.pc) {} + ~ShaderLabel() = default; + KYTY_CLASS_DEFAULT_COPY(ShaderLabel); + + [[nodiscard]] uint32_t GetDst() const { return m_dst; } + [[nodiscard]] uint32_t GetSrc() const { return m_src; } + + [[nodiscard]] String ToString() const { return String::FromPrintf("label_%04" PRIx32 "_%04" PRIx32, m_dst, m_src); } + +private: + uint32_t m_dst; + uint32_t m_src; }; struct ShaderDebugPrintf @@ -409,6 +420,9 @@ public: [[nodiscard]] uint32_t GetPsEmbeddedId() const { return m_ps_embedded_id; } void SetPsEmbeddedId(uint32_t embedded_id) { m_ps_embedded_id = embedded_id; } + [[nodiscard]] bool IsDiscardBlock(uint32_t pc) const; + [[nodiscard]] bool IsDiscardInstruction(uint32_t index) const; + private: Vector m_instructions; Vector m_labels; diff --git a/source/emulator/include/Emulator/Graphics/Tile.h b/source/emulator/include/Emulator/Graphics/Tile.h index 1998391..cc06186 100644 --- a/source/emulator/include/Emulator/Graphics/Tile.h +++ b/source/emulator/include/Emulator/Graphics/Tile.h @@ -19,16 +19,22 @@ enum class TileMode // RenderTextureTiled, }; +struct TileSizeAlign +{ + uint32_t size = 0; + uint32_t align = 0; +}; + void TileInit(); void TileConvertTiledToLinear(void* dst, const void* src, TileMode mode, uint32_t width, uint32_t height, bool neo); void TileConvertTiledToLinear(void* dst, const void* src, TileMode mode, uint32_t dfmt, uint32_t nfmt, uint32_t width, uint32_t height, uint32_t levels, bool neo); -void TileGetDepthSize(uint32_t width, uint32_t height, uint32_t z_format, uint32_t stencil_format, bool htile, bool neo, - uint32_t* stencil_size, uint32_t* htile_size, uint32_t* depth_size, uint32_t* pitch); -void TileGetVideoOutSize(uint32_t width, uint32_t height, bool tile, bool neo, uint32_t* size, uint32_t* pitch); +bool TileGetDepthSize(uint32_t width, uint32_t height, uint32_t pitch, uint32_t z_format, uint32_t stencil_format, bool htile, bool neo, + TileSizeAlign* stencil_size, TileSizeAlign* htile_size, TileSizeAlign* depth_size); +void TileGetVideoOutSize(uint32_t width, uint32_t height, uint32_t pitch, bool tile, bool neo, TileSizeAlign* size); void TileGetTextureSize(uint32_t dfmt, uint32_t nfmt, uint32_t width, uint32_t height, uint32_t pitch, uint32_t levels, uint32_t tile, - bool neo, uint32_t* total_size, uint32_t* level_sizes, uint32_t* padded_width, uint32_t* padded_height); + bool neo, TileSizeAlign* total_size, uint32_t* level_sizes, uint32_t* padded_width, uint32_t* padded_height); } // namespace Kyty::Libs::Graphics diff --git a/source/emulator/include/Emulator/Kernel/FileSystem.h b/source/emulator/include/Emulator/Kernel/FileSystem.h index f64ae81..cb078a9 100644 --- a/source/emulator/include/Emulator/Kernel/FileSystem.h +++ b/source/emulator/include/Emulator/Kernel/FileSystem.h @@ -52,6 +52,8 @@ int KYTY_SYSV_ABI KernelStat(const char* path, FileStat* sb); int KYTY_SYSV_ABI KernelFstat(int d, FileStat* sb); int KYTY_SYSV_ABI KernelUnlink(const char* path); int KYTY_SYSV_ABI KernelGetdirentries(int fd, char* buf, int nbytes, int64_t* basep); +int KYTY_SYSV_ABI KernelGetdents(int fd, char* buf, int nbytes); +int KYTY_SYSV_ABI KernelMkdir(const char* path, uint16_t mode); } // namespace Kyty::Libs::LibKernel::FileSystem diff --git a/source/emulator/include/Emulator/Kernel/Pthread.h b/source/emulator/include/Emulator/Kernel/Pthread.h index 550c9f6..87c4da1 100644 --- a/source/emulator/include/Emulator/Kernel/Pthread.h +++ b/source/emulator/include/Emulator/Kernel/Pthread.h @@ -90,6 +90,7 @@ int KYTY_SYSV_ABI PthreadSetaffinity(Pthread thread, KernelCpumask mask void KYTY_SYSV_ABI PthreadExit(void* value); int KYTY_SYSV_ABI PthreadEqual(Pthread thread1, Pthread thread2); int KYTY_SYSV_ABI PthreadGetname(Pthread thread, char* name); +void KYTY_SYSV_ABI PthreadYield(); int KYTY_SYSV_ABI KernelUsleep(KernelUseconds microseconds); unsigned int KYTY_SYSV_ABI KernelSleep(unsigned int seconds); int KYTY_SYSV_ABI KernelNanosleep(const KernelTimespec* rqtp, KernelTimespec* rmtp); @@ -160,6 +161,9 @@ uint64_t KYTY_SYSV_ABI KernelGetProcessTimeCounterFrequency(); namespace Posix { +int KYTY_SYSV_ABI pthread_create(LibKernel::Pthread* thread, const LibKernel::PthreadAttr* attr, LibKernel::pthread_entry_func_t entry, + void* arg); +int KYTY_SYSV_ABI pthread_join(LibKernel::Pthread thread, void** value); int KYTY_SYSV_ABI pthread_cond_broadcast(LibKernel::PthreadCond* cond); int KYTY_SYSV_ABI pthread_cond_wait(LibKernel::PthreadCond* cond, LibKernel::PthreadMutex* mutex); int KYTY_SYSV_ABI pthread_mutex_lock(LibKernel::PthreadMutex* mutex); diff --git a/source/emulator/include/Emulator/Libs/Errno.h b/source/emulator/include/Emulator/Libs/Errno.h index e2aae23..7388a49 100644 --- a/source/emulator/include/Emulator/Libs/Errno.h +++ b/source/emulator/include/Emulator/Libs/Errno.h @@ -346,6 +346,20 @@ constexpr int AUDIO_OUT_ERROR_INVALID_MIXLEVEL = -2144993260; /* 0x80260014 * constexpr int AUDIO_OUT_ERROR_INVALID_ARG = -2144993259; /* 0x80260015 */ constexpr int AUDIO_OUT_ERROR_INVALID_PARAM = -2144993258; /* 0x80260016 */ +constexpr int AUDIO_IN_ERROR_FATAL = -2144993024; /* 0x80260100 */ +constexpr int AUDIO_IN_ERROR_INVALID_HANDLE = -2144993023; /* 0x80260101 */ +constexpr int AUDIO_IN_ERROR_INVALID_SIZE = -2144993022; /* 0x80260102 */ +constexpr int AUDIO_IN_ERROR_INVALID_FREQ = -2144993021; /* 0x80260103 */ +constexpr int AUDIO_IN_ERROR_INVALID_TYPE = -2144993020; /* 0x80260104 */ +constexpr int AUDIO_IN_ERROR_INVALID_POINTER = -2144993019; /* 0x80260105 */ +constexpr int AUDIO_IN_ERROR_INVALID_PARAM = -2144993018; /* 0x80260106 */ +constexpr int AUDIO_IN_ERROR_PORT_FULL = -2144993017; /* 0x80260107 */ +constexpr int AUDIO_IN_ERROR_OUT_OF_MEMORY = -2144993016; /* 0x80260108 */ +constexpr int AUDIO_IN_ERROR_NOT_OPENED = -2144993015; /* 0x80260109 */ +constexpr int AUDIO_IN_ERROR_BUSY = -2144993014; /* 0x8026010A */ +constexpr int AUDIO_IN_ERROR_SYSTEM_MEMORY = -2144993013; /* 0x8026010B */ +constexpr int AUDIO_IN_ERROR_SYSTEM_IPC = -2144993012; /* 0x8026010C */ + } // namespace Audio namespace SystemService { diff --git a/source/emulator/include/Emulator/Network.h b/source/emulator/include/Emulator/Network.h index 9229c9d..754bc71 100644 --- a/source/emulator/include/Emulator/Network.h +++ b/source/emulator/include/Emulator/Network.h @@ -35,10 +35,28 @@ int KYTY_SYSV_ABI SslTerm(int ssl_ctx_id); namespace Http { +struct HttpEpoll; + +using HttpEpollHandle = HttpEpoll*; + +using HttpsCallback = int (*)(int, unsigned int, void* const*, int, void*); + int KYTY_SYSV_ABI HttpInit(int memid, int ssl_ctx_id, uint64_t pool_size); int KYTY_SYSV_ABI HttpTerm(int http_ctx_id); int KYTY_SYSV_ABI HttpCreateTemplate(int http_ctx_id, const char* user_agent, int http_ver, int is_auto_proxy_conf); int KYTY_SYSV_ABI HttpDeleteTemplate(int tmpl_id); +int KYTY_SYSV_ABI HttpSetNonblock(int id, int enable); +int KYTY_SYSV_ABI HttpCreateEpoll(int http_ctx_id, HttpEpollHandle* eh); +int KYTY_SYSV_ABI HttpDestroyEpoll(int http_ctx_id, HttpEpollHandle eh); +int KYTY_SYSV_ABI HttpCreateConnectionWithURL(int tmpl_id, const char* url, int enable_keep_alive); +int KYTY_SYSV_ABI HttpDeleteConnection(int conn_id); +int KYTY_SYSV_ABI HttpCreateRequestWithURL2(int conn_id, const char* method, const char* url, uint64_t content_length); +int KYTY_SYSV_ABI HttpDeleteRequest(int req_id); +int KYTY_SYSV_ABI HttpAddRequestHeader(int id, const char* name, const char* value, uint32_t mode); +int KYTY_SYSV_ABI HttpSetEpoll(int id, HttpEpollHandle eh, void* user_arg); +int KYTY_SYSV_ABI HttpUnsetEpoll(int id); +int KYTY_SYSV_ABI HttpSendRequest(int request_id, const void* post_data, size_t size); +int KYTY_SYSV_ABI HttpsSetSslCallback(int id, HttpsCallback cbfunc, void* user_arg); } // namespace Http @@ -64,6 +82,9 @@ namespace NpManager { struct NpTitleId; struct NpTitleSecret; struct NpContentRestriction; +struct NpId; +struct NpOnlineId; +struct NpCreateAsyncRequestParameter; int KYTY_SYSV_ABI NpCheckCallback(); int KYTY_SYSV_ABI NpSetNpTitleId(const NpTitleId* title_id, const NpTitleSecret* title_secret); @@ -71,18 +92,29 @@ int KYTY_SYSV_ABI NpSetContentRestriction(const NpContentRestriction* restricti int KYTY_SYSV_ABI NpRegisterStateCallback(void* callback, void* userdata); void KYTY_SYSV_ABI NpRegisterGamePresenceCallback(void* callback, void* userdata); int KYTY_SYSV_ABI NpRegisterPlusEventCallback(void* callback, void* userdata); +int KYTY_SYSV_ABI NpGetNpId(int user_id, NpId* np_id); +int KYTY_SYSV_ABI NpGetOnlineId(int user_id, NpOnlineId* online_id); +int KYTY_SYSV_ABI NpCreateAsyncRequest(const NpCreateAsyncRequestParameter* param); +int KYTY_SYSV_ABI NpDeleteRequest(int req_id); +int KYTY_SYSV_ABI NpCheckNpAvailability(int req_id, const char* user, void* result); +int KYTY_SYSV_ABI NpPollAsync(int req_id, int* result); +int KYTY_SYSV_ABI NpGetState(int user_id, uint32_t* state); } // namespace NpManager namespace NpManagerForToolkit { int KYTY_SYSV_ABI NpRegisterStateCallbackForToolkit(void* callback, void* userdata); +int KYTY_SYSV_ABI NpCheckCallbackForLib(); } // namespace NpManagerForToolkit namespace NpTrophy { int KYTY_SYSV_ABI NpTrophyCreateHandle(int* handle); +int KYTY_SYSV_ABI NpTrophyCreateContext(int* context, int user_id, uint32_t service_label, uint64_t options); +int KYTY_SYSV_ABI NpTrophyRegisterContext(int context, int handle, uint64_t options); +int KYTY_SYSV_ABI NpTrophyDestroyHandle(int handle); } // namespace NpTrophy diff --git a/source/emulator/src/Audio.cpp b/source/emulator/src/Audio.cpp index c5daa45..45b8b31 100644 --- a/source/emulator/src/Audio.cpp +++ b/source/emulator/src/Audio.cpp @@ -69,10 +69,15 @@ public: bool AudioOutSetVolume(Id handle, uint32_t bitflag, const int* volume); uint32_t AudioOutOutputs(OutputParam* params, uint32_t num); - static constexpr int PORTS_MAX = 32; + Id AudioInOpen(uint32_t type, uint32_t samples_num, uint32_t freq, Format format); + bool AudioInValid(Id handle); + uint32_t AudioInInput(Id handle, void* dest); + + static constexpr int OUT_PORTS_MAX = 32; + static constexpr int IN_PORTS_MAX = 8; private: - struct Port + struct PortOut { bool used = false; int type = 0; @@ -84,8 +89,19 @@ private: int volume[8] = {}; }; + struct PortIn + { + bool used = false; + uint32_t type = 0; + uint32_t samples_num = 0; + uint32_t freq = 0; + Format format = Format::Unknown; + uint64_t last_input_time = 0; + }; + Core::Mutex m_mutex; - Port m_ports[PORTS_MAX]; + PortOut m_out_ports[OUT_PORTS_MAX]; + PortIn m_in_ports[IN_PORTS_MAX]; }; static Audio* g_audio = nullptr; @@ -105,11 +121,11 @@ Audio::Id Audio::AudioOutOpen(int type, uint32_t samples_num, uint32_t freq, For { Core::LockGuard lock(m_mutex); - for (int id = 0; id < PORTS_MAX; id++) + for (int id = 0; id < OUT_PORTS_MAX; id++) { - if (!m_ports[id].used) + if (!m_out_ports[id].used) { - auto& port = m_ports[id]; + auto& port = m_out_ports[id]; port.used = true; port.type = type; @@ -147,7 +163,7 @@ bool Audio::AudioOutValid(Id handle) { Core::LockGuard lock(m_mutex); - return (handle.GetId() >= 0 && handle.GetId() < PORTS_MAX && m_ports[handle.GetId()].used); + return (handle.GetId() >= 0 && handle.GetId() < OUT_PORTS_MAX && m_out_ports[handle.GetId()].used); } bool Audio::AudioOutSetVolume(Id handle, uint32_t bitflag, const int* volume) @@ -156,7 +172,7 @@ bool Audio::AudioOutSetVolume(Id handle, uint32_t bitflag, const int* volume) if (AudioOutValid(handle)) { - auto& port = m_ports[handle.GetId()]; + auto& port = m_out_ports[handle.GetId()]; for (int i = 0; i < port.channels_num; i++, bitflag >>= 1u) { @@ -193,7 +209,7 @@ uint32_t Audio::AudioOutOutputs(OutputParam* params, uint32_t num) EXIT_NOT_IMPLEMENTED(num == 0); EXIT_NOT_IMPLEMENTED(!AudioOutValid(params[0].handle)); - const auto& first_port = m_ports[params[0].handle.GetId()]; + const auto& first_port = m_out_ports[params[0].handle.GetId()]; uint64_t block_time = (1000000 * first_port.samples_num) / first_port.freq; uint64_t current_time = LibKernel::KernelGetProcessTime(); @@ -202,22 +218,80 @@ uint32_t Audio::AudioOutOutputs(OutputParam* params, uint32_t num) for (uint32_t i = 0; i < num; i++) { - uint64_t next_time = m_ports[params[i].handle.GetId()].last_output_time + block_time; + uint64_t next_time = m_out_ports[params[i].handle.GetId()].last_output_time + block_time; uint64_t wait_time = (next_time > current_time ? next_time - current_time : 0); max_wait_time = (wait_time > max_wait_time ? wait_time : max_wait_time); } - // Audio output is not yet implemented, so simulate audio delay + // TODO(): Audio output is not yet implemented, so simulate audio delay Core::Thread::SleepMicro(max_wait_time); for (uint32_t i = 0; i < num; i++) { - m_ports[params[i].handle.GetId()].last_output_time = LibKernel::KernelGetProcessTime(); + m_out_ports[params[i].handle.GetId()].last_output_time = LibKernel::KernelGetProcessTime(); } return first_port.samples_num; } +Audio::Id Audio::AudioInOpen(uint32_t type, uint32_t samples_num, uint32_t freq, Format format) +{ + Core::LockGuard lock(m_mutex); + + for (int id = 0; id < IN_PORTS_MAX; id++) + { + if (!m_in_ports[id].used) + { + auto& port = m_in_ports[id]; + + port.used = true; + port.type = type; + port.samples_num = samples_num; + port.freq = freq; + port.format = format; + + switch (format) + { + case Format::Signed16bitMono: + case Format::Signed16bitStereo: break; + default: EXIT("unknown format"); + } + + return Id::Create(id); + } + } + + return Id::Invalid(); +} + +bool Audio::AudioInValid(Id handle) +{ + Core::LockGuard lock(m_mutex); + + return (handle.GetId() >= 0 && handle.GetId() < IN_PORTS_MAX && m_in_ports[handle.GetId()].used); +} + +uint32_t Audio::AudioInInput(Id handle, void* dest) +{ + EXIT_NOT_IMPLEMENTED(!AudioInValid(handle)); + EXIT_NOT_IMPLEMENTED(dest == nullptr); + + const auto& port = m_in_ports[handle.GetId()]; + + uint64_t block_time = (1000000 * port.samples_num) / port.freq; + uint64_t current_time = LibKernel::KernelGetProcessTime(); + + uint64_t next_time = m_in_ports[handle.GetId()].last_input_time + block_time; + uint64_t wait_time = (next_time > current_time ? next_time - current_time : 0); + + // TODO(): Audio input is not yet implemented, so simulate audio delay + Core::Thread::SleepMicro(wait_time); + + m_in_ports[handle.GetId()].last_input_time = LibKernel::KernelGetProcessTime(); + + return port.samples_num; +} + namespace AudioOut { LIB_NAME("AudioOut", "AudioOut"); @@ -245,8 +319,8 @@ int KYTY_SYSV_ABI AudioOutOpen(int user_id, int type, int index, uint32_t len, u printf("\t len = %u\n", len); printf("\t freq = %u\n", freq); - EXIT_NOT_IMPLEMENTED(user_id != 255); - EXIT_NOT_IMPLEMENTED(type != 0); + EXIT_NOT_IMPLEMENTED(user_id != 255 && user_id != 1); + EXIT_NOT_IMPLEMENTED(type != 0 && type != 3 && type != 4); EXIT_NOT_IMPLEMENTED(index != 0); Audio::Format format = Audio::Format::Unknown; @@ -302,10 +376,14 @@ int KYTY_SYSV_ABI AudioOutOutputs(AudioOutOutputParam* param, uint32_t num) { PRINT_NAME(); - EXIT_NOT_IMPLEMENTED(param == nullptr); - EXIT_NOT_IMPLEMENTED(num != 1); + for (uint32_t i = 0; i < num; i++) + { + printf("\t handle[%u] = %d\n", i, param[i].handle); + } - Audio::OutputParam params[Audio::PORTS_MAX]; + EXIT_NOT_IMPLEMENTED(param == nullptr); + + Audio::OutputParam params[Audio::OUT_PORTS_MAX]; EXIT_IF(g_audio == nullptr); @@ -325,6 +403,67 @@ int KYTY_SYSV_ABI AudioOutOutputs(AudioOutOutputParam* param, uint32_t num) } // namespace AudioOut +namespace AudioIn { + +LIB_NAME("AudioIn", "AudioIn"); + +int KYTY_SYSV_ABI AudioInOpen(int user_id, uint32_t type, uint32_t index, uint32_t len, uint32_t freq, uint32_t param) +{ + PRINT_NAME(); + + printf("\t user_id = %d\n", user_id); + printf("\t type = %u\n", type); + printf("\t index = %d\n", index); + printf("\t len = %u\n", len); + printf("\t freq = %u\n", freq); + + EXIT_NOT_IMPLEMENTED(user_id != 255 && user_id != 1); + EXIT_NOT_IMPLEMENTED(type != 1); + EXIT_NOT_IMPLEMENTED(index != 0); + + Audio::Format format = Audio::Format::Unknown; + + switch (param) + { + case 0: format = Audio::Format::Signed16bitMono; break; + case 2: format = Audio::Format::Signed16bitStereo; break; + default:; + } + + printf("\t param = %u (%s)\n", param, Core::EnumName(format).C_Str()); + + EXIT_NOT_IMPLEMENTED(format == Audio::Format::Unknown); + + EXIT_IF(g_audio == nullptr); + + auto id = g_audio->AudioInOpen(type, len, freq, format); + + if (!id.IsValid()) + { + return AUDIO_IN_ERROR_PORT_FULL; + } + + return id.ToInt(); +} + +int KYTY_SYSV_ABI AudioInInput(int handle, void* dest) +{ + PRINT_NAME(); + + EXIT_NOT_IMPLEMENTED(dest == nullptr); + + EXIT_IF(g_audio == nullptr); + + if (!g_audio->AudioInValid(Audio::Id(handle))) + { + return AUDIO_IN_ERROR_INVALID_HANDLE; + } + + return static_cast(g_audio->AudioInInput(Audio::Id(handle), dest)); +} + +} // namespace AudioIn + namespace VoiceQoS { LIB_NAME("VoiceQoS", "VoiceQoS"); @@ -342,6 +481,24 @@ int KYTY_SYSV_ABI VoiceQoSInit(void* mem_block, uint32_t mem_size, int32_t app_t } // namespace VoiceQoS +namespace Ajm { + +LIB_NAME("Ajm", "Ajm"); + +int KYTY_SYSV_ABI AjmInitialize(int64_t reserved, uint32_t* context) +{ + PRINT_NAME(); + + EXIT_NOT_IMPLEMENTED(context == nullptr); + EXIT_NOT_IMPLEMENTED(reserved != 0); + + *context = 1; + + return OK; +} + +} // namespace Ajm + } // namespace Kyty::Libs::Audio #endif // KYTY_EMU_ENABLED diff --git a/source/emulator/src/Controller.cpp b/source/emulator/src/Controller.cpp index 7e2699e..f612068 100644 --- a/source/emulator/src/Controller.cpp +++ b/source/emulator/src/Controller.cpp @@ -72,6 +72,12 @@ struct PadControllerInformation int device_class; }; +struct PadVibrationParam +{ + uint8_t large_motor; + uint8_t small_motor; +}; + struct ControllerState { uint64_t time = 0; @@ -93,10 +99,16 @@ public: void Axis(int id, Axis axis, int value); void GetConnectionInfo(bool* flag, int* count); void ReadState(ControllerState* state, bool* flag, int* count); + int ReadStates(ControllerState* states, int states_num, bool* flag, int* count); private: static constexpr uint32_t STATES_MAX = 64; + struct StatePrivate + { + bool obtained = false; + }; + void CheckActive(); [[nodiscard]] ControllerState GetLastState() const; void AddState(const ControllerState& state); @@ -107,6 +119,7 @@ private: bool m_connected = false; int m_connected_count = 0; ControllerState m_states[STATES_MAX]; + StatePrivate m_private[STATES_MAX]; ControllerState m_last_state; uint32_t m_states_num = 0; uint32_t m_first_state = 0; @@ -205,8 +218,12 @@ void GameController::AddState(const ControllerState& state) m_first_state = (m_first_state + 1) % STATES_MAX; } - m_states[(m_first_state + m_states_num) % STATES_MAX] = state; - m_last_state = state; + auto index = (m_first_state + m_states_num) % STATES_MAX; + + m_states[index] = state; + m_last_state = state; + + m_private[index].obtained = false; m_states_num++; } @@ -299,6 +316,48 @@ void GameController::ReadState(ControllerState* state, bool* flag, int* count) *state = GetLastState(); } +int GameController::ReadStates(ControllerState* states, int states_num, bool* flag, int* count) +{ + EXIT_IF(flag == nullptr); + EXIT_IF(count == nullptr); + EXIT_IF(states == nullptr); + EXIT_IF(states_num < 1 || states_num > STATES_MAX); + + Core::LockGuard lock(m_mutex); + + *flag = m_connected; + *count = m_connected_count; + + int ret_num = 0; + + if (m_connected) + { + if (m_states_num == 0) + { + ret_num = 1; + states[0] = m_last_state; + } else + { + for (uint32_t i = 0; i < m_states_num; i++) + { + if (ret_num >= states_num) + { + break; + } + auto index = (m_first_state + i) % STATES_MAX; + if (!m_private[index].obtained) + { + m_private[index].obtained = true; + + states[ret_num++] = m_states[index]; + } + } + } + } + + return ret_num; +} + void ControllerConnect(int id) { EXIT_IF(g_controller == nullptr); @@ -433,6 +492,74 @@ int KYTY_SYSV_ABI PadReadState(int handle, PadData* data) return OK; } +int KYTY_SYSV_ABI PadRead(int handle, PadData* data, int num) +{ + PRINT_NAME(); + + EXIT_NOT_IMPLEMENTED(num < 1 || num > 64); + EXIT_NOT_IMPLEMENTED(handle != 1); + EXIT_NOT_IMPLEMENTED(data == nullptr); + + EXIT_IF(g_controller == nullptr); + + int connected_count = 0; + bool connected = false; + ControllerState states[64]; + + int ret_num = g_controller->ReadStates(states, num, &connected, &connected_count); + + if (!connected) + { + ret_num = 1; + } + + for (int i = 0; i < ret_num; i++) + { + data[i].buttons = states[i].buttons; + data[i].left_stick_x = states[i].axes[static_cast(Axis::LeftX)]; + data[i].left_stick_y = states[i].axes[static_cast(Axis::LeftY)]; + data[i].right_stick_x = states[i].axes[static_cast(Axis::RightX)]; + data[i].right_stick_y = states[i].axes[static_cast(Axis::RightY)]; + data[i].analog_buttons_l2 = states[i].axes[static_cast(Axis::TriggerLeft)]; + data[i].analog_buttons_r2 = states[i].axes[static_cast(Axis::TriggerRight)]; + data[i].orientation_x = 0.0f; + data[i].orientation_y = 0.0f; + data[i].orientation_z = 0.0f; + data[i].orientation_w = 1.0f; + data[i].acceleration_x = 0.0f; + data[i].acceleration_y = 0.0f; + data[i].acceleration_z = 0.0f; + data[i].angular_velocity_x = 0.0f; + data[i].angular_velocity_y = 0.0f; + data[i].angular_velocity_z = 0.0f; + data[i].touch_data_touch_num = 0; + data[i].touch_data_touch0_x = 0; + data[i].touch_data_touch0_y = 0; + data[i].touch_data_touch0_id = 1; + data[i].touch_data_touch1_x = 0; + data[i].touch_data_touch1_y = 0; + data[i].touch_data_touch1_id = 2; + data[i].connected = connected; + data[i].timestamp = states[i].time; + data[i].connected_count = connected_count; + data[i].device_unique_data_len = 0; + } + + return ret_num; +} + +int KYTY_SYSV_ABI PadSetVibration(int handle, const PadVibrationParam* param) +{ + PRINT_NAME(); + + EXIT_NOT_IMPLEMENTED(handle != 1); + + printf("\t large_motor = %d\n", static_cast(param->large_motor)); + printf("\t small_motor = %d\n", static_cast(param->small_motor)); + + return OK; +} + } // namespace Kyty::Libs::Controller #endif // KYTY_EMU_ENABLED diff --git a/source/emulator/src/Dialog.cpp b/source/emulator/src/Dialog.cpp index f5f20ac..3cb7033 100644 --- a/source/emulator/src/Dialog.cpp +++ b/source/emulator/src/Dialog.cpp @@ -23,6 +23,36 @@ int KYTY_SYSV_ABI CommonDialogInitialize() } // namespace CommonDialog +namespace SaveDataDialog { + +LIB_NAME("SaveDataDialog", "SaveDataDialog"); + +int KYTY_SYSV_ABI SaveDataDialogUpdateStatus() +{ + PRINT_NAME(); + + return 0; +} + +int KYTY_SYSV_ABI SaveDataDialogTerminate() +{ + PRINT_NAME(); + + return 0; +} + +int KYTY_SYSV_ABI SaveDataDialogProgressBarSetValue(int target, uint32_t rate) +{ + PRINT_NAME(); + + printf("\t target = %d\n", target); + printf("\t rate = %u\n", rate); + + return OK; +} + +} // namespace SaveDataDialog + } // namespace Kyty::Libs::Dialog #endif // KYTY_EMU_ENABLED diff --git a/source/emulator/src/Graphics/Graphics.cpp b/source/emulator/src/Graphics/Graphics.cpp index ea12b99..26567e6 100644 --- a/source/emulator/src/Graphics/Graphics.cpp +++ b/source/emulator/src/Graphics/Graphics.cpp @@ -225,6 +225,35 @@ int KYTY_SYSV_ABI GraphicsUpdatePsShader(uint32_t* cmd, uint64_t size, const uin return OK; } +int KYTY_SYSV_ABI GraphicsUpdatePsShader350(uint32_t* cmd, uint64_t size, const uint32_t* ps_regs) +{ + PRINT_NAME(); + + EXIT_NOT_IMPLEMENTED(ps_regs == nullptr); + EXIT_NOT_IMPLEMENTED(size < 12 + 1); + + printf("\t cmd_buffer = %016" PRIx64 "\n", reinterpret_cast(cmd)); + printf("\t size = %" PRIu64 "\n", size); + + printf("\t ps_regs.m_spiShaderPgmLoPs = %08" PRIx32 "\n", ps_regs[0]); + printf("\t ps_regs.m_spiShaderPgmHiPs = %08" PRIx32 "\n", ps_regs[1]); + printf("\t ps_regs.m_spiShaderPgmRsrc1Ps = %08" PRIx32 "\n", ps_regs[2]); + printf("\t ps_regs.m_spiShaderPgmRsrc2Ps = %08" PRIx32 "\n", ps_regs[3]); + printf("\t ps_regs.m_spiShaderZFormat = %08" PRIx32 "\n", ps_regs[4]); + printf("\t ps_regs.m_spiShaderColFormat = %08" PRIx32 "\n", ps_regs[5]); + printf("\t ps_regs.m_spiPsInputEna = %08" PRIx32 "\n", ps_regs[6]); + printf("\t ps_regs.m_spiPsInputAddr = %08" PRIx32 "\n", ps_regs[7]); + printf("\t ps_regs.m_spiPsInControl = %08" PRIx32 "\n", ps_regs[8]); + printf("\t ps_regs.m_spiBarycCntl = %08" PRIx32 "\n", ps_regs[9]); + printf("\t ps_regs.m_dbShaderControl = %08" PRIx32 "\n", ps_regs[10]); + printf("\t ps_regs.m_cbShaderMask = %08" PRIx32 "\n", ps_regs[11]); + + cmd[0] = KYTY_PM4(size, Pm4::IT_NOP, Pm4::R_PS_UPDATE); + memcpy(&cmd[1], ps_regs, 12 * 4); + + return OK; +} + int KYTY_SYSV_ABI GraphicsSetCsShaderWithModifier(uint32_t* cmd, uint64_t size, const uint32_t* cs_regs, uint32_t shader_modifier) { PRINT_NAME(); diff --git a/source/emulator/src/Graphics/GraphicsRender.cpp b/source/emulator/src/Graphics/GraphicsRender.cpp index 51776b1..7c3dda9 100644 --- a/source/emulator/src/Graphics/GraphicsRender.cpp +++ b/source/emulator/src/Graphics/GraphicsRender.cpp @@ -1,6 +1,8 @@ #include "Emulator/Graphics/GraphicsRender.h" #include "Kyty/Core/DbgAssert.h" +#include "Kyty/Core/Hash.h" +#include "Kyty/Core/Hashmap.h" #include "Kyty/Core/Threads.h" #include "Kyty/Core/Vector.h" #include "Kyty/Math/Rand.h" @@ -116,20 +118,12 @@ struct PipelineDynamicParameters }; #pragma pack(pop) -// struct PipelineAdditionalParameters -//{ -// ShaderBindParameters vs_bind; -// ShaderBindParameters ps_bind; -// ShaderBindParameters cs_bind; -//}; - struct VulkanPipeline { VkPipelineLayout pipeline_layout = nullptr; VkPipeline pipeline = nullptr; const PipelineStaticParameters* static_params = nullptr; PipelineDynamicParameters* dynamic_params = nullptr; - // const PipelineAdditionalParameters* additional_params = nullptr; }; class PipelineCache @@ -198,8 +192,7 @@ public: virtual ~DescriptorCache() { KYTY_NOT_IMPLEMENTED; } KYTY_CLASS_NO_COPY(DescriptorCache); - VkDescriptorSetLayout GetDescriptorSetLayout(Stage stage, - const ShaderBindResources& bind /*, const ShaderBindParameters& bind_params*/); + VkDescriptorSetLayout GetDescriptorSetLayout(Stage stage, const ShaderBindResources& bind); VulkanDescriptorSet* Allocate(Stage stage, int storage_buffers_num, int textures2d_sampled_num, int textures2d_storage_num, int samplers_num, int gds_buffers_num); @@ -207,8 +200,7 @@ public: VulkanDescriptorSet* GetDescriptor(Stage stage, VulkanBuffer** storage_buffers, VulkanImage** textures2d_sampled, const bool* textures2d_depth, VulkanImage** textures2d_storage, uint64_t* samplers, - VulkanBuffer** gds_buffers, - const ShaderBindResources& bind /*, const ShaderBindParameters& bind_params*/); + VulkanBuffer** gds_buffers, const ShaderBindResources& bind); void FreeDescriptor(VulkanBuffer* buffer); void FreeDescriptor(VulkanImage* image); @@ -216,6 +208,8 @@ private: struct Set { VulkanDescriptorSet* set = nullptr; + int next_free_set = -1; + uint32_t hash = 0; Stage stage = Stage::Unknown; int storage_buffers_num = 0; uint64_t storage_buffers_id[BUFFERS_MAX] = {}; @@ -231,10 +225,18 @@ private: void Init(); void CreatePool(); + static uint32_t CalcHash(const Set& s); + + VulkanDescriptorSet* FindSet(const Set& s); + Core::Mutex m_mutex; Vector m_pools; Vector m_sets; - VkDescriptorSetLayout m_descriptor_set_layout_vertex[BUFFERS_MAX + 1][TEXTURES_SAMPLED_MAX + 1][TEXTURES_STORAGE_MAX + 1] + int m_first_free_set = -1; + + Core::Hashmap> m_sets_map; + + VkDescriptorSetLayout m_descriptor_set_layout_vertex[BUFFERS_MAX + 1][TEXTURES_SAMPLED_MAX + 1][TEXTURES_STORAGE_MAX + 1] [SAMPLERS_MAX + 1][GDS_BUFFER_MAX + 1] = {}; VkDescriptorSetLayout m_descriptor_set_layout_pixel[BUFFERS_MAX + 1][TEXTURES_SAMPLED_MAX + 1][TEXTURES_STORAGE_MAX + 1] [SAMPLERS_MAX + 1][GDS_BUFFER_MAX + 1] = {}; @@ -342,8 +344,6 @@ public: SamplerCache* GetSamplerCache() { return m_sampler_cache; } GdsBuffer* GetGdsBuffer() { return m_gds_buffer; } - //[[nodiscard]] LibKernel::EventQueue::KernelEqueue GetEopEq() const { return m_eop_eq; } - // void SetEopEq(LibKernel::EventQueue::KernelEqueue eop_eq) { m_eop_eq = eop_eq; } void AddEopEq(LibKernel::EventQueue::KernelEqueue eq); void DeleteEopEq(LibKernel::EventQueue::KernelEqueue eq); void TriggerEopEvent(); @@ -370,10 +370,13 @@ struct RenderDepthInfo bool neo = false; uint64_t depth_buffer_size = 0; uint64_t depth_buffer_vaddr = 0; + uint64_t depth_tile_swizzle = 0; uint64_t stencil_buffer_size = 0; uint64_t stencil_buffer_vaddr = 0; + uint64_t stencil_tile_swizzle = 0; uint64_t htile_buffer_size = 0; uint64_t htile_buffer_vaddr = 0; + uint64_t htile_tile_swizzle = 0; bool depth_clear_enable = false; float depth_clear_value = 0.0f; bool depth_test_enable = false; @@ -445,7 +448,6 @@ private: static RenderContext* g_render_ctx = nullptr; static thread_local CommandPool g_command_pool; -// NOLINTNEXTLINE(readability-function-cognitive-complexity) static void uc_print(const char* func, const HW::UserConfig& uc) { printf("%s\n", func); @@ -735,7 +737,7 @@ static void mc_check(const HW::ModeControl& c) { // EXIT_NOT_IMPLEMENTED(c.cull_front != false); // EXIT_NOT_IMPLEMENTED(c.cull_back != false); - EXIT_NOT_IMPLEMENTED(c.face != false); + // EXIT_NOT_IMPLEMENTED(c.face != false); EXIT_NOT_IMPLEMENTED(c.poly_mode != 0); EXIT_NOT_IMPLEMENTED(c.polymode_front_ptype != 0 && c.polymode_front_ptype != 2); EXIT_NOT_IMPLEMENTED(c.polymode_back_ptype != 0 && c.polymode_back_ptype != 2); @@ -864,38 +866,79 @@ static void eqaa_check(const HW::EqaaControl& c) // EXIT_NOT_IMPLEMENTED(c.static_anchor_associations != false); } -static void vp_print(const char* func, const HW::ScreenViewport& vp) +static void aa_print(const char* func, const HW::AaSampleControl& c, const HW::AaConfig& cf) { printf("%s\n", func); - printf("\t viewports[0].zmin = %f\n", vp.viewports[0].zmin); - printf("\t viewports[0].zmax = %f\n", vp.viewports[0].zmax); - printf("\t viewports[0].xscale = %f\n", vp.viewports[0].xscale); - printf("\t viewports[0].xoffset = %f\n", vp.viewports[0].xoffset); - printf("\t viewports[0].yscale = %f\n", vp.viewports[0].yscale); - printf("\t viewports[0].yoffset = %f\n", vp.viewports[0].yoffset); - printf("\t viewports[0].zscale = %f\n", vp.viewports[0].zscale); - printf("\t viewports[0].zoffset = %f\n", vp.viewports[0].zoffset); - printf("\t transform_control = 0x%08" PRIx32 "\n", vp.transform_control); - printf("\t screen_scissor_left = %d\n", vp.screen_scissor_left); - printf("\t screen_scissor_top = %d\n", vp.screen_scissor_top); - printf("\t screen_scissor_right = %d\n", vp.screen_scissor_right); - printf("\t screen_scissor_bottom = %d\n", vp.screen_scissor_bottom); - printf("\t generic_scissor_left = %d\n", vp.generic_scissor_left); - printf("\t generic_scissor_top = %d\n", vp.generic_scissor_top); - printf("\t generic_scissor_right = %d\n", vp.generic_scissor_right); - printf("\t generic_scissor_bottom = %d\n", vp.generic_scissor_bottom); - printf("\t hw_offset_x = %u\n", vp.hw_offset_x); - printf("\t hw_offset_y = %u\n", vp.hw_offset_y); - printf("\t guard_band_horz_clip = %f\n", vp.guard_band_horz_clip); - printf("\t guard_band_vert_clip = %f\n", vp.guard_band_vert_clip); - printf("\t guard_band_horz_discard = %f\n", vp.guard_band_horz_discard); - printf("\t guard_band_vert_discard = %f\n", vp.guard_band_vert_discard); - printf("\t generic_scissor_window_offset_enable = %s\n", vp.generic_scissor_window_offset_enable ? "true" : "false"); + printf("\t centroid_priority = %016" PRIx64 "\n", c.centroid_priority); + for (int i = 0; i < 16; i++) + { + printf("\t locations[%d] = %08" PRIx32 "\n", i, c.locations[i]); + } + printf("\t msaa_num_samples = %" PRIu8 "\n", cf.msaa_num_samples); + printf("\t aa_mask_centroid_dtmn = %s\n", cf.aa_mask_centroid_dtmn ? "true" : "false"); + printf("\t max_sample_dist = %" PRIu8 "\n", cf.max_sample_dist); + printf("\t msaa_exposed_samples = %" PRIu8 "\n", cf.msaa_exposed_samples); } -static void vp_check(const HW::ScreenViewport& vp) +static void aa_check(const HW::AaSampleControl& c, const HW::AaConfig& cf) { + EXIT_NOT_IMPLEMENTED(c.centroid_priority != 0); + for (uint32_t l: c.locations) + { + EXIT_NOT_IMPLEMENTED(l != 0); + } + EXIT_NOT_IMPLEMENTED(cf.msaa_num_samples != 0); + EXIT_NOT_IMPLEMENTED(cf.aa_mask_centroid_dtmn != false); + EXIT_NOT_IMPLEMENTED(cf.max_sample_dist != 0); + EXIT_NOT_IMPLEMENTED(cf.msaa_exposed_samples != 0); +} + +static void vp_print(const char* func, const HW::ScreenViewport& vp, const HW::ScanModeControl& smc) +{ + printf("%s\n", func); + + printf("\t msaa_enable = %s\n", smc.msaa_enable ? "true" : "false"); + printf("\t vport_scissor_enable = %s\n", smc.vport_scissor_enable ? "true" : "false"); + printf("\t line_stipple_enable = %s\n", smc.line_stipple_enable ? "true" : "false"); + printf("\t vp[0].zmin = %f\n", vp.viewports[0].zmin); + printf("\t vp[0].zmax = %f\n", vp.viewports[0].zmax); + printf("\t vp[0].xscale = %f\n", vp.viewports[0].xscale); + printf("\t vp[0].xoffset = %f\n", vp.viewports[0].xoffset); + printf("\t vp[0].yscale = %f\n", vp.viewports[0].yscale); + printf("\t vp[0].yoffset = %f\n", vp.viewports[0].yoffset); + printf("\t vp[0].zscale = %f\n", vp.viewports[0].zscale); + printf("\t vp[0].zoffset = %f\n", vp.viewports[0].zoffset); + printf("\t vp[0].viewport_scissor_left = %d\n", vp.viewports[0].viewport_scissor_left); + printf("\t vp[0].viewport_scissor_top = %d\n", vp.viewports[0].viewport_scissor_top); + printf("\t vp[0].viewport_scissor_right = %d\n", vp.viewports[0].viewport_scissor_right); + printf("\t vp[0].viewport_scissor_bottom = %d\n", vp.viewports[0].viewport_scissor_bottom); + printf("\t transform_control = 0x%08" PRIx32 "\n", vp.transform_control); + printf("\t screen_scissor_left = %d\n", vp.screen_scissor_left); + printf("\t screen_scissor_top = %d\n", vp.screen_scissor_top); + printf("\t screen_scissor_right = %d\n", vp.screen_scissor_right); + printf("\t screen_scissor_bottom = %d\n", vp.screen_scissor_bottom); + printf("\t generic_scissor_left = %d\n", vp.generic_scissor_left); + printf("\t generic_scissor_top = %d\n", vp.generic_scissor_top); + printf("\t generic_scissor_right = %d\n", vp.generic_scissor_right); + printf("\t generic_scissor_bottom = %d\n", vp.generic_scissor_bottom); + printf("\t hw_offset_x = %u\n", vp.hw_offset_x); + printf("\t hw_offset_y = %u\n", vp.hw_offset_y); + printf("\t guard_band_horz_clip = %f\n", vp.guard_band_horz_clip); + printf("\t guard_band_vert_clip = %f\n", vp.guard_band_vert_clip); + printf("\t guard_band_horz_discard = %f\n", vp.guard_band_horz_discard); + printf("\t guard_band_vert_discard = %f\n", vp.guard_band_vert_discard); + printf("\t generic_scissor_window_offset_enable = %s\n", vp.generic_scissor_window_offset_enable ? "true" : "false"); + printf("\t viewports[0].viewport_scissor_window_offset_enable = %s\n", + vp.viewports[0].viewport_scissor_window_offset_enable ? "true" : "false"); +} + +static void vp_check(const HW::ScreenViewport& vp, const HW::ScanModeControl& smc) +{ + EXIT_NOT_IMPLEMENTED(smc.msaa_enable); + // EXIT_NOT_IMPLEMENTED(smc.vport_scissor_enable); + EXIT_NOT_IMPLEMENTED(smc.line_stipple_enable); + EXIT_NOT_IMPLEMENTED(vp.viewports[0].zmin != 0.000000); EXIT_NOT_IMPLEMENTED(vp.viewports[0].zmax != 1.000000); // EXIT_NOT_IMPLEMENTED(vp.viewports[0].xscale != 960.000000); @@ -906,7 +949,7 @@ static void vp_check(const HW::ScreenViewport& vp) // EXIT_NOT_IMPLEMENTED(vp.viewports[0].zoffset != 0.500000); EXIT_NOT_IMPLEMENTED(vp.transform_control != 1087); EXIT_NOT_IMPLEMENTED(vp.generic_scissor_left != 0 && !(vp.screen_scissor_left == vp.generic_scissor_left)); - EXIT_NOT_IMPLEMENTED(vp.generic_scissor_right != 0 && !(vp.screen_scissor_right == vp.generic_scissor_right)); + EXIT_NOT_IMPLEMENTED(vp.generic_scissor_top != 0 && !(vp.screen_scissor_top == vp.generic_scissor_top)); EXIT_NOT_IMPLEMENTED(vp.generic_scissor_right != 0 && !(vp.screen_scissor_right == vp.generic_scissor_right)); EXIT_NOT_IMPLEMENTED(vp.generic_scissor_bottom != 0 && !(vp.screen_scissor_bottom == vp.generic_scissor_bottom)); // EXIT_NOT_IMPLEMENTED(vp.hw_offset_x != 60); @@ -916,6 +959,11 @@ static void vp_check(const HW::ScreenViewport& vp) EXIT_NOT_IMPLEMENTED(vp.guard_band_horz_discard != 1.000000); EXIT_NOT_IMPLEMENTED(vp.guard_band_vert_discard != 1.000000); EXIT_NOT_IMPLEMENTED(vp.generic_scissor_window_offset_enable != false); + EXIT_NOT_IMPLEMENTED(vp.viewports[0].viewport_scissor_left != 0); + EXIT_NOT_IMPLEMENTED(vp.viewports[0].viewport_scissor_top != 0); + EXIT_NOT_IMPLEMENTED(vp.viewports[0].viewport_scissor_right != 0); + EXIT_NOT_IMPLEMENTED(vp.viewports[0].viewport_scissor_bottom != 0); + EXIT_NOT_IMPLEMENTED(vp.viewports[0].viewport_scissor_window_offset_enable != false); } static void hw_check(const HW::HardwareContext& hw) @@ -933,9 +981,12 @@ static void hw_check(const HW::HardwareContext& hw) const auto& mc = hw.GetModeControl(); const auto& eqaa = hw.GetEqaaControl(); const auto& cc = hw.GetColorControl(); + const auto& smc = hw.GetScanModeControl(); + const auto& aa = hw.GetAaSampleControl(); + const auto& ac = hw.GetAaConfig(); rt_check(rt); - vp_check(vp); + vp_check(vp, smc); z_check(z); clip_check(c); rc_check(rc); @@ -943,6 +994,7 @@ static void hw_check(const HW::HardwareContext& hw) mc_check(mc); bc_check(bc, bclr, cc); eqaa_check(eqaa); + aa_check(aa, ac); EXIT_NOT_IMPLEMENTED(hw.GetRenderTargetMask() != 0xF && hw.GetRenderTargetMask() != 0x0); EXIT_NOT_IMPLEMENTED(hw.GetDepthClearValue() != 0.0f && hw.GetDepthClearValue() != 1.0f); @@ -964,6 +1016,9 @@ static void hw_print(const HW::HardwareContext& hw) const auto& mc = hw.GetModeControl(); const auto& eqaa = hw.GetEqaaControl(); const auto& cc = hw.GetColorControl(); + const auto& smc = hw.GetScanModeControl(); + const auto& aa = hw.GetAaSampleControl(); + const auto& ac = hw.GetAaConfig(); printf("HardwareContext\n"); printf("\t GetRenderTargetMask() = 0x%08" PRIx32 "\n", hw.GetRenderTargetMask()); @@ -973,13 +1028,14 @@ static void hw_print(const HW::HardwareContext& hw) rt_print("RenderTraget:", rt); z_print("DepthRenderTraget:", z); - vp_print("ScreenViewport:", vp); + vp_print("ScreenViewport:", vp, smc); clip_print("ClipControl:", c); rc_print("RenderControl:", rc); d_print("DepthStencilControlMask:", d, s, sm); mc_print("ModeControl:", mc); bc_print("BlendColorControl:", bc, bclr, cc); eqaa_print("EqaaControl:", eqaa); + aa_print("AaSampleControl:", aa, ac); } void GraphicsRenderInit() @@ -1669,8 +1725,8 @@ static VkBlendOp get_blend_op(uint32_t op) } static void CreateLayout(VkDescriptorSetLayout* set_layouts, uint32_t* set_layouts_num, VkPushConstantRange* push_constant_info, - uint32_t* push_constant_info_num, const ShaderBindResources& bind, /*const ShaderBindParameters& bind_params,*/ - VkShaderStageFlags vk_stage, DescriptorCache::Stage stage) + uint32_t* push_constant_info_num, const ShaderBindResources& bind, VkShaderStageFlags vk_stage, + DescriptorCache::Stage stage) { EXIT_IF(set_layouts == nullptr); EXIT_IF(set_layouts_num == nullptr); @@ -1705,17 +1761,14 @@ static void CreateLayout(VkDescriptorSetLayout* set_layouts, uint32_t* set_layou static VulkanPipeline* CreatePipelineInternal(VkRenderPass render_pass, const ShaderVertexInputInfo* vs_input_info, const Vector& vs_shader, const ShaderPixelInputInfo* ps_input_info, const Vector& ps_shader, const PipelineStaticParameters* static_params, - PipelineDynamicParameters* dynamic_params/*, - const PipelineAdditionalParameters* additional_params*/) + PipelineDynamicParameters* dynamic_params) { EXIT_IF(g_render_ctx == nullptr); EXIT_IF(render_pass == nullptr); EXIT_IF(static_params == nullptr); EXIT_IF(dynamic_params == nullptr); - // EXIT_IF(additional_params == nullptr); - auto* pipeline = new VulkanPipeline; - // pipeline->additional_params = additional_params; + auto* pipeline = new VulkanPipeline; pipeline->static_params = static_params; pipeline->dynamic_params = dynamic_params; @@ -2032,16 +2085,13 @@ static VulkanPipeline* CreatePipelineInternal(VkRenderPass render_pass, const Sh // NOLINTNEXTLINE(readability-function-cognitive-complexity) static VulkanPipeline* CreatePipelineInternal(const ShaderComputeInputInfo* input_info, const Vector& cs_shader, - const PipelineStaticParameters* static_params, PipelineDynamicParameters* dynamic_params/*, - const PipelineAdditionalParameters* additional_params*/) + const PipelineStaticParameters* static_params, PipelineDynamicParameters* dynamic_params) { EXIT_IF(g_render_ctx == nullptr); EXIT_IF(static_params == nullptr); EXIT_IF(dynamic_params == nullptr); - // EXIT_IF(additional_params == nullptr); - auto* pipeline = new VulkanPipeline; - // pipeline->additional_params = additional_params; + auto* pipeline = new VulkanPipeline; pipeline->static_params = static_params; pipeline->dynamic_params = dynamic_params; @@ -2124,18 +2174,15 @@ void PipelineCache::DeletePipelineInternal(Pipeline& p) EXIT_IF(p.pipeline->pipeline_layout == nullptr); EXIT_IF(p.static_params == nullptr); EXIT_IF(p.dynamic_params == nullptr); - // EXIT_IF(p.pipeline->additional_params == nullptr); EXIT_IF(p.pipeline->static_params != p.static_params); EXIT_IF(p.pipeline->dynamic_params != p.dynamic_params); delete p.static_params; delete p.dynamic_params; - // delete p.pipeline->additional_params; p.static_params = nullptr; p.dynamic_params = nullptr; - // p.pipeline->additional_params = nullptr; auto* gctx = g_render_ctx->GetGraphicCtx(); @@ -2315,11 +2362,6 @@ VulkanPipeline* PipelineCache::CreatePipeline(VulkanFramebuffer* framebuffer, Re auto vs_code = ShaderParseVS(&vs_regs); auto ps_code = ShaderParsePS(&ps_regs); - // auto* params2 = new PipelineAdditionalParameters; - - // params2->vs_bind = ShaderGetBindParametersVS(vs_code, vs_input_info); - // params2->ps_bind = ShaderGetBindParametersPS(ps_code, ps_input_info); - auto vs_shader = ShaderRecompileVS(vs_code, vs_input_info); auto ps_shader = ShaderRecompilePS(ps_code, ps_input_info); @@ -2327,7 +2369,7 @@ VulkanPipeline* PipelineCache::CreatePipeline(VulkanFramebuffer* framebuffer, Re EXIT_IF(ps_shader.IsEmpty()); p.pipeline = CreatePipelineInternal(framebuffer->render_pass, vs_input_info, vs_shader, ps_input_info, ps_shader, p.static_params, - p.dynamic_params /*, params2*/); + p.dynamic_params); EXIT_NOT_IMPLEMENTED(p.pipeline == nullptr); @@ -2393,10 +2435,6 @@ VulkanPipeline* PipelineCache::CreatePipeline(const ShaderComputeInputInfo* inpu auto cs_code = ShaderParseCS(cs_regs); - // auto* params2 = new PipelineAdditionalParameters; - - // params2->cs_bind = ShaderGetBindParametersCS(cs_code, input_info); - auto cs_shader = ShaderRecompileCS(cs_code, input_info); EXIT_IF(cs_shader.IsEmpty()); @@ -2442,7 +2480,6 @@ void PipelineCache::DeletePipeline(VulkanPipeline* pipeline) if (m_pipelines.IndexValid(index)) { DeletePipelineInternal(m_pipelines[index]); - // m_pipelines.RemoveAt(index); m_pipelines[index].pipeline = nullptr; } } @@ -2472,8 +2509,6 @@ void PipelineCache::DeleteAllPipelines() DeletePipelineInternal(p); p.pipeline = nullptr; } - - // m_pipelines.Clear(); } static void create_layout(GraphicContext* gctx, int storage_buffers_num, int textures2d_sampled_num, int textures2d_storage_num, @@ -2721,13 +2756,121 @@ void DescriptorCache::Free(VulkanDescriptorSet* set) delete set; } +uint32_t DescriptorCache::CalcHash(const Set& s) +{ + uint32_t hash = 0; + hash += Core::hash8(static_cast(s.stage)); + hash ^= Core::hash8(static_cast(s.storage_buffers_num)); + hash += Core::hash8(static_cast(s.textures2d_sampled_num)); + hash ^= Core::hash8(static_cast(s.textures2d_storage_num)); + hash += Core::hash8(static_cast(s.samplers_num)); + hash ^= Core::hash8(static_cast(s.gds_buffers_num)); + for (int i = 0; i < s.storage_buffers_num; i++) + { + hash += Core::hash64(s.storage_buffers_id[i]); + } + for (int i = 0; i < s.textures2d_sampled_num; i++) + { + hash ^= Core::hash64(s.textures2d_sampled_id[i]); + } + for (int i = 0; i < s.textures2d_storage_num; i++) + { + hash += Core::hash64(s.textures2d_storage_id[i]); + } + for (int i = 0; i < s.samplers_num; i++) + { + hash ^= Core::hash64(s.samplers_id[i]); + } + for (int i = 0; i < s.gds_buffers_num; i++) + { + hash += Core::hash64(s.gds_buffers_id[i]); + } + return hash; +} + +// NOLINTNEXTLINE(readability-function-cognitive-complexity) +VulkanDescriptorSet* DescriptorCache::FindSet(const Set& s) +{ + const auto* list = m_sets_map.Find(s.hash); + if (list != nullptr) + { + for (int index: *list) + { + auto& set = m_sets[index]; + + if (set.set != nullptr && set.stage == s.stage && set.storage_buffers_num == s.storage_buffers_num && + set.textures2d_sampled_num == s.textures2d_sampled_num && set.textures2d_storage_num == s.textures2d_storage_num && + set.samplers_num == s.samplers_num && set.gds_buffers_num == s.gds_buffers_num) + { + bool match = true; + for (int i = 0; i < s.storage_buffers_num; i++) + { + if (match && s.storage_buffers_id[i] != set.storage_buffers_id[i]) + { + match = false; + break; + } + } + if (match) + { + for (int i = 0; i < s.textures2d_sampled_num; i++) + { + if (s.textures2d_sampled_id[i] != set.textures2d_sampled_id[i]) + { + match = false; + break; + } + } + } + if (match) + { + for (int i = 0; i < s.textures2d_storage_num; i++) + { + if (s.textures2d_storage_id[i] != set.textures2d_storage_id[i]) + { + match = false; + break; + } + } + } + if (match) + { + for (int i = 0; i < s.samplers_num; i++) + { + if (s.samplers_id[i] != set.samplers_id[i]) + { + match = false; + break; + } + } + } + if (match) + { + for (int i = 0; i < s.gds_buffers_num; i++) + { + if (s.gds_buffers_id[i] != set.gds_buffers_id[i]) + { + match = false; + break; + } + } + } + if (match) + { + return set.set; + } + } + } + } + return nullptr; +} + // NOLINTNEXTLINE(readability-function-cognitive-complexity) VulkanDescriptorSet* DescriptorCache::GetDescriptor(Stage stage, VulkanBuffer** storage_buffers, VulkanImage** textures2d_sampled, const bool* textures2d_depth, VulkanImage** textures2d_storage, uint64_t* samplers, - VulkanBuffer** gds_buffers, - const ShaderBindResources& bind /*, const ShaderBindParameters& bind_params*/) + VulkanBuffer** gds_buffers, const ShaderBindResources& bind) { - KYTY_PROFILER_BLOCK("DescriptorCache::GetDescriptor"); + KYTY_PROFILER_BLOCK("DescriptorCache::GetDescriptor::search"); int storage_buffers_num = bind.storage_buffers.buffers_num; int textures2d_sampled_num = bind.textures2D.textures2d_sampled_num; @@ -2746,71 +2889,44 @@ VulkanDescriptorSet* DescriptorCache::GetDescriptor(Stage stage, VulkanBuffer** auto* gctx = g_render_ctx->GetGraphicCtx(); EXIT_IF(gctx == nullptr); - for (auto& set: m_sets) + Set nset; + nset.set = nullptr; + nset.storage_buffers_num = storage_buffers_num; + nset.textures2d_sampled_num = textures2d_sampled_num; + nset.textures2d_storage_num = textures2d_storage_num; + nset.samplers_num = samplers_num; + nset.gds_buffers_num = gds_buffers_num; + nset.stage = stage; + for (int i = 0; i < storage_buffers_num; i++) { - if (set.set != nullptr && set.stage == stage && set.storage_buffers_num == storage_buffers_num && - set.textures2d_sampled_num == textures2d_sampled_num && set.textures2d_storage_num == textures2d_storage_num && - set.samplers_num == samplers_num && set.gds_buffers_num == gds_buffers_num) - { - bool match = true; - for (int i = 0; i < storage_buffers_num; i++) - { - if (match && storage_buffers[i]->memory.unique_id != set.storage_buffers_id[i]) - { - match = false; - break; - } - } - if (match) - { - for (int i = 0; i < textures2d_sampled_num; i++) - { - if (textures2d_sampled[i]->memory.unique_id != set.textures2d_sampled_id[i]) - { - match = false; - break; - } - } - } - if (match) - { - for (int i = 0; i < textures2d_storage_num; i++) - { - if (textures2d_storage[i]->memory.unique_id != set.textures2d_storage_id[i]) - { - match = false; - break; - } - } - } - if (match) - { - for (int i = 0; i < samplers_num; i++) - { - if (samplers[i] != set.samplers_id[i]) - { - match = false; - break; - } - } - } - if (match) - { - for (int i = 0; i < gds_buffers_num; i++) - { - if (gds_buffers[i]->memory.unique_id != set.gds_buffers_id[i]) - { - match = false; - break; - } - } - } - if (match) - { - return set.set; - } - } + nset.storage_buffers_id[i] = storage_buffers[i]->memory.unique_id; } + for (int i = 0; i < textures2d_sampled_num; i++) + { + nset.textures2d_sampled_id[i] = textures2d_sampled[i]->memory.unique_id; + } + for (int i = 0; i < textures2d_storage_num; i++) + { + nset.textures2d_storage_id[i] = textures2d_storage[i]->memory.unique_id; + } + for (int i = 0; i < samplers_num; i++) + { + nset.samplers_id[i] = samplers[i]; + } + for (int i = 0; i < gds_buffers_num; i++) + { + nset.gds_buffers_id[i] = gds_buffers[i]->memory.unique_id; + } + nset.hash = CalcHash(nset); + + if (auto* f = FindSet(nset); f != nullptr) + { + return f; + } + + KYTY_PROFILER_END_BLOCK; + + KYTY_PROFILER_BLOCK("DescriptorCache::GetDescriptor::create"); auto* new_set = Allocate(stage, storage_buffers_num, textures2d_sampled_num, textures2d_storage_num, samplers_num, gds_buffers_num); EXIT_NOT_IMPLEMENTED(new_set == nullptr); @@ -2951,46 +3067,28 @@ VulkanDescriptorSet* DescriptorCache::GetDescriptor(Stage stage, VulkanBuffer** vkUpdateDescriptorSets(gctx->device, binding_num, descriptor_write, 0, nullptr); - Set nset; - nset.set = new_set; - nset.storage_buffers_num = storage_buffers_num; - nset.textures2d_sampled_num = textures2d_sampled_num; - nset.textures2d_storage_num = textures2d_storage_num; - nset.samplers_num = samplers_num; - nset.gds_buffers_num = gds_buffers_num; - nset.stage = stage; - for (int i = 0; i < storage_buffers_num; i++) + nset.set = new_set; + + int index = 0; + + if (m_first_free_set != -1) { - nset.storage_buffers_id[i] = storage_buffers[i]->memory.unique_id; - } - for (int i = 0; i < textures2d_sampled_num; i++) + index = m_first_free_set; + auto& set = m_sets[m_first_free_set]; + m_first_free_set = set.next_free_set; + set = nset; + } else { - nset.textures2d_sampled_id[i] = textures2d_sampled[i]->memory.unique_id; - } - for (int i = 0; i < textures2d_storage_num; i++) - { - nset.textures2d_storage_id[i] = textures2d_storage[i]->memory.unique_id; - } - for (int i = 0; i < samplers_num; i++) - { - nset.samplers_id[i] = samplers[i]; - } - for (int i = 0; i < gds_buffers_num; i++) - { - nset.gds_buffers_id[i] = gds_buffers[i]->memory.unique_id; + index = static_cast(m_sets.Size()); + m_sets.Add(nset); } - for (auto& set: m_sets) + auto& ids = m_sets_map[nset.hash]; + if (!ids.Contains(index)) { - if (set.set == nullptr) - { - set = nset; - return new_set; - } + ids.Add(index); } - m_sets.Add(nset); - return new_set; } @@ -3000,6 +3098,7 @@ void DescriptorCache::FreeDescriptor(VulkanBuffer* buffer) Core::LockGuard lock(m_mutex); + int index = 0; for (auto& set: m_sets) { if (set.set != nullptr) @@ -3009,11 +3108,15 @@ void DescriptorCache::FreeDescriptor(VulkanBuffer* buffer) if (set.storage_buffers_id[i] == buffer->memory.unique_id) { Free(set.set); - set.set = nullptr; + set.set = nullptr; + set.next_free_set = m_first_free_set; + m_first_free_set = index; + m_sets_map[set.hash].Remove(index); break; } } } + index++; } } @@ -3023,6 +3126,7 @@ void DescriptorCache::FreeDescriptor(VulkanImage* image) Core::LockGuard lock(m_mutex); + int index = 0; for (auto& set: m_sets) { if (set.set != nullptr) @@ -3032,16 +3136,19 @@ void DescriptorCache::FreeDescriptor(VulkanImage* image) if (set.textures2d_sampled_id[i] == image->memory.unique_id) { Free(set.set); - set.set = nullptr; + set.set = nullptr; + set.next_free_set = m_first_free_set; + m_first_free_set = index; + m_sets_map[set.hash].Remove(index); break; } } } + index++; } } -VkDescriptorSetLayout DescriptorCache::GetDescriptorSetLayout(Stage stage, const ShaderBindResources& bind/*, - const ShaderBindParameters& bind_params*/) +VkDescriptorSetLayout DescriptorCache::GetDescriptorSetLayout(Stage stage, const ShaderBindResources& bind) { int storage_buffers_num = bind.storage_buffers.buffers_num; int textures2d_sampled_num = bind.textures2D.textures2d_sampled_num; @@ -3192,7 +3299,7 @@ static Vector FindRenderTexture(uint64_t vaddr, uint6 Vector ret; - auto objects = GpuMemoryFindObjects(vaddr, size, exact, false); + auto objects = GpuMemoryFindObjects(vaddr, size, GpuMemoryObjectType::RenderTexture, exact, false); for (const auto& obj: objects) { @@ -3211,7 +3318,7 @@ static Vector FindDepthStencil(uint64_t vaddr, uint64_ Vector ret; - auto objects = GpuMemoryFindObjects(vaddr, size, exact, true); + auto objects = GpuMemoryFindObjects(vaddr, size, GpuMemoryObjectType::DepthStencilBuffer, exact, true); for (const auto& obj: objects) { @@ -3339,7 +3446,7 @@ void GraphicsRenderDepthStencilBarrier(CommandBuffer* buffer, uint64_t vaddr, ui } // NOLINTNEXTLINE(readability-function-cognitive-complexity) -static void FindRenderDepthInfo(CommandBuffer* /*buffer*/, const HW::HardwareContext& hw, RenderDepthInfo* r) +static void FindRenderDepthInfo(uint64_t submit_id, CommandBuffer* /*buffer*/, const HW::HardwareContext& hw, RenderDepthInfo* r) { KYTY_PROFILER_FUNCTION(); @@ -3353,11 +3460,11 @@ static void FindRenderDepthInfo(CommandBuffer* /*buffer*/, const HW::HardwareCon const auto& sm = hw.GetStencilMask(); const auto& cc = hw.GetColorControl(); - uint32_t size = 0; - uint32_t stencil_size = 0; - uint32_t htile_size = 0; - uint32_t depth_size = 0; - uint32_t pitch = 0; + uint32_t size = 0; + uint32_t pitch = (z.pitch_div8_minus1 + 1) * 8; + TileSizeAlign stencil_size {}; + TileSizeAlign htile_size {}; + TileSizeAlign depth_size {}; if (z.z_info.format == 3) { @@ -3371,16 +3478,14 @@ static void FindRenderDepthInfo(CommandBuffer* /*buffer*/, const HW::HardwareCon bool decompress = htile && (rc.depth_compress_disable || rc.stencil_compress_disable); - TileGetDepthSize(z.width, z.height, z.z_info.format, z.stencil_info.format, htile, neo, &stencil_size, &htile_size, &depth_size, - &pitch); - - if (pitch == 0) + if (!TileGetDepthSize(z.width, z.height, pitch, z.z_info.format, z.stencil_info.format, htile, neo, &stencil_size, &htile_size, + &depth_size)) { - depth_size = size; + depth_size.size = size; + depth_size.align = neo ? 65536 : 32768; } else { - EXIT_NOT_IMPLEMENTED(depth_size != size); - EXIT_NOT_IMPLEMENTED((z.pitch_div8_minus1 + 1) * 8 != pitch); + EXIT_NOT_IMPLEMENTED(depth_size.size != size); } if (dc.z_enable || dc.z_write_enable || dc.stencil_enable || decompress) @@ -3397,14 +3502,21 @@ static void FindRenderDepthInfo(CommandBuffer* /*buffer*/, const HW::HardwareCon } } + auto stencil_addr_mask = static_cast(stencil_size.align) - 1; + auto depth_addr_mask = static_cast(depth_size.align) - 1; + auto htile_addr_mask = static_cast(htile_size.align) - 1; + r->htile = htile; r->neo = neo; - r->depth_buffer_size = depth_size; - r->depth_buffer_vaddr = z.z_read_base_addr; - r->stencil_buffer_size = stencil_size; - r->stencil_buffer_vaddr = z.stencil_read_base_addr; - r->htile_buffer_size = htile_size; - r->htile_buffer_vaddr = z.htile_data_base_addr; + r->depth_buffer_size = depth_size.size; + r->depth_buffer_vaddr = z.z_read_base_addr & ~depth_addr_mask; + r->depth_tile_swizzle = z.z_read_base_addr & depth_addr_mask; + r->stencil_buffer_size = stencil_size.size; + r->stencil_buffer_vaddr = z.stencil_read_base_addr & ~stencil_addr_mask; + r->stencil_tile_swizzle = z.stencil_read_base_addr & stencil_addr_mask; + r->htile_buffer_size = htile_size.size; + r->htile_buffer_vaddr = z.htile_data_base_addr & ~htile_addr_mask; + r->htile_tile_swizzle = z.htile_data_base_addr & htile_addr_mask; r->width = z.width; r->height = z.height; r->depth_clear_enable = rc.depth_clear_enable; @@ -3452,6 +3564,10 @@ static void FindRenderDepthInfo(CommandBuffer* /*buffer*/, const HW::HardwareCon { DepthStencilBufferObject vulkan_buffer_info(r->format, r->width, r->height, htile, neo); + EXIT_NOT_IMPLEMENTED(z.z_info.tile_mode_index != 0 && r->depth_tile_swizzle != 0); + EXIT_NOT_IMPLEMENTED(r->stencil_tile_swizzle != 0); + EXIT_NOT_IMPLEMENTED(r->htile_tile_swizzle != 0); + r->vaddr_num = 0; if (r->depth_buffer_size > 0) @@ -3478,7 +3594,7 @@ static void FindRenderDepthInfo(CommandBuffer* /*buffer*/, const HW::HardwareCon EXIT_NOT_IMPLEMENTED(r->vaddr_num == 0); r->vulkan_buffer = static_cast( - GpuMemoryCreateObject(g_render_ctx->GetGraphicCtx(), nullptr, r->vaddr, r->size, r->vaddr_num, vulkan_buffer_info)); + GpuMemoryCreateObject(submit_id, g_render_ctx->GetGraphicCtx(), nullptr, r->vaddr, r->size, r->vaddr_num, vulkan_buffer_info)); EXIT_NOT_IMPLEMENTED(r->vulkan_buffer == nullptr); @@ -3490,7 +3606,7 @@ static void FindRenderDepthInfo(CommandBuffer* /*buffer*/, const HW::HardwareCon } // NOLINTNEXTLINE(readability-function-cognitive-complexity) -static void FindRenderColorInfo(CommandBuffer* buffer, const HW::HardwareContext& hw, RenderColorInfo* r) +static void FindRenderColorInfo(uint64_t submit_id, CommandBuffer* buffer, const HW::HardwareContext& hw, RenderColorInfo* r) { KYTY_PROFILER_FUNCTION(); @@ -3562,7 +3678,7 @@ static void FindRenderColorInfo(CommandBuffer* buffer, const HW::HardwareContext // Render to texture RenderTextureObject vulkan_buffer_info(rt_format, width, height, tile, rt.info.neo_mode, pitch); auto* buffer_vulkan = static_cast( - Graphics::GpuMemoryCreateObject(g_render_ctx->GetGraphicCtx(), buffer, rt.base.addr, size, vulkan_buffer_info)); + Graphics::GpuMemoryCreateObject(submit_id, g_render_ctx->GetGraphicCtx(), buffer, rt.base.addr, size, vulkan_buffer_info)); EXIT_NOT_IMPLEMENTED(buffer_vulkan == nullptr); r->type = RenderColorType::RenderTexture; r->base_addr = rt.base.addr; @@ -3583,7 +3699,7 @@ static void FindRenderColorInfo(CommandBuffer* buffer, const HW::HardwareContext // Offscreen buffer VideoOutBufferObject vulkan_buffer_info(format, width, height, tile, Config::IsNeo(), pitch); auto* buffer_vulkan = static_cast( - Graphics::GpuMemoryCreateObject(g_render_ctx->GetGraphicCtx(), nullptr, rt.base.addr, size, vulkan_buffer_info)); + Graphics::GpuMemoryCreateObject(submit_id, g_render_ctx->GetGraphicCtx(), nullptr, rt.base.addr, size, vulkan_buffer_info)); EXIT_NOT_IMPLEMENTED(buffer_vulkan == nullptr); r->type = RenderColorType::OffscreenBuffer; r->base_addr = rt.base.addr; @@ -3628,8 +3744,8 @@ static void InvalidateMemoryObject(const RenderDepthInfo& r) } } -static void PrepareStorageBuffers(CommandBuffer* buffer, const ShaderStorageResources& storage_buffers, VulkanBuffer** buffers, - uint32_t** sgprs) +static void PrepareStorageBuffers(uint64_t submit_id, CommandBuffer* buffer, const ShaderStorageResources& storage_buffers, + VulkanBuffer** buffers, uint32_t** sgprs) { KYTY_PROFILER_FUNCTION(); @@ -3667,7 +3783,8 @@ static void PrepareStorageBuffers(CommandBuffer* buffer, const ShaderStorageReso StorageBufferGpuObject buf_info(stride, num_records, read_only); - auto* buf = static_cast(GpuMemoryCreateObject(g_render_ctx->GetGraphicCtx(), nullptr, addr, size, buf_info)); + auto* buf = static_cast( + GpuMemoryCreateObject(submit_id, g_render_ctx->GetGraphicCtx(), nullptr, addr, size, buf_info)); EXIT_NOT_IMPLEMENTED(buf == nullptr); @@ -3689,7 +3806,7 @@ static void PrepareStorageBuffers(CommandBuffer* buffer, const ShaderStorageReso } // NOLINTNEXTLINE(readability-function-cognitive-complexity) -static void PrepareTextures(CommandBuffer* buffer, const ShaderTextureResources& textures, VulkanImage** images_sampled, +static void PrepareTextures(uint64_t submit_id, CommandBuffer* buffer, const ShaderTextureResources& textures, VulkanImage** images_sampled, VulkanImage** images_storage, bool* images_depth, uint32_t** sgprs /*, const bool* without_sampler*/) { KYTY_PROFILER_FUNCTION(); @@ -3721,7 +3838,8 @@ static void PrepareTextures(CommandBuffer* buffer, const ShaderTextureResources& // EXIT_NOT_IMPLEMENTED(r.DstSelW() != 7); // EXIT_NOT_IMPLEMENTED(r.BaseLevel() != 0); // EXIT_NOT_IMPLEMENTED(r.LastLevel() != 0 && r.LastLevel() != 9); - EXIT_NOT_IMPLEMENTED(!(r.TilingIdx() == 8 || r.TilingIdx() == 13 || r.TilingIdx() == 14 || r.TilingIdx() == 2)); + EXIT_NOT_IMPLEMENTED( + !(r.TilingIdx() == 8 || r.TilingIdx() == 13 || r.TilingIdx() == 14 || r.TilingIdx() == 2 || r.TilingIdx() == 10)); // EXIT_NOT_IMPLEMENTED(!(r.LastLevel() == 0 && r.Pow2Pad() == false) && !(r.LastLevel() == 9 && r.Pow2Pad() == true)); EXIT_NOT_IMPLEMENTED(r.Type() != 9); EXIT_NOT_IMPLEMENTED(r.Depth() != 0); @@ -3737,22 +3855,24 @@ static void PrepareTextures(CommandBuffer* buffer, const ShaderTextureResources& EXIT_NOT_IMPLEMENTED(read_only && !(textures.desc[i].usage == ShaderTextureUsage::ReadOnly)); - auto addr = r.Base(); - uint32_t size = 0; - bool neo = Config::IsNeo(); - auto width = r.Width() + 1; - auto height = r.Height() + 1; - auto pitch = r.Pitch() + 1; - auto base_level = r.BaseLevel(); - auto levels = r.LastLevel() + 1; - auto tile = r.TilingIdx(); - uint32_t swizzle = static_cast(r.DstSelX()) | (static_cast(r.DstSelY()) << 8u) | + TileSizeAlign size {}; + auto addr = r.Base(); + bool neo = Config::IsNeo(); + auto width = r.Width() + 1; + auto height = r.Height() + 1; + auto pitch = r.Pitch() + 1; + auto base_level = r.BaseLevel(); + auto levels = r.LastLevel() + 1; + auto tile = r.TilingIdx(); + uint32_t swizzle = static_cast(r.DstSelX()) | (static_cast(r.DstSelY()) << 8u) | (static_cast(r.DstSelZ()) << 16u) | (static_cast(r.DstSelW()) << 24u); bool check_depth_texture = (tile == 2); TileGetTextureSize(r.Dfmt(), r.Nfmt(), width, height, pitch, levels, tile, neo, &size, nullptr, nullptr, nullptr); - EXIT_NOT_IMPLEMENTED(size == 0); + + EXIT_NOT_IMPLEMENTED(size.size == 0); + EXIT_NOT_IMPLEMENTED((addr & (static_cast(size.align) - 1u)) != 0); VulkanImage* tex = nullptr; bool render_texture = false; @@ -3760,7 +3880,7 @@ static void PrepareTextures(CommandBuffer* buffer, const ShaderTextureResources& if (check_depth_texture) { - auto dtex = FindDepthStencil(addr, size, true); + auto dtex = FindDepthStencil(addr, size.size, true); depth_texture = !dtex.IsEmpty(); if (depth_texture) { @@ -3771,7 +3891,7 @@ static void PrepareTextures(CommandBuffer* buffer, const ShaderTextureResources& } } else { - auto rtex = FindRenderTexture(addr, size, true); + auto rtex = FindRenderTexture(addr, size.size, true); render_texture = !rtex.IsEmpty(); if (render_texture) { @@ -3790,7 +3910,7 @@ static void PrepareTextures(CommandBuffer* buffer, const ShaderTextureResources& StorageTextureObject vulkan_texture_info(r.Dfmt(), r.Nfmt(), width, height, pitch, base_level, levels, tile, neo, swizzle); tex = static_cast( - GpuMemoryCreateObject(g_render_ctx->GetGraphicCtx(), buffer, addr, size, vulkan_texture_info)); + GpuMemoryCreateObject(submit_id, g_render_ctx->GetGraphicCtx(), buffer, addr, size.size, vulkan_texture_info)); } else { EXIT_NOT_IMPLEMENTED(textures.desc[i].usage != ShaderTextureUsage::ReadOnly); @@ -3798,7 +3918,7 @@ static void PrepareTextures(CommandBuffer* buffer, const ShaderTextureResources& TextureObject vulkan_texture_info(r.Dfmt(), r.Nfmt(), width, height, pitch, base_level, levels, tile, neo, swizzle); tex = static_cast( - GpuMemoryCreateObject(g_render_ctx->GetGraphicCtx(), buffer, addr, size, vulkan_texture_info)); + GpuMemoryCreateObject(submit_id, g_render_ctx->GetGraphicCtx(), buffer, addr, size.size, vulkan_texture_info)); } } @@ -3906,9 +4026,8 @@ static void PrepareGdsPointers(const ShaderGdsResources& gds_pointers, uint32_t* } } -static void BindDescriptors(CommandBuffer* buffer, VkPipelineBindPoint pipeline_bind_point, VkPipelineLayout layout, - const ShaderBindResources& bind, /*const ShaderBindParameters& bind_params,*/ VkShaderStageFlags vk_stage, - DescriptorCache::Stage stage) +static void BindDescriptors(uint64_t submit_id, CommandBuffer* buffer, VkPipelineBindPoint pipeline_bind_point, VkPipelineLayout layout, + const ShaderBindResources& bind, VkShaderStageFlags vk_stage, DescriptorCache::Stage stage) { KYTY_PROFILER_FUNCTION(); @@ -3935,12 +4054,11 @@ static void BindDescriptors(CommandBuffer* buffer, VkPipelineBindPoint pipeline_ if (bind.storage_buffers.buffers_num > 0) { - PrepareStorageBuffers(buffer, bind.storage_buffers, storage_buffers, &sgprs_ptr); + PrepareStorageBuffers(submit_id, buffer, bind.storage_buffers, storage_buffers, &sgprs_ptr); } if (bind.textures2D.textures_num > 0) { - PrepareTextures(buffer, bind.textures2D, textures2d_sampled, textures2d_storage, textures2d_depth, &sgprs_ptr/*, - bind.textures2D.textures2d_without_sampler*/); + PrepareTextures(submit_id, buffer, bind.textures2D, textures2d_sampled, textures2d_storage, textures2d_depth, &sgprs_ptr); } if (bind.samplers.samplers_num > 0) { @@ -4035,8 +4153,8 @@ static void SetDynamicParams(VkCommandBuffer vk_buffer, VulkanPipeline* pipeline } } -void GraphicsRenderDrawIndex(CommandBuffer* buffer, HW::HardwareContext* ctx, HW::UserConfig* ucfg, uint32_t index_type_and_size, - uint32_t index_count, const void* index_addr, uint32_t flags, uint32_t type) +void GraphicsRenderDrawIndex(uint64_t submit_id, CommandBuffer* buffer, HW::HardwareContext* ctx, HW::UserConfig* ucfg, + uint32_t index_type_and_size, uint32_t index_count, const void* index_addr, uint32_t flags, uint32_t type) { KYTY_PROFILER_FUNCTION(); @@ -4058,17 +4176,23 @@ void GraphicsRenderDrawIndex(CommandBuffer* buffer, HW::HardwareContext* ctx, HW return; } - // const auto& rt = ctx->GetRenderTargets(0); - // const auto& bc = ctx->GetBlendControl(0); - uc_print("GraphicsRenderDrawIndex():UserConfig:", *ucfg); hw_print(*ctx); hw_check(*ctx); - EXIT_NOT_IMPLEMENTED(ucfg->GetPrimType() != 4); EXIT_NOT_IMPLEMENTED(ctx->GetShaderStages() != 0); + VkPrimitiveTopology topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST; + + switch (ucfg->GetPrimType()) + { + case 4: topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; break; // kPrimitiveTypeTriList + case 5: topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN; break; // kPrimitiveTypeTriFan + case 6: topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; break; // kPrimitiveTypeTriStrip + default: EXIT("unknown primitive type: %u\n", ucfg->GetPrimType()); + } + printf("GraphicsRenderDrawIndex():Parameters:\n"); printf("\t index_type_and_size = 0x%08" PRIx32 "\n", index_type_and_size); printf("\t index_count = 0x%08" PRIx32 "\n", index_count); @@ -4096,10 +4220,10 @@ void GraphicsRenderDrawIndex(CommandBuffer* buffer, HW::HardwareContext* ctx, HW EXIT_NOT_IMPLEMENTED(type != 1); RenderDepthInfo depth_info; - FindRenderDepthInfo(buffer, *ctx, &depth_info); + FindRenderDepthInfo(submit_id, buffer, *ctx, &depth_info); RenderColorInfo color_info; - FindRenderColorInfo(buffer, *ctx, &color_info); + FindRenderColorInfo(submit_id, buffer, *ctx, &color_info); auto* framebuffer = g_render_ctx->GetFramebufferCache()->CreateFramebuffer(&color_info, &depth_info); @@ -4117,7 +4241,7 @@ void GraphicsRenderDrawIndex(CommandBuffer* buffer, HW::HardwareContext* ctx, HW EXIT_NOT_IMPLEMENTED(vs_input_info.buffers_num > 1); auto* pipeline = g_render_ctx->GetPipelineCache()->CreatePipeline(framebuffer, &color_info, &depth_info, &vs_input_info, ctx, - &ps_input_info, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST); + &ps_input_info, topology); vkCmdBindPipeline(vk_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->pipeline); @@ -4129,22 +4253,22 @@ void GraphicsRenderDrawIndex(CommandBuffer* buffer, HW::HardwareContext* ctx, HW uint64_t addr = b.addr; uint64_t size = b.stride * b.num_records; - auto* vertices = - static_cast(GpuMemoryCreateObject(g_render_ctx->GetGraphicCtx(), nullptr, addr, size, VertexBufferGpuObject())); + auto* vertices = static_cast( + GpuMemoryCreateObject(submit_id, g_render_ctx->GetGraphicCtx(), nullptr, addr, size, VertexBufferGpuObject())); VkDeviceSize offset = 0; vkCmdBindVertexBuffers(vk_buffer, i, 1, &vertices->buffer, &offset); } - BindDescriptors(buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->pipeline_layout, vs_input_info.bind, - /*pipeline->additional_params->vs_bind,*/ VK_SHADER_STAGE_VERTEX_BIT, DescriptorCache::Stage::Vertex); + BindDescriptors(submit_id, buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->pipeline_layout, vs_input_info.bind, + VK_SHADER_STAGE_VERTEX_BIT, DescriptorCache::Stage::Vertex); - BindDescriptors(buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->pipeline_layout, ps_input_info.bind, - /*pipeline->additional_params->ps_bind,*/ VK_SHADER_STAGE_FRAGMENT_BIT, DescriptorCache::Stage::Pixel); + BindDescriptors(submit_id, buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->pipeline_layout, ps_input_info.bind, + VK_SHADER_STAGE_FRAGMENT_BIT, DescriptorCache::Stage::Pixel); VulkanBuffer* indices = static_cast(GpuMemoryCreateObject( - g_render_ctx->GetGraphicCtx(), nullptr, reinterpret_cast(index_addr), index_size, IndexBufferGpuObject())); + submit_id, g_render_ctx->GetGraphicCtx(), nullptr, reinterpret_cast(index_addr), index_size, IndexBufferGpuObject())); EXIT_NOT_IMPLEMENTED(indices == nullptr); @@ -4161,8 +4285,8 @@ void GraphicsRenderDrawIndex(CommandBuffer* buffer, HW::HardwareContext* ctx, HW } // NOLINTNEXTLINE(readability-function-cognitive-complexity) -void GraphicsRenderDrawIndexAuto(CommandBuffer* buffer, HW::HardwareContext* ctx, HW::UserConfig* ucfg, uint32_t index_count, - uint32_t flags) +void GraphicsRenderDrawIndexAuto(uint64_t submit_id, CommandBuffer* buffer, HW::HardwareContext* ctx, HW::UserConfig* ucfg, + uint32_t index_count, uint32_t flags) { KYTY_PROFILER_FUNCTION(); @@ -4182,9 +4306,6 @@ void GraphicsRenderDrawIndexAuto(CommandBuffer* buffer, HW::HardwareContext* ctx return; } - // const auto& rt = ctx->GetRenderTargets(0); - // const auto& bc = ctx->GetBlendControl(0); - uc_print("GraphicsRenderDrawIndexAuto():UserConfig:", *ucfg); hw_print(*ctx); @@ -4198,10 +4319,10 @@ void GraphicsRenderDrawIndexAuto(CommandBuffer* buffer, HW::HardwareContext* ctx EXIT_NOT_IMPLEMENTED(ctx->GetShaderStages() != 0); RenderDepthInfo depth_info; - FindRenderDepthInfo(buffer, *ctx, &depth_info); + FindRenderDepthInfo(submit_id, buffer, *ctx, &depth_info); RenderColorInfo color_info; - FindRenderColorInfo(buffer, *ctx, &color_info); + FindRenderColorInfo(submit_id, buffer, *ctx, &color_info); auto* framebuffer = g_render_ctx->GetFramebufferCache()->CreateFramebuffer(&color_info, &depth_info); @@ -4244,19 +4365,19 @@ void GraphicsRenderDrawIndexAuto(CommandBuffer* buffer, HW::HardwareContext* ctx uint64_t addr = b.addr; uint64_t size = b.stride * b.num_records; - auto* vertices = - static_cast(GpuMemoryCreateObject(g_render_ctx->GetGraphicCtx(), nullptr, addr, size, VertexBufferGpuObject())); + auto* vertices = static_cast( + GpuMemoryCreateObject(submit_id, g_render_ctx->GetGraphicCtx(), nullptr, addr, size, VertexBufferGpuObject())); VkDeviceSize offset = 0; vkCmdBindVertexBuffers(vk_buffer, i, 1, &vertices->buffer, &offset); } - BindDescriptors(buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->pipeline_layout, vs_input_info.bind, - /*pipeline->additional_params->vs_bind,*/ VK_SHADER_STAGE_VERTEX_BIT, DescriptorCache::Stage::Vertex); + BindDescriptors(submit_id, buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->pipeline_layout, vs_input_info.bind, + VK_SHADER_STAGE_VERTEX_BIT, DescriptorCache::Stage::Vertex); - BindDescriptors(buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->pipeline_layout, ps_input_info.bind, - /*pipeline->additional_params->ps_bind,*/ VK_SHADER_STAGE_FRAGMENT_BIT, DescriptorCache::Stage::Pixel); + BindDescriptors(submit_id, buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->pipeline_layout, ps_input_info.bind, + VK_SHADER_STAGE_FRAGMENT_BIT, DescriptorCache::Stage::Pixel); buffer->BeginRenderPass(framebuffer, &color_info, &depth_info); @@ -4264,8 +4385,7 @@ void GraphicsRenderDrawIndexAuto(CommandBuffer* buffer, HW::HardwareContext* ctx { case 4: vkCmdDraw(vk_buffer, index_count, 1, 0, 0); break; case 17: - EXIT_NOT_IMPLEMENTED(!(/*vertex_shader_info.vs_embedded && vertex_shader_info.vs_embedded_id == 0 &&*/ - index_count == 3 && vs_input_info.buffers_num == 0)); + EXIT_NOT_IMPLEMENTED(!(index_count == 3 && vs_input_info.buffers_num == 0)); vkCmdDraw(vk_buffer, 4, 1, 0, 0); break; case 19: @@ -4284,8 +4404,8 @@ void GraphicsRenderDrawIndexAuto(CommandBuffer* buffer, HW::HardwareContext* ctx InvalidateMemoryObject(depth_info); } -void GraphicsRenderDispatchDirect(CommandBuffer* buffer, HW::HardwareContext* ctx, uint32_t thread_group_x, uint32_t thread_group_y, - uint32_t thread_group_z, uint32_t mode) +void GraphicsRenderDispatchDirect(uint64_t submit_id, CommandBuffer* buffer, HW::HardwareContext* ctx, uint32_t thread_group_x, + uint32_t thread_group_y, uint32_t thread_group_z, uint32_t mode) { EXIT_IF(ctx == nullptr); EXIT_IF(g_render_ctx == nullptr); @@ -4314,13 +4434,13 @@ void GraphicsRenderDispatchDirect(CommandBuffer* buffer, HW::HardwareContext* ct SetDynamicParams(vk_buffer, pipeline); - BindDescriptors(buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline->pipeline_layout, input_info.bind, - /*pipeline->additional_params->cs_bind,*/ VK_SHADER_STAGE_COMPUTE_BIT, DescriptorCache::Stage::Compute); + BindDescriptors(submit_id, buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline->pipeline_layout, input_info.bind, + VK_SHADER_STAGE_COMPUTE_BIT, DescriptorCache::Stage::Compute); vkCmdDispatch(vk_buffer, thread_group_x, thread_group_y, thread_group_z); } -void GraphicsRenderWriteAtEndOfPipe(CommandBuffer* buffer, uint32_t* dst_gpu_addr, uint32_t value) +void GraphicsRenderWriteAtEndOfPipe32(uint64_t submit_id, CommandBuffer* buffer, uint32_t* dst_gpu_addr, uint32_t value) { EXIT_IF(g_render_ctx == nullptr); EXIT_IF(dst_gpu_addr == nullptr); @@ -4332,12 +4452,13 @@ void GraphicsRenderWriteAtEndOfPipe(CommandBuffer* buffer, uint32_t* dst_gpu_add Graphics::LabelGpuObject label_info(value, nullptr, nullptr); auto* label = static_cast( - GpuMemoryCreateObject(g_render_ctx->GetGraphicCtx(), nullptr, reinterpret_cast(dst_gpu_addr), 4, label_info)); + GpuMemoryCreateObject(submit_id, g_render_ctx->GetGraphicCtx(), nullptr, reinterpret_cast(dst_gpu_addr), 4, label_info)); LabelSet(buffer, label); } -void GraphicsRenderWriteAtEndOfPipeGds(CommandBuffer* buffer, uint32_t* dst_gpu_addr, uint32_t dw_offset, uint32_t dw_num) +void GraphicsRenderWriteAtEndOfPipeGds32(uint64_t submit_id, CommandBuffer* buffer, uint32_t* dst_gpu_addr, uint32_t dw_offset, + uint32_t dw_num) { EXIT_IF(g_render_ctx == nullptr); EXIT_IF(dst_gpu_addr == nullptr); @@ -4361,12 +4482,12 @@ void GraphicsRenderWriteAtEndOfPipeGds(CommandBuffer* buffer, uint32_t* dst_gpu_ nullptr, args); auto* label = static_cast( - GpuMemoryCreateObject(g_render_ctx->GetGraphicCtx(), nullptr, reinterpret_cast(dst_gpu_addr), 4, label_info)); + GpuMemoryCreateObject(submit_id, g_render_ctx->GetGraphicCtx(), nullptr, reinterpret_cast(dst_gpu_addr), 4, label_info)); LabelSet(buffer, label); } -void GraphicsRenderWriteAtEndOfPipe(CommandBuffer* buffer, uint64_t* dst_gpu_addr, uint64_t value) +void GraphicsRenderWriteAtEndOfPipe64(uint64_t submit_id, CommandBuffer* buffer, uint64_t* dst_gpu_addr, uint64_t value) { EXIT_IF(g_render_ctx == nullptr); EXIT_IF(dst_gpu_addr == nullptr); @@ -4378,12 +4499,12 @@ void GraphicsRenderWriteAtEndOfPipe(CommandBuffer* buffer, uint64_t* dst_gpu_add Graphics::LabelGpuObject label_info(value, nullptr, nullptr); auto* label = static_cast( - GpuMemoryCreateObject(g_render_ctx->GetGraphicCtx(), nullptr, reinterpret_cast(dst_gpu_addr), 8, label_info)); + GpuMemoryCreateObject(submit_id, g_render_ctx->GetGraphicCtx(), nullptr, reinterpret_cast(dst_gpu_addr), 8, label_info)); LabelSet(buffer, label); } -void GraphicsRenderWriteAtEndOfPipeClockCounter(CommandBuffer* buffer, uint64_t* dst_gpu_addr) +void GraphicsRenderWriteAtEndOfPipeClockCounter(uint64_t submit_id, CommandBuffer* buffer, uint64_t* dst_gpu_addr) { EXIT_IF(g_render_ctx == nullptr); EXIT_IF(dst_gpu_addr == nullptr); @@ -4408,12 +4529,12 @@ void GraphicsRenderWriteAtEndOfPipeClockCounter(CommandBuffer* buffer, uint64_t* nullptr, args); auto* label = static_cast( - GpuMemoryCreateObject(g_render_ctx->GetGraphicCtx(), nullptr, reinterpret_cast(dst_gpu_addr), 8, label_info)); + GpuMemoryCreateObject(submit_id, g_render_ctx->GetGraphicCtx(), nullptr, reinterpret_cast(dst_gpu_addr), 8, label_info)); LabelSet(buffer, label); } -void GraphicsRenderWriteAtEndOfPipeWithWriteBack(CommandBuffer* buffer, uint64_t* dst_gpu_addr, uint64_t value) +void GraphicsRenderWriteAtEndOfPipeWithWriteBack64(uint64_t submit_id, CommandBuffer* buffer, uint64_t* dst_gpu_addr, uint64_t value) { EXIT_IF(g_render_ctx == nullptr); EXIT_IF(dst_gpu_addr == nullptr); @@ -4433,12 +4554,13 @@ void GraphicsRenderWriteAtEndOfPipeWithWriteBack(CommandBuffer* buffer, uint64_t nullptr); auto* label = static_cast( - GpuMemoryCreateObject(g_render_ctx->GetGraphicCtx(), nullptr, reinterpret_cast(dst_gpu_addr), 8, label_info)); + GpuMemoryCreateObject(submit_id, g_render_ctx->GetGraphicCtx(), nullptr, reinterpret_cast(dst_gpu_addr), 8, label_info)); LabelSet(buffer, label); } -void GraphicsRenderWriteAtEndOfPipeWithInterruptWriteBack(CommandBuffer* buffer, uint64_t* dst_gpu_addr, uint64_t value) +void GraphicsRenderWriteAtEndOfPipeWithInterruptWriteBack64(uint64_t submit_id, CommandBuffer* buffer, uint64_t* dst_gpu_addr, + uint64_t value) { EXIT_IF(g_render_ctx == nullptr); EXIT_IF(dst_gpu_addr == nullptr); @@ -4463,12 +4585,12 @@ void GraphicsRenderWriteAtEndOfPipeWithInterruptWriteBack(CommandBuffer* buffer, }); auto* label = static_cast( - GpuMemoryCreateObject(g_render_ctx->GetGraphicCtx(), nullptr, reinterpret_cast(dst_gpu_addr), 8, label_info)); + GpuMemoryCreateObject(submit_id, g_render_ctx->GetGraphicCtx(), nullptr, reinterpret_cast(dst_gpu_addr), 8, label_info)); LabelSet(buffer, label); } -void GraphicsRenderWriteAtEndOfPipeWithInterrupt(CommandBuffer* buffer, uint64_t* dst_gpu_addr, uint64_t value) +void GraphicsRenderWriteAtEndOfPipeWithInterrupt64(uint64_t submit_id, CommandBuffer* buffer, uint64_t* dst_gpu_addr, uint64_t value) { EXIT_IF(g_render_ctx == nullptr); EXIT_IF(dst_gpu_addr == nullptr); @@ -4486,13 +4608,36 @@ void GraphicsRenderWriteAtEndOfPipeWithInterrupt(CommandBuffer* buffer, uint64_t }); auto* label = static_cast( - GpuMemoryCreateObject(g_render_ctx->GetGraphicCtx(), nullptr, reinterpret_cast(dst_gpu_addr), 8, label_info)); + GpuMemoryCreateObject(submit_id, g_render_ctx->GetGraphicCtx(), nullptr, reinterpret_cast(dst_gpu_addr), 8, label_info)); LabelSet(buffer, label); } -void GraphicsRenderWriteAtEndOfPipeWithInterruptWriteBackFlip(CommandBuffer* buffer, uint32_t* dst_gpu_addr, uint32_t value, int handle, - int index, int flip_mode, int64_t flip_arg) +void GraphicsRenderWriteAtEndOfPipeWithInterrupt32(uint64_t submit_id, CommandBuffer* buffer, uint32_t* dst_gpu_addr, uint32_t value) +{ + EXIT_IF(g_render_ctx == nullptr); + EXIT_IF(dst_gpu_addr == nullptr); + EXIT_IF(buffer == nullptr); + EXIT_IF(buffer->IsInvalid()); + + Core::LockGuard lock(g_render_ctx->GetMutex()); + + Graphics::LabelGpuObject label_info(value, nullptr, + [](const uint64_t* /*args*/) + { + EXIT_IF(g_render_ctx == nullptr); + g_render_ctx->TriggerEopEvent(); + return true; + }); + + auto* label = static_cast( + GpuMemoryCreateObject(submit_id, g_render_ctx->GetGraphicCtx(), nullptr, reinterpret_cast(dst_gpu_addr), 4, label_info)); + + LabelSet(buffer, label); +} + +void GraphicsRenderWriteAtEndOfPipeWithInterruptWriteBackFlip32(uint64_t submit_id, CommandBuffer* buffer, uint32_t* dst_gpu_addr, + uint32_t value, int handle, int index, int flip_mode, int64_t flip_arg) { EXIT_IF(g_render_ctx == nullptr); EXIT_IF(dst_gpu_addr == nullptr); @@ -4528,13 +4673,13 @@ void GraphicsRenderWriteAtEndOfPipeWithInterruptWriteBackFlip(CommandBuffer* buf args); auto* label = static_cast( - GpuMemoryCreateObject(g_render_ctx->GetGraphicCtx(), nullptr, reinterpret_cast(dst_gpu_addr), 4, label_info)); + GpuMemoryCreateObject(submit_id, g_render_ctx->GetGraphicCtx(), nullptr, reinterpret_cast(dst_gpu_addr), 4, label_info)); LabelSet(buffer, label); } -void GraphicsRenderWriteAtEndOfPipeWithFlip(CommandBuffer* buffer, uint32_t* dst_gpu_addr, uint32_t value, int handle, int index, - int flip_mode, int64_t flip_arg) +void GraphicsRenderWriteAtEndOfPipeWithFlip32(uint64_t submit_id, CommandBuffer* buffer, uint32_t* dst_gpu_addr, uint32_t value, int handle, + int index, int flip_mode, int64_t flip_arg) { EXIT_IF(g_render_ctx == nullptr); EXIT_IF(dst_gpu_addr == nullptr); @@ -4561,11 +4706,42 @@ void GraphicsRenderWriteAtEndOfPipeWithFlip(CommandBuffer* buffer, uint32_t* dst nullptr, args); auto* label = static_cast( - GpuMemoryCreateObject(g_render_ctx->GetGraphicCtx(), nullptr, reinterpret_cast(dst_gpu_addr), 4, label_info)); + GpuMemoryCreateObject(submit_id, g_render_ctx->GetGraphicCtx(), nullptr, reinterpret_cast(dst_gpu_addr), 4, label_info)); LabelSet(buffer, label); } +void GraphicsRenderWriteAtEndOfPipeOnlyFlip(uint64_t /*submit_id*/, CommandBuffer* buffer, int handle, int index, int flip_mode, + int64_t flip_arg) +{ + EXIT_IF(g_render_ctx == nullptr); + EXIT_IF(buffer == nullptr); + EXIT_IF(buffer->IsInvalid()); + + Core::LockGuard lock(g_render_ctx->GetMutex()); + + uint64_t args[] = {static_cast(handle), static_cast(index), static_cast(flip_mode), + static_cast(flip_arg)}; + + auto* label = LabelCreate32( + g_render_ctx->GetGraphicCtx(), nullptr, 0, + [](const uint64_t* args) + { + int handle = static_cast(args[0]); + int index = static_cast(args[1]); + int flip_mode = static_cast(args[2]); + int64_t flip_arg = static_cast(args[3]); + + VideoOut::VideoOutSubmitFlip(handle, index, flip_mode, flip_arg); + return true; + }, + nullptr, args); + + LabelSet(buffer, label); + + LabelDelete(label); +} + void GraphicsRenderWriteBack() { Core::LockGuard lock(g_render_ctx->GetMutex()); @@ -4773,7 +4949,6 @@ void CommandBuffer::ExecuteWithSemaphore() auto* buffer = m_pool->buffers[m_index]; auto* fence = m_pool->fences[m_index]; - // auto* semaphore = m_pool->semaphores[m_index]; VkSubmitInfo submit_info {}; submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; diff --git a/source/emulator/src/Graphics/GraphicsRun.cpp b/source/emulator/src/Graphics/GraphicsRun.cpp index 1f0225b..c82fa06 100644 --- a/source/emulator/src/Graphics/GraphicsRun.cpp +++ b/source/emulator/src/Graphics/GraphicsRun.cpp @@ -5,7 +5,6 @@ #include "Kyty/Core/String.h" #include "Kyty/Core/Threads.h" -#include "Emulator/Config.h" #include "Emulator/Graphics/AsyncJob.h" #include "Emulator/Graphics/GraphicContext.h" #include "Emulator/Graphics/Graphics.h" @@ -17,6 +16,8 @@ #include "Emulator/Graphics/Window.h" #include "Emulator/Profiler.h" +#include + #ifdef KYTY_EMU_ENABLED #define KYTY_HW_CTX_PARSER_ARGS \ @@ -67,6 +68,7 @@ public: void WriteAtEndOfPipe64(uint32_t cache_policy, uint32_t event_write_dest, uint32_t eop_event_type, uint32_t cache_action, uint32_t event_index, uint32_t event_write_source, void* dst_gpu_addr, uint64_t value, uint32_t interrupt_selector); + void Flip(); void Flip(void* dst_gpu_addr, uint32_t value); void FlipWithInterrupt(uint32_t eop_event_type, uint32_t cache_action, void* dst_gpu_addr, uint32_t value); void WriteBack(); @@ -106,6 +108,9 @@ public: [[nodiscard]] const FlipInfo& GetFlip() const { return m_flip; } void SetFlip(const FlipInfo& flip) { m_flip = flip; } + [[nodiscard]] uint64_t GetSumbitId() const { return m_sumbit_id; } + void SetSumbitId(uint64_t sumbit_id) { m_sumbit_id = sumbit_id; } + private: static constexpr int VK_BUFFERS_NUM = 4; @@ -133,6 +138,7 @@ private: uint32_t m_const_ram[0x3000] = {0}; FlipInfo m_flip; + uint64_t m_sumbit_id = 0; }; class GraphicsRing @@ -660,6 +666,7 @@ void GraphicsRing::Submit(uint32_t* cmd_draw_buffer, uint32_t num_draw_dw, uint3 m_idle_cond_var.Wait(&m_mutex); } m_done = false; + m_cp->Reset(); } @@ -714,6 +721,7 @@ GraphicsRing::CmdBatch GraphicsRing::GetCmdBatch() { m_idle = true; m_idle_cond_var.Signal(); + m_cond_var.Wait(&m_mutex); } @@ -732,6 +740,8 @@ void GraphicsRing::ThreadBatchRun(void* data) { EXIT_IF(data == nullptr); + static std::atomic_uint64_t seq = 0; + auto* ring = static_cast(data); auto* cp = ring->m_cp; @@ -745,6 +755,7 @@ void GraphicsRing::ThreadBatchRun(void* data) cp->BufferInit(); cp->ResetDeCe(); cp->SetFlip(buf.flip); + cp->SetSumbitId(++seq); ring->m_job1.Execute([cp, buf](void* /*unused*/) { cp->Run(buf.draw_buffer.data, buf.draw_buffer.num_dw); }); ring->m_job2.Execute([cp, buf](void* /*unused*/) { cp->Run(buf.const_buffer.data, buf.const_buffer.num_dw); }); @@ -968,7 +979,8 @@ void CommandProcessor::DrawIndex(uint32_t index_count, const void* index_addr, u EXIT_IF(m_current_buffer < 0 || m_current_buffer >= VK_BUFFERS_NUM); - GraphicsRenderDrawIndex(m_buffer[m_current_buffer], &m_ctx, &m_ucfg, m_index_type_and_size, index_count, index_addr, flags, type); + GraphicsRenderDrawIndex(m_sumbit_id, m_buffer[m_current_buffer], &m_ctx, &m_ucfg, m_index_type_and_size, index_count, index_addr, flags, + type); } void CommandProcessor::DispatchDirect(uint32_t thread_group_x, uint32_t thread_group_y, uint32_t thread_group_z, uint32_t mode) @@ -977,7 +989,7 @@ void CommandProcessor::DispatchDirect(uint32_t thread_group_x, uint32_t thread_g EXIT_IF(m_current_buffer < 0 || m_current_buffer >= VK_BUFFERS_NUM); - GraphicsRenderDispatchDirect(m_buffer[m_current_buffer], &m_ctx, thread_group_x, thread_group_y, thread_group_z, mode); + GraphicsRenderDispatchDirect(m_sumbit_id, m_buffer[m_current_buffer], &m_ctx, thread_group_x, thread_group_y, thread_group_z, mode); } void CommandProcessor::DrawIndexAuto(uint32_t index_count, uint32_t flags) @@ -986,7 +998,7 @@ void CommandProcessor::DrawIndexAuto(uint32_t index_count, uint32_t flags) EXIT_IF(m_current_buffer < 0 || m_current_buffer >= VK_BUFFERS_NUM); - GraphicsRenderDrawIndexAuto(m_buffer[m_current_buffer], &m_ctx, &m_ucfg, index_count, flags); + GraphicsRenderDrawIndexAuto(m_sumbit_id, m_buffer[m_current_buffer], &m_ctx, &m_ucfg, index_count, flags); } void CommandProcessor::ClearGds(uint64_t dw_offset, uint32_t dw_num, uint32_t clear_value) @@ -1035,10 +1047,11 @@ void CommandProcessor::WriteAtEndOfPipe32(uint32_t cache_policy, uint32_t event_ if (event_write_source == 0x00000002 && eop_event_type == 0x0000002f && cache_action == 0x00000000 && event_index == 0x00000006) { - GraphicsRenderWriteAtEndOfPipe(m_buffer[m_current_buffer], static_cast(dst_gpu_addr), value); + GraphicsRenderWriteAtEndOfPipe32(m_sumbit_id, m_buffer[m_current_buffer], static_cast(dst_gpu_addr), value); } else if (event_write_source == 0x00000001 && eop_event_type == 0x0000002f && cache_action == 0x00000000 && event_index == 0x00000006) { - GraphicsRenderWriteAtEndOfPipeGds(m_buffer[m_current_buffer], static_cast(dst_gpu_addr), value & 0xffffu, value >> 16u); + GraphicsRenderWriteAtEndOfPipeGds32(m_sumbit_id, m_buffer[m_current_buffer], static_cast(dst_gpu_addr), value & 0xffffu, + value >> 16u); } else { EXIT("unknown event type\n"); @@ -1067,31 +1080,43 @@ void CommandProcessor::WriteAtEndOfPipe64(uint32_t cache_policy, uint32_t event_ EXIT_NOT_IMPLEMENTED(cache_policy != 0x00000000); EXIT_NOT_IMPLEMENTED(event_write_dest != 0x00000000); - if (eop_event_type == 0x04 && cache_action == 0x00 && event_index == 0x05 && event_write_source == 0x02 && - (interrupt_selector == 0x00 || interrupt_selector == 0x03)) + bool with_interrupt = false; + bool source64 = (event_write_source == 0x02); + bool source32 = (event_write_source == 0x01); + bool source_counter = (event_write_source == 0x04); + + switch (interrupt_selector) { - GraphicsRenderWriteAtEndOfPipe(m_buffer[m_current_buffer], static_cast(dst_gpu_addr), value); - } else if (eop_event_type == 0x04 && cache_action == 0x00 && event_index == 0x05 && event_write_source == 0x01 && - (interrupt_selector == 0x00 || interrupt_selector == 0x03)) + case 0x00: + case 0x03: with_interrupt = false; break; + case 0x02: with_interrupt = true; break; + default: EXIT("unknown interrupt_selector\n"); + } + + if (eop_event_type == 0x04 && cache_action == 0x00 && event_index == 0x05 && source64 && !with_interrupt) { - GraphicsRenderWriteAtEndOfPipe(m_buffer[m_current_buffer], static_cast(dst_gpu_addr), value); + GraphicsRenderWriteAtEndOfPipe64(m_sumbit_id, m_buffer[m_current_buffer], static_cast(dst_gpu_addr), value); + } else if (eop_event_type == 0x04 && cache_action == 0x00 && event_index == 0x05 && source32 && !with_interrupt) + { + GraphicsRenderWriteAtEndOfPipe32(m_sumbit_id, m_buffer[m_current_buffer], static_cast(dst_gpu_addr), value); } else if (((eop_event_type == 0x04 && event_index == 0x05) || (eop_event_type == 0x28 && event_index == 0x05) || (eop_event_type == 0x2f && event_index == 0x06)) && - cache_action == 0x38 && event_write_source == 0x02 && (interrupt_selector == 0x00 || interrupt_selector == 0x03)) + cache_action == 0x38 && source64 && !with_interrupt) { - GraphicsRenderWriteAtEndOfPipeWithWriteBack(m_buffer[m_current_buffer], static_cast(dst_gpu_addr), value); - } else if (eop_event_type == 0x04 && cache_action == 0x00 && event_index == 0x05 && event_write_source == 0x04 && - (interrupt_selector == 0x00 || interrupt_selector == 0x03)) + GraphicsRenderWriteAtEndOfPipeWithWriteBack64(m_sumbit_id, m_buffer[m_current_buffer], static_cast(dst_gpu_addr), value); + } else if (eop_event_type == 0x04 && cache_action == 0x00 && event_index == 0x05 && source_counter && !with_interrupt) { - GraphicsRenderWriteAtEndOfPipeClockCounter(m_buffer[m_current_buffer], static_cast(dst_gpu_addr)); - } else if ((eop_event_type == 0x04 && event_index == 0x05) && cache_action == 0x00 && event_write_source == 0x02 && - interrupt_selector == 0x02) + GraphicsRenderWriteAtEndOfPipeClockCounter(m_sumbit_id, m_buffer[m_current_buffer], static_cast(dst_gpu_addr)); + } else if ((eop_event_type == 0x04 && event_index == 0x05) && cache_action == 0x00 && source64 && with_interrupt) { - GraphicsRenderWriteAtEndOfPipeWithInterrupt(m_buffer[m_current_buffer], static_cast(dst_gpu_addr), value); - } else if ((eop_event_type == 0x04 && event_index == 0x05) && cache_action == 0x3b && event_write_source == 0x02 && - interrupt_selector == 0x02) + GraphicsRenderWriteAtEndOfPipeWithInterrupt64(m_sumbit_id, m_buffer[m_current_buffer], static_cast(dst_gpu_addr), value); + } else if ((eop_event_type == 0x04 && event_index == 0x05) && cache_action == 0x00 && source32 && with_interrupt) { - GraphicsRenderWriteAtEndOfPipeWithInterruptWriteBack(m_buffer[m_current_buffer], static_cast(dst_gpu_addr), value); + GraphicsRenderWriteAtEndOfPipeWithInterrupt32(m_sumbit_id, m_buffer[m_current_buffer], static_cast(dst_gpu_addr), value); + } else if ((eop_event_type == 0x04 && event_index == 0x05) && cache_action == 0x3b && source64 && with_interrupt) + { + GraphicsRenderWriteAtEndOfPipeWithInterruptWriteBack64(m_sumbit_id, m_buffer[m_current_buffer], + static_cast(dst_gpu_addr), value); } else { EXIT("unknown event type\n"); @@ -1147,6 +1172,18 @@ void CommandProcessor::TriggerEvent(uint32_t event_type, uint32_t event_index) } } +void CommandProcessor::Flip() +{ + Core::LockGuard lock(m_mutex); + + EXIT_IF(m_current_buffer < 0 || m_current_buffer >= VK_BUFFERS_NUM); + + printf("CommandProcessor::Flip()\n"); + + GraphicsRenderWriteAtEndOfPipeOnlyFlip(m_sumbit_id, m_buffer[m_current_buffer], m_flip.handle, m_flip.index, m_flip.flip_mode, + m_flip.flip_arg); +} + void CommandProcessor::Flip(void* dst_gpu_addr, uint32_t value) { Core::LockGuard lock(m_mutex); @@ -1157,8 +1194,8 @@ void CommandProcessor::Flip(void* dst_gpu_addr, uint32_t value) printf("\t dst_gpu_addr = 0x%016" PRIx64 "\n", reinterpret_cast(dst_gpu_addr)); printf("\t value = 0x%08" PRIx32 "\n", value); - GraphicsRenderWriteAtEndOfPipeWithFlip(m_buffer[m_current_buffer], static_cast(dst_gpu_addr), value, m_flip.handle, - m_flip.index, m_flip.flip_mode, m_flip.flip_arg); + GraphicsRenderWriteAtEndOfPipeWithFlip32(m_sumbit_id, m_buffer[m_current_buffer], static_cast(dst_gpu_addr), value, + m_flip.handle, m_flip.index, m_flip.flip_mode, m_flip.flip_arg); } void CommandProcessor::FlipWithInterrupt(uint32_t eop_event_type, uint32_t cache_action, void* dst_gpu_addr, uint32_t value) @@ -1175,8 +1212,9 @@ void CommandProcessor::FlipWithInterrupt(uint32_t eop_event_type, uint32_t cache if (eop_event_type == 0x00000004 && cache_action == 0x00000038) { - GraphicsRenderWriteAtEndOfPipeWithInterruptWriteBackFlip(m_buffer[m_current_buffer], static_cast(dst_gpu_addr), value, - m_flip.handle, m_flip.index, m_flip.flip_mode, m_flip.flip_arg); + GraphicsRenderWriteAtEndOfPipeWithInterruptWriteBackFlip32(m_sumbit_id, m_buffer[m_current_buffer], + static_cast(dst_gpu_addr), value, m_flip.handle, m_flip.index, + m_flip.flip_mode, m_flip.flip_arg); } else { EXIT("unknown event type\n"); @@ -1308,13 +1346,13 @@ KYTY_HW_CTX_PARSER(hw_ctx_set_depth_render_target) z.stencil_info.tile_mode_index = KYTY_PM4_GET(buffer[1], DB_STENCIL_INFO, TILE_MODE_INDEX); z.stencil_info.tile_stencil_disable = KYTY_PM4_GET(buffer[1], DB_STENCIL_INFO, TILE_STENCIL_DISABLE); - if (Config::IsNeo()) - { - EXIT_NOT_IMPLEMENTED((buffer[2] & 0xffu) != 0); - EXIT_NOT_IMPLEMENTED((buffer[3] & 0xffu) != 0); - EXIT_NOT_IMPLEMENTED((buffer[4] & 0xffu) != 0); - EXIT_NOT_IMPLEMENTED((buffer[5] & 0xffu) != 0); - } + // if (Config::IsNeo()) + // { + // EXIT_NOT_IMPLEMENTED((buffer[2] & 0xffu) != 0); + // EXIT_NOT_IMPLEMENTED((buffer[3] & 0xffu) != 0); + // EXIT_NOT_IMPLEMENTED((buffer[4] & 0xffu) != 0); + // EXIT_NOT_IMPLEMENTED((buffer[5] & 0xffu) != 0); + // } z.z_read_base_addr = static_cast(buffer[2]) << 8u; z.stencil_read_base_addr = static_cast(buffer[3]) << 8u; @@ -1479,6 +1517,65 @@ KYTY_HW_CTX_PARSER(hw_ctx_set_line_control) return 1; } +KYTY_HW_CTX_PARSER(hw_ctx_set_scan_mode_control) +{ + EXIT_NOT_IMPLEMENTED(cmd_id != 0xc0016900); + EXIT_NOT_IMPLEMENTED(cmd_offset != Pm4::PA_SC_MODE_CNTL_0); + + HW::ScanModeControl r; + + r.msaa_enable = KYTY_PM4_GET(buffer[0], PA_SC_MODE_CNTL_0, MSAA_ENABLE) != 0; + r.vport_scissor_enable = KYTY_PM4_GET(buffer[0], PA_SC_MODE_CNTL_0, VPORT_SCISSOR_ENABLE) != 0; + r.line_stipple_enable = KYTY_PM4_GET(buffer[0], PA_SC_MODE_CNTL_0, LINE_STIPPLE_ENABLE) != 0; + + cp->GetCtx()->SetScanModeControl(r); + + return 1; +} + +KYTY_HW_CTX_PARSER(hw_ctx_set_aa_config) +{ + EXIT_NOT_IMPLEMENTED(cmd_id != 0xc0016900); + EXIT_NOT_IMPLEMENTED(cmd_offset != Pm4::PA_SC_AA_CONFIG); + + HW::AaConfig r; + + r.msaa_num_samples = KYTY_PM4_GET(buffer[0], PA_SC_AA_CONFIG, MSAA_NUM_SAMPLES); + r.aa_mask_centroid_dtmn = KYTY_PM4_GET(buffer[0], PA_SC_AA_CONFIG, AA_MASK_CENTROID_DTMN) != 0; + r.max_sample_dist = KYTY_PM4_GET(buffer[0], PA_SC_AA_CONFIG, MAX_SAMPLE_DIST); + r.msaa_exposed_samples = KYTY_PM4_GET(buffer[0], PA_SC_AA_CONFIG, MSAA_EXPOSED_SAMPLES); + + cp->GetCtx()->SetAaConfig(r); + + return 1; +} + +KYTY_HW_CTX_PARSER(hw_ctx_set_aa_sample_control) +{ + EXIT_NOT_IMPLEMENTED(cmd_id != 0xc0106900); + EXIT_NOT_IMPLEMENTED(cmd_offset != Pm4::PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0); + + uint32_t count = 1; + + if (dw >= 20 && buffer[16] == 0xc0026900 && buffer[17] == Pm4::PA_SC_CENTROID_PRIORITY_0) + { + count = 20; + + HW::AaSampleControl r; + + memcpy(r.locations, buffer, 16 * 4); + + r.centroid_priority = static_cast(buffer[18]) | (static_cast(buffer[19]) << 32u); + + cp->GetCtx()->SetAaSampleControl(r); + } else + { + KYTY_NOT_IMPLEMENTED; + } + + return count; +} + KYTY_HW_CTX_PARSER(hw_ctx_set_depth_control) { EXIT_NOT_IMPLEMENTED(cmd_id != 0xC0016900); @@ -2478,11 +2575,12 @@ KYTY_CP_OP_PARSER(cp_op_acquire_mem) { case 0x02c40040: case 0x02c43fc0: + case 0x02c47fc0: { - // target_mask: 0x00000040 (rt0), 0x00003fc0 (all rt) + // target_mask: 0x00000040 (rt0), 0x00003fc0 (all rt), 0x00007fc0 (all rt and depth) // extended_action: 0x02000000 (FlushAndInvalidateCbCache) // action: 0x38 (WriteBackAndInvalidateL1andL2) - EXIT_IF(target_mask != 0x00000040 && target_mask != 0x00003FC0); + EXIT_IF(target_mask != 0x00000040 && target_mask != 0x00003FC0 && target_mask != 0x00007FC0); EXIT_IF(extended_action != 0x02000000); EXIT_IF(action != 0x38); EXIT_NOT_IMPLEMENTED(size_lo == 0); @@ -2624,6 +2722,11 @@ KYTY_CP_OP_PARSER(cp_op_marker) case 0x0: cp->SetEmbeddedDataMarker(buffer + 1, len_dw, align); break; case 0x4: cp->SetUserDataMarker(HW::UserSgprType::Vsharp); break; case 0xd: cp->SetUserDataMarker(HW::UserSgprType::Region); break; + case 0x777: + { + cp->Flip(); + break; + } case 0x778: { auto* addr = reinterpret_cast(buffer[1] | (static_cast(buffer[2]) << 32u)); @@ -2730,28 +2833,31 @@ static void graphics_init_jmp_tables() func = nullptr; } - g_hw_ctx_func[Pm4::DB_RENDER_CONTROL] = hw_ctx_set_render_control; - g_hw_ctx_func[Pm4::DB_STENCIL_CLEAR] = hw_ctx_set_stencil_clear; - g_hw_ctx_func[Pm4::DB_DEPTH_CLEAR] = hw_ctx_set_depth_clear; - g_hw_ctx_func[Pm4::PA_SC_SCREEN_SCISSOR_TL] = hw_ctx_set_screen_scissor; - g_hw_ctx_func[Pm4::DB_Z_INFO] = hw_ctx_set_depth_render_target; - g_hw_ctx_func[Pm4::DB_STENCIL_INFO] = hw_ctx_set_stencil_info; - g_hw_ctx_func[0x08d] = hw_ctx_hardware_screen_offset; - g_hw_ctx_func[0x08e] = hw_ctx_set_render_target_mask; - g_hw_ctx_func[Pm4::PA_SC_GENERIC_SCISSOR_TL] = hw_ctx_set_generic_scissor; - g_hw_ctx_func[Pm4::CB_BLEND_RED] = hw_ctx_set_blend_color; - g_hw_ctx_func[Pm4::DB_STENCIL_CONTROL] = hw_ctx_set_stencil_control; - g_hw_ctx_func[Pm4::DB_STENCILREFMASK] = hw_ctx_set_stencil_mask; - g_hw_ctx_func[Pm4::SPI_PS_INPUT_CNTL_0] = hw_ctx_set_ps_input; - g_hw_ctx_func[Pm4::DB_DEPTH_CONTROL] = hw_ctx_set_depth_control; - g_hw_ctx_func[Pm4::DB_EQAA] = hw_ctx_set_eqaa_control; - g_hw_ctx_func[Pm4::CB_COLOR_CONTROL] = hw_ctx_set_color_control; - g_hw_ctx_func[0x204] = hw_ctx_set_clip_control; - g_hw_ctx_func[Pm4::PA_SU_SC_MODE_CNTL] = hw_ctx_set_mode_control; - g_hw_ctx_func[0x206] = hw_ctx_set_viewport_transform_control; - g_hw_ctx_func[Pm4::PA_SU_LINE_CNTL] = hw_ctx_set_line_control; - g_hw_ctx_func[Pm4::VGT_SHADER_STAGES_EN] = hw_ctx_set_shader_stages; - g_hw_ctx_func[0x2fa] = hw_ctx_set_guard_bands; + g_hw_ctx_func[Pm4::DB_RENDER_CONTROL] = hw_ctx_set_render_control; + g_hw_ctx_func[Pm4::DB_STENCIL_CLEAR] = hw_ctx_set_stencil_clear; + g_hw_ctx_func[Pm4::DB_DEPTH_CLEAR] = hw_ctx_set_depth_clear; + g_hw_ctx_func[Pm4::PA_SC_SCREEN_SCISSOR_TL] = hw_ctx_set_screen_scissor; + g_hw_ctx_func[Pm4::DB_Z_INFO] = hw_ctx_set_depth_render_target; + g_hw_ctx_func[Pm4::DB_STENCIL_INFO] = hw_ctx_set_stencil_info; + g_hw_ctx_func[0x08d] = hw_ctx_hardware_screen_offset; + g_hw_ctx_func[0x08e] = hw_ctx_set_render_target_mask; + g_hw_ctx_func[Pm4::PA_SC_GENERIC_SCISSOR_TL] = hw_ctx_set_generic_scissor; + g_hw_ctx_func[Pm4::CB_BLEND_RED] = hw_ctx_set_blend_color; + g_hw_ctx_func[Pm4::DB_STENCIL_CONTROL] = hw_ctx_set_stencil_control; + g_hw_ctx_func[Pm4::DB_STENCILREFMASK] = hw_ctx_set_stencil_mask; + g_hw_ctx_func[Pm4::SPI_PS_INPUT_CNTL_0] = hw_ctx_set_ps_input; + g_hw_ctx_func[Pm4::DB_DEPTH_CONTROL] = hw_ctx_set_depth_control; + g_hw_ctx_func[Pm4::DB_EQAA] = hw_ctx_set_eqaa_control; + g_hw_ctx_func[Pm4::CB_COLOR_CONTROL] = hw_ctx_set_color_control; + g_hw_ctx_func[0x204] = hw_ctx_set_clip_control; + g_hw_ctx_func[Pm4::PA_SU_SC_MODE_CNTL] = hw_ctx_set_mode_control; + g_hw_ctx_func[0x206] = hw_ctx_set_viewport_transform_control; + g_hw_ctx_func[Pm4::PA_SU_LINE_CNTL] = hw_ctx_set_line_control; + g_hw_ctx_func[Pm4::PA_SC_MODE_CNTL_0] = hw_ctx_set_scan_mode_control; + g_hw_ctx_func[Pm4::PA_SC_AA_CONFIG] = hw_ctx_set_aa_config; + g_hw_ctx_func[Pm4::PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0] = hw_ctx_set_aa_sample_control; + g_hw_ctx_func[Pm4::VGT_SHADER_STAGES_EN] = hw_ctx_set_shader_stages; + g_hw_ctx_func[0x2fa] = hw_ctx_set_guard_bands; for (uint32_t slot = 0; slot < 8; slot++) { diff --git a/source/emulator/src/Graphics/Objects/DepthStencilBuffer.cpp b/source/emulator/src/Graphics/Objects/DepthStencilBuffer.cpp index 534cc0e..3694165 100644 --- a/source/emulator/src/Graphics/Objects/DepthStencilBuffer.cpp +++ b/source/emulator/src/Graphics/Objects/DepthStencilBuffer.cpp @@ -159,6 +159,12 @@ bool DepthStencilBufferObject::Equal(const uint64_t* other) const params[PARAM_HEIGHT] == other[PARAM_HEIGHT] && params[PARAM_HTILE] == other[PARAM_HTILE]); } +// bool DepthStencilBufferObject::Reuse(const uint64_t* other) const +//{ +// return (params[PARAM_FORMAT] == other[PARAM_FORMAT] && params[PARAM_WIDTH] <= other[PARAM_WIDTH] && +// params[PARAM_HEIGHT] <= other[PARAM_HEIGHT] && params[PARAM_HTILE] == other[PARAM_HTILE]); +//} + GpuObject::create_func_t DepthStencilBufferObject::GetCreateFunc() const { return create_func; diff --git a/source/emulator/src/Graphics/Objects/GpuMemory.cpp b/source/emulator/src/Graphics/Objects/GpuMemory.cpp index bb4fe5a..1000945 100644 --- a/source/emulator/src/Graphics/Objects/GpuMemory.cpp +++ b/source/emulator/src/Graphics/Objects/GpuMemory.cpp @@ -2,6 +2,7 @@ #include "Kyty/Core/Database.h" #include "Kyty/Core/DbgAssert.h" +#include "Kyty/Core/Hashmap.h" #include "Kyty/Core/MagicEnum.h" #include "Kyty/Core/String.h" #include "Kyty/Core/Threads.h" @@ -9,7 +10,6 @@ #include "Emulator/Graphics/GraphicContext.h" #include "Emulator/Profiler.h" -#include "Emulator/VirtualMemory.h" #include #include @@ -60,9 +60,6 @@ static OverlapType GetOverlapType(uint64_t vaddr_a, uint64_t size_a, uint64_t va uint64_t vaddr_last_a = vaddr_a + size_a - 1; uint64_t vaddr_last_b = vaddr_b + size_b - 1; - // auto addr_in_block = [](uint64_t block_addr, uint64_t block_size, uint64_t addr) - // { return addr >= block_addr && addr < block_addr + block_size; }; - bool a_b = addr_in_block(vaddr_a, size_a, vaddr_b); bool a_lb = addr_in_block(vaddr_a, size_a, vaddr_last_b); bool b_a = addr_in_block(vaddr_b, size_b, vaddr_a); @@ -86,52 +83,121 @@ static OverlapType GetOverlapType(uint64_t vaddr_a, uint64_t size_a, uint64_t va return OverlapType::None; } -class MemoryWatcher +class GpuMap1 { public: - MemoryWatcher() { EXIT_NOT_IMPLEMENTED(!Core::Thread::IsMainThread()); } - virtual ~MemoryWatcher() { KYTY_NOT_IMPLEMENTED; } - KYTY_CLASS_NO_COPY(MemoryWatcher); + GpuMap1() = default; + ~GpuMap1() = default; - using callback_func_t = void (*)(void*, void*); + KYTY_CLASS_NO_COPY(GpuMap1); - void Watch(const uint64_t* vaddr, const uint64_t* size, int vaddr_num, callback_func_t func, void* arg0, void* arg1); - void Stop(const uint64_t* vaddr, const uint64_t* size, int vaddr_num); - bool AlreadyWatch(const uint64_t* vaddr, const uint64_t* size, int vaddr_num); - bool Check(uint64_t vaddr, uint64_t size); - - static bool Enabled() + void Insert(uint64_t vaddr, int id) { - static const bool enabled = false; // !Core::dbg_is_debugger_present(); - return enabled; + auto& ids = m_map[vaddr]; + if (!ids.Contains(id)) + { + ids.Add(id); + } + } + + void Erase(uint64_t vaddr, int id) { m_map[vaddr].Remove(id); } + + [[nodiscard]] Vector FindAll(uint64_t vaddr) const { return m_map.Get(vaddr); } + +private: + Core::Hashmap> m_map; +}; + +class GpuMap2 +{ +public: + GpuMap2() = default; + ~GpuMap2() = default; + + KYTY_CLASS_NO_COPY(GpuMap2); + + void Insert(uint64_t vaddr, uint64_t size, int id) + { + EXIT_IF(size == 0); + auto first_page = CalcPageId(vaddr); + auto last_page = CalcPageId(vaddr + size - 1); + EXIT_IF(last_page < first_page); + for (auto page = first_page; page <= last_page; page++) + { + auto& ids = m_map[page]; + if (!ids.Contains(id)) + { + ids.Add(id); + } + } + } + + void Erase(uint64_t vaddr, uint64_t size, int id) + { + EXIT_IF(size == 0); + auto first_page = CalcPageId(vaddr); + auto last_page = CalcPageId(vaddr + size - 1); + EXIT_IF(last_page < first_page); + for (auto page = first_page; page <= last_page; page++) + { + m_map[page].Remove(id); + } + } + + [[nodiscard]] Vector FindAll(uint64_t vaddr, uint64_t size) const + { + Vector ret; + EXIT_IF(size == 0); + auto first_page = CalcPageId(vaddr); + auto last_page = CalcPageId(vaddr + size - 1); + EXIT_IF(last_page < first_page); + for (auto page = first_page; page <= last_page; page++) + { + for (int id: m_map.Get(page)) + { + if (!ret.Contains(id)) + { + ret.Add(id); + } + } + } + return ret; + } + + [[nodiscard]] Vector FindAll(const uint64_t* vaddr, const uint64_t* size, int vaddr_num) const + { + EXIT_IF(vaddr == nullptr); + EXIT_IF(size == nullptr); + Vector ret; + for (int i = 0; i < vaddr_num; i++) + { + EXIT_IF(size[i] == 0); + auto first_page = CalcPageId(vaddr[i]); + auto last_page = CalcPageId(vaddr[i] + size[i] - 1); + EXIT_IF(last_page < first_page); + for (auto page = first_page; page <= last_page; page++) + { + for (int id: m_map.Get(page)) + { + if (!ret.Contains(id)) + { + ret.Add(id); + } + } + } + } + return ret; } private: - static constexpr uint64_t PAGES_NUM = 0x400000; + static constexpr uint32_t PAGE_BITS = 14u; - struct Callback + static uint32_t CalcPageId(uint64_t vaddr) { - callback_func_t func = nullptr; - void* arg0 = nullptr; - void* arg1 = nullptr; - }; - - struct Block - { - bool used = false; - uint64_t vaddr[VADDR_BLOCKS_MAX] = {}; - uint64_t size[VADDR_BLOCKS_MAX] = {}; - uint64_t page_start[VADDR_BLOCKS_MAX] = {}; - uint64_t page_end[VADDR_BLOCKS_MAX] = {}; - int vaddr_num = 0; - Callback cb; - }; - - void Delete(Block* b); - - Core::Mutex m_mutex; - uint8_t m_pages[PAGES_NUM] = {}; - Vector m_blocks; + EXIT_IF((vaddr >> (PAGE_BITS + 32u)) != 0); + return static_cast(vaddr >> PAGE_BITS); + } + Core::Hashmap> m_map; }; class GpuMemory @@ -149,12 +215,13 @@ public: void SetAllocatedRange(uint64_t vaddr, uint64_t size); void Free(GraphicContext* ctx, uint64_t vaddr, uint64_t size, bool unmap); - void* CreateObject(GraphicContext* ctx, CommandBuffer* buffer, const uint64_t* vaddr, const uint64_t* size, int vaddr_num, - const GpuObject& info); + void* CreateObject(uint64_t submit_id, GraphicContext* ctx, CommandBuffer* buffer, const uint64_t* vaddr, const uint64_t* size, + int vaddr_num, const GpuObject& info); void ResetHash(GraphicContext* ctx, const uint64_t* vaddr, const uint64_t* size, int vaddr_num, GpuMemoryObjectType type); void FrameDone(); - Vector FindObjects(const uint64_t* vaddr, const uint64_t* size, int vaddr_num, bool exact, bool only_first); + Vector FindObjects(const uint64_t* vaddr, const uint64_t* size, int vaddr_num, GpuMemoryObjectType type, bool exact, + bool only_first); // Sync: GPU -> CPU void WriteBack(GraphicContext* ctx); @@ -182,6 +249,7 @@ private: uint64_t hash[VADDR_BLOCKS_MAX] = {}; uint64_t cpu_update_time = 0; uint64_t gpu_update_time = 0; + uint64_t submit_id = 0; GpuObject::write_back_func_t write_back_func = nullptr; GpuObject::delete_func_t delete_func = nullptr; GpuObject::update_func_t update_func = nullptr; @@ -211,25 +279,29 @@ private: Block block; ObjectInfo info; Vector others; - GpuMemoryScenario scenario = GpuMemoryScenario::Common; - bool free = true; + GpuMemoryScenario scenario = GpuMemoryScenario::Common; + bool free = true; + int next_free_id = -1; }; void Free(GraphicContext* ctx, int object_id); + Vector FindBlocks_slow(const uint64_t* vaddr, const uint64_t* size, int vaddr_num, bool only_first = false); Vector FindBlocks(const uint64_t* vaddr, const uint64_t* size, int vaddr_num, bool only_first = false); - Block CreateBlock(const uint64_t* vaddr, const uint64_t* size, int vaddr_num); - void DeleteBlock(Block* b); - void Link(int id1, int id2, OverlapType rel, GpuMemoryScenario scenario); + bool FindFast(const uint64_t* vaddr, const uint64_t* size, int vaddr_num, GpuMemoryObjectType type, bool only_first, int* id); + Block CreateBlock(const uint64_t* vaddr, const uint64_t* size, int vaddr_num, int obj_id); + void DeleteBlock(Block* b, int obj_id); + void Link(int id1, int id2, OverlapType rel, GpuMemoryScenario scenario); // Update (CPU -> GPU) - void Update(GraphicContext* ctx, int obj_id); + void Update(uint64_t submit_id, GraphicContext* ctx, int obj_id); static void WatchCallback(void* a0, void* a1); bool create_existing(const Vector& others, const GpuObject& info, int* id); bool create_generate_mips(const Vector& others, GpuMemoryObjectType type); bool create_texture_triplet(const Vector& others, GpuMemoryObjectType type); + bool create_maybe_deleted(const Vector& others, GpuMemoryObjectType type); bool create_all_the_same(const Vector& others); void create_dbg_exit(const uint64_t* vaddr, const uint64_t* size, int vaddr_num, const Vector& others, GpuMemoryObjectType type); @@ -240,6 +312,10 @@ private: Vector m_objects; uint64_t m_objects_size = 0; uint64_t m_current_frame = 0; + int m_first_free_id = -1; + + GpuMap1 m_objects_map1; + GpuMap2 m_objects_map2; Core::Database::Connection m_db; Core::Database::Statement* m_db_add_range = nullptr; @@ -285,289 +361,8 @@ private: Vector m_infos; }; -static GpuMemory* g_gpu_memory = nullptr; -static GpuResources* g_gpu_resources = nullptr; -static MemoryWatcher* g_gpu_memory_watcher = nullptr; - -void MemoryWatcher::Watch(const uint64_t* vaddr, const uint64_t* size, int vaddr_num, callback_func_t func, void* arg0, void* arg1) -{ - KYTY_PROFILER_BLOCK("MemoryWatcher::Watch"); - - if (!Enabled()) - { - return; - } - - Core::LockGuard lock(m_mutex); - - if (AlreadyWatch(vaddr, size, vaddr_num)) - { - return; - } - - Stop(vaddr, size, vaddr_num); - - EXIT_IF(func == nullptr); - - Block nb; - nb.used = true; - nb.cb.func = func; - nb.cb.arg0 = arg0; - nb.cb.arg1 = arg1; - nb.vaddr_num = vaddr_num; - for (int i = 0; i < vaddr_num; i++) - { - EXIT_IF(size[i] == 0); - nb.vaddr[i] = vaddr[i]; - nb.size[i] = size[i]; - nb.page_start[i] = vaddr[i] >> 12u; - nb.page_end[i] = (vaddr[i] + size[i] - 1) >> 12u; - - EXIT_IF(nb.page_end[i] < nb.page_start[i]); - - struct Region - { - uint64_t start = 0; - uint64_t count = 0; - }; - - Vector rs; - - Region r; - - for (uint64_t page = nb.page_start[i]; page <= nb.page_end[i]; page++) - { - EXIT_NOT_IMPLEMENTED(page >= PAGES_NUM); - EXIT_NOT_IMPLEMENTED(m_pages[page] == 0xff); - - if (m_pages[page] == 0) - { - if (r.count == 0) - { - r.start = page; - } - r.count++; - } else - { - if (r.count > 0) - { - rs.Add(r); - r.count = 0; - } - } - - m_pages[page]++; - } - - if (r.count > 0) - { - rs.Add(r); - } - - for (const auto& r: rs) - { - Kyty::Loader::VirtualMemory::Mode old_mode = Kyty::Loader::VirtualMemory::Mode::NoAccess; - - // printf("protect %016" PRIx64 "\n", page << 12u); - - Kyty::Loader::VirtualMemory::Protect(r.start << 12u, r.count * 0x1000, Kyty::Loader::VirtualMemory::Mode::Read, &old_mode); - - EXIT_NOT_IMPLEMENTED(old_mode != Kyty::Loader::VirtualMemory::Mode::ReadWrite); - } - } - - for (auto& b: m_blocks) - { - if (!b.used) - { - b = nb; - return; - } - } - - m_blocks.Add(nb); -} - -void MemoryWatcher::Delete(Block* b) -{ - KYTY_PROFILER_BLOCK("MemoryWatcher::Delete"); - - EXIT_IF(!b->used); - - b->used = false; - - for (int i = 0; i < b->vaddr_num; i++) - { - struct Region - { - uint64_t start = 0; - uint64_t count = 0; - }; - - Vector rs; - - Region r; - - for (uint64_t page = b->page_start[i]; page <= b->page_end[i]; page++) - { - EXIT_NOT_IMPLEMENTED(m_pages[page] == 0); - - m_pages[page]--; - - if (m_pages[page] == 0) - { - if (r.count == 0) - { - r.start = page; - } - r.count++; - } else - { - if (r.count > 0) - { - rs.Add(r); - r.count = 0; - } - } - } - - if (r.count > 0) - { - rs.Add(r); - } - - for (const auto& r: rs) - { - Kyty::Loader::VirtualMemory::Mode old_mode = Kyty::Loader::VirtualMemory::Mode::NoAccess; - - // printf("unprotect %016" PRIx64 "\n", page << 12u); - - Kyty::Loader::VirtualMemory::Protect(r.start << 12u, r.count * 0x1000, Kyty::Loader::VirtualMemory::Mode::ReadWrite, &old_mode); - - EXIT_NOT_IMPLEMENTED(old_mode != Kyty::Loader::VirtualMemory::Mode::Read); - } - } -} - -void MemoryWatcher::Stop(const uint64_t* vaddr, const uint64_t* size, int vaddr_num) -{ - KYTY_PROFILER_BLOCK("MemoryWatcher::Stop"); - - if (!Enabled()) - { - return; - } - - Core::LockGuard lock(m_mutex); - - for (auto& b: m_blocks) - { - if (b.used && b.vaddr_num == vaddr_num) - { - bool equal = true; - for (int i = 0; i < vaddr_num; i++) - { - if (GetOverlapType(b.vaddr[i], b.size[i], vaddr[i], size[i]) != OverlapType::Equals) - { - equal = false; - break; - } - } - if (equal) - { - Delete(&b); - } - } - } -} - -bool MemoryWatcher::AlreadyWatch(const uint64_t* vaddr, const uint64_t* size, int vaddr_num) -{ - KYTY_PROFILER_BLOCK("MemoryWatcher::AlreadyWatch"); - - if (!Enabled()) - { - return false; - } - - Core::LockGuard lock(m_mutex); - - for (auto& b: m_blocks) - { - if (b.used && b.vaddr_num == vaddr_num) - { - bool equal = true; - for (int i = 0; i < vaddr_num; i++) - { - if (GetOverlapType(b.vaddr[i], b.size[i], vaddr[i], size[i]) != OverlapType::Equals) - { - equal = false; - break; - } - } - if (equal) - { - return true; - } - } - } - - return false; -} - -bool MemoryWatcher::Check(uint64_t vaddr, uint64_t size) -{ - if (!Enabled()) - { - return false; - } - - // printf("check begin\n"); - // - // Core::DebugStack s; - // Core::DebugStack::Trace(&s); - // s.Print(0); - - m_mutex.Lock(); - - uint64_t page_start = vaddr >> 12u; - uint64_t page_end = (vaddr + size - 1) >> 12u; - - Vector cbs; - - for (uint64_t page = page_start; page <= page_end; page++) - { - if (page < PAGES_NUM) - { - for (auto& b: m_blocks) - { - if (b.used) - { - for (int i = 0; i < b.vaddr_num; i++) - { - if (b.page_start[i] <= page && b.page_end[i] >= page) - { - cbs.Add(b.cb); - Delete(&b); - break; - } - } - } - } - } - } - - m_mutex.Unlock(); - - for (const auto& cb: cbs) - { - cb.func(cb.arg0, cb.arg1); - } - - // printf("check end\n"); - - return !cbs.IsEmpty(); -} +static GpuMemory* g_gpu_memory = nullptr; +static GpuResources* g_gpu_resources = nullptr; uint32_t GpuResources::AddOwner(const String& name) { @@ -755,7 +550,7 @@ void GpuMemory::Link(int id1, int id2, OverlapType rel, GpuMemoryScenario scenar h2.scenario = scenario; } -void GpuMemory::Update(GraphicContext* ctx, int obj_id) +void GpuMemory::Update(uint64_t submit_id, GraphicContext* ctx, int obj_id) { KYTY_PROFILER_BLOCK("GpuMemory::Update"); @@ -763,9 +558,9 @@ void GpuMemory::Update(GraphicContext* ctx, int obj_id) auto& o = h.info; bool need_update = false; - bool mem_watch = MemoryWatcher::Enabled(); + bool mem_watch = false; - if ((mem_watch && o.cpu_update_time > o.gpu_update_time) || !mem_watch) + if ((mem_watch && o.cpu_update_time > o.gpu_update_time) || (!mem_watch && submit_id > o.submit_id)) { uint64_t hash[VADDR_BLOCKS_MAX] = {}; @@ -792,6 +587,8 @@ void GpuMemory::Update(GraphicContext* ctx, int obj_id) o.hash[vi] = hash[vi]; } } + + o.submit_id = submit_id; } if (need_update) @@ -800,9 +597,6 @@ void GpuMemory::Update(GraphicContext* ctx, int obj_id) o.update_func(ctx, o.params, o.object.obj, h.block.vaddr, h.block.size, h.block.vaddr_num); o.gpu_update_time = get_current_time(); } - - g_gpu_memory_watcher->Watch(h.block.vaddr, h.block.size, h.block.vaddr_num, WatchCallback, this, - reinterpret_cast(static_cast(obj_id))); } void GpuMemory::WatchCallback(void* a0, void* a1) @@ -831,6 +625,7 @@ bool GpuMemory::create_existing(const Vector& others, const Gpu auto& h = m_objects[obj.object_id]; EXIT_IF(h.free); auto& o = h.info; + if (h.scenario == GpuMemoryScenario::Common && obj.relation == OverlapType::Equals && o.object.type == info.type && info.Equal(o.params)) { @@ -838,6 +633,13 @@ bool GpuMemory::create_existing(const Vector& others, const Gpu return true; } + // if (h.scenario == GpuMemoryScenario::Common && obj.relation == OverlapType::Contains && o.object.type == info.type && + // info.Reuse(o.params)) + // { + // *id = obj.object_id; + // return true; + // } + if (o.gpu_update_time > max_gpu_update_time) { max_gpu_update_time = o.gpu_update_time; @@ -941,6 +743,23 @@ bool GpuMemory::create_texture_triplet(const Vector& others, Gp return false; } +bool GpuMemory::create_maybe_deleted(const Vector& others, GpuMemoryObjectType type) +{ + if (type == GpuMemoryObjectType::IndexBuffer) + { + return std::all_of(others.begin(), others.end(), + [this](auto& r) + { + OverlapType rel = r.relation; + const auto& o = m_objects[r.object_id]; + GpuMemoryObjectType o_type = o.info.object.type; + return ((rel == OverlapType::IsContainedWithin || rel == OverlapType::Crosses) && + o_type == GpuMemoryObjectType::IndexBuffer); + }); + } + return false; +} + bool GpuMemory::create_all_the_same(const Vector& others) { OverlapType rel = others.At(0).relation; @@ -971,8 +790,8 @@ void GpuMemory::create_dbg_exit(const uint64_t* vaddr, const uint64_t* size, int } // NOLINTNEXTLINE(readability-function-cognitive-complexity) -void* GpuMemory::CreateObject(GraphicContext* ctx, CommandBuffer* buffer, const uint64_t* vaddr, const uint64_t* size, int vaddr_num, - const GpuObject& info) +void* GpuMemory::CreateObject(uint64_t submit_id, GraphicContext* ctx, CommandBuffer* buffer, const uint64_t* vaddr, const uint64_t* size, + int vaddr_num, const GpuObject& info) { KYTY_PROFILER_BLOCK("GpuMemory::CreateObject", profiler::colors::Green300); @@ -987,6 +806,27 @@ void* GpuMemory::CreateObject(GraphicContext* ctx, CommandBuffer* buffer, const GpuMemoryScenario scenario = GpuMemoryScenario::Common; + int fast_id = -1; + if (FindFast(vaddr, size, vaddr_num, info.type, false, &fast_id)) + { + auto& h = m_objects[fast_id]; + EXIT_IF(h.free); + auto& o = h.info; + + if (h.scenario == GpuMemoryScenario::Common && info.Equal(o.params)) + { + Update(submit_id, ctx, fast_id); + + o.use_num++; + o.use_last_frame = m_current_frame; + o.in_use = true; + o.read_only = info.read_only; + o.check_hash = info.check_hash; + + return o.object.obj; + } + } + auto others = FindBlocks(vaddr, size, vaddr_num); if (!others.IsEmpty()) @@ -998,7 +838,7 @@ void* GpuMemory::CreateObject(GraphicContext* ctx, CommandBuffer* buffer, const EXIT_IF(h.free); auto& o = h.info; - Update(ctx, existing_id); + Update(submit_id, ctx, existing_id); o.use_num++; o.use_last_frame = m_current_frame; @@ -1028,6 +868,11 @@ void* GpuMemory::CreateObject(GraphicContext* ctx, CommandBuffer* buffer, const } case ObjectsRelation(GpuMemoryObjectType::StorageBuffer, OverlapType::Contains, GpuMemoryObjectType::Label): case ObjectsRelation(GpuMemoryObjectType::Label, OverlapType::Equals, GpuMemoryObjectType::Label): + case ObjectsRelation(GpuMemoryObjectType::DepthStencilBuffer, OverlapType::Contains, + GpuMemoryObjectType::DepthStencilBuffer): + case ObjectsRelation(GpuMemoryObjectType::IndexBuffer, OverlapType::Crosses, GpuMemoryObjectType::IndexBuffer): + case ObjectsRelation(GpuMemoryObjectType::IndexBuffer, OverlapType::Contains, GpuMemoryObjectType::IndexBuffer): + case ObjectsRelation(GpuMemoryObjectType::IndexBuffer, OverlapType::IsContainedWithin, GpuMemoryObjectType::IndexBuffer): { delete_all = true; break; @@ -1054,6 +899,9 @@ void* GpuMemory::CreateObject(GraphicContext* ctx, CommandBuffer* buffer, const { overlap = true; scenario = GpuMemoryScenario::TextureTriplet; + } else if (create_maybe_deleted(others, info.type)) + { + delete_all = true; } else { if (!create_all_the_same(others)) @@ -1126,6 +974,7 @@ void* GpuMemory::CreateObject(GraphicContext* ctx, CommandBuffer* buffer, const } o.cpu_update_time = get_current_time(); o.gpu_update_time = o.cpu_update_time; + o.submit_id = submit_id; if (create_from_objects) { @@ -1152,28 +1001,24 @@ void* GpuMemory::CreateObject(GraphicContext* ctx, CommandBuffer* buffer, const o.read_only = info.read_only; o.check_hash = info.check_hash; - bool updated = false; - int index = 0; - for (auto& u: m_objects) - { - if (u.free) - { - u.free = false; - u.block = CreateBlock(vaddr, size, vaddr_num); - u.info = o; - u.others.Clear(); - u.scenario = scenario; - updated = true; - break; - } - index++; - } - if (!updated) + if (m_first_free_id != -1) { + index = m_first_free_id; + auto& u = m_objects[m_first_free_id]; + m_first_free_id = u.next_free_id; + u.free = false; + u.block = CreateBlock(vaddr, size, vaddr_num, index); + u.info = o; + u.others.Clear(); + u.scenario = scenario; + } else + { + index = static_cast(m_objects.Size()); + Object h {}; - h.block = CreateBlock(vaddr, size, vaddr_num); + h.block = CreateBlock(vaddr, size, vaddr_num, index); h.info = o; h.others.Clear(); h.scenario = scenario; @@ -1192,7 +1037,8 @@ void* GpuMemory::CreateObject(GraphicContext* ctx, CommandBuffer* buffer, const return o.object.obj; } -Vector GpuMemory::FindObjects(const uint64_t* vaddr, const uint64_t* size, int vaddr_num, bool exact, bool only_first) +Vector GpuMemory::FindObjects(const uint64_t* vaddr, const uint64_t* size, int vaddr_num, GpuMemoryObjectType type, + bool exact, bool only_first) { KYTY_PROFILER_BLOCK("GpuMemory::FindObjects", profiler::colors::Green200); @@ -1200,23 +1046,28 @@ Vector GpuMemory::FindObjects(const uint64_t* vaddr, const uint Core::LockGuard lock(m_mutex); - auto objects = FindBlocks(vaddr, size, vaddr_num, only_first); - Vector ret; - // printf("GpuMemory::FindObjects()\n"); + if (exact) + { + int fast_id = -1; + if (FindFast(vaddr, size, vaddr_num, type, only_first, &fast_id)) + { + const auto& h = m_objects[fast_id]; + EXIT_IF(h.free); + ret.Add(h.info.object); + } + return ret; + } - // for (int i = 0; i < vaddr_num; i++) - // { - // printf("\t vaddr = %016" PRIx64 ", size = %016" PRIx64 "\n", vaddr[i], size[i]); - // } + auto objects = FindBlocks(vaddr, size, vaddr_num, only_first); for (const auto& obj: objects) { const auto& h = m_objects[obj.object_id]; EXIT_IF(h.free); - // printf("\t %s, %d, %s\n", Core::EnumName(obj.relation).C_Str(), obj.object_id, Core::EnumName(h.info.object.type).C_Str()); - if (obj.relation == OverlapType::Equals || (!exact && obj.relation == OverlapType::IsContainedWithin)) + if (h.info.object.type == type && + (obj.relation == OverlapType::Equals || (!exact && obj.relation == OverlapType::IsContainedWithin))) { ret.Add(h.info.object); } @@ -1234,6 +1085,27 @@ void GpuMemory::ResetHash(GraphicContext* /*ctx*/, const uint64_t* vaddr, const uint64_t new_hash = 0; + int fast_id = -1; + if (FindFast(vaddr, size, vaddr_num, type, false, &fast_id)) + { + auto& h = m_objects[fast_id]; + EXIT_IF(h.free); + auto& o = h.info; + + if (h.scenario == GpuMemoryScenario::Common) + { + for (int vi = 0; vi < vaddr_num; vi++) + { + printf("ResetHash: type = %s, vaddr = 0x%016" PRIx64 ", size = 0x%016" PRIx64 ", old_hash = 0x%016" PRIx64 + ", new_hash = 0x%016" PRIx64 "\n", + Core::EnumName(o.object.type).C_Str(), vaddr[vi], size[vi], o.hash[vi], new_hash); + } + o.gpu_update_time = get_current_time(); + + return; + } + } + auto object_ids = FindBlocks(vaddr, size, vaddr_num); if (!object_ids.IsEmpty()) @@ -1253,12 +1125,8 @@ void GpuMemory::ResetHash(GraphicContext* /*ctx*/, const uint64_t* vaddr, const printf("ResetHash: type = %s, vaddr = 0x%016" PRIx64 ", size = 0x%016" PRIx64 ", old_hash = 0x%016" PRIx64 ", new_hash = 0x%016" PRIx64 "\n", Core::EnumName(o.object.type).C_Str(), vaddr[vi], size[vi], o.hash[vi], new_hash); - - o.hash[vi] = new_hash; } o.gpu_update_time = get_current_time(); - g_gpu_memory_watcher->Watch(vaddr, size, vaddr_num, WatchCallback, this, - reinterpret_cast(static_cast(obj.object_id))); } } } @@ -1266,6 +1134,8 @@ void GpuMemory::ResetHash(GraphicContext* /*ctx*/, const uint64_t* vaddr, const void GpuMemory::Free(GraphicContext* ctx, uint64_t vaddr, uint64_t size, bool unmap) { + KYTY_PROFILER_BLOCK("GpuMemory::Free", profiler::colors::Green300); + Core::LockGuard lock(m_mutex); printf("Release gpu objects:\n"); @@ -1322,13 +1192,58 @@ void GpuMemory::Free(GraphicContext* ctx, int object_id) } o.delete_func(ctx, o.object.obj, &o.mem); } - g_gpu_memory_watcher->Stop(block.vaddr, block.size, block.vaddr_num); - h.free = true; - DeleteBlock(&h.block); + h.free = true; + h.next_free_id = m_first_free_id; + m_first_free_id = object_id; + DeleteBlock(&h.block, object_id); +} + +bool GpuMemory::FindFast(const uint64_t* vaddr, const uint64_t* size, int vaddr_num, GpuMemoryObjectType type, bool only_first, int* id) +{ + KYTY_PROFILER_BLOCK("GpuMemory::FindFast", profiler::colors::Green200); + + EXIT_IF(id == nullptr); + + for (int vi = 0; vi < vaddr_num; vi++) + { + for (int obj_id: m_objects_map1.FindAll(vaddr[vi])) + { + auto& b = m_objects[obj_id]; + EXIT_IF(b.free); + if (b.info.object.type == type) + { + bool equal = true; + if (b.block.vaddr_num == 1 || only_first) + { + if (GetOverlapType(b.block.vaddr[0], b.block.size[0], vaddr[0], size[0]) != OverlapType::Equals) + { + equal = false; + } + } else + { + for (int i = 0; i < vaddr_num; i++) + { + if (GetOverlapType(b.block.vaddr[i], b.block.size[i], vaddr[i], size[i]) != OverlapType::Equals) + { + equal = false; + break; + } + } + } + if (equal) + { + *id = obj_id; + return true; + } + } + } + } + + return false; } // NOLINTNEXTLINE(readability-function-cognitive-complexity) -Vector GpuMemory::FindBlocks(const uint64_t* vaddr, const uint64_t* size, int vaddr_num, bool only_first) +Vector GpuMemory::FindBlocks_slow(const uint64_t* vaddr, const uint64_t* size, int vaddr_num, bool only_first) { KYTY_PROFILER_BLOCK("GpuMemory::FindBlocks", profiler::colors::Green100); @@ -1338,6 +1253,8 @@ Vector GpuMemory::FindBlocks(const uint64_t* vaddr, Vector ret; + // TODO(): implement interval-tree + if (vaddr_num != 1) { int index = 0; @@ -1412,10 +1329,136 @@ Vector GpuMemory::FindBlocks(const uint64_t* vaddr, index++; } } + + // printf("FindBlocks:\n"); + // for (int vi = 0; vi < vaddr_num; vi++) + // { + // printf("\t vaddr = 0x%016" PRIx64 ", size = 0x%016" PRIx64 "\n", vaddr[vi], size[vi]); + // } + // for (const auto& d: ret) + // { + // printf("\t id = %d, rel = %s\n", d.object_id, Core::EnumName(d.relation).C_Str()); + // const auto& b = m_objects[d.object_id]; + // for (int vi = 0; vi < b.block.vaddr_num; vi++) + // { + // printf("\t\t vaddr = 0x%016" PRIx64 ", size = 0x%016" PRIx64 "\n", b.block.vaddr[vi], b.block.size[vi]); + // } + // } + return ret; } -GpuMemory::Block GpuMemory::CreateBlock(const uint64_t* vaddr, const uint64_t* size, int vaddr_num) +// NOLINTNEXTLINE(readability-function-cognitive-complexity) +Vector GpuMemory::FindBlocks(const uint64_t* vaddr, const uint64_t* size, int vaddr_num, bool only_first) +{ + KYTY_PROFILER_BLOCK("GpuMemory::FindBlocks", profiler::colors::Green100); + + EXIT_IF(vaddr_num <= 0 || vaddr_num > VADDR_BLOCKS_MAX); + EXIT_IF(vaddr == nullptr || size == nullptr); + EXIT_IF(only_first && vaddr_num != 1); + + Vector ret; + + // TODO(): implement interval-tree + + if (vaddr_num != 1) + { + for (int index: m_objects_map2.FindAll(vaddr, size, vaddr_num)) + { + const auto& b = m_objects[index]; + if (!b.free) + { + bool equal = true; + for (int i = 0; i < vaddr_num; i++) + { + if (GetOverlapType(b.block.vaddr[i], b.block.size[i], vaddr[i], size[i]) != OverlapType::Equals) + { + equal = false; + break; + } + } + if (equal) + { + ret.Add({OverlapType::Equals, index}); + } else + { + bool cross = false; + for (int i = 0; i < vaddr_num; i++) + { + for (int j = 0; j < b.block.vaddr_num; j++) + { + if (GetOverlapType(b.block.vaddr[j], b.block.size[j], vaddr[i], size[i]) != OverlapType::None) + { + cross = true; + break; + } + } + if (cross) + { + break; + } + } + if (cross) + { + ret.Add({OverlapType::Crosses, index}); + } + } + } + } + } else + { + for (int index: m_objects_map2.FindAll(vaddr[0], size[0])) + { + const auto& b = m_objects[index]; + if (!b.free) + { + if (b.block.vaddr_num == 1 || only_first) + { + auto type = GetOverlapType(b.block.vaddr[0], b.block.size[0], vaddr[0], size[0]); + if (type != OverlapType::None) + { + ret.Add({type, index}); + } + } else + { + for (int i = 0; i < b.block.vaddr_num; i++) + { + if (GetOverlapType(b.block.vaddr[i], b.block.size[i], vaddr[0], size[0]) != OverlapType::None) + { + ret.Add({OverlapType::Crosses, index}); + break; + } + } + } + } + } + } + + { + KYTY_PROFILER_BLOCK("sort"); + ret.Sort([](auto& b1, auto& b2) { return b1.object_id < b2.object_id; }); + } + + // + // printf("FindBlocks:\n"); + // for (int vi = 0; vi < vaddr_num; vi++) + // { + // printf("\t vaddr = 0x%016" PRIx64 ", size = 0x%016" PRIx64 "\n", vaddr[vi], size[vi]); + // } + // for (const auto& d: ret) + // { + // printf("\t id = %d, rel = %s\n", d.object_id, Core::EnumName(d.relation).C_Str()); + // const auto& b = m_objects[d.object_id]; + // for (int vi = 0; vi < b.block.vaddr_num; vi++) + // { + // printf("\t\t vaddr = 0x%016" PRIx64 ", size = 0x%016" PRIx64 "\n", b.block.vaddr[vi], b.block.size[vi]); + // } + // } + + return ret; +} + +GpuMemory::Block GpuMemory::CreateBlock(const uint64_t* vaddr, const uint64_t* size, int vaddr_num, int obj_id) { EXIT_IF(vaddr_num > VADDR_BLOCKS_MAX); EXIT_IF(vaddr == nullptr || size == nullptr); @@ -1427,15 +1470,19 @@ GpuMemory::Block GpuMemory::CreateBlock(const uint64_t* vaddr, const uint64_t* s nb.vaddr[vi] = vaddr[vi]; nb.size[vi] = size[vi]; m_objects_size += size[vi]; + m_objects_map1.Insert(vaddr[vi], obj_id); + m_objects_map2.Insert(vaddr[vi], size[vi], obj_id); } return nb; } -void GpuMemory::DeleteBlock(Block* b) +void GpuMemory::DeleteBlock(Block* b, int obj_id) { for (int vi = 0; vi < b->vaddr_num; vi++) { m_objects_size -= b->size[vi]; + m_objects_map1.Erase(b->vaddr[vi], obj_id); + m_objects_map2.Erase(b->vaddr[vi], b->size[vi], obj_id); } } @@ -1462,7 +1509,6 @@ void GpuMemory::WriteBack(GraphicContext* ctx) auto& block = h.block; // EXIT_IF(block.free); - g_gpu_memory_watcher->Stop(block.vaddr, block.size, block.vaddr_num); o.write_back_func(ctx, o.object.obj, block.vaddr, block.size, block.vaddr_num); o.cpu_update_time = get_current_time(); @@ -1474,8 +1520,12 @@ void GpuMemory::WriteBack(GraphicContext* ctx) auto& o2 = m_objects[h.others.At(0).object_id].info; o2.cpu_update_time = o.cpu_update_time; - - Update(ctx, h.others.At(0).object_id); + o2.submit_id = 0; + for (int vi = 0; vi < block.vaddr_num; vi++) + { + o2.hash[vi] = 0; + } + Update(o.submit_id, ctx, h.others.At(0).object_id); for (int vi = 0; vi < block.vaddr_num; vi++) { @@ -1528,8 +1578,6 @@ void GpuMemory::Flush(GraphicContext* ctx) EXIT_IF(o.update_func == nullptr); o.update_func(ctx, o.params, o.object.obj, block.vaddr, block.size, block.vaddr_num); o.gpu_update_time = get_current_time(); - g_gpu_memory_watcher->Watch(block.vaddr, block.size, block.vaddr_num, WatchCallback, this, - reinterpret_cast(static_cast(index))); } index++; } @@ -1568,7 +1616,8 @@ CREATE TABLE [objects]( [hash2] TEXT, [hash3] TEXT, [gpu_update_time] INT64, - [cpu_update_time] INT64, + [cpu_update_time] INT64, + [submit_id] INT64, [write_back_func] TEXT, [delete_func] TEXT, [update_func] TEXT, @@ -1596,14 +1645,16 @@ CREATE TABLE [ranges]( m_db_add_object = m_db.Prepare( "insert into objects(dump_id, id, vaddr, vaddr2, vaddr3, size, size2, size3, obj, param0, param1, param2, param3, param4, " "param5, param6, param7, type, hash, hash2, " - "hash3, gpu_update_time, cpu_update_time, scenario, others, write_back_func, delete_func, update_func, use_last_frame, " + "hash3, gpu_update_time, cpu_update_time, submit_id, scenario, others, write_back_func, delete_func, update_func, " + "use_last_frame, " "use_num, in_use, read_only, " "check_hash, vk_mem_size, " "vk_mem_alignment, vk_mem_memoryTypeBits, vk_mem_property, vk_mem_memory, vk_mem_offset, vk_mem_type, vk_mem_unique_id) " "values(:dump_id, :id, :vaddr, :vaddr2, :vaddr3, :size, :size2, :size3, :obj, :param0, :param1, :param2, :param3, :param4, " ":param5, " ":param6, :param7, :type, :hash, " - ":hash2, :hash3, :gpu_update_time, :cpu_update_time, :scenario, :others, :write_back_func, :delete_func, :update_func, " + ":hash2, :hash3, :gpu_update_time, :cpu_update_time, :submit_id, :scenario, :others, :write_back_func, :delete_func, " + ":update_func, " ":use_last_frame, :use_num, :in_use, " ":read_only, :check_hash, " ":vk_mem_size, :vk_mem_alignment, :vk_mem_memoryTypeBits, :vk_mem_property, :vk_mem_memory, :vk_mem_offset, :vk_mem_type, " @@ -1689,6 +1740,7 @@ void GpuMemory::DbgDbDump() m_db_add_object->BindString(":scenario", Core::EnumName(r.scenario).C_Str()); m_db_add_object->BindInt64(":gpu_update_time", static_cast(r.info.gpu_update_time)); m_db_add_object->BindInt64(":cpu_update_time", static_cast(r.info.cpu_update_time)); + m_db_add_object->BindInt64(":submit_id", static_cast(r.info.submit_id)); if (r.others.Size() > 0) { @@ -1737,11 +1789,9 @@ void GpuMemoryInit() { EXIT_IF(g_gpu_memory != nullptr); EXIT_IF(g_gpu_resources != nullptr); - EXIT_IF(g_gpu_memory_watcher != nullptr); - g_gpu_memory = new GpuMemory; - g_gpu_resources = new GpuResources; - g_gpu_memory_watcher = new MemoryWatcher; + g_gpu_memory = new GpuMemory; + g_gpu_resources = new GpuResources; } void GpuMemorySetAllocatedRange(uint64_t vaddr, uint64_t size) @@ -1759,28 +1809,29 @@ void GpuMemoryFree(GraphicContext* ctx, uint64_t vaddr, uint64_t size, bool unma g_gpu_memory->Free(ctx, vaddr, size, unmap); } -void* GpuMemoryCreateObject(GraphicContext* ctx, CommandBuffer* buffer, uint64_t vaddr, uint64_t size, const GpuObject& info) -{ - EXIT_IF(g_gpu_memory == nullptr); - EXIT_IF(ctx == nullptr); - - return g_gpu_memory->CreateObject(ctx, buffer, &vaddr, &size, 1, info); -} - -void* GpuMemoryCreateObject(GraphicContext* ctx, CommandBuffer* buffer, const uint64_t* vaddr, const uint64_t* size, int vaddr_num, +void* GpuMemoryCreateObject(uint64_t submit_id, GraphicContext* ctx, CommandBuffer* buffer, uint64_t vaddr, uint64_t size, const GpuObject& info) { EXIT_IF(g_gpu_memory == nullptr); EXIT_IF(ctx == nullptr); - return g_gpu_memory->CreateObject(ctx, buffer, vaddr, size, vaddr_num, info); + return g_gpu_memory->CreateObject(submit_id, ctx, buffer, &vaddr, &size, 1, info); } -Vector GpuMemoryFindObjects(uint64_t vaddr, uint64_t size, bool exact, bool only_first) +void* GpuMemoryCreateObject(uint64_t submit_id, GraphicContext* ctx, CommandBuffer* buffer, const uint64_t* vaddr, const uint64_t* size, + int vaddr_num, const GpuObject& info) +{ + EXIT_IF(g_gpu_memory == nullptr); + EXIT_IF(ctx == nullptr); + + return g_gpu_memory->CreateObject(submit_id, ctx, buffer, vaddr, size, vaddr_num, info); +} + +Vector GpuMemoryFindObjects(uint64_t vaddr, uint64_t size, GpuMemoryObjectType type, bool exact, bool only_first) { EXIT_IF(g_gpu_memory == nullptr); - return g_gpu_memory->FindObjects(&vaddr, &size, 1, exact, only_first); + return g_gpu_memory->FindObjects(&vaddr, &size, 1, type, exact, only_first); } void GpuMemoryResetHash(GraphicContext* ctx, const uint64_t* vaddr, const uint64_t* size, int vaddr_num, GpuMemoryObjectType type) @@ -1824,20 +1875,20 @@ void GpuMemoryWriteBack(GraphicContext* ctx) g_gpu_memory->WriteBack(ctx); } -bool GpuMemoryCheckAccessViolation(uint64_t vaddr, uint64_t size) +bool GpuMemoryCheckAccessViolation(uint64_t /*vaddr*/, uint64_t /*size*/) { - EXIT_IF(g_gpu_memory_watcher == nullptr); - - return g_gpu_memory_watcher->Check(vaddr, size); + return false; } bool GpuMemoryWatcherEnabled() { - return MemoryWatcher::Enabled(); + return false; } bool VulkanAllocate(GraphicContext* ctx, VulkanMemory* mem) { + KYTY_PROFILER_FUNCTION(); + static std::atomic seq = 0; EXIT_IF(ctx == nullptr); @@ -1874,6 +1925,8 @@ bool VulkanAllocate(GraphicContext* ctx, VulkanMemory* mem) void VulkanFree(GraphicContext* ctx, VulkanMemory* mem) { + KYTY_PROFILER_FUNCTION(); + EXIT_IF(ctx == nullptr); EXIT_IF(mem == nullptr); @@ -1884,6 +1937,8 @@ void VulkanFree(GraphicContext* ctx, VulkanMemory* mem) void VulkanMapMemory(GraphicContext* ctx, VulkanMemory* mem, void** data) { + KYTY_PROFILER_FUNCTION(); + EXIT_IF(ctx == nullptr); EXIT_IF(mem == nullptr); EXIT_IF(data == nullptr); @@ -1893,6 +1948,8 @@ void VulkanMapMemory(GraphicContext* ctx, VulkanMemory* mem, void** data) void VulkanUnmapMemory(GraphicContext* ctx, VulkanMemory* mem) { + KYTY_PROFILER_FUNCTION(); + EXIT_IF(ctx == nullptr); EXIT_IF(mem == nullptr); @@ -1901,6 +1958,8 @@ void VulkanUnmapMemory(GraphicContext* ctx, VulkanMemory* mem) void VulkanBindImageMemory(GraphicContext* ctx, VulkanImage* image, VulkanMemory* mem) { + KYTY_PROFILER_FUNCTION(); + EXIT_IF(ctx == nullptr); EXIT_IF(mem == nullptr); EXIT_IF(image == nullptr); @@ -1910,6 +1969,8 @@ void VulkanBindImageMemory(GraphicContext* ctx, VulkanImage* image, VulkanMemory void VulkanBindBufferMemory(GraphicContext* ctx, VulkanBuffer* buffer, VulkanMemory* mem) { + KYTY_PROFILER_FUNCTION(); + EXIT_IF(ctx == nullptr); EXIT_IF(mem == nullptr); EXIT_IF(buffer == nullptr); diff --git a/source/emulator/src/Graphics/Objects/Label.cpp b/source/emulator/src/Graphics/Objects/Label.cpp index 6588743..86cfdf1 100644 --- a/source/emulator/src/Graphics/Objects/Label.cpp +++ b/source/emulator/src/Graphics/Objects/Label.cpp @@ -54,16 +54,19 @@ public: virtual ~LabelManager() { KYTY_NOT_IMPLEMENTED; } KYTY_CLASS_NO_COPY(LabelManager); - Label* Create(GraphicContext* ctx, uint64_t* dst_gpu_addr, uint64_t value, LabelGpuObject::callback_t callback_1, - LabelGpuObject::callback_t callback_2, const uint64_t* args); - Label* Create(GraphicContext* ctx, uint32_t* dst_gpu_addr, uint32_t value, LabelGpuObject::callback_t callback_1, - LabelGpuObject::callback_t callback_2, const uint64_t* args); + Label* Create64(GraphicContext* ctx, uint64_t* dst_gpu_addr, uint64_t value, LabelGpuObject::callback_t callback_1, + LabelGpuObject::callback_t callback_2, const uint64_t* args); + Label* Create32(GraphicContext* ctx, uint32_t* dst_gpu_addr, uint32_t value, LabelGpuObject::callback_t callback_1, + LabelGpuObject::callback_t callback_2, const uint64_t* args); void Delete(Label* label); void Set(CommandBuffer* buffer, Label* label); private: static void ThreadRun(void* data); + bool Remove(Label* label); + static void Destroy(Label* label); + Core::Mutex m_mutex; Core::CondVar m_cond_var; Vector m_labels; @@ -104,18 +107,24 @@ void LabelManager::ThreadRun(void* data) } } - for (auto& label: deleted_labels) - { - manager->Delete(label); - } - if (active_count == 0) { manager->m_cond_var.Wait(&manager->m_mutex); } + for (auto& label: deleted_labels) + { + bool removed = manager->Remove(label); + EXIT_NOT_IMPLEMENTED(!removed); + } + manager->m_mutex.Unlock(); + for (auto& label: deleted_labels) + { + Destroy(label); + } + for (auto& label: fired_labels) { bool write = true; @@ -151,11 +160,11 @@ void LabelManager::ThreadRun(void* data) } } -Label* LabelManager::Create(GraphicContext* ctx, uint64_t* dst_gpu_addr, uint64_t value, LabelGpuObject::callback_t callback_1, - LabelGpuObject::callback_t callback_2, const uint64_t* args) +Label* LabelManager::Create64(GraphicContext* ctx, uint64_t* dst_gpu_addr, uint64_t value, LabelGpuObject::callback_t callback_1, + LabelGpuObject::callback_t callback_2, const uint64_t* args) { EXIT_IF(ctx == nullptr); - EXIT_IF(dst_gpu_addr == nullptr); + EXIT_IF(args == nullptr); Core::LockGuard lock(m_mutex); @@ -190,11 +199,10 @@ Label* LabelManager::Create(GraphicContext* ctx, uint64_t* dst_gpu_addr, uint64_ return label; } -Label* LabelManager::Create(GraphicContext* ctx, uint32_t* dst_gpu_addr, uint32_t value, LabelGpuObject::callback_t callback_1, - LabelGpuObject::callback_t callback_2, const uint64_t* args) +Label* LabelManager::Create32(GraphicContext* ctx, uint32_t* dst_gpu_addr, uint32_t value, LabelGpuObject::callback_t callback_1, + LabelGpuObject::callback_t callback_2, const uint64_t* args) { EXIT_IF(ctx == nullptr); - EXIT_IF(dst_gpu_addr == nullptr); EXIT_IF(args == nullptr); Core::LockGuard lock(m_mutex); @@ -229,7 +237,7 @@ Label* LabelManager::Create(GraphicContext* ctx, uint32_t* dst_gpu_addr, uint32_ return label; } -void LabelManager::Delete(Label* label) +bool LabelManager::Remove(Label* label) { EXIT_IF(label == nullptr); EXIT_IF(label->event == nullptr); @@ -246,18 +254,35 @@ void LabelManager::Delete(Label* label) if (label->status == LabelStatus::Active) { label->status = LabelStatus::ActiveDeleted; - } else + + return false; + } + + m_labels.RemoveAt(index); + + return true; +} + +void LabelManager::Destroy(Label* label) +{ + EXIT_IF(label == nullptr); + EXIT_IF(label->event == nullptr); + EXIT_IF(label->device == nullptr); + EXIT_IF(label->buffer == nullptr); + + // All submitted commands that refer to event must have completed execution + label->buffer->CommandProcessorWait(); + + vkDestroyEvent(label->device, label->event, nullptr); + + delete label; +} + +void LabelManager::Delete(Label* label) +{ + if (Remove(label)) { - m_labels.RemoveAt(index); - - EXIT_IF(label->buffer == nullptr); - - // All submitted commands that refer to event must have completed execution - label->buffer->CommandProcessorWait(); - - vkDestroyEvent(label->device, label->event, nullptr); - - delete label; + Destroy(label); } } @@ -300,20 +325,20 @@ void LabelInit() g_label_manager = new LabelManager; } -Label* LabelCreate(GraphicContext* ctx, uint64_t* dst_gpu_addr, uint64_t value, LabelGpuObject::callback_t callback_1, - LabelGpuObject::callback_t callback_2, const uint64_t* args) +Label* LabelCreate64(GraphicContext* ctx, uint64_t* dst_gpu_addr, uint64_t value, LabelGpuObject::callback_t callback_1, + LabelGpuObject::callback_t callback_2, const uint64_t* args) { EXIT_IF(g_label_manager == nullptr); - return g_label_manager->Create(ctx, dst_gpu_addr, value, callback_1, callback_2, args); + return g_label_manager->Create64(ctx, dst_gpu_addr, value, callback_1, callback_2, args); } -Label* LabelCreate(GraphicContext* ctx, uint32_t* dst_gpu_addr, uint32_t value, LabelGpuObject::callback_t callback_1, - LabelGpuObject::callback_t callback_2, const uint64_t* args) +Label* LabelCreate32(GraphicContext* ctx, uint32_t* dst_gpu_addr, uint32_t value, LabelGpuObject::callback_t callback_1, + LabelGpuObject::callback_t callback_2, const uint64_t* args) { EXIT_IF(g_label_manager == nullptr); - return g_label_manager->Create(ctx, dst_gpu_addr, value, callback_1, callback_2, args); + return g_label_manager->Create32(ctx, dst_gpu_addr, value, callback_1, callback_2, args); } void LabelDelete(Label* label) @@ -343,10 +368,10 @@ static void* create_func(GraphicContext* ctx, const uint64_t* params, const uint auto callback_1 = reinterpret_cast(params[LabelGpuObject::PARAM_CALLBACK_1]); auto callback_2 = reinterpret_cast(params[LabelGpuObject::PARAM_CALLBACK_2]); - auto* label_obj = (*size == 8 ? LabelCreate(ctx, reinterpret_cast(*vaddr), value, callback_1, callback_2, - params + LabelGpuObject::PARAM_ARG_1) - : (*size == 4 ? LabelCreate(ctx, reinterpret_cast(*vaddr), static_cast(value), - callback_1, callback_2, params + LabelGpuObject::PARAM_ARG_1) + auto* label_obj = (*size == 8 ? LabelCreate64(ctx, reinterpret_cast(*vaddr), value, callback_1, callback_2, + params + LabelGpuObject::PARAM_ARG_1) + : (*size == 4 ? LabelCreate32(ctx, reinterpret_cast(*vaddr), static_cast(value), + callback_1, callback_2, params + LabelGpuObject::PARAM_ARG_1) : nullptr)); EXIT_NOT_IMPLEMENTED(label_obj == nullptr); diff --git a/source/emulator/src/Graphics/Shader.cpp b/source/emulator/src/Graphics/Shader.cpp index d3515a0..5383991 100644 --- a/source/emulator/src/Graphics/Shader.cpp +++ b/source/emulator/src/Graphics/Shader.cpp @@ -354,7 +354,7 @@ String ShaderCode::DbgDump() const String ret; for (const auto& inst: m_instructions) { - if (m_labels.Contains(inst.pc, [](auto label, auto pc) { return label.dst == pc; })) + if (m_labels.Contains(inst.pc, [](auto label, auto pc) { return label.GetDst() == pc; })) { ret += String::FromPrintf("label_%04" PRIx32 ":\n", inst.pc); } @@ -363,6 +363,51 @@ String ShaderCode::DbgDump() const return ret; } +bool ShaderCode::IsDiscardInstruction(uint32_t index) const +{ + if (!(index == 0 || index + 1 >= m_instructions.Size())) + { + const auto& prev_inst = m_instructions.At(index - 1); + const auto& inst = m_instructions.At(index); + const auto& next_inst = m_instructions.At(index + 1); + + return (inst.type == ShaderInstructionType::Exp && inst.format == ShaderInstructionFormat::Mrt0OffOffComprVmDone && + prev_inst.type == ShaderInstructionType::SMovB64 && prev_inst.format == ShaderInstructionFormat::Sdst2Ssrc02 && + prev_inst.dst.type == ShaderOperandType::ExecLo && prev_inst.src[0].type == ShaderOperandType::IntegerInlineConstant && + prev_inst.src[0].constant.i == 0 && next_inst.type == ShaderInstructionType::SEndpgm); + } + return false; +} + +bool ShaderCode::IsDiscardBlock(uint32_t pc) const +{ + auto inst_count = m_instructions.Size(); + for (uint32_t index = 0; index < inst_count; index++) + { + const auto& inst = m_instructions.At(index); + if (inst.pc == pc) + { + for (uint32_t i = index; i < inst_count; i++) + { + const auto& inst = m_instructions.At(i); + + if (inst.type == ShaderInstructionType::SEndpgm || inst.type == ShaderInstructionType::SCbranchExecz || + inst.type == ShaderInstructionType::SCbranchScc0) + { + return false; + } + + if (IsDiscardInstruction(i)) + { + return true; + } + } + return false; + } + } + return false; +} + static ShaderOperand operand_parse(uint32_t code) { ShaderOperand ret; @@ -555,7 +600,7 @@ KYTY_SHADER_PARSER(shader_parse_sopp) if (inst.type == ShaderInstructionType::SCbranchScc0 || inst.type == ShaderInstructionType::SCbranchExecz) { - dst->GetLabels().Add(ShaderLabel({inst.pc + 4 + inst.src[0].constant.i, inst.pc})); + dst->GetLabels().Add(ShaderLabel(inst)); } return 1; @@ -1782,7 +1827,7 @@ KYTY_SHADER_PARSER(shader_parse) } if ((instruction == 0xBF810000 && (type == ShaderType::Vertex || type == ShaderType::Pixel || type == ShaderType::Compute) && - !dst->GetLabels().Contains(4 * static_cast(ptr - src), [](auto label, auto pc) { return label.dst == pc; })) || + !dst->GetLabels().Contains(4 * static_cast(ptr - src), [](auto label, auto pc) { return label.GetDst() == pc; })) || (instruction == 0xBE802000 && type == ShaderType::Fetch)) { break; diff --git a/source/emulator/src/Graphics/ShaderSpirv.cpp b/source/emulator/src/Graphics/ShaderSpirv.cpp index 282c374..35c0ddf 100644 --- a/source/emulator/src/Graphics/ShaderSpirv.cpp +++ b/source/emulator/src/Graphics/ShaderSpirv.cpp @@ -2036,17 +2036,24 @@ KYTY_RECOMPILER_FUNC(Recompile_Exp_Mrt0OffOffComprVmDone) { EXIT_NOT_IMPLEMENTED(index == 0 || index + 1 >= code.GetInstructions().Size()); - const auto& prev_inst = code.GetInstructions().At(index - 1); - const auto& inst = code.GetInstructions().At(index); - const auto& next_inst = code.GetInstructions().At(index + 1); - - if (!(prev_inst.type == ShaderInstructionType::SMovB64 && prev_inst.format == ShaderInstructionFormat::Sdst2Ssrc02 && - prev_inst.dst.type == ShaderOperandType::ExecLo && prev_inst.src[0].type == ShaderOperandType::IntegerInlineConstant && - prev_inst.src[0].constant.i == 0 && next_inst.type == ShaderInstructionType::SEndpgm)) + if (!code.IsDiscardInstruction(index)) { return false; } + // const auto& prev_inst = code.GetInstructions().At(index - 1); + // const auto& inst = code.GetInstructions().At(index); + // const auto& next_inst = code.GetInstructions().At(index + 1); + // + // if (!(prev_inst.type == ShaderInstructionType::SMovB64 && prev_inst.format == ShaderInstructionFormat::Sdst2Ssrc02 && + // prev_inst.dst.type == ShaderOperandType::ExecLo && prev_inst.src[0].type == ShaderOperandType::IntegerInlineConstant && + // prev_inst.src[0].constant.i == 0 && next_inst.type == ShaderInstructionType::SEndpgm)) + // { + // return false; + // } + + const auto& inst = code.GetInstructions().At(index); + const auto* info = spirv->GetPsInputInfo(); EXIT_NOT_IMPLEMENTED(info == nullptr || !info->ps_pixel_kill_enable); @@ -3188,7 +3195,7 @@ KYTY_RECOMPILER_FUNC(Recompile_SCbranchExecz_Label) EXIT_NOT_IMPLEMENTED(!operand_is_constant(inst.src[0])); - String label = String::FromPrintf("label_%04" PRIx32 "_%04" PRIx32, inst.pc + 4 + inst.src[0].constant.i, inst.pc); + String label = ShaderLabel(inst).ToString(); static const char32_t* text = UR"( %execz_u_ = OpLoad %uint %execz @@ -3209,17 +3216,30 @@ KYTY_RECOMPILER_FUNC(Recompile_SCbranchScc0_Label) EXIT_NOT_IMPLEMENTED(!operand_is_constant(inst.src[0])); - String label = String::FromPrintf("label_%04" PRIx32 "_%04" PRIx32, inst.pc + 4 + inst.src[0].constant.i, inst.pc); + auto label = ShaderLabel(inst); + String label_str = label.ToString(); - static const char32_t* text = UR"( + // TODO(): analyze control flow graph + bool discard = code.IsDiscardBlock(label.GetDst()); + + static const char32_t* text_variant_a = UR"( %scc_u_ = OpLoad %uint %scc %scc_b_ = OpIEqual %bool %scc_u_ %uint_0 OpSelectionMerge %