Compare commits

..

1 Commits

Author SHA1 Message Date
GPUCode
d42d094bc6 pica_core: Propogate vertex uniforms to geometry setup when not in exclusive mode 2024-01-24 04:40:31 +02:00
4 changed files with 97 additions and 115 deletions

View File

@@ -10,6 +10,7 @@
#include "core/core.h" #include "core/core.h"
#include "core/core_timing.h" #include "core/core_timing.h"
#include "core/frontend/camera/factory.h" #include "core/frontend/camera/factory.h"
#include "core/hle/ipc.h"
#include "core/hle/ipc_helpers.h" #include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/event.h" #include "core/hle/kernel/event.h"
#include "core/hle/kernel/process.h" #include "core/hle/kernel/process.h"
@@ -76,10 +77,10 @@ constexpr std::array<int, 13> LATENCY_BY_FRAME_RATE{{
33, // Rate_30_To_10 33, // Rate_30_To_10
}}; }};
constexpr Result ResultInvalidEnumValue(ErrorDescription::InvalidEnumValue, ErrorModule::CAM, const Result ERROR_INVALID_ENUM_VALUE(ErrorDescription::InvalidEnumValue, ErrorModule::CAM,
ErrorSummary::InvalidArgument, ErrorLevel::Usage); ErrorSummary::InvalidArgument, ErrorLevel::Usage);
constexpr Result ResultOutOfRange(ErrorDescription::OutOfRange, ErrorModule::CAM, const Result ERROR_OUT_OF_RANGE(ErrorDescription::OutOfRange, ErrorModule::CAM,
ErrorSummary::InvalidArgument, ErrorLevel::Usage); ErrorSummary::InvalidArgument, ErrorLevel::Usage);
void Module::PortConfig::Clear() { void Module::PortConfig::Clear() {
completion_event->Clear(); completion_event->Clear();
@@ -260,32 +261,27 @@ void Module::Interface::StartCapture(Kernel::HLERequestContext& ctx) {
if (port_select.IsValid()) { if (port_select.IsValid()) {
for (int i : port_select) { for (int i : port_select) {
auto& port = cam->ports[i]; if (!cam->ports[i].is_busy) {
if (port.is_busy) { if (!cam->ports[i].is_active) {
// This doesn't return an error, but seems to put the camera in an undefined
// state
LOG_ERROR(Service_CAM, "port {} hasn't been activated", i);
} else {
cam->cameras[cam->ports[i].camera_id].impl->StartCapture();
cam->ports[i].is_busy = true;
if (cam->ports[i].is_pending_receiving) {
cam->ports[i].is_pending_receiving = false;
cam->StartReceiving(i);
}
}
} else {
LOG_WARNING(Service_CAM, "port {} already started", i); LOG_WARNING(Service_CAM, "port {} already started", i);
continue;
}
if (!port.is_active) {
// This doesn't return an error, but seems to put the camera in an undefined
// state
LOG_ERROR(Service_CAM, "port {} hasn't been activated", i);
continue;
}
auto& camera = cam->cameras[port.camera_id];
if (!camera.impl) {
cam->LoadCameraImplementation(camera, port.camera_id);
}
camera.impl->StartCapture();
port.is_busy = true;
if (port.is_pending_receiving) {
port.is_pending_receiving = false;
cam->StartReceiving(i);
} }
} }
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
} else { } else {
LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val); LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val);
rb.Push(ResultInvalidEnumValue); rb.Push(ERROR_INVALID_ENUM_VALUE);
} }
LOG_DEBUG(Service_CAM, "called, port_select={}", port_select.m_val); LOG_DEBUG(Service_CAM, "called, port_select={}", port_select.m_val);
@@ -310,7 +306,7 @@ void Module::Interface::StopCapture(Kernel::HLERequestContext& ctx) {
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
} else { } else {
LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val); LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val);
rb.Push(ResultInvalidEnumValue); rb.Push(ERROR_INVALID_ENUM_VALUE);
} }
LOG_DEBUG(Service_CAM, "called, port_select={}", port_select.m_val); LOG_DEBUG(Service_CAM, "called, port_select={}", port_select.m_val);
@@ -332,7 +328,7 @@ void Module::Interface::IsBusy(Kernel::HLERequestContext& ctx) {
rb.Push(is_busy); rb.Push(is_busy);
} else { } else {
LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val); LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val);
rb.Push(ResultInvalidEnumValue); rb.Push(ERROR_INVALID_ENUM_VALUE);
rb.Skip(1, false); rb.Skip(1, false);
} }
@@ -360,7 +356,7 @@ void Module::Interface::GetVsyncInterruptEvent(Kernel::HLERequestContext& ctx) {
rb.PushCopyObjects(cam->ports[port].vsync_interrupt_event); rb.PushCopyObjects(cam->ports[port].vsync_interrupt_event);
} else { } else {
LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val); LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val);
rb.Push(ResultInvalidEnumValue); rb.Push(ERROR_INVALID_ENUM_VALUE);
rb.PushCopyObjects<Kernel::Object>(nullptr); rb.PushCopyObjects<Kernel::Object>(nullptr);
} }
@@ -378,7 +374,7 @@ void Module::Interface::GetBufferErrorInterruptEvent(Kernel::HLERequestContext&
rb.PushCopyObjects(cam->ports[port].buffer_error_interrupt_event); rb.PushCopyObjects(cam->ports[port].buffer_error_interrupt_event);
} else { } else {
LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val); LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val);
rb.Push(ResultInvalidEnumValue); rb.Push(ERROR_INVALID_ENUM_VALUE);
rb.PushCopyObjects<Kernel::Object>(nullptr); rb.PushCopyObjects<Kernel::Object>(nullptr);
} }
@@ -413,7 +409,7 @@ void Module::Interface::SetReceiving(Kernel::HLERequestContext& ctx) {
rb.PushCopyObjects(port.completion_event); rb.PushCopyObjects(port.completion_event);
} else { } else {
LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val); LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val);
rb.Push(ResultInvalidEnumValue); rb.Push(ERROR_INVALID_ENUM_VALUE);
rb.PushCopyObjects<Kernel::Object>(nullptr); rb.PushCopyObjects<Kernel::Object>(nullptr);
} }
@@ -433,7 +429,7 @@ void Module::Interface::IsFinishedReceiving(Kernel::HLERequestContext& ctx) {
rb.Push(!is_busy); rb.Push(!is_busy);
} else { } else {
LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val); LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val);
rb.Push(ResultInvalidEnumValue); rb.Push(ERROR_INVALID_ENUM_VALUE);
rb.Skip(1, false); rb.Skip(1, false);
} }
@@ -455,7 +451,7 @@ void Module::Interface::SetTransferLines(Kernel::HLERequestContext& ctx) {
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
} else { } else {
LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val); LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val);
rb.Push(ResultInvalidEnumValue); rb.Push(ERROR_INVALID_ENUM_VALUE);
} }
LOG_WARNING(Service_CAM, "(STUBBED) called, port_select={}, lines={}, width={}, height={}", LOG_WARNING(Service_CAM, "(STUBBED) called, port_select={}, lines={}, width={}, height={}",
@@ -473,7 +469,7 @@ void Module::Interface::GetMaxLines(Kernel::HLERequestContext& ctx) {
constexpr u32 MIN_TRANSFER_UNIT = 256; constexpr u32 MIN_TRANSFER_UNIT = 256;
constexpr u32 MAX_BUFFER_SIZE = 2560; constexpr u32 MAX_BUFFER_SIZE = 2560;
if (width * height * 2 % MIN_TRANSFER_UNIT != 0) { if (width * height * 2 % MIN_TRANSFER_UNIT != 0) {
rb.Push(ResultOutOfRange); rb.Push(ERROR_OUT_OF_RANGE);
rb.Skip(1, false); rb.Skip(1, false);
} else { } else {
u32 lines = MAX_BUFFER_SIZE / width; u32 lines = MAX_BUFFER_SIZE / width;
@@ -484,7 +480,7 @@ void Module::Interface::GetMaxLines(Kernel::HLERequestContext& ctx) {
while (height % lines != 0 || (lines * width * 2 % MIN_TRANSFER_UNIT != 0)) { while (height % lines != 0 || (lines * width * 2 % MIN_TRANSFER_UNIT != 0)) {
--lines; --lines;
if (lines == 0) { if (lines == 0) {
result = ResultOutOfRange; result = ERROR_OUT_OF_RANGE;
break; break;
} }
} }
@@ -510,7 +506,7 @@ void Module::Interface::SetTransferBytes(Kernel::HLERequestContext& ctx) {
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
} else { } else {
LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val); LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val);
rb.Push(ResultInvalidEnumValue); rb.Push(ERROR_INVALID_ENUM_VALUE);
} }
LOG_WARNING(Service_CAM, "(STUBBED)called, port_select={}, bytes={}, width={}, height={}", LOG_WARNING(Service_CAM, "(STUBBED)called, port_select={}, bytes={}, width={}, height={}",
@@ -528,7 +524,7 @@ void Module::Interface::GetTransferBytes(Kernel::HLERequestContext& ctx) {
rb.Push(cam->ports[port].transfer_bytes); rb.Push(cam->ports[port].transfer_bytes);
} else { } else {
LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val); LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val);
rb.Push(ResultInvalidEnumValue); rb.Push(ERROR_INVALID_ENUM_VALUE);
rb.Skip(1, false); rb.Skip(1, false);
} }
@@ -546,7 +542,7 @@ void Module::Interface::GetMaxBytes(Kernel::HLERequestContext& ctx) {
constexpr u32 MIN_TRANSFER_UNIT = 256; constexpr u32 MIN_TRANSFER_UNIT = 256;
constexpr u32 MAX_BUFFER_SIZE = 2560; constexpr u32 MAX_BUFFER_SIZE = 2560;
if (width * height * 2 % MIN_TRANSFER_UNIT != 0) { if (width * height * 2 % MIN_TRANSFER_UNIT != 0) {
rb.Push(ResultOutOfRange); rb.Push(ERROR_OUT_OF_RANGE);
rb.Skip(1, false); rb.Skip(1, false);
} else { } else {
u32 bytes = MAX_BUFFER_SIZE; u32 bytes = MAX_BUFFER_SIZE;
@@ -575,7 +571,7 @@ void Module::Interface::SetTrimming(Kernel::HLERequestContext& ctx) {
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
} else { } else {
LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val); LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val);
rb.Push(ResultInvalidEnumValue); rb.Push(ERROR_INVALID_ENUM_VALUE);
} }
LOG_DEBUG(Service_CAM, "called, port_select={}, trim={}", port_select.m_val, trim); LOG_DEBUG(Service_CAM, "called, port_select={}, trim={}", port_select.m_val, trim);
@@ -592,7 +588,7 @@ void Module::Interface::IsTrimming(Kernel::HLERequestContext& ctx) {
rb.Push(cam->ports[port].is_trimming); rb.Push(cam->ports[port].is_trimming);
} else { } else {
LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val); LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val);
rb.Push(ResultInvalidEnumValue); rb.Push(ERROR_INVALID_ENUM_VALUE);
rb.Skip(1, false); rb.Skip(1, false);
} }
@@ -618,7 +614,7 @@ void Module::Interface::SetTrimmingParams(Kernel::HLERequestContext& ctx) {
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
} else { } else {
LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val); LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val);
rb.Push(ResultInvalidEnumValue); rb.Push(ERROR_INVALID_ENUM_VALUE);
} }
LOG_DEBUG(Service_CAM, "called, port_select={}, x0={}, y0={}, x1={}, y1={}", port_select.m_val, LOG_DEBUG(Service_CAM, "called, port_select={}, x0={}, y0={}, x1={}, y1={}", port_select.m_val,
@@ -639,7 +635,7 @@ void Module::Interface::GetTrimmingParams(Kernel::HLERequestContext& ctx) {
rb.Push(cam->ports[port].y1); rb.Push(cam->ports[port].y1);
} else { } else {
LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val); LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val);
rb.Push(ResultInvalidEnumValue); rb.Push(ERROR_INVALID_ENUM_VALUE);
rb.Skip(4, false); rb.Skip(4, false);
} }
@@ -665,7 +661,7 @@ void Module::Interface::SetTrimmingParamsCenter(Kernel::HLERequestContext& ctx)
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
} else { } else {
LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val); LOG_ERROR(Service_CAM, "invalid port_select={}", port_select.m_val);
rb.Push(ResultInvalidEnumValue); rb.Push(ERROR_INVALID_ENUM_VALUE);
} }
LOG_DEBUG(Service_CAM, "called, port_select={}, trim_w={}, trim_h={}, cam_w={}, cam_h={}", LOG_DEBUG(Service_CAM, "called, port_select={}, trim_w={}, trim_h={}, cam_w={}, cam_h={}",
@@ -691,7 +687,7 @@ void Module::Interface::Activate(Kernel::HLERequestContext& ctx) {
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
} else if (camera_select[0] && camera_select[1]) { } else if (camera_select[0] && camera_select[1]) {
LOG_ERROR(Service_CAM, "camera 0 and 1 can't be both activated"); LOG_ERROR(Service_CAM, "camera 0 and 1 can't be both activated");
rb.Push(ResultInvalidEnumValue); rb.Push(ERROR_INVALID_ENUM_VALUE);
} else { } else {
if (camera_select[0]) { if (camera_select[0]) {
cam->ActivatePort(0, 0); cam->ActivatePort(0, 0);
@@ -706,7 +702,7 @@ void Module::Interface::Activate(Kernel::HLERequestContext& ctx) {
} }
} else { } else {
LOG_ERROR(Service_CAM, "invalid camera_select={}", camera_select.m_val); LOG_ERROR(Service_CAM, "invalid camera_select={}", camera_select.m_val);
rb.Push(ResultInvalidEnumValue); rb.Push(ERROR_INVALID_ENUM_VALUE);
} }
LOG_DEBUG(Service_CAM, "called, camera_select={}", camera_select.m_val); LOG_DEBUG(Service_CAM, "called, camera_select={}", camera_select.m_val);
@@ -732,7 +728,7 @@ void Module::Interface::SwitchContext(Kernel::HLERequestContext& ctx) {
} else { } else {
LOG_ERROR(Service_CAM, "invalid camera_select={}, context_select={}", camera_select.m_val, LOG_ERROR(Service_CAM, "invalid camera_select={}, context_select={}", camera_select.m_val,
context_select.m_val); context_select.m_val);
rb.Push(ResultInvalidEnumValue); rb.Push(ERROR_INVALID_ENUM_VALUE);
} }
LOG_DEBUG(Service_CAM, "called, camera_select={}, context_select={}", camera_select.m_val, LOG_DEBUG(Service_CAM, "called, camera_select={}, context_select={}", camera_select.m_val,
@@ -742,29 +738,24 @@ void Module::Interface::SwitchContext(Kernel::HLERequestContext& ctx) {
void Module::Interface::FlipImage(Kernel::HLERequestContext& ctx) { void Module::Interface::FlipImage(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx); IPC::RequestParser rp(ctx);
const CameraSet camera_select(rp.Pop<u8>()); const CameraSet camera_select(rp.Pop<u8>());
const Flip flip = rp.PopEnum<Flip>(); const Flip flip = static_cast<Flip>(rp.Pop<u8>());
const ContextSet context_select(rp.Pop<u8>()); const ContextSet context_select(rp.Pop<u8>());
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
if (camera_select.IsValid() && context_select.IsValid()) { if (camera_select.IsValid() && context_select.IsValid()) {
for (int index : camera_select) { for (int camera : camera_select) {
auto& camera = cam->cameras[index];
for (int context : context_select) { for (int context : context_select) {
camera.contexts[context].flip = flip; cam->cameras[camera].contexts[context].flip = flip;
if (camera.current_context != context) { if (cam->cameras[camera].current_context == context) {
continue; cam->cameras[camera].impl->SetFlip(flip);
} }
if (!camera.impl) {
cam->LoadCameraImplementation(camera, index);
}
camera.impl->SetFlip(flip);
} }
} }
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
} else { } else {
LOG_ERROR(Service_CAM, "invalid camera_select={}, context_select={}", camera_select.m_val, LOG_ERROR(Service_CAM, "invalid camera_select={}, context_select={}", camera_select.m_val,
context_select.m_val); context_select.m_val);
rb.Push(ResultInvalidEnumValue); rb.Push(ERROR_INVALID_ENUM_VALUE);
} }
LOG_DEBUG(Service_CAM, "called, camera_select={}, flip={}, context_select={}", LOG_DEBUG(Service_CAM, "called, camera_select={}, flip={}, context_select={}",
@@ -785,24 +776,19 @@ void Module::Interface::SetDetailSize(Kernel::HLERequestContext& ctx) {
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
if (camera_select.IsValid() && context_select.IsValid()) { if (camera_select.IsValid() && context_select.IsValid()) {
for (int index : camera_select) { for (int camera : camera_select) {
auto& camera = cam->cameras[index];
for (int context : context_select) { for (int context : context_select) {
camera.contexts[context].resolution = resolution; cam->cameras[camera].contexts[context].resolution = resolution;
if (camera.current_context != context) { if (cam->cameras[camera].current_context == context) {
continue; cam->cameras[camera].impl->SetResolution(resolution);
} }
if (!camera.impl) {
cam->LoadCameraImplementation(camera, index);
}
camera.impl->SetResolution(resolution);
} }
} }
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
} else { } else {
LOG_ERROR(Service_CAM, "invalid camera_select={}, context_select={}", camera_select.m_val, LOG_ERROR(Service_CAM, "invalid camera_select={}, context_select={}", camera_select.m_val,
context_select.m_val); context_select.m_val);
rb.Push(ResultInvalidEnumValue); rb.Push(ERROR_INVALID_ENUM_VALUE);
} }
LOG_DEBUG(Service_CAM, LOG_DEBUG(Service_CAM,
@@ -820,24 +806,19 @@ void Module::Interface::SetSize(Kernel::HLERequestContext& ctx) {
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
if (camera_select.IsValid() && context_select.IsValid()) { if (camera_select.IsValid() && context_select.IsValid()) {
for (int index : camera_select) { for (int camera : camera_select) {
auto& camera = cam->cameras[index];
for (int context : context_select) { for (int context : context_select) {
camera.contexts[context].resolution = PRESET_RESOLUTION[size]; cam->cameras[camera].contexts[context].resolution = PRESET_RESOLUTION[size];
if (camera.current_context != context) { if (cam->cameras[camera].current_context == context) {
continue; cam->cameras[camera].impl->SetResolution(PRESET_RESOLUTION[size]);
} }
if (!camera.impl) {
cam->LoadCameraImplementation(camera, index);
}
camera.impl->SetResolution(PRESET_RESOLUTION[size]);
} }
} }
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
} else { } else {
LOG_ERROR(Service_CAM, "invalid camera_select={}, context_select={}", camera_select.m_val, LOG_ERROR(Service_CAM, "invalid camera_select={}, context_select={}", camera_select.m_val,
context_select.m_val); context_select.m_val);
rb.Push(ResultInvalidEnumValue); rb.Push(ERROR_INVALID_ENUM_VALUE);
} }
LOG_DEBUG(Service_CAM, "called, camera_select={}, size={}, context_select={}", LOG_DEBUG(Service_CAM, "called, camera_select={}, size={}, context_select={}",
@@ -847,22 +828,18 @@ void Module::Interface::SetSize(Kernel::HLERequestContext& ctx) {
void Module::Interface::SetFrameRate(Kernel::HLERequestContext& ctx) { void Module::Interface::SetFrameRate(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx); IPC::RequestParser rp(ctx);
const CameraSet camera_select(rp.Pop<u8>()); const CameraSet camera_select(rp.Pop<u8>());
const FrameRate frame_rate = rp.PopEnum<FrameRate>(); const FrameRate frame_rate = static_cast<FrameRate>(rp.Pop<u8>());
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
if (camera_select.IsValid()) { if (camera_select.IsValid()) {
for (int index : camera_select) { for (int camera : camera_select) {
auto& camera = cam->cameras[index]; cam->cameras[camera].frame_rate = frame_rate;
camera.frame_rate = frame_rate; cam->cameras[camera].impl->SetFrameRate(frame_rate);
if (!camera.impl) {
cam->LoadCameraImplementation(camera, index);
}
camera.impl->SetFrameRate(frame_rate);
} }
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
} else { } else {
LOG_ERROR(Service_CAM, "invalid camera_select={}", camera_select.m_val); LOG_ERROR(Service_CAM, "invalid camera_select={}", camera_select.m_val);
rb.Push(ResultInvalidEnumValue); rb.Push(ERROR_INVALID_ENUM_VALUE);
} }
LOG_WARNING(Service_CAM, "(STUBBED) called, camera_select={}, frame_rate={}", LOG_WARNING(Service_CAM, "(STUBBED) called, camera_select={}, frame_rate={}",
@@ -872,29 +849,24 @@ void Module::Interface::SetFrameRate(Kernel::HLERequestContext& ctx) {
void Module::Interface::SetEffect(Kernel::HLERequestContext& ctx) { void Module::Interface::SetEffect(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx); IPC::RequestParser rp(ctx);
const CameraSet camera_select(rp.Pop<u8>()); const CameraSet camera_select(rp.Pop<u8>());
const Effect effect = rp.PopEnum<Effect>(); const Effect effect = static_cast<Effect>(rp.Pop<u8>());
const ContextSet context_select(rp.Pop<u8>()); const ContextSet context_select(rp.Pop<u8>());
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
if (camera_select.IsValid() && context_select.IsValid()) { if (camera_select.IsValid() && context_select.IsValid()) {
for (int index : camera_select) { for (int camera : camera_select) {
auto& camera = cam->cameras[index];
for (int context : context_select) { for (int context : context_select) {
camera.contexts[context].effect = effect; cam->cameras[camera].contexts[context].effect = effect;
if (camera.current_context != context) { if (cam->cameras[camera].current_context == context) {
continue; cam->cameras[camera].impl->SetEffect(effect);
} }
if (!camera.impl) {
cam->LoadCameraImplementation(camera, index);
}
camera.impl->SetEffect(effect);
} }
} }
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
} else { } else {
LOG_ERROR(Service_CAM, "invalid camera_select={}, context_select={}", camera_select.m_val, LOG_ERROR(Service_CAM, "invalid camera_select={}, context_select={}", camera_select.m_val,
context_select.m_val); context_select.m_val);
rb.Push(ResultInvalidEnumValue); rb.Push(ERROR_INVALID_ENUM_VALUE);
} }
LOG_DEBUG(Service_CAM, "called, camera_select={}, effect={}, context_select={}", LOG_DEBUG(Service_CAM, "called, camera_select={}, effect={}, context_select={}",
@@ -904,29 +876,24 @@ void Module::Interface::SetEffect(Kernel::HLERequestContext& ctx) {
void Module::Interface::SetOutputFormat(Kernel::HLERequestContext& ctx) { void Module::Interface::SetOutputFormat(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx); IPC::RequestParser rp(ctx);
const CameraSet camera_select(rp.Pop<u8>()); const CameraSet camera_select(rp.Pop<u8>());
const OutputFormat format = rp.PopEnum<OutputFormat>(); const OutputFormat format = static_cast<OutputFormat>(rp.Pop<u8>());
const ContextSet context_select(rp.Pop<u8>()); const ContextSet context_select(rp.Pop<u8>());
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
if (camera_select.IsValid() && context_select.IsValid()) { if (camera_select.IsValid() && context_select.IsValid()) {
for (int index : camera_select) { for (int camera : camera_select) {
auto& camera = cam->cameras[index];
for (int context : context_select) { for (int context : context_select) {
camera.contexts[context].format = format; cam->cameras[camera].contexts[context].format = format;
if (camera.current_context != context) { if (cam->cameras[camera].current_context == context) {
continue; cam->cameras[camera].impl->SetFormat(format);
} }
if (!camera.impl) {
cam->LoadCameraImplementation(camera, index);
}
camera.impl->SetFormat(format);
} }
} }
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
} else { } else {
LOG_ERROR(Service_CAM, "invalid camera_select={}, context_select={}", camera_select.m_val, LOG_ERROR(Service_CAM, "invalid camera_select={}, context_select={}", camera_select.m_val,
context_select.m_val); context_select.m_val);
rb.Push(ResultInvalidEnumValue); rb.Push(ERROR_INVALID_ENUM_VALUE);
} }
LOG_DEBUG(Service_CAM, "called, camera_select={}, format={}, context_select={}", LOG_DEBUG(Service_CAM, "called, camera_select={}, format={}, context_select={}",
@@ -952,7 +919,7 @@ void Module::Interface::GetLatestVsyncTiming(Kernel::HLERequestContext& ctx) {
if (!port_select.IsSingle() || count > MaxVsyncTimings) { if (!port_select.IsSingle() || count > MaxVsyncTimings) {
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
rb.Push(ResultOutOfRange); rb.Push(ERROR_OUT_OF_RANGE);
rb.PushStaticBuffer({}, 0); rb.PushStaticBuffer({}, 0);
return; return;
} }
@@ -1036,7 +1003,7 @@ Result Module::SetPackageParameter(const PackageParameterType& package) {
} else { } else {
LOG_ERROR(Service_CAM, "invalid camera_select={}, context_select={}", package.camera_select, LOG_ERROR(Service_CAM, "invalid camera_select={}, context_select={}", package.camera_select,
package.context_select); package.context_select);
return ResultInvalidEnumValue; return ERROR_INVALID_ENUM_VALUE;
} }
} }

View File

@@ -256,6 +256,10 @@ void PicaCore::WriteInternalReg(u32 id, u32 value, u32 mask) {
case PICA_REG_INDEX(vs.bool_uniforms): case PICA_REG_INDEX(vs.bool_uniforms):
vs_setup.WriteUniformBoolReg(regs.internal.vs.bool_uniforms.Value()); vs_setup.WriteUniformBoolReg(regs.internal.vs.bool_uniforms.Value());
if (!regs.internal.pipeline.gs_unit_exclusive_configuration &&
regs.internal.pipeline.use_gs == PipelineRegs::UseGS::No) {
gs_setup.WriteUniformBoolReg(regs.internal.vs.bool_uniforms.Value());
}
break; break;
case PICA_REG_INDEX(vs.int_uniforms[0]): case PICA_REG_INDEX(vs.int_uniforms[0]):
@@ -264,6 +268,10 @@ void PicaCore::WriteInternalReg(u32 id, u32 value, u32 mask) {
case PICA_REG_INDEX(vs.int_uniforms[3]): { case PICA_REG_INDEX(vs.int_uniforms[3]): {
const u32 index = (id - PICA_REG_INDEX(vs.int_uniforms[0])); const u32 index = (id - PICA_REG_INDEX(vs.int_uniforms[0]));
vs_setup.WriteUniformIntReg(index, regs.internal.vs.GetIntUniform(index)); vs_setup.WriteUniformIntReg(index, regs.internal.vs.GetIntUniform(index));
if (!regs.internal.pipeline.gs_unit_exclusive_configuration &&
regs.internal.pipeline.use_gs == PipelineRegs::UseGS::No) {
gs_setup.WriteUniformIntReg(index, regs.internal.vs.GetIntUniform(index));
}
break; break;
} }
@@ -275,7 +283,11 @@ void PicaCore::WriteInternalReg(u32 id, u32 value, u32 mask) {
case PICA_REG_INDEX(vs.uniform_setup.set_value[5]): case PICA_REG_INDEX(vs.uniform_setup.set_value[5]):
case PICA_REG_INDEX(vs.uniform_setup.set_value[6]): case PICA_REG_INDEX(vs.uniform_setup.set_value[6]):
case PICA_REG_INDEX(vs.uniform_setup.set_value[7]): { case PICA_REG_INDEX(vs.uniform_setup.set_value[7]): {
vs_setup.WriteUniformFloatReg(regs.internal.vs, value); const auto index = vs_setup.WriteUniformFloatReg(regs.internal.vs, value);
if (!regs.internal.pipeline.gs_unit_exclusive_configuration &&
regs.internal.pipeline.use_gs == PipelineRegs::UseGS::No && index) {
gs_setup.uniforms.f[index.value()] = vs_setup.uniforms.f[index.value()];
}
break; break;
} }

View File

@@ -27,21 +27,23 @@ void ShaderSetup::WriteUniformIntReg(u32 index, const Common::Vec4<u8> values) {
uniforms.i[index] = values; uniforms.i[index] = values;
} }
void ShaderSetup::WriteUniformFloatReg(ShaderRegs& config, u32 value) { std::optional<u32> ShaderSetup::WriteUniformFloatReg(ShaderRegs& config, u32 value) {
auto& uniform_setup = config.uniform_setup; auto& uniform_setup = config.uniform_setup;
const bool is_float32 = uniform_setup.IsFloat32(); const bool is_float32 = uniform_setup.IsFloat32();
if (!uniform_queue.Push(value, is_float32)) { if (!uniform_queue.Push(value, is_float32)) {
return; return std::nullopt;
} }
const auto uniform = uniform_queue.Get(is_float32); const auto uniform = uniform_queue.Get(is_float32);
if (uniform_setup.index >= uniforms.f.size()) { if (uniform_setup.index >= uniforms.f.size()) {
LOG_ERROR(HW_GPU, "Invalid float uniform index {}", uniform_setup.index.Value()); LOG_ERROR(HW_GPU, "Invalid float uniform index {}", uniform_setup.index.Value());
return; return std::nullopt;
} }
uniforms.f[uniform_setup.index] = uniform; const u32 index = uniform_setup.index.Value();
uniform_setup.index.Assign(uniform_setup.index + 1); uniforms.f[index] = uniform;
uniform_setup.index.Assign(index + 1);
return index;
} }
u64 ShaderSetup::GetProgramCodeHash() { u64 ShaderSetup::GetProgramCodeHash() {

View File

@@ -4,6 +4,7 @@
#pragma once #pragma once
#include <optional>
#include "common/vector_math.h" #include "common/vector_math.h"
#include "video_core/pica/packed_attribute.h" #include "video_core/pica/packed_attribute.h"
#include "video_core/pica_types.h" #include "video_core/pica_types.h"
@@ -58,7 +59,7 @@ public:
void WriteUniformIntReg(u32 index, const Common::Vec4<u8> values); void WriteUniformIntReg(u32 index, const Common::Vec4<u8> values);
void WriteUniformFloatReg(ShaderRegs& config, u32 value); std::optional<u32> WriteUniformFloatReg(ShaderRegs& config, u32 value);
u64 GetProgramCodeHash(); u64 GetProgramCodeHash();