diff --git a/README.md b/README.md index 20eb0b1..b26c344 100644 --- a/README.md +++ b/README.md @@ -35,5 +35,5 @@ Define environment variable named Qt5_DIR pointing to the proper version of Qt MSVC compiler (cl.exe) is not supported! External dependencies: -* Vulkan SDK 1.2.176.1 +* Vulkan SDK 1.2.198.1 * Qt 5.15.0 diff --git a/appveyor.yml b/appveyor.yml index 64a3336..d2162e6 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 0.0.11.build-{build} +version: 0.0.12.build-{build} image: Visual Studio 2019 environment: matrix: diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index 672a4be..b8308c1 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.11) +project(Kyty${KYTY_PROJECT_NAME}${CMAKE_BUILD_TYPE}${KYTY_COMPILER} VERSION 0.0.12) include(src_script.cmake) diff --git a/source/emulator/include/Emulator/Graphics/GraphicContext.h b/source/emulator/include/Emulator/Graphics/GraphicContext.h index 7179a50..d0bda3c 100644 --- a/source/emulator/include/Emulator/Graphics/GraphicContext.h +++ b/source/emulator/include/Emulator/Graphics/GraphicContext.h @@ -83,6 +83,8 @@ struct VideoOutVulkanImage: public VulkanImage struct DepthStencilVulkanImage: public VulkanImage { + bool compressed = false; + VkImageView texture_view = nullptr; }; struct TextureVulkanImage: public VulkanImage diff --git a/source/emulator/include/Emulator/Graphics/Graphics.h b/source/emulator/include/Emulator/Graphics/Graphics.h index 9f92c6c..47dbd15 100644 --- a/source/emulator/include/Emulator/Graphics/Graphics.h +++ b/source/emulator/include/Emulator/Graphics/Graphics.h @@ -11,14 +11,16 @@ namespace Kyty::Libs::Graphics { +namespace HW { struct VsStageRegisters; +} // namespace HW KYTY_SUBSYSTEM_DEFINE(Graphics); void GraphicsDbgDumpDcb(const char* type, uint32_t num_dw, uint32_t* cmd_buffer); -int KYTY_SYSV_ABI GraphicsSetVsShader(uint32_t* cmd, uint64_t size, const VsStageRegisters* vs_regs, uint32_t shader_modifier); -int KYTY_SYSV_ABI GraphicsUpdateVsShader(uint32_t* cmd, uint64_t size, const VsStageRegisters* vs_regs, uint32_t shader_modifier); +int KYTY_SYSV_ABI GraphicsSetVsShader(uint32_t* cmd, uint64_t size, const HW::VsStageRegisters* vs_regs, uint32_t shader_modifier); +int KYTY_SYSV_ABI GraphicsUpdateVsShader(uint32_t* cmd, uint64_t size, const HW::VsStageRegisters* vs_regs, uint32_t shader_modifier); 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); diff --git a/source/emulator/include/Emulator/Graphics/GraphicsRender.h b/source/emulator/include/Emulator/Graphics/GraphicsRender.h index a85581f..006923a 100644 --- a/source/emulator/include/Emulator/Graphics/GraphicsRender.h +++ b/source/emulator/include/Emulator/Graphics/GraphicsRender.h @@ -10,8 +10,11 @@ namespace Kyty::Libs::Graphics { +namespace HW { class HardwareContext; class UserConfig; +} // namespace HW + class CommandProcessor; struct VideoOutVulkanImage; struct DepthStencilVulkanImage; @@ -66,9 +69,10 @@ private: void GraphicsRenderInit(); void GraphicsRenderCreateContext(); -void GraphicsRenderDrawIndex(CommandBuffer* buffer, HardwareContext* ctx, UserConfig* ucfg, uint32_t index_type_and_size, +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, HardwareContext* ctx, UserConfig* ucfg, uint32_t index_count, uint32_t flags); +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); @@ -81,7 +85,7 @@ void GraphicsRenderWriteAtEndOfPipeWithWriteBack(CommandBuffer* buffer, uint64_t 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 GraphicsRenderWriteBack(); -void GraphicsRenderDispatchDirect(CommandBuffer* buffer, HardwareContext* ctx, uint32_t thread_group_x, uint32_t thread_group_y, +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 GraphicsRenderMemoryBarrier(CommandBuffer* buffer); void GraphicsRenderRenderTextureBarrier(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 031e13a..60b6fb5 100644 --- a/source/emulator/include/Emulator/Graphics/HardwareContext.h +++ b/source/emulator/include/Emulator/Graphics/HardwareContext.h @@ -7,7 +7,29 @@ #ifdef KYTY_EMU_ENABLED -namespace Kyty::Libs::Graphics { +namespace Kyty::Libs::Graphics::HW { + +struct ColorBase +{ + uint64_t addr = 0; +}; + +struct ColorPitch +{ + uint32_t pitch_div8_minus1 = 0; + uint32_t fmask_pitch_div8_minus1 = 0; +}; + +struct ColorSlice +{ + uint32_t slice_div64_minus1 = 0; +}; + +struct ColorView +{ + uint32_t base_array_slice_index = 0; + uint32_t last_array_slice_index = 0; +}; struct ColorInfo { @@ -23,37 +45,83 @@ struct ColorInfo uint32_t channel_order = 0; }; +struct ColorAttrib +{ + bool force_dest_alpha_to_one = false; + uint32_t tile_mode = 0; + uint32_t fmask_tile_mode = 0; + uint32_t num_samples = 0; + uint32_t num_fragments = 0; +}; + +struct ColorDcc +{ + uint32_t max_uncompressed_block_size = 0; + uint32_t max_compressed_block_size = 0; + uint32_t min_compressed_block_size = 0; + uint32_t color_transform = 0; + bool enable_overwrite_combiner = false; + bool force_independent_blocks = false; +}; + +struct ColorCmask +{ + uint64_t addr = 0; +}; + +struct ColorCmaskSlice +{ + uint32_t slice_minus1 = 0; +}; + +struct ColorFmask +{ + uint64_t addr = 0; +}; + +struct ColorFmaskSlice +{ + uint32_t slice_minus1 = 0; +}; + +struct ColorClearWord0 +{ + uint32_t word0 = 0; +}; + +struct ColorClearWord1 +{ + uint32_t word1 = 0; +}; + +struct ColorDccAddr +{ + uint64_t addr = 0; +}; + +struct ColorSize +{ + uint32_t width = 0; + uint32_t height = 0; +}; + struct RenderTarget { - uint64_t base_addr = 0; - uint32_t pitch_div8_minus1 = 0; - uint32_t fmask_pitch_div8_minus1 = 0; - uint32_t slice_div64_minus1 = 0; - uint32_t base_array_slice_index = 0; - uint32_t last_array_slice_index = 0; - - ColorInfo color_info; - - bool force_dest_alpha_to_one = false; - uint32_t tile_mode = 0; - uint32_t fmask_tile_mode = 0; - uint32_t num_samples = 0; - uint32_t num_fragments = 0; - uint32_t dcc_max_uncompressed_block_size = 0; - uint32_t dcc_max_compressed_block_size = 0; - uint32_t dcc_min_compressed_block_size = 0; - uint32_t dcc_color_transform = 0; - bool dcc_enable_overwrite_combiner = false; - bool dcc_force_independent_blocks = false; - uint64_t cmask_addr = 0; - uint32_t cmask_slice_minus1 = 0; - uint64_t fmask_addr = 0; - uint32_t fmask_slice_minus1 = 0; - uint32_t clear_color_word0 = 0; - uint32_t clear_color_word1 = 0; - uint64_t dcc_addr = 0; - uint32_t width = 0; - uint32_t height = 0; + ColorBase base; + ColorPitch pitch; + ColorSlice slice; + ColorView view; + ColorInfo info; + ColorAttrib attrib; + ColorDcc dcc; + ColorCmask cmask; + ColorCmaskSlice cmask_slice; + ColorFmask fmask; + ColorFmaskSlice fmask_slice; + ColorClearWord0 clear_word0; + ColorClearWord1 clear_word1; + ColorDccAddr dcc_addr; + ColorSize size; }; struct DepthRenderTargetZInfo @@ -231,6 +299,12 @@ struct EqaaControl bool static_anchor_associations = false; }; +struct ColorControl +{ + uint8_t mode = 1; + uint8_t op = 0xCC; +}; + struct Viewport { float zmin = 0.0f; @@ -246,17 +320,22 @@ struct Viewport struct ScreenViewport { Viewport viewports[15]; - uint32_t transform_control = 0; - int scissor_left = 0; - int scissor_top = 0; - int scissor_right = 0; - int scissor_bottom = 0; - uint32_t hw_offset_x = 0; - uint32_t hw_offset_y = 0; - float guard_band_horz_clip = 0.0f; - float guard_band_vert_clip = 0.0f; - float guard_band_horz_discard = 0.0f; - float guard_band_vert_discard = 0.0f; + uint32_t transform_control = 0; + int screen_scissor_left = 0; + int screen_scissor_top = 0; + int screen_scissor_right = 0; + int screen_scissor_bottom = 0; + int generic_scissor_left = 0; + int generic_scissor_top = 0; + int generic_scissor_right = 0; + int generic_scissor_bottom = 0; + bool generic_scissor_window_offset_enable = false; + uint32_t hw_offset_x = 0; + uint32_t hw_offset_y = 0; + float guard_band_horz_clip = 0.0f; + float guard_band_vert_clip = 0.0f; + float guard_band_horz_discard = 0.0f; + float guard_band_vert_discard = 0.0f; }; struct VsStageRegisters @@ -372,9 +451,22 @@ public: void Reset() { *this = HardwareContext(); } - void SetRenderTarget(uint32_t slot, const RenderTarget& target) { m_render_targets[slot] = target; } - void SetColorInfo(uint32_t slot, const ColorInfo& color_info) { m_render_targets[slot].color_info = color_info; } - [[nodiscard]] const RenderTarget& GetRenderTargets(uint32_t slot) const { return m_render_targets[slot]; } + void SetColorBase(uint32_t slot, const ColorBase& base) { m_render_targets[slot].base = base; } + void SetColorPitch(uint32_t slot, const ColorPitch& pitch) { m_render_targets[slot].pitch = pitch; } + void SetColorSlice(uint32_t slot, const ColorSlice& slice) { m_render_targets[slot].slice = slice; } + void SetColorView(uint32_t slot, const ColorView& view) { m_render_targets[slot].view = view; } + void SetColorInfo(uint32_t slot, const ColorInfo& info) { m_render_targets[slot].info = info; } + void SetColorAttrib(uint32_t slot, const ColorAttrib& attrib) { m_render_targets[slot].attrib = attrib; } + void SetColorDcc(uint32_t slot, const ColorDcc& dcc) { m_render_targets[slot].dcc = dcc; } + void SetColorCmask(uint32_t slot, const ColorCmask& cmask) { m_render_targets[slot].cmask = cmask; } + void SetColorCmaskSlice(uint32_t slot, const ColorCmaskSlice& cmask_slice) { m_render_targets[slot].cmask_slice = cmask_slice; } + void SetColorFmask(uint32_t slot, const ColorFmask& fmask) { m_render_targets[slot].fmask = fmask; } + void SetColorFmaskSlice(uint32_t slot, const ColorFmaskSlice& fmask_slice) { m_render_targets[slot].fmask_slice = fmask_slice; } + void SetColorClearWord0(uint32_t slot, const ColorClearWord0& clear_word0) { m_render_targets[slot].clear_word0 = clear_word0; } + void SetColorClearWord1(uint32_t slot, const ColorClearWord1& clear_word1) { m_render_targets[slot].clear_word1 = clear_word1; } + void SetColorDccAddr(uint32_t slot, const ColorDccAddr& dcc_addr) { m_render_targets[slot].dcc_addr = dcc_addr; } + void SetColorSize(uint32_t slot, const ColorSize& size) { m_render_targets[slot].size = size; } + [[nodiscard]] const RenderTarget& GetRenderTarget(uint32_t slot) const { return m_render_targets[slot]; } void SetBlendControl(uint32_t slot, const BlendControl& control) { m_blend_control[slot] = control; } [[nodiscard]] const BlendControl& GetBlendControl(uint32_t slot) const { return m_blend_control[slot]; } @@ -409,10 +501,18 @@ public: void SetViewportTransformControl(uint32_t control) { m_screen_viewport.transform_control = control; } void SetScreenScissor(int left, int top, int right, int bottom) { - m_screen_viewport.scissor_left = left; - m_screen_viewport.scissor_top = top; - m_screen_viewport.scissor_right = right; - m_screen_viewport.scissor_bottom = bottom; + m_screen_viewport.screen_scissor_left = left; + m_screen_viewport.screen_scissor_top = top; + m_screen_viewport.screen_scissor_right = right; + m_screen_viewport.screen_scissor_bottom = bottom; + } + void SetGenericScissor(int left, int top, int right, int bottom, bool window_offset_enable) + { + m_screen_viewport.generic_scissor_left = left; + m_screen_viewport.generic_scissor_top = top; + m_screen_viewport.generic_scissor_right = right; + m_screen_viewport.generic_scissor_bottom = bottom; + m_screen_viewport.generic_scissor_window_offset_enable = window_offset_enable; } void SetHardwareScreenOffset(uint32_t offset_x, uint32_t offset_y) { @@ -474,6 +574,8 @@ public: 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; } void SetVsUserSgpr(uint32_t id, uint32_t value, UserSgprType type) { @@ -508,13 +610,19 @@ public: [[nodiscard]] uint8_t GetStencilClearValue() const { return m_stencil_clear_value; } void SetStencilClearValue(uint8_t clear_value) { m_stencil_clear_value = clear_value; } + [[nodiscard]] float GetLineWidth() const { return m_line_width; } + void SetLineWidth(float width) { m_line_width = width; } + 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; VertexShaderInfo m_vs; PixelShaderInfo m_ps; @@ -580,7 +688,7 @@ inline uint32_t VsStageRegisters::GetUnknown2() const return m_spiShaderPgmRsrc2Vs & 0xFFFFEFFFu; } -} // namespace Kyty::Libs::Graphics +} // namespace Kyty::Libs::Graphics::HW #endif // KYTY_EMU_ENABLED diff --git a/source/emulator/include/Emulator/Graphics/Objects/GpuMemory.h b/source/emulator/include/Emulator/Graphics/Objects/GpuMemory.h index 37b9218..28fe848 100644 --- a/source/emulator/include/Emulator/Graphics/Objects/GpuMemory.h +++ b/source/emulator/include/Emulator/Graphics/Objects/GpuMemory.h @@ -44,6 +44,7 @@ enum class GpuMemoryScenario { Common, GenerateMips, + TextureTriplet }; struct GpuMemoryObject @@ -98,8 +99,9 @@ void GpuMemoryFlush(GraphicContext* ctx); void GpuMemoryFrameDone(); void GpuMemoryWriteBack(GraphicContext* ctx); bool GpuMemoryCheckAccessViolation(uint64_t vaddr, uint64_t size); +bool GpuMemoryWatcherEnabled(); -Vector GpuMemoryFindObjects(uint64_t vaddr, uint64_t size, bool exact); +Vector GpuMemoryFindObjects(uint64_t vaddr, uint64_t size, 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/Pm4.h b/source/emulator/include/Emulator/Graphics/Pm4.h index 0c52e7a..3eafb45 100644 --- a/source/emulator/include/Emulator/Graphics/Pm4.h +++ b/source/emulator/include/Emulator/Graphics/Pm4.h @@ -119,6 +119,18 @@ constexpr uint32_t DB_DEPTH_CLEAR = 0xB; constexpr uint32_t DB_DEPTH_CLEAR_DEPTH_CLEAR_SHIFT = 0; constexpr uint32_t DB_DEPTH_CLEAR_DEPTH_CLEAR_MASK = 0xFFFFFFFF; +constexpr uint32_t PA_SC_SCREEN_SCISSOR_TL = 0xC; +constexpr uint32_t PA_SC_SCREEN_SCISSOR_TL_TL_X_SHIFT = 0; +constexpr uint32_t PA_SC_SCREEN_SCISSOR_TL_TL_X_MASK = 0xFFFF; +constexpr uint32_t PA_SC_SCREEN_SCISSOR_TL_TL_Y_SHIFT = 16; +constexpr uint32_t PA_SC_SCREEN_SCISSOR_TL_TL_Y_MASK = 0xFFFF; + +constexpr uint32_t PA_SC_SCREEN_SCISSOR_BR = 0xD; +constexpr uint32_t PA_SC_SCREEN_SCISSOR_BR_BR_X_SHIFT = 0; +constexpr uint32_t PA_SC_SCREEN_SCISSOR_BR_BR_X_MASK = 0xFFFF; +constexpr uint32_t PA_SC_SCREEN_SCISSOR_BR_BR_Y_SHIFT = 16; +constexpr uint32_t PA_SC_SCREEN_SCISSOR_BR_BR_Y_MASK = 0xFFFF; + constexpr uint32_t DB_DEPTH_INFO = 0xF; constexpr uint32_t DB_DEPTH_INFO_ADDR5_SWIZZLE_MASK_SHIFT = 0; constexpr uint32_t DB_DEPTH_INFO_ADDR5_SWIZZLE_MASK_MASK = 0xF; @@ -178,6 +190,20 @@ constexpr uint32_t DB_DEPTH_SLICE = 0x17; constexpr uint32_t DB_DEPTH_SLICE_SLICE_TILE_MAX_SHIFT = 0; constexpr uint32_t DB_DEPTH_SLICE_SLICE_TILE_MAX_MASK = 0x3FFFFF; +constexpr uint32_t PA_SC_GENERIC_SCISSOR_TL = 0x90; +constexpr uint32_t PA_SC_GENERIC_SCISSOR_TL_TL_X_SHIFT = 0; +constexpr uint32_t PA_SC_GENERIC_SCISSOR_TL_TL_X_MASK = 0x7FFF; +constexpr uint32_t PA_SC_GENERIC_SCISSOR_TL_TL_Y_SHIFT = 16; +constexpr uint32_t PA_SC_GENERIC_SCISSOR_TL_TL_Y_MASK = 0x7FFF; +constexpr uint32_t PA_SC_GENERIC_SCISSOR_TL_WINDOW_OFFSET_DISABLE_SHIFT = 31; +constexpr uint32_t PA_SC_GENERIC_SCISSOR_TL_WINDOW_OFFSET_DISABLE_MASK = 0x1; + +constexpr uint32_t PA_SC_GENERIC_SCISSOR_BR = 0x91; +constexpr uint32_t PA_SC_GENERIC_SCISSOR_BR_BR_X_SHIFT = 0; +constexpr uint32_t PA_SC_GENERIC_SCISSOR_BR_BR_X_MASK = 0x7FFF; +constexpr uint32_t PA_SC_GENERIC_SCISSOR_BR_BR_Y_SHIFT = 16; +constexpr uint32_t PA_SC_GENERIC_SCISSOR_BR_BR_Y_MASK = 0x7FFF; + constexpr uint32_t PA_SC_VPORT_ZMIN_0 = 0xB4; constexpr uint32_t CB_BLEND_RED = 0x105; @@ -277,6 +303,12 @@ constexpr uint32_t DB_EQAA_INTERPOLATE_COMP_Z_MASK = 0x1; constexpr uint32_t DB_EQAA_STATIC_ANCHOR_ASSOCIATIONS_SHIFT = 20; constexpr uint32_t DB_EQAA_STATIC_ANCHOR_ASSOCIATIONS_MASK = 0x1; +constexpr uint32_t CB_COLOR_CONTROL = 0x202; +constexpr uint32_t CB_COLOR_CONTROL_MODE_SHIFT = 4; +constexpr uint32_t CB_COLOR_CONTROL_MODE_MASK = 0x7; +constexpr uint32_t CB_COLOR_CONTROL_ROP3_SHIFT = 16; +constexpr uint32_t CB_COLOR_CONTROL_ROP3_MASK = 0xFF; + constexpr uint32_t PA_SU_SC_MODE_CNTL = 0x205; constexpr uint32_t PA_SU_SC_MODE_CNTL_CULL_FRONT_SHIFT = 0; constexpr uint32_t PA_SU_SC_MODE_CNTL_CULL_FRONT_MASK = 0x1; @@ -301,6 +333,10 @@ constexpr uint32_t PA_SU_SC_MODE_CNTL_PROVOKING_VTX_LAST_MASK = 0x1; constexpr uint32_t PA_SU_SC_MODE_CNTL_PERSP_CORR_DIS_SHIFT = 20; constexpr uint32_t PA_SU_SC_MODE_CNTL_PERSP_CORR_DIS_MASK = 0x1; +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 DB_HTILE_SURFACE = 0x2AF; constexpr uint32_t DB_HTILE_SURFACE_LINEAR_SHIFT = 0; constexpr uint32_t DB_HTILE_SURFACE_LINEAR_MASK = 0x1; diff --git a/source/emulator/include/Emulator/Graphics/Shader.h b/source/emulator/include/Emulator/Graphics/Shader.h index 9ed2300..89f380d 100644 --- a/source/emulator/include/Emulator/Graphics/Shader.h +++ b/source/emulator/include/Emulator/Graphics/Shader.h @@ -13,9 +13,11 @@ namespace Kyty::Libs::Graphics { +namespace HW { struct VertexShaderInfo; struct PixelShaderInfo; struct ComputeShaderInfo; +} // namespace HW enum class ShaderType { @@ -600,18 +602,26 @@ struct ShaderStorageResources int binding_index = 0; }; +struct ShaderTextureDescriptor +{ + ShaderTextureResource texture; + ShaderTextureUsage usage = ShaderTextureUsage::Unknown; + int slot = 0; + int start_register = 0; + bool extended = false; + bool textures2d_without_sampler = false; +}; + struct ShaderTextureResources { static constexpr int RES_MAX = 16; - ShaderTextureResource textures[RES_MAX]; - ShaderTextureUsage usages[RES_MAX] = {}; - int slots[RES_MAX] = {0}; - int start_register[RES_MAX] = {0}; - bool extended[RES_MAX] = {}; - int textures_num = 0; - int binding_sampled_index = 0; - int binding_storage_index = 0; + ShaderTextureDescriptor desc[RES_MAX]; + int textures_num = 0; + int textures2d_sampled_num = 0; + int textures2d_storage_num = 0; + int binding_sampled_index = 0; + int binding_storage_index = 0; }; struct ShaderSamplerResources @@ -658,12 +668,12 @@ struct ShaderBindResources ShaderExtendedResources extended; }; -struct ShaderBindParameters -{ - bool textures2d_without_sampler[ShaderTextureResources::RES_MAX] = {}; - int textures2d_sampled_num = 0; - int textures2d_storage_num = 0; -}; +// struct ShaderBindParameters +//{ +// bool textures2d_without_sampler[ShaderTextureResources::RES_MAX] = {}; +// int textures2d_sampled_num = 0; +// int textures2d_storage_num = 0; +//}; struct ShaderVertexInputInfo { @@ -700,28 +710,28 @@ struct ShaderPixelInputInfo ShaderBindResources bind; }; -void ShaderCalcBindingIndices(ShaderBindResources* bind); -void ShaderGetInputInfoVS(const VertexShaderInfo* regs, ShaderVertexInputInfo* info); -void ShaderGetInputInfoPS(const PixelShaderInfo* regs, const ShaderVertexInputInfo* vs_info, ShaderPixelInputInfo* ps_info); -void ShaderGetInputInfoCS(const ComputeShaderInfo* regs, ShaderComputeInputInfo* info); -void ShaderDbgDumpInputInfo(const ShaderVertexInputInfo* info); -void ShaderDbgDumpInputInfo(const ShaderPixelInputInfo* info); -void ShaderDbgDumpInputInfo(const ShaderComputeInputInfo* info); -ShaderId ShaderGetIdVS(const VertexShaderInfo* regs, const ShaderVertexInputInfo* input_info); -ShaderId ShaderGetIdPS(const PixelShaderInfo* regs, const ShaderPixelInputInfo* input_info); -ShaderId ShaderGetIdCS(const ComputeShaderInfo* regs, const ShaderComputeInputInfo* input_info); -ShaderCode ShaderParseVS(const VertexShaderInfo* regs); -ShaderCode ShaderParsePS(const PixelShaderInfo* regs); -ShaderCode ShaderParseCS(const ComputeShaderInfo* regs); -ShaderBindParameters ShaderGetBindParametersVS(const ShaderCode& code, const ShaderVertexInputInfo* input_info); -ShaderBindParameters ShaderGetBindParametersPS(const ShaderCode& code, const ShaderPixelInputInfo* input_info); -ShaderBindParameters ShaderGetBindParametersCS(const ShaderCode& code, const ShaderComputeInputInfo* input_info); -Vector ShaderRecompileVS(const ShaderCode& code, const ShaderVertexInputInfo* input_info); -Vector ShaderRecompilePS(const ShaderCode& code, const ShaderPixelInputInfo* input_info); -Vector ShaderRecompileCS(const ShaderCode& code, const ShaderComputeInputInfo* input_info); -bool ShaderIsDisabled(uint64_t addr); -void ShaderDisable(uint64_t id); -void ShaderInjectDebugPrintf(uint64_t id, const ShaderDebugPrintf& cmd); +void ShaderCalcBindingIndices(ShaderBindResources* bind); +void ShaderGetInputInfoVS(const HW::VertexShaderInfo* regs, ShaderVertexInputInfo* info); +void ShaderGetInputInfoPS(const HW::PixelShaderInfo* regs, const ShaderVertexInputInfo* vs_info, ShaderPixelInputInfo* ps_info); +void ShaderGetInputInfoCS(const HW::ComputeShaderInfo* regs, ShaderComputeInputInfo* info); +void ShaderDbgDumpInputInfo(const ShaderVertexInputInfo* info); +void ShaderDbgDumpInputInfo(const ShaderPixelInputInfo* info); +void ShaderDbgDumpInputInfo(const ShaderComputeInputInfo* info); +ShaderId ShaderGetIdVS(const HW::VertexShaderInfo* regs, const ShaderVertexInputInfo* input_info); +ShaderId ShaderGetIdPS(const HW::PixelShaderInfo* regs, const ShaderPixelInputInfo* input_info); +ShaderId ShaderGetIdCS(const HW::ComputeShaderInfo* regs, const ShaderComputeInputInfo* input_info); +ShaderCode ShaderParseVS(const HW::VertexShaderInfo* regs); +ShaderCode ShaderParsePS(const HW::PixelShaderInfo* regs); +ShaderCode ShaderParseCS(const HW::ComputeShaderInfo* regs); +// ShaderBindParameters ShaderGetBindParametersVS(const ShaderCode& code, const ShaderVertexInputInfo* input_info); +// ShaderBindParameters ShaderGetBindParametersPS(const ShaderCode& code, const ShaderPixelInputInfo* input_info); +// ShaderBindParameters ShaderGetBindParametersCS(const ShaderCode& code, const ShaderComputeInputInfo* input_info); +Vector ShaderRecompileVS(const ShaderCode& code, const ShaderVertexInputInfo* input_info); +Vector ShaderRecompilePS(const ShaderCode& code, const ShaderPixelInputInfo* input_info); +Vector ShaderRecompileCS(const ShaderCode& code, const ShaderComputeInputInfo* input_info); +bool ShaderIsDisabled(uint64_t addr); +void ShaderDisable(uint64_t id); +void ShaderInjectDebugPrintf(uint64_t id, const ShaderDebugPrintf& cmd); } // namespace Kyty::Libs::Graphics diff --git a/source/emulator/src/Graphics/Graphics.cpp b/source/emulator/src/Graphics/Graphics.cpp index fc371b4..ea12b99 100644 --- a/source/emulator/src/Graphics/Graphics.cpp +++ b/source/emulator/src/Graphics/Graphics.cpp @@ -44,11 +44,11 @@ KYTY_SUBSYSTEM_UNEXPECTED_SHUTDOWN(Graphics) {} KYTY_SUBSYSTEM_DESTROY(Graphics) {} -int KYTY_SYSV_ABI GraphicsSetVsShader(uint32_t* cmd, uint64_t size, const VsStageRegisters* vs_regs, uint32_t shader_modifier) +int KYTY_SYSV_ABI GraphicsSetVsShader(uint32_t* cmd, uint64_t size, const HW::VsStageRegisters* vs_regs, uint32_t shader_modifier) { PRINT_NAME(); - EXIT_NOT_IMPLEMENTED(size < sizeof(VsStageRegisters) / 4 + 2); + EXIT_NOT_IMPLEMENTED(size < sizeof(HW::VsStageRegisters) / 4 + 2); printf("\t cmd_buffer = %016" PRIx64 "\n", reinterpret_cast(cmd)); printf("\t size = %" PRIu64 "\n", size); @@ -64,16 +64,16 @@ int KYTY_SYSV_ABI GraphicsSetVsShader(uint32_t* cmd, uint64_t size, const VsStag cmd[0] = KYTY_PM4(size, Pm4::IT_NOP, Pm4::R_VS); cmd[1] = shader_modifier; - memcpy(&cmd[2], vs_regs, sizeof(VsStageRegisters)); + memcpy(&cmd[2], vs_regs, sizeof(HW::VsStageRegisters)); return OK; } -int KYTY_SYSV_ABI GraphicsUpdateVsShader(uint32_t* cmd, uint64_t size, const VsStageRegisters* vs_regs, uint32_t shader_modifier) +int KYTY_SYSV_ABI GraphicsUpdateVsShader(uint32_t* cmd, uint64_t size, const HW::VsStageRegisters* vs_regs, uint32_t shader_modifier) { PRINT_NAME(); - EXIT_NOT_IMPLEMENTED(size < sizeof(VsStageRegisters) / 4 + 2); + EXIT_NOT_IMPLEMENTED(size < sizeof(HW::VsStageRegisters) / 4 + 2); printf("\t cmd_buffer = %016" PRIx64 "\n", reinterpret_cast(cmd)); printf("\t size = %" PRIu64 "\n", size); @@ -89,7 +89,7 @@ int KYTY_SYSV_ABI GraphicsUpdateVsShader(uint32_t* cmd, uint64_t size, const VsS cmd[0] = KYTY_PM4(size, Pm4::IT_NOP, Pm4::R_VS_UPDATE); cmd[1] = shader_modifier; - memcpy(&cmd[2], vs_regs, sizeof(VsStageRegisters)); + memcpy(&cmd[2], vs_regs, sizeof(HW::VsStageRegisters)); return OK; } diff --git a/source/emulator/src/Graphics/GraphicsRender.cpp b/source/emulator/src/Graphics/GraphicsRender.cpp index 2086db8..3799e33 100644 --- a/source/emulator/src/Graphics/GraphicsRender.cpp +++ b/source/emulator/src/Graphics/GraphicsRender.cpp @@ -100,9 +100,14 @@ struct PipelineStaticParameters struct PipelineDynamicParameters { - bool vk_dynamic_state_stencil_compare_mask = false; - bool vk_dynamic_state_stencil_write_mask = false; - bool vk_dynamic_state_stencil_reference = false; + bool vk_dynamic_state_line_width = false; + bool vk_dynamic_state_stencil_compare_mask = false; + bool vk_dynamic_state_stencil_write_mask = false; + bool vk_dynamic_state_stencil_reference = false; + bool vk_dynamic_state_color_write_enable_ext = false; + + float line_width = 1.0f; + bool color_write_enable = true; PipelineStencilDynamicState stencil_front; PipelineStencilDynamicState stencil_back; @@ -111,20 +116,20 @@ struct PipelineDynamicParameters }; #pragma pack(pop) -struct PipelineAdditionalParameters -{ - ShaderBindParameters vs_bind; - ShaderBindParameters ps_bind; - ShaderBindParameters cs_bind; -}; +// 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; + VkPipelineLayout pipeline_layout = nullptr; + VkPipeline pipeline = nullptr; + const PipelineStaticParameters* static_params = nullptr; + PipelineDynamicParameters* dynamic_params = nullptr; + // const PipelineAdditionalParameters* additional_params = nullptr; }; class PipelineCache @@ -135,11 +140,9 @@ public: KYTY_CLASS_NO_COPY(PipelineCache); VulkanPipeline* CreatePipeline(VulkanFramebuffer* framebuffer, RenderColorInfo* color, RenderDepthInfo* depth, - const ShaderVertexInputInfo* vs_input_info, const VertexShaderInfo* vs_regs, - const ShaderPixelInputInfo* ps_input_info, const PixelShaderInfo* ps_regs, VkPrimitiveTopology topology, - uint32_t color_mask, const ModeControl& mc, const BlendControl& bc, const BlendColor& bclr, - const ScreenViewport& vp); - VulkanPipeline* CreatePipeline(const ShaderComputeInputInfo* input_info, const ComputeShaderInfo* cs_regs); + const ShaderVertexInputInfo* vs_input_info, HW::HardwareContext* ctx, + const ShaderPixelInputInfo* ps_input_info, VkPrimitiveTopology topology); + VulkanPipeline* CreatePipeline(const ShaderComputeInputInfo* input_info, const HW::ComputeShaderInfo* cs_regs); void DeletePipeline(VulkanPipeline* pipeline); void DeletePipelines(VulkanFramebuffer* framebuffer); void DeleteAllPipelines(); @@ -195,15 +198,17 @@ 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 /*, const ShaderBindParameters& bind_params*/); VulkanDescriptorSet* Allocate(Stage stage, int storage_buffers_num, int textures2d_sampled_num, int textures2d_storage_num, int samplers_num, int gds_buffers_num); void Free(VulkanDescriptorSet* set); VulkanDescriptorSet* GetDescriptor(Stage stage, VulkanBuffer** storage_buffers, VulkanImage** textures2d_sampled, - VulkanImage** textures2d_storage, uint64_t* samplers, VulkanBuffer** gds_buffers, - const ShaderBindResources& bind, const ShaderBindParameters& bind_params); + const bool* textures2d_depth, VulkanImage** textures2d_storage, uint64_t* samplers, + VulkanBuffer** gds_buffers, + const ShaderBindResources& bind /*, const ShaderBindParameters& bind_params*/); void FreeDescriptor(VulkanBuffer* buffer); void FreeDescriptor(VulkanImage* image); @@ -441,7 +446,7 @@ 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 UserConfig& uc) +static void uc_print(const char* func, const HW::UserConfig& uc) { printf("%s\n", func); @@ -453,94 +458,94 @@ static void uc_print(const char* func, const UserConfig& uc) // EXIT_NOT_IMPLEMENTED(uc.GetPrimType() != 4); //} -static void rt_print(const char* func, const RenderTarget& rt) +static void rt_print(const char* func, const HW::RenderTarget& rt) { printf("%s\n", func); - printf("\t base_addr = 0x%016" PRIx64 "\n", rt.base_addr); - printf("\t pitch_div8_minus1 = 0x%08" PRIx32 "\n", rt.pitch_div8_minus1); - printf("\t fmask_pitch_div8_minus1 = 0x%08" PRIx32 "\n", rt.fmask_pitch_div8_minus1); - printf("\t slice_div64_minus1 = 0x%08" PRIx32 "\n", rt.slice_div64_minus1); - printf("\t base_array_slice_index = 0x%08" PRIx32 "\n", rt.base_array_slice_index); - printf("\t last_array_slice_index = 0x%08" PRIx32 "\n", rt.last_array_slice_index); - printf("\t color_info.fmask_compression_enable = %s\n", rt.color_info.fmask_compression_enable ? "true" : "false"); - printf("\t color_info.fmask_compression_mode = 0x%08" PRIx32 "\n", rt.color_info.fmask_compression_mode); - printf("\t color_info.cmask_fast_clear_enable = %s\n", rt.color_info.cmask_fast_clear_enable ? "true" : "false"); - printf("\t color_info.dcc_compression_enable = %s\n", rt.color_info.dcc_compression_enable ? "true" : "false"); - printf("\t color_info.neo_mode = %s\n", rt.color_info.neo_mode ? "true" : "false"); - printf("\t color_info.cmask_tile_mode = 0x%08" PRIx32 "\n", rt.color_info.cmask_tile_mode); - printf("\t color_info.cmask_tile_mode_neo = 0x%08" PRIx32 "\n", rt.color_info.cmask_tile_mode_neo); - printf("\t color_info.format = 0x%08" PRIx32 "\n", rt.color_info.format); - printf("\t color_info.channel_type = 0x%08" PRIx32 "\n", rt.color_info.channel_type); - printf("\t color_info.channel_order = 0x%08" PRIx32 "\n", rt.color_info.channel_order); - printf("\t force_dest_alpha_to_one = %s\n", rt.force_dest_alpha_to_one ? "true" : "false"); - printf("\t tile_mode = 0x%08" PRIx32 "\n", rt.tile_mode); - printf("\t fmask_tile_mode = 0x%08" PRIx32 "\n", rt.fmask_tile_mode); - printf("\t num_samples = 0x%08" PRIx32 "\n", rt.num_samples); - printf("\t num_fragments = 0x%08" PRIx32 "\n", rt.num_fragments); - printf("\t dcc_max_uncompressed_block_size = 0x%08" PRIx32 "\n", rt.dcc_max_uncompressed_block_size); - printf("\t dcc_max_compressed_block_size = 0x%08" PRIx32 "\n", rt.dcc_max_compressed_block_size); - printf("\t dcc_min_compressed_block_size = 0x%08" PRIx32 "\n", rt.dcc_min_compressed_block_size); - printf("\t dcc_color_transform = 0x%08" PRIx32 "\n", rt.dcc_color_transform); - printf("\t dcc_enable_overwrite_combiner = %s\n", rt.dcc_enable_overwrite_combiner ? "true" : "false"); - printf("\t dcc_force_independent_blocks = %s\n", rt.dcc_force_independent_blocks ? "true" : "false"); - printf("\t cmask_addr = 0x%016" PRIx64 "\n", rt.cmask_addr); - printf("\t cmask_slice_minus1 = 0x%08" PRIx32 "\n", rt.cmask_slice_minus1); - printf("\t fmask_addr = 0x%016" PRIx64 "\n", rt.fmask_addr); - printf("\t fmask_slice_minus1 = 0x%08" PRIx32 "\n", rt.fmask_slice_minus1); - printf("\t clear_color_word0 = 0x%08" PRIx32 "\n", rt.clear_color_word0); - printf("\t clear_color_word1 = 0x%08" PRIx32 "\n", rt.clear_color_word1); - printf("\t dcc_addr = 0x%016" PRIx64 "\n", rt.dcc_addr); - printf("\t width = 0x%08" PRIx32 "\n", rt.width); - printf("\t height = 0x%08" PRIx32 "\n", rt.height); + printf("\t base.addr = 0x%016" PRIx64 "\n", rt.base.addr); + printf("\t pitch.pitch_div8_minus1 = 0x%08" PRIx32 "\n", rt.pitch.pitch_div8_minus1); + printf("\t pitch.fmask_pitch_div8_minus1 = 0x%08" PRIx32 "\n", rt.pitch.fmask_pitch_div8_minus1); + printf("\t slice.slice_div64_minus1 = 0x%08" PRIx32 "\n", rt.slice.slice_div64_minus1); + printf("\t view.base_array_slice_index = 0x%08" PRIx32 "\n", rt.view.base_array_slice_index); + printf("\t view.last_array_slice_index = 0x%08" PRIx32 "\n", rt.view.last_array_slice_index); + printf("\t info.fmask_compression_enable = %s\n", rt.info.fmask_compression_enable ? "true" : "false"); + printf("\t info.fmask_compression_mode = 0x%08" PRIx32 "\n", rt.info.fmask_compression_mode); + printf("\t info.cmask_fast_clear_enable = %s\n", rt.info.cmask_fast_clear_enable ? "true" : "false"); + printf("\t info.dcc_compression_enable = %s\n", rt.info.dcc_compression_enable ? "true" : "false"); + printf("\t info.neo_mode = %s\n", rt.info.neo_mode ? "true" : "false"); + printf("\t info.cmask_tile_mode = 0x%08" PRIx32 "\n", rt.info.cmask_tile_mode); + printf("\t info.cmask_tile_mode_neo = 0x%08" PRIx32 "\n", rt.info.cmask_tile_mode_neo); + printf("\t info.format = 0x%08" PRIx32 "\n", rt.info.format); + printf("\t info.channel_type = 0x%08" PRIx32 "\n", rt.info.channel_type); + printf("\t info.channel_order = 0x%08" PRIx32 "\n", rt.info.channel_order); + printf("\t attrib.force_dest_alpha_to_one = %s\n", rt.attrib.force_dest_alpha_to_one ? "true" : "false"); + printf("\t attrib.tile_mode = 0x%08" PRIx32 "\n", rt.attrib.tile_mode); + printf("\t attrib.fmask_tile_mode = 0x%08" PRIx32 "\n", rt.attrib.fmask_tile_mode); + printf("\t attrib.num_samples = 0x%08" PRIx32 "\n", rt.attrib.num_samples); + printf("\t attrib.num_fragments = 0x%08" PRIx32 "\n", rt.attrib.num_fragments); + printf("\t dcc.max_uncompressed_block_size = 0x%08" PRIx32 "\n", rt.dcc.max_uncompressed_block_size); + printf("\t dcc.max_compressed_block_size = 0x%08" PRIx32 "\n", rt.dcc.max_compressed_block_size); + printf("\t dcc.min_compressed_block_size = 0x%08" PRIx32 "\n", rt.dcc.min_compressed_block_size); + printf("\t dcc.color_transform = 0x%08" PRIx32 "\n", rt.dcc.color_transform); + printf("\t dcc.enable_overwrite_combiner = %s\n", rt.dcc.enable_overwrite_combiner ? "true" : "false"); + printf("\t dcc.force_independent_blocks = %s\n", rt.dcc.force_independent_blocks ? "true" : "false"); + printf("\t cmask.addr = 0x%016" PRIx64 "\n", rt.cmask.addr); + printf("\t cmask_slice.slice_minus1 = 0x%08" PRIx32 "\n", rt.cmask_slice.slice_minus1); + printf("\t fmask.addr = 0x%016" PRIx64 "\n", rt.fmask.addr); + printf("\t fmask_slice.slice_minus1 = 0x%08" PRIx32 "\n", rt.fmask_slice.slice_minus1); + printf("\t clear_word0.word0 = 0x%08" PRIx32 "\n", rt.clear_word0.word0); + printf("\t clear_word1.word1 = 0x%08" PRIx32 "\n", rt.clear_word1.word1); + printf("\t dcc_addr.addr = 0x%016" PRIx64 "\n", rt.dcc_addr.addr); + printf("\t size.width = 0x%08" PRIx32 "\n", rt.size.width); + printf("\t size.height = 0x%08" PRIx32 "\n", rt.size.height); } // NOLINTNEXTLINE(readability-function-cognitive-complexity) -static void rt_check(const RenderTarget& rt) +static void rt_check(const HW::RenderTarget& rt) { - if (rt.base_addr != 0) + if (rt.base.addr != 0) { - bool render_to_texture = (rt.tile_mode == 0x0d); + bool render_to_texture = (rt.attrib.tile_mode == 0x0d); // EXIT_NOT_IMPLEMENTED(rt.base_addr == 0); // EXIT_NOT_IMPLEMENTED(rt.pitch_div8_minus1 != 0x000000ef); // EXIT_NOT_IMPLEMENTED(rt.fmask_pitch_div8_minus1 != 0x000000ef); // EXIT_NOT_IMPLEMENTED(rt.slice_div64_minus1 != 0x000086ff); - EXIT_NOT_IMPLEMENTED(rt.base_array_slice_index != 0x00000000); - EXIT_NOT_IMPLEMENTED(rt.last_array_slice_index != 0x00000000); - EXIT_NOT_IMPLEMENTED(rt.color_info.fmask_compression_enable != false); - EXIT_NOT_IMPLEMENTED(rt.color_info.fmask_compression_mode != 0x00000000); - EXIT_NOT_IMPLEMENTED(rt.color_info.cmask_fast_clear_enable != false); - EXIT_NOT_IMPLEMENTED(rt.color_info.dcc_compression_enable != false); - EXIT_NOT_IMPLEMENTED(!render_to_texture && rt.color_info.neo_mode != Config::IsNeo()); - EXIT_NOT_IMPLEMENTED(rt.color_info.cmask_tile_mode != 0x00000000); - EXIT_NOT_IMPLEMENTED(rt.color_info.cmask_tile_mode_neo != 0x00000000); + EXIT_NOT_IMPLEMENTED(rt.view.base_array_slice_index != 0x00000000); + EXIT_NOT_IMPLEMENTED(rt.view.last_array_slice_index != 0x00000000); + EXIT_NOT_IMPLEMENTED(rt.info.fmask_compression_enable != false); + EXIT_NOT_IMPLEMENTED(rt.info.fmask_compression_mode != 0x00000000); + EXIT_NOT_IMPLEMENTED(rt.info.cmask_fast_clear_enable != false); + EXIT_NOT_IMPLEMENTED(rt.info.dcc_compression_enable != false); + EXIT_NOT_IMPLEMENTED(!render_to_texture && rt.info.neo_mode != Config::IsNeo()); + EXIT_NOT_IMPLEMENTED(rt.info.cmask_tile_mode != 0x00000000); + EXIT_NOT_IMPLEMENTED(rt.info.cmask_tile_mode_neo != 0x00000000); // EXIT_NOT_IMPLEMENTED(rt.format != 0x0000000a); // EXIT_NOT_IMPLEMENTED(rt.channel_type != 0x00000006); // EXIT_NOT_IMPLEMENTED(rt.channel_order != 0x00000001); - EXIT_NOT_IMPLEMENTED(rt.force_dest_alpha_to_one != false); + EXIT_NOT_IMPLEMENTED(rt.attrib.force_dest_alpha_to_one != false); // EXIT_NOT_IMPLEMENTED(rt.tile_mode != 0x0000000a); // EXIT_NOT_IMPLEMENTED(rt.fmask_tile_mode != 0x0000000a); - EXIT_NOT_IMPLEMENTED(rt.num_samples != 0x00000000); - EXIT_NOT_IMPLEMENTED(rt.num_fragments != 0x00000000); + EXIT_NOT_IMPLEMENTED(rt.attrib.num_samples != 0x00000000); + EXIT_NOT_IMPLEMENTED(rt.attrib.num_fragments != 0x00000000); // EXIT_NOT_IMPLEMENTED(rt.dcc_max_uncompressed_block_size != 0x00000002); - EXIT_NOT_IMPLEMENTED(rt.dcc_max_compressed_block_size != 0x00000000); - EXIT_NOT_IMPLEMENTED(rt.dcc_min_compressed_block_size != 0x00000000); - EXIT_NOT_IMPLEMENTED(rt.dcc_color_transform != 0x00000000); - EXIT_NOT_IMPLEMENTED(rt.dcc_enable_overwrite_combiner != false); - EXIT_NOT_IMPLEMENTED(rt.dcc_force_independent_blocks != false); - EXIT_NOT_IMPLEMENTED(rt.cmask_addr != 0x0000000000000000); - EXIT_NOT_IMPLEMENTED(rt.cmask_slice_minus1 != 0x00000000); - EXIT_NOT_IMPLEMENTED(rt.fmask_addr != 0x0000000000000000); - EXIT_NOT_IMPLEMENTED(rt.fmask_slice_minus1 != 0x00000000); - EXIT_NOT_IMPLEMENTED(rt.clear_color_word0 != 0x00000000); - EXIT_NOT_IMPLEMENTED(rt.clear_color_word1 != 0x00000000); - EXIT_NOT_IMPLEMENTED(rt.dcc_addr != 0x0000000000000000); + EXIT_NOT_IMPLEMENTED(rt.dcc.max_compressed_block_size != 0x00000000); + EXIT_NOT_IMPLEMENTED(rt.dcc.min_compressed_block_size != 0x00000000); + EXIT_NOT_IMPLEMENTED(rt.dcc.color_transform != 0x00000000); + EXIT_NOT_IMPLEMENTED(rt.dcc.enable_overwrite_combiner != false); + EXIT_NOT_IMPLEMENTED(rt.dcc.force_independent_blocks != false); + EXIT_NOT_IMPLEMENTED(rt.cmask.addr != 0x0000000000000000); + EXIT_NOT_IMPLEMENTED(rt.cmask_slice.slice_minus1 != 0x00000000); + EXIT_NOT_IMPLEMENTED(rt.fmask.addr != 0x0000000000000000); + EXIT_NOT_IMPLEMENTED(rt.fmask_slice.slice_minus1 != 0x00000000 && rt.fmask_slice.slice_minus1 != rt.slice.slice_div64_minus1); + EXIT_NOT_IMPLEMENTED(rt.clear_word0.word0 != 0x00000000); + EXIT_NOT_IMPLEMENTED(rt.clear_word1.word1 != 0x00000000); + EXIT_NOT_IMPLEMENTED(rt.dcc_addr.addr != 0x0000000000000000); // EXIT_NOT_IMPLEMENTED(rt.width != 0x00000780); // EXIT_NOT_IMPLEMENTED(rt.height != 0x00000438); } } -static void z_print(const char* func, const DepthRenderTarget& z) +static void z_print(const char* func, const HW::DepthRenderTarget& z) { printf("%s\n", func); @@ -584,7 +589,7 @@ static void z_print(const char* func, const DepthRenderTarget& z) } // NOLINTNEXTLINE(readability-function-cognitive-complexity) -static void z_check(const DepthRenderTarget& z) +static void z_check(const HW::DepthRenderTarget& z) { if (z.z_info.format == 0) { @@ -651,7 +656,7 @@ static void z_check(const DepthRenderTarget& z) } } -static void clip_print(const char* func, const ClipControl& c) +static void clip_print(const char* func, const HW::ClipControl& c) { printf("%s\n", func); @@ -669,7 +674,7 @@ static void clip_print(const char* func, const ClipControl& c) printf("\t force_viewport_index_from_vs_enable = %s\n", c.force_viewport_index_from_vs_enable ? "true" : "false"); } -static void clip_check(const ClipControl& c) +static void clip_check(const HW::ClipControl& c) { EXIT_NOT_IMPLEMENTED(c.user_clip_planes != 0); EXIT_NOT_IMPLEMENTED(c.user_clip_plane_mode != 0); @@ -685,7 +690,7 @@ static void clip_check(const ClipControl& c) EXIT_NOT_IMPLEMENTED(c.force_viewport_index_from_vs_enable != false); } -static void rc_print(const char* func, const RenderControl& c) +static void rc_print(const char* func, const HW::RenderControl& c) { printf("%s\n", func); @@ -698,18 +703,18 @@ static void rc_print(const char* func, const RenderControl& c) printf("\t copy_sample = %" PRIu8 "\n", c.copy_sample); } -static void rc_check(const RenderControl& c) +static void rc_check(const HW::RenderControl& c) { // EXIT_NOT_IMPLEMENTED(c.depth_clear_enable != false); // EXIT_NOT_IMPLEMENTED(c.stencil_clear_enable != false); EXIT_NOT_IMPLEMENTED(c.resummarize_enable != false); - EXIT_NOT_IMPLEMENTED(c.stencil_compress_disable != false); - EXIT_NOT_IMPLEMENTED(c.depth_compress_disable != false); + // EXIT_NOT_IMPLEMENTED(c.stencil_compress_disable != false); + // EXIT_NOT_IMPLEMENTED(c.depth_compress_disable != false); EXIT_NOT_IMPLEMENTED(c.copy_centroid != false); EXIT_NOT_IMPLEMENTED(c.copy_sample != 0); } -static void mc_print(const char* func, const ModeControl& c) +static void mc_print(const char* func, const HW::ModeControl& c) { printf("%s\n", func); @@ -726,7 +731,7 @@ static void mc_print(const char* func, const ModeControl& c) printf("\t persp_corr_dis = %s\n", c.persp_corr_dis ? "true" : "false"); } -static void mc_check(const ModeControl& c) +static void mc_check(const HW::ModeControl& c) { EXIT_NOT_IMPLEMENTED(c.cull_front != false); // EXIT_NOT_IMPLEMENTED(c.cull_back != false); @@ -741,7 +746,7 @@ static void mc_check(const ModeControl& c) EXIT_NOT_IMPLEMENTED(c.persp_corr_dis != false); } -static void bc_print(const char* func, const BlendControl& c, const BlendColor& color) +static void bc_print(const char* func, const HW::BlendControl& c, const HW::BlendColor& color, const HW::ColorControl& cc) { printf("%s\n", func); @@ -757,9 +762,11 @@ static void bc_print(const char* func, const BlendControl& c, const BlendColor& printf("\t green = %f\n", color.green); printf("\t blue = %f\n", color.blue); printf("\t alpha = %f\n", color.alpha); + printf("\t cc.mode = %" PRIu8 "\n", cc.mode); + printf("\t cc.op = %" PRIu8 "\n", cc.op); } -static void bc_check(const BlendControl& c, const BlendColor& color) +static void bc_check(const HW::BlendControl& c, const HW::BlendColor& color, const HW::ColorControl& cc) { // EXIT_NOT_IMPLEMENTED(c.color_srcblend != 0); EXIT_NOT_IMPLEMENTED(c.color_comb_fcn != 0); @@ -773,9 +780,11 @@ static void bc_check(const BlendControl& c, const BlendColor& color) EXIT_NOT_IMPLEMENTED(color.green != 0.0f); EXIT_NOT_IMPLEMENTED(color.blue != 0.0f); EXIT_NOT_IMPLEMENTED(color.alpha != 0.0f); + EXIT_NOT_IMPLEMENTED(cc.mode != 1 && cc.mode != 0); + EXIT_NOT_IMPLEMENTED(cc.op != 0xCC); } -static void d_print(const char* func, const DepthControl& c, const StencilControl& s, const StencilMask& sm) +static void d_print(const char* func, const HW::DepthControl& c, const HW::StencilControl& s, const HW::StencilMask& sm) { printf("%s\n", func); @@ -803,7 +812,7 @@ static void d_print(const char* func, const DepthControl& c, const StencilContro printf("\t stencil_opval_bf = %" PRIu8 "\n", sm.stencil_opval_bf); } -static void d_check(const DepthControl& c, const StencilControl& s, const StencilMask& /*sm*/) +static void d_check(const HW::DepthControl& c, const HW::StencilControl& s, const HW::StencilMask& /*sm*/) { // EXIT_NOT_IMPLEMENTED(c.stencil_enable != false); // EXIT_NOT_IMPLEMENTED(c.z_enable != false); @@ -829,7 +838,7 @@ static void d_check(const DepthControl& c, const StencilControl& s, const Stenci // EXIT_NOT_IMPLEMENTED(sm.stencil_opval_bf != 0); } -static void eqaa_print(const char* func, const EqaaControl& c) +static void eqaa_print(const char* func, const HW::EqaaControl& c) { printf("%s\n", func); @@ -843,7 +852,7 @@ static void eqaa_print(const char* func, const EqaaControl& c) printf("\t static_anchor_associations = %s\n", c.static_anchor_associations ? "true" : "false"); } -static void eqaa_check(const EqaaControl& c) +static void eqaa_check(const HW::EqaaControl& c) { EXIT_NOT_IMPLEMENTED(c.max_anchor_samples != 0); EXIT_NOT_IMPLEMENTED(c.ps_iter_samples != 0); @@ -852,10 +861,10 @@ static void eqaa_check(const EqaaControl& c) EXIT_NOT_IMPLEMENTED(c.high_quality_intersections != false); EXIT_NOT_IMPLEMENTED(c.incoherent_eqaa_reads != false); EXIT_NOT_IMPLEMENTED(c.interpolate_comp_z != false); - EXIT_NOT_IMPLEMENTED(c.static_anchor_associations != false); + // EXIT_NOT_IMPLEMENTED(c.static_anchor_associations != false); } -static void vp_print(const char* func, const ScreenViewport& vp) +static void vp_print(const char* func, const HW::ScreenViewport& vp) { printf("%s\n", func); @@ -868,19 +877,24 @@ static void vp_print(const char* func, const ScreenViewport& vp) 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 scissor_left = %d\n", vp.scissor_left); - printf("\t scissor_top = %d\n", vp.scissor_top); - printf("\t scissor_right = %d\n", vp.scissor_right); - printf("\t scissor_bottom = %d\n", vp.scissor_bottom); + 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"); } -static void vp_check(const ScreenViewport& vp) +static void vp_check(const HW::ScreenViewport& vp) { EXIT_NOT_IMPLEMENTED(vp.viewports[0].zmin != 0.000000); EXIT_NOT_IMPLEMENTED(vp.viewports[0].zmax != 1.000000); @@ -891,21 +905,22 @@ static void vp_check(const ScreenViewport& vp) // EXIT_NOT_IMPLEMENTED(vp.viewports[0].zscale != 0.500000); // EXIT_NOT_IMPLEMENTED(vp.viewports[0].zoffset != 0.500000); EXIT_NOT_IMPLEMENTED(vp.transform_control != 1087); - // EXIT_NOT_IMPLEMENTED(vp.scissor_left != 0); - // EXIT_NOT_IMPLEMENTED(vp.scissor_top != 0); - // EXIT_NOT_IMPLEMENTED(vp.scissor_right != 1920); - // EXIT_NOT_IMPLEMENTED(vp.scissor_bottom != 1080); + 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_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); // EXIT_NOT_IMPLEMENTED(vp.hw_offset_y != 32); // EXIT_NOT_IMPLEMENTED(fabsf(vp.guard_band_horz_clip - 33.133327f) > 0.001f); // EXIT_NOT_IMPLEMENTED(fabsf(vp.guard_band_vert_clip - 59.629623f) > 0.001f); 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); } -static void hw_check(const HardwareContext& hw) +static void hw_check(const HW::HardwareContext& hw) { - const auto& rt = hw.GetRenderTargets(0); + const auto& rt = hw.GetRenderTarget(0); const auto& bc = hw.GetBlendControl(0); const auto& bclr = hw.GetBlendColor(); const auto& vp = hw.GetScreenViewport(); @@ -917,6 +932,7 @@ static void hw_check(const HardwareContext& hw) const auto& sm = hw.GetStencilMask(); const auto& mc = hw.GetModeControl(); const auto& eqaa = hw.GetEqaaControl(); + const auto& cc = hw.GetColorControl(); rt_check(rt); vp_check(vp); @@ -925,7 +941,7 @@ static void hw_check(const HardwareContext& hw) rc_check(rc); d_check(d, s, sm); mc_check(mc); - bc_check(bc, bclr); + bc_check(bc, bclr, cc); eqaa_check(eqaa); EXIT_NOT_IMPLEMENTED(hw.GetRenderTargetMask() != 0xF && hw.GetRenderTargetMask() != 0x0); @@ -933,9 +949,9 @@ static void hw_check(const HardwareContext& hw) // EXIT_NOT_IMPLEMENTED(hw.GetStencilClearValue() != 0); } -static void hw_print(const HardwareContext& hw) +static void hw_print(const HW::HardwareContext& hw) { - const auto& rt = hw.GetRenderTargets(0); + const auto& rt = hw.GetRenderTarget(0); const auto& bc = hw.GetBlendControl(0); const auto& bclr = hw.GetBlendColor(); const auto& vp = hw.GetScreenViewport(); @@ -947,11 +963,13 @@ static void hw_print(const HardwareContext& hw) const auto& sm = hw.GetStencilMask(); const auto& mc = hw.GetModeControl(); const auto& eqaa = hw.GetEqaaControl(); + const auto& cc = hw.GetColorControl(); printf("HardwareContext\n"); - printf("\t GetRenderTargetMask() = 0x%08" PRIx32 "\n", hw.GetRenderTargetMask()); - printf("\t GetDepthClearValue() = %f\n", hw.GetDepthClearValue()); + printf("\t GetRenderTargetMask() = 0x%08" PRIx32 "\n", hw.GetRenderTargetMask()); + printf("\t GetDepthClearValue() = %f\n", hw.GetDepthClearValue()); printf("\t GetStencilClearValue() = %" PRIu8 "\n", hw.GetStencilClearValue()); + printf("\t GetLineWidth() = %f\n", hw.GetLineWidth()); rt_print("RenderTraget:", rt); z_print("DepthRenderTraget:", z); @@ -960,7 +978,7 @@ static void hw_print(const HardwareContext& hw) rc_print("RenderControl:", rc); d_print("DepthStencilControlMask:", d, s, sm); mc_print("ModeControl:", mc); - bc_print("BlendControl:", bc, bclr); + bc_print("BlendColorControl:", bc, bclr, cc); eqaa_print("EqaaControl:", eqaa); } @@ -1651,7 +1669,7 @@ 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, + uint32_t* push_constant_info_num, const ShaderBindResources& bind, /*const ShaderBindParameters& bind_params,*/ VkShaderStageFlags vk_stage, DescriptorCache::Stage stage) { EXIT_IF(set_layouts == nullptr); @@ -1678,7 +1696,7 @@ static void CreateLayout(VkDescriptorSetLayout* set_layouts, uint32_t* set_layou { EXIT_IF(bind.descriptor_set_slot != *set_layouts_num); - set_layouts[*set_layouts_num] = g_render_ctx->GetDescriptorCache()->GetDescriptorSetLayout(stage, bind, bind_params); + set_layouts[*set_layouts_num] = g_render_ctx->GetDescriptorCache()->GetDescriptorSetLayout(stage, bind /*, bind_params*/); (*set_layouts_num)++; } } @@ -1687,19 +1705,19 @@ 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/*, + const PipelineAdditionalParameters* additional_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); + // EXIT_IF(additional_params == nullptr); - auto* pipeline = new VulkanPipeline; - pipeline->additional_params = additional_params; - pipeline->static_params = static_params; - pipeline->dynamic_params = dynamic_params; + auto* pipeline = new VulkanPipeline; + // pipeline->additional_params = additional_params; + pipeline->static_params = static_params; + pipeline->dynamic_params = dynamic_params; auto* gctx = g_render_ctx->GetGraphicCtx(); @@ -1835,7 +1853,7 @@ static VulkanPipeline* CreatePipelineInternal(VkRenderPass render_pass, const Sh rasterizer.depthBiasConstantFactor = 0.0f; rasterizer.depthBiasClamp = 0.0f; rasterizer.depthBiasSlopeFactor = 0.0f; - rasterizer.lineWidth = 1.0f; + rasterizer.lineWidth = dynamic_params->line_width; VkPipelineMultisampleStateCreateInfo multisampling {}; multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; @@ -1876,9 +1894,17 @@ static VulkanPipeline* CreatePipelineInternal(VkRenderPass render_pass, const Sh color_blend_attachment.alphaBlendOp = (static_params->separate_alpha_blend ? get_blend_op(static_params->alpha_comb_fcn) : color_blend_attachment.colorBlendOp); + VkBool32 color_write_enable = (pipeline->dynamic_params->color_write_enable ? VK_TRUE : VK_FALSE); + + VkPipelineColorWriteCreateInfoEXT color_write {}; + color_write.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_WRITE_CREATE_INFO_EXT; + color_write.pNext = nullptr; + color_write.attachmentCount = 1; + color_write.pColorWriteEnables = &color_write_enable; + VkPipelineColorBlendStateCreateInfo color_blending {}; color_blending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; - color_blending.pNext = nullptr; + color_blending.pNext = &color_write; color_blending.flags = 0; color_blending.logicOpEnable = VK_FALSE; color_blending.logicOp = VK_LOGIC_OP_COPY; @@ -1896,9 +1922,9 @@ static VulkanPipeline* CreatePipelineInternal(VkRenderPass render_pass, const Sh uint32_t push_constant_info_num = 0; CreateLayout(set_layouts, &set_layouts_num, push_constant_info, &push_constant_info_num, vs_input_info->bind, - additional_params->vs_bind, VK_SHADER_STAGE_VERTEX_BIT, DescriptorCache::Stage::Vertex); + /*additional_params->vs_bind,*/ VK_SHADER_STAGE_VERTEX_BIT, DescriptorCache::Stage::Vertex); CreateLayout(set_layouts, &set_layouts_num, push_constant_info, &push_constant_info_num, ps_input_info->bind, - additional_params->ps_bind, VK_SHADER_STAGE_FRAGMENT_BIT, DescriptorCache::Stage::Pixel); + /*additional_params->ps_bind,*/ VK_SHADER_STAGE_FRAGMENT_BIT, DescriptorCache::Stage::Pixel); VkPipelineLayoutCreateInfo pipeline_layout_info {}; pipeline_layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; @@ -1943,6 +1969,10 @@ static VulkanPipeline* CreatePipelineInternal(VkRenderPass render_pass, const Sh VkDynamicState dynamic_states[8] = {}; uint32_t dynamic_states_count = 0; + if (dynamic_params->vk_dynamic_state_line_width) + { + dynamic_states[dynamic_states_count++] = VK_DYNAMIC_STATE_LINE_WIDTH; + } if (dynamic_params->vk_dynamic_state_stencil_compare_mask) { dynamic_states[dynamic_states_count++] = VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK; @@ -1955,6 +1985,10 @@ static VulkanPipeline* CreatePipelineInternal(VkRenderPass render_pass, const Sh { dynamic_states[dynamic_states_count++] = VK_DYNAMIC_STATE_STENCIL_WRITE_MASK; } + if (dynamic_params->vk_dynamic_state_color_write_enable_ext) + { + dynamic_states[dynamic_states_count++] = VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT; + } VkPipelineDynamicStateCreateInfo dynamic_state {}; dynamic_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; @@ -1998,18 +2032,18 @@ 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/*, + const PipelineAdditionalParameters* additional_params*/) { EXIT_IF(g_render_ctx == nullptr); EXIT_IF(static_params == nullptr); EXIT_IF(dynamic_params == nullptr); - EXIT_IF(additional_params == nullptr); + // EXIT_IF(additional_params == nullptr); - auto* pipeline = new VulkanPipeline; - pipeline->additional_params = additional_params; - pipeline->static_params = static_params; - pipeline->dynamic_params = dynamic_params; + auto* pipeline = new VulkanPipeline; + // pipeline->additional_params = additional_params; + pipeline->static_params = static_params; + pipeline->dynamic_params = dynamic_params; auto* gctx = g_render_ctx->GetGraphicCtx(); @@ -2043,7 +2077,8 @@ static VulkanPipeline* CreatePipelineInternal(const ShaderComputeInputInfo* inpu VkPushConstantRange push_constant_info[1]; uint32_t push_constant_info_num = 0; - CreateLayout(set_layouts, &set_layouts_num, push_constant_info, &push_constant_info_num, input_info->bind, additional_params->cs_bind, + CreateLayout(set_layouts, &set_layouts_num, push_constant_info, &push_constant_info_num, + input_info->bind, /*additional_params->cs_bind,*/ VK_SHADER_STAGE_COMPUTE_BIT, DescriptorCache::Stage::Compute); VkPipelineLayoutCreateInfo pipeline_layout_info {}; @@ -2089,18 +2124,18 @@ 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->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; + // delete p.pipeline->additional_params; - p.static_params = nullptr; - p.dynamic_params = nullptr; - p.pipeline->additional_params = nullptr; + p.static_params = nullptr; + p.dynamic_params = nullptr; + // p.pipeline->additional_params = nullptr; auto* gctx = g_render_ctx->GetGraphicCtx(); @@ -2121,10 +2156,19 @@ bool PipelineStaticParameters::operator==(const PipelineStaticParameters& other) bool PipelineDynamicParameters::operator==(const PipelineDynamicParameters& other) const { - EXIT_IF(vk_dynamic_state_stencil_compare_mask != other.vk_dynamic_state_stencil_compare_mask || + EXIT_IF(vk_dynamic_state_line_width != other.vk_dynamic_state_line_width || + vk_dynamic_state_stencil_compare_mask != other.vk_dynamic_state_stencil_compare_mask || vk_dynamic_state_stencil_write_mask != other.vk_dynamic_state_stencil_write_mask || - vk_dynamic_state_stencil_reference != other.vk_dynamic_state_stencil_reference); + vk_dynamic_state_stencil_reference != other.vk_dynamic_state_stencil_reference || + vk_dynamic_state_color_write_enable_ext != other.vk_dynamic_state_color_write_enable_ext); + if (!vk_dynamic_state_line_width) + { + if (line_width != other.line_width) + { + return false; + } + } if (!vk_dynamic_state_stencil_compare_mask) { if (stencil_front.compareMask != other.stencil_front.compareMask || stencil_back.compareMask != other.stencil_back.compareMask) @@ -2146,6 +2190,13 @@ bool PipelineDynamicParameters::operator==(const PipelineDynamicParameters& othe return false; } } + if (!vk_dynamic_state_color_write_enable_ext) + { + if (color_write_enable != other.color_write_enable) + { + return false; + } + } return true; } @@ -2164,29 +2215,34 @@ VulkanPipeline* PipelineCache::Find(const Pipeline& p) const } VulkanPipeline* PipelineCache::CreatePipeline(VulkanFramebuffer* framebuffer, RenderColorInfo* color, RenderDepthInfo* depth, - const ShaderVertexInputInfo* vs_input_info, const VertexShaderInfo* vs_regs, - const ShaderPixelInputInfo* ps_input_info, const PixelShaderInfo* ps_regs, - VkPrimitiveTopology topology, uint32_t color_mask, const ModeControl& mc, - const BlendControl& bc, const BlendColor& bclr, const ScreenViewport& vp) + const ShaderVertexInputInfo* vs_input_info, HW::HardwareContext* ctx, + const ShaderPixelInputInfo* ps_input_info, VkPrimitiveTopology topology) { KYTY_PROFILER_BLOCK("PipelineCache::CreatePipeline(Gfx)", profiler::colors::DeepOrangeA200); EXIT_IF(framebuffer == nullptr); - EXIT_IF(vs_regs == nullptr); - EXIT_IF(ps_regs == nullptr); EXIT_IF(depth == nullptr); EXIT_IF(color == nullptr); Core::LockGuard lock(m_mutex); + const auto& vs_regs = ctx->GetVs(); + const auto& ps_regs = ctx->GetPs(); + const HW::BlendColor& bclr = ctx->GetBlendColor(); + const HW::ScreenViewport& vp = ctx->GetScreenViewport(); + const auto& bc = ctx->GetBlendControl(0); + uint32_t color_mask = ctx->GetRenderTargetMask(); + const HW::ModeControl& mc = ctx->GetModeControl(); + const auto& cc = ctx->GetColorControl(); + if (Config::GetPrintfDirection() != Log::Direction::Silent) { ShaderDbgDumpInputInfo(vs_input_info); ShaderDbgDumpInputInfo(ps_input_info); } - auto vs_id = ShaderGetIdVS(vs_regs, vs_input_info); - auto ps_id = ShaderGetIdPS(ps_regs, ps_input_info); + auto vs_id = ShaderGetIdVS(&vs_regs, vs_input_info); + auto ps_id = ShaderGetIdPS(&ps_regs, ps_input_info); Pipeline p {}; p.render_pass_id = framebuffer->render_pass_id; @@ -2195,9 +2251,11 @@ VulkanPipeline* PipelineCache::CreatePipeline(VulkanFramebuffer* framebuffer, Re p.static_params = new PipelineStaticParameters; p.dynamic_params = new PipelineDynamicParameters; + p.dynamic_params->vk_dynamic_state_line_width = true; p.dynamic_params->vk_dynamic_state_stencil_compare_mask = true; p.dynamic_params->vk_dynamic_state_stencil_reference = true; p.dynamic_params->vk_dynamic_state_stencil_write_mask = true; + p.dynamic_params->color_write_enable = true; EXIT_NOT_IMPLEMENTED(depth->depth_test_enable && ps_input_info->ps_execute_on_noop); @@ -2207,10 +2265,10 @@ VulkanPipeline* PipelineCache::CreatePipeline(VulkanFramebuffer* framebuffer, Re p.static_params->viewport_offset[0] = vp.viewports[0].xoffset; p.static_params->viewport_offset[1] = vp.viewports[0].yoffset; p.static_params->viewport_offset[2] = vp.viewports[0].zoffset; - p.static_params->scissor_ltrb[0] = vp.scissor_left; - p.static_params->scissor_ltrb[1] = vp.scissor_top; - p.static_params->scissor_ltrb[2] = vp.scissor_right; - p.static_params->scissor_ltrb[3] = vp.scissor_bottom; + p.static_params->scissor_ltrb[0] = vp.screen_scissor_left; + p.static_params->scissor_ltrb[1] = vp.screen_scissor_top; + p.static_params->scissor_ltrb[2] = vp.screen_scissor_right; + p.static_params->scissor_ltrb[3] = vp.screen_scissor_bottom; p.static_params->topology = topology; p.static_params->with_depth = (depth->format != VK_FORMAT_UNDEFINED && depth->vulkan_buffer != nullptr); p.static_params->depth_test_enable = depth->depth_test_enable; @@ -2239,8 +2297,10 @@ VulkanPipeline* PipelineCache::CreatePipeline(VulkanFramebuffer* framebuffer, Re p.static_params->blend_color_blue = bclr.blue; p.static_params->blend_color_alpha = bclr.alpha; - p.dynamic_params->stencil_front = depth->stencil_dynamic_front; - p.dynamic_params->stencil_back = depth->stencil_dynamic_back; + p.dynamic_params->line_width = ctx->GetLineWidth(); + p.dynamic_params->stencil_front = depth->stencil_dynamic_front; + p.dynamic_params->stencil_back = depth->stencil_dynamic_back; + p.dynamic_params->color_write_enable = (cc.mode == 1); auto* found = Find(p); @@ -2252,13 +2312,13 @@ VulkanPipeline* PipelineCache::CreatePipeline(VulkanFramebuffer* framebuffer, Re return found; } - auto vs_code = ShaderParseVS(vs_regs); - auto ps_code = ShaderParsePS(ps_regs); + auto vs_code = ShaderParseVS(&vs_regs); + auto ps_code = ShaderParsePS(&ps_regs); - auto* params2 = new PipelineAdditionalParameters; + // auto* params2 = new PipelineAdditionalParameters; - params2->vs_bind = ShaderGetBindParametersVS(vs_code, vs_input_info); - params2->ps_bind = ShaderGetBindParametersPS(ps_code, ps_input_info); + // 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); @@ -2267,7 +2327,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 /*, params2*/); EXIT_NOT_IMPLEMENTED(p.pipeline == nullptr); @@ -2298,7 +2358,7 @@ VulkanPipeline* PipelineCache::CreatePipeline(VulkanFramebuffer* framebuffer, Re return p.pipeline; } -VulkanPipeline* PipelineCache::CreatePipeline(const ShaderComputeInputInfo* input_info, const ComputeShaderInfo* cs_regs) +VulkanPipeline* PipelineCache::CreatePipeline(const ShaderComputeInputInfo* input_info, const HW::ComputeShaderInfo* cs_regs) { KYTY_PROFILER_BLOCK("PipelineCache::CreatePipeline(Compute)", profiler::colors::RedA100); @@ -2315,9 +2375,11 @@ VulkanPipeline* PipelineCache::CreatePipeline(const ShaderComputeInputInfo* inpu p.static_params = new PipelineStaticParameters; p.dynamic_params = new PipelineDynamicParameters; + p.dynamic_params->vk_dynamic_state_line_width = true; p.dynamic_params->vk_dynamic_state_stencil_compare_mask = true; p.dynamic_params->vk_dynamic_state_stencil_reference = true; p.dynamic_params->vk_dynamic_state_stencil_write_mask = true; + p.dynamic_params->color_write_enable = true; auto* found = Find(p); @@ -2331,14 +2393,14 @@ VulkanPipeline* PipelineCache::CreatePipeline(const ShaderComputeInputInfo* inpu auto cs_code = ShaderParseCS(cs_regs); - auto* params2 = new PipelineAdditionalParameters; + // auto* params2 = new PipelineAdditionalParameters; - params2->cs_bind = ShaderGetBindParametersCS(cs_code, input_info); + // params2->cs_bind = ShaderGetBindParametersCS(cs_code, input_info); auto cs_shader = ShaderRecompileCS(cs_code, input_info); EXIT_IF(cs_shader.IsEmpty()); - p.pipeline = CreatePipelineInternal(input_info, cs_shader, p.static_params, p.dynamic_params, params2); + p.pipeline = CreatePipelineInternal(input_info, cs_shader, p.static_params, p.dynamic_params /*, params2*/); EXIT_NOT_IMPLEMENTED(p.pipeline == nullptr); @@ -2661,14 +2723,15 @@ void DescriptorCache::Free(VulkanDescriptorSet* set) // NOLINTNEXTLINE(readability-function-cognitive-complexity) VulkanDescriptorSet* DescriptorCache::GetDescriptor(Stage stage, VulkanBuffer** storage_buffers, VulkanImage** textures2d_sampled, - VulkanImage** textures2d_storage, uint64_t* samplers, VulkanBuffer** gds_buffers, - const ShaderBindResources& bind, const ShaderBindParameters& bind_params) + const bool* textures2d_depth, VulkanImage** textures2d_storage, uint64_t* samplers, + VulkanBuffer** gds_buffers, + const ShaderBindResources& bind /*, const ShaderBindParameters& bind_params*/) { KYTY_PROFILER_BLOCK("DescriptorCache::GetDescriptor"); int storage_buffers_num = bind.storage_buffers.buffers_num; - int textures2d_sampled_num = bind_params.textures2d_sampled_num; - int textures2d_storage_num = bind_params.textures2d_storage_num; + int textures2d_sampled_num = bind.textures2D.textures2d_sampled_num; + int textures2d_storage_num = bind.textures2D.textures2d_storage_num; int samplers_num = bind.samplers.samplers_num; int gds_buffers_num = bind.gds_pointers.pointers_num; @@ -2763,9 +2826,17 @@ VulkanDescriptorSet* DescriptorCache::GetDescriptor(Stage stage, VulkanBuffer** VkDescriptorImageInfo texture2d_sampled_info[TEXTURES_SAMPLED_MAX] {}; for (int i = 0; i < textures2d_sampled_num; i++) { - texture2d_sampled_info[i].sampler = nullptr; - texture2d_sampled_info[i].imageView = textures2d_sampled[i]->image_view; - texture2d_sampled_info[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + if (textures2d_depth[i]) + { + texture2d_sampled_info[i].sampler = nullptr; + texture2d_sampled_info[i].imageView = static_cast(textures2d_sampled[i])->texture_view; + texture2d_sampled_info[i].imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL; + } else + { + texture2d_sampled_info[i].sampler = nullptr; + texture2d_sampled_info[i].imageView = textures2d_sampled[i]->image_view; + texture2d_sampled_info[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + } } VkDescriptorImageInfo texture2d_storage_info[TEXTURES_STORAGE_MAX] {}; @@ -2969,12 +3040,12 @@ void DescriptorCache::FreeDescriptor(VulkanImage* image) } } -VkDescriptorSetLayout DescriptorCache::GetDescriptorSetLayout(Stage stage, const ShaderBindResources& bind, - const ShaderBindParameters& bind_params) +VkDescriptorSetLayout DescriptorCache::GetDescriptorSetLayout(Stage stage, const ShaderBindResources& bind/*, + const ShaderBindParameters& bind_params*/) { int storage_buffers_num = bind.storage_buffers.buffers_num; - int textures2d_sampled_num = bind_params.textures2d_sampled_num; - int textures2d_storage_num = bind_params.textures2d_storage_num; + int textures2d_sampled_num = bind.textures2D.textures2d_sampled_num; + int textures2d_storage_num = bind.textures2D.textures2d_storage_num; int samplers_num = bind.samplers.samplers_num; int gds_buffers_num = bind.gds_pointers.pointers_num; @@ -3115,7 +3186,143 @@ static void get_stencil_state(PipelineStencilStaticState* s, PipelineStencilDyna } } -static void FindRenderDepthInfo(CommandBuffer* /*buffer*/, const HardwareContext& hw, RenderDepthInfo* r) +static Vector FindRenderTexture(uint64_t vaddr, uint64_t size, bool exact) +{ + KYTY_PROFILER_FUNCTION(); + + Vector ret; + + auto objects = GpuMemoryFindObjects(vaddr, size, exact, false); + + for (const auto& obj: objects) + { + if (obj.type == GpuMemoryObjectType::RenderTexture) + { + ret.Add(static_cast(obj.obj)); + } + } + + return ret; +} + +static Vector FindDepthStencil(uint64_t vaddr, uint64_t size, bool exact) +{ + KYTY_PROFILER_FUNCTION(); + + Vector ret; + + auto objects = GpuMemoryFindObjects(vaddr, size, exact, true); + + for (const auto& obj: objects) + { + if (obj.type == GpuMemoryObjectType::DepthStencilBuffer) + { + ret.Add(static_cast(obj.obj)); + } + } + + return ret; +} + +void GraphicsRenderMemoryBarrier(CommandBuffer* buffer) +{ + EXIT_IF(buffer == nullptr); + EXIT_IF(buffer->IsInvalid()); + + Core::LockGuard lock(g_render_ctx->GetMutex()); + + auto* vk_buffer = buffer->GetPool()->buffers[buffer->GetIndex()]; + + VkMemoryBarrier mem_barrier {}; + mem_barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER; + mem_barrier.pNext = nullptr; + mem_barrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT; + mem_barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; + + vkCmdPipelineBarrier(vk_buffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &mem_barrier, 0, nullptr, 0, + nullptr); +} + +static void GraphicsRenderRenderTextureBarrier(VkCommandBuffer vk_buffer, VulkanImage* image) +{ + EXIT_IF(image == nullptr); + + if (image->layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) + { + VkImageMemoryBarrier image_memory_barrier {}; + image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + image_memory_barrier.pNext = nullptr; + image_memory_barrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT; + image_memory_barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; + image_memory_barrier.oldLayout = image->layout; + image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + image_memory_barrier.image = image->image; + image_memory_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + image_memory_barrier.subresourceRange.baseMipLevel = 0; + image_memory_barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + image_memory_barrier.subresourceRange.baseArrayLayer = 0; + image_memory_barrier.subresourceRange.layerCount = 1; + + vkCmdPipelineBarrier(vk_buffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, + &image_memory_barrier); + + image->layout = image_memory_barrier.newLayout; + } +} + +static void GraphicsRenderDepthStencilBarrier(VkCommandBuffer vk_buffer, VulkanImage* image) +{ + EXIT_IF(image == nullptr); + + if (image->layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) + { + VkImageMemoryBarrier image_memory_barrier {}; + image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + image_memory_barrier.pNext = nullptr; + image_memory_barrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT; + image_memory_barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; + image_memory_barrier.oldLayout = image->layout; + image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL; + image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + image_memory_barrier.image = image->image; + image_memory_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + image_memory_barrier.subresourceRange.baseMipLevel = 0; + image_memory_barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + image_memory_barrier.subresourceRange.baseArrayLayer = 0; + image_memory_barrier.subresourceRange.layerCount = 1; + + vkCmdPipelineBarrier(vk_buffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, + &image_memory_barrier); + + image->layout = image_memory_barrier.newLayout; + } +} + +void GraphicsRenderRenderTextureBarrier(CommandBuffer* buffer, uint64_t vaddr, uint64_t size) +{ + EXIT_IF(buffer == nullptr); + EXIT_IF(buffer->IsInvalid()); + + Core::LockGuard lock(g_render_ctx->GetMutex()); + + auto* vk_buffer = buffer->GetPool()->buffers[buffer->GetIndex()]; + + auto images = FindRenderTexture(vaddr, size, false); + + for (auto* image: images) + { + GraphicsRenderRenderTextureBarrier(vk_buffer, image); + } +} + +// NOLINTNEXTLINE(readability-function-cognitive-complexity) +static void FindRenderDepthInfo(CommandBuffer* /*buffer*/, const HW::HardwareContext& hw, RenderDepthInfo* r) { KYTY_PROFILER_FUNCTION(); @@ -3127,6 +3334,7 @@ static void FindRenderDepthInfo(CommandBuffer* /*buffer*/, const HardwareContext const auto& dc = hw.GetDepthControl(); const auto& sc = hw.GetStencilControl(); const auto& sm = hw.GetStencilMask(); + const auto& cc = hw.GetColorControl(); uint32_t size = 0; uint32_t stencil_size = 0; @@ -3144,6 +3352,8 @@ static void FindRenderDepthInfo(CommandBuffer* /*buffer*/, const HardwareContext bool htile = z.z_info.tile_surface_enable; + 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); @@ -3156,15 +3366,18 @@ static void FindRenderDepthInfo(CommandBuffer* /*buffer*/, const HardwareContext EXIT_NOT_IMPLEMENTED((z.pitch_div8_minus1 + 1) * 8 != pitch); } - switch (z.z_info.format * 2 + z.stencil_info.format) + if (dc.z_enable || dc.z_write_enable || dc.stencil_enable || decompress) { - case 0: r->format = VK_FORMAT_UNDEFINED; break; - case 1: /*r->format = VK_FORMAT_S8_UINT*/ EXIT("Unsupported format: VK_FORMAT_S8_UINT\n"); break; - case 2: r->format = VK_FORMAT_D16_UNORM; break; - case 3: r->format = VK_FORMAT_D24_UNORM_S8_UINT; break; - case 6: r->format = VK_FORMAT_D32_SFLOAT; break; - case 7: r->format = VK_FORMAT_D32_SFLOAT_S8_UINT; break; - default: EXIT("unknown z and stencil format: %u, %u\n", z.z_info.format, z.stencil_info.format); + switch (z.z_info.format * 2 + z.stencil_info.format) + { + case 0: r->format = VK_FORMAT_UNDEFINED; break; + case 1: /*r->format = VK_FORMAT_S8_UINT*/ EXIT("Unsupported format: VK_FORMAT_S8_UINT\n"); break; + case 2: r->format = VK_FORMAT_D16_UNORM; break; + case 3: r->format = VK_FORMAT_D24_UNORM_S8_UINT; break; + case 6: r->format = VK_FORMAT_D32_SFLOAT; break; + case 7: r->format = VK_FORMAT_D32_SFLOAT_S8_UINT; break; + default: EXIT("unknown z and stencil format: %u, %u\n", z.z_info.format, z.stencil_info.format); + } } r->htile = htile; @@ -3251,20 +3464,25 @@ static void FindRenderDepthInfo(CommandBuffer* /*buffer*/, const HardwareContext GpuMemoryCreateObject(g_render_ctx->GetGraphicCtx(), nullptr, r->vaddr, r->size, r->vaddr_num, vulkan_buffer_info)); EXIT_NOT_IMPLEMENTED(r->vulkan_buffer == nullptr); + + if ((cc.mode == 0 && cc.op == 0xCC) || (dc.z_enable || dc.z_write_enable)) + { + r->vulkan_buffer->compressed = htile && !decompress; + } } } // NOLINTNEXTLINE(readability-function-cognitive-complexity) -static void FindRenderColorInfo(CommandBuffer* buffer, const HardwareContext& hw, RenderColorInfo* r) +static void FindRenderColorInfo(CommandBuffer* buffer, const HW::HardwareContext& hw, RenderColorInfo* r) { KYTY_PROFILER_FUNCTION(); EXIT_IF(r == nullptr); - const auto& rt = hw.GetRenderTargets(0); + const auto& rt = hw.GetRenderTarget(0); auto mask = hw.GetRenderTargetMask(); - if (rt.base_addr == 0 || mask == 0) + if (rt.base.addr == 0 || mask == 0) { // No color output r->type = RenderColorType::NoColorOutput; @@ -3274,40 +3492,45 @@ static void FindRenderColorInfo(CommandBuffer* buffer, const HardwareContext& hw return; } - auto width = rt.width; - auto height = rt.height; - auto pitch = (rt.pitch_div8_minus1 + 1) * 8; - auto size = (rt.slice_div64_minus1 + 1) * 64 * 4; + auto width = rt.size.width; + auto height = rt.size.height; + auto pitch = (rt.pitch.pitch_div8_minus1 + 1) * 8; + auto size = (rt.slice.slice_div64_minus1 + 1) * 64 * 4; bool tile = false; uint32_t format = 0; bool render_to_texture = false; - if (rt.tile_mode == 0x8) + if (rt.attrib.tile_mode == 0x8) { tile = false; - } else if (rt.tile_mode == 0xa) + } else if (rt.attrib.tile_mode == 0xa) { tile = true; - } else if (rt.tile_mode == 0xd || rt.tile_mode == 0xe) + + if (rt.info.format == 0xa && rt.info.channel_type == 0x0 && rt.info.channel_order == 0x0 && rt.size.width == rt.size.height) + { + render_to_texture = true; + } + } else if (rt.attrib.tile_mode == 0xd || rt.attrib.tile_mode == 0xe) { tile = true; render_to_texture = true; } else { - EXIT("unknown tile mode: %u\n", rt.tile_mode); + EXIT("unknown tile mode: %u\n", rt.attrib.tile_mode); } if (render_to_texture) { - if (rt.color_info.format == 0xa && rt.color_info.channel_type == 0x0 && rt.color_info.channel_order == 0x0) + if (rt.info.format == 0xa && rt.info.channel_type == 0x0 && rt.info.channel_order == 0x0) { // Render to texture - RenderTextureObject vulkan_buffer_info(RenderTextureFormat::R8G8B8A8Unorm, width, height, tile, rt.color_info.neo_mode, pitch); + RenderTextureObject vulkan_buffer_info(RenderTextureFormat::R8G8B8A8Unorm, 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(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; + r->base_addr = rt.base.addr; r->vulkan_buffer = buffer_vulkan; r->buffer_size = size; } else @@ -3316,7 +3539,7 @@ static void FindRenderColorInfo(CommandBuffer* buffer, const HardwareContext& hw } } else { - if (rt.color_info.format == 0xa && rt.color_info.channel_type == 0x6 && rt.color_info.channel_order == 0x1) + if (rt.info.format == 0xa && rt.info.channel_type == 0x6 && rt.info.channel_order == 0x1) { format = 0x80000000; } else @@ -3324,16 +3547,16 @@ static void FindRenderColorInfo(CommandBuffer* buffer, const HardwareContext& hw EXIT("unknown format"); } - auto video_image = VideoOut::VideoOutGetImage(rt.base_addr); + auto video_image = VideoOut::VideoOutGetImage(rt.base.addr); if (video_image.image == nullptr) { // 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(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; + r->base_addr = rt.base.addr; r->vulkan_buffer = buffer_vulkan; r->buffer_size = size; } else @@ -3342,7 +3565,7 @@ static void FindRenderColorInfo(CommandBuffer* buffer, const HardwareContext& hw EXIT_NOT_IMPLEMENTED(video_image.buffer_size != size); EXIT_NOT_IMPLEMENTED(video_image.buffer_pitch != pitch); r->type = RenderColorType::DisplayBuffer; - r->base_addr = rt.base_addr; + r->base_addr = rt.base.addr; r->vulkan_buffer = video_image.image; r->buffer_size = video_image.buffer_size; } @@ -3375,25 +3598,6 @@ static void InvalidateMemoryObject(const RenderDepthInfo& r) } } -static Vector FindRenderTexture(uint64_t vaddr, uint64_t size, bool exact) -{ - KYTY_PROFILER_FUNCTION(); - - Vector ret; - - auto objects = GpuMemoryFindObjects(vaddr, size, exact); - - for (const auto& obj: objects) - { - if (obj.type == GpuMemoryObjectType::RenderTexture) - { - ret.Add(static_cast(obj.obj)); - } - } - - return ret; -} - static void PrepareStorageBuffers(CommandBuffer* buffer, const ShaderStorageResources& storage_buffers, VulkanBuffer** buffers, uint32_t** sgprs) { @@ -3456,7 +3660,7 @@ static void PrepareStorageBuffers(CommandBuffer* buffer, const ShaderStorageReso // NOLINTNEXTLINE(readability-function-cognitive-complexity) static void PrepareTextures(CommandBuffer* buffer, const ShaderTextureResources& textures, VulkanImage** images_sampled, - VulkanImage** images_storage, uint32_t** sgprs, const bool* without_sampler) + VulkanImage** images_storage, bool* images_depth, uint32_t** sgprs /*, const bool* without_sampler*/) { KYTY_PROFILER_FUNCTION(); @@ -3464,19 +3668,19 @@ static void PrepareTextures(CommandBuffer* buffer, const ShaderTextureResources& EXIT_IF(images_storage == nullptr); EXIT_IF(sgprs == nullptr); EXIT_IF(*sgprs == nullptr); - EXIT_IF(without_sampler == nullptr); + // EXIT_IF(without_sampler == nullptr); int index_sampled = 0; int index_storage = 0; for (int i = 0; i < textures.textures_num; i++) { - auto r = textures.textures[i]; + auto r = textures.desc[i].texture; EXIT_NOT_IMPLEMENTED(r.Base() == 0); EXIT_NOT_IMPLEMENTED(r.MinLod() != 0); - EXIT_NOT_IMPLEMENTED(r.Dfmt() != 10 && r.Dfmt() != 37); - EXIT_NOT_IMPLEMENTED(r.Nfmt() != 9 && r.Nfmt() != 0); + EXIT_NOT_IMPLEMENTED(r.Dfmt() != 10 && r.Dfmt() != 37 && r.Dfmt() != 4); + EXIT_NOT_IMPLEMENTED(r.Nfmt() != 9 && r.Nfmt() != 0 && r.Nfmt() != 7); // EXIT_NOT_IMPLEMENTED(r.Width() != 511); // EXIT_NOT_IMPLEMENTED(r.Height() != 511); EXIT_NOT_IMPLEMENTED(r.PerfMod() != 7 && r.PerfMod() != 0); @@ -3487,7 +3691,7 @@ 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)); + EXIT_NOT_IMPLEMENTED(!(r.TilingIdx() == 8 || r.TilingIdx() == 13 || r.TilingIdx() == 14 || r.TilingIdx() == 2)); // 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); @@ -3501,8 +3705,7 @@ static void PrepareTextures(CommandBuffer* buffer, const ShaderTextureResources& bool read_only = (r.MemoryType() == 0x10); - EXIT_NOT_IMPLEMENTED(read_only && !(textures.usages[i] == ShaderTextureUsage::ReadOnly)); - // EXIT_NOT_IMPLEMENTED(!read_only && !(textures.usages[i] == ShaderTextureUsage::ReadWrite)); + EXIT_NOT_IMPLEMENTED(read_only && !(textures.desc[i].usage == ShaderTextureUsage::ReadOnly)); auto addr = r.Base(); uint32_t size = 0; @@ -3516,25 +3719,52 @@ static void PrepareTextures(CommandBuffer* buffer, const ShaderTextureResources& 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); - auto rtex = FindRenderTexture(addr, size, true); + VulkanImage* tex = nullptr; + bool render_texture = false; + bool depth_texture = false; - EXIT_NOT_IMPLEMENTED(rtex.Size() > 1); - - VulkanImage* tex = (!rtex.IsEmpty() ? rtex.At(0) : nullptr); - - if (tex == nullptr) + if (check_depth_texture) { - if (without_sampler[i]) + auto dtex = FindDepthStencil(addr, size, true); + depth_texture = !dtex.IsEmpty(); + if (depth_texture) { + EXIT_NOT_IMPLEMENTED(dtex.Size() > 1); + EXIT_NOT_IMPLEMENTED(swizzle != 0x04040404); + EXIT_NOT_IMPLEMENTED(dtex.At(0)->compressed); + tex = dtex.At(0); + } + } else + { + auto rtex = FindRenderTexture(addr, size, true); + render_texture = !rtex.IsEmpty(); + if (render_texture) + { + EXIT_NOT_IMPLEMENTED(rtex.Size() > 1); + EXIT_NOT_IMPLEMENTED(swizzle != 0x07060504); + tex = rtex.At(0); + } + } + + if (!render_texture && !depth_texture) + { + if (textures.desc[i].textures2d_without_sampler) + { + EXIT_NOT_IMPLEMENTED(textures.desc[i].usage != ShaderTextureUsage::ReadWrite); + 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)); } else { + EXIT_NOT_IMPLEMENTED(textures.desc[i].usage != ShaderTextureUsage::ReadOnly); + TextureObject vulkan_texture_info(r.Dfmt(), r.Nfmt(), width, height, pitch, base_level, levels, tile, neo, swizzle); tex = static_cast( @@ -3544,7 +3774,7 @@ static void PrepareTextures(CommandBuffer* buffer, const ShaderTextureResources& EXIT_NOT_IMPLEMENTED(tex == nullptr); - if (without_sampler[i]) + if (textures.desc[i].textures2d_without_sampler) { images_storage[index_storage] = tex; r.UpdateAddress(index_storage); @@ -3552,6 +3782,7 @@ static void PrepareTextures(CommandBuffer* buffer, const ShaderTextureResources& } else { images_sampled[index_sampled] = tex; + images_depth[index_sampled] = depth_texture; r.UpdateAddress(index_sampled); index_sampled++; } @@ -3646,7 +3877,7 @@ 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, + const ShaderBindResources& bind, /*const ShaderBindParameters& bind_params,*/ VkShaderStageFlags vk_stage, DescriptorCache::Stage stage) { KYTY_PROFILER_FUNCTION(); @@ -3655,14 +3886,16 @@ static void BindDescriptors(CommandBuffer* buffer, VkPipelineBindPoint pipeline_ { EXIT_NOT_IMPLEMENTED(bind.push_constant_size > DescriptorCache::PUSH_CONSTANTS_MAX * 4); EXIT_NOT_IMPLEMENTED(bind.storage_buffers.buffers_num > DescriptorCache::BUFFERS_MAX); - EXIT_NOT_IMPLEMENTED((bind_params.textures2d_storage_num > DescriptorCache::TEXTURES_STORAGE_MAX) || - (bind_params.textures2d_sampled_num > DescriptorCache::TEXTURES_SAMPLED_MAX)); - EXIT_NOT_IMPLEMENTED(bind_params.textures2d_storage_num + bind_params.textures2d_sampled_num != bind.textures2D.textures_num); + EXIT_NOT_IMPLEMENTED((bind.textures2D.textures2d_storage_num > DescriptorCache::TEXTURES_STORAGE_MAX) || + (bind.textures2D.textures2d_sampled_num > DescriptorCache::TEXTURES_SAMPLED_MAX)); + EXIT_NOT_IMPLEMENTED(bind.textures2D.textures2d_storage_num + bind.textures2D.textures2d_sampled_num != + bind.textures2D.textures_num); EXIT_NOT_IMPLEMENTED(bind.samplers.samplers_num > DescriptorCache::SAMPLERS_MAX); VulkanBuffer* storage_buffers[DescriptorCache::BUFFERS_MAX]; VulkanImage* textures2d_sampled[DescriptorCache::TEXTURES_SAMPLED_MAX]; VulkanImage* textures2d_storage[DescriptorCache::TEXTURES_STORAGE_MAX]; + bool textures2d_depth[DescriptorCache::TEXTURES_SAMPLED_MAX]; uint64_t samplers[DescriptorCache::SAMPLERS_MAX]; uint32_t sgprs[DescriptorCache::PUSH_CONSTANTS_MAX]; @@ -3676,8 +3909,8 @@ static void BindDescriptors(CommandBuffer* buffer, VkPipelineBindPoint pipeline_ } if (bind.textures2D.textures_num > 0) { - PrepareTextures(buffer, bind.textures2D, textures2d_sampled, textures2d_storage, &sgprs_ptr, - bind_params.textures2d_without_sampler); + PrepareTextures(buffer, bind.textures2D, textures2d_sampled, textures2d_storage, textures2d_depth, &sgprs_ptr/*, + bind.textures2D.textures2d_without_sampler*/); } if (bind.samplers.samplers_num > 0) { @@ -3691,18 +3924,48 @@ static void BindDescriptors(CommandBuffer* buffer, VkPipelineBindPoint pipeline_ EXIT_IF(bind.push_constant_size != (sgprs_ptr - sgprs) * 4); - auto* descriptor_set = g_render_ctx->GetDescriptorCache()->GetDescriptor( - stage, storage_buffers, textures2d_sampled, textures2d_storage, samplers, &gds_buffer, bind, bind_params); + auto* descriptor_set = + g_render_ctx->GetDescriptorCache()->GetDescriptor(stage, storage_buffers, textures2d_sampled, textures2d_depth, + textures2d_storage, samplers, &gds_buffer, bind /*, bind_params*/); EXIT_IF(descriptor_set == nullptr); auto* vk_buffer = buffer->GetPool()->buffers[buffer->GetIndex()]; + if (bind.textures2D.textures_num > 0) + { + for (int i = 0; i < bind.textures2D.textures2d_sampled_num; i++) + { + if (textures2d_depth[i]) + { + GraphicsRenderDepthStencilBarrier(vk_buffer, textures2d_sampled[i]); + } + } + } + vkCmdBindDescriptorSets(vk_buffer, pipeline_bind_point, layout, bind.descriptor_set_slot, 1, &descriptor_set->set, 0, nullptr); vkCmdPushConstants(vk_buffer, layout, vk_stage, bind.push_constant_offset, bind.push_constant_size, sgprs); } } +static void VulkanCmdSetColorWriteEnableEXT(GraphicContext* ctx, VkCommandBuffer command_buffer, uint32_t attachment_count, + const VkBool32* p_color_write_enables) +{ + EXIT_IF(ctx == nullptr); + EXIT_IF(ctx->instance == nullptr); + + static auto func = + reinterpret_cast(vkGetInstanceProcAddr(ctx->instance, "vkCmdSetColorWriteEnableEXT")); + + if (func != nullptr) + { + func(command_buffer, attachment_count, p_color_write_enables); + } else + { + EXIT("vkCmdSetColorWriteEnableEXT not present\n"); + } +} + static void SetDynamicParams(VkCommandBuffer vk_buffer, VulkanPipeline* pipeline) { KYTY_PROFILER_FUNCTION(); @@ -3711,6 +3974,11 @@ static void SetDynamicParams(VkCommandBuffer vk_buffer, VulkanPipeline* pipeline EXIT_IF(pipeline->static_params == nullptr); EXIT_IF(pipeline->dynamic_params == nullptr); + if (pipeline->dynamic_params->vk_dynamic_state_line_width) + { + vkCmdSetLineWidth(vk_buffer, pipeline->dynamic_params->line_width); + } + if (pipeline->static_params->stencil_test_enable) { if (pipeline->dynamic_params->vk_dynamic_state_stencil_compare_mask) @@ -3729,9 +3997,15 @@ static void SetDynamicParams(VkCommandBuffer vk_buffer, VulkanPipeline* pipeline vkCmdSetStencilReference(vk_buffer, VK_STENCIL_FACE_BACK_BIT, pipeline->dynamic_params->stencil_back.reference); } } + + if (pipeline->dynamic_params->vk_dynamic_state_color_write_enable_ext) + { + VkBool32 enable = (pipeline->dynamic_params->color_write_enable ? VK_TRUE : VK_FALSE); + VulkanCmdSetColorWriteEnableEXT(g_render_ctx->GetGraphicCtx(), vk_buffer, 1, &enable); + } } -void GraphicsRenderDrawIndex(CommandBuffer* buffer, HardwareContext* ctx, UserConfig* ucfg, uint32_t index_type_and_size, +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) { KYTY_PROFILER_FUNCTION(); @@ -3755,7 +4029,7 @@ void GraphicsRenderDrawIndex(CommandBuffer* buffer, HardwareContext* ctx, UserCo } // const auto& rt = ctx->GetRenderTargets(0); - const auto& bc = ctx->GetBlendControl(0); + // const auto& bc = ctx->GetBlendControl(0); uc_print("GraphicsRenderDrawIndex():UserConfig:", *ucfg); @@ -3812,10 +4086,8 @@ void GraphicsRenderDrawIndex(CommandBuffer* buffer, HardwareContext* ctx, UserCo 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->GetVs(), - &ps_input_info, &ctx->GetPs(), VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, - ctx->GetRenderTargetMask(), ctx->GetModeControl(), bc, - ctx->GetBlendColor(), ctx->GetScreenViewport()); + auto* pipeline = g_render_ctx->GetPipelineCache()->CreatePipeline(framebuffer, &color_info, &depth_info, &vs_input_info, ctx, + &ps_input_info, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST); vkCmdBindPipeline(vk_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->pipeline); @@ -3836,10 +4108,10 @@ void GraphicsRenderDrawIndex(CommandBuffer* buffer, HardwareContext* ctx, UserCo } 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); + /*pipeline->additional_params->vs_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); + /*pipeline->additional_params->ps_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())); @@ -3859,7 +4131,8 @@ void GraphicsRenderDrawIndex(CommandBuffer* buffer, HardwareContext* ctx, UserCo } // NOLINTNEXTLINE(readability-function-cognitive-complexity) -void GraphicsRenderDrawIndexAuto(CommandBuffer* buffer, HardwareContext* ctx, UserConfig* ucfg, uint32_t index_count, uint32_t flags) +void GraphicsRenderDrawIndexAuto(CommandBuffer* buffer, HW::HardwareContext* ctx, HW::UserConfig* ucfg, uint32_t index_count, + uint32_t flags) { KYTY_PROFILER_FUNCTION(); @@ -3880,7 +4153,7 @@ void GraphicsRenderDrawIndexAuto(CommandBuffer* buffer, HardwareContext* ctx, Us } // const auto& rt = ctx->GetRenderTargets(0); - const auto& bc = ctx->GetBlendControl(0); + // const auto& bc = ctx->GetBlendControl(0); uc_print("GraphicsRenderDrawIndexAuto():UserConfig:", *ucfg); @@ -3928,9 +4201,8 @@ void GraphicsRenderDrawIndexAuto(CommandBuffer* buffer, HardwareContext* ctx, Us EXIT_NOT_IMPLEMENTED(vs_input_info.buffers_num > 1); - auto* pipeline = g_render_ctx->GetPipelineCache()->CreatePipeline( - framebuffer, &color_info, &depth_info, &vs_input_info, &vertex_shader_info, &ps_input_info, &pixel_shader_info, topology, - ctx->GetRenderTargetMask(), ctx->GetModeControl(), bc, ctx->GetBlendColor(), ctx->GetScreenViewport()); + auto* pipeline = g_render_ctx->GetPipelineCache()->CreatePipeline(framebuffer, &color_info, &depth_info, &vs_input_info, ctx, + &ps_input_info, topology); vkCmdBindPipeline(vk_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->pipeline); @@ -3951,10 +4223,10 @@ void GraphicsRenderDrawIndexAuto(CommandBuffer* buffer, HardwareContext* ctx, Us } 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); + /*pipeline->additional_params->vs_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); + /*pipeline->additional_params->ps_bind,*/ VK_SHADER_STAGE_FRAGMENT_BIT, DescriptorCache::Stage::Pixel); buffer->BeginRenderPass(framebuffer, &color_info, &depth_info); @@ -3979,7 +4251,7 @@ void GraphicsRenderDrawIndexAuto(CommandBuffer* buffer, HardwareContext* ctx, Us InvalidateMemoryObject(depth_info); } -void GraphicsRenderDispatchDirect(CommandBuffer* buffer, HardwareContext* ctx, uint32_t thread_group_x, uint32_t thread_group_y, +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) { EXIT_IF(ctx == nullptr); @@ -4010,72 +4282,11 @@ void GraphicsRenderDispatchDirect(CommandBuffer* buffer, HardwareContext* ctx, u 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); + /*pipeline->additional_params->cs_bind,*/ VK_SHADER_STAGE_COMPUTE_BIT, DescriptorCache::Stage::Compute); vkCmdDispatch(vk_buffer, thread_group_x, thread_group_y, thread_group_z); } -void GraphicsRenderMemoryBarrier(CommandBuffer* buffer) -{ - EXIT_IF(buffer == nullptr); - EXIT_IF(buffer->IsInvalid()); - - Core::LockGuard lock(g_render_ctx->GetMutex()); - - auto* vk_buffer = buffer->GetPool()->buffers[buffer->GetIndex()]; - - VkMemoryBarrier mem_barrier {}; - mem_barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER; - mem_barrier.pNext = nullptr; - mem_barrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT; - mem_barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; - - vkCmdPipelineBarrier(vk_buffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &mem_barrier, 0, nullptr, 0, - nullptr); -} - -void GraphicsRenderRenderTextureBarrier(CommandBuffer* buffer, uint64_t vaddr, uint64_t size) -{ - EXIT_IF(buffer == nullptr); - EXIT_IF(buffer->IsInvalid()); - - Core::LockGuard lock(g_render_ctx->GetMutex()); - - auto* vk_buffer = buffer->GetPool()->buffers[buffer->GetIndex()]; - - auto images = FindRenderTexture(vaddr, size, false); - - for (auto* image: images) - { - EXIT_NOT_IMPLEMENTED(image == nullptr); - if (image->layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) - { - VkImageMemoryBarrier image_memory_barrier {}; - image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - image_memory_barrier.pNext = nullptr; - image_memory_barrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT; - image_memory_barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; - image_memory_barrier.oldLayout = image->layout; - image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - image_memory_barrier.image = image->image; - image_memory_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - image_memory_barrier.subresourceRange.baseMipLevel = 0; - image_memory_barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; - image_memory_barrier.subresourceRange.baseArrayLayer = 0; - image_memory_barrier.subresourceRange.layerCount = 1; - - vkCmdPipelineBarrier(vk_buffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, - &image_memory_barrier); - - image->layout = image_memory_barrier.newLayout; - } - } -} - void GraphicsRenderWriteAtEndOfPipe(CommandBuffer* buffer, uint32_t* dst_gpu_addr, uint32_t value) { EXIT_IF(g_render_ctx == nullptr); @@ -4638,6 +4849,31 @@ void CommandBuffer::BeginRenderPass(VulkanFramebuffer* framebuffer, RenderColorI color->vulkan_buffer->layout = image_memory_barrier.newLayout; } + if (with_depth && depth->vulkan_buffer->layout != VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) + { + VkImageMemoryBarrier image_memory_barrier {}; + image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + image_memory_barrier.pNext = nullptr; + image_memory_barrier.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT; + image_memory_barrier.dstAccessMask = VK_ACCESS_MEMORY_WRITE_BIT; + image_memory_barrier.oldLayout = depth->vulkan_buffer->layout; + image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + image_memory_barrier.image = depth->vulkan_buffer->image; + image_memory_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + image_memory_barrier.subresourceRange.baseMipLevel = 0; + image_memory_barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + image_memory_barrier.subresourceRange.baseArrayLayer = 0; + image_memory_barrier.subresourceRange.layerCount = 1; + + vkCmdPipelineBarrier(buffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, + &image_memory_barrier); + + depth->vulkan_buffer->layout = image_memory_barrier.newLayout; + } + vkCmdBeginRenderPass(buffer, &render_pass_info, VK_SUBPASS_CONTENTS_INLINE); } diff --git a/source/emulator/src/Graphics/GraphicsRun.cpp b/source/emulator/src/Graphics/GraphicsRun.cpp index 7d1e5e2..725447b 100644 --- a/source/emulator/src/Graphics/GraphicsRun.cpp +++ b/source/emulator/src/Graphics/GraphicsRun.cpp @@ -55,8 +55,8 @@ public: void BufferFlush(); void BufferWait(); - HardwareContext* GetCtx(); - UserConfig* GetUcfg(); + HW::HardwareContext* GetCtx() { return &m_ctx; } + HW::UserConfig* GetUcfg() { return &m_ucfg; } void SetIndexType(uint32_t index_type_and_size); void DrawIndex(uint32_t index_count, const void* index_addr, uint32_t flags, uint32_t type); @@ -76,11 +76,11 @@ public: void WaitFlipDone(uint32_t video_out_handle, uint32_t display_buffer_index); void TriggerEvent(uint32_t event_type, uint32_t event_index); - void SetUserDataMarker(UserSgprType type) { m_user_data_marker = type; } - [[nodiscard]] UserSgprType GetUserDataMarker() const { return m_user_data_marker; } - void SetEmbeddedDataMarker(const uint32_t* buffer, uint32_t num_dw, uint32_t align) {} - void PushMarker(const char* str) {} - void PopMarker() {} + void SetUserDataMarker(HW::UserSgprType type) { m_user_data_marker = type; } + [[nodiscard]] HW::UserSgprType GetUserDataMarker() const { return m_user_data_marker; } + void SetEmbeddedDataMarker(const uint32_t* buffer, uint32_t num_dw, uint32_t align) {} + void PushMarker(const char* str) {} + void PopMarker() {} void PrefetchL2(void* addr, uint32_t size) {} void ClearGds(uint64_t dw_offset, uint32_t dw_num, uint32_t clear_value); @@ -115,10 +115,10 @@ private: uint32_t value = 0; }; - HardwareContext m_ctx; - UserConfig m_ucfg; - uint32_t m_index_type_and_size = 0; - UserSgprType m_user_data_marker = UserSgprType::Unknown; + HW::HardwareContext m_ctx; + HW::UserConfig m_ucfg; + uint32_t m_index_type_and_size = 0; + HW::UserSgprType m_user_data_marker = HW::UserSgprType::Unknown; Core::Mutex m_mutex; @@ -484,7 +484,7 @@ void CommandProcessor::Reset() m_ucfg.Reset(); m_ctx.Reset(); m_index_type_and_size = 0; - m_user_data_marker = UserSgprType::Unknown; + m_user_data_marker = HW::UserSgprType::Unknown; std::memset(m_const_ram, 0, sizeof(m_const_ram)); } @@ -954,22 +954,6 @@ void CommandProcessor::Run(uint32_t* data, uint32_t num_dw) } } -HardwareContext* CommandProcessor::GetCtx() -{ - Core::LockGuard lock(m_mutex); - - // EXIT_NOT_IMPLEMENTED(m_drawing); - - return &m_ctx; -} - -UserConfig* CommandProcessor::GetUcfg() -{ - Core::LockGuard lock(m_mutex); - - return &m_ucfg; -} - void CommandProcessor::SetIndexType(uint32_t index_type_and_size) { Core::LockGuard lock(m_mutex); @@ -1141,10 +1125,15 @@ void CommandProcessor::TriggerEvent(uint32_t event_type, uint32_t event_index) if ((event_type == 0x00000016 || event_type == 0x00000031) && event_index == 0x00000007) { + // CacheFlushAndInvEvent + // FlushAndInvalidateCbPixelData MemoryBarrier(); + } else if ((event_type == 0x0000002c) && event_index == 0x00000007) + { + // FlushAndInvalidateDbMeta } else { - EXIT("unknown event type\n"); + EXIT("unknown event type: 0x%08" PRIx32 ", 0x%08" PRIx32 "\n", event_type, event_index); } } @@ -1275,7 +1264,7 @@ KYTY_HW_CTX_PARSER(hw_ctx_set_depth_render_target) if (cmd_id == 0xC0016900) { - DepthRenderTargetZInfo r; + HW::DepthRenderTargetZInfo r; r.expclear_enabled = (buffer[0] & 0x08000000u) != 0; @@ -1294,7 +1283,7 @@ KYTY_HW_CTX_PARSER(hw_ctx_set_depth_render_target) { count = 22; - DepthRenderTarget z; + HW::DepthRenderTarget z; z.z_info.expclear_enabled = (buffer[0] & 0x08000000u) != 0; z.z_info.format = (buffer[0] >> Pm4::DB_Z_INFO_FORMAT_SHIFT) & Pm4::DB_Z_INFO_FORMAT_MASK; @@ -1403,7 +1392,7 @@ KYTY_HW_CTX_PARSER(hw_ctx_set_stencil_info) EXIT_NOT_IMPLEMENTED(cmd_id != 0xC0016900); EXIT_NOT_IMPLEMENTED(cmd_offset != Pm4::DB_STENCIL_INFO); - DepthRenderTargetStencilInfo r; + HW::DepthRenderTargetStencilInfo r; r.expclear_enabled = (buffer[0] & 0x08000000u) != 0; r.tile_split = (buffer[0] >> 13u) & 0x7u; @@ -1423,7 +1412,7 @@ KYTY_HW_CTX_PARSER(hw_ctx_set_render_control) EXIT_NOT_IMPLEMENTED(cmd_id != 0xC0016900); EXIT_NOT_IMPLEMENTED(cmd_offset != Pm4::DB_RENDER_CONTROL); - RenderControl r; + HW::RenderControl r; r.depth_clear_enable = KYTY_PM4_GET(buffer[0], DB_RENDER_CONTROL, DEPTH_CLEAR_ENABLE) != 0; r.stencil_clear_enable = KYTY_PM4_GET(buffer[0], DB_RENDER_CONTROL, STENCIL_CLEAR_ENABLE) != 0; @@ -1443,7 +1432,7 @@ KYTY_HW_CTX_PARSER(hw_ctx_set_mode_control) EXIT_NOT_IMPLEMENTED(cmd_id != 0xC0016900); EXIT_NOT_IMPLEMENTED(cmd_offset != Pm4::PA_SU_SC_MODE_CNTL); - ModeControl r; + HW::ModeControl r; r.cull_front = KYTY_PM4_GET(buffer[0], PA_SU_SC_MODE_CNTL, CULL_FRONT) != 0; r.cull_back = KYTY_PM4_GET(buffer[0], PA_SU_SC_MODE_CNTL, CULL_BACK) != 0; @@ -1462,12 +1451,30 @@ KYTY_HW_CTX_PARSER(hw_ctx_set_mode_control) return 1; } +KYTY_HW_CTX_PARSER(hw_ctx_set_line_control) +{ + EXIT_NOT_IMPLEMENTED(cmd_id != 0xC0016900); + EXIT_NOT_IMPLEMENTED(cmd_offset != Pm4::PA_SU_LINE_CNTL); + + auto line_width = KYTY_PM4_GET(buffer[0], PA_SU_LINE_CNTL, WIDTH); + + if (line_width == 8) + { + cp->GetCtx()->SetLineWidth(1.0f); + } else + { + cp->GetCtx()->SetLineWidth(static_cast(line_width) / 8.0f); + } + + return 1; +} + KYTY_HW_CTX_PARSER(hw_ctx_set_depth_control) { EXIT_NOT_IMPLEMENTED(cmd_id != 0xC0016900); EXIT_NOT_IMPLEMENTED(cmd_offset != Pm4::DB_DEPTH_CONTROL); - DepthControl r; + HW::DepthControl r; r.stencil_enable = KYTY_PM4_GET(buffer[0], DB_DEPTH_CONTROL, STENCIL_ENABLE) != 0; r.z_enable = KYTY_PM4_GET(buffer[0], DB_DEPTH_CONTROL, Z_ENABLE) != 0; @@ -1488,7 +1495,7 @@ KYTY_HW_CTX_PARSER(hw_ctx_set_stencil_control) EXIT_NOT_IMPLEMENTED(cmd_id != 0xC0016900); EXIT_NOT_IMPLEMENTED(cmd_offset != Pm4::DB_STENCIL_CONTROL); - StencilControl r; + HW::StencilControl r; r.stencil_fail = KYTY_PM4_GET(buffer[0], DB_STENCIL_CONTROL, STENCILFAIL); r.stencil_zpass = KYTY_PM4_GET(buffer[0], DB_STENCIL_CONTROL, STENCILZPASS); @@ -1507,7 +1514,7 @@ KYTY_HW_CTX_PARSER(hw_ctx_set_stencil_mask) EXIT_NOT_IMPLEMENTED(cmd_id != 0xc0026900); EXIT_NOT_IMPLEMENTED(cmd_offset != Pm4::DB_STENCILREFMASK); - StencilMask r; + HW::StencilMask r; r.stencil_testval = KYTY_PM4_GET(buffer[0], DB_STENCILREFMASK, STENCILTESTVAL); r.stencil_mask = KYTY_PM4_GET(buffer[0], DB_STENCILREFMASK, STENCILMASK); @@ -1528,7 +1535,7 @@ KYTY_HW_CTX_PARSER(hw_ctx_set_eqaa_control) EXIT_NOT_IMPLEMENTED(cmd_id != 0xC0016900); EXIT_NOT_IMPLEMENTED(cmd_offset != Pm4::DB_EQAA); - EqaaControl r; + HW::EqaaControl r; r.max_anchor_samples = KYTY_PM4_GET(buffer[0], DB_EQAA, MAX_ANCHOR_SAMPLES); r.ps_iter_samples = KYTY_PM4_GET(buffer[0], DB_EQAA, PS_ITER_SAMPLES); @@ -1544,6 +1551,21 @@ KYTY_HW_CTX_PARSER(hw_ctx_set_eqaa_control) return 1; } +KYTY_HW_CTX_PARSER(hw_ctx_set_color_control) +{ + EXIT_NOT_IMPLEMENTED(cmd_id != 0xc0016900); + EXIT_NOT_IMPLEMENTED(cmd_offset != Pm4::CB_COLOR_CONTROL); + + HW::ColorControl r; + + r.mode = KYTY_PM4_GET(buffer[0], CB_COLOR_CONTROL, MODE); + r.op = KYTY_PM4_GET(buffer[0], CB_COLOR_CONTROL, ROP3); + + cp->GetCtx()->SetColorControl(r); + + return 1; +} + KYTY_HW_CTX_PARSER(hw_ctx_set_stencil_clear) { EXIT_NOT_IMPLEMENTED(cmd_id != 0xC0016900); @@ -1580,7 +1602,7 @@ KYTY_HW_CTX_PARSER(hw_ctx_set_blend_control) uint32_t param = (cmd_offset - Pm4::CB_BLEND0_CONTROL) / 1; - BlendControl r; + HW::BlendControl r; r.color_srcblend = (buffer[0] >> Pm4::CB_BLEND0_CONTROL_COLOR_SRCBLEND_SHIFT) & Pm4::CB_BLEND0_CONTROL_COLOR_SRCBLEND_MASK; r.color_comb_fcn = (buffer[0] >> Pm4::CB_BLEND0_CONTROL_COLOR_COMB_FCN_SHIFT) & Pm4::CB_BLEND0_CONTROL_COLOR_COMB_FCN_MASK; @@ -1599,59 +1621,98 @@ KYTY_HW_CTX_PARSER(hw_ctx_set_blend_control) KYTY_HW_CTX_PARSER(hw_ctx_set_render_target) { - EXIT_NOT_IMPLEMENTED(cmd_id != 0xC00E6900); + EXIT_NOT_IMPLEMENTED(cmd_id != 0xC00E6900 && cmd_id != 0xC00B6900); uint32_t param = (cmd_offset - Pm4::CB_COLOR0_BASE) / 15; - uint32_t count = 14; + uint32_t count = 11; - if (dw >= 16 && buffer[14] == 0xC0001000) + auto* ctx = cp->GetCtx(); + + HW::ColorBase base; + HW::ColorPitch pitch; + HW::ColorSlice slice; + HW::ColorView view; + HW::ColorInfo info; + HW::ColorAttrib attrib; + HW::ColorDcc dcc; + HW::ColorCmask cmask; + HW::ColorCmaskSlice cmask_slice; + HW::ColorFmask fmask; + HW::ColorFmaskSlice fmask_slice; + + base.addr = static_cast(buffer[0]) << 8u; + pitch.pitch_div8_minus1 = buffer[1] & 0x7ffu; + pitch.fmask_pitch_div8_minus1 = (buffer[1] >> 20u) & 0x7ffu; + slice.slice_div64_minus1 = buffer[2] & 0x3fffffu; + view.base_array_slice_index = buffer[3] & 0x7ffu; + view.last_array_slice_index = (buffer[3] >> 13u) & 0x7ffu; + info.fmask_compression_enable = (buffer[4] & 0x4000u) != 0; + info.fmask_compression_mode = (buffer[4] >> 26u) & 0x3u; + info.cmask_fast_clear_enable = (buffer[4] & 0x2000u) != 0; + info.dcc_compression_enable = (buffer[4] & 0x10000000u) != 0; + info.neo_mode = (buffer[4] & 0x80000000u) != 0; + info.cmask_tile_mode = (buffer[4] >> 19u) & 0x1u; + info.cmask_tile_mode_neo = (buffer[4] >> 29u) & 0x3u; + info.format = (buffer[4] >> 2u) & 0x1fu; + info.channel_type = (buffer[4] >> 8u) & 0x7u; + info.channel_order = (buffer[4] >> 11u) & 0x3u; + attrib.force_dest_alpha_to_one = (buffer[5] & 0x20000u) != 0; + attrib.tile_mode = buffer[5] & 0x1fu; + attrib.fmask_tile_mode = (buffer[5] >> 5u) & 0x1fu; + attrib.num_samples = (buffer[5] >> 12u) & 0x7u; + attrib.num_fragments = (buffer[5] >> 15u) & 0x3u; + dcc.max_uncompressed_block_size = (buffer[6] >> 2u) & 0x3u; + dcc.max_compressed_block_size = (buffer[6] >> 5u) & 0x3u; + dcc.min_compressed_block_size = (buffer[6] >> 4u) & 0x1u; + dcc.color_transform = (buffer[6] >> 7u) & 0x3u; + dcc.enable_overwrite_combiner = (buffer[6] & 0x1u) != 0; + dcc.force_independent_blocks = (buffer[6] & 0x200u) != 0; + cmask.addr = static_cast(buffer[7]) << 8u; + cmask_slice.slice_minus1 = buffer[8] & 0x3fffu; + fmask.addr = static_cast(buffer[9]) << 8u; + fmask_slice.slice_minus1 = buffer[10] & 0x3fffffu; + + ctx->SetColorBase(param, base); + ctx->SetColorPitch(param, pitch); + ctx->SetColorSlice(param, slice); + ctx->SetColorView(param, view); + ctx->SetColorInfo(param, info); + ctx->SetColorAttrib(param, attrib); + ctx->SetColorDcc(param, dcc); + ctx->SetColorCmask(param, cmask); + ctx->SetColorCmaskSlice(param, cmask_slice); + ctx->SetColorFmask(param, fmask); + ctx->SetColorFmaskSlice(param, fmask_slice); + + if (cmd_id == 0xC00E6900) { - count = 16; + count = 14; + + HW::ColorClearWord0 clear_word0; + HW::ColorClearWord1 clear_word1; + HW::ColorDccAddr dcc_addr; + + clear_word0.word0 = buffer[11]; + clear_word1.word1 = buffer[12]; + dcc_addr.addr = static_cast(buffer[13]) << 8u; + + ctx->SetColorClearWord0(param, clear_word0); + ctx->SetColorClearWord1(param, clear_word1); + ctx->SetColorDccAddr(param, dcc_addr); } - RenderTarget r; + if (dw >= count + 2 && buffer[count] == 0xC0001000) + { + HW::ColorSize size; - r.base_addr = static_cast(buffer[0]) << 8u; - r.pitch_div8_minus1 = buffer[1] & 0x7ffu; - r.fmask_pitch_div8_minus1 = (buffer[1] >> 20u) & 0x7ffu; - r.slice_div64_minus1 = buffer[2] & 0x3fffffu; - r.base_array_slice_index = buffer[3] & 0x7ffu; - r.last_array_slice_index = (buffer[3] >> 13u) & 0x7ffu; + size.width = (buffer[count + 1] >> 0u) & 0xffffu; + size.height = (buffer[count + 1] >> 16u) & 0xffffu; - r.color_info.fmask_compression_enable = (buffer[4] & 0x4000u) != 0; - r.color_info.fmask_compression_mode = (buffer[4] >> 26u) & 0x3u; - r.color_info.cmask_fast_clear_enable = (buffer[4] & 0x2000u) != 0; - r.color_info.dcc_compression_enable = (buffer[4] & 0x10000000u) != 0; - r.color_info.neo_mode = (buffer[4] & 0x80000000u) != 0; - r.color_info.cmask_tile_mode = (buffer[4] >> 19u) & 0x1u; - r.color_info.cmask_tile_mode_neo = (buffer[4] >> 29u) & 0x3u; - r.color_info.format = (buffer[4] >> 2u) & 0x1fu; - r.color_info.channel_type = (buffer[4] >> 8u) & 0x7u; - r.color_info.channel_order = (buffer[4] >> 11u) & 0x3u; + ctx->SetColorSize(param, size); - r.force_dest_alpha_to_one = (buffer[5] & 0x20000u) != 0; - r.tile_mode = buffer[5] & 0x1fu; - r.fmask_tile_mode = (buffer[5] >> 5u) & 0x1fu; - r.num_samples = (buffer[5] >> 12u) & 0x7u; - r.num_fragments = (buffer[5] >> 15u) & 0x3u; - r.dcc_max_uncompressed_block_size = (buffer[6] >> 2u) & 0x3u; - r.dcc_max_compressed_block_size = (buffer[6] >> 5u) & 0x3u; - r.dcc_min_compressed_block_size = (buffer[6] >> 4u) & 0x1u; - r.dcc_color_transform = (buffer[6] >> 7u) & 0x3u; - r.dcc_enable_overwrite_combiner = (buffer[6] & 0x1u) != 0; - r.dcc_force_independent_blocks = (buffer[6] & 0x200u) != 0; - r.cmask_addr = static_cast(buffer[7]) << 8u; - r.cmask_slice_minus1 = buffer[8] & 0x3fffu; - r.fmask_addr = static_cast(buffer[9]) << 8u; - r.fmask_slice_minus1 = buffer[10] & 0x3fffffu; - r.clear_color_word0 = buffer[11]; - r.clear_color_word1 = buffer[12]; - r.dcc_addr = static_cast(buffer[13]) << 8u; - r.width = (count == 16 ? (buffer[15] >> 0u) & 0xffffu : 0); - r.height = (count == 16 ? (buffer[15] >> 16u) & 0xffffu : 0); - - cp->GetCtx()->SetRenderTarget(param, r); + count += 2; + } return count; } @@ -1662,7 +1723,7 @@ KYTY_HW_CTX_PARSER(hw_ctx_set_color_info) uint32_t param = (cmd_offset - Pm4::CB_COLOR0_INFO) / 15; - ColorInfo r; + HW::ColorInfo r; r.fmask_compression_enable = (buffer[4] & 0x4000u) != 0; r.fmask_compression_mode = (buffer[4] >> 26u) & 0x3u; @@ -1733,7 +1794,7 @@ KYTY_HW_CTX_PARSER(hw_ctx_set_clip_control) EXIT_NOT_IMPLEMENTED(cmd_id != 0xC0016900); EXIT_NOT_IMPLEMENTED(cmd_offset != 0x00000204); - ClipControl r; + HW::ClipControl r; r.user_clip_planes = buffer[0] & 0x3fu; r.user_clip_plane_mode = (buffer[0] >> 14u) & 0x3u; @@ -1756,18 +1817,35 @@ KYTY_HW_CTX_PARSER(hw_ctx_set_clip_control) KYTY_HW_CTX_PARSER(hw_ctx_set_screen_scissor) { EXIT_NOT_IMPLEMENTED(cmd_id != 0xC0026900); - EXIT_NOT_IMPLEMENTED(cmd_offset != 0x0000000C); + EXIT_NOT_IMPLEMENTED(cmd_offset != Pm4::PA_SC_SCREEN_SCISSOR_TL); - int left = static_cast(static_cast(buffer[0] & 0xffffu)); - int top = static_cast(static_cast((buffer[0] >> 16u) & 0xffffu)); - int right = static_cast(static_cast(buffer[1] & 0xffffu)); - int bottom = static_cast(static_cast((buffer[1] >> 16u) & 0xffffu)); + int left = static_cast(static_cast(KYTY_PM4_GET(buffer[0], PA_SC_SCREEN_SCISSOR_TL, TL_X))); + int top = static_cast(static_cast(KYTY_PM4_GET(buffer[0], PA_SC_SCREEN_SCISSOR_TL, TL_Y))); + int right = static_cast(static_cast(KYTY_PM4_GET(buffer[1], PA_SC_SCREEN_SCISSOR_BR, BR_X))); + int bottom = static_cast(static_cast(KYTY_PM4_GET(buffer[1], PA_SC_SCREEN_SCISSOR_BR, BR_Y))); cp->GetCtx()->SetScreenScissor(left, top, right, bottom); return 2; } +KYTY_HW_CTX_PARSER(hw_ctx_set_generic_scissor) +{ + EXIT_NOT_IMPLEMENTED(cmd_id != 0xC0026900); + EXIT_NOT_IMPLEMENTED(cmd_offset != Pm4::PA_SC_GENERIC_SCISSOR_TL); + + int left = static_cast(static_cast(KYTY_PM4_GET(buffer[0], PA_SC_GENERIC_SCISSOR_TL, TL_X))); + int top = static_cast(static_cast(KYTY_PM4_GET(buffer[0], PA_SC_GENERIC_SCISSOR_TL, TL_Y))); + int right = static_cast(static_cast(KYTY_PM4_GET(buffer[1], PA_SC_GENERIC_SCISSOR_BR, BR_X))); + int bottom = static_cast(static_cast(KYTY_PM4_GET(buffer[1], PA_SC_GENERIC_SCISSOR_BR, BR_Y))); + + bool window_offset_disable = KYTY_PM4_GET(buffer[0], PA_SC_GENERIC_SCISSOR_TL, WINDOW_OFFSET_DISABLE) != 0; + + cp->GetCtx()->SetGenericScissor(left, top, right, bottom, !window_offset_disable); + + return 2; +} + KYTY_HW_CTX_PARSER(hw_ctx_hardware_screen_offset) { EXIT_NOT_IMPLEMENTED(cmd_id != 0xC0016900); @@ -1801,7 +1879,7 @@ KYTY_HW_CTX_PARSER(hw_ctx_set_blend_color) EXIT_NOT_IMPLEMENTED(cmd_id != 0xc0046900); EXIT_NOT_IMPLEMENTED(cmd_offset != Pm4::CB_BLEND_RED); - BlendColor r; + HW::BlendColor r; r.red = *reinterpret_cast(&buffer[0]); r.green = *reinterpret_cast(&buffer[1]); @@ -1819,7 +1897,7 @@ KYTY_HW_CTX_PARSER(hw_ctx_set_vs_shader) auto shader_modifier = buffer[0]; - cp->GetCtx()->SetVsShader(reinterpret_cast(buffer + 1), shader_modifier); + cp->GetCtx()->SetVsShader(reinterpret_cast(buffer + 1), shader_modifier); return 28; } @@ -1851,7 +1929,7 @@ KYTY_HW_CTX_PARSER(hw_ctx_set_ps_shader) { EXIT_NOT_IMPLEMENTED(cmd_id != 0xC0261008); - PsStageRegisters r {}; + HW::PsStageRegisters r {}; r.data_addr = (static_cast(buffer[0]) << 8u) | (static_cast(buffer[1]) << 40u); r.vgprs = (buffer[2] >> Pm4::SPI_SHADER_PGM_RSRC1_PS_VGPRS_SHIFT) & Pm4::SPI_SHADER_PGM_RSRC1_PS_VGPRS_MASK; @@ -1889,7 +1967,7 @@ KYTY_HW_CTX_PARSER(hw_ctx_set_cs_shader) auto shader_modifier = buffer[0]; - CsStageRegisters r {}; + HW::CsStageRegisters r {}; r.data_addr = (static_cast(buffer[1]) << 8u) | (static_cast(buffer[2]) << 40u); r.vgprs = (buffer[3] >> Pm4::COMPUTE_PGM_RSRC1_VGPRS_SHIFT) & Pm4::COMPUTE_PGM_RSRC1_VGPRS_MASK; @@ -2033,14 +2111,47 @@ KYTY_CP_OP_PARSER(cp_op_draw_index_auto) { KYTY_PROFILER_FUNCTION(); - EXIT_NOT_IMPLEMENTED(cmd_id != 0xC0051010); + EXIT_NOT_IMPLEMENTED(cmd_id != 0xC0051010 && cmd_id != 0xc0012d00); - uint32_t index_count = buffer[0]; - uint32_t flags = buffer[1]; + if (cmd_id == 0xC0051010) + { + uint32_t index_count = buffer[0]; + uint32_t flags = buffer[1]; - cp->DrawIndexAuto(index_count, flags); + cp->DrawIndexAuto(index_count, flags); - return 6; + return 6; + } + + if (cmd_id == 0xc0012d00) + { + uint32_t index_count = buffer[0]; + uint32_t flags = 0; + + EXIT_NOT_IMPLEMENTED(buffer[1] != 2); + + cp->DrawIndexAuto(index_count, flags); + + EXIT_NOT_IMPLEMENTED(!(dw >= 4)); + + if (buffer[2] == 0xc0001000) + { + EXIT_NOT_IMPLEMENTED(buffer[3] != 0); + + return 4; + } + + if (buffer[2] == 0xc0021000) + { + EXIT_NOT_IMPLEMENTED(buffer[3] != 0); + + return 6; + } + + EXIT("invalid draw_index_auto\n"); + } + + return 1; } KYTY_CP_OP_PARSER(cp_op_dispatch_direct) @@ -2171,7 +2282,7 @@ KYTY_CP_OP_PARSER(cp_op_set_shader_reg) EXIT("unknown reg: %u\n", reg); } - cp->SetUserDataMarker(UserSgprType::Unknown); + cp->SetUserDataMarker(HW::UserSgprType::Unknown); return 1 + reg_num; } @@ -2299,6 +2410,7 @@ KYTY_CP_OP_PARSER(cp_op_wait_on_address) return 13; } +// NOLINTNEXTLINE(readability-function-cognitive-complexity) KYTY_CP_OP_PARSER(cp_op_acquire_mem) { KYTY_PROFILER_FUNCTION(); @@ -2313,7 +2425,11 @@ KYTY_CP_OP_PARSER(cp_op_acquire_mem) uint32_t base_hi = buffer[4]; uint32_t poll = buffer[5]; - EXIT_NOT_IMPLEMENTED(stall_mode != 1); + uint32_t target_mask = cache_action & 0x00007FC0u; + uint32_t extended_action = cache_action & 0x2E000000u; + uint32_t action = ((cache_action & 0x00C00000u) >> 0x12u) | ((cache_action & 0x00058000u) >> 0xfu); + + // EXIT_NOT_IMPLEMENTED(stall_mode != 1); EXIT_NOT_IMPLEMENTED(size_hi != 0); EXIT_NOT_IMPLEMENTED(base_hi != 0); EXIT_NOT_IMPLEMENTED(poll != 10); @@ -2321,36 +2437,81 @@ KYTY_CP_OP_PARSER(cp_op_acquire_mem) switch (cache_action) { case 0x02c40040: + case 0x02c43fc0: { + // target_mask: 0x00000040 (rt0), 0x00003fc0 (all rt) + // extended_action: 0x02000000 (FlushAndInvalidateCbCache) + // action: 0x38 (WriteBackAndInvalidateL1andL2) + EXIT_IF(target_mask != 0x00000040 && target_mask != 0x00003FC0); + EXIT_IF(extended_action != 0x02000000); + EXIT_IF(action != 0x38); EXIT_NOT_IMPLEMENTED(size_lo == 0); EXIT_NOT_IMPLEMENTED(base_lo == 0); + cp->RenderTextureBarrier(base_lo << 8u, size_lo << 8u); cp->WriteBack(); } break; case 0x02003fc0: { + // target_mask: 0x00003FC0 (all rt) + // extended_action: 0x02000000 (FlushAndInvalidateCbCache) + // action: 0x00 (none) + EXIT_IF(target_mask != 0x00003FC0); + EXIT_IF(extended_action != 0x02000000); + EXIT_IF(action != 0x00); EXIT_NOT_IMPLEMENTED(size_lo == 0); EXIT_NOT_IMPLEMENTED(base_lo == 0); + cp->RenderTextureBarrier(base_lo << 8u, size_lo << 8u); } break; case 0x00C40000: { + // target_mask: 0x00000000 (none) + // extended_action: 0x00000000 (none) + // action: 0x38 (WriteBackAndInvalidateL1andL2) + EXIT_IF(target_mask != 0x00000000); + EXIT_IF(extended_action != 0x00000000); + EXIT_IF(action != 0x38); EXIT_NOT_IMPLEMENTED(size_lo != 1); EXIT_NOT_IMPLEMENTED(base_lo != 0); + cp->MemoryBarrier(); cp->WriteBack(); } break; case 0x00400000: { + // target_mask: 0x00000000 (none) + // extended_action: 0x00000000 (none) + // action: 0x10 (InvalidateL1) + EXIT_IF(target_mask != 0x00000000); + EXIT_IF(extended_action != 0x00000000); + EXIT_IF(action != 0x10); EXIT_NOT_IMPLEMENTED(size_lo != 1); EXIT_NOT_IMPLEMENTED(base_lo != 0); + cp->MemoryBarrier(); } break; - default: EXIT("unknown barrier"); + case 0x04c44000: + { + // target_mask: 0x00004000 (Depth Target) + // extended_action: 0x04000000 (FlushAndInvalidateDbCache) + // action: 0x38 (WriteBackAndInvalidateL1andL2) + KYTY_NOT_IMPLEMENTED; + } + break; + default: + EXIT("unknown barrier: 0x%08" PRIx32 ", 0x%08" PRIx32 ", 0x%08" PRIx32 ", 0x%08" PRIx32 "\n", cache_action, target_mask, + extended_action, action); + } + + if (stall_mode == 0) + { + cp->BufferFlush(); + cp->BufferWait(); } return 6; @@ -2416,8 +2577,8 @@ KYTY_CP_OP_PARSER(cp_op_marker) switch (id) { case 0x0: cp->SetEmbeddedDataMarker(buffer + 1, len_dw, align); break; - case 0x4: cp->SetUserDataMarker(UserSgprType::Vsharp); break; - case 0xd: cp->SetUserDataMarker(UserSgprType::Region); break; + case 0x4: cp->SetUserDataMarker(HW::UserSgprType::Vsharp); break; + case 0xd: cp->SetUserDataMarker(HW::UserSgprType::Region); break; case 0x778: { auto* addr = reinterpret_cast(buffer[1] | (static_cast(buffer[2]) << 32u)); @@ -2522,25 +2683,28 @@ 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[0x00c] = 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::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[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::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::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++) { @@ -2563,6 +2727,7 @@ static void graphics_init_jmp_tables() g_cp_op_func[Pm4::IT_NOP] = cp_op_nop; g_cp_op_func[Pm4::IT_INDEX_TYPE] = cp_op_index_type; + g_cp_op_func[Pm4::IT_DRAW_INDEX_AUTO] = cp_op_draw_index_auto; g_cp_op_func[Pm4::IT_WAIT_REG_MEM] = cp_op_wait_reg_mem; g_cp_op_func[Pm4::IT_WRITE_DATA] = cp_op_write_data; g_cp_op_func[Pm4::IT_INDIRECT_BUFFER] = cp_op_indirect_buffer; diff --git a/source/emulator/src/Graphics/Objects/DepthStencilBuffer.cpp b/source/emulator/src/Graphics/Objects/DepthStencilBuffer.cpp index b0c0013..534cc0e 100644 --- a/source/emulator/src/Graphics/Objects/DepthStencilBuffer.cpp +++ b/source/emulator/src/Graphics/Objects/DepthStencilBuffer.cpp @@ -31,6 +31,7 @@ static void* create_func(GraphicContext* ctx, const uint64_t* params, const uint auto pixel_format = static_cast(params[DepthStencilBufferObject::PARAM_FORMAT]); auto width = params[DepthStencilBufferObject::PARAM_WIDTH]; auto height = params[DepthStencilBufferObject::PARAM_HEIGHT]; + bool htile = params[DepthStencilBufferObject::PARAM_HTILE] != 1; EXIT_NOT_IMPLEMENTED(pixel_format == VK_FORMAT_UNDEFINED); EXIT_NOT_IMPLEMENTED(width == 0); @@ -45,6 +46,8 @@ static void* create_func(GraphicContext* ctx, const uint64_t* params, const uint vk_obj->image_view = nullptr; vk_obj->layout = VK_IMAGE_LAYOUT_UNDEFINED; + vk_obj->compressed = htile; + VkImageCreateInfo image_info {}; image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; image_info.pNext = nullptr; @@ -58,9 +61,10 @@ static void* create_func(GraphicContext* ctx, const uint64_t* params, const uint image_info.format = vk_obj->format; image_info.tiling = VK_IMAGE_TILING_OPTIMAL; image_info.initialLayout = vk_obj->layout; - image_info.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - image_info.samples = VK_SAMPLE_COUNT_1_BIT; + image_info.usage = static_cast(VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) | + static_cast(VK_IMAGE_USAGE_SAMPLED_BIT); + image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + image_info.samples = VK_SAMPLE_COUNT_1_BIT; vkCreateImage(ctx->device, &image_info, nullptr, &vk_obj->image); @@ -101,7 +105,27 @@ static void* create_func(GraphicContext* ctx, const uint64_t* params, const uint vkCreateImageView(ctx->device, &create_info, nullptr, &vk_obj->image_view); + VkImageViewCreateInfo create_info2 {}; + create_info2.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + create_info2.pNext = nullptr; + create_info2.flags = 0; + create_info2.image = vk_obj->image; + create_info2.viewType = VK_IMAGE_VIEW_TYPE_2D; + create_info2.format = vk_obj->format; + create_info2.components.r = VK_COMPONENT_SWIZZLE_R; + create_info2.components.g = VK_COMPONENT_SWIZZLE_R; + create_info2.components.b = VK_COMPONENT_SWIZZLE_R; + create_info2.components.a = VK_COMPONENT_SWIZZLE_R; + create_info2.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + create_info2.subresourceRange.baseArrayLayer = 0; + create_info2.subresourceRange.baseMipLevel = 0; + create_info2.subresourceRange.layerCount = 1; + create_info2.subresourceRange.levelCount = 1; + + vkCreateImageView(ctx->device, &create_info2, nullptr, &vk_obj->texture_view); + EXIT_NOT_IMPLEMENTED(vk_obj->image_view == nullptr); + EXIT_NOT_IMPLEMENTED(vk_obj->texture_view == nullptr); UtilSetDepthLayoutOptimal(vk_obj); @@ -119,6 +143,7 @@ static void delete_func(GraphicContext* ctx, void* obj, VulkanMemory* mem) DeleteFramebuffer(vk_obj); + vkDestroyImageView(ctx->device, vk_obj->texture_view, nullptr); vkDestroyImageView(ctx->device, vk_obj->image_view, nullptr); vkDestroyImage(ctx->device, vk_obj->image, nullptr); diff --git a/source/emulator/src/Graphics/Objects/GpuMemory.cpp b/source/emulator/src/Graphics/Objects/GpuMemory.cpp index 91ed2df..2cd3d89 100644 --- a/source/emulator/src/Graphics/Objects/GpuMemory.cpp +++ b/source/emulator/src/Graphics/Objects/GpuMemory.cpp @@ -154,7 +154,7 @@ public: 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); + Vector FindObjects(const uint64_t* vaddr, const uint64_t* size, int vaddr_num, bool exact, bool only_first); // Sync: GPU -> CPU void WriteBack(GraphicContext* ctx); @@ -217,7 +217,7 @@ private: void Free(GraphicContext* ctx, int object_id); - Vector FindBlocks(const uint64_t* vaddr, const uint64_t* size, int vaddr_num); + 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); @@ -227,7 +227,9 @@ private: 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_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); @@ -817,43 +819,96 @@ void GpuMemory::WatchCallback(void* a0, void* a1) m->m_mutex.Unlock(); } +bool GpuMemory::create_existing(const Vector& others, const GpuObject& info, int* id) +{ + EXIT_IF(id == nullptr); + + uint64_t max_gpu_update_time = 0; + const OverlappedBlock* latest_block = nullptr; + + for (const auto& obj: others) + { + 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)) + { + *id = obj.object_id; + return true; + } + + if (o.gpu_update_time > max_gpu_update_time) + { + max_gpu_update_time = o.gpu_update_time; + latest_block = &obj; + } + } + + if (latest_block != nullptr) + { + auto& h = m_objects[latest_block->object_id]; + auto& o = h.info; + + if (h.scenario == GpuMemoryScenario::GenerateMips && latest_block->relation == OverlapType::Equals && o.object.type == info.type && + info.Equal(o.params)) + { + *id = latest_block->object_id; + return true; + } + } + + return false; +} + bool GpuMemory::create_generate_mips(const Vector& others, GpuMemoryObjectType type) { - if (others.Size() == 2 && type == GpuMemoryObjectType::RenderTexture) + if (others.Size() == 3 && type == GpuMemoryObjectType::RenderTexture) { const auto& b0 = others.At(0); const auto& b1 = others.At(1); + const auto& b2 = others.At(2); OverlapType rel0 = b0.relation; OverlapType rel1 = b1.relation; + OverlapType rel2 = b2.relation; const auto& o0 = m_objects[b0.object_id]; const auto& o1 = m_objects[b1.object_id]; + const auto& o2 = m_objects[b2.object_id]; GpuMemoryObjectType type0 = o0.info.object.type; GpuMemoryObjectType type1 = o1.info.object.type; + GpuMemoryObjectType type2 = o2.info.object.type; - if (rel0 == OverlapType::Contains && rel1 == OverlapType::Contains && type0 == GpuMemoryObjectType::StorageBuffer && - type1 == GpuMemoryObjectType::StorageTexture && - ((o0.others.Size() == 1 && o0.scenario == GpuMemoryScenario::Common && o1.others.Size() == 1 && - o1.scenario == GpuMemoryScenario::Common) || - (o0.others.Size() >= 2 && o0.scenario == GpuMemoryScenario::GenerateMips && o1.others.Size() >= 2 && - o1.scenario == GpuMemoryScenario::GenerateMips))) + if (rel0 == OverlapType::Contains && rel1 == OverlapType::Contains && rel2 == OverlapType::Contains && + type0 == GpuMemoryObjectType::StorageBuffer && type1 == GpuMemoryObjectType::Texture && + type2 == GpuMemoryObjectType::StorageTexture && + ((o0.others.Size() == 2 && o0.scenario == GpuMemoryScenario::TextureTriplet && o1.others.Size() == 2 && + o1.scenario == GpuMemoryScenario::TextureTriplet && o2.others.Size() == 2 && + o2.scenario == GpuMemoryScenario::TextureTriplet) || + (o0.others.Size() >= 3 && o0.scenario == GpuMemoryScenario::GenerateMips && o1.others.Size() >= 3 && + o1.scenario == GpuMemoryScenario::GenerateMips && o2.others.Size() >= 3 && o2.scenario == GpuMemoryScenario::GenerateMips))) { return true; } - } else if (others.Size() >= 2 && type == GpuMemoryObjectType::Texture) + } else if (others.Size() >= 3 && type == GpuMemoryObjectType::Texture) { const auto& b0 = others.At(0); const auto& b1 = others.At(1); + const auto& b2 = others.At(2); OverlapType rel0 = b0.relation; OverlapType rel1 = b1.relation; + OverlapType rel2 = b2.relation; const auto& o0 = m_objects[b0.object_id]; const auto& o1 = m_objects[b1.object_id]; + const auto& o2 = m_objects[b2.object_id]; GpuMemoryObjectType type0 = o0.info.object.type; GpuMemoryObjectType type1 = o1.info.object.type; + GpuMemoryObjectType type2 = o2.info.object.type; - if (((rel0 == OverlapType::Contains && rel1 == OverlapType::Contains) || - (rel0 == OverlapType::Equals && rel1 == OverlapType::Equals)) && - type0 == GpuMemoryObjectType::StorageBuffer && type1 == GpuMemoryObjectType::StorageTexture && - o0.scenario == GpuMemoryScenario::GenerateMips && o1.scenario == GpuMemoryScenario::GenerateMips) + if (((rel0 == OverlapType::Contains && rel1 == OverlapType::Contains && rel2 == OverlapType::Contains) || + (rel0 == OverlapType::Equals && rel1 == OverlapType::Equals && rel2 == OverlapType::Equals)) && + type0 == GpuMemoryObjectType::StorageBuffer && type1 == GpuMemoryObjectType::Texture && + type2 == GpuMemoryObjectType::StorageTexture && o0.scenario == GpuMemoryScenario::GenerateMips && + o1.scenario == GpuMemoryScenario::GenerateMips && o2.scenario == GpuMemoryScenario::GenerateMips) { return true; } @@ -862,6 +917,30 @@ bool GpuMemory::create_generate_mips(const Vector& others, GpuM return false; } +bool GpuMemory::create_texture_triplet(const Vector& others, GpuMemoryObjectType type) +{ + if (others.Size() == 2 && type == GpuMemoryObjectType::StorageTexture) + { + const auto& b0 = others.At(0); + const auto& b1 = others.At(1); + OverlapType rel0 = b0.relation; + OverlapType rel1 = b1.relation; + const auto& o0 = m_objects[b0.object_id]; + const auto& o1 = m_objects[b1.object_id]; + GpuMemoryObjectType type0 = o0.info.object.type; + GpuMemoryObjectType type1 = o1.info.object.type; + + if (rel0 == OverlapType::Equals && rel1 == OverlapType::Equals && type0 == GpuMemoryObjectType::StorageBuffer && + type1 == GpuMemoryObjectType::Texture && + (o0.others.Size() == 1 && o0.scenario == GpuMemoryScenario::Common && o1.others.Size() == 1 && + o1.scenario == GpuMemoryScenario::Common)) + { + return true; + } + } + return false; +} + bool GpuMemory::create_all_the_same(const Vector& others) { OverlapType rel = others.At(0).relation; @@ -912,22 +991,22 @@ void* GpuMemory::CreateObject(GraphicContext* ctx, CommandBuffer* buffer, const if (!others.IsEmpty()) { - for (const auto& obj: others) + int existing_id = -1; + if (create_existing(others, info, &existing_id)) { - auto& h = m_objects[obj.object_id]; + auto& h = m_objects[existing_id]; EXIT_IF(h.free); auto& o = h.info; - if (obj.relation == OverlapType::Equals && o.object.type == info.type && info.Equal(o.params)) - { - Update(ctx, obj.object_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; - } + Update(ctx, existing_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; } if (others.Size() == 1) @@ -941,6 +1020,7 @@ void* GpuMemory::CreateObject(GraphicContext* ctx, CommandBuffer* buffer, const { case ObjectsRelation(GpuMemoryObjectType::StorageBuffer, OverlapType::Equals, GpuMemoryObjectType::RenderTexture): case ObjectsRelation(GpuMemoryObjectType::StorageBuffer, OverlapType::Equals, GpuMemoryObjectType::StorageTexture): + case ObjectsRelation(GpuMemoryObjectType::StorageBuffer, OverlapType::Equals, GpuMemoryObjectType::Texture): case ObjectsRelation(GpuMemoryObjectType::VideoOutBuffer, OverlapType::Equals, GpuMemoryObjectType::StorageBuffer): { overlap = true; @@ -970,6 +1050,10 @@ void* GpuMemory::CreateObject(GraphicContext* ctx, CommandBuffer* buffer, const overlap = true; create_from_objects = true; scenario = GpuMemoryScenario::GenerateMips; + } else if (create_texture_triplet(others, info.type)) + { + overlap = true; + scenario = GpuMemoryScenario::TextureTriplet; } else { if (!create_all_the_same(others)) @@ -1108,7 +1192,7 @@ 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) +Vector GpuMemory::FindObjects(const uint64_t* vaddr, const uint64_t* size, int vaddr_num, bool exact, bool only_first) { KYTY_PROFILER_BLOCK("GpuMemory::FindObjects", profiler::colors::Green200); @@ -1116,7 +1200,7 @@ Vector GpuMemory::FindObjects(const uint64_t* vaddr, const uint Core::LockGuard lock(m_mutex); - auto objects = FindBlocks(vaddr, size, vaddr_num); + auto objects = FindBlocks(vaddr, size, vaddr_num, only_first); Vector ret; @@ -1244,12 +1328,13 @@ void GpuMemory::Free(GraphicContext* ctx, int object_id) } // NOLINTNEXTLINE(readability-function-cognitive-complexity) -Vector GpuMemory::FindBlocks(const uint64_t* vaddr, const uint64_t* size, int vaddr_num) +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; @@ -1305,7 +1390,7 @@ Vector GpuMemory::FindBlocks(const uint64_t* vaddr, { if (!b.free) { - if (b.block.vaddr_num == 1) + 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) @@ -1691,11 +1776,11 @@ void* GpuMemoryCreateObject(GraphicContext* ctx, CommandBuffer* buffer, const ui return g_gpu_memory->CreateObject(ctx, buffer, vaddr, size, vaddr_num, info); } -Vector GpuMemoryFindObjects(uint64_t vaddr, uint64_t size, bool exact) +Vector GpuMemoryFindObjects(uint64_t vaddr, uint64_t size, bool exact, bool only_first) { EXIT_IF(g_gpu_memory == nullptr); - return g_gpu_memory->FindObjects(&vaddr, &size, 1, exact); + return g_gpu_memory->FindObjects(&vaddr, &size, 1, exact, only_first); } void GpuMemoryResetHash(GraphicContext* ctx, const uint64_t* vaddr, const uint64_t* size, int vaddr_num, GpuMemoryObjectType type) @@ -1746,6 +1831,11 @@ bool GpuMemoryCheckAccessViolation(uint64_t vaddr, uint64_t size) return g_gpu_memory_watcher->Check(vaddr, size); } +bool GpuMemoryWatcherEnabled() +{ + return MemoryWatcher::Enabled(); +} + bool VulkanAllocate(GraphicContext* ctx, VulkanMemory* mem) { static std::atomic seq = 0; diff --git a/source/emulator/src/Graphics/Objects/RenderTexture.cpp b/source/emulator/src/Graphics/Objects/RenderTexture.cpp index b2cc07b..3f1b7b4 100644 --- a/source/emulator/src/Graphics/Objects/RenderTexture.cpp +++ b/source/emulator/src/Graphics/Objects/RenderTexture.cpp @@ -86,10 +86,15 @@ static void update2_func(GraphicContext* ctx, CommandBuffer* buffer, const uint6 vk_obj->layout = VK_IMAGE_LAYOUT_UNDEFINED; - if (objects.Size() == 2 && objects.At(0).type == GpuMemoryObjectType::StorageBuffer && - objects.At(1).type == GpuMemoryObjectType::StorageTexture && scenario == GpuMemoryScenario::GenerateMips) + // if (objects.Size() == 2 && objects.At(0).type == GpuMemoryObjectType::StorageBuffer && + // objects.At(1).type == GpuMemoryObjectType::StorageTexture && scenario == GpuMemoryScenario::GenerateMips) + // { + // auto* src_obj = static_cast(objects.At(1).obj); + if (objects.Size() == 3 && objects.At(0).type == GpuMemoryObjectType::StorageBuffer && + objects.At(1).type == GpuMemoryObjectType::Texture && objects.At(2).type == GpuMemoryObjectType::StorageTexture && + scenario == GpuMemoryScenario::GenerateMips) { - auto* src_obj = static_cast(objects.At(1).obj); + auto* src_obj = static_cast(objects.At(2).obj); uint32_t mip_width = src_obj->extent.width; uint32_t mip_height = src_obj->extent.height; diff --git a/source/emulator/src/Graphics/Objects/Texture.cpp b/source/emulator/src/Graphics/Objects/Texture.cpp index eba21f3..ecd8916 100644 --- a/source/emulator/src/Graphics/Objects/Texture.cpp +++ b/source/emulator/src/Graphics/Objects/Texture.cpp @@ -278,10 +278,12 @@ static void update2_func(GraphicContext* ctx, CommandBuffer* buffer, const uint6 mip_height /= 2; } } - } else if (objects.Size() >= 2 && objects.At(0).type == GpuMemoryObjectType::StorageBuffer && - objects.At(1).type == GpuMemoryObjectType::StorageTexture && scenario == GpuMemoryScenario::GenerateMips) + // } else if (objects.Size() >= 2 && objects.At(0).type == GpuMemoryObjectType::StorageBuffer && + // objects.At(1).type == GpuMemoryObjectType::StorageTexture && scenario == GpuMemoryScenario::GenerateMips) + } else if (objects.Size() >= 3 && objects.At(0).type == GpuMemoryObjectType::StorageBuffer && + objects.At(1).type == GpuMemoryObjectType::Texture && objects.At(2).type == GpuMemoryObjectType::StorageTexture && + scenario == GpuMemoryScenario::GenerateMips) { - for (uint32_t i = 0; i < levels; i++) { VulkanImage* src_image = nullptr; diff --git a/source/emulator/src/Graphics/Shader.cpp b/source/emulator/src/Graphics/Shader.cpp index d2d53cb..c7a4134 100644 --- a/source/emulator/src/Graphics/Shader.cpp +++ b/source/emulator/src/Graphics/Shader.cpp @@ -1777,7 +1777,7 @@ KYTY_SHADER_PARSER(shader_parse) return ptr - src; } -static void vs_print(const char* func, const VsStageRegisters& vs) +static void vs_print(const char* func, const HW::VsStageRegisters& vs) { printf("%s\n", func); @@ -1792,7 +1792,7 @@ static void vs_print(const char* func, const VsStageRegisters& vs) printf("\t m_paClVsOutCntl = 0x%08" PRIx32 "\n", vs.m_paClVsOutCntl); } -static void ps_print(const char* func, const PsStageRegisters& ps) +static void ps_print(const char* func, const HW::PsStageRegisters& ps) { printf("%s\n", func); @@ -1820,7 +1820,7 @@ static void ps_print(const char* func, const PsStageRegisters& ps) printf("\t m_cbShaderMask = 0x%08" PRIx32 "\n", ps.m_cbShaderMask); } -static void cs_print(const char* func, const CsStageRegisters& cs) +static void cs_print(const char* func, const HW::CsStageRegisters& cs) { printf("%s\n", func); @@ -1872,7 +1872,7 @@ static void bi_print(const char* func, const ShaderBinaryInfo& bi) printf("\t crc32 = 0x%08" PRIx32 "\n", bi.crc32); } -static void vs_check(const VsStageRegisters& vs) +static void vs_check(const HW::VsStageRegisters& vs) { EXIT_NOT_IMPLEMENTED(vs.GetStreamoutEnabled() != false); // EXIT_NOT_IMPLEMENTED(vs.GetSgprCount() != 0x00000000); @@ -1884,7 +1884,7 @@ static void vs_check(const VsStageRegisters& vs) EXIT_NOT_IMPLEMENTED(vs.m_paClVsOutCntl != 0x00000000); } -static void ps_check(const PsStageRegisters& ps) +static void ps_check(const HW::PsStageRegisters& ps) { EXIT_NOT_IMPLEMENTED(ps.target_output_mode[0] != 4 && ps.target_output_mode[0] != 9); EXIT_NOT_IMPLEMENTED(ps.conservative_z_export_value != 0x00000000); @@ -1907,7 +1907,7 @@ static void ps_check(const PsStageRegisters& ps) EXIT_NOT_IMPLEMENTED(ps.m_cbShaderMask != 0x0000000f); } -static void cs_check(const CsStageRegisters& cs) +static void cs_check(const HW::CsStageRegisters& cs) { // EXIT_NOT_IMPLEMENTED(cs.num_thread_x != 0x00000040); // EXIT_NOT_IMPLEMENTED(cs.num_thread_y != 0x00000001); @@ -2207,7 +2207,7 @@ static void ShaderParseFetch(ShaderVertexInputInfo* info, const uint32_t* fetch, } static void ShaderGetStorageBuffer(ShaderStorageResources* info, int start_index, int slot, ShaderStorageUsage usage, - const UserSgprInfo& user_sgpr, const uint32_t* extended_buffer) + const HW::UserSgprInfo& user_sgpr, const uint32_t* extended_buffer) { EXIT_IF(info == nullptr); @@ -2230,7 +2230,7 @@ static void ShaderGetStorageBuffer(ShaderStorageResources* info, int start_index for (int j = 0; j < 4; j++) { auto type = user_sgpr.type[start_index + j]; - EXIT_NOT_IMPLEMENTED(type != UserSgprType::Vsharp && type != UserSgprType::Region); + EXIT_NOT_IMPLEMENTED(type != HW::UserSgprType::Vsharp && type != HW::UserSgprType::Region); } } @@ -2243,7 +2243,7 @@ static void ShaderGetStorageBuffer(ShaderStorageResources* info, int start_index } static void ShaderGetTextureBuffer(ShaderTextureResources* info, int start_index, int slot, ShaderTextureUsage usage, - const UserSgprInfo& user_sgpr, const uint32_t* extended_buffer) + const HW::UserSgprInfo& user_sgpr, const uint32_t* extended_buffer) { EXIT_IF(info == nullptr); @@ -2256,33 +2256,45 @@ static void ShaderGetTextureBuffer(ShaderTextureResources* info, int start_index EXIT_NOT_IMPLEMENTED(!extended && start_index >= 16); EXIT_NOT_IMPLEMENTED(extended && !(start_index >= 16)); - info->start_register[index] = start_index; - info->extended[index] = extended; - info->slots[index] = slot; - info->usages[index] = usage; + info->desc[index].start_register = start_index; + info->desc[index].extended = extended; + info->desc[index].slot = slot; + info->desc[index].usage = usage; + + EXIT_IF(usage == ShaderTextureUsage::Unknown); + + if (usage == ShaderTextureUsage::ReadWrite) + { + info->textures2d_storage_num++; + info->desc[index].textures2d_without_sampler = true; + } else + { + info->textures2d_sampled_num++; + info->desc[index].textures2d_without_sampler = false; + } if (!extended) { for (int j = 0; j < 8; j++) { auto type = user_sgpr.type[start_index + j]; - EXIT_NOT_IMPLEMENTED(type != UserSgprType::Vsharp && type != UserSgprType::Region); + EXIT_NOT_IMPLEMENTED(type != HW::UserSgprType::Vsharp && type != HW::UserSgprType::Region); } } - info->textures[index].fields[0] = (extended ? extended_buffer[start_index - 16 + 0] : user_sgpr.value[start_index + 0]); - info->textures[index].fields[1] = (extended ? extended_buffer[start_index - 16 + 1] : user_sgpr.value[start_index + 1]); - info->textures[index].fields[2] = (extended ? extended_buffer[start_index - 16 + 2] : user_sgpr.value[start_index + 2]); - info->textures[index].fields[3] = (extended ? extended_buffer[start_index - 16 + 3] : user_sgpr.value[start_index + 3]); - info->textures[index].fields[4] = (extended ? extended_buffer[start_index - 16 + 4] : user_sgpr.value[start_index + 4]); - info->textures[index].fields[5] = (extended ? extended_buffer[start_index - 16 + 5] : user_sgpr.value[start_index + 5]); - info->textures[index].fields[6] = (extended ? extended_buffer[start_index - 16 + 6] : user_sgpr.value[start_index + 6]); - info->textures[index].fields[7] = (extended ? extended_buffer[start_index - 16 + 7] : user_sgpr.value[start_index + 7]); + info->desc[index].texture.fields[0] = (extended ? extended_buffer[start_index - 16 + 0] : user_sgpr.value[start_index + 0]); + info->desc[index].texture.fields[1] = (extended ? extended_buffer[start_index - 16 + 1] : user_sgpr.value[start_index + 1]); + info->desc[index].texture.fields[2] = (extended ? extended_buffer[start_index - 16 + 2] : user_sgpr.value[start_index + 2]); + info->desc[index].texture.fields[3] = (extended ? extended_buffer[start_index - 16 + 3] : user_sgpr.value[start_index + 3]); + info->desc[index].texture.fields[4] = (extended ? extended_buffer[start_index - 16 + 4] : user_sgpr.value[start_index + 4]); + info->desc[index].texture.fields[5] = (extended ? extended_buffer[start_index - 16 + 5] : user_sgpr.value[start_index + 5]); + info->desc[index].texture.fields[6] = (extended ? extended_buffer[start_index - 16 + 6] : user_sgpr.value[start_index + 6]); + info->desc[index].texture.fields[7] = (extended ? extended_buffer[start_index - 16 + 7] : user_sgpr.value[start_index + 7]); info->textures_num++; } -static void ShaderGetSampler(ShaderSamplerResources* info, int start_index, int slot, const UserSgprInfo& user_sgpr, +static void ShaderGetSampler(ShaderSamplerResources* info, int start_index, int slot, const HW::UserSgprInfo& user_sgpr, const uint32_t* extended_buffer) { EXIT_IF(info == nullptr); @@ -2305,7 +2317,7 @@ static void ShaderGetSampler(ShaderSamplerResources* info, int start_index, int for (int j = 0; j < 4; j++) { auto type = user_sgpr.type[start_index + j]; - EXIT_NOT_IMPLEMENTED(type != UserSgprType::Vsharp && type != UserSgprType::Region); + EXIT_NOT_IMPLEMENTED(type != HW::UserSgprType::Vsharp && type != HW::UserSgprType::Region); } } @@ -2317,7 +2329,7 @@ static void ShaderGetSampler(ShaderSamplerResources* info, int start_index, int info->samplers_num++; } -static void ShaderGetGdsPointer(ShaderGdsResources* info, int start_index, int slot, const UserSgprInfo& user_sgpr, +static void ShaderGetGdsPointer(ShaderGdsResources* info, int start_index, int slot, const HW::UserSgprInfo& user_sgpr, const uint32_t* extended_buffer) { EXIT_IF(info == nullptr); @@ -2338,7 +2350,7 @@ static void ShaderGetGdsPointer(ShaderGdsResources* info, int start_index, int s if (!extended) { auto type = user_sgpr.type[start_index]; - EXIT_NOT_IMPLEMENTED(type != UserSgprType::Unknown); + EXIT_NOT_IMPLEMENTED(type != HW::UserSgprType::Unknown); } info->pointers[index].field = (extended ? extended_buffer[start_index - 16] : user_sgpr.value[start_index]); @@ -2381,7 +2393,7 @@ void ShaderCalcBindingIndices(ShaderBindResources* bind) EXIT_IF((bind->push_constant_size % 16) != 0); } -void ShaderGetInputInfoVS(const VertexShaderInfo* regs, ShaderVertexInputInfo* info) +void ShaderGetInputInfoVS(const HW::VertexShaderInfo* regs, ShaderVertexInputInfo* info) { KYTY_PROFILER_FUNCTION(); @@ -2468,7 +2480,7 @@ void ShaderGetInputInfoVS(const VertexShaderInfo* regs, ShaderVertexInputInfo* i } // NOLINTNEXTLINE(readability-function-cognitive-complexity) -void ShaderGetInputInfoPS(const PixelShaderInfo* regs, const ShaderVertexInputInfo* vs_info, ShaderPixelInputInfo* ps_info) +void ShaderGetInputInfoPS(const HW::PixelShaderInfo* regs, const ShaderVertexInputInfo* vs_info, ShaderPixelInputInfo* ps_info) { KYTY_PROFILER_FUNCTION(); @@ -2522,7 +2534,7 @@ void ShaderGetInputInfoPS(const PixelShaderInfo* regs, const ShaderVertexInputIn { ShaderGetTextureBuffer(&ps_info->bind.textures2D, usage.start_register, usage.slot, ShaderTextureUsage::ReadOnly, regs->ps_user_sgpr, extended_buffer); - EXIT_NOT_IMPLEMENTED(ps_info->bind.textures2D.textures[ps_info->bind.textures2D.textures_num - 1].Type() != 9); + EXIT_NOT_IMPLEMENTED(ps_info->bind.textures2D.desc[ps_info->bind.textures2D.textures_num - 1].texture.Type() != 9); } break; case 0x01: @@ -2540,7 +2552,7 @@ void ShaderGetInputInfoPS(const PixelShaderInfo* regs, const ShaderVertexInputIn { ShaderGetTextureBuffer(&ps_info->bind.textures2D, usage.start_register, usage.slot, ShaderTextureUsage::ReadWrite, regs->ps_user_sgpr, extended_buffer); - EXIT_NOT_IMPLEMENTED(ps_info->bind.textures2D.textures[ps_info->bind.textures2D.textures_num - 1].Type() != 9); + EXIT_NOT_IMPLEMENTED(ps_info->bind.textures2D.desc[ps_info->bind.textures2D.textures_num - 1].texture.Type() != 9); } break; case 0x1b: @@ -2562,7 +2574,7 @@ void ShaderGetInputInfoPS(const PixelShaderInfo* regs, const ShaderVertexInputIn } // NOLINTNEXTLINE(readability-function-cognitive-complexity) -void ShaderGetInputInfoCS(const ComputeShaderInfo* regs, ShaderComputeInputInfo* info) +void ShaderGetInputInfoCS(const HW::ComputeShaderInfo* regs, ShaderComputeInputInfo* info) { EXIT_IF(info == nullptr); EXIT_IF(regs == nullptr); @@ -2602,7 +2614,7 @@ void ShaderGetInputInfoCS(const ComputeShaderInfo* regs, ShaderComputeInputInfo* { ShaderGetTextureBuffer(&info->bind.textures2D, usage.start_register, usage.slot, ShaderTextureUsage::ReadOnly, regs->cs_user_sgpr, extended_buffer); - EXIT_NOT_IMPLEMENTED(info->bind.textures2D.textures[info->bind.textures2D.textures_num - 1].Type() != 9); + EXIT_NOT_IMPLEMENTED(info->bind.textures2D.desc[info->bind.textures2D.textures_num - 1].texture.Type() != 9); } break; case 0x02: @@ -2620,7 +2632,7 @@ void ShaderGetInputInfoCS(const ComputeShaderInfo* regs, ShaderComputeInputInfo* { ShaderGetTextureBuffer(&info->bind.textures2D, usage.start_register, usage.slot, ShaderTextureUsage::ReadWrite, regs->cs_user_sgpr, extended_buffer); - EXIT_NOT_IMPLEMENTED(info->bind.textures2D.textures[info->bind.textures2D.textures_num - 1].Type() != 9); + EXIT_NOT_IMPLEMENTED(info->bind.textures2D.desc[info->bind.textures2D.textures_num - 1].texture.Type() != 9); } break; case 0x07: @@ -2692,7 +2704,7 @@ static void ShaderDbgDumpResources(const ShaderBindResources& bind) for (int i = 0; i < bind.textures2D.textures_num; i++) { - const auto& r = bind.textures2D.textures[i]; + const auto& r = bind.textures2D.desc[i].texture; printf("\t Texture %d\n", i); @@ -2723,10 +2735,10 @@ static void ShaderDbgDumpResources(const ShaderBindResources& bind) printf("\t\t MinLodWarn() = %" PRIu16 "\n", r.MinLodWarn()); printf("\t\t CounterBankId() = %" PRIu8 "\n", r.CounterBankId()); printf("\t\t LodHdwCntEn() = %s\n", r.LodHdwCntEn() ? "true" : "false"); - printf("\t\t slot = %d\n", bind.textures2D.slots[i]); - printf("\t\t start_register = %d\n", bind.textures2D.start_register[i]); - printf("\t\t extended = %s\n", (bind.textures2D.extended[i] ? "true" : "false")); - printf("\t\t usage = %s\n", Core::EnumName(bind.textures2D.usages[i]).C_Str()); + printf("\t\t slot = %d\n", bind.textures2D.desc[i].slot); + printf("\t\t start_register = %d\n", bind.textures2D.desc[i].start_register); + printf("\t\t extended = %s\n", (bind.textures2D.desc[i].extended ? "true" : "false")); + printf("\t\t usage = %s\n", Core::EnumName(bind.textures2D.desc[i].usage).C_Str()); } for (int i = 0; i < bind.samplers.samplers_num; i++) @@ -3017,7 +3029,7 @@ private: String m_file_name; }; -ShaderCode ShaderParseVS(const VertexShaderInfo* regs) +ShaderCode ShaderParseVS(const HW::VertexShaderInfo* regs) { KYTY_PROFILER_FUNCTION(profiler::colors::Amber300); @@ -3094,7 +3106,7 @@ Vector ShaderRecompileVS(const ShaderCode& code, const ShaderVertexInp return ret; } -ShaderCode ShaderParsePS(const PixelShaderInfo* regs) +ShaderCode ShaderParsePS(const HW::PixelShaderInfo* regs) { KYTY_PROFILER_FUNCTION(profiler::colors::Blue300); @@ -3178,7 +3190,7 @@ Vector ShaderRecompilePS(const ShaderCode& code, const ShaderPixelInpu return ret; } -ShaderCode ShaderParseCS(const ComputeShaderInfo* regs) +ShaderCode ShaderParseCS(const HW::ComputeShaderInfo* regs) { KYTY_PROFILER_FUNCTION(profiler::colors::CyanA700); @@ -3246,111 +3258,110 @@ Vector ShaderRecompileCS(const ShaderCode& code, const ShaderComputeIn return ret; } -// NOLINTNEXTLINE(readability-function-cognitive-complexity) -static ShaderBindParameters ShaderUpdateBindInfo(const ShaderCode& code, const ShaderBindResources* bind) -{ - ShaderBindParameters p {}; - - auto find_image_op = [&](int index, int s, bool& found, bool& without_sampler) - { - const auto& insts = code.GetInstructions(); - int size = static_cast(insts.Size()); - for (int i = index; i < size; i++) - { - const auto& inst = insts.At(i); - - if ((inst.dst.type == ShaderOperandType::Sgpr && s >= inst.dst.register_id && s < inst.dst.register_id + inst.dst.size) || - (inst.dst2.type == ShaderOperandType::Sgpr && s >= inst.dst2.register_id && s < inst.dst2.register_id + inst.dst2.size) || - inst.type == ShaderInstructionType::SEndpgm) - { - break; - } - - if (inst.type == ShaderInstructionType::ImageStore || inst.type == ShaderInstructionType::ImageStoreMip || - inst.type == ShaderInstructionType::ImageLoad) - { - if (inst.src[1].register_id == s) - { - EXIT_NOT_IMPLEMENTED(found && !without_sampler); - without_sampler = true; - found = true; - } - } else if (inst.type == ShaderInstructionType::ImageSample) - { - if (inst.src[1].register_id == s) - { - EXIT_NOT_IMPLEMENTED(found && without_sampler); - without_sampler = false; - found = true; - } - } - } - }; - - if (bind->textures2D.textures_num > 0) - { - const auto& insts = code.GetInstructions(); - - for (int ti = 0; ti < bind->textures2D.textures_num; ti++) - { - bool found = false; - if (bind->textures2D.extended[ti]) - { - int s = bind->extended.start_register; - - int index = 0; - for (const auto& inst: insts) - { - if ((inst.dst.type == ShaderOperandType::Sgpr && s >= inst.dst.register_id && - s < inst.dst.register_id + inst.dst.size) || - (inst.dst2.type == ShaderOperandType::Sgpr && s >= inst.dst2.register_id && - s < inst.dst2.register_id + inst.dst2.size) || - inst.type == ShaderInstructionType::SEndpgm) - { - break; - } - - if (inst.type == ShaderInstructionType::SLoadDwordx8 && inst.src[0].register_id == s && - static_cast(inst.src[1].constant.u >> 2u) + 16 == bind->textures2D.start_register[ti]) - { - find_image_op(index + 1, inst.dst.register_id, found, p.textures2d_without_sampler[ti]); - } - - index++; - } - } else - { - find_image_op(0, bind->textures2D.start_register[ti], found, p.textures2d_without_sampler[ti]); - } - - EXIT_NOT_IMPLEMENTED(!found); - - if (p.textures2d_without_sampler[ti]) - { - p.textures2d_storage_num++; - } else - { - p.textures2d_sampled_num++; - } - } - } - return p; -} - -ShaderBindParameters ShaderGetBindParametersVS(const ShaderCode& code, const ShaderVertexInputInfo* input_info) -{ - return ShaderUpdateBindInfo(code, &input_info->bind); -} - -ShaderBindParameters ShaderGetBindParametersPS(const ShaderCode& code, const ShaderPixelInputInfo* input_info) -{ - return ShaderUpdateBindInfo(code, &input_info->bind); -} - -ShaderBindParameters ShaderGetBindParametersCS(const ShaderCode& code, const ShaderComputeInputInfo* input_info) -{ - return ShaderUpdateBindInfo(code, &input_info->bind); -} +//// NOLINTNEXTLINE(readability-function-cognitive-complexity) +// static ShaderBindParameters ShaderUpdateBindInfo(const ShaderCode& code, const ShaderBindResources* bind) +//{ +// ShaderBindParameters p {}; +// +// auto find_image_op = [&](int index, int s, bool& found, bool& without_sampler) +// { +// const auto& insts = code.GetInstructions(); +// int size = static_cast(insts.Size()); +// for (int i = index; i < size; i++) +// { +// const auto& inst = insts.At(i); +// +// if ((inst.dst.type == ShaderOperandType::Sgpr && s >= inst.dst.register_id && s < inst.dst.register_id + inst.dst.size) || +// (inst.dst2.type == ShaderOperandType::Sgpr && s >= inst.dst2.register_id && s < inst.dst2.register_id + inst.dst2.size) || +// inst.type == ShaderInstructionType::SEndpgm) +// { +// break; +// } +// +// if (inst.type == ShaderInstructionType::ImageStore || inst.type == ShaderInstructionType::ImageStoreMip) +// { +// if (inst.src[1].register_id == s) +// { +// EXIT_NOT_IMPLEMENTED(found && !without_sampler); +// without_sampler = true; +// found = true; +// } +// } else if (inst.type == ShaderInstructionType::ImageSample || inst.type == ShaderInstructionType::ImageLoad) +// { +// if (inst.src[1].register_id == s) +// { +// EXIT_NOT_IMPLEMENTED(found && without_sampler); +// without_sampler = false; +// found = true; +// } +// } +// } +// }; +// +// if (bind->textures2D.textures_num > 0) +// { +// const auto& insts = code.GetInstructions(); +// +// for (int ti = 0; ti < bind->textures2D.textures_num; ti++) +// { +// bool found = false; +// if (bind->textures2D.desc[ti].extended) +// { +// int s = bind->extended.start_register; +// +// int index = 0; +// for (const auto& inst: insts) +// { +// if ((inst.dst.type == ShaderOperandType::Sgpr && s >= inst.dst.register_id && +// s < inst.dst.register_id + inst.dst.size) || +// (inst.dst2.type == ShaderOperandType::Sgpr && s >= inst.dst2.register_id && +// s < inst.dst2.register_id + inst.dst2.size) || +// inst.type == ShaderInstructionType::SEndpgm) +// { +// break; +// } +// +// if (inst.type == ShaderInstructionType::SLoadDwordx8 && inst.src[0].register_id == s && +// static_cast(inst.src[1].constant.u >> 2u) + 16 == bind->textures2D.desc[ti].start_register) +// { +// find_image_op(index + 1, inst.dst.register_id, found, p.textures2d_without_sampler[ti]); +// } +// +// index++; +// } +// } else +// { +// find_image_op(0, bind->textures2D.desc[ti].start_register, found, p.textures2d_without_sampler[ti]); +// } +// +// EXIT_NOT_IMPLEMENTED(!found); +// +// if (p.textures2d_without_sampler[ti]) +// { +// p.textures2d_storage_num++; +// } else +// { +// p.textures2d_sampled_num++; +// } +// } +// } +// return p; +//} +// +// ShaderBindParameters ShaderGetBindParametersVS(const ShaderCode& code, const ShaderVertexInputInfo* input_info) +//{ +// return ShaderUpdateBindInfo(code, &input_info->bind); +//} +// +// ShaderBindParameters ShaderGetBindParametersPS(const ShaderCode& code, const ShaderPixelInputInfo* input_info) +//{ +// return ShaderUpdateBindInfo(code, &input_info->bind); +//} +// +// ShaderBindParameters ShaderGetBindParametersCS(const ShaderCode& code, const ShaderComputeInputInfo* input_info) +//{ +// return ShaderUpdateBindInfo(code, &input_info->bind); +//} static void ShaderGetBindIds(ShaderId* ret, const ShaderBindResources& bind) { @@ -3402,10 +3413,10 @@ static void ShaderGetBindIds(ShaderId* ret, const ShaderBindResources& bind) // ret->ids.Add(r.MinLodWarn()); // ret->ids.Add(r.CounterBankId()); // ret->ids.Add(static_cast(r.LodHdwCntEn())); - ret->ids.Add(bind.textures2D.slots[i]); - ret->ids.Add(bind.textures2D.start_register[i]); - ret->ids.Add(static_cast(bind.textures2D.extended[i])); - ret->ids.Add(static_cast(bind.textures2D.usages[i])); + ret->ids.Add(bind.textures2D.desc[i].slot); + ret->ids.Add(bind.textures2D.desc[i].start_register); + ret->ids.Add(static_cast(bind.textures2D.desc[i].extended)); + ret->ids.Add(static_cast(bind.textures2D.desc[i].usage)); } ret->ids.Add(bind.samplers.samplers_num); @@ -3460,7 +3471,7 @@ static void ShaderGetBindIds(ShaderId* ret, const ShaderBindResources& bind) ret->ids.Add(bind.extended.start_register); } -ShaderId ShaderGetIdVS(const VertexShaderInfo* regs, const ShaderVertexInputInfo* input_info) +ShaderId ShaderGetIdVS(const HW::VertexShaderInfo* regs, const ShaderVertexInputInfo* input_info) { KYTY_PROFILER_FUNCTION(); @@ -3526,7 +3537,7 @@ ShaderId ShaderGetIdVS(const VertexShaderInfo* regs, const ShaderVertexInputInfo return ret; } -ShaderId ShaderGetIdPS(const PixelShaderInfo* regs, const ShaderPixelInputInfo* input_info) +ShaderId ShaderGetIdPS(const HW::PixelShaderInfo* regs, const ShaderPixelInputInfo* input_info) { KYTY_PROFILER_FUNCTION(); @@ -3567,7 +3578,7 @@ ShaderId ShaderGetIdPS(const PixelShaderInfo* regs, const ShaderPixelInputInfo* return ret; } -ShaderId ShaderGetIdCS(const ComputeShaderInfo* regs, const ShaderComputeInputInfo* input_info) +ShaderId ShaderGetIdCS(const HW::ComputeShaderInfo* regs, const ShaderComputeInputInfo* input_info) { const auto* src = reinterpret_cast(regs->cs_regs.data_addr); diff --git a/source/emulator/src/Graphics/ShaderSpirv.cpp b/source/emulator/src/Graphics/ShaderSpirv.cpp index e3b7419..68829fc 100644 --- a/source/emulator/src/Graphics/ShaderSpirv.cpp +++ b/source/emulator/src/Graphics/ShaderSpirv.cpp @@ -1113,6 +1113,42 @@ constexpr char32_t EMBEDDED_SHADER_VS_0[] = UR"( OpFunctionEnd )"; +constexpr char32_t EMBEDDED_SHADER_PS_0[] = UR"( + ; #version 450 + ; + ; layout(location = 0) out vec4 outColor; + ; + ; void main() { + ; outColor = vec4(0); + ; } + + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %4 "main" %9 + OpExecutionMode %4 OriginUpperLeft + + ; Annotations + OpDecorate %9 Location 0 + + ; Types, variables and constants + %void = OpTypeVoid + %3 = OpTypeFunction %void + %float = OpTypeFloat 32 + %v4float = OpTypeVector %float 4 +%_ptr_Output_v4float = OpTypePointer Output %v4float + %9 = OpVariable %_ptr_Output_v4float Output + %float_0 = OpConstant %float 0 + %11 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0 + + ; Function 4 + %4 = OpFunction %void None %3 + %5 = OpLabel + OpStore %9 %11 + OpReturn + OpFunctionEnd +)"; + constexpr char32_t EXECZ[] = UR"( %z191_ = OpLoad %uint %exec_lo %z192_ = OpIEqual %bool %z191_ %uint_0 @@ -1219,8 +1255,8 @@ public: void SetPsInputInfo(const ShaderPixelInputInfo* input_info) { m_ps_input_info = input_info; } [[nodiscard]] const ShaderPixelInputInfo* GetPsInputInfo() const { return m_ps_input_info; } - [[nodiscard]] const ShaderBindResources* GetBindInfo() const { return m_bind; } - [[nodiscard]] const ShaderBindParameters& GetBindParams() const { return m_bind_params; } + [[nodiscard]] const ShaderBindResources* GetBindInfo() const { return m_bind; } + //[[nodiscard]] const ShaderBindParameters& GetBindParams() const { return m_bind_params; } void AddConstantUint(uint32_t u); void AddConstantInt(int i); @@ -1280,7 +1316,7 @@ private: const ShaderComputeInputInfo* m_cs_input_info = nullptr; const ShaderPixelInputInfo* m_ps_input_info = nullptr; const ShaderBindResources* m_bind = nullptr; - ShaderBindParameters m_bind_params; + // ShaderBindParameters m_bind_params; Core::Array2 m_extended_mapping {}; }; @@ -2183,11 +2219,11 @@ KYTY_RECOMPILER_FUNC(Recompile_Exp_Pos0Vsrc0Vsrc1Vsrc2Vsrc3Done) KYTY_RECOMPILER_FUNC(Recompile_ImageSample_Vdata3Vaddr3StSsDmask7) { - const auto& inst = code.GetInstructions().At(index); - const auto* bind_info = spirv->GetBindInfo(); - const auto& bind_params = spirv->GetBindParams(); + const auto& inst = code.GetInstructions().At(index); + const auto* bind_info = spirv->GetBindInfo(); + // const auto& bind_params = spirv->GetBindParams(); - if (bind_info != nullptr && bind_params.textures2d_sampled_num > 0 && bind_info->samplers.samplers_num > 0) + if (bind_info != nullptr && bind_info->textures2D.textures2d_sampled_num > 0 && bind_info->samplers.samplers_num > 0) { auto dst_value0 = operand_variable_to_str(inst.dst, 0); auto dst_value1 = operand_variable_to_str(inst.dst, 1); @@ -2248,11 +2284,11 @@ KYTY_RECOMPILER_FUNC(Recompile_ImageSample_Vdata3Vaddr3StSsDmask7) KYTY_RECOMPILER_FUNC(Recompile_ImageSample_Vdata4Vaddr3StSsDmaskF) { - const auto& inst = code.GetInstructions().At(index); - const auto* bind_info = spirv->GetBindInfo(); - const auto& bind_params = spirv->GetBindParams(); + const auto& inst = code.GetInstructions().At(index); + const auto* bind_info = spirv->GetBindInfo(); + // const auto& bind_params = spirv->GetBindParams(); - if (bind_info != nullptr && bind_params.textures2d_sampled_num > 0 && bind_info->samplers.samplers_num > 0) + if (bind_info != nullptr && bind_info->textures2D.textures2d_sampled_num > 0 && bind_info->samplers.samplers_num > 0) { auto dst_value0 = operand_variable_to_str(inst.dst, 0); auto dst_value1 = operand_variable_to_str(inst.dst, 1); @@ -2318,11 +2354,11 @@ KYTY_RECOMPILER_FUNC(Recompile_ImageSample_Vdata4Vaddr3StSsDmaskF) KYTY_RECOMPILER_FUNC(Recompile_ImageLoad_Vdata4Vaddr3StDmaskF) { - const auto& inst = code.GetInstructions().At(index); - const auto* bind_info = spirv->GetBindInfo(); - const auto& bind_params = spirv->GetBindParams(); + const auto& inst = code.GetInstructions().At(index); + const auto* bind_info = spirv->GetBindInfo(); + // const auto& bind_params = spirv->GetBindParams(); - if (bind_info != nullptr && bind_params.textures2d_storage_num > 0) + if (bind_info != nullptr && bind_info->textures2D.textures2d_sampled_num > 0) { auto dst_value0 = operand_variable_to_str(inst.dst, 0); auto dst_value1 = operand_variable_to_str(inst.dst, 1); @@ -2344,14 +2380,14 @@ KYTY_RECOMPILER_FUNC(Recompile_ImageLoad_Vdata4Vaddr3StDmaskF) static const char32_t* text = UR"( %t24_ = OpLoad %uint % - %t26_ = OpAccessChain %_ptr_UniformConstant_ImageL %textures2D_L %t24_ - %t27_ = OpLoad %ImageL %t26_ + %t26_ = OpAccessChain %_ptr_UniformConstant_ImageS %textures2D_S %t24_ + %t27_ = OpLoad %ImageS %t26_ %t67_ = OpLoad %float % %t69_ = OpBitcast %uint %t67_ %t70_ = OpLoad %float % %t71_ = OpBitcast %uint %t70_ %t73_ = OpCompositeConstruct %v2uint %t69_ %t71_ - %t74_ = OpImageRead %v4float %t27_ %t73_ + %t74_ = OpImageFetch %v4float %t27_ %t73_ OpStore %temp_v4float %t74_ %t46_ = OpAccessChain %_ptr_Function_float %temp_v4float %uint_0 %t47_ = OpLoad %float %t46_ @@ -2385,11 +2421,11 @@ KYTY_RECOMPILER_FUNC(Recompile_ImageLoad_Vdata4Vaddr3StDmaskF) KYTY_RECOMPILER_FUNC(Recompile_ImageStore_Vdata4Vaddr3StDmaskF) { - const auto& inst = code.GetInstructions().At(index); - const auto* bind_info = spirv->GetBindInfo(); - const auto& bind_params = spirv->GetBindParams(); + const auto& inst = code.GetInstructions().At(index); + const auto* bind_info = spirv->GetBindInfo(); + // const auto& bind_params = spirv->GetBindParams(); - if (bind_info != nullptr && bind_params.textures2d_storage_num > 0) + if (bind_info != nullptr && bind_info->textures2D.textures2d_storage_num > 0) { auto dst_value0 = operand_variable_to_str(inst.dst, 0); auto dst_value1 = operand_variable_to_str(inst.dst, 1); @@ -2453,11 +2489,11 @@ KYTY_RECOMPILER_FUNC(Recompile_ImageStore_Vdata4Vaddr3StDmaskF) KYTY_RECOMPILER_FUNC(Recompile_ImageStoreMip_Vdata4Vaddr4StDmaskF) { - const auto& inst = code.GetInstructions().At(index); - const auto* bind_info = spirv->GetBindInfo(); - const auto& bind_params = spirv->GetBindParams(); + const auto& inst = code.GetInstructions().At(index); + const auto* bind_info = spirv->GetBindInfo(); + // const auto& bind_params = spirv->GetBindParams(); - if (bind_info != nullptr && bind_params.textures2d_storage_num > 0) + if (bind_info != nullptr && bind_info->textures2D.textures2d_storage_num > 0) { auto dst_value0 = operand_variable_to_str(inst.dst, 0); auto dst_value1 = operand_variable_to_str(inst.dst, 1); @@ -5206,20 +5242,20 @@ void Spirv::GenerateSource() switch (m_code.GetType()) { case ShaderType::Pixel: - m_bind = (m_ps_input_info != nullptr ? &m_ps_input_info->bind : nullptr); - m_bind_params = (m_ps_input_info != nullptr ? ShaderGetBindParametersPS(m_code, m_ps_input_info) : ShaderBindParameters()); + m_bind = (m_ps_input_info != nullptr ? &m_ps_input_info->bind : nullptr); + // m_bind_params = (m_ps_input_info != nullptr ? ShaderGetBindParametersPS(m_code, m_ps_input_info) : ShaderBindParameters()); break; case ShaderType::Vertex: - m_bind = (m_vs_input_info != nullptr ? &m_vs_input_info->bind : nullptr); - m_bind_params = (m_vs_input_info != nullptr ? ShaderGetBindParametersVS(m_code, m_vs_input_info) : ShaderBindParameters()); + m_bind = (m_vs_input_info != nullptr ? &m_vs_input_info->bind : nullptr); + // m_bind_params = (m_vs_input_info != nullptr ? ShaderGetBindParametersVS(m_code, m_vs_input_info) : ShaderBindParameters()); break; case ShaderType::Compute: - m_bind = (m_cs_input_info != nullptr ? &m_cs_input_info->bind : nullptr); - m_bind_params = (m_cs_input_info != nullptr ? ShaderGetBindParametersCS(m_code, m_cs_input_info) : ShaderBindParameters()); + m_bind = (m_cs_input_info != nullptr ? &m_cs_input_info->bind : nullptr); + // m_bind_params = (m_cs_input_info != nullptr ? ShaderGetBindParametersCS(m_code, m_cs_input_info) : ShaderBindParameters()); break; default: - m_bind = nullptr; - m_bind_params = ShaderBindParameters(); + m_bind = nullptr; + // m_bind_params = ShaderBindParameters(); break; } @@ -5269,11 +5305,11 @@ void Spirv::WriteHeader() { vars.Add(U"%buf"); } - if (m_bind_params.textures2d_sampled_num > 0) + if (m_bind->textures2D.textures2d_sampled_num > 0) { vars.Add(U"%textures2D_S"); } - if (m_bind_params.textures2d_storage_num > 0) + if (m_bind->textures2D.textures2d_storage_num > 0) { vars.Add(U"%textures2D_L"); } @@ -5473,13 +5509,13 @@ void Spirv::WriteAnnotations() .ReplaceStr(U"", String::FromPrintf("%u", m_bind->descriptor_set_slot)) .ReplaceStr(U"", String::FromPrintf("%d", m_bind->storage_buffers.binding_index)); } - if (m_bind_params.textures2d_sampled_num > 0) + if (m_bind->textures2D.textures2d_sampled_num > 0) { m_source += String(textures_annotations_s) .ReplaceStr(U"", String::FromPrintf("%u", m_bind->descriptor_set_slot)) .ReplaceStr(U"", String::FromPrintf("%d", m_bind->textures2D.binding_sampled_index)); } - if (m_bind_params.textures2d_storage_num > 0) + if (m_bind->textures2D.textures2d_storage_num > 0) { m_source += String(textures_annotations_l) .ReplaceStr(U"", String::FromPrintf("%u", m_bind->descriptor_set_slot)) @@ -5645,15 +5681,15 @@ void Spirv::WriteTypes() m_source += String(storage_buffers_types).ReplaceStr(U"", String::FromPrintf("%d", m_bind->storage_buffers.buffers_num)); } - if (m_bind_params.textures2d_sampled_num > 0) + if (m_bind->textures2D.textures2d_sampled_num > 0) { - m_source += - String(textures_sampled_types).ReplaceStr(U"", String::FromPrintf("%d", m_bind_params.textures2d_sampled_num)); + m_source += String(textures_sampled_types) + .ReplaceStr(U"", String::FromPrintf("%d", m_bind->textures2D.textures2d_sampled_num)); } - if (m_bind_params.textures2d_storage_num > 0) + if (m_bind->textures2D.textures2d_storage_num > 0) { - m_source += - String(textures_loaded_types).ReplaceStr(U"", String::FromPrintf("%d", m_bind_params.textures2d_storage_num)); + m_source += String(textures_loaded_types) + .ReplaceStr(U"", String::FromPrintf("%d", m_bind->textures2D.textures2d_storage_num)); } if (m_bind->samplers.samplers_num > 0) { @@ -5719,15 +5755,15 @@ void Spirv::WriteGlobalVariables() vars.Add(String::FromPrintf("%%buf = OpVariable %%_ptr_StorageBuffer__arr_BufferObject_uint_%d StorageBuffer", m_bind->storage_buffers.buffers_num)); } - if (m_bind_params.textures2d_sampled_num > 0) + if (m_bind->textures2D.textures2d_sampled_num > 0) { vars.Add(String::FromPrintf("%%textures2D_S = OpVariable %%_ptr_UniformConstant__arr_ImageS_uint_%d UniformConstant", - m_bind_params.textures2d_sampled_num)); + m_bind->textures2D.textures2d_sampled_num)); } - if (m_bind_params.textures2d_storage_num > 0) + if (m_bind->textures2D.textures2d_storage_num > 0) { vars.Add(String::FromPrintf("%%textures2D_L = OpVariable %%_ptr_UniformConstant__arr_ImageL_uint_%d UniformConstant", - m_bind_params.textures2d_storage_num)); + m_bind->textures2D.textures2d_storage_num)); } if (m_bind->samplers.samplers_num > 0) { @@ -5950,8 +5986,8 @@ void Spirv::WriteLocalVariables() for (int i = 0; i < m_bind->textures2D.textures_num; i++) { - int start_reg = m_bind->textures2D.start_register[i]; - bool extended = m_bind->textures2D.extended[i]; + int start_reg = m_bind->textures2D.desc[i].start_register; + bool extended = m_bind->textures2D.desc[i].extended; for (int ti = 0; ti < 2; ti++) { @@ -6304,7 +6340,7 @@ void Spirv::FindVariables() } for (int i = 0; i < m_bind->textures2D.textures_num; i++) { - int storage_start = m_bind->textures2D.start_register[i]; + int storage_start = m_bind->textures2D.desc[i].start_register; AddVariable(ShaderOperandType::Sgpr, storage_start, 8); } for (int i = 0; i < m_bind->samplers.samplers_num; i++) @@ -6339,9 +6375,7 @@ String SpirvGetEmbeddedPs(uint32_t id) { EXIT_NOT_IMPLEMENTED(id != 0); - KYTY_NOT_IMPLEMENTED; - - return U""; + return EMBEDDED_SHADER_PS_0; } } // namespace Kyty::Libs::Graphics diff --git a/source/emulator/src/Graphics/Tile.cpp b/source/emulator/src/Graphics/Tile.cpp index ee4cc7e..73474b8 100644 --- a/source/emulator/src/Graphics/Tile.cpp +++ b/source/emulator/src/Graphics/Tile.cpp @@ -673,6 +673,11 @@ void TileGetTextureSize(uint32_t dfmt, uint32_t nfmt, uint32_t width, uint32_t h { {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, } }, { 10, 0, 256, 256, 9, 14, true, {262144, 65536, 16384, 4096, 1024, 256, 256, 256, 256, }, { {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, } }, + // kDataFormatR32Float, 1920, 1080, kTileModeDepth_2dThin_256 + { 4, 7, 1920, 1080, 11, 2, false, {8355840, 12615680, 1048576, 262144, 65536, 16384, 2048, 1024, 1024, 1024, 1024, }, + { {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, } }, + { 4, 7, 1920, 1080, 11, 2, true, {8847360, 12124160, 1048576, 262144, 65536, 16384, 2048, 1024, 1024, 1024, 1024, }, + { {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, } }, // clang-format on }; diff --git a/source/emulator/src/Graphics/Window.cpp b/source/emulator/src/Graphics/Window.cpp index 0862465..a107275 100644 --- a/source/emulator/src/Graphics/Window.cpp +++ b/source/emulator/src/Graphics/Window.cpp @@ -1298,10 +1298,17 @@ static VkPhysicalDevice VulkanFindPhysicalDevice(VkInstance instance, VkSurfaceK bool skip_device = true; VkPhysicalDeviceProperties device_properties {}; - VkPhysicalDeviceFeatures device_features {}; + VkPhysicalDeviceFeatures2 device_features2 {}; + + VkPhysicalDeviceColorWriteEnableFeaturesEXT color_write_ext {}; + color_write_ext.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COLOR_WRITE_ENABLE_FEATURES_EXT; + color_write_ext.pNext = nullptr; + + device_features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; + device_features2.pNext = &color_write_ext; vkGetPhysicalDeviceProperties(device, &device_properties); - vkGetPhysicalDeviceFeatures(device, &device_features); + vkGetPhysicalDeviceFeatures2(device, &device_features2); printf("Vulkan device: %s\n", device_properties.deviceName); @@ -1331,7 +1338,14 @@ static VkPhysicalDevice VulkanFindPhysicalDevice(VkInstance instance, VkSurfaceK } } - if (device_features.fragmentStoresAndAtomics != VK_TRUE) + if (color_write_ext.colorWriteEnable != VK_TRUE) + { + + printf("colorWriteEnable is not supported\n"); + skip_device = true; + } + + if (device_features2.features.fragmentStoresAndAtomics != VK_TRUE) { printf("fragmentStoresAndAtomics is not supported\n"); skip_device = true; @@ -1529,9 +1543,14 @@ static VkDevice VulkanCreateDevice(VkPhysicalDevice physical_device, VkSurfaceKH VkPhysicalDeviceFeatures device_features {}; device_features.fragmentStoresAndAtomics = VK_TRUE; + VkPhysicalDeviceColorWriteEnableFeaturesEXT color_write_ext {}; + color_write_ext.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COLOR_WRITE_ENABLE_FEATURES_EXT; + color_write_ext.pNext = nullptr; + color_write_ext.colorWriteEnable = VK_TRUE; + VkDeviceCreateInfo create_info {}; create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; - create_info.pNext = nullptr; + create_info.pNext = &color_write_ext; create_info.flags = 0; create_info.pQueueCreateInfos = &queue_create_info; create_info.queueCreateInfoCount = 1; @@ -1965,7 +1984,7 @@ static void VulkanCreate(WindowContext* ctx) } Vector device_extensions = {VK_KHR_SWAPCHAIN_EXTENSION_NAME, VK_EXT_DEPTH_CLIP_ENABLE_EXTENSION_NAME, - "VK_KHR_maintenance1"}; + VK_EXT_COLOR_WRITE_ENABLE_EXTENSION_NAME, "VK_KHR_maintenance1"}; #ifdef KYTY_ENABLE_DEBUG_PRINTF if (Config::SpirvDebugPrintfEnabled()) diff --git a/source/emulator/src/RuntimeLinker.cpp b/source/emulator/src/RuntimeLinker.cpp index 33cbade..553564b 100644 --- a/source/emulator/src/RuntimeLinker.cpp +++ b/source/emulator/src/RuntimeLinker.cpp @@ -1057,7 +1057,10 @@ void RuntimeLinker::LoadProgramToMemory(Program* program) program->base_vaddr + program->base_size_aligned + exception_handler_size + tls_handler_size, kyty_exception_handler); - VirtualMemory::ExceptionHandler::InstallVectored(kyty_exception_handler); + if (Libs::Graphics::GpuMemoryWatcherEnabled()) + { + VirtualMemory::ExceptionHandler::InstallVectored(kyty_exception_handler); + } } // program->elf->SetBaseVAddr(program->base_vaddr);