mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 18:53:28 +01:00
rsx: Resurgence of HLE GCM
This commit is contained in:
parent
c4459dff40
commit
f9bc7458d4
@ -298,13 +298,32 @@ error_code cellGcmBindZcull(u8 index, u32 offset, u32 width, u32 height, u32 cul
|
||||
cellGcmSys.warning("cellGcmBindZcull(index=%d, offset=0x%x, width=%d, height=%d, cullStart=0x%x, zFormat=0x%x, aaFormat=0x%x, zCullDir=0x%x, zCullFormat=0x%x, sFunc=0x%x, sRef=0x%x, sMask=0x%x)",
|
||||
index, offset, width, height, cullStart, zFormat, aaFormat, zCullDir, zCullFormat, sFunc, sRef, sMask);
|
||||
|
||||
if (index >= rsx::limits::zculls_count)
|
||||
auto& gcm_cfg = g_fxo->get<gcm_config>();
|
||||
|
||||
GcmZcullInfo zcull{};
|
||||
zcull.offset = offset;
|
||||
zcull.width = width;
|
||||
zcull.height = height;
|
||||
zcull.cullStart = cullStart;
|
||||
zcull.zFormat = zFormat;
|
||||
zcull.aaFormat = aaFormat;
|
||||
zcull.zcullDir = zCullDir;
|
||||
zcull.zcullFormat = zCullFormat;
|
||||
zcull.sFunc = sFunc;
|
||||
zcull.sRef = sRef;
|
||||
zcull.sMask = sMask;
|
||||
zcull.bound = true;
|
||||
|
||||
const auto gcm_zcull = zcull.pack();
|
||||
|
||||
std::lock_guard lock(gcm_cfg.gcmio_mutex);
|
||||
|
||||
if (auto err = sys_rsx_context_attribute(0x5555'5555, 0x301, index, u64{gcm_zcull.region} << 32 | gcm_zcull.size, u64{gcm_zcull.start} << 32 | gcm_zcull.offset, u64{gcm_zcull.status0} << 32 | gcm_zcull.status1))
|
||||
{
|
||||
return CELL_GCM_ERROR_INVALID_VALUE;
|
||||
return err;
|
||||
}
|
||||
|
||||
rsx::get_current_renderer()->zculls[index].bound = true;
|
||||
|
||||
vm::_ptr<CellGcmZcullInfo>(gcm_cfg.zculls_addr)[index] = gcm_zcull;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@ -391,6 +410,12 @@ error_code _cellGcmInitBody(ppu_thread& ppu, vm::pptr<CellGcmContextData> contex
|
||||
render->main_mem_size = 0x10000000;
|
||||
}
|
||||
|
||||
render->isHLE = true;
|
||||
render->local_mem_size = gcm_cfg.local_size;
|
||||
|
||||
ensure(sys_rsx_device_map(ppu, vm::var<u64>{}, vm::null, 0x8) == CELL_OK);
|
||||
ensure(sys_rsx_context_allocate(ppu, vm::var<u32>{}, vm::var<u64>{}, vm::var<u64>{}, vm::var<u64>{}, 0, gcm_cfg.system_mode) == CELL_OK);
|
||||
|
||||
if (gcmMapEaIoAddress(ppu, ioAddress, 0, ioSize, false) != CELL_OK)
|
||||
{
|
||||
return CELL_GCM_ERROR_FAILURE;
|
||||
@ -403,18 +428,14 @@ error_code _cellGcmInitBody(ppu_thread& ppu, vm::pptr<CellGcmContextData> contex
|
||||
gcm_cfg.current_config.memoryFrequency = 650000000;
|
||||
gcm_cfg.current_config.coreFrequency = 500000000;
|
||||
|
||||
// Create contexts
|
||||
const auto area = vm::reserve_map(vm::rsx_context, 0, 0x10000000, 0x403);
|
||||
const u32 rsx_ctxaddr = area ? area->alloc(0x400000) : 0;
|
||||
const u32 rsx_ctxaddr = render->device_addr;
|
||||
ensure(rsx_ctxaddr);
|
||||
|
||||
g_defaultCommandBufferBegin = ioAddress;
|
||||
g_defaultCommandBufferFragmentCount = cmdSize / (32 * 1024);
|
||||
|
||||
gcm_cfg.gcm_info.context_addr = rsx_ctxaddr;
|
||||
gcm_cfg.gcm_info.control_addr = rsx_ctxaddr + 0x100000;
|
||||
gcm_cfg.gcm_info.label_addr = rsx_ctxaddr + 0x300000;
|
||||
|
||||
gcm_cfg.gcm_info.control_addr = render->dma_address;
|
||||
gcm_cfg.current_context.begin.set(g_defaultCommandBufferBegin + 4096); // 4 kb reserved at the beginning
|
||||
gcm_cfg.current_context.end.set(g_defaultCommandBufferBegin + 32 * 1024 - 4); // 4b at the end for jump
|
||||
gcm_cfg.current_context.current = gcm_cfg.current_context.begin;
|
||||
@ -430,21 +451,13 @@ error_code _cellGcmInitBody(ppu_thread& ppu, vm::pptr<CellGcmContextData> contex
|
||||
|
||||
// 0x40 is to offset CellGcmControl from RsxDmaControl
|
||||
gcm_cfg.gcm_info.control_addr += 0x40;
|
||||
auto& ctrl = vm::_ref<CellGcmControl>(gcm_cfg.gcm_info.control_addr);
|
||||
ctrl.put = 0;
|
||||
ctrl.get = 0;
|
||||
ctrl.ref = 0; // Set later to -1 at RSX initialization
|
||||
|
||||
vm::var<u64> _tid;
|
||||
vm::var<char[]> _name = vm::make_str("_gcm_intr_thread");
|
||||
ppu_execute<&sys_ppu_thread_create>(ppu, +_tid, 0x10000, 0, 1, 0x4000, SYS_PPU_THREAD_CREATE_INTERRUPT, +_name);
|
||||
render->intr_thread = idm::get<named_thread<ppu_thread>>(static_cast<u32>(*_tid));
|
||||
render->intr_thread->state -= cpu_flag::stop;
|
||||
render->isHLE = true;
|
||||
render->label_addr = gcm_cfg.gcm_info.label_addr;
|
||||
render->device_addr = gcm_cfg.gcm_info.context_addr;
|
||||
render->local_mem_size = gcm_cfg.local_size;
|
||||
render->init(gcm_cfg.gcm_info.control_addr - 0x40);
|
||||
thread_ctrl::notify(*render->intr_thread);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -516,7 +529,10 @@ void cellGcmSetFlipHandler(vm::ptr<void(u32)> handler)
|
||||
{
|
||||
cellGcmSys.warning("cellGcmSetFlipHandler(handler=*0x%x)", handler);
|
||||
|
||||
rsx::get_current_renderer()->flip_handler = handler;
|
||||
if (const auto rsx = rsx::get_current_renderer(); rsx->is_inited)
|
||||
{
|
||||
rsx->flip_handler = handler;
|
||||
}
|
||||
}
|
||||
|
||||
error_code cellGcmSetFlipHandler2()
|
||||
@ -665,51 +681,69 @@ void cellGcmSetUserHandler(vm::ptr<void(u32)> handler)
|
||||
{
|
||||
cellGcmSys.warning("cellGcmSetUserHandler(handler=*0x%x)", handler);
|
||||
|
||||
rsx::get_current_renderer()->user_handler = handler;
|
||||
if (const auto rsx = rsx::get_current_renderer(); rsx->is_inited)
|
||||
{
|
||||
rsx->user_handler = handler;
|
||||
}
|
||||
}
|
||||
|
||||
void cellGcmSetUserCommand(vm::ptr<CellGcmContextData> ctxt, u32 cause)
|
||||
void cellGcmSetUserCommand(ppu_thread& ppu, vm::ptr<CellGcmContextData> ctxt, u32 cause)
|
||||
{
|
||||
cellGcmSys.todo("cellGcmSetUserCommand(ctxt=*0x%x, cause=0x%x)", ctxt, cause);
|
||||
cellGcmSys.trace("cellGcmSetUserCommand(ctxt=*0x%x, cause=0x%x)", ctxt, cause);
|
||||
|
||||
if (ctxt->current + 2 >= ctxt->end)
|
||||
{
|
||||
if (s32 res = ctxt->callback(ppu, ctxt, 8 /* ??? */))
|
||||
{
|
||||
cellGcmSys.error("cellGcmSetUserCommand(): callback failed (0x%08x)", res);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
rsx::make_command(ctxt->current, GCM_SET_USER_COMMAND, { cause });
|
||||
}
|
||||
|
||||
void cellGcmSetVBlankHandler(vm::ptr<void(u32)> handler)
|
||||
{
|
||||
cellGcmSys.warning("cellGcmSetVBlankHandler(handler=*0x%x)", handler);
|
||||
|
||||
rsx::get_current_renderer()->vblank_handler = handler;
|
||||
if (const auto rsx = rsx::get_current_renderer(); rsx->is_inited)
|
||||
{
|
||||
rsx->vblank_handler = handler;
|
||||
}
|
||||
}
|
||||
|
||||
void cellGcmSetWaitFlip(vm::ptr<CellGcmContextData> ctxt)
|
||||
void cellGcmSetWaitFlip(ppu_thread& ppu, vm::ptr<CellGcmContextData> ctxt)
|
||||
{
|
||||
cellGcmSys.warning("cellGcmSetWaitFlip(ctxt=*0x%x)", ctxt);
|
||||
cellGcmSys.trace("cellGcmSetWaitFlip(ctxt=*0x%x)", ctxt);
|
||||
|
||||
// TODO: emit RSX command for "wait flip" operation
|
||||
if (ctxt->current + 2 >= ctxt->end)
|
||||
{
|
||||
if (s32 res = ctxt->callback(ppu, ctxt, 8 /* ??? */))
|
||||
{
|
||||
cellGcmSys.error("cellGcmSetWaitFlip(): callback failed (0x%08x)", res);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
error_code cellGcmSetWaitFlipUnsafe()
|
||||
{
|
||||
cellGcmSys.todo("cellGcmSetWaitFlipUnsafe()");
|
||||
rsx::make_command(ctxt->current, NV406E_SEMAPHORE_OFFSET, { 0x10u, 0 });
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
void cellGcmSetWaitFlipUnsafe(vm::ptr<CellGcmContextData> ctxt)
|
||||
{
|
||||
cellGcmSys.trace("cellGcmSetWaitFlipUnsafe(ctxt=*0x%x)", ctxt);
|
||||
|
||||
rsx::make_command(ctxt->current, NV406E_SEMAPHORE_OFFSET, { 0x10u, 0 });
|
||||
}
|
||||
|
||||
void cellGcmSetZcull(u8 index, u32 offset, u32 width, u32 height, u32 cullStart, u32 zFormat, u32 aaFormat, u32 zCullDir, u32 zCullFormat, u32 sFunc, u32 sRef, u32 sMask)
|
||||
{
|
||||
cellGcmSys.todo("cellGcmSetZcull(index=%d, offset=0x%x, width=%d, height=%d, cullStart=0x%x, zFormat=0x%x, aaFormat=0x%x, zCullDir=0x%x, zCullFormat=0x%x, sFunc=0x%x, sRef=0x%x, sMask=0x%x)",
|
||||
cellGcmSys.warning("cellGcmSetZcull(index=%d, offset=0x%x, width=%d, height=%d, cullStart=0x%x, zFormat=0x%x, aaFormat=0x%x, zCullDir=0x%x, zCullFormat=0x%x, sFunc=0x%x, sRef=0x%x, sMask=0x%x)",
|
||||
index, offset, width, height, cullStart, zFormat, aaFormat, zCullDir, zCullFormat, sFunc, sRef, sMask);
|
||||
|
||||
auto& gcm_cfg = g_fxo->get<gcm_config>();
|
||||
|
||||
if (index >= rsx::limits::zculls_count)
|
||||
{
|
||||
cellGcmSys.error("cellGcmSetZcull: CELL_GCM_ERROR_INVALID_VALUE");
|
||||
return;
|
||||
}
|
||||
|
||||
const auto render = rsx::get_current_renderer();
|
||||
|
||||
auto& zcull = render->zculls[index];
|
||||
GcmZcullInfo zcull{};
|
||||
zcull.offset = offset;
|
||||
zcull.width = width;
|
||||
zcull.height = height;
|
||||
@ -721,9 +755,18 @@ void cellGcmSetZcull(u8 index, u32 offset, u32 width, u32 height, u32 cullStart,
|
||||
zcull.sFunc = sFunc;
|
||||
zcull.sRef = sRef;
|
||||
zcull.sMask = sMask;
|
||||
zcull.bound = (zCullFormat > 0);
|
||||
zcull.bound = true;
|
||||
|
||||
vm::_ptr<CellGcmZcullInfo>(gcm_cfg.zculls_addr)[index] = zcull.pack();
|
||||
const auto gcm_zcull = zcull.pack();
|
||||
|
||||
// The second difference between BindZcull and this function (second is no return value) is that this function is not thread-safe
|
||||
// But take care anyway
|
||||
std::lock_guard lock(gcm_cfg.gcmio_mutex);
|
||||
|
||||
if (!sys_rsx_context_attribute(0x5555'5555, 0x301, index, u64{gcm_zcull.region} << 32 | gcm_zcull.size, u64{gcm_zcull.start} << 32 | gcm_zcull.offset, u64{gcm_zcull.status0} << 32 | gcm_zcull.status1))
|
||||
{
|
||||
vm::_ptr<CellGcmZcullInfo>(gcm_cfg.zculls_addr)[index] = gcm_zcull;
|
||||
}
|
||||
}
|
||||
|
||||
error_code cellGcmUnbindTile(u8 index)
|
||||
@ -878,7 +921,12 @@ void cellGcmSetGraphicsHandler(vm::ptr<void(u32)> handler)
|
||||
|
||||
void cellGcmSetQueueHandler(vm::ptr<void(u32)> handler)
|
||||
{
|
||||
cellGcmSys.todo("cellGcmSetQueueHandler(handler=*0x%x)", handler);
|
||||
cellGcmSys.warning("cellGcmSetQueueHandler(handler=*0x%x)", handler);
|
||||
|
||||
if (const auto rsx = rsx::get_current_renderer(); rsx->is_inited)
|
||||
{
|
||||
rsx->queue_handler = handler;
|
||||
}
|
||||
}
|
||||
|
||||
error_code cellGcmSetSecondVHandler(vm::ptr<void(u32)> handler)
|
||||
@ -1264,18 +1312,17 @@ error_code _cellGcmSetFlipCommand2()
|
||||
|
||||
void _cellGcmSetFlipCommandWithWaitLabel(ppu_thread& ppu, vm::ptr<CellGcmContextData> ctx, u32 id, u32 label_index, u32 label_value)
|
||||
{
|
||||
cellGcmSys.todo("cellGcmSetFlipCommandWithWaitLabel(ctx=*0x%x, id=0x%x, label_index=0x%x, label_value=0x%x)", ctx, id, label_index, label_value);
|
||||
cellGcmSys.warning("cellGcmSetFlipCommandWithWaitLabel(ctx=*0x%x, id=0x%x, label_index=0x%x, label_value=0x%x)", ctx, id, label_index, label_value);
|
||||
|
||||
auto& gcm_cfg = g_fxo->get<gcm_config>();
|
||||
|
||||
rsx::make_command(ctx->current, NV406E_SEMAPHORE_OFFSET, { label_index * 0x10, label_value });
|
||||
|
||||
if (auto error = gcmSetPrepareFlip<true>(ppu, ctx, id); error < 0)
|
||||
{
|
||||
// TODO: On actual fw this function doesn't have error checks at all
|
||||
cellGcmSys.error("cellGcmSetFlipCommandWithWaitLabel(): gcmSetPrepareFlip failed with %s", CellGcmError{error + 0u});
|
||||
}
|
||||
|
||||
// TODO: Fix this (must enqueue WaitLabel command instead)
|
||||
vm::write32(gcm_cfg.gcm_info.label_addr + 0x10 * label_index, label_value);
|
||||
}
|
||||
|
||||
error_code cellGcmSetTile(u8 index, u8 location, u32 offset, u32 size, u32 pitch, u8 comp, u16 base, u8 bank)
|
||||
|
@ -656,7 +656,10 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64
|
||||
//a6 high = status0 = (zcullDir << 1) | (zcullFormat << 2) | ((sFunc & 0xF) << 12) | (sRef << 16) | (sMask << 24);
|
||||
//a6 low = status1 = (0x2000 << 0) | (0x20 << 16);
|
||||
|
||||
ensure(a3 < std::size(render->zculls));
|
||||
if (a3 >= std::size(render->zculls))
|
||||
{
|
||||
return SYS_RSX_CONTEXT_ATTRIBUTE_ERROR;
|
||||
}
|
||||
|
||||
if (!render->is_fifo_idle())
|
||||
{
|
||||
|
@ -39,7 +39,6 @@ struct gcmInfo
|
||||
u32 config_addr;
|
||||
u32 context_addr;
|
||||
u32 control_addr;
|
||||
u32 label_addr;
|
||||
u32 command_size = 0x400;
|
||||
u32 segment_size = 0x100;
|
||||
};
|
||||
|
@ -703,15 +703,16 @@ namespace rsx
|
||||
|
||||
if (isHLE)
|
||||
{
|
||||
if (vblank_handler)
|
||||
if (auto ptr = vblank_handler)
|
||||
{
|
||||
intr_thread->cmd_list
|
||||
({
|
||||
{ ppu_cmd::set_args, 1 }, u64{1},
|
||||
{ ppu_cmd::lle_call, vblank_handler },
|
||||
{ ppu_cmd::lle_call, ptr },
|
||||
{ ppu_cmd::sleep, 0 }
|
||||
});
|
||||
|
||||
intr_thread->cmd_notify++;
|
||||
intr_thread->cmd_notify.notify_one();
|
||||
}
|
||||
}
|
||||
@ -2183,6 +2184,9 @@ namespace rsx
|
||||
void thread::reset()
|
||||
{
|
||||
rsx::method_registers.reset();
|
||||
m_graphics_state = pipeline_state::all_dirty;
|
||||
m_rtts_dirty = true;
|
||||
m_framebuffer_state_contested = false;
|
||||
}
|
||||
|
||||
void thread::init(u32 ctrlAddress)
|
||||
@ -3278,12 +3282,12 @@ namespace rsx
|
||||
return;
|
||||
}
|
||||
|
||||
if (flip_handler)
|
||||
if (auto ptr = flip_handler)
|
||||
{
|
||||
intr_thread->cmd_list
|
||||
({
|
||||
{ ppu_cmd::set_args, 1 }, u64{ 1 },
|
||||
{ ppu_cmd::lle_call, flip_handler },
|
||||
{ ppu_cmd::lle_call, ptr },
|
||||
{ ppu_cmd::sleep, 0 }
|
||||
});
|
||||
|
||||
|
@ -641,6 +641,7 @@ namespace rsx
|
||||
vm::ptr<void(u32)> flip_handler = vm::null;
|
||||
vm::ptr<void(u32)> user_handler = vm::null;
|
||||
vm::ptr<void(u32)> vblank_handler = vm::null;
|
||||
vm::ptr<void(u32)> queue_handler = vm::null;
|
||||
atomic_t<u64> vblank_count{0};
|
||||
bool capture_current_frame = false;
|
||||
|
||||
|
@ -1768,8 +1768,26 @@ namespace rsx
|
||||
void flip_command(thread* rsx, u32, u32 arg)
|
||||
{
|
||||
ensure(rsx->isHLE);
|
||||
|
||||
if (auto ptr = rsx->queue_handler)
|
||||
{
|
||||
rsx->intr_thread->cmd_list
|
||||
({
|
||||
{ ppu_cmd::set_args, 1 }, u64{1},
|
||||
{ ppu_cmd::lle_call, ptr },
|
||||
{ ppu_cmd::sleep, 0 }
|
||||
});
|
||||
|
||||
rsx->intr_thread->cmd_notify++;
|
||||
rsx->intr_thread->cmd_notify.notify_one();
|
||||
}
|
||||
|
||||
rsx->reset();
|
||||
nv4097::set_zcull_render_enable(rsx, 0, 0x3);
|
||||
nv4097::set_render_mode(rsx, 0, 0x0100'0000);
|
||||
rsx->on_frame_end(arg);
|
||||
rsx->request_emu_flip(arg);
|
||||
vm::_ref<atomic_t<u128>>(rsx->label_addr + 0x10).store(u128{});
|
||||
}
|
||||
|
||||
void user_command(thread* rsx, u32, u32 arg)
|
||||
@ -1780,12 +1798,12 @@ namespace rsx
|
||||
return;
|
||||
}
|
||||
|
||||
if (rsx->user_handler)
|
||||
if (auto ptr = rsx->user_handler)
|
||||
{
|
||||
rsx->intr_thread->cmd_list
|
||||
({
|
||||
{ ppu_cmd::set_args, 1 }, u64{arg},
|
||||
{ ppu_cmd::lle_call, rsx->user_handler },
|
||||
{ ppu_cmd::lle_call, ptr },
|
||||
{ ppu_cmd::sleep, 0 }
|
||||
});
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user