release 0.1.0

This commit is contained in:
InoriRus
2022-05-21 22:04:50 +10:00
parent bc02c0560e
commit a37a9ca253
1056 changed files with 222884 additions and 41332 deletions
+470 -1
View File
@@ -65,6 +65,7 @@ public:
KYTY_CLASS_NO_COPY(Audio);
Id AudioOutOpen(int type, uint32_t samples_num, uint32_t freq, Format format);
bool AudioOutClose(Id handle);
bool AudioOutValid(Id handle);
bool AudioOutSetVolume(Id handle, uint32_t bitflag, const int* volume);
uint32_t AudioOutOutputs(OutputParam* params, uint32_t num);
@@ -159,6 +160,19 @@ Audio::Id Audio::AudioOutOpen(int type, uint32_t samples_num, uint32_t freq, For
return Id::Invalid();
}
bool Audio::AudioOutClose(Id handle)
{
Core::LockGuard lock(m_mutex);
if (AudioOutValid(handle))
{
m_out_ports[handle.GetId()].used = false;
return true;
}
return false;
}
bool Audio::AudioOutValid(Id handle)
{
Core::LockGuard lock(m_mutex);
@@ -211,7 +225,7 @@ uint32_t Audio::AudioOutOutputs(OutputParam* params, uint32_t num)
const auto& first_port = m_out_ports[params[0].handle.GetId()];
uint64_t block_time = (1000000 * first_port.samples_num) / first_port.freq;
uint64_t block_time = (params->data != nullptr ? (1000000 * first_port.samples_num) / first_port.freq : 0);
uint64_t current_time = LibKernel::KernelGetProcessTime();
uint64_t max_wait_time = 0;
@@ -354,6 +368,18 @@ int KYTY_SYSV_ABI AudioOutOpen(int user_id, int type, int index, uint32_t len, u
return id.ToInt();
}
int KYTY_SYSV_ABI AudioOutClose(int handle)
{
PRINT_NAME();
if (!g_audio->AudioOutClose(Audio::Id(handle)))
{
return AUDIO_OUT_ERROR_INVALID_PORT;
}
return OK;
}
int KYTY_SYSV_ABI AudioOutSetVolume(int handle, uint32_t flag, int* vol)
{
PRINT_NAME();
@@ -401,6 +427,29 @@ int KYTY_SYSV_ABI AudioOutOutputs(AudioOutOutputParam* param, uint32_t num)
return static_cast<int>(g_audio->AudioOutOutputs(params, num));
}
int KYTY_SYSV_ABI AudioOutOutput(int handle, const void* ptr)
{
PRINT_NAME();
printf("\t handle = %d\n", handle);
// EXIT_NOT_IMPLEMENTED(ptr == nullptr);
Audio::OutputParam params[1];
EXIT_IF(g_audio == nullptr);
params[0].handle = Audio::Id(handle);
params[0].data = ptr;
if (!g_audio->AudioOutValid(params[0].handle))
{
return AUDIO_OUT_ERROR_INVALID_PORT;
}
return static_cast<int>(g_audio->AudioOutOutputs(params, 1));
}
} // namespace AudioOut
namespace AudioIn {
@@ -497,8 +546,428 @@ int KYTY_SYSV_ABI AjmInitialize(int64_t reserved, uint32_t* context)
return OK;
}
int KYTY_SYSV_ABI AjmModuleRegister(uint32_t context, uint32_t codec, int64_t reserved)
{
PRINT_NAME();
EXIT_NOT_IMPLEMENTED(context != 1);
EXIT_NOT_IMPLEMENTED(reserved != 0);
printf("\t codec = %u\n", codec);
switch (codec)
{
case 1: printf("\t %s\n", "ATRAC9 decoder"); break;
case 2: printf("\t %s\n", "MPEG4-AAC decoder"); break;
case 0: printf("\t %s\n", "MP3 decoder"); break;
case 4: printf("\t %s\n", "CELP8 encoder"); break;
case 3: printf("\t %s\n", "CELP8 decoder"); break;
case 13: printf("\t %s\n", "CELP16 encoder"); break;
case 12: printf("\t %s\n", "CELP16 decoder"); break;
default: EXIT("unknown codec\n");
}
return OK;
}
} // namespace Ajm
namespace AvPlayer {
LIB_NAME("AvPlayer", "AvPlayer");
using AvPlayerAllocate = KYTY_SYSV_ABI void* (*)(void*, uint32_t, uint32_t);
using AvPlayerDeallocate = KYTY_SYSV_ABI void (*)(void*, void*);
using AvPlayerAllocateTexture = KYTY_SYSV_ABI void* (*)(void*, uint32_t, uint32_t);
using AvPlayerDeallocateTexture = KYTY_SYSV_ABI void (*)(void*, void*);
using AvPlayerOpenFile = KYTY_SYSV_ABI int (*)(void*, const char*);
using AvPlayerCloseFile = KYTY_SYSV_ABI int (*)(void*);
using AvPlayerReadOffsetFile = KYTY_SYSV_ABI int (*)(void*, uint8_t*, uint64_t, uint32_t);
using AvPlayerSizeFile = KYTY_SYSV_ABI uint64_t (*)(void*);
using AvPlayerEventCallback = KYTY_SYSV_ABI void (*)(void*, int32_t, int32_t, void*);
struct AvPlayerMemAllocator
{
void* object_pointer = nullptr;
AvPlayerAllocate allocate = nullptr;
AvPlayerDeallocate deallocate = nullptr;
AvPlayerAllocateTexture allocate_texture = nullptr;
AvPlayerDeallocateTexture deallocate_texture = nullptr;
};
struct AvPlayerFileReplacement
{
void* object_pointer = nullptr;
AvPlayerOpenFile open = nullptr;
AvPlayerCloseFile close = nullptr;
AvPlayerReadOffsetFile read_offset = nullptr;
AvPlayerSizeFile size = nullptr;
};
struct AvPlayerEventReplacement
{
void* object_pointer = nullptr;
AvPlayerEventCallback event_callback = nullptr;
};
enum AvPlayerDebuglevels
{
AvplayerDbgNone,
AvplayerDbgInfo,
AvplayerDbgWarnings,
AvplayerDbgAll
};
struct AvPlayerInitData
{
AvPlayerMemAllocator memory_replacement;
AvPlayerFileReplacement file_replacement;
AvPlayerEventReplacement event_replacement;
AvPlayerDebuglevels debug_level = AvPlayerDebuglevels::AvplayerDbgNone;
uint32_t base_priority = 0;
int32_t num_output_video_framebuffers = 0;
Bool auto_start = 0;
uint8_t reserved[3] = {};
const char* default_language = nullptr;
};
struct AvPlayerAudioEx
{
uint16_t channel_count;
uint8_t reserved[2];
uint32_t sample_rate;
uint32_t size;
uint8_t language_code[4];
uint8_t reserved1[64];
};
struct AvPlayerVideoEx
{
uint32_t width;
uint32_t height;
float aspect_ratio;
uint8_t language_code[4];
uint32_t framerate;
uint32_t crop_left_offset;
uint32_t crop_right_offset;
uint32_t crop_top_offset;
uint32_t crop_bottom_offset;
uint32_t pitch;
uint8_t luma_bit_depth;
uint8_t chroma_bit_depth;
Bool video_full_tange_flag;
uint8_t reserved1[37];
};
struct AvPlayerTimedTextEx
{
uint8_t language_code[4];
uint8_t reserved[12];
uint8_t reserved1[64];
};
union AvPlayerStreamDetailsEx
{
AvPlayerAudioEx audio;
AvPlayerVideoEx video;
AvPlayerTimedTextEx subs;
uint8_t reserved1[80];
};
struct AvPlayerFrameInfoEx
{
void* data;
uint8_t reserved[4];
uint64_t time_stamp;
AvPlayerStreamDetailsEx details;
};
struct AvPlayerInternal
{
String filename;
bool loop = false;
AvPlayerMemAllocator mem;
Core::Mutex mutex;
void* fake_frame = nullptr;
uint32_t fake_width = 0;
uint32_t fake_height = 0;
float fake_frame_rate = 0.0f;
uint32_t fake_frame_num = 0;
uint32_t fake_obtained_num = 0;
};
static void rgb_to_yuv(float r, float g, float b, uint8_t* y, uint8_t* u, uint8_t* v)
{
int yf = static_cast<int>(16.0f + 65.481f * r + 128.553f * g + 24.966f * b);
int uf = static_cast<int>(128.0f + -37.797f * r + -74.203f * g + 112.0f * b);
int vf = static_cast<int>(128.0f + 112.0f * r + -93.786f * g + -18.214f * b);
*y = (yf < 0 ? 0 : (yf > 255 ? 255 : yf));
*u = (uf < 0 ? 0 : (uf > 255 ? 255 : uf));
*v = (vf < 0 ? 0 : (vf > 255 ? 255 : vf));
}
static void draw_fake_frame(uint32_t width, uint32_t height, void* data, float l)
{
constexpr int STRIPS_NUM = 5;
uint32_t luma_width = width;
uint32_t luma_height = height;
uint32_t chroma_width = luma_width / 2;
uint32_t chroma_height = luma_height / 2;
auto* buffer = static_cast<uint8_t*>(data);
auto* luma = buffer;
auto* chroma = buffer + luma_width * luma_height;
uint32_t luma_strip_size = luma_height / STRIPS_NUM;
uint32_t chroma_strip_size = chroma_height / STRIPS_NUM;
uint8_t color[STRIPS_NUM][3] = {};
rgb_to_yuv(l, 0, 0, &color[0][0], &color[0][1], &color[0][2]);
rgb_to_yuv(0, l, 0, &color[1][0], &color[1][1], &color[1][2]);
rgb_to_yuv(0, 0, l, &color[2][0], &color[2][1], &color[2][2]);
rgb_to_yuv(0, 0, 0, &color[3][0], &color[3][1], &color[3][2]);
rgb_to_yuv(l, l, l, &color[4][0], &color[4][1], &color[4][2]);
for (uint32_t y = 0; y < luma_strip_size; y++)
{
for (uint32_t x = 0; x < luma_width; x++)
{
for (int si = 0; si < STRIPS_NUM; si++)
{
luma[(y + luma_strip_size * si) * luma_width + x] = color[si][0];
}
}
}
for (uint32_t y = 0; y < chroma_strip_size; y++)
{
for (uint32_t x = 0; x < chroma_width; x++)
{
for (int si = 0; si < STRIPS_NUM; si++)
{
chroma[(y + chroma_strip_size * si) * chroma_width * 2 + x * 2 + 0] = color[si][1];
chroma[(y + chroma_strip_size * si) * chroma_width * 2 + x * 2 + 1] = color[si][2];
}
}
}
}
static void create_fake_video(AvPlayerInternal* r)
{
uint32_t luma_width = 1920;
uint32_t luma_height = 1080;
uint32_t chroma_width = luma_width / 2;
uint32_t chroma_height = luma_height / 2;
uint32_t size = luma_width * luma_height + chroma_width * chroma_height * 2;
auto* buffer = static_cast<uint8_t*>(r->mem.allocate_texture(r->mem.object_pointer, 256, size));
r->fake_frame = buffer;
r->fake_width = luma_width;
r->fake_height = luma_height;
r->fake_frame_rate = 59.94f;
r->fake_frame_num = 90;
r->fake_obtained_num = 0;
}
static void delete_fake_video(AvPlayerInternal* r)
{
r->mem.deallocate_texture(r->mem.object_pointer, r->fake_frame);
r->fake_frame = nullptr;
r->fake_width = 0;
r->fake_height = 0;
r->fake_frame_rate = 0.0f;
r->fake_frame_num = 0;
r->fake_obtained_num = 0;
}
static bool get_fake_video(AvPlayerInternal* r, AvPlayerFrameInfoEx* info)
{
if (r->fake_obtained_num < r->fake_frame_num)
{
info->data = r->fake_frame;
info->time_stamp = static_cast<uint64_t>(1000.0f * (static_cast<float>(r->fake_obtained_num) / r->fake_frame_rate));
info->details.video.width = r->fake_width;
info->details.video.height = r->fake_height;
info->details.video.aspect_ratio = static_cast<float>(r->fake_width) / static_cast<float>(r->fake_height);
info->details.video.language_code[0] = 'e';
info->details.video.language_code[1] = 'n';
info->details.video.language_code[2] = 'g';
info->details.video.language_code[3] = '\0';
info->details.video.framerate = 0;
info->details.video.crop_left_offset = 0;
info->details.video.crop_right_offset = 0;
info->details.video.crop_top_offset = 0;
info->details.video.crop_bottom_offset = 0;
info->details.video.pitch = r->fake_width;
info->details.video.luma_bit_depth = 8;
info->details.video.chroma_bit_depth = 8;
info->details.video.video_full_tange_flag = 0;
float pos = static_cast<float>(r->fake_obtained_num) / static_cast<float>(r->fake_frame_num);
float level = 1.0f;
if (pos < 0.2f)
{
level = pos * pos * ((1.0f / 0.2f) * (1.0f / 0.2f));
} else if (pos > 0.5f)
{
level = 1.0f - (1.0f - pos * (1.0f / 0.5f)) * (1.0f - pos * (1.0f / 0.5f));
}
draw_fake_frame(r->fake_width, r->fake_height, r->fake_frame, level * 0.7f);
r->fake_obtained_num++;
return true;
}
return false;
}
static bool fake_is_playing(AvPlayerInternal* r)
{
return r->fake_obtained_num < r->fake_frame_num;
}
AvPlayerInternal* KYTY_SYSV_ABI AvPlayerInit(AvPlayerInitData* init)
{
PRINT_NAME();
EXIT_NOT_IMPLEMENTED(init == nullptr);
printf("\t memory_replacement.object_pointer = %016" PRIx64 "\n",
reinterpret_cast<uint64_t>(init->memory_replacement.object_pointer));
printf("\t memory_replacement.allocate = %016" PRIx64 "\n", reinterpret_cast<uint64_t>(init->memory_replacement.allocate));
printf("\t memory_replacement.deallocate = %016" PRIx64 "\n", reinterpret_cast<uint64_t>(init->memory_replacement.deallocate));
printf("\t memory_replacement.allocate_texture = %016" PRIx64 "\n",
reinterpret_cast<uint64_t>(init->memory_replacement.allocate_texture));
printf("\t memory_replacement.deallocate_texture = %016" PRIx64 "\n",
reinterpret_cast<uint64_t>(init->memory_replacement.deallocate_texture));
printf("\t file_replacement.object_pointer = %016" PRIx64 "\n",
reinterpret_cast<uint64_t>(init->file_replacement.object_pointer));
printf("\t file_replacement.open = %016" PRIx64 "\n", reinterpret_cast<uint64_t>(init->file_replacement.open));
printf("\t file_replacement.close = %016" PRIx64 "\n", reinterpret_cast<uint64_t>(init->file_replacement.close));
printf("\t file_replacement.read_offset = %016" PRIx64 "\n", reinterpret_cast<uint64_t>(init->file_replacement.read_offset));
printf("\t file_replacement.size = %016" PRIx64 "\n", reinterpret_cast<uint64_t>(init->file_replacement.size));
printf("\t event_replacement.object_pointer = %016" PRIx64 "\n",
reinterpret_cast<uint64_t>(init->event_replacement.object_pointer));
printf("\t event_replacement.event_callback = %016" PRIx64 "\n",
reinterpret_cast<uint64_t>(init->event_replacement.event_callback));
printf("\t debug_level = %s\n", Core::EnumName(init->debug_level).C_Str());
printf("\t num_output_video_framebuffers = %d\n", init->num_output_video_framebuffers);
printf("\t base_priority = %u\n", init->base_priority);
printf("\t auto_start = %u\n", init->auto_start);
printf("\t default_language = %s\n", init->default_language == nullptr ? "(null)" : init->default_language);
auto* r = new AvPlayerInternal;
EXIT_NOT_IMPLEMENTED(init->auto_start != 0);
EXIT_NOT_IMPLEMENTED(init->file_replacement.object_pointer != nullptr);
EXIT_NOT_IMPLEMENTED(init->file_replacement.open != nullptr);
EXIT_NOT_IMPLEMENTED(init->file_replacement.close != nullptr);
EXIT_NOT_IMPLEMENTED(init->file_replacement.read_offset != nullptr);
EXIT_NOT_IMPLEMENTED(init->file_replacement.size != nullptr);
EXIT_NOT_IMPLEMENTED(init->event_replacement.object_pointer != nullptr);
EXIT_NOT_IMPLEMENTED(init->event_replacement.event_callback != nullptr);
r->mem = init->memory_replacement;
create_fake_video(r);
return r;
}
int KYTY_SYSV_ABI AvPlayerAddSource(AvPlayerInternal* h, const char* filename)
{
PRINT_NAME();
EXIT_NOT_IMPLEMENTED(h == nullptr);
printf("\t filename = %s\n", filename);
Core::LockGuard lock(h->mutex);
h->filename = filename;
return 0;
}
int KYTY_SYSV_ABI AvPlayerSetLooping(AvPlayerInternal* h, Bool loop)
{
PRINT_NAME();
EXIT_NOT_IMPLEMENTED(h == nullptr);
printf("\t loop = %u\n", loop);
Core::LockGuard lock(h->mutex);
h->loop = (loop != 0);
return 0;
}
Bool KYTY_SYSV_ABI AvPlayerGetVideoDataEx(AvPlayerInternal* h, AvPlayerFrameInfoEx* video_info)
{
PRINT_NAME();
EXIT_NOT_IMPLEMENTED(h == nullptr);
EXIT_NOT_IMPLEMENTED(video_info == nullptr);
Core::LockGuard lock(h->mutex);
EXIT_NOT_IMPLEMENTED(h->loop);
if (get_fake_video(h, video_info))
{
return 1; // true
}
return 0; // false
}
Bool KYTY_SYSV_ABI AvPlayerGetAudioData(AvPlayerInternal* h, AvPlayerFrameInfo* audio_info)
{
PRINT_NAME();
EXIT_NOT_IMPLEMENTED(h == nullptr);
EXIT_NOT_IMPLEMENTED(audio_info == nullptr);
return 0; // false
}
Bool KYTY_SYSV_ABI AvPlayerIsActive(AvPlayerInternal* h)
{
PRINT_NAME();
if (h != nullptr)
{
Core::LockGuard lock(h->mutex);
EXIT_NOT_IMPLEMENTED(h->loop);
if (fake_is_playing(h))
{
return 1; // true
}
}
return 0; // false
}
int KYTY_SYSV_ABI AvPlayerClose(AvPlayerInternal* h)
{
PRINT_NAME();
EXIT_NOT_IMPLEMENTED(h == nullptr);
delete_fake_video(h);
delete h;
return 0;
}
} // namespace AvPlayer
} // namespace Kyty::Libs::Audio
#endif // KYTY_EMU_ENABLED
+21
View File
@@ -22,9 +22,12 @@ struct Config
String command_buffer_dump_folder = U"_Buffers";
Log::Direction printf_direction = Log::Direction::Console;
String printf_output_file = U"_kyty.txt";
String printf_output_folder = U"_Logs";
ProfilerDirection profiler_direction = ProfilerDirection::None;
String profiler_output_file = U"_profile.prof";
bool spirv_debug_printf_enabled = false;
bool pipeline_dump_enabled = false;
String pipeline_dump_folder = U"_Pipelines";
};
static Config* g_config = nullptr;
@@ -92,9 +95,12 @@ void Load(const Scripts::ScriptVar& cfg)
LoadStr(g_config->command_buffer_dump_folder, cfg, U"CommandBufferDumpFolder");
LoadEnum(g_config->printf_direction, cfg, U"PrintfDirection");
LoadStr(g_config->printf_output_file, cfg, U"PrintfOutputFile");
LoadStr(g_config->printf_output_folder, cfg, U"PrintfOutputFolder");
LoadEnum(g_config->profiler_direction, cfg, U"ProfilerDirection");
LoadStr(g_config->profiler_output_file, cfg, U"ProfilerOutputFile");
LoadBool(g_config->spirv_debug_printf_enabled, cfg, U"SpirvDebugPrintfEnabled");
LoadBool(g_config->pipeline_dump_enabled, cfg, U"PipelineDumpEnabled");
LoadStr(g_config->pipeline_dump_folder, cfg, U"PipelineDumpFolder");
}
uint32_t GetScreenWidth()
@@ -157,6 +163,11 @@ String GetPrintfOutputFile()
return g_config->printf_output_file;
}
String GetPrintfOutputFolder()
{
return g_config->printf_output_folder;
}
ProfilerDirection GetProfilerDirection()
{
return g_config->profiler_direction;
@@ -172,6 +183,16 @@ bool SpirvDebugPrintfEnabled()
return g_config->spirv_debug_printf_enabled;
}
bool PipelineDumpEnabled()
{
return g_config->pipeline_dump_enabled;
}
String GetPipelineDumpFolder()
{
return g_config->pipeline_dump_folder;
}
} // namespace Kyty::Config
#endif // KYTY_EMU_ENABLED
+19
View File
@@ -560,6 +560,25 @@ int KYTY_SYSV_ABI PadSetVibration(int handle, const PadVibrationParam* param)
return OK;
}
int KYTY_SYSV_ABI PadResetLightBar(int handle)
{
PRINT_NAME();
EXIT_NOT_IMPLEMENTED(handle != 1);
return OK;
}
int KYTY_SYSV_ABI PadSetLightBar(int handle, const PadLightBarParam* param)
{
PRINT_NAME();
EXIT_NOT_IMPLEMENTED(handle != 1);
EXIT_NOT_IMPLEMENTED(param == nullptr);
return OK;
}
} // namespace Kyty::Libs::Controller
#endif // KYTY_EMU_ENABLED
+3 -1
View File
@@ -9,6 +9,7 @@
#include "Emulator/Graphics/GraphicsRun.h"
#include "Emulator/Graphics/HardwareContext.h"
#include "Emulator/Graphics/Objects/GpuMemory.h"
#include "Emulator/Graphics/Objects/IndexBuffer.h"
#include "Emulator/Graphics/Objects/Label.h"
#include "Emulator/Graphics/Pm4.h"
#include "Emulator/Graphics/Tile.h"
@@ -38,6 +39,7 @@ KYTY_SUBSYSTEM_INIT(Graphics)
GpuMemoryInit();
LabelInit();
TileInit();
IndexBufferInit();
}
KYTY_SUBSYSTEM_UNEXPECTED_SHUTDOWN(Graphics) {}
@@ -519,7 +521,7 @@ void KYTY_SYSV_ABI GraphicsFlushMemory()
{
PRINT_NAME();
GpuMemoryFlush(WindowGetGraphicContext());
GpuMemoryFlushAll(WindowGetGraphicContext());
}
int KYTY_SYSV_ABI GraphicsAddEqEvent(LibKernel::EventQueue::KernelEqueue eq, int id, void* udata)
File diff suppressed because it is too large Load Diff
+122 -42
View File
@@ -32,8 +32,6 @@
namespace Kyty::Libs::Graphics {
class CommandProcessor;
class CommandProcessor
{
public:
@@ -56,10 +54,14 @@ public:
void BufferFlush();
void BufferWait();
void Lock() { m_mutex.Lock(); }
void Unlock() { m_mutex.Unlock(); }
HW::HardwareContext* GetCtx() { return &m_ctx; }
HW::UserConfig* GetUcfg() { return &m_ucfg; }
void SetIndexType(uint32_t index_type_and_size);
void SetNumInstances(uint32_t num_instances);
void DrawIndex(uint32_t index_count, const void* index_addr, uint32_t flags, uint32_t type);
void DrawIndexAuto(uint32_t index_count, uint32_t flags);
void WriteAtEndOfPipe32(uint32_t cache_policy, uint32_t event_write_dest, uint32_t eop_event_type, uint32_t cache_action,
@@ -123,8 +125,9 @@ private:
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;
uint32_t m_index_type_and_size = 0;
uint32_t m_num_instances = 1;
Core::Mutex m_mutex;
@@ -488,6 +491,8 @@ void CommandProcessor::Reset()
BufferWait();
GraphicsRenderDeleteIndexBuffers();
m_ucfg.Reset();
m_ctx.Reset();
m_index_type_and_size = 0;
@@ -621,6 +626,8 @@ void CommandProcessor::DumpConstRam(uint32_t* dst, uint32_t offset, uint32_t dw_
GpuMemoryCheckAccessViolation(reinterpret_cast<uint64_t>(dst), dw_num * 4);
memcpy(dst, m_const_ram + offset / 4, dw_num * 4);
GraphicsRenderMemoryFlush(reinterpret_cast<uint64_t>(dst), dw_num * 4);
}
void CommandProcessor::WaitRegMem(uint32_t func, bool me, bool mem, const uint32_t* addr, uint32_t ref, uint32_t mask, uint32_t poll)
@@ -647,6 +654,8 @@ void CommandProcessor::WriteData(uint32_t* dst, const uint32_t* src, uint32_t dw
GpuMemoryCheckAccessViolation(reinterpret_cast<uint64_t>(dst), dw_num * 4);
memcpy(dst, src, dw_num * 4);
GraphicsRenderMemoryFlush(reinterpret_cast<uint64_t>(dst), dw_num * 4);
}
void GraphicsRing::Submit(uint32_t* cmd_draw_buffer, uint32_t num_draw_dw, uint32_t* cmd_const_buffer, uint32_t num_const_dw, int handle,
@@ -973,6 +982,20 @@ void CommandProcessor::SetIndexType(uint32_t index_type_and_size)
m_index_type_and_size = index_type_and_size;
}
void CommandProcessor::SetNumInstances(uint32_t num_instances)
{
Core::LockGuard lock(m_mutex);
if (num_instances == 0)
{
num_instances = 1;
}
m_num_instances = num_instances;
EXIT_NOT_IMPLEMENTED(m_num_instances != 1);
}
void CommandProcessor::DrawIndex(uint32_t index_count, const void* index_addr, uint32_t flags, uint32_t type)
{
Core::LockGuard lock(m_mutex);
@@ -1225,15 +1248,15 @@ void CommandProcessor::WriteBack()
{
Core::LockGuard lock(m_mutex);
GraphicsRenderWriteBack();
GraphicsRenderWriteBack(this);
}
void CommandBuffer::CommandProcessorWait()
{
EXIT_IF(m_parent == nullptr);
m_parent->BufferWait();
}
// void CommandBuffer::CommandProcessorWait()
//{
// EXIT_IF(m_parent == nullptr);
//
// m_parent->BufferWait();
//}
void GraphicsRunSubmit(uint32_t* cmd_draw_buffer, uint32_t num_draw_dw, uint32_t* cmd_const_buffer, uint32_t num_const_dw)
{
@@ -1304,6 +1327,34 @@ int GraphicsRunGetFrameNum()
return g_gpu->GetFrameNum();
}
void GraphicsRunCommandProcessorFlush(CommandProcessor* cp)
{
EXIT_IF(cp == nullptr);
cp->BufferFlush();
}
void GraphicsRunCommandProcessorWait(CommandProcessor* cp)
{
EXIT_IF(cp == nullptr);
cp->BufferWait();
}
void GraphicsRunCommandProcessorLock(CommandProcessor* cp)
{
EXIT_IF(cp == nullptr);
cp->Lock();
}
void GraphicsRunCommandProcessorUnlock(CommandProcessor* cp)
{
EXIT_IF(cp == nullptr);
cp->Unlock();
}
KYTY_HW_CTX_PARSER(hw_ctx_set_depth_render_target)
{
EXIT_NOT_IMPLEMENTED(cmd_offset != Pm4::DB_Z_INFO);
@@ -1404,33 +1455,15 @@ KYTY_HW_CTX_PARSER(hw_ctx_set_ps_input)
{
EXIT_NOT_IMPLEMENTED(cmd_offset != Pm4::SPI_PS_INPUT_CNTL_0);
uint32_t count = 0;
if (cmd_id == 0xC0016900)
{
cp->GetCtx()->SetPsInputSettings(0, buffer[0]);
count = 1;
} else if (cmd_id == 0xC0026900)
{
cp->GetCtx()->SetPsInputSettings(0, buffer[0]);
cp->GetCtx()->SetPsInputSettings(1, buffer[1]);
count = 2;
} else if (cmd_id == 0xC0036900)
{
cp->GetCtx()->SetPsInputSettings(0, buffer[0]);
cp->GetCtx()->SetPsInputSettings(1, buffer[1]);
cp->GetCtx()->SetPsInputSettings(2, buffer[2]);
count = 3;
} else if (cmd_id == 0xc0046900)
{
cp->GetCtx()->SetPsInputSettings(0, buffer[0]);
cp->GetCtx()->SetPsInputSettings(1, buffer[1]);
cp->GetCtx()->SetPsInputSettings(2, buffer[2]);
cp->GetCtx()->SetPsInputSettings(3, buffer[3]);
count = 4;
}
uint32_t count = (cmd_id >> 16u) & 0x3fffu;
EXIT_NOT_IMPLEMENTED(count == 0);
EXIT_NOT_IMPLEMENTED(count > 32);
for (uint32_t i = 0; i < count; i++)
{
cp->GetCtx()->SetPsInputSettings(i, buffer[i]);
}
return count;
}
@@ -2179,6 +2212,17 @@ KYTY_CP_OP_PARSER(cp_op_index_type)
return 1;
}
KYTY_CP_OP_PARSER(cp_op_num_instances)
{
KYTY_PROFILER_FUNCTION();
EXIT_NOT_IMPLEMENTED(cmd_id != 0xc0002f00);
cp->SetNumInstances(buffer[0]);
return 1;
}
KYTY_CP_OP_PARSER(cp_op_push_marker)
{
KYTY_PROFILER_FUNCTION();
@@ -2211,16 +2255,50 @@ KYTY_CP_OP_PARSER(cp_op_draw_index)
{
KYTY_PROFILER_FUNCTION();
EXIT_NOT_IMPLEMENTED(cmd_id != 0xC008100C);
EXIT_NOT_IMPLEMENTED(cmd_id != 0xC008100C && cmd_id != 0xc0042700);
uint32_t index_count = buffer[0];
auto* index_addr = reinterpret_cast<void*>(buffer[1] | (static_cast<uint64_t>(buffer[2]) << 32u));
uint32_t flags = buffer[3];
uint32_t type = buffer[4];
if (cmd_id == 0xC008100C)
{
uint32_t index_count = buffer[0];
auto* index_addr = reinterpret_cast<void*>(buffer[1] | (static_cast<uint64_t>(buffer[2]) << 32u));
uint32_t flags = buffer[3];
uint32_t type = buffer[4];
cp->DrawIndex(index_count, index_addr, flags, type);
cp->DrawIndex(index_count, index_addr, flags, type);
return 9;
return 9;
}
if (cmd_id == 0xc0042700)
{
uint32_t index_count = buffer[0];
auto* index_addr = reinterpret_cast<void*>(buffer[1] | (static_cast<uint64_t>(buffer[2]) << 32u));
EXIT_NOT_IMPLEMENTED(buffer[3] != index_count);
EXIT_NOT_IMPLEMENTED(buffer[4] != 0);
cp->DrawIndex(index_count, index_addr, 0, 1);
EXIT_NOT_IMPLEMENTED(!(dw >= 7));
if (buffer[5] == 0xc0001000)
{
EXIT_NOT_IMPLEMENTED(buffer[6] != 0);
return 7;
}
if (buffer[5] == 0xc0021000)
{
EXIT_NOT_IMPLEMENTED(buffer[6] != 0);
return 9;
}
EXIT("invalid draw_index\n");
}
return 1;
}
KYTY_CP_OP_PARSER(cp_op_indirect_buffer)
@@ -2879,7 +2957,9 @@ static void graphics_init_jmp_tables()
}
g_cp_op_func[Pm4::IT_NOP] = cp_op_nop;
g_cp_op_func[Pm4::IT_DRAW_INDEX_2] = cp_op_draw_index;
g_cp_op_func[Pm4::IT_INDEX_TYPE] = cp_op_index_type;
g_cp_op_func[Pm4::IT_NUM_INSTANCES] = cp_op_num_instances;
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;
@@ -7,7 +7,7 @@
#include "Emulator/Graphics/Utils.h"
#include "Emulator/Profiler.h"
#include <vulkan/vulkan_core.h>
// IWYU pragma: no_forward_declare VkImageView_T
#ifdef KYTY_EMU_ENABLED
@@ -43,9 +43,13 @@ static void* create_func(GraphicContext* ctx, const uint64_t* params, const uint
vk_obj->extent.height = height;
vk_obj->format = pixel_format;
vk_obj->image = nullptr;
vk_obj->image_view = nullptr;
vk_obj->layout = VK_IMAGE_LAYOUT_UNDEFINED;
for (auto& view: vk_obj->image_view)
{
view = nullptr;
}
vk_obj->compressed = htile;
VkImageCreateInfo image_info {};
@@ -103,7 +107,7 @@ static void* create_func(GraphicContext* ctx, const uint64_t* params, const uint
create_info.subresourceRange.layerCount = 1;
create_info.subresourceRange.levelCount = 1;
vkCreateImageView(ctx->device, &create_info, nullptr, &vk_obj->image_view);
vkCreateImageView(ctx->device, &create_info, nullptr, &vk_obj->image_view[VulkanImage::VIEW_DEFAULT]);
VkImageViewCreateInfo create_info2 {};
create_info2.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
@@ -122,10 +126,10 @@ static void* create_func(GraphicContext* ctx, const uint64_t* params, const uint
create_info2.subresourceRange.layerCount = 1;
create_info2.subresourceRange.levelCount = 1;
vkCreateImageView(ctx->device, &create_info2, nullptr, &vk_obj->texture_view);
vkCreateImageView(ctx->device, &create_info2, nullptr, &vk_obj->image_view[VulkanImage::VIEW_DEPTH_TEXTURE]);
EXIT_NOT_IMPLEMENTED(vk_obj->image_view == nullptr);
EXIT_NOT_IMPLEMENTED(vk_obj->texture_view == nullptr);
EXIT_NOT_IMPLEMENTED(vk_obj->image_view[VulkanImage::VIEW_DEFAULT] == nullptr);
EXIT_NOT_IMPLEMENTED(vk_obj->image_view[VulkanImage::VIEW_DEPTH_TEXTURE] == nullptr);
UtilSetDepthLayoutOptimal(vk_obj);
@@ -143,8 +147,8 @@ 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);
vkDestroyImageView(ctx->device, vk_obj->image_view[VulkanImage::VIEW_DEPTH_TEXTURE], nullptr);
vkDestroyImageView(ctx->device, vk_obj->image_view[VulkanImage::VIEW_DEFAULT], nullptr);
vkDestroyImage(ctx->device, vk_obj->image, nullptr);
File diff suppressed because it is too large Load Diff
@@ -1,17 +1,73 @@
#include "Emulator/Graphics/Objects/IndexBuffer.h"
#include "Kyty/Core/DbgAssert.h"
#include "Kyty/Core/Threads.h"
#include "Kyty/Core/Vector.h"
#include "Emulator/Graphics/GraphicContext.h"
#include "Emulator/Graphics/Utils.h"
#include "Emulator/Profiler.h"
#include <vulkan/vulkan_core.h>
#ifdef KYTY_EMU_ENABLED
namespace Kyty::Libs::Graphics {
class IndexBufferManager
{
public:
IndexBufferManager() { EXIT_NOT_IMPLEMENTED(!Core::Thread::IsMainThread()); }
virtual ~IndexBufferManager() { KYTY_NOT_IMPLEMENTED; }
KYTY_CLASS_NO_COPY(IndexBufferManager);
void RegisterForDelete(VulkanBuffer* buf)
{
Core::Mutex m_mutex;
m_buffers.Add(buf);
}
void DeleteAll(GraphicContext* ctx)
{
KYTY_PROFILER_BLOCK("IndexBufferManager::DeleteAll");
Core::Mutex m_mutex;
for (auto* vk_obj: m_buffers)
{
EXIT_IF(vk_obj == nullptr);
EXIT_IF(vk_obj->buffer == nullptr);
EXIT_IF(ctx == nullptr);
VulkanDeleteBuffer(ctx, vk_obj);
delete vk_obj;
}
m_buffers.Clear();
}
private:
Core::Mutex m_mutex;
Vector<VulkanBuffer*> m_buffers;
};
static IndexBufferManager* g_index_buffer_manager = nullptr;
void IndexBufferInit()
{
EXIT_IF(g_index_buffer_manager != nullptr);
g_index_buffer_manager = new IndexBufferManager;
}
void IndexBufferDeleteAll(GraphicContext* ctx)
{
EXIT_IF(g_index_buffer_manager == nullptr);
g_index_buffer_manager->DeleteAll(ctx);
}
static void* create_func(GraphicContext* ctx, const uint64_t* /*params*/, const uint64_t* vaddr, const uint64_t* size, int vaddr_num,
VulkanMemory* mem)
{
@@ -60,19 +116,15 @@ static void update_func(GraphicContext* /*ctx*/, const uint64_t* /*params*/, voi
KYTY_NOT_IMPLEMENTED;
}
static void delete_func(GraphicContext* ctx, void* obj, VulkanMemory* /*mem*/)
static void delete_func(GraphicContext* /*ctx*/, void* obj, VulkanMemory* /*mem*/)
{
KYTY_PROFILER_BLOCK("IndexBufferGpuObject::delete_func");
EXIT_IF(g_index_buffer_manager == nullptr);
auto* vk_obj = reinterpret_cast<VulkanBuffer*>(obj);
EXIT_IF(vk_obj == nullptr);
EXIT_IF(vk_obj->buffer == nullptr);
EXIT_IF(ctx == nullptr);
VulkanDeleteBuffer(ctx, vk_obj);
delete vk_obj;
g_index_buffer_manager->RegisterForDelete(vk_obj);
}
bool IndexBufferGpuObject::Equal(const uint64_t* /*other*/) const
+30 -26
View File
@@ -6,14 +6,15 @@
#include "Emulator/Graphics/GraphicContext.h"
#include "Emulator/Graphics/GraphicsRender.h"
#include "Emulator/Graphics/GraphicsRun.h"
#include "Emulator/Profiler.h"
#include <vulkan/vulkan_core.h>
#ifdef KYTY_EMU_ENABLED
namespace Kyty::Libs::Graphics {
class CommandProcessor;
enum LabelStatus
{
New,
@@ -24,22 +25,22 @@ enum LabelStatus
struct LabelCallbacks
{
uint64_t* dst_gpu_addr64 = nullptr;
uint64_t value64 = 0;
uint32_t* dst_gpu_addr32 = nullptr;
uint32_t value32 = 0;
LabelGpuObject::callback_t callback_1 = nullptr;
LabelGpuObject::callback_t callback_2 = nullptr;
uint64_t args[4] = {};
uint64_t* dst_gpu_addr64 = nullptr;
uint64_t value64 = 0;
uint32_t* dst_gpu_addr32 = nullptr;
uint32_t value32 = 0;
LabelGpuObject::callback_t callback_1 = nullptr;
LabelGpuObject::callback_t callback_2 = nullptr;
uint64_t args[LABEL_ARGS_MAX] = {};
};
struct Label
{
VkDevice device = nullptr;
VkEvent event = nullptr;
LabelStatus status = LabelStatus::New;
LabelCallbacks callbacks;
CommandBuffer* buffer = nullptr;
VkDevice device = nullptr;
VkEvent event = nullptr;
LabelStatus status = LabelStatus::New;
LabelCallbacks callbacks;
CommandProcessor* cp = nullptr;
};
class LabelManager
@@ -179,11 +180,12 @@ Label* LabelManager::Create64(GraphicContext* ctx, uint64_t* dst_gpu_addr, uint6
label->device = ctx->device;
label->callbacks.callback_1 = callback_1;
label->callbacks.callback_2 = callback_2;
label->callbacks.args[0] = args[0];
label->callbacks.args[1] = args[1];
label->callbacks.args[2] = args[2];
label->callbacks.args[3] = args[3];
label->buffer = nullptr;
label->cp = nullptr;
for (int i = 0; i < LABEL_ARGS_MAX; i++)
{
label->callbacks.args[i] = args[i];
}
VkEventCreateInfo create_info {};
create_info.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO;
@@ -218,10 +220,12 @@ Label* LabelManager::Create32(GraphicContext* ctx, uint32_t* dst_gpu_addr, uint3
label->device = ctx->device;
label->callbacks.callback_1 = callback_1;
label->callbacks.callback_2 = callback_2;
label->callbacks.args[0] = args[0];
label->callbacks.args[1] = args[1];
label->callbacks.args[2] = args[2];
label->callbacks.args[3] = args[3];
label->cp = nullptr;
for (int i = 0; i < LABEL_ARGS_MAX; i++)
{
label->callbacks.args[i] = args[i];
}
VkEventCreateInfo create_info {};
create_info.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO;
@@ -268,10 +272,10 @@ void LabelManager::Destroy(Label* label)
EXIT_IF(label == nullptr);
EXIT_IF(label->event == nullptr);
EXIT_IF(label->device == nullptr);
EXIT_IF(label->buffer == nullptr);
EXIT_IF(label->cp == nullptr);
// All submitted commands that refer to event must have completed execution
label->buffer->CommandProcessorWait();
GraphicsRunCommandProcessorWait(label->cp);
vkDestroyEvent(label->device, label->event, nullptr);
@@ -306,7 +310,7 @@ void LabelManager::Set(CommandBuffer* buffer, Label* label)
EXIT_IF(label->event == nullptr);
label->buffer = buffer;
label->cp = buffer->GetParent();
auto* vk_buffer = buffer->GetPool()->buffers[buffer->GetIndex()];
@@ -8,7 +8,7 @@
#include "Emulator/Graphics/Utils.h"
#include "Emulator/Profiler.h"
#include <vulkan/vulkan_core.h>
// IWYU pragma: no_forward_declare VkImageView_T
#ifdef KYTY_EMU_ENABLED
@@ -62,7 +62,8 @@ static void update_func(GraphicContext* ctx, const uint64_t* params, void* obj,
delete[] temp_buf;
} else
{
UtilFillImage(ctx, vk_obj, reinterpret_cast<void*>(*vaddr), *size, pitch);
UtilFillImage(ctx, vk_obj, reinterpret_cast<void*>(*vaddr), *size, pitch,
static_cast<uint64_t>(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL));
}
}
@@ -165,7 +166,9 @@ static void* create_func(GraphicContext* ctx, const uint64_t* params, const uint
switch (pixel_format) // NOLINT
{
case static_cast<uint64_t>(RenderTextureFormat::R8G8B8A8Unorm): vk_format = VK_FORMAT_R8G8B8A8_UNORM; break;
case static_cast<uint64_t>(RenderTextureFormat::R8G8B8A8Srgb): vk_format = VK_FORMAT_R8G8B8A8_SRGB; break;
case static_cast<uint64_t>(RenderTextureFormat::B8G8R8A8Unorm): vk_format = VK_FORMAT_B8G8R8A8_UNORM; break;
case static_cast<uint64_t>(RenderTextureFormat::B8G8R8A8Srgb): vk_format = VK_FORMAT_B8G8R8A8_SRGB; break;
default: EXIT("unknown format: %" PRIu64 "\n", pixel_format);
}
@@ -178,7 +181,11 @@ static void* create_func(GraphicContext* ctx, const uint64_t* params, const uint
vk_obj->extent.height = height;
vk_obj->format = vk_format;
vk_obj->image = nullptr;
vk_obj->image_view = nullptr;
for (auto& view: vk_obj->image_view)
{
view = nullptr;
}
VkImageCreateInfo image_info {};
image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
@@ -243,9 +250,29 @@ static void* create_func(GraphicContext* ctx, const uint64_t* params, const uint
create_info.subresourceRange.layerCount = 1;
create_info.subresourceRange.levelCount = 1;
vkCreateImageView(ctx->device, &create_info, nullptr, &vk_obj->image_view);
vkCreateImageView(ctx->device, &create_info, nullptr, &vk_obj->image_view[VulkanImage::VIEW_DEFAULT]);
EXIT_NOT_IMPLEMENTED(vk_obj->image_view == nullptr);
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_B;
create_info2.components.g = VK_COMPONENT_SWIZZLE_G;
create_info2.components.b = VK_COMPONENT_SWIZZLE_R;
create_info2.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
create_info2.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_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->image_view[VulkanImage::VIEW_BGRA]);
EXIT_NOT_IMPLEMENTED(vk_obj->image_view[VulkanImage::VIEW_DEFAULT] == nullptr);
EXIT_NOT_IMPLEMENTED(vk_obj->image_view[VulkanImage::VIEW_BGRA] == nullptr);
return vk_obj;
}
@@ -268,7 +295,9 @@ static void* create2_func(GraphicContext* ctx, CommandBuffer* buffer, const uint
switch (pixel_format) // NOLINT
{
case static_cast<uint64_t>(RenderTextureFormat::R8G8B8A8Unorm): vk_format = VK_FORMAT_R8G8B8A8_UNORM; break;
case static_cast<uint64_t>(RenderTextureFormat::R8G8B8A8Srgb): vk_format = VK_FORMAT_R8G8B8A8_SRGB; break;
case static_cast<uint64_t>(RenderTextureFormat::B8G8R8A8Unorm): vk_format = VK_FORMAT_B8G8R8A8_UNORM; break;
case static_cast<uint64_t>(RenderTextureFormat::B8G8R8A8Srgb): vk_format = VK_FORMAT_B8G8R8A8_SRGB; break;
default: EXIT("unknown format: %" PRIu64 "\n", pixel_format);
}
@@ -281,7 +310,11 @@ static void* create2_func(GraphicContext* ctx, CommandBuffer* buffer, const uint
vk_obj->extent.height = height;
vk_obj->format = vk_format;
vk_obj->image = nullptr;
vk_obj->image_view = nullptr;
for (auto& view: vk_obj->image_view)
{
view = nullptr;
}
VkImageCreateInfo image_info {};
image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
@@ -346,9 +379,29 @@ static void* create2_func(GraphicContext* ctx, CommandBuffer* buffer, const uint
create_info.subresourceRange.layerCount = 1;
create_info.subresourceRange.levelCount = 1;
vkCreateImageView(ctx->device, &create_info, nullptr, &vk_obj->image_view);
vkCreateImageView(ctx->device, &create_info, nullptr, &vk_obj->image_view[VulkanImage::VIEW_DEFAULT]);
EXIT_NOT_IMPLEMENTED(vk_obj->image_view == nullptr);
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_B;
create_info2.components.g = VK_COMPONENT_SWIZZLE_G;
create_info2.components.b = VK_COMPONENT_SWIZZLE_R;
create_info2.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
create_info2.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_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->image_view[VulkanImage::VIEW_BGRA]);
EXIT_NOT_IMPLEMENTED(vk_obj->image_view[VulkanImage::VIEW_DEFAULT] == nullptr);
EXIT_NOT_IMPLEMENTED(vk_obj->image_view[VulkanImage::VIEW_BGRA] == nullptr);
return vk_obj;
}
@@ -366,7 +419,7 @@ static void delete_func(GraphicContext* ctx, void* obj, VulkanMemory* mem)
DeleteFramebuffer(vk_obj);
vkDestroyImageView(ctx->device, vk_obj->image_view, nullptr);
vkDestroyImageView(ctx->device, vk_obj->image_view[VulkanImage::VIEW_DEFAULT], nullptr);
vkDestroyImage(ctx->device, vk_obj->image, nullptr);
@@ -375,11 +428,35 @@ static void delete_func(GraphicContext* ctx, void* obj, VulkanMemory* mem)
delete vk_obj;
}
static void write_back(GraphicContext* ctx, const uint64_t* params, void* obj, const uint64_t* vaddr, const uint64_t* size, int vaddr_num)
{
KYTY_PROFILER_BLOCK("RenderTextureObject::write_back");
EXIT_IF(ctx == nullptr);
EXIT_IF(obj == nullptr);
EXIT_IF(vaddr == nullptr || size == nullptr || vaddr_num != 1);
bool tiled = (params[RenderTextureObject::PARAM_TILED] != 0);
auto pitch = params[RenderTextureObject::PARAM_PITCH];
auto width = params[RenderTextureObject::PARAM_WIDTH];
EXIT_IF(!(params[RenderTextureObject::PARAM_WRITE_BACK] != 0));
EXIT_NOT_IMPLEMENTED(tiled);
EXIT_NOT_IMPLEMENTED(width != pitch);
auto* vk_obj = reinterpret_cast<RenderTextureVulkanImage*>(obj);
UtilFillBuffer(ctx, reinterpret_cast<void*>(*vaddr), *size, pitch, vk_obj,
static_cast<uint64_t>(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL));
}
bool RenderTextureObject::Equal(const uint64_t* other) const
{
return (params[PARAM_FORMAT] == other[PARAM_FORMAT] && params[PARAM_WIDTH] == other[PARAM_WIDTH] &&
params[PARAM_HEIGHT] == other[PARAM_HEIGHT] && params[PARAM_TILED] == other[PARAM_TILED] &&
params[PARAM_PITCH] == other[PARAM_PITCH] && params[PARAM_PITCH] == other[PARAM_PITCH]);
params[PARAM_PITCH] == other[PARAM_PITCH] && params[PARAM_PITCH] == other[PARAM_PITCH] &&
params[PARAM_WRITE_BACK] == other[PARAM_WRITE_BACK]);
}
GpuObject::create_func_t RenderTextureObject::GetCreateFunc() const
@@ -402,6 +479,12 @@ GpuObject::update_func_t RenderTextureObject::GetUpdateFunc() const
return update_func;
}
GpuObject::write_back_func_t RenderTextureObject::GetWriteBackFunc() const
{
bool wb = (params[RenderTextureObject::PARAM_WRITE_BACK] != 0);
return (wb ? write_back : nullptr);
}
} // namespace Kyty::Libs::Graphics
#endif // KYTY_EMU_ENABLED
@@ -4,11 +4,10 @@
#include "Emulator/Graphics/GraphicContext.h"
#include "Emulator/Graphics/GraphicsRender.h"
#include "Emulator/Graphics/GraphicsRun.h"
#include "Emulator/Graphics/Utils.h"
#include "Emulator/Profiler.h"
#include "vulkan/vulkan_core.h"
#ifdef KYTY_EMU_ENABLED
namespace Kyty::Libs::Graphics {
@@ -67,17 +66,18 @@ static void delete_func(GraphicContext* ctx, void* obj, VulkanMemory* /*mem*/)
EXIT_IF(vk_obj->buffer == nullptr);
EXIT_IF(ctx == nullptr);
EXIT_IF(vk_obj->cmd_buffer == nullptr);
EXIT_IF(vk_obj->cp == nullptr);
// All submitted commands that refer to any element of pDescriptorSets must have completed execution
vk_obj->cmd_buffer->CommandProcessorWait();
GraphicsRunCommandProcessorWait(vk_obj->cp);
VulkanDeleteBuffer(ctx, vk_obj);
delete vk_obj;
}
static void write_back(GraphicContext* ctx, void* obj, const uint64_t* vaddr, const uint64_t* size, int vaddr_num)
static void write_back(GraphicContext* ctx, const uint64_t* /*params*/, void* obj, const uint64_t* vaddr, const uint64_t* size,
int vaddr_num)
{
KYTY_PROFILER_BLOCK("StorageBufferGpuObject::write_back");
@@ -131,9 +131,7 @@ GpuObject::update_func_t StorageBufferGpuObject::GetUpdateFunc() const
void StorageBufferSet(CommandBuffer* cmd_buffer, StorageVulkanBuffer* buffer)
{
// EXIT_IF(buffer->cmd_buffer != nullptr);
buffer->cmd_buffer = cmd_buffer;
buffer->cp = cmd_buffer->GetParent();
}
} // namespace Kyty::Libs::Graphics
@@ -6,11 +6,12 @@
#include "Emulator/Config.h"
#include "Emulator/Graphics/GraphicContext.h"
#include "Emulator/Graphics/GraphicsRender.h"
#include "Emulator/Graphics/Shader.h"
#include "Emulator/Graphics/Tile.h"
#include "Emulator/Graphics/Utils.h"
#include "Emulator/Profiler.h"
#include <vulkan/vulkan_core.h>
// IWYU pragma: no_forward_declare VkImageView_T
#ifdef KYTY_EMU_ENABLED
@@ -188,9 +189,10 @@ static void update_func(GraphicContext* ctx, const uint64_t* params, void* obj,
if (tile == 13)
{
EXIT_NOT_IMPLEMENTED(pitch != width);
// EXIT_NOT_IMPLEMENTED(pitch != width);
auto* temp_buf = new uint8_t[*size];
TileConvertTiledToLinear(temp_buf, reinterpret_cast<void*>(*vaddr), TileMode::TextureTiled, dfmt, nfmt, width, height, levels, neo);
TileConvertTiledToLinear(temp_buf, reinterpret_cast<void*>(*vaddr), TileMode::TextureTiled, dfmt, nfmt, width, height, pitch,
levels, neo);
UtilFillImage(ctx, vk_obj, temp_buf, *size, regions, static_cast<uint64_t>(vk_layout));
delete[] temp_buf;
} else if (tile == 8)
@@ -223,10 +225,10 @@ static void* create_func(GraphicContext* ctx, const uint64_t* params, const uint
VkComponentMapping components {};
components.r = get_swizzle(swizzle & 0xffu);
components.g = get_swizzle((swizzle >> 8u) & 0xffu);
components.b = get_swizzle((swizzle >> 16u) & 0xffu);
components.a = get_swizzle((swizzle >> 24u) & 0xffu);
components.r = get_swizzle(GetDstSel(swizzle, 0));
components.g = get_swizzle(GetDstSel(swizzle, 1));
components.b = get_swizzle(GetDstSel(swizzle, 2));
components.a = get_swizzle(GetDstSel(swizzle, 3));
auto pixel_format = get_texture_format(dfmt, nfmt);
@@ -269,9 +271,13 @@ static void* create_func(GraphicContext* ctx, const uint64_t* params, const uint
vk_obj->extent.height = height;
vk_obj->format = image_info.format;
vk_obj->image = nullptr;
vk_obj->image_view = nullptr;
vk_obj->layout = image_info.initialLayout;
for (auto& view: vk_obj->image_view)
{
view = nullptr;
}
vkCreateImage(ctx->device, &image_info, nullptr, &vk_obj->image);
EXIT_NOT_IMPLEMENTED(vk_obj->image == nullptr);
@@ -304,9 +310,9 @@ static void* create_func(GraphicContext* ctx, const uint64_t* params, const uint
create_info.subresourceRange.layerCount = 1;
create_info.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
vkCreateImageView(ctx->device, &create_info, nullptr, &vk_obj->image_view);
vkCreateImageView(ctx->device, &create_info, nullptr, &vk_obj->image_view[VulkanImage::VIEW_DEFAULT]);
EXIT_NOT_IMPLEMENTED(vk_obj->image_view == nullptr);
EXIT_NOT_IMPLEMENTED(vk_obj->image_view[VulkanImage::VIEW_DEFAULT] == nullptr);
return vk_obj;
}
@@ -322,7 +328,7 @@ static void delete_func(GraphicContext* ctx, void* obj, VulkanMemory* mem)
DeleteDescriptor(vk_obj);
vkDestroyImageView(ctx->device, vk_obj->image_view, nullptr);
vkDestroyImageView(ctx->device, vk_obj->image_view[VulkanImage::VIEW_DEFAULT], nullptr);
vkDestroyImage(ctx->device, vk_obj->image, nullptr);
@@ -6,11 +6,12 @@
#include "Emulator/Config.h"
#include "Emulator/Graphics/GraphicContext.h"
#include "Emulator/Graphics/GraphicsRender.h"
#include "Emulator/Graphics/Shader.h"
#include "Emulator/Graphics/Tile.h"
#include "Emulator/Graphics/Utils.h"
#include "Emulator/Profiler.h"
#include <vulkan/vulkan_core.h>
// IWYU pragma: no_forward_declare VkImageView_T
#ifdef KYTY_EMU_ENABLED
@@ -30,10 +31,26 @@ static VkFormat get_texture_format(uint32_t dfmt, uint32_t nfmt)
{
return VK_FORMAT_R8_UNORM;
}
if (nfmt == 0 && dfmt == 3)
{
return VK_FORMAT_R8G8_UNORM;
}
if (nfmt == 9 && dfmt == 37)
{
return VK_FORMAT_BC3_SRGB_BLOCK;
}
if (nfmt == 0 && dfmt == 37)
{
return VK_FORMAT_BC3_UNORM_BLOCK;
}
if (nfmt == 0 && dfmt == 36)
{
return VK_FORMAT_BC2_UNORM_BLOCK;
}
if (nfmt == 0 && dfmt == 35)
{
return VK_FORMAT_BC1_RGBA_UNORM_BLOCK;
}
EXIT("unknown format: nfmt = %u, dfmt = %u\n", nfmt, dfmt);
return VK_FORMAT_UNDEFINED;
}
@@ -189,9 +206,10 @@ static void update_func(GraphicContext* ctx, const uint64_t* params, void* obj,
if (tile == 13)
{
EXIT_NOT_IMPLEMENTED(pitch != width);
// EXIT_NOT_IMPLEMENTED(pitch != width);
auto* temp_buf = new uint8_t[*size];
TileConvertTiledToLinear(temp_buf, reinterpret_cast<void*>(*vaddr), TileMode::TextureTiled, dfmt, nfmt, width, height, levels, neo);
TileConvertTiledToLinear(temp_buf, reinterpret_cast<void*>(*vaddr), TileMode::TextureTiled, dfmt, nfmt, width, height, pitch,
levels, neo);
UtilFillImage(ctx, vk_obj, temp_buf, *size, regions, static_cast<uint64_t>(vk_layout));
delete[] temp_buf;
} else if (tile == 8)
@@ -389,10 +407,10 @@ static void* create_func(GraphicContext* ctx, const uint64_t* params, const uint
VkComponentMapping components {};
components.r = get_swizzle(swizzle & 0xffu);
components.g = get_swizzle((swizzle >> 8u) & 0xffu);
components.b = get_swizzle((swizzle >> 16u) & 0xffu);
components.a = get_swizzle((swizzle >> 24u) & 0xffu);
components.r = get_swizzle(GetDstSel(swizzle, 0));
components.g = get_swizzle(GetDstSel(swizzle, 1));
components.b = get_swizzle(GetDstSel(swizzle, 2));
components.a = get_swizzle(GetDstSel(swizzle, 3));
auto pixel_format = get_texture_format(dfmt, nfmt);
@@ -433,9 +451,13 @@ static void* create_func(GraphicContext* ctx, const uint64_t* params, const uint
vk_obj->extent.height = height;
vk_obj->format = image_info.format;
vk_obj->image = nullptr;
vk_obj->image_view = nullptr;
vk_obj->layout = image_info.initialLayout;
for (auto& view: vk_obj->image_view)
{
view = nullptr;
}
vkCreateImage(ctx->device, &image_info, nullptr, &vk_obj->image);
EXIT_NOT_IMPLEMENTED(vk_obj->image == nullptr);
@@ -468,9 +490,9 @@ static void* create_func(GraphicContext* ctx, const uint64_t* params, const uint
create_info.subresourceRange.layerCount = 1;
create_info.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
vkCreateImageView(ctx->device, &create_info, nullptr, &vk_obj->image_view);
vkCreateImageView(ctx->device, &create_info, nullptr, &vk_obj->image_view[VulkanImage::VIEW_DEFAULT]);
EXIT_NOT_IMPLEMENTED(vk_obj->image_view == nullptr);
EXIT_NOT_IMPLEMENTED(vk_obj->image_view[VulkanImage::VIEW_DEFAULT] == nullptr);
return vk_obj;
}
@@ -497,10 +519,10 @@ static void* create2_func(GraphicContext* ctx, CommandBuffer* buffer, const uint
VkComponentMapping components {};
components.r = get_swizzle(swizzle & 0xffu);
components.g = get_swizzle((swizzle >> 8u) & 0xffu);
components.b = get_swizzle((swizzle >> 16u) & 0xffu);
components.a = get_swizzle((swizzle >> 24u) & 0xffu);
components.r = get_swizzle(GetDstSel(swizzle, 0));
components.g = get_swizzle(GetDstSel(swizzle, 1));
components.b = get_swizzle(GetDstSel(swizzle, 2));
components.a = get_swizzle(GetDstSel(swizzle, 3));
auto pixel_format = get_texture_format(dfmt, nfmt);
@@ -541,9 +563,13 @@ static void* create2_func(GraphicContext* ctx, CommandBuffer* buffer, const uint
vk_obj->extent.height = height;
vk_obj->format = image_info.format;
vk_obj->image = nullptr;
vk_obj->image_view = nullptr;
vk_obj->layout = image_info.initialLayout;
for (auto& view: vk_obj->image_view)
{
view = nullptr;
}
vkCreateImage(ctx->device, &image_info, nullptr, &vk_obj->image);
EXIT_NOT_IMPLEMENTED(vk_obj->image == nullptr);
@@ -576,9 +602,9 @@ static void* create2_func(GraphicContext* ctx, CommandBuffer* buffer, const uint
create_info.subresourceRange.layerCount = 1;
create_info.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
vkCreateImageView(ctx->device, &create_info, nullptr, &vk_obj->image_view);
vkCreateImageView(ctx->device, &create_info, nullptr, &vk_obj->image_view[VulkanImage::VIEW_DEFAULT]);
EXIT_NOT_IMPLEMENTED(vk_obj->image_view == nullptr);
EXIT_NOT_IMPLEMENTED(vk_obj->image_view[VulkanImage::VIEW_DEFAULT] == nullptr);
return vk_obj;
}
@@ -594,7 +620,7 @@ static void delete_func(GraphicContext* ctx, void* obj, VulkanMemory* mem)
DeleteDescriptor(vk_obj);
vkDestroyImageView(ctx->device, vk_obj->image_view, nullptr);
vkDestroyImageView(ctx->device, vk_obj->image_view[VulkanImage::VIEW_DEFAULT], nullptr);
vkDestroyImage(ctx->device, vk_obj->image, nullptr);
@@ -6,8 +6,6 @@
#include "Emulator/Graphics/Utils.h"
#include "Emulator/Profiler.h"
#include <vulkan/vulkan_core.h>
#ifdef KYTY_EMU_ENABLED
namespace Kyty::Libs::Graphics {
@@ -8,7 +8,7 @@
#include "Emulator/Graphics/Utils.h"
#include "Emulator/Profiler.h"
#include <vulkan/vulkan_core.h>
// IWYU pragma: no_forward_declare VkImageView_T
#ifdef KYTY_EMU_ENABLED
@@ -56,11 +56,12 @@ static void update_func(GraphicContext* ctx, const uint64_t* params, void* obj,
EXIT_NOT_IMPLEMENTED(width != pitch);
auto* temp_buf = new uint8_t[*size];
TileConvertTiledToLinear(temp_buf, reinterpret_cast<void*>(*vaddr), TileMode::VideoOutTiled, width, height, neo);
UtilFillImage(ctx, vk_obj, temp_buf, *size, pitch);
UtilFillImage(ctx, vk_obj, temp_buf, *size, pitch, static_cast<uint64_t>(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
delete[] temp_buf;
} else
{
UtilFillImage(ctx, vk_obj, reinterpret_cast<void*>(*vaddr), *size, pitch);
UtilFillImage(ctx, vk_obj, reinterpret_cast<void*>(*vaddr), *size, pitch,
static_cast<uint64_t>(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
}
}
@@ -87,9 +88,13 @@ static void* create_func(GraphicContext* ctx, const uint64_t* params, const uint
vk_obj->extent.height = height;
vk_obj->format = VK_FORMAT_B8G8R8A8_SRGB;
vk_obj->image = nullptr;
vk_obj->image_view = nullptr;
vk_obj->layout = VK_IMAGE_LAYOUT_UNDEFINED;
for (auto& view: vk_obj->image_view)
{
view = nullptr;
}
VkImageCreateInfo image_info {};
image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
image_info.pNext = nullptr;
@@ -151,9 +156,9 @@ static void* create_func(GraphicContext* ctx, const uint64_t* params, const uint
create_info.subresourceRange.layerCount = 1;
create_info.subresourceRange.levelCount = 1;
vkCreateImageView(ctx->device, &create_info, nullptr, &vk_obj->image_view);
vkCreateImageView(ctx->device, &create_info, nullptr, &vk_obj->image_view[VulkanImage::VIEW_DEFAULT]);
EXIT_NOT_IMPLEMENTED(vk_obj->image_view == nullptr);
EXIT_NOT_IMPLEMENTED(vk_obj->image_view[VulkanImage::VIEW_DEFAULT] == nullptr);
return vk_obj;
}
@@ -172,7 +177,7 @@ static void delete_func(GraphicContext* ctx, void* obj, VulkanMemory* mem)
DeleteFramebuffer(vk_obj);
}
vkDestroyImageView(ctx->device, vk_obj->image_view, nullptr);
vkDestroyImageView(ctx->device, vk_obj->image_view[VulkanImage::VIEW_DEFAULT], nullptr);
vkDestroyImage(ctx->device, vk_obj->image, nullptr);
+214 -48
View File
@@ -18,6 +18,7 @@
#include "spirv-tools/optimizer.hpp"
#include <algorithm>
#include <atomic>
#include <string>
#include <vector>
@@ -91,17 +92,17 @@ static String operand_to_str(ShaderOperand op)
{
case ShaderOperandType::LiteralConstant:
EXIT_IF(op.size != 0);
EXIT_IF(op.negate);
EXIT_IF(op.negate || op.absolute);
return String::FromPrintf("%f (%u)", op.constant.f, op.constant.u);
break;
case ShaderOperandType::IntegerInlineConstant:
EXIT_IF(op.size != 0);
EXIT_IF(op.negate);
EXIT_IF(op.negate || op.absolute);
return String::FromPrintf("%d", op.constant.i);
break;
case ShaderOperandType::FloatInlineConstant:
EXIT_IF(op.size != 0);
EXIT_IF(op.negate);
EXIT_IF(op.negate || op.absolute);
return String::FromPrintf("%f", op.constant.f);
break;
default: break;
@@ -123,6 +124,11 @@ static String operand_to_str(ShaderOperand op)
default: break;
}
if (op.absolute)
{
ret = U"abs(" + ret + U")";
}
if (op.negate)
{
return U"-" + ret;
@@ -170,6 +176,11 @@ static String operand_array_to_str(ShaderOperand op, int n)
EXIT_IF(ret == U"???");
if (op.absolute)
{
ret = U"abs(" + ret + U")";
}
if (op.negate)
{
return U"-" + ret;
@@ -192,6 +203,7 @@ static String dbg_fmt_to_str(const ShaderInstruction& inst)
case ShaderInstructionFormat::Param1Vsrc0Vsrc1Vsrc2Vsrc3: return U"Param1Vsrc0Vsrc1Vsrc2Vsrc3"; break;
case ShaderInstructionFormat::Param2Vsrc0Vsrc1Vsrc2Vsrc3: return U"Param2Vsrc0Vsrc1Vsrc2Vsrc3"; break;
case ShaderInstructionFormat::Param3Vsrc0Vsrc1Vsrc2Vsrc3: return U"Param3Vsrc0Vsrc1Vsrc2Vsrc3"; break;
case ShaderInstructionFormat::Param4Vsrc0Vsrc1Vsrc2Vsrc3: return U"Param4Vsrc0Vsrc1Vsrc2Vsrc3"; break;
case ShaderInstructionFormat::Pos0Vsrc0Vsrc1Vsrc2Vsrc3Done: return U"Pos0Vsrc0Vsrc1Vsrc2Vsrc3Done"; break;
case ShaderInstructionFormat::Saddr: return U"Saddr"; break;
case ShaderInstructionFormat::Sdst4SbaseSoffset: return U"Sdst4SbaseSoffset"; break;
@@ -207,13 +219,18 @@ static String dbg_fmt_to_str(const ShaderInstruction& inst)
case ShaderInstructionFormat::SmaskVsrc0Vsrc1: return U"SmaskVsrc0Vsrc1"; break;
case ShaderInstructionFormat::Ssrc0Ssrc1: return U"Ssrc0Ssrc1"; break;
case ShaderInstructionFormat::Vdata1VaddrSvSoffsIdxen: return U"Vdata1VaddrSvSoffsIdxen"; break;
case ShaderInstructionFormat::Vdata1VaddrSvSoffsIdxenFloat1: return U"Vdata1VaddrSvSoffsIdxenFloat1"; break;
case ShaderInstructionFormat::Vdata2VaddrSvSoffsIdxen: return U"Vdata2VaddrSvSoffsIdxen"; break;
case ShaderInstructionFormat::Vdata3VaddrSvSoffsIdxen: return U"Vdata3VaddrSvSoffsIdxen"; break;
case ShaderInstructionFormat::Vdata4VaddrSvSoffsIdxen: return U"Vdata4VaddrSvSoffsIdxen"; break;
case ShaderInstructionFormat::Vdata4VaddrSvSoffsIdxenFloat4: return U"Vdata4VaddrSvSoffsIdxenFloat4"; break;
case ShaderInstructionFormat::Vdata4Vaddr2SvSoffsOffenIdxenFloat4: return U"Vdata4Vaddr2SvSoffsOffenIdxenFloat4"; break;
case ShaderInstructionFormat::Vdata1Vaddr3StSsDmask1: return U"Vdata1Vaddr3StSsDmask1"; break;
case ShaderInstructionFormat::Vdata1Vaddr3StSsDmask8: return U"Vdata1Vaddr3StSsDmask8"; break;
case ShaderInstructionFormat::Vdata2Vaddr3StSsDmask3: return U"Vdata2Vaddr3StSsDmask3"; break;
case ShaderInstructionFormat::Vdata2Vaddr3StSsDmask5: return U"Vdata2Vaddr3StSsDmask5"; break;
case ShaderInstructionFormat::Vdata3Vaddr3StSsDmask7: return U"Vdata3Vaddr3StSsDmask7"; break;
case ShaderInstructionFormat::Vdata3Vaddr4StSsDmask7: return U"Vdata3Vaddr4StSsDmask7"; break;
case ShaderInstructionFormat::Vdata4Vaddr3StSsDmaskF: return U"Vdata4Vaddr3StSsDmaskF"; break;
case ShaderInstructionFormat::Vdata4Vaddr3StDmaskF: return U"Vdata4Vaddr3StDmaskF"; break;
case ShaderInstructionFormat::Vdata4Vaddr4StDmaskF: return U"Vdata4Vaddr4StDmaskF"; break;
@@ -275,6 +292,7 @@ static String dbg_fmt_print(const ShaderInstruction& inst)
case ShaderInstructionFormat::Attr: s = String::FromPrintf("attr%u.%u", inst.src[1].constant.u, inst.src[2].constant.u); break;
case ShaderInstructionFormat::Idxen: s = U"idxen"; break;
case ShaderInstructionFormat::Offen: s = U"offen"; break;
case ShaderInstructionFormat::Float1: s = U"format:float1"; break;
case ShaderInstructionFormat::Float4: s = U"format:float4"; break;
case ShaderInstructionFormat::Pos0: s = U"pos0"; break;
case ShaderInstructionFormat::Done: s = U"done"; break;
@@ -282,12 +300,16 @@ static String dbg_fmt_print(const ShaderInstruction& inst)
case ShaderInstructionFormat::Param1: s = U"param1"; break;
case ShaderInstructionFormat::Param2: s = U"param2"; break;
case ShaderInstructionFormat::Param3: s = U"param3"; break;
case ShaderInstructionFormat::Param4: s = U"param4"; break;
case ShaderInstructionFormat::Mrt0: s = U"mrt_color0"; break;
case ShaderInstructionFormat::Off: s = U"off"; break;
case ShaderInstructionFormat::Compr: s = U"compr"; break;
case ShaderInstructionFormat::Vm: s = U"vm"; break;
case ShaderInstructionFormat::L: s = String::FromPrintf("label_%04" PRIx32, inst.pc + 4 + inst.src[0].constant.i); break;
case ShaderInstructionFormat::Dmask1: s = U"dmask:0x1"; break;
case ShaderInstructionFormat::Dmask8: s = U"dmask:0x8"; break;
case ShaderInstructionFormat::Dmask3: s = U"dmask:0x3"; break;
case ShaderInstructionFormat::Dmask5: s = U"dmask:0x5"; break;
case ShaderInstructionFormat::Dmask7: s = U"dmask:0x7"; break;
case ShaderInstructionFormat::DmaskF: s = U"dmask:0xf"; break;
case ShaderInstructionFormat::Gds: s = U"gds"; break;
@@ -354,7 +376,7 @@ String ShaderCode::DbgDump() const
String ret;
for (const auto& inst: m_instructions)
{
if (m_labels.Contains(inst.pc, [](auto label, auto pc) { return label.GetDst() == pc; }))
if (m_labels.Contains(inst.pc, [](auto label, auto pc) { return (!label.IsDisabled() && label.GetDst() == pc); }))
{
ret += String::FromPrintf("label_%04" PRIx32 ":\n", inst.pc);
}
@@ -392,7 +414,7 @@ bool ShaderCode::IsDiscardBlock(uint32_t pc) const
const auto& inst = m_instructions.At(i);
if (inst.type == ShaderInstructionType::SEndpgm || inst.type == ShaderInstructionType::SCbranchExecz ||
inst.type == ShaderInstructionType::SCbranchScc0)
inst.type == ShaderInstructionType::SCbranchScc0 || inst.type == ShaderInstructionType::SCbranchVccz)
{
return false;
}
@@ -408,6 +430,35 @@ bool ShaderCode::IsDiscardBlock(uint32_t pc) const
return false;
}
Vector<ShaderInstruction> ShaderCode::GetDiscardBlock(uint32_t pc) const
{
Vector<ShaderInstruction> ret;
auto inst_count = m_instructions.Size();
for (uint32_t index = 0; index < inst_count; index++)
{
const auto& inst = m_instructions.At(index);
if (inst.pc == pc)
{
for (uint32_t i = index; i < inst_count; i++)
{
const auto& inst = m_instructions.At(i);
ret.Add(inst);
if (IsDiscardInstruction(i))
{
ret.Add(m_instructions.At(i + 1));
break;
}
}
break;
}
}
return ret;
}
static ShaderOperand operand_parse(uint32_t code)
{
ShaderOperand ret;
@@ -566,26 +617,21 @@ KYTY_SHADER_PARSER(shader_parse_sopp)
ShaderInstruction inst;
inst.pc = pc;
inst.format = ShaderInstructionFormat::Label;
inst.src[0].type = ShaderOperandType::LiteralConstant;
inst.src[0].constant.i = static_cast<int16_t>(simm) * 4;
inst.src_num = 1;
switch (opcode)
{
case 0x01:
inst.type = ShaderInstructionType::SEndpgm;
inst.format = ShaderInstructionFormat::Empty;
break;
case 0x04:
inst.type = ShaderInstructionType::SCbranchScc0;
inst.format = ShaderInstructionFormat::Label;
inst.src[0].type = ShaderOperandType::LiteralConstant;
inst.src[0].constant.i = static_cast<int16_t>(simm) * 4;
inst.src_num = 1;
break;
case 0x08:
inst.type = ShaderInstructionType::SCbranchExecz;
inst.format = ShaderInstructionFormat::Label;
inst.src[0].type = ShaderOperandType::LiteralConstant;
inst.src[0].constant.i = static_cast<int16_t>(simm) * 4;
inst.src_num = 1;
inst.type = ShaderInstructionType::SEndpgm;
inst.format = ShaderInstructionFormat::Empty;
inst.src_num = 0;
break;
case 0x04: inst.type = ShaderInstructionType::SCbranchScc0; break;
case 0x06: inst.type = ShaderInstructionType::SCbranchVccz; break;
case 0x08: inst.type = ShaderInstructionType::SCbranchExecz; break;
case 0x0c:
inst.type = ShaderInstructionType::SWaitcnt;
inst.format = ShaderInstructionFormat::Imm;
@@ -598,7 +644,8 @@ KYTY_SHADER_PARSER(shader_parse_sopp)
dst->GetInstructions().Add(inst);
if (inst.type == ShaderInstructionType::SCbranchScc0 || inst.type == ShaderInstructionType::SCbranchExecz)
if (inst.type == ShaderInstructionType::SCbranchScc0 || inst.type == ShaderInstructionType::SCbranchVccz ||
inst.type == ShaderInstructionType::SCbranchExecz)
{
dst->GetLabels().Add(ShaderLabel(inst));
}
@@ -849,6 +896,8 @@ KYTY_SHADER_PARSER(shader_parse_vopc)
case 0x0d: inst.type = ShaderInstructionType::VCmpNeqF32; break;
case 0x0e: inst.type = ShaderInstructionType::VCmpNltF32; break;
case 0x0f: inst.type = ShaderInstructionType::VCmpTruF32; break;
case 0x11: inst.type = ShaderInstructionType::VCmpxLtF32; break;
case 0x14: inst.type = ShaderInstructionType::VCmpxGtF32; break;
case 0x1d: inst.type = ShaderInstructionType::VCmpxNeqF32; break;
case 0x80: inst.type = ShaderInstructionType::VCmpFI32; break;
case 0x81: inst.type = ShaderInstructionType::VCmpLtI32; break;
@@ -870,7 +919,9 @@ KYTY_SHADER_PARSER(shader_parse_vopc)
case 0xd4: inst.type = ShaderInstructionType::VCmpxGtU32; break;
case 0xd5: inst.type = ShaderInstructionType::VCmpxNeU32; break;
case 0xd6: inst.type = ShaderInstructionType::VCmpxGeU32; break;
default: printf("%s", dst->DbgDump().C_Str()); EXIT("unknown vopc opcode: 0x%02" PRIx32 " at addr 0x%08" PRIx32 "\n", opcode, pc);
default:
printf("%s", dst->DbgDump().C_Str());
EXIT("unknown vopc opcode: 0x%02" PRIx32 " at addr 0x%08" PRIx32 " (hash0 = 0x%08" PRIx32 ")\n", opcode, pc, dst->GetHash0());
}
dst->GetInstructions().Add(inst);
@@ -921,13 +972,17 @@ KYTY_SHADER_PARSER(shader_parse_vop1)
case 0x23: inst.type = ShaderInstructionType::VRndneF32; break;
case 0x24: inst.type = ShaderInstructionType::VFloorF32; break;
case 0x25: inst.type = ShaderInstructionType::VExpF32; break;
case 0x27: inst.type = ShaderInstructionType::VLogF32; break;
case 0x2a: inst.type = ShaderInstructionType::VRcpF32; break;
case 0x2e: inst.type = ShaderInstructionType::VRsqF32; break;
case 0x33: inst.type = ShaderInstructionType::VSqrtF32; break;
case 0x35: inst.type = ShaderInstructionType::VSinF32; break;
case 0x36: inst.type = ShaderInstructionType::VCosF32; break;
case 0x37: inst.type = ShaderInstructionType::VNotB32; break;
case 0x38: inst.type = ShaderInstructionType::VBfrevB32; break;
default: printf("%s", dst->DbgDump().C_Str()); EXIT("unknown vop1 opcode: 0x%02" PRIx32 " at addr 0x%08" PRIx32 "\n", opcode, pc);
default:
printf("%s", dst->DbgDump().C_Str());
EXIT("unknown vop1 opcode: 0x%02" PRIx32 " at addr 0x%08" PRIx32 " (hash0 = 0x%08" PRIx32 ")\n", opcode, pc, dst->GetHash0());
}
dst->GetInstructions().Add(inst);
@@ -972,6 +1027,7 @@ KYTY_SHADER_PARSER(shader_parse_vop2)
inst.src[2].size = 2;
inst.src_num = 3;
break;
case 0x03: inst.type = ShaderInstructionType::VAddF32; break;
case 0x04: inst.type = ShaderInstructionType::VSubF32; break;
case 0x05: inst.type = ShaderInstructionType::VSubrevF32; break;
case 0x08: inst.type = ShaderInstructionType::VMulF32; break;
@@ -1171,6 +1227,7 @@ KYTY_SHADER_PARSER(shader_parse_vop3)
inst.src_num = 3;
inst.src[2].size = 2;
break;
case 0x103: inst.type = ShaderInstructionType::VAddF32; break;
case 0x104: inst.type = ShaderInstructionType::VSubF32; break;
case 0x105: inst.type = ShaderInstructionType::VSubrevF32; break;
case 0x108: inst.type = ShaderInstructionType::VMulF32; break;
@@ -1213,6 +1270,10 @@ KYTY_SHADER_PARSER(shader_parse_vop3)
case 0x141: inst.type = ShaderInstructionType::VMadF32; break;
case 0x143: inst.type = ShaderInstructionType::VMadU32U24; break;
case 0x148: inst.type = ShaderInstructionType::VBfeU32; break;
case 0x14b: inst.type = ShaderInstructionType::VFmaF32; break;
case 0x151: inst.type = ShaderInstructionType::VMin3F32; break;
case 0x154: inst.type = ShaderInstructionType::VMax3F32; break;
case 0x157: inst.type = ShaderInstructionType::VMed3F32; break;
case 0x15d: inst.type = ShaderInstructionType::VSadU32; break;
case 0x169:
inst.type = ShaderInstructionType::VMulLoU32;
@@ -1229,12 +1290,30 @@ KYTY_SHADER_PARSER(shader_parse_vop3)
inst.format = ShaderInstructionFormat::SVdstSVsrc0SVsrc1;
inst.src_num = 2;
break;
default: printf("%s", dst->DbgDump().C_Str()); EXIT("unknown vop3 opcode: 0x%02" PRIx32 " at addr 0x%08" PRIx32 "\n", opcode, pc);
case 0x1aa:
inst.type = ShaderInstructionType::VRcpF32;
inst.format = ShaderInstructionFormat::SVdstSVsrc0;
inst.src_num = 1;
break;
default:
printf("%s", dst->DbgDump().C_Str());
EXIT("unknown vop3 opcode: 0x%02" PRIx32 " at addr 0x%08" PRIx32 " (hash0 = 0x%08" PRIx32 ")\n", opcode, pc, dst->GetHash0());
}
if (inst.dst2.type == ShaderOperandType::Unknown)
{
EXIT_NOT_IMPLEMENTED(abs != 0);
if ((abs & 0x1u) != 0)
{
inst.src[0].absolute = true;
}
if ((abs & 0x2u) != 0)
{
inst.src[1].absolute = true;
}
if ((abs & 0x4u) != 0)
{
inst.src[2].absolute = true;
}
inst.dst.clamp = (clamp != 0);
}
@@ -1304,6 +1383,7 @@ KYTY_SHADER_PARSER(shader_parse_exp)
case 0x21: inst.format = ShaderInstructionFormat::Param1Vsrc0Vsrc1Vsrc2Vsrc3; break;
case 0x22: inst.format = ShaderInstructionFormat::Param2Vsrc0Vsrc1Vsrc2Vsrc3; break;
case 0x23: inst.format = ShaderInstructionFormat::Param3Vsrc0Vsrc1Vsrc2Vsrc3; break;
case 0x24: inst.format = ShaderInstructionFormat::Param4Vsrc0Vsrc1Vsrc2Vsrc3; break;
default: break;
}
}
@@ -1311,7 +1391,9 @@ KYTY_SHADER_PARSER(shader_parse_exp)
if (inst.format == ShaderInstructionFormat::Unknown)
{
printf("%s", dst->DbgDump().C_Str());
EXIT("unknown exp target: 0x%02" PRIx32 " at addr 0x%08" PRIx32 "\n", target, pc);
EXIT("%s\n"
"unknown exp target: 0x%02" PRIx32 " at addr 0x%08" PRIx32 " (hash0 = 0x%08" PRIx32 ")\n",
dst->DbgDump().C_Str(), target, pc, dst->GetHash0());
}
dst->GetInstructions().Add(inst);
@@ -1639,12 +1721,30 @@ KYTY_SHADER_PARSER(shader_parse_mimg)
inst.dst.size = 1;
break;
}
case 0x3:
{
inst.format = ShaderInstructionFormat::Vdata2Vaddr3StSsDmask3;
inst.dst.size = 2;
break;
}
case 0x5:
{
inst.format = ShaderInstructionFormat::Vdata2Vaddr3StSsDmask5;
inst.dst.size = 2;
break;
}
case 0x7:
{
inst.format = ShaderInstructionFormat::Vdata3Vaddr3StSsDmask7;
inst.dst.size = 3;
break;
}
case 0x8:
{
inst.format = ShaderInstructionFormat::Vdata1Vaddr3StSsDmask8;
inst.dst.size = 1;
break;
}
case 0xf:
{
inst.format = ShaderInstructionFormat::Vdata4Vaddr3StSsDmaskF;
@@ -1654,6 +1754,38 @@ KYTY_SHADER_PARSER(shader_parse_mimg)
default:;
}
break;
case 0x27:
inst.type = ShaderInstructionType::ImageSampleLz;
inst.src[0].size = 3;
inst.src[1].size = 8;
inst.src[2].size = 4;
switch (dmask) // NOLINT
{
case 0x7:
{
inst.format = ShaderInstructionFormat::Vdata3Vaddr3StSsDmask7;
inst.dst.size = 3;
break;
}
default:;
}
break;
case 0x37:
inst.type = ShaderInstructionType::ImageSampleLzO;
inst.src[0].size = 4;
inst.src[1].size = 8;
inst.src[2].size = 4;
switch (dmask) // NOLINT
{
case 0x7:
{
inst.format = ShaderInstructionFormat::Vdata3Vaddr4StSsDmask7;
inst.dst.size = 3;
break;
}
default:;
}
break;
default: printf("%s", dst->DbgDump().C_Str()); EXIT("unknown mimg opcode: 0x%02" PRIx32 " at addr 0x%08" PRIx32 "\n", opcode, pc);
}
@@ -1695,8 +1827,13 @@ KYTY_SHADER_PARSER(shader_parse_mtbuf)
EXIT_NOT_IMPLEMENTED(glc == 1);
EXIT_NOT_IMPLEMENTED(slc == 1);
EXIT_NOT_IMPLEMENTED(tfe == 1);
EXIT_NOT_IMPLEMENTED(dfmt != 14);
EXIT_NOT_IMPLEMENTED(nfmt != 7);
// EXIT_NOT_IMPLEMENTED(dfmt != 14);
// EXIT_NOT_IMPLEMENTED(nfmt != 7);
if ((dfmt != 14 && dfmt != 4) || nfmt != 7)
{
EXIT("unknown format: dfmt = %d, nfmt = %d at addr 0x%08" PRIx32 " (hash0 = 0x%08" PRIx32 ")\n", dfmt, nfmt, pc, dst->GetHash0());
}
uint32_t size = 2;
@@ -1716,14 +1853,22 @@ KYTY_SHADER_PARSER(shader_parse_mtbuf)
inst.src[1].size = 4;
switch (opcode) // NOLINT
switch (opcode)
{
case 0x00:
inst.type = ShaderInstructionType::TBufferLoadFormatX;
inst.format = ShaderInstructionFormat::Vdata1VaddrSvSoffsIdxenFloat1;
EXIT_NOT_IMPLEMENTED(offen == 1);
EXIT_NOT_IMPLEMENTED(!(dfmt == 4 && nfmt == 7));
break;
case 0x03:
inst.type = ShaderInstructionType::TBufferLoadFormatXyzw;
inst.format = (offen == 1 ? ShaderInstructionFormat::Vdata4Vaddr2SvSoffsOffenIdxenFloat4
: ShaderInstructionFormat::Vdata4VaddrSvSoffsIdxenFloat4);
inst.src[0].size += static_cast<int>(offen);
inst.dst.size = 4;
EXIT_NOT_IMPLEMENTED(!(dfmt == 14 && nfmt == 7));
break;
default: printf("%s", dst->DbgDump().C_Str()); EXIT("unknown mtbuf opcode: 0x%02" PRIx32 " at addr 0x%08" PRIx32 "\n", opcode, pc);
}
@@ -2026,21 +2171,24 @@ static bool SpirvToGlsl(const uint32_t* /*src_binary*/, size_t /*src_binary_size
return true;
}
static bool SpirvRun(const String& src, Vector<uint32_t>* dst)
static bool SpirvRun(const String& src, Vector<uint32_t>* dst, String* err_msg)
{
EXIT_IF(dst == nullptr);
EXIT_IF(err_msg == nullptr);
spvtools::SpirvTools core(SPV_ENV_VULKAN_1_2);
spvtools::Optimizer opt(SPV_ENV_VULKAN_1_2);
spv_position_t error_position {};
String error_msg;
auto print_msg_to_stderr = [&error_position](spv_message_level_t /* level */, const char* /*source*/,
[[maybe_unused]] const spv_position_t& position, const char* m)
auto print_msg_to_stderr = [&error_position, &error_msg](spv_message_level_t /* level */, const char* /*source*/,
[[maybe_unused]] const spv_position_t& position, const char* m)
{
// printf("%s\n", source);
printf(FG_BRIGHT_RED "error: %d: %d (%d) %s\n" FG_DEFAULT, static_cast<int>(position.line), static_cast<int>(position.column),
static_cast<int>(position.index), m);
error_msg = String::FromPrintf("%d: %d (%d) %s", static_cast<int>(position.line), static_cast<int>(position.column),
static_cast<int>(position.index), m);
printf(FG_BRIGHT_RED "error: %s\n" FG_DEFAULT, error_msg.C_Str());
error_position = position;
};
core.SetMessageConsumer(print_msg_to_stderr);
@@ -2054,6 +2202,7 @@ static bool SpirvRun(const String& src, Vector<uint32_t>* dst)
if (!core.Assemble(src_utf8.GetDataConst(), src_utf8.Size(), &spirv))
{
printf("Assemble failed at:\n%s\n", src.Mid(src.FindIndex(U'\n', error_position.index - 100), 200).C_Str());
*err_msg = String::FromPrintf("Assemble failed at:\n%s\n", src.Mid(src.FindIndex(U'\n', error_position.index - 100), 200).C_Str());
return false;
}
@@ -2063,6 +2212,7 @@ static bool SpirvRun(const String& src, Vector<uint32_t>* dst)
SpirvDisassemble(spirv.data(), spirv.size(), &disassembly);
printf("%s\n", disassembly.C_Str());
printf("Validate failed\n");
*err_msg = String::FromPrintf("%s\n\nValidate failed:\n%s\n", Log::RemoveColors(disassembly).C_Str(), error_msg.C_Str());
return false;
}
@@ -2077,6 +2227,7 @@ static bool SpirvRun(const String& src, Vector<uint32_t>* dst)
if (optimize && !opt.Run(spirv.data(), spirv.size(), &spirv))
{
printf("Optimize failed\n");
*err_msg = String::FromPrintf("Optimize failed\n");
return false;
}
@@ -2946,7 +3097,7 @@ class ShaderLogHelper
public:
explicit ShaderLogHelper(const char* type)
{
static int id = 0;
static std::atomic_int id = 0;
switch (Config::GetShaderLogDirection())
{
@@ -2989,11 +3140,17 @@ public:
if (m_console)
{
printf("--------- Original Shader ---------\n");
printf("crc32 = %08" PRIx32 "\n", code.GetCrc32());
printf("hash0 = %08" PRIx32 "\n", code.GetHash0());
printf("---------\n");
printf("%s", code.DbgDump().C_Str());
printf("---------\n");
} else if (!m_file.IsInvalid())
{
m_file.Printf("--------- Original Shader ---------\n");
m_file.Printf("crc32 = %08" PRIx32 "\n", code.GetCrc32());
m_file.Printf("hash0 = %08" PRIx32 "\n", code.GetHash0());
m_file.Printf("---------\n");
m_file.Printf("%s", code.DbgDump().C_Str());
m_file.Printf("---------\n");
}
@@ -3115,6 +3272,8 @@ ShaderCode ShaderParseVS(const HW::VertexShaderInfo* regs)
bi_print("ShaderParseVS():ShaderBinaryInfo", *header);
code.SetCrc32(header->crc32);
code.SetHash0(header->hash0);
shader_parse(0, src, nullptr, &code);
if (g_debug_printfs != nullptr)
@@ -3156,9 +3315,9 @@ Vector<uint32_t> ShaderRecompileVS(const ShaderCode& code, const ShaderVertexInp
log.DumpRecompiledShader(source);
if (!SpirvRun(source, &ret))
if (String err_msg; !SpirvRun(source, &ret, &err_msg))
{
EXIT("SpirvRun() failed\n");
EXIT("SpirvRun() failed:\n%s\n", err_msg.C_Str());
}
log.DumpOptimizedShader(ret);
@@ -3194,6 +3353,8 @@ ShaderCode ShaderParsePS(const HW::PixelShaderInfo* regs)
bi_print("ShaderParsePS():ShaderBinaryInfo", *header);
code.SetCrc32(header->crc32);
code.SetHash0(header->hash0);
shader_parse(0, src, nullptr, &code);
if (g_debug_printfs != nullptr)
@@ -3240,9 +3401,9 @@ Vector<uint32_t> ShaderRecompilePS(const ShaderCode& code, const ShaderPixelInpu
log.DumpRecompiledShader(source);
if (!SpirvRun(source, &ret))
if (String err_msg; !SpirvRun(source, &ret, &err_msg))
{
EXIT("SpirvRun() failed\n");
EXIT("SpirvRun() failed:\n%s\n", err_msg.C_Str());
}
log.DumpOptimizedShader(ret);
@@ -3272,6 +3433,8 @@ ShaderCode ShaderParseCS(const HW::ComputeShaderInfo* regs)
ShaderCode code;
code.SetType(ShaderType::Compute);
code.SetCrc32(header->crc32);
code.SetHash0(header->hash0);
shader_parse(0, src, nullptr, &code);
if (g_debug_printfs != nullptr)
@@ -3306,9 +3469,9 @@ Vector<uint32_t> ShaderRecompileCS(const ShaderCode& code, const ShaderComputeIn
log.DumpRecompiledShader(source);
if (!SpirvRun(source, &ret))
if (String err_msg; !SpirvRun(source, &ret, &err_msg))
{
EXIT("SpirvRun() failed\n");
EXIT("SpirvRun() failed:\n%s\n", err_msg.C_Str());
}
log.DumpOptimizedShader(ret);
@@ -3553,9 +3716,10 @@ ShaderId ShaderGetIdVS(const HW::VertexShaderInfo* regs, const ShaderVertexInput
ret.ids.Expand(64);
ret.hash0 = header->hash0;
ret.crc32 = header->crc32;
ret.ids.Add(header->length);
ret.ids.Add(header->hash0);
ret.ids.Add(header->crc32);
ret.ids.Add(static_cast<uint32_t>(input_info->fetch));
ret.ids.Add(input_info->resources_num);
ret.ids.Add(input_info->export_count);
@@ -3619,9 +3783,10 @@ ShaderId ShaderGetIdPS(const HW::PixelShaderInfo* regs, const ShaderPixelInputIn
ret.ids.Expand(64);
ret.hash0 = header->hash0;
ret.crc32 = header->crc32;
ret.ids.Add(header->length);
ret.ids.Add(header->hash0);
ret.ids.Add(header->crc32);
ret.ids.Add(input_info->input_num);
ret.ids.Add(static_cast<uint32_t>(input_info->ps_pos_xy));
ret.ids.Add(static_cast<uint32_t>(input_info->ps_pixel_kill_enable));
@@ -3651,9 +3816,10 @@ ShaderId ShaderGetIdCS(const HW::ComputeShaderInfo* regs, const ShaderComputeInp
ShaderId ret;
ret.ids.Expand(64);
ret.hash0 = header->hash0;
ret.crc32 = header->crc32;
ret.ids.Add(header->length);
ret.ids.Add(header->hash0);
ret.ids.Add(header->crc32);
ret.ids.Add(input_info->workgroup_register);
ret.ids.Add(input_info->thread_ids_num);
+584 -69
View File
@@ -1304,10 +1304,13 @@ private:
void WriteInstructions();
void WriteMainEpilog();
void WriteFunctions();
void WriteLabel(int index);
void FindConstants();
void FindVariables();
void ModifyCode();
String m_source;
ShaderCode m_code;
Vector<Constant> m_constants;
@@ -1454,7 +1457,7 @@ static bool operand_load_int(Spirv* spirv, ShaderOperand op, const String& resul
{
EXIT_IF(load == nullptr);
EXIT_NOT_IMPLEMENTED(op.negate);
EXIT_NOT_IMPLEMENTED(op.negate || op.absolute);
if (operand_is_constant(op))
{
@@ -1494,7 +1497,7 @@ static bool operand_load_uint(Spirv* spirv, ShaderOperand op, const String& resu
{
EXIT_IF(load == nullptr);
EXIT_NOT_IMPLEMENTED(op.negate);
EXIT_NOT_IMPLEMENTED(op.negate || op.absolute);
if (operand_is_constant(op))
{
@@ -1593,7 +1596,17 @@ static bool operand_load_float(Spirv* spirv, ShaderOperand op, const String& res
return false;
}
if (op.negate)
if (op.negate && op.absolute)
{
// TODO(): negated absolute value
return false;
}
if (op.absolute)
{
l += String(U' ', 10) + String(U"%<result> = OpExtInst %float %GLSL_std_450 FAbs %<result_id>\n");
*load = l.ReplaceStr(U"<index>", index).ReplaceStr(U"<result_id>", U"a" + result_id).ReplaceStr(U"<result>", result_id);
} else if (op.negate)
{
l += String(U' ', 10) + String(U"%<result> = OpFNegate %float %<result_id>\n");
*load = l.ReplaceStr(U"<index>", index).ReplaceStr(U"<result_id>", U"n" + result_id).ReplaceStr(U"<result>", result_id);
@@ -2149,7 +2162,7 @@ KYTY_RECOMPILER_FUNC(Recompile_Exp_Mrt0Vsrc0Vsrc1Vsrc2Vsrc3VmDone)
return true;
}
/* XXX: 0, 1, 2, 3*/
/* XXX: 0, 1, 2, 3, 4 */
KYTY_RECOMPILER_FUNC(Recompile_Exp_Param_XXX_Vsrc0Vsrc1Vsrc2Vsrc3)
{
const auto& inst = code.GetInstructions().At(index);
@@ -2228,11 +2241,10 @@ KYTY_RECOMPILER_FUNC(Recompile_ImageSample_Vdata1Vaddr3StSsDmask1)
{
const auto& inst = code.GetInstructions().At(index);
const auto* bind_info = spirv->GetBindInfo();
// const auto& bind_params = spirv->GetBindParams();
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_value0 = operand_variable_to_str(inst.dst);
auto src0_value0 = operand_variable_to_str(inst.src[0], 0);
auto src0_value1 = operand_variable_to_str(inst.src[0], 1);
auto src0_value2 = operand_variable_to_str(inst.src[0], 2);
@@ -2279,6 +2291,178 @@ KYTY_RECOMPILER_FUNC(Recompile_ImageSample_Vdata1Vaddr3StSsDmask1)
return false;
}
KYTY_RECOMPILER_FUNC(Recompile_ImageSample_Vdata1Vaddr3StSsDmask8)
{
const auto& inst = code.GetInstructions().At(index);
const auto* bind_info = spirv->GetBindInfo();
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);
auto src0_value0 = operand_variable_to_str(inst.src[0], 0);
auto src0_value1 = operand_variable_to_str(inst.src[0], 1);
auto src0_value2 = operand_variable_to_str(inst.src[0], 2);
auto src1_value0 = operand_variable_to_str(inst.src[1], 0);
auto src2_value0 = operand_variable_to_str(inst.src[2], 0);
EXIT_NOT_IMPLEMENTED(dst_value0.type != SpirvType::Float);
EXIT_NOT_IMPLEMENTED(src0_value0.type != SpirvType::Float);
EXIT_NOT_IMPLEMENTED(src1_value0.type != SpirvType::Uint);
EXIT_NOT_IMPLEMENTED(src2_value0.type != SpirvType::Uint);
// TODO() check VSKIP
// TODO() check LOD_CLAMPED
static const char32_t* text = UR"(
%t24_<index> = OpLoad %uint %<src1_value0>
%t26_<index> = OpAccessChain %_ptr_UniformConstant_ImageS %textures2D_S %t24_<index>
%t27_<index> = OpLoad %ImageS %t26_<index>
%t33_<index> = OpLoad %uint %<src2_value0>
%t35_<index> = OpAccessChain %_ptr_UniformConstant_Sampler %samplers %t33_<index>
%t36_<index> = OpLoad %Sampler %t35_<index>
%t38_<index> = OpSampledImage %SampledImage %t27_<index> %t36_<index>
%t39_<index> = OpLoad %float %<src0_value0>
%t40_<index> = OpLoad %float %<src0_value1>
%t42_<index> = OpCompositeConstruct %v2float %t39_<index> %t40_<index>
%t43_<index> = OpImageSampleImplicitLod %v4float %t38_<index> %t42_<index>
OpStore %temp_v4float %t43_<index>
%t46_<index> = OpAccessChain %_ptr_Function_float %temp_v4float %uint_3
%t47_<index> = OpLoad %float %t46_<index>
OpStore %<dst_value0> %t47_<index>
)";
*dst_source += String(text)
.ReplaceStr(U"<index>", String::FromPrintf("%u", index))
.ReplaceStr(U"<src0_value0>", src0_value0.value)
.ReplaceStr(U"<src0_value1>", src0_value1.value)
.ReplaceStr(U"<src0_value2>", src0_value2.value)
.ReplaceStr(U"<src1_value0>", src1_value0.value)
.ReplaceStr(U"<src2_value0>", src2_value0.value)
.ReplaceStr(U"<dst_value0>", dst_value0.value);
return true;
}
return false;
}
KYTY_RECOMPILER_FUNC(Recompile_ImageSample_Vdata2Vaddr3StSsDmask3)
{
const auto& inst = code.GetInstructions().At(index);
const auto* bind_info = spirv->GetBindInfo();
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);
auto src0_value0 = operand_variable_to_str(inst.src[0], 0);
auto src0_value1 = operand_variable_to_str(inst.src[0], 1);
auto src0_value2 = operand_variable_to_str(inst.src[0], 2);
auto src1_value0 = operand_variable_to_str(inst.src[1], 0);
auto src2_value0 = operand_variable_to_str(inst.src[2], 0);
EXIT_NOT_IMPLEMENTED(dst_value0.type != SpirvType::Float);
EXIT_NOT_IMPLEMENTED(src0_value0.type != SpirvType::Float);
EXIT_NOT_IMPLEMENTED(src1_value0.type != SpirvType::Uint);
EXIT_NOT_IMPLEMENTED(src2_value0.type != SpirvType::Uint);
// TODO() check VSKIP
// TODO() check LOD_CLAMPED
static const char32_t* text = UR"(
%t24_<index> = OpLoad %uint %<src1_value0>
%t26_<index> = OpAccessChain %_ptr_UniformConstant_ImageS %textures2D_S %t24_<index>
%t27_<index> = OpLoad %ImageS %t26_<index>
%t33_<index> = OpLoad %uint %<src2_value0>
%t35_<index> = OpAccessChain %_ptr_UniformConstant_Sampler %samplers %t33_<index>
%t36_<index> = OpLoad %Sampler %t35_<index>
%t38_<index> = OpSampledImage %SampledImage %t27_<index> %t36_<index>
%t39_<index> = OpLoad %float %<src0_value0>
%t40_<index> = OpLoad %float %<src0_value1>
%t42_<index> = OpCompositeConstruct %v2float %t39_<index> %t40_<index>
%t43_<index> = OpImageSampleImplicitLod %v4float %t38_<index> %t42_<index>
OpStore %temp_v4float %t43_<index>
%t46_<index> = OpAccessChain %_ptr_Function_float %temp_v4float %uint_0
%t47_<index> = OpLoad %float %t46_<index>
OpStore %<dst_value0> %t47_<index>
%t54_<index> = OpAccessChain %_ptr_Function_float %temp_v4float %uint_1
%t55_<index> = OpLoad %float %t54_<index>
OpStore %<dst_value1> %t55_<index>
)";
*dst_source += String(text)
.ReplaceStr(U"<index>", String::FromPrintf("%u", index))
.ReplaceStr(U"<src0_value0>", src0_value0.value)
.ReplaceStr(U"<src0_value1>", src0_value1.value)
.ReplaceStr(U"<src0_value2>", src0_value2.value)
.ReplaceStr(U"<src1_value0>", src1_value0.value)
.ReplaceStr(U"<src2_value0>", src2_value0.value)
.ReplaceStr(U"<dst_value0>", dst_value0.value)
.ReplaceStr(U"<dst_value1>", dst_value1.value);
return true;
}
return false;
}
KYTY_RECOMPILER_FUNC(Recompile_ImageSample_Vdata2Vaddr3StSsDmask5)
{
const auto& inst = code.GetInstructions().At(index);
const auto* bind_info = spirv->GetBindInfo();
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);
auto src0_value0 = operand_variable_to_str(inst.src[0], 0);
auto src0_value1 = operand_variable_to_str(inst.src[0], 1);
auto src0_value2 = operand_variable_to_str(inst.src[0], 2);
auto src1_value0 = operand_variable_to_str(inst.src[1], 0);
auto src2_value0 = operand_variable_to_str(inst.src[2], 0);
EXIT_NOT_IMPLEMENTED(dst_value0.type != SpirvType::Float);
EXIT_NOT_IMPLEMENTED(src0_value0.type != SpirvType::Float);
EXIT_NOT_IMPLEMENTED(src1_value0.type != SpirvType::Uint);
EXIT_NOT_IMPLEMENTED(src2_value0.type != SpirvType::Uint);
// TODO() check VSKIP
// TODO() check LOD_CLAMPED
static const char32_t* text = UR"(
%t24_<index> = OpLoad %uint %<src1_value0>
%t26_<index> = OpAccessChain %_ptr_UniformConstant_ImageS %textures2D_S %t24_<index>
%t27_<index> = OpLoad %ImageS %t26_<index>
%t33_<index> = OpLoad %uint %<src2_value0>
%t35_<index> = OpAccessChain %_ptr_UniformConstant_Sampler %samplers %t33_<index>
%t36_<index> = OpLoad %Sampler %t35_<index>
%t38_<index> = OpSampledImage %SampledImage %t27_<index> %t36_<index>
%t39_<index> = OpLoad %float %<src0_value0>
%t40_<index> = OpLoad %float %<src0_value1>
%t42_<index> = OpCompositeConstruct %v2float %t39_<index> %t40_<index>
%t43_<index> = OpImageSampleImplicitLod %v4float %t38_<index> %t42_<index>
OpStore %temp_v4float %t43_<index>
%t46_<index> = OpAccessChain %_ptr_Function_float %temp_v4float %uint_0
%t47_<index> = OpLoad %float %t46_<index>
OpStore %<dst_value0> %t47_<index>
%t54_<index> = OpAccessChain %_ptr_Function_float %temp_v4float %uint_2
%t55_<index> = OpLoad %float %t54_<index>
OpStore %<dst_value1> %t55_<index>
)";
*dst_source += String(text)
.ReplaceStr(U"<index>", String::FromPrintf("%u", index))
.ReplaceStr(U"<src0_value0>", src0_value0.value)
.ReplaceStr(U"<src0_value1>", src0_value1.value)
.ReplaceStr(U"<src0_value2>", src0_value2.value)
.ReplaceStr(U"<src1_value0>", src1_value0.value)
.ReplaceStr(U"<src2_value0>", src2_value0.value)
.ReplaceStr(U"<dst_value0>", dst_value0.value)
.ReplaceStr(U"<dst_value1>", dst_value1.value);
return true;
}
return false;
}
KYTY_RECOMPILER_FUNC(Recompile_ImageSample_Vdata3Vaddr3StSsDmask7)
{
const auto& inst = code.GetInstructions().At(index);
@@ -2344,6 +2528,153 @@ KYTY_RECOMPILER_FUNC(Recompile_ImageSample_Vdata3Vaddr3StSsDmask7)
return false;
}
KYTY_RECOMPILER_FUNC(Recompile_ImageSampleLz_Vdata3Vaddr3StSsDmask7)
{
const auto& inst = code.GetInstructions().At(index);
const auto* bind_info = spirv->GetBindInfo();
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);
auto dst_value2 = operand_variable_to_str(inst.dst, 2);
auto src0_value0 = operand_variable_to_str(inst.src[0], 0);
auto src0_value1 = operand_variable_to_str(inst.src[0], 1);
auto src0_value2 = operand_variable_to_str(inst.src[0], 2);
auto src1_value0 = operand_variable_to_str(inst.src[1], 0);
auto src2_value0 = operand_variable_to_str(inst.src[2], 0);
EXIT_NOT_IMPLEMENTED(dst_value0.type != SpirvType::Float);
EXIT_NOT_IMPLEMENTED(src0_value0.type != SpirvType::Float);
EXIT_NOT_IMPLEMENTED(src1_value0.type != SpirvType::Uint);
EXIT_NOT_IMPLEMENTED(src2_value0.type != SpirvType::Uint);
// TODO() check VSKIP
// TODO() check LOD_CLAMPED
static const char32_t* text = UR"(
%t24_<index> = OpLoad %uint %<src1_value0>
%t26_<index> = OpAccessChain %_ptr_UniformConstant_ImageS %textures2D_S %t24_<index>
%t27_<index> = OpLoad %ImageS %t26_<index>
%t33_<index> = OpLoad %uint %<src2_value0>
%t35_<index> = OpAccessChain %_ptr_UniformConstant_Sampler %samplers %t33_<index>
%t36_<index> = OpLoad %Sampler %t35_<index>
%t38_<index> = OpSampledImage %SampledImage %t27_<index> %t36_<index>
%t39_<index> = OpLoad %float %<src0_value0>
%t40_<index> = OpLoad %float %<src0_value1>
%t42_<index> = OpCompositeConstruct %v2float %t39_<index> %t40_<index>
%t43_<index> = OpImageSampleExplicitLod %v4float %t38_<index> %t42_<index> Lod %float_0_000000
OpStore %temp_v4float %t43_<index>
%t46_<index> = OpAccessChain %_ptr_Function_float %temp_v4float %uint_0
%t47_<index> = OpLoad %float %t46_<index>
OpStore %<dst_value0> %t47_<index>
%t50_<index> = OpAccessChain %_ptr_Function_float %temp_v4float %uint_1
%t51_<index> = OpLoad %float %t50_<index>
OpStore %<dst_value1> %t51_<index>
%t54_<index> = OpAccessChain %_ptr_Function_float %temp_v4float %uint_2
%t55_<index> = OpLoad %float %t54_<index>
OpStore %<dst_value2> %t55_<index>
)";
*dst_source += String(text)
.ReplaceStr(U"<index>", String::FromPrintf("%u", index))
.ReplaceStr(U"<src0_value0>", src0_value0.value)
.ReplaceStr(U"<src0_value1>", src0_value1.value)
.ReplaceStr(U"<src0_value2>", src0_value2.value)
.ReplaceStr(U"<src1_value0>", src1_value0.value)
.ReplaceStr(U"<src2_value0>", src2_value0.value)
.ReplaceStr(U"<dst_value0>", dst_value0.value)
.ReplaceStr(U"<dst_value1>", dst_value1.value)
.ReplaceStr(U"<dst_value2>", dst_value2.value);
return true;
}
return false;
}
KYTY_RECOMPILER_FUNC(Recompile_ImageSampleLzO_Vdata3Vaddr4StSsDmask7)
{
const auto& inst = code.GetInstructions().At(index);
const auto* bind_info = spirv->GetBindInfo();
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);
auto dst_value2 = operand_variable_to_str(inst.dst, 2);
auto src0_value0 = operand_variable_to_str(inst.src[0], 0);
auto src0_value1 = operand_variable_to_str(inst.src[0], 1);
auto src0_value2 = operand_variable_to_str(inst.src[0], 2);
auto src0_value3 = operand_variable_to_str(inst.src[0], 3);
auto src1_value0 = operand_variable_to_str(inst.src[1], 0);
auto src2_value0 = operand_variable_to_str(inst.src[2], 0);
EXIT_NOT_IMPLEMENTED(dst_value0.type != SpirvType::Float);
EXIT_NOT_IMPLEMENTED(src0_value0.type != SpirvType::Float);
EXIT_NOT_IMPLEMENTED(src1_value0.type != SpirvType::Uint);
EXIT_NOT_IMPLEMENTED(src2_value0.type != SpirvType::Uint);
// TODO() check VSKIP
// TODO() check LOD_CLAMPED
static const char32_t* text = UR"(
%t24_<index> = OpLoad %uint %<src1_value0>
%t26_<index> = OpAccessChain %_ptr_UniformConstant_ImageS %textures2D_S %t24_<index>
%t27_<index> = OpLoad %ImageS %t26_<index>
%t33_<index> = OpLoad %uint %<src2_value0>
%t35_<index> = OpAccessChain %_ptr_UniformConstant_Sampler %samplers %t33_<index>
%t36_<index> = OpLoad %Sampler %t35_<index>
%t38_<index> = OpSampledImage %SampledImage %t27_<index> %t36_<index>
%t39_<index> = OpLoad %float %<src0_value1>
%t40_<index> = OpLoad %float %<src0_value2>
%t42_<index> = OpCompositeConstruct %v2float %t39_<index> %t40_<index>
%90_<index> = OpLoad %float %<src0_value0>
%91_<index> = OpBitcast %int %90_<index>
%98_<index> = OpBitFieldSExtract %int %91_<index> %int_0 %int_6
%101_<index> = OpBitFieldSExtract %int %91_<index> %int_8 %int_6
%102_<index> = OpCompositeConstruct %v2int %98_<index> %101_<index>
%130_<index> = OpConvertSToF %v2float %102_<index>
%138_<index> = OpImage %ImageS %t38_<index>
%139_<index> = OpImageQuerySizeLod %v2int %138_<index> %int_0
%140_<index> = OpConvertSToF %v2float %139_<index>
%141_<index> = OpFDiv %v2float %130_<index> %140_<index>
%142_<index> = OpFAdd %v2float %t42_<index> %141_<index>
%t43_<index> = OpImageSampleExplicitLod %v4float %t38_<index> %142_<index> Lod %float_0_000000
OpStore %temp_v4float %t43_<index>
%t46_<index> = OpAccessChain %_ptr_Function_float %temp_v4float %uint_0
%t47_<index> = OpLoad %float %t46_<index>
OpStore %<dst_value0> %t47_<index>
%t50_<index> = OpAccessChain %_ptr_Function_float %temp_v4float %uint_1
%t51_<index> = OpLoad %float %t50_<index>
OpStore %<dst_value1> %t51_<index>
%t54_<index> = OpAccessChain %_ptr_Function_float %temp_v4float %uint_2
%t55_<index> = OpLoad %float %t54_<index>
OpStore %<dst_value2> %t55_<index>
)";
*dst_source += String(text)
.ReplaceStr(U"<index>", String::FromPrintf("%u", index))
.ReplaceStr(U"<src0_value0>", src0_value0.value)
.ReplaceStr(U"<src0_value1>", src0_value1.value)
.ReplaceStr(U"<src0_value2>", src0_value2.value)
.ReplaceStr(U"<src0_value3>", src0_value3.value)
.ReplaceStr(U"<src1_value0>", src1_value0.value)
.ReplaceStr(U"<src2_value0>", src2_value0.value)
.ReplaceStr(U"<dst_value0>", dst_value0.value)
.ReplaceStr(U"<dst_value1>", dst_value1.value)
.ReplaceStr(U"<dst_value2>", dst_value2.value);
return true;
}
return false;
}
KYTY_RECOMPILER_FUNC(Recompile_ImageSample_Vdata4Vaddr3StSsDmaskF)
{
const auto& inst = code.GetInstructions().At(index);
@@ -3195,6 +3526,8 @@ KYTY_RECOMPILER_FUNC(Recompile_SCbranchExecz_Label)
EXIT_NOT_IMPLEMENTED(!operand_is_constant(inst.src[0]));
EXIT_NOT_IMPLEMENTED(code.IsDiscardBlock(ShaderLabel(inst).GetDst()));
String label = ShaderLabel(inst).ToString();
static const char32_t* text = UR"(
@@ -3216,12 +3549,13 @@ KYTY_RECOMPILER_FUNC(Recompile_SCbranchScc0_Label)
EXIT_NOT_IMPLEMENTED(!operand_is_constant(inst.src[0]));
auto label = ShaderLabel(inst);
String label_str = label.ToString();
auto label = ShaderLabel(inst);
// TODO(): analyze control flow graph
bool discard = code.IsDiscardBlock(label.GetDst());
String label_str = label.ToString();
static const char32_t* text_variant_a = UR"(
%scc_u_<index> = OpLoad %uint %scc
%scc_b_<index> = OpIEqual %bool %scc_u_<index> %uint_0
@@ -3244,6 +3578,41 @@ KYTY_RECOMPILER_FUNC(Recompile_SCbranchScc0_Label)
return true;
}
KYTY_RECOMPILER_FUNC(Recompile_SCbranchVccz_Label)
{
const auto& inst = code.GetInstructions().At(index);
EXIT_NOT_IMPLEMENTED(!operand_is_constant(inst.src[0]));
auto label = ShaderLabel(inst);
// TODO(): analyze control flow graph
bool discard = code.IsDiscardBlock(label.GetDst());
String label_str = label.ToString();
static const char32_t* text_variant_a = UR"(
%vcc_lo_u_<index> = OpLoad %uint %vcc_lo
%vcc_lo_b_<index> = OpIEqual %bool %vcc_lo_u_<index> %uint_0
OpSelectionMerge %<label> None
OpBranchConditional %vcc_lo_b_<index> %<label> %t230_<index>
%t230_<index> = OpLabel
)";
static const char32_t* text_variant_b = UR"(
%vcc_lo_u_<index> = OpLoad %uint %vcc_lo
%vcc_lo_b_<index> = OpIEqual %bool %vcc_lo_u_<index> %uint_0
OpSelectionMerge %t230_<index> None
OpBranchConditional %vcc_lo_b_<index> %<label> %t230_<index>
%t230_<index> = OpLabel
)";
*dst_source += String(discard ? text_variant_b : text_variant_a)
.ReplaceStr(U"<index>", String::FromPrintf("%u", index))
.ReplaceStr(U"<label>", label_str);
return true;
}
KYTY_RECOMPILER_FUNC(Recompile_SEndpgm_Empty)
{
// const auto* info = spirv->GetPsInputInfo();
@@ -3532,7 +3901,7 @@ KYTY_RECOMPILER_FUNC(Recompile_SWqmB64_Sdst2Ssrc02)
EXIT_NOT_IMPLEMENTED(dst_value0.type != SpirvType::Uint);
EXIT_NOT_IMPLEMENTED(operand_is_exec(inst.dst));
// EXIT_NOT_IMPLEMENTED(operand_is_exec(inst.dst));
String load0;
String load1;
@@ -3604,6 +3973,59 @@ KYTY_RECOMPILER_FUNC(Recompile_SWaitcnt_Imm)
return true;
}
KYTY_RECOMPILER_FUNC(Recompile_TBufferLoadFormatX_Vdata1VaddrSvSoffsIdxenFloat1)
{
const auto& inst = code.GetInstructions().At(index);
const auto* bind_info = spirv->GetBindInfo();
if (bind_info != nullptr && bind_info->storage_buffers.buffers_num > 0)
{
EXIT_NOT_IMPLEMENTED(!operand_is_constant(inst.src[2]));
auto dst_value0 = operand_variable_to_str(inst.dst);
auto src0_value = operand_variable_to_str(inst.src[0]);
auto src1_value0 = operand_variable_to_str(inst.src[1], 0);
auto src1_value1 = operand_variable_to_str(inst.src[1], 1);
String offset = spirv->GetConstant(inst.src[2]);
EXIT_NOT_IMPLEMENTED(dst_value0.type != SpirvType::Float);
EXIT_NOT_IMPLEMENTED(src0_value.type != SpirvType::Float);
EXIT_NOT_IMPLEMENTED(src1_value0.type != SpirvType::Uint);
EXIT_NOT_IMPLEMENTED(src1_value1.type != SpirvType::Uint);
// TODO() check VSKIP
// TODO() check EXEC
static const char32_t* text = UR"(
%t100_<index> = OpLoad %float %<src0>
%t101_<index> = OpBitcast %int %t100_<index>
OpStore %temp_int_1 %t101_<index>
%t148_<index> = OpLoad %uint %<src1_value1>
%t150_<index> = OpShiftRightLogical %uint %t148_<index> %int_16
%t152_<index> = OpBitwiseAnd %uint %t150_<index> %uint_0x00003fff
%t153_<index> = OpBitcast %int %t152_<index>
OpStore %temp_int_3 %t153_<index>
%t155_<index> = OpLoad %uint %<src1_value0>
%t156_<index> = OpBitcast %int %t155_<index>
OpStore %temp_int_4 %t156_<index>
OpStore %temp_int_2 %<offset>
OpStore %temp_int_5 %int_36
%t110_<index> = OpFunctionCall %void %tbuffer_load_format_x %<p0> %temp_int_1 %temp_int_2 %temp_int_3 %temp_int_4 %temp_int_5
)";
*dst_source += String(text)
.ReplaceStr(U"<index>", String::FromPrintf("%u", index))
.ReplaceStr(U"<src0>", src0_value.value)
.ReplaceStr(U"<offset>", offset)
.ReplaceStr(U"<src1_value0>", src1_value0.value)
.ReplaceStr(U"<src1_value1>", src1_value1.value)
.ReplaceStr(U"<p0>", dst_value0.value);
return true;
}
return false;
}
KYTY_RECOMPILER_FUNC(Recompile_TBufferLoadFormatXyzw_Vdata4VaddrSvSoffsIdxenFloat4)
{
const auto& inst = code.GetInstructions().At(index);
@@ -3986,7 +4408,7 @@ KYTY_RECOMPILER_FUNC(Recompile_VCmpx_XXX_U32_SmaskVsrc0Vsrc1)
return true;
}
/* XXX: Neq */
/* XXX: Neq, Gt, Lt */
KYTY_RECOMPILER_FUNC(Recompile_VCmpx_XXX_F32_SmaskVsrc0Vsrc1)
{
const auto& inst = code.GetInstructions().At(index);
@@ -4188,7 +4610,7 @@ KYTY_RECOMPILER_FUNC(Recompile_VInterpP2F32_VdstVsrcAttrChan)
return true;
}
/* XXX: Mad, Madak, Madmk */
/* XXX: Mad, Madak, Madmk, Max3, Min3, Med3, Fma */
KYTY_RECOMPILER_FUNC(Recompile_V_XXX_F32_VdstVsrc0Vsrc1Vsrc2)
{
const auto& inst = code.GetInstructions().At(index);
@@ -4229,7 +4651,10 @@ KYTY_RECOMPILER_FUNC(Recompile_V_XXX_F32_VdstVsrc0Vsrc1Vsrc2)
<load0>
<load1>
<load2>
<param>
<param0>
<param1>
<param2>
<param3>
%exec_lo_u_<index> = OpLoad %uint %exec_lo
%exec_hi_u_<index> = OpLoad %uint %exec_hi ; unused
%exec_lo_b_<index> = OpINotEqual %bool %exec_lo_u_<index> %uint_0
@@ -4251,7 +4676,10 @@ KYTY_RECOMPILER_FUNC(Recompile_V_XXX_F32_VdstVsrc0Vsrc1Vsrc2)
.ReplaceStr(U"<load0>", load0)
.ReplaceStr(U"<load1>", load1)
.ReplaceStr(U"<load2>", load2)
.ReplaceStr(U"<param>", param[0])
.ReplaceStr(U"<param0>", param[0])
.ReplaceStr(U"<param1>", (param[1] == nullptr ? U"" : param[1]))
.ReplaceStr(U"<param2>", (param[2] == nullptr ? U"" : param[2]))
.ReplaceStr(U"<param3>", (param[3] == nullptr ? U"" : param[3]))
.ReplaceStr(U"<index>", index_str);
return true;
@@ -4416,7 +4844,7 @@ KYTY_RECOMPILER_FUNC(Recompile_VMovB32_SVdstSVsrc0)
return true;
}
/* XXX: Mac, Max, Min, Mul, Sub, Subrev */
/* XXX: Mac, Max, Min, Mul, Sub, Subrev, Add */
KYTY_RECOMPILER_FUNC(Recompile_V_XXX_F32_SVdstSVsrc0SVsrc1)
{
const auto& inst = code.GetInstructions().At(index);
@@ -4485,7 +4913,7 @@ KYTY_RECOMPILER_FUNC(Recompile_V_XXX_F32_SVdstSVsrc0SVsrc1)
return true;
}
/* XXX: Rcp, Rsq, Sqrt, Ceil, Floor, Fract, Rndne, Trunc */
/* XXX: Rcp, Rsq, Sqrt, Ceil, Floor, Fract, Rndne, Trunc, Exp, Log, Cos, Sin */
KYTY_RECOMPILER_FUNC(Recompile_V_XXX_F32_SVdstSVsrc0)
{
const auto& inst = code.GetInstructions().At(index);
@@ -4493,8 +4921,8 @@ KYTY_RECOMPILER_FUNC(Recompile_V_XXX_F32_SVdstSVsrc0)
String index_str = String::FromPrintf("%u", index);
EXIT_NOT_IMPLEMENTED(!operand_is_variable(inst.dst));
EXIT_NOT_IMPLEMENTED(inst.dst.clamp);
EXIT_NOT_IMPLEMENTED(inst.dst.multiplier != 1.0f);
// EXIT_NOT_IMPLEMENTED(inst.dst.clamp);
// EXIT_NOT_IMPLEMENTED(inst.dst.multiplier != 1.0f);
auto dst_value = operand_variable_to_str(inst.dst);
@@ -4518,11 +4946,20 @@ KYTY_RECOMPILER_FUNC(Recompile_V_XXX_F32_SVdstSVsrc0)
%exec_lo_u_<index> = OpLoad %uint %exec_lo
%exec_hi_u_<index> = OpLoad %uint %exec_hi ; unused
%exec_lo_b_<index> = OpINotEqual %bool %exec_lo_u_<index> %uint_0
%tdst_<index> = OpLoad %float %<dst>
%tval_<index> = OpSelect %float %exec_lo_b_<index> %t_<index> %tdst_<index>
OpStore %<dst> %tval_<index>
OpSelectionMerge %tl2_<index> None
OpBranchConditional %exec_lo_b_<index> %tl1_<index> %tl2_<index>
%tl1_<index> = OpLabel
OpStore %<dst> %t_<index>
<multiply>
<clamp>
OpBranch %tl2_<index>
%tl2_<index> = OpLabel
)";
*dst_source += String(text)
.ReplaceStr(U"<multiply>", (inst.dst.multiplier != 1.0f
? String(MULTIPLY).ReplaceStr(U"<mul>", spirv->GetConstantFloat(inst.dst.multiplier))
: U""))
.ReplaceStr(U"<clamp>", (inst.dst.clamp ? CLAMP : U""))
.ReplaceStr(U"<dst>", dst_value.value)
.ReplaceStr(U"<load0>", load0)
.ReplaceStr(U"<param0>", param[0])
@@ -4915,7 +5352,7 @@ static RecompilerFunc g_recomp_func[] = {
{Recompile_BufferLoadFormatX_Vdata1VaddrSvSoffsIdxen, ShaderInstructionType::BufferLoadFormatX, ShaderInstructionFormat::Vdata1VaddrSvSoffsIdxen, {U""}},
{Recompile_BufferStoreDword_Vdata1VaddrSvSoffsIdxen, ShaderInstructionType::BufferStoreDword, ShaderInstructionFormat::Vdata1VaddrSvSoffsIdxen, {U""}},
{Recompile_BufferStoreFormatX_Vdata1VaddrSvSoffsIdxen, ShaderInstructionType::BufferStoreFormatX, ShaderInstructionFormat::Vdata1VaddrSvSoffsIdxen, {U""}},
{Recompile_BufferStoreFormatXy_Vdata2VaddrSvSoffsIdxen, ShaderInstructionType::BufferStoreFormatXy, ShaderInstructionFormat::Vdata2VaddrSvSoffsIdxen, {U""}},
{Recompile_BufferStoreFormatXy_Vdata2VaddrSvSoffsIdxen, ShaderInstructionType::BufferStoreFormatXy, ShaderInstructionFormat::Vdata2VaddrSvSoffsIdxen, {U""}},
{Recompile_DsAppend_VdstGds, ShaderInstructionType::DsAppend, ShaderInstructionFormat::VdstGds, {U""}},
{Recompile_DsConsume_VdstGds, ShaderInstructionType::DsConsume, ShaderInstructionFormat::VdstGds, {U""}},
@@ -4927,12 +5364,18 @@ static RecompilerFunc g_recomp_func[] = {
{Recompile_Exp_Param_XXX_Vsrc0Vsrc1Vsrc2Vsrc3, ShaderInstructionType::Exp, ShaderInstructionFormat::Param1Vsrc0Vsrc1Vsrc2Vsrc3, {U"param1"}},
{Recompile_Exp_Param_XXX_Vsrc0Vsrc1Vsrc2Vsrc3, ShaderInstructionType::Exp, ShaderInstructionFormat::Param2Vsrc0Vsrc1Vsrc2Vsrc3, {U"param2"}},
{Recompile_Exp_Param_XXX_Vsrc0Vsrc1Vsrc2Vsrc3, ShaderInstructionType::Exp, ShaderInstructionFormat::Param3Vsrc0Vsrc1Vsrc2Vsrc3, {U"param3"}},
{Recompile_Exp_Param_XXX_Vsrc0Vsrc1Vsrc2Vsrc3, ShaderInstructionType::Exp, ShaderInstructionFormat::Param4Vsrc0Vsrc1Vsrc2Vsrc3, {U"param4"}},
{Recompile_Exp_Pos0Vsrc0Vsrc1Vsrc2Vsrc3Done, ShaderInstructionType::Exp, ShaderInstructionFormat::Pos0Vsrc0Vsrc1Vsrc2Vsrc3Done, {U""}},
{Recompile_ImageLoad_Vdata4Vaddr3StDmaskF, ShaderInstructionType::ImageLoad, ShaderInstructionFormat::Vdata4Vaddr3StDmaskF, {U""}},
{Recompile_ImageSample_Vdata1Vaddr3StSsDmask1, ShaderInstructionType::ImageSample, ShaderInstructionFormat::Vdata1Vaddr3StSsDmask1, {U""}},
{Recompile_ImageSample_Vdata1Vaddr3StSsDmask1, ShaderInstructionType::ImageSample, ShaderInstructionFormat::Vdata1Vaddr3StSsDmask1, {U""}},
{Recompile_ImageSample_Vdata1Vaddr3StSsDmask8, ShaderInstructionType::ImageSample, ShaderInstructionFormat::Vdata1Vaddr3StSsDmask8, {U""}},
{Recompile_ImageSample_Vdata2Vaddr3StSsDmask3, ShaderInstructionType::ImageSample, ShaderInstructionFormat::Vdata2Vaddr3StSsDmask3, {U""}},
{Recompile_ImageSample_Vdata2Vaddr3StSsDmask5, ShaderInstructionType::ImageSample, ShaderInstructionFormat::Vdata2Vaddr3StSsDmask5, {U""}},
{Recompile_ImageSample_Vdata3Vaddr3StSsDmask7, ShaderInstructionType::ImageSample, ShaderInstructionFormat::Vdata3Vaddr3StSsDmask7, {U""}},
{Recompile_ImageSample_Vdata4Vaddr3StSsDmaskF, ShaderInstructionType::ImageSample, ShaderInstructionFormat::Vdata4Vaddr3StSsDmaskF, {U""}},
{Recompile_ImageSampleLz_Vdata3Vaddr3StSsDmask7, ShaderInstructionType::ImageSampleLz, ShaderInstructionFormat::Vdata3Vaddr3StSsDmask7, {U""}},
{Recompile_ImageSampleLzO_Vdata3Vaddr4StSsDmask7, ShaderInstructionType::ImageSampleLzO, ShaderInstructionFormat::Vdata3Vaddr4StSsDmask7, {U""}},
{Recompile_ImageStore_Vdata4Vaddr3StDmaskF, ShaderInstructionType::ImageStore, ShaderInstructionFormat::Vdata4Vaddr3StDmaskF, {U""}},
{Recompile_ImageStoreMip_Vdata4Vaddr4StDmaskF, ShaderInstructionType::ImageStoreMip, ShaderInstructionFormat::Vdata4Vaddr4StDmaskF, {U""}},
@@ -4940,10 +5383,11 @@ static RecompilerFunc g_recomp_func[] = {
{Recompile_SBufferLoadDwordx2_Sdst2SvSoffset, ShaderInstructionType::SBufferLoadDwordx2, ShaderInstructionFormat::Sdst2SvSoffset, {U""}},
{Recompile_SBufferLoadDwordx4_Sdst4SvSoffset, ShaderInstructionType::SBufferLoadDwordx4, ShaderInstructionFormat::Sdst4SvSoffset, {U""}},
{Recompile_SBufferLoadDwordx8_Sdst8SvSoffset, ShaderInstructionType::SBufferLoadDwordx8, ShaderInstructionFormat::Sdst8SvSoffset, {U""}},
{Recompile_SBufferLoadDwordx16_Sdst16SvSoffset, ShaderInstructionType::SBufferLoadDwordx16, ShaderInstructionFormat::Sdst16SvSoffset, {U""}},
{Recompile_SBufferLoadDwordx16_Sdst16SvSoffset, ShaderInstructionType::SBufferLoadDwordx16, ShaderInstructionFormat::Sdst16SvSoffset, {U""}},
{Recompile_SCbranchExecz_Label, ShaderInstructionType::SCbranchExecz, ShaderInstructionFormat::Label, {U""}},
{Recompile_SCbranchScc0_Label, ShaderInstructionType::SCbranchScc0, ShaderInstructionFormat::Label, {U""}},
{Recompile_SCbranchVccz_Label, ShaderInstructionType::SCbranchVccz, ShaderInstructionFormat::Label, {U""}},
{Recompile_SEndpgm_Empty, ShaderInstructionType::SEndpgm, ShaderInstructionFormat::Empty, {U""}},
@@ -4992,6 +5436,7 @@ static RecompilerFunc g_recomp_func[] = {
{Recompile_S_XXX_U32_SVdstSVsrc0SVsrc1, ShaderInstructionType::SAddU32, ShaderInstructionFormat::SVdstSVsrc0SVsrc1, {U"%ts_<index> = OpIAddCarry %ResTypeU %t0_<index> %t1_<index>", U"%t_<index> = OpCompositeExtract %uint %ts_<index> 0", U"%carry_<index> = OpCompositeExtract %uint %ts_<index> 1"}, SccCheck::CarryOut},
{Recompile_V_XXX_B32_SVdstSVsrc0SVsrc1, ShaderInstructionType::VAndB32, ShaderInstructionFormat::SVdstSVsrc0SVsrc1, {U"%t_<index> = OpBitwiseAnd %uint %t0_<index> %t1_<index>"}},
{Recompile_V_XXX_B32_SVdstSVsrc0SVsrc1, ShaderInstructionType::VBcntU32B32, ShaderInstructionFormat::SVdstSVsrc0SVsrc1, {U"%tb_<index> = OpBitCount %int %t0_<index>", U"%tbu_<index> = OpBitcast %uint %tb_<index>", U"%t_<index> = OpIAdd %uint %tbu_<index> %t1_<index>"}},
{Recompile_V_XXX_B32_SVdstSVsrc0SVsrc1, ShaderInstructionType::VBfmB32, ShaderInstructionFormat::SVdstSVsrc0SVsrc1, {U"%tcount_<index> = OpBitwiseAnd %uint %t0_<index> %uint_31", U"%toffset_<index> = OpBitwiseAnd %uint %t1_<index> %uint_31", U"%t_<index> = OpBitFieldInsert %uint %uint_0 %uint_0xffffffff %toffset_<index> %tcount_<index>"}},
{Recompile_V_XXX_B32_SVdstSVsrc0SVsrc1, ShaderInstructionType::VLshlB32, ShaderInstructionFormat::SVdstSVsrc0SVsrc1, {U"%ts_<index> = OpBitwiseAnd %uint %t1_<index> %uint_31", U"%t_<index> = OpShiftLeftLogical %uint %t0_<index> %ts_<index>"}},
{Recompile_V_XXX_B32_SVdstSVsrc0SVsrc1, ShaderInstructionType::VLshlrevB32, ShaderInstructionFormat::SVdstSVsrc0SVsrc1, {U"%ts_<index> = OpBitwiseAnd %uint %t0_<index> %uint_31", U"%t_<index> = OpShiftLeftLogical %uint %t1_<index> %ts_<index>"}},
{Recompile_V_XXX_B32_SVdstSVsrc0SVsrc1, ShaderInstructionType::VLshrB32, ShaderInstructionFormat::SVdstSVsrc0SVsrc1, {U"%ts_<index> = OpBitwiseAnd %uint %t1_<index> %uint_31", U"%t_<index> = OpShiftRightLogical %uint %t0_<index> %ts_<index>"}},
@@ -5001,7 +5446,7 @@ static RecompilerFunc g_recomp_func[] = {
{Recompile_V_XXX_B32_SVdstSVsrc0SVsrc1, ShaderInstructionType::VMulU32U24, ShaderInstructionFormat::SVdstSVsrc0SVsrc1, {U"%tu0_<index> = OpBitwiseAnd %uint %t0_<index> %uint_0x00ffffff", U"%tu1_<index> = OpBitwiseAnd %uint %t1_<index> %uint_0x00ffffff", U"%t_<index> = OpFunctionCall %uint %mul_lo_uint %tu0_<index> %tu1_<index>"}},
{Recompile_V_XXX_B32_SVdstSVsrc0SVsrc1, ShaderInstructionType::VOrB32, ShaderInstructionFormat::SVdstSVsrc0SVsrc1, {U"%t_<index> = OpBitwiseOr %uint %t0_<index> %t1_<index>"}},
{Recompile_V_XXX_B32_SVdstSVsrc0SVsrc1, ShaderInstructionType::VXorB32, ShaderInstructionFormat::SVdstSVsrc0SVsrc1, {U"%t_<index> = OpBitwiseXor %uint %t0_<index> %t1_<index>"}},
{Recompile_V_XXX_B32_SVdstSVsrc0SVsrc1, ShaderInstructionType::VBfmB32, ShaderInstructionFormat::SVdstSVsrc0SVsrc1, {U"%tcount_<index> = OpBitwiseAnd %uint %t0_<index> %uint_31", U"%toffset_<index> = OpBitwiseAnd %uint %t1_<index> %uint_31", U"%t_<index> = OpBitFieldInsert %uint %uint_0 %uint_0xffffffff %toffset_<index> %tcount_<index>"}},
{Recompile_V_XXX_F32_SVdstSVsrc0SVsrc1, ShaderInstructionType::VAddF32, ShaderInstructionFormat::SVdstSVsrc0SVsrc1, {U"%t_<index> = OpFAdd %float %t0_<index> %t1_<index>"}},
{Recompile_V_XXX_F32_SVdstSVsrc0SVsrc1, ShaderInstructionType::VMacF32, ShaderInstructionFormat::SVdstSVsrc0SVsrc1, {U"%t_<index> = OpExtInst %float %GLSL_std_450 Fma %t0_<index> %t1_<index> %tdst_<index>"}},
{Recompile_V_XXX_F32_SVdstSVsrc0SVsrc1, ShaderInstructionType::VMaxF32, ShaderInstructionFormat::SVdstSVsrc0SVsrc1, {U"%t_<index> = OpExtInst %float %GLSL_std_450 FMax %t0_<index> %t1_<index>"}},
{Recompile_V_XXX_F32_SVdstSVsrc0SVsrc1, ShaderInstructionType::VMinF32, ShaderInstructionFormat::SVdstSVsrc0SVsrc1, {U"%t_<index> = OpExtInst %float %GLSL_std_450 FMin %t0_<index> %t1_<index>"}},
@@ -5020,16 +5465,18 @@ static RecompilerFunc g_recomp_func[] = {
{Recompile_SMovB32_SVdstSVsrc0, ShaderInstructionType::SMovkI32, ShaderInstructionFormat::SVdstSVsrc0, {U""}},
{Recompile_V_XXX_B32_SVdstSVsrc0, ShaderInstructionType::VBfrevB32, ShaderInstructionFormat::SVdstSVsrc0, {U"%t_<index> = OpBitReverse %uint %t0_<index>"}},
{Recompile_V_XXX_B32_SVdstSVsrc0, ShaderInstructionType::VNotB32, ShaderInstructionFormat::SVdstSVsrc0, {U"%t_<index> = OpNot %uint %t0_<index>"}},
{Recompile_V_XXX_F32_SVdstSVsrc0, ShaderInstructionType::VRcpF32, ShaderInstructionFormat::SVdstSVsrc0, {U"%t_<index> = OpFDiv %float %float_1_000000 %t0_<index>"}},
{Recompile_V_XXX_F32_SVdstSVsrc0, ShaderInstructionType::VRsqF32, ShaderInstructionFormat::SVdstSVsrc0, {U"%t_<index> = OpExtInst %float %GLSL_std_450 InverseSqrt %t0_<index>"}},
{Recompile_V_XXX_F32_SVdstSVsrc0, ShaderInstructionType::VSqrtF32, ShaderInstructionFormat::SVdstSVsrc0, {U"%t_<index> = OpExtInst %float %GLSL_std_450 Sqrt %t0_<index>"}},
{Recompile_V_XXX_F32_SVdstSVsrc0, ShaderInstructionType::VCeilF32, ShaderInstructionFormat::SVdstSVsrc0, {U"%t_<index> = OpExtInst %float %GLSL_std_450 Ceil %t0_<index>"}},
{Recompile_V_XXX_F32_SVdstSVsrc0, ShaderInstructionType::VFloorF32, ShaderInstructionFormat::SVdstSVsrc0, {U"%t_<index> = OpExtInst %float %GLSL_std_450 Floor %t0_<index>"}},
{Recompile_V_XXX_F32_SVdstSVsrc0, ShaderInstructionType::VFractF32, ShaderInstructionFormat::SVdstSVsrc0, {U"%t_<index> = OpExtInst %float %GLSL_std_450 Fract %t0_<index>"}},
{Recompile_V_XXX_F32_SVdstSVsrc0, ShaderInstructionType::VRndneF32, ShaderInstructionFormat::SVdstSVsrc0, {U"%t_<index> = OpExtInst %float %GLSL_std_450 RoundEven %t0_<index>"}},
{Recompile_V_XXX_F32_SVdstSVsrc0, ShaderInstructionType::VTruncF32, ShaderInstructionFormat::SVdstSVsrc0, {U"%t_<index> = OpExtInst %float %GLSL_std_450 Trunc %t0_<index>"}},
{Recompile_V_XXX_F32_SVdstSVsrc0, ShaderInstructionType::VCosF32, ShaderInstructionFormat::SVdstSVsrc0, {U"%tr_<index> = OpFMul %float %t0_<index> %float_2pi", U"%t_<index> = OpExtInst %float %GLSL_std_450 Cos %tr_<index>"}},
{Recompile_V_XXX_F32_SVdstSVsrc0, ShaderInstructionType::VExpF32, ShaderInstructionFormat::SVdstSVsrc0, {U"%t_<index> = OpExtInst %float %GLSL_std_450 Exp2 %t0_<index>"}},
{Recompile_V_XXX_F32_SVdstSVsrc0, ShaderInstructionType::VFloorF32, ShaderInstructionFormat::SVdstSVsrc0, {U"%t_<index> = OpExtInst %float %GLSL_std_450 Floor %t0_<index>"}},
{Recompile_V_XXX_F32_SVdstSVsrc0, ShaderInstructionType::VFractF32, ShaderInstructionFormat::SVdstSVsrc0, {U"%t_<index> = OpExtInst %float %GLSL_std_450 Fract %t0_<index>"}},
{Recompile_V_XXX_F32_SVdstSVsrc0, ShaderInstructionType::VLogF32, ShaderInstructionFormat::SVdstSVsrc0, {U"%t_<index> = OpExtInst %float %GLSL_std_450 Log2 %t0_<index>"}},
{Recompile_V_XXX_F32_SVdstSVsrc0, ShaderInstructionType::VRcpF32, ShaderInstructionFormat::SVdstSVsrc0, {U"%t_<index> = OpFDiv %float %float_1_000000 %t0_<index>"}},
{Recompile_V_XXX_F32_SVdstSVsrc0, ShaderInstructionType::VRndneF32, ShaderInstructionFormat::SVdstSVsrc0, {U"%t_<index> = OpExtInst %float %GLSL_std_450 RoundEven %t0_<index>"}},
{Recompile_V_XXX_F32_SVdstSVsrc0, ShaderInstructionType::VRsqF32, ShaderInstructionFormat::SVdstSVsrc0, {U"%t_<index> = OpExtInst %float %GLSL_std_450 InverseSqrt %t0_<index>"}},
{Recompile_V_XXX_F32_SVdstSVsrc0, ShaderInstructionType::VSinF32, ShaderInstructionFormat::SVdstSVsrc0, {U"%tr_<index> = OpFMul %float %t0_<index> %float_2pi", U"%t_<index> = OpExtInst %float %GLSL_std_450 Sin %tr_<index>"}},
{Recompile_V_XXX_F32_SVdstSVsrc0, ShaderInstructionType::VSqrtF32, ShaderInstructionFormat::SVdstSVsrc0, {U"%t_<index> = OpExtInst %float %GLSL_std_450 Sqrt %t0_<index>"}},
{Recompile_V_XXX_F32_SVdstSVsrc0, ShaderInstructionType::VTruncF32, ShaderInstructionFormat::SVdstSVsrc0, {U"%t_<index> = OpExtInst %float %GLSL_std_450 Trunc %t0_<index>"}},
{Recompile_VCvt_XXX_F32_SVdstSVsrc0, ShaderInstructionType::VCvtU32F32, ShaderInstructionFormat::SVdstSVsrc0, {U"%t1_<index> = OpExtInst %float %GLSL_std_450 Trunc %t0_<index>", U"%t2_<index> = OpConvertFToU %uint %t1_<index>"}},
{Recompile_VCvtF32_XXX_SVdstSVsrc0, ShaderInstructionType::VCvtF32F16, ShaderInstructionFormat::SVdstSVsrc0, {U"%ts_<index> = OpExtInst %v2float %GLSL_std_450 UnpackHalf2x16 %t0_<index>", U"%t_<index> = OpCompositeExtract %float %ts_<index> 0"}},
{Recompile_VCvtF32_XXX_SVdstSVsrc0, ShaderInstructionType::VCvtF32I32, ShaderInstructionFormat::SVdstSVsrc0, {U"%ti_<index> = OpBitcast %int %t0_<index>", U"%t_<index> = OpConvertSToF %float %ti_<index>"}},
@@ -5047,8 +5494,9 @@ static RecompilerFunc g_recomp_func[] = {
{Recompile_SWaitcnt_Imm, ShaderInstructionType::SWaitcnt, ShaderInstructionFormat::Imm, {U""}},
{Recompile_TBufferLoadFormatX_Vdata1VaddrSvSoffsIdxenFloat1, ShaderInstructionType::TBufferLoadFormatX, ShaderInstructionFormat::Vdata1VaddrSvSoffsIdxenFloat1, {U""}},
{Recompile_TBufferLoadFormatXyzw_Vdata4Vaddr2SvSoffsOffenIdxenFloat4, ShaderInstructionType::TBufferLoadFormatXyzw, ShaderInstructionFormat::Vdata4Vaddr2SvSoffsOffenIdxenFloat4, {U""}},
{Recompile_TBufferLoadFormatXyzw_Vdata4VaddrSvSoffsIdxenFloat4, ShaderInstructionType::TBufferLoadFormatXyzw, ShaderInstructionFormat::Vdata4VaddrSvSoffsIdxenFloat4, {U""}},
{Recompile_TBufferLoadFormatXyzw_Vdata4Vaddr2SvSoffsOffenIdxenFloat4, ShaderInstructionType::TBufferLoadFormatXyzw, ShaderInstructionFormat::Vdata4Vaddr2SvSoffsOffenIdxenFloat4, {U""}},
{Recompile_V_XXX_U32_VdstSdst2Vsrc0Vsrc1, ShaderInstructionType::VAddI32, ShaderInstructionFormat::VdstSdst2Vsrc0Vsrc1, {U"%t_<index> = OpIAddCarry %ResTypeU %t0_<index> %t1_<index>"}},
{Recompile_V_XXX_U32_VdstSdst2Vsrc0Vsrc1, ShaderInstructionType::VSubI32, ShaderInstructionFormat::VdstSdst2Vsrc0Vsrc1, {U"%t_<index> = OpISubBorrow %ResTypeU %t0_<index> %t1_<index>"}},
@@ -5087,6 +5535,8 @@ static RecompilerFunc g_recomp_func[] = {
{Recompile_VCmp_XXX_U32_SmaskVsrc0Vsrc1, ShaderInstructionType::VCmpLtU32, ShaderInstructionFormat::SmaskVsrc0Vsrc1, {U"OpULessThan"}},
{Recompile_VCmp_XXX_U32_SmaskVsrc0Vsrc1, ShaderInstructionType::VCmpTU32, ShaderInstructionFormat::SmaskVsrc0Vsrc1, {U"OpIEqual %bool %uint_0 %uint_0 ; "}},
{Recompile_VCmpx_XXX_F32_SmaskVsrc0Vsrc1, ShaderInstructionType::VCmpxNeqF32, ShaderInstructionFormat::SmaskVsrc0Vsrc1, {U"OpFUnordNotEqual"}},
{Recompile_VCmpx_XXX_F32_SmaskVsrc0Vsrc1, ShaderInstructionType::VCmpxGtF32, ShaderInstructionFormat::SmaskVsrc0Vsrc1, {U"OpFOrdGreaterThan"}},
{Recompile_VCmpx_XXX_F32_SmaskVsrc0Vsrc1, ShaderInstructionType::VCmpxLtF32, ShaderInstructionFormat::SmaskVsrc0Vsrc1, {U"OpFOrdLessThan"}},
{Recompile_VCmpx_XXX_I32_SmaskVsrc0Vsrc1, ShaderInstructionType::VCmpxEqU32, ShaderInstructionFormat::SmaskVsrc0Vsrc1, {U"OpIEqual"}},
{Recompile_VCmpx_XXX_I32_SmaskVsrc0Vsrc1, ShaderInstructionType::VCmpxNeU32, ShaderInstructionFormat::SmaskVsrc0Vsrc1, {U"OpINotEqual"}},
{Recompile_VCmpx_XXX_U32_SmaskVsrc0Vsrc1, ShaderInstructionType::VCmpxGeU32, ShaderInstructionFormat::SmaskVsrc0Vsrc1, {U"OpUGreaterThanEqual"}},
@@ -5111,8 +5561,17 @@ static RecompilerFunc g_recomp_func[] = {
{Recompile_VInterpP2F32_VdstVsrcAttrChan, ShaderInstructionType::VInterpP2F32, ShaderInstructionFormat::VdstVsrcAttrChan, {U""}},
{Recompile_V_XXX_F32_VdstVsrc0Vsrc1Vsrc2, ShaderInstructionType::VMadF32, ShaderInstructionFormat::VdstVsrc0Vsrc1Vsrc2, {U"%t_<index> = OpExtInst %float %GLSL_std_450 Fma %t0_<index> %t1_<index> %t2_<index>"}},
{Recompile_V_XXX_F32_VdstVsrc0Vsrc1Vsrc2, ShaderInstructionType::VFmaF32, ShaderInstructionFormat::VdstVsrc0Vsrc1Vsrc2, {U"%t_<index> = OpExtInst %float %GLSL_std_450 Fma %t0_<index> %t1_<index> %t2_<index>"}},
{Recompile_V_XXX_F32_VdstVsrc0Vsrc1Vsrc2, ShaderInstructionType::VMadakF32, ShaderInstructionFormat::VdstVsrc0Vsrc1Vsrc2, {U"%t_<index> = OpExtInst %float %GLSL_std_450 Fma %t0_<index> %t1_<index> %t2_<index>"}},
{Recompile_V_XXX_F32_VdstVsrc0Vsrc1Vsrc2, ShaderInstructionType::VMadmkF32, ShaderInstructionFormat::VdstVsrc0Vsrc1Vsrc2, {U"%t_<index> = OpExtInst %float %GLSL_std_450 Fma %t0_<index> %t1_<index> %t2_<index>"}},
{Recompile_V_XXX_F32_VdstVsrc0Vsrc1Vsrc2, ShaderInstructionType::VMax3F32, ShaderInstructionFormat::VdstVsrc0Vsrc1Vsrc2, {U"%tm_<index> = OpExtInst %float %GLSL_std_450 FMax %t0_<index> %t1_<index>",
U"%t_<index> = OpExtInst %float %GLSL_std_450 FMax %tm_<index> %t2_<index>"}},
{Recompile_V_XXX_F32_VdstVsrc0Vsrc1Vsrc2, ShaderInstructionType::VMin3F32, ShaderInstructionFormat::VdstVsrc0Vsrc1Vsrc2, {U"%tm_<index> = OpExtInst %float %GLSL_std_450 FMin %t0_<index> %t1_<index>",
U"%t_<index> = OpExtInst %float %GLSL_std_450 FMin %tm_<index> %t2_<index>"}},
{Recompile_V_XXX_F32_VdstVsrc0Vsrc1Vsrc2, ShaderInstructionType::VMed3F32, ShaderInstructionFormat::VdstVsrc0Vsrc1Vsrc2, {U"%t3_<index> = OpExtInst %float %GLSL_std_450 FMin %t0_<index> %t1_<index>",
U"%t4_<index> = OpExtInst %float %GLSL_std_450 FMax %t0_<index> %t1_<index>",
U"%t5_<index> = OpExtInst %float %GLSL_std_450 FMin %t4_<index> %t2_<index>",
U"%t_<index> = OpExtInst %float %GLSL_std_450 FMax %t3_<index> %t5_<index>"}},
{Recompile_V_XXX_U32_VdstVsrc0Vsrc1Vsrc2, ShaderInstructionType::VSadU32, ShaderInstructionFormat::VdstVsrc0Vsrc1Vsrc2, {U"%td_<index> = OpFunctionCall %uint %abs_diff %t0_<index> %t1_<index>",
U"%t_<index> = OpIAdd %uint %td_<index> %t2_<index>"}},
{Recompile_V_XXX_U32_VdstVsrc0Vsrc1Vsrc2, ShaderInstructionType::VBfeU32, ShaderInstructionFormat::VdstVsrc0Vsrc1Vsrc2, {U"%to_<index> = OpBitwiseAnd %uint %t1_<index> %uint_31",
@@ -5317,22 +5776,10 @@ 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());
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());
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());
break;
default:
m_bind = nullptr;
// m_bind_params = ShaderBindParameters();
break;
case ShaderType::Pixel: m_bind = (m_ps_input_info != nullptr ? &m_ps_input_info->bind : nullptr); break;
case ShaderType::Vertex: m_bind = (m_vs_input_info != nullptr ? &m_vs_input_info->bind : nullptr); break;
case ShaderType::Compute: m_bind = (m_cs_input_info != nullptr ? &m_cs_input_info->bind : nullptr); break;
default: m_bind = nullptr; break;
}
WriteHeader();
@@ -5352,7 +5799,8 @@ void Spirv::WriteHeader()
{
static const char32_t* header = UR"(
; Header
OpCapability Shader
OpCapability Shader
OpCapability ImageQuery
<Extensions>
<Imports>
OpMemoryModel Logical GLSL450
@@ -5633,6 +6081,7 @@ void Spirv::WriteTypes()
%v2uint = OpTypeVector %uint 2
%v3uint = OpTypeVector %uint 3
%v4uint = OpTypeVector %uint 4
%v2int = OpTypeVector %int 2
%undef_v2uint = OpUndef %v2uint
%_ptr_Input_int = OpTypePointer Input %int
%_ptr_Input_uint = OpTypePointer Input %uint
@@ -6165,8 +6614,91 @@ void Spirv::WriteLocalVariables()
m_source += U"\n";
}
void Spirv::WriteLabel(int index)
{
if (index > 0)
{
const auto& instructions = m_code.GetInstructions();
const auto& inst = instructions.At(index);
auto& labels = m_code.GetLabels();
int labels_num = 0;
for (uint32_t i = labels.Size(); i > 0; i--)
{
auto& label = labels[i - 1];
if (!label.IsDisabled() && label.GetDst() == inst.pc)
{
static const char32_t* text = UR"(
<branch>
%<label> = OpLabel
)";
bool discard = m_code.IsDiscardBlock(label.GetDst());
bool skip_branch = (discard || (instructions.At(index - 1).type == ShaderInstructionType::SEndpgm && labels_num == 0));
m_source += String(text)
.ReplaceStr(U"<branch>", (skip_branch ? U"" : U"OpBranch %<label>"))
.ReplaceStr(U"<label>", label.ToString());
labels_num++;
if (discard)
{
label.Disable();
break;
}
}
}
}
}
void Spirv::ModifyCode()
{
struct DiscardLabel
{
uint32_t pc = 0;
int num = 0;
};
const auto& labels = m_code.GetLabels();
Vector<DiscardLabel> dls;
for (const auto& l: labels)
{
if (!l.IsDisabled())
{
int num = 0;
auto pc = l.GetDst();
for (const auto& l2: labels)
{
if (l2.GetDst() == pc)
{
num++;
}
}
EXIT_IF(num == 0);
if (num > 1 && m_code.IsDiscardBlock(pc))
{
if (!dls.Contains(pc, [](auto d, auto pc) { return d.pc == pc; }))
{
dls.Add(DiscardLabel({pc, num - 1}));
}
}
}
}
for (const auto& dl: dls)
{
auto block = m_code.GetDiscardBlock(dl.pc);
for (int i = 0; i < dl.num; i++)
{
// Duplicate discard block if there are different branches with the same label
m_code.GetInstructions().Add(block);
}
}
}
void Spirv::WriteInstructions()
{
ModifyCode();
int index = -1;
const auto& instructions = m_code.GetInstructions();
bool need_debug = (Config::SpirvDebugPrintfEnabled() && !m_code.GetDebugPrintfs().IsEmpty());
@@ -6174,25 +6706,7 @@ void Spirv::WriteInstructions()
{
index++;
const auto& labels = m_code.GetLabels();
for (uint32_t i = labels.Size(); i > 0; i--)
{
auto label = labels.At(i - 1);
if (index > 0 && label.GetDst() == inst.pc)
{
static const char32_t* text = UR"(
<branch>
%<label> = OpLabel
)";
auto prev_type = instructions.At(index - 1).type;
bool skip_branch = (prev_type == ShaderInstructionType::SEndpgm);
m_source += String(text)
.ReplaceStr(U"<branch>", (skip_branch ? U"" : U"OpBranch %<label>"))
.ReplaceStr(U"<label>", label.ToString());
}
}
WriteLabel(index);
String src = ShaderCode::DbgInstructionToStr(inst);
String dst;
@@ -6277,7 +6791,8 @@ void Spirv::WriteFunctions()
if (m_code.HasAnyOf({ShaderInstructionType::BufferLoadDword, ShaderInstructionType::BufferLoadFormatX,
ShaderInstructionType::BufferLoadFormatXy, ShaderInstructionType::BufferLoadFormatXyz,
ShaderInstructionType::BufferLoadFormatXyzw, ShaderInstructionType::TBufferLoadFormatXyzw}))
ShaderInstructionType::BufferLoadFormatXyzw, ShaderInstructionType::TBufferLoadFormatX,
ShaderInstructionType::TBufferLoadFormatXyzw}))
{
m_source += BUFFER_LOAD_FLOAT1;
m_source += BUFFER_LOAD_FLOAT4;
+346 -75
View File
@@ -1,6 +1,8 @@
#include "Emulator/Graphics/Tile.h"
#include "Kyty/Core/ArrayWrapper.h"
#include "Kyty/Core/DbgAssert.h"
#include "Kyty/Core/String.h"
#include "Kyty/Core/Threads.h"
#include "Emulator/Graphics/AsyncJob.h"
@@ -200,26 +202,36 @@ class Tiler1d
public:
uint32_t m_width = 0;
uint32_t m_height = 0;
uint32_t m_pitch = 0;
uint32_t m_bits_per_element = 0;
uint32_t m_tile_bytes = 0;
uint32_t m_tiles_per_row = 0;
void Init(uint32_t dfmt, uint32_t nfmt, uint32_t width, uint32_t height, uint32_t padded_width, uint32_t /*padded_height*/,
bool /*neo*/)
void Init(uint32_t dfmt, uint32_t nfmt, uint32_t width, uint32_t height, uint32_t pitch, uint32_t padded_width,
uint32_t /*padded_height*/, bool /*neo*/)
{
m_width = width;
m_height = height;
m_pitch = pitch;
if ((nfmt == 9 && dfmt == 10) || (nfmt == 0 && dfmt == 10))
{
// VK_FORMAT_R8G8B8A8_SRGB;
// R8G8B8A8
m_bits_per_element = 32;
} else if (nfmt == 9 && dfmt == 37)
} else if ((nfmt == 9 && dfmt == 37) || (nfmt == 0 && dfmt == 37) || (nfmt == 0 && dfmt == 36))
{
// VK_FORMAT_BC3_SRGB_BLOCK;
// BC2 or BC3
m_bits_per_element = 128;
m_width = std::max((m_width + 3) / 4, 1U);
m_height = std::max((m_height + 3) / 4, 1U);
m_pitch = std::max((m_pitch + 3) / 4, 1U);
} else if ((nfmt == 0 && dfmt == 35))
{
// BC1
m_bits_per_element = 64;
m_width = std::max((m_width + 3) / 4, 1U);
m_height = std::max((m_height + 3) / 4, 1U);
m_pitch = std::max((m_pitch + 3) / 4, 1U);
} else
{
EXIT("unknown format: nfmt = %u, dfmt = %u\n", nfmt, dfmt);
@@ -365,6 +377,29 @@ static void Detile32(const Tiler1d* t, uint32_t width, uint32_t height, uint32_t
}
}
static void Detile64(const Tiler1d* t, uint32_t width, uint32_t height, uint32_t dst_pitch, uint8_t* dst, const uint8_t* src, bool neo)
{
for (uint32_t y = 0; y < height; y++)
{
uint32_t x = 0;
uint64_t linear_offset = y * dst_pitch * 8;
for (; x + 1 < width; x += 2)
{
auto tiled_offset = t->GetTiledOffset(x, y, neo);
*reinterpret_cast<Uint128*>(dst + linear_offset) = *reinterpret_cast<const Uint128*>(src + tiled_offset);
linear_offset += 16;
}
if (x < width)
{
auto tiled_offset = t->GetTiledOffset(x, y, neo);
*reinterpret_cast<uint64_t*>(dst + linear_offset) = *reinterpret_cast<const uint64_t*>(src + tiled_offset);
}
}
}
static void Detile128(const Tiler1d* t, uint32_t width, uint32_t height, uint32_t dst_pitch, uint8_t* dst, const uint8_t* src, bool neo)
{
for (uint32_t y = 0; y < height; y++)
@@ -392,10 +427,13 @@ static void Detile1d(const Tiler1d* t, uint8_t* dst, const uint8_t* src, bool ne
{
if (t->m_bits_per_element == 32)
{
Detile32(t, t->m_width, t->m_height, t->m_width, dst, src, neo);
Detile32(t, t->m_width, t->m_height, t->m_pitch, dst, src, neo);
} else if (t->m_bits_per_element == 64)
{
Detile64(t, t->m_width, t->m_height, t->m_pitch, dst, src, neo);
} else if (t->m_bits_per_element == 128)
{
Detile128(t, t->m_width, t->m_height, t->m_width, dst, src, neo);
Detile128(t, t->m_width, t->m_height, t->m_pitch, dst, src, neo);
} else
{
EXIT("Unknown size");
@@ -415,7 +453,7 @@ void TileConvertTiledToLinear(void* dst, const void* src, TileMode mode, uint32_
}
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)
uint32_t pitch, uint32_t levels, bool neo)
{
EXIT_NOT_IMPLEMENTED(mode != TileMode::TextureTiled);
@@ -423,10 +461,11 @@ void TileConvertTiledToLinear(void* dst, const void* src, TileMode mode, uint32_
uint32_t padded_height[16] = {0};
uint32_t level_sizes[16] = {0};
TileGetTextureSize(dfmt, nfmt, width, height, width, levels, 13, neo, nullptr, level_sizes, padded_width, padded_height);
TileGetTextureSize(dfmt, nfmt, width, height, pitch, levels, 13, neo, nullptr, level_sizes, padded_width, padded_height);
uint32_t mip_width = width;
uint32_t mip_height = height;
uint32_t mip_pitch = pitch;
auto* dstptr = static_cast<uint8_t*>(dst);
const auto* srcptr = static_cast<const uint8_t*>(src);
@@ -434,7 +473,7 @@ void TileConvertTiledToLinear(void* dst, const void* src, TileMode mode, uint32_
for (uint32_t l = 0; l < levels; l++)
{
Tiler1d t;
t.Init(dfmt, nfmt, mip_width, mip_height, padded_width[l], padded_height[l], neo);
t.Init(dfmt, nfmt, mip_width, mip_height, mip_pitch, padded_width[l], padded_height[l], neo);
Detile1d(&t, dstptr, srcptr, neo);
@@ -449,6 +488,10 @@ void TileConvertTiledToLinear(void* dst, const void* src, TileMode mode, uint32_
{
mip_height /= 2;
}
if (mip_pitch > 1)
{
mip_pitch /= 2;
}
}
}
@@ -657,75 +700,277 @@ void TileGetVideoOutSize(uint32_t width, uint32_t height, uint32_t pitch, bool t
size->align = ret_align;
}
struct TilePadded
{
uint32_t width = 0;
uint32_t height = 0;
};
struct TextureInfo
{
uint32_t dfmt = 0;
uint32_t nfmt = 0;
uint32_t width = 0;
uint32_t height = 0;
uint32_t pitch = 0;
uint32_t levels = 0;
uint32_t tile = 0;
bool neo = false;
TileSizeAlign size[16];
TilePadded padded[16];
};
static void FindTextureInfo(uint32_t tile, uint32_t dfmt, uint32_t nfmt, const TextureInfo** info, int* num)
{
EXIT_IF(info == nullptr);
EXIT_IF(num == nullptr);
static const TextureInfo infos_8[] = {
// clang-format off
// kDataFormatB8G8R8A8UnormSrgb, 512, 512, 0, 0, kTileModeDisplay_LinearAligned
{ 10, 9, 512, 512, 512, 10, 8, false, {{1048576, 256}, {262144, 256}, {65536, 256}, {16384, 256}, {4096, 256}, {1024, 256}, {512, 256}, {256, 256}, {256, 256}, {256, 256}, }, { {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, } },
{ 10, 9, 512, 512, 512, 10, 8, true, {{1048576, 256}, {262144, 256}, {65536, 256}, {16384, 256}, {4096, 256}, {1024, 256}, {512, 256}, {256, 256}, {256, 256}, {256, 256}, }, { {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, } },
// kDataFormatR8Unorm, 2048, 2048, 0, 0, kTileModeDisplay_LinearAligned
{ 1, 0, 2048, 2048, 2048, 12, 8, false, {{4194304, 256}, {1048576, 256}, {262144, 256}, {65536, 256}, {16384, 256}, {4096, 256}, {2048, 256}, {1024, 256}, {512, 256}, {256, 256}, {256, 256}, {256, 256}, }, { {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, } },
{ 1, 0, 2048, 2048, 2048, 12, 8, true, {{4194304, 256}, {1048576, 256}, {262144, 256}, {65536, 256}, {16384, 256}, {4096, 256}, {2048, 256}, {1024, 256}, {512, 256}, {256, 256}, {256, 256}, {256, 256}, }, { {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, } },
// kDataFormatB8G8R8A8Unorm, 1, 1, 64, 0, kTileModeDisplay_LinearAligned
{ 10, 0, 1, 1, 64, 1, 8, false, {{256, 256}, }, { {0, 0}, } },
{ 10, 0, 1, 1, 64, 1, 8, true, {{256, 256}, }, { {0, 0}, } },
// clang-format on
};
static const TextureInfo infos_13_10_0[] = {
// clang-format off
// kDataFormatB8G8R8A8Unorm, 512, 512, 0, 0, kTileModeThin_1dThin
{ 10, 0, 512, 512, 512, 10, 13, false, {{1048576, 256}, {262144, 256}, {65536, 256}, {16384, 256}, {4096, 256}, {1024, 256}, {256, 256}, {256, 256}, {256, 256}, {256, 256}, }, { {512, 512}, {256, 256}, {128, 128}, {64, 64}, {32, 32}, {16, 16}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
{ 10, 0, 512, 512, 512, 10, 13, true, {{1048576, 256}, {262144, 256}, {65536, 256}, {16384, 256}, {4096, 256}, {1024, 256}, {256, 256}, {256, 256}, {256, 256}, {256, 256}, }, { {512, 512}, {256, 256}, {128, 128}, {64, 64}, {32, 32}, {16, 16}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
// kDataFormatB8G8R8A8Unorm, 1024, 1024, 0, 0, kTileModeThin_1dThin
{ 10, 0, 1024, 1024, 1024, 11, 13, false, {{4194304, 256}, {1048576, 256}, {262144, 256}, {65536, 256}, {16384, 256}, {4096, 256}, {1024, 256}, {256, 256}, {256, 256}, {256, 256}, {256, 256}, }, { {1024, 1024}, {512, 512}, {256, 256}, {128, 128}, {64, 64}, {32, 32}, {16, 16}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
{ 10, 0, 1024, 1024, 1024, 11, 13, true, {{4194304, 256}, {1048576, 256}, {262144, 256}, {65536, 256}, {16384, 256}, {4096, 256}, {1024, 256}, {256, 256}, {256, 256}, {256, 256}, {256, 256}, }, { {1024, 1024}, {512, 512}, {256, 256}, {128, 128}, {64, 64}, {32, 32}, {16, 16}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
// kDataFormatB8G8R8A8Unorm, 2048, 2048, 0, 0, kTileModeThin_1dThin
{ 10, 0, 2048, 2048, 2048, 12, 13, false, {{16777216, 256}, {4194304, 256}, {1048576, 256}, {262144, 256}, {65536, 256}, {16384, 256}, {4096, 256}, {1024, 256}, {256, 256}, {256, 256}, {256, 256}, {256, 256}, }, { {2048, 2048}, {1024, 1024}, {512, 512}, {256, 256}, {128, 128}, {64, 64}, {32, 32}, {16, 16}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
{ 10, 0, 2048, 2048, 2048, 12, 13, true, {{16777216, 256}, {4194304, 256}, {1048576, 256}, {262144, 256}, {65536, 256}, {16384, 256}, {4096, 256}, {1024, 256}, {256, 256}, {256, 256}, {256, 256}, {256, 256}, }, { {2048, 2048}, {1024, 1024}, {512, 512}, {256, 256}, {128, 128}, {64, 64}, {32, 32}, {16, 16}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
// kDataFormatB8G8R8A8Unorm, 512, 768, 0, 0, kTileModeThin_1dThin
{ 10, 0, 512, 768, 512, 10, 13, false, {{1572864, 256}, {1048576, 256}, {131072, 256}, {32768, 256}, {8192, 256}, {2048, 256}, {512, 256}, {256, 256}, {256, 256}, {256, 256}, }, { {512, 768}, {256, 512}, {128, 256}, {64, 128}, {32, 64}, {16, 32}, {8, 16}, {8, 8}, {8, 8}, {8, 8}, } },
{ 10, 0, 512, 768, 512, 10, 13, true, {{1572864, 256}, {1048576, 256}, {131072, 256}, {32768, 256}, {8192, 256}, {2048, 256}, {512, 256}, {256, 256}, {256, 256}, {256, 256}, }, { {512, 768}, {256, 512}, {128, 256}, {64, 128}, {32, 64}, {16, 32}, {8, 16}, {8, 8}, {8, 8}, {8, 8}, } },
// clang-format on
};
static const TextureInfo infos_13_10_9[] = {
// clang-format off
// kDataFormatB8G8R8A8UnormSrgb, 512, 512, 0, 0, kTileModeThin_1dThin
{ 10, 9, 512, 512, 512, 10, 13, false, {{1048576, 256}, {262144, 256}, {65536, 256}, {16384, 256}, {4096, 256}, {1024, 256}, {256, 256}, {256, 256}, {256, 256}, {256, 256}, }, { {512, 512}, {256, 256}, {128, 128}, {64, 64}, {32, 32}, {16, 16}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
{ 10, 9, 512, 512, 512, 10, 13, true, {{1048576, 256}, {262144, 256}, {65536, 256}, {16384, 256}, {4096, 256}, {1024, 256}, {256, 256}, {256, 256}, {256, 256}, {256, 256}, }, { {512, 512}, {256, 256}, {128, 128}, {64, 64}, {32, 32}, {16, 16}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
// clang-format on
};
static const TextureInfo infos_13_35_0[] = {
// clang-format off
// kDataFormatBc1Unorm, 256, 64, 0, 0, kTileModeThin_1dThin
{ 35, 0, 256, 64, 256, 9, 13, false, {{8192, 256}, {2048, 256}, {1024, 256}, {512, 256}, {512, 256}, {512, 256}, {512, 256}, {512, 256}, {512, 256}, }, { {64, 16}, {32, 8}, {16, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
{ 35, 0, 256, 64, 256, 9, 13, true, {{8192, 256}, {2048, 256}, {1024, 256}, {512, 256}, {512, 256}, {512, 256}, {512, 256}, {512, 256}, {512, 256}, }, { {64, 16}, {32, 8}, {16, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
// kDataFormatBc1Unorm, 256, 256, 0, 0, kTileModeThin_1dThin
{ 35, 0, 256, 256, 256, 9, 13, false, {{32768, 256}, {8192, 256}, {2048, 256}, {512, 256}, {512, 256}, {512, 256}, {512, 256}, {512, 256}, {512, 256}, }, { {64, 64}, {32, 32}, {16, 16}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
{ 35, 0, 256, 256, 256, 9, 13, true, {{32768, 256}, {8192, 256}, {2048, 256}, {512, 256}, {512, 256}, {512, 256}, {512, 256}, {512, 256}, {512, 256}, }, { {64, 64}, {32, 32}, {16, 16}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
// kDataFormatBc1Unorm, 512, 512, 0, 0, kTileModeThin_1dThin
{ 35, 0, 512, 512, 512, 10, 13, false, {{131072, 256}, {32768, 256}, {8192, 256}, {2048, 256}, {512, 256}, {512, 256}, {512, 256}, {512, 256}, {512, 256}, {512, 256}, }, { {128, 128}, {64, 64}, {32, 32}, {16, 16}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
{ 35, 0, 512, 512, 512, 10, 13, true, {{131072, 256}, {32768, 256}, {8192, 256}, {2048, 256}, {512, 256}, {512, 256}, {512, 256}, {512, 256}, {512, 256}, {512, 256}, }, { {128, 128}, {64, 64}, {32, 32}, {16, 16}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
// kDataFormatBc1Unorm, 1024, 512, 0, 0, kTileModeThin_1dThin
{ 35, 0, 1024, 512, 1024, 11, 13, false, {{262144, 256}, {65536, 256}, {16384, 256}, {4096, 256}, {1024, 256}, {512, 256}, {512, 256}, {512, 256}, {512, 256}, {512, 256}, {512, 256}, }, { {256, 128}, {128, 64}, {64, 32}, {32, 16}, {16, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
{ 35, 0, 1024, 512, 1024, 11, 13, true, {{262144, 256}, {65536, 256}, {16384, 256}, {4096, 256}, {1024, 256}, {512, 256}, {512, 256}, {512, 256}, {512, 256}, {512, 256}, {512, 256}, }, { {256, 128}, {128, 64}, {64, 32}, {32, 16}, {16, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
// kDataFormatBc1Unorm, 1024, 1024, 0, 0, kTileModeThin_1dThin
{ 35, 0, 1024, 1024, 1024, 11, 13, false, {{524288, 256}, {131072, 256}, {32768, 256}, {8192, 256}, {2048, 256}, {512, 256}, {512, 256}, {512, 256}, {512, 256}, {512, 256}, {512, 256}, }, { {256, 256}, {128, 128}, {64, 64}, {32, 32}, {16, 16}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
{ 35, 0, 1024, 1024, 1024, 11, 13, true, {{524288, 256}, {131072, 256}, {32768, 256}, {8192, 256}, {2048, 256}, {512, 256}, {512, 256}, {512, 256}, {512, 256}, {512, 256}, {512, 256}, }, { {256, 256}, {128, 128}, {64, 64}, {32, 32}, {16, 16}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
// kDataFormatBc1Unorm, 2048, 1024, 0, 0, kTileModeThin_1dThin
{ 35, 0, 2048, 1024, 2048, 12, 13, false, {{1048576, 256}, {262144, 256}, {65536, 256}, {16384, 256}, {4096, 256}, {1024, 256}, {512, 256}, {512, 256}, {512, 256}, {512, 256}, {512, 256}, {512, 256}, }, { {512, 256}, {256, 128}, {128, 64}, {64, 32}, {32, 16}, {16, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
{ 35, 0, 2048, 1024, 2048, 12, 13, true, {{1048576, 256}, {262144, 256}, {65536, 256}, {16384, 256}, {4096, 256}, {1024, 256}, {512, 256}, {512, 256}, {512, 256}, {512, 256}, {512, 256}, {512, 256}, }, { {512, 256}, {256, 128}, {128, 64}, {64, 32}, {32, 16}, {16, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
// kDataFormatBc1Unorm, 2048, 2048, 0, 0, kTileModeThin_1dThin
{ 35, 0, 2048, 2048, 2048, 12, 13, false, {{2097152, 256}, {524288, 256}, {131072, 256}, {32768, 256}, {8192, 256}, {2048, 256}, {512, 256}, {512, 256}, {512, 256}, {512, 256}, {512, 256}, {512, 256}, }, { {512, 512}, {256, 256}, {128, 128}, {64, 64}, {32, 32}, {16, 16}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
{ 35, 0, 2048, 2048, 2048, 12, 13, true, {{2097152, 256}, {524288, 256}, {131072, 256}, {32768, 256}, {8192, 256}, {2048, 256}, {512, 256}, {512, 256}, {512, 256}, {512, 256}, {512, 256}, {512, 256}, }, { {512, 512}, {256, 256}, {128, 128}, {64, 64}, {32, 32}, {16, 16}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
// kDataFormatBc1Unorm, 1920, 1080, 1920, 1, kTileModeThin_1dThin
{ 35, 0, 1920, 1080, 1920, 1, 13, false, {{1044480, 256}, }, { {480, 272}, } },
{ 35, 0, 1920, 1080, 1920, 1, 13, true, {{1044480, 256}, }, { {480, 272}, } },
// clang-format on
};
static const TextureInfo infos_13_36_0[] = {
// clang-format off
// kDataFormatBc2Unorm, 1, 32, 0, 0, kTileModeThin_1dThin
{ 36, 0, 1, 32, 32, 6, 13, false, {{1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, }, { {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
{ 36, 0, 1, 32, 32, 6, 13, true, {{1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, }, { {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
// kDataFormatBc2Unorm, 8, 32, 0, 0, kTileModeThin_1dThin
{ 36, 0, 8, 32, 32, 6, 13, false, {{1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, }, { {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
{ 36, 0, 8, 32, 32, 6, 13, true, {{1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, }, { {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
// kDataFormatBc2Unorm, 2048, 2048, 0, 0, kTileModeThin_1dThin
{ 36, 0, 2048, 2048, 2048, 12, 13, false, {{4194304, 256}, {1048576, 256}, {262144, 256}, {65536, 256}, {16384, 256}, {4096, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, }, { {512, 512}, {256, 256}, {128, 128}, {64, 64}, {32, 32}, {16, 16}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
{ 36, 0, 2048, 2048, 2048, 12, 13, true, {{4194304, 256}, {1048576, 256}, {262144, 256}, {65536, 256}, {16384, 256}, {4096, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, }, { {512, 512}, {256, 256}, {128, 128}, {64, 64}, {32, 32}, {16, 16}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
// kDataFormatBc2Unorm, 4096, 4096, 0, 0, kTileModeThin_1dThin
{ 36, 0, 4096, 4096, 4096, 13, 13, false, {{16777216, 256}, {4194304, 256}, {1048576, 256}, {262144, 256}, {65536, 256}, {16384, 256}, {4096, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, }, { {1024, 1024}, {512, 512}, {256, 256}, {128, 128}, {64, 64}, {32, 32}, {16, 16}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
{ 36, 0, 4096, 4096, 4096, 13, 13, true, {{16777216, 256}, {4194304, 256}, {1048576, 256}, {262144, 256}, {65536, 256}, {16384, 256}, {4096, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, }, { {1024, 1024}, {512, 512}, {256, 256}, {128, 128}, {64, 64}, {32, 32}, {16, 16}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
// kDataFormatBc2Unorm, 8192, 8192, 0, 0, kTileModeThin_1dThin
{ 36, 0, 8192, 8192, 8192, 14, 13, false, {{67108864, 256}, {16777216, 256}, {4194304, 256}, {1048576, 256}, {262144, 256}, {65536, 256}, {16384, 256}, {4096, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, }, { {2048, 2048}, {1024, 1024}, {512, 512}, {256, 256}, {128, 128}, {64, 64}, {32, 32}, {16, 16}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
{ 36, 0, 8192, 8192, 8192, 14, 13, true, {{67108864, 256}, {16777216, 256}, {4194304, 256}, {1048576, 256}, {262144, 256}, {65536, 256}, {16384, 256}, {4096, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, }, { {2048, 2048}, {1024, 1024}, {512, 512}, {256, 256}, {128, 128}, {64, 64}, {32, 32}, {16, 16}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
// clang-format on
};
static const TextureInfo infos_13_37_0[] = {
// clang-format off
// kDataFormatBc3Unorm, 16, 32, 0, 0, kTileModeThin_1dThin
{ 37, 0, 16, 32, 32, 6, 13, false, {{1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, }, { {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
{ 37, 0, 16, 32, 32, 6, 13, true, {{1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, }, { {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
// kDataFormatBc3Unorm, 32, 32, 0, 0, kTileModeThin_1dThin
{ 37, 0, 32, 32, 32, 6, 13, false, {{1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, }, { {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
{ 37, 0, 32, 32, 32, 6, 13, true, {{1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, }, { {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
// kDataFormatBc3Unorm, 64, 64, 0, 0, kTileModeThin_1dThin
{ 37, 0, 64, 64, 64, 7, 13, false, {{4096, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, }, { {16, 16}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
{ 37, 0, 64, 64, 64, 7, 13, true, {{4096, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, }, { {16, 16}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
// kDataFormatBc3Unorm, 128, 128, 0, 0, kTileModeThin_1dThin
{ 37, 0, 128, 128, 128, 8, 13, false, {{16384, 256}, {4096, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, }, { {32, 32}, {16, 16}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
{ 37, 0, 128, 128, 128, 8, 13, true, {{16384, 256}, {4096, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, }, { {32, 32}, {16, 16}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
// kDataFormatBc3Unorm, 256, 256, 0, 0, kTileModeThin_1dThin
{ 37, 0, 256, 256, 256, 9, 13, false, {{65536, 256}, {16384, 256}, {4096, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, }, { {64, 64}, {32, 32}, {16, 16}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
{ 37, 0, 256, 256, 256, 9, 13, true, {{65536, 256}, {16384, 256}, {4096, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, }, { {64, 64}, {32, 32}, {16, 16}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
// kDataFormatBc3Unorm, 512, 512, 0, 0, kTileModeThin_1dThin
{ 37, 0, 512, 512, 512, 10, 13, false, {{262144, 256}, {65536, 256}, {16384, 256}, {4096, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, }, { {128, 128}, {64, 64}, {32, 32}, {16, 16}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
{ 37, 0, 512, 512, 512, 10, 13, true, {{262144, 256}, {65536, 256}, {16384, 256}, {4096, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, }, { {128, 128}, {64, 64}, {32, 32}, {16, 16}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
// kDataFormatBc3Unorm, 1024, 256, 0, 0, kTileModeThin_1dThin
{ 37, 0, 1024, 256, 1024, 11, 13, false, {{262144, 256}, {65536, 256}, {16384, 256}, {4096, 256}, {2048, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, }, { {256, 64}, {128, 32}, {64, 16}, {32, 8}, {16, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
{ 37, 0, 1024, 256, 1024, 11, 13, true, {{262144, 256}, {65536, 256}, {16384, 256}, {4096, 256}, {2048, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, }, { {256, 64}, {128, 32}, {64, 16}, {32, 8}, {16, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
// kDataFormatBc3Unorm, 1024, 512, 0, 0, kTileModeThin_1dThin
{ 37, 0, 1024, 512, 1024, 11, 13, false, {{524288, 256}, {131072, 256}, {32768, 256}, {8192, 256}, {2048, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, }, { {256, 128}, {128, 64}, {64, 32}, {32, 16}, {16, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
{ 37, 0, 1024, 512, 1024, 11, 13, true, {{524288, 256}, {131072, 256}, {32768, 256}, {8192, 256}, {2048, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, }, { {256, 128}, {128, 64}, {64, 32}, {32, 16}, {16, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
// kDataFormatBc3Unorm, 1024, 1024, 0, 0, kTileModeThin_1dThin
{ 37, 0, 1024, 1024, 1024, 11, 13, false, {{1048576, 256}, {262144, 256}, {65536, 256}, {16384, 256}, {4096, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, }, { {256, 256}, {128, 128}, {64, 64}, {32, 32}, {16, 16}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
{ 37, 0, 1024, 1024, 1024, 11, 13, true, {{1048576, 256}, {262144, 256}, {65536, 256}, {16384, 256}, {4096, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, }, { {256, 256}, {128, 128}, {64, 64}, {32, 32}, {16, 16}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
// kDataFormatBc3Unorm, 2048, 128, 0, 0, kTileModeThin_1dThin
{ 37, 0, 2048, 128, 2048, 12, 13, false, {{262144, 256}, {65536, 256}, {16384, 256}, {8192, 256}, {4096, 256}, {2048, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, }, { {512, 32}, {256, 16}, {128, 8}, {64, 8}, {32, 8}, {16, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
{ 37, 0, 2048, 128, 2048, 12, 13, true, {{262144, 256}, {65536, 256}, {16384, 256}, {8192, 256}, {4096, 256}, {2048, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, }, { {512, 32}, {256, 16}, {128, 8}, {64, 8}, {32, 8}, {16, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
// kDataFormatBc3Unorm, 2048, 2048, 0, 0, kTileModeThin_1dThin
{ 37, 0, 2048, 2048, 2048, 12, 13, false, {{4194304, 256}, {1048576, 256}, {262144, 256}, {65536, 256}, {16384, 256}, {4096, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, }, { {512, 512}, {256, 256}, {128, 128}, {64, 64}, {32, 32}, {16, 16}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
{ 37, 0, 2048, 2048, 2048, 12, 13, true, {{4194304, 256}, {1048576, 256}, {262144, 256}, {65536, 256}, {16384, 256}, {4096, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, }, { {512, 512}, {256, 256}, {128, 128}, {64, 64}, {32, 32}, {16, 16}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
// kDataFormatBc3Unorm, 256, 32, 0, 0, kTileModeThin_1dThin
{ 37, 0, 256, 32, 256, 9, 13, false, {{8192, 256}, {4096, 256}, {2048, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, }, { {64, 8}, {32, 8}, {16, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
{ 37, 0, 256, 32, 256, 9, 13, true, {{8192, 256}, {4096, 256}, {2048, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, }, { {64, 8}, {32, 8}, {16, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
// kDataFormatBc3Unorm, 256, 64, 0, 0, kTileModeThin_1dThin
{ 37, 0, 256, 64, 256, 9, 13, false, {{16384, 256}, {4096, 256}, {2048, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, }, { {64, 16}, {32, 8}, {16, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
{ 37, 0, 256, 64, 256, 9, 13, true, {{16384, 256}, {4096, 256}, {2048, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, }, { {64, 16}, {32, 8}, {16, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
// kDataFormatBc3Unorm, 256, 128, 0, 0, kTileModeThin_1dThin
{ 37, 0, 256, 128, 256, 9, 13, false, {{32768, 256}, {8192, 256}, {2048, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, }, { {64, 32}, {32, 16}, {16, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
{ 37, 0, 256, 128, 256, 9, 13, true, {{32768, 256}, {8192, 256}, {2048, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, }, { {64, 32}, {32, 16}, {16, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
// kDataFormatBc3Unorm, 512, 256, 0, 0, kTileModeThin_1dThin
{ 37, 0, 512, 256, 512, 10, 13, false, {{131072, 256}, {32768, 256}, {8192, 256}, {2048, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, }, { {128, 64}, {64, 32}, {32, 16}, {16, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
{ 37, 0, 512, 256, 512, 10, 13, true, {{131072, 256}, {32768, 256}, {8192, 256}, {2048, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, }, { {128, 64}, {64, 32}, {32, 16}, {16, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
// kDataFormatBc3Unorm, 1920, 1080, 1920, 1, kTileModeThin_1dThin
{ 37, 0, 1920, 1080, 1920, 1, 13, false, {{2088960, 256}, }, { {480, 272}, } },
{ 37, 0, 1920, 1080, 1920, 1, 13, true, {{2088960, 256}, }, { {480, 272}, } },
// clang-format on
};
static const TextureInfo infos_13_37_9[] = {
// clang-format off
// kDataFormatBc3UnormSrgb, 512, 512, 0, 0, kTileModeThin_1dThin
{ 37, 9, 512, 512, 512, 10, 13, false, {{262144, 256}, {65536, 256}, {16384, 256}, {4096, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, }, { {128, 128}, {64, 64}, {32, 32}, {16, 16}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
{ 37, 9, 512, 512, 512, 10, 13, true, {{262144, 256}, {65536, 256}, {16384, 256}, {4096, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, }, { {128, 128}, {64, 64}, {32, 32}, {16, 16}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
// clang-format on
};
static const TextureInfo infos_14[] = {
// clang-format off
// kDataFormatB8G8R8A8Unorm, 256, 256, 0, 0, kTileModeThin_2dThin
{ 10, 0, 256, 256, 256, 9, 14, false, {{262144, 32768}, {65536, 32768}, {16384, 32768}, {4096, 32768}, {1024, 32768}, {256, 32768}, {256, 32768}, {256, 32768}, {256, 32768}, }, { {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, } },
{ 10, 0, 256, 256, 256, 9, 14, true, {{262144, 65536}, {65536, 65536}, {16384, 65536}, {4096, 65536}, {1024, 65536}, {256, 65536}, {256, 65536}, {256, 65536}, {256, 65536}, }, { {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, } },
// clang-format on
};
static const TextureInfo infos_10[] = {
// clang-format off
// kDataFormatB8G8R8A8Unorm, 96, 96, 128, 1, kTileModeDisplay_2dThin
{ 10, 0, 96, 96, 128, 1, 10, false, {{65536, 32768}, }, { {0, 0}, } },
{ 10, 0, 96, 96, 128, 1, 10, true, {{65536, 65536}, }, { {0, 0}, } },
// kDataFormatB8G8R8A8Unorm, 128, 128, 128, 1, kTileModeDisplay_2dThin
{ 10, 0, 128, 128, 128, 1, 10, false, {{65536, 32768}, }, { {0, 0}, } },
{ 10, 0, 128, 128, 128, 1, 10, true, {{65536, 65536}, }, { {0, 0}, } },
// kDataFormatB8G8R8A8Unorm, 960, 540, 1024, 1, kTileModeDisplay_2dThin
{ 10, 0, 960, 540, 1024, 1, 10, false, {{2359296, 32768}, }, { {0, 0}, } },
{ 10, 0, 960, 540, 1024, 1, 10, true, {{2621440, 65536}, }, { {0, 0}, } },
// kDataFormatB8G8R8A8Unorm, 1920, 1080, 1920, 1, kTileModeDisplay_2dThin
{ 10, 0, 1920, 1080, 1920, 1, 10, false, {{8355840, 32768}, }, { {0, 0}, } },
{ 10, 0, 1920, 1080, 1920, 1, 10, true, {{8847360, 65536}, }, { {0, 0}, } },
// kDataFormatB8G8R8A8Unorm, 3840, 2160, 3840, 1, kTileModeDisplay_2dThin
{ 10, 0, 3840, 2160, 3840, 1, 10, false, {{33423360, 32768}, }, { {0, 0}, } },
{ 10, 0, 3840, 2160, 3840, 1, 10, true, {{33423360, 65536}, }, { {0, 0}, } },
// kDataFormatB8G8R8A8Unorm, 4096, 4096, 4096, 1, kTileModeDisplay_2dThin
{ 10, 0, 4096, 4096, 4096, 1, 10, false, {{67108864, 32768}, }, { {0, 0}, } },
{ 10, 0, 4096, 4096, 4096, 1, 10, true, {{67108864, 65536}, }, { {0, 0}, } },
// kDataFormatB8G8R8A8Unorm, 8192, 4096, 8192, 1, kTileModeDisplay_2dThin
{ 10, 0, 8192, 4096, 8192, 1, 10, false, {{134217728, 32768}, }, { {0, 0}, } },
{ 10, 0, 8192, 4096, 8192, 1, 10, true, {{134217728, 65536}, }, { {0, 0}, } },
// clang-format on
};
static const TextureInfo infos_2[] = {
// clang-format off
// kDataFormatR32Float, 1920, 1080, 1920, 1, kTileModeDepth_2dThin_256
{ 4, 7, 1920, 1080, 1920, 1, 2, false, {{8355840, 32768}, }, { {0, 0}, } },
{ 4, 7, 1920, 1080, 1920, 1, 2, true, {{8847360, 65536}, }, { {0, 0}, } },
// clang-format on
};
switch (tile)
{
case 8:
*info = infos_8;
*num = KYTY_ARRAY_NUM(infos_8);
break;
case 13:
if (dfmt == 10 && nfmt == 0)
{
*info = infos_13_10_0;
*num = KYTY_ARRAY_NUM(infos_13_10_0);
} else if (dfmt == 10 && nfmt == 9)
{
*info = infos_13_10_9;
*num = KYTY_ARRAY_NUM(infos_13_10_9);
} else if (dfmt == 35 && nfmt == 0)
{
*info = infos_13_35_0;
*num = KYTY_ARRAY_NUM(infos_13_35_0);
} else if (dfmt == 36 && nfmt == 0)
{
*info = infos_13_36_0;
*num = KYTY_ARRAY_NUM(infos_13_36_0);
} else if (dfmt == 37 && nfmt == 0)
{
*info = infos_13_37_0;
*num = KYTY_ARRAY_NUM(infos_13_37_0);
} else if (dfmt == 37 && nfmt == 9)
{
*info = infos_13_37_9;
*num = KYTY_ARRAY_NUM(infos_13_37_9);
}
break;
case 14:
*info = infos_14;
*num = KYTY_ARRAY_NUM(infos_14);
break;
case 10:
*info = infos_10;
*num = KYTY_ARRAY_NUM(infos_10);
break;
case 2:
*info = infos_2;
*num = KYTY_ARRAY_NUM(infos_2);
break;
default: *info = nullptr; *num = 0;
}
}
void TileGetTextureSize(uint32_t dfmt, uint32_t nfmt, uint32_t width, uint32_t height, uint32_t pitch, uint32_t levels, uint32_t tile,
bool neo, TileSizeAlign* total_size, uint32_t* level_sizes, uint32_t* padded_width, uint32_t* padded_height)
{
KYTY_PROFILER_FUNCTION();
struct Padded
{
uint32_t width = 0;
uint32_t height = 0;
};
struct TextureInfo
{
uint32_t dfmt = 0;
uint32_t nfmt = 0;
uint32_t width = 0;
uint32_t height = 0;
uint32_t pitch = 0;
uint32_t levels = 0;
uint32_t tile = 0;
bool neo = false;
TileSizeAlign size[16];
Padded padded[16];
};
static const TextureInfo infos[] = {
// clang-format off
// kDataFormatB8G8R8A8UnormSrgb, 512, 512, 0, 0, kTileModeDisplay_LinearAligned
{ 10, 9, 512, 512, 512, 10, 8, false, {{1048576, 256}, {262144, 256}, {65536, 256}, {16384, 256}, {4096, 256}, {1024, 256}, {512, 256}, {256, 256}, {256, 256}, {256, 256}, }, { {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, } },
{ 10, 9, 512, 512, 512, 10, 8, true, {{1048576, 256}, {262144, 256}, {65536, 256}, {16384, 256}, {4096, 256}, {1024, 256}, {512, 256}, {256, 256}, {256, 256}, {256, 256}, }, { {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, } },
// kDataFormatB8G8R8A8UnormSrgb, 512, 512, 0, 0, kTileModeThin_1dThin
{ 10, 9, 512, 512, 512, 10, 13, false, {{1048576, 256}, {262144, 256}, {65536, 256}, {16384, 256}, {4096, 256}, {1024, 256}, {256, 256}, {256, 256}, {256, 256}, {256, 256}, }, { {512, 512}, {256, 256}, {128, 128}, {64, 64}, {32, 32}, {16, 16}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
{ 10, 9, 512, 512, 512, 10, 13, true, {{1048576, 256}, {262144, 256}, {65536, 256}, {16384, 256}, {4096, 256}, {1024, 256}, {256, 256}, {256, 256}, {256, 256}, {256, 256}, }, { {512, 512}, {256, 256}, {128, 128}, {64, 64}, {32, 32}, {16, 16}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
// kDataFormatBc3UnormSrgb, 512, 512, 0, 0, kTileModeThin_1dThin
{ 37, 9, 512, 512, 512, 10, 13, false, {{262144, 256}, {65536, 256}, {16384, 256}, {4096, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, }, { {128, 128}, {64, 64}, {32, 32}, {16, 16}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
{ 37, 9, 512, 512, 512, 10, 13, true, {{262144, 256}, {65536, 256}, {16384, 256}, {4096, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, {1024, 256}, }, { {128, 128}, {64, 64}, {32, 32}, {16, 16}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
// kDataFormatB8G8R8A8Unorm, 512, 512, 0, 0, kTileModeThin_1dThin
{ 10, 0, 512, 512, 512, 10, 13, false, {{1048576, 256}, {262144, 256}, {65536, 256}, {16384, 256}, {4096, 256}, {1024, 256}, {256, 256}, {256, 256}, {256, 256}, {256, 256}, }, { {512, 512}, {256, 256}, {128, 128}, {64, 64}, {32, 32}, {16, 16}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
{ 10, 0, 512, 512, 512, 10, 13, true, {{1048576, 256}, {262144, 256}, {65536, 256}, {16384, 256}, {4096, 256}, {1024, 256}, {256, 256}, {256, 256}, {256, 256}, {256, 256}, }, { {512, 512}, {256, 256}, {128, 128}, {64, 64}, {32, 32}, {16, 16}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
// kDataFormatB8G8R8A8Unorm, 512, 768, 0, 0, kTileModeThin_1dThin
{ 10, 0, 512, 768, 512, 10, 13, false, {{1572864, 256}, {1048576, 256}, {131072, 256}, {32768, 256}, {8192, 256}, {2048, 256}, {512, 256}, {256, 256}, {256, 256}, {256, 256}, }, { {512, 768}, {256, 512}, {128, 256}, {64, 128}, {32, 64}, {16, 32}, {8, 16}, {8, 8}, {8, 8}, {8, 8}, } },
{ 10, 0, 512, 768, 512, 10, 13, true, {{1572864, 256}, {1048576, 256}, {131072, 256}, {32768, 256}, {8192, 256}, {2048, 256}, {512, 256}, {256, 256}, {256, 256}, {256, 256}, }, { {512, 768}, {256, 512}, {128, 256}, {64, 128}, {32, 64}, {16, 32}, {8, 16}, {8, 8}, {8, 8}, {8, 8}, } },
// kDataFormatB8G8R8A8Unorm, 256, 256, 0, 0, kTileModeThin_2dThin
{ 10, 0, 256, 256, 256, 9, 14, false, {{262144, 32768}, {65536, 32768}, {16384, 32768}, {4096, 32768}, {1024, 32768}, {256, 32768}, {256, 32768}, {256, 32768}, {256, 32768}, }, { {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, } },
{ 10, 0, 256, 256, 256, 9, 14, true, {{262144, 65536}, {65536, 65536}, {16384, 65536}, {4096, 65536}, {1024, 65536}, {256, 65536}, {256, 65536}, {256, 65536}, {256, 65536}, }, { {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, } },
// kDataFormatB8G8R8A8Unorm, 1920, 1080, 1920, 1, kTileModeDisplay_2dThin
{ 10, 0, 1920, 1080, 1920, 1, 10, false, {{8355840, 32768}, }, { {0, 0}, } },
{ 10, 0, 1920, 1080, 1920, 1, 10, true, {{8847360, 65536}, }, { {0, 0}, } },
// kDataFormatB8G8R8A8Unorm, 3840, 2160, 3840, 1, kTileModeDisplay_2dThin
{ 10, 0, 3840, 2160, 3840, 1, 10, false, {{33423360, 32768}, }, { {0, 0}, } },
{ 10, 0, 3840, 2160, 3840, 1, 10, true, {{33423360, 65536}, }, { {0, 0}, } },
// kDataFormatR32Float, 1920, 1080, 1920, 1, kTileModeDepth_2dThin_256
{ 4, 7, 1920, 1080, 1920, 1, 2, false, {{8355840, 32768}, }, { {0, 0}, } },
{ 4, 7, 1920, 1080, 1920, 1, 2, true, {{8847360, 65536}, }, { {0, 0}, } },
// kDataFormatR8Unorm, 2048, 2048, 0, 0, kTileModeDisplay_LinearAligned
{ 1, 0, 2048, 2048, 2048, 12, 8, false, {{4194304, 256}, {1048576, 256}, {262144, 256}, {65536, 256}, {16384, 256}, {4096, 256}, {2048, 256}, {1024, 256}, {512, 256}, {256, 256}, {256, 256}, {256, 256}, }, { {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, } },
{ 1, 0, 2048, 2048, 2048, 12, 8, true, {{4194304, 256}, {1048576, 256}, {262144, 256}, {65536, 256}, {16384, 256}, {4096, 256}, {2048, 256}, {1024, 256}, {512, 256}, {256, 256}, {256, 256}, {256, 256}, }, { {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, } },
// kDataFormatB8G8R8A8Unorm, 1, 1, 64, 0, kTileModeDisplay_LinearAligned
{ 10, 0, 1, 1, 64, 1, 8, false, {{256, 256}, }, { {0, 0}, } },
{ 10, 0, 1, 1, 64, 1, 8, true, {{256, 256}, }, { {0, 0}, } },
// clang-format on
};
// EXIT_IF(total_size == nullptr);
for (const auto& i: infos)
const TextureInfo* infos = nullptr;
int num = 0;
FindTextureInfo(tile, dfmt, nfmt, &infos, &num);
EXIT_NOT_IMPLEMENTED(tile != 31 && infos == nullptr);
for (int index = 0; index < num; index++)
{
const auto& i = infos[index];
if (i.dfmt == dfmt && i.nfmt == nfmt && i.width == width && i.pitch == pitch && i.height == height && i.levels >= levels &&
i.tile == tile && i.neo == neo)
{
@@ -753,9 +998,21 @@ void TileGetTextureSize(uint32_t dfmt, uint32_t nfmt, uint32_t width, uint32_t h
}
}
if (tile == 8 && levels == 1 && ((dfmt == 10 && nfmt == 9) || (dfmt == 10 && nfmt == 0)))
if ((tile == 8 || tile == 31) && levels == 1)
{
uint32_t size = pitch * height * 4;
uint32_t size = 0;
if ((dfmt == 10 && nfmt == 9) || (dfmt == 10 && nfmt == 0))
{
size = pitch * height * 4;
} else if ((dfmt == 3 && nfmt == 0))
{
size = pitch * height * 2;
} else if ((dfmt == 1 && nfmt == 0))
{
size = pitch * height;
}
if (total_size != nullptr)
{
total_size->size = size;
@@ -766,6 +1023,20 @@ void TileGetTextureSize(uint32_t dfmt, uint32_t nfmt, uint32_t width, uint32_t h
level_sizes[0] = size;
}
}
if (total_size != nullptr && total_size->size == 0)
{
Core::StringList list;
list.Add(String::FromPrintf("dfmt = %u", dfmt));
list.Add(String::FromPrintf("nfmt = %u", nfmt));
list.Add(String::FromPrintf("width = %u", width));
list.Add(String::FromPrintf("height = %u", height));
list.Add(String::FromPrintf("pitch = %u", pitch));
list.Add(String::FromPrintf("levels = %u", levels));
list.Add(String::FromPrintf("tile = %u", tile));
list.Add(String::FromPrintf("neo = %s", neo ? "true" : "false"));
EXIT("unknown format:\n%s\n", list.Concat(U'\n').C_Str());
}
}
} // namespace Kyty::Libs::Graphics
+71 -9
View File
@@ -8,8 +8,6 @@
#include "Emulator/Graphics/Objects/GpuMemory.h"
#include "Emulator/Profiler.h"
#include "vulkan/vulkan_core.h"
#ifdef KYTY_EMU_ENABLED
namespace Kyty::Libs::Graphics {
@@ -19,7 +17,7 @@ static void set_image_layout(VkCommandBuffer buffer, VulkanImage* dst_image, uin
{
EXIT_IF(buffer == nullptr);
EXIT_IF(dst_image->layout != old_image_layout);
EXIT_IF(old_image_layout != VK_IMAGE_LAYOUT_UNDEFINED && dst_image->layout != old_image_layout);
VkImageMemoryBarrier image_memory_barrier {};
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
@@ -86,7 +84,7 @@ static void set_image_layout(VkCommandBuffer buffer, VulkanImage* dst_image, uin
dst_image->layout = new_image_layout;
}
void UtilBufferToImage(CommandBuffer* buffer, VulkanBuffer* src_buffer, uint32_t src_pitch, VulkanImage* dst_image)
void UtilBufferToImage(CommandBuffer* buffer, VulkanBuffer* src_buffer, uint32_t src_pitch, VulkanImage* dst_image, uint64_t dst_layout)
{
EXIT_IF(src_buffer == nullptr);
EXIT_IF(src_buffer->buffer == nullptr);
@@ -114,7 +112,37 @@ void UtilBufferToImage(CommandBuffer* buffer, VulkanBuffer* src_buffer, uint32_t
vkCmdCopyBufferToImage(vk_buffer, src_buffer->buffer, dst_image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
set_image_layout(vk_buffer, dst_image, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
static_cast<VkImageLayout>(dst_layout));
}
void UtilImageToBuffer(CommandBuffer* buffer, VulkanImage* src_image, VulkanBuffer* dst_buffer, uint32_t dst_pitch, uint64_t src_layout)
{
EXIT_IF(dst_buffer == nullptr);
EXIT_IF(dst_buffer->buffer == nullptr);
EXIT_IF(src_image == nullptr);
EXIT_IF(src_image->image == nullptr);
auto* vk_buffer = buffer->GetPool()->buffers[buffer->GetIndex()];
set_image_layout(vk_buffer, src_image, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT, src_image->layout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
VkBufferImageCopy region {};
region.bufferOffset = 0;
region.bufferRowLength = (dst_pitch != src_image->extent.width ? dst_pitch : 0);
region.bufferImageHeight = 0;
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
region.imageSubresource.mipLevel = 0;
region.imageSubresource.baseArrayLayer = 0;
region.imageSubresource.layerCount = 1;
region.imageOffset = {0, 0, 0};
region.imageExtent = {src_image->extent.width, src_image->extent.height, 1};
vkCmdCopyImageToBuffer(vk_buffer, src_image->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dst_buffer->buffer, 1, &region);
set_image_layout(vk_buffer, src_image, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
static_cast<VkImageLayout>(src_layout));
}
void UtilBufferToImage(CommandBuffer* buffer, VulkanBuffer* src_buffer, VulkanImage* dst_image, const Vector<BufferImageCopy>& regions,
@@ -207,7 +235,7 @@ void UtilBlitImage(CommandBuffer* buffer, VulkanImage* src_image, VulkanSwapchai
auto* vk_buffer = buffer->GetPool()->buffers[buffer->GetIndex()];
VulkanImage swapchain_image {};
VulkanImage swapchain_image(VulkanImageType::Unknown);
swapchain_image.image = dst_swapchain->swapchain_images[dst_swapchain->current_index];
swapchain_image.layout = VK_IMAGE_LAYOUT_UNDEFINED;
@@ -286,12 +314,14 @@ void VulkanDeleteBuffer(GraphicContext* gctx, VulkanBuffer* buffer)
buffer->buffer = nullptr;
}
void UtilFillImage(GraphicContext* ctx, VulkanImage* image, const void* src_data, uint64_t size, uint32_t src_pitch)
void UtilFillImage(GraphicContext* ctx, VulkanImage* dst_image, const void* src_data, uint64_t size, uint32_t src_pitch,
uint64_t dst_layout)
{
KYTY_PROFILER_FUNCTION();
EXIT_IF(ctx == nullptr);
EXIT_IF(image == nullptr);
EXIT_IF(dst_image == nullptr);
EXIT_IF(src_data == nullptr);
VulkanBuffer staging_buffer {};
staging_buffer.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
@@ -309,7 +339,7 @@ void UtilFillImage(GraphicContext* ctx, VulkanImage* image, const void* src_data
EXIT_NOT_IMPLEMENTED(buffer.IsInvalid());
buffer.Begin();
UtilBufferToImage(&buffer, &staging_buffer, src_pitch, image);
UtilBufferToImage(&buffer, &staging_buffer, src_pitch, dst_image, dst_layout);
buffer.End();
buffer.Execute();
buffer.WaitForFence();
@@ -317,6 +347,38 @@ void UtilFillImage(GraphicContext* ctx, VulkanImage* image, const void* src_data
VulkanDeleteBuffer(ctx, &staging_buffer);
}
void UtilFillBuffer(GraphicContext* ctx, void* dst_data, uint64_t size, uint32_t dst_pitch, VulkanImage* src_image, uint64_t src_layout)
{
KYTY_PROFILER_FUNCTION();
EXIT_IF(ctx == nullptr);
EXIT_IF(src_image == nullptr);
EXIT_IF(dst_data == nullptr);
VulkanBuffer staging_buffer {};
staging_buffer.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
staging_buffer.memory.property = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
VulkanCreateBuffer(ctx, size, &staging_buffer);
CommandBuffer buffer;
buffer.SetQueue(GraphicContext::QUEUE_UTIL);
EXIT_NOT_IMPLEMENTED(buffer.IsInvalid());
buffer.Begin();
UtilImageToBuffer(&buffer, src_image, &staging_buffer, dst_pitch, src_layout);
buffer.End();
buffer.Execute();
buffer.WaitForFence();
void* data = nullptr;
VulkanMapMemory(ctx, &staging_buffer.memory, &data);
std::memcpy(dst_data, data, size);
VulkanUnmapMemory(ctx, &staging_buffer.memory);
VulkanDeleteBuffer(ctx, &staging_buffer);
}
void UtilSetDepthLayoutOptimal(DepthStencilVulkanImage* image)
{
CommandBuffer buffer;
+21 -1
View File
@@ -37,7 +37,6 @@
#include <string>
#include <vulkan/vk_enum_string_helper.h>
#include <vulkan/vk_platform.h>
#include <vulkan/vulkan_core.h>
// IWYU pragma: no_include <intrin.h>
@@ -1370,6 +1369,18 @@ static VkPhysicalDevice VulkanFindPhysicalDevice(VkInstance instance, VkSurfaceK
skip_device = true;
}
if (device_features2.features.samplerAnisotropy != VK_TRUE)
{
printf("samplerAnisotropy is not supported\n");
skip_device = true;
}
// if (device_features2.features.shaderImageGatherExtended != VK_TRUE)
// {
// printf("shaderImageGatherExtended is not supported\n");
// skip_device = true;
// }
if (!skip_device)
{
uint32_t extensions_count = 0;
@@ -1460,6 +1471,13 @@ static VkPhysicalDevice VulkanFindPhysicalDevice(VkInstance instance, VkSurfaceK
skip_device = true;
}
if (!skip_device &&
!CheckFormat(device, VK_FORMAT_R8G8_UNORM, true, VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))
{
printf("Format VK_FORMAT_R8G8_UNORM cannot be used as texture\n");
skip_device = true;
}
if (!skip_device &&
!CheckFormat(device, VK_FORMAT_R8G8B8A8_SRGB, true, VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))
{
@@ -1568,6 +1586,8 @@ static VkDevice VulkanCreateDevice(VkPhysicalDevice physical_device, VkSurfaceKH
VkPhysicalDeviceFeatures device_features {};
device_features.fragmentStoresAndAtomics = VK_TRUE;
device_features.samplerAnisotropy = VK_TRUE;
// device_features.shaderImageGatherExtended = VK_TRUE;
VkPhysicalDeviceColorWriteEnableFeaturesEXT color_write_ext {};
color_write_ext.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COLOR_WRITE_ENABLE_FEATURES_EXT;
+13 -10
View File
@@ -589,8 +589,6 @@ int KYTY_SYSV_ABI KernelMapDirectMemory(void** addr, size_t len, int prot, int f
EXIT_IF(g_physical_memory == nullptr);
// EXIT_NOT_IMPLEMENTED(!Core::Thread::IsMainThread());
EXIT_NOT_IMPLEMENTED(addr == nullptr);
EXIT_NOT_IMPLEMENTED(flags != 0);
@@ -619,12 +617,14 @@ int KYTY_SYSV_ABI KernelMapDirectMemory(void** addr, size_t len, int prot, int f
auto out_addr = VirtualMemory::AllocAligned(in_addr, len, mode, alignment);
*addr = reinterpret_cast<void*>(out_addr);
printf("\tin_addr = 0x%016" PRIx64 "\n", in_addr);
printf("\tout_addr = 0x%016" PRIx64 "\n", out_addr);
printf("\tsize = 0x%016" PRIx64 "\n", len);
printf("\tmode = %s\n", Core::EnumName(mode).C_Str());
printf("\talign = 0x%016" PRIx64 "\n", alignment);
printf("\tgpu_mode = %s\n", Core::EnumName(gpu_mode).C_Str());
printf("\t in_addr = 0x%016" PRIx64 "\n", in_addr);
printf("\t out_addr = 0x%016" PRIx64 "\n", out_addr);
printf("\t size = 0x%016" PRIx64 "\n", len);
printf("\t mode = %s\n", Core::EnumName(mode).C_Str());
printf("\t align = 0x%016" PRIx64 "\n", alignment);
printf("\t gpu_mode = %s\n", Core::EnumName(gpu_mode).C_Str());
EXIT_NOT_IMPLEMENTED(out_addr == 0);
if (out_addr == 0)
{
@@ -633,8 +633,11 @@ int KYTY_SYSV_ABI KernelMapDirectMemory(void** addr, size_t len, int prot, int f
if (!g_physical_memory->Map(out_addr, direct_memory_start, len, prot, mode, gpu_mode))
{
printf(FG_RED "\t[Fail]\n" FG_DEFAULT);
printf(FG_RED "\t [Fail]\n" FG_DEFAULT);
VirtualMemory::Free(out_addr);
KYTY_NOT_IMPLEMENTED;
return KERNEL_ERROR_EBUSY;
}
@@ -643,7 +646,7 @@ int KYTY_SYSV_ABI KernelMapDirectMemory(void** addr, size_t len, int prot, int f
Graphics::GpuMemorySetAllocatedRange(out_addr, len);
}
printf(FG_GREEN "\t[Ok]\n" FG_DEFAULT);
printf(FG_GREEN "\t [Ok]\n" FG_DEFAULT);
return OK;
}
+16 -3
View File
@@ -650,6 +650,8 @@ int KYTY_SYSV_ABI PthreadMutexattrDestroy(PthreadMutexattr* attr)
{
// PRINT_NAME();
EXIT_NOT_IMPLEMENTED(attr == nullptr || *attr == nullptr);
int result = pthread_mutexattr_destroy(&(*attr)->p);
delete *attr;
@@ -757,13 +759,11 @@ int KYTY_SYSV_ABI PthreadMutexDestroy(PthreadMutex* mutex)
{
PRINT_NAME();
if (mutex == nullptr)
if (mutex == nullptr || *mutex == nullptr)
{
return KERNEL_ERROR_EINVAL;
}
EXIT_NOT_IMPLEMENTED(*mutex == nullptr);
int result = pthread_mutex_destroy(&(*mutex)->p);
printf("\tmutex destroy: %s, %d\n", (*mutex)->name.C_Str(), result);
@@ -907,6 +907,8 @@ int KYTY_SYSV_ABI PthreadAttrDestroy(PthreadAttr* attr)
{
PRINT_NAME();
EXIT_NOT_IMPLEMENTED(attr == nullptr || *attr == nullptr);
int result = pthread_attr_destroy(&(*attr)->p);
delete *attr;
@@ -1584,6 +1586,8 @@ int KYTY_SYSV_ABI PthreadRwlockattrDestroy(PthreadRwlockattr* attr)
return KERNEL_ERROR_EINVAL;
}
EXIT_NOT_IMPLEMENTED(*attr == nullptr);
int result = pthread_rwlockattr_destroy(&(*attr)->p);
delete *attr;
@@ -1651,6 +1655,8 @@ int KYTY_SYSV_ABI PthreadCondattrDestroy(PthreadCondattr* attr)
return KERNEL_ERROR_EINVAL;
}
EXIT_NOT_IMPLEMENTED(*attr == nullptr);
int result = pthread_condattr_destroy(&(*attr)->p);
delete *attr;
@@ -2629,6 +2635,13 @@ int KYTY_SYSV_ABI pthread_setspecific(LibKernel::PthreadKey key, void* value)
return POSIX_PTHREAD_CALL(LibKernel::PthreadSetspecific(key, value));
}
void* KYTY_SYSV_ABI pthread_getspecific(LibKernel::PthreadKey key)
{
PRINT_NAME();
return (LibKernel::PthreadGetspecific(key));
}
int KYTY_SYSV_ABI pthread_mutex_destroy(LibKernel::PthreadMutex* mutex)
{
PRINT_NAME();
@@ -0,0 +1,79 @@
#include "Kyty/Core/Common.h"
#include "Kyty/Core/DbgAssert.h"
#include "Kyty/Core/String.h"
#include "Emulator/Common.h"
#include "Emulator/Libs/Errno.h"
#include "Emulator/Libs/Libs.h"
#include "Emulator/SymbolDatabase.h"
#ifdef KYTY_EMU_ENABLED
namespace Kyty::Libs {
LIB_VERSION("AppContent", 1, "AppContentUtil", 1, 1);
namespace AppContent {
struct AppContentInitParam
{
char reserved[32];
};
struct AppContentBootParam
{
char reserved1[4];
uint32_t attr;
char reserved2[32];
};
struct NpUnifiedEntitlementLabel
{
char data[17];
char padding[3];
};
struct AppContentAddcontInfo
{
NpUnifiedEntitlementLabel entitlement_label;
uint32_t status;
};
int KYTY_SYSV_ABI AppContentInitialize(const AppContentInitParam* init_param, AppContentBootParam* boot_param)
{
PRINT_NAME();
EXIT_NOT_IMPLEMENTED(init_param == nullptr);
EXIT_NOT_IMPLEMENTED(boot_param == nullptr);
boot_param->attr = 0;
return OK;
}
int KYTY_SYSV_ABI AppContentGetAddcontInfoList(uint32_t service_label, AppContentAddcontInfo* /*list*/, uint32_t list_num,
uint32_t* hit_num)
{
PRINT_NAME();
EXIT_NOT_IMPLEMENTED(hit_num == nullptr);
printf("\t service_label = %u\n", service_label);
printf("\t list_num = %u\n", list_num);
*hit_num = 0;
return OK;
}
} // namespace AppContent
LIB_DEFINE(InitAppContent_1)
{
LIB_FUNC("R9lA82OraNs", AppContent::AppContentInitialize);
LIB_FUNC("xnd8BJzAxmk", AppContent::AppContentGetAddcontInfoList);
}
} // namespace Kyty::Libs
#endif // KYTY_EMU_ENABLED
+23
View File
@@ -19,6 +19,8 @@ LIB_DEFINE(InitAudio_1_AudioOut)
LIB_FUNC("ekNvsT22rsY", AudioOut::AudioOutOpen);
LIB_FUNC("b+uAV89IlxE", AudioOut::AudioOutSetVolume);
LIB_FUNC("w3PdaSTSwGE", AudioOut::AudioOutOutputs);
LIB_FUNC("QOQtbeDqsT4", AudioOut::AudioOutOutput);
LIB_FUNC("s1--uE9mBFw", AudioOut::AudioOutClose);
}
} // namespace LibAudioOut
@@ -59,16 +61,37 @@ namespace Ajm = Audio::Ajm;
LIB_DEFINE(InitAudio_1_Ajm)
{
LIB_FUNC("dl+4eHSzUu4", Ajm::AjmInitialize);
LIB_FUNC("Q3dyFuwGn64", Ajm::AjmModuleRegister);
}
} // namespace LibAjm
namespace LibAvPlayer {
LIB_VERSION("AvPlayer", 1, "AvPlayer", 1, 0);
namespace AvPlayer = Audio::AvPlayer;
LIB_DEFINE(InitAudio_1_AvPlayer)
{
LIB_FUNC("aS66RI0gGgo", AvPlayer::AvPlayerInit);
LIB_FUNC("KMcEa+rHsIo", AvPlayer::AvPlayerAddSource);
LIB_FUNC("OVths0xGfho", AvPlayer::AvPlayerSetLooping);
LIB_FUNC("JdksQu8pNdQ", AvPlayer::AvPlayerGetVideoDataEx);
LIB_FUNC("Wnp1OVcrZgk", AvPlayer::AvPlayerGetAudioData);
LIB_FUNC("UbQoYawOsfY", AvPlayer::AvPlayerIsActive);
LIB_FUNC("NkJwDzKmIlw", AvPlayer::AvPlayerClose);
}
} // namespace LibAvPlayer
LIB_DEFINE(InitAudio_1)
{
LibAudioOut::InitAudio_1_AudioOut(s);
LibAudioIn::InitAudio_1_AudioIn(s);
LibVoiceQoS::InitAudio_1_VoiceQoS(s);
LibAjm::InitAudio_1_Ajm(s);
LibAvPlayer::InitAudio_1_AvPlayer(s);
}
} // namespace Kyty::Libs
+2 -1
View File
@@ -224,7 +224,7 @@ static void* KYTY_SYSV_ABI KernelGetProcParam()
{
PRINT_NAME();
auto* rt = Core::Singleton<Loader::RuntimeLinker>::Instance();
auto* rt = Core::Singleton<Loader::RuntimeLinker>::Instance(); // NOLINT
return reinterpret_cast<void*>(rt->GetProcParam());
}
@@ -461,6 +461,7 @@ LIB_DEFINE(InitLibKernel_1_Posix)
LIB_FUNC("mqULNdimTn0", Posix::pthread_key_create);
LIB_FUNC("6BpEZuDT7YI", Posix::pthread_key_delete);
LIB_FUNC("WrOLvHU0yQM", Posix::pthread_setspecific);
LIB_FUNC("0-KXaS70xy4", Posix::pthread_getspecific);
}
} // namespace Posix
+1
View File
@@ -183,6 +183,7 @@ LIB_DEFINE(InitNet_1_NpTrophy)
LIB_FUNC("XbkjbobZlCY", NpTrophy::NpTrophyCreateContext);
LIB_FUNC("TJCAxto9SEU", NpTrophy::NpTrophyRegisterContext);
LIB_FUNC("GNcF4oidY0Y", NpTrophy::NpTrophyDestroyHandle);
LIB_FUNC("LHuSmO3SLd8", NpTrophy::NpTrophyGetTrophyUnlockState);
}
} // namespace LibNpTrophy
+2
View File
@@ -20,6 +20,8 @@ LIB_DEFINE(InitPad_1)
LIB_FUNC("YndgXqQVV7c", Controller::PadReadState);
LIB_FUNC("q1cHNfGycLI", Controller::PadRead);
LIB_FUNC("yFVnOdGxvZY", Controller::PadSetVibration);
LIB_FUNC("DscD1i9HX1w", Controller::PadResetLightBar);
LIB_FUNC("RR4novUEENY", Controller::PadSetLightBar);
}
} // namespace Kyty::Libs
+119 -1
View File
@@ -31,6 +31,18 @@ struct SaveDataMountPoint
char data[16];
};
struct SaveDataMount
{
int user_id;
int pad;
const char* title_id;
const char* dir_name;
const char* fingerprint;
uint64_t blocks;
uint32_t mount_mode;
uint8_t reserved[32];
};
struct SaveDataMount2
{
int user_id;
@@ -63,6 +75,21 @@ struct SaveDataParam
uint8_t reserved[32];
};
struct SaveDataMountInfo
{
uint64_t blocks;
uint64_t free_blocks;
uint8_t reserved[32];
};
struct SaveDataIcon
{
void* buf;
size_t buf_size;
size_t data_size;
uint8_t reserved[32];
};
int KYTY_SYSV_ABI SaveDataInitialize(const void* /*init*/)
{
PRINT_NAME();
@@ -90,6 +117,69 @@ int KYTY_SYSV_ABI SaveDataInitialize3(const void* /*init*/)
return OK;
}
int KYTY_SYSV_ABI SaveDataMount(const SaveDataMount* mount, SaveDataMountResult* mount_result)
{
PRINT_NAME();
EXIT_NOT_IMPLEMENTED(mount == nullptr);
EXIT_NOT_IMPLEMENTED(mount_result == nullptr);
printf("\t user_id = %d\n", mount->user_id);
printf("\t title_id = %s\n", mount->title_id);
printf("\t dir_name = %s\n", mount->dir_name);
printf("\t fingerprint = %s\n", mount->fingerprint);
printf("\t blocks = %" PRIu64 "\n", mount->blocks);
printf("\t mount_mode = %" PRIu32 "\n", mount->mount_mode);
String mount_dir = String(SAVE_DATA_DIR) + U"/" + String::FromUtf8(mount->dir_name);
String mount_point = SAVE_DATA_POINT;
bool create = (mount->mount_mode == 6 || mount->mount_mode == 22);
bool open = (mount->mount_mode == 1 || mount->mount_mode == 2);
if (!create && !open)
{
EXIT("unknown mount mode: %u", mount->mount_mode);
}
if (open)
{
EXIT_NOT_IMPLEMENTED(create);
if (!Core::File::IsDirectoryExisting(mount_dir))
{
return SAVE_DATA_ERROR_NOT_FOUND;
}
LibKernel::FileSystem::Mount(mount_dir, mount_point);
mount_result->mount_status = 0;
}
if (create)
{
EXIT_NOT_IMPLEMENTED(open);
if (Core::File::IsDirectoryExisting(mount_dir))
{
return SAVE_DATA_ERROR_EXISTS;
}
Core::File::CreateDirectories(mount_dir);
EXIT_NOT_IMPLEMENTED((!Core::File::IsDirectoryExisting(mount_dir)));
LibKernel::FileSystem::Mount(mount_dir, mount_point);
mount_result->mount_status = 1;
}
snprintf(mount_result->mount_point.data, 16, "%s", mount_point.C_Str());
mount_result->required_blocks = 0;
return OK;
}
int KYTY_SYSV_ABI SaveDataMount2(const SaveDataMount2* mount, SaveDataMountResult* mount_result)
{
PRINT_NAME();
@@ -104,7 +194,7 @@ int KYTY_SYSV_ABI SaveDataMount2(const SaveDataMount2* mount, SaveDataMountResul
String mount_dir = String(SAVE_DATA_DIR) + U"/" + String::FromUtf8(mount->dir_name->data);
String mount_point = SAVE_DATA_POINT;
bool create = (mount->mount_mode == 22);
bool create = (mount->mount_mode == 6 || mount->mount_mode == 22);
bool open = (mount->mount_mode == 1 || mount->mount_mode == 2);
if (!create && !open)
@@ -190,6 +280,31 @@ int KYTY_SYSV_ABI SaveDataSetParam(const SaveDataMountPoint* mount_point, uint32
return OK;
}
int KYTY_SYSV_ABI SaveDataGetMountInfo(const SaveDataMountPoint* mount_point, SaveDataMountInfo* info)
{
PRINT_NAME();
EXIT_NOT_IMPLEMENTED(mount_point == nullptr);
EXIT_NOT_IMPLEMENTED(info == nullptr);
info->blocks = 100000;
info->free_blocks = 100000;
return OK;
}
int KYTY_SYSV_ABI SaveDataSaveIcon(const SaveDataMountPoint* mount_point, const SaveDataIcon* icon)
{
EXIT_NOT_IMPLEMENTED(mount_point == nullptr);
EXIT_NOT_IMPLEMENTED(icon == nullptr);
printf("\t buf = %016" PRIx64 "\n", reinterpret_cast<uint64_t>(icon->buf));
printf("\t buf_size = %" PRIu64 "\n", icon->buf_size);
printf("\t data_size = %" PRIu64 "\n", icon->data_size);
return OK;
}
} // namespace SaveData
LIB_DEFINE(InitSaveData_1)
@@ -197,9 +312,12 @@ LIB_DEFINE(InitSaveData_1)
LIB_FUNC("ZkZhskCPXFw", SaveData::SaveDataInitialize);
LIB_FUNC("l1NmDeDpNGU", SaveData::SaveDataInitialize2);
LIB_FUNC("TywrFKCoLGY", SaveData::SaveDataInitialize3);
LIB_FUNC("32HQAQdwM2o", SaveData::SaveDataMount);
LIB_FUNC("0z45PIH+SNI", SaveData::SaveDataMount2);
LIB_FUNC("BMR4F-Uek3E", SaveData::SaveDataUmount);
LIB_FUNC("85zul--eGXs", SaveData::SaveDataSetParam);
LIB_FUNC("65VH0Qaaz6s", SaveData::SaveDataGetMountInfo);
LIB_FUNC("c88Yy54Mx0w", SaveData::SaveDataSaveIcon);
}
} // namespace Kyty::Libs
@@ -116,7 +116,7 @@ static int KYTY_SYSV_ABI SystemServiceParamGetInt(int param_id, int* value)
switch (param_id)
{
case PARAM_ID_LANG: v = PARAM_LANG_RUSSIAN; break;
case PARAM_ID_LANG: v = PARAM_LANG_ENGLISH_US; break;
case PARAM_ID_DATE_FORMAT: v = PARAM_DATE_FORMAT_DDMMYYYY; break;
case PARAM_ID_TIME_FORMAT: v = PARAM_TIME_FORMAT_24HOUR; break;
case PARAM_ID_TIME_ZONE: v = +180; break;
+23 -1
View File
@@ -21,6 +21,18 @@ struct UserServiceLoginUserIdList
int user_id[4];
};
enum UserServiceEventType
{
UserServiceEventTypeLogin,
UserServiceEventTypeLogout
};
struct SceUserServiceEvent
{
UserServiceEventType event_type;
int user_id;
};
static KYTY_SYSV_ABI int UserServiceInitialize(const void* /*params*/)
{
PRINT_NAME();
@@ -39,12 +51,22 @@ static KYTY_SYSV_ABI int UserServiceGetInitialUser(int* user_id)
return OK;
}
static KYTY_SYSV_ABI int UserServiceGetEvent(void* event)
static KYTY_SYSV_ABI int UserServiceGetEvent(SceUserServiceEvent* event)
{
PRINT_NAME();
EXIT_NOT_IMPLEMENTED(event == nullptr);
static bool logged_in = false;
if (!logged_in)
{
logged_in = true;
event->event_type = UserServiceEventTypeLogin;
event->user_id = 1;
return OK;
}
return USER_SERVICE_ERROR_NO_EVENT;
}
+2 -2
View File
@@ -8,12 +8,12 @@ namespace LibcInternal {
LIB_DEFINE(InitLibcInternal_1);
} // namespace LibcInternal
LIB_DEFINE(InitAppContent_1);
LIB_DEFINE(InitAudio_1);
LIB_DEFINE(InitDebug_1);
LIB_DEFINE(InitDialog_1);
LIB_DEFINE(InitDiscMap_1);
LIB_DEFINE(InitGraphicsDriver_1);
// LIB_DEFINE(InitLibC_1);
LIB_DEFINE(InitLibKernel_1);
LIB_DEFINE(InitNet_1);
LIB_DEFINE(InitPad_1);
@@ -27,7 +27,7 @@ LIB_DEFINE(InitVideoOut_1);
bool Init(const String& id, Loader::SymbolDatabase* s)
{
LIB_CHECK(U"libAudio_1", InitAudio_1);
// LIB_CHECK(U"libc_1", InitLibC_1);
LIB_CHECK(U"libAppContent_1", InitAppContent_1);
LIB_CHECK(U"libc_internal_1", LibcInternal::InitLibcInternal_1);
LIB_CHECK(U"libDebug_1", InitDebug_1);
LIB_CHECK(U"libDialog_1", InitDialog_1);
+79 -20
View File
@@ -5,6 +5,7 @@
#include "Kyty/Core/String.h"
#include "Kyty/Core/Subsystems.h"
#include "Kyty/Core/Threads.h"
#include "Kyty/Core/Vector.h"
#include "Emulator/Common.h"
#include "Emulator/Config.h"
@@ -22,11 +23,13 @@ namespace Kyty {
namespace Log {
static bool g_log_initialized = false;
static Core::Mutex* g_mutex = nullptr;
static Direction g_dir = Direction::Console;
static Core::File* g_file = nullptr;
static bool g_colored_printf = false;
static bool g_log_initialized = false;
static Core::Mutex* g_mutex = nullptr;
static Direction g_dir = Direction::Console;
static Core::File* g_file = nullptr;
static bool g_colored_printf = false;
static thread_local Core::File* g_thread_local_file = nullptr;
static Vector<Core::File*>* g_thread_local_files = nullptr;
static bool EnableVTMode()
{
@@ -92,6 +95,16 @@ static void Close()
delete g_file;
g_file = nullptr;
}
if (g_dir == Direction::Directory && !g_thread_local_files->IsEmpty())
{
for (auto* file: *g_thread_local_files)
{
file->Flush();
file->Close();
delete file;
}
g_thread_local_files->Clear();
}
g_mutex->Unlock();
}
}
@@ -110,6 +123,8 @@ KYTY_SUBSYSTEM_INIT(Log)
{
SetOutputFile(Config::GetPrintfOutputFile());
}
g_thread_local_files = new Vector<Core::File*>;
}
KYTY_SUBSYSTEM_UNEXPECTED_SHUTDOWN(Log)
@@ -172,6 +187,40 @@ void SetOutputFile(const String& file_name, Core::File::Encoding enc)
}
}
void SetOutputThreadLocalFile(const String& file_name, Core::File::Encoding enc)
{
EXIT_IF(!Log::g_log_initialized);
EXIT_IF(Log::g_dir != Log::Direction::Directory);
EXIT_IF(Log::g_thread_local_file != nullptr);
EXIT_IF(g_thread_local_files == nullptr);
Core::File::CreateDirectories(file_name.DirectoryWithoutFilename());
g_thread_local_file = new Core::File;
g_thread_local_file->Create(file_name);
if (g_thread_local_file->IsInvalid())
{
::printf("Can't create log file: %s\n", file_name.C_Str());
delete g_thread_local_file;
g_thread_local_file = nullptr;
} else
{
g_thread_local_file->SetEncoding(enc);
g_thread_local_file->WriteBOM();
}
g_mutex->Lock();
g_thread_local_files->Add(g_thread_local_file);
g_mutex->Unlock();
}
void CreateThreadLocalFile()
{
auto file_name = String::FromPrintf("%s/%d.txt", Config::GetPrintfOutputFolder().C_Str(), Core::Thread::GetThreadIdUnique());
SetOutputThreadLocalFile(file_name, Core::File::Encoding::Utf8);
}
} // namespace Log
void emu_printf(const char* format, ...)
@@ -214,28 +263,38 @@ void printf(const char* format, ...)
EXIT_IF(Log::g_mutex == nullptr);
Log::g_mutex->Lock();
va_list args {};
va_start(args, format);
String s;
s.Printf(format, args);
va_end(args);
if (!Log::g_colored_printf)
{
va_list args {};
va_start(args, format);
String s;
s.Printf(format, args);
va_end(args);
s = Log::RemoveColors(s);
}
if (!Log::g_colored_printf)
if (Log::g_dir == Log::Direction::Console)
{
Log::g_mutex->Lock();
::printf("%s", s.C_Str());
Log::g_mutex->Unlock();
} else if (Log::g_dir == Log::Direction::File && Log::g_file != nullptr)
{
Log::g_mutex->Lock();
Log::g_file->Write(s);
Log::g_mutex->Unlock();
} else if (Log::g_dir == Log::Direction::Directory)
{
if (Log::g_thread_local_file == nullptr)
{
s = Log::RemoveColors(s);
Log::CreateThreadLocalFile();
}
if (Log::g_dir == Log::Direction::Console)
if (Log::g_thread_local_file != nullptr)
{
::printf("%s", s.C_Str());
} else if (Log::g_dir == Log::Direction::File && Log::g_file != nullptr)
{
Log::g_file->Write(s);
Log::g_thread_local_file->Write(s);
}
}
Log::g_mutex->Unlock();
}
} // namespace Kyty
+28 -1
View File
@@ -69,7 +69,7 @@ public:
uint32_t m_type = static_cast<uint32_t>(Type::Invalid);
};
using HttpsCallback = int (*)(int, unsigned int, void* const*, int, void*);
using HttpsCallback = KYTY_SYSV_ABI int (*)(int, unsigned int, void* const*, int, void*);
Network() = default;
virtual ~Network() = default;
@@ -1341,6 +1341,11 @@ namespace NpTrophy {
LIB_NAME("NpTrophy", "NpTrophy");
struct NpTrophyFlagArray
{
uint32_t flag_bits[4];
};
int KYTY_SYSV_ABI NpTrophyCreateHandle(int* handle)
{
PRINT_NAME();
@@ -1392,6 +1397,28 @@ int KYTY_SYSV_ABI NpTrophyDestroyHandle(int handle)
return OK;
}
int KYTY_SYSV_ABI NpTrophyGetTrophyUnlockState(int context, int handle, NpTrophyFlagArray* flags, uint32_t* count)
{
PRINT_NAME();
EXIT_NOT_IMPLEMENTED(flags == nullptr);
EXIT_NOT_IMPLEMENTED(count == nullptr);
EXIT_NOT_IMPLEMENTED(context != 1);
EXIT_NOT_IMPLEMENTED(handle != 1);
printf("\t context = %d\n", context);
printf("\t handle = %d\n", handle);
flags->flag_bits[0] = 0;
flags->flag_bits[1] = 0;
flags->flag_bits[2] = 0;
flags->flag_bits[3] = 0;
*count = 0;
return OK;
}
} // namespace NpTrophy
namespace NpWebApi {
+67 -4
View File
@@ -74,6 +74,8 @@ constexpr uint64_t DESIRED_BASE_ADDR = 0x010000000;
constexpr size_t XSAVE_BUFFER_SIZE = 2688;
constexpr uint64_t XSAVE_CHK_GUARD = 0xDeadBeef5533CCAA;
static uint64_t g_desired_base_addr = DESIRED_BASE_ADDR;
static Program* g_tls_main_program = nullptr;
alignas(64) static uint8_t g_tls_reg_save_area[XSAVE_BUFFER_SIZE + sizeof(XSAVE_CHK_GUARD)];
static uint8_t g_tls_spinlock = 0;
@@ -153,6 +155,45 @@ static VirtualMemory::Mode get_mode(Elf64_Word flags)
}
}
struct FrameS
{
FrameS* next;
uintptr_t ret_addr;
};
static void KYTY_SYSV_ABI stackwalk_x86(uint64_t rbp, void** stack, int* depth, uintptr_t stack_addr, size_t stack_size,
uintptr_t code_addr, size_t code_size)
{
auto* frame = reinterpret_cast<FrameS*>(rbp);
int d = *depth;
int i = 0;
for (; i < d; i++)
{
if (!(uintptr_t(frame) >= stack_addr && uintptr_t(frame) < stack_addr + stack_size))
{
break;
}
if (!(frame->ret_addr >= code_addr && frame->ret_addr < code_addr + code_size))
{
break;
}
stack[i] = reinterpret_cast<void*>(frame->ret_addr);
frame = frame->next;
}
*depth = i;
}
void KYTY_SYSV_ABI sys_stack_walk_x86(uint64_t rbp, void** stack, int* depth)
{
stackwalk_x86(rbp, stack, depth, 0, UINT64_MAX, DESIRED_BASE_ADDR, g_desired_base_addr - DESIRED_BASE_ADDR);
}
static void kyty_exception_handler(const VirtualMemory::ExceptionHandler::ExceptionInfo* info)
{
printf("kyty_exception_handler: %016" PRIx64 "\n", info->exception_address);
@@ -165,6 +206,8 @@ static void kyty_exception_handler(const VirtualMemory::ExceptionHandler::Except
return;
}
Core::Singleton<Loader::RuntimeLinker>::Instance()->StackTrace(info->rbp);
EXIT("Access violation: %s [%016" PRIx64 "] %s\n", Core::EnumName(info->access_violation_type).C_Str(),
info->access_violation_vaddr, (info->access_violation_vaddr == INVALID_MEMORY ? "(Unpatched object)" : ""));
}
@@ -453,8 +496,11 @@ static KYTY_SYSV_ABI void RelocateHandler(RelocateHandlerStack s)
name = String::FromPrintf(FG_BRIGHT_RED "%s" DEFAULT, ri.name.C_Str());
}
// Restore return address (for debug)
// Restore return address (for stack trace)
stack[-1] = stack[1];
Core::Singleton<Loader::RuntimeLinker>::Instance()->StackTrace(reinterpret_cast<uint64_t>(s.stack - 2));
EXIT("=== Unpatched function!!! ===\n[%d]\t%s\n", Core::Thread::GetThreadIdUnique(),
(Log::IsColoredPrintf() ? name : Log::RemoveColors(name)).C_Str());
}
@@ -920,6 +966,23 @@ Program* RuntimeLinker::FindProgramByAddr(uint64_t vaddr)
return nullptr;
}
void RuntimeLinker::StackTrace(uint64_t frame_ptr)
{
void* stack[20];
int depth = 20;
sys_stack_walk_x86(frame_ptr, stack, &depth);
std::printf("Stack trace [thread = %d]:\n", Core::Thread::GetThreadIdUnique());
for (int i = 0; i < depth; i++)
{
auto vaddr = reinterpret_cast<uint64_t>(stack[i]);
auto* p = FindProgramByAddr(vaddr);
std::printf("[%d] %016" PRIx64 ", %s\n", i, vaddr, (p == nullptr ? "???" : p->file_name.FilenameWithoutDirectory().C_Str()));
}
}
void RuntimeLinker::StartAllModules()
{
// EXIT_NOT_IMPLEMENTED(!Core::Thread::IsMainThread());
@@ -1043,7 +1106,7 @@ void RuntimeLinker::LoadProgramToMemory(Program* program)
EXIT_IF(program == nullptr || program->base_vaddr != 0 || program->base_size != 0 || program->elf == nullptr ||
program->exception_handler != nullptr);
static uint64_t desired_base_addr = DESIRED_BASE_ADDR;
// static uint64_t desired_base_addr = DESIRED_BASE_ADDR;
bool is_shared = program->elf->IsShared();
bool is_next_gen = program->elf->IsNextGen();
@@ -1060,14 +1123,14 @@ void RuntimeLinker::LoadProgramToMemory(Program* program)
uint64_t tls_handler_size = is_shared ? 0 : Jit::SafeCall::GetSize();
uint64_t alloc_size = program->base_size_aligned + exception_handler_size + tls_handler_size;
program->base_vaddr = VirtualMemory::Alloc(desired_base_addr, alloc_size, VirtualMemory::Mode::ExecuteReadWrite);
program->base_vaddr = VirtualMemory::Alloc(g_desired_base_addr, alloc_size, VirtualMemory::Mode::ExecuteReadWrite);
if (!is_shared)
{
program->tls.handler_vaddr = program->base_vaddr + program->base_size_aligned + exception_handler_size;
}
desired_base_addr += DESIRED_BASE_ADDR * (1 + alloc_size / DESIRED_BASE_ADDR);
g_desired_base_addr += DESIRED_BASE_ADDR * (1 + alloc_size / DESIRED_BASE_ADDR);
EXIT_IF(program->base_vaddr == 0);
EXIT_IF(program->base_size_aligned < program->base_size);
+11 -2
View File
@@ -113,6 +113,8 @@ public:
info.access_violation_vaddr = exception_record->ExceptionInformation[1];
}
info.rbp = dispatcher_context->ContextRecord->Rbp;
auto* p = *static_cast<ExceptionHandlerPrivate**>(dispatcher_context->HandlerData);
p->func(&info);
@@ -318,8 +320,13 @@ static VirtualAlloc2_func_t ResolveVirtualAlloc2()
return nullptr;
}
uint64_t AllocAligned(uint64_t /*address*/, uint64_t size, Mode mode, uint64_t alignment)
uint64_t AllocAligned(uint64_t address, uint64_t size, Mode mode, uint64_t alignment)
{
if (alignment == 0)
{
return 0;
}
MEM_ADDRESS_REQUIREMENTS req2 {};
MEM_EXTENDED_PARAMETER param {};
req2.LowestStartingAddress = nullptr;
@@ -337,7 +344,9 @@ uint64_t AllocAligned(uint64_t /*address*/, uint64_t size, Mode mode, uint64_t a
get_protection_flag(mode), &param, 1));
if (ptr == 0)
{
printf("VirtualAlloc2() failed: 0x%08" PRIx32 "\n", static_cast<uint32_t>(GetLastError()));
printf("VirtualAlloc2(alignment = 0x%016" PRIx64 ") failed: 0x%08" PRIx32 "\n", alignment, static_cast<uint32_t>(GetLastError()));
return AllocAligned(address, size, mode, alignment << 1u);
}
return ptr;
}