mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-21 11:26:56 +02:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0c4dfd565e | |||
| 0c8d7a1e49 | |||
| a2150c70bb | |||
| 160cf5352c | |||
| 3b6b3c2040 | |||
| 63dd3917e2 | |||
| 2333c235f1 | |||
| dd062ceeeb | |||
| e591a66b67 | |||
| b8a459e83d | |||
| 7684c343d6 | |||
| e0c055fd74 |
@@ -574,6 +574,8 @@ if(BUILD_TESTING)
|
||||
COMMAND $<TARGET_FILE:shader_recompiler_compute_tests> --storage-sampled-only)
|
||||
add_test(NAME texture_cache_depth_readback
|
||||
COMMAND $<TARGET_FILE:shader_recompiler_compute_tests> --depth-readback-only)
|
||||
add_test(NAME compute_meta_clear_classification
|
||||
COMMAND $<TARGET_FILE:shader_recompiler_compute_tests> --compute-meta-clear-only)
|
||||
add_test(NAME buffer_cache_dirty_gc
|
||||
COMMAND $<TARGET_FILE:shader_recompiler_compute_tests> --buffer-cache-gc-only)
|
||||
|
||||
|
||||
@@ -136,7 +136,6 @@ static HW::ColorControl DecodeColorControl(uint32_t value) {
|
||||
|
||||
static HW::DepthControl DecodeDepthControl(uint32_t value) {
|
||||
HW::DepthControl r {};
|
||||
EXIT_NOT_IMPLEMENTED((value & 0xc0000000u) != 0);
|
||||
|
||||
r.stencil_enable = KYTY_PM4_GET(value, DB_DEPTH_CONTROL, STENCIL_ENABLE) != 0;
|
||||
r.z_enable = KYTY_PM4_GET(value, DB_DEPTH_CONTROL, Z_ENABLE) != 0;
|
||||
@@ -3635,6 +3634,9 @@ void GraphicsInitJmpTablesShIndirect() {
|
||||
g_hw_sh_indirect_func[Pm4::SPI_SHADER_PACE_ID_GS] = [](KYTY_HW_SH_INDIRECT_ARGS) {
|
||||
HwShIgnoreShaderRegister(cmd_offset, value);
|
||||
};
|
||||
g_hw_sh_indirect_func[Pm4::SPI_SHADER_PGM_RSRC4_GS] = [](KYTY_HW_SH_INDIRECT_ARGS) {
|
||||
HwShIgnoreShaderRegister(cmd_offset, value);
|
||||
};
|
||||
g_hw_sh_indirect_func[Pm4::SPI_GRAPHICS_SHADER_CONTROL_GS] = [](KYTY_HW_SH_INDIRECT_ARGS) {
|
||||
HwShIgnoreShaderRegister(cmd_offset, value);
|
||||
};
|
||||
@@ -3644,6 +3646,12 @@ void GraphicsInitJmpTablesShIndirect() {
|
||||
g_hw_sh_indirect_func[Pm4::SPI_SHADER_USER_DATA_ADDR_HI_GS] = [](KYTY_HW_SH_INDIRECT_ARGS) {
|
||||
HwShIgnoreShaderRegister(cmd_offset, value);
|
||||
};
|
||||
g_hw_sh_indirect_func[Pm4::SPI_SHADER_PGM_CHKSUM_HS] = [](KYTY_HW_SH_INDIRECT_ARGS) {
|
||||
HwShIgnoreShaderRegister(cmd_offset, value);
|
||||
};
|
||||
g_hw_sh_indirect_func[Pm4::SPI_SHADER_PGM_RSRC4_HS] = [](KYTY_HW_SH_INDIRECT_ARGS) {
|
||||
HwShIgnoreShaderRegister(cmd_offset, value);
|
||||
};
|
||||
g_hw_sh_indirect_func[Pm4::SPI_GRAPHICS_SHADER_CONTROL_HS] = [](KYTY_HW_SH_INDIRECT_ARGS) {
|
||||
HwShIgnoreShaderRegister(cmd_offset, value);
|
||||
};
|
||||
@@ -3818,6 +3826,11 @@ void GraphicsInitJmpTablesUcIndirect() {
|
||||
r.vertex_group_size = KYTY_PM4_GET(value, GE_CNTL, VERT_GRP_SIZE);
|
||||
cp.GetUcfg().SetGeControl(r);
|
||||
};
|
||||
g_hw_uc_indirect_func[Pm4::UC_PARAMETER_OVERSUBSCRIPTION] = [](KYTY_HW_UC_INDIRECT_ARGS) {
|
||||
(void)cp;
|
||||
(void)cmd_offset;
|
||||
(void)value;
|
||||
};
|
||||
g_hw_uc_indirect_func[Pm4::GE_USER_VGPR_EN] = [](KYTY_HW_UC_INDIRECT_ARGS) {
|
||||
HW::GeUserVgprEn r;
|
||||
r.vgpr1 = KYTY_PM4_GET(value, GE_USER_VGPR_EN, EN_USER_VGPR1) != 0;
|
||||
|
||||
@@ -834,8 +834,9 @@ constexpr uint32_t SPI_SHADER_USER_ACCUM_ESGS_0 = 0xB2;
|
||||
constexpr uint32_t SPI_SHADER_USER_ACCUM_ESGS_3 = 0xB5;
|
||||
constexpr uint32_t SPI_SHADER_PGM_LO_ES = 0xC8;
|
||||
constexpr uint32_t SPI_SHADER_PGM_HI_ES = 0xC9;
|
||||
// Retained only as an opaque AGC compiler-record tag; 0x100 is not a PS5 SH register.
|
||||
// Private AGC registers used by shader binaries submitted through SET_SH_REG_INDIRECT.
|
||||
constexpr uint32_t SPI_SHADER_PGM_CHKSUM_HS = 0x100;
|
||||
constexpr uint32_t SPI_SHADER_PGM_RSRC4_HS = 0x101;
|
||||
constexpr uint32_t SPI_SHADER_USER_DATA_ADDR_LO_HS = 0x102;
|
||||
constexpr uint32_t SPI_SHADER_USER_DATA_ADDR_HI_HS = 0x103;
|
||||
constexpr uint32_t SPI_GRAPHICS_SHADER_CONTROL_HS = 0x107;
|
||||
@@ -976,7 +977,7 @@ constexpr uint32_t GE_USER_VGPR1 = 0x25C;
|
||||
constexpr uint32_t GE_USER_VGPR2 = 0x25D;
|
||||
constexpr uint32_t GE_USER_VGPR3 = 0x25E;
|
||||
constexpr uint32_t GE_STEREO_CNTL = 0x25F;
|
||||
constexpr uint32_t GE_PC_ALLOC = 0x260;
|
||||
constexpr uint32_t UC_PARAMETER_OVERSUBSCRIPTION = 0x260;
|
||||
|
||||
constexpr uint32_t GE_USER_VGPR_EN = 0x262;
|
||||
constexpr uint32_t GE_USER_VGPR_EN_EN_USER_VGPR1_SHIFT = 0;
|
||||
|
||||
@@ -490,7 +490,7 @@ static void ClipCheck(const HW::ClipControl& c) {
|
||||
// dx_linear_attr_clip_enable preserves linear (noperspective) attributes at clip-generated
|
||||
// vertices, which Vulkan provides as part of clipping and interpolation.
|
||||
EXIT_NOT_IMPLEMENTED(c.user_clip_planes != 0 || c.user_clip_plane_mode != 0 ||
|
||||
c.vertex_kill_any || c.user_clip_plane_negate_y || c.clip_disable ||
|
||||
c.vertex_kill_any || c.user_clip_plane_negate_y ||
|
||||
c.user_clip_plane_cull_only || c.cull_on_clipping_error_disable ||
|
||||
c.force_viewport_index_from_vs_enable);
|
||||
}
|
||||
@@ -1079,7 +1079,7 @@ void hw_check(const CommandBuffer& buffer) {
|
||||
AaCheck(aa, ac);
|
||||
log_phase("done");
|
||||
|
||||
if (RenderTargetMaskHasBoundMrt(buffer)) {
|
||||
if (graphics_debug_dump_enabled() && RenderTargetMaskHasBoundMrt(buffer)) {
|
||||
LOGF("MRT render target mask: 0x%08" PRIx32 "\n", hw.GetRenderTargetMask());
|
||||
for (uint32_t i = 0; i < 8; i++) {
|
||||
const auto& mrt = hw.GetRenderTarget(i);
|
||||
|
||||
@@ -431,6 +431,10 @@ IsSupportedDisplayRenderTargetTileMode(Prospero::TileMode tile_mode) noexcept {
|
||||
return encoded <= 0.04045f ? encoded / 12.92f : std::pow((encoded + 0.055f) / 1.055f, 2.4f);
|
||||
};
|
||||
switch (format) {
|
||||
// A single-plane float target carries its clear as raw float bits, the same encoding the
|
||||
// depth decoder below uses. Without this the clear is discarded and the target keeps stale
|
||||
// contents.
|
||||
case vk::Format::eR32Sfloat: next.float32[0] = std::bit_cast<float>(packed); break;
|
||||
case vk::Format::eR32Uint: next.uint32[0] = packed; break;
|
||||
case vk::Format::eR32Sint: next.int32[0] = static_cast<int32_t>(packed); break;
|
||||
case vk::Format::eR8G8B8A8Srgb:
|
||||
|
||||
@@ -116,7 +116,7 @@ struct PipelineCache::ProgramCache {
|
||||
}
|
||||
|
||||
static constexpr std::size_t MaxStaticKeyWords =
|
||||
5 + ShaderVertexInputInfo::RES_MAX * 17;
|
||||
12 + ShaderVertexInputInfo::RES_MAX * 17;
|
||||
|
||||
template <typename InputInfo>
|
||||
ShaderProgram Get(const ShaderParams& params, InputInfo& input_info) {
|
||||
@@ -340,8 +340,23 @@ void PipelineCache::Save() {
|
||||
|
||||
ShaderProgram PipelineCache::GetVertexProgram(const HW::VertexShaderInfo& regs,
|
||||
const HW::ShaderRegisters& sh,
|
||||
const HW::Context& context,
|
||||
ShaderVertexInputInfo& input_info) {
|
||||
const auto params = PrepareProgram(regs, sh, input_info);
|
||||
if (context.GetClipControl().clip_disable) {
|
||||
const auto& viewport = context.GetScreenViewport().viewports[0];
|
||||
const auto& limits = m_graphics.GetPhysicalDeviceProperties().limits;
|
||||
auto& clip = input_info.clip_space;
|
||||
clip.scale[0] = viewport.xscale;
|
||||
clip.scale[1] = viewport.yscale;
|
||||
clip.offset[0] = viewport.xoffset;
|
||||
clip.offset[1] = viewport.yoffset;
|
||||
clip.half_extent[0] =
|
||||
static_cast<float>(std::min(limits.maxViewportDimensions[0], 16384u)) * 0.5f;
|
||||
clip.half_extent[1] =
|
||||
static_cast<float>(std::min(limits.maxViewportDimensions[1], 16384u)) * 0.5f;
|
||||
clip.enabled = true;
|
||||
}
|
||||
Common::LockGuard lock(m_mutex);
|
||||
return m_program_cache->Get(params, input_info);
|
||||
}
|
||||
|
||||
@@ -130,6 +130,7 @@ public:
|
||||
|
||||
ShaderProgram GetVertexProgram(const HW::VertexShaderInfo& regs,
|
||||
const HW::ShaderRegisters& sh,
|
||||
const HW::Context& context,
|
||||
ShaderVertexInputInfo& input_info);
|
||||
ShaderProgram
|
||||
GetPixelProgram(const HW::PixelShaderInfo& regs, const HW::ShaderRegisters& sh,
|
||||
|
||||
@@ -54,7 +54,9 @@ bool RenderExecutor::TryConsumeComputeMetaClear(const ShaderComputeInputInfo& in
|
||||
for (uint32_t i = 0; i < program.info.buffers.size(); i++) {
|
||||
const auto& resource = program.info.buffers[i];
|
||||
const auto descriptor = DecodeNativeDescriptor<ShaderBufferResource>(resources.buffers[i]);
|
||||
if (!resource.written && cache.IsMeta(descriptor.Base48())) {
|
||||
// A metadata resource that is also read is not proven to be a full overwrite. Execute it
|
||||
// conservatively instead of replacing the dispatch with a coarse full-surface clear.
|
||||
if (cache.IsMeta(descriptor.Base48()) && (!resource.written || resource.read)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -331,10 +331,18 @@ static void SetGraphicsDynamicParams(const CommandBuffer& buffer, vk::CommandBuf
|
||||
const auto final_scissor = calc_final_scissor(vp, ctx.GetScanModeControl(), framebuffer_extent);
|
||||
|
||||
vk::Viewport viewport {};
|
||||
viewport.x = vp.viewports[0].xoffset - vp.viewports[0].xscale;
|
||||
viewport.y = vp.viewports[0].yoffset - vp.viewports[0].yscale;
|
||||
viewport.width = vp.viewports[0].xscale * 2.0f;
|
||||
viewport.height = vp.viewports[0].yscale * 2.0f;
|
||||
if (ctx.GetClipControl().clip_disable) {
|
||||
const auto& limits = buffer.GetGraphics().GetPhysicalDeviceProperties().limits;
|
||||
viewport.x = 0.0f;
|
||||
viewport.y = 0.0f;
|
||||
viewport.width = static_cast<float>(std::min(limits.maxViewportDimensions[0], 16384u));
|
||||
viewport.height = static_cast<float>(std::min(limits.maxViewportDimensions[1], 16384u));
|
||||
} else {
|
||||
viewport.x = vp.viewports[0].xoffset - vp.viewports[0].xscale;
|
||||
viewport.y = vp.viewports[0].yoffset - vp.viewports[0].yscale;
|
||||
viewport.width = vp.viewports[0].xscale * 2.0f;
|
||||
viewport.height = vp.viewports[0].yscale * 2.0f;
|
||||
}
|
||||
viewport.minDepth = vp.viewports[0].zoffset;
|
||||
viewport.maxDepth = vp.viewports[0].zscale + vp.viewports[0].zoffset;
|
||||
vk_buffer.setViewport(0, 1, &viewport);
|
||||
@@ -1013,8 +1021,8 @@ static void RefreshShaders(CommandBuffer& buffer, const DrawCallInfo& draw, bool
|
||||
LogDrawPhase(draw.name, "GetVertexProgram");
|
||||
}
|
||||
auto& pipeline_cache = buffer.GetContext().GetPipelineCache();
|
||||
state.vertex_program =
|
||||
pipeline_cache.GetVertexProgram(vertex_shader_info, shader_regs, state.vs_input_info);
|
||||
state.vertex_program = pipeline_cache.GetVertexProgram(vertex_shader_info, shader_regs, ctx,
|
||||
state.vs_input_info);
|
||||
|
||||
if (!state.ps_active) {
|
||||
return;
|
||||
|
||||
@@ -242,7 +242,6 @@ static void GameEventKeyboard(WindowLoopState& game, const EventKeyboard& key) {
|
||||
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS || KYTY_PLATFORM == KYTY_PLATFORM_LINUX
|
||||
if (key.down) {
|
||||
switch (key.key_code) {
|
||||
case SDLK_ESCAPE: game.need_exit = true; break;
|
||||
case SDLK_SPACE: SetPause(game, !game.paused.load(std::memory_order_acquire)); break;
|
||||
case SDLK_F1:
|
||||
if (!key.repeat) {
|
||||
|
||||
@@ -408,6 +408,41 @@ void EmitAuxPositionExport(ValueEmitContext& ctx, uint32_t data, const IR::Expor
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t ConvertClipCoordinate(EmitterState& state, uint32_t coordinate, float scale,
|
||||
float offset, float half_extent) {
|
||||
const auto window = state.builder.AllocateId();
|
||||
const auto biased = state.builder.AllocateId();
|
||||
const auto divided = state.builder.AllocateId();
|
||||
const auto ndc = state.builder.AllocateId();
|
||||
state.builder.AddFunction(
|
||||
{OpFMul, TypeF32(state), window, coordinate, ConstantF32Value(state, scale)});
|
||||
state.builder.AddFunction(
|
||||
{OpFAdd, TypeF32(state), biased, window, ConstantF32Value(state, offset)});
|
||||
state.builder.AddFunction(
|
||||
{OpFDiv, TypeF32(state), divided, biased, ConstantF32Value(state, half_extent)});
|
||||
state.builder.AddFunction(
|
||||
{OpFSub, TypeF32(state), ndc, divided, ConstantF32Value(state, 1.0f)});
|
||||
return ndc;
|
||||
}
|
||||
|
||||
uint32_t ConvertPositionToClipSpace(EmitterState& state, uint32_t position) {
|
||||
const auto& transform = state.input_info.vertex->clip_space;
|
||||
uint32_t components[4] {};
|
||||
for (uint32_t i = 0; i < 4; i++) {
|
||||
components[i] = state.builder.AllocateId();
|
||||
state.builder.AddFunction(
|
||||
{OpCompositeExtract, TypeF32(state), components[i], position, i});
|
||||
}
|
||||
components[0] = ConvertClipCoordinate(state, components[0], transform.scale[0],
|
||||
transform.offset[0], transform.half_extent[0]);
|
||||
components[1] = ConvertClipCoordinate(state, components[1], transform.scale[1],
|
||||
transform.offset[1], transform.half_extent[1]);
|
||||
const auto converted = state.builder.AllocateId();
|
||||
state.builder.AddFunction({OpCompositeConstruct, TypeF32Vector(state, 4), converted,
|
||||
components[0], components[1], components[2], components[3]});
|
||||
return converted;
|
||||
}
|
||||
|
||||
void EmitExport(ValueEmitContext& ctx, const IR::Inst& inst) {
|
||||
auto& state = ctx.state;
|
||||
const auto& exp = ctx.Export(inst);
|
||||
@@ -467,6 +502,9 @@ void EmitExport(ValueEmitContext& ctx, const IR::Inst& inst) {
|
||||
}
|
||||
}
|
||||
if (exp.kind == IR::ExportTargetKind::Position) {
|
||||
if (state.stage == ShaderType::Vertex && state.input_info.vertex->clip_space.enabled) {
|
||||
value = ConvertPositionToClipSpace(state, value);
|
||||
}
|
||||
const auto pointer = state.builder.AllocateId();
|
||||
state.builder.AddFunction(
|
||||
{OpAccessChain, TypePointer(state, StorageClassOutput, TypeF32Vector(state, 4)),
|
||||
|
||||
@@ -110,6 +110,12 @@ DppTargetLane EmitDppTargetLane(EmitterState& state, uint32_t control) {
|
||||
if (control == 0x141u) {
|
||||
return EmitDppMirrorTargetLane(state, subid, true);
|
||||
}
|
||||
if (control >= 0x160u && control <= 0x16fu) {
|
||||
const auto target = state.builder.AllocateId();
|
||||
state.builder.AddFunction(
|
||||
{OpBitwiseXor, TypeU32(state), target, subid, ConstantU32(state, control & 0xfu)});
|
||||
return {target, EmitTrueBool(state)};
|
||||
}
|
||||
return {subid, EmitTrueBool(state)};
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@ void Translator::EmitCompareResult(const Decoder::Instruction& inst, IR::U1 valu
|
||||
if (cmpx) {
|
||||
const auto mask = BallotMask(masked);
|
||||
ir.SetExec(masked);
|
||||
ir.SetExecMaskTag(IR::U1(IR::Value(true)));
|
||||
ir.SetExecLo(mask[0]);
|
||||
ir.SetExecHi(mask[1]);
|
||||
return;
|
||||
|
||||
@@ -24,28 +24,18 @@ Decoder::Operand ConditionOperand(Decoder::OperandKind kind) {
|
||||
|
||||
void Translator::S_SAVEEXEC(const Decoder::Instruction& inst, IR::ValueOpcode operation,
|
||||
bool negate_exec, bool negate_source, bool write_64) {
|
||||
if (write_64) {
|
||||
const auto exec_operand = ConditionOperand(Decoder::OperandKind::ExecLo);
|
||||
const auto old = ReadScalarU64(exec_operand);
|
||||
const auto bit_operation = operation == IR::ValueOpcode::LogicalAnd
|
||||
? IR::ValueOpcode::BitwiseAnd32
|
||||
: IR::ValueOpcode::BitwiseOr32;
|
||||
const auto result = BinaryScalarU64(old, ReadScalarU64(inst.src0), operation, bit_operation,
|
||||
negate_exec, negate_source, false);
|
||||
WriteScalarU64(inst.dst, old);
|
||||
WriteScalarU64(exec_operand, result);
|
||||
ir.SetScc(ScalarU64NonZero(result));
|
||||
return;
|
||||
}
|
||||
const auto old = ir.GetExec();
|
||||
const auto src = ReadMask(inst.src0);
|
||||
const auto lhs = negate_exec ? ir.LogicalNot(old) : old;
|
||||
const auto rhs = negate_source ? ir.LogicalNot(src) : src;
|
||||
const auto result = IR::U1(ir.Emit(operation, {lhs, rhs}));
|
||||
WriteMask(inst.dst, old);
|
||||
if (write_64) {
|
||||
WriteMask64(inst.dst, old);
|
||||
} else {
|
||||
WriteMask(inst.dst, old);
|
||||
}
|
||||
const auto mask = BallotMask(result);
|
||||
ir.SetExec(result);
|
||||
ir.SetExecMaskTag(IR::U1(IR::Value(true)));
|
||||
ir.SetExecLo(mask[0]);
|
||||
ir.SetExecHi(mask[1]);
|
||||
ir.SetScc(result);
|
||||
@@ -201,21 +191,30 @@ void Translator::S_CSELECT_B32(const Decoder::Instruction& inst) {
|
||||
}
|
||||
|
||||
void Translator::S_CSELECT_B64(const Decoder::Instruction& inst) {
|
||||
const auto condition = ir.GetScc();
|
||||
const auto lhs = ReadScalarU64(inst.src0);
|
||||
const auto rhs = ReadScalarU64(inst.src1);
|
||||
WriteScalarU64(inst.dst, SelectScalarU64(condition, lhs, rhs));
|
||||
const auto condition = ir.GetScc();
|
||||
const auto lhs = ReadU32Pair(inst.src0);
|
||||
const auto rhs = ReadU32Pair(inst.src1);
|
||||
const auto selected_mask = IR::U1(
|
||||
ir.Emit(IR::ValueOpcode::SelectU1, {condition, ReadMask(inst.src0), ReadMask(inst.src1)}));
|
||||
const auto selected_mask_valid =
|
||||
IR::U1(ir.Emit(IR::ValueOpcode::SelectU1,
|
||||
{condition, ReadMaskValid(inst.src0), ReadMaskValid(inst.src1)}));
|
||||
if (IsExecOrVcc(inst.dst)) {
|
||||
WriteMask64(inst.dst, selected_mask);
|
||||
return;
|
||||
}
|
||||
WriteU32Pair(inst.dst,
|
||||
{ir.Select(condition, lhs[0], rhs[0]), ir.Select(condition, lhs[1], rhs[1])});
|
||||
if (inst.dst.kind == Decoder::OperandKind::Sgpr) {
|
||||
const auto dst = static_cast<IR::ScalarReg>(inst.dst.reg);
|
||||
ir.SetThreadBitScalarReg(dst, selected_mask);
|
||||
ir.SetScalarMaskTag(dst, selected_mask_valid);
|
||||
}
|
||||
}
|
||||
|
||||
void Translator::MOV_B32(const Decoder::Instruction& inst, bool apply_float_modifiers) {
|
||||
if (inst.src0.kind == Decoder::OperandKind::Sgpr &&
|
||||
inst.dst.kind == Decoder::OperandKind::Sgpr && inst.src0.reg == inst.dst.reg) {
|
||||
return;
|
||||
}
|
||||
if (IsExecOrVcc(inst.src0) && IsExecOrVcc(inst.dst)) {
|
||||
if (inst.src0.kind != inst.dst.kind) {
|
||||
WriteRawU32(inst.dst, ReadRawU32(inst.src0));
|
||||
}
|
||||
WriteMask(inst.dst, ReadMask(inst.src0));
|
||||
} else if (apply_float_modifiers && (inst.src0.negate || inst.src0.absolute)) {
|
||||
WriteOperand(DestinationOperand(inst), ReadOperand(inst.src0, IR::Type::F32));
|
||||
} else {
|
||||
@@ -224,17 +223,50 @@ void Translator::MOV_B32(const Decoder::Instruction& inst, bool apply_float_modi
|
||||
}
|
||||
|
||||
void Translator::S_MOV_B64(const Decoder::Instruction& inst) {
|
||||
WriteScalarU64(inst.dst, ReadScalarU64(inst.src0));
|
||||
if (IsExecOrVcc(inst.dst) || IsExecOrVcc(inst.src0)) {
|
||||
WriteMask64(inst.dst, ReadMask(inst.src0));
|
||||
return;
|
||||
}
|
||||
const bool scalar_copy =
|
||||
inst.dst.kind == Decoder::OperandKind::Sgpr && inst.src0.kind == Decoder::OperandKind::Sgpr;
|
||||
IR::U1 source_mask;
|
||||
IR::U1 source_mask_valid;
|
||||
if (scalar_copy) {
|
||||
source_mask = ir.GetThreadBitScalarReg(static_cast<IR::ScalarReg>(inst.src0.reg));
|
||||
source_mask_valid = ir.GetScalarMaskTag(static_cast<IR::ScalarReg>(inst.src0.reg));
|
||||
}
|
||||
WriteU32Pair(inst.dst, ReadU32Pair(inst.src0));
|
||||
if (scalar_copy) {
|
||||
ir.SetThreadBitScalarReg(static_cast<IR::ScalarReg>(inst.dst.reg), source_mask);
|
||||
ir.SetScalarMaskTag(static_cast<IR::ScalarReg>(inst.dst.reg), source_mask_valid);
|
||||
}
|
||||
}
|
||||
|
||||
void Translator::S_WQM_B64(const Decoder::Instruction& inst) {
|
||||
const auto source = ReadScalarU64(inst.src0);
|
||||
const auto raw = ExtractU64(
|
||||
IR::U64(ir.Emit(IR::ValueOpcode::WqmU64, {ir.ConstructU64(source.raw[0], source.raw[1])})));
|
||||
const auto invocation = IR::U1(ir.Emit(IR::ValueOpcode::WqmMask, {source.invocation}));
|
||||
const auto result = MakeScalarU64Result(raw, invocation, source.mask_valid);
|
||||
WriteScalarU64(inst.dst, result);
|
||||
ir.SetScc(ScalarU64NonZero(result));
|
||||
if (!IsExecOrVcc(inst.dst) && !IsExecOrVcc(inst.src0)) {
|
||||
const auto mask_valid = ReadMaskValid(inst.src0);
|
||||
const auto invocation_result =
|
||||
IR::U1(ir.Emit(IR::ValueOpcode::WqmMask, {ReadMask(inst.src0)}));
|
||||
const auto result =
|
||||
IR::U64(ir.Emit(IR::ValueOpcode::WqmU64, {ReadOperand(inst.src0, IR::Type::U64)}));
|
||||
WriteOperand(DestinationOperand(inst), result);
|
||||
if (inst.dst.kind == Decoder::OperandKind::Sgpr) {
|
||||
const auto dst = static_cast<IR::ScalarReg>(inst.dst.reg);
|
||||
ir.SetThreadBitScalarReg(dst, invocation_result);
|
||||
ir.SetScalarMaskTag(dst, mask_valid);
|
||||
const auto raw_nonzero =
|
||||
IR::U1(ir.Emit(IR::ValueOpcode::INotEqual64, {result, IR::Value(uint64_t {0})}));
|
||||
ir.SetScc(IR::U1(
|
||||
ir.Emit(IR::ValueOpcode::SelectU1, {mask_valid, invocation_result, raw_nonzero})));
|
||||
} else {
|
||||
ir.SetScc(
|
||||
IR::U1(ir.Emit(IR::ValueOpcode::INotEqual64, {result, IR::Value(uint64_t {0})})));
|
||||
}
|
||||
return;
|
||||
}
|
||||
const auto result = IR::U1(ir.Emit(IR::ValueOpcode::WqmMask, {ReadMask(inst.src0)}));
|
||||
WriteMask64(inst.dst, result);
|
||||
ir.SetScc(result);
|
||||
}
|
||||
|
||||
void Translator::V_MOVRELS_B32(const Decoder::Instruction& inst) {
|
||||
|
||||
@@ -77,15 +77,68 @@ bool Translator::PackedInteger16MinMax(const Decoder::Instruction& inst, IR::Val
|
||||
return true;
|
||||
}
|
||||
|
||||
IR::U1 Translator::U64MaskBinary(const Decoder::Instruction& inst, IR::ValueOpcode opcode,
|
||||
bool negate_rhs, bool negate_result) {
|
||||
const auto lhs = ReadMask(inst.src0);
|
||||
auto rhs = ReadMask(inst.src1);
|
||||
if (negate_rhs) {
|
||||
rhs = ir.LogicalNot(rhs);
|
||||
}
|
||||
auto result = IR::U1(ir.Emit(opcode, {lhs, rhs}));
|
||||
return negate_result ? ir.LogicalNot(result) : result;
|
||||
}
|
||||
|
||||
bool Translator::S_U64_MASK(const Decoder::Instruction& inst, IR::ValueOpcode logical_opcode,
|
||||
IR::ValueOpcode bit_opcode, bool negate_rhs, bool negate_result,
|
||||
bool unary) {
|
||||
const auto lhs = ReadScalarU64(inst.src0);
|
||||
const auto result = unary ? NotScalarU64(lhs)
|
||||
: BinaryScalarU64(lhs, ReadScalarU64(inst.src1), logical_opcode,
|
||||
bit_opcode, false, negate_rhs, negate_result);
|
||||
WriteScalarU64(inst.dst, result);
|
||||
ir.SetScc(ScalarU64NonZero(result));
|
||||
const auto invocation_result =
|
||||
unary ? ir.LogicalNot(ReadMask(inst.src0))
|
||||
: U64MaskBinary(inst, logical_opcode, negate_rhs, negate_result);
|
||||
const auto is_exec_or_vcc = [](const Decoder::Operand& operand) {
|
||||
switch (operand.kind) {
|
||||
case Decoder::OperandKind::ExecLo:
|
||||
case Decoder::OperandKind::ExecHi:
|
||||
case Decoder::OperandKind::VccLo:
|
||||
case Decoder::OperandKind::VccHi: return true;
|
||||
default: return false;
|
||||
}
|
||||
};
|
||||
if (is_exec_or_vcc(inst.dst) || is_exec_or_vcc(inst.src0) ||
|
||||
(inst.src_count > 1u && is_exec_or_vcc(inst.src1))) {
|
||||
WriteMask64(inst.dst, invocation_result);
|
||||
ir.SetScc(invocation_result);
|
||||
return true;
|
||||
}
|
||||
|
||||
const auto lhs = ReadU32Pair(inst.src0);
|
||||
auto mask_valid = ReadMaskValid(inst.src0);
|
||||
if (inst.src_count > 1u) {
|
||||
mask_valid = ir.LogicalAnd(mask_valid, ReadMaskValid(inst.src1));
|
||||
}
|
||||
std::array<IR::U32, 2> result;
|
||||
if (unary) {
|
||||
result = {ir.BitwiseNot(lhs[0]), ir.BitwiseNot(lhs[1])};
|
||||
} else {
|
||||
const auto rhs = ReadU32Pair(inst.src1);
|
||||
for (uint32_t component = 0; component < 2u; component++) {
|
||||
auto value = ir.Emit(
|
||||
bit_opcode, {lhs[component], negate_rhs ? IR::Value(ir.BitwiseNot(rhs[component]))
|
||||
: IR::Value(rhs[component])});
|
||||
result[component] = negate_result ? ir.BitwiseNot(IR::U32(value)) : IR::U32(value);
|
||||
}
|
||||
}
|
||||
WriteU32Pair(inst.dst, result);
|
||||
if (inst.dst.kind == Decoder::OperandKind::Sgpr) {
|
||||
const auto dst = static_cast<IR::ScalarReg>(inst.dst.reg);
|
||||
ir.SetThreadBitScalarReg(dst, invocation_result);
|
||||
ir.SetScalarMaskTag(dst, mask_valid);
|
||||
const auto raw_nonzero =
|
||||
ir.INotEqual(ir.BitwiseOr(result[0], result[1]), IR::U32(IR::Value(0u)));
|
||||
ir.SetScc(IR::U1(
|
||||
ir.Emit(IR::ValueOpcode::SelectU1, {mask_valid, invocation_result, raw_nonzero})));
|
||||
} else {
|
||||
ir.SetScc(ir.INotEqual(ir.BitwiseOr(result[0], result[1]), IR::U32(IR::Value(0u))));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -55,14 +55,11 @@ uint32_t ResourceIndexFromOperand(const Decoder::Operand& operand) {
|
||||
}
|
||||
}
|
||||
|
||||
Decoder::Operand RawScalarLoadBase(const Decoder::Operand& operand) {
|
||||
if (operand.kind != Decoder::OperandKind::M0) {
|
||||
return operand;
|
||||
uint32_t RawScalarLoadBase(const Decoder::Operand& operand) {
|
||||
if (operand.kind == Decoder::OperandKind::Sgpr) {
|
||||
return operand.reg;
|
||||
}
|
||||
auto result = operand;
|
||||
// The compressed SBASE value 62 decodes as code 124, but means NULL for S_LOAD.
|
||||
result.kind = Decoder::OperandKind::Null;
|
||||
return result;
|
||||
return operand.kind == Decoder::OperandKind::VccLo ? 106u : 0u;
|
||||
}
|
||||
|
||||
ResourceKind FlatSegmentResourceKind(uint32_t segment) {
|
||||
@@ -322,9 +319,8 @@ Translator::AddressOperands Translator::ReadAddressOperands(const Decoder::Instr
|
||||
return {GetAddressResource(low, high), low, high};
|
||||
}
|
||||
|
||||
IR::Value Translator::GetScalarAddressResource(const Decoder::Operand& base) {
|
||||
const auto raw = ReadU32Pair(base);
|
||||
return GetAddressResource(raw[0], raw[1]);
|
||||
IR::Value Translator::GetScalarAddressResource(uint32_t base) {
|
||||
return GetAddressResource(ReadScalarCode(base), ReadScalarCode(base + 1u));
|
||||
}
|
||||
|
||||
IR::Value Translator::GetImageResource(const IR::MemoryInfo& memory) {
|
||||
|
||||
@@ -151,8 +151,11 @@ IR::U32 Translator::ReadScalarCode(uint32_t code) {
|
||||
case 106u: return ir.GetVccLo();
|
||||
case 107u: return ir.GetVccHi();
|
||||
case 124u: return ir.GetM0();
|
||||
case 126u: return ir.GetExecLo();
|
||||
case 127u: return ir.GetExecHi();
|
||||
case 126u:
|
||||
case 127u: {
|
||||
const auto mask = BallotMask(ir.GetExec());
|
||||
return mask[code - 126u];
|
||||
}
|
||||
default: return IR::U32(IR::Value(0u));
|
||||
}
|
||||
}
|
||||
@@ -312,23 +315,19 @@ void Translator::WriteRawU32(const Decoder::Operand& operand, IR::U32 value) {
|
||||
case Decoder::OperandKind::VccLo:
|
||||
ir.SetVccLo(IR::U32(value));
|
||||
ir.SetVcc(ThreadBit(IR::U32(value)));
|
||||
ir.SetVccMaskValidTag(IR::U1(IR::Value(false)));
|
||||
break;
|
||||
case Decoder::OperandKind::VccHi:
|
||||
ir.SetVccHi(IR::U32(value));
|
||||
ir.SetVcc(ThreadBit(ir.GetVccLo()));
|
||||
ir.SetVccMaskValidTag(IR::U1(IR::Value(false)));
|
||||
break;
|
||||
case Decoder::OperandKind::M0: ir.SetM0(IR::U32(value)); break;
|
||||
case Decoder::OperandKind::ExecLo:
|
||||
ir.SetExecLo(IR::U32(value));
|
||||
ir.SetExec(ThreadBit(IR::U32(value)));
|
||||
ir.SetExecMaskTag(IR::U1(IR::Value(false)));
|
||||
break;
|
||||
case Decoder::OperandKind::ExecHi:
|
||||
ir.SetExecHi(IR::U32(value));
|
||||
ir.SetExec(ThreadBit(ir.GetExecLo()));
|
||||
ir.SetExecMaskTag(IR::U1(IR::Value(false)));
|
||||
break;
|
||||
case Decoder::OperandKind::Scc:
|
||||
ir.SetScc(ir.INotEqual(value, IR::U32(IR::Value(0u))));
|
||||
@@ -373,7 +372,6 @@ void Translator::WriteOperand(const Decoder::Operand& operand, IR::Value value)
|
||||
case Decoder::OperandKind::ExecHi: {
|
||||
const auto mask = BallotMask(IR::U1(value));
|
||||
ir.SetExec(IR::U1(value));
|
||||
ir.SetExecMaskTag(IR::U1(IR::Value(true)));
|
||||
ir.SetExecLo(mask[0]);
|
||||
ir.SetExecHi(mask[1]);
|
||||
return;
|
||||
@@ -382,7 +380,6 @@ void Translator::WriteOperand(const Decoder::Operand& operand, IR::Value value)
|
||||
case Decoder::OperandKind::VccHi: {
|
||||
const auto mask = BallotMask(IR::U1(value));
|
||||
ir.SetVcc(IR::U1(value));
|
||||
ir.SetVccMaskValidTag(IR::U1(IR::Value(true)));
|
||||
ir.SetVccLo(mask[0]);
|
||||
ir.SetVccHi(mask[1]);
|
||||
return;
|
||||
@@ -583,13 +580,11 @@ void Translator::WriteU32Pair(const Decoder::Operand& operand,
|
||||
switch (operand.kind) {
|
||||
case Decoder::OperandKind::ExecLo:
|
||||
ir.SetExec(thread_bit);
|
||||
ir.SetExecMaskTag(IR::U1(IR::Value(false)));
|
||||
ir.SetExecLo(value[0]);
|
||||
ir.SetExecHi(value[1]);
|
||||
return;
|
||||
case Decoder::OperandKind::VccLo:
|
||||
ir.SetVcc(thread_bit);
|
||||
ir.SetVccMaskValidTag(IR::U1(IR::Value(false)));
|
||||
ir.SetVccLo(value[0]);
|
||||
ir.SetVccHi(value[1]);
|
||||
return;
|
||||
@@ -600,87 +595,6 @@ void Translator::WriteU32Pair(const Decoder::Operand& operand,
|
||||
WriteRawU32(OffsetOperand(operand, 1), value[1]);
|
||||
}
|
||||
|
||||
Translator::ScalarU64 Translator::ReadScalarU64(const Decoder::Operand& operand) {
|
||||
return {ReadU32Pair(operand), ReadMask(operand), ReadMaskValid(operand)};
|
||||
}
|
||||
|
||||
Translator::ScalarU64 Translator::MakeScalarU64Mask(IR::U1 value) {
|
||||
return {BallotMask(value), value, IR::U1(IR::Value(true))};
|
||||
}
|
||||
|
||||
Translator::ScalarU64 Translator::MakeScalarU64Result(const std::array<IR::U32, 2>& raw,
|
||||
IR::U1 invocation, IR::U1 mask_valid) {
|
||||
return {raw,
|
||||
IR::U1(ir.Emit(IR::ValueOpcode::SelectU1, {mask_valid, invocation, ThreadBit(raw[0])})),
|
||||
mask_valid};
|
||||
}
|
||||
|
||||
Translator::ScalarU64 Translator::SelectScalarU64(IR::U1 condition, const ScalarU64& lhs,
|
||||
const ScalarU64& rhs) {
|
||||
return {
|
||||
{ir.Select(condition, lhs.raw[0], rhs.raw[0]),
|
||||
ir.Select(condition, lhs.raw[1], rhs.raw[1])},
|
||||
IR::U1(ir.Emit(IR::ValueOpcode::SelectU1, {condition, lhs.invocation, rhs.invocation})),
|
||||
IR::U1(ir.Emit(IR::ValueOpcode::SelectU1, {condition, lhs.mask_valid, rhs.mask_valid}))};
|
||||
}
|
||||
|
||||
Translator::ScalarU64 Translator::NotScalarU64(const ScalarU64& value) {
|
||||
return MakeScalarU64Result({ir.BitwiseNot(value.raw[0]), ir.BitwiseNot(value.raw[1])},
|
||||
ir.LogicalNot(value.invocation), value.mask_valid);
|
||||
}
|
||||
|
||||
Translator::ScalarU64 Translator::BinaryScalarU64(const ScalarU64& lhs, const ScalarU64& rhs,
|
||||
IR::ValueOpcode logical_opcode,
|
||||
IR::ValueOpcode bit_opcode, bool negate_lhs,
|
||||
bool negate_rhs, bool negate_result) {
|
||||
auto lhs_mask = negate_lhs ? ir.LogicalNot(lhs.invocation) : lhs.invocation;
|
||||
auto rhs_mask = negate_rhs ? ir.LogicalNot(rhs.invocation) : rhs.invocation;
|
||||
auto mask = IR::U1(ir.Emit(logical_opcode, {lhs_mask, rhs_mask}));
|
||||
if (negate_result) {
|
||||
mask = ir.LogicalNot(mask);
|
||||
}
|
||||
std::array<IR::U32, 2> raw;
|
||||
for (uint32_t component = 0; component < raw.size(); component++) {
|
||||
auto lhs_raw = negate_lhs ? ir.BitwiseNot(lhs.raw[component]) : lhs.raw[component];
|
||||
auto rhs_raw = negate_rhs ? ir.BitwiseNot(rhs.raw[component]) : rhs.raw[component];
|
||||
raw[component] = IR::U32(ir.Emit(bit_opcode, {lhs_raw, rhs_raw}));
|
||||
if (negate_result) {
|
||||
raw[component] = ir.BitwiseNot(raw[component]);
|
||||
}
|
||||
}
|
||||
return MakeScalarU64Result(raw, mask, ir.LogicalAnd(lhs.mask_valid, rhs.mask_valid));
|
||||
}
|
||||
|
||||
void Translator::WriteScalarU64(const Decoder::Operand& operand, const ScalarU64& value) {
|
||||
WriteU32Pair(operand, value.raw);
|
||||
switch (operand.kind) {
|
||||
case Decoder::OperandKind::ExecLo:
|
||||
case Decoder::OperandKind::ExecHi:
|
||||
ir.SetExec(value.invocation);
|
||||
ir.SetExecMaskTag(value.mask_valid);
|
||||
break;
|
||||
case Decoder::OperandKind::VccLo:
|
||||
case Decoder::OperandKind::VccHi:
|
||||
ir.SetVcc(value.invocation);
|
||||
ir.SetVccMaskValidTag(value.mask_valid);
|
||||
break;
|
||||
case Decoder::OperandKind::Sgpr: {
|
||||
const auto reg = static_cast<IR::ScalarReg>(operand.reg);
|
||||
ir.SetThreadBitScalarReg(reg, value.invocation);
|
||||
ir.SetScalarMaskTag(reg, value.mask_valid);
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
IR::U1 Translator::ScalarU64NonZero(const ScalarU64& value) {
|
||||
const auto raw_nonzero =
|
||||
ir.INotEqual(ir.BitwiseOr(value.raw[0], value.raw[1]), IR::U32(IR::Value(0u)));
|
||||
return IR::U1(
|
||||
ir.Emit(IR::ValueOpcode::SelectU1, {value.mask_valid, value.invocation, raw_nonzero}));
|
||||
}
|
||||
|
||||
IR::U1 Translator::ThreadBit(IR::U32 low) {
|
||||
return ir.INotEqual(low, IR::U32(IR::Value(0u)));
|
||||
}
|
||||
@@ -736,9 +650,9 @@ IR::U1 Translator::ReadMaskValid(const Decoder::Operand& operand) {
|
||||
case Decoder::OperandKind::Sgpr:
|
||||
return ir.GetScalarMaskTag(static_cast<IR::ScalarReg>(operand.reg));
|
||||
case Decoder::OperandKind::ExecLo:
|
||||
case Decoder::OperandKind::ExecHi: return ir.GetExecMaskTag();
|
||||
case Decoder::OperandKind::ExecHi:
|
||||
case Decoder::OperandKind::VccLo:
|
||||
case Decoder::OperandKind::VccHi: return ir.GetVccMaskValidTag();
|
||||
case Decoder::OperandKind::VccHi:
|
||||
case Decoder::OperandKind::VccZ:
|
||||
case Decoder::OperandKind::ExecZ:
|
||||
case Decoder::OperandKind::Scc: return IR::U1(IR::Value(true));
|
||||
@@ -771,7 +685,6 @@ void Translator::WriteMask(const Decoder::Operand& operand, IR::U1 value) {
|
||||
case Decoder::OperandKind::ExecHi: {
|
||||
const auto mask = BallotMask(value);
|
||||
ir.SetExec(value);
|
||||
ir.SetExecMaskTag(IR::U1(IR::Value(true)));
|
||||
ir.SetExecLo(mask[0]);
|
||||
ir.SetExecHi(mask[1]);
|
||||
return;
|
||||
@@ -780,7 +693,6 @@ void Translator::WriteMask(const Decoder::Operand& operand, IR::U1 value) {
|
||||
case Decoder::OperandKind::VccHi: {
|
||||
const auto mask = BallotMask(value);
|
||||
ir.SetVcc(value);
|
||||
ir.SetVccMaskValidTag(IR::U1(IR::Value(true)));
|
||||
ir.SetVccLo(mask[0]);
|
||||
ir.SetVccHi(mask[1]);
|
||||
return;
|
||||
@@ -794,7 +706,25 @@ void Translator::WriteMask(const Decoder::Operand& operand, IR::U1 value) {
|
||||
}
|
||||
|
||||
void Translator::WriteMask64(const Decoder::Operand& operand, IR::U1 value) {
|
||||
WriteScalarU64(operand, MakeScalarU64Mask(value));
|
||||
if (operand.kind != Decoder::OperandKind::Sgpr) {
|
||||
WriteMask(operand, value);
|
||||
return;
|
||||
}
|
||||
const auto reg = static_cast<IR::ScalarReg>(operand.reg);
|
||||
const auto mask = BallotMask(value);
|
||||
ir.SetThreadBitScalarReg(reg, value);
|
||||
ir.SetScalarMaskTag(reg, IR::U1(IR::Value(true)));
|
||||
if (IR::RegIndex(reg) > 0u) {
|
||||
ir.SetScalarMaskTag(static_cast<IR::ScalarReg>(IR::RegIndex(reg) - 1u),
|
||||
IR::U1(IR::Value(false)));
|
||||
}
|
||||
ir.SetScalarReg(reg, mask[0]);
|
||||
if (IR::RegIndex(reg) + 1u < IR::NumScalarRegs) {
|
||||
const auto high = static_cast<IR::ScalarReg>(IR::RegIndex(reg) + 1u);
|
||||
ir.SetScalarReg(high, mask[1]);
|
||||
ir.SetThreadBitScalarReg(high, IR::U1(IR::Value(false)));
|
||||
ir.SetScalarMaskTag(high, IR::U1(IR::Value(false)));
|
||||
}
|
||||
}
|
||||
|
||||
void Translator::WriteCompareResult(const Decoder::Operand& operand, IR::U1 value) {
|
||||
@@ -1095,7 +1025,6 @@ IR::Program TranslateProgram(const Decoder::Program& decoded, const CFG::Graph&
|
||||
entry_ir.SetScalarMaskTag(reg, IR::U1(IR::Value(false)));
|
||||
}
|
||||
entry_ir.SetExec(IR::U1(IR::Value(true)));
|
||||
entry_ir.SetExecMaskTag(IR::U1(IR::Value(true)));
|
||||
entry_ir.SetExecLo(IR::U32(IR::Value(1u)));
|
||||
entry_ir.SetExecHi(IR::U32(IR::Value(0u)));
|
||||
if (options.stage == ShaderType::Compute) {
|
||||
|
||||
@@ -19,14 +19,6 @@ public:
|
||||
void AddBranchCondition(const CFG::BasicBlock& source, IR::BlockInfo& info);
|
||||
|
||||
private:
|
||||
struct ScalarU64 {
|
||||
std::array<IR::U32, 2> raw;
|
||||
// Raw words and Kyty's per-invocation mask model remain independent.
|
||||
// mask_valid selects invocation for logical consumers and SCC.
|
||||
IR::U1 invocation;
|
||||
IR::U1 mask_valid;
|
||||
};
|
||||
|
||||
Decoder::Operand SourceAt(const Decoder::Instruction& inst, uint32_t index);
|
||||
Decoder::Operand DestinationOperand(const Decoder::Instruction& inst);
|
||||
Decoder::Operand OffsetOperand(const Decoder::Operand& operand, uint32_t offset);
|
||||
@@ -56,25 +48,14 @@ private:
|
||||
IR::U32 ReadU16AsU32(const Decoder::Operand& operand, bool sign_extend);
|
||||
IR::U32 ReadF16LaneBits(const Decoder::Operand& operand, bool high_lane);
|
||||
std::array<IR::U32, 2> ExtractU64(IR::U64 value);
|
||||
void WriteU32Pair(const Decoder::Operand& operand, const std::array<IR::U32, 2>& value);
|
||||
ScalarU64 ReadScalarU64(const Decoder::Operand& operand);
|
||||
ScalarU64 MakeScalarU64Mask(IR::U1 value);
|
||||
ScalarU64 MakeScalarU64Result(const std::array<IR::U32, 2>& raw, IR::U1 invocation,
|
||||
IR::U1 mask_valid);
|
||||
ScalarU64 SelectScalarU64(IR::U1 condition, const ScalarU64& lhs, const ScalarU64& rhs);
|
||||
ScalarU64 NotScalarU64(const ScalarU64& value);
|
||||
ScalarU64 BinaryScalarU64(const ScalarU64& lhs, const ScalarU64& rhs,
|
||||
IR::ValueOpcode logical_opcode, IR::ValueOpcode bit_opcode,
|
||||
bool negate_lhs, bool negate_rhs, bool negate_result);
|
||||
void WriteScalarU64(const Decoder::Operand& operand, const ScalarU64& value);
|
||||
IR::U1 ScalarU64NonZero(const ScalarU64& value);
|
||||
IR::U1 ReadCondition(const Decoder::Operand& operand);
|
||||
IR::U32 ConditionBit(const Decoder::Operand& operand);
|
||||
IR::U1 ReadMask(const Decoder::Operand& operand);
|
||||
IR::U1 ReadMaskValid(const Decoder::Operand& operand);
|
||||
void WriteMask(const Decoder::Operand& operand, IR::U1 value);
|
||||
void WriteMask64(const Decoder::Operand& operand, IR::U1 value);
|
||||
void WriteCompareResult(const Decoder::Operand& operand, IR::U1 value);
|
||||
void WriteU32Pair(const Decoder::Operand& operand, const std::array<IR::U32, 2>& value);
|
||||
IR::U1 ReadCondition(const Decoder::Operand& operand);
|
||||
IR::U32 ConditionBit(const Decoder::Operand& operand);
|
||||
IR::U1 ReadMask(const Decoder::Operand& operand);
|
||||
IR::U1 ReadMaskValid(const Decoder::Operand& operand);
|
||||
void WriteMask(const Decoder::Operand& operand, IR::U1 value);
|
||||
void WriteMask64(const Decoder::Operand& operand, IR::U1 value);
|
||||
void WriteCompareResult(const Decoder::Operand& operand, IR::U1 value);
|
||||
|
||||
IR::MemoryFlags AddMemoryInfo(const IR::MemoryInfo& memory, uint32_t pc);
|
||||
IR::ExportFlags AddExportInfo(const Decoder::Instruction& inst);
|
||||
@@ -92,7 +73,7 @@ private:
|
||||
IR::U32 GetResourceDword(uint32_t index, uint32_t dword);
|
||||
IR::Value GetBufferResource(const IR::MemoryInfo& memory);
|
||||
IR::Value GetAddressResource(IR::Value low, IR::Value high);
|
||||
IR::Value GetScalarAddressResource(const Decoder::Operand& base);
|
||||
IR::Value GetScalarAddressResource(uint32_t base);
|
||||
IR::Value GetImageResource(const IR::MemoryInfo& memory);
|
||||
IR::Value GetSamplerResource(const IR::MemoryInfo& memory);
|
||||
IR::Value MakeImageAddress(const Decoder::Instruction& inst, const Decoder::Operand& base);
|
||||
@@ -194,6 +175,8 @@ private:
|
||||
bool PackedInteger16MinMax(const Decoder::Instruction& inst, IR::ValueOpcode opcode, bool sign);
|
||||
bool S_U64_MASK(const Decoder::Instruction& inst, IR::ValueOpcode logical_opcode,
|
||||
IR::ValueOpcode bit_opcode, bool negate_rhs, bool negate_result, bool unary);
|
||||
IR::U1 U64MaskBinary(const Decoder::Instruction& inst, IR::ValueOpcode opcode, bool negate_rhs,
|
||||
bool negate_result);
|
||||
bool SimpleInteger(const Decoder::Instruction& inst, IR::ValueOpcode opcode, IR::Type type,
|
||||
bool reverse, bool mask_shift_count, bool update_scc);
|
||||
bool ComposedIntegerBinary(const Decoder::Instruction& inst, IR::ValueOpcode opcode,
|
||||
|
||||
@@ -76,14 +76,6 @@ void IREmitter::SetExec(U1 value) {
|
||||
Emit(ValueOpcode::SetExec, {value});
|
||||
}
|
||||
|
||||
U1 IREmitter::GetExecMaskTag() {
|
||||
return U1(Emit(ValueOpcode::GetExecMaskTag));
|
||||
}
|
||||
|
||||
void IREmitter::SetExecMaskTag(U1 value) {
|
||||
Emit(ValueOpcode::SetExecMaskTag, {value});
|
||||
}
|
||||
|
||||
U32 IREmitter::GetExecLo() {
|
||||
return U32(Emit(ValueOpcode::GetExecLo));
|
||||
}
|
||||
@@ -108,14 +100,6 @@ void IREmitter::SetVcc(U1 value) {
|
||||
Emit(ValueOpcode::SetVcc, {value});
|
||||
}
|
||||
|
||||
U1 IREmitter::GetVccMaskValidTag() {
|
||||
return U1(Emit(ValueOpcode::GetVccMaskValidTag));
|
||||
}
|
||||
|
||||
void IREmitter::SetVccMaskValidTag(U1 value) {
|
||||
Emit(ValueOpcode::SetVccMaskValidTag, {value});
|
||||
}
|
||||
|
||||
U32 IREmitter::GetVccLo() {
|
||||
return U32(Emit(ValueOpcode::GetVccLo));
|
||||
}
|
||||
|
||||
@@ -39,16 +39,12 @@ public:
|
||||
void SetScc(U1 value);
|
||||
U1 GetExec();
|
||||
void SetExec(U1 value);
|
||||
U1 GetExecMaskTag();
|
||||
void SetExecMaskTag(U1 value);
|
||||
U32 GetExecLo();
|
||||
void SetExecLo(U32 value);
|
||||
U32 GetExecHi();
|
||||
void SetExecHi(U32 value);
|
||||
U1 GetVcc();
|
||||
void SetVcc(U1 value);
|
||||
U1 GetVccMaskValidTag();
|
||||
void SetVccMaskValidTag(U1 value);
|
||||
U32 GetVccLo();
|
||||
void SetVccLo(U32 value);
|
||||
U32 GetVccHi();
|
||||
|
||||
@@ -33,16 +33,12 @@ bool IsRegisterStatePseudo(ValueOpcode opcode) {
|
||||
case ValueOpcode::SetScc:
|
||||
case ValueOpcode::GetExec:
|
||||
case ValueOpcode::SetExec:
|
||||
case ValueOpcode::GetExecMaskTag:
|
||||
case ValueOpcode::SetExecMaskTag:
|
||||
case ValueOpcode::GetExecLo:
|
||||
case ValueOpcode::SetExecLo:
|
||||
case ValueOpcode::GetExecHi:
|
||||
case ValueOpcode::SetExecHi:
|
||||
case ValueOpcode::GetVcc:
|
||||
case ValueOpcode::SetVcc:
|
||||
case ValueOpcode::GetVccMaskValidTag:
|
||||
case ValueOpcode::SetVccMaskValidTag:
|
||||
case ValueOpcode::GetVccLo:
|
||||
case ValueOpcode::SetVccLo:
|
||||
case ValueOpcode::GetVccHi:
|
||||
|
||||
@@ -23,16 +23,12 @@ VALUE_OPCODE(GetScc, U1)
|
||||
VALUE_OPCODE(SetScc, Void, U1)
|
||||
VALUE_OPCODE(GetExec, U1)
|
||||
VALUE_OPCODE(SetExec, Void, U1)
|
||||
VALUE_OPCODE(GetExecMaskTag, U1)
|
||||
VALUE_OPCODE(SetExecMaskTag, Void, U1)
|
||||
VALUE_OPCODE(GetExecLo, U32)
|
||||
VALUE_OPCODE(SetExecLo, Void, U32)
|
||||
VALUE_OPCODE(GetExecHi, U32)
|
||||
VALUE_OPCODE(SetExecHi, Void, U32)
|
||||
VALUE_OPCODE(GetVcc, U1)
|
||||
VALUE_OPCODE(SetVcc, Void, U1)
|
||||
VALUE_OPCODE(GetVccMaskValidTag, U1)
|
||||
VALUE_OPCODE(SetVccMaskValidTag, Void, U1)
|
||||
VALUE_OPCODE(GetVccLo, U32)
|
||||
VALUE_OPCODE(SetVccLo, Void, U32)
|
||||
VALUE_OPCODE(GetVccHi, U32)
|
||||
|
||||
@@ -22,9 +22,6 @@ struct ScalarMaskTag {
|
||||
struct ExecTag {
|
||||
auto operator<=>(const ExecTag&) const = default;
|
||||
};
|
||||
struct ExecMaskTag {
|
||||
auto operator<=>(const ExecMaskTag&) const = default;
|
||||
};
|
||||
struct ExecLoTag {
|
||||
auto operator<=>(const ExecLoTag&) const = default;
|
||||
};
|
||||
@@ -34,9 +31,6 @@ struct ExecHiTag {
|
||||
struct VccTag {
|
||||
auto operator<=>(const VccTag&) const = default;
|
||||
};
|
||||
struct VccMaskValidTag {
|
||||
auto operator<=>(const VccMaskValidTag&) const = default;
|
||||
};
|
||||
struct VccLoTag {
|
||||
auto operator<=>(const VccLoTag&) const = default;
|
||||
};
|
||||
@@ -51,9 +45,9 @@ struct GotoVariable {
|
||||
auto operator<=>(const GotoVariable&) const = default;
|
||||
};
|
||||
|
||||
using Variable = std::variant<ScalarReg, ThreadBitScalarReg, ScalarMaskTag, VectorReg, GotoVariable,
|
||||
SccTag, ExecTag, ExecMaskTag, ExecLoTag, ExecHiTag, VccTag,
|
||||
VccMaskValidTag, VccLoTag, VccHiTag, M0Tag>;
|
||||
using Variable =
|
||||
std::variant<ScalarReg, ThreadBitScalarReg, ScalarMaskTag, VectorReg, GotoVariable, SccTag,
|
||||
ExecTag, ExecLoTag, ExecHiTag, VccTag, VccLoTag, VccHiTag, M0Tag>;
|
||||
using ValueMap = std::unordered_map<Block*, Value>;
|
||||
|
||||
struct DefTable {
|
||||
@@ -105,16 +99,12 @@ struct DefTable {
|
||||
void Set(Block* block, SccTag, Value value) { scc[block] = value; }
|
||||
const Value& Get(Block* block, ExecTag) { return exec[block]; }
|
||||
void Set(Block* block, ExecTag, Value value) { exec[block] = value; }
|
||||
const Value& Get(Block* block, ExecMaskTag) { return exec_mask_tag[block]; }
|
||||
void Set(Block* block, ExecMaskTag, Value value) { exec_mask_tag[block] = value; }
|
||||
const Value& Get(Block* block, ExecLoTag) { return exec_lo[block]; }
|
||||
void Set(Block* block, ExecLoTag, Value value) { exec_lo[block] = value; }
|
||||
const Value& Get(Block* block, ExecHiTag) { return exec_hi[block]; }
|
||||
void Set(Block* block, ExecHiTag, Value value) { exec_hi[block] = value; }
|
||||
const Value& Get(Block* block, VccTag) { return vcc[block]; }
|
||||
void Set(Block* block, VccTag, Value value) { vcc[block] = value; }
|
||||
const Value& Get(Block* block, VccMaskValidTag) { return vcc_mask_valid_tag[block]; }
|
||||
void Set(Block* block, VccMaskValidTag, Value value) { vcc_mask_valid_tag[block] = value; }
|
||||
const Value& Get(Block* block, VccLoTag) { return vcc_lo[block]; }
|
||||
void Set(Block* block, VccLoTag, Value value) { vcc_lo[block] = value; }
|
||||
const Value& Get(Block* block, VccHiTag) { return vcc_hi[block]; }
|
||||
@@ -124,11 +114,9 @@ struct DefTable {
|
||||
|
||||
ValueMap scc;
|
||||
ValueMap exec;
|
||||
ValueMap exec_mask_tag;
|
||||
ValueMap exec_lo;
|
||||
ValueMap exec_hi;
|
||||
ValueMap vcc;
|
||||
ValueMap vcc_mask_valid_tag;
|
||||
ValueMap vcc_lo;
|
||||
ValueMap vcc_hi;
|
||||
ValueMap m0;
|
||||
@@ -156,9 +144,6 @@ ValueOpcode UndefOpcode(SccTag) {
|
||||
ValueOpcode UndefOpcode(ExecTag) {
|
||||
return ValueOpcode::UndefU1;
|
||||
}
|
||||
ValueOpcode UndefOpcode(ExecMaskTag) {
|
||||
return ValueOpcode::UndefU1;
|
||||
}
|
||||
ValueOpcode UndefOpcode(ExecLoTag) {
|
||||
return ValueOpcode::UndefU32;
|
||||
}
|
||||
@@ -168,9 +153,6 @@ ValueOpcode UndefOpcode(ExecHiTag) {
|
||||
ValueOpcode UndefOpcode(VccTag) {
|
||||
return ValueOpcode::UndefU1;
|
||||
}
|
||||
ValueOpcode UndefOpcode(VccMaskValidTag) {
|
||||
return ValueOpcode::UndefU1;
|
||||
}
|
||||
ValueOpcode UndefOpcode(VccLoTag) {
|
||||
return ValueOpcode::UndefU32;
|
||||
}
|
||||
@@ -202,9 +184,6 @@ Value InitialValue(SccTag) {
|
||||
Value InitialValue(ExecTag) {
|
||||
return Value(false);
|
||||
}
|
||||
Value InitialValue(ExecMaskTag) {
|
||||
return Value(false);
|
||||
}
|
||||
Value InitialValue(ExecLoTag) {
|
||||
return Value(0u);
|
||||
}
|
||||
@@ -214,9 +193,6 @@ Value InitialValue(ExecHiTag) {
|
||||
Value InitialValue(VccTag) {
|
||||
return Value(false);
|
||||
}
|
||||
Value InitialValue(VccMaskValidTag) {
|
||||
return Value(false);
|
||||
}
|
||||
Value InitialValue(VccLoTag) {
|
||||
return Value(0u);
|
||||
}
|
||||
@@ -375,15 +351,9 @@ void VisitInstruction(Pass& pass, Block* block, Inst& inst) {
|
||||
break;
|
||||
case ValueOpcode::SetScc: pass.Write(SccTag {}, block, inst.Arg(0)); break;
|
||||
case ValueOpcode::SetExec: pass.Write(ExecTag {}, block, inst.Arg(0)); break;
|
||||
case ValueOpcode::SetExecMaskTag:
|
||||
pass.Write(ExecMaskTag {}, block, inst.Arg(0));
|
||||
break;
|
||||
case ValueOpcode::SetExecLo: pass.Write(ExecLoTag {}, block, inst.Arg(0)); break;
|
||||
case ValueOpcode::SetExecHi: pass.Write(ExecHiTag {}, block, inst.Arg(0)); break;
|
||||
case ValueOpcode::SetVcc: pass.Write(VccTag {}, block, inst.Arg(0)); break;
|
||||
case ValueOpcode::SetVccMaskValidTag:
|
||||
pass.Write(VccMaskValidTag {}, block, inst.Arg(0));
|
||||
break;
|
||||
case ValueOpcode::SetVccLo: pass.Write(VccLoTag {}, block, inst.Arg(0)); break;
|
||||
case ValueOpcode::SetVccHi: pass.Write(VccHiTag {}, block, inst.Arg(0)); break;
|
||||
case ValueOpcode::SetM0: pass.Write(M0Tag {}, block, inst.Arg(0)); break;
|
||||
@@ -405,15 +375,9 @@ void VisitInstruction(Pass& pass, Block* block, Inst& inst) {
|
||||
break;
|
||||
case ValueOpcode::GetScc: inst.ReplaceUsesWith(pass.Read(SccTag {}, block)); break;
|
||||
case ValueOpcode::GetExec: inst.ReplaceUsesWith(pass.Read(ExecTag {}, block)); break;
|
||||
case ValueOpcode::GetExecMaskTag:
|
||||
inst.ReplaceUsesWith(pass.Read(ExecMaskTag {}, block));
|
||||
break;
|
||||
case ValueOpcode::GetExecLo: inst.ReplaceUsesWith(pass.Read(ExecLoTag {}, block)); break;
|
||||
case ValueOpcode::GetExecHi: inst.ReplaceUsesWith(pass.Read(ExecHiTag {}, block)); break;
|
||||
case ValueOpcode::GetVcc: inst.ReplaceUsesWith(pass.Read(VccTag {}, block)); break;
|
||||
case ValueOpcode::GetVccMaskValidTag:
|
||||
inst.ReplaceUsesWith(pass.Read(VccMaskValidTag {}, block));
|
||||
break;
|
||||
case ValueOpcode::GetVccLo: inst.ReplaceUsesWith(pass.Read(VccLoTag {}, block)); break;
|
||||
case ValueOpcode::GetVccHi: inst.ReplaceUsesWith(pass.Read(VccHiTag {}, block)); break;
|
||||
case ValueOpcode::GetM0: inst.ReplaceUsesWith(pass.Read(M0Tag {}, block)); break;
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <bit>
|
||||
#include <cstdio>
|
||||
#include <filesystem>
|
||||
#include <fmt/format.h>
|
||||
@@ -571,7 +572,10 @@ static void ShaderApplyAttribSemantics(ShaderVertexInputInfo& info,
|
||||
uint32_t reg = in.hardware_mapping;
|
||||
uint32_t size = in.size_in_elements;
|
||||
|
||||
LOGF("reg = %u, size = %u, va[%u] = 0x%08" PRIx32 "\n", reg, size, i, attrib[in.semantic]);
|
||||
if (Config::GraphicsDebugDumpEnabled()) {
|
||||
LOGF("reg = %u, size = %u, va[%u] = 0x%08" PRIx32 "\n", reg, size, i,
|
||||
attrib[in.semantic]);
|
||||
}
|
||||
|
||||
size_t index = attrib[in.semantic] & 0x1fu;
|
||||
auto format =
|
||||
@@ -894,6 +898,18 @@ void BuildStageStaticKey(const ShaderVertexInputInfo& info, std::vector<uint32_t
|
||||
key.push_back(info.resources_num);
|
||||
key.push_back(info.scratch_size_dwords);
|
||||
key.push_back(info.pa_cl_vs_out_cntl);
|
||||
key.push_back(static_cast<uint32_t>(info.clip_space.enabled));
|
||||
if (info.clip_space.enabled) {
|
||||
for (const float value: info.clip_space.scale) {
|
||||
key.push_back(std::bit_cast<uint32_t>(value));
|
||||
}
|
||||
for (const float value: info.clip_space.offset) {
|
||||
key.push_back(std::bit_cast<uint32_t>(value));
|
||||
}
|
||||
for (const float value: info.clip_space.half_extent) {
|
||||
key.push_back(std::bit_cast<uint32_t>(value));
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < info.resources_num; i++) {
|
||||
const auto& resource = info.resources[i];
|
||||
|
||||
@@ -68,6 +68,13 @@ inline uint8_t GetDstSel(uint32_t swizzle, uint32_t channel) {
|
||||
return (swizzle >> (channel * 3u)) & 0x7u;
|
||||
}
|
||||
|
||||
struct ShaderClipSpaceTransform {
|
||||
float scale[2] = {};
|
||||
float offset[2] = {};
|
||||
float half_extent[2] = {};
|
||||
bool enabled = false;
|
||||
};
|
||||
|
||||
struct ShaderVertexInputInfo {
|
||||
static constexpr int RES_MAX = 32;
|
||||
|
||||
@@ -84,6 +91,7 @@ struct ShaderVertexInputInfo {
|
||||
uint32_t scratch_size_dwords = 0;
|
||||
uint32_t param_export_mask = 0;
|
||||
uint32_t pa_cl_vs_out_cntl = 0;
|
||||
ShaderClipSpaceTransform clip_space;
|
||||
bool fetch_external = false;
|
||||
bool fetch_embedded = false;
|
||||
};
|
||||
|
||||
+48
-37
@@ -44,6 +44,13 @@ namespace Libs::Graphics {
|
||||
|
||||
static RenderContext* g_renderer = nullptr;
|
||||
|
||||
template <typename... Args>
|
||||
static void AgcTrace(const char* format, const Args&... args) {
|
||||
if (Config::GraphicsDebugDumpEnabled()) {
|
||||
LOGF(format, args...);
|
||||
}
|
||||
}
|
||||
|
||||
void Initialize() {
|
||||
// Some games lock up if this is not called first
|
||||
if (Config::RenderDocEnabled()) {
|
||||
@@ -363,6 +370,10 @@ void* KYTY_SYSV_ABI AgcGetRegisterDefaults2Internal(uint32_t ver) {
|
||||
}
|
||||
|
||||
static void dbg_dump_shader(const Shader* h) {
|
||||
if (!Config::GraphicsDebugDumpEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOGF("\t file_header = 0x%08" PRIx32 "\n"
|
||||
"\t version = 0x%08" PRIx32 "\n"
|
||||
"\t user_data = 0x%016" PRIx64 "\n",
|
||||
@@ -952,7 +963,7 @@ int KYTY_SYSV_ABI AgcSetCxRegIndirectPatchSetAddress(uint32_t*
|
||||
const volatile ShaderRegister* regs) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t cmd = 0x%016" PRIx64 "\n"
|
||||
AgcTrace("\t cmd = 0x%016" PRIx64 "\n"
|
||||
"\t regs = 0x%016" PRIx64 "\n",
|
||||
reinterpret_cast<uint64_t>(cmd), reinterpret_cast<uint64_t>(regs));
|
||||
|
||||
@@ -968,7 +979,7 @@ int KYTY_SYSV_ABI AgcSetShRegIndirectPatchSetAddress(uint32_t*
|
||||
const volatile ShaderRegister* regs) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t cmd = 0x%016" PRIx64 "\n"
|
||||
AgcTrace("\t cmd = 0x%016" PRIx64 "\n"
|
||||
"\t regs = 0x%016" PRIx64 "\n",
|
||||
reinterpret_cast<uint64_t>(cmd), reinterpret_cast<uint64_t>(regs));
|
||||
|
||||
@@ -984,7 +995,7 @@ int KYTY_SYSV_ABI AgcSetUcRegIndirectPatchSetAddress(uint32_t*
|
||||
const volatile ShaderRegister* regs) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t cmd = 0x%016" PRIx64 "\n"
|
||||
AgcTrace("\t cmd = 0x%016" PRIx64 "\n"
|
||||
"\t regs = 0x%016" PRIx64 "\n",
|
||||
reinterpret_cast<uint64_t>(cmd), reinterpret_cast<uint64_t>(regs));
|
||||
|
||||
@@ -999,7 +1010,7 @@ int KYTY_SYSV_ABI AgcSetUcRegIndirectPatchSetAddress(uint32_t*
|
||||
int KYTY_SYSV_ABI AgcSetCxRegIndirectPatchSetNumRegisters(uint32_t* cmd, uint32_t num_regs) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t cmd = 0x%016" PRIx64 "\n"
|
||||
AgcTrace("\t cmd = 0x%016" PRIx64 "\n"
|
||||
"\t num_regs = %" PRIu32 "\n",
|
||||
reinterpret_cast<uint64_t>(cmd), num_regs);
|
||||
|
||||
@@ -1011,7 +1022,7 @@ int KYTY_SYSV_ABI AgcSetCxRegIndirectPatchSetNumRegisters(uint32_t* cmd, uint32_
|
||||
int KYTY_SYSV_ABI AgcSetShRegIndirectPatchSetNumRegisters(uint32_t* cmd, uint32_t num_regs) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t cmd = 0x%016" PRIx64 "\n"
|
||||
AgcTrace("\t cmd = 0x%016" PRIx64 "\n"
|
||||
"\t num_regs = %" PRIu32 "\n",
|
||||
reinterpret_cast<uint64_t>(cmd), num_regs);
|
||||
|
||||
@@ -1023,7 +1034,7 @@ int KYTY_SYSV_ABI AgcSetShRegIndirectPatchSetNumRegisters(uint32_t* cmd, uint32_
|
||||
int KYTY_SYSV_ABI AgcSetUcRegIndirectPatchSetNumRegisters(uint32_t* cmd, uint32_t num_regs) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t cmd = 0x%016" PRIx64 "\n"
|
||||
AgcTrace("\t cmd = 0x%016" PRIx64 "\n"
|
||||
"\t num_regs = %" PRIu32 "\n",
|
||||
reinterpret_cast<uint64_t>(cmd), num_regs);
|
||||
|
||||
@@ -1035,7 +1046,7 @@ int KYTY_SYSV_ABI AgcSetUcRegIndirectPatchSetNumRegisters(uint32_t* cmd, uint32_
|
||||
int KYTY_SYSV_ABI AgcSetCxRegIndirectPatchAddRegisters(uint32_t* cmd, uint32_t num_regs) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t cmd = 0x%016" PRIx64 "\n"
|
||||
AgcTrace("\t cmd = 0x%016" PRIx64 "\n"
|
||||
"\t num_regs = %" PRIu32 "\n",
|
||||
reinterpret_cast<uint64_t>(cmd), num_regs);
|
||||
|
||||
@@ -1047,7 +1058,7 @@ int KYTY_SYSV_ABI AgcSetCxRegIndirectPatchAddRegisters(uint32_t* cmd, uint32_t n
|
||||
int KYTY_SYSV_ABI AgcSetShRegIndirectPatchAddRegisters(uint32_t* cmd, uint32_t num_regs) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t cmd = 0x%016" PRIx64 "\n"
|
||||
AgcTrace("\t cmd = 0x%016" PRIx64 "\n"
|
||||
"\t num_regs = %" PRIu32 "\n",
|
||||
reinterpret_cast<uint64_t>(cmd), num_regs);
|
||||
|
||||
@@ -1059,7 +1070,7 @@ int KYTY_SYSV_ABI AgcSetShRegIndirectPatchAddRegisters(uint32_t* cmd, uint32_t n
|
||||
int KYTY_SYSV_ABI AgcSetUcRegIndirectPatchAddRegisters(uint32_t* cmd, uint32_t num_regs) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t cmd = 0x%016" PRIx64 "\n"
|
||||
AgcTrace("\t cmd = 0x%016" PRIx64 "\n"
|
||||
"\t num_regs = %" PRIu32 "\n",
|
||||
reinterpret_cast<uint64_t>(cmd), num_regs);
|
||||
|
||||
@@ -1090,7 +1101,7 @@ int KYTY_SYSV_ABI AgcCreatePrimState(ShaderRegister* cx_regs, ShaderRegister* uc
|
||||
const Shader* hs, const Shader* gs, uint32_t prim_type) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t cx_regs = 0x%016" PRIx64 "\n"
|
||||
AgcTrace("\t cx_regs = 0x%016" PRIx64 "\n"
|
||||
"\t uc_regs = 0x%016" PRIx64 "\n"
|
||||
"\t hs = 0x%016" PRIx64 "\n"
|
||||
"\t gs = 0x%016" PRIx64 "\n"
|
||||
@@ -1158,7 +1169,7 @@ int KYTY_SYSV_ABI AgcUpdatePrimState(ShaderRegister* cx_regs, ShaderRegister* uc
|
||||
uint32_t prim_type) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t cx_regs = 0x%016" PRIx64 "\n"
|
||||
AgcTrace("\t cx_regs = 0x%016" PRIx64 "\n"
|
||||
"\t uc_regs = 0x%016" PRIx64 "\n"
|
||||
"\t prim_type = %" PRIu32 "\n",
|
||||
reinterpret_cast<uint64_t>(cx_regs), reinterpret_cast<uint64_t>(uc_regs), prim_type);
|
||||
@@ -1220,7 +1231,7 @@ int KYTY_SYSV_ABI AgcGetGsOversubscription(ShaderRegister* regs, const Shader* g
|
||||
constexpr uint32_t FULL_PC_OVERSUBSCRIPTION = 0x7ffu;
|
||||
constexpr uint32_t FULL_SH_OVERSUBSCRIPTION = 0x007f0000u;
|
||||
|
||||
regs[0] = {Pm4::GE_PC_ALLOC, 0u};
|
||||
regs[0] = {Pm4::UC_PARAMETER_OVERSUBSCRIPTION, 0u};
|
||||
regs[1] = {Pm4::SPI_SHADER_PGM_RSRC4_GS, 0u};
|
||||
|
||||
if (budget == 0u) {
|
||||
@@ -1363,7 +1374,7 @@ int KYTY_SYSV_ABI AgcCreateInterpolantMapping(ShaderRegister* regs, const Shader
|
||||
const Shader* ps) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t regs = 0x%016" PRIx64 "\n"
|
||||
AgcTrace("\t regs = 0x%016" PRIx64 "\n"
|
||||
"\t gs = 0x%016" PRIx64 "\n"
|
||||
"\t ps = 0x%016" PRIx64 "\n",
|
||||
reinterpret_cast<uint64_t>(regs), reinterpret_cast<uint64_t>(gs),
|
||||
@@ -1419,7 +1430,7 @@ int KYTY_SYSV_ABI AgcCreateInterpolantMapping2(ShaderRegister* regs, const Shade
|
||||
const Shader* ps) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t regs = 0x%016" PRIx64 "\n"
|
||||
AgcTrace("\t regs = 0x%016" PRIx64 "\n"
|
||||
"\t gs = 0x%016" PRIx64 "\n"
|
||||
"\t ps = 0x%016" PRIx64 "\n",
|
||||
reinterpret_cast<uint64_t>(regs), reinterpret_cast<uint64_t>(gs),
|
||||
@@ -1942,7 +1953,7 @@ uint32_t* KYTY_SYSV_ABI AgcCbSetShRegistersDirect(CommandBuffer*
|
||||
uint32_t num_regs) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t regs = 0x%016" PRIx64 "\n"
|
||||
AgcTrace("\t regs = 0x%016" PRIx64 "\n"
|
||||
"\t num_regs = %" PRIu32 "\n",
|
||||
reinterpret_cast<uint64_t>(regs), num_regs);
|
||||
|
||||
@@ -2009,7 +2020,7 @@ uint32_t* KYTY_SYSV_ABI AgcCbSetUcRegistersDirect(CommandBuffer*
|
||||
uint32_t num_regs) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t regs = 0x%016" PRIx64 "\n"
|
||||
AgcTrace("\t regs = 0x%016" PRIx64 "\n"
|
||||
"\t num_regs = %" PRIu32 "\n",
|
||||
reinterpret_cast<uint64_t>(regs), num_regs);
|
||||
|
||||
@@ -2396,7 +2407,7 @@ uint32_t* KYTY_SYSV_ABI AgcDcbSetCxRegistersIndirect(CommandBuffer*
|
||||
uint32_t num_regs) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t regs = 0x%016" PRIx64 "\n"
|
||||
AgcTrace("\t regs = 0x%016" PRIx64 "\n"
|
||||
"\t num_regs = %" PRIu32 "\n",
|
||||
reinterpret_cast<uint64_t>(regs), num_regs);
|
||||
|
||||
@@ -2420,7 +2431,7 @@ uint32_t* KYTY_SYSV_ABI AgcDcbSetShRegistersIndirect(CommandBuffer*
|
||||
uint32_t num_regs) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t regs = 0x%016" PRIx64 "\n"
|
||||
AgcTrace("\t regs = 0x%016" PRIx64 "\n"
|
||||
"\t num_regs = %" PRIu32 "\n",
|
||||
reinterpret_cast<uint64_t>(regs), num_regs);
|
||||
|
||||
@@ -2444,7 +2455,7 @@ uint32_t* KYTY_SYSV_ABI AgcDcbSetUcRegistersIndirect(CommandBuffer*
|
||||
uint32_t num_regs) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t regs = 0x%016" PRIx64 "\n"
|
||||
AgcTrace("\t regs = 0x%016" PRIx64 "\n"
|
||||
"\t num_regs = %" PRIu32 "\n",
|
||||
reinterpret_cast<uint64_t>(regs), num_regs);
|
||||
|
||||
@@ -2467,7 +2478,7 @@ uint32_t* KYTY_SYSV_ABI AgcDcbSetIndexSize(CommandBuffer* buf, uint8_t index_siz
|
||||
uint8_t cache_policy) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t index_size = 0x%" PRIx8 "\n"
|
||||
AgcTrace("\t index_size = 0x%" PRIx8 "\n"
|
||||
"\t cache_policy = 0x%" PRIx8 "\n",
|
||||
index_size, cache_policy);
|
||||
|
||||
@@ -2488,7 +2499,7 @@ uint32_t* KYTY_SYSV_ABI AgcDcbSetIndexSize(CommandBuffer* buf, uint8_t index_siz
|
||||
uint32_t* KYTY_SYSV_ABI AgcDcbSetIndexBuffer(CommandBuffer* buf, uint64_t index_addr) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t index_addr = 0x%016" PRIx64 "\n", index_addr);
|
||||
AgcTrace("\t index_addr = 0x%016" PRIx64 "\n", index_addr);
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(buf == nullptr);
|
||||
EXIT_NOT_IMPLEMENTED((index_addr & 1u) != 0);
|
||||
@@ -2509,7 +2520,7 @@ uint32_t* KYTY_SYSV_ABI AgcDcbSetIndexBuffer(CommandBuffer* buf, uint64_t index_
|
||||
uint32_t* KYTY_SYSV_ABI AgcDcbSetIndexCount(CommandBuffer* buf, uint32_t index_count) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t index_count = 0x%" PRIx32 "\n", index_count);
|
||||
AgcTrace("\t index_count = 0x%" PRIx32 "\n", index_count);
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(buf == nullptr);
|
||||
|
||||
@@ -2528,7 +2539,7 @@ uint32_t* KYTY_SYSV_ABI AgcDcbSetIndexCount(CommandBuffer* buf, uint32_t index_c
|
||||
uint32_t* KYTY_SYSV_ABI AgcDcbSetNumInstances(CommandBuffer* buf, uint32_t num_instances) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t num_instances = 0x%" PRIx32 "\n", num_instances);
|
||||
AgcTrace("\t num_instances = 0x%" PRIx32 "\n", num_instances);
|
||||
|
||||
if (buf == nullptr) {
|
||||
return nullptr;
|
||||
@@ -2624,7 +2635,7 @@ uint32_t* KYTY_SYSV_ABI AgcDcbDrawIndex(CommandBuffer* buf, uint32_t index_count
|
||||
const volatile void* index_addr, uint64_t modifier) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t index_count = 0x%" PRIx32 "\n"
|
||||
AgcTrace("\t index_count = 0x%" PRIx32 "\n"
|
||||
"\t index_addr = 0x%016" PRIx64 "\n"
|
||||
"\t modifier = 0x%016" PRIx64 "\n",
|
||||
index_count, reinterpret_cast<uint64_t>(index_addr), modifier);
|
||||
@@ -2663,7 +2674,7 @@ uint32_t* KYTY_SYSV_ABI AgcDcbDrawIndexMultiInstanced(CommandBuffer* buf, uint32
|
||||
uint32_t instance_count, uint64_t modifier) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t index_count = 0x%" PRIx32 "\n"
|
||||
AgcTrace("\t index_count = 0x%" PRIx32 "\n"
|
||||
"\t index_addr = 0x%016" PRIx64 "\n"
|
||||
"\t instance_count = 0x%" PRIx32 "\n"
|
||||
"\t object_ids = 0x%016" PRIx64 "\n"
|
||||
@@ -2739,7 +2750,7 @@ uint32_t* KYTY_SYSV_ABI AgcDcbDrawIndexAuto(CommandBuffer* buf, uint32_t index_c
|
||||
uint64_t modifier) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t index_count = 0x%" PRIx32 "\n"
|
||||
AgcTrace("\t index_count = 0x%" PRIx32 "\n"
|
||||
"\t modifier = 0x%016" PRIx64 "\n",
|
||||
index_count, modifier);
|
||||
|
||||
@@ -2768,7 +2779,7 @@ uint32_t* KYTY_SYSV_ABI AgcDcbDrawIndexOffset(CommandBuffer* buf, uint32_t index
|
||||
uint32_t index_count, uint64_t modifier) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t index_offset = 0x%" PRIx32 "\n"
|
||||
AgcTrace("\t index_offset = 0x%" PRIx32 "\n"
|
||||
"\t index_count = 0x%" PRIx32 "\n"
|
||||
"\t modifier = 0x%016" PRIx64 "\n",
|
||||
index_offset, index_count, modifier);
|
||||
@@ -2826,7 +2837,7 @@ uint32_t* KYTY_SYSV_ABI AgcDcbDrawIndexIndirect(CommandBuffer* buf, uint32_t dat
|
||||
uint64_t modifier) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t data_offset = 0x%" PRIx32 "\n"
|
||||
AgcTrace("\t data_offset = 0x%" PRIx32 "\n"
|
||||
"\t modifier = 0x%016" PRIx64 "\n",
|
||||
data_offset_in_bytes, modifier);
|
||||
|
||||
@@ -2853,7 +2864,7 @@ uint32_t* KYTY_SYSV_ABI AgcDcbDrawIndirect(CommandBuffer* buf, uint32_t data_off
|
||||
uint64_t modifier) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t data_offset = 0x%" PRIx32 "\n"
|
||||
AgcTrace("\t data_offset = 0x%" PRIx32 "\n"
|
||||
"\t modifier = 0x%016" PRIx64 "\n",
|
||||
data_offset_in_bytes, modifier);
|
||||
|
||||
@@ -2884,7 +2895,7 @@ uint32_t* KYTY_SYSV_ABI AgcDcbDrawIndirectMulti(CommandBuffer* buf,
|
||||
uint32_t stride_in_bytes, uint64_t modifier) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t data_offset = 0x%" PRIx32 "\n"
|
||||
AgcTrace("\t data_offset = 0x%" PRIx32 "\n"
|
||||
"\t count_indirect = 0x%" PRIx32 "\n"
|
||||
"\t max_count_or_count = 0x%" PRIx32 "\n"
|
||||
"\t count_addr = 0x%016" PRIx64 "\n"
|
||||
@@ -2947,7 +2958,7 @@ uint32_t* KYTY_SYSV_ABI AgcDcbDrawIndexIndirectMulti(CommandBuffer* buf,
|
||||
uint32_t stride_in_bytes, uint64_t modifier) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t data_offset = 0x%" PRIx32 "\n"
|
||||
AgcTrace("\t data_offset = 0x%" PRIx32 "\n"
|
||||
"\t count_indirect = 0x%" PRIx32 "\n"
|
||||
"\t max_count_or_count = 0x%" PRIx32 "\n"
|
||||
"\t count_addr = 0x%016" PRIx64 "\n"
|
||||
@@ -3801,7 +3812,7 @@ uint32_t* KYTY_SYSV_ABI AgcDcbWriteData(CommandBuffer* buf, uint8_t dst, uint8_t
|
||||
uint8_t write_confirm) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t dst = 0x%02" PRIx8 "\n"
|
||||
AgcTrace("\t dst = 0x%02" PRIx8 "\n"
|
||||
"\t cache_policy = 0x%02" PRIx8 "\n"
|
||||
"\t address_or_offset = 0x%016" PRIx64 "\n"
|
||||
"\t data = 0x%016" PRIx64 "\n"
|
||||
@@ -4054,7 +4065,7 @@ uint32_t* KYTY_SYSV_ABI AgcDcbWaitRegMem(CommandBuffer* buf, uint8_t size, uint8
|
||||
uint64_t mask, uint32_t poll_cycles) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t size = 0x%02" PRIx8 "\n"
|
||||
AgcTrace("\t size = 0x%02" PRIx8 "\n"
|
||||
"\t compare_function = 0x%02" PRIx8 "\n"
|
||||
"\t op = 0x%02" PRIx8 "\n"
|
||||
"\t cache_policy = 0x%02" PRIx8 "\n"
|
||||
@@ -4201,7 +4212,7 @@ uint32_t* KYTY_SYSV_ABI AgcDcbSetFlip(CommandBuffer* buf, uint32_t video_out_han
|
||||
int64_t flip_arg) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t video_out_handle = %" PRIu32 "\n"
|
||||
AgcTrace("\t video_out_handle = %" PRIu32 "\n"
|
||||
"\t display_buffer_index = %" PRId32 "\n"
|
||||
"\t flip_mode = %" PRIu32 "\n"
|
||||
"\t flip_arg = %" PRId64 "\n",
|
||||
@@ -4252,7 +4263,7 @@ int KYTY_SYSV_ABI AgcDriverSubmitDcb(const Packet* packet) {
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(packet == nullptr);
|
||||
|
||||
LOGF("\t addr = 0x%016" PRIx64 "\n"
|
||||
AgcTrace("\t addr = 0x%016" PRIx64 "\n"
|
||||
"\t dw_num = 0x%08" PRIx32 "\n"
|
||||
"\t flags = 0x%02" PRIx8 "\n",
|
||||
reinterpret_cast<uint64_t>(packet->addr), packet->dw_num, packet->flags);
|
||||
@@ -4266,7 +4277,7 @@ int KYTY_SYSV_ABI AgcDriverSubmitMultiDcbs(uint32_t* const* dcb_gpu_addrs,
|
||||
const uint32_t* dcb_sizes_in_dwords, uint32_t count) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t count = %" PRIu32 "\n", count);
|
||||
AgcTrace("\t count = %" PRIu32 "\n", count);
|
||||
|
||||
if (count == 0) {
|
||||
return OK;
|
||||
@@ -4279,7 +4290,7 @@ int KYTY_SYSV_ABI AgcDriverSubmitMultiDcbs(uint32_t* const* dcb_gpu_addrs,
|
||||
auto* dcb = dcb_gpu_addrs[i];
|
||||
uint32_t size_in_dwords = dcb_sizes_in_dwords[i];
|
||||
|
||||
LOGF("\t dcb[%" PRIu32 "] = 0x%016" PRIx64 "\n"
|
||||
AgcTrace("\t dcb[%" PRIu32 "] = 0x%016" PRIx64 "\n"
|
||||
"\t size[%" PRIu32 "] = 0x%08" PRIx32 "\n",
|
||||
i, reinterpret_cast<uint64_t>(dcb), i, size_in_dwords);
|
||||
|
||||
|
||||
@@ -2931,7 +2931,6 @@ int KYTY_SYSV_ABI Ngs2VoiceGetState(uintptr_t voice_handle, Ngs2VoiceState* stat
|
||||
auto* submixer = reinterpret_cast<Ngs2SubmixerVoiceState*>(state);
|
||||
*submixer = {};
|
||||
submixer->voice_state.state_flags = Ngs2GetStateFlags(voice);
|
||||
LOGF("\t state_flags = %u\n", submixer->voice_state.state_flags);
|
||||
break;
|
||||
}
|
||||
case Ngs2RackType::CustomMastering: {
|
||||
@@ -2942,7 +2941,6 @@ int KYTY_SYSV_ABI Ngs2VoiceGetState(uintptr_t voice_handle, Ngs2VoiceState* stat
|
||||
std::memset(state, 0, state_size);
|
||||
auto* mastering = reinterpret_cast<Ngs2CustomMasteringVoiceState*>(state);
|
||||
mastering->voice_state.state_flags = Ngs2GetStateFlags(voice);
|
||||
LOGF("\t state_flags = %u\n", mastering->voice_state.state_flags);
|
||||
break;
|
||||
}
|
||||
case Ngs2RackType::Sampler:
|
||||
@@ -2957,7 +2955,6 @@ int KYTY_SYSV_ABI Ngs2VoiceGetState(uintptr_t voice_handle, Ngs2VoiceState* stat
|
||||
|
||||
state->state_flags = Ngs2GetStateFlags(voice);
|
||||
if (state_size < sizeof(Ngs2SamplerVoiceState)) {
|
||||
LOGF("\t state_flags = %u\n", state->state_flags);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2968,7 +2965,6 @@ int KYTY_SYSV_ABI Ngs2VoiceGetState(uintptr_t voice_handle, Ngs2VoiceState* stat
|
||||
sampler->num_decoded_samples = 0;
|
||||
sampler->user_data = 0;
|
||||
sampler->waveform_data = nullptr;
|
||||
LOGF("\t state_flags = %u\n", sampler->voice_state.state_flags);
|
||||
break;
|
||||
}
|
||||
default: EXIT("unknown type: %s\n", Common::EnumName(voice->rack->type).c_str());
|
||||
@@ -2989,8 +2985,6 @@ int KYTY_SYSV_ABI Ngs2VoiceGetStateFlags(uintptr_t voice_handle, uint32_t* state
|
||||
|
||||
*state_flags = Ngs2GetStateFlags(voice);
|
||||
|
||||
LOGF("\t state_flags = %u\n", *state_flags);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -635,6 +635,7 @@ LIB_DEFINE(InitNet_1_Http) {
|
||||
LIB_FUNC("P6A3ytpsiYc", Http::HttpDeleteConnection);
|
||||
LIB_FUNC("tsGVru3hCe8", Http::HttpCreateRequest);
|
||||
LIB_FUNC("Aeu5wVKkF9w", Http::HttpCreateRequest);
|
||||
LIB_FUNC("rGNm+FjIXKk", Http::HttpCreateRequest2);
|
||||
LIB_FUNC("Cnp77podkCU", Http::HttpCreateRequestWithURL2);
|
||||
LIB_FUNC("qe7oZ+v4PWA", Http::HttpDeleteRequest);
|
||||
LIB_FUNC("PTiFIUxCpJc", Http::HttpSetRequestContentLength);
|
||||
|
||||
+26
-12
@@ -1055,8 +1055,7 @@ static int ConvertGuestSockaddr(const void* addr, uint32_t addrlen, sockaddr_sto
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
static int ConvertHostSockaddr(const sockaddr_storage* addr, int addrlen, void* out,
|
||||
static int ConvertHostSockaddr(const sockaddr_storage* addr, SocketLength addrlen, void* out,
|
||||
uint32_t* out_len) {
|
||||
EXIT_IF(addr == nullptr);
|
||||
EXIT_IF(out_len == nullptr);
|
||||
@@ -1066,7 +1065,8 @@ static int ConvertHostSockaddr(const sockaddr_storage* addr, int addrlen, void*
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (addr->ss_family != AF_INET || addrlen < static_cast<int>(sizeof(sockaddr_in))) {
|
||||
if (addr->ss_family != AF_INET ||
|
||||
addrlen < static_cast<SocketLength>(sizeof(sockaddr_in))) {
|
||||
*Posix::GetErrorAddr() = Posix::POSIX_EOPNOTSUPP;
|
||||
return -1;
|
||||
}
|
||||
@@ -1088,7 +1088,6 @@ static int ConvertHostSockaddr(const sockaddr_storage* addr, int addrlen, void*
|
||||
*out_len = guest_addrlen;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool GetSocketBackend(int guest_fd, NativeSocket* out) {
|
||||
EXIT_IF(out == nullptr);
|
||||
@@ -1851,19 +1850,13 @@ int KYTY_SYSV_ABI Getsockname(int s, void* addr, uint32_t* addrlen) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
sockaddr_storage host_addr {};
|
||||
int host_addrlen = sizeof(host_addr);
|
||||
if (::getsockname(socket, reinterpret_cast<sockaddr*>(&host_addr), &host_addrlen) ==
|
||||
SOCKET_ERROR) {
|
||||
SocketLength host_addrlen = sizeof(host_addr);
|
||||
if (::getsockname(socket, reinterpret_cast<sockaddr*>(&host_addr), &host_addrlen) != 0) {
|
||||
return SetHostSocketError();
|
||||
}
|
||||
|
||||
return ConvertHostSockaddr(&host_addr, host_addrlen, addr, addrlen);
|
||||
#else
|
||||
*Posix::GetErrorAddr() = Posix::POSIX_ENOSYS;
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI Getsockopt(int s, int level, int optname, void* optval, uint32_t* optlen) {
|
||||
@@ -2818,6 +2811,27 @@ int KYTY_SYSV_ABI HttpCreateRequest(int conn_id, int method, const char* path,
|
||||
return id.ToInt();
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI HttpCreateRequest2(int conn_id, const char* method, const char* path,
|
||||
uint64_t content_length) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t conn_id = %d\n"
|
||||
"\t method = %s\n"
|
||||
"\t path = %s\n"
|
||||
"\t content_length = %" PRIu64 "\n",
|
||||
conn_id, method, path, content_length);
|
||||
|
||||
EXIT_IF(g_net == nullptr);
|
||||
|
||||
if (method == nullptr || path == nullptr) {
|
||||
return HTTP_ERROR_INVALID_VALUE;
|
||||
}
|
||||
|
||||
auto id =
|
||||
g_net->HttpCreateRequestWithURL2(Network::Id(conn_id), method, path, content_length);
|
||||
return id.IsValid() ? id.ToInt() : HTTP_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI HttpCreateRequestWithURL2(int conn_id, const char* method, const char* url,
|
||||
uint64_t content_length) {
|
||||
PRINT_NAME();
|
||||
|
||||
@@ -106,6 +106,8 @@ int KYTY_SYSV_ABI HttpCreateConnectionWithURL(int tmpl_id, const char* url, int
|
||||
int KYTY_SYSV_ABI HttpDeleteConnection(int conn_id);
|
||||
int KYTY_SYSV_ABI HttpCreateRequest(int conn_id, int method, const char* path,
|
||||
uint64_t content_length);
|
||||
int KYTY_SYSV_ABI HttpCreateRequest2(int conn_id, const char* method, const char* path,
|
||||
uint64_t content_length);
|
||||
int KYTY_SYSV_ABI HttpCreateRequestWithURL2(int conn_id, const char* method, const char* url,
|
||||
uint64_t content_length);
|
||||
int KYTY_SYSV_ABI HttpSetRequestContentLength(int request_id, uint64_t content_length);
|
||||
|
||||
@@ -1166,7 +1166,6 @@ static void PatchProgram(Program* program, uint64_t address, uint64_t size) {
|
||||
prefix_count++;
|
||||
}
|
||||
|
||||
const size_t inst_size = prefix_count + Jit::Call9::GetSize();
|
||||
if (inst_ptr + Jit::Call9::GetSize() > start_ptr + size) {
|
||||
break;
|
||||
}
|
||||
@@ -1175,20 +1174,18 @@ static void PatchProgram(Program* program, uint64_t address, uint64_t size) {
|
||||
if (memcmp(inst_ptr, tls_pattern, 3) == 0 && (modrm & 0xc7u) == 0x04u &&
|
||||
inst_ptr[4] == tls_pattern[4] &&
|
||||
*reinterpret_cast<const uint32_t*>(inst_ptr + 5) == 0) {
|
||||
LOGF("Patch tls at addr: [%016" PRIx64 "]\n", reinterpret_cast<uint64_t>(ptr));
|
||||
LOGF("Patch tls at addr: [%016" PRIx64 "]\n",
|
||||
reinterpret_cast<uint64_t>(inst_ptr));
|
||||
|
||||
const auto reg = (modrm >> 3u) & 7u;
|
||||
EXIT_NOT_IMPLEMENTED(reg == 4u);
|
||||
|
||||
auto* code = new (ptr) Jit::Call9;
|
||||
// A raw scan can encounter a 0x66 in the preceding instruction.
|
||||
auto* code = new (inst_ptr) Jit::Call9;
|
||||
code->SetFunc(reg == 0
|
||||
? program->tls.handler_vaddr
|
||||
: program->tls.handler_vaddr + Jit::TlsRegStub::GetOffset(reg));
|
||||
if (inst_size > Jit::Call9::GetSize()) {
|
||||
std::memset(ptr + Jit::Call9::GetSize(), 0x90,
|
||||
inst_size - Jit::Call9::GetSize());
|
||||
}
|
||||
ptr += inst_size - 1;
|
||||
ptr += prefix_count + Jit::Call9::GetSize() - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -357,10 +357,23 @@ struct TextureCacheTestAccess {
|
||||
return cache.TryDownloadImage(id);
|
||||
}
|
||||
|
||||
static void RegisterHtileMeta(TextureCache &cache, uint64_t address) {
|
||||
std::lock_guard lock(cache.m_lock);
|
||||
auto &metadata = cache.m_surface_metas[address];
|
||||
metadata.type = TextureCache::MetaDataInfo::Type::HTile;
|
||||
metadata.clear_mask = 0;
|
||||
}
|
||||
|
||||
static TileManager &Tiler(TextureCache &cache) { return cache.m_tiler; }
|
||||
};
|
||||
|
||||
struct RenderExecutorTestAccess {
|
||||
static bool TryConsumeComputeMetaClear(RenderExecutor &executor,
|
||||
const ShaderComputeInputInfo &input,
|
||||
const CommandBuffer &buffer) {
|
||||
return executor.TryConsumeComputeMetaClear(input, buffer);
|
||||
}
|
||||
|
||||
static TextureBinding
|
||||
ResolveTexture(RenderExecutor &executor,
|
||||
const ShaderRecompiler::IR::ImageResource &resource,
|
||||
@@ -3778,6 +3791,92 @@ public:
|
||||
std::printf("[host] %-32s ok\n", name);
|
||||
}
|
||||
|
||||
void CheckComputeMetaClearClassification() {
|
||||
constexpr const char *name = "ComputeMetaClearClassification";
|
||||
constexpr uint64_t read_only_meta = 0x0000000204201f00ull;
|
||||
constexpr uint64_t read_write_meta = 0x0000000204202000ull;
|
||||
constexpr uint64_t write_only_meta = 0x0000000204202100ull;
|
||||
EnsureRuntimeContext();
|
||||
RenderContext context(m_runtime_context);
|
||||
auto &scheduler = context.GetCommandScheduler();
|
||||
HW::Context registers{};
|
||||
HW::UserConfig user_config{};
|
||||
HW::Shader shaders{};
|
||||
scheduler.Begin(registers, user_config, shaders);
|
||||
auto &texture_cache = context.GetTextureCache();
|
||||
TextureCacheTestAccess::RegisterHtileMeta(texture_cache, read_only_meta);
|
||||
TextureCacheTestAccess::RegisterHtileMeta(texture_cache, read_write_meta);
|
||||
TextureCacheTestAccess::RegisterHtileMeta(texture_cache, write_only_meta);
|
||||
Require(name, "HTile fixture",
|
||||
texture_cache.IsMeta(read_only_meta) &&
|
||||
texture_cache.IsMeta(read_write_meta) &&
|
||||
texture_cache.IsMeta(write_only_meta) &&
|
||||
!texture_cache.IsMetaCleared(read_only_meta, 0) &&
|
||||
!texture_cache.IsMetaCleared(read_write_meta, 0) &&
|
||||
!texture_cache.IsMetaCleared(write_only_meta, 0),
|
||||
"test HTile entries were not registered in their initial state");
|
||||
|
||||
const auto MakeInput = [](uint64_t address, bool read, bool written) {
|
||||
auto program = std::make_shared<ShaderRecompiler::IR::Program>();
|
||||
program->stage = ShaderType::Compute;
|
||||
ShaderRecompiler::IR::BufferResource resource{};
|
||||
resource.read = read;
|
||||
resource.written = written;
|
||||
resource.formatted = true;
|
||||
program->info.buffers.push_back(resource);
|
||||
|
||||
ShaderBufferResource descriptor{};
|
||||
descriptor.UpdateAddress48(address);
|
||||
descriptor.fields[1] |= 16u << 16u;
|
||||
descriptor.fields[2] = 8;
|
||||
descriptor.fields[3] =
|
||||
DstSel(4, 5, 6, 7) |
|
||||
(static_cast<uint32_t>(Prospero::BufferFormat::k32_32_32_32UInt)
|
||||
<< 12u);
|
||||
ShaderRecompiler::IR::DescriptorValue value{};
|
||||
value.dword_count = 4;
|
||||
std::copy_n(descriptor.fields, value.dword_count, value.dwords.begin());
|
||||
auto snapshot =
|
||||
std::make_shared<ShaderRecompiler::IR::ResourceSnapshot>();
|
||||
snapshot->buffers.push_back(value);
|
||||
|
||||
ShaderComputeInputInfo input{};
|
||||
input.stage.program = std::move(program);
|
||||
input.stage.resources = std::move(snapshot);
|
||||
return input;
|
||||
};
|
||||
auto &executor = context.GetRenderExecutor();
|
||||
auto &command = scheduler.Current();
|
||||
const auto read_only_input = MakeInput(read_only_meta, true, false);
|
||||
const bool read_only_consumed =
|
||||
RenderExecutorTestAccess::TryConsumeComputeMetaClear(
|
||||
executor, read_only_input, command);
|
||||
Require(name, "read-only dispatch preserved",
|
||||
!read_only_consumed &&
|
||||
!texture_cache.IsMetaCleared(read_only_meta, 0),
|
||||
"a metadata read-only dispatch changed logical clear state");
|
||||
|
||||
const auto read_write_input = MakeInput(read_write_meta, true, true);
|
||||
const bool read_write_consumed =
|
||||
RenderExecutorTestAccess::TryConsumeComputeMetaClear(
|
||||
executor, read_write_input, command);
|
||||
Require(name, "read/write dispatch preserved",
|
||||
!read_write_consumed &&
|
||||
!texture_cache.IsMetaCleared(read_write_meta, 0),
|
||||
"a metadata read/modify/write dispatch was replaced by a clear");
|
||||
|
||||
const auto write_only_input = MakeInput(write_only_meta, false, true);
|
||||
const bool write_only_consumed =
|
||||
RenderExecutorTestAccess::TryConsumeComputeMetaClear(
|
||||
executor, write_only_input, command);
|
||||
Require(name, "write-only fill consumed",
|
||||
write_only_consumed &&
|
||||
texture_cache.IsMetaCleared(write_only_meta, 0),
|
||||
"a metadata write-only fill was not consumed as a clear");
|
||||
scheduler.Finish();
|
||||
std::printf("[host] %-32s ok\n", name);
|
||||
}
|
||||
|
||||
void CheckUnifiedTextureCacheFlow() {
|
||||
constexpr const char *name = "UnifiedTextureCacheFlow";
|
||||
constexpr uintptr_t base = 0x0000000200600000ull;
|
||||
@@ -12741,160 +12840,6 @@ TestCase ScalarNotB64UpdatesScc() {
|
||||
O::S_ENDPGM}};
|
||||
}
|
||||
|
||||
TestCase ScalarMovB64PreservesRawSpecialData() {
|
||||
using O = ShaderOpcode;
|
||||
|
||||
std::vector<u32> code;
|
||||
AppendSMovLiteral(&code, 0, 0x09500000u);
|
||||
AppendSMovLiteral(&code, 1, 0x81234567u);
|
||||
code.push_back(EncodeSop1(0x04, 106, 0)); // s_mov_b64 vcc, s[0:1]
|
||||
code.push_back(EncodeSop1(0x04, 2, 106)); // s_mov_b64 s[2:3], vcc
|
||||
code.push_back(EncodeSop1(0x08, 4, 2)); // s_not_b64 s[4:5], s[2:3]
|
||||
code.push_back(EncodeSop2(0x0a, 6, InlineU32(1), InlineU32(0)));
|
||||
|
||||
AppendStoreSgprPair(&code, 2, 0);
|
||||
AppendStoreSgprPair(&code, 4, 2);
|
||||
AppendStoreSgpr(&code, 6, 4);
|
||||
|
||||
AppendSMovLiteral(&code, 8, 0x09500001u);
|
||||
AppendSMovLiteral(&code, 9, 0x81234567u);
|
||||
code.push_back(EncodeSop1(0x04, 126, 8)); // s_mov_b64 exec, s[8:9]
|
||||
code.push_back(EncodeSop1(0x04, 10, 126)); // s_mov_b64 s[10:11], exec
|
||||
code.push_back(EncodeSop1(0x08, 12, 10)); // s_not_b64 s[12:13], s[10:11]
|
||||
code.push_back(EncodeSop2(0x0a, 14, InlineU32(1), InlineU32(0)));
|
||||
|
||||
AppendStoreSgprPair(&code, 10, 5);
|
||||
AppendStoreSgprPair(&code, 12, 7);
|
||||
AppendStoreSgpr(&code, 14, 9);
|
||||
AppendEnd(&code);
|
||||
|
||||
return {"ScalarMovB64PreservesRawSpecialData",
|
||||
code,
|
||||
{},
|
||||
{0x09500000u, 0x81234567u, 0xf6afffffu, 0x7edcba98u, 1u,
|
||||
0x09500001u, 0x81234567u, 0xf6affffeu, 0x7edcba98u, 1u},
|
||||
{O::S_MOV_B32, O::S_MOV_B64, O::S_NOT_B64, O::S_CSELECT_B32,
|
||||
O::V_MOV_B32, O::BUFFER_STORE_DWORD, O::S_ENDPGM}};
|
||||
}
|
||||
|
||||
TestCase Scalar64RawSpecialOps() {
|
||||
using O = ShaderOpcode;
|
||||
|
||||
std::vector<u32> code;
|
||||
const auto capture_scc = [&](u32 dst) {
|
||||
code.push_back(EncodeSop2(0x0a, dst, InlineU32(1), InlineU32(0)));
|
||||
};
|
||||
|
||||
AppendSMovLiteral(&code, 0, 0x09500001u);
|
||||
AppendSMovLiteral(&code, 1, 0x81234567u);
|
||||
AppendSMovLiteral(&code, 2, 0xff00ff01u);
|
||||
AppendSMovLiteral(&code, 3, 0x0f0f0f0fu);
|
||||
code.push_back(EncodeSop1(0x04, 126, 0));
|
||||
code.push_back(EncodeSop2(0x0f, 106, 126, 2));
|
||||
code.push_back(EncodeSop1(0x04, 4, 106));
|
||||
capture_scc(6);
|
||||
code.push_back(EncodeSop1(0x08, 106, 106));
|
||||
code.push_back(EncodeSop1(0x04, 8, 106));
|
||||
capture_scc(10);
|
||||
|
||||
AppendSMovLiteral(&code, 12, 0x80000011u);
|
||||
AppendSMovLiteral(&code, 13, 0x80000001u);
|
||||
code.push_back(EncodeSop1(0x04, 106, 12));
|
||||
code.push_back(EncodeSop1(0x0a, 106, 106));
|
||||
code.push_back(EncodeSop1(0x04, 14, 106));
|
||||
capture_scc(16);
|
||||
|
||||
code.push_back(EncodeSop1(0x0a, 26, 193u));
|
||||
capture_scc(28);
|
||||
|
||||
code.push_back(EncodeSMovB32(18, InlineU32(1)));
|
||||
code.push_back(EncodeSMovB32(19, InlineU32(0)));
|
||||
code.push_back(EncodeSopc(0x06, InlineU32(1), InlineU32(1)));
|
||||
code.push_back(EncodeSop2(0x0b, 126, 0, 18));
|
||||
code.push_back(EncodeSop1(0x04, 20, 126));
|
||||
code.push_back(EncodeSop1(0x08, 106, 126));
|
||||
code.push_back(EncodeSop1(0x04, 22, 106));
|
||||
capture_scc(24);
|
||||
code.push_back(EncodeSop1(0x04, 126, 18));
|
||||
|
||||
AppendStoreSgprPair(&code, 4, 0);
|
||||
AppendStoreSgpr(&code, 6, 2);
|
||||
AppendStoreSgprPair(&code, 8, 3);
|
||||
AppendStoreSgpr(&code, 10, 5);
|
||||
AppendStoreSgprPair(&code, 14, 6);
|
||||
AppendStoreSgpr(&code, 16, 8);
|
||||
AppendStoreSgprPair(&code, 26, 9);
|
||||
AppendStoreSgpr(&code, 28, 11);
|
||||
AppendStoreSgprPair(&code, 20, 12);
|
||||
AppendStoreSgprPair(&code, 22, 14);
|
||||
AppendStoreSgpr(&code, 24, 16);
|
||||
AppendEnd(&code);
|
||||
|
||||
return {"Scalar64RawSpecialOps",
|
||||
code,
|
||||
{},
|
||||
{0x09000001u, 0x01030507u, 1, 0xf6fffffeu, 0xfefcfaf8u, 1,
|
||||
0xf00000ffu, 0xf000000fu, 1, 0xffffffffu, 0xffffffffu, 1,
|
||||
0x09500001u, 0x81234567u, 0xf6affffeu, 0x7edcba98u, 1},
|
||||
{O::S_MOV_B32, O::S_MOV_B64, O::S_AND_B64, O::S_NOT_B64,
|
||||
O::S_CSELECT_B32, O::S_WQM_B64, O::S_CMP_EQ_U32, O::S_CSELECT_B64,
|
||||
O::V_MOV_B32, O::BUFFER_STORE_DWORD, O::S_ENDPGM}};
|
||||
}
|
||||
|
||||
TestCase ScalarMovB32SpecialAliases() {
|
||||
using O = ShaderOpcode;
|
||||
|
||||
std::vector<u32> code;
|
||||
const auto capture_scc = [&](u32 dst) {
|
||||
code.push_back(EncodeSop2(0x0a, dst, InlineU32(1), InlineU32(0)));
|
||||
};
|
||||
|
||||
AppendSMovLiteral(&code, 0, 0x09500001u);
|
||||
AppendSMovLiteral(&code, 1, 0x81234567u);
|
||||
AppendSMovLiteral(&code, 2, 0xaaaaaaaau);
|
||||
AppendSMovLiteral(&code, 3, 0xbbbbbbbbu);
|
||||
code.push_back(EncodeSMovB32(4, InlineU32(1)));
|
||||
code.push_back(EncodeSMovB32(5, InlineU32(0)));
|
||||
code.push_back(EncodeSop1(0x04, 126, 0));
|
||||
code.push_back(EncodeSop1(0x04, 106, 2));
|
||||
code.push_back(EncodeSMovB32(107, 126));
|
||||
code.push_back(EncodeSop1(0x04, 6, 106));
|
||||
code.push_back(EncodeSop1(0x08, 8, 106));
|
||||
capture_scc(10);
|
||||
|
||||
AppendSMovLiteral(&code, 12, 0x13579bdfu);
|
||||
AppendSMovLiteral(&code, 13, 0x2468ace0u);
|
||||
code.push_back(EncodeSop1(0x04, 106, 12));
|
||||
code.push_back(EncodeSMovB32(126, 106));
|
||||
code.push_back(EncodeSop1(0x04, 14, 126));
|
||||
code.push_back(EncodeSop1(0x04, 126, 4));
|
||||
|
||||
code.push_back(EncodeVopc(0xc2, InlineU32(0), 0));
|
||||
code.push_back(EncodeSMovB32(106, 106));
|
||||
code.push_back(EncodeSop1(0x08, 16, 106));
|
||||
capture_scc(18);
|
||||
code.push_back(EncodeSop1(0x04, 20, 106));
|
||||
code.push_back(EncodeSMovB32(20, 20));
|
||||
code.push_back(EncodeSop1(0x08, 22, 20));
|
||||
capture_scc(24);
|
||||
|
||||
AppendStoreSgprPair(&code, 6, 0);
|
||||
AppendStoreSgprPair(&code, 8, 2);
|
||||
AppendStoreSgpr(&code, 10, 4);
|
||||
AppendStoreSgprPair(&code, 14, 5);
|
||||
AppendStoreSgpr(&code, 18, 7);
|
||||
AppendStoreSgpr(&code, 24, 8);
|
||||
AppendEnd(&code);
|
||||
|
||||
return {"ScalarMovB32SpecialAliases",
|
||||
code,
|
||||
{},
|
||||
{0xaaaaaaaau, 0x09500001u, 0x55555555u, 0xf6affffeu, 1, 0x13579bdfu,
|
||||
0x81234567u, 0, 0},
|
||||
{O::S_MOV_B32, O::S_MOV_B64, O::S_NOT_B64, O::S_CSELECT_B32,
|
||||
O::V_CMP_EQ_U32, O::V_MOV_B32, O::BUFFER_STORE_DWORD, O::S_ENDPGM}};
|
||||
}
|
||||
|
||||
TestCase ScalarQuadmaskB64() {
|
||||
using O = ShaderOpcode;
|
||||
|
||||
@@ -13023,7 +12968,8 @@ TestCase ScalarSaveExecOps() {
|
||||
return {"ScalarSaveExecOps",
|
||||
code,
|
||||
{},
|
||||
{1, 0, 1, 0, 0xffffffffu, 0xffffffffu, 1, 1, 0, 1, 0, 0, 0},
|
||||
// EXEC and saved EXEC values are invocation-local Booleans.
|
||||
{1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0},
|
||||
{O::S_MOV_B32, O::S_AND_SAVEEXEC_B64, O::S_ORN2_SAVEEXEC_B64,
|
||||
O::S_ANDN1_SAVEEXEC_B64, O::S_AND_SAVEEXEC_B32,
|
||||
O::S_ANDN1_SAVEEXEC_B32, O::S_MOV_B64, O::V_MOV_B32,
|
||||
@@ -13050,7 +12996,7 @@ TestCase ScalarOrn2SaveexecUsesSourceOrNotExec() {
|
||||
return {"ScalarOrn2SaveexecUsesSourceOrNotExec",
|
||||
code,
|
||||
{},
|
||||
{0x0000000cu, 0x80000000u, 0xfffffff3u, 0x7fffffffu, 1},
|
||||
{1, 0, 1, 0, 1},
|
||||
{O::S_MOV_B32, O::S_ORN2_SAVEEXEC_B64, O::S_MOV_B64, O::V_MOV_B32,
|
||||
O::BUFFER_STORE_DWORD, O::S_ENDPGM}};
|
||||
}
|
||||
@@ -15175,6 +15121,31 @@ TestCase VectorDppQuadPermuteReverse() {
|
||||
return test;
|
||||
}
|
||||
|
||||
TestCase VectorDppRowXmask() {
|
||||
using O = ShaderOpcode;
|
||||
|
||||
std::vector<u32> code;
|
||||
AppendVMovU32(&code, 1, 100);
|
||||
code.push_back(EncodeVop2(0x25, 2, 250, 1));
|
||||
code.push_back(EncodeVop2Dpp(0, 0x164));
|
||||
code.push_back(EncodeVop2(0x1a, 3, InlineU32(2), 0));
|
||||
AppendBufferStoreDword(&code, 2, 3);
|
||||
AppendEnd(&code);
|
||||
|
||||
TestCase test;
|
||||
test.name = "VectorDppRowXmask";
|
||||
test.code = code;
|
||||
test.expected = {104, 105, 106, 107, 100, 101, 102, 103};
|
||||
test.opcodes = {O::V_MOV_B32, O::V_ADD_NC_U32, O::V_LSHLREV_B32,
|
||||
O::BUFFER_STORE_DWORD, O::S_ENDPGM};
|
||||
test.compute_info.threads_num[0] = 8;
|
||||
test.compute_info.threads_num[1] = 1;
|
||||
test.compute_info.threads_num[2] = 1;
|
||||
test.compute_info.thread_ids_num = 1;
|
||||
test.has_compute_info = true;
|
||||
return test;
|
||||
}
|
||||
|
||||
TestCase VectorDppBankMaskPreservesDestination() {
|
||||
using O = ShaderOpcode;
|
||||
|
||||
@@ -16736,30 +16707,6 @@ TestCase ScalarMemoryLoadVariants() {
|
||||
O::BUFFER_STORE_DWORD, O::S_ENDPGM}};
|
||||
}
|
||||
|
||||
TestCase ScalarLoadUsesRawExecAddress() {
|
||||
using O = ShaderOpcode;
|
||||
|
||||
std::vector<u32> code;
|
||||
code.push_back(EncodeSMovB32(0, InlineU32(0)));
|
||||
code.push_back(EncodeSMovB32(1, InlineU32(0)));
|
||||
code.push_back(EncodeSMovB32(2, InlineU32(4)));
|
||||
code.push_back(EncodeSMovB32(3, InlineU32(0)));
|
||||
code.push_back(EncodeSop1(0x04, 126, 2));
|
||||
code.push_back(EncodeSmem0(0x00, 20, 63));
|
||||
code.push_back(EncodeSmem1(0));
|
||||
code.push_back(EncodeSMovB32(2, InlineU32(1)));
|
||||
code.push_back(EncodeSop1(0x04, 126, 2));
|
||||
AppendStoreSgpr(&code, 20, 0);
|
||||
AppendEnd(&code);
|
||||
|
||||
return {"ScalarLoadUsesRawExecAddress",
|
||||
code,
|
||||
{0x11111111u, 0x22222222u},
|
||||
{0x22222222u, 0x22222222u},
|
||||
{O::S_MOV_B32, O::S_MOV_B64, O::S_LOAD_DWORD, O::V_MOV_B32,
|
||||
O::BUFFER_STORE_DWORD, O::S_ENDPGM}};
|
||||
}
|
||||
|
||||
TestCase ScalarLoadSignedImmediateOffsetAddsSoffset() {
|
||||
using O = ShaderOpcode;
|
||||
|
||||
@@ -21203,9 +21150,6 @@ std::vector<TestCase> MakeCases() {
|
||||
AddCase(ScalarCompareOps);
|
||||
AddCase(ScalarShiftAddAndMaskOps);
|
||||
AddCase(ScalarNotB64UpdatesScc);
|
||||
AddCase(ScalarMovB64PreservesRawSpecialData);
|
||||
AddCase(Scalar64RawSpecialOps);
|
||||
AddCase(ScalarMovB32SpecialAliases);
|
||||
AddCase(ScalarQuadmaskB64);
|
||||
AddCase(ScalarFlbitI32B64Gpu);
|
||||
AddCase(ScalarFlbitI32B32Gpu);
|
||||
@@ -21275,6 +21219,7 @@ std::vector<TestCase> MakeCases() {
|
||||
AddCase(VectorPermlane16FetchInactiveZero);
|
||||
AddCase(VectorPermlane16FetchInactiveFi);
|
||||
AddCase(VectorDppQuadPermuteReverse);
|
||||
AddCase(VectorDppRowXmask);
|
||||
AddCase(VectorDppBankMaskPreservesDestination);
|
||||
AddCase(VectorDppBoundsControlZeroPreservesDestination);
|
||||
AddCase(Vop3LdexpSourceModifier);
|
||||
@@ -21322,7 +21267,6 @@ std::vector<TestCase> MakeCases() {
|
||||
AddCase(BranchVccnzUsesInvocationMask);
|
||||
AddCase(BranchVccnzUsesCarryProducedInvocationMask);
|
||||
AddCase(ScalarMemoryLoadVariants);
|
||||
AddCase(ScalarLoadUsesRawExecAddress);
|
||||
AddCase(ScalarLoadSignedImmediateOffsetAddsSoffset);
|
||||
AddCase(ScalarLoadAlignsComponentsAndMasksAddress);
|
||||
AddCase(BufferLoadStore);
|
||||
@@ -24556,10 +24500,10 @@ void CheckPm4NativeTargetGeometryRegisters(RenderContext &renderer) {
|
||||
|
||||
// Removed GCN shader resource/checksum/queue registers. Numeric offsets keep
|
||||
// this check independent of the deleted legacy names.
|
||||
constexpr std::array<uint32_t, 22> legacy_shader_slots{
|
||||
0x000u, 0x001u, 0x002u, 0x003u, 0x030u, 0x081u, 0x0b0u, 0x0bcu,
|
||||
0x100u, 0x101u, 0x130u, 0x14au, 0x14bu, 0x20eu, 0x20fu, 0x210u,
|
||||
0x211u, 0x216u, 0x217u, 0x219u, 0x21au, 0x27du,
|
||||
constexpr std::array<uint32_t, 19> legacy_shader_slots{
|
||||
0x000u, 0x001u, 0x002u, 0x003u, 0x030u, 0x0b0u, 0x0bcu, 0x130u,
|
||||
0x14au, 0x14bu, 0x20eu, 0x20fu, 0x210u, 0x211u, 0x216u, 0x217u,
|
||||
0x219u, 0x21au, 0x27du,
|
||||
};
|
||||
for (const auto offset : legacy_shader_slots) {
|
||||
legacy_slots_are_unhandled &= g_hw_sh_func[offset] == nullptr &&
|
||||
@@ -24570,12 +24514,6 @@ void CheckPm4NativeTargetGeometryRegisters(RenderContext &renderer) {
|
||||
g_hw_sh_indirect_func[offset] == nullptr;
|
||||
}
|
||||
|
||||
constexpr std::array<uint32_t, 1> legacy_uconfig_slots{0x0260u};
|
||||
for (const auto offset : legacy_uconfig_slots) {
|
||||
legacy_slots_are_unhandled &= g_hw_uc_func[offset] == nullptr &&
|
||||
g_hw_uc_indirect_func[offset] == nullptr;
|
||||
}
|
||||
|
||||
std::array<uint32_t, 3> index_size_packet{
|
||||
KYTY_PM4(3, Pm4::IT_SET_UCONFIG_REG_INDEX, Pm4::R_ZERO),
|
||||
0x20000000u | Pm4::VGT_INDEX_TYPE,
|
||||
@@ -24601,6 +24539,54 @@ void CheckPm4NativeTargetGeometryRegisters(RenderContext &renderer) {
|
||||
std::printf("[host] %-32s ok\n", "Pm4NativeTargetGeometry");
|
||||
}
|
||||
|
||||
void CheckPm4PrivateAgcShaderRegisters(RenderContext &renderer) {
|
||||
GraphicsInitJmpTables();
|
||||
CommandProcessor processor(renderer, 0);
|
||||
std::array<uint32_t, 6> registers{
|
||||
Pm4::SPI_SHADER_PGM_RSRC4_GS, 0x0badc0deu,
|
||||
Pm4::SPI_SHADER_PGM_CHKSUM_HS, 0x12345678u,
|
||||
Pm4::SPI_SHADER_PGM_RSRC4_HS, 0x87654321u,
|
||||
};
|
||||
const auto address = reinterpret_cast<uint64_t>(registers.data());
|
||||
std::array<uint32_t, 5> command{
|
||||
KYTY_PM4(5, Pm4::IT_SET_SH_REG_INDIRECT, Pm4::R_ZERO),
|
||||
static_cast<uint32_t>(address), static_cast<uint32_t>(address >> 32u),
|
||||
0x80000000u, 3u,
|
||||
};
|
||||
Pm4Execution execution;
|
||||
const bool handlers_present =
|
||||
g_hw_sh_indirect_func[Pm4::SPI_SHADER_PGM_RSRC4_GS] != nullptr &&
|
||||
g_hw_sh_indirect_func[Pm4::SPI_SHADER_PGM_CHKSUM_HS] != nullptr &&
|
||||
g_hw_sh_indirect_func[Pm4::SPI_SHADER_PGM_RSRC4_HS] != nullptr;
|
||||
Require("Pm4PrivateAgcShaderRegisters", "private shader register stream",
|
||||
handlers_present &&
|
||||
processor.Process(execution, command) == Pm4ProcessResult::Complete,
|
||||
"private AGC shader registers were rejected by SET_SH_REG_INDIRECT");
|
||||
std::printf("[host] %-32s ok\n", "Pm4PrivateAgcShaderRegisters");
|
||||
}
|
||||
|
||||
void CheckPm4PrivateAgcUconfigRegisters(RenderContext &renderer) {
|
||||
GraphicsInitJmpTables();
|
||||
CommandProcessor processor(renderer, 0);
|
||||
std::array<uint32_t, 2> registers{
|
||||
Pm4::UC_PARAMETER_OVERSUBSCRIPTION, 0x12345678u,
|
||||
};
|
||||
const auto address = reinterpret_cast<uint64_t>(registers.data());
|
||||
std::array<uint32_t, 5> command{
|
||||
KYTY_PM4(5, Pm4::IT_SET_UCONFIG_REG_INDIRECT, Pm4::R_ZERO),
|
||||
static_cast<uint32_t>(address), static_cast<uint32_t>(address >> 32u),
|
||||
0x80000000u, 1u,
|
||||
};
|
||||
Pm4Execution execution;
|
||||
const bool handler_present =
|
||||
g_hw_uc_indirect_func[Pm4::UC_PARAMETER_OVERSUBSCRIPTION] != nullptr;
|
||||
Require("Pm4PrivateAgcUconfigRegisters", "private UCONFIG register stream",
|
||||
handler_present &&
|
||||
processor.Process(execution, command) == Pm4ProcessResult::Complete,
|
||||
"private AGC UCONFIG register was rejected by SET_UCONFIG_REG_INDIRECT");
|
||||
std::printf("[host] %-32s ok\n", "Pm4PrivateAgcUconfigRegisters");
|
||||
}
|
||||
|
||||
void CheckPm4DirectShaderRegisterFallback(RenderContext &renderer) {
|
||||
GraphicsInitJmpTables();
|
||||
CommandProcessor processor(renderer, 0);
|
||||
@@ -24763,6 +24749,54 @@ void CheckPm4PolygonOffsetRegisters(RenderContext &renderer) {
|
||||
std::printf("[host] %-32s ok\n", "Pm4PolygonOffset");
|
||||
}
|
||||
|
||||
void CheckPm4DepthControlHighBits(RenderContext &renderer) {
|
||||
GraphicsInitJmpTables();
|
||||
CommandProcessor processor(renderer, 0);
|
||||
|
||||
std::array<uint32_t, 3> direct{
|
||||
KYTY_PM4(3, Pm4::IT_SET_CONTEXT_REG, Pm4::R_ZERO),
|
||||
Pm4::DB_DEPTH_CONTROL,
|
||||
0x80000072u,
|
||||
};
|
||||
Pm4Execution direct_execution;
|
||||
const bool direct_complete =
|
||||
processor.Process(direct_execution, direct) == Pm4ProcessResult::Complete;
|
||||
const auto &direct_control = processor.GetCtx().GetDepthControl();
|
||||
const bool direct_decoded =
|
||||
!direct_control.stencil_enable && direct_control.z_enable &&
|
||||
!direct_control.z_write_enable && !direct_control.depth_bounds_enable &&
|
||||
direct_control.zfunc == 7u && !direct_control.backface_enable &&
|
||||
direct_control.stencilfunc == 0u && direct_control.stencilfunc_bf == 0u;
|
||||
|
||||
std::array<uint32_t, 2> registers{
|
||||
Pm4::DB_DEPTH_CONTROL,
|
||||
0x4070078du,
|
||||
};
|
||||
const auto address = reinterpret_cast<uint64_t>(registers.data());
|
||||
std::array<uint32_t, 5> indirect{
|
||||
KYTY_PM4(5, Pm4::IT_SET_CONTEXT_REG_INDIRECT, Pm4::R_ZERO),
|
||||
static_cast<uint32_t>(address), static_cast<uint32_t>(address >> 32u),
|
||||
0x80000000u, 1u,
|
||||
};
|
||||
Pm4Execution indirect_execution;
|
||||
const bool indirect_complete =
|
||||
processor.Process(indirect_execution, indirect) ==
|
||||
Pm4ProcessResult::Complete;
|
||||
const auto &indirect_control = processor.GetCtx().GetDepthControl();
|
||||
const bool indirect_decoded =
|
||||
indirect_control.stencil_enable && !indirect_control.z_enable &&
|
||||
indirect_control.z_write_enable && indirect_control.depth_bounds_enable &&
|
||||
indirect_control.zfunc == 0u && indirect_control.backface_enable &&
|
||||
indirect_control.stencilfunc == 7u &&
|
||||
indirect_control.stencilfunc_bf == 7u;
|
||||
|
||||
Require("Pm4DepthControlHighBits", "preserved high bits",
|
||||
direct_complete && direct_decoded && indirect_complete &&
|
||||
indirect_decoded,
|
||||
"DB_DEPTH_CONTROL high bits rejected or changed decoded PS5 state");
|
||||
std::printf("[host] %-32s ok\n", "Pm4DepthControlHighBits");
|
||||
}
|
||||
|
||||
struct AgcCommandBufferLayout {
|
||||
using Callback = KYTY_SYSV_ABI bool (*)(Gen5::CommandBuffer *, uint32_t,
|
||||
void *);
|
||||
@@ -25361,8 +25395,11 @@ int main(int argc, char **argv) {
|
||||
if (argc == 2 && std::strcmp(argv[1], "--context-state-only") == 0) {
|
||||
VulkanHarness vulkan;
|
||||
CheckPm4NativeTargetGeometryRegisters(vulkan.RuntimeRenderer());
|
||||
CheckPm4PrivateAgcShaderRegisters(vulkan.RuntimeRenderer());
|
||||
CheckPm4PrivateAgcUconfigRegisters(vulkan.RuntimeRenderer());
|
||||
CheckPm4BlendColorRegisterRanges(vulkan.RuntimeRenderer());
|
||||
CheckPm4PolygonOffsetRegisters(vulkan.RuntimeRenderer());
|
||||
CheckPm4DepthControlHighBits(vulkan.RuntimeRenderer());
|
||||
CheckPm4ContextStateOperations(vulkan.RuntimeRenderer());
|
||||
return 0;
|
||||
}
|
||||
@@ -25399,6 +25436,11 @@ int main(int argc, char **argv) {
|
||||
vulkan.CheckUnifiedTextureCacheFlow();
|
||||
return 0;
|
||||
}
|
||||
if (argc == 2 && std::strcmp(argv[1], "--compute-meta-clear-only") == 0) {
|
||||
VulkanHarness vulkan;
|
||||
vulkan.CheckComputeMetaClearClassification();
|
||||
return 0;
|
||||
}
|
||||
if (argc == 2 && std::strcmp(argv[1], "--layered-image-only") == 0) {
|
||||
VulkanHarness vulkan;
|
||||
vulkan.CheckUnifiedImageViewCache();
|
||||
@@ -25541,10 +25583,13 @@ int main(int argc, char **argv) {
|
||||
CheckPm4SyntheticOcclusionCounterDump(vulkan.RuntimeRenderer());
|
||||
CheckPm4StencilInfoValueLane(vulkan.RuntimeRenderer());
|
||||
CheckPm4NativeTargetGeometryRegisters(vulkan.RuntimeRenderer());
|
||||
CheckPm4PrivateAgcShaderRegisters(vulkan.RuntimeRenderer());
|
||||
CheckPm4PrivateAgcUconfigRegisters(vulkan.RuntimeRenderer());
|
||||
CheckPm4DirectShaderRegisterFallback(vulkan.RuntimeRenderer());
|
||||
CheckPm4GuardBandRegisterRanges(vulkan.RuntimeRenderer());
|
||||
CheckPm4BlendColorRegisterRanges(vulkan.RuntimeRenderer());
|
||||
CheckPm4PolygonOffsetRegisters(vulkan.RuntimeRenderer());
|
||||
CheckPm4DepthControlHighBits(vulkan.RuntimeRenderer());
|
||||
CheckAgcWaitPackets(vulkan.RuntimeRenderer());
|
||||
CheckAgcDrawIndirectMultiPacket(vulkan.RuntimeRenderer());
|
||||
CheckPm4ContextStateOperations(vulkan.RuntimeRenderer());
|
||||
|
||||
+51
-17
@@ -8811,6 +8811,45 @@ void TestNewShaderRecompilerExpVertexOutputs() {
|
||||
CheckSpirvBinaryValidates(result.spirv);
|
||||
}
|
||||
|
||||
void TestNewShaderRecompilerClipDisabledPosition() {
|
||||
const uint32_t shader[] = {
|
||||
EncodeExp0(0x0c, 0xf), EncodeExp1(0, 1, 2, 3), 0xbf810000u,
|
||||
};
|
||||
const auto compile = [&](const ShaderVertexInputInfo &vertex) {
|
||||
auto options = MakeCompileOptions(ShaderType::Vertex);
|
||||
options.input_info.vertex = &vertex;
|
||||
return ShaderRecompiler::Recompile(shader, options);
|
||||
};
|
||||
|
||||
ShaderVertexInputInfo regular{};
|
||||
auto clipped = regular;
|
||||
clipped.clip_space = {
|
||||
.scale = {640.0f, 360.0f},
|
||||
.offset = {640.0f, 360.0f},
|
||||
.half_extent = {8192.0f, 8192.0f},
|
||||
.enabled = true,
|
||||
};
|
||||
const auto regular_result = compile(regular);
|
||||
const auto clipped_result = compile(clipped);
|
||||
CheckSpirvBinaryValidates(clipped_result.spirv);
|
||||
Check(SpirvInstructionOpcodeCount(regular_result.spirv, 136u) == 0u &&
|
||||
SpirvInstructionOpcodeCount(clipped_result.spirv, 133u) == 2u &&
|
||||
SpirvInstructionOpcodeCount(clipped_result.spirv, 129u) == 2u &&
|
||||
SpirvInstructionOpcodeCount(clipped_result.spirv, 136u) == 2u &&
|
||||
SpirvInstructionOpcodeCount(clipped_result.spirv, 131u) == 2u,
|
||||
"clip-disabled position export did not convert both screen coordinates to NDC");
|
||||
Check(MakeStageStaticKey(regular) != MakeStageStaticKey(clipped),
|
||||
"clip-disabled vertex shader shared the regular shader cache key");
|
||||
auto disabled = clipped;
|
||||
disabled.clip_space.enabled = false;
|
||||
Check(MakeStageStaticKey(regular) == MakeStageStaticKey(disabled),
|
||||
"disabled clip-space payload affected the shader cache key");
|
||||
auto shifted = clipped;
|
||||
shifted.clip_space.offset[0] += 1.0f;
|
||||
Check(MakeStageStaticKey(clipped) != MakeStageStaticKey(shifted),
|
||||
"clip-disabled viewport transform is absent from the shader cache key");
|
||||
}
|
||||
|
||||
void TestNewShaderRecompilerAuxPositionExports() {
|
||||
const auto compile = [](std::span<const uint32_t> shader, uint32_t control) {
|
||||
ShaderVertexInputInfo vertex{};
|
||||
@@ -9059,12 +9098,10 @@ void TestTypedEntryStateIsMinimal() {
|
||||
translate_options);
|
||||
|
||||
uint32_t set_exec = 0;
|
||||
uint32_t set_exec_mask_tag = 0;
|
||||
uint32_t set_exec_lo = 0;
|
||||
uint32_t set_exec_hi = 0;
|
||||
uint32_t ballots = 0;
|
||||
IR::Value exec;
|
||||
IR::Value exec_mask_tag;
|
||||
IR::Value exec_lo;
|
||||
IR::Value exec_hi;
|
||||
for (const auto *block : values.blocks) {
|
||||
@@ -9077,10 +9114,6 @@ void TestTypedEntryStateIsMinimal() {
|
||||
set_exec++;
|
||||
exec = inst.Arg(0).Resolve();
|
||||
break;
|
||||
case IR::ValueOpcode::SetExecMaskTag:
|
||||
set_exec_mask_tag++;
|
||||
exec_mask_tag = inst.Arg(0).Resolve();
|
||||
break;
|
||||
case IR::ValueOpcode::SetExecLo:
|
||||
set_exec_lo++;
|
||||
exec_lo = inst.Arg(0).Resolve();
|
||||
@@ -9095,7 +9128,6 @@ void TestTypedEntryStateIsMinimal() {
|
||||
case IR::ValueOpcode::SetVectorRegister:
|
||||
case IR::ValueOpcode::SetScc:
|
||||
case IR::ValueOpcode::SetVcc:
|
||||
case IR::ValueOpcode::SetVccMaskValidTag:
|
||||
case IR::ValueOpcode::SetVccLo:
|
||||
case IR::ValueOpcode::SetVccHi:
|
||||
case IR::ValueOpcode::SetM0:
|
||||
@@ -9106,9 +9138,8 @@ void TestTypedEntryStateIsMinimal() {
|
||||
}
|
||||
}
|
||||
}
|
||||
Check(set_exec == 1u && set_exec_mask_tag == 1u && set_exec_lo == 1u &&
|
||||
set_exec_hi == 1u && ballots == 0u && exec.IsImmediate() &&
|
||||
exec.U1() && exec_mask_tag.IsImmediate() && exec_mask_tag.U1() &&
|
||||
Check(set_exec == 1u && set_exec_lo == 1u && set_exec_hi == 1u &&
|
||||
ballots == 0u && exec.IsImmediate() && exec.U1() &&
|
||||
exec_lo.IsImmediate() && exec_lo.U32() == 1u &&
|
||||
exec_hi.IsImmediate() && exec_hi.U32() == 0u,
|
||||
"typed entry is not the local {1,0} invocation mask");
|
||||
@@ -9937,16 +9968,18 @@ void TestNewShaderRecompilerPerInvocationMasksWithoutMirrors() {
|
||||
result = ShaderRecompiler::Recompile(wqm_shader, options);
|
||||
CheckSpirvBinaryValidates(result.spirv);
|
||||
const auto wqm_source = DisassembleSpirvBinary(result.spirv);
|
||||
Check(!Common::ContainsStr(wqm_source, "OpGroupNonUniformBallot"),
|
||||
"raw scalar WQM reconstructed its source from invocation provenance");
|
||||
Check(Common::ContainsStr(wqm_source, "OpCapability GroupNonUniformBallot") &&
|
||||
Common::ContainsStr(wqm_source, "OpGroupNonUniformBallot"),
|
||||
"per-invocation scalar WQM omitted its subgroup ballot capability");
|
||||
Check(SpirvInstructionOpcodeCount(result.spirv, 132u) == 2u,
|
||||
"wave64 WQM did not compact exactly two ballot words");
|
||||
|
||||
auto wave32_options = options;
|
||||
wave32_options.wave_size = 32u;
|
||||
result = ShaderRecompiler::Recompile(wqm_shader, wave32_options);
|
||||
CheckSpirvBinaryValidates(result.spirv);
|
||||
Check(!Common::ContainsStr(DisassembleSpirvBinary(result.spirv),
|
||||
"OpGroupNonUniformBallot"),
|
||||
"wave32 raw scalar WQM reconstructed invocation provenance");
|
||||
Check(SpirvInstructionOpcodeCount(result.spirv, 132u) == 1u,
|
||||
"wave32 WQM retained the unused high ballot-word expansion");
|
||||
|
||||
const uint32_t cross_lane_shader[] = {
|
||||
EncodeSop2(0x25, 126, 132, 128), // s_bfm_b64 exec, 4, 0
|
||||
@@ -11868,8 +11901,8 @@ void TestNewShaderRecompilerSpirvSizeBaselines() {
|
||||
.conditional_branches = 1,
|
||||
.ballots = 1},
|
||||
ShaderType::Vertex);
|
||||
Check(Common::ContainsStr(wqm_result.ir_dump, "WqmU64"),
|
||||
"WQM size fixture no longer reaches raw WqmU64 IR");
|
||||
Check(Common::ContainsStr(wqm_result.ir_dump, "WqmMask"),
|
||||
"WQM size fixture no longer reaches per-invocation WqmMask IR");
|
||||
|
||||
const uint32_t dispatcher[] = {
|
||||
EncodeSopp(0x05, 2), // entry -> B, fallthrough A
|
||||
@@ -11914,6 +11947,7 @@ int main() {
|
||||
TestNewShaderRecompilerSpirvSizeBaselines();
|
||||
TestDemandDrivenSpirvDeclarations();
|
||||
TestNewShaderRecompilerSMovB32();
|
||||
TestNewShaderRecompilerClipDisabledPosition();
|
||||
TestNewShaderRecompilerAuxPositionExports();
|
||||
TestNewShaderRecompilerNativeWideScalarMemoryIr();
|
||||
TestNewShaderRecompilerNativeWideBufferIr();
|
||||
|
||||
Reference in New Issue
Block a user