fix(videoout): accept a buffer attribute change while a flip is pending
sceVideoOutSubmitChangeBufferAttribute2 threw when a buffer of the group had a flip pending, and Marvel's Wolverine makes that call with flips in the queue. A flip now takes its buffer group when it is reserved, in submission order, so flips submitted before the change keep the attributes their buffers were rendered with and later flips use the new ones. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
a11c8f7f70
commit
5cd25dedbd
|
|
@ -173,6 +173,7 @@ struct FlipRequest final : AgcDriver::IFlipRequest, std::enable_shared_from_this
|
|||
uint32_t height = 0;
|
||||
VideoOutBuffer buffer;
|
||||
BufferAttributeGroup group;
|
||||
bool groupCaptured = false;
|
||||
bool reserved = false;
|
||||
bool unregistered = false;
|
||||
bool ready = false;
|
||||
|
|
|
|||
|
|
@ -127,7 +127,6 @@ int APS5_VABI sceVideoOutSubmitChangeBufferAttribute2(int handle, int setIndex,
|
|||
group.attribute = *attribute;
|
||||
for (int i = 0; i < VIDEO_OUT_BUFFER_NUM_MAX; ++i) {
|
||||
if (cfg->buffers[i].groupIndex != setIndex) continue;
|
||||
if (cfg->bufferPending[i] != 0) throw std::runtime_error("VideoOut: buffer attributes are in use by a pending flip");
|
||||
const auto display = DescribeVideoOutBuffer(cfg->buffers[i], group);
|
||||
AgcDriverCheckGuestMemory_nid_postfix(reinterpret_cast<const void*>(display.address), AgcDriverDisplayBufferSize_nid_postfix(display), 65536);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ void resolveFlipBuffer(FlipRequest& request, const VideoOutConfig& cfg) {
|
|||
return;
|
||||
}
|
||||
require(request.buffer.groupIndex < VIDEO_OUT_BUFFER_ATTRIBUTE_NUM_MAX, "invalid buffer group");
|
||||
request.group = cfg.groups[request.buffer.groupIndex];
|
||||
if (!request.groupCaptured) request.group = cfg.groups[request.buffer.groupIndex];
|
||||
require(request.group.occupied, "buffer group is not registered");
|
||||
require(request.buffer.dataAddress != 0, "null registered buffer address");
|
||||
static_cast<void>(DescribeVideoOutBuffer(request.buffer, request.group));
|
||||
|
|
@ -152,6 +152,10 @@ public:
|
|||
++queue->reservations;
|
||||
++cfg->flipStatus.flipPendingNum;
|
||||
if (info.index >= 0) ++cfg->bufferPending[info.index];
|
||||
if (info.index >= 0 && cfg->buffers[info.index].Occupied() && cfg->buffers[info.index].groupIndex < VIDEO_OUT_BUFFER_ATTRIBUTE_NUM_MAX && cfg->groups[cfg->buffers[info.index].groupIndex].occupied) {
|
||||
request->group = cfg->groups[cfg->buffers[info.index].groupIndex];
|
||||
request->groupCaptured = true;
|
||||
}
|
||||
request->reserved = true;
|
||||
return request;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -86,8 +86,16 @@ void testLifetime(bool reopen) {
|
|||
std::lock_guard lock(cfg->mutex);
|
||||
check(cfg->flipStatus.flipPendingNum == 1 && cfg->flipStatus.count == 0, "reservation status is wrong");
|
||||
}
|
||||
auto smaller = attribute;
|
||||
smaller.width = 32;
|
||||
smaller.height = 32;
|
||||
check(sceVideoOutSubmitChangeBufferAttribute2(handle, 0, &smaller, nullptr) == 0, "attributes of a buffer with a pending flip could not be changed");
|
||||
{
|
||||
std::lock_guard lock(cfg->mutex);
|
||||
check(cfg->groups[0].attribute.width == 32 && cfg->groups[0].attribute.height == 32 && cfg->flipStatus.flipPendingNum == 1, "the attribute change did not reach later flips or dropped the pending one");
|
||||
}
|
||||
attribute.dcc_control = 1;
|
||||
check(expectFailure([&] { sceVideoOutSubmitChangeBufferAttribute2(handle, 0, &attribute, nullptr); }).find("pending flip") != std::string::npos, "pending attributes were changed");
|
||||
check(expectFailure([&] { sceVideoOutSubmitChangeBufferAttribute2(handle, 0, &attribute, nullptr); }).find("DCC") != std::string::npos, "an invalid attribute change was accepted");
|
||||
check(expectFailure([&] { sceVideoOutUnregisterBuffers(handle, 0); }).find("pending flip") != std::string::npos, "pending buffer was unregistered");
|
||||
check(sceVideoOutWaitVblank(handle) == 0 && sceVideoOutWaitVblank(handle) == 0, "vblank stalled behind the GPU queue");
|
||||
std::shared_ptr<VideoOutConfig> replacement;
|
||||
|
|
|
|||
Loading…
Reference in New Issue