mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 02:47:02 +02:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2f4b8a335d | |||
| b38b7454a6 | |||
| b65dc12208 | |||
| 58978d154a |
@@ -617,6 +617,13 @@ PipelineCache::GraphicsPrograms PipelineCache::GetGraphicsPrograms(
|
||||
ShaderParams pixel_params;
|
||||
if (pixel_active) {
|
||||
pixel_params = PrepareProgram(pixel_regs, sh, target_export_mapping, pixel_info);
|
||||
if (!mesh_active && !tess_active && Prospero::IsRectList(user_config.GetPrimType())) {
|
||||
pixel_info.parameter_mode = ShaderPixelParameterMode::Rectangle;
|
||||
} else if (context.GetModeControl().provoking_vtx_last) {
|
||||
pixel_info.parameter_mode = ShaderPixelParameterMode::LastVertex;
|
||||
} else {
|
||||
pixel_info.parameter_mode = ShaderPixelParameterMode::FirstVertex;
|
||||
}
|
||||
const auto& blend = context.GetBlendControl(0);
|
||||
pixel_info.dual_source_blending =
|
||||
blend.enable && !context.GetRenderTarget(0).info.blend_bypass &&
|
||||
|
||||
@@ -177,6 +177,13 @@ uint32_t EmitAttribute(EmitterState& state, uint32_t attr, uint32_t chan) {
|
||||
return value;
|
||||
};
|
||||
if (input->per_vertex) {
|
||||
if (PixelParameterIsFlat(state, attr)) {
|
||||
const auto value = load_per_vertex(
|
||||
state.input_info.pixel->parameter_mode == ShaderPixelParameterMode::LastVertex ? 2u : 0u);
|
||||
const auto bits = state.builder.AllocateId();
|
||||
state.builder.AddFunction(spv::OpBitcast, TypeU32(state), bits, value);
|
||||
return bits;
|
||||
}
|
||||
const auto barycentric_kind = state.input_info.pixel->ps_no_perspective
|
||||
? IR::StageInputKind::BaryCoordNoPerspective
|
||||
: IR::StageInputKind::BaryCoordSmooth;
|
||||
@@ -231,8 +238,12 @@ uint32_t EmitInterpolationParameter(ValueEmitContext& ctx, uint32_t attr, uint32
|
||||
return value;
|
||||
};
|
||||
|
||||
const auto selected_vertex = (mode + 1u) % 3u;
|
||||
uint32_t value = load_vertex(selected_vertex);
|
||||
uint32_t selected_vertex = (mode + 1u) % 3u;
|
||||
if (mode == 2u && PixelParameterIsFlat(state, attr)) {
|
||||
selected_vertex =
|
||||
state.input_info.pixel->parameter_mode == ShaderPixelParameterMode::LastVertex ? 2u : 0u;
|
||||
}
|
||||
uint32_t value = load_vertex(selected_vertex);
|
||||
if (!PixelParameterIsCustom(state, attr) && mode < 2u) {
|
||||
const auto delta = state.builder.AllocateId();
|
||||
state.builder.AddFunction(spv::OpFSub, TypeF32(state), delta, value, load_vertex(0));
|
||||
|
||||
@@ -997,7 +997,8 @@ constexpr Vop2SdwaRule VOP2_SDWA_RULES[] = {
|
||||
{SdwaSelAll(), SdwaSelAll(), SdwaSelAll(), true, false},
|
||||
{SdwaSelFull(), SdwaSelAll(), SdwaSelAll(), false, false},
|
||||
{SdwaSelFull(), SdwaSelAll(), SdwaSelAll(), false, false},
|
||||
{SdwaSelWords() | SdwaSelFull(), SdwaSelAll(), SdwaSelAll(), true, false},
|
||||
// Bitwise: WriteRawU32 inserts a byte or word destination like any other partial write.
|
||||
{SdwaSelAll(), SdwaSelAll(), SdwaSelAll(), true, false},
|
||||
};
|
||||
static_assert(sizeof(VOP2_SDWA_RULES) / sizeof(VOP2_SDWA_RULES[0]) ==
|
||||
static_cast<size_t>(Vop2SdwaProfile::Count));
|
||||
|
||||
@@ -227,15 +227,16 @@ void CollectPixelInputs(const Program& program, const ShaderPixelInputInfo* pixe
|
||||
}
|
||||
}
|
||||
}
|
||||
// Aliases of a vertex output share one SPIR-V interface variable. If any
|
||||
// alias reads raw vertices, interpolate the other aliases from those too.
|
||||
// Mixed interpolation modes share raw vertices at their guest export slot.
|
||||
// Rectangle expansion alone supplies separate flat and smooth outputs.
|
||||
for (uint32_t input = 0; input < pixel->input_num; input++) {
|
||||
for (uint32_t alias = 0; alias < pixel->input_num; alias++) {
|
||||
const bool same_mode = ShaderPixelParameterIsFlat(*pixel, input) ==
|
||||
ShaderPixelParameterIsFlat(*pixel, alias);
|
||||
if (ShaderPixelParameterMappedLocation(*pixel, input) ==
|
||||
ShaderPixelParameterMappedLocation(*pixel, alias) &&
|
||||
ShaderPixelParameterIsFlat(*pixel, input) ==
|
||||
ShaderPixelParameterIsFlat(*pixel, alias)) {
|
||||
per_vertex[input] = per_vertex[input] || per_vertex[alias];
|
||||
(pixel->parameter_mode != ShaderPixelParameterMode::Rectangle || same_mode)) {
|
||||
per_vertex[input] = per_vertex[input] || per_vertex[alias] || !same_mode;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -244,7 +245,8 @@ void CollectPixelInputs(const Program& program, const ShaderPixelInputInfo* pixe
|
||||
per_vertex[input]);
|
||||
}
|
||||
for (uint32_t input = 0; input < pixel->input_num; input++) {
|
||||
if (interpolated[input] && per_vertex[input]) {
|
||||
if (interpolated[input] && per_vertex[input] &&
|
||||
!ShaderPixelParameterIsFlat(*pixel, input)) {
|
||||
const auto kind = pixel->ps_no_perspective ? StageInputKind::BaryCoordNoPerspective
|
||||
: StageInputKind::BaryCoordSmooth;
|
||||
AddInput(info, kind, 0, 3,
|
||||
|
||||
@@ -663,6 +663,7 @@ void BuildStageStaticKey(const ShaderPixelInputInfo& info, std::vector<uint32_t>
|
||||
key.push_back(static_cast<uint32_t>(info.ps_front_face));
|
||||
key.push_back(static_cast<uint32_t>(info.ps_ancillary));
|
||||
key.push_back(static_cast<uint32_t>(info.ps_no_perspective));
|
||||
key.push_back(static_cast<uint32_t>(info.parameter_mode));
|
||||
key.push_back(static_cast<uint32_t>(info.ps_pixel_kill_enable));
|
||||
key.push_back(static_cast<uint32_t>(info.ps_depth_export_enable));
|
||||
key.push_back(static_cast<uint32_t>(info.ps_sample_mask_export_enable));
|
||||
|
||||
@@ -159,6 +159,7 @@ struct ShaderComputeInputInfo: ShaderWorkgroupInputInfo {
|
||||
};
|
||||
|
||||
enum class ShaderAlphaBlendSource : uint8_t { None, SourceAlpha, SourceAlphaOne, SourceAlphaZero };
|
||||
enum class ShaderPixelParameterMode : uint8_t { FirstVertex, LastVertex, Rectangle };
|
||||
|
||||
struct ShaderPixelInputInfo {
|
||||
uint32_t interpolator_settings[32] = {0};
|
||||
@@ -180,6 +181,7 @@ struct ShaderPixelInputInfo {
|
||||
bool ps_front_face = false;
|
||||
bool ps_ancillary = false;
|
||||
bool ps_no_perspective = false;
|
||||
ShaderPixelParameterMode parameter_mode = ShaderPixelParameterMode::FirstVertex;
|
||||
bool ps_pixel_kill_enable = false;
|
||||
bool ps_depth_export_enable = false;
|
||||
bool ps_sample_mask_export_enable = false;
|
||||
|
||||
@@ -30,6 +30,9 @@ uint32_t ShaderPixelParameterMappedLocation(const ShaderPixelInputInfo& info, ui
|
||||
|
||||
uint32_t ShaderPixelParameterLocation(const ShaderPixelInputInfo& info,
|
||||
std::span<const uint32_t> active_inputs, uint32_t input) {
|
||||
if (info.parameter_mode != ShaderPixelParameterMode::Rectangle) {
|
||||
return ShaderPixelParameterMappedLocation(info, input);
|
||||
}
|
||||
std::array<bool, 32> used_locations {};
|
||||
for (const auto active_input: active_inputs) {
|
||||
used_locations[ShaderPixelParameterMappedLocation(info, active_input)] = true;
|
||||
@@ -42,8 +45,7 @@ uint32_t ShaderPixelParameterLocation(const ShaderPixelInputInfo& info,
|
||||
auto& location = group_locations[group];
|
||||
if (location == UINT32_MAX) {
|
||||
location = mapped;
|
||||
// Smooth and custom interpolation read the same vertex output. Only
|
||||
// differing flat/smooth rectangle outputs need separate locations.
|
||||
// Rectangle expansion broadcasts flat aliases through separate outputs.
|
||||
if (group_locations[group ^ 1u] != UINT32_MAX) {
|
||||
location = 0;
|
||||
while (location < used_locations.size() && used_locations[location]) {
|
||||
|
||||
+112
-57
@@ -24,8 +24,12 @@ namespace Libs::Controller {
|
||||
|
||||
LIB_NAME("Pad", "Pad");
|
||||
|
||||
constexpr int PAD_ERROR_INVALID_ARG = -2137915391; /* 0x80920001 */
|
||||
constexpr int PAD_ERROR_INVALID_HANDLE = -2137915389; /* 0x80920003 */
|
||||
constexpr int PAD_ERROR_INVALID_ARG = -2137915391; /* 0x80920001 */
|
||||
constexpr int PAD_ERROR_INVALID_HANDLE = -2137915389; /* 0x80920003 */
|
||||
constexpr int PAD_ERROR_ALREADY_OPENED = -2137915388; /* 0x80920004 */
|
||||
constexpr int PAD_ERROR_NOT_INITIALIZED = -2137915387; /* 0x80920005 */
|
||||
constexpr int PAD_ERROR_NO_HANDLE = -2137915384; /* 0x80920008 */
|
||||
constexpr int PAD_HANDLE = 1;
|
||||
|
||||
constexpr uint32_t RUMBLE_DURATION_MS = 0xffff;
|
||||
constexpr uint32_t RELEASE_FLUSH_MS = 50;
|
||||
@@ -107,6 +111,12 @@ public:
|
||||
|
||||
KYTY_CLASS_NO_COPY(GameController);
|
||||
|
||||
int InitPort();
|
||||
int OpenPort(int user_id, int type, int index);
|
||||
int GetPortHandle(int user_id, int type, int index);
|
||||
int ClosePort(int handle);
|
||||
int CheckPortHandle(int handle);
|
||||
|
||||
void Connect(int id);
|
||||
void Disconnect(int id);
|
||||
void Button(int id, uint32_t button, bool down);
|
||||
@@ -131,6 +141,9 @@ public:
|
||||
|
||||
private:
|
||||
static constexpr uint32_t STATES_MAX = 64;
|
||||
enum class PortState { Uninitialized, Closed, Open };
|
||||
|
||||
int CheckPortHandleLocked(int handle) const;
|
||||
|
||||
void CheckActive();
|
||||
void AddState();
|
||||
@@ -140,6 +153,7 @@ private:
|
||||
void UpdateTriggerEffectState();
|
||||
|
||||
Common::Mutex m_mutex;
|
||||
PortState m_port_state = PortState::Uninitialized;
|
||||
std::vector<int> m_connected_ids;
|
||||
int m_active_id = -1;
|
||||
bool m_connected = false;
|
||||
@@ -925,21 +939,71 @@ int GetActiveControllerId() {
|
||||
return g_controller != nullptr ? g_controller->GetActiveControllerId() : -1;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI PadInit() {
|
||||
PRINT_NAME();
|
||||
static bool PadOpenArgsAreValid(int user_id, int type, int index) {
|
||||
// The host keyboard and gamepad feed one standard port for the configured user.
|
||||
return user_id == Config::GetUserId() && type == 0 && index == 0;
|
||||
}
|
||||
|
||||
int GameController::InitPort() {
|
||||
Common::LockGuard lock(m_mutex);
|
||||
if (m_port_state == PortState::Uninitialized) {
|
||||
m_port_state = PortState::Closed;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
static bool PadOpenArgsAreValid(int user_id, int type, int index) {
|
||||
constexpr int user_id_system = 0xff;
|
||||
constexpr int port_type_standard = 0;
|
||||
constexpr int port_type_special = 2;
|
||||
constexpr int port_type_remote = 16;
|
||||
const bool personal_port =
|
||||
user_id == Config::GetUserId() && (type == port_type_standard || type == port_type_special);
|
||||
const bool system_remote_control = user_id == user_id_system && type == port_type_remote;
|
||||
return index == 0 && (personal_port || system_remote_control);
|
||||
int GameController::OpenPort(int user_id, int type, int index) {
|
||||
Common::LockGuard lock(m_mutex);
|
||||
if (m_port_state == PortState::Uninitialized) {
|
||||
return PAD_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
if (!PadOpenArgsAreValid(user_id, type, index)) {
|
||||
return PAD_ERROR_INVALID_ARG;
|
||||
}
|
||||
if (m_port_state == PortState::Open) {
|
||||
return PAD_ERROR_ALREADY_OPENED;
|
||||
}
|
||||
m_port_state = PortState::Open;
|
||||
return PAD_HANDLE;
|
||||
}
|
||||
|
||||
int GameController::GetPortHandle(int user_id, int type, int index) {
|
||||
Common::LockGuard lock(m_mutex);
|
||||
if (m_port_state == PortState::Uninitialized) {
|
||||
return PAD_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
return m_port_state == PortState::Open && PadOpenArgsAreValid(user_id, type, index) ? PAD_HANDLE
|
||||
: PAD_ERROR_NO_HANDLE;
|
||||
}
|
||||
|
||||
int GameController::CheckPortHandleLocked(int handle) const {
|
||||
if (m_port_state == PortState::Uninitialized) {
|
||||
return PAD_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
return m_port_state == PortState::Open && handle == PAD_HANDLE ? OK : PAD_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
int GameController::CheckPortHandle(int handle) {
|
||||
Common::LockGuard lock(m_mutex);
|
||||
return CheckPortHandleLocked(handle);
|
||||
}
|
||||
|
||||
int GameController::ClosePort(int handle) {
|
||||
Common::LockGuard lock(m_mutex);
|
||||
if (const auto error = CheckPortHandleLocked(handle); error != OK) {
|
||||
return error;
|
||||
}
|
||||
m_port_state = PortState::Closed;
|
||||
return OK;
|
||||
}
|
||||
|
||||
int PadCheckHandle(int handle) {
|
||||
return g_controller->CheckPortHandle(handle);
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI PadInit() {
|
||||
PRINT_NAME();
|
||||
return g_controller->InitPort();
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI PadOpen(int user_id, int type, int index, const void* param) {
|
||||
@@ -951,15 +1015,7 @@ int KYTY_SYSV_ABI PadOpen(int user_id, int type, int index, const void* param) {
|
||||
"\t param = 0x%016" PRIx64 "\n",
|
||||
user_id, type, index, reinterpret_cast<uint64_t>(param));
|
||||
|
||||
constexpr int pad_error_invalid_arg = -2137915391; /* 0x80920001 */
|
||||
|
||||
if (!PadOpenArgsAreValid(user_id, type, index)) {
|
||||
return pad_error_invalid_arg;
|
||||
}
|
||||
|
||||
int handle = 1;
|
||||
|
||||
return handle;
|
||||
return g_controller->OpenPort(user_id, type, index);
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI PadGetHandle(int user_id, int type, int index) {
|
||||
@@ -970,20 +1026,20 @@ int KYTY_SYSV_ABI PadGetHandle(int user_id, int type, int index) {
|
||||
"\t index = %d\n",
|
||||
user_id, type, index);
|
||||
|
||||
constexpr int pad_error_device_no_handle = -2137915384; /* 0x80920008 */
|
||||
return g_controller->GetPortHandle(user_id, type, index);
|
||||
}
|
||||
|
||||
if (!PadOpenArgsAreValid(user_id, type, index)) {
|
||||
return pad_error_device_no_handle;
|
||||
}
|
||||
|
||||
return 1;
|
||||
int KYTY_SYSV_ABI PadClose(int handle) {
|
||||
PRINT_NAME();
|
||||
LOGF("\t handle = %d\n", handle);
|
||||
return g_controller->ClosePort(handle);
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI PadSetMotionSensorState(int handle, bool enable) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (handle != 1) {
|
||||
return PAD_ERROR_INVALID_HANDLE;
|
||||
if (const auto error = PadCheckHandle(handle); error != OK) {
|
||||
return error;
|
||||
}
|
||||
|
||||
LOGF("\t enable = %s\n", (enable ? "true" : "false"));
|
||||
@@ -995,8 +1051,8 @@ int KYTY_SYSV_ABI PadSetMotionSensorState(int handle, bool enable) {
|
||||
int KYTY_SYSV_ABI PadSetAngularVelocityDeadbandState(int handle, bool enable) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (handle != 1) {
|
||||
return PAD_ERROR_INVALID_HANDLE;
|
||||
if (const auto error = PadCheckHandle(handle); error != OK) {
|
||||
return error;
|
||||
}
|
||||
|
||||
LOGF("\t enable = %s\n", (enable ? "true" : "false"));
|
||||
@@ -1007,8 +1063,8 @@ int KYTY_SYSV_ABI PadSetAngularVelocityDeadbandState(int handle, bool enable) {
|
||||
int KYTY_SYSV_ABI PadResetOrientation(int handle) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (handle != 1) {
|
||||
return PAD_ERROR_INVALID_HANDLE;
|
||||
if (const auto error = PadCheckHandle(handle); error != OK) {
|
||||
return error;
|
||||
}
|
||||
|
||||
g_controller->ResetOrientation();
|
||||
@@ -1018,18 +1074,17 @@ int KYTY_SYSV_ABI PadResetOrientation(int handle) {
|
||||
int KYTY_SYSV_ABI PadGetControllerInformation(int handle, PadControllerInformation* info) {
|
||||
PRINT_NAME();
|
||||
|
||||
int connected_count = 0;
|
||||
bool connected = false;
|
||||
|
||||
g_controller->GetConnectionInfo(&connected, &connected_count);
|
||||
|
||||
if (handle != 1) {
|
||||
return PAD_ERROR_INVALID_HANDLE;
|
||||
if (const auto error = PadCheckHandle(handle); error != OK) {
|
||||
return error;
|
||||
}
|
||||
if (info == nullptr) {
|
||||
return PAD_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
int connected_count = 0;
|
||||
bool connected = false;
|
||||
g_controller->GetConnectionInfo(&connected, &connected_count);
|
||||
|
||||
std::memset(info, 0, sizeof(*info));
|
||||
|
||||
info->touch_pixel_density = 44.86f;
|
||||
@@ -1048,8 +1103,8 @@ int KYTY_SYSV_ABI PadGetControllerInformation(int handle, PadControllerInformati
|
||||
int KYTY_SYSV_ABI PadIsRemoteController(int handle, bool* is_remote) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (handle != 1) {
|
||||
return PAD_ERROR_INVALID_HANDLE;
|
||||
if (const auto error = PadCheckHandle(handle); error != OK) {
|
||||
return error;
|
||||
}
|
||||
if (is_remote == nullptr) {
|
||||
return PAD_ERROR_INVALID_ARG;
|
||||
@@ -1062,8 +1117,8 @@ int KYTY_SYSV_ABI PadIsRemoteController(int handle, bool* is_remote) {
|
||||
int KYTY_SYSV_ABI PadReadState(int handle, PadData* data) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (handle != 1) {
|
||||
return PAD_ERROR_INVALID_HANDLE;
|
||||
if (const auto error = PadCheckHandle(handle); error != OK) {
|
||||
return error;
|
||||
}
|
||||
if (data == nullptr) {
|
||||
return PAD_ERROR_INVALID_ARG;
|
||||
@@ -1084,8 +1139,8 @@ int KYTY_SYSV_ABI PadRead(int handle, PadData* data, int num) {
|
||||
PRINT_NAME();
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(num < 1 || num > 64);
|
||||
if (handle != 1) {
|
||||
return PAD_ERROR_INVALID_HANDLE;
|
||||
if (const auto error = PadCheckHandle(handle); error != OK) {
|
||||
return error;
|
||||
}
|
||||
if (data == nullptr) {
|
||||
return PAD_ERROR_INVALID_ARG;
|
||||
@@ -1116,8 +1171,8 @@ int KYTY_SYSV_ABI PadRead(int handle, PadData* data, int num) {
|
||||
int KYTY_SYSV_ABI PadSetVibration(int handle, const PadVibrationParam* param) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (handle != 1) {
|
||||
return PAD_ERROR_INVALID_HANDLE;
|
||||
if (const auto error = PadCheckHandle(handle); error != OK) {
|
||||
return error;
|
||||
}
|
||||
if (param == nullptr) {
|
||||
return PAD_ERROR_INVALID_ARG;
|
||||
@@ -1135,8 +1190,8 @@ int KYTY_SYSV_ABI PadSetVibration(int handle, const PadVibrationParam* param) {
|
||||
int KYTY_SYSV_ABI PadResetLightBar(int handle) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (handle != 1) {
|
||||
return PAD_ERROR_INVALID_HANDLE;
|
||||
if (const auto error = PadCheckHandle(handle); error != OK) {
|
||||
return error;
|
||||
}
|
||||
|
||||
return OK;
|
||||
@@ -1145,8 +1200,8 @@ int KYTY_SYSV_ABI PadResetLightBar(int handle) {
|
||||
int KYTY_SYSV_ABI PadSetLightBar(int handle, const PadLightBarParam* param) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (handle != 1) {
|
||||
return PAD_ERROR_INVALID_HANDLE;
|
||||
if (const auto error = PadCheckHandle(handle); error != OK) {
|
||||
return error;
|
||||
}
|
||||
if (param == nullptr) {
|
||||
return PAD_ERROR_INVALID_ARG;
|
||||
@@ -1160,8 +1215,8 @@ int KYTY_SYSV_ABI PadSetLightBar(int handle, const PadLightBarParam* param) {
|
||||
int KYTY_SYSV_ABI PadSetTriggerEffect(int handle, const PadTriggerEffectParam* param) {
|
||||
PRINT_NAME();
|
||||
|
||||
if (handle != 1) {
|
||||
return PAD_ERROR_INVALID_HANDLE;
|
||||
if (const auto error = PadCheckHandle(handle); error != OK) {
|
||||
return error;
|
||||
}
|
||||
if (param == nullptr) {
|
||||
return PAD_ERROR_INVALID_ARG;
|
||||
@@ -1175,8 +1230,8 @@ int KYTY_SYSV_ABI PadGetTriggerEffectState(int handle, PadTriggerEffectStateInfo
|
||||
|
||||
LOGF("\t handle = %d\n", handle);
|
||||
|
||||
if (handle != 1) {
|
||||
return PAD_ERROR_INVALID_HANDLE;
|
||||
if (const auto error = PadCheckHandle(handle); error != OK) {
|
||||
return error;
|
||||
}
|
||||
if (info == nullptr) {
|
||||
return PAD_ERROR_INVALID_ARG;
|
||||
|
||||
@@ -81,9 +81,12 @@ enum class Setting { SpeakerVolume, VibrationIntensity, TriggerEffectIntensity }
|
||||
void CycleSetting(Setting setting);
|
||||
float GetSettingScale(Setting setting);
|
||||
|
||||
int PadCheckHandle(int handle);
|
||||
|
||||
int KYTY_SYSV_ABI PadInit();
|
||||
int KYTY_SYSV_ABI PadOpen(int user_id, int type, int index, const void* param);
|
||||
int KYTY_SYSV_ABI PadGetHandle(int user_id, int type, int index);
|
||||
int KYTY_SYSV_ABI PadClose(int handle);
|
||||
int KYTY_SYSV_ABI PadSetMotionSensorState(int handle, bool enable);
|
||||
int KYTY_SYSV_ABI PadSetAngularVelocityDeadbandState(int handle, bool enable);
|
||||
int KYTY_SYSV_ABI PadResetOrientation(int handle);
|
||||
|
||||
+17
-15
@@ -78,6 +78,8 @@ constexpr int SCE_FONT_TEXT_PARSER_RESULT_TERMINATE = 0;
|
||||
constexpr int SCE_FONT_TEXT_PARSER_RESULT_ERROR = -1;
|
||||
constexpr int SCE_FONT_WRITING_FORM_HORIZONTAL = 0x10;
|
||||
constexpr int FONT_BITMAP_MAX_DIM = 128;
|
||||
// TrueType glyphs are rasterized at the requested size; the limit only rejects absurd scales.
|
||||
constexpr int FONT_GLYPH_MAX_DIM = 4096;
|
||||
constexpr int FONT_ERROR_INVALID_PARAMETER = static_cast<int>(0x80460002u);
|
||||
constexpr int FONT_ERROR_INVALID_FONT_HANDLE = static_cast<int>(0x80460005u);
|
||||
constexpr int FONT_ERROR_NO_SUPPORT_CODE = static_cast<int>(0x80460041u);
|
||||
@@ -206,7 +208,7 @@ struct FontState {
|
||||
const uint8_t* ttf_data;
|
||||
uint32_t ttf_size;
|
||||
bool has_ttf;
|
||||
std::array<uint8_t, FONT_BITMAP_MAX_DIM * FONT_BITMAP_MAX_DIM> fallback_image;
|
||||
std::vector<uint8_t> fallback_image;
|
||||
FontTransImage trans_image;
|
||||
};
|
||||
|
||||
@@ -227,7 +229,7 @@ struct GlyphState {
|
||||
uint32_t code;
|
||||
int attribute;
|
||||
FontGlyphMetrics metrics;
|
||||
std::array<uint8_t, FONT_BITMAP_MAX_DIM * FONT_BITMAP_MAX_DIM> image;
|
||||
std::vector<uint8_t> image;
|
||||
FontTransImage trans_image;
|
||||
};
|
||||
|
||||
@@ -851,8 +853,8 @@ static bool get_stb_metrics(FontState* font, uint32_t code, FontGlyphMetrics* me
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool init_stb_image(std::array<uint8_t, FONT_BITMAP_MAX_DIM * FONT_BITMAP_MAX_DIM>* image,
|
||||
FontTransImage* trans_image, uint32_t code, FontState* font) {
|
||||
static bool init_stb_image(std::vector<uint8_t>* image, FontTransImage* trans_image, uint32_t code,
|
||||
FontState* font) {
|
||||
if (image == nullptr || trans_image == nullptr || !ensure_stb_font(font)) {
|
||||
return false;
|
||||
}
|
||||
@@ -868,12 +870,12 @@ static bool init_stb_image(std::array<uint8_t, FONT_BITMAP_MAX_DIM * FONT_BITMAP
|
||||
stbtt_GetCodepointBitmapBox(&font->font_info, static_cast<int>(code), scale_x, scale_y, &x0, &y0,
|
||||
&x1, &y1);
|
||||
|
||||
image->fill(0);
|
||||
|
||||
const auto width = static_cast<uint32_t>(std::clamp(x1 - x0, 0, FONT_BITMAP_MAX_DIM));
|
||||
const auto height = static_cast<uint32_t>(std::clamp(y1 - y0, 0, FONT_BITMAP_MAX_DIM));
|
||||
const auto width = static_cast<uint32_t>(std::clamp(x1 - x0, 0, FONT_GLYPH_MAX_DIM));
|
||||
const auto height = static_cast<uint32_t>(std::clamp(y1 - y0, 0, FONT_GLYPH_MAX_DIM));
|
||||
// Keep at least one byte so that blank glyphs still get a valid address.
|
||||
image->assign(std::max<size_t>(static_cast<size_t>(width) * height, 1), 0);
|
||||
trans_image->address = image->data();
|
||||
trans_image->width_byte = FONT_BITMAP_MAX_DIM;
|
||||
trans_image->width_byte = width;
|
||||
trans_image->image_width = width;
|
||||
trans_image->image_height = height;
|
||||
|
||||
@@ -882,7 +884,7 @@ static bool init_stb_image(std::array<uint8_t, FONT_BITMAP_MAX_DIM * FONT_BITMAP
|
||||
}
|
||||
|
||||
stbtt_MakeCodepointBitmap(&font->font_info, image->data(), static_cast<int>(width),
|
||||
static_cast<int>(height), FONT_BITMAP_MAX_DIM, scale_x, scale_y,
|
||||
static_cast<int>(height), static_cast<int>(width), scale_x, scale_y,
|
||||
static_cast<int>(code));
|
||||
|
||||
return true;
|
||||
@@ -939,8 +941,8 @@ static uint32_t normalize_bitmap_font_code(uint32_t code) {
|
||||
return static_cast<uint32_t>('?');
|
||||
}
|
||||
|
||||
static void init_image(std::array<uint8_t, FONT_BITMAP_MAX_DIM * FONT_BITMAP_MAX_DIM>* image,
|
||||
FontTransImage* trans_image, uint32_t code, const FontState* font) {
|
||||
static void init_image(std::vector<uint8_t>* image, FontTransImage* trans_image, uint32_t code,
|
||||
const FontState* font) {
|
||||
EXIT_NOT_IMPLEMENTED(image == nullptr);
|
||||
EXIT_NOT_IMPLEMENTED(trans_image == nullptr);
|
||||
|
||||
@@ -948,11 +950,11 @@ static void init_image(std::array<uint8_t, FONT_BITMAP_MAX_DIM * FONT_BITMAP_MAX
|
||||
return;
|
||||
}
|
||||
|
||||
image->fill(0);
|
||||
code = normalize_bitmap_font_code(code);
|
||||
|
||||
const auto width = static_cast<uint32_t>(scaled_font_width(font));
|
||||
const auto height = static_cast<uint32_t>(scaled_font_height(font));
|
||||
image->assign(static_cast<size_t>(width) * height, 0);
|
||||
#if LIBAVUTIL_VERSION_MAJOR < 61
|
||||
const auto* vga_font = avpriv_vga16_font;
|
||||
#else
|
||||
@@ -965,13 +967,13 @@ static void init_image(std::array<uint8_t, FONT_BITMAP_MAX_DIM * FONT_BITMAP_MAX
|
||||
for (uint32_t x = 0; x < width; x++) {
|
||||
const uint32_t src_x = std::min<uint32_t>((x * 8u) / width, 7u);
|
||||
if ((row & (0x80u >> src_x)) != 0) {
|
||||
(*image)[y * FONT_BITMAP_MAX_DIM + x] = 0xff;
|
||||
(*image)[y * width + x] = 0xff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trans_image->address = image->data();
|
||||
trans_image->width_byte = FONT_BITMAP_MAX_DIM;
|
||||
trans_image->width_byte = width;
|
||||
trans_image->image_width = width;
|
||||
trans_image->image_height = height;
|
||||
}
|
||||
|
||||
+10
-20
@@ -19,7 +19,7 @@ static int KYTY_SYSV_ABI PadSetVibrationMode(int handle, int mode) {
|
||||
"\t mode = %d\n",
|
||||
handle, mode);
|
||||
|
||||
return 0;
|
||||
return Controller::PadCheckHandle(handle);
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI PadSetVibrationTriggerEffectWeakWhileEmbeddedMicInUse(bool enabled) {
|
||||
@@ -66,11 +66,10 @@ static int KYTY_SYSV_ABI
|
||||
PadDeviceClassGetExtendedInformation(int handle, PadDeviceClassExtendedInformation* info) {
|
||||
PRINT_NAME();
|
||||
|
||||
constexpr int pad_error_invalid_handle = -2137915389; /* 0x80920003 */
|
||||
constexpr int pad_error_invalid_arg = -2137915391; /* 0x80920001 */
|
||||
constexpr int pad_error_invalid_arg = -2137915391; /* 0x80920001 */
|
||||
|
||||
if (handle != 1) {
|
||||
return pad_error_invalid_handle;
|
||||
if (const auto error = Controller::PadCheckHandle(handle); error != OK) {
|
||||
return error;
|
||||
}
|
||||
if (info == nullptr) {
|
||||
return pad_error_invalid_arg;
|
||||
@@ -85,16 +84,15 @@ static int KYTY_SYSV_ABI PadDeviceClassParseData(int handle, const Controller::P
|
||||
PadDeviceClassData* class_data) {
|
||||
PRINT_NAME();
|
||||
|
||||
constexpr int pad_error_invalid_handle = -2137915389; /* 0x80920003 */
|
||||
constexpr int pad_error_invalid_arg = -2137915391; /* 0x80920001 */
|
||||
constexpr int pad_error_invalid_arg = -2137915391; /* 0x80920001 */
|
||||
|
||||
LOGF("\t handle = %d\n"
|
||||
"\t data = 0x%016" PRIx64 "\n"
|
||||
"\t class_data = 0x%016" PRIx64 "\n",
|
||||
handle, reinterpret_cast<uint64_t>(data), reinterpret_cast<uint64_t>(class_data));
|
||||
|
||||
if (handle != 1) {
|
||||
return pad_error_invalid_handle;
|
||||
if (const auto error = Controller::PadCheckHandle(handle); error != OK) {
|
||||
return error;
|
||||
}
|
||||
if (data == nullptr || class_data == nullptr) {
|
||||
return pad_error_invalid_arg;
|
||||
@@ -122,15 +120,7 @@ static int KYTY_SYSV_ABI PadSetTiltCorrectionState(int handle, bool enabled) {
|
||||
"\t enabled = %d\n",
|
||||
handle, enabled ? 1 : 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI PadClose(int handle) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t handle = %d\n", handle);
|
||||
|
||||
return OK;
|
||||
return Controller::PadCheckHandle(handle);
|
||||
}
|
||||
|
||||
// PPSA02385
|
||||
@@ -154,7 +144,7 @@ static int KYTY_SYSV_ABI PadGetExtControllerInformationStub(int handle, void* in
|
||||
"\t info = 0x%016" PRIx64 "\n",
|
||||
handle, reinterpret_cast<uint64_t>(info));
|
||||
|
||||
return OK;
|
||||
return Controller::PadCheckHandle(handle);
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI PadUnknownN3kSX62fgNo(uint64_t arg0, uint64_t arg1, uint64_t arg2,
|
||||
@@ -197,7 +187,7 @@ LIB_DEFINE(InitPad_1) {
|
||||
LIB_FUNC("znaWI0gpuo8", Controller::PadGetTriggerEffectState);
|
||||
LIB_FUNC("DscD1i9HX1w", Controller::PadResetLightBar);
|
||||
LIB_FUNC("RR4novUEENY", Controller::PadSetLightBar);
|
||||
LIB_FUNC("6ncge5+l5Qs", PadClose);
|
||||
LIB_FUNC("6ncge5+l5Qs", Controller::PadClose);
|
||||
LIB_FUNC("n3kSX62fgNo", PadUnknownN3kSX62fgNo);
|
||||
}
|
||||
|
||||
|
||||
@@ -110,6 +110,8 @@ struct Controller {
|
||||
now = 1000;
|
||||
haptics_handles_rumble = false;
|
||||
Initialize();
|
||||
Check(PadInit() == 0 && PadOpen(Config::GetUserId(), 0, 0, nullptr) == 1,
|
||||
"the standard controller port did not open");
|
||||
Connect(1);
|
||||
Check(GetSettingScale(Setting::SpeakerVolume) ==
|
||||
Config::GetControllerSpeakerVolume() / 50.0f &&
|
||||
@@ -143,6 +145,54 @@ void SetRumble(uint8_t large, uint8_t small) {
|
||||
Check(PadSetVibration(1, ¶m) == 0, "vibration request failed");
|
||||
}
|
||||
|
||||
void TestPadPortOwnership() {
|
||||
Initialize();
|
||||
const int user = Config::GetUserId();
|
||||
constexpr auto not_initialized = static_cast<int32_t>(0x80920005u);
|
||||
constexpr auto already_opened = static_cast<int32_t>(0x80920004u);
|
||||
constexpr auto invalid_handle = static_cast<int32_t>(0x80920003u);
|
||||
constexpr auto no_handle = static_cast<int32_t>(0x80920008u);
|
||||
PadData data {};
|
||||
Check(PadOpen(user, 0, 0, nullptr) == not_initialized &&
|
||||
PadGetHandle(user, 0, 0) == not_initialized &&
|
||||
PadReadState(1, &data) == not_initialized,
|
||||
"an uninitialized library exposed a controller port");
|
||||
Check(PadInit() == 0 && PadGetHandle(user, 0, 0) == no_handle,
|
||||
"initializing the library opened a controller port");
|
||||
const int handle = PadOpen(user, 0, 0, nullptr);
|
||||
Check(handle == 1 && PadInit() == 0 && PadGetHandle(user, 0, 0) == handle,
|
||||
"reinitializing the library lost the open port");
|
||||
for (int duplicate = 0; duplicate < 4; duplicate++) {
|
||||
const int rejected = PadOpen(user, 0, 0, nullptr);
|
||||
Check(rejected == already_opened,
|
||||
"opening one pad five times exposed duplicate connected controllers");
|
||||
Check(PadClose(rejected) == invalid_handle && PadGetHandle(user, 0, 0) == handle,
|
||||
"closing a rejected duplicate released the original owner");
|
||||
}
|
||||
Check(PadGetHandle(user + 1, 0, 0) == no_handle &&
|
||||
PadGetHandle(user, 2, 0) == no_handle && PadGetHandle(user, 0, 1) == no_handle,
|
||||
"a different port tuple aliased the open standard pad");
|
||||
SetButton(HOST_INPUT_CONTROLLER_ID, PAD_BUTTON_CROSS, true);
|
||||
Check(PadReadState(handle, &data) == 0 && data.connected &&
|
||||
data.buttons == PAD_BUTTON_CROSS,
|
||||
"keyboard Cross did not reach the owned port");
|
||||
SetButton(HOST_INPUT_CONTROLLER_ID, PAD_BUTTON_CROSS, false);
|
||||
Connect(1);
|
||||
SetButton(1, PAD_BUTTON_CROSS, true);
|
||||
Check(PadReadState(handle, &data) == 0 && data.buttons == PAD_BUTTON_CROSS,
|
||||
"the physical controller did not share the owned port");
|
||||
Disconnect(1);
|
||||
Check(PadGetHandle(user, 0, 0) == handle && PadOpen(user, 0, 0, nullptr) == already_opened,
|
||||
"host disconnection released guest port ownership");
|
||||
Check(PadClose(handle) == 0 && PadGetHandle(user, 0, 0) == no_handle &&
|
||||
PadReadState(handle, &data) == invalid_handle &&
|
||||
PadRead(handle, &data, 1) == invalid_handle && PadClose(handle) == invalid_handle,
|
||||
"a closed port retained a usable handle");
|
||||
Check(PadOpen(user, 0, 0, nullptr) == handle && PadReadState(handle, &data) == 0,
|
||||
"a closed port could not reopen");
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
void TestSettingCycles() {
|
||||
Controller controller;
|
||||
for (auto setting:
|
||||
@@ -503,6 +553,7 @@ void TestTriggerEffectState() {
|
||||
|
||||
int main() {
|
||||
Config::Initialize();
|
||||
TestPadPortOwnership();
|
||||
TestSettingCycles();
|
||||
TestGlobalControllerLevels();
|
||||
// Each following test initializes another controller and requires strong defaults.
|
||||
|
||||
@@ -1353,6 +1353,7 @@ struct GraphicsCase {
|
||||
std::vector<u32> push_constants;
|
||||
std::vector<u32> pixel_interpolator_settings;
|
||||
bool pixel_no_perspective = false;
|
||||
bool provoking_vtx_last = false;
|
||||
std::vector<u32> vertices;
|
||||
bool pixel_ancillary = false;
|
||||
bool pixel_front_face = false;
|
||||
@@ -1449,6 +1450,20 @@ void CheckPixelParameterAliases() {
|
||||
pixel.interpolator_settings[1] = 0u;
|
||||
pixel.interpolator_settings[2] = 1u;
|
||||
const std::array<uint32_t, 3> active = {0, 1, 2};
|
||||
Require(name, "ordinary mixed aliases",
|
||||
ShaderPixelParameterLocation(pixel, active, 0) == 0u &&
|
||||
ShaderPixelParameterLocation(pixel, active, 1) == 0u &&
|
||||
ShaderPixelParameterLocation(pixel, active, 2) == 1u,
|
||||
"flat/smooth aliases must retain the real vertex export location");
|
||||
std::vector<uint32_t> ordinary_key, rectangle_key, provoking_key;
|
||||
BuildStageStaticKey(pixel, ordinary_key);
|
||||
pixel.parameter_mode = ShaderPixelParameterMode::LastVertex;
|
||||
BuildStageStaticKey(pixel, provoking_key);
|
||||
pixel.parameter_mode = ShaderPixelParameterMode::Rectangle;
|
||||
BuildStageStaticKey(pixel, rectangle_key);
|
||||
Require(name, "interpolation specialization",
|
||||
ordinary_key != rectangle_key && ordinary_key != provoking_key,
|
||||
"rectangle and provoking-vertex modes must participate in the shader key");
|
||||
Require(name, "reserved physical locations",
|
||||
ShaderPixelParameterLocation(pixel, active, 0) == 0u &&
|
||||
ShaderPixelParameterLocation(pixel, active, 1) == 2u &&
|
||||
@@ -1473,6 +1488,7 @@ void CheckRectListShaders() {
|
||||
vertex.stage.program = &vertex_program;
|
||||
vertex.stage.resources = &empty_snapshot;
|
||||
ShaderPixelInputInfo pixel{};
|
||||
pixel.parameter_mode = ShaderPixelParameterMode::Rectangle;
|
||||
pixel.input_num = 2;
|
||||
pixel.interpolator_settings[0] = 0x400u;
|
||||
pixel.interpolator_settings[1] = 0;
|
||||
@@ -1774,6 +1790,8 @@ CompiledShader CompileFragmentCase(const GraphicsCase &test) {
|
||||
? 1u
|
||||
: static_cast<u32>(test.pixel_interpolator_settings.size());
|
||||
pixel_info.ps_no_perspective = test.pixel_no_perspective;
|
||||
pixel_info.parameter_mode = test.provoking_vtx_last ? ShaderPixelParameterMode::LastVertex
|
||||
: ShaderPixelParameterMode::FirstVertex;
|
||||
pixel_info.ps_ancillary = test.pixel_ancillary;
|
||||
pixel_info.ps_front_face = test.pixel_front_face;
|
||||
pixel_info.ps_pos_w = test.pixel_position_w;
|
||||
@@ -16928,6 +16946,12 @@ public:
|
||||
raster.frontFace = vk::FrontFace::eCounterClockwise;
|
||||
raster.lineWidth = 1.0f;
|
||||
|
||||
vk::PipelineRasterizationProvokingVertexStateCreateInfoEXT provoking_vertex{};
|
||||
if (test.provoking_vtx_last) {
|
||||
provoking_vertex.provokingVertexMode = vk::ProvokingVertexModeEXT::eLastVertex;
|
||||
raster.pNext = &provoking_vertex;
|
||||
}
|
||||
|
||||
vk::PipelineMultisampleStateCreateInfo multisample{};
|
||||
multisample.sType = vk::StructureType::ePipelineMultisampleStateCreateInfo;
|
||||
multisample.rasterizationSamples = test.samples;
|
||||
@@ -22118,6 +22142,75 @@ TestCase Vop1SdwaNotPartialSourcesAndDestinations() {
|
||||
return test;
|
||||
}
|
||||
|
||||
TestCase Vop2SdwaBitwiseByteDestinations(u32 wave_size) {
|
||||
using O = ShaderOpcode;
|
||||
// Low result bytes of AND, OR, XOR, XNOR for the two runtime inputs.
|
||||
constexpr std::array<u32, 4> result_bytes{0xa4u, 0xbeu, 0x1au, 0xe5u};
|
||||
constexpr std::array<u32, 4> alias_expected{
|
||||
0xc350e5a6u, 0xc3fce5a6u, 0xc3ace5a6u, 0xc353e5a6u};
|
||||
constexpr u32 sentinel = 0xa1b2c3d4u;
|
||||
TestCase test;
|
||||
test.name = wave_size == 64 ? "Vop2SdwaBitwiseByteDestinationsWave64"
|
||||
: "Vop2SdwaBitwiseByteDestinationsWave32";
|
||||
test.initial = {0xc3d4e5a6u, 0x9b785abcu};
|
||||
test.expected = test.initial;
|
||||
auto &code = test.code;
|
||||
const auto store = [&](u32 reg, u32 expected) {
|
||||
AppendStoreVgpr(&code, reg, static_cast<u32>(test.expected.size()));
|
||||
test.expected.push_back(expected);
|
||||
};
|
||||
for (u32 op = 0; op < 4; ++op) {
|
||||
AppendVMovU32(&code, 30, 0);
|
||||
AppendBufferLoadDword(&code, 12, 30);
|
||||
AppendVMovU32(&code, 30, 4);
|
||||
AppendBufferLoadDword(&code, 13, 30);
|
||||
for (u32 selector = 0; selector < 4; ++selector) {
|
||||
for (u32 unused = 0; unused < 3; ++unused) {
|
||||
AppendVMovLiteral(&code, 26, sentinel);
|
||||
code.push_back(EncodeVop2(0x1b + op, 26, 249, 13));
|
||||
code.push_back(EncodeVop2Sdwa(12, selector, unused));
|
||||
// RDNA2 table 88: pad, sign extend above/zero below, or preserve.
|
||||
const u32 shift = selector * 8u;
|
||||
u32 expected = result_bytes[op] << shift;
|
||||
if (unused == 1 && (result_bytes[op] & 0x80u) != 0) {
|
||||
expected = (0xffffff00u | result_bytes[op]) << shift;
|
||||
} else if (unused == 2) {
|
||||
expected |= sentinel & ~(0xffu << shift);
|
||||
}
|
||||
store(26, expected);
|
||||
}
|
||||
}
|
||||
// Read source byte2 and word1 before overwriting source0's byte2.
|
||||
code.push_back(EncodeVop2(0x1b + op, 12, 249, 13));
|
||||
code.push_back(EncodeVop2Sdwa(12, 2, 2, 2, 5));
|
||||
store(12, alias_expected[op]);
|
||||
// Source1 may also alias the destination.
|
||||
AppendVMovU32(&code, 30, 0);
|
||||
AppendBufferLoadDword(&code, 12, 30);
|
||||
code.push_back(EncodeVop2(0x1b + op, 13, 249, 13));
|
||||
code.push_back(EncodeVop2Sdwa(12, 1, 2));
|
||||
store(13, 0x9b7800bcu | (result_bytes[op] << 8u));
|
||||
for (u32 unused = 0; unused < 3; ++unused) {
|
||||
AppendVMovLiteral(&code, 26, sentinel);
|
||||
code.push_back(EncodeSMovB32(126, InlineU32(0)));
|
||||
code.push_back(EncodeVop2(0x1b + op, 26, 249, 13));
|
||||
code.push_back(EncodeVop2Sdwa(12, 2, unused));
|
||||
code.push_back(EncodeSMovB32(126, InlineU32(1)));
|
||||
store(26, sentinel);
|
||||
}
|
||||
}
|
||||
AppendEnd(&code);
|
||||
test.initial.resize(test.expected.size());
|
||||
test.opcodes = {O::V_MOV_B32, O::S_MOV_B32, O::BUFFER_LOAD_DWORD,
|
||||
O::V_AND_B32, O::V_OR_B32, O::V_XOR_B32, O::V_XNOR_B32,
|
||||
O::BUFFER_STORE_DWORD, O::S_ENDPGM};
|
||||
test.required_spirv = {"OpBitwiseAnd", "OpBitwiseOr", "OpBitwiseXor", "OpNot",
|
||||
"OpBitFieldInsert", "OpBitFieldSExtract"};
|
||||
test.compute_info.wave_size = wave_size;
|
||||
test.has_compute_info = true;
|
||||
return test;
|
||||
}
|
||||
|
||||
TestCase Vop1SdwaMovByteDestinations() {
|
||||
using O = ShaderOpcode;
|
||||
|
||||
@@ -35871,6 +35964,38 @@ GraphicsCase GraphicsSmoothRawInputAlias() {
|
||||
return test;
|
||||
}
|
||||
|
||||
GraphicsCase GraphicsSmoothFlatInputAlias(bool flat_first, bool provoking_last = false) {
|
||||
auto test = GraphicsSmoothRawInputAlias();
|
||||
test.name = provoking_last
|
||||
? (flat_first ? "GraphicsFlatSmoothAliasLast" : "GraphicsSmoothFlatAliasLast")
|
||||
: (flat_first ? "GraphicsFlatSmoothInputAlias" : "GraphicsSmoothFlatInputAlias");
|
||||
test.pixel_custom_interpolation_mask = 0;
|
||||
test.provoking_vtx_last = provoking_last;
|
||||
test.pixel_interpolator_settings = flat_first ? std::vector<u32>{0x400u, 0u}
|
||||
: std::vector<u32>{0u, 0x400u};
|
||||
const u32 smooth = flat_first ? 1u : 0u;
|
||||
const u32 flat = smooth ^ 1u;
|
||||
// One export carries smooth values (2,4,8) and packed light IDs (5,7,11).
|
||||
// Flat P0 preserves the ID bits; flat P1/P2 uses the same provoking vertex.
|
||||
test.vertices[4] = 0x3f800005u;
|
||||
test.vertices[10] = 0x3f800007u;
|
||||
test.vertices[16] = 0x3f80000bu;
|
||||
test.fragment_code = {EncodeVintrp(0x00, 0, smooth, 1, 0),
|
||||
EncodeVintrp(0x01, 0, smooth, 1, 1),
|
||||
EncodeVintrp(0x02, 1, flat, 2, 2),
|
||||
EncodeVop2(0x1b, 1, InlineU32(63), 1),
|
||||
EncodeVop1(0x06, 1, Vgpr(1)),
|
||||
EncodeVintrp(0x00, 2, flat, 1, 0),
|
||||
EncodeVintrp(0x01, 2, flat, 1, 1),
|
||||
EncodeExp0(0x00, 0xf), EncodeExp1(0, 1, 2, 0)};
|
||||
AppendEnd(&test.fragment_code);
|
||||
test.expected_pixel = {0x40700000u, provoking_last ? 0x41300000u : 0x40a00000u,
|
||||
provoking_last ? 0x41000000u : 0x40000000u, 0x40700000u};
|
||||
test.opcodes.insert(test.opcodes.end(),
|
||||
{ShaderOpcode::V_AND_B32, ShaderOpcode::V_CVT_F32_U32});
|
||||
return test;
|
||||
}
|
||||
|
||||
GraphicsCase GraphicsAncillaryLayer(bool front_face) {
|
||||
GraphicsCase test;
|
||||
test.name = front_face ? "GraphicsAncillaryAfterFrontFace" : "GraphicsAncillaryLayer";
|
||||
@@ -36278,6 +36403,8 @@ std::vector<TestCase> MakeCases() {
|
||||
AddCase(Vop1SdwaNotCapturedByte0Source);
|
||||
AddCase(Vop1SdwaNotPreservesHighWordDestination);
|
||||
AddCase(Vop1SdwaNotPartialSourcesAndDestinations);
|
||||
cases.push_back(Vop2SdwaBitwiseByteDestinations(32));
|
||||
cases.push_back(Vop2SdwaBitwiseByteDestinations(64));
|
||||
AddCase(Vop1SdwaMovByteDestinations);
|
||||
cases.push_back(Vop1SdwaMovByteSources(32));
|
||||
cases.push_back(Vop1SdwaMovByteSources(64));
|
||||
@@ -36714,6 +36841,10 @@ std::vector<GraphicsCase> MakeGraphicsCases() {
|
||||
GraphicsPackedHalfInputAlias(false),
|
||||
GraphicsPackedHalfInputAlias(true),
|
||||
GraphicsSmoothRawInputAlias(),
|
||||
GraphicsSmoothFlatInputAlias(false),
|
||||
GraphicsSmoothFlatInputAlias(true),
|
||||
GraphicsSmoothFlatInputAlias(false, true),
|
||||
GraphicsSmoothFlatInputAlias(true, true),
|
||||
GraphicsAncillaryLayer(false),
|
||||
GraphicsAncillaryLayer(true),
|
||||
GraphicsAncillarySampleId(),
|
||||
@@ -42196,6 +42327,11 @@ int main(int argc, char **argv) {
|
||||
RunGraphicsCase(&vulkan, GraphicsPackedHalfInputAlias(false));
|
||||
RunGraphicsCase(&vulkan, GraphicsPackedHalfInputAlias(true));
|
||||
RunGraphicsCase(&vulkan, GraphicsSmoothRawInputAlias());
|
||||
RunGraphicsCase(&vulkan, GraphicsSmoothFlatInputAlias(false));
|
||||
RunGraphicsCase(&vulkan, GraphicsSmoothFlatInputAlias(true));
|
||||
RunGraphicsCase(&vulkan, GraphicsSmoothFlatInputAlias(false, true));
|
||||
RunGraphicsCase(&vulkan, GraphicsSmoothFlatInputAlias(true, true));
|
||||
RunGraphicsCase(&vulkan, GraphicsFlatInterpolatorExport());
|
||||
return 0;
|
||||
}
|
||||
if (argc == 2 && std::strcmp(argv[1], "--clip-control-only") == 0) {
|
||||
@@ -42350,6 +42486,13 @@ int main(int argc, char **argv) {
|
||||
RunCase(&vulkan, ScalarZeroShiftWithRuntimeCount());
|
||||
return 0;
|
||||
}
|
||||
if (argc == 2 && std::strcmp(argv[1], "--sdwa-bitwise-only") == 0) {
|
||||
VulkanHarness vulkan;
|
||||
RunCase(&vulkan, Vop2SdwaBitwiseByteDestinations(32));
|
||||
RunCase(&vulkan, Vop2SdwaBitwiseByteDestinations(64));
|
||||
RunCase(&vulkan, Vop1SdwaNotPartialSourcesAndDestinations());
|
||||
return 0;
|
||||
}
|
||||
if (argc == 2 && std::strcmp(argv[1], "--sdwa-mov-only") == 0) {
|
||||
VulkanHarness vulkan;
|
||||
RunCase(&vulkan, Vop1SdwaMovByteDestinations());
|
||||
|
||||
Reference in New Issue
Block a user