Initial commit

This commit is contained in:
InoriRus
2021-12-01 19:29:27 +10:00
parent b1e7dcdc5d
commit 43f49c8763
1843 changed files with 1111694 additions and 0 deletions
@@ -0,0 +1,94 @@
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_ASYNCJOB_H_
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_ASYNCJOB_H_
#include "Kyty/Core/Common.h"
#include "Kyty/Core/Threads.h"
#include "Emulator/Common.h"
#include "Emulator/Profiler.h"
#ifdef KYTY_EMU_ENABLED
namespace Kyty::Libs::Graphics {
class AsyncJob
{
public:
using func_t = std::function<void(void*)>;
explicit AsyncJob(const char* name): m_name(name) { m_thread = new Core::Thread(ThreadRun, this); }
virtual ~AsyncJob()
{
EXIT_IF(m_thread == nullptr);
Core::LockGuard lock(m_mutex);
m_need_exit = true;
m_cond_var1.Signal();
m_thread->Join();
delete m_thread;
}
KYTY_CLASS_NO_COPY(AsyncJob);
void Execute(func_t func, void* arg = nullptr)
{
Core::LockGuard lock(m_mutex);
while (m_func != nullptr)
{
m_cond_var2.Wait(&m_mutex);
}
m_func = std::move(func);
m_arg = arg;
m_cond_var1.Signal();
}
void Wait()
{
Core::LockGuard lock(m_mutex);
while (m_func != nullptr)
{
m_cond_var2.Wait(&m_mutex);
}
}
private:
Core::Mutex m_mutex;
Core::CondVar m_cond_var1;
Core::CondVar m_cond_var2;
Core::Thread* m_thread = nullptr;
const char* m_name = nullptr;
func_t m_func = nullptr;
void* m_arg = nullptr;
bool m_need_exit = false;
static void ThreadRun(void* data)
{
// printf("Start AsyncJob Thread: 0x%" PRIx64 "\n", static_cast<uint64_t>(GetCurrentThreadId()));
auto* aj = static_cast<AsyncJob*>(data);
if (aj->m_name != nullptr)
{
KYTY_PROFILER_THREAD(aj->m_name);
}
for (;;)
{
Core::LockGuard lock(aj->m_mutex);
while (aj->m_func == nullptr && !aj->m_need_exit)
{
aj->m_cond_var1.Wait(&aj->m_mutex);
}
if (aj->m_need_exit)
{
break;
}
aj->m_func(aj->m_arg);
aj->m_func = nullptr;
aj->m_cond_var2.Signal();
}
}
};
} // namespace Kyty::Libs::Graphics
#endif // KYTY_EMU_ENABLED
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_ASYNCJOB_H_ */
@@ -0,0 +1,48 @@
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_DEPTHSTENCILBUFFER_H_
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_DEPTHSTENCILBUFFER_H_
#include "Kyty/Core/Common.h"
#include "Emulator/Common.h"
#include "Emulator/Graphics/GpuMemory.h"
#ifdef KYTY_EMU_ENABLED
namespace Kyty::Libs::Graphics {
struct GraphicContext;
struct VulkanMemory;
class DepthStencilBufferObject: public GpuObject
{
public:
static constexpr int PARAM_FORMAT = 0;
static constexpr int PARAM_WIDTH = 1;
static constexpr int PARAM_HEIGHT = 2;
static constexpr int PARAM_HTILE = 3;
static constexpr int PARAM_NEO = 4;
DepthStencilBufferObject(uint64_t vk_format, uint32_t width, uint32_t height, bool htile, bool neo)
{
params[PARAM_FORMAT] = vk_format;
params[PARAM_WIDTH] = width;
params[PARAM_HEIGHT] = height;
params[PARAM_HTILE] = htile ? 1 : 0;
params[PARAM_NEO] = neo ? 1 : 0;
check_hash = false;
type = Graphics::GpuMemoryObjectType::DepthStencilBuffer;
}
void* Create(GraphicContext* ctx, const uint64_t* vaddr, const uint64_t* size, int vaddr_num, VulkanMemory* mem) const override;
bool Equal(const uint64_t* other) const override;
[[nodiscard]] write_back_func_t GetWriteBackFunc() const override { return nullptr; };
[[nodiscard]] delete_func_t GetDeleteFunc() const override;
[[nodiscard]] update_func_t GetUpdateFunc() const override;
};
} // namespace Kyty::Libs::Graphics
#endif // KYTY_EMU_ENABLED
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_DEPTHSTENCILBUFFER_H_ */
@@ -0,0 +1,99 @@
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_GPUMEMORY_H_
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_GPUMEMORY_H_
#include "Kyty/Core/Common.h"
#include "Emulator/Common.h"
#ifdef KYTY_EMU_ENABLED
namespace Kyty::Libs::Graphics {
struct GraphicContext;
struct VulkanMemory;
struct VulkanBuffer;
struct TextureVulkanImage;
struct VideoOutVulkanImage;
struct DepthStencilVulkanImage;
enum class GpuMemoryMode
{
NoAccess,
Read,
Write,
ReadWrite
};
enum class GpuMemoryObjectType
{
Invalid,
VideoOutBuffer,
DepthStencilBuffer,
Label,
IndexBuffer,
VertexBuffer,
StorageBuffer,
Texture
};
class GpuObject
{
public:
using write_back_func_t = void (*)(GraphicContext* ctx, void* obj, const uint64_t* vaddr, const uint64_t* size, int vaddr_num);
using delete_func_t = void (*)(GraphicContext* ctx, void* obj, VulkanMemory* mem);
using update_func_t = void (*)(GraphicContext* ctx, const uint64_t* params, void* obj, const uint64_t* vaddr, const uint64_t* size,
int vaddr_num);
static constexpr int PARAMS_MAX = 8;
GpuObject() = default;
virtual ~GpuObject() = default;
KYTY_CLASS_DEFAULT_COPY(GpuObject);
virtual void* Create(GraphicContext* ctx, const uint64_t* vaddr, const uint64_t* size, int vaddr_num, VulkanMemory* mem) const = 0;
virtual bool Equal(const uint64_t* other) const = 0;
[[nodiscard]] virtual write_back_func_t GetWriteBackFunc() const = 0;
[[nodiscard]] virtual delete_func_t GetDeleteFunc() const = 0;
[[nodiscard]] virtual update_func_t GetUpdateFunc() const = 0;
uint64_t params[PARAMS_MAX] = {};
bool check_hash = false;
bool read_only = false;
GpuMemoryObjectType type = GpuMemoryObjectType::Invalid;
};
void GpuMemoryInit();
void GpuMemorySetAllocatedRange(uint64_t vaddr, uint64_t size);
void GpuMemoryFree(GraphicContext* ctx, uint64_t vaddr, uint64_t size);
void* GpuMemoryGetObject(GraphicContext* ctx, uint64_t vaddr, uint64_t size, const GpuObject& info);
void* GpuMemoryGetObject(GraphicContext* ctx, const uint64_t* vaddr, const uint64_t* size, int vaddr_num, const GpuObject& info);
void GpuMemoryResetHash(GraphicContext* ctx, uint64_t vaddr, uint64_t size, GpuMemoryObjectType type);
void GpuMemoryDbgDump();
void GpuMemoryFlush();
void GpuMemoryFrameDone();
void GpuMemoryWriteBack(GraphicContext* ctx);
bool VulkanAllocate(GraphicContext* ctx, VulkanMemory* mem);
void VulkanFree(GraphicContext* ctx, VulkanMemory* mem);
void VulkanMapMemory(GraphicContext* ctx, VulkanMemory* mem, void** data);
void VulkanUnmapMemory(GraphicContext* ctx, VulkanMemory* mem);
void VulkanBindImageMemory(GraphicContext* ctx, TextureVulkanImage* image, VulkanMemory* mem);
void VulkanBindImageMemory(GraphicContext* ctx, VideoOutVulkanImage* image, VulkanMemory* mem);
void VulkanBindImageMemory(GraphicContext* ctx, DepthStencilVulkanImage* image, VulkanMemory* mem);
void VulkanBindBufferMemory(GraphicContext* ctx, VulkanBuffer* buffer, VulkanMemory* mem);
void GpuMemoryRegisterOwner(uint32_t* owner_handle, const char* name);
void GpuMemoryRegisterResource(uint32_t* resource_handle, uint32_t owner_handle, const void* memory, size_t size, const char* name,
uint32_t type, uint64_t user_data);
void GpuMemoryUnregisterAllResourcesForOwner(uint32_t owner_handle);
void GpuMemoryUnregisterOwnerAndResources(uint32_t owner_handle);
void GpuMemoryUnregisterResource(uint32_t resource_handle);
} // namespace Kyty::Libs::Graphics
#endif // KYTY_EMU_ENABLED
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_GPUMEMORY_H_ */
@@ -0,0 +1,106 @@
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_GRAPHICCONTEXT_H_
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_GRAPHICCONTEXT_H_
#include "Kyty/Core/Common.h"
#include "Kyty/Core/Threads.h"
#include "Emulator/Common.h"
#include <vulkan/vulkan_core.h>
#ifdef KYTY_EMU_ENABLED
namespace Kyty::Libs::Graphics {
struct VulkanSwapchain
{
VkSwapchainKHR swapchain = nullptr;
VkFormat swapchain_format = VK_FORMAT_UNDEFINED;
VkExtent2D swapchain_extent = {};
VkImage* swapchain_images = nullptr;
VkImageView* swapchain_image_views = nullptr;
uint32_t swapchain_images_count = 0;
VkSemaphore present_complete_semaphore = nullptr;
VkFence present_complete_fence = nullptr;
uint32_t current_index = 0;
};
struct VulkanCommandPool
{
Core::Mutex mutex;
VkCommandPool pool = nullptr;
VkCommandBuffer* buffers = nullptr;
VkFence* fences = nullptr;
VkSemaphore* semaphores = nullptr;
bool* busy = nullptr;
uint32_t buffers_count = 0;
};
struct GraphicContext
{
static constexpr int QUEUES_NUM = 11;
static constexpr int QUEUE_GFX = 8;
static constexpr int QUEUE_UTIL = 9;
static constexpr int QUEUE_PRESENT = 10;
static constexpr int QUEUE_COMPUTE_START = 0;
static constexpr int QUEUE_COMPUTE_NUM = 8;
uint32_t screen_width = 0;
uint32_t screen_height = 0;
VkInstance instance = nullptr;
VkDebugUtilsMessengerEXT debug_messenger = nullptr;
VkPhysicalDevice physical_device = nullptr;
VkDevice device = nullptr;
uint32_t queue_family_index = static_cast<uint32_t>(-1);
VkQueue queue[QUEUES_NUM] = {};
};
struct VulkanMemory
{
VkMemoryRequirements requirements = {};
VkMemoryPropertyFlags property = 0;
VkDeviceMemory memory = nullptr;
VkDeviceSize offset = 0;
uint32_t type = 0;
uint64_t unique_id = 0;
};
struct VideoOutVulkanImage
{
VkFormat format = VK_FORMAT_UNDEFINED;
VkExtent2D extent = {};
VkImage image = nullptr;
VkImageView image_view = nullptr;
Graphics::VulkanMemory memory;
};
struct DepthStencilVulkanImage
{
VkFormat format = VK_FORMAT_UNDEFINED;
VkExtent2D extent = {};
VkImage image = nullptr;
VkImageView image_view = nullptr;
Graphics::VulkanMemory memory;
};
struct TextureVulkanImage
{
VkFormat format = VK_FORMAT_UNDEFINED;
VkExtent2D extent = {};
VkImage image = nullptr;
VkImageView image_view = nullptr;
Graphics::VulkanMemory memory;
};
struct VulkanBuffer
{
VkBuffer buffer = nullptr;
VulkanMemory memory;
VkBufferUsageFlags usage = 0;
};
} // namespace Kyty::Libs::Graphics
#endif // KYTY_EMU_ENABLED
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_GRAPHICCONTEXT_H_ */
@@ -0,0 +1,60 @@
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_GRAPHICS_H_
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_GRAPHICS_H_
#include "Kyty/Core/Common.h"
#include "Kyty/Core/Subsystems.h"
#include "Emulator/Common.h"
#include "Emulator/Kernel/EventQueue.h"
#ifdef KYTY_EMU_ENABLED
namespace Kyty::Libs::Graphics {
struct VsStageRegisters;
KYTY_SUBSYSTEM_DEFINE(Graphics);
int KYTY_SYSV_ABI GraphicsSetVsShader(uint32_t* cmd, uint64_t size, const VsStageRegisters* vs_regs, uint32_t shader_modifier);
int KYTY_SYSV_ABI GraphicsSetPsShader350(uint32_t* cmd, uint64_t size, const uint32_t* ps_regs);
int KYTY_SYSV_ABI GraphicsSetCsShaderWithModifier(uint32_t* cmd, uint64_t size, const uint32_t* cs_regs, uint32_t shader_modifier);
int KYTY_SYSV_ABI GraphicsSetEmbeddedVsShader(uint32_t* cmd, uint64_t size, uint32_t id, uint32_t shader_modifier);
int KYTY_SYSV_ABI GraphicsDrawIndex(uint32_t* cmd, uint64_t size, uint32_t index_count, const void* index_addr, uint32_t flags,
uint32_t type);
int KYTY_SYSV_ABI GraphicsDrawIndexAuto(uint32_t* cmd, uint64_t size, uint32_t index_count, uint32_t flags);
int KYTY_SYSV_ABI GraphicsSubmitCommandBuffers(uint32_t count, void* dcb_gpu_addrs[], const uint32_t* dcb_sizes_in_bytes,
void* ccb_gpu_addrs[], const uint32_t* ccb_sizes_in_bytes);
int KYTY_SYSV_ABI GraphicsSubmitAndFlipCommandBuffers(uint32_t count, void* dcb_gpu_addrs[], const uint32_t* dcb_sizes_in_bytes,
void* ccb_gpu_addrs[], const uint32_t* ccb_sizes_in_bytes, int handle, int index,
int flip_mode, int64_t flip_arg);
int KYTY_SYSV_ABI GraphicsSubmitDone();
void KYTY_SYSV_ABI GraphicsFlushMemory();
int KYTY_SYSV_ABI GraphicsAddEqEvent(LibKernel::EventQueue::KernelEqueue eq, int id, void* udata);
int KYTY_SYSV_ABI GraphicsDeleteEqEvent(LibKernel::EventQueue::KernelEqueue eq, int id);
uint32_t KYTY_SYSV_ABI GraphicsDrawInitDefaultHardwareState350(uint32_t* cmd, uint64_t size);
uint32_t KYTY_SYSV_ABI GraphicsDispatchInitDefaultHardwareState(uint32_t* cmd, uint64_t size);
int KYTY_SYSV_ABI GraphicsInsertWaitFlipDone(uint32_t* cmd, uint64_t size, uint32_t video_out_handle, uint32_t display_buffer_index);
int KYTY_SYSV_ABI GraphicsDispatchDirect(uint32_t* cmd, uint64_t size, uint32_t thread_group_x, uint32_t thread_group_y,
uint32_t thread_group_z, uint32_t mode);
uint32_t KYTY_SYSV_ABI GraphicsMapComputeQueue(uint32_t pipe_id, uint32_t queue_id, uint32_t* ring_addr, uint32_t ring_size_dw,
uint32_t* read_ptr_addr);
int KYTY_SYSV_ABI GraphicsComputeWaitOnAddress(uint32_t* cmd, uint64_t size, uint32_t* gpu_addr, uint32_t mask, uint32_t func,
uint32_t ref);
void KYTY_SYSV_ABI GraphicsDingDong(uint32_t ring_id, uint32_t offset_dw);
void KYTY_SYSV_ABI GraphicsUnmapComputeQueue(uint32_t id);
int KYTY_SYSV_ABI GraphicsInsertPushMarker(uint32_t* cmd, uint64_t size, const char* str);
int KYTY_SYSV_ABI GraphicsInsertPopMarker(uint32_t* cmd, uint64_t size);
uint64_t KYTY_SYSV_ABI GraphicsGetGpuCoreClockFrequency();
int KYTY_SYSV_ABI GraphicsRegisterOwner(uint32_t* owner_handle, const char* name);
int KYTY_SYSV_ABI GraphicsRegisterResource(uint32_t* resource_handle, uint32_t owner_handle, const void* memory, size_t size,
const char* name, uint32_t type, uint64_t user_data);
int KYTY_SYSV_ABI GraphicsUnregisterAllResourcesForOwner(uint32_t owner_handle);
int KYTY_SYSV_ABI GraphicsUnregisterOwnerAndResources(uint32_t owner_handle);
int KYTY_SYSV_ABI GraphicsUnregisterResource(uint32_t resource_handle);
} // namespace Kyty::Libs::Graphics
#endif // KYTY_EMU_ENABLED
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_GRAPHICS_H_ */
@@ -0,0 +1,92 @@
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_GRAPHICSRENDER_H_
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_GRAPHICSRENDER_H_
#include "Kyty/Core/Common.h"
#include "Emulator/Common.h"
#include "Emulator/Kernel/EventQueue.h"
#ifdef KYTY_EMU_ENABLED
namespace Kyty::Libs::Graphics {
class HardwareContext;
class UserConfig;
struct VideoOutVulkanImage;
struct DepthStencilVulkanImage;
struct TextureVulkanImage;
struct VulkanCommandPool;
struct VulkanBuffer;
struct VulkanFramebuffer;
struct RenderDepthInfo;
struct RenderColorInfo;
class CommandBuffer
{
public:
CommandBuffer() { Allocate(); }
virtual ~CommandBuffer() { Free(); }
KYTY_CLASS_NO_COPY(CommandBuffer);
[[nodiscard]] bool IsInvalid() const;
void Allocate();
void Free();
void Begin() const;
void End() const;
void Execute();
void ExecuteWithSemaphore();
VulkanFramebuffer* BeginRenderPass(RenderColorInfo* color, RenderDepthInfo* depth) const;
void EndRenderPass() const;
void WaitForFence();
void WaitForFenceAndReset();
[[nodiscard]] uint32_t GetIndex() const { return m_index; }
VulkanCommandPool* GetPool() { return m_pool; }
[[nodiscard]] bool IsExecute() const { return m_execute; }
void SetQueue(int queue) { m_queue = queue; }
private:
VulkanCommandPool* m_pool = nullptr;
uint32_t m_index = static_cast<uint32_t>(-1);
int m_queue = -1;
bool m_execute = false;
};
void GraphicsRenderInit();
void GraphicsRenderCreateContext();
void GraphicsRenderDrawIndex(CommandBuffer* buffer, HardwareContext* ctx, 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 GraphicsRenderWriteAtEndOfPipe(CommandBuffer* buffer, uint64_t* dst_gpu_addr, uint64_t value);
void GraphicsRenderWriteAtEndOfPipeClockCounter(CommandBuffer* buffer, uint64_t* dst_gpu_addr);
void GraphicsRenderWriteAtEndOfPipe(CommandBuffer* buffer, uint32_t* dst_gpu_addr, uint32_t value);
void GraphicsRenderWriteAtEndOfPipeGds(CommandBuffer* buffer, uint32_t* dst_gpu_addr, uint32_t dw_offset, uint32_t dw_num);
void GraphicsRenderWriteAtEndOfPipeWithInterruptWriteBackFlip(CommandBuffer* buffer, uint32_t* dst_gpu_addr, uint32_t value, int handle,
int index, int flip_mode, int64_t flip_arg);
void GraphicsRenderWriteAtEndOfPipeWithWriteBack(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,
uint32_t thread_group_z, uint32_t mode);
void GraphicsRenderMemoryBarrier(CommandBuffer* buffer);
void DeleteFramebuffer(VideoOutVulkanImage* image);
void DeleteFramebuffer(DepthStencilVulkanImage* image);
void DeleteDescriptor(VulkanBuffer* buffer);
void DeleteDescriptor(TextureVulkanImage* image);
int GraphicsRenderAddEqEvent(LibKernel::EventQueue::KernelEqueue eq, int id, void* udata);
int GraphicsRenderDeleteEqEvent(LibKernel::EventQueue::KernelEqueue eq, int id);
void GraphicsRenderClearGds(uint64_t dw_offset, uint32_t dw_num, uint32_t clear_value);
void GraphicsRenderReadGds(uint32_t* dst, uint32_t dw_offset, uint32_t dw_size);
} // namespace Kyty::Libs::Graphics
#endif // KYTY_EMU_ENABLED
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_GRAPHICSRENDER_H_ */
@@ -0,0 +1,29 @@
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_GRAPHICSRUN_H_
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_GRAPHICSRUN_H_
#include "Kyty/Core/Common.h"
#include "Emulator/Common.h"
#ifdef KYTY_EMU_ENABLED
namespace Kyty::Libs::Graphics {
void GraphicsRunInit();
void GraphicsRunSubmit(uint32_t* cmd_draw_buffer, uint32_t num_draw_dw, uint32_t* cmd_const_buffer, uint32_t num_const_dw);
void GraphicsRunSubmitAndFlip(uint32_t* cmd_draw_buffer, uint32_t num_draw_dw, uint32_t* cmd_const_buffer, uint32_t num_const_dw,
int handle, int index, int flip_mode, int64_t flip_arg);
uint32_t GraphicsRunMapComputeQueue(uint32_t pipe_id, uint32_t queue_id, uint32_t* ring_addr, uint32_t ring_size_dw,
uint32_t* read_ptr_addr);
void GraphicsRunUnmapComputeQueue(uint32_t id);
void GraphicsRunWait();
void GraphicsRunDone();
void GraphicsRunDingDong(uint32_t ring_id, uint32_t offset_dw);
int GraphicsRunGetFrameNum();
} // namespace Kyty::Libs::Graphics
#endif // KYTY_EMU_ENABLED
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_GRAPHICSRUN_H_ */
@@ -0,0 +1,511 @@
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_HARDWARECONTEXT_H_
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_HARDWARECONTEXT_H_
#include "Kyty/Core/Common.h"
#include "Emulator/Common.h"
#ifdef KYTY_EMU_ENABLED
namespace Kyty::Libs::Graphics {
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;
bool fmask_compression_enable = false;
uint32_t fmask_compression_mode = 0;
bool cmask_fast_clear_enable = false;
bool dcc_compression_enable = false;
bool neo_mode = false;
uint32_t cmask_tile_mode = 0;
uint32_t cmask_tile_mode_neo = 0;
uint32_t format = 0;
uint32_t channel_type = 0;
uint32_t channel_order = 0;
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;
};
struct DepthRenderTargetZInfo
{
uint32_t format = 0;
uint32_t tile_mode_index = 0;
uint32_t num_samples = 0;
bool tile_surface_enable = false;
bool expclear_enabled = false;
uint32_t zrange_precision = 0;
};
struct DepthRenderTargetStencilInfo
{
uint32_t format = 0;
uint32_t tile_mode_index = 0;
uint32_t tile_split = 0;
bool expclear_enabled = false;
bool tile_stencil_disable = false;
};
struct DepthRenderTargetDepthInfo
{
uint32_t addr5_swizzle_mask = 0;
uint32_t array_mode = 0;
uint32_t pipe_config = 0;
uint32_t bank_width = 0;
uint32_t bank_height = 0;
uint32_t macro_tile_aspect = 0;
uint32_t num_banks = 0;
};
struct DepthRenderTargetDepthView
{
uint32_t slice_start = 0;
uint32_t slice_max = 0;
};
struct DepthRenderTargetHTileSurface
{
uint32_t linear = 0;
uint32_t full_cache = 0;
uint32_t htile_uses_preload_win = 0;
uint32_t preload = 0;
uint32_t prefetch_width = 0;
uint32_t prefetch_height = 0;
uint32_t dst_outside_zero_to_one = 0;
};
struct DepthRenderTarget
{
DepthRenderTargetZInfo z_info;
DepthRenderTargetStencilInfo stencil_info;
DepthRenderTargetDepthInfo depth_info;
DepthRenderTargetDepthView depth_view;
DepthRenderTargetHTileSurface htile_surface;
uint64_t z_read_base_addr = 0;
uint64_t stencil_read_base_addr = 0;
uint64_t z_write_base_addr = 0;
uint64_t stencil_write_base_addr = 0;
uint32_t pitch_div8_minus1 = 0;
uint32_t height_div8_minus1 = 0;
uint32_t slice_div64_minus1 = 0;
uint64_t htile_data_base_addr = 0;
uint32_t width = 0;
uint32_t height = 0;
};
struct RenderControl
{
bool depth_clear_enable = false;
bool stencil_clear_enable = false;
bool resummarize_enable = false;
bool stencil_compress_disable = false;
bool depth_compress_disable = false;
bool copy_centroid = false;
uint8_t copy_sample = 0;
};
struct ClipControl
{
uint32_t user_clip_planes = 0;
uint32_t user_clip_plane_mode = 0;
uint32_t clip_space = 0;
uint32_t vertex_kill_mode = 0;
uint32_t min_z_clip_enable = 0;
uint32_t max_z_clip_enable = 0;
bool user_clip_plane_negate_y = false;
bool clip_enable = false;
bool user_clip_plane_cull_only = false;
bool cull_on_clipping_error_disable = false;
bool linear_attribute_clip_enable = false;
bool force_viewport_index_from_vs_enable = false;
};
struct DepthControl
{
bool stencil_enable = false;
bool z_enable = false;
bool z_write_enable = false;
bool depth_bounds_enable = false;
uint8_t zfunc = 0;
bool backface_enable = false;
uint8_t stencilfunc = 0;
uint8_t stencilfunc_bf = 0;
};
struct ModeControl
{
bool cull_front = false;
bool cull_back = false;
bool face = false;
uint8_t poly_mode = 0;
uint8_t polymode_front_ptype = 0;
uint8_t polymode_back_ptype = 0;
bool poly_offset_front_enable = false;
bool poly_offset_back_enable = false;
bool vtx_window_offset_enable = false;
bool provoking_vtx_last = false;
bool persp_corr_dis = false;
};
struct BlendControl
{
uint8_t color_srcblend = 0;
uint8_t color_comb_fcn = 0;
uint8_t color_destblend = 0;
uint8_t alpha_srcblend = 0;
uint8_t alpha_comb_fcn = 0;
uint8_t alpha_destblend = 0;
bool separate_alpha_blend = false;
bool enable = false;
};
struct Viewport
{
float zmin = 0.0f;
float zmax = 0.0f;
float xscale = 0.0f;
float xoffset = 0.0f;
float yscale = 0.0f;
float yoffset = 0.0f;
float zscale = 0.0f;
float zoffset = 0.0f;
};
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;
};
struct VsStageRegisters
{
uint32_t m_spiShaderPgmLoVs = 0;
uint32_t m_spiShaderPgmHiVs = 0;
uint32_t m_spiShaderPgmRsrc1Vs = 0;
uint32_t m_spiShaderPgmRsrc2Vs = 0;
uint32_t m_spiVsOutConfig = 0;
uint32_t m_spiShaderPosFormat = 0;
uint32_t m_paClVsOutCntl = 0;
[[nodiscard]] uint64_t GetGpuAddress() const;
[[nodiscard]] bool GetStreamoutEnabled() const;
[[nodiscard]] uint32_t GetSgprCount() const;
[[nodiscard]] uint32_t GetInputComponentsCount() const;
[[nodiscard]] uint32_t GetUnknown1() const;
[[nodiscard]] uint32_t GetUnknown2() const;
};
struct PsStageRegisters
{
uint64_t data_addr = 0;
uint8_t vgprs = 0;
uint8_t sgprs = 0;
uint8_t scratch_en = 0;
uint8_t user_sgpr = 0;
uint8_t wave_cnt_en = 0;
uint32_t shader_z_format = 0;
uint8_t target_output_mode[8] = {};
uint32_t ps_input_ena = 0;
uint32_t ps_input_addr = 0;
uint32_t ps_in_control = 0;
uint32_t baryc_cntl = 0;
uint8_t conservative_z_export_value = 0;
uint8_t shader_z_behavior = 0;
bool shader_kill_enable = false;
bool shader_z_export_enable = false;
bool shader_execute_on_noop = false;
uint32_t m_cbShaderMask = 0;
};
struct CsStageRegisters
{
uint64_t data_addr = 0;
uint32_t num_thread_x = 0;
uint32_t num_thread_y = 0;
uint32_t num_thread_z = 0;
uint8_t vgprs = 0;
uint8_t sgprs = 0;
uint8_t bulky = 0;
uint8_t scratch_en = 0;
uint8_t user_sgpr = 0;
uint8_t tgid_x_en = 0;
uint8_t tgid_y_en = 0;
uint8_t tgid_z_en = 0;
uint8_t tg_size_en = 0;
uint8_t tidig_comp_cnt = 0;
uint8_t lds_size = 0;
};
enum class UserSgprType
{
Unknown,
Region,
Vsharp
};
struct UserSgprInfo
{
uint32_t value[16] = {0};
UserSgprType type[16] = {};
uint32_t count = 0;
};
struct VertexShaderInfo
{
VsStageRegisters vs_regs;
uint32_t vs_shader_modifier = 0;
uint32_t vs_embedded_id = 0;
UserSgprInfo vs_user_sgpr;
bool vs_embedded = false;
};
struct PixelShaderInfo
{
PsStageRegisters ps_regs;
uint32_t ps_interpolator_settings[32] = {0};
uint32_t ps_input_num = 0;
UserSgprInfo ps_user_sgpr;
};
struct ComputeShaderInfo
{
CsStageRegisters cs_regs;
uint32_t cs_shader_modifier = 0;
UserSgprInfo cs_user_sgpr;
};
class HardwareContext
{
public:
HardwareContext() = default;
virtual ~HardwareContext() = default;
KYTY_CLASS_DEFAULT_COPY(HardwareContext);
void Reset() { *this = HardwareContext(); }
void SetRenderTarget(uint32_t slot, const RenderTarget& target) { m_render_targets[slot] = target; }
[[nodiscard]] const RenderTarget& GetRenderTargets(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]; }
void SetRenderTargetMask(uint32_t mask) { m_render_target_mask = mask; }
[[nodiscard]] uint32_t GetRenderTargetMask() const { return m_render_target_mask; }
void SetShaderStages(uint32_t flags) { m_shader_stages = flags; }
[[nodiscard]] uint32_t GetShaderStages() const { return m_shader_stages; }
void SetDepthRenderTarget(const DepthRenderTarget& target) { m_depth_render_target = target; }
[[nodiscard]] const DepthRenderTarget& GetDepthRenderTarget() const { return m_depth_render_target; }
void SetDepthRenderTargetZInfo(const DepthRenderTargetZInfo& info) { m_depth_render_target.z_info = info; }
[[nodiscard]] const DepthRenderTargetZInfo& GetDepthRenderTargetZInfo() const { return m_depth_render_target.z_info; }
void SetDepthRenderTargetStencilInfo(const DepthRenderTargetStencilInfo& info) { m_depth_render_target.stencil_info = info; }
[[nodiscard]] const DepthRenderTargetStencilInfo& GetDepthRenderTargetStencilInfo() const { return m_depth_render_target.stencil_info; }
void SetViewportZ(uint32_t viewport_id, float zmin, float zmax)
{
m_screen_viewport.viewports[viewport_id].zmin = zmin;
m_screen_viewport.viewports[viewport_id].zmax = zmax;
}
void SetViewportScaleOffset(uint32_t viewport_id, float xscale, float xoffset, float yscale, float yoffset, float zscale, float zoffset)
{
m_screen_viewport.viewports[viewport_id].xscale = xscale;
m_screen_viewport.viewports[viewport_id].xoffset = xoffset;
m_screen_viewport.viewports[viewport_id].yscale = yscale;
m_screen_viewport.viewports[viewport_id].yoffset = yoffset;
m_screen_viewport.viewports[viewport_id].zscale = zscale;
m_screen_viewport.viewports[viewport_id].zoffset = zoffset;
}
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;
}
void SetHardwareScreenOffset(uint32_t offset_x, uint32_t offset_y)
{
m_screen_viewport.hw_offset_x = offset_x;
m_screen_viewport.hw_offset_y = offset_y;
}
void SetGuardBands(float horz_clip, float vert_clip, float horz_discard, float vert_discard)
{
m_screen_viewport.guard_band_horz_clip = horz_clip;
m_screen_viewport.guard_band_vert_clip = vert_clip;
m_screen_viewport.guard_band_horz_discard = horz_discard;
m_screen_viewport.guard_band_vert_discard = vert_discard;
}
[[nodiscard]] const ScreenViewport& GetScreenViewport() const { return m_screen_viewport; }
void SetVsShader(const VsStageRegisters* vs_regs, uint32_t shader_modifier)
{
m_vs.vs_regs = *vs_regs;
m_vs.vs_shader_modifier = shader_modifier;
m_vs.vs_embedded = false;
}
void SetVsEmbedded(uint32_t id, uint32_t shader_modifier)
{
m_vs.vs_embedded_id = id;
m_vs.vs_shader_modifier = shader_modifier;
m_vs.vs_embedded = true;
}
void SetPsShader(const PsStageRegisters* ps_regs) { m_ps.ps_regs = *ps_regs; }
void SetCsShader(const CsStageRegisters* cs_regs, uint32_t shader_modifier)
{
m_cs.cs_regs = *cs_regs;
m_cs.cs_shader_modifier = shader_modifier;
}
[[nodiscard]] const ClipControl& GetClipControl() const { return m_clip_control; }
void SetClipControl(const ClipControl& control) { m_clip_control = control; }
[[nodiscard]] const RenderControl& GetRenderControl() const { return m_render_control; }
void SetRenderControl(const RenderControl& control) { m_render_control = control; }
[[nodiscard]] const DepthControl& GetDepthControl() const { return m_depth_control; }
void SetDepthControl(const DepthControl& control) { m_depth_control = control; }
[[nodiscard]] const ModeControl& GetModeControl() const { return m_mode_control; }
void SetModeControl(const ModeControl& control) { m_mode_control = control; }
void SetVsUserSgpr(uint32_t id, uint32_t value, UserSgprType type)
{
m_vs.vs_user_sgpr.value[id] = value;
m_vs.vs_user_sgpr.type[id] = type;
m_vs.vs_user_sgpr.count = ((id + 1) > m_vs.vs_user_sgpr.count ? (id + 1) : m_vs.vs_user_sgpr.count);
}
void SetPsUserSgpr(uint32_t id, uint32_t value, UserSgprType type)
{
m_ps.ps_user_sgpr.value[id] = value;
m_ps.ps_user_sgpr.type[id] = type;
m_ps.ps_user_sgpr.count = ((id + 1) > m_ps.ps_user_sgpr.count ? (id + 1) : m_ps.ps_user_sgpr.count);
}
void SetCsUserSgpr(uint32_t id, uint32_t value, UserSgprType type)
{
m_cs.cs_user_sgpr.value[id] = value;
m_cs.cs_user_sgpr.type[id] = type;
m_cs.cs_user_sgpr.count = ((id + 1) > m_cs.cs_user_sgpr.count ? (id + 1) : m_cs.cs_user_sgpr.count);
}
void SetPsInputSettings(uint32_t id, uint32_t value)
{
m_ps.ps_interpolator_settings[id] = value;
m_ps.ps_input_num = ((id + 1) > m_ps.ps_input_num ? (id + 1) : m_ps.ps_input_num);
}
[[nodiscard]] const PixelShaderInfo& GetPs() const { return m_ps; }
[[nodiscard]] const VertexShaderInfo& GetVs() const { return m_vs; }
[[nodiscard]] const ComputeShaderInfo& GetCs() const { return m_cs; }
[[nodiscard]] float GetDepthClearValue() const { return m_depth_clear_value; }
void SetDepthClearValue(float clear_value) { m_depth_clear_value = clear_value; }
private:
BlendControl m_blend_control[8];
RenderTarget m_render_targets[8];
uint32_t m_render_target_mask = 0;
ScreenViewport m_screen_viewport;
ClipControl m_clip_control;
VertexShaderInfo m_vs;
PixelShaderInfo m_ps;
ComputeShaderInfo m_cs;
uint32_t m_shader_stages = 0;
DepthRenderTarget m_depth_render_target;
RenderControl m_render_control;
DepthControl m_depth_control;
float m_depth_clear_value = 0.0f;
ModeControl m_mode_control;
};
class UserConfig
{
public:
UserConfig() = default;
virtual ~UserConfig() = default;
KYTY_CLASS_DEFAULT_COPY(UserConfig);
void Reset() { *this = UserConfig(); }
void SetPrimitiveType(uint32_t prim_type) { m_prim_type = prim_type; }
[[nodiscard]] uint32_t GetPrimType() const { return m_prim_type; }
private:
uint32_t m_prim_type = 0;
};
inline uint64_t VsStageRegisters::GetGpuAddress() const
{
return (static_cast<uint64_t>(m_spiShaderPgmLoVs) << 8u) | (static_cast<uint64_t>(m_spiShaderPgmHiVs) << 40u);
}
inline bool VsStageRegisters::GetStreamoutEnabled() const
{
return (m_spiShaderPgmRsrc2Vs & 0x00001000u) != 0u;
}
inline uint32_t VsStageRegisters::GetSgprCount() const
{
return (m_spiShaderPgmRsrc1Vs >> 6u) & 0xfu;
}
inline uint32_t VsStageRegisters::GetInputComponentsCount() const
{
return (m_spiShaderPgmRsrc1Vs >> 24u) & 0x3u;
}
inline uint32_t VsStageRegisters::GetUnknown1() const
{
return m_spiShaderPgmRsrc1Vs & 0xfcfffc3fu;
}
inline uint32_t VsStageRegisters::GetUnknown2() const
{
return m_spiShaderPgmRsrc2Vs & 0xFFFFEFFFu;
}
} // namespace Kyty::Libs::Graphics
#endif // KYTY_EMU_ENABLED
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_HARDWARECONTEXT_H_ */
@@ -0,0 +1,37 @@
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_INDEXBUFFER_H_
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_INDEXBUFFER_H_
#include "Kyty/Core/Common.h"
#include "Emulator/Common.h"
#include "Emulator/Graphics/GpuMemory.h"
#ifdef KYTY_EMU_ENABLED
namespace Kyty::Libs::Graphics {
struct GraphicContext;
struct VulkanMemory;
class IndexBufferGpuObject: public GpuObject
{
public:
IndexBufferGpuObject()
{
check_hash = true;
type = Graphics::GpuMemoryObjectType::IndexBuffer;
}
void* Create(GraphicContext* ctx, const uint64_t* vaddr, const uint64_t* size, int vaddr_num, VulkanMemory* mem) const override;
bool Equal(const uint64_t* other) const override;
[[nodiscard]] write_back_func_t GetWriteBackFunc() const override { return nullptr; };
[[nodiscard]] delete_func_t GetDeleteFunc() const override;
[[nodiscard]] update_func_t GetUpdateFunc() const override;
};
} // namespace Kyty::Libs::Graphics
#endif // KYTY_EMU_ENABLED
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_INDEXBUFFER_H_ */
@@ -0,0 +1,63 @@
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_LABEL_H_
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_LABEL_H_
#include "Kyty/Core/Common.h"
#include "Emulator/Common.h"
#include "Emulator/Graphics/GpuMemory.h"
#ifdef KYTY_EMU_ENABLED
namespace Kyty::Libs::Graphics {
struct Label;
struct GraphicContext;
class CommandBuffer;
struct VulkanMemory;
void LabelInit();
class LabelGpuObject: public GpuObject
{
public:
using callback_t = bool (*)(const uint64_t* args);
static constexpr int PARAM_VALUE = 0;
static constexpr int PARAM_CALLBACK_1 = 1;
static constexpr int PARAM_CALLBACK_2 = 2;
static constexpr int PARAM_ARG_1 = 3;
static constexpr int PARAM_ARG_2 = 4;
static constexpr int PARAM_ARG_3 = 5;
static constexpr int PARAM_ARG_4 = 6;
explicit LabelGpuObject(uint64_t value, callback_t callback_1, callback_t callback_2, const uint64_t* args = nullptr)
{
params[PARAM_VALUE] = value;
params[PARAM_CALLBACK_1] = reinterpret_cast<uint64_t>(callback_1);
params[PARAM_CALLBACK_2] = reinterpret_cast<uint64_t>(callback_2);
if (args != nullptr)
{
params[PARAM_ARG_1] = args[0];
params[PARAM_ARG_2] = args[1];
params[PARAM_ARG_3] = args[2];
params[PARAM_ARG_4] = args[3];
}
check_hash = false;
type = Graphics::GpuMemoryObjectType::Label;
}
void* Create(GraphicContext* ctx, const uint64_t* vaddr, const uint64_t* size, int vaddr_num, VulkanMemory* mem) const override;
bool Equal(const uint64_t* other) const override;
[[nodiscard]] write_back_func_t GetWriteBackFunc() const override { return nullptr; };
[[nodiscard]] delete_func_t GetDeleteFunc() const override;
[[nodiscard]] update_func_t GetUpdateFunc() const override;
};
void LabelSet(CommandBuffer* buffer, Label* label);
} // namespace Kyty::Libs::Graphics
#endif // KYTY_EMU_ENABLED
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_LABEL_H_ */
@@ -0,0 +1,315 @@
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_PM4_H_
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_PM4_H_
#include "Kyty/Core/Common.h"
#include "Emulator/Common.h"
#ifdef KYTY_EMU_ENABLED
namespace Kyty::Core {
class File;
} // namespace Kyty::Core
#define KYTY_PM4_GET(u, r, f) (((u) >> Pm4::r##_##f##_SHIFT) & Pm4::r##_##f##_MASK)
#define KYTY_PM4(len, op, r) \
(0xC0000000u | (((static_cast<uint16_t>(len) - 2u) & 0x3fffu) << 16u) | (((op)&0xffu) << 8u) | (((r)&0x3fu) << 2u))
namespace Kyty::Libs::Graphics::Pm4 {
constexpr uint32_t IT_NOP = 0x10;
constexpr uint32_t IT_SET_BASE = 0x11;
constexpr uint32_t IT_CLEAR_STATE = 0x12;
constexpr uint32_t IT_INDEX_BUFFER_SIZE = 0x13;
constexpr uint32_t IT_DISPATCH_DIRECT = 0x15;
constexpr uint32_t IT_DISPATCH_INDIRECT = 0x16;
constexpr uint32_t IT_SET_PREDICATION = 0x20;
constexpr uint32_t IT_COND_EXEC = 0x22;
constexpr uint32_t IT_DRAW_INDIRECT = 0x24;
constexpr uint32_t IT_DRAW_INDEX_INDIRECT = 0x25;
constexpr uint32_t IT_INDEX_BASE = 0x26;
constexpr uint32_t IT_DRAW_INDEX_2 = 0x27;
constexpr uint32_t IT_CONTEXT_CONTROL = 0x28;
constexpr uint32_t IT_INDEX_TYPE = 0x2A;
constexpr uint32_t IT_DRAW_INDIRECT_MULTI = 0x2C;
constexpr uint32_t IT_DRAW_INDEX_AUTO = 0x2D;
constexpr uint32_t IT_NUM_INSTANCES = 0x2F;
constexpr uint32_t IT_INDIRECT_BUFFER_CNST = 0x33;
constexpr uint32_t IT_DRAW_INDEX_OFFSET_2 = 0x35;
constexpr uint32_t IT_WRITE_DATA = 0x37;
constexpr uint32_t IT_MEM_SEMAPHORE = 0x39;
constexpr uint32_t IT_DRAW_INDEX_INDIRECT_MULTI = 0x38;
constexpr uint32_t IT_WAIT_REG_MEM = 0x3C;
constexpr uint32_t IT_INDIRECT_BUFFER = 0x3F;
constexpr uint32_t IT_COPY_DATA = 0x40;
constexpr uint32_t IT_CP_DMA = 0x41;
constexpr uint32_t IT_PFP_SYNC_ME = 0x42;
constexpr uint32_t IT_SURFACE_SYNC = 0x43;
constexpr uint32_t IT_EVENT_WRITE = 0x46;
constexpr uint32_t IT_EVENT_WRITE_EOP = 0x47;
constexpr uint32_t IT_EVENT_WRITE_EOS = 0x48;
constexpr uint32_t IT_RELEASE_MEM = 0x49;
constexpr uint32_t IT_DMA_DATA = 0x50;
constexpr uint32_t IT_ACQUIRE_MEM = 0x58;
constexpr uint32_t IT_REWIND = 0x59;
constexpr uint32_t IT_SET_CONFIG_REG = 0x68;
constexpr uint32_t IT_SET_CONTEXT_REG = 0x69;
constexpr uint32_t IT_SET_SH_REG = 0x76;
constexpr uint32_t IT_SET_QUEUE_REG = 0x78;
constexpr uint32_t IT_SET_UCONFIG_REG = 0x79;
constexpr uint32_t IT_WRITE_CONST_RAM = 0x81;
constexpr uint32_t IT_DUMP_CONST_RAM = 0x83;
constexpr uint32_t IT_INCREMENT_CE_COUNTER = 0x84;
constexpr uint32_t IT_INCREMENT_DE_COUNTER = 0x85;
constexpr uint32_t IT_WAIT_ON_CE_COUNTER = 0x86;
constexpr uint32_t IT_WAIT_ON_DE_COUNTER_DIFF = 0x88;
constexpr uint32_t IT_DISPATCH_DRAW_PREAMBLE = 0x8C;
constexpr uint32_t IT_DISPATCH_DRAW = 0x8D;
constexpr uint32_t R_ZERO = 0x00;
constexpr uint32_t R_VS = 0x01;
constexpr uint32_t R_PS = 0x02;
constexpr uint32_t R_DRAW_INDEX = 0x03;
constexpr uint32_t R_DRAW_INDEX_AUTO = 0x04;
constexpr uint32_t R_DRAW_RESET = 0x05;
constexpr uint32_t R_WAIT_FLIP_DONE = 0x06;
constexpr uint32_t R_CS = 0x07;
constexpr uint32_t R_DISPATCH_DIRECT = 0x08;
constexpr uint32_t R_DISPATCH_RESET = 0x09;
constexpr uint32_t R_DISPATCH_WAIT_MEM = 0x0A;
constexpr uint32_t R_PUSH_MARKER = 0x0B;
constexpr uint32_t R_POP_MARKER = 0x0C;
constexpr uint32_t R_VS_EMBEDDED = 0x0D;
constexpr uint32_t DB_RENDER_CONTROL = 0x0;
constexpr uint32_t DB_RENDER_CONTROL_DEPTH_CLEAR_ENABLE_SHIFT = 0;
constexpr uint32_t DB_RENDER_CONTROL_DEPTH_CLEAR_ENABLE_MASK = 0x1;
constexpr uint32_t DB_RENDER_CONTROL_STENCIL_CLEAR_ENABLE_SHIFT = 1;
constexpr uint32_t DB_RENDER_CONTROL_STENCIL_CLEAR_ENABLE_MASK = 0x1;
constexpr uint32_t DB_RENDER_CONTROL_RESUMMARIZE_ENABLE_SHIFT = 4;
constexpr uint32_t DB_RENDER_CONTROL_RESUMMARIZE_ENABLE_MASK = 0x1;
constexpr uint32_t DB_RENDER_CONTROL_STENCIL_COMPRESS_DISABLE_SHIFT = 5;
constexpr uint32_t DB_RENDER_CONTROL_STENCIL_COMPRESS_DISABLE_MASK = 0x1;
constexpr uint32_t DB_RENDER_CONTROL_DEPTH_COMPRESS_DISABLE_SHIFT = 6;
constexpr uint32_t DB_RENDER_CONTROL_DEPTH_COMPRESS_DISABLE_MASK = 0x1;
constexpr uint32_t DB_RENDER_CONTROL_COPY_CENTROID_SHIFT = 7;
constexpr uint32_t DB_RENDER_CONTROL_COPY_CENTROID_MASK = 0x1;
constexpr uint32_t DB_RENDER_CONTROL_COPY_SAMPLE_SHIFT = 8;
constexpr uint32_t DB_RENDER_CONTROL_COPY_SAMPLE_MASK = 0xF;
constexpr uint32_t DB_DEPTH_VIEW = 0x2;
constexpr uint32_t DB_DEPTH_VIEW_SLICE_START_SHIFT = 0;
constexpr uint32_t DB_DEPTH_VIEW_SLICE_START_MASK = 0x7FF;
constexpr uint32_t DB_DEPTH_VIEW_SLICE_MAX_SHIFT = 13;
constexpr uint32_t DB_DEPTH_VIEW_SLICE_MAX_MASK = 0x7FF;
constexpr uint32_t DB_HTILE_DATA_BASE = 0x5;
constexpr uint32_t DB_HTILE_DATA_BASE_BASE_256B_SHIFT = 0;
constexpr uint32_t DB_HTILE_DATA_BASE_BASE_256B_MASK = 0xFFFFFFFF;
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 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;
constexpr uint32_t DB_DEPTH_INFO_ARRAY_MODE_SHIFT = 4;
constexpr uint32_t DB_DEPTH_INFO_ARRAY_MODE_MASK = 0xF;
constexpr uint32_t DB_DEPTH_INFO_PIPE_CONFIG_SHIFT = 8;
constexpr uint32_t DB_DEPTH_INFO_PIPE_CONFIG_MASK = 0x1F;
constexpr uint32_t DB_DEPTH_INFO_BANK_WIDTH_SHIFT = 13;
constexpr uint32_t DB_DEPTH_INFO_BANK_WIDTH_MASK = 0x3;
constexpr uint32_t DB_DEPTH_INFO_BANK_HEIGHT_SHIFT = 15;
constexpr uint32_t DB_DEPTH_INFO_BANK_HEIGHT_MASK = 0x3;
constexpr uint32_t DB_DEPTH_INFO_MACRO_TILE_ASPECT_SHIFT = 17;
constexpr uint32_t DB_DEPTH_INFO_MACRO_TILE_ASPECT_MASK = 0x3;
constexpr uint32_t DB_DEPTH_INFO_NUM_BANKS_SHIFT = 19;
constexpr uint32_t DB_DEPTH_INFO_NUM_BANKS_MASK = 0x3;
constexpr uint32_t DB_Z_INFO = 0x10;
constexpr uint32_t DB_Z_INFO_FORMAT_SHIFT = 0;
constexpr uint32_t DB_Z_INFO_FORMAT_MASK = 0x3;
constexpr uint32_t DB_Z_INFO_NUM_SAMPLES_SHIFT = 2;
constexpr uint32_t DB_Z_INFO_NUM_SAMPLES_MASK = 0x3;
constexpr uint32_t DB_Z_INFO_TILE_MODE_INDEX_SHIFT = 20;
constexpr uint32_t DB_Z_INFO_TILE_MODE_INDEX_MASK = 0x7;
constexpr uint32_t DB_Z_INFO_TILE_SURFACE_ENABLE_SHIFT = 29;
constexpr uint32_t DB_Z_INFO_TILE_SURFACE_ENABLE_MASK = 0x1;
constexpr uint32_t DB_Z_INFO_ZRANGE_PRECISION_SHIFT = 31;
constexpr uint32_t DB_Z_INFO_ZRANGE_PRECISION_MASK = 0x1;
constexpr uint32_t DB_STENCIL_INFO = 0x11;
constexpr uint32_t DB_STENCIL_INFO_FORMAT_SHIFT = 0;
constexpr uint32_t DB_STENCIL_INFO_FORMAT_MASK = 0x1;
constexpr uint32_t DB_STENCIL_INFO_TILE_MODE_INDEX_SHIFT = 20;
constexpr uint32_t DB_STENCIL_INFO_TILE_MODE_INDEX_MASK = 0x7;
constexpr uint32_t DB_STENCIL_INFO_TILE_STENCIL_DISABLE_SHIFT = 29;
constexpr uint32_t DB_STENCIL_INFO_TILE_STENCIL_DISABLE_MASK = 0x1;
constexpr uint32_t DB_Z_READ_BASE = 0x12;
constexpr uint32_t DB_Z_READ_BASE_BASE_256B_SHIFT = 0;
constexpr uint32_t DB_Z_READ_BASE_BASE_256B_MASK = 0xFFFFFFFF;
constexpr uint32_t DB_STENCIL_READ_BASE = 0x13;
constexpr uint32_t DB_STENCIL_READ_BASE_BASE_256B_SHIFT = 0;
constexpr uint32_t DB_STENCIL_READ_BASE_BASE_256B_MASK = 0xFFFFFFFF;
constexpr uint32_t DB_Z_WRITE_BASE = 0x14;
constexpr uint32_t DB_Z_WRITE_BASE_BASE_256B_SHIFT = 0;
constexpr uint32_t DB_Z_WRITE_BASE_BASE_256B_MASK = 0xFFFFFFFF;
constexpr uint32_t DB_STENCIL_WRITE_BASE = 0x15;
constexpr uint32_t DB_STENCIL_WRITE_BASE_BASE_256B_SHIFT = 0;
constexpr uint32_t DB_STENCIL_WRITE_BASE_BASE_256B_MASK = 0xFFFFFFFF;
constexpr uint32_t DB_DEPTH_SIZE = 0x16;
constexpr uint32_t DB_DEPTH_SIZE_PITCH_TILE_MAX_SHIFT = 0;
constexpr uint32_t DB_DEPTH_SIZE_PITCH_TILE_MAX_MASK = 0x7FF;
constexpr uint32_t DB_DEPTH_SIZE_HEIGHT_TILE_MAX_SHIFT = 11;
constexpr uint32_t DB_DEPTH_SIZE_HEIGHT_TILE_MAX_MASK = 0x7FF;
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_VPORT_ZMIN_0 = 0xB4;
constexpr uint32_t PA_CL_VPORT_XSCALE = 0x10F;
constexpr uint32_t SPI_PS_INPUT_CNTL_0 = 0x191;
constexpr uint32_t CB_BLEND0_CONTROL = 0x1E0;
constexpr uint32_t CB_BLEND0_CONTROL_COLOR_SRCBLEND_SHIFT = 0;
constexpr uint32_t CB_BLEND0_CONTROL_COLOR_SRCBLEND_MASK = 0x1F;
constexpr uint32_t CB_BLEND0_CONTROL_COLOR_COMB_FCN_SHIFT = 5;
constexpr uint32_t CB_BLEND0_CONTROL_COLOR_COMB_FCN_MASK = 0x7;
constexpr uint32_t CB_BLEND0_CONTROL_COLOR_DESTBLEND_SHIFT = 8;
constexpr uint32_t CB_BLEND0_CONTROL_COLOR_DESTBLEND_MASK = 0x1F;
constexpr uint32_t CB_BLEND0_CONTROL_ALPHA_SRCBLEND_SHIFT = 16;
constexpr uint32_t CB_BLEND0_CONTROL_ALPHA_SRCBLEND_MASK = 0x1F;
constexpr uint32_t CB_BLEND0_CONTROL_ALPHA_COMB_FCN_SHIFT = 21;
constexpr uint32_t CB_BLEND0_CONTROL_ALPHA_COMB_FCN_MASK = 0x7;
constexpr uint32_t CB_BLEND0_CONTROL_ALPHA_DESTBLEND_SHIFT = 24;
constexpr uint32_t CB_BLEND0_CONTROL_ALPHA_DESTBLEND_MASK = 0x1F;
constexpr uint32_t CB_BLEND0_CONTROL_SEPARATE_ALPHA_BLEND_SHIFT = 29;
constexpr uint32_t CB_BLEND0_CONTROL_SEPARATE_ALPHA_BLEND_MASK = 0x1;
constexpr uint32_t CB_BLEND0_CONTROL_ENABLE_SHIFT = 30;
constexpr uint32_t CB_BLEND0_CONTROL_ENABLE_MASK = 0x1;
constexpr uint32_t DB_DEPTH_CONTROL = 0x200;
constexpr uint32_t DB_DEPTH_CONTROL_STENCIL_ENABLE_SHIFT = 0;
constexpr uint32_t DB_DEPTH_CONTROL_STENCIL_ENABLE_MASK = 0x1;
constexpr uint32_t DB_DEPTH_CONTROL_Z_ENABLE_SHIFT = 1;
constexpr uint32_t DB_DEPTH_CONTROL_Z_ENABLE_MASK = 0x1;
constexpr uint32_t DB_DEPTH_CONTROL_Z_WRITE_ENABLE_SHIFT = 2;
constexpr uint32_t DB_DEPTH_CONTROL_Z_WRITE_ENABLE_MASK = 0x1;
constexpr uint32_t DB_DEPTH_CONTROL_DEPTH_BOUNDS_ENABLE_SHIFT = 3;
constexpr uint32_t DB_DEPTH_CONTROL_DEPTH_BOUNDS_ENABLE_MASK = 0x1;
constexpr uint32_t DB_DEPTH_CONTROL_ZFUNC_SHIFT = 4;
constexpr uint32_t DB_DEPTH_CONTROL_ZFUNC_MASK = 0x7;
constexpr uint32_t DB_DEPTH_CONTROL_BACKFACE_ENABLE_SHIFT = 7;
constexpr uint32_t DB_DEPTH_CONTROL_BACKFACE_ENABLE_MASK = 0x1;
constexpr uint32_t DB_DEPTH_CONTROL_STENCILFUNC_SHIFT = 8;
constexpr uint32_t DB_DEPTH_CONTROL_STENCILFUNC_MASK = 0x7;
constexpr uint32_t DB_DEPTH_CONTROL_STENCILFUNC_BF_SHIFT = 20;
constexpr uint32_t DB_DEPTH_CONTROL_STENCILFUNC_BF_MASK = 0x7;
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;
constexpr uint32_t PA_SU_SC_MODE_CNTL_CULL_BACK_SHIFT = 1;
constexpr uint32_t PA_SU_SC_MODE_CNTL_CULL_BACK_MASK = 0x1;
constexpr uint32_t PA_SU_SC_MODE_CNTL_FACE_SHIFT = 2;
constexpr uint32_t PA_SU_SC_MODE_CNTL_FACE_MASK = 0x1;
constexpr uint32_t PA_SU_SC_MODE_CNTL_POLY_MODE_SHIFT = 3;
constexpr uint32_t PA_SU_SC_MODE_CNTL_POLY_MODE_MASK = 0x3;
constexpr uint32_t PA_SU_SC_MODE_CNTL_POLYMODE_FRONT_PTYPE_SHIFT = 5;
constexpr uint32_t PA_SU_SC_MODE_CNTL_POLYMODE_FRONT_PTYPE_MASK = 0x7;
constexpr uint32_t PA_SU_SC_MODE_CNTL_POLYMODE_BACK_PTYPE_SHIFT = 8;
constexpr uint32_t PA_SU_SC_MODE_CNTL_POLYMODE_BACK_PTYPE_MASK = 0x7;
constexpr uint32_t PA_SU_SC_MODE_CNTL_POLY_OFFSET_FRONT_ENABLE_SHIFT = 11;
constexpr uint32_t PA_SU_SC_MODE_CNTL_POLY_OFFSET_FRONT_ENABLE_MASK = 0x1;
constexpr uint32_t PA_SU_SC_MODE_CNTL_POLY_OFFSET_BACK_ENABLE_SHIFT = 12;
constexpr uint32_t PA_SU_SC_MODE_CNTL_POLY_OFFSET_BACK_ENABLE_MASK = 0x1;
constexpr uint32_t PA_SU_SC_MODE_CNTL_VTX_WINDOW_OFFSET_ENABLE_SHIFT = 16;
constexpr uint32_t PA_SU_SC_MODE_CNTL_VTX_WINDOW_OFFSET_ENABLE_MASK = 0x1;
constexpr uint32_t PA_SU_SC_MODE_CNTL_PROVOKING_VTX_LAST_SHIFT = 19;
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 DB_HTILE_SURFACE = 0x2AF;
constexpr uint32_t DB_HTILE_SURFACE_LINEAR_SHIFT = 0;
constexpr uint32_t DB_HTILE_SURFACE_LINEAR_MASK = 0x1;
constexpr uint32_t DB_HTILE_SURFACE_FULL_CACHE_SHIFT = 1;
constexpr uint32_t DB_HTILE_SURFACE_FULL_CACHE_MASK = 0x1;
constexpr uint32_t DB_HTILE_SURFACE_HTILE_USES_PRELOAD_WIN_SHIFT = 2;
constexpr uint32_t DB_HTILE_SURFACE_HTILE_USES_PRELOAD_WIN_MASK = 0x1;
constexpr uint32_t DB_HTILE_SURFACE_PRELOAD_SHIFT = 3;
constexpr uint32_t DB_HTILE_SURFACE_PRELOAD_MASK = 0x1;
constexpr uint32_t DB_HTILE_SURFACE_PREFETCH_WIDTH_SHIFT = 4;
constexpr uint32_t DB_HTILE_SURFACE_PREFETCH_WIDTH_MASK = 0x3F;
constexpr uint32_t DB_HTILE_SURFACE_PREFETCH_HEIGHT_SHIFT = 10;
constexpr uint32_t DB_HTILE_SURFACE_PREFETCH_HEIGHT_MASK = 0x3F;
constexpr uint32_t DB_HTILE_SURFACE_DST_OUTSIDE_ZERO_TO_ONE_SHIFT = 16;
constexpr uint32_t DB_HTILE_SURFACE_DST_OUTSIDE_ZERO_TO_ONE_MASK = 0x1;
constexpr uint32_t VGT_SHADER_STAGES_EN = 0x2D5;
constexpr uint32_t CB_COLOR0_BASE = 0x318;
constexpr uint32_t SPI_SHADER_PGM_RSRC1_PS = 0xA;
constexpr uint32_t SPI_SHADER_PGM_RSRC1_PS_VGPRS_SHIFT = 0;
constexpr uint32_t SPI_SHADER_PGM_RSRC1_PS_VGPRS_MASK = 0x3F;
constexpr uint32_t SPI_SHADER_PGM_RSRC1_PS_SGPRS_SHIFT = 6;
constexpr uint32_t SPI_SHADER_PGM_RSRC1_PS_SGPRS_MASK = 0xF;
constexpr uint32_t SPI_SHADER_PGM_RSRC2_PS = 0xB;
constexpr uint32_t SPI_SHADER_PGM_RSRC2_PS_SCRATCH_EN_SHIFT = 0;
constexpr uint32_t SPI_SHADER_PGM_RSRC2_PS_SCRATCH_EN_MASK = 0x1;
constexpr uint32_t SPI_SHADER_PGM_RSRC2_PS_USER_SGPR_SHIFT = 1;
constexpr uint32_t SPI_SHADER_PGM_RSRC2_PS_USER_SGPR_MASK = 0x1F;
constexpr uint32_t SPI_SHADER_PGM_RSRC2_PS_WAVE_CNT_EN_SHIFT = 7;
constexpr uint32_t SPI_SHADER_PGM_RSRC2_PS_WAVE_CNT_EN_MASK = 0x0;
constexpr uint32_t SPI_SHADER_USER_DATA_PS_0 = 0xC;
constexpr uint32_t SPI_SHADER_USER_DATA_PS_15 = 0x1B;
constexpr uint32_t SPI_SHADER_USER_DATA_VS_0 = 0x4C;
constexpr uint32_t SPI_SHADER_USER_DATA_VS_15 = 0x5B;
constexpr uint32_t COMPUTE_PGM_RSRC1 = 0x212;
constexpr uint32_t COMPUTE_PGM_RSRC1_VGPRS_SHIFT = 0;
constexpr uint32_t COMPUTE_PGM_RSRC1_VGPRS_MASK = 0x3F;
constexpr uint32_t COMPUTE_PGM_RSRC1_SGPRS_SHIFT = 6;
constexpr uint32_t COMPUTE_PGM_RSRC1_SGPRS_MASK = 0xF;
constexpr uint32_t COMPUTE_PGM_RSRC1_BULKY_SHIFT = 24;
constexpr uint32_t COMPUTE_PGM_RSRC1_BULKY_MASK = 0x1;
constexpr uint32_t COMPUTE_PGM_RSRC2 = 0x213;
constexpr uint32_t COMPUTE_PGM_RSRC2_SCRATCH_EN_SHIFT = 0;
constexpr uint32_t COMPUTE_PGM_RSRC2_SCRATCH_EN_MASK = 0x1;
constexpr uint32_t COMPUTE_PGM_RSRC2_USER_SGPR_SHIFT = 1;
constexpr uint32_t COMPUTE_PGM_RSRC2_USER_SGPR_MASK = 0x1F;
constexpr uint32_t COMPUTE_PGM_RSRC2_TGID_X_EN_SHIFT = 7;
constexpr uint32_t COMPUTE_PGM_RSRC2_TGID_X_EN_MASK = 0x1;
constexpr uint32_t COMPUTE_PGM_RSRC2_TGID_Y_EN_SHIFT = 8;
constexpr uint32_t COMPUTE_PGM_RSRC2_TGID_Y_EN_MASK = 0x1;
constexpr uint32_t COMPUTE_PGM_RSRC2_TGID_Z_EN_SHIFT = 9;
constexpr uint32_t COMPUTE_PGM_RSRC2_TGID_Z_EN_MASK = 0x1;
constexpr uint32_t COMPUTE_PGM_RSRC2_TG_SIZE_EN_SHIFT = 10;
constexpr uint32_t COMPUTE_PGM_RSRC2_TG_SIZE_EN_MASK = 0x1;
constexpr uint32_t COMPUTE_PGM_RSRC2_TIDIG_COMP_CNT_SHIFT = 11;
constexpr uint32_t COMPUTE_PGM_RSRC2_TIDIG_COMP_CNT_MASK = 0x3;
constexpr uint32_t COMPUTE_PGM_RSRC2_LDS_SIZE_SHIFT = 15;
constexpr uint32_t COMPUTE_PGM_RSRC2_LDS_SIZE_MASK = 0x1FF;
constexpr uint32_t COMPUTE_USER_DATA_0 = 0x240;
constexpr uint32_t COMPUTE_USER_DATA_15 = 0x24F;
void DumpPm4PacketStream(Core::File* file, uint32_t* cmd_buffer, uint32_t start_dw, uint32_t num_dw);
} // namespace Kyty::Libs::Graphics::Pm4
#endif // KYTY_EMU_ENABLED
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_PM4_H_ */
@@ -0,0 +1,554 @@
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_SHADER_H_
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_SHADER_H_
#include "Kyty/Core/Common.h"
#include "Kyty/Core/String.h"
#include "Kyty/Core/Vector.h"
#include "Emulator/Common.h"
#ifdef KYTY_EMU_ENABLED
namespace Kyty::Libs::Graphics {
struct VertexShaderInfo;
struct PixelShaderInfo;
struct ComputeShaderInfo;
enum class ShaderType
{
Unknown,
Vertex,
Pixel,
Fetch,
Compute
};
enum class ShaderInstructionType
{
Unknown,
DsAppend,
DsConsume,
Exp,
BufferLoadDword,
BufferLoadFormatX,
BufferLoadFormatXy,
BufferLoadFormatXyz,
BufferLoadFormatXyzw,
BufferStoreDword,
BufferStoreFormatX,
ImageSample,
TBufferLoadFormatXyzw,
SAndn2B64,
SAndSaveexecB64,
SEndpgm,
SCbranchExecz,
SLshlB32,
SLoadDwordx4,
SLoadDwordx8,
SBufferLoadDword,
SBufferLoadDwordx4,
SBufferLoadDwordx8,
SBufferLoadDwordx16,
SMovB32,
SMovB64,
SSetpcB64,
SSwappcB64,
SWaitcnt,
SWqmB64,
VAddI32,
VAndB32,
VCmpEqF32,
VCmpEqU32,
VCmpLeF32,
VCmpLeU32,
VCmpNeU32,
VCmpNeqF32,
VCmpxEqU32,
VCmpxGtU32,
VCndmaskB32,
VCvtF32U32,
VCvtPkrtzF16F32,
VCvtU32F32,
VMacF32,
VMadakF32,
VMadF32,
VMaxF32,
VMbcntHiU32B32,
VMbcntLoU32B32,
VMinF32,
VMovB32,
VMulF32,
VInterpP1F32,
VInterpP2F32,
VRcpF32,
VRsqF32,
VSadU32,
VSqrtF32,
VSubF32,
VSubI32,
VSubrevF32,
VSubrevI32,
};
namespace ShaderInstructionFormat {
enum FormatByte : uint64_t
{
U = 0,
N,
D, // operand_to_str(inst.dst)
D2, // operand_to_str(inst.dst2)
S0, // operand_to_str(inst.src[0])
S1, // operand_to_str(inst.src[1])
S2, // operand_to_str(inst.src[2])
S3, // operand_to_str(inst.src[3])
DA2, // operand_array_to_str(inst.dst, 2)
DA3, // operand_array_to_str(inst.dst, 3)
DA4, // operand_array_to_str(inst.dst, 4)
DA8, // operand_array_to_str(inst.dst, 8)
DA16, // operand_array_to_str(inst.dst, 16)
D2A2, // operand_array_to_str(inst.dst2, 2)
D2A3, // operand_array_to_str(inst.dst2, 3)
D2A4, // operand_array_to_str(inst.dst2, 4)
S0A2, // operand_array_to_str(inst.src[0], 2)
S0A3, // operand_array_to_str(inst.src[0], 3)
S0A4, // operand_array_to_str(inst.src[0], 4)
S1A2, // operand_array_to_str(inst.src[1], 2)
S1A3, // operand_array_to_str(inst.src[1], 3)
S1A4, // operand_array_to_str(inst.src[1], 4)
S1A8, // operand_array_to_str(inst.src[1], 8)
S2A2, // operand_array_to_str(inst.src[2], 2)
S2A3, // operand_array_to_str(inst.src[2], 3)
S2A4, // operand_array_to_str(inst.src[2], 4)
Attr, // attr%u.%u <- inst.src[1].constant.u, inst.src[2].constant.u
Idxen, // idxen
Float4, // format:float4
Pos0, // pos0
Done, // done
Param0, // param0
Param1, // param1
Param2, // param2
Param3, // param3
Mrt0, // mrt_color0
Compr, // compr
Vm, // vm
L, // label_%u
DmaskF, // dmask:0xf
Dmask7, // dmask:0x7
Gds, // gds
};
constexpr uint64_t FormatDefine(std::initializer_list<uint64_t> f)
{
uint64_t r = 0;
for (auto n: f)
{
r = (r << 8u) | n;
}
return r;
}
enum Format : uint64_t
{
Unknown = FormatDefine({U}),
Empty = FormatDefine({N}),
Imm = FormatDefine({S0}),
Label = FormatDefine({L}),
Mrt0Vsrc0Vsrc1ComprVmDone = FormatDefine({Mrt0, S0, S1, Compr, Vm, Done}),
Mrt0Vsrc0Vsrc1Vsrc2Vsrc3VmDone = FormatDefine({Mrt0, S0, S1, S2, S3, Vm, Done}),
Param0Vsrc0Vsrc1Vsrc2Vsrc3 = FormatDefine({Param0, S0, S1, S2, S3}),
Param1Vsrc0Vsrc1Vsrc2Vsrc3 = FormatDefine({Param1, S0, S1, S2, S3}),
Param2Vsrc0Vsrc1Vsrc2Vsrc3 = FormatDefine({Param2, S0, S1, S2, S3}),
Param3Vsrc0Vsrc1Vsrc2Vsrc3 = FormatDefine({Param3, S0, S1, S2, S3}),
Pos0Vsrc0Vsrc1Vsrc2Vsrc3Done = FormatDefine({Pos0, S0, S1, S2, S3, Done}),
Saddr = FormatDefine({S0A2}),
Sdst4SbaseSoffset = FormatDefine({DA4, S0A2, S1}),
Sdst8SbaseSoffset = FormatDefine({DA8, S0A2, S1}),
SdstSvSoffset = FormatDefine({D, S0A4, S1}),
Sdst4SvSoffset = FormatDefine({DA4, S0A4, S1}),
Sdst8SvSoffset = FormatDefine({DA8, S0A4, S1}),
Sdst16SvSoffset = FormatDefine({DA16, S0A4, S1}),
SVdstSVsrc0 = FormatDefine({D, S0}),
SVdstSVsrc0SVsrc1 = FormatDefine({D, S0, S1}),
Sdst2Ssrc02 = FormatDefine({DA2, S0A2}),
Sdst2Ssrc02Ssrc12 = FormatDefine({DA2, S0A2, S1A2}),
SmaskVsrc0Vsrc1 = FormatDefine({DA2, S0, S1}),
Vdata1VaddrSvSoffsIdxen = FormatDefine({D, S0, S1A4, S2, Idxen}),
Vdata2VaddrSvSoffsIdxen = FormatDefine({DA2, S0, S1A4, S2, Idxen}),
Vdata3VaddrSvSoffsIdxen = FormatDefine({DA3, S0, S1A4, S2, Idxen}),
Vdata4VaddrSvSoffsIdxen = FormatDefine({DA4, S0, S1A4, S2, Idxen}),
Vdata4VaddrSvSoffsIdxenFloat4 = FormatDefine({DA4, S0, S1A4, S2, Idxen, Float4}),
Vdata3Vaddr3StSsDmask7 = FormatDefine({DA3, S0A3, S1A8, S2A4, Dmask7}),
Vdata4Vaddr3StSsDmaskF = FormatDefine({DA4, S0A3, S1A8, S2A4, DmaskF}),
VdstVsrc0Vsrc1Smask2 = FormatDefine({D, S0, S1, S2A2}),
VdstVsrc0Vsrc1Vsrc2 = FormatDefine({D, S0, S1, S2}),
VdstVsrcAttrChan = FormatDefine({D, S0, Attr}),
VdstSdst2Vsrc0Vsrc1 = FormatDefine({D, D2A2, S0, S1}),
VdstGds = FormatDefine({D, Gds})
};
} // namespace ShaderInstructionFormat
enum class ShaderOperandType
{
Unknown,
LiteralConstant,
IntegerInlineConstant,
FloatInlineConstant,
VccLo,
VccHi,
ExecLo,
ExecHi,
ExecZ,
Vgpr,
Sgpr,
M0
};
union ShaderConstant
{
int32_t i;
uint32_t u;
float f;
};
struct ShaderOperand
{
ShaderOperandType type = ShaderOperandType::Unknown;
ShaderConstant constant = {0};
int register_id = 0;
int size = 0;
float multiplier = 1.0f;
bool negate = false;
bool clamp = false;
bool operator==(const ShaderOperand& other) const
{
return type == other.type && constant.u == other.constant.u && register_id == other.register_id && size == other.size;
}
};
struct ShaderInstruction
{
uint32_t pc = 0;
ShaderInstructionType type = ShaderInstructionType::Unknown;
ShaderInstructionFormat::Format format = ShaderInstructionFormat::Unknown;
ShaderOperand src[4];
int src_num = 0;
ShaderOperand dst;
ShaderOperand dst2;
};
class ShaderCode
{
public:
ShaderCode() { m_instructions.Expand(128); };
virtual ~ShaderCode() = default;
KYTY_CLASS_DEFAULT_COPY(ShaderCode);
[[nodiscard]] const Vector<ShaderInstruction>& GetInstructions() const { return m_instructions; }
Vector<ShaderInstruction>& GetInstructions() { return m_instructions; }
[[nodiscard]] const Vector<uint32_t>& GetLabels() const { return m_labels; }
Vector<uint32_t>& GetLabels() { return m_labels; }
[[nodiscard]] String DbgDump() const;
static String DbgInstructionToStr(const ShaderInstruction& inst);
[[nodiscard]] ShaderType GetType() const { return m_type; }
void SetType(ShaderType type) { this->m_type = type; }
private:
Vector<ShaderInstruction> m_instructions;
Vector<uint32_t> m_labels;
ShaderType m_type = ShaderType::Unknown;
};
struct ShaderId
{
Vector<uint32_t> ids;
bool operator==(const ShaderId& other) const { return ids == other.ids; }
bool operator!=(const ShaderId& other) const { return !(*this == other); }
};
struct ShaderBufferResource
{
uint32_t fields[4] = {0};
void UpdateAddress(uint64_t gpu_addr)
{
auto lo = static_cast<uint32_t>(gpu_addr & 0xffffffffu);
auto hi = static_cast<uint32_t>(gpu_addr >> 32u);
fields[0] = lo;
fields[1] = (fields[1] & 0xfffff000u) | (hi & 0xfffu);
}
[[nodiscard]] uint64_t Base() const { return (fields[0] | (static_cast<uint64_t>(fields[1]) << 32u)) & 0xFFFFFFFFFFFu; }
[[nodiscard]] uint16_t Stride() const { return (fields[1] >> 16u) & 0x3FFFu; }
[[nodiscard]] bool SwizzleEnabled() const { return ((fields[1] >> 31u) & 0x1u) == 1; }
[[nodiscard]] uint32_t NumRecords() const { return fields[2]; }
[[nodiscard]] uint8_t DstSelX() const { return (fields[3] >> 0u) & 0x7u; }
[[nodiscard]] uint8_t DstSelY() const { return (fields[3] >> 3u) & 0x7u; }
[[nodiscard]] uint8_t DstSelZ() const { return (fields[3] >> 6u) & 0x7u; }
[[nodiscard]] uint8_t DstSelW() const { return (fields[3] >> 9u) & 0x7u; }
[[nodiscard]] uint8_t Nfmt() const { return (fields[3] >> 12u) & 0x7u; }
[[nodiscard]] uint8_t Dfmt() const { return (fields[3] >> 15u) & 0xFu; }
[[nodiscard]] bool AddTid() const { return ((fields[3] >> 23u) & 0x1u) == 1; }
[[nodiscard]] uint8_t MemoryType() const
{
return ((fields[1] >> 7u) & 0x60u) | ((fields[3] >> 25u) & 0x1cu) | ((fields[1] >> 14u) & 0x3u);
}
};
struct ShaderTextureResource
{
uint32_t fields[8] = {0};
void UpdateAddress(uint64_t gpu_addr)
{
auto lo = static_cast<uint32_t>(gpu_addr & 0xffffffffu);
auto hi = static_cast<uint32_t>(gpu_addr >> 32u);
fields[0] = lo;
fields[1] = (fields[1] & 0xffffffc0u) | (hi & 0x3fu);
}
[[nodiscard]] uint64_t Base() const { return ((fields[0] | (static_cast<uint64_t>(fields[1]) << 32u)) & 0x3FFFFFFFFFu) << 8u; }
[[nodiscard]] uint16_t MinLod() const { return (fields[1] >> 8u) & 0xFFFu; }
[[nodiscard]] uint8_t Dfmt() const { return (fields[1] >> 20u) & 0x3Fu; }
[[nodiscard]] uint8_t Nfmt() const { return (fields[1] >> 26u) & 0xFu; }
[[nodiscard]] uint16_t Width() const { return (fields[2] >> 0u) & 0x3FFFu; }
[[nodiscard]] uint16_t Height() const { return (fields[2] >> 14u) & 0x3FFFu; }
[[nodiscard]] uint8_t PerfMod() const { return (fields[2] >> 28u) & 0x7u; }
[[nodiscard]] bool Interlaced() const { return ((fields[2] >> 31u) & 0x1u) == 1; }
[[nodiscard]] uint8_t DstSelX() const { return (fields[3] >> 0u) & 0x7u; }
[[nodiscard]] uint8_t DstSelY() const { return (fields[3] >> 3u) & 0x7u; }
[[nodiscard]] uint8_t DstSelZ() const { return (fields[3] >> 6u) & 0x7u; }
[[nodiscard]] uint8_t DstSelW() const { return (fields[3] >> 9u) & 0x7u; }
[[nodiscard]] uint8_t BaseLevel() const { return (fields[3] >> 12u) & 0xFu; }
[[nodiscard]] uint8_t LastLevel() const { return (fields[3] >> 16u) & 0xFu; }
[[nodiscard]] uint8_t TilingIdx() const { return (fields[3] >> 20u) & 0x1Fu; }
[[nodiscard]] bool Pow2Pad() const { return ((fields[3] >> 25u) & 0x1u) == 1; }
[[nodiscard]] uint8_t Type() const { return (fields[3] >> 28u) & 0xFu; }
[[nodiscard]] uint16_t Depth() const { return (fields[4] >> 0u) & 0x1FFFu; }
[[nodiscard]] uint16_t Pitch() const { return (fields[4] >> 13u) & 0x3FFFu; }
[[nodiscard]] uint16_t BaseArray() const { return (fields[5] >> 0u) & 0x1FFFu; }
[[nodiscard]] uint16_t LastArray() const { return (fields[5] >> 13u) & 0x1FFFu; }
[[nodiscard]] uint16_t MinLodWarn() const { return (fields[6] >> 0u) & 0xFFFu; }
[[nodiscard]] uint8_t CounterBankId() const { return (fields[6] >> 12u) & 0xFFu; }
[[nodiscard]] bool LodHdwCntEn() const { return ((fields[6] >> 20u) & 0x1u) == 1; }
[[nodiscard]] uint8_t MemoryType() const
{
return ((fields[1] >> 6u) & 0x3u) | ((fields[1] >> 30u) << 2u) | ((fields[3] & 0x04000000u) == 0 ? 0x60u : 0x10u);
}
};
struct ShaderSamplerResource
{
uint32_t fields[4] = {0};
void UpdateIndex(uint32_t index) { fields[0] = index; }
[[nodiscard]] uint8_t ClampX() const { return (fields[0] >> 0u) & 0x7u; }
[[nodiscard]] uint8_t ClampY() const { return (fields[0] >> 3u) & 0x7u; }
[[nodiscard]] uint8_t ClampZ() const { return (fields[0] >> 6u) & 0x7u; }
[[nodiscard]] uint8_t MaxAnisoRatio() const { return (fields[0] >> 9u) & 0x7u; }
[[nodiscard]] uint8_t DepthCompareFunc() const { return (fields[0] >> 12u) & 0x7u; }
[[nodiscard]] bool ForceUnormCoords() const { return ((fields[0] >> 15u) & 0x1u) == 1; }
[[nodiscard]] uint8_t AnisoThreshold() const { return (fields[0] >> 16u) & 0x7u; }
[[nodiscard]] bool McCoordTrunc() const { return ((fields[0] >> 19u) & 0x1u) == 1; }
[[nodiscard]] bool ForceDegamma() const { return ((fields[0] >> 20u) & 0x1u) == 1; }
[[nodiscard]] uint8_t AnisoBias() const { return (fields[0] >> 21u) & 0x3Fu; }
[[nodiscard]] bool TruncCoord() const { return ((fields[0] >> 27u) & 0x1u) == 1; }
[[nodiscard]] bool DisableCubeWrap() const { return ((fields[0] >> 28u) & 0x1u) == 1; }
[[nodiscard]] uint8_t FilterMode() const { return (fields[0] >> 29u) & 0x3u; }
[[nodiscard]] uint16_t MinLod() const { return (fields[1] >> 0u) & 0xFFFu; }
[[nodiscard]] uint16_t MaxLod() const { return (fields[1] >> 12u) & 0xFFFu; }
[[nodiscard]] uint8_t PerfMip() const { return (fields[1] >> 24u) & 0xFu; }
[[nodiscard]] uint8_t PerfZ() const { return (fields[1] >> 28u) & 0xFu; }
[[nodiscard]] uint16_t LodBias() const { return (fields[2] >> 0u) & 0x3FFFu; }
[[nodiscard]] uint8_t LodBiasSec() const { return (fields[2] >> 14u) & 0x3Fu; }
[[nodiscard]] uint8_t XyMagFilter() const { return (fields[2] >> 20u) & 0x3u; }
[[nodiscard]] uint8_t XyMinFilter() const { return (fields[2] >> 22u) & 0x3u; }
[[nodiscard]] uint8_t ZFilter() const { return (fields[2] >> 24u) & 0x3u; }
[[nodiscard]] uint8_t MipFilter() const { return (fields[2] >> 26u) & 0x3u; }
[[nodiscard]] uint16_t BorderColorPtr() const { return (fields[3] >> 0u) & 0xFFFu; }
[[nodiscard]] uint8_t BorderColorType() const { return (fields[3] >> 30u) & 0x3u; }
};
struct ShaderGdsResource
{
uint32_t field = 0;
[[nodiscard]] uint16_t Base() const { return (field >> 16u) & 0xFFFFu; }
[[nodiscard]] uint16_t Size() const { return field & 0xFFFFu; }
};
struct ShaderExtendedResource
{
uint32_t fields[2] = {0};
void UpdateAddress(uint64_t gpu_addr)
{
auto lo = static_cast<uint32_t>(gpu_addr & 0xffffffffu);
auto hi = static_cast<uint32_t>(gpu_addr >> 32u);
fields[0] = lo;
fields[1] = hi;
}
[[nodiscard]] uint64_t Base() const { return (fields[0] | (static_cast<uint64_t>(fields[1]) << 32u)); }
};
struct ShaderVertexInputBuffer
{
static constexpr int ATTR_MAX = 16;
uint64_t addr = 0;
uint32_t stride = 0;
uint32_t num_records = 0;
int attr_num = 0;
int attr_indices[ATTR_MAX] = {0};
uint32_t attr_offsets[ATTR_MAX] = {0};
};
struct ShaderVertexDestination
{
int register_start = 0;
int registers_num = 0;
};
enum class ShaderStorageUsage
{
Unknown,
Constant,
ReadOnly,
ReadWrite,
};
struct ShaderStorageResources
{
static constexpr int BUFFERS_MAX = 16;
ShaderBufferResource buffers[BUFFERS_MAX];
ShaderStorageUsage usages[BUFFERS_MAX] = {};
int slots[BUFFERS_MAX] = {0};
int start_register[BUFFERS_MAX] = {0};
bool extended[BUFFERS_MAX] = {};
// int extended_index[BUFFERS_MAX] = {0};
int buffers_num = 0;
int binding_index = 0;
};
struct ShaderTextureResources
{
static constexpr int RES_MAX = 16;
ShaderTextureResource textures[RES_MAX];
int start_register[RES_MAX] = {0};
bool extended[RES_MAX] = {};
// int extended_index[RES_MAX] = {0};
int textures_num = 0;
int binding_index = 0;
};
struct ShaderSamplerResources
{
static constexpr int RES_MAX = 16;
ShaderSamplerResource samplers[RES_MAX];
int start_register[RES_MAX] = {0};
bool extended[RES_MAX] = {};
// int extended_index[RES_MAX] = {0};
int samplers_num = 0;
int binding_index = 0;
};
struct ShaderGdsResources
{
static constexpr int POINTERS_MAX = 1;
ShaderGdsResource pointers[POINTERS_MAX];
int slots[POINTERS_MAX] = {0};
int start_register[POINTERS_MAX] = {0};
bool extended[POINTERS_MAX] = {};
// int extended_index[POINTERS_MAX] = {0};
int pointers_num = 0;
int binding_index = 0;
};
struct ShaderExtendedResources
{
bool used = false;
int slot = 0;
// int dw_num = 0;
int start_register = 0;
ShaderExtendedResource data;
};
struct ShaderResources
{
uint32_t push_constant_offset = 0;
uint32_t push_constant_size = 0;
uint32_t descriptor_set_slot = 0;
ShaderStorageResources storage_buffers;
ShaderTextureResources textures2D;
ShaderSamplerResources samplers;
ShaderGdsResources gds_pointers;
ShaderExtendedResources extended;
};
struct ShaderVertexInputInfo
{
static constexpr int RES_MAX = 16;
ShaderBufferResource resources[RES_MAX];
ShaderVertexDestination resources_dst[RES_MAX];
int resources_num = 0;
bool fetch = false;
ShaderVertexInputBuffer buffers[RES_MAX];
int buffers_num = 0;
int export_count = 0;
ShaderResources bind;
};
struct ShaderComputeInputInfo
{
uint32_t threads_num[3] = {};
int workgroup_register = 0;
ShaderResources bind;
};
struct ShaderPixelInputInfo
{
uint32_t interpolator_settings[32] = {0};
uint32_t input_num = 0;
uint8_t target_output_mode[8] = {};
bool ps_pos_xy = false;
bool ps_pixel_kill_enable = false;
ShaderResources 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);
Vector<uint32_t> ShaderRecompileVS(const VertexShaderInfo* regs, const ShaderVertexInputInfo* input_info);
Vector<uint32_t> ShaderRecompilePS(const PixelShaderInfo* regs, const ShaderPixelInputInfo* input_info);
Vector<uint32_t> ShaderRecompileCS(const ComputeShaderInfo* regs, const ShaderComputeInputInfo* input_info);
bool ShaderIsDisabled(uint64_t addr);
void ShaderDisable(uint64_t id);
} // namespace Kyty::Libs::Graphics
#endif // KYTY_EMU_ENABLED
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_SHADER_H_ */
@@ -0,0 +1,26 @@
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_SHADERSPIRV_H_
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_SHADERSPIRV_H_
#include "Kyty/Core/Common.h"
#include "Kyty/Core/String.h"
#include "Emulator/Common.h"
#ifdef KYTY_EMU_ENABLED
namespace Kyty::Libs::Graphics {
class ShaderCode;
struct ShaderVertexInputInfo;
struct ShaderPixelInputInfo;
struct ShaderComputeInputInfo;
String SpirvGenerateSource(const ShaderCode& code, const ShaderVertexInputInfo* vs_input_info, const ShaderPixelInputInfo* ps_input_info,
const ShaderComputeInputInfo* cs_input_info);
String SpirvGetEmbeddedVs(uint32_t id);
} // namespace Kyty::Libs::Graphics
#endif // KYTY_EMU_ENABLED
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_SHADERSPIRV_H_ */
@@ -0,0 +1,40 @@
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_STORAGEBUFFER_H_
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_STORAGEBUFFER_H_
#include "Kyty/Core/Common.h"
#include "Emulator/Common.h"
#include "Emulator/Graphics/GpuMemory.h"
#ifdef KYTY_EMU_ENABLED
namespace Kyty::Libs::Graphics {
struct GraphicContext;
struct VulkanMemory;
class StorageBufferGpuObject: public GpuObject
{
public:
StorageBufferGpuObject(uint64_t stride, uint64_t num_records, bool ronly)
{
params[0] = stride;
params[1] = num_records;
check_hash = true;
read_only = ronly;
type = Graphics::GpuMemoryObjectType::StorageBuffer;
}
void* Create(GraphicContext* ctx, const uint64_t* vaddr, const uint64_t* size, int vaddr_num, VulkanMemory* mem) const override;
bool Equal(const uint64_t* other) const override;
[[nodiscard]] write_back_func_t GetWriteBackFunc() const override;
[[nodiscard]] delete_func_t GetDeleteFunc() const override;
[[nodiscard]] update_func_t GetUpdateFunc() const override;
};
} // namespace Kyty::Libs::Graphics
#endif // KYTY_EMU_ENABLED
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_STORAGEBUFFER_H_ */
@@ -0,0 +1,54 @@
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_TEXTURE_H_
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_TEXTURE_H_
#include "Kyty/Core/Common.h"
#include "Emulator/Common.h"
#include "Emulator/Graphics/GpuMemory.h"
#ifdef KYTY_EMU_ENABLED
namespace Kyty::Libs::Graphics {
struct GraphicContext;
struct VulkanMemory;
class TextureObject: public GpuObject
{
public:
static constexpr int PARAM_DFMT = 0;
static constexpr int PARAM_NFMT = 1;
static constexpr int PARAM_WIDTH = 2;
static constexpr int PARAM_HEIGHT = 3;
static constexpr int PARAM_LEVELS = 4;
static constexpr int PARAM_TILE = 5;
static constexpr int PARAM_NEO = 6;
static constexpr int PARAM_SWIZZLE = 7;
TextureObject(uint32_t dfmt, uint32_t nfmt, uint32_t width, uint32_t height, uint32_t levels, bool htile, bool neo, uint32_t swizzle)
{
params[PARAM_DFMT] = dfmt;
params[PARAM_NFMT] = nfmt;
params[PARAM_WIDTH] = width;
params[PARAM_HEIGHT] = height;
params[PARAM_LEVELS] = levels;
params[PARAM_TILE] = htile ? 1 : 0;
params[PARAM_NEO] = neo ? 1 : 0;
params[PARAM_SWIZZLE] = swizzle;
check_hash = true;
type = Graphics::GpuMemoryObjectType::Texture;
}
void* Create(GraphicContext* ctx, const uint64_t* vaddr, const uint64_t* size, int vaddr_num, VulkanMemory* mem) const override;
bool Equal(const uint64_t* other) const override;
[[nodiscard]] write_back_func_t GetWriteBackFunc() const override { return nullptr; };
[[nodiscard]] delete_func_t GetDeleteFunc() const override;
[[nodiscard]] update_func_t GetUpdateFunc() const override;
};
} // namespace Kyty::Libs::Graphics
#endif // KYTY_EMU_ENABLED
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_TEXTURE_H_ */
@@ -0,0 +1,35 @@
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_TILE_H_
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_TILE_H_
#include "Kyty/Core/Common.h"
#include "Emulator/Common.h"
#ifdef KYTY_EMU_ENABLED
namespace Kyty::Libs::Graphics {
enum class TileMode
{
VideoOutLinear,
VideoOutTiled,
TextureLinear,
TextureTiled,
};
void TileInit();
void TileConvertTiledToLinear(void* dst, const void* src, TileMode mode, uint32_t width, uint32_t height, bool neo);
void TileConvertTiledToLinear(void* dst, const void* src, TileMode mode, uint32_t dfmt, uint32_t nfmt, uint32_t width, uint32_t height,
uint32_t levels, bool neo);
void TileGetDepthSize(uint32_t width, uint32_t height, uint32_t z_format, uint32_t stencil_format, bool htile, bool neo,
uint32_t* stencil_size, uint32_t* htile_size, uint32_t* depth_size, uint32_t* pitch);
void TileGetVideoOutSize(uint32_t width, uint32_t height, bool tile, bool neo, uint32_t* size);
void TileGetTextureSize(uint32_t dfmt, uint32_t nfmt, uint32_t width, uint32_t height, uint32_t levels, bool tile, bool neo,
uint32_t* total_size, uint32_t* level_sizes, uint32_t* padded_width, uint32_t* padded_height);
} // namespace Kyty::Libs::Graphics
#endif
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_TILE_H_ */
@@ -0,0 +1,50 @@
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_UTILS_H_
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_UTILS_H_
#include "Kyty/Core/Common.h"
#include "Emulator/Common.h"
#ifdef KYTY_EMU_ENABLED
namespace Kyty {
template <typename T>
class Vector;
} // namespace Kyty
namespace Kyty::Libs::Graphics {
class CommandBuffer;
struct GraphicContext;
struct VulkanBuffer;
struct VideoOutVulkanImage;
struct TextureVulkanImage;
struct DepthStencilVulkanImage;
struct VulkanSwapchain;
struct BufferImageCopy
{
uint32_t offset;
uint32_t width;
uint32_t height;
};
void UtilBufferToImage(CommandBuffer* buffer, VulkanBuffer* src_buffer, VideoOutVulkanImage* dst_image);
void UtilBufferToImage(CommandBuffer* buffer, VulkanBuffer* src_buffer, TextureVulkanImage* dst_image,
const Vector<BufferImageCopy>& regions);
void UtilBlitImage(CommandBuffer* buffer, VideoOutVulkanImage* src_image, VulkanSwapchain* dst_swapchain);
void UtilFillImage(GraphicContext* ctx, VideoOutVulkanImage* dst_image, const void* src_data, uint64_t size);
void UtilFillImage(GraphicContext* ctx, TextureVulkanImage* dst_image, const void* src_data, uint64_t size,
const Vector<BufferImageCopy>& regions);
void UtilCopyBuffer(VulkanBuffer* src_buffer, VulkanBuffer* dst_buffer, uint64_t size);
void UtilSetImageLayoutOptimal(DepthStencilVulkanImage* image);
void UtilSetImageLayoutOptimal(VideoOutVulkanImage* image);
void VulkanCreateBuffer(GraphicContext* gctx, uint64_t size, VulkanBuffer* buffer);
void VulkanDeleteBuffer(GraphicContext* gctx, VulkanBuffer* buffer);
} // namespace Kyty::Libs::Graphics
#endif // KYTY_EMU_ENABLED
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_UTILS_H_ */
@@ -0,0 +1,37 @@
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_VERTEXBUFFER_H_
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_VERTEXBUFFER_H_
#include "Kyty/Core/Common.h"
#include "Emulator/Common.h"
#include "Emulator/Graphics/GpuMemory.h"
#ifdef KYTY_EMU_ENABLED
namespace Kyty::Libs::Graphics {
struct GraphicContext;
struct VulkanMemory;
class VertexBufferGpuObject: public GpuObject
{
public:
VertexBufferGpuObject()
{
check_hash = true;
type = Graphics::GpuMemoryObjectType::VertexBuffer;
}
void* Create(GraphicContext* ctx, const uint64_t* vaddr, const uint64_t* size, int vaddr_num, VulkanMemory* mem) const override;
bool Equal(const uint64_t* other) const override;
[[nodiscard]] write_back_func_t GetWriteBackFunc() const override { return nullptr; };
[[nodiscard]] delete_func_t GetDeleteFunc() const override;
[[nodiscard]] update_func_t GetUpdateFunc() const override;
};
} // namespace Kyty::Libs::Graphics
#endif // KYTY_EMU_ENABLED
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_VERTEXBUFFER_H_ */
@@ -0,0 +1,52 @@
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_VIDEOOUT_H_
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_VIDEOOUT_H_
#include "Kyty/Core/Common.h"
//#include "Kyty/Core/Subsystems.h"
#include "Emulator/Common.h"
#include "Emulator/Kernel/EventQueue.h"
#ifdef KYTY_EMU_ENABLED
namespace Kyty::Libs::Graphics {
// struct VulkanSwapchain;
struct VideoOutVulkanImage;
} // namespace Kyty::Libs::Graphics
namespace Kyty::Libs::VideoOut {
struct VideoOutResolutionStatus;
struct VideoOutBufferAttribute;
struct VideoOutFlipStatus;
struct VideoOutBufferImageInfo
{
Graphics::VideoOutVulkanImage* image = nullptr;
uint32_t index = static_cast<uint32_t>(-1);
uint64_t buffer_size = 0;
};
void VideoOutInit(uint32_t width, uint32_t height);
VideoOutBufferImageInfo VideoOutGetImage(uint64_t addr);
void VideoOutWaitFlipDone(int handle, int index);
KYTY_SYSV_ABI int VideoOutOpen(int user_id, int bus_type, int index, const void* param);
KYTY_SYSV_ABI int VideoOutClose(int handle);
KYTY_SYSV_ABI int VideoOutGetResolutionStatus(int handle, VideoOutResolutionStatus* status);
KYTY_SYSV_ABI void VideoOutSetBufferAttribute(VideoOutBufferAttribute* attribute, uint32_t pixel_format, uint32_t tiling_mode,
uint32_t aspect_ratio, uint32_t width, uint32_t height, uint32_t pitch_in_pixel);
KYTY_SYSV_ABI int VideoOutSetFlipRate(int handle, int rate);
KYTY_SYSV_ABI int VideoOutAddFlipEvent(LibKernel::EventQueue::KernelEqueue eq, int handle, void* udata);
KYTY_SYSV_ABI int VideoOutRegisterBuffers(int handle, int start_index, void* const* addresses, int buffer_num,
const VideoOutBufferAttribute* attribute);
KYTY_SYSV_ABI int VideoOutSubmitFlip(int handle, int index, int flip_mode, int64_t flip_arg);
KYTY_SYSV_ABI int VideoOutGetFlipStatus(int handle, VideoOutFlipStatus* status);
bool FlipWindow(uint32_t micros);
} // namespace Kyty::Libs::VideoOut
#endif // KYTY_EMU_ENABLED
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_VIDEOOUT_H_ */
@@ -0,0 +1,48 @@
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_VIDEOOUTBUFFER_H_
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_VIDEOOUTBUFFER_H_
#include "Kyty/Core/Common.h"
#include "Emulator/Common.h"
#include "Emulator/Graphics/GpuMemory.h"
#ifdef KYTY_EMU_ENABLED
namespace Kyty::Libs::Graphics {
struct GraphicContext;
struct VulkanMemory;
class VideoOutBufferObject: public GpuObject
{
public:
static constexpr int PARAM_FORMAT = 0;
static constexpr int PARAM_WIDTH = 1;
static constexpr int PARAM_HEIGHT = 2;
static constexpr int PARAM_TILED = 3;
static constexpr int PARAM_NEO = 4;
explicit VideoOutBufferObject(uint32_t pixel_format, uint32_t width, uint32_t height, bool tiled, bool neo)
{
params[PARAM_FORMAT] = pixel_format;
params[PARAM_WIDTH] = width;
params[PARAM_HEIGHT] = height;
params[PARAM_TILED] = tiled ? 1 : 0;
params[PARAM_NEO] = neo ? 1 : 0;
check_hash = true;
type = Graphics::GpuMemoryObjectType::VideoOutBuffer;
}
void* Create(GraphicContext* ctx, const uint64_t* vaddr, const uint64_t* size, int vaddr_num, VulkanMemory* mem) const override;
bool Equal(const uint64_t* other) const override;
[[nodiscard]] write_back_func_t GetWriteBackFunc() const override { return nullptr; };
[[nodiscard]] delete_func_t GetDeleteFunc() const override;
[[nodiscard]] update_func_t GetUpdateFunc() const override;
};
} // namespace Kyty::Libs::Graphics
#endif // KYTY_EMU_ENABLED
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_VIDEOOUTBUFFER_H_ */
@@ -0,0 +1,30 @@
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_WINDOW_H_
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_WINDOW_H_
#include "Kyty/Core/Common.h"
#include "Emulator/Common.h"
#ifdef KYTY_EMU_ENABLED
struct VkSurfaceCapabilitiesKHR;
namespace Kyty::Libs::Graphics {
struct GraphicContext;
struct VideoOutVulkanImage;
VkSurfaceCapabilitiesKHR* VulkanGetSurfaceCapabilities();
GraphicContext* WindowGetGraphicContext();
void WindowInit(uint32_t width, uint32_t height);
void WindowRun();
void WindowWaitForGraphicInitialized();
void WindowDrawBuffer(VideoOutVulkanImage* image);
} // namespace Kyty::Libs::Graphics
#endif // KYTY_EMU_ENABLED
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_WINDOW_H_ */