fix some issues

This commit is contained in:
InoriRus 2022-06-14 19:41:45 +10:00
parent f1f4302f99
commit 1aa7cf72ce
12 changed files with 486 additions and 200 deletions

View File

@ -1,4 +1,4 @@
version: 0.1.6.build-{build} version: 0.1.7.build-{build}
image: Visual Studio 2019 image: Visual Studio 2019
environment: environment:
matrix: matrix:

View File

@ -1 +1,3 @@
doc/** filter=lfs diff=lfs merge=lfs -text doc/** filter=lfs diff=lfs merge=lfs -text
*.inc linguist-language=C++

View File

@ -82,7 +82,7 @@ if (KYTY_LINKER STREQUAL LD)
set(KYTY_LD_OPTIONS "-Wl,--image-base=0x100000000000") set(KYTY_LD_OPTIONS "-Wl,--image-base=0x100000000000")
endif() endif()
project(Kyty${KYTY_PROJECT_NAME}${CMAKE_BUILD_TYPE}${KYTY_COMPILER} VERSION 0.1.6) project(Kyty${KYTY_PROJECT_NAME}${CMAKE_BUILD_TYPE}${KYTY_COMPILER} VERSION 0.1.7)
include(src_script.cmake) include(src_script.cmake)

View File

@ -13,6 +13,7 @@ namespace Kyty::Libs::Graphics {
enum class RenderTextureFormat : uint64_t enum class RenderTextureFormat : uint64_t
{ {
Unknown, Unknown,
R8Unorm,
R8G8B8A8Unorm, R8G8B8A8Unorm,
R8G8B8A8Srgb, R8G8B8A8Srgb,
B8G8R8A8Unorm, B8G8R8A8Unorm,

View File

@ -6,9 +6,9 @@
#include "Kyty/Core/Vector.h" #include "Kyty/Core/Vector.h"
#include "Emulator/Common.h" #include "Emulator/Common.h"
#include "Emulator/Graphics/Shader.h"
#include <algorithm> #include <algorithm>
#ifdef KYTY_EMU_ENABLED #ifdef KYTY_EMU_ENABLED
namespace Kyty::Libs::Graphics { namespace Kyty::Libs::Graphics {
@ -57,6 +57,7 @@ enum class ShaderInstructionType
SAndn2B64, SAndn2B64,
SAndSaveexecB64, SAndSaveexecB64,
SBfmB32, SBfmB32,
SBranch,
SBufferLoadDword, SBufferLoadDword,
SBufferLoadDwordx16, SBufferLoadDwordx16,
SBufferLoadDwordx2, SBufferLoadDwordx2,
@ -66,6 +67,7 @@ enum class ShaderInstructionType
SCbranchScc0, SCbranchScc0,
SCbranchScc1, SCbranchScc1,
SCbranchVccz, SCbranchVccz,
SCbranchVccnz,
SCmpEqI32, SCmpEqI32,
SCmpEqU32, SCmpEqU32,
SCmpGeI32, SCmpGeI32,
@ -260,6 +262,7 @@ enum FormatByte : uint64_t
Dmask8, // dmask:0x8 Dmask8, // dmask:0x8
Dmask3, // dmask:0x3 Dmask3, // dmask:0x3
Dmask5, // dmask:0x5 Dmask5, // dmask:0x5
Dmask9, // dmask:0x9
Gds, // gds Gds, // gds
}; };
@ -308,6 +311,7 @@ enum Format : uint64_t
Vdata1VaddrSvSoffsIdxenFloat1 = FormatDefine({D, S0, S1A4, S2, Idxen, Float1}), Vdata1VaddrSvSoffsIdxenFloat1 = FormatDefine({D, S0, S1A4, S2, Idxen, Float1}),
Vdata2Vaddr3StSsDmask3 = FormatDefine({DA2, S0A3, S1A8, S2A4, Dmask3}), Vdata2Vaddr3StSsDmask3 = FormatDefine({DA2, S0A3, S1A8, S2A4, Dmask3}),
Vdata2Vaddr3StSsDmask5 = FormatDefine({DA2, S0A3, S1A8, S2A4, Dmask5}), Vdata2Vaddr3StSsDmask5 = FormatDefine({DA2, S0A3, S1A8, S2A4, Dmask5}),
Vdata2Vaddr3StSsDmask9 = FormatDefine({DA2, S0A3, S1A8, S2A4, Dmask9}),
Vdata2VaddrSvSoffsIdxen = FormatDefine({DA2, S0, S1A4, S2, Idxen}), Vdata2VaddrSvSoffsIdxen = FormatDefine({DA2, S0, S1A4, S2, Idxen}),
Vdata3Vaddr3StSsDmask7 = FormatDefine({DA3, S0A3, S1A8, S2A4, Dmask7}), Vdata3Vaddr3StSsDmask7 = FormatDefine({DA3, S0A3, S1A8, S2A4, Dmask7}),
Vdata3Vaddr4StSsDmask7 = FormatDefine({DA3, S0A4, S1A8, S2A4, Dmask7}), Vdata3Vaddr4StSsDmask7 = FormatDefine({DA3, S0A4, S1A8, S2A4, Dmask7}),
@ -418,6 +422,14 @@ struct ShaderDebugPrintf
Vector<ShaderOperand> args; Vector<ShaderOperand> args;
}; };
struct ShaderControlFlowBlock
{
uint32_t pc = 0;
bool is_discard = false;
bool is_valid = false;
ShaderInstruction last;
};
class ShaderCode class ShaderCode
{ {
public: public:
@ -455,9 +467,11 @@ public:
[[nodiscard]] uint32_t GetPsEmbeddedId() const { return m_ps_embedded_id; } [[nodiscard]] uint32_t GetPsEmbeddedId() const { return m_ps_embedded_id; }
void SetPsEmbeddedId(uint32_t embedded_id) { m_ps_embedded_id = embedded_id; } void SetPsEmbeddedId(uint32_t embedded_id) { m_ps_embedded_id = embedded_id; }
[[nodiscard]] bool IsDiscardBlock(uint32_t pc) const; //[[nodiscard]] bool IsDiscardBlock(uint32_t pc) const;
[[nodiscard]] bool IsDiscardInstruction(uint32_t index) const; //[[nodiscard]] bool IsDiscardInstruction(uint32_t index) const;
[[nodiscard]] Vector<ShaderInstruction> GetDiscardBlock(uint32_t pc) const; //[[nodiscard]] Vector<ShaderInstruction> GetDiscardBlock(uint32_t pc) const;
[[nodiscard]] ShaderControlFlowBlock ReadBlock(uint32_t pc) const;
[[nodiscard]] Vector<ShaderInstruction> ReadIntructions(const ShaderControlFlowBlock& block) const;
[[nodiscard]] uint32_t GetCrc32() const { return m_crc32; } [[nodiscard]] uint32_t GetCrc32() const { return m_crc32; }
void SetCrc32(uint32_t c) { this->m_crc32 = c; } void SetCrc32(uint32_t c) { this->m_crc32 = c; }

View File

@ -1128,9 +1128,12 @@ static void playback_simulate(void* arg)
EXIT_IF(play_data == nullptr); EXIT_IF(play_data == nullptr);
// TODO(): Audio output is not yet implemented, so simulate audio delay if (play_data != nullptr)
Core::Thread::SleepMicro(port->data_delay); {
play_data->state = Audio3dData::State::Empty; // TODO(): Audio output is not yet implemented, so simulate audio delay
Core::Thread::SleepMicro(port->data_delay);
play_data->state = Audio3dData::State::Empty;
}
} }
port->playback_finished = true; port->playback_finished = true;

View File

@ -476,46 +476,50 @@ static void uc_print(const char* func, const HW::UserConfig& uc)
// EXIT_NOT_IMPLEMENTED(uc.GetPrimType() != 4); // EXIT_NOT_IMPLEMENTED(uc.GetPrimType() != 4);
//} //}
static void rt_print(const char* func, const HW::RenderTarget& rt) static Core::StringList rt_print(const char* func, const HW::RenderTarget& rt)
{ {
printf("%s\n", func); Core::StringList dst;
printf("\t base.addr = 0x%016" PRIx64 "\n", rt.base.addr); dst.Add(String::FromPrintf("%s\n", func));
printf("\t pitch.pitch_div8_minus1 = 0x%08" PRIx32 "\n", rt.pitch.pitch_div8_minus1);
printf("\t pitch.fmask_pitch_div8_minus1 = 0x%08" PRIx32 "\n", rt.pitch.fmask_pitch_div8_minus1); dst.Add(String::FromPrintf("\t base.addr = 0x%016" PRIx64 "\n", rt.base.addr));
printf("\t slice.slice_div64_minus1 = 0x%08" PRIx32 "\n", rt.slice.slice_div64_minus1); dst.Add(String::FromPrintf("\t pitch.pitch_div8_minus1 = 0x%08" PRIx32 "\n", rt.pitch.pitch_div8_minus1));
printf("\t view.base_array_slice_index = 0x%08" PRIx32 "\n", rt.view.base_array_slice_index); dst.Add(String::FromPrintf("\t pitch.fmask_pitch_div8_minus1 = 0x%08" PRIx32 "\n", rt.pitch.fmask_pitch_div8_minus1));
printf("\t view.last_array_slice_index = 0x%08" PRIx32 "\n", rt.view.last_array_slice_index); dst.Add(String::FromPrintf("\t slice.slice_div64_minus1 = 0x%08" PRIx32 "\n", rt.slice.slice_div64_minus1));
printf("\t info.fmask_compression_enable = %s\n", rt.info.fmask_compression_enable ? "true" : "false"); dst.Add(String::FromPrintf("\t view.base_array_slice_index = 0x%08" PRIx32 "\n", rt.view.base_array_slice_index));
printf("\t info.fmask_compression_mode = 0x%08" PRIx32 "\n", rt.info.fmask_compression_mode); dst.Add(String::FromPrintf("\t view.last_array_slice_index = 0x%08" PRIx32 "\n", rt.view.last_array_slice_index));
printf("\t info.cmask_fast_clear_enable = %s\n", rt.info.cmask_fast_clear_enable ? "true" : "false"); dst.Add(String::FromPrintf("\t info.fmask_compression_enable = %s\n", rt.info.fmask_compression_enable ? "true" : "false"));
printf("\t info.dcc_compression_enable = %s\n", rt.info.dcc_compression_enable ? "true" : "false"); dst.Add(String::FromPrintf("\t info.fmask_compression_mode = 0x%08" PRIx32 "\n", rt.info.fmask_compression_mode));
printf("\t info.neo_mode = %s\n", rt.info.neo_mode ? "true" : "false"); dst.Add(String::FromPrintf("\t info.cmask_fast_clear_enable = %s\n", rt.info.cmask_fast_clear_enable ? "true" : "false"));
printf("\t info.cmask_tile_mode = 0x%08" PRIx32 "\n", rt.info.cmask_tile_mode); dst.Add(String::FromPrintf("\t info.dcc_compression_enable = %s\n", rt.info.dcc_compression_enable ? "true" : "false"));
printf("\t info.cmask_tile_mode_neo = 0x%08" PRIx32 "\n", rt.info.cmask_tile_mode_neo); dst.Add(String::FromPrintf("\t info.neo_mode = %s\n", rt.info.neo_mode ? "true" : "false"));
printf("\t info.format = 0x%08" PRIx32 "\n", rt.info.format); dst.Add(String::FromPrintf("\t info.cmask_tile_mode = 0x%08" PRIx32 "\n", rt.info.cmask_tile_mode));
printf("\t info.channel_type = 0x%08" PRIx32 "\n", rt.info.channel_type); dst.Add(String::FromPrintf("\t info.cmask_tile_mode_neo = 0x%08" PRIx32 "\n", rt.info.cmask_tile_mode_neo));
printf("\t info.channel_order = 0x%08" PRIx32 "\n", rt.info.channel_order); dst.Add(String::FromPrintf("\t info.format = 0x%08" PRIx32 "\n", rt.info.format));
printf("\t attrib.force_dest_alpha_to_one = %s\n", rt.attrib.force_dest_alpha_to_one ? "true" : "false"); dst.Add(String::FromPrintf("\t info.channel_type = 0x%08" PRIx32 "\n", rt.info.channel_type));
printf("\t attrib.tile_mode = 0x%08" PRIx32 "\n", rt.attrib.tile_mode); dst.Add(String::FromPrintf("\t info.channel_order = 0x%08" PRIx32 "\n", rt.info.channel_order));
printf("\t attrib.fmask_tile_mode = 0x%08" PRIx32 "\n", rt.attrib.fmask_tile_mode); dst.Add(String::FromPrintf("\t attrib.force_dest_alpha_to_one = %s\n", rt.attrib.force_dest_alpha_to_one ? "true" : "false"));
printf("\t attrib.num_samples = 0x%08" PRIx32 "\n", rt.attrib.num_samples); dst.Add(String::FromPrintf("\t attrib.tile_mode = 0x%08" PRIx32 "\n", rt.attrib.tile_mode));
printf("\t attrib.num_fragments = 0x%08" PRIx32 "\n", rt.attrib.num_fragments); dst.Add(String::FromPrintf("\t attrib.fmask_tile_mode = 0x%08" PRIx32 "\n", rt.attrib.fmask_tile_mode));
printf("\t dcc.max_uncompressed_block_size = 0x%08" PRIx32 "\n", rt.dcc.max_uncompressed_block_size); dst.Add(String::FromPrintf("\t attrib.num_samples = 0x%08" PRIx32 "\n", rt.attrib.num_samples));
printf("\t dcc.max_compressed_block_size = 0x%08" PRIx32 "\n", rt.dcc.max_compressed_block_size); dst.Add(String::FromPrintf("\t attrib.num_fragments = 0x%08" PRIx32 "\n", rt.attrib.num_fragments));
printf("\t dcc.min_compressed_block_size = 0x%08" PRIx32 "\n", rt.dcc.min_compressed_block_size); dst.Add(String::FromPrintf("\t dcc.max_uncompressed_block_size = 0x%08" PRIx32 "\n", rt.dcc.max_uncompressed_block_size));
printf("\t dcc.color_transform = 0x%08" PRIx32 "\n", rt.dcc.color_transform); dst.Add(String::FromPrintf("\t dcc.max_compressed_block_size = 0x%08" PRIx32 "\n", rt.dcc.max_compressed_block_size));
printf("\t dcc.enable_overwrite_combiner = %s\n", rt.dcc.enable_overwrite_combiner ? "true" : "false"); dst.Add(String::FromPrintf("\t dcc.min_compressed_block_size = 0x%08" PRIx32 "\n", rt.dcc.min_compressed_block_size));
printf("\t dcc.force_independent_blocks = %s\n", rt.dcc.force_independent_blocks ? "true" : "false"); dst.Add(String::FromPrintf("\t dcc.color_transform = 0x%08" PRIx32 "\n", rt.dcc.color_transform));
printf("\t cmask.addr = 0x%016" PRIx64 "\n", rt.cmask.addr); dst.Add(String::FromPrintf("\t dcc.enable_overwrite_combiner = %s\n", rt.dcc.enable_overwrite_combiner ? "true" : "false"));
printf("\t cmask_slice.slice_minus1 = 0x%08" PRIx32 "\n", rt.cmask_slice.slice_minus1); dst.Add(String::FromPrintf("\t dcc.force_independent_blocks = %s\n", rt.dcc.force_independent_blocks ? "true" : "false"));
printf("\t fmask.addr = 0x%016" PRIx64 "\n", rt.fmask.addr); dst.Add(String::FromPrintf("\t cmask.addr = 0x%016" PRIx64 "\n", rt.cmask.addr));
printf("\t fmask_slice.slice_minus1 = 0x%08" PRIx32 "\n", rt.fmask_slice.slice_minus1); dst.Add(String::FromPrintf("\t cmask_slice.slice_minus1 = 0x%08" PRIx32 "\n", rt.cmask_slice.slice_minus1));
printf("\t clear_word0.word0 = 0x%08" PRIx32 "\n", rt.clear_word0.word0); dst.Add(String::FromPrintf("\t fmask.addr = 0x%016" PRIx64 "\n", rt.fmask.addr));
printf("\t clear_word1.word1 = 0x%08" PRIx32 "\n", rt.clear_word1.word1); dst.Add(String::FromPrintf("\t fmask_slice.slice_minus1 = 0x%08" PRIx32 "\n", rt.fmask_slice.slice_minus1));
printf("\t dcc_addr.addr = 0x%016" PRIx64 "\n", rt.dcc_addr.addr); dst.Add(String::FromPrintf("\t clear_word0.word0 = 0x%08" PRIx32 "\n", rt.clear_word0.word0));
printf("\t size.width = 0x%08" PRIx32 "\n", rt.size.width); dst.Add(String::FromPrintf("\t clear_word1.word1 = 0x%08" PRIx32 "\n", rt.clear_word1.word1));
printf("\t size.height = 0x%08" PRIx32 "\n", rt.size.height); dst.Add(String::FromPrintf("\t dcc_addr.addr = 0x%016" PRIx64 "\n", rt.dcc_addr.addr));
dst.Add(String::FromPrintf("\t size.width = 0x%08" PRIx32 "\n", rt.size.width));
dst.Add(String::FromPrintf("\t size.height = 0x%08" PRIx32 "\n", rt.size.height));
return dst;
} }
// NOLINTNEXTLINE(readability-function-cognitive-complexity) // NOLINTNEXTLINE(readability-function-cognitive-complexity)
@ -1039,22 +1043,26 @@ static void hw_print(const HW::HardwareContext& hw)
const auto& aa = hw.GetAaSampleControl(); const auto& aa = hw.GetAaSampleControl();
const auto& ac = hw.GetAaConfig(); const auto& ac = hw.GetAaConfig();
printf("HardwareContext\n"); if (Kyty::Log::GetDirection() != Kyty::Log::Direction::Silent)
printf("\t GetRenderTargetMask() = 0x%08" PRIx32 "\n", hw.GetRenderTargetMask()); {
printf("\t GetDepthClearValue() = %f\n", hw.GetDepthClearValue()); printf("HardwareContext\n");
printf("\t GetStencilClearValue() = %" PRIu8 "\n", hw.GetStencilClearValue()); printf("\t GetRenderTargetMask() = 0x%08" PRIx32 "\n", hw.GetRenderTargetMask());
printf("\t GetLineWidth() = %f\n", hw.GetLineWidth()); printf("\t GetDepthClearValue() = %f\n", hw.GetDepthClearValue());
printf("\t GetStencilClearValue() = %" PRIu8 "\n", hw.GetStencilClearValue());
printf("\t GetLineWidth() = %f\n", hw.GetLineWidth());
rt_print("RenderTraget:", rt); printf("%s", rt_print("RenderTraget:", rt).Concat(U"").C_Str());
z_print("DepthRenderTraget:", z);
vp_print("ScreenViewport:", vp, smc); z_print("DepthRenderTraget:", z);
clip_print("ClipControl:", c); vp_print("ScreenViewport:", vp, smc);
rc_print("RenderControl:", rc); clip_print("ClipControl:", c);
d_print("DepthStencilControlMask:", d, s, sm); rc_print("RenderControl:", rc);
mc_print("ModeControl:", mc); d_print("DepthStencilControlMask:", d, s, sm);
bc_print("BlendColorControl:", bc, bclr, cc); mc_print("ModeControl:", mc);
eqaa_print("EqaaControl:", eqaa); bc_print("BlendColorControl:", bc, bclr, cc);
aa_print("AaSampleControl:", aa, ac); eqaa_print("EqaaControl:", eqaa);
aa_print("AaSampleControl:", aa, ac);
}
} }
void GraphicsRenderInit() void GraphicsRenderInit()
@ -3828,9 +3836,12 @@ static void FindRenderColorInfo(uint64_t submit_id, CommandBuffer* buffer, const
} else if (rt.info.format == 0xa && rt.info.channel_type == 0x6 && rt.info.channel_order == 0x1) } else if (rt.info.format == 0xa && rt.info.channel_type == 0x6 && rt.info.channel_order == 0x1)
{ {
rt_format = RenderTextureFormat::B8G8R8A8Srgb; rt_format = RenderTextureFormat::B8G8R8A8Srgb;
} else if (rt.info.format == 0x1 && rt.info.channel_type == 0x0 && rt.info.channel_order == 0x0)
{
rt_format = RenderTextureFormat::R8Unorm;
} else } else
{ {
EXIT("unknown format"); EXIT("%s\n unknown format\n", rt_print("RenderTarget", rt).Concat(U"").C_Str());
} }
// Render to texture // Render to texture

View File

@ -836,6 +836,18 @@ bool GpuMemory::create_maybe_deleted(const Vector<OverlappedBlock>& others, GpuM
o_type == GpuMemoryObjectType::Texture); o_type == GpuMemoryObjectType::Texture);
}); });
} }
if (type == GpuMemoryObjectType::RenderTexture)
{
return std::all_of(others.begin(), others.end(),
[heap](auto& r)
{
OverlapType rel = r.relation;
const auto& o = heap.objects[r.object_id];
GpuMemoryObjectType o_type = o.info.object.type;
return ((rel == OverlapType::IsContainedWithin || rel == OverlapType::Crosses) &&
(o_type == GpuMemoryObjectType::RenderTexture || o_type == GpuMemoryObjectType::DepthStencilBuffer));
});
}
return false; return false;
} }

View File

@ -163,8 +163,9 @@ static void* create_func(GraphicContext* ctx, const uint64_t* params, const uint
VkFormat vk_format = VK_FORMAT_UNDEFINED; VkFormat vk_format = VK_FORMAT_UNDEFINED;
switch (pixel_format) // NOLINT switch (pixel_format)
{ {
case static_cast<uint64_t>(RenderTextureFormat::R8Unorm): vk_format = VK_FORMAT_R8_UNORM; break;
case static_cast<uint64_t>(RenderTextureFormat::R8G8B8A8Unorm): vk_format = VK_FORMAT_R8G8B8A8_UNORM; break; 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::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::B8G8R8A8Unorm): vk_format = VK_FORMAT_B8G8R8A8_UNORM; break;
@ -292,8 +293,9 @@ static void* create2_func(GraphicContext* ctx, CommandBuffer* buffer, const uint
VkFormat vk_format = VK_FORMAT_UNDEFINED; VkFormat vk_format = VK_FORMAT_UNDEFINED;
switch (pixel_format) // NOLINT switch (pixel_format)
{ {
case static_cast<uint64_t>(RenderTextureFormat::R8Unorm): vk_format = VK_FORMAT_R8_UNORM; break;
case static_cast<uint64_t>(RenderTextureFormat::R8G8B8A8Unorm): vk_format = VK_FORMAT_R8G8B8A8_UNORM; break; 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::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::B8G8R8A8Unorm): vk_format = VK_FORMAT_B8G8R8A8_UNORM; break;

View File

@ -229,6 +229,7 @@ static String dbg_fmt_to_str(const ShaderInstruction& inst)
case ShaderInstructionFormat::Vdata1Vaddr3StSsDmask8: return U"Vdata1Vaddr3StSsDmask8"; break; case ShaderInstructionFormat::Vdata1Vaddr3StSsDmask8: return U"Vdata1Vaddr3StSsDmask8"; break;
case ShaderInstructionFormat::Vdata2Vaddr3StSsDmask3: return U"Vdata2Vaddr3StSsDmask3"; break; case ShaderInstructionFormat::Vdata2Vaddr3StSsDmask3: return U"Vdata2Vaddr3StSsDmask3"; break;
case ShaderInstructionFormat::Vdata2Vaddr3StSsDmask5: return U"Vdata2Vaddr3StSsDmask5"; break; case ShaderInstructionFormat::Vdata2Vaddr3StSsDmask5: return U"Vdata2Vaddr3StSsDmask5"; break;
case ShaderInstructionFormat::Vdata2Vaddr3StSsDmask9: return U"Vdata2Vaddr3StSsDmask9"; break;
case ShaderInstructionFormat::Vdata3Vaddr3StSsDmask7: return U"Vdata3Vaddr3StSsDmask7"; break; case ShaderInstructionFormat::Vdata3Vaddr3StSsDmask7: return U"Vdata3Vaddr3StSsDmask7"; break;
case ShaderInstructionFormat::Vdata3Vaddr4StSsDmask7: return U"Vdata3Vaddr4StSsDmask7"; break; case ShaderInstructionFormat::Vdata3Vaddr4StSsDmask7: return U"Vdata3Vaddr4StSsDmask7"; break;
case ShaderInstructionFormat::Vdata4Vaddr3StSsDmaskF: return U"Vdata4Vaddr3StSsDmaskF"; break; case ShaderInstructionFormat::Vdata4Vaddr3StSsDmaskF: return U"Vdata4Vaddr3StSsDmaskF"; break;
@ -311,6 +312,7 @@ static String dbg_fmt_print(const ShaderInstruction& inst)
case ShaderInstructionFormat::Dmask3: s = U"dmask:0x3"; break; case ShaderInstructionFormat::Dmask3: s = U"dmask:0x3"; break;
case ShaderInstructionFormat::Dmask5: s = U"dmask:0x5"; break; case ShaderInstructionFormat::Dmask5: s = U"dmask:0x5"; break;
case ShaderInstructionFormat::Dmask7: s = U"dmask:0x7"; break; case ShaderInstructionFormat::Dmask7: s = U"dmask:0x7"; break;
case ShaderInstructionFormat::Dmask9: s = U"dmask:0x9"; break;
case ShaderInstructionFormat::DmaskF: s = U"dmask:0xf"; break; case ShaderInstructionFormat::DmaskF: s = U"dmask:0xf"; break;
case ShaderInstructionFormat::Gds: s = U"gds"; break; case ShaderInstructionFormat::Gds: s = U"gds"; break;
default: EXIT("unknown code: %u\n", static_cast<uint32_t>(fu)); default: EXIT("unknown code: %u\n", static_cast<uint32_t>(fu));
@ -385,13 +387,13 @@ String ShaderCode::DbgDump() const
return ret; return ret;
} }
bool ShaderCode::IsDiscardInstruction(uint32_t index) const static bool IsDiscardInstruction(const Vector<ShaderInstruction>& code, uint32_t index)
{ {
if (!(index == 0 || index + 1 >= m_instructions.Size())) if (!(index == 0 || index + 1 >= code.Size()))
{ {
const auto& prev_inst = m_instructions.At(index - 1); const auto& prev_inst = code.At(index - 1);
const auto& inst = m_instructions.At(index); const auto& inst = code.At(index);
const auto& next_inst = m_instructions.At(index + 1); const auto& next_inst = code.At(index + 1);
return (inst.type == ShaderInstructionType::Exp && inst.format == ShaderInstructionFormat::Mrt0OffOffComprVmDone && return (inst.type == ShaderInstructionType::Exp && inst.format == ShaderInstructionFormat::Mrt0OffOffComprVmDone &&
prev_inst.type == ShaderInstructionType::SMovB64 && prev_inst.format == ShaderInstructionFormat::Sdst2Ssrc02 && prev_inst.type == ShaderInstructionType::SMovB64 && prev_inst.format == ShaderInstructionFormat::Sdst2Ssrc02 &&
@ -401,37 +403,72 @@ bool ShaderCode::IsDiscardInstruction(uint32_t index) const
return false; return false;
} }
bool ShaderCode::IsDiscardBlock(uint32_t pc) const // bool ShaderCode::IsDiscardBlock(uint32_t pc) const
//{
// auto inst_count = m_instructions.Size();
// for (uint32_t index = 0; index < inst_count; index++)
// {
// const auto& inst = m_instructions.At(index);
// if (inst.pc == pc)
// {
// for (uint32_t i = index; i < inst_count; i++)
// {
// const auto& inst = m_instructions.At(i);
//
// if (inst.type == ShaderInstructionType::SEndpgm || inst.type == ShaderInstructionType::SCbranchExecz ||
// inst.type == ShaderInstructionType::SCbranchScc0 || inst.type == ShaderInstructionType::SCbranchScc1 ||
// inst.type == ShaderInstructionType::SCbranchVccz)
// {
// return false;
// }
//
// if (IsDiscardInstruction(i))
// {
// return true;
// }
// }
// return false;
// }
// }
// return false;
// }
ShaderControlFlowBlock ShaderCode::ReadBlock(uint32_t pc) const
{ {
auto inst_count = m_instructions.Size(); ShaderControlFlowBlock ret;
auto inst_count = m_instructions.Size();
for (uint32_t index = 0; index < inst_count; index++) for (uint32_t index = 0; index < inst_count; index++)
{ {
const auto& inst = m_instructions.At(index); const auto& inst = m_instructions.At(index);
if (inst.pc == pc) if (inst.pc == pc)
{ {
ret.pc = pc;
ret.is_valid = true;
for (uint32_t i = index; i < inst_count; i++) for (uint32_t i = index; i < inst_count; i++)
{ {
const auto& inst = m_instructions.At(i); const auto& inst = m_instructions.At(i);
if (inst.type == ShaderInstructionType::SEndpgm || inst.type == ShaderInstructionType::SCbranchExecz || if (inst.type == ShaderInstructionType::SEndpgm || inst.type == ShaderInstructionType::SCbranchExecz ||
inst.type == ShaderInstructionType::SCbranchScc0 || inst.type == ShaderInstructionType::SCbranchScc1 || inst.type == ShaderInstructionType::SCbranchScc0 || inst.type == ShaderInstructionType::SCbranchScc1 ||
inst.type == ShaderInstructionType::SCbranchVccz) inst.type == ShaderInstructionType::SCbranchVccz || inst.type == ShaderInstructionType::SCbranchVccnz ||
inst.type == ShaderInstructionType::SBranch)
{ {
return false; ret.last = inst;
break;
} }
if (IsDiscardInstruction(i)) if (IsDiscardInstruction(m_instructions, i))
{ {
return true; ret.is_discard = true;
} }
} }
return false; break;
} }
} }
return false; return ret;
} }
Vector<ShaderInstruction> ShaderCode::GetDiscardBlock(uint32_t pc) const Vector<ShaderInstruction> ShaderCode::ReadIntructions(const ShaderControlFlowBlock& block) const
{ {
Vector<ShaderInstruction> ret; Vector<ShaderInstruction> ret;
@ -439,7 +476,7 @@ Vector<ShaderInstruction> ShaderCode::GetDiscardBlock(uint32_t pc) const
for (uint32_t index = 0; index < inst_count; index++) for (uint32_t index = 0; index < inst_count; index++)
{ {
const auto& inst = m_instructions.At(index); const auto& inst = m_instructions.At(index);
if (inst.pc == pc) if (inst.pc == block.pc)
{ {
for (uint32_t i = index; i < inst_count; i++) for (uint32_t i = index; i < inst_count; i++)
{ {
@ -447,9 +484,8 @@ Vector<ShaderInstruction> ShaderCode::GetDiscardBlock(uint32_t pc) const
ret.Add(inst); ret.Add(inst);
if (IsDiscardInstruction(i)) if (inst.pc == block.last.pc)
{ {
ret.Add(m_instructions.At(i + 1));
break; break;
} }
} }
@ -460,6 +496,35 @@ Vector<ShaderInstruction> ShaderCode::GetDiscardBlock(uint32_t pc) const
return ret; return ret;
} }
// 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) static ShaderOperand operand_parse(uint32_t code)
{ {
ShaderOperand ret; ShaderOperand ret;
@ -634,9 +699,11 @@ KYTY_SHADER_PARSER(shader_parse_sopp)
inst.format = ShaderInstructionFormat::Empty; inst.format = ShaderInstructionFormat::Empty;
inst.src_num = 0; inst.src_num = 0;
break; break;
case 0x02: inst.type = ShaderInstructionType::SBranch; break;
case 0x04: inst.type = ShaderInstructionType::SCbranchScc0; break; case 0x04: inst.type = ShaderInstructionType::SCbranchScc0; break;
case 0x05: inst.type = ShaderInstructionType::SCbranchScc1; break; case 0x05: inst.type = ShaderInstructionType::SCbranchScc1; break;
case 0x06: inst.type = ShaderInstructionType::SCbranchVccz; break; case 0x06: inst.type = ShaderInstructionType::SCbranchVccz; break;
case 0x07: inst.type = ShaderInstructionType::SCbranchVccnz; break;
case 0x08: inst.type = ShaderInstructionType::SCbranchExecz; break; case 0x08: inst.type = ShaderInstructionType::SCbranchExecz; break;
case 0x0c: case 0x0c:
inst.type = ShaderInstructionType::SWaitcnt; inst.type = ShaderInstructionType::SWaitcnt;
@ -653,7 +720,8 @@ KYTY_SHADER_PARSER(shader_parse_sopp)
dst->GetInstructions().Add(inst); dst->GetInstructions().Add(inst);
if (inst.type == ShaderInstructionType::SCbranchScc0 || inst.type == ShaderInstructionType::SCbranchScc1 || if (inst.type == ShaderInstructionType::SCbranchScc0 || inst.type == ShaderInstructionType::SCbranchScc1 ||
inst.type == ShaderInstructionType::SCbranchVccz || inst.type == ShaderInstructionType::SCbranchExecz) inst.type == ShaderInstructionType::SCbranchVccz || inst.type == ShaderInstructionType::SCbranchVccnz ||
inst.type == ShaderInstructionType::SCbranchExecz || inst.type == ShaderInstructionType::SBranch)
{ {
dst->GetLabels().Add(ShaderLabel(inst)); dst->GetLabels().Add(ShaderLabel(inst));
} }
@ -1777,6 +1845,12 @@ KYTY_SHADER_PARSER(shader_parse_mimg)
inst.dst.size = 1; inst.dst.size = 1;
break; break;
} }
case 0x9:
{
inst.format = ShaderInstructionFormat::Vdata2Vaddr3StSsDmask9;
inst.dst.size = 2;
break;
}
case 0xf: case 0xf:
{ {
inst.format = ShaderInstructionFormat::Vdata4Vaddr3StSsDmaskF; inst.format = ShaderInstructionFormat::Vdata4Vaddr3StSsDmaskF;

View File

@ -2049,24 +2049,15 @@ KYTY_RECOMPILER_FUNC(Recompile_Exp_Mrt0OffOffComprVmDone)
{ {
EXIT_NOT_IMPLEMENTED(index == 0 || index + 1 >= code.GetInstructions().Size()); EXIT_NOT_IMPLEMENTED(index == 0 || index + 1 >= code.GetInstructions().Size());
if (!code.IsDiscardInstruction(index)) const auto& prev_inst = code.GetInstructions().At(index - 1);
const auto& inst = code.GetInstructions().At(index);
auto block = code.ReadBlock(prev_inst.pc);
if (!block.is_discard)
{ {
return false; return false;
} }
// const auto& prev_inst = code.GetInstructions().At(index - 1);
// const auto& inst = code.GetInstructions().At(index);
// const auto& next_inst = code.GetInstructions().At(index + 1);
//
// if (!(prev_inst.type == ShaderInstructionType::SMovB64 && prev_inst.format == ShaderInstructionFormat::Sdst2Ssrc02 &&
// prev_inst.dst.type == ShaderOperandType::ExecLo && prev_inst.src[0].type == ShaderOperandType::IntegerInlineConstant &&
// prev_inst.src[0].constant.i == 0 && next_inst.type == ShaderInstructionType::SEndpgm))
// {
// return false;
// }
const auto& inst = code.GetInstructions().At(index);
const auto* info = spirv->GetPsInputInfo(); const auto* info = spirv->GetPsInputInfo();
EXIT_NOT_IMPLEMENTED(info == nullptr || !info->ps_pixel_kill_enable); EXIT_NOT_IMPLEMENTED(info == nullptr || !info->ps_pixel_kill_enable);
@ -2463,6 +2454,65 @@ KYTY_RECOMPILER_FUNC(Recompile_ImageSample_Vdata2Vaddr3StSsDmask5)
return false; return false;
} }
KYTY_RECOMPILER_FUNC(Recompile_ImageSample_Vdata2Vaddr3StSsDmask9)
{
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_3
%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) KYTY_RECOMPILER_FUNC(Recompile_ImageSample_Vdata3Vaddr3StSsDmask7)
{ {
const auto& inst = code.GetInstructions().At(index); const auto& inst = code.GetInstructions().At(index);
@ -3520,22 +3570,41 @@ KYTY_RECOMPILER_FUNC(Recompile_SBufferLoadDwordx16_Sdst16SvSoffset)
return false; return false;
} }
KYTY_RECOMPILER_FUNC(Recompile_SCbranchExecz_Label) // KYTY_RECOMPILER_FUNC(Recompile_SCbranchExecz_Label)
//{
// const auto& inst = code.GetInstructions().At(index);
//
// EXIT_NOT_IMPLEMENTED(!operand_is_constant(inst.src[0]));
//
// EXIT_NOT_IMPLEMENTED(code.ReadBlock(ShaderLabel(inst).GetDst()).is_discard);
//
// String label = ShaderLabel(inst).ToString();
//
// static const char32_t* text = UR"(
// %execz_u_<index> = OpLoad %uint %execz
// %execz_b_<index> = OpINotEqual %bool %execz_u_<index> %uint_0
// OpSelectionMerge %<label> None
// OpBranchConditional %execz_b_<index> %<label> %t230_<index>
// %t230_<index> = OpLabel
//)";
//
// *dst_source += String(text).ReplaceStr(U"<index>", String::FromPrintf("%u", index)).ReplaceStr(U"<label>", label);
//
// return true;
// }
KYTY_RECOMPILER_FUNC(Recompile_SBranch_Label)
{ {
const auto& inst = code.GetInstructions().At(index); const auto& inst = code.GetInstructions().At(index);
EXIT_NOT_IMPLEMENTED(!operand_is_constant(inst.src[0])); EXIT_NOT_IMPLEMENTED(!operand_is_constant(inst.src[0]));
EXIT_NOT_IMPLEMENTED(code.IsDiscardBlock(ShaderLabel(inst).GetDst())); EXIT_NOT_IMPLEMENTED(code.ReadBlock(ShaderLabel(inst).GetDst()).is_discard);
String label = ShaderLabel(inst).ToString(); String label = ShaderLabel(inst).ToString();
static const char32_t* text = UR"( static const char32_t* text = UR"(
%execz_u_<index> = OpLoad %uint %execz OpBranch %<label>
%execz_b_<index> = OpINotEqual %bool %execz_u_<index> %uint_0
OpSelectionMerge %<label> None
OpBranchConditional %execz_b_<index> %<label> %t230_<index>
%t230_<index> = OpLabel
)"; )";
*dst_source += String(text).ReplaceStr(U"<index>", String::FromPrintf("%u", index)).ReplaceStr(U"<label>", label); *dst_source += String(text).ReplaceStr(U"<index>", String::FromPrintf("%u", index)).ReplaceStr(U"<label>", label);
@ -3543,110 +3612,197 @@ KYTY_RECOMPILER_FUNC(Recompile_SCbranchExecz_Label)
return true; return true;
} }
KYTY_RECOMPILER_FUNC(Recompile_SCbranchScc0_Label) /* XXX: Execz, Scc0, Scc1, Vccz, Vccnz */
KYTY_RECOMPILER_FUNC(Recompile_SCbranch_XXX_Label)
{ {
const auto& inst = code.GetInstructions().At(index); EXIT_NOT_IMPLEMENTED(index + 1 >= code.GetInstructions().Size());
const auto& inst = code.GetInstructions().At(index);
const auto& next_inst = code.GetInstructions().At(index + 1);
EXIT_NOT_IMPLEMENTED(!operand_is_constant(inst.src[0])); EXIT_NOT_IMPLEMENTED(!operand_is_constant(inst.src[0]));
auto label = ShaderLabel(inst);
// TODO(): analyze control flow graph // TODO(): analyze control flow graph
bool discard = code.IsDiscardBlock(label.GetDst()); auto label = ShaderLabel(inst);
auto dst_block = code.ReadBlock(label.GetDst());
auto next_block = code.ReadBlock(next_inst.pc);
bool discard = dst_block.is_discard;
auto label_next_block = ShaderLabel(next_block.last);
auto label_dst_block = ShaderLabel(dst_block.last);
bool if_else = next_block.is_valid && !next_block.is_discard && dst_block.is_valid && !dst_block.is_discard &&
((next_block.last.type == ShaderInstructionType::SBranch && label_next_block.GetDst() >= dst_block.pc &&
label_next_block.GetDst() <= dst_block.last.pc) ||
(dst_block.last.type == ShaderInstructionType::SBranch && label_dst_block.GetDst() >= next_block.pc &&
label_dst_block.GetDst() <= next_block.last.pc));
String label_str = label.ToString(); String label_str = label.ToString();
String label_merge =
if_else ? (dst_block.last.type == ShaderInstructionType::SBranch ? label_dst_block.ToString() : label_next_block.ToString()) : U"";
// if (condition)
// {
// L1:
// ...
// }
// L2: /* merge */
// ...
static const char32_t* text_variant_a = UR"( static const char32_t* text_variant_a = UR"(
%scc_u_<index> = OpLoad %uint %scc <param0>
%scc_b_<index> = OpIEqual %bool %scc_u_<index> %uint_0 <param1>
OpSelectionMerge %<label> None OpSelectionMerge %<label> None
OpBranchConditional %scc_b_<index> %<label> %t230_<index> OpBranchConditional %cc_b_<index> %<label> %t230_<index>
%t230_<index> = OpLabel
)";
static const char32_t* text_variant_b = UR"(
%scc_u_<index> = OpLoad %uint %scc
%scc_b_<index> = OpIEqual %bool %scc_u_<index> %uint_0
OpSelectionMerge %t230_<index> None
OpBranchConditional %scc_b_<index> %<label> %t230_<index>
%t230_<index> = OpLabel %t230_<index> = OpLabel
)"; )";
*dst_source += String(discard ? text_variant_b : text_variant_a) // if (condition)
// {
// L2:
// ...
// discard;
// }
// L1: /* merge */
// ...
static const char32_t* text_variant_b = UR"(
<param0>
<param1>
OpSelectionMerge %t230_<index> None
OpBranchConditional %cc_b_<index> %<label> %t230_<index>
%t230_<index> = OpLabel
)";
// if (condition)
// {
// L1:
// ...
// } else
// {
// L2:
// ...
// }
// /* merge */
static const char32_t* text_variant_c = UR"(
<param0>
<param1>
OpSelectionMerge %<merge> None
OpBranchConditional %cc_b_<index> %<label> %t230_<index>
%t230_<index> = OpLabel
)";
*dst_source += String(if_else ? text_variant_c : (discard ? text_variant_b : text_variant_a))
.ReplaceStr(U"<param0>", param[0])
.ReplaceStr(U"<param1>", param[1])
.ReplaceStr(U"<merge>", label_merge)
.ReplaceStr(U"<index>", String::FromPrintf("%u", index)) .ReplaceStr(U"<index>", String::FromPrintf("%u", index))
.ReplaceStr(U"<label>", label_str); .ReplaceStr(U"<label>", label_str);
return true; return true;
} }
KYTY_RECOMPILER_FUNC(Recompile_SCbranchScc1_Label) // KYTY_RECOMPILER_FUNC(Recompile_SCbranchScc0_Label)
{ //{
const auto& inst = code.GetInstructions().At(index); // 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.ReadBlock(label.GetDst()).is_discard;
//
// 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
// OpSelectionMerge %<label> None
// OpBranchConditional %scc_b_<index> %<label> %t230_<index>
// %t230_<index> = OpLabel
//)";
// static const char32_t* text_variant_b = UR"(
// %scc_u_<index> = OpLoad %uint %scc
// %scc_b_<index> = OpIEqual %bool %scc_u_<index> %uint_0
// OpSelectionMerge %t230_<index> None
// OpBranchConditional %scc_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;
// }
EXIT_NOT_IMPLEMENTED(!operand_is_constant(inst.src[0])); // KYTY_RECOMPILER_FUNC(Recompile_SCbranchScc1_Label)
//{
auto label = ShaderLabel(inst); // const auto& inst = code.GetInstructions().At(index);
//
// TODO(): analyze control flow graph // EXIT_NOT_IMPLEMENTED(!operand_is_constant(inst.src[0]));
bool discard = code.IsDiscardBlock(label.GetDst()); //
// auto label = ShaderLabel(inst);
String label_str = label.ToString(); //
// // TODO(): analyze control flow graph
static const char32_t* text_variant_a = UR"( // bool discard = code.ReadBlock(label.GetDst()).is_discard;
%scc_u_<index> = OpLoad %uint %scc //
%scc_b_<index> = OpIEqual %bool %scc_u_<index> %uint_1 // String label_str = label.ToString();
OpSelectionMerge %<label> None //
OpBranchConditional %scc_b_<index> %<label> %t230_<index> // static const char32_t* text_variant_a = UR"(
%t230_<index> = OpLabel // %scc_u_<index> = OpLoad %uint %scc
)"; // %scc_b_<index> = OpIEqual %bool %scc_u_<index> %uint_1
static const char32_t* text_variant_b = UR"( // OpSelectionMerge %<label> None
%scc_u_<index> = OpLoad %uint %scc // OpBranchConditional %scc_b_<index> %<label> %t230_<index>
%scc_b_<index> = OpIEqual %bool %scc_u_<index> %uint_1 // %t230_<index> = OpLabel
OpSelectionMerge %t230_<index> None //)";
OpBranchConditional %scc_b_<index> %<label> %t230_<index> // static const char32_t* text_variant_b = UR"(
%t230_<index> = OpLabel // %scc_u_<index> = OpLoad %uint %scc
)"; // %scc_b_<index> = OpIEqual %bool %scc_u_<index> %uint_1
// OpSelectionMerge %t230_<index> None
*dst_source += String(discard ? text_variant_b : text_variant_a) // OpBranchConditional %scc_b_<index> %<label> %t230_<index>
.ReplaceStr(U"<index>", String::FromPrintf("%u", index)) // %t230_<index> = OpLabel
.ReplaceStr(U"<label>", label_str); //)";
//
return true; // *dst_source += String(discard ? text_variant_b : text_variant_a)
} // .ReplaceStr(U"<index>", String::FromPrintf("%u", index))
// .ReplaceStr(U"<label>", label_str);
KYTY_RECOMPILER_FUNC(Recompile_SCbranchVccz_Label) //
{ // return true;
const auto& inst = code.GetInstructions().At(index); // }
//
EXIT_NOT_IMPLEMENTED(!operand_is_constant(inst.src[0])); // KYTY_RECOMPILER_FUNC(Recompile_SCbranchVccz_Label)
//{
auto label = ShaderLabel(inst); // const auto& inst = code.GetInstructions().At(index);
//
// TODO(): analyze control flow graph // EXIT_NOT_IMPLEMENTED(!operand_is_constant(inst.src[0]));
bool discard = code.IsDiscardBlock(label.GetDst()); //
// auto label = ShaderLabel(inst);
String label_str = label.ToString(); //
// // TODO(): analyze control flow graph
static const char32_t* text_variant_a = UR"( // bool discard = code.ReadBlock(label.GetDst()).is_discard;
%vcc_lo_u_<index> = OpLoad %uint %vcc_lo //
%vcc_lo_b_<index> = OpIEqual %bool %vcc_lo_u_<index> %uint_0 // String label_str = label.ToString();
OpSelectionMerge %<label> None //
OpBranchConditional %vcc_lo_b_<index> %<label> %t230_<index> // static const char32_t* text_variant_a = UR"(
%t230_<index> = OpLabel // %vcc_lo_u_<index> = OpLoad %uint %vcc_lo
)"; // %vcc_lo_b_<index> = OpIEqual %bool %vcc_lo_u_<index> %uint_0
static const char32_t* text_variant_b = UR"( // OpSelectionMerge %<label> None
%vcc_lo_u_<index> = OpLoad %uint %vcc_lo // OpBranchConditional %vcc_lo_b_<index> %<label> %t230_<index>
%vcc_lo_b_<index> = OpIEqual %bool %vcc_lo_u_<index> %uint_0 // %t230_<index> = OpLabel
OpSelectionMerge %t230_<index> None //)";
OpBranchConditional %vcc_lo_b_<index> %<label> %t230_<index> // static const char32_t* text_variant_b = UR"(
%t230_<index> = OpLabel // %vcc_lo_u_<index> = OpLoad %uint %vcc_lo
)"; // %vcc_lo_b_<index> = OpIEqual %bool %vcc_lo_u_<index> %uint_0
// OpSelectionMerge %t230_<index> None
*dst_source += String(discard ? text_variant_b : text_variant_a) // OpBranchConditional %vcc_lo_b_<index> %<label> %t230_<index>
.ReplaceStr(U"<index>", String::FromPrintf("%u", index)) // %t230_<index> = OpLabel
.ReplaceStr(U"<label>", label_str); //)";
//
return true; // *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) KYTY_RECOMPILER_FUNC(Recompile_SEndpgm_Empty)
{ {
@ -5407,6 +5563,7 @@ static RecompilerFunc g_recomp_func[] = {
{Recompile_ImageSample_Vdata1Vaddr3StSsDmask8, ShaderInstructionType::ImageSample, ShaderInstructionFormat::Vdata1Vaddr3StSsDmask8, {U""}}, {Recompile_ImageSample_Vdata1Vaddr3StSsDmask8, ShaderInstructionType::ImageSample, ShaderInstructionFormat::Vdata1Vaddr3StSsDmask8, {U""}},
{Recompile_ImageSample_Vdata2Vaddr3StSsDmask3, ShaderInstructionType::ImageSample, ShaderInstructionFormat::Vdata2Vaddr3StSsDmask3, {U""}}, {Recompile_ImageSample_Vdata2Vaddr3StSsDmask3, ShaderInstructionType::ImageSample, ShaderInstructionFormat::Vdata2Vaddr3StSsDmask3, {U""}},
{Recompile_ImageSample_Vdata2Vaddr3StSsDmask5, ShaderInstructionType::ImageSample, ShaderInstructionFormat::Vdata2Vaddr3StSsDmask5, {U""}}, {Recompile_ImageSample_Vdata2Vaddr3StSsDmask5, ShaderInstructionType::ImageSample, ShaderInstructionFormat::Vdata2Vaddr3StSsDmask5, {U""}},
{Recompile_ImageSample_Vdata2Vaddr3StSsDmask9, ShaderInstructionType::ImageSample, ShaderInstructionFormat::Vdata2Vaddr3StSsDmask9, {U""}},
{Recompile_ImageSample_Vdata3Vaddr3StSsDmask7, ShaderInstructionType::ImageSample, ShaderInstructionFormat::Vdata3Vaddr3StSsDmask7, {U""}}, {Recompile_ImageSample_Vdata3Vaddr3StSsDmask7, ShaderInstructionType::ImageSample, ShaderInstructionFormat::Vdata3Vaddr3StSsDmask7, {U""}},
{Recompile_ImageSample_Vdata4Vaddr3StSsDmaskF, ShaderInstructionType::ImageSample, ShaderInstructionFormat::Vdata4Vaddr3StSsDmaskF, {U""}}, {Recompile_ImageSample_Vdata4Vaddr3StSsDmaskF, ShaderInstructionType::ImageSample, ShaderInstructionFormat::Vdata4Vaddr3StSsDmaskF, {U""}},
{Recompile_ImageSampleLz_Vdata3Vaddr3StSsDmask7, ShaderInstructionType::ImageSampleLz, ShaderInstructionFormat::Vdata3Vaddr3StSsDmask7, {U""}}, {Recompile_ImageSampleLz_Vdata3Vaddr3StSsDmask7, ShaderInstructionType::ImageSampleLz, ShaderInstructionFormat::Vdata3Vaddr3StSsDmask7, {U""}},
@ -5420,10 +5577,12 @@ static RecompilerFunc g_recomp_func[] = {
{Recompile_SBufferLoadDwordx8_Sdst8SvSoffset, ShaderInstructionType::SBufferLoadDwordx8, ShaderInstructionFormat::Sdst8SvSoffset, {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_SCbranch_XXX_Label, ShaderInstructionType::SCbranchExecz, ShaderInstructionFormat::Label, {U"%cc_u_<index> = OpLoad %uint %execz", U"%cc_b_<index> = OpINotEqual %bool %cc_u_<index> %uint_0"}},
{Recompile_SCbranchScc0_Label, ShaderInstructionType::SCbranchScc0, ShaderInstructionFormat::Label, {U""}}, {Recompile_SCbranch_XXX_Label, ShaderInstructionType::SCbranchScc0, ShaderInstructionFormat::Label, {U"%cc_u_<index> = OpLoad %uint %scc", U"%cc_b_<index> = OpIEqual %bool %cc_u_<index> %uint_0"}},
{Recompile_SCbranchScc1_Label, ShaderInstructionType::SCbranchScc1, ShaderInstructionFormat::Label, {U""}}, {Recompile_SCbranch_XXX_Label, ShaderInstructionType::SCbranchScc1, ShaderInstructionFormat::Label, {U"%cc_u_<index> = OpLoad %uint %scc", U"%cc_b_<index> = OpIEqual %bool %cc_u_<index> %uint_1"}},
{Recompile_SCbranchVccz_Label, ShaderInstructionType::SCbranchVccz, ShaderInstructionFormat::Label, {U""}}, {Recompile_SCbranch_XXX_Label, ShaderInstructionType::SCbranchVccz, ShaderInstructionFormat::Label, {U"%cc_u_<index> = OpLoad %uint %vcc_lo", U"%cc_b_<index> = OpIEqual %bool %cc_u_<index> %uint_0"}},
{Recompile_SCbranch_XXX_Label, ShaderInstructionType::SCbranchVccnz, ShaderInstructionFormat::Label, {U"%cc_u_<index> = OpLoad %uint %vcc_lo", U"%cc_b_<index> = OpINotEqual %bool %cc_u_<index> %uint_0"}},
{Recompile_SBranch_Label, ShaderInstructionType::SBranch, ShaderInstructionFormat::Label, {U""}},
{Recompile_SEndpgm_Empty, ShaderInstructionType::SEndpgm, ShaderInstructionFormat::Empty, {U""}}, {Recompile_SEndpgm_Empty, ShaderInstructionType::SEndpgm, ShaderInstructionFormat::Empty, {U""}},
@ -6669,9 +6828,11 @@ void Spirv::WriteLabel(int index)
%<label> = OpLabel %<label> = OpLabel
)"; )";
bool discard = m_code.IsDiscardBlock(label.GetDst()); bool discard = m_code.ReadBlock(label.GetDst()).is_discard;
bool skip_branch = (discard || (instructions.At(index - 1).type == ShaderInstructionType::SEndpgm && labels_num == 0)); bool skip_branch = (discard || ((instructions.At(index - 1).type == ShaderInstructionType::SEndpgm ||
instructions.At(index - 1).type == ShaderInstructionType::SBranch) &&
labels_num == 0));
m_source += String(text) m_source += String(text)
.ReplaceStr(U"<branch>", (skip_branch ? U"" : U"OpBranch %<label>")) .ReplaceStr(U"<branch>", (skip_branch ? U"" : U"OpBranch %<label>"))
@ -6692,8 +6853,8 @@ void Spirv::ModifyCode()
{ {
struct DiscardLabel struct DiscardLabel
{ {
uint32_t pc = 0; ShaderControlFlowBlock block;
int num = 0; int num = 0;
}; };
const auto& labels = m_code.GetLabels(); const auto& labels = m_code.GetLabels();
Vector<DiscardLabel> dls; Vector<DiscardLabel> dls;
@ -6711,18 +6872,21 @@ void Spirv::ModifyCode()
} }
} }
EXIT_IF(num == 0); EXIT_IF(num == 0);
if (num > 1 && m_code.IsDiscardBlock(pc)) if (num > 1)
{ {
if (!dls.Contains(pc, [](auto d, auto pc) { return d.pc == pc; })) if (auto block = m_code.ReadBlock(pc); block.is_discard)
{ {
dls.Add(DiscardLabel({pc, num - 1})); if (!dls.Contains(pc, [](auto d, auto pc) { return d.block.pc == pc; }))
{
dls.Add(DiscardLabel({block, num - 1}));
}
} }
} }
} }
} }
for (const auto& dl: dls) for (const auto& dl: dls)
{ {
auto block = m_code.GetDiscardBlock(dl.pc); auto block = m_code.ReadIntructions(dl.block);
for (int i = 0; i < dl.num; i++) for (int i = 0; i < dl.num; i++)
{ {
// Duplicate discard block if there are different branches with the same label // Duplicate discard block if there are different branches with the same label

View File

@ -5,6 +5,9 @@ static const TextureInfo infos_10_10_0[] = {
// kDataFormatB8G8R8A8Unorm, 96, 96, 128, 1, kTileModeDisplay_2dThin // kDataFormatB8G8R8A8Unorm, 96, 96, 128, 1, kTileModeDisplay_2dThin
{ 10, 0, 96, 96, 128, 1, 10, false, {{65536, 32768, 0, 65536}, }, { {0, 0}, } }, { 10, 0, 96, 96, 128, 1, 10, false, {{65536, 32768, 0, 65536}, }, { {0, 0}, } },
{ 10, 0, 96, 96, 128, 1, 10, true, {{65536, 65536, 0, 65536}, }, { {0, 0}, } }, { 10, 0, 96, 96, 128, 1, 10, true, {{65536, 65536, 0, 65536}, }, { {0, 0}, } },
// kDataFormatB8G8R8A8Unorm, 288, 216, 384, 1, kTileModeDisplay_2dThin
{ 10, 0, 288, 216, 384, 1, 10, false, {{393216, 32768, 0, 393216}, }, { {0, 0}, } },
{ 10, 0, 288, 216, 384, 1, 10, true, {{393216, 65536, 0, 393216}, }, { {0, 0}, } },
// kDataFormatB8G8R8A8Unorm, 960, 540, 1024, 1, kTileModeDisplay_2dThin // kDataFormatB8G8R8A8Unorm, 960, 540, 1024, 1, kTileModeDisplay_2dThin
{ 10, 0, 960, 540, 1024, 1, 10, false, {{2359296, 32768, 0, 2359296}, }, { {0, 0}, } }, { 10, 0, 960, 540, 1024, 1, 10, false, {{2359296, 32768, 0, 2359296}, }, { {0, 0}, } },
{ 10, 0, 960, 540, 1024, 1, 10, true, {{2621440, 65536, 0, 2621440}, }, { {0, 0}, } }, { 10, 0, 960, 540, 1024, 1, 10, true, {{2621440, 65536, 0, 2621440}, }, { {0, 0}, } },