mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-23 20:36:58 +02:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e9425e101d | |||
| 04b404f3c9 | |||
| 80225015c5 | |||
| 0c4dfd565e | |||
| 0c8d7a1e49 | |||
| a2150c70bb | |||
| 160cf5352c | |||
| 3b6b3c2040 | |||
| 63dd3917e2 | |||
| 2333c235f1 |
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -59,16 +59,8 @@ namespace {
|
||||
if (HasFormatFeature(properties, vk::FormatFeatureFlagBits::eColorAttachment)) {
|
||||
usage |= vk::ImageUsageFlagBits::eColorAttachment;
|
||||
}
|
||||
if (info.samples == 1 &&
|
||||
HasFormatFeature(properties, vk::FormatFeatureFlagBits::eStorageImage)) {
|
||||
if (info.samples == 1) {
|
||||
usage |= vk::ImageUsageFlagBits::eStorage;
|
||||
} else if (info.samples == 1) {
|
||||
const auto compatible = SrgbStorageViewFormat(info.pixel_format);
|
||||
if (compatible != vk::Format::eUndefined &&
|
||||
HasFormatFeature(graphics.GetFormatProperties(compatible),
|
||||
vk::FormatFeatureFlagBits::eStorageImage)) {
|
||||
usage |= vk::ImageUsageFlagBits::eStorage;
|
||||
}
|
||||
}
|
||||
return usage;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -814,6 +814,7 @@ static void WindowCreate(WindowContext& context) {
|
||||
int width = static_cast<int>(context.graphic_ctx.screen_width);
|
||||
int height = static_cast<int>(context.graphic_ctx.screen_height);
|
||||
|
||||
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, "1");
|
||||
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS
|
||||
SDL_SetHint(SDL_HINT_WINDOWS_DPI_SCALING, "0");
|
||||
#endif
|
||||
|
||||
@@ -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)};
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,8 @@ constexpr OpcodeMap SOP2_OPCODE_LIST[] = {
|
||||
{0x22u, Opcode::S_ASHR_I32}, {0x24u, Opcode::S_BFM_B32},
|
||||
{0x25u, Opcode::S_BFM_B64}, {0x26u, Opcode::S_MUL_I32},
|
||||
{0x27u, Opcode::S_BFE_U32}, {0x28u, Opcode::S_BFE_I32},
|
||||
{0x29u, Opcode::S_BFE_U64}, {0x2eu, Opcode::S_LSHL1_ADD_U32},
|
||||
{0x29u, Opcode::S_BFE_U64}, {0x2cu, Opcode::S_ABSDIFF_I32},
|
||||
{0x2eu, Opcode::S_LSHL1_ADD_U32},
|
||||
{0x2fu, Opcode::S_LSHL2_ADD_U32}, {0x30u, Opcode::S_LSHL3_ADD_U32},
|
||||
{0x31u, Opcode::S_LSHL4_ADD_U32}, {0x32u, Opcode::S_PACK_LL_B32_B16},
|
||||
{0x33u, Opcode::S_PACK_LH_B32_B16}, {0x34u, Opcode::S_PACK_HH_B32_B16},
|
||||
@@ -48,7 +49,9 @@ constexpr OpcodeMap SOP1_OPCODE_LIST[] = {
|
||||
{0x15u, Opcode::S_FLBIT_I32_B32},
|
||||
{0x16u, Opcode::S_FLBIT_I32_B64},
|
||||
{0x1bu, Opcode::S_BITSET0_B32},
|
||||
{0x1cu, Opcode::S_BITSET0_B64},
|
||||
{0x1du, Opcode::S_BITSET1_B32},
|
||||
{0x1eu, Opcode::S_BITSET1_B64},
|
||||
{0x1fu, Opcode::S_GETPC_B64},
|
||||
{0x20u, Opcode::S_SETPC_B64},
|
||||
{0x24u, Opcode::S_AND_SAVEEXEC_B64},
|
||||
@@ -93,6 +96,7 @@ constexpr OpcodeMap SOPP_OPCODE_LIST[] = {
|
||||
{0x0au, Opcode::S_BARRIER},
|
||||
{0x0cu, Opcode::S_WAITCNT},
|
||||
{0x0eu, Opcode::S_SLEEP},
|
||||
{0x0fu, Opcode::S_SETPRIO},
|
||||
{0x10u, Opcode::S_SENDMSG},
|
||||
{0x12u, Opcode::S_TRAP},
|
||||
{0x16u, Opcode::S_TTRACEDATA},
|
||||
@@ -276,6 +280,7 @@ void DecodeSopp(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index
|
||||
: static_cast<int32_t>(static_cast<int16_t>(simm));
|
||||
inst.src_count = (inst.opcode == Opcode::S_NOP || inst.opcode == Opcode::S_WAITCNT ||
|
||||
inst.opcode == Opcode::S_WAITCNT_DEPCTR || inst.opcode == Opcode::S_SLEEP ||
|
||||
inst.opcode == Opcode::S_SETPRIO ||
|
||||
inst.opcode == Opcode::S_SENDMSG || inst.opcode == Opcode::S_TRAP ||
|
||||
inst.opcode == Opcode::S_TTRACEDATA || inst.opcode == Opcode::S_INST_PREFETCH)
|
||||
? 1
|
||||
|
||||
@@ -479,6 +479,8 @@ std::string InstructionToString(const Instruction& inst) {
|
||||
case Opcode::S_FLBIT_I32_B32:
|
||||
case Opcode::S_FF1_I32_B32:
|
||||
case Opcode::S_FF1_I32_B64:
|
||||
case Opcode::S_BITSET0_B64:
|
||||
case Opcode::S_BITSET1_B64:
|
||||
case Opcode::S_NOT_B64:
|
||||
case Opcode::S_WQM_B64:
|
||||
case Opcode::S_QUADMASK_B64:
|
||||
@@ -505,6 +507,7 @@ std::string InstructionToString(const Instruction& inst) {
|
||||
case Opcode::S_WAITCNT:
|
||||
case Opcode::S_WAITCNT_DEPCTR:
|
||||
case Opcode::S_SLEEP:
|
||||
case Opcode::S_SETPRIO:
|
||||
case Opcode::S_TRAP:
|
||||
case Opcode::S_SENDMSG:
|
||||
case Opcode::S_TTRACEDATA:
|
||||
|
||||
@@ -40,6 +40,7 @@ enum class Opcode {
|
||||
S_MOV_B64,
|
||||
S_MOVK_I32,
|
||||
S_ABS_I32,
|
||||
S_ABSDIFF_I32,
|
||||
S_BREV_B32,
|
||||
S_BCNT1_I32_B32,
|
||||
S_BCNT1_I32_B64,
|
||||
@@ -69,6 +70,8 @@ enum class Opcode {
|
||||
S_BITCMP1_B32,
|
||||
S_BITSET0_B32,
|
||||
S_BITSET1_B32,
|
||||
S_BITSET0_B64,
|
||||
S_BITSET1_B64,
|
||||
S_MIN_I32,
|
||||
S_MAX_I32,
|
||||
S_MIN_U32,
|
||||
@@ -108,6 +111,7 @@ enum class Opcode {
|
||||
S_BFM_B64,
|
||||
S_CSELECT_B32,
|
||||
S_CSELECT_B64,
|
||||
S_SETPRIO,
|
||||
S_PACK_LL_B32_B16,
|
||||
S_PACK_LH_B32_B16,
|
||||
S_PACK_HH_B32_B16,
|
||||
@@ -282,6 +286,7 @@ enum class Opcode {
|
||||
V_MAD_MIXHI_F16,
|
||||
V_ADD_NC_U32,
|
||||
V_ADDC_U32,
|
||||
V_SUB_CO_CI_U32,
|
||||
V_SUBREV_CO_CI_U32,
|
||||
V_SUB_NC_U32,
|
||||
V_SUBREV_NC_U32,
|
||||
|
||||
@@ -61,6 +61,7 @@ constexpr Vop2OpcodeInfo VOP2_OPCODE_LIST[] = {
|
||||
{0x24u, Opcode::V_MBCNT_HI_U32_B32},
|
||||
{0x25u, Opcode::V_ADD_NC_U32, Vop2SdwaProfile::IntegerPartialDestination},
|
||||
{0x28u, Opcode::V_ADDC_U32, Vop2SdwaProfile::IntegerFullDestination},
|
||||
{0x29u, Opcode::V_SUB_CO_CI_U32},
|
||||
{0x2au, Opcode::V_SUBREV_CO_CI_U32},
|
||||
{0x26u, Opcode::V_SUB_NC_U32, Vop2SdwaProfile::IntegerPartialDestination},
|
||||
{0x27u, Opcode::V_SUBREV_NC_U32, Vop2SdwaProfile::IntegerFullDestination},
|
||||
@@ -1033,6 +1034,7 @@ void FinalizeVop2Instruction(std::span<const uint32_t> code, uint32_t word_index
|
||||
inst.src_count = 3;
|
||||
break;
|
||||
case Opcode::V_ADDC_U32:
|
||||
case Opcode::V_SUB_CO_CI_U32:
|
||||
case Opcode::V_SUBREV_CO_CI_U32:
|
||||
inst.dst2.kind = OperandKind::VccLo;
|
||||
inst.src2.kind = OperandKind::VccLo;
|
||||
@@ -1643,6 +1645,7 @@ void DecodeVop3(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index
|
||||
SetRawWords(inst, code, word_index, 2);
|
||||
|
||||
const bool carry_in_out = (inst.opcode == Opcode::V_ADDC_U32 && opcode == 0x128u) ||
|
||||
(inst.opcode == Opcode::V_SUB_CO_CI_U32 && opcode == 0x129u) ||
|
||||
(inst.opcode == Opcode::V_SUBREV_CO_CI_U32 && opcode == 0x12au);
|
||||
const bool vop3b_carry_out = IsVop3BCarryOutOpcode(inst.opcode);
|
||||
const bool vop3b_mad_u64 = IsVop3BMadU64Opcode(inst.opcode);
|
||||
|
||||
@@ -76,9 +76,9 @@ void Translator::SUB_U32(const Decoder::Instruction& inst, bool vector, bool rev
|
||||
}
|
||||
}
|
||||
|
||||
void Translator::SUBB_U32(const Decoder::Instruction& inst, bool vector) {
|
||||
const auto lhs = ReadU32(vector ? inst.src1 : inst.src0);
|
||||
const auto rhs = ReadU32(vector ? inst.src0 : inst.src1);
|
||||
void Translator::SUBB_U32(const Decoder::Instruction& inst, bool vector, bool reverse) {
|
||||
const auto lhs = ReadU32(reverse ? inst.src1 : inst.src0);
|
||||
const auto rhs = ReadU32(reverse ? inst.src0 : inst.src1);
|
||||
const auto borrow_in = vector ? ConditionBit(inst.src2)
|
||||
: ConditionBit(ConditionOperand(Decoder::OperandKind::Scc));
|
||||
const auto partial = ir.ISub(lhs, rhs);
|
||||
@@ -94,6 +94,13 @@ void Translator::SUBB_U32(const Decoder::Instruction& inst, bool vector) {
|
||||
}
|
||||
}
|
||||
|
||||
void Translator::S_ABSDIFF_I32(const Decoder::Instruction& inst) {
|
||||
const auto difference = ir.ISub(ReadU32(inst.src0), ReadU32(inst.src1));
|
||||
const auto result = IR::U32(ir.Emit(IR::ValueOpcode::IAbs32, {difference}));
|
||||
WriteOperand(DestinationOperand(inst), result);
|
||||
ir.SetScc(ir.INotEqual(result, IR::U32(IR::Value(0u))));
|
||||
}
|
||||
|
||||
void Translator::S_ADD_SUB_I32(const Decoder::Instruction& inst, bool subtract) {
|
||||
const auto lhs = ReadU32(inst.src0);
|
||||
const auto rhs = ReadU32(inst.src1);
|
||||
|
||||
@@ -312,6 +312,22 @@ bool Translator::S_BITSET_B32(const Decoder::Instruction& inst, bool set) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Translator::S_BITSET_B64(const Decoder::Instruction& inst, bool set) {
|
||||
const auto offset = ir.BitwiseAnd(ReadU32(inst.src0), IR::U32(IR::Value(63u)));
|
||||
const auto word_bit = ir.BitwiseAnd(offset, IR::U32(IR::Value(31u)));
|
||||
const auto bit = ir.ShiftLeftLogical(IR::U32(IR::Value(1u)), word_bit);
|
||||
const auto old = ReadU32Pair(inst.dst);
|
||||
const auto low_value = set ? ir.BitwiseOr(old[0], bit)
|
||||
: ir.BitwiseAnd(old[0], ir.BitwiseNot(bit));
|
||||
const auto high_value = set ? ir.BitwiseOr(old[1], bit)
|
||||
: ir.BitwiseAnd(old[1], ir.BitwiseNot(bit));
|
||||
const auto high = IR::U1(ir.Emit(IR::ValueOpcode::UGreaterThanEqual32,
|
||||
{offset, IR::Value(32u)}));
|
||||
WriteU32Pair(inst.dst,
|
||||
{ir.Select(high, old[0], low_value), ir.Select(high, high_value, old[1])});
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Translator::V_BCNT_U32_B32(const Decoder::Instruction& inst) {
|
||||
const auto count = IR::U32(ir.Emit(IR::ValueOpcode::BitCount32, {ReadU32(inst.src0)}));
|
||||
WriteOperand(DestinationOperand(inst), ir.IAdd(count, ReadU32(inst.src1)));
|
||||
|
||||
@@ -34,7 +34,8 @@ bool Translator::EmitScalar(const Decoder::Instruction& inst) {
|
||||
case O::S_ADD_U32: ADD_U32(inst, false, false); return true;
|
||||
case O::S_ADDC_U32: ADD_U32(inst, false, true); return true;
|
||||
case O::S_SUB_U32: SUB_U32(inst, false, false); return true;
|
||||
case O::S_SUBB_U32: SUBB_U32(inst, false); return true;
|
||||
case O::S_SUBB_U32: SUBB_U32(inst, false, false); return true;
|
||||
case O::S_ABSDIFF_I32: S_ABSDIFF_I32(inst); return true;
|
||||
case O::S_ADD_I32: S_ADD_SUB_I32(inst, false); return true;
|
||||
case O::S_SUB_I32: S_ADD_SUB_I32(inst, true); return true;
|
||||
case O::S_LSHL1_ADD_U32: S_LSHL_ADD_U32(inst, 1u); return true;
|
||||
@@ -186,6 +187,8 @@ bool Translator::EmitScalar(const Decoder::Instruction& inst) {
|
||||
|
||||
case O::S_BITSET0_B32: return S_BITSET_B32(inst, false);
|
||||
case O::S_BITSET1_B32: return S_BITSET_B32(inst, true);
|
||||
case O::S_BITSET0_B64: return S_BITSET_B64(inst, false);
|
||||
case O::S_BITSET1_B64: return S_BITSET_B64(inst, true);
|
||||
case O::S_BITREPLICATE_B64_B32: return S_BITREPLICATE_B64_B32(inst);
|
||||
case O::S_QUADMASK_B64: return S_QUADMASK_B64(inst);
|
||||
case O::S_BFM_B32: return BFM_B32(inst);
|
||||
@@ -201,6 +204,7 @@ bool Translator::EmitScalar(const Decoder::Instruction& inst) {
|
||||
|
||||
case O::S_NOP:
|
||||
case O::S_SLEEP:
|
||||
case O::S_SETPRIO:
|
||||
case O::S_TRAP: EmitControlNop(); return true;
|
||||
case O::S_WAITCNT_DEPCTR: EmitWaitcnt(); return true;
|
||||
case O::S_BARRIER: S_BARRIER(); return true;
|
||||
|
||||
@@ -192,6 +192,7 @@ private:
|
||||
bool V_SAD_U32(const Decoder::Instruction& inst);
|
||||
bool V_ADD3_U32(const Decoder::Instruction& inst);
|
||||
bool S_BITSET_B32(const Decoder::Instruction& inst, bool set);
|
||||
bool S_BITSET_B64(const Decoder::Instruction& inst, bool set);
|
||||
bool V_BCNT_U32_B32(const Decoder::Instruction& inst);
|
||||
bool V_MBCNT_U32_B32(const Decoder::Instruction& inst, bool low);
|
||||
bool S_BITREPLICATE_B64_B32(const Decoder::Instruction& inst);
|
||||
@@ -218,7 +219,8 @@ private:
|
||||
bool negate_source, bool write_64);
|
||||
void ADD_U32(const Decoder::Instruction& inst, bool vector, bool use_carry_in);
|
||||
void SUB_U32(const Decoder::Instruction& inst, bool vector, bool reverse);
|
||||
void SUBB_U32(const Decoder::Instruction& inst, bool vector);
|
||||
void SUBB_U32(const Decoder::Instruction& inst, bool vector, bool reverse);
|
||||
void S_ABSDIFF_I32(const Decoder::Instruction& inst);
|
||||
void S_ADD_SUB_I32(const Decoder::Instruction& inst, bool subtract);
|
||||
void S_LSHL_ADD_U32(const Decoder::Instruction& inst, uint32_t shift_amount);
|
||||
void ScalarMinMax32(const Decoder::Instruction& inst, IR::ValueOpcode value_opcode,
|
||||
|
||||
@@ -10,7 +10,8 @@ bool Translator::EmitVector(const Decoder::Instruction& inst) {
|
||||
case O::V_ADDC_U32: ADD_U32(inst, true, true); return true;
|
||||
case O::V_SUB_I32: SUB_U32(inst, true, false); return true;
|
||||
case O::V_SUBREV_I32: SUB_U32(inst, true, true); return true;
|
||||
case O::V_SUBREV_CO_CI_U32: SUBB_U32(inst, true); return true;
|
||||
case O::V_SUB_CO_CI_U32: SUBB_U32(inst, true, false); return true;
|
||||
case O::V_SUBREV_CO_CI_U32: SUBB_U32(inst, true, true); return true;
|
||||
|
||||
case O::V_MOV_B32: MOV_B32(inst, true); return true;
|
||||
case O::V_MOVRELS_B32: V_MOVRELS_B32(inst); return true;
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
+47
-36
@@ -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);
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -39,11 +39,42 @@ struct PadControllerInformation {
|
||||
uint8_t reserve[8];
|
||||
};
|
||||
|
||||
struct PadLightBarParam {
|
||||
uint8_t r;
|
||||
uint8_t g;
|
||||
uint8_t b;
|
||||
uint8_t reserve;
|
||||
};
|
||||
|
||||
struct PadVibrationParam {
|
||||
uint8_t large_motor;
|
||||
uint8_t small_motor;
|
||||
};
|
||||
|
||||
struct PadTriggerEffectCommand {
|
||||
uint32_t mode;
|
||||
uint8_t reserve[4];
|
||||
uint8_t data[48];
|
||||
};
|
||||
|
||||
struct PadTriggerEffectParam {
|
||||
uint8_t trigger_mask;
|
||||
uint8_t reserve[7];
|
||||
PadTriggerEffectCommand command[2];
|
||||
};
|
||||
|
||||
static_assert(sizeof(PadTriggerEffectCommand) == 56);
|
||||
static_assert(sizeof(PadTriggerEffectParam) == 120);
|
||||
|
||||
struct DualSenseEffects {
|
||||
uint8_t enable_bits;
|
||||
uint8_t reserve[9];
|
||||
uint8_t right_trigger[11];
|
||||
uint8_t left_trigger[11];
|
||||
};
|
||||
|
||||
static_assert(sizeof(DualSenseEffects) == 32);
|
||||
|
||||
struct ControllerState {
|
||||
struct Touch {
|
||||
uint8_t id = 0;
|
||||
@@ -73,6 +104,8 @@ public:
|
||||
void ResetInputState();
|
||||
void GetConnectionInfo(bool* flag, int* count);
|
||||
void SetVibration(uint8_t large_motor, uint8_t small_motor);
|
||||
void SetLightBar(uint8_t r, uint8_t g, uint8_t b);
|
||||
bool SetTriggerEffect(const PadTriggerEffectParam& param);
|
||||
void ReadState(ControllerState* state, bool* flag, int* count);
|
||||
int ReadStates(ControllerState* states, int states_num, bool* flag, int* count);
|
||||
|
||||
@@ -125,6 +158,92 @@ static void pad_fill_data(PadData* data, const ControllerState& state, bool conn
|
||||
data->device_unique_data_len = 0;
|
||||
}
|
||||
|
||||
static bool trigger_effect_zones(uint8_t* effect, const uint8_t* strengths, uint8_t type,
|
||||
uint8_t frequency = 0) {
|
||||
uint16_t active = 0;
|
||||
uint32_t packed = 0;
|
||||
for (int i = 0; i < 10; i++) {
|
||||
if (strengths[i] > 8) {
|
||||
return false;
|
||||
}
|
||||
if (strengths[i] != 0) {
|
||||
active |= static_cast<uint16_t>(1u << i);
|
||||
packed |= static_cast<uint32_t>(strengths[i] - 1u) << (3 * i);
|
||||
}
|
||||
}
|
||||
|
||||
effect[0] = active != 0 && (type != 0x26 || frequency != 0) ? type : 0x05;
|
||||
effect[1] = static_cast<uint8_t>(active);
|
||||
effect[2] = static_cast<uint8_t>(active >> 8u);
|
||||
effect[3] = static_cast<uint8_t>(packed);
|
||||
effect[4] = static_cast<uint8_t>(packed >> 8u);
|
||||
effect[5] = static_cast<uint8_t>(packed >> 16u);
|
||||
effect[6] = static_cast<uint8_t>(packed >> 24u);
|
||||
effect[9] = frequency;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool trigger_effect_to_dualsense(const PadTriggerEffectCommand& command, uint8_t* effect) {
|
||||
std::memset(effect, 0, 11);
|
||||
effect[0] = 0x05;
|
||||
|
||||
uint8_t strengths[10] = {};
|
||||
switch (command.mode) {
|
||||
case 0: return true;
|
||||
case 1:
|
||||
if (command.data[0] > 9 || command.data[1] > 8) {
|
||||
return false;
|
||||
}
|
||||
std::fill(strengths + command.data[0], strengths + 10, command.data[1]);
|
||||
return trigger_effect_zones(effect, strengths, 0x21);
|
||||
case 2: {
|
||||
const auto start = command.data[0];
|
||||
const auto end = command.data[1];
|
||||
const auto strength = command.data[2];
|
||||
if (start < 2 || start > 7 || end <= start || end > 8 || strength > 8) {
|
||||
return false;
|
||||
}
|
||||
if (strength == 0) {
|
||||
return true;
|
||||
}
|
||||
const uint16_t zones = static_cast<uint16_t>((1u << start) | (1u << end));
|
||||
effect[0] = 0x25;
|
||||
effect[1] = static_cast<uint8_t>(zones);
|
||||
effect[2] = static_cast<uint8_t>(zones >> 8u);
|
||||
effect[3] = strength - 1u;
|
||||
return true;
|
||||
}
|
||||
case 3:
|
||||
if (command.data[0] > 9 || command.data[1] > 8) {
|
||||
return false;
|
||||
}
|
||||
std::fill(strengths + command.data[0], strengths + 10, command.data[1]);
|
||||
return trigger_effect_zones(effect, strengths, 0x26, command.data[2]);
|
||||
case 4: return trigger_effect_zones(effect, command.data, 0x21);
|
||||
case 5: {
|
||||
const int start = command.data[0];
|
||||
const int end = command.data[1];
|
||||
const int start_strength = command.data[2];
|
||||
const int end_strength = command.data[3];
|
||||
if (start > 8 || end <= start || end > 9 || start_strength < 1 || start_strength > 8 ||
|
||||
end_strength < 1 || end_strength > 8) {
|
||||
return false;
|
||||
}
|
||||
for (int i = start; i < 10; i++) {
|
||||
const int delta = (end_strength - start_strength) * (i - start);
|
||||
const int length = end - start;
|
||||
strengths[i] = static_cast<uint8_t>(
|
||||
i >= end ? end_strength
|
||||
: start_strength +
|
||||
(delta + (delta < 0 ? -length / 2 : length / 2)) / length);
|
||||
}
|
||||
return trigger_effect_zones(effect, strengths, 0x21);
|
||||
}
|
||||
case 6: return trigger_effect_zones(effect, command.data + 1, 0x26, command.data[0]);
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
void Initialize() {
|
||||
EXIT_IF(g_controller != nullptr);
|
||||
|
||||
@@ -304,6 +423,44 @@ void GameController::SetVibration(uint8_t large_motor, uint8_t small_motor) {
|
||||
}
|
||||
}
|
||||
|
||||
void GameController::SetLightBar(uint8_t r, uint8_t g, uint8_t b) {
|
||||
Common::LockGuard lock(m_mutex);
|
||||
if (auto* pad = SDL_GameControllerFromInstanceID(static_cast<SDL_JoystickID>(m_active_id));
|
||||
pad != nullptr) {
|
||||
(void)SDL_GameControllerSetLED(pad, r, g, b);
|
||||
}
|
||||
}
|
||||
|
||||
bool GameController::SetTriggerEffect(const PadTriggerEffectParam& param) {
|
||||
if ((param.trigger_mask & ~0x03u) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DualSenseEffects effect {};
|
||||
if ((param.trigger_mask & 0x01u) != 0) {
|
||||
effect.enable_bits |= 0x08;
|
||||
if (!trigger_effect_to_dualsense(param.command[0], effect.left_trigger)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if ((param.trigger_mask & 0x02u) != 0) {
|
||||
effect.enable_bits |= 0x04;
|
||||
if (!trigger_effect_to_dualsense(param.command[1], effect.right_trigger)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (effect.enable_bits == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Common::LockGuard lock(m_mutex);
|
||||
auto* pad = SDL_GameControllerFromInstanceID(static_cast<SDL_JoystickID>(m_active_id));
|
||||
if (pad != nullptr && SDL_GameControllerGetType(pad) == SDL_CONTROLLER_TYPE_PS5) {
|
||||
(void)SDL_GameControllerSendEffect(pad, &effect, sizeof(effect));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void GameController::GetConnectionInfo(bool* flag, int* count) {
|
||||
EXIT_IF(flag == nullptr);
|
||||
EXIT_IF(count == nullptr);
|
||||
@@ -617,7 +774,24 @@ int KYTY_SYSV_ABI PadSetLightBar(int handle, const PadLightBarParam* param) {
|
||||
return PAD_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
EXIT_IF(g_controller == nullptr);
|
||||
g_controller->SetLightBar(param->r, param->g, param->b);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI PadSetTriggerEffect(int handle, const PadTriggerEffectParam* param) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (handle != 1) {
|
||||
return PAD_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
if (param == nullptr) {
|
||||
return PAD_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
EXIT_IF(g_controller == nullptr);
|
||||
return g_controller->SetTriggerEffect(*param) ? OK : PAD_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
} // namespace Libs::Controller
|
||||
|
||||
@@ -48,6 +48,7 @@ struct PadControllerInformation;
|
||||
struct PadData;
|
||||
struct PadVibrationParam;
|
||||
struct PadLightBarParam;
|
||||
struct PadTriggerEffectParam;
|
||||
|
||||
inline int controller_get_axis(int min, int max, int value) {
|
||||
int v = (255 * (value - min)) / (max - min);
|
||||
@@ -78,6 +79,7 @@ int KYTY_SYSV_ABI PadGetControllerInformation(int handle, PadControllerInformati
|
||||
int KYTY_SYSV_ABI PadReadState(int handle, PadData* data);
|
||||
int KYTY_SYSV_ABI PadRead(int handle, PadData* data, int num);
|
||||
int KYTY_SYSV_ABI PadSetVibration(int handle, const PadVibrationParam* param);
|
||||
int KYTY_SYSV_ABI PadSetTriggerEffect(int handle, const PadTriggerEffectParam* param);
|
||||
int KYTY_SYSV_ABI PadResetLightBar(int handle);
|
||||
int KYTY_SYSV_ABI PadSetLightBar(int handle, const PadLightBarParam* param);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
+1
-18
@@ -42,23 +42,6 @@ static int KYTY_SYSV_ABI PadGetTriggerEffectState(int
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI PadSetTriggerEffect(int handle, const void* param) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t handle = %d\n"
|
||||
"\t param = 0x%016" PRIx64 "\n",
|
||||
handle, reinterpret_cast<uint64_t>(param));
|
||||
|
||||
if (handle != 1) {
|
||||
return -2137915389; /* 0x80920003 */
|
||||
}
|
||||
if (param == nullptr) {
|
||||
return -2137915391; /* 0x80920001 */
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI PadSetVibrationTriggerEffectWeakWhileEmbeddedMicInUse(bool enabled) {
|
||||
PRINT_NAME();
|
||||
|
||||
@@ -198,7 +181,7 @@ LIB_DEFINE(InitPad_1) {
|
||||
LIB_FUNC("rIZnR6eSpvk", Controller::PadResetOrientation);
|
||||
LIB_FUNC("vDLMoJLde8I", PadSetTiltCorrectionState);
|
||||
LIB_FUNC("gjP9-KQzoUk", Controller::PadGetControllerInformation);
|
||||
LIB_FUNC("2JgFB2n9oUM", PadSetTriggerEffect);
|
||||
LIB_FUNC("2JgFB2n9oUM", Controller::PadSetTriggerEffect);
|
||||
LIB_FUNC("YndgXqQVV7c", Controller::PadReadState);
|
||||
LIB_FUNC("q1cHNfGycLI", Controller::PadRead);
|
||||
LIB_FUNC("yFVnOdGxvZY", Controller::PadSetVibration);
|
||||
|
||||
+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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2950,6 +2950,28 @@ public:
|
||||
"dynamic view identity omitted mapping, format, mip, layer, type, "
|
||||
"or storage usage");
|
||||
|
||||
auto video_out_info = color_info;
|
||||
video_out_info.pixel_format = vk::Format::eA2R10G10B10UnormPack32;
|
||||
video_out_info.guest_format = Prospero::BufferFormat::k10_10_10_2UNorm;
|
||||
Libs::Graphics::Image video_out(m_runtime_context, scheduler,
|
||||
video_out_info);
|
||||
auto video_out_view_info = sampled;
|
||||
video_out_view_info.format = video_out_info.pixel_format;
|
||||
video_out_view_info.usage = vk::ImageUsageFlagBits::eTransferSrc;
|
||||
const auto video_out_view = video_out.FindView(video_out_view_info);
|
||||
auto storage_alias_info = video_out_view_info;
|
||||
storage_alias_info.format = vk::Format::eA2B10G10R10UnormPack32;
|
||||
storage_alias_info.usage = vk::ImageUsageFlagBits::eStorage;
|
||||
const auto storage_alias_view = video_out.FindView(storage_alias_info);
|
||||
Require(
|
||||
name, "video-out storage alias usage",
|
||||
ImageViewOps::FormatsCompatible(video_out_info.pixel_format,
|
||||
storage_alias_info.format) &&
|
||||
static_cast<bool>(video_out.backing.usage &
|
||||
vk::ImageUsageFlagBits::eStorage) &&
|
||||
video_out_view != nullptr && storage_alias_view != nullptr,
|
||||
"compatible video-out backing was created without storage usage");
|
||||
|
||||
ImageInfo depth_info{};
|
||||
depth_info.pixel_format = vk::Format::eD32Sfloat;
|
||||
depth_info.guest_format = Prospero::BufferFormat::k32Float;
|
||||
@@ -12655,6 +12677,76 @@ TestCase ScalarAbsI32UpdatesScc() {
|
||||
O::V_MOV_B32, O::BUFFER_STORE_DWORD, O::S_ENDPGM}};
|
||||
}
|
||||
|
||||
TestCase ScalarAbsdiffBitset64AndSetprio() {
|
||||
using O = ShaderOpcode;
|
||||
|
||||
std::vector<u32> code;
|
||||
auto capture_scc = [&](u32 dst_sgpr) {
|
||||
code.push_back(
|
||||
EncodeSop2(0x0a, dst_sgpr, InlineU32(1), InlineU32(0)));
|
||||
};
|
||||
|
||||
code.push_back(EncodeSMovB32(0, InlineU32(2)));
|
||||
code.push_back(EncodeSMovB32(1, InlineU32(5)));
|
||||
code.push_back(EncodeSop2(0x2c, 10, 0, 1));
|
||||
capture_scc(20);
|
||||
AppendSMovLiteral(&code, 0, 0xffffffffu);
|
||||
code.push_back(EncodeSMovB32(1, InlineU32(0)));
|
||||
code.push_back(EncodeSop2(0x2c, 11, 0, 1));
|
||||
capture_scc(21);
|
||||
AppendSMovLiteral(&code, 0, 0x80000000u);
|
||||
code.push_back(EncodeSop2(0x2c, 12, 0, 1));
|
||||
capture_scc(22);
|
||||
code.push_back(EncodeSMovB32(1, InlineU32(1)));
|
||||
code.push_back(EncodeSop2(0x2c, 13, 0, 1));
|
||||
capture_scc(23);
|
||||
code.push_back(EncodeSop2(0x2c, 14, 0, 0));
|
||||
capture_scc(24);
|
||||
|
||||
AppendSMovLiteral(&code, 2, 65u);
|
||||
AppendSMovLiteral(&code, 3, 101u);
|
||||
code.push_back(EncodeSMovB32(4, InlineU32(0)));
|
||||
code.push_back(EncodeSMovB32(5, InlineU32(0)));
|
||||
code.push_back(EncodeSop1(0x1e, 4, 2));
|
||||
AppendStoreSgprPair(&code, 4, 10);
|
||||
code.push_back(EncodeSop1(0x1e, 4, 3));
|
||||
AppendStoreSgprPair(&code, 4, 12);
|
||||
code.push_back(EncodeSop1(0x1c, 4, 2));
|
||||
AppendStoreSgprPair(&code, 4, 14);
|
||||
code.push_back(EncodeSop1(0x1c, 4, 3));
|
||||
AppendStoreSgprPair(&code, 4, 16);
|
||||
code.push_back(EncodeSopp(0x0f, 3));
|
||||
|
||||
AppendStoreSgpr(&code, 10, 0);
|
||||
AppendStoreSgpr(&code, 11, 1);
|
||||
AppendStoreSgpr(&code, 12, 2);
|
||||
AppendStoreSgpr(&code, 13, 3);
|
||||
AppendStoreSgpr(&code, 14, 4);
|
||||
AppendStoreSgpr(&code, 20, 5);
|
||||
AppendStoreSgpr(&code, 21, 6);
|
||||
AppendStoreSgpr(&code, 22, 7);
|
||||
AppendStoreSgpr(&code, 23, 8);
|
||||
AppendStoreSgpr(&code, 24, 9);
|
||||
AppendEnd(&code);
|
||||
|
||||
TestCase test;
|
||||
test.name = "ScalarAbsdiffBitset64AndSetprio";
|
||||
test.code = std::move(code);
|
||||
test.expected = {3u, 1u, 0x80000000u, 0x7fffffffu, 0u,
|
||||
1u, 1u, 1u, 1u, 0u,
|
||||
2u, 0u, 2u, 32u, 0u,
|
||||
32u, 0u, 0u};
|
||||
test.opcodes = {O::S_MOV_B32, O::S_ABSDIFF_I32, O::S_CSELECT_B32,
|
||||
O::S_BITSET1_B64, O::S_BITSET0_B64, O::S_SETPRIO,
|
||||
O::V_MOV_B32,
|
||||
O::BUFFER_STORE_DWORD, O::S_ENDPGM};
|
||||
test.decoded_counts = {{"S_ABSDIFF_I32", 5},
|
||||
{"S_BITSET1_B64", 2},
|
||||
{"S_BITSET0_B64", 2},
|
||||
{"S_SETPRIO 0x00000003", 1}};
|
||||
return test;
|
||||
}
|
||||
|
||||
TestCase ScalarShiftLeftAddSccCarryEdges() {
|
||||
using O = ShaderOpcode;
|
||||
|
||||
@@ -14155,6 +14247,55 @@ TestCase VectorAddcWritesPerLaneCarryOut() {
|
||||
return test;
|
||||
}
|
||||
|
||||
TestCase VectorSubCoCiU32CompactAndVop3() {
|
||||
using O = ShaderOpcode;
|
||||
|
||||
std::vector<u32> code;
|
||||
code.push_back(EncodeVop2(0x1a, 4, InlineU32(2), 0));
|
||||
AppendBufferLoadDword(&code, 1, 4);
|
||||
code.push_back(EncodeVop2(0x25, 5, InlineU32(16), 4));
|
||||
AppendBufferLoadDword(&code, 2, 5);
|
||||
code.push_back(EncodeVop2(0x1b, 3, InlineU32(1), 0));
|
||||
code.push_back(EncodeVopc(0xc5, InlineU32(0), 3));
|
||||
code.push_back(EncodeSop1(0x04, 20, 106));
|
||||
code.push_back(EncodeVop2(0x29, 10, Vgpr(1), 2));
|
||||
AppendVMovU32(&code, 6, 1);
|
||||
code.push_back(EncodeVop2(0x01, 11, InlineU32(0), 6));
|
||||
AppendStoreVgprAtLaneDwordOffset(&code, 10, 0, 0);
|
||||
AppendStoreVgprAtLaneDwordOffset(&code, 11, 0, 4);
|
||||
|
||||
code.push_back(EncodeVopc(0xc2, InlineU32(0), 6));
|
||||
AppendVop3B(&code, 0x129u, 12, 22, Vgpr(1), Vgpr(2), 20);
|
||||
AppendVop3(&code, 0x101u, 13, InlineU32(0), Vgpr(6), 22);
|
||||
code.push_back(EncodeVop2(0x01, 14, InlineU32(0), 6));
|
||||
AppendStoreVgprAtLaneDwordOffset(&code, 12, 0, 8);
|
||||
AppendStoreVgprAtLaneDwordOffset(&code, 13, 0, 12);
|
||||
AppendStoreVgprAtLaneDwordOffset(&code, 14, 0, 16);
|
||||
AppendEnd(&code);
|
||||
|
||||
TestCase test;
|
||||
test.name = "VectorSubCoCiU32CompactAndVop3";
|
||||
test.code = std::move(code);
|
||||
test.initial = {5u, 5u, 3u, 3u, 3u, 3u, 5u, 3u, 0u, 0u,
|
||||
0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u};
|
||||
test.expected = {2u, 1u, 0xfffffffeu, 0xffffffffu, 0u, 0u, 1u,
|
||||
1u, 2u, 1u, 0xfffffffeu, 0xffffffffu, 0u, 0u,
|
||||
1u, 1u, 0u, 0u, 0u, 0u};
|
||||
test.opcodes = {O::V_MOV_B32, O::V_LSHLREV_B32, O::V_ADD_NC_U32,
|
||||
O::V_AND_B32, O::V_CMP_NE_U32, O::V_CMP_EQ_U32,
|
||||
O::V_SUB_CO_CI_U32, O::V_CNDMASK_B32, O::S_MOV_B64,
|
||||
O::BUFFER_LOAD_DWORD, O::BUFFER_STORE_DWORD, O::S_ENDPGM};
|
||||
test.decoded_counts = {{"V_SUB_CO_CI_U32", 2}};
|
||||
test.required_spirv = {"OpISub", "OpUGreaterThan", "OpLogicalOr"};
|
||||
test.compute_info.threads_num[0] = 4;
|
||||
test.compute_info.threads_num[1] = 1;
|
||||
test.compute_info.threads_num[2] = 1;
|
||||
test.compute_info.thread_ids_num = 1;
|
||||
test.compute_info.wave_size = 32;
|
||||
test.has_compute_info = true;
|
||||
return test;
|
||||
}
|
||||
|
||||
TestCase VectorSubrevCoCiU32ExactRawOnGpu() {
|
||||
using O = ShaderOpcode;
|
||||
|
||||
@@ -15121,6 +15262,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;
|
||||
|
||||
@@ -21121,6 +21287,7 @@ std::vector<TestCase> MakeCases() {
|
||||
AddCase(ScalarArithmeticSccCarryBorrowOverflow);
|
||||
AddCase(ScalarMinMaxSccComparisonEdges);
|
||||
AddCase(ScalarAbsI32UpdatesScc);
|
||||
AddCase(ScalarAbsdiffBitset64AndSetprio);
|
||||
AddCase(ScalarShiftLeftAddSccCarryEdges);
|
||||
AddCase(ScalarCompareOps);
|
||||
AddCase(ScalarShiftAddAndMaskOps);
|
||||
@@ -21166,6 +21333,7 @@ std::vector<TestCase> MakeCases() {
|
||||
AddCase(VectorMbcntUsesThreadMask);
|
||||
AddCase(VectorAddcWritesPerLaneCarryOut);
|
||||
AddCase(VectorAddcUsesPerLaneCarryIn);
|
||||
AddCase(VectorSubCoCiU32CompactAndVop3);
|
||||
AddCase(VectorSubrevCoCiU32ExactRawOnGpu);
|
||||
AddCase(VectorVop3BSubrevCoCiUsesEncodedMasks);
|
||||
AddCase(VectorVop3BCarryOutWritesSgprMask);
|
||||
@@ -21194,6 +21362,7 @@ std::vector<TestCase> MakeCases() {
|
||||
AddCase(VectorPermlane16FetchInactiveZero);
|
||||
AddCase(VectorPermlane16FetchInactiveFi);
|
||||
AddCase(VectorDppQuadPermuteReverse);
|
||||
AddCase(VectorDppRowXmask);
|
||||
AddCase(VectorDppBankMaskPreservesDestination);
|
||||
AddCase(VectorDppBoundsControlZeroPreservesDestination);
|
||||
AddCase(Vop3LdexpSourceModifier);
|
||||
@@ -23413,6 +23582,7 @@ void CheckStorageTextureDepthTileUploadLayout() {
|
||||
"1x1 R8_UINT depth tile lost its 64 KiB source footprint");
|
||||
std::printf("[host] %-32s ok\n", "StorageTextureDepthTileUpload");
|
||||
}
|
||||
|
||||
void CheckImageSamplerSpecialization() {
|
||||
ShaderSamplerResource filtered_sampler{};
|
||||
filtered_sampler.fields[2] =
|
||||
@@ -24723,6 +24893,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 *);
|
||||
@@ -25325,6 +25543,7 @@ int main(int argc, char **argv) {
|
||||
CheckPm4PrivateAgcUconfigRegisters(vulkan.RuntimeRenderer());
|
||||
CheckPm4BlendColorRegisterRanges(vulkan.RuntimeRenderer());
|
||||
CheckPm4PolygonOffsetRegisters(vulkan.RuntimeRenderer());
|
||||
CheckPm4DepthControlHighBits(vulkan.RuntimeRenderer());
|
||||
CheckPm4ContextStateOperations(vulkan.RuntimeRenderer());
|
||||
return 0;
|
||||
}
|
||||
@@ -25514,6 +25733,7 @@ int main(int argc, char **argv) {
|
||||
CheckPm4GuardBandRegisterRanges(vulkan.RuntimeRenderer());
|
||||
CheckPm4BlendColorRegisterRanges(vulkan.RuntimeRenderer());
|
||||
CheckPm4PolygonOffsetRegisters(vulkan.RuntimeRenderer());
|
||||
CheckPm4DepthControlHighBits(vulkan.RuntimeRenderer());
|
||||
CheckAgcWaitPackets(vulkan.RuntimeRenderer());
|
||||
CheckAgcDrawIndirectMultiPacket(vulkan.RuntimeRenderer());
|
||||
CheckPm4ContextStateOperations(vulkan.RuntimeRenderer());
|
||||
|
||||
@@ -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{};
|
||||
@@ -11908,6 +11947,7 @@ int main() {
|
||||
TestNewShaderRecompilerSpirvSizeBaselines();
|
||||
TestDemandDrivenSpirvDeclarations();
|
||||
TestNewShaderRecompilerSMovB32();
|
||||
TestNewShaderRecompilerClipDisabledPosition();
|
||||
TestNewShaderRecompilerAuxPositionExports();
|
||||
TestNewShaderRecompilerNativeWideScalarMemoryIr();
|
||||
TestNewShaderRecompilerNativeWideBufferIr();
|
||||
|
||||
Reference in New Issue
Block a user