libraries: gnm_driver: added `sceGnmDrawIndexIndirect` and `sceGnmDrawIndirect`

This commit is contained in:
psucien 2024-06-24 22:53:59 +02:00
parent 508d034263
commit c04fbb75d8
3 changed files with 78 additions and 8 deletions

View File

@ -24,6 +24,20 @@ using namespace AmdGpu;
static std::unique_ptr<AmdGpu::Liverpool> liverpool; static std::unique_ptr<AmdGpu::Liverpool> liverpool;
enum ShaderStages : u32 {
Cs,
Ps,
Vs,
Gs,
Es,
Hs,
Ls,
Max
};
static constexpr std::array indirect_sgpr_offsets{0u, 0u, 0x4cu, 0u, 0xccu, 0u, 0x14cu};
// In case of precise gnm driver emulation we need to send a bunch of HW-specific // In case of precise gnm driver emulation we need to send a bunch of HW-specific
// initialization commands. It may slowdown development at early stage as their // initialization commands. It may slowdown development at early stage as their
// support is not important and can be ignored for a while. // support is not important and can be ignored for a while.
@ -347,10 +361,30 @@ s32 PS4_SYSV_ABI sceGnmDrawIndexAuto(u32* cmdbuf, u32 size, u32 index_count, u32
return -1; return -1;
} }
int PS4_SYSV_ABI sceGnmDrawIndexIndirect() { s32 PS4_SYSV_ABI sceGnmDrawIndexIndirect(u32* cmdbuf, u32 size, u32 data_offset, u32 shader_stage,
LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); u32 vertex_sgpr_offset, u32 instance_vgpr_offset,
u32 flags) {
LOG_TRACE(Lib_GnmDriver, "called");
if (cmdbuf && (size == 9) && (shader_stage < ShaderStages::Max) &&
(vertex_sgpr_offset < 0x10u) && (instance_vgpr_offset < 0x10u)) {
const auto predicate = flags & 1 ? PM4Predicate::PredEnable : PM4Predicate::PredDisable;
cmdbuf = WriteHeader<PM4ItOpcode::DrawIndexIndirect>(
cmdbuf, 4, PM4ShaderType::ShaderGraphics, predicate);
const auto sgpr_offset = indirect_sgpr_offsets[shader_stage];
cmdbuf[0] = data_offset;
cmdbuf[1] = vertex_sgpr_offset == 0 ? 0 : (vertex_sgpr_offset & 0xffffu) + sgpr_offset;
cmdbuf[2] = instance_vgpr_offset == 0 ? 0 : (instance_vgpr_offset & 0xffffu) + sgpr_offset;
cmdbuf[3] = 0;
WriteTrailingNop<3>(cmdbuf);
return ORBIS_OK; return ORBIS_OK;
} }
return -1;
}
int PS4_SYSV_ABI sceGnmDrawIndexIndirectCountMulti() { int PS4_SYSV_ABI sceGnmDrawIndexIndirectCountMulti() {
LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); LOG_ERROR(Lib_GnmDriver, "(STUBBED) called");
@ -383,10 +417,29 @@ s32 PS4_SYSV_ABI sceGnmDrawIndexOffset(u32* cmdbuf, u32 size, u32 index_offset,
return -1; return -1;
} }
int PS4_SYSV_ABI sceGnmDrawIndirect() { s32 PS4_SYSV_ABI sceGnmDrawIndirect(u32* cmdbuf, u32 size, u32 data_offset, u32 shader_stage,
LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); u32 vertex_sgpr_offset, u32 instance_vgpr_offset, u32 flags) {
LOG_TRACE(Lib_GnmDriver, "called");
if (cmdbuf && (size == 9) && (shader_stage < ShaderStages::Max) &&
(vertex_sgpr_offset < 0x10u) && (instance_vgpr_offset < 0x10u)) {
const auto predicate = flags & 1 ? PM4Predicate::PredEnable : PM4Predicate::PredDisable;
cmdbuf = WriteHeader<PM4ItOpcode::DrawIndirect>(cmdbuf, 4, PM4ShaderType::ShaderGraphics,
predicate);
const auto sgpr_offset = indirect_sgpr_offsets[shader_stage];
cmdbuf[0] = data_offset;
cmdbuf[1] = vertex_sgpr_offset == 0 ? 0 : (vertex_sgpr_offset & 0xffffu) + sgpr_offset;
cmdbuf[2] = instance_vgpr_offset == 0 ? 0 : (instance_vgpr_offset & 0xffffu) + sgpr_offset;
cmdbuf[3] = 2; // auto index
WriteTrailingNop<3>(cmdbuf);
return ORBIS_OK; return ORBIS_OK;
} }
return -1;
}
int PS4_SYSV_ABI sceGnmDrawIndirectCountMulti() { int PS4_SYSV_ABI sceGnmDrawIndirectCountMulti() {
LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); LOG_ERROR(Lib_GnmDriver, "(STUBBED) called");

View File

@ -44,13 +44,16 @@ u32 PS4_SYSV_ABI sceGnmDispatchInitDefaultHardwareState(u32* cmdbuf, u32 size);
s32 PS4_SYSV_ABI sceGnmDrawIndex(u32* cmdbuf, u32 size, u32 index_count, uintptr_t index_addr, s32 PS4_SYSV_ABI sceGnmDrawIndex(u32* cmdbuf, u32 size, u32 index_count, uintptr_t index_addr,
u32 flags, u32 type); u32 flags, u32 type);
s32 PS4_SYSV_ABI sceGnmDrawIndexAuto(u32* cmdbuf, u32 size, u32 index_count, u32 flags); s32 PS4_SYSV_ABI sceGnmDrawIndexAuto(u32* cmdbuf, u32 size, u32 index_count, u32 flags);
int PS4_SYSV_ABI sceGnmDrawIndexIndirect(); s32 PS4_SYSV_ABI sceGnmDrawIndexIndirect(u32* cmdbuf, u32 size, u32 data_offset, u32 shader_stage,
u32 vertex_sgpr_offset, u32 instance_vgpr_offset,
u32 flags);
int PS4_SYSV_ABI sceGnmDrawIndexIndirectCountMulti(); int PS4_SYSV_ABI sceGnmDrawIndexIndirectCountMulti();
int PS4_SYSV_ABI sceGnmDrawIndexIndirectMulti(); int PS4_SYSV_ABI sceGnmDrawIndexIndirectMulti();
int PS4_SYSV_ABI sceGnmDrawIndexMultiInstanced(); int PS4_SYSV_ABI sceGnmDrawIndexMultiInstanced();
s32 PS4_SYSV_ABI sceGnmDrawIndexOffset(u32* cmdbuf, u32 size, u32 index_offset, u32 index_count, s32 PS4_SYSV_ABI sceGnmDrawIndexOffset(u32* cmdbuf, u32 size, u32 index_offset, u32 index_count,
u32 flags); u32 flags);
int PS4_SYSV_ABI sceGnmDrawIndirect(); s32 PS4_SYSV_ABI sceGnmDrawIndirect(u32* cmdbuf, u32 size, u32 data_offset, u32 shader_stage,
u32 vertex_sgpr_offset, u32 instance_vgpr_offset, u32 flags);
int PS4_SYSV_ABI sceGnmDrawIndirectCountMulti(); int PS4_SYSV_ABI sceGnmDrawIndirectCountMulti();
int PS4_SYSV_ABI sceGnmDrawIndirectMulti(); int PS4_SYSV_ABI sceGnmDrawIndirectMulti();
int PS4_SYSV_ABI sceGnmDrawInitDefaultHardwareState(); int PS4_SYSV_ABI sceGnmDrawInitDefaultHardwareState();

View File

@ -253,6 +253,20 @@ struct PM4CmdDrawIndexAuto {
u32 draw_initiator; u32 draw_initiator;
}; };
struct PM4CmdDrawIndirect {
PM4Type3Header header; ///< header
u32 data_offset; ///< DWORD aligned offset
union {
u32 dw2;
BitField<0, 16, u32> base_vtx_loc; ///< base vertex location
};
union {
u32 dw3;
BitField<0, 16, u32> start_inst_loc; ///< start instance location
};
u32 draw_initiator; ///< Draw Initiator Register
};
enum class DataSelect : u32 { enum class DataSelect : u32 {
None = 0, None = 0,
Data32Low = 1, Data32Low = 1,