mirror of
https://github.com/cemu-project/Cemu.git
synced 2025-12-16 12:08:52 +00:00
Latte: Instance count minimum is 1
Previously we skipped drawcalls when the instance count was set to zero. But the hardware register enforces a minimum of 1. Fixes black screen in "Cubit The Hardcore Platformer Robot" which does all it's drawcalls with an hardcoded instance count of 0.
This commit is contained in:
parent
5bf58c3d20
commit
47b8d911b9
@ -27,11 +27,6 @@ struct LatteGPUState_t
|
|||||||
uint32 contextControl1;
|
uint32 contextControl1;
|
||||||
// optional features
|
// optional features
|
||||||
bool allowFramebufferSizeOptimization{false}; // allow using scissor box as size hint to determine non-padded rendertarget size
|
bool allowFramebufferSizeOptimization{false}; // allow using scissor box as size hint to determine non-padded rendertarget size
|
||||||
// draw context
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
uint32 numInstances;
|
|
||||||
}drawContext;
|
|
||||||
// stats
|
// stats
|
||||||
uint32 frameCounter;
|
uint32 frameCounter;
|
||||||
uint32 flipCounter; // increased by one everytime a vsync + flip happens
|
uint32 flipCounter; // increased by one everytime a vsync + flip happens
|
||||||
|
|||||||
@ -62,16 +62,7 @@ public:
|
|||||||
{
|
{
|
||||||
uint32 baseVertex = LatteGPUState.contextRegister[mmSQ_VTX_BASE_VTX_LOC];
|
uint32 baseVertex = LatteGPUState.contextRegister[mmSQ_VTX_BASE_VTX_LOC];
|
||||||
uint32 baseInstance = LatteGPUState.contextRegister[mmSQ_VTX_START_INST_LOC];
|
uint32 baseInstance = LatteGPUState.contextRegister[mmSQ_VTX_START_INST_LOC];
|
||||||
uint32 numInstances = LatteGPUState.drawContext.numInstances;
|
uint32 numInstances = LatteGPUState.contextNew.VGT_DMA_NUM_INSTANCES.get_NUM_INSTANCES();
|
||||||
if (numInstances == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/*
|
|
||||||
if (GetAsyncKeyState('B'))
|
|
||||||
{
|
|
||||||
cemuLog_force("[executeDraw] {} Count {} BaseVertex {} BaseInstance {}", m_isFirstDraw?"Init":"Fast", count, baseVertex, baseInstance);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!isAutoIndex)
|
if (!isAutoIndex)
|
||||||
{
|
{
|
||||||
@ -391,7 +382,10 @@ LatteCMDPtr LatteCP_itIndexType(LatteCMDPtr cmd, uint32 nWords)
|
|||||||
LatteCMDPtr LatteCP_itNumInstances(LatteCMDPtr cmd, uint32 nWords)
|
LatteCMDPtr LatteCP_itNumInstances(LatteCMDPtr cmd, uint32 nWords)
|
||||||
{
|
{
|
||||||
cemu_assert_debug(nWords == 1);
|
cemu_assert_debug(nWords == 1);
|
||||||
LatteGPUState.drawContext.numInstances = LatteReadCMD();
|
uint32 numInstances = LatteReadCMD();
|
||||||
|
if (numInstances == 0)
|
||||||
|
numInstances = 1;
|
||||||
|
LatteGPUState.contextNew.VGT_DMA_NUM_INSTANCES.set_NUM_INSTANCES(numInstances);
|
||||||
return cmd;
|
return cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -690,9 +684,6 @@ LatteCMDPtr LatteCP_itDrawIndexAuto(LatteCMDPtr cmd, uint32 nWords, DrawPassCont
|
|||||||
cemu_assert_debug(nWords == 2);
|
cemu_assert_debug(nWords == 2);
|
||||||
uint32 count = LatteReadCMD();
|
uint32 count = LatteReadCMD();
|
||||||
uint32 ukn = LatteReadCMD();
|
uint32 ukn = LatteReadCMD();
|
||||||
|
|
||||||
if (LatteGPUState.drawContext.numInstances == 0)
|
|
||||||
return cmd;
|
|
||||||
LatteGPUState.currentDrawCallTick = GetTickCount();
|
LatteGPUState.currentDrawCallTick = GetTickCount();
|
||||||
// todo - better way to identify compute drawcalls
|
// todo - better way to identify compute drawcalls
|
||||||
if ((LatteGPUState.contextRegister[mmSQ_CONFIG] >> 24) == 0xE4)
|
if ((LatteGPUState.contextRegister[mmSQ_CONFIG] >> 24) == 0xE4)
|
||||||
@ -750,13 +741,7 @@ LatteCMDPtr LatteCP_itDrawImmediate(LatteCMDPtr cmd, uint32 nWords, DrawPassCont
|
|||||||
cemuLog_log(LogType::Force, "itDrawImmediate - Unsupported index type");
|
cemuLog_log(LogType::Force, "itDrawImmediate - Unsupported index type");
|
||||||
return cmd;
|
return cmd;
|
||||||
}
|
}
|
||||||
// verify packet size
|
cemu_assert_debug(nWords == (2 + numIndexU32s)); // verify packet size
|
||||||
if (nWords != (2 + numIndexU32s))
|
|
||||||
debugBreakpoint();
|
|
||||||
|
|
||||||
uint32 baseVertex = LatteGPUState.contextRegister[mmSQ_VTX_BASE_VTX_LOC];
|
|
||||||
uint32 baseInstance = LatteGPUState.contextRegister[mmSQ_VTX_START_INST_LOC];
|
|
||||||
uint32 numInstances = LatteGPUState.drawContext.numInstances;
|
|
||||||
|
|
||||||
drawPassCtx.executeDraw(count, false, _tempIndexArrayMPTR);
|
drawPassCtx.executeDraw(count, false, _tempIndexArrayMPTR);
|
||||||
return cmd;
|
return cmd;
|
||||||
|
|||||||
@ -30,6 +30,7 @@ void Latte_LoadInitialRegisters()
|
|||||||
{
|
{
|
||||||
LatteGPUState.contextNew.CB_TARGET_MASK.set_MASK(0xFFFFFFFF);
|
LatteGPUState.contextNew.CB_TARGET_MASK.set_MASK(0xFFFFFFFF);
|
||||||
LatteGPUState.contextNew.VGT_MULTI_PRIM_IB_RESET_INDX.set_RESTART_INDEX(0xFFFFFFFF);
|
LatteGPUState.contextNew.VGT_MULTI_PRIM_IB_RESET_INDX.set_RESTART_INDEX(0xFFFFFFFF);
|
||||||
|
LatteGPUState.contextNew.VGT_DMA_NUM_INSTANCES.set_NUM_INSTANCES(1);
|
||||||
LatteGPUState.contextRegister[Latte::REGADDR::PA_CL_CLIP_CNTL] = 0;
|
LatteGPUState.contextRegister[Latte::REGADDR::PA_CL_CLIP_CNTL] = 0;
|
||||||
*(float*)&LatteGPUState.contextRegister[mmDB_DEPTH_CLEAR] = 1.0f;
|
*(float*)&LatteGPUState.contextRegister[mmDB_DEPTH_CLEAR] = 1.0f;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -445,6 +445,7 @@ namespace Latte
|
|||||||
VGT_DMA_INDEX_TYPE = 0xA29F, // todo - verify offset
|
VGT_DMA_INDEX_TYPE = 0xA29F, // todo - verify offset
|
||||||
|
|
||||||
VGT_PRIMITIVEID_EN = 0xA2A1,
|
VGT_PRIMITIVEID_EN = 0xA2A1,
|
||||||
|
VGT_DMA_NUM_INSTANCES = 0xA2A2,
|
||||||
|
|
||||||
VGT_MULTI_PRIM_IB_RESET_EN = 0xA2A5,
|
VGT_MULTI_PRIM_IB_RESET_EN = 0xA2A5,
|
||||||
|
|
||||||
@ -977,6 +978,11 @@ float get_##__regname() const \
|
|||||||
LATTE_BITFIELD_BOOL(PRIMITIVEID_EN, 0);
|
LATTE_BITFIELD_BOOL(PRIMITIVEID_EN, 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct LATTE_VGT_DMA_NUM_INSTANCES : LATTEREG // 0xA2A2
|
||||||
|
{
|
||||||
|
LATTE_BITFIELD_FULL_TYPED(NUM_INSTANCES, uint32);
|
||||||
|
};
|
||||||
|
|
||||||
struct LATTE_VGT_MULTI_PRIM_IB_RESET_EN : LATTEREG // 0xA2A5
|
struct LATTE_VGT_MULTI_PRIM_IB_RESET_EN : LATTEREG // 0xA2A5
|
||||||
{
|
{
|
||||||
LATTE_BITFIELD_BOOL(RESET_EN, 0);
|
LATTE_BITFIELD_BOOL(RESET_EN, 0);
|
||||||
@ -1541,7 +1547,7 @@ struct LatteContextRegister
|
|||||||
/* +0x28A7C */ Latte::LATTE_VGT_DMA_INDEX_TYPE VGT_DMA_INDEX_TYPE;
|
/* +0x28A7C */ Latte::LATTE_VGT_DMA_INDEX_TYPE VGT_DMA_INDEX_TYPE;
|
||||||
/* +0x28A80 */ uint32 ukn28A80;
|
/* +0x28A80 */ uint32 ukn28A80;
|
||||||
/* +0x28A84 */ Latte::LATTE_VGT_PRIMITIVEID_EN VGT_PRIMITIVEID_EN;
|
/* +0x28A84 */ Latte::LATTE_VGT_PRIMITIVEID_EN VGT_PRIMITIVEID_EN;
|
||||||
/* +0x28A88 */ uint32 ukn28A88;
|
/* +0x28A88 */ Latte::LATTE_VGT_DMA_NUM_INSTANCES VGT_DMA_NUM_INSTANCES;
|
||||||
/* +0x28A8C */ uint32 ukn28A8C;
|
/* +0x28A8C */ uint32 ukn28A8C;
|
||||||
/* +0x28A90 */ uint32 ukn28A90;
|
/* +0x28A90 */ uint32 ukn28A90;
|
||||||
/* +0x28A94 */ Latte::LATTE_VGT_MULTI_PRIM_IB_RESET_EN VGT_MULTI_PRIM_IB_RESET_EN;
|
/* +0x28A94 */ Latte::LATTE_VGT_MULTI_PRIM_IB_RESET_EN VGT_MULTI_PRIM_IB_RESET_EN;
|
||||||
@ -1611,6 +1617,7 @@ static_assert(offsetof(LatteContextRegister, PA_SC_GENERIC_SCISSOR_TL) == Latte:
|
|||||||
static_assert(offsetof(LatteContextRegister, PA_SC_GENERIC_SCISSOR_BR) == Latte::REGADDR::PA_SC_GENERIC_SCISSOR_BR * 4);
|
static_assert(offsetof(LatteContextRegister, PA_SC_GENERIC_SCISSOR_BR) == Latte::REGADDR::PA_SC_GENERIC_SCISSOR_BR * 4);
|
||||||
static_assert(offsetof(LatteContextRegister, VGT_MULTI_PRIM_IB_RESET_INDX) == Latte::REGADDR::VGT_MULTI_PRIM_IB_RESET_INDX * 4);
|
static_assert(offsetof(LatteContextRegister, VGT_MULTI_PRIM_IB_RESET_INDX) == Latte::REGADDR::VGT_MULTI_PRIM_IB_RESET_INDX * 4);
|
||||||
static_assert(offsetof(LatteContextRegister, VGT_PRIMITIVEID_EN) == Latte::REGADDR::VGT_PRIMITIVEID_EN * 4);
|
static_assert(offsetof(LatteContextRegister, VGT_PRIMITIVEID_EN) == Latte::REGADDR::VGT_PRIMITIVEID_EN * 4);
|
||||||
|
static_assert(offsetof(LatteContextRegister, VGT_DMA_NUM_INSTANCES) == Latte::REGADDR::VGT_DMA_NUM_INSTANCES * 4);
|
||||||
static_assert(offsetof(LatteContextRegister, VGT_MULTI_PRIM_IB_RESET_EN) == Latte::REGADDR::VGT_MULTI_PRIM_IB_RESET_EN * 4);
|
static_assert(offsetof(LatteContextRegister, VGT_MULTI_PRIM_IB_RESET_EN) == Latte::REGADDR::VGT_MULTI_PRIM_IB_RESET_EN * 4);
|
||||||
static_assert(offsetof(LatteContextRegister, VGT_INSTANCE_STEP_RATE_0) == Latte::REGADDR::VGT_INSTANCE_STEP_RATE_0 * 4);
|
static_assert(offsetof(LatteContextRegister, VGT_INSTANCE_STEP_RATE_0) == Latte::REGADDR::VGT_INSTANCE_STEP_RATE_0 * 4);
|
||||||
static_assert(offsetof(LatteContextRegister, VGT_INSTANCE_STEP_RATE_1) == Latte::REGADDR::VGT_INSTANCE_STEP_RATE_1 * 4);
|
static_assert(offsetof(LatteContextRegister, VGT_INSTANCE_STEP_RATE_1) == Latte::REGADDR::VGT_INSTANCE_STEP_RATE_1 * 4);
|
||||||
|
|||||||
@ -1331,7 +1331,6 @@ void wxGameList::AsyncWorkerThread()
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
cemuLog_log(LogType::Force, "Failed to load icon for title {:016x}", titleId);
|
cemuLog_log(LogType::Force, "Failed to load icon for title {:016x}", titleId);
|
||||||
cemu_assert_debug(false);
|
|
||||||
}
|
}
|
||||||
titleInfo.Unmount(tempMountPath);
|
titleInfo.Unmount(tempMountPath);
|
||||||
// notify UI about loaded icon
|
// notify UI about loaded icon
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user